Merge pull request #78 from D3v1s0m/modular-property-system
Added url skin type
This commit is contained in:
commit
fff8d7435a
8 changed files with 110 additions and 13 deletions
|
@ -1,8 +1,13 @@
|
|||
package lol.pyr.znpcsplus.api.skin;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
public interface SkinDescriptorFactory {
|
||||
SkinDescriptor createMirrorDescriptor();
|
||||
SkinDescriptor createRefreshingDescriptor(String playerName);
|
||||
SkinDescriptor createStaticDescriptor(String playerName);
|
||||
SkinDescriptor createStaticDescriptor(String texture, String signature);
|
||||
SkinDescriptor createUrlDescriptor(String url) throws MalformedURLException;
|
||||
SkinDescriptor createUrlDescriptor(URL url);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@ import lol.pyr.znpcsplus.skin.descriptor.PrefetchedDescriptor;
|
|||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -44,9 +46,7 @@ public class SkinCommand implements CommandHandler {
|
|||
npc.setProperty(propertyRegistry.getByName("skin", SkinDescriptor.class), new MirrorDescriptor(skinCache));
|
||||
npc.respawn();
|
||||
context.halt(Component.text("The NPC's skin will now mirror the player that it's being displayed to", NamedTextColor.GREEN));
|
||||
}
|
||||
|
||||
if (type.equalsIgnoreCase("static")) {
|
||||
} else if (type.equalsIgnoreCase("static")) {
|
||||
context.ensureArgsNotEmpty();
|
||||
String name = context.dumpAllArgs();
|
||||
context.send(Component.text("Fetching skin \"" + name + "\"...", NamedTextColor.GREEN));
|
||||
|
@ -57,25 +57,42 @@ public class SkinCommand implements CommandHandler {
|
|||
}
|
||||
npc.setProperty(propertyRegistry.getByName("skin", SkinDescriptor.class), skin);
|
||||
npc.respawn();
|
||||
context.send(Component.text("The NPC's skin has been set to \"" + name + "\""));
|
||||
context.send(Component.text("The NPC's skin has been set to \"" + name + "\"", NamedTextColor.GREEN));
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (type.equalsIgnoreCase("dynamic")) {
|
||||
} else if (type.equalsIgnoreCase("dynamic")) {
|
||||
context.ensureArgsNotEmpty();
|
||||
String name = context.dumpAllArgs();
|
||||
npc.setProperty(propertyRegistry.getByName("skin", SkinDescriptor.class), new FetchingDescriptor(skinCache, name));
|
||||
npc.respawn();
|
||||
context.halt(Component.text("The NPC's skin will now be resolved per-player from \"" + name + "\""));
|
||||
} else if (type.equalsIgnoreCase("url")) {
|
||||
context.ensureArgsNotEmpty();
|
||||
String urlString = context.dumpAllArgs();
|
||||
try {
|
||||
URL url = new URL(urlString);
|
||||
context.send(Component.text("Fetching skin from url \"" + urlString + "\"...", NamedTextColor.GREEN));
|
||||
PrefetchedDescriptor.fromUrl(skinCache, url).thenAccept(skin -> {
|
||||
if (skin.getSkin() == null) {
|
||||
context.send(Component.text("Failed to fetch skin, are you sure the url is valid?", NamedTextColor.RED));
|
||||
return;
|
||||
}
|
||||
context.send(Component.text("Unknown skin type! Please use one of the following: mirror, static, dynamic"));
|
||||
npc.setProperty(propertyRegistry.getByName("skin", SkinDescriptor.class), skin);
|
||||
npc.respawn();
|
||||
context.send(Component.text("The NPC's skin has been set.", NamedTextColor.GREEN));
|
||||
});
|
||||
} catch (MalformedURLException e) {
|
||||
context.send(Component.text("Invalid url!", NamedTextColor.RED));
|
||||
}
|
||||
return;
|
||||
}
|
||||
context.send(Component.text("Unknown skin type! Please use one of the following: mirror, static, dynamic, url"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> suggest(CommandContext context) throws CommandExecutionException {
|
||||
if (context.argSize() == 1) return context.suggestCollection(npcRegistry.getModifiableIds());
|
||||
if (context.argSize() == 2) return context.suggestLiteral("mirror", "static", "dynamic");
|
||||
if (context.argSize() == 2) return context.suggestLiteral("mirror", "static", "dynamic", "url");
|
||||
if (context.matchSuggestion("*", "static")) return context.suggestPlayers();
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
|
|
@ -254,6 +254,7 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
|
|||
register(new GlowProperty(packetFactory));
|
||||
register(new EffectsProperty("fire", 0x01));
|
||||
register(new EffectsProperty("invisible", 0x20));
|
||||
register(new SkinProperty());
|
||||
}
|
||||
|
||||
private void registerSerializer(PropertySerializer<?> serializer) {
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
package lol.pyr.znpcsplus.entity.properties;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
|
||||
import lol.pyr.znpcsplus.api.skin.SkinDescriptor;
|
||||
import lol.pyr.znpcsplus.entity.EntityPropertyImpl;
|
||||
import lol.pyr.znpcsplus.entity.PacketEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class SkinProperty extends EntityPropertyImpl<SkinDescriptor> {
|
||||
public SkinProperty() {
|
||||
super("skin", null, SkinDescriptor.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(SkinDescriptor value, Player player, PacketEntity entity, boolean isSpawned, Map<Integer, EntityData> properties) {
|
||||
|
||||
}
|
||||
}
|
|
@ -87,7 +87,7 @@ public class NpcTypeImpl implements NpcType {
|
|||
|
||||
public NpcTypeImpl build() {
|
||||
ServerVersion version = PacketEvents.getAPI().getServerManager().getVersion();
|
||||
addProperties("fire", "invisible", "silent", "look", "skin_cape",
|
||||
addProperties("fire", "invisible", "silent", "look",
|
||||
"using_item", "potion_color", "potion_ambient", "dinnerbone");
|
||||
if (version.isNewerThanOrEquals(ServerVersion.V_1_9)) addProperties("glow");
|
||||
if (version.isNewerThanOrEquals(ServerVersion.V_1_14)) addProperties("pose");
|
||||
|
|
|
@ -7,6 +7,9 @@ import lol.pyr.znpcsplus.skin.descriptor.FetchingDescriptor;
|
|||
import lol.pyr.znpcsplus.skin.descriptor.MirrorDescriptor;
|
||||
import lol.pyr.znpcsplus.skin.descriptor.PrefetchedDescriptor;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
public class SkinDescriptorFactoryImpl implements SkinDescriptorFactory {
|
||||
private final MojangSkinCache skinCache;
|
||||
private final MirrorDescriptor mirrorDescriptor;
|
||||
|
@ -35,4 +38,14 @@ public class SkinDescriptorFactoryImpl implements SkinDescriptorFactory {
|
|||
public SkinDescriptor createStaticDescriptor(String texture, String signature) {
|
||||
return new PrefetchedDescriptor(new Skin(texture, signature));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SkinDescriptor createUrlDescriptor(String url) throws MalformedURLException {
|
||||
return createUrlDescriptor(new URL(url));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SkinDescriptor createUrlDescriptor(URL url) {
|
||||
return PrefetchedDescriptor.fromUrl(skinCache, url).join();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,9 +8,7 @@ import lol.pyr.znpcsplus.skin.Skin;
|
|||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.io.*;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
|
@ -69,6 +67,44 @@ public class MojangSkinCache {
|
|||
});
|
||||
}
|
||||
|
||||
public CompletableFuture<Skin> fetchByUrl(URL url) {
|
||||
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
URL apiUrl = parseUrl("https://api.mineskin.org/generate/url");
|
||||
HttpURLConnection connection = null;
|
||||
try {
|
||||
connection = (HttpURLConnection) apiUrl.openConnection();
|
||||
connection.setRequestMethod("POST");
|
||||
connection.setRequestProperty("accept", "application/json");
|
||||
connection.setRequestProperty("Content-Type", "application/json");
|
||||
connection.setDoOutput(true);
|
||||
OutputStream outStream = connection.getOutputStream();
|
||||
DataOutputStream out = new DataOutputStream(outStream);
|
||||
out.writeBytes("{\"variant\":\"classic\",\"url\":\"" + url.toString() + "\"}"); // TODO: configurable variant (slim, classic) default: classic
|
||||
out.flush();
|
||||
out.close();
|
||||
outStream.close();
|
||||
|
||||
try (Reader reader = new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8)) {
|
||||
JsonObject obj = JsonParser.parseReader(reader).getAsJsonObject();
|
||||
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());
|
||||
}
|
||||
|
||||
} catch (IOException exception) {
|
||||
if (!configManager.getConfig().disableSkinFetcherWarnings()) {
|
||||
logger.warning("Failed to get skin from url:");
|
||||
exception.printStackTrace();
|
||||
}
|
||||
} finally {
|
||||
if (connection != null) connection.disconnect();
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
public boolean isNameFullyCached(String s) {
|
||||
String name = s.toLowerCase();
|
||||
if (!idCache.containsKey(name)) return false;
|
||||
|
|
|
@ -7,6 +7,7 @@ import lol.pyr.znpcsplus.skin.Skin;
|
|||
import lol.pyr.znpcsplus.skin.cache.MojangSkinCache;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class PrefetchedDescriptor implements BaseSkinDescriptor, SkinDescriptor {
|
||||
|
@ -20,6 +21,10 @@ public class PrefetchedDescriptor implements BaseSkinDescriptor, SkinDescriptor
|
|||
return CompletableFuture.supplyAsync(() -> new PrefetchedDescriptor(cache.fetchByName(name).join()));
|
||||
}
|
||||
|
||||
public static CompletableFuture<PrefetchedDescriptor> fromUrl(MojangSkinCache cache, URL url) {
|
||||
return CompletableFuture.supplyAsync(() -> new PrefetchedDescriptor(cache.fetchByUrl(url).join()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Skin> fetch(Player player) {
|
||||
return CompletableFuture.completedFuture(skin);
|
||||
|
|
Loading…
Reference in a new issue