From a6566f3616c774ee2f40954df327fa1c30e5831c Mon Sep 17 00:00:00 2001 From: APickledWalrus Date: Sat, 23 Jul 2022 20:10:48 -0400 Subject: [PATCH] Make this experiment use Paper's integration This results in much faster execution times comparable to the current system. However, it also means that Spigot is no longer supported, and versions below 1.17 won't work. (Paper 1.17+ only now) --- build.gradle | 16 ++- src/main/java/ch/njol/skript/Skript.java | 6 +- .../ch/njol/skript/command/ScriptCommand.java | 2 +- .../ch/njol/skript/expressions/ExprName.java | 134 ++++++++---------- .../ch/njol/skript/expressions/ExprNamed.java | 50 ++++--- .../ExprPlayerListHeaderFooter.java | 41 +++--- .../skript/bukkit/chat/ChatModule.java | 18 ++- .../bukkit/chat/elements/EffBroadcast.java | 29 ++-- .../bukkit/chat/elements/EffMessage.java | 25 ++-- .../bukkit/chat/elements/EffSendTitle.java | 40 +++--- .../bukkit/chat/util/ComponentHandler.java | 56 ++------ .../environments/java8/paper-1.13.2.json | 17 --- .../environments/java8/paper-1.14.4.json | 17 --- .../environments/java8/paper-1.15.2.json | 17 --- .../environments/java8/paper-1.16.5.json | 17 --- 15 files changed, 201 insertions(+), 284 deletions(-) delete mode 100644 src/test/skript/environments/java8/paper-1.13.2.json delete mode 100644 src/test/skript/environments/java8/paper-1.14.4.json delete mode 100644 src/test/skript/environments/java8/paper-1.15.2.json delete mode 100644 src/test/skript/environments/java8/paper-1.16.5.json diff --git a/build.gradle b/build.gradle index b5ce7ed1b8f..59c5ef55a73 100644 --- a/build.gradle +++ b/build.gradle @@ -25,8 +25,7 @@ dependencies { shadow group: 'io.papermc', name: 'paperlib', version: '1.0.7' shadow group: 'org.bstats', name: 'bstats-bukkit', version: '3.0.0' implementation group: 'io.papermc.paper', name: 'paper-api', version: '1.19-R0.1-SNAPSHOT' - shadow group: 'net.kyori', name: 'adventure-text-minimessage', version: '4.11.0-SNAPSHOT' - shadow group: 'net.kyori', name: 'adventure-platform-bukkit', version: '4.1.1-SNAPSHOT' + shadow group: 'net.kyori', name: 'adventure-text-serializer-legacy', version: '4.11.0-SNAPSHOT' shadow group: 'net.kyori', name: 'adventure-text-serializer-plain', version: '4.11.0-SNAPSHOT' implementation group: 'org.eclipse.jdt', name: 'org.eclipse.jdt.annotation', version: '2.2.600' implementation group: 'com.google.code.findbugs', name: 'findbugs', version: '3.0.1' @@ -75,9 +74,15 @@ tasks.withType(ShadowJar) { configurations = [ project.configurations.shadow ] + dependencies { + include(dependency('io.papermc:paperlib')) + include(dependency('org.bstats:bstats-bukkit')) + include(dependency('org.bstats:bstats-base')) + include(dependency('net.kyori:adventure-text-serializer-legacy')) + include(dependency('net.kyori:adventure-text-serializer-plain')) + } relocate 'io.papermc.lib', 'ch.njol.skript.paperlib' relocate 'org.bstats', 'ch.njol.skript.bstats' - relocate 'net.kyori', 'ch.njol.skript.kyori' manifest { attributes( 'Name': 'ch/njol/skript', @@ -187,7 +192,7 @@ void createTestTask(String name, String environments, boolean devMode, int javaV def latestEnv = 'java17/paper-1.19.json' def latestJava = 17 -def oldestJava = 8 +def oldestJava = 17 tasks.withType(JavaCompile).configureEach { options.compilerArgs += ["-source", "" + oldestJava, "-target", "" + oldestJava] @@ -196,11 +201,10 @@ tasks.withType(JavaCompile).configureEach { // Register different Skript testing tasks createTestTask('quickTest', 'src/test/skript/environments/' + latestEnv, false, latestJava, false) createTestTask('skriptTestJava17', 'src/test/skript/environments/java17', false, latestJava, false) -createTestTask('skriptTestJava8', 'src/test/skript/environments/java8', false, oldestJava, false) createTestTask('skriptTestDev', 'src/test/skript/environments/' + (project.property('testEnv') == null ? latestEnv : project.property('testEnv') + '.json'), true, Integer.parseInt(project.property('testEnvJavaVersion') == null ? latestJava : project.property('testEnvJavaVersion')), false) -tasks.register('skriptTest') {dependsOn skriptTestJava8, skriptTestJava17} +tasks.register('skriptTest') {dependsOn skriptTestJava17} createTestTask('genDocs', 'src/test/skript/environments/' + (project.property('testEnv') == null ? latestEnv : project.property('testEnv') + '.json'), false, Integer.parseInt(project.property('testEnvJavaVersion') == null ? latestJava : project.property('testEnvJavaVersion')), true) diff --git a/src/main/java/ch/njol/skript/Skript.java b/src/main/java/ch/njol/skript/Skript.java index 3d0f634dbbf..bcf0241149a 100644 --- a/src/main/java/ch/njol/skript/Skript.java +++ b/src/main/java/ch/njol/skript/Skript.java @@ -1742,7 +1742,7 @@ static void logEx(final String... lines) { // } public static void info(final CommandSender sender, final String info) { - ComponentHandler.audienceFrom(sender).sendMessage(SKRIPT_PREFIX_COMPONENT.append(ComponentHandler.parse(info))); + sender.sendMessage(SKRIPT_PREFIX_COMPONENT.append(ComponentHandler.parse(info))); } /** @@ -1765,11 +1765,11 @@ public static void adminBroadcast(final String message) { * @param info */ public static void message(final CommandSender sender, final String info) { - ComponentHandler.audienceFrom(sender).sendMessage(ComponentHandler.parse(info)); + sender.sendMessage(ComponentHandler.parse(info)); } public static void error(final CommandSender sender, final String error) { - ComponentHandler.audienceFrom(sender).sendMessage(SKRIPT_PREFIX_COMPONENT.append(ComponentHandler.parse(error).color(NamedTextColor.DARK_RED))); + sender.sendMessage(SKRIPT_PREFIX_COMPONENT.append(ComponentHandler.parse(error).color(NamedTextColor.DARK_RED))); } /** diff --git a/src/main/java/ch/njol/skript/command/ScriptCommand.java b/src/main/java/ch/njol/skript/command/ScriptCommand.java index 15b823a1f3e..a14e59d5906 100644 --- a/src/main/java/ch/njol/skript/command/ScriptCommand.java +++ b/src/main/java/ch/njol/skript/command/ScriptCommand.java @@ -207,7 +207,7 @@ public boolean execute(final CommandSender sender, final String commandLabel, fi final ScriptCommandEvent event = new ScriptCommandEvent(ScriptCommand.this, sender); if (!permission.isEmpty() && !sender.hasPermission(permission)) { - ComponentHandler.audienceFrom(sender).sendMessage(ComponentHandler.parseFromSingleExpression(event, permissionMessage)); + sender.sendMessage(ComponentHandler.parseFromSingleExpression(event, permissionMessage)); return false; } diff --git a/src/main/java/ch/njol/skript/expressions/ExprName.java b/src/main/java/ch/njol/skript/expressions/ExprName.java index c0c26f40e8c..831dd0e44ad 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprName.java +++ b/src/main/java/ch/njol/skript/expressions/ExprName.java @@ -18,12 +18,21 @@ */ package ch.njol.skript.expressions; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; -import java.util.ArrayList; -import java.util.List; - +import ch.njol.skript.Skript; +import ch.njol.skript.aliases.Aliases; +import ch.njol.skript.aliases.ItemType; +import ch.njol.skript.classes.Changer.ChangeMode; +import ch.njol.skript.doc.Description; +import ch.njol.skript.doc.Examples; +import ch.njol.skript.doc.Name; +import ch.njol.skript.doc.Since; +import ch.njol.skript.expressions.base.SimplePropertyExpression; +import ch.njol.skript.lang.Expression; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.util.slot.Slot; +import ch.njol.util.Kleenean; +import ch.njol.util.coll.CollectionUtils; +import net.kyori.adventure.text.Component; import org.bukkit.Bukkit; import org.bukkit.GameRule; import org.bukkit.Nameable; @@ -41,21 +50,8 @@ import org.bukkit.inventory.meta.ItemMeta; import org.eclipse.jdt.annotation.Nullable; -import ch.njol.skript.Skript; -import ch.njol.skript.aliases.Aliases; -import ch.njol.skript.aliases.ItemType; -import ch.njol.skript.classes.Changer.ChangeMode; -import ch.njol.skript.doc.Description; -import ch.njol.skript.doc.Examples; -import ch.njol.skript.doc.Name; -import ch.njol.skript.doc.Since; -import ch.njol.skript.expressions.base.SimplePropertyExpression; -import ch.njol.skript.lang.Expression; -import ch.njol.skript.lang.SkriptParser.ParseResult; -import ch.njol.skript.util.slot.Slot; -import ch.njol.util.Kleenean; -import ch.njol.util.coll.CollectionUtils; -import net.md_5.bungee.api.ChatColor; +import java.util.ArrayList; +import java.util.List; @Name("Name / Display Name / Tab List Name") @Description({"Represents the Minecraft account, display or tab list name of a player, or the custom name of an item, entity, block, inventory, or gamerule.", @@ -99,24 +95,14 @@ " set the player's tab list name to \"<green>%player's name%\"", "set the name of the player's tool to \"Legendary Sword of Awesomeness\""}) @Since("before 2.1, 2.2-dev20 (inventory name), 2.4 (non-living entity support, changeable inventory name)") -public class ExprName extends SimplePropertyExpression { - - @Nullable - static final MethodHandle TITLE_METHOD; - static final boolean HAS_GAMERULES; +public class ExprName extends SimplePropertyExpression { static { - HAS_GAMERULES = Skript.classExists("org.bukkit.GameRule"); - register(ExprName.class, String.class, "(1¦name[s]|2¦(display|nick|chat|custom)[ ]name[s])", "offlineplayers/entities/blocks/itemtypes/inventories/slots" - + (HAS_GAMERULES ? "/gamerules" : "")); - register(ExprName.class, String.class, "(3¦(player|tab)[ ]list name[s])", "players"); - - // Get the old method for getting the name of an inventory. - MethodHandle _METHOD = null; - try { - _METHOD = MethodHandles.lookup().findVirtual(Inventory.class, "getTitle", MethodType.methodType(String.class)); - } catch (IllegalAccessException | NoSuchMethodException ignored) {} - TITLE_METHOD = _METHOD; + register(ExprName.class, Component.class, + "(1:name[s]|2:(display|nick|chat|custom)[ ]name[s])", + "offlineplayers/entities/blocks/itemtypes/inventories/slots/gamerules" + ); + register(ExprName.class, Component.class, "(3:(player|tab)[ ]list name[s])", "players"); } /* @@ -137,51 +123,45 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye @Override @Nullable - public String convert(Object o) { + public Component convert(Object o) { if (o instanceof OfflinePlayer && ((OfflinePlayer) o).isOnline()) o = ((OfflinePlayer) o).getPlayer(); if (o instanceof Player) { switch (mark) { case 1: - return ((Player) o).getName(); + return ((Player) o).name(); case 2: - return ((Player) o).getDisplayName(); + return ((Player) o).displayName(); case 3: - return ((Player) o).getPlayerListName(); + return ((Player) o).playerListName(); } } else if (o instanceof OfflinePlayer) { - return mark == 1 ? ((OfflinePlayer) o).getName() : null; + if (mark != 1) + return null; + String name = ((OfflinePlayer) o).getName(); + return name != null ? Component.text(name) : null; } else if (o instanceof Entity) { - return ((Entity) o).getCustomName(); + return ((Entity) o).customName(); } else if (o instanceof Block) { BlockState state = ((Block) o).getState(); if (state instanceof Nameable) - return ((Nameable) state).getCustomName(); + return ((Nameable) state).customName(); } else if (o instanceof ItemType) { ItemMeta m = ((ItemType) o).getItemMeta(); - return m.hasDisplayName() ? m.getDisplayName() : null; + return m.hasDisplayName() ? m.displayName() : null; } else if (o instanceof Inventory) { - if (TITLE_METHOD != null) { - try { - return (String) TITLE_METHOD.invoke(o); - } catch (Throwable e) { - Skript.exception(e); - return null; - } - } else { - if (!((Inventory) o).getViewers().isEmpty()) - return ((Inventory) o).getViewers().get(0).getOpenInventory().getTitle(); - return null; - } + if (!((Inventory) o).getViewers().isEmpty()) + return ((Inventory) o).getViewers().get(0).getOpenInventory().title(); + return null; } else if (o instanceof Slot) { ItemStack is = ((Slot) o).getItem(); if (is != null && is.hasItemMeta()) { ItemMeta m = is.getItemMeta(); - return m.hasDisplayName() ? m.getDisplayName() : null; + return m.hasDisplayName() ? m.displayName() : null; } - } else if (HAS_GAMERULES && o instanceof GameRule) { - return ((GameRule) o).getName(); + } else if (o instanceof GameRule) { + return Component.text(((GameRule) o).getName()); } return null; } @@ -194,26 +174,26 @@ public Class[] acceptChange(ChangeMode mode) { Skript.error("Can't change the Minecraft name of a player. Change the 'display name' or 'tab list name' instead."); return null; } - return CollectionUtils.array(String.class); + return CollectionUtils.array(Component.class); } return null; } @Override public void change(Event e, @Nullable Object[] delta, ChangeMode mode) { - String name = delta != null ? (String) delta[0] : null; + Component name = delta != null ? (Component) delta[0] : null; for (Object o : getExpr().getArray(e)) { if (o instanceof Player) { switch (mark) { case 2: - ((Player) o).setDisplayName(name != null ? name + ChatColor.RESET : ((Player) o).getName()); + ((Player) o).displayName(name); break; - case 3: // Null check not necessary. This method will use the player's name if 'name' is null. - ((Player) o).setPlayerListName(name); + case 3: + ((Player) o).playerListName(name); break; } } else if (o instanceof Entity) { - ((Entity) o).setCustomName(name); + ((Entity) o).customName(name); if (mark == 2 || mode == ChangeMode.RESET) // Using "display name" ((Entity) o).setCustomNameVisible(name != null); if (o instanceof LivingEntity) @@ -221,13 +201,13 @@ public void change(Event e, @Nullable Object[] delta, ChangeMode mode) { } else if (o instanceof Block) { BlockState state = ((Block) o).getState(); if (state instanceof Nameable) { - ((Nameable) state).setCustomName(name); + ((Nameable) state).customName(name); state.update(); } } else if (o instanceof ItemType) { ItemType i = (ItemType) o; ItemMeta m = i.getItemMeta(); - m.setDisplayName(name); + m.displayName(name); i.setItemMeta(m); } else if (o instanceof Inventory) { Inventory inv = (Inventory) o; @@ -241,7 +221,7 @@ public void change(Event e, @Nullable Object[] delta, ChangeMode mode) { if (!type.isCreatable()) return; if (name == null) - name = type.getDefaultTitle(); + name = type.defaultTitle(); Inventory copy; if (type == InventoryType.CHEST) { @@ -256,7 +236,7 @@ public void change(Event e, @Nullable Object[] delta, ChangeMode mode) { ItemStack is = s.getItem(); if (is != null && !AIR.isOfType(is)) { ItemMeta m = is.hasItemMeta() ? is.getItemMeta() : Bukkit.getItemFactory().getItemMeta(is.getType()); - m.setDisplayName(name); + m.displayName(name); is.setItemMeta(m); s.setItem(is); } @@ -265,17 +245,19 @@ public void change(Event e, @Nullable Object[] delta, ChangeMode mode) { } @Override - public Class getReturnType() { - return String.class; + public Class getReturnType() { + return Component.class; } @Override protected String getPropertyName() { switch (mark) { - case 1: return "name"; - case 2: return "display name"; - case 3: return "tablist name"; - default: return "name"; + case 2: + return "display name"; + case 3: + return "tablist name"; + default: + return "name"; } } diff --git a/src/main/java/ch/njol/skript/expressions/ExprNamed.java b/src/main/java/ch/njol/skript/expressions/ExprNamed.java index c01724bb7f2..2a7a6e1f9f7 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprNamed.java +++ b/src/main/java/ch/njol/skript/expressions/ExprNamed.java @@ -18,6 +18,7 @@ */ package ch.njol.skript.expressions; +import net.kyori.adventure.text.Component; import org.bukkit.Bukkit; import org.bukkit.event.Event; import org.bukkit.event.inventory.InventoryType; @@ -39,42 +40,45 @@ import ch.njol.skript.util.Getter; import ch.njol.util.Kleenean; -/** - * @author Peter Güttinger - */ @Name("Named Item/Inventory") -@Description("Directly names an item/inventory, useful for defining a named item/inventory in a script. " + - "If you want to (re)name existing items/inventories you can either use this expression or use set name of <item/inventory> to <text>.") -@Examples({"give a diamond sword of sharpness 100 named \"<gold>Excalibur\" to the player", - "set tool of player to the player's tool named \"<gold>Wand\"", - "set the name of the player's tool to \"<gold>Wand\"", - "open hopper inventory named \"Magic Hopper\" to player"}) +@Description({ + "Directly names an item/inventory, useful for defining a named item/inventory in a script.", + "If you want to (re)name existing items/inventories you can either use this expression or " + + "use set name of <item/inventory> to <text>." +}) +@Examples({ + "give a diamond sword of sharpness 100 named \"<gold>Excalibur\" to the player", + "set tool of player to the player's tool named \"<gold>Wand\"", + "set the name of the player's tool to \"<gold>Wand\"", + "open hopper inventory named \"Magic Hopper\" to player" +}) @Since("2.0, 2.2-dev34 (inventories)") public class ExprNamed extends PropertyExpression { + static { Skript.registerExpression(ExprNamed.class, Object.class, ExpressionType.PROPERTY, - "%itemtype/inventorytype% (named|with name[s]) %string%"); + "%itemtype/inventorytype% (named|with name[s]) %component%" + ); } - @SuppressWarnings("null") - private Expression name; - - @SuppressWarnings({"unchecked", "null"}) + @SuppressWarnings("NotNullFieldNotInitialized") + private Expression name; + @Override - public boolean init(final Expression[] exprs, final int matchedPattern, final Kleenean isDelayed, final ParseResult parseResult) { + @SuppressWarnings("unchecked") + public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { setExpr(exprs[0]); - name = (Expression) exprs[1]; + name = (Expression) exprs[1]; return true; } @Override protected Object[] get(final Event e, final Object[] source) { - String name = this.name.getSingle(e); + Component name = this.name.getSingle(e); if (name == null) return get(source, obj -> obj); // No name provided, do nothing return get(source, new Getter() { @Override - @Nullable public Object get(Object obj) { if (obj instanceof InventoryType) return Bukkit.createInventory(null, (InventoryType) obj, name); @@ -83,7 +87,7 @@ public Object get(Object obj) { stack = stack.clone(); ItemMeta meta = stack.getItemMeta(); if (meta != null) { - meta.setDisplayName(name); + meta.displayName(name); stack.setItemMeta(meta); } return new ItemType(stack); @@ -91,7 +95,7 @@ public Object get(Object obj) { ItemType item = (ItemType) obj; item = item.clone(); ItemMeta meta = item.getItemMeta(); - meta.setDisplayName(name); + meta.displayName(name); item.setItemMeta(meta); return item; } @@ -99,13 +103,13 @@ public Object get(Object obj) { } @Override - public Class getReturnType() { + public Class getReturnType() { return getExpr().getReturnType() == InventoryType.class ? Inventory.class : ItemType.class; } @Override - public String toString(final @Nullable Event e, final boolean debug) { - return getExpr().toString(e, debug) + " named " + name; + public String toString(@Nullable Event e, boolean debug) { + return getExpr().toString(e, debug) + " named " + name.toString(e, debug); } } diff --git a/src/main/java/ch/njol/skript/expressions/ExprPlayerListHeaderFooter.java b/src/main/java/ch/njol/skript/expressions/ExprPlayerListHeaderFooter.java index c8dc302014c..40aeaf51e71 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprPlayerListHeaderFooter.java +++ b/src/main/java/ch/njol/skript/expressions/ExprPlayerListHeaderFooter.java @@ -29,7 +29,6 @@ import ch.njol.skript.lang.SkriptParser.ParseResult; import ch.njol.util.Kleenean; import ch.njol.util.coll.CollectionUtils; -import io.skriptlang.skript.chat.util.ComponentHandler; import net.kyori.adventure.audience.Audience; import net.kyori.adventure.text.Component; import org.bukkit.entity.Player; @@ -44,24 +43,26 @@ "reset all players' tab list header" }) @Since("2.4") -public class ExprPlayerListHeaderFooter extends SimplePropertyExpression { +public class ExprPlayerListHeaderFooter extends SimplePropertyExpression { static { - PropertyExpression.register(ExprPlayerListHeaderFooter.class, String.class, "(player|tab)[ ]list (header|1¦footer) [(text|message)]", "players"); + PropertyExpression.register(ExprPlayerListHeaderFooter.class, Component.class, + "(player|tab)[ ]list (header|:footer) [(text|message)]", "players" + ); } - private boolean isHeader; + private boolean footer; @Override public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { - isHeader = parseResult.mark == 0; + footer = parseResult.hasTag("footer"); return super.init(exprs, matchedPattern, isDelayed, parseResult); } @Override @Nullable - public String convert(Player player) { - return isHeader ? player.getPlayerListHeader() : player.getPlayerListFooter(); + public Component convert(Player player) { + return footer ? player.playerListFooter() : player.playerListHeader(); } @Override @@ -71,7 +72,7 @@ public Class[] acceptChange(ChangeMode mode) { case SET: case DELETE: case RESET: - return CollectionUtils.array(String[].class, Component.class); + return CollectionUtils.array(Component[].class); default: return null; } @@ -79,30 +80,26 @@ public Class[] acceptChange(ChangeMode mode) { @Override public void change(Event e, @Nullable Object[] delta, ChangeMode mode) { - Component component; - if (delta == null) { - component = Component.empty(); - } else if (delta[0] instanceof Component) { - component = (Component) delta[0]; + Component component = Component.empty(); + for (Object userComponent : delta) + component = component.append((Component) userComponent).append(Component.newline()); + + Audience audience = Audience.audience(getExpr().getArray(e)); + if (footer) { + audience.sendPlayerListFooter(component); } else { - component = ComponentHandler.parse(String.join("\n", (String[]) delta), false); - } - Audience audience = ComponentHandler.audienceFrom(getExpr().getArray(e)); - if (isHeader) { audience.sendPlayerListHeader(component); - } else { - audience.sendPlayerListFooter(component); } } @Override - public Class getReturnType() { - return String.class; + public Class getReturnType() { + return Component.class; } @Override protected String getPropertyName() { - return "player list " + (isHeader ? "header" : "footer"); + return "player list " + (footer ? "header" : "footer"); } } diff --git a/src/main/java/org/skriptlang/skript/bukkit/chat/ChatModule.java b/src/main/java/org/skriptlang/skript/bukkit/chat/ChatModule.java index 81f0dc6031c..d6f16121cf9 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/chat/ChatModule.java +++ b/src/main/java/org/skriptlang/skript/bukkit/chat/ChatModule.java @@ -20,9 +20,11 @@ import ch.njol.skript.SkriptAddon; import ch.njol.skript.classes.ClassInfo; +import ch.njol.skript.classes.Comparator; import ch.njol.skript.classes.Parser; import ch.njol.skript.lang.ParseContext; import ch.njol.skript.registrations.Classes; +import ch.njol.skript.registrations.Comparators; import ch.njol.skript.registrations.Converters; import org.skriptlang.skript.bukkit.chat.util.ComponentHandler; import net.kyori.adventure.text.Component; @@ -37,13 +39,24 @@ public class ChatModule { public void register(SkriptAddon addon) { try { - addon.loadClasses("io.skriptlang.skript.chat.elements"); + addon.loadClasses("org.skriptlang.skript.bukkit.chat.elements"); } catch (IOException e) { e.printStackTrace(); } Converters.registerConverter(String.class, Component.class, ComponentHandler::parse); Converters.registerConverter(Component.class, String.class, ComponentHandler::toLegacyString); + Comparators.registerComparator(String.class, Component.class, new Comparator() { + @Override + public Relation compare(String o1, Component o2) { + return Relation.get(o1.equals(ComponentHandler.toLegacyString(o2))); + } + + @Override + public boolean supportsOrdering() { + return false; + } + }); Classes.registerClass(new ClassInfo<>(Component.class, "component") .user("components?") @@ -67,9 +80,6 @@ public String toVariableNameString(Component component) { }) ); - // Just to initialize it now - ComponentHandler.getAdventure(); - ComponentHandler.registerPlaceholder("dark_cyan", ""); ComponentHandler.registerPlaceholder("dark_turquoise", ""); ComponentHandler.registerPlaceholder("cyan", ""); diff --git a/src/main/java/org/skriptlang/skript/bukkit/chat/elements/EffBroadcast.java b/src/main/java/org/skriptlang/skript/bukkit/chat/elements/EffBroadcast.java index 48453dba1f5..a224eb43c11 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/chat/elements/EffBroadcast.java +++ b/src/main/java/org/skriptlang/skript/bukkit/chat/elements/EffBroadcast.java @@ -29,6 +29,8 @@ import ch.njol.skript.lang.SkriptParser.ParseResult; import ch.njol.skript.util.LiteralUtils; import ch.njol.util.Kleenean; +import ch.njol.util.coll.CollectionUtils; +import net.kyori.adventure.text.Component; import org.skriptlang.skript.bukkit.chat.util.ComponentHandler; import net.kyori.adventure.audience.Audience; import org.bukkit.Bukkit; @@ -47,13 +49,12 @@ "broadcast \"Woah! It's a message!\"" }) @Since("1.0, 2.6 (broadcasting objects), 2.6.1 (using advanced formatting)") -// TODO see what might need taken from https://github.com/SkriptLang/Skript/pull/4545 public class EffBroadcast extends Effect { @SuppressWarnings("NotNullFieldNotInitialized") private Expression[] messages; @SuppressWarnings("NotNullFieldNotInitialized") - private Expression messageExpr; // Used in toString + private Expression messageExpr; @Nullable private Expression worlds; @@ -65,24 +66,34 @@ public class EffBroadcast extends Effect { @SuppressWarnings("unchecked") public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { messageExpr = LiteralUtils.defendExpression(exprs[0]); - messages = messageExpr instanceof ExpressionList ? - ((ExpressionList) messageExpr).getExpressions() : new Expression[]{messageExpr}; + if (messageExpr instanceof ExpressionList) { + ExpressionList exprList = (ExpressionList) messageExpr; + if (exprList.getAnd()) { + messages = exprList.getExpressions(); + } else { + messages = new Expression[]{CollectionUtils.getRandom(exprList.getExpressions())}; + } + } else { + messages = new Expression[]{messageExpr}; + } + worlds = (Expression) exprs[1]; return LiteralUtils.canInitSafely(messageExpr); } @Override protected void execute(Event e) { - List recipients = new ArrayList<>(); if (worlds == null) { - recipients.addAll(Bukkit.getOnlinePlayers()); - recipients.add(Bukkit.getConsoleSender()); + for (Component component : ComponentHandler.parseFromExpressions(e, messages)) + Bukkit.broadcast(component); } else { + List recipients = new ArrayList<>(); for (World world : worlds.getArray(e)) recipients.addAll(world.getPlayers()); + Audience audience = Audience.audience(recipients); + for (Component component : ComponentHandler.parseFromExpressions(e, messages)) + audience.sendMessage(component); } - Audience audience = ComponentHandler.audienceFrom(recipients); - ComponentHandler.parseFromExpressions(e, messages).forEach(audience::sendMessage); } @Override diff --git a/src/main/java/org/skriptlang/skript/bukkit/chat/elements/EffMessage.java b/src/main/java/org/skriptlang/skript/bukkit/chat/elements/EffMessage.java index 8162a047bfa..42e6d841707 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/chat/elements/EffMessage.java +++ b/src/main/java/org/skriptlang/skript/bukkit/chat/elements/EffMessage.java @@ -30,6 +30,7 @@ import ch.njol.skript.lang.SkriptParser.ParseResult; import ch.njol.skript.util.LiteralUtils; import ch.njol.util.Kleenean; +import ch.njol.util.coll.CollectionUtils; import org.skriptlang.skript.bukkit.chat.util.ComponentHandler; import net.kyori.adventure.audience.Audience; import net.kyori.adventure.identity.Identity; @@ -61,7 +62,6 @@ }) @RequiredPlugins("Minecraft 1.16.4+ for optional sender") @Since("1.0, 2.2-dev26 (advanced features), 2.5.2 (optional sender), 2.6 (sending objects)") -// See what might need taken from https://github.com/SkriptLang/Skript/pull/4545 public class EffMessage extends Effect { static { @@ -74,7 +74,7 @@ public class EffMessage extends Effect { @SuppressWarnings("NotNullFieldNotInitialized") private Expression[] messages; @SuppressWarnings("NotNullFieldNotInitialized") - private Expression messageExpr; // Used in toString + private Expression messageExpr; @SuppressWarnings("NotNullFieldNotInitialized") private Expression recipients; @@ -87,9 +87,19 @@ public class EffMessage extends Effect { @SuppressWarnings("unchecked") public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { isChatMessage = matchedPattern == 0; + messageExpr = LiteralUtils.defendExpression(exprs[0]); - messages = messageExpr instanceof ExpressionList ? - ((ExpressionList) messageExpr).getExpressions() : new Expression[]{messageExpr}; + if (messageExpr instanceof ExpressionList) { + ExpressionList exprList = (ExpressionList) messageExpr; + if (exprList.getAnd()) { + messages = exprList.getExpressions(); + } else { + messages = new Expression[]{CollectionUtils.getRandom(exprList.getExpressions())}; + } + } else { + messages = new Expression[]{messageExpr}; + } + recipients = (Expression) exprs[1]; if (isChatMessage) sender = (Expression) exprs[2]; @@ -98,8 +108,7 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye @Override protected void execute(Event e) { - long start = System.nanoTime(); - Audience audience = ComponentHandler.audienceFrom(recipients.getArray(e)); + Audience audience = Audience.audience(recipients.getArray(e)); List components = ComponentHandler.parseFromExpressions(e, messages); @@ -109,9 +118,9 @@ protected void execute(Event e) { for (Component component : components) audience.sendMessage(identity, component); } else { - components.forEach(audience::sendActionBar); + for (Component component : components) + audience.sendActionBar(component); } - System.out.println("TIME TO EXECUTE SEND MESSAGE: " + (1. * (System.nanoTime() - start) / 1000000.)); } @Override diff --git a/src/main/java/org/skriptlang/skript/bukkit/chat/elements/EffSendTitle.java b/src/main/java/org/skriptlang/skript/bukkit/chat/elements/EffSendTitle.java index fecd73c6d41..38ea543313c 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/chat/elements/EffSendTitle.java +++ b/src/main/java/org/skriptlang/skript/bukkit/chat/elements/EffSendTitle.java @@ -41,18 +41,22 @@ @Name("Send Title") @Description({ - "Sends a title/subtitle to the given player(s) with optional fadein/stay/fadeout times for Minecraft versions 1.11 and above.", - "Note: if no input is given for the title/subtitle or the times, " + - "it will keep the ones from the last title sent, use the reset title effect to restore the default values." + "Sends a title/subtitle to the given player(s) with optional fadein/stay/fadeout times for Minecraft versions 1.11 and above. ", + "", + "If you're sending only the subtitle, it will be shown only if there's a title displayed at the moment, otherwise it will " + + "be sent with the next title. To show only the subtitle, use: send title \" \" with subtitle \"yourtexthere\" to player.", + "", + "Note: if no input is given for the times, it will keep the ones from the last title sent, " + + "use the reset title effect to restore the default values." }) @Examples({ - "send title \"Competition Started\" with subtitle \"Have fun, Stay safe!\" to player for 5 seconds", - "send title \"Hi %player%\" to player", "send title \"Loot Drop\" with subtitle \"starts in 3 minutes\" to all players", - "send title \"Hello %player%!\" with subtitle \"Welcome to our server\" to player for 5 seconds with fadein 1 second and fade out 1 second", - "send subtitle \"Party!\" to all players" + "send title \"Competition Started\" with subtitle \"Have fun, Stay safe!\" to player for 5 seconds", + "send title \"Hi %player%\" to player", + "send title \"Loot Drop\" with subtitle \"starts in 3 minutes\" to all players", + "send title \"Hello %player%!\" with subtitle \"Welcome to our server\" to player for 5 seconds with fadein 1 second and fade out 1 second", + "send subtitle \"Party!\" to all players" }) @Since("2.3, INSERT VERSION (sending objects)") -// TODO see what might need taken from https://github.com/SkriptLang/Skript/pull/4362 public class EffSendTitle extends Effect { static { @@ -85,18 +89,17 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye @Override protected void execute(Event e) { - Audience audience = ComponentHandler.audienceFrom(recipients.getArray(e)); + Audience audience = Audience.audience(recipients.getArray(e)); Timespan fadeIn = this.fadeIn != null ? this.fadeIn.getSingle(e) : null; Timespan stay = this.stay != null ? this.stay.getSingle(e) : null; Timespan fadeOut = this.fadeOut != null ? this.fadeOut.getSingle(e) : null; - // From Title#DEFAULT_TIMES - Duration fadeInDuration = fadeIn != null ? Ticks.duration(fadeIn.getTicks_i()) : Ticks.duration(10); - Duration stayDuration = stay != null ? Ticks.duration(stay.getTicks_i()) : Ticks.duration(70); - Duration fadeOutDuration = fadeOut != null ? Ticks.duration(fadeOut.getTicks_i()) : Ticks.duration(20); + Duration fadeInDuration = fadeIn != null ? Ticks.duration(fadeIn.getTicks_i()) : Title.DEFAULT_TIMES.fadeIn(); + Duration stayDuration = stay != null ? Ticks.duration(stay.getTicks_i()) : Title.DEFAULT_TIMES.stay(); + Duration fadeOutDuration = fadeOut != null ? Ticks.duration(fadeOut.getTicks_i()) : Title.DEFAULT_TIMES.fadeOut(); - Times times = Times.of(fadeInDuration, stayDuration, fadeOutDuration); + Times times = Times.times(fadeInDuration, stayDuration, fadeOutDuration); Title title = Title.title(ComponentHandler.parseFromSingleExpression(e, this.title), ComponentHandler.parseFromSingleExpression(e, this.subtitle), times); audience.showTitle(title); @@ -119,12 +122,14 @@ public String toString(@Nullable Event e, boolean debug) { if (stay != null) { builder.append(" for ").append(stay.toString(e, debug)); } else { - builder.append(" for 70 ticks"); + long ticks = Title.DEFAULT_TIMES.stay().toMillis() / Ticks.SINGLE_TICK_DURATION_MS; + builder.append(" for ").append(ticks).append(" ticks"); } if (fadeIn != null) { builder.append(" with fade in ").append(fadeIn.toString(e, debug)); } else { - builder.append(" with fade in 10 ticks"); + long ticks = Title.DEFAULT_TIMES.fadeIn().toMillis() / Ticks.SINGLE_TICK_DURATION_MS; + builder.append(" with fade in ").append(ticks).append(" ticks"); } if (fadeOut != null) { builder.append(" with fade out ").append(fadeOut.toString(e, debug)); @@ -134,7 +139,8 @@ public String toString(@Nullable Event e, boolean debug) { } else { builder.append(" with"); } - builder.append(" fade out 20 ticks"); + long ticks = Title.DEFAULT_TIMES.fadeOut().toMillis() / Ticks.SINGLE_TICK_DURATION_MS; + builder.append(" fade out ").append(ticks).append(" ticks"); } return builder.toString(); diff --git a/src/main/java/org/skriptlang/skript/bukkit/chat/util/ComponentHandler.java b/src/main/java/org/skriptlang/skript/bukkit/chat/util/ComponentHandler.java index ca46b795d90..b1667375ffa 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/chat/util/ComponentHandler.java +++ b/src/main/java/org/skriptlang/skript/bukkit/chat/util/ComponentHandler.java @@ -18,13 +18,9 @@ */ package org.skriptlang.skript.bukkit.chat.util; -import ch.njol.skript.Skript; import ch.njol.skript.lang.Expression; import ch.njol.skript.lang.VariableString; import ch.njol.skript.registrations.Classes; -import net.kyori.adventure.audience.Audience; -import net.kyori.adventure.platform.bukkit.BukkitAudiences; -import net.kyori.adventure.platform.bukkit.BukkitComponentSerializer; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.minimessage.Context; import net.kyori.adventure.text.minimessage.MiniMessage; @@ -33,14 +29,13 @@ import net.kyori.adventure.text.minimessage.tag.resolver.ArgumentQueue; import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; import net.kyori.adventure.text.minimessage.tag.standard.StandardTags; +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; -import org.bukkit.command.CommandSender; import org.bukkit.event.Event; import org.eclipse.jdt.annotation.Nullable; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; -import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -303,53 +298,20 @@ public static String toLegacyString(String string, boolean all) { return toLegacyString(parse(string, !all)); } + private static final LegacyComponentSerializer LEGACY_SERIALIZER = LegacyComponentSerializer.builder() + .hexColors() + .hexCharacter(LegacyComponentSerializer.HEX_CHAR) + .character(LegacyComponentSerializer.SECTION_CHAR) + .useUnusualXRepeatedCharacterHexFormat() + .build(); + /** * Converts a component into a legacy formatted string. * @param component The component to convert. * @return The legacy string. */ public static String toLegacyString(Component component) { - return BukkitComponentSerializer.legacy().serialize(component); - } - - @Nullable - private static BukkitAudiences adventure = null; // Can't set here as we need an instance of Skript - - public static BukkitAudiences getAdventure() { - if (adventure == null) - adventure = BukkitAudiences.create(Skript.getInstance()); - // TODO we might need to close this ('adventure.close()') - return adventure; - } - - /** - * Constructs an audience from command senders. - * @param senders The members of this audience. - * @return An audience consisting of the provided command senders. - */ - @SuppressWarnings("ConstantConditions") - public static Audience audienceFrom(Collection senders) { - List bukkitAudiences = new ArrayList<>(); - for (CommandSender sender : senders) { - if (sender instanceof Audience) { // On paper, a CommandSender is an Audience - bukkitAudiences.add(sender); - } else { - bukkitAudiences.add(getAdventure().sender(sender)); - } - } - return Audience.audience(bukkitAudiences); - } - - /** - * Constructs an audience from command senders. - * @param senders The members of this audience. - * @return An audience consisting of the provided command senders. - */ - public static Audience audienceFrom(CommandSender... senders) { - List bukkitAudiences = new ArrayList<>(); - for (CommandSender sender : senders) - bukkitAudiences.add(getAdventure().sender(sender)); - return Audience.audience(bukkitAudiences); + return LEGACY_SERIALIZER.serialize(component); } } diff --git a/src/test/skript/environments/java8/paper-1.13.2.json b/src/test/skript/environments/java8/paper-1.13.2.json deleted file mode 100644 index e6efb949c03..00000000000 --- a/src/test/skript/environments/java8/paper-1.13.2.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "paper-1.13.2", - "resources": [ - {"source": "server.properties.generic", "target": "server.properties"} - ], - "paperDownloads": [ - { - "version": "1.13.2", - "target": "paperclip.jar" - } - ], - "skriptTarget": "plugins/Skript.jar", - "commandLine": [ - "-Dcom.mojang.eula.agree=true", - "-jar", "paperclip.jar" - ] -} diff --git a/src/test/skript/environments/java8/paper-1.14.4.json b/src/test/skript/environments/java8/paper-1.14.4.json deleted file mode 100644 index 1e2972dd84c..00000000000 --- a/src/test/skript/environments/java8/paper-1.14.4.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "paper-1.14.4", - "resources": [ - {"source": "server.properties.generic", "target": "server.properties"} - ], - "paperDownloads": [ - { - "version": "1.14.4", - "target": "paperclip.jar" - } - ], - "skriptTarget": "plugins/Skript.jar", - "commandLine": [ - "-Dcom.mojang.eula.agree=true", - "-jar", "paperclip.jar" - ] -} diff --git a/src/test/skript/environments/java8/paper-1.15.2.json b/src/test/skript/environments/java8/paper-1.15.2.json deleted file mode 100644 index 08a849ff98d..00000000000 --- a/src/test/skript/environments/java8/paper-1.15.2.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "paper-1.15.2", - "resources": [ - {"source": "server.properties.generic", "target": "server.properties"} - ], - "paperDownloads": [ - { - "version": "1.15.2", - "target": "paperclip.jar" - } - ], - "skriptTarget": "plugins/Skript.jar", - "commandLine": [ - "-Dcom.mojang.eula.agree=true", - "-jar", "paperclip.jar", "--nogui" - ] -} diff --git a/src/test/skript/environments/java8/paper-1.16.5.json b/src/test/skript/environments/java8/paper-1.16.5.json deleted file mode 100644 index 690a180c001..00000000000 --- a/src/test/skript/environments/java8/paper-1.16.5.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "paper-1.16.5", - "resources": [ - {"source": "server.properties.generic", "target": "server.properties"} - ], - "paperDownloads": [ - { - "version": "1.16.5", - "target": "paperclip.jar" - } - ], - "skriptTarget": "plugins/Skript.jar", - "commandLine": [ - "-Dcom.mojang.eula.agree=true", - "-jar", "paperclip.jar", "--nogui" - ] -}