diff options
Diffstat (limited to 'patches/server/1054-Optional-per-player-mob-spawns.patch')
-rw-r--r-- | patches/server/1054-Optional-per-player-mob-spawns.patch | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/patches/server/1054-Optional-per-player-mob-spawns.patch b/patches/server/1054-Optional-per-player-mob-spawns.patch new file mode 100644 index 0000000000..e08da27a04 --- /dev/null +++ b/patches/server/1054-Optional-per-player-mob-spawns.patch @@ -0,0 +1,232 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kickash32 <[email protected]> +Date: Mon, 19 Aug 2019 01:27:58 +0500 +Subject: [PATCH] Optional per player mob spawns + + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index bf43bdb43c5301c0e0954729bc531fb6a5045075..97a24cb410cf7d22a1a8edf8a5622d03a3d5a9c7 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -231,8 +231,26 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + + // Paper start ++ // Paper start - Optional per player mob spawns ++ public void updatePlayerMobTypeMap(final Entity entity) { ++ if (!this.level.paperConfig().entities.spawning.perPlayerMobSpawns) { ++ return; ++ } ++ final int index = entity.getType().getCategory().ordinal(); ++ ++ final ca.spottedleaf.moonrise.common.list.ReferenceList<ServerPlayer> inRange = ++ this.level.moonrise$getNearbyPlayers().getPlayers(entity.chunkPosition(), ca.spottedleaf.moonrise.common.misc.NearbyPlayers.NearbyMapType.TICK_VIEW_DISTANCE); ++ if (inRange == null) { ++ return; ++ } ++ final ServerPlayer[] backingSet = inRange.getRawDataUnchecked(); ++ for (int i = 0, len = inRange.size(); i < len; i++) { ++ ++(backingSet[i].mobCounts[index]); ++ } ++ } + public int getMobCountNear(final ServerPlayer player, final net.minecraft.world.entity.MobCategory mobCategory) { +- return -1; ++ return player.mobCounts[mobCategory.ordinal()]; ++ // Paper end - Optional per player mob spawns + } + // Paper end + +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index 4b5985c284faac7b06c0f99d53065f5060ecff4a..ba989879c43cb7d614198444fd2ead85ea71eae9 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -503,7 +503,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon + gameprofilerfiller.popPush("shuffleChunks"); + // Paper start - chunk tick iteration optimisation + this.shuffleRandom.setSeed(this.level.random.nextLong()); +- Util.shuffle(list, this.shuffleRandom); ++ if (!this.level.paperConfig().entities.spawning.perPlayerMobSpawns) Util.shuffle(list, this.shuffleRandom); // Paper - Optional per player mob spawns; do not need this when per-player is enabled + // Paper end - chunk tick iteration optimisation + this.tickChunks(gameprofilerfiller, j, list); + gameprofilerfiller.pop(); +@@ -563,7 +563,19 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon + profiler.popPush("naturalSpawnCount"); + this.level.timings.countNaturalMobs.startTiming(); // Paper - timings + int j = this.distanceManager.getNaturalSpawnChunkCount(); +- NaturalSpawner.SpawnState spawnercreature_d = NaturalSpawner.createState(j, this.level.getAllEntities(), this::getFullChunk, new LocalMobCapCalculator(this.chunkMap)); ++ // Paper start - Optional per player mob spawns ++ final int naturalSpawnChunkCount = j; ++ NaturalSpawner.SpawnState spawnercreature_d; // moved down ++ if ((this.spawnFriendlies || this.spawnEnemies) && this.level.paperConfig().entities.spawning.perPlayerMobSpawns) { // don't count mobs when animals and monsters are disabled ++ // re-set mob counts ++ for (ServerPlayer player : this.level.players) { ++ Arrays.fill(player.mobCounts, 0); ++ } ++ spawnercreature_d = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, null, true); ++ } else { ++ spawnercreature_d = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, !this.level.paperConfig().entities.spawning.perPlayerMobSpawns ? new LocalMobCapCalculator(this.chunkMap) : null, false); ++ } ++ // Paper end - Optional per player mob spawns + this.level.timings.countNaturalMobs.stopTiming(); // Paper - timings + + this.lastSpawnState = spawnercreature_d; +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 8c9148426f23cbbdfaf7ae66657d1a620f8bd853..8cc02ee9b1a710e35eb65a5a095681cc7dc542bb 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -303,6 +303,10 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple + public boolean queueHealthUpdatePacket; + public net.minecraft.network.protocol.game.ClientboundSetHealthPacket queuedHealthUpdatePacket; + // Paper end - cancellable death event ++ // Paper start - Optional per player mob spawns ++ public static final int MOBCATEGORY_TOTAL_ENUMS = net.minecraft.world.entity.MobCategory.values().length; ++ public final int[] mobCounts = new int[MOBCATEGORY_TOTAL_ENUMS]; // Paper ++ // Paper end - Optional per player mob spawns + + // CraftBukkit start + public CraftPlayer.TransferCookieConnection transferCookieConnection; +diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java +index 6eb69ebe688c1c52d5a5986dfc63cdd42e66687e..f3b52e61ddde25a60c1d178a7607b220ca01f770 100644 +--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java ++++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java +@@ -71,6 +71,12 @@ public final class NaturalSpawner { + private NaturalSpawner() {} + + public static NaturalSpawner.SpawnState createState(int spawningChunkCount, Iterable<Entity> entities, NaturalSpawner.ChunkGetter chunkSource, LocalMobCapCalculator densityCapper) { ++ // Paper start - Optional per player mob spawns ++ return createState(spawningChunkCount, entities, chunkSource, densityCapper, false); ++ } ++ ++ public static NaturalSpawner.SpawnState createState(int spawningChunkCount, Iterable<Entity> entities, NaturalSpawner.ChunkGetter chunkSource, LocalMobCapCalculator densityCapper, boolean countMobs) { ++ // Paper end - Optional per player mob spawns + PotentialCalculator spawnercreatureprobabilities = new PotentialCalculator(); + Object2IntOpenHashMap<MobCategory> object2intopenhashmap = new Object2IntOpenHashMap(); + Iterator iterator = entities.iterator(); +@@ -103,11 +109,16 @@ public final class NaturalSpawner { + spawnercreatureprobabilities.addCharge(entity.blockPosition(), biomesettingsmobs_b.charge()); + } + +- if (entity instanceof Mob) { ++ if (densityCapper != null && entity instanceof Mob) { // Paper - Optional per player mob spawns + densityCapper.addMob(chunk.getPos(), enumcreaturetype); + } + + object2intopenhashmap.addTo(enumcreaturetype, 1); ++ // Paper start - Optional per player mob spawns ++ if (countMobs) { ++ chunk.level.getChunkSource().chunkMap.updatePlayerMobTypeMap(entity); ++ } ++ // Paper end - Optional per player mob spawns + }); + } + } +@@ -142,7 +153,7 @@ public final class NaturalSpawner { + continue; + } + +- if ((flag || !enumcreaturetype.isFriendly()) && (flag1 || enumcreaturetype.isFriendly()) && (flag2 || !enumcreaturetype.isPersistent()) && spawnercreature_d.canSpawnForCategoryGlobal(enumcreaturetype, limit)) { ++ if ((flag || !enumcreaturetype.isFriendly()) && (flag1 || enumcreaturetype.isFriendly()) && (flag2 || !enumcreaturetype.isPersistent()) && (!worldserver.paperConfig().entities.spawning.perPlayerMobSpawns || spawnercreature_d.canSpawnForCategoryGlobal(enumcreaturetype, limit))) { // Paper - Optional per player mob spawns; remove global check, check later during the local one + // CraftBukkit end + list.add(enumcreaturetype); + } +@@ -161,12 +172,43 @@ public final class NaturalSpawner { + while (iterator.hasNext()) { + MobCategory enumcreaturetype = (MobCategory) iterator.next(); + +- if (info.canSpawnForCategoryLocal(enumcreaturetype, chunk.getPos())) { ++ // Paper start - Optional per player mob spawns ++ final boolean canSpawn; ++ int maxSpawns = Integer.MAX_VALUE; ++ if (world.paperConfig().entities.spawning.perPlayerMobSpawns) { ++ // Copied from getFilteredSpawningCategories ++ int limit = enumcreaturetype.getMaxInstancesPerChunk(); ++ SpawnCategory spawnCategory = CraftSpawnCategory.toBukkit(enumcreaturetype); ++ if (CraftSpawnCategory.isValidForLimits(spawnCategory)) { ++ limit = world.getWorld().getSpawnLimit(spawnCategory); ++ } ++ ++ // Apply per-player limit ++ int minDiff = Integer.MAX_VALUE; ++ final ca.spottedleaf.moonrise.common.list.ReferenceList<net.minecraft.server.level.ServerPlayer> inRange = ++ world.moonrise$getNearbyPlayers().getPlayers(chunk.getPos(), ca.spottedleaf.moonrise.common.misc.NearbyPlayers.NearbyMapType.TICK_VIEW_DISTANCE); ++ if (inRange != null) { ++ final net.minecraft.server.level.ServerPlayer[] backingSet = inRange.getRawDataUnchecked(); ++ for (int k = 0, len = inRange.size(); k < len; k++) { ++ minDiff = Math.min(limit - world.getChunkSource().chunkMap.getMobCountNear(backingSet[k], enumcreaturetype), minDiff); ++ } ++ } ++ ++ maxSpawns = (minDiff == Integer.MAX_VALUE) ? 0 : minDiff; ++ canSpawn = maxSpawns > 0; ++ } else { ++ canSpawn = info.canSpawnForCategoryLocal(enumcreaturetype, chunk.getPos()); ++ } ++ if (canSpawn) { ++ // Paper end - Optional per player mob spawns + Objects.requireNonNull(info); + NaturalSpawner.SpawnPredicate spawnercreature_c = info::canSpawn; + + Objects.requireNonNull(info); +- NaturalSpawner.spawnCategoryForChunk(enumcreaturetype, world, chunk, spawnercreature_c, info::afterSpawn); ++ // Paper start - Optional per player mob spawns ++ NaturalSpawner.spawnCategoryForChunk(enumcreaturetype, world, chunk, spawnercreature_c, info::afterSpawn, ++ maxSpawns, world.paperConfig().entities.spawning.perPlayerMobSpawns ? world.getChunkSource().chunkMap::updatePlayerMobTypeMap : null); ++ // Paper end - Optional per player mob spawns + } + } + +@@ -185,10 +227,15 @@ public final class NaturalSpawner { + // Paper end - Add mobcaps commands + + public static void spawnCategoryForChunk(MobCategory group, ServerLevel world, LevelChunk chunk, NaturalSpawner.SpawnPredicate checker, NaturalSpawner.AfterSpawnCallback runner) { ++ // Paper start - Optional per player mob spawns ++ spawnCategoryForChunk(group, world, chunk, checker, runner, Integer.MAX_VALUE, null); ++ } ++ public static void spawnCategoryForChunk(MobCategory group, ServerLevel world, LevelChunk chunk, NaturalSpawner.SpawnPredicate checker, NaturalSpawner.AfterSpawnCallback runner, int maxSpawns, Consumer<Entity> trackEntity) { ++ // Paper end - Optional per player mob spawns + BlockPos blockposition = NaturalSpawner.getRandomPosWithin(world, chunk); + + if (blockposition.getY() >= world.getMinY() + 1) { +- NaturalSpawner.spawnCategoryForPosition(group, world, chunk, blockposition, checker, runner); ++ NaturalSpawner.spawnCategoryForPosition(group, world, chunk, blockposition, checker, runner, maxSpawns, trackEntity); // Paper - Optional per player mob spawns + } + } + +@@ -200,7 +247,12 @@ public final class NaturalSpawner { + }); + } + ++ // Paper start - Optional per player mob spawns + public static void spawnCategoryForPosition(MobCategory group, ServerLevel world, ChunkAccess chunk, BlockPos pos, NaturalSpawner.SpawnPredicate checker, NaturalSpawner.AfterSpawnCallback runner) { ++ spawnCategoryForPosition(group, world,chunk, pos, checker, runner, Integer.MAX_VALUE, null); ++ } ++ public static void spawnCategoryForPosition(MobCategory group, ServerLevel world, ChunkAccess chunk, BlockPos pos, NaturalSpawner.SpawnPredicate checker, NaturalSpawner.AfterSpawnCallback runner, int maxSpawns, Consumer<Entity> trackEntity) { ++ // Paper end - Optional per player mob spawns + StructureManager structuremanager = world.structureManager(); + ChunkGenerator chunkgenerator = world.getChunkSource().getGenerator(); + int i = pos.getY(); +@@ -270,9 +322,14 @@ public final class NaturalSpawner { + ++j; + ++k1; + runner.run(entityinsentient, chunk); ++ // Paper start - Optional per player mob spawns ++ if (trackEntity != null) { ++ trackEntity.accept(entityinsentient); ++ } ++ // Paper end - Optional per player mob spawns + } + // CraftBukkit end +- if (j >= entityinsentient.getMaxSpawnClusterSize()) { ++ if (j >= entityinsentient.getMaxSpawnClusterSize() || j >= maxSpawns) { // Paper - Optional per player mob spawns + return; + } + +@@ -545,7 +602,7 @@ public final class NaturalSpawner { + MobCategory enumcreaturetype = entitytypes.getCategory(); + + this.mobCategoryCounts.addTo(enumcreaturetype, 1); +- this.localMobCapCalculator.addMob(new ChunkPos(blockposition), enumcreaturetype); ++ if (this.localMobCapCalculator != null) this.localMobCapCalculator.addMob(new ChunkPos(blockposition), enumcreaturetype); // Paper - Optional per player mob spawns + } + + public int getSpawnableChunkCount() { |