From a8ce723d1c481d80d06b7f3e700a024c709c0fd3 Mon Sep 17 00:00:00 2001 From: Vonr Date: Tue, 24 Dec 2024 16:21:19 +0800 Subject: [PATCH 1/2] feat: make EffectBreak find a proper tool from the inventory it will find the first tool able to break the BlockState and cache it per BlockState if there are more blocks to break. --- .../common/spell/effect/EffectBreak.java | 79 ++++++++++++++----- 1 file changed, 59 insertions(+), 20 deletions(-) diff --git a/src/main/java/com/hollingsworth/arsnouveau/common/spell/effect/EffectBreak.java b/src/main/java/com/hollingsworth/arsnouveau/common/spell/effect/EffectBreak.java index ee740edee..da455cd2e 100644 --- a/src/main/java/com/hollingsworth/arsnouveau/common/spell/effect/EffectBreak.java +++ b/src/main/java/com/hollingsworth/arsnouveau/common/spell/effect/EffectBreak.java @@ -1,5 +1,8 @@ package com.hollingsworth.arsnouveau.common.spell.effect; +import com.hollingsworth.arsnouveau.api.item.inv.InteractType; +import com.hollingsworth.arsnouveau.api.item.inv.InventoryManager; +import com.hollingsworth.arsnouveau.api.item.inv.SlotReference; import com.hollingsworth.arsnouveau.api.spell.*; import com.hollingsworth.arsnouveau.api.util.BlockUtil; import com.hollingsworth.arsnouveau.api.util.SpellUtil; @@ -8,14 +11,19 @@ import com.hollingsworth.arsnouveau.common.lib.GlyphLib; import com.hollingsworth.arsnouveau.common.spell.augment.*; import com.hollingsworth.arsnouveau.common.util.HolderHelper; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import net.minecraft.core.BlockPos; +import net.minecraft.core.Holder; +import net.minecraft.core.component.DataComponents; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; +import net.minecraft.tags.BlockTags; import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.effect.MobEffects; import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; +import net.minecraft.world.item.*; +import net.minecraft.world.item.component.Unbreakable; +import net.minecraft.world.item.enchantment.Enchantment; import net.minecraft.world.item.enchantment.Enchantments; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; @@ -23,9 +31,8 @@ import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.NotNull; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; +import java.util.function.Function; public class EffectBreak extends AbstractEffect { public static EffectBreak INSTANCE = new EffectBreak(); @@ -39,13 +46,18 @@ public int getDefaultManaCost() { return 10; } - public ItemStack getStack(LivingEntity shooter, BlockHitResult blockHitResult) { + public ItemStack getStack(LivingEntity shooter, InventoryManager inventory, BlockHitResult blockHitResult) { ItemStack stack = shooter.getMainHandItem().copy(); - boolean usePick = shooter.level.getBlockState(blockHitResult.getBlockPos()).is(BlockTagProvider.BREAK_WITH_PICKAXE); - if (usePick) { - return new ItemStack(Items.DIAMOND_PICKAXE); + BlockState state = shooter.level.getBlockState(blockHitResult.getBlockPos()); + + if (!stack.isCorrectToolForDrops(state)) { + SlotReference tool = inventory.findItem(s -> !s.isEmpty() && s.isCorrectToolForDrops(state), InteractType.EXTRACT); + if (!tool.isEmpty() && tool.getHandler() != null) { + return tool.getHandler().getStackInSlot(tool.getSlot()).copy(); + } } - return stack.isEmpty() ? new ItemStack(Items.DIAMOND_PICKAXE) : stack; + + return new ItemStack(Items.DIAMOND_PICKAXE); } @Override @@ -60,27 +72,54 @@ public void onResolveBlock(BlockHitResult rayTraceResult, Level world, @NotNull double aoeBuff = spellStats.getAoeMultiplier(); int pierceBuff = spellStats.getBuffCount(AugmentPierce.INSTANCE); List posList = SpellUtil.calcAOEBlocks(shooter, pos, rayTraceResult, aoeBuff, pierceBuff); - ItemStack stack = spellStats.isSensitive() ? new ItemStack(Items.SHEARS) : getStack(shooter, rayTraceResult); int numFortune = spellStats.getBuffCount(AugmentFortune.INSTANCE); int numSilkTouch = spellStats.getBuffCount(AugmentExtract.INSTANCE); - if (numFortune > 0 && stack.getEnchantmentLevel(HolderHelper.unwrap(world,Enchantments.FORTUNE)) < numFortune) { - stack.enchant(HolderHelper.unwrap(world,Enchantments.FORTUNE), numFortune); - } - if (numSilkTouch > 0 && stack.getEnchantmentLevel(HolderHelper.unwrap(world,Enchantments.SILK_TOUCH)) < numSilkTouch) { - stack.enchant(HolderHelper.unwrap(world,Enchantments.SILK_TOUCH), numSilkTouch); - } - for (BlockPos pos1 : posList) { + Holder fortune = HolderHelper.unwrap(world, Enchantments.FORTUNE); + Holder silkTouch = HolderHelper.unwrap(world, Enchantments.FORTUNE); + + Map toolCache = posList.size() > 1 ? new Object2ObjectOpenHashMap<>(8) : null; + InventoryManager manager = spellContext.getCaster().getInvManager(); + + Function compute = s -> { + ItemStack stack = getStack(shooter, manager, rayTraceResult); + stack.set(DataComponents.UNBREAKABLE, new Unbreakable(true)); + + if (numFortune > 0 && stack.getEnchantmentLevel(fortune) < numFortune) { + stack.enchant(fortune, numFortune); + } + if (numSilkTouch > 0 && stack.getEnchantmentLevel(silkTouch) < numSilkTouch) { + stack.enchant(silkTouch, numSilkTouch); + } + + return stack; + }; + + for (int i = 0; i < posList.size(); i++) { + BlockPos pos1 = posList.get(i); + if (world.isOutsideBuildHeight(pos1) || world.random.nextFloat() < spellStats.getBuffCount(AugmentRandomize.INSTANCE) * 0.25F) { continue; } state = world.getBlockState(pos1); + if (state.is(BlockTags.AIR)) { + continue; + } + + ItemStack tool; + if (spellStats.isSensitive()) { + tool = new ItemStack(Items.SHEARS); + } else if (toolCache != null && i < posList.size() - 1) { + tool = toolCache.computeIfAbsent(state, compute); + } else { + tool = compute.apply(state); + } - if (!canBlockBeHarvested(spellStats, world, pos1) || !BlockUtil.destroyRespectsClaim(getPlayer(shooter, (ServerLevel) world), world, pos1) || state.is(BlockTagProvider.BREAK_BLACKLIST)) { + if (world.getBlockState(pos).getDestroySpeed(world, pos) < 0 || !tool.isCorrectToolForDrops(state) || !BlockUtil.destroyRespectsClaim(getPlayer(shooter, (ServerLevel) world), world, pos1) || state.is(BlockTagProvider.BREAK_BLACKLIST)) { continue; } - if (!BlockUtil.breakExtraBlock((ServerLevel) world, pos1, stack, shooter.getUUID(), true)) { + if (!BlockUtil.breakExtraBlock((ServerLevel) world, pos1, tool, shooter.getUUID(), true)) { continue; } From 0eb6040dcda6eef47ca8f156651ea2cf7b305dae Mon Sep 17 00:00:00 2001 From: Vonr Date: Tue, 24 Dec 2024 16:35:40 +0800 Subject: [PATCH 2/2] make amps affect default tool instead of doing nothing --- .../common/spell/effect/EffectBreak.java | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/hollingsworth/arsnouveau/common/spell/effect/EffectBreak.java b/src/main/java/com/hollingsworth/arsnouveau/common/spell/effect/EffectBreak.java index da455cd2e..21f45cbcd 100644 --- a/src/main/java/com/hollingsworth/arsnouveau/common/spell/effect/EffectBreak.java +++ b/src/main/java/com/hollingsworth/arsnouveau/common/spell/effect/EffectBreak.java @@ -46,7 +46,7 @@ public int getDefaultManaCost() { return 10; } - public ItemStack getStack(LivingEntity shooter, InventoryManager inventory, BlockHitResult blockHitResult) { + public ItemStack getStack(double ampMultiplier, LivingEntity shooter, InventoryManager inventory, BlockHitResult blockHitResult) { ItemStack stack = shooter.getMainHandItem().copy(); BlockState state = shooter.level.getBlockState(blockHitResult.getBlockPos()); @@ -57,7 +57,17 @@ public ItemStack getStack(LivingEntity shooter, InventoryManager inventory, Bloc } } - return new ItemStack(Items.DIAMOND_PICKAXE); + return getDefaultTool(ampMultiplier); + } + + public ItemStack getDefaultTool(double ampMultiplier) { + if (ampMultiplier < 1.0) { + return new ItemStack(Items.IRON_PICKAXE); + } else if (ampMultiplier < 2.0) { + return new ItemStack(Items.DIAMOND_PICKAXE); + } else { + return new ItemStack(Items.NETHERITE_PICKAXE); + } } @Override @@ -82,7 +92,7 @@ public void onResolveBlock(BlockHitResult rayTraceResult, Level world, @NotNull InventoryManager manager = spellContext.getCaster().getInvManager(); Function compute = s -> { - ItemStack stack = getStack(shooter, manager, rayTraceResult); + ItemStack stack = getStack(spellStats.getAmpMultiplier(), shooter, manager, rayTraceResult); stack.set(DataComponents.UNBREAKABLE, new Unbreakable(true)); if (numFortune > 0 && stack.getEnchantmentLevel(fortune) < numFortune) {