From e837b2e2cd840d129335c0b609be9c7570adba05 Mon Sep 17 00:00:00 2001 From: cpw Date: Fri, 3 Apr 2015 10:26:17 -0400 Subject: [PATCH 01/48] MinecraftForge/FML@12ccf9cf49b76140841cdc5a459422ae4781de1a Rather than try to fall back to the backup level.dat in case of weirdness in the ID map, just fail hard. There is probably a serious modder derp in this case and there's nothing FML can do to recover the situation except avoid making it worse. MinecraftForge/FML@e8cd368da30661ed2898fff232e2db787edcbdcc It's an IllegalState not an IllegalArgument *sigh* MinecraftForge/FML@2be9c743424c92f8799a6af1d59d60edd65e6bf0 And fix itemblocks being removed, leaving behind a residual block. This is a legitimate action - use the missing mapping event to let the mod tell us about it MinecraftForge/FML@7d8804cf656081d1570068f52e9bfc7140b21a65 You can't setAction to BLOCKONLY MinecraftForge/FML@c73861efe67594ee9995bc93744cab06bd6647d1 Cherry-pick 01aaa7dc97480b381ca0d192ec65016d7baeb747 Fix mods defined via --mods or --modListFile launch args not being searched for coremods. #560 MinecraftForge/FML@94c45b48c1265e7c4f60f591d413fa545787d354 Fix json cache crash, handle the file much more cleanly. Probably an MC JIRA since it's a vanilla bug. Closes #619 --- fml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fml b/fml index 24cb4a42c..94c45b48c 160000 --- a/fml +++ b/fml @@ -1 +1 @@ -Subproject commit 24cb4a42c4e4bddde95c0e49d1f8b8bcc20c626d +Subproject commit 94c45b48c1265e7c4f60f591d413fa545787d354 From 38b9febfe5cf9a1d15eef6983d3ccbb92b4b8dda Mon Sep 17 00:00:00 2001 From: cpw Date: Fri, 3 Apr 2015 10:31:25 -0400 Subject: [PATCH 02/48] Forge really should have always supported the concept of an "exact spawn". Individual world providers can still change this behaviour of course, but for default maps it makes sense to support it as a config option. --- .../minecraft/world/WorldProvider.java.patch | 22 +++++++++---------- .../common/ForgeModContainer.java | 11 ++++++++-- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/patches/minecraft/net/minecraft/world/WorldProvider.java.patch b/patches/minecraft/net/minecraft/world/WorldProvider.java.patch index 047326f7c..72b9ef57b 100644 --- a/patches/minecraft/net/minecraft/world/WorldProvider.java.patch +++ b/patches/minecraft/net/minecraft/world/WorldProvider.java.patch @@ -51,11 +51,11 @@ + private IRenderHandler skyRenderer = null; + private IRenderHandler cloudRenderer = null; + private IRenderHandler weatherRenderer = null; -+ ++ + /** + * Sets the providers current dimension ID, used in default getSaveFolder() + * Added to allow default providers to be registered for multiple dimensions. -+ * ++ * + * @param dim Dimension ID + */ + public void setDimension(int dim) @@ -105,7 +105,7 @@ + else if (this instanceof WorldProviderHell) + { + return "Leaving the Nether"; -+ } ++ } + return null; + } + @@ -168,7 +168,7 @@ + int spawnFuzz = field_76577_b.getSpawnFuzz(); + int spawnFuzzHalf = spawnFuzz / 2; + -+ if (!field_76576_e && !isAdventure) ++ if (!field_76576_e && !isAdventure && net.minecraftforge.common.ForgeModContainer.defaultHasSpawnFuzz) + { + chunkcoordinates.field_71574_a += this.field_76579_a.field_73012_v.nextInt(spawnFuzz) - spawnFuzzHalf; + chunkcoordinates.field_71573_c += this.field_76579_a.field_73012_v.nextInt(spawnFuzz) - spawnFuzzHalf; @@ -177,10 +177,10 @@ + + return chunkcoordinates; + } -+ ++ + /** + * Determine if the cusor on the map should 'spin' when rendered, like it does for the player in the nether. -+ * ++ * + * @param entity The entity holding the map, playername, or frame-ENTITYID + * @param x X Position + * @param y Y Position @@ -194,7 +194,7 @@ + + /** + * Determines the dimension the player will be respawned in, typically this brings them back to the overworld. -+ * ++ * + * @param player The player that is respawning + * @return The dimension to respawn the player in + */ @@ -214,20 +214,20 @@ + { + return field_76579_a.field_73008_k < 4; + } -+ ++ + /** + * The current sun brightness factor for this dimension. + * 0.0f means no light at all, and 1.0f means maximum sunlight. + * This will be used for the "calculateSkylightSubtracted" + * which is for Sky light value calculation. -+ * ++ * + * @return The current brightness factor + * */ + public float getSunBrightnessFactor(float par1) + { + return field_76579_a.getSunBrightnessFactor(par1); + } -+ ++ + /** + * Calculates the current moon phase factor. + * This factor is effective for slimes. @@ -258,7 +258,7 @@ + { + return field_76579_a.getSunBrightnessBody(par1); + } -+ ++ + /** + * Gets the Star Brightness for rendering sky. + * */ diff --git a/src/main/java/net/minecraftforge/common/ForgeModContainer.java b/src/main/java/net/minecraftforge/common/ForgeModContainer.java index dcff0959a..40ed8b2e6 100644 --- a/src/main/java/net/minecraftforge/common/ForgeModContainer.java +++ b/src/main/java/net/minecraftforge/common/ForgeModContainer.java @@ -68,6 +68,7 @@ public class ForgeModContainer extends DummyModContainer implements WorldAccessC public static boolean shouldSortRecipies = true; public static boolean disableVersionCheck = false; public static int defaultSpawnFuzz = 20; + public static boolean defaultHasSpawnFuzz = true; private static Configuration config; @@ -225,6 +226,12 @@ public class ForgeModContainer extends DummyModContainer implements WorldAccessC defaultSpawnFuzz = prop.getInt(20); propOrder.add(prop.getName()); + prop = config.get(Configuration.CATEGORY_GENERAL, "spawnHasFuzz", Boolean.TRUE, + "If the overworld has ANY spawn fuzz at all. If not, the spawn will always be the exact same location."); + prop.setLanguageKey("forge.configgui.hasspawnfuzz").setRequiresWorldRestart(false); + defaultHasSpawnFuzz = prop.getBoolean(Boolean.TRUE); + propOrder.add(prop.getName()); + config.setCategoryPropertyOrder(CATEGORY_GENERAL, propOrder); if (config.hasChanged()) @@ -253,7 +260,7 @@ public class ForgeModContainer extends DummyModContainer implements WorldAccessC } } } - + @SubscribeEvent public void playerLogin(PlayerEvent.PlayerLoggedInEvent event) { @@ -280,7 +287,7 @@ public class ForgeModContainer extends DummyModContainer implements WorldAccessC MinecraftForge.EVENT_BUS.register(MinecraftForge.INTERNAL_HANDLER); ForgeChunkManager.captureConfig(evt.getModConfigurationDirectory()); FMLCommonHandler.instance().bus().register(this); - + if (!ForgeModContainer.disableVersionCheck) { ForgeVersion.startVersionCheck(); From 3fc40b955acb088d28354d348b283bce054ddef1 Mon Sep 17 00:00:00 2001 From: King Lemming Date: Wed, 25 Mar 2015 01:27:15 -0400 Subject: [PATCH 03/48] Removed fluidID from ItemStack. This fixes a rather huge issue where FluidStacks on the client could be desynced if a modder was unaware of it. This is a breaking change but can be mitigated with a transformer to the getter getFluidID(). Signed-off-by: King Lemming --- .../common/network/ForgeMessage.java | 14 ++--- .../minecraftforge/fluids/BlockFluidBase.java | 8 ++- .../java/net/minecraftforge/fluids/Fluid.java | 23 ++----- .../fluids/FluidContainerRegistry.java | 19 +++--- .../minecraftforge/fluids/FluidRegistry.java | 43 +++++++------ .../net/minecraftforge/fluids/FluidStack.java | 63 +++++++++++-------- 6 files changed, 88 insertions(+), 82 deletions(-) diff --git a/src/main/java/net/minecraftforge/common/network/ForgeMessage.java b/src/main/java/net/minecraftforge/common/network/ForgeMessage.java index 72f44d79e..6ba6ccd5f 100644 --- a/src/main/java/net/minecraftforge/common/network/ForgeMessage.java +++ b/src/main/java/net/minecraftforge/common/network/ForgeMessage.java @@ -1,12 +1,10 @@ package net.minecraftforge.common.network; import java.util.Map; - +import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidRegistry; - import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; - import cpw.mods.fml.common.network.ByteBufUtils; import io.netty.buffer.ByteBuf; @@ -40,15 +38,15 @@ public abstract class ForgeMessage { } public static class FluidIdMapMessage extends ForgeMessage { - BiMap fluidIds = HashBiMap.create(); + BiMap fluidIds = HashBiMap.create(); @Override void toBytes(ByteBuf bytes) { - Map ids = FluidRegistry.getRegisteredFluidIDs(); + Map ids = FluidRegistry.getRegisteredFluidIDs(); bytes.writeInt(ids.size()); - for (Map.Entry entry : ids.entrySet()) + for (Map.Entry entry : ids.entrySet()) { - ByteBufUtils.writeUTF8String(bytes,entry.getKey()); + ByteBufUtils.writeUTF8String(bytes,entry.getKey().getName()); bytes.writeInt(entry.getValue()); } } @@ -60,7 +58,7 @@ public abstract class ForgeMessage { for (int i = 0; i < listSize; i++) { String fluidName = ByteBufUtils.readUTF8String(bytes); int fluidId = bytes.readInt(); - fluidIds.put(fluidName, fluidId); + fluidIds.put(FluidRegistry.getFluid(fluidName), fluidId); } } } diff --git a/src/main/java/net/minecraftforge/fluids/BlockFluidBase.java b/src/main/java/net/minecraftforge/fluids/BlockFluidBase.java index 014fec041..2bda1e32b 100644 --- a/src/main/java/net/minecraftforge/fluids/BlockFluidBase.java +++ b/src/main/java/net/minecraftforge/fluids/BlockFluidBase.java @@ -42,7 +42,7 @@ public abstract class BlockFluidBase extends Block implements IFluidBlock protected float quantaPerBlockFloat = 8F; protected int density = 1; protected int densityDir = -1; - protected int temperature = 295; + protected int temperature = 300; protected int tickRate = 20; protected int renderPass = 1; @@ -226,6 +226,12 @@ public abstract class BlockFluidBase extends Block implements IFluidBlock return false; } + @Override + public boolean canPlaceBlockAt(World world, int x, int y, int z) + { + return canDisplace(world, x, y, z); + } + @Override public boolean getBlocksMovement(IBlockAccess world, int x, int y, int z) { diff --git a/src/main/java/net/minecraftforge/fluids/Fluid.java b/src/main/java/net/minecraftforge/fluids/Fluid.java index 8ef8b9b59..548e82e1e 100644 --- a/src/main/java/net/minecraftforge/fluids/Fluid.java +++ b/src/main/java/net/minecraftforge/fluids/Fluid.java @@ -33,7 +33,7 @@ import net.minecraft.item.EnumRarity; * */ public class Fluid -{ +{ /** The unique identification name for this fluid. */ protected final String fluidName; @@ -65,13 +65,17 @@ public class Fluid * * Default value is approximately the real-life room temperature of water in degrees Kelvin. */ - protected int temperature = 295; + protected int temperature = 300; /** * Viscosity ("thickness") of the fluid - completely arbitrary; negative values are not * permissible. * * Default value is approximately the real-life density of water in m/s^2 (x10^-3). + * + * Higher viscosity means that a fluid flows more slowly, like molasses. + * Lower viscosity means that a fluid flows more quickly, like helium. + * */ protected int viscosity = 1000; @@ -318,19 +322,4 @@ public class Fluid public int getColor(World world, int x, int y, int z){ return getColor(); } public IIcon getIcon(World world, int x, int y, int z){ return getIcon(); } - private static Map legacyNames = Maps.newHashMap(); - static String convertLegacyName(String fluidName) - { - return fluidName != null && legacyNames.containsKey(fluidName) ? legacyNames.get(fluidName) : fluidName; - } - - /** - * Register a legacy liquid name with the Fluids system - * @param legacyName The legacy name to recognize - * @param canonicalName The canonical fluid name it will become - */ - public static void registerLegacyName(String legacyName, String canonicalName) - { - legacyNames.put(legacyName.toLowerCase(Locale.ENGLISH), canonicalName); - } } diff --git a/src/main/java/net/minecraftforge/fluids/FluidContainerRegistry.java b/src/main/java/net/minecraftforge/fluids/FluidContainerRegistry.java index 043267c18..5ff13369e 100644 --- a/src/main/java/net/minecraftforge/fluids/FluidContainerRegistry.java +++ b/src/main/java/net/minecraftforge/fluids/FluidContainerRegistry.java @@ -34,15 +34,15 @@ public abstract class FluidContainerRegistry private static class ContainerKey { ItemStack container; - FluidStack fluid; + FluidStack stack; private ContainerKey(ItemStack container) { this.container = container; } - private ContainerKey(ItemStack container, FluidStack fluid) + private ContainerKey(ItemStack container, FluidStack stack) { this(container); - this.fluid = fluid; + this.stack = stack; } @Override public int hashCode() @@ -50,8 +50,8 @@ public abstract class FluidContainerRegistry int code = 1; code = 31*code + container.getItem().hashCode(); code = 31*code + container.getItemDamage(); - if (fluid != null) - code = 31*code + fluid.fluidID; + if (stack != null) + code = 31*code + stack.hashCode(); return code; } @Override @@ -61,10 +61,10 @@ public abstract class FluidContainerRegistry ContainerKey ck = (ContainerKey)o; if (container.getItem() != ck.container.getItem()) return false; if (container.getItemDamage() != ck.container.getItemDamage()) return false; - if (fluid == null && ck.fluid != null) return false; - if (fluid != null && ck.fluid == null) return false; - if (fluid == null && ck.fluid == null) return true; - if (fluid.fluidID != ck.fluid.fluidID) return false; + if (stack == null && ck.stack != null) return false; + if (stack != null && ck.stack == null) return false; + if (stack == null && ck.stack == null) return true; + if (stack.fluid != ck.stack.fluid) return false; return true; } } @@ -361,7 +361,6 @@ public abstract class FluidContainerRegistry public final ItemStack filledContainer; public final ItemStack emptyContainer; - public FluidContainerData(FluidStack stack, ItemStack filledContainer, ItemStack emptyContainer) { this(stack, filledContainer, emptyContainer, false); diff --git a/src/main/java/net/minecraftforge/fluids/FluidRegistry.java b/src/main/java/net/minecraftforge/fluids/FluidRegistry.java index 4fb50d12f..89476afe7 100644 --- a/src/main/java/net/minecraftforge/fluids/FluidRegistry.java +++ b/src/main/java/net/minecraftforge/fluids/FluidRegistry.java @@ -25,8 +25,8 @@ public abstract class FluidRegistry { static int maxID = 0; - static HashMap fluids = Maps.newHashMap(); - static BiMap fluidIDs = HashBiMap.create(); + static BiMap fluids = HashBiMap.create(); + static BiMap fluidIDs = HashBiMap.create(); static BiMap fluidBlocks; public static final Fluid WATER = new Fluid("water") { @@ -57,7 +57,7 @@ public abstract class FluidRegistry * Called by Forge to prepare the ID map for server -> client sync. * Modders, DO NOT call this. */ - public static void initFluidIDs(BiMap newfluidIDs) + public static void initFluidIDs(BiMap newfluidIDs) { maxID = newfluidIDs.size(); fluidIDs.clear(); @@ -78,7 +78,7 @@ public abstract class FluidRegistry return false; } fluids.put(fluid.getName(), fluid); - fluidIDs.put(fluid.getName(), ++maxID); + fluidIDs.put(fluid, ++maxID); MinecraftForge.EVENT_BUS.post(new FluidRegisterEvent(fluid.getName(), maxID)); return true; @@ -86,12 +86,12 @@ public abstract class FluidRegistry public static boolean isFluidRegistered(Fluid fluid) { - return fluidIDs.containsKey(fluid.getName()); + return fluids.containsKey(fluid.getName()); } public static boolean isFluidRegistered(String fluidName) { - return fluidIDs.containsKey(fluidName); + return fluids.containsKey(fluidName); } public static Fluid getFluid(String fluidName) @@ -101,31 +101,36 @@ public abstract class FluidRegistry public static Fluid getFluid(int fluidID) { - return fluids.get(getFluidName(fluidID)); + return fluidIDs.inverse().get(fluidID); } - public static String getFluidName(int fluidID) + public static int getFluidID(Fluid fluid) { - return fluidIDs.inverse().get(fluidID); - } - - public static String getFluidName(FluidStack stack) - { - return getFluidName(stack.fluidID); + return fluidIDs.get(fluid); } public static int getFluidID(String fluidName) { - return fluidIDs.get(fluidName); + return fluidIDs.get(getFluid(fluidName)); + } + + public static String getFluidName(Fluid fluid) + { + return fluids.inverse().get(fluid); + } + + public static String getFluidName(FluidStack stack) + { + return getFluidName(stack.fluid); } public static FluidStack getFluidStack(String fluidName, int amount) { - if (!fluidIDs.containsKey(fluidName)) + if (!fluids.containsKey(fluidName)) { return null; } - return new FluidStack(getFluidID(fluidName), amount); + return new FluidStack(getFluid(fluidName), amount); } /** @@ -137,9 +142,9 @@ public abstract class FluidRegistry } /** - * Returns a read-only map containing Fluid Names and their associated IDs. + * Returns a read-only map containing Fluid IDs and their associated Fluids. */ - public static Map getRegisteredFluidIDs() + public static Map getRegisteredFluidIDs() { return ImmutableMap.copyOf(fluidIDs); } diff --git a/src/main/java/net/minecraftforge/fluids/FluidStack.java b/src/main/java/net/minecraftforge/fluids/FluidStack.java index 4de7a2609..f23bb0b9e 100644 --- a/src/main/java/net/minecraftforge/fluids/FluidStack.java +++ b/src/main/java/net/minecraftforge/fluids/FluidStack.java @@ -18,25 +18,19 @@ import net.minecraft.nbt.NBTTagCompound; */ public class FluidStack { - public int fluidID; + public final Fluid fluid; public int amount; public NBTTagCompound tag; public FluidStack(Fluid fluid, int amount) { - this.fluidID = fluid.getID(); + this.fluid = fluid; this.amount = amount; } - public FluidStack(int fluidID, int amount) + public FluidStack(Fluid fluid, int amount, NBTTagCompound nbt) { - this.fluidID = fluidID; - this.amount = amount; - } - - public FluidStack(int fluidID, int amount, NBTTagCompound nbt) - { - this(fluidID, amount); + this(fluid, amount); if (nbt != null) { @@ -46,9 +40,23 @@ public class FluidStack public FluidStack(FluidStack stack, int amount) { - this(stack.fluidID, amount, stack.tag); + this(stack.fluid, amount, stack.tag); } + // To be removed in 1.8 + @Deprecated + public FluidStack(int fluidID, int amount) + { + this(FluidRegistry.getFluid(fluidID), amount); + } + + // To be removed in 1.8 + @Deprecated + public FluidStack(int fluidID, int amount, NBTTagCompound nbt) + { + this(FluidRegistry.getFluid(fluidID), amount, nbt); + } + /** * This provides a safe method for retrieving a FluidStack - if the Fluid is invalid, the stack * will return as null. @@ -60,32 +68,23 @@ public class FluidStack return null; } String fluidName = nbt.getString("FluidName"); - if (Strings.isNullOrEmpty(fluidName)) - { - fluidName = nbt.hasKey("LiquidName") ? nbt.getString("LiquidName").toLowerCase(Locale.ENGLISH) : null; - fluidName = Fluid.convertLegacyName(fluidName); - } - if (fluidName ==null || FluidRegistry.getFluid(fluidName) == null) + if (fluidName == null || FluidRegistry.getFluid(fluidName) == null) { return null; } - FluidStack stack = new FluidStack(FluidRegistry.getFluidID(fluidName), nbt.getInteger("Amount")); + FluidStack stack = new FluidStack(FluidRegistry.getFluid(fluidName), nbt.getInteger("Amount")); if (nbt.hasKey("Tag")) { stack.tag = nbt.getCompoundTag("Tag"); } - else if (nbt.hasKey("extra")) - { - stack.tag = nbt.getCompoundTag("extra"); - } return stack; } public NBTTagCompound writeToNBT(NBTTagCompound nbt) { - nbt.setString("FluidName", FluidRegistry.getFluidName(fluidID)); + nbt.setString("FluidName", FluidRegistry.getFluidName(fluid)); nbt.setInteger("Amount", amount); if (tag != null) @@ -97,9 +96,14 @@ public class FluidStack public final Fluid getFluid() { - return FluidRegistry.getFluid(fluidID); + return fluid; } + public final int getFluidID() + { + return FluidRegistry.getFluidID(fluid); + } + public String getLocalizedName() { return this.getFluid().getLocalizedName(this); @@ -115,7 +119,7 @@ public class FluidStack */ public FluidStack copy() { - return new FluidStack(fluidID, amount, tag); + return new FluidStack(fluid, amount, tag); } /** @@ -127,7 +131,7 @@ public class FluidStack */ public boolean isFluidEqual(FluidStack other) { - return other != null && fluidID == other.fluidID && isFluidStackTagEqual(other); + return other != null && fluid == other.fluid && isFluidStackTagEqual(other); } private boolean isFluidStackTagEqual(FluidStack other) @@ -192,7 +196,12 @@ public class FluidStack @Override public final int hashCode() { - return fluidID; + int code = 1; + code = 31*code + fluid.hashCode(); + code = 31*code + amount; + if (tag != null) + code = 31*code + tag.hashCode(); + return code; } /** From 7506a5b7ad28f30dd8394092956b4a198aab0a8d Mon Sep 17 00:00:00 2001 From: cpw Date: Sun, 5 Apr 2015 15:28:27 -0400 Subject: [PATCH 04/48] Add in a fluidid transformer --- .../classloading/FMLForgePlugin.java | 2 +- .../classloading/FluidIdTransformer.java | 56 +++++++++++++++++++ .../minecraftforge/common/ForgeVersion.java | 2 +- 3 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 src/main/java/net/minecraftforge/classloading/FluidIdTransformer.java diff --git a/src/main/java/net/minecraftforge/classloading/FMLForgePlugin.java b/src/main/java/net/minecraftforge/classloading/FMLForgePlugin.java index 35e0cdf68..cc0366402 100644 --- a/src/main/java/net/minecraftforge/classloading/FMLForgePlugin.java +++ b/src/main/java/net/minecraftforge/classloading/FMLForgePlugin.java @@ -13,7 +13,7 @@ public class FMLForgePlugin implements IFMLLoadingPlugin @Override public String[] getASMTransformerClass() { - return new String[0]; + return new String[] { "net.minecraftforge.classloading.FluidIdTransformer" }; } @Override diff --git a/src/main/java/net/minecraftforge/classloading/FluidIdTransformer.java b/src/main/java/net/minecraftforge/classloading/FluidIdTransformer.java new file mode 100644 index 000000000..a1dfb21d0 --- /dev/null +++ b/src/main/java/net/minecraftforge/classloading/FluidIdTransformer.java @@ -0,0 +1,56 @@ +package net.minecraftforge.classloading; + +import java.util.ListIterator; + +import net.minecraft.launchwrapper.IClassTransformer; + +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.FieldInsnNode; +import org.objectweb.asm.tree.FieldNode; +import org.objectweb.asm.tree.MethodInsnNode; +import org.objectweb.asm.tree.MethodNode; + +import cpw.mods.fml.common.FMLLog; + +public class FluidIdTransformer implements IClassTransformer { + private static final String FLUID_TYPE = "net/minecraftforge/fluids/FluidStack"; + private static final String GETID_NAME = "getFluidID"; + private static final String LEGACY_FIELDNAME = "fluidID"; + private static final String GETID_DESC = "()I"; + + @Override + public byte[] transform(String name, String transformedName, byte[] basicClass) { + if (basicClass == null) + return null; + ClassNode classNode = new ClassNode(); + ClassReader classReader = new ClassReader(basicClass); + classReader.accept(classNode, 0); + + for (MethodNode m: classNode.methods) + { + for (ListIterator it = m.instructions.iterator(); it.hasNext(); ) + { + AbstractInsnNode insnNode = it.next(); + if (insnNode.getType() == AbstractInsnNode.FIELD_INSN) + { + FieldInsnNode fi = (FieldInsnNode)insnNode; + if (FLUID_TYPE.equals(fi.owner) && LEGACY_FIELDNAME.equals(fi.name) && fi.getOpcode() == Opcodes.GETFIELD) + { + FMLLog.fine("Method %s.%s%s: Replacing GETFIELD fluidID with INVOKEVIRTUAL getFluidID", name, m.name, m.desc); + it.remove(); + MethodInsnNode replace = new MethodInsnNode(Opcodes.INVOKEVIRTUAL, FLUID_TYPE, GETID_NAME, GETID_DESC, false); + it.add(replace); + } + } + } + } + ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS); + classNode.accept(writer); + return writer.toByteArray(); + } + +} diff --git a/src/main/java/net/minecraftforge/common/ForgeVersion.java b/src/main/java/net/minecraftforge/common/ForgeVersion.java index 88ec7b55d..b8dacccf9 100644 --- a/src/main/java/net/minecraftforge/common/ForgeVersion.java +++ b/src/main/java/net/minecraftforge/common/ForgeVersion.java @@ -23,7 +23,7 @@ public class ForgeVersion //This number is incremented every minecraft release, never reset public static final int minorVersion = 13; //This number is incremented every time a interface changes or new major feature is added, and reset every Minecraft version - public static final int revisionVersion = 2; + public static final int revisionVersion = 3; //This number is incremented every time Jenkins builds Forge, and never reset. Should always be 0 in the repo code. public static final int buildVersion = 0; From defaddecec92b1027a0efd42461b5d95016d3031 Mon Sep 17 00:00:00 2001 From: cpw Date: Sun, 5 Apr 2015 16:13:17 -0400 Subject: [PATCH 05/48] Fix formatting --- .../minecraftforge/fluids/BlockFluidBase.java | 56 +++++++++---------- .../java/net/minecraftforge/fluids/Fluid.java | 12 ++-- .../fluids/FluidContainerRegistry.java | 32 +++++------ .../minecraftforge/fluids/FluidRegistry.java | 6 +- .../net/minecraftforge/fluids/FluidStack.java | 4 +- 5 files changed, 55 insertions(+), 55 deletions(-) diff --git a/src/main/java/net/minecraftforge/fluids/BlockFluidBase.java b/src/main/java/net/minecraftforge/fluids/BlockFluidBase.java index 2bda1e32b..7e36157b2 100644 --- a/src/main/java/net/minecraftforge/fluids/BlockFluidBase.java +++ b/src/main/java/net/minecraftforge/fluids/BlockFluidBase.java @@ -42,7 +42,7 @@ public abstract class BlockFluidBase extends Block implements IFluidBlock protected float quantaPerBlockFloat = 8F; protected int density = 1; protected int densityDir = -1; - protected int temperature = 300; + protected int temperature = 300; protected int tickRate = 20; protected int renderPass = 1; @@ -135,18 +135,18 @@ public abstract class BlockFluidBase extends Block implements IFluidBlock } int density = getDensity(world, x, y, z); - if (density == Integer.MAX_VALUE) + if (density == Integer.MAX_VALUE) { - return true; + return true; } - + if (this.density > density) { - return true; + return true; } else { - return false; + return false; } } @@ -183,19 +183,19 @@ public abstract class BlockFluidBase extends Block implements IFluidBlock } int density = getDensity(world, x, y, z); - if (density == Integer.MAX_VALUE) + if (density == Integer.MAX_VALUE) { - block.dropBlockAsItem(world, x, y, z, world.getBlockMetadata(x, y, z), 0); - return true; + block.dropBlockAsItem(world, x, y, z, world.getBlockMetadata(x, y, z), 0); + return true; } - + if (this.density > density) { - return true; + return true; } else { - return false; + return false; } } @@ -231,7 +231,7 @@ public abstract class BlockFluidBase extends Block implements IFluidBlock { return canDisplace(world, x, y, z); } - + @Override public boolean getBlocksMovement(IBlockAccess world, int x, int y, int z) { @@ -309,7 +309,7 @@ public abstract class BlockFluidBase extends Block implements IFluidBlock float lightUp = world.getLightBrightness(x, y + 1, z); return lightThis > lightUp ? lightThis : lightUp; } - */ + */ @Override public int getMixedBrightnessForBlock(IBlockAccess world, int x, int y, int z) @@ -321,7 +321,7 @@ public abstract class BlockFluidBase extends Block implements IFluidBlock int lightThisExt = lightThis >> 16 & 255; int lightUpExt = lightUp >> 16 & 255; return (lightThisBase > lightUpBase ? lightThisBase : lightUpBase) | - ((lightThisExt > lightUpExt ? lightThisExt : lightUpExt) << 16); + ((lightThisExt > lightUpExt ? lightThisExt : lightUpExt) << 16); } @Override @@ -351,7 +351,7 @@ public abstract class BlockFluidBase extends Block implements IFluidBlock } return ((BlockFluidBase)block).density; } - + public static final int getTemperature(IBlockAccess world, int x, int y, int z) { Block block = world.getBlock(x, y, z); @@ -411,10 +411,10 @@ public abstract class BlockFluidBase extends Block implements IFluidBlock switch (side) { - case 0: --x2; break; - case 1: --z2; break; - case 2: ++x2; break; - case 3: ++z2; break; + case 0: --x2; break; + case 1: --z2; break; + case 2: ++x2; break; + case 3: ++z2; break; } int otherDecay = quantaPerBlock - getQuantaValue(world, x2, y, z2); @@ -440,14 +440,14 @@ public abstract class BlockFluidBase extends Block implements IFluidBlock if (world.getBlock(x, y + 1, z) == this) { boolean flag = - isBlockSolid(world, x, y, z - 1, 2) || - isBlockSolid(world, x, y, z + 1, 3) || - isBlockSolid(world, x - 1, y, z, 4) || - isBlockSolid(world, x + 1, y, z, 5) || - isBlockSolid(world, x, y + 1, z - 1, 2) || - isBlockSolid(world, x, y + 1, z + 1, 3) || - isBlockSolid(world, x - 1, y + 1, z, 4) || - isBlockSolid(world, x + 1, y + 1, z, 5); + isBlockSolid(world, x, y, z - 1, 2) || + isBlockSolid(world, x, y, z + 1, 3) || + isBlockSolid(world, x - 1, y, z, 4) || + isBlockSolid(world, x + 1, y, z, 5) || + isBlockSolid(world, x, y + 1, z - 1, 2) || + isBlockSolid(world, x, y + 1, z + 1, 3) || + isBlockSolid(world, x - 1, y + 1, z, 4) || + isBlockSolid(world, x + 1, y + 1, z, 5); if (flag) { diff --git a/src/main/java/net/minecraftforge/fluids/Fluid.java b/src/main/java/net/minecraftforge/fluids/Fluid.java index 548e82e1e..28096dda8 100644 --- a/src/main/java/net/minecraftforge/fluids/Fluid.java +++ b/src/main/java/net/minecraftforge/fluids/Fluid.java @@ -33,7 +33,7 @@ import net.minecraft.item.EnumRarity; * */ public class Fluid -{ +{ /** The unique identification name for this fluid. */ protected final String fluidName; @@ -62,7 +62,7 @@ public class Fluid /** * Temperature of the fluid - completely arbitrary; higher temperature indicates that the fluid is * hotter than air. - * + * * Default value is approximately the real-life room temperature of water in degrees Kelvin. */ protected int temperature = 300; @@ -72,10 +72,10 @@ public class Fluid * permissible. * * Default value is approximately the real-life density of water in m/s^2 (x10^-3). - * + * * Higher viscosity means that a fluid flows more slowly, like molasses. * Lower viscosity means that a fluid flows more quickly, like helium. - * + * */ protected int viscosity = 1000; @@ -198,7 +198,7 @@ public class Fluid { return getLocalizedName(); } - + /** * Use the FluidStack sensitive version above */ @@ -258,7 +258,7 @@ public class Fluid { return this.isGaseous; } - + public EnumRarity getRarity() { return rarity; diff --git a/src/main/java/net/minecraftforge/fluids/FluidContainerRegistry.java b/src/main/java/net/minecraftforge/fluids/FluidContainerRegistry.java index 5ff13369e..33c47f24e 100644 --- a/src/main/java/net/minecraftforge/fluids/FluidContainerRegistry.java +++ b/src/main/java/net/minecraftforge/fluids/FluidContainerRegistry.java @@ -20,16 +20,16 @@ import net.minecraftforge.common.MinecraftForge; /** * Register simple items that contain fluids here. Useful for buckets, bottles, and things that have * ID/metadata mappings. - * + * * For more complex items, use {@link IFluidContainerItem} instead. - * + * * @author King Lemming - * + * */ public abstract class FluidContainerRegistry { - // Holder object that implements HashCode for an ItemStack, - // the local maps are not guaranteed to have the same internal generic structure, + // Holder object that implements HashCode for an ItemStack, + // the local maps are not guaranteed to have the same internal generic structure, // but the external interface for checking ItemStacks will still exist. private static class ContainerKey { @@ -89,7 +89,7 @@ public abstract class FluidContainerRegistry /** * Register a new fluid containing item. - * + * * @param stack * FluidStack containing the type and amount of the fluid stored in the item. * @param filledContainer @@ -106,7 +106,7 @@ public abstract class FluidContainerRegistry /** * Register a new fluid containing item. The item is assumed to hold 1000 mB of fluid. Also * registers the Fluid if possible. - * + * * @param fluid * Fluid type that is stored in the item. * @param filledContainer @@ -126,7 +126,7 @@ public abstract class FluidContainerRegistry /** * Register a new fluid containing item that does not have an empty container. - * + * * @param stack * FluidStack containing the type and amount of the fluid stored in the item. * @param filledContainer @@ -141,7 +141,7 @@ public abstract class FluidContainerRegistry /** * Register a new fluid containing item that does not have an empty container. The item is * assumed to hold 1000 mB of fluid. Also registers the Fluid if possible. - * + * * @param fluid * Fluid type that is stored in the item. * @param filledContainer @@ -159,7 +159,7 @@ public abstract class FluidContainerRegistry /** * Register a new fluid containing item. - * + * * @param data * See {@link FluidContainerData}. * @return True if container was successfully registered; false if it already is. @@ -184,7 +184,7 @@ public abstract class FluidContainerRegistry /** * Determines the fluid type and amount inside a container. - * + * * @param container * The fluid container. * @return FluidStack representing stored fluid. @@ -202,9 +202,9 @@ public abstract class FluidContainerRegistry /** * Attempts to fill an empty container with a fluid. - * + * * NOTE: Returns null on fail, NOT the empty container. - * + * * @param fluid * FluidStack containing the type and amount of fluid to fill. * @param container @@ -228,7 +228,7 @@ public abstract class FluidContainerRegistry /** * Attempts to empty a full container. - * + * * @param container * ItemStack representing the full container. * @return Empty container if successful, otherwise null. @@ -251,7 +251,7 @@ public abstract class FluidContainerRegistry /** * Determines the capacity of a full container. - * + * * @param container * The full container. * @return The containers capacity, or 0 if the ItemStack does not represent @@ -264,7 +264,7 @@ public abstract class FluidContainerRegistry /** * Determines the capacity of a container. - * + * * @param fluid * FluidStack containing the type of fluid the capacity should be * determined for (ignored for full containers). diff --git a/src/main/java/net/minecraftforge/fluids/FluidRegistry.java b/src/main/java/net/minecraftforge/fluids/FluidRegistry.java index 89476afe7..bff900767 100644 --- a/src/main/java/net/minecraftforge/fluids/FluidRegistry.java +++ b/src/main/java/net/minecraftforge/fluids/FluidRegistry.java @@ -28,14 +28,14 @@ public abstract class FluidRegistry static BiMap fluids = HashBiMap.create(); static BiMap fluidIDs = HashBiMap.create(); static BiMap fluidBlocks; - + public static final Fluid WATER = new Fluid("water") { @Override public String getLocalizedName() { return StatCollector.translateToLocal("tile.water.name"); } }.setBlock(Blocks.water).setUnlocalizedName(Blocks.water.getUnlocalizedName()); - + public static final Fluid LAVA = new Fluid("lava") { @Override public String getLocalizedName() { @@ -165,7 +165,7 @@ public abstract class FluidRegistry } return fluidBlocks.get(block); } - + public static class FluidRegisterEvent extends Event { public final String fluidName; diff --git a/src/main/java/net/minecraftforge/fluids/FluidStack.java b/src/main/java/net/minecraftforge/fluids/FluidStack.java index f23bb0b9e..16e386863 100644 --- a/src/main/java/net/minecraftforge/fluids/FluidStack.java +++ b/src/main/java/net/minecraftforge/fluids/FluidStack.java @@ -56,7 +56,7 @@ public class FluidStack { this(FluidRegistry.getFluid(fluidID), amount, nbt); } - + /** * This provides a safe method for retrieving a FluidStack - if the Fluid is invalid, the stack * will return as null. @@ -103,7 +103,7 @@ public class FluidStack { return FluidRegistry.getFluidID(fluid); } - + public String getLocalizedName() { return this.getFluid().getLocalizedName(this); From f7395f517b9af06ec042f234f8f1f6b0665f8c6a Mon Sep 17 00:00:00 2001 From: King Lemming Date: Sun, 5 Apr 2015 19:39:15 -0400 Subject: [PATCH 06/48] Allow for duplicate Fluid Blocks. It's annoying to be sure but just as with the OreDictionary, we'll have to handle it. Signed-off-by: King Lemming --- .../net/minecraftforge/common/ForgeModContainer.java | 12 ------------ src/main/java/net/minecraftforge/fluids/Fluid.java | 11 ++--------- 2 files changed, 2 insertions(+), 21 deletions(-) diff --git a/src/main/java/net/minecraftforge/common/ForgeModContainer.java b/src/main/java/net/minecraftforge/common/ForgeModContainer.java index 40ed8b2e6..fe9459c1c 100644 --- a/src/main/java/net/minecraftforge/common/ForgeModContainer.java +++ b/src/main/java/net/minecraftforge/common/ForgeModContainer.java @@ -60,7 +60,6 @@ public class ForgeModContainer extends DummyModContainer implements WorldAccessC public static boolean removeErroringEntities = false; public static boolean removeErroringTileEntities = false; public static boolean disableStitchedFileSaving = false; - public static boolean forceDuplicateFluidBlockCrash = true; public static boolean fullBoundingBoxLadders = false; public static double zombieSummonBaseChance = 0.1; public static int[] blendRanges = { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34 }; @@ -158,17 +157,6 @@ public class ForgeModContainer extends DummyModContainer implements WorldAccessC shouldSortRecipies = prop.getBoolean(shouldSortRecipies); propOrder.add(prop.getName()); - prop = config.get(Configuration.CATEGORY_GENERAL, "forceDuplicateFluidBlockCrash", true); - prop.comment = "Set this to true to force a crash if more than one block attempts to link back to the same Fluid. Enabled by default."; - prop.setLanguageKey("forge.configgui.forceDuplicateFluidBlockCrash").setRequiresMcRestart(true); - forceDuplicateFluidBlockCrash = prop.getBoolean(true); - propOrder.add(prop.getName()); - - if (!forceDuplicateFluidBlockCrash) - { - FMLLog.warning("Disabling forced crashes on duplicate Fluid Blocks - USE AT YOUR OWN RISK"); - } - prop = config.get(Configuration.CATEGORY_GENERAL, "removeErroringEntities", false); prop.comment = "Set this to true to remove any Entity that throws an error in its update method instead of closing the server and reporting a crash log. BE WARNED THIS COULD SCREW UP EVERYTHING USE SPARINGLY WE ARE NOT RESPONSIBLE FOR DAMAGES."; prop.setLanguageKey("forge.configgui.removeErroringEntities").setRequiresWorldRestart(true); diff --git a/src/main/java/net/minecraftforge/fluids/Fluid.java b/src/main/java/net/minecraftforge/fluids/Fluid.java index 28096dda8..fed6e8866 100644 --- a/src/main/java/net/minecraftforge/fluids/Fluid.java +++ b/src/main/java/net/minecraftforge/fluids/Fluid.java @@ -120,17 +120,10 @@ public class Fluid { this.block = block; } - else if (!ForgeModContainer.forceDuplicateFluidBlockCrash) - { - FMLLog.warning("A mod has attempted to assign Block " + block + " to the Fluid '" + fluidName + "' but this Fluid has already been linked to BlockID " - + this.block + ". Configure your mods to prevent this from happening."); - } else { - FMLLog.severe("A mod has attempted to assign BlockID " + block + " to the Fluid '" + fluidName + "' but this Fluid has already been linked to BlockID " - + this.block + ". Configure your mods to prevent this from happening."); - throw new LoaderException(new RuntimeException("A mod has attempted to assign BlockID " + block + " to the Fluid '" + fluidName - + "' but this Fluid has already been linked to BlockID " + this.block + ". Configure your mods to prevent this from happening.")); + FMLLog.warning("A mod has attempted to assign Block " + block + " to the Fluid '" + fluidName + "' but this Fluid has already been linked to the Block " + + this.block + ". You may have duplicate Fluid Blocks as a result. It *may* be possible to configure your mods to avoid this."); } return this; } From 4f0e2fb9c4359ecdcffea30e673d026dfa97ba14 Mon Sep 17 00:00:00 2001 From: cpw Date: Sun, 5 Apr 2015 22:37:40 -0400 Subject: [PATCH 07/48] You shouldn't be creating FluidStacks from unregistered Fluids. Warn clearly on failed registrations, and make a useful log message for failed fluidstack creations. Should help a lot with tracking down broken mods that are doing this wrongly. --- .../java/net/minecraftforge/fluids/FluidRegistry.java | 2 ++ src/main/java/net/minecraftforge/fluids/FluidStack.java | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/src/main/java/net/minecraftforge/fluids/FluidRegistry.java b/src/main/java/net/minecraftforge/fluids/FluidRegistry.java index bff900767..866f0dbf6 100644 --- a/src/main/java/net/minecraftforge/fluids/FluidRegistry.java +++ b/src/main/java/net/minecraftforge/fluids/FluidRegistry.java @@ -13,6 +13,7 @@ import com.google.common.collect.HashBiMap; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; +import cpw.mods.fml.common.FMLLog; import cpw.mods.fml.common.eventhandler.Event; /** @@ -75,6 +76,7 @@ public abstract class FluidRegistry { if (fluidIDs.containsKey(fluid.getName())) { + FMLLog.bigWarning("Duplicate registration attempt for fluid %s (type %s) has occurred. This is not a problem itself, but subsequent failed FluidStacks might be a result if not handled properly", fluid.getName(), fluid.getClass().getName()); return false; } fluids.put(fluid.getName(), fluid); diff --git a/src/main/java/net/minecraftforge/fluids/FluidStack.java b/src/main/java/net/minecraftforge/fluids/FluidStack.java index 16e386863..b485170e9 100644 --- a/src/main/java/net/minecraftforge/fluids/FluidStack.java +++ b/src/main/java/net/minecraftforge/fluids/FluidStack.java @@ -2,7 +2,10 @@ package net.minecraftforge.fluids; import java.util.Locale; + import com.google.common.base.Strings; + +import cpw.mods.fml.common.FMLLog; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; @@ -24,6 +27,11 @@ public class FluidStack public FluidStack(Fluid fluid, int amount) { + if (!FluidRegistry.isFluidRegistered(fluid)) + { + FMLLog.bigWarning("Failed attempt to create a FluidStack for an unregistered Fluid %s (type %s)", fluid.getName(), fluid.getClass().getName()); + throw new IllegalArgumentException("Cannot create a fluidstack from an unregistered fluid"); + } this.fluid = fluid; this.amount = amount; } From 1fd39578b077ce40797340bd22e0c05c4a8122e3 Mon Sep 17 00:00:00 2001 From: Lex Manos Date: Tue, 7 Apr 2015 20:06:01 -0700 Subject: [PATCH 08/48] MinecraftForge/FML@31cf2a9cab6d1977d31436220d9612eaa13d4e0f Remove J7 only constructor in EnhancedRuntimeException, J6 compiling compatibility restored. --- fml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fml b/fml index 94c45b48c..31cf2a9ca 160000 --- a/fml +++ b/fml @@ -1 +1 @@ -Subproject commit 94c45b48c1265e7c4f60f591d413fa545787d354 +Subproject commit 31cf2a9cab6d1977d31436220d9612eaa13d4e0f From 02ebc9ca2184f1862b5f45ede7dcb1dd91bb1e86 Mon Sep 17 00:00:00 2001 From: Lex Manos Date: Tue, 7 Apr 2015 20:06:55 -0700 Subject: [PATCH 09/48] Restore binary compatibility issues in FluidRegistry caused by recent changes. --- .../common/network/ForgeMessage.java | 6 ++--- .../minecraftforge/fluids/FluidRegistry.java | 26 +++++++++++++++++-- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/main/java/net/minecraftforge/common/network/ForgeMessage.java b/src/main/java/net/minecraftforge/common/network/ForgeMessage.java index 6ba6ccd5f..17f6ff0c4 100644 --- a/src/main/java/net/minecraftforge/common/network/ForgeMessage.java +++ b/src/main/java/net/minecraftforge/common/network/ForgeMessage.java @@ -14,14 +14,14 @@ public abstract class ForgeMessage { int dimensionId; /** The provider ID to register with dimension on client */ int providerId; - + public DimensionRegisterMessage(){} public DimensionRegisterMessage(int dimensionId, int providerId) { this.dimensionId = dimensionId; this.providerId = providerId; } - + @Override void toBytes(ByteBuf bytes) { @@ -42,7 +42,7 @@ public abstract class ForgeMessage { @Override void toBytes(ByteBuf bytes) { - Map ids = FluidRegistry.getRegisteredFluidIDs(); + Map ids = FluidRegistry.getRegisteredFluidIDsByFluid(); bytes.writeInt(ids.size()); for (Map.Entry entry : ids.entrySet()) { diff --git a/src/main/java/net/minecraftforge/fluids/FluidRegistry.java b/src/main/java/net/minecraftforge/fluids/FluidRegistry.java index 866f0dbf6..30d777494 100644 --- a/src/main/java/net/minecraftforge/fluids/FluidRegistry.java +++ b/src/main/java/net/minecraftforge/fluids/FluidRegistry.java @@ -2,6 +2,7 @@ package net.minecraftforge.fluids; import java.util.HashMap; import java.util.Map; +import java.util.Map.Entry; import net.minecraft.block.Block; import net.minecraft.init.Blocks; @@ -28,6 +29,7 @@ public abstract class FluidRegistry static BiMap fluids = HashBiMap.create(); static BiMap fluidIDs = HashBiMap.create(); + static BiMap fluidNames = HashBiMap.create(); //Caching this just makes some other calls faster static BiMap fluidBlocks; public static final Fluid WATER = new Fluid("water") { @@ -63,6 +65,9 @@ public abstract class FluidRegistry maxID = newfluidIDs.size(); fluidIDs.clear(); fluidIDs.putAll(newfluidIDs); + fluidNames.clear(); + for (Entry e : fluidIDs.entrySet()) + fluidNames.put(e.getValue(), e.getKey().getName()); } /** @@ -81,6 +86,7 @@ public abstract class FluidRegistry } fluids.put(fluid.getName(), fluid); fluidIDs.put(fluid, ++maxID); + fluidNames.put(maxID, fluid.getName()); MinecraftForge.EVENT_BUS.post(new FluidRegisterEvent(fluid.getName(), maxID)); return true; @@ -116,6 +122,12 @@ public abstract class FluidRegistry return fluidIDs.get(getFluid(fluidName)); } + @Deprecated //Remove in 1.8.3 + public static String getFluidName(int fluidID) + { + return fluidNames.get(fluidID); + } + public static String getFluidName(Fluid fluid) { return fluids.inverse().get(fluid); @@ -144,9 +156,19 @@ public abstract class FluidRegistry } /** - * Returns a read-only map containing Fluid IDs and their associated Fluids. + * Returns a read-only map containing Fluid Names and their associated IDs. */ - public static Map getRegisteredFluidIDs() + @Deprecated //Change return type to in 1.8.3 + public static Map getRegisteredFluidIDs() + { + return ImmutableMap.copyOf(fluidNames.inverse()); + } + + /** + * Returns a read-only map containing Fluid IDs and their associated Fluids. + * In 1.8.3, this will change to just 'getRegisteredFluidIDs' + */ + public static Map getRegisteredFluidIDsByFluid() { return ImmutableMap.copyOf(fluidIDs); } From a42cf1ae37cc61f2f97feb800cc1f3aaa323a5ec Mon Sep 17 00:00:00 2001 From: Sergey Shatunov Date: Wed, 8 Apr 2015 17:26:40 +0600 Subject: [PATCH 10/48] Fix FluidRegsitry.registerFluid FluidRegistry: ```java static BiMap fluids = HashBiMap.create(); static BiMap fluidIDs = HashBiMap.create(); ... public static boolean registerFluid(Fluid fluid) { if (fluidIDs.containsKey(fluid.getName())) ^^^^^^^ ``` There is definitely should be fluids instead fluidIDs. This mistake broke many mods. --- src/main/java/net/minecraftforge/fluids/FluidRegistry.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/minecraftforge/fluids/FluidRegistry.java b/src/main/java/net/minecraftforge/fluids/FluidRegistry.java index 30d777494..cd9ef9292 100644 --- a/src/main/java/net/minecraftforge/fluids/FluidRegistry.java +++ b/src/main/java/net/minecraftforge/fluids/FluidRegistry.java @@ -79,7 +79,7 @@ public abstract class FluidRegistry */ public static boolean registerFluid(Fluid fluid) { - if (fluidIDs.containsKey(fluid.getName())) + if (fluids.containsKey(fluid.getName())) { FMLLog.bigWarning("Duplicate registration attempt for fluid %s (type %s) has occurred. This is not a problem itself, but subsequent failed FluidStacks might be a result if not handled properly", fluid.getName(), fluid.getClass().getName()); return false; From 433b7ca5894d60762cbee52cd1bd42af3007879e Mon Sep 17 00:00:00 2001 From: King Lemming Date: Thu, 9 Apr 2015 17:28:20 -0400 Subject: [PATCH 11/48] Fixes #1782 Signed-off-by: King Lemming --- .../java/net/minecraftforge/fluids/FluidContainerRegistry.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/minecraftforge/fluids/FluidContainerRegistry.java b/src/main/java/net/minecraftforge/fluids/FluidContainerRegistry.java index 33c47f24e..552d6eea0 100644 --- a/src/main/java/net/minecraftforge/fluids/FluidContainerRegistry.java +++ b/src/main/java/net/minecraftforge/fluids/FluidContainerRegistry.java @@ -51,7 +51,7 @@ public abstract class FluidContainerRegistry code = 31*code + container.getItem().hashCode(); code = 31*code + container.getItemDamage(); if (stack != null) - code = 31*code + stack.hashCode(); + code = 31*code + stack.getFluidID(); return code; } @Override From 186f92479d2d43ee6e92113d94dd8ab768140494 Mon Sep 17 00:00:00 2001 From: King Lemming Date: Fri, 10 Apr 2015 16:38:45 -0400 Subject: [PATCH 12/48] Fixes FluidContainerRegistry properly - no more corner case where client/server mods disagree. Also clarifies the 2x Fluid registration error message somewhat. Signed-off-by: King Lemming --- .../net/minecraftforge/fluids/FluidContainerRegistry.java | 2 +- src/main/java/net/minecraftforge/fluids/FluidRegistry.java | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/net/minecraftforge/fluids/FluidContainerRegistry.java b/src/main/java/net/minecraftforge/fluids/FluidContainerRegistry.java index 552d6eea0..9702c28bf 100644 --- a/src/main/java/net/minecraftforge/fluids/FluidContainerRegistry.java +++ b/src/main/java/net/minecraftforge/fluids/FluidContainerRegistry.java @@ -51,7 +51,7 @@ public abstract class FluidContainerRegistry code = 31*code + container.getItem().hashCode(); code = 31*code + container.getItemDamage(); if (stack != null) - code = 31*code + stack.getFluidID(); + code = 31*code + stack.fluid.hashCode(); return code; } @Override diff --git a/src/main/java/net/minecraftforge/fluids/FluidRegistry.java b/src/main/java/net/minecraftforge/fluids/FluidRegistry.java index cd9ef9292..83f8565ae 100644 --- a/src/main/java/net/minecraftforge/fluids/FluidRegistry.java +++ b/src/main/java/net/minecraftforge/fluids/FluidRegistry.java @@ -81,11 +81,12 @@ public abstract class FluidRegistry { if (fluids.containsKey(fluid.getName())) { - FMLLog.bigWarning("Duplicate registration attempt for fluid %s (type %s) has occurred. This is not a problem itself, but subsequent failed FluidStacks might be a result if not handled properly", fluid.getName(), fluid.getClass().getName()); + FMLLog.bigWarning("Duplicate registration attempt for fluid %s (type %s) has occurred. This is not a problem itself, but subsequent failed FluidStacks result if this is not handled properly", fluid.getName(), fluid.getClass().getName()); return false; } fluids.put(fluid.getName(), fluid); - fluidIDs.put(fluid, ++maxID); + maxID++; + fluidIDs.put(fluid, maxID); fluidNames.put(maxID, fluid.getName()); MinecraftForge.EVENT_BUS.post(new FluidRegisterEvent(fluid.getName(), maxID)); From 37d63b3fe95718aafe8f9fcd8fd2f6952c3525c3 Mon Sep 17 00:00:00 2001 From: King Lemming Date: Fri, 10 Apr 2015 20:09:58 -0400 Subject: [PATCH 13/48] Adds a warning to the FluidContainerRegistry when a mod does something stupid! Also denies the registration. Signed-off-by: King Lemming --- .../fluids/FluidContainerRegistry.java | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/main/java/net/minecraftforge/fluids/FluidContainerRegistry.java b/src/main/java/net/minecraftforge/fluids/FluidContainerRegistry.java index 9702c28bf..7d6a963e1 100644 --- a/src/main/java/net/minecraftforge/fluids/FluidContainerRegistry.java +++ b/src/main/java/net/minecraftforge/fluids/FluidContainerRegistry.java @@ -7,10 +7,9 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; - import com.google.common.collect.Maps; import com.google.common.collect.Sets; - +import cpw.mods.fml.common.FMLLog; import cpw.mods.fml.common.eventhandler.Event; import net.minecraft.init.Items; import net.minecraft.item.Item; @@ -113,7 +112,7 @@ public abstract class FluidContainerRegistry * ItemStack representing the container when it is full. * @param emptyContainer * ItemStack representing the container when it is empty. - * @return True if container was successfully registered; false if it already is. + * @return True if container was successfully registered; false if it already is, or an invalid parameter was passed. */ public static boolean registerFluidContainer(Fluid fluid, ItemStack filledContainer, ItemStack emptyContainer) { @@ -131,7 +130,7 @@ public abstract class FluidContainerRegistry * FluidStack containing the type and amount of the fluid stored in the item. * @param filledContainer * ItemStack representing the container when it is full. - * @return True if container was successfully registered; false if it already is. + * @return True if container was successfully registered; false if it already is, or an invalid parameter was passed. */ public static boolean registerFluidContainer(FluidStack stack, ItemStack filledContainer) { @@ -146,7 +145,7 @@ public abstract class FluidContainerRegistry * Fluid type that is stored in the item. * @param filledContainer * ItemStack representing the container when it is full. - * @return True if container was successfully registered; false if it already is. + * @return True if container was successfully registered; false if it already is, or an invalid parameter was passed. */ public static boolean registerFluidContainer(Fluid fluid, ItemStack filledContainer) { @@ -162,14 +161,19 @@ public abstract class FluidContainerRegistry * * @param data * See {@link FluidContainerData}. - * @return True if container was successfully registered; false if it already is. + * @return True if container was successfully registered; false if it already is, or an invalid parameter was passed. */ public static boolean registerFluidContainer(FluidContainerData data) { - if (isFilledContainer(data.filledContainer)) + if (isFilledContainer(data.filledContainer) || data.filledContainer == null) { return false; } + if (data.fluid == null || data.fluid.getFluid() == null) + { + FMLLog.bigWarning("Invalid registration attempt for a fluid container item %s (type %s) has occurred. The registration has been denied to prevent crashes. The mod responsible for the registration needs to correct this.", data.filledContainer.getItem().getUnlocalizedName(data.filledContainer)); + return false; + } containerFluidMap.put(new ContainerKey(data.filledContainer), data); if (data.emptyContainer != null && data.emptyContainer != NULL_EMPTYCONTAINER) From 6049d371f3404ffd8134768d89fad4e396988072 Mon Sep 17 00:00:00 2001 From: cpw Date: Fri, 10 Apr 2015 22:46:53 -0400 Subject: [PATCH 14/48] MinecraftForge/FML@ce791cb1f2cf983ef77b1e5c4028ddefab394062 Rework EventSubscriptionTransformer to bake @Cancelable and @HasResult values, should increase EventBus performance even more by removing logic from Event constructors. MinecraftForge/FML@852710962a9b6d7c8e2ca188c715eebb2da44c2a Clean up some dead code --- fml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fml b/fml index 31cf2a9ca..852710962 160000 --- a/fml +++ b/fml @@ -1 +1 @@ -Subproject commit 31cf2a9cab6d1977d31436220d9612eaa13d4e0f +Subproject commit 852710962a9b6d7c8e2ca188c715eebb2da44c2a From 345d90543896c6579492136e1fe90b3b63317eb1 Mon Sep 17 00:00:00 2001 From: cpw Date: Sat, 11 Apr 2015 01:03:50 -0400 Subject: [PATCH 15/48] MinecraftForge/FML@be5ec06e3144d55a03d125f3ce364eade3771f4f Cleaning up the missing resource stack spam, and condensing the information into a usefully understandable format. --- fml | 2 +- .../minecraft/client/renderer/texture/TextureMap.java.patch | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/fml b/fml index 852710962..be5ec06e3 160000 --- a/fml +++ b/fml @@ -1 +1 @@ -Subproject commit 852710962a9b6d7c8e2ca188c715eebb2da44c2a +Subproject commit be5ec06e3144d55a03d125f3ce364eade3771f4f diff --git a/patches/minecraft/net/minecraft/client/renderer/texture/TextureMap.java.patch b/patches/minecraft/net/minecraft/client/renderer/texture/TextureMap.java.patch index a320f4a8b..9041d5073 100644 --- a/patches/minecraft/net/minecraft/client/renderer/texture/TextureMap.java.patch +++ b/patches/minecraft/net/minecraft/client/renderer/texture/TextureMap.java.patch @@ -40,7 +40,7 @@ try { IResource iresource = p_110571_1_.func_110536_a(resourcelocation1); -@@ -274,6 +288,7 @@ +@@ -275,6 +289,7 @@ textureatlassprite = (TextureAtlasSprite)iterator2.next(); textureatlassprite.func_94217_a(this.field_94249_f); } @@ -48,7 +48,7 @@ } private ResourceLocation func_147634_a(ResourceLocation p_147634_1_, int p_147634_2_) -@@ -347,7 +362,7 @@ +@@ -348,7 +363,7 @@ { throw new IllegalArgumentException("Name cannot be null!"); } @@ -57,7 +57,7 @@ { Object object = (TextureAtlasSprite)this.field_110574_e.get(p_94245_1_); -@@ -403,4 +418,37 @@ +@@ -404,4 +419,37 @@ { this.field_147637_k = p_147632_1_; } From eb12936a52fa1b407281d6ec6db76061312bbd43 Mon Sep 17 00:00:00 2001 From: cpw Date: Sat, 11 Apr 2015 12:30:20 -0400 Subject: [PATCH 16/48] MinecraftForge/FML@0da1263ff9ede99267c03728a1c823b8056d5e44 Enhance error output for bad textures a bit more and try and capture more types of error.. --- fml | 2 +- .../minecraft/client/renderer/texture/TextureMap.java.patch | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/fml b/fml index be5ec06e3..0da1263ff 160000 --- a/fml +++ b/fml @@ -1 +1 @@ -Subproject commit be5ec06e3144d55a03d125f3ce364eade3771f4f +Subproject commit 0da1263ff9ede99267c03728a1c823b8056d5e44 diff --git a/patches/minecraft/net/minecraft/client/renderer/texture/TextureMap.java.patch b/patches/minecraft/net/minecraft/client/renderer/texture/TextureMap.java.patch index 9041d5073..cac9df558 100644 --- a/patches/minecraft/net/minecraft/client/renderer/texture/TextureMap.java.patch +++ b/patches/minecraft/net/minecraft/client/renderer/texture/TextureMap.java.patch @@ -40,7 +40,7 @@ try { IResource iresource = p_110571_1_.func_110536_a(resourcelocation1); -@@ -275,6 +289,7 @@ +@@ -276,6 +290,7 @@ textureatlassprite = (TextureAtlasSprite)iterator2.next(); textureatlassprite.func_94217_a(this.field_94249_f); } @@ -48,7 +48,7 @@ } private ResourceLocation func_147634_a(ResourceLocation p_147634_1_, int p_147634_2_) -@@ -348,7 +363,7 @@ +@@ -349,7 +364,7 @@ { throw new IllegalArgumentException("Name cannot be null!"); } @@ -57,7 +57,7 @@ { Object object = (TextureAtlasSprite)this.field_110574_e.get(p_94245_1_); -@@ -404,4 +419,37 @@ +@@ -405,4 +420,37 @@ { this.field_147637_k = p_147632_1_; } From 96711794536a42626a504635f3a4bd1fb82f72ed Mon Sep 17 00:00:00 2001 From: cpw Date: Sat, 11 Apr 2015 17:18:53 -0400 Subject: [PATCH 17/48] Fluids are now tracked internally by mod. This allows for the server and the world to specify a "default" in the case of a possible alternative fluid implementation. If you always called registerFluid, things should work pretty seamlessly, but if you didn't (gating with an isFluidRegistered check for example) you should change to register anyway. This way, even if you're not default in the overall instance, you may become default if you're the only mod present on a server, for example, or in a world save. This should radically decrease the mixups caused by mod load ordering problems, and other issues around fluid tracking. --- .../common/ForgeModContainer.java | 3 + .../FluidIdRegistryMessageHandler.java | 2 +- .../common/network/ForgeMessage.java | 28 ++++ .../minecraftforge/fluids/FluidRegistry.java | 120 +++++++++++++++++- .../net/minecraftforge/fluids/FluidStack.java | 4 - 5 files changed, 145 insertions(+), 12 deletions(-) diff --git a/src/main/java/net/minecraftforge/common/ForgeModContainer.java b/src/main/java/net/minecraftforge/common/ForgeModContainer.java index fe9459c1c..366ad2be7 100644 --- a/src/main/java/net/minecraftforge/common/ForgeModContainer.java +++ b/src/main/java/net/minecraftforge/common/ForgeModContainer.java @@ -26,6 +26,7 @@ import net.minecraftforge.classloading.FMLForgePlugin; import net.minecraftforge.common.config.Configuration; import net.minecraftforge.common.config.Property; import net.minecraftforge.common.network.ForgeNetworkHandler; +import net.minecraftforge.fluids.FluidRegistry; import net.minecraftforge.oredict.OreDictionary; import net.minecraftforge.oredict.RecipeSorter; import net.minecraftforge.server.command.ForgeCommand; @@ -309,6 +310,7 @@ public class ForgeModContainer extends DummyModContainer implements WorldAccessC NBTTagCompound forgeData = new NBTTagCompound(); NBTTagCompound dimData = DimensionManager.saveDimensionDataMap(); forgeData.setTag("DimensionData", dimData); + FluidRegistry.writeDefaultFluidList(forgeData); return forgeData; } @@ -316,6 +318,7 @@ public class ForgeModContainer extends DummyModContainer implements WorldAccessC public void readData(SaveHandler handler, WorldInfo info, Map propertyMap, NBTTagCompound tag) { DimensionManager.loadDimensionDataMap(tag.hasKey("DimensionData") ? tag.getCompoundTag("DimensionData") : null); + FluidRegistry.loadFluidDefaults(tag); } @Subscribe diff --git a/src/main/java/net/minecraftforge/common/network/FluidIdRegistryMessageHandler.java b/src/main/java/net/minecraftforge/common/network/FluidIdRegistryMessageHandler.java index 032ff758e..dbb39244d 100644 --- a/src/main/java/net/minecraftforge/common/network/FluidIdRegistryMessageHandler.java +++ b/src/main/java/net/minecraftforge/common/network/FluidIdRegistryMessageHandler.java @@ -12,7 +12,7 @@ public class FluidIdRegistryMessageHandler extends SimpleChannelInboundHandler fluidIds = HashBiMap.create(); + Set defaultFluids = Sets.newHashSet(); @Override void toBytes(ByteBuf bytes) { @@ -49,6 +58,11 @@ public abstract class ForgeMessage { ByteBufUtils.writeUTF8String(bytes,entry.getKey().getName()); bytes.writeInt(entry.getValue()); } + for (Map.Entry entry : ids.entrySet()) + { + String defaultName = FluidRegistry.getDefaultFluidName(entry.getKey()); + ByteBufUtils.writeUTF8String(bytes, defaultName); + } } @Override @@ -60,6 +74,20 @@ public abstract class ForgeMessage { int fluidId = bytes.readInt(); fluidIds.put(FluidRegistry.getFluid(fluidName), fluidId); } + // do we have a defaults list? + + if (bytes.isReadable()) + { + for (int i = 0; i < listSize; i++) + { + defaultFluids.add(ByteBufUtils.readUTF8String(bytes)); + } + } + else + { + FMLLog.getLogger().log(Level.INFO, "Legacy server message contains no default fluid list - there may be problems with fluids"); + defaultFluids.clear(); + } } } diff --git a/src/main/java/net/minecraftforge/fluids/FluidRegistry.java b/src/main/java/net/minecraftforge/fluids/FluidRegistry.java index 83f8565ae..cb25e471b 100644 --- a/src/main/java/net/minecraftforge/fluids/FluidRegistry.java +++ b/src/main/java/net/minecraftforge/fluids/FluidRegistry.java @@ -1,21 +1,29 @@ package net.minecraftforge.fluids; -import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; +import java.util.Set; + +import org.apache.logging.log4j.Level; import net.minecraft.block.Block; import net.minecraft.init.Blocks; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.nbt.NBTTagString; import net.minecraft.util.StatCollector; import net.minecraftforge.common.MinecraftForge; import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Maps; +import com.google.common.collect.Sets; import cpw.mods.fml.common.FMLLog; +import cpw.mods.fml.common.Loader; +import cpw.mods.fml.common.ModContainer; import cpw.mods.fml.common.eventhandler.Event; +import cpw.mods.fml.common.network.ByteBufUtils; /** * Handles Fluid registrations. Fluids MUST be registered in order to function. @@ -32,6 +40,10 @@ public abstract class FluidRegistry static BiMap fluidNames = HashBiMap.create(); //Caching this just makes some other calls faster static BiMap fluidBlocks; + // the globally unique fluid map - only used to associate non-defaults during world/server loading + static BiMap masterFluidReference = HashBiMap.create(); + static BiMap defaultFluidName = HashBiMap.create(); + public static final Fluid WATER = new Fluid("water") { @Override public String getLocalizedName() { @@ -60,39 +72,97 @@ public abstract class FluidRegistry * Called by Forge to prepare the ID map for server -> client sync. * Modders, DO NOT call this. */ - public static void initFluidIDs(BiMap newfluidIDs) + public static void initFluidIDs(BiMap newfluidIDs, Set defaultNames) { maxID = newfluidIDs.size(); fluidIDs.clear(); fluidIDs.putAll(newfluidIDs); fluidNames.clear(); - for (Entry e : fluidIDs.entrySet()) + for (Entry e : fluidIDs.entrySet()) { fluidNames.put(e.getValue(), e.getKey().getName()); + } + loadFluidDefaults(defaultNames); } /** - * Register a new Fluid. If a fluid with the same name already exists, registration is denied. + * Called by forge to load default fluid IDs from the world or from server -> client for syncing + * DO NOT call this and expect useful behaviour. + */ + private static void loadFluidDefaults(Set defaultNames) + { + // If there's an empty set of default names, use the defaults as defined locally + if (defaultNames.isEmpty()) { + defaultNames.addAll(defaultFluidName.values()); + } + for (String defaultName : defaultNames) + { + Fluid fluid = masterFluidReference.get(defaultName); + if (fluid == null) { + String derivedName = defaultName.split(":",2)[1]; + String localDefault = defaultFluidName.get(derivedName); + if (localDefault == null) { + FMLLog.getLogger().log(Level.ERROR, "The fluid {} (specified as {}) is missing from this instance - it will be removed", derivedName, defaultName); + continue; + } + fluid = masterFluidReference.get(localDefault); + FMLLog.getLogger().log(Level.ERROR, "The fluid {} specified as default is not present - it will be reverted to default {}", defaultName, localDefault); + } + FMLLog.getLogger().log(Level.DEBUG, "The fluid {} has been selected as the default fluid for {}", defaultName, fluid.getName()); + fluids.put(fluid.getName(), fluid); + Integer id = fluidIDs.remove(fluid); + fluidIDs.put(fluid, id); + } + fluidBlocks = null; + } + + /** + * Register a new Fluid. If a fluid with the same name already exists, registration the alternative fluid is tracked + * in case it is the default in another place * * @param fluid * The fluid to register. - * @return True if the fluid was successfully registered; false if there is a name clash. + * @return True if the fluid was registered as the current default fluid, false if it was only registered as an alternative */ public static boolean registerFluid(Fluid fluid) { + masterFluidReference.put(uniqueName(fluid), fluid); + if (fluids.containsKey(fluid.getName())) { - FMLLog.bigWarning("Duplicate registration attempt for fluid %s (type %s) has occurred. This is not a problem itself, but subsequent failed FluidStacks result if this is not handled properly", fluid.getName(), fluid.getClass().getName()); return false; } fluids.put(fluid.getName(), fluid); maxID++; fluidIDs.put(fluid, maxID); fluidNames.put(maxID, fluid.getName()); + defaultFluidName.put(fluid.getName(), uniqueName(fluid)); MinecraftForge.EVENT_BUS.post(new FluidRegisterEvent(fluid.getName(), maxID)); return true; } + private static String uniqueName(Fluid fluid) + { + ModContainer activeModContainer = Loader.instance().activeModContainer(); + String activeModContainerName = activeModContainer == null ? "minecraft" : activeModContainer.getModId(); + return activeModContainerName+":"+fluid.getName(); + } + + /** + * Is the supplied fluid the current default fluid for it's name + * @param fluid the fluid we're testing + * @return if the fluid is default + */ + public static boolean isFluidDefault(Fluid fluid) + { + return fluids.containsValue(fluid); + } + + /** + * Does the supplied fluid have an entry for it's name (whether or not the fluid itself is default) + * @param fluid the fluid we're testing + * @return if the fluid's name has a registration entry + */ public static boolean isFluidRegistered(Fluid fluid) { return fluids.containsKey(fluid.getName()); @@ -207,4 +277,40 @@ public abstract class FluidRegistry { return maxID; } + + public static String getDefaultFluidName(Fluid key) + { + return masterFluidReference.inverse().get(key); + } + + public static void loadFluidDefaults(NBTTagCompound tag) + { + Set defaults = Sets.newHashSet(); + if (tag.hasKey("DefaultFluidList",9)) + { + FMLLog.getLogger().log(Level.DEBUG, "Loading persistent fluid defaults from world"); + NBTTagList tl = tag.getTagList("DefaultFluidList", 8); + for (int i = 0; i < tl.tagCount(); i++) + { + defaults.add(tl.getStringTagAt(i)); + } + } + else + { + FMLLog.getLogger().log(Level.DEBUG, "World is missing persistent fluid defaults - using local defaults"); + } + loadFluidDefaults(defaults); + } + + public static void writeDefaultFluidList(NBTTagCompound forgeData) + { + NBTTagList tagList = new NBTTagList(); + + for (Entry def : fluids.entrySet()) + { + tagList.appendTag(new NBTTagString(getDefaultFluidName(def.getValue()))); + } + + forgeData.setTag("DefaultFluidList", tagList); + } } diff --git a/src/main/java/net/minecraftforge/fluids/FluidStack.java b/src/main/java/net/minecraftforge/fluids/FluidStack.java index b485170e9..962633149 100644 --- a/src/main/java/net/minecraftforge/fluids/FluidStack.java +++ b/src/main/java/net/minecraftforge/fluids/FluidStack.java @@ -1,10 +1,6 @@ package net.minecraftforge.fluids; -import java.util.Locale; - -import com.google.common.base.Strings; - import cpw.mods.fml.common.FMLLog; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; From 230d757a8918b2f4e9c1b0aa9c001ea3b5c85f4e Mon Sep 17 00:00:00 2001 From: cpw Date: Sat, 11 Apr 2015 17:27:14 -0400 Subject: [PATCH 18/48] Fix NPE - Closes #1794 --- src/main/java/net/minecraftforge/fluids/FluidRegistry.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/minecraftforge/fluids/FluidRegistry.java b/src/main/java/net/minecraftforge/fluids/FluidRegistry.java index cb25e471b..b6fc32258 100644 --- a/src/main/java/net/minecraftforge/fluids/FluidRegistry.java +++ b/src/main/java/net/minecraftforge/fluids/FluidRegistry.java @@ -165,7 +165,7 @@ public abstract class FluidRegistry */ public static boolean isFluidRegistered(Fluid fluid) { - return fluids.containsKey(fluid.getName()); + return fluid != null && fluids.containsKey(fluid.getName()); } public static boolean isFluidRegistered(String fluidName) From 5c881642110f646f462674ef2aa39442cc81dc68 Mon Sep 17 00:00:00 2001 From: cpw Date: Sat, 11 Apr 2015 17:38:15 -0400 Subject: [PATCH 19/48] And handle the null case in the constructor itself. Closes #1794 (again) --- src/main/java/net/minecraftforge/fluids/FluidStack.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/minecraftforge/fluids/FluidStack.java b/src/main/java/net/minecraftforge/fluids/FluidStack.java index 962633149..c18e18e70 100644 --- a/src/main/java/net/minecraftforge/fluids/FluidStack.java +++ b/src/main/java/net/minecraftforge/fluids/FluidStack.java @@ -23,7 +23,12 @@ public class FluidStack public FluidStack(Fluid fluid, int amount) { - if (!FluidRegistry.isFluidRegistered(fluid)) + if (fluid == null) + { + FMLLog.bigWarning("Null fluid supplied to fluidstack. Did you try and create a stack for an unregistered fluid?"); + throw new IllegalArgumentException("Cannot create a fluidstack from a null fluid"); + } + else if (!FluidRegistry.isFluidRegistered(fluid)) { FMLLog.bigWarning("Failed attempt to create a FluidStack for an unregistered Fluid %s (type %s)", fluid.getName(), fluid.getClass().getName()); throw new IllegalArgumentException("Cannot create a fluidstack from an unregistered fluid"); From 277495c8e45686fa43b52050182452d5226b794c Mon Sep 17 00:00:00 2001 From: cpw Date: Sat, 11 Apr 2015 18:20:11 -0400 Subject: [PATCH 20/48] MinecraftForge/FML@dfce4cd8d023a546c4c21405db182b8ddcd38633 Allow registering custom language adapters. MinecraftForge/FML@9fecd72cf0bd483ae7bc2ce821ae6b2f5e5b9c65 Some tidyup of the PR MinecraftForge/FML@10ac2a4fd972e923a60d23d10e8f297b8584f565 Fix itemCtorArgs javadoc in registerBlock MinecraftForge/FML@86f70d37a40bbeaf7c389a14adcd8311ba5584df Patch TracingPrintStream to handle Kotlin IO. --- fml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fml b/fml index 0da1263ff..86f70d37a 160000 --- a/fml +++ b/fml @@ -1 +1 @@ -Subproject commit 0da1263ff9ede99267c03728a1c823b8056d5e44 +Subproject commit 86f70d37a40bbeaf7c389a14adcd8311ba5584df From 3cd7f6bd8718caf71396481c7c6f7281eae0589c Mon Sep 17 00:00:00 2001 From: King Lemming Date: Mon, 13 Apr 2015 22:40:38 -0400 Subject: [PATCH 21/48] Adjusts OreDictionary to prevent invalid registrations. Getting Ore Names for a non-existent ore will no longer automatically add that Name to the list nor generate an ID. Tweaks a warning message in the FluidContainerRegistry. No functionality change. Signed-off-by: King Lemming --- .../minecraftforge/fluids/FluidContainerRegistry.java | 2 +- .../java/net/minecraftforge/oredict/OreDictionary.java | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/net/minecraftforge/fluids/FluidContainerRegistry.java b/src/main/java/net/minecraftforge/fluids/FluidContainerRegistry.java index 7d6a963e1..355fd1eb4 100644 --- a/src/main/java/net/minecraftforge/fluids/FluidContainerRegistry.java +++ b/src/main/java/net/minecraftforge/fluids/FluidContainerRegistry.java @@ -171,7 +171,7 @@ public abstract class FluidContainerRegistry } if (data.fluid == null || data.fluid.getFluid() == null) { - FMLLog.bigWarning("Invalid registration attempt for a fluid container item %s (type %s) has occurred. The registration has been denied to prevent crashes. The mod responsible for the registration needs to correct this.", data.filledContainer.getItem().getUnlocalizedName(data.filledContainer)); + FMLLog.bigWarning("Invalid registration attempt for a fluid container item %s has occurred. The registration has been denied to prevent crashes. The mod responsible for the registration needs to correct this.", data.filledContainer.getItem().getUnlocalizedName(data.filledContainer)); return false; } containerFluidMap.put(new ContainerKey(data.filledContainer), data); diff --git a/src/main/java/net/minecraftforge/oredict/OreDictionary.java b/src/main/java/net/minecraftforge/oredict/OreDictionary.java index 0c820a1a8..6b972e27b 100644 --- a/src/main/java/net/minecraftforge/oredict/OreDictionary.java +++ b/src/main/java/net/minecraftforge/oredict/OreDictionary.java @@ -344,7 +344,7 @@ public class OreDictionary */ public static ArrayList getOres(String name) //TODO: 1.8 ArrayList -> List { - return getOres(getOreID(name)); + return nameToId.get(name) != null ? getOres(getOreID(name)) : EMPTY_LIST; } /** @@ -447,7 +447,12 @@ public class OreDictionary */ private static void registerOreImpl(String name, ItemStack ore) { - if ("Unknown".equals(name)) return; //prevent bad IDs. + if (name == null || name.isEmpty() || "Unknown".equals(name)) return; //prevent bad IDs. + if (ore == null || ore.getItem() == null) + { + FMLLog.bigWarning("Invalid registration attempt for an Ore Dictionary item with name %s has occurred. The registration has been denied to prevent crashes. The mod responsible for the registration needs to correct this.", name); + return; //prevent bad ItemStacks. + } int oreID = getOreID(name); int hash = Item.getIdFromItem(ore.getItem()); From 475d7fc02d1b0a98d4102ac8bd118832f5852def Mon Sep 17 00:00:00 2001 From: LexManos Date: Mon, 13 Apr 2015 21:28:16 -0700 Subject: [PATCH 22/48] Revert KL's change, requesting a ore WILL register it. Registering like this and returning a new empty list allows for modders to register their recipes and such without requiring to be executed after someone actually adds an item. If handled properly this allows for more flexible load orders, and more responsive code. --- src/main/java/net/minecraftforge/oredict/OreDictionary.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/minecraftforge/oredict/OreDictionary.java b/src/main/java/net/minecraftforge/oredict/OreDictionary.java index 6b972e27b..fe1b46b06 100644 --- a/src/main/java/net/minecraftforge/oredict/OreDictionary.java +++ b/src/main/java/net/minecraftforge/oredict/OreDictionary.java @@ -344,7 +344,7 @@ public class OreDictionary */ public static ArrayList getOres(String name) //TODO: 1.8 ArrayList -> List { - return nameToId.get(name) != null ? getOres(getOreID(name)) : EMPTY_LIST; + return getOres(getOreID(name)); } /** From cd3bbfb02c9fcd4ce4bbf00f460dfdd6a386d107 Mon Sep 17 00:00:00 2001 From: King Lemming Date: Thu, 16 Apr 2015 17:18:37 -0400 Subject: [PATCH 23/48] Adds some new Ore querying functionality. Also attempts to size initial Hashmaps in a logical manner. Signed-off-by: King Lemming --- .../minecraftforge/oredict/OreDictionary.java | 42 ++++++++++++++++++- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/minecraftforge/oredict/OreDictionary.java b/src/main/java/net/minecraftforge/oredict/OreDictionary.java index fe1b46b06..5b5006092 100644 --- a/src/main/java/net/minecraftforge/oredict/OreDictionary.java +++ b/src/main/java/net/minecraftforge/oredict/OreDictionary.java @@ -34,10 +34,10 @@ public class OreDictionary { private static boolean hasInit = false; private static List idToName = new ArrayList(); - private static Map nameToId = new HashMap(); + private static Map nameToId = new HashMap(128); private static List> idToStack = Lists.newArrayList(); //ToDo: Unqualify to List when possible {1.8} private static List> idToStackUn = Lists.newArrayList(); //ToDo: Unqualify to List when possible {1.8} - private static Map> stackToId = Maps.newHashMap(); + private static Map> stackToId = Maps.newHashMapWithExpectedSize(96); // Calculated from 128 * 0.75 public static final ArrayList EMPTY_LIST = new UnmodifiableArrayList(Lists.newArrayList()); //ToDo: Unqualify to List when possible {1.8} /** @@ -347,6 +347,44 @@ public class OreDictionary return getOres(getOreID(name)); } + /** + * Retrieves the List of items that are registered to this ore type at this instant. + * If the flag is TRUE, then it will create the list as empty if it did not exist. + * + * This option should be used by modders who are doing blanket scans in postInit. + * It greatly reduces clutter in the OreDictionary is the responsible and proper + * way to use the dictionary in a large number of cases. + * + * The other function above is utilized in OreRecipe and is required for the + * operation of that code. + * + * @param name The ore name, directly calls getOreID if the flag is TRUE + * @param alwaysCreateEntry Flag - should a new entry be created if empty + * @return An arraylist containing ItemStacks registered for this ore + */ + public static List getOres(String name, boolean alwaysCreateEntry) + { + if (alwaysCreateEntry) { + return getOres(getOreID(name)); + } + return nameToId.get(name) != null ? getOres(getOreID(name)) : EMPTY_LIST; + } + + /** + * Returns whether or not an oreName exists in the dictionary. + * This function can be used to safely query the Ore Dictionary without + * adding needless clutter to the underlying map structure. + * + * Please use this when possible and appropriate. + * + * @param name The ore name + * @return Whether or not that name is in the Ore Dictionary. + */ + public static boolean doesOreNameExist(String name) + { + return nameToId.get(name) != null; + } + /** * Retrieves a list of all unique ore names that are already registered. * From 1effc2779063cee2975b6af9e19ceaded8750f5f Mon Sep 17 00:00:00 2001 From: Lex Manos Date: Fri, 17 Apr 2015 02:07:01 -0700 Subject: [PATCH 24/48] Fixed NBTSizeTracker missing a lot of data being read. Also made new NBT object allocation claim 32-bits in the size tracker. (cherry picked from commit de066a86da281d381b0e3ab9e83682720327049c) Conflicts: patches/minecraft/net/minecraft/nbt/CompressedStreamTools.java.patch patches/minecraft/net/minecraft/nbt/NBTTagList.java.patch --- .../nbt/CompressedStreamTools.java.patch | 22 ++++++++++- .../minecraft/nbt/NBTSizeTracker.java.patch | 37 +++++++++++++++++++ .../minecraft/nbt/NBTTagByteArray.java.patch | 10 +++++ .../minecraft/nbt/NBTTagCompound.java.patch | 27 ++++++++++++++ .../minecraft/nbt/NBTTagIntArray.java.patch | 10 +++++ .../net/minecraft/nbt/NBTTagList.java.patch | 18 ++++++++- .../net/minecraft/nbt/NBTTagString.java.patch | 11 ++++++ 7 files changed, 131 insertions(+), 4 deletions(-) create mode 100644 patches/minecraft/net/minecraft/nbt/NBTSizeTracker.java.patch create mode 100644 patches/minecraft/net/minecraft/nbt/NBTTagByteArray.java.patch create mode 100644 patches/minecraft/net/minecraft/nbt/NBTTagCompound.java.patch create mode 100644 patches/minecraft/net/minecraft/nbt/NBTTagIntArray.java.patch create mode 100644 patches/minecraft/net/minecraft/nbt/NBTTagString.java.patch diff --git a/patches/minecraft/net/minecraft/nbt/CompressedStreamTools.java.patch b/patches/minecraft/net/minecraft/nbt/CompressedStreamTools.java.patch index 3e1d5829a..749a98d58 100644 --- a/patches/minecraft/net/minecraft/nbt/CompressedStreamTools.java.patch +++ b/patches/minecraft/net/minecraft/nbt/CompressedStreamTools.java.patch @@ -16,7 +16,25 @@ public static void func_74793_a(NBTTagCompound p_74793_0_, File p_74793_1_) throws IOException { File file2 = new File(p_74793_1_.getAbsolutePath() + "_tmp"); -@@ -182,7 +179,6 @@ +@@ -156,6 +153,7 @@ + private static NBTBase func_152455_a(DataInput p_152455_0_, int p_152455_1_, NBTSizeTracker p_152455_2_) throws IOException + { + byte b0 = p_152455_0_.readByte(); ++ p_152455_2_.func_152450_a(8); // Forge: Count everything! + + if (b0 == 0) + { +@@ -163,7 +161,8 @@ + } + else + { +- p_152455_0_.readUTF(); ++ NBTSizeTracker.readUTF(p_152455_2_, p_152455_0_.readUTF()); //Forge: Count this string. ++ p_152455_2_.func_152450_a(32); //Forge: 4 extra bytes for the object allocation. + NBTBase nbtbase = NBTBase.func_150284_a(b0); + + try +@@ -182,7 +181,6 @@ } } @@ -24,7 +42,7 @@ public static void func_74795_b(NBTTagCompound p_74795_0_, File p_74795_1_) throws IOException { DataOutputStream dataoutputstream = new DataOutputStream(new FileOutputStream(p_74795_1_)); -@@ -197,13 +193,11 @@ +@@ -197,13 +195,11 @@ } } diff --git a/patches/minecraft/net/minecraft/nbt/NBTSizeTracker.java.patch b/patches/minecraft/net/minecraft/nbt/NBTSizeTracker.java.patch new file mode 100644 index 000000000..c7720b745 --- /dev/null +++ b/patches/minecraft/net/minecraft/nbt/NBTSizeTracker.java.patch @@ -0,0 +1,37 @@ +--- ../src-base/minecraft/net/minecraft/nbt/NBTSizeTracker.java ++++ ../src-work/minecraft/net/minecraft/nbt/NBTSizeTracker.java +@@ -25,4 +25,34 @@ + throw new RuntimeException("Tried to read NBT tag that was too big; tried to allocate: " + this.field_152453_c + "bytes where max allowed: " + this.field_152452_b); + } + } ++ ++ /* ++ * UTF8 is not a simple encoding system, each character can be either ++ * 1, 2, or 3 bytes. Depending on where it's numerical value falls. ++ * We have to count up each character individually to see the true ++ * length of the data. ++ * ++ * Basic concept is that it uses the MSB of each byte as a 'read more' signal. ++ * So it has to shift each 7-bit segment. ++ * ++ * This will accurately count the correct byte length to encode this string, plus the 2 bytes for it's length prefix. ++ */ ++ public static void readUTF(NBTSizeTracker tracker, String data) ++ { ++ tracker.func_152450_a(16); //Header length ++ if (data == null) ++ return; ++ ++ int len = data.length(); ++ int utflen = 0; ++ ++ for (int i = 0; i < len; i++) ++ { ++ int c = data.charAt(i); ++ if ((c >= 0x0001) && (c <= 0x007F)) utflen += 1; ++ else if (c > 0x07FF) utflen += 3; ++ else utflen += 2; ++ } ++ tracker.func_152450_a(8 * utflen); ++ } + } diff --git a/patches/minecraft/net/minecraft/nbt/NBTTagByteArray.java.patch b/patches/minecraft/net/minecraft/nbt/NBTTagByteArray.java.patch new file mode 100644 index 000000000..ead6ffc34 --- /dev/null +++ b/patches/minecraft/net/minecraft/nbt/NBTTagByteArray.java.patch @@ -0,0 +1,10 @@ +--- ../src-base/minecraft/net/minecraft/nbt/NBTTagByteArray.java ++++ ../src-work/minecraft/net/minecraft/nbt/NBTTagByteArray.java +@@ -25,6 +25,7 @@ + + void func_152446_a(DataInput p_152446_1_, int p_152446_2_, NBTSizeTracker p_152446_3_) throws IOException + { ++ p_152446_3_.func_152450_a(32); //Forge: Count the length as well + int j = p_152446_1_.readInt(); + p_152446_3_.func_152450_a((long)(8 * j)); + this.field_74754_a = new byte[j]; diff --git a/patches/minecraft/net/minecraft/nbt/NBTTagCompound.java.patch b/patches/minecraft/net/minecraft/nbt/NBTTagCompound.java.patch new file mode 100644 index 000000000..f98f85e2f --- /dev/null +++ b/patches/minecraft/net/minecraft/nbt/NBTTagCompound.java.patch @@ -0,0 +1,27 @@ +--- ../src-base/minecraft/net/minecraft/nbt/NBTTagCompound.java ++++ ../src-work/minecraft/net/minecraft/nbt/NBTTagCompound.java +@@ -48,7 +48,7 @@ + while ((b0 = func_152447_a(p_152446_1_, p_152446_3_)) != 0) + { + String s = func_152448_b(p_152446_1_, p_152446_3_); +- p_152446_3_.func_152450_a((long)(16 * s.length())); ++ NBTSizeTracker.readUTF(p_152446_3_, s); // Forge: Correctly read String length including header. + NBTBase nbtbase = func_152449_a(b0, s, p_152446_1_, p_152446_2_ + 1, p_152446_3_); + this.field_74784_a.put(s, nbtbase); + } +@@ -379,6 +379,7 @@ + + private static byte func_152447_a(DataInput p_152447_0_, NBTSizeTracker p_152447_1_) throws IOException + { ++ p_152447_1_.func_152450_a(8); + return p_152447_0_.readByte(); + } + +@@ -389,6 +390,7 @@ + + static NBTBase func_152449_a(byte p_152449_0_, String p_152449_1_, DataInput p_152449_2_, int p_152449_3_, NBTSizeTracker p_152449_4_) + { ++ p_152449_4_.func_152450_a(32); //Forge: 4 extra bytes for the object allocation. + NBTBase nbtbase = NBTBase.func_150284_a(p_152449_0_); + + try diff --git a/patches/minecraft/net/minecraft/nbt/NBTTagIntArray.java.patch b/patches/minecraft/net/minecraft/nbt/NBTTagIntArray.java.patch new file mode 100644 index 000000000..40a4b4cb7 --- /dev/null +++ b/patches/minecraft/net/minecraft/nbt/NBTTagIntArray.java.patch @@ -0,0 +1,10 @@ +--- ../src-base/minecraft/net/minecraft/nbt/NBTTagIntArray.java ++++ ../src-work/minecraft/net/minecraft/nbt/NBTTagIntArray.java +@@ -29,6 +29,7 @@ + + void func_152446_a(DataInput p_152446_1_, int p_152446_2_, NBTSizeTracker p_152446_3_) throws IOException + { ++ p_152446_3_.func_152450_a(32); //Forge: Count the length as well + int j = p_152446_1_.readInt(); + p_152446_3_.func_152450_a((long)(32 * j)); + this.field_74749_a = new int[j]; diff --git a/patches/minecraft/net/minecraft/nbt/NBTTagList.java.patch b/patches/minecraft/net/minecraft/nbt/NBTTagList.java.patch index 5d1657430..7fc49f2dc 100644 --- a/patches/minecraft/net/minecraft/nbt/NBTTagList.java.patch +++ b/patches/minecraft/net/minecraft/nbt/NBTTagList.java.patch @@ -8,7 +8,21 @@ import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; -@@ -91,7 +89,6 @@ +@@ -45,11 +43,13 @@ + { + p_152446_3_.func_152450_a(8L); + this.field_74746_b = p_152446_1_.readByte(); ++ p_152446_3_.func_152450_a(32); //Forge: Count the length as well + int j = p_152446_1_.readInt(); + this.field_74747_a = new ArrayList(); + + for (int k = 0; k < j; ++k) + { ++ p_152446_3_.func_152450_a(32); //Forge: 4 extra bytes for the object allocation. + NBTBase nbtbase = NBTBase.func_150284_a(this.field_74746_b); + nbtbase.func_152446_a(p_152446_1_, p_152446_2_ + 1, p_152446_3_); + this.field_74747_a.add(nbtbase); +@@ -91,7 +91,6 @@ this.field_74747_a.add(p_74742_1_); } @@ -16,7 +30,7 @@ public void func_150304_a(int p_150304_1_, NBTBase p_150304_2_) { if (p_150304_1_ >= 0 && p_150304_1_ < this.field_74747_a.size()) -@@ -114,7 +111,6 @@ +@@ -114,7 +113,6 @@ } } diff --git a/patches/minecraft/net/minecraft/nbt/NBTTagString.java.patch b/patches/minecraft/net/minecraft/nbt/NBTTagString.java.patch new file mode 100644 index 000000000..56efede98 --- /dev/null +++ b/patches/minecraft/net/minecraft/nbt/NBTTagString.java.patch @@ -0,0 +1,11 @@ +--- ../src-base/minecraft/net/minecraft/nbt/NBTTagString.java ++++ ../src-work/minecraft/net/minecraft/nbt/NBTTagString.java +@@ -32,7 +32,7 @@ + void func_152446_a(DataInput p_152446_1_, int p_152446_2_, NBTSizeTracker p_152446_3_) throws IOException + { + this.field_74751_a = p_152446_1_.readUTF(); +- p_152446_3_.func_152450_a((long)(16 * this.field_74751_a.length())); ++ NBTSizeTracker.readUTF(p_152446_3_, field_74751_a); // Forge: Correctly read String length including header. + } + + public byte func_74732_a() From 54af7507177a7ddf7b3d7b3e20c2c33f9352be78 Mon Sep 17 00:00:00 2001 From: cpw Date: Sat, 18 Apr 2015 21:37:45 -0400 Subject: [PATCH 25/48] Verify that the fluid registry doesn't contain "junk" fluids thru reflection. --- .../common/ForgeModContainer.java | 1 + .../minecraftforge/fluids/FluidRegistry.java | 32 ++++++++++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/minecraftforge/common/ForgeModContainer.java b/src/main/java/net/minecraftforge/common/ForgeModContainer.java index 366ad2be7..70202ad46 100644 --- a/src/main/java/net/minecraftforge/common/ForgeModContainer.java +++ b/src/main/java/net/minecraftforge/common/ForgeModContainer.java @@ -297,6 +297,7 @@ public class ForgeModContainer extends DummyModContainer implements WorldAccessC { RecipeSorter.sortCraftManager(); } + FluidRegistry.validateFluidRegistry(); } @Subscribe diff --git a/src/main/java/net/minecraftforge/fluids/FluidRegistry.java b/src/main/java/net/minecraftforge/fluids/FluidRegistry.java index b6fc32258..bf15975fd 100644 --- a/src/main/java/net/minecraftforge/fluids/FluidRegistry.java +++ b/src/main/java/net/minecraftforge/fluids/FluidRegistry.java @@ -14,6 +14,7 @@ import net.minecraft.nbt.NBTTagString; import net.minecraft.util.StatCollector; import net.minecraftforge.common.MinecraftForge; +import com.google.common.base.Strings; import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; import com.google.common.collect.ImmutableMap; @@ -280,7 +281,12 @@ public abstract class FluidRegistry public static String getDefaultFluidName(Fluid key) { - return masterFluidReference.inverse().get(key); + String name = masterFluidReference.inverse().get(key); + if (Strings.isNullOrEmpty(name)) { + FMLLog.getLogger().log(Level.ERROR, "The fluid registry is corrupted. A fluid {} {} is not properly registered. The mod that registered this is broken", key.getClass().getName(), key.getName()); + throw new IllegalStateException("The fluid registry is corrupted"); + } + return name; } public static void loadFluidDefaults(NBTTagCompound tag) @@ -313,4 +319,28 @@ public abstract class FluidRegistry forgeData.setTag("DefaultFluidList", tagList); } + + public static void validateFluidRegistry() + { + Set illegalFluids = Sets.newHashSet(); + for (Fluid f : fluids.values()) + { + if (!masterFluidReference.containsValue(f)) + { + illegalFluids.add(f); + } + } + + if (!illegalFluids.isEmpty()) + { + FMLLog.getLogger().log(Level.FATAL, "The fluid registry is corrupted. Something has inserted a fluid without registering it"); + FMLLog.getLogger().log(Level.FATAL, "There is {} unregistered fluids", illegalFluids.size()); + for (Fluid f: illegalFluids) + { + FMLLog.getLogger().log(Level.FATAL, " Fluid name : {}, type: {}", f.getName(), f.getClass().getName()); + } + FMLLog.getLogger().log(Level.FATAL, "The mods that own these fluids need to register them properly"); + throw new IllegalStateException("The fluid map contains fluids unknown to the master fluid registry"); + } + } } From 57408af2a3e14470ef9cc3d4bdb4668bd0e879b9 Mon Sep 17 00:00:00 2001 From: cpw Date: Sat, 18 Apr 2015 21:54:01 -0400 Subject: [PATCH 26/48] MinecraftForge/FML@8f9e3a7e30c8cc436dcb8d94b18b4634e0376339 Exceptions during construction phase should not propogate and cause an immediate crash. Closes #638 --- fml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fml b/fml index 86f70d37a..8f9e3a7e3 160000 --- a/fml +++ b/fml @@ -1 +1 @@ -Subproject commit 86f70d37a40bbeaf7c389a14adcd8311ba5584df +Subproject commit 8f9e3a7e30c8cc436dcb8d94b18b4634e0376339 From 178acfbb20bdbddf4177c8741f90335fafc2785f Mon Sep 17 00:00:00 2001 From: cpw Date: Sun, 19 Apr 2015 11:52:23 -0400 Subject: [PATCH 27/48] Change logging to avoid the String.format bug. Closes #1809 --- patches/minecraft/net/minecraft/world/World.java.patch | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/patches/minecraft/net/minecraft/world/World.java.patch b/patches/minecraft/net/minecraft/world/World.java.patch index afeadef72..99f22384a 100644 --- a/patches/minecraft/net/minecraft/world/World.java.patch +++ b/patches/minecraft/net/minecraft/world/World.java.patch @@ -418,7 +418,7 @@ - throw new ReportedException(crashreport); + if (ForgeModContainer.removeErroringEntities) + { -+ FMLLog.severe(crashreport.func_71502_e()); ++ FMLLog.getLogger().log(org.apache.logging.log4j.Level.ERROR, crashreport.func_71502_e()); + func_72900_e(entity); + } + else @@ -436,7 +436,7 @@ + + if (ForgeModContainer.removeErroringEntities) + { -+ FMLLog.severe(crashreport.func_71502_e()); ++ FMLLog.getLogger().log(org.apache.logging.log4j.Level.ERROR, crashreport.func_71502_e()); + func_72900_e(entity); + } + else @@ -453,7 +453,7 @@ - throw new ReportedException(crashreport); + if (ForgeModContainer.removeErroringTileEntities) + { -+ FMLLog.severe(crashreport.func_71502_e()); ++ FMLLog.getLogger().log(org.apache.logging.log4j.Level.ERROR, crashreport.func_71502_e()); + tileentity.func_145843_s(); + func_147468_f(tileentity.field_145851_c, tileentity.field_145848_d, tileentity.field_145849_e); + } From dcb2f2588caef1ae4e18a7bd0d6cff4111970c78 Mon Sep 17 00:00:00 2001 From: cpw Date: Sun, 19 Apr 2015 11:57:39 -0400 Subject: [PATCH 28/48] Actually use the override constraint in ticket requests. Closes #1802 --- src/main/java/net/minecraftforge/common/ForgeChunkManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/minecraftforge/common/ForgeChunkManager.java b/src/main/java/net/minecraftforge/common/ForgeChunkManager.java index 59fc7353e..62d5b0df0 100644 --- a/src/main/java/net/minecraftforge/common/ForgeChunkManager.java +++ b/src/main/java/net/minecraftforge/common/ForgeChunkManager.java @@ -664,7 +664,7 @@ public class ForgeChunkManager throw new RuntimeException("Invalid ticket request"); } - int allowedCount = ticketConstraints.containsKey(modId) ? ticketConstraints.get(modId) : defaultMaxCount; + int allowedCount = getMaxTicketLengthFor(modId); if (tickets.get(world).get(modId).size() >= allowedCount) { From 7e9d2fb50973bf811dc0118091e5d2ac2130b4ec Mon Sep 17 00:00:00 2001 From: cpw Date: Sun, 19 Apr 2015 12:04:22 -0400 Subject: [PATCH 29/48] Reformat ItemArmor$ArmorMaterial.getBaseItem to use an if/then/else structure. The switch causes the generation of an internal class which may derp custom armor addition. Closes #1799 --- .../net/minecraft/item/ItemArmor.java.patch | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/patches/minecraft/net/minecraft/item/ItemArmor.java.patch b/patches/minecraft/net/minecraft/item/ItemArmor.java.patch index 8c21039da..c660916d7 100644 --- a/patches/minecraft/net/minecraft/item/ItemArmor.java.patch +++ b/patches/minecraft/net/minecraft/item/ItemArmor.java.patch @@ -19,20 +19,17 @@ private ArmorMaterial(int p_i1827_3_, int[] p_i1827_4_, int p_i1827_5_) { this.field_78048_f = p_i1827_3_; -@@ -283,7 +286,15 @@ +@@ -283,7 +286,12 @@ public Item func_151685_b() { - return this == CLOTH ? Items.field_151116_aA : (this == CHAIN ? Items.field_151042_j : (this == GOLD ? Items.field_151043_k : (this == IRON ? Items.field_151042_j : (this == DIAMOND ? Items.field_151045_i : null)))); -+ switch (this) -+ { -+ case CLOTH: return Items.field_151116_aA; -+ case CHAIN: return Items.field_151042_j; -+ case GOLD: return Items.field_151043_k; -+ case IRON: return Items.field_151042_j; -+ case DIAMOND: return Items.field_151045_i; -+ default: return customCraftingMaterial; -+ } ++ return this == CLOTH ? Items.field_151116_aA : ++ (this == CHAIN ? Items.field_151042_j : ++ (this == GOLD ? Items.field_151043_k : ++ (this == IRON ? Items.field_151042_j : ++ (this == DIAMOND ? Items.field_151045_i : ++ customCraftingMaterial)))); } } } From 0543828603e663fb79984cd13fafd3c55a3d2fc4 Mon Sep 17 00:00:00 2001 From: cpw Date: Mon, 20 Apr 2015 09:06:23 -0400 Subject: [PATCH 30/48] Make FluidStack hold a delegate for the fluid. This can then float based on what is "live" at present. --- .../fluids/FluidContainerRegistry.java | 4 +- .../minecraftforge/fluids/FluidRegistry.java | 54 +++++++++++++++++-- .../net/minecraftforge/fluids/FluidStack.java | 26 +++++---- 3 files changed, 70 insertions(+), 14 deletions(-) diff --git a/src/main/java/net/minecraftforge/fluids/FluidContainerRegistry.java b/src/main/java/net/minecraftforge/fluids/FluidContainerRegistry.java index 355fd1eb4..10317c1b2 100644 --- a/src/main/java/net/minecraftforge/fluids/FluidContainerRegistry.java +++ b/src/main/java/net/minecraftforge/fluids/FluidContainerRegistry.java @@ -50,7 +50,7 @@ public abstract class FluidContainerRegistry code = 31*code + container.getItem().hashCode(); code = 31*code + container.getItemDamage(); if (stack != null) - code = 31*code + stack.fluid.hashCode(); + code = 31*code + stack.getFluid().hashCode(); return code; } @Override @@ -63,7 +63,7 @@ public abstract class FluidContainerRegistry if (stack == null && ck.stack != null) return false; if (stack != null && ck.stack == null) return false; if (stack == null && ck.stack == null) return true; - if (stack.fluid != ck.stack.fluid) return false; + if (stack.getFluid() != ck.stack.getFluid()) return false; return true; } } diff --git a/src/main/java/net/minecraftforge/fluids/FluidRegistry.java b/src/main/java/net/minecraftforge/fluids/FluidRegistry.java index bf15975fd..dce949f2e 100644 --- a/src/main/java/net/minecraftforge/fluids/FluidRegistry.java +++ b/src/main/java/net/minecraftforge/fluids/FluidRegistry.java @@ -18,6 +18,7 @@ import com.google.common.base.Strings; import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; import com.google.common.collect.Sets; import cpw.mods.fml.common.FMLLog; @@ -25,6 +26,7 @@ import cpw.mods.fml.common.Loader; import cpw.mods.fml.common.ModContainer; import cpw.mods.fml.common.eventhandler.Event; import cpw.mods.fml.common.network.ByteBufUtils; +import cpw.mods.fml.common.registry.RegistryDelegate; /** * Handles Fluid registrations. Fluids MUST be registered in order to function. @@ -114,6 +116,10 @@ public abstract class FluidRegistry fluidIDs.put(fluid, id); } fluidBlocks = null; + for (FluidDelegate fd : delegates.values()) + { + fd.rebind(); + } } /** @@ -127,7 +133,7 @@ public abstract class FluidRegistry public static boolean registerFluid(Fluid fluid) { masterFluidReference.put(uniqueName(fluid), fluid); - + delegates.put(fluid, new FluidDelegate(fluid, fluid.getName())); if (fluids.containsKey(fluid.getName())) { return false; @@ -207,7 +213,7 @@ public abstract class FluidRegistry public static String getFluidName(FluidStack stack) { - return getFluidName(stack.fluid); + return getFluidName(stack.getFluid()); } public static FluidStack getFluidStack(String fluidName, int amount) @@ -343,4 +349,46 @@ public abstract class FluidRegistry throw new IllegalStateException("The fluid map contains fluids unknown to the master fluid registry"); } } -} + + private static Map delegates = Maps.newHashMap(); + static RegistryDelegate makeDelegate(Fluid fl) + { + return delegates.get(fl); + } + + + private static class FluidDelegate implements RegistryDelegate + { + private String name; + private Fluid fluid; + + FluidDelegate(Fluid fluid, String name) + { + this.fluid = fluid; + this.name = name; + } + + @Override + public Fluid get() + { + return fluid; + } + + @Override + public String name() + { + return name; + } + + @Override + public Class type() + { + return Fluid.class; + } + + void rebind() + { + fluid = fluids.get(name); + } + } +} \ No newline at end of file diff --git a/src/main/java/net/minecraftforge/fluids/FluidStack.java b/src/main/java/net/minecraftforge/fluids/FluidStack.java index c18e18e70..e3037008f 100644 --- a/src/main/java/net/minecraftforge/fluids/FluidStack.java +++ b/src/main/java/net/minecraftforge/fluids/FluidStack.java @@ -2,6 +2,7 @@ package net.minecraftforge.fluids; import cpw.mods.fml.common.FMLLog; +import cpw.mods.fml.common.registry.RegistryDelegate; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; @@ -17,9 +18,15 @@ import net.minecraft.nbt.NBTTagCompound; */ public class FluidStack { - public final Fluid fluid; + /** + * This field will be removed in 1.8. It may be incorrect after a world is loaded. Code should always + * use {@link #getFluid()} instead. That will always reflect the correct value. + */ + @Deprecated + public final Fluid fluid; public int amount; public NBTTagCompound tag; + private RegistryDelegate fluidDelegate; public FluidStack(Fluid fluid, int amount) { @@ -33,8 +40,9 @@ public class FluidStack FMLLog.bigWarning("Failed attempt to create a FluidStack for an unregistered Fluid %s (type %s)", fluid.getName(), fluid.getClass().getName()); throw new IllegalArgumentException("Cannot create a fluidstack from an unregistered fluid"); } - this.fluid = fluid; + this.fluidDelegate = FluidRegistry.makeDelegate(fluid); this.amount = amount; + this.fluid = fluid; } public FluidStack(Fluid fluid, int amount, NBTTagCompound nbt) @@ -49,7 +57,7 @@ public class FluidStack public FluidStack(FluidStack stack, int amount) { - this(stack.fluid, amount, stack.tag); + this(stack.getFluid(), amount, stack.tag); } // To be removed in 1.8 @@ -93,7 +101,7 @@ public class FluidStack public NBTTagCompound writeToNBT(NBTTagCompound nbt) { - nbt.setString("FluidName", FluidRegistry.getFluidName(fluid)); + nbt.setString("FluidName", FluidRegistry.getFluidName(getFluid())); nbt.setInteger("Amount", amount); if (tag != null) @@ -105,12 +113,12 @@ public class FluidStack public final Fluid getFluid() { - return fluid; + return fluidDelegate.get(); } public final int getFluidID() { - return FluidRegistry.getFluidID(fluid); + return FluidRegistry.getFluidID(getFluid()); } public String getLocalizedName() @@ -128,7 +136,7 @@ public class FluidStack */ public FluidStack copy() { - return new FluidStack(fluid, amount, tag); + return new FluidStack(getFluid(), amount, tag); } /** @@ -140,7 +148,7 @@ public class FluidStack */ public boolean isFluidEqual(FluidStack other) { - return other != null && fluid == other.fluid && isFluidStackTagEqual(other); + return other != null && getFluid() == other.getFluid() && isFluidStackTagEqual(other); } private boolean isFluidStackTagEqual(FluidStack other) @@ -206,7 +214,7 @@ public class FluidStack public final int hashCode() { int code = 1; - code = 31*code + fluid.hashCode(); + code = 31*code + getFluid().hashCode(); code = 31*code + amount; if (tag != null) code = 31*code + tag.hashCode(); From 7bbe8df2b8c9db7506b919564d90f4bb3c5492c3 Mon Sep 17 00:00:00 2001 From: cpw Date: Mon, 20 Apr 2015 09:26:27 -0400 Subject: [PATCH 31/48] Fix static initializer derp. --- src/main/java/net/minecraftforge/fluids/FluidRegistry.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/minecraftforge/fluids/FluidRegistry.java b/src/main/java/net/minecraftforge/fluids/FluidRegistry.java index dce949f2e..697d25bdb 100644 --- a/src/main/java/net/minecraftforge/fluids/FluidRegistry.java +++ b/src/main/java/net/minecraftforge/fluids/FluidRegistry.java @@ -46,6 +46,7 @@ public abstract class FluidRegistry // the globally unique fluid map - only used to associate non-defaults during world/server loading static BiMap masterFluidReference = HashBiMap.create(); static BiMap defaultFluidName = HashBiMap.create(); + static Map delegates = Maps.newHashMap(); public static final Fluid WATER = new Fluid("water") { @Override @@ -350,7 +351,6 @@ public abstract class FluidRegistry } } - private static Map delegates = Maps.newHashMap(); static RegistryDelegate makeDelegate(Fluid fl) { return delegates.get(fl); From 50608986fe419c9328b3fc6f65415c805fa140cd Mon Sep 17 00:00:00 2001 From: cpw Date: Mon, 20 Apr 2015 10:01:36 -0400 Subject: [PATCH 32/48] Replace the OLD fluid in the fluidID map, not the new one.. --- src/main/java/net/minecraftforge/fluids/FluidRegistry.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/minecraftforge/fluids/FluidRegistry.java b/src/main/java/net/minecraftforge/fluids/FluidRegistry.java index 697d25bdb..77ce2b887 100644 --- a/src/main/java/net/minecraftforge/fluids/FluidRegistry.java +++ b/src/main/java/net/minecraftforge/fluids/FluidRegistry.java @@ -112,8 +112,8 @@ public abstract class FluidRegistry FMLLog.getLogger().log(Level.ERROR, "The fluid {} specified as default is not present - it will be reverted to default {}", defaultName, localDefault); } FMLLog.getLogger().log(Level.DEBUG, "The fluid {} has been selected as the default fluid for {}", defaultName, fluid.getName()); - fluids.put(fluid.getName(), fluid); - Integer id = fluidIDs.remove(fluid); + Fluid oldFluid = fluids.put(fluid.getName(), fluid); + Integer id = fluidIDs.remove(oldFluid); fluidIDs.put(fluid, id); } fluidBlocks = null; From 96cbadb874e0485df965c1679a4d14d92da70433 Mon Sep 17 00:00:00 2001 From: cpw Date: Mon, 20 Apr 2015 10:29:04 -0400 Subject: [PATCH 33/48] Expose the fluid that a block was constructed with, useful for 'non-default' configuration of fluidblocks. Shouldn't be used outside of this purpose. --- .../java/net/minecraftforge/fluids/BlockFluidBase.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/net/minecraftforge/fluids/BlockFluidBase.java b/src/main/java/net/minecraftforge/fluids/BlockFluidBase.java index 7e36157b2..1f8fd15af 100644 --- a/src/main/java/net/minecraftforge/fluids/BlockFluidBase.java +++ b/src/main/java/net/minecraftforge/fluids/BlockFluidBase.java @@ -50,6 +50,13 @@ public abstract class BlockFluidBase extends Block implements IFluidBlock protected final String fluidName; + /** + * This is the fluid used in the constructor. Use this reference to configure things + * like icons for your block. It might not be active in the registry, so do + * NOT expose it. + */ + protected final Fluid definedFluid; + public BlockFluidBase(Fluid fluid, Material material) { super(material); @@ -65,6 +72,7 @@ public abstract class BlockFluidBase extends Block implements IFluidBlock this.densityDir = fluid.density > 0 ? -1 : 1; fluid.setBlock(this); + this.definedFluid = fluid; displacements.putAll(defaultDisplacements); } From 50215307f25d7c84bbd392513e2bac5a9d3dbfeb Mon Sep 17 00:00:00 2001 From: cpw Date: Mon, 20 Apr 2015 22:27:10 -0400 Subject: [PATCH 34/48] MinecraftForge/FML@d14d1a8fea4c9242c944079ab8e4cdd516dfce4c Update to use the inherited jar format. Simplifies a lot.. --- fml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fml b/fml index 8f9e3a7e3..d14d1a8fe 160000 --- a/fml +++ b/fml @@ -1 +1 @@ -Subproject commit 8f9e3a7e30c8cc436dcb8d94b18b4634e0376339 +Subproject commit d14d1a8fea4c9242c944079ab8e4cdd516dfce4c From c12bb689fbde0d5528ae3ab3b247bd28f4441913 Mon Sep 17 00:00:00 2001 From: cpw Date: Tue, 21 Apr 2015 00:30:52 -0400 Subject: [PATCH 35/48] MinecraftForge/FML@a39482c4b7ac2883f821619b47ff31e0b6e74b29 Splash screen implementation MinecraftForge/FML@01fea095cdcd80c2ae9f0ebfd1c72242b3f2dbf8 Merge branch '1.7.10-load-progress' of github.com:RainWarrior/FML into 1.7.10 MinecraftForge/FML@364b4bbbb0d4d168f9a63fa62a09e4e2fa213039 Call some loader stuffs MinecraftForge/FML@61a891280d15f9f17e28bf86a427f32de5a8983e Make sure to close the splash screen if there's gonna be an error display --- fml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fml b/fml index d14d1a8fe..61a891280 160000 --- a/fml +++ b/fml @@ -1 +1 @@ -Subproject commit d14d1a8fea4c9242c944079ab8e4cdd516dfce4c +Subproject commit 61a891280d15f9f17e28bf86a427f32de5a8983e From a297a615b9da62c3734745e13fbdd6c2f3148327 Mon Sep 17 00:00:00 2001 From: RainWarrior Date: Fri, 24 Apr 2015 05:51:44 +0300 Subject: [PATCH 36/48] MinecraftForge/FML@5785a9c9e8d76b91a03ed1f9791aeee1cb7ea00b Fix up multiple injections of cmdline files via versionspecificmoddir. Closes #645 MinecraftForge/FML@bd117be9c3e3919f3c29538cde80e3eb8fa48368 Correctly track exceptions thrown in the loading screen rendering thread --- fml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fml b/fml index 61a891280..bd117be9c 160000 --- a/fml +++ b/fml @@ -1 +1 @@ -Subproject commit 61a891280d15f9f17e28bf86a427f32de5a8983e +Subproject commit bd117be9c3e3919f3c29538cde80e3eb8fa48368 From 55cbba07642195e5ecd78fa93249b454b061a84c Mon Sep 17 00:00:00 2001 From: cpw Date: Fri, 24 Apr 2015 19:16:55 -0400 Subject: [PATCH 37/48] MinecraftForge/FML@36688e781aae67fb1e4e7047acf689edeeac7ddb Add in resource reloading to the bar. Tidy up some of the labels a bit. MinecraftForge/FML@a1dc465a55612ecdd44e6cde3adc0f1d53c6d97b More progress bar action! MinecraftForge/FML@bfcbf4ef4366fd3d8bfd20adafb63a857bb0dd53 More progress bar hooks MinecraftForge/FML@a6670c415ee97e771020921e00773c4c15e7512e Thread errors should be correctly displayed in the crash report now MinecraftForge/FML@9a16d26186d27029cae32a19c09ddf48f7cba22e fixed bar text positioning MinecraftForge/FML@0059c630281b7105c0532d2dba1bec27cf0323b2 Track mipmaps and texture upload MinecraftForge/FML@ef5f809752e87e369235e98a63027e9347185cd9 Fix broken log message in vanilla. --- fml | 2 +- .../net/minecraft/client/Minecraft.java.patch | 26 +++++++++---------- .../renderer/texture/TextureMap.java.patch | 14 +++++----- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/fml b/fml index bd117be9c..ef5f80975 160000 --- a/fml +++ b/fml @@ -1 +1 @@ -Subproject commit bd117be9c3e3919f3c29538cde80e3eb8fa48368 +Subproject commit ef5f809752e87e369235e98a63027e9347185cd9 diff --git a/patches/minecraft/net/minecraft/client/Minecraft.java.patch b/patches/minecraft/net/minecraft/client/Minecraft.java.patch index 9ec828797..248ff1af8 100644 --- a/patches/minecraft/net/minecraft/client/Minecraft.java.patch +++ b/patches/minecraft/net/minecraft/client/Minecraft.java.patch @@ -17,8 +17,8 @@ } catch (LWJGLException lwjglexception) { -@@ -541,7 +540,7 @@ - this.field_71452_i = new EffectRenderer(this.field_71441_e, this.field_71446_o); +@@ -552,7 +551,7 @@ + cpw.mods.fml.common.ProgressManager.pop(bar); FMLClientHandler.instance().finishMinecraftLoading(); this.func_71361_d("Post startup"); - this.field_71456_v = new GuiIngame(this); @@ -26,7 +26,7 @@ if (this.field_71475_ae != null) { -@@ -761,11 +760,6 @@ +@@ -772,11 +771,6 @@ public void func_147108_a(GuiScreen p_147108_1_) { @@ -38,7 +38,7 @@ if (p_147108_1_ == null && this.field_71441_e == null) { p_147108_1_ = new GuiMainMenu(); -@@ -775,6 +769,17 @@ +@@ -786,6 +780,17 @@ p_147108_1_ = new GuiGameOver(); } @@ -56,7 +56,7 @@ if (p_147108_1_ instanceof GuiMainMenu) { this.field_71474_y.field_74330_P = false; -@@ -1341,7 +1346,7 @@ +@@ -1352,7 +1357,7 @@ if (this.field_71439_g.func_82246_f(i, j, k)) { @@ -65,7 +65,7 @@ this.field_71439_g.func_71038_i(); } } -@@ -1422,11 +1427,12 @@ +@@ -1433,11 +1438,12 @@ int j = this.field_71476_x.field_72312_c; int k = this.field_71476_x.field_72309_d; @@ -80,7 +80,7 @@ { flag = false; this.field_71439_g.func_71038_i(); -@@ -1453,7 +1459,8 @@ +@@ -1464,7 +1470,8 @@ { ItemStack itemstack1 = this.field_71439_g.field_71071_by.func_70448_g(); @@ -90,7 +90,7 @@ { this.field_71460_t.field_78516_c.func_78445_c(); } -@@ -1665,6 +1672,8 @@ +@@ -1676,6 +1683,8 @@ while (Mouse.next()) { @@ -99,7 +99,7 @@ j = Mouse.getEventButton(); KeyBinding.func_74510_a(j - 100, Mouse.getEventButtonState()); -@@ -2127,6 +2136,11 @@ +@@ -2138,6 +2147,11 @@ public void func_71353_a(WorldClient p_71353_1_, String p_71353_2_) { @@ -111,7 +111,7 @@ if (p_71353_1_ == null) { NetHandlerPlayClient nethandlerplayclient = this.func_147114_u(); -@@ -2139,6 +2153,18 @@ +@@ -2150,6 +2164,18 @@ if (this.field_71437_Z != null) { this.field_71437_Z.func_71263_m(); @@ -130,7 +130,7 @@ } this.field_71437_Z = null; -@@ -2287,113 +2313,10 @@ +@@ -2298,113 +2324,10 @@ if (this.field_71476_x != null) { boolean flag = this.field_71439_g.field_71075_bZ.field_75098_d; @@ -246,7 +246,7 @@ if (flag) { j = this.field_71439_g.field_71069_bz.field_75151_b.size() - 9 + this.field_71439_g.field_71071_by.field_70461_c; -@@ -2659,8 +2582,15 @@ +@@ -2670,8 +2593,15 @@ p_70001_1_.func_152767_b("gl_max_texture_size", Integer.valueOf(func_71369_N())); } @@ -262,7 +262,7 @@ for (int i = 16384; i > 0; i >>= 1) { GL11.glTexImage2D(GL11.GL_PROXY_TEXTURE_2D, 0, GL11.GL_RGBA, i, i, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, (ByteBuffer)null); -@@ -2668,6 +2598,7 @@ +@@ -2679,6 +2609,7 @@ if (j != 0) { diff --git a/patches/minecraft/net/minecraft/client/renderer/texture/TextureMap.java.patch b/patches/minecraft/net/minecraft/client/renderer/texture/TextureMap.java.patch index cac9df558..ee4979668 100644 --- a/patches/minecraft/net/minecraft/client/renderer/texture/TextureMap.java.patch +++ b/patches/minecraft/net/minecraft/client/renderer/texture/TextureMap.java.patch @@ -20,12 +20,12 @@ this.field_94258_i.clear(); int j = Integer.MAX_VALUE; + ForgeHooksClient.onTextureStitchedPre(this); + cpw.mods.fml.common.ProgressManager.ProgressBar bar = cpw.mods.fml.common.ProgressManager.push("Texture stitching", this.field_110574_e.size()); Iterator iterator = this.field_110574_e.entrySet().iterator(); TextureAtlasSprite textureatlassprite; - -@@ -106,6 +110,16 @@ - textureatlassprite = (TextureAtlasSprite)entry.getValue(); +@@ -108,6 +112,16 @@ ResourceLocation resourcelocation1 = this.func_147634_a(resourcelocation, 0); + bar.step(resourcelocation1.func_110623_a()); + if (textureatlassprite.hasCustomLoader(p_110571_1_, resourcelocation)) + { @@ -40,15 +40,15 @@ try { IResource iresource = p_110571_1_.func_110536_a(resourcelocation1); -@@ -276,6 +290,7 @@ +@@ -286,6 +300,7 @@ textureatlassprite = (TextureAtlasSprite)iterator2.next(); textureatlassprite.func_94217_a(this.field_94249_f); } + ForgeHooksClient.onTextureStitchedPost(this); + cpw.mods.fml.common.ProgressManager.pop(bar); } - private ResourceLocation func_147634_a(ResourceLocation p_147634_1_, int p_147634_2_) -@@ -349,7 +364,7 @@ +@@ -360,7 +375,7 @@ { throw new IllegalArgumentException("Name cannot be null!"); } @@ -57,7 +57,7 @@ { Object object = (TextureAtlasSprite)this.field_110574_e.get(p_94245_1_); -@@ -405,4 +420,37 @@ +@@ -416,4 +431,37 @@ { this.field_147637_k = p_147632_1_; } From 66a4db5fa0f6c5d4d3ee6420068e32930b48d5e1 Mon Sep 17 00:00:00 2001 From: cpw Date: Sat, 25 Apr 2015 00:47:09 -0400 Subject: [PATCH 38/48] MinecraftForge/FML@4fe7b469b5ba156d4a786cd9e105b18cca7c271a Loading screen: logo rotation is now optional; initial support for animated textures - animation rate is fixed for now. MinecraftForge/FML@31ae43590a2ba771d69b6c6513bcd5fe87ae8f8f Fix trying to close the screen during error. --- fml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fml b/fml index ef5f80975..31ae43590 160000 --- a/fml +++ b/fml @@ -1 +1 @@ -Subproject commit ef5f809752e87e369235e98a63027e9347185cd9 +Subproject commit 31ae43590a2ba771d69b6c6513bcd5fe87ae8f8f From 63e71af22939f43cd404447b5bcbddfdeaa3483e Mon Sep 17 00:00:00 2001 From: cpw Date: Sat, 25 Apr 2015 01:34:25 -0400 Subject: [PATCH 39/48] MinecraftForge/FML@94821fac98e64d9b8ad7434ed23a621850a8e11c Add a config file that lets you add additional soft dependencies at runtime - injectedDependencies.json --- fml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fml b/fml index 31ae43590..94821fac9 160000 --- a/fml +++ b/fml @@ -1 +1 @@ -Subproject commit 31ae43590a2ba771d69b6c6513bcd5fe87ae8f8f +Subproject commit 94821fac98e64d9b8ad7434ed23a621850a8e11c From 37075d04372b80cc67ce52f2be4b576f7397ca83 Mon Sep 17 00:00:00 2001 From: cpw Date: Sat, 25 Apr 2015 15:06:20 -0400 Subject: [PATCH 40/48] MinecraftForge/FML@2ed00c4da0ee76eb15e28eb8ee2c07a3096155c2 Splash progress screen will not load in the presence of optifine anymore. --- fml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fml b/fml index 94821fac9..2ed00c4da 160000 --- a/fml +++ b/fml @@ -1 +1 @@ -Subproject commit 94821fac98e64d9b8ad7434ed23a621850a8e11c +Subproject commit 2ed00c4da0ee76eb15e28eb8ee2c07a3096155c2 From 1b1fbbb70df4481e6a2f5a6764e337a0ad79f702 Mon Sep 17 00:00:00 2001 From: cpw Date: Mon, 4 May 2015 09:26:09 -0400 Subject: [PATCH 41/48] MinecraftForge/FML@dda431353953457608c38aacb060ef82ddc88883 Revert "Merge pull request #650 from luacs1998/1.7.10" This undoes the seriously broken change from Sponge to support Mixins, that breaks a wide variety of coremods. Given the widespread incompatibility it introduces, it won't be re-added at 1.7.10. --- fml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fml b/fml index 02a5a58a1..dda431353 160000 --- a/fml +++ b/fml @@ -1 +1 @@ -Subproject commit 02a5a58a1cbb25cd3baecf1535950e4780b7810f +Subproject commit dda431353953457608c38aacb060ef82ddc88883 From 88a7c0b2337738526f789e37382e4b07ae1e9a71 Mon Sep 17 00:00:00 2001 From: RainWarrior Date: Mon, 4 May 2015 22:18:38 +0300 Subject: [PATCH 42/48] Updated FML: MinecraftForge/FML@2ed00c4da0ee76eb15e28eb8ee2c07a3096155c2 Splash progress screen will not load in the presence of optifine anymore. MinecraftForge/FML@adcf2247c69f68415033a3c0b2c527053733514c Loading screen: moved config file to the standard config directory; added the option to load textures from the custom resource pack MinecraftForge/FML@91338433fa74e782e237643632de2cc5e17ee280 Add classloader exclusion for ASM MinecraftForge/FML@7c10b93a2ded2799d41b73b67a2766c31e992d8a Synchronize the available libraries. Turns out we've been forcing a newer apache commons-lang(3.2.1) for a long time, also sync the dev guava - we've been forcing 17 for a long time too. Bumping commons-lang to 3.3.2 since that's what Mojang are shipping with 1.8. It has no observable ill effects Closes MinecraftForge/FML#651 MinecraftForge/FML@8ccfa24764a3f4854f5334c0da1224286175e13b Merge pull request MinecraftForge/FML#650 from luacs1998/1.7.10 MinecraftForge/FML@b2650a0bdb7d69010a55de518e76591a6c417e87 Optifine can tell us when they're ready for the new splash screen. MinecraftForge/FML@02a5a58a1cbb25cd3baecf1535950e4780b7810f Fix the ordering of the messages, so they make sense now. MinecraftForge/FML@dda431353953457608c38aacb060ef82ddc88883 Revert "Merge pull request MinecraftForge/FML#650 from luacs1998/1.7.10" This undoes the seriously broken change from Sponge to support Mixins, that breaks a wide variety of coremods. Given the widespread incompatibility it introduces, it won't be re-added at 1.7.10. MinecraftForge/FML@5dbb481732bf4bcf8b0c5c02806051a933e6587e Eliminated texture name allocation race condition MinecraftForge/FML@450b82ca0e13cf889a42eeb198b67115a4851031 Updated default forge logo to animated gif; reverted config folder resolution to Minecraft class due to Loader not being initialized at the point it's needed --- fml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fml b/fml index 94821fac9..450b82ca0 160000 --- a/fml +++ b/fml @@ -1 +1 @@ -Subproject commit 94821fac98e64d9b8ad7434ed23a621850a8e11c +Subproject commit 450b82ca0e13cf889a42eeb198b67115a4851031 From 4270f0fb4a7bf97888451b27e48f60d79ce10d1f Mon Sep 17 00:00:00 2001 From: cpw Date: Thu, 7 May 2015 14:24:14 -0400 Subject: [PATCH 43/48] MinecraftForge/FML@0b84b6aa297bdf6ab9f010e340f286442cb242dc Expose the state of the loader --- fml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fml b/fml index 450b82ca0..0b84b6aa2 160000 --- a/fml +++ b/fml @@ -1 +1 @@ -Subproject commit 450b82ca0e13cf889a42eeb198b67115a4851031 +Subproject commit 0b84b6aa297bdf6ab9f010e340f286442cb242dc From 5fe653cf82b7e1ab775836479acd32df56d107b4 Mon Sep 17 00:00:00 2001 From: cpw Date: Sat, 16 May 2015 12:55:15 -0400 Subject: [PATCH 44/48] Attempt to fix the slow loading problem. Instead of forcing the main thread to wait around on every call to processWindowMessages, we will simply skip it, if the mutex is already claimed by the display thread. This should fix slow loading issues seen by some with the new loading screen. --- .../java/cpw/mods/fml/client/FMLClientHandler.java | 10 ++++++---- .../main/java/cpw/mods/fml/client/SplashProgress.java | 11 +++++++++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/fml/src/main/java/cpw/mods/fml/client/FMLClientHandler.java b/fml/src/main/java/cpw/mods/fml/client/FMLClientHandler.java index 5a41a7245..53b7f3cb8 100644 --- a/fml/src/main/java/cpw/mods/fml/client/FMLClientHandler.java +++ b/fml/src/main/java/cpw/mods/fml/client/FMLClientHandler.java @@ -1003,9 +1003,11 @@ public class FMLClientHandler implements IFMLSidedHandler public void processWindowMessages() { // workaround for windows requiring messages being processed on the main thread - if(LWJGLUtil.getPlatform() == LWJGLUtil.PLATFORM_WINDOWS) - { - Display.processMessages(); - } + if (LWJGLUtil.getPlatform() != LWJGLUtil.PLATFORM_WINDOWS) return; + // If we can't grab the mutex, the update call is blocked, probably in native code, just skip it and carry on + // We'll get another go next time + if (!SplashProgress.mutex.tryAcquire()) return; + Display.processMessages(); + SplashProgress.mutex.release(); } } diff --git a/fml/src/main/java/cpw/mods/fml/client/SplashProgress.java b/fml/src/main/java/cpw/mods/fml/client/SplashProgress.java index 62e672aed..d52154d0f 100644 --- a/fml/src/main/java/cpw/mods/fml/client/SplashProgress.java +++ b/fml/src/main/java/cpw/mods/fml/client/SplashProgress.java @@ -13,6 +13,7 @@ import java.lang.Thread.UncaughtExceptionHandler; import java.nio.IntBuffer; import java.util.Iterator; import java.util.Properties; +import java.util.concurrent.Semaphore; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; @@ -81,6 +82,7 @@ public class SplashProgress private static int barBorderColor; private static int barColor; private static int barBackgroundColor; + static final Semaphore mutex = new Semaphore(1); private static String getString(String name, String def) { @@ -297,7 +299,16 @@ public class SplashProgress glEnd(); glDisable(GL_TEXTURE_2D); + // We use mutex to indicate safely to the main thread that we're taking the display global lock + // So the main thread can skip processing messages while we're updating. + // There are system setups where this call can pause for a while, because the GL implementation + // is trying to impose a framerate or other thing is occurring. Without the mutex, the main + // thread would delay waiting for the same global display lock + mutex.acquireUninterruptibly(); Display.update(); + // As soon as we're done, we release the mutex. The other thread can now ping the processmessages + // call as often as it wants until we get get back here again + mutex.release(); if(pause) { clearGL(); From 686db5e5eb53fd4ca29e8da40312891d872a36ec Mon Sep 17 00:00:00 2001 From: cpw Date: Sat, 16 May 2015 13:43:35 -0400 Subject: [PATCH 45/48] Hardcode the FML version in-game as a specific value. --- fml/src/main/java/cpw/mods/fml/common/Loader.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fml/src/main/java/cpw/mods/fml/common/Loader.java b/fml/src/main/java/cpw/mods/fml/common/Loader.java index 3612faf96..006af1b15 100644 --- a/fml/src/main/java/cpw/mods/fml/common/Loader.java +++ b/fml/src/main/java/cpw/mods/fml/common/Loader.java @@ -620,7 +620,7 @@ public class Loader public String getFMLVersionString() { - return String.format("%s.%s.%s.%s", major, minor, rev, build); + return "7.10.99.99"; } public ClassLoader getModClassLoader() From 3bbf5c04a61882fee1abe25ab0cfb822a606cc6d Mon Sep 17 00:00:00 2001 From: cpw Date: Sun, 17 May 2015 10:11:41 -0400 Subject: [PATCH 46/48] Strip control codes in progress bar messages. They cause crashes sometimes. --- .../main/java/cpw/mods/fml/client/FMLClientHandler.java | 7 +++++++ .../main/java/cpw/mods/fml/common/FMLCommonHandler.java | 5 +++++ .../main/java/cpw/mods/fml/common/IFMLSidedHandler.java | 2 ++ .../main/java/cpw/mods/fml/common/ProgressManager.java | 2 +- .../main/java/cpw/mods/fml/server/FMLServerHandler.java | 8 +++++++- 5 files changed, 22 insertions(+), 2 deletions(-) diff --git a/fml/src/main/java/cpw/mods/fml/client/FMLClientHandler.java b/fml/src/main/java/cpw/mods/fml/client/FMLClientHandler.java index 53b7f3cb8..73dc9a694 100644 --- a/fml/src/main/java/cpw/mods/fml/client/FMLClientHandler.java +++ b/fml/src/main/java/cpw/mods/fml/client/FMLClientHandler.java @@ -58,6 +58,7 @@ import net.minecraft.network.NetworkManager; import net.minecraft.network.ServerStatusResponse; import net.minecraft.server.MinecraftServer; import net.minecraft.util.ResourceLocation; +import net.minecraft.util.StringUtils; import net.minecraft.world.WorldSettings; import net.minecraft.world.storage.SaveFormatOld; @@ -1010,4 +1011,10 @@ public class FMLClientHandler implements IFMLSidedHandler Display.processMessages(); SplashProgress.mutex.release(); } + + @Override + public String stripSpecialChars(String message) + { + return StringUtils.stripControlCodes(message); + } } diff --git a/fml/src/main/java/cpw/mods/fml/common/FMLCommonHandler.java b/fml/src/main/java/cpw/mods/fml/common/FMLCommonHandler.java index ed4e61382..b770baf44 100644 --- a/fml/src/main/java/cpw/mods/fml/common/FMLCommonHandler.java +++ b/fml/src/main/java/cpw/mods/fml/common/FMLCommonHandler.java @@ -632,4 +632,9 @@ public class FMLCommonHandler Runtime.getRuntime().exit(exitCode); } } + + public String stripSpecialChars(String message) + { + return sidedDelegate != null ? sidedDelegate.stripSpecialChars(message) : message; + } } diff --git a/fml/src/main/java/cpw/mods/fml/common/IFMLSidedHandler.java b/fml/src/main/java/cpw/mods/fml/common/IFMLSidedHandler.java index abc08bc42..5daadbb11 100644 --- a/fml/src/main/java/cpw/mods/fml/common/IFMLSidedHandler.java +++ b/fml/src/main/java/cpw/mods/fml/common/IFMLSidedHandler.java @@ -63,4 +63,6 @@ public interface IFMLSidedHandler void allowLogins(); void processWindowMessages(); + + String stripSpecialChars(String message); } diff --git a/fml/src/main/java/cpw/mods/fml/common/ProgressManager.java b/fml/src/main/java/cpw/mods/fml/common/ProgressManager.java index a2a7194c8..7808c3d20 100644 --- a/fml/src/main/java/cpw/mods/fml/common/ProgressManager.java +++ b/fml/src/main/java/cpw/mods/fml/common/ProgressManager.java @@ -71,7 +71,7 @@ public class ProgressManager { if(step >= steps) throw new IllegalStateException("too much steps for ProgressBar " + title); step++; - this.message = message; + this.message = FMLCommonHandler.instance().stripSpecialChars(message); FMLCommonHandler.instance().processWindowMessages(); } diff --git a/fml/src/main/java/cpw/mods/fml/server/FMLServerHandler.java b/fml/src/main/java/cpw/mods/fml/server/FMLServerHandler.java index 0a362de43..d8dc4e9b1 100644 --- a/fml/src/main/java/cpw/mods/fml/server/FMLServerHandler.java +++ b/fml/src/main/java/cpw/mods/fml/server/FMLServerHandler.java @@ -259,7 +259,7 @@ public class FMLServerHandler implements IFMLSidedHandler { return DedicatedServer.allowPlayerLogins; } - + @Override public void allowLogins() { DedicatedServer.allowPlayerLogins = true; @@ -270,4 +270,10 @@ public class FMLServerHandler implements IFMLSidedHandler { // NOOP } + + @Override + public String stripSpecialChars(String message) + { + return message; + } } From 06398fa25990b458ee3183e0cf9066a3a75f221e Mon Sep 17 00:00:00 2001 From: cpw Date: Sun, 17 May 2015 10:08:46 -0400 Subject: [PATCH 47/48] Clean up transformers a bit. Can't use COMPUTE_FRAMES even though it's required - the game refuses to even run if I do. Note for j8: when we force Java8 classes, all coremods will need a thorough overhaul - the current way we do things is not sustainable when Java8 becomes the universal norm. --- .../common/asm/transformers/EventSubscriptionTransformer.java | 2 +- .../cpw/mods/fml/common/asm/transformers/MarkerTransformer.java | 2 +- .../cpw/mods/fml/common/asm/transformers/SideTransformer.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/fml/src/main/java/cpw/mods/fml/common/asm/transformers/EventSubscriptionTransformer.java b/fml/src/main/java/cpw/mods/fml/common/asm/transformers/EventSubscriptionTransformer.java index fd77ebcbc..0062ab829 100644 --- a/fml/src/main/java/cpw/mods/fml/common/asm/transformers/EventSubscriptionTransformer.java +++ b/fml/src/main/java/cpw/mods/fml/common/asm/transformers/EventSubscriptionTransformer.java @@ -65,7 +65,7 @@ public class EventSubscriptionTransformer implements IClassTransformer { if (buildEvents(classNode)) { - ClassWriter cw = new ClassWriter(COMPUTE_MAXS | COMPUTE_FRAMES); + ClassWriter cw = new ClassWriter(COMPUTE_FRAMES); classNode.accept(cw); return cw.toByteArray(); } diff --git a/fml/src/main/java/cpw/mods/fml/common/asm/transformers/MarkerTransformer.java b/fml/src/main/java/cpw/mods/fml/common/asm/transformers/MarkerTransformer.java index 8f05923dc..30abc68e6 100644 --- a/fml/src/main/java/cpw/mods/fml/common/asm/transformers/MarkerTransformer.java +++ b/fml/src/main/java/cpw/mods/fml/common/asm/transformers/MarkerTransformer.java @@ -100,7 +100,7 @@ public class MarkerTransformer implements IClassTransformer @Override public byte[] transform(String name, String transformedName, byte[] bytes) { - if (bytes == null) { return null; } + if (bytes == null) { return null; } if (!markers.containsKey(name)) { return bytes; } ClassNode classNode = new ClassNode(); diff --git a/fml/src/main/java/cpw/mods/fml/common/asm/transformers/SideTransformer.java b/fml/src/main/java/cpw/mods/fml/common/asm/transformers/SideTransformer.java index 3f45115ee..4904613aa 100644 --- a/fml/src/main/java/cpw/mods/fml/common/asm/transformers/SideTransformer.java +++ b/fml/src/main/java/cpw/mods/fml/common/asm/transformers/SideTransformer.java @@ -35,7 +35,7 @@ public class SideTransformer implements IClassTransformer @Override public byte[] transform(String name, String transformedName, byte[] bytes) { - if (bytes == null) { return null; } + if (bytes == null) { return null; } ClassNode classNode = new ClassNode(); ClassReader classReader = new ClassReader(bytes); From bd6630810f3d4e04438ca77099b5fc19cf474b9c Mon Sep 17 00:00:00 2001 From: cpw Date: Sat, 30 May 2015 14:07:54 -0400 Subject: [PATCH 48/48] Add in an ItemStackHolder - a way to inject ItemStacks without having to have complex lookup code everywhere. Example: https://gist.github.com/cpw/9af398451a20459ac263 --- .../main/java/cpw/mods/fml/common/Loader.java | 4 + .../fml/common/registry/GameRegistry.java | 72 ++++++++++++++++ .../registry/ItemStackHolderInjector.java | 80 ++++++++++++++++++ .../common/registry/ItemStackHolderRef.java | 84 +++++++++++++++++++ 4 files changed, 240 insertions(+) create mode 100644 fml/src/main/java/cpw/mods/fml/common/registry/ItemStackHolderInjector.java create mode 100644 fml/src/main/java/cpw/mods/fml/common/registry/ItemStackHolderRef.java diff --git a/fml/src/main/java/cpw/mods/fml/common/Loader.java b/fml/src/main/java/cpw/mods/fml/common/Loader.java index 006af1b15..4de8f74ad 100644 --- a/fml/src/main/java/cpw/mods/fml/common/Loader.java +++ b/fml/src/main/java/cpw/mods/fml/common/Loader.java @@ -75,6 +75,7 @@ import cpw.mods.fml.common.functions.ArtifactVersionNameFunction; import cpw.mods.fml.common.functions.ModIdFunction; import cpw.mods.fml.common.registry.GameData; import cpw.mods.fml.common.registry.GameRegistry.Type; +import cpw.mods.fml.common.registry.ItemStackHolderInjector; import cpw.mods.fml.common.registry.ObjectHolderRegistry; import cpw.mods.fml.common.toposort.ModSorter; import cpw.mods.fml.common.toposort.ModSortingException; @@ -530,8 +531,10 @@ public class Loader return; } ObjectHolderRegistry.INSTANCE.findObjectHolders(discoverer.getASMTable()); + ItemStackHolderInjector.INSTANCE.findHolders(discoverer.getASMTable()); modController.distributeStateMessage(LoaderState.PREINITIALIZATION, discoverer.getASMTable(), canonicalConfigDir); ObjectHolderRegistry.INSTANCE.applyObjectHolders(); + ItemStackHolderInjector.INSTANCE.inject(); modController.transition(LoaderState.INITIALIZATION, false); progressBar.step("Initializing Minecraft Engine"); } @@ -714,6 +717,7 @@ public class Loader progressBar.step("Initializing mods Phase 3"); modController.transition(LoaderState.POSTINITIALIZATION, false); modController.distributeStateMessage(FMLInterModComms.IMCEvent.class); + ItemStackHolderInjector.INSTANCE.inject(); modController.distributeStateMessage(LoaderState.POSTINITIALIZATION); progressBar.step("Finishing up"); modController.transition(LoaderState.AVAILABLE, false); diff --git a/fml/src/main/java/cpw/mods/fml/common/registry/GameRegistry.java b/fml/src/main/java/cpw/mods/fml/common/registry/GameRegistry.java index 62c45bf8a..4b84fe3a9 100644 --- a/fml/src/main/java/cpw/mods/fml/common/registry/GameRegistry.java +++ b/fml/src/main/java/cpw/mods/fml/common/registry/GameRegistry.java @@ -32,6 +32,10 @@ import net.minecraft.item.ItemStack; import net.minecraft.item.crafting.CraftingManager; import net.minecraft.item.crafting.FurnaceRecipes; import net.minecraft.item.crafting.IRecipe; +import net.minecraft.nbt.JsonToNBT; +import net.minecraft.nbt.NBTBase; +import net.minecraft.nbt.NBTException; +import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.world.World; import net.minecraft.world.chunk.IChunkProvider; @@ -39,6 +43,8 @@ import net.minecraft.world.chunk.IChunkProvider; import org.apache.logging.log4j.Level; import com.google.common.base.Objects; +import com.google.common.base.Strings; +import com.google.common.base.Throwables; import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; import com.google.common.collect.Maps; @@ -476,4 +482,70 @@ public class GameRegistry */ String value(); } + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.FIELD) + public @interface ItemStackHolder + { + /** + * The registry name of the item being looked up. + * @return The registry name + */ + public String value(); + + /** + * The metadata or damage value for the itemstack, defaults to 0. + * @return the metadata value + */ + public int meta() default 0; + + /** + * The string serialized nbt value for the itemstack. Defaults to empty for no nbt. + * + * @return a nbt string + */ + public String nbt() default ""; + } + + /** + * Makes an {@link ItemStack} based on the itemName reference, with supplied meta, stackSize and nbt, if possible + * + * Will return null if the item doesn't exist (because it's not from a loaded mod for example) + * Will throw a {@link RuntimeException} if the nbtString is invalid for use in an {@link ItemStack} + * + * @param itemName a registry name reference + * @param meta the meta + * @param stackSize the stack size + * @param nbtString an nbt stack as a string, will be processed by {@link JsonToNBT} + * @return a new itemstack + */ + public static ItemStack makeItemStack(String itemName, int meta, int stackSize, String nbtString) + { + if (itemName == null) throw new IllegalArgumentException("The itemName cannot be null"); + Item item = GameData.getItemRegistry().getObject(itemName); + if (item == null) { + FMLLog.getLogger().log(Level.TRACE, "Unable to find item with name {}", itemName); + return null; + } + ItemStack is = new ItemStack(item,1,meta); + if (!Strings.isNullOrEmpty(nbtString)) { + NBTBase nbttag = null; + try + { + nbttag = JsonToNBT.func_150315_a(nbtString); + } catch (NBTException e) + { + FMLLog.getLogger().log(Level.WARN, "Encountered an exception parsing ItemStack NBT string {}", nbtString, e); + throw Throwables.propagate(e); + } + if (!(nbttag instanceof NBTTagCompound)) { + FMLLog.getLogger().log(Level.WARN, "Unexpected NBT string - multiple values {}", nbtString); + throw new RuntimeException("Invalid NBT JSON"); + } else { + is.setTagCompound((NBTTagCompound) nbttag); + } + } + return is; + } + } diff --git a/fml/src/main/java/cpw/mods/fml/common/registry/ItemStackHolderInjector.java b/fml/src/main/java/cpw/mods/fml/common/registry/ItemStackHolderInjector.java new file mode 100644 index 000000000..fe8b47e89 --- /dev/null +++ b/fml/src/main/java/cpw/mods/fml/common/registry/ItemStackHolderInjector.java @@ -0,0 +1,80 @@ +package cpw.mods.fml.common.registry; + +import java.lang.reflect.Field; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.logging.log4j.Level; + +import com.google.common.base.Throwables; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; + +import cpw.mods.fml.common.FMLLog; +import cpw.mods.fml.common.discovery.ASMDataTable; +import cpw.mods.fml.common.discovery.ASMDataTable.ASMData; + +public enum ItemStackHolderInjector +{ + INSTANCE; + + private List itemStackHolders = Lists.newArrayList(); + + public void inject() { + FMLLog.getLogger().log(Level.INFO, "Injecting itemstacks"); + for (ItemStackHolderRef ishr: itemStackHolders) { + ishr.apply(); + } + FMLLog.getLogger().log(Level.INFO, "Itemstack injection complete"); + } + + public void findHolders(ASMDataTable table) { + FMLLog.info("Identifying ItemStackHolder annotations"); + Set allItemStackHolders = table.getAll(GameRegistry.ItemStackHolder.class.getName()); + Map> classCache = Maps.newHashMap(); + for (ASMData data : allItemStackHolders) + { + String className = data.getClassName(); + String annotationTarget = data.getObjectName(); + String value = (String) data.getAnnotationInfo().get("value"); + int meta = data.getAnnotationInfo().containsKey("meta") ? (Integer) data.getAnnotationInfo().get("meta") : 0; + String nbt = data.getAnnotationInfo().containsKey("nbt") ? (String) data.getAnnotationInfo().get("nbt") : ""; + addHolder(classCache, className, annotationTarget, value, meta, nbt); + } + FMLLog.info("Found %d ItemStackHolder annotations", allItemStackHolders.size()); + + } + + private void addHolder(Map> classCache, String className, String annotationTarget, String value, Integer meta, String nbt) + { + Class clazz; + if (classCache.containsKey(className)) + { + clazz = classCache.get(className); + } + else + { + try + { + clazz = Class.forName(className, true, getClass().getClassLoader()); + classCache.put(className, clazz); + } + catch (Exception ex) + { + // unpossible? + throw Throwables.propagate(ex); + } + } + try + { + Field f = clazz.getField(annotationTarget); + itemStackHolders.add(new ItemStackHolderRef(f, value, meta, nbt)); + } + catch (Exception ex) + { + // unpossible? + throw Throwables.propagate(ex); + } + } +} diff --git a/fml/src/main/java/cpw/mods/fml/common/registry/ItemStackHolderRef.java b/fml/src/main/java/cpw/mods/fml/common/registry/ItemStackHolderRef.java new file mode 100644 index 000000000..18f9adcaa --- /dev/null +++ b/fml/src/main/java/cpw/mods/fml/common/registry/ItemStackHolderRef.java @@ -0,0 +1,84 @@ +package cpw.mods.fml.common.registry; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +import net.minecraft.item.ItemStack; + +import org.apache.logging.log4j.Level; + +import com.google.common.base.Throwables; + +import cpw.mods.fml.common.FMLLog; +import cpw.mods.fml.common.registry.GameRegistry.ItemStackHolder; + + +/** + * Internal class used in tracking {@link ItemStackHolder} references + * + * @author cpw + * + */ +class ItemStackHolderRef { + private Field field; + private String itemName; + private int meta; + private String serializednbt; + + + ItemStackHolderRef(Field field, String itemName, int meta, String serializednbt) + { + this.field = field; + this.itemName = itemName; + this.meta = meta; + this.serializednbt = serializednbt; + makeWritable(field); + } + + private static Field modifiersField; + private static Object reflectionFactory; + private static Method newFieldAccessor; + private static Method fieldAccessorSet; + private static void makeWritable(Field f) + { + try + { + if (modifiersField == null) + { + Method getReflectionFactory = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("getReflectionFactory"); + reflectionFactory = getReflectionFactory.invoke(null); + newFieldAccessor = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("newFieldAccessor", Field.class, boolean.class); + fieldAccessorSet = Class.forName("sun.reflect.FieldAccessor").getDeclaredMethod("set", Object.class, Object.class); + modifiersField = Field.class.getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + } + modifiersField.setInt(f, f.getModifiers() & ~Modifier.FINAL); + } catch (Exception e) + { + throw Throwables.propagate(e); + } + } + + public void apply() + { + ItemStack is; + try + { + is = GameRegistry.makeItemStack(itemName, meta, 1, serializednbt); + } catch (RuntimeException e) + { + FMLLog.getLogger().log(Level.ERROR, "Caught exception processing itemstack {},{},{} in annotation at {}.{}", itemName, meta, serializednbt,field.getClass().getName(),field.getName()); + throw e; + } + try + { + Object fieldAccessor = newFieldAccessor.invoke(reflectionFactory, field, false); + fieldAccessorSet.invoke(fieldAccessor, null, is); + } + catch (Exception e) + { + FMLLog.getLogger().log(Level.WARN, "Unable to set {} with value {},{},{}", this.field, this.itemName, this.meta, this.serializednbt); + } + } +}