[Change] Recipes use Codecs for Serialization now

This commit is contained in:
Frank 2023-12-18 15:23:13 +01:00
parent 7e06e9ce3f
commit 7a972fc22f
4 changed files with 162 additions and 160 deletions

View file

@ -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

View file

@ -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

View file

@ -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;
} }
} }

View file

@ -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;