Merge branch '1.7.10' - imports all the fluid fixups and other stuff from 1.7 into 1.8
Conflicts: fml/src/main/java/net/minecraftforge/fml/common/FMLCommonHandler.java fml/src/main/java/net/minecraftforge/fml/common/Loader.java patches/minecraft/net/minecraft/client/Minecraft.java.patch patches/minecraft/net/minecraft/client/renderer/texture/TextureMap.java.patch patches/minecraft/net/minecraft/item/ItemArmor.java.patch patches/minecraft/net/minecraft/nbt/CompressedStreamTools.java.patch patches/minecraft/net/minecraft/nbt/NBTTagCompound.java.patch patches/minecraft/net/minecraft/nbt/NBTTagList.java.patch patches/minecraft/net/minecraft/world/World.java.patch patches/minecraft/net/minecraft/world/WorldProvider.java.patch src/main/java/net/minecraftforge/common/ForgeVersion.java src/main/java/net/minecraftforge/common/network/ForgeMessage.java src/main/java/net/minecraftforge/fluids/BlockFluidBase.java src/main/java/net/minecraftforge/fluids/FluidContainerRegistry.java src/main/java/net/minecraftforge/fluids/FluidRegistry.java src/main/java/net/minecraftforge/oredict/OreDictionary.java
This commit is contained in:
commit
d02636213a
25 changed files with 722 additions and 135 deletions
|
@ -66,6 +66,7 @@ import net.minecraft.network.status.INetHandlerStatusServer;
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.util.IThreadListener;
|
import net.minecraft.util.IThreadListener;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
import net.minecraft.util.StringUtils;
|
||||||
import net.minecraft.world.WorldSettings;
|
import net.minecraft.world.WorldSettings;
|
||||||
import net.minecraft.world.storage.SaveFormatOld;
|
import net.minecraft.world.storage.SaveFormatOld;
|
||||||
import net.minecraftforge.fml.client.registry.RenderingRegistry;
|
import net.minecraftforge.fml.client.registry.RenderingRegistry;
|
||||||
|
@ -991,9 +992,17 @@ public class FMLClientHandler implements IFMLSidedHandler
|
||||||
public void processWindowMessages()
|
public void processWindowMessages()
|
||||||
{
|
{
|
||||||
// workaround for windows requiring messages being processed on the main thread
|
// workaround for windows requiring messages being processed on the main thread
|
||||||
if(LWJGLUtil.getPlatform() == LWJGLUtil.PLATFORM_WINDOWS)
|
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
|
||||||
Display.processMessages();
|
// We'll get another go next time
|
||||||
}
|
if (!SplashProgress.mutex.tryAcquire()) return;
|
||||||
|
Display.processMessages();
|
||||||
|
SplashProgress.mutex.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String stripSpecialChars(String message)
|
||||||
|
{
|
||||||
|
return StringUtils.stripControlCodes(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,6 +63,7 @@ import java.lang.Thread.UncaughtExceptionHandler;
|
||||||
import java.nio.IntBuffer;
|
import java.nio.IntBuffer;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
import java.util.concurrent.Semaphore;
|
||||||
import java.util.concurrent.locks.Lock;
|
import java.util.concurrent.locks.Lock;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
|
@ -131,6 +132,7 @@ public class SplashProgress
|
||||||
private static int barBorderColor;
|
private static int barBorderColor;
|
||||||
private static int barColor;
|
private static int barColor;
|
||||||
private static int barBackgroundColor;
|
private static int barBackgroundColor;
|
||||||
|
static final Semaphore mutex = new Semaphore(1);
|
||||||
|
|
||||||
private static String getString(String name, String def)
|
private static String getString(String name, String def)
|
||||||
{
|
{
|
||||||
|
@ -352,7 +354,16 @@ public class SplashProgress
|
||||||
glEnd();
|
glEnd();
|
||||||
glDisable(GL_TEXTURE_2D);
|
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();
|
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)
|
if(pause)
|
||||||
{
|
{
|
||||||
clearGL();
|
clearGL();
|
||||||
|
|
|
@ -764,4 +764,8 @@ public class FMLCommonHandler
|
||||||
props.clear();
|
props.clear();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
public String stripSpecialChars(String message)
|
||||||
|
{
|
||||||
|
return sidedDelegate != null ? sidedDelegate.stripSpecialChars(message) : message;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,4 +64,6 @@ public interface IFMLSidedHandler
|
||||||
IThreadListener getWorldThread(INetHandler net);
|
IThreadListener getWorldThread(INetHandler net);
|
||||||
|
|
||||||
void processWindowMessages();
|
void processWindowMessages();
|
||||||
|
|
||||||
|
String stripSpecialChars(String message);
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@ import net.minecraftforge.fml.common.functions.ArtifactVersionNameFunction;
|
||||||
import net.minecraftforge.fml.common.functions.ModIdFunction;
|
import net.minecraftforge.fml.common.functions.ModIdFunction;
|
||||||
import net.minecraftforge.fml.common.registry.GameData;
|
import net.minecraftforge.fml.common.registry.GameData;
|
||||||
import net.minecraftforge.fml.common.registry.GameRegistry;
|
import net.minecraftforge.fml.common.registry.GameRegistry;
|
||||||
|
import net.minecraftforge.fml.common.registry.ItemStackHolderInjector;
|
||||||
import net.minecraftforge.fml.common.registry.ObjectHolderRegistry;
|
import net.minecraftforge.fml.common.registry.ObjectHolderRegistry;
|
||||||
import net.minecraftforge.fml.common.registry.GameRegistry.Type;
|
import net.minecraftforge.fml.common.registry.GameRegistry.Type;
|
||||||
import net.minecraftforge.fml.common.toposort.ModSorter;
|
import net.minecraftforge.fml.common.toposort.ModSorter;
|
||||||
|
@ -524,8 +525,10 @@ public class Loader
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ObjectHolderRegistry.INSTANCE.findObjectHolders(discoverer.getASMTable());
|
ObjectHolderRegistry.INSTANCE.findObjectHolders(discoverer.getASMTable());
|
||||||
|
ItemStackHolderInjector.INSTANCE.findHolders(discoverer.getASMTable());
|
||||||
modController.distributeStateMessage(LoaderState.PREINITIALIZATION, discoverer.getASMTable(), canonicalConfigDir);
|
modController.distributeStateMessage(LoaderState.PREINITIALIZATION, discoverer.getASMTable(), canonicalConfigDir);
|
||||||
ObjectHolderRegistry.INSTANCE.applyObjectHolders();
|
ObjectHolderRegistry.INSTANCE.applyObjectHolders();
|
||||||
|
ItemStackHolderInjector.INSTANCE.inject();
|
||||||
modController.transition(LoaderState.INITIALIZATION, false);
|
modController.transition(LoaderState.INITIALIZATION, false);
|
||||||
progressBar.step("Initializing Minecraft Engine");
|
progressBar.step("Initializing Minecraft Engine");
|
||||||
}
|
}
|
||||||
|
@ -614,7 +617,7 @@ public class Loader
|
||||||
|
|
||||||
public String getFMLVersionString()
|
public String getFMLVersionString()
|
||||||
{
|
{
|
||||||
return String.format("%s.%s.%s.%s", major, minor, rev, build);
|
return "8.0.99.99";
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClassLoader getModClassLoader()
|
public ClassLoader getModClassLoader()
|
||||||
|
@ -708,6 +711,7 @@ public class Loader
|
||||||
progressBar.step("Initializing mods Phase 3");
|
progressBar.step("Initializing mods Phase 3");
|
||||||
modController.transition(LoaderState.POSTINITIALIZATION, false);
|
modController.transition(LoaderState.POSTINITIALIZATION, false);
|
||||||
modController.distributeStateMessage(FMLInterModComms.IMCEvent.class);
|
modController.distributeStateMessage(FMLInterModComms.IMCEvent.class);
|
||||||
|
ItemStackHolderInjector.INSTANCE.inject();
|
||||||
modController.distributeStateMessage(LoaderState.POSTINITIALIZATION);
|
modController.distributeStateMessage(LoaderState.POSTINITIALIZATION);
|
||||||
progressBar.step("Finishing up");
|
progressBar.step("Finishing up");
|
||||||
modController.transition(LoaderState.AVAILABLE, false);
|
modController.transition(LoaderState.AVAILABLE, false);
|
||||||
|
|
|
@ -71,7 +71,7 @@ public class ProgressManager
|
||||||
{
|
{
|
||||||
if(step >= steps) throw new IllegalStateException("too much steps for ProgressBar " + title);
|
if(step >= steps) throw new IllegalStateException("too much steps for ProgressBar " + title);
|
||||||
step++;
|
step++;
|
||||||
this.message = message;
|
this.message = FMLCommonHandler.instance().stripSpecialChars(message);
|
||||||
FMLCommonHandler.instance().processWindowMessages();
|
FMLCommonHandler.instance().processWindowMessages();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,7 @@ public class EventSubscriptionTransformer implements IClassTransformer
|
||||||
{
|
{
|
||||||
if (buildEvents(classNode))
|
if (buildEvents(classNode))
|
||||||
{
|
{
|
||||||
ClassWriter cw = new ClassWriter(COMPUTE_MAXS | COMPUTE_FRAMES);
|
ClassWriter cw = new ClassWriter(COMPUTE_FRAMES);
|
||||||
classNode.accept(cw);
|
classNode.accept(cw);
|
||||||
return cw.toByteArray();
|
return cw.toByteArray();
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,7 +100,7 @@ public class MarkerTransformer implements IClassTransformer
|
||||||
@Override
|
@Override
|
||||||
public byte[] transform(String name, String transformedName, byte[] bytes)
|
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; }
|
if (!markers.containsKey(name)) { return bytes; }
|
||||||
|
|
||||||
ClassNode classNode = new ClassNode();
|
ClassNode classNode = new ClassNode();
|
||||||
|
|
|
@ -34,7 +34,7 @@ public class SideTransformer implements IClassTransformer
|
||||||
@Override
|
@Override
|
||||||
public byte[] transform(String name, String transformedName, byte[] bytes)
|
public byte[] transform(String name, String transformedName, byte[] bytes)
|
||||||
{
|
{
|
||||||
if (bytes == null) { return null; }
|
if (bytes == null) { return null; }
|
||||||
|
|
||||||
ClassNode classNode = new ClassNode();
|
ClassNode classNode = new ClassNode();
|
||||||
ClassReader classReader = new ClassReader(bytes);
|
ClassReader classReader = new ClassReader(bytes);
|
||||||
|
|
|
@ -32,6 +32,10 @@ import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.item.crafting.CraftingManager;
|
import net.minecraft.item.crafting.CraftingManager;
|
||||||
import net.minecraft.item.crafting.FurnaceRecipes;
|
import net.minecraft.item.crafting.FurnaceRecipes;
|
||||||
import net.minecraft.item.crafting.IRecipe;
|
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.tileentity.TileEntity;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
@ -47,6 +51,8 @@ import net.minecraftforge.fml.common.ObfuscationReflectionHelper;
|
||||||
import org.apache.logging.log4j.Level;
|
import org.apache.logging.log4j.Level;
|
||||||
|
|
||||||
import com.google.common.base.Objects;
|
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.ImmutableList;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
|
@ -451,4 +457,70 @@ public class GameRegistry
|
||||||
*/
|
*/
|
||||||
String value();
|
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_180713_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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
package net.minecraftforge.fml.common.registry;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import net.minecraftforge.fml.common.FMLLog;
|
||||||
|
import net.minecraftforge.fml.common.discovery.ASMDataTable;
|
||||||
|
import net.minecraftforge.fml.common.discovery.ASMDataTable.ASMData;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.Level;
|
||||||
|
|
||||||
|
import com.google.common.base.Throwables;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
|
||||||
|
|
||||||
|
public enum ItemStackHolderInjector
|
||||||
|
{
|
||||||
|
INSTANCE;
|
||||||
|
|
||||||
|
private List<ItemStackHolderRef> 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<ASMData> allItemStackHolders = table.getAll(GameRegistry.ItemStackHolder.class.getName());
|
||||||
|
Map<String, Class<?>> 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<String, Class<?>> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
package net.minecraftforge.fml.common.registry;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraftforge.fml.common.FMLLog;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.Level;
|
||||||
|
|
||||||
|
import com.google.common.base.Throwables;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -272,4 +272,10 @@ public class FMLServerHandler implements IFMLSidedHandler
|
||||||
{
|
{
|
||||||
// NOOP
|
// NOOP
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String stripSpecialChars(String message)
|
||||||
|
{
|
||||||
|
return message;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
boolean flag1 = (c0 == 0 || j == -1 || this.field_78293_l) && p_78255_2_;
|
boolean flag1 = (c0 == 0 || j == -1 || this.field_78293_l) && p_78255_2_;
|
||||||
|
|
||||||
if (flag1)
|
if (flag1)
|
||||||
@@ -583,11 +584,6 @@
|
@@ -592,11 +593,6 @@
|
||||||
int j = this.field_78287_e[p_78263_1_] >>> 4;
|
int j = this.field_78287_e[p_78263_1_] >>> 4;
|
||||||
int k = this.field_78287_e[p_78263_1_] & 15;
|
int k = this.field_78287_e[p_78263_1_] & 15;
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ public class FMLForgePlugin implements IFMLLoadingPlugin
|
||||||
@Override
|
@Override
|
||||||
public String[] getASMTransformerClass()
|
public String[] getASMTransformerClass()
|
||||||
{
|
{
|
||||||
return new String[0];
|
return new String[] { "net.minecraftforge.classloading.FluidIdTransformer" };
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
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.MethodInsnNode;
|
||||||
|
import org.objectweb.asm.tree.MethodNode;
|
||||||
|
|
||||||
|
import net.minecraftforge.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<AbstractInsnNode> 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -663,7 +663,7 @@ public class ForgeChunkManager
|
||||||
throw new RuntimeException("Invalid ticket request");
|
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)
|
if (tickets.get(world).get(modId).size() >= allowedCount)
|
||||||
{
|
{
|
||||||
|
|
|
@ -26,6 +26,7 @@ import net.minecraftforge.classloading.FMLForgePlugin;
|
||||||
import net.minecraftforge.common.config.Configuration;
|
import net.minecraftforge.common.config.Configuration;
|
||||||
import net.minecraftforge.common.config.Property;
|
import net.minecraftforge.common.config.Property;
|
||||||
import net.minecraftforge.common.network.ForgeNetworkHandler;
|
import net.minecraftforge.common.network.ForgeNetworkHandler;
|
||||||
|
import net.minecraftforge.fluids.FluidRegistry;
|
||||||
import net.minecraftforge.oredict.OreDictionary;
|
import net.minecraftforge.oredict.OreDictionary;
|
||||||
import net.minecraftforge.oredict.RecipeSorter;
|
import net.minecraftforge.oredict.RecipeSorter;
|
||||||
import net.minecraftforge.server.command.ForgeCommand;
|
import net.minecraftforge.server.command.ForgeCommand;
|
||||||
|
@ -60,7 +61,6 @@ public class ForgeModContainer extends DummyModContainer implements WorldAccessC
|
||||||
public static boolean removeErroringEntities = false;
|
public static boolean removeErroringEntities = false;
|
||||||
public static boolean removeErroringTileEntities = false;
|
public static boolean removeErroringTileEntities = false;
|
||||||
public static boolean disableStitchedFileSaving = false;
|
public static boolean disableStitchedFileSaving = false;
|
||||||
public static boolean forceDuplicateFluidBlockCrash = true;
|
|
||||||
public static boolean fullBoundingBoxLadders = false;
|
public static boolean fullBoundingBoxLadders = false;
|
||||||
public static double zombieSummonBaseChance = 0.1;
|
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 };
|
public static int[] blendRanges = { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34 };
|
||||||
|
@ -68,6 +68,7 @@ public class ForgeModContainer extends DummyModContainer implements WorldAccessC
|
||||||
public static boolean shouldSortRecipies = true;
|
public static boolean shouldSortRecipies = true;
|
||||||
public static boolean disableVersionCheck = false;
|
public static boolean disableVersionCheck = false;
|
||||||
public static int defaultSpawnFuzz = 20;
|
public static int defaultSpawnFuzz = 20;
|
||||||
|
public static boolean defaultHasSpawnFuzz = true;
|
||||||
|
|
||||||
private static Configuration config;
|
private static Configuration config;
|
||||||
|
|
||||||
|
@ -157,17 +158,6 @@ public class ForgeModContainer extends DummyModContainer implements WorldAccessC
|
||||||
shouldSortRecipies = prop.getBoolean(shouldSortRecipies);
|
shouldSortRecipies = prop.getBoolean(shouldSortRecipies);
|
||||||
propOrder.add(prop.getName());
|
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 = 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.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);
|
prop.setLanguageKey("forge.configgui.removeErroringEntities").setRequiresWorldRestart(true);
|
||||||
|
@ -225,6 +215,12 @@ public class ForgeModContainer extends DummyModContainer implements WorldAccessC
|
||||||
defaultSpawnFuzz = prop.getInt(20);
|
defaultSpawnFuzz = prop.getInt(20);
|
||||||
propOrder.add(prop.getName());
|
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);
|
config.setCategoryPropertyOrder(CATEGORY_GENERAL, propOrder);
|
||||||
|
|
||||||
if (config.hasChanged())
|
if (config.hasChanged())
|
||||||
|
@ -280,7 +276,7 @@ public class ForgeModContainer extends DummyModContainer implements WorldAccessC
|
||||||
MinecraftForge.EVENT_BUS.register(MinecraftForge.INTERNAL_HANDLER);
|
MinecraftForge.EVENT_BUS.register(MinecraftForge.INTERNAL_HANDLER);
|
||||||
ForgeChunkManager.captureConfig(evt.getModConfigurationDirectory());
|
ForgeChunkManager.captureConfig(evt.getModConfigurationDirectory());
|
||||||
FMLCommonHandler.instance().bus().register(this);
|
FMLCommonHandler.instance().bus().register(this);
|
||||||
|
|
||||||
if (!ForgeModContainer.disableVersionCheck)
|
if (!ForgeModContainer.disableVersionCheck)
|
||||||
{
|
{
|
||||||
ForgeVersion.startVersionCheck();
|
ForgeVersion.startVersionCheck();
|
||||||
|
@ -301,6 +297,7 @@ public class ForgeModContainer extends DummyModContainer implements WorldAccessC
|
||||||
{
|
{
|
||||||
RecipeSorter.sortCraftManager();
|
RecipeSorter.sortCraftManager();
|
||||||
}
|
}
|
||||||
|
FluidRegistry.validateFluidRegistry();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
|
@ -314,6 +311,7 @@ public class ForgeModContainer extends DummyModContainer implements WorldAccessC
|
||||||
NBTTagCompound forgeData = new NBTTagCompound();
|
NBTTagCompound forgeData = new NBTTagCompound();
|
||||||
NBTTagCompound dimData = DimensionManager.saveDimensionDataMap();
|
NBTTagCompound dimData = DimensionManager.saveDimensionDataMap();
|
||||||
forgeData.setTag("DimensionData", dimData);
|
forgeData.setTag("DimensionData", dimData);
|
||||||
|
FluidRegistry.writeDefaultFluidList(forgeData);
|
||||||
return forgeData;
|
return forgeData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -321,6 +319,7 @@ public class ForgeModContainer extends DummyModContainer implements WorldAccessC
|
||||||
public void readData(SaveHandler handler, WorldInfo info, Map<String, NBTBase> propertyMap, NBTTagCompound tag)
|
public void readData(SaveHandler handler, WorldInfo info, Map<String, NBTBase> propertyMap, NBTTagCompound tag)
|
||||||
{
|
{
|
||||||
DimensionManager.loadDimensionDataMap(tag.hasKey("DimensionData") ? tag.getCompoundTag("DimensionData") : null);
|
DimensionManager.loadDimensionDataMap(tag.hasKey("DimensionData") ? tag.getCompoundTag("DimensionData") : null);
|
||||||
|
FluidRegistry.loadFluidDefaults(tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
|
|
|
@ -12,7 +12,7 @@ public class FluidIdRegistryMessageHandler extends SimpleChannelInboundHandler<F
|
||||||
@Override
|
@Override
|
||||||
protected void channelRead0(ChannelHandlerContext ctx, ForgeMessage.FluidIdMapMessage msg) throws Exception
|
protected void channelRead0(ChannelHandlerContext ctx, ForgeMessage.FluidIdMapMessage msg) throws Exception
|
||||||
{
|
{
|
||||||
FluidRegistry.initFluidIDs(msg.fluidIds);
|
FluidRegistry.initFluidIDs(msg.fluidIds, msg.defaultFluids);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception
|
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception
|
||||||
|
|
|
@ -1,12 +1,18 @@
|
||||||
package net.minecraftforge.common.network;
|
package net.minecraftforge.common.network;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.Level;
|
||||||
|
|
||||||
|
import net.minecraftforge.fluids.Fluid;
|
||||||
import net.minecraftforge.fluids.FluidRegistry;
|
import net.minecraftforge.fluids.FluidRegistry;
|
||||||
|
|
||||||
import com.google.common.collect.BiMap;
|
import com.google.common.collect.BiMap;
|
||||||
import com.google.common.collect.HashBiMap;
|
import com.google.common.collect.HashBiMap;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
|
||||||
|
import net.minecraftforge.fml.common.FMLLog;
|
||||||
import net.minecraftforge.fml.common.network.ByteBufUtils;
|
import net.minecraftforge.fml.common.network.ByteBufUtils;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
|
|
||||||
|
@ -16,14 +22,14 @@ public abstract class ForgeMessage {
|
||||||
int dimensionId;
|
int dimensionId;
|
||||||
/** The provider ID to register with dimension on client */
|
/** The provider ID to register with dimension on client */
|
||||||
int providerId;
|
int providerId;
|
||||||
|
|
||||||
public DimensionRegisterMessage(){}
|
public DimensionRegisterMessage(){}
|
||||||
public DimensionRegisterMessage(int dimensionId, int providerId)
|
public DimensionRegisterMessage(int dimensionId, int providerId)
|
||||||
{
|
{
|
||||||
this.dimensionId = dimensionId;
|
this.dimensionId = dimensionId;
|
||||||
this.providerId = providerId;
|
this.providerId = providerId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void toBytes(ByteBuf bytes)
|
void toBytes(ByteBuf bytes)
|
||||||
{
|
{
|
||||||
|
@ -40,17 +46,23 @@ public abstract class ForgeMessage {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class FluidIdMapMessage extends ForgeMessage {
|
public static class FluidIdMapMessage extends ForgeMessage {
|
||||||
BiMap<String, Integer> fluidIds = HashBiMap.create();
|
BiMap<Fluid, Integer> fluidIds = HashBiMap.create();
|
||||||
|
Set<String> defaultFluids = Sets.newHashSet();
|
||||||
@Override
|
@Override
|
||||||
void toBytes(ByteBuf bytes)
|
void toBytes(ByteBuf bytes)
|
||||||
{
|
{
|
||||||
Map<String, Integer> ids = FluidRegistry.getRegisteredFluidIDs();
|
Map<Fluid, Integer> ids = FluidRegistry.getRegisteredFluidIDsByFluid();
|
||||||
bytes.writeInt(ids.size());
|
bytes.writeInt(ids.size());
|
||||||
for (Map.Entry<String, Integer> entry : ids.entrySet())
|
for (Map.Entry<Fluid, Integer> entry : ids.entrySet())
|
||||||
{
|
{
|
||||||
ByteBufUtils.writeUTF8String(bytes,entry.getKey());
|
ByteBufUtils.writeUTF8String(bytes,entry.getKey().getName());
|
||||||
bytes.writeInt(entry.getValue());
|
bytes.writeInt(entry.getValue());
|
||||||
}
|
}
|
||||||
|
for (Map.Entry<Fluid, Integer> entry : ids.entrySet())
|
||||||
|
{
|
||||||
|
String defaultName = FluidRegistry.getDefaultFluidName(entry.getKey());
|
||||||
|
ByteBufUtils.writeUTF8String(bytes, defaultName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -60,7 +72,21 @@ public abstract class ForgeMessage {
|
||||||
for (int i = 0; i < listSize; i++) {
|
for (int i = 0; i < listSize; i++) {
|
||||||
String fluidName = ByteBufUtils.readUTF8String(bytes);
|
String fluidName = ByteBufUtils.readUTF8String(bytes);
|
||||||
int fluidId = bytes.readInt();
|
int fluidId = bytes.readInt();
|
||||||
fluidIds.put(fluidName, fluidId);
|
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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,6 +96,13 @@ public abstract class BlockFluidBase extends Block implements IFluidBlock
|
||||||
|
|
||||||
protected final String fluidName;
|
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)
|
public BlockFluidBase(Fluid fluid, Material material)
|
||||||
{
|
{
|
||||||
super(material);
|
super(material);
|
||||||
|
@ -111,6 +118,7 @@ public abstract class BlockFluidBase extends Block implements IFluidBlock
|
||||||
this.densityDir = fluid.density > 0 ? -1 : 1;
|
this.densityDir = fluid.density > 0 ? -1 : 1;
|
||||||
fluid.setBlock(this);
|
fluid.setBlock(this);
|
||||||
|
|
||||||
|
this.definedFluid = fluid;
|
||||||
displacements.putAll(defaultDisplacements);
|
displacements.putAll(defaultDisplacements);
|
||||||
this.setDefaultState(blockState.getBaseState().withProperty(LEVEL, 0));
|
this.setDefaultState(blockState.getBaseState().withProperty(LEVEL, 0));
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,13 +66,17 @@ public class Fluid
|
||||||
*
|
*
|
||||||
* Default value is approximately the real-life room temperature of water in degrees Kelvin.
|
* 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
|
* Viscosity ("thickness") of the fluid - completely arbitrary; negative values are not
|
||||||
* permissible.
|
* permissible.
|
||||||
*
|
*
|
||||||
* Default value is approximately the real-life density of water in m/s^2 (x10^-3).
|
* 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;
|
protected int viscosity = 1000;
|
||||||
|
|
||||||
|
@ -117,17 +121,10 @@ public class Fluid
|
||||||
{
|
{
|
||||||
this.block = block;
|
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
|
else
|
||||||
{
|
{
|
||||||
FMLLog.severe("A mod has attempted to assign BlockID " + block + " to the Fluid '" + fluidName + "' but this Fluid has already been linked to BlockID "
|
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 + ". Configure your mods to prevent this from happening.");
|
+ this.block + ". You may have duplicate Fluid Blocks as a result. It *may* be possible to configure your mods to avoid this.");
|
||||||
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."));
|
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -320,19 +317,4 @@ public class Fluid
|
||||||
public int getColor(World world, BlockPos pos){ return getColor(); }
|
public int getColor(World world, BlockPos pos){ return getColor(); }
|
||||||
public TextureAtlasSprite getIcon(World world, BlockPos pos){ return getIcon(); }
|
public TextureAtlasSprite getIcon(World world, BlockPos pos){ return getIcon(); }
|
||||||
|
|
||||||
private static Map<String, String> 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import java.util.Set;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
|
|
||||||
|
import net.minecraftforge.fml.common.FMLLog;
|
||||||
import net.minecraftforge.fml.common.eventhandler.Event;
|
import net.minecraftforge.fml.common.eventhandler.Event;
|
||||||
import net.minecraft.init.Items;
|
import net.minecraft.init.Items;
|
||||||
import net.minecraft.item.Item;
|
import net.minecraft.item.Item;
|
||||||
|
@ -20,16 +21,16 @@ import net.minecraftforge.common.MinecraftForge;
|
||||||
/**
|
/**
|
||||||
* Register simple items that contain fluids here. Useful for buckets, bottles, and things that have
|
* Register simple items that contain fluids here. Useful for buckets, bottles, and things that have
|
||||||
* ID/metadata mappings.
|
* ID/metadata mappings.
|
||||||
*
|
*
|
||||||
* For more complex items, use {@link IFluidContainerItem} instead.
|
* For more complex items, use {@link IFluidContainerItem} instead.
|
||||||
*
|
*
|
||||||
* @author King Lemming
|
* @author King Lemming
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public abstract class FluidContainerRegistry
|
public abstract class FluidContainerRegistry
|
||||||
{
|
{
|
||||||
// Holder object that implements HashCode for an ItemStack,
|
// Holder object that implements HashCode for an ItemStack,
|
||||||
// the local maps are not guaranteed to have the same internal generic structure,
|
// the local maps are not guaranteed to have the same internal generic structure,
|
||||||
// but the external interface for checking ItemStacks will still exist.
|
// but the external interface for checking ItemStacks will still exist.
|
||||||
private static class ContainerKey
|
private static class ContainerKey
|
||||||
{
|
{
|
||||||
|
@ -51,7 +52,7 @@ public abstract class FluidContainerRegistry
|
||||||
code = 31*code + container.getItem().hashCode();
|
code = 31*code + container.getItem().hashCode();
|
||||||
code = 31*code + container.getItemDamage();
|
code = 31*code + container.getItemDamage();
|
||||||
if (fluid != null)
|
if (fluid != null)
|
||||||
code = 31*code + fluid.fluidID;
|
code = 31*code + fluid.getFluid().hashCode();
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
|
@ -64,7 +65,7 @@ public abstract class FluidContainerRegistry
|
||||||
if (fluid == null && ck.fluid != null) 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 false;
|
||||||
if (fluid == null && ck.fluid == null) return true;
|
if (fluid == null && ck.fluid == null) return true;
|
||||||
if (fluid.fluidID != ck.fluid.fluidID) return false;
|
if (fluid.getFluid() != ck.fluid.getFluid()) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,7 +90,7 @@ public abstract class FluidContainerRegistry
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a new fluid containing item.
|
* Register a new fluid containing item.
|
||||||
*
|
*
|
||||||
* @param stack
|
* @param stack
|
||||||
* FluidStack containing the type and amount of the fluid stored in the item.
|
* FluidStack containing the type and amount of the fluid stored in the item.
|
||||||
* @param filledContainer
|
* @param filledContainer
|
||||||
|
@ -106,7 +107,7 @@ public abstract class FluidContainerRegistry
|
||||||
/**
|
/**
|
||||||
* Register a new fluid containing item. The item is assumed to hold 1000 mB of fluid. Also
|
* Register a new fluid containing item. The item is assumed to hold 1000 mB of fluid. Also
|
||||||
* registers the Fluid if possible.
|
* registers the Fluid if possible.
|
||||||
*
|
*
|
||||||
* @param fluid
|
* @param fluid
|
||||||
* Fluid type that is stored in the item.
|
* Fluid type that is stored in the item.
|
||||||
* @param filledContainer
|
* @param filledContainer
|
||||||
|
@ -126,12 +127,12 @@ public abstract class FluidContainerRegistry
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a new fluid containing item that does not have an empty container.
|
* Register a new fluid containing item that does not have an empty container.
|
||||||
*
|
*
|
||||||
* @param stack
|
* @param stack
|
||||||
* FluidStack containing the type and amount of the fluid stored in the item.
|
* FluidStack containing the type and amount of the fluid stored in the item.
|
||||||
* @param filledContainer
|
* @param filledContainer
|
||||||
* ItemStack representing the container when it is full.
|
* 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)
|
public static boolean registerFluidContainer(FluidStack stack, ItemStack filledContainer)
|
||||||
{
|
{
|
||||||
|
@ -141,12 +142,12 @@ public abstract class FluidContainerRegistry
|
||||||
/**
|
/**
|
||||||
* Register a new fluid containing item that does not have an empty container. The item is
|
* 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.
|
* assumed to hold 1000 mB of fluid. Also registers the Fluid if possible.
|
||||||
*
|
*
|
||||||
* @param fluid
|
* @param fluid
|
||||||
* Fluid type that is stored in the item.
|
* Fluid type that is stored in the item.
|
||||||
* @param filledContainer
|
* @param filledContainer
|
||||||
* ItemStack representing the container when it is full.
|
* 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)
|
public static boolean registerFluidContainer(Fluid fluid, ItemStack filledContainer)
|
||||||
{
|
{
|
||||||
|
@ -159,17 +160,22 @@ public abstract class FluidContainerRegistry
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a new fluid containing item.
|
* Register a new fluid containing item.
|
||||||
*
|
*
|
||||||
* @param data
|
* @param data
|
||||||
* See {@link FluidContainerData}.
|
* 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)
|
public static boolean registerFluidContainer(FluidContainerData data)
|
||||||
{
|
{
|
||||||
if (isFilledContainer(data.filledContainer))
|
if (isFilledContainer(data.filledContainer) || data.filledContainer == null)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (data.fluid == null || data.fluid.getFluid() == null)
|
||||||
|
{
|
||||||
|
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);
|
containerFluidMap.put(new ContainerKey(data.filledContainer), data);
|
||||||
|
|
||||||
if (data.emptyContainer != null && data.emptyContainer != NULL_EMPTYCONTAINER)
|
if (data.emptyContainer != null && data.emptyContainer != NULL_EMPTYCONTAINER)
|
||||||
|
@ -184,7 +190,7 @@ public abstract class FluidContainerRegistry
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines the fluid type and amount inside a container.
|
* Determines the fluid type and amount inside a container.
|
||||||
*
|
*
|
||||||
* @param container
|
* @param container
|
||||||
* The fluid container.
|
* The fluid container.
|
||||||
* @return FluidStack representing stored fluid.
|
* @return FluidStack representing stored fluid.
|
||||||
|
@ -202,9 +208,9 @@ public abstract class FluidContainerRegistry
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempts to fill an empty container with a fluid.
|
* Attempts to fill an empty container with a fluid.
|
||||||
*
|
*
|
||||||
* NOTE: Returns null on fail, NOT the empty container.
|
* NOTE: Returns null on fail, NOT the empty container.
|
||||||
*
|
*
|
||||||
* @param fluid
|
* @param fluid
|
||||||
* FluidStack containing the type and amount of fluid to fill.
|
* FluidStack containing the type and amount of fluid to fill.
|
||||||
* @param container
|
* @param container
|
||||||
|
@ -228,7 +234,7 @@ public abstract class FluidContainerRegistry
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempts to empty a full container.
|
* Attempts to empty a full container.
|
||||||
*
|
*
|
||||||
* @param container
|
* @param container
|
||||||
* ItemStack representing the full container.
|
* ItemStack representing the full container.
|
||||||
* @return Empty container if successful, otherwise null.
|
* @return Empty container if successful, otherwise null.
|
||||||
|
@ -251,7 +257,7 @@ public abstract class FluidContainerRegistry
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines the capacity of a full container.
|
* Determines the capacity of a full container.
|
||||||
*
|
*
|
||||||
* @param container
|
* @param container
|
||||||
* The full container.
|
* The full container.
|
||||||
* @return The containers capacity, or 0 if the ItemStack does not represent
|
* @return The containers capacity, or 0 if the ItemStack does not represent
|
||||||
|
@ -264,7 +270,7 @@ public abstract class FluidContainerRegistry
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines the capacity of a container.
|
* Determines the capacity of a container.
|
||||||
*
|
*
|
||||||
* @param fluid
|
* @param fluid
|
||||||
* FluidStack containing the type of fluid the capacity should be
|
* FluidStack containing the type of fluid the capacity should be
|
||||||
* determined for (ignored for full containers).
|
* determined for (ignored for full containers).
|
||||||
|
@ -361,7 +367,7 @@ public abstract class FluidContainerRegistry
|
||||||
public final ItemStack filledContainer;
|
public final ItemStack filledContainer;
|
||||||
public final ItemStack emptyContainer;
|
public final ItemStack emptyContainer;
|
||||||
|
|
||||||
|
|
||||||
public FluidContainerData(FluidStack stack, ItemStack filledContainer, ItemStack emptyContainer)
|
public FluidContainerData(FluidStack stack, ItemStack filledContainer, ItemStack emptyContainer)
|
||||||
{
|
{
|
||||||
this(stack, filledContainer, emptyContainer, false);
|
this(stack, filledContainer, emptyContainer, false);
|
||||||
|
|
|
@ -1,19 +1,31 @@
|
||||||
package net.minecraftforge.fluids;
|
package net.minecraftforge.fluids;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
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.block.Block;
|
||||||
import net.minecraft.init.Blocks;
|
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.minecraft.util.StatCollector;
|
||||||
import net.minecraftforge.common.MinecraftForge;
|
import net.minecraftforge.common.MinecraftForge;
|
||||||
|
|
||||||
|
import com.google.common.base.Strings;
|
||||||
import com.google.common.collect.BiMap;
|
import com.google.common.collect.BiMap;
|
||||||
import com.google.common.collect.HashBiMap;
|
import com.google.common.collect.HashBiMap;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
|
||||||
|
import net.minecraftforge.fml.common.FMLLog;
|
||||||
|
import net.minecraftforge.fml.common.Loader;
|
||||||
|
import net.minecraftforge.fml.common.ModContainer;
|
||||||
import net.minecraftforge.fml.common.eventhandler.Event;
|
import net.minecraftforge.fml.common.eventhandler.Event;
|
||||||
|
import net.minecraftforge.fml.common.registry.RegistryDelegate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles Fluid registrations. Fluids MUST be registered in order to function.
|
* Handles Fluid registrations. Fluids MUST be registered in order to function.
|
||||||
|
@ -25,17 +37,23 @@ public abstract class FluidRegistry
|
||||||
{
|
{
|
||||||
static int maxID = 0;
|
static int maxID = 0;
|
||||||
|
|
||||||
static HashMap<String, Fluid> fluids = Maps.newHashMap();
|
static BiMap<String, Fluid> fluids = HashBiMap.create();
|
||||||
static BiMap<String, Integer> fluidIDs = HashBiMap.create();
|
static BiMap<Fluid, Integer> fluidIDs = HashBiMap.create();
|
||||||
|
static BiMap<Integer, String> fluidNames = HashBiMap.create(); //Caching this just makes some other calls faster
|
||||||
static BiMap<Block, Fluid> fluidBlocks;
|
static BiMap<Block, Fluid> fluidBlocks;
|
||||||
|
|
||||||
|
// the globally unique fluid map - only used to associate non-defaults during world/server loading
|
||||||
|
static BiMap<String,Fluid> masterFluidReference = HashBiMap.create();
|
||||||
|
static BiMap<String,String> defaultFluidName = HashBiMap.create();
|
||||||
|
static Map<Fluid,FluidDelegate> delegates = Maps.newHashMap();
|
||||||
|
|
||||||
public static final Fluid WATER = new Fluid("water") {
|
public static final Fluid WATER = new Fluid("water") {
|
||||||
@Override
|
@Override
|
||||||
public String getLocalizedName() {
|
public String getLocalizedName() {
|
||||||
return StatCollector.translateToLocal("tile.water.name");
|
return StatCollector.translateToLocal("tile.water.name");
|
||||||
}
|
}
|
||||||
}.setBlock(Blocks.water).setUnlocalizedName(Blocks.water.getUnlocalizedName());
|
}.setBlock(Blocks.water).setUnlocalizedName(Blocks.water.getUnlocalizedName());
|
||||||
|
|
||||||
public static final Fluid LAVA = new Fluid("lava") {
|
public static final Fluid LAVA = new Fluid("lava") {
|
||||||
@Override
|
@Override
|
||||||
public String getLocalizedName() {
|
public String getLocalizedName() {
|
||||||
|
@ -57,41 +75,109 @@ public abstract class FluidRegistry
|
||||||
* Called by Forge to prepare the ID map for server -> client sync.
|
* Called by Forge to prepare the ID map for server -> client sync.
|
||||||
* Modders, DO NOT call this.
|
* Modders, DO NOT call this.
|
||||||
*/
|
*/
|
||||||
public static void initFluidIDs(BiMap<String, Integer> newfluidIDs)
|
public static void initFluidIDs(BiMap<Fluid, Integer> newfluidIDs, Set<String> defaultNames)
|
||||||
{
|
{
|
||||||
maxID = newfluidIDs.size();
|
maxID = newfluidIDs.size();
|
||||||
fluidIDs.clear();
|
fluidIDs.clear();
|
||||||
fluidIDs.putAll(newfluidIDs);
|
fluidIDs.putAll(newfluidIDs);
|
||||||
|
fluidNames.clear();
|
||||||
|
for (Entry<Fluid, Integer> 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<String> 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());
|
||||||
|
Fluid oldFluid = fluids.put(fluid.getName(), fluid);
|
||||||
|
Integer id = fluidIDs.remove(oldFluid);
|
||||||
|
fluidIDs.put(fluid, id);
|
||||||
|
}
|
||||||
|
fluidBlocks = null;
|
||||||
|
for (FluidDelegate fd : delegates.values())
|
||||||
|
{
|
||||||
|
fd.rebind();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
* @param fluid
|
||||||
* The fluid to register.
|
* 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)
|
public static boolean registerFluid(Fluid fluid)
|
||||||
{
|
{
|
||||||
if (fluidIDs.containsKey(fluid.getName()))
|
masterFluidReference.put(uniqueName(fluid), fluid);
|
||||||
|
delegates.put(fluid, new FluidDelegate(fluid, fluid.getName()));
|
||||||
|
if (fluids.containsKey(fluid.getName()))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
fluids.put(fluid.getName(), fluid);
|
fluids.put(fluid.getName(), fluid);
|
||||||
fluidIDs.put(fluid.getName(), ++maxID);
|
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));
|
MinecraftForge.EVENT_BUS.post(new FluidRegisterEvent(fluid.getName(), maxID));
|
||||||
return true;
|
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)
|
public static boolean isFluidRegistered(Fluid fluid)
|
||||||
{
|
{
|
||||||
return fluidIDs.containsKey(fluid.getName());
|
return fluid != null && fluids.containsKey(fluid.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isFluidRegistered(String fluidName)
|
public static boolean isFluidRegistered(String fluidName)
|
||||||
{
|
{
|
||||||
return fluidIDs.containsKey(fluidName);
|
return fluids.containsKey(fluidName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Fluid getFluid(String fluidName)
|
public static Fluid getFluid(String fluidName)
|
||||||
|
@ -101,31 +187,42 @@ public abstract class FluidRegistry
|
||||||
|
|
||||||
public static Fluid getFluid(int fluidID)
|
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);
|
return fluidIDs.get(fluid);
|
||||||
}
|
|
||||||
|
|
||||||
public static String getFluidName(FluidStack stack)
|
|
||||||
{
|
|
||||||
return getFluidName(stack.fluidID);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getFluidID(String fluidName)
|
public static int getFluidID(String fluidName)
|
||||||
{
|
{
|
||||||
return fluidIDs.get(fluidName);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getFluidName(FluidStack stack)
|
||||||
|
{
|
||||||
|
return getFluidName(stack.getFluid());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FluidStack getFluidStack(String fluidName, int amount)
|
public static FluidStack getFluidStack(String fluidName, int amount)
|
||||||
{
|
{
|
||||||
if (!fluidIDs.containsKey(fluidName))
|
if (!fluids.containsKey(fluidName))
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return new FluidStack(getFluidID(fluidName), amount);
|
return new FluidStack(getFluid(fluidName), amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -139,7 +236,17 @@ public abstract class FluidRegistry
|
||||||
/**
|
/**
|
||||||
* Returns a read-only map containing Fluid Names and their associated IDs.
|
* Returns a read-only map containing Fluid Names and their associated IDs.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated //Change return type to <Fluid, Integer> in 1.8.3
|
||||||
public static Map<String, Integer> getRegisteredFluidIDs()
|
public static Map<String, Integer> 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<Fluid, Integer> getRegisteredFluidIDsByFluid()
|
||||||
{
|
{
|
||||||
return ImmutableMap.copyOf(fluidIDs);
|
return ImmutableMap.copyOf(fluidIDs);
|
||||||
}
|
}
|
||||||
|
@ -160,7 +267,7 @@ public abstract class FluidRegistry
|
||||||
}
|
}
|
||||||
return fluidBlocks.get(block);
|
return fluidBlocks.get(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class FluidRegisterEvent extends Event
|
public static class FluidRegisterEvent extends Event
|
||||||
{
|
{
|
||||||
public final String fluidName;
|
public final String fluidName;
|
||||||
|
@ -177,4 +284,110 @@ public abstract class FluidRegistry
|
||||||
{
|
{
|
||||||
return maxID;
|
return maxID;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public static String getDefaultFluidName(Fluid 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)
|
||||||
|
{
|
||||||
|
Set<String> 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<String, Fluid> def : fluids.entrySet())
|
||||||
|
{
|
||||||
|
tagList.appendTag(new NBTTagString(getDefaultFluidName(def.getValue())));
|
||||||
|
}
|
||||||
|
|
||||||
|
forgeData.setTag("DefaultFluidList", tagList);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void validateFluidRegistry()
|
||||||
|
{
|
||||||
|
Set<Fluid> 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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static RegistryDelegate<Fluid> makeDelegate(Fluid fl)
|
||||||
|
{
|
||||||
|
return delegates.get(fl);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static class FluidDelegate implements RegistryDelegate<Fluid>
|
||||||
|
{
|
||||||
|
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<Fluid> type()
|
||||||
|
{
|
||||||
|
return Fluid.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rebind()
|
||||||
|
{
|
||||||
|
fluid = fluids.get(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,10 +1,10 @@
|
||||||
|
|
||||||
package net.minecraftforge.fluids;
|
package net.minecraftforge.fluids;
|
||||||
|
|
||||||
import java.util.Locale;
|
|
||||||
import com.google.common.base.Strings;
|
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.nbt.NBTTagCompound;
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
|
import net.minecraftforge.fml.common.FMLLog;
|
||||||
|
import net.minecraftforge.fml.common.registry.RegistryDelegate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ItemStack substitute for Fluids.
|
* ItemStack substitute for Fluids.
|
||||||
|
@ -18,25 +18,36 @@ import net.minecraft.nbt.NBTTagCompound;
|
||||||
*/
|
*/
|
||||||
public class FluidStack
|
public class FluidStack
|
||||||
{
|
{
|
||||||
public int fluidID;
|
/**
|
||||||
|
* 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 int amount;
|
||||||
public NBTTagCompound tag;
|
public NBTTagCompound tag;
|
||||||
|
private RegistryDelegate<Fluid> fluidDelegate;
|
||||||
|
|
||||||
public FluidStack(Fluid fluid, int amount)
|
public FluidStack(Fluid fluid, int amount)
|
||||||
{
|
{
|
||||||
this.fluidID = fluid.getID();
|
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");
|
||||||
|
}
|
||||||
|
this.fluidDelegate = FluidRegistry.makeDelegate(fluid);
|
||||||
this.amount = amount;
|
this.amount = amount;
|
||||||
|
this.fluid = fluid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public FluidStack(int fluidID, int amount)
|
public FluidStack(Fluid fluid, int amount, NBTTagCompound nbt)
|
||||||
{
|
{
|
||||||
this.fluidID = fluidID;
|
this(fluid, amount);
|
||||||
this.amount = amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public FluidStack(int fluidID, int amount, NBTTagCompound nbt)
|
|
||||||
{
|
|
||||||
this(fluidID, amount);
|
|
||||||
|
|
||||||
if (nbt != null)
|
if (nbt != null)
|
||||||
{
|
{
|
||||||
|
@ -46,7 +57,21 @@ public class FluidStack
|
||||||
|
|
||||||
public FluidStack(FluidStack stack, int amount)
|
public FluidStack(FluidStack stack, int amount)
|
||||||
{
|
{
|
||||||
this(stack.fluidID, amount, stack.tag);
|
this(stack.getFluid(), 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -60,32 +85,23 @@ public class FluidStack
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
String fluidName = nbt.getString("FluidName");
|
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;
|
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"))
|
if (nbt.hasKey("Tag"))
|
||||||
{
|
{
|
||||||
stack.tag = nbt.getCompoundTag("Tag");
|
stack.tag = nbt.getCompoundTag("Tag");
|
||||||
}
|
}
|
||||||
else if (nbt.hasKey("extra"))
|
|
||||||
{
|
|
||||||
stack.tag = nbt.getCompoundTag("extra");
|
|
||||||
}
|
|
||||||
return stack;
|
return stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
public NBTTagCompound writeToNBT(NBTTagCompound nbt)
|
public NBTTagCompound writeToNBT(NBTTagCompound nbt)
|
||||||
{
|
{
|
||||||
nbt.setString("FluidName", FluidRegistry.getFluidName(fluidID));
|
nbt.setString("FluidName", FluidRegistry.getFluidName(getFluid()));
|
||||||
nbt.setInteger("Amount", amount);
|
nbt.setInteger("Amount", amount);
|
||||||
|
|
||||||
if (tag != null)
|
if (tag != null)
|
||||||
|
@ -97,7 +113,12 @@ public class FluidStack
|
||||||
|
|
||||||
public final Fluid getFluid()
|
public final Fluid getFluid()
|
||||||
{
|
{
|
||||||
return FluidRegistry.getFluid(fluidID);
|
return fluidDelegate.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public final int getFluidID()
|
||||||
|
{
|
||||||
|
return FluidRegistry.getFluidID(getFluid());
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getLocalizedName()
|
public String getLocalizedName()
|
||||||
|
@ -115,7 +136,7 @@ public class FluidStack
|
||||||
*/
|
*/
|
||||||
public FluidStack copy()
|
public FluidStack copy()
|
||||||
{
|
{
|
||||||
return new FluidStack(fluidID, amount, tag);
|
return new FluidStack(getFluid(), amount, tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -127,7 +148,7 @@ public class FluidStack
|
||||||
*/
|
*/
|
||||||
public boolean isFluidEqual(FluidStack other)
|
public boolean isFluidEqual(FluidStack other)
|
||||||
{
|
{
|
||||||
return other != null && fluidID == other.fluidID && isFluidStackTagEqual(other);
|
return other != null && getFluid() == other.getFluid() && isFluidStackTagEqual(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isFluidStackTagEqual(FluidStack other)
|
private boolean isFluidStackTagEqual(FluidStack other)
|
||||||
|
@ -192,7 +213,12 @@ public class FluidStack
|
||||||
@Override
|
@Override
|
||||||
public final int hashCode()
|
public final int hashCode()
|
||||||
{
|
{
|
||||||
return fluidID;
|
int code = 1;
|
||||||
|
code = 31*code + getFluid().hashCode();
|
||||||
|
code = 31*code + amount;
|
||||||
|
if (tag != null)
|
||||||
|
code = 31*code + tag.hashCode();
|
||||||
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue