port A LOT

This commit is contained in:
2026-01-10 23:36:28 -05:00
parent dfde4b2315
commit 9a954a0af1
446 changed files with 57881 additions and 71 deletions
@@ -0,0 +1,142 @@
package net.cmr.jurassicrevived.recipe;
import net.cmr.jurassicrevived.Constants;
import net.minecraft.core.NonNullList;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.*;
import net.minecraft.world.level.Level;
import net.minecraft.resources.ResourceLocation;
import org.jetbrains.annotations.NotNull;
/*? if >1.20.1 {*/
/*import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import com.mojang.serialization.DataResult;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.ByteBufCodecs;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.core.HolderLookup;
import java.util.List;
*//*?} else {*/
import com.google.gson.JsonObject;
import com.google.gson.JsonArray;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.util.GsonHelper;
import net.minecraft.core.RegistryAccess;
/*?}*/
public record DNAAnalyzerRecipe(
NonNullList<Ingredient> inputs,
ItemStack output,
java.util.Map<ResourceLocation, Integer> weights
) implements Recipe<DNAAnalyzerRecipeInput> {
@Override
public boolean matches(DNAAnalyzerRecipeInput input, Level level) {
if (level.isClientSide) return false;
ItemStack in0 = input.getItem(0);
ItemStack in1 = input.getItem(1);
return (inputs.get(0).test(in0) && inputs.get(1).test(in1)) ||
(inputs.get(0).test(in1) && inputs.get(1).test(in0));
}
/*? if >1.20.1 {*/
/*@Override
public ItemStack assemble(DNAAnalyzerRecipeInput input, HolderLookup.Provider provider) {
return output.copy();
}
@Override
public ItemStack getResultItem(HolderLookup.Provider provider) {
return output.copy();
}
*//*?} else {*/
@Override
public ItemStack assemble(DNAAnalyzerRecipeInput input, RegistryAccess access) {
return output.copy();
}
@Override
public ItemStack getResultItem(RegistryAccess access) {
return output.copy();
}
@Override
public ResourceLocation getId() {
// In 1.20.1, the ID was stored. In 1.21.1, it's handled by the registry.
// If you need the ID specifically in 1.20.1, you'd need to add it to the record.
return Constants.rl("dna_analyzing");
}
/*?}*/
@Override
public boolean canCraftInDimensions(int width, int height) { return true; }
@Override
public RecipeSerializer<?> getSerializer() { return ModRecipes.DNA_ANALYZER_SERIALIZER.get(); }
@Override
public RecipeType<?> getType() { return ModRecipes.DNA_ANALYZER_RECIPE_TYPE.get(); }
public int getWeightFor(Item item) {
ResourceLocation key = BuiltInRegistries.ITEM.getKey(item);
return weights.getOrDefault(key, 1);
}
public static class Serializer implements RecipeSerializer<DNAAnalyzerRecipe> {
/*? if >1.20.1 {*/
/*public static final MapCodec<DNAAnalyzerRecipe> CODEC = RecordCodecBuilder.mapCodec(inst -> inst.group(
Ingredient.CODEC_NONEMPTY.listOf().fieldOf("ingredients").flatXmap(
l -> l.size() == 2 ? DataResult.success(NonNullList.of(Ingredient.EMPTY, l.get(0), l.get(1))) : DataResult.error(() -> "Needs 2 ingredients"),
l -> DataResult.success(List.copyOf(l))
).forGetter(DNAAnalyzerRecipe::inputs),
ItemStack.CODEC.fieldOf("result").forGetter(DNAAnalyzerRecipe::output),
Codec.unboundedMap(ResourceLocation.CODEC, Codec.INT).optionalFieldOf("weights", java.util.Map.of()).forGetter(DNAAnalyzerRecipe::weights)
).apply(inst, DNAAnalyzerRecipe::new));
public static final StreamCodec<RegistryFriendlyByteBuf, DNAAnalyzerRecipe> STREAM_CODEC = StreamCodec.of(
(buf, r) -> {
buf.writeVarInt(r.inputs().size());
for(Ingredient i : r.inputs()) Ingredient.CONTENTS_STREAM_CODEC.encode(buf, i);
ItemStack.STREAM_CODEC.encode(buf, r.output());
buf.writeMap(r.weights(), ResourceLocation.STREAM_CODEC, ByteBufCodecs.VAR_INT);
},
buf -> {
int size = buf.readVarInt();
NonNullList<Ingredient> ins = NonNullList.create();
for(int i=0; i<size; i++) ins.add(Ingredient.CONTENTS_STREAM_CODEC.decode(buf));
return new DNAAnalyzerRecipe(ins, ItemStack.STREAM_CODEC.decode(buf), buf.readMap(m -> new java.util.HashMap<>(), ResourceLocation.STREAM_CODEC, ByteBufCodecs.VAR_INT));
}
);
@Override public MapCodec<DNAAnalyzerRecipe> codec() { return CODEC; }
@Override public StreamCodec<RegistryFriendlyByteBuf, DNAAnalyzerRecipe> streamCodec() { return STREAM_CODEC; }
*//*?} else {*/
@Override
public DNAAnalyzerRecipe fromJson(ResourceLocation id, JsonObject json) {
JsonArray ingredients = GsonHelper.getAsJsonArray(json, "ingredients");
NonNullList<Ingredient> inputs = NonNullList.withSize(2, Ingredient.EMPTY);
for (int i = 0; i < 2; i++) inputs.set(i, Ingredient.fromJson(ingredients.get(i)));
ItemStack output = ShapedRecipe.itemStackFromJson(GsonHelper.getAsJsonObject(json, "result"));
return new DNAAnalyzerRecipe(inputs, output, java.util.Map.of()); // Weights logic can be added here
}
@Override
public DNAAnalyzerRecipe fromNetwork(ResourceLocation id, FriendlyByteBuf buf) {
NonNullList<Ingredient> inputs = NonNullList.withSize(buf.readInt(), Ingredient.EMPTY);
for (int i = 0; i < inputs.size(); i++) inputs.set(i, Ingredient.fromNetwork(buf));
return new DNAAnalyzerRecipe(inputs, buf.readItem(), java.util.Map.of());
}
@Override
public void toNetwork(FriendlyByteBuf buf, DNAAnalyzerRecipe recipe) {
buf.writeInt(recipe.inputs().size());
for (Ingredient ing : recipe.inputs()) ing.toNetwork(buf);
buf.writeItem(recipe.output());
}
/*?}*/
}
}
@@ -0,0 +1,47 @@
package net.cmr.jurassicrevived.recipe;
import net.minecraft.world.item.ItemStack;
import java.util.List;
import java.util.Objects;
/*? if >1.20.1 {*/
/*import net.minecraft.world.item.crafting.RecipeInput;
*//*?} else {*/
import net.minecraft.world.Container;
import net.minecraft.world.entity.player.Player;
/*?}*/
public record DNAAnalyzerRecipeInput(List<ItemStack> inputs)
/*? if >1.20.1 {*/ /*implements RecipeInput *//*?} else {*/ implements Container /*?}*/ {
public DNAAnalyzerRecipeInput {
Objects.requireNonNull(inputs, "inputs");
if (inputs.size() != 2) {
throw new IllegalArgumentException("DNAAnalyzerRecipeInput requires exactly 2 input stacks");
}
}
public DNAAnalyzerRecipeInput(ItemStack first, ItemStack second) {
this(List.of(first, second));
}
@Override
public ItemStack getItem(int i) {
return inputs.get(i);
}
public int size() {
return inputs.size();
}
/*? if <=1.20.1 {*/
@Override public int getContainerSize() { return size(); }
@Override public boolean isEmpty() { return inputs.stream().allMatch(ItemStack::isEmpty); }
@Override public ItemStack removeItem(int i, int j) { return ItemStack.EMPTY; }
@Override public ItemStack removeItemNoUpdate(int i) { return ItemStack.EMPTY; }
@Override public void setItem(int i, ItemStack itemStack) {}
@Override public void setChanged() {}
@Override public boolean stillValid(Player player) { return true; }
@Override public void clearContent() {}
/*?}*/
}
@@ -0,0 +1,142 @@
package net.cmr.jurassicrevived.recipe;
import net.cmr.jurassicrevived.Constants;
import net.cmr.jurassicrevived.item.ModItems;
import net.cmr.jurassicrevived.util.ModTags;
import net.minecraft.core.NonNullList;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.*;
import net.minecraft.world.level.Level;
import net.minecraft.util.RandomSource;
import org.jetbrains.annotations.NotNull;
/*? if >1.20.1 {*/
/*import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import com.mojang.serialization.DataResult;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.ByteBufCodecs;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.core.HolderLookup;
import java.util.List;
*//*?} else {*/
import com.google.gson.JsonObject;
import com.google.gson.JsonArray;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.util.GsonHelper;
import net.minecraft.core.RegistryAccess;
/*?}*/
public record DNAExtractorRecipe(
NonNullList<Ingredient> inputs,
ItemStack output,
java.util.Map<ResourceLocation, Integer> weights
) implements Recipe<DNAExtractorRecipeInput> {
@Override
public boolean matches(DNAExtractorRecipeInput input, Level level) {
if (level.isClientSide) return false;
ItemStack in0 = input.getItem(0);
ItemStack in1 = input.getItem(1);
return (inputs.get(0).test(in0) && inputs.get(1).test(in1)) ||
(inputs.get(0).test(in1) && inputs.get(1).test(in0));
}
private ItemStack handleAmberExtraction(DNAExtractorRecipeInput input) {
if (!input.getItem(1).isEmpty() && input.getItem(1).is(ModItems.MOSQUITO_IN_AMBER.get())) {
ItemStack[] candidates = Ingredient.of(ModTags.Items.DNA).getItems();
if (candidates.length > 0) {
return new ItemStack(pickWeightedRandomDNA(candidates, RandomSource.create()));
}
}
return output.copy();
}
private net.minecraft.world.item.Item pickWeightedRandomDNA(ItemStack[] candidates, RandomSource random) {
long total = 0;
int[] itemWeights = new int[candidates.length];
for (int i = 0; i < candidates.length; i++) {
ResourceLocation key = net.minecraft.core.registries.BuiltInRegistries.ITEM.getKey(candidates[i].getItem());
int w = Math.max(0, weights.getOrDefault(key, 1));
itemWeights[i] = w;
total += w;
}
if (total <= 0) return candidates[random.nextInt(candidates.length)].getItem();
long roll = 1L + (total <= Integer.MAX_VALUE ? random.nextInt((int) total) : Math.abs(random.nextLong()) % total);
long cumulative = 0;
for (int i = 0; i < candidates.length; i++) {
cumulative += itemWeights[i];
if (roll <= cumulative) return candidates[i].getItem();
}
return candidates[candidates.length - 1].getItem();
}
/*? if >1.20.1 {*/
/*@Override public ItemStack assemble(DNAExtractorRecipeInput input, HolderLookup.Provider p) { return handleAmberExtraction(input); }
@Override public ItemStack getResultItem(HolderLookup.Provider p) { return output.copy(); }
*//*?} else {*/
@Override public ItemStack assemble(DNAExtractorRecipeInput input, RegistryAccess a) { return handleAmberExtraction(input); }
@Override public ItemStack getResultItem(RegistryAccess a) { return output.copy(); }
@Override public ResourceLocation getId() { return Constants.rl("dna_extracting"); }
/*?}*/
@Override public boolean canCraftInDimensions(int w, int h) { return true; }
@Override public RecipeSerializer<?> getSerializer() { return ModRecipes.DNA_EXTRACTOR_SERIALIZER.get(); }
@Override public RecipeType<?> getType() { return ModRecipes.DNA_EXTRACTOR_RECIPE_TYPE.get(); }
public int getWeightFor(Item item) {
ResourceLocation key = BuiltInRegistries.ITEM.getKey(item);
return weights.getOrDefault(key, 1);
}
public static class Serializer implements RecipeSerializer<DNAExtractorRecipe> {
/*? if >1.20.1 {*/
/*public static final MapCodec<DNAExtractorRecipe> CODEC = RecordCodecBuilder.mapCodec(inst -> inst.group(
Ingredient.CODEC_NONEMPTY.listOf().fieldOf("ingredients").flatXmap(
l -> l.size() == 2 ? DataResult.success(NonNullList.of(Ingredient.EMPTY, l.get(0), l.get(1))) : DataResult.error(() -> "Needs 2 ingredients"),
l -> DataResult.success(List.copyOf(l))
).forGetter(DNAExtractorRecipe::inputs),
ItemStack.CODEC.fieldOf("result").forGetter(DNAExtractorRecipe::output),
Codec.unboundedMap(ResourceLocation.CODEC, Codec.INT).optionalFieldOf("weights", java.util.Map.of()).forGetter(DNAExtractorRecipe::weights)
).apply(inst, DNAExtractorRecipe::new));
public static final StreamCodec<RegistryFriendlyByteBuf, DNAExtractorRecipe> STREAM_CODEC = StreamCodec.of(
(buf, r) -> {
buf.writeVarInt(r.inputs().size());
for(Ingredient i : r.inputs()) Ingredient.CONTENTS_STREAM_CODEC.encode(buf, i);
ItemStack.STREAM_CODEC.encode(buf, r.output());
buf.writeMap(r.weights(), ResourceLocation.STREAM_CODEC, ByteBufCodecs.VAR_INT);
},
buf -> {
int size = buf.readVarInt();
NonNullList<Ingredient> ins = NonNullList.create();
for(int i=0; i<size; i++) ins.add(Ingredient.CONTENTS_STREAM_CODEC.decode(buf));
return new DNAExtractorRecipe(ins, ItemStack.STREAM_CODEC.decode(buf), buf.readMap(m -> new java.util.HashMap<>(), ResourceLocation.STREAM_CODEC, ByteBufCodecs.VAR_INT));
}
);
@Override public MapCodec<DNAExtractorRecipe> codec() { return CODEC; }
@Override public StreamCodec<RegistryFriendlyByteBuf, DNAExtractorRecipe> streamCodec() { return STREAM_CODEC; }
*//*?} else {*/
@Override public DNAExtractorRecipe fromJson(ResourceLocation id, JsonObject json) {
JsonArray ingredients = GsonHelper.getAsJsonArray(json, "ingredients");
NonNullList<Ingredient> inputs = NonNullList.withSize(2, Ingredient.EMPTY);
for (int i = 0; i < 2; i++) inputs.set(i, Ingredient.fromJson(ingredients.get(i)));
return new DNAExtractorRecipe(inputs, ShapedRecipe.itemStackFromJson(GsonHelper.getAsJsonObject(json, "result")), java.util.Map.of());
}
@Override public DNAExtractorRecipe fromNetwork(ResourceLocation id, FriendlyByteBuf buf) {
NonNullList<Ingredient> inputs = NonNullList.withSize(buf.readInt(), Ingredient.EMPTY);
for (int i = 0; i < inputs.size(); i++) inputs.set(i, Ingredient.fromNetwork(buf));
return new DNAExtractorRecipe(inputs, buf.readItem(), java.util.Map.of());
}
@Override public void toNetwork(FriendlyByteBuf buf, DNAExtractorRecipe recipe) {
buf.writeInt(recipe.inputs().size());
for (Ingredient ing : recipe.inputs()) ing.toNetwork(buf);
buf.writeItem(recipe.output());
}
/*?}*/
}
}
@@ -0,0 +1,47 @@
package net.cmr.jurassicrevived.recipe;
import net.minecraft.world.item.ItemStack;
import java.util.List;
import java.util.Objects;
/*? if >1.20.1 {*/
/*import net.minecraft.world.item.crafting.RecipeInput;
*//*?} else {*/
import net.minecraft.world.Container;
import net.minecraft.world.entity.player.Player;
/*?}*/
public record DNAExtractorRecipeInput(List<ItemStack> inputs)
/*? if >1.20.1 {*/ /*implements RecipeInput *//*?} else {*/ implements Container /*?}*/ {
public DNAExtractorRecipeInput {
Objects.requireNonNull(inputs, "inputs");
if (inputs.size() != 2) {
throw new IllegalArgumentException("DNAExtractorRecipeInput requires exactly 2 input stacks");
}
}
public DNAExtractorRecipeInput(ItemStack first, ItemStack second) {
this(List.of(first, second));
}
@Override
public ItemStack getItem(int i) {
return inputs.get(i);
}
public int size() {
return inputs.size();
}
/*? if <=1.20.1 {*/
@Override public int getContainerSize() { return size(); }
@Override public boolean isEmpty() { return inputs.stream().allMatch(ItemStack::isEmpty); }
@Override public ItemStack removeItem(int i, int j) { return ItemStack.EMPTY; }
@Override public ItemStack removeItemNoUpdate(int i) { return ItemStack.EMPTY; }
@Override public void setItem(int i, ItemStack itemStack) {}
@Override public void setChanged() {}
@Override public boolean stillValid(Player player) { return true; }
@Override public void clearContent() {}
/*?}*/
}
@@ -0,0 +1,128 @@
package net.cmr.jurassicrevived.recipe;
import net.cmr.jurassicrevived.Constants;
import net.minecraft.core.NonNullList;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.*;
import net.minecraft.world.level.Level;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
/*? if >1.20.1 {*/
/*import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import com.mojang.serialization.DataResult;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.ByteBufCodecs;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.core.HolderLookup;
*//*?} else {*/
import com.google.gson.JsonObject;
import com.google.gson.JsonArray;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.util.GsonHelper;
import net.minecraft.core.RegistryAccess;
/*?}*/
public record DNAHybridizerRecipe(NonNullList<Ingredient> inputs, ItemStack output) implements Recipe<DNAHybridizerRecipeInput> {
@Override
public boolean matches(DNAHybridizerRecipeInput recipeInput, Level level) {
if (level.isClientSide) return false;
// Catalyst matching (Slot 8)
Ingredient catalystNeed = inputs.size() > 8 ? inputs.get(8) : Ingredient.EMPTY;
ItemStack catalystIn = recipeInput.getItem(8);
if (!catalystNeed.test(catalystIn)) return false;
// Unordered matching for DNA slots (0-7)
List<Ingredient> dnaNeeds = new ArrayList<>();
for (int i = 0; i < 8 && i < inputs.size(); i++) {
if (!inputs.get(i).isEmpty()) dnaNeeds.add(inputs.get(i));
}
List<ItemStack> dnaInputs = new ArrayList<>();
for (int i = 0; i < 8; i++) {
if (!recipeInput.getItem(i).isEmpty()) dnaInputs.add(recipeInput.getItem(i));
}
if (dnaNeeds.size() != dnaInputs.size()) return false;
boolean[] used = new boolean[dnaNeeds.size()];
for (ItemStack stack : dnaInputs) {
boolean matched = false;
for (int i = 0; i < dnaNeeds.size(); i++) {
if (!used[i] && dnaNeeds.get(i).test(stack)) {
used[i] = true;
matched = true;
break;
}
}
if (!matched) return false;
}
return true;
}
/*? if >1.20.1 {*/
/*@Override public ItemStack assemble(DNAHybridizerRecipeInput input, HolderLookup.Provider p) { return output.copy(); }
@Override public ItemStack getResultItem(HolderLookup.Provider p) { return output.copy(); }
*//*?} else {*/
@Override public ItemStack assemble(DNAHybridizerRecipeInput input, RegistryAccess a) { return output.copy(); }
@Override public ItemStack getResultItem(RegistryAccess a) { return output.copy(); }
@Override public ResourceLocation getId() { return Constants.rl("dna_hybridizing"); }
/*?}*/
@Override public boolean canCraftInDimensions(int w, int h) { return true; }
@Override public RecipeSerializer<?> getSerializer() { return ModRecipes.DNA_HYBRIDIZER_SERIALIZER.get(); }
@Override public RecipeType<?> getType() { return ModRecipes.DNA_HYBRIDIZER_RECIPE_TYPE.get(); }
public static class Serializer implements RecipeSerializer<DNAHybridizerRecipe> {
/*? if >1.20.1 {*/
/*public static final MapCodec<DNAHybridizerRecipe> CODEC = RecordCodecBuilder.mapCodec(inst -> inst.group(
Ingredient.CODEC.listOf().fieldOf("ingredients").flatXmap(
l -> l.isEmpty() || l.size() > 9 ? DataResult.error(() -> "Needs 1-9 ingredients") : DataResult.success(NonNullList.of(Ingredient.EMPTY, l.toArray(new Ingredient[0]))),
l -> DataResult.success(List.copyOf(l))
).forGetter(DNAHybridizerRecipe::inputs),
ItemStack.CODEC.fieldOf("result").forGetter(DNAHybridizerRecipe::output)
).apply(inst, DNAHybridizerRecipe::new));
public static final StreamCodec<RegistryFriendlyByteBuf, DNAHybridizerRecipe> STREAM_CODEC = StreamCodec.of(
(buf, r) -> {
buf.writeVarInt(r.inputs().size());
for(Ingredient i : r.inputs()) Ingredient.CONTENTS_STREAM_CODEC.encode(buf, i);
ItemStack.STREAM_CODEC.encode(buf, r.output());
},
buf -> {
int size = buf.readVarInt();
NonNullList<Ingredient> ins = NonNullList.create();
for(int i=0; i<size; i++) ins.add(Ingredient.CONTENTS_STREAM_CODEC.decode(buf));
return new DNAHybridizerRecipe(ins, ItemStack.STREAM_CODEC.decode(buf));
}
);
@Override public MapCodec<DNAHybridizerRecipe> codec() { return CODEC; }
@Override public StreamCodec<RegistryFriendlyByteBuf, DNAHybridizerRecipe> streamCodec() { return STREAM_CODEC; }
*//*?} else {*/
@Override public DNAHybridizerRecipe fromJson(ResourceLocation id, JsonObject json) {
JsonArray ings = GsonHelper.getAsJsonArray(json, "ingredients");
NonNullList<Ingredient> inputs = NonNullList.withSize(9, Ingredient.EMPTY);
for (int i = 0; i < Math.min(ings.size(), 8); i++) inputs.set(i, Ingredient.fromJson(ings.get(i)));
if (json.has("catalyst")) inputs.set(8, Ingredient.fromJson(json.get("catalyst")));
return new DNAHybridizerRecipe(inputs, ShapedRecipe.itemStackFromJson(GsonHelper.getAsJsonObject(json, "result")));
}
@Override public DNAHybridizerRecipe fromNetwork(ResourceLocation id, FriendlyByteBuf buf) {
NonNullList<Ingredient> inputs = NonNullList.withSize(9, Ingredient.EMPTY);
for (int i = 0; i < 9; i++) inputs.set(i, Ingredient.fromNetwork(buf));
return new DNAHybridizerRecipe(inputs, buf.readItem());
}
@Override public void toNetwork(FriendlyByteBuf buf, DNAHybridizerRecipe r) {
for (int i = 0; i < 9; i++) (i < r.inputs().size() ? r.inputs().get(i) : Ingredient.EMPTY).toNetwork(buf);
buf.writeItem(r.output());
}
/*?}*/
}
}
@@ -0,0 +1,33 @@
package net.cmr.jurassicrevived.recipe;
import net.minecraft.world.item.ItemStack;
//? if >1.20.1 {
/*import net.minecraft.world.item.crafting.RecipeInput;
import java.util.List;
*///?} else {
import net.minecraft.world.SimpleContainer;
//?}
//? if >1.20.1 {
/*public record DNAHybridizerRecipeInput(List<ItemStack> inputs) implements RecipeInput {
public DNAHybridizerRecipeInput(ItemStack i0, ItemStack i1, ItemStack i2, ItemStack i3, ItemStack i4, ItemStack i5, ItemStack i6, ItemStack i7, ItemStack i8) {
this(List.of(i0, i1, i2, i3, i4, i5, i6, i7, i8));
}
@Override
public ItemStack getItem(int index) {
return inputs.get(index);
}
@Override
public int size() {
return inputs.size();
}
}
*///?} else {
public class DNAHybridizerRecipeInput extends SimpleContainer {
public DNAHybridizerRecipeInput(ItemStack i0, ItemStack i1, ItemStack i2, ItemStack i3, ItemStack i4, ItemStack i5, ItemStack i6, ItemStack i7, ItemStack i8) {
super(i0, i1, i2, i3, i4, i5, i6, i7, i8);
}
}
//?}
@@ -0,0 +1,103 @@
package net.cmr.jurassicrevived.recipe;
import net.cmr.jurassicrevived.Constants;
import net.minecraft.core.NonNullList;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.*;
import net.minecraft.world.level.Level;
import org.jetbrains.annotations.NotNull;
/*? if >1.20.1 {*/
/*import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import com.mojang.serialization.DataResult;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.ByteBufCodecs;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.core.HolderLookup;
import java.util.List;
*//*?} else {*/
import com.google.gson.JsonObject;
import com.google.gson.JsonArray;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.util.GsonHelper;
import net.minecraft.core.RegistryAccess;
/*?}*/
public record EmbryoCalcificationMachineRecipe(NonNullList<Ingredient> inputs, ItemStack output)
implements Recipe<EmbryoCalcificationMachineRecipeInput> {
@Override
public boolean matches(EmbryoCalcificationMachineRecipeInput recipeInput, Level level) {
if (level.isClientSide) return false;
if (recipeInput.size() < 2 || inputs.size() < 2) return false;
ItemStack in0 = recipeInput.getItem(0);
ItemStack in1 = recipeInput.getItem(1);
Ingredient a = inputs.get(0);
Ingredient b = inputs.get(1);
// Symmetric match: (A+B) or (B+A)
return (a.test(in0) && b.test(in1)) || (a.test(in1) && b.test(in0));
}
/*? if >1.20.1 {*/
/*@Override public ItemStack assemble(EmbryoCalcificationMachineRecipeInput input, HolderLookup.Provider p) { return output.copy(); }
@Override public ItemStack getResultItem(HolderLookup.Provider p) { return output.copy(); }
*//*?} else {*/
@Override public ItemStack assemble(EmbryoCalcificationMachineRecipeInput input, RegistryAccess a) { return output.copy(); }
@Override public ItemStack getResultItem(RegistryAccess a) { return output.copy(); }
@Override public ResourceLocation getId() { return Constants.rl("embryonic_machining"); }
/*?}*/
@Override public boolean canCraftInDimensions(int width, int height) { return true; }
@Override public RecipeSerializer<?> getSerializer() { return ModRecipes.EMBRYO_CALCIFICATION_MACHINE_SERIALIZER.get(); }
@Override public RecipeType<?> getType() { return ModRecipes.EMBRYO_CALCIFICATION_MACHINE_RECIPE_TYPE.get(); }
public static class Serializer implements RecipeSerializer<EmbryoCalcificationMachineRecipe> {
/*? if >1.20.1 {*/
/*public static final MapCodec<EmbryoCalcificationMachineRecipe> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
Ingredient.CODEC_NONEMPTY.listOf().fieldOf("ingredients").flatXmap(
list -> list.size() != 2 ? DataResult.error(() -> "Requires exactly 2 ingredients") : DataResult.success(NonNullList.of(Ingredient.EMPTY, list.get(0), list.get(1))),
list -> DataResult.success(List.copyOf(list))
).forGetter(EmbryoCalcificationMachineRecipe::inputs),
ItemStack.CODEC.fieldOf("result").forGetter(EmbryoCalcificationMachineRecipe::output)
).apply(instance, EmbryoCalcificationMachineRecipe::new));
public static final StreamCodec<RegistryFriendlyByteBuf, EmbryoCalcificationMachineRecipe> STREAM_CODEC = StreamCodec.of(
(buf, recipe) -> {
buf.writeVarInt(recipe.inputs().size());
for(Ingredient i : recipe.inputs()) Ingredient.CONTENTS_STREAM_CODEC.encode(buf, i);
ItemStack.STREAM_CODEC.encode(buf, recipe.output());
},
buf -> {
int size = buf.readVarInt();
NonNullList<Ingredient> ins = NonNullList.create();
for(int i=0; i<size; i++) ins.add(Ingredient.CONTENTS_STREAM_CODEC.decode(buf));
return new EmbryoCalcificationMachineRecipe(ins, ItemStack.STREAM_CODEC.decode(buf));
}
);
@Override public MapCodec<EmbryoCalcificationMachineRecipe> codec() { return CODEC; }
@Override public StreamCodec<RegistryFriendlyByteBuf, EmbryoCalcificationMachineRecipe> streamCodec() { return STREAM_CODEC; }
*//*?} else {*/
@Override public EmbryoCalcificationMachineRecipe fromJson(ResourceLocation id, JsonObject json) {
JsonArray ingredients = GsonHelper.getAsJsonArray(json, "ingredients");
NonNullList<Ingredient> inputs = NonNullList.withSize(2, Ingredient.EMPTY);
for (int i = 0; i < 2; i++) inputs.set(i, Ingredient.fromJson(ingredients.get(i)));
ItemStack output = ShapedRecipe.itemStackFromJson(GsonHelper.getAsJsonObject(json, "result"));
return new EmbryoCalcificationMachineRecipe(inputs, output);
}
@Override public EmbryoCalcificationMachineRecipe fromNetwork(ResourceLocation id, FriendlyByteBuf buf) {
NonNullList<Ingredient> inputs = NonNullList.withSize(buf.readInt(), Ingredient.EMPTY);
for (int i = 0; i < inputs.size(); i++) inputs.set(i, Ingredient.fromNetwork(buf));
return new EmbryoCalcificationMachineRecipe(inputs, buf.readItem());
}
@Override public void toNetwork(FriendlyByteBuf buf, EmbryoCalcificationMachineRecipe recipe) {
buf.writeInt(recipe.inputs().size());
for (Ingredient ing : recipe.inputs()) ing.toNetwork(buf);
buf.writeItem(recipe.output());
}
/*?}*/
}
}
@@ -0,0 +1,47 @@
package net.cmr.jurassicrevived.recipe;
import net.minecraft.world.item.ItemStack;
import java.util.List;
import java.util.Objects;
/*? if >1.20.1 {*/
/*import net.minecraft.world.item.crafting.RecipeInput;
*//*?} else {*/
import net.minecraft.world.Container;
import net.minecraft.world.entity.player.Player;
/*?}*/
public record EmbryoCalcificationMachineRecipeInput(List<ItemStack> inputs)
/*? if >1.20.1 {*/ /*implements RecipeInput *//*?} else {*/ implements Container /*?}*/ {
public EmbryoCalcificationMachineRecipeInput {
Objects.requireNonNull(inputs, "inputs");
if (inputs.size() != 2) {
throw new IllegalArgumentException("EmbryoCalcificationMachineRecipeInput requires exactly 2 input stacks");
}
}
public EmbryoCalcificationMachineRecipeInput(ItemStack first, ItemStack second) {
this(List.of(first, second));
}
@Override
public ItemStack getItem(int i) {
return inputs.get(i);
}
public int size() {
return inputs.size();
}
/*? if <=1.20.1 {*/
@Override public int getContainerSize() { return size(); }
@Override public boolean isEmpty() { return inputs.stream().allMatch(ItemStack::isEmpty); }
@Override public ItemStack removeItem(int i, int j) { return ItemStack.EMPTY; }
@Override public ItemStack removeItemNoUpdate(int i) { return ItemStack.EMPTY; }
@Override public void setItem(int i, ItemStack itemStack) {}
@Override public void setChanged() {}
@Override public boolean stillValid(Player player) { return true; }
@Override public void clearContent() {}
/*?}*/
}
@@ -0,0 +1,202 @@
package net.cmr.jurassicrevived.recipe;
//? if >1.20.1 {
/*import com.mojang.serialization.Codec;
import com.mojang.serialization.DataResult;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.HolderLookup;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.ByteBufCodecs;
import net.minecraft.network.codec.StreamCodec;
*///?} else {
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import net.minecraft.core.RegistryAccess;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.util.GsonHelper;
//?}
import net.minecraft.core.NonNullList;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.*;
import net.minecraft.world.level.Level;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
//? if >1.20.1 {
/*public record EmbryonicMachineRecipe(NonNullList<Ingredient> inputs, ItemStack output, Map<ResourceLocation, Integer> weights) implements Recipe<EmbryonicMachineRecipeInput> {
*///?} else {
public class EmbryonicMachineRecipe implements Recipe<EmbryonicMachineRecipeInput> {
private final NonNullList<Ingredient> inputs;
private final ItemStack output;
private final ResourceLocation id;
private final Map<ResourceLocation, Integer> weights;
//?}
//? if <=1.20.1 {
public EmbryonicMachineRecipe(ResourceLocation id, NonNullList<Ingredient> inputs, ItemStack output, Map<ResourceLocation, Integer> weights) {
this.id = id;
this.inputs = inputs;
this.output = output;
this.weights = Map.copyOf(weights);
}
//?}
@Override
public boolean matches(@NotNull EmbryonicMachineRecipeInput input, Level level) {
if (level.isClientSide()) return false;
//? if >1.20.1 {
/*ItemStack in0 = input.getItem(0);
ItemStack in1 = input.getItem(1);
ItemStack in2 = input.getItem(2);
*///?} else {
ItemStack in0 = input.getItem(0);
ItemStack in1 = input.getItem(1);
ItemStack in2 = input.getItem(2);
//?}
boolean testTubeOk = inputs.get(0).test(in0);
boolean materialOk = inputs.get(1).test(in1);
boolean frogOk = inputs.size() > 2 && inputs.get(2).test(in2);
return testTubeOk && materialOk && frogOk;
}
//? if >1.20.1 {
/*@Override
public @NotNull ItemStack assemble(EmbryonicMachineRecipeInput input, HolderLookup.Provider registries) {
return output.copy();
}
@Override
public @NotNull ItemStack getResultItem(HolderLookup.Provider registries) {
return output.copy();
}
*///?} else {
@Override
public ItemStack assemble(EmbryonicMachineRecipeInput input, RegistryAccess registries) {
return output.copy();
}
@Override
public ItemStack getResultItem(RegistryAccess registries) {
return output.copy();
}
@Override
public ResourceLocation getId() {
return id;
}
//?}
@Override
public boolean canCraftInDimensions(int width, int height) {
return true;
}
@Override
public @NotNull NonNullList<Ingredient> getIngredients() {
return inputs;
}
@Override
public @NotNull RecipeSerializer<?> getSerializer() {
return ModRecipes.EMBRYONIC_MACHINE_SERIALIZER.get();
}
@Override
public @NotNull RecipeType<?> getType() {
return ModRecipes.EMBRYONIC_MACHINE_RECIPE_TYPE.get();
}
public int getWeightFor(Item item) {
ResourceLocation key = BuiltInRegistries.ITEM.getKey(item);
return weights.getOrDefault(key, 1);
}
//? if >1.20.1 {
/*public Map<ResourceLocation, Integer> weights() { return weights; }
public ItemStack output() { return output; }
*///?}
public static class Serializer implements RecipeSerializer<EmbryonicMachineRecipe> {
//? if >1.20.1 {
/*private static final Codec<Map<ResourceLocation, Integer>> WEIGHTS_CODEC =
Codec.unboundedMap(ResourceLocation.CODEC, Codec.INT);
public static final MapCodec<EmbryonicMachineRecipe> CODEC = RecordCodecBuilder.mapCodec(inst -> inst.group(
Ingredient.CODEC_NONEMPTY.listOf().fieldOf("ingredients").flatXmap(list -> {
if (list.size() != 3) return DataResult.error(() -> "Must have 3 ingredients");
return DataResult.success(NonNullList.of(Ingredient.EMPTY, list.toArray(Ingredient[]::new)));
}, DataResult::success).forGetter(EmbryonicMachineRecipe::inputs),
ItemStack.CODEC.fieldOf("result").forGetter(EmbryonicMachineRecipe::output),
WEIGHTS_CODEC.optionalFieldOf("weights", Map.of()).forGetter(EmbryonicMachineRecipe::weights)
).apply(inst, EmbryonicMachineRecipe::new));
public static final StreamCodec<RegistryFriendlyByteBuf, EmbryonicMachineRecipe> STREAM_CODEC = StreamCodec.of(
(buf, recipe) -> {
ByteBufCodecs.collection(NonNullList::createWithCapacity, Ingredient.CONTENTS_STREAM_CODEC).encode(buf, recipe.inputs());
ItemStack.STREAM_CODEC.encode(buf, recipe.output());
buf.writeMap(recipe.weights(), ResourceLocation.STREAM_CODEC, ByteBufCodecs.VAR_INT);
},
buf -> {
NonNullList<Ingredient> inputs = ByteBufCodecs.collection(NonNullList::createWithCapacity, Ingredient.CONTENTS_STREAM_CODEC).decode(buf);
ItemStack output = ItemStack.STREAM_CODEC.decode(buf);
Map<ResourceLocation, Integer> weights = buf.readMap(ResourceLocation.STREAM_CODEC, ByteBufCodecs.VAR_INT);
return new EmbryonicMachineRecipe(inputs, output, weights);
}
);
@Override public MapCodec<EmbryonicMachineRecipe> codec() { return CODEC; }
@Override public StreamCodec<RegistryFriendlyByteBuf, EmbryonicMachineRecipe> streamCodec() { return STREAM_CODEC; }
*///?} else {
@Override
public EmbryonicMachineRecipe fromJson(ResourceLocation id, JsonObject json) {
ItemStack output = ShapedRecipe.itemStackFromJson(GsonHelper.getAsJsonObject(json, "result"));
JsonArray ingredients = GsonHelper.getAsJsonArray(json, "ingredients");
NonNullList<Ingredient> inputs = NonNullList.withSize(3, Ingredient.EMPTY);
for (int i = 0; i < inputs.size(); i++) {
inputs.set(i, Ingredient.fromJson(ingredients.get(i)));
}
Map<ResourceLocation, Integer> weights = new HashMap<>();
if (json.has("weights")) {
JsonObject weightsObj = json.getAsJsonObject("weights");
for (String key : weightsObj.keySet()) {
weights.put(ResourceLocation.tryParse(key), weightsObj.get(key).getAsInt());
}
}
return new EmbryonicMachineRecipe(id, inputs, output, weights);
}
@Override
public EmbryonicMachineRecipe fromNetwork(ResourceLocation id, FriendlyByteBuf buf) {
int size = buf.readVarInt();
NonNullList<Ingredient> inputs = NonNullList.withSize(size, Ingredient.EMPTY);
for (int i = 0; i < size; i++) {
inputs.set(i, Ingredient.fromNetwork(buf));
}
ItemStack output = buf.readItem();
Map<ResourceLocation, Integer> weights = buf.readMap(FriendlyByteBuf::readResourceLocation, FriendlyByteBuf::readVarInt);
return new EmbryonicMachineRecipe(id, inputs, output, weights);
}
@Override
public void toNetwork(FriendlyByteBuf buf, EmbryonicMachineRecipe recipe) {
buf.writeVarInt(recipe.getIngredients().size());
for (Ingredient ing : recipe.getIngredients()) {
ing.toNetwork(buf);
}
buf.writeItem(recipe.output);
buf.writeMap(recipe.weights, FriendlyByteBuf::writeResourceLocation, FriendlyByteBuf::writeVarInt);
}
//?}
}
}
@@ -0,0 +1,36 @@
package net.cmr.jurassicrevived.recipe;
import net.minecraft.world.item.ItemStack;
//? if >1.20.1 {
/*import net.minecraft.world.item.crafting.RecipeInput;
*///?} else {
import net.minecraft.world.Container;
import net.minecraft.world.SimpleContainer;
//?}
import java.util.List;
//? if >1.20.1 {
/*public record EmbryonicMachineRecipeInput(ItemStack testTube, ItemStack material, ItemStack frog) implements RecipeInput {
@Override
public ItemStack getItem(int index) {
return switch (index) {
case 0 -> testTube;
case 1 -> material;
case 2 -> frog;
default -> throw new IllegalArgumentException("Unexpected slot index: " + index);
};
}
@Override
public int size() {
return 3;
}
}
*///?} else {
public class EmbryonicMachineRecipeInput extends SimpleContainer {
public EmbryonicMachineRecipeInput(ItemStack testTube, ItemStack material, ItemStack frog) {
super(testTube, material, frog);
}
}
//?}
@@ -0,0 +1,228 @@
package net.cmr.jurassicrevived.recipe;
//? if >1.20.1 {
/*import com.mojang.serialization.Codec;
import com.mojang.serialization.DataResult;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.HolderLookup;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.ByteBufCodecs;
import net.minecraft.network.codec.StreamCodec;
*///?} else {
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import net.minecraft.core.RegistryAccess;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.util.GsonHelper;
//?}
import net.cmr.jurassicrevived.util.ModTags;
import net.minecraft.core.NonNullList;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.RandomSource;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.*;
import net.minecraft.world.level.Level;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
import java.util.HashMap;
import java.util.List;
//? if >1.20.1 {
/*public record FossilCleanerRecipe(NonNullList<Ingredient> inputs, ItemStack output, Map<ResourceLocation, Integer> weights) implements Recipe<FossilCleanerRecipeInput> {
*///?} else {
public class FossilCleanerRecipe implements Recipe<FossilCleanerRecipeInput> {
private final NonNullList<Ingredient> inputs;
private final ItemStack output;
private final ResourceLocation id;
private final Map<ResourceLocation, Integer> weights;
//?}
//? if <=1.20.1 {
public FossilCleanerRecipe(ResourceLocation id, NonNullList<Ingredient> inputs, ItemStack output, Map<ResourceLocation, Integer> weights) {
this.id = id;
this.inputs = inputs;
this.output = output;
this.weights = Map.copyOf(weights);
}
//?}
@Override
public boolean matches(@NotNull FossilCleanerRecipeInput input, Level level) {
if (level.isClientSide()) return false;
if (inputs.isEmpty()) return false;
// Single fossil block ingredient lives in machine slot 1 (input.getItem(1))
return inputs.get(0).test(input.getItem(1));
}
//? if >1.20.1 {
/*@Override
public @NotNull ItemStack assemble(FossilCleanerRecipeInput input, HolderLookup.Provider registries) {
return getWeightedResult(registries);
}
@Override
public @NotNull ItemStack getResultItem(HolderLookup.Provider registries) {
return output.copy();
}
*///?} else {
@Override
public ItemStack assemble(FossilCleanerRecipeInput input, RegistryAccess registries) {
return getWeightedResult(registries);
}
@Override
public ItemStack getResultItem(RegistryAccess registries) {
return output.copy();
}
@Override
public ResourceLocation getId() {
return id;
}
//?}
private ItemStack getWeightedResult(Object registries) {
//? if >1.20.1 {
/*var fossilTag = BuiltInRegistries.ITEM.getOrCreateTag(ModTags.Items.FOSSILS);
List<ItemStack> candidates = fossilTag.stream().map(ItemStack::new).toList();
*///?} else {
ItemStack[] candidatesArr = Ingredient.of(ModTags.Items.FOSSILS).getItems();
List<ItemStack> candidates = List.of(candidatesArr);
//?}
if (candidates.isEmpty()) return output.copy();
RandomSource random = RandomSource.create();
long total = 0;
int[] weightsArray = new int[candidates.size()];
for (int i = 0; i < candidates.size(); i++) {
Item item = candidates.get(i).getItem();
ResourceLocation key = BuiltInRegistries.ITEM.getKey(item);
int w = Math.max(0, weights.getOrDefault(key, 1));
weightsArray[i] = w;
total += w;
}
if (total <= 0) return candidates.get(random.nextInt(candidates.size())).copy();
long roll = 1L + (total <= Integer.MAX_VALUE ? random.nextInt((int) total) : Math.abs(random.nextLong()) % total);
long cumulative = 0;
for (int i = 0; i < candidates.size(); i++) {
cumulative += weightsArray[i];
if (roll <= cumulative) return candidates.get(i).copy();
}
return candidates.get(candidates.size() - 1).copy();
}
@Override
public boolean canCraftInDimensions(int width, int height) {
return true;
}
@Override
public @NotNull NonNullList<Ingredient> getIngredients() {
return inputs;
}
@Override
public @NotNull RecipeSerializer<?> getSerializer() {
return ModRecipes.FOSSIL_CLEANER_SERIALIZER.get();
}
@Override
public @NotNull RecipeType<?> getType() {
return ModRecipes.FOSSIL_CLEANER_RECIPE_TYPE.get();
}
public int getWeightFor(Item item) {
ResourceLocation key = BuiltInRegistries.ITEM.getKey(item);
return weights.getOrDefault(key, 1);
}
//? if <=1.20.1 {
public ItemStack output() { return output; }
//?}
//? if >1.20.1 {
/*public Map<ResourceLocation, Integer> weights() { return weights; }
public ItemStack output() { return output; }
*///?}
public static class Serializer implements RecipeSerializer<FossilCleanerRecipe> {
//? if >1.20.1 {
/*private static final Codec<Map<ResourceLocation, Integer>> WEIGHTS_CODEC =
Codec.unboundedMap(ResourceLocation.CODEC, Codec.INT);
public static final MapCodec<FossilCleanerRecipe> CODEC = RecordCodecBuilder.mapCodec(inst -> inst.group(
Ingredient.CODEC_NONEMPTY.listOf().fieldOf("ingredients").flatXmap(list -> {
if (list.size() != 1) return DataResult.error(() -> "Must have 1 ingredient");
return DataResult.success(NonNullList.of(Ingredient.EMPTY, list.toArray(Ingredient[]::new)));
}, DataResult::success).forGetter(FossilCleanerRecipe::inputs),
ItemStack.CODEC.fieldOf("result").forGetter(FossilCleanerRecipe::output),
WEIGHTS_CODEC.optionalFieldOf("fossil_weights", Map.of()).forGetter(FossilCleanerRecipe::weights)
).apply(inst, FossilCleanerRecipe::new));
public static final StreamCodec<RegistryFriendlyByteBuf, FossilCleanerRecipe> STREAM_CODEC = StreamCodec.of(
(buf, recipe) -> {
ByteBufCodecs.collection(NonNullList::createWithCapacity, Ingredient.CONTENTS_STREAM_CODEC).encode(buf, recipe.inputs());
ItemStack.STREAM_CODEC.encode(buf, recipe.output());
buf.writeMap(recipe.weights(), ResourceLocation.STREAM_CODEC, ByteBufCodecs.VAR_INT);
},
buf -> {
NonNullList<Ingredient> inputs = ByteBufCodecs.collection(NonNullList::createWithCapacity, Ingredient.CONTENTS_STREAM_CODEC).decode(buf);
ItemStack output = ItemStack.STREAM_CODEC.decode(buf);
Map<ResourceLocation, Integer> weights = buf.readMap(ResourceLocation.STREAM_CODEC, ByteBufCodecs.VAR_INT);
return new FossilCleanerRecipe(inputs, output, weights);
}
);
@Override public MapCodec<FossilCleanerRecipe> codec() { return CODEC; }
@Override public StreamCodec<RegistryFriendlyByteBuf, FossilCleanerRecipe> streamCodec() { return STREAM_CODEC; }
*///?} else {
@Override
public FossilCleanerRecipe fromJson(ResourceLocation id, JsonObject json) {
ItemStack output = ShapedRecipe.itemStackFromJson(GsonHelper.getAsJsonObject(json, "result"));
JsonArray ingredients = GsonHelper.getAsJsonArray(json, "ingredients");
NonNullList<Ingredient> inputs = NonNullList.withSize(1, Ingredient.EMPTY);
inputs.set(0, Ingredient.fromJson(ingredients.get(0)));
Map<ResourceLocation, Integer> weights = new HashMap<>();
if (json.has("fossil_weights")) {
JsonObject weightsObj = json.getAsJsonObject("fossil_weights");
for (String key : weightsObj.keySet()) {
weights.put(ResourceLocation.tryParse(key), weightsObj.get(key).getAsInt());
}
}
return new FossilCleanerRecipe(id, inputs, output, weights);
}
@Override
public FossilCleanerRecipe fromNetwork(ResourceLocation id, FriendlyByteBuf buf) {
int size = buf.readVarInt();
NonNullList<Ingredient> inputs = NonNullList.withSize(size, Ingredient.EMPTY);
for (int i = 0; i < size; i++) {
inputs.set(i, Ingredient.fromNetwork(buf));
}
ItemStack output = buf.readItem();
Map<ResourceLocation, Integer> weights = buf.readMap(FriendlyByteBuf::readResourceLocation, FriendlyByteBuf::readVarInt);
return new FossilCleanerRecipe(id, inputs, output, weights);
}
@Override
public void toNetwork(FriendlyByteBuf buf, FossilCleanerRecipe recipe) {
buf.writeVarInt(recipe.inputs.size());
for (Ingredient ing : recipe.inputs) {
ing.toNetwork(buf);
}
buf.writeItem(recipe.output);
buf.writeMap(recipe.weights, FriendlyByteBuf::writeResourceLocation, FriendlyByteBuf::writeVarInt);
}
//?}
}
}
@@ -0,0 +1,34 @@
package net.cmr.jurassicrevived.recipe;
import net.minecraft.world.item.ItemStack;
//? if >1.20.1 {
/*import net.minecraft.world.item.crafting.RecipeInput;
*///?} else {
import net.minecraft.world.SimpleContainer;
//?}
import java.util.List;
//? if >1.20.1 {
/*public record FossilCleanerRecipeInput(ItemStack material, ItemStack fuel) implements RecipeInput {
@Override
public ItemStack getItem(int index) {
return switch (index) {
case 0 -> material;
case 1 -> fuel;
default -> throw new IllegalArgumentException("Unexpected slot index: " + index);
};
}
@Override
public int size() {
return 2;
}
}
*///?} else {
public class FossilCleanerRecipeInput extends SimpleContainer {
public FossilCleanerRecipeInput(ItemStack material, ItemStack fuel) {
super(material, fuel);
}
}
//?}
@@ -0,0 +1,224 @@
package net.cmr.jurassicrevived.recipe;
//? if >1.20.1 {
/*import com.mojang.serialization.Codec;
import com.mojang.serialization.DataResult;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.HolderLookup;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.ByteBufCodecs;
import net.minecraft.network.codec.StreamCodec;
*///?} else {
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import net.minecraft.core.RegistryAccess;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.util.GsonHelper;
//?}
import net.minecraft.core.NonNullList;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.RandomSource;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.*;
import net.minecraft.world.level.Level;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
//? if >1.20.1 {
/*public record FossilGrinderRecipe(NonNullList<Ingredient> inputs, ItemStack output, Map<ResourceLocation, Integer> weights) implements Recipe<FossilGrinderRecipeInput> {
*///?} else {
public class FossilGrinderRecipe implements Recipe<FossilGrinderRecipeInput> {
private final NonNullList<Ingredient> inputs;
private final ItemStack output;
private final ResourceLocation id;
private final Map<ResourceLocation, Integer> weights;
//?}
//? if <=1.20.1 {
public FossilGrinderRecipe(ResourceLocation id, NonNullList<Ingredient> inputs, ItemStack output, Map<ResourceLocation, Integer> weights) {
this.id = id;
this.inputs = inputs;
this.output = output;
this.weights = Map.copyOf(weights);
}
//?}
@Override
public boolean matches(@NotNull FossilGrinderRecipeInput input, Level level) {
if (level.isClientSide()) return false;
if (inputs.isEmpty()) return false;
return inputs.get(0).test(input.getItem(0));
}
//? if >1.20.1 {
/*@Override
public @NotNull ItemStack assemble(FossilGrinderRecipeInput input, HolderLookup.Provider registries) {
return getWeightedResult();
}
@Override
public @NotNull ItemStack getResultItem(HolderLookup.Provider registries) {
return output.copy();
}
*///?} else {
@Override
public ItemStack assemble(FossilGrinderRecipeInput input, RegistryAccess registries) {
return getWeightedResult();
}
@Override
public ItemStack getResultItem(RegistryAccess registries) {
return output.copy();
}
@Override
public ResourceLocation getId() {
return id;
}
//?}
private ItemStack getWeightedResult() {
if (weights.isEmpty()) return output.copy();
RandomSource random = RandomSource.create();
long total = 0;
List<ResourceLocation> keys = new ArrayList<>(weights.keySet());
int[] weightsArray = new int[keys.size()];
for (int i = 0; i < keys.size(); i++) {
int w = Math.max(0, weights.getOrDefault(keys.get(i), 0));
weightsArray[i] = w;
total += w;
}
if (total <= 0) {
Item fallback = BuiltInRegistries.ITEM.get(keys.get(random.nextInt(keys.size())));
return new ItemStack(fallback);
}
long roll = 1L + (total <= Integer.MAX_VALUE ? random.nextInt((int) total) : Math.abs(random.nextLong()) % total);
long cumulative = 0;
for (int i = 0; i < keys.size(); i++) {
cumulative += weightsArray[i];
if (roll <= cumulative) {
Item chosen = BuiltInRegistries.ITEM.get(keys.get(i));
return new ItemStack(chosen);
}
}
return new ItemStack(BuiltInRegistries.ITEM.get(keys.get(keys.size() - 1)));
}
@Override
public boolean canCraftInDimensions(int width, int height) {
return true;
}
@Override
public @NotNull NonNullList<Ingredient> getIngredients() {
return inputs;
}
@Override
public @NotNull RecipeSerializer<?> getSerializer() {
return ModRecipes.FOSSIL_GRINDER_SERIALIZER.get();
}
@Override
public @NotNull RecipeType<?> getType() {
return ModRecipes.FOSSIL_GRINDER_RECIPE_TYPE.get();
}
//? if <=1.20.1 {
public Map<ResourceLocation, Integer> weights() { return weights; }
//?}
//? if >1.20.1 {
/*public Map<ResourceLocation, Integer> weights() { return weights; }
public ItemStack output() { return output; }
*///?}
public int getWeightFor(Item item) {
ResourceLocation key = BuiltInRegistries.ITEM.getKey(item);
return weights.getOrDefault(key, 0);
}
public static class Serializer implements RecipeSerializer<FossilGrinderRecipe> {
//? if >1.20.1 {
/*private static final Codec<Map<ResourceLocation, Integer>> WEIGHTS_CODEC =
Codec.unboundedMap(ResourceLocation.CODEC, Codec.INT);
public static final MapCodec<FossilGrinderRecipe> CODEC = RecordCodecBuilder.mapCodec(inst -> inst.group(
Ingredient.CODEC_NONEMPTY.listOf().fieldOf("ingredients").flatXmap(list -> {
if (list.size() != 1) return DataResult.error(() -> "Must have 1 ingredient");
return DataResult.success(NonNullList.of(Ingredient.EMPTY, list.toArray(Ingredient[]::new)));
}, DataResult::success).forGetter(FossilGrinderRecipe::inputs),
ItemStack.CODEC.fieldOf("result").forGetter(FossilGrinderRecipe::output),
WEIGHTS_CODEC.optionalFieldOf("weighted_outputs", Map.of()).forGetter(FossilGrinderRecipe::weights)
).apply(inst, FossilGrinderRecipe::new));
public static final StreamCodec<RegistryFriendlyByteBuf, FossilGrinderRecipe> STREAM_CODEC = StreamCodec.of(
(buf, recipe) -> {
ByteBufCodecs.collection(NonNullList::createWithCapacity, Ingredient.CONTENTS_STREAM_CODEC).encode(buf, recipe.inputs());
ItemStack.STREAM_CODEC.encode(buf, recipe.output());
buf.writeMap(recipe.weights(), ResourceLocation.STREAM_CODEC, ByteBufCodecs.VAR_INT);
},
buf -> {
NonNullList<Ingredient> inputs = ByteBufCodecs.collection(NonNullList::createWithCapacity, Ingredient.CONTENTS_STREAM_CODEC).decode(buf);
ItemStack output = ItemStack.STREAM_CODEC.decode(buf);
Map<ResourceLocation, Integer> weights = buf.readMap(ResourceLocation.STREAM_CODEC, ByteBufCodecs.VAR_INT);
return new FossilGrinderRecipe(inputs, output, weights);
}
);
@Override public MapCodec<FossilGrinderRecipe> codec() { return CODEC; }
@Override public StreamCodec<RegistryFriendlyByteBuf, FossilGrinderRecipe> streamCodec() { return STREAM_CODEC; }
*///?} else {
@Override
public FossilGrinderRecipe fromJson(ResourceLocation id, JsonObject json) {
ItemStack output = ShapedRecipe.itemStackFromJson(GsonHelper.getAsJsonObject(json, "result"));
JsonArray ingredients = GsonHelper.getAsJsonArray(json, "ingredients");
NonNullList<Ingredient> inputs = NonNullList.withSize(1, Ingredient.EMPTY);
inputs.set(0, Ingredient.fromJson(ingredients.get(0)));
Map<ResourceLocation, Integer> weights = new HashMap<>();
if (json.has("weighted_outputs")) {
JsonObject weightsObj = json.getAsJsonObject("weighted_outputs");
for (String key : weightsObj.keySet()) {
weights.put(ResourceLocation.tryParse(key), weightsObj.get(key).getAsInt());
}
}
return new FossilGrinderRecipe(id, inputs, output, weights);
}
@Override
public FossilGrinderRecipe fromNetwork(ResourceLocation id, FriendlyByteBuf buf) {
int size = buf.readVarInt();
NonNullList<Ingredient> inputs = NonNullList.withSize(size, Ingredient.EMPTY);
for (int i = 0; i < size; i++) {
inputs.set(i, Ingredient.fromNetwork(buf));
}
ItemStack output = buf.readItem();
Map<ResourceLocation, Integer> weights = buf.readMap(FriendlyByteBuf::readResourceLocation, FriendlyByteBuf::readVarInt);
return new FossilGrinderRecipe(id, inputs, output, weights);
}
@Override
public void toNetwork(FriendlyByteBuf buf, FossilGrinderRecipe recipe) {
buf.writeVarInt(recipe.inputs.size());
for (Ingredient ing : recipe.inputs) {
ing.toNetwork(buf);
}
buf.writeItem(recipe.output);
buf.writeMap(recipe.weights, FriendlyByteBuf::writeResourceLocation, FriendlyByteBuf::writeVarInt);
}
//?}
}
}
@@ -0,0 +1,29 @@
package net.cmr.jurassicrevived.recipe;
import net.minecraft.world.item.ItemStack;
//? if >1.20.1 {
/*import net.minecraft.world.item.crafting.RecipeInput;
*///?} else {
import net.minecraft.world.SimpleContainer;
//?}
//? if >1.20.1 {
/*public record FossilGrinderRecipeInput(ItemStack input) implements RecipeInput {
@Override
public ItemStack getItem(int index) {
if (index == 0) return input;
throw new IllegalArgumentException("Unexpected slot index: " + index);
}
@Override
public int size() {
return 1;
}
}
*///?} else {
public class FossilGrinderRecipeInput extends SimpleContainer {
public FossilGrinderRecipeInput(ItemStack input) {
super(input);
}
}
//?}
@@ -0,0 +1,158 @@
package net.cmr.jurassicrevived.recipe;
//? if >1.20.1 {
/*import com.mojang.serialization.DataResult;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.HolderLookup;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.ByteBufCodecs;
import net.minecraft.network.codec.StreamCodec;
*///?} else {
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import net.minecraft.core.RegistryAccess;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.util.GsonHelper;
//?}
import net.minecraft.core.NonNullList;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.*;
import net.minecraft.world.level.Level;
import org.jetbrains.annotations.NotNull;
import java.util.List;
//? if >1.20.1 {
/*public record IncubatorRecipe(NonNullList<Ingredient> inputs, ItemStack output) implements Recipe<IncubatorRecipeInput> {
*///?} else {
public class IncubatorRecipe implements Recipe<IncubatorRecipeInput> {
private final NonNullList<Ingredient> inputs;
private final ItemStack output;
private final ResourceLocation id;
//?}
//? if <=1.20.1 {
public IncubatorRecipe(ResourceLocation id, NonNullList<Ingredient> inputs, ItemStack output) {
this.id = id;
this.inputs = inputs;
this.output = output;
}
//?}
@Override
public boolean matches(@NotNull IncubatorRecipeInput input, Level level) {
if (level.isClientSide()) return false;
if (inputs.isEmpty()) return false;
return inputs.get(0).test(input.getItem(0));
}
//? if >1.20.1 {
/*@Override
public @NotNull ItemStack assemble(IncubatorRecipeInput input, HolderLookup.Provider registries) {
return output.copy();
}
@Override
public @NotNull ItemStack getResultItem(HolderLookup.Provider registries) {
return output.copy();
}
*///?} else {
@Override
public ItemStack assemble(IncubatorRecipeInput input, RegistryAccess registries) {
return output.copy();
}
@Override
public ItemStack getResultItem(RegistryAccess registries) {
return output.copy();
}
@Override
public ResourceLocation getId() {
return id;
}
//?}
@Override
public boolean canCraftInDimensions(int width, int height) {
return true;
}
@Override
public @NotNull NonNullList<Ingredient> getIngredients() {
return inputs;
}
@Override
public @NotNull RecipeSerializer<?> getSerializer() {
return ModRecipes.INCUBATOR_SERIALIZER.get();
}
@Override
public @NotNull RecipeType<?> getType() {
return ModRecipes.INCUBATOR_RECIPE_TYPE.get();
}
//? if >1.20.1 {
/*public ItemStack output() { return output; }
*///?}
public static class Serializer implements RecipeSerializer<IncubatorRecipe> {
//? if >1.20.1 {
/*public static final MapCodec<IncubatorRecipe> CODEC = RecordCodecBuilder.mapCodec(inst -> inst.group(
Ingredient.CODEC_NONEMPTY.listOf().fieldOf("ingredients").flatXmap(list -> {
if (list.size() != 1) return DataResult.error(() -> "Must have 1 ingredient");
return DataResult.success(NonNullList.of(Ingredient.EMPTY, list.toArray(Ingredient[]::new)));
}, DataResult::success).forGetter(IncubatorRecipe::inputs),
ItemStack.CODEC.fieldOf("result").forGetter(IncubatorRecipe::output)
).apply(inst, IncubatorRecipe::new));
public static final StreamCodec<RegistryFriendlyByteBuf, IncubatorRecipe> STREAM_CODEC = StreamCodec.of(
(buf, recipe) -> {
ByteBufCodecs.collection(NonNullList::createWithCapacity, Ingredient.CONTENTS_STREAM_CODEC).encode(buf, recipe.inputs());
ItemStack.STREAM_CODEC.encode(buf, recipe.output());
},
buf -> {
NonNullList<Ingredient> inputs = ByteBufCodecs.collection(NonNullList::createWithCapacity, Ingredient.CONTENTS_STREAM_CODEC).decode(buf);
ItemStack output = ItemStack.STREAM_CODEC.decode(buf);
return new IncubatorRecipe(inputs, output);
}
);
@Override public MapCodec<IncubatorRecipe> codec() { return CODEC; }
@Override public StreamCodec<RegistryFriendlyByteBuf, IncubatorRecipe> streamCodec() { return STREAM_CODEC; }
*///?} else {
@Override
public IncubatorRecipe fromJson(ResourceLocation id, JsonObject json) {
JsonArray arr = GsonHelper.getAsJsonArray(json, "ingredients");
NonNullList<Ingredient> inputs = NonNullList.withSize(1, Ingredient.EMPTY);
inputs.set(0, Ingredient.fromJson(arr.get(0)));
ItemStack output = ShapedRecipe.itemStackFromJson(GsonHelper.getAsJsonObject(json, "result"));
return new IncubatorRecipe(id, inputs, output);
}
@Override
public IncubatorRecipe fromNetwork(ResourceLocation id, FriendlyByteBuf buf) {
int size = buf.readVarInt();
NonNullList<Ingredient> inputs = NonNullList.withSize(size, Ingredient.EMPTY);
for (int i = 0; i < size; i++) {
inputs.set(i, Ingredient.fromNetwork(buf));
}
ItemStack output = buf.readItem();
return new IncubatorRecipe(id, inputs, output);
}
@Override
public void toNetwork(FriendlyByteBuf buf, IncubatorRecipe recipe) {
buf.writeVarInt(recipe.inputs.size());
for (Ingredient ing : recipe.inputs) {
ing.toNetwork(buf);
}
buf.writeItem(recipe.output);
}
//?}
}
}
@@ -0,0 +1,29 @@
package net.cmr.jurassicrevived.recipe;
import net.minecraft.world.item.ItemStack;
//? if >1.20.1 {
/*import net.minecraft.world.item.crafting.RecipeInput;
*///?} else {
import net.minecraft.world.SimpleContainer;
//?}
//? if >1.20.1 {
/*public record IncubatorRecipeInput(ItemStack input) implements RecipeInput {
@Override
public ItemStack getItem(int index) {
if (index == 0) return input;
throw new IllegalArgumentException("Unexpected slot index: " + index);
}
@Override
public int size() {
return 1;
}
}
*///?} else {
public class IncubatorRecipeInput extends SimpleContainer {
public IncubatorRecipeInput(ItemStack input) {
super(input);
}
}
//?}
@@ -0,0 +1,100 @@
package net.cmr.jurassicrevived.recipe;
import dev.architectury.registry.registries.DeferredRegister;
import dev.architectury.registry.registries.RegistrySupplier;
import net.cmr.jurassicrevived.Constants;
import net.minecraft.core.registries.Registries;
import net.minecraft.world.item.crafting.RecipeSerializer;
import net.minecraft.world.item.crafting.RecipeType;
public class ModRecipes {
public static final DeferredRegister<RecipeSerializer<?>> SERIALIZERS =
DeferredRegister.create(Constants.MOD_ID, Registries.RECIPE_SERIALIZER);
public static final DeferredRegister<RecipeType<?>> TYPES =
DeferredRegister.create(Constants.MOD_ID, Registries.RECIPE_TYPE);
public static final RegistrySupplier<RecipeSerializer<DNAExtractorRecipe>> DNA_EXTRACTOR_SERIALIZER =
SERIALIZERS.register("dna_extracting", DNAExtractorRecipe.Serializer::new);
public static final RegistrySupplier<RecipeType<DNAExtractorRecipe>> DNA_EXTRACTOR_RECIPE_TYPE =
TYPES.register("dna_extracting", () -> new RecipeType<DNAExtractorRecipe>() {
@Override
public String toString() {
return "dna_extracting";
}
});
public static final RegistrySupplier<RecipeSerializer<DNAAnalyzerRecipe>> DNA_ANALYZER_SERIALIZER =
SERIALIZERS.register("dna_analyzing", DNAAnalyzerRecipe.Serializer::new);
public static final RegistrySupplier<RecipeType<DNAAnalyzerRecipe>> DNA_ANALYZER_RECIPE_TYPE =
TYPES.register("dna_analyzing", () -> new RecipeType<DNAAnalyzerRecipe>() {
@Override
public String toString() {
return "dna_analyzing";
}
});
public static final RegistrySupplier<RecipeSerializer<FossilGrinderRecipe>> FOSSIL_GRINDER_SERIALIZER =
SERIALIZERS.register("fossil_grinding", FossilGrinderRecipe.Serializer::new);
public static final RegistrySupplier<RecipeType<FossilGrinderRecipe>> FOSSIL_GRINDER_RECIPE_TYPE =
TYPES.register("fossil_grinding", () -> new RecipeType<FossilGrinderRecipe>() {
@Override
public String toString() {
return "fossil_grinding";
}
});
public static final RegistrySupplier<RecipeSerializer<FossilCleanerRecipe>> FOSSIL_CLEANER_SERIALIZER =
SERIALIZERS.register("fossil_cleaning", FossilCleanerRecipe.Serializer::new);
public static final RegistrySupplier<RecipeType<FossilCleanerRecipe>> FOSSIL_CLEANER_RECIPE_TYPE =
TYPES.register("fossil_cleaning", () -> new RecipeType<FossilCleanerRecipe>() {
@Override
public String toString() {
return "fossil_cleaning";
}
});
public static final RegistrySupplier<RecipeSerializer<DNAHybridizerRecipe>> DNA_HYBRIDIZER_SERIALIZER =
SERIALIZERS.register("dna_hybridizing", DNAHybridizerRecipe.Serializer::new);
public static final RegistrySupplier<RecipeType<DNAHybridizerRecipe>> DNA_HYBRIDIZER_RECIPE_TYPE =
TYPES.register("dna_hybridizing", () -> new RecipeType<DNAHybridizerRecipe>() {
@Override
public String toString() {
return "dna_hybridizing";
}
});
public static final RegistrySupplier<RecipeSerializer<EmbryonicMachineRecipe>> EMBRYONIC_MACHINE_SERIALIZER =
SERIALIZERS.register("embryonic_machining", EmbryonicMachineRecipe.Serializer::new);
public static final RegistrySupplier<RecipeType<EmbryonicMachineRecipe>> EMBRYONIC_MACHINE_RECIPE_TYPE =
TYPES.register("embryonic_machining", () -> new RecipeType<EmbryonicMachineRecipe>() {
@Override
public String toString() {
return "embryonic_machining";
}
});
public static final RegistrySupplier<RecipeSerializer<EmbryoCalcificationMachineRecipe>> EMBRYO_CALCIFICATION_MACHINE_SERIALIZER =
SERIALIZERS.register("embryo_calcification_machining", EmbryoCalcificationMachineRecipe.Serializer::new);
public static final RegistrySupplier<RecipeType<EmbryoCalcificationMachineRecipe>> EMBRYO_CALCIFICATION_MACHINE_RECIPE_TYPE =
TYPES.register("embryo_calcification_machining", () -> new RecipeType<EmbryoCalcificationMachineRecipe>() {
@Override
public String toString() {
return "embryo_calcification_machining";
}
});
public static final RegistrySupplier<RecipeSerializer<IncubatorRecipe>> INCUBATOR_SERIALIZER =
SERIALIZERS.register("incubating", IncubatorRecipe.Serializer::new);
public static final RegistrySupplier<RecipeType<IncubatorRecipe>> INCUBATOR_RECIPE_TYPE =
TYPES.register("incubating", () -> new RecipeType<IncubatorRecipe>() {
@Override
public String toString() {
return "incubating";
}
});
public static void register() {
SERIALIZERS.register();
TYPES.register();
}
}