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;