From 79ef32663e1f4603d8011e36d58552f05c7cc5cb Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Thu, 2 Apr 2020 00:28:06 -0500 Subject: [PATCH] Optimize Chunk Ticks --- .../minecraft/server/ChunkProviderServer.java | 70 ++++++------------- .../minecraft/server/EnumCreatureType.java | 14 ++++ .../net/minecraft/server/PlayerChunkMap.java | 30 ++++---- 3 files changed, 51 insertions(+), 63 deletions(-) diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java index 78a8a3cc6..0a09e8dd7 100644 --- a/src/main/java/net/minecraft/server/ChunkProviderServer.java +++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java @@ -737,11 +737,12 @@ public class ChunkProviderServer extends IChunkProvider { int k = this.world.getGameRules().getInt(GameRules.RANDOM_TICK_SPEED); BlockPosition blockposition = this.world.getSpawn(); // 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; + // Purpur start + EnumCreatureType.CREATURE.setLimitThisTick(world.ticksPerAnimalSpawns != 0L && i % world.ticksPerAnimalSpawns == 0L ? world.getWorld().getAnimalSpawnLimit() : -1); + EnumCreatureType.MONSTER.setLimitThisTick(world.ticksPerMonsterSpawns != 0L && i % world.ticksPerMonsterSpawns == 0L ? world.getWorld().getMonsterSpawnLimit() : -1); + EnumCreatureType.WATER_CREATURE.setLimitThisTick(world.ticksPerWaterSpawns != 0L && i % world.ticksPerWaterSpawns == 0L ? world.getWorld().getWaterAnimalSpawnLimit() : -1); + EnumCreatureType.AMBIENT.setLimitThisTick(world.ticksPerAmbientSpawns != 0L && i % world.ticksPerAmbientSpawns == 0L ? world.getWorld().getAmbientSpawnLimit() : -1); + // Purpur end // CraftBukkit end this.world.getMethodProfiler().enter("naturalSpawnCount"); @@ -767,15 +768,17 @@ public class ChunkProviderServer extends IChunkProvider { this.world.timings.countNaturalMobs.stopTiming(); // Paper - timings this.world.getMethodProfiler().exit(); - //Paper start - call player naturally spawn event - int chunkRange = world.spigotConfig.mobSpawnRange; - chunkRange = (chunkRange > world.spigotConfig.viewDistance) ? (byte) world.spigotConfig.viewDistance : chunkRange; - chunkRange = Math.min(chunkRange, 8); - for (EntityPlayer entityPlayer : this.world.players) { - entityPlayer.playerNaturallySpawnedEvent = new com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent(entityPlayer.getBukkitEntity(), (byte) chunkRange); - entityPlayer.playerNaturallySpawnedEvent.callEvent(); - }; - // Paper end + // Purpur start + if (com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent.getHandlerList().getRegisteredListeners().length > 0) { + // Paper start - call player naturally spawn event + byte chunkRange = (byte) Math.min(Math.min(world.spigotConfig.mobSpawnRange, world.spigotConfig.viewDistance), 8); + for (EntityPlayer entityPlayer : this.world.players) { + entityPlayer.playerNaturallySpawnedEvent = new com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent(entityPlayer.getBukkitEntity(), (byte) chunkRange); + entityPlayer.playerNaturallySpawnedEvent.callEvent(); + } + // Paper end + } + // Purpur end final int[] chunksTicked = {0}; this.playerChunkMap.forEachVisibleChunk((playerchunk) -> { // Paper - safe iterator incase chunk loads, also no wrapping Optional optional = ((Either) playerchunk.b().getNow(PlayerChunk.UNLOADED_CHUNK)).left(); @@ -795,40 +798,11 @@ public class ChunkProviderServer extends IChunkProvider { if (flag1 && (this.allowMonsters || this.allowAnimals) && this.world.getWorldBorder().isInBounds(chunk.getPos()) && !this.playerChunkMap.isOutsideOfRange(chunkcoordintpair, true)) { // Spigot this.world.getMethodProfiler().enter("spawner"); this.world.timings.mobSpawn.startTiming(); // Spigot - EnumCreatureType[] aenumcreaturetype1 = aenumcreaturetype; - int i1 = aenumcreaturetype.length; - - 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 (!spawnThisTick || limit == 0) { - continue; - } - // CraftBukkit end - - if (enumcreaturetype != EnumCreatureType.MISC && (!enumcreaturetype.c() || this.allowAnimals) && (enumcreaturetype.c() || this.allowMonsters) && (!enumcreaturetype.d() || flag2)) { + // Purpur start + for (EnumCreatureType enumcreaturetype : aenumcreaturetype) { + int limit = enumcreaturetype.getLimitThisTick(); + if (limit > 0 && enumcreaturetype != EnumCreatureType.MISC && (!enumcreaturetype.isFriendly() || this.allowAnimals) && (enumcreaturetype.isFriendly() || this.allowMonsters)) { + // Purpur end int k1 = limit * l / ChunkProviderServer.b; // CraftBukkit - use per-world limits // Paper start - only allow spawns upto the limit per chunk and update count afterwards diff --git a/src/main/java/net/minecraft/server/EnumCreatureType.java b/src/main/java/net/minecraft/server/EnumCreatureType.java index 3ed7fa324..7f236585d 100644 --- a/src/main/java/net/minecraft/server/EnumCreatureType.java +++ b/src/main/java/net/minecraft/server/EnumCreatureType.java @@ -31,11 +31,25 @@ public enum EnumCreatureType { return this.g; } + public boolean isFriendly() { return c(); } // Purpur - OBFHELPER public boolean c() { return this.h; } + public boolean isPersistent() { return d(); } // Purpur - OBFHELPER public boolean d() { return this.i; } + + // Purpur start + private int limitThisTick = -1; + + void setLimitThisTick(int cap) { + this.limitThisTick = cap; + } + + int getLimitThisTick() { + return this.limitThisTick; + } + // Purpur end } diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java index aabb9220d..b0c95aebf 100644 --- a/src/main/java/net/minecraft/server/PlayerChunkMap.java +++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java @@ -1386,28 +1386,28 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { } boolean isOutsideOfRange(ChunkCoordIntPair chunkcoordintpair, boolean reducedRange) { - int chunkRange = world.spigotConfig.mobSpawnRange; - chunkRange = (chunkRange > world.spigotConfig.viewDistance) ? (byte) world.spigotConfig.viewDistance : chunkRange; - chunkRange = (chunkRange > 8) ? 8 : chunkRange; - - final int finalChunkRange = chunkRange; // Paper for lambda below - //double blockRange = (reducedRange) ? Math.pow(chunkRange << 4, 2) : 16384.0D; // Paper - use from event - // Spigot end + // Purpur start long i = chunkcoordintpair.pair(); - - return !this.chunkDistanceManager.d(i) ? true : this.playerMap.a(i).noneMatch((entityplayer) -> { - // Paper start - - com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent event; + return !this.chunkDistanceManager.d(i) || this.playerMap.a(i).noneMatch((player) -> { + // Paper start double blockRange = 16384.0D; if (reducedRange) { - event = entityplayer.playerNaturallySpawnedEvent; - if (event == null || event.isCancelled()) return false; - blockRange = (double) ((event.getSpawnRadius() << 4) * (event.getSpawnRadius() << 4)); + int radius; + if (player.playerNaturallySpawnedEvent != null) { + if (player.playerNaturallySpawnedEvent.isCancelled()) { + return false; + } + radius = player.playerNaturallySpawnedEvent.getSpawnRadius(); + } else { + radius = Math.min(Math.min(world.spigotConfig.mobSpawnRange, world.spigotConfig.viewDistance), 8) << 4; + } + blockRange = radius * radius; } - return (!entityplayer.isSpectator() && a(chunkcoordintpair, (Entity) entityplayer) < blockRange); // Spigot + return (!player.isSpectator() && a(chunkcoordintpair, player) < blockRange); // Spigot // Paper end }); + // Purpur end } private boolean b(EntityPlayer entityplayer) { -- 2.24.0