From 28df27e9d6ec2a9f31ee93fd5b9d7cca3599e2c7 Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Mon, 17 Mar 2025 16:45:56 +0800 Subject: [PATCH 01/15] fix templates --- README.md | 4 +-- .../default/configuration/palm_tree.yml | 6 ++-- .../default/configuration/templates.yml | 30 ++++++++++++++----- 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 33bd80f46..ea3c73de8 100644 --- a/README.md +++ b/README.md @@ -135,7 +135,7 @@ repositories { ``` ```kotlin dependencies { - compileOnly("net.momirealms:craft-engine-core:0.0.29") - compileOnly("net.momirealms:craft-engine-bukkit:0.0.29") + compileOnly("net.momirealms:craft-engine-core:0.0.34") + compileOnly("net.momirealms:craft-engine-bukkit:0.0.34") } ``` diff --git a/bukkit-loader/src/main/resources/resources/default/configuration/palm_tree.yml b/bukkit-loader/src/main/resources/resources/default/configuration/palm_tree.yml index f2aefb28d..b3446fb13 100644 --- a/bukkit-loader/src/main/resources/resources/default/configuration/palm_tree.yml +++ b/bukkit-loader/src/main/resources/resources/default/configuration/palm_tree.yml @@ -314,12 +314,12 @@ recipes: default:palm_planks: template: default:recipe/planks arguments: - tree_type: palm + wood_type: palm default:palm_wood: template: default:recipe/log_2_wood arguments: - tree_type: palm + wood_type: palm default:stripped_palm_wood: template: default:recipe/log_2_wood arguments: - tree_type: stripped_palm \ No newline at end of file + wood_type: stripped_palm \ No newline at end of file diff --git a/bukkit-loader/src/main/resources/resources/default/configuration/templates.yml b/bukkit-loader/src/main/resources/resources/default/configuration/templates.yml index 4a7a39aa8..d365adc15 100644 --- a/bukkit-loader/src/main/resources/resources/default/configuration/templates.yml +++ b/bukkit-loader/src/main/resources/resources/default/configuration/templates.yml @@ -92,6 +92,22 @@ templates#models#generated: textures: "layer0": "{path}" +# shield +templates#models#shield: + # template: default:model/shield_3d + # arguments: + # model: shield_model_path + # block_model: shield_block_model_path + default:model/shield_3d: + type: "minecraft:condition" + property: "minecraft:using_item" + on-false: + type: minecraft:model + path: "{model}" + on-true: + type: minecraft:model + path: "{block_model}" + # fishing rods templates#models#fishing_rod: # template: default:model/fishing_rod_3d @@ -305,7 +321,7 @@ templates#models#crossbow: - when: arrow model: type: minecraft:model - path: "{arrow_path}" + path: "{arrow_model}" generation: parent: "minecraft:item/crossbow_arrow" textures: @@ -320,7 +336,7 @@ templates#models#crossbow: "layer0": "{firework_texture}" fallback: type: minecraft:model - path: "{path}" + path: "{model}" generation: parent: "minecraft:item/crossbow" textures: @@ -339,7 +355,7 @@ templates#models#crossbow: threshold: 0.58 - model: type: minecraft:model - path: "{pulling_2_path}" + path: "{pulling_2_model}" generation: parent: "minecraft:item/crossbow_pulling_2" textures: @@ -862,9 +878,9 @@ templates#recipes: category: building group: planks ingredients: - A: "#default:{tree_type}_logs" + A: "#default:{wood_type}_logs" result: - id: "default:{tree_type}_planks" + id: "default:{wood_type}_planks" count: 4 default:recipe/log_2_wood: type: shaped @@ -874,9 +890,9 @@ templates#recipes: - "AA" - "AA" ingredients: - A: "default:{tree_type}_log" + A: "default:{wood_type}_log" result: - id: "default:{tree_type}_wood" + id: "default:{wood_type}_wood" count: 3 default:recipe/smelting_ore: type: smelting From cb5925775577b36ae8485d6708317e94841ae65d Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Mon, 17 Mar 2025 16:48:15 +0800 Subject: [PATCH 02/15] Update templates.yml --- .../resources/resources/default/configuration/templates.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bukkit-loader/src/main/resources/resources/default/configuration/templates.yml b/bukkit-loader/src/main/resources/resources/default/configuration/templates.yml index d365adc15..42161181f 100644 --- a/bukkit-loader/src/main/resources/resources/default/configuration/templates.yml +++ b/bukkit-loader/src/main/resources/resources/default/configuration/templates.yml @@ -274,14 +274,14 @@ templates#models#crossbow: - when: arrow model: type: minecraft:model - path: "{arrow_path}" + path: "{arrow_model}" - when: rocket model: type: minecraft:model path: "{firework_model}" fallback: type: minecraft:model - path: "{path}" + path: "{model}" on-true: type: "minecraft:range_dispatch" property: "minecraft:crossbow/pull" From efbf273d65ff7d89dc18dd535702b84ed508219c Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Mon, 17 Mar 2025 19:46:41 +0800 Subject: [PATCH 03/15] bump sparrow util --- .../default/configuration/templates.yml | 24 ++++++++++++++++++- .../recipe/CustomSmithingTransformRecipe.java | 4 ++++ .../core/item/recipe/RecipeTypes.java | 1 + gradle.properties | 2 +- 4 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomSmithingTransformRecipe.java diff --git a/bukkit-loader/src/main/resources/resources/default/configuration/templates.yml b/bukkit-loader/src/main/resources/resources/default/configuration/templates.yml index 42161181f..d8c84f87f 100644 --- a/bukkit-loader/src/main/resources/resources/default/configuration/templates.yml +++ b/bukkit-loader/src/main/resources/resources/default/configuration/templates.yml @@ -33,9 +33,31 @@ templates#models#block: textures: "end": "{end_texture}" "side": "{side_texture}" + # template: default:model/cube + # arguments: + # model: model_path + # particle_texture: particle_texture_path + # down_texture: down_texture_path + # up_texture: up_texture_path + # north_texture: north_texture_path + # east_texture: east_texture_path + # south_texture: south_texture_path + # west_texture: west_texture_path + default:model/cube: + path: "{model}" + generation: + parent: "minecraft:block/cube_column" + textures: + "particle": "minecraft:block/custom/block_particle" + "down": "minecraft:block/custom/block_down" + "up": "minecraft:block/custom/block_up" + "north": "minecraft:block/custom/block_north" + "east": "minecraft:block/custom/block_east" + "south": "minecraft:block/custom/block_south" + "west": "minecraft:block/custom/block_west" # 2D items -templates#models#generated: +templates#models#2d: # template: default:model/generated # arguments: # model: model_path 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 new file mode 100644 index 000000000..fb74a8767 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomSmithingTransformRecipe.java @@ -0,0 +1,4 @@ +package net.momirealms.craftengine.core.item.recipe; + +public class CustomSmithingTransformRecipe { +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/RecipeTypes.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/RecipeTypes.java index e350f5111..fb81f5678 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/RecipeTypes.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/RecipeTypes.java @@ -17,6 +17,7 @@ public class RecipeTypes { public static final Key SMOKING = Key.of("minecraft:smoking"); public static final Key CAMPFIRE_COOKING = Key.of("minecraft:campfire_cooking"); public static final Key STONE_CUTTING = Key.of("minecraft:stone_cutting"); + public static final Key SMITHING_TRANSFORM = Key.of("minecraft:smithing_transform"); static { register(SHAPED, CustomShapedRecipe.FACTORY); diff --git a/gradle.properties b/gradle.properties index fbc8cbd28..4d87c25e8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -38,7 +38,7 @@ geantyref_version=1.3.16 zstd_version=1.5.6-9 commons_io_version=2.17.0 sparrow_nbt_version=0.3 -sparrow_util_version=0.22 +sparrow_util_version=0.23 fastutil_version=8.5.15 netty_version=4.1.119.Final joml_version=1.10.8 From 67cd99be55b67c5a383bb22b54d70f3164f5df52 Mon Sep 17 00:00:00 2001 From: jhqwqmc <2110242767@qq.com> Date: Tue, 18 Mar 2025 16:21:46 +0800 Subject: [PATCH 04/15] =?UTF-8?q?fix(resourcepack):=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E6=A8=A1=E5=9E=8B=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../assets/minecraft/models/item/custom/bench.json | 3 ++- .../assets/minecraft/models/item/custom/table_lamp.json | 3 ++- .../assets/minecraft/models/item/custom/wooden_chair.json | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/bukkit-loader/src/main/resources/resources/default/resourcepack/assets/minecraft/models/item/custom/bench.json b/bukkit-loader/src/main/resources/resources/default/resourcepack/assets/minecraft/models/item/custom/bench.json index 563e589db..21bb4288d 100644 --- a/bukkit-loader/src/main/resources/resources/default/resourcepack/assets/minecraft/models/item/custom/bench.json +++ b/bukkit-loader/src/main/resources/resources/default/resourcepack/assets/minecraft/models/item/custom/bench.json @@ -1,7 +1,8 @@ { "texture_size": [64, 64], "textures": { - "0": "item/custom/bench" + "0": "item/custom/bench", + "particle": "item/custom/bench" }, "elements": [ { diff --git a/bukkit-loader/src/main/resources/resources/default/resourcepack/assets/minecraft/models/item/custom/table_lamp.json b/bukkit-loader/src/main/resources/resources/default/resourcepack/assets/minecraft/models/item/custom/table_lamp.json index bb2e8fdf6..25ad38f50 100644 --- a/bukkit-loader/src/main/resources/resources/default/resourcepack/assets/minecraft/models/item/custom/table_lamp.json +++ b/bukkit-loader/src/main/resources/resources/default/resourcepack/assets/minecraft/models/item/custom/table_lamp.json @@ -1,7 +1,8 @@ { "texture_size": [32, 32], "textures": { - "0": "item/custom/table_lamp" + "0": "item/custom/table_lamp", + "particle": "item/custom/table_lamp" }, "elements": [ { diff --git a/bukkit-loader/src/main/resources/resources/default/resourcepack/assets/minecraft/models/item/custom/wooden_chair.json b/bukkit-loader/src/main/resources/resources/default/resourcepack/assets/minecraft/models/item/custom/wooden_chair.json index ca279830c..f1ee8e866 100644 --- a/bukkit-loader/src/main/resources/resources/default/resourcepack/assets/minecraft/models/item/custom/wooden_chair.json +++ b/bukkit-loader/src/main/resources/resources/default/resourcepack/assets/minecraft/models/item/custom/wooden_chair.json @@ -1,7 +1,8 @@ { "texture_size": [32, 32], "textures": { - "0": "item/custom/wooden_chair" + "0": "item/custom/wooden_chair", + "particle": "item/custom/wooden_chair" }, "elements": [ { From 3ab223654d2134af6c9a98cc2322b12c80896fdd Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Tue, 18 Mar 2025 17:15:40 +0800 Subject: [PATCH 05/15] fix cooking reload on 1.20-1.20.4 --- .../craftengine/bukkit/plugin/injector/BukkitInjector.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BukkitInjector.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BukkitInjector.java index 1dba5c41c..a7614305e 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BukkitInjector.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BukkitInjector.java @@ -85,8 +85,6 @@ public class BukkitInjector { public static void init() { try { - MethodHandles.Lookup lookup = MethodHandles.lookup(); - clazz$InjectedCacheChecker = byteBuddy .subclass(Object.class, ConstructorStrategy.Default.IMITATE_SUPER_CLASS_OPENING) .implement(Reflections.clazz$RecipeManager$CachedCheck) @@ -349,7 +347,7 @@ public class BukkitInjector { boolean isCustom = recipeManager.isCustomRecipe(recipeId); if (!isCustom) { field$InjectedCacheChecker$lastRecipe.set(thisObj, resourceLocation); - return optionalRecipe; + return Optional.of(pair.getSecond()); } Item wrappedItem = BukkitItemManager.instance().wrap(itemStack); From 5fb238f090588c8ef937e8e7502c93ed35ef4fe4 Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Tue, 18 Mar 2025 23:37:34 +0800 Subject: [PATCH 06/15] bump versions --- bukkit-loader/build.gradle.kts | 2 +- bukkit/build.gradle.kts | 2 +- bukkit/legacy/build.gradle.kts | 2 +- .../furniture/BukkitFurnitureManager.java | 4 +- .../bukkit/item/behavior/AxeItemBehavior.java | 2 +- .../item/recipe/BukkitRecipeManager.java | 3 + .../item/recipe/RecipeEventListener.java | 7 +++ core/build.gradle.kts | 2 +- ...Recipe.java => AbstractGroupedRecipe.java} | 5 +- .../core/item/recipe/CustomCookingRecipe.java | 2 +- .../recipe/CustomCraftingTableRecipe.java | 2 +- .../recipe/CustomSmithingTransformRecipe.java | 57 ++++++++++++++++++- .../item/recipe/CustomStoneCuttingRecipe.java | 2 +- .../craftengine/core/item/recipe/Recipe.java | 4 -- gradle.properties | 4 +- gradle/wrapper/gradle-wrapper.properties | 2 +- server-mod/build.gradle.kts | 4 +- settings.gradle.kts | 4 ++ 18 files changed, 86 insertions(+), 24 deletions(-) rename core/src/main/java/net/momirealms/craftengine/core/item/recipe/{AbstractRecipe.java => AbstractGroupedRecipe.java} (82%) diff --git a/bukkit-loader/build.gradle.kts b/bukkit-loader/build.gradle.kts index 987b566ca..eef46cabe 100644 --- a/bukkit-loader/build.gradle.kts +++ b/bukkit-loader/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("com.gradleup.shadow") version "9.0.0-beta6" + id("com.gradleup.shadow") version "9.0.0-beta11" id("net.minecrell.plugin-yml.bukkit") version "0.6.0" } diff --git a/bukkit/build.gradle.kts b/bukkit/build.gradle.kts index 4d23ac5f6..0fab7cd0e 100644 --- a/bukkit/build.gradle.kts +++ b/bukkit/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("com.gradleup.shadow") version "9.0.0-beta6" + id("com.gradleup.shadow") version "9.0.0-beta11" id("maven-publish") } diff --git a/bukkit/legacy/build.gradle.kts b/bukkit/legacy/build.gradle.kts index 40e26ed6f..4d8b59eca 100644 --- a/bukkit/legacy/build.gradle.kts +++ b/bukkit/legacy/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("io.github.goooler.shadow") version "8.1.8" + id("com.gradleup.shadow") version "9.0.0-beta11" } repositories { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurnitureManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurnitureManager.java index 7967d8078..b7cf50a44 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurnitureManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurnitureManager.java @@ -343,9 +343,7 @@ public class BukkitFurnitureManager implements FurnitureManager { return; } Vector3f seatPos = MiscUtils.getVector3f(vector3f); - if (!furniture.releaseSeat(seatPos)) { - plugin.logger().warn("Failed to release seat " + seatPos + " for player " + player.getName()); - } + furniture.releaseSeat(seatPos); } protected boolean isSeatCarrierType(Entity entity) { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/AxeItemBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/AxeItemBehavior.java index 08717093a..be9824b72 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/AxeItemBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/AxeItemBehavior.java @@ -88,7 +88,7 @@ public class AxeItemBehavior extends ItemBehavior { if (!InteractUtils.isInteractable(BlockStateUtils.getBlockOwnerIdFromState(state.vanillaBlockState().handle()), bukkitPlayer, BlockStateUtils.fromBlockData(state.vanillaBlockState().handle()), context.getHitResult(), item - )) { + ) || player.isSecondaryUseActive()) { player.swingHand(context.getHand()); } // shrink item amount diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/BukkitRecipeManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/BukkitRecipeManager.java index bcefff087..463e37e25 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/BukkitRecipeManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/BukkitRecipeManager.java @@ -54,6 +54,9 @@ public class BukkitRecipeManager implements RecipeManager { private static BukkitRecipeManager instance; static { + BUKKIT_RECIPE_FACTORIES.put(RecipeTypes.SMITHING_TRANSFORM, (key, recipe) -> { + + }); BUKKIT_RECIPE_FACTORIES.put(RecipeTypes.SHAPED, (key, recipe) -> { CustomShapedRecipe ceRecipe = (CustomShapedRecipe) recipe; ShapedRecipe shapedRecipe = new ShapedRecipe(key, ceRecipe.result(ItemBuildContext.EMPTY)); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/RecipeEventListener.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/RecipeEventListener.java index 545134541..7a0443a12 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/RecipeEventListener.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/RecipeEventListener.java @@ -832,4 +832,11 @@ public class RecipeEventListener implements Listener { plugin.logger().warn("Failed to correct used recipe", e); } } + + @EventHandler(ignoreCancelled = true) + public void onSmithingTransform(PrepareSmithingEvent event) { + SmithingInventory inventory = event.getInventory(); + if (!(inventory.getRecipe() instanceof SmithingTransformRecipe recipe)) return; + + } } diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 04d5bd3dc..5099cf31c 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("com.gradleup.shadow") version "9.0.0-beta6" + id("com.gradleup.shadow") version "9.0.0-beta11" id("maven-publish") } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/AbstractRecipe.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/AbstractGroupedRecipe.java similarity index 82% rename from core/src/main/java/net/momirealms/craftengine/core/item/recipe/AbstractRecipe.java rename to core/src/main/java/net/momirealms/craftengine/core/item/recipe/AbstractGroupedRecipe.java index 96ecf0394..a1e5e3303 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/AbstractRecipe.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/AbstractGroupedRecipe.java @@ -4,18 +4,17 @@ import net.momirealms.craftengine.core.item.ItemBuildContext; import net.momirealms.craftengine.core.util.Key; import org.jetbrains.annotations.Nullable; -public abstract class AbstractRecipe implements Recipe { +public abstract class AbstractGroupedRecipe implements Recipe { protected final String group; protected final Key id; protected final CustomRecipeResult result; - protected AbstractRecipe(Key id, String group, CustomRecipeResult result) { + protected AbstractGroupedRecipe(Key id, String group, CustomRecipeResult result) { this.group = group; this.id = id; this.result = result; } - @Override @Nullable public String group() { return group; diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomCookingRecipe.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomCookingRecipe.java index 971e51a34..423470eb1 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomCookingRecipe.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomCookingRecipe.java @@ -6,7 +6,7 @@ import net.momirealms.craftengine.core.util.Key; import java.util.List; -public abstract class CustomCookingRecipe extends AbstractRecipe { +public abstract class CustomCookingRecipe extends AbstractGroupedRecipe { protected final CookingRecipeCategory category; protected final Ingredient ingredient; protected final float experience; diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomCraftingTableRecipe.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomCraftingTableRecipe.java index aaa19bc49..866a2db07 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomCraftingTableRecipe.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomCraftingTableRecipe.java @@ -2,7 +2,7 @@ package net.momirealms.craftengine.core.item.recipe; import net.momirealms.craftengine.core.util.Key; -public abstract class CustomCraftingTableRecipe extends AbstractRecipe { +public abstract class CustomCraftingTableRecipe extends AbstractGroupedRecipe { protected final CraftingRecipeCategory category; protected CustomCraftingTableRecipe(Key id, CraftingRecipeCategory category, String group, CustomRecipeResult result) { 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 fb74a8767..e3eedc4bb 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 @@ -1,4 +1,59 @@ package net.momirealms.craftengine.core.item.recipe; -public class CustomSmithingTransformRecipe { +import net.momirealms.craftengine.core.item.ItemBuildContext; +import net.momirealms.craftengine.core.item.recipe.input.RecipeInput; +import net.momirealms.craftengine.core.util.Key; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public class CustomSmithingTransformRecipe implements Recipe { + private final Key id; + private final CustomRecipeResult result; + private final Ingredient template; + private final Ingredient base; + private final Ingredient addition; + + public CustomSmithingTransformRecipe(Key id, + CustomRecipeResult result, + Ingredient template, + Ingredient base, + Ingredient addition + ) { + this.id = id; + this.result = result; + this.template = template; + this.base = base; + this.addition = addition; + } + + @Override + public boolean matches(RecipeInput input) { + return false; + } + + @Override + public List> ingredientsInUse() { + return List.of(); + } + + @Override + public @NotNull Key type() { + return RecipeTypes.SMITHING_TRANSFORM; + } + + @Override + public Key id() { + return id; + } + + @Override + public T result(ItemBuildContext context) { + return result.buildItemStack(context); + } + + @Override + public CustomRecipeResult result() { + return this.result; + } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomStoneCuttingRecipe.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomStoneCuttingRecipe.java index 1c14ee66e..9d95bfe89 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomStoneCuttingRecipe.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomStoneCuttingRecipe.java @@ -14,7 +14,7 @@ import java.util.List; import java.util.Map; import java.util.Set; -public class CustomStoneCuttingRecipe extends AbstractRecipe { +public class CustomStoneCuttingRecipe extends AbstractGroupedRecipe { public static final Factory FACTORY = new Factory<>(); protected final Ingredient ingredient; diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/Recipe.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/Recipe.java index 1e99f00ca..befd2940a 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/Recipe.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/Recipe.java @@ -4,7 +4,6 @@ import net.momirealms.craftengine.core.item.ItemBuildContext; import net.momirealms.craftengine.core.item.recipe.input.RecipeInput; import net.momirealms.craftengine.core.util.Key; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.util.List; @@ -22,7 +21,4 @@ public interface Recipe { Key type(); Key id(); - - @Nullable - String group(); } diff --git a/gradle.properties b/gradle.properties index 4d87c25e8..3bbacafe3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ # Project settings # Rule: [major update].[feature update].[bug fix] -project_version=0.0.34 +project_version=0.0.35 config_version=14 lang_version=3 project_group=net.momirealms @@ -38,7 +38,7 @@ geantyref_version=1.3.16 zstd_version=1.5.6-9 commons_io_version=2.17.0 sparrow_nbt_version=0.3 -sparrow_util_version=0.23 +sparrow_util_version=0.27 fastutil_version=8.5.15 netty_version=4.1.119.Final joml_version=1.10.8 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 18362b78b..c6f003026 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/server-mod/build.gradle.kts b/server-mod/build.gradle.kts index 8f3a35e5e..e2ca5fbe4 100644 --- a/server-mod/build.gradle.kts +++ b/server-mod/build.gradle.kts @@ -1,7 +1,7 @@ plugins { id("java-library") - id("com.gradleup.shadow") version "9.0.0-beta6" - id("io.papermc.paperweight.userdev") version "2.0.0-beta.14" + id("com.gradleup.shadow") version "9.0.0-beta11" + id("io.papermc.paperweight.userdev") version "2.0.0-beta.16" } repositories { diff --git a/settings.gradle.kts b/settings.gradle.kts index 26b036286..02db6f8bf 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -9,5 +9,9 @@ pluginManagement { plugins { kotlin("jvm") version "2.0.20" } + repositories { + gradlePluginPortal() + maven("https://repo.papermc.io/repository/maven-public/") + } } From 4653adc43c78be0fdbad5a04d1ae0c7e89dcfddc Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Wed, 19 Mar 2025 03:29:08 +0800 Subject: [PATCH 07/15] refactor recipes --- .../item/recipe/BukkitRecipeManager.java | 131 ++++++++++++++---- .../bukkit/item/recipe/EmptyRecipeChoice.java | 35 +++++ .../item/recipe/RecipeEventListener.java | 8 ++ .../craftengine/bukkit/util/Reflections.java | 12 ++ .../item/recipe/CustomBlastingRecipe.java | 4 +- .../item/recipe/CustomCampfireRecipe.java | 4 +- .../item/recipe/CustomSmeltingRecipe.java | 4 +- .../recipe/CustomSmithingTransformRecipe.java | 90 ++++++++++-- .../core/item/recipe/CustomSmokingRecipe.java | 4 +- .../core/item/recipe/RecipeTypes.java | 2 + .../core/item/recipe/input/SmithingInput.java | 33 +++++ .../recipe/vanilla/VanillaBlastingRecipe.java | 7 + .../recipe/vanilla/VanillaCampfireRecipe.java | 7 + .../recipe/vanilla/VanillaCookingRecipe.java | 2 +- .../recipe/vanilla/VanillaCraftingRecipe.java | 2 +- .../recipe/vanilla/VanillaGroupedRecipe.java | 20 +++ .../item/recipe/vanilla/VanillaRecipe.java | 17 +-- .../recipe/vanilla/VanillaRecipeReader.java | 2 + .../recipe/vanilla/VanillaShapedRecipe.java | 7 + .../vanilla/VanillaShapelessRecipe.java | 7 + .../recipe/vanilla/VanillaSmeltingRecipe.java | 7 + .../VanillaSmithingTransformRecipe.java | 42 ++++++ .../recipe/vanilla/VanillaSmokingRecipe.java | 7 + .../vanilla/VanillaStoneCuttingRecipe.java | 10 +- .../reader/VanillaRecipeReader1_20.java | 16 +++ .../reader/VanillaRecipeReader1_20_5.java | 5 + 26 files changed, 424 insertions(+), 61 deletions(-) create mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/EmptyRecipeChoice.java create mode 100644 core/src/main/java/net/momirealms/craftengine/core/item/recipe/input/SmithingInput.java create mode 100644 core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaGroupedRecipe.java create mode 100644 core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaSmithingTransformRecipe.java diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/BukkitRecipeManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/BukkitRecipeManager.java index 463e37e25..b4eb96104 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/BukkitRecipeManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/BukkitRecipeManager.java @@ -55,7 +55,20 @@ public class BukkitRecipeManager implements RecipeManager { static { BUKKIT_RECIPE_FACTORIES.put(RecipeTypes.SMITHING_TRANSFORM, (key, recipe) -> { - + CustomSmithingTransformRecipe ceRecipe = (CustomSmithingTransformRecipe) recipe; + SmithingTransformRecipe transformRecipe = new SmithingTransformRecipe( + key, ceRecipe.result(ItemBuildContext.EMPTY), + ingredientToBukkitRecipeChoice(ceRecipe.template()), + ingredientToBukkitRecipeChoice(ceRecipe.base()), + ingredientToBukkitRecipeChoice(ceRecipe.addition()), + false + ); + try { + Object craftRecipe = Reflections.method$CraftSmithingTransformRecipe$fromBukkitRecipe.invoke(null, transformRecipe); + Reflections.method$CraftRecipe$addToCraftingManager.invoke(craftRecipe); + } catch (Exception e) { + CraftEngine.instance().logger().warn("Failed to convert smithing transform recipe", e); + } }); BUKKIT_RECIPE_FACTORIES.put(RecipeTypes.SHAPED, (key, recipe) -> { CustomShapedRecipe ceRecipe = (CustomShapedRecipe) recipe; @@ -68,7 +81,7 @@ public class BukkitRecipeManager implements RecipeManager { } shapedRecipe.shape(ceRecipe.pattern().pattern()); for (Map.Entry> entry : ceRecipe.pattern().ingredients().entrySet()) { - shapedRecipe.setIngredient(entry.getKey(), new RecipeChoice.MaterialChoice(ingredientToBukkitMaterials(entry.getValue()))); + shapedRecipe.setIngredient(entry.getKey(), ingredientToBukkitRecipeChoice(entry.getValue())); } try { Object craftRecipe = Reflections.method$CraftShapedRecipe$fromBukkitRecipe.invoke(null, shapedRecipe); @@ -88,7 +101,7 @@ public class BukkitRecipeManager implements RecipeManager { shapelessRecipe.setCategory(CraftingBookCategory.valueOf(Objects.requireNonNull(ceRecipe.category()).name())); } for (Ingredient ingredient : ceRecipe.ingredientsInUse()) { - shapelessRecipe.addIngredient(new RecipeChoice.MaterialChoice(ingredientToBukkitMaterials(ingredient))); + shapelessRecipe.addIngredient(ingredientToBukkitRecipeChoice(ingredient)); } try { Object craftRecipe = Reflections.method$CraftShapelessRecipe$fromBukkitRecipe.invoke(null, shapelessRecipe); @@ -102,7 +115,7 @@ public class BukkitRecipeManager implements RecipeManager { CustomSmeltingRecipe ceRecipe = (CustomSmeltingRecipe) recipe; FurnaceRecipe furnaceRecipe = new FurnaceRecipe( key, ceRecipe.result(ItemBuildContext.EMPTY), - new RecipeChoice.MaterialChoice(ingredientToBukkitMaterials(ceRecipe.ingredient())), + ingredientToBukkitRecipeChoice(ceRecipe.ingredient()), ceRecipe.experience(), ceRecipe.cookingTime() ); if (ceRecipe.group() != null) { @@ -123,7 +136,7 @@ public class BukkitRecipeManager implements RecipeManager { CustomSmokingRecipe ceRecipe = (CustomSmokingRecipe) recipe; SmokingRecipe smokingRecipe = new SmokingRecipe( key, ceRecipe.result(ItemBuildContext.EMPTY), - new RecipeChoice.MaterialChoice(ingredientToBukkitMaterials(ceRecipe.ingredient())), + ingredientToBukkitRecipeChoice(ceRecipe.ingredient()), ceRecipe.experience(), ceRecipe.cookingTime() ); if (ceRecipe.group() != null) { @@ -144,7 +157,7 @@ public class BukkitRecipeManager implements RecipeManager { CustomBlastingRecipe ceRecipe = (CustomBlastingRecipe) recipe; BlastingRecipe blastingRecipe = new BlastingRecipe( key, ceRecipe.result(ItemBuildContext.EMPTY), - new RecipeChoice.MaterialChoice(ingredientToBukkitMaterials(ceRecipe.ingredient())), + ingredientToBukkitRecipeChoice(ceRecipe.ingredient()), ceRecipe.experience(), ceRecipe.cookingTime() ); if (ceRecipe.group() != null) { @@ -165,7 +178,7 @@ public class BukkitRecipeManager implements RecipeManager { CustomCampfireRecipe ceRecipe = (CustomCampfireRecipe) recipe; CampfireRecipe campfireRecipe = new CampfireRecipe( key, ceRecipe.result(ItemBuildContext.EMPTY), - new RecipeChoice.MaterialChoice(ingredientToBukkitMaterials(ceRecipe.ingredient())), + ingredientToBukkitRecipeChoice(ceRecipe.ingredient()), ceRecipe.experience(), ceRecipe.cookingTime() ); if (ceRecipe.group() != null) { @@ -495,6 +508,10 @@ public class BukkitRecipeManager implements RecipeManager { VanillaStoneCuttingRecipe recipe = this.recipeReader.readStoneCutting(jsonObject); handleDataPackStoneCuttingRecipe(id, recipe); } + case "minecraft:smithing_transform" -> { + VanillaSmithingTransformRecipe recipe = this.recipeReader.readSmithingTransform(jsonObject); + handleDataPackSmithingTransform(id, recipe, (injectLogics::add)); + } } } } @@ -520,6 +537,29 @@ public class BukkitRecipeManager implements RecipeManager { return future; } + private boolean readVanillaIngredients(boolean hasCustomItemInTag, List ingredients, Consumer materialConsumer, Consumer> holderConsumer) { + for (String item : ingredients) { + if (item.charAt(0) == '#') { + Key tag = Key.from(item.substring(1)); + for (Material material : tagToMaterials(tag)) { + materialConsumer.accept(material); + } + if (!hasCustomItemInTag) { + if (!plugin.itemManager().tagToCustomItems(tag).isEmpty()) { + hasCustomItemInTag = true; + } + } + for (Holder holder : plugin.itemManager().tagToItems(tag)) { + holderConsumer.accept(holder); + } + } else { + materialConsumer.accept(MaterialUtils.getMaterial(item)); + holderConsumer.accept(BuiltInRegistries.OPTIMIZED_ITEM_ID.get(Key.from(item)).orElseThrow()); + } + } + return hasCustomItemInTag; + } + private void handleDataPackShapelessRecipe(Key id, VanillaShapelessRecipe recipe, Consumer callback) { NamespacedKey key = new NamespacedKey(id.namespace(), id.value()); ItemStack result = createResultStack(recipe.result()); @@ -669,22 +709,7 @@ public class BukkitRecipeManager implements RecipeManager { Set materials = new HashSet<>(); Set> holders = new HashSet<>(); - boolean hasCustomItemInTag = false; - for (String item : recipe.ingredient()) { - if (item.charAt(0) == '#') { - Key tag = Key.from(item.substring(1)); - materials.addAll(tagToMaterials(tag)); - if (!hasCustomItemInTag) { - if (!plugin.itemManager().tagToCustomItems(tag).isEmpty()) { - hasCustomItemInTag = true; - } - } - holders.addAll(plugin.itemManager().tagToItems(tag)); - } else { - materials.add(MaterialUtils.getMaterial(item)); - holders.add(BuiltInRegistries.OPTIMIZED_ITEM_ID.get(Key.from(item)).orElseThrow()); - } - } + boolean hasCustomItemInTag = readVanillaIngredients(false, recipe.ingredient(), materials::add, holders::add); org.bukkit.inventory.CookingRecipe cookingRecipe = constructor1.apply(key, result, new RecipeChoice.MaterialChoice(new ArrayList<>(materials)), recipe.experience(), recipe.cookingTime()); if (recipe.group() != null) { cookingRecipe.setGroup(recipe.group()); @@ -717,6 +742,52 @@ public class BukkitRecipeManager implements RecipeManager { this.addInternalRecipe(id, ceRecipe); } + private void handleDataPackSmithingTransform(Key id, VanillaSmithingTransformRecipe recipe, Consumer callback) { + NamespacedKey key = new NamespacedKey(id.namespace(), id.value()); + ItemStack result = createResultStack(recipe.result()); + boolean hasCustomItemInTag; + + Set additionMaterials = new HashSet<>(); + Set> additionHolders = new HashSet<>(); + hasCustomItemInTag = readVanillaIngredients(false, recipe.addition(), additionMaterials::add, additionHolders::add); + + Set templateMaterials = new HashSet<>(); + Set> templateHolders = new HashSet<>(); + hasCustomItemInTag = readVanillaIngredients(hasCustomItemInTag, recipe.template(), templateMaterials::add, templateHolders::add); + + Set baseMaterials = new HashSet<>(); + Set> baseHolders = new HashSet<>(); + hasCustomItemInTag = readVanillaIngredients(hasCustomItemInTag, recipe.base(), baseMaterials::add, baseHolders::add); + + CustomSmithingTransformRecipe ceRecipe = new CustomSmithingTransformRecipe<>( + id, + Ingredient.of(baseHolders), + Ingredient.of(templateHolders), + Ingredient.of(additionHolders), + new CustomRecipeResult<>(new CloneableConstantItem(recipe.result().isCustom() ? Key.of("!internal:custom") : Key.of(recipe.result().id()), result), recipe.result().count()) + ); + + SmithingTransformRecipe transformRecipe = new SmithingTransformRecipe(key, result, + new RecipeChoice.MaterialChoice(new ArrayList<>(templateMaterials)), + new RecipeChoice.MaterialChoice(new ArrayList<>(baseMaterials)), + new RecipeChoice.MaterialChoice(new ArrayList<>(additionMaterials)), + true + ); + + if (hasCustomItemInTag) { + callback.accept(() -> { + try { + unregisterRecipe(key); + Reflections.method$CraftRecipe$addToCraftingManager.invoke(Reflections.method$CraftSmithingTransformRecipe$fromBukkitRecipe.invoke(null, transformRecipe)); + } catch (Exception e) { + CraftEngine.instance().logger().warn("Failed to convert smelting recipe", e); + } + }); + this.injectedDataPackRecipes.add(key); + } + this.addInternalRecipe(id, ceRecipe); + } + private List tagToMaterials(Key tag) { Set materials = new HashSet<>(); List> holders = this.plugin.itemManager().tagToVanillaItems(tag); @@ -766,12 +837,16 @@ public class BukkitRecipeManager implements RecipeManager { return Key.of(prefix, fileName); } - private static List ingredientToBukkitMaterials(Ingredient ingredient) { - Set materials = new HashSet<>(); - for (Holder holder : ingredient.items()) { - materials.add(getMaterialById(holder.value())); + private static RecipeChoice ingredientToBukkitRecipeChoice(Ingredient ingredient) { + if (ingredient == null) { + return EmptyRecipeChoice.INSTANCE; + } else { + Set materials = new HashSet<>(); + for (Holder holder : ingredient.items()) { + materials.add(getMaterialById(holder.value())); + } + return new RecipeChoice.MaterialChoice(new ArrayList<>(materials)); } - return new ArrayList<>(materials); } private static Material getMaterialById(Key key) { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/EmptyRecipeChoice.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/EmptyRecipeChoice.java new file mode 100644 index 000000000..382b2c0de --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/EmptyRecipeChoice.java @@ -0,0 +1,35 @@ +package net.momirealms.craftengine.bukkit.item.recipe; + +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.RecipeChoice; +import org.jetbrains.annotations.NotNull; + +record EmptyRecipeChoice() implements RecipeChoice { + + static final RecipeChoice INSTANCE = new EmptyRecipeChoice(); + + @Override + @NotNull + public ItemStack getItemStack() { + throw new UnsupportedOperationException("This is an empty RecipeChoice"); + } + + @SuppressWarnings("MethodDoesntCallSuperMethod") + @Override + @NotNull + public RecipeChoice clone() { + return this; + } + + @Override + public boolean test(final @NotNull ItemStack itemStack) { + return false; + } + + @Override + @NotNull + public RecipeChoice validate(final boolean allowEmptyRecipes) { + if (allowEmptyRecipes) return this; + throw new IllegalArgumentException("empty RecipeChoice isn't allowed here"); + } +} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/RecipeEventListener.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/RecipeEventListener.java index 7a0443a12..bbf3ed9dd 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/RecipeEventListener.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/RecipeEventListener.java @@ -838,5 +838,13 @@ public class RecipeEventListener implements Listener { SmithingInventory inventory = event.getInventory(); if (!(inventory.getRecipe() instanceof SmithingTransformRecipe recipe)) return; + Key recipeId = Key.of(recipe.getKey().namespace(), recipe.getKey().value()); + boolean isCustom = this.recipeManager.isCustomRecipe(recipeId); + // Maybe it's recipe from other plugins, then we ignore it + if (!isCustom) { + return; + } + + } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java index 7e267118f..3e6506c61 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java @@ -4125,6 +4125,18 @@ public class Reflections { ) ); + public static final Class clazz$CraftSmithingTransformRecipe = requireNonNull( + ReflectionUtils.getClazz( + BukkitReflectionUtils.assembleCBClass("inventory.CraftSmithingTransformRecipe") + ) + ); + + public static final Method method$CraftSmithingTransformRecipe$fromBukkitRecipe = requireNonNull( + ReflectionUtils.getStaticMethod( + clazz$CraftSmithingTransformRecipe, clazz$CraftSmithingTransformRecipe, SmithingTransformRecipe.class + ) + ); + public static final Class clazz$FeatureFlagSet = requireNonNull( ReflectionUtils.getClazz( BukkitReflectionUtils.assembleMCClass("world.flag.FeatureFlagSet") diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomBlastingRecipe.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomBlastingRecipe.java index 673212f9a..8d80181ec 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomBlastingRecipe.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomBlastingRecipe.java @@ -21,11 +21,11 @@ public class CustomBlastingRecipe extends CustomCookingRecipe { return RecipeTypes.BLASTING; } - public static class Factory implements RecipeFactory> { + public static class Factory implements RecipeFactory { @SuppressWarnings({"unchecked", "rawtypes", "DuplicatedCode"}) @Override - public Recipe> create(Key id, Map arguments) { + public Recipe create(Key id, Map arguments) { CookingRecipeCategory recipeCategory = arguments.containsKey("category") ? CookingRecipeCategory.valueOf(arguments.get("category").toString().toUpperCase(Locale.ENGLISH)) : null; String group = arguments.containsKey("group") ? arguments.get("group").toString() : null; int cookingTime = MiscUtils.getAsInt(arguments.getOrDefault("time", 80)); diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomCampfireRecipe.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomCampfireRecipe.java index 7045774fb..fd3220981 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomCampfireRecipe.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomCampfireRecipe.java @@ -21,11 +21,11 @@ public class CustomCampfireRecipe extends CustomCookingRecipe { return RecipeTypes.CAMPFIRE_COOKING; } - public static class Factory implements RecipeFactory> { + public static class Factory implements RecipeFactory { @SuppressWarnings({"unchecked", "rawtypes", "DuplicatedCode"}) @Override - public Recipe> create(Key id, Map arguments) { + public Recipe create(Key id, Map arguments) { CookingRecipeCategory recipeCategory = arguments.containsKey("category") ? CookingRecipeCategory.valueOf(arguments.get("category").toString().toUpperCase(Locale.ENGLISH)) : null; String group = arguments.containsKey("group") ? arguments.get("group").toString() : null; int cookingTime = MiscUtils.getAsInt(arguments.getOrDefault("time", 80)); diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomSmeltingRecipe.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomSmeltingRecipe.java index dbc3c5039..7f4fed503 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomSmeltingRecipe.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomSmeltingRecipe.java @@ -21,11 +21,11 @@ public class CustomSmeltingRecipe extends CustomCookingRecipe { return RecipeTypes.SMELTING; } - public static class Factory implements RecipeFactory> { + public static class Factory implements RecipeFactory { @SuppressWarnings({"unchecked", "rawtypes", "DuplicatedCode"}) @Override - public Recipe> create(Key id, Map arguments) { + public Recipe create(Key id, Map arguments) { CookingRecipeCategory recipeCategory = arguments.containsKey("category") ? CookingRecipeCategory.valueOf(arguments.get("category").toString().toUpperCase(Locale.ENGLISH)) : null; String group = arguments.containsKey("group") ? arguments.get("group").toString() : null; int cookingTime = MiscUtils.getAsInt(arguments.getOrDefault("time", 80)); 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 e3eedc4bb..9f878670d 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 @@ -2,39 +2,69 @@ package net.momirealms.craftengine.core.item.recipe; import net.momirealms.craftengine.core.item.ItemBuildContext; import net.momirealms.craftengine.core.item.recipe.input.RecipeInput; +import net.momirealms.craftengine.core.item.recipe.input.SmithingInput; +import net.momirealms.craftengine.core.plugin.CraftEngine; +import net.momirealms.craftengine.core.registry.BuiltInRegistries; +import net.momirealms.craftengine.core.registry.Holder; import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.MiscUtils; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; -import java.util.List; +import java.util.*; public class CustomSmithingTransformRecipe implements Recipe { + public static final Factory FACTORY = new Factory<>(); private final Key id; private final CustomRecipeResult result; - private final Ingredient template; private final Ingredient base; + private final Ingredient template; private final Ingredient addition; public CustomSmithingTransformRecipe(Key id, - CustomRecipeResult result, - Ingredient template, - Ingredient base, - Ingredient addition + @Nullable Ingredient addition, + @Nullable Ingredient base, + @Nullable Ingredient template, + CustomRecipeResult result ) { this.id = id; this.result = result; - this.template = template; this.base = base; + this.template = template; this.addition = addition; } + @SuppressWarnings("unchecked") @Override public boolean matches(RecipeInput input) { - return false; + SmithingInput smithingInput = (SmithingInput) input; + return checkIngredient(this.base, smithingInput.base()) + && checkIngredient(this.template, smithingInput.template()) + && checkIngredient(this.addition, smithingInput.addition()); + } + + private boolean checkIngredient(Ingredient ingredient, OptimizedIDItem item) { + if (ingredient != null) { + if (item == null) { + return false; + } + return ingredient.test(item); + } else { + return item == null; + } } @Override public List> ingredientsInUse() { - return List.of(); + List> ingredients = new ArrayList<>(); + ingredients.add(this.base); + if (this.template != null) { + ingredients.add(this.template); + } + if (this.addition != null) { + ingredients.add(this.addition); + } + return ingredients; } @Override @@ -56,4 +86,46 @@ public class CustomSmithingTransformRecipe implements Recipe { public CustomRecipeResult result() { return this.result; } + + @Nullable + public Ingredient base() { + return base; + } + + @Nullable + public Ingredient template() { + return template; + } + + @Nullable + public Ingredient addition() { + return addition; + } + + @SuppressWarnings({"DuplicatedCode"}) + public static class Factory implements RecipeFactory { + + @Override + public Recipe create(Key id, Map arguments) { + List base = MiscUtils.getAsStringList(arguments.get("base")); + List addition = MiscUtils.getAsStringList(arguments.get("addition")); + List template = MiscUtils.getAsStringList(arguments.get("template")); + return new CustomSmithingTransformRecipe<>( + id, + toIngredient(addition), toIngredient(base), toIngredient(template), parseResult(arguments) + ); + } + + private Ingredient toIngredient(List items) { + Set> holders = new HashSet<>(); + for (String item : items) { + if (item.charAt(0) == '#') { + holders.addAll(CraftEngine.instance().itemManager().tagToItems(Key.of(item.substring(1)))); + } else { + holders.add(BuiltInRegistries.OPTIMIZED_ITEM_ID.get(Key.of(item)).orElseThrow(() -> new IllegalArgumentException("Invalid vanilla/custom item: " + item))); + } + } + return Ingredient.of(holders); + } + } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomSmokingRecipe.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomSmokingRecipe.java index bb243c90d..2976836e0 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomSmokingRecipe.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomSmokingRecipe.java @@ -21,11 +21,11 @@ public class CustomSmokingRecipe extends CustomCookingRecipe { return RecipeTypes.SMOKING; } - public static class Factory implements RecipeFactory> { + public static class Factory implements RecipeFactory { @SuppressWarnings({"unchecked", "rawtypes", "DuplicatedCode"}) @Override - public Recipe> create(Key id, Map arguments) { + public Recipe create(Key id, Map arguments) { CookingRecipeCategory recipeCategory = arguments.containsKey("category") ? CookingRecipeCategory.valueOf(arguments.get("category").toString().toUpperCase(Locale.ENGLISH)) : null; String group = arguments.containsKey("group") ? arguments.get("group").toString() : null; int cookingTime = MiscUtils.getAsInt(arguments.getOrDefault("time", 80)); diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/RecipeTypes.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/RecipeTypes.java index fb81f5678..523470030 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/RecipeTypes.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/RecipeTypes.java @@ -18,6 +18,7 @@ public class RecipeTypes { public static final Key CAMPFIRE_COOKING = Key.of("minecraft:campfire_cooking"); public static final Key STONE_CUTTING = Key.of("minecraft:stone_cutting"); public static final Key SMITHING_TRANSFORM = Key.of("minecraft:smithing_transform"); + public static final Key SMITHING_TRIM = Key.of("minecraft:smithing_trim"); static { register(SHAPED, CustomShapedRecipe.FACTORY); @@ -27,6 +28,7 @@ public class RecipeTypes { register(BLASTING, CustomBlastingRecipe.FACTORY); register(CAMPFIRE_COOKING, CustomCampfireRecipe.FACTORY); register(STONE_CUTTING, CustomStoneCuttingRecipe.FACTORY); + register(SMITHING_TRANSFORM, CustomSmithingTransformRecipe.FACTORY); } public static void register(Key key, RecipeFactory factory) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/input/SmithingInput.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/input/SmithingInput.java new file mode 100644 index 000000000..29764fcb5 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/input/SmithingInput.java @@ -0,0 +1,33 @@ +package net.momirealms.craftengine.core.item.recipe.input; + +import net.momirealms.craftengine.core.item.recipe.OptimizedIDItem; +import org.jetbrains.annotations.Nullable; + +public class SmithingInput implements RecipeInput { + private final OptimizedIDItem base; + private final OptimizedIDItem template; + private final OptimizedIDItem addition; + + public SmithingInput(@Nullable OptimizedIDItem base, + @Nullable OptimizedIDItem template, + @Nullable OptimizedIDItem addition) { + this.base = base; + this.template = template; + this.addition = addition; + } + + @Nullable + public OptimizedIDItem base() { + return base; + } + + @Nullable + public OptimizedIDItem template() { + return template; + } + + @Nullable + public OptimizedIDItem addition() { + return addition; + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaBlastingRecipe.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaBlastingRecipe.java index 9e6775d69..a78b6bb0c 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaBlastingRecipe.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaBlastingRecipe.java @@ -1,6 +1,8 @@ package net.momirealms.craftengine.core.item.recipe.vanilla; import net.momirealms.craftengine.core.item.recipe.CookingRecipeCategory; +import net.momirealms.craftengine.core.item.recipe.RecipeTypes; +import net.momirealms.craftengine.core.util.Key; import java.util.List; @@ -9,4 +11,9 @@ public class VanillaBlastingRecipe extends VanillaCookingRecipe { public VanillaBlastingRecipe(CookingRecipeCategory category, String group, RecipeResult result, List ingredient, float experience, int cookingTime) { super(category, group, result, ingredient, experience, cookingTime); } + + @Override + public Key type() { + return RecipeTypes.BLASTING; + } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaCampfireRecipe.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaCampfireRecipe.java index b2d8cae30..aa12d79db 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaCampfireRecipe.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaCampfireRecipe.java @@ -1,6 +1,8 @@ package net.momirealms.craftengine.core.item.recipe.vanilla; import net.momirealms.craftengine.core.item.recipe.CookingRecipeCategory; +import net.momirealms.craftengine.core.item.recipe.RecipeTypes; +import net.momirealms.craftengine.core.util.Key; import java.util.List; @@ -9,4 +11,9 @@ public class VanillaCampfireRecipe extends VanillaCookingRecipe { public VanillaCampfireRecipe(CookingRecipeCategory category, String group, RecipeResult result, List ingredient, float experience, int cookingTime) { super(category, group, result, ingredient, experience, cookingTime); } + + @Override + public Key type() { + return RecipeTypes.CAMPFIRE_COOKING; + } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaCookingRecipe.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaCookingRecipe.java index 594d372ac..93d91f943 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaCookingRecipe.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaCookingRecipe.java @@ -4,7 +4,7 @@ import net.momirealms.craftengine.core.item.recipe.CookingRecipeCategory; import java.util.List; -public abstract class VanillaCookingRecipe extends VanillaRecipe { +public abstract class VanillaCookingRecipe extends VanillaGroupedRecipe { protected final List ingredient; protected final CookingRecipeCategory category; protected final float experience; diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaCraftingRecipe.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaCraftingRecipe.java index 2ba1d3c09..d8cd3bdb5 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaCraftingRecipe.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaCraftingRecipe.java @@ -2,7 +2,7 @@ package net.momirealms.craftengine.core.item.recipe.vanilla; import net.momirealms.craftengine.core.item.recipe.CraftingRecipeCategory; -public class VanillaCraftingRecipe extends VanillaRecipe { +public abstract class VanillaCraftingRecipe extends VanillaGroupedRecipe { protected final CraftingRecipeCategory category; protected VanillaCraftingRecipe(CraftingRecipeCategory category, String group, RecipeResult result) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaGroupedRecipe.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaGroupedRecipe.java new file mode 100644 index 000000000..813a35e34 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaGroupedRecipe.java @@ -0,0 +1,20 @@ +package net.momirealms.craftengine.core.item.recipe.vanilla; + +public abstract class VanillaGroupedRecipe implements VanillaRecipe { + protected final String group; + protected final RecipeResult result; + + protected VanillaGroupedRecipe(String group, RecipeResult result) { + this.group = group; + this.result = result; + } + + public String group() { + return group; + } + + @Override + public RecipeResult result() { + return result; + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaRecipe.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaRecipe.java index 000077538..d020f5a69 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaRecipe.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaRecipe.java @@ -1,19 +1,10 @@ package net.momirealms.craftengine.core.item.recipe.vanilla; -public abstract class VanillaRecipe { - protected final String group; - protected final RecipeResult result; +import net.momirealms.craftengine.core.util.Key; - protected VanillaRecipe(String group, RecipeResult result) { - this.group = group; - this.result = result; - } +public interface VanillaRecipe { - public String group() { - return group; - } + Key type(); - public RecipeResult result() { - return result; - } + RecipeResult result(); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaRecipeReader.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaRecipeReader.java index 2f534efb1..f75e42eea 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaRecipeReader.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaRecipeReader.java @@ -17,4 +17,6 @@ public interface VanillaRecipeReader { VanillaCampfireRecipe readCampfire(JsonObject json); VanillaStoneCuttingRecipe readStoneCutting(JsonObject json); + + VanillaSmithingTransformRecipe readSmithingTransform(JsonObject json); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaShapedRecipe.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaShapedRecipe.java index 3b8f5d127..753590f5c 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaShapedRecipe.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaShapedRecipe.java @@ -1,6 +1,8 @@ package net.momirealms.craftengine.core.item.recipe.vanilla; import net.momirealms.craftengine.core.item.recipe.CraftingRecipeCategory; +import net.momirealms.craftengine.core.item.recipe.RecipeTypes; +import net.momirealms.craftengine.core.util.Key; import java.util.List; import java.util.Map; @@ -26,4 +28,9 @@ public class VanillaShapedRecipe extends VanillaCraftingRecipe { public String[] pattern() { return pattern; } + + @Override + public Key type() { + return RecipeTypes.SHAPED; + } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaShapelessRecipe.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaShapelessRecipe.java index 613a2f7e8..2e06b2988 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaShapelessRecipe.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaShapelessRecipe.java @@ -1,6 +1,8 @@ package net.momirealms.craftengine.core.item.recipe.vanilla; import net.momirealms.craftengine.core.item.recipe.CraftingRecipeCategory; +import net.momirealms.craftengine.core.item.recipe.RecipeTypes; +import net.momirealms.craftengine.core.util.Key; import java.util.List; @@ -15,4 +17,9 @@ public class VanillaShapelessRecipe extends VanillaCraftingRecipe { public List> ingredients() { return ingredients; } + + @Override + public Key type() { + return RecipeTypes.SHAPELESS; + } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaSmeltingRecipe.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaSmeltingRecipe.java index 5aa346c26..ebbed4b21 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaSmeltingRecipe.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaSmeltingRecipe.java @@ -1,6 +1,8 @@ package net.momirealms.craftengine.core.item.recipe.vanilla; import net.momirealms.craftengine.core.item.recipe.CookingRecipeCategory; +import net.momirealms.craftengine.core.item.recipe.RecipeTypes; +import net.momirealms.craftengine.core.util.Key; import java.util.List; @@ -9,4 +11,9 @@ public class VanillaSmeltingRecipe extends VanillaCookingRecipe { public VanillaSmeltingRecipe(CookingRecipeCategory category, String group, RecipeResult result, List ingredient, float experience, int cookingTime) { super(category, group, result, ingredient, experience, cookingTime); } + + @Override + public Key type() { + return RecipeTypes.SMELTING; + } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaSmithingTransformRecipe.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaSmithingTransformRecipe.java new file mode 100644 index 000000000..5e4713622 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaSmithingTransformRecipe.java @@ -0,0 +1,42 @@ +package net.momirealms.craftengine.core.item.recipe.vanilla; + +import net.momirealms.craftengine.core.item.recipe.RecipeTypes; +import net.momirealms.craftengine.core.util.Key; + +import java.util.List; + +public class VanillaSmithingTransformRecipe implements VanillaRecipe { + private final RecipeResult result; + private final List base; + private final List template; + private final List addition; + + public VanillaSmithingTransformRecipe(List addition, List base, List template, RecipeResult result) { + this.result = result; + this.base = base; + this.template = template; + this.addition = addition; + } + + @Override + public Key type() { + return RecipeTypes.SMITHING_TRANSFORM; + } + + @Override + public RecipeResult result() { + return result; + } + + public List base() { + return base; + } + + public List template() { + return template; + } + + public List addition() { + return addition; + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaSmokingRecipe.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaSmokingRecipe.java index df919f810..736a3fd5e 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaSmokingRecipe.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaSmokingRecipe.java @@ -1,6 +1,8 @@ package net.momirealms.craftengine.core.item.recipe.vanilla; import net.momirealms.craftengine.core.item.recipe.CookingRecipeCategory; +import net.momirealms.craftengine.core.item.recipe.RecipeTypes; +import net.momirealms.craftengine.core.util.Key; import java.util.List; @@ -9,4 +11,9 @@ public class VanillaSmokingRecipe extends VanillaCookingRecipe { public VanillaSmokingRecipe(CookingRecipeCategory category, String group, RecipeResult result, List ingredient, float experience, int cookingTime) { super(category, group, result, ingredient, experience, cookingTime); } + + @Override + public Key type() { + return RecipeTypes.SMOKING; + } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaStoneCuttingRecipe.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaStoneCuttingRecipe.java index 79ab56d86..bd032294d 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaStoneCuttingRecipe.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaStoneCuttingRecipe.java @@ -1,8 +1,11 @@ package net.momirealms.craftengine.core.item.recipe.vanilla; +import net.momirealms.craftengine.core.item.recipe.RecipeTypes; +import net.momirealms.craftengine.core.util.Key; + import java.util.List; -public class VanillaStoneCuttingRecipe extends VanillaRecipe { +public class VanillaStoneCuttingRecipe extends VanillaGroupedRecipe { private final List ingredient; public VanillaStoneCuttingRecipe(String group, RecipeResult result, List ingredient) { @@ -13,4 +16,9 @@ public class VanillaStoneCuttingRecipe extends VanillaRecipe { public List ingredient() { return ingredient; } + + @Override + public Key type() { + return RecipeTypes.STONE_CUTTING; + } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/reader/VanillaRecipeReader1_20.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/reader/VanillaRecipeReader1_20.java index c6897a43c..ff836a317 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/reader/VanillaRecipeReader1_20.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/reader/VanillaRecipeReader1_20.java @@ -91,6 +91,16 @@ public class VanillaRecipeReader1_20 extends AbstractRecipeReader { ); } + @Override + public VanillaSmithingTransformRecipe readSmithingTransform(JsonObject json) { + return new VanillaSmithingTransformRecipe( + readSingleIngredient(json.get("base")), + readSingleIngredient(json.get("template")), + readSingleIngredient(json.get("addition")), + readSmithingResult(json.getAsJsonObject("result")) + ); + } + protected List readSingleIngredient(JsonElement json) { List ingredients = new ArrayList<>(); if (json.isJsonObject()) { @@ -126,6 +136,12 @@ public class VanillaRecipeReader1_20 extends AbstractRecipeReader { return new RecipeResult(item, count, null); } + @NotNull + protected RecipeResult readSmithingResult(JsonObject object) { + String item = object.get("item").getAsString(); + return new RecipeResult(item, 1, null); + } + protected List> readShapelessIngredients(JsonArray json) { List> ingredients = new ArrayList<>(); for (JsonElement element : json) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/reader/VanillaRecipeReader1_20_5.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/reader/VanillaRecipeReader1_20_5.java index 727ba41cb..3bd399f96 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/reader/VanillaRecipeReader1_20_5.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/reader/VanillaRecipeReader1_20_5.java @@ -26,4 +26,9 @@ public class VanillaRecipeReader1_20_5 extends VanillaRecipeReader1_20 { protected RecipeResult readStoneCuttingResult(JsonObject json) { return readCraftingResult(json.getAsJsonObject("result")); } + + @Override + protected @NotNull RecipeResult readSmithingResult(JsonObject object) { + return readCraftingResult(object.getAsJsonObject()); + } } From 4090501191de9890d8862aabac164b7897256b6f Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Wed, 19 Mar 2025 04:16:52 +0800 Subject: [PATCH 08/15] register smithing recipes --- .../furniture/DismountListener1_20.java | 1 + .../item/recipe/BukkitRecipeManager.java | 85 ++++++++++++++----- .../bukkit/item/recipe/EmptyRecipeChoice.java | 35 -------- .../craftengine/bukkit/util/Reflections.java | 32 +++++++ .../recipe/CustomSmithingTransformRecipe.java | 2 +- 5 files changed, 98 insertions(+), 57 deletions(-) delete mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/EmptyRecipeChoice.java diff --git a/bukkit/legacy/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/DismountListener1_20.java b/bukkit/legacy/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/DismountListener1_20.java index 98fd4deea..d4a230393 100644 --- a/bukkit/legacy/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/DismountListener1_20.java +++ b/bukkit/legacy/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/DismountListener1_20.java @@ -4,6 +4,7 @@ import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; +import org.bukkit.inventory.RecipeChoice; import java.util.function.BiConsumer; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/BukkitRecipeManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/BukkitRecipeManager.java index b4eb96104..3d9283b9b 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/BukkitRecipeManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/BukkitRecipeManager.java @@ -56,18 +56,18 @@ public class BukkitRecipeManager implements RecipeManager { static { BUKKIT_RECIPE_FACTORIES.put(RecipeTypes.SMITHING_TRANSFORM, (key, recipe) -> { CustomSmithingTransformRecipe ceRecipe = (CustomSmithingTransformRecipe) recipe; - SmithingTransformRecipe transformRecipe = new SmithingTransformRecipe( - key, ceRecipe.result(ItemBuildContext.EMPTY), - ingredientToBukkitRecipeChoice(ceRecipe.template()), - ingredientToBukkitRecipeChoice(ceRecipe.base()), - ingredientToBukkitRecipeChoice(ceRecipe.addition()), - false - ); + ceRecipe.addition(); + // bukkit api doesn't allow empty material choices, that's why we do this try { - Object craftRecipe = Reflections.method$CraftSmithingTransformRecipe$fromBukkitRecipe.invoke(null, transformRecipe); - Reflections.method$CraftRecipe$addToCraftingManager.invoke(craftRecipe); + Object smithingRecipe = createMinecraftSmithingTransformRecipe(ceRecipe); + if (VersionHelper.isVersionNewerThan1_21_2()) { + smithingRecipe = Reflections.constructor$RecipeHolder.newInstance(Reflections.method$CraftRecipe$toMinecraft.invoke(null, key), smithingRecipe); + } else if (VersionHelper.isVersionNewerThan1_20_2()) { + smithingRecipe = Reflections.constructor$RecipeHolder.newInstance(Reflections.method$ResourceLocation$fromNamespaceAndPath.invoke(null, key.namespace(), key.value()), smithingRecipe); + } + Reflections.method$RecipeManager$addRecipe.invoke(minecraftRecipeManager(), smithingRecipe); } catch (Exception e) { - CraftEngine.instance().logger().warn("Failed to convert smithing transform recipe", e); + CraftEngine.instance().logger().warn("Failed to convert transform recipe", e); } }); BUKKIT_RECIPE_FACTORIES.put(RecipeTypes.SHAPED, (key, recipe) -> { @@ -761,9 +761,9 @@ public class BukkitRecipeManager implements RecipeManager { CustomSmithingTransformRecipe ceRecipe = new CustomSmithingTransformRecipe<>( id, - Ingredient.of(baseHolders), - Ingredient.of(templateHolders), - Ingredient.of(additionHolders), + baseHolders.isEmpty() ? null : Ingredient.of(baseHolders), + templateHolders.isEmpty() ? null : Ingredient.of(templateHolders), + additionHolders.isEmpty() ? null : Ingredient.of(additionHolders), new CustomRecipeResult<>(new CloneableConstantItem(recipe.result().isCustom() ? Key.of("!internal:custom") : Key.of(recipe.result().id()), result), recipe.result().count()) ); @@ -838,15 +838,11 @@ public class BukkitRecipeManager implements RecipeManager { } private static RecipeChoice ingredientToBukkitRecipeChoice(Ingredient ingredient) { - if (ingredient == null) { - return EmptyRecipeChoice.INSTANCE; - } else { - Set materials = new HashSet<>(); - for (Holder holder : ingredient.items()) { - materials.add(getMaterialById(holder.value())); - } - return new RecipeChoice.MaterialChoice(new ArrayList<>(materials)); + Set materials = new HashSet<>(); + for (Holder holder : ingredient.items()) { + materials.add(getMaterialById(holder.value())); } + return new RecipeChoice.MaterialChoice(new ArrayList<>(materials)); } private static Material getMaterialById(Key key) { @@ -966,6 +962,53 @@ public class BukkitRecipeManager implements RecipeManager { } } + // 1.20-1.21.2 + private static Object toMinecraftIngredient(Ingredient ingredient) throws ReflectiveOperationException { + if (ingredient == null) { + return Reflections.method$CraftRecipe$toIngredient.invoke(null, null, true); + } else { + RecipeChoice choice = ingredientToBukkitRecipeChoice(ingredient); + return Reflections.method$CraftRecipe$toIngredient.invoke(null, choice, true); + } + } + + // 1.21.2+ + private static Optional toOptionalMinecraftIngredient(Ingredient ingredient) throws ReflectiveOperationException { + if (ingredient == null) { + return Optional.empty(); + } else { + RecipeChoice choice = ingredientToBukkitRecipeChoice(ingredient); + Object mcIngredient = Reflections.method$CraftRecipe$toIngredient.invoke(null, choice, true); + return Optional.of(mcIngredient); + } + } + + private static Object createMinecraftSmithingTransformRecipe(CustomSmithingTransformRecipe ceRecipe) throws ReflectiveOperationException { + if (VersionHelper.isVersionNewerThan1_21_2()) { + return Reflections.constructor$SmithingTransformRecipe.newInstance( + toOptionalMinecraftIngredient(ceRecipe.template()), + toOptionalMinecraftIngredient(ceRecipe.base()), + toOptionalMinecraftIngredient(ceRecipe.addition()), + Reflections.method$CraftItemStack$asNMSMirror.invoke(null, ceRecipe.result(ItemBuildContext.EMPTY)) + ); + } else if (VersionHelper.isVersionNewerThan1_20_2()) { + return Reflections.constructor$SmithingTransformRecipe.newInstance( + toMinecraftIngredient(ceRecipe.template()), + toMinecraftIngredient(ceRecipe.base()), + toMinecraftIngredient(ceRecipe.addition()), + Reflections.method$CraftItemStack$asNMSMirror.invoke(null, ceRecipe.result(ItemBuildContext.EMPTY)) + ); + } else { + return Reflections.constructor$SmithingTransformRecipe.newInstance( + Reflections.method$ResourceLocation$fromNamespaceAndPath.invoke(null, ceRecipe.id().namespace(), ceRecipe.id().value()), + toMinecraftIngredient(ceRecipe.template()), + toMinecraftIngredient(ceRecipe.base()), + toMinecraftIngredient(ceRecipe.addition()), + Reflections.method$CraftItemStack$asNMSMirror.invoke(null, ceRecipe.result(ItemBuildContext.EMPTY)) + ); + } + } + public Object getRecipeHolderByRecipe(Recipe recipe) { return recipeToMcRecipeHolder.get(recipe); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/EmptyRecipeChoice.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/EmptyRecipeChoice.java deleted file mode 100644 index 382b2c0de..000000000 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/EmptyRecipeChoice.java +++ /dev/null @@ -1,35 +0,0 @@ -package net.momirealms.craftengine.bukkit.item.recipe; - -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.RecipeChoice; -import org.jetbrains.annotations.NotNull; - -record EmptyRecipeChoice() implements RecipeChoice { - - static final RecipeChoice INSTANCE = new EmptyRecipeChoice(); - - @Override - @NotNull - public ItemStack getItemStack() { - throw new UnsupportedOperationException("This is an empty RecipeChoice"); - } - - @SuppressWarnings("MethodDoesntCallSuperMethod") - @Override - @NotNull - public RecipeChoice clone() { - return this; - } - - @Override - public boolean test(final @NotNull ItemStack itemStack) { - return false; - } - - @Override - @NotNull - public RecipeChoice validate(final boolean allowEmptyRecipes) { - if (allowEmptyRecipes) return this; - throw new IllegalArgumentException("empty RecipeChoice isn't allowed here"); - } -} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java index 3e6506c61..cd20007d2 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java @@ -4267,6 +4267,12 @@ public class Reflections { BukkitReflectionUtils.assembleMCClass("world.item.crafting.RecipeHolder") ); + // 1.20.2-1.21.1 resource location + // 1.21.2+ resource key + public static final Constructor constructor$RecipeHolder = Optional.ofNullable(clazz$RecipeHolder) + .map(it -> ReflectionUtils.getConstructor(it, 0)) + .orElse(null); + // 1.20.2+ public static final Field field$RecipeHolder$recipe = Optional.ofNullable(clazz$RecipeHolder) .map(it -> ReflectionUtils.getDeclaredField(it, 1)) @@ -4945,4 +4951,30 @@ public class Reflections { ReflectionUtils.getDeclaredField( clazz$CraftInventoryAnvil, clazz$AnvilMenu, 0 ); + + public static final Class clazz$SmithingTransformRecipe = requireNonNull( + ReflectionUtils.getClazz( + BukkitReflectionUtils.assembleMCClass("world.item.crafting.SmithingTransformRecipe") + ) + ); + + public static final Constructor constructor$SmithingTransformRecipe = requireNonNull( + VersionHelper.isVersionNewerThan1_21_2() ? + ReflectionUtils.getConstructor(clazz$SmithingTransformRecipe, Optional.class, Optional.class, Optional.class, clazz$ItemStack) : + VersionHelper.isVersionNewerThan1_20_2() ? + ReflectionUtils.getConstructor(clazz$SmithingTransformRecipe, clazz$Ingredient, clazz$Ingredient, clazz$Ingredient, clazz$ItemStack) : + ReflectionUtils.getConstructor(clazz$SmithingTransformRecipe, clazz$ResourceLocation, clazz$Ingredient, clazz$Ingredient, clazz$Ingredient, clazz$ItemStack) + ); + + public static final Method method$RecipeManager$addRecipe = requireNonNull( + VersionHelper.isVersionNewerThan1_20_2() ? + ReflectionUtils.getMethod(clazz$RecipeManager, void.class, clazz$RecipeHolder) : + ReflectionUtils.getMethod(clazz$RecipeManager, void.class, clazz$Recipe) + ); + + public static final Method method$CraftRecipe$toIngredient = requireNonNull( + ReflectionUtils.getStaticMethod( + clazz$CraftRecipe, clazz$Ingredient, RecipeChoice.class, boolean.class + ) + ); } 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 9f878670d..e77e1f81e 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 @@ -125,7 +125,7 @@ public class CustomSmithingTransformRecipe implements Recipe { holders.add(BuiltInRegistries.OPTIMIZED_ITEM_ID.get(Key.of(item)).orElseThrow(() -> new IllegalArgumentException("Invalid vanilla/custom item: " + item))); } } - return Ingredient.of(holders); + return holders.isEmpty() ? null : Ingredient.of(holders); } } } From 917e1b51410dda5937982d495a745465003f9a8b Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Wed, 19 Mar 2025 05:26:17 +0800 Subject: [PATCH 09/15] added some recipe methods --- .../furniture/DismountListener1_20.java | 1 - .../bukkit/item/RTagItemWrapper.java | 7 ++++ .../item/factory/ComponentItemFactory.java | 18 ++++++++++ .../item/factory/UniversalItemFactory.java | 10 ++++++ .../item/recipe/BukkitRecipeManager.java | 6 ++-- .../craftengine/bukkit/util/Reflections.java | 26 ++++++++++++++ .../craftengine/core/item/AbstractItem.java | 6 ++++ .../craftengine/core/item/Item.java | 2 ++ .../craftengine/core/item/ItemFactory.java | 2 ++ .../craftengine/core/item/ItemWrapper.java | 4 +++ .../recipe/CustomSmithingTransformRecipe.java | 34 +++++++++++++++++-- 11 files changed, 110 insertions(+), 6 deletions(-) diff --git a/bukkit/legacy/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/DismountListener1_20.java b/bukkit/legacy/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/DismountListener1_20.java index d4a230393..98fd4deea 100644 --- a/bukkit/legacy/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/DismountListener1_20.java +++ b/bukkit/legacy/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/DismountListener1_20.java @@ -4,7 +4,6 @@ import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; -import org.bukkit.inventory.RecipeChoice; import java.util.function.BiConsumer; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/RTagItemWrapper.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/RTagItemWrapper.java index 46d87ddd0..b8785432b 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/RTagItemWrapper.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/RTagItemWrapper.java @@ -4,6 +4,8 @@ import com.saicone.rtag.RtagItem; import net.momirealms.craftengine.core.item.ItemWrapper; import org.bukkit.inventory.ItemStack; +import java.util.Map; + @SuppressWarnings("UnstableApiUsage") public class RTagItemWrapper implements ItemWrapper { private final RtagItem rtagItem; @@ -110,4 +112,9 @@ public class RTagItemWrapper implements ItemWrapper { public ItemWrapper copyWithCount(int count) { return new RTagItemWrapper(new RtagItem(this.rtagItem.loadCopy()), count); } + + @Override + public Map getData() { + return this.rtagItem.get(); + } } \ No newline at end of file diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/ComponentItemFactory.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/ComponentItemFactory.java index 95d371115..76254dea4 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/ComponentItemFactory.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/ComponentItemFactory.java @@ -1,7 +1,11 @@ package net.momirealms.craftengine.bukkit.item.factory; +import com.saicone.rtag.RtagItem; import com.saicone.rtag.data.ComponentType; +import com.saicone.rtag.item.ItemObject; +import net.momirealms.craftengine.bukkit.item.RTagItemWrapper; import net.momirealms.craftengine.bukkit.util.EnchantmentUtils; +import net.momirealms.craftengine.bukkit.util.Reflections; import net.momirealms.craftengine.core.item.ComponentKeys; import net.momirealms.craftengine.core.item.Enchantment; import net.momirealms.craftengine.core.item.ItemWrapper; @@ -287,4 +291,18 @@ public class ComponentItemFactory extends BukkitItemFactory { if (!item.hasComponent(ComponentKeys.REPAIR_COST)) return Optional.empty(); return Optional.ofNullable((Integer) ComponentType.encodeJava(ComponentKeys.REPAIR_COST, item.getComponent(ComponentKeys.REPAIR_COST)).orElse(null)); } + + @Override + protected ItemWrapper merge(ItemWrapper item1, ItemWrapper item2) { + Object itemStack1 = item1.getLiteralObject(); + Object itemStack2 = item2.getLiteralObject(); + try { + Object itemStack3 = Reflections.method$ItemStack$transmuteCopy.invoke(itemStack1, Reflections.method$ItemStack$getItem.invoke(itemStack2), 1); + Reflections.method$ItemStack$applyComponents.invoke(itemStack3, Reflections.method$ItemStack$getComponentsPatch.invoke(itemStack2)); + return new RTagItemWrapper(new RtagItem(ItemObject.asCraftMirror(itemStack3)), item2.count()); + } catch (Exception e) { + this.plugin.logger().warn("Failed to merge item", e); + } + return null; + } } \ No newline at end of file diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/UniversalItemFactory.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/UniversalItemFactory.java index 9be055d2f..b3179717e 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/UniversalItemFactory.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/UniversalItemFactory.java @@ -1,8 +1,11 @@ package net.momirealms.craftengine.bukkit.item.factory; +import com.saicone.rtag.RtagItem; +import com.saicone.rtag.item.ItemObject; import com.saicone.rtag.tag.TagBase; import com.saicone.rtag.tag.TagCompound; import com.saicone.rtag.tag.TagList; +import net.momirealms.craftengine.bukkit.item.RTagItemWrapper; import net.momirealms.craftengine.core.item.Enchantment; import net.momirealms.craftengine.core.item.ItemWrapper; import net.momirealms.craftengine.core.plugin.CraftEngine; @@ -229,4 +232,11 @@ public class UniversalItemFactory extends BukkitItemFactory { if (!item.hasTag("RepairCost")) return Optional.empty(); return Optional.of(item.get("RepairCost")); } + + @Override + protected ItemWrapper merge(ItemWrapper item1, ItemWrapper item2) { + Object itemStack = ItemObject.copy(item2.getLiteralObject()); + ItemObject.setCustomDataTag(itemStack, ItemObject.getCustomDataTag(item1.getLiteralObject())); + return new RTagItemWrapper(new RtagItem(ItemObject.asCraftMirror(itemStack)), item2.count()); + } } \ No newline at end of file diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/BukkitRecipeManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/BukkitRecipeManager.java index 3d9283b9b..370169d20 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/BukkitRecipeManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/BukkitRecipeManager.java @@ -764,14 +764,14 @@ public class BukkitRecipeManager implements RecipeManager { baseHolders.isEmpty() ? null : Ingredient.of(baseHolders), templateHolders.isEmpty() ? null : Ingredient.of(templateHolders), additionHolders.isEmpty() ? null : Ingredient.of(additionHolders), - new CustomRecipeResult<>(new CloneableConstantItem(recipe.result().isCustom() ? Key.of("!internal:custom") : Key.of(recipe.result().id()), result), recipe.result().count()) + new CustomRecipeResult<>(new CloneableConstantItem(recipe.result().isCustom() ? Key.of("!internal:custom") : Key.of(recipe.result().id()), result), recipe.result().count()), + List.of(CustomSmithingTransformRecipe.ItemDataProcessor.MERGE_ALL) ); SmithingTransformRecipe transformRecipe = new SmithingTransformRecipe(key, result, new RecipeChoice.MaterialChoice(new ArrayList<>(templateMaterials)), new RecipeChoice.MaterialChoice(new ArrayList<>(baseMaterials)), - new RecipeChoice.MaterialChoice(new ArrayList<>(additionMaterials)), - true + new RecipeChoice.MaterialChoice(new ArrayList<>(additionMaterials)) ); if (hasCustomItemInTag) { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java index cd20007d2..c7850595e 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java @@ -4977,4 +4977,30 @@ public class Reflections { clazz$CraftRecipe, clazz$Ingredient, RecipeChoice.class, boolean.class ) ); + + // 1.20.5+ + public static final Method method$ItemStack$transmuteCopy = ReflectionUtils.getMethod( + clazz$ItemStack, clazz$ItemStack, clazz$ItemLike, int.class + ); + + // 1.20.5+ + public static final Class clazz$DataComponentPatch = ReflectionUtils.getClazz( + BukkitReflectionUtils.assembleMCClass("core.component.DataComponentPatch") + ); + + // 1.20.5+ + public static final Method method$ItemStack$getComponentsPatch = Optional.ofNullable(clazz$DataComponentPatch) + .map(it -> ReflectionUtils.getMethod(clazz$ItemStack, it)) + .orElse(null); + + // 1.20.5+ + public static final Method method$ItemStack$applyComponents = Optional.ofNullable(clazz$DataComponentPatch) + .map(it -> ReflectionUtils.getMethod(clazz$ItemStack, void.class, it)) + .orElse(null); + + public static final Method method$ItemStack$getItem = requireNonNull( + ReflectionUtils.getMethod( + clazz$ItemStack, clazz$Item + ) + ); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItem.java b/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItem.java index eda369c0c..c31af1519 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItem.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItem.java @@ -276,4 +276,10 @@ public class AbstractItem, I> implements Item { public Object getLiteralObject() { return this.item.getLiteralObject(); } + + @SuppressWarnings({"unchecked", "rawtypes"}) + @Override + public Item merge(Item another) { + return new AbstractItem<>(this.factory, this.factory.merge(this.item, ((AbstractItem) another).item)); + } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/Item.java b/core/src/main/java/net/momirealms/craftengine/core/item/Item.java index 8d734326d..7de763c22 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/Item.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/Item.java @@ -116,4 +116,6 @@ public interface Item { boolean is(Key itemTag); Object getLiteralObject(); + + Item merge(Item another); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/ItemFactory.java b/core/src/main/java/net/momirealms/craftengine/core/item/ItemFactory.java index d35dc1042..c5595bef9 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/ItemFactory.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/ItemFactory.java @@ -108,4 +108,6 @@ public abstract class ItemFactory

, I> protected abstract void repairCost(ItemWrapper item, Integer data); protected abstract Optional repairCost(ItemWrapper item); + + protected abstract ItemWrapper merge(ItemWrapper item1, ItemWrapper item2); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/ItemWrapper.java b/core/src/main/java/net/momirealms/craftengine/core/item/ItemWrapper.java index 49af43621..241ac787e 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/ItemWrapper.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/ItemWrapper.java @@ -1,5 +1,7 @@ package net.momirealms.craftengine.core.item; +import java.util.Map; + public interface ItemWrapper { I getItem(); @@ -37,4 +39,6 @@ public interface ItemWrapper { void count(int amount); ItemWrapper copyWithCount(int count); + + Map getData(); } 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 e77e1f81e..03b619f5d 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 @@ -1,5 +1,6 @@ package net.momirealms.craftengine.core.item.recipe; +import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.item.ItemBuildContext; import net.momirealms.craftengine.core.item.recipe.input.RecipeInput; import net.momirealms.craftengine.core.item.recipe.input.SmithingInput; @@ -12,6 +13,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.*; +import java.util.function.BiFunction; public class CustomSmithingTransformRecipe implements Recipe { public static final Factory FACTORY = new Factory<>(); @@ -20,18 +22,21 @@ public class CustomSmithingTransformRecipe implements Recipe { private final Ingredient base; private final Ingredient template; private final Ingredient addition; + private final List processors; public CustomSmithingTransformRecipe(Key id, @Nullable Ingredient addition, @Nullable Ingredient base, @Nullable Ingredient template, - CustomRecipeResult result + CustomRecipeResult result, + List processors ) { this.id = id; this.result = result; this.base = base; this.template = template; this.addition = addition; + this.processors = processors; } @SuppressWarnings("unchecked") @@ -82,6 +87,17 @@ public class CustomSmithingTransformRecipe implements Recipe { return result.buildItemStack(context); } + @SuppressWarnings("unchecked") + public T assemble(ItemBuildContext context, Item base) { + T result = this.result(context); + Item wrappedResult = (Item) CraftEngine.instance().itemManager().wrap(result); + Item finalResult = wrappedResult; + for (ItemDataProcessor processor : this.processors) { + finalResult = (Item) processor.apply(base, wrappedResult); + } + return finalResult.getItem(); + } + @Override public CustomRecipeResult result() { return this.result; @@ -112,7 +128,8 @@ public class CustomSmithingTransformRecipe implements Recipe { List template = MiscUtils.getAsStringList(arguments.get("template")); return new CustomSmithingTransformRecipe<>( id, - toIngredient(addition), toIngredient(base), toIngredient(template), parseResult(arguments) + toIngredient(addition), toIngredient(base), toIngredient(template), parseResult(arguments), + List.of(new ItemDataProcessor[]{}) ); } @@ -128,4 +145,17 @@ public class CustomSmithingTransformRecipe implements Recipe { return holders.isEmpty() ? null : Ingredient.of(holders); } } + + @FunctionalInterface + public interface ItemDataProcessor extends BiFunction, Item, Item> { + MergeAllDataProcessor MERGE_ALL = new MergeAllDataProcessor(); + } + + public static class MergeAllDataProcessor implements ItemDataProcessor { + + @Override + public Item apply(Item item1, Item item2) { + return item1.merge(item2); + } + } } From b298f76b862ad9ab7b604139d37ee274738709e7 Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Wed, 19 Mar 2025 20:25:21 +0800 Subject: [PATCH 10/15] add smithing transform --- .../item/factory/UniversalItemFactory.java | 7 ---- .../item/recipe/BukkitRecipeManager.java | 2 +- .../item/recipe/RecipeEventListener.java | 42 +++++++++++++++++-- .../craftengine/core/item/AbstractItem.java | 1 + .../recipe/CustomSmithingTransformRecipe.java | 14 +++---- .../VanillaSmithingTransformRecipe.java | 2 +- 6 files changed, 49 insertions(+), 19 deletions(-) diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/UniversalItemFactory.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/UniversalItemFactory.java index b3179717e..10d657bb0 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/UniversalItemFactory.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/UniversalItemFactory.java @@ -126,18 +126,11 @@ public class UniversalItemFactory extends BukkitItemFactory { @Override protected Optional maxDamage(ItemWrapper item) { -// if (!item.hasTag("CustomFishing", "max_dur")) return Optional.empty(); -// return Optional.of(item.get("CustomFishing", "max_dur")); return Optional.of((int) item.getItem().getType().getMaxDurability()); } @Override protected void maxDamage(ItemWrapper item, Integer damage) { -// if (damage == null) { -// item.remove("CustomFishing", "max_dur"); -// } else { -// item.set(damage, "CustomFishing", "max_dur"); -// } throw new UnsupportedOperationException("This feature is only available on 1.20.5+"); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/BukkitRecipeManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/BukkitRecipeManager.java index 370169d20..72918957f 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/BukkitRecipeManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/BukkitRecipeManager.java @@ -780,7 +780,7 @@ public class BukkitRecipeManager implements RecipeManager { unregisterRecipe(key); Reflections.method$CraftRecipe$addToCraftingManager.invoke(Reflections.method$CraftSmithingTransformRecipe$fromBukkitRecipe.invoke(null, transformRecipe)); } catch (Exception e) { - CraftEngine.instance().logger().warn("Failed to convert smelting recipe", e); + CraftEngine.instance().logger().warn("Failed to convert transform recipe", e); } }); this.injectedDataPackRecipes.add(key); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/RecipeEventListener.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/RecipeEventListener.java index bbf3ed9dd..35b3e4060 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/RecipeEventListener.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/RecipeEventListener.java @@ -11,12 +11,11 @@ import net.momirealms.craftengine.bukkit.util.ItemUtils; import net.momirealms.craftengine.bukkit.util.LegacyInventoryUtils; import net.momirealms.craftengine.bukkit.util.Reflections; import net.momirealms.craftengine.core.item.*; -import net.momirealms.craftengine.core.item.recipe.CustomCampfireRecipe; -import net.momirealms.craftengine.core.item.recipe.OptimizedIDItem; import net.momirealms.craftengine.core.item.recipe.Recipe; -import net.momirealms.craftengine.core.item.recipe.RecipeTypes; +import net.momirealms.craftengine.core.item.recipe.*; import net.momirealms.craftengine.core.item.recipe.input.CraftingInput; import net.momirealms.craftengine.core.item.recipe.input.SingleItemInput; +import net.momirealms.craftengine.core.item.recipe.input.SmithingInput; import net.momirealms.craftengine.core.plugin.config.ConfigManager; import net.momirealms.craftengine.core.registry.BuiltInRegistries; import net.momirealms.craftengine.core.registry.Holder; @@ -38,6 +37,7 @@ import org.bukkit.event.inventory.*; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.*; import org.bukkit.inventory.view.AnvilView; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; @@ -845,6 +845,42 @@ public class RecipeEventListener implements Listener { return; } + ItemStack base = inventory.getInputEquipment(); + ItemStack template = inventory.getInputTemplate(); + ItemStack addition = inventory.getInputMineral(); + SmithingInput input = new SmithingInput<>( + getOptimizedIDItem(base), + getOptimizedIDItem(template), + getOptimizedIDItem(addition) + ); + + Recipe ceRecipe = this.recipeManager.getRecipe(RecipeTypes.SMITHING_TRANSFORM, input); + if (ceRecipe == null) { + event.setResult(null); + return; + } + + Player player; + try { + player = (Player) Reflections.method$InventoryView$getPlayer.invoke(event.getView()); + } catch (ReflectiveOperationException e) { + this.plugin.logger().warn("Failed to get inventory viewer", e); + return; + } + + CustomSmithingTransformRecipe transformRecipe = (CustomSmithingTransformRecipe) ceRecipe; + ItemStack processed = transformRecipe.assemble(new ItemBuildContext(this.plugin.adapt(player), ContextHolder.EMPTY), this.itemManager.wrap(base)); + event.setResult(processed); + } + + private OptimizedIDItem getOptimizedIDItem(@Nullable ItemStack itemStack) { + if (ItemUtils.isEmpty(itemStack)) { + return EMPTY; + } else { + Item wrappedItem = this.itemManager.wrap(itemStack); + Optional> idHolder = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(wrappedItem.id()); + return idHolder.map(keyReference -> new OptimizedIDItem<>(keyReference, itemStack)).orElse(EMPTY); + } } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItem.java b/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItem.java index c31af1519..ae652add7 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItem.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItem.java @@ -143,6 +143,7 @@ public class AbstractItem, I> implements Item { this.factory.customName(this.item, displayName); return this; } + @Override public Item itemName(String itemName) { this.factory.itemName(this.item, itemName); 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 03b619f5d..cda1f1288 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 @@ -25,9 +25,9 @@ public class CustomSmithingTransformRecipe implements Recipe { private final List processors; public CustomSmithingTransformRecipe(Key id, - @Nullable Ingredient addition, @Nullable Ingredient base, @Nullable Ingredient template, + @Nullable Ingredient addition, CustomRecipeResult result, List processors ) { @@ -50,12 +50,12 @@ public class CustomSmithingTransformRecipe implements Recipe { private boolean checkIngredient(Ingredient ingredient, OptimizedIDItem item) { if (ingredient != null) { - if (item == null) { + if (item == null || item.isEmpty()) { return false; } return ingredient.test(item); } else { - return item == null; + return item == null || item.isEmpty(); } } @@ -124,12 +124,12 @@ public class CustomSmithingTransformRecipe implements Recipe { @Override public Recipe create(Key id, Map arguments) { List base = MiscUtils.getAsStringList(arguments.get("base")); - List addition = MiscUtils.getAsStringList(arguments.get("addition")); - List template = MiscUtils.getAsStringList(arguments.get("template")); + List addition = MiscUtils.getAsStringList(arguments.get("addition-input")); + List template = MiscUtils.getAsStringList(arguments.get("template-type")); return new CustomSmithingTransformRecipe<>( id, - toIngredient(addition), toIngredient(base), toIngredient(template), parseResult(arguments), - List.of(new ItemDataProcessor[]{}) + toIngredient(base), toIngredient(template),toIngredient(addition), parseResult(arguments), + List.of(ItemDataProcessor.MERGE_ALL) ); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaSmithingTransformRecipe.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaSmithingTransformRecipe.java index 5e4713622..6ad75f38e 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaSmithingTransformRecipe.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaSmithingTransformRecipe.java @@ -11,7 +11,7 @@ public class VanillaSmithingTransformRecipe implements VanillaRecipe { private final List template; private final List addition; - public VanillaSmithingTransformRecipe(List addition, List base, List template, RecipeResult result) { + public VanillaSmithingTransformRecipe(List base, List template, List addition, RecipeResult result) { this.result = result; this.base = base; this.template = template; From c84117ef8a9212a116f9ea063e2fdc85c35269d1 Mon Sep 17 00:00:00 2001 From: jhqwqmc <2110242767@qq.com> Date: Wed, 19 Mar 2025 23:45:16 +0800 Subject: [PATCH 11/15] =?UTF-8?q?feat(core):=20=E4=BC=98=E5=8C=96=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bukkit-loader/src/main/resources/config.yml | 1 + .../craftengine/core/plugin/config/ConfigManager.java | 6 ++++++ gradle.properties | 4 ++-- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/bukkit-loader/src/main/resources/config.yml b/bukkit-loader/src/main/resources/config.yml index 7c3c61845..fb908e038 100644 --- a/bukkit-loader/src/main/resources/config.yml +++ b/bukkit-loader/src/main/resources/config.yml @@ -28,6 +28,7 @@ resource-pack: seed: 0 # 0 = random seed fake-directory: true escape-unicode: true + break-json: true resource-location: enable: true random-namespace: diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/config/ConfigManager.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/config/ConfigManager.java index 9490ece90..2e449ac12 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/config/ConfigManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/config/ConfigManager.java @@ -54,6 +54,7 @@ public class ConfigManager implements Reloadable { protected long resource_pack$protection$obfuscation$seed; protected boolean resource_pack$protection$obfuscation$fake_directory; protected boolean resource_pack$protection$obfuscation$escape_unicode; + protected boolean resource_pack$protection$obfuscation$break_json; protected boolean resource_pack$protection$obfuscation$resource_location$enable; protected int resource_pack$protection$obfuscation$resource_location$random_namespace$length; protected int resource_pack$protection$obfuscation$resource_location$random_namespace$amount; @@ -200,6 +201,7 @@ public class ConfigManager implements Reloadable { resource_pack$protection$obfuscation$seed = config.getLong("resource-pack.protection.obfuscation.seed", 0L); resource_pack$protection$obfuscation$fake_directory = config.getBoolean("resource-pack.protection.obfuscation.fake-directory", false); resource_pack$protection$obfuscation$escape_unicode = config.getBoolean("resource-pack.protection.obfuscation.escape-unicode", false); + resource_pack$protection$obfuscation$break_json = config.getBoolean("resource-pack.protection.obfuscation.break-json", false); resource_pack$protection$obfuscation$resource_location$enable = config.getBoolean("resource-pack.protection.obfuscation.resource-location.enable", false); resource_pack$protection$obfuscation$resource_location$random_namespace$amount = config.getInt("resource-pack.protection.obfuscation.resource-location.random-namespace.amount", 32); @@ -435,6 +437,10 @@ public class ConfigManager implements Reloadable { return instance.resource_pack$protection$obfuscation$escape_unicode; } + public static boolean breakJson() { + return instance.resource_pack$protection$obfuscation$break_json; + } + public static boolean enableRandomResourceLocation() { return instance.resource_pack$protection$obfuscation$resource_location$enable; } diff --git a/gradle.properties b/gradle.properties index 3bbacafe3..4366964ee 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ # Project settings # Rule: [major update].[feature update].[bug fix] -project_version=0.0.35 -config_version=14 +project_version=0.0.36 +config_version=15 lang_version=3 project_group=net.momirealms latest_minecraft_version=1.21.4 From 70aa917cfbdd7a1297d440b666d0ca296cccf729 Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Thu, 20 Mar 2025 03:27:24 +0800 Subject: [PATCH 12/15] 0.0.35 --- bukkit-loader/src/main/resources/config.yml | 10 +- .../resources/default/configuration/items.yml | 66 ++++++ .../resources/internal/configuration/gui.yml | 8 +- .../gui/custom/smithing_transform_recipe.png | Bin 0 -> 2219 bytes .../font/gui/custom/stonecutting_recipe.png | Bin 2251 -> 4344 bytes .../item/recipe/BukkitRecipeManager.java | 4 +- .../item/recipe/RecipeEventListener.java | 16 ++ .../craftengine/bukkit/util/Reflections.java | 12 + .../recipe/CustomSmithingTransformRecipe.java | 2 +- .../item/recipe/CustomStoneCuttingRecipe.java | 2 +- .../core/item/recipe/RecipeTypes.java | 4 +- .../vanilla/VanillaStoneCuttingRecipe.java | 2 +- .../core/pack/AbstractPackManager.java | 1 + .../gui/category/ItemBrowserManager.java | 4 +- .../gui/category/ItemBrowserManagerImpl.java | 207 +++++++++++++++++- gradle.properties | 4 +- 16 files changed, 326 insertions(+), 16 deletions(-) create mode 100644 bukkit-loader/src/main/resources/resources/internal/resourcepack/assets/minecraft/textures/font/gui/custom/smithing_transform_recipe.png diff --git a/bukkit-loader/src/main/resources/config.yml b/bukkit-loader/src/main/resources/config.yml index fb908e038..125390fb7 100644 --- a/bukkit-loader/src/main/resources/config.yml +++ b/bukkit-loader/src/main/resources/config.yml @@ -26,9 +26,9 @@ resource-pack: obfuscation: enable: false seed: 0 # 0 = random seed - fake-directory: true - escape-unicode: true - break-json: true + fake-directory: false + escape-unicode: false + break-json: false resource-location: enable: true random-namespace: @@ -184,12 +184,14 @@ gui: title: "" smoking: title: "" - campfire: + campfire-cooking: title: "" crafting: title: "" stonecutting: title: "" + smithing-transform: + title: "" performance: # Maximum chain update depth when fixing client visuals diff --git a/bukkit-loader/src/main/resources/resources/default/configuration/items.yml b/bukkit-loader/src/main/resources/resources/default/configuration/items.yml index f01d4a7b7..979df89bc 100644 --- a/bukkit-loader/src/main/resources/resources/default/configuration/items.yml +++ b/bukkit-loader/src/main/resources/resources/default/configuration/items.yml @@ -329,4 +329,70 @@ recipes#11: B: "minecraft:stick" result: id: default:topaz_pickaxe + count: 1 + default:topaz_helmet: + type: shaped + pattern: + - "AAA" + - "A A" + ingredients: + A: "default:topaz" + result: + id: default:topaz_helmet + count: 1 + default:topaz_chestplate: + type: shaped + pattern: + - "A A" + - "AAA" + - "AAA" + ingredients: + A: "default:topaz" + result: + id: default:topaz_chestplate + count: 1 + default:topaz_leggings: + type: shaped + pattern: + - "AAA" + - "A A" + - "A A" + ingredients: + A: "default:topaz" + result: + id: default:topaz_leggings + count: 1 + default:topaz_boots: + type: shaped + pattern: + - "A A" + - "A A" + ingredients: + A: "default:topaz" + result: + id: default:topaz_boots + count: 1 + default:topaz_bow: + type: smithing_transform + base: minecraft:bow + addition: default:topaz + template-type: default:topaz + result: + id: default:topaz_bow + count: 1 + default:topaz_crossbow: + type: smithing_transform + base: minecraft:bow + addition: default:topaz + template-type: default:topaz + result: + id: default:topaz_crossbow + count: 1 + default:topaz_rod: + type: smithing_transform + base: minecraft:fishing_rod + addition: default:topaz + template-type: default:topaz + result: + id: default:topaz_rod count: 1 \ No newline at end of file diff --git a/bukkit-loader/src/main/resources/resources/internal/configuration/gui.yml b/bukkit-loader/src/main/resources/resources/internal/configuration/gui.yml index b81da6caf..7ba729dc6 100644 --- a/bukkit-loader/src/main/resources/resources/internal/configuration/gui.yml +++ b/bukkit-loader/src/main/resources/resources/internal/configuration/gui.yml @@ -53,12 +53,18 @@ images: font: minecraft:internal file: minecraft:font/gui/custom/stonecutting_recipe.png char: '\ub008' + internal:smithing_transform_recipe: + height: 142 + ascent: 20 + font: minecraft:internal + file: minecraft:font/gui/custom/smithing_transform_recipe.png + char: '\ub009' internal:no_recipe: height: 140 ascent: 18 font: minecraft:internal file: minecraft:font/gui/custom/no_recipe.png - char: '\ub009' + char: '\ub00a' templates: internal:icon/2d: diff --git a/bukkit-loader/src/main/resources/resources/internal/resourcepack/assets/minecraft/textures/font/gui/custom/smithing_transform_recipe.png b/bukkit-loader/src/main/resources/resources/internal/resourcepack/assets/minecraft/textures/font/gui/custom/smithing_transform_recipe.png new file mode 100644 index 0000000000000000000000000000000000000000..31b6ea3e5def92f421a725cf8661f76535ff67e2 GIT binary patch literal 2219 zcmbVMd0Z1`8cucV4fU#SMcr%&ph7Z}giJ^D zuqb9vBeE5Tn~zEYf>pshFP0FMlHq9?vQ8?;&^X*y7o8jyMjPF_3Z#e%#_OcfG9^pLCcM?l!uHeG z00IA2L>0v*ydxFN^ToTP3Ixw2Q%FJ(q~aM&G7P~GjR`ry4tOd^bp${f074`Rg+-^b zKstVA5HN!Zk(lMj@t84(o!Ep(l}gS60IgO_*3!tRA_AZ=nM?qr0#qsqlOQQ$WGYxk zk}0icHE){G=Ar8ac&5=WM<+! ziH=6o*dTzUFT5OA%W=M5Vb(vH&E2UVJhe#V zA3I^Z*V=ioeQ{5UL$jSPyA>_OK;BOL-MQg-coF)*C8uH+b z`>;QT;%EZJiwvvY?tLqU%?6zVAarJ?+4VQ9)|X|T%CCN0N?fyDuchB})0>~4Yl7|{ zSL7H^gy7|6#_4b1cI;E$_ zGoIxA&?K3chI_WG$baP94W0GU(tKh_ZBB{Zj=vgXs5zsl4G*rh*U>C1J}RkjUT$kL zR&swHKO0!5ZA@T#vqs~J;VF%1!})JcDT~uzHr#KMsJx(GNGnwb@!+t zx3EO!v)#`BoK12;x1g}xsZ%PrXxd_&AetrnB^0FPxJ%SdtB(G*wR$wNY-z{g#_(eK z`k^1G&c#iuo;zjU9Jhbz7uW?z7M?`xSmBYgse-A-m|!aKPWq#WX`z zUyV;;wZ7e@A$x4a5Iv0-TGT!d`uSg71+s9#q0oyVO@-NC6pF`W<9niZT?pz9V|PIy$iuZ^~cc9B7%HA=2NC zUU$K?S!+MOC;86WG!J9`x{0RT*3&E$neyNKfSKH4IbPl^|IeVhHrc**{e$L>K?f?m z_#cy3d6y}_^Zn=Wi1(R8xrb|3svnKm+o{#s^yXW6eDSN8tT+ckP;KsDLQ?Zs%cfL@ za%JiuSS7PL+bijN&Mq^zB_Wqyba=lySiK}(o0#*&dTlJv?l^O+yqyG&I1%YyKnS2hdd^mEfx?3_S7;^NnCWwkM!SY7n=H8HF3 zYi{Fn4rO5AZdm4-9^1*Si+DHOrxGWFI?|^WD+|8@r-HR__=}`%iCy0x`6Tei4V95Y z>EfaON7?Ss?!DQXozBd0Z(U#AkzMM?ewUMm7l(g7aP_N^FPa1sH?ICx&P_;p9MN6X znzAn8xI<0miMl(d!gp<9MP^+-*IF*^3En-!Zjzg1S+M8I3JD2C5`rN#6{4bFAoNfM0`ftM zK>4*`TIR5XHHEYeR_3nCa-@DJb``mNyS@(5;KS?JYm*xh6 zK-nYf&79ZaKuhN!5a@{Tx5fp^%031H{iP|{I#*N~qOPj030KvCtEt0ObpTCWKwYDf zi;L?pJ|GAPBAbVhX}MgdXp3C@X67Nd0J01e5=QtohV?Rl`jW|k0303|Ov0-WNj`9_ z7aWJj5jeCUxSEO@{7-J6FOf_P@+Agxe2MY@Kpc)LoVLfMLjlZ4I5ZiD;4}j$N0Amx zRUM|TYp<>fsB3Z_B~@KORrQ;@KmbX^`gw={D^&xgu4=EU4rpovni~H`#gWliG#UNB z$TZahlBd13&uZvsd7)vNsv0^lEu5wX45Q<%4a2J9R8_sTHFR~bUNrv$27=#IAd!GA z$H&m=(grJ}i4V$H@0Y+o?8+y3pEryHln- ztrmjHe58yZ@IdAZTD-BGgK@l)7HP`j?n`sXT}hc}$x8uzWu}LkY`M?n%rxB|`efXG zhnMHo@w~p@Cp@F<+F65RW3QK9uPk*-QH(qvzcYIJ^l9$iIFV8psuMycBPfjZ8JqIt z?tKc;=W$Gk$@RE&0v2w~i&kfWa7{r{f)YLzm#W4>ZK(e%jsr zz0I}!UizW{e@TGQ4XAcvD<$T_`asX8SRoEa25M)GL_DisKMDqqvv%6rnZYuYg;l*v zqL}rEmgd?+JTC##)glz4m+2FkIq=1?tE;n@9zAbOWL^+YnK9C1o0YpKw(MP}^bB^* z&Ck5g8;Yz|Wev;b^OErC*9h#x}5rDAw`^) z0J}#$GXr0AWG>WM&pq7lQE8j?eSt3%@Qtj{+YFFri4}J&QVBH|h6t#^w&yh(*8z#z zsF-EfE6{37Sa&r#vf{i>fPqw2s{+-^4Sab&BbTN0wXu&La$hB&|9K(-OdWHnfOnH6 z#-9)wF#~;u?Z5z`|p)0XztGp(g_n_X`{h?bi(!tU3{#hr1^VYLuCNgf}O0y&=2 zWjWYdIwExPn9TFUpKiI`_Imp~w?_cw(L*((IOI>722$sjGRx=7b@nAczM3i>B8U8r zy${12lFgT9gk7fhCRa0n6xQ z*(xtMMW}vkPT0AxlKg6>$wEFx-(95plB-HrM449Darp|5Wy)!2{zm`j!LZDpY=e!o ztBw8%duRJ*E1q5Ld=?kCl`?suadiLTn5D9v2D39k!EUIwFdIN#YO)#DEp)XocVt9| zov$%E)?lvOFR&xR<$KJ(;*D+MrEBMXk9Z`%Euu6tl+djR6RJ3sh<4_7ZD4NBAMK0Q8Kz^#zaPT7TG z%&sIUVy3-YWBT?*9YN6vK`T|uQ>?ZYkEZzLAqTEN6SA{wTkFo|tzosZv67k)%K1tW zcFRQakcZ5{k9i_`8JdSkbBW!9$}-!9-A=ov5dU@F-+qGZ%pof=i+y~wo_c<`46FO- z)j0h2TFb=G+Fr?6MNDUo!$vdJYVg+7uEOjzvoWK=vC8YIo8oEN=cP9$)r%e$(#E`9 z_~t*)06Ftm<;wVB1$%`3?RBG8ibzZ6`+Ns^3p^>qszlg6Zgu^b`$Am24VA!hc$gip zj-eMQQ<)_P6_1pg24kWZiv&ALtew&u3nA4uvRuVYOE?e%A=+qr~#q`J_@Bqf8_zb%eiFONqgZNCvaCm-TWQ8XcwR%gYE z=6@~UcP9%69YJlH>V`2xW0^l&2Ty`e<~lj_HavJ(PzD(4l!wyN^?(XO&A@TVl+P30 zJjGiX*M!MEM)s%l&x$e>b&f>z7!`DkbSHVzp5|a8Prj^WjoE^KzTz=Ovjc=?TD*=2 z7l;i_M77PUh`8IO*WP7N@+kl#{2kBUD@?ffv|^Giqb0a`t(TzWm?A=Fkb20AS*+w+t9opAQKuLorxKNU#oa$DjP(% z+t@GjvvMuic8hmha*BLnpZ>Vx;m@*mUG`}%Ljsvem=?LJj$Y333UNK?QuTQv1w}8I z-RipXrpR>`nbH@eX%!6&jM`A*DcEb`3dWs1$5^cnE3w^cvSo1(qiy9!LUr*Wth z-{Zo@@CH|2SURO|dh2+=hv#;E=>rV?bF}H4wxX*srZUwzp%z3lYUpbEHQ~*`xmT7V zJA+bzHUnTi?8+>Yuy)(F@l(G+IohR|FQHFb<+Rsp1}+IjhF66yU~nU#GfCriB7RL&(aUWG}K=~q`*Puk|lbZLr9nMw_$ z{E?!2?FmaYiLT_4IRJ{=+t4yxM^=iwKWWjNz!)f&eBmQWq%N4HMYS#3bca}+>Utb| zrm*x^hqr15;q4nWE@sm{H=1dN77T}OxwP15{dZxmV_T0%t5}9R<8w!SBLOd2yr*tULtpz8Qy*k7Zq z@pOQ(2+4>T&-emtN6iZbyZ33-Mxd5~Z8d1D4IWx&^7N!rKWVZqs%#-eof&GBal$$H zR!-+JSy$0s_cV5rArJYD^`(ekfT}fXM|}P!cO8M$ndu&*BFgoG=bvSe^54tik1`lX zIonU&pArN)L6|pUqkVUJt!v(c{ss=&P1WbRX%9ZB()`{{s%PbasLL`-pico*QaMVo ztxI(D4ceQoyZDRBDQO+cqiF+(*b?4pZpN>)EKAhNJB~&FyRP_9zMB+4zoFrAY8G!W zK1tyZSs2*!h3ZX^udp~z4t`MUM1MKt=H?n0(NF-5o_!(S=(e8jWfpKzJePlB68sOP zlc%>I?IqS+JXDHm(etlp`9)gCms;{(T9nJ#?jv{n%7SPb_@by}u?x#&ifJ=$FZWiM zmt9!266rv3mSXU>r}UvFMqBlWl5E0+Kal|5U3NYB#3STct%pTLMC6N|ro^53Z{txd zQ6its+K1tKS;OTzbyCkZo?%#HdIcHRBLU7ur?9v><0CtFh3&U0{6#@(y!cEOH+#l{ z&K|T*7@tnK1AIbqrf?8&)4#2JYZ!7KqTNmriauI-2ov=uPI;TlTqC(wd9V(D@MQ5F z8ZLKi*^ZzOlh0Qnzbh(@S>6zfu<>L~9y+Vt{;%e-)HbR{PSPIeh0+uP!MO+tj0-4v y*U|FoR-OB$PTX0!t>v{3?8726#j$NhPjb>nyrBHmd7Qs6kd^rbM474Q?Y{$ArcyKj delta 1494 zcmV;{1u6RYAp^02y>eSaefwW^{L9a%BKPWN%_+AW3auXJt}l zVPtu6$z?nM00SqHI-eIfVJsjrFfueRFf%VOHZ3tRIyEvnFg3C60RfYb0yC3E0~eEC z1P1{*lcWP6lZXQ~lP?62lfwl)e_9$^QUCw|Ay7jR!+5K@h z8{;Ji+#Lutvm2X2us0rHFH9-t@K5pQ<6KK)nuxtu7l ztL`d0R7cQjhf0o62Rf{BkW+}02Zo|%PWY_a@^*g3uk{uD;$?2N=`UG6H2bLWGIpU#gG#f_k1zoH$Zc6^f0Wo3)yKa42(XK7 zlBB|pBj_~&5iWY2olO!G=h;!eU$nNdt364PovgG!USYFa1I8{E(cV^e@3FZaF-#)TJ1NuZS1%lKnH$;t+vMuyQrpXB1cl?kVo0XZ>LC2jl0Y~ zk=uZCNl_!Dx;0YkM5-hStS4cuY?ftL)pU(E$?W2j>)8y%j@7og^`StXT}+jb4Hg zUgaNQre@+`lVWby+}E<1&o*xAOpw(cDL%|D?Im3{b<^XRSnU~5elK|kJAWu;+G)+I z4>r;4xE$CqiOXi7O)`Jr>a)|aItPmB16Kywx%(roP{+QJnADBg|p#WdY@r4;++uq!%E=MhVp6rwMjz!!%jj1 z0%;kMD#EX1XEK*Hk3B{#J+ej8=g}9nb}*J?zB)7LN`g^K&}hr4-1gkznBJ*zVt?Ly zI>0_>rnNgS@C|xhaOLpS_dcIAPDMx^b?*!cIi0sQSZy?wu=Or=ElPiHrJFpPza2T)6i1MTApD zVByN6F&~+$_|V97QMKo`Ju%m0PxfR__GG7v%I#dsfcxhvvr%s6S_C{W7v%ZdUl@}; w*?*dihYP`m|33lS%>kEuu6T6p3-K$!0AtP;RZi9@rT_o{07*qoM6N<$g192~>i_@% diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/BukkitRecipeManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/BukkitRecipeManager.java index 72918957f..7f34ce945 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/BukkitRecipeManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/BukkitRecipeManager.java @@ -195,7 +195,7 @@ public class BukkitRecipeManager implements RecipeManager { CraftEngine.instance().logger().warn("Failed to convert campfire recipe", e); } }); - BUKKIT_RECIPE_FACTORIES.put(RecipeTypes.STONE_CUTTING, (key, recipe) -> { + BUKKIT_RECIPE_FACTORIES.put(RecipeTypes.STONECUTTING, (key, recipe) -> { CustomStoneCuttingRecipe ceRecipe = (CustomStoneCuttingRecipe) recipe; List itemStacks = new ArrayList<>(); for (Holder item : ceRecipe.ingredient().items()) { @@ -383,7 +383,7 @@ public class BukkitRecipeManager implements RecipeManager { this.byId.put(id, recipe); this.byResult.computeIfAbsent(recipe.result().item().id(), k -> new ArrayList<>()).add(recipe); for (Ingredient ingredient : recipe.ingredientsInUse()) { - for (Holder holder : ingredient.items()) { + for (Holder holder : ingredient.items().stream().distinct().toList()) { this.byIngredient.computeIfAbsent(holder.value(), k -> new ArrayList<>()).add(recipe); } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/RecipeEventListener.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/RecipeEventListener.java index 35b3e4060..f6b0518cb 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/RecipeEventListener.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/RecipeEventListener.java @@ -835,6 +835,7 @@ public class RecipeEventListener implements Listener { @EventHandler(ignoreCancelled = true) public void onSmithingTransform(PrepareSmithingEvent event) { + if (!ConfigManager.enableRecipeSystem()) return; SmithingInventory inventory = event.getInventory(); if (!(inventory.getRecipe() instanceof SmithingTransformRecipe recipe)) return; @@ -872,6 +873,21 @@ public class RecipeEventListener implements Listener { CustomSmithingTransformRecipe transformRecipe = (CustomSmithingTransformRecipe) ceRecipe; ItemStack processed = transformRecipe.assemble(new ItemBuildContext(this.plugin.adapt(player), ContextHolder.EMPTY), this.itemManager.wrap(base)); event.setResult(processed); + correctSmithingRecipeUsed(inventory, ceRecipe); + } + + private void correctSmithingRecipeUsed(SmithingInventory inventory, Recipe recipe) { + Object holderOrRecipe = recipeManager.getRecipeHolderByRecipe(recipe); + if (holderOrRecipe == null) { + // it's a vanilla recipe but not injected + return; + } + try { + Object resultInventory = Reflections.field$CraftResultInventory$resultInventory.get(inventory); + Reflections.field$ResultContainer$recipeUsed.set(resultInventory, holderOrRecipe); + } catch (ReflectiveOperationException e) { + plugin.logger().warn("Failed to correct used recipe", e); + } } private OptimizedIDItem getOptimizedIDItem(@Nullable ItemStack itemStack) { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java index c7850595e..0e474bebd 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java @@ -4414,6 +4414,18 @@ public class Reflections { ) ); + public static final Class clazz$CraftResultInventory = requireNonNull( + ReflectionUtils.getClazz( + BukkitReflectionUtils.assembleCBClass("inventory.CraftResultInventory") + ) + ); + + public static final Field field$CraftResultInventory$resultInventory = requireNonNull( + ReflectionUtils.getDeclaredField( + clazz$CraftResultInventory, clazz$Container, 0 + ) + ); + // 1.20.5+ public static final Method method$ItemStack$hurtAndBreak = ReflectionUtils.getMethod( 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 cda1f1288..449866c83 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 @@ -124,7 +124,7 @@ public class CustomSmithingTransformRecipe implements Recipe { @Override public Recipe create(Key id, Map arguments) { List base = MiscUtils.getAsStringList(arguments.get("base")); - List addition = MiscUtils.getAsStringList(arguments.get("addition-input")); + List addition = MiscUtils.getAsStringList(arguments.get("addition")); List template = MiscUtils.getAsStringList(arguments.get("template-type")); return new CustomSmithingTransformRecipe<>( id, diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomStoneCuttingRecipe.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomStoneCuttingRecipe.java index 9d95bfe89..bc0cbc901 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomStoneCuttingRecipe.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomStoneCuttingRecipe.java @@ -36,7 +36,7 @@ public class CustomStoneCuttingRecipe extends AbstractGroupedRecipe { @Override public @NotNull Key type() { - return RecipeTypes.STONE_CUTTING; + return RecipeTypes.STONECUTTING; } public Ingredient ingredient() { diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/RecipeTypes.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/RecipeTypes.java index 523470030..4f9b7a047 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/RecipeTypes.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/RecipeTypes.java @@ -16,7 +16,7 @@ public class RecipeTypes { public static final Key BLASTING = Key.of("minecraft:blasting"); public static final Key SMOKING = Key.of("minecraft:smoking"); public static final Key CAMPFIRE_COOKING = Key.of("minecraft:campfire_cooking"); - public static final Key STONE_CUTTING = Key.of("minecraft:stone_cutting"); + public static final Key STONECUTTING = Key.of("minecraft:stonecutting"); public static final Key SMITHING_TRANSFORM = Key.of("minecraft:smithing_transform"); public static final Key SMITHING_TRIM = Key.of("minecraft:smithing_trim"); @@ -27,7 +27,7 @@ public class RecipeTypes { register(SMOKING, CustomSmokingRecipe.FACTORY); register(BLASTING, CustomBlastingRecipe.FACTORY); register(CAMPFIRE_COOKING, CustomCampfireRecipe.FACTORY); - register(STONE_CUTTING, CustomStoneCuttingRecipe.FACTORY); + register(STONECUTTING, CustomStoneCuttingRecipe.FACTORY); register(SMITHING_TRANSFORM, CustomSmithingTransformRecipe.FACTORY); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaStoneCuttingRecipe.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaStoneCuttingRecipe.java index bd032294d..864557c68 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaStoneCuttingRecipe.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaStoneCuttingRecipe.java @@ -19,6 +19,6 @@ public class VanillaStoneCuttingRecipe extends VanillaGroupedRecipe { @Override public Key type() { - return RecipeTypes.STONE_CUTTING; + return RecipeTypes.STONECUTTING; } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java b/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java index 359bd76bd..c67945b43 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java @@ -249,6 +249,7 @@ public abstract class AbstractPackManager implements PackManager { plugin.saveResource("resources/internal/resourcepack/assets/minecraft/textures/font/gui/custom/smelting.png"); plugin.saveResource("resources/internal/resourcepack/assets/minecraft/textures/font/gui/custom/campfire.png"); plugin.saveResource("resources/internal/resourcepack/assets/minecraft/textures/font/gui/custom/stonecutting_recipe.png"); + plugin.saveResource("resources/internal/resourcepack/assets/minecraft/textures/font/gui/custom/smithing_transform_recipe.png"); plugin.saveResource("resources/internal/resourcepack/assets/minecraft/textures/font/gui/custom/cooking_recipe.png"); plugin.saveResource("resources/internal/resourcepack/assets/minecraft/textures/font/gui/custom/crafting_recipe.png"); plugin.saveResource("resources/internal/resourcepack/assets/minecraft/textures/font/gui/custom/no_recipe.png"); diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/gui/category/ItemBrowserManager.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/gui/category/ItemBrowserManager.java index 222136c53..9586fb7ad 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/gui/category/ItemBrowserManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/gui/category/ItemBrowserManager.java @@ -65,6 +65,7 @@ public interface ItemBrowserManager extends Reloadable, ConfigSectionParser { public static String RECIPE_CAMPFIRE_TITLE; public static String RECIPE_CRAFTING_TITLE; public static String RECIPE_STONECUTTING_TITLE; + public static String RECIPE_SMITHING_TRANSFORM_TITLE; public static Key RECIPE_BACK; public static Key RECIPE_EXIT; public static Key RECIPE_NEXT_PAGE_AVAILABLE; @@ -100,9 +101,10 @@ public interface ItemBrowserManager extends Reloadable, ConfigSectionParser { RECIPE_BLASTING_TITLE = getOrThrow(section, "recipe.blasting.title"); RECIPE_SMELTING_TITLE = getOrThrow(section, "recipe.smelting.title"); RECIPE_SMOKING_TITLE = getOrThrow(section, "recipe.smoking.title"); - RECIPE_CAMPFIRE_TITLE = getOrThrow(section, "recipe.campfire.title"); + RECIPE_CAMPFIRE_TITLE = getOrThrow(section, "recipe.campfire-cooking.title"); RECIPE_CRAFTING_TITLE = getOrThrow(section, "recipe.crafting.title"); RECIPE_STONECUTTING_TITLE = getOrThrow(section, "recipe.stonecutting.title"); + RECIPE_SMITHING_TRANSFORM_TITLE = getOrThrow(section, "recipe.smithing-transform.title"); RECIPE_BACK = Key.of(getOrThrow(section, "recipe.page-navigation.return")); RECIPE_EXIT = Key.of(getOrThrow(section, "recipe.page-navigation.exit")); RECIPE_NEXT_PAGE_AVAILABLE = Key.of(getOrThrow(section, "recipe.page-navigation.next.available")); diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/gui/category/ItemBrowserManagerImpl.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/gui/category/ItemBrowserManagerImpl.java index 5742fe02d..2b203b19d 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/gui/category/ItemBrowserManagerImpl.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/gui/category/ItemBrowserManagerImpl.java @@ -349,10 +349,215 @@ public class ItemBrowserManagerImpl implements ItemBrowserManager { openCookingRecipePage(player, (CustomCookingRecipe) recipe, parentGui, recipes, index, depth, canOpenNoRecipePage); return; } - if (recipeType == RecipeTypes.STONE_CUTTING) { + if (recipeType == RecipeTypes.STONECUTTING) { openStoneCuttingRecipePage(player, (CustomStoneCuttingRecipe) recipe, parentGui, recipes, index, depth, canOpenNoRecipePage); return; } + if (recipeType == RecipeTypes.SMITHING_TRANSFORM) { + openSmithingTransformRecipePage(player, (CustomSmithingTransformRecipe) recipe, parentGui, recipes, index, depth, canOpenNoRecipePage); + return; + } + } + + public void openSmithingTransformRecipePage(Player player, CustomSmithingTransformRecipe recipe, Gui parentGui, List> recipes, int index, int depth, boolean canOpenNoRecipePage) { + Key previous = index > 0 ? Constants.RECIPE_PREVIOUS_PAGE_AVAILABLE : Constants.RECIPE_PREVIOUS_PAGE_BLOCK; + Key next = index + 1 < recipes.size() ? Constants.RECIPE_NEXT_PAGE_AVAILABLE : Constants.RECIPE_NEXT_PAGE_BLOCK; + Key result = recipe.result().item().id(); + GuiLayout layout = new GuiLayout( + " ", + " ", + " ABC X ", + " ^ ", + " ", + " < = > " + ) + .addIngredient('X', GuiElement.constant(this.plugin.itemManager().createWrappedItem(result, player).count(recipe.result().count()), (e, c) -> { + c.cancel(); + if (MIDDLE_CLICK.contains(c.type()) && player.isCreativeMode() && player.hasPermission(GET_ITEM_PERMISSION) && c.itemOnCursor() == null) { + Item item = this.plugin.itemManager().createWrappedItem(result, player); + item.count(item.maxStackSize()); + c.setItemOnCursor(item); + return; + } + if (LEFT_CLICK.contains(c.type())) { + List> inRecipes = this.plugin.recipeManager().getRecipeByResult(result); + if (inRecipes == recipes) return; + player.playSound(Constants.SOUND_CLICK_BUTTON); + if (!inRecipes.isEmpty()) { + openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage); + } else if (canOpenNoRecipePage) { + openNoRecipePage(player, result, e.gui(), 0); + } + } else if (RIGHT_CLICK.contains(c.type())) { + List> inRecipes = this.plugin.recipeManager().getRecipeByIngredient(result); + if (inRecipes == recipes) return; + player.playSound(Constants.SOUND_CLICK_BUTTON); + if (!inRecipes.isEmpty()) { + openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage); + } + } + })) + .addIngredient('^', player.hasPermission(GET_ITEM_PERMISSION) ? GuiElement.constant(this.plugin.itemManager().createWrappedItem(Constants.RECIPE_GET_ITEM, player), (e, c) -> { + c.cancel(); + player.playSound(Constants.SOUND_PICK_ITEM); + if (LEFT_CLICK.contains(c.type())) { + player.giveItem(this.plugin.itemManager().createWrappedItem(result, player)); + } else if (RIGHT_CLICK.contains(c.type())) { + Item item = this.plugin.itemManager().createWrappedItem(result, player); + player.giveItem(item.count(item.maxStackSize())); + } + }) : GuiElement.EMPTY) + .addIngredient('=', GuiElement.constant(this.plugin.itemManager().getCustomItem(parentGui != null ? Constants.RECIPE_BACK : Constants.RECIPE_EXIT) + .map(it -> it.buildItem(ItemBuildContext.of(player, ContextHolder.EMPTY))) + .orElseThrow(() -> new GuiElementMissingException("Can't find gui element " + (parentGui != null ? Constants.RECIPE_BACK : Constants.RECIPE_EXIT))), + ((element, click) -> { + click.cancel(); + player.playSound(Constants.SOUND_RETURN_PAGE, 0.25f, 1); + if (parentGui != null) { + parentGui.open(player); + } else { + player.closeInventory(); + } + })) + ) + .addIngredient('>', GuiElement.constant(this.plugin.itemManager() + .getCustomItem(next) + .map(it -> it.buildItem(ItemBuildContext.of(player, ContextHolder.builder() + .withParameter(GuiParameters.CURRENT_PAGE, String.valueOf(index + 1)) + .withParameter(GuiParameters.MAX_PAGE, String.valueOf(recipes.size())) + .build()))) + .orElseThrow(() -> new GuiElementMissingException("Can't find gui element " + next)), (e, c) -> { + c.cancel(); + if (index + 1 < recipes.size()) { + player.playSound(Constants.SOUND_CHANGE_PAGE, 0.25f, 1); + openRecipePage(player, parentGui, recipes, index + 1, depth, canOpenNoRecipePage); + } + })) + .addIngredient('<', GuiElement.constant(this.plugin.itemManager() + .getCustomItem(previous) + .map(it -> it.buildItem(ItemBuildContext.of(player, ContextHolder.builder() + .withParameter(GuiParameters.CURRENT_PAGE, String.valueOf(index + 1)) + .withParameter(GuiParameters.MAX_PAGE, String.valueOf(recipes.size())) + .build()))) + .orElseThrow(() -> new GuiElementMissingException("Can't find gui element " + previous)), (e, c) -> { + c.cancel(); + if (index > 0) { + player.playSound(Constants.SOUND_CHANGE_PAGE, 0.25f, 1); + openRecipePage(player, parentGui, recipes, index - 1, depth, canOpenNoRecipePage); + } + })); + + + List> templates = new ArrayList<>(); + Optional.ofNullable(recipe.template()).ifPresent(it -> { + for (Holder in : it.items()) { + templates.add(this.plugin.itemManager().createWrappedItem(in.value(), player)); + } + }); + layout.addIngredient('A', templates.isEmpty() ? GuiElement.EMPTY : GuiElement.recipeIngredient(templates, (e, c) -> { + c.cancel(); + if (MIDDLE_CLICK.contains(c.type()) && player.isCreativeMode() && player.hasPermission(GET_ITEM_PERMISSION) && c.itemOnCursor() == null) { + Item item = this.plugin.itemManager().createWrappedItem(e.item().id(), player); + item.count(item.maxStackSize()); + c.setItemOnCursor(item); + return; + } + if (LEFT_CLICK.contains(c.type())) { + List> inRecipes = this.plugin.recipeManager().getRecipeByResult(e.item().id()); + if (inRecipes == recipes) return; + player.playSound(Constants.SOUND_CLICK_BUTTON); + if (!inRecipes.isEmpty()) { + openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage); + } else if (canOpenNoRecipePage) { + openNoRecipePage(player, e.item().id(), e.gui(), 0); + } + } else if (RIGHT_CLICK.contains(c.type())) { + List> inRecipes = this.plugin.recipeManager().getRecipeByIngredient(e.item().id()); + if (inRecipes == recipes) return; + player.playSound(Constants.SOUND_CLICK_BUTTON); + if (!inRecipes.isEmpty()) { + openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage); + } + } + })); + + List> bases = new ArrayList<>(); + Optional.ofNullable(recipe.base()).ifPresent(it -> { + for (Holder in : it.items()) { + bases.add(this.plugin.itemManager().createWrappedItem(in.value(), player)); + } + }); + layout.addIngredient('B', bases.isEmpty() ? GuiElement.EMPTY : GuiElement.recipeIngredient(bases, (e, c) -> { + c.cancel(); + if (MIDDLE_CLICK.contains(c.type()) && player.isCreativeMode() && player.hasPermission(GET_ITEM_PERMISSION) && c.itemOnCursor() == null) { + Item item = this.plugin.itemManager().createWrappedItem(e.item().id(), player); + item.count(item.maxStackSize()); + c.setItemOnCursor(item); + return; + } + if (LEFT_CLICK.contains(c.type())) { + List> inRecipes = this.plugin.recipeManager().getRecipeByResult(e.item().id()); + if (inRecipes == recipes) return; + player.playSound(Constants.SOUND_CLICK_BUTTON); + if (!inRecipes.isEmpty()) { + openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage); + } else if (canOpenNoRecipePage) { + openNoRecipePage(player, e.item().id(), e.gui(), 0); + } + } else if (RIGHT_CLICK.contains(c.type())) { + List> inRecipes = this.plugin.recipeManager().getRecipeByIngredient(e.item().id()); + if (inRecipes == recipes) return; + player.playSound(Constants.SOUND_CLICK_BUTTON); + if (!inRecipes.isEmpty()) { + openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage); + } + } + })); + + List> additions = new ArrayList<>(); + Optional.ofNullable(recipe.addition()).ifPresent(it -> { + for (Holder in : it.items()) { + additions.add(this.plugin.itemManager().createWrappedItem(in.value(), player)); + } + }); + layout.addIngredient('C', additions.isEmpty() ? GuiElement.EMPTY : GuiElement.recipeIngredient(additions, (e, c) -> { + c.cancel(); + if (MIDDLE_CLICK.contains(c.type()) && player.isCreativeMode() && player.hasPermission(GET_ITEM_PERMISSION) && c.itemOnCursor() == null) { + Item item = this.plugin.itemManager().createWrappedItem(e.item().id(), player); + item.count(item.maxStackSize()); + c.setItemOnCursor(item); + return; + } + if (LEFT_CLICK.contains(c.type())) { + List> inRecipes = this.plugin.recipeManager().getRecipeByResult(e.item().id()); + if (inRecipes == recipes) return; + player.playSound(Constants.SOUND_CLICK_BUTTON); + if (!inRecipes.isEmpty()) { + openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage); + } else if (canOpenNoRecipePage) { + openNoRecipePage(player, e.item().id(), e.gui(), 0); + } + } else if (RIGHT_CLICK.contains(c.type())) { + List> inRecipes = this.plugin.recipeManager().getRecipeByIngredient(e.item().id()); + if (inRecipes == recipes) return; + player.playSound(Constants.SOUND_CLICK_BUTTON); + if (!inRecipes.isEmpty()) { + openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage); + } + } + })); + + BasicGui.builder() + .layout(layout) + .inventoryClickConsumer(c -> { + if (MOVE_TO_OTHER_INV.contains(c.type()) || DOUBLE_CLICK.contains(c.type())) { + c.cancel(); + } + }) + .build() + .title(AdventureHelper.miniMessage().deserialize(Constants.RECIPE_SMITHING_TRANSFORM_TITLE, ItemBuildContext.of(player, ContextHolder.EMPTY).tagResolvers())) + .refresh() + .open(player); } public void openStoneCuttingRecipePage(Player player, CustomStoneCuttingRecipe recipe, Gui parentGui, List> recipes, int index, int depth, boolean canOpenNoRecipePage) { diff --git a/gradle.properties b/gradle.properties index 4366964ee..eb61f868c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ # Project settings # Rule: [major update].[feature update].[bug fix] -project_version=0.0.36 +project_version=0.0.35 config_version=15 lang_version=3 project_group=net.momirealms @@ -38,7 +38,7 @@ geantyref_version=1.3.16 zstd_version=1.5.6-9 commons_io_version=2.17.0 sparrow_nbt_version=0.3 -sparrow_util_version=0.27 +sparrow_util_version=0.29 fastutil_version=8.5.15 netty_version=4.1.119.Final joml_version=1.10.8 From e70d8703fe3155b89213bd81751cc89e34d50c28 Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Thu, 20 Mar 2025 03:30:41 +0800 Subject: [PATCH 13/15] Update BukkitRecipeManager.java --- .../bukkit/item/recipe/BukkitRecipeManager.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/BukkitRecipeManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/BukkitRecipeManager.java index 7f34ce945..f72c781e2 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/BukkitRecipeManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/BukkitRecipeManager.java @@ -382,9 +382,13 @@ public class BukkitRecipeManager implements RecipeManager { this.byType.computeIfAbsent(recipe.type(), k -> new ArrayList<>()).add(recipe); this.byId.put(id, recipe); this.byResult.computeIfAbsent(recipe.result().item().id(), k -> new ArrayList<>()).add(recipe); + HashSet usedKeys = new HashSet<>(); for (Ingredient ingredient : recipe.ingredientsInUse()) { - for (Holder holder : ingredient.items().stream().distinct().toList()) { - this.byIngredient.computeIfAbsent(holder.value(), k -> new ArrayList<>()).add(recipe); + for (Holder holder : ingredient.items()) { + Key key = holder.value(); + if (usedKeys.add(key)) { + this.byIngredient.computeIfAbsent(key, k -> new ArrayList<>()).add(recipe); + } } } } From 81aa965bea16c52ecdeac2641b6cd0a28c1f2b61 Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Thu, 20 Mar 2025 03:31:24 +0800 Subject: [PATCH 14/15] Update items.yml --- .../main/resources/resources/default/configuration/items.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bukkit-loader/src/main/resources/resources/default/configuration/items.yml b/bukkit-loader/src/main/resources/resources/default/configuration/items.yml index 979df89bc..4d152b824 100644 --- a/bukkit-loader/src/main/resources/resources/default/configuration/items.yml +++ b/bukkit-loader/src/main/resources/resources/default/configuration/items.yml @@ -382,7 +382,7 @@ recipes#11: count: 1 default:topaz_crossbow: type: smithing_transform - base: minecraft:bow + base: minecraft:crossbow addition: default:topaz template-type: default:topaz result: From f22f04a1970d95796b826ee3828e588196b43206 Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Thu, 20 Mar 2025 04:28:06 +0800 Subject: [PATCH 15/15] fix merge nbt tags on 1.20 --- .../item/factory/UniversalItemFactory.java | 5 +- .../item/recipe/BukkitRecipeManager.java | 3 +- .../recipe/CustomSmithingTransformRecipe.java | 69 +++++++++++++++---- .../core/loot/number/NumberProviders.java | 2 +- .../core/registry/BuiltInRegistries.java | 2 + .../craftengine/core/registry/Registries.java | 2 + 6 files changed, 65 insertions(+), 18 deletions(-) diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/UniversalItemFactory.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/UniversalItemFactory.java index 10d657bb0..98cca0794 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/UniversalItemFactory.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/UniversalItemFactory.java @@ -213,6 +213,7 @@ public class UniversalItemFactory extends BukkitItemFactory { @Override protected void maxStackSize(ItemWrapper item, Integer maxStackSize) { + throw new UnsupportedOperationException("This feature is only available on 1.20.5+"); } @Override @@ -229,7 +230,9 @@ public class UniversalItemFactory extends BukkitItemFactory { @Override protected ItemWrapper merge(ItemWrapper item1, ItemWrapper item2) { Object itemStack = ItemObject.copy(item2.getLiteralObject()); - ItemObject.setCustomDataTag(itemStack, ItemObject.getCustomDataTag(item1.getLiteralObject())); + ItemObject.setCustomDataTag(itemStack, TagCompound.clone(ItemObject.getCustomDataTag(item1.getLiteralObject()))); + // one more step than vanilla + TagCompound.merge(ItemObject.getCustomDataTag(itemStack), ItemObject.getCustomDataTag(item2.getLiteralObject()), true, true); return new RTagItemWrapper(new RtagItem(ItemObject.asCraftMirror(itemStack)), item2.count()); } } \ No newline at end of file diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/BukkitRecipeManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/BukkitRecipeManager.java index f72c781e2..729e2a607 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/BukkitRecipeManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/BukkitRecipeManager.java @@ -769,7 +769,8 @@ public class BukkitRecipeManager implements RecipeManager { templateHolders.isEmpty() ? null : Ingredient.of(templateHolders), additionHolders.isEmpty() ? null : Ingredient.of(additionHolders), new CustomRecipeResult<>(new CloneableConstantItem(recipe.result().isCustom() ? Key.of("!internal:custom") : Key.of(recipe.result().id()), result), recipe.result().count()), - List.of(CustomSmithingTransformRecipe.ItemDataProcessor.MERGE_ALL) + true, + List.of() ); SmithingTransformRecipe transformRecipe = new SmithingTransformRecipe(key, result, 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 449866c83..5dbe5a725 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 @@ -7,13 +7,16 @@ import net.momirealms.craftengine.core.item.recipe.input.SmithingInput; import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.registry.BuiltInRegistries; import net.momirealms.craftengine.core.registry.Holder; +import net.momirealms.craftengine.core.registry.Registries; +import net.momirealms.craftengine.core.registry.WritableRegistry; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.MiscUtils; +import net.momirealms.craftengine.core.util.ResourceKey; +import net.momirealms.craftengine.core.util.TriConsumer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.*; -import java.util.function.BiFunction; public class CustomSmithingTransformRecipe implements Recipe { public static final Factory FACTORY = new Factory<>(); @@ -22,6 +25,7 @@ public class CustomSmithingTransformRecipe implements Recipe { private final Ingredient base; private final Ingredient template; private final Ingredient addition; + private final boolean mergeComponents; private final List processors; public CustomSmithingTransformRecipe(Key id, @@ -29,6 +33,7 @@ public class CustomSmithingTransformRecipe implements Recipe { @Nullable Ingredient template, @Nullable Ingredient addition, CustomRecipeResult result, + boolean mergeComponents, List processors ) { this.id = id; @@ -37,6 +42,7 @@ public class CustomSmithingTransformRecipe implements Recipe { this.template = template; this.addition = addition; this.processors = processors; + this.mergeComponents = mergeComponents; } @SuppressWarnings("unchecked") @@ -79,12 +85,12 @@ public class CustomSmithingTransformRecipe implements Recipe { @Override public Key id() { - return id; + return this.id; } @Override public T result(ItemBuildContext context) { - return result.buildItemStack(context); + return this.result.buildItemStack(context); } @SuppressWarnings("unchecked") @@ -92,10 +98,13 @@ public class CustomSmithingTransformRecipe implements Recipe { T result = this.result(context); Item wrappedResult = (Item) CraftEngine.instance().itemManager().wrap(result); Item finalResult = wrappedResult; - for (ItemDataProcessor processor : this.processors) { - finalResult = (Item) processor.apply(base, wrappedResult); + if (this.mergeComponents) { + finalResult = base.merge(wrappedResult); } - return finalResult.getItem(); + for (ItemDataProcessor processor : this.processors) { + processor.accept(base, wrappedResult, finalResult); + } + return finalResult.load(); } @Override @@ -105,7 +114,7 @@ public class CustomSmithingTransformRecipe implements Recipe { @Nullable public Ingredient base() { - return base; + return this.base; } @Nullable @@ -126,10 +135,14 @@ public class CustomSmithingTransformRecipe implements Recipe { List base = MiscUtils.getAsStringList(arguments.get("base")); List addition = MiscUtils.getAsStringList(arguments.get("addition")); List template = MiscUtils.getAsStringList(arguments.get("template-type")); + boolean mergeComponents = (boolean) arguments.getOrDefault("merge-components", true); + @SuppressWarnings("unchecked") + List> processors = (List>) arguments.getOrDefault("post-processors", List.of()); return new CustomSmithingTransformRecipe<>( id, toIngredient(base), toIngredient(template),toIngredient(addition), parseResult(arguments), - List.of(ItemDataProcessor.MERGE_ALL) + mergeComponents, + ItemDataProcessors.fromMapList(processors) ); } @@ -146,16 +159,42 @@ public class CustomSmithingTransformRecipe implements Recipe { } } - @FunctionalInterface - public interface ItemDataProcessor extends BiFunction, Item, Item> { - MergeAllDataProcessor MERGE_ALL = new MergeAllDataProcessor(); + public static class ItemDataProcessors { + + public static List fromMapList(List> mapList) { + if (mapList == null || mapList.isEmpty()) return List.of(); + List functions = new ArrayList<>(); + for (Map map : mapList) { + functions.add(fromMap(map)); + } + return functions; + } + + public static ItemDataProcessor fromMap(Map map) { + String type = (String) map.get("type"); + if (type == null) { + throw new NullPointerException("processor type cannot be null"); + } + Key key = Key.withDefaultNamespace(type, "craftengine"); + ItemDataProcessor.Factory factory = BuiltInRegistries.SMITHING_RESULT_PROCESSOR_FACTORY.getValue(key); + if (factory == null) { + throw new IllegalArgumentException("Unknown processor type: " + type); + } + return factory.create(map); + } + + public static void register(Key key, ItemDataProcessor.Factory factory) { + Holder.Reference holder = ((WritableRegistry) BuiltInRegistries.SMITHING_RESULT_PROCESSOR_FACTORY) + .registerForHolder(new ResourceKey<>(Registries.SMITHING_RESULT_PROCESSOR_FACTORY.location(), key)); + holder.bindValue(factory); + } } - public static class MergeAllDataProcessor implements ItemDataProcessor { + @FunctionalInterface + public interface ItemDataProcessor extends TriConsumer, Item, Item> { - @Override - public Item apply(Item item1, Item item2) { - return item1.merge(item2); + interface Factory { + ItemDataProcessor create(Map arguments); } } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/loot/number/NumberProviders.java b/core/src/main/java/net/momirealms/craftengine/core/loot/number/NumberProviders.java index 9fc14c68e..45ec409e9 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/loot/number/NumberProviders.java +++ b/core/src/main/java/net/momirealms/craftengine/core/loot/number/NumberProviders.java @@ -26,7 +26,7 @@ public class NumberProviders { holder.bindValue(factory); } - static List fromMapList(List> mapList) { + public static List fromMapList(List> mapList) { if (mapList == null || mapList.isEmpty()) return List.of(); List functions = new ArrayList<>(); for (Map map : mapList) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/registry/BuiltInRegistries.java b/core/src/main/java/net/momirealms/craftengine/core/registry/BuiltInRegistries.java index 8f2a53152..a1c907c9d 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/registry/BuiltInRegistries.java +++ b/core/src/main/java/net/momirealms/craftengine/core/registry/BuiltInRegistries.java @@ -4,6 +4,7 @@ import net.momirealms.craftengine.core.block.CustomBlock; import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory; import net.momirealms.craftengine.core.block.properties.PropertyFactory; import net.momirealms.craftengine.core.item.behavior.ItemBehaviorFactory; +import net.momirealms.craftengine.core.item.recipe.CustomSmithingTransformRecipe; import net.momirealms.craftengine.core.item.recipe.RecipeFactory; import net.momirealms.craftengine.core.loot.condition.LootConditionFactory; import net.momirealms.craftengine.core.loot.entry.LootEntryContainerFactory; @@ -43,6 +44,7 @@ public class BuiltInRegistries { public static final Registry FORMULA_FACTORY = createRegistry(Registries.FORMULA_FACTORY); public static final Registry PATH_MATCHER_FACTORY = createRegistry(Registries.PATH_MATCHER_FACTORY); public static final Registry RESOLUTION_FACTORY = createRegistry(Registries.RESOLUTION_FACTORY); + public static final Registry SMITHING_RESULT_PROCESSOR_FACTORY = createRegistry(Registries.SMITHING_RESULT_PROCESSOR_FACTORY); private static Registry createRegistry(ResourceKey> key) { return new MappedRegistry<>(key); diff --git a/core/src/main/java/net/momirealms/craftengine/core/registry/Registries.java b/core/src/main/java/net/momirealms/craftengine/core/registry/Registries.java index 5d8047bf9..3d766235f 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/registry/Registries.java +++ b/core/src/main/java/net/momirealms/craftengine/core/registry/Registries.java @@ -4,6 +4,7 @@ import net.momirealms.craftengine.core.block.CustomBlock; import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory; import net.momirealms.craftengine.core.block.properties.PropertyFactory; import net.momirealms.craftengine.core.item.behavior.ItemBehaviorFactory; +import net.momirealms.craftengine.core.item.recipe.CustomSmithingTransformRecipe; import net.momirealms.craftengine.core.item.recipe.RecipeFactory; import net.momirealms.craftengine.core.loot.condition.LootConditionFactory; import net.momirealms.craftengine.core.loot.entry.LootEntryContainerFactory; @@ -44,4 +45,5 @@ public class Registries { public static final ResourceKey> FORMULA_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("formula_factory")); public static final ResourceKey> PATH_MATCHER_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("path_matcher_factory")); public static final ResourceKey> RESOLUTION_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("resolution_factory")); + public static final ResourceKey> SMITHING_RESULT_PROCESSOR_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("smithing_result_processor_factory")); }