7141632abf
While Velocity supports BungeeCord-style IP forwarding, it is not secure. Users have a lot of problems setting up firewalls or setting up plugins like IPWhitelist. Further, the BungeeCord IP forwarding protocol still retains essentially its original form, when there is brand new support for custom login plugin messages in 1.13. Velocity's modern IP forwarding uses an HMAC-SHA256 code to ensure authenticity of messages, is packed into a binary format that is smaller than BungeeCord's forwarding, and is integrated into the Minecraft login process by using the 1.13 login plugin message packet.
234 lines
12 KiB
Diff
234 lines
12 KiB
Diff
From f397718c1bd2ed68e1dca5603ca882a4b087b7a9 Mon Sep 17 00:00:00 2001
|
|
From: Aikar <aikar@aikar.co>
|
|
Date: Mon, 19 Sep 2016 23:16:39 -0400
|
|
Subject: [PATCH] Auto Save Improvements
|
|
|
|
Makes Auto Save Rate setting configurable per-world. If the auto save rate is left -1, the global bukkit.yml value will be used.
|
|
|
|
Process auto save every tick instead of once per auto tick interval, so that chunk saves will distribute over many ticks instead of all at once.
|
|
|
|
Re-introduce a cap per tick for auto save (Spigot disabled the vanilla cap) and make it configurable.
|
|
|
|
Adds incremental player auto saving too
|
|
|
|
diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
|
index c278ac98d..ae3d0f8f7 100644
|
|
--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
|
+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
|
@@ -269,4 +269,15 @@ public class PaperConfig {
|
|
flyingKickPlayerMessage = getString("messages.kick.flying-player", flyingKickPlayerMessage);
|
|
flyingKickVehicleMessage = getString("messages.kick.flying-vehicle", flyingKickVehicleMessage);
|
|
}
|
|
+
|
|
+ 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 your mass spamming player auto save
|
|
+ maxPlayerAutoSavePerTick = (playerAutoSaveRate == -1 || playerAutoSaveRate > 100) ? 10 : 20;
|
|
+ }
|
|
+ }
|
|
}
|
|
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
|
index 0cd15c17e..c43152f45 100644
|
|
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
|
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
|
@@ -2,6 +2,7 @@ package com.destroystokyo.paper;
|
|
|
|
import java.util.List;
|
|
|
|
+import net.minecraft.server.MinecraftServer;
|
|
import org.bukkit.configuration.file.YamlConfiguration;
|
|
import org.spigotmc.SpigotWorldConfig;
|
|
|
|
@@ -310,4 +311,19 @@ public class PaperWorldConfig {
|
|
private void skipEntityTickingInChunksScheduledForUnload() {
|
|
skipEntityTickingInChunksScheduledForUnload = getBoolean("skip-entity-ticking-in-chunks-scheduled-for-unload", skipEntityTickingInChunksScheduledForUnload);
|
|
}
|
|
+
|
|
+ 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 = 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 7e371c278..a79b0b59d 100644
|
|
--- a/src/main/java/net/minecraft/server/Chunk.java
|
|
+++ b/src/main/java/net/minecraft/server/Chunk.java
|
|
@@ -50,9 +50,9 @@ public class Chunk implements IChunkAccess {
|
|
private final TickList<Block> s;
|
|
private final TickList<FluidType> t;
|
|
private boolean u;
|
|
- private boolean v;
|
|
+ private boolean v;public boolean hasEntities() { return v; } // Paper - OBFHELPER
|
|
private long lastSaved;
|
|
- private boolean x;
|
|
+ private boolean x; public boolean isModified() { return x; } // Paper - OBFHELPER
|
|
private int y;
|
|
private long z;
|
|
private int A;
|
|
@@ -1058,11 +1058,11 @@ public class Chunk implements IChunkAccess {
|
|
if (this.v && this.world.getTime() != this.lastSaved || this.x) {
|
|
return true;
|
|
}
|
|
- } else if (this.v && this.world.getTime() >= this.lastSaved + MinecraftServer.getServer().autosavePeriod * 4) { // Spigot - Only save if we've passed 2 auto save intervals without modification
|
|
- return true;
|
|
}
|
|
-
|
|
- return this.x;
|
|
+ // Paper start - Make world configurable and incremental
|
|
+ // This !flag section should say if isModified or hasEntities, then check auto save
|
|
+ return ((isModified() || hasEntities()) && this.world.getTime() >= this.lastSaved + world.paperConfig.autoSavePeriod);
|
|
+ // Paper end
|
|
}
|
|
|
|
public boolean isEmpty() {
|
|
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
|
index 719d5deb2..69219b13a 100644
|
|
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
|
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
|
@@ -241,7 +241,7 @@ public class ChunkProviderServer implements IChunkProvider {
|
|
this.saveChunk(chunk, false); // Spigot
|
|
chunk.a(false);
|
|
++i;
|
|
- if (i == 24 && !flag && false) { // Spigot
|
|
+ if (!flag && i >= world.paperConfig.maxAutoSaveChunksPerTick) { // Spigot - // Paper - Incremental Auto Save - cap max
|
|
return false;
|
|
}
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java
|
|
index 3d8390029..690cff882 100644
|
|
--- a/src/main/java/net/minecraft/server/EntityPlayer.java
|
|
+++ b/src/main/java/net/minecraft/server/EntityPlayer.java
|
|
@@ -37,6 +37,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
|
|
|
|
private static final Logger cc = LogManager.getLogger();
|
|
public String locale = null; // CraftBukkit - lowercase // Paper - default to null
|
|
+ public long lastSave = MinecraftServer.currentTick; // Paper
|
|
public PlayerConnection playerConnection;
|
|
public final MinecraftServer server;
|
|
public final PlayerInteractManager playerInteractManager;
|
|
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
|
index 04d8c108b..a547ee5ca 100644
|
|
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
|
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
|
@@ -148,6 +148,7 @@ public abstract class MinecraftServer implements IAsyncTaskHandler, IMojangStati
|
|
public org.bukkit.command.RemoteConsoleCommandSender remoteConsole;
|
|
public ConsoleReader reader;
|
|
public static int currentTick = 0; // Paper - Further improve tick loop
|
|
+ public boolean serverAutoSave = false; // Paper
|
|
public final Thread primaryThread;
|
|
public java.util.Queue<Runnable> processQueue = new java.util.concurrent.ConcurrentLinkedQueue<Runnable>();
|
|
public int autosavePeriod;
|
|
@@ -942,22 +943,30 @@ public abstract class MinecraftServer implements IAsyncTaskHandler, IMojangStati
|
|
this.m.b().a(agameprofile);
|
|
}
|
|
|
|
- if (autosavePeriod > 0 && this.ticks % autosavePeriod == 0) { // CraftBukkit
|
|
this.methodProfiler.a("save");
|
|
- this.s.savePlayers();
|
|
+
|
|
+ serverAutoSave = (autosavePeriod > 0 && this.ticks % autosavePeriod == 0); // Paper
|
|
+ int playerSaveInterval = com.destroystokyo.paper.PaperConfig.playerAutoSaveRate;
|
|
+ if (playerSaveInterval < 0) {
|
|
+ playerSaveInterval = autosavePeriod;
|
|
+ }
|
|
+ if (playerSaveInterval > 0) { // CraftBukkit // Paper
|
|
+ this.s.savePlayers(playerSaveInterval);
|
|
// Spigot Start
|
|
+ } // Paper - Incremental Auto Saving
|
|
+
|
|
// We replace this with saving each individual world as this.saveChunks(...) is broken,
|
|
// and causes the main thread to sleep for random amounts of time depending on chunk activity
|
|
// Also pass flag to only save modified chunks
|
|
server.playerCommandState = true;
|
|
for (World world : getWorlds()) {
|
|
- world.getWorld().save(false);
|
|
+ if (world.paperConfig.autoSavePeriod > 0) world.getWorld().save(false); // Paper - Incremental / Configurable Auto Saving
|
|
}
|
|
server.playerCommandState = false;
|
|
// this.saveChunks(true);
|
|
// Spigot End
|
|
this.methodProfiler.e();
|
|
- }
|
|
+ //} // Paper - Incremental Auto Saving
|
|
|
|
this.methodProfiler.a("snooper");
|
|
if (getSnooperEnabled() && !this.i.d() && this.ticks > 100) { // Spigot
|
|
diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java
|
|
index baf870ac2..7d778ff3e 100644
|
|
--- a/src/main/java/net/minecraft/server/PlayerList.java
|
|
+++ b/src/main/java/net/minecraft/server/PlayerList.java
|
|
@@ -342,6 +342,7 @@ public abstract class PlayerList {
|
|
|
|
protected void savePlayerFile(EntityPlayer entityplayer) {
|
|
if (!entityplayer.getBukkitEntity().isPersistent()) return; // CraftBukkit
|
|
+ entityplayer.lastSave = MinecraftServer.currentTick; // Paper
|
|
this.playerFileData.save(entityplayer);
|
|
ServerStatisticManager serverstatisticmanager = (ServerStatisticManager) entityplayer.getStatisticManager(); // CraftBukkit
|
|
|
|
@@ -1208,13 +1209,25 @@ public abstract class PlayerList {
|
|
|
|
}
|
|
|
|
+ // Paper start
|
|
public void savePlayers() {
|
|
+ savePlayers(null);
|
|
+ }
|
|
+
|
|
+ public void savePlayers(Integer interval) {
|
|
+ long now = MinecraftServer.currentTick;
|
|
MinecraftTimings.savePlayers.startTiming(); // Paper
|
|
+ int numSaved = 0; // Paper
|
|
for (int i = 0; i < this.players.size(); ++i) {
|
|
- this.savePlayerFile((EntityPlayer) this.players.get(i));
|
|
+ EntityPlayer entityplayer = this.players.get(i);
|
|
+ if (interval == null || now - entityplayer.lastSave >= interval) {
|
|
+ this.savePlayerFile(entityplayer);
|
|
+ if (interval != null && ++numSaved <= com.destroystokyo.paper.PaperConfig.maxPlayerAutoSavePerTick) { break; } // Paper
|
|
+ }
|
|
}
|
|
MinecraftTimings.savePlayers.stopTiming(); // Paper
|
|
}
|
|
+ // Paper end
|
|
|
|
public WhiteList getWhitelist() {
|
|
return this.whitelist;
|
|
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
|
|
index c5201697d..ca2e027cd 100644
|
|
--- a/src/main/java/net/minecraft/server/WorldServer.java
|
|
+++ b/src/main/java/net/minecraft/server/WorldServer.java
|
|
@@ -872,8 +872,9 @@ public class WorldServer extends World implements IAsyncTaskHandler {
|
|
ChunkProviderServer chunkproviderserver = this.getChunkProviderServer();
|
|
|
|
if (chunkproviderserver.d()) {
|
|
- 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 // Paper - Incremental Auto Saving - Only fire event on full save
|
|
timings.worldSave.startTiming(); // Paper
|
|
+ if (flag || server.serverAutoSave) { // Paper
|
|
if (iprogressupdate != null) {
|
|
iprogressupdate.a(new ChatMessage("menu.savingLevel", new Object[0]));
|
|
}
|
|
@@ -882,6 +883,7 @@ public class WorldServer extends World implements IAsyncTaskHandler {
|
|
if (iprogressupdate != null) {
|
|
iprogressupdate.c(new ChatMessage("menu.savingChunks", new Object[0]));
|
|
}
|
|
+ } // Paper
|
|
|
|
timings.worldSaveChunks.startTiming(); // Paper
|
|
chunkproviderserver.a(flag);
|
|
--
|
|
2.19.1
|
|
|