Fix a bunch of codec-related stuff

This commit is contained in:
Sollace 2023-09-29 22:39:19 +01:00
parent 7c9071a321
commit ef5e26124e
No known key found for this signature in database
GPG key ID: E52FACE7B5C773DB
5 changed files with 57 additions and 66 deletions

View file

@ -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<SpellCraftingRecipe> {
private static final Codec<SpellCraftingRecipe> CODEC = RecordCodecBuilder.<SpellCraftingRecipe>create(instance -> instance.group(
IngredientWithSpell.CODEC.fieldOf("material").forGetter(recipe -> recipe.material),
((MapCodec<TraitIngredient>)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));

View file

@ -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<SpellTraits> min,
Optional<SpellTraits> max
) implements Predicate<SpellTraits> {
public static final Codec<TraitIngredient> 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.<TraitIngredient>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<SpellTraits> min = Optional.empty();
Optional<SpellTraits> 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);
}
}

View file

@ -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<Map.Entry<Trait, Float>> {
private static Map<Identifier, SpellTraits> REGISTRY = new HashMap<>();
static final Map<Trait, List<Item>> ITEMS = new HashMap<>();
public static final Codec<SpellTraits> 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<Identifier, SpellTraits> newRegistry) {
REGISTRY = new HashMap<>(newRegistry);
ITEMS.clear();
@ -244,11 +251,7 @@ public final class SpellTraits implements Iterable<Map.Entry<Trait, Float>> {
}
public static Optional<SpellTraits> fromNbt(NbtCompound traits) {
return fromEntries(streamFromNbt(traits));
}
public static Optional<SpellTraits> fromJson(JsonObject traits) {
return fromEntries(streamFromJson(traits));
return CODEC.decode(NbtOps.INSTANCE, traits).result().map(Pair::getFirst);
}
public static Optional<SpellTraits> fromPacketOrEmpty(PacketByteBuf buf) {
@ -256,7 +259,6 @@ public final class SpellTraits implements Iterable<Map.Entry<Trait, Float>> {
}
public static SpellTraits fromPacket(PacketByteBuf buf) {
Map<Trait, Float> entries = new HashMap<>();
int count = buf.readInt();
if (count <= 0) {
@ -295,26 +297,6 @@ public final class SpellTraits implements Iterable<Map.Entry<Trait, Float>> {
}));
}
public static Stream<Map.Entry<Trait, Float>> 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<Map.Entry<Trait, Float>> 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<SpellTraits> fromEntries(Stream<Map.Entry<Trait, Float>> entries) {
var result = collect(entries);

View file

@ -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<Trait> {
/**
@ -60,8 +63,17 @@ public enum Trait implements CommandArgumentEnum<Trait> {
POISON(TraitGroup.DARKNESS),
BLOOD(TraitGroup.DARKNESS);
private static final Map<String, Trait> REGISTRY = Arrays.stream(values()).collect(Collectors.toMap(Trait::name, Function.identity()));
private static final Map<Identifier, Trait> IDS = Arrays.stream(values()).collect(Collectors.toMap(Trait::getId, Function.identity()));
@Deprecated
private static final EnumCodec<Trait> NAME_CODEC = StringIdentifiable.createCodec(Trait::values);
@Deprecated
private static final EnumCodec<Trait> ID_CODEC = StringIdentifiable.createCodec(Trait::values, i -> "unicopia:" + i);
public static final Codec<Trait> 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<Trait> {
.flatMap(Optional::stream);
}
@Deprecated
public static Optional<Trait> fromId(Identifier id) {
return Optional.ofNullable(IDS.getOrDefault(id, null));
return Optional.ofNullable(ID_CODEC.byId(id.toString()));
}
@Deprecated
public static Optional<Trait> fromId(String name) {
return Optional.ofNullable(Identifier.tryParse(name)).flatMap(Trait::fromId);
}
@Deprecated
public static Optional<Trait> fromName(String name) {
return Optional.ofNullable(REGISTRY.getOrDefault(name.toUpperCase(), null));
return Optional.ofNullable(NAME_CODEC.byId(name.toUpperCase()));
}
public static EnumArgumentType<Trait> argument() {
return new ArgumentType();
}
public static final class ArgumentType extends EnumArgumentType<Trait> {
static final Codec<Trait> CODEC = StringIdentifiable.createCodec(Trait::values);
public static class ArgumentType extends EnumArgumentType<Trait> {
protected ArgumentType() {
super(CODEC, Trait::values);
}

View file

@ -17,17 +17,6 @@ import net.minecraft.util.Identifier;
import net.minecraft.util.collection.DefaultedList;
public interface URecipes {
RecipeType<SpellbookRecipe> SPELLBOOK = RecipeType.register("unicopia:spellbook");
RecipeSerializer<ZapAppleRecipe> ZAP_APPLE_SERIALIZER = RecipeSerializer.register("unicopia:crafting_zap_apple", new ZapAppleRecipe.Serializer());
RecipeSerializer<GlowingRecipe> GLOWING_SERIALIZER = RecipeSerializer.register("unicopia:crafting_glowing", new SpecialRecipeSerializer<>(GlowingRecipe::new));
RecipeSerializer<JarInsertRecipe> JAR_INSERT_SERIALIZER = RecipeSerializer.register("unicopia:jar_insert", new SpecialRecipeSerializer<>(JarInsertRecipe::new));
RecipeSerializer<JarExtractRecipe> JAR_EXTRACT_SERIALIZER = RecipeSerializer.register("unicopia:jar_extract", new SpecialRecipeSerializer<>(JarExtractRecipe::new));
RecipeSerializer<ShapedRecipe> CRAFTING_MAGICAL_SERIALIZER = RecipeSerializer.register("unicopia:crafting_magical", new SpellShapedCraftingRecipe.Serializer());
RecipeSerializer<SpellCraftingRecipe> TRAIT_REQUIREMENT = RecipeSerializer.register("unicopia:spellbook/crafting", new SpellCraftingRecipe.Serializer());
RecipeSerializer<SpellEnhancingRecipe> TRAIT_COMBINING = RecipeSerializer.register("unicopia:spellbook/combining", new SpellEnhancingRecipe.Serializer());
RecipeSerializer<SpellDuplicatingRecipe> SPELL_DUPLICATING = RecipeSerializer.register("unicopia:spellbook/duplicating", new SpellDuplicatingRecipe.Serializer());
Codec<DefaultedList<Ingredient>> 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<SpellbookRecipe> SPELLBOOK = RecipeType.register("unicopia:spellbook");
RecipeSerializer<ZapAppleRecipe> ZAP_APPLE_SERIALIZER = RecipeSerializer.register("unicopia:crafting_zap_apple", new ZapAppleRecipe.Serializer());
RecipeSerializer<GlowingRecipe> GLOWING_SERIALIZER = RecipeSerializer.register("unicopia:crafting_glowing", new SpecialRecipeSerializer<>(GlowingRecipe::new));
RecipeSerializer<JarInsertRecipe> JAR_INSERT_SERIALIZER = RecipeSerializer.register("unicopia:jar_insert", new SpecialRecipeSerializer<>(JarInsertRecipe::new));
RecipeSerializer<JarExtractRecipe> JAR_EXTRACT_SERIALIZER = RecipeSerializer.register("unicopia:jar_extract", new SpecialRecipeSerializer<>(JarExtractRecipe::new));
RecipeSerializer<ShapedRecipe> CRAFTING_MAGICAL_SERIALIZER = RecipeSerializer.register("unicopia:crafting_magical", new SpellShapedCraftingRecipe.Serializer());
RecipeSerializer<SpellCraftingRecipe> TRAIT_REQUIREMENT = RecipeSerializer.register("unicopia:spellbook/crafting", new SpellCraftingRecipe.Serializer());
RecipeSerializer<SpellEnhancingRecipe> TRAIT_COMBINING = RecipeSerializer.register("unicopia:spellbook/combining", new SpellEnhancingRecipe.Serializer());
RecipeSerializer<SpellDuplicatingRecipe> 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())) {