f8fd607e04
Upstream has released updates that appears 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: bbfd13dd Hyperlink 'Events' in raid event package documentation b2095bed SPIGOT-5413: Add TrustedPlayer API for foxes 1bf1f3f4 Block trace methods do not require hash sets abf0cfdc Javadoc improvements per checkstyle c4a2b425 Add TimeSkipEvent CraftBukkit Changes: 817116de SPIGOT-5413: Add TrustedPlayer API for foxes 062680a8 SPIGOT-5467: Calm down bees that cannot exit hive 75fac431 SPIGOT-5472: Spurious warning when using clone command on tile entities 85106731 SPIGOT-5471: Allow empty title/author for books 2d9db47f Add TimeSkipEvent 384225c2 Add thread name to TerminalConsoleWriterThread Spigot Changes: 05bb8bcf Postpone stopping the watchdog until the server is completely stopped 18e2b9be Add package-info.java for Spigot APIs
211 lines
9.6 KiB
Diff
211 lines
9.6 KiB
Diff
From 4688cfc998f599ddb723bf1a06d90cafacc4e2a5 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 saving
|
|
|
|
|
|
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
|
index 778de4630..99f1541b9 100644
|
|
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
|
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
|
@@ -485,4 +485,19 @@ public class PaperWorldConfig {
|
|
keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16);
|
|
log( "Keep Spawn Loaded Range: " + (keepLoadedRange/16));
|
|
}
|
|
+
|
|
+ public int autoSavePeriod = -1;
|
|
+ private void autoSavePeriod() {
|
|
+ autoSavePeriod = getInt("auto-save-interval", -1);
|
|
+ if (autoSavePeriod > 0) {
|
|
+ log("Auto Save Interval: " +autoSavePeriod + " (" + (autoSavePeriod / 20) + "s)");
|
|
+ } else if (autoSavePeriod < 0) {
|
|
+ autoSavePeriod = net.minecraft.server.MinecraftServer.getServer().autosavePeriod;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public int maxAutoSaveChunksPerTick = 24;
|
|
+ private void maxAutoSaveChunksPerTick() {
|
|
+ maxAutoSaveChunksPerTick = getInt("max-auto-save-chunks-per-tick", 24);
|
|
+ }
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java
|
|
index 64c327669..14ec31f0a 100644
|
|
--- a/src/main/java/net/minecraft/server/Chunk.java
|
|
+++ b/src/main/java/net/minecraft/server/Chunk.java
|
|
@@ -42,7 +42,7 @@ public class Chunk implements IChunkAccess {
|
|
private TickList<Block> o;
|
|
private TickList<FluidType> p;
|
|
private boolean q;
|
|
- private long lastSaved;
|
|
+ public long lastSaved; // Paper
|
|
private volatile boolean s;
|
|
private long inhabitedTime;
|
|
@Nullable
|
|
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
|
index 9b2bafdbd..f138b112f 100644
|
|
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
|
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
|
@@ -335,6 +335,15 @@ public class ChunkProviderServer extends IChunkProvider {
|
|
} // Paper - Timings
|
|
}
|
|
|
|
+ // Paper start - duplicate save, but call incremental
|
|
+ public void saveIncrementally() {
|
|
+ this.tickDistanceManager();
|
|
+ try (co.aikar.timings.Timing timed = world.timings.chunkSaveData.startTiming()) { // Paper - Timings
|
|
+ this.playerChunkMap.saveIncrementally();
|
|
+ } // Paper - Timings
|
|
+ }
|
|
+ // Paper end
|
|
+
|
|
@Override
|
|
public void close() throws IOException {
|
|
// CraftBukkit start
|
|
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
|
index 105ac1358..4eba20b6a 100644
|
|
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
|
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
|
@@ -168,6 +168,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
|
|
public static int currentTick = 0; // Paper - Further improve tick loop
|
|
public java.util.Queue<Runnable> processQueue = new java.util.concurrent.ConcurrentLinkedQueue<Runnable>();
|
|
public int autosavePeriod;
|
|
+ public boolean serverAutoSave = false; // Paper
|
|
public File bukkitDataPackFolder;
|
|
public CommandDispatcher vanillaCommandDispatcher;
|
|
private boolean forceTicks;
|
|
@@ -1116,14 +1117,28 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
|
|
this.serverPing.b().a(agameprofile);
|
|
}
|
|
|
|
- if (autosavePeriod > 0 && this.ticks % autosavePeriod == 0) { // CraftBukkit
|
|
- MinecraftServer.LOGGER.debug("Autosave started");
|
|
+ //if (autosavePeriod > 0 && this.ticks % autosavePeriod == 0) { // CraftBukkit // Paper - move down
|
|
+ //MinecraftServer.LOGGER.debug("Autosave started"); // Paper
|
|
+ serverAutoSave = (autosavePeriod > 0 && this.ticks % autosavePeriod == 0); // Paper
|
|
this.methodProfiler.enter("save");
|
|
+ if (autosavePeriod > 0 && this.ticks % autosavePeriod == 0) { // Paper
|
|
this.playerList.savePlayers();
|
|
- this.saveChunks(true, false, false);
|
|
+ }// Paper
|
|
+ // Paper start
|
|
+ for (WorldServer world : getWorlds()) {
|
|
+ if (world.paperConfig.autoSavePeriod > 0) {
|
|
+ try {
|
|
+ world.saveIncrementally(serverAutoSave);
|
|
+ } catch (ExceptionWorldConflict exceptionWorldConflict) {
|
|
+ MinecraftServer.LOGGER.warn(exceptionWorldConflict.getMessage());
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ // Paper end
|
|
+
|
|
this.methodProfiler.exit();
|
|
- MinecraftServer.LOGGER.debug("Autosave finished");
|
|
- }
|
|
+ //MinecraftServer.LOGGER.debug("Autosave finished"); // Paper
|
|
+ //} // Paper
|
|
|
|
this.methodProfiler.enter("snooper");
|
|
if (((DedicatedServer) this).getDedicatedServerProperties().snooperEnabled && !this.snooper.d() && this.ticks > 100) { // Spigot
|
|
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
|
index dfbac1b3b..4acb03c9e 100644
|
|
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
|
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
|
@@ -302,6 +302,36 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
|
|
|
}
|
|
|
|
+ // Paper start - derived from below
|
|
+ protected void saveIncrementally() {
|
|
+ int savedThisTick = 0;
|
|
+ for (PlayerChunk playerchunk : visibleChunks.values()) {
|
|
+ if (playerchunk.hasBeenLoaded()) {
|
|
+
|
|
+ IChunkAccess ichunkaccess = (IChunkAccess) playerchunk.getChunkSave().getNow(null); // CraftBukkit - decompile error
|
|
+
|
|
+
|
|
+ if (ichunkaccess instanceof ProtoChunkExtension || ichunkaccess instanceof Chunk) {
|
|
+ boolean shouldSave = true;
|
|
+
|
|
+ if (ichunkaccess instanceof Chunk) {
|
|
+ shouldSave = ((Chunk) ichunkaccess).lastSaved + world.paperConfig.autoSavePeriod <= world.getTime();
|
|
+ }
|
|
+
|
|
+ if (shouldSave && this.saveChunk(ichunkaccess)) {
|
|
+ ++savedThisTick;
|
|
+ playerchunk.m();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (savedThisTick >= world.paperConfig.maxAutoSaveChunksPerTick) {
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ // paper end
|
|
+
|
|
protected void save(boolean flag) {
|
|
if (flag) {
|
|
List<PlayerChunk> list = (List) this.visibleChunks.values().stream().filter(PlayerChunk::hasBeenLoaded).peek(PlayerChunk::m).collect(Collectors.toList());
|
|
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
|
|
index 8b3ea6544..2b42f3262 100644
|
|
--- a/src/main/java/net/minecraft/server/WorldServer.java
|
|
+++ b/src/main/java/net/minecraft/server/WorldServer.java
|
|
@@ -800,11 +800,44 @@ public class WorldServer extends World {
|
|
return this.worldProvider.c();
|
|
}
|
|
|
|
+ // Paper start - derived from below
|
|
+ public void saveIncrementally(boolean doFull) throws ExceptionWorldConflict {
|
|
+ ChunkProviderServer chunkproviderserver = this.getChunkProvider();
|
|
+
|
|
+ if (doFull) {
|
|
+ org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld()));
|
|
+ }
|
|
+
|
|
+ try (co.aikar.timings.Timing ignored = timings.worldSave.startTiming()) {
|
|
+ if (doFull) {
|
|
+ this.saveData();
|
|
+ }
|
|
+
|
|
+ timings.worldSaveChunks.startTiming(); // Paper
|
|
+ if (!this.isSavingDisabled()) chunkproviderserver.saveIncrementally();
|
|
+ timings.worldSaveChunks.stopTiming(); // Paper
|
|
+
|
|
+
|
|
+ // CraftBukkit start - moved from MinecraftServer.saveChunks
|
|
+ // PAIL - rename
|
|
+ if (doFull) {
|
|
+ WorldServer worldserver1 = this;
|
|
+ WorldData worlddata = worldserver1.getWorldData();
|
|
+
|
|
+ worldserver1.getWorldBorder().save(worlddata);
|
|
+ worlddata.setCustomBossEvents(this.server.getBossBattleCustomData().save());
|
|
+ worldserver1.getDataManager().saveWorldData(worlddata, this.server.getPlayerList().save());
|
|
+ // CraftBukkit end
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ // Paper end
|
|
+
|
|
public void save(@Nullable IProgressUpdate iprogressupdate, boolean flag, boolean flag1) throws ExceptionWorldConflict {
|
|
ChunkProviderServer chunkproviderserver = this.getChunkProvider();
|
|
|
|
if (!flag1) {
|
|
- org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld())); // CraftBukkit
|
|
+ if (flag) org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld())); // CraftBukkit
|
|
try (co.aikar.timings.Timing ignored = timings.worldSave.startTiming()) { // Paper
|
|
if (iprogressupdate != null) {
|
|
iprogressupdate.a(new ChatMessage("menu.savingLevel", new Object[0]));
|
|
@@ -831,6 +864,7 @@ public class WorldServer extends World {
|
|
// CraftBukkit end
|
|
}
|
|
|
|
+ protected void saveData() throws ExceptionWorldConflict { this.m_(); } // Paper - OBFHELPER
|
|
protected void m_() throws ExceptionWorldConflict {
|
|
this.checkSession();
|
|
this.worldProvider.i();
|
|
--
|
|
2.24.1
|
|
|