expose skin texture methods in api
This commit is contained in:
parent
c560fe597e
commit
2a1f44b1bb
11 changed files with 72 additions and 43 deletions
6
api/src/main/java/lol/pyr/znpcsplus/api/skin/Skin.java
Normal file
6
api/src/main/java/lol/pyr/znpcsplus/api/skin/Skin.java
Normal file
|
@ -0,0 +1,6 @@
|
|||
package lol.pyr.znpcsplus.api.skin;
|
||||
|
||||
public interface Skin {
|
||||
String getTexture();
|
||||
String getSignature();
|
||||
}
|
|
@ -1,4 +1,11 @@
|
|||
package lol.pyr.znpcsplus.api.skin;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public interface SkinDescriptor {
|
||||
CompletableFuture<? extends Skin> fetch(Player player);
|
||||
Skin fetchInstant(Player player);
|
||||
boolean supportsInstant(Player player);
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import lol.pyr.znpcsplus.api.entity.EntityPropertyRegistry;
|
|||
import lol.pyr.znpcsplus.api.skin.SkinDescriptor;
|
||||
import lol.pyr.znpcsplus.conversion.citizens.model.SectionCitizensTrait;
|
||||
import lol.pyr.znpcsplus.npc.NpcImpl;
|
||||
import lol.pyr.znpcsplus.skin.Skin;
|
||||
import lol.pyr.znpcsplus.skin.SkinImpl;
|
||||
import lol.pyr.znpcsplus.skin.descriptor.PrefetchedDescriptor;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
@ -21,7 +21,7 @@ public class SkinTrait extends SectionCitizensTrait {
|
|||
public @NotNull NpcImpl apply(NpcImpl npc, ConfigurationSection section) {
|
||||
String texture = section.getString("textureRaw");
|
||||
String signature = section.getString("signature");
|
||||
if (texture != null && signature != null) npc.setProperty(registry.getByName("skin", SkinDescriptor.class), new PrefetchedDescriptor(new Skin(texture, signature)));
|
||||
if (texture != null && signature != null) npc.setProperty(registry.getByName("skin", SkinDescriptor.class), new PrefetchedDescriptor(new SkinImpl(texture, signature)));
|
||||
return npc;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ import lol.pyr.znpcsplus.npc.NpcImpl;
|
|||
import lol.pyr.znpcsplus.npc.NpcTypeRegistryImpl;
|
||||
import lol.pyr.znpcsplus.packets.PacketFactory;
|
||||
import lol.pyr.znpcsplus.scheduling.TaskScheduler;
|
||||
import lol.pyr.znpcsplus.skin.Skin;
|
||||
import lol.pyr.znpcsplus.skin.SkinImpl;
|
||||
import lol.pyr.znpcsplus.skin.cache.MojangSkinCache;
|
||||
import lol.pyr.znpcsplus.skin.descriptor.FetchingDescriptor;
|
||||
import lol.pyr.znpcsplus.skin.descriptor.MirrorDescriptor;
|
||||
|
@ -36,7 +36,6 @@ import lol.pyr.znpcsplus.util.LookType;
|
|||
import lol.pyr.znpcsplus.util.NpcLocation;
|
||||
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
import org.bukkit.DyeColor;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
@ -130,7 +129,7 @@ public class ZNpcImporter implements DataImporter {
|
|||
npc.setProperty(propertyRegistry.getByName("skin", SkinDescriptor.class), new FetchingDescriptor(skinCache, model.getSkinName()));
|
||||
}
|
||||
else if (model.getSkin() != null && model.getSignature() != null) {
|
||||
npc.setProperty(propertyRegistry.getByName("skin", SkinDescriptor.class), new PrefetchedDescriptor(new Skin(model.getSkin(), model.getSignature())));
|
||||
npc.setProperty(propertyRegistry.getByName("skin", SkinDescriptor.class), new PrefetchedDescriptor(new SkinImpl(model.getSkin(), model.getSignature())));
|
||||
}
|
||||
|
||||
Map<String, Object> toggleValues = model.getNpcToggleValues();
|
||||
|
|
|
@ -13,8 +13,8 @@ import java.util.List;
|
|||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public interface BaseSkinDescriptor extends SkinDescriptor {
|
||||
CompletableFuture<Skin> fetch(Player player);
|
||||
Skin fetchInstant(Player player);
|
||||
CompletableFuture<SkinImpl> fetch(Player player);
|
||||
SkinImpl fetchInstant(Player player);
|
||||
boolean supportsInstant(Player player);
|
||||
String serialize();
|
||||
|
||||
|
@ -27,7 +27,7 @@ public interface BaseSkinDescriptor extends SkinDescriptor {
|
|||
for (int i = 0; i < (arr.length - 1) / 3; i++) {
|
||||
properties.add(new TextureProperty(arr[i + 1], arr[i + 2], arr[i + 3]));
|
||||
}
|
||||
return new PrefetchedDescriptor(new Skin(properties));
|
||||
return new PrefetchedDescriptor(new SkinImpl(properties));
|
||||
}
|
||||
throw new IllegalArgumentException("Unknown SkinDescriptor type!");
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ public class SkinDescriptorFactoryImpl implements SkinDescriptorFactory {
|
|||
|
||||
@Override
|
||||
public SkinDescriptor createStaticDescriptor(String texture, String signature) {
|
||||
return new PrefetchedDescriptor(new Skin(texture, signature));
|
||||
return new PrefetchedDescriptor(new SkinImpl(texture, signature));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -6,6 +6,7 @@ import com.github.retrooper.packetevents.protocol.player.TextureProperty;
|
|||
import com.github.retrooper.packetevents.protocol.player.UserProfile;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import lol.pyr.znpcsplus.api.skin.Skin;
|
||||
import lol.pyr.znpcsplus.reflection.Reflections;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
@ -13,21 +14,21 @@ import java.util.ArrayList;
|
|||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class Skin {
|
||||
public class SkinImpl implements Skin {
|
||||
private final long timestamp = System.currentTimeMillis();
|
||||
private final List<TextureProperty> properties;
|
||||
private static final boolean V1_20_2 = PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_20_2);
|
||||
|
||||
public Skin(String texture, String signature) {
|
||||
public SkinImpl(String texture, String signature) {
|
||||
properties = new ArrayList<>(1);
|
||||
properties.add(new TextureProperty("textures", texture, signature));
|
||||
}
|
||||
|
||||
public Skin(Collection<TextureProperty> properties) {
|
||||
public SkinImpl(Collection<TextureProperty> properties) {
|
||||
this.properties = new ArrayList<>(properties);
|
||||
}
|
||||
|
||||
public Skin(Object propertyMap) {
|
||||
public SkinImpl(Object propertyMap) {
|
||||
this.properties = new ArrayList<>();
|
||||
try {
|
||||
Collection<?> properties = (Collection<?>) Reflections.PROPERTY_MAP_VALUES_METHOD.get().invoke(propertyMap);
|
||||
|
@ -51,7 +52,7 @@ public class Skin {
|
|||
}
|
||||
}
|
||||
|
||||
public Skin(JsonObject obj) {
|
||||
public SkinImpl(JsonObject obj) {
|
||||
properties = new ArrayList<>();
|
||||
for (JsonElement e : obj.get("properties").getAsJsonArray()) {
|
||||
JsonObject o = e.getAsJsonObject();
|
||||
|
@ -71,4 +72,20 @@ public class Skin {
|
|||
public boolean isExpired() {
|
||||
return System.currentTimeMillis() - timestamp > 60000L;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTexture() {
|
||||
for (TextureProperty property : properties)
|
||||
if (property.getName().equalsIgnoreCase("textures"))
|
||||
return property.getValue();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSignature() {
|
||||
for (TextureProperty property : properties)
|
||||
if (property.getName().equalsIgnoreCase("textures"))
|
||||
return property.getSignature();
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -4,7 +4,7 @@ import com.google.gson.JsonObject;
|
|||
import com.google.gson.JsonParser;
|
||||
import lol.pyr.znpcsplus.config.ConfigManager;
|
||||
import lol.pyr.znpcsplus.reflection.Reflections;
|
||||
import lol.pyr.znpcsplus.skin.Skin;
|
||||
import lol.pyr.znpcsplus.skin.SkinImpl;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
|
@ -24,7 +24,7 @@ public class MojangSkinCache {
|
|||
|
||||
private final ConfigManager configManager;
|
||||
|
||||
private final Map<String, Skin> cache = new ConcurrentHashMap<>();
|
||||
private final Map<String, SkinImpl> cache = new ConcurrentHashMap<>();
|
||||
private final Map<String, CachedId> idCache = new ConcurrentHashMap<>();
|
||||
|
||||
public MojangSkinCache(ConfigManager configManager) {
|
||||
|
@ -32,11 +32,11 @@ public class MojangSkinCache {
|
|||
}
|
||||
|
||||
public void cleanCache() {
|
||||
for (Map.Entry<String, Skin> entry : cache.entrySet()) if (entry.getValue().isExpired()) cache.remove(entry.getKey());
|
||||
for (Map.Entry<String, SkinImpl> entry : cache.entrySet()) if (entry.getValue().isExpired()) cache.remove(entry.getKey());
|
||||
for (Map.Entry<String, CachedId> entry : idCache.entrySet()) if (entry.getValue().isExpired()) cache.remove(entry.getKey());
|
||||
}
|
||||
|
||||
public CompletableFuture<Skin> fetchByName(String name) {
|
||||
public CompletableFuture<SkinImpl> fetchByName(String name) {
|
||||
Player player = Bukkit.getPlayerExact(name);
|
||||
if (player != null && player.isOnline()) return CompletableFuture.completedFuture(getFromPlayer(player));
|
||||
|
||||
|
@ -53,7 +53,7 @@ public class MojangSkinCache {
|
|||
if (obj.has("errorMessage")) return fetchByNameFallback(name).join();
|
||||
String id = obj.get("id").getAsString();
|
||||
idCache.put(name.toLowerCase(), new CachedId(id));
|
||||
Skin skin = fetchByUUID(id).join();
|
||||
SkinImpl skin = fetchByUUID(id).join();
|
||||
if (skin == null) return fetchByNameFallback(name).join();
|
||||
return skin;
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ public class MojangSkinCache {
|
|||
});
|
||||
}
|
||||
|
||||
public CompletableFuture<Skin> fetchByNameFallback(String name) {
|
||||
public CompletableFuture<SkinImpl> fetchByNameFallback(String name) {
|
||||
Player player = Bukkit.getPlayerExact(name);
|
||||
if (player != null && player.isOnline()) return CompletableFuture.completedFuture(getFromPlayer(player));
|
||||
|
||||
|
@ -89,7 +89,7 @@ public class MojangSkinCache {
|
|||
JsonObject textures = obj.get("textures").getAsJsonObject();
|
||||
String value = textures.get("raw").getAsJsonObject().get("value").getAsString();
|
||||
String signature = textures.get("raw").getAsJsonObject().get("signature").getAsString();
|
||||
Skin skin = new Skin(value, signature);
|
||||
SkinImpl skin = new SkinImpl(value, signature);
|
||||
cache.put(uuid, skin);
|
||||
return skin;
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ public class MojangSkinCache {
|
|||
});
|
||||
}
|
||||
|
||||
public CompletableFuture<Skin> fetchByUrl(URL url, String variant) {
|
||||
public CompletableFuture<SkinImpl> fetchByUrl(URL url, String variant) {
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
URL apiUrl = parseUrl("https://api.mineskin.org/generate/url");
|
||||
HttpURLConnection connection = null;
|
||||
|
@ -127,7 +127,7 @@ public class MojangSkinCache {
|
|||
if (obj.has("error")) return null;
|
||||
if (!obj.has("data")) return null;
|
||||
JsonObject texture = obj.get("data").getAsJsonObject().get("texture").getAsJsonObject();
|
||||
return new Skin(texture.get("value").getAsString(), texture.get("signature").getAsString());
|
||||
return new SkinImpl(texture.get("value").getAsString(), texture.get("signature").getAsString());
|
||||
}
|
||||
|
||||
} catch (IOException exception) {
|
||||
|
@ -147,26 +147,26 @@ public class MojangSkinCache {
|
|||
if (!idCache.containsKey(name)) return false;
|
||||
CachedId id = idCache.get(name);
|
||||
if (id.isExpired() || !cache.containsKey(id.getId())) return false;
|
||||
Skin skin = cache.get(id.getId());
|
||||
SkinImpl skin = cache.get(id.getId());
|
||||
return !skin.isExpired();
|
||||
}
|
||||
|
||||
public Skin getFullyCachedByName(String s) {
|
||||
public SkinImpl getFullyCachedByName(String s) {
|
||||
String name = s.toLowerCase();
|
||||
if (!idCache.containsKey(name)) return null;
|
||||
CachedId id = idCache.get(name);
|
||||
if (id.isExpired() || !cache.containsKey(id.getId())) return null;
|
||||
Skin skin = cache.get(id.getId());
|
||||
SkinImpl skin = cache.get(id.getId());
|
||||
if (skin.isExpired()) return null;
|
||||
return skin;
|
||||
}
|
||||
|
||||
public CompletableFuture<Skin> fetchByUUID(String uuid) {
|
||||
public CompletableFuture<SkinImpl> fetchByUUID(String uuid) {
|
||||
Player player = Bukkit.getPlayer(uuid);
|
||||
if (player != null && player.isOnline()) return CompletableFuture.completedFuture(getFromPlayer(player));
|
||||
|
||||
if (cache.containsKey(uuid)) {
|
||||
Skin skin = cache.get(uuid);
|
||||
SkinImpl skin = cache.get(uuid);
|
||||
if (!skin.isExpired()) return CompletableFuture.completedFuture(skin);
|
||||
}
|
||||
|
||||
|
@ -179,7 +179,7 @@ public class MojangSkinCache {
|
|||
try (Reader reader = new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8)) {
|
||||
JsonObject obj = JsonParser.parseReader(reader).getAsJsonObject();
|
||||
if (obj.has("errorMessage")) return null;
|
||||
Skin skin = new Skin(obj);
|
||||
SkinImpl skin = new SkinImpl(obj);
|
||||
cache.put(uuid, skin);
|
||||
return skin;
|
||||
}
|
||||
|
@ -195,12 +195,12 @@ public class MojangSkinCache {
|
|||
});
|
||||
}
|
||||
|
||||
public Skin getFromPlayer(Player player) {
|
||||
public SkinImpl getFromPlayer(Player player) {
|
||||
try {
|
||||
Object playerHandle = Reflections.GET_PLAYER_HANDLE_METHOD.get().invoke(player);
|
||||
Object gameProfile = Reflections.GET_PROFILE_METHOD.get().invoke(playerHandle);
|
||||
Object propertyMap = Reflections.GET_PROPERTY_MAP_METHOD.get().invoke(gameProfile);
|
||||
return new Skin(propertyMap);
|
||||
return new SkinImpl(propertyMap);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ package lol.pyr.znpcsplus.skin.descriptor;
|
|||
|
||||
import lol.pyr.znpcsplus.api.skin.SkinDescriptor;
|
||||
import lol.pyr.znpcsplus.skin.BaseSkinDescriptor;
|
||||
import lol.pyr.znpcsplus.skin.Skin;
|
||||
import lol.pyr.znpcsplus.skin.SkinImpl;
|
||||
import lol.pyr.znpcsplus.skin.cache.MojangSkinCache;
|
||||
import lol.pyr.znpcsplus.util.PapiUtil;
|
||||
import org.bukkit.entity.Player;
|
||||
|
@ -19,12 +19,12 @@ public class FetchingDescriptor implements BaseSkinDescriptor, SkinDescriptor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Skin> fetch(Player player) {
|
||||
public CompletableFuture<SkinImpl> fetch(Player player) {
|
||||
return skinCache.fetchByName(PapiUtil.set(player, name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Skin fetchInstant(Player player) {
|
||||
public SkinImpl fetchInstant(Player player) {
|
||||
return skinCache.getFullyCachedByName(PapiUtil.set(player, name));
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ package lol.pyr.znpcsplus.skin.descriptor;
|
|||
|
||||
import lol.pyr.znpcsplus.api.skin.SkinDescriptor;
|
||||
import lol.pyr.znpcsplus.skin.BaseSkinDescriptor;
|
||||
import lol.pyr.znpcsplus.skin.Skin;
|
||||
import lol.pyr.znpcsplus.skin.SkinImpl;
|
||||
import lol.pyr.znpcsplus.skin.cache.MojangSkinCache;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
|
@ -16,12 +16,12 @@ public class MirrorDescriptor implements BaseSkinDescriptor, SkinDescriptor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Skin> fetch(Player player) {
|
||||
public CompletableFuture<SkinImpl> fetch(Player player) {
|
||||
return CompletableFuture.completedFuture(skinCache.getFromPlayer(player));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Skin fetchInstant(Player player) {
|
||||
public SkinImpl fetchInstant(Player player) {
|
||||
return skinCache.getFromPlayer(player);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ package lol.pyr.znpcsplus.skin.descriptor;
|
|||
import com.github.retrooper.packetevents.protocol.player.TextureProperty;
|
||||
import lol.pyr.znpcsplus.api.skin.SkinDescriptor;
|
||||
import lol.pyr.znpcsplus.skin.BaseSkinDescriptor;
|
||||
import lol.pyr.znpcsplus.skin.Skin;
|
||||
import lol.pyr.znpcsplus.skin.SkinImpl;
|
||||
import lol.pyr.znpcsplus.skin.cache.MojangSkinCache;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
|
@ -11,9 +11,9 @@ import java.net.URL;
|
|||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class PrefetchedDescriptor implements BaseSkinDescriptor, SkinDescriptor {
|
||||
private final Skin skin;
|
||||
private final SkinImpl skin;
|
||||
|
||||
public PrefetchedDescriptor(Skin skin) {
|
||||
public PrefetchedDescriptor(SkinImpl skin) {
|
||||
this.skin = skin;
|
||||
}
|
||||
|
||||
|
@ -26,12 +26,12 @@ public class PrefetchedDescriptor implements BaseSkinDescriptor, SkinDescriptor
|
|||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Skin> fetch(Player player) {
|
||||
public CompletableFuture<SkinImpl> fetch(Player player) {
|
||||
return CompletableFuture.completedFuture(skin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Skin fetchInstant(Player player) {
|
||||
public SkinImpl fetchInstant(Player player) {
|
||||
return skin;
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,7 @@ public class PrefetchedDescriptor implements BaseSkinDescriptor, SkinDescriptor
|
|||
return true;
|
||||
}
|
||||
|
||||
public Skin getSkin() {
|
||||
public SkinImpl getSkin() {
|
||||
return skin;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue