diff --git a/src/main/java/ch/njol/skript/classes/data/BukkitEventValues.java b/src/main/java/ch/njol/skript/classes/data/BukkitEventValues.java index 503baf87877..a2710936cfe 100644 --- a/src/main/java/ch/njol/skript/classes/data/BukkitEventValues.java +++ b/src/main/java/ch/njol/skript/classes/data/BukkitEventValues.java @@ -286,6 +286,7 @@ public PotionEffectType convert(AreaEffectCloudApplyEvent event) { EventValues.registerEventValue(PlayerDropItemEvent.class, Player.class, PlayerEvent::getPlayer); EventValues.registerEventValue(PlayerDropItemEvent.class, Item.class, PlayerDropItemEvent::getItemDrop); EventValues.registerEventValue(PlayerDropItemEvent.class, ItemStack.class, event -> event.getItemDrop().getItemStack()); + EventValues.registerEventValue(PlayerDropItemEvent.class, Entity.class, PlayerEvent::getPlayer); // EntityDropItemEvent EventValues.registerEventValue(EntityDropItemEvent.class, Item.class, EntityDropItemEvent::getItemDrop); EventValues.registerEventValue(EntityDropItemEvent.class, ItemStack.class, event -> event.getItemDrop().getItemStack()); @@ -293,6 +294,7 @@ public PotionEffectType convert(AreaEffectCloudApplyEvent event) { EventValues.registerEventValue(PlayerPickupItemEvent.class, Player.class, PlayerEvent::getPlayer); EventValues.registerEventValue(PlayerPickupItemEvent.class, Item.class, PlayerPickupItemEvent::getItem); EventValues.registerEventValue(PlayerPickupItemEvent.class, ItemStack.class, event -> event.getItem().getItemStack()); + EventValues.registerEventValue(PlayerPickupItemEvent.class, Entity.class, PlayerEvent::getPlayer); // EntityPickupItemEvent EventValues.registerEventValue(EntityPickupItemEvent.class, Entity.class, EntityPickupItemEvent::getEntity); EventValues.registerEventValue(EntityPickupItemEvent.class, Item.class, EntityPickupItemEvent::getItem); diff --git a/src/main/java/ch/njol/skript/doc/JSONGenerator.java b/src/main/java/ch/njol/skript/doc/JSONGenerator.java index 7d7431e9cde..98ccac05eb7 100644 --- a/src/main/java/ch/njol/skript/doc/JSONGenerator.java +++ b/src/main/java/ch/njol/skript/doc/JSONGenerator.java @@ -176,7 +176,7 @@ private static JsonArray getEventValues(SkriptEventInfo info) { continue; } - ClassInfo exactClassInfo = Classes.getExactClassInfo(eventValueInfo.c()); + ClassInfo exactClassInfo = Classes.getExactClassInfo(eventValueInfo.valueClass()); if (exactClassInfo == null) { continue; } diff --git a/src/main/java/ch/njol/skript/expressions/ExprEntity.java b/src/main/java/ch/njol/skript/expressions/ExprEntity.java index 15782c7bcdb..0b92213e627 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprEntity.java +++ b/src/main/java/ch/njol/skript/expressions/ExprEntity.java @@ -108,7 +108,13 @@ public Expression getConvertedExpression(Class... to) { } return super.getConvertedExpression(to); } - + + @Override + public boolean setTime(int time) { + // Allows using 'past' / 'future' event-entitydata if they're registered + return entity.setTime(time); + } + @Override public String toString(final @Nullable Event e, final boolean debug) { return "the " + type; diff --git a/src/main/java/ch/njol/skript/registrations/EventValues.java b/src/main/java/ch/njol/skript/registrations/EventValues.java index 190df76b2be..9d45f5aa77e 100644 --- a/src/main/java/ch/njol/skript/registrations/EventValues.java +++ b/src/main/java/ch/njol/skript/registrations/EventValues.java @@ -1,6 +1,7 @@ package ch.njol.skript.registrations; import ch.njol.skript.Skript; +import ch.njol.skript.classes.ClassInfo; import ch.njol.skript.expressions.base.EventValueExpression; import ch.njol.skript.util.Getter; import ch.njol.util.Kleenean; @@ -14,7 +15,9 @@ import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.List; +import java.util.Map; public class EventValues { @@ -66,61 +69,61 @@ private EventValues() {} * @see #registerEventValue(Class, Class, Converter, int) */ public static void registerEventValue( - Class event, Class type, + Class eventClass, Class valueClass, Converter converter ) { - registerEventValue(event, type, converter, TIME_NOW); + registerEventValue(eventClass, valueClass, converter, TIME_NOW); } /** * Registers an event value. * - * @param event the event type class. - * @param type the return type of the converter for the event value. - * @param converter the converter to get the value with the provided event. - * @param time value of TIME_PAST if this is the value before the event, TIME_FUTURE if after, and TIME_NOW if it's the default or this value doesn't have distinct states. + * @param eventClass the event class. + * @param valueClass the return type of the converter for the event value. + * @param converter the converter to get the value with the provided eventClass. + * @param time value of TIME_PAST if this is the value before the eventClass, TIME_FUTURE if after, and TIME_NOW if it's the default or this value doesn't have distinct states. * Always register a default state! You can leave out one of the other states instead, e.g. only register a default and a past state. The future state will * default to the default state in this case. */ public static void registerEventValue( - Class event, Class type, + Class eventClass, Class valueClass, Converter converter, int time ) { - registerEventValue(event, type, converter, time, null, (Class[]) null); + registerEventValue(eventClass, valueClass, converter, time, null, (Class[]) null); } /** * Registers an event value and with excluded events. * Excluded events are events that this event value can't operate in. * - * @param event the event type class. - * @param type the return type of the converter for the event value. - * @param converter the converter to get the value with the provided event. - * @param time value of TIME_PAST if this is the value before the event, TIME_FUTURE if after, and TIME_NOW if it's the default or this value doesn't have distinct states. + * @param eventClass the event class. + * @param valueClass the return type of the converter for the event value. + * @param converter the converter to get the value with the provided eventClass. + * @param time value of TIME_PAST if this is the value before the eventClass, TIME_FUTURE if after, and TIME_NOW if it's the default or this value doesn't have distinct states. * Always register a default state! You can leave out one of the other states instead, e.g. only register a default and a past state. The future state will * default to the default state in this case. * @param excludeErrorMessage The error message to display when used in the excluded events. - * @param excludes subclasses of the event for which this event value should not be registered for + * @param excludes subclasses of the eventClass for which this event value should not be registered for */ @SafeVarargs public static void registerEventValue( - Class event, Class type, + Class eventClass, Class valueClass, Converter converter, int time, @Nullable String excludeErrorMessage, @Nullable Class... excludes ) { Skript.checkAcceptRegistrations(); List> eventValues = getEventValuesList(time); - EventValueInfo element = new EventValueInfo<>(event, type, converter, excludeErrorMessage, excludes, time); + EventValueInfo element = new EventValueInfo<>(eventClass, valueClass, converter, excludeErrorMessage, excludes, time); for (int i = 0; i < eventValues.size(); i++) { EventValueInfo info = eventValues.get(i); // We don't care for exact duplicates. Prefer Skript's over any addon. - if (info.event.equals(event) && info.c.equals(type)) + if (info.eventClass.equals(eventClass) && info.valueClass.equals(valueClass)) return; // If the events don't match, we prefer the highest subclass event. // If the events match, we prefer the highest subclass type. - if (!info.event.equals(event) ? info.event.isAssignableFrom(event) : info.c.isAssignableFrom(type)) { + if (!info.eventClass.equals(eventClass) ? info.eventClass.isAssignableFrom(eventClass) : info.valueClass.isAssignableFrom(valueClass)) { eventValues.add(i, element); return; } @@ -135,12 +138,12 @@ public static void registerEventValue( @SafeVarargs @SuppressWarnings({"removal"}) public static void registerEventValue( - Class event, Class type, + Class eventClass, Class valueClass, Getter getter, int time, @Nullable String excludeErrorMessage, @Nullable Class... excludes ) { - registerEventValue(event, type, (Converter) getter, time, excludeErrorMessage, excludes); + registerEventValue(eventClass, valueClass, (Converter) getter, time, excludeErrorMessage, excludes); } /** @@ -149,32 +152,32 @@ public static void registerEventValue( @Deprecated(forRemoval = true) @SuppressWarnings({"removal"}) public static void registerEventValue( - Class event, Class type, + Class eventClass, Class valueClass, Getter getter, int time ) { - registerEventValue(event, type, (Converter) getter, time); + registerEventValue(eventClass, valueClass, (Converter) getter, time); } /** - * Gets a specific value from an event. Returns null if the event doesn't have such a value (conversions are done to try and get the desired value). + * Gets a specific value from an eventClass. Returns null if the eventClass doesn't have such a value (conversions are done to try and get the desired value). *

* It is recommended to use {@link EventValues#getEventValueGetter(Class, Class, int)} or {@link EventValueExpression#EventValueExpression(Class)} instead of invoking this * method repeatedly. * - * @param e event - * @param c return type of getter - * @param time -1 if this is the value before the event, 1 if after, and 0 if it's the default or this value doesn't have distinct states. + * @param event eventClass + * @param valueClass return type of getter + * @param time -1 if this is the value before the eventClass, 1 if after, and 0 if it's the default or this value doesn't have distinct states. * Always register a default state! You can leave out one of the other states instead, e.g. only register a default and a past state. The future state will * default to the default state in this case. * @return The event's value * @see #registerEventValue(Class, Class, Converter, int) */ - public static @Nullable T getEventValue(E e, Class c, int time) { + public static @Nullable T getEventValue(E event, Class valueClass, int time) { //noinspection unchecked - Converter converter = getEventValueConverter((Class) e.getClass(), c, time); + Converter converter = getEventValueConverter((Class) event.getClass(), valueClass, time); if (converter == null) return null; - return converter.convert(e); + return converter.convert(event); } /** @@ -183,15 +186,15 @@ public static void registerEventValue( @Nullable @Deprecated(forRemoval = true) @SuppressWarnings({"removal"}) - public static Getter getExactEventValueGetter(Class event, Class c, int time) { - return toGetter(getExactEventValueConverter(event, c, time)); + public static Getter getExactEventValueGetter(Class eventClass, Class valueClass, int time) { + return toGetter(getExactEventValueConverter(eventClass, valueClass, time)); } /** * Checks that a {@link Converter} exists for the exact type. No converting or subclass checking. * - * @param event the event class the getter will be getting from - * @param c type of {@link Converter} + * @param eventClass the event class the getter will be getting from + * @param valueClass type of {@link Converter} * @param time the event-value's time * @return A getter to get values for a given type of events * @see #registerEventValue(Class, Class, Converter, int) @@ -199,16 +202,16 @@ public static void registerEventValue( */ @Nullable public static Converter getExactEventValueConverter( - Class event, Class c, int time + Class eventClass, Class valueClass, int time ) { List> eventValues = getEventValuesList(time); // First check for exact classes matching the parameters. for (EventValueInfo eventValueInfo : eventValues) { - if (!c.equals(eventValueInfo.c)) + if (!valueClass.equals(eventValueInfo.valueClass)) continue; - if (!checkExcludes(eventValueInfo, event)) + if (!checkExcludes(eventValueInfo, eventClass)) return null; - if (eventValueInfo.event.isAssignableFrom(event)) + if (eventValueInfo.eventClass.isAssignableFrom(eventClass)) //noinspection unchecked return (Converter) eventValueInfo.converter; } @@ -219,20 +222,20 @@ public static void registerEventValue( * @deprecated Use {@link #hasMultipleConverters(Class, Class, int)} instead. */ @Deprecated(forRemoval = true) - public static Kleenean hasMultipleGetters(Class event, Class type, int time) { - return hasMultipleConverters(event, type, time); + public static Kleenean hasMultipleGetters(Class eventClass, Class valueClass, int time) { + return hasMultipleConverters(eventClass, valueClass, time); } /** * Checks if an event has multiple {@link Converter}s, including default ones. * - * @param event the event class the {@link Converter} will be getting from. - * @param type type of {@link Converter}. + * @param eventClass the event class the {@link Converter} will be getting from. + * @param valueClass type of {@link Converter}. * @param time the event-value's time. * @return true or false if the event and type have multiple {@link Converter}s. */ - public static Kleenean hasMultipleConverters(Class event, Class type, int time) { - List> getters = getEventValueConverters(event, type, time, true, false); + public static Kleenean hasMultipleConverters(Class eventClass, Class valueClass, int time) { + List> getters = getEventValueConverters(eventClass, valueClass, time, true, false); if (getters == null) return Kleenean.UNKNOWN; return Kleenean.get(getters.size() > 1); @@ -244,8 +247,8 @@ public static Kleenean hasMultipleConverters(Class event @Nullable @Deprecated(forRemoval = true) @SuppressWarnings({"removal"}) - public static Getter getEventValueGetter(Class event, Class type, int time) { - return toGetter(getEventValueConverter(event, type, time, true)); + public static Getter getEventValueGetter(Class eventClass, Class valueClass, int time) { + return toGetter(getEventValueConverter(eventClass, valueClass, time, true)); } /** @@ -253,24 +256,24 @@ public static Kleenean hasMultipleConverters(Class event *

* Can print an error if the event value is blocked for the given event. * - * @param event the event class the {@link Converter} will be getting from. - * @param type type of {@link Converter}. + * @param eventClass the event class the {@link Converter} will be getting from. + * @param valueClass type of {@link Converter}. * @param time the event-value's time. * @return A getter to get values for a given type of events. * @see #registerEventValue(Class, Class, Converter, int) * @see EventValueExpression#EventValueExpression(Class) */ public static @Nullable Converter getEventValueConverter( - Class event, Class type, int time + Class eventClass, Class valueClass, int time ) { - return getEventValueConverter(event, type, time, true); + return getEventValueConverter(eventClass, valueClass, time, true); } @Nullable private static Converter getEventValueConverter( - Class event, Class type, int time, boolean allowDefault + Class eventClass, Class valueClass, int time, boolean allowDefault ) { - List> list = getEventValueConverters(event, type, time, allowDefault); + List> list = getEventValueConverters(eventClass, valueClass, time, allowDefault); if (list == null || list.isEmpty()) return null; return list.get(0); @@ -278,9 +281,9 @@ public static Kleenean hasMultipleConverters(Class event @Nullable private static List> getEventValueConverters( - Class event, Class type, int time, boolean allowDefault + Class eventClass, Class valueClass, int time, boolean allowDefault ) { - return getEventValueConverters(event, type, time, allowDefault, true); + return getEventValueConverters(eventClass, valueClass, time, allowDefault, true); } /* @@ -290,92 +293,98 @@ public static Kleenean hasMultipleConverters(Class event @Nullable @SuppressWarnings("unchecked") private static List> getEventValueConverters( - Class event, Class type, int time, + Class eventClass, Class valueClass, int time, boolean allowDefault, boolean allowConverting ) { List> eventValues = getEventValuesList(time); List> list = new ArrayList<>(); // First check for exact classes matching the parameters. - Converter exact = getExactEventValueConverter(event, type, time); + Converter exact = getExactEventValueConverter(eventClass, valueClass, time); if (exact != null) { list.add(exact); return list; } + Map, Converter> infoConverterMap = new HashMap<>(); // Second check for assignable subclasses. for (EventValueInfo eventValueInfo : eventValues) { - if (!type.isAssignableFrom(eventValueInfo.c)) + if (!valueClass.isAssignableFrom(eventValueInfo.valueClass)) continue; - if (!checkExcludes(eventValueInfo, event)) + if (!checkExcludes(eventValueInfo, eventClass)) return null; - if (eventValueInfo.event.isAssignableFrom(event)) { + if (eventValueInfo.eventClass.isAssignableFrom(eventClass)) { list.add((Converter) eventValueInfo.converter); + infoConverterMap.put(eventValueInfo, (Converter) eventValueInfo.converter); continue; } - if (!event.isAssignableFrom(eventValueInfo.event)) + if (!eventClass.isAssignableFrom(eventValueInfo.eventClass)) continue; - list.add(e -> { - if (!eventValueInfo.event.isInstance(e)) + Converter converter = e -> { + if (!eventValueInfo.eventClass.isInstance(e)) return null; return ((Converter) eventValueInfo.converter).convert(e); - }); + }; + list.add(converter); + infoConverterMap.put(eventValueInfo, converter); } if (!list.isEmpty()) - return list; + return stripConverters(eventClass, valueClass, infoConverterMap, list); if (!allowConverting) return null; // Most checks have returned before this below is called, but Skript will attempt to convert or find an alternative. // Third check is if the returned object matches the class. for (EventValueInfo eventValueInfo : eventValues) { - if (!eventValueInfo.c.isAssignableFrom(type)) + if (!eventValueInfo.valueClass.isAssignableFrom(valueClass)) continue; - boolean checkInstanceOf = !eventValueInfo.event.isAssignableFrom(event); - if (checkInstanceOf && !event.isAssignableFrom(eventValueInfo.event)) + boolean checkInstanceOf = !eventValueInfo.eventClass.isAssignableFrom(eventClass); + if (checkInstanceOf && !eventClass.isAssignableFrom(eventValueInfo.eventClass)) continue; - if (!checkExcludes(eventValueInfo, event)) + if (!checkExcludes(eventValueInfo, eventClass)) return null; - list.add(e -> { - if (checkInstanceOf && !eventValueInfo.event.isInstance(e)) + Converter converter = e -> { + if (checkInstanceOf && !eventValueInfo.eventClass.isInstance(e)) return null; T object = ((Converter) eventValueInfo.converter).convert(e); - if (type.isInstance(object)) + if (valueClass.isInstance(object)) return object; return null; - }); + }; + list.add(converter); + infoConverterMap.put(eventValueInfo, converter); } if (!list.isEmpty()) - return list; + return stripConverters(eventClass, valueClass, infoConverterMap, list); // Fourth check will attempt to convert the event value to the requesting type. // This first for loop will check that the events are exact. See issue #5016 for (EventValueInfo eventValueInfo : eventValues) { - if (!event.equals(eventValueInfo.event)) + if (!eventClass.equals(eventValueInfo.eventClass)) continue; Converter converter = (Converter) - getConvertedConverter(eventValueInfo, type, false); + getConvertedConverter(eventValueInfo, valueClass, false); if (converter == null) continue; - if (!checkExcludes(eventValueInfo, event)) + if (!checkExcludes(eventValueInfo, eventClass)) return null; list.add(converter); continue; } if (!list.isEmpty()) return list; - // This loop will attempt to look for converters assignable to the class of the provided event. + // This loop will attempt to look for converters assignable to the class of the provided eventClass. for (EventValueInfo eventValueInfo : eventValues) { - // The requesting event must be assignable to the event value's event. Otherwise it'll throw an error. - if (!event.isAssignableFrom(eventValueInfo.event)) + // The requesting eventClass must be assignable to the event value's eventClass. Otherwise it'll throw an error. + if (!eventClass.isAssignableFrom(eventValueInfo.eventClass)) continue; Converter converter = (Converter) - getConvertedConverter(eventValueInfo, type, true); + getConvertedConverter(eventValueInfo, valueClass, true); if (converter == null) continue; - if (!checkExcludes(eventValueInfo, event)) + if (!checkExcludes(eventValueInfo, eventClass)) return null; list.add(converter); continue; @@ -384,23 +393,54 @@ public static Kleenean hasMultipleConverters(Class event return list; // If the check should try again matching event values with a 0 time (most event values). if (allowDefault && time != 0) - return getEventValueConverters(event, type, 0, false); + return getEventValueConverters(eventClass, valueClass, 0, false); return null; } + /** + *

+ * In this method we can strip converters that are able to be obtainable through their own 'event-classinfo'. + * For example, PlayerTradeEvent has a player value (player who traded) and an AbstractVillager value (villager traded from). + * Beforehand, since there is no Entity value, it was then grabbing both values as they both can be casted as an Entity + * resulting in a parse error of "multiple entities" + * Now, we filter out the ones that can be obtained using their own classinfo, such as 'event-player' + * which leaves us only the AbstractVillager for 'event-entity' + *

+ */ + private static List> stripConverters( + Class eventClass, + Class valueClass, + Map, Converter> infoConverterMap, + List> converters + ) { + if (converters.size() == 1) + return converters; + ClassInfo valueClassInfo = Classes.getExactClassInfo(valueClass); + List> delegated = new ArrayList<>(); + for (EventValueInfo eventValueInfo : infoConverterMap.keySet()) { + ClassInfo thisClassInfo = Classes.getExactClassInfo(eventValueInfo.valueClass); + if (thisClassInfo != null && !thisClassInfo.equals(valueClassInfo)) + continue; + delegated.add(infoConverterMap.get(eventValueInfo)); + } + if (delegated.isEmpty()) + return converters; + return delegated; + } + /** * Check if the event value states to exclude events. - * False if the current EventValueInfo cannot operate in the provided event. + * False if the current EventValueInfo cannot operate in the provided eventClass. * * @param info The event value info that will be used to grab the value from - * @param event The event class to check the excludes against. + * @param eventClass The event class to check the excludes against. * @return boolean if true the event value passes for the events. */ - private static boolean checkExcludes(EventValueInfo info, Class event) { + private static boolean checkExcludes(EventValueInfo info, Class eventClass) { if (info.excludes == null) return true; for (Class ex : (Class[]) info.excludes) { - if (ex.isAssignableFrom(event)) { + if (ex.isAssignableFrom(eventClass)) { Skript.error(info.excludeErrorMessage); return false; } @@ -412,21 +452,21 @@ private static boolean checkExcludes(EventValueInfo info, Class Converter getConvertedConverter( - EventValueInfo info, Class to, boolean checkInstanceOf + EventValueInfo info, Class valueClass, boolean checkInstanceOf ) { - Converter converter = Converters.getConverter(info.c, to); + Converter converter = Converters.getConverter(info.valueClass, valueClass); if (converter == null) return null; return event -> { - if (checkInstanceOf && !info.event.isInstance(event)) + if (checkInstanceOf && !info.eventClass.isInstance(event)) return null; F f = info.converter.convert(event); if (f == null) @@ -449,12 +489,14 @@ private static Getter toGetter(Converter converter) { }; } - public static boolean doesExactEventValueHaveTimeStates(Class event, Class c) { - return getExactEventValueConverter(event, c, TIME_PAST) != null || getExactEventValueConverter(event, c, TIME_FUTURE) != null; + public static boolean doesExactEventValueHaveTimeStates(Class eventClass, Class valueClass) { + return getExactEventValueConverter(eventClass, valueClass, TIME_PAST) != null + || getExactEventValueConverter(eventClass, valueClass, TIME_FUTURE) != null; } - public static boolean doesEventValueHaveTimeStates(Class event, Class c) { - return getEventValueConverter(event, c, TIME_PAST, false) != null || getEventValueConverter(event, c, TIME_FUTURE, false) != null; + public static boolean doesEventValueHaveTimeStates(Class eventClass, Class valueClass) { + return getEventValueConverter(eventClass, valueClass, TIME_PAST, false) != null + || getEventValueConverter(eventClass, valueClass, TIME_FUTURE, false) != null; } /** @@ -476,22 +518,22 @@ public static int[] getTimeStates() { for (int time : getTimeStates()) { for (EventValueInfo eventValueInfo : getEventValuesListForTime(time)) { - Collection> existing = eventValues.get(eventValueInfo.event); + Collection> existing = eventValues.get(eventValueInfo.eventClass); existing.add(eventValueInfo); - eventValues.putAll(eventValueInfo.event, existing); + eventValues.putAll(eventValueInfo.eventClass, existing); } } return eventValues; } public record EventValueInfo( - Class event, Class c, Converter converter, + Class eventClass, Class valueClass, Converter converter, @Nullable String excludeErrorMessage, @Nullable Class[] excludes, int time ) { public EventValueInfo { - assert event != null; - assert c != null; + assert eventClass != null; + assert valueClass != null; assert converter != null; } diff --git a/src/test/skript/tests/misc/EventValues.sk b/src/test/skript/tests/misc/EventValues.sk new file mode 100644 index 00000000000..3a6157b7af7 --- /dev/null +++ b/src/test/skript/tests/misc/EventValues.sk @@ -0,0 +1,966 @@ + +# This is to test parsing of event-value expressions + +parse: + results: {EventValues::on beacon effect} + code: + on beacon effect: + set {_values::*} to event-player and event-block + +parse: + results: {EventValues::on beacon toggle} + code: + on beacon toggle: + set {_values::*} to event-block + +parse: + results: {EventValues::on break} + code: + on break: + set {_values::*} to event-player, event-block and past event-block + +parse: + results: {EventValues::on burn} + code: + on burn: + set {_value::*} to event-block + +parse: + results: {EventValues::on place} + code: + on place: + set {_values::*} to event-player, event-block, past event-block, past event-item, event-item and future event-item + +parse: + results: {EventValues::on fade} + code: + on fade: + set {_values::*} to past event-block, event-block and future event-block + +parse: + results: {EventValues::on form} + code: + on form: + set {_values::*} to past event-block and event-block + +parse: + results: {EventValues::on block drop} + code: + on block drop: + set {_values::*} to past event-block, event-block, event-player, event-items and event-entities + +parse: + results: {EventValues::on book edit} + code: + on book edit: + set {_values::*} to event-player, past event-item, event-item, past event-strings and event-strings + +parse: + results: {EventValues::on click} + code: + on click: + set {_values::*} to event-item, event-block, event-direction, event-player and event-entity + +parse: + results: {EventValues::on command} + code: + on command: + set {_values::*} to event-player, event-sender, event-world and event-block + +parse: + results: {EventValues::on damage} + code: + on damage: + set {_values::*} to event-world, event-location, event-damage cause and event-projectile + +parse: + results: {EventValues::on death} + code: + on death: + set {_values::*} to event-world, event-location, event-damage cause, event-items and event-projectile + +parse: + results: {EventValues::on spawn} + code: + on spawn: + set {_values::*} to event-entity + +parse: + results: {EventValues::on entity change block} + code: + on entity change block: + set {_values::*} to past event-block, event-block, past event-block data and event-block data + +parse: + results: {EventValues::on entity potion effect} + code: + on entity potion effect: + set {_values::*} to past event-potion effect, event-potion effect and event-potion effect type + +parse: + results: {EventValues::on target} + code: + on target: + set {_values::*} to event-entity + +parse: + results: {EventValues::on entity transform} + code: + on entity transform: + set {_values::*} to event-entities and event-transform reason + +parse: + results: {EventValues::on xp change} + code: + on xp change: + set {_values::*} to event-player and event-experience + +parse: + results: {EventValues::on xp spawn} + code: + on xp spawn: + set {_values::*} to event-location and event-experience + +parse: + results: {EventValues::on firework explode} + code: + on firework explode: + set {_values::*} to event-firework, event-firework effect and event-colors + +parse: + results: {EventValues::on first join} + code: + on first join: + set {_values::*} to event-player + +parse: + results: {EventValues::on gamemode change} + code: + on gamemode change: + set {_values::*} to event-player + +parse: + results: {EventValues::on grow} + code: + on grow: + set {_values::*} to past event-block and event-block + +parse: + results: {EventValues::on heal} + code: + on heal: + set {_values::*} to event-entity and event-heal reason + +parse: + results: {EventValues::on dispense} + code: + on dispense: + set {_values::*} to event-block and event-item + +parse: + results: {EventValues::on item spawn} + code: + on item spawn: + set {_values::*} to event-item + +parse: + results: {EventValues::on entity drop} + code: + on entity drop: + set {_values::*} to event-entity, event-dropped item and event-item + +parse: + results: {EventValues::on player drop} + code: + on player drop: + set {_values::*} to event-player, event-dropped item and event-item + +parse: + results: {EventValues::on preparing craft} + code: + on preparing craft: + set {_values::*} to event-slot, event-item, event-inventory, event-player and event-string + +parse: + results: {EventValues::on craft} + code: + on craft: + set {_values::*} to event-string and event-item + +parse: + results: {EventValues::on entity pickup} + code: + on entity pickup: + set {_values::*} to event-entity, event-dropped item and event-itemtype + +parse: + results: {EventValues::on player pickup} + code: + on player pickup: + set {_values::*} to event-player, event-dropped item and event-itemtype + +parse: + results: {EventValues::on consume} + code: + on consume: + set {_values::*} to event-player and event-item + +parse: + results: {EventValues::on inventory click} + code: + on inventory click: + set {_values::*} to event-player, event-world, event-item, event-slot, event-inventory action, event-click type and event-inventory + +parse: + results: {EventValues::on item despawn} + code: + on item despawn: + set {_values::*} to event-dropped item and event-item + +parse: + results: {EventValues::on item merge} + code: + on item merge: + set {_values::*} to event-dropped item and event-item and future event-dropped item + +parse: + results: {EventValues::on inventory item move} + code: + on inventory item move: + set {_values::*} to event-inventory, future event-inventory, event-block, event-item and future event-block + +parse: + results: {EventValues::on stonecutting} + code: + on stonecutting: + set {_values::*} to event-player and event-item + +parse: + results: {EventValues::on leash} + code: + on leash: + set {_values::*} to event-player and event-entity + +parse: + results: {EventValues::on unleash} + code: + on unleash: + set {_values::*} to event-entity and event-unleash reason + +parse: + results: {EventValues::on player unleash} + code: + on player unleash: + set {_values::*} to event-player and event-unleash reason + +parse: + results: {EventValues::on level change} + code: + on level change: + set {_values::*} to event-player and event-entity + +parse: + results: {EventValues::on entity move} + code: + on entity move: + set {_values::*} to event-entity + +parse: + results: {EventValues::on step on dirt} + code: + on step on dirt: + set {_values::*} to event-player, event-block, past event-location, event-location, past event-chunk and event-chunk + +parse: + results: {EventValues::on send command list} + code: + on send command list: + set {_values::*} to event-player and event-entity + +parse: + results: {EventValues::on resource pack response} + code: + on resource pack response: + set {_values::*} to event-player and event-entity + +parse: + results: {EventValues::on load} + code: + on load: + set {_values::*} to event-sender + +parse: + results: {EventValues::on unload} + code: + on unload: + set {_values::*} to event-sender + +parse: + results: {EventValues::on skript load} + code: + on skript load: + set {_values::*} to event-sender + +parse: + results: {EventValues::on skript unload} + code: + on skript unload: + set {_values::*} to event-sender + +parse: + results: {EventValues::on start spectating} + code: + on start spectating: + set {_values::*} to event-player and event-entity + +parse: + results: {EventValues::on entity teleport} + code: + on entity teleport: + set {_values::*} to event-entity, past event-location and event-location + +parse: + results: {EventValues::on player teleport} + code: + on player teleport: + set {_values::*} to event-player, past event-location and event-location + +parse: + results: {EventValues::on vehicle collision} + code: + on vehicle collision: + set {_values::*} to event-world, event-entity and event-block + +parse: + results: {EventValues::on weather change} + code: + on weather change: + set {_values::*} to event-world + +parse: + results: {EventValues::on world save} + code: + on world save: + set {_values::*} to event-world + +parse: + results: {EventValues::on world init} + code: + on world init: + set {_values::*} to event-world + +parse: + results: {EventValues::on world load} + code: + on world load: + set {_values::*} to event-world + +parse: + results: {EventValues::on world unload} + code: + on world unload: + set {_values::*} to event-world + +parse: + results: {EventValues::on can build check} + code: + on can build check: + set {_values::*} to past event-block, event-block and event-player + +parse: + results: {EventValues::on block damage} + code: + on block damage: + set {_values::*} to event-block and event-player + +parse: + results: {EventValues::on flow} + code: + on flow: + set {_values::*} to event-block and future event-block + +parse: + results: {EventValues::on ignite} + code: + on ignite: + set {_values::*} to event-block and event-player + +parse: + results: {EventValues::on physics} + code: + on physics: + set {_values::*} to event-block + +parse: + results: {EventValues::on piston extend} + code: + on piston extend: + set {_values::*} to event-block + +parse: + results: {EventValues::on piston retract} + code: + on piston retract: + set {_values::*} to event-block + +parse: + results: {EventValues::on redstone} + code: + on redstone: + set {_values::*} to event-block + +parse: + results: {EventValues::on spread} + code: + on spread: + set {_values::*} to event-block + +parse: + results: {EventValues::on chunk load} + code: + on chunk load: + set {_values::*} to event-world and event-chunk + +parse: + results: {EventValues::on chunk generate} + code: + on chunk generate: + set {_values::*} to event-world and event-chunk + +parse: + results: {EventValues::on chunk unload} + code: + on chunk unload: + set {_values::*} to event-world and event-chunk + +parse: + results: {EventValues::on creeper power} + code: + on creeper power: + set {_values::*} to event-entity + +parse: + results: {EventValues::on zombie break door} + code: + on zombie break door: + set {_values::*} to event-entity, past event-block, event-block, event-block data and future event-block data + +parse: + results: {EventValues::on combust} + code: + on combust: + set {_values::*} to event-entity + +parse: + results: {EventValues::on explode} + code: + on explode: + set {_values::*} to event-entity + +parse: + results: {EventValues::on portal enter} + code: + on portal enter: + set {_values::*} to event-entity + +parse: + results: {EventValues::on tame} + code: + on tame: + set {_values::*} to event-entity + +parse: + results: {EventValues::on explosion prime} + code: + on explosion prime: + set {_values::*} to event-entity + +parse: + results: {EventValues::on hunger level change} + code: + on hunger level change: + set {_values::*} to event-entity + +parse: + results: {EventValues::on leaves decay} + code: + on leaves decay: + set {_values::*} to event-block + +parse: + results: {EventValues::on lightning} + code: + on lightning: + set {_values::*} to event-entity + +parse: + results: {EventValues::on pig zap} + code: + on pig zap: + set {_values::*} to event-entity, event-entities and event-transform reason + +parse: + results: {EventValues::on bed enter} + code: + on bed enter: + set {_values::*} to event-player and event-block + +parse: + results: {EventValues::on leave bed} + code: + on leave bed: + set {_values::*} to event-player and event-block + +parse: + results: {EventValues::on bucket empty} + code: + on bucket empty: + set {_values::*} to event-player, past event-block and event-block + +parse: + results: {EventValues::on bucket fill} + code: + on bucket fill: + set {_values::*} to event-player, event-block and future event-block + +parse: + results: {EventValues::on throw egg} + code: + on throw egg: + set {_values::*} to event-player and event-projectile + +parse: + results: {EventValues::on tool break} + code: + on tool break: + set {_values::*} to event-player and event-item + +parse: + results: {EventValues::on item damage} + code: + on item damage: + set {_values::*} to event-player and event-item + +parse: + results: {EventValues::on tool change} + code: + on tool change: + set {_values::*} to event-player, past event-slot and event-slot + +parse: + results: {EventValues::on join} + code: + on join: + set {_values::*} to event-player and event-entity + +parse: + results: {EventValues::on connect} + code: + on connect: + set {_values::*} to event-player and event-entity + +parse: + results: {EventValues::on kick} + code: + on kick: + set {_values::*} to event-player and event-entity + +parse: + results: {EventValues::on entity portal} + code: + on entity portal: + set {_values::*} to event-entity, past event-location and event-location + +parse: + results: {EventValues::on portal} + code: + on portal: + set {_values::*} to event-player, event-teleport cause, event-block, past event-location, event-location, past event-chunk and event-chunk + +parse: + results: {EventValues::on leave} + code: + on leave: + set {_values::*} to event-player and event-quit reason + +parse: + results: {EventValues::on respawn} + code: + on respawn: + set {_values::*} to event-player and event-entity + +parse: + results: {EventValues::on toggle sneak} + code: + on toggle sneak: + set {_values::*} to event-player and event-entity + +parse: + results: {EventValues::on toggle sprint} + code: + on toggle sprint: + set {_values::*} to event-player and event-entity + +parse: + results: {EventValues::on portal create} + code: + on portal create: + set {_values::*} to event-world, event-blocks and event-entity + +parse: + results: {EventValues::on projectile collide} + code: + on projectile collide: + set {_values::*} to event-projectile and event-entity + +parse: + results: {EventValues::on shoot} + code: + on shoot: + set {_values::*} to event-projectile + +parse: + results: {EventValues::on sign change} + code: + on sign change: + set {_values::*} to event-player, event-strings and event-block + +parse: + results: {EventValues::on spawn change} + code: + on spawn change: + set {_values::*} to event-world + +parse: + results: {EventValues::on vehicle create} + code: + on vehicle create: + set {_values::*} to event-vehicle, event-world and event-entity + +parse: + results: {EventValues::on vehicle damage} + code: + on vehicle damage: + set {_values::*} to event-vehicle, event-world and event-entity + +parse: + results: {EventValues::on vehicle enter} + code: + on vehicle enter: + set {_values::*} to event-vehicle, event-world and event-entity + +parse: + results: {EventValues::on vehicle destroy} + code: + on vehicle destroy: + set {_values::*} to event-vehicle, event-world and event-entity + +parse: + results: {EventValues::on vehicle exit} + code: + on vehicle exit: + set {_values::*} to event-vehicle, event-world and event-entity + +parse: + results: {EventValues::on mount} + code: + on mount: + set {_values::*} to event-entity + +parse: + results: {EventValues::on dismount} + code: + on dismount: + set {_values::*} to event-entity + +parse: + results: {EventValues::on toggle gliding} + code: + on toggle gliding: + set {_values::*} to event-entity + +parse: + results: {EventValues::on area effect} + code: + on area effect: + set {_values::*} to event-living entities and event-potion effect type + +parse: + results: {EventValues::on sheep grow wool} + code: + on sheep grow wool: + set {_values::*} to event-entity + +parse: + results: {EventValues::on inventory open} + code: + on inventory open: + set {_values::*} to event-player and event-inventory + +parse: + results: {EventValues::on inventory close} + code: + on inventory close: + set {_values::*} to event-player, event-inventory and event-inventory close reason + +parse: + results: {EventValues::on slime split} + code: + on slime split: + set {_values::*} to event-entity + +parse: + results: {EventValues::on resurrect} + code: + on resurrect: + set {_values::*} to event-entity and event-slot + +parse: + results: {EventValues::on world change} + code: + on world change: + set {_values::*} to event-player and past event-world + +parse: + results: {EventValues::on toggle flight} + code: + on toggle flight: + set {_values::*} to event-player + +parse: + results: {EventValues::on locale change} + code: + on locale change: + set {_values::*} to event-player + +parse: + results: {EventValues::on jump} + code: + on jump: + set {_values::*} to event-player + +parse: + results: {EventValues::on swap item} + code: + on swap item: + set {_values::*} to event-player + +parse: + results: {EventValues::on toggle swim} + code: + on toggle swim: + set {_values::*} to event-entity + +parse: + results: {EventValues::on riptide} + code: + on riptide: + set {_values::*} to event-player and event-item + +parse: + results: {EventValues::on armor change} + code: + on armor change: + set {_values::*} to event-player + +parse: + results: {EventValues::on sponge absorb} + code: + on sponge absorb: + set {_values::*} to event-block, event-world and event-location + +parse: + results: {EventValues::on enchant prepare} + code: + on enchant prepare: + set {_values::*} to event-player, event-item, event-block and event-inventory + +parse: + results: {EventValues::on enchant} + code: + on enchant: + set {_values::*} to event-player, event-item, event-enchantment types and event-block + +parse: + results: {EventValues::on inventory pickup} + code: + on inventory pickup: + set {_values::*} to event-inventory, event-dropped item and event-item + +parse: + results: {EventValues::on horse jump} + code: + on horse jump: + set {_values::*} to event-entity + +parse: + results: {EventValues::on fertilize} + code: + on fertilize: + set {_values::*} to event-player and event-blocks + +parse: + results: {EventValues::on arm swing} + code: + on arm swing: + set {_values::*} to event-player + +parse: + results: {EventValues::on anvil prepare} + code: + on anvil prepare: + set {_values::*} to event-item and event-inventory + +parse: + results: {EventValues::on player trade} + code: + on player trade: + set {_values::*} to event-player and event-entity + +parse: + results: {EventValues::on entity jump} + code: + on entity jump: + set {_values::*} to event-entity + +parse: + results: {EventValues::on anvil damage} + code: + on anvil damage: + set {_values::*} to event-inventory + +parse: + results: {EventValues::on stop item use} + code: + on stop item use: + set {_values::*} to event-player, event-timespan and event-item + +parse: + results: {EventValues::on ready arrow} + code: + on ready arrow: + set {_values::*} to event-player + +parse: + results: {EventValues::on inventory slot change} + code: + on inventory slot change: + set {_values::*} to event-player, past event-item, event-item and event-slot + +parse: + results: {EventValues::on chat} + code: + on chat: + set {_values::*} to event-player + +parse: + results: {EventValues::on deep sleep} + code: + on deep sleep: + set {_values::*} to event-player + +parse: + results: {EventValues::on arrow pickup} + code: + on arrow pickup: + set {_values::*} to event-player, event-projectile and event-item + +parse: + results: {EventValues::on inventory drag} + code: + on inventory drag: + set {_values::*} to event-player, event-world, past event-item, event-item, event-items, event-slots, event-click type and event-inventories + +parse: + results: {EventValues::on piglin barter} + code: + on piglin barter: + set {_values::*} to event-entity + +parse: + results: {EventValues::on bell ring} + code: + on bell ring: + set {_values::*} to event-block, event-entity and event-direction + +parse: + results: {EventValues::on bell resonate} + code: + on bell resonate: + set {_values::*} to event-block and event-entities + +parse: + results: {EventValues::on enderman anger} + code: + on enderman anger: + set {_values::*} to event-entity and event-player + +parse: + results: {EventValues::on player change beacon effect} + code: + on player change beacon effect: + set {_values::*} to event-player and event-block + +parse: + results: {EventValues::on player xp cooldown change} + code: + on player xp cooldown change: + set {_values::*} to event-player, event-experience cooldown change reason, past event-timespan and event-timespan + +parse: + results: {EventValues::on vehicle move} + code: + on vehicle move: + set {_values::*} to event-vehicle, past event-location and event-location + +parse: + results: {EventValues::on elytra boost} + code: + on elytra boost: + set {_values::*} to event-player, event-item and event-entity + +parse: + results: {EventValues::on breed} + code: + on breed: + set {_values::*} to event-entity and event-item + +parse: + results: {EventValues::on fish caught} + code: + on fish caught: + set {_values::*} to event-player + +parse: + results: {EventValues::on smelt} + code: + on smelt: + set {_values::*} to event-block + +parse: + results: {EventValues::on fuel burn} + code: + on fuel burn: + set {_values::*} to event-block + +parse: + results: {EventValues::on furnace extract} + code: + on furnace extract: + set {_values::*} to event-block, event-player and event-items + +parse: + results: {EventValues::on smelt start} + code: + on smelt start: + set {_values::*} to event-block + +test "Event Values": + if size of {EventValues::*} > 0: + set {_string} to "Event value error(s) in:" + loop {EventValues::*}: + set {_string} to {_string} + newline + " %loop-index%: %loop-value%" + clear {EventValues::*} + assert true is false with {_string} + else: + clear {EventValues::*} diff --git a/src/test/skript/tests/syntaxes/effects/EffDetonate.sk b/src/test/skript/tests/syntaxes/effects/EffDetonate.sk index f7f7c803009..f22118edf7b 100644 --- a/src/test/skript/tests/syntaxes/effects/EffDetonate.sk +++ b/src/test/skript/tests/syntaxes/effects/EffDetonate.sk @@ -5,10 +5,11 @@ test "detonate entity effect": assert last spawned entity isn't valid with "creepers should instantly detonate when spawned" test "detonate explosive minecart": - spawn a minecart with tnt at event-location - assert last spawned entity is valid with "minecarts with tnt should not detonate when they are first spawned" - detonate last spawned entity - assert last spawned entity isn't valid with "minecarts with tnt should instantly detonate when they are first spawned" + spawn a minecart with tnt at event-location: + set {_entity} to entity + assert {_entity} is valid with "minecarts with tnt should not detonate when they are first spawned" + detonate {_entity} + assert {_entity} isn't valid with "minecarts with tnt should instantly detonate when they are first spawned" test "detonate wind charge" when running minecraft "1.21": spawn a wind charge at event-location ~ vector(0, 100, 0)