Allow coremods to inject a modcontainer and run code

this will mean that FML is deliberately and very obviously incompatible with a modloader installation.

Fix up worldtype so that the server can run.
This commit is contained in:
Christian 2012-08-04 11:26:51 -04:00
parent ae79c79447
commit e39092335a
25 changed files with 468 additions and 49 deletions

View File

@ -322,7 +322,6 @@ public class FMLClientHandler implements IFMLSidedHandler
*/
public void addSpecialModEntries(ArrayList<ModContainer> mods)
{
mods.add(new FMLDummyContainer());
if (optifineContainer!=null) {
mods.add(optifineContainer);
}

View File

@ -18,7 +18,7 @@ import net.minecraft.client.Minecraft;
public class EntityRendererProxy extends EntityRenderer
{
public static final String fmlMarker = "This is an FML marker";
private Minecraft game;
public EntityRendererProxy(Minecraft minecraft)

View File

@ -42,6 +42,7 @@ import cpw.mods.fml.common.ObfuscationReflectionHelper;
public class ModLoader
{
public static final String fmlMarker = "This is an FML marker";
// TODO dirty workaround for millinaire
@Deprecated
public static final Map<String,Map<String,String>> localizedStrings=Collections.emptyMap();

View File

@ -117,4 +117,9 @@ public class DummyModContainer implements ModContainer
return null;
}
@Override
public boolean isImmutable()
{
return false;
}
}

View File

@ -16,6 +16,8 @@ package cpw.mods.fml.common;
import java.util.Arrays;
import com.google.common.eventbus.EventBus;
/**
* @author cpw
*
@ -41,4 +43,10 @@ public class FMLDummyContainer extends DummyModContainer
meta.screenshots=new String[0];
meta.logoFile="";
}
@Override
public boolean registerBus(EventBus bus, LoadController controller)
{
return true;
}
}

View File

@ -78,8 +78,8 @@ public class FMLModContainer implements ModContainer
.put(FMLServerStoppingEvent.class, Mod.ServerStopping.class)
.build();
private static final BiMap<Class<? extends Annotation>, Class<? extends FMLStateEvent>> modTypeAnnotations = modAnnotationTypes.inverse();
public FMLModContainer(String className, File modSource, Map<String,Object> modDescriptor)
{
this.className = className;
@ -223,7 +223,7 @@ public class FMLModContainer implements ModContainer
for (Annotation a : m.getAnnotations())
{
Class<?>[] paramTypes = new Class[] { modTypeAnnotations.get(a.annotationType()) };
if (Arrays.equals(m.getParameterTypes(), paramTypes))
{
m.setAccessible(true);
@ -311,4 +311,9 @@ public class FMLModContainer implements ModContainer
}
return processedVersion;
}
@Override
public boolean isImmutable()
{
return false;
}
}

View File

@ -0,0 +1,105 @@
package cpw.mods.fml.common;
import java.io.File;
import java.util.List;
import com.google.common.eventbus.EventBus;
import cpw.mods.fml.common.versioning.ArtifactVersion;
public class InjectedModContainer implements ModContainer
{
private ModContainer wrappedContainer;
public InjectedModContainer(ModContainer mc)
{
this.wrappedContainer = mc;
}
public String getModId()
{
return wrappedContainer.getModId();
}
public String getName()
{
return wrappedContainer.getName();
}
public String getVersion()
{
return wrappedContainer.getVersion();
}
public File getSource()
{
return wrappedContainer.getSource();
}
public ModMetadata getMetadata()
{
return wrappedContainer.getMetadata();
}
public void bindMetadata(MetadataCollection mc)
{
wrappedContainer.bindMetadata(mc);
}
public void setEnabledState(boolean enabled)
{
wrappedContainer.setEnabledState(enabled);
}
public List<ArtifactVersion> getRequirements()
{
return wrappedContainer.getRequirements();
}
public List<ArtifactVersion> getDependencies()
{
return wrappedContainer.getDependencies();
}
public List<ArtifactVersion> getDependants()
{
return wrappedContainer.getDependants();
}
public String getSortingRules()
{
return wrappedContainer.getSortingRules();
}
public boolean registerBus(EventBus bus, LoadController controller)
{
return wrappedContainer.registerBus(bus, controller);
}
public boolean matches(Object mod)
{
return wrappedContainer.matches(mod);
}
public Object getMod()
{
return wrappedContainer.getMod();
}
public ArtifactVersion getProcessedVersion()
{
return wrappedContainer.getProcessedVersion();
}
public ProxyInjector findSidedProxy()
{
return wrappedContainer.findSidedProxy();
}
@Override
public boolean isImmutable()
{
return true;
}
}

View File

@ -17,6 +17,7 @@ import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import cpw.mods.fml.common.LoaderState.ModState;
import cpw.mods.fml.common.event.FMLLoadEvent;
import cpw.mods.fml.common.event.FMLStateEvent;
public class LoadController
@ -34,10 +35,16 @@ public class LoadController
public LoadController(Loader loader)
{
this.loader = loader;
this.modList = loader.getIndexedModList();
this.masterChannel = new EventBus("FMLMainChannel");
this.masterChannel.register(this);
state = LoaderState.NOINIT;
}
@Subscribe
public void buildModList(FMLLoadEvent event)
{
this.modList = loader.getIndexedModList();
Builder<String, EventBus> eventBus = ImmutableMap.builder();
for (ModContainer mod : loader.getModList())
@ -60,8 +67,6 @@ public class LoadController
}
eventChannels = eventBus.build();
state = LoaderState.NOINIT;
}
public void distributeStateMessage(LoaderState state, Object... eventData)
@ -141,4 +146,17 @@ public class LoadController
{
return Iterables.getLast(modStates.get(selectedMod.getModId()), ModState.AVAILABLE);
}
public void distributeStateMessage(Class<?> customEvent)
{
try
{
masterChannel.post(customEvent.newInstance());
}
catch (Exception e)
{
FMLLog.log(Level.SEVERE, e, "An unexpected exception");
throw new LoaderException(e);
}
}
}

View File

@ -47,6 +47,7 @@ import com.google.common.collect.Maps;
import cpw.mods.fml.common.LoaderState.ModState;
import cpw.mods.fml.common.discovery.ContainerType;
import cpw.mods.fml.common.discovery.ModDiscoverer;
import cpw.mods.fml.common.event.FMLLoadEvent;
import cpw.mods.fml.common.functions.ModIdFunction;
import cpw.mods.fml.common.toposort.ModSorter;
import cpw.mods.fml.common.toposort.ModSortingException;
@ -131,6 +132,7 @@ public class Loader
private LoadController modController;
private static File minecraftDir;
private static List<String> injectedContainers;
public static Loader instance()
{
@ -151,6 +153,7 @@ public class Loader
mccversion = (String) data[4];
mcsversion = (String) data[5];
minecraftDir = (File) data[6];
injectedContainers = (List<String>)data[7];
}
private Loader()
@ -214,7 +217,10 @@ public class Loader
FMLLog.fine("Mod sorting data:");
for (ModContainer mod : mods)
{
FMLLog.fine("\t%s(%s): %s (%s)", mod.getModId(), mod.getName(), mod.getSource().getName(), mod.getSortingRules());
if (!mod.isImmutable())
{
FMLLog.fine("\t%s(%s): %s (%s)", mod.getModId(), mod.getName(), mod.getSource().getName(), mod.getSortingRules());
}
}
if (mods.size()==0)
{
@ -247,6 +253,21 @@ public class Loader
*/
private void identifyMods()
{
FMLLog.fine("Building injected Mod Containers %s", injectedContainers);
for (String cont : injectedContainers)
{
ModContainer mc;
try
{
mc = (ModContainer) Class.forName(cont,true,modClassLoader).newInstance();
}
catch (Exception e)
{
FMLLog.log(Level.SEVERE, e, "A problem occured instantiating the injected mod container %s", cont);
throw new LoaderException(e);
}
mods.add(new InjectedModContainer(mc));
}
ModDiscoverer discoverer = new ModDiscoverer();
FMLLog.fine("Attempting to load mods contained in the minecraft jar file and associated classes");
discoverer.findClasspathMods(modClassLoader);
@ -255,7 +276,7 @@ public class Loader
FMLLog.info("Searching %s for mods", canonicalModsDir.getAbsolutePath());
discoverer.findModDirMods(canonicalModsDir);
mods = discoverer.identifyMods();
mods.addAll(discoverer.identifyMods());
namedMods = Maps.uniqueIndex(mods, new ModIdFunction());
FMLLog.info("Forge Mod Loader has identified %d mod%s to load", mods.size(), mods.size() != 1 ? "s" : "");
}
@ -343,6 +364,7 @@ public class Loader
disableRequestedMods();
sortModList();
mods = ImmutableList.copyOf(mods);
modController.distributeStateMessage(FMLLoadEvent.class);
modController.transition(LoaderState.CONSTRUCTING);
modController.distributeStateMessage(LoaderState.CONSTRUCTING, modClassLoader);
modController.transition(LoaderState.PREINITIALIZATION);
@ -565,18 +587,18 @@ public class Loader
modController.distributeStateMessage(LoaderState.SERVER_STARTING, server);
modController.transition(LoaderState.SERVER_STARTING);
}
public void serverStarted()
{
modController.distributeStateMessage(LoaderState.SERVER_STARTED);
modController.transition(LoaderState.SERVER_STARTED);
}
public void serverStopping()
{
modController.distributeStateMessage(LoaderState.SERVER_STOPPING);
modController.transition(LoaderState.SERVER_STOPPING);
modController.transition(LoaderState.AVAILABLE);
}
}

View File

@ -148,4 +148,6 @@ public interface ModContainer
ArtifactVersion getProcessedVersion();
ProxyInjector findSidedProxy();
boolean isImmutable();
}

View File

@ -0,0 +1,6 @@
package cpw.mods.fml.common.event;
public class FMLLoadEvent
{
}

View File

@ -558,4 +558,10 @@ public class ModLoaderModContainer implements ModContainer
}
return processedVersion;
}
@Override
public boolean isImmutable()
{
return false;
}
}

View File

@ -16,6 +16,8 @@ import java.util.Arrays;
import java.util.List;
import java.util.Map;
import com.google.common.collect.Lists;
import cpw.mods.fml.common.DummyModContainer;
import cpw.mods.fml.common.FMLModContainer;
import cpw.mods.fml.common.ModContainer;
@ -35,6 +37,8 @@ public class ModSorter
private ModContainer before = new DummyModContainer();
private ModContainer after = new DummyModContainer();
private List<ModContainer> immutableMods;
public ModSorter(List<ModContainer> modList, Map<String, ModContainer> nameLookup)
{
buildGraph(modList, nameLookup);
@ -43,6 +47,7 @@ public class ModSorter
private void buildGraph(List<ModContainer> modList, Map<String, ModContainer> nameLookup)
{
modGraph = new DirectedGraph<ModContainer>();
immutableMods = Lists.newArrayList();
modGraph.addNode(beforeAll);
modGraph.addNode(before);
modGraph.addNode(afterAll);
@ -53,11 +58,20 @@ public class ModSorter
for (ModContainer mod : modList)
{
modGraph.addNode(mod);
if (!mod.isImmutable())
{
modGraph.addNode(mod);
}
else
{
immutableMods.add(mod);
}
}
for (ModContainer mod : modList)
{
if (mod.isImmutable())
continue;
boolean preDepAdded = false;
boolean postDepAdded = false;
@ -117,6 +131,7 @@ public class ModSorter
{
List<ModContainer> sortedList = TopologicalSort.topologicalSort(modGraph);
sortedList.removeAll(Arrays.asList(new ModContainer[] {beforeAll, before, after, afterAll}));
return sortedList;
immutableMods.addAll(sortedList);
return immutableMods;
}
}

View File

@ -1,5 +1,7 @@
package cpw.mods.fml.relauncher;
import java.util.Map;
public class FMLCorePlugin implements IFMLLoadingPlugin
{
@Override
@ -13,4 +15,22 @@ public class FMLCorePlugin implements IFMLLoadingPlugin
{
return new String[] {"cpw.mods.fml.common.asm.ASMTransformer"};
}
@Override
public String getModContainerClass()
{
return "cpw.mods.fml.common.FMLDummyContainer";
}
@Override
public String getSetupClass()
{
return "cpw.mods.fml.relauncher.FMLSanityChecker";
}
@Override
public void injectData(Map<String, Object> data)
{
// don't care about this data
}
}

View File

@ -3,10 +3,12 @@ package cpw.mods.fml.relauncher;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.logging.Level;
public class FMLVersionData
public class FMLInjectionData
{
static File minecraftHome;
static String major;
@ -15,6 +17,7 @@ public class FMLVersionData
static String build;
static String mccversion;
static String mcsversion;
public static List<String> containers = new ArrayList<String>();
static void build(File mcHome, RelaunchClassLoader classLoader)
{
@ -46,6 +49,6 @@ public class FMLVersionData
public static Object[] data()
{
return new Object[] { major, minor, rev, build, mccversion, mcsversion, minecraftHome };
return new Object[] { major, minor, rev, build, mccversion, mcsversion, minecraftHome, containers };
}
}

View File

@ -28,7 +28,7 @@ public class FMLRelauncher
private Object newApplet;
private Class<? super Object> appletClass;
private JDialog popupWindow;
JDialog popupWindow;
public static void handleClientRelaunch(ArgsWrapper wrap)
{
@ -39,7 +39,7 @@ public class FMLRelauncher
{
instance().relaunchServer(wrap);
}
static FMLRelauncher instance()
{
if (INSTANCE == null)
@ -128,8 +128,8 @@ public class FMLRelauncher
private void setupHome(File minecraftHome)
{
FMLVersionData.build(minecraftHome, classLoader);
FMLLog.info("Forge Mod Loader version %s.%s.%s.%s for Minecraft client:%s, server:%s loading", FMLVersionData.major, FMLVersionData.minor, FMLVersionData.rev, FMLVersionData.build, FMLVersionData.mccversion, FMLVersionData.mcsversion);
FMLInjectionData.build(minecraftHome, classLoader);
FMLLog.info("Forge Mod Loader version %s.%s.%s.%s for Minecraft client:%s, server:%s loading", FMLInjectionData.major, FMLInjectionData.minor, FMLInjectionData.rev, FMLInjectionData.build, FMLInjectionData.mccversion, FMLInjectionData.mcsversion);
try
{

View File

@ -0,0 +1,69 @@
package cpw.mods.fml.relauncher;
import java.util.Map;
import javax.swing.JOptionPane;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.Opcodes;
public class FMLSanityChecker implements IFMLCallHook
{
static class MLDetectorClassVisitor extends ClassVisitor
{
private boolean foundMarker = false;
private MLDetectorClassVisitor()
{
super(Opcodes.ASM4);
}
@Override
public FieldVisitor visitField(int arg0, String arg1, String arg2, String arg3, Object arg4)
{
if (arg1 == "fmlMarker")
{
foundMarker = true;
}
return null;
}
}
private RelaunchClassLoader cl;
@Override
public Void call() throws Exception
{
byte[] mlClass = cl.getClassBytes("ModLoader");
// Only care in obfuscated env
if (mlClass == null)
{
return null;
}
MLDetectorClassVisitor mlTester = new MLDetectorClassVisitor();
ClassReader cr = new ClassReader(mlClass);
cr.accept(mlTester, ClassReader.SKIP_CODE);
if (!mlTester.foundMarker)
{
JOptionPane.showMessageDialog(FMLRelauncher.instance().popupWindow, "<html>CRITICAL ERROR<br/>" +
"ModLoader was detected in this environment<br/>" +
"ForgeModLoader cannot be installed alongside ModLoader<br/>" +
"All mods should work without ModLoader being installed<br/>" +
"Because ForgeModLoader is 100% compatible with ModLoader<br/>" +
"Re-install Minecraft Forge or Forge ModLoader into a clean<br/>" +
"jar and try again.",
"ForgeModLoader critical error",
JOptionPane.ERROR_MESSAGE);
throw new RuntimeException("Invalid ModLoader class detected");
}
return null;
}
@Override
public void injectData(Map<String, Object> data)
{
cl = (RelaunchClassLoader) data.get("classLoader");
}
}

View File

@ -0,0 +1,22 @@
package cpw.mods.fml.relauncher;
import java.util.Map;
import java.util.concurrent.Callable;
/**
* This call hook allows for code to execute at the very early stages of
* minecraft initialization. FML uses it to validate that there is a
* safe environment for further loading of FML.
*
* @author cpw
*
*/
public interface IFMLCallHook extends Callable<Void>
{
/**
* Injected with data from the FML environment:
* "classLoader" : The FML Class Loader
* @param data
*/
void injectData(Map<String,Object> data);
}

View File

@ -1,5 +1,7 @@
package cpw.mods.fml.relauncher;
import java.util.Map;
/**
* The base plugin that provides class name meta information to FML to
* enhance the classloading lifecycle for mods in FML
@ -20,4 +22,34 @@ public interface IFMLLoadingPlugin
* @return
*/
String[] getASMTransformerClass();
/**
* Return a class name that implements "ModContainer" for injection into the mod list
* The "getName" function should return a name that other mods can, if need be,
* depend on.
* Trivially, this modcontainer will be loaded before all regular mod containers,
* which means it will be forced to be "immutable" - not susceptible to normal
* sorting behaviour.
* All other mod behaviours are available however- this container can receive and handle
* normal loading events
*/
String getModContainerClass();
/**
* Return the class name of an implementor of "IFMLCallHook", that will be run, in the
* main thread, to perform any additional setup this coremod may require. It will be
* run <strong>prior</strong> to Minecraft starting, so it CANNOT operate on minecraft
* itself. The game will deliberately crash if this code is detected to trigger a
* minecraft class loading (TODO: implement crash ;) )
*/
String getSetupClass();
/**
* Inject coremod data into this coremod
* This data includes:
* "mcLocation" : the location of the minecraft directory,
* "coremodList" : the list of coremods
* "coremodLocation" : the file this coremod loaded from,
*/
void injectData(Map<String, Object> data);
}

View File

@ -2,6 +2,7 @@ package cpw.mods.fml.relauncher;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLClassLoader;
@ -79,7 +80,7 @@ public class RelaunchClassLoader extends URLClassLoader
try
{
byte[] basicClass = readFully(findResource(name.replace('.', '/').concat(".class")).openStream());
byte[] basicClass = getClassBytes(name);
byte[] transformedClass = runTransformers(name, basicClass);
Class<?> cl = defineClass(name, transformedClass, 0, transformedClass.length);
cachedClasses.put(name, cl);
@ -91,6 +92,40 @@ public class RelaunchClassLoader extends URLClassLoader
}
}
/**
* @param name
* @return
* @throws IOException
*/
public byte[] getClassBytes(String name) throws IOException
{
InputStream classStream = null;
try
{
URL classResource = findResource(name.replace('.', '/').concat(".class"));
if (classResource == null)
{
return null;
}
classStream = classResource.openStream();
return readFully(classStream);
}
finally
{
if (classStream != null)
{
try
{
classStream.close();
}
catch (IOException e)
{
// Swallow the close exception
}
}
}
}
private byte[] runTransformers(String name, byte[] basicClass)
{
for (IClassTransformer transformer : transformers)

View File

@ -14,6 +14,7 @@ import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
@ -23,7 +24,9 @@ import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
@ -40,10 +43,14 @@ public class RelaunchLibraryManager
private static String[] rootPlugins = { "cpw.mods.fml.relauncher.FMLCorePlugin" , "net.minecraftforge.classloading.FMLForgePlugin" };
private static final String HEXES = "0123456789abcdef";
private static List<String> loadedLibraries = new ArrayList<String>();
private static Map<IFMLLoadingPlugin, File> pluginLocations;
private static List<IFMLLoadingPlugin> loadPlugins;
private static List<ILibrarySet> libraries;
public static void handleLaunch(File mcDir, RelaunchClassLoader actualClassLoader)
{
List<IFMLLoadingPlugin> loadPlugins = new ArrayList<IFMLLoadingPlugin>();
List<ILibrarySet> libraries = new ArrayList<ILibrarySet>();
pluginLocations = new HashMap<IFMLLoadingPlugin, File>();
loadPlugins = new ArrayList<IFMLLoadingPlugin>();
libraries = new ArrayList<ILibrarySet>();
for (String s : rootPlugins)
{
try
@ -189,11 +196,42 @@ public class RelaunchLibraryManager
}
}
}
Map<String,Object> data = new HashMap<String,Object>();
data.put("mcLocation", mcDir);
data.put("coremodList", loadPlugins);
for (IFMLLoadingPlugin plugin : loadPlugins)
{
data.put("coremodLocation", pluginLocations.get(plugin));
plugin.injectData(data);
String setupClass = plugin.getSetupClass();
if (setupClass != null)
{
try
{
IFMLCallHook call = (IFMLCallHook) Class.forName(setupClass, true, actualClassLoader).newInstance();
Map<String,Object> callData = new HashMap<String, Object>();
callData.put("classLoader", actualClassLoader);
call.injectData(callData);
call.call();
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
String modContainer = plugin.getModContainerClass();
if (modContainer != null)
{
FMLInjectionData.containers.add(modContainer);
}
}
try
{
Class<?> loaderClazz = Class.forName("cpw.mods.fml.common.Loader", true, actualClassLoader);
Method m = loaderClazz.getMethod("injectData", Object[].class);
m.invoke(null, (Object)FMLVersionData.data());
m.invoke(null, (Object)FMLInjectionData.data());
}
catch (Exception e)
{
@ -270,6 +308,7 @@ public class RelaunchLibraryManager
Class<?> coreModClass = Class.forName(fmlCorePlugin, true, classLoader);
IFMLLoadingPlugin plugin = (IFMLLoadingPlugin) coreModClass.newInstance();
loadPlugins.add(plugin);
pluginLocations .put(plugin, coreMod);
if (plugin.getLibraryRequestClass()!=null)
{
for (String libName : plugin.getLibraryRequestClass())

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="common"/>
<classpathentry kind="src" path="src-common"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="src-common"/>
<classpathentry kind="src" path="transformers"/>
<classpathentry kind="src" path="client"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src-common"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="src-common"/>
<classpathentry kind="src" path="common"/>
<classpathentry kind="src" path="server"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>

View File

@ -1,6 +1,6 @@
--- ../src-base/minecraft/net/minecraft/src/WorldType.java
+++ ../src-work/minecraft/net/minecraft/src/WorldType.java
@@ -1,4 +1,14 @@
@@ -1,7 +1,20 @@
package net.minecraft.src;
+
+import java.util.Arrays;
@ -15,19 +15,23 @@
public class WorldType
{
@@ -12,6 +22,11 @@
private boolean field_77140_h;
private boolean field_77141_i;
+ protected BiomeGenBase[] biomesForWorldType;
+
+ public static final BiomeGenBase[] base11Biomes = new BiomeGenBase[] {BiomeGenBase.field_76769_d, BiomeGenBase.field_76767_f, BiomeGenBase.field_76770_e, BiomeGenBase.field_76780_h, BiomeGenBase.field_76772_c, BiomeGenBase.field_76768_g};
+ public static final BiomeGenBase[] base12Biomes = ObjectArrays.concat(base11Biomes, BiomeGenBase.field_76782_w);
+
public static final WorldType[] field_77139_a = new WorldType[16];
public static final WorldType field_77137_b = (new WorldType(0, "default", 1)).func_77129_f();
public static final WorldType field_77138_c = new WorldType(1, "flat");
@@ -11,6 +24,9 @@
private final int field_77134_g;
private boolean field_77140_h;
private boolean field_77141_i;
+
+ protected BiomeGenBase[] biomesForWorldType;
+
private WorldType(int p_i3737_1_, String p_i3737_2_)
{
this(p_i3737_1_, p_i3737_2_, 0);
@@ -23,6 +38,14 @@
@@ -23,6 +39,14 @@
this.field_77134_g = p_i3738_3_;
this.field_77140_h = true;
field_77139_a[p_i3738_1_] = this;
@ -42,11 +46,11 @@
}
public String func_77127_a()
@@ -84,4 +107,63 @@
@@ -84,4 +108,63 @@
return null;
}
+
+
+ public WorldChunkManager getChunkManager(World world)
+ {
+ return this == field_77138_c ? new WorldChunkManagerHell(BiomeGenBase.field_76772_c, 0.5F, 0.5F) : new WorldChunkManager(world);
@ -96,7 +100,7 @@
+ newBiomesForWorld.remove(biome);
+ biomesForWorldType = newBiomesForWorld.toArray(new BiomeGenBase[0]);
+ }
+
+
+ public boolean handleSlimeSpawnReduction(Random random, World world)
+ {
+ return this == field_77138_c ? random.nextInt(4) != 1 : false;

View File

@ -1,6 +1,6 @@
--- ../src-base/minecraft_server/net/minecraft/src/WorldType.java
+++ ../src-work/minecraft_server/net/minecraft/src/WorldType.java
@@ -1,4 +1,14 @@
@@ -1,7 +1,19 @@
package net.minecraft.src;
+
+import java.util.Arrays;
@ -15,18 +15,21 @@
public class WorldType
{
@@ -12,6 +22,11 @@
private boolean field_77140_h;
private boolean field_77141_i;
+ protected BiomeGenBase[] biomesForWorldType;
+
+ public static final BiomeGenBase[] base11Biomes = new BiomeGenBase[] {BiomeGenBase.field_76769_d, BiomeGenBase.field_76767_f, BiomeGenBase.field_76770_e, BiomeGenBase.field_76780_h, BiomeGenBase.field_76772_c, BiomeGenBase.field_76768_g};
+ public static final BiomeGenBase[] base12Biomes = ObjectArrays.concat(base11Biomes, BiomeGenBase.field_76782_w);
public static final WorldType[] field_77139_a = new WorldType[16];
public static final WorldType field_77137_b = (new WorldType(0, "default", 1)).func_77129_f();
public static final WorldType field_77138_c = new WorldType(1, "flat");
@@ -11,6 +23,9 @@
private final int field_77134_g;
private boolean field_77140_h;
private boolean field_77141_i;
+
+ protected BiomeGenBase[] biomesForWorldType;
+
private WorldType(int p_i3737_1_, String p_i3737_2_)
{
this(p_i3737_1_, p_i3737_2_, 0);
@@ -23,6 +38,14 @@
this.field_77134_g = p_i3738_3_;
this.field_77140_h = true;
@ -46,7 +49,7 @@
return null;
}
+
+
+ public WorldChunkManager getChunkManager(World world)
+ {
+ return this == field_77138_c ? new WorldChunkManagerHell(BiomeGenBase.field_76772_c, 0.5F, 0.5F) : new WorldChunkManager(world);
@ -96,7 +99,7 @@
+ newBiomesForWorld.remove(biome);
+ biomesForWorldType = newBiomesForWorld.toArray(new BiomeGenBase[0]);
+ }
+
+
+ public boolean handleSlimeSpawnReduction(Random random, World world)
+ {
+ return this == field_77138_c ? random.nextInt(4) != 1 : false;