-
Notifications
You must be signed in to change notification settings - Fork 752
/
ModifierLootingHandler.java
108 lines (100 loc) · 4.68 KB
/
ModifierLootingHandler.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package slimeknights.tconstruct.library.tools.helper;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.projectile.AbstractArrow;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.entity.living.LootingLevelEvent;
import net.minecraftforge.event.entity.player.PlayerEvent.PlayerLoggedOutEvent;
import slimeknights.tconstruct.common.TinkerTags;
import slimeknights.tconstruct.library.modifiers.TinkerHooks;
import slimeknights.tconstruct.library.modifiers.hook.LootingModifierHook;
import slimeknights.tconstruct.library.tools.capability.EntityModifierCapability;
import slimeknights.tconstruct.library.tools.capability.PersistentDataCapability;
import slimeknights.tconstruct.library.tools.nbt.DummyToolStack;
import slimeknights.tconstruct.library.tools.nbt.ModDataNBT;
import slimeknights.tconstruct.library.tools.nbt.ModifierNBT;
import slimeknights.tconstruct.library.tools.nbt.ToolStack;
import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
* Logic to handle the looting event for all main tinker tools
*/
public class ModifierLootingHandler {
/** If contained in the set, they should use the offhand for looting */
private static final Map<UUID,EquipmentSlot> LOOTING_OFFHAND = new HashMap<>();
private static boolean init = false;
/** Initializies this listener */
public static void init() {
if (init) {
return;
}
init = true;
MinecraftForge.EVENT_BUS.addListener(ModifierLootingHandler::onLooting);
MinecraftForge.EVENT_BUS.addListener(ModifierLootingHandler::onLeaveServer);
}
/**
* Sets the hand used for looting, so the tool is fetched from the proper context
* @param entity Player to set
* @param slotType Slot type
*/
public static void setLootingSlot(LivingEntity entity, EquipmentSlot slotType) {
if (slotType == EquipmentSlot.MAINHAND) {
LOOTING_OFFHAND.remove(entity.getUUID());
} else {
LOOTING_OFFHAND.put(entity.getUUID(), slotType);
}
}
/** Gets the slot to use for looting */
public static EquipmentSlot getLootingSlot(@Nullable LivingEntity entity) {
return entity != null ? LOOTING_OFFHAND.getOrDefault(entity.getUUID(), EquipmentSlot.MAINHAND) : EquipmentSlot.MAINHAND;
}
/** Applies the looting bonus for modifiers */
private static void onLooting(LootingLevelEvent event) {
// must be an attacker with our tool
DamageSource damageSource = event.getDamageSource();
if (damageSource == null) {
return;
}
Entity source = damageSource.getEntity();
if (source instanceof LivingEntity holder) {
Entity direct = damageSource.getDirectEntity();
int level = event.getLootingLevel();
LivingEntity target = event.getEntityLiving();
if (direct != source) {
if (direct instanceof AbstractArrow) {
// need to build a context from the relevant capabilities to use the modifier
ModifierNBT modifiers = direct.getCapability(EntityModifierCapability.CAPABILITY).orElse(EntityModifierCapability.EMPTY).getModifiers();
if (!modifiers.isEmpty()) {
ModDataNBT persistentData = direct.getCapability(PersistentDataCapability.CAPABILITY).map(ModDataNBT::new).orElseGet(ModDataNBT::new);
DummyToolStack tool = new DummyToolStack(Items.AIR, modifiers, persistentData);
level = LootingModifierHook.getLootingValue(TinkerHooks.PROJECTILE_LOOTING, tool, holder, target, damageSource, 0);
}
}
} else {
// not an arrow? means the held tool is to blame
EquipmentSlot slotType = getLootingSlot(holder);
ItemStack held = holder.getItemBySlot(slotType);
if (held.is(TinkerTags.Items.MODIFIABLE)) {
ToolStack tool = ToolStack.from(held);
level = ModifierUtil.getLootingLevel(tool, holder, event.getEntityLiving(), damageSource);
// ignore default looting if we are looting from another slot
} else if (slotType != EquipmentSlot.MAINHAND) {
level = 0;
}
}
// boost looting with pants regardless, hopefully you did not switch your pants mid arrow firing
level = ModifierUtil.getLeggingsLootingLevel(holder, event.getEntityLiving(), damageSource, level);
event.setLootingLevel(level);
}
}
/** Called when a player leaves the server to clear the face */
private static void onLeaveServer(PlayerLoggedOutEvent event) {
LOOTING_OFFHAND.remove(event.getPlayer().getUUID());
}
}