mirror of
https://github.com/MinecraftForge/MinecraftForge.git
synced 2026-11-12 08:17:35 +00:00
Rework DimensionManager for new DimensionType enum, replaces the old provider registry. Also fixed save folder issues with dimensions. Closes #2570
This commit is contained in:
1 parent
bebf22c0b0
commit
6fd9a2c00e
9 files changed
+174
-84
No files matched your search
@@ -20,13 +20,11 @@ import com.google.common.collect.Multiset;
|
||||
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.world.DimensionType;
|
||||
import net.minecraft.world.MinecraftException;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldManager;
|
||||
import net.minecraft.world.WorldProvider;
|
||||
import net.minecraft.world.WorldProviderEnd;
|
||||
import net.minecraft.world.WorldProviderHell;
|
||||
import net.minecraft.world.WorldProviderSurface;
|
||||
import net.minecraft.world.WorldServer;
|
||||
import net.minecraft.world.WorldServerMulti;
|
||||
import net.minecraft.world.storage.ISaveHandler;
|
||||
@@ -37,51 +35,24 @@ import net.minecraftforge.fml.common.FMLLog;
|
||||
|
||||
public class DimensionManager
|
||||
{
|
||||
private static Hashtable<Integer, Class<? extends WorldProvider>> providers = new Hashtable<Integer, Class<? extends WorldProvider>>();
|
||||
private static Hashtable<Integer, Boolean> spawnSettings = new Hashtable<Integer, Boolean>();
|
||||
private static Hashtable<Integer, WorldServer> worlds = new Hashtable<Integer, WorldServer>();
|
||||
private static boolean hasInit = false;
|
||||
private static Hashtable<Integer, Integer> dimensions = new Hashtable<Integer, Integer>();
|
||||
private static Hashtable<Integer, DimensionType> dimensions = new Hashtable<Integer, DimensionType>();
|
||||
private static ArrayList<Integer> unloadQueue = new ArrayList<Integer>();
|
||||
private static BitSet dimensionMap = new BitSet(Long.SIZE << 4);
|
||||
private static ConcurrentMap<World, World> weakWorldMap = new MapMaker().weakKeys().weakValues().<World,World>makeMap();
|
||||
private static Multiset<Integer> leakedWorlds = HashMultiset.create();
|
||||
|
||||
public static boolean registerProviderType(int id, Class<? extends WorldProvider> provider, boolean keepLoaded)
|
||||
{
|
||||
if (providers.containsKey(id))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
providers.put(id, provider);
|
||||
spawnSettings.put(id, keepLoaded);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters a Provider type, and returns a array of all dimensions that are
|
||||
* registered to this provider type.
|
||||
* If the return size is greater then 0, it is required that the caller either
|
||||
* change those dimensions's registered type, or replace this type before the
|
||||
* world is attempted to load, else the loader will throw an exception.
|
||||
*
|
||||
* @param id The provider type ID to unreigster
|
||||
* @return An array containing all dimension IDs still registered to this provider type.
|
||||
* Returns a list of dimensions associated with this DimensionType.
|
||||
*/
|
||||
public static int[] unregisterProviderType(int id)
|
||||
public static int[] getDimensions(DimensionType type)
|
||||
{
|
||||
if (!providers.containsKey(id))
|
||||
{
|
||||
return new int[0];
|
||||
}
|
||||
providers.remove(id);
|
||||
spawnSettings.remove(id);
|
||||
|
||||
int[] ret = new int[dimensions.size()];
|
||||
int x = 0;
|
||||
for (Map.Entry<Integer, Integer> ent : dimensions.entrySet())
|
||||
for (Map.Entry<Integer, DimensionType> ent : dimensions.entrySet())
|
||||
{
|
||||
if (ent.getValue() == id)
|
||||
if (ent.getValue() == type)
|
||||
{
|
||||
ret[x++] = ent.getKey();
|
||||
}
|
||||
@@ -99,25 +70,19 @@ public class DimensionManager
|
||||
|
||||
hasInit = true;
|
||||
|
||||
registerProviderType( 0, WorldProviderSurface.class, true);
|
||||
registerProviderType(-1, WorldProviderHell.class, true);
|
||||
registerProviderType( 1, WorldProviderEnd.class, false);
|
||||
registerDimension( 0, 0);
|
||||
registerDimension(-1, -1);
|
||||
registerDimension( 1, 1);
|
||||
registerDimension( 0, DimensionType.OVERWORLD);
|
||||
registerDimension(-1, DimensionType.NETHER);
|
||||
registerDimension( 1, DimensionType.THE_END);
|
||||
}
|
||||
|
||||
public static void registerDimension(int id, int providerType)
|
||||
public static void registerDimension(int id, DimensionType type)
|
||||
{
|
||||
if (!providers.containsKey(providerType))
|
||||
{
|
||||
throw new IllegalArgumentException(String.format("Failed to register dimension for id %d, provider type %d does not exist", id, providerType));
|
||||
}
|
||||
DimensionType.getById(type.getId()); //Check if type is invalid {will throw an error} No clue how it would be invalid tho...
|
||||
if (dimensions.containsKey(id))
|
||||
{
|
||||
throw new IllegalArgumentException(String.format("Failed to register dimension for id %d, One is already registered", id));
|
||||
}
|
||||
dimensions.put(id, providerType);
|
||||
dimensions.put(id, type);
|
||||
if (id >= 0)
|
||||
{
|
||||
dimensionMap.set(id);
|
||||
@@ -141,7 +106,7 @@ public class DimensionManager
|
||||
return dimensions.containsKey(dim);
|
||||
}
|
||||
|
||||
public static int getProviderType(int dim)
|
||||
public static DimensionType getProviderType(int dim)
|
||||
{
|
||||
if (!dimensions.containsKey(dim))
|
||||
{
|
||||
@@ -264,12 +229,6 @@ public class DimensionManager
|
||||
return worlds.values().toArray(new WorldServer[worlds.size()]);
|
||||
}
|
||||
|
||||
public static boolean shouldLoadSpawn(int dim)
|
||||
{
|
||||
int id = getProviderType(dim);
|
||||
return spawnSettings.containsKey(id) && spawnSettings.get(id);
|
||||
}
|
||||
|
||||
static
|
||||
{
|
||||
init();
|
||||
@@ -289,9 +248,9 @@ public class DimensionManager
|
||||
{
|
||||
if (dimensions.containsKey(dim))
|
||||
{
|
||||
WorldProvider provider = providers.get(getProviderType(dim)).newInstance();
|
||||
provider.setDimension(dim);
|
||||
return provider;
|
||||
WorldProvider ret = getProviderType(dim).createDimension();
|
||||
ret.setDimension(dim);
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -301,7 +260,7 @@ public class DimensionManager
|
||||
catch (Exception e)
|
||||
{
|
||||
FMLCommonHandler.instance().getFMLLogger().log(Level.ERROR, String.format("An error occured trying to create an instance of WorldProvider %d (%s)",
|
||||
dim, providers.get(getProviderType(dim)).getSimpleName()),e);
|
||||
dim, getProviderType(dim)),e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,24 +50,37 @@ public class WorldSpecificSaveHandler implements ISaveHandler
|
||||
dataDir.mkdirs();
|
||||
}
|
||||
File file = new File(dataDir, name + ".dat");
|
||||
if (!file.exists() && name.equalsIgnoreCase("FORTRESS") && world.provider.getDimension() == -1) //Only copy over the fortress.dat for the vanilla nether.
|
||||
if (!file.exists())
|
||||
{
|
||||
File parentFile = parent.getMapFileFromName(name);
|
||||
if (parentFile.exists())
|
||||
switch (world.provider.getDimension())
|
||||
{
|
||||
try
|
||||
{
|
||||
Files.copy(parentFile, file);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
FMLLog.log(Level.ERROR, e, "A critical error occured copying fortress.dat to world specific dat folder - new file will be created.");
|
||||
}
|
||||
case -1:
|
||||
if (name.equalsIgnoreCase("FORTRESS")) copyFile(name, file);
|
||||
break;
|
||||
case 1:
|
||||
if (name.equalsIgnoreCase("VILLAGES_END")) copyFile(name, file);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
private void copyFile(String name, File to)
|
||||
{
|
||||
File parentFile = parent.getMapFileFromName(name);
|
||||
if (parentFile.exists())
|
||||
{
|
||||
try
|
||||
{
|
||||
Files.copy(parentFile, to);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
FMLLog.log(Level.ERROR, e, "A critical error occured copying %s to world specific dat folder - new file will be created.", parentFile.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TemplateManager getStructureTemplateManager()
|
||||
{
|
||||
|
||||
@@ -2,6 +2,7 @@ package net.minecraftforge.common.network;
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
import net.minecraft.world.DimensionType;
|
||||
import net.minecraftforge.common.DimensionManager;
|
||||
import net.minecraftforge.common.network.ForgeMessage.DimensionRegisterMessage;
|
||||
import org.apache.logging.log4j.Level;
|
||||
@@ -13,7 +14,7 @@ public class DimensionMessageHandler extends SimpleChannelInboundHandler<ForgeMe
|
||||
{
|
||||
if (!DimensionManager.isDimensionRegistered(msg.dimensionId))
|
||||
{
|
||||
DimensionManager.registerDimension(msg.dimensionId, msg.providerId);
|
||||
DimensionManager.registerDimension(msg.dimensionId, DimensionType.valueOf(msg.providerId));
|
||||
}
|
||||
}
|
||||
@Override
|
||||
|
||||
@@ -8,6 +8,7 @@ import org.apache.logging.log4j.Level;
|
||||
import net.minecraftforge.fluids.Fluid;
|
||||
import net.minecraftforge.fluids.FluidRegistry;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.collect.BiMap;
|
||||
import com.google.common.collect.HashBiMap;
|
||||
import com.google.common.collect.Sets;
|
||||
@@ -21,10 +22,10 @@ public abstract class ForgeMessage {
|
||||
/** The dimension ID to register on client */
|
||||
int dimensionId;
|
||||
/** The provider ID to register with dimension on client */
|
||||
int providerId;
|
||||
String providerId;
|
||||
|
||||
public DimensionRegisterMessage(){}
|
||||
public DimensionRegisterMessage(int dimensionId, int providerId)
|
||||
public DimensionRegisterMessage(int dimensionId, String providerId)
|
||||
{
|
||||
this.dimensionId = dimensionId;
|
||||
this.providerId = providerId;
|
||||
@@ -34,14 +35,18 @@ public abstract class ForgeMessage {
|
||||
void toBytes(ByteBuf bytes)
|
||||
{
|
||||
bytes.writeInt(this.dimensionId);
|
||||
bytes.writeInt(this.providerId);
|
||||
byte[] data = this.providerId.getBytes(Charsets.UTF_8);
|
||||
bytes.writeShort(data.length);
|
||||
bytes.writeBytes(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
void fromBytes(ByteBuf bytes)
|
||||
{
|
||||
dimensionId = bytes.readInt();
|
||||
providerId = bytes.readInt();
|
||||
byte[] data = new byte[bytes.readShort()];
|
||||
bytes.readBytes(data);
|
||||
providerId = new String(data, Charsets.UTF_8);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,9 @@ package net.minecraftforge.common.util;
|
||||
import java.lang.reflect.*;
|
||||
import java.util.*;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import net.minecraftforge.fml.common.EnhancedRuntimeException;
|
||||
import net.minecraftforge.fml.common.FMLLog;
|
||||
import net.minecraft.block.BlockPressurePlate.Sensitivity;
|
||||
import net.minecraft.block.material.Material;
|
||||
@@ -204,8 +207,19 @@ public class EnumHelper
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T extends Enum<? >> T addEnum(Class<T> enumType, String enumName, Class<?>[] paramTypes, Object[] paramValues)
|
||||
//Tests an enum is compatible with these args, throws an error if not.
|
||||
public static void testEnum(Class<? extends Enum<?>> enumType, Class<?>[] paramTypes)
|
||||
{
|
||||
addEnum(true, enumType, null, paramTypes, (Object[])null);
|
||||
}
|
||||
|
||||
public static <T extends Enum<? >> T addEnum(Class<T> enumType, String enumName, Class<?>[] paramTypes, Object... paramValues)
|
||||
{
|
||||
return addEnum(false, enumType, enumName, paramTypes, paramValues);
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "serial" })
|
||||
private static <T extends Enum<? >> T addEnum(boolean test, final Class<T> enumType, String enumName, final Class<?>[] paramTypes, Object[] paramValues)
|
||||
{
|
||||
if (!isSetup)
|
||||
{
|
||||
@@ -243,14 +257,74 @@ public class EnumHelper
|
||||
|
||||
if (valuesField == null)
|
||||
{
|
||||
FMLLog.severe("Could not find $VALUES field for enum: %s", enumType.getName());
|
||||
FMLLog.severe("Runtime Deobf: %s", FMLForgePlugin.RUNTIME_DEOBF);
|
||||
FMLLog.severe("Flags: %s", String.format("%16s", Integer.toBinaryString(flags)).replace(' ', '0'));
|
||||
FMLLog.severe("Fields:");
|
||||
final List<String> lines = Lists.newArrayList();
|
||||
lines.add(String.format("Could not find $VALUES field for enum: %s", enumType.getName()));
|
||||
lines.add(String.format("Runtime Deobf: %s", FMLForgePlugin.RUNTIME_DEOBF));
|
||||
lines.add(String.format("Flags: %s", String.format("%16s", Integer.toBinaryString(flags)).replace(' ', '0')));
|
||||
lines.add( "Fields:");
|
||||
for (Field field : fields)
|
||||
{
|
||||
String mods = String.format("%16s", Integer.toBinaryString(field.getModifiers())).replace(' ', '0');
|
||||
FMLLog.severe(" %s %s: %s", mods, field.getName(), field.getType().getName());
|
||||
lines.add(String.format(" %s %s: %s", mods, field.getName(), field.getType().getName()));
|
||||
}
|
||||
|
||||
for (String line : lines)
|
||||
FMLLog.severe(line);
|
||||
|
||||
if (test)
|
||||
{
|
||||
throw new EnhancedRuntimeException("Could not find $VALUES field for enum: " + enumType.getName())
|
||||
{
|
||||
@Override
|
||||
protected void printStackTrace(WrappedPrintStream stream)
|
||||
{
|
||||
for (String line : lines)
|
||||
stream.println(line);
|
||||
}
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
if (test)
|
||||
{
|
||||
Object ctr = null;
|
||||
Exception ex = null;
|
||||
try
|
||||
{
|
||||
ctr = getConstructorAccessor(enumType, paramTypes);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ex = e;
|
||||
}
|
||||
if (ctr == null || ex != null)
|
||||
{
|
||||
throw new EnhancedRuntimeException(String.format("Could not find constructor for Enum %s", enumType.getName()), ex)
|
||||
{
|
||||
private String toString(Class<?>[] cls)
|
||||
{
|
||||
StringBuilder b = new StringBuilder();
|
||||
for (int x = 0; x < cls.length; x++)
|
||||
{
|
||||
b.append(cls[x].getName());
|
||||
if (x != cls.length - 1)
|
||||
b.append(", ");
|
||||
}
|
||||
return b.toString();
|
||||
}
|
||||
@Override
|
||||
protected void printStackTrace(WrappedPrintStream stream)
|
||||
{
|
||||
stream.println("Target Arguments:");
|
||||
stream.println(" java.lang.String, int, " + toString(paramTypes));
|
||||
stream.println("Found Constructors:");
|
||||
for (Constructor<?> ctr : enumType.getDeclaredConstructors())
|
||||
{
|
||||
stream.println(" " + toString(ctr.getParameterTypes()));
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user