From 9802a1e39331574260d97d6e9b4164c36e08fc98 Mon Sep 17 00:00:00 2001 From: GStefanowich Date: Wed, 17 Mar 2021 01:09:35 -0400 Subject: [PATCH] Added an anvil hammering sound for when a piglin crafts an armor piece Added a cooldown to armor crafting checks Changed finding of nearby piglins from TARGET to NEARBY_VISIBLE Changed piglins giving out armor to allow giving to Brutes Changed piglin drops during death/zombification to not drop stored gold Added two helper utils classes --- .../NetherMod/goals/PiglinTradingGoal.java | 50 ++--- .../interfaces/EmotionalPiglins.java | 4 + .../NetherMod/mixins/PiglinEmotions.java | 199 +++++++++++------- .../TheElm/NetherMod/utils/EntityUtils.java | 104 +++++++++ .../me/TheElm/NetherMod/utils/ItemUtils.java | 78 +++++++ 5 files changed, 325 insertions(+), 110 deletions(-) create mode 100644 src/main/java/me/TheElm/NetherMod/utils/EntityUtils.java create mode 100644 src/main/java/me/TheElm/NetherMod/utils/ItemUtils.java diff --git a/src/main/java/me/TheElm/NetherMod/goals/PiglinTradingGoal.java b/src/main/java/me/TheElm/NetherMod/goals/PiglinTradingGoal.java index e8ad917..f0404a0 100644 --- a/src/main/java/me/TheElm/NetherMod/goals/PiglinTradingGoal.java +++ b/src/main/java/me/TheElm/NetherMod/goals/PiglinTradingGoal.java @@ -27,29 +27,26 @@ import com.google.common.collect.ImmutableMap; import me.TheElm.NetherMod.interfaces.EmotionalPiglins; -import net.minecraft.entity.LivingEntity; +import me.TheElm.NetherMod.utils.EntityUtils; import net.minecraft.entity.ai.brain.Brain; import net.minecraft.entity.ai.brain.MemoryModuleState; import net.minecraft.entity.ai.brain.MemoryModuleType; -import net.minecraft.entity.ai.brain.task.LookTargetUtil; import net.minecraft.entity.ai.brain.task.Task; -import net.minecraft.entity.mob.AbstractPiglinEntity; import net.minecraft.entity.mob.PiglinBrain; import net.minecraft.entity.mob.PiglinEntity; import net.minecraft.inventory.SimpleInventory; -import net.minecraft.item.ItemStack; import net.minecraft.server.world.ServerWorld; import org.jetbrains.annotations.NotNull; -import java.util.List; -import java.util.Optional; - /** * Created on Mar 11 2021 at 12:14 AM. * By greg in PiglinMod */ public final class PiglinTradingGoal extends Task { + private static final int TICKS = 60; + private int cooldown = TICKS; + public PiglinTradingGoal() { this(60); } @@ -59,46 +56,29 @@ public PiglinTradingGoal( int runTime ) { } public PiglinTradingGoal( int minRunTime, int maxRunTime ) { - super(ImmutableMap.of(MemoryModuleType.NEARBY_ADULT_PIGLINS, MemoryModuleState.VALUE_PRESENT, MemoryModuleType.INTERACTION_TARGET, MemoryModuleState.VALUE_PRESENT), minRunTime, maxRunTime); + super(ImmutableMap.of(MemoryModuleType.NEAREST_VISIBLE_ADULT_PIGLINS, MemoryModuleState.VALUE_PRESENT), minRunTime, maxRunTime); } @Override protected boolean shouldRun( ServerWorld world, PiglinEntity piglin ) { + if ( this.cooldown-- > 0 ) + return false; + this.cooldown = PiglinTradingGoal.TICKS; if ( !((EmotionalPiglins)piglin).hasFullArmorSet() ) return false; SimpleInventory inventory = ((EmotionalPiglins)piglin).getInventory(); if ( inventory.count(PiglinBrain.BARTERING_ITEM) <= 0 ) return false; - LivingEntity entity; - Brain brain = piglin.getBrain(); - Optional optional = brain.getOptionalMemory(MemoryModuleType.INTERACTION_TARGET); - return optional.isPresent() && ((entity = optional.get()) instanceof PiglinEntity) && !((EmotionalPiglins)entity).hasFullArmorSet(); + return piglin.getBrain() + .getOptionalMemory(MemoryModuleType.NEAREST_VISIBLE_ADULT_PIGLINS) + .map(list -> list.stream().anyMatch(EntityUtils::missingArmorSet)) + .orElse(Boolean.FALSE); } @Override - protected void run( ServerWorld world, PiglinEntity piglin, long time ) { + protected void run(ServerWorld world, @NotNull PiglinEntity piglin, long time) { Brain brain = piglin.getBrain(); - brain.getOptionalMemory(MemoryModuleType.INTERACTION_TARGET).ifPresent((target) -> { - SimpleInventory inventory = ((EmotionalPiglins)piglin).getInventory(); - if (!( target instanceof PiglinEntity )) - return; - boolean doCheck = false; - - for ( int i = 0; i < inventory.size(); i++ ) { - ItemStack stack = inventory.getStack(i); - if (stack.isEmpty() || !PiglinBrain.BARTERING_ITEM.equals(stack.getItem()) ) - continue; - - // Directly give the piglin gold telepathically - ItemStack remainder = ((EmotionalPiglins)target) - .incrementGold(stack); - inventory.setStack(i, remainder); - - doCheck = true; - } - - if ( doCheck ) - ((EmotionalPiglins) target).craftingCheck(); - }); + brain.getOptionalMemory(MemoryModuleType.NEAREST_VISIBLE_ADULT_PIGLINS) + .ifPresent((target) -> EntityUtils.transferDesiredItems(target, piglin)); } } diff --git a/src/main/java/me/TheElm/NetherMod/interfaces/EmotionalPiglins.java b/src/main/java/me/TheElm/NetherMod/interfaces/EmotionalPiglins.java index 200932d..2d808cd 100644 --- a/src/main/java/me/TheElm/NetherMod/interfaces/EmotionalPiglins.java +++ b/src/main/java/me/TheElm/NetherMod/interfaces/EmotionalPiglins.java @@ -26,6 +26,7 @@ package me.TheElm.NetherMod.interfaces; import net.minecraft.inventory.SimpleInventory; +import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.particle.ParticleEffect; import org.jetbrains.annotations.NotNull; @@ -66,4 +67,7 @@ default void incrementGold(Iterable stacks) { boolean hasFullArmorSet(); void craftingCheck(); + boolean canCraftItem(@NotNull Item item); + @NotNull ItemStack tryCraftItem(@NotNull Item item); + } diff --git a/src/main/java/me/TheElm/NetherMod/mixins/PiglinEmotions.java b/src/main/java/me/TheElm/NetherMod/mixins/PiglinEmotions.java index dcdc3f8..1509687 100644 --- a/src/main/java/me/TheElm/NetherMod/mixins/PiglinEmotions.java +++ b/src/main/java/me/TheElm/NetherMod/mixins/PiglinEmotions.java @@ -26,16 +26,19 @@ package me.TheElm.NetherMod.mixins; import me.TheElm.NetherMod.interfaces.EmotionalPiglins; +import me.TheElm.NetherMod.utils.EntityUtils; +import me.TheElm.NetherMod.utils.ItemUtils; import net.minecraft.enchantment.Enchantment; import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.enchantment.Enchantments; import net.minecraft.entity.CrossbowUser; import net.minecraft.entity.EntityType; import net.minecraft.entity.EquipmentSlot; -import net.minecraft.entity.damage.DamageSource; import net.minecraft.entity.mob.HostileEntity; +import net.minecraft.entity.mob.PiglinBrain; import net.minecraft.entity.mob.PiglinEntity; import net.minecraft.inventory.SimpleInventory; +import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.nbt.CompoundTag; @@ -44,14 +47,13 @@ import net.minecraft.recipe.Ingredient; import net.minecraft.server.world.ServerWorld; import net.minecraft.sound.SoundCategory; -import net.minecraft.sound.SoundEvent; import net.minecraft.sound.SoundEvents; import net.minecraft.util.Identifier; +import net.minecraft.util.registry.Registry; import net.minecraft.world.LocalDifficulty; import net.minecraft.world.World; import org.jetbrains.annotations.NotNull; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -60,9 +62,12 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Objects; +import java.util.Optional; +import java.util.stream.Stream; @Mixin(PiglinEntity.class) public abstract class PiglinEmotions extends HostileEntity implements CrossbowUser, EmotionalPiglins { @@ -76,28 +81,6 @@ protected PiglinEmotions(EntityType entityType, World w super(entityType, world); } - @Redirect(at = @At(value = "INVOKE", target = "net/minecraft/inventory/SimpleInventory.addStack(Lnet/minecraft/item/ItemStack;)Lnet/minecraft/item/ItemStack;"), method = "addItem") - protected ItemStack onAddToInventory(SimpleInventory inventory, ItemStack stack) { - if ((!stack.isEmpty())) { - if (stack.getItem() == Items.GOLD_BLOCK) { - int blocks = stack.getCount(); - return this.addGoldToInventory(new ItemStack(Items.GOLD_INGOT, blocks * 9), false); - } else if (stack.getItem() == Items.GOLD_INGOT) - return this.addGoldToInventory(stack, true); - } - - return inventory.addStack( stack ); - } - - private ItemStack addGoldToInventory(@NotNull ItemStack stack, boolean traded) { - if (traded) { - EnchantmentHelper.set(new HashMap() {{ - put(Enchantments.VANISHING_CURSE, 1); - }}, stack); - } - return this.inventory.addStack(stack); - } - @Inject(at = @At("RETURN"), method = "addItem") protected void onAddItem(ItemStack stack, CallbackInfoReturnable callback) { this.craftingCheck(); @@ -105,10 +88,7 @@ protected void onAddItem(ItemStack stack, CallbackInfoReturnable call @Inject(at = @At("TAIL"), method = "readCustomDataFromTag") public void onReadFromTag(@NotNull CompoundTag tag, @NotNull CallbackInfo callback) { - for ( EquipmentSlot slot : EquipmentSlot.values() ) - if ( slot.getType() == EquipmentSlot.Type.ARMOR && this.getEquippedStack(slot).isEmpty() ) - return; - this.shareGold = true; + this.shareGold = EntityUtils.hasFullArmorSet(this); } @Override @@ -141,22 +121,58 @@ public void produceParticles(@NotNull ParticleEffect particle) { @Override public ItemStack incrementGold(@NotNull ItemStack stack) { - ItemStack remainder = this.addGoldToInventory(stack.copy(), true); + ItemStack remainder = PiglinEmotions.addTradedItemToInventory(this.inventory, stack.copy(), true); this.craftingCheck(); return remainder; } + @Redirect(at = @At(value = "INVOKE", target = "net/minecraft/inventory/SimpleInventory.addStack(Lnet/minecraft/item/ItemStack;)Lnet/minecraft/item/ItemStack;"), method = "addItem") + protected ItemStack onAddToInventory(@NotNull SimpleInventory inventory, @NotNull ItemStack stack) { + // If the stack picked up is NOT EMPTY + if (!stack.isEmpty()) { + // If the item is the BARTER ITEM, add it to the inventory for later + if (stack.getItem() == PiglinBrain.BARTERING_ITEM) + return PiglinEmotions.addTradedItemToInventory(inventory, stack, true); + + // If the item can be MADE into the BARTER ITEM, Attempt crafting it + Optional recipes = PiglinEmotions.getMakesTradingItem(this.world, stack); + if ( recipes.isPresent() ) { + CraftingRecipe recipe = recipes.get(); + + // Get the output of the crafting + ItemStack makes = recipe.getOutput(); + PiglinEmotions.addVanishingCurse(makes); + + // Try to add the crafted items into the inventory + while ( !stack.isEmpty() && inventory.canInsert(makes) ) { + // Decrement the item used to make the recipe + stack.decrement(1); + ItemStack remainder = inventory.addStack(makes); + + // Drop any leftover crafted items + if ( !remainder.isEmpty() ) // Drop the items WITHOUT the VANISHING curse + this.dropStack(new ItemStack(remainder.getItem(), remainder.getCount())); + } + } + } + + // Fallback to adding the item to the inventory + return inventory.addStack(stack); + } + /** * Overwrite of the Vanilla DropEquipment to remove cursed items from the inventory * @reason Items in a Piglins inventory that have Curse of Vanishing are not destroyed * @author TheElm */ - @Overwrite - public void dropEquipment(DamageSource source, int lootingMultiplier, boolean allowDrops) { - super.dropEquipment(source, lootingMultiplier, allowDrops); - this.inventory.clearToList().stream() - .filter(stack -> !EnchantmentHelper.hasVanishingCurse(stack)) // Filter out cursed items - .forEach(this::dropStack); // Drop all inventory items + @Redirect(at = @At(value = "INVOKE", target = "net/minecraft/inventory/SimpleInventory.clearToList()Ljava/util/List;"), method = "dropEquipment") + public List onDropEquipment(@NotNull SimpleInventory inventory) { + return ItemUtils.getDroppableItems(inventory.clearToList()); + } + + @Redirect(at = @At(value = "INVOKE", target = "net/minecraft/inventory/SimpleInventory.clearToList()Ljava/util/List;"), method = "zombify") + public List onZombify(@NotNull SimpleInventory inventory) { + return ItemUtils.getDroppableItems(inventory.clearToList()); } public void craftingCheck() { @@ -171,11 +187,12 @@ public void craftingCheck() { // Skip to the next armor slot if (!armorStack.isEmpty()) { // If the slot is occupied by armor - if (slot.getType() == EquipmentSlot.Type.ARMOR) armors++; + if (slot.getType() == EquipmentSlot.Type.ARMOR) + armors++; continue; } - ItemStack createStack = this.craftArmorFromInventory(slot); + ItemStack createStack = this.tryCraftItem(slot); if (!createStack.isEmpty()) { this.world.playSoundFromEntity(null, this, SoundEvents.ITEM_ARMOR_EQUIP_GOLD, SoundCategory.AMBIENT, 1.0F, 1.0F); this.equipStack(slot, createStack); @@ -186,11 +203,26 @@ public void craftingCheck() { this.shareGold = (armors >= 4); } } - private ItemStack craftArmorFromInventory(EquipmentSlot slot) { + + @Override + public boolean canCraftItem(@NotNull Item item) { + return !this.tryCraftItem(PiglinEmotions.getItemRecipeId(item), false) + .isEmpty(); + } + + @Override + public @NotNull ItemStack tryCraftItem(@NotNull Item item) { + return this.tryCraftItem(PiglinEmotions.getItemRecipeId(item), true); + } + private @NotNull ItemStack tryCraftItem(@NotNull EquipmentSlot slot) { + return this.tryCraftItem(PiglinEmotions.getGoldArmorRecipeId(slot), true); + } + private @NotNull ItemStack tryCraftItem(@NotNull Optional identifier, final boolean doCraft) { // Find the recipe for the equipment slot - CraftingRecipe recipe = PiglinEmotions.getArmorRecipe(this.world, PiglinEmotions.getGoldArmorRecipeId(slot)); - if (recipe == null) // Check that a recipe was found + Optional recipes = PiglinEmotions.getArmorRecipe(this.world, identifier); + if (!recipes.isPresent()) // Check that a recipe was found return ItemStack.EMPTY; + CraftingRecipe recipe = recipes.get(); // Check for all of the ingredients boolean hasAllIngredients = true; @@ -216,57 +248,74 @@ private ItemStack craftArmorFromInventory(EquipmentSlot slot) { if (!hasIngredient) { if ( ingredient.test(PiglinEmotions.STICK_ITEM) ) continue; - + hasAllIngredients = false; break; } } // If all of the ingredients are present - if (!hasAllIngredients) + if (!hasAllIngredients || !doCraft) craftingTable.forEach(this.inventory::addStack); - else { - // "Craft" the item - LocalDifficulty difficulty = this.world.getLocalDifficulty(this.getBlockPos()); - float f = difficulty.getClampedLocalDifficulty(); - + if ( hasAllIngredients ) { // Clone the recipe output (Or you modify the recipe!) ItemStack output = recipe.getOutput() .copy(); - // Attempt to enchant the item - if (this.random.nextFloat() < 0.5F * f) - return EnchantmentHelper.enchant(random, output, (int) (5.0F + f * (float) this.random.nextInt(18)), false); + if ( doCraft ) { + // Get enchantment possibilities based off of difficulty + LocalDifficulty difficulty = this.world.getLocalDifficulty(this.getBlockPos()); + float f = difficulty.getClampedLocalDifficulty(); + + // Attempt to enchant the item + if (this.random.nextFloat() < 0.5F * f) + return EnchantmentHelper.enchant(random, output, (int) (5.0F + f * (float) this.random.nextInt(18)), false); + if ( !this.world.isClient ) + this.world.playSoundFromEntity(null, this, SoundEvents.BLOCK_ANVIL_USE, SoundCategory.AMBIENT, 1.0F, 1.0F); + } + return output; } return ItemStack.EMPTY; } - private static CraftingRecipe getArmorRecipe(World world, Identifier identifier) { - if (identifier == null) return null; - return world.getRecipeManager().values().stream().map(recipe -> { - if (recipe instanceof CraftingRecipe) - return (CraftingRecipe) recipe; - return null; - }).filter(Objects::nonNull).filter(recipe -> recipe.getId().equals(identifier)).findFirst().orElse(null); + private static @NotNull ItemStack addTradedItemToInventory( @NotNull SimpleInventory inventory, @NotNull ItemStack stack, boolean traded) { + if (traded && !EnchantmentHelper.hasVanishingCurse(stack)) + PiglinEmotions.addVanishingCurse(stack); + return inventory.addStack(stack); } - private static Identifier getGoldArmorRecipeId(EquipmentSlot slot) { - switch (slot) { - case FEET: - return new Identifier("golden_boots"); - case LEGS: - return new Identifier("golden_leggings"); - case CHEST: - return new Identifier("golden_chestplate"); - case HEAD: - return new Identifier("golden_helmet"); - case MAINHAND: - return new Identifier("golden_sword"); - case OFFHAND: - return new Identifier("crossbow"); - default: - return null; - } + private static @NotNull Optional getArmorRecipe(@NotNull World world, @NotNull Optional identifier) { + return identifier.flatMap((value) -> PiglinEmotions.getWorldCraftingRecipes(world) + .filter(recipe -> recipe.getId().equals(value)) + .findFirst()); + } + private static @NotNull Optional getMakesTradingItem( @NotNull World world, @NotNull ItemStack stack) { + return PiglinEmotions.getWorldCraftingRecipes(world) + .filter((recipe) -> { + Collection ingredients = recipe.getPreviewInputs(); + return ingredients.size() == 1 && recipe.getOutput().getItem() == PiglinBrain.BARTERING_ITEM && ingredients.stream() + .anyMatch(ingredient -> ingredient.test(stack)); + }) + .findFirst(); + } + private static @NotNull Optional getGoldArmorRecipeId(@NotNull EquipmentSlot slot) { + return ItemUtils.getOptionalPiglinEquipmentSlotItem(slot) + .flatMap(PiglinEmotions::getItemRecipeId); + } + private static @NotNull Optional getItemRecipeId(@NotNull Item slot) { + return Optional.of(Registry.ITEM.getId(slot)); + } + private static @NotNull Stream getWorldCraftingRecipes(@NotNull World world) { + return world.getRecipeManager() + .values() + .stream() + .map((recipe) -> recipe instanceof CraftingRecipe ? (CraftingRecipe) recipe : null) + .filter(Objects::nonNull); + } + private static void addVanishingCurse(@NotNull ItemStack stack) { + EnchantmentHelper.set(new HashMap() {{ + put(Enchantments.VANISHING_CURSE, 1); + }}, stack); } } diff --git a/src/main/java/me/TheElm/NetherMod/utils/EntityUtils.java b/src/main/java/me/TheElm/NetherMod/utils/EntityUtils.java new file mode 100644 index 0000000..9dcfcdf --- /dev/null +++ b/src/main/java/me/TheElm/NetherMod/utils/EntityUtils.java @@ -0,0 +1,104 @@ +/* + * This software is licensed under the MIT License + * https://github.com/GStefanowich/MC-Nether-Mod + * + * Copyright (c) 2019 Gregory Stefanowich + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.TheElm.NetherMod.utils; + +import me.TheElm.NetherMod.interfaces.EmotionalPiglins; +import net.minecraft.entity.EquipmentSlot; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.mob.AbstractPiglinEntity; +import net.minecraft.entity.mob.MobEntity; +import net.minecraft.entity.mob.PiglinEntity; +import net.minecraft.inventory.SimpleInventory; +import net.minecraft.item.ArmorItem; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; + +/** + * Created on Mar 16 2021 at 7:58 PM. + * By greg in PiglinMod + */ +public final class EntityUtils { + + public static boolean hasFullArmorSet(@NotNull LivingEntity entity) { + return EntityUtils.getNeededArmorSlot(entity) == null; + } + public static boolean missingArmorSet(@NotNull LivingEntity entity) { + return !EntityUtils.hasFullArmorSet(entity); + } + public static @Nullable EquipmentSlot getNeededArmorSlot(@NotNull LivingEntity entity) { + for ( EquipmentSlot slot : EquipmentSlot.values() ) + if ( slot.getType() == EquipmentSlot.Type.ARMOR && entity.getEquippedStack(slot).isEmpty() ) + return slot; + return null; + } + public static void transferDesiredItems(@NotNull Collection piglins, @NotNull PiglinEntity main) { + SimpleInventory inventory = ((EmotionalPiglins)main).getInventory(); + for ( AbstractPiglinEntity piglin : piglins ) { + while ( true ) { + ItemStack transfer = null; + Item wanted = ItemUtils.getPiglinGiftItem(piglin); + if ( wanted != null ) { + if ( inventory.count(wanted) > 0 ) + transfer = inventory.removeItem(wanted, wanted.getMaxCount()); + else if (((EmotionalPiglins)main).canCraftItem(wanted)) + transfer = ((EmotionalPiglins)main).tryCraftItem(wanted); + } + + if ( transfer == null ) + break; + + // Try to transfer the item to the other entity + ItemStack remainder = EntityUtils.transferDesiredItem(piglin, transfer); + if ( !remainder.isEmpty() ) // Try to take the item bback + remainder = inventory.addStack(remainder); + if ( !remainder.isEmpty() ) // Drop the item if all else fails + main.dropStack(remainder); + } + } + } + public static ItemStack transferDesiredItem(@NotNull AbstractPiglinEntity piglin, @NotNull ItemStack stack) { + Item item = stack.getItem(); + if ( item instanceof ArmorItem && EntityUtils.equipCraftedStack(piglin, stack) ) + return ItemStack.EMPTY; + if (piglin instanceof PiglinEntity) + return ((EmotionalPiglins) piglin).incrementGold(stack); + return ItemStack.EMPTY; + } + + public static boolean equipCraftedStack(@NotNull MobEntity mob, @NotNull ItemStack equipment) { + EquipmentSlot equipmentSlot = mob.getPreferredEquipmentSlot(equipment); + ItemStack itemStack = mob.getEquippedStack(equipmentSlot); + if (!itemStack.isEmpty() || !mob.canPickupItem(equipment)) + return false; + mob.equipStack(equipmentSlot, equipment); + return true; + } + +} diff --git a/src/main/java/me/TheElm/NetherMod/utils/ItemUtils.java b/src/main/java/me/TheElm/NetherMod/utils/ItemUtils.java new file mode 100644 index 0000000..9531b05 --- /dev/null +++ b/src/main/java/me/TheElm/NetherMod/utils/ItemUtils.java @@ -0,0 +1,78 @@ +/* + * This software is licensed under the MIT License + * https://github.com/GStefanowich/MC-Nether-Mod + * + * Copyright (c) 2019 Gregory Stefanowich + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.TheElm.NetherMod.utils; + +import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.entity.EquipmentSlot; +import net.minecraft.entity.mob.AbstractPiglinEntity; +import net.minecraft.entity.mob.PiglinEntity; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +/** + * Created on Mar 16 2021 at 8:01 PM. + * By greg in PiglinMod + */ +public final class ItemUtils { + private ItemUtils() {} + + public static @NotNull List getDroppableItems(@NotNull Collection inventory) { + return inventory.stream() + .filter(stack -> !EnchantmentHelper.hasVanishingCurse(stack)) + .collect(Collectors.toList()); + } + public static @Nullable Item getPiglinGiftItem(@NotNull AbstractPiglinEntity piglin) { + if (piglin instanceof PiglinEntity) + return EntityUtils.hasFullArmorSet(piglin) ? null : Items.GOLD_INGOT; + EquipmentSlot slot = EntityUtils.getNeededArmorSlot(piglin); + if ( slot == null ) + return null; + return ItemUtils.getPiglinEquipmentSlotItem(slot); + } + public static @NotNull Optional getOptionalPiglinEquipmentSlotItem(@NotNull EquipmentSlot slot) { + return Optional.ofNullable(ItemUtils.getPiglinEquipmentSlotItem(slot)); + } + public static @Nullable Item getPiglinEquipmentSlotItem(@NotNull EquipmentSlot slot) { + switch (slot) { + case HEAD: return Items.GOLDEN_HELMET; + case CHEST: return Items.GOLDEN_CHESTPLATE; + case LEGS: return Items.GOLDEN_LEGGINGS; + case FEET: return Items.GOLDEN_BOOTS; + case MAINHAND: return Items.GOLDEN_SWORD; + case OFFHAND: return Items.CROSSBOW; + } + return null; + } + +}