From 17fe25bef7fcb1898d5cb1aac3308cba2c07910f Mon Sep 17 00:00:00 2001 From: TheDarkDnKTv Date: Tue, 9 Mar 2021 03:22:54 +0200 Subject: [PATCH] Fixed Fluid recipe NBT write Wow, forge overrides equals() and hashCode() in FluidStack but did not int Fluid. It cause fluid has different hash after restart of JVM. Fixed by adding custom hashCode in GT_Utility. Works fine. Closes #74. --- .../java/gregtechmod/api/recipe/Recipe.java | 61 +++++++++++++------ .../java/gregtechmod/api/util/GT_Utility.java | 23 +++++++ .../recipe/logic/GeneratorRecipeLogic.java | 2 +- 3 files changed, 66 insertions(+), 20 deletions(-) diff --git a/src/main/java/gregtechmod/api/recipe/Recipe.java b/src/main/java/gregtechmod/api/recipe/Recipe.java index e9c7e1c..6a162fd 100644 --- a/src/main/java/gregtechmod/api/recipe/Recipe.java +++ b/src/main/java/gregtechmod/api/recipe/Recipe.java @@ -2,7 +2,6 @@ package gregtechmod.api.recipe; import gregtechmod.api.util.GT_Log; import gregtechmod.api.util.GT_Utility; -import gregtechmod.common.recipe.RecipeEntry; import java.util.ArrayList; import java.util.Collection; @@ -16,7 +15,6 @@ import java.util.stream.Collectors; import org.apache.commons.lang3.tuple.Pair; -import net.minecraft.init.Blocks; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; @@ -332,16 +330,18 @@ public class Recipe { //////////////////// public void writeToNBT(NBTTagCompound data) { - NBTTagList outputs = new NBTTagList(); - for (ItemStack out : this.getResults(new Random())) { - NBTTagCompound stack = out.writeToNBT(new NBTTagCompound()); - outputs.appendTag(stack); - } + NBTTagList itemOut = new NBTTagList(); + NBTTagList fluidOut = new NBTTagList(); + for (ItemStack out : this.getResults(new Random())) + itemOut.appendTag(out.writeToNBT(new NBTTagCompound())); + for (FluidStack out : this.getFluidOutputs()) + fluidOut.appendTag(out.writeToNBT(new NBTTagCompound())); + data.setInteger("recipeHash", this.hashCode()); - data.setTag("recipeOutput", outputs); + data.setTag("recipeItemOutput", itemOut); + data.setTag("recipeFluidOutput", fluidOut); } - // TODO still does not support fluid output saves public static Recipe loadFromNBT(RecipeMap recipeMap, NBTTagCompound data) { if (recipeMap != null && data.hasKey("recipeHash")) { int hash = data.getInteger("recipeHash"); @@ -352,21 +352,41 @@ public class Recipe { } } - if (data.hasKey("recipeOutput")) { - NBTTagList recipe = data.getTagList("recipeOutput", 10); + if (data.hasKey("recipeItemOutput") || data.hasKey("recipeFluidOutput")) { + NBTTagList itemOut = data.getTagList("recipeItemOutput", 10); + NBTTagList fluidOut = data.getTagList("recipeFluidOutput", 10); List stacks = new ArrayList<>(); - for (int i = 0; i < recipe.tagCount(); i++) { - NBTTagCompound stackData = recipe.getCompoundTagAt(i); + List fluids = new ArrayList<>(); + + for (int i = 0; itemOut != null && i < itemOut.tagCount(); i++) { + NBTTagCompound stackData = itemOut.getCompoundTagAt(i); ItemStack stack = ItemStack.loadItemStackFromNBT(stackData); if (stack != null) { stacks.add(stack); - } else GT_Log.log.error("Unable to load stack from tag: " + stackData); + } else GT_Log.log.error("Unable to load item stack from tag: " + stackData); + } + + for (int i = 0; fluidOut != null && i < fluidOut.tagCount(); i++) { + NBTTagCompound stackData = fluidOut.getCompoundTagAt(i); + FluidStack stack = FluidStack.loadFluidStackFromNBT(stackData); + if (stack != null) { + fluids.add(stack); + } else GT_Log.log.error("Unable to load fluid stack from tag: " + stackData); } return new Recipe(0, 0, 0, false, - Collections.singleton(RecipeEntry.singleton(new ItemStack(Blocks.bedrock))), + Collections.emptyList(), stacks, - Collections.emptyList()); + Collections.emptyList(), + Collections.emptyList(), + fluids, + Collections.emptyMap()) { + + @Override + public boolean matches(boolean decrease, List input, List fluidInputs) { + return false; + } + }; } return null; @@ -378,13 +398,16 @@ public class Recipe { @Override public int hashCode() { - return (startEU * EUt * duration) + (shaped ? 1 : 0) + int hash = (3 * startEU) + (3 * EUt) + (3 * duration) + (shaped ? 1 : 0) + itemInputs.hashCode() + itemOutputs.hashCode() + chancedOutputs.hashCode() - + fluidInputs.hashCode() - + fluidOutputs.hashCode() + metadata.hashCode(); + for (FluidStack fluid : fluidInputs) + hash += GT_Utility.hashFluidStack(fluid); + for (FluidStack fluid : fluidOutputs) + hash += GT_Utility.hashFluidStack(fluid); + return hash; } @Override diff --git a/src/main/java/gregtechmod/api/util/GT_Utility.java b/src/main/java/gregtechmod/api/util/GT_Utility.java index 894629c..38469fb 100644 --- a/src/main/java/gregtechmod/api/util/GT_Utility.java +++ b/src/main/java/gregtechmod/api/util/GT_Utility.java @@ -71,6 +71,29 @@ public class GT_Utility { public static final DecimalFormat sFormat = new DecimalFormat("###,###.##", new DecimalFormatSymbols(Locale.ENGLISH)); + public static int hashFluidStack(FluidStack stack) { + int code = 1; + code = 31*code + hashFluid(stack.getFluid()); + code = 31*code + stack.amount; + if (stack.tag != null) + code = 31*code + stack.tag.hashCode(); + return code; + } + + public static int hashFluid(Fluid fluid) { + int code = 1; + code = 31*code + fluid.getName().hashCode(); + if (fluid.getUnlocalizedName() != null) + code = 31*code + fluid.getUnlocalizedName().hashCode(); + code = 31*code + fluid.getColor(); + code += fluid.getDensity() + + fluid.getLuminosity() + + fluid.getTemperature() + + fluid.getViscosity() + + (fluid.isGaseous() ? 1 : 0); + return code; + } + public static String toIndexNumbers(String string) { char[] charArray = string.toCharArray(); for (int i = 0; i < charArray.length; i++) { diff --git a/src/main/java/gregtechmod/common/recipe/logic/GeneratorRecipeLogic.java b/src/main/java/gregtechmod/common/recipe/logic/GeneratorRecipeLogic.java index 020cce2..7900fec 100644 --- a/src/main/java/gregtechmod/common/recipe/logic/GeneratorRecipeLogic.java +++ b/src/main/java/gregtechmod/common/recipe/logic/GeneratorRecipeLogic.java @@ -85,7 +85,7 @@ public class GeneratorRecipeLogic extends RecipeLogic { if (getMachine().spaceForOutput(recipe)) { previousRecipe = recipe; progressTime = 1; - leftEU = (int) (recipe.getDuration() * recipe.getEUt() * (efficiency.getAsInt() / 100.0D)); + leftEU = (long) (recipe.getDuration() * recipe.getEUt() * (efficiency.getAsInt() / 100.0D)); maxProgressTime = (int) Math.ceil(leftEU * 1.0D / ((MetaTileEntity) getMachine()).maxEUOutput()); if (consumeInputs(recipe)) { triggerMachine(true);