improve holo commands, add skin command

This commit is contained in:
Pyrbu 2023-05-11 14:25:26 +01:00
parent ca94951b63
commit e6a7e6f2f0
7 changed files with 90 additions and 9 deletions

@ -190,6 +190,7 @@ public class ZNpcsPlus extends JavaPlugin {
manager.registerCommand("npc", new MultiCommand() manager.registerCommand("npc", new MultiCommand()
.addSubcommand("action", new ActionCommand()) .addSubcommand("action", new ActionCommand())
.addSubcommand("create", new CreateCommand()) .addSubcommand("create", new CreateCommand())
.addSubcommand("skin", new SkinCommand())
.addSubcommand("delete", new DeleteCommand()) .addSubcommand("delete", new DeleteCommand())
.addSubcommand("move", new MoveCommand()) .addSubcommand("move", new MoveCommand())
.addSubcommand("properties", new PropertiesCommand()) .addSubcommand("properties", new PropertiesCommand())

@ -0,0 +1,67 @@
package lol.pyr.znpcsplus.commands;
import lol.pyr.director.adventure.command.CommandContext;
import lol.pyr.director.adventure.command.CommandHandler;
import lol.pyr.director.common.command.CommandExecutionException;
import lol.pyr.znpcsplus.entity.EntityPropertyImpl;
import lol.pyr.znpcsplus.npc.NpcEntryImpl;
import lol.pyr.znpcsplus.npc.NpcImpl;
import lol.pyr.znpcsplus.npc.NpcRegistryImpl;
import lol.pyr.znpcsplus.npc.NpcTypeImpl;
import lol.pyr.znpcsplus.skin.descriptor.FetchingDescriptor;
import lol.pyr.znpcsplus.skin.descriptor.MirrorDescriptor;
import lol.pyr.znpcsplus.skin.descriptor.PrefetchedDescriptor;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import java.util.Collections;
import java.util.List;
public class SkinCommand implements CommandHandler {
@Override
public void run(CommandContext context) throws CommandExecutionException {
context.setUsage(context.getLabel() + " skin <id> <type> [value]");
NpcImpl npc = context.parse(NpcEntryImpl.class).getNpc();
if (npc.getType() != NpcTypeImpl.byName("player")) context.halt(Component.text("The NPC must be a player to have a skin", NamedTextColor.RED));
String type = context.popString();
if (type.equalsIgnoreCase("mirror")) {
npc.setProperty(EntityPropertyImpl.SKIN, new MirrorDescriptor());
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")) {
context.ensureArgsNotEmpty();
String name = context.dumpAllArgs();
context.send(Component.text("Fetching skin \"" + name + "\"...", NamedTextColor.GREEN));
PrefetchedDescriptor.forPlayer(name).thenAccept(skin -> {
if (skin == null) {
context.send(Component.text("Failed to fetch skin, are you sure the player name is valid?", NamedTextColor.RED));
return;
}
npc.setProperty(EntityPropertyImpl.SKIN, skin);
npc.respawn();
context.send(Component.text("The NPC's skin has been set to \"" + name + "\""));
});
return;
}
if (type.equalsIgnoreCase("dynamic")) {
context.ensureArgsNotEmpty();
String name = context.dumpAllArgs();
npc.setProperty(EntityPropertyImpl.SKIN, new FetchingDescriptor(name));
npc.respawn();
context.halt(Component.text("The NPC's skin will now be resolved per-player from \"" + name + "\""));
}
context.send(Component.text("Unknown skin type! Please use one of the following: mirror, static, dynamic"));
}
@Override
public List<String> suggest(CommandContext context) throws CommandExecutionException {
if (context.argSize() == 1) return context.suggestCollection(NpcRegistryImpl.get().modifiableIds());
if (context.argSize() == 2) return context.suggestLiteral("mirror", "static", "dynamic");
if (context.matchSuggestion("*", "static")) return context.suggestPlayers();
return Collections.emptyList();
}
}

@ -18,6 +18,7 @@ public class HoloAddCommand implements CommandHandler {
public void run(CommandContext context) throws CommandExecutionException { public void run(CommandContext context) throws CommandExecutionException {
context.setUsage(context.getLabel() + " holo add <id> <text>"); context.setUsage(context.getLabel() + " holo add <id> <text>");
HologramImpl hologram = context.parse(NpcEntryImpl.class).getNpc().getHologram(); HologramImpl hologram = context.parse(NpcEntryImpl.class).getNpc().getHologram();
context.ensureArgsNotEmpty();
hologram.addLine(ZNpcsPlus.LEGACY_AMPERSAND_SERIALIZER.deserialize(context.dumpAllArgs())); hologram.addLine(ZNpcsPlus.LEGACY_AMPERSAND_SERIALIZER.deserialize(context.dumpAllArgs()));
context.send(Component.text("NPC line added!", NamedTextColor.GREEN)); context.send(Component.text("NPC line added!", NamedTextColor.GREEN));
} }

@ -21,6 +21,7 @@ public class HoloInsertCommand implements CommandHandler {
HologramImpl hologram = context.parse(NpcEntryImpl.class).getNpc().getHologram(); HologramImpl hologram = context.parse(NpcEntryImpl.class).getNpc().getHologram();
int line = context.parse(Integer.class); int line = context.parse(Integer.class);
if (line < 0 || line >= hologram.getLines().size()) context.halt(Component.text("Invalid line number!", NamedTextColor.RED)); if (line < 0 || line >= hologram.getLines().size()) context.halt(Component.text("Invalid line number!", NamedTextColor.RED));
context.ensureArgsNotEmpty();
hologram.insertLine(line, ZNpcsPlus.LEGACY_AMPERSAND_SERIALIZER.deserialize(context.dumpAllArgs())); hologram.insertLine(line, ZNpcsPlus.LEGACY_AMPERSAND_SERIALIZER.deserialize(context.dumpAllArgs()));
context.send(Component.text("NPC line inserted!", NamedTextColor.GREEN)); context.send(Component.text("NPC line inserted!", NamedTextColor.GREEN));
} }

@ -21,6 +21,7 @@ public class HoloSetCommand implements CommandHandler {
HologramImpl hologram = context.parse(NpcEntryImpl.class).getNpc().getHologram(); HologramImpl hologram = context.parse(NpcEntryImpl.class).getNpc().getHologram();
int line = context.parse(Integer.class); int line = context.parse(Integer.class);
if (line < 0 || line >= hologram.getLines().size()) context.halt(Component.text("Invalid line number!", NamedTextColor.RED)); if (line < 0 || line >= hologram.getLines().size()) context.halt(Component.text("Invalid line number!", NamedTextColor.RED));
context.ensureArgsNotEmpty();
hologram.removeLine(line); hologram.removeLine(line);
hologram.insertLine(line, ZNpcsPlus.LEGACY_AMPERSAND_SERIALIZER.deserialize(context.dumpAllArgs())); hologram.insertLine(line, ZNpcsPlus.LEGACY_AMPERSAND_SERIALIZER.deserialize(context.dumpAllArgs()));
context.send(Component.text("NPC line set!", NamedTextColor.GREEN)); context.send(Component.text("NPC line set!", NamedTextColor.GREEN));

@ -31,4 +31,9 @@ public interface MainConfig {
@ConfComments("The storage type to use. Available storage types: YAML") @ConfComments("The storage type to use. Available storage types: YAML")
@DefaultString("YAML") @DefaultString("YAML")
NpcStorageType storageType(); NpcStorageType storageType();
@ConfKey("disable-skin-fetcher-warnings")
@ConfComments("Set this to true if you don't want to be warned in the console when a skin fails to resolve")
@DefaultBoolean(false)
boolean disableSkinFetcherWarnings();
} }

@ -3,6 +3,8 @@ package lol.pyr.znpcsplus.skin.cache;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.google.gson.JsonParser; import com.google.gson.JsonParser;
import com.mojang.authlib.GameProfile; import com.mojang.authlib.GameProfile;
import lol.pyr.znpcsplus.ZNpcsPlus;
import lol.pyr.znpcsplus.config.Configs;
import lol.pyr.znpcsplus.reflection.Reflections; import lol.pyr.znpcsplus.reflection.Reflections;
import lol.pyr.znpcsplus.skin.Skin; import lol.pyr.znpcsplus.skin.Skin;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@ -36,8 +38,7 @@ public class SkinCache {
if (cache.containsKey(name.toLowerCase())) return fetchByUUID(idCache.get(name.toLowerCase()).getId()); if (cache.containsKey(name.toLowerCase())) return fetchByUUID(idCache.get(name.toLowerCase()).getId());
CompletableFuture<Skin> future = new CompletableFuture<>(); return CompletableFuture.supplyAsync(() -> {
CompletableFuture.runAsync(() -> {
URL url = parseUrl("https://api.mojang.com/users/profiles/minecraft/" + name); URL url = parseUrl("https://api.mojang.com/users/profiles/minecraft/" + name);
HttpURLConnection connection = null; HttpURLConnection connection = null;
try { try {
@ -45,18 +46,21 @@ public class SkinCache {
connection.setRequestMethod("GET"); connection.setRequestMethod("GET");
try (Reader reader = new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8)) { try (Reader reader = new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8)) {
JsonObject obj = JsonParser.parseReader(reader).getAsJsonObject(); JsonObject obj = JsonParser.parseReader(reader).getAsJsonObject();
if (obj.has("errorMessage")) future.complete(null); if (obj.has("errorMessage")) return null;
String id = obj.get("id").getAsString(); String id = obj.get("id").getAsString();
idCache.put(name.toLowerCase(), new CachedId(id)); idCache.put(name.toLowerCase(), new CachedId(id));
fetchByUUID(id).thenAccept(future::complete); return fetchByUUID(id).join();
} }
} catch (IOException exception) { } catch (IOException exception) {
exception.printStackTrace(); if (!Configs.config().disableSkinFetcherWarnings()) {
ZNpcsPlus.LOGGER.warning("Failed to uuid from player name:");
exception.printStackTrace();
}
} finally { } finally {
if (connection != null) connection.disconnect(); if (connection != null) connection.disconnect();
} }
return null;
}); });
return future;
} }
public static CompletableFuture<Skin> fetchByUUID(UUID uuid) { public static CompletableFuture<Skin> fetchByUUID(UUID uuid) {
@ -96,7 +100,6 @@ public class SkinCache {
HttpURLConnection connection = null; HttpURLConnection connection = null;
try { try {
connection = (HttpURLConnection) url.openConnection(); connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET"); connection.setRequestMethod("GET");
try (Reader reader = new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8)) { try (Reader reader = new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8)) {
JsonObject obj = JsonParser.parseReader(reader).getAsJsonObject(); JsonObject obj = JsonParser.parseReader(reader).getAsJsonObject();
@ -105,11 +108,13 @@ public class SkinCache {
return skin; return skin;
} }
} catch (IOException exception) { } catch (IOException exception) {
exception.printStackTrace(); if (!Configs.config().disableSkinFetcherWarnings()) {
ZNpcsPlus.LOGGER.warning("Failed to fetch skin:");
exception.printStackTrace();
}
} finally { } finally {
if (connection != null) connection.disconnect(); if (connection != null) connection.disconnect();
} }
Bukkit.broadcastMessage("failed");
return null; return null;
}); });
} }