Files
Purpur/patches/server/0151-PaperPR-Apply-advancements-async.patch
BillyGalbreath ef0b93df2e Rebuild patches
2020-12-12 18:19:48 -06:00

157 lines
9.0 KiB
Diff

From e88f1042add937869deed2a768ead73f108e5ff5 Mon Sep 17 00:00:00 2001
From: Mariell Hoversholm <proximyst@proximyst.com>
Date: Thu, 20 Aug 2020 17:57:02 +0200
Subject: [PATCH] PaperPR - Apply advancements async
diff --git a/src/main/java/net/minecraft/server/AdvancementDataPlayer.java b/src/main/java/net/minecraft/server/AdvancementDataPlayer.java
index eaa1063ff2bc5621e93043c4de41ca62f1323fde..a3b89a4f2a291b9a9bf847e059c6b926ea9db9b2 100644
--- a/src/main/java/net/minecraft/server/AdvancementDataPlayer.java
+++ b/src/main/java/net/minecraft/server/AdvancementDataPlayer.java
@@ -63,6 +63,7 @@ public class AdvancementDataPlayer {
this.d(advancementdataworld);
}
+ public final void setPlayer(EntityPlayer entityPlayer) { this.a(entityPlayer); } // Paper - OBFHELPER
public void a(EntityPlayer entityplayer) {
this.player = entityplayer;
}
diff --git a/src/main/java/net/minecraft/server/CriterionProgress.java b/src/main/java/net/minecraft/server/CriterionProgress.java
index 98c3884f478aed1eba82c15f258ebfa1c7203b14..244b58a7c41d2b0ba3117550282e68a168439708 100644
--- a/src/main/java/net/minecraft/server/CriterionProgress.java
+++ b/src/main/java/net/minecraft/server/CriterionProgress.java
@@ -10,8 +10,9 @@ import java.util.Date;
public class CriterionProgress {
- private static final SimpleDateFormat a = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z");
- private Date b;
+ private static final SimpleDateFormat a = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z"); // Paper - diff on change
+ private static final ThreadLocal<SimpleDateFormat> THREAD_LOCAL_FORMATTER = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z")); // Paper - async advancements - SimpleDateFormat is not thread safe
+ private Date b; private void setDate(Date date) { this.b = date; } // Paper - OBFHELPER
public CriterionProgress() {}
@@ -44,7 +45,7 @@ public class CriterionProgress {
}
public JsonElement e() {
- return (JsonElement) (this.b != null ? new JsonPrimitive(CriterionProgress.a.format(this.b)) : JsonNull.INSTANCE);
+ return this.getDate() != null ? new JsonPrimitive(THREAD_LOCAL_FORMATTER.get().format(this.getDate())) : JsonNull.INSTANCE; // Paper
}
public static CriterionProgress b(PacketDataSerializer packetdataserializer) {
@@ -61,7 +62,7 @@ public class CriterionProgress {
CriterionProgress criterionprogress = new CriterionProgress();
try {
- criterionprogress.b = CriterionProgress.a.parse(s);
+ criterionprogress.setDate(THREAD_LOCAL_FORMATTER.get().parse(s)); // Paper
return criterionprogress;
} catch (ParseException parseexception) {
throw new JsonSyntaxException("Invalid datetime: " + s, parseexception);
diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java
index 50ea875a3b31ea920442ea2cf3d3359cee1d62dc..cc6a54e06a4fe91a19dee0397192e9884597835e 100644
--- a/src/main/java/net/minecraft/server/EntityPlayer.java
+++ b/src/main/java/net/minecraft/server/EntityPlayer.java
@@ -49,7 +49,8 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
public final MinecraftServer server;
public final PlayerInteractManager playerInteractManager;
public final Deque<Integer> removeQueue = new ArrayDeque<>(); // Paper
- private final AdvancementDataPlayer advancementDataPlayer;
+ private AdvancementDataPlayer advancementDataPlayer; // Paper - remove final
+ private final java.util.concurrent.CompletableFuture<AdvancementDataPlayer> advancementDataPlayerCompletableFuture; // Paper - async advancements
private final ServerStatisticManager serverStatisticManager;
private float lastHealthScored = Float.MIN_VALUE;
private int lastFoodScored = Integer.MIN_VALUE;
@@ -136,7 +137,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
this.playerInteractManager = playerinteractmanager;
this.server = minecraftserver;
this.serverStatisticManager = minecraftserver.getPlayerList().getStatisticManager(this);
- this.advancementDataPlayer = minecraftserver.getPlayerList().f(this);
+ this.advancementDataPlayerCompletableFuture = minecraftserver.getPlayerList().loadAdvancementDataPlayerAsync(this); // Paper - async advancements
this.G = 1.0F;
//this.c(worldserver); // Paper - don't move to spawn on login, only first join
this.co = minecraftserver.a(this);
@@ -505,7 +506,8 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
CriterionTriggers.u.a(this, this.cf, this.ticksLived - this.cg);
}
- this.advancementDataPlayer.b(this);
+ if (areAdvancementsLoaded()) // Paper - async advancements: don't tick advancements until they're loaded
+ this.advancementDataPlayer.sendUpdateIfNeeded(this); // Paper - conflict on change
// Purpur start
if (this.world.purpurConfig.useNightVisionWhenRiding && this.getVehicle() != null && this.getVehicle().getRider() == this && world.getTime() % 100 == 0) { // 5 seconds
@@ -2121,7 +2123,26 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
this.worldChangeInvuln = false;
}
+ // Paper start - async advancements
+ public boolean areAdvancementsLoaded() {
+ return this.advancementDataPlayer != null
+ || this.advancementDataPlayerCompletableFuture.isDone();
+ }
+
+ public AdvancementDataPlayer getAdvancementDataIfLoadedImmediately() {
+ // We need a null check here because this method is called before the future is assigned.
+ // Once assigned, it will essentially be a no-op as the field is final.
+ if (this.advancementDataPlayer == null && this.advancementDataPlayerCompletableFuture != null && this.advancementDataPlayerCompletableFuture.isDone())
+ this.advancementDataPlayer = this.advancementDataPlayerCompletableFuture.join();
+ return this.advancementDataPlayer;
+ }
+
public AdvancementDataPlayer getAdvancementData() {
+ if (this.advancementDataPlayer == null)
+ synchronized (this.advancementDataPlayerCompletableFuture) {
+ if (this.advancementDataPlayer == null) this.advancementDataPlayer = this.advancementDataPlayerCompletableFuture.join();
+ }
+ // Paper end
return this.advancementDataPlayer;
}
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 2374a7ee018493795389b21848289395168db422..6c9a8d92e70106635699e55367eed60ac95c3290 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -2315,6 +2315,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
return methodprofilerresults;
}
+ public final java.nio.file.Path getSavedFilePath(SavedFile savedFile) { return this.a(savedFile); } // Paper - OBFHELPER
public java.nio.file.Path a(SavedFile savedfile) {
return this.convertable.getWorldFolder(savedfile);
}
diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java
index 7b385eb43e4cf565d500d0250f3c5e4dbebae986..eae19141e3cc890d3b4bdc0d0297061e79857160 100644
--- a/src/main/java/net/minecraft/server/PlayerList.java
+++ b/src/main/java/net/minecraft/server/PlayerList.java
@@ -1339,9 +1339,26 @@ public abstract class PlayerList {
return serverstatisticmanager;
}
+ // Paper start - async advancements
+ public java.util.concurrent.CompletableFuture<AdvancementDataPlayer> loadAdvancementDataPlayerAsync(EntityPlayer entityPlayer) {
+ if (entityPlayer.getAdvancementDataIfLoadedImmediately() != null) {
+ entityPlayer.getAdvancementData().setPlayer(entityPlayer);
+ return java.util.concurrent.CompletableFuture.completedFuture(entityPlayer.getAdvancementData());
+ }
+
+ UUID uuid = entityPlayer.getUniqueID();
+ File file = this.server.getSavedFilePath(SavedFile.ADVANCEMENTS).toFile();
+ final File file1 = new File(file, uuid + ".json");
+ return java.util.concurrent.CompletableFuture.supplyAsync(
+ () -> new AdvancementDataPlayer(this.server.getDataFixer(), this, this.server.getAdvancementData(), file1, entityPlayer),
+ this.server.executorService
+ );
+ }
+ // Paper end
+
public AdvancementDataPlayer f(EntityPlayer entityplayer) {
UUID uuid = entityplayer.getUniqueID();
- AdvancementDataPlayer advancementdataplayer = (AdvancementDataPlayer) entityplayer.getAdvancementData(); // CraftBukkit
+ AdvancementDataPlayer advancementdataplayer = (AdvancementDataPlayer) entityplayer.getAdvancementDataIfLoadedImmediately(); // CraftBukkit // Paper
if (advancementdataplayer == null) {
File file = this.server.a(SavedFile.ADVANCEMENTS).toFile();