From 9cf6f2818abce369ed02561a78c1c48179c1d93a Mon Sep 17 00:00:00 2001 From: Sollace Date: Fri, 29 Sep 2023 22:39:19 +0100 Subject: [PATCH] Fix a bunch of codec-related stuff --- .../spell/crafting/SpellCraftingRecipe.java | 3 +- .../magic/spell/crafting/TraitIngredient.java | 37 +++++++++---------- .../magic/spell/trait/SpellTraits.java | 36 +++++------------- .../ability/magic/spell/trait/Trait.java | 25 ++++++++++--- .../unicopia/item/URecipes.java | 22 +++++------ 5 files changed, 57 insertions(+), 66 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/crafting/SpellCraftingRecipe.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/crafting/SpellCraftingRecipe.java index 84853bac..cfac436c 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/crafting/SpellCraftingRecipe.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/crafting/SpellCraftingRecipe.java @@ -13,7 +13,6 @@ import com.minelittlepony.unicopia.item.URecipes; import com.minelittlepony.unicopia.util.InventoryUtil; import com.mojang.datafixers.util.Pair; import com.mojang.serialization.Codec; -import com.mojang.serialization.MapCodec; import com.mojang.serialization.codecs.RecordCodecBuilder; import net.minecraft.item.ItemStack; @@ -144,7 +143,7 @@ public class SpellCraftingRecipe implements SpellbookRecipe { public static class Serializer implements RecipeSerializer { private static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( IngredientWithSpell.CODEC.fieldOf("material").forGetter(recipe -> recipe.material), - ((MapCodec)null).forGetter(recipe -> recipe.requiredTraits), + TraitIngredient.CODEC.fieldOf("traits").forGetter(recipe -> recipe.requiredTraits), IngredientWithSpell.CODEC.listOf().fieldOf("ingredients").forGetter(recipe -> recipe.requiredItems), ItemStackWithSpell.CODEC.fieldOf("result").forGetter(recipe -> recipe.output) ).apply(instance, SpellCraftingRecipe::new)); diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/crafting/TraitIngredient.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/crafting/TraitIngredient.java index 83359d6b..9e4ac345 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/crafting/TraitIngredient.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/crafting/TraitIngredient.java @@ -3,16 +3,31 @@ package com.minelittlepony.unicopia.ability.magic.spell.crafting; import java.util.Optional; import java.util.function.Predicate; -import com.google.gson.JsonObject; import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits; +import com.mojang.datafixers.util.Either; +import com.mojang.serialization.Codec; +import com.mojang.serialization.DataResult; +import com.mojang.serialization.codecs.RecordCodecBuilder; import net.minecraft.network.PacketByteBuf; -import net.minecraft.util.JsonHelper; +import net.minecraft.util.dynamic.Codecs; public record TraitIngredient ( Optional min, Optional max ) implements Predicate { + public static final Codec CODEC = Codecs.xor( + SpellTraits.CODEC.flatXmap( + traits -> DataResult.success(new TraitIngredient(Optional.ofNullable(traits), Optional.empty())), + ingredient -> ingredient.min().map(DataResult::success).orElseGet(() -> DataResult.error(() -> "Cannot serialize an empty trait ingredient"))), + RecordCodecBuilder.create(instance -> instance.group( + SpellTraits.CODEC.optionalFieldOf("min").forGetter(TraitIngredient::min), + SpellTraits.CODEC.optionalFieldOf("max").forGetter(TraitIngredient::max) + ).apply(instance, TraitIngredient::new)) + ).flatXmap( + either -> either.left().or(either::right).map(DataResult::success).orElseGet(() -> DataResult.error(() -> "Invalid traits")), + ingredient -> DataResult.success(ingredient.max.isPresent() ? Either.left(ingredient) : Either.right(ingredient)) + ); @Override public boolean test(SpellTraits t) { @@ -29,22 +44,4 @@ public record TraitIngredient ( public static TraitIngredient fromPacket(PacketByteBuf buf) { return new TraitIngredient(SpellTraits.fromPacketOrEmpty(buf), SpellTraits.fromPacketOrEmpty(buf)); } - - public static TraitIngredient fromJson(JsonObject json) { - Optional min = Optional.empty(); - Optional max = Optional.empty(); - - if (json.has("min") || json.has("max")) { - if (json.has("min")) { - min = SpellTraits.fromJson(JsonHelper.getObject(json, "min")); - } - if (json.has("max")) { - max = SpellTraits.fromJson(JsonHelper.getObject(json, "max")); - } - } else { - min = SpellTraits.fromJson(json); - } - - return new TraitIngredient(min, max); - } } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/trait/SpellTraits.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/trait/SpellTraits.java index ae16b248..bd6d31a0 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/trait/SpellTraits.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/trait/SpellTraits.java @@ -17,10 +17,12 @@ import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; -import com.google.gson.JsonObject; import com.minelittlepony.unicopia.Unicopia; import com.minelittlepony.unicopia.client.gui.ItemTraitsTooltipRenderer; import com.minelittlepony.unicopia.util.InventoryUtil; +import com.mojang.datafixers.util.Pair; +import com.mojang.serialization.Codec; +import com.mojang.serialization.DataResult; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; @@ -30,6 +32,7 @@ import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtElement; +import net.minecraft.nbt.NbtOps; import net.minecraft.network.PacketByteBuf; import net.minecraft.text.Text; import net.minecraft.util.Identifier; @@ -42,6 +45,10 @@ public final class SpellTraits implements Iterable> { private static Map REGISTRY = new HashMap<>(); static final Map> ITEMS = new HashMap<>(); + public static final Codec CODEC = Codec.unboundedMap(Trait.CODEC, Codec.FLOAT).flatXmap(map -> { + return fromEntries(map.entrySet().stream()).map(DataResult::success).orElseGet(() -> DataResult.error(() -> "No traits were supplied")); + }, traits -> DataResult.success(traits.traits)); + public static void load(Map newRegistry) { REGISTRY = new HashMap<>(newRegistry); ITEMS.clear(); @@ -244,11 +251,7 @@ public final class SpellTraits implements Iterable> { } public static Optional fromNbt(NbtCompound traits) { - return fromEntries(streamFromNbt(traits)); - } - - public static Optional fromJson(JsonObject traits) { - return fromEntries(streamFromJson(traits)); + return CODEC.decode(NbtOps.INSTANCE, traits).result().map(Pair::getFirst); } public static Optional fromPacketOrEmpty(PacketByteBuf buf) { @@ -256,7 +259,6 @@ public final class SpellTraits implements Iterable> { } public static SpellTraits fromPacket(PacketByteBuf buf) { - Map entries = new HashMap<>(); int count = buf.readInt(); if (count <= 0) { @@ -295,26 +297,6 @@ public final class SpellTraits implements Iterable> { })); } - public static Stream> streamFromNbt(NbtCompound traits) { - return traits.getKeys().stream().map(key -> { - Trait trait = Trait.fromId(key).orElse(null); - if (trait == null || !traits.contains(key, NbtElement.NUMBER_TYPE)) { - return null; - } - return Map.entry(trait, traits.getFloat(key)); - }); - } - - public static Stream> streamFromJson(JsonObject traits) { - return traits.entrySet().stream().map(entry -> { - Trait trait = Trait.fromName(entry.getKey()).orElse(null); - if (trait == null || !entry.getValue().isJsonPrimitive() && !entry.getValue().getAsJsonPrimitive().isNumber()) { - return null; - } - return Map.entry(trait, entry.getValue().getAsJsonPrimitive().getAsFloat()); - }); - } - public static Optional fromEntries(Stream> entries) { var result = collect(entries); diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/trait/Trait.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/trait/Trait.java index 00372e95..72bba977 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/trait/Trait.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/trait/Trait.java @@ -7,7 +7,9 @@ import java.util.stream.Stream; import com.minelittlepony.unicopia.Unicopia; import com.minelittlepony.unicopia.command.CommandArgumentEnum; +import com.mojang.datafixers.util.Either; import com.mojang.serialization.Codec; +import com.mojang.serialization.DataResult; import net.minecraft.command.argument.EnumArgumentType; import net.minecraft.item.Item; @@ -18,6 +20,7 @@ import net.minecraft.text.*; import net.minecraft.util.Formatting; import net.minecraft.util.Identifier; import net.minecraft.util.StringIdentifiable; +import net.minecraft.util.dynamic.Codecs; public enum Trait implements CommandArgumentEnum { /** @@ -60,8 +63,17 @@ public enum Trait implements CommandArgumentEnum { POISON(TraitGroup.DARKNESS), BLOOD(TraitGroup.DARKNESS); - private static final Map REGISTRY = Arrays.stream(values()).collect(Collectors.toMap(Trait::name, Function.identity())); private static final Map IDS = Arrays.stream(values()).collect(Collectors.toMap(Trait::getId, Function.identity())); + @Deprecated + private static final EnumCodec NAME_CODEC = StringIdentifiable.createCodec(Trait::values); + @Deprecated + private static final EnumCodec ID_CODEC = StringIdentifiable.createCodec(Trait::values, i -> "unicopia:" + i); + + public static final Codec CODEC = Codecs.xor(NAME_CODEC, ID_CODEC).flatXmap( + either -> either.left().or(either::right).map(DataResult::success).orElseGet(() -> DataResult.error(() -> "Not a proper trait")), + trait -> DataResult.success(Either.right(trait)) + ); + private final Identifier id; private final Identifier sprite; private final TraitGroup group; @@ -149,25 +161,26 @@ public enum Trait implements CommandArgumentEnum { .flatMap(Optional::stream); } + @Deprecated public static Optional fromId(Identifier id) { - return Optional.ofNullable(IDS.getOrDefault(id, null)); + return Optional.ofNullable(ID_CODEC.byId(id.toString())); } + @Deprecated public static Optional fromId(String name) { return Optional.ofNullable(Identifier.tryParse(name)).flatMap(Trait::fromId); } + @Deprecated public static Optional fromName(String name) { - return Optional.ofNullable(REGISTRY.getOrDefault(name.toUpperCase(), null)); + return Optional.ofNullable(NAME_CODEC.byId(name.toUpperCase())); } public static EnumArgumentType argument() { return new ArgumentType(); } - public static final class ArgumentType extends EnumArgumentType { - static final Codec CODEC = StringIdentifiable.createCodec(Trait::values); - + public static class ArgumentType extends EnumArgumentType { protected ArgumentType() { super(CODEC, Trait::values); } diff --git a/src/main/java/com/minelittlepony/unicopia/item/URecipes.java b/src/main/java/com/minelittlepony/unicopia/item/URecipes.java index 08a3e7d7..14648158 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/URecipes.java +++ b/src/main/java/com/minelittlepony/unicopia/item/URecipes.java @@ -17,17 +17,6 @@ import net.minecraft.util.Identifier; import net.minecraft.util.collection.DefaultedList; public interface URecipes { - RecipeType SPELLBOOK = RecipeType.register("unicopia:spellbook"); - - RecipeSerializer ZAP_APPLE_SERIALIZER = RecipeSerializer.register("unicopia:crafting_zap_apple", new ZapAppleRecipe.Serializer()); - RecipeSerializer GLOWING_SERIALIZER = RecipeSerializer.register("unicopia:crafting_glowing", new SpecialRecipeSerializer<>(GlowingRecipe::new)); - RecipeSerializer JAR_INSERT_SERIALIZER = RecipeSerializer.register("unicopia:jar_insert", new SpecialRecipeSerializer<>(JarInsertRecipe::new)); - RecipeSerializer JAR_EXTRACT_SERIALIZER = RecipeSerializer.register("unicopia:jar_extract", new SpecialRecipeSerializer<>(JarExtractRecipe::new)); - RecipeSerializer CRAFTING_MAGICAL_SERIALIZER = RecipeSerializer.register("unicopia:crafting_magical", new SpellShapedCraftingRecipe.Serializer()); - RecipeSerializer TRAIT_REQUIREMENT = RecipeSerializer.register("unicopia:spellbook/crafting", new SpellCraftingRecipe.Serializer()); - RecipeSerializer TRAIT_COMBINING = RecipeSerializer.register("unicopia:spellbook/combining", new SpellEnhancingRecipe.Serializer()); - RecipeSerializer SPELL_DUPLICATING = RecipeSerializer.register("unicopia:spellbook/duplicating", new SpellDuplicatingRecipe.Serializer()); - Codec> SHAPELESS_RECIPE_INGREDIENTS_CODEC = Ingredient.DISALLOW_EMPTY_CODEC.listOf().flatXmap(ingredients -> { Ingredient[] ingredients2 = ingredients.stream().filter(ingredient -> !ingredient.isEmpty()).toArray(Ingredient[]::new); if (ingredients2.length == 0) { @@ -39,6 +28,17 @@ public interface URecipes { return DataResult.success(DefaultedList.copyOf(Ingredient.EMPTY, ingredients2)); }, DataResult::success); + RecipeType SPELLBOOK = RecipeType.register("unicopia:spellbook"); + + RecipeSerializer ZAP_APPLE_SERIALIZER = RecipeSerializer.register("unicopia:crafting_zap_apple", new ZapAppleRecipe.Serializer()); + RecipeSerializer GLOWING_SERIALIZER = RecipeSerializer.register("unicopia:crafting_glowing", new SpecialRecipeSerializer<>(GlowingRecipe::new)); + RecipeSerializer JAR_INSERT_SERIALIZER = RecipeSerializer.register("unicopia:jar_insert", new SpecialRecipeSerializer<>(JarInsertRecipe::new)); + RecipeSerializer JAR_EXTRACT_SERIALIZER = RecipeSerializer.register("unicopia:jar_extract", new SpecialRecipeSerializer<>(JarExtractRecipe::new)); + RecipeSerializer CRAFTING_MAGICAL_SERIALIZER = RecipeSerializer.register("unicopia:crafting_magical", new SpellShapedCraftingRecipe.Serializer()); + RecipeSerializer TRAIT_REQUIREMENT = RecipeSerializer.register("unicopia:spellbook/crafting", new SpellCraftingRecipe.Serializer()); + RecipeSerializer TRAIT_COMBINING = RecipeSerializer.register("unicopia:spellbook/combining", new SpellEnhancingRecipe.Serializer()); + RecipeSerializer SPELL_DUPLICATING = RecipeSerializer.register("unicopia:spellbook/duplicating", new SpellDuplicatingRecipe.Serializer()); + static void bootstrap() { LootTableEvents.MODIFY.register((res, manager, id, supplier, setter) -> { if (!"minecraft".contentEquals(id.getNamespace())) {