aboutsummaryrefslogtreecommitdiffhomepage
path: root/patches/server/0881-Fix-save-problems-on-shutdown.patch
blob: 97b9516f0953d23b515dc6fc4e186563d40e67af (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
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Sat, 5 Mar 2022 17:12:52 -0800
Subject: [PATCH] Fix save problems on shutdown

- Save level.dat first, in case the shutdown is killed later
- Force run minecraftserver tasks and the chunk source tasks
  while waiting for the chunk system to empty, as there's simply
  too much trash that could prevent them from executing during
  the chunk source tick (i.e "time left in tick" logic).
- Set forceTicks to true, so that player packets are always
  processed so that the main process queue can be drained

diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 17e87875a95495940899b862eabf98b3d6a365da..39b7c78b032ed6fc29ac765020d5a38858bf2a3a 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -998,6 +998,13 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
             }
         }
 
+        // Paper start - let's be a little more intelligent around crashes
+        // make sure level.dat saves
+        for (ServerLevel level : this.getAllLevels()) {
+            level.saveLevelDat();
+        }
+        // Paper end - let's be a little more intelligent around crashes
+
         while (this.levels.values().stream().anyMatch((worldserver1) -> {
             return worldserver1.getChunkSource().chunkMap.hasWork();
         })) {
@@ -1010,9 +1017,11 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
                 worldserver.getChunkSource().tick(() -> {
                     return true;
                 }, false);
+                while (worldserver.getChunkSource().pollTask()); // Paper - drain tasks
             }
 
-            this.waitUntilNextTick();
+            this.forceTicks = true; // Paper
+            while (this.pollTask()); // Paper - drain tasks
         }
 
         this.saveAllChunks(false, true, false);
@@ -1308,6 +1317,11 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
     }
 
     private boolean haveTime() {
+        // Paper start
+        if (this.forceTicks) {
+            return true;
+        }
+        // Paper end
         // CraftBukkit start
         if (isOversleep) return canOversleep();// Paper - because of our changes, this logic is broken
         return this.forceTicks || this.runningTask() || Util.getMillis() < (this.mayHaveDelayedTasks ? this.delayedTasksMaxNextTickTime : this.nextTickTime);
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index b5b56d4549e97abbbe9e91d881b9bca8428f1eec..dce7452d58d6081f1a83baddafb1596ebd423d21 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -1258,7 +1258,13 @@ public class ServerLevel extends Level implements WorldGenLevel {
             }
 
         }
+        // Paper start
+        this.saveLevelDat();
+    }
 
+    public void saveLevelDat() {
+        this.saveLevelData();
+        // Paper end
         // CraftBukkit start - moved from MinecraftServer.saveChunks
         ServerLevel worldserver1 = this;