Skip to content

Commit c57a850

Browse files
committed
use skull handler from CraftItem
1 parent eaec076 commit c57a850

File tree

1 file changed

+5
-262
lines changed

1 file changed

+5
-262
lines changed
Lines changed: 5 additions & 262 deletions
Original file line numberDiff line numberDiff line change
@@ -1,109 +1,25 @@
11
package me.hsgamer.bettergui.modifier;
22

3-
import com.google.gson.Gson;
4-
import com.google.gson.JsonObject;
5-
import com.mojang.authlib.GameProfile;
6-
import com.mojang.authlib.properties.Property;
3+
import io.github.projectunified.craftitem.spigot.skull.handler.SkullHandler;
74
import me.hsgamer.hscore.bukkit.item.modifier.ItemMetaModifier;
8-
import me.hsgamer.hscore.bukkit.utils.VersionUtils;
95
import me.hsgamer.hscore.common.StringReplacer;
10-
import me.hsgamer.hscore.common.Validate;
11-
import org.bukkit.Bukkit;
12-
import org.bukkit.Material;
13-
import org.bukkit.OfflinePlayer;
14-
import org.bukkit.inventory.ItemStack;
156
import org.bukkit.inventory.meta.ItemMeta;
167
import org.bukkit.inventory.meta.SkullMeta;
17-
import org.bukkit.profile.PlayerProfile;
18-
import org.bukkit.profile.PlayerTextures;
198
import org.jetbrains.annotations.NotNull;
209
import org.jetbrains.annotations.Nullable;
2110

22-
import java.lang.reflect.Field;
23-
import java.lang.reflect.Method;
24-
import java.net.URL;
25-
import java.nio.charset.StandardCharsets;
26-
import java.util.*;
27-
import java.util.concurrent.ConcurrentHashMap;
28-
import java.util.regex.Pattern;
11+
import java.util.UUID;
2912

30-
/**
31-
* This is a legacy modifier that was removed from HSCore.
32-
* I decide to keep it here for compatibility.
33-
*/
34-
@SuppressWarnings("deprecation")
3513
public class SkullModifier implements ItemMetaModifier {
36-
/**
37-
* <a href="https://github.com/CryptoMorin/XSeries/blob/b633d00608435701f1045a566b98a81edd5f923c/src/main/java/com/cryptomorin/xseries/profiles/objects/ProfileInputType.java#L29C35-L29C50">...</a>
38-
*/
39-
private static final Pattern MOJANG_SHA256_APPROX_PATTERN = Pattern.compile("[0-9a-z]{55,70}");
40-
/**
41-
* <a href="https://github.com/CryptoMorin/XSeries/blob/b11b176deca55da6d465e67a3d4be548c3ef06c6/src/main/java/com/cryptomorin/xseries/profiles/objects/ProfileInputType.java#L55C12-L55C57">...</a>
42-
*/
43-
private static final Pattern BASE64_PATTERN = Pattern.compile("[-A-Za-z0-9+/]{100,}={0,3}");
44-
private static final SkullMeta delegateSkullMeta;
45-
private static final SkullHandler skullHandler = getSkullHandler();
46-
47-
static {
48-
ItemStack itemStack;
49-
if (VersionUtils.isAtLeast(13)) {
50-
itemStack = new ItemStack(Material.valueOf("PLAYER_HEAD"));
51-
} else {
52-
itemStack = new ItemStack(Material.valueOf("SKULL_ITEM"));
53-
itemStack.setDurability((short) 3);
54-
}
55-
delegateSkullMeta = (SkullMeta) Objects.requireNonNull(itemStack.getItemMeta());
56-
}
14+
private static final SkullHandler skullHandler = SkullHandler.getInstance();
5715

5816
private String skullString = "";
5917

60-
private static SkullHandler getSkullHandler() {
61-
try {
62-
Class.forName("org.bukkit.profile.PlayerProfile");
63-
return new NewSkullHandler();
64-
} catch (ClassNotFoundException e) {
65-
return new OldSkullHandler();
66-
}
67-
}
68-
69-
private static void setSkull(SkullMeta meta, String skull) {
70-
Optional<URL> url = Validate.getURL(skull);
71-
if (url.isPresent()) {
72-
skullHandler.setSkullByURL(meta, url.get());
73-
return;
74-
}
75-
76-
if (MOJANG_SHA256_APPROX_PATTERN.matcher(skull).matches()) {
77-
skullHandler.setSkullByURL(meta, "https://textures.minecraft.net/texture/" + skull);
78-
return;
79-
}
80-
81-
if (BASE64_PATTERN.matcher(skull).matches()) {
82-
skullHandler.setSkullByBase64(meta, skull);
83-
return;
84-
}
85-
86-
Optional<UUID> uuid = Validate.getUUID(skull);
87-
if (uuid.isPresent()) {
88-
skullHandler.setSkullByUUID(meta, uuid.get());
89-
return;
90-
}
91-
92-
skullHandler.setSkullByName(meta, skull);
93-
}
94-
95-
private static SkullMeta getSkullMeta(String skull) {
96-
SkullMeta meta = delegateSkullMeta.clone();
97-
setSkull(meta, skull);
98-
return meta;
99-
}
100-
10118
@Override
10219
public @NotNull ItemMeta modifyMeta(@NotNull ItemMeta meta, @Nullable UUID uuid, @NotNull StringReplacer stringReplacer) {
103-
if (!(meta instanceof SkullMeta)) {
104-
return meta;
20+
if (meta instanceof SkullMeta && !skullString.isEmpty()) {
21+
skullHandler.setSkull((SkullMeta) meta, stringReplacer.replaceOrOriginal(skullString, uuid));
10522
}
106-
setSkull((SkullMeta) meta, stringReplacer.replaceOrOriginal(skullString, uuid));
10723
return meta;
10824
}
10925

@@ -125,177 +41,4 @@ public Object toObject() {
12541
public void loadFromObject(Object object) {
12642
this.skullString = String.valueOf(object);
12743
}
128-
129-
private interface SkullHandler {
130-
@SuppressWarnings("deprecation")
131-
default void setSkullByName(SkullMeta meta, String name) {
132-
setSkullByPlayer(meta, Bukkit.getOfflinePlayer(name));
133-
}
134-
135-
default void setSkullByUUID(SkullMeta meta, UUID uuid) {
136-
setSkullByPlayer(meta, Bukkit.getOfflinePlayer(uuid));
137-
}
138-
139-
void setSkullByPlayer(SkullMeta meta, OfflinePlayer player);
140-
141-
void setSkullByURL(SkullMeta meta, URL url);
142-
143-
default void setSkullByURL(SkullMeta meta, String url) {
144-
try {
145-
setSkullByURL(meta, new URL(url));
146-
} catch (Exception e) {
147-
throw new RuntimeException(e);
148-
}
149-
}
150-
151-
void setSkullByBase64(SkullMeta meta, String base64);
152-
153-
String getSkullValue(SkullMeta meta);
154-
}
155-
156-
private static class OldSkullHandler implements SkullHandler {
157-
private final Map<String, GameProfile> cache = new ConcurrentHashMap<>();
158-
private final Method getProfileMethod;
159-
160-
private OldSkullHandler() {
161-
Method method = null;
162-
try {
163-
//noinspection JavaReflectionMemberAccess
164-
method = Property.class.getDeclaredMethod("value");
165-
} catch (Exception e) {
166-
try {
167-
//noinspection JavaReflectionMemberAccess
168-
method = Property.class.getDeclaredMethod("getValue");
169-
} catch (NoSuchMethodException ex) {
170-
// IGNORE
171-
}
172-
}
173-
getProfileMethod = method;
174-
}
175-
176-
@SuppressWarnings("deprecation")
177-
@Override
178-
public void setSkullByPlayer(SkullMeta meta, OfflinePlayer player) {
179-
if (VersionUtils.isAtLeast(12)) {
180-
meta.setOwningPlayer(player);
181-
} else {
182-
meta.setOwner(player.getName());
183-
}
184-
}
185-
186-
private void setSkullByGameProfile(SkullMeta meta, GameProfile profile) {
187-
try {
188-
Method setProfile = meta.getClass().getMethod("setProfile", GameProfile.class);
189-
setProfile.setAccessible(true);
190-
setProfile.invoke(meta, profile);
191-
} catch (Exception e) {
192-
try {
193-
Field profileField = meta.getClass().getDeclaredField("profile");
194-
profileField.setAccessible(true);
195-
profileField.set(meta, profile);
196-
} catch (Exception ignored) {
197-
// IGNORE
198-
}
199-
}
200-
}
201-
202-
@Override
203-
public void setSkullByURL(SkullMeta meta, URL url) {
204-
GameProfile profile = cache.computeIfAbsent(url.toString(), url1 -> {
205-
GameProfile gameProfile = new GameProfile(UUID.randomUUID(), "");
206-
gameProfile.getProperties().put("textures", new Property("textures", Base64.getEncoder().encodeToString(String.format("{textures:{SKIN:{url:\"%s\"}}}", url1).getBytes())));
207-
return gameProfile;
208-
});
209-
setSkullByGameProfile(meta, profile);
210-
}
211-
212-
@Override
213-
public void setSkullByBase64(SkullMeta meta, String base64) {
214-
GameProfile gameProfile = cache.computeIfAbsent(base64, b -> {
215-
GameProfile profile = new GameProfile(UUID.randomUUID(), "");
216-
profile.getProperties().put("textures", new Property("textures", b));
217-
return profile;
218-
});
219-
setSkullByGameProfile(meta, gameProfile);
220-
}
221-
222-
@Override
223-
public String getSkullValue(SkullMeta meta) {
224-
GameProfile profile;
225-
try {
226-
Field profileField = meta.getClass().getDeclaredField("profile");
227-
profileField.setAccessible(true);
228-
profile = (GameProfile) profileField.get(meta);
229-
} catch (Exception e) {
230-
return "";
231-
}
232-
233-
Collection<Property> properties = profile.getProperties().get("textures");
234-
if (properties == null || properties.isEmpty()) {
235-
return "";
236-
}
237-
238-
for (Property property : properties) {
239-
String value;
240-
try {
241-
value = (String) getProfileMethod.invoke(property);
242-
} catch (Exception e) {
243-
continue;
244-
}
245-
246-
if (!value.isEmpty()) {
247-
return value;
248-
}
249-
}
250-
return "";
251-
}
252-
}
253-
254-
private static class NewSkullHandler implements SkullHandler {
255-
private final Map<String, PlayerProfile> profileMap = new ConcurrentHashMap<>();
256-
257-
@Override
258-
public void setSkullByPlayer(SkullMeta meta, OfflinePlayer player) {
259-
meta.setOwningPlayer(player);
260-
}
261-
262-
@Override
263-
public void setSkullByURL(SkullMeta meta, URL url) {
264-
PlayerProfile profile = profileMap.computeIfAbsent(url.toString(), u -> {
265-
PlayerProfile newProfile = Bukkit.createPlayerProfile(UUID.randomUUID(), "");
266-
PlayerTextures textures = newProfile.getTextures();
267-
textures.setSkin(url);
268-
return newProfile;
269-
});
270-
meta.setOwnerProfile(profile);
271-
}
272-
273-
@Override
274-
public void setSkullByBase64(SkullMeta meta, String base64) {
275-
try {
276-
String decoded = new String(Base64.getDecoder().decode(base64), StandardCharsets.UTF_8);
277-
JsonObject json = new Gson().fromJson(decoded, JsonObject.class);
278-
String url = json.getAsJsonObject("textures").getAsJsonObject("SKIN").get("url").getAsString();
279-
setSkullByURL(meta, url);
280-
} catch (Exception e) {
281-
throw new RuntimeException(e);
282-
}
283-
}
284-
285-
@Override
286-
public String getSkullValue(SkullMeta meta) {
287-
PlayerProfile profile = meta.getOwnerProfile();
288-
if (profile == null) {
289-
return "";
290-
}
291-
292-
PlayerTextures textures = profile.getTextures();
293-
URL url = textures.getSkin();
294-
if (url == null) {
295-
return "";
296-
}
297-
298-
return url.toString();
299-
}
300-
}
30144
}

0 commit comments

Comments
 (0)