More work on recipes, custom ingredients, recipes, and constants should work now.
This commit is contained in:
parent
03d19f2e70
commit
02c31cc867
22 changed files with 599 additions and 683 deletions
|
@ -25,3 +25,23 @@
|
||||||
public String getGroup() {
|
public String getGroup() {
|
||||||
return this.field_201833_b;
|
return this.field_201833_b;
|
||||||
}
|
}
|
||||||
|
@@ -75,6 +71,7 @@
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Serializer implements IRecipeSerializer<FurnaceRecipe> {
|
||||||
|
+ private static ResourceLocation NAME = new ResourceLocation("minecraft", "smelting");
|
||||||
|
public FurnaceRecipe func_199425_a_(ResourceLocation p_199425_1_, JsonObject p_199425_2_) {
|
||||||
|
String s = JsonUtils.getString(p_199425_2_, "group", "");
|
||||||
|
Ingredient ingredient;
|
||||||
|
@@ -113,8 +110,9 @@
|
||||||
|
p_199427_1_.writeVarInt(p_199427_2_.field_201837_f);
|
||||||
|
}
|
||||||
|
|
||||||
|
- public String func_199567_a() {
|
||||||
|
- return "smelting";
|
||||||
|
+ @Override
|
||||||
|
+ public ResourceLocation getName() {
|
||||||
|
+ return NAME;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
--- a/net/minecraft/item/crafting/IRecipeSerializer.java
|
||||||
|
+++ b/net/minecraft/item/crafting/IRecipeSerializer.java
|
||||||
|
@@ -11,5 +11,11 @@
|
||||||
|
|
||||||
|
void func_199427_a_(PacketBuffer p_199427_1_, T p_199427_2_);
|
||||||
|
|
||||||
|
- String func_199567_a();
|
||||||
|
+ @Deprecated //Modders, do not use, this is un-namespaced and thus could cause clashes.
|
||||||
|
+ default String func_199567_a() {
|
||||||
|
+ ResourceLocation name = getName(); //To keep compatibility with vanilla, anything in the "minecraft" namespace doesn't get a prefix.
|
||||||
|
+ return name.getNamespace().equals("minecraft") ? name.getPath() : name.toString();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ResourceLocation getName();
|
||||||
|
}
|
|
@ -7,7 +7,7 @@
|
||||||
-import net.minecraftforge.api.distmarker.Dist;
|
-import net.minecraftforge.api.distmarker.Dist;
|
||||||
-import net.minecraftforge.api.distmarker.OnlyIn;
|
-import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
|
||||||
public final class Ingredient implements Predicate<ItemStack> {
|
public class Ingredient implements Predicate<ItemStack> {
|
||||||
+ //Because Mojang caches things... we need to invalidate them.. so... here we go..
|
+ //Because Mojang caches things... we need to invalidate them.. so... here we go..
|
||||||
+ private static final java.util.Set<Ingredient> INSTANCES = java.util.Collections.newSetFromMap(new java.util.WeakHashMap<Ingredient, Boolean>());
|
+ private static final java.util.Set<Ingredient> INSTANCES = java.util.Collections.newSetFromMap(new java.util.WeakHashMap<Ingredient, Boolean>());
|
||||||
+ public static void invalidateAll() {
|
+ public static void invalidateAll() {
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
private IntList matchingStacksPacked;
|
private IntList matchingStacksPacked;
|
||||||
+ private final boolean isSimple;
|
+ private final boolean isSimple;
|
||||||
|
|
||||||
private Ingredient(Stream<? extends Ingredient.IItemList> p_i49381_1_) {
|
protected Ingredient(Stream<? extends Ingredient.IItemList> p_i49381_1_) {
|
||||||
this.field_199807_b = (Ingredient.IItemList[])p_i49381_1_.filter(field_209362_b).toArray((p_209360_0_) -> {
|
this.field_199807_b = (Ingredient.IItemList[])p_i49381_1_.filter(field_209362_b).toArray((p_209360_0_) -> {
|
||||||
return new Ingredient.IItemList[p_209360_0_];
|
return new Ingredient.IItemList[p_209360_0_];
|
||||||
});
|
});
|
||||||
|
@ -35,7 +35,18 @@
|
||||||
public ItemStack[] getMatchingStacks() {
|
public ItemStack[] getMatchingStacks() {
|
||||||
this.func_199806_d();
|
this.func_199806_d();
|
||||||
return this.matchingStacks;
|
return this.matchingStacks;
|
||||||
@@ -121,6 +127,15 @@
|
@@ -95,6 +101,10 @@
|
||||||
|
|
||||||
|
public final void func_199564_a(PacketBuffer p_199564_1_) {
|
||||||
|
this.func_199806_d();
|
||||||
|
+ if (!this.isVanilla()) {
|
||||||
|
+ net.minecraftforge.common.crafting.CraftingHelper.write(p_199564_1_, this);
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
p_199564_1_.writeVarInt(this.matchingStacks.length);
|
||||||
|
|
||||||
|
for(int i = 0; i < this.matchingStacks.length; ++i) {
|
||||||
|
@@ -121,6 +131,25 @@
|
||||||
return this.field_199807_b.length == 0 && (this.matchingStacks == null || this.matchingStacks.length == 0) && (this.matchingStacksPacked == null || this.matchingStacksPacked.isEmpty());
|
return this.field_199807_b.length == 0 && (this.matchingStacks == null || this.matchingStacks.length == 0) && (this.matchingStacksPacked == null || this.matchingStacksPacked.isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,10 +59,20 @@
|
||||||
+ return isSimple || this == EMPTY;
|
+ return isSimple || this == EMPTY;
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
private static Ingredient func_209357_a(Stream<? extends Ingredient.IItemList> p_209357_0_) {
|
+ private final boolean isVanilla = this.getClass() == Ingredient.class;
|
||||||
|
+ public final boolean isVanilla() {
|
||||||
|
+ return isVanilla;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ public net.minecraftforge.common.crafting.IIngredientSerializer<? extends Ingredient> getSerializer() {
|
||||||
|
+ if (!isVanilla()) throw new IllegalStateException("Modderrs must implement Ingredient.getSerializer in their custom Ingredients: " + this);
|
||||||
|
+ return net.minecraftforge.common.crafting.CraftingHelper.INGREDIENT_VANILLA;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
public static Ingredient func_209357_a(Stream<? extends Ingredient.IItemList> p_209357_0_) {
|
||||||
Ingredient ingredient = new Ingredient(p_209357_0_);
|
Ingredient ingredient = new Ingredient(p_209357_0_);
|
||||||
return ingredient.field_199807_b.length == 0 ? EMPTY : ingredient;
|
return ingredient.field_199807_b.length == 0 ? EMPTY : ingredient;
|
||||||
@@ -132,7 +147,6 @@
|
@@ -132,7 +161,6 @@
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,3 +80,50 @@
|
||||||
public static Ingredient fromStacks(ItemStack... stacks) {
|
public static Ingredient fromStacks(ItemStack... stacks) {
|
||||||
return func_209357_a(Arrays.stream(stacks).map((p_209356_0_) -> {
|
return func_209357_a(Arrays.stream(stacks).map((p_209356_0_) -> {
|
||||||
return new Ingredient.SingleItemList(p_209356_0_);
|
return new Ingredient.SingleItemList(p_209356_0_);
|
||||||
|
@@ -144,7 +172,12 @@
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Ingredient func_199566_b(PacketBuffer p_199566_0_) {
|
||||||
|
+ p_199566_0_.markReaderIndex();
|
||||||
|
int i = p_199566_0_.readVarInt();
|
||||||
|
+ if (i == -1) {
|
||||||
|
+ p_199566_0_.resetReaderIndex();
|
||||||
|
+ return net.minecraftforge.common.crafting.CraftingHelper.getIngredient(p_199566_0_.readResourceLocation(), p_199566_0_);
|
||||||
|
+ }
|
||||||
|
return func_209357_a(Stream.generate(() -> {
|
||||||
|
return new Ingredient.SingleItemList(p_199566_0_.readItemStack());
|
||||||
|
}).limit((long)i));
|
||||||
|
@@ -152,6 +185,8 @@
|
||||||
|
|
||||||
|
public static Ingredient func_199802_a(@Nullable JsonElement p_199802_0_) {
|
||||||
|
if (p_199802_0_ != null && !p_199802_0_.isJsonNull()) {
|
||||||
|
+ Ingredient ret = net.minecraftforge.common.crafting.CraftingHelper.getIngredient(p_199802_0_);
|
||||||
|
+ if (ret != null) return ret;
|
||||||
|
if (p_199802_0_.isJsonObject()) {
|
||||||
|
return func_209357_a(Stream.of(func_199803_a(p_199802_0_.getAsJsonObject())));
|
||||||
|
} else if (p_199802_0_.isJsonArray()) {
|
||||||
|
@@ -172,6 +207,11 @@
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Ingredient.IItemList func_199803_a(JsonObject p_199803_0_) {
|
||||||
|
+ if (p_199803_0_.has("constant")) {
|
||||||
|
+ Ingredient.IItemList ret = net.minecraftforge.common.crafting.CraftingHelper.getConstant(new ResourceLocation(JsonUtils.getString(p_199803_0_, "constant")));
|
||||||
|
+ if (ret == null) throw new JsonSyntaxException("Ingredient referenced invalid constant: " + JsonUtils.getString(p_199803_0_, "constant"));
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
if (p_199803_0_.has("item") && p_199803_0_.has("tag")) {
|
||||||
|
throw new JsonParseException("An ingredient entry is either a tag or an item, not both");
|
||||||
|
} else if (p_199803_0_.has("item")) {
|
||||||
|
@@ -195,6 +235,12 @@
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ //Merges several vanilla Ingredients together. As a qwerk of how the json is structured, we can't tell if its a single Ingredient type or multiple so we split per item and remerge here.
|
||||||
|
+ //Only public for internal use, so we can access a private field in here.
|
||||||
|
+ public static Ingredient merge(Collection<Ingredient> parts) {
|
||||||
|
+ return func_209357_a(parts.stream().flatMap(i -> Arrays.stream(i.field_199807_b)));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
public interface IItemList {
|
||||||
|
Collection<ItemStack> func_199799_a();
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
--- a/net/minecraft/item/crafting/RecipeManager.java
|
||||||
|
+++ b/net/minecraft/item/crafting/RecipeManager.java
|
||||||
|
@@ -37,6 +37,8 @@
|
||||||
|
this.field_199523_e = false;
|
||||||
|
this.field_199522_d.clear();
|
||||||
|
|
||||||
|
+ net.minecraftforge.common.crafting.CraftingHelper.reloadConstants(p_195410_1_);
|
||||||
|
+
|
||||||
|
for(ResourceLocation resourcelocation : p_195410_1_.func_199003_a("recipes", (p_199516_0_) -> {
|
||||||
|
return p_199516_0_.endsWith(".json");
|
||||||
|
})) {
|
||||||
|
@@ -47,6 +49,8 @@
|
||||||
|
JsonObject jsonobject = (JsonObject)JsonUtils.gsonDeserialize(gson, IOUtils.toString(iresource.func_199027_b(), StandardCharsets.UTF_8), JsonObject.class);
|
||||||
|
if (jsonobject == null) {
|
||||||
|
field_199521_c.error("Couldn't load recipe {} as it's null or empty", (Object)resourcelocation1);
|
||||||
|
+ } else if (jsonobject.has("conditions") && !net.minecraftforge.common.crafting.CraftingHelper.processConditions(JsonUtils.getJsonArray(jsonobject, "conditions"))) {
|
||||||
|
+ field_199521_c.info("Skipping loading recipe {} as it's conditions were not met", resourcelocation1);
|
||||||
|
} else {
|
||||||
|
this.func_199509_a(RecipeSerializers.func_199572_a(resourcelocation1, jsonobject));
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
--- a/net/minecraft/item/crafting/RecipeSerializers.java
|
||||||
|
+++ b/net/minecraft/item/crafting/RecipeSerializers.java
|
||||||
|
@@ -10,7 +10,7 @@
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
|
||||||
|
public class RecipeSerializers {
|
||||||
|
- private static final Map<String, IRecipeSerializer<?>> field_199590_p = Maps.<String, IRecipeSerializer<?>>newHashMap();
|
||||||
|
+ private static final Map<ResourceLocation, IRecipeSerializer<?>> field_199590_p = Maps.newHashMap();
|
||||||
|
public static final IRecipeSerializer<ShapedRecipe> field_199575_a = func_199573_a(new ShapedRecipe.Serializer());
|
||||||
|
public static final IRecipeSerializer<ShapelessRecipe> field_199576_b = func_199573_a(new ShapelessRecipe.Serializer());
|
||||||
|
public static final RecipeSerializers.SimpleSerializer<RecipesArmorDyes> field_199577_c = func_199573_a(new RecipeSerializers.SimpleSerializer<RecipesArmorDyes>("crafting_special_armordye", RecipesArmorDyes::new));
|
||||||
|
@@ -27,18 +27,19 @@
|
||||||
|
public static final RecipeSerializers.SimpleSerializer<ShieldRecipes> field_199588_n = func_199573_a(new RecipeSerializers.SimpleSerializer<ShieldRecipes>("crafting_special_shielddecoration", ShieldRecipes::new));
|
||||||
|
public static final RecipeSerializers.SimpleSerializer<ShulkerBoxColoringRecipe> field_199589_o = func_199573_a(new RecipeSerializers.SimpleSerializer<ShulkerBoxColoringRecipe>("crafting_special_shulkerboxcoloring", ShulkerBoxColoringRecipe::new));
|
||||||
|
public static final IRecipeSerializer<FurnaceRecipe> field_201839_p = func_199573_a(new FurnaceRecipe.Serializer());
|
||||||
|
+ private static final java.util.Set<ResourceLocation> VANILLA_TYPES = new java.util.HashSet<>(field_199590_p.keySet()); //Copy of vanilla so we can keep track for compatibility.
|
||||||
|
|
||||||
|
public static <S extends IRecipeSerializer<T>, T extends IRecipe> S func_199573_a(S p_199573_0_) {
|
||||||
|
- if (field_199590_p.containsKey(p_199573_0_.func_199567_a())) {
|
||||||
|
- throw new IllegalArgumentException("Duplicate recipe serializer " + p_199573_0_.func_199567_a());
|
||||||
|
+ if (field_199590_p.containsKey(p_199573_0_.getName())) {
|
||||||
|
+ throw new IllegalArgumentException("Duplicate recipe serializer " + p_199573_0_.getName());
|
||||||
|
} else {
|
||||||
|
- field_199590_p.put(p_199573_0_.func_199567_a(), p_199573_0_);
|
||||||
|
+ field_199590_p.put(p_199573_0_.getName(), p_199573_0_);
|
||||||
|
return p_199573_0_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IRecipe func_199572_a(ResourceLocation p_199572_0_, JsonObject p_199572_1_) {
|
||||||
|
- String s = JsonUtils.getString(p_199572_1_, "type");
|
||||||
|
+ ResourceLocation s = new ResourceLocation(JsonUtils.getString(p_199572_1_, "type"));
|
||||||
|
IRecipeSerializer<?> irecipeserializer = field_199590_p.get(s);
|
||||||
|
if (irecipeserializer == null) {
|
||||||
|
throw new JsonSyntaxException("Invalid or unsupported recipe type '" + s + "'");
|
||||||
|
@@ -49,7 +50,7 @@
|
||||||
|
|
||||||
|
public static IRecipe func_199571_a(PacketBuffer p_199571_0_) {
|
||||||
|
ResourceLocation resourcelocation = p_199571_0_.readResourceLocation();
|
||||||
|
- String s = p_199571_0_.readString(32767);
|
||||||
|
+ ResourceLocation s = new ResourceLocation(p_199571_0_.readString(32767));
|
||||||
|
IRecipeSerializer<?> irecipeserializer = field_199590_p.get(s);
|
||||||
|
if (irecipeserializer == null) {
|
||||||
|
throw new IllegalArgumentException("Unknown recipe serializer " + s);
|
||||||
|
@@ -68,10 +69,12 @@
|
||||||
|
public static final class SimpleSerializer<T extends IRecipe> implements IRecipeSerializer<T> {
|
||||||
|
private final String field_199569_a;
|
||||||
|
private final Function<ResourceLocation, T> field_199570_b;
|
||||||
|
+ private final ResourceLocation name;
|
||||||
|
|
||||||
|
public SimpleSerializer(String p_i48188_1_, Function<ResourceLocation, T> p_i48188_2_) {
|
||||||
|
this.field_199569_a = p_i48188_1_;
|
||||||
|
this.field_199570_b = p_i48188_2_;
|
||||||
|
+ this.name = new ResourceLocation(field_199569_a);
|
||||||
|
}
|
||||||
|
|
||||||
|
public T func_199425_a_(ResourceLocation p_199425_1_, JsonObject p_199425_2_) {
|
||||||
|
@@ -85,8 +88,9 @@
|
||||||
|
public void func_199427_a_(PacketBuffer p_199427_1_, T p_199427_2_) {
|
||||||
|
}
|
||||||
|
|
||||||
|
- public String func_199567_a() {
|
||||||
|
- return this.field_199569_a;
|
||||||
|
+ @Override
|
||||||
|
+ public ResourceLocation getName() {
|
||||||
|
+ return this.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,7 +14,7 @@
|
||||||
itemstack = itemstack1;
|
itemstack = itemstack1;
|
||||||
} else {
|
} else {
|
||||||
- if (!(itemstack1.getItem() instanceof ItemDye)) {
|
- if (!(itemstack1.getItem() instanceof ItemDye)) {
|
||||||
+ if (!itemstack1.getItem().func_206844_a(net.minecraft.tags.ItemTags.DYES)) {
|
+ if (!itemstack1.getItem().func_206844_a(net.minecraftforge.common.Tags.Items.DYES)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,8 @@
|
||||||
-import net.minecraftforge.api.distmarker.Dist;
|
-import net.minecraftforge.api.distmarker.Dist;
|
||||||
-import net.minecraftforge.api.distmarker.OnlyIn;
|
-import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
|
||||||
public class ShapedRecipe implements IRecipe {
|
-public class ShapedRecipe implements IRecipe {
|
||||||
|
+public class ShapedRecipe implements IRecipe, net.minecraftforge.common.crafting.IShapedRecipe {
|
||||||
+ static int MAX_WIDTH = 3;
|
+ static int MAX_WIDTH = 3;
|
||||||
+ static int MAX_HEIGHT = 3;
|
+ static int MAX_HEIGHT = 3;
|
||||||
+ /**
|
+ /**
|
||||||
|
@ -40,7 +41,28 @@
|
||||||
public boolean canFit(int width, int height) {
|
public boolean canFit(int width, int height) {
|
||||||
return width >= this.recipeWidth && height >= this.recipeHeight;
|
return width >= this.recipeWidth && height >= this.recipeHeight;
|
||||||
}
|
}
|
||||||
@@ -202,15 +211,15 @@
|
@@ -117,10 +126,20 @@
|
||||||
|
return this.recipeWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ @Override
|
||||||
|
+ public int getRecipeWidth() {
|
||||||
|
+ return getWidth();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
public int getHeight() {
|
||||||
|
return this.recipeHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ @Override
|
||||||
|
+ public int getRecipeHeight() {
|
||||||
|
+ return getHeight();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
private static NonNullList<Ingredient> deserializeIngredients(String[] pattern, Map<String, Ingredient> keys, int patternWidth, int patternHeight) {
|
||||||
|
NonNullList<Ingredient> nonnulllist = NonNullList.<Ingredient>withSize(patternWidth * patternHeight, Ingredient.EMPTY);
|
||||||
|
Set<String> set = Sets.newHashSet(keys.keySet());
|
||||||
|
@@ -202,15 +221,15 @@
|
||||||
|
|
||||||
private static String[] patternFromJson(JsonArray jsonArr) {
|
private static String[] patternFromJson(JsonArray jsonArr) {
|
||||||
String[] astring = new String[jsonArr.size()];
|
String[] astring = new String[jsonArr.size()];
|
||||||
|
@ -60,3 +82,23 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i > 0 && astring[0].length() != s.length()) {
|
if (i > 0 && astring[0].length() != s.length()) {
|
||||||
|
@@ -257,6 +276,7 @@
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Serializer implements IRecipeSerializer<ShapedRecipe> {
|
||||||
|
+ private static final ResourceLocation NAME = new ResourceLocation("minecraft", "crafting_shaped");
|
||||||
|
public ShapedRecipe func_199425_a_(ResourceLocation p_199425_1_, JsonObject p_199425_2_) {
|
||||||
|
String s = JsonUtils.getString(p_199425_2_, "group", "");
|
||||||
|
Map<String, Ingredient> map = ShapedRecipe.deserializeKey(JsonUtils.getJsonObject(p_199425_2_, "key"));
|
||||||
|
@@ -268,8 +288,9 @@
|
||||||
|
return new ShapedRecipe(p_199425_1_, s, i, j, nonnulllist, itemstack);
|
||||||
|
}
|
||||||
|
|
||||||
|
- public String func_199567_a() {
|
||||||
|
- return "crafting_shaped";
|
||||||
|
+ @Override
|
||||||
|
+ public ResourceLocation getName() {
|
||||||
|
+ return NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShapedRecipe func_199426_a_(ResourceLocation p_199426_1_, PacketBuffer p_199426_2_) {
|
||||||
|
|
|
@ -56,7 +56,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,7 +77,6 @@
|
@@ -74,19 +77,19 @@
|
||||||
return this.recipeOutput.copy();
|
return this.recipeOutput.copy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +64,11 @@
|
||||||
public boolean canFit(int width, int height) {
|
public boolean canFit(int width, int height) {
|
||||||
return width * height >= this.recipeItems.size();
|
return width * height >= this.recipeItems.size();
|
||||||
}
|
}
|
||||||
@@ -85,8 +87,8 @@
|
|
||||||
|
public static class Serializer implements IRecipeSerializer<ShapelessRecipe> {
|
||||||
|
+ private static final ResourceLocation NAME = new ResourceLocation("minecraft", "crafting_shapeless");
|
||||||
|
public ShapelessRecipe func_199425_a_(ResourceLocation p_199425_1_, JsonObject p_199425_2_) {
|
||||||
|
String s = JsonUtils.getString(p_199425_2_, "group", "");
|
||||||
NonNullList<Ingredient> nonnulllist = func_199568_a(JsonUtils.getJsonArray(p_199425_2_, "ingredients"));
|
NonNullList<Ingredient> nonnulllist = func_199568_a(JsonUtils.getJsonArray(p_199425_2_, "ingredients"));
|
||||||
if (nonnulllist.isEmpty()) {
|
if (nonnulllist.isEmpty()) {
|
||||||
throw new JsonParseException("No ingredients for shapeless recipe");
|
throw new JsonParseException("No ingredients for shapeless recipe");
|
||||||
|
@ -75,3 +79,15 @@
|
||||||
} else {
|
} else {
|
||||||
ItemStack itemstack = ShapedRecipe.func_199798_a(JsonUtils.getJsonObject(p_199425_2_, "result"));
|
ItemStack itemstack = ShapedRecipe.func_199798_a(JsonUtils.getJsonObject(p_199425_2_, "result"));
|
||||||
return new ShapelessRecipe(p_199425_1_, s, itemstack, nonnulllist);
|
return new ShapelessRecipe(p_199425_1_, s, itemstack, nonnulllist);
|
||||||
|
@@ -106,8 +109,9 @@
|
||||||
|
return nonnulllist;
|
||||||
|
}
|
||||||
|
|
||||||
|
- public String func_199567_a() {
|
||||||
|
- return "crafting_shapeless";
|
||||||
|
+ @Override
|
||||||
|
+ public ResourceLocation getName() {
|
||||||
|
+ return NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShapelessRecipe func_199426_a_(ResourceLocation p_199426_1_, PacketBuffer p_199426_2_) {
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
++i;
|
++i;
|
||||||
} else {
|
} else {
|
||||||
- if (!(itemstack.getItem() instanceof ItemDye)) {
|
- if (!(itemstack.getItem() instanceof ItemDye)) {
|
||||||
+ if (!itemstack.getItem().func_206844_a(net.minecraft.tags.ItemTags.DYES)) {
|
+ if (!itemstack.getItem().func_206844_a(net.minecraftforge.common.Tags.Items.DYES)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -939,8 +939,8 @@ public class ForgeChunkManager
|
||||||
{
|
{
|
||||||
ticket.setInteger("chunkX", MathHelper.floor(tick.entity.chunkCoordX));
|
ticket.setInteger("chunkX", MathHelper.floor(tick.entity.chunkCoordX));
|
||||||
ticket.setInteger("chunkZ", MathHelper.floor(tick.entity.chunkCoordZ));
|
ticket.setInteger("chunkZ", MathHelper.floor(tick.entity.chunkCoordZ));
|
||||||
ticket.setLong("PersistentIDMSB", tick.entity.getPersistentID().getMostSignificantBits());
|
ticket.setLong("PersistentIDMSB", tick.entity.getUniqueID().getMostSignificantBits());
|
||||||
ticket.setLong("PersistentIDLSB", tick.entity.getPersistentID().getLeastSignificantBits());
|
ticket.setLong("PersistentIDLSB", tick.entity.getUniqueID().getLeastSignificantBits());
|
||||||
tickets.add(ticket);
|
tickets.add(ticket);
|
||||||
}
|
}
|
||||||
else if (tick.ticketType != Type.ENTITY)
|
else if (tick.ticketType != Type.ENTITY)
|
||||||
|
@ -966,7 +966,7 @@ public class ForgeChunkManager
|
||||||
|
|
||||||
static void loadEntity(Entity entity)
|
static void loadEntity(Entity entity)
|
||||||
{
|
{
|
||||||
UUID id = entity.getPersistentID();
|
UUID id = entity.getUniqueID();
|
||||||
Ticket tick = pendingEntities.get(id);
|
Ticket tick = pendingEntities.get(id);
|
||||||
if (tick != null)
|
if (tick != null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1014,7 +1014,7 @@ public class ForgeHooks
|
||||||
if (stack.getItem().hasContainerItem(stack))
|
if (stack.getItem().hasContainerItem(stack))
|
||||||
{
|
{
|
||||||
stack = stack.getItem().getContainerItem(stack);
|
stack = stack.getItem().getContainerItem(stack);
|
||||||
if (!stack.isEmpty() && stack.isItemStackDamageable() && stack.getMetadata() > stack.getMaxDamage())
|
if (!stack.isEmpty() && stack.isItemStackDamageable() && stack.getItemDamage() > stack.getMaxDamage())
|
||||||
{
|
{
|
||||||
ForgeEventFactory.onPlayerDestroyItem(craftingPlayer.get(), stack, null);
|
ForgeEventFactory.onPlayerDestroyItem(craftingPlayer.get(), stack, null);
|
||||||
return ItemStack.EMPTY;
|
return ItemStack.EMPTY;
|
||||||
|
@ -1035,10 +1035,10 @@ public class ForgeHooks
|
||||||
{
|
{
|
||||||
filled = ((IFluidBlock)block).getFilledPercentage(entity.world, pos);
|
filled = ((IFluidBlock)block).getFilledPercentage(entity.world, pos);
|
||||||
}
|
}
|
||||||
else if (block instanceof BlockLiquid)
|
/*else if (block instanceof BlockLiquid)
|
||||||
{
|
{
|
||||||
filled = 1.0 - (BlockLiquid.getLiquidHeightPercent(block.getMetaFromState(state)) - (1.0 / 9.0));
|
filled = 1.0 - (BlockLiquid.getLiquidHeightPercent(block.getMetaFromState(state)) - (1.0 / 9.0));
|
||||||
}
|
}*/
|
||||||
|
|
||||||
if (filled < 0)
|
if (filled < 0)
|
||||||
{
|
{
|
||||||
|
@ -1271,13 +1271,6 @@ public class ForgeHooks
|
||||||
public static LootEntry deserializeJsonLootEntry(String type, JsonObject json, int weight, int quality, LootCondition[] conditions){ return null; }
|
public static LootEntry deserializeJsonLootEntry(String type, JsonObject json, int weight, int quality, LootCondition[] conditions){ return null; }
|
||||||
public static String getLootEntryType(LootEntry entry){ return null; } //Companion to above function
|
public static String getLootEntryType(LootEntry entry){ return null; } //Companion to above function
|
||||||
|
|
||||||
/** @deprecated use {@link ForgeEventFactory#onProjectileImpact(EntityThrowable, RayTraceResult)} */
|
|
||||||
@Deprecated // TODO: remove (1.13)
|
|
||||||
public static boolean onThrowableImpact(EntityThrowable throwable, RayTraceResult ray)
|
|
||||||
{
|
|
||||||
return ForgeEventFactory.onProjectileImpact(throwable, ray);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean onCropsGrowPre(World worldIn, BlockPos pos, IBlockState state, boolean def)
|
public static boolean onCropsGrowPre(World worldIn, BlockPos pos, IBlockState state, boolean def)
|
||||||
{
|
{
|
||||||
BlockEvent ev = new BlockEvent.CropGrowEvent.Pre(worldIn,pos,state);
|
BlockEvent ev = new BlockEvent.CropGrowEvent.Pre(worldIn,pos,state);
|
||||||
|
|
|
@ -106,7 +106,7 @@ public class Tags
|
||||||
public static final Tag<Item> GEMS_PRISMARINE = tag("gems/prismarine");
|
public static final Tag<Item> GEMS_PRISMARINE = tag("gems/prismarine");
|
||||||
public static final Tag<Item> GEMS_QUARRTZ = tag("gems/quartz");
|
public static final Tag<Item> GEMS_QUARRTZ = tag("gems/quartz");
|
||||||
public static final Tag<Item> INGOTS = tag("ingots");
|
public static final Tag<Item> INGOTS = tag("ingots");
|
||||||
public static final Tag<Item> INGOTS_BRICK = tag("ingots/brrick");
|
public static final Tag<Item> INGOTS_BRICK = tag("ingots/brick");
|
||||||
public static final Tag<Item> INGOTS_GOLD = tag("ingots/gold");
|
public static final Tag<Item> INGOTS_GOLD = tag("ingots/gold");
|
||||||
public static final Tag<Item> INGOTS_IRON = tag("ingots/iron");
|
public static final Tag<Item> INGOTS_IRON = tag("ingots/iron");
|
||||||
public static final Tag<Item> INGOTS_NETHER_BRICK = tag("ingots/nether_brick");
|
public static final Tag<Item> INGOTS_NETHER_BRICK = tag("ingots/nether_brick");
|
||||||
|
|
|
@ -22,17 +22,22 @@ package net.minecraftforge.common.crafting;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonSyntaxException;
|
||||||
|
|
||||||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||||
import it.unimi.dsi.fastutil.ints.IntComparators;
|
import it.unimi.dsi.fastutil.ints.IntComparators;
|
||||||
import it.unimi.dsi.fastutil.ints.IntList;
|
import it.unimi.dsi.fastutil.ints.IntList;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.item.crafting.Ingredient;
|
import net.minecraft.item.crafting.Ingredient;
|
||||||
|
import net.minecraft.network.PacketBuffer;
|
||||||
|
|
||||||
public class CompoundIngredient extends Ingredient
|
public class CompoundIngredient extends Ingredient
|
||||||
{
|
{
|
||||||
|
@ -41,15 +46,11 @@ public class CompoundIngredient extends Ingredient
|
||||||
private IntList itemIds;
|
private IntList itemIds;
|
||||||
private final boolean isSimple;
|
private final boolean isSimple;
|
||||||
|
|
||||||
protected CompoundIngredient(Collection<Ingredient> children)
|
protected CompoundIngredient(Stream<Ingredient> children)
|
||||||
{
|
{
|
||||||
super(0);
|
super(Stream.of());
|
||||||
this.children = children;
|
this.isSimple = children.allMatch(Ingredient::isSimple);
|
||||||
|
this.children = children.collect(Collectors.toList());
|
||||||
boolean simple = true;
|
|
||||||
for (Ingredient child : children)
|
|
||||||
simple &= child.isSimple();
|
|
||||||
this.isSimple = simple;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -84,16 +85,12 @@ public class CompoundIngredient extends Ingredient
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(@Nullable ItemStack target)
|
public boolean test(@Nullable ItemStack target)
|
||||||
{
|
{
|
||||||
if (target == null)
|
if (target == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (Ingredient child : children)
|
return children.stream().anyMatch(c -> c.test(target));
|
||||||
if (child.apply(target))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -115,4 +112,27 @@ public class CompoundIngredient extends Ingredient
|
||||||
{
|
{
|
||||||
return Collections.unmodifiableCollection(this.children);
|
return Collections.unmodifiableCollection(this.children);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class Serializer implements IIngredientSerializer<CompoundIngredient>
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public CompoundIngredient parse(PacketBuffer buffer)
|
||||||
|
{
|
||||||
|
return new CompoundIngredient(Stream.generate(() -> Ingredient.func_199566_b(buffer)).limit(buffer.readVarInt()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompoundIngredient parse(JsonObject json)
|
||||||
|
{
|
||||||
|
throw new JsonSyntaxException("CompountIngredient should not be directly referenced in json, just use an array of ingredients.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(PacketBuffer buffer, CompoundIngredient ingredient)
|
||||||
|
{
|
||||||
|
buffer.writeVarInt(ingredient.children.size());
|
||||||
|
ingredient.children.forEach(c -> c.func_199564_a(buffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,31 +19,21 @@
|
||||||
|
|
||||||
package net.minecraftforge.common.crafting;
|
package net.minecraftforge.common.crafting;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Path;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
import java.util.function.BooleanSupplier;
|
import java.util.function.BooleanSupplier;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import net.minecraft.client.util.RecipeBookClient;
|
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
|
||||||
import net.minecraftforge.fml.ModList;
|
import net.minecraftforge.fml.ModList;
|
||||||
import net.minecraftforge.fml.DistExecutor;
|
import com.google.common.collect.BiMap;
|
||||||
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
|
import com.google.common.collect.HashBiMap;
|
||||||
import org.apache.commons.io.FilenameUtils;
|
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import com.google.common.collect.Sets;
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
import com.google.gson.JsonArray;
|
import com.google.gson.JsonArray;
|
||||||
|
@ -51,92 +41,140 @@ import com.google.gson.JsonElement;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import com.google.gson.JsonParseException;
|
import com.google.gson.JsonParseException;
|
||||||
import com.google.gson.JsonSyntaxException;
|
import com.google.gson.JsonSyntaxException;
|
||||||
|
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||||
|
|
||||||
import net.minecraft.block.Block;
|
|
||||||
import net.minecraft.item.Item;
|
import net.minecraft.item.Item;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.item.crafting.IRecipe;
|
|
||||||
import net.minecraft.item.crafting.Ingredient;
|
import net.minecraft.item.crafting.Ingredient;
|
||||||
import net.minecraft.item.crafting.ShapedRecipes;
|
import net.minecraft.item.crafting.Ingredient.IItemList;
|
||||||
import net.minecraft.item.crafting.ShapelessRecipes;
|
|
||||||
import net.minecraft.nbt.JsonToNBT;
|
import net.minecraft.nbt.JsonToNBT;
|
||||||
import net.minecraft.nbt.NBTException;
|
|
||||||
import net.minecraft.nbt.NBTTagCompound;
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
|
import net.minecraft.network.PacketBuffer;
|
||||||
|
import net.minecraft.resources.IResource;
|
||||||
|
import net.minecraft.resources.IResourceManager;
|
||||||
import net.minecraft.util.JsonUtils;
|
import net.minecraft.util.JsonUtils;
|
||||||
import net.minecraft.util.NonNullList;
|
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
import net.minecraftforge.oredict.OreDictionary;
|
|
||||||
import net.minecraftforge.oredict.OreIngredient;
|
|
||||||
import net.minecraftforge.oredict.ShapedOreRecipe;
|
|
||||||
import net.minecraftforge.oredict.ShapelessOreRecipe;
|
|
||||||
import net.minecraftforge.registries.ForgeRegistries;
|
import net.minecraftforge.registries.ForgeRegistries;
|
||||||
import net.minecraftforge.registries.ForgeRegistry;
|
|
||||||
import net.minecraftforge.registries.GameData;
|
import org.apache.commons.io.IOUtils;
|
||||||
import net.minecraftforge.registries.RegistryManager;
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.apache.logging.log4j.Marker;
|
import org.apache.logging.log4j.Marker;
|
||||||
import org.apache.logging.log4j.MarkerManager;
|
import org.apache.logging.log4j.MarkerManager;
|
||||||
|
|
||||||
public class CraftingHelper {
|
public class CraftingHelper
|
||||||
|
{
|
||||||
private static final boolean DEBUG_LOAD_MINECRAFT = false;
|
|
||||||
private static final Logger LOGGER = LogManager.getLogger();
|
private static final Logger LOGGER = LogManager.getLogger();
|
||||||
private static final Marker CRAFTHELPER = MarkerManager.getMarker("CRAFTHELPER");
|
private static final Marker CRAFTHELPER = MarkerManager.getMarker("CRAFTHELPER");
|
||||||
private static Gson GSON = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create();
|
private static Gson GSON = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create();
|
||||||
private static Map<ResourceLocation, IConditionFactory> conditions = new HashMap<>();
|
private static final Map<ResourceLocation, IConditionSerializer> conditions = new HashMap<>();
|
||||||
private static Map<ResourceLocation, IIngredientFactory> ingredients = new HashMap<>();
|
private static final BiMap<ResourceLocation, IIngredientSerializer<?>> ingredients = HashBiMap.create();
|
||||||
private static Map<ResourceLocation, IRecipeFactory> recipes = new HashMap<>();
|
private static Map<ResourceLocation, IItemList> constants = new HashMap<>();
|
||||||
|
|
||||||
static {
|
public static final IConditionSerializer CONDITION_MOD_LOADED = condition("mod_loaded", json -> {
|
||||||
init();
|
String modid = JsonUtils.getString(json, "modid");
|
||||||
|
return () -> ModList.get().isLoaded(modid);
|
||||||
|
});
|
||||||
|
public static final IConditionSerializer CONDITION_ITEM_EXISTS = condition("item_exists", json -> {
|
||||||
|
String itemName = JsonUtils.getString(json, "item");
|
||||||
|
return () -> ForgeRegistries.ITEMS.containsKey(new ResourceLocation(itemName));
|
||||||
|
});
|
||||||
|
public static final IConditionSerializer CONDITION_NOT = condition("not", json -> {
|
||||||
|
BooleanSupplier child = CraftingHelper.getCondition(JsonUtils.getJsonObject(json, "value"));
|
||||||
|
return () -> !child.getAsBoolean();
|
||||||
|
});
|
||||||
|
public static final IConditionSerializer CONDITION_OR = condition("or", json -> {
|
||||||
|
JsonArray values = JsonUtils.getJsonArray(json, "values");
|
||||||
|
List<BooleanSupplier> children = Lists.newArrayList();
|
||||||
|
for (JsonElement j : values)
|
||||||
|
{
|
||||||
|
if (!j.isJsonObject())
|
||||||
|
throw new JsonSyntaxException("Or condition values must be an array of JsonObjects");
|
||||||
|
children.add(CraftingHelper.getCondition(j.getAsJsonObject()));
|
||||||
|
}
|
||||||
|
return () -> children.stream().anyMatch(BooleanSupplier::getAsBoolean);
|
||||||
|
});
|
||||||
|
public static final IConditionSerializer CONDITION_AND = condition("and", json -> {
|
||||||
|
JsonArray values = JsonUtils.getJsonArray(json, "values");
|
||||||
|
List<BooleanSupplier> children = Lists.newArrayList();
|
||||||
|
for (JsonElement j : values)
|
||||||
|
{
|
||||||
|
if (!j.isJsonObject())
|
||||||
|
throw new JsonSyntaxException("And condition values must be an array of JsonObjects");
|
||||||
|
children.add(CraftingHelper.getCondition(j.getAsJsonObject()));
|
||||||
|
}
|
||||||
|
return () -> children.stream().allMatch(c -> c.getAsBoolean());
|
||||||
|
});
|
||||||
|
public static final IConditionSerializer CONDITION_FALSE = condition("false", json -> () -> false);
|
||||||
|
|
||||||
|
public static final IIngredientSerializer<IngredientNBT> INGREDIENT_NBT = register(new ResourceLocation("forge", "nbt"), new IngredientNBT.Serializer());
|
||||||
|
public static final IIngredientSerializer<CompoundIngredient> INGREDIENT_COMPOUND = register(new ResourceLocation("forge", "nbt"), new CompoundIngredient.Serializer());
|
||||||
|
public static final IIngredientSerializer<Ingredient> INGREDIENT_VANILLA = register(new ResourceLocation("minecraft", "item"), new IIngredientSerializer<Ingredient>() {
|
||||||
|
public Ingredient parse(PacketBuffer buffer) {
|
||||||
|
return Ingredient.func_209357_a(Stream.generate(() -> new Ingredient.SingleItemList(buffer.readItemStack())).limit(buffer.readVarInt()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void register(ResourceLocation key, IConditionFactory factory)
|
public Ingredient parse(JsonObject json) {
|
||||||
|
return Ingredient.func_209357_a(Stream.of(Ingredient.func_199803_a(json)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(PacketBuffer buffer, Ingredient ingredient) {
|
||||||
|
ItemStack[] items = ingredient.getMatchingStacks();
|
||||||
|
buffer.writeVarInt(items.length);
|
||||||
|
|
||||||
|
for (ItemStack stack : items)
|
||||||
|
buffer.writeItemStack(stack);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
public static IConditionSerializer register(ResourceLocation key, IConditionSerializer serializer)
|
||||||
{
|
{
|
||||||
if (conditions.containsKey(key))
|
if (conditions.containsKey(key))
|
||||||
throw new IllegalStateException("Duplicate recipe condition factory: " + key);
|
throw new IllegalStateException("Duplicate recipe condition serializer: " + key);
|
||||||
conditions.put(key, factory);
|
conditions.put(key, serializer);
|
||||||
|
return serializer;
|
||||||
}
|
}
|
||||||
public static void register(ResourceLocation key, IRecipeFactory factory)
|
public static <T extends Ingredient> IIngredientSerializer<T> register(ResourceLocation key, IIngredientSerializer<T> serializer)
|
||||||
{
|
|
||||||
if (recipes.containsKey(key))
|
|
||||||
throw new IllegalStateException("Duplicate recipe factory: " + key);
|
|
||||||
recipes.put(key, factory);
|
|
||||||
}
|
|
||||||
public static void register(ResourceLocation key, IIngredientFactory factory)
|
|
||||||
{
|
{
|
||||||
if (ingredients.containsKey(key))
|
if (ingredients.containsKey(key))
|
||||||
throw new IllegalStateException("Duplicate recipe ingredient factory: " + key);
|
throw new IllegalStateException("Duplicate recipe ingredient serializer: " + key);
|
||||||
ingredients.put(key, factory);
|
if (ingredients.containsValue(serializer))
|
||||||
|
throw new IllegalStateException("Duplicate recipe ingredient serializer: " + key + " " + serializer);
|
||||||
|
ingredients.put(key, serializer);
|
||||||
|
return serializer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static IConditionSerializer condition(String name, IConditionSerializer serializer) {
|
||||||
|
return register(new ResourceLocation("forge", name), serializer);
|
||||||
|
}
|
||||||
|
|
||||||
public static Ingredient getIngredient(Object obj)
|
public static <T extends Ingredient> void write(PacketBuffer buffer, T ingredient)
|
||||||
{
|
{
|
||||||
if (obj instanceof Ingredient)
|
@SuppressWarnings("unchecked") //I wonder if there is a better way generic wise...
|
||||||
return (Ingredient)obj;
|
IIngredientSerializer<T> serializer = (IIngredientSerializer<T>)ingredient.getSerializer();
|
||||||
else if (obj instanceof ItemStack)
|
ResourceLocation key = ingredients.inverse().get(serializer);
|
||||||
return Ingredient.fromStacks(((ItemStack)obj).copy());
|
if (key == null)
|
||||||
else if (obj instanceof Item)
|
throw new IllegalArgumentException("Tried to serialize unregistered Ingredient: " + ingredient + " " + serializer);
|
||||||
return Ingredient.fromItem((Item)obj);
|
if (serializer != INGREDIENT_VANILLA)
|
||||||
else if (obj instanceof Block)
|
{
|
||||||
return Ingredient.fromStacks(new ItemStack((Block)obj, 1, OreDictionary.WILDCARD_VALUE));
|
buffer.writeVarInt(-1); //Marker to know there is a custom ingredient
|
||||||
else if (obj instanceof String)
|
buffer.writeResourceLocation(key);
|
||||||
return new OreIngredient((String)obj);
|
}
|
||||||
else if (obj instanceof JsonElement)
|
serializer.write(buffer, ingredient);
|
||||||
throw new IllegalArgumentException("JsonObjects must use getIngredient(JsonObject, JsonContext)");
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
public static Ingredient getIngredient(ResourceLocation type, PacketBuffer buffer)
|
||||||
public static Ingredient getIngredient(JsonElement json, JsonContext context)
|
{
|
||||||
|
IIngredientSerializer<?> serializer = ingredients.get(type);
|
||||||
|
if (serializer == null)
|
||||||
|
throw new IllegalArgumentException("Can not deserialize unknown Ingredient type: " + type);
|
||||||
|
return serializer.parse(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Ingredient getIngredient(JsonElement json)
|
||||||
{
|
{
|
||||||
if (json == null || json.isJsonNull())
|
if (json == null || json.isJsonNull())
|
||||||
throw new JsonSyntaxException("Json cannot be null");
|
throw new JsonSyntaxException("Json cannot be null");
|
||||||
if (context == null)
|
|
||||||
throw new IllegalArgumentException("getIngredient Context cannot be null");
|
|
||||||
|
|
||||||
if (json.isJsonArray())
|
if (json.isJsonArray())
|
||||||
{
|
{
|
||||||
|
@ -144,23 +182,16 @@ public class CraftingHelper {
|
||||||
List<Ingredient> vanilla = Lists.newArrayList();
|
List<Ingredient> vanilla = Lists.newArrayList();
|
||||||
json.getAsJsonArray().forEach((ele) ->
|
json.getAsJsonArray().forEach((ele) ->
|
||||||
{
|
{
|
||||||
Ingredient ing = CraftingHelper.getIngredient(ele, context);
|
Ingredient ing = CraftingHelper.getIngredient(ele);
|
||||||
|
|
||||||
if (ing.getClass() == Ingredient.class)
|
if (ing.getClass() == Ingredient.class) //Vanilla, Due to how we read it splits each itemstack, so we pull out to re-merge later
|
||||||
{
|
|
||||||
//Vanilla, Due to how we read it splits each itemstack, so we pull out to re-merge later
|
|
||||||
vanilla.add(ing);
|
vanilla.add(ing);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
ingredients.add(ing);
|
ingredients.add(ing);
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!vanilla.isEmpty())
|
if (!vanilla.isEmpty())
|
||||||
{
|
|
||||||
ingredients.add(Ingredient.merge(vanilla));
|
ingredients.add(Ingredient.merge(vanilla));
|
||||||
}
|
|
||||||
|
|
||||||
if (ingredients.size() == 0)
|
if (ingredients.size() == 0)
|
||||||
throw new JsonSyntaxException("Item array cannot be empty, at least one item must be defined");
|
throw new JsonSyntaxException("Item array cannot be empty, at least one item must be defined");
|
||||||
|
@ -168,7 +199,7 @@ public class CraftingHelper {
|
||||||
if (ingredients.size() == 1)
|
if (ingredients.size() == 1)
|
||||||
return ingredients.get(0);
|
return ingredients.get(0);
|
||||||
|
|
||||||
return new CompoundIngredient(ingredients);
|
return new CompoundIngredient(ingredients.stream());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!json.isJsonObject())
|
if (!json.isJsonObject())
|
||||||
|
@ -176,42 +207,27 @@ public class CraftingHelper {
|
||||||
|
|
||||||
JsonObject obj = (JsonObject)json;
|
JsonObject obj = (JsonObject)json;
|
||||||
|
|
||||||
String type = context.appendModId(JsonUtils.getString(obj, "type", "minecraft:item"));
|
String type = JsonUtils.getString(obj, "type", "minecraft:item");
|
||||||
if (type.isEmpty())
|
if (type.isEmpty())
|
||||||
throw new JsonSyntaxException("Ingredient type can not be an empty string");
|
throw new JsonSyntaxException("Ingredient type can not be an empty string");
|
||||||
|
|
||||||
if (type.equals("minecraft:item"))
|
IIngredientSerializer<?> serializer = ingredients.get(new ResourceLocation(type));
|
||||||
{
|
if (serializer == null)
|
||||||
String item = JsonUtils.getString(obj, "item");
|
|
||||||
if (item.startsWith("#"))
|
|
||||||
{
|
|
||||||
Ingredient constant = context.getConstant(item.substring(1));
|
|
||||||
if (constant == null)
|
|
||||||
throw new JsonSyntaxException("Ingredient referenced invalid constant: " + item);
|
|
||||||
return constant;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IIngredientFactory factory = ingredients.get(new ResourceLocation(type));
|
|
||||||
if (factory == null)
|
|
||||||
throw new JsonSyntaxException("Unknown ingredient type: " + type);
|
throw new JsonSyntaxException("Unknown ingredient type: " + type);
|
||||||
|
|
||||||
return factory.parse(context, obj);
|
return serializer.parse(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ItemStack getItemStack(JsonObject json, JsonContext context)
|
public static ItemStack getItemStack(JsonObject json, boolean readNBT)
|
||||||
{
|
{
|
||||||
String itemName = context.appendModId(JsonUtils.getString(json, "item"));
|
String itemName = JsonUtils.getString(json, "item");
|
||||||
|
|
||||||
Item item = ForgeRegistries.ITEMS.getValue(new ResourceLocation(itemName));
|
Item item = ForgeRegistries.ITEMS.getValue(new ResourceLocation(itemName));
|
||||||
|
|
||||||
if (item == null)
|
if (item == null)
|
||||||
throw new JsonSyntaxException("Unknown item '" + itemName + "'");
|
throw new JsonSyntaxException("Unknown item '" + itemName + "'");
|
||||||
|
|
||||||
if (item.getHasSubtypes() && !json.has("data"))
|
if (readNBT && json.has("nbt"))
|
||||||
throw new JsonParseException("Missing data for item '" + itemName + "'");
|
|
||||||
|
|
||||||
if (json.has("nbt"))
|
|
||||||
{
|
{
|
||||||
// Lets hope this works? Needs test
|
// Lets hope this works? Needs test
|
||||||
try
|
try
|
||||||
|
@ -233,138 +249,19 @@ public class CraftingHelper {
|
||||||
tmp.setTag("tag", nbt);
|
tmp.setTag("tag", nbt);
|
||||||
tmp.setString("id", itemName);
|
tmp.setString("id", itemName);
|
||||||
tmp.setInteger("Count", JsonUtils.getInt(json, "count", 1));
|
tmp.setInteger("Count", JsonUtils.getInt(json, "count", 1));
|
||||||
tmp.setInteger("Damage", JsonUtils.getInt(json, "data", 0));
|
|
||||||
|
|
||||||
return new ItemStack(tmp);
|
return ItemStack.func_199557_a(tmp);
|
||||||
}
|
}
|
||||||
catch (NBTException e)
|
catch (CommandSyntaxException e)
|
||||||
{
|
{
|
||||||
throw new JsonSyntaxException("Invalid NBT Entry: " + e.toString());
|
throw new JsonSyntaxException("Invalid NBT Entry: " + e.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ItemStack(item, JsonUtils.getInt(json, "count", 1), JsonUtils.getInt(json, "data", 0));
|
return new ItemStack(item, JsonUtils.getInt(json, "count", 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean processConditions(JsonArray conditions)
|
||||||
public static ItemStack getItemStackBasic(JsonObject json, JsonContext context)
|
|
||||||
{
|
|
||||||
String itemName = context.appendModId(JsonUtils.getString(json, "item"));
|
|
||||||
|
|
||||||
Item item = ForgeRegistries.ITEMS.getValue(new ResourceLocation(itemName));
|
|
||||||
|
|
||||||
if (item == null)
|
|
||||||
throw new JsonSyntaxException("Unknown item '" + itemName + "'");
|
|
||||||
|
|
||||||
if (item.getHasSubtypes() && !json.has("data"))
|
|
||||||
throw new JsonParseException("Missing data for item '" + itemName + "'");
|
|
||||||
|
|
||||||
return new ItemStack(item, 1, JsonUtils.getInt(json, "data", 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ShapedPrimer {
|
|
||||||
public int height, width;
|
|
||||||
public boolean mirrored = true;
|
|
||||||
public NonNullList<Ingredient> input;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ShapedPrimer parseShaped(Object... recipe)
|
|
||||||
{
|
|
||||||
ShapedPrimer ret = new ShapedPrimer();
|
|
||||||
String shape = "";
|
|
||||||
int idx = 0;
|
|
||||||
|
|
||||||
if (recipe[idx] instanceof Boolean)
|
|
||||||
{
|
|
||||||
ret.mirrored = (Boolean)recipe[idx];
|
|
||||||
if (recipe[idx+1] instanceof Object[])
|
|
||||||
recipe = (Object[])recipe[idx+1];
|
|
||||||
else
|
|
||||||
idx = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (recipe[idx] instanceof String[])
|
|
||||||
{
|
|
||||||
String[] parts = ((String[])recipe[idx++]);
|
|
||||||
|
|
||||||
for (String s : parts)
|
|
||||||
{
|
|
||||||
ret.width = s.length();
|
|
||||||
shape += s;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret.height = parts.length;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
while (recipe[idx] instanceof String)
|
|
||||||
{
|
|
||||||
String s = (String)recipe[idx++];
|
|
||||||
shape += s;
|
|
||||||
ret.width = s.length();
|
|
||||||
ret.height++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret.width * ret.height != shape.length() || shape.length() == 0)
|
|
||||||
{
|
|
||||||
String err = "Invalid shaped recipe: ";
|
|
||||||
for (Object tmp : recipe)
|
|
||||||
{
|
|
||||||
err += tmp + ", ";
|
|
||||||
}
|
|
||||||
throw new RuntimeException(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
HashMap<Character, Ingredient> itemMap = Maps.newHashMap();
|
|
||||||
itemMap.put(' ', Ingredient.EMPTY);
|
|
||||||
|
|
||||||
for (; idx < recipe.length; idx += 2)
|
|
||||||
{
|
|
||||||
Character chr = (Character)recipe[idx];
|
|
||||||
Object in = recipe[idx + 1];
|
|
||||||
Ingredient ing = CraftingHelper.getIngredient(in);
|
|
||||||
|
|
||||||
if (' ' == chr.charValue())
|
|
||||||
throw new JsonSyntaxException("Invalid key entry: ' ' is a reserved symbol.");
|
|
||||||
|
|
||||||
if (ing != null)
|
|
||||||
{
|
|
||||||
itemMap.put(chr, ing);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
String err = "Invalid shaped ore recipe: ";
|
|
||||||
for (Object tmp : recipe)
|
|
||||||
{
|
|
||||||
err += tmp + ", ";
|
|
||||||
}
|
|
||||||
throw new RuntimeException(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ret.input = NonNullList.withSize(ret.width * ret.height, Ingredient.EMPTY);
|
|
||||||
|
|
||||||
Set<Character> keys = Sets.newHashSet(itemMap.keySet());
|
|
||||||
keys.remove(' ');
|
|
||||||
|
|
||||||
int x = 0;
|
|
||||||
for (char chr : shape.toCharArray())
|
|
||||||
{
|
|
||||||
Ingredient ing = itemMap.get(chr);
|
|
||||||
if (ing == null)
|
|
||||||
throw new IllegalArgumentException("Pattern references symbol '" + chr + "' but it's not defined in the key");
|
|
||||||
ret.input.set(x++, ing);
|
|
||||||
keys.remove(chr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!keys.isEmpty())
|
|
||||||
throw new IllegalArgumentException("Key defines symbols that aren't used in pattern: " + keys);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean processConditions(JsonArray conditions, JsonContext context)
|
|
||||||
{
|
{
|
||||||
for (int x = 0; x < conditions.size(); x++)
|
for (int x = 0; x < conditions.size(); x++)
|
||||||
{
|
{
|
||||||
|
@ -372,334 +269,82 @@ public class CraftingHelper {
|
||||||
throw new JsonSyntaxException("Conditions must be an array of JsonObjects");
|
throw new JsonSyntaxException("Conditions must be an array of JsonObjects");
|
||||||
|
|
||||||
JsonObject json = conditions.get(x).getAsJsonObject();
|
JsonObject json = conditions.get(x).getAsJsonObject();
|
||||||
BooleanSupplier cond = CraftingHelper.getCondition(json, context);
|
BooleanSupplier cond = CraftingHelper.getCondition(json);
|
||||||
if (!cond.getAsBoolean())
|
if (!cond.getAsBoolean())
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BooleanSupplier getCondition(JsonObject json, JsonContext context)
|
public static BooleanSupplier getCondition(JsonObject json)
|
||||||
{
|
{
|
||||||
ResourceLocation type = new ResourceLocation(context.appendModId(JsonUtils.getString(json, "type")));
|
ResourceLocation type = new ResourceLocation(JsonUtils.getString(json, "type"));
|
||||||
IConditionFactory factory = conditions.get(type);
|
IConditionSerializer serrializer = conditions.get(type);
|
||||||
if (factory == null)
|
if (serrializer == null)
|
||||||
throw new JsonSyntaxException("Unknown condition type: " + type.toString());
|
throw new JsonSyntaxException("Unknown condition type: " + type.toString());
|
||||||
return factory.parse(context, json);
|
return serrializer.parse(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IRecipe getRecipe(JsonObject json, JsonContext context)
|
@Nullable
|
||||||
|
public static IItemList getConstant(ResourceLocation key) {
|
||||||
|
return constants.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void reloadConstants(IResourceManager manager) {
|
||||||
|
Map<ResourceLocation, IItemList> ret = new HashMap<>();
|
||||||
|
for(ResourceLocation key : manager.func_199003_a("recipes", filename -> filename.equals("_constants.json")))
|
||||||
{
|
{
|
||||||
if (json == null || json.isJsonNull())
|
String path = key.getPath();
|
||||||
throw new JsonSyntaxException("Json cannot be null");
|
if (!path.equals("rrecipes/_constants.json")) //Top level only
|
||||||
if (context == null)
|
continue;
|
||||||
throw new IllegalArgumentException("getRecipe Context cannot be null");
|
|
||||||
|
|
||||||
String type = context.appendModId(JsonUtils.getString(json, "type"));
|
try (IResource iresource = manager.func_199002_a(key))
|
||||||
if (type.isEmpty())
|
|
||||||
throw new JsonSyntaxException("Recipe type can not be an empty string");
|
|
||||||
|
|
||||||
IRecipeFactory factory = recipes.get(new ResourceLocation(type));
|
|
||||||
if (factory == null)
|
|
||||||
throw new JsonSyntaxException("Unknown recipe type: " + type);
|
|
||||||
|
|
||||||
return factory.parse(context, json);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//=======================================================
|
|
||||||
// INTERNAL
|
|
||||||
//=======================================================
|
|
||||||
|
|
||||||
private static void init()
|
|
||||||
{
|
{
|
||||||
conditions.clear();
|
JsonObject[] elements = JsonUtils.gsonDeserialize(GSON, IOUtils.toString(iresource.func_199027_b(), StandardCharsets.UTF_8), JsonObject[].class);
|
||||||
ingredients.clear();
|
for (int x = 0; x < elements.length; x++)
|
||||||
recipes.clear();
|
|
||||||
|
|
||||||
registerC("forge:mod_loaded", (context, json) -> {
|
|
||||||
String modid = JsonUtils.getString(json, "modid");
|
|
||||||
return () -> ModList.get().isLoaded(modid);
|
|
||||||
});
|
|
||||||
registerC("minecraft:item_exists", (context, json) -> {
|
|
||||||
String itemName = context.appendModId(JsonUtils.getString(json, "item"));
|
|
||||||
return () -> ForgeRegistries.ITEMS.containsKey(new ResourceLocation(itemName));
|
|
||||||
});
|
|
||||||
registerC("forge:not", (context, json) -> {
|
|
||||||
BooleanSupplier child = CraftingHelper.getCondition(JsonUtils.getJsonObject(json, "value"), context);
|
|
||||||
return () -> !child.getAsBoolean();
|
|
||||||
});
|
|
||||||
registerC("forge:or", (context, json) -> {
|
|
||||||
JsonArray values = JsonUtils.getJsonArray(json, "values");
|
|
||||||
List<BooleanSupplier> children = Lists.newArrayList();
|
|
||||||
for (JsonElement j : values)
|
|
||||||
{
|
{
|
||||||
if (!j.isJsonObject())
|
JsonObject json = elements[x];
|
||||||
throw new JsonSyntaxException("Or condition values must be an array of JsonObjects");
|
if (json == null || json.size() == 0)
|
||||||
children.add(CraftingHelper.getCondition(j.getAsJsonObject(), context));
|
LOGGER.error(CRAFTHELPER, "Couldn't load constant #{} from {} as it's null or empty", x, key);
|
||||||
|
else if (json.has("conditions") && !processConditions(JsonUtils.getJsonArray(json, "conditions")))
|
||||||
|
LOGGER.info(CRAFTHELPER, "Skipping loading constant #{} from {} as it's conditions were not met", x, key);
|
||||||
|
else if (!json.has("name"))
|
||||||
|
LOGGER.error(CRAFTHELPER, "Couldn't load constant #{} from {} as it's missing `name`", x, key);
|
||||||
|
else if (json.has("items"))
|
||||||
|
{
|
||||||
|
List<ItemStack> items = new ArrayList<>();
|
||||||
|
for (JsonElement item : JsonUtils.getJsonArray(json, "items"))
|
||||||
|
{
|
||||||
|
if (item.isJsonObject())
|
||||||
|
items.add(getItemStack(item.getAsJsonObject(), true));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOGGER.error(CRAFTHELPER, "Couldn't load constant #{} from {} as it's `items` entry is not a object", x, key);
|
||||||
|
items.clear();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return () -> children.stream().anyMatch(BooleanSupplier::getAsBoolean);
|
|
||||||
});
|
|
||||||
registerC("forge:and", (context, json) -> {
|
|
||||||
JsonArray values = JsonUtils.getJsonArray(json, "values");
|
|
||||||
List<BooleanSupplier> children = Lists.newArrayList();
|
|
||||||
for (JsonElement j : values)
|
|
||||||
{
|
|
||||||
if (!j.isJsonObject())
|
|
||||||
throw new JsonSyntaxException("And condition values must be an array of JsonObjects");
|
|
||||||
children.add(CraftingHelper.getCondition(j.getAsJsonObject(), context));
|
|
||||||
}
|
}
|
||||||
return () -> children.stream().allMatch(c -> c.getAsBoolean());
|
if (!items.isEmpty())
|
||||||
});
|
constants.put(new ResourceLocation(JsonUtils.getString(json, "name")), new StackList(items));
|
||||||
registerC("forge:false", (context, json) -> {
|
|
||||||
return () -> false;
|
|
||||||
});
|
|
||||||
|
|
||||||
registerR("minecraft:crafting_shaped", (context, json) -> {
|
|
||||||
String group = JsonUtils.getString(json, "group", "");
|
|
||||||
//if (!group.isEmpty() && group.indexOf(':') == -1)
|
|
||||||
// group = context.getModId() + ":" + group;
|
|
||||||
|
|
||||||
Map<Character, Ingredient> ingMap = Maps.newHashMap();
|
|
||||||
for (Entry<String, JsonElement> entry : JsonUtils.getJsonObject(json, "key").entrySet())
|
|
||||||
{
|
|
||||||
if (entry.getKey().length() != 1)
|
|
||||||
throw new JsonSyntaxException("Invalid key entry: '" + entry.getKey() + "' is an invalid symbol (must be 1 character only).");
|
|
||||||
if (" ".equals(entry.getKey()))
|
|
||||||
throw new JsonSyntaxException("Invalid key entry: ' ' is a reserved symbol.");
|
|
||||||
|
|
||||||
ingMap.put(entry.getKey().toCharArray()[0], CraftingHelper.getIngredient(entry.getValue(), context));
|
|
||||||
}
|
}
|
||||||
ingMap.put(' ', Ingredient.EMPTY);
|
else if (json.has("tag"))
|
||||||
|
constants.put(new ResourceLocation(JsonUtils.getString(json, "name")), Ingredient.func_199803_a(json));
|
||||||
JsonArray patternJ = JsonUtils.getJsonArray(json, "pattern");
|
else if (json.has("item"))
|
||||||
|
constants.put(new ResourceLocation(JsonUtils.getString(json, "name")), new StackList(Lists.newArrayList(getItemStack(JsonUtils.getJsonObject(json, "item"), true))));
|
||||||
if (patternJ.size() == 0)
|
else
|
||||||
throw new JsonSyntaxException("Invalid pattern: empty pattern not allowed");
|
LOGGER.error(CRAFTHELPER, "Couldn't load constant #{} from {} as it's missing `item` or `items` element", x, key);
|
||||||
if (patternJ.size() > 3)
|
|
||||||
throw new JsonSyntaxException("Invalid pattern: too many rows, 3 is maximum");
|
|
||||||
|
|
||||||
String[] pattern = new String[patternJ.size()];
|
|
||||||
for (int x = 0; x < pattern.length; ++x)
|
|
||||||
{
|
|
||||||
String line = JsonUtils.getString(patternJ.get(x), "pattern[" + x + "]");
|
|
||||||
if (line.length() > 3)
|
|
||||||
throw new JsonSyntaxException("Invalid pattern: too many columns, 3 is maximum");
|
|
||||||
if (x > 0 && pattern[0].length() != line.length())
|
|
||||||
throw new JsonSyntaxException("Invalid pattern: each row must be the same width");
|
|
||||||
pattern[x] = line;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NonNullList<Ingredient> input = NonNullList.withSize(pattern[0].length() * pattern.length, Ingredient.EMPTY);
|
}
|
||||||
Set<Character> keys = Sets.newHashSet(ingMap.keySet());
|
catch (IllegalArgumentException | JsonParseException e)
|
||||||
keys.remove(' ');
|
|
||||||
|
|
||||||
int x = 0;
|
|
||||||
for (String line : pattern)
|
|
||||||
{
|
{
|
||||||
for (char chr : line.toCharArray())
|
LOGGER.error(CRAFTHELPER, "Parsing error loading constants {}", key, e);
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
{
|
{
|
||||||
Ingredient ing = ingMap.get(chr);
|
LOGGER.error(CRAFTHELPER, "Couldn't read constants from {}", key, e);
|
||||||
if (ing == null)
|
|
||||||
throw new JsonSyntaxException("Pattern references symbol '" + chr + "' but it's not defined in the key");
|
|
||||||
input.set(x++, ing);
|
|
||||||
keys.remove(chr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
constants = ret;
|
||||||
if (!keys.isEmpty())
|
|
||||||
throw new JsonSyntaxException("Key defines symbols that aren't used in pattern: " + keys);
|
|
||||||
|
|
||||||
ItemStack result = CraftingHelper.getItemStack(JsonUtils.getJsonObject(json, "result"), context);
|
|
||||||
return new ShapedRecipes(group, pattern[0].length(), pattern.length, input, result);
|
|
||||||
});
|
|
||||||
registerR("minecraft:crafting_shapeless", (context, json) -> {
|
|
||||||
String group = JsonUtils.getString(json, "group", "");
|
|
||||||
|
|
||||||
NonNullList<Ingredient> ings = NonNullList.create();
|
|
||||||
for (JsonElement ele : JsonUtils.getJsonArray(json, "ingredients"))
|
|
||||||
ings.add(CraftingHelper.getIngredient(ele, context));
|
|
||||||
|
|
||||||
if (ings.isEmpty())
|
|
||||||
throw new JsonParseException("No ingredients for shapeless recipe");
|
|
||||||
if (ings.size() > 9)
|
|
||||||
throw new JsonParseException("Too many ingredients for shapeless recipe");
|
|
||||||
|
|
||||||
ItemStack itemstack = CraftingHelper.getItemStack(JsonUtils.getJsonObject(json, "result"), context);
|
|
||||||
return new ShapelessRecipes(group, itemstack, ings);
|
|
||||||
});
|
|
||||||
registerR("forge:ore_shaped", ShapedOreRecipe::factory);
|
|
||||||
registerR("forge:ore_shapeless", ShapelessOreRecipe::factory);
|
|
||||||
|
|
||||||
registerI("minecraft:item", (context, json) -> Ingredient.fromStacks(CraftingHelper.getItemStackBasic(json, context)));
|
|
||||||
registerI("minecraft:empty", (context, json) -> Ingredient.EMPTY);
|
|
||||||
registerI("minecraft:item_nbt", (context, json) -> new IngredientNBT(CraftingHelper.getItemStack(json, context)));
|
|
||||||
registerI("forge:ore_dict", (context, json) -> new OreIngredient(JsonUtils.getString(json, "ore")));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void registerC(String name, IConditionFactory fac) {
|
|
||||||
register(new ResourceLocation(name), fac);
|
|
||||||
}
|
|
||||||
private static void registerR(String name, IRecipeFactory fac) {
|
|
||||||
register(new ResourceLocation(name), fac);
|
|
||||||
}
|
|
||||||
private static void registerI(String name, IIngredientFactory fac) {
|
|
||||||
register(new ResourceLocation(name), fac);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void loadFactories(JsonObject json, JsonContext context)
|
|
||||||
{
|
|
||||||
if (json.has("ingredients"))
|
|
||||||
{
|
|
||||||
for (Entry<String, JsonElement> entry : JsonUtils.getJsonObject(json, "ingredients").entrySet())
|
|
||||||
{
|
|
||||||
ResourceLocation key = new ResourceLocation(context.getModId(), entry.getKey());
|
|
||||||
String clsName = JsonUtils.getString(entry.getValue(), "ingredients[" + entry.getValue() + "]");
|
|
||||||
register(key, getClassInstance(clsName, IIngredientFactory.class));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (json.has("recipes"))
|
|
||||||
{
|
|
||||||
for (Entry<String, JsonElement> entry : JsonUtils.getJsonObject(json, "recipes").entrySet())
|
|
||||||
{
|
|
||||||
ResourceLocation key = new ResourceLocation(context.getModId(), entry.getKey());
|
|
||||||
String clsName = JsonUtils.getString(entry.getValue(), "recipes[" + entry.getValue() + "]");
|
|
||||||
register(key, getClassInstance(clsName, IRecipeFactory.class));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (json.has("conditions"))
|
|
||||||
{
|
|
||||||
for (Entry<String, JsonElement> entry : JsonUtils.getJsonObject(json, "conditions").entrySet())
|
|
||||||
{
|
|
||||||
ResourceLocation key = new ResourceLocation(context.getModId(), entry.getKey());
|
|
||||||
String clsName = JsonUtils.getString(entry.getValue(), "conditions[" + entry.getValue() + "]");
|
|
||||||
register(key, getClassInstance(clsName, IConditionFactory.class));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private static <T> T getClassInstance(String clsName, Class<T> expected)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Class<?> cls = Class.forName(clsName, true, Thread.currentThread().getContextClassLoader());
|
|
||||||
if (!expected.isAssignableFrom(cls))
|
|
||||||
throw new JsonSyntaxException("Class '" + clsName + "' is not an " + expected.getSimpleName());
|
|
||||||
return (T)cls.newInstance();
|
|
||||||
}
|
|
||||||
catch (ClassNotFoundException e)
|
|
||||||
{
|
|
||||||
throw new JsonSyntaxException("Could not find " + expected.getSimpleName() + ": " + clsName, e);
|
|
||||||
}
|
|
||||||
catch (InstantiationException | IllegalAccessException e)
|
|
||||||
{
|
|
||||||
throw new JsonSyntaxException("Could not instantiate " + expected.getSimpleName() + ": " + clsName, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void loadRecipes(boolean revertFrozen)
|
|
||||||
{
|
|
||||||
//TODO: If this errors in ServerInit it freezes the client at loading world, find a way to pop that up?
|
|
||||||
//TODO: Figure out how to remove recipes, and override them. This relies on cpw to help.
|
|
||||||
//For now this is only done one after mod init, I want to move this to ServerInit and re-do it many times.
|
|
||||||
init();
|
|
||||||
ForgeRegistry<IRecipe> reg = (ForgeRegistry<IRecipe>)ForgeRegistries.RECIPES;
|
|
||||||
//reg.unfreeze();
|
|
||||||
if (DEBUG_LOAD_MINECRAFT)
|
|
||||||
reg.clear();
|
|
||||||
else if (revertFrozen)
|
|
||||||
GameData.revert(RegistryManager.FROZEN, GameData.RECIPES, false);
|
|
||||||
|
|
||||||
ModList.get().forEachModFile(CraftingHelper::loadFactories);
|
|
||||||
ModList.get().forEachModFile(CraftingHelper::loadRecipes);
|
|
||||||
|
|
||||||
GameData.fireRegistryEvents(rl -> rl.equals(GameData.RECIPES));
|
|
||||||
|
|
||||||
//reg.freeze();
|
|
||||||
DistExecutor.runWhenOn(Dist.CLIENT, ()-> RecipeBookClient::rebuildTable);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void loadFactories(final ModFile modFile)
|
|
||||||
{
|
|
||||||
modFile.getModInfos().forEach(modInfo-> {
|
|
||||||
final String modId = modInfo.getModId();
|
|
||||||
JsonContext ctx = new JsonContext(modId);
|
|
||||||
final Path fPath = modFile.getLocator().findPath(modFile, "assets", modId, "recipes","_factories.json");
|
|
||||||
if (fPath != null && Files.exists(fPath))
|
|
||||||
{
|
|
||||||
try (final BufferedReader reader = Files.newBufferedReader(fPath))
|
|
||||||
{
|
|
||||||
JsonObject json = JsonUtils.fromJson(GSON, reader, JsonObject.class);
|
|
||||||
loadFactories(json, ctx);
|
|
||||||
}
|
|
||||||
catch (final IOException e)
|
|
||||||
{
|
|
||||||
LOGGER.error(CRAFTHELPER,"Encountered error reading recipe factories for {}", modId, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean loadRecipes(final ModFile modFile)
|
|
||||||
{
|
|
||||||
final AtomicBoolean errored = new AtomicBoolean(false);
|
|
||||||
modFile.getModInfos().forEach(modInfo-> {
|
|
||||||
final String modId = modInfo.getModId();
|
|
||||||
JsonContext ctx = new JsonContext(modId);
|
|
||||||
final Path root = modFile.getLocator().findPath(modFile, "assets", modId, "recipes");
|
|
||||||
if (!Files.exists(root)) return;
|
|
||||||
final Path constants = modFile.getLocator().findPath(modFile, "assets", modId, "recipes", "_constants.json");
|
|
||||||
if (Files.exists(constants))
|
|
||||||
{
|
|
||||||
try (BufferedReader reader = Files.newBufferedReader(constants))
|
|
||||||
{
|
|
||||||
JsonObject[] json = JsonUtils.fromJson(GSON, reader, JsonObject[].class);
|
|
||||||
ctx.loadConstants(json);
|
|
||||||
}
|
|
||||||
catch (final IOException e)
|
|
||||||
{
|
|
||||||
LOGGER.error(CRAFTHELPER, "Error loading _constants.json: ", e);
|
|
||||||
errored.set(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Files.walk(root).
|
|
||||||
filter(p -> p.getFileName().toString().startsWith("_") || Objects.equals(FilenameUtils.getExtension(p.getFileName().toString()), "json")).
|
|
||||||
forEach(p -> {
|
|
||||||
final String relative = root.relativize(p).toString();
|
|
||||||
final String name = FilenameUtils.removeExtension(relative).replaceAll("\\\\", "/");
|
|
||||||
final ResourceLocation key = new ResourceLocation(modId, name);
|
|
||||||
try (BufferedReader reader = Files.newBufferedReader(constants))
|
|
||||||
{
|
|
||||||
JsonObject json = JsonUtils.fromJson(GSON, reader, JsonObject.class);
|
|
||||||
if (json.has("conditions") && !CraftingHelper.processConditions(JsonUtils.getJsonArray(json, "conditions"), ctx))
|
|
||||||
return;
|
|
||||||
IRecipe recipe = CraftingHelper.getRecipe(json, ctx);
|
|
||||||
ForgeRegistries.RECIPES.register(recipe.setRegistryName(key));
|
|
||||||
}
|
|
||||||
catch (final JsonParseException e)
|
|
||||||
{
|
|
||||||
LOGGER.error(CRAFTHELPER, "Parsing error loading recipe {}", key, e);
|
|
||||||
errored.set(true);
|
|
||||||
}
|
|
||||||
catch (final IOException e)
|
|
||||||
{
|
|
||||||
LOGGER.error(CRAFTHELPER, "Couldn't read recipe {} from {}", key, p, e);
|
|
||||||
errored.set(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
catch (final IOException e)
|
|
||||||
{
|
|
||||||
LOGGER.error(CRAFTHELPER, "Error occurred walking file tree", e);
|
|
||||||
errored.set(true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return errored.get();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,8 @@ import java.util.function.BooleanSupplier;
|
||||||
|
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
public interface IConditionFactory {
|
@FunctionalInterface
|
||||||
BooleanSupplier parse(JsonContext context, JsonObject json);
|
public interface IConditionSerializer
|
||||||
|
{
|
||||||
|
BooleanSupplier parse(JsonObject json);
|
||||||
}
|
}
|
|
@ -19,14 +19,16 @@
|
||||||
|
|
||||||
package net.minecraftforge.common.crafting;
|
package net.minecraftforge.common.crafting;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
|
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
import net.minecraft.item.crafting.Ingredient;
|
import net.minecraft.item.crafting.Ingredient;
|
||||||
|
import net.minecraft.network.PacketBuffer;
|
||||||
|
|
||||||
public interface IIngredientFactory
|
public interface IIngredientSerializer<T extends Ingredient>
|
||||||
{
|
{
|
||||||
@Nonnull //If you would return null throw JsonSyntaxException to explain why
|
T parse(PacketBuffer buffer);
|
||||||
Ingredient parse(JsonContext context, JsonObject json);
|
|
||||||
|
T parse(JsonObject json);
|
||||||
|
|
||||||
|
void write(PacketBuffer buffer, T ingredient);
|
||||||
}
|
}
|
|
@ -1,28 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.common.crafting;
|
|
||||||
|
|
||||||
import com.google.gson.JsonObject;
|
|
||||||
|
|
||||||
import net.minecraft.item.crafting.IRecipe;
|
|
||||||
|
|
||||||
public interface IRecipeFactory {
|
|
||||||
IRecipe parse(JsonContext context, JsonObject json);
|
|
||||||
}
|
|
|
@ -19,22 +19,27 @@
|
||||||
|
|
||||||
package net.minecraftforge.common.crafting;
|
package net.minecraftforge.common.crafting;
|
||||||
|
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.item.crafting.Ingredient;
|
import net.minecraft.item.crafting.Ingredient;
|
||||||
|
import net.minecraft.network.PacketBuffer;
|
||||||
|
|
||||||
public class IngredientNBT extends Ingredient
|
public class IngredientNBT extends Ingredient
|
||||||
{
|
{
|
||||||
private final ItemStack stack;
|
private final ItemStack stack;
|
||||||
protected IngredientNBT(ItemStack stack)
|
protected IngredientNBT(ItemStack stack)
|
||||||
{
|
{
|
||||||
super(stack);
|
super(Stream.of(new Ingredient.SingleItemList(stack)));
|
||||||
this.stack = stack;
|
this.stack = stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(@Nullable ItemStack input)
|
public boolean test(@Nullable ItemStack input)
|
||||||
{
|
{
|
||||||
if (input == null)
|
if (input == null)
|
||||||
return false;
|
return false;
|
||||||
|
@ -47,4 +52,22 @@ public class IngredientNBT extends Ingredient
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class Serializer implements IIngredientSerializer<IngredientNBT>
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public IngredientNBT parse(PacketBuffer buffer) {
|
||||||
|
return new IngredientNBT(buffer.readItemStack());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IngredientNBT parse(JsonObject json) {
|
||||||
|
return new IngredientNBT(CraftingHelper.getItemStack(json, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(PacketBuffer buffer, IngredientNBT ingredient) {
|
||||||
|
buffer.writeItemStack(ingredient.stack);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,73 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.common.crafting;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import com.google.gson.JsonObject;
|
|
||||||
import com.google.gson.JsonSyntaxException;
|
|
||||||
|
|
||||||
import net.minecraft.item.crafting.Ingredient;
|
|
||||||
import net.minecraft.util.JsonUtils;
|
|
||||||
|
|
||||||
public class JsonContext
|
|
||||||
{
|
|
||||||
private String modId;
|
|
||||||
private Map<String, Ingredient> constants = Maps.newHashMap();
|
|
||||||
|
|
||||||
public JsonContext(String modId)
|
|
||||||
{
|
|
||||||
this.modId = modId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getModId()
|
|
||||||
{
|
|
||||||
return this.modId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String appendModId(String data)
|
|
||||||
{
|
|
||||||
if (data.indexOf(':') == -1)
|
|
||||||
return modId + ":" + data;
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public Ingredient getConstant(String name)
|
|
||||||
{
|
|
||||||
return constants.get(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void loadConstants(JsonObject[] jsons)
|
|
||||||
{
|
|
||||||
for (JsonObject json : jsons)
|
|
||||||
{
|
|
||||||
if (json.has("conditions") && !CraftingHelper.processConditions(json.getAsJsonArray("conditions"), this))
|
|
||||||
continue;
|
|
||||||
if (!json.has("ingredient"))
|
|
||||||
throw new JsonSyntaxException("Constant entry must contain 'ingredient' value");
|
|
||||||
constants.put(JsonUtils.getString(json, "name"), CraftingHelper.getIngredient(json.get("ingredient"), this));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
* Minecraft Forge
|
||||||
|
* Copyright (c) 2016-2018.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation version 2.1
|
||||||
|
* of the License.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/package net.minecraftforge.common.crafting;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import com.google.gson.JsonArray;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.item.crafting.Ingredient.IItemList;
|
||||||
|
|
||||||
|
public class StackList implements IItemList
|
||||||
|
{
|
||||||
|
private Collection<ItemStack> items;
|
||||||
|
public StackList(Collection<ItemStack> items)
|
||||||
|
{
|
||||||
|
this.items = Collections.unmodifiableCollection(items);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<ItemStack> func_199799_a()
|
||||||
|
{
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JsonObject func_200303_b()
|
||||||
|
{
|
||||||
|
if (items.size() == 1)
|
||||||
|
return toJson(items.iterator().next());
|
||||||
|
|
||||||
|
JsonObject ret = new JsonObject();
|
||||||
|
JsonArray array = new JsonArray();
|
||||||
|
items.forEach(stack -> array.add(toJson(stack)));
|
||||||
|
ret.add("items", array);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
private JsonObject toJson(ItemStack stack)
|
||||||
|
{
|
||||||
|
JsonObject ret = new JsonObject();
|
||||||
|
ret.addProperty("item", stack.getItem().getRegistryName().toString());
|
||||||
|
if (stack.getCount() != 1)
|
||||||
|
ret.addProperty("count", stack.getCount());
|
||||||
|
if (stack.getTagCompound() != null)
|
||||||
|
ret.addProperty("nbt", stack.getTagCompound().toString()); //TODO: Better serialization?
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
// Auto generated package-info by MCP
|
||||||
|
@ParametersAreNonnullByDefault
|
||||||
|
@MethodsReturnNonnullByDefault
|
||||||
|
package net.minecraftforge.common.crafting;
|
||||||
|
|
||||||
|
import mcp.MethodsReturnNonnullByDefault;
|
||||||
|
import javax.annotation.ParametersAreNonnullByDefault;
|
|
@ -345,7 +345,15 @@ protected net.minecraft.world.Teleporter field_85191_c # destinationCoordinateCa
|
||||||
public net.minecraft.util.ResourceLocation func_177516_a(Ljava/lang/String;)[Ljava/lang/String; # splitObjectName
|
public net.minecraft.util.ResourceLocation func_177516_a(Ljava/lang/String;)[Ljava/lang/String; # splitObjectName
|
||||||
|
|
||||||
# Ingredient
|
# Ingredient
|
||||||
protected net.minecraft.item.crafting.Ingredient <init>([Lnet/minecraft/item/ItemStack;)V # Ingredient
|
public-f net.minecraft.item.crafting.Ingredient
|
||||||
|
protected net.minecraft.item.crafting.Ingredient <init>(Ljava/util/stream/Stream;)V
|
||||||
|
public net.minecraft.item.crafting.Ingredient func_209357_a(Ljava/util/stream/Stream;)Lnet/minecraft/item/crafting/Ingredient;
|
||||||
|
public+f net.minecraft.item.crafting.Ingredient func_199564_a(Lnet/minecraft/network/PacketBuffer;)V
|
||||||
|
public net.minecraft.item.crafting.Ingredient$IItemList
|
||||||
|
public net.minecraft.item.crafting.Ingredient$SingleItemList
|
||||||
|
public net.minecraft.item.crafting.Ingredient$SingleItemList <init>(Lnet/minecraft/item/ItemStack;)V
|
||||||
|
public net.minecraft.item.crafting.Ingredient$TagList
|
||||||
|
public net.minecraft.item.crafting.Ingredient$TagList <init>(Lnet/minecraft/tags/Tag;)V
|
||||||
|
|
||||||
# Crafting
|
# Crafting
|
||||||
public net.minecraft.client.Minecraft func_193986_ar()V # populateSearchTreeManager
|
public net.minecraft.client.Minecraft func_193986_ar()V # populateSearchTreeManager
|
||||||
|
|
Loading…
Reference in a new issue