385f313a8b
Upstream has released updates that appear to apply and compile correctly. This update has not been tested by PaperMC and as with ANY update, please do your own testing Bukkit Changes: d41796de SPIGOT-7071: Add Player#stopSound(SoundCategory category) 61dae5b2 SPIGOT-7011, SPIGOT-7065: Overhaul of structures CraftBukkit Changes: 991aeda12 SPIGOT-1729, SPIGOT-7090: Keep precision in teleportation between worlds 5c9a5f628 SPIGOT-7071: Add Player#stopSound(SoundCategory category) 68f888ded SPIGOT-7011, SPIGOT-7065: Overhaul of structures 0231a3746 Remove outdated build delay. Spigot Changes: 475f6008 Rebuild patches 8ce1761f Rebuild patches
239 Zeilen
15 KiB
Diff
239 Zeilen
15 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
|
Date: Sun, 21 Mar 2021 11:22:10 -0700
|
|
Subject: [PATCH] Do not copy visible chunks
|
|
|
|
For servers with a lot of chunk holders, copying for each
|
|
tickDistanceManager call can take up quite a bit in
|
|
the function. I saw approximately 1/3rd of the function
|
|
on the copy.
|
|
|
|
diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java
|
|
index 008bb8896657892fcaf64e134684cc49e62f23f6..a538473f4a75791c7c657f9f1e3ddf96042ab071 100644
|
|
--- a/src/main/java/com/destroystokyo/paper/PaperCommand.java
|
|
+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java
|
|
@@ -480,7 +480,7 @@ public class PaperCommand extends Command {
|
|
int ticking = 0;
|
|
int entityTicking = 0;
|
|
|
|
- for (ChunkHolder chunk : world.getChunkSource().chunkMap.updatingChunkMap.values()) {
|
|
+ for (ChunkHolder chunk : world.getChunkSource().chunkMap.updatingChunks.getUpdatingMap().values()) { // Paper - change updating chunks map
|
|
if (chunk.getFullChunkNowUnchecked() == null) {
|
|
continue;
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java
|
|
index 613988c9ea892ab15516e1c8b4f376d52415ae34..1eb71004a19866590a3d27fa6e72842934989177 100644
|
|
--- a/src/main/java/net/minecraft/server/MCUtil.java
|
|
+++ b/src/main/java/net/minecraft/server/MCUtil.java
|
|
@@ -625,7 +625,7 @@ public final class MCUtil {
|
|
|
|
ServerLevel world = ((org.bukkit.craftbukkit.CraftWorld)bukkitWorld).getHandle();
|
|
ChunkMap chunkMap = world.getChunkSource().chunkMap;
|
|
- Long2ObjectLinkedOpenHashMap<ChunkHolder> visibleChunks = chunkMap.visibleChunkMap;
|
|
+ Long2ObjectLinkedOpenHashMap<ChunkHolder> visibleChunks = chunkMap.updatingChunks.getVisibleMap(); // Paper
|
|
DistanceManager chunkMapDistance = chunkMap.distanceManager;
|
|
List<ChunkHolder> allChunks = new ArrayList<>(visibleChunks.values());
|
|
List<ServerPlayer> players = world.players;
|
|
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
|
index bb8478d9a216ec53f650b887508638965f371d47..a04a52b5e154d55a7b1d35f0094bbac055612054 100644
|
|
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
|
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
|
@@ -126,9 +126,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
|
private static final int MIN_VIEW_DISTANCE = 3;
|
|
public static final int MAX_VIEW_DISTANCE = 33;
|
|
public static final int MAX_CHUNK_DISTANCE = 33 + ChunkStatus.maxDistance();
|
|
+ // Paper start - Don't copy
|
|
+ public final com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object<ChunkHolder> updatingChunks = new com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object<>();
|
|
+ // Paper end - Don't copy
|
|
public static final int FORCED_TICKET_LEVEL = 31;
|
|
- public final Long2ObjectLinkedOpenHashMap<ChunkHolder> updatingChunkMap = new Long2ObjectLinkedOpenHashMap();
|
|
- public volatile Long2ObjectLinkedOpenHashMap<ChunkHolder> visibleChunkMap;
|
|
+ // Paper - Don't copy
|
|
private final Long2ObjectLinkedOpenHashMap<ChunkHolder> pendingUnloads;
|
|
public final LongSet entitiesInLevel;
|
|
public final ServerLevel level;
|
|
@@ -321,7 +323,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
|
boolean unloadingPlayerChunk = false; // Paper - do not allow ticket level changes while unloading chunks
|
|
public ChunkMap(ServerLevel world, LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, StructureTemplateManager structureTemplateManager, Executor executor, BlockableEventLoop<Runnable> mainThreadExecutor, LightChunkGetter chunkProvider, ChunkGenerator chunkGenerator, ChunkProgressListener worldGenerationProgressListener, ChunkStatusUpdateListener chunkStatusChangeListener, Supplier<DimensionDataStorage> persistentStateManagerFactory, int viewDistance, boolean dsync) {
|
|
super(session.getDimensionPath(world.dimension()).resolve("region"), dataFixer, dsync);
|
|
- this.visibleChunkMap = this.updatingChunkMap.clone();
|
|
+ // Paper - don't copy
|
|
this.pendingUnloads = new Long2ObjectLinkedOpenHashMap();
|
|
this.entitiesInLevel = new LongOpenHashSet();
|
|
this.toDrop = new LongOpenHashSet();
|
|
@@ -562,12 +564,17 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
|
|
|
@Nullable
|
|
public ChunkHolder getUpdatingChunkIfPresent(long pos) {
|
|
- return (ChunkHolder) this.updatingChunkMap.get(pos);
|
|
+ return this.updatingChunks.getUpdating(pos); // Paper - Don't copy
|
|
}
|
|
|
|
@Nullable
|
|
public ChunkHolder getVisibleChunkIfPresent(long pos) {
|
|
- return (ChunkHolder) this.visibleChunkMap.get(pos);
|
|
+ // Paper start - Don't copy
|
|
+ if (Thread.currentThread() == this.level.thread) {
|
|
+ return this.updatingChunks.getVisible(pos);
|
|
+ }
|
|
+ return this.updatingChunks.getVisibleAsync(pos);
|
|
+ // Paper end - Don't copy
|
|
}
|
|
|
|
protected IntSupplier getChunkQueueLevel(long pos) {
|
|
@@ -707,9 +714,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
|
};
|
|
|
|
stringbuilder.append("Updating:").append(System.lineSeparator());
|
|
- this.updatingChunkMap.values().forEach(consumer);
|
|
+ this.updatingChunks.getUpdatingValuesCopy().forEach(consumer); // Paper
|
|
stringbuilder.append("Visible:").append(System.lineSeparator());
|
|
- this.visibleChunkMap.values().forEach(consumer);
|
|
+ this.updatingChunks.getVisibleValuesCopy().forEach(consumer); // Paper
|
|
CrashReport crashreport = CrashReport.forThrowable(exception, "Chunk loading");
|
|
CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Chunk loading");
|
|
|
|
@@ -760,7 +767,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
|
// Paper end
|
|
}
|
|
|
|
- this.updatingChunkMap.put(pos, holder);
|
|
+ this.updatingChunks.queueUpdate(pos, holder); // Paper - Don't copy
|
|
this.modified = true;
|
|
}
|
|
|
|
@@ -840,7 +847,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
|
|
|
protected void saveAllChunks(boolean flush) {
|
|
if (flush) {
|
|
- List<ChunkHolder> list = (List) this.visibleChunkMap.values().stream().filter(ChunkHolder::wasAccessibleSinceLastSave).peek(ChunkHolder::refreshAccessibility).collect(Collectors.toList());
|
|
+ List<ChunkHolder> list = (List) this.updatingChunks.getVisibleValuesCopy().stream().filter(ChunkHolder::wasAccessibleSinceLastSave).peek(ChunkHolder::refreshAccessibility).collect(Collectors.toList()); // Paper
|
|
MutableBoolean mutableboolean = new MutableBoolean();
|
|
|
|
do {
|
|
@@ -871,7 +878,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
|
//this.flushWorker(); // Paper - nuke IOWorker
|
|
this.level.asyncChunkTaskManager.flush(); // Paper - flush to preserve behavior compat with pre-async behaviour
|
|
} else {
|
|
- this.visibleChunkMap.values().forEach(this::saveChunkIfNeeded);
|
|
+ this.updatingChunks.getVisibleValuesCopy().forEach(this::saveChunkIfNeeded); // Paper
|
|
}
|
|
|
|
}
|
|
@@ -894,14 +901,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
|
}
|
|
|
|
public boolean hasWork() {
|
|
- return this.lightEngine.hasLightWork() || !this.pendingUnloads.isEmpty() || !this.updatingChunkMap.isEmpty() || this.poiManager.hasWork() || !this.toDrop.isEmpty() || !this.unloadQueue.isEmpty() || this.queueSorter.hasWork() || this.distanceManager.hasTickets();
|
|
+ return this.lightEngine.hasLightWork() || !this.pendingUnloads.isEmpty() || !this.updatingChunks.getUpdatingValuesCopy().isEmpty() || this.poiManager.hasWork() || !this.toDrop.isEmpty() || !this.unloadQueue.isEmpty() || this.queueSorter.hasWork() || this.distanceManager.hasTickets(); // Paper
|
|
}
|
|
|
|
private void processUnloads(BooleanSupplier shouldKeepTicking) {
|
|
LongIterator longiterator = this.toDrop.iterator();
|
|
for (int i = 0; longiterator.hasNext() && (shouldKeepTicking.getAsBoolean() || i < 200 || this.toDrop.size() > 2000); longiterator.remove()) {
|
|
long j = longiterator.nextLong();
|
|
- ChunkHolder playerchunk = (ChunkHolder) this.updatingChunkMap.remove(j);
|
|
+ ChunkHolder playerchunk = this.updatingChunks.queueRemove(j); // Paper - Don't copy
|
|
|
|
if (playerchunk != null) {
|
|
playerchunk.onChunkRemove(); // Paper
|
|
@@ -996,7 +1003,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
|
if (!this.modified) {
|
|
return false;
|
|
} else {
|
|
- this.visibleChunkMap = this.updatingChunkMap.clone();
|
|
+ // Paper start - Don't copy
|
|
+ synchronized (this.updatingChunks) {
|
|
+ this.updatingChunks.performUpdates();
|
|
+ }
|
|
+ // Paper end - Don't copy
|
|
+
|
|
this.modified = false;
|
|
return true;
|
|
}
|
|
@@ -1496,7 +1508,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
|
|
|
this.viewDistance = j;
|
|
this.distanceManager.updatePlayerTickets(this.viewDistance + 1);
|
|
- ObjectIterator objectiterator = this.updatingChunkMap.values().iterator();
|
|
+ Iterator objectiterator = this.updatingChunks.getVisibleValuesCopy().iterator(); // Paper
|
|
|
|
while (objectiterator.hasNext()) {
|
|
ChunkHolder playerchunk = (ChunkHolder) objectiterator.next();
|
|
@@ -1539,7 +1551,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
|
}
|
|
|
|
public int size() {
|
|
- return this.visibleChunkMap.size();
|
|
+ return this.updatingChunks.getVisibleMap().size(); // Paper - Don't copy
|
|
}
|
|
|
|
public DistanceManager getDistanceManager() {
|
|
@@ -1547,13 +1559,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
|
}
|
|
|
|
protected Iterable<ChunkHolder> getChunks() {
|
|
- return Iterables.unmodifiableIterable(this.visibleChunkMap.values());
|
|
+ return Iterables.unmodifiableIterable(this.updatingChunks.getVisibleValuesCopy()); // Paper
|
|
}
|
|
|
|
void dumpChunks(Writer writer) throws IOException {
|
|
CsvOutput csvwriter = CsvOutput.builder().addColumn("x").addColumn("z").addColumn("level").addColumn("in_memory").addColumn("status").addColumn("full_status").addColumn("accessible_ready").addColumn("ticking_ready").addColumn("entity_ticking_ready").addColumn("ticket").addColumn("spawning").addColumn("block_entity_count").addColumn("ticking_ticket").addColumn("ticking_level").addColumn("block_ticks").addColumn("fluid_ticks").build(writer);
|
|
TickingTracker tickingtracker = this.distanceManager.tickingTracker();
|
|
- ObjectBidirectionalIterator objectbidirectionaliterator = this.visibleChunkMap.long2ObjectEntrySet().iterator();
|
|
+ ObjectBidirectionalIterator objectbidirectionaliterator = this.updatingChunks.getVisibleMap().clone().long2ObjectEntrySet().fastIterator(); // Paper
|
|
|
|
while (objectbidirectionaliterator.hasNext()) {
|
|
Entry<ChunkHolder> entry = (Entry) objectbidirectionaliterator.next();
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
|
index 21bf39ef5b20ecc989881b07c4e6b90c68540afd..beee040abf846492cefabe985c5286b00fc6bc63 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
|
@@ -167,7 +167,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
|
@Override
|
|
public int getTileEntityCount() {
|
|
// We don't use the full world tile entity list, so we must iterate chunks
|
|
- Long2ObjectLinkedOpenHashMap<ChunkHolder> chunks = world.getChunkSource().chunkMap.visibleChunkMap;
|
|
+ Long2ObjectLinkedOpenHashMap<ChunkHolder> chunks = world.getChunkSource().chunkMap.updatingChunks.getVisibleMap(); // Paper - change updating chunks map
|
|
int size = 0;
|
|
for (ChunkHolder playerchunk : chunks.values()) {
|
|
net.minecraft.world.level.chunk.LevelChunk chunk = playerchunk.getTickingChunk();
|
|
@@ -188,7 +188,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
|
public int getChunkCount() {
|
|
int ret = 0;
|
|
|
|
- for (ChunkHolder chunkHolder : world.getChunkSource().chunkMap.visibleChunkMap.values()) {
|
|
+ for (ChunkHolder chunkHolder : world.getChunkSource().chunkMap.updatingChunks.getVisibleMap().values()) { // Paper - change updating chunks map
|
|
if (chunkHolder.getTickingChunk() != null) {
|
|
++ret;
|
|
}
|
|
@@ -345,7 +345,18 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
|
|
|
@Override
|
|
public Chunk[] getLoadedChunks() {
|
|
- Long2ObjectLinkedOpenHashMap<ChunkHolder> chunks = this.world.getChunkSource().chunkMap.visibleChunkMap;
|
|
+ // Paper start
|
|
+ if (Thread.currentThread() != world.getLevel().thread) {
|
|
+ // Paper start - change updating chunks map
|
|
+ Long2ObjectLinkedOpenHashMap<ChunkHolder> chunks;
|
|
+ synchronized (world.getChunkSource().chunkMap.updatingChunks) {
|
|
+ chunks = world.getChunkSource().chunkMap.updatingChunks.getVisibleMap().clone();
|
|
+ }
|
|
+ return chunks.values().stream().map(ChunkHolder::getFullChunkNow).filter(Objects::nonNull).map(net.minecraft.world.level.chunk.LevelChunk::getBukkitChunk).toArray(Chunk[]::new);
|
|
+ // Paper end - change updating chunks map
|
|
+ }
|
|
+ // Paper end
|
|
+ Long2ObjectLinkedOpenHashMap<ChunkHolder> chunks = this.world.getChunkSource().chunkMap.updatingChunks.getVisibleMap(); // Paper - change updating chunks map
|
|
return chunks.values().stream().map(ChunkHolder::getFullChunkNow).filter(Objects::nonNull).map(net.minecraft.world.level.chunk.LevelChunk::getBukkitChunk).toArray(Chunk[]::new);
|
|
}
|
|
|
|
@@ -421,7 +432,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
|
|
|
@Override
|
|
public boolean refreshChunk(int x, int z) {
|
|
- ChunkHolder playerChunk = this.world.getChunkSource().chunkMap.visibleChunkMap.get(ChunkPos.asLong(x, z));
|
|
+ ChunkHolder playerChunk = this.world.getChunkSource().chunkMap.updatingChunks.getVisibleMap().get(ChunkPos.asLong(x, z));
|
|
if (playerChunk == null) return false;
|
|
|
|
playerChunk.getTickingChunkFuture().thenAccept(either -> {
|