Make Skull Texture Lookup use the User Cache

Spigots cache only cached by name which really was not correct...

Additionally, user cache exposes a cache of any player who has logged in
once this session too even if offline.

Also fixed some quirks with Profile API where we might of had textures
in the cache that we didn't even try to look up.

So this should overall help reduce API calls to Mojang.

Sadly, the User Cache doesn't cache textures, but if that ever
changes in future, we would gain benefit there too.
This commit is contained in:
Aikar 2020-06-19 21:32:42 -04:00
parent 92d1247ee3
commit a70618cd5c
No known key found for this signature in database
GPG key ID: 401ADFC9891FAAFE
2 changed files with 87 additions and 16 deletions

View file

@ -7,10 +7,10 @@ Establishes base extension of profile systems for future edits too
diff --git a/src/main/java/com/destroystokyo/paper/profile/CraftPlayerProfile.java b/src/main/java/com/destroystokyo/paper/profile/CraftPlayerProfile.java
new file mode 100644
index 0000000000000000000000000000000000000000..b151a13c1b9058eb057081ef8a64558028443a07
index 0000000000000000000000000000000000000000..5eee712e4c9230b10a969daee9fd8b4eec9bf6c9
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/profile/CraftPlayerProfile.java
@@ -0,0 +1,280 @@
@@ -0,0 +1,285 @@
+package com.destroystokyo.paper.profile;
+
+import com.destroystokyo.paper.PaperConfig;
@ -151,9 +151,6 @@ index 0000000000000000000000000000000000000000..b151a13c1b9058eb057081ef8a645580
+ }
+
+ public boolean completeFromCache(boolean lookupName) {
+ if (profile.isComplete()) {
+ return true;
+ }
+ MinecraftServer server = MinecraftServer.getServer();
+ String name = profile.getName();
+ UserCache userCache = server.getUserCache();
@ -167,14 +164,17 @@ index 0000000000000000000000000000000000000000..b151a13c1b9058eb057081ef8a645580
+ profile = new GameProfile(UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(Charsets.UTF_8)), name);
+ }
+ if (profile != null) {
+ // if old has it, assume its newer, so overwrite, else use cached if it was set and ours wasn't
+ copyProfileProperties(this.profile, profile);
+ this.profile = profile;
+ }
+ }
+
+ if (profile.getName() == null) {
+ // If we need textures, skip this check, as we will get it below anyways.
+ if (profile.getName() == null || !hasTextures()) {
+ GameProfile profile = userCache.getProfile(this.profile.getId());
+ if (profile != null) {
+ // if old has it, assume its newer, so overwrite, else use cached if it was set and ours wasn't
+ copyProfileProperties(this.profile, profile);
+ this.profile = profile;
+ }
+ }
@ -189,22 +189,27 @@ index 0000000000000000000000000000000000000000..b151a13c1b9058eb057081ef8a645580
+ if (isOnlineMode && (!isCompleteFromCache || textures && !hasTextures())) {
+ GameProfile result = server.getSessionService().fillProfileProperties(profile, true);
+ if (result != null) {
+ this.profile = result;
+ copyProfileProperties(result, this.profile, true);
+ }
+ server.getUserCache().saveProfile(this.profile);
+ }
+ return profile.isComplete() && (!isOnlineMode || !textures || hasTextures());
+ }
+
+ private static void copyProfileProperties(GameProfile source, GameProfile target) {
+ copyProfileProperties(source, target, false);
+ }
+
+ private static void copyProfileProperties(GameProfile source, GameProfile target, boolean clearTarget) {
+ PropertyMap sourceProperties = source.getProperties();
+ PropertyMap targetProperties = target.getProperties();
+ if (clearTarget) targetProperties.clear();
+ if (sourceProperties.isEmpty()) {
+ return;
+ }
+ PropertyMap properties = target.getProperties();
+ properties.clear();
+
+ for (Property property : sourceProperties.values()) {
+ properties.put(property.getName(), property);
+ targetProperties.put(property.getName(), property);
+ }
+ }
+
@ -450,8 +455,50 @@ index ed32242bd169e9f28607942aa31aa48a5799b215..54f80cb8e1b771f2a493543e04f8bc83
public MinecraftSessionService getMinecraftSessionService() {
return this.minecraftSessionService;
}
diff --git a/src/main/java/net/minecraft/server/TileEntitySkull.java b/src/main/java/net/minecraft/server/TileEntitySkull.java
index 177cceb77f8783fe93ba7e4342de9c589f155c1b..e2544aeb5a28fd98a4dc162227276b23a99424fc 100644
--- a/src/main/java/net/minecraft/server/TileEntitySkull.java
+++ b/src/main/java/net/minecraft/server/TileEntitySkull.java
@@ -158,6 +158,7 @@ public class TileEntitySkull extends TileEntity /*implements ITickable*/ { // Pa
private void f() {
// Spigot start
GameProfile profile = this.gameProfile;
+ if (profile.isComplete() && profile.getProperties().containsKey("textures")) return; // Paper
b(profile, new Predicate<GameProfile>() {
@Override
@@ -178,7 +179,16 @@ public class TileEntitySkull extends TileEntity /*implements ITickable*/ { // Pa
} else if (MinecraftServer.getServer() == null) {
callback.apply(gameprofile);
} else {
- GameProfile profile = skinCache.getIfPresent(gameprofile.getName().toLowerCase(java.util.Locale.ROOT));
+ // Paper start
+ com.destroystokyo.paper.profile.CraftPlayerProfile paperProfile = new com.destroystokyo.paper.profile.CraftPlayerProfile(gameprofile);
+ if (sync) {
+ // might complete by cache, but if not, go ahead and do it now, avoid the code below
+ paperProfile.complete(true);
+ } else {
+ paperProfile.completeFromCache();
+ }
+ GameProfile profile = paperProfile.getGameProfile();
+ // Paper end
if (profile != null && Iterables.getFirst(profile.getProperties().get("textures"), (Object) null) != null) {
callback.apply(profile);
@@ -187,7 +197,10 @@ public class TileEntitySkull extends TileEntity /*implements ITickable*/ { // Pa
Callable<GameProfile> callable = new Callable<GameProfile>() {
@Override
public GameProfile call() {
- final GameProfile profile = skinCache.getUnchecked(gameprofile.getName().toLowerCase(java.util.Locale.ROOT));
+ // Paper start
+ paperProfile.complete(true);
+ final GameProfile profile = paperProfile.getGameProfile();
+ // Paper end
MinecraftServer.getServer().processQueue.add(new Runnable() {
@Override
public void run() {
diff --git a/src/main/java/net/minecraft/server/UserCache.java b/src/main/java/net/minecraft/server/UserCache.java
index 581199e6dcddb3692ccc6b6cf6c42fa5ef1f5e7e..a072222bc5b8b1b62990bce35034b09ebf270865 100644
index 581199e6dcddb3692ccc6b6cf6c42fa5ef1f5e7e..39d2f83531d539fb96824c2e6a9018c12ea75272 100644
--- a/src/main/java/net/minecraft/server/UserCache.java
+++ b/src/main/java/net/minecraft/server/UserCache.java
@@ -43,7 +43,7 @@ public class UserCache {
@ -463,7 +510,15 @@ index 581199e6dcddb3692ccc6b6cf6c42fa5ef1f5e7e..a072222bc5b8b1b62990bce35034b09e
private final Map<UUID, UserCache.UserCacheEntry> e = new java.util.concurrent.ConcurrentHashMap<>(); // Paper
private final Deque<GameProfile> f = new java.util.concurrent.LinkedBlockingDeque<GameProfile>(); // CraftBukkit
private final GameProfileRepository g;
@@ -165,6 +165,13 @@ public class UserCache {
@@ -104,6 +104,7 @@ public class UserCache {
return UserCache.c;
}
+ public void saveProfile(GameProfile gameprofile) { a(gameprofile); } // Paper - OBFHELPER
public void a(GameProfile gameprofile) {
this.a(gameprofile, (Date) null);
}
@@ -165,6 +166,13 @@ public class UserCache {
return usercache_usercacheentry == null ? null : usercache_usercacheentry.a();
}
@ -477,7 +532,7 @@ index 581199e6dcddb3692ccc6b6cf6c42fa5ef1f5e7e..a072222bc5b8b1b62990bce35034b09e
@Nullable
public GameProfile getProfile(UUID uuid) {
UserCache.UserCacheEntry usercache_usercacheentry = (UserCache.UserCacheEntry) this.e.get(uuid);
@@ -273,7 +280,7 @@ public class UserCache {
@@ -273,7 +281,7 @@ public class UserCache {
class UserCacheEntry {
@ -525,3 +580,19 @@ index f01bd38d0b600a69224f610fd77a542ec6d1c322..95f4abddf57eb8c59cb5a5410b8d551d
+ }
// Paper end
}
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java
index 4fb27cc7ed062696239f75b6f85ddb0a31866568..52c8d31590ea8e355395fa95cf690cc3770f5f71 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java
@@ -71,6 +71,11 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta {
}
private void setProfile(GameProfile profile) {
+ // Paper start
+ com.destroystokyo.paper.profile.CraftPlayerProfile paperProfile = new com.destroystokyo.paper.profile.CraftPlayerProfile(profile);
+ paperProfile.completeFromCache();
+ profile = paperProfile.getGameProfile();
+ // Paper end
this.profile = profile;
this.serializedProfile = (profile == null) ? null : GameProfileSerializer.serialize(new NBTTagCompound(), profile);
}

View file

@ -48,7 +48,7 @@ index 20588598386a4f479e6a58b294149bed789c63ce..ecc32c2fb1e8e1ac03074102b982adb4
public BlockFace getRotation() {
BlockData blockData = getBlockData();
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java
index 4fb27cc7ed062696239f75b6f85ddb0a31866568..96d62bbf883cf589509d51ac02fbe11a452dce64 100644
index 52c8d31590ea8e355395fa95cf690cc3770f5f71..2a3c86b0cbce0c37ebd8cace138c72c99f7455ea 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java
@@ -3,6 +3,8 @@ package org.bukkit.craftbukkit.inventory;
@ -68,7 +68,7 @@ index 4fb27cc7ed062696239f75b6f85ddb0a31866568..96d62bbf883cf589509d51ac02fbe11a
@DelegateDeserialization(SerializableMeta.class)
class CraftMetaSkull extends CraftMetaItem implements SkullMeta {
@@ -133,6 +136,19 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta {
@@ -138,6 +141,19 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta {
return hasOwner() ? profile.getName() : null;
}