From 140273ca413cb0250e77b67d40e39f506c6aadf5 Mon Sep 17 00:00:00 2001 From: YocyCraft Date: Mon, 16 Feb 2026 13:52:13 +0800 Subject: [PATCH 1/4] fix(item): exp gem is not consumed when used by creative mode player --- .../dev/dubhe/anvilcraft/item/ExpGemItem.java | 79 +++++++++++-------- .../mixin/accessor/VillagerAccessor.java | 19 +++++ src/main/resources/anvilcraft.mixins.json | 1 + 3 files changed, 64 insertions(+), 35 deletions(-) create mode 100644 src/main/java/dev/dubhe/anvilcraft/mixin/accessor/VillagerAccessor.java diff --git a/src/main/java/dev/dubhe/anvilcraft/item/ExpGemItem.java b/src/main/java/dev/dubhe/anvilcraft/item/ExpGemItem.java index bdb82692ee..d3363de3aa 100644 --- a/src/main/java/dev/dubhe/anvilcraft/item/ExpGemItem.java +++ b/src/main/java/dev/dubhe/anvilcraft/item/ExpGemItem.java @@ -2,6 +2,7 @@ import com.google.common.collect.Lists; import dev.dubhe.anvilcraft.block.ExpFluidBlock; +import dev.dubhe.anvilcraft.mixin.accessor.VillagerAccessor; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import net.minecraft.sounds.SoundEvents; import net.minecraft.world.InteractionHand; @@ -41,7 +42,7 @@ public InteractionResultHolder use( ItemStack itemStack = player.getItemInHand(usedHand); int count = player.isShiftKeyDown() ? itemStack.getCount() : 1; player.giveExperiencePoints(ExpFluidBlock.XP_POINTS * count); - itemStack.shrink(count); + itemStack.consume(count, player); player.getCooldowns().addCooldown(this, 5); return InteractionResultHolder.sidedSuccess(itemStack, level.isClientSide()); } @@ -60,11 +61,11 @@ public static InteractionResult useEntity(Player player, Entity target, ItemStac if (!VillagerData.canLevelUp(villagerLevel)) return InteractionResult.PASS; updateVillager(villager); - stack.shrink(1); + stack.consume(1, player); return InteractionResult.SUCCESS; } else { villager.ageUp(AGE_ADDITION, true); - stack.shrink(1); + stack.consume(1, player); return InteractionResult.SUCCESS; } } @@ -74,40 +75,48 @@ public static void updateVillager(Villager villager) { int villagerLevel = villagerData.getLevel(); int villagerXp = villager.getVillagerXp() + VILLAGER_XP; villager.setVillagerXp(villagerXp); - // 检测经验值是否足够,足够则升级(我好想直接用Villager::increaseMerchantCareer啊,可惜protect) - if (villagerXp >= VillagerData.getMaxXpPerLevel(villagerLevel)) { - villager.setVillagerXp(villagerXp); - ++villagerLevel; - villagerData = villagerData.setLevel(villagerLevel); - villager.setVillagerData(villagerData); - villager.addEffect(new MobEffectInstance(MobEffects.REGENERATION, 200, 0)); - villager.playSound(SoundEvents.PLAYER_LEVELUP, 1.0F, 0.9f + 0.2f * villager.getRandom().nextFloat()); - - // 获取对应职业的交易列表 - Int2ObjectMap trades = VillagerTrades.TRADES.get(villagerData.getProfession()); - if (villager.level().enabledFeatures().contains(FeatureFlags.TRADE_REBALANCE)) { - Int2ObjectMap rebalanceTrades = - VillagerTrades.EXPERIMENTAL_TRADES.get(villagerData.getProfession()); - if (rebalanceTrades != null) { - trades = rebalanceTrades; - } - } - if (trades == null || trades.isEmpty()) return; - VillagerTrades.ItemListing[] itemlisting = trades.get(villagerLevel); - if (itemlisting == null) return; - ArrayList arraylist = Lists.newArrayList(itemlisting); - - // 更新村民当前的交易列表(MerchantOffers) - MerchantOffers merchantoffers = villager.getOffers(); - for (int i = 0; i < itemlisting.length; i++) { - if (arraylist.isEmpty() || i >= 2) break; - MerchantOffer merchantoffer = arraylist.remove(villager.getRandom().nextInt(arraylist.size())) - .getOffer(villager, villager.getRandom()); - if (merchantoffer != null) { - merchantoffers.add(merchantoffer); - } + if (villager instanceof VillagerAccessor villager1) { + if (villager1.invokeShouldIncreaseLevel()) { + villager1.setUpdateMerchantTimer(40); + villager1.setIncreaseProfessionLevelOnUpdate(true); } } + +// // 检测经验值是否足够,足够则升级(我好想直接用Villager::increaseMerchantCareer啊,可惜protect) +// if (villagerXp >= VillagerData.getMaxXpPerLevel(villagerLevel)) { +// villager.setVillagerXp(villagerXp); +// ++villagerLevel; +// villagerData = villagerData.setLevel(villagerLevel); +// villager.setVillagerData(villagerData); +// +// villager.addEffect(new MobEffectInstance(MobEffects.REGENERATION, 200, 0)); +// villager.playSound(SoundEvents.PLAYER_LEVELUP, 1.0F, 0.9f + 0.2f * villager.getRandom().nextFloat()); +// +// // 获取对应职业的交易列表 +// Int2ObjectMap trades = VillagerTrades.TRADES.get(villagerData.getProfession()); +// if (villager.level().enabledFeatures().contains(FeatureFlags.TRADE_REBALANCE)) { +// Int2ObjectMap rebalanceTrades = +// VillagerTrades.EXPERIMENTAL_TRADES.get(villagerData.getProfession()); +// if (rebalanceTrades != null) { +// trades = rebalanceTrades; +// } +// } +// if (trades == null || trades.isEmpty()) return; +// VillagerTrades.ItemListing[] itemlisting = trades.get(villagerLevel); +// if (itemlisting == null) return; +// ArrayList arraylist = Lists.newArrayList(itemlisting); +// +// // 更新村民当前的交易列表(MerchantOffers) +// MerchantOffers merchantoffers = villager.getOffers(); +// for (int i = 0; i < itemlisting.length; i++) { +// if (arraylist.isEmpty() || i >= 2) break; +// MerchantOffer merchantoffer = arraylist.remove(villager.getRandom().nextInt(arraylist.size())) +// .getOffer(villager, villager.getRandom()); +// if (merchantoffer != null) { +// merchantoffers.add(merchantoffer); +// } +// } +// } } } diff --git a/src/main/java/dev/dubhe/anvilcraft/mixin/accessor/VillagerAccessor.java b/src/main/java/dev/dubhe/anvilcraft/mixin/accessor/VillagerAccessor.java new file mode 100644 index 0000000000..7e3e52bd9d --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/mixin/accessor/VillagerAccessor.java @@ -0,0 +1,19 @@ +package dev.dubhe.anvilcraft.mixin.accessor; + +import net.minecraft.world.entity.npc.Villager; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(Villager.class) +public interface VillagerAccessor { + + @Accessor + void setUpdateMerchantTimer(int timer); + + @Accessor + void setIncreaseProfessionLevelOnUpdate(boolean flag); + + @Invoker + boolean invokeShouldIncreaseLevel(); +} diff --git a/src/main/resources/anvilcraft.mixins.json b/src/main/resources/anvilcraft.mixins.json index aec4d1bfbd..91d3f37970 100644 --- a/src/main/resources/anvilcraft.mixins.json +++ b/src/main/resources/anvilcraft.mixins.json @@ -63,6 +63,7 @@ "accessor.ShapedRecipePatternAccessor", "accessor.TargetingConditionsAccessor", "accessor.VaultServerDataAccessor", + "accessor.VillagerAccessor", "invoker.BlockBehaviourInvoker", "invoker.BlockItemInvoker", "piglin.AbstractPiglinMixin", From 2b8ce22fb7f335e7996a22202ff8488560f48b73 Mon Sep 17 00:00:00 2001 From: YocyCraft Date: Mon, 16 Feb 2026 14:07:36 +0800 Subject: [PATCH 2/4] fix(style): remove import and comment --- .../dev/dubhe/anvilcraft/item/ExpGemItem.java | 49 ------------------- 1 file changed, 49 deletions(-) diff --git a/src/main/java/dev/dubhe/anvilcraft/item/ExpGemItem.java b/src/main/java/dev/dubhe/anvilcraft/item/ExpGemItem.java index d3363de3aa..a864d61e0b 100644 --- a/src/main/java/dev/dubhe/anvilcraft/item/ExpGemItem.java +++ b/src/main/java/dev/dubhe/anvilcraft/item/ExpGemItem.java @@ -1,30 +1,19 @@ package dev.dubhe.anvilcraft.item; -import com.google.common.collect.Lists; import dev.dubhe.anvilcraft.block.ExpFluidBlock; import dev.dubhe.anvilcraft.mixin.accessor.VillagerAccessor; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import net.minecraft.sounds.SoundEvents; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.InteractionResultHolder; -import net.minecraft.world.effect.MobEffectInstance; -import net.minecraft.world.effect.MobEffects; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.npc.Villager; import net.minecraft.world.entity.npc.VillagerData; import net.minecraft.world.entity.npc.VillagerProfession; -import net.minecraft.world.entity.npc.VillagerTrades; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.flag.FeatureFlags; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.trading.MerchantOffer; -import net.minecraft.world.item.trading.MerchantOffers; import net.minecraft.world.level.Level; -import java.util.ArrayList; - public class ExpGemItem extends Item { public static final int VILLAGER_XP = 20; public static final int AGE_ADDITION = 2 * 60; @@ -71,8 +60,6 @@ public static InteractionResult useEntity(Player player, Entity target, ItemStac } public static void updateVillager(Villager villager) { - VillagerData villagerData = villager.getVillagerData(); - int villagerLevel = villagerData.getLevel(); int villagerXp = villager.getVillagerXp() + VILLAGER_XP; villager.setVillagerXp(villagerXp); @@ -82,41 +69,5 @@ public static void updateVillager(Villager villager) { villager1.setIncreaseProfessionLevelOnUpdate(true); } } - -// // 检测经验值是否足够,足够则升级(我好想直接用Villager::increaseMerchantCareer啊,可惜protect) -// if (villagerXp >= VillagerData.getMaxXpPerLevel(villagerLevel)) { -// villager.setVillagerXp(villagerXp); -// ++villagerLevel; -// villagerData = villagerData.setLevel(villagerLevel); -// villager.setVillagerData(villagerData); -// -// villager.addEffect(new MobEffectInstance(MobEffects.REGENERATION, 200, 0)); -// villager.playSound(SoundEvents.PLAYER_LEVELUP, 1.0F, 0.9f + 0.2f * villager.getRandom().nextFloat()); -// -// // 获取对应职业的交易列表 -// Int2ObjectMap trades = VillagerTrades.TRADES.get(villagerData.getProfession()); -// if (villager.level().enabledFeatures().contains(FeatureFlags.TRADE_REBALANCE)) { -// Int2ObjectMap rebalanceTrades = -// VillagerTrades.EXPERIMENTAL_TRADES.get(villagerData.getProfession()); -// if (rebalanceTrades != null) { -// trades = rebalanceTrades; -// } -// } -// if (trades == null || trades.isEmpty()) return; -// VillagerTrades.ItemListing[] itemlisting = trades.get(villagerLevel); -// if (itemlisting == null) return; -// ArrayList arraylist = Lists.newArrayList(itemlisting); -// -// // 更新村民当前的交易列表(MerchantOffers) -// MerchantOffers merchantoffers = villager.getOffers(); -// for (int i = 0; i < itemlisting.length; i++) { -// if (arraylist.isEmpty() || i >= 2) break; -// MerchantOffer merchantoffer = arraylist.remove(villager.getRandom().nextInt(arraylist.size())) -// .getOffer(villager, villager.getRandom()); -// if (merchantoffer != null) { -// merchantoffers.add(merchantoffer); -// } -// } -// } } } From 60b334dd7e69696c0b6b76741ff65ec88bbb0e0d Mon Sep 17 00:00:00 2001 From: YocyCraft Date: Wed, 18 Feb 2026 20:33:58 +0800 Subject: [PATCH 3/4] fix(fluid): fix player inside behavior of exp fluid --- .../java/dev/dubhe/anvilcraft/block/ExpFluidBlock.java | 2 +- .../java/dev/dubhe/anvilcraft/init/block/ModBlocks.java | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/dev/dubhe/anvilcraft/block/ExpFluidBlock.java b/src/main/java/dev/dubhe/anvilcraft/block/ExpFluidBlock.java index 35cf2bdcb0..15a87dd1ae 100644 --- a/src/main/java/dev/dubhe/anvilcraft/block/ExpFluidBlock.java +++ b/src/main/java/dev/dubhe/anvilcraft/block/ExpFluidBlock.java @@ -18,8 +18,8 @@ public ExpFluidBlock(FlowingFluid fluid, Properties properties) { @Override public void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) { - // 这个不触发,我没招了... if (level.isClientSide) return; + if (!level.getFluidState(pos).isSource()) return; if (entity instanceof Player player) { player.giveExperiencePoints(XP_POINTS); level.setBlock(pos, Blocks.AIR.defaultBlockState(), 3); diff --git a/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlocks.java b/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlocks.java index a7974c360b..74afe6d940 100644 --- a/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlocks.java +++ b/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlocks.java @@ -4401,9 +4401,9 @@ private static BlockEntry registerPressu }) .register(); - public static final BlockEntry EXP_FLUID = REGISTRATE.block( + public static final BlockEntry EXP_FLUID = REGISTRATE.block( "exp_fluid", - p -> new LiquidBlock(ModFluids.EXP_FLUID.get(), p) + p -> new ExpFluidBlock(ModFluids.EXP_FLUID.get(), p) ) .properties(it -> it.mapColor(MapColor.COLOR_GREEN) .replaceable() @@ -4416,7 +4416,8 @@ private static BlockEntry registerPressu .blockstate(ModelProviderUtil::liquid) .register(); - public static final BlockEntry OIL = REGISTRATE.block("oil", p -> new ExpFluidBlock(ModFluids.OIL.get(), p)) + public static final BlockEntry OIL = REGISTRATE.block( + "oil", p -> new LiquidBlock(ModFluids.OIL.get(), p)) .properties(it -> it.mapColor(MapColor.TERRACOTTA_BLACK) .replaceable() .noCollission() From d426c6701495a39a344e833e36d5d625ef6583b0 Mon Sep 17 00:00:00 2001 From: QiuShui1012 <150409561+QiuShui1012@users.noreply.github.com> Date: Wed, 25 Feb 2026 06:54:41 +0800 Subject: [PATCH 4/4] =?UTF-8?q?style(=E7=BB=8F=E9=AA=8C=E5=AE=9D=E7=9F=B3)?= =?UTF-8?q?:=20=E4=BC=98=E5=8C=96Mixin=20Accessor=E8=BD=AC=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将Mixin Accessor的instanceof转换替换为了Util.cast --- .../java/dev/dubhe/anvilcraft/item/ExpGemItem.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/dev/dubhe/anvilcraft/item/ExpGemItem.java b/src/main/java/dev/dubhe/anvilcraft/item/ExpGemItem.java index a864d61e0b..21c484ca09 100644 --- a/src/main/java/dev/dubhe/anvilcraft/item/ExpGemItem.java +++ b/src/main/java/dev/dubhe/anvilcraft/item/ExpGemItem.java @@ -2,6 +2,7 @@ import dev.dubhe.anvilcraft.block.ExpFluidBlock; import dev.dubhe.anvilcraft.mixin.accessor.VillagerAccessor; +import dev.dubhe.anvilcraft.util.Util; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.InteractionResultHolder; @@ -63,11 +64,10 @@ public static void updateVillager(Villager villager) { int villagerXp = villager.getVillagerXp() + VILLAGER_XP; villager.setVillagerXp(villagerXp); - if (villager instanceof VillagerAccessor villager1) { - if (villager1.invokeShouldIncreaseLevel()) { - villager1.setUpdateMerchantTimer(40); - villager1.setIncreaseProfessionLevelOnUpdate(true); - } + VillagerAccessor accessor = Util.cast(villager); + if (accessor.invokeShouldIncreaseLevel()) { + accessor.setUpdateMerchantTimer(40); + accessor.setIncreaseProfessionLevelOnUpdate(true); } } }