Paper/patches/server/0500-Incremental-player-saving.patch

127 lines
7.0 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Sun, 9 Aug 2020 08:59:25 +0300
Subject: [PATCH] Incremental player saving
diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java
index 9a66cddbf9863aa6ff566a337153883c07c08e41..b6c7aec1516a4db4fde8c9ec2772cd982ed5e304 100644
--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java
@@ -468,4 +468,15 @@ public class PaperConfig {
config.set("settings.unsupported-settings.allow-headless-pistons-readme", "This setting controls if players should be able to create headless pistons.");
allowHeadlessPistons = getBoolean("settings.unsupported-settings.allow-headless-pistons", false);
}
+
+ public static int playerAutoSaveRate = -1;
+ public static int maxPlayerAutoSavePerTick = 10;
+ private static void playerAutoSaveRate() {
+ playerAutoSaveRate = getInt("settings.player-auto-save-rate", -1);
+ maxPlayerAutoSavePerTick = getInt("settings.max-player-auto-save-per-tick", -1);
+ if (maxPlayerAutoSavePerTick == -1) { // -1 Automatic / "Recommended"
+ // 10 should be safe for everyone unless you mass spamming player auto save
+ maxPlayerAutoSavePerTick = (playerAutoSaveRate == -1 || playerAutoSaveRate > 100) ? 10 : 20;
+ }
+ }
}
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 4351dd9c293d1db48c87c5df28bcb2b9a59583f7..7f733bd666e42f8ba80bfda233f662564bfc0e24 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -896,12 +896,17 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
return flag3;
}
+ // Paper start
public boolean saveEverything(boolean suppressLogs, boolean flush, boolean force) {
+ return saveEverything(suppressLogs, flush, force, -1);
+ }
+ public boolean saveEverything(boolean suppressLogs, boolean flush, boolean force, int playerSaveInterval) {
+ // Paper end
boolean flag3;
try {
this.isSaving = true;
- this.getPlayerList().saveAll();
+ this.getPlayerList().saveAll(playerSaveInterval); // Paper
flag3 = this.saveAllChunks(suppressLogs, flush, force);
} finally {
this.isSaving = false;
@@ -963,7 +968,6 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.isSaving = true;
if (this.playerList != null) {
MinecraftServer.LOGGER.info("Saving players");
- this.playerList.saveAll();
this.playerList.removeAll(this.isRestarting); // Paper
try { Thread.sleep(100); } catch (InterruptedException ex) {} // CraftBukkit - SPIGOT-625 - give server at least a chance to send packets
}
@@ -1408,13 +1412,19 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
}
}
+ // Paper start
+ int playerSaveInterval = com.destroystokyo.paper.PaperConfig.playerAutoSaveRate;
+ if (playerSaveInterval < 0) {
+ playerSaveInterval = autosavePeriod;
+ }
+ // Paper end
if (this.autosavePeriod > 0 && this.tickCount % this.autosavePeriod == 0) { // CraftBukkit
MinecraftServer.LOGGER.debug("Autosave started");
this.profiler.push("save");
- this.saveEverything(true, false, false);
+ this.saveEverything(true, false, false, playerSaveInterval); // Paper
this.profiler.pop();
MinecraftServer.LOGGER.debug("Autosave finished");
- }
+ } else this.getPlayerList().saveAll(playerSaveInterval); // Paper
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/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
index 84f78e2b3bf51eae1d486852464df032861c5a0b..968b8180f92066a43f06bff8dd1d49b03bd08f5b 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -171,6 +171,7 @@ public class ServerPlayer extends Player {
public final int getViewDistance() { return this.getLevel().getChunkSource().chunkMap.viewDistance - 1; } // Paper - placeholder
private static final Logger LOGGER = LogManager.getLogger();
+ public long lastSave = MinecraftServer.currentTick; // Paper
private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_XZ = 32;
private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_Y = 10;
public ServerGamePacketListenerImpl connection;
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index 310bed27c04ef812aa8607c9dca789db13341d25..b1f93551ce3e4d12e5cbe424c1ceaf3da20d0ffd 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -569,6 +569,7 @@ public abstract class PlayerList {
protected void save(ServerPlayer player) {
if (!player.getBukkitEntity().isPersistent()) return; // CraftBukkit
if (!player.didPlayerJoinEvent) return; // Paper - If we never fired PJE, we disconnected during login. Data has not changed, and additionally, our saved vehicle is not loaded! If we save now, we will lose our vehicle (CraftBukkit bug)
+ player.lastSave = MinecraftServer.currentTick; // Paper
this.playerIo.save(player);
ServerStatsCounter serverstatisticmanager = (ServerStatsCounter) player.getStats(); // CraftBukkit
@@ -1181,10 +1182,21 @@ public abstract class PlayerList {
}
public void saveAll() {
+ // Paper start - incremental player saving
+ saveAll(-1);
+ }
+ public void saveAll(int interval) {
net.minecraft.server.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 <= com.destroystokyo.paper.PaperConfig.maxPlayerAutoSavePerTick) { break; }
+ }
+ // Paper end
}
MinecraftTimings.savePlayers.stopTiming(); // Paper
return null; }); // Paper - ensure main