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
134
|
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
Feature patch
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index ca70815b73199835b88c9d68c8a01699536d320f..be6e64d5c858961b19eb7b1b028530c1eb4c68d7 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -1007,7 +1007,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;
@@ -1655,9 +1655,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 2e0dcac7642d899efd60cf70fb0ad0336e1923da..b5f0ce0869c0ea6ad478bddddfc463ec42a5bef7 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -1353,6 +1353,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 2b6c5b2387b67f25d8877849ccbfaaa77eab51d3..05981a075898794b899f1327bff1e7ca8ef8fc13 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 532e4c1dac20d7481557bb8c84f81c30994ae4d5..8de23b39806734c9a413b6d98dbfff25888c1798 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
|