diff --git a/patches/minecraft/net/minecraft/block/Block.java.patch b/patches/minecraft/net/minecraft/block/Block.java.patch index 425b4bd1b0..91a1c1d28a 100644 --- a/patches/minecraft/net/minecraft/block/Block.java.patch +++ b/patches/minecraft/net/minecraft/block/Block.java.patch @@ -1110,7 +1110,7 @@ + */ + public void setHarvestLevel(String toolClass, int level) + { -+ Iterator itr = getBlockState().getValidStates().iterator(); ++ java.util.Iterator itr = getBlockState().getValidStates().iterator(); + while (itr.hasNext()) + { + setHarvestLevel(toolClass, level, itr.next()); diff --git a/patches/minecraft/net/minecraft/entity/ai/EntityAIAttackOnCollide.java.patch b/patches/minecraft/net/minecraft/entity/ai/EntityAIAttackOnCollide.java.patch index 6060c996e8..e0e63f53ca 100644 --- a/patches/minecraft/net/minecraft/entity/ai/EntityAIAttackOnCollide.java.patch +++ b/patches/minecraft/net/minecraft/entity/ai/EntityAIAttackOnCollide.java.patch @@ -1,6 +1,21 @@ --- ../src-base/minecraft/net/minecraft/entity/ai/EntityAIAttackOnCollide.java +++ ../src-work/minecraft/net/minecraft/entity/ai/EntityAIAttackOnCollide.java -@@ -55,6 +55,19 @@ +@@ -21,11 +21,14 @@ + private double field_151495_j; + private double field_151496_k; + private static final String __OBFID = "CL_00001595"; ++ private int failedPathFindingPenalty = 0; ++ private boolean canPenalize = false; + + public EntityAIAttackOnCollide(EntityCreature p_i1635_1_, Class p_i1635_2_, double p_i1635_3_, boolean p_i1635_5_) + { + this(p_i1635_1_, p_i1635_3_, p_i1635_5_); + this.classTarget = p_i1635_2_; ++ canPenalize = classTarget == null || !net.minecraft.entity.player.EntityPlayer.class.isAssignableFrom(classTarget); //Only enable delaying when not targeting players. + } + + public EntityAIAttackOnCollide(EntityCreature p_i1636_1_, double p_i1636_2_, boolean p_i1636_4_) +@@ -55,6 +58,19 @@ } else { @@ -20,7 +35,7 @@ this.entityPathEntity = this.attacker.getNavigator().getPathToEntityLiving(entitylivingbase); return this.entityPathEntity != null; } -@@ -92,6 +105,23 @@ +@@ -92,6 +108,23 @@ this.field_151496_k = entitylivingbase.posZ; this.field_75445_i = 4 + this.attacker.getRNG().nextInt(7); diff --git a/patches/minecraft/net/minecraft/network/ServerStatusResponse.java.patch b/patches/minecraft/net/minecraft/network/ServerStatusResponse.java.patch index 1acebaeb31..5b32599ba8 100644 --- a/patches/minecraft/net/minecraft/network/ServerStatusResponse.java.patch +++ b/patches/minecraft/net/minecraft/network/ServerStatusResponse.java.patch @@ -38,7 +38,7 @@ return serverstatusresponse; } -@@ -251,6 +256,7 @@ +@@ -251,7 +256,47 @@ jsonobject.addProperty("favicon", p_serialize_1_.getFavicon()); } @@ -46,3 +46,43 @@ return jsonobject; } } ++ ++ private java.util.concurrent.Semaphore mutex = new java.util.concurrent.Semaphore(1); ++ private String json = null; ++ /** ++ * Returns this object as a Json string. ++ * Converting to JSON if a cached version is not available. ++ * ++ * Also to prevent potentially large memory allocations on the server ++ * this is moved from the S00PacketServerInfo writePacket function ++ * ++ * As this method is called from the network threads thread safety is important! ++ * ++ * @return ++ */ ++ public String getJson() ++ { ++ String ret = this.json; ++ if (ret == null) ++ { ++ mutex.acquireUninterruptibly(); ++ ret = this.json; ++ if (ret == null) ++ { ++ ret = net.minecraft.network.status.server.S00PacketServerInfo.GSON.toJson(this); ++ this.json = ret; ++ } ++ mutex.release(); ++ } ++ return ret; ++ } ++ ++ /** ++ * Invalidates the cached json, causing the next call to getJson to rebuild it. ++ * This is needed externally because PlayerCountData.setPlayer's is public. ++ */ ++ public void invalidateJson() ++ { ++ this.json = null; ++ } + } diff --git a/patches/minecraft/net/minecraft/server/MinecraftServer.java.patch b/patches/minecraft/net/minecraft/server/MinecraftServer.java.patch index 319a317428..6347d1b7ca 100644 --- a/patches/minecraft/net/minecraft/server/MinecraftServer.java.patch +++ b/patches/minecraft/net/minecraft/server/MinecraftServer.java.patch @@ -28,7 +28,72 @@ ISaveHandler isavehandler = this.anvilConverterForAnvilFile.getSaveLoader(p_71247_1_, true); this.setResourcePackFromWorld(this.getFolderName(), isavehandler); WorldInfo worldinfo = isavehandler.loadWorldInfo(); -@@ -405,7 +404,7 @@ +@@ -261,47 +260,21 @@ + worldsettings = new WorldSettings(worldinfo); + } + +- for (int i = 0; i < this.worldServers.length; ++i) ++ WorldServer overWorld = (WorldServer)(isDemo() ? new DemoWorldServer(this, isavehandler, worldinfo, 0, theProfiler).init() : new WorldServer(this, isavehandler, worldinfo, 0, theProfiler).init()); ++ overWorld.initialize(worldsettings); ++ for (int dim : net.minecraftforge.common.DimensionManager.getStaticDimensionIDs()) + { +- int j = 0; ++ WorldServer world = (dim == 0 ? overWorld : (WorldServer)new WorldServerMulti(this, isavehandler, dim, overWorld, theProfiler).init()); ++ world.addWorldAccess(new WorldManager(this, world)); + +- if (i == 1) +- { +- j = -1; +- } +- +- if (i == 2) +- { +- j = 1; +- } +- +- if (i == 0) +- { +- if (this.isDemo()) +- { +- this.worldServers[i] = (WorldServer)(new DemoWorldServer(this, isavehandler, worldinfo, j, this.theProfiler)).init(); +- } +- else +- { +- this.worldServers[i] = (WorldServer)(new WorldServer(this, isavehandler, worldinfo, j, this.theProfiler)).init(); +- } +- +- this.worldServers[i].initialize(worldsettings); +- } +- else +- { +- this.worldServers[i] = (WorldServer)(new WorldServerMulti(this, isavehandler, j, this.worldServers[0], this.theProfiler)).init(); +- } +- +- this.worldServers[i].addWorldAccess(new WorldManager(this, this.worldServers[i])); +- + if (!this.isSinglePlayer()) + { +- this.worldServers[i].getWorldInfo().setGameType(this.getGameType()); ++ world.getWorldInfo().setGameType(this.getGameType()); + } ++ net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.world.WorldEvent.Load(world)); + } + +- this.serverConfigManager.setPlayerManager(this.worldServers); ++ this.serverConfigManager.setPlayerManager(new WorldServer[]{ overWorld }); + this.setDifficultyForAllWorlds(this.getDifficulty()); + this.initialWorldChunkLoad(); + } +@@ -316,7 +289,7 @@ + this.setUserMessage("menu.generatingTerrain"); + int j1 = 0; + logger.info("Preparing start region for level " + j1); +- WorldServer worldserver = this.worldServers[j1]; ++ WorldServer worldserver = net.minecraftforge.common.DimensionManager.getWorld(j1); + BlockPos blockpos = worldserver.getSpawnPoint(); + long k1 = getCurrentTimeMillis(); + +@@ -405,7 +378,7 @@ public void stopServer() { @@ -37,7 +102,7 @@ { logger.info("Stopping server"); -@@ -429,8 +428,15 @@ +@@ -429,8 +402,15 @@ for (int i = 0; i < this.worldServers.length; ++i) { WorldServer worldserver = this.worldServers[i]; @@ -53,7 +118,7 @@ } if (this.usageSnooper.isSnooperRunning()) -@@ -462,6 +468,7 @@ +@@ -462,6 +442,7 @@ { if (this.startServer()) { @@ -61,7 +126,7 @@ this.currentTime = getCurrentTimeMillis(); long i = 0L; this.statusResponse.setServerDescription(new ChatComponentText(this.motd)); -@@ -506,12 +513,20 @@ +@@ -506,12 +487,20 @@ Thread.sleep(Math.max(1L, 50L - i)); this.serverIsRunning = true; } @@ -82,7 +147,7 @@ catch (Throwable throwable1) { logger.error("Encountered an unexpected exception", throwable1); -@@ -537,6 +552,7 @@ +@@ -537,6 +526,7 @@ logger.error("We were unable to save this crash report to disk."); } @@ -90,7 +155,7 @@ this.finalTick(crashreport); } finally -@@ -552,6 +568,8 @@ +@@ -552,6 +542,8 @@ } finally { @@ -99,7 +164,7 @@ this.systemExitNow(); } } -@@ -601,6 +619,7 @@ +@@ -601,6 +593,7 @@ public void tick() { long i = System.nanoTime(); @@ -107,7 +172,7 @@ ++this.tickCounter; if (this.startProfiling) -@@ -627,6 +646,7 @@ +@@ -627,6 +620,7 @@ Collections.shuffle(Arrays.asList(agameprofile)); this.statusResponse.getPlayerCountData().setPlayers(agameprofile); @@ -115,7 +180,7 @@ } if (this.tickCounter % 900 == 0) -@@ -654,6 +674,7 @@ +@@ -654,6 +648,7 @@ this.theProfiler.endSection(); this.theProfiler.endSection(); @@ -123,7 +188,36 @@ } public void updateTimeLightAndEntities() -@@ -710,6 +731,7 @@ +@@ -669,14 +664,17 @@ + } + + this.theProfiler.endStartSection("levels"); ++ net.minecraftforge.common.chunkio.ChunkIOExecutor.tick(); + +- for (int j = 0; j < this.worldServers.length; ++j) ++ Integer[] ids = net.minecraftforge.common.DimensionManager.getIDs(this.tickCounter % 200 == 0); ++ for (int x = 0; x < ids.length; x++) + { ++ int id = ids[x]; + long i = System.nanoTime(); + +- if (j == 0 || this.getAllowNether()) ++ if (id == 0 || this.getAllowNether()) + { +- WorldServer worldserver = this.worldServers[j]; ++ WorldServer worldserver = net.minecraftforge.common.DimensionManager.getWorld(id); + this.theProfiler.startSection(worldserver.getWorldInfo().getWorldName()); + + if (this.tickCounter % 20 == 0) +@@ -687,6 +685,7 @@ + } + + this.theProfiler.startSection("tick"); ++ net.minecraftforge.fml.common.FMLCommonHandler.instance().onPreWorldTick(worldserver); + + try + { +@@ -710,6 +709,7 @@ throw new ReportedException(crashreport1); } @@ -131,7 +225,7 @@ this.theProfiler.endSection(); this.theProfiler.startSection("tracker"); worldserver.getEntityTracker().updateTrackedEntities(); -@@ -717,9 +739,11 @@ +@@ -717,9 +717,11 @@ this.theProfiler.endSection(); } @@ -144,7 +238,7 @@ this.theProfiler.endStartSection("connection"); this.getNetworkSystem().networkTick(); this.theProfiler.endStartSection("players"); -@@ -741,6 +765,7 @@ +@@ -741,6 +743,7 @@ public void startServerThread() { @@ -152,7 +246,7 @@ this.serverThread = new Thread(this, "Server thread"); this.serverThread.start(); } -@@ -757,7 +782,13 @@ +@@ -757,7 +760,13 @@ public WorldServer worldServerForDimension(int dimension) { @@ -167,7 +261,7 @@ } public String getMinecraftVersion() -@@ -787,7 +818,7 @@ +@@ -787,7 +796,7 @@ public String getServerModName() { @@ -176,7 +270,7 @@ } public CrashReport addServerInfoToCrashReport(CrashReport report) -@@ -1000,6 +1031,7 @@ +@@ -1000,6 +1009,7 @@ if (worldserver != null) { diff --git a/patches/minecraft/net/minecraft/server/network/NetHandlerLoginServer.java.patch b/patches/minecraft/net/minecraft/server/network/NetHandlerLoginServer.java.patch index 7c5e637060..c27eab907a 100644 --- a/patches/minecraft/net/minecraft/server/network/NetHandlerLoginServer.java.patch +++ b/patches/minecraft/net/minecraft/server/network/NetHandlerLoginServer.java.patch @@ -9,3 +9,12 @@ { this.closeConnection("Took too long to log in"); } +@@ -132,7 +132,7 @@ + } + else + { +- this.server.getConfigurationManager().initializeConnectionToPlayer(this.networkManager, this.server.getConfigurationManager().createPlayerForUser(this.loginGameProfile)); ++ net.minecraftforge.fml.common.network.internal.FMLNetworkHandler.fmlServerHandshake(this.server.getConfigurationManager(), this.networkManager, this.server.getConfigurationManager().createPlayerForUser(this.loginGameProfile)); + } + } + } diff --git a/patches/minecraft/net/minecraft/util/Vec3.java.patch b/patches/minecraft/net/minecraft/util/Vec3.java.patch index cd1142a157..96c890b92a 100644 --- a/patches/minecraft/net/minecraft/util/Vec3.java.patch +++ b/patches/minecraft/net/minecraft/util/Vec3.java.patch @@ -25,3 +25,11 @@ public Vec3 crossProduct(Vec3 vec) { return new Vec3(this.yCoord * vec.zCoord - this.zCoord * vec.yCoord, this.zCoord * vec.xCoord - this.xCoord * vec.zCoord, this.xCoord * vec.yCoord - this.yCoord * vec.xCoord); +@@ -80,7 +75,6 @@ + return new Vec3(this.xCoord + x, this.yCoord + y, this.zCoord + z); + } + +- @SideOnly(Side.CLIENT) + public double distanceTo(Vec3 vec) + { + double d0 = vec.xCoord - this.xCoord; diff --git a/patches/minecraft/net/minecraft/world/biome/BiomeGenBase.java.patch b/patches/minecraft/net/minecraft/world/biome/BiomeGenBase.java.patch new file mode 100644 index 0000000000..ad6f56998d --- /dev/null +++ b/patches/minecraft/net/minecraft/world/biome/BiomeGenBase.java.patch @@ -0,0 +1,138 @@ +--- ../src-base/minecraft/net/minecraft/world/biome/BiomeGenBase.java ++++ ../src-work/minecraft/net/minecraft/world/biome/BiomeGenBase.java +@@ -139,6 +139,10 @@ + + public BiomeGenBase(int p_i1971_1_) + { ++ this(p_i1971_1_, true); ++ } ++ public BiomeGenBase(int p_i1971_1_, boolean register) ++ { + this.minHeight = height_Default.rootHeight; + this.maxHeight = height_Default.variation; + this.temperature = 0.5F; +@@ -153,6 +157,7 @@ + this.worldGeneratorBigTree = new WorldGenBigTree(false); + this.worldGeneratorSwamp = new WorldGenSwamp(); + this.biomeID = p_i1971_1_; ++ if (register) + biomeList[p_i1971_1_] = this; + this.theBiomeDecorator = this.createBiomeDecorator(); + this.spawnableCreatureList.add(new BiomeGenBase.SpawnListEntry(EntitySheep.class, 12, 4, 4)); +@@ -169,11 +174,12 @@ + this.spawnableMonsterList.add(new BiomeGenBase.SpawnListEntry(EntityWitch.class, 5, 1, 1)); + this.spawnableWaterCreatureList.add(new BiomeGenBase.SpawnListEntry(EntitySquid.class, 10, 4, 4)); + this.spawnableCaveCreatureList.add(new BiomeGenBase.SpawnListEntry(EntityBat.class, 10, 8, 8)); ++ this.addDefaultFlowers(); + } + + public BiomeDecorator createBiomeDecorator() + { +- return new BiomeDecorator(); ++ return getModdedBiomeDecorator(new BiomeDecorator()); + } + + public BiomeGenBase setTemperatureRainfall(float p_76732_1_, float p_76732_2_) +@@ -343,7 +349,7 @@ + { + double d0 = (double)MathHelper.clamp_float(this.getFloatTemperature(p_180627_1_), 0.0F, 1.0F); + double d1 = (double)MathHelper.clamp_float(this.getFloatRainfall(), 0.0F, 1.0F); +- return ColorizerGrass.getGrassColor(d0, d1); ++ return getModdedBiomeGrassColor(ColorizerGrass.getGrassColor(d0, d1)); + } + + @SideOnly(Side.CLIENT) +@@ -351,7 +357,7 @@ + { + double d0 = (double)MathHelper.clamp_float(this.getFloatTemperature(p_180625_1_), 0.0F, 1.0F); + double d1 = (double)MathHelper.clamp_float(this.getFloatRainfall(), 0.0F, 1.0F); +- return ColorizerFoliage.getFoliageColor(d0, d1); ++ return getModdedBiomeFoliageColor(ColorizerFoliage.getFoliageColor(d0, d1)); + } + + public boolean isSnowyBiome() +@@ -498,6 +504,84 @@ + } + } + ++ /* ========================================= FORGE START ======================================*/ ++ protected List flowers = new java.util.ArrayList(); ++ ++ public BiomeDecorator getModdedBiomeDecorator(BiomeDecorator original) ++ { ++ return new net.minecraftforge.event.terraingen.DeferredBiomeDecorator(original); ++ } ++ ++ public int getWaterColorMultiplier() ++ { ++ net.minecraftforge.event.terraingen.BiomeEvent.GetWaterColor event = new net.minecraftforge.event.terraingen.BiomeEvent.GetWaterColor(this, waterColorMultiplier); ++ net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(event); ++ return event.newColor; ++ } ++ ++ public int getModdedBiomeGrassColor(int original) ++ { ++ net.minecraftforge.event.terraingen.BiomeEvent.GetGrassColor event = new net.minecraftforge.event.terraingen.BiomeEvent.GetGrassColor(this, original); ++ net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(event); ++ return event.newColor; ++ } ++ ++ public int getModdedBiomeFoliageColor(int original) ++ { ++ net.minecraftforge.event.terraingen.BiomeEvent.GetFoliageColor event = new net.minecraftforge.event.terraingen.BiomeEvent.GetFoliageColor(this, original); ++ net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(event); ++ return event.newColor; ++ } ++ ++ /** ++ * Weighted random holder class used to hold possible flowers ++ * that can spawn in this biome when bonemeal is used on grass. ++ */ ++ public static class FlowerEntry extends WeightedRandom.Item ++ { ++ public final net.minecraft.block.state.IBlockState state; ++ public FlowerEntry(net.minecraft.block.state.IBlockState state, int weight) ++ { ++ super(weight); ++ this.state = state; ++ } ++ } ++ ++ /** ++ * Adds the default flowers, as of 1.7, it is 2 yellow, and 1 red. I chose 10 to allow some wiggle room in the numbers. ++ */ ++ public void addDefaultFlowers() ++ { ++ addFlower(Blocks.yellow_flower.getDefaultState().withProperty(Blocks.yellow_flower.getTypeProperty(), BlockFlower.EnumFlowerType.DANDELION), 20); ++ addFlower(Blocks.red_flower.getDefaultState().withProperty(Blocks.red_flower.getTypeProperty(), BlockFlower.EnumFlowerType.POPPY), 20); ++ } ++ ++ /** Register a new plant to be planted when bonemeal is used on grass. ++ * @param state The block to place. ++ * @param weight The weight of the plant, where red flowers are ++ * 10 and yellow flowers are 20. ++ */ ++ public void addFlower(IBlockState state, int weight) ++ { ++ this.flowers.add(new FlowerEntry(state, weight)); ++ } ++ ++ public void plantFlower(World world, Random rand, BlockPos pos) ++ { ++ FlowerEntry flower = (FlowerEntry)WeightedRandom.getRandomItem(rand, flowers); ++ if (flower == null || flower.state == null || ++ (flower.state.getBlock() instanceof net.minecraft.block.BlockBush && ++ !((net.minecraft.block.BlockBush)flower.state.getBlock()).canBlockStay(world, pos, flower.state))) ++ { ++ return; ++ } ++ ++ world.setBlockState(pos, flower.state, 3); ++ } ++ ++ ++ /* ========================================= FORGE END ======================================*/ ++ + static + { + plains.createMutation(); diff --git a/patches/minecraft/net/minecraft/world/chunk/storage/AnvilChunkLoader.java.patch b/patches/minecraft/net/minecraft/world/chunk/storage/AnvilChunkLoader.java.patch new file mode 100644 index 0000000000..3ed1e56b30 --- /dev/null +++ b/patches/minecraft/net/minecraft/world/chunk/storage/AnvilChunkLoader.java.patch @@ -0,0 +1,162 @@ +--- ../src-base/minecraft/net/minecraft/world/chunk/storage/AnvilChunkLoader.java ++++ ../src-work/minecraft/net/minecraft/world/chunk/storage/AnvilChunkLoader.java +@@ -43,8 +43,41 @@ + this.chunkSaveLocation = chunkSaveLocationIn; + } + ++ public boolean chunkExists(World world, int x, int z) ++ { ++ ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(x, z); ++ ++ if (this.pendingAnvilChunksCoordinates.contains(chunkcoordintpair)) ++ { ++ for(ChunkCoordIntPair pendingChunkCoord : this.chunksToRemove.keySet()) ++ { ++ if (pendingChunkCoord.equals(chunkcoordintpair)) ++ { ++ return true; ++ } ++ } ++ } ++ ++ return RegionFileCache.createOrLoadRegionFile(this.chunkSaveLocation, x, z).chunkExists(x & 31, z & 31); ++ } ++ + public Chunk loadChunk(World worldIn, int x, int z) throws IOException + { ++ Object[] data = this.loadChunk__Async(worldIn, x, z); ++ ++ if (data != null) ++ { ++ Chunk chunk = (Chunk) data[0]; ++ NBTTagCompound nbttagcompound = (NBTTagCompound) data[1]; ++ this.loadEntities(worldIn, nbttagcompound.getCompoundTag("Level"), chunk); ++ return chunk; ++ } ++ ++ return null; ++ } ++ ++ public Object[] loadChunk__Async(World worldIn, int x, int z) throws IOException ++ { + ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(x, z); + NBTTagCompound nbttagcompound = (NBTTagCompound)this.chunksToRemove.get(chunkcoordintpair); + +@@ -60,11 +93,17 @@ + nbttagcompound = CompressedStreamTools.read(datainputstream); + } + +- return this.checkedReadChunkFromNBT(worldIn, x, z, nbttagcompound); ++ return this.checkedReadChunkFromNBT__Async(worldIn, x, z, nbttagcompound); + } + + protected Chunk checkedReadChunkFromNBT(World worldIn, int x, int z, NBTTagCompound p_75822_4_) + { ++ Object[] data = this.checkedReadChunkFromNBT__Async(worldIn, x, z, p_75822_4_); ++ return data != null ? (Chunk)data[0] : null; ++ } ++ ++ protected Object[] checkedReadChunkFromNBT__Async(World worldIn, int x, int z, NBTTagCompound p_75822_4_) ++ { + if (!p_75822_4_.hasKey("Level", 10)) + { + logger.error("Chunk file at " + x + "," + z + " is missing level data, skipping"); +@@ -88,10 +127,29 @@ + logger.error("Chunk file at " + x + "," + z + " is in the wrong location; relocating. (Expected " + x + ", " + z + ", got " + chunk.xPosition + ", " + chunk.zPosition + ")"); + nbttagcompound.setInteger("xPos", x); + nbttagcompound.setInteger("zPos", z); ++ ++ // Have to move tile entities since we don't load them at this stage ++ NBTTagList _tileEntities = nbttagcompound.getTagList("TileEntities", 10); ++ ++ if (_tileEntities != null) ++ { ++ for (int te = 0; te < _tileEntities.tagCount(); te++) ++ { ++ NBTTagCompound _nbt = (NBTTagCompound) _tileEntities.getCompoundTagAt(te); ++ _nbt.setInteger("x", x * 16 + (_nbt.getInteger("x") - chunk.xPosition * 16)); ++ _nbt.setInteger("z", z * 16 + (_nbt.getInteger("z") - chunk.zPosition * 16)); ++ } ++ } ++ + chunk = this.readChunkFromNBT(worldIn, nbttagcompound); + } + +- return chunk; ++ Object[] data = new Object[2]; ++ data[0] = chunk; ++ data[1] = p_75822_4_; ++ // event is fired in ChunkIOProvider.callStage2 since it must be fired after TE's load. ++ // MinecraftForge.EVENT_BUS.post(new ChunkDataEvent.Load(chunk, par4NBTTagCompound)); ++ return data; + } + } + } +@@ -106,6 +164,7 @@ + NBTTagCompound nbttagcompound1 = new NBTTagCompound(); + nbttagcompound.setTag("Level", nbttagcompound1); + this.writeChunkToNBT(chunkIn, worldIn, nbttagcompound1); ++ net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.world.ChunkDataEvent.Save(chunkIn, nbttagcompound)); + this.addChunkToPending(chunkIn.getChunkCoordIntPair(), nbttagcompound); + } + catch (Exception exception) +@@ -282,11 +341,20 @@ + { + NBTTagCompound nbttagcompound1 = new NBTTagCompound(); + ++ try ++ { + if (entity.writeToNBTOptional(nbttagcompound1)) + { + chunkIn.setHasEntities(true); + nbttaglist1.appendTag(nbttagcompound1); + } ++ } ++ catch (Exception e) ++ { ++ net.minecraftforge.fml.common.FMLLog.log(org.apache.logging.log4j.Level.ERROR, e, ++ "An Entity type %s has thrown an exception trying to write state. It will not persist. Report this to the mod author", ++ entity.getClass().getName()); ++ } + } + } + +@@ -296,8 +364,17 @@ + for (TileEntity tileentity : chunkIn.getTileEntityMap().values()) + { + NBTTagCompound nbttagcompound2 = new NBTTagCompound(); ++ try ++ { + tileentity.writeToNBT(nbttagcompound2); + nbttaglist2.appendTag(nbttagcompound2); ++ } ++ catch (Exception e) ++ { ++ net.minecraftforge.fml.common.FMLLog.log(org.apache.logging.log4j.Level.ERROR, e, ++ "A TileEntity type %s has throw an exception trying to write state. It will not persist. Report this to the mod author", ++ tileentity.getClass().getName()); ++ } + } + + p_75820_3_.setTag("TileEntities", nbttaglist2); +@@ -377,6 +454,12 @@ + chunk.setBiomeArray(p_75823_2_.getByteArray("Biomes")); + } + ++ // End this method here and split off entity loading to another method ++ return chunk; ++ } ++ ++ public void loadEntities(World worldIn, NBTTagCompound p_75823_2_, Chunk chunk) ++ { + NBTTagList nbttaglist1 = p_75823_2_.getTagList("Entities", 10); + + if (nbttaglist1 != null) +@@ -448,7 +531,5 @@ + } + } + } +- +- return chunk; + } + } diff --git a/patches/minecraft/net/minecraft/world/gen/ChunkProviderServer.java.patch b/patches/minecraft/net/minecraft/world/gen/ChunkProviderServer.java.patch new file mode 100644 index 0000000000..284195ebf2 --- /dev/null +++ b/patches/minecraft/net/minecraft/world/gen/ChunkProviderServer.java.patch @@ -0,0 +1,125 @@ +--- ../src-base/minecraft/net/minecraft/world/gen/ChunkProviderServer.java ++++ ../src-work/minecraft/net/minecraft/world/gen/ChunkProviderServer.java +@@ -36,6 +36,7 @@ + public LongHashMap id2ChunkMap = new LongHashMap(); + public List loadedChunks = Lists.newArrayList(); + public WorldServer worldObj; ++ private Set loadingChunks = com.google.common.collect.Sets.newHashSet(); + private static final String __OBFID = "CL_00001436"; + + public ChunkProviderServer(WorldServer p_i1520_1_, IChunkLoader p_i1520_2_, IChunkProvider p_i1520_3_) +@@ -58,7 +59,7 @@ + + public void dropChunk(int p_73241_1_, int p_73241_2_) + { +- if (this.worldObj.provider.canRespawnHere()) ++ if (this.worldObj.provider.canRespawnHere() && net.minecraftforge.common.DimensionManager.shouldLoadSpawn(this.worldObj.provider.getDimensionId())) + { + if (!this.worldObj.isSpawnChunk(p_73241_1_, p_73241_2_)) + { +@@ -81,12 +82,64 @@ + + public Chunk loadChunk(int p_73158_1_, int p_73158_2_) + { ++ return loadChunk(p_73158_1_, p_73158_2_, null); ++ } ++ ++ public Chunk loadChunk(int par1, int par2, Runnable runnable) ++ { ++ long k = ChunkCoordIntPair.chunkXZ2Int(par1, par2); ++ this.droppedChunksSet.remove(Long.valueOf(k)); ++ Chunk chunk = (Chunk)this.id2ChunkMap.getValueByKey(k); ++ net.minecraft.world.chunk.storage.AnvilChunkLoader loader = null; ++ ++ if (this.chunkLoader instanceof net.minecraft.world.chunk.storage.AnvilChunkLoader) ++ { ++ loader = (net.minecraft.world.chunk.storage.AnvilChunkLoader) this.chunkLoader; ++ } ++ ++ // We can only use the queue for already generated chunks ++ if (chunk == null && loader != null && loader.chunkExists(this.worldObj, par1, par2)) ++ { ++ if (runnable != null) ++ { ++ net.minecraftforge.common.chunkio.ChunkIOExecutor.queueChunkLoad(this.worldObj, loader, this, par1, par2, runnable); ++ return null; ++ } ++ else ++ { ++ chunk = net.minecraftforge.common.chunkio.ChunkIOExecutor.syncChunkLoad(this.worldObj, loader, this, par1, par2); ++ } ++ } ++ else if (chunk == null) ++ { ++ chunk = this.originalLoadChunk(par1, par2); ++ } ++ ++ // If we didn't load the chunk async and have a callback run it now ++ if (runnable != null) ++ { ++ runnable.run(); ++ } ++ ++ return chunk; ++ } ++ ++ public Chunk originalLoadChunk(int p_73158_1_, int p_73158_2_) ++ { + long i = ChunkCoordIntPair.chunkXZ2Int(p_73158_1_, p_73158_2_); + this.droppedChunksSet.remove(Long.valueOf(i)); + Chunk chunk = (Chunk)this.id2ChunkMap.getValueByKey(i); + + if (chunk == null) + { ++ boolean added = loadingChunks.add(i); ++ if (!added) ++ { ++ net.minecraftforge.fml.common.FMLLog.bigWarning("There is an attempt to load a chunk (%d,%d) in di >mension %d that is already being loaded. This will cause weird chunk breakages.", p_73158_1_, p_73158_2_, worldObj.provider.getDimensionId()); ++ } ++ chunk = net.minecraftforge.common.ForgeChunkManager.fetchDormantChunk(i, this.worldObj); ++ ++ if (chunk == null) + chunk = this.loadChunkFromFile(p_73158_1_, p_73158_2_); + + if (chunk == null) +@@ -115,6 +168,7 @@ + + this.id2ChunkMap.add(i, chunk); + this.loadedChunks.add(chunk); ++ loadingChunks.remove(i); + chunk.onChunkLoad(); + chunk.populateChunk(this, this, p_73158_1_, p_73158_2_); + } +@@ -206,6 +260,7 @@ + if (this.serverChunkGenerator != null) + { + this.serverChunkGenerator.populate(p_73153_1_, p_73153_2_, p_73153_3_); ++ net.minecraftforge.fml.common.registry.GameRegistry.generateWorld(p_73153_2_, p_73153_3_, worldObj, serverChunkGenerator, p_73153_1_); + chunk.setChunkModified(); + } + } +@@ -267,6 +322,11 @@ + { + if (!this.worldObj.disableLevelSaving) + { ++ for (ChunkCoordIntPair forced : this.worldObj.getPersistentChunks().keySet()) ++ { ++ this.droppedChunksSet.remove(ChunkCoordIntPair.chunkXZ2Int(forced.chunkXPos, forced.chunkZPos)); ++ } ++ + for (int i = 0; i < 100; ++i) + { + if (!this.droppedChunksSet.isEmpty()) +@@ -281,6 +341,12 @@ + this.saveChunkExtraData(chunk); + this.id2ChunkMap.remove(olong.longValue()); + this.loadedChunks.remove(chunk); ++ net.minecraftforge.common.ForgeChunkManager.putDormantChunk(ChunkCoordIntPair.chunkXZ2Int(chunk.xPosition, chunk.zPosition), chunk); ++ if(loadedChunks.size() == 0 && net.minecraftforge.common.ForgeChunkManager.getPersistentChunksFor(this.worldObj).size() == 0 && !net.minecraftforge.common.DimensionManager.shouldLoadSpawn(this.worldObj.provider.getDimensionId())){ ++ net.minecraftforge.common.DimensionManager.unloadWorld(this.worldObj.provider.getDimensionId()); ++ return serverChunkGenerator.unloadQueuedChunks(); ++ } ++ + } + + this.droppedChunksSet.remove(olong); diff --git a/patches/minecraft/net/minecraft/world/gen/MapGenRavine.java.patch b/patches/minecraft/net/minecraft/world/gen/MapGenRavine.java.patch index 8671a0f119..48e386ee64 100644 --- a/patches/minecraft/net/minecraft/world/gen/MapGenRavine.java.patch +++ b/patches/minecraft/net/minecraft/world/gen/MapGenRavine.java.patch @@ -5,11 +5,42 @@ IBlockState iblockstate = p_180707_5_.getBlockState(j1, l1, k1); - if (iblockstate.getBlock() == Blocks.flowing_water || iblockstate.getBlock() == Blocks.water) -+ if (isOceanBlock(p_180707_5_, k2, i2, l2, p_180707_3_, p_180707_4_)) ++ if (isOceanBlock(p_180707_5_, j1, l1, k1, p_180707_3_, p_180707_4_)) { flag2 = true; } -@@ -222,4 +222,68 @@ +@@ -166,28 +166,12 @@ + { + IBlockState iblockstate1 = p_180707_5_.getBlockState(j3, j2, i2); + +- if (iblockstate1.getBlock() == Blocks.grass) ++ if (isTopBlock(p_180707_5_, j3, j2, i2, p_180707_3_, p_180707_4_)) + { + flag = true; + } + +- if (iblockstate1.getBlock() == Blocks.stone || iblockstate1.getBlock() == Blocks.dirt || iblockstate1.getBlock() == Blocks.grass) +- { +- if (j2 - 1 < 10) +- { +- p_180707_5_.setBlockState(j3, j2, i2, Blocks.flowing_lava.getDefaultState()); +- } +- else +- { +- p_180707_5_.setBlockState(j3, j2, i2, Blocks.air.getDefaultState()); +- +- if (flag && p_180707_5_.getBlockState(j3, j2 - 1, i2).getBlock() == Blocks.dirt) +- { +- blockpos$mutableblockpos.func_181079_c(j3 + p_180707_3_ * 16, 0, i2 + p_180707_4_ * 16); +- p_180707_5_.setBlockState(j3, j2 - 1, i2, this.worldObj.getBiomeGenForCoords(blockpos$mutableblockpos).topBlock); +- } +- } +- } ++ digBlock(p_180707_5_, j3, j2, i2, p_180707_3_, p_180707_4_, flag); + } + } + } +@@ -222,4 +206,68 @@ } } } diff --git a/rejects/minecraft/net/minecraft/entity/ai/EntityAIAttackOnCollide.java.patch.rej b/rejects/minecraft/net/minecraft/entity/ai/EntityAIAttackOnCollide.java.patch.rej deleted file mode 100644 index 6ae31bd0f5..0000000000 --- a/rejects/minecraft/net/minecraft/entity/ai/EntityAIAttackOnCollide.java.patch.rej +++ /dev/null @@ -1,16 +0,0 @@ -++++ REJECTED PATCH 1 - private double field_151495_j; - private double field_151496_k; - private static final String __OBFID = "CL_00001595"; -+ private int failedPathFindingPenalty = 0; -+ private boolean canPenalize = false; - - public EntityAIAttackOnCollide(EntityCreature p_i1635_1_, Class p_i1635_2_, double p_i1635_3_, boolean p_i1635_5_) - { - this(p_i1635_1_, p_i1635_3_, p_i1635_5_); - this.classTarget = p_i1635_2_; -+ canPenalize = classTarget == null || !net.minecraft.entity.player.EntityPlayer.class.isAssignableFrom(classTarget); //Only enable delaying when not targeting players. - } - - public EntityAIAttackOnCollide(EntityCreature p_i1636_1_, double p_i1636_2_, boolean p_i1636_4_) -++++ END PATCH diff --git a/rejects/minecraft/net/minecraft/network/ServerStatusResponse.java.patch.rej b/rejects/minecraft/net/minecraft/network/ServerStatusResponse.java.patch.rej deleted file mode 100644 index e909ac525f..0000000000 --- a/rejects/minecraft/net/minecraft/network/ServerStatusResponse.java.patch.rej +++ /dev/null @@ -1,45 +0,0 @@ -++++ REJECTED PATCH 6 - return this.serialize((ServerStatusResponse)p_serialize_1_, p_serialize_2_, p_serialize_3_); - } - } -+ -+ private java.util.concurrent.Semaphore mutex = new java.util.concurrent.Semaphore(1); -+ private String json = null; -+ /** -+ * Returns this object as a Json string. -+ * Converting to JSON if a cached version is not available. -+ * -+ * Also to prevent potentially large memory allocations on the server -+ * this is moved from the S00PacketServerInfo writePacket function -+ * -+ * As this method is called from the network threads thread safety is important! -+ * -+ * @return -+ */ -+ public String getJson() -+ { -+ String ret = this.json; -+ if (ret == null) -+ { -+ mutex.acquireUninterruptibly(); -+ ret = this.json; -+ if (ret == null) -+ { -+ ret = net.minecraft.network.status.server.S00PacketServerInfo.GSON.toJson(this); -+ this.json = ret; -+ } -+ mutex.release(); -+ } -+ return ret; -+ } -+ -+ /** -+ * Invalidates the cached json, causing the next call to getJson to rebuild it. -+ * This is needed externally because PlayerCountData.setPlayer's is public. -+ */ -+ public void invalidateJson() -+ { -+ this.json = null; -+ } - } -++++ END PATCH diff --git a/rejects/minecraft/net/minecraft/server/MinecraftServer.java.patch.rej b/rejects/minecraft/net/minecraft/server/MinecraftServer.java.patch.rej index cfdcbd57e2..43108a30c5 100644 --- a/rejects/minecraft/net/minecraft/server/MinecraftServer.java.patch.rej +++ b/rejects/minecraft/net/minecraft/server/MinecraftServer.java.patch.rej @@ -1,79 +1,4 @@ -++++ REJECTED PATCH 4 - worldsettings = new WorldSettings(worldinfo); - } - -- for (int j = 0; j < this.worldServers.length; ++j) -+ WorldServer overWorld = (WorldServer)(isDemo() ? new DemoWorldServer(this, isavehandler, worldinfo, 0, theProfiler).init() : new WorldServer(this, isavehandler, worldinfo, 0, theProfiler).init()); -+ overWorld.initialize(worldsettings); -+ for (int dim : net.minecraftforge.common.DimensionManager.getStaticDimensionIDs()) - { -- byte b0 = 0; -+ WorldServer world = (dim == 0 ? overWorld : (WorldServer)new WorldServerMulti(this, isavehandler, dim, overWorld, theProfiler).init()); -+ world.addWorldAccess(new WorldManager(this, world)); - -- if (j == 1) -- { -- b0 = -1; -- } -- -- if (j == 2) -- { -- b0 = 1; -- } -- -- if (j == 0) -- { -- if (this.isDemo()) -- { -- this.worldServers[j] = (WorldServer)(new DemoWorldServer(this, isavehandler, worldinfo, b0, this.theProfiler)).init(); -- } -- else -- { -- this.worldServers[j] = (WorldServer)(new WorldServer(this, isavehandler, worldinfo, b0, this.theProfiler)).init(); -- } -- -- this.worldServers[j].initialize(worldsettings); -- } -- else -- { -- this.worldServers[j] = (WorldServer)(new WorldServerMulti(this, isavehandler, b0, this.worldServers[0], this.theProfiler)).init(); -- } -- -- this.worldServers[j].addWorldAccess(new WorldManager(this, this.worldServers[j])); -- - if (!this.isSinglePlayer()) - { -- this.worldServers[j].getWorldInfo().setGameType(this.getGameType()); -+ world.getWorldInfo().setGameType(this.getGameType()); - } -+ net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.world.WorldEvent.Load(world)); - } - -- this.serverConfigManager.setPlayerManager(this.worldServers); -+ this.serverConfigManager.setPlayerManager(new WorldServer[]{ overWorld }); - this.setDifficultyForAllWorlds(this.getDifficulty()); - this.initialWorldChunkLoad(); - } -++++ END PATCH -++++ REJECTED PATCH 5 - this.setUserMessage("menu.generatingTerrain"); - byte b0 = 0; - logger.info("Preparing start region for level " + b0); -- WorldServer worldserver = this.worldServers[b0]; -+ WorldServer worldserver = net.minecraftforge.common.DimensionManager.getWorld(b0); - BlockPos blockpos = worldserver.getSpawnPoint(); - long j = getCurrentTimeMillis(); - -++++ END PATCH -++++ REJECTED PATCH 6 - if (!this.worldIsBeingDeleted) - { - WorldServer[] aworldserver = this.worldServers; -+ if (aworldserver == null) return; //Forge: Just in case, NPE protection as it has been encountered. - int i = aworldserver.length; - - for (int j = 0; j < i; ++j) -++++ END PATCH +// do we still need this? ++++ REJECTED PATCH 16 { try @@ -84,44 +9,3 @@ catch (Throwable throwable2) { ++++ END PATCH -++++ REJECTED PATCH 17 - } - - this.theProfiler.endStartSection("levels"); -+ net.minecraftforge.common.chunkio.ChunkIOExecutor.tick(); - int j; - -- for (j = 0; j < this.worldServers.length; ++j) -+ Integer[] ids = net.minecraftforge.common.DimensionManager.getIDs(this.tickCounter % 200 == 0); -+ for (int x = 0; x < ids.length; x++) - { -+ int id = ids[x]; - long i = System.nanoTime(); - -- if (j == 0 || this.getAllowNether()) -+ if (id == 0 || this.getAllowNether()) - { -- WorldServer worldserver = this.worldServers[j]; -+ WorldServer worldserver = net.minecraftforge.common.DimensionManager.getWorld(id); - this.theProfiler.startSection(worldserver.getWorldInfo().getWorldName()); - - if (this.tickCounter % 20 == 0) -++++ END PATCH -++++ REJECTED PATCH 18 - } - - this.theProfiler.startSection("tick"); -+ net.minecraftforge.fml.common.FMLCommonHandler.instance().onPreWorldTick(worldserver); - CrashReport crashreport; - - try -++++ END PATCH -++++ REJECTED PATCH 25 - this.serverPort = port; - } - -- @SideOnly(Side.SERVER) - public boolean isServerStopped() - { - return this.serverStopped; -++++ END PATCH diff --git a/rejects/minecraft/net/minecraft/server/network/NetHandlerLoginServer.java.patch.rej b/rejects/minecraft/net/minecraft/server/network/NetHandlerLoginServer.java.patch.rej deleted file mode 100644 index 6b058fdfe3..0000000000 --- a/rejects/minecraft/net/minecraft/server/network/NetHandlerLoginServer.java.patch.rej +++ /dev/null @@ -1,10 +0,0 @@ -++++ REJECTED PATCH 2 - } - - this.networkManager.sendPacket(new S02PacketLoginSuccess(this.loginGameProfile)); -- this.server.getConfigurationManager().initializeConnectionToPlayer(this.networkManager, this.server.getConfigurationManager().createPlayerForUser(this.loginGameProfile)); -+ net.minecraftforge.fml.common.network.internal.FMLNetworkHandler.fmlServerHandshake(this.server.getConfigurationManager(), this.networkManager, this.server.getConfigurationManager().createPlayerForUser(this.loginGameProfile)); - } - } - -++++ END PATCH diff --git a/rejects/minecraft/net/minecraft/world/gen/MapGenRavine.java.patch.rej b/rejects/minecraft/net/minecraft/world/gen/MapGenRavine.java.patch.rej deleted file mode 100644 index 091395f9c1..0000000000 --- a/rejects/minecraft/net/minecraft/world/gen/MapGenRavine.java.patch.rej +++ /dev/null @@ -1,31 +0,0 @@ -++++ REJECTED PATCH 2 - { - IBlockState iblockstate1 = p_180707_5_.getBlockState(k2, j3, j4); - -- if (iblockstate1.getBlock() == Blocks.grass) -+ if (isTopBlock(p_180707_5_, k2, j3, j4, p_180707_3_, p_180707_4_)) - { - flag = true; - } - -- if (iblockstate1.getBlock() == Blocks.stone || iblockstate1.getBlock() == Blocks.dirt || iblockstate1.getBlock() == Blocks.grass) -- { -- if (j3 - 1 < 10) -- { -- p_180707_5_.setBlockState(k2, j3, j4, Blocks.flowing_lava.getDefaultState()); -- } -- else -- { -- p_180707_5_.setBlockState(k2, j3, j4, Blocks.air.getDefaultState()); -- -- if (flag && p_180707_5_.getBlockState(k2, j3 - 1, j4).getBlock() == Blocks.dirt) -- { -- p_180707_5_.setBlockState(k2, j3 - 1, j4, this.worldObj.getBiomeGenForCoords(new BlockPos(k2 + p_180707_3_ * 16, 0, j4 + p_180707_4_ * 16)).topBlock); -- } -- } -- } -+ digBlock(p_180707_5_, k2, j3, j4, p_180707_3_, p_180707_4_, flag); - } - } - } -++++ END PATCH diff --git a/src/main/java/net/minecraftforge/client/GuiIngameForge.java b/src/main/java/net/minecraftforge/client/GuiIngameForge.java index 8025d44e0c..5c3adae6b2 100644 --- a/src/main/java/net/minecraftforge/client/GuiIngameForge.java +++ b/src/main/java/net/minecraftforge/client/GuiIngameForge.java @@ -94,7 +94,7 @@ public class GuiIngameForge extends GuiIngame @Override public void renderGameOverlay(float partialTicks) { - res = new ScaledResolution(mc, mc.displayWidth, mc.displayHeight); + res = new ScaledResolution(mc); eventParent = new RenderGameOverlayEvent(partialTicks, res); int width = res.getScaledWidth(); int height = res.getScaledHeight();