mirror of
https://github.com/Winds-Studio/Leaf.git
synced 2025-12-24 01:19:25 +00:00
Upstream has released updates that appear to apply and compile correctly Paper Changes: PaperMC/Paper@30fdfb1a [ci/skip] Fix docs for DamageResistant (#11992) PaperMC/Paper@6b7650d8 Only add goat horn once (#12001) PaperMC/Paper@30046e04 Fix a rare crash with a concurrent modification of scaled health attributes (#12002) PaperMC/Paper@88bbead1 Flush regionfiles on save configuration option PaperMC/Paper@336ea9df Check for empty when sending equipment changes (#12008) PaperMC/Paper@939bb782 Add RayTraceConfigurationBuilder (#11907) PaperMC/Paper@81bb82f5 Fix wrong piston world border check (#12007) PaperMC/Paper@ce95b5d6 Use proper default for setting null display background color (#12010) PaperMC/Paper@2477f1f6 [ci/skip] fix and improvements for docs in ConsumeEffect component (#11998) PaperMC/Paper@fb5b173c Add PlayerClientLoadedWorldEvent (#11940) PaperMC/Paper@3af5e771 Add Player#give (#11995) PaperMC/Paper@7e21cb81 fix PlayerChangedMainHandEvent javadoc (#12020) PaperMC/Paper@5a34bf04 Correctly retrun true for empty input shapes in EntityGetter#isUnobstructed PaperMC/Paper@a392d475 Make Watchdog thread extend TickThread Gale Changes: Dreeam-qwq/Gale@f9080a7e Updated Upstream (Paper) Dreeam-qwq/Gale@ff0596c1 [ci/skip] Fix upstream commit sh on mac Dreeam-qwq/Gale@24970274 [ci/skip] Hermanez - Wutaf Dreeam-qwq/Gale@85eabf60 [ci/skip] cleanup Dreeam-qwq/Gale@7d9faf00 [ci/skip] cleanup & drop xor-shift random Dreeam-qwq/Gale@7af04981 [ci/skip] cleanup Dreeam-qwq/Gale@4d5d39df [ci/skip] Remove useless params standardize in upstream commit generator Dreeam-qwq/Gale@964f16ff Updated Upstream (Paper) Dreeam-qwq/Gale@0566a223 [ci/skip] cleanup Dreeam-qwq/Gale@5e3f6740 [ci/skip] cleanup work finished Dreeam-qwq/Gale@98a66cfb Updated Upstream (Paper) Dreeam-qwq/Gale@f7736578 [ci/skip] Update upstreamCommit.sh Dreeam-qwq/Gale@1c46c816 Updated Upstream (Paper) Dreeam-qwq/Gale@2b0a4c09 [ci/skip] Skip tests during auto update validate phase Purpur Changes: PurpurMC/Purpur@4a0a86b9 Updated Upstream (Paper) PurpurMC/Purpur@7399988c Fix hover in /plugins PurpurMC/Purpur@5e5857dc [ci/skip] modify ci skip references in paper upstream commits PurpurMC/Purpur@5583a3f1 Updated Upstream (Paper)
167 lines
11 KiB
Diff
167 lines
11 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Kevin Raneri <kevin.raneri@gmail.com>
|
|
Date: Wed, 10 Nov 2021 00:37:03 -0500
|
|
Subject: [PATCH] Pufferfish: Optimize mob spawning
|
|
|
|
Original license: GPL v3
|
|
Original project: https://github.com/pufferfish-gg/Pufferfish
|
|
|
|
Co-authored-by: booky10 <boooky10@gmail.com>
|
|
|
|
This patch aims to reduce the main-thread impact of mob spawning by
|
|
offloading as much work as possible to other threads. It is possible for
|
|
inconsistencies to come up, but when they happen they never interfere
|
|
with the server's operation (they don't produce errors), and side
|
|
effects are limited to more or less mobs being spawned in any particular
|
|
tick.
|
|
|
|
It is possible to disable this optimization if it is not required or if
|
|
it interferes with any plugins. On servers with thousands of entities,
|
|
this can result in performance gains of up to 15%, which is significant
|
|
and, in my opinion, worth the low risk of minor mob-spawning-related
|
|
inconsistencies.
|
|
|
|
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
|
index 4ba85d704ffebae38f7a76a97a182e3674730c6f..a76b67a846b12a7b3d0c41b6ac4833d4f0372531 100644
|
|
--- a/net/minecraft/server/MinecraftServer.java
|
|
+++ b/net/minecraft/server/MinecraftServer.java
|
|
@@ -286,6 +286,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
|
public boolean isIteratingOverLevels = false; // Paper - Throw exception on world create while being ticked
|
|
private final Set<String> pluginsBlockingSleep = new java.util.HashSet<>(); // Paper - API to allow/disallow tick sleeping
|
|
public static final long SERVER_INIT = System.nanoTime(); // Paper - Lag compensation
|
|
+ public gg.pufferfish.pufferfish.util.AsyncExecutor mobSpawnExecutor = new gg.pufferfish.pufferfish.util.AsyncExecutor("MobSpawning"); // Pufferfish - optimize mob spawning
|
|
|
|
public static <S extends MinecraftServer> S spin(Function<Thread, S> threadFunction) {
|
|
ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.init(); // Paper - rewrite data converter system
|
|
diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java
|
|
index f2e24d52240a84ff7ca69ad2c8ec0d1c197467c0..30dc45b2201bf7435d7f38866dfa4b5fbbf44957 100644
|
|
--- a/net/minecraft/server/dedicated/DedicatedServer.java
|
|
+++ b/net/minecraft/server/dedicated/DedicatedServer.java
|
|
@@ -362,6 +362,8 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
|
|
LOGGER.info("JMX monitoring enabled");
|
|
}
|
|
|
|
+ if (org.dreeam.leaf.config.modules.async.AsyncMobSpawning.enabled) mobSpawnExecutor.start(); // Pufferfish
|
|
+
|
|
return true;
|
|
}
|
|
}
|
|
diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
|
|
index 7a18b11782b2524280fddf20e6b1cabdddf07c49..72cdd8f72fb3f552d9729f21de438405abe3acdb 100644
|
|
--- a/net/minecraft/server/level/ServerChunkCache.java
|
|
+++ b/net/minecraft/server/level/ServerChunkCache.java
|
|
@@ -179,6 +179,8 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
|
}
|
|
// Paper end - chunk tick iteration optimisations
|
|
|
|
+ public boolean firstRunSpawnCounts = true; // Pufferfish
|
|
+ public final java.util.concurrent.atomic.AtomicBoolean _pufferfish_spawnCountsReady = new java.util.concurrent.atomic.AtomicBoolean(false); // Pufferfish - optimize countmobs
|
|
|
|
public ServerChunkCache(
|
|
ServerLevel level,
|
|
@@ -513,6 +515,43 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
|
|
|
this.broadcastChangedChunks(); // Gale - Purpur - remove vanilla profiler
|
|
}
|
|
+
|
|
+ // Pufferfish start - optimize mob spawning
|
|
+ if (org.dreeam.leaf.config.modules.async.AsyncMobSpawning.enabled) {
|
|
+ for (ServerPlayer player : this.level.players) {
|
|
+ // 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
|
|
+ }
|
|
+ if (firstRunSpawnCounts) {
|
|
+ firstRunSpawnCounts = false;
|
|
+ _pufferfish_spawnCountsReady.set(true);
|
|
+ }
|
|
+ if (_pufferfish_spawnCountsReady.getAndSet(false)) {
|
|
+ net.minecraft.server.MinecraftServer.getServer().mobSpawnExecutor.submit(() -> {
|
|
+ int mapped = distanceManager.getNaturalSpawnChunkCount();
|
|
+ ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet.Iterator<Entity> objectiterator =
|
|
+ level.entityTickList.entities.iterator(ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet.ITERATOR_FLAG_SEE_ADDITIONS);
|
|
+ try {
|
|
+ gg.pufferfish.pufferfish.util.IterableWrapper<Entity> wrappedIterator =
|
|
+ new gg.pufferfish.pufferfish.util.IterableWrapper<>(objectiterator);
|
|
+ lastSpawnState = NaturalSpawner.createState(mapped, wrappedIterator, this::getFullChunk, null, true);
|
|
+ } finally {
|
|
+ objectiterator.finishedIterating();
|
|
+ }
|
|
+ _pufferfish_spawnCountsReady.set(true);
|
|
+ });
|
|
+ }
|
|
+ }
|
|
+ // Pufferfish end
|
|
}
|
|
|
|
private void broadcastChangedChunks() { // Gale - Purpur - remove vanilla profiler
|
|
@@ -560,6 +599,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
|
int naturalSpawnChunkCount = this.distanceManager.getNaturalSpawnChunkCount();
|
|
// Paper start - Optional per player mob spawns
|
|
if ((this.spawnFriendlies || this.spawnEnemies) && this.level.paperConfig().entities.spawning.perPlayerMobSpawns) { // don't count mobs when animals and monsters are disabled
|
|
+ if (!org.dreeam.leaf.config.modules.async.AsyncMobSpawning.enabled) { // Pufferfish - moved down when async processing
|
|
// re-set mob counts
|
|
for (ServerPlayer player : this.level.players) {
|
|
// Paper start - per player mob spawning backoff
|
|
@@ -574,12 +614,16 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
|
}
|
|
// Paper end - per player mob spawning backoff
|
|
}
|
|
- spawnState = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, null, true);
|
|
+ lastSpawnState = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, null, true); // Pufferfish - async mob spawning
|
|
+ } // Pufferfish - (endif) moved down when async processing
|
|
} else {
|
|
- spawnState = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, !this.level.paperConfig().entities.spawning.perPlayerMobSpawns ? new LocalMobCapCalculator(this.chunkMap) : null, false);
|
|
+ // Pufferfish start - async mob spawning
|
|
+ lastSpawnState = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, !this.level.paperConfig().entities.spawning.perPlayerMobSpawns ? new LocalMobCapCalculator(this.chunkMap) : null, false);
|
|
+ _pufferfish_spawnCountsReady.set(true);
|
|
+ // Pufferfish end
|
|
}
|
|
// Paper end - Optional per player mob spawns
|
|
- this.lastSpawnState = spawnState;
|
|
+ //this.lastSpawnState = spawnState; // Pufferfish - this is managed asynchronously
|
|
// Gale start - MultiPaper - skip unnecessary mob spawning computations
|
|
} else {
|
|
spawnState = null;
|
|
@@ -597,7 +641,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
|
}
|
|
// Paper end - PlayerNaturallySpawnCreaturesEvent
|
|
boolean flag = this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) != 0L && this.level.getLevelData().getGameTime() % this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) == 0L; // CraftBukkit
|
|
- filteredSpawningCategories = NaturalSpawner.getFilteredSpawningCategories(spawnState, this.spawnFriendlies, this.spawnEnemies, flag, this.level); // CraftBukkit
|
|
+ filteredSpawningCategories = NaturalSpawner.getFilteredSpawningCategories(lastSpawnState, this.spawnFriendlies, this.spawnEnemies, flag, this.level); // CraftBukkit // Pufferfish
|
|
} else {
|
|
filteredSpawningCategories = List.of();
|
|
}
|
|
@@ -605,8 +649,8 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
|
for (LevelChunk levelChunk : chunks) {
|
|
ChunkPos pos = levelChunk.getPos();
|
|
levelChunk.incrementInhabitedTime(timeInhabited);
|
|
- if (!filteredSpawningCategories.isEmpty() && this.level.getWorldBorder().isWithinBounds(pos) && this.chunkMap.anyPlayerCloseEnoughForSpawning(pos, true)) { // Spigot
|
|
- NaturalSpawner.spawnForChunk(this.level, levelChunk, spawnState, filteredSpawningCategories);
|
|
+ if (!filteredSpawningCategories.isEmpty() && this.level.getWorldBorder().isWithinBounds(pos) && (!org.dreeam.leaf.config.modules.async.AsyncMobSpawning.enabled || _pufferfish_spawnCountsReady.get()) && this.chunkMap.anyPlayerCloseEnoughForSpawning(pos, true)) { // Spigot // Pufferfish
|
|
+ NaturalSpawner.spawnForChunk(this.level, levelChunk, lastSpawnState, filteredSpawningCategories); // Pufferfish
|
|
}
|
|
|
|
if (true) { // Paper - rewrite chunk system
|
|
diff --git a/net/minecraft/world/level/entity/EntityTickList.java b/net/minecraft/world/level/entity/EntityTickList.java
|
|
index 423779a2b690f387a4f0bd07b97b50e0baefda76..dec51066fc3f57b7bdc56195313c219f45a7fbee 100644
|
|
--- a/net/minecraft/world/level/entity/EntityTickList.java
|
|
+++ b/net/minecraft/world/level/entity/EntityTickList.java
|
|
@@ -9,7 +9,7 @@ import javax.annotation.Nullable;
|
|
import net.minecraft.world.entity.Entity;
|
|
|
|
public class EntityTickList {
|
|
- private final ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet<net.minecraft.world.entity.Entity> entities = new ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet<>(); // Paper - rewrite chunk system
|
|
+ public final ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet<net.minecraft.world.entity.Entity> entities = new ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet<>(); // Paper - rewrite chunk system // Pufferfish - private->public
|
|
|
|
private void ensureActiveIsNotIterated() {
|
|
// Paper - rewrite chunk system
|