aboutsummaryrefslogtreecommitdiffhomepage
path: root/patches/server/1048-Incremental-chunk-and-player-saving.patch
blob: 14a46b153bcfe206f5b15ffb90a274de32ba0ea9 (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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shane Freeder <theboyetronic@gmail.com>
Date: Sun, 9 Jun 2019 03:53:22 +0100
Subject: [PATCH] Incremental chunk and player saving


diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 3340c1b7afa9ac237b295295774a8454d36b862c..ae1449b6b9a74048e5c6eea8b6005a264ff9ad90 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -1008,7 +1008,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
 
         try {
             this.isSaving = true;
-            this.getPlayerList().saveAll();
+            this.getPlayerList().saveAll(); // Paper - Incremental chunk and player saving; diff on change
             flag3 = this.saveAllChunks(suppressLogs, flush, force);
         } finally {
             this.isSaving = false;
@@ -1657,9 +1657,29 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
         }
 
         --this.ticksUntilAutosave;
-        if (this.autosavePeriod > 0 && this.ticksUntilAutosave <= 0) { // CraftBukkit
-            this.autoSave();
+        // Paper start - Incremental chunk and player saving
+        final ProfilerFiller profiler = Profiler.get();
+        int playerSaveInterval = io.papermc.paper.configuration.GlobalConfiguration.get().playerAutoSave.rate;
+        if (playerSaveInterval < 0) {
+            playerSaveInterval = autosavePeriod;
+        }
+        profiler.push("save");
+        final boolean fullSave = autosavePeriod > 0 && this.tickCount % autosavePeriod == 0;
+        try {
+            this.isSaving = true;
+            if (playerSaveInterval > 0) {
+                this.playerList.saveAll(playerSaveInterval);
+            }
+            for (final ServerLevel level : this.getAllLevels()) {
+                if (level.paperConfig().chunks.autoSaveInterval.value() > 0) {
+                    level.saveIncrementally(fullSave);
+                }
+            }
+        } finally {
+            this.isSaving = false;
         }
+        profiler.pop();
+        // Paper end - Incremental chunk and player saving
 
         ProfilerFiller gameprofilerfiller = Profiler.get();
 
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index c9d7ea8fbaf8858564282b42f6f6dda3d6927f8e..2519a886317362db4ac0aeadb3655624f175cd99 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -1347,6 +1347,30 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
         return !this.server.isUnderSpawnProtection(this, pos, player) && this.getWorldBorder().isWithinBounds(pos);
     }
 
+    // Paper start - Incremental chunk and player saving
+    public void saveIncrementally(boolean doFull) {
+        ServerChunkCache chunkproviderserver = this.getChunkSource();
+
+        if (doFull) {
+            org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld()));
+        }
+
+        if (doFull) {
+            this.saveLevelData(true);
+        }
+        // chunk autosave is already called by the ChunkSystem during unload processing (ChunkMap#processUnloads)
+        // Copied from save()
+        // CraftBukkit start - moved from MinecraftServer.saveChunks
+        if (doFull) { // Paper
+            ServerLevel worldserver1 = this;
+            this.serverLevelData.setWorldBorder(worldserver1.getWorldBorder().createSettings());
+            this.serverLevelData.setCustomBossEvents(this.server.getCustomBossEvents().save(this.registryAccess()));
+            this.convertable.saveDataTag(this.server.registryAccess(), this.serverLevelData, this.server.getPlayerList().getSingleplayerData());
+        }
+        // CraftBukkit end
+    }
+    // Paper end - Incremental chunk and player saving
+
     public void save(@Nullable ProgressListener progressListener, boolean flush, boolean savingDisabled) {
         // Paper start - add close param
         this.save(progressListener, flush, savingDisabled, false);
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
index 8ceeebb561046933cba0725e15732fa074226884..8c9148426f23cbbdfaf7ae66657d1a620f8bd853 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -221,6 +221,7 @@ import org.bukkit.inventory.MainHand;
 public class ServerPlayer extends net.minecraft.world.entity.player.Player implements ca.spottedleaf.moonrise.patches.chunk_system.player.ChunkSystemServerPlayer { // Paper - rewrite chunk system
 
     private static final Logger LOGGER = LogUtils.getLogger();
+    public long lastSave = MinecraftServer.currentTick; // Paper - Incremental chunk and player saving
     private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_XZ = 32;
     private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_Y = 10;
     private static final int FLY_STAT_RECORDING_SPEED = 25;
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index 88f40e54fa3b78d82261e06f941ef42587d52c25..cf42042c754b30e41c0ec8a6a15195369bdbd199 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -518,6 +518,7 @@ public abstract class PlayerList {
 
     protected void save(ServerPlayer player) {
         if (!player.getBukkitEntity().isPersistent()) return; // CraftBukkit
+        player.lastSave = MinecraftServer.currentTick; // Paper - Incremental chunk and player saving
         this.playerIo.save(player);
         ServerStatsCounter serverstatisticmanager = (ServerStatsCounter) player.getStats(); // CraftBukkit
 
@@ -1152,9 +1153,21 @@ public abstract class PlayerList {
     }
 
     public void saveAll() {
+        // Paper start - Incremental chunk and player saving
+        this.saveAll(-1);
+    }
+
+    public void saveAll(int interval) {
         io.papermc.paper.util.MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main
+        int numSaved = 0;
+        long now = MinecraftServer.currentTick;
         for (int i = 0; i < this.players.size(); ++i) {
-            this.save((ServerPlayer) this.players.get(i));
+            final ServerPlayer player = this.players.get(i);
+            if (interval == -1 || now - player.lastSave >= interval) {
+                this.save(player);
+                if (interval != -1 && ++numSaved >= io.papermc.paper.configuration.GlobalConfiguration.get().playerAutoSave.maxPerTick()) { break; }
+            }
+            // Paper end - Incremental chunk and player saving
         }
 
         return null; }); // Paper - ensure main