From b9a7ab8445092cd6fa9166f286425aa04432d58e Mon Sep 17 00:00:00 2001 From: Patrick Miller <apickledwalrus@gmail.com> Date: Thu, 6 Jun 2024 12:28:02 -0400 Subject: [PATCH 1/6] Fix PotionData NPE (#6757) --- .../classes/data/BukkitEventValues.java | 32 +++------------ .../njol/skript/util/PotionEffectUtils.java | 41 ++++++------------- ...756-potion missing base type causes npe.sk | 3 ++ 3 files changed, 22 insertions(+), 54 deletions(-) create mode 100644 src/test/skript/tests/regressions/6756-potion missing base type causes npe.sk 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 d026bc55a19..d8e9ea0b94e 100644 --- a/src/main/java/ch/njol/skript/classes/data/BukkitEventValues.java +++ b/src/main/java/ch/njol/skript/classes/data/BukkitEventValues.java @@ -18,9 +18,6 @@ */ package ch.njol.skript.classes.data; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -662,34 +659,17 @@ public LivingEntity[] get(AreaEffectCloudApplyEvent event) { } }, EventValues.TIME_NOW); EventValues.registerEventValue(AreaEffectCloudApplyEvent.class, PotionEffectType.class, new Getter<PotionEffectType, AreaEffectCloudApplyEvent>() { - @Nullable - private final MethodHandle BASE_POTION_DATA_HANDLE; - - { - MethodHandle basePotionDataHandle = null; - if (Skript.methodExists(AreaEffectCloud.class, "getBasePotionData")) { - try { - basePotionDataHandle = MethodHandles.lookup().findVirtual(AreaEffectCloud.class, "getBasePotionData", MethodType.methodType(PotionData.class)); - } catch (NoSuchMethodException | IllegalAccessException e) { - Skript.exception(e, "Failed to load legacy potion data support. Potions may not work as expected."); - } - } - BASE_POTION_DATA_HANDLE = basePotionDataHandle; - } - + private final boolean HAS_POTION_TYPE_METHOD = Skript.methodExists(AreaEffectCloud.class, "getBasePotionType"); @Override @Nullable public PotionEffectType get(AreaEffectCloudApplyEvent e) { - if (BASE_POTION_DATA_HANDLE != null) { - try { - return ((PotionData) BASE_POTION_DATA_HANDLE.invoke(e.getEntity())).getType().getEffectType(); - } catch (Throwable ex) { - throw Skript.exception(ex, "An error occurred while trying to invoke legacy area effect cloud potion effect support."); - } - } else { + // TODO needs to be reworked to support multiple values (there can be multiple potion effects) + if (HAS_POTION_TYPE_METHOD) { PotionType base = e.getEntity().getBasePotionType(); - if (base != null) // TODO this is deprecated... this should become a multi-value event value + if (base != null) return base.getEffectType(); + } else { + return e.getEntity().getBasePotionData().getType().getEffectType(); } return null; } diff --git a/src/main/java/ch/njol/skript/util/PotionEffectUtils.java b/src/main/java/ch/njol/skript/util/PotionEffectUtils.java index bc72f768ae6..88f4bfbfe7c 100644 --- a/src/main/java/ch/njol/skript/util/PotionEffectUtils.java +++ b/src/main/java/ch/njol/skript/util/PotionEffectUtils.java @@ -18,9 +18,6 @@ */ package ch.njol.skript.util; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -346,20 +343,7 @@ else if (HAS_SUSPICIOUS_META && meta instanceof SuspiciousStewMeta) itemType.setItemMeta(meta); } - @Nullable - private static final MethodHandle BASE_POTION_DATA_HANDLE; - - static { - MethodHandle basePotionDataHandle = null; - if (Skript.methodExists(PotionMeta.class, "getBasePotionData")) { - try { - basePotionDataHandle = MethodHandles.lookup().findVirtual(PotionMeta.class, "getBasePotionData", MethodType.methodType(PotionData.class)); - } catch (NoSuchMethodException | IllegalAccessException e) { - Skript.exception(e, "Failed to load legacy potion data support. Potions may not work as expected."); - } - } - BASE_POTION_DATA_HANDLE = basePotionDataHandle; - } + private static final boolean HAS_POTION_TYPE_METHOD = Skript.methodExists(PotionMeta.class, "hasBasePotionType"); /** * Get all the PotionEffects of an ItemType @@ -374,21 +358,22 @@ public static List<PotionEffect> getEffects(ItemType itemType) { ItemMeta meta = itemType.getItemMeta(); if (meta instanceof PotionMeta) { PotionMeta potionMeta = ((PotionMeta) meta); - effects.addAll(potionMeta.getCustomEffects()); - if (BASE_POTION_DATA_HANDLE != null) { - try { - effects.addAll(PotionDataUtils.getPotionEffects((PotionData) BASE_POTION_DATA_HANDLE.invoke(meta))); - } catch (Throwable e) { - throw Skript.exception(e, "An error occurred while trying to invoke legacy potion data support."); + if (potionMeta.hasCustomEffects()) + effects.addAll(potionMeta.getCustomEffects()); + if (HAS_POTION_TYPE_METHOD) { + if (potionMeta.hasBasePotionType()) { + //noinspection ConstantConditions - checked via hasBasePotionType + effects.addAll(potionMeta.getBasePotionType().getPotionEffects()); + } + } else { // use deprecated method + PotionData data = potionMeta.getBasePotionData(); + if (data != null) { + effects.addAll(PotionDataUtils.getPotionEffects(data)); } - } else if (potionMeta.hasBasePotionType()) { - //noinspection ConstantConditions - checked via hasBasePotionType - effects.addAll(potionMeta.getBasePotionType().getPotionEffects()); } - } else if (HAS_SUSPICIOUS_META && meta instanceof SuspiciousStewMeta) effects.addAll(((SuspiciousStewMeta) meta).getCustomEffects()); return effects; } - + } diff --git a/src/test/skript/tests/regressions/6756-potion missing base type causes npe.sk b/src/test/skript/tests/regressions/6756-potion missing base type causes npe.sk new file mode 100644 index 00000000000..8ffa025b5e6 --- /dev/null +++ b/src/test/skript/tests/regressions/6756-potion missing base type causes npe.sk @@ -0,0 +1,3 @@ +test "potion missing base type": + + assert potion effects of (plain potion of mundane) is not set with "it should not have any effects" From 23cc26ba1328bc48c8a65154cdc329638ea43b82 Mon Sep 17 00:00:00 2001 From: Patrick Miller <apickledwalrus@gmail.com> Date: Thu, 6 Jun 2024 12:50:28 -0400 Subject: [PATCH 2/6] Fix Command Syncing CME (#6763) --- .../njol/skript/structures/StructCommand.java | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/main/java/ch/njol/skript/structures/StructCommand.java b/src/main/java/ch/njol/skript/structures/StructCommand.java index 5947a66ca52..e50476e5a8e 100644 --- a/src/main/java/ch/njol/skript/structures/StructCommand.java +++ b/src/main/java/ch/njol/skript/structures/StructCommand.java @@ -80,6 +80,9 @@ @Since("1.0") public class StructCommand extends Structure { + // Paper versions with the new command system need a delay before syncing commands or a CME will occur. + private static final boolean DELAY_COMMAND_SYNCING = Skript.classExists("io.papermc.paper.command.brigadier.Commands"); + public static final Priority PRIORITY = new Priority(500); private static final Pattern COMMAND_PATTERN = Pattern.compile("(?i)^command\\s+/?(\\S+)\\s*(\\s+(.+))?$"); @@ -315,7 +318,7 @@ public boolean load() { @Override public boolean postLoad() { - attemptCommandSync(); + scheduleCommandSync(); return true; } @@ -328,20 +331,28 @@ public void unload() { @Override public void postUnload() { - attemptCommandSync(); + scheduleCommandSync(); } - private void attemptCommandSync() { + private void scheduleCommandSync() { if (SYNC_COMMANDS.get()) { SYNC_COMMANDS.set(false); - if (CommandReloader.syncCommands(Bukkit.getServer())) { - Skript.debug("Commands synced to clients"); + if (DELAY_COMMAND_SYNCING) { + Bukkit.getScheduler().runTask(Skript.getInstance(), this::forceCommandSync); } else { - Skript.debug("Commands changed but not synced to clients (normal on 1.12 and older)"); + forceCommandSync(); } } } + private void forceCommandSync() { + if (CommandReloader.syncCommands(Bukkit.getServer())) { + Skript.debug("Commands synced to clients"); + } else { + Skript.debug("Commands changed but not synced to clients (normal on 1.12 and older)"); + } + } + @Override public Priority getPriority() { return PRIORITY; From aa7955c2663f5623213b529b6d331909e00cac36 Mon Sep 17 00:00:00 2001 From: Patrick Miller <apickledwalrus@gmail.com> Date: Sat, 15 Jun 2024 12:59:10 -0400 Subject: [PATCH 3/6] Fix Particle Definition Conflicts (#6760) --- .../skript/classes/data/SkriptClasses.java | 1 + src/main/resources/lang/default.lang | 38 +++++++++---------- .../pull-6760-particle itemtype conflicts.sk | 5 +++ .../tests/syntaxes/effects/EffVisualEffect.sk | 6 +-- 4 files changed, 28 insertions(+), 22 deletions(-) create mode 100644 src/test/skript/tests/regressions/pull-6760-particle itemtype conflicts.sk diff --git a/src/main/java/ch/njol/skript/classes/data/SkriptClasses.java b/src/main/java/ch/njol/skript/classes/data/SkriptClasses.java index 39dc6447fa5..6f92502cd2a 100644 --- a/src/main/java/ch/njol/skript/classes/data/SkriptClasses.java +++ b/src/main/java/ch/njol/skript/classes/data/SkriptClasses.java @@ -661,6 +661,7 @@ public String toVariableNameString(final Experience xp) { .usage(VisualEffects.getAllNames()) .since("2.1") .user("(visual|particle) effects?") + .after("itemtype") .parser(new Parser<VisualEffect>() { @Override @Nullable diff --git a/src/main/resources/lang/default.lang b/src/main/resources/lang/default.lang index 9f7df2c9e4c..90a37eb9e32 100644 --- a/src/main/resources/lang/default.lang +++ b/src/main/resources/lang/default.lang @@ -1473,13 +1473,13 @@ visual effects: block_marker: # added in 1.18 name: block marker @a - pattern: (barrierbm:barrier|lightbm:light|%-blockdata/itemtype% block marker) + pattern: (barrierbm:barrier [particle]|lightbm:light [particle]|%-blockdata/itemtype% block marker) barrier: name: barrier @a - pattern: barrier + pattern: barrier [particle] light: # added in 1.17 name: light @- - pattern: light + pattern: light [particle] bubble: # added in 1.20.5 name: bubble @- @@ -1534,7 +1534,7 @@ visual effects: dolphin: # added in 1.13 name: dolphin @- - pattern: dolphin + pattern: dolphin [particle] dragon_breath: # added in 1.14 name: dragon breath @- @@ -1602,10 +1602,10 @@ visual effects: elder_guardian: # added in 1.20.5 name: elder guardian @- - pattern: (elder guardian|mob appearance|guardian ghost) + pattern: (elder guardian particle|mob appearance|guardian ghost) mob_appearance: # for versions below 1.20.5 name: mob appearance @- - pattern: (elder guardian|mob appearance|guardian ghost) + pattern: (elder guardian particle|mob appearance|guardian ghost) electric_spark: name: electric spark @- @@ -1627,7 +1627,7 @@ visual effects: end_rod: name: end rod @- - pattern: end rod + pattern: end rod [particle] entity_effect: # added in 1.20.5 name: entity effect @an @@ -1693,10 +1693,10 @@ visual effects: firework: # added in 1.20.5 name: firework @- - pattern: (firework|firework['s] spark) + pattern: (firework particle|firework['s] spark) fireworks_spark: # for versions below 1.20.5 name: firework's spark @- - pattern: (firework|firework['s] spark) + pattern: (firework particle|firework['s] spark) fishing: # added in 1.20.5 name: water wake @- @@ -1764,24 +1764,24 @@ visual effects: item_cobweb: # added in 1.20.5 (for 1.21) name: cobweb @- - pattern: cobweb + pattern: cobweb [item|particle] item_slime: # added in 1.20.5 name: slime @- - pattern: slime + pattern: slime [item|particle] slime: # for versions below 1.20.5 name: slime @- - pattern: slime + pattern: slime [item|particle] item_snowball: # added in 1.20.5 name: snowball @- - pattern: (snowball [break]|snow shovel|snow(man| golem) spawn) + pattern: (snowball [item|break|particle]|snow shovel|snow(man| golem) spawn) snowball: # for versions below 1.20.5 name: snowball break @- pattern: snowball break snow_shovel: # for versions below 1.20.5 name: snow shovel @- - pattern: (snowball|snow shovel|snow(man| golem) spawn) + pattern: (snowball [item|particle]|snow shovel|snow(man| golem) spawn) landing_honey: # added in 1.15 name: landing honey @- @@ -1808,7 +1808,7 @@ visual effects: mycelium: # previously town_aura, changed in 1.20.5 name: mycelium @- - pattern: (mycelium|small smoke|town aura) + pattern: (mycelium [particle]|small smoke|town aura) town_aura: name: small smoke @- pattern: (mycelium|small smoke|town aura) @@ -1931,10 +1931,10 @@ visual effects: totem_of_undying: # added in 1.20.5 name: totem of undying @a - pattern: totem [of undying] + pattern: totem [of undying] [particle] totem: # for versions below 1.20.5 name: totem @a - pattern: totem [of undying] + pattern: totem [of undying] [particle] trial omen: # added in 1.20.5 (for 1.21) name: trial omen @a @@ -1989,10 +1989,10 @@ visual effects: witch: # added in 1.20.5 name: witch @a - pattern: (witch [magic|spell]|purple spark) + pattern: (witch (magic|spell|particle)|purple spark) spell_witch: # for versions below 1.20.5 name: witch spell @a - pattern: (witch [magic|spell]|purple spark) + pattern: (witch (magic|spell|particle)|purple spark) # -- Inventory Actions -- inventory actions: diff --git a/src/test/skript/tests/regressions/pull-6760-particle itemtype conflicts.sk b/src/test/skript/tests/regressions/pull-6760-particle itemtype conflicts.sk new file mode 100644 index 00000000000..d4cac535c18 --- /dev/null +++ b/src/test/skript/tests/regressions/pull-6760-particle itemtype conflicts.sk @@ -0,0 +1,5 @@ +test "particle itemtype conflicts": + + # itemtype parsing should take priority over visual effects + assert totem of undying is an itemtype with "totem of undying is not an itemtype" + assert mycelium is an itemtype with "mycelium is not an itemtype" diff --git a/src/test/skript/tests/syntaxes/effects/EffVisualEffect.sk b/src/test/skript/tests/syntaxes/effects/EffVisualEffect.sk index b8631e79cf2..a4791d1752a 100644 --- a/src/test/skript/tests/syntaxes/effects/EffVisualEffect.sk +++ b/src/test/skript/tests/syntaxes/effects/EffVisualEffect.sk @@ -16,7 +16,7 @@ test "visual effects": play dripping water at {_} play white dust with size 2 at {_} play effect at {_} - play elder guardian at {_} + play elder guardian particle at {_} play enchant at {_} play enchanted hit at {_} play end rod at {_} @@ -26,7 +26,7 @@ test "visual effects": play large explosion at {_} play explosion emitter at {_} play falling dust of air at {_} - play firework at {_} + play firework spark at {_} play fishing at {_} play flame at {_} play happy villager at {_} @@ -51,7 +51,7 @@ test "visual effects": play totem of undying at {_} play suspended at {_} play void fog at {_} - play witch at {_} + play witch particle at {_} parse if running minecraft "1.14.4": play campfire cosy smoke at {_} play campfire signal smoke at {_} From 2627c950d1734e45c5ad8e366ee2161fd44fba32 Mon Sep 17 00:00:00 2001 From: Shane Bee <shanebolenback@me.com> Date: Sat, 15 Jun 2024 10:42:35 -0700 Subject: [PATCH 4/6] ExprStringCase - include expression in toString (#6777) --- .../skript/expressions/ExprStringCase.java | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/main/java/ch/njol/skript/expressions/ExprStringCase.java b/src/main/java/ch/njol/skript/expressions/ExprStringCase.java index af963a333af..7a21357dca8 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprStringCase.java +++ b/src/main/java/ch/njol/skript/expressions/ExprStringCase.java @@ -153,22 +153,28 @@ public Class<? extends String> getReturnType() { } @Override - public String toString(@Nullable Event e, boolean debug) { + public String toString(@Nullable Event event, boolean debug) { + String mode = ""; switch (type) { case 0: // Basic Case Change - return (casemode == 1) ? "uppercase" : "lowercase"; + mode = (casemode == 1) ? "uppercase" : "lowercase"; + break; case 1: // Proper Case - return ((casemode == 3) ? "strict" : "lenient") + " proper case"; + mode = ((casemode == 3) ? "strict" : "lenient") + " proper case"; + break; case 2: // Camel Case - return ((casemode == 3) ? "strict" : "lenient") + " camel case"; + mode = ((casemode == 3) ? "strict" : "lenient") + " camel case"; + break; case 3: // Pascal Case - return ((casemode == 3) ? "strict" : "lenient") + " pascal case"; + mode = ((casemode == 3) ? "strict" : "lenient") + " pascal case"; + break; case 4: // Snake Case - return ((casemode == 0) ? "" : ((casemode == 1)) ? "upper " : "lower ") + "snake case"; + mode = ((casemode == 0) ? "" : ((casemode == 1)) ? "upper " : "lower ") + "snake case"; + break; case 5: // Kebab Case - return ((casemode == 0) ? "" : ((casemode == 1)) ? "upper " : "lower ") + "kebab case"; + mode = ((casemode == 0) ? "" : ((casemode == 1)) ? "upper " : "lower ") + "kebab case"; } - return ""; // Shouldn't reach here anyways + return mode + " " + expr.toString(event, debug); } @SuppressWarnings("null") From c6b0bfa71179259a1c21f735588c02548d8d4d8d Mon Sep 17 00:00:00 2001 From: Patrick Miller <apickledwalrus@gmail.com> Date: Sat, 15 Jun 2024 14:06:55 -0400 Subject: [PATCH 5/6] Fix firework spawning (#6764) --- .../njol/skript/entity/SimpleEntityData.java | 36 ++++++++++++++----- .../regressions/6762-cant spawn a firework.sk | 4 +++ 2 files changed, 31 insertions(+), 9 deletions(-) create mode 100644 src/test/skript/tests/regressions/6762-cant spawn a firework.sk diff --git a/src/main/java/ch/njol/skript/entity/SimpleEntityData.java b/src/main/java/ch/njol/skript/entity/SimpleEntityData.java index 6cad5ec1a2c..504c4449dc7 100644 --- a/src/main/java/ch/njol/skript/entity/SimpleEntityData.java +++ b/src/main/java/ch/njol/skript/entity/SimpleEntityData.java @@ -23,6 +23,8 @@ import java.util.ArrayList; import java.util.List; +import ch.njol.util.Kleenean; +import org.bukkit.World; import org.bukkit.entity.AbstractHorse; import org.bukkit.entity.Allay; import org.bukkit.entity.Animals; @@ -155,15 +157,13 @@ public final static class SimpleEntityDataInfo { final String codeName; final Class<? extends Entity> c; final boolean isSupertype; + final Kleenean allowSpawning; - SimpleEntityDataInfo(final String codeName, final Class<? extends Entity> c) { - this(codeName, c, false); - } - - SimpleEntityDataInfo(final String codeName, final Class<? extends Entity> c, final boolean isSupertype) { + SimpleEntityDataInfo(String codeName, Class<? extends Entity> c, boolean isSupertype, Kleenean allowSpawning) { this.codeName = codeName; this.c = c; this.isSupertype = isSupertype; + this.allowSpawning = allowSpawning; } @Override @@ -191,11 +191,18 @@ public boolean equals(final @Nullable Object obj) { private final static List<SimpleEntityDataInfo> types = new ArrayList<>(); private static void addSimpleEntity(String codeName, Class<? extends Entity> entityClass) { - types.add(new SimpleEntityDataInfo(codeName, entityClass)); + addSimpleEntity(codeName, entityClass, Kleenean.UNKNOWN); + } + + /** + * @param allowSpawning Whether to override the default {@link #canSpawn(World)} behavior and allow this entity to be spawned. + */ + private static void addSimpleEntity(String codeName, Class<? extends Entity> entityClass, Kleenean allowSpawning) { + types.add(new SimpleEntityDataInfo(codeName, entityClass, false, allowSpawning)); } private static void addSuperEntity(String codeName, Class<? extends Entity> entityClass) { - types.add(new SimpleEntityDataInfo(codeName, entityClass, true)); + types.add(new SimpleEntityDataInfo(codeName, entityClass, true, Kleenean.UNKNOWN)); } static { // Simple Entities @@ -238,7 +245,9 @@ private static void addSuperEntity(String codeName, Class<? extends Entity> enti addSimpleEntity("witch", Witch.class); addSimpleEntity("wither", Wither.class); addSimpleEntity("wither skull", WitherSkull.class); - addSimpleEntity("firework", Firework.class); + // bukkit marks fireworks as not spawnable + // see https://hub.spigotmc.org/jira/browse/SPIGOT-7677 + addSimpleEntity("firework", Firework.class, Kleenean.TRUE); addSimpleEntity("endermite", Endermite.class); addSimpleEntity("armor stand", ArmorStand.class); addSimpleEntity("shulker", Shulker.class); @@ -449,7 +458,16 @@ protected boolean equals_i(final EntityData<?> obj) { final SimpleEntityData other = (SimpleEntityData) obj; return info.equals(other.info); } - + + @Override + public boolean canSpawn(@Nullable World world) { + if (info.allowSpawning.isUnknown()) // unspecified, refer to default behavior + return super.canSpawn(world); + if (world == null) + return false; + return info.allowSpawning.isTrue(); + } + @Override public Fields serialize() throws NotSerializableException { final Fields f = super.serialize(); diff --git a/src/test/skript/tests/regressions/6762-cant spawn a firework.sk b/src/test/skript/tests/regressions/6762-cant spawn a firework.sk new file mode 100644 index 00000000000..f272e0bc8e0 --- /dev/null +++ b/src/test/skript/tests/regressions/6762-cant spawn a firework.sk @@ -0,0 +1,4 @@ +test "can't spawn a firework": + + spawn a firework at spawn of world "world" + assert last spawned firework is set with "firework did not spawn" From 7fc699e17299763523942d99524216480d426295 Mon Sep 17 00:00:00 2001 From: APickledWalrus <apickledwalrus@gmail.com> Date: Sat, 15 Jun 2024 14:40:33 -0400 Subject: [PATCH 6/6] Prepare For Release (2.8.7) --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 0b5b23f30d5..f78ae1766eb 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,7 +5,7 @@ org.gradle.parallel=true groupid=ch.njol name=skript -version=2.8.6 +version=2.8.7 jarName=Skript.jar testEnv=java21/paper-1.20.6 testEnvJavaVersion=21