diff --git a/src/main/java/ch/njol/skript/effects/EffBroadcast.java b/src/main/java/ch/njol/skript/effects/EffBroadcast.java index 5e2b8fbdefb..fd6ef3ff245 100644 --- a/src/main/java/ch/njol/skript/effects/EffBroadcast.java +++ b/src/main/java/ch/njol/skript/effects/EffBroadcast.java @@ -18,6 +18,13 @@ */ package ch.njol.skript.effects; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.regex.Pattern; + import ch.njol.skript.Skript; import ch.njol.skript.doc.Description; import ch.njol.skript.doc.Examples; @@ -31,19 +38,20 @@ import ch.njol.skript.lang.VariableString; import ch.njol.skript.registrations.Classes; import ch.njol.skript.util.LiteralUtils; +import ch.njol.skript.util.SkriptColor; +import ch.njol.skript.util.Utils; import ch.njol.skript.util.chat.BungeeConverter; import ch.njol.skript.util.chat.ChatMessages; import ch.njol.util.Kleenean; +import ch.njol.util.StringUtils; import ch.njol.util.coll.CollectionUtils; import net.md_5.bungee.api.chat.BaseComponent; import org.bukkit.Bukkit; import org.bukkit.World; import org.bukkit.command.CommandSender; import org.bukkit.event.Event; -import org.eclipse.jdt.annotation.Nullable; - -import java.util.ArrayList; -import java.util.List; +import org.bukkit.event.server.BroadcastMessageEvent; +import org.jetbrains.annotations.Nullable; @Name("Broadcast") @Description("Broadcasts a message to the server.") @@ -54,6 +62,8 @@ @Since("1.0, 2.6 (broadcasting objects), 2.6.1 (using advanced formatting)") public class EffBroadcast extends Effect { + private static final Pattern HEX_PATTERN = Pattern.compile("(?i)&x((?:&\\p{XDigit}){6})"); + static { Skript.registerEffect(EffBroadcast.class, "broadcast %objects% [(to|in) %-worlds%]"); } @@ -65,8 +75,8 @@ public class EffBroadcast extends Effect { @Nullable private Expression worlds; - @SuppressWarnings("unchecked") @Override + @SuppressWarnings("unchecked") public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { messageExpr = LiteralUtils.defendExpression(exprs[0]); messages = messageExpr instanceof ExpressionList ? @@ -74,37 +84,51 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye worlds = (Expression) exprs[1]; return LiteralUtils.canInitSafely(messageExpr); } - + + /** + * This effect will call {@link BroadcastMessageEvent} as of INSERT_VERSION. + */ @Override @SuppressWarnings("deprecation") - public void execute(Event e) { + public void execute(Event event) { List receivers = new ArrayList<>(); if (worlds == null) { receivers.addAll(Bukkit.getOnlinePlayers()); receivers.add(Bukkit.getConsoleSender()); } else { - for (World world : worlds.getArray(e)) + for (World world : worlds.getArray(event)) receivers.addAll(world.getPlayers()); } for (Expression message : getMessages()) { if (message instanceof VariableString) { - BaseComponent[] components = BungeeConverter.convert(((VariableString) message).getMessageComponents(e)); + if (!dispatchEvent(getRawString(event, (VariableString) message), receivers)) + continue; + BaseComponent[] components = BungeeConverter.convert(((VariableString) message).getMessageComponents(event)); receivers.forEach(receiver -> receiver.spigot().sendMessage(components)); } else if (message instanceof ExprColoured && ((ExprColoured) message).isUnsafeFormat()) { // Manually marked as trusted - for (Object realMessage : message.getArray(e)) { + for (Object realMessage : message.getArray(event)) { + if (!dispatchEvent(Utils.replaceChatStyles((String) realMessage), receivers)) + continue; BaseComponent[] components = BungeeConverter.convert(ChatMessages.parse((String) realMessage)); receivers.forEach(receiver -> receiver.spigot().sendMessage(components)); } } else { - for (Object messageObject : message.getArray(e)) { + for (Object messageObject : message.getArray(event)) { String realMessage = messageObject instanceof String ? (String) messageObject : Classes.toString(messageObject); + if (!dispatchEvent(Utils.replaceChatStyles(realMessage), receivers)) + continue; receivers.forEach(receiver -> receiver.sendMessage(realMessage)); } } } } + @Override + public String toString(@Nullable Event event, boolean debug) { + return "broadcast " + messageExpr.toString(event, debug) + (worlds == null ? "" : " to " + worlds.toString(event, debug)); + } + private Expression[] getMessages() { if (messageExpr instanceof ExpressionList && !messageExpr.getAnd()) { return new Expression[] {CollectionUtils.getRandom(messages)}; @@ -112,9 +136,35 @@ private Expression[] getMessages() { return messages; } - @Override - public String toString(@Nullable Event e, boolean debug) { - return "broadcast " + messageExpr.toString(e, debug) + (worlds == null ? "" : " to " + worlds.toString(e, debug)); + /** + * Manually calls a {@link BroadcastMessageEvent}. + * @param message the message + * @return true if the dispatched event does not get cancelled + */ + @SuppressWarnings("deprecation") + private static boolean dispatchEvent(String message, List receivers) { + Set recipients = Collections.unmodifiableSet(new HashSet<>(receivers)); + BroadcastMessageEvent broadcastEvent; + if (Skript.isRunningMinecraft(1, 14)) { + broadcastEvent = new BroadcastMessageEvent(!Bukkit.isPrimaryThread(), message, recipients); + } else { + broadcastEvent = new BroadcastMessageEvent(message, recipients); + } + Bukkit.getPluginManager().callEvent(broadcastEvent); + return !broadcastEvent.isCancelled(); } - + + @Nullable + private static String getRawString(Event event, Expression string) { + if (string instanceof VariableString) + return ((VariableString) string).toUnformattedString(event); + String rawString = string.getSingle(event); + rawString = SkriptColor.replaceColorChar(rawString); + if (rawString.toLowerCase().contains("&x")) { + rawString = StringUtils.replaceAll(rawString, HEX_PATTERN, matchResult -> + "<#" + matchResult.group(1).replace("&", "") + '>'); + } + return rawString; + } + }