diff --git a/build.gradle b/build.gradle index e7317a3848a..df63b834f2a 100644 --- a/build.gradle +++ b/build.gradle @@ -350,7 +350,10 @@ runs { data { with commonRunProperties programArguments = [ - '--mod', 'ae2', '--all', '--output', file('src/generated/resources/'), "--existing", file("src/main/resources") + '--mod', 'ae2', + '--all', + '--output', file('src/generated/resources/').absolutePath, + '--existing', file('src/main/resources').absolutePath ] } guideexport { diff --git a/src/main/java/appeng/datagen/providers/recipes/EntropyRecipes.java b/src/main/java/appeng/datagen/providers/recipes/EntropyRecipes.java index 5d4dfa71cb2..f628c5723e7 100644 --- a/src/main/java/appeng/datagen/providers/recipes/EntropyRecipes.java +++ b/src/main/java/appeng/datagen/providers/recipes/EntropyRecipes.java @@ -46,59 +46,59 @@ public void buildRecipes(RecipeOutput consumer) { private void buildCoolRecipes(RecipeOutput consumer) { - EntropyRecipeBuilder.cool(AppEng.makeId("entropy/cool/flowing_water_snowball")) + EntropyRecipeBuilder.cool() .setInputFluid(Fluids.FLOWING_WATER) .setDrops(new ItemStack(Items.SNOWBALL)) - .save(consumer); + .save(consumer, AppEng.makeId("entropy/cool/flowing_water_snowball")); - EntropyRecipeBuilder.cool(AppEng.makeId("entropy/cool/grass_block_dirt")) + EntropyRecipeBuilder.cool() .setInputBlock(Blocks.GRASS_BLOCK) .setOutputBlock(Blocks.DIRT) - .save(consumer); + .save(consumer, AppEng.makeId("entropy/cool/grass_block_dirt")); - EntropyRecipeBuilder.cool(AppEng.makeId("entropy/cool/lava_obsidian")) + EntropyRecipeBuilder.cool() .setInputFluid(Fluids.LAVA) .setOutputBlock(Blocks.OBSIDIAN) - .save(consumer); + .save(consumer, AppEng.makeId("entropy/cool/lava_obsidian")); - EntropyRecipeBuilder.cool(AppEng.makeId("entropy/cool/stone_bricks_cracked_stone_bricks")) + EntropyRecipeBuilder.cool() .setInputBlock(Blocks.STONE_BRICKS) .setOutputBlock(Blocks.CRACKED_STONE_BRICKS) - .save(consumer); + .save(consumer, AppEng.makeId("entropy/cool/stone_bricks_cracked_stone_bricks")); - EntropyRecipeBuilder.cool(AppEng.makeId("entropy/cool/stone_cobblestone")) + EntropyRecipeBuilder.cool() .setInputBlock(Blocks.STONE) .setOutputBlock(Blocks.COBBLESTONE) - .save(consumer); + .save(consumer, AppEng.makeId("entropy/cool/stone_cobblestone")); - EntropyRecipeBuilder.cool(AppEng.makeId("entropy/cool/water_ice")) + EntropyRecipeBuilder.cool() .setInputFluid(Fluids.WATER) .setOutputBlock(Blocks.ICE) - .save(consumer); + .save(consumer, AppEng.makeId("entropy/cool/water_ice")); } private void buildHeatRecipes(RecipeOutput consumer) { - EntropyRecipeBuilder.heat(AppEng.makeId("entropy/heat/cobblestone_stone")) + EntropyRecipeBuilder.heat() .setInputBlock(Blocks.COBBLESTONE) .setOutputBlock(Blocks.STONE) - .save(consumer); + .save(consumer, AppEng.makeId("entropy/heat/cobblestone_stone")); - EntropyRecipeBuilder.heat(AppEng.makeId("entropy/heat/ice_water")) + EntropyRecipeBuilder.heat() .setInputBlock(Blocks.ICE) .setOutputFluid(Fluids.WATER) - .save(consumer); + .save(consumer, AppEng.makeId("entropy/heat/ice_water")); - EntropyRecipeBuilder.heat(AppEng.makeId("entropy/heat/snow_water")) + EntropyRecipeBuilder.heat() .setInputBlock(Blocks.SNOW) .setOutputFluid(Fluids.FLOWING_WATER) - .save(consumer); + .save(consumer, AppEng.makeId("entropy/heat/snow_water")); - EntropyRecipeBuilder.heat(AppEng.makeId("entropy/heat/water_air")) + EntropyRecipeBuilder.heat() .setInputFluid(Fluids.WATER) .setOutputBlock(Blocks.AIR) - .save(consumer); + .save(consumer, AppEng.makeId("entropy/heat/water_air")); } diff --git a/src/main/java/appeng/integration/modules/jei/FacadeRegistryPlugin.java b/src/main/java/appeng/integration/modules/jei/FacadeRegistryPlugin.java index 42903ea6a1d..7a4fb197e7a 100644 --- a/src/main/java/appeng/integration/modules/jei/FacadeRegistryPlugin.java +++ b/src/main/java/appeng/integration/modules/jei/FacadeRegistryPlugin.java @@ -89,11 +89,6 @@ public List getRecipes(IRecipeCategory recipeCategory, IFocus fo } private ShapedRecipe make(ItemStack textureItem, ItemStack cableAnchor, ItemStack result) { - // This id should only be used within JEI and not really matter - var itemId = BuiltInRegistries.ITEM.getKey(textureItem.getItem()); - ResourceLocation id = new ResourceLocation(AppEng.MOD_ID, - "facade/" + itemId.getNamespace() + "/" + itemId.getPath()); - NonNullList ingredients = NonNullList.withSize(9, Ingredient.EMPTY); ingredients.set(1, Ingredient.of(cableAnchor)); ingredients.set(3, Ingredient.of(cableAnchor)); @@ -104,7 +99,7 @@ private ShapedRecipe make(ItemStack textureItem, ItemStack cableAnchor, ItemStac var output = result.copy(); output.setCount(4); - return new ShapedRecipe(id, "", CraftingBookCategory.MISC, 3, 3, ingredients, output); + return new ShapedRecipe("", CraftingBookCategory.MISC, 3, 3, ingredients, output); } @Override diff --git a/src/main/java/appeng/recipes/entropy/EntropyRecipeBuilder.java b/src/main/java/appeng/recipes/entropy/EntropyRecipeBuilder.java index fd9ab9df73a..050e2b6be82 100644 --- a/src/main/java/appeng/recipes/entropy/EntropyRecipeBuilder.java +++ b/src/main/java/appeng/recipes/entropy/EntropyRecipeBuilder.java @@ -27,6 +27,8 @@ import com.google.common.base.Preconditions; import com.google.gson.JsonObject; +import com.mojang.serialization.JsonOps; +import net.minecraft.Util; import net.minecraft.advancements.AdvancementHolder; import net.minecraft.data.recipes.RecipeOutput; import org.jetbrains.annotations.Nullable; @@ -39,7 +41,6 @@ import net.minecraft.world.level.material.Fluid; public class EntropyRecipeBuilder { - private ResourceLocation id; private EntropyMode mode; private Block inputBlock; @@ -56,18 +57,12 @@ public class EntropyRecipeBuilder { private boolean outputFluidKeep; private List drops = Collections.emptyList(); - public static EntropyRecipeBuilder cool(ResourceLocation id) { - return new EntropyRecipeBuilder().setId(id).setMode(EntropyMode.COOL); + public static EntropyRecipeBuilder cool() { + return new EntropyRecipeBuilder().setMode(EntropyMode.COOL); } - public static EntropyRecipeBuilder heat(ResourceLocation id) { - return new EntropyRecipeBuilder().setId(id).setMode(EntropyMode.HEAT); - } - - public EntropyRecipeBuilder setId(ResourceLocation id) { - Preconditions.checkArgument(id != null); - this.id = id; - return this; + public static EntropyRecipeBuilder heat() { + return new EntropyRecipeBuilder().setMode(EntropyMode.HEAT); } public EntropyRecipeBuilder setMode(EntropyMode mode) { @@ -169,7 +164,6 @@ public EntropyRecipeBuilder addFluidStateAppliers(StateApplier applier) { } public EntropyRecipe build() { - Preconditions.checkState(id != null); Preconditions.checkState(mode != null); Preconditions.checkState(inputBlock != null || inputFluid != null, "Either inputBlock or inputFluid needs to be not null"); @@ -179,14 +173,21 @@ public EntropyRecipe build() { drops); } - public void save(RecipeOutput consumer) { - consumer.accept(new Result()); + public void save(RecipeOutput consumer, ResourceLocation id) { + consumer.accept(new Result(id)); } private class Result implements FinishedRecipe { + private final ResourceLocation id; + + public Result(ResourceLocation id) { + this.id = id; + } + @Override public void serializeRecipeData(JsonObject json) { - EntropyRecipeSerializer.INSTANCE.toJson(build(), json); + Util.getOrThrow(EntropyRecipeSerializer.INSTANCE.codec() + .encode(build(), JsonOps.INSTANCE, json), IllegalStateException::new); } @Override diff --git a/src/main/java/appeng/recipes/entropy/EntropyRecipeSerializer.java b/src/main/java/appeng/recipes/entropy/EntropyRecipeSerializer.java index fb0dbf0b67a..148d3e3ec05 100644 --- a/src/main/java/appeng/recipes/entropy/EntropyRecipeSerializer.java +++ b/src/main/java/appeng/recipes/entropy/EntropyRecipeSerializer.java @@ -28,6 +28,9 @@ import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.minecraft.util.ExtraCodecs; import org.jetbrains.annotations.Nullable; import net.minecraft.core.Registry; @@ -46,15 +49,24 @@ public class EntropyRecipeSerializer implements RecipeSerializer public static final EntropyRecipeSerializer INSTANCE = new EntropyRecipeSerializer(); + private static final Codec CODEC = ExtraCodecs.adaptJsonSerializer( + EntropyRecipeSerializer::fromJson, + EntropyRecipeSerializer::toJson + ); + private EntropyRecipeSerializer() { } @Override - public EntropyRecipe fromJson(ResourceLocation recipeId, JsonObject json) { + public Codec codec() { + return CODEC; + } + + private static EntropyRecipe fromJson(JsonElement jsonEl) { + var json = jsonEl.getAsJsonObject(); EntropyRecipeBuilder builder = new EntropyRecipeBuilder(); // Set id and mode - builder.setId(recipeId); builder.setMode(EntropyMode.valueOf(GsonHelper.getAsString(json, "mode").toUpperCase(Locale.ROOT))); //// Parse inputs @@ -136,10 +148,9 @@ private static T getRequiredEntry(Registry registry, String id) { @Nullable @Override - public EntropyRecipe fromNetwork(ResourceLocation recipeId, FriendlyByteBuf buffer) { + public EntropyRecipe fromNetwork(FriendlyByteBuf buffer) { EntropyRecipeBuilder builder = new EntropyRecipeBuilder(); - builder.setId(recipeId); builder.setMode(buffer.readEnum(EntropyMode.class)); if (buffer.readBoolean()) { @@ -295,13 +306,15 @@ private static void parseStateAppliers(StateDefinition stateDefinition, Js }); } - public void toJson(EntropyRecipe recipe, JsonObject json) { + private static JsonElement toJson(EntropyRecipe recipe) { + JsonObject json = new JsonObject(); json.addProperty("mode", recipe.getMode().name().toLowerCase(Locale.ROOT)); json.add("input", serializeInput(recipe)); json.add("output", serializeOutput(recipe)); + return json; } - private JsonObject serializeInput(EntropyRecipe recipe) { + private static JsonObject serializeInput(EntropyRecipe recipe) { var input = new JsonObject(); if (recipe.getInputBlock() != null) { var jsonBlock = new JsonObject(); @@ -319,7 +332,7 @@ private JsonObject serializeInput(EntropyRecipe recipe) { return input; } - private JsonElement serializeOutput(EntropyRecipe recipe) { + private static JsonElement serializeOutput(EntropyRecipe recipe) { var output = new JsonObject(); if (recipe.getOutputBlock() != null) { var jsonBlock = new JsonObject(); @@ -358,7 +371,7 @@ private JsonElement serializeOutput(EntropyRecipe recipe) { return output; } - private void serializeStateMatchers(List matchers, JsonObject json) { + private static void serializeStateMatchers(List matchers, JsonObject json) { if (matchers.isEmpty()) { return; } @@ -389,7 +402,7 @@ private void serializeStateMatchers(List matchers, JsonObject json json.add("properties", properties); } - private void serializeStateAppliers(List> appliers, JsonObject json) { + private static void serializeStateAppliers(List> appliers, JsonObject json) { if (appliers.isEmpty()) { return; } diff --git a/src/main/java/appeng/recipes/game/FacadeRecipe.java b/src/main/java/appeng/recipes/game/FacadeRecipe.java index 7b147bc7bc9..79928bc5178 100644 --- a/src/main/java/appeng/recipes/game/FacadeRecipe.java +++ b/src/main/java/appeng/recipes/game/FacadeRecipe.java @@ -81,7 +81,7 @@ public RecipeSerializer getSerializer() { public static RecipeSerializer getSerializer(FacadeItem facade) { if (SERIALIZER == null) { - SERIALIZER = new SimpleCraftingRecipeSerializer<>((id, category) -> new FacadeRecipe(category, facade)); + SERIALIZER = new SimpleCraftingRecipeSerializer<>((category) -> new FacadeRecipe(category, facade)); } return SERIALIZER; } diff --git a/src/main/java/appeng/recipes/handlers/ChargerRecipe.java b/src/main/java/appeng/recipes/handlers/ChargerRecipe.java index 70c31c5cc53..c8b2d20c1b6 100644 --- a/src/main/java/appeng/recipes/handlers/ChargerRecipe.java +++ b/src/main/java/appeng/recipes/handlers/ChargerRecipe.java @@ -1,7 +1,12 @@ package appeng.recipes.handlers; +import appeng.core.AppEng; +import appeng.init.InitRecipeTypes; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; import net.minecraft.core.NonNullList; import net.minecraft.core.RegistryAccess; +import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.Container; import net.minecraft.world.item.Item; @@ -12,9 +17,6 @@ import net.minecraft.world.item.crafting.RecipeType; import net.minecraft.world.level.Level; -import appeng.core.AppEng; -import appeng.init.InitRecipeTypes; - public class ChargerRecipe implements Recipe { public static final ResourceLocation TYPE_ID = AppEng.makeId("charger"); @@ -24,6 +26,13 @@ public class ChargerRecipe implements Recipe { public final NonNullList ingredients; public final Item result; + public static final Codec CODEC = RecordCodecBuilder.create(builder -> { + return builder.group( + Ingredient.CODEC_NONEMPTY.fieldOf("ingredient").forGetter(ChargerRecipe::getIngredient), + BuiltInRegistries.ITEM.byNameCodec().fieldOf("result").forGetter(cr -> cr.result) + ).apply(builder, ChargerRecipe::new); + }); + public ChargerRecipe(Ingredient ingredient, Item result) { this.ingredient = ingredient; this.result = result; diff --git a/src/main/java/appeng/recipes/handlers/ChargerRecipeSerializer.java b/src/main/java/appeng/recipes/handlers/ChargerRecipeSerializer.java index 2d09cb7475b..596aa28a951 100644 --- a/src/main/java/appeng/recipes/handlers/ChargerRecipeSerializer.java +++ b/src/main/java/appeng/recipes/handlers/ChargerRecipeSerializer.java @@ -2,6 +2,9 @@ import com.google.gson.JsonObject; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.GsonHelper; @@ -16,16 +19,12 @@ public class ChargerRecipeSerializer implements RecipeSerializer public static final ChargerRecipeSerializer INSTANCE = new ChargerRecipeSerializer(); @Override - public ChargerRecipe fromJson(ResourceLocation recipeId, JsonObject serializedRecipe) { - - Ingredient ingredient = Ingredient.fromJson(serializedRecipe.get("ingredient")); - Item result = ShapedRecipe.itemFromJson(GsonHelper.getAsJsonObject(serializedRecipe, "result")); - - return new ChargerRecipe(ingredient, result); + public Codec codec() { + return ChargerRecipe.CODEC; } @Override - public ChargerRecipe fromNetwork(ResourceLocation recipeId, FriendlyByteBuf buffer) { + public ChargerRecipe fromNetwork(FriendlyByteBuf buffer) { Ingredient ingredient = Ingredient.fromNetwork(buffer); ItemStack result = buffer.readItem(); diff --git a/src/main/java/appeng/recipes/handlers/InscriberRecipe.java b/src/main/java/appeng/recipes/handlers/InscriberRecipe.java index c890dc14016..2c301964415 100644 --- a/src/main/java/appeng/recipes/handlers/InscriberRecipe.java +++ b/src/main/java/appeng/recipes/handlers/InscriberRecipe.java @@ -18,21 +18,46 @@ package appeng.recipes.handlers; +import appeng.core.AppEng; +import appeng.init.InitRecipeTypes; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; import net.minecraft.core.NonNullList; import net.minecraft.core.RegistryAccess; import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.ExtraCodecs; import net.minecraft.world.Container; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.CraftingRecipeCodecs; import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.Recipe; import net.minecraft.world.item.crafting.RecipeSerializer; import net.minecraft.world.item.crafting.RecipeType; import net.minecraft.world.level.Level; -import appeng.core.AppEng; -import appeng.init.InitRecipeTypes; - public class InscriberRecipe implements Recipe { + + private static final Codec MODE_CODEC = ExtraCodecs.stringResolverCodec( + mode -> switch (mode) { + case INSCRIBE -> "inscribe"; + case PRESS -> "press"; + }, + mode -> switch (mode) { + default -> InscriberProcessType.INSCRIBE; + case "press" -> InscriberProcessType.PRESS; + } + ); + + public static final Codec CODEC = RecordCodecBuilder.create( + builder -> builder.group( + Ingredient.CODEC_NONEMPTY.fieldOf("middle").forGetter(ir -> ir.middleInput), + CraftingRecipeCodecs.ITEMSTACK_OBJECT_CODEC.fieldOf("result").forGetter(ir -> ir.output), + Ingredient.CODEC.fieldOf("top").forGetter(ir -> ir.topOptional), + Ingredient.CODEC.fieldOf("bottom").forGetter(ir -> ir.bottomOptional), + MODE_CODEC.fieldOf("mode").forGetter(ir -> ir.processType) + ).apply(builder, InscriberRecipe::new) + ); + public static final ResourceLocation TYPE_ID = AppEng.makeId("inscriber"); public static final RecipeType TYPE = InitRecipeTypes.register(TYPE_ID.toString()); @@ -44,7 +69,7 @@ public class InscriberRecipe implements Recipe { private final InscriberProcessType processType; public InscriberRecipe(Ingredient middleInput, ItemStack output, - Ingredient topOptional, Ingredient bottomOptional, InscriberProcessType processType) { + Ingredient topOptional, Ingredient bottomOptional, InscriberProcessType processType) { this.middleInput = middleInput; this.output = output; this.topOptional = topOptional; diff --git a/src/main/java/appeng/recipes/handlers/InscriberRecipeBuilder.java b/src/main/java/appeng/recipes/handlers/InscriberRecipeBuilder.java index 31a12de0a18..d5d676db2ee 100644 --- a/src/main/java/appeng/recipes/handlers/InscriberRecipeBuilder.java +++ b/src/main/java/appeng/recipes/handlers/InscriberRecipeBuilder.java @@ -82,12 +82,12 @@ public void serializeRecipeData(JsonObject json) { json.add("result", result); var ingredients = new JsonObject(); - ingredients.add("middle", middleInput.toJson()); + ingredients.add("middle", middleInput.toJson(false)); if (topOptional != null) { - ingredients.add("top", topOptional.toJson()); + ingredients.add("top", topOptional.toJson(true)); } if (bottomOptional != null) { - ingredients.add("bottom", bottomOptional.toJson()); + ingredients.add("bottom", bottomOptional.toJson(true)); } json.add("ingredients", ingredients); } diff --git a/src/main/java/appeng/recipes/handlers/InscriberRecipeSerializer.java b/src/main/java/appeng/recipes/handlers/InscriberRecipeSerializer.java index 83ba894de25..cd1bb5d3464 100644 --- a/src/main/java/appeng/recipes/handlers/InscriberRecipeSerializer.java +++ b/src/main/java/appeng/recipes/handlers/InscriberRecipeSerializer.java @@ -20,6 +20,7 @@ import com.google.gson.JsonObject; +import com.mojang.serialization.Codec; import org.jetbrains.annotations.Nullable; import net.minecraft.network.FriendlyByteBuf; @@ -37,48 +38,21 @@ public class InscriberRecipeSerializer implements RecipeSerializer InscriberProcessType.INSCRIBE; - case "press" -> InscriberProcessType.PRESS; - default -> throw new IllegalStateException("Unknown mode for inscriber recipe: " + mode); - }; - - } - @Override - public InscriberRecipe fromJson(ResourceLocation recipeId, JsonObject json) { - - InscriberProcessType mode = getMode(json); - - ItemStack result = ShapedRecipe.itemStackFromJson(GsonHelper.getAsJsonObject(json, "result")); - - // Deserialize the three parts of the input - JsonObject ingredients = GsonHelper.getAsJsonObject(json, "ingredients"); - Ingredient middle = Ingredient.fromJson(ingredients.get("middle")); - Ingredient top = Ingredient.EMPTY; - if (ingredients.has("top")) { - top = Ingredient.fromJson(ingredients.get("top")); - } - Ingredient bottom = Ingredient.EMPTY; - if (ingredients.has("bottom")) { - bottom = Ingredient.fromJson(ingredients.get("bottom")); - } - - return new InscriberRecipe(recipeId, middle, result, top, bottom, mode); + public Codec codec() { + return InscriberRecipe.CODEC; } @Nullable @Override - public InscriberRecipe fromNetwork(ResourceLocation recipeId, FriendlyByteBuf buffer) { + public InscriberRecipe fromNetwork(FriendlyByteBuf buffer) { Ingredient middle = Ingredient.fromNetwork(buffer); ItemStack result = buffer.readItem(); Ingredient top = Ingredient.fromNetwork(buffer); Ingredient bottom = Ingredient.fromNetwork(buffer); InscriberProcessType mode = buffer.readEnum(InscriberProcessType.class); - return new InscriberRecipe(recipeId, middle, result, top, bottom, mode); + return new InscriberRecipe(middle, result, top, bottom, mode); } @Override diff --git a/src/main/java/appeng/recipes/mattercannon/MatterCannonAmmo.java b/src/main/java/appeng/recipes/mattercannon/MatterCannonAmmo.java index 3f2f25b2a81..1b1d9b94ca9 100644 --- a/src/main/java/appeng/recipes/mattercannon/MatterCannonAmmo.java +++ b/src/main/java/appeng/recipes/mattercannon/MatterCannonAmmo.java @@ -18,15 +18,22 @@ package appeng.recipes.mattercannon; +import java.util.ArrayList; +import java.util.List; import java.util.Objects; import java.util.function.Consumer; import com.google.common.base.Preconditions; import com.google.gson.JsonArray; +import com.google.gson.JsonElement; import com.google.gson.JsonObject; +import com.mojang.serialization.DataResult; +import com.mojang.serialization.JsonOps; +import net.minecraft.Util; import net.minecraft.advancements.AdvancementHolder; import net.minecraft.data.recipes.RecipeOutput; +import net.neoforged.neoforge.common.conditions.ICondition; import org.jetbrains.annotations.Nullable; import net.minecraft.core.NonNullList; @@ -127,17 +134,18 @@ public record Ammo(ResourceLocation id, TagKey tag, Ingredient nonTag, float weight) implements FinishedRecipe { public void serializeRecipeData(JsonObject json) { - JsonArray conditions = new JsonArray(); + List conditions = new ArrayList<>(); if (tag != null) { - json.add("ammo", Ingredient.of(tag).toJson()); - conditions.add(CraftingHelper.serialize(new NotCondition( - new TagEmptyCondition(tag.location())))); + json.add("ammo", Ingredient.of(tag).toJson(false)); + conditions.add(new NotCondition( + new TagEmptyCondition(tag.location()))); } else if (nonTag != null) { - json.add("ammo", nonTag.toJson()); + json.add("ammo", nonTag.toJson(false)); } json.addProperty("weight", this.weight); - json.add("conditions", conditions); + var conditionsJson = Util.getOrThrow(ICondition.LIST_CODEC.encodeStart(JsonOps.INSTANCE, conditions), IllegalStateException::new); + json.add("conditions", conditionsJson); } @Override diff --git a/src/main/java/appeng/recipes/mattercannon/MatterCannonAmmoSerializer.java b/src/main/java/appeng/recipes/mattercannon/MatterCannonAmmoSerializer.java index ac08d9b35b5..49a2ff27964 100644 --- a/src/main/java/appeng/recipes/mattercannon/MatterCannonAmmoSerializer.java +++ b/src/main/java/appeng/recipes/mattercannon/MatterCannonAmmoSerializer.java @@ -18,32 +18,35 @@ package appeng.recipes.mattercannon; -import com.google.gson.JsonObject; - -import org.jetbrains.annotations.Nullable; - +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.RecipeSerializer; +import org.jetbrains.annotations.Nullable; public class MatterCannonAmmoSerializer implements RecipeSerializer { public static final MatterCannonAmmoSerializer INSTANCE = new MatterCannonAmmoSerializer(); + private static final Codec CODEC = RecordCodecBuilder.create((builder) -> { + return builder.group( + Ingredient.CODEC_NONEMPTY.fieldOf("ammo").forGetter(MatterCannonAmmo::getAmmo), + Codec.FLOAT.fieldOf("weight").forGetter(MatterCannonAmmo::getWeight) + ).apply(builder, MatterCannonAmmo::new); + }); + private MatterCannonAmmoSerializer() { } @Override - public MatterCannonAmmo fromJson(ResourceLocation recipeId, JsonObject json) { - var ammo = Ingredient.fromJson(json.get("ammo")); - var weight = json.get("weight").getAsFloat(); - return new MatterCannonAmmo(ammo, weight); + public Codec codec() { + return CODEC; } @Nullable @Override - public MatterCannonAmmo fromNetwork(ResourceLocation recipeId, FriendlyByteBuf buffer) { + public MatterCannonAmmo fromNetwork(FriendlyByteBuf buffer) { var ammo = Ingredient.fromNetwork(buffer); var weight = buffer.readFloat(); return new MatterCannonAmmo(ammo, weight); diff --git a/src/main/java/appeng/recipes/transform/TransformCircumstance.java b/src/main/java/appeng/recipes/transform/TransformCircumstance.java index 27394a67d01..dcad5099ea2 100644 --- a/src/main/java/appeng/recipes/transform/TransformCircumstance.java +++ b/src/main/java/appeng/recipes/transform/TransformCircumstance.java @@ -6,19 +6,40 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParseException; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.KeyDispatchCodec; +import com.mojang.serialization.codecs.RecordCodecBuilder; import io.netty.handler.codec.DecoderException; import net.minecraft.core.Holder; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.Registries; import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.chat.FilterMask; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.TagKey; +import net.minecraft.util.ExtraCodecs; +import net.minecraft.util.StringRepresentable; import net.minecraft.world.level.material.Fluid; import net.minecraft.world.level.material.FluidState; +import net.neoforged.neoforge.registries.ForgeRegistries; public class TransformCircumstance { + public static final TransformCircumstance EXPLOSION = new TransformCircumstance("explosion"); + + private static final Codec EXPLOSION_CODEC = Codec.unit(EXPLOSION); + + private static final Codec FLUID_CODEC = RecordCodecBuilder.create(builder -> builder.group( + TagKey.codec(Registries.FLUID).fieldOf("tag").forGetter(f -> f.fluidTag) + ).apply(builder, FluidType::new)); + + public static final Codec CODEC = Codec.STRING.dispatch(t -> t.type, type -> switch(type) { + case "explosion" -> EXPLOSION_CODEC; + case "fluid" -> FLUID_CODEC; + default -> throw new IllegalStateException("Invalid type: " + type); + }); + private final String type; public TransformCircumstance(String type) { diff --git a/src/main/java/appeng/recipes/transform/TransformRecipeBuilder.java b/src/main/java/appeng/recipes/transform/TransformRecipeBuilder.java index 87f9cc261ae..0ced09d5c72 100644 --- a/src/main/java/appeng/recipes/transform/TransformRecipeBuilder.java +++ b/src/main/java/appeng/recipes/transform/TransformRecipeBuilder.java @@ -44,7 +44,7 @@ public void serializeRecipeData(@NotNull JsonObject json) { json.add("result", stackObj); JsonArray inputs = new JsonArray(); - ingredients.forEach(ingredient -> inputs.add(ingredient.toJson())); + ingredients.forEach(ingredient -> inputs.add(ingredient.toJson(false))); json.add("ingredients", inputs); json.add("circumstance", circumstance.toJson()); } diff --git a/src/main/java/appeng/recipes/transform/TransformRecipeSerializer.java b/src/main/java/appeng/recipes/transform/TransformRecipeSerializer.java index 33f4a094d0d..6ec227dac6f 100644 --- a/src/main/java/appeng/recipes/transform/TransformRecipeSerializer.java +++ b/src/main/java/appeng/recipes/transform/TransformRecipeSerializer.java @@ -18,43 +18,49 @@ package appeng.recipes.transform; -import com.google.gson.JsonObject; - -import org.jetbrains.annotations.Nullable; - +import com.mojang.serialization.Codec; +import com.mojang.serialization.DataResult; +import com.mojang.serialization.codecs.RecordCodecBuilder; import net.minecraft.core.NonNullList; import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.FluidTags; -import net.minecraft.util.GsonHelper; +import net.minecraft.util.ExtraCodecs; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.CraftingRecipeCodecs; import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.RecipeSerializer; -import net.minecraft.world.item.crafting.ShapedRecipe; +import org.jetbrains.annotations.Nullable; public class TransformRecipeSerializer implements RecipeSerializer { public static final TransformRecipeSerializer INSTANCE = new TransformRecipeSerializer(); + private static Codec CODEC = RecordCodecBuilder.create(builder -> { + return builder.group( + Ingredient.CODEC_NONEMPTY + .listOf() + .fieldOf("ingredients") + .flatXmap(ingredients -> { + return DataResult.success(NonNullList.of(Ingredient.EMPTY, ingredients.toArray(Ingredient[]::new))); + }, DataResult::success) + .forGetter(r -> r.ingredients), + CraftingRecipeCodecs.ITEMSTACK_OBJECT_CODEC.fieldOf("result").forGetter(r -> r.output), + ExtraCodecs.strictOptionalField(TransformCircumstance.CODEC, "circumstance", TransformCircumstance.fluid(FluidTags.WATER)) + .forGetter(t -> t.circumstance) + ).apply(builder, TransformRecipe::new); + }); + private TransformRecipeSerializer() { } @Override - public TransformRecipe fromJson(ResourceLocation recipeId, JsonObject json) { - NonNullList ingredients = NonNullList.create(); - GsonHelper.getAsJsonArray(json, "ingredients") - .forEach(ingredient -> ingredients.add(Ingredient.fromJson(ingredient))); - - ItemStack result = ShapedRecipe.itemStackFromJson(GsonHelper.getAsJsonObject(json, "result")); - TransformCircumstance circumstance = json.has("circumstance") - ? TransformCircumstance.fromJson(GsonHelper.getAsJsonObject(json, "circumstance")) - : TransformCircumstance.fluid(FluidTags.WATER); - return new TransformRecipe(ingredients, result, circumstance); + public Codec codec() { + return CODEC; } @Nullable @Override - public TransformRecipe fromNetwork(ResourceLocation recipeId, FriendlyByteBuf buffer) { + public TransformRecipe fromNetwork(FriendlyByteBuf buffer) { ItemStack output = buffer.readItem(); int size = buffer.readByte(); diff --git a/src/main/java/appeng/siteexport/SiteExportWriter.java b/src/main/java/appeng/siteexport/SiteExportWriter.java index e290390be4a..f89806ba1d2 100644 --- a/src/main/java/appeng/siteexport/SiteExportWriter.java +++ b/src/main/java/appeng/siteexport/SiteExportWriter.java @@ -24,6 +24,7 @@ import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonWriter; +import net.minecraft.world.item.crafting.RecipeHolder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -167,7 +168,7 @@ public void addFluid(String id, FluidStack fluid, String iconPath) { siteExport.fluids.put(fluidInfo.id, fluidInfo); } - public void addRecipe(CraftingRecipe recipe) { + public void addRecipe(ResourceLocation id, CraftingRecipe recipe) { Map fields = new HashMap<>(); if (recipe instanceof ShapedRecipe shapedRecipe) { fields.put("shapeless", false); @@ -182,12 +183,12 @@ public void addRecipe(CraftingRecipe recipe) { fields.put("resultCount", resultItem.getCount()); fields.put("ingredients", recipe.getIngredients()); - addRecipe(recipe, fields); + addRecipe(id, recipe, fields); } - public void addRecipe(InscriberRecipe recipe) { + public void addRecipe(ResourceLocation id, InscriberRecipe recipe) { var resultItem = recipe.getResultItem(); - addRecipe(recipe, Map.of( + addRecipe(id, recipe, Map.of( "top", recipe.getTopOptional(), "middle", recipe.getMiddleInput(), "bottom", recipe.getBottomOptional(), @@ -196,13 +197,13 @@ public void addRecipe(InscriberRecipe recipe) { "consumesTopAndBottom", recipe.getProcessType() == InscriberProcessType.PRESS)); } - public void addRecipe(AbstractCookingRecipe recipe) { - addRecipe(recipe, Map.of( + public void addRecipe(ResourceLocation id, AbstractCookingRecipe recipe) { + addRecipe(id, recipe, Map.of( "resultItem", recipe.getResultItem(null), "ingredient", recipe.getIngredients().get(0))); } - public void addRecipe(TransformRecipe recipe) { + public void addRecipe(ResourceLocation id, TransformRecipe recipe) { Map circumstanceJson = new HashMap<>(); var circumstance = recipe.circumstance; @@ -221,58 +222,56 @@ public void addRecipe(TransformRecipe recipe) { throw new IllegalStateException("Unknown circumstance: " + circumstance.toJson()); } - addRecipe(recipe, Map.of( + addRecipe(id, recipe, Map.of( "resultItem", recipe.getResultItem(null), "ingredients", recipe.getIngredients(), "circumstance", circumstanceJson)); } - public void addRecipe(EntropyRecipe recipe) { - addRecipe(recipe, Map.of( + public void addRecipe(ResourceLocation id, EntropyRecipe recipe) { + addRecipe(id, recipe, Map.of( "mode", recipe.getMode().name().toLowerCase(Locale.ROOT))); } - public void addRecipe(MatterCannonAmmo recipe) { - addRecipe(recipe, Map.of( + public void addRecipe(ResourceLocation id, MatterCannonAmmo recipe) { + addRecipe(id, recipe, Map.of( "ammo", recipe.getAmmo(), "damage", MatterCannonItem.getDamageFromPenetration(recipe.getWeight()))); } - public void addRecipe(ChargerRecipe recipe) { - addRecipe(recipe, Map.of( + public void addRecipe(ResourceLocation id, ChargerRecipe recipe) { + addRecipe(id, recipe, Map.of( "resultItem", recipe.getResultItem(), "ingredient", recipe.getIngredient())); } - public void addRecipe(SmithingTransformRecipe recipe) { - addRecipe(recipe, Map.of( + public void addRecipe(ResourceLocation id, SmithingTransformRecipe recipe) { + addRecipe(id, recipe, Map.of( "resultItem", recipe.getResultItem(null), "base", recipe.base, "addition", recipe.addition, "template", recipe.template)); } - public void addRecipe(SmithingTrimRecipe recipe) { - addRecipe(recipe, Map.of( + public void addRecipe(ResourceLocation id, SmithingTrimRecipe recipe) { + addRecipe(id, recipe, Map.of( "base", recipe.base, "addition", recipe.addition, "template", recipe.template)); } - public void addRecipe(StonecutterRecipe recipe) { - addRecipe( - recipe, + public void addRecipe(ResourceLocation id, StonecutterRecipe recipe) { + addRecipe(id, recipe, Map.of( "resultItem", recipe.getResultItem(null), "ingredient", recipe.getIngredients().get(0))); } - public void addRecipe(Recipe recipe, Map element) { + public void addRecipe(ResourceLocation id, Recipe recipe, Map element) { // Auto-transform ingredients var jsonElement = GSON.toJsonTree(element); - var id = recipe.getId(); var type = BuiltInRegistries.RECIPE_TYPE.getKey(recipe.getType()).toString(); jsonElement.getAsJsonObject().addProperty("type", type);