diff --git a/CraftBukkit-Patches/0004-Spigot-Configuration.patch b/CraftBukkit-Patches/0004-Spigot-Configuration.patch index c05d989567..4b64eab6ae 100644 --- a/CraftBukkit-Patches/0004-Spigot-Configuration.patch +++ b/CraftBukkit-Patches/0004-Spigot-Configuration.patch @@ -1,4 +1,4 @@ -From 1dd9dbc277e2a8afd185b7acab193b6913da26e7 Mon Sep 17 00:00:00 2001 +From 23604895a4c7e1eeb6ae4dc364ba42630403f2d9 Mon Sep 17 00:00:00 2001 From: md_5 Date: Tue, 14 May 2013 12:06:27 +1000 Subject: [PATCH] Spigot Configuration @@ -25,6 +25,54 @@ index 7261dc9..10ce69d 100644 if (!this.getOnlineMode()) { this.getLogger().warning("**** SERVER IS RUNNING IN OFFLINE/INSECURE MODE!"); +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 6cb50b7..2956e75 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -145,7 +145,7 @@ public final class CraftServer implements Server { + protected final MinecraftServer console; + protected final DedicatedPlayerList playerList; + private final Map worlds = new LinkedHashMap(); +- private YamlConfiguration configuration; ++ public YamlConfiguration configuration; // Spigot + private final Yaml yaml = new Yaml(new SafeConstructor()); + private final Map offlinePlayers = new MapMaker().softValues().makeMap(); + private final AutoUpdater updater; +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index c0fb528..430a9c0 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -77,6 +77,30 @@ public class CraftWorld implements World { + if (server.chunkGCPeriod > 0) { + chunkGCTickCount = rand.nextInt(server.chunkGCPeriod); + } ++ // Spigot start ++ org.bukkit.configuration.file.YamlConfiguration configuration = server.configuration; ++ String name; ++ if ( world.worldData == null || world.worldData.getName() == null ) ++ { ++ name = "default"; ++ } else ++ { ++ name = world.worldData.getName().replaceAll( " ", "_" ); ++ } ++ ++ // Load defaults first ++ boolean info = configuration.getBoolean( "world-settings.default.info", true ); ++ ++ // Override defaults with world specific, if they exist ++ info = configuration.getBoolean( "world-settings." + name + ".info", info ); ++ ++ if ( info ) ++ { ++ server.getLogger().info( "-------------- Spigot ----------------" ); ++ server.getLogger().info( "-------- World Settings For [" + name + "] --------" ); ++ server.getLogger().info( "-------------------------------------------------" ); ++ } ++ // Spigot end + } + + public Block getBlockAt(int x, int y, int z) { -- 1.8.1.2 diff --git a/CraftBukkit-Patches/0005-Better-Chunk-Tick-Selection.patch b/CraftBukkit-Patches/0005-Better-Chunk-Tick-Selection.patch new file mode 100644 index 0000000000..8a071065ab --- /dev/null +++ b/CraftBukkit-Patches/0005-Better-Chunk-Tick-Selection.patch @@ -0,0 +1,184 @@ +From b50024fe4c26652f55fcb2aa4f395130838e7a49 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Tue, 11 Jun 2013 12:56:02 +1000 +Subject: [PATCH] Better Chunk Tick Selection + + +diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java +index 3a4ddea..ddf84f8 100644 +--- a/src/main/java/net/minecraft/server/World.java ++++ b/src/main/java/net/minecraft/server/World.java +@@ -66,13 +66,35 @@ public abstract class World implements IBlockAccess { + // CraftBukkit start - public, longhashset + public boolean allowMonsters = true; + public boolean allowAnimals = true; +- protected LongHashSet chunkTickList = new LongHashSet(); + public long ticksPerAnimalSpawns; + public long ticksPerMonsterSpawns; + // CraftBukkit end + private int O; + int[] H; + public boolean isStatic; ++ // Spigot start ++ protected final gnu.trove.map.hash.TLongShortHashMap chunkTickList; ++ protected float growthOdds = 100; ++ protected float modifiedOdds = 100; ++ private final byte chunkTickRadius; ++ ++ public static long chunkToKey(int x, int z) ++ { ++ long k = ( ( ( (long) x ) & 0xFFFF0000L ) << 16 ) | ( ( ( (long) x ) & 0x0000FFFFL ) << 0 ); ++ k |= ( ( ( (long) z ) & 0xFFFF0000L ) << 32 ) | ( ( ( (long) z ) & 0x0000FFFFL ) << 16 ); ++ return k; ++ } ++ ++ public static int keyToX(long k) ++ { ++ return (int) ( ( ( k >> 16 ) & 0xFFFF0000 ) | ( k & 0x0000FFFF ) ); ++ } ++ ++ public static int keyToZ(long k) ++ { ++ return (int) ( ( ( k >> 32 ) & 0xFFFF0000L ) | ( ( k >> 16 ) & 0x0000FFFF ) ); ++ } ++ // Spigot end + + public BiomeBase getBiome(int i, int j) { + if (this.isLoaded(i, 0, j)) { +@@ -115,6 +137,11 @@ public abstract class World implements IBlockAccess { + this.ticksPerAnimalSpawns = this.getServer().getTicksPerAnimalSpawns(); // CraftBukkit + this.ticksPerMonsterSpawns = this.getServer().getTicksPerMonsterSpawns(); // CraftBukkit + // CraftBukkit end ++ // Spigot start ++ this.chunkTickRadius = (byte) ( ( this.getServer().getViewDistance() < 7 ) ? this.getServer().getViewDistance() : 7 ); ++ this.chunkTickList = new gnu.trove.map.hash.TLongShortHashMap( world.growthPerTick * 5, 0.7f, Long.MIN_VALUE, Short.MIN_VALUE ); ++ this.chunkTickList.setAutoCompactionFactor( 0 ); ++ // Spigot end + + this.O = this.random.nextInt(12000); + this.H = new int['\u8000']; +@@ -1954,24 +1981,44 @@ public abstract class World implements IBlockAccess { + int j; + int k; + ++ // Spigot start ++ int optimalChunks = this.getWorld().growthPerTick; ++ // Quick conditions to allow us to exist early ++ if ( optimalChunks <= 0 || players.isEmpty() ) ++ { ++ return; ++ } ++ // Keep chunks with growth inside of the optimal chunk range ++ int chunksPerPlayer = Math.min( 200, Math.max( 1, (int) ( ( ( optimalChunks - players.size() ) / (double) players.size() ) + 0.5 ) ) ); ++ int randRange = 3 + chunksPerPlayer / 30; ++ // Limit to normal tick radius - including view distance ++ randRange = ( randRange > chunkTickRadius ) ? chunkTickRadius : randRange; ++ // odds of growth happening vs growth happening in vanilla ++ this.growthOdds = this.modifiedOdds = Math.max( 35, Math.min( 100, ( ( chunksPerPlayer + 1 ) * 100F ) / 15F ) ); ++ // Spigot end + for (i = 0; i < this.players.size(); ++i) { + entityhuman = (EntityHuman) this.players.get(i); + j = MathHelper.floor(entityhuman.locX / 16.0D); + k = MathHelper.floor(entityhuman.locZ / 16.0D); + byte b0 = 7; + +- for (int l = -b0; l <= b0; ++l) { +- for (int i1 = -b0; i1 <= b0; ++i1) { +- // CraftBukkit start - Don't tick chunks queued for unload +- ChunkProviderServer chunkProviderServer = ((WorldServer) entityhuman.world).chunkProviderServer; +- if (chunkProviderServer.unloadQueue.contains(l + j, i1 + k)) { +- continue; +- } +- // CraftBukkit end +- +- this.chunkTickList.add(org.bukkit.craftbukkit.util.LongHash.toLong(l + j, i1 + k)); // CraftBukkit ++ // Spigot start - Always update the chunk the player is on ++ long key = chunkToKey( j, k ); ++ int existingPlayers = Math.max( 0, chunkTickList.get( key ) ); // filter out -1 ++ chunkTickList.put(key, (short) (existingPlayers + 1)); ++ ++ // Check and see if we update the chunks surrounding the player this tick ++ for ( int chunk = 0; chunk < chunksPerPlayer; chunk++ ) ++ { ++ int dx = ( random.nextBoolean() ? 1 : -1 ) * random.nextInt( randRange ); ++ int dz = ( random.nextBoolean() ? 1 : -1 ) * random.nextInt( randRange ); ++ long hash = chunkToKey( dx + j, dz + k ); ++ if ( !chunkTickList.contains( hash ) && this.isChunkLoaded( dx + j, dz + k ) ) ++ { ++ chunkTickList.put( hash, (short) -1 ); // no players + } + } ++ // Spigot End + } + + this.methodProfiler.b(); +diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java +index 49360c1..6c3fcf1 100644 +--- a/src/main/java/net/minecraft/server/WorldServer.java ++++ b/src/main/java/net/minecraft/server/WorldServer.java +@@ -301,9 +301,19 @@ public class WorldServer extends World implements org.bukkit.BlockChangeDelegate + // CraftBukkit start + // Iterator iterator = this.chunkTickList.iterator(); + +- for (long chunkCoord : this.chunkTickList.popAll()) { +- int chunkX = LongHash.msw(chunkCoord); +- int chunkZ = LongHash.lsw(chunkCoord); ++ // Spigot start ++ for (gnu.trove.iterator.TLongShortIterator iter = chunkTickList.iterator(); iter.hasNext();) { ++ iter.advance(); ++ long chunkCoord = iter.key(); ++ int chunkX = World.keyToX(chunkCoord); ++ int chunkZ = World.keyToZ(chunkCoord); ++ // If unloaded, or in procedd of being unloaded, drop it ++ if ( ( !this.isChunkLoaded( chunkX, chunkZ ) ) || ( this.chunkProviderServer.unloadQueue.contains( chunkX, chunkZ ) ) ) ++ { ++ iter.remove(); ++ continue; ++ } ++ // Spigot end + // ChunkCoordIntPair chunkcoordintpair = (ChunkCoordIntPair) iterator.next(); + int k = chunkX * 16; + int l = chunkZ * 16; +@@ -401,6 +411,7 @@ public class WorldServer extends World implements org.bukkit.BlockChangeDelegate + + if (block != null && block.isTicking()) { + ++i; ++ this.growthOdds = (iter.value() < 1) ? this.modifiedOdds : 100; // Spigot - grow fast if no players are in this chunk (value = player count) + block.a(this, k2 + k, i3 + chunksection.getYPosition(), l2 + l, this.random); + } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 430a9c0..d28a4c8 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -67,6 +67,9 @@ public class CraftWorld implements World { + private int chunkGCTickCount; + + private static final Random rand = new Random(); ++ // Spigot start ++ public int growthPerTick = 650; ++ // Spigot end + + public CraftWorld(WorldServer world, ChunkGenerator gen, Environment env) { + this.world = world; +@@ -90,14 +93,17 @@ public class CraftWorld implements World { + + // Load defaults first + boolean info = configuration.getBoolean( "world-settings.default.info", true ); ++ growthPerTick = configuration.getInt( "world-settings.default.growth-chunks-per-tick", growthPerTick ); + + // Override defaults with world specific, if they exist + info = configuration.getBoolean( "world-settings." + name + ".info", info ); ++ growthPerTick = configuration.getInt( "world-settings." + name + ".growth-chunks-per-tick", growthPerTick ); + + if ( info ) + { + server.getLogger().info( "-------------- Spigot ----------------" ); + server.getLogger().info( "-------- World Settings For [" + name + "] --------" ); ++ server.getLogger().info( "Growth Per Tick: " + growthPerTick ); + server.getLogger().info( "-------------------------------------------------" ); + } + // Spigot end +-- +1.8.1.2 +