From 10723399a3d8d9a6515b8e2f1bb2f368e489436a Mon Sep 17 00:00:00 2001 From: david <89749147+davight@users.noreply.github.com> Date: Thu, 13 Nov 2025 21:32:39 +0100 Subject: [PATCH 1/2] work --- .../paper/utilities/PaperAPIToolsImpl.java | 12 ++-- .../denizen/objects/PlayerTag.java | 28 ++++++++ .../commands/player/ResourcePackCommand.java | 71 +++++++++++++++---- .../denizen/utilities/PaperAPITools.java | 2 +- 4 files changed, 95 insertions(+), 18 deletions(-) diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java index c468235626..b205e55c3f 100644 --- a/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java +++ b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java @@ -6,6 +6,7 @@ import com.denizenscript.denizen.objects.ItemTag; import com.denizenscript.denizen.paper.PaperModule; import com.denizenscript.denizen.scripts.commands.entity.TeleportCommand; +import com.denizenscript.denizen.scripts.commands.player.ResourcePackCommand; import com.denizenscript.denizen.scripts.containers.core.ItemScriptContainer; import com.denizenscript.denizen.scripts.containers.core.ItemScriptHelper; import com.denizenscript.denizen.utilities.FormattedTextHelper; @@ -116,13 +117,16 @@ public void setSignLine(Sign sign, int line, String text) { } @Override - public void sendResourcePack(Player player, String url, String hash, boolean forced, String prompt) { - if (prompt == null && !forced) { - super.sendResourcePack(player, url, hash, false, null); + public void setResourcePack(Player player, String url, String hash, boolean forced, String prompt, String id) { + if (prompt == null && !forced && id == null) { + super.setResourcePack(player, url, hash, false, null, null); } - else { + else if (id == null) { player.setResourcePack(url, CoreUtilities.toLowerCase(hash), forced, PaperModule.parseFormattedText(prompt, ChatColor.WHITE)); } + else { + player.setResourcePack(ResourcePackCommand.parseUUID(id), url, CoreUtilities.toLowerCase(hash), PaperModule.parseFormattedText(prompt, ChatColor.WHITE), forced); + } } @Override diff --git a/plugin/src/main/java/com/denizenscript/denizen/objects/PlayerTag.java b/plugin/src/main/java/com/denizenscript/denizen/objects/PlayerTag.java index eae5750277..47c9829c3f 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/objects/PlayerTag.java +++ b/plugin/src/main/java/com/denizenscript/denizen/objects/PlayerTag.java @@ -9,6 +9,7 @@ import com.denizenscript.denizen.objects.properties.entity.EntityHealth; import com.denizenscript.denizen.scripts.commands.player.DisguiseCommand; import com.denizenscript.denizen.scripts.commands.player.ExperienceCommand; +import com.denizenscript.denizen.scripts.commands.player.ResourcePackCommand; import com.denizenscript.denizen.scripts.commands.player.SidebarCommand; import com.denizenscript.denizen.scripts.commands.server.BossBarCommand; import com.denizenscript.denizen.tags.core.PlayerTagBase; @@ -2679,6 +2680,33 @@ else if (mechanism.requireObject(LocationTag.class)) { object.getNBTEditor().setSpawnForced(input.asBoolean()); } }); + + if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20)) { + + // <--[mechanism] + // @object PlayerTag + // @name remove_resource_pack + // @input ElementTag + // @description + // Removes a server resource pack from a player by id. + // To apply a resource pack, use <@link command resourcepack>. + // --> + registerOnlineOnlyMechanism("remove_resource_pack", ElementTag.class, (object, mechanism, input) -> { + object.getPlayerEntity().removeResourcePack(ResourcePackCommand.parseUUID(input.asString())); + }); + + // <--[mechanism] + // @object PlayerTag + // @name remove_resource_packs + // @input None + // @description + // Removes all server resource packs from a player. + // To apply a resource pack, use <@link command resourcepack>. + // --> + registerOnlineOnlyMechanism("remove_resource_packs", (object, mechanism) -> { + object.getPlayerEntity().removeResourcePacks(); + }); + } } public static ObjectTagProcessor tagProcessor = new ObjectTagProcessor<>(); diff --git a/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/player/ResourcePackCommand.java b/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/player/ResourcePackCommand.java index d221734b42..4ffa70acdd 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/player/ResourcePackCommand.java +++ b/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/player/ResourcePackCommand.java @@ -1,33 +1,34 @@ package com.denizenscript.denizen.scripts.commands.player; +import com.denizenscript.denizen.nms.NMSHandler; +import com.denizenscript.denizen.nms.NMSVersion; import com.denizenscript.denizen.objects.PlayerTag; import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizen.utilities.Utilities; import com.denizenscript.denizencore.exceptions.InvalidArgumentsRuntimeException; -import com.denizenscript.denizencore.scripts.commands.generator.ArgDefaultNull; -import com.denizenscript.denizencore.scripts.commands.generator.ArgName; -import com.denizenscript.denizencore.scripts.commands.generator.ArgPrefixed; -import com.denizenscript.denizencore.scripts.commands.generator.ArgSubType; +import com.denizenscript.denizencore.scripts.commands.generator.*; import com.denizenscript.denizencore.utilities.debugging.Debug; import com.denizenscript.denizencore.scripts.ScriptEntry; import com.denizenscript.denizencore.scripts.commands.AbstractCommand; +import java.nio.charset.StandardCharsets; import java.util.Collections; import java.util.List; +import java.util.UUID; public class ResourcePackCommand extends AbstractCommand { public ResourcePackCommand() { setName("resourcepack"); - setSyntax("resourcepack [url:] [hash:] (forced) (prompt:) (targets:|...)"); - setRequiredArguments(2, 5); + setSyntax("resourcepack ({set}/add) (id:) [url:] [hash:] (forced) (prompt:) (targets:|...)"); + setRequiredArguments(2, 7); isProcedural = false; autoCompile(); } // <--[command] // @Name ResourcePack - // @Syntax resourcepack [url:] [hash:] (forced) (prompt:) (targets:|...) + // @Syntax resourcepack ({set}/add) (id:) [url:] [hash:] (forced) (prompt:) (targets:|...) // @Required 2 // @Maximum 5 // @Short Prompts a player to download a server resource pack. @@ -36,6 +37,9 @@ public ResourcePackCommand() { // @Description // Sets the current resource pack by specifying a valid URL to a resource pack. // + // Optionally, you can send the player additional resource packs by using the "add" argument. + // The "id" argument allows you to overwrite a specific resource pack or remove one via <@link mechanism PlayerTag.remove_resource_pack>. + // // The player will be prompted to download the pack, with the optional prompt text or a default vanilla message. // Once a player says "yes" once, all future packs will be automatically downloaded. If the player selects "no" once, all future packs will automatically be rejected. // Players can change the automatic setting from their server list in the main menu. @@ -56,12 +60,21 @@ public ResourcePackCommand() { // None // // @Usage - // Use to send a resource pack with a pre-known hash. + // Use to set a resource pack with a pre-known hash. // - resourcepack url:https://example.com/pack.zip hash:0102030405060708090a0b0c0d0e0f1112131415 // + // @Usage + // Use to send multiple resource packs to a player. + // - resourcepack add id:first_pack url:https://example.com/pack1.zip hash:0102030405060708090a0b0c0d0e0f1112131415 + // - resourcepack add id:second_pack url:https://example.com/pack2.zip hash:0102030405060708090a0b0c0d0e0f1112131415 + // // --> + public enum Action { SET, ADD } + public static void autoExecute(ScriptEntry scriptEntry, + @ArgName("action") @ArgDefaultText("set") Action action, + @ArgName("id") @ArgPrefixed @ArgDefaultNull String id, @ArgName("url") @ArgPrefixed String url, @ArgName("hash") @ArgPrefixed String hash, @ArgName("prompt") @ArgPrefixed @ArgDefaultNull String prompt, @@ -77,12 +90,44 @@ public static void autoExecute(ScriptEntry scriptEntry, Debug.echoError("Invalid resource_pack hash. Should be 40 characters of hexadecimal data."); return; } - for (PlayerTag player : targets) { - if (!player.isOnline()) { - Debug.echoDebug(scriptEntry, "Player is offline, can't send resource pack to them. Skipping."); - continue; + if (!NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20) && (action == Action.ADD || id != null)) { + throw new UnsupportedOperationException(); + } + switch (action) { + case SET -> { + for (PlayerTag player : targets) { + if (!player.isOnline()) { + Debug.echoDebug(scriptEntry, "Player is offline, can't send resource pack to them. Skipping."); + continue; + } + PaperAPITools.instance.setResourcePack(player.getPlayerEntity(), url, hash, forced, prompt, id); + } } - PaperAPITools.instance.sendResourcePack(player.getPlayerEntity(), url, hash, forced, prompt); + case ADD -> { + byte[] hashData = new byte[20]; + for (int i = 0; i < 20; i++) { + hashData[i] = (byte) Integer.parseInt(hash.substring(i * 2, i * 2 + 2), 16); + } + UUID packUUID = id == null ? UUID.nameUUIDFromBytes(url.getBytes(StandardCharsets.UTF_8)) : parseUUID(id); + for (PlayerTag player : targets) { + if (!player.isOnline()) { + Debug.echoDebug(scriptEntry, "Player is offline, can't send resource pack to them. Skipping."); + continue; + } + player.getPlayerEntity().addResourcePack(packUUID, url, hashData, prompt, forced); + } + } + } + } + + public static UUID parseUUID(String id) { + UUID uuid; + try { + uuid = UUID.fromString(id); + } + catch (IllegalArgumentException ex) { + uuid = UUID.nameUUIDFromBytes(id.getBytes(StandardCharsets.UTF_8)); } + return uuid; } } diff --git a/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java b/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java index 2625cc5ced..14b4e55750 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java +++ b/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java @@ -92,7 +92,7 @@ public void setSignLine(Sign sign, int line, String text) { sign.setLine(line, text == null ? "" : text); } - public void sendResourcePack(Player player, String url, String hash, boolean forced, String prompt) { + public void setResourcePack(Player player, String url, String hash, boolean forced, String prompt, String id) { byte[] hashData = new byte[20]; for (int i = 0; i < 20; i++) { hashData[i] = (byte) Integer.parseInt(hash.substring(i * 2, i * 2 + 2), 16); From 8661eff5bd7089cd7995a20b5fe9b5d813f02d0e Mon Sep 17 00:00:00 2001 From: david <89749147+davight@users.noreply.github.com> Date: Tue, 23 Dec 2025 23:17:17 +0100 Subject: [PATCH 2/2] move remove to resourcepack command --- .../denizen/objects/PlayerTag.java | 27 -------- .../commands/player/ResourcePackCommand.java | 65 +++++++++++++------ 2 files changed, 46 insertions(+), 46 deletions(-) diff --git a/plugin/src/main/java/com/denizenscript/denizen/objects/PlayerTag.java b/plugin/src/main/java/com/denizenscript/denizen/objects/PlayerTag.java index 47c9829c3f..d1ad659225 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/objects/PlayerTag.java +++ b/plugin/src/main/java/com/denizenscript/denizen/objects/PlayerTag.java @@ -2680,33 +2680,6 @@ else if (mechanism.requireObject(LocationTag.class)) { object.getNBTEditor().setSpawnForced(input.asBoolean()); } }); - - if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20)) { - - // <--[mechanism] - // @object PlayerTag - // @name remove_resource_pack - // @input ElementTag - // @description - // Removes a server resource pack from a player by id. - // To apply a resource pack, use <@link command resourcepack>. - // --> - registerOnlineOnlyMechanism("remove_resource_pack", ElementTag.class, (object, mechanism, input) -> { - object.getPlayerEntity().removeResourcePack(ResourcePackCommand.parseUUID(input.asString())); - }); - - // <--[mechanism] - // @object PlayerTag - // @name remove_resource_packs - // @input None - // @description - // Removes all server resource packs from a player. - // To apply a resource pack, use <@link command resourcepack>. - // --> - registerOnlineOnlyMechanism("remove_resource_packs", (object, mechanism) -> { - object.getPlayerEntity().removeResourcePacks(); - }); - } } public static ObjectTagProcessor tagProcessor = new ObjectTagProcessor<>(); diff --git a/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/player/ResourcePackCommand.java b/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/player/ResourcePackCommand.java index 4ffa70acdd..badb6e770d 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/player/ResourcePackCommand.java +++ b/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/player/ResourcePackCommand.java @@ -20,15 +20,15 @@ public class ResourcePackCommand extends AbstractCommand { public ResourcePackCommand() { setName("resourcepack"); - setSyntax("resourcepack ({set}/add) (id:) [url:] [hash:] (forced) (prompt:) (targets:|...)"); - setRequiredArguments(2, 7); + setSyntax("resourcepack ({set}/add/remove) (id:) (url:) (hash:) (forced) (prompt:) (targets:|...)"); + setRequiredArguments(1, 7); isProcedural = false; autoCompile(); } // <--[command] // @Name ResourcePack - // @Syntax resourcepack ({set}/add) (id:) [url:] [hash:] (forced) (prompt:) (targets:|...) + // @Syntax resourcepack ({set}/add/remove) (id:) (url:) (hash:) (forced) (prompt:) (targets:|...) // @Required 2 // @Maximum 5 // @Short Prompts a player to download a server resource pack. @@ -38,7 +38,7 @@ public ResourcePackCommand() { // Sets the current resource pack by specifying a valid URL to a resource pack. // // Optionally, you can send the player additional resource packs by using the "add" argument. - // The "id" argument allows you to overwrite a specific resource pack or remove one via <@link mechanism PlayerTag.remove_resource_pack>. + // The "id" argument allows you to overwrite a specific resource pack or remove one with "remove" argument. // // The player will be prompted to download the pack, with the optional prompt text or a default vanilla message. // Once a player says "yes" once, all future packs will be automatically downloaded. If the player selects "no" once, all future packs will automatically be rejected. @@ -68,39 +68,43 @@ public ResourcePackCommand() { // - resourcepack add id:first_pack url:https://example.com/pack1.zip hash:0102030405060708090a0b0c0d0e0f1112131415 // - resourcepack add id:second_pack url:https://example.com/pack2.zip hash:0102030405060708090a0b0c0d0e0f1112131415 // + // @Usage + // Use to remove all resource packs from all online players. + // - resourcepack remove targets: // --> - public enum Action { SET, ADD } + public enum Action { SET, ADD, REMOVE } public static void autoExecute(ScriptEntry scriptEntry, @ArgName("action") @ArgDefaultText("set") Action action, @ArgName("id") @ArgPrefixed @ArgDefaultNull String id, - @ArgName("url") @ArgPrefixed String url, - @ArgName("hash") @ArgPrefixed String hash, + @ArgName("url") @ArgPrefixed @ArgDefaultNull String url, + @ArgName("hash") @ArgPrefixed @ArgDefaultNull String hash, @ArgName("prompt") @ArgPrefixed @ArgDefaultNull String prompt, @ArgName("targets") @ArgPrefixed @ArgDefaultNull @ArgSubType(PlayerTag.class) List targets, @ArgName("forced") boolean forced) { + if (!NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20) && (action == Action.ADD || id != null)) { + throw new UnsupportedOperationException(); + } if (targets == null) { if (!Utilities.entryHasPlayer(scriptEntry)) { throw new InvalidArgumentsRuntimeException("Must specify an online player!"); } targets = Collections.singletonList(Utilities.getEntryPlayer(scriptEntry)); } - if (hash.length() != 40) { + if ((action == Action.ADD || action == Action.SET) && (url == null || hash == null)) { + throw new InvalidArgumentsRuntimeException("Must specify both a resource pack URL and hash!"); + } + if ((action == Action.ADD || action == Action.SET) && hash.length() != 40) { Debug.echoError("Invalid resource_pack hash. Should be 40 characters of hexadecimal data."); return; } - if (!NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20) && (action == Action.ADD || id != null)) { - throw new UnsupportedOperationException(); - } switch (action) { case SET -> { for (PlayerTag player : targets) { - if (!player.isOnline()) { - Debug.echoDebug(scriptEntry, "Player is offline, can't send resource pack to them. Skipping."); - continue; + if (checkOnline(player)) { + PaperAPITools.instance.setResourcePack(player.getPlayerEntity(), url, hash, forced, prompt, id); } - PaperAPITools.instance.setResourcePack(player.getPlayerEntity(), url, hash, forced, prompt, id); } } case ADD -> { @@ -110,14 +114,37 @@ public static void autoExecute(ScriptEntry scriptEntry, } UUID packUUID = id == null ? UUID.nameUUIDFromBytes(url.getBytes(StandardCharsets.UTF_8)) : parseUUID(id); for (PlayerTag player : targets) { - if (!player.isOnline()) { - Debug.echoDebug(scriptEntry, "Player is offline, can't send resource pack to them. Skipping."); - continue; + if (checkOnline(player)) { + player.getPlayerEntity().addResourcePack(packUUID, url, hashData, prompt, forced); } - player.getPlayerEntity().addResourcePack(packUUID, url, hashData, prompt, forced); } } + case REMOVE -> { + if (id == null) { + for (PlayerTag player : targets) { + if (checkOnline(player)) { + player.getPlayerEntity().removeResourcePacks(); + } + } + } + else { + UUID packUUID = parseUUID(id); + for (PlayerTag player : targets) { + if (checkOnline(player)) { + player.getPlayerEntity().removeResourcePack(packUUID); + } + } + } + } + } + } + + public static boolean checkOnline(PlayerTag player) { + if (!player.isOnline()) { + Debug.echoError("Invalid player '" + player.getName() + "' specified: must be online"); + return false; } + return true; } public static UUID parseUUID(String id) {