mirror of
https://github.com/YatopiaMC/Yatopia.git
synced 2024-11-05 10:23:15 +01:00
5f55124016
This update had major internal changes, which took us 8 hours to figure out and resolve all things untill we have a successful build. YatopiaMC members wish you happy playing using Yatopia for your server software MAKE A BACKUP OF YOUR WORLD BEFORE RUNNING IT ON YOUR SERVER. YOU HAVE BEEN WARNED. People have reported to paper that after upgrading villagers are gone. There could be even more issues we are unknown of. MAKE A BACKUP OF YOUR WORLD BEFORE RUNNING IT ON YOUR SERVER. YOU HAVE BEEN WARNED. Co-authored-by: Ovydux <68059159+Ovydux@users.noreply.github.com> Co-authored-by: Simon Gardling <Titaniumtown@gmail.com> Co-authored-by: budgidiere <sgidiere@gmail.com>
211 lines
10 KiB
Diff
211 lines
10 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: tr7zw <tr7zw@live.de>
|
|
Date: Fri, 31 Jul 2020 22:39:45 -0500
|
|
Subject: [PATCH] Player-saving-async-FileIO
|
|
|
|
|
|
diff --git a/src/main/java/net/minecraft/server/AdvancementDataPlayer.java b/src/main/java/net/minecraft/server/AdvancementDataPlayer.java
|
|
index cf539c98073b475eb5b769c8cc11d48a7e6d58f1..b19c702bae3e750bee13c8b1b3eaa62f0d3ba1ae 100644
|
|
--- a/src/main/java/net/minecraft/server/AdvancementDataPlayer.java
|
|
+++ b/src/main/java/net/minecraft/server/AdvancementDataPlayer.java
|
|
@@ -50,6 +50,7 @@ public class AdvancementDataPlayer {
|
|
@Nullable
|
|
private Advancement l;
|
|
private boolean m = true;
|
|
+ public static java.util.concurrent.ExecutorService saveThread = java.util.concurrent.Executors.newSingleThreadExecutor(); // Yatopia
|
|
|
|
// Paper start - fix advancement data player leakage
|
|
final Map<CriterionTriggerAbstract, Set<CriterionTrigger.a>> criterionData = Maps.newIdentityHashMap();
|
|
@@ -228,6 +229,15 @@ public class AdvancementDataPlayer {
|
|
|
|
jsonelement.getAsJsonObject().addProperty("DataVersion", SharedConstants.getGameVersion().getWorldVersion());
|
|
|
|
+ // Yatopia start - replace whole logic
|
|
+ saveThread.submit(() -> {
|
|
+ try (OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(f), Charsets.UTF_8.newEncoder())) {
|
|
+ AdvancementDataPlayer.b.toJson(jsonelement, writer);
|
|
+ } catch (Throwable e) {
|
|
+ AdvancementDataPlayer.LOGGER.error("Couldn't save player advancements to {}", this.f, e);
|
|
+ }
|
|
+ });
|
|
+ /*
|
|
try {
|
|
FileOutputStream fileoutputstream = new FileOutputStream(this.f);
|
|
Throwable throwable = null;
|
|
@@ -275,7 +285,7 @@ public class AdvancementDataPlayer {
|
|
} catch (IOException ioexception) {
|
|
AdvancementDataPlayer.LOGGER.error("Couldn't save player advancements to {}", this.f, ioexception);
|
|
}
|
|
-
|
|
+ */ // Yatopia end
|
|
}
|
|
|
|
public boolean grantCriteria(Advancement advancement, String s) {
|
|
diff --git a/src/main/java/net/minecraft/server/EntityHuman.java b/src/main/java/net/minecraft/server/EntityHuman.java
|
|
index ce4ebc96c01f3dacf4e4d0569d86f52140440d43..a52c0391b171c8a57de75f87c534ce1e0e78c44a 100644
|
|
--- a/src/main/java/net/minecraft/server/EntityHuman.java
|
|
+++ b/src/main/java/net/minecraft/server/EntityHuman.java
|
|
@@ -700,11 +700,20 @@ public abstract class EntityHuman extends EntityLiving {
|
|
|
|
}
|
|
|
|
+ // Yatopia start
|
|
+ private NBTTagList inventorySnapshot = null;
|
|
+ private NBTTagList enderchestSnapshot = null;
|
|
+ public void takeSnapshot() {
|
|
+ inventorySnapshot = this.inventory.a(new NBTTagList());
|
|
+ enderchestSnapshot = this.enderChest.g();
|
|
+ }
|
|
+ // Yatopia end
|
|
+
|
|
@Override
|
|
public void saveData(NBTTagCompound nbttagcompound) {
|
|
super.saveData(nbttagcompound);
|
|
nbttagcompound.setInt("DataVersion", SharedConstants.getGameVersion().getWorldVersion());
|
|
- nbttagcompound.set("Inventory", this.inventory.a(new NBTTagList()));
|
|
+ nbttagcompound.set("Inventory", inventorySnapshot != null ? inventorySnapshot : this.inventory.a(new NBTTagList())); inventorySnapshot = null; // Yatopia
|
|
nbttagcompound.setInt("SelectedItemSlot", this.inventory.itemInHandIndex);
|
|
nbttagcompound.setShort("SleepTimer", (short) this.sleepTicks);
|
|
nbttagcompound.setFloat("XpP", this.exp);
|
|
@@ -714,7 +723,7 @@ public abstract class EntityHuman extends EntityLiving {
|
|
nbttagcompound.setInt("Score", this.getScore());
|
|
this.foodData.b(nbttagcompound);
|
|
this.abilities.a(nbttagcompound);
|
|
- nbttagcompound.set("EnderItems", this.enderChest.g());
|
|
+ nbttagcompound.set("EnderItems", enderchestSnapshot != null ? enderchestSnapshot : this.enderChest.g()); enderchestSnapshot = null; // Yatopia
|
|
if (!this.getShoulderEntityLeft().isEmpty()) {
|
|
nbttagcompound.set("ShoulderEntityLeft", this.getShoulderEntityLeft());
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java
|
|
index 4c6e708b6d6af45159315dc6ab5fdf72320d9825..2b7fb65942f5d22737cbbf0f8e7ef2194fc607a2 100644
|
|
--- a/src/main/java/net/minecraft/server/PlayerList.java
|
|
+++ b/src/main/java/net/minecraft/server/PlayerList.java
|
|
@@ -1284,6 +1284,28 @@ public abstract class PlayerList {
|
|
if (team != null) scoreboard.removeTeam(team);
|
|
}
|
|
// Paper end
|
|
+
|
|
+ // Yatopia start - make sure all saves are done
|
|
+ try {
|
|
+ playerFileData.saveThread.shutdown();
|
|
+ boolean done = playerFileData.saveThread.awaitTermination(30, java.util.concurrent.TimeUnit.SECONDS);
|
|
+ if (!done) {
|
|
+ LOGGER.error("Players did not save completely!");
|
|
+ }
|
|
+ ServerStatisticManager.saveThread.shutdown();
|
|
+ done = ServerStatisticManager.saveThread.awaitTermination(30, java.util.concurrent.TimeUnit.SECONDS);
|
|
+ if (!done) {
|
|
+ LOGGER.error("Stats did not save completely!");
|
|
+ }
|
|
+ AdvancementDataPlayer.saveThread.shutdown();
|
|
+ done = AdvancementDataPlayer.saveThread.awaitTermination(30, java.util.concurrent.TimeUnit.SECONDS);
|
|
+ if (!done) {
|
|
+ LOGGER.error("Advancements did not save completely!");
|
|
+ }
|
|
+ } catch (InterruptedException e) {
|
|
+ e.printStackTrace();
|
|
+ }
|
|
+ // Yatopia end
|
|
}
|
|
// Paper end
|
|
|
|
@@ -1321,13 +1343,13 @@ public abstract class PlayerList {
|
|
File file = this.server.a(SavedFile.STATS).toFile();
|
|
File file1 = new File(file, uuid + ".json");
|
|
|
|
- if (!file1.exists()) {
|
|
+ /*if (!file1.exists()) { // Yatopia - don't check for old stats files with sync file IO
|
|
File file2 = new File(file, displayName + ".json"); // CraftBukkit
|
|
|
|
if (file2.exists() && file2.isFile()) {
|
|
file2.renameTo(file1);
|
|
}
|
|
- }
|
|
+ }*/ // Yatopia
|
|
|
|
serverstatisticmanager = new ServerStatisticManager(this.server, file1);
|
|
// this.o.put(uuid, serverstatisticmanager); // CraftBukkit
|
|
diff --git a/src/main/java/net/minecraft/server/ServerStatisticManager.java b/src/main/java/net/minecraft/server/ServerStatisticManager.java
|
|
index 3c3b87e37cbf69c223da007e8b7eb646ec83691e..e2d12750bce9cb5ef087412b03809632a678bc04 100644
|
|
--- a/src/main/java/net/minecraft/server/ServerStatisticManager.java
|
|
+++ b/src/main/java/net/minecraft/server/ServerStatisticManager.java
|
|
@@ -30,6 +30,7 @@ public class ServerStatisticManager extends StatisticManager {
|
|
private final File d;
|
|
private final Set<Statistic<?>> e = Sets.newHashSet();
|
|
private int f = -300;
|
|
+ public static java.util.concurrent.ExecutorService saveThread = java.util.concurrent.Executors.newSingleThreadExecutor(); // Yatopia
|
|
|
|
public ServerStatisticManager(MinecraftServer minecraftserver, File file) {
|
|
this.c = minecraftserver;
|
|
@@ -41,6 +42,7 @@ public class ServerStatisticManager extends StatisticManager {
|
|
this.a.put( wrapper, entry.getValue().intValue() );
|
|
}
|
|
// Spigot end
|
|
+ saveThread.submit(() -> { // Yatopia
|
|
if (file.isFile()) {
|
|
try {
|
|
this.a(minecraftserver.getDataFixer(), org.apache.commons.io.FileUtils.readFileToString(file));
|
|
@@ -50,17 +52,20 @@ public class ServerStatisticManager extends StatisticManager {
|
|
ServerStatisticManager.LOGGER.error("Couldn't parse statistics file {}", file, jsonparseexception);
|
|
}
|
|
}
|
|
-
|
|
+ }); // Yatopia
|
|
}
|
|
|
|
public void save() {
|
|
if ( org.spigotmc.SpigotConfig.disableStatSaving ) return; // Spigot
|
|
+ // Yatopia start
|
|
+ String str = this.b();
|
|
+ saveThread.submit(() -> {
|
|
try {
|
|
- org.apache.commons.io.FileUtils.writeStringToFile(this.d, this.b());
|
|
+ org.apache.commons.io.FileUtils.writeStringToFile(this.d, str);
|
|
} catch (IOException ioexception) {
|
|
ServerStatisticManager.LOGGER.error("Couldn't save stats", ioexception);
|
|
}
|
|
-
|
|
+ }); // Yatopia end
|
|
}
|
|
|
|
@Override
|
|
@@ -111,7 +116,7 @@ public class ServerStatisticManager extends StatisticManager {
|
|
|
|
if (nbttagcompound2.hasKeyOfType(s2, 99)) {
|
|
SystemUtils.a(this.a(statisticwrapper, s2), (statistic) -> {
|
|
- this.a.put(statistic, nbttagcompound2.getInt(s2));
|
|
+ this.a.put(statistic, nbttagcompound2.getInt(s2) + this.a.getOrDefault(statistic, 0)); // Yatopia
|
|
}, () -> {
|
|
ServerStatisticManager.LOGGER.warn("Invalid statistic in {}: Don't know what {} is", this.d, s2);
|
|
});
|
|
diff --git a/src/main/java/net/minecraft/server/WorldNBTStorage.java b/src/main/java/net/minecraft/server/WorldNBTStorage.java
|
|
index a959672f5857b987001252c3fd7ace9e83e07c9b..bcae104ac104d6dcdf8653f291b24601247b5a55 100644
|
|
--- a/src/main/java/net/minecraft/server/WorldNBTStorage.java
|
|
+++ b/src/main/java/net/minecraft/server/WorldNBTStorage.java
|
|
@@ -17,6 +17,7 @@ public class WorldNBTStorage {
|
|
private static final Logger LOGGER = LogManager.getLogger();
|
|
private final File playerDir;
|
|
protected final DataFixer a;
|
|
+ public java.util.concurrent.ExecutorService saveThread = java.util.concurrent.Executors.newSingleThreadExecutor(); // Yatopia
|
|
|
|
public WorldNBTStorage(Convertable.ConversionSession convertable_conversionsession, DataFixer datafixer) {
|
|
this.a = datafixer;
|
|
@@ -26,6 +27,8 @@ public class WorldNBTStorage {
|
|
|
|
public void save(EntityHuman entityhuman) {
|
|
if(!com.destroystokyo.paper.PaperConfig.savePlayerData) return; // Paper - Make player data saving configurable
|
|
+ entityhuman.takeSnapshot(); // Yatopia
|
|
+ saveThread.submit(() -> { // Yatopia
|
|
try {
|
|
NBTTagCompound nbttagcompound = entityhuman.save(new NBTTagCompound());
|
|
File file = File.createTempFile(entityhuman.getUniqueIDString() + "-", ".dat", this.playerDir);
|
|
@@ -38,7 +41,7 @@ public class WorldNBTStorage {
|
|
} catch (Exception exception) {
|
|
WorldNBTStorage.LOGGER.error("Failed to save player data for {}", entityhuman.getName(), exception); // Paper
|
|
}
|
|
-
|
|
+ }); // Yatopia
|
|
}
|
|
|
|
@Nullable
|