mirror of
https://hub.spigotmc.org/stash/scm/spigot/spigot.git
synced 2025-09-18 21:33:01 +00:00

Caveat: When using skull meta, the user must refresh the inventory, because that can't be done form the context in which the lookup is done.
245 lines
10 KiB
Diff
245 lines
10 KiB
Diff
From 6eaf9a0a9503de652b7a3dfad975c891c09d74ca 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/ItemStack.java b/src/main/java/net/minecraft/server/ItemStack.java
|
|
index 2723ccb..26f9fae 100644
|
|
--- a/src/main/java/net/minecraft/server/ItemStack.java
|
|
+++ b/src/main/java/net/minecraft/server/ItemStack.java
|
|
@@ -216,9 +216,61 @@ public final class ItemStack {
|
|
if (nbttagcompound.hasKeyOfType("tag", 10)) {
|
|
// CraftBukkit - make defensive copy as this data may be coming from the save thread
|
|
this.tag = (NBTTagCompound) nbttagcompound.getCompound("tag").clone();
|
|
+ validateSkullSkin(); // Spigot
|
|
}
|
|
}
|
|
|
|
+ // Spigot start - make sure the tag is given the full gameprofile if it's a skull (async lookup)
|
|
+ public void validateSkullSkin()
|
|
+ {
|
|
+ if ( this.item == Items.SKULL && this.getData() == 3 )
|
|
+ {
|
|
+ String owner;
|
|
+ if ( this.tag.hasKeyOfType( "SkullOwner", 8 ) )
|
|
+ {
|
|
+ owner = this.tag.getString( "SkullOwner" );
|
|
+ } else if ( this.tag.hasKeyOfType( "SkullOwner", 10 ) )
|
|
+ {
|
|
+ net.minecraft.util.com.mojang.authlib.GameProfile profile = GameProfileSerializer.deserialize( this.tag.getCompound( "SkullOwner" ) );
|
|
+ if ( profile == null || !profile.getProperties().isEmpty() )
|
|
+ {
|
|
+ return;
|
|
+ } else
|
|
+ {
|
|
+ owner = profile.getName();
|
|
+ }
|
|
+ } else
|
|
+ {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ final String finalOwner = owner;
|
|
+ TileEntitySkull.executor.execute( new Runnable()
|
|
+ {
|
|
+ @Override
|
|
+ public void run()
|
|
+ {
|
|
+
|
|
+ final net.minecraft.util.com.mojang.authlib.GameProfile profile = TileEntitySkull.skinCache.getUnchecked( finalOwner.toLowerCase() );
|
|
+ if ( profile != null )
|
|
+ {
|
|
+ MinecraftServer.getServer().processQueue.add( new Runnable()
|
|
+ {
|
|
+ @Override
|
|
+ public void run()
|
|
+ {
|
|
+ NBTTagCompound nbtProfile = new NBTTagCompound();
|
|
+ GameProfileSerializer.serialize( nbtProfile, profile );
|
|
+ ItemStack.this.tag.set( "SkullOwner", nbtProfile );
|
|
+ }
|
|
+ } );
|
|
+ }
|
|
+ }
|
|
+ } );
|
|
+ }
|
|
+ }
|
|
+ // Spigot end
|
|
+
|
|
public int getMaxStackSize() {
|
|
return this.getItem().getMaxStackSize();
|
|
}
|
|
@@ -457,6 +509,7 @@ public final class ItemStack {
|
|
|
|
public void setTag(NBTTagCompound nbttagcompound) {
|
|
this.tag = nbttagcompound;
|
|
+ validateSkullSkin(); // Spigot
|
|
}
|
|
|
|
public String getName() {
|
|
diff --git a/src/main/java/net/minecraft/server/TileEntitySkull.java b/src/main/java/net/minecraft/server/TileEntitySkull.java
|
|
index 2a50db9..c95e4c8 100644
|
|
--- a/src/main/java/net/minecraft/server/TileEntitySkull.java
|
|
+++ b/src/main/java/net/minecraft/server/TileEntitySkull.java
|
|
@@ -6,11 +6,61 @@ import net.minecraft.util.com.google.common.collect.Iterables;
|
|
import net.minecraft.util.com.mojang.authlib.GameProfile;
|
|
import net.minecraft.util.com.mojang.authlib.properties.Property;
|
|
|
|
+// Spigot start
|
|
+import com.google.common.cache.Cache;
|
|
+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 net.minecraft.util.com.mojang.authlib.Agent;
|
|
+// Spigot end
|
|
+
|
|
public class TileEntitySkull extends TileEntity {
|
|
|
|
private int a;
|
|
private int i;
|
|
private GameProfile j = null;
|
|
+ // Spigot start
|
|
+ public static final Executor executor = Executors.newFixedThreadPool(3,
|
|
+ new ThreadFactoryBuilder()
|
|
+ .setNameFormat("Head Conversion Thread - %1$d")
|
|
+ .build()
|
|
+ );
|
|
+ public static final Cache<String, GameProfile> skinCache = CacheBuilder.newBuilder()
|
|
+ .maximumSize( 5000 )
|
|
+ .expireAfterAccess( 60, TimeUnit.MINUTES )
|
|
+ .build( new CacheLoader<String, GameProfile>()
|
|
+ {
|
|
+ @Override
|
|
+ public GameProfile load(String key) throws Exception
|
|
+ {
|
|
+ GameProfile[] profiles = new GameProfile[1];
|
|
+ GameProfileLookup gameProfileLookup = new GameProfileLookup(profiles);
|
|
+
|
|
+ MinecraftServer.getServer().getGameProfileRepository().findProfilesByNames(new String[] { key }, Agent.MINECRAFT, gameProfileLookup);
|
|
+ if (!MinecraftServer.getServer().getOnlineMode() && profiles[0] == null) {
|
|
+ UUID uuid = EntityHuman.a(new GameProfile(null, key));
|
|
+ GameProfile profile = new GameProfile(uuid, key);
|
|
+
|
|
+ gameProfileLookup.onProfileLookupSucceeded(profile);
|
|
+ }
|
|
+
|
|
+ GameProfile profile = profiles[0];
|
|
+
|
|
+ Property property = Iterables.getFirst(profile.getProperties().get("textures"), null);
|
|
+
|
|
+ if (property == null) {
|
|
+ profile = MinecraftServer.getServer().av().fillProfileProperties(profile, true);
|
|
+ }
|
|
+
|
|
+
|
|
+ return profile;
|
|
+ }
|
|
+ } );
|
|
+ // Spigot end
|
|
|
|
public TileEntitySkull() {}
|
|
|
|
@@ -66,18 +116,38 @@ public class TileEntitySkull extends TileEntity {
|
|
private void d() {
|
|
if (this.j != null && !UtilColor.b(this.j.getName())) {
|
|
if (!this.j.isComplete() || !this.j.getProperties().containsKey("textures")) {
|
|
- GameProfile gameprofile = MinecraftServer.getServer().getUserCache().getProfile(this.j.getName());
|
|
-
|
|
- if (gameprofile != null) {
|
|
- Property property = (Property) Iterables.getFirst(gameprofile.getProperties().get("textures"), null);
|
|
-
|
|
- if (property == null) {
|
|
- gameprofile = MinecraftServer.getServer().av().fillProfileProperties(gameprofile, true);
|
|
+ // Spigot start - Handle async
|
|
+ final String name = this.j.getName();
|
|
+ setSkullType( 0 ); // Work around a client bug
|
|
+ executor.execute(new Runnable() {
|
|
+ @Override
|
|
+ public void run() {
|
|
+
|
|
+ GameProfile profile = skinCache.getUnchecked( name.toLowerCase() );
|
|
+
|
|
+ if (profile != null) {
|
|
+ final GameProfile finalProfile = profile;
|
|
+ MinecraftServer.getServer().processQueue.add(new Runnable() {
|
|
+ @Override
|
|
+ public void run() {
|
|
+ a = 3;
|
|
+ j = finalProfile;
|
|
+ world.notify( x, y, z );
|
|
+ }
|
|
+ });
|
|
+ } else {
|
|
+ MinecraftServer.getServer().processQueue.add(new Runnable() {
|
|
+ @Override
|
|
+ public void run() {
|
|
+ a = 3;
|
|
+ j = new GameProfile( null, name );
|
|
+ world.notify( x, y, z );
|
|
+ }
|
|
+ });
|
|
+ }
|
|
}
|
|
-
|
|
- this.j = gameprofile;
|
|
- this.update();
|
|
- }
|
|
+ });
|
|
+ // Spigot end
|
|
}
|
|
}
|
|
}
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java
|
|
index d648d05..e32bcb1 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java
|
|
@@ -46,13 +46,39 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta {
|
|
}
|
|
|
|
@Override
|
|
- void applyToItem(NBTTagCompound tag) {
|
|
+ void applyToItem(final NBTTagCompound tag) { // Spigot - make final
|
|
super.applyToItem(tag);
|
|
|
|
if (hasOwner()) {
|
|
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.executor.execute( new Runnable()
|
|
+ {
|
|
+ @Override
|
|
+ public void run()
|
|
+ {
|
|
+
|
|
+ final GameProfile profile = net.minecraft.server.TileEntitySkull.skinCache.getUnchecked( CraftMetaSkull.this.profile.getName().toLowerCase() );
|
|
+ if ( profile != null )
|
|
+ {
|
|
+ MinecraftServer.getServer().processQueue.add( new Runnable()
|
|
+ {
|
|
+ @Override
|
|
+ public void run()
|
|
+ {
|
|
+ NBTTagCompound owner = new NBTTagCompound();
|
|
+ GameProfileSerializer.serialize( owner, profile );
|
|
+ tag.set( SKULL_OWNER.NBT, owner );
|
|
+ }
|
|
+ } );
|
|
+ }
|
|
+ }
|
|
+ } );
|
|
+ // Spigot end
|
|
}
|
|
}
|
|
|
|
--
|
|
1.9.1
|
|
|