From 563dc931e97c6703b9607d2197cea8f2e26bf500 Mon Sep 17 00:00:00 2001 From: jhqwqmc Date: Mon, 1 Dec 2025 05:07:02 +0800 Subject: [PATCH 1/5] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=94=BB=E9=80=A0?= =?UTF-8?q?=E9=85=8D=E6=96=B9=E5=90=8E=E5=A4=84=E7=90=86=E5=99=A8=E5=A6=82?= =?UTF-8?q?=E6=9E=9C=E4=BF=9D=E7=95=99custom=5Fdata=E7=BB=84=E4=BB=B6?= =?UTF-8?q?=E4=BC=9A=E5=86=99=E5=85=A5=E9=94=99=E8=AF=AF=E7=9A=84=E8=87=AA?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=E7=89=A9=E5=93=81ID=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/item/recipe/CustomSmithingTransformRecipe.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomSmithingTransformRecipe.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomSmithingTransformRecipe.java index 190ee8004..cad232493 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomSmithingTransformRecipe.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomSmithingTransformRecipe.java @@ -19,10 +19,7 @@ import net.momirealms.craftengine.core.util.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Objects; +import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -158,6 +155,7 @@ public class CustomSmithingTransformRecipe extends AbstractedFixedResultRecip private T createSmithingResult(Item base, T result) { Item wrappedResult = (Item) CraftEngine.instance().itemManager().wrap(result); Item finalResult = wrappedResult; + Optional customId = finalResult.customId(); // 修复在保留custom_data组件的时候意外保留前物品的id if (this.mergeComponents) { finalResult = base.mergeCopy(wrappedResult); } @@ -166,6 +164,9 @@ public class CustomSmithingTransformRecipe extends AbstractedFixedResultRecip processor.accept(base, wrappedResult, finalResult); } } + if (customId.isPresent()) { + finalResult.customId(customId.get()); + } return finalResult.getItem(); } From 13c76821d4b3e136b01fdf87121f5982c1716283 Mon Sep 17 00:00:00 2001 From: jhqwqmc Date: Tue, 2 Dec 2025 01:52:52 +0800 Subject: [PATCH 2/5] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=8E=89=E8=90=BD?= =?UTF-8?q?=E7=BB=8F=E9=AA=8C=E6=96=B9=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../block/behavior/BukkitBlockBehaviors.java | 2 + .../behavior/DropExperienceBlockBehavior.java | 104 ++++++++++++++++++ 2 files changed, 106 insertions(+) create mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/DropExperienceBlockBehavior.java diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BukkitBlockBehaviors.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BukkitBlockBehaviors.java index 11133b67d..090512f4c 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BukkitBlockBehaviors.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BukkitBlockBehaviors.java @@ -47,6 +47,7 @@ public class BukkitBlockBehaviors extends BlockBehaviors { public static final Key SURFACE_SPREADING_BLOCK = Key.from("craftengine:surface_spreading_block"); public static final Key SNOWY_BLOCK = Key.from("craftengine:snowy_block"); public static final Key HANGABLE_BLOCK = Key.from("craftengine:hangable_block"); + public static final Key DROP_EXPERIENCE_BLOCK = Key.from("craftengine:drop_experience_block"); public static void init() { register(EMPTY, (block, args) -> EmptyBlockBehavior.INSTANCE); @@ -92,5 +93,6 @@ public class BukkitBlockBehaviors extends BlockBehaviors { register(SURFACE_SPREADING_BLOCK, SurfaceSpreadingBlockBehavior.FACTORY); register(SNOWY_BLOCK, SnowyBlockBehavior.FACTORY); register(HANGABLE_BLOCK, HangableBlockBehavior.FACTORY); + register(DROP_EXPERIENCE_BLOCK, DropExperienceBlockBehavior.FACTORY); } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/DropExperienceBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/DropExperienceBlockBehavior.java new file mode 100644 index 000000000..ef629c558 --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/DropExperienceBlockBehavior.java @@ -0,0 +1,104 @@ +package net.momirealms.craftengine.bukkit.block.behavior; + +import net.momirealms.craftengine.bukkit.item.BukkitItemManager; +import net.momirealms.craftengine.bukkit.nms.FastNMS; +import net.momirealms.craftengine.bukkit.util.BlockStateUtils; +import net.momirealms.craftengine.bukkit.util.LocationUtils; +import net.momirealms.craftengine.bukkit.world.BukkitWorldManager; +import net.momirealms.craftengine.core.block.BlockBehavior; +import net.momirealms.craftengine.core.block.BlockSettings; +import net.momirealms.craftengine.core.block.CustomBlock; +import net.momirealms.craftengine.core.block.ImmutableBlockState; +import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory; +import net.momirealms.craftengine.core.item.Item; +import net.momirealms.craftengine.core.loot.LootContext; +import net.momirealms.craftengine.core.plugin.context.Condition; +import net.momirealms.craftengine.core.plugin.context.Context; +import net.momirealms.craftengine.core.plugin.context.ContextHolder; +import net.momirealms.craftengine.core.plugin.context.condition.AllOfCondition; +import net.momirealms.craftengine.core.plugin.context.event.EventConditions; +import net.momirealms.craftengine.core.plugin.context.number.NumberProvider; +import net.momirealms.craftengine.core.plugin.context.number.NumberProviders; +import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters; +import net.momirealms.craftengine.core.util.ResourceConfigUtils; +import net.momirealms.craftengine.core.world.BlockPos; +import net.momirealms.craftengine.core.world.Vec3d; +import net.momirealms.craftengine.core.world.World; +import net.momirealms.craftengine.core.world.WorldPosition; +import org.bukkit.inventory.ItemStack; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.Callable; + +public class DropExperienceBlockBehavior extends BukkitBlockBehavior { + public static final Factory FACTORY = new Factory(); + private final NumberProvider amount; + private final Condition conditions; + + public DropExperienceBlockBehavior(CustomBlock customBlock, NumberProvider amount, Condition conditions) { + super(customBlock); + this.amount = amount; + this.conditions = conditions; + } + + @Override + public void spawnAfterBreak(Object thisBlock, Object[] args, Callable superMethod) { + boolean dropExperience = (boolean) args[4]; // 通常来说是 false + Item item = BukkitItemManager.instance().wrap(FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(args[3])); + if (!dropExperience) { + ImmutableBlockState state = BlockStateUtils.getOptionalCustomBlockState(args[0]).orElse(null); + if (state == null) { + return; + } + BlockSettings settings = state.settings(); + if (settings.requireCorrectTool()) { + if (item.isEmpty()) { + return; + } + boolean cannotBreak = !settings.isCorrectTool(item.id()) + && (!settings.respectToolComponent() + || !FastNMS.INSTANCE.method$ItemStack$isCorrectToolForDrops(args[3], state.customBlockState().literalObject())); + if (cannotBreak) { + return; + } + } + } + World world = BukkitWorldManager.instance().wrap(FastNMS.INSTANCE.method$Level$getCraftWorld(args[1])); + BlockPos pos = LocationUtils.fromBlockPos(args[2]); + tryDropExperience(world, pos, item); + } + + private void tryDropExperience(World world, BlockPos pos, Item item) { + Vec3d dropPos = Vec3d.atCenterOf(pos); + ContextHolder holder = ContextHolder.builder() + .withParameter(DirectContextParameters.POSITION, new WorldPosition(world, dropPos)) + .withParameter(DirectContextParameters.ITEM_IN_HAND, item) + .build(); + LootContext context = new LootContext(world, null, 1.0f, holder); + if (this.conditions != null && !this.conditions.test(context)) { + return; + } + int finalAmount = this.amount.getInt(context); + if (finalAmount <= 0) { + return; + } + world.dropExp(dropPos, finalAmount); + } + + public static class Factory implements BlockBehaviorFactory { + + @Override + public BlockBehavior create(CustomBlock block, Map arguments) { + NumberProvider amount = NumberProviders.fromObject(arguments.getOrDefault("amount", 0)); + Condition conditions = null; + List> conditionList = ResourceConfigUtils.parseConfigAsList(ResourceConfigUtils.get(arguments, "conditions", "condition"), EventConditions::fromMap); + if (conditionList.size() == 1) { + conditions = conditionList.getFirst(); + } else if (!conditionList.isEmpty()) { + conditions = new AllOfCondition<>(conditionList); + } + return new DropExperienceBlockBehavior(block, amount, conditions); + } + } +} From db27567b12d8e41e2e9a74f9455982e82dc227e1 Mon Sep 17 00:00:00 2001 From: jhqwqmc Date: Tue, 2 Dec 2025 01:58:07 +0800 Subject: [PATCH 3/5] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=BB=98=E8=AE=A4?= =?UTF-8?q?=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../default/configuration/blocks/topaz_ore.yml | 16 ++++++++++++---- .../configuration/templates/loot_tables.yml | 3 --- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/common-files/src/main/resources/resources/default/configuration/blocks/topaz_ore.yml b/common-files/src/main/resources/resources/default/configuration/blocks/topaz_ore.yml index 1a5a03297..2435ae04e 100644 --- a/common-files/src/main/resources/resources/default/configuration/blocks/topaz_ore.yml +++ b/common-files/src/main/resources/resources/default/configuration/blocks/topaz_ore.yml @@ -27,13 +27,17 @@ items: texture: minecraft:item/custom/topaz blocks: default:topaz_ore: + behavior: + type: drop_experience_block + amount: 3~7 + condition: + type: enchantment + predicate: minecraft:silk_touch<=0 loot: template: default:loot_table/ore arguments: ore_drop: default:topaz ore_block: default:topaz_ore - min_exp: 3 - max_exp: 7 settings: template: default:settings/ore arguments: @@ -45,13 +49,17 @@ blocks: arguments: path: minecraft:block/custom/topaz_ore default:deepslate_topaz_ore: + behavior: + type: drop_experience_block + amount: 3~7 + condition: + type: enchantment + predicate: minecraft:silk_touch<=0 loot: template: default:loot_table/ore arguments: ore_drop: default:topaz ore_block: default:deepslate_topaz_ore - min_exp: 3 - max_exp: 7 settings: template: default:settings/deepslate_ore arguments: diff --git a/common-files/src/main/resources/resources/default/configuration/templates/loot_tables.yml b/common-files/src/main/resources/resources/default/configuration/templates/loot_tables.yml index 24d3c1878..c089ddca6 100644 --- a/common-files/src/main/resources/resources/default/configuration/templates/loot_tables.yml +++ b/common-files/src/main/resources/resources/default/configuration/templates/loot_tables.yml @@ -180,7 +180,6 @@ templates: # ore_block: the ore block # ore_drop: the drops of the ore material # ore_drop_count: the amount of the ore materials - # exp: the exp to drop default:loot_table/ore: pools: - rolls: 1 @@ -203,8 +202,6 @@ templates: formula: type: ore_drops - type: explosion_decay - - type: drop_exp - count: ${exp:-2~4} # Using Silk Touch or shears will cause the leaves block itself to drop. # Using Fortune, however, increases the drop rates of sticks and saplings. From c5bc8d8e3b014c809dfa70d0681705e81f282094 Mon Sep 17 00:00:00 2001 From: jhqwqmc Date: Tue, 2 Dec 2025 21:47:47 +0800 Subject: [PATCH 4/5] =?UTF-8?q?=E6=94=B9=E8=BF=9B=E5=90=88=E5=B9=B6?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/translations/en.yml | 1 + .../src/main/resources/translations/zh_cn.yml | 1 + .../recipe/CustomSmithingTransformRecipe.java | 45 ++++++++++++++++--- 3 files changed, 42 insertions(+), 5 deletions(-) diff --git a/common-files/src/main/resources/translations/en.yml b/common-files/src/main/resources/translations/en.yml index fce2f7ea7..b53305b6e 100644 --- a/common-files/src/main/resources/translations/en.yml +++ b/common-files/src/main/resources/translations/en.yml @@ -161,6 +161,7 @@ warning.config.recipe.smithing_transform.post_processor.missing_type: "I warning.config.recipe.smithing_transform.post_processor.invalid_type: "Issue found in file - The smithing transform recipe '' is using an invalid post processor type ''." warning.config.recipe.smithing_transform.post_processor.keep_component.missing_components: "Issue found in file - The smithing transform recipe '' is missing the required argument 'components' for post-processors 'keep_components'." warning.config.recipe.smithing_transform.post_processor.keep_component.missing_tags: "Issue found in file - The smithing transform recipe '' is missing the required argument 'tags' for post-processors 'keep_tags'." +warning.config.recipe.smithing_transform.post_processor.keep_custom_data.missing_paths: "Issue found in file - The smithing transform recipe '' is missing the required argument 'paths' for post-processors 'keep_custom_data'." warning.config.recipe.smithing_transform.missing_base: "Issue found in file - The smithing transform recipe '' is missing the required 'base' argument." warning.config.recipe.smithing_trim.missing_base: "Issue found in file - The smithing trim recipe '' is missing the required 'base' argument." warning.config.recipe.smithing_trim.missing_template_type: "Issue found in file - The smithing trim recipe '' is missing the required 'template-type' argument." diff --git a/common-files/src/main/resources/translations/zh_cn.yml b/common-files/src/main/resources/translations/zh_cn.yml index da06eeff2..bbada1743 100644 --- a/common-files/src/main/resources/translations/zh_cn.yml +++ b/common-files/src/main/resources/translations/zh_cn.yml @@ -159,6 +159,7 @@ warning.config.recipe.smithing_transform.post_processor.missing_type: " warning.config.recipe.smithing_transform.post_processor.invalid_type: "在文件 发现问题 - 锻造升级配方 '' 使用了无效的后处理器类型 ''" warning.config.recipe.smithing_transform.post_processor.keep_component.missing_components: "在文件 发现问题 - 锻造升级配方 '' 的 'keep_components' 后处理器缺少必需的 'components' 参数" warning.config.recipe.smithing_transform.post_processor.keep_component.missing_tags: "在文件 发现问题 - 锻造升级配方 '' 的 'keep_tags' 后处理器缺少必需的 'tags' 参数" +warning.config.recipe.smithing_transform.post_processor.keep_custom_data.missing_paths: "在文件 发现问题 - 锻造升级配方 '' 的 'keep_custom_data' 后处理器缺少必需的 'paths' 参数" warning.config.recipe.smithing_transform.missing_base: "在文件 发现问题 - 锻造升级配方 '' 缺少必需的 'base' 参数" warning.config.recipe.smithing_trim.missing_base: "在文件 发现问题 - 锻造纹饰配方 '' 缺少必需的 'base' 参数" warning.config.recipe.smithing_trim.missing_template_type: "在文件 发现问题 - 锻造纹饰配方 '' 缺少必需的 'template-type' 参数" diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomSmithingTransformRecipe.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomSmithingTransformRecipe.java index cad232493..87730aa0e 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomSmithingTransformRecipe.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomSmithingTransformRecipe.java @@ -155,7 +155,6 @@ public class CustomSmithingTransformRecipe extends AbstractedFixedResultRecip private T createSmithingResult(Item base, T result) { Item wrappedResult = (Item) CraftEngine.instance().itemManager().wrap(result); Item finalResult = wrappedResult; - Optional customId = finalResult.customId(); // 修复在保留custom_data组件的时候意外保留前物品的id if (this.mergeComponents) { finalResult = base.mergeCopy(wrappedResult); } @@ -164,9 +163,6 @@ public class CustomSmithingTransformRecipe extends AbstractedFixedResultRecip processor.accept(base, wrappedResult, finalResult); } } - if (customId.isPresent()) { - finalResult.customId(customId.get()); - } return finalResult.getItem(); } @@ -233,10 +229,12 @@ public class CustomSmithingTransformRecipe extends AbstractedFixedResultRecip public static final Key KEEP_COMPONENTS = Key.of("craftengine:keep_components"); public static final Key KEEP_TAGS = Key.of("craftengine:keep_tags"); public static final Key MERGE_ENCHANTMENTS = Key.of("craftengine:merge_enchantments"); + public static final Key KEEP_CUSTOM_DATA = Key.of("craftengine:keep_custom_data"); static { if (VersionHelper.isOrAbove1_20_5()) { register(KEEP_COMPONENTS, KeepComponents.FACTORY); + register(KEEP_CUSTOM_DATA, KeepCustomData.FACTORY); } else { register(KEEP_TAGS, KeepTags.FACTORY); } @@ -316,6 +314,42 @@ public class CustomSmithingTransformRecipe extends AbstractedFixedResultRecip } } + public static class KeepCustomData implements ItemDataProcessor { + public static final Factory FACTORY = new Factory(); + private final List paths; + + public KeepCustomData(List data) { + this.paths = data; + } + + @Override + public void accept(Item item1, Item item2, Item item3) { + for (String[] path : this.paths) { + Object dataObj = item1.getJavaTag((Object[]) path); + if (dataObj != null) { + item3.setTag(dataObj, (Object[]) path); + } + } + } + + @Override + public Key type() { + return ItemDataProcessors.KEEP_CUSTOM_DATA; + } + + public static class Factory implements ProcessorFactory { + + @Override + public ItemDataProcessor create(Map arguments) { + List paths = MiscUtils.getAsStringList(ResourceConfigUtils.requireNonNullOrThrow( + arguments.get("paths"), + "warning.config.recipe.smithing_transform.post_processor.keep_custom_data.missing_paths") + ); + return new KeepCustomData(paths.stream().map(it -> it.split("\\.")).toList()); + } + } + } + public static class KeepComponents implements ItemDataProcessor { public static final Factory FACTORY = new Factory(); private final List components; @@ -340,6 +374,7 @@ public class CustomSmithingTransformRecipe extends AbstractedFixedResultRecip } public static class Factory implements ProcessorFactory { + private static final Key CUSTOM_DATA = Key.of("minecraft", "custom_data"); @Override public ItemDataProcessor create(Map arguments) { @@ -348,7 +383,7 @@ public class CustomSmithingTransformRecipe extends AbstractedFixedResultRecip throw new LocalizedResourceConfigException("warning.config.recipe.smithing_transform.post_processor.keep_component.missing_components"); } List components = MiscUtils.getAsStringList(componentsObj); - return new KeepComponents(components.stream().map(Key::of).toList()); + return new KeepComponents(components.stream().map(Key::of).filter(it -> !CUSTOM_DATA.equals(it)).toList()); } } } From 20e1a42f6256292fe50e09768e241cad441e64ca Mon Sep 17 00:00:00 2001 From: jhqwqmc Date: Tue, 2 Dec 2025 23:19:33 +0800 Subject: [PATCH 5/5] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=AE=80=E5=8D=95?= =?UTF-8?q?=E5=AD=98=E5=82=A8=E5=AE=B9=E5=99=A8=E5=85=B3=E4=B8=8D=E4=B8=8A?= =?UTF-8?q?=E9=97=A8=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bukkit/block/entity/SimpleStorageBlockEntity.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/SimpleStorageBlockEntity.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/SimpleStorageBlockEntity.java index 625818617..5649bccc4 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/SimpleStorageBlockEntity.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/SimpleStorageBlockEntity.java @@ -173,7 +173,9 @@ public class SimpleStorageBlockEntity extends BlockEntity { public void updateOpenBlockState(boolean open) { ImmutableBlockState state = super.world.getBlockStateAtIfLoaded(this.pos); if (state == null || state.behavior() != this.behavior) return; - Property property = this.behavior.openProperty(); + SimpleStorageBlockBehavior behavior = state.behavior().getAs(SimpleStorageBlockBehavior.class).orElse(null); + if (behavior == null) return; + Property property = behavior.openProperty(); if (property == null) return; super.world.world().setBlockState(this.pos.x(), this.pos.y(), this.pos.z(), state.with(property, open), UpdateOption.UPDATE_ALL.flags()); }