[Change] Recipes use Codecs for Serialization now
This commit is contained in:
parent
7e06e9ce3f
commit
7a972fc22f
4 changed files with 162 additions and 160 deletions
|
@ -5,13 +5,14 @@ import org.betterx.bclib.interfaces.AlloyingRecipeWorkstation;
|
||||||
import org.betterx.bclib.interfaces.UnknownReceipBookCategory;
|
import org.betterx.bclib.interfaces.UnknownReceipBookCategory;
|
||||||
import org.betterx.bclib.util.ItemUtil;
|
import org.betterx.bclib.util.ItemUtil;
|
||||||
|
|
||||||
|
import com.mojang.serialization.Codec;
|
||||||
|
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||||
import net.minecraft.core.NonNullList;
|
import net.minecraft.core.NonNullList;
|
||||||
import net.minecraft.core.RegistryAccess;
|
import net.minecraft.core.RegistryAccess;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.network.FriendlyByteBuf;
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.tags.TagKey;
|
import net.minecraft.tags.TagKey;
|
||||||
import net.minecraft.util.GsonHelper;
|
|
||||||
import net.minecraft.world.Container;
|
import net.minecraft.world.Container;
|
||||||
import net.minecraft.world.item.Item;
|
import net.minecraft.world.item.Item;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
@ -25,9 +26,10 @@ import net.minecraft.world.level.Level;
|
||||||
import net.fabricmc.api.EnvType;
|
import net.fabricmc.api.EnvType;
|
||||||
import net.fabricmc.api.Environment;
|
import net.fabricmc.api.Environment;
|
||||||
|
|
||||||
import com.google.gson.JsonArray;
|
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class AlloyingRecipe implements Recipe<Container>, UnknownReceipBookCategory {
|
public class AlloyingRecipe implements Recipe<Container>, UnknownReceipBookCategory {
|
||||||
public final static String GROUP = "alloying";
|
public final static String GROUP = "alloying";
|
||||||
public final static RecipeType<AlloyingRecipe> TYPE = BCLRecipeManager.registerType(BCLib.MOD_ID, GROUP);
|
public final static RecipeType<AlloyingRecipe> TYPE = BCLRecipeManager.registerType(BCLib.MOD_ID, GROUP);
|
||||||
|
@ -38,7 +40,6 @@ public class AlloyingRecipe implements Recipe<Container>, UnknownReceipBookCateg
|
||||||
);
|
);
|
||||||
|
|
||||||
protected final RecipeType<?> type;
|
protected final RecipeType<?> type;
|
||||||
protected final ResourceLocation id;
|
|
||||||
protected final Ingredient primaryInput;
|
protected final Ingredient primaryInput;
|
||||||
protected final Ingredient secondaryInput;
|
protected final Ingredient secondaryInput;
|
||||||
protected final ItemStack output;
|
protected final ItemStack output;
|
||||||
|
@ -47,7 +48,23 @@ public class AlloyingRecipe implements Recipe<Container>, UnknownReceipBookCateg
|
||||||
protected final int smeltTime;
|
protected final int smeltTime;
|
||||||
|
|
||||||
public AlloyingRecipe(
|
public AlloyingRecipe(
|
||||||
ResourceLocation id,
|
List<Ingredient> inputs,
|
||||||
|
String group,
|
||||||
|
ItemStack output,
|
||||||
|
float experience,
|
||||||
|
int smeltTime
|
||||||
|
) {
|
||||||
|
this(
|
||||||
|
group,
|
||||||
|
!inputs.isEmpty() ? inputs.get(0) : null,
|
||||||
|
inputs.size() > 1 ? inputs.get(1) : null,
|
||||||
|
output,
|
||||||
|
experience,
|
||||||
|
smeltTime
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AlloyingRecipe(
|
||||||
String group,
|
String group,
|
||||||
Ingredient primaryInput,
|
Ingredient primaryInput,
|
||||||
Ingredient secondaryInput,
|
Ingredient secondaryInput,
|
||||||
|
@ -56,7 +73,6 @@ public class AlloyingRecipe implements Recipe<Container>, UnknownReceipBookCateg
|
||||||
int smeltTime
|
int smeltTime
|
||||||
) {
|
) {
|
||||||
this.group = group;
|
this.group = group;
|
||||||
this.id = id;
|
|
||||||
this.primaryInput = primaryInput;
|
this.primaryInput = primaryInput;
|
||||||
this.secondaryInput = secondaryInput;
|
this.secondaryInput = secondaryInput;
|
||||||
this.output = output;
|
this.output = output;
|
||||||
|
@ -103,11 +119,6 @@ public class AlloyingRecipe implements Recipe<Container>, UnknownReceipBookCateg
|
||||||
return this.output;
|
return this.output;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ResourceLocation getId() {
|
|
||||||
return this.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RecipeSerializer<?> getSerializer() {
|
public RecipeSerializer<?> getSerializer() {
|
||||||
return SERIALIZER;
|
return SERIALIZER;
|
||||||
|
@ -209,27 +220,19 @@ public class AlloyingRecipe implements Recipe<Container>, UnknownReceipBookCateg
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Serializer implements RecipeSerializer<AlloyingRecipe> {
|
public static class Serializer implements RecipeSerializer<AlloyingRecipe> {
|
||||||
@Override
|
public static final Codec<AlloyingRecipe> CODEC = RecordCodecBuilder.create(instance -> instance.group(
|
||||||
public AlloyingRecipe fromJson(ResourceLocation id, JsonObject json) {
|
Codec.list(Ingredient.CODEC_NONEMPTY)
|
||||||
JsonArray ingredients = GsonHelper.getAsJsonArray(json, "ingredients");
|
.fieldOf("ingredients")
|
||||||
Ingredient primaryInput = Ingredient.fromJson(ingredients.get(0));
|
.forGetter(recipe -> List.of(recipe.primaryInput, recipe.secondaryInput)),
|
||||||
Ingredient secondaryInput = Ingredient.fromJson(ingredients.get(1));
|
Codec.STRING.optionalFieldOf("group", "")
|
||||||
|
.forGetter(recipe -> recipe.group),
|
||||||
String group = GsonHelper.getAsString(json, "group", "");
|
ItemUtil.CODEC_ITEM_STACK_WITH_NBT.fieldOf("result").forGetter(recipe -> recipe.output),
|
||||||
|
Codec.FLOAT.optionalFieldOf("experience", 0f).forGetter(recipe -> recipe.experience),
|
||||||
JsonObject result = GsonHelper.getAsJsonObject(json, "result");
|
Codec.INT.optionalFieldOf("smelttime", 350).forGetter(recipe -> recipe.smeltTime)
|
||||||
ItemStack output = ItemUtil.fromJsonRecipeWithNBT(result);
|
).apply(instance, AlloyingRecipe::new));
|
||||||
if (output == null) {
|
|
||||||
throw new IllegalStateException("Output item does not exists!");
|
|
||||||
}
|
|
||||||
float experience = GsonHelper.getAsFloat(json, "experience", 0.0F);
|
|
||||||
int smeltTime = GsonHelper.getAsInt(json, "smelttime", 350);
|
|
||||||
|
|
||||||
return new AlloyingRecipe(id, group, primaryInput, secondaryInput, output, experience, smeltTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AlloyingRecipe fromNetwork(ResourceLocation id, FriendlyByteBuf packetBuffer) {
|
public AlloyingRecipe fromNetwork(FriendlyByteBuf packetBuffer) {
|
||||||
String group = packetBuffer.readUtf(32767);
|
String group = packetBuffer.readUtf(32767);
|
||||||
Ingredient primary = Ingredient.fromNetwork(packetBuffer);
|
Ingredient primary = Ingredient.fromNetwork(packetBuffer);
|
||||||
Ingredient secondary = Ingredient.fromNetwork(packetBuffer);
|
Ingredient secondary = Ingredient.fromNetwork(packetBuffer);
|
||||||
|
@ -237,7 +240,12 @@ public class AlloyingRecipe implements Recipe<Container>, UnknownReceipBookCateg
|
||||||
float experience = packetBuffer.readFloat();
|
float experience = packetBuffer.readFloat();
|
||||||
int smeltTime = packetBuffer.readVarInt();
|
int smeltTime = packetBuffer.readVarInt();
|
||||||
|
|
||||||
return new AlloyingRecipe(id, group, primary, secondary, output, experience, smeltTime);
|
return new AlloyingRecipe(group, primary, secondary, output, experience, smeltTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Codec<AlloyingRecipe> codec() {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -6,6 +6,8 @@ import org.betterx.bclib.util.ItemUtil;
|
||||||
import org.betterx.worlds.together.tag.v3.CommonItemTags;
|
import org.betterx.worlds.together.tag.v3.CommonItemTags;
|
||||||
import org.betterx.worlds.together.world.event.WorldBootstrap;
|
import org.betterx.worlds.together.world.event.WorldBootstrap;
|
||||||
|
|
||||||
|
import com.mojang.serialization.Codec;
|
||||||
|
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.core.Holder;
|
import net.minecraft.core.Holder;
|
||||||
import net.minecraft.core.NonNullList;
|
import net.minecraft.core.NonNullList;
|
||||||
|
@ -16,7 +18,6 @@ import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.network.FriendlyByteBuf;
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.tags.TagKey;
|
import net.minecraft.tags.TagKey;
|
||||||
import net.minecraft.util.GsonHelper;
|
|
||||||
import net.minecraft.world.Container;
|
import net.minecraft.world.Container;
|
||||||
import net.minecraft.world.InteractionHand;
|
import net.minecraft.world.InteractionHand;
|
||||||
import net.minecraft.world.entity.player.Player;
|
import net.minecraft.world.entity.player.Player;
|
||||||
|
@ -53,7 +54,6 @@ public class AnvilRecipe implements Recipe<Container>, UnknownReceipBookCategory
|
||||||
//we call this to make sure that TYPE is initialized
|
//we call this to make sure that TYPE is initialized
|
||||||
}
|
}
|
||||||
|
|
||||||
private final ResourceLocation id;
|
|
||||||
private final Ingredient input;
|
private final Ingredient input;
|
||||||
private final ItemStack output;
|
private final ItemStack output;
|
||||||
private final int damage;
|
private final int damage;
|
||||||
|
@ -62,7 +62,6 @@ public class AnvilRecipe implements Recipe<Container>, UnknownReceipBookCategory
|
||||||
private final int inputCount;
|
private final int inputCount;
|
||||||
|
|
||||||
public AnvilRecipe(
|
public AnvilRecipe(
|
||||||
ResourceLocation identifier,
|
|
||||||
Ingredient input,
|
Ingredient input,
|
||||||
ItemStack output,
|
ItemStack output,
|
||||||
int inputCount,
|
int inputCount,
|
||||||
|
@ -70,7 +69,6 @@ public class AnvilRecipe implements Recipe<Container>, UnknownReceipBookCategory
|
||||||
int anvilLevel,
|
int anvilLevel,
|
||||||
int damage
|
int damage
|
||||||
) {
|
) {
|
||||||
this.id = identifier;
|
|
||||||
this.input = input;
|
this.input = input;
|
||||||
this.output = output;
|
this.output = output;
|
||||||
this.toolLevel = toolLevel;
|
this.toolLevel = toolLevel;
|
||||||
|
@ -214,11 +212,6 @@ public class AnvilRecipe implements Recipe<Container>, UnknownReceipBookCategory
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ResourceLocation getId() {
|
|
||||||
return this.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RecipeType<?> getType() {
|
public RecipeType<?> getType() {
|
||||||
return TYPE;
|
return TYPE;
|
||||||
|
@ -234,18 +227,25 @@ public class AnvilRecipe implements Recipe<Container>, UnknownReceipBookCategory
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
AnvilRecipe that = (AnvilRecipe) o;
|
AnvilRecipe that = (AnvilRecipe) o;
|
||||||
return damage == that.damage && toolLevel == that.toolLevel && id.equals(that.id) && input.equals(that.input) && output.equals(
|
return damage == that.damage && toolLevel == that.toolLevel && input.equals(that.input) && output.equals(that.output);
|
||||||
that.output);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(id, input, output, damage, toolLevel);
|
return Objects.hash(input, output, damage, toolLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "AnvilRecipe [" + id + "]";
|
final StringBuffer sb = new StringBuffer("AnvilRecipe{");
|
||||||
|
sb.append("input=").append(input);
|
||||||
|
sb.append(", output=").append(output);
|
||||||
|
sb.append(", damage=").append(damage);
|
||||||
|
sb.append(", toolLevel=").append(toolLevel);
|
||||||
|
sb.append(", anvilLevel=").append(anvilLevel);
|
||||||
|
sb.append(", inputCount=").append(inputCount);
|
||||||
|
sb.append('}');
|
||||||
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Builder extends AbstractSingleInputRecipeBuilder<Builder, AnvilRecipe> {
|
public static class Builder extends AbstractSingleInputRecipeBuilder<Builder, AnvilRecipe> {
|
||||||
|
@ -357,25 +357,23 @@ public class AnvilRecipe implements Recipe<Container>, UnknownReceipBookCategory
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Serializer implements RecipeSerializer<AnvilRecipe> {
|
public static class Serializer implements RecipeSerializer<AnvilRecipe> {
|
||||||
|
public static Codec<AnvilRecipe> CODEC = RecordCodecBuilder.create(instance -> instance.group(
|
||||||
|
Ingredient.CODEC_NONEMPTY.fieldOf("input").forGetter(recipe -> recipe.input),
|
||||||
|
ItemUtil.CODEC_ITEM_STACK_WITH_NBT.fieldOf("result").forGetter(recipe -> recipe.output),
|
||||||
|
Codec.INT.fieldOf("inputCount").forGetter(recipe -> recipe.inputCount),
|
||||||
|
Codec.INT.fieldOf("toolLevel").forGetter(recipe -> recipe.toolLevel),
|
||||||
|
Codec.INT.fieldOf("anvilLevel").forGetter(recipe -> recipe.anvilLevel),
|
||||||
|
Codec.INT.fieldOf("damage").forGetter(recipe -> recipe.damage)
|
||||||
|
).apply(instance, AnvilRecipe::new));
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AnvilRecipe fromJson(ResourceLocation id, JsonObject json) {
|
public Codec<AnvilRecipe> codec() {
|
||||||
Ingredient input = Ingredient.fromJson(json.get("input"));
|
return CODEC;
|
||||||
JsonObject result = GsonHelper.getAsJsonObject(json, "result");
|
|
||||||
ItemStack output = ItemUtil.fromJsonRecipeWithNBT(result);
|
|
||||||
if (output == null) {
|
|
||||||
throw new IllegalStateException("Output item does not exists!");
|
|
||||||
}
|
|
||||||
|
|
||||||
int inputCount = GsonHelper.getAsInt(json, "inputCount", 1);
|
|
||||||
int toolLevel = GsonHelper.getAsInt(json, "toolLevel", 1);
|
|
||||||
int anvilLevel = GsonHelper.getAsInt(json, "anvilLevel", 1);
|
|
||||||
int damage = GsonHelper.getAsInt(json, "damage", 1);
|
|
||||||
|
|
||||||
return new AnvilRecipe(id, input, output, inputCount, toolLevel, anvilLevel, damage);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AnvilRecipe fromNetwork(ResourceLocation id, FriendlyByteBuf packetBuffer) {
|
public AnvilRecipe fromNetwork(FriendlyByteBuf packetBuffer) {
|
||||||
Ingredient input = Ingredient.fromNetwork(packetBuffer);
|
Ingredient input = Ingredient.fromNetwork(packetBuffer);
|
||||||
ItemStack output = packetBuffer.readItem();
|
ItemStack output = packetBuffer.readItem();
|
||||||
int inputCount = packetBuffer.readVarInt();
|
int inputCount = packetBuffer.readVarInt();
|
||||||
|
@ -383,7 +381,7 @@ public class AnvilRecipe implements Recipe<Container>, UnknownReceipBookCategory
|
||||||
int anvilLevel = packetBuffer.readVarInt();
|
int anvilLevel = packetBuffer.readVarInt();
|
||||||
int damage = packetBuffer.readVarInt();
|
int damage = packetBuffer.readVarInt();
|
||||||
|
|
||||||
return new AnvilRecipe(id, input, output, inputCount, toolLevel, anvilLevel, damage);
|
return new AnvilRecipe(input, output, inputCount, toolLevel, anvilLevel, damage);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -2,26 +2,28 @@ package org.betterx.bclib.util;
|
||||||
|
|
||||||
import org.betterx.bclib.BCLib;
|
import org.betterx.bclib.BCLib;
|
||||||
|
|
||||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
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.core.registries.BuiltInRegistries;
|
import net.minecraft.core.registries.BuiltInRegistries;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
|
||||||
import net.minecraft.nbt.TagParser;
|
import net.minecraft.nbt.TagParser;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.util.GsonHelper;
|
import net.minecraft.util.ExtraCodecs;
|
||||||
import net.minecraft.world.item.Item;
|
import net.minecraft.world.item.Item;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.item.crafting.Ingredient;
|
import net.minecraft.world.item.crafting.Ingredient;
|
||||||
import net.minecraft.world.level.ItemLike;
|
|
||||||
|
|
||||||
import com.google.gson.JsonElement;
|
|
||||||
import com.google.gson.JsonObject;
|
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
public class ItemUtil {
|
public class ItemUtil {
|
||||||
@Nullable
|
@Nullable
|
||||||
public static ItemStack fromStackString(String stackString) {
|
public static ItemStack fromStackString(String stackString) {
|
||||||
if (stackString == null || stackString.equals("")) {
|
if (stackString == null || stackString.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
@ -29,112 +31,99 @@ public class ItemUtil {
|
||||||
if (parts.length < 2) return null;
|
if (parts.length < 2) return null;
|
||||||
if (parts.length == 2) {
|
if (parts.length == 2) {
|
||||||
ResourceLocation itemId = new ResourceLocation(stackString);
|
ResourceLocation itemId = new ResourceLocation(stackString);
|
||||||
Item item = BuiltInRegistries.ITEM.getOptional(itemId).orElseThrow(() -> {
|
Item item = BuiltInRegistries
|
||||||
return new IllegalStateException("Output item " + itemId + " does not exists!");
|
.ITEM
|
||||||
});
|
.getOptional(itemId)
|
||||||
|
.orElseThrow(() -> new IllegalStateException("Output item " + itemId + " does not exists!"));
|
||||||
return new ItemStack(item);
|
return new ItemStack(item);
|
||||||
}
|
}
|
||||||
ResourceLocation itemId = new ResourceLocation(parts[0], parts[1]);
|
ResourceLocation itemId = new ResourceLocation(parts[0], parts[1]);
|
||||||
Item item = BuiltInRegistries.ITEM.getOptional(itemId)
|
Item item = BuiltInRegistries
|
||||||
.orElseThrow(() -> new IllegalStateException("Output item " + itemId + " does not exists!"));
|
.ITEM
|
||||||
return new ItemStack(item, Integer.valueOf(parts[2]));
|
.getOptional(itemId)
|
||||||
|
.orElseThrow(() -> new IllegalStateException("Output item " + itemId + " does not exists!"));
|
||||||
|
return new ItemStack(item, Integer.parseInt(parts[2]));
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
BCLib.LOGGER.error("ItemStack deserialization error!", ex);
|
BCLib.LOGGER.error("ItemStack deserialization error!", ex);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CompoundTag readNBT(JsonObject recipe) {
|
public static Codec<ItemStack> CODEC_ITEM_STACK_WITH_NBT = RecordCodecBuilder.create((instance) -> instance.group(
|
||||||
if (recipe.has("nbt")) {
|
BuiltInRegistries.ITEM.holderByNameCodec()
|
||||||
try {
|
.fieldOf("item")
|
||||||
String nbtData = GsonHelper.getAsString(recipe, "nbt");
|
.forGetter(ItemStack::getItemHolder),
|
||||||
CompoundTag nbt = TagParser.parseTag(nbtData);
|
Codec.INT.optionalFieldOf("count", 1)
|
||||||
return nbt;
|
.forGetter(ItemStack::getCount),
|
||||||
} catch (CommandSyntaxException ex) {
|
ExtraCodecs.strictOptionalField(TagParser.AS_CODEC, "nbt")
|
||||||
BCLib.LOGGER.warning("Error parsing nbt data for output.", ex);
|
.forGetter((itemStack) -> Optional.ofNullable(itemStack.getTag()))
|
||||||
|
).apply(instance, ItemStack::new));
|
||||||
|
|
||||||
|
public static Codec<Ingredient> CODEC_INGREDIENT_WITH_NBT = ingredientCodec(true);
|
||||||
|
public static Codec<Ingredient> CODEC_INGREDIENT_WITH_NBT_NOT_EMPTY = ingredientCodec(false);
|
||||||
|
|
||||||
|
|
||||||
|
private static Codec<Ingredient> ingredientCodec(boolean allowEmpty) {
|
||||||
|
record NbtItemValue(ItemStack item) implements Ingredient.Value {
|
||||||
|
static final Codec<NbtItemValue> CODEC = RecordCodecBuilder.create((instance) -> instance
|
||||||
|
.group(CODEC_ITEM_STACK_WITH_NBT.fieldOf("item").forGetter((itemValue) -> itemValue.item))
|
||||||
|
.apply(instance, NbtItemValue::new));
|
||||||
|
|
||||||
|
public boolean equals(Object object) {
|
||||||
|
if (object instanceof NbtItemValue itemValue) {
|
||||||
|
return ItemStack.isSameItemSameTags(itemValue.item, this.item)
|
||||||
|
&& itemValue.item.getCount() == this.item.getCount();
|
||||||
|
} else if (object instanceof Ingredient.ItemValue itemValue) {
|
||||||
|
return ItemStack.isSameItemSameTags(itemValue.item(), this.item)
|
||||||
|
&& itemValue.item().getCount() == this.item.getCount();
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<ItemStack> getItems() {
|
||||||
|
return Collections.singleton(this.item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemStack item() {
|
||||||
|
return this.item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void writeNBT(JsonObject root, CompoundTag nbt) {
|
Codec<Ingredient.Value> VALUE_CODEC = ExtraCodecs
|
||||||
if (nbt != null) {
|
.xor(NbtItemValue.CODEC, Ingredient.TagValue.CODEC)
|
||||||
final String nbtData = nbt.toString();
|
.xmap(
|
||||||
root.addProperty("nbt", nbtData);
|
(either) -> either.map((itemValue) -> itemValue, (tagValue) -> tagValue),
|
||||||
}
|
(value) -> {
|
||||||
}
|
if (value instanceof Ingredient.TagValue tagValue) {
|
||||||
|
return Either.right(tagValue);
|
||||||
public static Ingredient fromJsonIngredientWithNBT(JsonObject ingredient) {
|
} else if (value instanceof NbtItemValue itemValue) {
|
||||||
Ingredient ing = Ingredient.fromJson(ingredient);
|
return Either.left(itemValue);
|
||||||
CompoundTag nbt = readNBT(ingredient);
|
} else {
|
||||||
if (nbt != null && !ing.isEmpty()) {
|
throw new UnsupportedOperationException(
|
||||||
ing.getItems()[0].setTag(nbt);
|
"This is neither an nbt-item value nor a tag value.");
|
||||||
}
|
}
|
||||||
return ing;
|
}
|
||||||
}
|
);
|
||||||
|
|
||||||
public static ItemStack fromJsonRecipeWithNBT(JsonObject recipe) {
|
|
||||||
ItemStack output = ItemUtil.fromJsonRecipe(recipe);
|
|
||||||
CompoundTag nbt = ItemUtil.readNBT(recipe);
|
|
||||||
if (output != null && nbt != null) {
|
|
||||||
output.setTag(nbt);
|
|
||||||
}
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public static ItemStack fromJsonRecipe(JsonObject recipe) {
|
|
||||||
try {
|
|
||||||
if (!recipe.has("item")) {
|
|
||||||
throw new IllegalStateException("Invalid JsonObject. Entry 'item' does not exists!");
|
|
||||||
}
|
|
||||||
ResourceLocation itemId = new ResourceLocation(GsonHelper.getAsString(recipe, "item"));
|
|
||||||
Item item = BuiltInRegistries.ITEM.getOptional(itemId).orElseThrow(() -> {
|
|
||||||
return new IllegalStateException("Output item " + itemId + " does not exists!");
|
|
||||||
});
|
|
||||||
int count = GsonHelper.getAsInt(recipe, "count", 1);
|
|
||||||
return new ItemStack(item, count);
|
|
||||||
} catch (Exception ex) {
|
|
||||||
BCLib.LOGGER.error("ItemStack deserialization error!", ex);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsonElement toJsonIngredientWithNBT(Ingredient ing) {
|
|
||||||
JsonElement el = ing.toJson();
|
|
||||||
if (el.isJsonObject() && !ing.isEmpty() && ing.getItems()[0].hasTag()) {
|
|
||||||
JsonObject obj = el.getAsJsonObject();
|
|
||||||
writeNBT(obj, ing.getItems()[0].getTag());
|
|
||||||
}
|
|
||||||
return el;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static JsonObject toJsonRecipeWithNBT(ItemStack stack) {
|
Codec<Ingredient.Value[]> codec = Codec.list(VALUE_CODEC).comapFlatMap((list) ->
|
||||||
return toJsonRecipeWithNBT(stack.getItem(), stack.getCount(), stack.getTag());
|
!allowEmpty && list.size() < 1
|
||||||
}
|
? DataResult.error(() -> "Item array cannot be empty, at least one item must be defined")
|
||||||
|
: DataResult.success(list.toArray(new Ingredient.Value[0]))
|
||||||
|
, List::of);
|
||||||
|
|
||||||
public static JsonObject toJsonRecipeWithNBT(ItemLike item, int count, CompoundTag nbt) {
|
return ExtraCodecs.either(codec, VALUE_CODEC).flatComapMap(
|
||||||
JsonObject root = toJsonRecipe(item, count);
|
(either) -> either.map(Ingredient::new, (value) -> new Ingredient(new Ingredient.Value[]{value})),
|
||||||
writeNBT(root, nbt);
|
(ingredient) -> {
|
||||||
return root;
|
if (ingredient.values.length == 1) {
|
||||||
}
|
return DataResult.success(Either.right(ingredient.values[0]));
|
||||||
|
} else {
|
||||||
public static JsonObject toJsonRecipe(ItemStack stack) {
|
return ingredient.values.length == 0 && !allowEmpty
|
||||||
return toJsonRecipe(stack.getItem(), stack.getCount());
|
? DataResult.error(() -> "Item array cannot be empty, at least one item must be defined")
|
||||||
}
|
: DataResult.success(Either.left(ingredient.values));
|
||||||
|
}
|
||||||
public static JsonObject toJsonRecipe(ItemLike item, int count) {
|
}
|
||||||
final ResourceLocation id = BuiltInRegistries.ITEM.getKey(item.asItem());
|
);
|
||||||
if (id == null) {
|
|
||||||
throw new IllegalStateException("Unknown Item " + item);
|
|
||||||
}
|
|
||||||
|
|
||||||
final JsonObject root = new JsonObject();
|
|
||||||
root.addProperty("item", BuiltInRegistries.ITEM.getKey(item.asItem()).toString());
|
|
||||||
if (count > 1) {
|
|
||||||
root.addProperty("count", count);
|
|
||||||
}
|
|
||||||
return root;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,9 @@ accessible class net/minecraft/client/resources/model/AtlasSet$AtlasEntry
|
||||||
extendable class net/minecraft/world/level/block/state/properties/WoodType
|
extendable class net/minecraft/world/level/block/state/properties/WoodType
|
||||||
accessible class net/minecraft/world/level/levelgen/SurfaceRules$BiomeConditionSource
|
accessible class net/minecraft/world/level/levelgen/SurfaceRules$BiomeConditionSource
|
||||||
accessible class net/minecraft/world/level/levelgen/SurfaceRules$TestRuleSource
|
accessible class net/minecraft/world/level/levelgen/SurfaceRules$TestRuleSource
|
||||||
|
accessible class net/minecraft/world/item/crafting/Ingredient$Value
|
||||||
|
accessible class net/minecraft/world/item/crafting/Ingredient$TagValue
|
||||||
|
accessible class net/minecraft/world/item/crafting/Ingredient$ItemValue
|
||||||
|
|
||||||
#Methods
|
#Methods
|
||||||
accessible method net/minecraft/world/level/storage/loot/LootPool <init> (Ljava/util/List;Ljava/util/List;Ljava/util/List;Lnet/minecraft/world/level/storage/loot/providers/number/NumberProvider;Lnet/minecraft/world/level/storage/loot/providers/number/NumberProvider;)V
|
accessible method net/minecraft/world/level/storage/loot/LootPool <init> (Ljava/util/List;Ljava/util/List;Ljava/util/List;Lnet/minecraft/world/level/storage/loot/providers/number/NumberProvider;Lnet/minecraft/world/level/storage/loot/providers/number/NumberProvider;)V
|
||||||
|
@ -36,7 +39,11 @@ accessible method net/minecraft/world/level/block/Blocks never (Lnet/minecraft/w
|
||||||
accessible method net/minecraft/world/level/block/Blocks never (Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/BlockGetter;Lnet/minecraft/core/BlockPos;)Z
|
accessible method net/minecraft/world/level/block/Blocks never (Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/BlockGetter;Lnet/minecraft/core/BlockPos;)Z
|
||||||
accessible method net/minecraft/world/level/levelgen/structure/pools/SinglePoolElement <init> (Lcom/mojang/datafixers/util/Either;Lnet/minecraft/core/Holder;Lnet/minecraft/world/level/levelgen/structure/pools/StructureTemplatePool$Projection;)V
|
accessible method net/minecraft/world/level/levelgen/structure/pools/SinglePoolElement <init> (Lcom/mojang/datafixers/util/Either;Lnet/minecraft/core/Holder;Lnet/minecraft/world/level/levelgen/structure/pools/StructureTemplatePool$Projection;)V
|
||||||
accessible method net/minecraft/world/level/levelgen/structure/pools/LegacySinglePoolElement <init> (Lcom/mojang/datafixers/util/Either;Lnet/minecraft/core/Holder;Lnet/minecraft/world/level/levelgen/structure/pools/StructureTemplatePool$Projection;)V
|
accessible method net/minecraft/world/level/levelgen/structure/pools/LegacySinglePoolElement <init> (Lcom/mojang/datafixers/util/Either;Lnet/minecraft/core/Holder;Lnet/minecraft/world/level/levelgen/structure/pools/StructureTemplatePool$Projection;)V
|
||||||
|
accessible method net/minecraft/world/item/crafting/Ingredient <init> ([Lnet/minecraft/world/item/crafting/Ingredient$Value;)V
|
||||||
|
accessible method net/minecraft/world/item/crafting/Ingredient$TagValue <init> (Lnet/minecraft/tags/TagKey;)V
|
||||||
|
|
||||||
#Fields
|
#Fields
|
||||||
accessible field net/minecraft/world/entity/ai/village/poi/PoiTypes TYPE_BY_STATE Ljava/util/Map;
|
accessible field net/minecraft/world/entity/ai/village/poi/PoiTypes TYPE_BY_STATE Ljava/util/Map;
|
||||||
accessible field net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity lootTable Lnet/minecraft/resources/ResourceLocation;
|
accessible field net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity lootTable Lnet/minecraft/resources/ResourceLocation;
|
||||||
|
accessible field net/minecraft/world/item/crafting/Ingredient values [Lnet/minecraft/world/item/crafting/Ingredient$Value;
|
||||||
|
accessible field net/minecraft/world/item/crafting/Ingredient$TagValue CODEC Lcom/mojang/serialization/Codec;
|
Loading…
Add table
Add a link
Reference in a new issue