PaperMC/patches/server/0279-Replace-OfflinePlayer-getLastPlayed.patch

165 lines
7.2 KiB
Diff
Raw Normal View History

2021-06-11 14:02:28 +02:00
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Zach Brown <zach@zachbr.io>
Date: Wed, 2 Jan 2019 00:35:43 -0600
Subject: [PATCH] Replace OfflinePlayer#getLastPlayed
2021-06-11 14:02:28 +02:00
Currently OfflinePlayer#getLastPlayed could more accurately be described
as "OfflinePlayer#getLastTimeTheirDataWasSaved".
The API doc says it should return the last time the server "witnessed"
the player, whilst also saying it should return the last time they
logged in. The current implementation does neither.
Given this interesting contradiction in the API documentation and the
current defacto implementation, I've elected to deprecate (with no
intent to remove) and replace it with two new methods, clearly named and
documented as to their purpose.
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
index c201325314b27c7658d6c16ddc7311afa79ccb4e..f21d6a14fa7f7ea1581ba02bc3ca06e589281a58 100644
2021-06-11 14:02:28 +02:00
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
2023-12-05 23:21:44 +01:00
@@ -248,6 +248,7 @@ public class ServerPlayer extends Player {
2023-09-22 00:26:51 +02:00
private int containerCounter;
2021-06-11 14:02:28 +02:00
public boolean wonGame;
private int containerUpdateDelay; // Paper - Configurable container update tick rate
+ public long loginTime; // Paper - Replace OfflinePlayer#getLastPlayed
2021-06-11 14:02:28 +02:00
// Paper start - cancellable death event
public boolean queueHealthUpdatePacket;
2021-06-11 14:02:28 +02:00
public net.minecraft.network.protocol.game.ClientboundSetHealthPacket queuedHealthUpdatePacket;
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index 455f14d758551229d15d703990bb5225fff37700..e2136ae52074f922a87ac30f5e34cb8035c70475 100644
2021-06-11 14:02:28 +02:00
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
2023-12-05 23:21:44 +01:00
@@ -179,6 +179,7 @@ public abstract class PlayerList {
2021-06-11 14:02:28 +02:00
2023-09-22 00:26:51 +02:00
public void placeNewPlayer(Connection connection, ServerPlayer player, CommonListenerCookie clientData) {
Rewrite chunk system (#8177) Patch documentation to come Issues with the old system that are fixed now: - World generation does not scale with cpu cores effectively. - Relies on the main thread for scheduling and maintaining chunk state, dropping chunk load/generate rates at lower tps. - Unreliable prioritisation of chunk gen/load calls that block the main thread. - Shutdown logic is utterly unreliable, as it has to wait for all chunks to unload - is it guaranteed that the chunk system is in a state on shutdown that it can reliably do this? Watchdog shutdown also typically failed due to thread checks, which is now resolved. - Saving of data is not unified (i.e can save chunk data without saving entity data, poses problems for desync if shutdown is really abnormal. - Entities are not loaded with chunks. This caused quite a bit of headache for Chunk#getEntities API, but now the new chunk system loads entities with chunks so that they are ready whenever the chunk loads in. Effectively brings the behavior back to 1.16 era, but still storing entities in their own separate regionfiles. The above list is not complete. The patch documentation will complete it. New chunk system hard relies on starlight and dataconverter, and most importantly the new concurrent utilities in ConcurrentUtil. Some of the old async chunk i/o interface (i.e the old file io thread reroutes _some_ calls to the new file io thread) is kept for plugin compat reasons. It will be removed in the next major version of minecraft. The old legacy chunk system patches have been moved to the removed folder in case we need them again.
2022-09-26 10:02:51 +02:00
player.isRealPlayer = true; // Paper
+ player.loginTime = System.currentTimeMillis(); // Paper - Replace OfflinePlayer#getLastPlayed
2021-06-11 14:02:28 +02:00
GameProfile gameprofile = player.getGameProfile();
GameProfileCache usercache = this.server.getProfileCache();
String s;
2021-06-11 14:02:28 +02:00
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java
index 34925d6448e0ef1d5bb4b24359f732b67aaa4230..0c1b5f625a351905e082b2c2a63bfd737101527e 100644
2021-06-11 14:02:28 +02:00
--- a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java
@@ -262,6 +262,61 @@ public class CraftOfflinePlayer implements OfflinePlayer, ConfigurationSerializa
2021-06-13 10:26:58 +02:00
return this.getData() != null;
2021-06-11 14:02:28 +02:00
}
+ // Paper start
+ @Override
+ public long getLastLogin() {
+ Player player = getPlayer();
+ if (player != null) return player.getLastLogin();
+
+ CompoundTag data = getPaperData();
+
+ if (data != null) {
+ if (data.contains("LastLogin")) {
+ return data.getLong("LastLogin");
+ } else {
+ // if the player file cannot provide accurate data, this is probably the closest we can approximate
+ File file = getDataFile();
+ return file.lastModified();
+ }
+ } else {
+ return 0;
+ }
+ }
+
+ @Override
+ public long getLastSeen() {
+ Player player = getPlayer();
+ if (player != null) return player.getLastSeen();
+
+ CompoundTag data = getPaperData();
+
+ if (data != null) {
+ if (data.contains("LastSeen")) {
+ return data.getLong("LastSeen");
+ } else {
+ // if the player file cannot provide accurate data, this is probably the closest we can approximate
+ File file = getDataFile();
+ return file.lastModified();
+ }
+ } else {
+ return 0;
+ }
+ }
+
+ private CompoundTag getPaperData() {
+ CompoundTag result = getData();
+
+ if (result != null) {
+ if (!result.contains("Paper")) {
+ result.put("Paper", new CompoundTag());
+ }
+ result = result.getCompound("Paper");
+ }
+
+ return result;
+ }
+ // Paper end
+
@Override
public Location getLastDeathLocation() {
if (this.getData().contains("LastDeathLocation", 10)) {
2021-06-11 14:02:28 +02:00
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index adcba9111415a20a4a55bb182be84c9f6d3755d7..95eb6060eb5661fa88bfdbd1c4d8bbcd78c2d983 100644
2021-06-11 14:02:28 +02:00
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -191,6 +191,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
private BorderChangeListener clientWorldBorderListener = this.createWorldBorderListener();
public org.bukkit.event.player.PlayerResourcePackStatusEvent.Status resourcePackStatus; // Paper - more resource pack API
2021-06-11 14:02:28 +02:00
private static final boolean DISABLE_CHANNEL_LIMIT = System.getProperty("paper.disableChannelLimit") != null; // Paper - add a flag to disable the channel limit
+ private long lastSaveTime; // Paper - getLastPlayed replacement API
2021-06-11 14:02:28 +02:00
public CraftPlayer(CraftServer server, ServerPlayer entity) {
super(server, entity);
@@ -1926,6 +1927,18 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
2021-06-11 14:02:28 +02:00
this.firstPlayed = firstPlayed;
}
+ // Paper start - getLastPlayed replacement API
2021-06-11 14:02:28 +02:00
+ @Override
+ public long getLastLogin() {
+ return this.getHandle().loginTime;
2021-06-11 14:02:28 +02:00
+ }
+
+ @Override
+ public long getLastSeen() {
+ return this.isOnline() ? System.currentTimeMillis() : this.lastSaveTime;
2021-06-11 14:02:28 +02:00
+ }
+ // Paper end - getLastPlayed replacement API
2021-06-11 14:02:28 +02:00
+
public void readExtraData(CompoundTag nbttagcompound) {
2021-06-13 10:26:58 +02:00
this.hasPlayedBefore = true;
2021-06-11 14:02:28 +02:00
if (nbttagcompound.contains("bukkit")) {
@@ -1948,6 +1961,8 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
2021-06-11 14:02:28 +02:00
}
public void setExtraData(CompoundTag nbttagcompound) {
+ this.lastSaveTime = System.currentTimeMillis(); // Paper
+
if (!nbttagcompound.contains("bukkit")) {
nbttagcompound.put("bukkit", new CompoundTag());
}
@@ -1962,6 +1977,16 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
2021-06-13 10:26:58 +02:00
data.putLong("firstPlayed", this.getFirstPlayed());
2021-06-11 14:02:28 +02:00
data.putLong("lastPlayed", System.currentTimeMillis());
data.putString("lastKnownName", handle.getScoreboardName());
+
+ // Paper start - persist for use in offline save data
+ if (!nbttagcompound.contains("Paper")) {
+ nbttagcompound.put("Paper", new CompoundTag());
+ }
+
+ CompoundTag paper = nbttagcompound.getCompound("Paper");
+ paper.putLong("LastLogin", handle.loginTime);
+ paper.putLong("LastSeen", System.currentTimeMillis());
+ // Paper end
}
@Override