2014-11-28 02:17:45 +01:00
|
|
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
|
|
From: Thinkofdeath <thethinkofdeath@gmail.com>
|
|
|
|
Date: Sun, 20 Apr 2014 13:18:55 +0100
|
|
|
|
Subject: [PATCH] Convert player skulls async
|
|
|
|
|
|
|
|
|
|
|
|
diff --git a/src/main/java/net/minecraft/server/ItemSkull.java b/src/main/java/net/minecraft/server/ItemSkull.java
|
|
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
|
|
|
--- a/src/main/java/net/minecraft/server/ItemSkull.java
|
|
|
|
+++ b/src/main/java/net/minecraft/server/ItemSkull.java
|
|
|
|
@@ -0,0 +0,0 @@ public class ItemSkull extends Item {
|
|
|
|
return super.a(itemstack);
|
|
|
|
}
|
|
|
|
|
|
|
|
- public boolean a(NBTTagCompound nbttagcompound) {
|
|
|
|
+ public boolean a(final NBTTagCompound nbttagcompound) { // Spigot - make final
|
|
|
|
super.a(nbttagcompound);
|
2016-02-29 22:33:06 +01:00
|
|
|
if (nbttagcompound.hasKeyOfType("SkullOwner", 8) && !nbttagcompound.getString("SkullOwner").isEmpty()) {
|
2014-11-28 02:17:45 +01:00
|
|
|
GameProfile gameprofile = new GameProfile((UUID) null, nbttagcompound.getString("SkullOwner"));
|
|
|
|
|
|
|
|
- gameprofile = TileEntitySkull.b(gameprofile);
|
|
|
|
- nbttagcompound.set("SkullOwner", GameProfileSerializer.serialize(new NBTTagCompound(), gameprofile));
|
|
|
|
+ // Spigot start
|
|
|
|
+ TileEntitySkull.b(gameprofile, new com.google.common.base.Predicate<GameProfile>() {
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public boolean apply(GameProfile gameprofile) {
|
|
|
|
+ nbttagcompound.set("SkullOwner", GameProfileSerializer.serialize(new NBTTagCompound(), gameprofile));
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ // Spigot end
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
diff --git a/src/main/java/net/minecraft/server/TileEntitySkull.java b/src/main/java/net/minecraft/server/TileEntitySkull.java
|
|
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
|
|
|
--- a/src/main/java/net/minecraft/server/TileEntitySkull.java
|
|
|
|
+++ b/src/main/java/net/minecraft/server/TileEntitySkull.java
|
2016-02-29 22:33:06 +01:00
|
|
|
@@ -0,0 +0,0 @@ import com.mojang.authlib.minecraft.MinecraftSessionService;
|
2014-11-28 02:17:45 +01:00
|
|
|
import com.mojang.authlib.properties.Property;
|
|
|
|
import java.util.UUID;
|
|
|
|
|
|
|
|
+// Spigot start
|
|
|
|
+import com.google.common.base.Predicate;
|
|
|
|
+import com.google.common.cache.LoadingCache;
|
|
|
|
+import com.google.common.cache.CacheBuilder;
|
|
|
|
+import com.google.common.cache.CacheLoader;
|
|
|
|
+import java.util.concurrent.Executor;
|
|
|
|
+import java.util.concurrent.Executors;
|
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
|
+
|
|
|
|
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
|
|
|
+import com.mojang.authlib.Agent;
|
2015-02-28 12:36:22 +01:00
|
|
|
+import com.mojang.authlib.ProfileLookupCallback;
|
2014-11-28 02:17:45 +01:00
|
|
|
+// Spigot end
|
|
|
|
+
|
2016-02-29 22:33:06 +01:00
|
|
|
public class TileEntitySkull extends TileEntity implements ITickable {
|
2014-11-28 02:17:45 +01:00
|
|
|
|
|
|
|
private int a;
|
2016-02-29 22:33:06 +01:00
|
|
|
@@ -0,0 +0,0 @@ public class TileEntitySkull extends TileEntity implements ITickable {
|
|
|
|
private boolean i;
|
|
|
|
private static UserCache j;
|
|
|
|
private static MinecraftSessionService k;
|
2014-11-28 02:17:45 +01:00
|
|
|
+ // Spigot start
|
|
|
|
+ public static final Executor executor = Executors.newFixedThreadPool(3,
|
|
|
|
+ new ThreadFactoryBuilder()
|
|
|
|
+ .setNameFormat("Head Conversion Thread - %1$d")
|
|
|
|
+ .build()
|
|
|
|
+ );
|
|
|
|
+ public static final LoadingCache<String, GameProfile> skinCache = CacheBuilder.newBuilder()
|
|
|
|
+ .maximumSize( 5000 )
|
|
|
|
+ .expireAfterAccess( 60, TimeUnit.MINUTES )
|
|
|
|
+ .build( new CacheLoader<String, GameProfile>()
|
|
|
|
+ {
|
|
|
|
+ @Override
|
|
|
|
+ public GameProfile load(String key) throws Exception
|
|
|
|
+ {
|
2015-02-28 12:36:22 +01:00
|
|
|
+ final GameProfile[] profiles = new GameProfile[1];
|
|
|
|
+ ProfileLookupCallback gameProfileLookup = new ProfileLookupCallback() {
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void onProfileLookupSucceeded(GameProfile gp) {
|
|
|
|
+ profiles[0] = gp;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void onProfileLookupFailed(GameProfile gp, Exception excptn) {
|
|
|
|
+ profiles[0] = gp;
|
|
|
|
+ }
|
|
|
|
+ };
|
2014-11-28 02:17:45 +01:00
|
|
|
+
|
|
|
|
+ MinecraftServer.getServer().getGameProfileRepository().findProfilesByNames(new String[] { key }, Agent.MINECRAFT, gameProfileLookup);
|
|
|
|
+
|
|
|
|
+ GameProfile profile = profiles[ 0 ];
|
|
|
|
+ if (profile == null) {
|
|
|
|
+ UUID uuid = EntityHuman.a(new GameProfile(null, key));
|
|
|
|
+ profile = new GameProfile(uuid, key);
|
|
|
|
+
|
|
|
|
+ gameProfileLookup.onProfileLookupSucceeded(profile);
|
|
|
|
+ } else
|
|
|
|
+ {
|
|
|
|
+
|
|
|
|
+ Property property = Iterables.getFirst( profile.getProperties().get( "textures" ), null );
|
|
|
|
+
|
|
|
|
+ if ( property == null )
|
|
|
|
+ {
|
2016-02-29 22:33:06 +01:00
|
|
|
+ profile = MinecraftServer.getServer().ay().fillProfileProperties( profile, true );
|
2014-11-28 02:17:45 +01:00
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ return profile;
|
|
|
|
+ }
|
|
|
|
+ } );
|
|
|
|
+ // Spigot end
|
|
|
|
|
|
|
|
public TileEntitySkull() {}
|
|
|
|
|
2016-02-29 22:33:06 +01:00
|
|
|
@@ -0,0 +0,0 @@ public class TileEntitySkull extends TileEntity implements ITickable {
|
2014-11-28 02:17:45 +01:00
|
|
|
}
|
|
|
|
|
2016-02-29 22:33:06 +01:00
|
|
|
private void g() {
|
2014-11-28 02:17:45 +01:00
|
|
|
- this.g = b(this.g);
|
|
|
|
- this.update();
|
|
|
|
+ // Spigot start
|
|
|
|
+ GameProfile profile = this.g;
|
|
|
|
+ setSkullType( 0 ); // Work around client bug
|
|
|
|
+ b(profile, new Predicate<GameProfile>() {
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public boolean apply(GameProfile input) {
|
2015-05-09 22:23:26 +02:00
|
|
|
+ setSkullType(3); // Work around client bug
|
2014-11-28 02:17:45 +01:00
|
|
|
+ g = input;
|
|
|
|
+ update();
|
2015-01-05 03:01:24 +01:00
|
|
|
+ if (world != null) {
|
2016-02-29 22:33:06 +01:00
|
|
|
+ world.m(position); // PAIL: notify
|
2015-01-05 03:01:24 +01:00
|
|
|
+ }
|
2014-11-28 02:17:45 +01:00
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ // Spigot end
|
|
|
|
}
|
|
|
|
|
|
|
|
- public static GameProfile b(GameProfile gameprofile) {
|
|
|
|
+ // Spigot start - Support async lookups
|
|
|
|
+ public static void b(final GameProfile gameprofile, final Predicate<GameProfile> callback) {
|
|
|
|
if (gameprofile != null && !UtilColor.b(gameprofile.getName())) {
|
|
|
|
if (gameprofile.isComplete() && gameprofile.getProperties().containsKey("textures")) {
|
|
|
|
- return gameprofile;
|
2016-02-29 22:33:06 +01:00
|
|
|
- } else if (TileEntitySkull.j != null && TileEntitySkull.k != null) {
|
|
|
|
- GameProfile gameprofile1 = TileEntitySkull.j.getProfile(gameprofile.getName());
|
2014-11-28 02:17:45 +01:00
|
|
|
-
|
|
|
|
- if (gameprofile1 == null) {
|
|
|
|
- return gameprofile;
|
2016-02-29 22:33:06 +01:00
|
|
|
+ callback.apply(gameprofile);
|
|
|
|
+ } else if (MinecraftServer.getServer() == null) {
|
|
|
|
+ callback.apply(gameprofile);
|
|
|
|
+ } else {
|
2014-11-28 02:17:45 +01:00
|
|
|
+ GameProfile profile = skinCache.getIfPresent(gameprofile.getName());
|
2015-03-07 16:48:05 +01:00
|
|
|
+ if (profile != null && Iterables.getFirst(profile.getProperties().get("textures"), (Object) null) != null) {
|
2014-11-28 02:17:45 +01:00
|
|
|
+ callback.apply(profile);
|
|
|
|
} else {
|
|
|
|
- Property property = (Property) Iterables.getFirst(gameprofile1.getProperties().get("textures"), (Object) null);
|
2015-03-07 16:48:05 +01:00
|
|
|
-
|
2014-11-28 02:17:45 +01:00
|
|
|
- if (property == null) {
|
2016-02-29 22:33:06 +01:00
|
|
|
- gameprofile1 = TileEntitySkull.k.fillProfileProperties(gameprofile1, true);
|
2015-03-07 16:48:05 +01:00
|
|
|
- }
|
2014-11-28 02:17:45 +01:00
|
|
|
-
|
|
|
|
- return gameprofile1;
|
|
|
|
+ executor.execute(new Runnable() {
|
|
|
|
+ @Override
|
|
|
|
+ public void run() {
|
|
|
|
+ final GameProfile profile = skinCache.getUnchecked(gameprofile.getName().toLowerCase());
|
|
|
|
+ MinecraftServer.getServer().processQueue.add(new Runnable() {
|
|
|
|
+ @Override
|
|
|
|
+ public void run() {
|
|
|
|
+ if (profile == null) {
|
|
|
|
+ callback.apply(gameprofile);
|
|
|
|
+ } else {
|
|
|
|
+ callback.apply(profile);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
}
|
2016-02-29 22:33:06 +01:00
|
|
|
- } else {
|
|
|
|
- return gameprofile;
|
2014-11-28 02:17:45 +01:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
- return gameprofile;
|
|
|
|
+ callback.apply(gameprofile);
|
|
|
|
}
|
|
|
|
}
|
2016-02-29 22:33:06 +01:00
|
|
|
+ // Spigot end
|
2014-11-28 02:17:45 +01:00
|
|
|
|
|
|
|
public int getSkullType() {
|
|
|
|
return this.a;
|
|
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java
|
|
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
|
|
|
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java
|
|
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java
|
|
|
|
@@ -0,0 +0,0 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta {
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
- void applyToItem(NBTTagCompound tag) {
|
|
|
|
+ void applyToItem(final NBTTagCompound tag) { // Spigot - make final
|
|
|
|
super.applyToItem(tag);
|
|
|
|
|
2016-02-21 09:22:37 +01:00
|
|
|
if (profile != null) {
|
2014-11-28 02:17:45 +01:00
|
|
|
NBTTagCompound owner = new NBTTagCompound();
|
|
|
|
GameProfileSerializer.serialize(owner, profile);
|
|
|
|
- tag.set(SKULL_OWNER.NBT, owner);
|
|
|
|
+ tag.set( SKULL_OWNER.NBT, owner );
|
|
|
|
+ // Spigot start - do an async lookup of the profile.
|
|
|
|
+ // Unfortunately there is not way to refresh the holding
|
|
|
|
+ // inventory, so that responsibility is left to the user.
|
|
|
|
+ net.minecraft.server.TileEntitySkull.b(profile, new com.google.common.base.Predicate<GameProfile>() {
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public boolean apply(GameProfile input) {
|
|
|
|
+ NBTTagCompound owner = new NBTTagCompound();
|
|
|
|
+ GameProfileSerializer.serialize( owner, input );
|
|
|
|
+ tag.set( SKULL_OWNER.NBT, owner );
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ // Spigot end
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
--
|