Paper/patches/server/0982-incremental-chunk-and-player-saving.patch
Jake Potrebic 3e90a19183
Updated Upstream (Bukkit/CraftBukkit)
Upstream has released updates that appear to apply and compile correctly.
This update has not been tested by PaperMC and as with ANY update, please do your own testing

Bukkit Changes:
304e83eb PR-1002: Improve documentation and implementation of getMaxStackSize
e8215ea2 SPIGOT-7638: Library loader does not seem to resolve every dependency
79c595c0 SPIGOT-7637: Bad logic in checking nullability of AttributeModifier slots

CraftBukkit Changes:
91b1fc3f1 SPIGOT-7644: Fix ItemMeta#getAsString
4e77a81e1 SPIGOT-7615: PlayerLeashEntityEvent cancelled eats lead
996f660f3 Do not remove leash knot if leasing to an existing leash knot gets cancelled
f70367d42 SPIGOT-7643: Fix inverted leash event cancelled usage and remove leash knot if no entity gets leashed
7ddb48294 SPIGOT-7640: Abnormal jumping height of wind charge
080c8711e SPIGOT-7639: Incoming plugin channels not working
ad549847e Open a direct connection instead of pinging mojang server to check if it is reachable
38e2926c5 SPIGOT-7365: DamageCause blocked by shield should trigger invulnerableTime
2024-04-27 18:00:01 -07:00

168 lines
8.6 KiB
Diff

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 7d33a4638660aaa55b2ef114efd6d618312b61c9..8607652b274fb8f6eca5f3fb7183925da3c710cf 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -916,7 +916,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;
@@ -1448,16 +1448,28 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
}
--this.ticksUntilAutosave;
- // CraftBukkit start
- if (this.autosavePeriod > 0 && this.ticksUntilAutosave <= 0) {
- this.ticksUntilAutosave = this.autosavePeriod;
- // CraftBukkit end
- MinecraftServer.LOGGER.debug("Autosave started");
- this.profiler.push("save");
- this.saveEverything(true, false, false);
- this.profiler.pop();
- MinecraftServer.LOGGER.debug("Autosave finished");
+ // Paper start - Incremental chunk and player saving
+ int playerSaveInterval = io.papermc.paper.configuration.GlobalConfiguration.get().playerAutoSave.rate;
+ if (playerSaveInterval < 0) {
+ playerSaveInterval = autosavePeriod;
}
+ this.profiler.push("save");
+ final boolean fullSave = autosavePeriod > 0 && this.tickCount % autosavePeriod == 0;
+ try {
+ this.isSaving = true;
+ if (playerSaveInterval > 0) {
+ this.playerList.saveAll(playerSaveInterval);
+ }
+ for (ServerLevel level : this.getAllLevels()) {
+ if (level.paperConfig().chunks.autoSaveInterval.value() > 0) {
+ level.saveIncrementally(fullSave);
+ }
+ }
+ } finally {
+ this.isSaving = false;
+ }
+ this.profiler.pop();
+ // Paper end - Incremental chunk and player saving
io.papermc.paper.util.CachedLists.reset(); // Paper
// Paper start - move executeAll() into full server tick timing
try (co.aikar.timings.Timing ignored = MinecraftTimings.processTasksTimer.startTiming()) {
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
index f74efe41cd0da2f9749fc96fb9e0f7cf237ad1c6..d1728e13a7b649f308bde90ab633c79d86c10822 100644
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
@@ -430,6 +430,15 @@ public class ServerChunkCache extends ChunkSource {
} // Paper - Timings
}
+ // Paper start - Incremental chunk and player saving; duplicate save, but call incremental
+ public void saveIncrementally() {
+ this.runDistanceManagerUpdates();
+ try (co.aikar.timings.Timing timed = level.timings.chunkSaveData.startTiming()) { // Paper - Timings
+ this.chunkMap.saveIncrementally();
+ } // Paper - Timings
+ }
+ // Paper end - Incremental chunk and player saving
+
@Override
public void close() throws IOException {
// CraftBukkit start
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index 60fd84819ea7aa96f351db743e8667334af9e96b..afc1639c96c01197c6c11873fcd5d779e4ed93a9 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -1296,6 +1296,37 @@ public class ServerLevel extends Level implements WorldGenLevel {
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()));
+ }
+
+ try (co.aikar.timings.Timing ignored = this.timings.worldSave.startTiming()) {
+ if (doFull) {
+ this.saveLevelData();
+ }
+
+ this.timings.worldSaveChunks.startTiming(); // Paper
+ if (!this.noSave()) chunkproviderserver.saveIncrementally();
+ this.timings.worldSaveChunks.stopTiming(); // Paper
+
+ // 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 - rewrite chunk system - 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 c7290763e546252f511ff849f5da3b47283ec24a..305d88c8bfb0d9864f132be7b0e8fd2f4d18a539 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -199,6 +199,7 @@ import org.bukkit.inventory.MainHand;
public class ServerPlayer extends Player {
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 c4b4e5f5c9366b241686e881cda34568a57b4877..57164b266d23715c224a85660531220477d4dda8 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -575,6 +575,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
@@ -1227,10 +1228,22 @@ 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
MinecraftTimings.savePlayers.startTiming(); // Paper
+ int numSaved = 0;
+ long now = MinecraftServer.currentTick;
for (int i = 0; i < this.players.size(); ++i) {
- this.save(this.players.get(i));
+ ServerPlayer entityplayer = this.players.get(i);
+ if (interval == -1 || now - entityplayer.lastSave >= interval) {
+ this.save(entityplayer);
+ if (interval != -1 && ++numSaved >= io.papermc.paper.configuration.GlobalConfiguration.get().playerAutoSave.maxPerTick()) { break; }
+ }
+ // Paper end - Incremental chunk and player saving
}
MinecraftTimings.savePlayers.stopTiming(); // Paper
return null; }); // Paper - ensure main