diff --git a/nms-patches/ChunkProviderServer.patch b/nms-patches/ChunkProviderServer.patch index adb0b48483..1309bf5263 100644 --- a/nms-patches/ChunkProviderServer.patch +++ b/nms-patches/ChunkProviderServer.patch @@ -83,7 +83,7 @@ public void tick(BooleanSupplier booleansupplier) { this.world.getMethodProfiler().enter("purge"); this.chunkMapDistance.purgeTickets(); -@@ -318,13 +346,13 @@ +@@ -318,13 +346,19 @@ this.lastTickTime = i; WorldData worlddata = this.world.getWorldData(); boolean flag = worlddata.getType() == WorldType.DEBUG_ALL_BLOCK_STATES; @@ -95,32 +95,43 @@ int k = this.world.getGameRules().getInt(GameRules.RANDOM_TICK_SPEED); BlockPosition blockposition = this.world.getSpawn(); - boolean flag2 = worlddata.getTime() % 400L == 0L; -+ boolean flag2 = world.ticksPerAnimalSpawns != 0L && worlddata.getTime() % world.ticksPerAnimalSpawns == 0L; // CraftBukkit // PAIL: TODO monster ticks ++ // CraftBukkit start - Other mob type spawn tick rate ++ boolean spawnAnimalThisTick = world.ticksPerAnimalSpawns != 0L && worlddata.getTime() % world.ticksPerAnimalSpawns == 0L; ++ boolean spawnMonsterThisTick = world.ticksPerMonsterSpawns != 0L && worlddata.getTime() % world.ticksPerMonsterSpawns == 0L; ++ boolean spawnWaterThisTick = world.ticksPerWaterSpawns != 0L && worlddata.getTime() % world.ticksPerWaterSpawns == 0L; ++ boolean spawnAmbientThisTick = world.ticksPerAmbientSpawns != 0L && worlddata.getTime() % world.ticksPerAmbientSpawns == 0L; ++ boolean flag2 = spawnAnimalThisTick; ++ // CraftBukkit end this.world.getMethodProfiler().enter("naturalSpawnCount"); int l = this.chunkMapDistance.b(); -@@ -353,8 +381,30 @@ +@@ -353,8 +387,35 @@ for (int j1 = 0; j1 < i1; ++j1) { EnumCreatureType enumcreaturetype = aenumcreaturetype1[j1]; + // CraftBukkit start - Use per-world spawn limits ++ boolean spawnThisTick = true; + int limit = enumcreaturetype.b(); + switch (enumcreaturetype) { + case MONSTER: ++ spawnThisTick = spawnMonsterThisTick; + limit = world.getWorld().getMonsterSpawnLimit(); + break; + case CREATURE: ++ spawnThisTick = spawnAnimalThisTick; + limit = world.getWorld().getAnimalSpawnLimit(); + break; + case WATER_CREATURE: ++ spawnThisTick = spawnWaterThisTick; + limit = world.getWorld().getWaterAnimalSpawnLimit(); + break; + case AMBIENT: ++ spawnThisTick = spawnAmbientThisTick; + limit = world.getWorld().getAmbientSpawnLimit(); + break; + } + -+ if (limit == 0) { ++ if (!spawnThisTick || limit == 0) { + continue; + } + // CraftBukkit end @@ -131,7 +142,7 @@ if (object2intmap.getInt(enumcreaturetype) <= k1) { SpawnerCreature.a(enumcreaturetype, this.world, chunk, blockposition); -@@ -507,12 +557,18 @@ +@@ -507,12 +568,18 @@ @Override protected boolean executeNext() { diff --git a/nms-patches/World.patch b/nms-patches/World.patch index fa0ca962d3..459078da7d 100644 --- a/nms-patches/World.patch +++ b/nms-patches/World.patch @@ -18,7 +18,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { protected static final Logger LOGGER = LogManager.getLogger(); -@@ -40,7 +51,39 @@ +@@ -40,7 +51,43 @@ private final WorldBorder worldBorder; private final BiomeManager biomeManager; @@ -36,6 +36,8 @@ + public List captureDrops; + public long ticksPerAnimalSpawns; + public long ticksPerMonsterSpawns; ++ public long ticksPerWaterSpawns; ++ public long ticksPerAmbientSpawns; + public boolean populating; + + public CraftWorld getWorld() { @@ -55,11 +57,13 @@ + this.world = new CraftWorld((WorldServer) this, gen, env); + this.ticksPerAnimalSpawns = this.getServer().getTicksPerAnimalSpawns(); // CraftBukkit + this.ticksPerMonsterSpawns = this.getServer().getTicksPerMonsterSpawns(); // CraftBukkit ++ this.ticksPerWaterSpawns = this.getServer().getTicksPerWaterSpawns(); // CraftBukkit ++ this.ticksPerAmbientSpawns = this.getServer().getTicksPerAmbientSpawns(); // CraftBukkit + // CraftBukkit end this.methodProfiler = gameprofilerfiller; this.worldData = worlddata; this.worldProvider = dimensionmanager.getWorldProvider(this); -@@ -49,6 +92,35 @@ +@@ -49,6 +96,35 @@ this.worldBorder = this.worldProvider.getWorldBorder(); this.serverThread = Thread.currentThread(); this.biomeManager = new BiomeManager(this, flag ? worlddata.getSeed() : WorldData.c(worlddata.getSeed()), dimensionmanager.getGenLayerZoomer()); @@ -95,7 +99,7 @@ } @Override -@@ -105,6 +177,17 @@ +@@ -105,6 +181,17 @@ @Override public boolean setTypeAndData(BlockPosition blockposition, IBlockData iblockdata, int i) { @@ -113,7 +117,7 @@ if (isOutsideWorld(blockposition)) { return false; } else if (!this.isClientSide && this.worldData.getType() == WorldType.DEBUG_ALL_BLOCK_STATES) { -@@ -112,9 +195,22 @@ +@@ -112,9 +199,22 @@ } else { Chunk chunk = this.getChunkAtWorldCoords(blockposition); Block block = iblockdata.getBlock(); @@ -137,7 +141,7 @@ return false; } else { IBlockData iblockdata2 = this.getType(blockposition); -@@ -125,6 +221,7 @@ +@@ -125,6 +225,7 @@ this.methodProfiler.exit(); } @@ -145,7 +149,7 @@ if (iblockdata2 == iblockdata) { if (iblockdata1 != iblockdata2) { this.b(blockposition, iblockdata1, iblockdata2); -@@ -151,12 +248,65 @@ +@@ -151,12 +252,65 @@ this.a(blockposition, iblockdata1, iblockdata2); } @@ -211,7 +215,7 @@ public void a(BlockPosition blockposition, IBlockData iblockdata, IBlockData iblockdata1) {} @Override -@@ -195,6 +345,11 @@ +@@ -195,6 +349,11 @@ @Override public void update(BlockPosition blockposition, Block block) { if (this.worldData.getType() != WorldType.DEBUG_ALL_BLOCK_STATES) { @@ -223,7 +227,7 @@ this.applyPhysics(blockposition, block); } -@@ -243,6 +398,17 @@ +@@ -243,6 +402,17 @@ IBlockData iblockdata = this.getType(blockposition); try { @@ -241,7 +245,7 @@ iblockdata.doPhysics(this, blockposition, block, blockposition1, false); } catch (Throwable throwable) { CrashReport crashreport = CrashReport.a(throwable, "Exception while updating neighbours"); -@@ -285,6 +451,14 @@ +@@ -285,6 +455,14 @@ @Override public IBlockData getType(BlockPosition blockposition) { @@ -256,7 +260,7 @@ if (isOutsideWorld(blockposition)) { return Blocks.VOID_AIR.getBlockData(); } else { -@@ -306,11 +480,11 @@ +@@ -306,11 +484,11 @@ } public boolean isDay() { @@ -270,7 +274,7 @@ } @Override -@@ -432,9 +606,11 @@ +@@ -432,9 +610,11 @@ TileEntity tileentity1 = (TileEntity) this.tileEntityListPending.get(i); if (!tileentity1.isRemoved()) { @@ -282,7 +286,7 @@ if (this.isLoaded(tileentity1.getPosition())) { Chunk chunk = this.getChunkAtWorldCoords(tileentity1.getPosition()); -@@ -442,6 +618,12 @@ +@@ -442,6 +622,12 @@ chunk.setTileEntity(tileentity1.getPosition(), tileentity1); this.notify(tileentity1.getPosition(), iblockdata, iblockdata, 3); @@ -295,7 +299,7 @@ } } } -@@ -606,12 +788,25 @@ +@@ -606,12 +792,25 @@ @Nullable @Override @@ -321,7 +325,7 @@ TileEntity tileentity = null; if (this.tickingTileEntities) { -@@ -646,6 +841,13 @@ +@@ -646,6 +845,13 @@ public void setTileEntity(BlockPosition blockposition, @Nullable TileEntity tileentity) { if (!isOutsideWorld(blockposition)) { if (tileentity != null && !tileentity.isRemoved()) { @@ -335,7 +339,7 @@ if (this.tickingTileEntities) { tileentity.setLocation(this, blockposition); Iterator iterator = this.tileEntityListPending.iterator(); -@@ -670,7 +872,7 @@ +@@ -670,7 +876,7 @@ } public void removeTileEntity(BlockPosition blockposition) { diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java index 8d1aba5354..e3d5b7bd25 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -639,6 +639,16 @@ public final class CraftServer implements Server { return this.configuration.getInt("ticks-per.monster-spawns"); } + @Override + public int getTicksPerWaterSpawns() { + return this.configuration.getInt("ticks-per.water-spawns"); + } + + @Override + public int getTicksPerAmbientSpawns() { + return this.configuration.getInt("ticks-per.ambient-spawns"); + } + @Override public PluginManager getPluginManager() { return pluginManager; @@ -751,6 +761,18 @@ public final class CraftServer implements Server { } else { world.ticksPerMonsterSpawns = this.getTicksPerMonsterSpawns(); } + + if (this.getTicksPerWaterSpawns() < 0) { + world.ticksPerWaterSpawns = 1; + } else { + world.ticksPerWaterSpawns = this.getTicksPerWaterSpawns(); + } + + if (this.getTicksPerAmbientSpawns() < 0) { + world.ticksPerAmbientSpawns = 1; + } else { + world.ticksPerAmbientSpawns = this.getTicksPerAmbientSpawns(); + } } pluginManager.clearPlugins(); diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java index 32bcbd7b42..c1cdf857df 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java @@ -1920,6 +1920,26 @@ public class CraftWorld implements World { world.ticksPerMonsterSpawns = ticksPerMonsterSpawns; } + @Override + public long getTicksPerWaterSpawns() { + return world.ticksPerWaterSpawns; + } + + @Override + public void setTicksPerWaterSpawns(int ticksPerWaterSpawns) { + world.ticksPerWaterSpawns = ticksPerWaterSpawns; + } + + @Override + public long getTicksPerAmbientSpawns() { + return world.ticksPerAmbientSpawns; + } + + @Override + public void setTicksPerAmbientSpawns(int ticksPerAmbientSpawns) { + world.ticksPerAmbientSpawns = ticksPerAmbientSpawns; + } + @Override public void setMetadata(String metadataKey, MetadataValue newMetadataValue) { server.getWorldMetadata().setMetadata(this, metadataKey, newMetadataValue); diff --git a/src/main/resources/configurations/bukkit.yml b/src/main/resources/configurations/bukkit.yml index 39dbf58ceb..e9cee1713e 100644 --- a/src/main/resources/configurations/bukkit.yml +++ b/src/main/resources/configurations/bukkit.yml @@ -33,5 +33,7 @@ chunk-gc: ticks-per: animal-spawns: 400 monster-spawns: 1 + water-spawns: 1 + ambient-spawns: 1 autosave: 6000 aliases: now-in-commands.yml