From e600bc78356dac16f8870aedb3a3c7ac81c9855d Mon Sep 17 00:00:00 2001 From: KnightMiner Date: Sat, 18 Jan 2025 23:57:59 -0500 Subject: [PATCH] Fix severing not running using the right hand (#5283) Caused by unneeded conditions in the loot modifier JSON, all we had to do was do the tag check inside the logic Also fix severing and alike on projectiles running using the held tool instead of the projectile --- .../loot_modifiers/modifier_hook.json | 22 ------------ .../loot/GlobalLootModifiersProvider.java | 14 +------- .../tools/modifiers/ModifierLootModifier.java | 36 ++++++++++++++++--- 3 files changed, 32 insertions(+), 40 deletions(-) diff --git a/src/generated/resources/data/tconstruct/loot_modifiers/modifier_hook.json b/src/generated/resources/data/tconstruct/loot_modifiers/modifier_hook.json index 4c6bc2cf5b..4bdb06597c 100644 --- a/src/generated/resources/data/tconstruct/loot_modifiers/modifier_hook.json +++ b/src/generated/resources/data/tconstruct/loot_modifiers/modifier_hook.json @@ -3,28 +3,6 @@ "conditions": [ { "condition": "tconstruct:block_or_entity" - }, - { - "condition": "minecraft:any_of", - "terms": [ - { - "condition": "minecraft:match_tool", - "predicate": { - "tag": "tconstruct:modifiable/loot_capable_tool" - } - }, - { - "condition": "minecraft:entity_properties", - "entity": "killer", - "predicate": { - "equipment": { - "mainhand": { - "tag": "tconstruct:modifiable/loot_capable_tool" - } - } - } - } - ] } ] } \ No newline at end of file diff --git a/src/main/java/slimeknights/tconstruct/common/data/loot/GlobalLootModifiersProvider.java b/src/main/java/slimeknights/tconstruct/common/data/loot/GlobalLootModifiersProvider.java index 2b70e7e2b4..69cbeaf11d 100644 --- a/src/main/java/slimeknights/tconstruct/common/data/loot/GlobalLootModifiersProvider.java +++ b/src/main/java/slimeknights/tconstruct/common/data/loot/GlobalLootModifiersProvider.java @@ -1,8 +1,5 @@ package slimeknights.tconstruct.common.data.loot; -import net.minecraft.advancements.critereon.EntityEquipmentPredicate; -import net.minecraft.advancements.critereon.EntityPredicate; -import net.minecraft.advancements.critereon.ItemPredicate; import net.minecraft.core.registries.Registries; import net.minecraft.data.PackOutput; import net.minecraft.resources.ResourceLocation; @@ -10,12 +7,9 @@ import net.minecraft.world.item.Item; import net.minecraft.world.item.Items; import net.minecraft.world.item.crafting.Ingredient; -import net.minecraft.world.level.storage.loot.LootContext.EntityTarget; import net.minecraft.world.level.storage.loot.entries.LootItem; import net.minecraft.world.level.storage.loot.functions.ApplyExplosionDecay; import net.minecraft.world.level.storage.loot.functions.SetItemCountFunction; -import net.minecraft.world.level.storage.loot.predicates.LootItemEntityPropertyCondition; -import net.minecraft.world.level.storage.loot.predicates.MatchTool; import net.minecraft.world.level.storage.loot.providers.number.UniformGenerator; import net.minecraftforge.common.data.GlobalLootModifierProvider; import net.minecraftforge.common.loot.LootTableIdCondition; @@ -55,13 +49,7 @@ protected void start() { // generic modifier hook // TODO: look into migrating this fully to loot tables - ItemPredicate.Builder lootCapableTool = ItemPredicate.Builder.item().of(TinkerTags.Items.LOOT_CAPABLE_TOOL); - add("modifier_hook", ModifierLootModifier.builder() - .addCondition(BlockOrEntityCondition.INSTANCE) - .addCondition(MatchTool.toolMatches(lootCapableTool) - .or(LootItemEntityPropertyCondition.hasProperties(EntityTarget.KILLER, EntityPredicate.Builder.entity().equipment(EntityEquipmentPredicate.Builder.equipment().mainhand(lootCapableTool.build()).build()))) - .build()) - .build()); + add("modifier_hook", ModifierLootModifier.builder().addCondition(BlockOrEntityCondition.INSTANCE).build()); // chrysophilite modifier hook add("chrysophilite_modifier", AddEntryLootModifier.builder(LootItem.lootTableItem(Items.GOLD_NUGGET)) diff --git a/src/main/java/slimeknights/tconstruct/tools/modifiers/ModifierLootModifier.java b/src/main/java/slimeknights/tconstruct/tools/modifiers/ModifierLootModifier.java index 61eb0360fa..a1cf699bd1 100644 --- a/src/main/java/slimeknights/tconstruct/tools/modifiers/ModifierLootModifier.java +++ b/src/main/java/slimeknights/tconstruct/tools/modifiers/ModifierLootModifier.java @@ -3,18 +3,26 @@ import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.projectile.Projectile; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; import net.minecraft.world.level.storage.loot.LootContext; import net.minecraft.world.level.storage.loot.parameters.LootContextParams; import net.minecraft.world.level.storage.loot.predicates.LootItemCondition; import net.minecraftforge.common.loot.IGlobalLootModifier; import net.minecraftforge.common.loot.LootModifier; import slimeknights.mantle.loot.AbstractLootModifierBuilder.GenericLootModifierBuilder; +import slimeknights.tconstruct.common.TinkerTags; import slimeknights.tconstruct.library.modifiers.ModifierEntry; import slimeknights.tconstruct.library.modifiers.ModifierHooks; +import slimeknights.tconstruct.library.tools.capability.EntityModifierCapability; +import slimeknights.tconstruct.library.tools.capability.PersistentDataCapability; import slimeknights.tconstruct.library.tools.helper.ModifierLootingHandler; +import slimeknights.tconstruct.library.tools.nbt.DummyToolStack; +import slimeknights.tconstruct.library.tools.nbt.IToolStackView; +import slimeknights.tconstruct.library.tools.nbt.ModDataNBT; +import slimeknights.tconstruct.library.tools.nbt.ModifierNBT; import slimeknights.tconstruct.library.tools.nbt.ToolStack; import javax.annotation.Nonnull; @@ -37,15 +45,33 @@ public static GenericLootModifierBuilder builder() { protected ObjectArrayList doApply(ObjectArrayList generatedLoot, LootContext context) { // tool is for harvest ItemStack stack = context.getParamOrNull(LootContextParams.TOOL); - // if null, try entity held item + + // if null, try killer entity if (stack == null) { - Entity entity = context.getParamOrNull(LootContextParams.KILLER_ENTITY); - if (entity instanceof LivingEntity living) { + // if this loot is due to a projectile fired by one of our tools, then use that projectile as the loot source + // prevents weirdness when held tool switches after firing a projectile + if (context.getParamOrNull(LootContextParams.DIRECT_KILLER_ENTITY) instanceof Projectile projectile) { + ModifierNBT modifiers = EntityModifierCapability.getOrEmpty(projectile); + + // no need to build the dummy tool if we lack modifiers + if (!modifiers.isEmpty()) { + ModDataNBT persistentData = projectile.getCapability(PersistentDataCapability.CAPABILITY).orElseGet(ModDataNBT::new); + IToolStackView dummyTool = new DummyToolStack(Items.AIR, modifiers, persistentData); + for (ModifierEntry entry : modifiers) { + entry.getHook(ModifierHooks.PROCESS_LOOT).processLoot(dummyTool, entry, generatedLoot, context); + } + } + // don't run held item hook for projectiles, if you didn't put the modifier on the projectile we shouldn't count it + return generatedLoot; + } + + // not a projectile causing it, fetch the killer entity directly from loot context + if (context.getParamOrNull(LootContextParams.KILLER_ENTITY) instanceof LivingEntity living) { stack = living.getItemBySlot(ModifierLootingHandler.getLootingSlot(living)); } } // hopefully one of the two worked - if (stack != null) { + if (stack != null && stack.is(TinkerTags.Items.LOOT_CAPABLE_TOOL)) { ToolStack tool = ToolStack.from(stack); if (!tool.isBroken()) { for (ModifierEntry entry : tool.getModifierList()) {