@@ -5,37 +5,81 @@ Subject: [PATCH] Incremental chunk and player saving
55
66
77diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
8- index a9751f4bda862ef597ba39700b83c434f7a457d9..90e23b96ed3fc5a84f52e6f94ad40bdb028fedf7 100644
8+ index 65a971379f35c4b1b519b93787f690d891e29523..dadad4106e774884bc32af0ce37591b08c6d9a4c 100644
99--- a/net/minecraft/server/MinecraftServer.java
1010+++ b/net/minecraft/server/MinecraftServer.java
11- @@ -972,7 +972,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
12- boolean var4;
11+ @@ -957,7 +957,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
12+ }
13+ public boolean saveAllChunks(final boolean silent, final boolean flush, final boolean force, final boolean close) {
14+ // Paper end - add close param
15+ - this.scoreboard.storeToSaveDataIfDirty(this.getDataStorage().computeIfAbsent(ScoreboardSaveData.TYPE));
16+ + this.saveGlobalData(flush); // Paper - move to saveGlobalData()
17+ boolean result = false;
18+
19+ for (ServerLevel level : this.getAllLevels()) {
20+ @@ -969,13 +969,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
21+ result = true;
22+ }
23+
24+ - GameProfile singleplayerProfile = this.getSingleplayerProfile();
25+ - this.storageSource.saveDataTag(this.worldData, singleplayerProfile == null ? null : singleplayerProfile.id());
26+ - if (flush) {
27+ - this.savedDataStorage.saveAndJoin();
28+ - } else {
29+ - this.savedDataStorage.scheduleSave();
30+ - }
31+ + // Paper - move to saveGlobalData()
32+
33+ if (flush) {
34+ for (ServerLevel level : this.getAllLevels()) {
35+ @@ -989,11 +983,25 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
36+ return result;
37+ }
38+
39+ + // Paper start - split out global level data
40+ + public void saveGlobalData(final boolean flush) {
41+ + this.scoreboard.storeToSaveDataIfDirty(this.getDataStorage().computeIfAbsent(ScoreboardSaveData.TYPE));
42+ +
43+ + GameProfile singleplayerProfile = this.getSingleplayerProfile();
44+ + this.storageSource.saveDataTag(this.worldData, singleplayerProfile == null ? null : singleplayerProfile.id());
45+ + if (flush) {
46+ + this.savedDataStorage.saveAndJoin();
47+ + } else {
48+ + this.savedDataStorage.scheduleSave();
49+ + }
50+ + }
51+ + // Paper end - split out global level data
52+ +
53+ public boolean saveEverything(final boolean silent, final boolean flush, final boolean force) {
54+ boolean var5;
1355 try {
1456 this.isSaving = true;
1557- this.getPlayerList().saveAll();
1658+ this.getPlayerList().saveAll(); // Paper - Incremental chunk and player saving; diff on change
17- var4 = this.saveAllChunks(suppressLogs , flush, force);
18- } finally {
19- this.isSaving = false ;
20- @@ -1615 ,9 +1615,29 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
59+ boolean result = this.saveAllChunks(silent , flush, force);
60+ this.warnOnLowDiskSpace();
61+ var5 = result ;
62+ @@ -1640 ,9 +1648,31 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
2163 }
2264
2365 this.ticksUntilAutosave--;
2466- if (this.autosavePeriod > 0 && this.ticksUntilAutosave <= 0) { // CraftBukkit
2567- this.autoSave();
2668+ // Paper start - Incremental chunk and player saving
27- + final ProfilerFiller profiler = Profiler.get();
2869+ int playerSaveInterval = io.papermc.paper.configuration.GlobalConfiguration.get().playerAutoSave.rate;
2970+ if (playerSaveInterval < 0) {
30- + playerSaveInterval = autosavePeriod;
71+ + playerSaveInterval = this. autosavePeriod;
3172+ }
32- + profiler .push("save");
33- + final boolean fullSave = autosavePeriod > 0 && this.tickCount % autosavePeriod == 0;
73+ + Profiler.get() .push("save");
74+ + final boolean fullSave = this. autosavePeriod > 0 && this.tickCount % this. autosavePeriod == 0;
3475+ try {
3576+ this.isSaving = true;
3677+ if (playerSaveInterval > 0) {
3778+ this.playerList.saveAll(playerSaveInterval);
3879+ }
80+ + if (fullSave) {
81+ + this.saveGlobalData(false);
82+ + }
3983+ for (final ServerLevel level : this.getAllLevels()) {
4084+ if (level.paperConfig().chunks.autoSaveInterval.value() > 0) {
4185+ level.saveIncrementally(fullSave);
@@ -44,47 +88,36 @@ index a9751f4bda862ef597ba39700b83c434f7a457d9..90e23b96ed3fc5a84f52e6f94ad40bdb
4488+ } finally {
4589+ this.isSaving = false;
4690 }
47- + profiler .pop();
91+ + Profiler.get() .pop();
4892+ // Paper end - Incremental chunk and player saving
4993
50- ProfilerFiller profilerFiller = Profiler.get();
94+ ProfilerFiller profiler = Profiler.get();
5195 this.server.spark.executeMainThreadTasks(); // Paper - spark
5296diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
53- index ef7e24716c2fc6a643d107cadcf743f80b39af41..45550619778b6a6b7f1f03467ece6bfe3d7b1e51 100644
97+ index 18eb79f76fb558a1ba9f989f59d2f273975be3a1..7a55657f9fb106dc3e95ef808d103a66cf2e56bd 100644
5498--- a/net/minecraft/server/level/ServerLevel.java
5599+++ b/net/minecraft/server/level/ServerLevel.java
56- @@ -1416,6 +1416,26 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
100+ @@ -1441,6 +1441,15 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
101+ public boolean mayInteract(final Entity entity, final BlockPos pos) {
57102 return !(entity instanceof Player player && (this.server.isUnderSpawnProtection(this, pos, player) || !this.getWorldBorder().isWithinBounds(pos)));
58103 }
59-
60104+ // Paper start - Incremental chunk and player saving
61- + public void saveIncrementally(boolean doFull) {
105+ + public void saveIncrementally(final boolean doFull) {
62106+ if (doFull) {
63107+ org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(this.getWorld()));
64- + }
65- +
66- + if (doFull) {
67108+ this.saveLevelData(false);
68109+ }
69110+ // chunk autosave is already called by the ChunkSystem during unload processing (ChunkMap#processUnloads)
70- + // Copied from save()
71- + // CraftBukkit start - moved from MinecraftServer.saveChunks
72- + if (doFull) { // Paper
73- + this.serverLevelData.setCustomBossEvents(this.server.getCustomBossEvents().save(this.registryAccess()));
74- + this.levelStorageAccess.saveDataTag(this.server.registryAccess(), this.serverLevelData, this.server.getPlayerList().getSingleplayerData());
75- + }
76- + // CraftBukkit end
77111+ }
78112+ // Paper end - Incremental chunk and player saving
79- +
80- public void save(@Nullable ProgressListener progress, boolean flush, boolean skipSave ) {
113+
114+ public void save(final @Nullable ProgressListener progressListener, final boolean flush, final boolean noSave ) {
81115 // Paper start - add close param
82- this.save(progress, flush, skipSave, false);
83116diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
84- index 1776f98636ca53a7cdbd160fbf6c22526fdb26a4..ea0853d09f17ee6dab3f063fd3abf10248d92ccd 100644
117+ index 41816ca8d4ef3d959d2b88cd4b2eedaaa541e612..82e87270d1ad89ad7aa56e028ced6b998ea0eca5 100644
85118--- a/net/minecraft/server/level/ServerPlayer.java
86119+++ b/net/minecraft/server/level/ServerPlayer.java
87- @@ -203 ,6 +203 ,7 @@ import org.slf4j.Logger;
120+ @@ -205 ,6 +205 ,7 @@ import org.slf4j.Logger;
88121
89122 public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patches.chunk_system.player.ChunkSystemServerPlayer { // Paper - rewrite chunk system
90123 private static final Logger LOGGER = LogUtils.getLogger();
@@ -93,39 +126,42 @@ index 1776f98636ca53a7cdbd160fbf6c22526fdb26a4..ea0853d09f17ee6dab3f063fd3abf102
93126 private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_Y = 10;
94127 private static final int FLY_STAT_RECORDING_SPEED = 25;
95128diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
96- index 38c30d98a200dd2a5c888cc080e9c77795f0e0c4..dec9dd8e42f90ccf7e5e3ad945e459d07159250d 100644
129+ index 0613b053f4a75c0884280011ee092d9d108b3857..b69bcaa1e27a4fbe9a9568f3c9e1843167abe1f5 100644
97130--- a/net/minecraft/server/players/PlayerList.java
98131+++ b/net/minecraft/server/players/PlayerList.java
99- @@ -412 ,6 +412 ,7 @@ public abstract class PlayerList {
132+ @@ -418 ,6 +418 ,7 @@ public abstract class PlayerList {
100133
101- protected void save(ServerPlayer player) {
134+ protected void save(final ServerPlayer player) {
102135 if (!player.getBukkitEntity().isPersistent()) return; // CraftBukkit
103136+ player.lastSave = MinecraftServer.currentTick; // Paper - Incremental chunk and player saving
104137 this.playerIo.save(player);
105- ServerStatsCounter serverStatsCounter = player.getStats(); // CraftBukkit
106- if (serverStatsCounter != null) {
107- @@ -941,9 +942,23 @@ public abstract class PlayerList {
138+ ServerStatsCounter stats = player.getStats(); // CraftBukkit
139+ if (stats != null) {
140+ @@ -951,10 +952,24 @@ public abstract class PlayerList {
108141 }
109142
110143 public void saveAll() {
111144+ // Paper start - Incremental chunk and player saving
112145+ this.saveAll(-1);
113146+ }
114- +
115147+ public void saveAll(final int interval) {
148+ + // Paper end - Incremental chunk and player saving
116149 io.papermc.paper.util.MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main
117- + int numSaved = 0;
118- + final long now = MinecraftServer.currentTick;
119- for (int i = 0; i < this.players.size(); i++) {
150+ - for (int i = 0; i < this.players.size(); i++) {
120151- this.save(this.players.get(i));
121- + final ServerPlayer player = this.players.get(i);
152+ - }
153+ + // Paper start - Incremental chunk and player saving
154+ + int numSaved = 0;
155+ + final long now = MinecraftServer.currentTick;
156+ + for (final ServerPlayer player : this.players) {
122157+ if (interval == -1 || now - player.lastSave >= interval) {
123158+ this.save(player);
124159+ if (interval != -1 && ++numSaved >= io.papermc.paper.configuration.GlobalConfiguration.get().playerAutoSave.maxPerTick()) {
125160+ break;
126161+ }
127162+ }
128- + // Paper end - Incremental chunk and player saving
129- }
163+ + }
164+ + // Paper end - Incremental chunk and player saving
130165 return null; }); // Paper - ensure main
131166 }
167+
0 commit comments