Commits
md_5 authored bb614f84146
1 - | From 216a5be97ac0a288850345b677a787dfd98dcfd2 Mon Sep 17 00:00:00 2001 |
1 + | From 292bf189c31ce52e14f8d724767a5ea534a91a45 Mon Sep 17 00:00:00 2001 |
2 2 | From: Thinkofdeath <thethinkofdeath@gmail.com> |
3 3 | Date: Sun, 20 Apr 2014 13:18:55 +0100 |
4 4 | Subject: [PATCH] Convert player skulls async |
5 5 | |
6 6 | |
7 7 | diff --git a/src/main/java/net/minecraft/server/ItemSkull.java b/src/main/java/net/minecraft/server/ItemSkull.java |
8 - | index cbb902f50..bd99b5a18 100644 |
8 + | index cbb902f50..ca33c9c13 100644 |
9 9 | --- a/src/main/java/net/minecraft/server/ItemSkull.java |
10 10 | +++ b/src/main/java/net/minecraft/server/ItemSkull.java |
11 11 | |
12 12 | return super.b(itemstack); |
13 13 | } |
14 14 | |
15 15 | - public boolean a(NBTTagCompound nbttagcompound) { |
16 16 | + public boolean a(final NBTTagCompound nbttagcompound) { // Spigot - make final |
17 17 | super.a(nbttagcompound); |
18 18 | if (nbttagcompound.hasKeyOfType("SkullOwner", 8) && !StringUtils.isBlank(nbttagcompound.getString("SkullOwner"))) { |
19 19 | GameProfile gameprofile = new GameProfile((UUID) null, nbttagcompound.getString("SkullOwner")); |
20 20 | |
21 21 | - gameprofile = TileEntitySkull.b(gameprofile); |
22 22 | - nbttagcompound.set("SkullOwner", GameProfileSerializer.serialize(new NBTTagCompound(), gameprofile)); |
23 23 | + // Spigot start |
24 24 | + TileEntitySkull.b(gameprofile, new com.google.common.base.Predicate<GameProfile>() { |
25 25 | + |
26 26 | + @Override |
27 27 | + public boolean apply(GameProfile gameprofile) { |
28 - | + nbttagcompound.set("SkullOwner", GameProfileSerializer.serialize(new NBTTagCompound(), gameprofile)); |
28 + | + nbttagcompound.set("SkullOwner", GameProfileSerializer.serialize(new NBTTagCompound(), gameprofile)); |
29 29 | + return false; |
30 30 | + } |
31 31 | + }); |
32 32 | + // Spigot end |
33 33 | return true; |
34 34 | } else { |
35 35 | // CraftBukkit start |
36 36 | diff --git a/src/main/java/net/minecraft/server/TileEntitySkull.java b/src/main/java/net/minecraft/server/TileEntitySkull.java |
37 - | index 223e2ed2d..fd08e0bdc 100644 |
37 + | index 223e2ed2d..1e3c687d6 100644 |
38 38 | --- a/src/main/java/net/minecraft/server/TileEntitySkull.java |
39 39 | +++ b/src/main/java/net/minecraft/server/TileEntitySkull.java |
40 - | |
40 + | |
41 41 | import java.util.UUID; |
42 42 | import javax.annotation.Nullable; |
43 43 | |
44 44 | +// Spigot start |
45 45 | +import com.google.common.base.Predicate; |
46 46 | +import com.google.common.cache.LoadingCache; |
47 47 | +import com.google.common.cache.CacheBuilder; |
48 48 | +import com.google.common.cache.CacheLoader; |
49 - | +import java.util.concurrent.Executor; |
49 + | +import com.google.common.util.concurrent.Futures; |
50 50 | +import java.util.concurrent.Executors; |
51 + | +import java.util.concurrent.ExecutorService; |
52 + | +import java.util.concurrent.Future; |
51 53 | +import java.util.concurrent.TimeUnit; |
52 54 | + |
53 55 | +import com.google.common.util.concurrent.ThreadFactoryBuilder; |
54 56 | +import com.mojang.authlib.Agent; |
55 57 | +import com.mojang.authlib.ProfileLookupCallback; |
58 + | +import java.util.concurrent.Callable; |
56 59 | +// Spigot end |
57 60 | + |
58 61 | public class TileEntitySkull extends TileEntity implements ITickable { |
59 62 | |
60 63 | private int a; |
61 - | |
64 + | |
62 65 | private boolean i; |
63 66 | private static UserCache j; |
64 67 | private static MinecraftSessionService k; |
65 68 | + // Spigot start |
66 - | + public static final Executor executor = Executors.newFixedThreadPool(3, |
69 + | + public static final ExecutorService executor = Executors.newFixedThreadPool(3, |
67 70 | + new ThreadFactoryBuilder() |
68 71 | + .setNameFormat("Head Conversion Thread - %1$d") |
69 72 | + .build() |
70 73 | + ); |
71 74 | + public static final LoadingCache<String, GameProfile> skinCache = CacheBuilder.newBuilder() |
72 75 | + .maximumSize( 5000 ) |
73 76 | + .expireAfterAccess( 60, TimeUnit.MINUTES ) |
74 77 | + .build( new CacheLoader<String, GameProfile>() |
75 78 | + { |
76 79 | + @Override |
110 113 | + } |
111 114 | + |
112 115 | + |
113 116 | + return profile; |
114 117 | + } |
115 118 | + } ); |
116 119 | + // Spigot end |
117 120 | |
118 121 | public TileEntitySkull() {} |
119 122 | |
120 - | |
123 + | |
121 124 | } |
122 125 | |
123 126 | private void i() { |
124 127 | - this.g = b(this.g); |
125 128 | - this.update(); |
126 129 | + // Spigot start |
127 130 | + GameProfile profile = this.g; |
128 131 | + setSkullType( 0 ); // Work around client bug |
129 132 | + b(profile, new Predicate<GameProfile>() { |
130 133 | + |
137 140 | + world.m(position); // PAIL: notify |
138 141 | + } |
139 142 | + return false; |
140 143 | + } |
141 144 | + }); |
142 145 | + // Spigot end |
143 146 | } |
144 147 | |
145 148 | - public static GameProfile b(GameProfile gameprofile) { |
146 149 | + // Spigot start - Support async lookups |
147 - | + public static void b(final GameProfile gameprofile, final Predicate<GameProfile> callback) { |
150 + | + public static Future<GameProfile> b(final GameProfile gameprofile, final Predicate<GameProfile> callback) { |
148 151 | if (gameprofile != null && !UtilColor.b(gameprofile.getName())) { |
149 152 | if (gameprofile.isComplete() && gameprofile.getProperties().containsKey("textures")) { |
150 153 | - return gameprofile; |
151 154 | - } else if (TileEntitySkull.j != null && TileEntitySkull.k != null) { |
152 155 | - GameProfile gameprofile1 = TileEntitySkull.j.getProfile(gameprofile.getName()); |
153 - | - |
154 - | - if (gameprofile1 == null) { |
155 - | - return gameprofile; |
156 156 | + callback.apply(gameprofile); |
157 157 | + } else if (MinecraftServer.getServer() == null) { |
158 158 | + callback.apply(gameprofile); |
159 159 | + } else { |
160 160 | + GameProfile profile = skinCache.getIfPresent(gameprofile.getName().toLowerCase(java.util.Locale.ROOT)); |
161 161 | + if (profile != null && Iterables.getFirst(profile.getProperties().get("textures"), (Object) null) != null) { |
162 162 | + callback.apply(profile); |
163 + | |
164 + | - if (gameprofile1 == null) { |
165 + | - return gameprofile; |
166 + | + return Futures.immediateFuture(profile); |
163 167 | } else { |
164 168 | - Property property = (Property) Iterables.getFirst(gameprofile1.getProperties().get("textures"), (Object) null); |
165 169 | - |
166 170 | - if (property == null) { |
167 171 | - gameprofile1 = TileEntitySkull.k.fillProfileProperties(gameprofile1, true); |
168 172 | - } |
169 173 | - |
170 174 | - return gameprofile1; |
171 - | + executor.execute(new Runnable() { |
175 + | + return executor.submit(new Callable<GameProfile>() { |
172 176 | + @Override |
173 - | + public void run() { |
177 + | + public GameProfile call() { |
174 178 | + final GameProfile profile = skinCache.getUnchecked(gameprofile.getName().toLowerCase(java.util.Locale.ROOT)); |
175 179 | + MinecraftServer.getServer().processQueue.add(new Runnable() { |
176 180 | + @Override |
177 181 | + public void run() { |
178 182 | + if (profile == null) { |
179 183 | + callback.apply(gameprofile); |
180 184 | + } else { |
181 185 | + callback.apply(profile); |
182 186 | + } |
183 187 | + } |
184 188 | + }); |
189 + | + return profile; |
185 190 | + } |
186 191 | + }); |
187 192 | } |
188 193 | - } else { |
189 194 | - return gameprofile; |
190 195 | } |
191 196 | } else { |
192 197 | - return gameprofile; |
193 198 | + callback.apply(gameprofile); |
194 199 | } |
200 + | + |
201 + | + return Futures.immediateFuture(gameprofile); |
195 202 | } |
196 203 | + // Spigot end |
197 204 | |
198 205 | public int getSkullType() { |
199 206 | return this.a; |
200 207 | diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java |
201 - | index fbc16890c..4976eb26a 100644 |
208 + | index 8c5d3effc..8a58615f8 100644 |
202 209 | --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java |
203 210 | +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java |
204 - | |
205 - | import net.minecraft.server.GameProfileSerializer; |
206 - | import net.minecraft.server.NBTBase; |
207 - | import net.minecraft.server.NBTTagCompound; |
208 - | +import net.minecraft.server.TileEntitySkull; |
209 - | |
210 - | import org.bukkit.Bukkit; |
211 - | import org.bukkit.Material; |
212 - | |
213 - | } |
214 - | |
215 - | @Override |
216 - | - void applyToItem(NBTTagCompound tag) { |
217 - | + void applyToItem(final NBTTagCompound tag) { // Spigot - make final |
218 - | super.applyToItem(tag); |
211 + | |
219 212 | |
220 213 | if (profile != null) { |
214 + | // Fill in textures |
215 + | - profile = TileEntitySkull.b(profile); |
216 + | + // Must be done sync due to way client handles textures |
217 + | + profile = com.google.common.util.concurrent.Futures.getUnchecked(TileEntitySkull.b(profile, com.google.common.base.Predicates.alwaysTrue())); // Spigot |
218 + | |
221 219 | NBTTagCompound owner = new NBTTagCompound(); |
222 220 | GameProfileSerializer.serialize(owner, profile); |
223 - | - tag.set(SKULL_OWNER.NBT, owner); |
224 - | + tag.set( SKULL_OWNER.NBT, owner ); |
225 - | + // Spigot start - do an async lookup of the profile. |
226 - | + // Unfortunately there is not way to refresh the holding |
227 - | + // inventory, so that responsibility is left to the user. |
228 - | + net.minecraft.server.TileEntitySkull.b(profile, new com.google.common.base.Predicate<GameProfile>() { |
229 - | + |
230 - | + @Override |
231 - | + public boolean apply(GameProfile input) { |
232 - | + NBTTagCompound owner = new NBTTagCompound(); |
233 - | + GameProfileSerializer.serialize( owner, input ); |
234 - | + tag.set( SKULL_OWNER.NBT, owner ); |
235 - | + return false; |
236 - | + } |
237 - | + }); |
238 - | + // Spigot end |
239 - | } |
240 - | } |
241 - | |
242 - | |
243 - | if (name == null) { |
244 - | profile = null; |
245 - | } else { |
246 - | - profile = new GameProfile(null, name); |
247 - | + // Spigot start |
248 - | + profile = TileEntitySkull.skinCache.getIfPresent(name.toLowerCase(java.util.Locale.ROOT)); |
249 - | + if (profile == null) profile = new GameProfile(null, name); |
250 - | + // Spigot end |
251 - | } |
252 - | |
253 - | return true; |
254 221 | -- |
255 222 | 2.14.1 |
256 223 | |