geforkt von Mirrors/Paper
8c5b837e05
Firstly, the old methods all routed to the CompletableFuture method. However, the CF method could not guarantee that if the caller was off-main that the future would be "completed" on-main. Since the callback methods used the CF one, this meant that the callback methods did not guarantee that the callbacks were to be called on the main thread. Now, all methods route to getChunkAtAsync(x, z, gen, urgent, cb) so that the methods with the callback are guaranteed to invoke the callback on the main thread. The CF behavior remains unchanged; it may still appear to complete on main if invoked off-main. Secondly, remove the scheduleOnMain invocation in the async chunk completion. This unnecessarily delays the callback by 1 tick. Thirdly, add getChunksAtAsync(minX, minZ, maxX, maxZ, ...) which will load chunks within an area. This method is provided as a helper as keeping all chunks loaded within an area can be complicated to implement for plugins (due to the lacking ticket API), and is already implemented internally anyways. Fourthly, remove the ticket addition that occured with getChunkAt and getChunkAtAsync. The ticket addition may delay the unloading of the chunk unnecessarily. It also fixes a very rare timing bug where the future/callback would be completed after the chunk unloads.
90 Zeilen
5.8 KiB
Diff
90 Zeilen
5.8 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: kickash32 <kickash32@gmail.com>
|
|
Date: Mon, 5 Apr 2021 01:42:35 -0400
|
|
Subject: [PATCH] Improve cancelling PreCreatureSpawnEvent with 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 4896c3ba81ead769972fa9efdbe563d4006e4401..5b3a886c624b36557cbfaccdc3fb05a46a4ba36a 100644
|
|
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
|
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
|
@@ -246,8 +246,25 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
|
++(backingSet[i].mobCounts[index]);
|
|
}
|
|
}
|
|
+ // Paper start - per player mob count backoff
|
|
+ public void updateFailurePlayerMobTypeMap(int chunkX, int chunkZ, net.minecraft.world.entity.MobCategory mobCategory) {
|
|
+ if (!this.level.paperConfig().entities.spawning.perPlayerMobSpawns) {
|
|
+ return;
|
|
+ }
|
|
+ int idx = mobCategory.ordinal();
|
|
+ final ca.spottedleaf.moonrise.common.list.ReferenceList<ServerPlayer> inRange =
|
|
+ this.level.moonrise$getNearbyPlayers().getPlayersByChunk(chunkX, chunkZ, 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].mobBackoffCounts[idx]);
|
|
+ }
|
|
+ }
|
|
+ // Paper end - per player mob count backoff
|
|
public int getMobCountNear(final ServerPlayer player, final net.minecraft.world.entity.MobCategory mobCategory) {
|
|
- return player.mobCounts[mobCategory.ordinal()];
|
|
+ return player.mobCounts[mobCategory.ordinal()] + player.mobBackoffCounts[mobCategory.ordinal()]; // Paper - per player mob count backoff
|
|
// 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 b1ecc218034944533967375d11297705c3fc01a3..aaaadb7be8abf867624a1ca83371595bef4ab633 100644
|
|
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
|
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
|
@@ -555,7 +555,17 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
|
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);
|
|
+ // Paper start - per player mob spawning backoff
|
|
+ for (int ii = 0; ii < ServerPlayer.MOBCATEGORY_TOTAL_ENUMS; ii++) {
|
|
+ player.mobCounts[ii] = 0;
|
|
+
|
|
+ int newBackoff = player.mobBackoffCounts[ii] - 1; // TODO make configurable bleed // TODO use nonlinear algorithm?
|
|
+ if (newBackoff < 0) {
|
|
+ newBackoff = 0;
|
|
+ }
|
|
+ player.mobBackoffCounts[ii] = newBackoff;
|
|
+ }
|
|
+ // Paper end - per player mob spawning backoff
|
|
}
|
|
spawnercreature_d = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, null, true);
|
|
} else {
|
|
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
|
index f28babf8c778ef570d35e1aaa88467160cf3f1b1..b525369fb6f3bb80c1553ae41b1e3bddeda29936 100644
|
|
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
|
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
|
@@ -307,6 +307,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple
|
|
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
|
|
+ public final int[] mobBackoffCounts = new int[MOBCATEGORY_TOTAL_ENUMS]; // Paper - per player mob count backoff
|
|
|
|
// 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 12ebd7829c7f6814ccd79ae96aa9023afcc64696..c1b76a1ebc1eea7ab70cf61d8175a31794dd122a 100644
|
|
--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java
|
|
+++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
|
|
@@ -299,6 +299,11 @@ public final class NaturalSpawner {
|
|
|
|
// Paper start - PreCreatureSpawnEvent
|
|
PreSpawnStatus doSpawning = isValidSpawnPostitionForType(world, group, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2);
|
|
+ // Paper start - per player mob count backoff
|
|
+ if (doSpawning == PreSpawnStatus.ABORT || doSpawning == PreSpawnStatus.CANCELLED) {
|
|
+ world.getChunkSource().chunkMap.updateFailurePlayerMobTypeMap(blockposition_mutableblockposition.getX() >> 4, blockposition_mutableblockposition.getZ() >> 4, group);
|
|
+ }
|
|
+ // Paper end - per player mob count backoff
|
|
if (doSpawning == PreSpawnStatus.ABORT) {
|
|
return;
|
|
}
|