aboutsummaryrefslogtreecommitdiffhomepage
path: root/Spigot-Server-Patches/0537-Delay-Chunk-Unloads-based-on-Player-Movement.patch
blob: 36bc22fde837ebade0ba89c99d439d58e5e09a06 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
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 will be handled by the ticket expiry process.

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 c3f7717869c86d9ac6395615bceda324aea16b27..ecacb72b922927f06883b75e7d2cc1f904eb9f03 100644
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
@@ -682,4 +682,13 @@ public class PaperWorldConfig {
     private void viewDistance() {
         this.noTickViewDistance = this.getInt("viewdistances.no-tick-view-distance", -1);
     }
+
+    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 *= 20;
+        }
+    }
 }
diff --git a/src/main/java/net/minecraft/server/ChunkMapDistance.java b/src/main/java/net/minecraft/server/ChunkMapDistance.java
index ff9e164574f1f3d043740ac727faf567122e5b64..cc02ed6b58a219d8f06e4ccc2a51f46c33af98d1 100644
--- a/src/main/java/net/minecraft/server/ChunkMapDistance.java
+++ b/src/main/java/net/minecraft/server/ChunkMapDistance.java
@@ -176,6 +176,27 @@ public abstract class ChunkMapDistance {
         boolean removed = false; // CraftBukkit
         if (arraysetsorted.remove(ticket)) {
             removed = true; // CraftBukkit
+            // Paper start - delay chunk unloads for player tickets
+            long delayChunkUnloadsBy = chunkMap.world.paperConfig.delayChunkUnloadsBy;
+            if (ticket.getTicketType() == TicketType.PLAYER && delayChunkUnloadsBy > 0) {
+                boolean hasPlayer = false;
+                for (Ticket<?> ticket1 : arraysetsorted) {
+                    if (ticket1.getTicketType() == TicketType.PLAYER) {
+                        hasPlayer = true;
+                        break;
+                    }
+                }
+                PlayerChunk playerChunk = chunkMap.getUpdatingChunk(i);
+                if (!hasPlayer && playerChunk != null && playerChunk.isFullChunkReady()) {
+                    Ticket<Long> delayUnload = new Ticket<Long>(TicketType.DELAY_UNLOAD, 33, i);
+                    delayUnload.delayUnloadBy = delayChunkUnloadsBy;
+                    delayUnload.setCurrentTick(this.currentTick);
+                    arraysetsorted.remove(delayUnload);
+                    // refresh ticket
+                    arraysetsorted.add(delayUnload);
+                }
+            }
+            // Paper end
         }
 
         if (arraysetsorted.isEmpty()) {
diff --git a/src/main/java/net/minecraft/server/Ticket.java b/src/main/java/net/minecraft/server/Ticket.java
index 0d6e0f2ddaa85c04e626980591e9a78ac27fb42d..c79aa4a80a8a2288f7a50466abd677f388360ba1 100644
--- a/src/main/java/net/minecraft/server/Ticket.java
+++ b/src/main/java/net/minecraft/server/Ticket.java
@@ -9,11 +9,13 @@ public final class Ticket<T> implements Comparable<Ticket<?>> {
     public final T identifier; public final T getObjectReason() { return this.identifier; } // Paper - OBFHELPER
     private long d; public final long getCreationTick() { return this.d; } // Paper - OBFHELPER
     public int priority = 0; // Paper
+    public long delayUnloadBy; // Paper
 
     protected Ticket(TicketType<T> tickettype, int i, T t0) {
         this.a = tickettype;
         this.b = i;
         this.identifier = t0;
+        this.delayUnloadBy = tickettype.loadPeriod; // Paper
     }
 
     public int compareTo(Ticket<?> ticket) {
@@ -57,12 +59,13 @@ public final class Ticket<T> implements Comparable<Ticket<?>> {
         return this.b;
     }
 
+    protected void setCurrentTick(long i) { a(i); } // Paper - OBFHELPER
     protected void a(long i) {
         this.d = i;
     }
 
     protected boolean b(long i) {
-        long j = this.a.b();
+        long j = delayUnloadBy; // Paper
 
         return j != 0L && i - this.d > j;
     }
diff --git a/src/main/java/net/minecraft/server/TicketType.java b/src/main/java/net/minecraft/server/TicketType.java
index 6fd852db6bcfbfbf84ec2acf6d23b08a6051165c..5c789b25f1df2eae8ea8ceb4ba977ba336fe6d5e 100644
--- a/src/main/java/net/minecraft/server/TicketType.java
+++ b/src/main/java/net/minecraft/server/TicketType.java
@@ -26,6 +26,7 @@ public class TicketType<T> {
     public static final TicketType<Long> ASYNC_LOAD = a("async_load", Long::compareTo); // Paper
     public static final TicketType<ChunkCoordIntPair> PRIORITY = a("priority", Comparator.comparingLong(ChunkCoordIntPair::pair), 300); // Paper
     public static final TicketType<ChunkCoordIntPair> URGENT = a("urgent", Comparator.comparingLong(ChunkCoordIntPair::pair), 300); // Paper
+    public static final TicketType<Long> DELAY_UNLOAD = a("delay_unload", Long::compareTo, 300); // Paper
 
     public static <T> TicketType<T> a(String s, Comparator<T> comparator) {
         return new TicketType<>(s, comparator, 0L);