mirror of
https://github.com/PurpurMC/Purpur.git
synced 2026-02-17 16:37:43 +01:00
244 lines
13 KiB
Diff
244 lines
13 KiB
Diff
From 25ba7be0350d6cecf3f97c1b8f3c15cb76cab74b Mon Sep 17 00:00:00 2001
|
|
From: kickash32 <kickash32@gmail.com>
|
|
Date: Tue, 11 Jun 2019 22:22:16 -0400
|
|
Subject: [PATCH] implement optional per player mob spawns
|
|
|
|
---
|
|
.../destroystokyo/paper/PaperWorldConfig.java | 5 +++
|
|
.../minecraft/server/ChunkProviderServer.java | 16 +++++++--
|
|
.../net/minecraft/server/PlayerChunkMap.java | 10 ++++++
|
|
.../java/net/minecraft/server/PlayerMap.java | 1 +
|
|
.../net/minecraft/server/SpawnerCreature.java | 21 ++++++-----
|
|
.../net/minecraft/server/WorldServer.java | 36 +++++++++++++++++++
|
|
6 files changed, 76 insertions(+), 13 deletions(-)
|
|
|
|
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
|
index ff520d9e86..c2823c10f9 100644
|
|
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
|
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
|
@@ -509,6 +509,11 @@ public class PaperWorldConfig {
|
|
maxAutoSaveChunksPerTick = getInt("max-auto-save-chunks-per-tick", 24);
|
|
}
|
|
|
|
+ public boolean perPlayerMobSpawns = false;
|
|
+ private void perPlayerMobSpawns() {
|
|
+ perPlayerMobSpawns = getBoolean("per-player-mob-spawns", false);
|
|
+ }
|
|
+
|
|
public boolean countAllMobsForSpawning = false;
|
|
private void countAllMobsForSpawning() {
|
|
countAllMobsForSpawning = getBoolean("count-all-mobs-for-spawning", false);
|
|
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
|
index cd11efc68f..ede99204ad 100644
|
|
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
|
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
|
@@ -622,9 +622,21 @@ public class ChunkProviderServer extends IChunkProvider {
|
|
// Paper start - only allow spawns upto the limit per chunk and update count afterwards
|
|
int currEntityCount = object2intmap.getInt(enumcreaturetype);
|
|
int difference = k1 - currEntityCount;
|
|
+ if(this.world.paperConfig.perPlayerMobSpawns){
|
|
+ final int[] min = {Integer.MAX_VALUE};
|
|
+ final int finalLimit = limit;
|
|
+ playerChunkMap.getPlayersNear(chunk.getPos(), this.world.spigotConfig.mobSpawnRange)
|
|
+ .forEach((entityplayer) -> min[0] = Math.min(
|
|
+ finalLimit - ((WorldServer)chunk.getWorld()).getMobCountNear(entityplayer, enumcreaturetype),
|
|
+ min[0]));
|
|
+ difference = (min[0] == Integer.MAX_VALUE) ? 0 : min[0];
|
|
+ }
|
|
+
|
|
if (difference > 0) {
|
|
- object2intmap.put(enumcreaturetype, currEntityCount + SpawnerCreature.spawnMobs(enumcreaturetype, world, chunk, blockposition, difference));
|
|
- // Paper end
|
|
+ List spawned = SpawnerCreature.spawnMobs(enumcreaturetype, this.world, chunk, blockposition, difference);
|
|
+ object2intmap.put(enumcreaturetype, currEntityCount + spawned.size());
|
|
+ this.world.updatePlayerMobTypeMap(spawned);
|
|
+ // Paper end
|
|
}
|
|
}
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
|
index 594c2b9aa6..bdfa18bca7 100644
|
|
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
|
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
|
@@ -137,6 +137,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
|
this.setViewDistance(i);
|
|
}
|
|
|
|
+ private static double squareDist(ChunkCoordIntPair chunkcoord, Entity entity) { return a(chunkcoord, entity); } // Paper - OBFHELPER
|
|
private static double a(ChunkCoordIntPair chunkcoordintpair, Entity entity) {
|
|
double d0 = (double) (chunkcoordintpair.x * 16 + 8);
|
|
double d1 = (double) (chunkcoordintpair.z * 16 + 8);
|
|
@@ -1322,6 +1323,15 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
|
|
|
}
|
|
|
|
+ // Paper start
|
|
+ public Stream<EntityPlayer> getPlayersNear(ChunkCoordIntPair coordIntPair, int rangeChunks) {
|
|
+ int squareRangeBlocks = ((rangeChunks << 4) * (rangeChunks << 4));
|
|
+
|
|
+ return this.playerMap.getPlayers(coordIntPair.pair()).filter( (entityplayer) ->
|
|
+ (!entityplayer.isSpectator() && squareDist(coordIntPair, entityplayer) < squareRangeBlocks));
|
|
+ }
|
|
+ // Paper end
|
|
+
|
|
@Override
|
|
public Stream<EntityPlayer> a(ChunkCoordIntPair chunkcoordintpair, boolean flag) {
|
|
return this.playerMap.a(chunkcoordintpair.pair()).filter((entityplayer) -> {
|
|
diff --git a/src/main/java/net/minecraft/server/PlayerMap.java b/src/main/java/net/minecraft/server/PlayerMap.java
|
|
index f386c4e997..c896a0b85f 100644
|
|
--- a/src/main/java/net/minecraft/server/PlayerMap.java
|
|
+++ b/src/main/java/net/minecraft/server/PlayerMap.java
|
|
@@ -10,6 +10,7 @@ public final class PlayerMap {
|
|
|
|
public PlayerMap() {}
|
|
|
|
+ public Stream<EntityPlayer> getPlayers(long chunkCoord) { return this.a(chunkCoord); } // Paper - OBFHELPER
|
|
public Stream<EntityPlayer> a(long i) {
|
|
return this.a.keySet().stream();
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/server/SpawnerCreature.java b/src/main/java/net/minecraft/server/SpawnerCreature.java
|
|
index 925efd4a15..70580355c6 100644
|
|
--- a/src/main/java/net/minecraft/server/SpawnerCreature.java
|
|
+++ b/src/main/java/net/minecraft/server/SpawnerCreature.java
|
|
@@ -20,16 +20,15 @@ public final class SpawnerCreature {
|
|
public static void a(EnumCreatureType enumcreaturetype, World world, Chunk chunk, BlockPosition blockposition) {
|
|
spawnMobs(enumcreaturetype, world, chunk, blockposition, Integer.MAX_VALUE);
|
|
}
|
|
-
|
|
- public static int spawnMobs(EnumCreatureType enumcreaturetype, World world, Chunk chunk, BlockPosition blockposition, int maxSpawns) {
|
|
- // Paper end
|
|
+ public static List<Entity> spawnMobs(EnumCreatureType enumcreaturetype, World world, Chunk chunk, BlockPosition blockposition, int maxSpawns) {
|
|
+ List<Entity> mobsSpawned = new java.util.ArrayList<>();
|
|
+ // Paper end
|
|
ChunkGenerator<?> chunkgenerator = world.getChunkProvider().getChunkGenerator();
|
|
int i = 0;
|
|
BlockPosition blockposition1 = getRandomPosition(world, chunk);
|
|
int j = blockposition1.getX();
|
|
int k = blockposition1.getY();
|
|
int l = blockposition1.getZ();
|
|
- int amountSpawned = 0; // Paper - keep track of mobs spawned
|
|
|
|
if (k >= 1) {
|
|
IBlockData iblockdata = world.getTypeIfLoadedAndInBounds(blockposition1); // Paper - don't load chunks for mob spawn
|
|
@@ -104,7 +103,7 @@ public final class SpawnerCreature {
|
|
);
|
|
if (!event.callEvent()) {
|
|
if (event.shouldAbortSpawn()) {
|
|
- return amountSpawned; // Paper
|
|
+ return mobsSpawned; // Paper
|
|
}
|
|
++i2;
|
|
continue;
|
|
@@ -123,7 +122,7 @@ public final class SpawnerCreature {
|
|
} catch (Exception exception) {
|
|
SpawnerCreature.LOGGER.warn("Failed to create mob", exception);
|
|
ServerInternalException.reportInternalException(exception); // Paper
|
|
- return amountSpawned; // Paper
|
|
+ return mobsSpawned; // Paper
|
|
}
|
|
|
|
entityinsentient.setPositionRotation((double) f, (double) k, (double) f1, world.random.nextFloat() * 360.0F, 0.0F);
|
|
@@ -134,15 +133,15 @@ public final class SpawnerCreature {
|
|
++i;
|
|
++i2;
|
|
// Paper start - stop when limit is reached
|
|
- ++amountSpawned;
|
|
+ mobsSpawned.add(entityinsentient);
|
|
}
|
|
- if (amountSpawned >= maxSpawns) {
|
|
- return amountSpawned;
|
|
+ if (mobsSpawned.size() >= maxSpawns) {
|
|
+ return mobsSpawned;
|
|
}
|
|
// Paper end
|
|
// CraftBukkit end
|
|
if (i >= entityinsentient.dC()) {
|
|
- return amountSpawned; // Paper
|
|
+ return mobsSpawned; // Paper
|
|
}
|
|
|
|
if (entityinsentient.c(i2)) {
|
|
@@ -168,7 +167,7 @@ public final class SpawnerCreature {
|
|
|
|
}
|
|
}
|
|
- return amountSpawned; // Paper
|
|
+ return mobsSpawned; // Paper
|
|
}
|
|
|
|
@Nullable
|
|
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
|
|
index 3e66e1782c..f98b4346b5 100644
|
|
--- a/src/main/java/net/minecraft/server/WorldServer.java
|
|
+++ b/src/main/java/net/minecraft/server/WorldServer.java
|
|
@@ -70,6 +70,7 @@ public class WorldServer extends World {
|
|
private boolean ticking;
|
|
@Nullable
|
|
private final MobSpawnerTrader mobSpawnerTrader;
|
|
+ private Map<UUID, Map<EnumCreatureType, Integer>> playerMobTypeMap; // Paper
|
|
|
|
// CraftBukkit start
|
|
private int tickPosition;
|
|
@@ -931,6 +932,7 @@ public class WorldServer extends World {
|
|
}
|
|
|
|
public Object2IntMap<EnumCreatureType> l() {
|
|
+ List<Entity> filteredEntities = new java.util.ArrayList<>(); // Paper
|
|
Object2IntMap<EnumCreatureType> object2intmap = new Object2IntOpenHashMap();
|
|
ObjectIterator objectiterator = this.entitiesById.values().iterator();
|
|
|
|
@@ -949,6 +951,7 @@ public class WorldServer extends World {
|
|
EnumCreatureType enumcreaturetype = entity.getEntityType().e();
|
|
|
|
if (enumcreaturetype != EnumCreatureType.MISC && this.getChunkProvider().b(entity)) {
|
|
+ filteredEntities.add(entity); // Paper
|
|
// Paper start - Only count natural spawns
|
|
if (!this.paperConfig.countAllMobsForSpawning &&
|
|
!(entity.spawnReason == CreatureSpawnEvent.SpawnReason.NATURAL ||
|
|
@@ -960,9 +963,42 @@ public class WorldServer extends World {
|
|
}
|
|
}
|
|
|
|
+ // Paper start
|
|
+ if(this.paperConfig.perPlayerMobSpawns) {
|
|
+ this.playerMobTypeMap = new java.util.HashMap<>();
|
|
+ updatePlayerMobTypeMap(filteredEntities);
|
|
+ }
|
|
+ // Paper end
|
|
return object2intmap;
|
|
}
|
|
|
|
+ // Paper start
|
|
+ public void updatePlayerMobTypeMap(List<Entity> entities) {
|
|
+ if (this.playerMobTypeMap == null) { return; }
|
|
+ for (Entity entity : entities) {
|
|
+ ((ChunkProviderServer) this.chunkProvider).playerChunkMap.getPlayersNear(entity.getChunkAtLocation().getPos(), this.spigotConfig.mobSpawnRange).forEach( (player) -> {
|
|
+ if (!this.playerMobTypeMap.containsKey(player.uniqueID)) { this.playerMobTypeMap.put(player.uniqueID, new Object2IntOpenHashMap()); }
|
|
+ Map<EnumCreatureType, Integer> tmpMap = this.playerMobTypeMap.get(player.uniqueID);
|
|
+ EnumCreatureType enumType = entity.getEntityType().e();
|
|
+ tmpMap.put(
|
|
+ enumType,
|
|
+ tmpMap.getOrDefault(enumType, 0) + 1);
|
|
+ });
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public int getMobCountNear(EntityPlayer entityPlayer, EnumCreatureType enumCreatureType) {
|
|
+ int count = 0;
|
|
+ if (this.playerMobTypeMap != null) {
|
|
+ Map<EnumCreatureType, Integer> map = this.playerMobTypeMap.get(entityPlayer.uniqueID);
|
|
+ if (map != null) {
|
|
+ count = map.getOrDefault(enumCreatureType, 0);
|
|
+ }
|
|
+ }
|
|
+ return count;
|
|
+ }
|
|
+ // Paper end
|
|
+
|
|
@Override
|
|
public boolean addEntity(Entity entity) {
|
|
// CraftBukkit start
|
|
--
|
|
2.20.1
|
|
|