More 1.14 work
This commit is contained in:
@@ -1,222 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sat, 18 Jun 2016 23:22:12 -0400
|
||||
Subject: [PATCH] Delay Chunk Unloads based on Player Movement
|
||||
|
||||
When players are moving in the world, doing things such as building or exploring,
|
||||
they will commonly go back and forth in a small area. This causes a ton of chunk load
|
||||
and unload activity on the edge chunks of their view distance.
|
||||
|
||||
A simple back and forth movement in 6 blocks could spam a chunk to thrash a
|
||||
loading and unload cycle over and over again.
|
||||
|
||||
This is very wasteful. This system introduces a delay of inactivity on a chunk
|
||||
before it actually unloads, which is maintained separately from ChunkGC.
|
||||
|
||||
This allows servers with smaller worlds who do less long distance exploring to stop
|
||||
wasting cpu cycles on saving/unloading/reloading chunks repeatedly.
|
||||
|
||||
This also makes the Chunk GC System useless, by auto scheduling unload as soon as
|
||||
a spare chunk is added to the server thats outside of view distance.
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
index bcc2ecaa3a..c70771614d 100644
|
||||
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
@@ -0,0 +0,0 @@ public class PaperWorldConfig {
|
||||
preventTntFromMovingInWater = getBoolean("prevent-tnt-from-moving-in-water", false);
|
||||
log("Prevent TNT from moving in water: " + preventTntFromMovingInWater);
|
||||
}
|
||||
+
|
||||
+ public long delayChunkUnloadsBy;
|
||||
+ private void delayChunkUnloadsBy() {
|
||||
+ delayChunkUnloadsBy = PaperConfig.getSeconds(getString("delay-chunk-unloads-by", "10s"));
|
||||
+ if (delayChunkUnloadsBy > 0) {
|
||||
+ log("Delaying chunk unloads by " + delayChunkUnloadsBy + " seconds");
|
||||
+ delayChunkUnloadsBy *= 1000;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public boolean skipEntityTickingInChunksScheduledForUnload = true;
|
||||
+ private void skipEntityTickingInChunksScheduledForUnload() {
|
||||
+ skipEntityTickingInChunksScheduledForUnload = getBoolean("skip-entity-ticking-in-chunks-scheduled-for-unload", skipEntityTickingInChunksScheduledForUnload);
|
||||
+ }
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java
|
||||
index c74176daa5..bdf922db50 100644
|
||||
--- a/src/main/java/net/minecraft/server/Chunk.java
|
||||
+++ b/src/main/java/net/minecraft/server/Chunk.java
|
||||
@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess {
|
||||
private boolean i;public boolean isLoaded() { return i; } // Paper - OBFHELPER
|
||||
public final World world;
|
||||
public final Map<HeightMap.Type, HeightMap> heightMap;
|
||||
+ public Long scheduledForUnload; // Paper - delay chunk unloads
|
||||
public final int locX;
|
||||
public final int locZ;
|
||||
private boolean l;
|
||||
diff --git a/src/main/java/net/minecraft/server/ChunkMap.java b/src/main/java/net/minecraft/server/ChunkMap.java
|
||||
index 8b3738c8f7..2021c0d02e 100644
|
||||
--- a/src/main/java/net/minecraft/server/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/ChunkMap.java
|
||||
@@ -0,0 +0,0 @@ public class ChunkMap extends Long2ObjectOpenHashMap<Chunk> {
|
||||
}
|
||||
}
|
||||
}
|
||||
+ // Paper start - if this is a spare chunk (not part of any players view distance), go ahead and queue it for unload.
|
||||
+ if (!((WorldServer)chunk.world).getPlayerChunkMap().isChunkInUse(chunk.locX, chunk.locZ)) {
|
||||
+ if (chunk.world.paperConfig.delayChunkUnloadsBy > 0) {
|
||||
+ chunk.scheduledForUnload = System.currentTimeMillis();
|
||||
+ } else {
|
||||
+ ((WorldServer) chunk.world).getChunkProvider().unload(chunk);
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
chunk.world.timings.syncChunkLoadPostTimer.stopTiming(); // Paper
|
||||
// CraftBukkit end
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
||||
index c54df45837..d0bf0f72da 100644
|
||||
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
||||
@@ -0,0 +0,0 @@ public class ChunkProviderServer implements IChunkProvider {
|
||||
}
|
||||
activityAccountant.endActivity(); // Spigot
|
||||
}
|
||||
+ // Paper start - delayed chunk unloads
|
||||
+ long now = System.currentTimeMillis();
|
||||
+ long unloadAfter = world.paperConfig.delayChunkUnloadsBy;
|
||||
+ if (unloadAfter > 0) {
|
||||
+ //noinspection Convert2streamapi
|
||||
+ for (Chunk chunk : chunks.values()) {
|
||||
+ if (chunk.scheduledForUnload != null && now - chunk.scheduledForUnload > unloadAfter) {
|
||||
+ chunk.scheduledForUnload = null;
|
||||
+ unload(chunk);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
this.chunkScheduler.a(booleansupplier);
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/PlayerChunk.java b/src/main/java/net/minecraft/server/PlayerChunk.java
|
||||
index e47aae2f8b..b9d90c4fb8 100644
|
||||
--- a/src/main/java/net/minecraft/server/PlayerChunk.java
|
||||
+++ b/src/main/java/net/minecraft/server/PlayerChunk.java
|
||||
@@ -0,0 +0,0 @@ public class PlayerChunk {
|
||||
|
||||
chunkproviderserver.a(i, j);
|
||||
this.chunk = chunkproviderserver.getChunkAt(i, j, true, false);
|
||||
+ markChunkUsed(); // Paper - delay chunk unloads
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ private void markChunkUsed() {
|
||||
+ if (chunk == null) {
|
||||
+ return;
|
||||
+ }
|
||||
+ if (chunkHasPlayers) {
|
||||
+ chunk.scheduledForUnload = null;
|
||||
+ } else if (chunk.scheduledForUnload == null) {
|
||||
+ chunk.scheduledForUnload = System.currentTimeMillis();
|
||||
+ }
|
||||
+ }
|
||||
+ private boolean chunkHasPlayers = false;
|
||||
+ // Paper end
|
||||
+
|
||||
public ChunkCoordIntPair a() {
|
||||
return this.location;
|
||||
}
|
||||
@@ -0,0 +0,0 @@ public class PlayerChunk {
|
||||
} else {
|
||||
if (this.players.isEmpty()) {
|
||||
this.i = this.playerChunkMap.getWorld().getTime();
|
||||
+ chunkHasPlayers = true; // Paper - delay chunk unloads
|
||||
+ markChunkUsed(); // Paper - delay chunk unloads
|
||||
}
|
||||
|
||||
this.players.add(entityplayer);
|
||||
@@ -0,0 +0,0 @@ public class PlayerChunk {
|
||||
|
||||
this.players.remove(entityplayer);
|
||||
if (this.players.isEmpty()) {
|
||||
+ chunkHasPlayers = false; // Paper - delay chunk unloads
|
||||
+ markChunkUsed(); // Paper - delay chunk unloads
|
||||
this.playerChunkMap.b(this);
|
||||
}
|
||||
|
||||
@@ -0,0 +0,0 @@ public class PlayerChunk {
|
||||
return true;
|
||||
} else {
|
||||
this.chunk = this.playerChunkMap.getWorld().getChunkProvider().getChunkAt(this.location.x, this.location.z, true, flag);
|
||||
+ markChunkUsed(); // Paper - delay chunk unloads
|
||||
return this.chunk != null;
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
||||
index 2064576501..ab4f3b7223 100644
|
||||
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
||||
@@ -0,0 +0,0 @@ public class PlayerChunkMap {
|
||||
Chunk chunk = playerchunk.f();
|
||||
|
||||
if (chunk != null) {
|
||||
- this.getWorld().getChunkProvider().unload(chunk);
|
||||
+ // Paper start - delay chunk unloads
|
||||
+ if (world.paperConfig.delayChunkUnloadsBy <= 0) {
|
||||
+ this.getWorld().getChunkProvider().unload(chunk);
|
||||
+ } else {
|
||||
+ chunk.scheduledForUnload = System.currentTimeMillis();
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
|
||||
index 32ee298648..dcff6c8d8a 100644
|
||||
--- a/src/main/java/net/minecraft/server/World.java
|
||||
+++ b/src/main/java/net/minecraft/server/World.java
|
||||
@@ -0,0 +0,0 @@ public abstract class World implements IEntityAccess, GeneratorAccess, IIBlockAc
|
||||
if (!tileentity.x() && tileentity.hasWorld()) {
|
||||
BlockPosition blockposition = tileentity.getPosition();
|
||||
|
||||
- if (this.isLoaded(blockposition) && this.K.a(blockposition)) {
|
||||
+ // Paper start - Skip ticking in chunks scheduled for unload
|
||||
+ net.minecraft.server.Chunk chunk = this.getChunkIfLoaded(blockposition);
|
||||
+ boolean shouldTick = chunk != null;
|
||||
+ if(this.paperConfig.skipEntityTickingInChunksScheduledForUnload)
|
||||
+ shouldTick = shouldTick && chunk.scheduledForUnload == null;
|
||||
+ if (shouldTick && this.K.a(blockposition)) {
|
||||
+ // Paper end
|
||||
try {
|
||||
this.methodProfiler.a(() -> {
|
||||
return String.valueOf(TileEntityTypes.a(tileentity.C()));
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
index a8c7e7931e..f7883e7085 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
@@ -0,0 +0,0 @@ public class CraftWorld implements World {
|
||||
ChunkProviderServer cps = world.getChunkProvider();
|
||||
for (net.minecraft.server.Chunk chunk : cps.chunks.values()) {
|
||||
// If in use, skip it
|
||||
- if (isChunkInUse(chunk.locX, chunk.locZ)) {
|
||||
+ if (isChunkInUse(chunk.locX, chunk.locZ) || chunk.scheduledForUnload != null) { // Paper - delayed chunk unloads
|
||||
continue;
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java
|
||||
index d08ef3fe10..081789a8fe 100644
|
||||
--- a/src/main/java/org/spigotmc/ActivationRange.java
|
||||
+++ b/src/main/java/org/spigotmc/ActivationRange.java
|
||||
@@ -0,0 +0,0 @@ public class ActivationRange
|
||||
{
|
||||
isActive = false;
|
||||
}
|
||||
+ // Paper start - Skip ticking in chunks scheduled for unload
|
||||
+ else if (entity.world.paperConfig.skipEntityTickingInChunksScheduledForUnload && (chunk == null || chunk.scheduledForUnload != null)) {
|
||||
+ isActive = false;
|
||||
+ }
|
||||
+ // Paper end
|
||||
return isActive;
|
||||
}
|
||||
}
|
||||
--
|
||||
Reference in New Issue
Block a user