diff --git a/src/main/java/ch/njol/skript/classes/data/DefaultFunctions.java b/src/main/java/ch/njol/skript/classes/data/DefaultFunctions.java index 94ecbe7fe35..aeee3e3fb6b 100644 --- a/src/main/java/ch/njol/skript/classes/data/DefaultFunctions.java +++ b/src/main/java/ch/njol/skript/classes/data/DefaultFunctions.java @@ -90,7 +90,7 @@ public Long[] execute(final FunctionEvent e, final Object[][] params) { return new Long[] {(Long) params[0][0]}; return new Long[] {Math2.ceil(((Number) params[0][0]).doubleValue())}; } - }.description("Rounds a number down, i.e. returns the closest integer larger than or equal to the argument.") + }.description("Rounds a number up, i.e. returns the closest integer larger than or equal to the argument.") .examples("ceil(2.34) = 3", "ceil(2) = 2", "ceil(2.99) = 3") .since("2.2")); Functions.registerFunction(new JavaFunction("ceiling", numberParam, longClass, true) { diff --git a/src/main/java/ch/njol/skript/command/Commands.java b/src/main/java/ch/njol/skript/command/Commands.java index 7b8266bd569..4539fa651e9 100644 --- a/src/main/java/ch/njol/skript/command/Commands.java +++ b/src/main/java/ch/njol/skript/command/Commands.java @@ -427,14 +427,10 @@ else if (aliases.get(0).isEmpty()) final String rawPermissionMessage = ScriptLoader.replaceOptions(node.get("permission message", "")); - Expression permissionMessage = rawPermissionMessage.isEmpty() ? + VariableString permissionMessage = rawPermissionMessage.isEmpty() ? null : VariableString.newInstance(rawPermissionMessage); - if (permissionMessage != null && ((VariableString) permissionMessage).isSimple()) { - permissionMessage = new SimpleLiteral<>(rawPermissionMessage, false); - } - final SectionNode trigger = (SectionNode) node.get("trigger"); if (trigger == null) return null; diff --git a/src/main/java/ch/njol/skript/command/ScriptCommand.java b/src/main/java/ch/njol/skript/command/ScriptCommand.java index 02b5429dce6..6ce088afdb2 100644 --- a/src/main/java/ch/njol/skript/command/ScriptCommand.java +++ b/src/main/java/ch/njol/skript/command/ScriptCommand.java @@ -40,6 +40,8 @@ import ch.njol.skript.lang.util.SimpleLiteral; import ch.njol.skript.util.Date; import ch.njol.skript.util.Timespan; +import ch.njol.skript.util.chat.BungeeConverter; +import ch.njol.skript.util.chat.MessageComponent; import ch.njol.skript.variables.Variables; import org.bukkit.Bukkit; import org.bukkit.ChatColor; @@ -89,7 +91,7 @@ public class ScriptCommand implements CommandExecutor { private final List aliases; private List activeAliases; private String permission; - private final Expression permissionMessage; + private final VariableString permissionMessage; private final String description; @Nullable private final Timespan cooldown; @@ -126,15 +128,16 @@ public class ScriptCommand implements CommandExecutor { */ public ScriptCommand(final File script, final String name, final String pattern, final List> arguments, final String description, final String usage, final ArrayList aliases, - final String permission, @Nullable final Expression permissionMessage, @Nullable final Timespan cooldown, + final String permission, @Nullable final VariableString permissionMessage, @Nullable final Timespan cooldown, @Nullable final VariableString cooldownMessage, final String cooldownBypass, @Nullable VariableString cooldownStorage, final int executableBy, final List items) { Validate.notNull(name, pattern, arguments, description, usage, aliases, items); this.name = name; label = "" + name.toLowerCase(); this.permission = permission; + assert permissionMessage != null; this.permissionMessage = permissionMessage == null ? - new SimpleLiteral<>(Language.get("commands.no permission message"), false) + VariableString.newInstance(Language.get("commands.no permission message")) : permissionMessage; this.cooldown = cooldown; @@ -174,9 +177,9 @@ private PluginCommand setupBukkitCommand() { bukkitCommand.setDescription(description); bukkitCommand.setLabel(label); bukkitCommand.setPermission(permission); - // We can only set the message if it's available at parse time (aka a literal) - if (permissionMessage instanceof Literal) - bukkitCommand.setPermissionMessage(((Literal) permissionMessage).getSingle()); + // We can only set the message if it's simple (doesn't contains expressions) + if (permissionMessage.isSimple()) + bukkitCommand.setPermissionMessage(permissionMessage.toString(null)); bukkitCommand.setUsage(usage); bukkitCommand.setExecutor(this); return bukkitCommand; @@ -210,7 +213,13 @@ public boolean execute(final CommandSender sender, final String commandLabel, fi final ScriptCommandEvent event = new ScriptCommandEvent(ScriptCommand.this, sender); if (!permission.isEmpty() && !sender.hasPermission(permission)) { - sender.sendMessage(permissionMessage.getSingle(event)); + if (sender instanceof Player) { + List components = + permissionMessage.getMessageComponents(event); + ((Player) sender).spigot().sendMessage(BungeeConverter.convert(components)); + } else { + sender.sendMessage(permissionMessage.getSingle(event)); + } return false; } diff --git a/src/main/java/ch/njol/skript/conditions/CondDamageCause.java b/src/main/java/ch/njol/skript/conditions/CondDamageCause.java index 995973bf35c..0d884c0ec79 100644 --- a/src/main/java/ch/njol/skript/conditions/CondDamageCause.java +++ b/src/main/java/ch/njol/skript/conditions/CondDamageCause.java @@ -49,7 +49,7 @@ " apply fire resistance to the victim for 30 seconds", " remove 1 potion of fire resistance from the victim", "# prevent mobs from dropping items under certain circumstances", - "on death;", + "on death:", " entity is not a player", " damage wasn't caused by a block explosion, an attack, a projectile, a potion, fire, burning, thorns or poison", " clear drops"}) diff --git a/src/main/java/ch/njol/skript/effects/EffMessage.java b/src/main/java/ch/njol/skript/effects/EffMessage.java index 12cf4e564c7..963c45c459f 100644 --- a/src/main/java/ch/njol/skript/effects/EffMessage.java +++ b/src/main/java/ch/njol/skript/effects/EffMessage.java @@ -85,7 +85,7 @@ protected void execute(final Event e) { for (CommandSender sender : recipients.getArray(e)) { if (message instanceof VariableString && sender instanceof Player) { // this could contain json formatting List components = ((VariableString) message).getMessageComponents(e); - ((Player) sender).spigot().sendMessage(BungeeConverter.convert(components.toArray(new MessageComponent[components.size()]))); + ((Player) sender).spigot().sendMessage(BungeeConverter.convert(components)); } else { String string = message.getSingle(e); if (string != null) diff --git a/src/main/java/ch/njol/skript/effects/EffSendBlockChange.java b/src/main/java/ch/njol/skript/effects/EffSendBlockChange.java new file mode 100644 index 00000000000..68864502458 --- /dev/null +++ b/src/main/java/ch/njol/skript/effects/EffSendBlockChange.java @@ -0,0 +1,108 @@ +/** + * This file is part of Skript. + * + * Skript is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Skript is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Skript. If not, see . + * + * + * Copyright 2011-2017 Peter Güttinger and contributors + */ +package ch.njol.skript.effects; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.inventory.ItemStack; +import org.eclipse.jdt.annotation.Nullable; + +import ch.njol.skript.Skript; +import ch.njol.skript.aliases.ItemType; +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.lang.Effect; +import ch.njol.skript.lang.Expression; +import ch.njol.skript.lang.SkriptParser; +import ch.njol.util.Kleenean; + +@Name("Send Block Change") +@Description("Makes a player see a block as something it really isn't") +@Examples("make player see block at player as dirt") +@Since("INSERT VERSION") +public class EffSendBlockChange extends Effect { + + private static final boolean SUPPORTED = + Skript.methodExists( + Player.class, + "sendBlockChange", + Location.class, + Material.class, + byte.class + ); + + static { + Skript.registerEffect(EffSendBlockChange.class, + "make %players% see %blocks% as %itemstack%" + ); + } + + @SuppressWarnings("null") + private Expression players; + + @SuppressWarnings("null") + private Expression blocks; + + @SuppressWarnings("null") + private Expression as; + + @Override + protected void execute(Event e) { + ItemStack as = this.as.getSingle(e); + if (as == null) + return; + for (Player player : players.getArray(e)) { + for (Block block : blocks.getArray(e)) { + player.sendBlockChange(block.getLocation(), as.getType(), (byte) as.getDurability()); + } + } + } + + @Override + public String toString(@Nullable Event e, boolean debug) { + return String.format( + "make %s see %s as %s", + players.toString(e, debug), + blocks.toString(e, debug), + as.toString(e, debug) + ); + } + + @Override + @SuppressWarnings("unchecked") + public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, SkriptParser.ParseResult parseResult) { + if (!SUPPORTED) { + Skript.error("The send block change effect is not supported on this version. " + + "If Spigot has added a replacement method without magic values " + + "please open an issue at https://github.com/SkriptLang/Skript/issues " + + "and support will be added for it."); + return false; + } + players = (Expression) exprs[0]; + blocks = (Expression) exprs[1]; + as = (Expression) exprs[2]; + return true; + } +} diff --git a/src/main/java/ch/njol/skript/effects/EffVisualEffect.java b/src/main/java/ch/njol/skript/effects/EffVisualEffect.java index 9ff203b1c43..88cd26654db 100644 --- a/src/main/java/ch/njol/skript/effects/EffVisualEffect.java +++ b/src/main/java/ch/njol/skript/effects/EffVisualEffect.java @@ -97,8 +97,11 @@ public boolean init(final Expression[] exprs, final int matchedPattern, final Skript.warning("Entity effects are visible to all players"); if (!hasLocationEffect && !direction.isDefault()) Skript.warning("Entity effects are always played on an entity"); - if (hasEntityEffect && !Entity.class.isAssignableFrom(where.getReturnType())) + if (hasEntityEffect + && (!Entity.class.isAssignableFrom(where.getReturnType()) + || where.getReturnType() == Object.class)) { // variables and similar Skript.warning("Entity effects can only be played on entities"); + } } return true; } diff --git a/src/main/java/ch/njol/skript/expressions/ExprFilter.java b/src/main/java/ch/njol/skript/expressions/ExprFilter.java index a54bee60c52..315d36afa55 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprFilter.java +++ b/src/main/java/ch/njol/skript/expressions/ExprFilter.java @@ -20,6 +20,7 @@ package ch.njol.skript.expressions; import ch.njol.skript.Skript; +import ch.njol.skript.classes.Changer; import ch.njol.skript.classes.ClassInfo; import ch.njol.skript.doc.Description; import ch.njol.skript.doc.Examples; @@ -31,11 +32,13 @@ import ch.njol.skript.lang.Literal; import ch.njol.skript.lang.SkriptParser; import ch.njol.skript.lang.util.SimpleExpression; +import ch.njol.skript.registrations.Classes; import ch.njol.skript.registrations.Converters; import ch.njol.skript.util.LiteralUtils; import ch.njol.skript.util.Utils; import ch.njol.util.Kleenean; import org.bukkit.event.Event; +import org.eclipse.jdt.annotation.Nullable; import java.lang.reflect.Array; import java.util.ArrayList; @@ -49,57 +52,41 @@ @Examples("send \"congrats on being staff!\" to all players where [player input has permission \"staff\"]") @Since("2.2-dev36") @SuppressWarnings({"null", "unchecked"}) -public class ExprFilter extends SimpleExpression { +public class ExprFilter extends SimpleExpression { - private static ExprFilter parsing; + private static ExprFilter parsing; static { Skript.registerExpression(ExprFilter.class, Object.class, ExpressionType.COMBINED, "%objects% (where|that match) \\[<.+>\\]"); } - private ExprFilter source; private Object current; private List> children = new ArrayList<>(); - private Class superType; private Condition condition; private String rawCond; private Expression objects; - public ExprFilter() { - this(null, (Class) Object.class); - } - public ExprFilter(ExprFilter source, Class... types) { - this.source = source; - if (source != null) { - this.condition = source.condition; - this.rawCond = source.rawCond; - this.objects = source.objects; - this.children = source.children; - for (ExprInput child : children) { - child.setParent(this); - } - } - this.superType = (Class) Utils.getSuperType(types); - } - - public static ExprFilter getParsing() { + public static ExprFilter getParsing() { return parsing; } @Override public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, SkriptParser.ParseResult parseResult) { - parsing = this; - objects = LiteralUtils.defendExpression(exprs[0]); - rawCond = parseResult.regexes.get(0).group(); - condition = Condition.parse(rawCond, "Can't understand this condition: " + rawCond); - parsing = null; + try { + parsing = this; + objects = LiteralUtils.defendExpression(exprs[0]); + rawCond = parseResult.regexes.get(0).group(); + condition = Condition.parse(rawCond, "Can't understand this condition: " + rawCond); + } finally { + parsing = null; + } return condition != null && LiteralUtils.canInitSafely(objects); } @Override - protected T[] get(Event e) { + protected Object[] get(Event e) { List filtered = new ArrayList<>(); try { for (Object object : objects.getArray(e)) { @@ -112,7 +99,7 @@ protected T[] get(Event e) { current = null; } try { - return Converters.convertStrictly(filtered.toArray(), superType); + return Converters.convertStrictly(filtered.toArray(), objects.getReturnType()); } catch (ClassCastException e1) { return null; } @@ -122,23 +109,13 @@ public Object getCurrent() { return current; } - public void addChild(ExprInput child) { + private void addChild(ExprInput child) { children.add(child); } @Override - public Expression getConvertedExpression(Class... to) { - return new ExprFilter<>(this, to); - } - - @Override - public Expression getSource() { - return source == null ? this : source; - } - - @Override - public Class getReturnType() { - return superType; + public Class getReturnType() { + return objects.getReturnType(); } @Override @@ -154,7 +131,7 @@ public String toString(Event e, boolean debug) { @Override public boolean isLoopOf(String s) { for (ExprInput child : children) { // if they used player input, let's assume loop-player is valid - if (child.getClassInfo() == null) + if (child.getClassInfo() == null || child.getClassInfo().getUserInputPatterns() == null) continue; for (Pattern pattern : child.getClassInfo().getUserInputPatterns()) { if (pattern.matcher(s).matches()) { @@ -181,7 +158,7 @@ public static class ExprInput extends SimpleExpression { private ExprInput source; private Class superType; - private ExprFilter parent; + private ExprFilter parent; private Literal> inputType; public ExprInput() { @@ -222,7 +199,7 @@ protected T[] get(Event e) { } } - public void setParent(ExprFilter parent) { + public void setParent(ExprFilter parent) { this.parent = parent; } @@ -241,7 +218,7 @@ public Class getReturnType() { return superType; } - public ClassInfo getClassInfo() { + private ClassInfo getClassInfo() { return inputType == null ? null : inputType.getSingle(); } diff --git a/src/main/java/ch/njol/skript/expressions/ExprHighestSolidBlock.java b/src/main/java/ch/njol/skript/expressions/ExprHighestSolidBlock.java index 5351ffcd19e..cb4537aecf7 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprHighestSolidBlock.java +++ b/src/main/java/ch/njol/skript/expressions/ExprHighestSolidBlock.java @@ -38,12 +38,14 @@ public class ExprHighestSolidBlock extends SimplePropertyExpression { static { - Skript.registerExpression(ExprHighestSolidBlock.class, Block.class, ExpressionType.PROPERTY, "highest [(solid|non-air)] block at %locations%"); + Skript.registerExpression(ExprHighestSolidBlock.class, Block.class, ExpressionType.PROPERTY, + "highest [(solid|non-air)] block[s] at %locations%" + ); } @Override protected String getPropertyName() { - return "highest [(solid|non-air)] block"; + return "highest block"; } @Nullable diff --git a/src/main/java/ch/njol/skript/expressions/ExprIndexes.java b/src/main/java/ch/njol/skript/expressions/ExprIndexes.java new file mode 100644 index 00000000000..276213841f7 --- /dev/null +++ b/src/main/java/ch/njol/skript/expressions/ExprIndexes.java @@ -0,0 +1,99 @@ +/** + * This file is part of Skript. + * + * Skript is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Skript is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Skript. If not, see . + * + * + * Copyright 2011-2017 Peter Güttinger and contributors + */ +package ch.njol.skript.expressions; + +import java.util.TreeMap; + +import org.bukkit.event.Event; +import org.eclipse.jdt.annotation.Nullable; + +import ch.njol.skript.Skript; +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.lang.Expression; +import ch.njol.skript.lang.ExpressionType; +import ch.njol.skript.lang.SkriptParser; +import ch.njol.skript.lang.UnparsedLiteral; +import ch.njol.skript.lang.Variable; +import ch.njol.skript.lang.util.SimpleExpression; +import ch.njol.util.Kleenean; + +@Name("Indexes of List") +@Description("Returns all the indexes of a list variable") +@Examples("set {l::*} to \"some\", \"cool\" and \"values\"\n" + + "broadcast \"%all indexes of {l::*}%\" # result is 1, 2 and 3") +@Since("INSERT VERSION") +public class ExprIndexes extends SimpleExpression { + + static { + Skript.registerExpression(ExprIndexes.class, String.class, ExpressionType.COMBINED, + "[the] indexes of %objects%", + "(all of the|all the|all) indexes of %objects%" + ); + } + + @SuppressWarnings("null") + private Variable list; + + @Nullable + @Override + @SuppressWarnings("unchecked") + protected String[] get(Event e) { + TreeMap valueMap = (TreeMap) list.getRaw(e); + if (valueMap == null) { + return null; + } + return valueMap.keySet().toArray(new String[0]); + } + + @Override + public boolean isSingle() { + return false; + } + + @Override + public Class getReturnType() { + return String.class; + } + + @Override + public String toString(@Nullable Event e, boolean debug) { + // we need to provide a null event otherwise the string value is what's held in the var + return String.format("all indexes of %s", list.toString(null, debug)); + } + + @Override + public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, SkriptParser.ParseResult parseResult) { + if (exprs[0] instanceof Variable && ((Variable) exprs[0]).isList()) { + list = (Variable) exprs[0]; + return true; + } + + // things like "all indexes of fake expression" shouldn't have any output at all + if (!(exprs[0] instanceof UnparsedLiteral)) { + Skript.error("The indexes expression may only be used with list variables"); + } + + return false; + } + +} diff --git a/src/main/java/ch/njol/skript/expressions/ExprJoinSplit.java b/src/main/java/ch/njol/skript/expressions/ExprJoinSplit.java index 7302a20ea54..4cbc12d4fcc 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprJoinSplit.java +++ b/src/main/java/ch/njol/skript/expressions/ExprJoinSplit.java @@ -20,6 +20,7 @@ package ch.njol.skript.expressions; import java.util.regex.Pattern; +import java.util.stream.Stream; import org.bukkit.event.Event; import org.eclipse.jdt.annotation.Nullable; @@ -33,6 +34,8 @@ import ch.njol.skript.lang.ExpressionType; import ch.njol.skript.lang.SkriptParser.ParseResult; import ch.njol.skript.lang.util.SimpleExpression; +import ch.njol.skript.registrations.Classes; +import ch.njol.skript.util.LiteralUtils; import ch.njol.util.Kleenean; import ch.njol.util.StringUtils; @@ -47,13 +50,13 @@ public class ExprJoinSplit extends SimpleExpression { static { Skript.registerExpression(ExprJoinSplit.class, String.class, ExpressionType.COMBINED, - "(concat[enate]|join) %strings% [(with|using|by) [[the] delimiter] %-string%]", + "(concat[enate]|join) %objects% [(with|using|by) [[the] delimiter] %-string%]", "split %string% (at|using|by) [[the] delimiter] %string%", "%string% split (at|using|by) [[the] delimiter] %string%"); } private boolean join; @SuppressWarnings("null") - private Expression strings; + private Expression things; @Nullable private Expression delimiter; @@ -61,22 +64,27 @@ public class ExprJoinSplit extends SimpleExpression { @Override public boolean init(final Expression[] exprs, final int matchedPattern, final Kleenean isDelayed, final ParseResult parseResult) { join = matchedPattern == 0; - strings = (Expression) exprs[0]; + things = LiteralUtils.defendExpression(exprs[0]); delimiter = (Expression) exprs[1]; - return true; + return LiteralUtils.canInitSafely(things); } @Override @Nullable protected String[] get(final Event e) { - final String[] s = strings.getArray(e); + final Object[] t = things.getArray(e); final String d = delimiter != null ? delimiter.getSingle(e) : ""; - if (s.length == 0 || d == null) + if (t.length == 0 || d == null) return new String[0]; if (join) { - return new String[] {StringUtils.join(s, d)}; + return new String[] { + StringUtils.join( + Stream.of(t).map(Classes::toString).toArray(String[]::new), + d + ) + }; } else { - return s[0].split(Pattern.quote(d), -1); + return ((String) t[0]).split(Pattern.quote(d), -1); } } @@ -92,7 +100,7 @@ public Class getReturnType() { @Override public String toString(final @Nullable Event e, final boolean debug) { - return join ? "join " + strings.toString(e, debug) + (delimiter != null ? " with " + delimiter.toString(e, debug) : "") : "split " + strings.toString(e, debug) + (delimiter != null ? " at " + delimiter.toString(e, debug) : ""); + return join ? "join " + things.toString(e, debug) + (delimiter != null ? " with " + delimiter.toString(e, debug) : "") : "split " + things.toString(e, debug) + (delimiter != null ? " at " + delimiter.toString(e, debug) : ""); } } diff --git a/src/main/java/ch/njol/skript/expressions/ExprSpectatorTarget.java b/src/main/java/ch/njol/skript/expressions/ExprSpectatorTarget.java new file mode 100644 index 00000000000..91d2915d941 --- /dev/null +++ b/src/main/java/ch/njol/skript/expressions/ExprSpectatorTarget.java @@ -0,0 +1,91 @@ +/** + * This file is part of Skript. + * + * Skript is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Skript is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Skript. If not, see . + * + * + * Copyright 2011-2017 Peter Güttinger and contributors + */ +package ch.njol.skript.expressions; + +import org.bukkit.GameMode; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.eclipse.jdt.annotation.Nullable; + +import ch.njol.skript.classes.Changer; +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.util.coll.CollectionUtils; + +@Name("Spectator Target") +@Description("The entity a player is currently spectating. This can be set and cleared when" + + "the given player is in spectator mode.") +@Examples("set spectator target of player to last spawned creeper") +@Since("INSERT VERSION") +public class ExprSpectatorTarget extends SimplePropertyExpression { + + static { + register(ExprSpectatorTarget.class, Entity.class, "spectator target", "players"); + } + + @Override + protected String getPropertyName() { + return "spectator target"; + } + + @Nullable + @Override + public Entity convert(Player player) { + return player.getSpectatorTarget(); + } + + @Override + public Class getReturnType() { + return Entity.class; + } + + @Nullable + @Override + public Class[] acceptChange(Changer.ChangeMode mode) { + if (mode == Changer.ChangeMode.SET + || mode == Changer.ChangeMode.RESET + || mode == Changer.ChangeMode.DELETE) { + return CollectionUtils.array(Entity.class); + } + return null; + } + + @Override + public void change(Event e, @Nullable Object[] delta, Changer.ChangeMode mode) { + for (Player player : getExpr().getArray(e)) { + if (player.getGameMode() == GameMode.SPECTATOR) { + switch (mode) { + case SET: + assert delta != null; + player.setSpectatorTarget((Entity) delta[0]); + break; + case RESET: + case DELETE: + player.setSpectatorTarget(null); + } + } + } + } + +} diff --git a/src/main/java/ch/njol/skript/lang/Variable.java b/src/main/java/ch/njol/skript/lang/Variable.java index 000b36aa3ca..b0a5e04d2ba 100644 --- a/src/main/java/ch/njol/skript/lang/Variable.java +++ b/src/main/java/ch/njol/skript/lang/Variable.java @@ -226,7 +226,7 @@ public Variable getConvertedExpression(final Class... to) { * Gets the value of this variable as stored in the variables map. */ @Nullable - private Object getRaw(final Event e) { + public Object getRaw(final Event e) { final String n = name.toString(e); if (n.endsWith(Variable.SEPARATOR + "*") != list) // prevents e.g. {%expr%} where "%expr%" ends with "::*" from returning a Map return null; diff --git a/src/main/java/ch/njol/skript/lang/VariableString.java b/src/main/java/ch/njol/skript/lang/VariableString.java index 0e6af9b7cbe..bb5f9d939a9 100644 --- a/src/main/java/ch/njol/skript/lang/VariableString.java +++ b/src/main/java/ch/njol/skript/lang/VariableString.java @@ -409,15 +409,21 @@ public static VariableString[] makeStringsFromQuoted(final List args) { /** * Parses all expressions in the string and returns it. + * If this is a simple string, the event may be null. * * @param e Event to pass to the expressions. * @return The input string with all expressions replaced. */ - public String toString(final Event e) { + public String toString(@Nullable final Event e) { if (isSimple) { assert simple != null; return simple; } + + if (e == null) { + throw new IllegalArgumentException("Event may not be null in non-simple VariableStrings!"); + } + final Object[] string = this.string; assert string != null; final StringBuilder b = new StringBuilder(); diff --git a/src/main/java/ch/njol/skript/util/chat/BungeeConverter.java b/src/main/java/ch/njol/skript/util/chat/BungeeConverter.java index 08ad3ade79f..98656e1785a 100644 --- a/src/main/java/ch/njol/skript/util/chat/BungeeConverter.java +++ b/src/main/java/ch/njol/skript/util/chat/BungeeConverter.java @@ -19,6 +19,8 @@ */ package ch.njol.skript.util.chat; +import java.util.List; + import ch.njol.skript.Skript; import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.chat.BaseComponent; @@ -62,7 +64,11 @@ public static BaseComponent convert(MessageComponent origin) { return base; } - + + public static BaseComponent[] convert(List origins) { + return convert(origins.toArray(new MessageComponent[0])); + } + @SuppressWarnings("null") // For origins[i] access public static BaseComponent[] convert(MessageComponent[] origins) { BaseComponent[] bases = new BaseComponent[origins.length];