3
0

Initial commit (Forge 1291).

This commit is contained in:
gamerforEA
2015-03-22 20:38:04 +03:00
commit 16773ead6a
611 changed files with 64826 additions and 0 deletions

View File

@ -0,0 +1,376 @@
--- ../src-base/minecraft/net/minecraftforge/common/DimensionManager.java
+++ ../src-work/minecraft/net/minecraftforge/common/DimensionManager.java
@@ -34,6 +34,15 @@
import net.minecraft.world.storage.ISaveHandler;
import net.minecraft.world.storage.SaveHandler;
import net.minecraftforge.event.world.WorldEvent;
+// Cauldron start
+import net.minecraft.server.dedicated.DedicatedServer;
+import net.minecraft.world.chunk.storage.AnvilSaveHandler;
+import net.minecraftforge.cauldron.CauldronUtils;
+import net.minecraftforge.common.util.EnumHelper;
+import org.bukkit.World.Environment;
+import org.bukkit.WorldCreator;
+import org.bukkit.generator.ChunkGenerator;
+// Cauldron end
public class DimensionManager
{
@@ -46,6 +55,11 @@
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();
+ // Cauldron start
+ private static Hashtable<Class<? extends WorldProvider>, Integer> classToProviders = new Hashtable<Class<? extends WorldProvider>, Integer>();
+ private static ArrayList<Integer> bukkitDims = new ArrayList<Integer>(); // used to keep track of Bukkit dimensions
+ private static final String FILE_SEPARATOR = System.getProperty("file.separator");
+ // Cauldron end
public static boolean registerProviderType(int id, Class<? extends WorldProvider> provider, boolean keepLoaded)
{
@@ -53,7 +67,23 @@
{
return false;
}
+ // Cauldron start - register provider with bukkit and add appropriate config option
+ String worldType = "unknown";
+ if (id != -1 && id != 0 && id != 1) // ignore vanilla
+ {
+ worldType = provider.getSimpleName().toLowerCase();
+ worldType = worldType.replace("worldprovider", "");
+ worldType = worldType.replace("provider", "");
+ registerBukkitEnvironment(id, worldType);
+ }
+ else
+ {
+ worldType = Environment.getEnvironment(id).name().toLowerCase();
+ }
+ keepLoaded = MinecraftServer.getServer().cauldronConfig.getBoolean("world-environment-settings." + worldType + ".keep-world-loaded", keepLoaded);
+ // Cauldron end
providers.put(id, provider);
+ classToProviders.put(provider, id);
spawnSettings.put(id, keepLoaded);
return true;
}
@@ -157,28 +187,33 @@
public static Integer[] getIDs(boolean check)
{
- if (check)
+ // Cauldron start - check config option and only log world leak messages if enabled
+ if (MinecraftServer.getServer().cauldronConfig.worldLeakDebug.getValue())
{
- List<World> allWorlds = Lists.newArrayList(weakWorldMap.keySet());
- allWorlds.removeAll(worlds.values());
- for (ListIterator<World> li = allWorlds.listIterator(); li.hasNext(); )
+ if (check)
{
- World w = li.next();
- leakedWorlds.add(System.identityHashCode(w));
- }
- for (World w : allWorlds)
- {
- int leakCount = leakedWorlds.count(System.identityHashCode(w));
- if (leakCount == 5)
+ List<World> allWorlds = Lists.newArrayList(weakWorldMap.keySet());
+ allWorlds.removeAll(worlds.values());
+ for (ListIterator<World> li = allWorlds.listIterator(); li.hasNext(); )
{
- FMLLog.fine("The world %x (%s) may have leaked: first encounter (5 occurences).\n", System.identityHashCode(w), w.getWorldInfo().getWorldName());
+ World w = li.next();
+ leakedWorlds.add(System.identityHashCode(w));
}
- else if (leakCount % 5 == 0)
+ for (World w : allWorlds)
{
- FMLLog.fine("The world %x (%s) may have leaked: seen %d times.\n", System.identityHashCode(w), w.getWorldInfo().getWorldName(), leakCount);
+ int leakCount = leakedWorlds.count(System.identityHashCode(w));
+ if (leakCount == 5)
+ {
+ FMLLog.fine("The world %x (%s) may have leaked: first encounter (5 occurences). Note: This may be a caused by a mod, plugin, or just a false-positive(No memory leak). If server crashes due to OOM, report to Cauldron.\n", System.identityHashCode(w), w.getWorldInfo().getWorldName());
+ }
+ else if (leakCount % 5 == 0)
+ {
+ FMLLog.fine("The world %x (%s) may have leaked: seen %d times. Note: This may be a caused by a mod, plugin, or just a false-positive(No memory leak). If server crashes due to OOM, report to Cauldron.\n", System.identityHashCode(w), w.getWorldInfo().getWorldName(), leakCount);
+ }
}
}
}
+ // Cauldron end
return getIDs();
}
public static Integer[] getIDs()
@@ -191,12 +226,23 @@
if (world != null)
{
worlds.put(id, world);
- weakWorldMap.put(world, world);
+ // Cauldron start - check config option and only log world leak messages if enabled
+ if (MinecraftServer.getServer().cauldronConfig.worldLeakDebug.getValue())
+ {
+ weakWorldMap.put(world, world);
+ }
+ // handle all world adds here for Bukkit
+ if (!MinecraftServer.getServer().worlds.contains(world))
+ {
+ MinecraftServer.getServer().worlds.add(world);
+ }
+ // Cauldron end
MinecraftServer.getServer().worldTickTimes.put(id, new long[100]);
FMLLog.info("Loading dimension %d (%s) (%s)", id, world.getWorldInfo().getWorldName(), world.func_73046_m());
}
else
{
+ MinecraftServer.getServer().worlds.remove(getWorld(id)); // Cauldron - remove world from our new world arraylist
worlds.remove(id);
MinecraftServer.getServer().worldTickTimes.remove(id);
FMLLog.info("Unloading dimension %d", id);
@@ -224,6 +270,7 @@
}
public static void initDimension(int dim) {
+ if (dim == 0) return; // Cauldron - overworld
WorldServer overworld = getWorld(0);
if (overworld == null)
{
@@ -231,6 +278,12 @@
}
try
{
+ // Cauldron start - Fixes MultiVerse issue when mods such as Twilight Forest try to hotload their dimension when using its WorldProvider
+ if(net.minecraftforge.cauldron.CauldronHooks.craftWorldLoading)
+ {
+ return;
+ }
+ // Cauldron end
DimensionManager.getProviderType(dim);
}
catch (Exception e)
@@ -242,9 +295,52 @@
ISaveHandler savehandler = overworld.getSaveHandler();
WorldSettings worldSettings = new WorldSettings(overworld.getWorldInfo());
- WorldServer world = (dim == 0 ? overworld : new WorldServerMulti(mcServer, savehandler, overworld.getWorldInfo().getWorldName(), dim, worldSettings, overworld, mcServer.theProfiler));
+ // Cauldron start - handles hotloading dimensions
+ String worldType;
+ String name;
+ String oldName = "";
+ Environment env = Environment.getEnvironment(getProviderType(dim));
+ if (dim >= -1 && dim <= 1)
+ {
+ if ((dim == -1 && !mcServer.getAllowNether()) || (dim == 1 && !mcServer.server.getAllowEnd()))
+ return;
+ worldType = env.toString().toLowerCase();
+ name = "DIM" + dim;
+ }
+ else
+ {
+ WorldProvider provider = WorldProvider.getProviderForDimension(dim);
+ worldType = provider.getClass().getSimpleName().toLowerCase();
+ worldType = worldType.replace("worldprovider", "");
+ oldName = "world_" + worldType;
+ worldType = worldType.replace("provider", "");
+
+ if (Environment.getEnvironment(DimensionManager.getProviderType(dim)) == null)
+ env = DimensionManager.registerBukkitEnvironment(DimensionManager.getProviderType(provider.getClass()), worldType);
+
+ name = provider.getSaveFolder();
+ if (name == null) name = "DIM0";
+ }
+ // add ability to disable dimensions
+ if (!MinecraftServer.getServer().cauldronConfig.getBoolean("world-environment-settings." + worldType + ".enabled", true))
+ return;
+
+ CauldronUtils.migrateWorlds(worldType, oldName, overworld.getWorldInfo().getWorldName(), name); // Cauldron
+ ChunkGenerator gen = mcServer.server.getGenerator(name);
+ if (mcServer instanceof DedicatedServer) {
+ worldSettings.func_82750_a(((DedicatedServer) mcServer).getStringProperty("generator-settings", ""));
+ }
+ WorldServer world = new WorldServerMulti(mcServer, new AnvilSaveHandler(mcServer.server.getWorldContainer(), name, true), name, dim, worldSettings, overworld, mcServer.theProfiler, env, gen);
+
+ if (gen != null)
+ {
+ world.getWorld().getPopulators().addAll(gen.getDefaultPopulators(world.getWorld()));
+ }
+ mcServer.getConfigurationManager().setPlayerManager(mcServer.worlds.toArray(new WorldServer[mcServer.worlds.size()]));
world.addWorldAccess(new WorldManager(mcServer, world));
MinecraftForge.EVENT_BUS.post(new WorldEvent.Load(world));
+ mcServer.server.getPluginManager().callEvent(new org.bukkit.event.world.WorldLoadEvent(world.getWorld()));
+ // Cauldron end
if (!mcServer.isSinglePlayer())
{
world.getWorldInfo().setGameType(mcServer.getGameType());
@@ -253,6 +349,79 @@
mcServer.func_147139_a(mcServer.func_147135_j());
}
+ // Cauldron start - new method for handling creation of Bukkit dimensions. Currently supports MultiVerse
+ public static WorldServer initDimension(WorldCreator creator, WorldSettings worldSettings) {
+ WorldServer overworld = getWorld(0);
+ if (overworld == null) {
+ throw new RuntimeException("Cannot Hotload Dim: Overworld is not Loaded!");
+ }
+
+ MinecraftServer mcServer = overworld.func_73046_m();
+
+ String worldType;
+ String name;
+
+ int providerId = 0;
+ if (creator.environment() != null)
+ providerId = creator.environment().getId();
+ try {
+ providerId = getProviderType(providerId);
+ }
+ catch (IllegalArgumentException e)
+ {
+ // do nothing
+ }
+
+ Environment env = creator.environment();
+ worldType = env.name().toLowerCase();
+ name = creator.name();
+ int dim = 0;
+ // Use saved dimension from level.dat if it exists. This guarantees that after a world is created, the same dimension will be used. Fixes issues with MultiVerse
+ AnvilSaveHandler saveHandler = new AnvilSaveHandler(mcServer.server.getWorldContainer(), name, true);
+ if (saveHandler.loadWorldInfo() != null)
+ {
+ int savedDim = saveHandler.loadWorldInfo().getDimension();
+ if (savedDim != 0 && savedDim != -1 && savedDim != 1)
+ {
+ dim = savedDim;
+ }
+ }
+ if (dim == 0)
+ {
+ dim = getNextFreeDimId();
+ }
+
+ if (!isDimensionRegistered(dim)) // handle reloads properly
+ {
+ registerDimension(dim, providerId);
+ addBukkitDimension(dim);
+ }
+ ChunkGenerator gen = creator.generator();
+ if (mcServer instanceof DedicatedServer) {
+ worldSettings.func_82750_a(((DedicatedServer) mcServer).getStringProperty("generator-settings", ""));
+ }
+
+ WorldServer world = new WorldServerMulti(mcServer, saveHandler, name, dim, worldSettings, overworld, mcServer.theProfiler, env, gen);
+
+ if (gen != null)
+ {
+ world.getWorld().getPopulators().addAll(gen.getDefaultPopulators(world.getWorld()));
+ }
+ world.provider.dimensionId = dim; // Fix for TerrainControl injecting their own WorldProvider
+ mcServer.getConfigurationManager().setPlayerManager(mcServer.worlds.toArray(new WorldServer[mcServer.worlds.size()]));
+
+ world.addWorldAccess(new WorldManager(mcServer, world));
+ MinecraftForge.EVENT_BUS.post(new WorldEvent.Load(world));
+ if (!mcServer.isSinglePlayer())
+ {
+ world.getWorldInfo().setGameType(mcServer.getGameType());
+ }
+ mcServer.func_147139_a(mcServer.func_147135_j());
+
+ return world;
+ }
+ // Cauldron end
+
public static WorldServer getWorld(int id)
{
return worlds.get(id);
@@ -266,7 +435,7 @@
public static boolean shouldLoadSpawn(int dim)
{
int id = getProviderType(dim);
- return spawnSettings.containsKey(id) && spawnSettings.get(id);
+ return ((spawnSettings.containsKey(id) && spawnSettings.get(id)) || (getWorld(dim) != null && getWorld(dim).keepSpawnInMemory)); // Cauldron added bukkit check
}
static
@@ -306,7 +475,8 @@
}
public static void unloadWorld(int id) {
- unloadQueue.add(id);
+ if (!shouldLoadSpawn(id)) // Cauldron - prevent mods from force unloading if we have it disabled
+ unloadQueue.add(id);
}
/*
@@ -315,26 +485,9 @@
public static void unloadWorlds(Hashtable<Integer, long[]> worldTickTimes) {
for (int id : unloadQueue) {
WorldServer w = worlds.get(id);
- try {
- if (w != null)
- {
- w.saveAllChunks(true, null);
- }
- else
- {
- FMLLog.warning("Unexpected world unload - world %d is already unloaded", id);
- }
- } catch (MinecraftException e) {
- e.printStackTrace();
- }
- finally
+ if (w != null)
{
- if (w != null)
- {
- MinecraftForge.EVENT_BUS.post(new WorldEvent.Unload(w));
- w.flush();
- setWorld(id, null);
- }
+ MinecraftServer.getServer().server.unloadWorld(w.getWorld(), true); // Cauldron - unload through our new method for simplicity
}
}
unloadQueue.clear();
@@ -425,4 +578,45 @@
return null;
}
}
+
+ // Cauldron start - add registration for Bukkit Environments
+ public static Environment registerBukkitEnvironment(int dim, String providerName)
+ {
+ Environment env = Environment.getEnvironment(dim);
+ if (env == null) // Cauldron if environment not found, register one
+ {
+ providerName = providerName.replace("WorldProvider", "");
+ env = EnumHelper.addBukkitEnvironment(dim, providerName.toUpperCase());
+ Environment.registerEnvironment(env);
+ }
+ return env;
+ }
+
+ public static int getProviderType(Class<? extends WorldProvider> provider)
+ {
+ return classToProviders.get(provider);
+ }
+
+ public static void addBukkitDimension(int dim)
+ {
+ if (!bukkitDims.contains(dim))
+ bukkitDims.add(dim);
+ }
+
+ public static void removeBukkitDimension(int dim)
+ {
+ if (bukkitDims.contains(dim))
+ bukkitDims.remove(bukkitDims.indexOf(dim));
+ }
+
+ public static ArrayList<Integer> getBukkitDimensionIDs()
+ {
+ return bukkitDims;
+ }
+
+ public static boolean isBukkitDimension(int dim)
+ {
+ return bukkitDims.contains(dim);
+ }
+ // Cauldron end
}

View File

@ -0,0 +1,45 @@
--- ../src-base/minecraft/net/minecraftforge/common/ForgeHooks.java
+++ ../src-work/minecraft/net/minecraftforge/common/ForgeHooks.java
@@ -63,6 +63,7 @@
import net.minecraftforge.event.world.BlockEvent;
import net.minecraftforge.event.world.NoteBlockEvent;
import static net.minecraft.init.Blocks.*;
+import net.minecraftforge.common.util.FakePlayer; // Cauldron
public class ForgeHooks
{
@@ -439,6 +440,8 @@
public static BlockEvent.BreakEvent onBlockBreakEvent(World world, GameType gameType, EntityPlayerMP entityPlayer, int x, int y, int z)
{
+ // Cauldron - pre-cancel handled in BreakEvent
+ /*
// Logic from tryHarvestBlock for pre-canceling the event
boolean preCancelEvent = false;
if (gameType.isAdventure() && !entityPlayer.isCurrentToolAdventureModeExempt(x, y, z))
@@ -449,9 +452,9 @@
{
preCancelEvent = true;
}
-
+ */
// Tell client the block is gone immediately then process events
- if (world.getTileEntity(x, y, z) == null)
+ if (world.getTileEntity(x, y, z) == null && !(entityPlayer instanceof FakePlayer)) // Cauldron - don't send packets to fakeplayers
{
S23PacketBlockChange packet = new S23PacketBlockChange(x, y, z, world);
packet.field_148883_d = Blocks.air;
@@ -463,11 +466,11 @@
Block block = world.getBlock(x, y, z);
int blockMetadata = world.getBlockMetadata(x, y, z);
BlockEvent.BreakEvent event = new BlockEvent.BreakEvent(x, y, z, world, block, blockMetadata, entityPlayer);
- event.setCanceled(preCancelEvent);
+ // event.setCanceled(preCancelEvent); // Cauldron
MinecraftForge.EVENT_BUS.post(event);
// Handle if the event is canceled
- if (event.isCanceled())
+ if (event.isCanceled() && !(entityPlayer instanceof FakePlayer)) // Cauldron - don't send packets to fakeplayers
{
// Let the client know the block still exists
entityPlayer.playerNetServerHandler.sendPacket(new S23PacketBlockChange(x, y, z, world));

View File

@ -0,0 +1,11 @@
--- ../src-base/minecraft/net/minecraftforge/common/ForgeVersion.java
+++ ../src-work/minecraft/net/minecraftforge/common/ForgeVersion.java
@@ -25,7 +25,7 @@
//This number is incremented every time a interface changes or new major feature is added, and reset every Minecraft version
public static final int revisionVersion = 2;
//This number is incremented every time Jenkins builds Forge, and never reset. Should always be 0 in the repo code.
- public static final int buildVersion = 0;
+ public static final int buildVersion = 1291; // Cauldron
private static Status status = PENDING;
private static String target = null;

View File

@ -0,0 +1,22 @@
--- ../src-base/minecraft/net/minecraftforge/common/WorldSpecificSaveHandler.java
+++ ../src-work/minecraft/net/minecraftforge/common/WorldSpecificSaveHandler.java
@@ -1,6 +1,7 @@
package net.minecraftforge.common;
import java.io.File;
+import java.util.UUID;
import net.minecraft.world.chunk.storage.IChunkLoader;
import net.minecraft.world.storage.IPlayerFileData;
@@ -43,4 +44,11 @@
return new File(dataDir, name + ".dat");
}
+ // Cauldron start
+ @Override
+ public UUID getUUID()
+ {
+ return parent.getUUID();
+ }
+ // Cauldron end
}

View File

@ -0,0 +1,34 @@
--- ../src-base/minecraft/net/minecraftforge/common/chunkio/ChunkIOProvider.java
+++ ../src-work/minecraft/net/minecraftforge/common/chunkio/ChunkIOProvider.java
@@ -9,6 +9,9 @@
import java.io.IOException;
import java.util.concurrent.atomic.AtomicInteger;
+import org.bukkit.Server;
+import org.bukkit.craftbukkit.util.LongHash;
+
class ChunkIOProvider implements AsynchronousExecutor.CallBackProvider<QueuedChunk, net.minecraft.world.chunk.Chunk, Runnable, RuntimeException> {
private final AtomicInteger threadNumber = new AtomicInteger(1);
@@ -41,13 +44,20 @@
queuedChunk.loader.loadEntities(queuedChunk.world, queuedChunk.compound.getCompoundTag("Level"), chunk);
MinecraftForge.EVENT_BUS.post(new ChunkDataEvent.Load(chunk, queuedChunk.compound)); // Don't call ChunkDataEvent.Load async
chunk.lastSaveTime = queuedChunk.provider.worldObj.getTotalWorldTime();
- queuedChunk.provider.loadedChunkHashMap.add(ChunkCoordIntPair.chunkXZ2Int(queuedChunk.x, queuedChunk.z), chunk);
+ queuedChunk.provider.loadedChunkHashMap.put(LongHash.toLong(queuedChunk.x, queuedChunk.z), chunk);
queuedChunk.provider.loadedChunks.add(chunk);
chunk.onChunkLoad();
if (queuedChunk.provider.currentChunkProvider != null) {
+ queuedChunk.provider.worldObj.timings.syncChunkLoadStructuresTimer.startTiming(); // Spigot
queuedChunk.provider.currentChunkProvider.recreateStructures(queuedChunk.x, queuedChunk.z);
+ queuedChunk.provider.worldObj.timings.syncChunkLoadStructuresTimer.stopTiming(); // Spigot
}
+
+ Server server = queuedChunk.provider.worldObj.getServer();
+ if (server != null) {
+ server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkLoadEvent(chunk.bukkitChunk, false));
+ }
chunk.populateChunk(queuedChunk.provider, queuedChunk.provider, queuedChunk.x, queuedChunk.z);
}

View File

@ -0,0 +1,12 @@
--- ../src-base/minecraft/net/minecraftforge/common/network/ForgeNetworkHandler.java
+++ ../src-work/minecraft/net/minecraftforge/common/network/ForgeNetworkHandler.java
@@ -35,4 +35,9 @@
clientChannel.pipeline().addAfter(handlerName, "DimensionHandler", new DimensionMessageHandler());
clientChannel.pipeline().addAfter(handlerName, "FluidIdRegistryHandler", new FluidIdRegistryMessageHandler());
}
+
+ public static FMLEmbeddedChannel getServerChannel()
+ {
+ return channelPair.get(Side.SERVER);
+ }
}

View File

@ -0,0 +1,195 @@
--- ../src-base/minecraft/net/minecraftforge/common/util/EnumHelper.java
+++ ../src-work/minecraft/net/minecraftforge/common/util/EnumHelper.java
@@ -21,7 +21,23 @@
import net.minecraft.world.EnumSkyBlock;
import net.minecraft.world.gen.structure.StructureStrongholdPieces.Stronghold.Door;
import net.minecraftforge.classloading.FMLForgePlugin;
+// Cauldron start
+import cpw.mods.fml.relauncher.ReflectionHelper;
+import net.minecraft.inventory.IInventory;
+import net.minecraft.server.MinecraftServer;
+import net.minecraft.tileentity.TileEntity;
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.bukkit.World;
+import org.bukkit.WorldType;
+import org.bukkit.block.Biome;
+import org.bukkit.craftbukkit.entity.CraftEntity;
+import org.bukkit.entity.EntityType;
+import org.bukkit.event.inventory.InventoryType;
+// Cauldron end
+
public class EnumHelper
{
private static Object reflectionFactory = null;
@@ -30,6 +46,7 @@
private static Method newFieldAccessor = null;
private static Method fieldAccessorSet = null;
private static boolean isSetup = false;
+ private static final Logger logger = LogManager.getLogger();
//Some enums are decompiled with extra arguments, so lets check for that
@SuppressWarnings("rawtypes")
@@ -51,6 +68,73 @@
{EnumRarity.class, EnumChatFormatting.class, String.class}
};
+ // Cauldron start
+ public static Biome addBukkitBiome(String name)
+ {
+ return (Biome)addEnum(Biome.class, name, new Class[0], new Object[0]);
+ }
+
+ public static World.Environment addBukkitEnvironment(int id, String name)
+ {
+ if (!isSetup)
+ {
+ setup();
+ }
+
+ return (World.Environment)addEnum(World.Environment.class, name, new Class[] { Integer.TYPE }, new Object[] { Integer.valueOf(id) });
+ }
+
+ public static WorldType addBukkitWorldType(String name)
+ {
+ if (!isSetup)
+ {
+ setup();
+ }
+
+ WorldType worldType = addEnum(WorldType.class, name, new Class [] { String.class }, new Object[] { name });
+ Map<String, WorldType> BY_NAME = ReflectionHelper.getPrivateValue(WorldType.class, null, "BY_NAME");
+ BY_NAME.put(name.toUpperCase(), worldType);
+
+ return worldType;
+ }
+
+ public static EntityType addBukkitEntityType(String name, Class <? extends org.bukkit.entity.Entity> clazz, int typeId, boolean independent) {
+ String entityType = name.replace("-", "_").toUpperCase();
+ EntityType bukkitType = addEnum(EntityType.class, entityType, new Class[] { String.class, Class.class, Integer.TYPE, Boolean.TYPE }, new Object[] { name, clazz, typeId, independent });
+
+ Map<String, EntityType> NAME_MAP = ReflectionHelper.getPrivateValue(EntityType.class, null, "NAME_MAP");
+ Map<Short, EntityType> ID_MAP = ReflectionHelper.getPrivateValue(EntityType.class, null, "ID_MAP");
+
+ NAME_MAP.put(name.toLowerCase(), bukkitType);
+ ID_MAP.put((short)typeId, bukkitType);
+
+
+ return bukkitType;
+ }
+
+ public static InventoryType addInventoryType(TileEntity tileentity)
+ {
+ if (!IInventory.class.isAssignableFrom(tileentity.getClass())) return null;
+ String id = (String)TileEntity.classToNameMap.get(tileentity.getClass());
+
+ try
+ {
+ IInventory teInv = (IInventory)tileentity;
+ int size = teInv.getSizeInventory();
+ return addEnum(org.bukkit.event.inventory.InventoryType.class, id, new Class[]{Integer.TYPE, String.class}, new Object[]{size, id});
+ }
+ catch (Throwable e)
+ {
+ if (MinecraftServer.getServer().tileEntityConfig.enableTEInventoryWarning.getValue())
+ {
+ logger.log(Level.WARN, "Could not create inventory type " + tileentity.getClass().getName() + " Exception: " + e.toString());
+ logger.log(Level.WARN, "Could not determine default inventory size for type " + tileentity.getClass().getName() + " using size of 9");
+ }
+ return addEnum(org.bukkit.event.inventory.InventoryType.class, id, new Class[]{Integer.TYPE, String.class}, new Object[]{9, id});
+ }
+ }
+ // Cauldron end
+
public static EnumAction addAction(String name)
{
return addEnum(EnumAction.class, name);
@@ -280,6 +364,86 @@
}
}
+ // Cauldron start
+ @SuppressWarnings("unchecked")
+ public static <T extends Enum<?>> T replaceEnum(Class<T> enumType, String enumName, int ordinal, Class<?>[] paramTypes, Object[] paramValues)
+ {
+ if (!isSetup)
+ {
+ setup();
+ }
+
+ Field valuesField = null;
+ Field[] fields = enumType.getDeclaredFields();
+
+ for (Field field : fields)
+ {
+ String name = field.getName();
+ if (name.equals("$VALUES") || name.equals("ENUM$VALUES")) //Added 'ENUM$VALUES' because Eclipse's internal compiler doesn't follow standards
+ {
+ valuesField = field;
+ break;
+ }
+ }
+
+ int flags = (FMLForgePlugin.RUNTIME_DEOBF ? Modifier.PUBLIC : Modifier.PRIVATE) | Modifier.STATIC | Modifier.FINAL | 0x1000 /*SYNTHETIC*/;
+ if (valuesField == null)
+ {
+ String valueType = String.format("[L%s;", enumType.getName().replace('.', '/'));
+
+ for (Field field : fields)
+ {
+ if ((field.getModifiers() & flags) == flags &&
+ field.getType().getName().replace('.', '/').equals(valueType)) //Apparently some JVMs return .'s and some don't..
+ {
+ valuesField = field;
+ break;
+ }
+ }
+ }
+
+ 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:");
+ 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());
+ }
+ return null;
+ }
+
+ valuesField.setAccessible(true);
+ try
+ {
+ Enum[] previousValues = (Enum[])(Enum[])valuesField.get(enumType);
+ Enum[] newValues = new Enum[previousValues.length];
+ Enum newValue = null;
+ for (Enum enumValue : previousValues)
+ {
+ if (enumValue.ordinal() == ordinal)
+ {
+ newValue = makeEnum(enumType, enumName, ordinal, paramTypes, paramValues);
+ newValues[enumValue.ordinal()] = newValue;
+ }
+ else newValues[enumValue.ordinal()] = enumValue;
+ }
+ List values = new ArrayList(Arrays.asList(newValues));
+ setFailsafeFieldValue(valuesField, null, values.toArray((Enum[])(Enum[])Array.newInstance(enumType, 0)));
+ cleanEnumCache(enumType);
+ return (T) newValue;
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ throw new RuntimeException(e.getMessage(), e);
+ }
+ }
+ // Cauldron end
+
static
{
if (!isSetup)

View File

@ -0,0 +1,31 @@
--- ../src-base/minecraft/net/minecraftforge/common/util/FakePlayerFactory.java
+++ ../src-work/minecraft/net/minecraftforge/common/util/FakePlayerFactory.java
@@ -35,12 +35,24 @@
*/
public static FakePlayer get(WorldServer world, GameProfile username)
{
- if (!fakePlayers.containsKey(username))
+ // Cauldron start - Refactored below to avoid a hashCode check with a null GameProfile ID
+ if (username == null || username.getName() == null) return null;
+
+ for (Map.Entry<GameProfile, FakePlayer> mapEntry : fakePlayers.entrySet())
{
- FakePlayer fakePlayer = new FakePlayer(world, username);
- fakePlayers.put(username, fakePlayer);
+ GameProfile gameprofile = mapEntry.getKey();
+ if (gameprofile.getName().equals(username.getName()))
+ {
+ return mapEntry.getValue();
+ }
}
-
+ FakePlayer fakePlayer = new FakePlayer(world, username);
+ if (username.getId() == null) // GameProfile hashCode check will fail with a null ID
+ {
+ username = new GameProfile(UUID.randomUUID(), username.getName()); // Create new GameProfile with random UUID
+ }
+ // Cauldron end
+ fakePlayers.put(username, fakePlayer);
return fakePlayers.get(username);
}

View File

@ -0,0 +1,18 @@
--- ../src-base/minecraft/net/minecraftforge/event/entity/living/LivingSpawnEvent.java
+++ ../src-work/minecraft/net/minecraftforge/event/entity/living/LivingSpawnEvent.java
@@ -48,6 +48,7 @@
public CheckSpawn(EntityLiving entity, World world, float x, float y, float z)
{
super(entity, world, x, y, z);
+ entity.spawnReason = "natural"; // Cauldron - used to handle CraftBukkit's SpawnReason with CustomSpawners
}
}
@@ -71,6 +72,7 @@
public SpecialSpawn(EntityLiving entity, World world, float x, float y, float z)
{
super(entity, world, x, y, z);
+ entity.spawnReason = "spawner"; // Cauldron - used to handle CraftBukkit's SpawnReason with CustomSpawners
}
}

View File

@ -0,0 +1,39 @@
--- ../src-base/minecraft/net/minecraftforge/event/world/BlockEvent.java
+++ ../src-work/minecraft/net/minecraftforge/event/world/BlockEvent.java
@@ -16,6 +16,11 @@
import net.minecraftforge.common.ForgeHooks;
import net.minecraftforge.common.util.BlockSnapshot;
+// Cauldron start
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+import net.minecraft.entity.player.EntityPlayerMP;
+// Cauldron end
+
public class BlockEvent extends Event {
private static final boolean DEBUG = Boolean.parseBoolean(System.getProperty("forge.debugBlockEvent", "false"));
@@ -80,17 +85,18 @@
super(x, y, z, world, block, blockMetadata);
this.player = player;
- if (block == null || !ForgeHooks.canHarvestBlock(block, player, blockMetadata) || // Handle empty block or player unable to break block scenario
- block.canSilkHarvest(world, player, x, y, z, blockMetadata) && EnchantmentHelper.getSilkTouchModifier(player)) // If the block is being silk harvested, the exp dropped is 0
+ // Cauldron start - handle event on bukkit side
+ org.bukkit.event.block.BlockBreakEvent bukkitEvent = CraftEventFactory.callBlockBreakEvent(world, x, y, z, block, blockMetadata,
+ (EntityPlayerMP) player);
+ if (bukkitEvent.isCancelled())
{
- this.exp = 0;
+ this.setCanceled(true);
}
else
{
- int meta = block.getDamageValue(world, x, y, z);
- int bonusLevel = EnchantmentHelper.getFortuneModifier(player);
- this.exp = block.getExpDrop(world, meta, bonusLevel);
+ this.exp = bukkitEvent.getExpToDrop();
}
+ // Cauldron end
}
public EntityPlayer getPlayer()

View File

@ -0,0 +1,20 @@
--- ../src-base/minecraft/net/minecraftforge/oredict/OreDictionary.java
+++ ../src-work/minecraft/net/minecraftforge/oredict/OreDictionary.java
@@ -216,7 +216,7 @@
{
ShapedRecipes recipe = (ShapedRecipes)obj;
ItemStack output = recipe.getRecipeOutput();
- if (output != null && containsMatch(false, exclusions, output))
+ if ((output != null && containsMatch(false, exclusions, output)) || output == null) // Cauldron - fixes NPE's with null recipes being added to forge
{
continue;
}
@@ -231,7 +231,7 @@
{
ShapelessRecipes recipe = (ShapelessRecipes)obj;
ItemStack output = recipe.getRecipeOutput();
- if (output != null && containsMatch(false, exclusions, output))
+ if ((output != null && containsMatch(false, exclusions, output)) || output == null) // Cauldron - fixes NPE's with null recipes being added to forge
{
continue;
}

View File

@ -0,0 +1,51 @@
--- ../src-base/minecraft/net/minecraftforge/oredict/ShapedOreRecipe.java
+++ ../src-work/minecraft/net/minecraftforge/oredict/ShapedOreRecipe.java
@@ -6,6 +6,10 @@
import java.util.Map;
import java.util.Map.Entry;
+// Cauldron start
+import org.bukkit.inventory.Recipe;
+// Cauldron end
+
import net.minecraft.block.Block;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.inventory.InventoryCrafting;
@@ -13,6 +17,7 @@
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.ShapedRecipes;
import net.minecraft.world.World;
+import net.minecraftforge.cauldron.inventory.CustomModRecipe;
public class ShapedOreRecipe implements IRecipe
{
@@ -25,6 +30,7 @@
private int width = 0;
private int height = 0;
private boolean mirrored = true;
+ private ShapedRecipes vanillaRecipe = null; // Cauldron - bukkit compatibility
public ShapedOreRecipe(Block result, Object... recipe){ this(new ItemStack(result), recipe); }
public ShapedOreRecipe(Item result, Object... recipe){ this(new ItemStack(result), recipe); }
@@ -127,6 +133,7 @@
ShapedOreRecipe(ShapedRecipes recipe, Map<ItemStack, String> replacements)
{
+ vanillaRecipe = recipe; // Cauldron - bukkit compatibility
output = recipe.getRecipeOutput();
width = recipe.recipeWidth;
height = recipe.recipeHeight;
@@ -255,4 +262,13 @@
{
return this.input;
}
+
+ // Cauldron start - required for Bukkit API
+ @Override
+ public Recipe toBukkitRecipe() {
+ if (vanillaRecipe != null)
+ return vanillaRecipe.toBukkitRecipe();
+ return new CustomModRecipe(this);
+ }
+ // Cauldron end
}

View File

@ -0,0 +1,49 @@
--- ../src-base/minecraft/net/minecraftforge/oredict/ShapelessOreRecipe.java
+++ ../src-work/minecraft/net/minecraftforge/oredict/ShapelessOreRecipe.java
@@ -6,6 +6,10 @@
import java.util.Map.Entry;
import java.util.List;
+// Cauldron start
+import org.bukkit.inventory.Recipe;
+// Cauldron end
+
import net.minecraft.block.Block;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.inventory.InventoryCrafting;
@@ -13,11 +17,13 @@
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.ShapelessRecipes;
import net.minecraft.world.World;
+import net.minecraftforge.cauldron.inventory.CustomModRecipe;
public class ShapelessOreRecipe implements IRecipe
{
private ItemStack output = null;
private ArrayList<Object> input = new ArrayList<Object>();
+ private ShapelessRecipes vanillaRecipe = null; // Cauldron - bukkit compatibility
public ShapelessOreRecipe(Block result, Object... recipe){ this(new ItemStack(result), recipe); }
public ShapelessOreRecipe(Item result, Object... recipe){ this(new ItemStack(result), recipe); }
@@ -59,6 +65,7 @@
@SuppressWarnings("unchecked")
ShapelessOreRecipe(ShapelessRecipes recipe, Map<ItemStack, String> replacements)
{
+ vanillaRecipe = recipe; // Cauldron - bukkit compatibility
output = recipe.getRecipeOutput();
for(ItemStack ingred : ((List<ItemStack>)recipe.recipeItems))
@@ -146,4 +153,13 @@
{
return this.input;
}
+
+ // Cauldron start - required for Bukkit API
+ @Override
+ public Recipe toBukkitRecipe() {
+ if (vanillaRecipe != null)
+ return vanillaRecipe.toBukkitRecipe();
+ return new CustomModRecipe(this);
+ }
+ // Cauldron end
}