From 3a5700b7d9c7ba124e9a9a1e0fa0590ae7780608 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 3 May 2026 02:14:03 +0000 Subject: [PATCH 01/35] Update Gradle wrapper to 9.5.0 --- gradle/wrapper/gradle-wrapper.jar | Bin 48966 -> 48462 bytes gradle/wrapper/gradle-wrapper.properties | 4 +++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index d997cfc60f4cff0e7451d19d49a82fa986695d07..b1b8ef56b44f16b14dc800fa8103a6d89abb526f 100644 GIT binary patch delta 39760 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 e(*aw}>J`&Ep$5$o2mVP)i30-M3~u@DBh0 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 delta 40115 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 e{Sg5G5zENPNVU~b5#<2@M#Os+0czL&{q{eZe Date: Sun, 17 May 2026 02:33:20 +0000 Subject: [PATCH 02/35] Update Gradle wrapper to 9.5.1 --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index b52fb7e713a..df6a6ad763d 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip networkTimeout=10000 retries=0 retryBackOffMs=500 From 1a465314088852371c8819b4df8ca8a8d2b3d5b8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 21 Jun 2026 03:01:54 +0000 Subject: [PATCH 03/35] Update Gradle wrapper to 9.6.0 --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index df6a6ad763d..eb84db68da7 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.0-bin.zip networkTimeout=10000 retries=0 retryBackOffMs=500 From f3a8990dfa253444005e7cc58502694e56241138 Mon Sep 17 00:00:00 2001 From: OwlBe Date: Fri, 26 Jun 2026 13:38:44 -0400 Subject: [PATCH 04/35] initial work still alot todo --- .../classes/data/BukkitEventValues.java | 23 - .../java/ch/njol/skript/events/EvtDamage.java | 137 ---- .../java/ch/njol/skript/events/EvtEntity.java | 90 --- .../njol/skript/events/EvtEntityShootBow.java | 94 --- .../ch/njol/skript/events/SimpleEvents.java | 648 +++++++----------- .../skript/bukkit/entity/EntityEvents.java | 275 ++++++++ .../skript/bukkit/entity/EntityModule.java | 15 + .../elements/events/EvtEntityBreakDoor.java | 65 ++ .../elements/events/EvtEntityDamage.java | 101 +++ .../elements/events/EvtEntityDeath.java | 79 +++ .../elements/events/EvtEntityShootBow.java | 99 +++ .../elements/events/EvtEntitySpawn.java | 78 +++ .../elements/events/EvtEntityTarget.java | 86 +++ 13 files changed, 1063 insertions(+), 727 deletions(-) delete mode 100644 src/main/java/ch/njol/skript/events/EvtDamage.java delete mode 100644 src/main/java/ch/njol/skript/events/EvtEntity.java delete mode 100644 src/main/java/ch/njol/skript/events/EvtEntityShootBow.java create mode 100644 src/main/java/org/skriptlang/skript/bukkit/entity/EntityEvents.java create mode 100644 src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java create mode 100644 src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java create mode 100644 src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDeath.java create mode 100644 src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityShootBow.java create mode 100644 src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntitySpawn.java create mode 100644 src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTarget.java 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 d04dd7b28c7..ee9f4fbe945 100644 --- a/src/main/java/ch/njol/skript/classes/data/BukkitEventValues.java +++ b/src/main/java/ch/njol/skript/classes/data/BukkitEventValues.java @@ -694,15 +694,6 @@ else if (hand == EquipmentSlot.OFF_HAND) registry.register(EventValue.simple(PlayerStopUsingItemEvent.class, ItemType.class, event -> new ItemType(event.getItem()))); } - // EntityResurrectEvent - registry.register(EventValue.simple(EntityResurrectEvent.class, Slot.class, event -> { - EquipmentSlot hand = event.getHand(); - EntityEquipment equipment = event.getEntity().getEquipment(); - if (equipment == null || hand == null) - return null; - return new ch.njol.skript.util.slot.EquipmentSlot(equipment, hand); - })); - // PlayerItemHeldEvent registry.register(EventValue.simple(PlayerItemHeldEvent.class, Slot.class, event -> new InventorySlot(event.getPlayer().getInventory(), event.getNewSlot()))); registry.register(EventValue.builder(PlayerItemHeldEvent.class, Slot.class) @@ -843,20 +834,6 @@ else if (hand == EquipmentSlot.OFF_HAND) .build()); } - registry.register(EventValue.simple(VillagerCareerChangeEvent.class, VillagerCareerChangeEvent.ChangeReason.class, VillagerCareerChangeEvent::getReason)); - registry.register(EventValue.builder(VillagerCareerChangeEvent.class, Villager.Profession.class) - .getter(VillagerCareerChangeEvent::getProfession) - .registerChanger(ChangeMode.SET, (event, profession) -> { - if (profession == null) - return; - event.setProfession(profession); - }) - .build()); - registry.register(EventValue.builder(VillagerCareerChangeEvent.class, Villager.Profession.class) - .getter(event -> event.getEntity().getProfession()) - .time(Time.PAST) - .build()); - } } diff --git a/src/main/java/ch/njol/skript/events/EvtDamage.java b/src/main/java/ch/njol/skript/events/EvtDamage.java deleted file mode 100644 index 60fafa120fb..00000000000 --- a/src/main/java/ch/njol/skript/events/EvtDamage.java +++ /dev/null @@ -1,137 +0,0 @@ -package ch.njol.skript.events; - -import org.bukkit.entity.EnderDragon; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.event.Event; -import org.bukkit.event.entity.EntityDamageByEntityEvent; -import org.bukkit.event.entity.EntityDamageEvent; -import org.jetbrains.annotations.Nullable; - -import ch.njol.skript.Skript; -import ch.njol.skript.bukkitutil.HealthUtils; -import ch.njol.skript.entity.EntityData; -import ch.njol.skript.lang.Literal; -import ch.njol.skript.lang.SkriptEvent; -import ch.njol.skript.lang.SkriptParser.ParseResult; - -/** - * @author Peter Güttinger - */ -@SuppressWarnings("unchecked") -public class EvtDamage extends SkriptEvent { - - static { - Skript.registerEvent("Damage", EvtDamage.class, EntityDamageEvent.class, "damag(e|ing) [of %-entitydata%] [by %-entitydata%]") - .description("Called when an entity receives damage, e.g. by an attack from another entity, lava, fire, drowning, fall, suffocation, etc.") - .examples("on damage:", "on damage of a player:", "on damage of player by zombie:") - .since("1.0, 2.7 (by entity)"); - } - - @Nullable - private Literal> ofTypes, byTypes; - - @Override - public boolean init(Literal[] args, int matchedPattern, ParseResult parser) { - ofTypes = (Literal>) args[0]; - byTypes = (Literal>) args[1]; - return true; - } - - @Override - public boolean check(Event evt) { - EntityDamageEvent e = (EntityDamageEvent) evt; - if (evt instanceof EntityDamageByEntityEvent) { - EntityDamageByEntityEvent event = (EntityDamageByEntityEvent) evt; - if (!checkDamager(event.getDamager())) - return false; - } else if (byTypes != null) { - return false; - } - if (!checkDamaged(e.getEntity())) - return false; - if (e instanceof EntityDamageByEntityEvent && ((EntityDamageByEntityEvent) e).getDamager() instanceof EnderDragon && ((EntityDamageByEntityEvent) e).getEntity() instanceof EnderDragon) - return false; - return checkDamage(e); - } - - private boolean checkDamager(Entity e) { - if (byTypes != null) { - for (EntityData d : byTypes.getAll()) { - if (d.isInstance(e)) - return true; - } - return false; - } - return true; - } - - private boolean checkDamaged(Entity e) { - if (ofTypes != null) { - for (EntityData d : ofTypes.getAll()) { - if (d.isInstance(e)) - return true; - } - return false; - } - return true; - } - - @Override - public String toString(@Nullable Event e, boolean debug) { - return "damage" + (ofTypes != null ? " of " + ofTypes.toString(e, debug) : "") + - (byTypes != null ? " by " + byTypes.toString(e, debug) : ""); - } - -// private final static WeakHashMap lastDamages = new WeakHashMap(); - - private static boolean checkDamage(EntityDamageEvent e) { - if (!(e.getEntity() instanceof LivingEntity)) - return true; - LivingEntity en = (LivingEntity) e.getEntity(); - if (HealthUtils.getHealth(en) <= 0) - return false; -// if (en.getNoDamageTicks() <= en.getMaximumNoDamageTicks() / 2) { -// lastDamages.put(en, e.getDamage()); -// return true; -// } -// final Integer lastDamage = lastDamages.get(en); -// if (lastDamage != null && lastDamage >= e.getDamage()) -// return false; -// lastDamages.put(en, e.getDamage()); - return true; - } - - /* - static { - Bukkit.getPluginManager().registerEvents(new Listener() { - @EventHandler - public void onDamage(final EntityDamageEvent e) { - if (e.getEntity() == EffSecSpawn.lastSpawned) { - final Entity en = e.getEntity(); - Skript.info(""); - Skript.info("- damage event! time: " + en.getWorld().getTime()); - // Skript.info("entity: " + en); - Skript.info("damage: " + e.getDamage()); - // Skript.info("last damage: " + (en.getLastDamageCause() == null ? "" : ""+en.getLastDamageCause().getDamage())); - if (en instanceof LivingEntity) { - Skript.info("is invincible: " + (((LivingEntity) en).getNoDamageTicks() > ((LivingEntity) en).getMaximumNoDamageTicks() / 2f)); - if (((LivingEntity) en).getNoDamageTicks() > 0) - Skript.info("damage difference (positive = more): " + (e.getDamage() - en.getLastDamageCause().getDamage())); - final int h = Math.max(((LivingEntity) en).getHealth(), 0); - Bukkit.getScheduler().scheduleSyncDelayedTask(Skript.getInstance(), new Runnable() { - @Override - public void run() { - Skript.info("actual damage: " + (h - Math.max(((LivingEntity) en).getHealth(), 0))); - } - }); - } - if (e instanceof EntityDamageByEntityEvent) { - Skript.info("attacker: " + ((EntityDamageByEntityEvent) e).getDamager()); - } - } - } - }, Skript.getInstance()); - } - // */ -} diff --git a/src/main/java/ch/njol/skript/events/EvtEntity.java b/src/main/java/ch/njol/skript/events/EvtEntity.java deleted file mode 100644 index bfbef66a66c..00000000000 --- a/src/main/java/ch/njol/skript/events/EvtEntity.java +++ /dev/null @@ -1,90 +0,0 @@ -package ch.njol.skript.events; - -import org.bukkit.entity.Entity; -import org.bukkit.entity.HumanEntity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.event.Event; -import org.bukkit.event.entity.EntityDeathEvent; -import org.bukkit.event.entity.EntitySpawnEvent; -import org.jetbrains.annotations.Nullable; - -import ch.njol.skript.Skript; -import ch.njol.skript.entity.EntityData; -import ch.njol.skript.lang.Literal; -import ch.njol.skript.lang.SkriptEvent; -import ch.njol.skript.lang.SkriptParser.ParseResult; -import ch.njol.skript.log.ErrorQuality; -import ch.njol.skript.registrations.Classes; -import ch.njol.util.StringUtils; - -/** - * @author Peter Güttinger - */ -@SuppressWarnings("unchecked") -public final class EvtEntity extends SkriptEvent { - - static { - Skript.registerEvent("Death", EvtEntity.class, EntityDeathEvent.class, "death [of %-entitydatas%]") - .description("Called when a living entity (including players) dies.") - .examples("on death:", - "on death of player:", - "on death of a wither or ender dragon:", - " broadcast \"A %entity% has been slain in %world%!\"") - .since("1.0"); - Skript.registerEvent("Spawn", EvtEntity.class, EntitySpawnEvent.class, "spawn[ing] [of %-entitydatas%]") - .description("Called when an entity spawns (excluding players).") - .examples("on spawn of a zombie:", - "on spawn of an ender dragon:", - " broadcast \"A dragon has been sighted in %world%!\"") - .since("1.0, 2.5.1 (non-living entities)"); - } - - @Nullable - private EntityData[] types; - - private boolean spawn; - - @SuppressWarnings("null") - @Override - public boolean init(final Literal[] args, final int matchedPattern, final ParseResult parser) { - types = args[0] == null ? null : ((Literal>) args[0]).getAll(); - spawn = StringUtils.startsWithIgnoreCase(parser.expr, "spawn"); - if (types != null) { - if (spawn) { - for (final EntityData d : types) { - if (HumanEntity.class.isAssignableFrom(d.getType())) { - Skript.error("The spawn event does not work for human entities", ErrorQuality.SEMANTIC_ERROR); - return false; - } - } - } else { - for (final EntityData d : types) { - if (!LivingEntity.class.isAssignableFrom(d.getType())) { - Skript.error("The death event only works for living entities", ErrorQuality.SEMANTIC_ERROR); - return false; - } - } - } - } - return true; - } - - @SuppressWarnings("null") - @Override - public boolean check(final Event e) { - if (types == null) - return true; - final Entity en = e instanceof EntityDeathEvent ? ((EntityDeathEvent) e).getEntity() : ((EntitySpawnEvent) e).getEntity(); - for (final EntityData d : types) { - if (d.isInstance(en)) - return true; - } - return false; - } - - @Override - public String toString(final @Nullable Event e, final boolean debug) { - return (spawn ? "spawn" : "death") + (types != null ? " of " + Classes.toString(types, false) : ""); - } - -} diff --git a/src/main/java/ch/njol/skript/events/EvtEntityShootBow.java b/src/main/java/ch/njol/skript/events/EvtEntityShootBow.java deleted file mode 100644 index 6561481cb58..00000000000 --- a/src/main/java/ch/njol/skript/events/EvtEntityShootBow.java +++ /dev/null @@ -1,94 +0,0 @@ -package ch.njol.skript.events; - -import ch.njol.skript.Skript; -import ch.njol.skript.entity.EntityData; -import ch.njol.skript.lang.Literal; -import ch.njol.skript.lang.LiteralList; -import ch.njol.skript.lang.SkriptEvent; -import ch.njol.skript.lang.SkriptParser.ParseResult; -import ch.njol.skript.registrations.EventConverter; -import ch.njol.skript.registrations.EventValues; -import ch.njol.skript.util.slot.EquipmentSlot; -import ch.njol.skript.util.slot.Slot; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.event.Event; -import org.bukkit.event.entity.EntityShootBowEvent; -import org.bukkit.inventory.EntityEquipment; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public class EvtEntityShootBow extends SkriptEvent { - - static { - Skript.registerEvent("Entity Shoot Bow", EvtEntityShootBow.class, EntityShootBowEvent.class, - "%entitydatas% shoot[ing] (bow|projectile)") - .description(""" - Called when an entity shoots a bow. - event-entity refers to the shot projectile/entity. - """) - .examples(""" - on player shoot bow: - chance of 30%: - damage event-slot by 10 - send "Your bow has taken increased damage!" to shooter - - on stray shooting bow: - set {_e} to event-entity - spawn a cow at {_e}: - set velocity of entity to velocity of {_e} - set event-entity to last spawned entity - """) - .since("2.11"); - - EventValues.registerEventValue(EntityShootBowEvent.class, ItemStack.class, EntityShootBowEvent::getBow); - - EventValues.registerEventValue(EntityShootBowEvent.class, Entity.class, new EventConverter<>() { - @Override - public void set(EntityShootBowEvent event, @Nullable Entity entity) { - if (entity == null) - return; - event.setProjectile(entity); - } - - @Override - public @NotNull Entity convert(EntityShootBowEvent from) { - return from.getProjectile(); - } - }); - - EventValues.registerEventValue(EntityShootBowEvent.class, Slot.class, event -> { - EntityEquipment equipment = event.getEntity().getEquipment(); - if (equipment == null) - return null; - return new EquipmentSlot(equipment, event.getHand()); - }); - - } - - private Literal> entityDatas; - - @Override - public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { - //noinspection unchecked - entityDatas = (Literal>) args[0]; - if (entityDatas instanceof LiteralList> list && list.getAnd()) - list.invertAnd(); - return true; - } - - @Override - public boolean check(Event event) { - if (!(event instanceof EntityShootBowEvent shootBowEvent)) - return false; - LivingEntity eventEntity = shootBowEvent.getEntity(); - return entityDatas.check(event, entityData -> entityData.isInstance(eventEntity)); - } - - @Override - public String toString(@Nullable Event event, boolean debug) { - return this.entityDatas.toString(event, debug) + " shoot bow"; - } - -} diff --git a/src/main/java/ch/njol/skript/events/SimpleEvents.java b/src/main/java/ch/njol/skript/events/SimpleEvents.java index 1da15c26671..b369f6272bd 100644 --- a/src/main/java/ch/njol/skript/events/SimpleEvents.java +++ b/src/main/java/ch/njol/skript/events/SimpleEvents.java @@ -35,398 +35,326 @@ public class SimpleEvents { // TODO - remove unncessary classExists checks when Spigot support is dropped Skript.registerEvent("Can Build Check", SimpleEvent.class, BlockCanBuildEvent.class, "[block] can build check") - .description("Called when a player rightclicks on a block while holding a block or a placeable item. You can either cancel the event to prevent the block from being built, or uncancel it to allow it.", - "Please note that the data value of the block to be placed is not available in this event, only its ID.") - .examples("on block can build check:", - "\tcancel event") - .since("1.0 (basic), 2.0 ([un]cancellable)"); + .description("Called when a player rightclicks on a block while holding a block or a placeable item. You can either cancel the event to prevent the block from being built, or uncancel it to allow it.", + "Please note that the data value of the block to be placed is not available in this event, only its ID.") + .examples("on block can build check:", + "\tcancel event") + .since("1.0 (basic), 2.0 ([un]cancellable)"); Skript.registerEvent("Block Damage", SimpleEvent.class, BlockDamageEvent.class, "block damag(ing|e)") - .description("Called when a player starts to break a block. You can usually just use the leftclick event for this.") - .examples("on block damaging:", - "\tif block is tagged with minecraft tag \"logs\":", - "\t\tsend \"You can't break the holy log!\"") - .since("1.0"); + .description("Called when a player starts to break a block. You can usually just use the leftclick event for this.") + .examples("on block damaging:", + "\tif block is tagged with minecraft tag \"logs\":", + "\t\tsend \"You can't break the holy log!\"") + .since("1.0"); Skript.registerEvent("Flow", SimpleEvent.class, BlockFromToEvent.class, "[block] flow[ing]", "block mov(e|ing)") - .description("Called when a blocks flows or teleports to another block. This not only applies to water and lava, but teleporting dragon eggs as well.") - .examples("on block flow:", - "\tif event-block is water:", - "\t\tbroadcast \"Build more dams! It's starting to get wet in here\"") - .since("1.0"); + .description("Called when a blocks flows or teleports to another block. This not only applies to water and lava, but teleporting dragon eggs as well.") + .examples("on block flow:", + "\tif event-block is water:", + "\t\tbroadcast \"Build more dams! It's starting to get wet in here\"") + .since("1.0"); Skript.registerEvent("Ignition", SimpleEvent.class, BlockIgniteEvent.class, "[block] ignit(e|ion)") - .description("Called when a block starts burning, i.e. a fire block is placed next to it and this block is flammable.", - "The burn event will be called when the block is about do be destroyed by the fire.") - .examples("on block ignite:", - "\tif event-block is a ladder:", - "\t\tcancel event") - .since("1.0"); + .description("Called when a block starts burning, i.e. a fire block is placed next to it and this block is flammable.", + "The burn event will be called when the block is about do be destroyed by the fire.") + .examples("on block ignite:", + "\tif event-block is a ladder:", + "\t\tcancel event") + .since("1.0"); Skript.registerEvent("Physics", SimpleEvent.class, BlockPhysicsEvent.class, "[block] physics") - .description("Called when a physics check is done on a block. By cancelling this event you can prevent some things from happening, " + - "e.g. sand falling, dirt turning into grass, torches dropping if their supporting block is destroyed, etc." + - "Please note that using this event might cause quite some lag since it gets called extremely often.") - .examples("# prevents sand from falling", - "on block physics:", - " block is sand", - " cancel event") - .since("1.4.6"); + .description("Called when a physics check is done on a block. By cancelling this event you can prevent some things from happening, " + + "e.g. sand falling, dirt turning into grass, torches dropping if their supporting block is destroyed, etc." + + "Please note that using this event might cause quite some lag since it gets called extremely often.") + .examples("# prevents sand from falling", + "on block physics:", + " block is sand", + " cancel event") + .since("1.4.6"); Skript.registerEvent("Piston Extend", SimpleEvent.class, BlockPistonExtendEvent.class, "piston extend[ing]") - .description("Called when a piston is about to extend.") - .examples("on piston extend:", - "\tbroadcast \"A piston is extending!\"") - .since("1.0"); + .description("Called when a piston is about to extend.") + .examples("on piston extend:", + "\tbroadcast \"A piston is extending!\"") + .since("1.0"); Skript.registerEvent("Piston Retract", SimpleEvent.class, BlockPistonRetractEvent.class, "piston retract[ing]") - .description("Called when a piston is about to retract.") - .examples("on piston retract:", - "\tbroadcast \"A piston is retracting!\"") - .since("1.0"); + .description("Called when a piston is about to retract.") + .examples("on piston retract:", + "\tbroadcast \"A piston is retracting!\"") + .since("1.0"); Skript.registerEvent("Redstone", SimpleEvent.class, BlockRedstoneEvent.class, "redstone [current] [chang(e|ing)]") - .description("Called when the redstone current of a block changes. This event is of not much use yet.") - .examples("on redstone change:", - "\tsend \"someone is using redstone\" to console") - .since("1.0"); + .description("Called when the redstone current of a block changes. This event is of not much use yet.") + .examples("on redstone change:", + "\tsend \"someone is using redstone\" to console") + .since("1.0"); Skript.registerEvent("Spread", SimpleEvent.class, BlockSpreadEvent.class, "spread[ing]") - .description("Called when a new block forms as a result of a block that can spread, e.g. water or mushrooms.") - .examples("on spread:") - .since("1.0"); + .description("Called when a new block forms as a result of a block that can spread, e.g. water or mushrooms.") + .examples("on spread:") + .since("1.0"); Skript.registerEvent("Chunk Load", SimpleEvent.class, ChunkLoadEvent.class, "chunk load[ing]") - .description("Called when a chunk loads. The chunk might or might not contain mobs when it's loaded.") - .examples("on chunk load:") - .since("1.0"); + .description("Called when a chunk loads. The chunk might or might not contain mobs when it's loaded.") + .examples("on chunk load:") + .since("1.0"); Skript.registerEvent("Chunk Generate", SimpleEvent.class, ChunkPopulateEvent.class, "chunk (generat|populat)(e|ing)") - .description("Called after a new chunk was generated.") - .examples("on chunk generate:") - .since("1.0"); + .description("Called after a new chunk was generated.") + .examples("on chunk generate:") + .since("1.0"); Skript.registerEvent("Chunk Unload", SimpleEvent.class, ChunkUnloadEvent.class, "chunk unload[ing]") - .description("Called when a chunk is unloaded due to not being near any player.") - .examples("on chunk unload:") - .since("1.0"); - Skript.registerEvent("Creeper Power", SimpleEvent.class, CreeperPowerEvent.class, "creeper power") - .description("Called when a creeper is struck by lighting and gets powered. Cancel the event to prevent the creeper from being powered.") - .examples("on creeper power:") - .since("1.0"); - Skript.registerEvent("Zombie Break Door", SimpleEvent.class, EntityBreakDoorEvent.class, "zombie break[ing] [a] [wood[en]] door") - .description("Called when a zombie is done breaking a wooden door. Can be cancelled to prevent the zombie from breaking the door.") - .examples("on zombie breaking a wood door:") - .since("1.0"); - Skript.registerEvent("Combust", SimpleEvent.class, EntityCombustEvent.class, "combust[ing]") - .description("Called when an entity is set on fire, e.g. by fire or lava, a fireball, or by standing in direct sunlight (zombies, skeletons).") - .examples("on combust:") - .since("1.0"); - Skript.registerEvent("Explode", SimpleEvent.class, EntityExplodeEvent.class, "explo(d(e|ing)|sion)") - .description("Called when an entity (a primed TNT or a creeper) explodes.") - .examples("on explosion:") - .since("1.0"); + .description("Called when a chunk is unloaded due to not being near any player.") + .examples("on chunk unload:") + .since("1.0"); // Skript.registerEvent(SimpleEvent.class, EntityInteractEvent.class, "interact");// = entity interacts with block, e.g. endermen?; player -> PlayerInteractEvent // likely tripwires, pressure plates, etc. - Skript.registerEvent("Portal Enter", SimpleEvent.class, EntityPortalEnterEvent.class, "portal enter[ing]", "entering [a] portal") - .description("Called when an entity enters a nether portal or an end portal. Please note that this event will be fired many times for a nether portal.") - .examples("on portal enter:") - .since("1.0"); - Skript.registerEvent("Tame", SimpleEvent.class, EntityTameEvent.class, "[entity] tam(e|ing)") - .description("Called when a player tames a wolf or ocelot. Can be cancelled to prevent the entity from being tamed.") - .examples("on tame:") - .since("1.0"); Skript.registerEvent("Explosion Prime", SimpleEvent.class, ExplosionPrimeEvent.class, "explosion prime") - .description("Called when an explosive is primed, i.e. an entity will explode shortly. Creepers can abort the explosion if the player gets too far away, " + - "while TNT will explode for sure after a short time.") - .examples("on explosion prime:") - .since("1.0"); + .description("Called when an explosive is primed, i.e. an entity will explode shortly. Creepers can abort the explosion if the player gets too far away, " + + "while TNT will explode for sure after a short time.") + .examples("on explosion prime:") + .since("1.0"); Skript.registerEvent("Hunger Meter Change", SimpleEvent.class, FoodLevelChangeEvent.class, "(food|hunger) (level|met(er|re)|bar) chang(e|ing)") - .description("Called when the hunger bar of a player changes, i.e. either increases by eating or decreases over time.") - .examples("on food bar change:") - .since("1.4.4"); + .description("Called when the hunger bar of a player changes, i.e. either increases by eating or decreases over time.") + .examples("on food bar change:") + .since("1.4.4"); Skript.registerEvent("Leaves Decay", SimpleEvent.class, LeavesDecayEvent.class, "leaves decay[ing]") - .description("Called when a leaf block decays due to not being connected to a tree.") - .examples("on leaves decay:") - .since("1.0"); + .description("Called when a leaf block decays due to not being connected to a tree.") + .examples("on leaves decay:") + .since("1.0"); Skript.registerEvent("Lightning Strike", SimpleEvent.class, LightningStrikeEvent.class, "lightning [strike]") - .description("Called when lightning strikes.") - .examples("on lightning:", "\tspawn a zombie at location of event-entity") - .since("1.0"); + .description("Called when lightning strikes.") + .examples("on lightning:", "\tspawn a zombie at location of event-entity") + .since("1.0"); Skript.registerEvent("Pig Zap", SimpleEvent.class, PigZapEvent.class, "pig[ ]zap") - .description("Called when a pig is stroke by lightning and transformed into a zombie pigman. Cancel the event to prevent the transformation.") - .examples("on pig zap:") - .since("1.0"); + .description("Called when a pig is stroke by lightning and transformed into a zombie pigman. Cancel the event to prevent the transformation.") + .examples("on pig zap:") + .since("1.0"); Skript.registerEvent("Bed Enter", SimpleEvent.class, PlayerBedEnterEvent.class, "bed enter[ing]", "[player] enter[ing] [a] bed") - .description("Called when a player starts sleeping.") - .examples("on bed enter:") - .since("1.0"); + .description("Called when a player starts sleeping.") + .examples("on bed enter:") + .since("1.0"); Skript.registerEvent("Bed Leave", SimpleEvent.class, PlayerBedLeaveEvent.class, "bed leav(e|ing)", "[player] leav(e|ing) [a] bed") - .description("Called when a player leaves a bed.") - .examples("on player leaving a bed:") - .since("1.0"); + .description("Called when a player leaves a bed.") + .examples("on player leaving a bed:") + .since("1.0"); Skript.registerEvent("Bucket Empty", SimpleEvent.class, PlayerBucketEmptyEvent.class, "bucket empty[ing]", "[player] empty[ing] [a] bucket")//TODO , "emptying bucket [of %itemtype%]", "emptying %itemtype% bucket") -> place of water/lava) - .description("Called when a player empties a bucket. You can also use the place event with a check for water or lava.") - .examples("on bucket empty:") - .since("1.0"); + .description("Called when a player empties a bucket. You can also use the place event with a check for water or lava.") + .examples("on bucket empty:") + .since("1.0"); Skript.registerEvent("Bucket fill", SimpleEvent.class, PlayerBucketFillEvent.class, "bucket fill[ing]", "[player] fill[ing] [a] bucket")//TODO , "filling bucket [(with|of) %itemtype%]", "filling %itemtype% bucket");) - .description("Called when a player fills a bucket.") - .examples("on player filling a bucket:") - .since("1.0"); + .description("Called when a player fills a bucket.") + .examples("on player filling a bucket:") + .since("1.0"); Skript.registerEvent("Egg Throw", SimpleEvent.class, PlayerEggThrowEvent.class, "throw[ing] [of] [an] egg", "[player] egg throw") - .description( - "Called when a player throws an egg and it lands. You can just use the shoot event in most cases." + - " However, this event allows modification of properties like the hatched entity type and the number of entities to hatch." - ) - .examples("on throw of an egg:") - .since("1.0"); + .description( + "Called when a player throws an egg and it lands. You can just use the shoot event in most cases." + + " However, this event allows modification of properties like the hatched entity type and the number of entities to hatch." + ) + .examples("on throw of an egg:") + .since("1.0"); Skript.registerEvent("Item Break", SimpleEvent.class, PlayerItemBreakEvent.class, "[player] tool break[ing]", "[player] break[ing] (a|the|) tool") - .description("Called when a player breaks their tool because its damage reached the maximum value.", - "This event cannot be cancelled.") - .examples("on tool break:") - .since("2.1.1"); + .description("Called when a player breaks their tool because its damage reached the maximum value.", + "This event cannot be cancelled.") + .examples("on tool break:") + .since("2.1.1"); Skript.registerEvent("Item Damage", SimpleEvent.class, PlayerItemDamageEvent.class, "item damag(e|ing)") - .description("Called when an item is damaged. Most tools are damaged by using them; armor is damaged when the wearer takes damage.") - .examples("on item damage:", - "\tcancel event") - .since("2.5"); + .description("Called when an item is damaged. Most tools are damaged by using them; armor is damaged when the wearer takes damage.") + .examples("on item damage:", + "\tcancel event") + .since("2.5"); Skript.registerEvent("Tool Change", SimpleEvent.class, PlayerItemHeldEvent.class, "[player['s]] (tool|item held|held item) chang(e|ing)") - .description("Called whenever a player changes their held item by selecting a different slot (e.g. the keys 1-9 or the mouse wheel), not by dropping or replacing the item in the current slot.") - .examples("on player's held item change:") - .since("1.0"); + .description("Called whenever a player changes their held item by selecting a different slot (e.g. the keys 1-9 or the mouse wheel), not by dropping or replacing the item in the current slot.") + .examples("on player's held item change:") + .since("1.0"); Skript.registerEvent("Join", SimpleEvent.class, PlayerJoinEvent.class, "[player] (login|logging in|join[ing])") - .description("Called when the player joins the server. The player is already in a world when this event is called, so if you want to prevent players from joining you should prefer on connect over this event.") - .examples("on join:", - " message \"Welcome on our awesome server!\"", - " broadcast \"%player% just joined the server!\"") - .since("1.0"); + .description("Called when the player joins the server. The player is already in a world when this event is called, so if you want to prevent players from joining you should prefer on connect over this event.") + .examples("on join:", + " message \"Welcome on our awesome server!\"", + " broadcast \"%player% just joined the server!\"") + .since("1.0"); Skript.registerEvent("Connect", SimpleEvent.class, PlayerLoginEvent.class, "[player] connect[ing]") - .description("Called when the player connects to the server. This event is called before the player actually joins the server, so if you want to prevent players from joining you should prefer this event over on join.") - .examples("on connect:", - " player doesn't have permission \"VIP\"", - " number of players is greater than 15", - " kick the player due to \"The last 5 slots are reserved for VIP players.\"") - .since("2.0"); + .description("Called when the player connects to the server. This event is called before the player actually joins the server, so if you want to prevent players from joining you should prefer this event over on join.") + .examples("on connect:", + " player doesn't have permission \"VIP\"", + " number of players is greater than 15", + " kick the player due to \"The last 5 slots are reserved for VIP players.\"") + .since("2.0"); Skript.registerEvent("Kick", SimpleEvent.class, PlayerKickEvent.class, "[player] (kick|being kicked)") - .description("Called when a player is kicked from the server. You can change the kick message or cancel the event entirely.") - .examples("on kick:") - .since("1.0"); + .description("Called when a player is kicked from the server. You can change the kick message or cancel the event entirely.") + .examples("on kick:") + .since("1.0"); Skript.registerEvent("Quit", SimpleEvent.class, PlayerQuitEvent.class, "(quit[ting]|disconnect[ing]|log[ ]out|logging out|leav(e|ing))") - .description("Called when a player leaves the server.") - .examples("on quit:", - "on disconnect:") - .since("1.0 (simple disconnection)"); + .description("Called when a player leaves the server.") + .examples("on quit:", + "on disconnect:") + .since("1.0 (simple disconnection)"); Skript.registerEvent("Respawn", SimpleEvent.class, PlayerRespawnEvent.class, "[player] respawn[ing]") - .description("Called when a player respawns via death or entering the end portal in the end. You should prefer this event over the death event as the player is technically alive when this event is called.") - .examples("on respawn:") - .since("1.0"); + .description("Called when a player respawns via death or entering the end portal in the end. You should prefer this event over the death event as the player is technically alive when this event is called.") + .examples("on respawn:") + .since("1.0"); Skript.registerEvent("Sneak Toggle", SimpleEvent.class, PlayerToggleSneakEvent.class, "[player] toggl(e|ing) sneak", "[player] sneak toggl(e|ing)") - .description("Called when a player starts or stops sneaking. Use is sneaking to get whether the player was sneaking before the event was called.") - .examples("# make players that stop sneaking jump", - "on sneak toggle:", - " player is sneaking", - " push the player upwards at speed 0.5") - .since("1.0"); + .description("Called when a player starts or stops sneaking. Use is sneaking to get whether the player was sneaking before the event was called.") + .examples("# make players that stop sneaking jump", + "on sneak toggle:", + " player is sneaking", + " push the player upwards at speed 0.5") + .since("1.0"); Skript.registerEvent("Sprint Toggle", SimpleEvent.class, PlayerToggleSprintEvent.class, "[player] toggl(e|ing) sprint", "[player] sprint toggl(e|ing)") - .description("Called when a player starts or stops sprinting. Use is sprinting to get whether the player was sprinting before the event was called.") - .examples("on sprint toggle:", - " player is not sprinting", - " send \"Run!\"") - .since("1.0"); + .description("Called when a player starts or stops sprinting. Use is sprinting to get whether the player was sprinting before the event was called.") + .examples("on sprint toggle:", + " player is not sprinting", + " send \"Run!\"") + .since("1.0"); Skript.registerEvent("Portal Create", SimpleEvent.class, PortalCreateEvent.class, "portal creat(e|ion)") - .description("Called when a portal is created, either by a player or mob lighting an obsidian frame on fire, or by a nether portal creating its teleportation target in the nether/overworld.", - "In Minecraft 1.14+, you can use the player in this event.", "Please note that there may not always be a player (or other entity) in this event.") - .examples("on portal create:") - .requiredPlugins("Minecraft 1.14+ (event-entity support)") - .since("1.0, 2.5.3 (event-entity support)"); + .description("Called when a portal is created, either by a player or mob lighting an obsidian frame on fire, or by a nether portal creating its teleportation target in the nether/overworld.", + "In Minecraft 1.14+, you can use the player in this event.", "Please note that there may not always be a player (or other entity) in this event.") + .examples("on portal create:") + .requiredPlugins("Minecraft 1.14+ (event-entity support)") + .since("1.0, 2.5.3 (event-entity support)"); Skript.registerEvent("Projectile Hit", SimpleEvent.class, ProjectileHitEvent.class, "projectile hit") - .description("Called when a projectile hits an entity or a block.") - .examples("on projectile hit:", - "\tif victim's health <= 3:", - "\t\tdelete event-projectile") - .since("1.0"); + .description("Called when a projectile hits an entity or a block.") + .examples("on projectile hit:", + "\tif victim's health <= 3:", + "\t\tdelete event-projectile") + .since("1.0"); if (Skript.classExists("com.destroystokyo.paper.event.entity.ProjectileCollideEvent")) Skript.registerEvent("Projectile Collide", SimpleEvent.class, ProjectileCollideEvent.class, "projectile collide") - .description("Called when a projectile collides with an entity.") - .examples("on projectile collide:", - "\tteleport shooter of event-projectile to event-entity") - .since("2.5"); + .description("Called when a projectile collides with an entity.") + .examples("on projectile collide:", + "\tteleport shooter of event-projectile to event-entity") + .since("2.5"); Skript.registerEvent("Shoot", SimpleEvent.class, ProjectileLaunchEvent.class, "[projectile] (shoot|launch)") - .description("Called whenever a projectile is shot. Use the shooter expression to get who shot the projectile.") - .examples("on shoot:", - "\tif projectile is an arrow:", - "\t\tsend \"you shot an arrow!\" to shooter") - .since("1.0"); + .description("Called whenever a projectile is shot. Use the shooter expression to get who shot the projectile.") + .examples("on shoot:", + "\tif projectile is an arrow:", + "\t\tsend \"you shot an arrow!\" to shooter") + .since("1.0"); Skript.registerEvent("Sign Change", SimpleEvent.class, SignChangeEvent.class, "sign (chang[e]|edit)[ing]", "[player] (chang[e]|edit)[ing] [a] sign") - .description("As signs are placed empty, this event is called when a player is done editing a sign.") - .examples("on sign change:", - " line 2 is empty", - " set line 1 to \"<red>%line 1%\"") - .since("1.0"); + .description("As signs are placed empty, this event is called when a player is done editing a sign.") + .examples("on sign change:", + " line 2 is empty", + " set line 1 to \"<red>%line 1%\"") + .since("1.0"); Skript.registerEvent("Spawn Change", SimpleEvent.class, SpawnChangeEvent.class, "[world] spawn change") - .description("Called when the spawn point of a world changes.") - .examples("on spawn change:", - "\tbroadcast \"someone changed the spawn!\"") - .since("1.0"); + .description("Called when the spawn point of a world changes.") + .examples("on spawn change:", + "\tbroadcast \"someone changed the spawn!\"") + .since("1.0"); Skript.registerEvent("Vehicle Create", SimpleEvent.class, VehicleCreateEvent.class, "vehicle create", "creat(e|ing|ion of) [a] vehicle") - .description("Called when a new vehicle is created, e.g. when a player places a boat or minecart.") - .examples("on vehicle create:") - .since("1.0"); + .description("Called when a new vehicle is created, e.g. when a player places a boat or minecart.") + .examples("on vehicle create:") + .since("1.0"); Skript.registerEvent("Vehicle Damage", SimpleEvent.class, VehicleDamageEvent.class, "vehicle damage", "damag(e|ing) [a] vehicle") - .description("Called when a vehicle gets damage. Too much damage will destroy the vehicle.") - .examples("on vehicle damage:") - .since("1.0"); + .description("Called when a vehicle gets damage. Too much damage will destroy the vehicle.") + .examples("on vehicle damage:") + .since("1.0"); Skript.registerEvent("Vehicle Destroy", SimpleEvent.class, VehicleDestroyEvent.class, "vehicle destroy", "destr(oy[ing]|uction of) [a] vehicle") - .description("Called when a vehicle is destroyed. Any passenger will be ejected and the vehicle might drop some item(s).") - .examples("on vehicle destroy:", - "\tcancel event") - .since("1.0"); + .description("Called when a vehicle is destroyed. Any passenger will be ejected and the vehicle might drop some item(s).") + .examples("on vehicle destroy:", + "\tcancel event") + .since("1.0"); Skript.registerEvent("Vehicle Enter", SimpleEvent.class, VehicleEnterEvent.class, "vehicle enter", "enter[ing] [a] vehicle") - .description("Called when an entity enters a vehicle, either deliberately (players) or by falling into them (mobs).") - .examples("on vehicle enter:", - "\tentity is a player", - "\tcancel event") - .since("1.0"); + .description("Called when an entity enters a vehicle, either deliberately (players) or by falling into them (mobs).") + .examples("on vehicle enter:", + "\tentity is a player", + "\tcancel event") + .since("1.0"); Skript.registerEvent("Vehicle Exit", SimpleEvent.class, VehicleExitEvent.class, "vehicle exit", "exit[ing] [a] vehicle") - .description("Called when an entity exits a vehicle.") - .examples("on vehicle exit:", - "\tif event-entity is a spider:", - "\t\tkill event-entity") - .since("1.0"); - if (Skript.classExists("org.bukkit.event.entity.EntityMountEvent") || Skript.classExists("org.spigotmc.event.entity.EntityMountEvent")) { - Class mountEventClass = null; - Class dismountEventClass = null; - if (Skript.classExists("org.bukkit.event.entity.EntityMountEvent")) { - mountEventClass = EntityMountEvent.class; - dismountEventClass = EntityDismountEvent.class; - } else { - try { - mountEventClass = (Class) Class.forName("org.spigotmc.event.entity.EntityMountEvent"); - dismountEventClass = (Class) Class.forName("org.spigotmc.event.entity.EntityDismountEvent"); - } catch (ClassNotFoundException e) { - Skript.exception(e, "Failed to load legacy mount/dismount event classes. These events may not work."); - } - } - if (mountEventClass != null) { - Skript.registerEvent("Entity Mount", SimpleEvent.class, mountEventClass, "mount[ing]") - .description("Called when entity starts riding another.") - .examples("on mount:", - "\tcancel event") - .since("2.2-dev13b"); - } - if (dismountEventClass != null) { - Skript.registerEvent("Entity Dismount", SimpleEvent.class, dismountEventClass, "dismount[ing]") - .description("Called when an entity dismounts.") - .examples("on dismount:", - "\tkill event-entity") - .since("2.2-dev13b"); - } - } + .description("Called when an entity exits a vehicle.") + .examples("on vehicle exit:", + "\tif event-entity is a spider:", + "\t\tkill event-entity") + .since("1.0"); Skript.registerEvent("Gliding State Change", SimpleEvent.class, EntityToggleGlideEvent.class, "(gliding state change|toggl(e|ing) gliding)") - .description("Called when an entity toggles glider on or off, or when server toggles gliding state of an entity forcibly.") - .examples("on toggling gliding:", - " cancel the event # bad idea, but you CAN do it!") - .since("2.2-dev21"); + .description("Called when an entity toggles glider on or off, or when server toggles gliding state of an entity forcibly.") + .examples("on toggling gliding:", + " cancel the event # bad idea, but you CAN do it!") + .since("2.2-dev21"); Skript.registerEvent("AoE Cloud Effect", SimpleEvent.class, AreaEffectCloudApplyEvent.class, "(area|AoE) [cloud] effect") - .description("Called when area effect cloud applies its potion effect. This happens every 5 ticks by default.") - .examples("on area cloud effect:") - .since("2.2-dev21"); - Skript.registerEvent("Sheep Regrow Wool", SimpleEvent.class, SheepRegrowWoolEvent.class, "sheep [re]grow[ing] wool") - .description("Called when sheep regrows its sheared wool back.") - .examples("on sheep grow wool:", - "\tcancel event") - .since("2.2-dev21"); + .description("Called when area effect cloud applies its potion effect. This happens every 5 ticks by default.") + .examples("on area cloud effect:") + .since("2.2-dev21"); Skript.registerEvent("Inventory Open", SimpleEvent.class, InventoryOpenEvent.class, "inventory open[ed]") - .description("Called when an inventory is opened for player.") - .examples("on inventory open:", - "\tclose player's inventory") - .since("2.2-dev21"); + .description("Called when an inventory is opened for player.") + .examples("on inventory open:", + "\tclose player's inventory") + .since("2.2-dev21"); Skript.registerEvent("Inventory Close", SimpleEvent.class, InventoryCloseEvent.class, "inventory clos(ing|e[d])") - .description("Called when player's currently viewed inventory is closed.") - .examples("on inventory close:", - "\tif player's location is {location}:", - "\t\tsend \"You exited the shop!\"") - .since("2.2-dev21"); - Skript.registerEvent("Slime Split", SimpleEvent.class, SlimeSplitEvent.class, "slime split[ting]") - .description("Called when a slime splits. Usually this happens when a big slime dies.") - .examples("on slime split:") - .since("2.2-dev26"); - Skript.registerEvent("Resurrect Attempt", SimpleEvent.class, EntityResurrectEvent.class, "[entity] resurrect[ion] [attempt]") - .description("Called when an entity dies, always. If they are not holding a totem, this is cancelled - you can, however, uncancel it.") - .examples( - "on resurrect attempt:", - "\tentity is player", - "\tentity has permission \"admin.undying\"", - "\tuncancel the event" - ) - .since("2.2-dev28") - .listeningBehavior(ListeningBehavior.ANY); + .description("Called when player's currently viewed inventory is closed.") + .examples("on inventory close:", + "\tif player's location is {location}:", + "\t\tsend \"You exited the shop!\"") + .since("2.2-dev21"); Skript.registerEvent("Player World Change", SimpleEvent.class, PlayerChangedWorldEvent.class, "[player] world chang(ing|e[d])") - .description("Called when a player enters a world. Does not work with other entities!") - .examples("on player world change:", - " world is \"city\"", - " send \"Welcome to the City!\"") - .since("2.2-dev28"); + .description("Called when a player enters a world. Does not work with other entities!") + .examples("on player world change:", + " world is \"city\"", + " send \"Welcome to the City!\"") + .since("2.2-dev28"); Skript.registerEvent("Flight Toggle", SimpleEvent.class, PlayerToggleFlightEvent.class, "[player] flight toggl(e|ing)", "[player] toggl(e|ing) flight") - .description("Called when a players stops/starts flying.") - .examples("on flight toggle:", - " if {game::%player%::playing} exists:", - " cancel event") - .since("2.2-dev36"); + .description("Called when a players stops/starts flying.") + .examples("on flight toggle:", + " if {game::%player%::playing} exists:", + " cancel event") + .since("2.2-dev36"); Skript.registerEvent("Language Change", SimpleEvent.class, PlayerLocaleChangeEvent.class, "[player] (language|locale) chang(e|ing)", "[player] chang(e|ing) (language|locale)") - .description("Called after a player changed their language in the game settings. You can use the language expression to get the current language of the player.") - .examples("on language change:", - " if player's language starts with \"en\":", - " send \"Hello!\"") - .since("2.3"); + .description("Called after a player changed their language in the game settings. You can use the language expression to get the current language of the player.") + .examples("on language change:", + " if player's language starts with \"en\":", + " send \"Hello!\"") + .since("2.3"); if (Skript.classExists("com.destroystokyo.paper.event.player.PlayerJumpEvent")) { Skript.registerEvent("Jump", SimpleEvent.class, PlayerJumpEvent.class, "[player] jump[ing]") - .description("Called whenever a player jumps.", - "This event requires PaperSpigot.") - .examples("on jump:", - " event-player does not have permission \"jump\"", - " cancel event") - .since("2.3"); - } - Skript.registerEvent("Hand Item Swap", SimpleEvent.class, PlayerSwapHandItemsEvent.class, "swap[ping of] [(hand|held)] item[s]") - .description("Called whenever a player swaps the items in their main- and offhand slots.", - "Works also when one or both of the slots are empty.", - "The event is called before the items are actually swapped,", - "so when you use the player's tool or player's offtool expressions,", - "they will return the values before the swap -", - "this enables you to cancel the event before anything happens.") - .examples("on swap hand items:", - " event-player's tool is a diamond sword", + .description("Called whenever a player jumps.", + "This event requires PaperSpigot.") + .examples("on jump:", + " event-player does not have permission \"jump\"", " cancel event") .since("2.3"); + } + Skript.registerEvent("Hand Item Swap", SimpleEvent.class, PlayerSwapHandItemsEvent.class, "swap[ping of] [(hand|held)] item[s]") + .description("Called whenever a player swaps the items in their main- and offhand slots.", + "Works also when one or both of the slots are empty.", + "The event is called before the items are actually swapped,", + "so when you use the player's tool or player's offtool expressions,", + "they will return the values before the swap -", + "this enables you to cancel the event before anything happens.") + .examples("on swap hand items:", + " event-player's tool is a diamond sword", + " cancel event") + .since("2.3"); Class serverListPingEventClass = (Skript.classExists("com.destroystokyo.paper.event.server.PaperServerListPingEvent") ? PaperServerListPingEvent.class : ServerListPingEvent.class); Skript.registerEvent("Server List Ping", SimpleEvent.class, serverListPingEventClass, "server [list] ping") - .description("Called when a server list ping is coming in, generally when a Minecraft client pings the server to show its information in the server list.", - "The IP expression can be used to get the IP adress of the pinger.", - "This event can be cancelled on PaperSpigot 1.12.2+ only and this means the player will see the server as offline (but still can join).", - "", - "Also you can use MOTD, Max Players, " + - "Online Players Count, Protocol Version, " + - "Version String, Hover List and Server Icon " + - "expressions, and Player Info Visibility and Hide Player from Server List effects to modify the server list.") - .examples("on server list ping:", - " set the motd to \"Welcome %{player-by-IP::%ip%}%! Join now!\" if {player-by-IP::%ip%} is set, else \"Join now!\"", - " set the fake max players count to (online players count + 1)", - " set the shown icon to a random server icon out of {server-icons::*}") - .since("2.3"); + .description("Called when a server list ping is coming in, generally when a Minecraft client pings the server to show its information in the server list.", + "The IP expression can be used to get the IP adress of the pinger.", + "This event can be cancelled on PaperSpigot 1.12.2+ only and this means the player will see the server as offline (but still can join).", + "", + "Also you can use MOTD, Max Players, " + + "Online Players Count, Protocol Version, " + + "Version String, Hover List and Server Icon " + + "expressions, and Player Info Visibility and Hide Player from Server List effects to modify the server list.") + .examples("on server list ping:", + " set the motd to \"Welcome %{player-by-IP::%ip%}%! Join now!\" if {player-by-IP::%ip%} is set, else \"Join now!\"", + " set the fake max players count to (online players count + 1)", + " set the shown icon to a random server icon out of {server-icons::*}") + .since("2.3"); Skript.registerEvent("Swim Toggle", SimpleEvent.class, EntityToggleSwimEvent.class, "[entity] toggl(e|ing) swim", "[entity] swim toggl(e|ing)") - .description("Called when an entity swims or stops swimming.") - .requiredPlugins("1.13 or newer") - .examples("on swim toggle:", - " event-entity does not have permission \"swim\"", - " cancel event") - .since("2.3"); + .description("Called when an entity swims or stops swimming.") + .requiredPlugins("1.13 or newer") + .examples("on swim toggle:", + " event-entity does not have permission \"swim\"", + " cancel event") + .since("2.3"); Skript.registerEvent("Riptide", SimpleEvent.class, PlayerRiptideEvent.class, "[use of] riptide [enchant[ment]]") - .description("Called when the player activates the riptide enchantment, using their trident to propel them through the air.", - "Note: the riptide action is performed client side, so manipulating the player in this event may have undesired effects.") - .examples("on riptide:", - " send \"You are riptiding!\"") - .since("2.5"); + .description("Called when the player activates the riptide enchantment, using their trident to propel them through the air.", + "Note: the riptide action is performed client side, so manipulating the player in this event may have undesired effects.") + .examples("on riptide:", + " send \"You are riptiding!\"") + .since("2.5"); Skript.registerEvent("Sponge Absorb", SimpleEvent.class, SpongeAbsorbEvent.class, "sponge absorb") - .description("Called when a sponge absorbs blocks.") - .requiredPlugins("Minecraft 1.13 or newer") - .examples("on sponge absorb:", - "\tloop absorbed blocks:", - "\t\tbroadcast \"%loop-block% was absorbed by a sponge\"!") - .since("2.5"); + .description("Called when a sponge absorbs blocks.") + .requiredPlugins("Minecraft 1.13 or newer") + .examples("on sponge absorb:", + "\tloop absorbed blocks:", + "\t\tbroadcast \"%loop-block% was absorbed by a sponge\"!") + .since("2.5"); Skript.registerEvent("Enchant Prepare", SimpleEvent.class, PrepareItemEnchantEvent.class, "[item] enchant prepare") .description("Called when a player puts an item into enchantment table. This event may be called multiple times.", " To get the enchant item, see the enchant item expression") @@ -435,19 +363,15 @@ public class SimpleEvents { "\tset the cost of enchant offer 1 to 10 levels") .since("2.5"); Skript.registerEvent("Enchant", SimpleEvent.class, EnchantItemEvent.class, "[item] enchant") - .description("Called when a player successfully enchants an item.", - " To get the enchanted item, see the enchant item expression") - .examples("on enchant:", - "\tif the clicked button is 1: # offer 1", - "\t\tset the applied enchantments to sharpness 10 and unbreaking 10") - .since("2.5"); + .description("Called when a player successfully enchants an item.", + " To get the enchanted item, see the enchant item expression") + .examples("on enchant:", + "\tif the clicked button is 1: # offer 1", + "\t\tset the applied enchantments to sharpness 10 and unbreaking 10") + .since("2.5"); Skript.registerEvent("Inventory Pickup", SimpleEvent.class, InventoryPickupItemEvent.class, "inventory pick[ ]up") - .description("Called when an inventory (a hopper, a hopper minecart, etc.) picks up an item") - .examples("on inventory pickup:") - .since("2.5.1"); - Skript.registerEvent("Horse Jump", SimpleEvent.class, HorseJumpEvent.class, "horse jump") - .description("Called when a horse jumps.") - .examples("on horse jump:", "\tpush event-entity upwards at speed 2") + .description("Called when an inventory (a hopper, a hopper minecart, etc.) picks up an item") + .examples("on inventory pickup:") .since("2.5.1"); Skript.registerEvent("Block Fertilize", SimpleEvent.class, BlockFertilizeEvent.class, "[block] fertilize") .description("Called when a player fertilizes blocks.") @@ -486,18 +410,10 @@ public class SimpleEvents { "\t\tsend \"The trade was somehow denied!\" to player") .since("2.7"); } - if (Skript.classExists("com.destroystokyo.paper.event.entity.EntityJumpEvent")) { - Skript.registerEvent("Entity Jump", SimpleEvent.class, EntityJumpEvent.class, "entity jump[ing]") - .description("Called when an entity jumps.") - .examples("on entity jump:", - "\tif entity is a wither skeleton:", - "\t\tcancel event") - .since("2.7"); - } if (Skript.classExists("com.destroystokyo.paper.event.block.AnvilDamagedEvent")) { Skript.registerEvent("Anvil Damage", SimpleEvent.class, AnvilDamagedEvent.class, "anvil damag(e|ing)") .description("Called when an anvil is damaged/broken from being used to repair/rename items.", - "Note: this does not include anvil damage from falling.") + "Note: this does not include anvil damage from falling.") .examples("on anvil damage:", "\tcancel the event") .since("2.7"); @@ -598,21 +514,6 @@ public class SimpleEvents { ) .since("2.9.0"); - if (Skript.classExists("com.destroystokyo.paper.event.entity.EndermanAttackPlayerEvent")) { - Skript.registerEvent("Enderman Enrage", SimpleEvent.class, com.destroystokyo.paper.event.entity.EndermanAttackPlayerEvent.class, "enderman (enrage|anger)") - .description( - "Called when an enderman gets mad because a player looked at them.", - "Note: This does not stop enderman from targeting the player as a result of getting damaged." - ) - .examples( - "# Stops endermen from getting angry players with the permission \"safeFrom.enderman\"", - "on enderman enrage:", - "\tif player has permission \"safeFrom.enderman\":", - "\t\tcancel event" - ) - .since("2.9.0"); - } - if (Skript.classExists("io.papermc.paper.event.player.PlayerChangeBeaconEffectEvent")) { Skript.registerEvent("Beacon Change Effect", SimpleEvent.class, PlayerChangeBeaconEffectEvent.class, "beacon change effect", "beacon effect change", "player chang(e[s]|ing) [of] beacon effect") @@ -673,11 +574,6 @@ public class SimpleEvents { .since("2.10"); } - Skript.registerEvent("Bat Toggle Sleep", SimpleEvent.class, BatToggleSleepEvent.class, "bat toggle sleep") - .description("Called when a bat attempts to go to sleep or wakes up.") - .examples("on bat toggle sleep:") - .since("2.11"); - // WorldBorder Events if (Skript.classExists("io.papermc.paper.event.world.border.WorldBorderEvent")) { Skript.registerEvent("World Border Bounds Change", SimpleEvent.class, WorldBorderBoundsChangeEvent.class, "world[ ]border [bounds] chang(e|ing)") @@ -721,26 +617,12 @@ public class SimpleEvents { .examples( """ on vault display item: - set event-item to a netherite ingot + set event-item to a netherite ingot """ ) .since("2.12") .requiredPlugins("Minecraft 1.21.1+"); } - - Skript.registerEvent("Villager Career Change", SimpleEvent.class, VillagerCareerChangeEvent.class, - "villager career chang(e[d]|ing)") - .description("Called when a villager changes its career. Can be caused by being employed or losing their job.") - .examples(""" - on villager career change: - if all: - event-career change reason is employment - event-villager profession is armorer profession - then: - cancel event - """) - .since("2.12"); - } } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/EntityEvents.java b/src/main/java/org/skriptlang/skript/bukkit/entity/EntityEvents.java new file mode 100644 index 00000000000..14e9d479125 --- /dev/null +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/EntityEvents.java @@ -0,0 +1,275 @@ +package org.skriptlang.skript.bukkit.entity; + +import ch.njol.skript.classes.Changer.ChangeMode; +import ch.njol.skript.lang.SkriptEvent; +import ch.njol.skript.lang.util.SimpleEvent; +import ch.njol.skript.util.slot.EquipmentSlot; +import ch.njol.skript.util.slot.Slot; +import com.destroystokyo.paper.event.entity.EntityJumpEvent; +import org.bukkit.entity.Villager; +import org.bukkit.event.entity.*; +import org.bukkit.inventory.EntityEquipment; +import org.bukkit.inventory.ItemStack; +import org.skriptlang.skript.bukkit.lang.eventvalue.EventValue; +import org.skriptlang.skript.bukkit.lang.eventvalue.EventValueRegistry; +import org.skriptlang.skript.bukkit.registration.BukkitSyntaxInfos; +import org.skriptlang.skript.registration.SyntaxRegistry; + +import static org.skriptlang.skript.bukkit.lang.eventvalue.EventValue.Time.PAST; + +public class EntityEvents { + + public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry eventValueRegistry) { + + // + // Entity Events + // + + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Entity Combust") + .addEvent(EntityCombustEvent.class) + .addPatterns("[entity] combust[ing]") + .addDescription(""" + Called when an entity is set on fire, + e.g. when a player gets hit by a fireball, or a zombie goes into sunlight during the day. + """) + .addExample(""" + on entity combust: + broadcast "It burns!!" + """) + .addSince("1.0") + .build()); + + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Entity Explode") + .addEvent(EntityExplodeEvent.class) + .addPatterns("[entity] explo(d(e|ing)|sion)") + .addDescription(""" + Called when an entity (usually a primed TNT or creeper) explodes. + """) + .addExample(""" + on entity explode: + broadcast "*Explosion*" + """) + .addSince("1.0") + .build()); + + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Entity Portal Enter") + .addEvent(EntityPortalEnterEvent.class) + .addPatterns("[entity] enter[ing] [a] portal", "[entity] portal enter[ing]") + .addDescription(""" + Called when an entity enters a nether portal or an end portal. + Please note that this event will be fired many times for a nether portal. + """) + .addExample(""" + on portal enter: + kill event-entity + broadcast "%event-entity% never got to see a new dimension.." + """) + .addSince("1.0") + .build()); + + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Entity Tame") + .addEvent(EntityTameEvent.class) + .addPatterns("[entity] tam(e|ing)") + .addDescription(""" + Called when a player tames a wolf or ocelot. + Can be cancelled to prevent the entity from being tamed. + """) + .addExample(""" + on tame: + broadcast "Best friends for life!" + """) + .addSince("1.0") + .build()); + + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Entity Mount") + .addEvent(EntityMountEvent.class) + .addPatterns("[entity] mount[ing]") + .addDescription(""" + Called when an entity starts riding another." + """) + .addExample(""" + on entity mount: + cancel event + """) + .addSince("2.2-dev13b") + .build()); + + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Entity Dismount") + .addEvent(EntityDismountEvent.class) + .addPatterns("[entity] dismount[ing]") + .addDescription(""" + Called when an entity dismounts another. + """) + .addExample(""" + on entity dismount: + kill event-entity + """) + .addSince("2.2-dev13b") + .build()); + + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Entity Resurrect Attempt") + .addEvent(EntityResurrectEvent.class) + .addPatterns("[entity] resurrect[ion] [attempt]") + .listeningBehavior(SkriptEvent.ListeningBehavior.ANY) + .addDescription(""" + Called when an entity dies. + If they are not holding a totem, this is cancellable - you can, however, uncancel it. + """) + .addExample(""" + on entity resurrect attempt: + if all: + event-entity is a player + event-entity has permission "god" + then: + send "You seem to be immortal.. how" to event-entity + """) + .addSince("2.2-dev28") + .build()); + + eventValueRegistry.register(EventValue.builder(EntityResurrectEvent.class, Slot.class) + .getter(event -> { + org.bukkit.inventory.EquipmentSlot hand = event.getHand(); + EntityEquipment equipment = event.getEntity().getEquipment(); + if (equipment == null || hand == null) + return null; + return new EquipmentSlot(equipment, hand); + }) + .build()); + + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Entity Jump") + .addEvent(EntityJumpEvent.class) + .addPatterns("entity jump[ing]") + .addDescription(""" + Called when an entity jumps. + """) + .addExample(""" + on entity jump: + push event-entity up at speed 1 + """) + .addSince("2.7") + .build()); + + // + // Entity specific events (e.g. CreeperPowerEvent) + // + + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Creeper Power") + .addEvent(CreeperPowerEvent.class) + .addPatterns("creeper power") + .addDescription(""" + Called when a creeper is struck by lighting and gets powered. + Cancelling the event will prevent the creeper from being powered. + """) + .addExample(""" + on creeper power: + cancel event + broadcast "No charged creepers in this world!" + """) + .addSince("1.0") + .build()); + + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Sheep Regrow Wool") + .addEvent(SheepRegrowWoolEvent.class) + .addPatterns("sheep [re]grow[ing] wool") + .addDescription("Called when sheep regrows its sheared wool back.") + .addExample(""" + on sheep grow wool: + loop all players in radius 50 of event-entity: + send "Theres free wool nearby!" to loop-value + """) + .addSince("2.2-dev21") + .build()); + + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Slime Split") + .addEvent(SlimeSplitEvent.class) + .addPatterns("slime split[ting]") + .addDescription(""" + Called when a slime splits. + Usually when a big slime dies. + """) + .addExample(""" + on slime split: + broadcast "More slime minions have spawned!" + """) + .addSince("2.2-dev26") + .build()); + + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Horse Jump") + .addEvent(HorseJumpEvent.class) + .addPatterns("horse jump[ing]") + .addDescription("Called when a horse jumps.") + .addExample(""" + on horse jumping: + push event-entity upwards at speed 2 + send "Wow that horse can really go high.." to (all players in radius 3 of event-entity) + """) + .addSince("2.5.1") + .build()); + + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Piglin Barter") + .addEvent(PiglinBarterEvent.class) + .addPatterns("piglin (barter[ing]|trad(e|ing))") + .addDescription(""" + Called when a piglin finishes bartering. + Note that a piglin may start bartering after picking up an item on its bartering list. + If this event is cancelled it will prevent piglins from dropping items, but will still make them pick up the input. + """) + .addExample(""" + on piglin barter: + if barter drops contain diamond: + broadcast "Diamonds are too rare for this world.." + cancel event + """) + .addSince("2.10") + .build()); + + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Bat Toggle Sleep") + .addEvent(BatToggleSleepEvent.class) + .addPatterns("bat toggl(e|ing) sleep") + .addDescription("Called when a bat attempts to go to sleep or wakes up.") + .addExample(""" + on bat toggle sleep: + kill event-entity + broadcast "Another bat tried to sleep and perished.." + """) + .addSince("2.11") + .build()); + + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Villager Career Change") + .addEvent(VillagerCareerChangeEvent.class) + .addPatterns("villager career chang(e[d]|ing)") + .addDescription(""" + Called when a villager changes its career. + Can be caused by being employed or losing their job. + """) + .addExample(""" + on villager career change: + if all: + event-career change reason is employment + event-villager profession is armorer profession + then: + cancel event + """) + .addSince("2.12") + .build()); + + eventValueRegistry.register(EventValue.builder(VillagerCareerChangeEvent.class, Villager.Profession.class) + .getter(VillagerCareerChangeEvent::getProfession) + .registerChanger(ChangeMode.SET, (event, profession) -> { + if (profession == null) + return; + event.setProfession(profession); + }) + .build()); + + eventValueRegistry.register(EventValue.builder(VillagerCareerChangeEvent.class, VillagerCareerChangeEvent.ChangeReason.class) + .getter(VillagerCareerChangeEvent::getReason) + .build()); + + eventValueRegistry.register(EventValue.builder(VillagerCareerChangeEvent.class, Villager.Profession.class) + .getter(event -> event.getEntity().getProfession()) + .time(PAST) + .build()); + } + +} diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/EntityModule.java b/src/main/java/org/skriptlang/skript/bukkit/entity/EntityModule.java index 5e07c604ed6..8bf6acfd59f 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/EntityModule.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/EntityModule.java @@ -7,11 +7,14 @@ import org.skriptlang.skript.addon.HierarchicalAddonModule; import org.skriptlang.skript.addon.SkriptAddon; import org.skriptlang.skript.bukkit.entity.displays.DisplayModule; +import org.skriptlang.skript.bukkit.entity.elements.events.*; import org.skriptlang.skript.bukkit.entity.interactions.InteractionModule; import org.skriptlang.skript.bukkit.entity.elements.expressions.ExprDeathMessage; import org.skriptlang.skript.bukkit.entity.entitydata.NautilusData; import org.skriptlang.skript.bukkit.entity.entitydata.ZombieNautilusData; import org.skriptlang.skript.bukkit.entity.player.PlayerModule; +import org.skriptlang.skript.bukkit.lang.eventvalue.EventValueRegistry; +import org.skriptlang.skript.registration.SyntaxRegistry; import java.util.List; @@ -40,6 +43,18 @@ protected void loadSelf(SkriptAddon addon) { register(addon, ExprDeathMessage::register ); + + EventValueRegistry eventValueRegistry = addon.registry(EventValueRegistry.class); + SyntaxRegistry syntaxRegistry = moduleRegistry(addon); + + EntityEvents.register(syntaxRegistry, eventValueRegistry); + + EvtEntityBreakDoor.register(syntaxRegistry); + EvtEntityDamage.register(syntaxRegistry); + EvtEntityDeath.register(syntaxRegistry); + EvtEntityShootBow.register(syntaxRegistry, eventValueRegistry); + EvtEntitySpawn.register(syntaxRegistry); + } @Override diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java new file mode 100644 index 00000000000..b1fefdbbcdb --- /dev/null +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java @@ -0,0 +1,65 @@ +package org.skriptlang.skript.bukkit.entity.elements.events; + +import ch.njol.skript.entity.EntityData; +import ch.njol.skript.lang.Literal; +import ch.njol.skript.lang.SkriptEvent; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.lang.SyntaxStringBuilder; +import org.bukkit.event.Event; +import org.bukkit.event.entity.EntityBreakDoorEvent; +import org.jetbrains.annotations.Nullable; +import org.skriptlang.skript.bukkit.registration.BukkitSyntaxInfos; +import org.skriptlang.skript.registration.SyntaxRegistry; + +@SuppressWarnings("rawtypes") +public class EvtEntityBreakDoor extends SkriptEvent { + + public static void register(SyntaxRegistry syntaxRegistry) { + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(EvtEntityBreakDoor.class, "Entity Break Door") + .supplier(EvtEntityBreakDoor::new) + .addEvent(EntityBreakDoorEvent.class) + .addPatterns("[entity:%entitydata%] break[ing] [a] [wood[en]] door") + .addDescription(""" + Called when an entity (usually a zombie) is breaking a door. + Can be cancelled to prevent the entity from breaking the door. + """) + .addExample(""" + on entity breaking a door: + type of event-entity is zombie + broadcast "A zombie is about to murder a villager!" + """) + .addSince("1.0, INSERT VERSION (new pattern)") + .build()); + } + + private EntityData[] entityData; + + @Override + @SuppressWarnings("unchecked") + public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { + if (parseResult.hasTag("entity")) { + Literal entityLiteral = (Literal) args[0]; + entityData = entityLiteral.getArray(); + } + return true; + } + + @Override + public boolean check(Event event) { + if (entityData != null) { + EntityBreakDoorEvent entityEvent = (EntityBreakDoorEvent) event; + for (EntityData entity : entityData) + return entity.isInstance(entityEvent.getEntity()); + } + return true; + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return new SyntaxStringBuilder(event, debug) + .append(entityData != null ? entityData : "entity") + .append("breaking a wooden door") + .toString(); + } + +} \ No newline at end of file diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java new file mode 100644 index 00000000000..d2447199f59 --- /dev/null +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java @@ -0,0 +1,101 @@ +package org.skriptlang.skript.bukkit.entity.elements.events; + +import ch.njol.skript.bukkitutil.HealthUtils; +import ch.njol.skript.entity.EntityData; +import ch.njol.skript.lang.Literal; +import ch.njol.skript.lang.SkriptEvent; +import ch.njol.skript.lang.SkriptParser; +import ch.njol.skript.lang.SyntaxStringBuilder; +import org.bukkit.entity.LivingEntity; +import org.bukkit.event.Event; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.EntityDamageEvent; +import org.jetbrains.annotations.Nullable; +import org.skriptlang.skript.bukkit.registration.BukkitSyntaxInfos; +import org.skriptlang.skript.registration.SyntaxRegistry; + +@SuppressWarnings("rawtypes") +public class EvtEntityDamage extends SkriptEvent { + + public static void register(SyntaxRegistry syntaxRegistry) { + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(EvtEntityDamage.class, "Entity Damage") + .supplier(EvtEntityDamage::new) + .addEvent(EntityDamageEvent.class) + .addPatterns("damag(e|ing) [of:of %-entitydata%] [by:by %-entitydata%]") + .addDescription(""" + Called when an entity receives damage, e.g. by an attack from another entity, lava, fire, drowning, fall, suffocation, etc. + See attacker/victim/ for how to get the victim or attacker in this event. + """) + .addExample(""" + on damage of player by player: + send "Send you are being attacked.. defend yourself!" to victim + send "You better win this fight.." to attacker + """) + .addExample(""" + on damage of bee: + broadcast "A poor bee was just damaged :(" + if attacker is a player: + send "You monster.." to attacker + """) + .addSince("1.0, 2.7 (by entity)") + .build()); + } + + private EntityData[] byEntityData; + private EntityData[] ofEntityData; + + @Override + @SuppressWarnings("unchecked") + public boolean init(Literal[] args, int matchedPattern, SkriptParser.ParseResult parseResult) { + if (parseResult.hasTag("by")) { + Literal entityLiteral = (Literal) args[1]; + byEntityData = entityLiteral.getArray(); + } + if (parseResult.hasTag("of")) { + Literal entityLiteral = (Literal) args[0]; + ofEntityData = entityLiteral.getArray(); + } + return true; + } + + @Override + public boolean check(Event event) { + EntityDamageEvent entityDamageEvent = (EntityDamageEvent) event; + + if (event instanceof EntityDamageByEntityEvent entityEvent) { + if (byEntityData != null) { + boolean matched = false; + for (EntityData value : byEntityData) { + if (value.isInstance(entityEvent.getDamager())) + matched = true; + } + if (!matched) + return false; + } + } else if (byEntityData != null) { + return false; + } + + if (ofEntityData != null) { + boolean matched = false; + for (EntityData value : ofEntityData) { + if (value.isInstance(entityDamageEvent.getEntity())) + matched = true; + } + if (!matched) + return false; + } + + return !(entityDamageEvent.getEntity() instanceof LivingEntity entity) || !(HealthUtils.getHealth(entity) <= 0); + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return new SyntaxStringBuilder(event, debug) + .append("damage") + .appendIf(ofEntityData != null, "of", ofEntityData) + .appendIf(byEntityData != null, "by", byEntityData) + .toString(); + } + +} diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDeath.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDeath.java new file mode 100644 index 00000000000..37d79739a40 --- /dev/null +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDeath.java @@ -0,0 +1,79 @@ +package org.skriptlang.skript.bukkit.entity.elements.events; + +import ch.njol.skript.Skript; +import ch.njol.skript.entity.EntityData; +import ch.njol.skript.lang.Literal; +import ch.njol.skript.lang.SkriptEvent; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.lang.SyntaxStringBuilder; +import ch.njol.skript.log.ErrorQuality; +import org.bukkit.entity.LivingEntity; +import org.bukkit.event.Event; +import org.bukkit.event.entity.EntityDeathEvent; +import org.jetbrains.annotations.Nullable; +import org.skriptlang.skript.bukkit.registration.BukkitSyntaxInfos; +import org.skriptlang.skript.registration.SyntaxRegistry; + +@SuppressWarnings("rawtypes") +public class EvtEntityDeath extends SkriptEvent { + + public static void register(SyntaxRegistry syntaxRegistry) { + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(EvtEntityDeath.class, "Entity Death") + .supplier(EvtEntityDeath::new) + .addEvent(EntityDeathEvent.class) + .addPatterns("death [entity:of %-entitydatas%]") + .addDescription(""" + Called when a living entity (including players) dies. + See attacker/victim/ for how to get the victim or attacker in this event. + """) + .addExample(""" + on death of player: + send "You died.. tragic" to victim + send "Nice kill.. did you get any loot?" to attacker + """) + .addExample(""" + on death of a wither or ender dragon: + broadcast "A great boss has been slain today.." + """) + .addSince("1.0") + .build()); + } + + private EntityData[] entityData; + + @Override + @SuppressWarnings("unchecked") + public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { + if (parseResult.hasTag("entity")) { + Literal entityLiteral = (Literal) args[0]; + entityData = entityLiteral.getArray(); + for (EntityData value : entityData) { + if (!LivingEntity.class.isAssignableFrom(value.getType())) { + Skript.error("The death event only works for living entities", ErrorQuality.SEMANTIC_ERROR); + return false; + } + } + } + return true; + } + + @Override + public boolean check(Event event) { + if (entityData != null) { + EntityDeathEvent entityEvent = (EntityDeathEvent) event; + for (EntityData value : entityData) { + return value.getType().isInstance(entityEvent.getEntityType()); + } + } + return true; + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return new SyntaxStringBuilder(event, debug) + .append("death") + .appendIf(entityData != null, "of", entityData) + .toString(); + } + +} diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityShootBow.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityShootBow.java new file mode 100644 index 00000000000..9016a5bce1e --- /dev/null +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityShootBow.java @@ -0,0 +1,99 @@ +package org.skriptlang.skript.bukkit.entity.elements.events; + +import ch.njol.skript.classes.Changer.ChangeMode; +import ch.njol.skript.entity.EntityData; +import ch.njol.skript.lang.Literal; +import ch.njol.skript.lang.SkriptEvent; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.lang.SyntaxStringBuilder; +import ch.njol.skript.util.slot.EquipmentSlot; +import ch.njol.skript.util.slot.Slot; +import org.bukkit.entity.Entity; +import org.bukkit.event.Event; +import org.bukkit.event.entity.EntityShootBowEvent; +import org.bukkit.inventory.EntityEquipment; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.Nullable; +import org.skriptlang.skript.bukkit.lang.eventvalue.EventValue; +import org.skriptlang.skript.bukkit.lang.eventvalue.EventValueRegistry; +import org.skriptlang.skript.bukkit.registration.BukkitSyntaxInfos; +import org.skriptlang.skript.registration.SyntaxRegistry; + +@SuppressWarnings("rawtypes") +public class EvtEntityShootBow extends SkriptEvent { + + public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry eventValueRegistry) { + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(EvtEntityShootBow.class, "Entity Shoot Bow") + .supplier(EvtEntityShootBow::new) + .addEvent(EntityShootBowEvent.class) + .addPatterns("%entitydatas% shoot[ing] (bow|projectile)") + .addDescription(""" + Called when an entity shoots something from a bow. + event-entity refers to the shot projectile/entity. + """) + .addExample(""" + on player shoot bow: + chance of 30%: + damage event-slot by 10 + send "Your bow has taken increased damage!" to shooter + """) + .addExample(""" + on stray shooting bow: + spawn a cow at event-entity: + set velocity of entity to velocity of event-entity + set {_e} to entity + set event-entity to {_e} + """) + .addSince("2.11") + .build()); + + eventValueRegistry.register(EventValue.builder(EntityShootBowEvent.class, Entity.class) + .getter(EntityShootBowEvent::getProjectile) + .registerChanger(ChangeMode.SET, EntityShootBowEvent::setProjectile) + .build()); + + eventValueRegistry.register(EventValue.builder(EntityShootBowEvent.class, Slot.class) + .getter(event -> { + EntityEquipment equipment = event.getEntity().getEquipment(); + if (equipment == null) + return null; + return new EquipmentSlot(equipment, event.getHand()); + }) + .build()); + + eventValueRegistry.register(EventValue.builder(EntityShootBowEvent.class, ItemStack.class) + .getter(EntityShootBowEvent::getBow) + .build()); + } + + private EntityData[] entityData; + + @Override + @SuppressWarnings("unchecked") + public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { + if (parseResult.hasTag("entity")) { + Literal entityLiteral = (Literal) args[0]; + entityData = entityLiteral.getArray(); + } + return true; + } + + @Override + public boolean check(Event event) { + if (entityData != null) { + EntityShootBowEvent entityEvent = (EntityShootBowEvent) event; + for (EntityData entity : entityData) + return entity.isInstance(entityEvent.getEntity()); + } + return true; + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return new SyntaxStringBuilder(event, debug) + .append(entityData != null ? entityData : "entity") + .append("shooting projectile") + .toString(); + } + +} diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntitySpawn.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntitySpawn.java new file mode 100644 index 00000000000..cd882b52fcb --- /dev/null +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntitySpawn.java @@ -0,0 +1,78 @@ +package org.skriptlang.skript.bukkit.entity.elements.events; + +import ch.njol.skript.Skript; +import ch.njol.skript.entity.EntityData; +import ch.njol.skript.lang.Literal; +import ch.njol.skript.lang.SkriptEvent; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.lang.SyntaxStringBuilder; +import ch.njol.skript.log.ErrorQuality; +import org.bukkit.entity.HumanEntity; +import org.bukkit.event.Event; +import org.bukkit.event.entity.EntitySpawnEvent; +import org.jetbrains.annotations.Nullable; +import org.skriptlang.skript.bukkit.registration.BukkitSyntaxInfos; +import org.skriptlang.skript.registration.SyntaxRegistry; + +@SuppressWarnings("rawtypes") +public class EvtEntitySpawn extends SkriptEvent { + + public static void register(SyntaxRegistry syntaxRegistry) { + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(EvtEntitySpawn.class, "Entity Spawn") + .supplier(EvtEntitySpawn::new) + .addEvent(EntitySpawnEvent.class) + .addPatterns("spawn[ing] [entity:of %-entitydatas%]") + .addDescription("Called when an entity spawns (excluding players).") + .addExample(""" + on spawn of a zombie: + chance of 5%: + set scale attribute of event-entity to 3 + broadcast "A mega zombie has spawned!" + """) + .addExample(""" + on spawn of an ender dragon: + loop all players in radius 120 of event-entity: + send "A great beast has been seen near you.." to loop-value + """) + .addSince("1.0, 2.5.1 (non-living entities)") + .build()); + } + + private EntityData[] entityData; + + @Override + @SuppressWarnings("unchecked") + public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { + if (parseResult.hasTag("entity")) { + Literal entityLiteral = (Literal) args[0]; + entityData = entityLiteral.getArray(); + for (EntityData value : entityData) { + if (HumanEntity.class.isAssignableFrom(value.getType())) { + Skript.error("The spawn event does not work for human entities", ErrorQuality.SEMANTIC_ERROR); + return false; + } + } + } + return true; + } + + @Override + public boolean check(Event event) { + if (entityData != null) { + EntitySpawnEvent entityEvent = (EntitySpawnEvent) event; + for (EntityData value : entityData) { + return value.getType().isInstance(entityEvent.getEntityType()); + } + } + return true; + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return new SyntaxStringBuilder(event, debug) + .append("spawn") + .appendIf(entityData != null, "of", entityData) + .toString(); + } + +} diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTarget.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTarget.java new file mode 100644 index 00000000000..ee0ae715b60 --- /dev/null +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTarget.java @@ -0,0 +1,86 @@ +package org.skriptlang.skript.bukkit.entity.elements.events; + + +import ch.njol.skript.entity.EntityData; +import ch.njol.skript.lang.Literal; +import ch.njol.skript.lang.SkriptEvent; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.lang.SyntaxStringBuilder; +import org.bukkit.event.Event; +import org.bukkit.event.entity.EntityBreakDoorEvent; +import org.bukkit.event.entity.EntityTargetEvent; +import org.jetbrains.annotations.Nullable; +import org.skriptlang.skript.bukkit.registration.BukkitSyntaxInfos; +import org.skriptlang.skript.registration.SyntaxRegistry; +/* +public class EvtEntityTarget extends SkriptEvent { + static { + Skript.registerEvent("Target", EvtEntityTarget.class, EntityTargetEvent.class, "[entity] target", "[entity] un[-]target") + .description("Called when a mob starts/stops following/attacking another entity, usually a player.") + .examples("on entity target:", + "\ttarget is a player") + .since("1.0"); + } + + private boolean target; + + @Override + public boolean init(final Literal[] args, final int matchedPattern, final ParseResult parser) { + target = matchedPattern == 0; + return true; + } + + @Override + public boolean check(final Event e) { + return ((EntityTargetEvent) e).getTarget() == null ^ target; + } + + @Override + public String toString(final @Nullable Event e, final boolean debug) { + return "entity " + (target ? "" : "un") + "target"; + } + +} + */ + +@SuppressWarnings("rawtypes") +public class EvtEntityTarget extends SkriptEvent { + + public static void register(SyntaxRegistry syntaxRegistry) { + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(EvtEntityTarget.class, "Entity Target") + .supplier(EvtEntityTarget::new) + .addEvent(EntityTargetEvent.class) + .addPatterns("[entity] target", "[entity] un[-]target") + .addDescription(""" + Called when a mob starts/stops following/attacking another entity, usually a player. + See target. for how to get the entity being targeted. + """) + .addExample(""" + + """) + .addSince("1.0, INSERT VERSION (entity data in pattern support)") + .build()); + } + + private boolean target; + + @Override + public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { + return true; + } + + @Override + public boolean check(Event event) { + EntityTargetEvent entityEvent = (EntityTargetEvent) event; + return target == (entityEvent.getEntity() != null); + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return new SyntaxStringBuilder(event, debug) + .append(entityData != null ? entityData : "entity") + .append("breaking a wooden door") + .toString(); + } + +} From d78e01be88448785cff80f9d26b2f5dcc52fc4ab Mon Sep 17 00:00:00 2001 From: OwlBe Date: Sat, 27 Jun 2026 05:20:38 -0400 Subject: [PATCH 05/35] more random stuff --- .../classes/data/BukkitEventValues.java | 16 ---- .../njol/skript/events/EvtEntityTarget.java | 42 -------- .../skript/events/EvtEntityTransform.java | 61 ------------ .../skript/bukkit/entity/EntityModule.java | 3 + .../events/EvtEntityBlockChange.java | 75 ++++++++++----- .../elements/events/EvtEntityBreakDoor.java | 7 +- .../elements/events/EvtEntityDamage.java | 37 +++---- .../elements/events/EvtEntityDeath.java | 6 +- .../elements/events/EvtEntityShootBow.java | 5 +- .../elements/events/EvtEntitySpawn.java | 6 +- .../elements/events/EvtEntityTarget.java | 43 ++------- .../elements/events/EvtEntityTransform.java | 96 +++++++++++++++++++ 12 files changed, 185 insertions(+), 212 deletions(-) delete mode 100644 src/main/java/ch/njol/skript/events/EvtEntityTarget.java delete mode 100644 src/main/java/ch/njol/skript/events/EvtEntityTransform.java rename src/main/java/{ch/njol/skript => org/skriptlang/skript/bukkit/entity/elements}/events/EvtEntityBlockChange.java (54%) create mode 100644 src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTransform.java 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 ee9f4fbe945..ef50050518d 100644 --- a/src/main/java/ch/njol/skript/classes/data/BukkitEventValues.java +++ b/src/main/java/ch/njol/skript/classes/data/BukkitEventValues.java @@ -268,18 +268,6 @@ public static void register(EventValueRegistry registry) { // EntityTameEvent registry.register(EventValue.simple(EntityTameEvent.class, Entity.class, EntityTameEvent::getEntity)); - // EntityChangeBlockEvent - registry.register(EventValue.builder(EntityChangeBlockEvent.class, Block.class) - .getter(EntityChangeBlockEvent::getBlock) - .time(Time.PAST) - .build()); - registry.register(EventValue.simple(EntityChangeBlockEvent.class, Block.class, EntityChangeBlockEvent::getBlock)); - registry.register(EventValue.simple(EntityChangeBlockEvent.class, BlockData.class, EntityChangeBlockEvent::getBlockData)); - registry.register(EventValue.builder(EntityChangeBlockEvent.class, BlockData.class) - .getter(EntityChangeBlockEvent::getBlockData) - .time(Time.FUTURE) - .build()); - // AreaEffectCloudApplyEvent registry.register(EventValue.simple(AreaEffectCloudApplyEvent.class, LivingEntity[].class, event -> event.getAffectedEntities().toArray(new LivingEntity[0]))); registry.register(EventValue.simple(AreaEffectCloudApplyEvent.class, PotionEffectType.class, new Converter<>() { @@ -717,10 +705,6 @@ else if (hand == EquipmentSlot.OFF_HAND) if (Skript.classExists("io.papermc.paper.event.player.PlayerStonecutterRecipeSelectEvent")) registry.register(EventValue.simple(PlayerStonecutterRecipeSelectEvent.class, ItemStack.class, event -> event.getStonecuttingRecipe().getResult())); - // EntityTransformEvent - registry.register(EventValue.simple(EntityTransformEvent.class, Entity[].class, event -> event.getTransformedEntities().stream().toArray(Entity[]::new))); - registry.register(EventValue.simple(EntityTransformEvent.class, TransformReason.class, EntityTransformEvent::getTransformReason)); - // BellRingEvent - these are BlockEvents and not EntityEvents, so they have declared methods for getEntity() if (Skript.classExists("org.bukkit.event.block.BellRingEvent")) { registry.register(EventValue.simple(BellRingEvent.class, Entity.class, BellRingEvent::getEntity)); diff --git a/src/main/java/ch/njol/skript/events/EvtEntityTarget.java b/src/main/java/ch/njol/skript/events/EvtEntityTarget.java deleted file mode 100644 index 10fb2ddfdba..00000000000 --- a/src/main/java/ch/njol/skript/events/EvtEntityTarget.java +++ /dev/null @@ -1,42 +0,0 @@ -package ch.njol.skript.events; - -import org.bukkit.event.Event; -import org.bukkit.event.entity.EntityTargetEvent; -import org.jetbrains.annotations.Nullable; - -import ch.njol.skript.Skript; -import ch.njol.skript.lang.Literal; -import ch.njol.skript.lang.SkriptEvent; -import ch.njol.skript.lang.SkriptParser.ParseResult; - -/** - * @author Peter Güttinger - */ -public class EvtEntityTarget extends SkriptEvent { - static { - Skript.registerEvent("Target", EvtEntityTarget.class, EntityTargetEvent.class, "[entity] target", "[entity] un[-]target") - .description("Called when a mob starts/stops following/attacking another entity, usually a player.") - .examples("on entity target:", - "\ttarget is a player") - .since("1.0"); - } - - private boolean target; - - @Override - public boolean init(final Literal[] args, final int matchedPattern, final ParseResult parser) { - target = matchedPattern == 0; - return true; - } - - @Override - public boolean check(final Event e) { - return ((EntityTargetEvent) e).getTarget() == null ^ target; - } - - @Override - public String toString(final @Nullable Event e, final boolean debug) { - return "entity " + (target ? "" : "un") + "target"; - } - -} diff --git a/src/main/java/ch/njol/skript/events/EvtEntityTransform.java b/src/main/java/ch/njol/skript/events/EvtEntityTransform.java deleted file mode 100644 index 18a8b137eba..00000000000 --- a/src/main/java/ch/njol/skript/events/EvtEntityTransform.java +++ /dev/null @@ -1,61 +0,0 @@ -package ch.njol.skript.events; - -import org.bukkit.event.Event; -import org.bukkit.event.entity.EntityTransformEvent; -import org.bukkit.event.entity.EntityTransformEvent.TransformReason; -import org.jetbrains.annotations.Nullable; - -import ch.njol.skript.Skript; -import ch.njol.skript.entity.EntityData; -import ch.njol.skript.lang.Literal; -import ch.njol.skript.lang.SkriptEvent; -import ch.njol.skript.lang.SkriptParser.ParseResult; - -public class EvtEntityTransform extends SkriptEvent { - - static { - Skript.registerEvent("Entity Transform", EvtEntityTransform.class, EntityTransformEvent.class, "(entit(y|ies)|%*-entitydatas%) transform[ing] [due to %-transformreasons%]") - .description("Called when an entity is about to be replaced by another entity.", - "Examples when it's called include; when a zombie gets cured and a villager spawns, " + - "an entity drowns in water like a zombie that turns to a drown, " + - "an entity that gets frozen in powder snow, " + - "a mooshroom that when sheared, spawns a new cow.") - .examples("on a zombie transforming due to curing:", "on mooshroom transforming:", "on zombie, skeleton or slime transform:") - .keywords("entity transform") - .since("2.8.0"); - } - - @Nullable - private Literal reasons; - - @Nullable - private Literal> datas; - - @Override - @SuppressWarnings("unchecked") - public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { - datas = (Literal>) args[0]; - reasons = (Literal) args[1]; - return true; - } - - @Override - public boolean check(Event event) { - if (!(event instanceof EntityTransformEvent)) - return false; - EntityTransformEvent transformEvent = (EntityTransformEvent) event; - if (reasons != null && !reasons.check(event, reason -> transformEvent.getTransformReason().equals(reason))) - return false; - if (datas != null && !datas.check(event, data -> data.isInstance(transformEvent.getEntity()))) - return false; - return true; - } - - @Override - public String toString(@Nullable Event event, boolean debug) { - if (datas == null) - return "entities transforming" + (reasons == null ? "" : " due to " + reasons.toString(event, debug)); - return datas.toString(event, debug) + " transforming" + (reasons == null ? "" : " due to " + reasons.toString(event, debug)); - } - -} diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/EntityModule.java b/src/main/java/org/skriptlang/skript/bukkit/entity/EntityModule.java index 8bf6acfd59f..3bea5dccf0e 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/EntityModule.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/EntityModule.java @@ -49,11 +49,14 @@ protected void loadSelf(SkriptAddon addon) { EntityEvents.register(syntaxRegistry, eventValueRegistry); + EvtEntityBlockChange.register(syntaxRegistry, eventValueRegistry); EvtEntityBreakDoor.register(syntaxRegistry); EvtEntityDamage.register(syntaxRegistry); EvtEntityDeath.register(syntaxRegistry); EvtEntityShootBow.register(syntaxRegistry, eventValueRegistry); EvtEntitySpawn.register(syntaxRegistry); + EvtEntityTarget.register(syntaxRegistry); + EvtEntityTransform.register(syntaxRegistry, eventValueRegistry); } diff --git a/src/main/java/ch/njol/skript/events/EvtEntityBlockChange.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBlockChange.java similarity index 54% rename from src/main/java/ch/njol/skript/events/EvtEntityBlockChange.java rename to src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBlockChange.java index fa749354f1b..c09994b3137 100644 --- a/src/main/java/ch/njol/skript/events/EvtEntityBlockChange.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBlockChange.java @@ -1,12 +1,13 @@ -package ch.njol.skript.events; +package org.skriptlang.skript.bukkit.entity.elements.events; -import ch.njol.skript.Skript; import ch.njol.skript.bukkitutil.ItemUtils; import ch.njol.skript.entity.EntityData; import ch.njol.skript.lang.Literal; import ch.njol.skript.lang.SkriptEvent; import ch.njol.skript.lang.SkriptParser.ParseResult; - +import ch.njol.skript.lang.SyntaxStringBuilder; +import org.bukkit.block.Block; +import org.bukkit.block.data.BlockData; import org.bukkit.entity.Enderman; import org.bukkit.entity.FallingBlock; import org.bukkit.entity.Sheep; @@ -14,31 +15,59 @@ import org.bukkit.event.Event; import org.bukkit.event.entity.EntityChangeBlockEvent; import org.jetbrains.annotations.Nullable; +import org.skriptlang.skript.bukkit.lang.eventvalue.EventValue; +import org.skriptlang.skript.bukkit.lang.eventvalue.EventValue.Time; +import org.skriptlang.skript.bukkit.lang.eventvalue.EventValueRegistry; +import org.skriptlang.skript.bukkit.registration.BukkitSyntaxInfos; +import org.skriptlang.skript.registration.SyntaxRegistry; -import java.util.Locale; import java.util.function.Predicate; public class EvtEntityBlockChange extends SkriptEvent { - static { - Skript.registerEvent("Enderman/Sheep/Silverfish/Falling Block", EvtEntityBlockChange.class, EntityChangeBlockEvent.class, ChangeEvent.patterns) - .description( - "Called when an enderman places or picks up a block, a sheep eats grass, " + - "a silverfish boops into/out of a block or a falling block lands and turns into a block respectively.", - "event-block represents the old block and event-blockdata represents the new replacement that'll be applied to the block." - ) - .examples( - "on sheep eat:", - "\tkill event-entity", - "\tbroadcast \"A sheep stole some grass!\"", - "", - "on falling block land:", - "\tevent-entity is a falling dirt", - "\tcancel event" - ) - .since("unknown, 2.5.2 (falling block), 2.8.0 (any entity support)"); + public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry eventValueRegistry) { + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(EvtEntityBlockChange.class, "Entity Change Block") + .supplier(EvtEntityBlockChange::new) + .addEvent(EntityChangeBlockEvent.class) + .addPatterns(ChangeEvent.patterns) + .addDescription(""" + Called when an enderman places or picks up a block, a sheep eats grass,\s + a silverfish boops into/out of a block or a falling block lands and turns into a block respectively. + event-block represents the old block and event-blockdata represents the new replacement that will be applied to the block. + """) + .addExample(""" + on sheep eat: + kill event-entity + broadcast "A sheep stole some grass!" + """) + .addExample(""" + on falling block land: + event-entity is a falling dirt + cancel event + """) + .addSince("unknown, 2.5.2 (falling block), 2.8.0 (any entity support)") + .build()); + + eventValueRegistry.register(EventValue.builder(EntityChangeBlockEvent.class, Block.class) + .getter(EntityChangeBlockEvent::getBlock) + .time(Time.PAST) + .build()); + + eventValueRegistry.register(EventValue.builder(EntityChangeBlockEvent.class, Block.class) + .getter(EntityChangeBlockEvent::getBlock) // why is there past event-block & event-block with both values?? + .build()); + + eventValueRegistry.register(EventValue.builder(EntityChangeBlockEvent.class, BlockData.class) + .getter(EntityChangeBlockEvent::getBlockData) + .time(Time.FUTURE) + .build()); + + eventValueRegistry.register(EventValue.builder(EntityChangeBlockEvent.class, Block.class) + .getter(EntityChangeBlockEvent::getBlock) + .build()); } + // this is pretty messy but was unsure of a way to really clean it up? private enum ChangeEvent { ENDERMAN_PLACE("enderman place", event -> event.getEntity() instanceof Enderman && !ItemUtils.isAir(event.getTo())), @@ -103,7 +132,9 @@ public boolean check(Event event) { @Override public String toString(@Nullable Event event, boolean debug) { - return this.event.name().toLowerCase(Locale.ENGLISH).replace('_', ' '); + return new SyntaxStringBuilder(event, debug) + .append(this.event.name()) + .toString(); } } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java index b1fefdbbcdb..ec9dc726510 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java @@ -11,6 +11,8 @@ import org.skriptlang.skript.bukkit.registration.BukkitSyntaxInfos; import org.skriptlang.skript.registration.SyntaxRegistry; +import java.util.Arrays; + @SuppressWarnings("rawtypes") public class EvtEntityBreakDoor extends SkriptEvent { @@ -18,7 +20,7 @@ public static void register(SyntaxRegistry syntaxRegistry) { syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(EvtEntityBreakDoor.class, "Entity Break Door") .supplier(EvtEntityBreakDoor::new) .addEvent(EntityBreakDoorEvent.class) - .addPatterns("[entity:%entitydata%] break[ing] [a] [wood[en]] door") + .addPatterns("[entity:%entitydatas%] break[ing] [a] [wood[en]] door") .addDescription(""" Called when an entity (usually a zombie) is breaking a door. Can be cancelled to prevent the entity from breaking the door. @@ -48,8 +50,7 @@ public boolean init(Literal[] args, int matchedPattern, ParseResult parseResu public boolean check(Event event) { if (entityData != null) { EntityBreakDoorEvent entityEvent = (EntityBreakDoorEvent) event; - for (EntityData entity : entityData) - return entity.isInstance(entityEvent.getEntity()); + return Arrays.stream(entityData).anyMatch(entity -> entity.isInstance(entityEvent.getEntity())); } return true; } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java index d2447199f59..20ea529b4d9 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java @@ -14,6 +14,8 @@ import org.skriptlang.skript.bukkit.registration.BukkitSyntaxInfos; import org.skriptlang.skript.registration.SyntaxRegistry; +import java.util.Arrays; + @SuppressWarnings("rawtypes") public class EvtEntityDamage extends SkriptEvent { @@ -61,32 +63,21 @@ public boolean init(Literal[] args, int matchedPattern, SkriptParser.ParseRes @Override public boolean check(Event event) { EntityDamageEvent entityDamageEvent = (EntityDamageEvent) event; + boolean damagerMatched = !(event instanceof EntityDamageByEntityEvent entityEvent) + ? byEntityData == null + : byEntityData == null + || Arrays.stream(byEntityData) + .anyMatch(data -> data.isInstance(entityEvent.getDamager())); - if (event instanceof EntityDamageByEntityEvent entityEvent) { - if (byEntityData != null) { - boolean matched = false; - for (EntityData value : byEntityData) { - if (value.isInstance(entityEvent.getDamager())) - matched = true; - } - if (!matched) - return false; - } - } else if (byEntityData != null) { - return false; - } + boolean entityMatched = ofEntityData == null + || Arrays.stream(ofEntityData) + .anyMatch(data -> data.isInstance(entityDamageEvent.getEntity())); - if (ofEntityData != null) { - boolean matched = false; - for (EntityData value : ofEntityData) { - if (value.isInstance(entityDamageEvent.getEntity())) - matched = true; - } - if (!matched) - return false; - } + boolean healthMatched = !(entityDamageEvent.getEntity() instanceof LivingEntity entity) + || !(HealthUtils.getHealth(entity) <= 0); + + return damagerMatched && entityMatched && healthMatched; - return !(entityDamageEvent.getEntity() instanceof LivingEntity entity) || !(HealthUtils.getHealth(entity) <= 0); } @Override diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDeath.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDeath.java index 37d79739a40..4f7441916c7 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDeath.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDeath.java @@ -14,6 +14,8 @@ import org.skriptlang.skript.bukkit.registration.BukkitSyntaxInfos; import org.skriptlang.skript.registration.SyntaxRegistry; +import java.util.Arrays; + @SuppressWarnings("rawtypes") public class EvtEntityDeath extends SkriptEvent { @@ -61,9 +63,7 @@ public boolean init(Literal[] args, int matchedPattern, ParseResult parseResu public boolean check(Event event) { if (entityData != null) { EntityDeathEvent entityEvent = (EntityDeathEvent) event; - for (EntityData value : entityData) { - return value.getType().isInstance(entityEvent.getEntityType()); - } + return Arrays.stream(entityData).anyMatch(entity -> entity.isInstance(entityEvent.getEntity())); } return true; } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityShootBow.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityShootBow.java index 9016a5bce1e..1e6eb1a3588 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityShootBow.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityShootBow.java @@ -19,6 +19,8 @@ import org.skriptlang.skript.bukkit.registration.BukkitSyntaxInfos; import org.skriptlang.skript.registration.SyntaxRegistry; +import java.util.Arrays; + @SuppressWarnings("rawtypes") public class EvtEntityShootBow extends SkriptEvent { @@ -82,8 +84,7 @@ public boolean init(Literal[] args, int matchedPattern, ParseResult parseResu public boolean check(Event event) { if (entityData != null) { EntityShootBowEvent entityEvent = (EntityShootBowEvent) event; - for (EntityData entity : entityData) - return entity.isInstance(entityEvent.getEntity()); + return Arrays.stream(entityData).anyMatch(entity -> entity.isInstance(entityEvent.getEntity())); } return true; } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntitySpawn.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntitySpawn.java index cd882b52fcb..9804dcfcc59 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntitySpawn.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntitySpawn.java @@ -14,6 +14,8 @@ import org.skriptlang.skript.bukkit.registration.BukkitSyntaxInfos; import org.skriptlang.skript.registration.SyntaxRegistry; +import java.util.Arrays; + @SuppressWarnings("rawtypes") public class EvtEntitySpawn extends SkriptEvent { @@ -60,9 +62,7 @@ public boolean init(Literal[] args, int matchedPattern, ParseResult parseResu public boolean check(Event event) { if (entityData != null) { EntitySpawnEvent entityEvent = (EntitySpawnEvent) event; - for (EntityData value : entityData) { - return value.getType().isInstance(entityEvent.getEntityType()); - } + return Arrays.stream(entityData).anyMatch(entity -> entity.isInstance(entityEvent.getEntity())); } return true; } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTarget.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTarget.java index ee0ae715b60..b590e1b283e 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTarget.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTarget.java @@ -1,49 +1,16 @@ package org.skriptlang.skript.bukkit.entity.elements.events; -import ch.njol.skript.entity.EntityData; import ch.njol.skript.lang.Literal; import ch.njol.skript.lang.SkriptEvent; import ch.njol.skript.lang.SkriptParser.ParseResult; import ch.njol.skript.lang.SyntaxStringBuilder; import org.bukkit.event.Event; -import org.bukkit.event.entity.EntityBreakDoorEvent; import org.bukkit.event.entity.EntityTargetEvent; import org.jetbrains.annotations.Nullable; import org.skriptlang.skript.bukkit.registration.BukkitSyntaxInfos; import org.skriptlang.skript.registration.SyntaxRegistry; -/* -public class EvtEntityTarget extends SkriptEvent { - static { - Skript.registerEvent("Target", EvtEntityTarget.class, EntityTargetEvent.class, "[entity] target", "[entity] un[-]target") - .description("Called when a mob starts/stops following/attacking another entity, usually a player.") - .examples("on entity target:", - "\ttarget is a player") - .since("1.0"); - } - - private boolean target; - - @Override - public boolean init(final Literal[] args, final int matchedPattern, final ParseResult parser) { - target = matchedPattern == 0; - return true; - } - @Override - public boolean check(final Event e) { - return ((EntityTargetEvent) e).getTarget() == null ^ target; - } - - @Override - public String toString(final @Nullable Event e, final boolean debug) { - return "entity " + (target ? "" : "un") + "target"; - } - -} - */ - -@SuppressWarnings("rawtypes") public class EvtEntityTarget extends SkriptEvent { public static void register(SyntaxRegistry syntaxRegistry) { @@ -58,7 +25,7 @@ public static void register(SyntaxRegistry syntaxRegistry) { .addExample(""" """) - .addSince("1.0, INSERT VERSION (entity data in pattern support)") + .addSince("1.0") .build()); } @@ -66,20 +33,22 @@ public static void register(SyntaxRegistry syntaxRegistry) { @Override public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { + target = matchedPattern == 0; return true; } @Override public boolean check(Event event) { EntityTargetEvent entityEvent = (EntityTargetEvent) event; - return target == (entityEvent.getEntity() != null); + return target == (entityEvent.getTarget() != null); } @Override public String toString(@Nullable Event event, boolean debug) { return new SyntaxStringBuilder(event, debug) - .append(entityData != null ? entityData : "entity") - .append("breaking a wooden door") + .append("entity") + .appendIf(!target,"un") + .append("target") .toString(); } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTransform.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTransform.java new file mode 100644 index 00000000000..4752478de86 --- /dev/null +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTransform.java @@ -0,0 +1,96 @@ +package org.skriptlang.skript.bukkit.entity.elements.events; + +import ch.njol.skript.entity.EntityData; +import ch.njol.skript.lang.Literal; +import ch.njol.skript.lang.SkriptEvent; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.lang.SyntaxStringBuilder; +import org.bukkit.entity.Entity; +import org.bukkit.event.Event; +import org.bukkit.event.entity.EntityTransformEvent; +import org.bukkit.event.entity.EntityTransformEvent.TransformReason; +import org.jetbrains.annotations.Nullable; +import org.skriptlang.skript.bukkit.lang.eventvalue.EventValue; +import org.skriptlang.skript.bukkit.lang.eventvalue.EventValueRegistry; +import org.skriptlang.skript.bukkit.registration.BukkitSyntaxInfos; +import org.skriptlang.skript.registration.SyntaxRegistry; + +import java.util.Arrays; + +@SuppressWarnings("rawtypes") +public class EvtEntityTransform extends SkriptEvent { + + public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry eventValueRegistry) { + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(EvtEntityTransform.class, "Entity Transform") + .supplier(EvtEntityTransform::new) + .addEvent(EntityTransformEvent.class) + .addPatterns("[entity:%*-entitydatas%] transform[ing] [transform: due to %-transformreasons%]") + .addDescription(""" + Called when an entity is about to be replaced by another entity. + e.g. when a zombie gets cured and a villager spawns,\s + an entity drowns in water like a zombie that turns to a drown,\s + an entity that gets frozen in powder snow,\s + a mooshroom that when sheared, spawns a new cow. + """) + .addExample(""" + on a zombie transforming due to curing: + broadcast "Another one cured from this madness.." + """) + .addExample(""" + on mooshroom transforming: + cancel event + broadcast "forever a mooshroom!" + """) + .addSince("2.8.0") + .build()); + + eventValueRegistry.register(EventValue.builder(EntityTransformEvent.class, Entity[].class) + .getter(event -> event.getTransformedEntities().toArray(Entity[]::new)) + .build()); + + eventValueRegistry.register(EventValue.builder(EntityTransformEvent.class, TransformReason.class) + .getter(EntityTransformEvent::getTransformReason) + .build()); + } + + private EntityData[] entityData; + private TransformReason[] reasons; + + @Override + @SuppressWarnings("unchecked") + public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { + if (parseResult.hasTag("transform")) { + Literal transformLiteral = (Literal) args[1]; + reasons = transformLiteral.getArray(); + } + if (parseResult.hasTag("entity")) { + Literal entityLiteral = (Literal) args[0]; + entityData = entityLiteral.getArray(); + } + return true; + } + + @Override + public boolean check(Event event) { + EntityTransformEvent entityEvent = (EntityTransformEvent) event; + boolean reasonMatched = reasons == null + || Arrays.stream(reasons) + .anyMatch(reason -> reason == entityEvent.getTransformReason()); + + boolean entityDataMatched = entityData == null + || Arrays.stream(entityData) + .anyMatch(data -> data.isInstance(entityEvent.getEntity())); + + return reasonMatched && entityDataMatched; + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return new SyntaxStringBuilder(event, debug) + .append(entityData != null ? entityData : "entity") + .append("transforming") + .appendIf(reasons != null, "due to", reasons) + .toString(); + } + +} From 30d8ead4296899a9c203cd5a6124a2f096a2c465 Mon Sep 17 00:00:00 2001 From: OwlBe Date: Sun, 28 Jun 2026 02:16:28 -0400 Subject: [PATCH 06/35] push before switching branches --- .../elements/events/EvtEntityBlockChange.java | 6 ++--- .../elements/events/EvtEntityBreakDoor.java | 5 ++-- .../elements/events/EvtEntityDamage.java | 27 +++++++------------ .../elements/events/EvtEntityDeath.java | 7 +++-- .../elements/events/EvtEntityShootBow.java | 5 ++-- .../elements/events/EvtEntitySpawn.java | 7 +++-- .../elements/events/EvtEntityTransform.java | 15 +++-------- 7 files changed, 26 insertions(+), 46 deletions(-) diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBlockChange.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBlockChange.java index c09994b3137..2de07a0db70 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBlockChange.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBlockChange.java @@ -107,7 +107,7 @@ private enum ChangeEvent { } @Nullable - private Literal> datas; + private Literal> entityData; private ChangeEvent event; @Override @@ -115,7 +115,7 @@ private enum ChangeEvent { public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { event = ChangeEvent.values()[matchedPattern]; if (event == ChangeEvent.GENERIC) - datas = (Literal>) args[0]; + entityData = (Literal>) args[0]; return true; } @@ -123,7 +123,7 @@ public boolean init(Literal[] args, int matchedPattern, ParseResult parseResu public boolean check(Event event) { if (!(event instanceof EntityChangeBlockEvent)) return false; - if (datas != null && !datas.check(event, data -> data.isInstance(((EntityChangeBlockEvent) event).getEntity()))) + if (entityData != null && !entityData.check(event, data -> data.isInstance(((EntityChangeBlockEvent) event).getEntity()))) return false; if (this.event.checker == null) return true; diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java index ec9dc726510..67fb00f4c44 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java @@ -13,7 +13,6 @@ import java.util.Arrays; -@SuppressWarnings("rawtypes") public class EvtEntityBreakDoor extends SkriptEvent { public static void register(SyntaxRegistry syntaxRegistry) { @@ -34,13 +33,13 @@ Called when an entity (usually a zombie) is breaking a door. .build()); } - private EntityData[] entityData; + private EntityData[] entityData; @Override @SuppressWarnings("unchecked") public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { if (parseResult.hasTag("entity")) { - Literal entityLiteral = (Literal) args[0]; + Literal> entityLiteral = (Literal>) args[0]; entityData = entityLiteral.getArray(); } return true; diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java index 20ea529b4d9..08dac1042da 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java @@ -16,7 +16,6 @@ import java.util.Arrays; -@SuppressWarnings("rawtypes") public class EvtEntityDamage extends SkriptEvent { public static void register(SyntaxRegistry syntaxRegistry) { @@ -43,18 +42,18 @@ public static void register(SyntaxRegistry syntaxRegistry) { .build()); } - private EntityData[] byEntityData; - private EntityData[] ofEntityData; + private EntityData[] byEntityData; + private EntityData[] ofEntityData; @Override @SuppressWarnings("unchecked") public boolean init(Literal[] args, int matchedPattern, SkriptParser.ParseResult parseResult) { if (parseResult.hasTag("by")) { - Literal entityLiteral = (Literal) args[1]; + Literal> entityLiteral = (Literal>) args[1]; byEntityData = entityLiteral.getArray(); } if (parseResult.hasTag("of")) { - Literal entityLiteral = (Literal) args[0]; + Literal> entityLiteral = (Literal>) args[0]; ofEntityData = entityLiteral.getArray(); } return true; @@ -63,19 +62,11 @@ public boolean init(Literal[] args, int matchedPattern, SkriptParser.ParseRes @Override public boolean check(Event event) { EntityDamageEvent entityDamageEvent = (EntityDamageEvent) event; - boolean damagerMatched = !(event instanceof EntityDamageByEntityEvent entityEvent) - ? byEntityData == null - : byEntityData == null - || Arrays.stream(byEntityData) - .anyMatch(data -> data.isInstance(entityEvent.getDamager())); - - boolean entityMatched = ofEntityData == null - || Arrays.stream(ofEntityData) - .anyMatch(data -> data.isInstance(entityDamageEvent.getEntity())); - - boolean healthMatched = !(entityDamageEvent.getEntity() instanceof LivingEntity entity) - || !(HealthUtils.getHealth(entity) <= 0); - + boolean entityMatched = ofEntityData == null || Arrays.stream(ofEntityData).anyMatch(data -> data.isInstance(entityDamageEvent.getEntity())); + boolean healthMatched = !(entityDamageEvent.getEntity() instanceof LivingEntity entity) || HealthUtils.getHealth(entity) > 0; + if (!(event instanceof EntityDamageByEntityEvent entityEvent)) + return byEntityData == null && entityMatched && healthMatched; + boolean damagerMatched = byEntityData == null || Arrays.stream(byEntityData).anyMatch(data -> data.isInstance(entityEvent.getDamager())); return damagerMatched && entityMatched && healthMatched; } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDeath.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDeath.java index 4f7441916c7..1dfa17aabde 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDeath.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDeath.java @@ -16,7 +16,6 @@ import java.util.Arrays; -@SuppressWarnings("rawtypes") public class EvtEntityDeath extends SkriptEvent { public static void register(SyntaxRegistry syntaxRegistry) { @@ -41,15 +40,15 @@ Called when a living entity (including players) dies. .build()); } - private EntityData[] entityData; + private EntityData[] entityData; @Override @SuppressWarnings("unchecked") public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { if (parseResult.hasTag("entity")) { - Literal entityLiteral = (Literal) args[0]; + Literal> entityLiteral = (Literal>) args[0]; entityData = entityLiteral.getArray(); - for (EntityData value : entityData) { + for (EntityData value : entityData) { if (!LivingEntity.class.isAssignableFrom(value.getType())) { Skript.error("The death event only works for living entities", ErrorQuality.SEMANTIC_ERROR); return false; diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityShootBow.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityShootBow.java index 1e6eb1a3588..111ab7d5724 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityShootBow.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityShootBow.java @@ -21,7 +21,6 @@ import java.util.Arrays; -@SuppressWarnings("rawtypes") public class EvtEntityShootBow extends SkriptEvent { public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry eventValueRegistry) { @@ -68,13 +67,13 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev .build()); } - private EntityData[] entityData; + private EntityData[] entityData; @Override @SuppressWarnings("unchecked") public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { if (parseResult.hasTag("entity")) { - Literal entityLiteral = (Literal) args[0]; + Literal> entityLiteral = (Literal>) args[0]; entityData = entityLiteral.getArray(); } return true; diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntitySpawn.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntitySpawn.java index 9804dcfcc59..05b9d3bddb8 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntitySpawn.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntitySpawn.java @@ -16,7 +16,6 @@ import java.util.Arrays; -@SuppressWarnings("rawtypes") public class EvtEntitySpawn extends SkriptEvent { public static void register(SyntaxRegistry syntaxRegistry) { @@ -40,15 +39,15 @@ public static void register(SyntaxRegistry syntaxRegistry) { .build()); } - private EntityData[] entityData; + private EntityData[] entityData; @Override @SuppressWarnings("unchecked") public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { if (parseResult.hasTag("entity")) { - Literal entityLiteral = (Literal) args[0]; + Literal> entityLiteral = (Literal>) args[0]; entityData = entityLiteral.getArray(); - for (EntityData value : entityData) { + for (EntityData value : entityData) { if (HumanEntity.class.isAssignableFrom(value.getType())) { Skript.error("The spawn event does not work for human entities", ErrorQuality.SEMANTIC_ERROR); return false; diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTransform.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTransform.java index 4752478de86..0c123951a9a 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTransform.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTransform.java @@ -17,7 +17,6 @@ import java.util.Arrays; -@SuppressWarnings("rawtypes") public class EvtEntityTransform extends SkriptEvent { public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry eventValueRegistry) { @@ -53,7 +52,7 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev .build()); } - private EntityData[] entityData; + private EntityData[] entityData; private TransformReason[] reasons; @Override @@ -64,7 +63,7 @@ public boolean init(Literal[] args, int matchedPattern, ParseResult parseResu reasons = transformLiteral.getArray(); } if (parseResult.hasTag("entity")) { - Literal entityLiteral = (Literal) args[0]; + Literal> entityLiteral = (Literal>) args[0]; entityData = entityLiteral.getArray(); } return true; @@ -73,14 +72,8 @@ public boolean init(Literal[] args, int matchedPattern, ParseResult parseResu @Override public boolean check(Event event) { EntityTransformEvent entityEvent = (EntityTransformEvent) event; - boolean reasonMatched = reasons == null - || Arrays.stream(reasons) - .anyMatch(reason -> reason == entityEvent.getTransformReason()); - - boolean entityDataMatched = entityData == null - || Arrays.stream(entityData) - .anyMatch(data -> data.isInstance(entityEvent.getEntity())); - + boolean reasonMatched = reasons == null || Arrays.stream(reasons).anyMatch(reason -> reason == entityEvent.getTransformReason()); + boolean entityDataMatched = entityData == null || Arrays.stream(entityData).anyMatch(data -> data.isInstance(entityEvent.getEntity())); return reasonMatched && entityDataMatched; } From 66f633ce58f6cb0349799716de209c8f1f926079 Mon Sep 17 00:00:00 2001 From: OwlBe Date: Sun, 28 Jun 2026 15:17:45 -0400 Subject: [PATCH 07/35] more stuff --- .../java/org/skriptlang/skript/bukkit/entity/EntityModule.java | 1 + .../skript/bukkit/entity/{ => elements}/EntityEvents.java | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) rename src/main/java/org/skriptlang/skript/bukkit/entity/{ => elements}/EntityEvents.java (99%) diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/EntityModule.java b/src/main/java/org/skriptlang/skript/bukkit/entity/EntityModule.java index 3bea5dccf0e..396873103a5 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/EntityModule.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/EntityModule.java @@ -7,6 +7,7 @@ import org.skriptlang.skript.addon.HierarchicalAddonModule; import org.skriptlang.skript.addon.SkriptAddon; import org.skriptlang.skript.bukkit.entity.displays.DisplayModule; +import org.skriptlang.skript.bukkit.entity.elements.EntityEvents; import org.skriptlang.skript.bukkit.entity.elements.events.*; import org.skriptlang.skript.bukkit.entity.interactions.InteractionModule; import org.skriptlang.skript.bukkit.entity.elements.expressions.ExprDeathMessage; diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/EntityEvents.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/EntityEvents.java similarity index 99% rename from src/main/java/org/skriptlang/skript/bukkit/entity/EntityEvents.java rename to src/main/java/org/skriptlang/skript/bukkit/entity/elements/EntityEvents.java index 14e9d479125..f8879a516f2 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/EntityEvents.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/EntityEvents.java @@ -1,4 +1,4 @@ -package org.skriptlang.skript.bukkit.entity; +package org.skriptlang.skript.bukkit.entity.elements; import ch.njol.skript.classes.Changer.ChangeMode; import ch.njol.skript.lang.SkriptEvent; From cda7f94c2c26ae4fa383c1d7cd978bef2b1c6cbc Mon Sep 17 00:00:00 2001 From: OwlBe Date: Mon, 29 Jun 2026 01:55:33 -0400 Subject: [PATCH 08/35] wtflip is tis --- .../ch/njol/skript/events/EvtFirework.java | 82 ----------- .../ch/njol/skript/events/SimpleEvents.java | 131 ------------------ .../skript/bukkit/entity/EntityModule.java | 1 + .../bukkit/entity/elements/EntityEvents.java | 38 ++++- .../elements/events/EvtFireworkExplode.java | 120 ++++++++++++++++ 5 files changed, 158 insertions(+), 214 deletions(-) delete mode 100644 src/main/java/ch/njol/skript/events/EvtFirework.java create mode 100644 src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtFireworkExplode.java diff --git a/src/main/java/ch/njol/skript/events/EvtFirework.java b/src/main/java/ch/njol/skript/events/EvtFirework.java deleted file mode 100644 index 412f2b246e2..00000000000 --- a/src/main/java/ch/njol/skript/events/EvtFirework.java +++ /dev/null @@ -1,82 +0,0 @@ -package ch.njol.skript.events; - -import ch.njol.skript.Skript; -import ch.njol.skript.lang.Literal; -import ch.njol.skript.lang.SkriptEvent; -import ch.njol.skript.lang.SkriptParser.ParseResult; -import ch.njol.skript.lang.SyntaxStringBuilder; -import ch.njol.skript.util.Color; -import ch.njol.skript.util.ColorRGB; -import org.bukkit.FireworkEffect; -import org.bukkit.event.Event; -import org.bukkit.event.entity.FireworkExplodeEvent; -import org.bukkit.inventory.meta.FireworkMeta; -import org.jetbrains.annotations.Nullable; - -import java.util.Set; -import java.util.stream.Collectors; - -public class EvtFirework extends SkriptEvent { - - static { - if (Skript.classExists("org.bukkit.event.entity.FireworkExplodeEvent")) - //Making the event argument type fireworkeffects, led to Skript having troubles parsing for some reason. - Skript.registerEvent("Firework Explode", EvtFirework.class, FireworkExplodeEvent.class, - "[a] firework explo(d(e|ing)|sion) [colo[u]red %-colors%]") - .description("Called when a firework explodes.") - .examples( - "on firework explode:", - "\tif event-colors contains red:", - "on firework exploding colored red, light green and black:", - "on firework explosion colored rgb 0, 255, 0:", - "\tbroadcast \"A firework colored %colors% was exploded at %location%!\"" - ) - .since("2.4"); - } - - private @Nullable Literal colors; - - @Override - public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { - if (args[0] != null) - //noinspection unchecked - colors = (Literal) args[0]; - return true; - } - - @Override - public boolean check(Event event) { - if (!(event instanceof FireworkExplodeEvent fireworkExplodeEvent)) - return false; - - if (colors == null) - return true; - - Set colours = colors.stream(event) - .map(color -> { - if (color instanceof ColorRGB) - return color.asBukkitColor(); - return color.asDyeColor().getFireworkColor(); - }) - .collect(Collectors.toSet()); - - FireworkMeta meta = fireworkExplodeEvent.getEntity().getFireworkMeta(); - for (FireworkEffect effect : meta.getEffects()) { - if (colours.containsAll(effect.getColors())) - return true; - } - return false; - } - - @Override - public String toString(@Nullable Event event, boolean debug) { - SyntaxStringBuilder builder = new SyntaxStringBuilder(event, debug); - - builder.append("firework explode"); - if (colors != null) - builder.append("with colors").append(colors); - - return builder.toString(); - } - -} diff --git a/src/main/java/ch/njol/skript/events/SimpleEvents.java b/src/main/java/ch/njol/skript/events/SimpleEvents.java index 2819ede651e..b564c238d49 100644 --- a/src/main/java/ch/njol/skript/events/SimpleEvents.java +++ b/src/main/java/ch/njol/skript/events/SimpleEvents.java @@ -99,31 +99,11 @@ public class SimpleEvents { .description("Called when a chunk is unloaded due to not being near any player.") .examples("on chunk unload:") .since("1.0"); - Skript.registerEvent("Creeper Power", SimpleEvent.class, CreeperPowerEvent.class, "creeper power") - .description("Called when a creeper is struck by lighting and gets powered. Cancel the event to prevent the creeper from being powered.") - .examples("on creeper power:") - .since("1.0"); Skript.registerEvent("Zombie Break Door", SimpleEvent.class, EntityBreakDoorEvent.class, "zombie break[ing] [a] [wood[en]] door") .description("Called when a zombie is done breaking a wooden door. Can be cancelled to prevent the zombie from breaking the door.") .examples("on zombie breaking a wood door:") .since("1.0"); - Skript.registerEvent("Combust", SimpleEvent.class, EntityCombustEvent.class, "combust[ing]") - .description("Called when an entity is set on fire, e.g. by fire or lava, a fireball, or by standing in direct sunlight (zombies, skeletons).") - .examples("on combust:") - .since("1.0"); - Skript.registerEvent("Explode", SimpleEvent.class, EntityExplodeEvent.class, "explo(d(e|ing)|sion)") - .description("Called when an entity (a primed TNT or a creeper) explodes. When the mob griefing gamerule is false, this is not called for entities.") - .examples("on explosion:") - .since("1.0"); // Skript.registerEvent(SimpleEvent.class, EntityInteractEvent.class, "interact");// = entity interacts with block, e.g. endermen?; player -> PlayerInteractEvent // likely tripwires, pressure plates, etc. - Skript.registerEvent("Portal Enter", SimpleEvent.class, EntityPortalEnterEvent.class, "portal enter[ing]", "entering [a] portal") - .description("Called when an entity enters a nether portal or an end portal. Please note that this event will be fired many times for a nether portal.") - .examples("on portal enter:") - .since("1.0"); - Skript.registerEvent("Tame", SimpleEvent.class, EntityTameEvent.class, "[entity] tam(e|ing)") - .description("Called when a player tames a wolf or ocelot. Can be cancelled to prevent the entity from being tamed.") - .examples("on tame:") - .since("1.0"); Skript.registerEvent("Explosion Prime", SimpleEvent.class, ExplosionPrimeEvent.class, "explosion prime") .description("Called when an explosive is primed, i.e. an entity will explode shortly. Creepers can abort the explosion if the player gets too far away, " + "while TNT will explode for sure after a short time.") @@ -141,10 +121,6 @@ public class SimpleEvents { .description("Called when lightning strikes.") .examples("on lightning:", "\tspawn a zombie at location of event-entity") .since("1.0"); - Skript.registerEvent("Pig Zap", SimpleEvent.class, PigZapEvent.class, "pig[ ]zap") - .description("Called when a pig is stroke by lightning and transformed into a zombie pigman. Cancel the event to prevent the transformation.") - .examples("on pig zap:") - .since("1.0"); Skript.registerEvent("Bed Enter", SimpleEvent.class, PlayerBedEnterEvent.class, "bed enter[ing]", "[player] enter[ing] [a] bed") .description("Called when a player starts sleeping.") .examples("on bed enter:") @@ -281,35 +257,6 @@ public class SimpleEvents { "\tif event-entity is a spider:", "\t\tkill event-entity") .since("1.0"); - if (Skript.classExists("org.bukkit.event.entity.EntityMountEvent") || Skript.classExists("org.spigotmc.event.entity.EntityMountEvent")) { - Class mountEventClass = null; - Class dismountEventClass = null; - if (Skript.classExists("org.bukkit.event.entity.EntityMountEvent")) { - mountEventClass = EntityMountEvent.class; - dismountEventClass = EntityDismountEvent.class; - } else { - try { - mountEventClass = (Class) Class.forName("org.spigotmc.event.entity.EntityMountEvent"); - dismountEventClass = (Class) Class.forName("org.spigotmc.event.entity.EntityDismountEvent"); - } catch (ClassNotFoundException e) { - Skript.exception(e, "Failed to load legacy mount/dismount event classes. These events may not work."); - } - } - if (mountEventClass != null) { - Skript.registerEvent("Entity Mount", SimpleEvent.class, mountEventClass, "mount[ing]") - .description("Called when entity starts riding another.") - .examples("on mount:", - "\tcancel event") - .since("2.2-dev13b"); - } - if (dismountEventClass != null) { - Skript.registerEvent("Entity Dismount", SimpleEvent.class, dismountEventClass, "dismount[ing]") - .description("Called when an entity dismounts.") - .examples("on dismount:", - "\tkill event-entity") - .since("2.2-dev13b"); - } - } Skript.registerEvent("Gliding State Change", SimpleEvent.class, EntityToggleGlideEvent.class, "(gliding state change|toggl(e|ing) gliding)") .description("Called when an entity toggles glider on or off, or when server toggles gliding state of an entity forcibly.") @@ -336,20 +283,6 @@ public class SimpleEvents { "\tif player's location is {location}:", "\t\tsend \"You exited the shop!\"") .since("2.2-dev21"); - Skript.registerEvent("Slime Split", SimpleEvent.class, SlimeSplitEvent.class, "slime split[ting]") - .description("Called when a slime splits. Usually this happens when a big slime dies.") - .examples("on slime split:") - .since("2.2-dev26"); - Skript.registerEvent("Resurrect Attempt", SimpleEvent.class, EntityResurrectEvent.class, "[entity] resurrect[ion] [attempt]") - .description("Called when an entity dies, always. If they are not holding a totem, this is cancelled - you can, however, uncancel it.") - .examples( - "on resurrect attempt:", - "\tentity is player", - "\tentity has permission \"admin.undying\"", - "\tuncancel the event" - ) - .since("2.2-dev28") - .listeningBehavior(ListeningBehavior.ANY); Skript.registerEvent("Player World Change", SimpleEvent.class, PlayerChangedWorldEvent.class, "[player] world chang(ing|e[d])") .description("Called when a player enters a world. Does not work with other entities!") .examples("on player world change:", @@ -406,14 +339,6 @@ public class SimpleEvents { " set the fake max players count to (online players count + 1)", " set the shown icon to a random server icon out of {server-icons::*}") .since("2.3"); - Skript.registerEvent("Swim Toggle", SimpleEvent.class, EntityToggleSwimEvent.class, "[entity] toggl(e|ing) swim", - "[entity] swim toggl(e|ing)") - .description("Called when an entity swims or stops swimming.") - .requiredPlugins("1.13 or newer") - .examples("on swim toggle:", - " event-entity does not have permission \"swim\"", - " cancel event") - .since("2.3"); Skript.registerEvent("Riptide", SimpleEvent.class, PlayerRiptideEvent.class, "[use of] riptide [enchant[ment]]") .description("Called when the player activates the riptide enchantment, using their trident to propel them through the air.", "Note: the riptide action is performed client side, so manipulating the player in this event may have undesired effects.") @@ -445,10 +370,6 @@ public class SimpleEvents { .description("Called when an inventory (a hopper, a hopper minecart, etc.) picks up an item") .examples("on inventory pickup:") .since("2.5.1"); - Skript.registerEvent("Horse Jump", SimpleEvent.class, HorseJumpEvent.class, "horse jump") - .description("Called when a horse jumps.") - .examples("on horse jump:", "\tpush event-entity upwards at speed 2") - .since("2.5.1"); Skript.registerEvent("Block Fertilize", SimpleEvent.class, BlockFertilizeEvent.class, "[block] fertilize") .description("Called when a player fertilizes blocks.") .requiredPlugins("Minecraft 1.13 or newer") @@ -486,14 +407,6 @@ public class SimpleEvents { "\t\tsend \"The trade was somehow denied!\" to player") .since("2.7"); } - if (Skript.classExists("com.destroystokyo.paper.event.entity.EntityJumpEvent")) { - Skript.registerEvent("Entity Jump", SimpleEvent.class, EntityJumpEvent.class, "entity jump[ing]") - .description("Called when an entity jumps.") - .examples("on entity jump:", - "\tif entity is a wither skeleton:", - "\t\tcancel event") - .since("2.7"); - } if (Skript.classExists("com.destroystokyo.paper.event.block.AnvilDamagedEvent")) { Skript.registerEvent("Anvil Damage", SimpleEvent.class, AnvilDamagedEvent.class, "anvil damag(e|ing)") .description("Called when an anvil is damaged/broken from being used to repair/rename items.", @@ -571,17 +484,6 @@ public class SimpleEvents { "\t\tcancel event" ) .since("2.7"); - Skript.registerEvent("Piglin Barter", SimpleEvent.class, PiglinBarterEvent.class, "piglin (barter[ing]|trad(e|ing))") - .description( - "Called when a piglin finishes bartering. A piglin may start bartering after picking up an item on its bartering list.", - "Cancelling will prevent piglins from dropping items, but will still make them pick up the input.") - .examples( - "on piglin barter:", - "\tif barter drops contain diamond:", - "\t\tsend \"Diamonds belong in the money pit!\" to player", - "\t\tcancel event" - ) - .since("2.10"); Skript.registerEvent("Bell Ring", SimpleEvent.class, BellRingEvent.class, "bell ring[ing]") .description("Called when a bell is rung.") .examples( @@ -598,21 +500,6 @@ public class SimpleEvents { ) .since("2.9.0"); - if (Skript.classExists("com.destroystokyo.paper.event.entity.EndermanAttackPlayerEvent")) { - Skript.registerEvent("Enderman Enrage", SimpleEvent.class, com.destroystokyo.paper.event.entity.EndermanAttackPlayerEvent.class, "enderman (enrage|anger)") - .description( - "Called when an enderman gets mad because a player looked at them.", - "Note: This does not stop enderman from targeting the player as a result of getting damaged." - ) - .examples( - "# Stops endermen from getting angry players with the permission \"safeFrom.enderman\"", - "on enderman enrage:", - "\tif player has permission \"safeFrom.enderman\":", - "\t\tcancel event" - ) - .since("2.9.0"); - } - if (Skript.classExists("io.papermc.paper.event.player.PlayerChangeBeaconEffectEvent")) { Skript.registerEvent("Beacon Change Effect", SimpleEvent.class, PlayerChangeBeaconEffectEvent.class, "beacon change effect", "beacon effect change", "player chang(e[s]|ing) [of] beacon effect") @@ -673,11 +560,6 @@ public class SimpleEvents { .since("2.10"); } - Skript.registerEvent("Bat Toggle Sleep", SimpleEvent.class, BatToggleSleepEvent.class, "bat toggle sleep") - .description("Called when a bat attempts to go to sleep or wakes up.") - .examples("on bat toggle sleep:") - .since("2.11"); - // WorldBorder Events if (Skript.classExists("io.papermc.paper.event.world.border.WorldBorderEvent")) { Skript.registerEvent("World Border Bounds Change", SimpleEvent.class, WorldBorderBoundsChangeEvent.class, "world[ ]border [bounds] chang(e|ing)") @@ -728,19 +610,6 @@ public class SimpleEvents { .requiredPlugins("Minecraft 1.21.1+"); } - Skript.registerEvent("Villager Career Change", SimpleEvent.class, VillagerCareerChangeEvent.class, - "villager career chang(e[d]|ing)") - .description("Called when a villager changes its career. Can be caused by being employed or losing their job.") - .examples(""" - on villager career change: - if all: - event-career change reason is employment - event-villager profession is armorer profession - then: - cancel event - """) - .since("2.12"); - } } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/EntityModule.java b/src/main/java/org/skriptlang/skript/bukkit/entity/EntityModule.java index 396873103a5..28c2857fe4d 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/EntityModule.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/EntityModule.java @@ -58,6 +58,7 @@ protected void loadSelf(SkriptAddon addon) { EvtEntitySpawn.register(syntaxRegistry); EvtEntityTarget.register(syntaxRegistry); EvtEntityTransform.register(syntaxRegistry, eventValueRegistry); + EvtFireworkExplode.register(syntaxRegistry, eventValueRegistry); } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/EntityEvents.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/EntityEvents.java index f8879a516f2..7540fa76eb3 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/EntityEvents.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/EntityEvents.java @@ -5,11 +5,12 @@ import ch.njol.skript.lang.util.SimpleEvent; import ch.njol.skript.util.slot.EquipmentSlot; import ch.njol.skript.util.slot.Slot; +import com.destroystokyo.paper.event.entity.EndermanAttackPlayerEvent; import com.destroystokyo.paper.event.entity.EntityJumpEvent; +import org.bukkit.entity.Player; import org.bukkit.entity.Villager; import org.bukkit.event.entity.*; import org.bukkit.inventory.EntityEquipment; -import org.bukkit.inventory.ItemStack; import org.skriptlang.skript.bukkit.lang.eventvalue.EventValue; import org.skriptlang.skript.bukkit.lang.eventvalue.EventValueRegistry; import org.skriptlang.skript.bukkit.registration.BukkitSyntaxInfos; @@ -149,6 +150,21 @@ Called when an entity (usually a primed TNT or creeper) explodes. .addSince("2.7") .build()); + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Entity Toggle Swim") + .addEvent(EntityToggleSwimEvent.class) + .addPatterns( + "[entity] toggl(e|ing) swim", + "[on] [entity] swim toggl(e|ing)" + ) + .addDescription("Called when an entity swims or stops swimming.") + .addExample(""" + on swim toggle: + event-entity does not have the permission "perk.swim" + cancel event + """) + .addSince("2.3") + .build()); + // // Entity specific events (e.g. CreeperPowerEvent) // @@ -270,6 +286,26 @@ Called when an entity (usually a primed TNT or creeper) explodes. .getter(event -> event.getEntity().getProfession()) .time(PAST) .build()); + + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Enderman Enrage") + .addEvent(EndermanAttackPlayerEvent.class) + .addPatterns("enderman (enrage|anger)") + .addDescription(""" + Called when an enderman gets mad because a player looked at them. + Note: This does not stop enderman from targeting the player as a result of getting damaged + """) + .addExample(""" + on enderman enrage: + player has permission "safe.from.enderman" + cancel event + send "well you got lucky this time.." to event-player + """) + .addSince("2.9.0") + .build()); + + eventValueRegistry.register(EventValue.builder(EndermanAttackPlayerEvent.class, Player.class) + .getter(EndermanAttackPlayerEvent::getPlayer) + .build()); } } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtFireworkExplode.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtFireworkExplode.java new file mode 100644 index 00000000000..2e3ae37afe3 --- /dev/null +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtFireworkExplode.java @@ -0,0 +1,120 @@ +package org.skriptlang.skript.bukkit.entity.elements.events; + + +import ch.njol.skript.lang.Literal; +import ch.njol.skript.lang.SkriptEvent; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.lang.SyntaxStringBuilder; +import ch.njol.skript.util.Color; +import ch.njol.skript.util.ColorRGB; +import ch.njol.skript.util.SkriptColor; +import org.bukkit.FireworkEffect; +import org.bukkit.entity.Firework; +import org.bukkit.event.Event; +import org.bukkit.event.entity.FireworkExplodeEvent; +import org.bukkit.inventory.meta.FireworkMeta; +import org.jetbrains.annotations.Nullable; +import org.skriptlang.skript.bukkit.lang.eventvalue.EventValue; +import org.skriptlang.skript.bukkit.lang.eventvalue.EventValueRegistry; +import org.skriptlang.skript.bukkit.registration.BukkitSyntaxInfos; +import org.skriptlang.skript.registration.SyntaxRegistry; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +public class EvtFireworkExplode extends SkriptEvent { + + public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry eventValueRegistry) { + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(EvtFireworkExplode.class, "Firework Explode") + .supplier(EvtFireworkExplode::new) + .addEvent(FireworkExplodeEvent.class) + .addPatterns("[a] firework explo(d(e|ing)|sion) [color:colo[u]red %-colors%]") + .addDescription("Called when a firework explodes.") + .addExample(""" + on firework explode: + if event-colors contains red: + broadcast "its a red firework!" + """) + .addSince("2.4") + .build()); + + eventValueRegistry.register(EventValue.builder(FireworkExplodeEvent.class, Firework.class) + .getter(FireworkExplodeEvent::getEntity) + .build()); + + eventValueRegistry.register(EventValue.builder(FireworkExplodeEvent.class, FireworkEffect.class) + .getter(event -> { + List effects = event.getEntity().getFireworkMeta().getEffects(); + if (effects.isEmpty()) + return null; + return effects.getFirst(); + }) + .build()); + + eventValueRegistry.register(EventValue.builder(FireworkExplodeEvent.class, Color[].class) + .getter(event -> { + List effects = event.getEntity().getFireworkMeta().getEffects(); + if (effects.isEmpty()) + return new Color[0]; + List colors = new ArrayList<>(); + for (FireworkEffect fireworkEffect : effects) { + for (org.bukkit.Color color : fireworkEffect.getColors()) { + if (SkriptColor.fromBukkitColor(color) != null) + colors.add(SkriptColor.fromBukkitColor(color)); + else + colors.add(ColorRGB.fromBukkitColor(color)); + } + } + if (colors.isEmpty()) + return new Color[0]; + return colors.toArray(Color[]::new); + }) + .build()); + } + + private Color[] colors; + + @Override + @SuppressWarnings("unchecked") + public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { + if (parseResult.hasTag("color")) { + Literal colorLiteral = (Literal) args[0]; + colors = colorLiteral.getArray(); + } + return true; + } + + @Override + public boolean check(Event event) { + FireworkExplodeEvent entityEvent = (FireworkExplodeEvent) event; + if (colors == null) + return true; + + Set colours = Arrays.stream(colors) + .map(color -> { + if (color instanceof ColorRGB) + return color.asBukkitColor(); + return color.asDyeColor().getFireworkColor(); + }) + .collect(Collectors.toSet()); + + FireworkMeta meta = entityEvent.getEntity().getFireworkMeta(); + for (FireworkEffect effect : meta.getEffects()) { + if (colours.containsAll(effect.getColors())) + return true; + } + return false; + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return new SyntaxStringBuilder(event, debug) + .append("firework exploding") + .appendIf(colors != null, "colored", colors) + .toString(); + } + +} From 7ad15185c0991995a23386bef4271b742a74bae3 Mon Sep 17 00:00:00 2001 From: OwlBe Date: Mon, 29 Jun 2026 14:47:38 -0400 Subject: [PATCH 09/35] more random stuff --- .../classes/data/BukkitEventValues.java | 25 --- .../elements/events/EvtExperienceSpawn.java | 205 ++++++++++++++++++ 2 files changed, 205 insertions(+), 25 deletions(-) create mode 100644 src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtExperienceSpawn.java 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 ef50050518d..d289875053a 100644 --- a/src/main/java/ch/njol/skript/classes/data/BukkitEventValues.java +++ b/src/main/java/ch/njol/skript/classes/data/BukkitEventValues.java @@ -606,31 +606,6 @@ else if (hand == EquipmentSlot.OFF_HAND) })); } catch (NoSuchMethodException ignored) {} } - //FireworkExplodeEvent - registry.register(EventValue.simple(FireworkExplodeEvent.class, Firework.class, FireworkExplodeEvent::getEntity)); - registry.register(EventValue.simple(FireworkExplodeEvent.class, FireworkEffect.class, event -> { - List effects = event.getEntity().getFireworkMeta().getEffects(); - if (effects.isEmpty()) - return null; - return effects.get(0); - })); - registry.register(EventValue.simple(FireworkExplodeEvent.class, Color[].class, event -> { - List effects = event.getEntity().getFireworkMeta().getEffects(); - if (effects.isEmpty()) - return null; - List colors = new ArrayList<>(); - for (FireworkEffect fireworkEffect : effects) { - for (org.bukkit.Color color : fireworkEffect.getColors()) { - if (SkriptColor.fromBukkitColor(color) != null) - colors.add(SkriptColor.fromBukkitColor(color)); - else - colors.add(ColorRGB.fromBukkitColor(color)); - } - } - if (colors.isEmpty()) - return null; - return colors.toArray(Color[]::new); - })); //PlayerRiptideEvent registry.register(EventValue.simple(PlayerRiptideEvent.class, ItemStack.class, PlayerRiptideEvent::getItem)); //PlayerInventorySlotChangeEvent diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtExperienceSpawn.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtExperienceSpawn.java new file mode 100644 index 00000000000..0ed92bf6eaa --- /dev/null +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtExperienceSpawn.java @@ -0,0 +1,205 @@ +package org.skriptlang.skript.bukkit.entity.elements.events; + + +import ch.njol.skript.entity.EntityData; +import ch.njol.skript.lang.Literal; +import ch.njol.skript.lang.SkriptEvent; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.lang.SyntaxStringBuilder; +import org.bukkit.entity.Entity; +import org.bukkit.event.Event; +import org.bukkit.event.entity.EntityTransformEvent; +import org.bukkit.event.entity.EntityTransformEvent.TransformReason; +import org.jetbrains.annotations.Nullable; +import org.skriptlang.skript.bukkit.lang.eventvalue.EventValue; +import org.skriptlang.skript.bukkit.lang.eventvalue.EventValueRegistry; +import org.skriptlang.skript.bukkit.registration.BukkitSyntaxInfos; +import org.skriptlang.skript.registration.SyntaxRegistry; + +import java.util.Arrays; + +/* +public class EvtExperienceSpawn extends SkriptEvent { + + static { + Skript.registerEvent("Experience Spawn", EvtExperienceSpawn.class, ExperienceSpawnEvent.class, + "[e]xp[erience] [orb] spawn", + "spawn of [a[n]] [e]xp[erience] [orb]" + ).description( + "Called whenever experience is about to spawn.", + "Please note that this event will not fire for xp orbs spawned by plugins (including Skript) with Bukkit." + ).examples( + "on xp spawn:", + "\tworld is \"minigame_world\"", + "\tcancel event" + ).since("2.0"); + EventValues.registerEventValue(ExperienceSpawnEvent.class, Location.class, ExperienceSpawnEvent::getLocation); + EventValues.registerEventValue(ExperienceSpawnEvent.class, Experience.class, event -> new Experience(event.getSpawnedXP())); + } + + private static final List TRIGGERS = Collections.synchronizedList(new ArrayList<>()); + + private static final AtomicBoolean REGISTERED_EXECUTORS = new AtomicBoolean(); + + private static final EventExecutor EXECUTOR = (listener, event) -> { + ExperienceSpawnEvent experienceEvent; + if (event instanceof BlockExpEvent) { + experienceEvent = new ExperienceSpawnEvent( + ((BlockExpEvent) event).getExpToDrop(), + ((BlockExpEvent) event).getBlock().getLocation().add(0.5, 0.5, 0.5) + ); + } else if (event instanceof EntityDeathEvent) { + experienceEvent = new ExperienceSpawnEvent( + ((EntityDeathEvent) event).getDroppedExp(), + ((EntityDeathEvent) event).getEntity().getLocation() + ); + } else if (event instanceof ExpBottleEvent) { + experienceEvent = new ExperienceSpawnEvent( + ((ExpBottleEvent) event).getExperience(), + ((ExpBottleEvent) event).getEntity().getLocation() + ); + } else if (event instanceof PlayerFishEvent) { + if (((PlayerFishEvent) event).getState() != PlayerFishEvent.State.CAUGHT_FISH) // There is no EXP + return; + experienceEvent = new ExperienceSpawnEvent( + ((PlayerFishEvent) event).getExpToDrop(), + ((PlayerFishEvent) event).getPlayer().getLocation() + ); + } else { + assert false; + return; + } + + SkriptEventHandler.logEventStart(event); + synchronized (TRIGGERS) { + for (Trigger trigger : TRIGGERS) { + SkriptEventHandler.logTriggerStart(trigger); + trigger.execute(experienceEvent); + SkriptEventHandler.logTriggerEnd(trigger); + } + } + SkriptEventHandler.logEventEnd(); + + if (experienceEvent.isCancelled()) + experienceEvent.setSpawnedXP(0); + + if (event instanceof BlockExpEvent) { + ((BlockExpEvent) event).setExpToDrop(experienceEvent.getSpawnedXP()); + } else if (event instanceof EntityDeathEvent) { + ((EntityDeathEvent) event).setDroppedExp(experienceEvent.getSpawnedXP()); + } else if (event instanceof ExpBottleEvent) { + ((ExpBottleEvent) event).setExperience(experienceEvent.getSpawnedXP()); + } else if (event instanceof PlayerFishEvent) { + ((PlayerFishEvent) event).setExpToDrop(experienceEvent.getSpawnedXP()); + } + }; + + @Override + public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { + return true; + } + + @Override + public boolean postLoad() { + TRIGGERS.add(trigger); + if (REGISTERED_EXECUTORS.compareAndSet(false, true)) { + EventPriority priority = SkriptConfig.defaultEventPriority.value(); + //noinspection unchecked + for (Class clazz : new Class[]{BlockExpEvent.class, EntityDeathEvent.class, ExpBottleEvent.class, PlayerFishEvent.class}) + Bukkit.getPluginManager().registerEvent(clazz, new Listener(){}, priority, EXECUTOR, Skript.getInstance(), true); + } + return true; + } + + @Override + public void unload() { + TRIGGERS.remove(trigger); + } + + @Override + public boolean check(Event event) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isEventPrioritySupported() { + return false; + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return "experience spawn"; + } + +} + */ +public class EvtExperienceSpawn extends SkriptEvent { + + public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry eventValueRegistry) { + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(EvtEntityTransform.class, "Entity Transform") + .supplier(EvtEntityTransform::new) + .addEvent(EntityTransformEvent.class) + .addPatterns("[entity:%*-entitydatas%] transform[ing] [transform: due to %-transformreasons%]") + .addDescription(""" + Called when an entity is about to be replaced by another entity. + e.g. when a zombie gets cured and a villager spawns,\s + an entity drowns in water like a zombie that turns to a drown,\s + an entity that gets frozen in powder snow,\s + a mooshroom that when sheared, spawns a new cow. + """) + .addExample(""" + on a zombie transforming due to curing: + broadcast "Another one cured from this madness.." + """) + .addExample(""" + on mooshroom transforming: + cancel event + broadcast "forever a mooshroom!" + """) + .addSince("2.8.0") + .build()); + + eventValueRegistry.register(EventValue.builder(EntityTransformEvent.class, Entity[].class) + .getter(event -> event.getTransformedEntities().toArray(Entity[]::new)) + .build()); + + eventValueRegistry.register(EventValue.builder(EntityTransformEvent.class, TransformReason.class) + .getter(EntityTransformEvent::getTransformReason) + .build()); + } + + private EntityData[] entityData; + private TransformReason[] reasons; + + @Override + @SuppressWarnings("unchecked") + public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { + if (parseResult.hasTag("transform")) { + Literal transformLiteral = (Literal) args[1]; + reasons = transformLiteral.getArray(); + } + if (parseResult.hasTag("entity")) { + Literal> entityLiteral = (Literal>) args[0]; + entityData = entityLiteral.getArray(); + } + return true; + } + + @Override + public boolean check(Event event) { + EntityTransformEvent entityEvent = (EntityTransformEvent) event; + boolean reasonMatched = reasons == null || Arrays.stream(reasons).anyMatch(reason -> reason == entityEvent.getTransformReason()); + boolean entityDataMatched = entityData == null || Arrays.stream(entityData).anyMatch(data -> data.isInstance(entityEvent.getEntity())); + return reasonMatched && entityDataMatched; + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return new SyntaxStringBuilder(event, debug) + .append(entityData != null ? entityData : "entity") + .append("transforming") + .appendIf(reasons != null, "due to", reasons) + .toString(); + } + +} From a2f8ac1d91f9ee62fb61daeef523a62d46fd43ec Mon Sep 17 00:00:00 2001 From: OwlBe Date: Tue, 30 Jun 2026 17:11:26 -0400 Subject: [PATCH 10/35] final straw (just need to finish EvtEntityMove.java & do a quick review over all files) --- .../classes/data/BukkitEventValues.java | 45 ---- .../skript/events/EvtExperienceSpawn.java | 142 ----------- .../ch/njol/skript/events/EvtHealing.java | 82 ------- .../java/ch/njol/skript/events/EvtLeash.java | 126 ---------- .../java/ch/njol/skript/events/EvtPortal.java | 57 ----- .../ch/njol/skript/events/EvtTeleport.java | 128 ---------- .../skript/bukkit/entity/EntityModule.java | 9 +- .../bukkit/entity/elements/EntityEvents.java | 52 ++++ .../elements/events/EvtEntityBreakDoor.java | 2 +- .../elements/events/EvtEntityDamage.java | 18 +- .../elements/events/EvtEntityDeath.java | 29 ++- .../entity/elements/events/EvtEntityHeal.java | 88 +++++++ .../elements/events/EvtEntityLeash.java | 131 ++++++++++ .../entity/elements/events/EvtEntityMove.java | 230 ++++++++++++++++++ .../elements/events/EvtEntityPortal.java | 63 +++++ .../elements/events/EvtEntityTeleport.java | 105 ++++++++ .../elements/events/EvtExperienceSpawn.java | 203 ++++++---------- 17 files changed, 796 insertions(+), 714 deletions(-) delete mode 100644 src/main/java/ch/njol/skript/events/EvtExperienceSpawn.java delete mode 100644 src/main/java/ch/njol/skript/events/EvtHealing.java delete mode 100644 src/main/java/ch/njol/skript/events/EvtLeash.java delete mode 100644 src/main/java/ch/njol/skript/events/EvtPortal.java delete mode 100644 src/main/java/ch/njol/skript/events/EvtTeleport.java create mode 100644 src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityHeal.java create mode 100644 src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityLeash.java create mode 100644 src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityMove.java create mode 100644 src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityPortal.java create mode 100644 src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTeleport.java 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 d289875053a..38b47c7f041 100644 --- a/src/main/java/ch/njol/skript/classes/data/BukkitEventValues.java +++ b/src/main/java/ch/njol/skript/classes/data/BukkitEventValues.java @@ -192,44 +192,6 @@ public static void register(EventValueRegistry registry) { registry.register(EventValue.simple(SignChangeEvent.class, Player.class, SignChangeEvent::getPlayer)); registry.register(EventValue.simple(SignChangeEvent.class, Component[].class, event -> event.lines().toArray(new Component[0]))); - // === EntityEvents === - registry.register(EventValue.builder(EntityEvent.class, Entity.class) - .getter(EntityEvent::getEntity) - .excludes(EntityDamageEvent.class, EntityDeathEvent.class) - .excludedErrorMessage("Use 'attacker' and/or 'victim' in damage/death events") - .build()); - registry.register(EventValue.builder(EntityEvent.class, CommandSender.class) - .getter(EntityEvent::getEntity) - .excludes(EntityDamageEvent.class, EntityDeathEvent.class) - .excludedErrorMessage("Use 'attacker' and/or 'victim' in damage/death events") - .build()); - registry.register(EventValue.simple(EntityEvent.class, World.class, event -> event.getEntity().getWorld())); - registry.register(EventValue.simple(EntityEvent.class, Location.class, event -> event.getEntity().getLocation())); - registry.register(EventValue.builder(EntityEvent.class, EntityData.class) - .getter(event -> EntityData.fromEntity(event.getEntity())) - .excludes(EntityDamageEvent.class, EntityDeathEvent.class) - .excludedErrorMessage("Use 'type of attacker/victim' in damage/death events.") - .build()); - // EntityDamageEvent - registry.register(EventValue.simple(EntityDamageEvent.class, DamageCause.class, EntityDamageEvent::getCause)); - registry.register(EventValue.simple(EntityDamageByEntityEvent.class, Projectile.class, event -> { - if (event.getDamager() instanceof Projectile projectile) - return projectile; - return null; - })); - // EntityDeathEvent - registry.register(EventValue.simple(EntityDeathEvent.class, ItemStack[].class, event -> event.getDrops().toArray(new ItemStack[0]))); - registry.register(EventValue.simple(EntityDeathEvent.class, Projectile.class, event -> { - EntityDamageEvent damageEvent = event.getEntity().getLastDamageCause(); - if (damageEvent instanceof EntityDamageByEntityEvent entityEvent && entityEvent.getDamager() instanceof Projectile projectile) - return projectile; - return null; - })); - registry.register(EventValue.simple(EntityDeathEvent.class, DamageCause.class, event -> { - EntityDamageEvent damageEvent = event.getEntity().getLastDamageCause(); - return damageEvent == null ? null : damageEvent.getCause(); - })); - // ProjectileHitEvent // ProjectileHitEvent#getHitBlock was added in 1.11 if (Skript.methodExists(ProjectileHitEvent.class, "getHitBlock")) @@ -290,10 +252,6 @@ public PotionEffectType convert(AreaEffectCloudApplyEvent event) { registry.register(EventValue.simple(ItemSpawnEvent.class, ItemStack.class, event -> event.getEntity().getItemStack())); // LightningStrikeEvent registry.register(EventValue.simple(LightningStrikeEvent.class, Entity.class, LightningStrikeEvent::getLightning)); - // EndermanAttackPlayerEvent - if (Skript.classExists("com.destroystokyo.paper.event.entity.EndermanAttackPlayerEvent")) { - registry.register(EventValue.simple(EndermanAttackPlayerEvent.class, Player.class, EndermanAttackPlayerEvent::getPlayer)); - } // --- PlayerEvents --- registry.register(EventValue.simple(PlayerEvent.class, Player.class, PlayerEvent::getPlayer)); @@ -706,9 +664,6 @@ else if (hand == EquipmentSlot.OFF_HAND) .build()); registry.register(EventValue.simple(InventoryMoveItemEvent.class, ItemStack.class, InventoryMoveItemEvent::getItem)); - // EntityRegainHealthEvent - registry.register(EventValue.simple(EntityRegainHealthEvent.class, RegainReason.class, EntityRegainHealthEvent::getRegainReason)); - // FurnaceExtractEvent registry.register(EventValue.simple(FurnaceExtractEvent.class, Player.class, FurnaceExtractEvent::getPlayer)); registry.register(EventValue.simple(FurnaceExtractEvent.class, ItemStack[].class, event -> new ItemStack[]{ItemStack.of(event.getItemType(), event.getItemAmount())})); diff --git a/src/main/java/ch/njol/skript/events/EvtExperienceSpawn.java b/src/main/java/ch/njol/skript/events/EvtExperienceSpawn.java deleted file mode 100644 index 4aad0cfeab6..00000000000 --- a/src/main/java/ch/njol/skript/events/EvtExperienceSpawn.java +++ /dev/null @@ -1,142 +0,0 @@ -package ch.njol.skript.events; - -import ch.njol.skript.Skript; -import ch.njol.skript.SkriptConfig; -import ch.njol.skript.SkriptEventHandler; -import ch.njol.skript.events.bukkit.ExperienceSpawnEvent; -import ch.njol.skript.lang.Literal; -import ch.njol.skript.lang.SkriptEvent; -import ch.njol.skript.lang.SkriptParser.ParseResult; -import ch.njol.skript.lang.Trigger; -import ch.njol.skript.registrations.EventValues; -import ch.njol.skript.util.Experience; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.event.Event; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; -import org.bukkit.event.block.BlockExpEvent; -import org.bukkit.event.entity.EntityDeathEvent; -import org.bukkit.event.entity.ExpBottleEvent; -import org.bukkit.event.player.PlayerFishEvent; -import org.bukkit.plugin.EventExecutor; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.atomic.AtomicBoolean; - -public class EvtExperienceSpawn extends SkriptEvent { - - static { - Skript.registerEvent("Experience Spawn", EvtExperienceSpawn.class, ExperienceSpawnEvent.class, - "[e]xp[erience] [orb] spawn", - "spawn of [a[n]] [e]xp[erience] [orb]" - ).description( - "Called whenever experience is about to spawn.", - "Please note that this event will not fire for xp orbs spawned by plugins (including Skript) with Bukkit." - ).examples( - "on xp spawn:", - "\tworld is \"minigame_world\"", - "\tcancel event" - ).since("2.0"); - EventValues.registerEventValue(ExperienceSpawnEvent.class, Location.class, ExperienceSpawnEvent::getLocation); - EventValues.registerEventValue(ExperienceSpawnEvent.class, Experience.class, event -> new Experience(event.getSpawnedXP())); - } - - private static final List TRIGGERS = Collections.synchronizedList(new ArrayList<>()); - - private static final AtomicBoolean REGISTERED_EXECUTORS = new AtomicBoolean(); - - private static final EventExecutor EXECUTOR = (listener, event) -> { - ExperienceSpawnEvent experienceEvent; - if (event instanceof BlockExpEvent) { - experienceEvent = new ExperienceSpawnEvent( - ((BlockExpEvent) event).getExpToDrop(), - ((BlockExpEvent) event).getBlock().getLocation().add(0.5, 0.5, 0.5) - ); - } else if (event instanceof EntityDeathEvent) { - experienceEvent = new ExperienceSpawnEvent( - ((EntityDeathEvent) event).getDroppedExp(), - ((EntityDeathEvent) event).getEntity().getLocation() - ); - } else if (event instanceof ExpBottleEvent) { - experienceEvent = new ExperienceSpawnEvent( - ((ExpBottleEvent) event).getExperience(), - ((ExpBottleEvent) event).getEntity().getLocation() - ); - } else if (event instanceof PlayerFishEvent) { - if (((PlayerFishEvent) event).getState() != PlayerFishEvent.State.CAUGHT_FISH) // There is no EXP - return; - experienceEvent = new ExperienceSpawnEvent( - ((PlayerFishEvent) event).getExpToDrop(), - ((PlayerFishEvent) event).getPlayer().getLocation() - ); - } else { - assert false; - return; - } - - SkriptEventHandler.logEventStart(event); - synchronized (TRIGGERS) { - for (Trigger trigger : TRIGGERS) { - SkriptEventHandler.logTriggerStart(trigger); - trigger.execute(experienceEvent); - SkriptEventHandler.logTriggerEnd(trigger); - } - } - SkriptEventHandler.logEventEnd(); - - if (experienceEvent.isCancelled()) - experienceEvent.setSpawnedXP(0); - - if (event instanceof BlockExpEvent) { - ((BlockExpEvent) event).setExpToDrop(experienceEvent.getSpawnedXP()); - } else if (event instanceof EntityDeathEvent) { - ((EntityDeathEvent) event).setDroppedExp(experienceEvent.getSpawnedXP()); - } else if (event instanceof ExpBottleEvent) { - ((ExpBottleEvent) event).setExperience(experienceEvent.getSpawnedXP()); - } else if (event instanceof PlayerFishEvent) { - ((PlayerFishEvent) event).setExpToDrop(experienceEvent.getSpawnedXP()); - } - }; - - @Override - public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { - return true; - } - - @Override - public boolean postLoad() { - TRIGGERS.add(trigger); - if (REGISTERED_EXECUTORS.compareAndSet(false, true)) { - EventPriority priority = SkriptConfig.defaultEventPriority.value(); - //noinspection unchecked - for (Class clazz : new Class[]{BlockExpEvent.class, EntityDeathEvent.class, ExpBottleEvent.class, PlayerFishEvent.class}) - Bukkit.getPluginManager().registerEvent(clazz, new Listener(){}, priority, EXECUTOR, Skript.getInstance(), true); - } - return true; - } - - @Override - public void unload() { - TRIGGERS.remove(trigger); - } - - @Override - public boolean check(Event event) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isEventPrioritySupported() { - return false; - } - - @Override - public String toString(@Nullable Event event, boolean debug) { - return "experience spawn"; - } - -} diff --git a/src/main/java/ch/njol/skript/events/EvtHealing.java b/src/main/java/ch/njol/skript/events/EvtHealing.java deleted file mode 100644 index 95c530adaaf..00000000000 --- a/src/main/java/ch/njol/skript/events/EvtHealing.java +++ /dev/null @@ -1,82 +0,0 @@ -package ch.njol.skript.events; - -import org.bukkit.entity.Entity; -import org.bukkit.event.Event; -import org.bukkit.event.entity.EntityRegainHealthEvent; -import org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason; -import org.jetbrains.annotations.Nullable; - -import ch.njol.skript.Skript; -import ch.njol.skript.entity.EntityData; -import ch.njol.skript.lang.Literal; -import ch.njol.skript.lang.SkriptEvent; -import ch.njol.skript.lang.SkriptParser.ParseResult; - -public class EvtHealing extends SkriptEvent { - - static { - Skript.registerEvent("Heal", EvtHealing.class, EntityRegainHealthEvent.class, "heal[ing] [of %-entitydatas%] [(from|due to|by) %-healreasons%]", "%entitydatas% heal[ing] [(from|due to|by) %-healreasons%]") - .description("Called when an entity is healed, e.g. by eating (players), being fed (pets), or by the effect of a potion of healing (overworld mobs) or harm (nether mobs).") - .examples( - "on heal:", - "on player healing from a regeneration potion:", - "on healing of a zombie, cow or a wither:", - "\theal reason is healing potion", - "\tcancel event" - ) - .since("1.0, 2.9.0 (by reason)"); - } - - @Nullable - private Literal> entityDatas; - - @Nullable - private Literal healReasons; - - @Override - @SuppressWarnings("unchecked") - public boolean init(Literal[] args, int matchedPattern, ParseResult parser) { - entityDatas = (Literal>) args[0]; - healReasons = (Literal) args[1]; - return true; - } - - @Override - public boolean check(Event event) { - if (!(event instanceof EntityRegainHealthEvent)) - return false; - EntityRegainHealthEvent healthEvent = (EntityRegainHealthEvent) event; - if (entityDatas != null) { - Entity compare = healthEvent.getEntity(); - boolean result = false; - for (EntityData entityData : entityDatas.getAll()) { - if (entityData.isInstance(compare)) { - result = true; - break; - } - } - if (!result) - return false; - } - if (healReasons != null) { - RegainReason compare = healthEvent.getRegainReason(); - boolean result = false; - for (RegainReason healReason : healReasons.getAll()) { - if (healReason == compare) { - result = true; - break; - } - } - if (!result) - return false; - } - return true; - } - - @Override - public String toString(@Nullable Event event, boolean debug) { - return "heal" + (entityDatas != null ? " of " + entityDatas.toString(event, debug) : "") + - (healReasons != null ? " by " + healReasons.toString(event, debug) : ""); - } - -} diff --git a/src/main/java/ch/njol/skript/events/EvtLeash.java b/src/main/java/ch/njol/skript/events/EvtLeash.java deleted file mode 100644 index ddce3535e08..00000000000 --- a/src/main/java/ch/njol/skript/events/EvtLeash.java +++ /dev/null @@ -1,126 +0,0 @@ -package ch.njol.skript.events; - -import org.bukkit.entity.Entity; -import org.bukkit.entity.Player; -import org.bukkit.event.Event; -import org.bukkit.event.entity.EntityUnleashEvent; -import org.bukkit.event.entity.PlayerLeashEntityEvent; -import org.bukkit.event.player.PlayerUnleashEntityEvent; -import org.jetbrains.annotations.Nullable; - -import ch.njol.skript.Skript; -import ch.njol.skript.entity.EntityData; -import ch.njol.skript.lang.Literal; -import ch.njol.skript.lang.SkriptEvent; -import ch.njol.skript.lang.SkriptParser.ParseResult; -import ch.njol.skript.registrations.Classes; -import ch.njol.skript.registrations.EventValues; -import ch.njol.util.coll.CollectionUtils; - -public class EvtLeash extends SkriptEvent { - - static { - Skript.registerEvent("Leash / Unleash", EvtLeash.class, CollectionUtils.array(PlayerLeashEntityEvent.class, EntityUnleashEvent.class), "[:player] [:un]leash[ing] [of %-entitydatas%]") - .description("Called when an entity is leashed or unleashed. Cancelling these events will prevent the leashing or unleashing from occurring.") - .examples( - "on player leash of a sheep:", - "\tsend \"Baaaaa--\" to player", - "", - "on player leash:", - "\tsend \"<%event-entity%> Let me go!\" to player", - "", - "on unleash:", - "\tbroadcast \"<%event-entity%> I'm free\"", - "", - "on player unleash:", - "\tsend \"<%event-entity%> Thanks for freeing me!\" to player" - ) - .since("2.10"); - - // PlayerLeashEntityEvent - // event-player is explicitly registered due to event does not extend PlayerEvent - EventValues.registerEventValue(PlayerLeashEntityEvent.class, Player.class, PlayerLeashEntityEvent::getPlayer); - EventValues.registerEventValue(PlayerLeashEntityEvent.class, Entity.class, PlayerLeashEntityEvent::getEntity); - - // EntityUnleashEvent - EventValues.registerEventValue(EntityUnleashEvent.class, EntityUnleashEvent.UnleashReason.class, EntityUnleashEvent::getReason); - - // PlayerUnleashEntityEvent - EventValues.registerEventValue(PlayerUnleashEntityEvent.class, Player.class, PlayerUnleashEntityEvent::getPlayer); - } - - private enum EventType { - - LEASH("leash"), - UNLEASH("unleash"), - UNLEASH_BY_PLAYER("player unleash"); - - private final String name; - - EventType(String name) { - this.name = name; - } - - - @Override - public String toString() { - return name; - } - - } - - private @Nullable EntityData[] types; - private EventType eventType; - - @Override - public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { - //noinspection unchecked - types = args[0] == null ? null : ((Literal>) args[0]).getAll(); - eventType = EventType.LEASH; - if (parseResult.hasTag("un")) { - eventType = EventType.UNLEASH; - if (parseResult.hasTag("player")) { - eventType = EventType.UNLEASH_BY_PLAYER; - } - } - return true; - } - - @Override - public boolean check(Event event) { - Entity leashedEntity; - switch (eventType) { - case LEASH -> { - if (!(event instanceof PlayerLeashEntityEvent playerLeash)) - return false; - leashedEntity = playerLeash.getEntity(); - } - case UNLEASH -> { - if (!(event instanceof EntityUnleashEvent entityUnleash)) - return false; - leashedEntity = entityUnleash.getEntity(); - } - case UNLEASH_BY_PLAYER -> { - if (!(event instanceof PlayerUnleashEntityEvent playerUnleash)) - return false; - leashedEntity = playerUnleash.getEntity(); - } - default -> { - return false; - } - } - if (types == null) - return true; - for (EntityData entityData : types) { - if (entityData.isInstance(leashedEntity)) - return true; - } - return false; - } - - @Override - public String toString(@Nullable Event event, boolean debug) { - return eventType + (types != null ? " of " + Classes.toString(types, false) : ""); - } - -} diff --git a/src/main/java/ch/njol/skript/events/EvtPortal.java b/src/main/java/ch/njol/skript/events/EvtPortal.java deleted file mode 100644 index 2d1de76eb2a..00000000000 --- a/src/main/java/ch/njol/skript/events/EvtPortal.java +++ /dev/null @@ -1,57 +0,0 @@ -package ch.njol.skript.events; - -import org.bukkit.event.Event; -import org.bukkit.event.entity.EntityPortalEvent; -import org.bukkit.event.player.PlayerPortalEvent; -import org.jetbrains.annotations.Nullable; - -import ch.njol.skript.Skript; -import ch.njol.skript.lang.Literal; -import ch.njol.skript.lang.SkriptEvent; -import ch.njol.skript.lang.SkriptParser.ParseResult; -import ch.njol.util.coll.CollectionUtils; - -public class EvtPortal extends SkriptEvent { - - static { - Skript.registerEvent("Portal", EvtPortal.class, CollectionUtils.array(PlayerPortalEvent.class, EntityPortalEvent.class), "[player] portal", "entity portal") - .description( - "Called when a player or an entity uses a nether or end portal. Note that 'on entity portal' event does not apply to players.", - "Cancel the event to prevent the entity from teleporting." - ).keywords( - "player", "entity" - ).examples( - "on portal:", - "\tbroadcast \"%player% has entered a portal!\"", - "", - "on player portal:", - "\tplayer's world is world(\"wilderness\")", - "\tset world of event-location to player's world", - "\tadd 9000 to x-pos of event-location", - "", - "on entity portal:", - "\tbroadcast \"A %type of event-entity% has entered a portal!" - ).since("1.0, 2.5.3 (entities), 2.13 (location changers)"); - } - - private boolean isPlayer; - - @Override - public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { - isPlayer = matchedPattern == 0; - return true; - } - - @Override - public boolean check(Event event) { - if (isPlayer) - return event instanceof PlayerPortalEvent; - return event instanceof EntityPortalEvent; - } - - @Override - public String toString(@Nullable Event event, boolean debug) { - return (isPlayer ? "player" : "entity") + " portal"; - } - -} diff --git a/src/main/java/ch/njol/skript/events/EvtTeleport.java b/src/main/java/ch/njol/skript/events/EvtTeleport.java deleted file mode 100644 index 7c85221a8d3..00000000000 --- a/src/main/java/ch/njol/skript/events/EvtTeleport.java +++ /dev/null @@ -1,128 +0,0 @@ -package ch.njol.skript.events; - -import ch.njol.skript.Skript; -import ch.njol.skript.lang.Literal; -import ch.njol.skript.lang.SkriptEvent; -import ch.njol.skript.lang.SkriptParser.ParseResult; -import ch.njol.skript.entity.EntityType; -import ch.njol.skript.registrations.EventConverter; -import ch.njol.skript.registrations.EventValues; -import ch.njol.util.coll.CollectionUtils; - -import org.bukkit.Location; -import org.bukkit.entity.Entity; -import org.bukkit.event.Event; -import org.bukkit.event.entity.EntityTeleportEvent; -import org.bukkit.event.player.PlayerTeleportEvent; -import org.jetbrains.annotations.Nullable; - -import static ch.njol.skript.registrations.EventValues.TIME_PAST; - -public class EvtTeleport extends SkriptEvent { - - static { - Skript.registerEvent("Teleport", EvtTeleport.class, CollectionUtils.array(EntityTeleportEvent.class, PlayerTeleportEvent.class), "[%entitytypes%] teleport[ing]") - .description( - "This event can be used to listen to teleports from non-players or player entities respectively.", - "When teleporting entities, the event may also be called due to a result of natural causes, such as an enderman or shulker teleporting, or wolves teleporting to players.", - "When teleporting players, the event can be called by teleporting through a nether/end portal, or by other means (e.g. plugins).") - .examples( - "on teleport:", - "on player teleport:", - "on creeper teleport:" - ) - .since("1.0, 2.9.0 (entity teleport)"); - - EventValues.registerEventValue(PlayerTeleportEvent.class, Location.class, new EventConverter<>() { - @Override - public void set(PlayerTeleportEvent event, Location value) { - event.setFrom(value.clone()); - } - - @Override - public Location convert(PlayerTeleportEvent event) { - return event.getFrom(); - } - }, TIME_PAST); - EventValues.registerEventValue(PlayerTeleportEvent.class, Location.class, new EventConverter<>() { - @Override - public void set(PlayerTeleportEvent event, Location value) { - event.setTo(value.clone()); - } - - @Override - public Location convert(PlayerTeleportEvent event) { - return event.getTo(); - } - }); - - EventValues.registerEventValue(EntityTeleportEvent.class, Location.class, new EventConverter<>() { - @Override - public void set(EntityTeleportEvent event, Location value) { - event.setFrom(value.clone()); - } - - @Override - public Location convert(EntityTeleportEvent event) { - return event.getFrom(); - } - }, TIME_PAST); - EventValues.registerEventValue(EntityTeleportEvent.class, Location.class, new EventConverter<>() { - @Override - public void set(EntityTeleportEvent event, Location value) { - event.setTo(value.clone()); - } - - @Override - public Location convert(EntityTeleportEvent event) { - return event.getTo(); - } - }); - - } - - @Nullable - private Literal entitiesLiteral; - private EntityType @Nullable [] entities; - - @Override - public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { - if (args[0] != null) { - entitiesLiteral = ((Literal) args[0]); // evaluate only once - entities = entitiesLiteral.getAll(); - } - return true; - } - - - @Override - public boolean check(Event event) { - if (event instanceof EntityTeleportEvent) { - Entity entity = ((EntityTeleportEvent) event).getEntity(); - return checkEntity(entity); - } else if (event instanceof PlayerTeleportEvent) { - Entity entity = ((PlayerTeleportEvent) event).getPlayer(); - return checkEntity(entity); - } else { - return false; - } - } - - private boolean checkEntity(Entity entity) { - if (entities != null) { - for (EntityType entType : entities) { - if (entType.isInstance(entity)) - return true; - } - return false; - } - return true; - } - - public String toString(@Nullable Event event, boolean debug) { - if (entitiesLiteral != null) - return "on " + entitiesLiteral.toString(event, debug) + " teleport"; - return "on teleport"; - } - -} diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/EntityModule.java b/src/main/java/org/skriptlang/skript/bukkit/entity/EntityModule.java index 28c2857fe4d..7b58f1f4c87 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/EntityModule.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/EntityModule.java @@ -52,12 +52,17 @@ protected void loadSelf(SkriptAddon addon) { EvtEntityBlockChange.register(syntaxRegistry, eventValueRegistry); EvtEntityBreakDoor.register(syntaxRegistry); - EvtEntityDamage.register(syntaxRegistry); - EvtEntityDeath.register(syntaxRegistry); + EvtEntityDamage.register(syntaxRegistry, eventValueRegistry); + EvtEntityDeath.register(syntaxRegistry, eventValueRegistry); + EvtEntityHeal.register(syntaxRegistry, eventValueRegistry); + EvtEntityLeash.register(syntaxRegistry, eventValueRegistry); + EvtEntityPortal.register(syntaxRegistry); EvtEntityShootBow.register(syntaxRegistry, eventValueRegistry); EvtEntitySpawn.register(syntaxRegistry); EvtEntityTarget.register(syntaxRegistry); + EvtEntityTeleport.register(syntaxRegistry, eventValueRegistry); EvtEntityTransform.register(syntaxRegistry, eventValueRegistry); + EvtExperienceSpawn.register(syntaxRegistry, eventValueRegistry); EvtFireworkExplode.register(syntaxRegistry, eventValueRegistry); } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/EntityEvents.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/EntityEvents.java index 7540fa76eb3..3cadce41c95 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/EntityEvents.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/EntityEvents.java @@ -1,12 +1,17 @@ package org.skriptlang.skript.bukkit.entity.elements; import ch.njol.skript.classes.Changer.ChangeMode; +import ch.njol.skript.entity.EntityData; import ch.njol.skript.lang.SkriptEvent; import ch.njol.skript.lang.util.SimpleEvent; import ch.njol.skript.util.slot.EquipmentSlot; import ch.njol.skript.util.slot.Slot; import com.destroystokyo.paper.event.entity.EndermanAttackPlayerEvent; import com.destroystokyo.paper.event.entity.EntityJumpEvent; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.entity.Villager; import org.bukkit.event.entity.*; @@ -22,6 +27,36 @@ public class EntityEvents { public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry eventValueRegistry) { + // + // Entity Event Values + // + + eventValueRegistry.register(EventValue.builder(EntityEvent.class, Entity.class) + .getter(EntityEvent::getEntity) + .excludes(EntityDamageEvent.class, EntityDeathEvent.class) + .excludedErrorMessage("Use 'attacker' and/or 'victim' in damage/death events") + .build()); + + eventValueRegistry.register(EventValue.builder(EntityEvent.class, CommandSender.class) + .getter(EntityEvent::getEntity) + .excludes(EntityDamageEvent.class, EntityDeathEvent.class) + .excludedErrorMessage("Use 'attacker' and/or 'victim' in damage/death events") + .build()); + + eventValueRegistry.register(EventValue.builder(EntityEvent.class, World.class) + .getter(event -> event.getEntity().getWorld()) + .build()); + + eventValueRegistry.register(EventValue.builder(EntityEvent.class, Location.class) + .getter(event -> event.getEntity().getLocation()) + .build()); + + eventValueRegistry.register(EventValue.builder(EntityEvent.class, EntityData.class) + .getter(event -> EntityData.fromEntity(event.getEntity())) + .excludes(EntityDamageEvent.class, EntityDeathEvent.class) + .excludedErrorMessage("Use 'type of attacker/victim' in damage/death events.") + .build()); + // // Entity Events // @@ -38,6 +73,7 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev broadcast "It burns!!" """) .addSince("1.0") + .supplier(() -> new SimpleEvent("entity combusting")) .build()); syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Entity Explode") @@ -51,6 +87,7 @@ Called when an entity (usually a primed TNT or creeper) explodes. broadcast "*Explosion*" """) .addSince("1.0") + .supplier(() -> new SimpleEvent("entity exploding")) .build()); syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Entity Portal Enter") @@ -66,6 +103,7 @@ Called when an entity (usually a primed TNT or creeper) explodes. broadcast "%event-entity% never got to see a new dimension.." """) .addSince("1.0") + .supplier(() -> new SimpleEvent("entity entering a portal")) .build()); syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Entity Tame") @@ -80,6 +118,7 @@ Called when an entity (usually a primed TNT or creeper) explodes. broadcast "Best friends for life!" """) .addSince("1.0") + .supplier(() -> new SimpleEvent("entity taming")) .build()); syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Entity Mount") @@ -93,6 +132,7 @@ Called when an entity (usually a primed TNT or creeper) explodes. cancel event """) .addSince("2.2-dev13b") + .supplier(() -> new SimpleEvent("entity mounting")) .build()); syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Entity Dismount") @@ -106,6 +146,7 @@ Called when an entity (usually a primed TNT or creeper) explodes. kill event-entity """) .addSince("2.2-dev13b") + .supplier(() -> new SimpleEvent("entity dismounting")) .build()); syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Entity Resurrect Attempt") @@ -125,6 +166,7 @@ Called when an entity (usually a primed TNT or creeper) explodes. send "You seem to be immortal.. how" to event-entity """) .addSince("2.2-dev28") + .supplier(() -> new SimpleEvent("entity resurrection attempt")) .build()); eventValueRegistry.register(EventValue.builder(EntityResurrectEvent.class, Slot.class) @@ -148,6 +190,7 @@ Called when an entity (usually a primed TNT or creeper) explodes. push event-entity up at speed 1 """) .addSince("2.7") + .supplier(() -> new SimpleEvent("entity jumping")) .build()); syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Entity Toggle Swim") @@ -163,6 +206,7 @@ Called when an entity (usually a primed TNT or creeper) explodes. cancel event """) .addSince("2.3") + .supplier(() -> new SimpleEvent("entity toggling swim")) .build()); // @@ -182,6 +226,7 @@ Called when an entity (usually a primed TNT or creeper) explodes. broadcast "No charged creepers in this world!" """) .addSince("1.0") + .supplier(() -> new SimpleEvent("creeper power")) .build()); syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Sheep Regrow Wool") @@ -194,6 +239,7 @@ Called when an entity (usually a primed TNT or creeper) explodes. send "Theres free wool nearby!" to loop-value """) .addSince("2.2-dev21") + .supplier(() -> new SimpleEvent("sheep regrowing wool")) .build()); syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Slime Split") @@ -208,6 +254,7 @@ Called when an entity (usually a primed TNT or creeper) explodes. broadcast "More slime minions have spawned!" """) .addSince("2.2-dev26") + .supplier(() -> new SimpleEvent("slime splitting")) .build()); syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Horse Jump") @@ -220,6 +267,7 @@ Called when an entity (usually a primed TNT or creeper) explodes. send "Wow that horse can really go high.." to (all players in radius 3 of event-entity) """) .addSince("2.5.1") + .supplier(() -> new SimpleEvent("horse jumping")) .build()); syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Piglin Barter") @@ -237,6 +285,7 @@ Called when an entity (usually a primed TNT or creeper) explodes. cancel event """) .addSince("2.10") + .supplier(() -> new SimpleEvent("piglin bartering")) .build()); syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Bat Toggle Sleep") @@ -249,6 +298,7 @@ Called when an entity (usually a primed TNT or creeper) explodes. broadcast "Another bat tried to sleep and perished.." """) .addSince("2.11") + .supplier(() -> new SimpleEvent("bat toggling sleep")) .build()); syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Villager Career Change") @@ -267,6 +317,7 @@ Called when an entity (usually a primed TNT or creeper) explodes. cancel event """) .addSince("2.12") + .supplier(() -> new SimpleEvent("villager career change")) .build()); eventValueRegistry.register(EventValue.builder(VillagerCareerChangeEvent.class, Villager.Profession.class) @@ -301,6 +352,7 @@ Called when an entity (usually a primed TNT or creeper) explodes. send "well you got lucky this time.." to event-player """) .addSince("2.9.0") + .supplier(() -> new SimpleEvent("enderman enrage")) .build()); eventValueRegistry.register(EventValue.builder(EndermanAttackPlayerEvent.class, Player.class) diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java index 67fb00f4c44..b1cf2616955 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java @@ -62,4 +62,4 @@ public String toString(@Nullable Event event, boolean debug) { .toString(); } -} \ No newline at end of file +} diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java index 08dac1042da..5b696b5fa33 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java @@ -7,10 +7,14 @@ import ch.njol.skript.lang.SkriptParser; import ch.njol.skript.lang.SyntaxStringBuilder; import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Projectile; import org.bukkit.event.Event; import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; import org.jetbrains.annotations.Nullable; +import org.skriptlang.skript.bukkit.lang.eventvalue.EventValue; +import org.skriptlang.skript.bukkit.lang.eventvalue.EventValueRegistry; import org.skriptlang.skript.bukkit.registration.BukkitSyntaxInfos; import org.skriptlang.skript.registration.SyntaxRegistry; @@ -18,7 +22,7 @@ public class EvtEntityDamage extends SkriptEvent { - public static void register(SyntaxRegistry syntaxRegistry) { + public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry eventValueRegistry) { syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(EvtEntityDamage.class, "Entity Damage") .supplier(EvtEntityDamage::new) .addEvent(EntityDamageEvent.class) @@ -40,6 +44,18 @@ public static void register(SyntaxRegistry syntaxRegistry) { """) .addSince("1.0, 2.7 (by entity)") .build()); + + eventValueRegistry.register(EventValue.builder(EntityDamageEvent.class, DamageCause.class) + .getter(EntityDamageEvent::getCause) + .build()); + + eventValueRegistry.register(EventValue.builder(EntityDamageByEntityEvent.class, Projectile.class) + .getter(event -> { + if (event.getDamager() instanceof Projectile projectile) + return projectile; + return null; + }) + .build()); } private EntityData[] byEntityData; diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDeath.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDeath.java index 1dfa17aabde..63eca8ef9a3 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDeath.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDeath.java @@ -8,9 +8,16 @@ import ch.njol.skript.lang.SyntaxStringBuilder; import ch.njol.skript.log.ErrorQuality; import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Projectile; import org.bukkit.event.Event; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; import org.bukkit.event.entity.EntityDeathEvent; +import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.Nullable; +import org.skriptlang.skript.bukkit.lang.eventvalue.EventValue; +import org.skriptlang.skript.bukkit.lang.eventvalue.EventValueRegistry; import org.skriptlang.skript.bukkit.registration.BukkitSyntaxInfos; import org.skriptlang.skript.registration.SyntaxRegistry; @@ -18,7 +25,7 @@ public class EvtEntityDeath extends SkriptEvent { - public static void register(SyntaxRegistry syntaxRegistry) { + public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry eventValueRegistry) { syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(EvtEntityDeath.class, "Entity Death") .supplier(EvtEntityDeath::new) .addEvent(EntityDeathEvent.class) @@ -38,6 +45,26 @@ Called when a living entity (including players) dies. """) .addSince("1.0") .build()); + + eventValueRegistry.register(EventValue.builder(EntityDeathEvent.class, ItemStack[].class) + .getter(event -> event.getDrops().toArray(new ItemStack[0])) + .build()); + + eventValueRegistry.register(EventValue.builder(EntityDeathEvent.class, Projectile.class) + .getter(event -> { + EntityDamageEvent damageEvent = event.getEntity().getLastDamageCause(); + if (damageEvent instanceof EntityDamageByEntityEvent entityEvent && entityEvent.getDamager() instanceof Projectile projectile) + return projectile; + return null; + }) + .build()); + + eventValueRegistry.register(EventValue.builder(EntityDeathEvent.class, DamageCause.class) + .getter(event -> { + EntityDamageEvent entityEvent = event.getEntity().getLastDamageCause(); + return entityEvent == null ? null : entityEvent.getCause(); + }) + .build()); } private EntityData[] entityData; diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityHeal.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityHeal.java new file mode 100644 index 00000000000..0a416b9fe82 --- /dev/null +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityHeal.java @@ -0,0 +1,88 @@ +package org.skriptlang.skript.bukkit.entity.elements.events; + +import ch.njol.skript.entity.EntityData; +import ch.njol.skript.lang.Literal; +import ch.njol.skript.lang.SkriptEvent; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.lang.SyntaxStringBuilder; +import org.bukkit.event.Event; +import org.bukkit.event.entity.EntityRegainHealthEvent; +import org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason; +import org.jetbrains.annotations.Nullable; +import org.skriptlang.skript.bukkit.lang.eventvalue.EventValue; +import org.skriptlang.skript.bukkit.lang.eventvalue.EventValueRegistry; +import org.skriptlang.skript.bukkit.registration.BukkitSyntaxInfos; +import org.skriptlang.skript.registration.SyntaxRegistry; + +import java.util.Arrays; + +public class EvtEntityHeal extends SkriptEvent { + + public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry eventValueRegistry) { + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(EvtEntityHeal.class, "Entity Heal") + .supplier(EvtEntityHeal::new) + .addEvent(EntityRegainHealthEvent.class) + .addPatterns( + "heal[ing] [of %-entitydatas%] [reason:(from|due to|by) %-healreasons%]", + "%entitydatas% heal[ing] [reason:(from|due to|by) %-healreasons%]" + ) + .addDescription(""" + Called when an entity is healed,\s + e.g. by eating (players),\s + being fed (pets),\s + or by the effect of a potion of healing (overworld mobs) or harm (nether mobs). + """) + .addExample(""" + on healing of a zombie, cow or a wither: + event-heal reason is healing potion + cancel event + """) + .addExample(""" + on player healing from a regeneration potion: + send "all better!" to event-entity + """) + .addSince("1.0, 2.9.0 (by reason)") + .build()); + + eventValueRegistry.register(EventValue.builder(EntityRegainHealthEvent.class, RegainReason.class) + .getter(EntityRegainHealthEvent::getRegainReason) + .build()); + } + + private EntityData[] entityData; + private RegainReason[] reasons; + + @Override + @SuppressWarnings("unchecked") + public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { + if (parseResult.hasTag("reason")) { + Literal reasonLiteral = (Literal) args[1]; + reasons = reasonLiteral.getArray(); + } + Literal> entityLiteral = (Literal>) args[0]; + entityData = entityLiteral.getArray(); + return true; + } + + @Override + public boolean check(Event event) { + EntityRegainHealthEvent entityEvent = (EntityRegainHealthEvent) event; + boolean entityMatched = true; + boolean reasonMatched = true; + if (entityData != null) + entityMatched = Arrays.stream(entityData).noneMatch(data -> data.isInstance(entityEvent.getEntity())); + if (reasons != null) + reasonMatched = Arrays.stream(reasons).noneMatch(reason -> reason == entityEvent.getRegainReason()); + return entityMatched && reasonMatched; + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return new SyntaxStringBuilder(event, debug) + .append(entityData != null ? entityData : "entity") + .append("healing") + .appendIf(reasons != null, "due to", reasons) + .toString(); + } + +} diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityLeash.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityLeash.java new file mode 100644 index 00000000000..df300dd7dd7 --- /dev/null +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityLeash.java @@ -0,0 +1,131 @@ +package org.skriptlang.skript.bukkit.entity.elements.events; + +import ch.njol.skript.entity.EntityData; +import ch.njol.skript.lang.Literal; +import ch.njol.skript.lang.SkriptEvent; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.lang.SyntaxStringBuilder; +import ch.njol.util.coll.CollectionUtils; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.entity.EntityUnleashEvent; +import org.bukkit.event.entity.EntityUnleashEvent.UnleashReason; +import org.bukkit.event.entity.PlayerLeashEntityEvent; +import org.bukkit.event.player.PlayerUnleashEntityEvent; +import org.jetbrains.annotations.Nullable; +import org.skriptlang.skript.bukkit.lang.eventvalue.EventValue; +import org.skriptlang.skript.bukkit.lang.eventvalue.EventValueRegistry; +import org.skriptlang.skript.bukkit.registration.BukkitSyntaxInfos; +import org.skriptlang.skript.registration.SyntaxRegistry; + +import java.util.Arrays; + +public class EvtEntityLeash extends SkriptEvent { + + public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry eventValueRegistry) { + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(EvtEntityLeash.class, "Entity Leash") + .supplier(EvtEntityLeash::new) + .addEvents(CollectionUtils.array(PlayerLeashEntityEvent.class, EntityUnleashEvent.class)) + .addPatterns("[:player] [:un]leash[ing] [entity:of %-entitydatas%]") + .addDescription(""" + Called when an entity is leashed or unleashed. + Cancelling these events will prevent the leashing or unleashing from occurring. + """) + .addExample(""" + on player leash of a sheep: + send "Baaaaa--" to player + """) + .addExample(""" + on player leash: + send "<%event-entity%> Let me go!" to player + """) + .addExample(""" + on unleash: + broadcast "<%event-entity%> I'm free!" + """) + .addSince("2.10") + .build()); + + eventValueRegistry.register(EventValue.builder(PlayerLeashEntityEvent.class, Player.class) + .getter(PlayerLeashEntityEvent::getPlayer) + .build()); + + eventValueRegistry.register(EventValue.builder(PlayerLeashEntityEvent.class, Entity.class) + .getter(PlayerLeashEntityEvent::getEntity) + .build()); + + eventValueRegistry.register(EventValue.builder(EntityUnleashEvent.class, UnleashReason.class) + .getter(EntityUnleashEvent::getReason) + .build()); + + eventValueRegistry.register(EventValue.builder(PlayerUnleashEntityEvent.class, Player.class) + .getter(PlayerUnleashEntityEvent::getPlayer) + .build()); + + } + + private enum EventType { + + LEASH("leash"), + UNLEASH("unleash"), + UNLEASH_BY_PLAYER("player unleash"); + + private final String name; + + EventType(String name) { + this.name = name; + } + + + @Override + public String toString() { + return name; + } + + } + + private @Nullable EntityData[] entityData; + private EventType eventType; + + @Override + @SuppressWarnings("unchecked") + public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { + if (parseResult.hasTag("entity")) { + Literal> entityLiteral = (Literal>) args[0]; + entityData = entityLiteral.getArray(); + } + eventType = EventType.LEASH; + if (parseResult.hasTag("un")) { + eventType = EventType.UNLEASH; + if (parseResult.hasTag("player")) + eventType = EventType.UNLEASH_BY_PLAYER; + } + return true; + } + + @Override + public boolean check(Event event) { + Entity leashedEntity = switch (eventType) { + case LEASH -> event instanceof PlayerLeashEntityEvent playerLeash ? playerLeash.getEntity() : null; + case UNLEASH -> event instanceof EntityUnleashEvent entityUnleash ? entityUnleash.getEntity() : null; + case UNLEASH_BY_PLAYER -> event instanceof PlayerUnleashEntityEvent playerUnleash ? playerUnleash.getEntity() : null; + }; + + if (leashedEntity == null) + return false; + if (entityData == null) + return true; + return Arrays.stream(entityData).anyMatch(entityData -> entityData.isInstance(leashedEntity)); + + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return new SyntaxStringBuilder(event, debug) + .append(eventType) + .appendIf(entityData != null, "of", entityData) + .toString(); + } + +} diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityMove.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityMove.java new file mode 100644 index 00000000000..cc0fc5d27d9 --- /dev/null +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityMove.java @@ -0,0 +1,230 @@ +package org.skriptlang.skript.bukkit.entity.elements.events; + +/*import ch.njol.skript.Skript; +import ch.njol.skript.entity.EntityData; +import ch.njol.skript.lang.Literal; +import ch.njol.skript.lang.SkriptEvent; +import ch.njol.skript.lang.SkriptParser; +import ch.njol.util.coll.CollectionUtils; +import io.papermc.paper.event.entity.EntityMoveEvent; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.player.PlayerMoveEvent; +import org.jetbrains.annotations.Nullable; + +public class EvtMove extends SkriptEvent { + + // TODO - remove this when Spigot support is dropped + private static final boolean HAS_ENTITY_MOVE = Skript.classExists("io.papermc.paper.event.entity.EntityMoveEvent"); + + static { + Class[] events; + if (HAS_ENTITY_MOVE) + events = CollectionUtils.array(PlayerMoveEvent.class, EntityMoveEvent.class); + else + events = CollectionUtils.array(PlayerMoveEvent.class); + Skript.registerEvent("Move / Rotate", ch.njol.skript.events.EvtMove.class, events, + "%entitydata% (move|walk|step|rotate:(turn[ing] around|rotate))", + "%entitydata% (move|walk|step) or (turn[ing] around|rotate)", + "%entitydata% (turn[ing] around|rotate) or (move|walk|step)") + .description( + "Called when a player or entity moves or rotates their head.", + "NOTE: Move event will only be called when the entity/player moves position, keyword 'turn around' is for orientation (ie: looking around), and the combined syntax listens for both.", + "NOTE: These events can be performance heavy as they are called quite often.") + .examples( + "on player move:", + "\tif player does not have permission \"player.can.move\":", + "\t\tcancel event", + "on skeleton move:", + "\tif event-entity is not in world \"world\":", + "\t\tkill event-entity", + "on player turning around:", + "\tsend action bar \"You are currently turning your head around!\" to player") + .since("2.6, 2.8.0 (turn around)"); + } + + private EntityData entityData; + private boolean isPlayer; + private boolean canBePlayer; + private ch.njol.skript.events.EvtMove.Move moveType; + + private enum Move { + + MOVE("move"), + MOVE_OR_ROTATE("move or rotate"), + ROTATE("rotate"); + + private final String name; + + Move(String name) { + this.name = name; + } + + @Override + public String toString() { + return name; + } + + } + + @Override + @SuppressWarnings("unchecked") + public boolean init(Literal[] args, int matchedPattern, SkriptParser.ParseResult parseResult) { + entityData = ((Literal>) args[0]).getSingle(); + isPlayer = Player.class.isAssignableFrom(entityData.getType()); + if (!HAS_ENTITY_MOVE && !isPlayer) { + Skript.error("Entity move event requires Paper"); + return false; + } + canBePlayer = entityData.getType().isAssignableFrom(Player.class); + if (matchedPattern > 0) { + moveType = ch.njol.skript.events.EvtMove.Move.MOVE_OR_ROTATE; + } else if (parseResult.hasTag("rotate")) { + moveType = ch.njol.skript.events.EvtMove.Move.ROTATE; + } else { + moveType = ch.njol.skript.events.EvtMove.Move.MOVE; + } + return true; + } + + @Override + public boolean check(Event event) { + Location from, to; + if (canBePlayer && event instanceof PlayerMoveEvent playerMoveEvent) { + from = playerMoveEvent.getFrom(); + to = playerMoveEvent.getTo(); + } else if (HAS_ENTITY_MOVE && event instanceof EntityMoveEvent entityMoveEvent) { + if (!(entityData.isInstance(entityMoveEvent.getEntity()))) + return false; + from = entityMoveEvent.getFrom(); + to = entityMoveEvent.getTo(); + } else { + return false; + } + return switch (moveType) { + case MOVE -> hasChangedPosition(from, to); + case ROTATE -> hasChangedOrientation(from, to); + case MOVE_OR_ROTATE -> true; + }; + } + + @Override + @SuppressWarnings("unchecked") + public Class [] getEventClasses() { + if (isPlayer) { + return new Class[] {PlayerMoveEvent.class}; + } else if (HAS_ENTITY_MOVE) { + if (canBePlayer) + return new Class[] {EntityMoveEvent.class, PlayerMoveEvent.class}; + return new Class[] {EntityMoveEvent.class}; + } + throw new IllegalStateException("This event has not yet initialized!"); + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return entityData + " " + moveType; + } + + private static boolean hasChangedPosition(Location from, Location to) { + return from.getX() != to.getX() || from.getY() != to.getY() || from.getZ() != to.getZ() || from.getWorld() != to.getWorld(); + } + + private static boolean hasChangedOrientation(Location from, Location to) { + return from.getYaw() != to.getYaw() || from.getPitch() != to.getPitch(); + } + +} + + */ +import ch.njol.skript.entity.EntityData; +import ch.njol.skript.lang.Literal; +import ch.njol.skript.lang.SkriptEvent; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.lang.SyntaxStringBuilder; +import ch.njol.util.coll.CollectionUtils; +import io.papermc.paper.event.entity.EntityMoveEvent; +import org.bukkit.event.Event; +import org.bukkit.event.entity.EntityRegainHealthEvent; +import org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason; +import org.bukkit.event.player.PlayerMoveEvent; +import org.jetbrains.annotations.Nullable; +import org.skriptlang.skript.bukkit.lang.eventvalue.EventValue; +import org.skriptlang.skript.bukkit.lang.eventvalue.EventValueRegistry; +import org.skriptlang.skript.bukkit.registration.BukkitSyntaxInfos; +import org.skriptlang.skript.registration.SyntaxRegistry; + +import java.util.Arrays; + +public class EvtEntityMove extends SkriptEvent { + + public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry eventValueRegistry) { + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(EvtEntityMove.class, "Entity Move / Rotate") + .supplier(EvtEntityMove::new) + .addEvents(CollectionUtils.array(EntityMoveEvent.class, PlayerMoveEvent.class)) + .addPatterns( + "%entitydata% (move|walk|step|rotate:(turn[ing] around|rotate))", + "%entitydata% (move|walk|step) or (turn[ing] around|rotate)", + "%entitydata% (turn[ing] around|rotate) or (move|walk|step)" + ) + .addDescription(""" + Called when a player or entity moves or rotates their head. + The move event will only be called when the entity/player moves position,\s + keyword 'turn around' is for orientation (ie: looking around),\s + and the combined syntax listens for both. + Note that this event is called extremely often and may cause performance issues. + """) + .addExample(""" + on healing of a zombie, cow or a wither: + event-heal reason is healing potion + cancel event + """) + .addExample(""" + on player healing from a regeneration potion: + send "all better!" to event-entity + """) + .addSince("2.6, 2.8.0 (turn around)") + .build()); + + eventValueRegistry.register(EventValue.builder(EntityRegainHealthEvent.class, RegainReason.class) + .getter(EntityRegainHealthEvent::getRegainReason) + .build()); + } + + private EntityData[] entityData; + private RegainReason[] reasons; + + @Override + @SuppressWarnings("unchecked") + public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { + if (parseResult.hasTag("reason")) { + Literal reasonLiteral = (Literal) args[1]; + reasons = reasonLiteral.getArray(); + } + Literal> entityLiteral = (Literal>) args[0]; + entityData = entityLiteral.getArray(); + return true; + } + + @Override + public boolean check(Event event) { + return true; + } + + @Override + @SuppressWarnings("unchecked") + public Class [] getEventClasses() { + return null; + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return new SyntaxStringBuilder(event, debug) + .append(entityData != null ? entityData : "entity") + .append("healing") + .appendIf(reasons != null, "due to", reasons) + .toString(); + } + +} diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityPortal.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityPortal.java new file mode 100644 index 00000000000..a165644334b --- /dev/null +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityPortal.java @@ -0,0 +1,63 @@ +package org.skriptlang.skript.bukkit.entity.elements.events; + +import ch.njol.skript.lang.Literal; +import ch.njol.skript.lang.SkriptEvent; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.lang.SyntaxStringBuilder; +import ch.njol.util.coll.CollectionUtils; +import org.bukkit.event.Event; +import org.bukkit.event.entity.EntityPortalEvent; +import org.bukkit.event.player.PlayerPortalEvent; +import org.jetbrains.annotations.Nullable; +import org.skriptlang.skript.bukkit.registration.BukkitSyntaxInfos; +import org.skriptlang.skript.registration.SyntaxRegistry; + +public class EvtEntityPortal extends SkriptEvent { + + public static void register(SyntaxRegistry syntaxRegistry) { + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(EvtEntityPortal.class, "Entity/Player Portal") + .supplier(EvtEntityPortal::new) + .addEvents(CollectionUtils.array(PlayerPortalEvent.class, EntityPortalEvent.class)) + .addPatterns("[player] portal", "entity portal") + .addDescription(""" + Called when a player or an entity uses a nether or end portal. + Note that 'on entity portal' event does not apply to players. + Use Cancel the event to prevent the entity from teleporting. + """) + .addExample(""" + on portal: + broadcast "An entity has entered a portal!" + """) + .addExample(""" + on player portal: + player's world is world("wilderness") + set world of event-location to player's world + add 9000 to x-pos of event-location + """) + .addSince("1.0, 2.5.3 (entities), 2.13 (location changers)") + .build()); + } + + private boolean isPlayer; + + @Override + public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { + isPlayer = matchedPattern == 0; + return true; + } + + @Override + public boolean check(Event event) { + if (isPlayer) + return event instanceof PlayerPortalEvent; + return event instanceof EntityPortalEvent; + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return new SyntaxStringBuilder(event, debug) + .append(isPlayer ? "player" : "entity", "portal") + .toString(); + } + +} diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTeleport.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTeleport.java new file mode 100644 index 00000000000..03bcf3ec7dd --- /dev/null +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTeleport.java @@ -0,0 +1,105 @@ +package org.skriptlang.skript.bukkit.entity.elements.events; + +import ch.njol.skript.classes.Changer.ChangeMode; +import ch.njol.util.coll.CollectionUtils; +import org.bukkit.Location; +import org.bukkit.event.entity.EntityTeleportEvent; +import org.bukkit.event.player.PlayerTeleportEvent; +import ch.njol.skript.entity.EntityData; +import org.jetbrains.annotations.Nullable; +import ch.njol.skript.lang.Literal; +import ch.njol.skript.lang.SkriptEvent; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.lang.SyntaxStringBuilder; +import org.bukkit.event.Event; +import org.skriptlang.skript.bukkit.lang.eventvalue.EventValue; +import org.skriptlang.skript.bukkit.lang.eventvalue.EventValue.Time; +import org.skriptlang.skript.bukkit.lang.eventvalue.EventValueRegistry; +import org.skriptlang.skript.bukkit.registration.BukkitSyntaxInfos; +import org.skriptlang.skript.registration.SyntaxRegistry; + +import java.util.Arrays; + +public class EvtEntityTeleport extends SkriptEvent { + + public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry eventValueRegistry) { + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(EvtEntityTeleport.class, "Entity Teleport") + .supplier(EvtEntityTeleport::new) + .addEvents(CollectionUtils.array(EntityTeleportEvent.class, PlayerTeleportEvent.class)) + .addPatterns("[entity:%-entitydatas%] teleport[ing]") + .addDescription(""" + Called when an entity teleports including players. + This event will also be called due to a result of natural causes,\s + such as an enderman or shulker teleporting, + or wolves teleporting to players.\s + When teleporting players, the event can be called by teleporting through a nether/end portal,\s + or by other means (e.g. plugins). + """) + .addExample(""" + on player teleport: + send "Well you somehow teleported.." to player + """) + .addExample(""" + on wolf teleport: + send "Your wolf just teleported!" to owner of event-entity + """) + .addSince("1.0, 2.9.0 (entity teleport)") + .build()); + + eventValueRegistry.register(EventValue.builder(PlayerTeleportEvent.class, Location.class) + .getter(PlayerTeleportEvent::getFrom) + .registerChanger(ChangeMode.SET, PlayerTeleportEvent::setFrom) + .time(Time.PAST) + .build()); + + eventValueRegistry.register(EventValue.builder(PlayerTeleportEvent.class, Location.class) + .getter(PlayerTeleportEvent::getTo) + .registerChanger(ChangeMode.SET, PlayerTeleportEvent::setTo) + .build()); + + eventValueRegistry.register(EventValue.builder(EntityTeleportEvent.class, Location.class) + .getter(EntityTeleportEvent::getFrom) + .registerChanger(ChangeMode.SET, EntityTeleportEvent::setFrom) + .time(Time.PAST) + .build()); + + eventValueRegistry.register(EventValue.builder(EntityTeleportEvent.class, Location.class) + .getter(EntityTeleportEvent::getTo) + .registerChanger(ChangeMode.SET, EntityTeleportEvent::setTo) + .build()); + } + + private EntityData[] entityData; + + @Override + @SuppressWarnings("unchecked") + public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { + if (parseResult.hasTag("entity")) { + Literal> entityLiteral = (Literal>) args[0]; + entityData = entityLiteral.getArray(); + } + return true; + } + + @Override + public boolean check(Event event) { + if (entityData == null) + return true; + if (event instanceof EntityTeleportEvent entityEvent) { + return Arrays.stream(entityData).anyMatch(entity -> entity.isInstance(entityEvent.getEntity())); + } else if (event instanceof PlayerTeleportEvent playerEvent) { + return Arrays.stream(entityData).anyMatch(player -> player.isInstance(playerEvent.getPlayer())); + } + return false; + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return new SyntaxStringBuilder(event, debug) + .appendIf(entityData != null, (Object) entityData) + .append("teleporting") + .toString(); + } + +} + diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtExperienceSpawn.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtExperienceSpawn.java index 0ed92bf6eaa..0c2bffd8804 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtExperienceSpawn.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtExperienceSpawn.java @@ -1,74 +1,97 @@ package org.skriptlang.skript.bukkit.entity.elements.events; -import ch.njol.skript.entity.EntityData; +import ch.njol.skript.Skript; +import ch.njol.skript.SkriptConfig; +import ch.njol.skript.SkriptEventHandler; +import ch.njol.skript.events.bukkit.ExperienceSpawnEvent; import ch.njol.skript.lang.Literal; import ch.njol.skript.lang.SkriptEvent; import ch.njol.skript.lang.SkriptParser.ParseResult; -import ch.njol.skript.lang.SyntaxStringBuilder; -import org.bukkit.entity.Entity; +import ch.njol.skript.lang.Trigger; +import ch.njol.skript.util.Experience; +import org.bukkit.Bukkit; +import org.bukkit.Location; import org.bukkit.event.Event; -import org.bukkit.event.entity.EntityTransformEvent; -import org.bukkit.event.entity.EntityTransformEvent.TransformReason; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockExpEvent; +import org.bukkit.event.entity.EntityDeathEvent; +import org.bukkit.event.entity.ExpBottleEvent; +import org.bukkit.event.player.PlayerFishEvent; +import org.bukkit.plugin.EventExecutor; import org.jetbrains.annotations.Nullable; import org.skriptlang.skript.bukkit.lang.eventvalue.EventValue; import org.skriptlang.skript.bukkit.lang.eventvalue.EventValueRegistry; import org.skriptlang.skript.bukkit.registration.BukkitSyntaxInfos; import org.skriptlang.skript.registration.SyntaxRegistry; -import java.util.Arrays; +import java.util.*; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.BiConsumer; +import java.util.function.Function; -/* public class EvtExperienceSpawn extends SkriptEvent { - static { - Skript.registerEvent("Experience Spawn", EvtExperienceSpawn.class, ExperienceSpawnEvent.class, + public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry eventValueRegistry) { + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(EvtExperienceSpawn.class, "Experience Spawn") + .supplier(EvtExperienceSpawn::new) + .addEvent(ExperienceSpawnEvent.class) + .addPatterns( "[e]xp[erience] [orb] spawn", "spawn of [a[n]] [e]xp[erience] [orb]" - ).description( - "Called whenever experience is about to spawn.", - "Please note that this event will not fire for xp orbs spawned by plugins (including Skript) with Bukkit." - ).examples( - "on xp spawn:", - "\tworld is \"minigame_world\"", - "\tcancel event" - ).since("2.0"); - EventValues.registerEventValue(ExperienceSpawnEvent.class, Location.class, ExperienceSpawnEvent::getLocation); - EventValues.registerEventValue(ExperienceSpawnEvent.class, Experience.class, event -> new Experience(event.getSpawnedXP())); + ) + .addDescription(""" + Called whenever experience is about to spawn. + Please note that this event will not fire for xp orbs spawned by plugins (including Skript) with Bukkit. + """) + .addExample(""" + on xp spawn: + event-world is not world("experience") + cancel event + """) + .addSince("2.0") + .build()); + + eventValueRegistry.register(EventValue.builder(ExperienceSpawnEvent.class, Location.class) + .getter(ExperienceSpawnEvent::getLocation) + .build()); + + eventValueRegistry.register(EventValue.builder(ExperienceSpawnEvent.class, Experience.class) + .getter(event -> new Experience(event.getSpawnedXP())) + .build()); + + trackEvent(BlockExpEvent.class, BlockExpEvent::getExpToDrop, BlockExpEvent::setExpToDrop, blockEvent -> blockEvent.getBlock().getLocation().add(0.5, 0.5, 0.5)); + trackEvent(EntityDeathEvent.class, EntityDeathEvent::getDroppedExp, EntityDeathEvent::setDroppedExp, entityEvent -> entityEvent.getEntity().getLocation()); + trackEvent(ExpBottleEvent.class, ExpBottleEvent::getExperience, ExpBottleEvent::setExperience, entityEvent -> entityEvent.getEntity().getLocation()); + trackEvent(PlayerFishEvent.class, PlayerFishEvent::getExpToDrop, PlayerFishEvent::setExpToDrop, playerEvent -> playerEvent.getPlayer().getLocation()); } private static final List TRIGGERS = Collections.synchronizedList(new ArrayList<>()); - private static final AtomicBoolean REGISTERED_EXECUTORS = new AtomicBoolean(); + private static final Map, EventDetails> TRACKED_EVENTS = new HashMap<>(); + + public static void trackEvent(Class event, + Function getExp, + @Nullable BiConsumer setExp, + Function getLocation) { + //noinspection unchecked + TRACKED_EVENTS.put(event, (EventDetails) new EventDetails<>(getExp, setExp, getLocation)); + } + + public record EventDetails(Function getExp, + @Nullable BiConsumer setExp, + Function getLocation) { + } private static final EventExecutor EXECUTOR = (listener, event) -> { - ExperienceSpawnEvent experienceEvent; - if (event instanceof BlockExpEvent) { - experienceEvent = new ExperienceSpawnEvent( - ((BlockExpEvent) event).getExpToDrop(), - ((BlockExpEvent) event).getBlock().getLocation().add(0.5, 0.5, 0.5) - ); - } else if (event instanceof EntityDeathEvent) { - experienceEvent = new ExperienceSpawnEvent( - ((EntityDeathEvent) event).getDroppedExp(), - ((EntityDeathEvent) event).getEntity().getLocation() - ); - } else if (event instanceof ExpBottleEvent) { - experienceEvent = new ExperienceSpawnEvent( - ((ExpBottleEvent) event).getExperience(), - ((ExpBottleEvent) event).getEntity().getLocation() - ); - } else if (event instanceof PlayerFishEvent) { - if (((PlayerFishEvent) event).getState() != PlayerFishEvent.State.CAUGHT_FISH) // There is no EXP - return; - experienceEvent = new ExperienceSpawnEvent( - ((PlayerFishEvent) event).getExpToDrop(), - ((PlayerFishEvent) event).getPlayer().getLocation() - ); - } else { - assert false; + EventDetails details = TRACKED_EVENTS.get(event.getClass()); + if (details == null) return; - } + ExperienceSpawnEvent experienceEvent = new ExperienceSpawnEvent( + details.getExp().apply(event), + details.getLocation().apply(event) + ); SkriptEventHandler.logEventStart(event); synchronized (TRIGGERS) { @@ -83,15 +106,8 @@ public class EvtExperienceSpawn extends SkriptEvent { if (experienceEvent.isCancelled()) experienceEvent.setSpawnedXP(0); - if (event instanceof BlockExpEvent) { - ((BlockExpEvent) event).setExpToDrop(experienceEvent.getSpawnedXP()); - } else if (event instanceof EntityDeathEvent) { - ((EntityDeathEvent) event).setDroppedExp(experienceEvent.getSpawnedXP()); - } else if (event instanceof ExpBottleEvent) { - ((ExpBottleEvent) event).setExperience(experienceEvent.getSpawnedXP()); - } else if (event instanceof PlayerFishEvent) { - ((PlayerFishEvent) event).setExpToDrop(experienceEvent.getSpawnedXP()); - } + if (details.setExp() != null) + details.setExp().accept(event, experienceEvent.getSpawnedXP()); }; @Override @@ -104,9 +120,9 @@ public boolean postLoad() { TRIGGERS.add(trigger); if (REGISTERED_EXECUTORS.compareAndSet(false, true)) { EventPriority priority = SkriptConfig.defaultEventPriority.value(); - //noinspection unchecked - for (Class clazz : new Class[]{BlockExpEvent.class, EntityDeathEvent.class, ExpBottleEvent.class, PlayerFishEvent.class}) - Bukkit.getPluginManager().registerEvent(clazz, new Listener(){}, priority, EXECUTOR, Skript.getInstance(), true); + for (Class clazz : TRACKED_EVENTS.keySet()) + Bukkit.getPluginManager().registerEvent(clazz, new Listener() { + }, priority, EXECUTOR, Skript.getInstance(), true); } return true; } @@ -131,75 +147,4 @@ public String toString(@Nullable Event event, boolean debug) { return "experience spawn"; } -} - */ -public class EvtExperienceSpawn extends SkriptEvent { - - public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry eventValueRegistry) { - syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(EvtEntityTransform.class, "Entity Transform") - .supplier(EvtEntityTransform::new) - .addEvent(EntityTransformEvent.class) - .addPatterns("[entity:%*-entitydatas%] transform[ing] [transform: due to %-transformreasons%]") - .addDescription(""" - Called when an entity is about to be replaced by another entity. - e.g. when a zombie gets cured and a villager spawns,\s - an entity drowns in water like a zombie that turns to a drown,\s - an entity that gets frozen in powder snow,\s - a mooshroom that when sheared, spawns a new cow. - """) - .addExample(""" - on a zombie transforming due to curing: - broadcast "Another one cured from this madness.." - """) - .addExample(""" - on mooshroom transforming: - cancel event - broadcast "forever a mooshroom!" - """) - .addSince("2.8.0") - .build()); - - eventValueRegistry.register(EventValue.builder(EntityTransformEvent.class, Entity[].class) - .getter(event -> event.getTransformedEntities().toArray(Entity[]::new)) - .build()); - - eventValueRegistry.register(EventValue.builder(EntityTransformEvent.class, TransformReason.class) - .getter(EntityTransformEvent::getTransformReason) - .build()); - } - - private EntityData[] entityData; - private TransformReason[] reasons; - - @Override - @SuppressWarnings("unchecked") - public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { - if (parseResult.hasTag("transform")) { - Literal transformLiteral = (Literal) args[1]; - reasons = transformLiteral.getArray(); - } - if (parseResult.hasTag("entity")) { - Literal> entityLiteral = (Literal>) args[0]; - entityData = entityLiteral.getArray(); - } - return true; - } - - @Override - public boolean check(Event event) { - EntityTransformEvent entityEvent = (EntityTransformEvent) event; - boolean reasonMatched = reasons == null || Arrays.stream(reasons).anyMatch(reason -> reason == entityEvent.getTransformReason()); - boolean entityDataMatched = entityData == null || Arrays.stream(entityData).anyMatch(data -> data.isInstance(entityEvent.getEntity())); - return reasonMatched && entityDataMatched; - } - - @Override - public String toString(@Nullable Event event, boolean debug) { - return new SyntaxStringBuilder(event, debug) - .append(entityData != null ? entityData : "entity") - .append("transforming") - .appendIf(reasons != null, "due to", reasons) - .toString(); - } - } From 975a8337534c177cb4e70a8ba7390551c69d6dd1 Mon Sep 17 00:00:00 2001 From: OwlBe Date: Thu, 2 Jul 2026 02:54:45 -0400 Subject: [PATCH 11/35] small stuff --- .../classes/data/BukkitEventValues.java | 7 - .../skript/bukkit/BukkitModule.java | 23 ++ .../skript/bukkit/entity/EntityModule.java | 44 ++-- .../entity/elements/events/EvtEntityMove.java | 228 +++++++----------- 4 files changed, 126 insertions(+), 176 deletions(-) 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 38b47c7f041..b6571ebf2aa 100644 --- a/src/main/java/ch/njol/skript/classes/data/BukkitEventValues.java +++ b/src/main/java/ch/njol/skript/classes/data/BukkitEventValues.java @@ -540,13 +540,6 @@ else if (hand == EquipmentSlot.OFF_HAND) //PlayerTeleportEvent registry.register(EventValue.simple(PlayerTeleportEvent.class, TeleportCause.class, PlayerTeleportEvent::getCause)); //EntityMoveEvent - if (Skript.classExists("io.papermc.paper.event.entity.EntityMoveEvent")) { - registry.register(EventValue.simple(EntityMoveEvent.class, Location.class, EntityMoveEvent::getFrom)); - registry.register(EventValue.builder(EntityMoveEvent.class, Location.class) - .getter(EntityMoveEvent::getTo) - .time(Time.FUTURE) - .build()); - } //CreatureSpawnEvent registry.register(EventValue.simple(CreatureSpawnEvent.class, SpawnReason.class, CreatureSpawnEvent::getSpawnReason)); //PlayerRespawnEvent - 1.21.5+ added AbstractRespawnEvent as a base class, where prior to that, getRespawnReason was in PlayerRespawnEvent diff --git a/src/main/java/org/skriptlang/skript/bukkit/BukkitModule.java b/src/main/java/org/skriptlang/skript/bukkit/BukkitModule.java index b1e42eadc10..7bf84c9ee0d 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/BukkitModule.java +++ b/src/main/java/org/skriptlang/skript/bukkit/BukkitModule.java @@ -2,6 +2,7 @@ import ch.njol.skript.Skript; import ch.njol.skript.registrations.Classes; +import org.bukkit.event.Event; import org.skriptlang.skript.addon.AddonModule; import org.skriptlang.skript.addon.HierarchicalAddonModule; import org.skriptlang.skript.addon.SkriptAddon; @@ -14,6 +15,7 @@ import org.skriptlang.skript.bukkit.input.InputModule; import org.skriptlang.skript.bukkit.item.ItemModule; import org.skriptlang.skript.bukkit.itemcomponents.ItemComponentModule; +import org.skriptlang.skript.bukkit.lang.eventvalue.EventValueRegistry; import org.skriptlang.skript.bukkit.loottables.LootTableModule; import org.skriptlang.skript.bukkit.misc.MiscModule; import org.skriptlang.skript.bukkit.particles.ParticleModule; @@ -22,6 +24,8 @@ import org.skriptlang.skript.bukkit.tags.TagModule; import org.skriptlang.skript.bukkit.text.TextModule; import org.skriptlang.skript.bukkit.types.*; +import org.skriptlang.skript.docs.Origin; +import org.skriptlang.skript.registration.SyntaxRegistry; import java.util.List; @@ -74,6 +78,25 @@ protected void loadSelf(SkriptAddon addon) { // nothing to do } + /** + * Helper method that calls the given methods with a {@link SyntaxRegistry} and {@link EventValueRegistry} + * @param syntaxRegistry The syntax registry to register with. + * @param eventValueRegistry The event value registry to register with. + * @param functions A series of consumers to call the register syntax. + */ + public static void register(SyntaxRegistry syntaxRegistry,EventValueRegistry eventValueRegistry, EventRegistrar... functions) { + for (EventRegistrar value : functions) + value.register(syntaxRegistry, eventValueRegistry); + } + + /** + * A method of registration via a {@link SyntaxRegistry} and {@link EventValueRegistry} + */ + @FunctionalInterface + public interface EventRegistrar { + void register(SyntaxRegistry syntaxRegistry, EventValueRegistry eventValueRegistry); + } + @Override public String name() { return "bukkit"; diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/EntityModule.java b/src/main/java/org/skriptlang/skript/bukkit/entity/EntityModule.java index 7b58f1f4c87..3b427e45f9c 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/EntityModule.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/EntityModule.java @@ -6,6 +6,7 @@ import org.skriptlang.skript.addon.AddonModule; import org.skriptlang.skript.addon.HierarchicalAddonModule; import org.skriptlang.skript.addon.SkriptAddon; +import org.skriptlang.skript.bukkit.BukkitModule; import org.skriptlang.skript.bukkit.entity.displays.DisplayModule; import org.skriptlang.skript.bukkit.entity.elements.EntityEvents; import org.skriptlang.skript.bukkit.entity.elements.events.*; @@ -15,7 +16,6 @@ import org.skriptlang.skript.bukkit.entity.entitydata.ZombieNautilusData; import org.skriptlang.skript.bukkit.entity.player.PlayerModule; import org.skriptlang.skript.bukkit.lang.eventvalue.EventValueRegistry; -import org.skriptlang.skript.registration.SyntaxRegistry; import java.util.List; @@ -41,30 +41,30 @@ protected void loadSelf(SkriptAddon addon) { SimpleEntityData.addSuperEntity("any nautilus", AbstractNautilus.class); } - register(addon, - ExprDeathMessage::register - ); - EventValueRegistry eventValueRegistry = addon.registry(EventValueRegistry.class); - SyntaxRegistry syntaxRegistry = moduleRegistry(addon); - - EntityEvents.register(syntaxRegistry, eventValueRegistry); - EvtEntityBlockChange.register(syntaxRegistry, eventValueRegistry); - EvtEntityBreakDoor.register(syntaxRegistry); - EvtEntityDamage.register(syntaxRegistry, eventValueRegistry); - EvtEntityDeath.register(syntaxRegistry, eventValueRegistry); - EvtEntityHeal.register(syntaxRegistry, eventValueRegistry); - EvtEntityLeash.register(syntaxRegistry, eventValueRegistry); - EvtEntityPortal.register(syntaxRegistry); - EvtEntityShootBow.register(syntaxRegistry, eventValueRegistry); - EvtEntitySpawn.register(syntaxRegistry); - EvtEntityTarget.register(syntaxRegistry); - EvtEntityTeleport.register(syntaxRegistry, eventValueRegistry); - EvtEntityTransform.register(syntaxRegistry, eventValueRegistry); - EvtExperienceSpawn.register(syntaxRegistry, eventValueRegistry); - EvtFireworkExplode.register(syntaxRegistry, eventValueRegistry); + BukkitModule.register(addon.syntaxRegistry(), eventValueRegistry, + EntityEvents::register, + EvtEntityBlockChange::register, + EvtEntityDamage::register, + EvtEntityDeath::register, + EvtEntityHeal::register, + EvtEntityLeash::register, + EvtEntityMove::register, + EvtEntityShootBow::register, + EvtEntityTeleport::register, + EvtEntityTransform::register, + EvtExperienceSpawn::register, + EvtFireworkExplode::register + ); + register(addon, + EvtEntityBreakDoor::register, + EvtEntityPortal::register, + EvtEntitySpawn::register, + EvtEntityTarget::register, + ExprDeathMessage::register + ); } @Override diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityMove.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityMove.java index cc0fc5d27d9..2c4cdff7340 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityMove.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityMove.java @@ -1,10 +1,9 @@ package org.skriptlang.skript.bukkit.entity.elements.events; -/*import ch.njol.skript.Skript; import ch.njol.skript.entity.EntityData; import ch.njol.skript.lang.Literal; import ch.njol.skript.lang.SkriptEvent; -import ch.njol.skript.lang.SkriptParser; +import ch.njol.skript.lang.SkriptParser.ParseResult; import ch.njol.util.coll.CollectionUtils; import io.papermc.paper.event.entity.EntityMoveEvent; import org.bukkit.Location; @@ -12,45 +11,66 @@ import org.bukkit.event.Event; import org.bukkit.event.player.PlayerMoveEvent; import org.jetbrains.annotations.Nullable; +import org.skriptlang.skript.bukkit.lang.eventvalue.EventValue; +import org.skriptlang.skript.bukkit.lang.eventvalue.EventValue.Time; +import org.skriptlang.skript.bukkit.lang.eventvalue.EventValueRegistry; +import org.skriptlang.skript.bukkit.registration.BukkitSyntaxInfos; +import org.skriptlang.skript.registration.SyntaxRegistry; -public class EvtMove extends SkriptEvent { - - // TODO - remove this when Spigot support is dropped - private static final boolean HAS_ENTITY_MOVE = Skript.classExists("io.papermc.paper.event.entity.EntityMoveEvent"); +public class EvtEntityMove extends SkriptEvent { - static { - Class[] events; - if (HAS_ENTITY_MOVE) - events = CollectionUtils.array(PlayerMoveEvent.class, EntityMoveEvent.class); - else - events = CollectionUtils.array(PlayerMoveEvent.class); - Skript.registerEvent("Move / Rotate", ch.njol.skript.events.EvtMove.class, events, + public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry eventValueRegistry) { + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(EvtEntityMove.class, "Entity Move / Rotate") + .supplier(EvtEntityMove::new) + .addEvents(CollectionUtils.array(EntityMoveEvent.class, PlayerMoveEvent.class)) + .addPatterns( "%entitydata% (move|walk|step|rotate:(turn[ing] around|rotate))", "%entitydata% (move|walk|step) or (turn[ing] around|rotate)", - "%entitydata% (turn[ing] around|rotate) or (move|walk|step)") - .description( - "Called when a player or entity moves or rotates their head.", - "NOTE: Move event will only be called when the entity/player moves position, keyword 'turn around' is for orientation (ie: looking around), and the combined syntax listens for both.", - "NOTE: These events can be performance heavy as they are called quite often.") - .examples( - "on player move:", - "\tif player does not have permission \"player.can.move\":", - "\t\tcancel event", - "on skeleton move:", - "\tif event-entity is not in world \"world\":", - "\t\tkill event-entity", - "on player turning around:", - "\tsend action bar \"You are currently turning your head around!\" to player") - .since("2.6, 2.8.0 (turn around)"); + "%entitydata% (turn[ing] around|rotate) or (move|walk|step)" + ) + .addDescription(""" + Called when a player or entity moves or rotates their head. + The move event will only be called when the entity/player moves position, + keyword 'turn around' is for orientation (ie: looking around), + and the combined syntax listens for both. + Note that this event is called extremely often and may cause performance issues. + """) + .addExample(""" + on player move: + if {frozen::%player's uuid%} is set: + cancel event + send actionbar "You are frozen!" to player + // Generally not recommended over setting movement & jump attributes but useful for older servers + """) + .addExample(""" + on player turning around: + send "BOO!" to player + spawn skeleton behind player + """) + .addExample(""" + on skeleton move: + if event-world is "no_skeleton_movement": + cancel event + """) + .addSince("2.6, 2.8.0 (turn around)") + .build()); + + eventValueRegistry.register(EventValue.builder(EntityMoveEvent.class, Location.class) + .getter(EntityMoveEvent::getFrom) + .build()); + + eventValueRegistry.register(EventValue.builder(EntityMoveEvent.class, Location.class) + .getter(EntityMoveEvent::getTo) + .time(Time.FUTURE) + .build()); } private EntityData entityData; private boolean isPlayer; private boolean canBePlayer; - private ch.njol.skript.events.EvtMove.Move moveType; + private Move moveType; private enum Move { - MOVE("move"), MOVE_OR_ROTATE("move or rotate"), ROTATE("rotate"); @@ -65,25 +85,20 @@ private enum Move { public String toString() { return name; } - } @Override @SuppressWarnings("unchecked") - public boolean init(Literal[] args, int matchedPattern, SkriptParser.ParseResult parseResult) { + public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { entityData = ((Literal>) args[0]).getSingle(); isPlayer = Player.class.isAssignableFrom(entityData.getType()); - if (!HAS_ENTITY_MOVE && !isPlayer) { - Skript.error("Entity move event requires Paper"); - return false; - } canBePlayer = entityData.getType().isAssignableFrom(Player.class); if (matchedPattern > 0) { - moveType = ch.njol.skript.events.EvtMove.Move.MOVE_OR_ROTATE; + moveType = Move.MOVE_OR_ROTATE; } else if (parseResult.hasTag("rotate")) { - moveType = ch.njol.skript.events.EvtMove.Move.ROTATE; + moveType = Move.ROTATE; } else { - moveType = ch.njol.skript.events.EvtMove.Move.MOVE; + moveType = Move.MOVE; } return true; } @@ -91,14 +106,14 @@ public boolean init(Literal[] args, int matchedPattern, SkriptParser.ParseRes @Override public boolean check(Event event) { Location from, to; - if (canBePlayer && event instanceof PlayerMoveEvent playerMoveEvent) { - from = playerMoveEvent.getFrom(); - to = playerMoveEvent.getTo(); - } else if (HAS_ENTITY_MOVE && event instanceof EntityMoveEvent entityMoveEvent) { - if (!(entityData.isInstance(entityMoveEvent.getEntity()))) + if (canBePlayer && event instanceof PlayerMoveEvent playerEvent) { + from = playerEvent.getFrom(); + to = playerEvent.getTo(); + } else if (event instanceof EntityMoveEvent entityEvent) { + if (!(entityData.isInstance(entityEvent.getEntity()))) return false; - from = entityMoveEvent.getFrom(); - to = entityMoveEvent.getTo(); + from = entityEvent.getFrom(); + to = entityEvent.getTo(); } else { return false; } @@ -109,122 +124,41 @@ public boolean check(Event event) { }; } - @Override - @SuppressWarnings("unchecked") - public Class [] getEventClasses() { - if (isPlayer) { - return new Class[] {PlayerMoveEvent.class}; - } else if (HAS_ENTITY_MOVE) { - if (canBePlayer) - return new Class[] {EntityMoveEvent.class, PlayerMoveEvent.class}; - return new Class[] {EntityMoveEvent.class}; - } - throw new IllegalStateException("This event has not yet initialized!"); - } - - @Override - public String toString(@Nullable Event event, boolean debug) { - return entityData + " " + moveType; - } - + /** + * Checks if the from location is different from the to location. + * @param from The location from. + * @param to The location to. + * @return Whether from matches to. + */ private static boolean hasChangedPosition(Location from, Location to) { return from.getX() != to.getX() || from.getY() != to.getY() || from.getZ() != to.getZ() || from.getWorld() != to.getWorld(); } + + /** + * Checks if the yaw and pitch of from is different from the yaw and pitch of to. + * @param from The location from. + * @param to The location to. + * @return Whether the orientation has changed or not. + */ private static boolean hasChangedOrientation(Location from, Location to) { return from.getYaw() != to.getYaw() || from.getPitch() != to.getPitch(); } -} - - */ -import ch.njol.skript.entity.EntityData; -import ch.njol.skript.lang.Literal; -import ch.njol.skript.lang.SkriptEvent; -import ch.njol.skript.lang.SkriptParser.ParseResult; -import ch.njol.skript.lang.SyntaxStringBuilder; -import ch.njol.util.coll.CollectionUtils; -import io.papermc.paper.event.entity.EntityMoveEvent; -import org.bukkit.event.Event; -import org.bukkit.event.entity.EntityRegainHealthEvent; -import org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason; -import org.bukkit.event.player.PlayerMoveEvent; -import org.jetbrains.annotations.Nullable; -import org.skriptlang.skript.bukkit.lang.eventvalue.EventValue; -import org.skriptlang.skript.bukkit.lang.eventvalue.EventValueRegistry; -import org.skriptlang.skript.bukkit.registration.BukkitSyntaxInfos; -import org.skriptlang.skript.registration.SyntaxRegistry; - -import java.util.Arrays; - -public class EvtEntityMove extends SkriptEvent { - - public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry eventValueRegistry) { - syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(EvtEntityMove.class, "Entity Move / Rotate") - .supplier(EvtEntityMove::new) - .addEvents(CollectionUtils.array(EntityMoveEvent.class, PlayerMoveEvent.class)) - .addPatterns( - "%entitydata% (move|walk|step|rotate:(turn[ing] around|rotate))", - "%entitydata% (move|walk|step) or (turn[ing] around|rotate)", - "%entitydata% (turn[ing] around|rotate) or (move|walk|step)" - ) - .addDescription(""" - Called when a player or entity moves or rotates their head. - The move event will only be called when the entity/player moves position,\s - keyword 'turn around' is for orientation (ie: looking around),\s - and the combined syntax listens for both. - Note that this event is called extremely often and may cause performance issues. - """) - .addExample(""" - on healing of a zombie, cow or a wither: - event-heal reason is healing potion - cancel event - """) - .addExample(""" - on player healing from a regeneration potion: - send "all better!" to event-entity - """) - .addSince("2.6, 2.8.0 (turn around)") - .build()); - - eventValueRegistry.register(EventValue.builder(EntityRegainHealthEvent.class, RegainReason.class) - .getter(EntityRegainHealthEvent::getRegainReason) - .build()); - } - - private EntityData[] entityData; - private RegainReason[] reasons; - @Override @SuppressWarnings("unchecked") - public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { - if (parseResult.hasTag("reason")) { - Literal reasonLiteral = (Literal) args[1]; - reasons = reasonLiteral.getArray(); + public Class[] getEventClasses() { + if (isPlayer) { + return new Class[]{PlayerMoveEvent.class}; } - Literal> entityLiteral = (Literal>) args[0]; - entityData = entityLiteral.getArray(); - return true; - } - - @Override - public boolean check(Event event) { - return true; - } - - @Override - @SuppressWarnings("unchecked") - public Class [] getEventClasses() { - return null; + if (canBePlayer) + return new Class[]{EntityMoveEvent.class, PlayerMoveEvent.class}; + return new Class[]{EntityMoveEvent.class}; } @Override public String toString(@Nullable Event event, boolean debug) { - return new SyntaxStringBuilder(event, debug) - .append(entityData != null ? entityData : "entity") - .append("healing") - .appendIf(reasons != null, "due to", reasons) - .toString(); + return entityData + " " + moveType; } } From 846edb85b98f9c88931be833e413aed6f3351e36 Mon Sep 17 00:00:00 2001 From: OwlBe Date: Thu, 2 Jul 2026 16:59:58 -0400 Subject: [PATCH 12/35] code cleanup --- .../skript/bukkit/BukkitModule.java | 1 + .../elements/events/EvtEntityBlockChange.java | 6 +++--- .../elements/events/EvtEntityDamage.java | 20 +++++++++++++------ .../elements/events/EvtEntityDeath.java | 9 ++++----- .../elements/events/EvtEntityShootBow.java | 9 ++++----- .../elements/events/EvtEntitySpawn.java | 9 ++++----- .../elements/events/EvtEntityTransform.java | 8 ++++++-- 7 files changed, 36 insertions(+), 26 deletions(-) diff --git a/src/main/java/org/skriptlang/skript/bukkit/BukkitModule.java b/src/main/java/org/skriptlang/skript/bukkit/BukkitModule.java index 7bf84c9ee0d..266a263f8e4 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/BukkitModule.java +++ b/src/main/java/org/skriptlang/skript/bukkit/BukkitModule.java @@ -78,6 +78,7 @@ protected void loadSelf(SkriptAddon addon) { // nothing to do } + // TODO: Remove this once the pr for it is merged probably around 7/16/2026 /** * Helper method that calls the given methods with a {@link SyntaxRegistry} and {@link EventValueRegistry} * @param syntaxRegistry The syntax registry to register with. diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBlockChange.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBlockChange.java index 2de07a0db70..71dbb69e9ca 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBlockChange.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBlockChange.java @@ -121,13 +121,13 @@ public boolean init(Literal[] args, int matchedPattern, ParseResult parseResu @Override public boolean check(Event event) { - if (!(event instanceof EntityChangeBlockEvent)) + if (!(event instanceof EntityChangeBlockEvent entityEvent)) return false; - if (entityData != null && !entityData.check(event, data -> data.isInstance(((EntityChangeBlockEvent) event).getEntity()))) + if (entityData != null && !entityData.check(event, data -> data.isInstance((entityEvent.getEntity())))) return false; if (this.event.checker == null) return true; - return this.event.checker.test((EntityChangeBlockEvent) event); + return this.event.checker.test(entityEvent); } @Override diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java index 5b696b5fa33..0dc5c1ea57a 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java @@ -78,12 +78,20 @@ public boolean init(Literal[] args, int matchedPattern, SkriptParser.ParseRes @Override public boolean check(Event event) { EntityDamageEvent entityDamageEvent = (EntityDamageEvent) event; - boolean entityMatched = ofEntityData == null || Arrays.stream(ofEntityData).anyMatch(data -> data.isInstance(entityDamageEvent.getEntity())); - boolean healthMatched = !(entityDamageEvent.getEntity() instanceof LivingEntity entity) || HealthUtils.getHealth(entity) > 0; - if (!(event instanceof EntityDamageByEntityEvent entityEvent)) - return byEntityData == null && entityMatched && healthMatched; - boolean damagerMatched = byEntityData == null || Arrays.stream(byEntityData).anyMatch(data -> data.isInstance(entityEvent.getDamager())); - return damagerMatched && entityMatched && healthMatched; + boolean entityMatched = true; + boolean healthMatched = true; + boolean damagerMatched = true; + + if (ofEntityData != null) + entityMatched = Arrays.stream(ofEntityData).anyMatch(data -> data.isInstance(entityDamageEvent.getEntity())); + + if (entityDamageEvent.getEntity() instanceof LivingEntity entity) + healthMatched = HealthUtils.getHealth(entity) > 0; + + if (byEntityData != null && event instanceof EntityDamageByEntityEvent entityEvent) + damagerMatched = Arrays.stream(byEntityData).anyMatch(data -> data.isInstance(entityEvent.getDamager())); + + return entityMatched && healthMatched && damagerMatched; } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDeath.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDeath.java index 63eca8ef9a3..776017134c8 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDeath.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDeath.java @@ -87,11 +87,10 @@ public boolean init(Literal[] args, int matchedPattern, ParseResult parseResu @Override public boolean check(Event event) { - if (entityData != null) { - EntityDeathEvent entityEvent = (EntityDeathEvent) event; - return Arrays.stream(entityData).anyMatch(entity -> entity.isInstance(entityEvent.getEntity())); - } - return true; + if (entityData == null) + return true; + EntityDeathEvent entityEvent = (EntityDeathEvent) event; + return Arrays.stream(entityData).anyMatch(entity -> entity.isInstance(entityEvent.getEntity())); } @Override diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityShootBow.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityShootBow.java index 111ab7d5724..8db38019214 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityShootBow.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityShootBow.java @@ -81,11 +81,10 @@ public boolean init(Literal[] args, int matchedPattern, ParseResult parseResu @Override public boolean check(Event event) { - if (entityData != null) { - EntityShootBowEvent entityEvent = (EntityShootBowEvent) event; - return Arrays.stream(entityData).anyMatch(entity -> entity.isInstance(entityEvent.getEntity())); - } - return true; + if (entityData == null) + return true; + EntityShootBowEvent entityEvent = (EntityShootBowEvent) event; + return Arrays.stream(entityData).anyMatch(entity -> entity.isInstance(entityEvent.getEntity())); } @Override diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntitySpawn.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntitySpawn.java index 05b9d3bddb8..029f15f4dfc 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntitySpawn.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntitySpawn.java @@ -59,11 +59,10 @@ public boolean init(Literal[] args, int matchedPattern, ParseResult parseResu @Override public boolean check(Event event) { - if (entityData != null) { - EntitySpawnEvent entityEvent = (EntitySpawnEvent) event; - return Arrays.stream(entityData).anyMatch(entity -> entity.isInstance(entityEvent.getEntity())); - } - return true; + if (entityData == null) + return true; + EntitySpawnEvent entityEvent = (EntitySpawnEvent) event; + return Arrays.stream(entityData).anyMatch(entity -> entity.isInstance(entityEvent.getEntity())); } @Override diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTransform.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTransform.java index 0c123951a9a..f8a6da1a794 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTransform.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTransform.java @@ -72,8 +72,12 @@ public boolean init(Literal[] args, int matchedPattern, ParseResult parseResu @Override public boolean check(Event event) { EntityTransformEvent entityEvent = (EntityTransformEvent) event; - boolean reasonMatched = reasons == null || Arrays.stream(reasons).anyMatch(reason -> reason == entityEvent.getTransformReason()); - boolean entityDataMatched = entityData == null || Arrays.stream(entityData).anyMatch(data -> data.isInstance(entityEvent.getEntity())); + boolean reasonMatched = true; + boolean entityDataMatched = true; + if (reasons != null) + reasonMatched = Arrays.stream(reasons).anyMatch(reason -> reason == entityEvent.getTransformReason()); + if (entityData != null) + entityDataMatched = Arrays.stream(entityData).anyMatch(data -> data.isInstance(entityEvent.getEntity())); return reasonMatched && entityDataMatched; } From 434fdd7cc3c64fded5efecaf26c3b8c62e78629a Mon Sep 17 00:00:00 2001 From: OwlBe Date: Thu, 2 Jul 2026 22:59:18 -0400 Subject: [PATCH 13/35] Final commit before pr (hopefully) --- .../java/ch/njol/skript/events/EvtMove.java | 138 ------------------ .../ch/njol/skript/events/SimpleEvents.java | 9 -- .../skript/bukkit/entity/EntityModule.java | 9 ++ .../bukkit/entity/elements/EntityEvents.java | 17 ++- .../elements/events/EvtEntityBlockChange.java | 15 +- .../elements/events/EvtEntityBreakDoor.java | 2 +- .../entity/elements/events/EvtEntityHeal.java | 10 +- .../elements/events/EvtEntityTarget.java | 7 +- .../skript/tests/misc/supported events.sk | 2 +- 9 files changed, 46 insertions(+), 163 deletions(-) delete mode 100644 src/main/java/ch/njol/skript/events/EvtMove.java diff --git a/src/main/java/ch/njol/skript/events/EvtMove.java b/src/main/java/ch/njol/skript/events/EvtMove.java deleted file mode 100644 index 628cbafeacc..00000000000 --- a/src/main/java/ch/njol/skript/events/EvtMove.java +++ /dev/null @@ -1,138 +0,0 @@ -package ch.njol.skript.events; - -import ch.njol.skript.Skript; -import ch.njol.skript.entity.EntityData; -import ch.njol.skript.lang.Literal; -import ch.njol.skript.lang.SkriptEvent; -import ch.njol.skript.lang.SkriptParser.ParseResult; -import ch.njol.util.coll.CollectionUtils; -import io.papermc.paper.event.entity.EntityMoveEvent; -import org.bukkit.Location; -import org.bukkit.entity.Player; -import org.bukkit.event.Event; -import org.bukkit.event.player.PlayerMoveEvent; -import org.jetbrains.annotations.Nullable; - -public class EvtMove extends SkriptEvent { - - // TODO - remove this when Spigot support is dropped - private static final boolean HAS_ENTITY_MOVE = Skript.classExists("io.papermc.paper.event.entity.EntityMoveEvent"); - - static { - Class[] events; - if (HAS_ENTITY_MOVE) - events = CollectionUtils.array(PlayerMoveEvent.class, EntityMoveEvent.class); - else - events = CollectionUtils.array(PlayerMoveEvent.class); - Skript.registerEvent("Move / Rotate", EvtMove.class, events, - "%entitydata% (move|walk|step|rotate:(turn[ing] around|rotate))", - "%entitydata% (move|walk|step) or (turn[ing] around|rotate)", - "%entitydata% (turn[ing] around|rotate) or (move|walk|step)") - .description( - "Called when a player or entity moves or rotates their head.", - "NOTE: Move event will only be called when the entity/player moves position, keyword 'turn around' is for orientation (ie: looking around), and the combined syntax listens for both.", - "NOTE: These events can be performance heavy as they are called quite often.") - .examples( - "on player move:", - "\tif player does not have permission \"player.can.move\":", - "\t\tcancel event", - "on skeleton move:", - "\tif event-entity is not in world \"world\":", - "\t\tkill event-entity", - "on player turning around:", - "\tsend action bar \"You are currently turning your head around!\" to player") - .since("2.6, 2.8.0 (turn around)"); - } - - private EntityData entityData; - private boolean isPlayer; - private boolean canBePlayer; - private Move moveType; - - private enum Move { - - MOVE("move"), - MOVE_OR_ROTATE("move or rotate"), - ROTATE("rotate"); - - private final String name; - - Move(String name) { - this.name = name; - } - - @Override - public String toString() { - return name; - } - - } - - @Override - @SuppressWarnings("unchecked") - public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { - entityData = ((Literal>) args[0]).getSingle(); - isPlayer = Player.class.isAssignableFrom(entityData.getType()); - if (!HAS_ENTITY_MOVE && !isPlayer) { - Skript.error("Entity move event requires Paper"); - return false; - } - canBePlayer = entityData.getType().isAssignableFrom(Player.class); - if (matchedPattern > 0) { - moveType = Move.MOVE_OR_ROTATE; - } else if (parseResult.hasTag("rotate")) { - moveType = Move.ROTATE; - } else { - moveType = Move.MOVE; - } - return true; - } - - @Override - public boolean check(Event event) { - Location from, to; - if (canBePlayer && event instanceof PlayerMoveEvent playerMoveEvent) { - from = playerMoveEvent.getFrom(); - to = playerMoveEvent.getTo(); - } else if (HAS_ENTITY_MOVE && event instanceof EntityMoveEvent entityMoveEvent) { - if (!(entityData.isInstance(entityMoveEvent.getEntity()))) - return false; - from = entityMoveEvent.getFrom(); - to = entityMoveEvent.getTo(); - } else { - return false; - } - return switch (moveType) { - case MOVE -> hasChangedPosition(from, to); - case ROTATE -> hasChangedOrientation(from, to); - case MOVE_OR_ROTATE -> true; - }; - } - - @Override - @SuppressWarnings("unchecked") - public Class [] getEventClasses() { - if (isPlayer) { - return new Class[] {PlayerMoveEvent.class}; - } else if (HAS_ENTITY_MOVE) { - if (canBePlayer) - return new Class[] {EntityMoveEvent.class, PlayerMoveEvent.class}; - return new Class[] {EntityMoveEvent.class}; - } - throw new IllegalStateException("This event has not yet initialized!"); - } - - @Override - public String toString(@Nullable Event event, boolean debug) { - return entityData + " " + moveType; - } - - private static boolean hasChangedPosition(Location from, Location to) { - return from.getX() != to.getX() || from.getY() != to.getY() || from.getZ() != to.getZ() || from.getWorld() != to.getWorld(); - } - - private static boolean hasChangedOrientation(Location from, Location to) { - return from.getYaw() != to.getYaw() || from.getPitch() != to.getPitch(); - } - -} diff --git a/src/main/java/ch/njol/skript/events/SimpleEvents.java b/src/main/java/ch/njol/skript/events/SimpleEvents.java index b564c238d49..09a72276546 100644 --- a/src/main/java/ch/njol/skript/events/SimpleEvents.java +++ b/src/main/java/ch/njol/skript/events/SimpleEvents.java @@ -99,10 +99,6 @@ public class SimpleEvents { .description("Called when a chunk is unloaded due to not being near any player.") .examples("on chunk unload:") .since("1.0"); - Skript.registerEvent("Zombie Break Door", SimpleEvent.class, EntityBreakDoorEvent.class, "zombie break[ing] [a] [wood[en]] door") - .description("Called when a zombie is done breaking a wooden door. Can be cancelled to prevent the zombie from breaking the door.") - .examples("on zombie breaking a wood door:") - .since("1.0"); // Skript.registerEvent(SimpleEvent.class, EntityInteractEvent.class, "interact");// = entity interacts with block, e.g. endermen?; player -> PlayerInteractEvent // likely tripwires, pressure plates, etc. Skript.registerEvent("Explosion Prime", SimpleEvent.class, ExplosionPrimeEvent.class, "explosion prime") .description("Called when an explosive is primed, i.e. an entity will explode shortly. Creepers can abort the explosion if the player gets too far away, " + @@ -267,11 +263,6 @@ public class SimpleEvents { .description("Called when area effect cloud applies its potion effect. This happens every 5 ticks by default.") .examples("on area cloud effect:") .since("2.2-dev21"); - Skript.registerEvent("Sheep Regrow Wool", SimpleEvent.class, SheepRegrowWoolEvent.class, "sheep [re]grow[ing] wool") - .description("Called when sheep regrows its sheared wool back.") - .examples("on sheep grow wool:", - "\tcancel event") - .since("2.2-dev21"); Skript.registerEvent("Inventory Open", SimpleEvent.class, InventoryOpenEvent.class, "inventory open[ed]") .description("Called when an inventory is opened for player.") .examples("on inventory open:", diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/EntityModule.java b/src/main/java/org/skriptlang/skript/bukkit/entity/EntityModule.java index 3b427e45f9c..1bd0cdfb1a6 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/EntityModule.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/EntityModule.java @@ -2,6 +2,7 @@ import ch.njol.skript.Skript; import ch.njol.skript.entity.SimpleEntityData; +import ch.njol.skript.registrations.Classes; import org.bukkit.entity.AbstractNautilus; import org.skriptlang.skript.addon.AddonModule; import org.skriptlang.skript.addon.HierarchicalAddonModule; @@ -9,12 +10,14 @@ import org.skriptlang.skript.bukkit.BukkitModule; import org.skriptlang.skript.bukkit.entity.displays.DisplayModule; import org.skriptlang.skript.bukkit.entity.elements.EntityEvents; +import org.skriptlang.skript.bukkit.entity.elements.effects.EffTeleport; import org.skriptlang.skript.bukkit.entity.elements.events.*; import org.skriptlang.skript.bukkit.entity.interactions.InteractionModule; import org.skriptlang.skript.bukkit.entity.elements.expressions.ExprDeathMessage; import org.skriptlang.skript.bukkit.entity.entitydata.NautilusData; import org.skriptlang.skript.bukkit.entity.entitydata.ZombieNautilusData; import org.skriptlang.skript.bukkit.entity.player.PlayerModule; +import org.skriptlang.skript.bukkit.entity.types.TeleportFlagClassInfo; import org.skriptlang.skript.bukkit.lang.eventvalue.EventValueRegistry; import java.util.List; @@ -33,6 +36,11 @@ public Iterable children() { ); } + @Override + protected void initSelf(SkriptAddon addon) { + Classes.registerClass(new TeleportFlagClassInfo()); + } + @Override protected void loadSelf(SkriptAddon addon) { if (Skript.classExists("org.bukkit.entity.Nautilus")) { @@ -63,6 +71,7 @@ protected void loadSelf(SkriptAddon addon) { EvtEntityPortal::register, EvtEntitySpawn::register, EvtEntityTarget::register, + EffTeleport::register, ExprDeathMessage::register ); } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/EntityEvents.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/EntityEvents.java index 3cadce41c95..08153018ea4 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/EntityEvents.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/EntityEvents.java @@ -87,7 +87,7 @@ Called when an entity (usually a primed TNT or creeper) explodes. broadcast "*Explosion*" """) .addSince("1.0") - .supplier(() -> new SimpleEvent("entity exploding")) + .supplier(() -> new SimpleEvent("entity explode")) .build()); syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Entity Portal Enter") @@ -288,6 +288,21 @@ Called when an entity (usually a primed TNT or creeper) explodes. .supplier(() -> new SimpleEvent("piglin bartering")) .build()); + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Pig Zap") + .addEvent(PigZapEvent.class) + .addPatterns("pig[ ]zap") + .addDescription(""" + Called when a pig is stroke by lightning and transformed into a zombie pigman. + Cancelling this will prevent the transformation. + """) + .addExample(""" + on pig zap: + broadcast "I'm feeling a bit static!" + """) + .addSince("1.0") + .supplier(() -> new SimpleEvent("pig zap")) + .build()); + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Bat Toggle Sleep") .addEvent(BatToggleSleepEvent.class) .addPatterns("bat toggl(e|ing) sleep") diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBlockChange.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBlockChange.java index 71dbb69e9ca..cbbfde3eb16 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBlockChange.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBlockChange.java @@ -54,16 +54,16 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev .build()); eventValueRegistry.register(EventValue.builder(EntityChangeBlockEvent.class, Block.class) - .getter(EntityChangeBlockEvent::getBlock) // why is there past event-block & event-block with both values?? + .getter(EntityChangeBlockEvent::getBlock) .build()); eventValueRegistry.register(EventValue.builder(EntityChangeBlockEvent.class, BlockData.class) .getter(EntityChangeBlockEvent::getBlockData) - .time(Time.FUTURE) .build()); - eventValueRegistry.register(EventValue.builder(EntityChangeBlockEvent.class, Block.class) - .getter(EntityChangeBlockEvent::getBlock) + eventValueRegistry.register(EventValue.builder(EntityChangeBlockEvent.class, BlockData.class) + .getter(EntityChangeBlockEvent::getBlockData) + .time(Time.FUTURE) .build()); } @@ -121,10 +121,9 @@ public boolean init(Literal[] args, int matchedPattern, ParseResult parseResu @Override public boolean check(Event event) { - if (!(event instanceof EntityChangeBlockEvent entityEvent)) - return false; - if (entityData != null && !entityData.check(event, data -> data.isInstance((entityEvent.getEntity())))) - return false; + EntityChangeBlockEvent entityEvent = (EntityChangeBlockEvent) event; + if (entityData != null) + return !entityData.check(event, data -> data.isInstance((entityEvent.getEntity()))); if (this.event.checker == null) return true; return this.event.checker.test(entityEvent); diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java index b1cf2616955..db25956d8c0 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java @@ -21,7 +21,7 @@ public static void register(SyntaxRegistry syntaxRegistry) { .addEvent(EntityBreakDoorEvent.class) .addPatterns("[entity:%entitydatas%] break[ing] [a] [wood[en]] door") .addDescription(""" - Called when an entity (usually a zombie) is breaking a door. + Called when an entity (usually a zombie) is breaks a door. Can be cancelled to prevent the entity from breaking the door. """) .addExample(""" diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityHeal.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityHeal.java index 0a416b9fe82..ea98496fa2b 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityHeal.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityHeal.java @@ -23,8 +23,8 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev .supplier(EvtEntityHeal::new) .addEvent(EntityRegainHealthEvent.class) .addPatterns( - "heal[ing] [of %-entitydatas%] [reason:(from|due to|by) %-healreasons%]", - "%entitydatas% heal[ing] [reason:(from|due to|by) %-healreasons%]" + "heal[ing] [entity:of %-entitydatas%] [reason:(from|due to|by) %-healreasons%]", + "[entity:%-entitydatas%] heal[ing] [reason:(from|due to|by) %-healreasons%]" ) .addDescription(""" Called when an entity is healed,\s @@ -59,8 +59,10 @@ public boolean init(Literal[] args, int matchedPattern, ParseResult parseResu Literal reasonLiteral = (Literal) args[1]; reasons = reasonLiteral.getArray(); } - Literal> entityLiteral = (Literal>) args[0]; - entityData = entityLiteral.getArray(); + if (parseResult.hasTag("entity")) { + Literal> entityLiteral = (Literal>) args[0]; + entityData = entityLiteral.getArray(); + } return true; } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTarget.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTarget.java index b590e1b283e..b95206128c7 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTarget.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTarget.java @@ -23,7 +23,12 @@ public static void register(SyntaxRegistry syntaxRegistry) { See target. for how to get the entity being targeted. """) .addExample(""" - + on entity target: + broadcast "I detect an entity is targeting another.." + """) + .addExample(""" + on entity untarget: + broadcast "Phew.. it looks like they stopped.." """) .addSince("1.0") .build()); diff --git a/src/test/skript/tests/misc/supported events.sk b/src/test/skript/tests/misc/supported events.sk index 79e2d51e7f8..46169653cbf 100644 --- a/src/test/skript/tests/misc/supported events.sk +++ b/src/test/skript/tests/misc/supported events.sk @@ -2,4 +2,4 @@ test "supported events": parse: set {_x} to the exploded blocks - assert last parse logs contain "'the exploded blocks' can only be used in the on explode event" with "supported events message did not get sent correctly" + assert last parse logs contain "'the exploded blocks' can only be used in the on entity explode event" with "supported events message did not get sent correctly" From a5020056f168e80c28070b5208d88264a947d518 Mon Sep 17 00:00:00 2001 From: OwlBe Date: Thu, 2 Jul 2026 23:14:34 -0400 Subject: [PATCH 14/35] stuff --- .../skript/bukkit/entity/EntityModule.java | 35 ------------------- .../bukkit/entity/elements/EntityEvents.java | 26 ++++++++++++++ 2 files changed, 26 insertions(+), 35 deletions(-) diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/EntityModule.java b/src/main/java/org/skriptlang/skript/bukkit/entity/EntityModule.java index 855a22053cb..20602a9bb44 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/EntityModule.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/EntityModule.java @@ -2,13 +2,8 @@ import ch.njol.skript.Skript; import ch.njol.skript.entity.SimpleEntityData; -import ch.njol.skript.lang.util.SimpleEvent; -import com.destroystokyo.paper.event.entity.EntityPathfindEvent; -import io.papermc.paper.event.player.AsyncChatEvent; -import org.bukkit.Location; import ch.njol.skript.registrations.Classes; import org.bukkit.entity.AbstractNautilus; -import org.bukkit.entity.Entity; import org.skriptlang.skript.addon.AddonModule; import org.skriptlang.skript.addon.HierarchicalAddonModule; import org.skriptlang.skript.addon.SkriptAddon; @@ -24,12 +19,8 @@ import org.skriptlang.skript.bukkit.entity.entitydata.NautilusData; import org.skriptlang.skript.bukkit.entity.entitydata.ZombieNautilusData; import org.skriptlang.skript.bukkit.entity.player.PlayerModule; -import org.skriptlang.skript.bukkit.lang.eventvalue.EventValue; import org.skriptlang.skript.bukkit.lang.eventvalue.EventValueRegistry; -import org.skriptlang.skript.bukkit.registration.BukkitSyntaxInfos; -import org.skriptlang.skript.registration.SyntaxRegistry; import org.skriptlang.skript.bukkit.entity.types.TeleportFlagClassInfo; -import org.skriptlang.skript.bukkit.lang.eventvalue.EventValueRegistry; import java.util.List; @@ -59,32 +50,6 @@ protected void loadSelf(SkriptAddon addon) { ZombieNautilusData.register(); SimpleEntityData.addSuperEntity("any nautilus", AbstractNautilus.class); } - SyntaxRegistry syntaxRegistry = moduleRegistry(addon); - EventValueRegistry registry = addon.registry(EventValueRegistry.class); - syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Pathfind") - .addDescription("Called whenever an entity tries to pathfind to a location or another entity.") - .addExample(""" - on pathfind: - broadcast "%event-entity% is about to move to %event-location%!" - """) - .addSince("2.16") - .addPattern("[entity] [start[s]] pathfind[ing]") - .addEvent(EntityPathfindEvent.class) - .build()); - - registry.register(EventValue.builder(EntityPathfindEvent.class, Location.class) - .getter(EntityPathfindEvent::getLoc) - .patterns("target location") - .build()); - - registry.register(EventValue.builder(EntityPathfindEvent.class, Entity.class) - .getter(EntityPathfindEvent::getTargetEntity) - .patterns("target entity") - .build()); - - registry.register(EventValue.builder(EntityPathfindEvent.class, Location.class) - .getter(event -> event.getEntity().getLocation()) - .build()); EventValueRegistry eventValueRegistry = addon.registry(EventValueRegistry.class); diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/EntityEvents.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/EntityEvents.java index 08153018ea4..04d6f5f8e12 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/EntityEvents.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/EntityEvents.java @@ -8,6 +8,7 @@ import ch.njol.skript.util.slot.Slot; import com.destroystokyo.paper.event.entity.EndermanAttackPlayerEvent; import com.destroystokyo.paper.event.entity.EntityJumpEvent; +import com.destroystokyo.paper.event.entity.EntityPathfindEvent; import org.bukkit.Location; import org.bukkit.World; import org.bukkit.command.CommandSender; @@ -373,6 +374,31 @@ Called when an entity (usually a primed TNT or creeper) explodes. eventValueRegistry.register(EventValue.builder(EndermanAttackPlayerEvent.class, Player.class) .getter(EndermanAttackPlayerEvent::getPlayer) .build()); + + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Pathfind") + .addDescription("Called whenever an entity tries to pathfind to a location or another entity.") + .addExample(""" + on pathfind: + broadcast "%event-entity% is about to move to %event-location%!" + """) + .addSince("2.16") + .addPattern("[entity] [start[s]] pathfind[ing]") + .addEvent(EntityPathfindEvent.class) + .build()); + + eventValueRegistry.register(EventValue.builder(EntityPathfindEvent.class, Location.class) + .getter(EntityPathfindEvent::getLoc) + .patterns("target location") + .build()); + + eventValueRegistry.register(EventValue.builder(EntityPathfindEvent.class, Entity.class) + .getter(EntityPathfindEvent::getTargetEntity) + .patterns("target entity") + .build()); + + eventValueRegistry.register(EventValue.builder(EntityPathfindEvent.class, Location.class) + .getter(event -> event.getEntity().getLocation()) + .build()); } } From 7f2d44db9f7f377f975c9d528dc8a2b71992ef3d Mon Sep 17 00:00:00 2001 From: OwlBe Date: Thu, 2 Jul 2026 23:15:19 -0400 Subject: [PATCH 15/35] this isn't needed --- src/main/java/ch/njol/skript/events/SimpleEvents.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/main/java/ch/njol/skript/events/SimpleEvents.java b/src/main/java/ch/njol/skript/events/SimpleEvents.java index 186cc823a9c..2728efbb933 100644 --- a/src/main/java/ch/njol/skript/events/SimpleEvents.java +++ b/src/main/java/ch/njol/skript/events/SimpleEvents.java @@ -551,11 +551,6 @@ public class SimpleEvents { .since("2.10"); } - Skript.registerEvent("Bat Toggle Sleep", SimpleEvent.class, BatToggleSleepEvent.class, "bat toggle sleep") - .description("Called when a bat attempts to go to sleep or wakes up.") - .examples("on bat toggle sleep:") - .since("2.11"); - if (Skript.classExists("org.bukkit.event.block.VaultDisplayItemEvent")) { Skript.registerEvent("Vault Display Item", SimpleEvent.class, VaultDisplayItemEvent.class, "vault display[ing] item") @@ -563,7 +558,7 @@ public class SimpleEvents { .examples( """ on vault display item: - set event-item to a netherite ingot + set event-item to a netherite ingot """ ) .since("2.12") From 4fd2bb0a415974062d36474cb1ba0a99daf35277 Mon Sep 17 00:00:00 2001 From: OwlBe Date: Fri, 3 Jul 2026 19:35:37 -0400 Subject: [PATCH 16/35] requested changes --- .../elements/events/EvtEntityBreakDoor.java | 15 +++----- .../elements/events/EvtEntityDamage.java | 32 ++++++---------- .../elements/events/EvtEntityDeath.java | 15 +++----- .../entity/elements/events/EvtEntityHeal.java | 37 ++++++++----------- .../elements/events/EvtEntityLeash.java | 15 +++----- .../elements/events/EvtEntityShootBow.java | 12 ++---- .../elements/events/EvtEntitySpawn.java | 15 +++----- .../elements/events/EvtEntityTarget.java | 7 +--- .../elements/events/EvtEntityTeleport.java | 18 ++++----- .../elements/events/EvtEntityTransform.java | 32 ++++++---------- 10 files changed, 76 insertions(+), 122 deletions(-) diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java index db25956d8c0..f0b5ef60915 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java @@ -11,17 +11,15 @@ import org.skriptlang.skript.bukkit.registration.BukkitSyntaxInfos; import org.skriptlang.skript.registration.SyntaxRegistry; -import java.util.Arrays; - public class EvtEntityBreakDoor extends SkriptEvent { public static void register(SyntaxRegistry syntaxRegistry) { syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(EvtEntityBreakDoor.class, "Entity Break Door") .supplier(EvtEntityBreakDoor::new) .addEvent(EntityBreakDoorEvent.class) - .addPatterns("[entity:%entitydatas%] break[ing] [a] [wood[en]] door") + .addPatterns("[%-entitydatas%] break[ing] [a] [wood[en]] door") .addDescription(""" - Called when an entity (usually a zombie) is breaks a door. + Called when an entity (usually a zombie, husk, zombie pigman or zombie villager) is breaking a door. Can be cancelled to prevent the entity from breaking the door. """) .addExample(""" @@ -33,14 +31,13 @@ Called when an entity (usually a zombie) is breaks a door. .build()); } - private EntityData[] entityData; + private Literal> entityData; @Override @SuppressWarnings("unchecked") public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { - if (parseResult.hasTag("entity")) { - Literal> entityLiteral = (Literal>) args[0]; - entityData = entityLiteral.getArray(); + if (args[0] != null) { + entityData = (Literal>) args[0]; } return true; } @@ -49,7 +46,7 @@ public boolean init(Literal[] args, int matchedPattern, ParseResult parseResu public boolean check(Event event) { if (entityData != null) { EntityBreakDoorEvent entityEvent = (EntityBreakDoorEvent) event; - return Arrays.stream(entityData).anyMatch(entity -> entity.isInstance(entityEvent.getEntity())); + return entityData.check(event, data -> data.isInstance((entityEvent.getEntity()))); } return true; } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java index 0dc5c1ea57a..d04862181ab 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java @@ -58,20 +58,16 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev .build()); } - private EntityData[] byEntityData; - private EntityData[] ofEntityData; + private Literal> byEntityData; + private Literal> ofEntityData; @Override @SuppressWarnings("unchecked") public boolean init(Literal[] args, int matchedPattern, SkriptParser.ParseResult parseResult) { - if (parseResult.hasTag("by")) { - Literal> entityLiteral = (Literal>) args[1]; - byEntityData = entityLiteral.getArray(); - } - if (parseResult.hasTag("of")) { - Literal> entityLiteral = (Literal>) args[0]; - ofEntityData = entityLiteral.getArray(); - } + if (parseResult.hasTag("by")) + byEntityData = (Literal>) args[1]; + if (parseResult.hasTag("of")) + ofEntityData = (Literal>) args[0]; return true; } @@ -82,17 +78,13 @@ public boolean check(Event event) { boolean healthMatched = true; boolean damagerMatched = true; - if (ofEntityData != null) - entityMatched = Arrays.stream(ofEntityData).anyMatch(data -> data.isInstance(entityDamageEvent.getEntity())); - - if (entityDamageEvent.getEntity() instanceof LivingEntity entity) - healthMatched = HealthUtils.getHealth(entity) > 0; - + if (ofEntityData != null && !ofEntityData.check(event, data -> data.isInstance(entityDamageEvent.getEntity()))) + return false; + if (entityDamageEvent.getEntity() instanceof LivingEntity entity && HealthUtils.getHealth(entity) <= 0) + return false; if (byEntityData != null && event instanceof EntityDamageByEntityEvent entityEvent) - damagerMatched = Arrays.stream(byEntityData).anyMatch(data -> data.isInstance(entityEvent.getDamager())); - - return entityMatched && healthMatched && damagerMatched; - + return byEntityData.check(event, data -> data.isInstance(entityEvent.getDamager())); + return true; } @Override diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDeath.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDeath.java index 776017134c8..bfd81afbb5b 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDeath.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDeath.java @@ -21,15 +21,13 @@ import org.skriptlang.skript.bukkit.registration.BukkitSyntaxInfos; import org.skriptlang.skript.registration.SyntaxRegistry; -import java.util.Arrays; - public class EvtEntityDeath extends SkriptEvent { public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry eventValueRegistry) { syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(EvtEntityDeath.class, "Entity Death") .supplier(EvtEntityDeath::new) .addEvent(EntityDeathEvent.class) - .addPatterns("death [entity:of %-entitydatas%]") + .addPatterns("death [of %-entitydatas%]") .addDescription(""" Called when a living entity (including players) dies. See attacker/victim/ for how to get the victim or attacker in this event. @@ -67,15 +65,14 @@ Called when a living entity (including players) dies. .build()); } - private EntityData[] entityData; + private Literal> entityData; @Override @SuppressWarnings("unchecked") public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { - if (parseResult.hasTag("entity")) { - Literal> entityLiteral = (Literal>) args[0]; - entityData = entityLiteral.getArray(); - for (EntityData value : entityData) { + if (args[0] != null) { + entityData = (Literal>) args[0]; + for (EntityData value : entityData.getAll()) { if (!LivingEntity.class.isAssignableFrom(value.getType())) { Skript.error("The death event only works for living entities", ErrorQuality.SEMANTIC_ERROR); return false; @@ -90,7 +87,7 @@ public boolean check(Event event) { if (entityData == null) return true; EntityDeathEvent entityEvent = (EntityDeathEvent) event; - return Arrays.stream(entityData).anyMatch(entity -> entity.isInstance(entityEvent.getEntity())); + return entityData.check(event, data -> data.isInstance(entityEvent.getEntity())); } @Override diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityHeal.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityHeal.java index ea98496fa2b..c264a1e7ef6 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityHeal.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityHeal.java @@ -14,8 +14,6 @@ import org.skriptlang.skript.bukkit.registration.BukkitSyntaxInfos; import org.skriptlang.skript.registration.SyntaxRegistry; -import java.util.Arrays; - public class EvtEntityHeal extends SkriptEvent { public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry eventValueRegistry) { @@ -23,8 +21,8 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev .supplier(EvtEntityHeal::new) .addEvent(EntityRegainHealthEvent.class) .addPatterns( - "heal[ing] [entity:of %-entitydatas%] [reason:(from|due to|by) %-healreasons%]", - "[entity:%-entitydatas%] heal[ing] [reason:(from|due to|by) %-healreasons%]" + "heal[ing] [of %-entitydatas%] [(from|due to|by) %-healreasons%]", + "[%-entitydatas%] heal[ing] [(from|due to|by) %-healreasons%]" ) .addDescription(""" Called when an entity is healed,\s @@ -49,35 +47,32 @@ or by the effect of a potion of healing (overworld mobs) or harm (nether mobs). .build()); } - private EntityData[] entityData; - private RegainReason[] reasons; + private Literal> entityData; + private Literal reasons; @Override @SuppressWarnings("unchecked") public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { - if (parseResult.hasTag("reason")) { - Literal reasonLiteral = (Literal) args[1]; - reasons = reasonLiteral.getArray(); - } - if (parseResult.hasTag("entity")) { - Literal> entityLiteral = (Literal>) args[0]; - entityData = entityLiteral.getArray(); - } + if (args[0] != null) + entityData = (Literal>) args[0]; + + if (args[1] != null) + reasons = (Literal) args[1]; return true; } @Override public boolean check(Event event) { EntityRegainHealthEvent entityEvent = (EntityRegainHealthEvent) event; - boolean entityMatched = true; - boolean reasonMatched = true; - if (entityData != null) - entityMatched = Arrays.stream(entityData).noneMatch(data -> data.isInstance(entityEvent.getEntity())); - if (reasons != null) - reasonMatched = Arrays.stream(reasons).noneMatch(reason -> reason == entityEvent.getRegainReason()); - return entityMatched && reasonMatched; + if (entityData != null && !entityData.check(event, data -> data.isInstance(entityEvent.getEntity()))) + return false; + if (reasons != null && !reasons.check(event, reason -> reason.equals(entityEvent.getRegainReason()))) + return false; + return true; + } + @Override public String toString(@Nullable Event event, boolean debug) { return new SyntaxStringBuilder(event, debug) diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityLeash.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityLeash.java index df300dd7dd7..24966e49601 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityLeash.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityLeash.java @@ -19,15 +19,13 @@ import org.skriptlang.skript.bukkit.registration.BukkitSyntaxInfos; import org.skriptlang.skript.registration.SyntaxRegistry; -import java.util.Arrays; - public class EvtEntityLeash extends SkriptEvent { public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry eventValueRegistry) { syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(EvtEntityLeash.class, "Entity Leash") .supplier(EvtEntityLeash::new) .addEvents(CollectionUtils.array(PlayerLeashEntityEvent.class, EntityUnleashEvent.class)) - .addPatterns("[:player] [:un]leash[ing] [entity:of %-entitydatas%]") + .addPatterns("[:player] [:un]leash[ing] [of %-entitydatas%]") .addDescription(""" Called when an entity is leashed or unleashed. Cancelling these events will prevent the leashing or unleashing from occurring. @@ -85,16 +83,15 @@ public String toString() { } - private @Nullable EntityData[] entityData; + private Literal> entityData; private EventType eventType; @Override @SuppressWarnings("unchecked") public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { - if (parseResult.hasTag("entity")) { - Literal> entityLiteral = (Literal>) args[0]; - entityData = entityLiteral.getArray(); - } + if (args[0] != null) + entityData = (Literal>) args[0]; + eventType = EventType.LEASH; if (parseResult.hasTag("un")) { eventType = EventType.UNLEASH; @@ -116,7 +113,7 @@ public boolean check(Event event) { return false; if (entityData == null) return true; - return Arrays.stream(entityData).anyMatch(entityData -> entityData.isInstance(leashedEntity)); + return entityData.check(event, data -> data.isInstance(leashedEntity)); } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityShootBow.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityShootBow.java index 8db38019214..ca8851765ad 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityShootBow.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityShootBow.java @@ -19,8 +19,6 @@ import org.skriptlang.skript.bukkit.registration.BukkitSyntaxInfos; import org.skriptlang.skript.registration.SyntaxRegistry; -import java.util.Arrays; - public class EvtEntityShootBow extends SkriptEvent { public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry eventValueRegistry) { @@ -67,15 +65,13 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev .build()); } - private EntityData[] entityData; + private Literal> entityData; @Override @SuppressWarnings("unchecked") public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { - if (parseResult.hasTag("entity")) { - Literal> entityLiteral = (Literal>) args[0]; - entityData = entityLiteral.getArray(); - } + if (args[0] != null) + entityData = (Literal>) args[0]; return true; } @@ -84,7 +80,7 @@ public boolean check(Event event) { if (entityData == null) return true; EntityShootBowEvent entityEvent = (EntityShootBowEvent) event; - return Arrays.stream(entityData).anyMatch(entity -> entity.isInstance(entityEvent.getEntity())); + return entityData.check(event, data -> data.isInstance(entityEvent.getEntity())); } @Override diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntitySpawn.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntitySpawn.java index 029f15f4dfc..0bf7648b7ca 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntitySpawn.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntitySpawn.java @@ -14,15 +14,13 @@ import org.skriptlang.skript.bukkit.registration.BukkitSyntaxInfos; import org.skriptlang.skript.registration.SyntaxRegistry; -import java.util.Arrays; - public class EvtEntitySpawn extends SkriptEvent { public static void register(SyntaxRegistry syntaxRegistry) { syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(EvtEntitySpawn.class, "Entity Spawn") .supplier(EvtEntitySpawn::new) .addEvent(EntitySpawnEvent.class) - .addPatterns("spawn[ing] [entity:of %-entitydatas%]") + .addPatterns("spawn[ing] [of %-entitydatas%]") .addDescription("Called when an entity spawns (excluding players).") .addExample(""" on spawn of a zombie: @@ -39,15 +37,14 @@ public static void register(SyntaxRegistry syntaxRegistry) { .build()); } - private EntityData[] entityData; + private Literal> entityData; @Override @SuppressWarnings("unchecked") public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { - if (parseResult.hasTag("entity")) { - Literal> entityLiteral = (Literal>) args[0]; - entityData = entityLiteral.getArray(); - for (EntityData value : entityData) { + if (args[0] != null) { + entityData = (Literal>) args[0]; + for (EntityData value : entityData.getAll()) { if (HumanEntity.class.isAssignableFrom(value.getType())) { Skript.error("The spawn event does not work for human entities", ErrorQuality.SEMANTIC_ERROR); return false; @@ -62,7 +59,7 @@ public boolean check(Event event) { if (entityData == null) return true; EntitySpawnEvent entityEvent = (EntitySpawnEvent) event; - return Arrays.stream(entityData).anyMatch(entity -> entity.isInstance(entityEvent.getEntity())); + return entityData.check(event, data -> data.isInstance(entityEvent.getEntity())); } @Override diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTarget.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTarget.java index b95206128c7..c587b11ebb8 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTarget.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTarget.java @@ -4,7 +4,6 @@ import ch.njol.skript.lang.Literal; import ch.njol.skript.lang.SkriptEvent; import ch.njol.skript.lang.SkriptParser.ParseResult; -import ch.njol.skript.lang.SyntaxStringBuilder; import org.bukkit.event.Event; import org.bukkit.event.entity.EntityTargetEvent; import org.jetbrains.annotations.Nullable; @@ -50,11 +49,7 @@ public boolean check(Event event) { @Override public String toString(@Nullable Event event, boolean debug) { - return new SyntaxStringBuilder(event, debug) - .append("entity") - .appendIf(!target,"un") - .append("target") - .toString(); + return "entity " + (target ? "" : "un") + "target"; } } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTeleport.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTeleport.java index 03bcf3ec7dd..0ba241ec454 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTeleport.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTeleport.java @@ -18,15 +18,13 @@ import org.skriptlang.skript.bukkit.registration.BukkitSyntaxInfos; import org.skriptlang.skript.registration.SyntaxRegistry; -import java.util.Arrays; - public class EvtEntityTeleport extends SkriptEvent { public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry eventValueRegistry) { syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(EvtEntityTeleport.class, "Entity Teleport") .supplier(EvtEntityTeleport::new) .addEvents(CollectionUtils.array(EntityTeleportEvent.class, PlayerTeleportEvent.class)) - .addPatterns("[entity:%-entitydatas%] teleport[ing]") + .addPatterns("[%-entitydatas%] teleport[ing]") .addDescription(""" Called when an entity teleports including players. This event will also be called due to a result of natural causes,\s @@ -69,15 +67,13 @@ or by other means (e.g. plugins). .build()); } - private EntityData[] entityData; + private Literal> entityData; @Override @SuppressWarnings("unchecked") public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { - if (parseResult.hasTag("entity")) { - Literal> entityLiteral = (Literal>) args[0]; - entityData = entityLiteral.getArray(); - } + if (args[0] != null) + entityData = (Literal>) args[0]; return true; } @@ -86,9 +82,9 @@ public boolean check(Event event) { if (entityData == null) return true; if (event instanceof EntityTeleportEvent entityEvent) { - return Arrays.stream(entityData).anyMatch(entity -> entity.isInstance(entityEvent.getEntity())); + return entityData.check(event, data -> data.isInstance(entityEvent.getEntity())); } else if (event instanceof PlayerTeleportEvent playerEvent) { - return Arrays.stream(entityData).anyMatch(player -> player.isInstance(playerEvent.getPlayer())); + return entityData.check(event, data -> data.isInstance(playerEvent.getPlayer())); } return false; } @@ -96,7 +92,7 @@ public boolean check(Event event) { @Override public String toString(@Nullable Event event, boolean debug) { return new SyntaxStringBuilder(event, debug) - .appendIf(entityData != null, (Object) entityData) + .appendIf(entityData != null, entityData) .append("teleporting") .toString(); } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTransform.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTransform.java index f8a6da1a794..c76e169382a 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTransform.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTransform.java @@ -15,15 +15,13 @@ import org.skriptlang.skript.bukkit.registration.BukkitSyntaxInfos; import org.skriptlang.skript.registration.SyntaxRegistry; -import java.util.Arrays; - public class EvtEntityTransform extends SkriptEvent { public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry eventValueRegistry) { syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(EvtEntityTransform.class, "Entity Transform") .supplier(EvtEntityTransform::new) .addEvent(EntityTransformEvent.class) - .addPatterns("[entity:%*-entitydatas%] transform[ing] [transform: due to %-transformreasons%]") + .addPatterns("[%*-entitydatas%] transform[ing] [due to %-transformreasons%]") .addDescription(""" Called when an entity is about to be replaced by another entity. e.g. when a zombie gets cured and a villager spawns,\s @@ -52,33 +50,27 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev .build()); } - private EntityData[] entityData; - private TransformReason[] reasons; + private Literal> entityData; + private Literal reasons; @Override @SuppressWarnings("unchecked") public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { - if (parseResult.hasTag("transform")) { - Literal transformLiteral = (Literal) args[1]; - reasons = transformLiteral.getArray(); - } - if (parseResult.hasTag("entity")) { - Literal> entityLiteral = (Literal>) args[0]; - entityData = entityLiteral.getArray(); - } + if (args[1] != null) + reasons = (Literal) args[1]; + if (args[0] != null) + entityData = (Literal>) args[0]; return true; } @Override public boolean check(Event event) { EntityTransformEvent entityEvent = (EntityTransformEvent) event; - boolean reasonMatched = true; - boolean entityDataMatched = true; - if (reasons != null) - reasonMatched = Arrays.stream(reasons).anyMatch(reason -> reason == entityEvent.getTransformReason()); - if (entityData != null) - entityDataMatched = Arrays.stream(entityData).anyMatch(data -> data.isInstance(entityEvent.getEntity())); - return reasonMatched && entityDataMatched; + if (reasons != null && !reasons.check(event, reason -> reason == entityEvent.getTransformReason())) + return false; + if (entityData != null && !entityData.check(event, data -> data.isInstance(entityEvent.getEntity()))) + return false; + return true; } @Override From e357160ff25dde4c48ca45f55474b06c57a50d73 Mon Sep 17 00:00:00 2001 From: OwlBe <258166039+AnOwlBe@users.noreply.github.com> Date: Fri, 3 Jul 2026 19:37:18 -0400 Subject: [PATCH 17/35] Apply suggestions from code review Co-authored-by: SirSmurfy2 <82696841+Absolutionism@users.noreply.github.com> --- .../entity/elements/events/EvtEntityBlockChange.java | 4 +--- .../entity/elements/events/EvtEntityBreakDoor.java | 2 +- .../entity/elements/events/EvtExperienceSpawn.java | 10 ++++++---- .../entity/elements/events/EvtFireworkExplode.java | 5 +++-- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBlockChange.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBlockChange.java index cbbfde3eb16..464829b9107 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBlockChange.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBlockChange.java @@ -131,9 +131,7 @@ public boolean check(Event event) { @Override public String toString(@Nullable Event event, boolean debug) { - return new SyntaxStringBuilder(event, debug) - .append(this.event.name()) - .toString(); + return this.event.name(); } } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java index f0b5ef60915..fd028d67d94 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java @@ -27,7 +27,7 @@ Called when an entity (usually a zombie, husk, zombie pigman or zombie villager) type of event-entity is zombie broadcast "A zombie is about to murder a villager!" """) - .addSince("1.0, INSERT VERSION (new pattern)") + .addSince("1.0, INSERT VERSION (entity types)") .build()); } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtExperienceSpawn.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtExperienceSpawn.java index 0c2bffd8804..92f7b135683 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtExperienceSpawn.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtExperienceSpawn.java @@ -71,10 +71,12 @@ Please note that this event will not fire for xp orbs spawned by plugins (includ private static final AtomicBoolean REGISTERED_EXECUTORS = new AtomicBoolean(); private static final Map, EventDetails> TRACKED_EVENTS = new HashMap<>(); - public static void trackEvent(Class event, - Function getExp, - @Nullable BiConsumer setExp, - Function getLocation) { + public static void trackEvent( + Class event, + Function getExp, + @Nullable BiConsumer setExp, + Function getLocation + ) { //noinspection unchecked TRACKED_EVENTS.put(event, (EventDetails) new EventDetails<>(getExp, setExp, getLocation)); } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtFireworkExplode.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtFireworkExplode.java index 2e3ae37afe3..e50845fbf2c 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtFireworkExplode.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtFireworkExplode.java @@ -62,10 +62,11 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev List colors = new ArrayList<>(); for (FireworkEffect fireworkEffect : effects) { for (org.bukkit.Color color : fireworkEffect.getColors()) { - if (SkriptColor.fromBukkitColor(color) != null) + if (SkriptColor.fromBukkitColor(color) != null) { colors.add(SkriptColor.fromBukkitColor(color)); - else + } else { colors.add(ColorRGB.fromBukkitColor(color)); + } } } if (colors.isEmpty()) From 941e68d7f0e4a7f0a96ad5999d8d12296d2298e4 Mon Sep 17 00:00:00 2001 From: OwlBe Date: Sat, 4 Jul 2026 22:58:07 -0400 Subject: [PATCH 18/35] requested changes --- .../elements/events/EvtEntityBlockChange.java | 2 +- .../elements/events/EvtEntityDamage.java | 4 ++-- .../elements/events/EvtEntityPortal.java | 4 +--- .../elements/events/EvtEntityShootBow.java | 5 +---- .../elements/events/EvtFireworkExplode.java | 18 ++++++------------ 5 files changed, 11 insertions(+), 22 deletions(-) diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBlockChange.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBlockChange.java index cbbfde3eb16..1c97ba1a395 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBlockChange.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBlockChange.java @@ -132,7 +132,7 @@ public boolean check(Event event) { @Override public String toString(@Nullable Event event, boolean debug) { return new SyntaxStringBuilder(event, debug) - .append(this.event.name()) + .append(this.event.name().toLowerCase().replace("_", " ")) .toString(); } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java index d04862181ab..82023732319 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java @@ -64,9 +64,9 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev @Override @SuppressWarnings("unchecked") public boolean init(Literal[] args, int matchedPattern, SkriptParser.ParseResult parseResult) { - if (parseResult.hasTag("by")) + if (args[0] != null) byEntityData = (Literal>) args[1]; - if (parseResult.hasTag("of")) + if (args[0] != null) ofEntityData = (Literal>) args[0]; return true; } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityPortal.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityPortal.java index a165644334b..322806da200 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityPortal.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityPortal.java @@ -55,9 +55,7 @@ public boolean check(Event event) { @Override public String toString(@Nullable Event event, boolean debug) { - return new SyntaxStringBuilder(event, debug) - .append(isPlayer ? "player" : "entity", "portal") - .toString(); + return isPlayer ? "player" : "entity" + "portal"; } } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityShootBow.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityShootBow.java index ca8851765ad..0aa13dfecd5 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityShootBow.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityShootBow.java @@ -70,15 +70,12 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev @Override @SuppressWarnings("unchecked") public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { - if (args[0] != null) - entityData = (Literal>) args[0]; + entityData = (Literal>) args[0]; return true; } @Override public boolean check(Event event) { - if (entityData == null) - return true; EntityShootBowEvent entityEvent = (EntityShootBowEvent) event; return entityData.check(event, data -> data.isInstance(entityEvent.getEntity())); } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtFireworkExplode.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtFireworkExplode.java index 2e3ae37afe3..7d6dec1eb94 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtFireworkExplode.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtFireworkExplode.java @@ -31,7 +31,7 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(EvtFireworkExplode.class, "Firework Explode") .supplier(EvtFireworkExplode::new) .addEvent(FireworkExplodeEvent.class) - .addPatterns("[a] firework explo(d(e|ing)|sion) [color:colo[u]red %-colors%]") + .addPatterns("[a] firework explo(d(e|ing)|sion) [colo[u]red %-colors%]") .addDescription("Called when a firework explodes.") .addExample(""" on firework explode: @@ -75,15 +75,13 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev .build()); } - private Color[] colors; + private Literal colors; @Override @SuppressWarnings("unchecked") public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { - if (parseResult.hasTag("color")) { - Literal colorLiteral = (Literal) args[0]; - colors = colorLiteral.getArray(); - } + if (args[0] != null) + colors = (Literal) args[0]; return true; } @@ -93,12 +91,8 @@ public boolean check(Event event) { if (colors == null) return true; - Set colours = Arrays.stream(colors) - .map(color -> { - if (color instanceof ColorRGB) - return color.asBukkitColor(); - return color.asDyeColor().getFireworkColor(); - }) + Set colours = Arrays.stream(colors.getAll()) + .map(color -> color instanceof ColorRGB ? color.asBukkitColor() : color.asDyeColor().getFireworkColor()) .collect(Collectors.toSet()); FireworkMeta meta = entityEvent.getEntity().getFireworkMeta(); From 908d6fbddee2a2480d5e82d3730cbce8886a81d0 Mon Sep 17 00:00:00 2001 From: OwlBe <258166039+AnOwlBe@users.noreply.github.com> Date: Sat, 4 Jul 2026 22:59:49 -0400 Subject: [PATCH 19/35] Apply suggestions from code review Co-authored-by: SirSmurfy2 <82696841+Absolutionism@users.noreply.github.com> --- .../org/skriptlang/skript/bukkit/entity/EntityModule.java | 2 +- .../bukkit/entity/elements/events/EvtEntityBlockChange.java | 6 ++---- .../bukkit/entity/elements/events/EvtEntityDamage.java | 3 --- .../skript/bukkit/entity/elements/events/EvtEntityMove.java | 1 + 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/EntityModule.java b/src/main/java/org/skriptlang/skript/bukkit/entity/EntityModule.java index 20602a9bb44..7bb8fa66120 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/EntityModule.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/EntityModule.java @@ -53,7 +53,7 @@ protected void loadSelf(SkriptAddon addon) { EventValueRegistry eventValueRegistry = addon.registry(EventValueRegistry.class); - BukkitModule.register(addon.syntaxRegistry(), eventValueRegistry, + BukkitModule.register(moduleRegistry(addon), eventValueRegistry, EntityEvents::register, EvtEntityBlockChange::register, EvtEntityDamage::register, diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBlockChange.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBlockChange.java index 464829b9107..68ae5ee0383 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBlockChange.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBlockChange.java @@ -84,8 +84,7 @@ private enum ChangeEvent { // Covers all possible entity block changes. GENERIC("(entity|%*-entitydatas%) chang(e|ing) block[s]"); - @Nullable - private final Predicate checker; + private final @Nullable Predicate checker; private final String pattern; ChangeEvent(String pattern) { @@ -106,8 +105,7 @@ private enum ChangeEvent { } } - @Nullable - private Literal> entityData; + private @Nullable Literal> entityData; private ChangeEvent event; @Override diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java index d04862181ab..fb42a199b9c 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java @@ -74,9 +74,6 @@ public boolean init(Literal[] args, int matchedPattern, SkriptParser.ParseRes @Override public boolean check(Event event) { EntityDamageEvent entityDamageEvent = (EntityDamageEvent) event; - boolean entityMatched = true; - boolean healthMatched = true; - boolean damagerMatched = true; if (ofEntityData != null && !ofEntityData.check(event, data -> data.isInstance(entityDamageEvent.getEntity()))) return false; diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityMove.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityMove.java index 2c4cdff7340..28a86457cc3 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityMove.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityMove.java @@ -85,6 +85,7 @@ private enum Move { public String toString() { return name; } + } @Override From a5213b912abec38e9b38e583b5ab805219dcaf6b Mon Sep 17 00:00:00 2001 From: OwlBe <258166039+AnOwlBe@users.noreply.github.com> Date: Sat, 4 Jul 2026 23:01:32 -0400 Subject: [PATCH 20/35] Apply suggestions from code review Co-authored-by: SirSmurfy2 <82696841+Absolutionism@users.noreply.github.com> --- .../bukkit/entity/elements/events/EvtEntityBreakDoor.java | 2 +- .../bukkit/entity/elements/events/EvtEntityDamage.java | 4 ++-- .../bukkit/entity/elements/events/EvtEntityDeath.java | 2 +- .../skript/bukkit/entity/elements/events/EvtEntityHeal.java | 5 ++--- .../bukkit/entity/elements/events/EvtEntityLeash.java | 2 +- .../bukkit/entity/elements/events/EvtEntitySpawn.java | 2 +- .../bukkit/entity/elements/events/EvtEntityTeleport.java | 2 +- .../bukkit/entity/elements/events/EvtEntityTransform.java | 6 +++--- 8 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java index fd028d67d94..a8291d1e812 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java @@ -31,7 +31,7 @@ Called when an entity (usually a zombie, husk, zombie pigman or zombie villager) .build()); } - private Literal> entityData; + private @Nullable Literal> entityData; @Override @SuppressWarnings("unchecked") diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java index fb42a199b9c..fe66f8a81ca 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java @@ -58,8 +58,8 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev .build()); } - private Literal> byEntityData; - private Literal> ofEntityData; + private @Nullable Literal> byEntityData; + private @Nullable Literal> ofEntityData; @Override @SuppressWarnings("unchecked") diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDeath.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDeath.java index bfd81afbb5b..a293eb03564 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDeath.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDeath.java @@ -65,7 +65,7 @@ Called when a living entity (including players) dies. .build()); } - private Literal> entityData; + private @Nullable Literal> entityData; @Override @SuppressWarnings("unchecked") diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityHeal.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityHeal.java index c264a1e7ef6..224cc5ae71e 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityHeal.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityHeal.java @@ -47,8 +47,8 @@ or by the effect of a potion of healing (overworld mobs) or harm (nether mobs). .build()); } - private Literal> entityData; - private Literal reasons; + private @Nullable Literal> entityData; + private @Nullable Literal reasons; @Override @SuppressWarnings("unchecked") @@ -69,7 +69,6 @@ public boolean check(Event event) { if (reasons != null && !reasons.check(event, reason -> reason.equals(entityEvent.getRegainReason()))) return false; return true; - } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityLeash.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityLeash.java index 24966e49601..220aacf24e3 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityLeash.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityLeash.java @@ -83,7 +83,7 @@ public String toString() { } - private Literal> entityData; + private @Nullable Literal> entityData; private EventType eventType; @Override diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntitySpawn.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntitySpawn.java index 0bf7648b7ca..8807780793b 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntitySpawn.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntitySpawn.java @@ -37,7 +37,7 @@ public static void register(SyntaxRegistry syntaxRegistry) { .build()); } - private Literal> entityData; + private @Nullable Literal> entityData; @Override @SuppressWarnings("unchecked") diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTeleport.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTeleport.java index 0ba241ec454..5eeabd301b5 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTeleport.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTeleport.java @@ -67,7 +67,7 @@ or by other means (e.g. plugins). .build()); } - private Literal> entityData; + private @Nullable Literal> entityData; @Override @SuppressWarnings("unchecked") diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTransform.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTransform.java index c76e169382a..0f645dc92be 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTransform.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTransform.java @@ -50,14 +50,14 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev .build()); } - private Literal> entityData; - private Literal reasons; + private @Nullable Literal> entityData; + private @Nullable Literal reasons; @Override @SuppressWarnings("unchecked") public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { if (args[1] != null) - reasons = (Literal) args[1]; + reasons = (Literal) args[1]; if (args[0] != null) entityData = (Literal>) args[0]; return true; From 9400900897f7c5793d8a8f8ad774c05286336316 Mon Sep 17 00:00:00 2001 From: OwlBe Date: Sun, 5 Jul 2026 15:32:32 -0400 Subject: [PATCH 21/35] requested changes --- .../bukkit/entity/elements/EntityEvents.java | 76 +++++++++---------- .../elements/events/EvtEntityBlockChange.java | 19 +++-- .../elements/events/EvtEntityBreakDoor.java | 21 +++-- .../elements/events/EvtEntityDamage.java | 27 +++---- .../elements/events/EvtEntityDeath.java | 15 ++-- .../entity/elements/events/EvtEntityHeal.java | 18 +++-- .../elements/events/EvtEntityLeash.java | 10 ++- .../entity/elements/events/EvtEntityMove.java | 36 ++++----- .../elements/events/EvtEntityPortal.java | 9 +-- .../elements/events/EvtEntityShootBow.java | 5 +- .../elements/events/EvtEntitySpawn.java | 13 ++-- .../elements/events/EvtEntityTarget.java | 4 +- .../elements/events/EvtEntityTeleport.java | 10 ++- .../elements/events/EvtEntityTransform.java | 17 +++-- .../elements/events/EvtExperienceSpawn.java | 4 +- .../elements/events/EvtFireworkExplode.java | 10 ++- 16 files changed, 170 insertions(+), 124 deletions(-) diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/EntityEvents.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/EntityEvents.java index 04d6f5f8e12..ee8ea421882 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/EntityEvents.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/EntityEvents.java @@ -29,8 +29,8 @@ public class EntityEvents { public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry eventValueRegistry) { // - // Entity Event Values - // + // Entity Event Values + // eventValueRegistry.register(EventValue.builder(EntityEvent.class, Entity.class) .getter(EntityEvent::getEntity) @@ -60,7 +60,7 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev // // Entity Events - // + // syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Entity Combust") .addEvent(EntityCombustEvent.class) @@ -71,7 +71,7 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev """) .addExample(""" on entity combust: - broadcast "It burns!!" + broadcast "It burns!!" """) .addSince("1.0") .supplier(() -> new SimpleEvent("entity combusting")) @@ -85,7 +85,7 @@ Called when an entity (usually a primed TNT or creeper) explodes. """) .addExample(""" on entity explode: - broadcast "*Explosion*" + broadcast "*Explosion*" """) .addSince("1.0") .supplier(() -> new SimpleEvent("entity explode")) @@ -100,8 +100,8 @@ Called when an entity (usually a primed TNT or creeper) explodes. """) .addExample(""" on portal enter: - kill event-entity - broadcast "%event-entity% never got to see a new dimension.." + kill event-entity + broadcast "%event-entity% never got to see a new dimension.." """) .addSince("1.0") .supplier(() -> new SimpleEvent("entity entering a portal")) @@ -116,7 +116,7 @@ Called when an entity (usually a primed TNT or creeper) explodes. """) .addExample(""" on tame: - broadcast "Best friends for life!" + broadcast "Best friends for life!" """) .addSince("1.0") .supplier(() -> new SimpleEvent("entity taming")) @@ -130,7 +130,7 @@ Called when an entity (usually a primed TNT or creeper) explodes. """) .addExample(""" on entity mount: - cancel event + cancel event """) .addSince("2.2-dev13b") .supplier(() -> new SimpleEvent("entity mounting")) @@ -144,7 +144,7 @@ Called when an entity (usually a primed TNT or creeper) explodes. """) .addExample(""" on entity dismount: - kill event-entity + kill event-entity """) .addSince("2.2-dev13b") .supplier(() -> new SimpleEvent("entity dismounting")) @@ -160,11 +160,11 @@ Called when an entity (usually a primed TNT or creeper) explodes. """) .addExample(""" on entity resurrect attempt: - if all: - event-entity is a player - event-entity has permission "god" - then: - send "You seem to be immortal.. how" to event-entity + if all: + event-entity is a player + event-entity has permission "god" + then: + send "You seem to be immortal.. how" to event-entity """) .addSince("2.2-dev28") .supplier(() -> new SimpleEvent("entity resurrection attempt")) @@ -188,7 +188,7 @@ Called when an entity (usually a primed TNT or creeper) explodes. """) .addExample(""" on entity jump: - push event-entity up at speed 1 + push event-entity up at speed 1 """) .addSince("2.7") .supplier(() -> new SimpleEvent("entity jumping")) @@ -202,10 +202,10 @@ Called when an entity (usually a primed TNT or creeper) explodes. ) .addDescription("Called when an entity swims or stops swimming.") .addExample(""" - on swim toggle: - event-entity does not have the permission "perk.swim" - cancel event - """) + on swim toggle: + event-entity does not have the permission "perk.swim" + cancel event + """) .addSince("2.3") .supplier(() -> new SimpleEvent("entity toggling swim")) .build()); @@ -223,8 +223,8 @@ Called when an entity (usually a primed TNT or creeper) explodes. """) .addExample(""" on creeper power: - cancel event - broadcast "No charged creepers in this world!" + cancel event + broadcast "No charged creepers in this world!" """) .addSince("1.0") .supplier(() -> new SimpleEvent("creeper power")) @@ -236,8 +236,8 @@ Called when an entity (usually a primed TNT or creeper) explodes. .addDescription("Called when sheep regrows its sheared wool back.") .addExample(""" on sheep grow wool: - loop all players in radius 50 of event-entity: - send "Theres free wool nearby!" to loop-value + loop all players in radius 50 of event-entity: + send "Theres free wool nearby!" to loop-value """) .addSince("2.2-dev21") .supplier(() -> new SimpleEvent("sheep regrowing wool")) @@ -252,7 +252,7 @@ Called when an entity (usually a primed TNT or creeper) explodes. """) .addExample(""" on slime split: - broadcast "More slime minions have spawned!" + broadcast "More slime minions have spawned!" """) .addSince("2.2-dev26") .supplier(() -> new SimpleEvent("slime splitting")) @@ -264,8 +264,8 @@ Called when an entity (usually a primed TNT or creeper) explodes. .addDescription("Called when a horse jumps.") .addExample(""" on horse jumping: - push event-entity upwards at speed 2 - send "Wow that horse can really go high.." to (all players in radius 3 of event-entity) + push event-entity upwards at speed 2 + send "Wow that horse can really go high.." to (all players in radius 3 of event-entity) """) .addSince("2.5.1") .supplier(() -> new SimpleEvent("horse jumping")) @@ -281,9 +281,9 @@ Called when an entity (usually a primed TNT or creeper) explodes. """) .addExample(""" on piglin barter: - if barter drops contain diamond: - broadcast "Diamonds are too rare for this world.." - cancel event + if barter drops contain diamond: + broadcast "Diamonds are too rare for this world.." + cancel event """) .addSince("2.10") .supplier(() -> new SimpleEvent("piglin bartering")) @@ -298,7 +298,7 @@ Called when an entity (usually a primed TNT or creeper) explodes. """) .addExample(""" on pig zap: - broadcast "I'm feeling a bit static!" + broadcast "I'm feeling a bit static!" """) .addSince("1.0") .supplier(() -> new SimpleEvent("pig zap")) @@ -310,8 +310,8 @@ Called when an entity (usually a primed TNT or creeper) explodes. .addDescription("Called when a bat attempts to go to sleep or wakes up.") .addExample(""" on bat toggle sleep: - kill event-entity - broadcast "Another bat tried to sleep and perished.." + kill event-entity + broadcast "Another bat tried to sleep and perished.." """) .addSince("2.11") .supplier(() -> new SimpleEvent("bat toggling sleep")) @@ -326,7 +326,7 @@ Called when an entity (usually a primed TNT or creeper) explodes. """) .addExample(""" on villager career change: - if all: + if all: event-career change reason is employment event-villager profession is armorer profession then: @@ -363,9 +363,9 @@ Called when an entity (usually a primed TNT or creeper) explodes. """) .addExample(""" on enderman enrage: - player has permission "safe.from.enderman" - cancel event - send "well you got lucky this time.." to event-player + player has permission "safe.from.enderman" + cancel event + send "well you got lucky this time.." to event-player """) .addSince("2.9.0") .supplier(() -> new SimpleEvent("enderman enrage")) @@ -379,7 +379,7 @@ Called when an entity (usually a primed TNT or creeper) explodes. .addDescription("Called whenever an entity tries to pathfind to a location or another entity.") .addExample(""" on pathfind: - broadcast "%event-entity% is about to move to %event-location%!" + broadcast "%event-entity% is about to move to %event-location%!" """) .addSince("2.16") .addPattern("[entity] [start[s]] pathfind[ing]") diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBlockChange.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBlockChange.java index 002e38ba1a6..15a2caf0520 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBlockChange.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBlockChange.java @@ -3,6 +3,7 @@ import ch.njol.skript.bukkitutil.ItemUtils; import ch.njol.skript.entity.EntityData; import ch.njol.skript.lang.Literal; +import ch.njol.skript.lang.LiteralList; import ch.njol.skript.lang.SkriptEvent; import ch.njol.skript.lang.SkriptParser.ParseResult; import ch.njol.skript.lang.SyntaxStringBuilder; @@ -37,13 +38,13 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev """) .addExample(""" on sheep eat: - kill event-entity - broadcast "A sheep stole some grass!" + kill event-entity + broadcast "A sheep stole some grass!" """) .addExample(""" on falling block land: - event-entity is a falling dirt - cancel event + event-entity is a falling dirt + cancel event """) .addSince("unknown, 2.5.2 (falling block), 2.8.0 (any entity support)") .build()); @@ -67,7 +68,7 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev .build()); } - // this is pretty messy but was unsure of a way to really clean it up? + // this is pretty messy but was unsure of a way to really clean it up? private enum ChangeEvent { ENDERMAN_PLACE("enderman place", event -> event.getEntity() instanceof Enderman && !ItemUtils.isAir(event.getTo())), @@ -112,8 +113,11 @@ private enum ChangeEvent { @SuppressWarnings("unchecked") public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { event = ChangeEvent.values()[matchedPattern]; - if (event == ChangeEvent.GENERIC) + if (event == ChangeEvent.GENERIC) { entityData = (Literal>) args[0]; + if (entityData.getAnd() && entityData instanceof LiteralList) + ((LiteralList>) entityData).invertAnd(); + } return true; } @@ -130,7 +134,8 @@ public boolean check(Event event) { @Override public String toString(@Nullable Event event, boolean debug) { return new SyntaxStringBuilder(event, debug) - .append(this.event.name().toLowerCase().replace("_", " ")) + .appendIf(this.event != ChangeEvent.GENERIC, this.event.name().toLowerCase().replace("_", " ")) + .appendIf(this.event == ChangeEvent.GENERIC, entityData, "changing blocks") .toString(); } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java index a8291d1e812..ee715907d81 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java @@ -2,6 +2,7 @@ import ch.njol.skript.entity.EntityData; import ch.njol.skript.lang.Literal; +import ch.njol.skript.lang.LiteralList; import ch.njol.skript.lang.SkriptEvent; import ch.njol.skript.lang.SkriptParser.ParseResult; import ch.njol.skript.lang.SyntaxStringBuilder; @@ -24,8 +25,12 @@ Called when an entity (usually a zombie, husk, zombie pigman or zombie villager) """) .addExample(""" on entity breaking a door: - type of event-entity is zombie - broadcast "A zombie is about to murder a villager!" + type of event-entity is zombie + broadcast "A zombie is about to murder a villager!" + """) + .addExample(""" + on husk breaking a door: + broadcast "Rest in peace villagers.." """) .addSince("1.0, INSERT VERSION (entity types)") .build()); @@ -38,17 +43,19 @@ Called when an entity (usually a zombie, husk, zombie pigman or zombie villager) public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { if (args[0] != null) { entityData = (Literal>) args[0]; + if (entityData.getAnd() && entityData instanceof LiteralList) + ((LiteralList>) entityData).invertAnd(); } return true; } @Override public boolean check(Event event) { - if (entityData != null) { - EntityBreakDoorEvent entityEvent = (EntityBreakDoorEvent) event; - return entityData.check(event, data -> data.isInstance((entityEvent.getEntity()))); - } - return true; + if (entityData == null) + return true; + + EntityBreakDoorEvent entityEvent = (EntityBreakDoorEvent) event; + return entityData.check(event, data -> data.isInstance((entityEvent.getEntity()))); } @Override diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java index f7210c6e469..34e8d27594d 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java @@ -2,10 +2,7 @@ import ch.njol.skript.bukkitutil.HealthUtils; import ch.njol.skript.entity.EntityData; -import ch.njol.skript.lang.Literal; -import ch.njol.skript.lang.SkriptEvent; -import ch.njol.skript.lang.SkriptParser; -import ch.njol.skript.lang.SyntaxStringBuilder; +import ch.njol.skript.lang.*; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Projectile; import org.bukkit.event.Event; @@ -18,8 +15,6 @@ import org.skriptlang.skript.bukkit.registration.BukkitSyntaxInfos; import org.skriptlang.skript.registration.SyntaxRegistry; -import java.util.Arrays; - public class EvtEntityDamage extends SkriptEvent { public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry eventValueRegistry) { @@ -33,14 +28,14 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev """) .addExample(""" on damage of player by player: - send "Send you are being attacked.. defend yourself!" to victim - send "You better win this fight.." to attacker + send "Send you are being attacked.. defend yourself!" to victim + send "You better win this fight.." to attacker """) .addExample(""" on damage of bee: - broadcast "A poor bee was just damaged :(" - if attacker is a player: - send "You monster.." to attacker + broadcast "A poor bee was just damaged :(" + if attacker is a player: + send "You monster.." to attacker """) .addSince("1.0, 2.7 (by entity)") .build()); @@ -64,10 +59,16 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev @Override @SuppressWarnings("unchecked") public boolean init(Literal[] args, int matchedPattern, SkriptParser.ParseResult parseResult) { - if (args[0] != null) + if (args[0] != null) { byEntityData = (Literal>) args[1]; - if (args[0] != null) + if (byEntityData.getAnd() && byEntityData instanceof LiteralList) + ((LiteralList>) byEntityData).invertAnd(); + } + if (args[0] != null) { ofEntityData = (Literal>) args[0]; + if (ofEntityData.getAnd() && ofEntityData instanceof LiteralList) + ((LiteralList>) ofEntityData).invertAnd(); + } return true; } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDeath.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDeath.java index a293eb03564..7c5b6a98eee 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDeath.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDeath.java @@ -3,6 +3,7 @@ import ch.njol.skript.Skript; import ch.njol.skript.entity.EntityData; import ch.njol.skript.lang.Literal; +import ch.njol.skript.lang.LiteralList; import ch.njol.skript.lang.SkriptEvent; import ch.njol.skript.lang.SkriptParser.ParseResult; import ch.njol.skript.lang.SyntaxStringBuilder; @@ -29,17 +30,17 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev .addEvent(EntityDeathEvent.class) .addPatterns("death [of %-entitydatas%]") .addDescription(""" - Called when a living entity (including players) dies. - See attacker/victim/ for how to get the victim or attacker in this event. - """) + Called when a living entity (including players) dies. + See attacker/victim/ for how to get the victim or attacker in this event. + """) .addExample(""" on death of player: - send "You died.. tragic" to victim - send "Nice kill.. did you get any loot?" to attacker + send "You died.. tragic" to victim + send "Nice kill.. did you get any loot?" to attacker """) .addExample(""" on death of a wither or ender dragon: - broadcast "A great boss has been slain today.." + broadcast "A great boss has been slain today.." """) .addSince("1.0") .build()); @@ -78,6 +79,8 @@ public boolean init(Literal[] args, int matchedPattern, ParseResult parseResu return false; } } + if (entityData.getAnd() && entityData instanceof LiteralList) + ((LiteralList>) entityData).invertAnd(); } return true; } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityHeal.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityHeal.java index 224cc5ae71e..f20a9b319cd 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityHeal.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityHeal.java @@ -2,6 +2,7 @@ import ch.njol.skript.entity.EntityData; import ch.njol.skript.lang.Literal; +import ch.njol.skript.lang.LiteralList; import ch.njol.skript.lang.SkriptEvent; import ch.njol.skript.lang.SkriptParser.ParseResult; import ch.njol.skript.lang.SyntaxStringBuilder; @@ -32,12 +33,12 @@ or by the effect of a potion of healing (overworld mobs) or harm (nether mobs). """) .addExample(""" on healing of a zombie, cow or a wither: - event-heal reason is healing potion - cancel event + event-heal reason is healing potion + cancel event """) .addExample(""" on player healing from a regeneration potion: - send "all better!" to event-entity + send "all better!" to event-entity """) .addSince("1.0, 2.9.0 (by reason)") .build()); @@ -53,11 +54,16 @@ or by the effect of a potion of healing (overworld mobs) or harm (nether mobs). @Override @SuppressWarnings("unchecked") public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { - if (args[0] != null) + if (args[0] != null) { entityData = (Literal>) args[0]; - - if (args[1] != null) + if (entityData.getAnd() && entityData instanceof LiteralList) + ((LiteralList>) entityData).invertAnd(); + } + if (args[1] != null) { reasons = (Literal) args[1]; + if (reasons.getAnd() && reasons instanceof LiteralList) + ((LiteralList) reasons).invertAnd(); + } return true; } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityLeash.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityLeash.java index 220aacf24e3..3b37ddb2dd0 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityLeash.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityLeash.java @@ -2,6 +2,7 @@ import ch.njol.skript.entity.EntityData; import ch.njol.skript.lang.Literal; +import ch.njol.skript.lang.LiteralList; import ch.njol.skript.lang.SkriptEvent; import ch.njol.skript.lang.SkriptParser.ParseResult; import ch.njol.skript.lang.SyntaxStringBuilder; @@ -32,7 +33,7 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev """) .addExample(""" on player leash of a sheep: - send "Baaaaa--" to player + send "Baaaaa--" to player """) .addExample(""" on player leash: @@ -40,7 +41,7 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev """) .addExample(""" on unleash: - broadcast "<%event-entity%> I'm free!" + broadcast "<%event-entity%> I'm free!" """) .addSince("2.10") .build()); @@ -89,8 +90,11 @@ public String toString() { @Override @SuppressWarnings("unchecked") public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { - if (args[0] != null) + if (args[0] != null) { entityData = (Literal>) args[0]; + if (entityData.getAnd() && entityData instanceof LiteralList) + ((LiteralList>) entityData).invertAnd(); + } eventType = EventType.LEASH; if (parseResult.hasTag("un")) { diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityMove.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityMove.java index 28a86457cc3..126855113f3 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityMove.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityMove.java @@ -29,28 +29,28 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev "%entitydata% (turn[ing] around|rotate) or (move|walk|step)" ) .addDescription(""" - Called when a player or entity moves or rotates their head. - The move event will only be called when the entity/player moves position, - keyword 'turn around' is for orientation (ie: looking around), - and the combined syntax listens for both. - Note that this event is called extremely often and may cause performance issues. - """) + Called when a player or entity moves or rotates their head. + The move event will only be called when the entity/player moves position, + keyword 'turn around' is for orientation (ie: looking around), + and the combined syntax listens for both. + Note that this event is called extremely often and may cause performance issues. + """) .addExample(""" - on player move: - if {frozen::%player's uuid%} is set: - cancel event - send actionbar "You are frozen!" to player - // Generally not recommended over setting movement & jump attributes but useful for older servers - """) + on player move: + if {frozen::%player's uuid%} is set: + cancel event + send actionbar "You are frozen!" to player + // Generally not recommended over setting movement & jump attributes but useful for older servers + """) .addExample(""" - on player turning around: - send "BOO!" to player - spawn skeleton behind player - """) + on player turning around: + send "BOO!" to player + spawn skeleton behind player + """) .addExample(""" on skeleton move: - if event-world is "no_skeleton_movement": - cancel event + if event-world is "no_skeleton_movement": + cancel event """) .addSince("2.6, 2.8.0 (turn around)") .build()); diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityPortal.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityPortal.java index 322806da200..2145988acc3 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityPortal.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityPortal.java @@ -3,7 +3,6 @@ import ch.njol.skript.lang.Literal; import ch.njol.skript.lang.SkriptEvent; import ch.njol.skript.lang.SkriptParser.ParseResult; -import ch.njol.skript.lang.SyntaxStringBuilder; import ch.njol.util.coll.CollectionUtils; import org.bukkit.event.Event; import org.bukkit.event.entity.EntityPortalEvent; @@ -26,13 +25,13 @@ public static void register(SyntaxRegistry syntaxRegistry) { """) .addExample(""" on portal: - broadcast "An entity has entered a portal!" + broadcast "An entity has entered a portal!" """) .addExample(""" on player portal: - player's world is world("wilderness") - set world of event-location to player's world - add 9000 to x-pos of event-location + player's world is world("wilderness") + set world of event-location to player's world + add 9000 to x-pos of event-location """) .addSince("1.0, 2.5.3 (entities), 2.13 (location changers)") .build()); diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityShootBow.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityShootBow.java index 0aa13dfecd5..da2293f014e 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityShootBow.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityShootBow.java @@ -3,6 +3,7 @@ import ch.njol.skript.classes.Changer.ChangeMode; import ch.njol.skript.entity.EntityData; import ch.njol.skript.lang.Literal; +import ch.njol.skript.lang.LiteralList; import ch.njol.skript.lang.SkriptEvent; import ch.njol.skript.lang.SkriptParser.ParseResult; import ch.njol.skript.lang.SyntaxStringBuilder; @@ -41,7 +42,7 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev spawn a cow at event-entity: set velocity of entity to velocity of event-entity set {_e} to entity - set event-entity to {_e} + set event-entity to {_e} """) .addSince("2.11") .build()); @@ -71,6 +72,8 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev @SuppressWarnings("unchecked") public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { entityData = (Literal>) args[0]; + if (entityData.getAnd() && entityData instanceof LiteralList) + ((LiteralList>) entityData).invertAnd(); return true; } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntitySpawn.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntitySpawn.java index 8807780793b..c1eb8d9a4b2 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntitySpawn.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntitySpawn.java @@ -3,6 +3,7 @@ import ch.njol.skript.Skript; import ch.njol.skript.entity.EntityData; import ch.njol.skript.lang.Literal; +import ch.njol.skript.lang.LiteralList; import ch.njol.skript.lang.SkriptEvent; import ch.njol.skript.lang.SkriptParser.ParseResult; import ch.njol.skript.lang.SyntaxStringBuilder; @@ -24,14 +25,14 @@ public static void register(SyntaxRegistry syntaxRegistry) { .addDescription("Called when an entity spawns (excluding players).") .addExample(""" on spawn of a zombie: - chance of 5%: - set scale attribute of event-entity to 3 - broadcast "A mega zombie has spawned!" + chance of 5%: + set scale attribute of event-entity to 3 + broadcast "A mega zombie has spawned!" """) .addExample(""" on spawn of an ender dragon: - loop all players in radius 120 of event-entity: - send "A great beast has been seen near you.." to loop-value + loop all players in radius 120 of event-entity: + send "A great beast has been seen near you.." to loop-value """) .addSince("1.0, 2.5.1 (non-living entities)") .build()); @@ -50,6 +51,8 @@ public boolean init(Literal[] args, int matchedPattern, ParseResult parseResu return false; } } + if (entityData.getAnd() && entityData instanceof LiteralList) + ((LiteralList>) entityData).invertAnd(); } return true; } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTarget.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTarget.java index c587b11ebb8..1e17b1787e5 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTarget.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTarget.java @@ -23,11 +23,11 @@ public static void register(SyntaxRegistry syntaxRegistry) { """) .addExample(""" on entity target: - broadcast "I detect an entity is targeting another.." + broadcast "I detect an entity is targeting another.." """) .addExample(""" on entity untarget: - broadcast "Phew.. it looks like they stopped.." + broadcast "Phew.. it looks like they stopped.." """) .addSince("1.0") .build()); diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTeleport.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTeleport.java index 5eeabd301b5..c41272c2e79 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTeleport.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTeleport.java @@ -1,6 +1,7 @@ package org.skriptlang.skript.bukkit.entity.elements.events; import ch.njol.skript.classes.Changer.ChangeMode; +import ch.njol.skript.lang.LiteralList; import ch.njol.util.coll.CollectionUtils; import org.bukkit.Location; import org.bukkit.event.entity.EntityTeleportEvent; @@ -35,11 +36,11 @@ or by other means (e.g. plugins). """) .addExample(""" on player teleport: - send "Well you somehow teleported.." to player + send "Well you somehow teleported.." to player """) .addExample(""" on wolf teleport: - send "Your wolf just teleported!" to owner of event-entity + send "Your wolf just teleported!" to owner of event-entity """) .addSince("1.0, 2.9.0 (entity teleport)") .build()); @@ -72,8 +73,11 @@ or by other means (e.g. plugins). @Override @SuppressWarnings("unchecked") public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { - if (args[0] != null) + if (args[0] != null) { entityData = (Literal>) args[0]; + if (entityData.getAnd() && entityData instanceof LiteralList) + ((LiteralList>) entityData).invertAnd(); + } return true; } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTransform.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTransform.java index 0f645dc92be..d6bf6045a8e 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTransform.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTransform.java @@ -2,6 +2,7 @@ import ch.njol.skript.entity.EntityData; import ch.njol.skript.lang.Literal; +import ch.njol.skript.lang.LiteralList; import ch.njol.skript.lang.SkriptEvent; import ch.njol.skript.lang.SkriptParser.ParseResult; import ch.njol.skript.lang.SyntaxStringBuilder; @@ -31,12 +32,12 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev """) .addExample(""" on a zombie transforming due to curing: - broadcast "Another one cured from this madness.." + broadcast "Another one cured from this madness.." """) .addExample(""" on mooshroom transforming: - cancel event - broadcast "forever a mooshroom!" + cancel event + broadcast "forever a mooshroom!" """) .addSince("2.8.0") .build()); @@ -56,10 +57,16 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev @Override @SuppressWarnings("unchecked") public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { - if (args[1] != null) + if (args[1] != null) { reasons = (Literal) args[1]; - if (args[0] != null) + if (reasons.getAnd() && reasons instanceof LiteralList) + ((LiteralList) reasons).invertAnd(); + } + if (args[0] != null) { entityData = (Literal>) args[0]; + if (entityData.getAnd() && entityData instanceof LiteralList) + ((LiteralList>) entityData).invertAnd(); + } return true; } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtExperienceSpawn.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtExperienceSpawn.java index 92f7b135683..2a746399867 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtExperienceSpawn.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtExperienceSpawn.java @@ -47,8 +47,8 @@ Please note that this event will not fire for xp orbs spawned by plugins (includ """) .addExample(""" on xp spawn: - event-world is not world("experience") - cancel event + event-world is not world("experience") + cancel event """) .addSince("2.0") .build()); diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtFireworkExplode.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtFireworkExplode.java index fec80470bb2..d35097b0ab3 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtFireworkExplode.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtFireworkExplode.java @@ -2,6 +2,7 @@ import ch.njol.skript.lang.Literal; +import ch.njol.skript.lang.LiteralList; import ch.njol.skript.lang.SkriptEvent; import ch.njol.skript.lang.SkriptParser.ParseResult; import ch.njol.skript.lang.SyntaxStringBuilder; @@ -35,8 +36,8 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev .addDescription("Called when a firework explodes.") .addExample(""" on firework explode: - if event-colors contains red: - broadcast "its a red firework!" + if event-colors contains red: + broadcast "its a red firework!" """) .addSince("2.4") .build()); @@ -81,8 +82,11 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev @Override @SuppressWarnings("unchecked") public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { - if (args[0] != null) + if (args[0] != null) { colors = (Literal) args[0]; + if (colors.getAnd() && colors instanceof LiteralList) + ((LiteralList) colors).invertAnd(); + } return true; } From f03ba394382e742a36e0f880c7c3dc6090874f37 Mon Sep 17 00:00:00 2001 From: OwlBe <258166039+AnOwlBe@users.noreply.github.com> Date: Sun, 5 Jul 2026 15:33:07 -0400 Subject: [PATCH 22/35] Update src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java Co-authored-by: SirSmurfy2 <82696841+Absolutionism@users.noreply.github.com> --- .../skript/bukkit/entity/elements/events/EvtEntityDamage.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java index 34e8d27594d..6f3a4c22132 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java @@ -21,7 +21,7 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(EvtEntityDamage.class, "Entity Damage") .supplier(EvtEntityDamage::new) .addEvent(EntityDamageEvent.class) - .addPatterns("damag(e|ing) [of:of %-entitydata%] [by:by %-entitydata%]") + .addPatterns("damag(e|ing) [of %-entitydata%] [by %-entitydata%]") .addDescription(""" Called when an entity receives damage, e.g. by an attack from another entity, lava, fire, drowning, fall, suffocation, etc. See attacker/victim/ for how to get the victim or attacker in this event. From 3f551759fbd11c963dc7104fd0511c9d3c24232f Mon Sep 17 00:00:00 2001 From: OwlBe Date: Sun, 5 Jul 2026 17:02:49 -0400 Subject: [PATCH 23/35] should fix tests failing --- .../bukkit/entity/elements/events/EvtEntityBlockChange.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBlockChange.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBlockChange.java index 15a2caf0520..bce396ec26c 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBlockChange.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBlockChange.java @@ -115,6 +115,8 @@ public boolean init(Literal[] args, int matchedPattern, ParseResult parseResu event = ChangeEvent.values()[matchedPattern]; if (event == ChangeEvent.GENERIC) { entityData = (Literal>) args[0]; + if (entityData == null) + return true; if (entityData.getAnd() && entityData instanceof LiteralList) ((LiteralList>) entityData).invertAnd(); } From 3ed83a5ff0eca9c2cdaea9017dc5c59734e0e251 Mon Sep 17 00:00:00 2001 From: OwlBe Date: Sun, 5 Jul 2026 17:51:59 -0400 Subject: [PATCH 24/35] should fix tests failing [2x] --- .../skript/bukkit/entity/elements/events/EvtEntityDamage.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java index 6f3a4c22132..9f7e7183560 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java @@ -59,7 +59,7 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev @Override @SuppressWarnings("unchecked") public boolean init(Literal[] args, int matchedPattern, SkriptParser.ParseResult parseResult) { - if (args[0] != null) { + if (args[1] != null) { byEntityData = (Literal>) args[1]; if (byEntityData.getAnd() && byEntityData instanceof LiteralList) ((LiteralList>) byEntityData).invertAnd(); From 59148b5fed1d8c526a39cf228355a12492c38a42 Mon Sep 17 00:00:00 2001 From: OwlBe Date: Sun, 5 Jul 2026 18:00:25 -0400 Subject: [PATCH 25/35] requested changes --- .../entity/elements/events/EvtEntityBlockChange.java | 4 ++-- .../bukkit/entity/elements/events/EvtEntityBreakDoor.java | 4 ++-- .../bukkit/entity/elements/events/EvtEntityDamage.java | 8 ++++---- .../bukkit/entity/elements/events/EvtEntityDeath.java | 4 ++-- .../bukkit/entity/elements/events/EvtEntityHeal.java | 8 ++++---- .../bukkit/entity/elements/events/EvtEntityLeash.java | 4 ++-- .../bukkit/entity/elements/events/EvtEntityShootBow.java | 4 ++-- .../bukkit/entity/elements/events/EvtEntitySpawn.java | 4 ++-- .../bukkit/entity/elements/events/EvtEntityTeleport.java | 4 ++-- .../bukkit/entity/elements/events/EvtEntityTransform.java | 8 ++++---- .../bukkit/entity/elements/events/EvtFireworkExplode.java | 4 ++-- 11 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBlockChange.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBlockChange.java index bce396ec26c..47619600bbc 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBlockChange.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBlockChange.java @@ -117,8 +117,8 @@ public boolean init(Literal[] args, int matchedPattern, ParseResult parseResu entityData = (Literal>) args[0]; if (entityData == null) return true; - if (entityData.getAnd() && entityData instanceof LiteralList) - ((LiteralList>) entityData).invertAnd(); + if (entityData.getAnd() && entityData instanceof LiteralList> list) + list.invertAnd(); } return true; } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java index ee715907d81..75ca22a218e 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java @@ -43,8 +43,8 @@ Called when an entity (usually a zombie, husk, zombie pigman or zombie villager) public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { if (args[0] != null) { entityData = (Literal>) args[0]; - if (entityData.getAnd() && entityData instanceof LiteralList) - ((LiteralList>) entityData).invertAnd(); + if (entityData.getAnd() && entityData instanceof LiteralList> list) + list.invertAnd(); } return true; } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java index 9f7e7183560..c848a679d18 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java @@ -61,13 +61,13 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev public boolean init(Literal[] args, int matchedPattern, SkriptParser.ParseResult parseResult) { if (args[1] != null) { byEntityData = (Literal>) args[1]; - if (byEntityData.getAnd() && byEntityData instanceof LiteralList) - ((LiteralList>) byEntityData).invertAnd(); + if (byEntityData.getAnd() && byEntityData instanceof LiteralList> list) + list.invertAnd(); } if (args[0] != null) { ofEntityData = (Literal>) args[0]; - if (ofEntityData.getAnd() && ofEntityData instanceof LiteralList) - ((LiteralList>) ofEntityData).invertAnd(); + if (ofEntityData.getAnd() && ofEntityData instanceof LiteralList> list) + list.invertAnd(); } return true; } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDeath.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDeath.java index 7c5b6a98eee..36b63fdc68f 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDeath.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDeath.java @@ -79,8 +79,8 @@ public boolean init(Literal[] args, int matchedPattern, ParseResult parseResu return false; } } - if (entityData.getAnd() && entityData instanceof LiteralList) - ((LiteralList>) entityData).invertAnd(); + if (entityData.getAnd() && entityData instanceof LiteralList> list) + list.invertAnd(); } return true; } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityHeal.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityHeal.java index f20a9b319cd..c6c31e3b7ce 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityHeal.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityHeal.java @@ -56,13 +56,13 @@ or by the effect of a potion of healing (overworld mobs) or harm (nether mobs). public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { if (args[0] != null) { entityData = (Literal>) args[0]; - if (entityData.getAnd() && entityData instanceof LiteralList) - ((LiteralList>) entityData).invertAnd(); + if (entityData.getAnd() && entityData instanceof LiteralList> list) + list.invertAnd(); } if (args[1] != null) { reasons = (Literal) args[1]; - if (reasons.getAnd() && reasons instanceof LiteralList) - ((LiteralList) reasons).invertAnd(); + if (reasons.getAnd() && reasons instanceof LiteralList list) + list.invertAnd(); } return true; } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityLeash.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityLeash.java index 3b37ddb2dd0..2fcb559c5a5 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityLeash.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityLeash.java @@ -92,8 +92,8 @@ public String toString() { public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { if (args[0] != null) { entityData = (Literal>) args[0]; - if (entityData.getAnd() && entityData instanceof LiteralList) - ((LiteralList>) entityData).invertAnd(); + if (entityData.getAnd() && entityData instanceof LiteralList> list) + list.invertAnd(); } eventType = EventType.LEASH; diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityShootBow.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityShootBow.java index da2293f014e..c9b9afa446a 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityShootBow.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityShootBow.java @@ -72,8 +72,8 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev @SuppressWarnings("unchecked") public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { entityData = (Literal>) args[0]; - if (entityData.getAnd() && entityData instanceof LiteralList) - ((LiteralList>) entityData).invertAnd(); + if (entityData.getAnd() && entityData instanceof LiteralList> list) + list.invertAnd(); return true; } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntitySpawn.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntitySpawn.java index c1eb8d9a4b2..73528c17877 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntitySpawn.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntitySpawn.java @@ -51,8 +51,8 @@ public boolean init(Literal[] args, int matchedPattern, ParseResult parseResu return false; } } - if (entityData.getAnd() && entityData instanceof LiteralList) - ((LiteralList>) entityData).invertAnd(); + if (entityData.getAnd() && entityData instanceof LiteralList> list) + list.invertAnd(); } return true; } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTeleport.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTeleport.java index c41272c2e79..b353a14c4f7 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTeleport.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTeleport.java @@ -75,8 +75,8 @@ or by other means (e.g. plugins). public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { if (args[0] != null) { entityData = (Literal>) args[0]; - if (entityData.getAnd() && entityData instanceof LiteralList) - ((LiteralList>) entityData).invertAnd(); + if (entityData.getAnd() && entityData instanceof LiteralList> list) + list.invertAnd(); } return true; } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTransform.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTransform.java index d6bf6045a8e..2351dfff0c8 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTransform.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTransform.java @@ -59,13 +59,13 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { if (args[1] != null) { reasons = (Literal) args[1]; - if (reasons.getAnd() && reasons instanceof LiteralList) - ((LiteralList) reasons).invertAnd(); + if (reasons.getAnd() && reasons instanceof LiteralList list) + list.invertAnd(); } if (args[0] != null) { entityData = (Literal>) args[0]; - if (entityData.getAnd() && entityData instanceof LiteralList) - ((LiteralList>) entityData).invertAnd(); + if (entityData.getAnd() && entityData instanceof LiteralList> list) + list.invertAnd(); } return true; } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtFireworkExplode.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtFireworkExplode.java index d35097b0ab3..ce333b0fc2b 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtFireworkExplode.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtFireworkExplode.java @@ -84,8 +84,8 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { if (args[0] != null) { colors = (Literal) args[0]; - if (colors.getAnd() && colors instanceof LiteralList) - ((LiteralList) colors).invertAnd(); + if (colors.getAnd() && colors instanceof LiteralList lis) + lis.invertAnd(); } return true; } From da1aec6785ce371dbf2de67b96a209cd2e05d369 Mon Sep 17 00:00:00 2001 From: OwlBe Date: Wed, 8 Jul 2026 20:29:57 -0400 Subject: [PATCH 26/35] small thing noticed --- .../bukkit/entity/elements/events/EvtFireworkExplode.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtFireworkExplode.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtFireworkExplode.java index ce333b0fc2b..73dfe2129f1 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtFireworkExplode.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtFireworkExplode.java @@ -84,8 +84,8 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { if (args[0] != null) { colors = (Literal) args[0]; - if (colors.getAnd() && colors instanceof LiteralList lis) - lis.invertAnd(); + if (colors.getAnd() && colors instanceof LiteralList list) + list.invertAnd(); } return true; } From fd84805119b2e101ed738ce136530f14631c2817 Mon Sep 17 00:00:00 2001 From: OwlBe Date: Sat, 11 Jul 2026 17:34:31 -0400 Subject: [PATCH 27/35] adds projectile + vehicle + other misc entity events --- .../classes/data/BukkitEventValues.java | 93 +----- .../java/ch/njol/skript/events/EvtItem.java | 29 +- .../ch/njol/skript/events/SimpleEvents.java | 70 ----- .../skript/bukkit/entity/EntityModule.java | 6 +- .../bukkit/entity/elements/EntityEvents.java | 290 ++++++++++++++++-- .../elements/events/EvtEntityDropItem.java | 134 ++++++++ .../elements/events/EvtEntityPickupItem.java | 101 ++++++ .../elements/events/EvtEntityTarget.java | 1 - .../elements/events/EvtProjectileCollide.java | 62 ++++ .../elements}/events/EvtVehicleCollision.java | 75 +++-- 10 files changed, 621 insertions(+), 240 deletions(-) create mode 100644 src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDropItem.java create mode 100644 src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityPickupItem.java create mode 100644 src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtProjectileCollide.java rename src/main/java/{ch/njol/skript => org/skriptlang/skript/bukkit/entity/elements}/events/EvtVehicleCollision.java (60%) 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 09ae089a6c9..50576e8ef39 100644 --- a/src/main/java/ch/njol/skript/classes/data/BukkitEventValues.java +++ b/src/main/java/ch/njol/skript/classes/data/BukkitEventValues.java @@ -192,62 +192,9 @@ public static void register(EventValueRegistry registry) { registry.register(EventValue.simple(SignChangeEvent.class, Player.class, SignChangeEvent::getPlayer)); registry.register(EventValue.simple(SignChangeEvent.class, Component[].class, event -> event.lines().toArray(new Component[0]))); - // ProjectileHitEvent - // ProjectileHitEvent#getHitBlock was added in 1.11 - if (Skript.methodExists(ProjectileHitEvent.class, "getHitBlock")) - registry.register(EventValue.simple(ProjectileHitEvent.class, Block.class, ProjectileHitEvent::getHitBlock)); - registry.register(EventValue.builder(ProjectileHitEvent.class, Entity.class) - .getter(event -> { - assert false; - return event.getEntity(); - }) - .excludes(ProjectileHitEvent.class) - .excludedErrorMessage("Use 'projectile' and/or 'shooter' in projectile hit events") - .build()); - registry.register(EventValue.simple(ProjectileHitEvent.class, Projectile.class, ProjectileHitEvent::getEntity)); - if (Skript.methodExists(ProjectileHitEvent.class, "getHitBlockFace")) { - registry.register(EventValue.simple(ProjectileHitEvent.class, Direction.class, event -> { - BlockFace theHitFace = event.getHitBlockFace(); - if (theHitFace == null) return null; - return new Direction(theHitFace, 1); - })); - } - // ProjectileLaunchEvent - registry.register(EventValue.builder(ProjectileLaunchEvent.class, Entity.class) - .getter(event -> { - assert false; - return event.getEntity(); - }) - .excludes(ProjectileLaunchEvent.class) - .excludedErrorMessage("Use 'projectile' and/or 'shooter' in shoot events") - .build()); - //ProjectileCollideEvent - if (Skript.classExists("com.destroystokyo.paper.event.entity.ProjectileCollideEvent")) { - registry.register(EventValue.simple(ProjectileCollideEvent.class, Projectile.class, ProjectileCollideEvent::getEntity)); - registry.register(EventValue.simple(ProjectileCollideEvent.class, Entity.class, ProjectileCollideEvent::getCollidedWith)); - } - registry.register(EventValue.simple(ProjectileLaunchEvent.class, Projectile.class, ProjectileLaunchEvent::getEntity)); // EntityTameEvent registry.register(EventValue.simple(EntityTameEvent.class, Entity.class, EntityTameEvent::getEntity)); - // AreaEffectCloudApplyEvent - registry.register(EventValue.simple(AreaEffectCloudApplyEvent.class, LivingEntity[].class, event -> event.getAffectedEntities().toArray(new LivingEntity[0]))); - registry.register(EventValue.simple(AreaEffectCloudApplyEvent.class, PotionEffectType.class, new Converter<>() { - private final boolean HAS_POTION_TYPE_METHOD = Skript.methodExists(AreaEffectCloud.class, "getBasePotionType"); - - @Override - public PotionEffectType convert(AreaEffectCloudApplyEvent event) { - // TODO needs to be reworked to support multiple values (there can be multiple potion effects) - if (HAS_POTION_TYPE_METHOD) { - PotionType base = event.getEntity().getBasePotionType(); - if (base != null) - return base.getEffectType(); - } else { - return event.getEntity().getBasePotionData().getType().getEffectType(); - } - return null; - } - })); // ItemSpawnEvent registry.register(EventValue.simple(ItemSpawnEvent.class, ItemStack.class, event -> event.getEntity().getItemStack())); // LightningStrikeEvent @@ -279,23 +226,7 @@ public PotionEffectType convert(AreaEffectCloudApplyEvent event) { state.setType(event.getBucket() == Material.WATER_BUCKET ? Material.WATER : Material.LAVA); return new BlockStateBlock(state, true); })); - // PlayerDropItemEvent - registry.register(EventValue.simple(PlayerDropItemEvent.class, Player.class, PlayerEvent::getPlayer)); - registry.register(EventValue.simple(PlayerDropItemEvent.class, Item.class, PlayerDropItemEvent::getItemDrop)); - registry.register(EventValue.simple(PlayerDropItemEvent.class, ItemStack.class, event -> event.getItemDrop().getItemStack())); - registry.register(EventValue.simple(PlayerDropItemEvent.class, Entity.class, PlayerEvent::getPlayer)); - // EntityDropItemEvent - registry.register(EventValue.simple(EntityDropItemEvent.class, Item.class, EntityDropItemEvent::getItemDrop)); - registry.register(EventValue.simple(EntityDropItemEvent.class, ItemStack.class, event -> event.getItemDrop().getItemStack())); - // PlayerPickupItemEvent - registry.register(EventValue.simple(PlayerPickupItemEvent.class, Player.class, PlayerEvent::getPlayer)); - registry.register(EventValue.simple(PlayerPickupItemEvent.class, Item.class, PlayerPickupItemEvent::getItem)); - registry.register(EventValue.simple(PlayerPickupItemEvent.class, ItemStack.class, event -> event.getItem().getItemStack())); - registry.register(EventValue.simple(PlayerPickupItemEvent.class, Entity.class, PlayerEvent::getPlayer)); - // EntityPickupItemEvent - registry.register(EventValue.simple(EntityPickupItemEvent.class, Entity.class, EntityPickupItemEvent::getEntity)); - registry.register(EventValue.simple(EntityPickupItemEvent.class, Item.class, EntityPickupItemEvent::getItem)); - registry.register(EventValue.simple(EntityPickupItemEvent.class, ItemType.class, event -> new ItemType(event.getItem().getItemStack()))); + // PlayerItemConsumeEvent registry.register(EventValue.builder(PlayerItemConsumeEvent.class, ItemStack.class) .getter(PlayerItemConsumeEvent::getItem) @@ -355,21 +286,6 @@ else if (hand == EquipmentSlot.OFF_HAND) // HangingPlaceEvent registry.register(EventValue.simple(HangingPlaceEvent.class, Player.class, HangingPlaceEvent::getPlayer)); - // --- VehicleEvents --- - registry.register(EventValue.simple(VehicleEvent.class, Vehicle.class, VehicleEvent::getVehicle)); - registry.register(EventValue.simple(VehicleEvent.class, World.class, event -> event.getVehicle().getWorld())); - registry.register(EventValue.simple(VehicleExitEvent.class, LivingEntity.class, VehicleExitEvent::getExited)); - - registry.register(EventValue.simple(VehicleEnterEvent.class, Entity.class, VehicleEnterEvent::getEntered)); - - // We could error here instead but it's preferable to not do it in this case - registry.register(EventValue.simple(VehicleDamageEvent.class, Entity.class, VehicleDamageEvent::getAttacker)); - - registry.register(EventValue.simple(VehicleDestroyEvent.class, Entity.class, VehicleDestroyEvent::getAttacker)); - - registry.register(EventValue.simple(VehicleEvent.class, Entity.class, event -> event.getVehicle().getPassenger())); - - // === CommandEvents === // PlayerCommandPreprocessEvent is a PlayerEvent registry.register(EventValue.simple(ServerCommandEvent.class, CommandSender.class, ServerCommandEvent::getSender)); @@ -678,13 +594,6 @@ else if (hand == EquipmentSlot.OFF_HAND) .time(Time.PAST) .build()); - // VehicleMoveEvent - registry.register(EventValue.simple(VehicleMoveEvent.class, Location.class, VehicleMoveEvent::getTo)); - registry.register(EventValue.builder(VehicleMoveEvent.class, Location.class) - .getter(VehicleMoveEvent::getFrom) - .time(Time.PAST) - .build()); - // BeaconEffectEvent if (Skript.classExists("com.destroystokyo.paper.event.block.BeaconEffectEvent")) { registry.register(EventValue.builder(BeaconEffectEvent.class, PotionEffectType.class) diff --git a/src/main/java/ch/njol/skript/events/EvtItem.java b/src/main/java/ch/njol/skript/events/EvtItem.java index 6bb505a76bd..fee8b0c2ea9 100644 --- a/src/main/java/ch/njol/skript/events/EvtItem.java +++ b/src/main/java/ch/njol/skript/events/EvtItem.java @@ -27,7 +27,6 @@ import ch.njol.skript.lang.SkriptEvent; import ch.njol.skript.lang.SkriptParser.ParseResult; import ch.njol.skript.lang.util.SimpleEvent; -import ch.njol.util.coll.CollectionUtils; @SuppressWarnings("deprecation") public class EvtItem extends SkriptEvent { @@ -46,17 +45,7 @@ public class EvtItem extends SkriptEvent { .examples("on item spawn of iron sword:", "\tbroadcast \"Someone dropped an iron sword!\"") .since("unknown (before 2.1)"); - Skript.registerEvent("Drop", EvtItem.class, CollectionUtils.array(PlayerDropItemEvent.class, EntityDropItemEvent.class), - "[player|1:entity] drop[ping] [[of] %-itemtypes%]") - .description("Called when a player drops an item from their inventory, or an entity drops an item, such as a chicken laying an egg.") - .examples("on drop:", - "\tif event-item is compass:", - "\t\tcancel event", - "", - "on entity drop of an egg:", - "\tif event-entity is a chicken:", - "\t\tset item of event-dropped item to a diamond") - .since("unknown (before 2.1), 2.7 (entity)"); + Skript.registerEvent("Prepare Craft", EvtItem.class, PrepareItemCraftEvent.class, "[player] (preparing|beginning) craft[ing] [[of] %-itemtypes%]") .description("Called just before displaying crafting result to player. Note that setting the result item might or might not work due to Bukkit bugs.") .examples("on preparing craft of torch:") @@ -67,12 +56,6 @@ public class EvtItem extends SkriptEvent { .description("Called when a player crafts an item.") .examples("on craft:") .since("unknown (before 2.1)"); - Skript.registerEvent("Pick Up", EvtItem.class, CollectionUtils.array(PlayerPickupItemEvent.class, EntityPickupItemEvent.class), - "[(player|1¦entity)] (pick[ ]up|picking up) [[of] %-itemtypes%]") - .description("Called when a player/entity picks up an item. Please note that the item is still on the ground when this event is called.") - .examples("on pick up:", "on entity pickup of wheat:") - .since("unknown (before 2.1), 2.5 (entity)") - .keywords("pickup"); Skript.registerEvent("Consume", EvtItem.class, PlayerItemConsumeEvent.class, "[player] ((eat|drink)[ing]|consum(e|ing)) [[of] %-itemtypes%]") .description("Called when a player is done eating/drinking something, e.g. an apple, bread, meat, milk or a potion.") .examples("on consume:") @@ -151,10 +134,6 @@ public boolean check(final Event event) { itemStack = blockDispenseEvent.getItem(); } else if (event instanceof ItemSpawnEvent itemSpawnEvent) { itemStack = itemSpawnEvent.getEntity().getItemStack(); - } else if (event instanceof PlayerDropItemEvent playerDropItemEvent) { - itemStack = playerDropItemEvent.getItemDrop().getItemStack(); - } else if (event instanceof EntityDropItemEvent entityDropItemEvent) { - itemStack = entityDropItemEvent.getItemDrop().getItemStack(); } else if (event instanceof CraftItemEvent craftItemEvent) { Recipe recipe = craftItemEvent.getRecipe(); if (recipe instanceof ComplexRecipe) { @@ -172,10 +151,6 @@ public boolean check(final Event event) { } else if (HAS_PLAYER_STONECUTTER_RECIPE_SELECT_EVENT && event instanceof PlayerStonecutterRecipeSelectEvent stonecutterRecipeSelectEvent) { itemStack = stonecutterRecipeSelectEvent.getStonecuttingRecipe().getResult(); - } else if (event instanceof EntityPickupItemEvent entityPickupItemEvent) { - itemStack = entityPickupItemEvent.getItem().getItemStack(); - } else if (event instanceof PlayerPickupItemEvent playerPickupItemEvent) { - itemStack = playerPickupItemEvent.getItem().getItemStack(); } else if (event instanceof PlayerItemConsumeEvent playerItemConsumeEvent) { itemStack = playerItemConsumeEvent.getItem(); } else if (event instanceof InventoryClickEvent inventoryClickEvent) { @@ -197,7 +172,7 @@ public boolean check(final Event event) { @Override public String toString(@Nullable Event event, boolean debug) { - return "dispense/spawn/drop/craft/pickup/consume/break/despawn/merge/move/stonecutting" + (types == null ? "" : " of " + types); + return "dispense/spawn/craft/consume/break/despawn/merge/move/stonecutting" + (types == null ? "" : " of " + types); } } diff --git a/src/main/java/ch/njol/skript/events/SimpleEvents.java b/src/main/java/ch/njol/skript/events/SimpleEvents.java index 2728efbb933..87ce0d0ce5b 100644 --- a/src/main/java/ch/njol/skript/events/SimpleEvents.java +++ b/src/main/java/ch/njol/skript/events/SimpleEvents.java @@ -1,19 +1,13 @@ package ch.njol.skript.events; import ch.njol.skript.Skript; -import ch.njol.skript.lang.SkriptEvent.ListeningBehavior; import ch.njol.skript.lang.util.SimpleEvent; import com.destroystokyo.paper.event.block.AnvilDamagedEvent; -import com.destroystokyo.paper.event.entity.EntityJumpEvent; -import com.destroystokyo.paper.event.entity.ProjectileCollideEvent; import com.destroystokyo.paper.event.player.PlayerElytraBoostEvent; import com.destroystokyo.paper.event.player.PlayerJumpEvent; import com.destroystokyo.paper.event.player.PlayerReadyArrowEvent; import com.destroystokyo.paper.event.server.PaperServerListPingEvent; import io.papermc.paper.event.player.*; -import io.papermc.paper.event.world.border.WorldBorderBoundsChangeEvent; -import io.papermc.paper.event.world.border.WorldBorderBoundsChangeFinishEvent; -import io.papermc.paper.event.world.border.WorldBorderCenterChangeEvent; import org.bukkit.event.Event; import org.bukkit.event.block.*; import org.bukkit.event.enchantment.EnchantItemEvent; @@ -23,7 +17,6 @@ import org.bukkit.event.player.*; import org.bukkit.event.server.BroadcastMessageEvent; import org.bukkit.event.server.ServerListPingEvent; -import org.bukkit.event.vehicle.*; import org.bukkit.event.weather.LightningStrikeEvent; import org.bukkit.event.world.*; @@ -100,11 +93,6 @@ public class SimpleEvents { .examples("on chunk unload:") .since("1.0"); // Skript.registerEvent(SimpleEvent.class, EntityInteractEvent.class, "interact");// = entity interacts with block, e.g. endermen?; player -> PlayerInteractEvent // likely tripwires, pressure plates, etc. - Skript.registerEvent("Explosion Prime", SimpleEvent.class, ExplosionPrimeEvent.class, "explosion prime") - .description("Called when an explosive is primed, i.e. an entity will explode shortly. Creepers can abort the explosion if the player gets too far away, " + - "while TNT will explode for sure after a short time.") - .examples("on explosion prime:") - .since("1.0"); Skript.registerEvent("Hunger Meter Change", SimpleEvent.class, FoodLevelChangeEvent.class, "(food|hunger) (level|met(er|re)|bar) chang(e|ing)") .description("Called when the hunger bar of a player changes, i.e. either increases by eating or decreases over time.") .examples("on food bar change:") @@ -199,24 +187,6 @@ public class SimpleEvents { .examples("on portal create:") .requiredPlugins("Minecraft 1.14+ (event-entity support)") .since("1.0, 2.5.3 (event-entity support)"); - Skript.registerEvent("Projectile Hit", SimpleEvent.class, ProjectileHitEvent.class, "projectile hit") - .description("Called when a projectile hits an entity or a block.") - .examples("on projectile hit:", - "\tif victim's health <= 3:", - "\t\tdelete event-projectile") - .since("1.0"); - if (Skript.classExists("com.destroystokyo.paper.event.entity.ProjectileCollideEvent")) - Skript.registerEvent("Projectile Collide", SimpleEvent.class, ProjectileCollideEvent.class, "projectile collide") - .description("Called when a projectile collides with an entity.") - .examples("on projectile collide:", - "\tteleport shooter of event-projectile to event-entity") - .since("2.5"); - Skript.registerEvent("Shoot", SimpleEvent.class, ProjectileLaunchEvent.class, "[projectile] (shoot|launch)") - .description("Called whenever a projectile is shot. Use the shooter expression to get who shot the projectile.") - .examples("on shoot:", - "\tif projectile is an arrow:", - "\t\tsend \"you shot an arrow!\" to shooter") - .since("1.0"); Skript.registerEvent("Sign Change", SimpleEvent.class, SignChangeEvent.class, "sign (chang[e]|edit)[ing]", "[player] (chang[e]|edit)[ing] [a] sign") .description("As signs are placed empty, this event is called when a player is done editing a sign.") .examples("on sign change:", @@ -228,41 +198,12 @@ public class SimpleEvents { .examples("on spawn change:", "\tbroadcast \"someone changed the spawn!\"") .since("1.0"); - Skript.registerEvent("Vehicle Create", SimpleEvent.class, VehicleCreateEvent.class, "vehicle create", "creat(e|ing|ion of) [a] vehicle") - .description("Called when a new vehicle is created, e.g. when a player places a boat or minecart.") - .examples("on vehicle create:") - .since("1.0"); - Skript.registerEvent("Vehicle Damage", SimpleEvent.class, VehicleDamageEvent.class, "vehicle damage", "damag(e|ing) [a] vehicle") - .description("Called when a vehicle gets damage. Too much damage will destroy the vehicle.") - .examples("on vehicle damage:") - .since("1.0"); - Skript.registerEvent("Vehicle Destroy", SimpleEvent.class, VehicleDestroyEvent.class, "vehicle destroy", "destr(oy[ing]|uction of) [a] vehicle") - .description("Called when a vehicle is destroyed. Any passenger will be ejected and the vehicle might drop some item(s).") - .examples("on vehicle destroy:", - "\tcancel event") - .since("1.0"); - Skript.registerEvent("Vehicle Enter", SimpleEvent.class, VehicleEnterEvent.class, "vehicle enter", "enter[ing] [a] vehicle") - .description("Called when an entity enters a vehicle, either deliberately (players) or by falling into them (mobs).") - .examples("on vehicle enter:", - "\tentity is a player", - "\tcancel event") - .since("1.0"); - Skript.registerEvent("Vehicle Exit", SimpleEvent.class, VehicleExitEvent.class, "vehicle exit", "exit[ing] [a] vehicle") - .description("Called when an entity exits a vehicle.") - .examples("on vehicle exit:", - "\tif event-entity is a spider:", - "\t\tkill event-entity") - .since("1.0"); Skript.registerEvent("Gliding State Change", SimpleEvent.class, EntityToggleGlideEvent.class, "(gliding state change|toggl(e|ing) gliding)") .description("Called when an entity toggles glider on or off, or when server toggles gliding state of an entity forcibly.") .examples("on toggling gliding:", " cancel the event # bad idea, but you CAN do it!") .since("2.2-dev21"); - Skript.registerEvent("AoE Cloud Effect", SimpleEvent.class, AreaEffectCloudApplyEvent.class, "(area|AoE) [cloud] effect") - .description("Called when area effect cloud applies its potion effect. This happens every 5 ticks by default.") - .examples("on area cloud effect:") - .since("2.2-dev21"); Skript.registerEvent("Inventory Open", SimpleEvent.class, InventoryOpenEvent.class, "inventory open[ed]") .description("Called when an inventory is opened for player.") .examples("on inventory open:", @@ -529,17 +470,6 @@ public class SimpleEvents { ) .since("2.10"); - Skript.registerEvent("Vehicle Move", SimpleEvent.class, VehicleMoveEvent.class, "vehicle move") - .description( - "Called when a vehicle moves.", - "Please note that using this event can cause lag if there are multiple vehicle entities, i.e. Horse, Pig, Boat, Minecart") - .examples( - "on vehicle move:", - "\tbroadcast past event-location", - "\tbroadcast event-location" - ) - .since("2.10"); - if (Skript.classExists("com.destroystokyo.paper.event.player.PlayerElytraBoostEvent")) { Skript.registerEvent("Elytra Boost", SimpleEvent.class, PlayerElytraBoostEvent.class, "elytra boost") .description("Called when a player uses a firework to boost their fly speed when flying with an elytra.") diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/EntityModule.java b/src/main/java/org/skriptlang/skript/bukkit/entity/EntityModule.java index 7bb8fa66120..c6ad1205d0d 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/EntityModule.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/EntityModule.java @@ -58,14 +58,18 @@ protected void loadSelf(SkriptAddon addon) { EvtEntityBlockChange::register, EvtEntityDamage::register, EvtEntityDeath::register, + EvtEntityDropItem::register, EvtEntityHeal::register, EvtEntityLeash::register, EvtEntityMove::register, + EvtEntityPickupItem::register, EvtEntityShootBow::register, EvtEntityTeleport::register, EvtEntityTransform::register, EvtExperienceSpawn::register, - EvtFireworkExplode::register + EvtFireworkExplode::register, + EvtProjectileCollide::register, + EvtVehicleCollision::register ); register(addon, diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/EntityEvents.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/EntityEvents.java index ee8ea421882..f9c311a9d09 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/EntityEvents.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/EntityEvents.java @@ -4,6 +4,7 @@ import ch.njol.skript.entity.EntityData; import ch.njol.skript.lang.SkriptEvent; import ch.njol.skript.lang.util.SimpleEvent; +import ch.njol.skript.util.Direction; import ch.njol.skript.util.slot.EquipmentSlot; import ch.njol.skript.util.slot.Slot; import com.destroystokyo.paper.event.entity.EndermanAttackPlayerEvent; @@ -11,17 +12,24 @@ import com.destroystokyo.paper.event.entity.EntityPathfindEvent; import org.bukkit.Location; import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; import org.bukkit.command.CommandSender; -import org.bukkit.entity.Entity; -import org.bukkit.entity.Player; -import org.bukkit.entity.Villager; +import org.bukkit.entity.*; import org.bukkit.event.entity.*; +import org.bukkit.event.vehicle.*; import org.bukkit.inventory.EntityEquipment; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.potion.PotionType; import org.skriptlang.skript.bukkit.lang.eventvalue.EventValue; +import org.skriptlang.skript.bukkit.lang.eventvalue.EventValue.Time; import org.skriptlang.skript.bukkit.lang.eventvalue.EventValueRegistry; import org.skriptlang.skript.bukkit.registration.BukkitSyntaxInfos; import org.skriptlang.skript.registration.SyntaxRegistry; +import java.util.List; + import static org.skriptlang.skript.bukkit.lang.eventvalue.EventValue.Time.PAST; public class EntityEvents { @@ -210,6 +218,31 @@ Called when an entity (usually a primed TNT or creeper) explodes. .supplier(() -> new SimpleEvent("entity toggling swim")) .build()); + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Pathfind") + .addDescription("Called whenever an entity tries to pathfind to a location or another entity.") + .addExample(""" + on pathfind: + broadcast "%event-entity% is about to move to %event-location%!" + """) + .addSince("2.16") + .addPattern("[entity] [start[s]] pathfind[ing]") + .addEvent(EntityPathfindEvent.class) + .build()); + + eventValueRegistry.register(EventValue.builder(EntityPathfindEvent.class, Location.class) + .getter(EntityPathfindEvent::getLoc) + .patterns("target location") + .build()); + + eventValueRegistry.register(EventValue.builder(EntityPathfindEvent.class, Entity.class) + .getter(EntityPathfindEvent::getTargetEntity) + .patterns("target entity") + .build()); + + eventValueRegistry.register(EventValue.builder(EntityPathfindEvent.class, Location.class) + .getter(event -> event.getEntity().getLocation()) + .build()); + // // Entity specific events (e.g. CreeperPowerEvent) // @@ -230,6 +263,22 @@ Called when an entity (usually a primed TNT or creeper) explodes. .supplier(() -> new SimpleEvent("creeper power")) .build()); + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Creeper Power") + .addEvent(ExplosionPrimeEvent.class) + .addPatterns("explosion prim(e|ing)") + .addDescription(""" + Called when an explosive is primed, i.e. an entity will explode shortly. + Creepers can abort the explosion if the player gets too far away,\s + while TNT will explode no matter what after a short period of time. + """) + .addExample(""" + on explosion prime: + broadcast "The explosion is primed!" + """) + .addSince("1.0, INSERT VERSION (updated pattern)") + .supplier(() -> new SimpleEvent("explosion prime")) + .build()); + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Sheep Regrow Wool") .addEvent(SheepRegrowWoolEvent.class) .addPatterns("sheep [re]grow[ing] wool") @@ -375,29 +424,234 @@ Called when an entity (usually a primed TNT or creeper) explodes. .getter(EndermanAttackPlayerEvent::getPlayer) .build()); - syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Pathfind") - .addDescription("Called whenever an entity tries to pathfind to a location or another entity.") + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Area Cloud Effect") + .addEvent(AreaEffectCloudApplyEvent.class) + .addPatterns("(area|AoE) [cloud] effect") + .addDescription(""" + Called when area effect cloud applies its potion effect. + This happens every 5 ticks by default. + """) .addExample(""" - on pathfind: - broadcast "%event-entity% is about to move to %event-location%!" + on area cloud effect: + broadcast "Try to avoid the effect cloud!" """) - .addSince("2.16") - .addPattern("[entity] [start[s]] pathfind[ing]") - .addEvent(EntityPathfindEvent.class) + .addSince("2.2-dev21") + .supplier(() -> new SimpleEvent("area cloud effect")) .build()); - eventValueRegistry.register(EventValue.builder(EntityPathfindEvent.class, Location.class) - .getter(EntityPathfindEvent::getLoc) - .patterns("target location") + eventValueRegistry.register(EventValue.builder(AreaEffectCloudApplyEvent.class, LivingEntity[].class) + .getter(event -> event.getAffectedEntities().toArray(new LivingEntity[0])) .build()); - eventValueRegistry.register(EventValue.builder(EntityPathfindEvent.class, Entity.class) - .getter(EntityPathfindEvent::getTargetEntity) - .patterns("target entity") + eventValueRegistry.register(EventValue.builder(AreaEffectCloudApplyEvent.class, PotionEffectType[].class) + .getter(event -> { + PotionType base = event.getEntity().getBasePotionType(); + if (base != null) + return base.getPotionEffects().stream() + .map(PotionEffect::getType) + .toArray(PotionEffectType[]::new); + return null; + }) .build()); - eventValueRegistry.register(EventValue.builder(EntityPathfindEvent.class, Location.class) - .getter(event -> event.getEntity().getLocation()) + // Vehicle Event Values + + eventValueRegistry.register(EventValue.builder(VehicleEvent.class, Vehicle.class) + .getter(VehicleEvent::getVehicle) + .build()); + + eventValueRegistry.register(EventValue.builder(VehicleEvent.class, World.class) + .getter(event -> event.getVehicle().getWorld()) + .build()); + + eventValueRegistry.register(EventValue.builder(VehicleEvent.class, Entity[].class) + .getter(event -> event.getVehicle().getPassengers().toArray(new Entity[0])) + .build()); + + // To avoid breaking changes + eventValueRegistry.register(EventValue.builder(VehicleEvent.class, Entity.class) + .getter(event -> { + List passengers = event.getVehicle().getPassengers(); + if (passengers.isEmpty()) + return null; + return passengers.getFirst(); + }) + .build()); + + // Vehicle Events + + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Vehicle Move") + .addEvent(VehicleMoveEvent.class) + .addPatterns("vehicle mov(e|ing)") + .addDescription(""" + Called when a vehicle moves. + Note that this event may be called extremely often depending on how many vehicles are in the world and cause performance issues. + """) + .addExample(""" + on vehicle move: + send actionbar "A vehicle is moving from %past event location% to %event-location%!" to (all players) + """) + .addSince("2.10, INSERT VERSION (pattern update)") + .supplier(() -> new SimpleEvent("vehicle moving")) + .build()); + + eventValueRegistry.register(EventValue.builder(VehicleMoveEvent.class, Location.class) + .getter(VehicleMoveEvent::getTo) + .build()); + + eventValueRegistry.register(EventValue.builder(VehicleMoveEvent.class, Location.class) + .getter(VehicleMoveEvent::getFrom) + .time(Time.PAST) + .build()); + + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Vehicle Exit") + .addEvent(VehicleExitEvent.class) + .addPatterns("vehicle exit", "exit[ing] [a] vehicle") + .addDescription("Called when an entity exits a vehicle.") + .addExample(""" + on vehicle exit: + event-entity is a spider + kill event-entity + """) + .addSince("1.0") + .supplier(() -> new SimpleEvent("vehicle exit")) + .build()); + + eventValueRegistry.register(EventValue.builder(VehicleExitEvent.class, LivingEntity.class) + .getter(VehicleExitEvent::getExited) + .build()); + + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Vehicle Enter") + .addEvent(VehicleEnterEvent.class) + .addPatterns("vehicle enter", "enter[ing] [a] vehicle") + .addDescription(""" + Called when an entity enters a vehicle,\s + either deliberately (players) or by falling into them (mobs). + """) + .addExample(""" + on vehicle enter: + event-entity is a player + cancel event + """) + .addSince("1.0") + .supplier(() -> new SimpleEvent("vehicle enter")) + .build()); + + eventValueRegistry.register(EventValue.builder(VehicleEnterEvent.class, Entity.class) + .getter(VehicleEnterEvent::getEntered) + .build()); + + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Vehicle Destroy") + .addEvent(VehicleDestroyEvent.class) + .addPatterns("vehicle destroy", "destr(oy[ing]|uction of) [a] vehicle") + .addDescription(""" + Called when a vehicle is destroyed. + Note that all passengers will be ejected and the vehicle might drop some item(s). + """) + .addExample(""" + on vehicle destroy: + broadcast "Not our vehicle!" + """) + .addSince("1.0") + .supplier(() -> new SimpleEvent("vehicle destroy")) + .build()); + + eventValueRegistry.register(EventValue.builder(VehicleDestroyEvent.class, Entity.class) + .getter(VehicleDestroyEvent::getAttacker) + .build()); + + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Vehicle Damage") + .addEvent(VehicleDamageEvent.class) + .addPatterns("vehicle damage", "damag(e|ing) [of] [a] vehicle") + .addDescription(""" + Called when a vehicle gets damaged. + Note that too much damage will destroy the vehicle. + """) + .addExample(""" + on vehicle damage: + broadcast "How dare you hurt %event-vehicle%!" + """) + .addSince("1.0") + .supplier(() -> new SimpleEvent("vehicle damage")) + .build()); + + eventValueRegistry.register(EventValue.builder(VehicleDamageEvent.class, Entity.class) + .getter(VehicleDamageEvent::getAttacker) + .build()); + + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Vehicle Create") + .addEvent(VehicleCreateEvent.class) + .addPatterns("vehicle create", "creat(e|ing|ion of) [a] vehicle") + .addDescription(""" + Called when a new vehicle is created,\s + e.g. when a player places a boat or minecart. + """) + .addExample(""" + on vehicle create: + broadcast "+1 %event-vehicle% now in the world.." + """) + .addSince("1.0") + .supplier(() -> new SimpleEvent("vehicle create")) + .build()); + + // Projectile Events + + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Projectile Shoot") + .addEvent(ProjectileLaunchEvent.class) + .addPatterns("[projectile] (shoot|launch[ing])") + .addDescription(""" + Called whenever a projectile is shot. + See shooter expression for how to get who shot the projectile. + """) + .addExample(""" + on projectile shoot: + projectile is an arrow + send "You shot an arrow!" to shooter + """) + .addSince("1.0, INSERT VERSION (ing)") + .supplier(() -> new SimpleEvent("projectile shoot")) + .build()); + + eventValueRegistry.register(EventValue.builder(ProjectileLaunchEvent.class, Entity.class) + .getter(ProjectileLaunchEvent::getEntity) + .excludes(ProjectileLaunchEvent.class) + .excludedErrorMessage("Use 'projectile' and/or 'shooter' in shoot events") + .build()); + + eventValueRegistry.register(EventValue.builder(ProjectileLaunchEvent.class, Projectile.class) + .getter(ProjectileLaunchEvent::getEntity) + .build()); + + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Projectile Hit") + .addEvent(ProjectileHitEvent.class) + .addPatterns("projectile hit[ting]") + .addDescription("Called when a projectile hits an entity or block.") + .addExample(""" + on projectile hit: + victim's health <= 3 + delete event-projectile + """) + .addSince("1.0, INSERT VERSION (pattern update)") + .supplier(() -> new SimpleEvent("projectile hit")) + .build()); + + eventValueRegistry.register(EventValue.builder(ProjectileHitEvent.class, Block.class) + .getter(ProjectileHitEvent::getHitBlock) + .build()); + + eventValueRegistry.register(EventValue.builder(ProjectileHitEvent.class, Entity.class) + .getter(ProjectileHitEvent::getEntity) + .excludes(ProjectileHitEvent.class) + .excludedErrorMessage("Use 'projectile' and/or 'shooter' in projectile hit events") + .build()); + + eventValueRegistry.register(EventValue.builder(ProjectileHitEvent.class, Direction.class) + .getter(event -> { + BlockFace blockFace = event.getHitBlockFace(); + if (blockFace == null) + return null; + return new Direction(blockFace, 1); + }) .build()); } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDropItem.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDropItem.java new file mode 100644 index 00000000000..326d10f4a38 --- /dev/null +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDropItem.java @@ -0,0 +1,134 @@ +package org.skriptlang.skript.bukkit.entity.elements.events; + +import ch.njol.skript.aliases.ItemType; +import ch.njol.skript.entity.EntityData; +import ch.njol.skript.lang.Literal; +import ch.njol.skript.lang.LiteralList; +import ch.njol.skript.lang.SkriptEvent; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.lang.SyntaxStringBuilder; +import ch.njol.util.coll.CollectionUtils; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Item; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.entity.EntityDropItemEvent; +import org.bukkit.event.player.PlayerDropItemEvent; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.Nullable; +import org.skriptlang.skript.bukkit.lang.eventvalue.EventValue; +import org.skriptlang.skript.bukkit.lang.eventvalue.EventValueRegistry; +import org.skriptlang.skript.bukkit.registration.BukkitSyntaxInfos; +import org.skriptlang.skript.registration.SyntaxRegistry; + +public class EvtEntityDropItem extends SkriptEvent { + + public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry eventValueRegistry) { + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(EvtEntityDropItem.class, "Entity Drop Item") + .supplier(EvtEntityDropItem::new) + .addEvents(CollectionUtils.array(PlayerDropItemEvent.class, EntityDropItemEvent.class)) + .addPatterns("[%-entitydatas%] drop[ping] [[of] %-itemtypes%]") + .addKeyword("drop") + .addDescription(""" + Called when an entity (including players) drops an item. + e.g. when a chicken lays an egg. + """) + .addExample(""" + on player dropping of tnt: + send "Don't waste perfectly good explosives!" to player + """) + .addExample(""" + on piglin drop ender pearl: + broadcast "Time to beat the dragon!" + """) + .addExample(""" + on drop: + broadcast "%event-item stack% was just dropped at %location of event-item stack%!" + """) + .addSince("unknown (before 2.1), 2.7 (entity), INSERT VERSION (entity data)") + .build()); + + eventValueRegistry.register(EventValue.builder(PlayerDropItemEvent.class, Player.class) + .getter(PlayerDropItemEvent::getPlayer) + .build()); + + eventValueRegistry.register(EventValue.builder(PlayerDropItemEvent.class, Item.class) + .getter(PlayerDropItemEvent::getItemDrop) + .build()); + + eventValueRegistry.register(EventValue.builder(PlayerDropItemEvent.class, ItemStack.class) + .getter(event -> event.getItemDrop().getItemStack()) + .build()); + + eventValueRegistry.register(EventValue.builder(PlayerDropItemEvent.class, Entity.class) + .getter(PlayerDropItemEvent::getPlayer) + .build()); + + eventValueRegistry.register(EventValue.builder(EntityDropItemEvent.class, Item.class) + .getter(EntityDropItemEvent::getItemDrop) + .build()); + + eventValueRegistry.register(EventValue.builder(EntityDropItemEvent.class, ItemStack.class) + .getter(event -> event.getItemDrop().getItemStack()) + .build()); + } + + private @Nullable Literal> entityData; + private @Nullable Literal itemType; + + @Override + @SuppressWarnings("unchecked") + public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { + if (args[0] != null) { + entityData = (Literal>) args[0]; + if (entityData.getAnd() && entityData instanceof LiteralList> list) + list.invertAnd(); + } + if (args[1] != null) { + itemType = (Literal) args[1]; + if (itemType.getAnd() && itemType instanceof LiteralList list) + list.invertAnd(); + } + return true; + } + + @Override + public boolean check(Event event) { + boolean entityDataMatches = true; + boolean itemTypeMatches = true; + + Entity entity; + Item drop; + + if (event instanceof PlayerDropItemEvent playerEvent) { + entity = playerEvent.getPlayer(); + drop = playerEvent.getItemDrop(); + } else if (event instanceof EntityDropItemEvent entityEvent ){ + entity = entityEvent.getEntity(); + drop = entityEvent.getItemDrop(); + } else { + entity = null; + drop = null; + } + + if (entityData != null) + entityDataMatches = entityData.check(event, data -> data.isInstance(entity)); + if (itemType != null) { + if (drop == null) + return false; + itemTypeMatches = itemType.check(event, item -> item.isOfType(drop.getItemStack())); + } + + return entityDataMatches && itemTypeMatches; + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return new SyntaxStringBuilder(event, debug) + .appendIf(entityData != null, entityData) + .append("dropping") + .appendIf(itemType != null, "of", itemType) + .toString(); + } + +} diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityPickupItem.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityPickupItem.java new file mode 100644 index 00000000000..c5707e860e5 --- /dev/null +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityPickupItem.java @@ -0,0 +1,101 @@ +package org.skriptlang.skript.bukkit.entity.elements.events; + +import ch.njol.skript.aliases.ItemType; +import ch.njol.skript.entity.EntityData; +import ch.njol.skript.lang.Literal; +import ch.njol.skript.lang.LiteralList; +import ch.njol.skript.lang.SkriptEvent; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.lang.SyntaxStringBuilder; +import org.bukkit.entity.Item; +import org.bukkit.event.Event; +import org.bukkit.event.entity.EntityPickupItemEvent; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.Nullable; +import org.skriptlang.skript.bukkit.lang.eventvalue.EventValue; +import org.skriptlang.skript.bukkit.lang.eventvalue.EventValueRegistry; +import org.skriptlang.skript.bukkit.registration.BukkitSyntaxInfos; +import org.skriptlang.skript.registration.SyntaxRegistry; + +public class EvtEntityPickupItem extends SkriptEvent { + + public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry eventValueRegistry) { + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(EvtEntityPickupItem.class, "Entity Pickup Item") + .supplier(EvtEntityPickupItem::new) + .addEvent(EntityPickupItemEvent.class) + .addPatterns("[%-entitydatas%] (pick[ ]up|picking up) [[of] %-itemtypes%]") + .addKeyword("pickup") + .addDescription(""" + Called when an entity (including players) picks up an item. + Note that the item is still on the ground when this event is called. + """) + .addExample(""" + on player pickup: + broadcast "Great just what I need: More junk.." + """) + .addExample(""" + on entity pickup of iron chestplate: + cancel event + broadcast "%event-entity% tried to equip themself with gear, but failed!" + """) + .addExample(""" + on player pickup of bedrock: + broadcast "%player% just got a forbidden item! Get them!!" + """) + .addSince("unknown (before 2.1), 2.5 (entity), INSERT VERSION (entity data)") + .build()); + + eventValueRegistry.register(EventValue.builder(EntityPickupItemEvent.class, Item.class) + .getter(EntityPickupItemEvent::getItem) + .build()); + + eventValueRegistry.register(EventValue.builder(EntityPickupItemEvent.class, ItemStack.class) + .getter(event -> event.getItem().getItemStack()) + .build()); + } + + private @Nullable Literal> entityData; + private @Nullable Literal itemType; + + @Override + @SuppressWarnings("unchecked") + public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { + if (args[0] != null) { + entityData = (Literal>) args[0]; + if (entityData.getAnd() && entityData instanceof LiteralList> list) + list.invertAnd(); + } + if (args[1] != null) { + itemType = (Literal) args[1]; + if (itemType.getAnd() && itemType instanceof LiteralList list) + list.invertAnd(); + } + return true; + } + + @Override + public boolean check(Event event) { + EntityPickupItemEvent entityEvent = (EntityPickupItemEvent) event; + + boolean entityDataMatches = true; + boolean itemTypeMatches = true; + + if (entityData != null) + entityDataMatches = entityData.check(event, data -> data.isInstance(entityEvent.getEntity())); + + if (itemType != null) + itemTypeMatches = itemType.check(event, item -> item.isOfType(entityEvent.getItem().getItemStack())); + + return entityDataMatches && itemTypeMatches; + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return new SyntaxStringBuilder(event, debug) + .appendIf(entityData != null, entityData) + .append("picking up") + .appendIf(itemType != null, "of", itemType) + .toString(); + } + +} diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTarget.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTarget.java index 1e17b1787e5..11ecf22eee2 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTarget.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTarget.java @@ -1,6 +1,5 @@ package org.skriptlang.skript.bukkit.entity.elements.events; - import ch.njol.skript.lang.Literal; import ch.njol.skript.lang.SkriptEvent; import ch.njol.skript.lang.SkriptParser.ParseResult; diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtProjectileCollide.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtProjectileCollide.java new file mode 100644 index 00000000000..80e08058634 --- /dev/null +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtProjectileCollide.java @@ -0,0 +1,62 @@ +package org.skriptlang.skript.bukkit.entity.elements.events; + +import ch.njol.skript.lang.Literal; +import ch.njol.skript.lang.SkriptEvent; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import com.destroystokyo.paper.event.entity.ProjectileCollideEvent; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Projectile; +import org.bukkit.event.Event; +import org.jetbrains.annotations.Nullable; +import org.skriptlang.skript.bukkit.lang.eventvalue.EventValue; +import org.skriptlang.skript.bukkit.lang.eventvalue.EventValueRegistry; +import org.skriptlang.skript.bukkit.registration.BukkitSyntaxInfos; +import org.skriptlang.skript.registration.SyntaxRegistry; + +import static org.skriptlang.skript.lang.script.ScriptWarning.printDeprecationWarning; + +@Deprecated(since = "INSERT VERSION", forRemoval = true) +public class EvtProjectileCollide extends SkriptEvent { + + public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry eventValueRegistry) { + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(EvtProjectileCollide.class, "Projectile Collide") + .supplier(EvtProjectileCollide::new) + .addEvent(ProjectileCollideEvent.class) + .addPatterns("projectile collid(e|ing)") + .addDescription(""" + Called when a projectile collides with an entity. + You should generally prefer projectile hit event and check if victim is set over this. + """) + .addExample(""" + on projectile collide: + teleport shooter of event-projectile to event-entity + """) + .addSince("2.5, INSERT VERSION (ing)") + .build()); + + eventValueRegistry.register(EventValue.builder(ProjectileCollideEvent.class, Projectile.class) + .getter(ProjectileCollideEvent::getEntity) + .build()); + + eventValueRegistry.register(EventValue.builder(ProjectileCollideEvent.class, Entity.class) + .getter(ProjectileCollideEvent::getCollidedWith) + .build()); + } + + @Override + public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { + printDeprecationWarning("This event is deprecated and scheduled for removal. Please use the projectile hit event instead."); + return true; + } + + @Override + public boolean check(Event event) { + return true; + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return "projectile collide"; + } + +} diff --git a/src/main/java/ch/njol/skript/events/EvtVehicleCollision.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtVehicleCollision.java similarity index 60% rename from src/main/java/ch/njol/skript/events/EvtVehicleCollision.java rename to src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtVehicleCollision.java index 7b709d6e9fc..f90628835be 100644 --- a/src/main/java/ch/njol/skript/events/EvtVehicleCollision.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtVehicleCollision.java @@ -1,13 +1,12 @@ -package ch.njol.skript.events; +package org.skriptlang.skript.bukkit.entity.elements.events; -import ch.njol.skript.Skript; import ch.njol.skript.aliases.ItemType; import ch.njol.skript.entity.EntityData; import ch.njol.skript.lang.Literal; import ch.njol.skript.lang.SkriptEvent; import ch.njol.skript.lang.SkriptParser.ParseResult; import ch.njol.skript.lang.SyntaxStringBuilder; -import ch.njol.skript.registrations.EventValues; +import ch.njol.util.coll.CollectionUtils; import org.bukkit.block.Block; import org.bukkit.block.data.BlockData; import org.bukkit.entity.Entity; @@ -16,26 +15,48 @@ import org.bukkit.event.vehicle.VehicleCollisionEvent; import org.bukkit.event.vehicle.VehicleEntityCollisionEvent; import org.jetbrains.annotations.Nullable; +import org.skriptlang.skript.bukkit.lang.eventvalue.EventValue; +import org.skriptlang.skript.bukkit.lang.eventvalue.EventValueRegistry; +import org.skriptlang.skript.bukkit.registration.BukkitSyntaxInfos; +import org.skriptlang.skript.registration.SyntaxRegistry; import java.util.ArrayList; import java.util.List; public class EvtVehicleCollision extends SkriptEvent { - static { - Skript.registerEvent("Vehicle Collision", EvtVehicleCollision.class, new Class[]{VehicleBlockCollisionEvent.class, VehicleEntityCollisionEvent.class}, + public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry eventValueRegistry) { + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(EvtVehicleCollision.class, "Vehicle Collision") + .supplier(EvtVehicleCollision::new) + .addEvents(CollectionUtils.array(VehicleBlockCollisionEvent.class, VehicleEntityCollisionEvent.class)) + .addPatterns( "vehicle collision [(with|of) [a[n]] %-itemtypes/blockdatas/entitydatas%]", "vehicle block collision [(with|of) [a[n]] %-itemtypes/blockdatas%]", - "vehicle entity collision [(with|of) [a[n]] %-entitydatas%]") - .description("Called when a vehicle collides with a block or entity.") - .examples("on vehicle collision:", "on vehicle collision with obsidian:", "on vehicle collision with a zombie:") - .since("2.10"); + "vehicle entity collision [(with|of) [a[n]] %-entitydatas%]" + ) + .addDescription("Called when a vehicle collides with a block or entity.") + .addExample(""" + on vehicle collision: + broadcast "COLLISION!" + """) + .addExample(""" + on vehicle collision with obsidian: + broadcast "Looks like something hard was hit.." + """) + .addExample(""" + on vehicle collision with a zombie: + broadcast "How dare you hit the undead!" + """) + .addSince("2.10") + .build()); - // VehicleBlockCollisionEvent - EventValues.registerEventValue(VehicleBlockCollisionEvent.class, Block.class, VehicleBlockCollisionEvent::getBlock); + eventValueRegistry.register(EventValue.builder(VehicleBlockCollisionEvent.class, Block.class) + .getter(VehicleBlockCollisionEvent::getBlock) + .build()); - // VehicleEntityCollisionEvent - EventValues.registerEventValue(VehicleEntityCollisionEvent.class, Entity.class, VehicleEntityCollisionEvent::getEntity); + eventValueRegistry.register(EventValue.builder(VehicleEntityCollisionEvent.class, Entity.class) + .getter(VehicleEntityCollisionEvent::getEntity) + .build()); } private Literal expr; @@ -66,18 +87,14 @@ public boolean init(Literal[] args, int matchedPattern, ParseResult parseResu @Override public boolean check(Event event) { - if (!(event instanceof VehicleCollisionEvent collisionEvent)) - return false; - if (expr == null) { if (blockCollision && !(event instanceof VehicleBlockCollisionEvent)) { return false; - } else if (entityCollision && !(event instanceof VehicleEntityCollisionEvent)) { - return false; - } - return true; + } else return !entityCollision || event instanceof VehicleEntityCollisionEvent; } + VehicleCollisionEvent collisionEvent = (VehicleCollisionEvent) event; + if (collisionEvent instanceof VehicleBlockCollisionEvent blockCollisionEvent && (!itemTypes.isEmpty() || !blockDatas.isEmpty())) { Block eventBlock = blockCollisionEvent.getBlock(); ItemType eventItemType = new ItemType(eventBlock.getType()); @@ -102,17 +119,13 @@ public boolean check(Event event) { @Override public String toString(@Nullable Event event, boolean debug) { - SyntaxStringBuilder builder = new SyntaxStringBuilder(event, debug); - builder.append("vehicle"); - if (blockCollision) { - builder.append("block"); - } else if (entityCollision) { - builder.append("entity"); - } - builder.append("collision"); - if (expr != null) - builder.append("of", expr); - return builder.toString(); + return new SyntaxStringBuilder(event, debug) + .append("vehicle") + .appendIf(blockCollision, "block") + .appendIf(entityCollision, "entity") + .append("collision") + .appendIf(expr != null, "of", expr) + .toString(); } } From b40988629b5182c0bbd5fd8e9538462ca9dd5d4b Mon Sep 17 00:00:00 2001 From: OwlBe Date: Thu, 16 Jul 2026 17:56:36 -0400 Subject: [PATCH 28/35] should resolve tests failing --- src/test/skript/tests/misc/EventValues.sk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/skript/tests/misc/EventValues.sk b/src/test/skript/tests/misc/EventValues.sk index 3a6157b7af7..7e78be11920 100644 --- a/src/test/skript/tests/misc/EventValues.sk +++ b/src/test/skript/tests/misc/EventValues.sk @@ -683,7 +683,7 @@ parse: results: {EventValues::on area effect} code: on area effect: - set {_values::*} to event-living entities and event-potion effect type + set {_values::*} to event-living entities and event-potion effect types parse: results: {EventValues::on sheep grow wool} From d36429ae05ab1e229d6832b3362d678884d43091 Mon Sep 17 00:00:00 2001 From: OwlBe Date: Thu, 16 Jul 2026 18:06:19 -0400 Subject: [PATCH 29/35] space invaders --- .../bukkit/entity/elements/EntityEvents.java | 24 +++++++++---------- .../elements/events/EvtEntityBreakDoor.java | 2 +- .../elements/events/EvtEntityPickupItem.java | 8 +++---- .../elements/events/EvtProjectileCollide.java | 2 +- .../elements/events/EvtVehicleCollision.java | 6 ++--- 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/EntityEvents.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/EntityEvents.java index f9c311a9d09..36a4934e079 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/EntityEvents.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/EntityEvents.java @@ -273,7 +273,7 @@ Called when an entity (usually a primed TNT or creeper) explodes. """) .addExample(""" on explosion prime: - broadcast "The explosion is primed!" + broadcast "The explosion is primed!" """) .addSince("1.0, INSERT VERSION (updated pattern)") .supplier(() -> new SimpleEvent("explosion prime")) @@ -433,7 +433,7 @@ Called when an entity (usually a primed TNT or creeper) explodes. """) .addExample(""" on area cloud effect: - broadcast "Try to avoid the effect cloud!" + broadcast "Try to avoid the effect cloud!" """) .addSince("2.2-dev21") .supplier(() -> new SimpleEvent("area cloud effect")) @@ -489,7 +489,7 @@ Called when an entity (usually a primed TNT or creeper) explodes. """) .addExample(""" on vehicle move: - send actionbar "A vehicle is moving from %past event location% to %event-location%!" to (all players) + send actionbar "A vehicle is moving from %past event location% to %event-location%!" to (all players) """) .addSince("2.10, INSERT VERSION (pattern update)") .supplier(() -> new SimpleEvent("vehicle moving")) @@ -510,8 +510,8 @@ Called when an entity (usually a primed TNT or creeper) explodes. .addDescription("Called when an entity exits a vehicle.") .addExample(""" on vehicle exit: - event-entity is a spider - kill event-entity + event-entity is a spider + kill event-entity """) .addSince("1.0") .supplier(() -> new SimpleEvent("vehicle exit")) @@ -530,8 +530,8 @@ either deliberately (players) or by falling into them (mobs). """) .addExample(""" on vehicle enter: - event-entity is a player - cancel event + event-entity is a player + cancel event """) .addSince("1.0") .supplier(() -> new SimpleEvent("vehicle enter")) @@ -550,7 +550,7 @@ either deliberately (players) or by falling into them (mobs). """) .addExample(""" on vehicle destroy: - broadcast "Not our vehicle!" + broadcast "Not our vehicle!" """) .addSince("1.0") .supplier(() -> new SimpleEvent("vehicle destroy")) @@ -569,7 +569,7 @@ either deliberately (players) or by falling into them (mobs). """) .addExample(""" on vehicle damage: - broadcast "How dare you hurt %event-vehicle%!" + broadcast "How dare you hurt %event-vehicle%!" """) .addSince("1.0") .supplier(() -> new SimpleEvent("vehicle damage")) @@ -588,7 +588,7 @@ either deliberately (players) or by falling into them (mobs). """) .addExample(""" on vehicle create: - broadcast "+1 %event-vehicle% now in the world.." + broadcast "+1 %event-vehicle% now in the world.." """) .addSince("1.0") .supplier(() -> new SimpleEvent("vehicle create")) @@ -605,8 +605,8 @@ either deliberately (players) or by falling into them (mobs). """) .addExample(""" on projectile shoot: - projectile is an arrow - send "You shot an arrow!" to shooter + projectile is an arrow + send "You shot an arrow!" to shooter """) .addSince("1.0, INSERT VERSION (ing)") .supplier(() -> new SimpleEvent("projectile shoot")) diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java index 75ca22a218e..c8a8eee9922 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java @@ -30,7 +30,7 @@ Called when an entity (usually a zombie, husk, zombie pigman or zombie villager) """) .addExample(""" on husk breaking a door: - broadcast "Rest in peace villagers.." + broadcast "Rest in peace villagers.." """) .addSince("1.0, INSERT VERSION (entity types)") .build()); diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityPickupItem.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityPickupItem.java index c5707e860e5..eba7fe135e3 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityPickupItem.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityPickupItem.java @@ -31,16 +31,16 @@ Called when an entity (including players) picks up an item. """) .addExample(""" on player pickup: - broadcast "Great just what I need: More junk.." + broadcast "Great just what I need: More junk.." """) .addExample(""" on entity pickup of iron chestplate: - cancel event - broadcast "%event-entity% tried to equip themself with gear, but failed!" + cancel event + broadcast "%event-entity% tried to equip themself with gear, but failed!" """) .addExample(""" on player pickup of bedrock: - broadcast "%player% just got a forbidden item! Get them!!" + broadcast "%player% just got a forbidden item! Get them!!" """) .addSince("unknown (before 2.1), 2.5 (entity), INSERT VERSION (entity data)") .build()); diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtProjectileCollide.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtProjectileCollide.java index 80e08058634..bddbcb3e76c 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtProjectileCollide.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtProjectileCollide.java @@ -29,7 +29,7 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev """) .addExample(""" on projectile collide: - teleport shooter of event-projectile to event-entity + teleport shooter of event-projectile to event-entity """) .addSince("2.5, INSERT VERSION (ing)") .build()); diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtVehicleCollision.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtVehicleCollision.java index f90628835be..7c682f29e3d 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtVehicleCollision.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtVehicleCollision.java @@ -37,15 +37,15 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev .addDescription("Called when a vehicle collides with a block or entity.") .addExample(""" on vehicle collision: - broadcast "COLLISION!" + broadcast "COLLISION!" """) .addExample(""" on vehicle collision with obsidian: - broadcast "Looks like something hard was hit.." + broadcast "Looks like something hard was hit.." """) .addExample(""" on vehicle collision with a zombie: - broadcast "How dare you hit the undead!" + broadcast "How dare you hit the undead!" """) .addSince("2.10") .build()); From 28fcf39a9cfcb8406e95201fac2a81198f7f704a Mon Sep 17 00:00:00 2001 From: OwlBe Date: Thu, 16 Jul 2026 18:21:18 -0400 Subject: [PATCH 30/35] small thing noticed --- .../skript/bukkit/entity/elements/EntityEvents.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/EntityEvents.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/EntityEvents.java index 36a4934e079..b4c7d807589 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/EntityEvents.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/EntityEvents.java @@ -446,11 +446,11 @@ Called when an entity (usually a primed TNT or creeper) explodes. eventValueRegistry.register(EventValue.builder(AreaEffectCloudApplyEvent.class, PotionEffectType[].class) .getter(event -> { PotionType base = event.getEntity().getBasePotionType(); - if (base != null) - return base.getPotionEffects().stream() - .map(PotionEffect::getType) - .toArray(PotionEffectType[]::new); - return null; + if (base == null) + return null; + return base.getPotionEffects().stream() + .map(PotionEffect::getType) + .toArray(PotionEffectType[]::new); }) .build()); From e4fd03396327aaf6a7f6fbb304692e01fb9d5f98 Mon Sep 17 00:00:00 2001 From: OwlBe Date: Sun, 19 Jul 2026 12:16:57 -0400 Subject: [PATCH 31/35] fixes tests failing --- .../entity/elements/events/EvtProjectileCollide.java | 2 +- src/test/skript/tests/misc/EventValues.sk | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtProjectileCollide.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtProjectileCollide.java index bddbcb3e76c..cce6487cfa9 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtProjectileCollide.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtProjectileCollide.java @@ -31,7 +31,7 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev on projectile collide: teleport shooter of event-projectile to event-entity """) - .addSince("2.5, INSERT VERSION (ing)") + .addSince("2.5, INSERT VERSION (pattern update)") .build()); eventValueRegistry.register(EventValue.builder(ProjectileCollideEvent.class, Projectile.class) diff --git a/src/test/skript/tests/misc/EventValues.sk b/src/test/skript/tests/misc/EventValues.sk index 7e78be11920..1fc657704c3 100644 --- a/src/test/skript/tests/misc/EventValues.sk +++ b/src/test/skript/tests/misc/EventValues.sk @@ -608,10 +608,10 @@ parse: 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 + results: {EventValues::on projectile collide} + code: + on projectile collide: + set {_values::*} to event-projectile and event-entity parse: results: {EventValues::on shoot} @@ -961,6 +961,7 @@ test "Event Values": loop {EventValues::*}: set {_string} to {_string} + newline + " %loop-index%: %loop-value%" clear {EventValues::*} + {_string} does not contain "on projectile collide: [Deprecated] This event is deprecated and scheduled for removal. Please use the projectile hit event instead." assert true is false with {_string} else: clear {EventValues::*} From 2f303c5f791570a05121fb3ec2a067fc4da466f3 Mon Sep 17 00:00:00 2001 From: OwlBe Date: Mon, 20 Jul 2026 23:49:50 -0400 Subject: [PATCH 32/35] space --- .../skript/bukkit/entity/elements/events/EvtEntityDropItem.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDropItem.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDropItem.java index 326d10f4a38..7a7839eb8ca 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDropItem.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDropItem.java @@ -103,7 +103,7 @@ public boolean check(Event event) { if (event instanceof PlayerDropItemEvent playerEvent) { entity = playerEvent.getPlayer(); drop = playerEvent.getItemDrop(); - } else if (event instanceof EntityDropItemEvent entityEvent ){ + } else if (event instanceof EntityDropItemEvent entityEvent) { entity = entityEvent.getEntity(); drop = entityEvent.getItemDrop(); } else { From 59aff7c77633de0b09c1307e848ff3ac1a06cde6 Mon Sep 17 00:00:00 2001 From: OwlBe Date: Mon, 27 Jul 2026 00:10:22 -0400 Subject: [PATCH 33/35] Attempt at fixing gradlew.bat --- gradlew.bat | 164 ++++++++++++++++++++++++++-------------------------- 1 file changed, 82 insertions(+), 82 deletions(-) diff --git a/gradlew.bat b/gradlew.bat index a51ec4f5886..8508ef684d4 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,82 +1,82 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem -@rem SPDX-License-Identifier: Apache-2.0 -@rem - -@if "%DEBUG%"=="" @echo off -@rem ########################################################################## -@rem -@rem gradlew startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables, and ensure extensions are enabled -setlocal EnableExtensions - -set DIRNAME=%~dp0 -if "%DIRNAME%"=="" set DIRNAME=. -@rem This is normally unused -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if %ERRORLEVEL% equ 0 goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -"%COMSPEC%" /c exit 1 - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -"%COMSPEC%" /c exit 1 - -:execute -@rem Setup the command line - - - -@rem Execute gradlew -@rem endlocal doesn't take effect until after the line is parsed and variables are expanded -@rem which allows us to clear the local environment before executing the java command -endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel - -:exitWithErrorLevel -@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts -"%COMSPEC%" /c exit %ERRORLEVEL% +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem gradlew startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables, and ensure extensions are enabled +setlocal EnableExtensions + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +"%COMSPEC%" /c exit 1 + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +"%COMSPEC%" /c exit 1 + +:execute +@rem Setup the command line + + + +@rem Execute gradlew +@rem endlocal doesn't take effect until after the line is parsed and variables are expanded +@rem which allows us to clear the local environment before executing the java command +endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel + +:exitWithErrorLevel +@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts +"%COMSPEC%" /c exit %ERRORLEVEL% From 2d1ebf14fd4df54632695f30ca4929e5adfff5b4 Mon Sep 17 00:00:00 2001 From: OwlBe Date: Mon, 27 Jul 2026 21:03:40 -0400 Subject: [PATCH 34/35] Adds FoodLevelChangeEvent and splits all the `addSince`'s --- .../ch/njol/skript/events/SimpleEvents.java | 4 --- .../bukkit/entity/elements/EntityEvents.java | 28 ++++++++++++++++--- .../elements/events/EvtEntityBlockChange.java | 4 ++- .../elements/events/EvtEntityBreakDoor.java | 3 +- .../elements/events/EvtEntityDamage.java | 3 +- .../elements/events/EvtEntityDropItem.java | 4 ++- .../entity/elements/events/EvtEntityHeal.java | 3 +- .../entity/elements/events/EvtEntityMove.java | 3 +- .../elements/events/EvtEntityPickupItem.java | 4 ++- .../elements/events/EvtEntityPortal.java | 4 ++- .../elements/events/EvtEntitySpawn.java | 3 +- .../elements/events/EvtEntityTeleport.java | 3 +- .../elements/events/EvtProjectileCollide.java | 3 +- 13 files changed, 50 insertions(+), 19 deletions(-) diff --git a/src/main/java/ch/njol/skript/events/SimpleEvents.java b/src/main/java/ch/njol/skript/events/SimpleEvents.java index 87ce0d0ce5b..360d503b0fe 100644 --- a/src/main/java/ch/njol/skript/events/SimpleEvents.java +++ b/src/main/java/ch/njol/skript/events/SimpleEvents.java @@ -93,10 +93,6 @@ public class SimpleEvents { .examples("on chunk unload:") .since("1.0"); // Skript.registerEvent(SimpleEvent.class, EntityInteractEvent.class, "interact");// = entity interacts with block, e.g. endermen?; player -> PlayerInteractEvent // likely tripwires, pressure plates, etc. - Skript.registerEvent("Hunger Meter Change", SimpleEvent.class, FoodLevelChangeEvent.class, "(food|hunger) (level|met(er|re)|bar) chang(e|ing)") - .description("Called when the hunger bar of a player changes, i.e. either increases by eating or decreases over time.") - .examples("on food bar change:") - .since("1.4.4"); Skript.registerEvent("Leaves Decay", SimpleEvent.class, LeavesDecayEvent.class, "leaves decay[ing]") .description("Called when a leaf block decays due to not being connected to a tree.") .examples("on leaves decay:") diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/EntityEvents.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/EntityEvents.java index b4c7d807589..f3c8d774256 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/EntityEvents.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/EntityEvents.java @@ -243,6 +243,22 @@ Called when an entity (usually a primed TNT or creeper) explodes. .getter(event -> event.getEntity().getLocation()) .build()); + // This technically is only called for players but in the future it may support other human entities + syntaxRegistry.register(BukkitSyntaxInfos.Event.KEY, BukkitSyntaxInfos.Event.builder(SimpleEvent.class, "Hunger Meter Change") + .addEvent(FoodLevelChangeEvent.class) + .addPatterns("(food|hunger) (level|met(er|re)|bar) chang(e|ing)") + .addDescription(""" + Called when the hunger bar of a player changes,\s + i.e. either increases by eating or decreases over time. + """) + .addExample(""" + on food bar change: + send "Getting hungry eh?" to event-entity + """) + .addSince("1.4.4") + .supplier(() -> new SimpleEvent("hunger meter change")) + .build()); + // // Entity specific events (e.g. CreeperPowerEvent) // @@ -275,7 +291,8 @@ Called when an entity (usually a primed TNT or creeper) explodes. on explosion prime: broadcast "The explosion is primed!" """) - .addSince("1.0, INSERT VERSION (updated pattern)") + .addSince("1.0") + .addSince("INSERT VERSION (updated pattern)") .supplier(() -> new SimpleEvent("explosion prime")) .build()); @@ -491,7 +508,8 @@ Called when an entity (usually a primed TNT or creeper) explodes. on vehicle move: send actionbar "A vehicle is moving from %past event location% to %event-location%!" to (all players) """) - .addSince("2.10, INSERT VERSION (pattern update)") + .addSince("2.10") + .addSince("INSERT VERSION (pattern update)") .supplier(() -> new SimpleEvent("vehicle moving")) .build()); @@ -608,7 +626,8 @@ either deliberately (players) or by falling into them (mobs). projectile is an arrow send "You shot an arrow!" to shooter """) - .addSince("1.0, INSERT VERSION (ing)") + .addSince("1.0") + .addSince("INSERT VERSION (pattern update)") .supplier(() -> new SimpleEvent("projectile shoot")) .build()); @@ -631,7 +650,8 @@ either deliberately (players) or by falling into them (mobs). victim's health <= 3 delete event-projectile """) - .addSince("1.0, INSERT VERSION (pattern update)") + .addSince("1.0") + .addSince("INSERT VERSION (pattern update)") .supplier(() -> new SimpleEvent("projectile hit")) .build()); diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBlockChange.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBlockChange.java index 47619600bbc..0499bf9eab4 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBlockChange.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBlockChange.java @@ -46,7 +46,9 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev event-entity is a falling dirt cancel event """) - .addSince("unknown, 2.5.2 (falling block), 2.8.0 (any entity support)") + .addSince("unknown") + .addSince("2.5.2 (falling block)") + .addSince("2.8.0 (any entity support)") .build()); eventValueRegistry.register(EventValue.builder(EntityChangeBlockEvent.class, Block.class) diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java index c8a8eee9922..4520bfff6ea 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBreakDoor.java @@ -32,7 +32,8 @@ Called when an entity (usually a zombie, husk, zombie pigman or zombie villager) on husk breaking a door: broadcast "Rest in peace villagers.." """) - .addSince("1.0, INSERT VERSION (entity types)") + .addSince("1.0") + .addSince("INSERT VERSION (entity types)") .build()); } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java index c848a679d18..cb50592b03f 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDamage.java @@ -37,7 +37,8 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev if attacker is a player: send "You monster.." to attacker """) - .addSince("1.0, 2.7 (by entity)") + .addSince("1.0") + .addSince("2.7 (by entity)") .build()); eventValueRegistry.register(EventValue.builder(EntityDamageEvent.class, DamageCause.class) diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDropItem.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDropItem.java index 7a7839eb8ca..8d484c636f1 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDropItem.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityDropItem.java @@ -45,7 +45,9 @@ Called when an entity (including players) drops an item. on drop: broadcast "%event-item stack% was just dropped at %location of event-item stack%!" """) - .addSince("unknown (before 2.1), 2.7 (entity), INSERT VERSION (entity data)") + .addSince("unknown (before 2.1)") + .addSince("2.7 (entity)") + .addSince("INSERT VERSION (entity data)") .build()); eventValueRegistry.register(EventValue.builder(PlayerDropItemEvent.class, Player.class) diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityHeal.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityHeal.java index c6c31e3b7ce..88f840b5f75 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityHeal.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityHeal.java @@ -40,7 +40,8 @@ or by the effect of a potion of healing (overworld mobs) or harm (nether mobs). on player healing from a regeneration potion: send "all better!" to event-entity """) - .addSince("1.0, 2.9.0 (by reason)") + .addSince("1.0") + .addSince("2.9.0 (by reason)") .build()); eventValueRegistry.register(EventValue.builder(EntityRegainHealthEvent.class, RegainReason.class) diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityMove.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityMove.java index 126855113f3..5741571313c 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityMove.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityMove.java @@ -52,7 +52,8 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev if event-world is "no_skeleton_movement": cancel event """) - .addSince("2.6, 2.8.0 (turn around)") + .addSince("2.6") + .addSince("2.8.0 (turn around)") .build()); eventValueRegistry.register(EventValue.builder(EntityMoveEvent.class, Location.class) diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityPickupItem.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityPickupItem.java index eba7fe135e3..68306fcb318 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityPickupItem.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityPickupItem.java @@ -42,7 +42,9 @@ Called when an entity (including players) picks up an item. on player pickup of bedrock: broadcast "%player% just got a forbidden item! Get them!!" """) - .addSince("unknown (before 2.1), 2.5 (entity), INSERT VERSION (entity data)") + .addSince("unknown (before 2.1)") + .addSince("2.5 (entity)") + .addSince("INSERT VERSION (entity data)") .build()); eventValueRegistry.register(EventValue.builder(EntityPickupItemEvent.class, Item.class) diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityPortal.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityPortal.java index 2145988acc3..6e7f2e1a498 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityPortal.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityPortal.java @@ -33,7 +33,9 @@ public static void register(SyntaxRegistry syntaxRegistry) { set world of event-location to player's world add 9000 to x-pos of event-location """) - .addSince("1.0, 2.5.3 (entities), 2.13 (location changers)") + .addSince("1.0") + .addSince("2.5.3 (entities)") + .addSince("2.13 (location changers)") .build()); } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntitySpawn.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntitySpawn.java index 73528c17877..d6f858a5899 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntitySpawn.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntitySpawn.java @@ -34,7 +34,8 @@ public static void register(SyntaxRegistry syntaxRegistry) { loop all players in radius 120 of event-entity: send "A great beast has been seen near you.." to loop-value """) - .addSince("1.0, 2.5.1 (non-living entities)") + .addSince("1.0") + .addSince("2.5.1 (non-living entities)") .build()); } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTeleport.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTeleport.java index b353a14c4f7..18b7960d89b 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTeleport.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTeleport.java @@ -42,7 +42,8 @@ or by other means (e.g. plugins). on wolf teleport: send "Your wolf just teleported!" to owner of event-entity """) - .addSince("1.0, 2.9.0 (entity teleport)") + .addSince("1.0") + .addSince("2.9.0 (entity teleport)") .build()); eventValueRegistry.register(EventValue.builder(PlayerTeleportEvent.class, Location.class) diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtProjectileCollide.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtProjectileCollide.java index cce6487cfa9..3cc0905fbe8 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtProjectileCollide.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtProjectileCollide.java @@ -31,7 +31,8 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev on projectile collide: teleport shooter of event-projectile to event-entity """) - .addSince("2.5, INSERT VERSION (pattern update)") + .addSince("2.5") + .addSince("INSERT VERSION (pattern update)") .build()); eventValueRegistry.register(EventValue.builder(ProjectileCollideEvent.class, Projectile.class) From 6606f8c60fc4668b581e9c43ecdf4b1297542884 Mon Sep 17 00:00:00 2001 From: OwlBe Date: Tue, 28 Jul 2026 17:15:13 -0400 Subject: [PATCH 35/35] noticed some things --- .../bukkit/entity/elements/EntityEvents.java | 14 +++++++------- .../elements/events/EvtEntityBlockChange.java | 2 +- .../entity/elements/events/EvtEntityHeal.java | 4 +--- .../entity/elements/events/EvtEntityMove.java | 2 +- .../entity/elements/events/EvtEntityTransform.java | 6 +++--- .../elements/events/EvtProjectileCollide.java | 2 +- 6 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/EntityEvents.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/EntityEvents.java index f3c8d774256..24e50ad8b04 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/EntityEvents.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/EntityEvents.java @@ -63,7 +63,7 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev eventValueRegistry.register(EventValue.builder(EntityEvent.class, EntityData.class) .getter(event -> EntityData.fromEntity(event.getEntity())) .excludes(EntityDamageEvent.class, EntityDeathEvent.class) - .excludedErrorMessage("Use 'type of attacker/victim' in damage/death events.") + .excludedErrorMessage("Use 'type of attacker/victim' in damage/death events") .build()); // @@ -292,7 +292,7 @@ Called when an entity (usually a primed TNT or creeper) explodes. broadcast "The explosion is primed!" """) .addSince("1.0") - .addSince("INSERT VERSION (updated pattern)") + .addSince("INSERT VERSION ('priming' in pattern)") .supplier(() -> new SimpleEvent("explosion prime")) .build()); @@ -509,7 +509,7 @@ Called when an entity (usually a primed TNT or creeper) explodes. send actionbar "A vehicle is moving from %past event location% to %event-location%!" to (all players) """) .addSince("2.10") - .addSince("INSERT VERSION (pattern update)") + .addSince("INSERT VERSION ('moving' in pattern)") .supplier(() -> new SimpleEvent("vehicle moving")) .build()); @@ -543,7 +543,7 @@ Called when an entity (usually a primed TNT or creeper) explodes. .addEvent(VehicleEnterEvent.class) .addPatterns("vehicle enter", "enter[ing] [a] vehicle") .addDescription(""" - Called when an entity enters a vehicle,\s + Called when an entity enters a vehicle, \ either deliberately (players) or by falling into them (mobs). """) .addExample(""" @@ -601,7 +601,7 @@ either deliberately (players) or by falling into them (mobs). .addEvent(VehicleCreateEvent.class) .addPatterns("vehicle create", "creat(e|ing|ion of) [a] vehicle") .addDescription(""" - Called when a new vehicle is created,\s + Called when a new vehicle is created, \ e.g. when a player places a boat or minecart. """) .addExample(""" @@ -627,7 +627,7 @@ either deliberately (players) or by falling into them (mobs). send "You shot an arrow!" to shooter """) .addSince("1.0") - .addSince("INSERT VERSION (pattern update)") + .addSince("INSERT VERSION ('ing' in pattern)") .supplier(() -> new SimpleEvent("projectile shoot")) .build()); @@ -651,7 +651,7 @@ either deliberately (players) or by falling into them (mobs). delete event-projectile """) .addSince("1.0") - .addSince("INSERT VERSION (pattern update)") + .addSince("INSERT VERSION ('hitting' in pattern)") .supplier(() -> new SimpleEvent("projectile hit")) .build()); diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBlockChange.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBlockChange.java index 0499bf9eab4..ba28d3fe4ae 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBlockChange.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityBlockChange.java @@ -32,7 +32,7 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev .addEvent(EntityChangeBlockEvent.class) .addPatterns(ChangeEvent.patterns) .addDescription(""" - Called when an enderman places or picks up a block, a sheep eats grass,\s + Called when an enderman places or picks up a block, a sheep eats grass, \ a silverfish boops into/out of a block or a falling block lands and turns into a block respectively. event-block represents the old block and event-blockdata represents the new replacement that will be applied to the block. """) diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityHeal.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityHeal.java index 88f840b5f75..0deec6d9424 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityHeal.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityHeal.java @@ -26,9 +26,7 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev "[%-entitydatas%] heal[ing] [(from|due to|by) %-healreasons%]" ) .addDescription(""" - Called when an entity is healed,\s - e.g. by eating (players),\s - being fed (pets),\s + Called when an entity is healed, e.g. by eating (players), being fed (pets), \ or by the effect of a potion of healing (overworld mobs) or harm (nether mobs). """) .addExample(""" diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityMove.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityMove.java index 5741571313c..1c50a14a7de 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityMove.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityMove.java @@ -40,7 +40,7 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev if {frozen::%player's uuid%} is set: cancel event send actionbar "You are frozen!" to player - // Generally not recommended over setting movement & jump attributes but useful for older servers + # Generally not recommended over setting movement & jump attributes but useful for older servers """) .addExample(""" on player turning around: diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTransform.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTransform.java index 2351dfff0c8..087c1fb759c 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTransform.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtEntityTransform.java @@ -25,9 +25,9 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev .addPatterns("[%*-entitydatas%] transform[ing] [due to %-transformreasons%]") .addDescription(""" Called when an entity is about to be replaced by another entity. - e.g. when a zombie gets cured and a villager spawns,\s - an entity drowns in water like a zombie that turns to a drown,\s - an entity that gets frozen in powder snow,\s + e.g. when a zombie gets cured and a villager spawns, \ + an entity drowns in water like a zombie that turns to a drown, \ + an entity that gets frozen in powder snow, \ a mooshroom that when sheared, spawns a new cow. """) .addExample(""" diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtProjectileCollide.java b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtProjectileCollide.java index 3cc0905fbe8..8c1a9397d60 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtProjectileCollide.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/elements/events/EvtProjectileCollide.java @@ -32,7 +32,7 @@ public static void register(SyntaxRegistry syntaxRegistry, EventValueRegistry ev teleport shooter of event-projectile to event-entity """) .addSince("2.5") - .addSince("INSERT VERSION (pattern update)") + .addSince("INSERT VERSION ('colliding' in pattern)") .build()); eventValueRegistry.register(EventValue.builder(ProjectileCollideEvent.class, Projectile.class)