05466e3b47
Upstream has released updates that appear to apply compile correctly. This update has not been tested by PaperMC and as with ANY update, please do your own testing. Bukkit Changes: d2834556 SPIGOT-4219: Event for PigZombies angering. CraftBukkit Changes: a9c796f1 SPIGOT-4184: Fix furnaces not matching Vanilla smelt or animations 195f071e SPIGOT-4219: Event for PigZombies angering. 5e3082c7 SPIGOT-4230: Improve legacy block types
182 lines
8.8 KiB
Diff
182 lines
8.8 KiB
Diff
From 15087609882f8372870b8dfe7f6cf033071fc532 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.
|
|
|
|
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
|
index 41e73b3409..ec6b550ff6 100644
|
|
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
|
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
|
@@ -285,4 +285,18 @@ 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 63ca61c1d6..ace64c0345 100644
|
|
--- a/src/main/java/net/minecraft/server/Chunk.java
|
|
+++ b/src/main/java/net/minecraft/server/Chunk.java
|
|
@@ -39,6 +39,7 @@ public class Chunk implements IChunkAccess {
|
|
private boolean j; public boolean isLoaded() { return j; } // 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 m;
|
|
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
|
index 2925c345a1..a5139b0b0d 100644
|
|
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
|
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
|
@@ -328,6 +328,19 @@ 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.f.a();
|
|
this.chunkLoader.b();
|
|
diff --git a/src/main/java/net/minecraft/server/PlayerChunk.java b/src/main/java/net/minecraft/server/PlayerChunk.java
|
|
index ffff87dc03..344b95233f 100644
|
|
--- a/src/main/java/net/minecraft/server/PlayerChunk.java
|
|
+++ b/src/main/java/net/minecraft/server/PlayerChunk.java
|
|
@@ -33,14 +33,23 @@ public class PlayerChunk {
|
|
public void run() {
|
|
loadInProgress = false;
|
|
PlayerChunk.this.chunk = PlayerChunk.this.playerChunkMap.getWorld().getChunkProviderServer().getOrLoadChunkAt(location.x, location.z);
|
|
+ markChunkUsed(); // Paper - delay chunk unloads
|
|
}
|
|
};
|
|
+ // Paper start - delay chunk unloads
|
|
+ public final void markChunkUsed() {
|
|
+ if (chunk != null && chunk.scheduledForUnload != null) {
|
|
+ chunk.scheduledForUnload = null;
|
|
+ }
|
|
+ }
|
|
+ // Paper end
|
|
// CraftBukkit end
|
|
|
|
public PlayerChunk(PlayerChunkMap playerchunkmap, int i, int j) {
|
|
this.playerChunkMap = playerchunkmap;
|
|
this.location = new ChunkCoordIntPair(i, j);
|
|
this.chunk = playerchunkmap.getWorld().getChunkProviderServer().getOrLoadChunkAt(i, j);
|
|
+ markChunkUsed(); // Paper - delay chunk unloads
|
|
}
|
|
|
|
public ChunkCoordIntPair a() {
|
|
@@ -85,6 +94,7 @@ public class PlayerChunk {
|
|
this.chunk = this.playerChunkMap.getWorld().getChunkProviderServer().getChunkAt(this.location.x, this.location.z);
|
|
} else {
|
|
this.chunk = this.playerChunkMap.getWorld().getChunkProviderServer().getOrLoadChunkAt(this.location.x, this.location.z);
|
|
+ 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 4d888d6d4f..cf5c76a78e 100644
|
|
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
|
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
|
@@ -461,7 +461,13 @@ public class PlayerChunkMap {
|
|
Chunk chunk = playerchunk.f();
|
|
|
|
if (chunk != null) {
|
|
- this.getWorld().getChunkProviderServer().unload(chunk);
|
|
+ // Paper start - delay chunk unloads
|
|
+ if (world.paperConfig.delayChunkUnloadsBy <= 0) {
|
|
+ this.getWorld().getChunkProviderServer().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 7dae87199e..b6efd8506b 100644
|
|
--- a/src/main/java/net/minecraft/server/World.java
|
|
+++ b/src/main/java/net/minecraft/server/World.java
|
|
@@ -1305,7 +1305,13 @@ public abstract class World implements GeneratorAccess, IIBlockAccess, AutoClose
|
|
if (!tileentity.x() && tileentity.u()) {
|
|
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.isUnloading() && 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 e3e45ed48a..d4851dd2a6 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
|
@@ -1577,7 +1577,7 @@ public class CraftWorld implements World {
|
|
ChunkProviderServer cps = world.getChunkProviderServer();
|
|
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 a9b84fdec4..e02647f806 100644
|
|
--- a/src/main/java/org/spigotmc/ActivationRange.java
|
|
+++ b/src/main/java/org/spigotmc/ActivationRange.java
|
|
@@ -284,6 +284,10 @@ public class ActivationRange
|
|
{
|
|
isActive = false;
|
|
}
|
|
+ // Paper start - Skip ticking in chunks scheduled for unload
|
|
+ if(entity.world.paperConfig.skipEntityTickingInChunksScheduledForUnload && (chunk == null || chunk.isUnloading() || chunk.scheduledForUnload != null))
|
|
+ isActive = false;
|
|
+ // Paper end
|
|
return isActive;
|
|
}
|
|
}
|
|
--
|
|
2.18.0
|
|
|