From 6a645a69b4a5cce8c2a454e96e5a116ba7d0a45b Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Mon, 2 Feb 2026 08:33:27 -0800 Subject: [PATCH 01/29] Block - remove holder of Type as this may cause issues when a block changes and you're storing this in a variable --- .../skriptdev/skript/api/hytale/Block.java | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/github/skriptdev/skript/api/hytale/Block.java b/src/main/java/com/github/skriptdev/skript/api/hytale/Block.java index aee689bd..986102dd 100644 --- a/src/main/java/com/github/skriptdev/skript/api/hytale/Block.java +++ b/src/main/java/com/github/skriptdev/skript/api/hytale/Block.java @@ -14,11 +14,9 @@ import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore; import org.jetbrains.annotations.NotNull; -import java.util.Objects; - /** * Represents a block in a world. - * Hytale doesn't appear to have a representation of a block in a world. + * Hytale doesn't appear to have a representation of a block in the world. * This class provides a wrapper around Hytale's block system, allowing for easy interaction with blocks in a world. * This may be changed/removed in the future. */ @@ -26,19 +24,16 @@ public class Block { private final @NotNull World world; - private @NotNull BlockType type; private final @NotNull Vector3i pos; public Block(@NotNull World world, @NotNull Vector3i pos) { this.world = world; this.pos = pos; - this.type = Objects.requireNonNull(world.getBlockType(pos)); } public Block(@NotNull World world, @NotNull Vector3i pos, @NotNull BlockType type) { this.world = world; this.pos = pos; - this.type = type; } public Block(@NotNull Location location) { @@ -52,11 +47,11 @@ public Block(@NotNull Location location) { } public @NotNull BlockType getType() { - return this.type; + BlockType blockType = this.world.getBlockType(this.pos); + return blockType != null ? blockType : BlockType.EMPTY; } public void setType(@NotNull BlockType type, int settings) { - this.type = type; this.world.setBlock(this.pos.getX(), this.pos.getY(), this.pos.getZ(), type.getId(), settings); } @@ -152,15 +147,15 @@ public void breakBlock(int settings) { public String toTypeString() { return String.format("[%s] block at (%s,%s,%s) in '%s'", - this.type.getId(), this.pos.getX(), this.pos.getY(), this.pos.getZ(), this.world.getName()); + this.getType().getId(), this.pos.getX(), this.pos.getY(), this.pos.getZ(), this.world.getName()); } @Override public String toString() { return "Block{" + - "world=" + world.getName() + - ", type=" + type + - ", pos=" + pos + + "world=" + this.world.getName() + + ", type=" + this.getType() + + ", pos=" + this.pos + '}'; } From b338614ae8a694573150029cb8709244a53fa648 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Mon, 2 Feb 2026 10:07:17 -0800 Subject: [PATCH 02/29] ExprLocationOf - fix rotation being NaN --- .../plugin/elements/expressions/other/ExprLocationOf.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/other/ExprLocationOf.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/other/ExprLocationOf.java index c522b044..e9970d9f 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/other/ExprLocationOf.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/other/ExprLocationOf.java @@ -29,7 +29,7 @@ public static void register(SkriptRegistration registration) { World world = entity.getWorld(); assert world != null; TransformComponent transform = entity.getTransformComponent(); - return new Location(world.getName(), transform.getPosition()); + return new Location(world.getName(), transform.getPosition(), transform.getRotation()); } else if (owner instanceof Block block) { return block.getLocation(); } From 5a742fad3036a72327da67bc3e65ae922859a86c Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Mon, 2 Feb 2026 10:11:59 -0800 Subject: [PATCH 03/29] SecSpawnNPC: - a lil bit of cleanup --- .../plugin/elements/sections/SecSpawnNPC.java | 36 +++++++++---------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/sections/SecSpawnNPC.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/sections/SecSpawnNPC.java index 99949f9b..4e1a8ef4 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/sections/SecSpawnNPC.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/sections/SecSpawnNPC.java @@ -1,16 +1,14 @@ package com.github.skriptdev.skript.plugin.elements.sections; import com.github.skriptdev.skript.api.skript.registration.NPCRegistry; -import com.hypixel.hytale.component.Holder; import com.hypixel.hytale.component.Store; -import com.hypixel.hytale.function.consumer.TriConsumer; import com.hypixel.hytale.math.vector.Location; +import com.hypixel.hytale.math.vector.Vector3f; import com.hypixel.hytale.server.core.entity.Entity; import com.hypixel.hytale.server.core.universe.Universe; import com.hypixel.hytale.server.core.universe.world.World; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import com.hypixel.hytale.server.npc.NPCPlugin; -import com.hypixel.hytale.server.npc.entities.NPCEntity; import io.github.syst3ms.skriptparser.lang.CodeSection; import io.github.syst3ms.skriptparser.lang.Expression; import io.github.syst3ms.skriptparser.lang.Statement; @@ -104,22 +102,22 @@ public Optional walk(@NotNull TriggerContext ctx) { Optional firstStatement = getFirst(); - NPCPlugin.get().spawnEntity(store, roleSingle.get().index(), location.getPosition(), location.getRotation(), null, new TriConsumer, Store>() { - @Override - public void accept(NPCEntity npcEntity, Holder entityStoreRef, Store entityStoreStore) { - SpawnMobContext spawnMobContext = new SpawnMobContext(npcEntity); - - // Copy the variables from the main TriggerContext into the SpawnMobContext - Variables.copyLocalVariables(ctx, spawnMobContext); - setNext(null); - firstStatement.ifPresent(statement -> - Statement.runAll(statement, spawnMobContext)); - - // After that is run, copy them back - Variables.copyLocalVariables(spawnMobContext, ctx); - // Clear locals from the no longer used SpawnMobContext - Variables.clearLocalVariables(spawnMobContext); - } + Vector3f rotation = location.getRotation().clone(); + if (Float.isNaN(rotation.getX())) rotation = Vector3f.ZERO; + + NPCPlugin.get().spawnEntity(store, roleSingle.get().index(), location.getPosition().clone(), rotation, null, (npcEntity, _, _) -> { + SpawnMobContext spawnMobContext = new SpawnMobContext(npcEntity); + + // Copy the variables from the main TriggerContext into the SpawnMobContext + Variables.copyLocalVariables(ctx, spawnMobContext); + setNext(null); + firstStatement.ifPresent(statement -> + Statement.runAll(statement, spawnMobContext)); + + // After that is run, copy them back + Variables.copyLocalVariables(spawnMobContext, ctx); + // Clear locals from the no longer used SpawnMobContext + Variables.clearLocalVariables(spawnMobContext); }, null); return nextStatement; From 65d74130c44ec30c79dcc96b658b3d353269b9d9 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Mon, 2 Feb 2026 10:38:21 -0800 Subject: [PATCH 04/29] Exprfluid - fix fluid level not clamping properly --- .../skriptdev/skript/api/hytale/Block.java | 21 +++++++++++++------ .../expressions/block/ExprBlockFluid.java | 4 ++-- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/github/skriptdev/skript/api/hytale/Block.java b/src/main/java/com/github/skriptdev/skript/api/hytale/Block.java index 986102dd..19f4a165 100644 --- a/src/main/java/com/github/skriptdev/skript/api/hytale/Block.java +++ b/src/main/java/com/github/skriptdev/skript/api/hytale/Block.java @@ -1,5 +1,6 @@ package com.github.skriptdev.skript.api.hytale; +import com.github.skriptdev.skript.api.utils.Utils; import com.hypixel.hytale.component.Ref; import com.hypixel.hytale.component.Store; import com.hypixel.hytale.math.util.ChunkUtil; @@ -13,6 +14,7 @@ import com.hypixel.hytale.server.core.universe.world.chunk.section.FluidSection; import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * Represents a block in a world. @@ -86,10 +88,10 @@ public void setFluidLevel(byte level) { return null; } - Fluid fluid = fluidSection.getFluid(this.pos.getX(), this.pos.getY(), this.pos.getZ()); if (fluid == null) return null; - fluidSection.setFluid(this.pos.getX(), this.pos.getY(), this.pos.getZ(), fluid, level); + byte fluidLevel = (byte)Math.clamp((int)level, 0, fluid.getMaxFluidLevel()); + fluidSection.setFluid(this.pos.getX(), this.pos.getY(), this.pos.getZ(), fluid, fluidLevel); } return chunk; }); @@ -103,7 +105,7 @@ public Fluid getFluid() { return Fluid.getAssetMap().getAsset(fluidId); } - public void setFluid(@NotNull Fluid fluid) { + public void setFluid(@NotNull Fluid fluid, @Nullable Integer level) { long index = ChunkUtil.indexChunkFromBlock(this.pos.getX(), this.pos.getZ()); this.world.getChunkAsync(index).thenApply((chunk) -> { Ref columnRef = chunk.getReference(); @@ -121,9 +123,16 @@ public void setFluid(@NotNull Fluid fluid) { } - byte level = fluidSection.getFluidLevel(this.pos.getX(), this.pos.getY(), this.pos.getZ()); - if (level <= 0) level = 8; - fluidSection.setFluid(this.pos.getX(), this.pos.getY(), this.pos.getZ(), fluid, level); + byte fluidLevel; + if (level != null) { + fluidLevel = level.byteValue(); + } else { + fluidLevel = fluidSection.getFluidLevel(this.pos.getX(), this.pos.getY(), this.pos.getZ()); + if (fluidLevel <= 0) fluidLevel = (byte)fluid.getMaxFluidLevel(); + } + fluidLevel = (byte)Math.clamp((int)fluidLevel, 0, fluid.getMaxFluidLevel()); + Utils.log("Set fluid level to %s", fluidLevel); + fluidSection.setFluid(this.pos.getX(), this.pos.getY(), this.pos.getZ(), fluid, fluidLevel); } return chunk; }); diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/block/ExprBlockFluid.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/block/ExprBlockFluid.java index 1181acb5..90e5991c 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/block/ExprBlockFluid.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/block/ExprBlockFluid.java @@ -65,10 +65,10 @@ public void change(@NotNull TriggerContext ctx, @NotNull ChangeMode changeMode, if (!(changeWith[0] instanceof Fluid fluid)) return; for (Object o : this.locations.getArray(ctx)) { if (o instanceof Block block) { - block.setFluid(fluid); + block.setFluid(fluid, null); } else if (o instanceof Location location) { Block block = new Block(location); - block.setFluid(fluid); + block.setFluid(fluid, null); } } } From 71755866ea6687295951bfe332d112e08743b291 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Mon, 2 Feb 2026 11:47:25 -0800 Subject: [PATCH 05/29] Block - remove old constructor --- .../github/skriptdev/skript/api/hytale/Block.java | 15 ++++----------- .../events/player/EvtPlayerBreakBlock.java | 5 +++-- .../events/player/EvtPlayerDamageBlock.java | 2 +- .../elements/events/player/EvtPlayerUseBlock.java | 2 +- .../elements/expressions/block/ExprBlockAt.java | 5 +---- 5 files changed, 10 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/github/skriptdev/skript/api/hytale/Block.java b/src/main/java/com/github/skriptdev/skript/api/hytale/Block.java index 19f4a165..b8f1bb85 100644 --- a/src/main/java/com/github/skriptdev/skript/api/hytale/Block.java +++ b/src/main/java/com/github/skriptdev/skript/api/hytale/Block.java @@ -33,19 +33,12 @@ public Block(@NotNull World world, @NotNull Vector3i pos) { this.pos = pos; } - public Block(@NotNull World world, @NotNull Vector3i pos, @NotNull BlockType type) { - this.world = world; - this.pos = pos; - } - public Block(@NotNull Location location) { World world = Universe.get().getWorld(location.getWorld()); if (world == null) { throw new IllegalArgumentException("World '" + location.getWorld() + "' not found."); } - BlockType blockType = world.getBlockType(location.getPosition().toVector3i()); - assert blockType != null; - this(world, location.getPosition().toVector3i(), blockType); + this(world, location.getPosition().toVector3i()); } public @NotNull BlockType getType() { @@ -90,7 +83,7 @@ public void setFluidLevel(byte level) { Fluid fluid = fluidSection.getFluid(this.pos.getX(), this.pos.getY(), this.pos.getZ()); if (fluid == null) return null; - byte fluidLevel = (byte)Math.clamp((int)level, 0, fluid.getMaxFluidLevel()); + byte fluidLevel = (byte) Math.clamp((int) level, 0, fluid.getMaxFluidLevel()); fluidSection.setFluid(this.pos.getX(), this.pos.getY(), this.pos.getZ(), fluid, fluidLevel); } return chunk; @@ -128,9 +121,9 @@ public void setFluid(@NotNull Fluid fluid, @Nullable Integer level) { fluidLevel = level.byteValue(); } else { fluidLevel = fluidSection.getFluidLevel(this.pos.getX(), this.pos.getY(), this.pos.getZ()); - if (fluidLevel <= 0) fluidLevel = (byte)fluid.getMaxFluidLevel(); + if (fluidLevel <= 0) fluidLevel = (byte) fluid.getMaxFluidLevel(); } - fluidLevel = (byte)Math.clamp((int)fluidLevel, 0, fluid.getMaxFluidLevel()); + fluidLevel = (byte) Math.clamp((int) fluidLevel, 0, fluid.getMaxFluidLevel()); Utils.log("Set fluid level to %s", fluidLevel); fluidSection.setFluid(this.pos.getX(), this.pos.getY(), this.pos.getZ(), fluid, fluidLevel); } diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerBreakBlock.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerBreakBlock.java index 8eacb022..8593c3a6 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerBreakBlock.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerBreakBlock.java @@ -69,7 +69,8 @@ public String toString(@NotNull TriggerContext ctx, boolean debug) { return "player block break"; } - private record BreakBlockEventContext(BreakBlockEvent event, Player player) implements PlayerContext, CancellableContext { + private record BreakBlockEventContext(BreakBlockEvent event, + Player player) implements PlayerContext, CancellableContext { public Player[] getPlayer() { return new Player[]{this.player}; @@ -80,7 +81,7 @@ private Block[] getBlock() { Vector3i targetBlock = event.getTargetBlock(); World world = this.player.getWorld(); if (world == null || blockType == BlockType.EMPTY) return null; - Block block = new Block(world, targetBlock, blockType); + Block block = new Block(world, targetBlock); return new Block[]{block}; } diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerDamageBlock.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerDamageBlock.java index 7fcf288e..aebad12d 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerDamageBlock.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerDamageBlock.java @@ -80,7 +80,7 @@ public Block[] getBlock() { Vector3i targetBlock = this.event.getTargetBlock(); World world = this.player.getWorld(); if (world == null) return null; - return new Block[]{new Block(world, targetBlock, this.event.getBlockType())}; + return new Block[]{new Block(world, targetBlock)}; } public BlockType[] getBlockType() { diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerUseBlock.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerUseBlock.java index 7967bba3..9c5f6b01 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerUseBlock.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerUseBlock.java @@ -103,7 +103,7 @@ public InteractionType[] getInteractionType() { public Block[] getBlock() { World world = this.player.getWorld(); if (world == null) return null; - return new Block[]{new Block(world, this.event.getTargetBlock(), this.event.getBlockType())}; + return new Block[]{new Block(world, this.event.getTargetBlock())}; } } diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/block/ExprBlockAt.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/block/ExprBlockAt.java index 8e60d015..2779fdc1 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/block/ExprBlockAt.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/block/ExprBlockAt.java @@ -4,7 +4,6 @@ import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; import com.hypixel.hytale.math.vector.Location; import com.hypixel.hytale.math.vector.Vector3i; -import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType; import com.hypixel.hytale.server.core.universe.Universe; import com.hypixel.hytale.server.core.universe.world.World; import io.github.syst3ms.skriptparser.lang.Expression; @@ -47,10 +46,8 @@ public Block[] getValues(@NotNull TriggerContext ctx) { if (world == null) continue; Vector3i pos = location.getPosition().toVector3i(); - BlockType blockType = world.getBlockType(pos); - if (blockType == null) continue; - Block block = new Block(world, pos, blockType); + Block block = new Block(world, pos); blocks.add(block); } From 7d4aad103d4fe17b016971edaff156ba9943a89e Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Mon, 2 Feb 2026 11:51:40 -0800 Subject: [PATCH 06/29] Block - set type on correct world thread. --- .../java/com/github/skriptdev/skript/api/hytale/Block.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/github/skriptdev/skript/api/hytale/Block.java b/src/main/java/com/github/skriptdev/skript/api/hytale/Block.java index b8f1bb85..c2ebefd6 100644 --- a/src/main/java/com/github/skriptdev/skript/api/hytale/Block.java +++ b/src/main/java/com/github/skriptdev/skript/api/hytale/Block.java @@ -47,7 +47,12 @@ public Block(@NotNull Location location) { } public void setType(@NotNull BlockType type, int settings) { - this.world.setBlock(this.pos.getX(), this.pos.getY(), this.pos.getZ(), type.getId(), settings); + Runnable r = () -> Block.this.world.setBlock(Block.this.pos.getX(), Block.this.pos.getY(), Block.this.pos.getZ(), type.getId(), settings); + if (this.world.isInThread()) { + r.run(); + } else { + this.world.execute(r); + } } public byte getFluidLevel() { From 7d130ed407aae3b1e3af7a032d0b2c4b8925b5db Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Mon, 2 Feb 2026 12:06:51 -0800 Subject: [PATCH 07/29] CondPlayerIsCrouching - fix pattern --- .../plugin/elements/conditions/CondPlayerIsCrouching.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/conditions/CondPlayerIsCrouching.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/conditions/CondPlayerIsCrouching.java index 62c21c85..8ba2218d 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/conditions/CondPlayerIsCrouching.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/conditions/CondPlayerIsCrouching.java @@ -14,7 +14,7 @@ public class CondPlayerIsCrouching extends ConditionalExpression { public static void register(SkriptRegistration reg) { reg.newExpression(CondPlayerIsCrouching.class, Boolean.class, true, - "%players% (is|are)[neg:( not|n't)] crouching", + "%players% (is|are) crouching", "%players% (isn't|is not|aren't|are not) crouching") .name("Player is Crouching") .description("Checks if the player is crouching.") From 2a60ae57fdac0155291c87d304063ebe5db60525 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Mon, 2 Feb 2026 13:15:39 -0800 Subject: [PATCH 08/29] ExprLocationOf - clone new locations --- .../plugin/elements/expressions/other/ExprLocationOf.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/other/ExprLocationOf.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/other/ExprLocationOf.java index e9970d9f..795672fd 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/other/ExprLocationOf.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/other/ExprLocationOf.java @@ -29,7 +29,7 @@ public static void register(SkriptRegistration registration) { World world = entity.getWorld(); assert world != null; TransformComponent transform = entity.getTransformComponent(); - return new Location(world.getName(), transform.getPosition(), transform.getRotation()); + return new Location(world.getName(), transform.getPosition().clone(), transform.getRotation().clone()); } else if (owner instanceof Block block) { return block.getLocation(); } From a23bdbcc011f9f952de6fca890b56746e515f17d Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Mon, 2 Feb 2026 14:03:59 -0800 Subject: [PATCH 09/29] Block Iterator/Sphere expressions added --- .../expressions/ExpressionHandler.java | 4 + .../expressions/block/ExprBlockIterator.java | 115 ++++++++++++++++++ .../expressions/block/ExprBlockSphere.java | 82 +++++++++++++ 3 files changed, 201 insertions(+) create mode 100644 src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/block/ExprBlockIterator.java create mode 100644 src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/block/ExprBlockSphere.java diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/ExpressionHandler.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/ExpressionHandler.java index c9b891c1..4360f31a 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/ExpressionHandler.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/ExpressionHandler.java @@ -3,6 +3,8 @@ import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; import com.github.skriptdev.skript.plugin.elements.expressions.block.ExprBlockAt; import com.github.skriptdev.skript.plugin.elements.expressions.block.ExprBlockFluid; +import com.github.skriptdev.skript.plugin.elements.expressions.block.ExprBlockIterator; +import com.github.skriptdev.skript.plugin.elements.expressions.block.ExprBlockSphere; import com.github.skriptdev.skript.plugin.elements.expressions.block.ExprBlockTypeAtLocation; import com.github.skriptdev.skript.plugin.elements.expressions.block.ExprBlockTypeOfBlock; import com.github.skriptdev.skript.plugin.elements.expressions.block.ExprBlockFluidLevel; @@ -51,6 +53,8 @@ public static void register(SkriptRegistration registration) { ExprBlockAt.register(registration); ExprBlockFluid.register(registration); ExprBlockFluidLevel.register(registration); + ExprBlockIterator.register(registration); + ExprBlockSphere.register(registration); ExprBlockTypeAtLocation.register(registration); ExprBlockTypeOfBlock.register(registration); ExprTargetBlockOfPlayer.register(registration); diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/block/ExprBlockIterator.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/block/ExprBlockIterator.java new file mode 100644 index 00000000..c2ea6276 --- /dev/null +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/block/ExprBlockIterator.java @@ -0,0 +1,115 @@ +package com.github.skriptdev.skript.plugin.elements.expressions.block; + +import com.github.skriptdev.skript.api.hytale.Block; +import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; +import com.hypixel.hytale.math.iterator.LineIterator; +import com.hypixel.hytale.math.vector.Location; +import com.hypixel.hytale.math.vector.Vector3i; +import com.hypixel.hytale.server.core.universe.Universe; +import com.hypixel.hytale.server.core.universe.world.World; +import io.github.syst3ms.skriptparser.lang.Expression; +import io.github.syst3ms.skriptparser.lang.TriggerContext; +import io.github.syst3ms.skriptparser.parsing.ParseContext; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class ExprBlockIterator implements Expression { + + public static void register(SkriptRegistration reg) { + reg.newExpression(ExprBlockIterator.class, Block.class, false, + "blocks within %location% and %location%", + "blocks between %location% and %location%") + .name("Block Iterator") + .description("Get all blocks within (cuboid) or between (straight line) two locations.") + .examples("loop blocks within {_loc1} and {_loc2}:", + "\tset blocktype of loop-value to rock_stone") + .since("INSERT VERSION") + .register(); + } + + private boolean within; + private Expression loc1, loc2; + + @SuppressWarnings("unchecked") + @Override + public boolean init(Expression[] expressions, int matchedPattern, @NotNull ParseContext parseContext) { + this.within = matchedPattern == 0; + this.loc1 = (Expression) expressions[0]; + this.loc2 = (Expression) expressions[1]; + return true; + } + + @Override + public Block[] getValues(@NotNull TriggerContext ctx) { + List blocks = new ArrayList<>(); + iterator(ctx).forEachRemaining(blocks::add); + return blocks.toArray(Block[]::new); + } + + @SuppressWarnings("RedundantOperationOnEmptyContainer") + @Override + public Iterator iterator(@NotNull TriggerContext ctx) { + List blocks = new ArrayList<>(); + + Location loc1 = this.loc1.getSingle(ctx).orElse(null); + Location loc2 = this.loc2.getSingle(ctx).orElse(null); + if (loc1 == null || loc2 == null) return blocks.iterator(); + + String worldString = loc1.getWorld(); + if (worldString == null) return blocks.iterator(); + + World world = Universe.get().getWorld(worldString); + if (world == null) return blocks.iterator(); + + Vector3i pos1 = loc1.getPosition().toVector3i(); + Vector3i pos2 = loc2.getPosition().toVector3i(); + + if (this.within) { + Vector3i min = Vector3i.min(pos1, pos2); + Vector3i max = Vector3i.max(pos1, pos2); + for (int x = min.getX(); x <= max.getX(); x++) { + for (int y = min.getY(); y <= max.getY(); y++) { + for (int z = min.getZ(); z <= max.getZ(); z++) { + Block block = new Block(world, new Vector3i(x, y, z)); + blocks.add(block); + } + } + } + return blocks.iterator(); + } else { + return new BlockLineIterator(world, pos1, pos2); + } + } + + @Override + public String toString(@NotNull TriggerContext ctx, boolean debug) { + String type = this.within ? " within " : " between "; + return "Blocks" + type + this.loc1.toString(ctx, debug) + " and " + this.loc2.toString(ctx, debug); + } + + private static class BlockLineIterator implements Iterator { + + private final World world; + private final LineIterator lineIterator; + + public BlockLineIterator(World world, Vector3i pos1, Vector3i pos2) { + this.world = world; + this.lineIterator = new LineIterator(pos1.getX(), pos1.getY(), pos1.getZ(), pos2.getX(), pos2.getY(), pos2.getZ()); + } + + @Override + public boolean hasNext() { + return this.lineIterator.hasNext(); + } + + @Override + public Block next() { + Vector3i pos = this.lineIterator.next(); + return new Block(world, pos); + } + } + +} diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/block/ExprBlockSphere.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/block/ExprBlockSphere.java new file mode 100644 index 00000000..3ccd5dba --- /dev/null +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/block/ExprBlockSphere.java @@ -0,0 +1,82 @@ +package com.github.skriptdev.skript.plugin.elements.expressions.block; + +import com.github.skriptdev.skript.api.hytale.Block; +import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; +import com.hypixel.hytale.math.block.BlockSphereUtil; +import com.hypixel.hytale.math.vector.Location; +import com.hypixel.hytale.math.vector.Vector3i; +import com.hypixel.hytale.server.core.universe.Universe; +import com.hypixel.hytale.server.core.universe.world.World; +import io.github.syst3ms.skriptparser.lang.Expression; +import io.github.syst3ms.skriptparser.lang.TriggerContext; +import io.github.syst3ms.skriptparser.parsing.ParseContext; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class ExprBlockSphere implements Expression { + + public static void register(SkriptRegistration reg) { + reg.newExpression(ExprBlockSphere.class, Block.class, false, + "blocks in radius %number% (of|around) %location%") + .name("Block Sphere") + .description("Get all blocks within a sphere of a given radius around a location.") + .examples("set {_blocks::*} to blocks in radius 5 of player's location", + "loop blocks in radius 5 of player's location:", + "\tset blocktype of loop-block to empty") + .since("INSERT VERSION") + .register(); + } + + private Expression radius; + private Expression loc; + + @SuppressWarnings("unchecked") + @Override + public boolean init(Expression @NotNull [] expressions, int matchedPattern, @NotNull ParseContext parseContext) { + this.radius = (Expression) expressions[0]; + this.loc = (Expression) expressions[1]; + return true; + } + + @Override + public Block[] getValues(@NotNull TriggerContext ctx) { + List blocks = new ArrayList<>(); + iterator(ctx).forEachRemaining(blocks::add); + return blocks.toArray(Block[]::new); + } + + @Override + public String toString(@NotNull TriggerContext ctx, boolean debug) { + return "blocks in radius " + this.radius.toString(ctx, debug) + " of " + this.loc.toString(ctx, debug); + } + + @Override + public Iterator iterator(TriggerContext ctx) { + List blocks = new ArrayList<>(); + + Location location = this.loc.getSingle(ctx).orElse(null); + if (location == null) return blocks.iterator(); + Number number = this.radius.getSingle(ctx).orElse(null); + if (number == null) return blocks.iterator(); + int radius = number.intValue(); + + String worldName = location.getWorld(); + if (worldName == null) return blocks.iterator(); + World world = Universe.get().getWorld(worldName); + if (world == null) return blocks.iterator(); + + Vector3i pos = location.getPosition().toVector3i(); + + BlockSphereUtil.forEachBlock(pos.getX(), pos.getY(), pos.getZ(), + radius, blocks, (i, i1, i2, blocks1) -> { + blocks1.add(new Block(world, new Vector3i(i, i1, i2))); + return true; + }); + + return blocks.iterator(); + } + +} From 26d5eb270177be74ea3979ca6c23e101097ad146 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Mon, 2 Feb 2026 14:05:40 -0800 Subject: [PATCH 10/29] EffCancelEvent - remove debug message --- .../skript/plugin/elements/effects/other/EffCancelEvent.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/other/EffCancelEvent.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/other/EffCancelEvent.java index d1fc5410..3227ccf4 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/other/EffCancelEvent.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/other/EffCancelEvent.java @@ -1,7 +1,6 @@ package com.github.skriptdev.skript.plugin.elements.effects.other; import com.github.skriptdev.skript.api.skript.event.CancellableContext; -import com.github.skriptdev.skript.api.utils.Utils; import io.github.syst3ms.skriptparser.lang.Effect; import io.github.syst3ms.skriptparser.lang.Expression; import io.github.syst3ms.skriptparser.lang.TriggerContext; @@ -27,10 +26,6 @@ public static void register(SkriptRegistration registration) { @Override public boolean init(Expression @NotNull [] expressions, int matchedPattern, ParseContext parseContext) { this.cancel = matchedPattern == 0; - Utils.log("Contexts:"); - for (Class currentContext : parseContext.getParserState().getCurrentContexts()) { - Utils.log(" - %s", currentContext.getSimpleName()); - } for (Class currentContext : parseContext.getParserState().getCurrentContexts()) { if (!CancellableContext.class.isAssignableFrom(currentContext)) { parseContext.getLogger().error("This event cannot be cancelled", ErrorType.SEMANTIC_ERROR); From d8de552c620d579727abc5ecd963c3a59f620798 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Mon, 2 Feb 2026 15:12:47 -0800 Subject: [PATCH 11/29] JsonDocPrinter - fix some things --- .../skriptdev/skript/api/skript/docs/JsonDocPrinter.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/github/skriptdev/skript/api/skript/docs/JsonDocPrinter.java b/src/main/java/com/github/skriptdev/skript/api/skript/docs/JsonDocPrinter.java index 7ac41e4c..336dc271 100644 --- a/src/main/java/com/github/skriptdev/skript/api/skript/docs/JsonDocPrinter.java +++ b/src/main/java/com/github/skriptdev/skript/api/skript/docs/JsonDocPrinter.java @@ -164,10 +164,10 @@ private void printStructures(BsonDocument mainDocs, SkriptRegistration registrat Documentation documentation = event.getDocumentation(); if (documentation.isNoDoc()) return; - BsonDocument structureDoc = new BsonDocument(); - if (Structure.class.isAssignableFrom(event.getSyntaxClass())) { + BsonDocument structureDoc = new BsonDocument(); printDocumentation("structure", structureDoc, event); + structuresArray.add(structureDoc); } }); @@ -402,7 +402,7 @@ private void printDocumentation(String type, BsonDocument syntaxDoc, SyntaxInfo< // PATTERNS List patterns = syntaxInfo.getPatterns(); - if (patterns.isEmpty()) { + if (!patterns.isEmpty()) { BsonArray patternArray = new BsonArray(); patterns.forEach(pattern -> patternArray.add(new BsonString(pattern.toString()))); syntaxDoc.put("patterns", patternArray); From 4794b5384c82c0efcfaafeb4be0f1331718027c9 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Mon, 2 Feb 2026 15:26:27 -0800 Subject: [PATCH 12/29] JsonDocPrinter - more changes with experimental --- .../skript/api/skript/docs/JsonDocPrinter.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/github/skriptdev/skript/api/skript/docs/JsonDocPrinter.java b/src/main/java/com/github/skriptdev/skript/api/skript/docs/JsonDocPrinter.java index 336dc271..b0ce2786 100644 --- a/src/main/java/com/github/skriptdev/skript/api/skript/docs/JsonDocPrinter.java +++ b/src/main/java/com/github/skriptdev/skript/api/skript/docs/JsonDocPrinter.java @@ -307,18 +307,23 @@ private void printEffects(BsonDocument mainDocs, SkriptRegistration registration private void printTypes(BsonDocument mainDocs, SkriptRegistration registration) { BsonArray typesArray = mainDocs.getArray("types", new BsonArray()); - String addonName = registration.getRegisterer().getAddonName().toLowerCase(Locale.ROOT).replace(" ", "_"); - registration.getTypes().forEach(type -> { Documentation documentation = type.getDocumentation(); if (documentation.isNoDoc()) return; BsonDocument syntaxDoc = new BsonDocument(); + + // NAME and ID String baseName = type.getBaseName(); String docName = documentation.getName(); syntaxDoc.put("name", new BsonString(docName != null ? docName : baseName)); syntaxDoc.put("id", getId("type", baseName)); + // EXPERIMENTAL + if (documentation.isExperimental()) { + syntaxDoc.put("experimental", new BsonString(documentation.getExperimentalMessage())); + } + // DESCRIPTION BsonArray descriptionArray = new BsonArray(); for (String s : documentation.getDescription()) { @@ -385,7 +390,9 @@ private void printDocumentation(String type, BsonDocument syntaxDoc, SyntaxInfo< syntaxDoc.put("id", getId(type, syntaxInfo)); // EXPERIMENTAL - // TODO + if (documentation.isExperimental()) { + syntaxDoc.put("experimental", new BsonString(documentation.getExperimentalMessage())); + } // DESCRIPTION BsonArray descriptionArray = new BsonArray(); From 9cd70030f12bafeba8d3d759070cec6b407446ef Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Mon, 2 Feb 2026 15:28:14 -0800 Subject: [PATCH 13/29] MarkdownDocPrinter - add experimental message --- .../skriptdev/skript/api/skript/docs/MarkdownDocPrinter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/github/skriptdev/skript/api/skript/docs/MarkdownDocPrinter.java b/src/main/java/com/github/skriptdev/skript/api/skript/docs/MarkdownDocPrinter.java index 09f03068..d57d2670 100644 --- a/src/main/java/com/github/skriptdev/skript/api/skript/docs/MarkdownDocPrinter.java +++ b/src/main/java/com/github/skriptdev/skript/api/skript/docs/MarkdownDocPrinter.java @@ -277,7 +277,7 @@ private static void printDocumentation(String type, PrintWriter writer, Document if (documentation.isExperimental()) { writer.println("> [!WARNING]"); writer.println("> **This is an experimental feature!** "); - writer.println("> Things may not work as expected and may change without notice. "); + writer.println("> " + documentation.getExperimentalMessage()); } String[] description = documentation.getDescription(); if (description.length > 0) { From 155bbdf695ded7c8b996009f200f1de84800131a Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Mon, 2 Feb 2026 15:36:57 -0800 Subject: [PATCH 14/29] JsonDocPrinter - add serializable tag --- .../skriptdev/skript/api/skript/docs/JsonDocPrinter.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/com/github/skriptdev/skript/api/skript/docs/JsonDocPrinter.java b/src/main/java/com/github/skriptdev/skript/api/skript/docs/JsonDocPrinter.java index b0ce2786..88b9fa6a 100644 --- a/src/main/java/com/github/skriptdev/skript/api/skript/docs/JsonDocPrinter.java +++ b/src/main/java/com/github/skriptdev/skript/api/skript/docs/JsonDocPrinter.java @@ -354,6 +354,9 @@ private void printTypes(BsonDocument mainDocs, SkriptRegistration registration) syntaxDoc.put("examples", exampleArray); } + // SERIALIZABLE + syntaxDoc.put("serializable", new BsonBoolean(type.getSerializer().isPresent())); + // SINCE String since = documentation.getSince(); if (since != null) { From c67256cc1dda8ee7a46f3e66f9c96a53b9d10787 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Mon, 2 Feb 2026 15:40:01 -0800 Subject: [PATCH 15/29] build.gradle.kts - forgot to switch the parser to the dev branch --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index a713f22d..6e33f7a1 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -25,7 +25,7 @@ repositories { dependencies { compileOnly("com.hypixel.hytale:Server:${hytaleVersion}") compileOnly("org.jetbrains:annotations:26.0.2") - implementation("com.github.SkriptDev:skript-parser:1.0.2") { + implementation("com.github.SkriptDev:skript-parser:dev~patch-SNAPSHOT") { // TODO change before release isTransitive = false } implementation("com.github.Zoltus:TinyMessage:2.0.1") { From 1eaa216699c52e755bbcf1b82dd6e6fdc1e5efe0 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Mon, 2 Feb 2026 15:50:29 -0800 Subject: [PATCH 16/29] EffSpawnEntity - add spawn entity effect --- .../elements/effects/EffectHandler.java | 2 + .../effects/entity/EffSpawnEntity.java | 70 +++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 src/main/java/com/github/skriptdev/skript/plugin/elements/effects/entity/EffSpawnEntity.java diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/EffectHandler.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/EffectHandler.java index cdd14e68..c7ce5afa 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/EffectHandler.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/EffectHandler.java @@ -4,6 +4,7 @@ import com.github.skriptdev.skript.plugin.elements.effects.block.EffBreakBlock; import com.github.skriptdev.skript.plugin.elements.effects.entity.EffDropItem; import com.github.skriptdev.skript.plugin.elements.effects.entity.EffKill; +import com.github.skriptdev.skript.plugin.elements.effects.entity.EffSpawnEntity; import com.github.skriptdev.skript.plugin.elements.effects.other.EffSendMessage; import com.github.skriptdev.skript.plugin.elements.effects.entity.EffTeleport; import com.github.skriptdev.skript.plugin.elements.effects.player.EffBan; @@ -21,6 +22,7 @@ public static void register(SkriptRegistration registration) { // ENTITY EffDropItem.register(registration); EffKill.register(registration); + EffSpawnEntity.register(registration); EffTeleport.register(registration); // OTHER diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/entity/EffSpawnEntity.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/entity/EffSpawnEntity.java new file mode 100644 index 00000000..3e4ccc20 --- /dev/null +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/entity/EffSpawnEntity.java @@ -0,0 +1,70 @@ +package com.github.skriptdev.skript.plugin.elements.effects.entity; + +import com.github.skriptdev.skript.api.skript.registration.NPCRegistry.NPCRole; +import com.hypixel.hytale.component.Store; +import com.hypixel.hytale.math.vector.Location; +import com.hypixel.hytale.math.vector.Vector3f; +import com.hypixel.hytale.server.core.universe.Universe; +import com.hypixel.hytale.server.core.universe.world.World; +import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; +import com.hypixel.hytale.server.npc.NPCPlugin; +import io.github.syst3ms.skriptparser.lang.Effect; +import io.github.syst3ms.skriptparser.lang.Expression; +import io.github.syst3ms.skriptparser.lang.TriggerContext; +import io.github.syst3ms.skriptparser.parsing.ParseContext; +import io.github.syst3ms.skriptparser.registration.SkriptRegistration; +import org.jetbrains.annotations.NotNull; + +import java.util.Optional; + +public class EffSpawnEntity extends Effect { + + public static void register(SkriptRegistration registration) { + registration.newEffect(EffSpawnEntity.class, "spawn [a|an] %npcrole% at %location%") + .name("Spawn NPC") + .description("Spawn an npc at a location.") + .examples("player command /sheep:", + "\ttrigger:", + "\t\tspawn a sheep at location of player") + .since("INSERT VERSION") + .register(); + } + + private Expression npcRole; + private Expression location; + + @SuppressWarnings("unchecked") + @Override + public boolean init(Expression @NotNull [] expressions, int matchedPattern, @NotNull ParseContext parseContext) { + this.npcRole = (Expression) expressions[0]; + this.location = (Expression) expressions[1]; + return true; + } + + @Override + protected void execute(@NotNull TriggerContext ctx) { + Optional locSingle = this.location.getSingle(ctx); + Optional roleSingle = this.npcRole.getSingle(ctx); + if (locSingle.isEmpty() || roleSingle.isEmpty()) return; + + Location location = locSingle.get(); + String worldName = location.getWorld(); + if (worldName == null) return; + + World world = Universe.get().getWorld(worldName); + if (world == null) return; + + Store store = world.getEntityStore().getStore(); + + Vector3f rotation = location.getRotation().clone(); + if (Float.isNaN(rotation.getX())) rotation = Vector3f.ZERO; + + NPCPlugin.get().spawnEntity(store, roleSingle.get().index(), location.getPosition().clone(), rotation, null, null, null); + } + + @Override + public String toString(@NotNull TriggerContext ctx, boolean debug) { + return "spawn " + this.npcRole.toString(ctx, debug) + " at " + this.location.toString(ctx, debug); + } + +} From d7a8044cb77aeb8e6ff51d8b6036ebe1338d737d Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Mon, 2 Feb 2026 16:22:55 -0800 Subject: [PATCH 17/29] Chunk stuff: - Add expression to get chunks at locations - Add effect to regenerate a chunk --- .../elements/effects/EffectHandler.java | 4 ++ .../effects/world/EffChunkRegenerate.java | 51 ++++++++++++++ .../expressions/ExpressionHandler.java | 2 + .../world/ExprChunkAtLocation.java | 69 +++++++++++++++++++ 4 files changed, 126 insertions(+) create mode 100644 src/main/java/com/github/skriptdev/skript/plugin/elements/effects/world/EffChunkRegenerate.java create mode 100644 src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/world/ExprChunkAtLocation.java diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/EffectHandler.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/EffectHandler.java index c7ce5afa..e7db02e5 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/EffectHandler.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/EffectHandler.java @@ -12,6 +12,7 @@ import com.github.skriptdev.skript.plugin.elements.effects.other.EffCancelEvent; import com.github.skriptdev.skript.plugin.elements.effects.other.EffDelay; import com.github.skriptdev.skript.plugin.elements.effects.player.EffKick; +import com.github.skriptdev.skript.plugin.elements.effects.world.EffChunkRegenerate; public class EffectHandler { @@ -34,6 +35,9 @@ public static void register(SkriptRegistration registration) { // PLAYER EffBan.register(registration); EffKick.register(registration); + + // WORLD + EffChunkRegenerate.register(registration); } } diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/world/EffChunkRegenerate.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/world/EffChunkRegenerate.java new file mode 100644 index 00000000..c2d43acc --- /dev/null +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/world/EffChunkRegenerate.java @@ -0,0 +1,51 @@ +package com.github.skriptdev.skript.plugin.elements.effects.world; + +import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; +import com.hypixel.hytale.server.core.universe.world.World; +import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk; +import io.github.syst3ms.skriptparser.lang.Effect; +import io.github.syst3ms.skriptparser.lang.Expression; +import io.github.syst3ms.skriptparser.lang.TriggerContext; +import io.github.syst3ms.skriptparser.parsing.ParseContext; +import org.jetbrains.annotations.NotNull; + +public class EffChunkRegenerate extends Effect { + + public static void register(SkriptRegistration reg) { + reg.newEffect(EffChunkRegenerate.class, + "regenerate %chunks%") + .name("Chunk Regenerate") + .description("Regenerates the specified chunks.") + .examples("regenerate chunk at player's location") + .since("INSERT VERSION") + .register(); + } + + private Expression chunks; + + @SuppressWarnings("unchecked") + @Override + public boolean init(Expression[] expressions, int matchedPattern, @NotNull ParseContext parseContext) { + this.chunks = (Expression) expressions[0]; + return true; + } + + @Override + protected void execute(@NotNull TriggerContext ctx) { + for (WorldChunk worldChunk : this.chunks.getArray(ctx)) { + World world = worldChunk.getWorld(); + Runnable runnable = () -> world.getChunkStore().getChunkReferenceAsync(worldChunk.getIndex(), 9); + if (world.isInThread()) { + runnable.run(); + } else { + world.execute(runnable); + } + } + } + + @Override + public String toString(@NotNull TriggerContext ctx, boolean debug) { + return "regenerate " + this.chunks.toString(ctx, debug); + } + +} diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/ExpressionHandler.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/ExpressionHandler.java index 4360f31a..8515c3ec 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/ExpressionHandler.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/ExpressionHandler.java @@ -42,6 +42,7 @@ import com.github.skriptdev.skript.plugin.elements.expressions.player.ExprChatMessage; import com.github.skriptdev.skript.plugin.elements.expressions.player.ExprPlayerSpawns; import com.github.skriptdev.skript.plugin.elements.expressions.server.ExprConsole; +import com.github.skriptdev.skript.plugin.elements.expressions.world.ExprChunkAtLocation; import com.github.skriptdev.skript.plugin.elements.expressions.world.ExprWorld; import com.github.skriptdev.skript.plugin.elements.expressions.world.ExprWorldOf; import com.github.skriptdev.skript.plugin.elements.expressions.world.ExprWorldSpawn; @@ -103,6 +104,7 @@ public static void register(SkriptRegistration registration) { ExprConsole.register(registration); // WORLD + ExprChunkAtLocation.register(registration); ExprWorld.register(registration); ExprWorldOf.register(registration); ExprWorldSpawn.register(registration); diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/world/ExprChunkAtLocation.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/world/ExprChunkAtLocation.java new file mode 100644 index 00000000..424ae852 --- /dev/null +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/world/ExprChunkAtLocation.java @@ -0,0 +1,69 @@ +package com.github.skriptdev.skript.plugin.elements.expressions.world; + +import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; +import com.hypixel.hytale.math.util.ChunkUtil; +import com.hypixel.hytale.math.vector.Location; +import com.hypixel.hytale.math.vector.Vector3i; +import com.hypixel.hytale.server.core.universe.Universe; +import com.hypixel.hytale.server.core.universe.world.World; +import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk; +import io.github.syst3ms.skriptparser.lang.Expression; +import io.github.syst3ms.skriptparser.lang.TriggerContext; +import io.github.syst3ms.skriptparser.parsing.ParseContext; +import org.jetbrains.annotations.NotNull; + +public class ExprChunkAtLocation implements Expression { + + public static void register(SkriptRegistration reg) { + reg.newExpression(ExprChunkAtLocation.class, WorldChunk.class, true, + "chunk[s] at %locations%") + .name("Chunk At Location") + .description("Get the chunk at a location.") + .examples("set {_chunk} to chunk at player's location", + "regenerate chunk at player's location") + .since("INSERT VERSION") + .register(); + } + + private Expression locations; + + @SuppressWarnings("unchecked") + @Override + public boolean init(Expression[] expressions, int matchedPattern, @NotNull ParseContext parseContext) { + this.locations = (Expression) expressions[0]; + return true; + } + + @Override + public WorldChunk[] getValues(@NotNull TriggerContext ctx) { + Location[] locArray = this.locations.getArray(ctx); + WorldChunk[] chunks = new WorldChunk[locArray.length]; + + for (int i = 0; i < locArray.length; i++) { + Location location = locArray[i]; + String worldName = location.getWorld(); + if (worldName == null) continue; + + World world = Universe.get().getWorld(worldName); + if (world == null) continue; + + Vector3i pos = location.getPosition().toVector3i(); + + long index = ChunkUtil.indexChunkFromBlock(pos.getX(), pos.getZ()); + chunks[i] = world.getChunk(index); + } + + return chunks; + } + + @Override + public boolean isSingle() { + return this.locations.isSingle(); + } + + @Override + public String toString(@NotNull TriggerContext ctx, boolean debug) { + return "chunk[s] at " + this.locations.toString(ctx, debug); + } + +} From 0bb600893576b2bbb210830a95812a59f1ee567e Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Mon, 2 Feb 2026 17:11:09 -0800 Subject: [PATCH 18/29] EntityComponentUtils - add shortcut method to get component of an entity --- .../api/hytale/EntityComponentUtils.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/main/java/com/github/skriptdev/skript/api/hytale/EntityComponentUtils.java b/src/main/java/com/github/skriptdev/skript/api/hytale/EntityComponentUtils.java index 088a26da..c8b07171 100644 --- a/src/main/java/com/github/skriptdev/skript/api/hytale/EntityComponentUtils.java +++ b/src/main/java/com/github/skriptdev/skript/api/hytale/EntityComponentUtils.java @@ -1,6 +1,8 @@ package com.github.skriptdev.skript.api.hytale; import com.hypixel.hytale.component.AddReason; +import com.hypixel.hytale.component.Component; +import com.hypixel.hytale.component.ComponentType; import com.hypixel.hytale.component.Holder; import com.hypixel.hytale.component.Ref; import com.hypixel.hytale.component.Store; @@ -27,6 +29,24 @@ @SuppressWarnings("UnusedReturnValue") public class EntityComponentUtils { + /** + * Get a component from an Entity + * + * @param entity Entity to get component from + * @param type Component type to get + * @param EntityStore Type + * @param Type of returned component + * @return Component from entity if available otherwise null + */ + @SuppressWarnings("unchecked") + public static > @Nullable T getComponent(Entity entity, ComponentType type) { + Ref reference = (Ref) entity.getReference(); + if (reference == null) return null; + + Store store = reference.getStore(); + return store.getComponent(reference, type); + } + /** * Get the EntityStatMap component of an entity. * From 5cf703952b8385b2746857ccf4a02b86b80590dc Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Mon, 2 Feb 2026 17:11:39 -0800 Subject: [PATCH 19/29] ExprEntityVelocity - add expression to get/modify entity velocity --- .../expressions/ExpressionHandler.java | 2 + .../entity/ExprEntityVelocity.java | 91 +++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/entity/ExprEntityVelocity.java diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/ExpressionHandler.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/ExpressionHandler.java index 8515c3ec..b9784e1b 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/ExpressionHandler.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/ExpressionHandler.java @@ -12,6 +12,7 @@ import com.github.skriptdev.skript.plugin.elements.expressions.entity.ExprActiveSlot; import com.github.skriptdev.skript.plugin.elements.expressions.entity.ExprEntityHealth; import com.github.skriptdev.skript.plugin.elements.expressions.entity.ExprEntityStat; +import com.github.skriptdev.skript.plugin.elements.expressions.entity.ExprEntityVelocity; import com.github.skriptdev.skript.plugin.elements.expressions.entity.ExprHeldItem; import com.github.skriptdev.skript.plugin.elements.expressions.entity.ExprNPCType; import com.github.skriptdev.skript.plugin.elements.expressions.entity.ExprName; @@ -64,6 +65,7 @@ public static void register(SkriptRegistration registration) { ExprActiveSlot.register(registration); ExprEntityHealth.register(registration); ExprEntityStat.register(registration); + ExprEntityVelocity.register(registration); ExprHeldItem.register(registration); ExprName.register(registration); ExprNPCType.register(registration); diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/entity/ExprEntityVelocity.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/entity/ExprEntityVelocity.java new file mode 100644 index 00000000..8748937c --- /dev/null +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/entity/ExprEntityVelocity.java @@ -0,0 +1,91 @@ +package com.github.skriptdev.skript.plugin.elements.expressions.entity; + +import com.github.skriptdev.skript.api.hytale.EntityComponentUtils; +import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; +import com.hypixel.hytale.math.vector.Vector3d; +import com.hypixel.hytale.protocol.ChangeVelocityType; +import com.hypixel.hytale.server.core.entity.Entity; +import com.hypixel.hytale.server.core.modules.physics.component.Velocity; +import com.hypixel.hytale.server.core.modules.splitvelocity.VelocityConfig; +import io.github.syst3ms.skriptparser.lang.Expression; +import io.github.syst3ms.skriptparser.lang.TriggerContext; +import io.github.syst3ms.skriptparser.parsing.ParseContext; +import io.github.syst3ms.skriptparser.types.changers.ChangeMode; +import org.jetbrains.annotations.NotNull; + +import java.util.Optional; + +public class ExprEntityVelocity implements Expression { + + public static void register(SkriptRegistration reg) { + reg.newExpression(ExprEntityVelocity.class, Vector3d.class, false, + "velocit(y|ies) of %entities%") + .name("Entity Velocity") + .description("Get/set/add to the velocity of an entity.") + .examples("set velocity of player to vector3d(1, 2, 3)", + "add vector3d(1, 2, 3) to velocity of target entity of player") + .since("INSERT VERSION") + .register(); + } + + private Expression entities; + + @SuppressWarnings("unchecked") + @Override + public boolean init(Expression @NotNull [] expressions, int matchedPattern, @NotNull ParseContext parseContext) { + this.entities = (Expression) expressions[0]; + return true; + } + + @Override + public Vector3d[] getValues(@NotNull TriggerContext ctx) { + Entity[] entityArray = this.entities.getArray(ctx); + Vector3d[] velocities = new Vector3d[entityArray.length]; + + for (int i = 0; i < entityArray.length; i++) { + Velocity component = EntityComponentUtils.getComponent(entityArray[i], Velocity.getComponentType()); + if (component == null) continue; + velocities[i] = component.getVelocity(); + } + + return velocities; + } + + @Override + public Optional[]> acceptsChange(@NotNull ChangeMode mode) { + if (mode == ChangeMode.SET || mode == ChangeMode.RESET || mode == ChangeMode.ADD) + return Optional.of(new Class[]{Vector3d.class}); + return Optional.empty(); + } + + @SuppressWarnings("ConstantValue") + @Override + public void change(@NotNull TriggerContext ctx, @NotNull ChangeMode changeMode, Object @NotNull [] changeWith) { + Vector3d velocity = Vector3d.ZERO; + if (changeWith != null && changeWith[0] instanceof Vector3d vec) { + velocity = vec; + } + + for (Entity entity : this.entities.getArray(ctx)) { + Velocity component = EntityComponentUtils.getComponent(entity, Velocity.getComponentType()); + if (component == null) continue; + + switch (changeMode) { + case SET, RESET -> component.addInstruction(velocity, new VelocityConfig(), ChangeVelocityType.Set); + case ADD -> component.addInstruction(velocity, new VelocityConfig(), ChangeVelocityType.Add); + } + } + } + + @Override + public boolean isSingle() { + return this.entities.isSingle(); + } + + @Override + public String toString(@NotNull TriggerContext ctx, boolean debug) { + String plural = this.entities.isSingle() ? "velocity" : "velocities"; + return plural + " of " + this.entities.toString(ctx, debug); + } + +} From d2a36e2bac32d6d21d940e57cbefdee557dde4ec Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Mon, 2 Feb 2026 17:24:00 -0800 Subject: [PATCH 20/29] BlockContext - add a block context --- .../skript/api/skript/event/BlockContext.java | 13 +++++++++++++ .../skript/plugin/elements/events/EventHandler.java | 4 ++++ 2 files changed, 17 insertions(+) create mode 100644 src/main/java/com/github/skriptdev/skript/api/skript/event/BlockContext.java diff --git a/src/main/java/com/github/skriptdev/skript/api/skript/event/BlockContext.java b/src/main/java/com/github/skriptdev/skript/api/skript/event/BlockContext.java new file mode 100644 index 00000000..83a94bf3 --- /dev/null +++ b/src/main/java/com/github/skriptdev/skript/api/skript/event/BlockContext.java @@ -0,0 +1,13 @@ +package com.github.skriptdev.skript.api.skript.event; + +import com.github.skriptdev.skript.api.hytale.Block; +import io.github.syst3ms.skriptparser.lang.TriggerContext; + +/** + * Represents a {@link TriggerContext} which includes a {@link Block} + */ +public interface BlockContext extends TriggerContext { + + Block[] getBlock(); + +} diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/EventHandler.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/EventHandler.java index f3690392..f067b533 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/EventHandler.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/EventHandler.java @@ -1,6 +1,8 @@ package com.github.skriptdev.skript.plugin.elements.events; +import com.github.skriptdev.skript.api.hytale.Block; +import com.github.skriptdev.skript.api.skript.event.BlockContext; import com.github.skriptdev.skript.api.skript.event.PlayerContext; import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; import com.github.skriptdev.skript.plugin.elements.events.entity.EvtEntityDamage; @@ -62,6 +64,8 @@ public static void register(SkriptRegistration registration) { } private static void registerGlobalContexts(SkriptRegistration reg) { + reg.newContextValue(BlockContext.class, Block.class, true, "block", BlockContext::getBlock) + .register(); reg.newContextValue(PlayerContext.class, Player.class, true, "player", PlayerContext::getPlayer) .setUsage(Usage.EXPRESSION_OR_ALONE) .register(); From 29b0ef10013a9881ded02cb3731924e8c49367f1 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Mon, 2 Feb 2026 17:41:25 -0800 Subject: [PATCH 21/29] AssetStoreUtils - add new util --- .../skript/api/hytale/AssetStoreUtils.java | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 src/main/java/com/github/skriptdev/skript/api/hytale/AssetStoreUtils.java diff --git a/src/main/java/com/github/skriptdev/skript/api/hytale/AssetStoreUtils.java b/src/main/java/com/github/skriptdev/skript/api/hytale/AssetStoreUtils.java new file mode 100644 index 00000000..062fd6cf --- /dev/null +++ b/src/main/java/com/github/skriptdev/skript/api/hytale/AssetStoreUtils.java @@ -0,0 +1,45 @@ +package com.github.skriptdev.skript.api.hytale; + +import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType; +import com.hypixel.hytale.server.core.asset.type.item.config.Item; +import com.hypixel.hytale.server.core.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * Quick utility methods for working with AssetStore + */ +public class AssetStoreUtils { + + /** + * Get a BlockType from ID + * + * @param blockId ID of the BlockType + * @return BlockType from ID if found, otherwise null + */ + public static @Nullable BlockType getBlockType(@NotNull String blockId) { + return BlockType.getAssetMap().getAsset(blockId); + } + + /** + * Get a BlockType from ItemStack + * + * @param itemStack ItemStack to get BlockType from + * @return BlockType from ItemStack if found, otherwise null + */ + public static @Nullable BlockType getBlockType(@NotNull ItemStack itemStack) { + return getBlockType(itemStack.getItem()); + } + + /** + * Get a BlockType from Item + * + * @param item Item to get BlockType from + * @return BlockType from Item if found, otherwise null + */ + public static @Nullable BlockType getBlockType(@NotNull Item item) { + if (item.hasBlockType()) return getBlockType(item.getBlockId()); + return null; + } + +} From 8d03345119cc1bf66ce71b2f4f529200765ef077 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Mon, 2 Feb 2026 17:41:59 -0800 Subject: [PATCH 22/29] EvtPlayerPlaceBlock - add event --- .../plugin/elements/events/EventHandler.java | 2 + .../events/player/EvtPlayerPlaceBlock.java | 154 ++++++++++++++++++ 2 files changed, 156 insertions(+) create mode 100644 src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerPlaceBlock.java diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/EventHandler.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/EventHandler.java index f067b533..b841a1ad 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/EventHandler.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/EventHandler.java @@ -19,6 +19,7 @@ import com.github.skriptdev.skript.plugin.elements.events.player.EvtPlayerJoin; import com.github.skriptdev.skript.plugin.elements.events.player.EvtPlayerMouseClick; import com.github.skriptdev.skript.plugin.elements.events.player.EvtPlayerMouseMove; +import com.github.skriptdev.skript.plugin.elements.events.player.EvtPlayerPlaceBlock; import com.github.skriptdev.skript.plugin.elements.events.player.EvtPlayerSetupConnect; import com.github.skriptdev.skript.plugin.elements.events.player.EvtPlayerSetupDisconnect; import com.github.skriptdev.skript.plugin.elements.events.player.EvtPlayerUseBlock; @@ -48,6 +49,7 @@ public static void register(SkriptRegistration registration) { EvtPlayerJoin.register(registration); EvtPlayerMouseClick.register(registration); EvtPlayerMouseMove.register(registration); + EvtPlayerPlaceBlock.register(registration); EvtPlayerSetupConnect.register(registration); EvtPlayerSetupDisconnect.register(registration); EvtPlayerUseBlock.register(registration); diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerPlaceBlock.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerPlaceBlock.java new file mode 100644 index 00000000..0ac5571b --- /dev/null +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerPlaceBlock.java @@ -0,0 +1,154 @@ +package com.github.skriptdev.skript.plugin.elements.events.player; + +import com.github.skriptdev.skript.api.hytale.AssetStoreUtils; +import com.github.skriptdev.skript.api.hytale.Block; +import com.github.skriptdev.skript.api.skript.event.BlockContext; +import com.github.skriptdev.skript.api.skript.event.CancellableContext; +import com.github.skriptdev.skript.api.skript.event.PlayerContext; +import com.github.skriptdev.skript.api.skript.event.SystemEvent; +import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; +import com.hypixel.hytale.component.ArchetypeChunk; +import com.hypixel.hytale.component.CommandBuffer; +import com.hypixel.hytale.component.Ref; +import com.hypixel.hytale.component.Store; +import com.hypixel.hytale.component.query.Query; +import com.hypixel.hytale.component.system.EntityEventSystem; +import com.hypixel.hytale.math.vector.Vector3i; +import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType; +import com.hypixel.hytale.server.core.asset.type.item.config.Item; +import com.hypixel.hytale.server.core.entity.entities.Player; +import com.hypixel.hytale.server.core.event.events.ecs.PlaceBlockEvent; +import com.hypixel.hytale.server.core.inventory.ItemStack; +import com.hypixel.hytale.server.core.universe.world.World; +import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; +import io.github.syst3ms.skriptparser.lang.Expression; +import io.github.syst3ms.skriptparser.lang.TriggerContext; +import io.github.syst3ms.skriptparser.lang.TriggerMap; +import io.github.syst3ms.skriptparser.parsing.ParseContext; +import io.github.syst3ms.skriptparser.registration.context.ContextValue; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class EvtPlayerPlaceBlock extends SystemEvent> { + + public static void register(SkriptRegistration reg) { + reg.newEvent(EvtPlayerPlaceBlock.class, + "player place block", "player places block", "player placed block") + .name("Player Place Block") + .description("Called when a player places a block.") + .examples("on player place block:", + "\tset {_past} to past context-blocktype", + "\tset {_future} to context-blocktype", + "\tbroadcast \"%context-player% placed %{_future}% over %{_past}%\"") + .since("INSERT VERSION") + .setHandledContexts(PlaceBlockContext.class) + .register(); + + reg.addContextValue(PlaceBlockContext.class, Item.class, true, "item-in-hand", PlaceBlockContext::getItemInHand); + reg.addContextValue(PlaceBlockContext.class, ItemStack.class, true, "itemstack-in-hand", PlaceBlockContext::getItemStackInHand); + reg.addContextValue(PlaceBlockContext.class, BlockType.class, true, "blocktype", PlaceBlockContext::getPlacedBlockType); + reg.newContextValue(PlaceBlockContext.class, BlockType.class, true, "blocktype", PlaceBlockContext::getPreviousBlockType) + .setState(ContextValue.State.PAST) + .register(); + } + + private static PlaceBlockSystem SYSTEM; + + @Override + public boolean init(Expression[] expressions, int matchedPattern, ParseContext parseContext) { + if (SYSTEM == null) { + SYSTEM = new PlaceBlockSystem(); + applySystem(SYSTEM); + } + return true; + } + + @Override + public boolean check(TriggerContext ctx) { + return ctx instanceof PlaceBlockContext; + } + + @Override + public String toString(@NotNull TriggerContext ctx, boolean debug) { + return "player place block"; + } + + public record PlaceBlockContext(PlaceBlockEvent event, + Player player) implements PlayerContext, BlockContext, CancellableContext { + + public Player[] getPlayer() { + return new Player[]{this.player}; + } + + public Item[] getItemInHand() { + ItemStack itemInHand = this.event.getItemInHand(); + if (itemInHand == null) return null; + return new Item[]{itemInHand.getItem()}; + } + + public ItemStack[] getItemStackInHand() { + return new ItemStack[]{this.event.getItemInHand()}; + } + + public BlockType[] getPreviousBlockType() { + Block[] block = getBlock(); + if (block == null) return null; + Block block1 = block[0]; + if (block1 == null) return null; + return new BlockType[]{block1.getType()}; + } + + public BlockType[] getPlacedBlockType() { + ItemStack itemInHand = this.event.getItemInHand(); + if (itemInHand == null) return null; + return new BlockType[]{AssetStoreUtils.getBlockType(itemInHand.getItem())}; + } + + @Override + public Block[] getBlock() { + Vector3i targetBlock = this.event.getTargetBlock(); + World world = this.player.getWorld(); + if (world == null) return null; + return new Block[]{new Block(world, targetBlock)}; + } + + @Override + public boolean isCancelled() { + return this.event.isCancelled(); + } + + @Override + public void setCancelled(boolean cancelled) { + this.event.setCancelled(cancelled); + } + + @Override + public String getName() { + return "place block context"; + } + } + + public static class PlaceBlockSystem extends EntityEventSystem { + protected PlaceBlockSystem() { + super(PlaceBlockEvent.class); + } + + @Override + public void handle(int i, @NotNull ArchetypeChunk archetypeChunk, @NotNull Store store, + @NotNull CommandBuffer commandBuffer, @NotNull PlaceBlockEvent event) { + + Ref ref = archetypeChunk.getReferenceTo(i); + Player player = store.getComponent(ref, Player.getComponentType()); + if (player == null) return; + + PlaceBlockContext context = new PlaceBlockContext(event, player); + TriggerMap.callTriggersByContext(context); + } + + @Override + public @Nullable Query getQuery() { + return Player.getComponentType(); + } + } + +} From 5c04784a4832ac1e69b51785cdd744d028e013e8 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Mon, 2 Feb 2026 21:19:56 -0800 Subject: [PATCH 23/29] DefaultConverters - add converter for Player -> PlayerRef --- .../skript/plugin/elements/types/DefaultConverters.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/types/DefaultConverters.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/types/DefaultConverters.java index 7eb503eb..cc3528bb 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/types/DefaultConverters.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/types/DefaultConverters.java @@ -2,6 +2,8 @@ import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType; import com.hypixel.hytale.server.core.asset.type.item.config.Item; +import com.hypixel.hytale.server.core.entity.entities.Player; +import com.hypixel.hytale.server.core.universe.PlayerRef; import io.github.syst3ms.skriptparser.types.conversions.Converters; import java.util.Optional; @@ -12,6 +14,7 @@ public static void register() { inventory(); } + @SuppressWarnings("removal") private static void inventory() { // Item to BlockType Converters.registerConverter(Item.class, BlockType.class, (item) -> { @@ -30,6 +33,10 @@ private static void inventory() { if (item != null) return Optional.of(item); return Optional.empty(); }); + + // Player to PlayerRef + Converters.registerConverter(Player.class, PlayerRef.class, (player) -> + Optional.ofNullable(player.getPlayerRef())); } } From 0cbc542fa87c7c04a48a306d7153a2463e4b8dc4 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Mon, 2 Feb 2026 21:20:17 -0800 Subject: [PATCH 24/29] SecPlaySound - add sound section --- .../elements/sections/SecPlaySound.java | 131 ++++++++++++++++++ .../elements/sections/SectionHandler.java | 1 + .../plugin/elements/types/TypesWorld.java | 13 +- 3 files changed, 142 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/github/skriptdev/skript/plugin/elements/sections/SecPlaySound.java diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/sections/SecPlaySound.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/sections/SecPlaySound.java new file mode 100644 index 00000000..e8b891ba --- /dev/null +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/sections/SecPlaySound.java @@ -0,0 +1,131 @@ +package com.github.skriptdev.skript.plugin.elements.sections; + +import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; +import com.hypixel.hytale.component.Ref; +import com.hypixel.hytale.component.Store; +import com.hypixel.hytale.math.vector.Location; +import com.hypixel.hytale.math.vector.Vector3d; +import com.hypixel.hytale.protocol.SoundCategory; +import com.hypixel.hytale.server.core.asset.type.soundevent.config.SoundEvent; +import com.hypixel.hytale.server.core.universe.PlayerRef; +import com.hypixel.hytale.server.core.universe.Universe; +import com.hypixel.hytale.server.core.universe.world.SoundUtil; +import com.hypixel.hytale.server.core.universe.world.World; +import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; +import io.github.syst3ms.skriptparser.file.FileSection; +import io.github.syst3ms.skriptparser.lang.CodeSection; +import io.github.syst3ms.skriptparser.lang.Expression; +import io.github.syst3ms.skriptparser.lang.Statement; +import io.github.syst3ms.skriptparser.lang.TriggerContext; +import io.github.syst3ms.skriptparser.lang.entries.SectionConfiguration; +import io.github.syst3ms.skriptparser.log.SkriptLogger; +import io.github.syst3ms.skriptparser.parsing.ParseContext; +import io.github.syst3ms.skriptparser.parsing.ParserState; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Optional; + +public class SecPlaySound extends CodeSection { + + public static void register(SkriptRegistration reg) { + reg.newSection(SecPlaySound.class, "play sound %soundevent%") + .name("Play Sound") + .description("Play a sound at a location or to players.", + "**Entries**:", + " - `to-players` = The players/playerRefs to send the sound to (must use either this or `location`).", + " - `location` = The location to play the sound at (must use either this or `to-players`).", + " - `volume` = The volume of the sound ([optional] default: 1.0).", + " - `pitch` = The pitch of the sound ([optional] default: 1.0).", + " - `3d` = Whether the sound should be 3D ([optional, `location` is required for this] default: false).", + " - `sound-category` = The category of the sound ([optional] default: ambient).") + .experimental("This seems a bit messy/buggy and may change in the future.") + .since("INSERT VERSION") + .register(); + } + + SectionConfiguration sectionConfig = new SectionConfiguration.Builder() + .addOptionalExpression("to-players", PlayerRef.class, true) + .addOptionalKey("location") + .addOptionalLiteral("volume", Number.class) + .addOptionalLiteral("pitch", Number.class) + .addOptionalLiteral("3d", Boolean.class) + .addOptionalLiteral("sound-category", SoundCategory.class) + .build(); + + private Expression soundEvent; + + @SuppressWarnings("unchecked") + @Override + public boolean init(Expression @NotNull [] expressions, int matchedPattern, @NotNull ParseContext parseContext) { + this.soundEvent = (Expression) expressions[0]; + return true; + } + + @Override + public boolean loadSection(@NotNull FileSection section, @NotNull ParserState parserState, @NotNull SkriptLogger logger) { + return this.sectionConfig.loadConfiguration(null, section, parserState, logger); + } + + @Override + public Optional walk(@NotNull TriggerContext ctx) { + Optional nextStatement = getNext(); + + SoundEvent soundEvent = this.soundEvent.getSingle(ctx).orElse(null); + if (soundEvent == null) return nextStatement; + int soundIndex = SoundEvent.getAssetMap().getIndex(soundEvent.getId()); + if (soundIndex < 0) return nextStatement; + + Location location = this.sectionConfig.getValue("location", Location.class).orElse(null); + Expression playerExpr = this.sectionConfig.getExpression("to-players", PlayerRef.class).orElse(null); + Number volume = this.sectionConfig.getValue("volume", Number.class).orElse(1.0f); + Number pitch = this.sectionConfig.getValue("pitch", Number.class).orElse(1.0f); + boolean is3d = this.sectionConfig.getValue("3d", Boolean.class).orElse(false); + SoundCategory soundCategory = this.sectionConfig.getValue("sound-category", SoundCategory.class).orElse(SoundCategory.Ambient); + + if (playerExpr != null) { + PlayerRef[] playerRefs = playerExpr.getArray(ctx); + playSoundToPlayer(playerRefs, location, soundIndex, soundCategory, is3d, volume.floatValue(), pitch.floatValue()); + } else if (location != null) { + playSoundAtLocation(location, soundIndex, soundCategory, is3d, volume.floatValue(), pitch.floatValue()); + } + return nextStatement; + } + + @Override + public String toString(@NotNull TriggerContext ctx, boolean debug) { + return ""; + } + + public void playSoundToPlayer(@NotNull PlayerRef[] players, @Nullable Location location, int soundEvent, SoundCategory category, boolean is3d, float volume, float pitch) { + for (PlayerRef player : players) { + if (is3d && location != null) { + Vector3d pos = location.getPosition(); + Ref reference = player.getReference(); + if (reference == null || !reference.isValid()) continue; + + Store store = reference.getStore(); + SoundUtil.playSoundEvent3dToPlayer(reference, soundEvent, category, pos.getX(), pos.getY(), pos.getZ(), volume, pitch, store); + } else { + SoundUtil.playSoundEvent2dToPlayer(player, soundEvent, category, volume, pitch); + } + } + } + + public void playSoundAtLocation(@NotNull Location location, int soundEvent, SoundCategory category, boolean is3d, float volume, float pitch) { + String worldName = location.getWorld(); + if (worldName == null) return; + + World world = Universe.get().getWorld(worldName); + if (world == null) return; + + Store store = world.getEntityStore().getStore(); + if (is3d) { + Vector3d pos = location.getPosition(); + SoundUtil.playSoundEvent3d(soundEvent, category, pos.getX(), pos.getY(), pos.getZ(), volume, pitch, store); + } else { + SoundUtil.playSoundEvent2d(soundEvent, category, volume, pitch, store); + } + } + +} diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/sections/SectionHandler.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/sections/SectionHandler.java index f3f0541f..0c25581e 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/sections/SectionHandler.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/sections/SectionHandler.java @@ -7,6 +7,7 @@ public class SectionHandler { public static void register(SkriptRegistration registration) { SecDropItem.register(registration); SecExecuteInWorld.register(registration); + SecPlaySound.register(registration); SecSpawnNPC.register(registration); } diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesWorld.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesWorld.java index fc8bba3d..612f9aa2 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesWorld.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesWorld.java @@ -1,19 +1,26 @@ package com.github.skriptdev.skript.plugin.elements.types; +import com.github.skriptdev.skript.api.skript.registration.EnumRegistry; import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; +import com.hypixel.hytale.protocol.SoundCategory; import com.hypixel.hytale.server.core.universe.world.World; import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk; public class TypesWorld { - static void register(SkriptRegistration registration) { - registration.newType(World.class, "world", "world@s") + static void register(SkriptRegistration reg) { + EnumRegistry.register(reg, SoundCategory.class, "soundcategory", "soundcategor@y@ies") + .name("Sound Category") + .description("Represents a sound category.") + .since("INSERT VERSION") + .register(); + reg.newType(World.class, "world", "world@s") .name("World") .description("Represents a world in the game.") .since("1.0.0") .toStringFunction(World::getName) .register(); - registration.newType(WorldChunk.class, "chunk", "chunk@s") + reg.newType(WorldChunk.class, "chunk", "chunk@s") .name("Chunk") .description("Represents a chunk in a world. A chunk is a 32x32x(world height) set of blocks.") .since("1.0.0") From c067f6784fa9d880d62c0a5551622bee291c7025 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Mon, 2 Feb 2026 22:03:26 -0800 Subject: [PATCH 25/29] EvtEntityPickupItem - add pickup event --- .../plugin/elements/events/EventHandler.java | 4 +- .../events/entity/EvtEntityPickupItem.java | 135 ++++++++++++++++++ 2 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/github/skriptdev/skript/plugin/elements/events/entity/EvtEntityPickupItem.java diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/EventHandler.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/EventHandler.java index b841a1ad..54b1d72a 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/EventHandler.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/EventHandler.java @@ -7,6 +7,7 @@ import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; import com.github.skriptdev.skript.plugin.elements.events.entity.EvtEntityDamage; import com.github.skriptdev.skript.plugin.elements.events.entity.EvtEntityDeath; +import com.github.skriptdev.skript.plugin.elements.events.entity.EvtEntityPickupItem; import com.github.skriptdev.skript.plugin.elements.events.entity.EvtEntityRemove; import com.github.skriptdev.skript.plugin.elements.events.entity.EvtLivingEntityInvChange; import com.github.skriptdev.skript.plugin.elements.events.player.EvtPlayerAddToWorld; @@ -34,8 +35,9 @@ public class EventHandler { public static void register(SkriptRegistration registration) { // ENTITY EvtEntityDamage.register(registration); - EvtEntityRemove.register(registration); EvtEntityDeath.register(registration); + EvtEntityPickupItem.register(registration); + EvtEntityRemove.register(registration); EvtLivingEntityInvChange.register(registration); // PLAYER diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/entity/EvtEntityPickupItem.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/entity/EvtEntityPickupItem.java new file mode 100644 index 00000000..a8c85c76 --- /dev/null +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/entity/EvtEntityPickupItem.java @@ -0,0 +1,135 @@ +package com.github.skriptdev.skript.plugin.elements.events.entity; + +import com.github.skriptdev.skript.api.skript.event.CancellableContext; +import com.github.skriptdev.skript.api.skript.event.PlayerContext; +import com.github.skriptdev.skript.api.skript.event.SystemEvent; +import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; +import com.hypixel.hytale.component.ArchetypeChunk; +import com.hypixel.hytale.component.CommandBuffer; +import com.hypixel.hytale.component.Ref; +import com.hypixel.hytale.component.Store; +import com.hypixel.hytale.component.query.Query; +import com.hypixel.hytale.component.system.EntityEventSystem; +import com.hypixel.hytale.server.core.entity.Entity; +import com.hypixel.hytale.server.core.entity.entities.Player; +import com.hypixel.hytale.server.core.event.events.ecs.InteractivelyPickupItemEvent; +import com.hypixel.hytale.server.core.inventory.ItemStack; +import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; +import com.hypixel.hytale.server.npc.entities.NPCEntity; +import io.github.syst3ms.skriptparser.lang.Expression; +import io.github.syst3ms.skriptparser.lang.TriggerContext; +import io.github.syst3ms.skriptparser.lang.TriggerMap; +import io.github.syst3ms.skriptparser.parsing.ParseContext; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class EvtEntityPickupItem extends SystemEvent> { + + public static void register(SkriptRegistration reg) { + reg.newEvent(EvtEntityPickupItem.class, + "entity interactively pickup item", "entity interactively picked up item", + "player interactively pickup item", "player interactively picked up item") + .name("Entity Interactively Pickup Item") + .description("Called when picking up an item after interacting, such as clicking `F` on a block.") + .since("INSERT VERSION") + .setHandledContexts(PickupItemContext.class) + .register(); + + reg.addContextValue(PickupItemContext.class, Entity.class, true, "entity", PickupItemContext::getEntity); + reg.addContextValue(PickupItemContext.class, ItemStack.class, true, "item-stack", PickupItemContext::getItemStack); + } + + private static PickupItemSystem SYSTEM; + private int pattern; + + @Override + public boolean init(Expression[] expressions, int matchedPattern, ParseContext parseContext) { + this.pattern = matchedPattern > 1 ? 1 : 0; + if (SYSTEM == null) { + SYSTEM = new PickupItemSystem(); + applySystem(SYSTEM); + } + return true; + } + + @Override + public boolean check(TriggerContext ctx) { + if (ctx instanceof PickupItemContext pickupItemContext) { + return this.pattern == pickupItemContext.pattern; + } + return false; + } + + @Override + public String toString(@NotNull TriggerContext ctx, boolean debug) { + return "entity pickup item"; + } + + public record PickupItemContext(InteractivelyPickupItemEvent event, Entity entity, + int pattern) implements PlayerContext, CancellableContext { + + public Entity[] getEntity() { + return new Entity[]{this.entity}; + } + + public ItemStack[] getItemStack() { + return new ItemStack[]{this.event.getItemStack()}; + } + + public Player[] getPlayer() { + if (this.entity instanceof Player p) return new Player[]{p}; + return null; + } + + @Override + public boolean isCancelled() { + return this.event.isCancelled(); + } + + @Override + public void setCancelled(boolean cancelled) { + this.event.setCancelled(cancelled); + } + + @Override + public String getName() { + return "pickup item context"; + } + } + + public static class PickupItemSystem extends EntityEventSystem { + protected PickupItemSystem() { + super(InteractivelyPickupItemEvent.class); + } + + + @SuppressWarnings("DataFlowIssue") + @Override + public void handle(int i, @NotNull ArchetypeChunk archetypeChunk, @NotNull Store store, + @NotNull CommandBuffer commandBuffer, @NotNull InteractivelyPickupItemEvent event) { + + Ref ref = archetypeChunk.getReferenceTo(i); + + Entity entity = null; + int pattern = 0; + Player player = store.getComponent(ref, Player.getComponentType()); + if (player != null) { + pattern = 1; + entity = player; + } else { + NPCEntity component = store.getComponent(ref, NPCEntity.getComponentType()); + if (component != null) { + entity = component; + } + } + + PickupItemContext pickupItemContext = new PickupItemContext(event, entity, pattern); + TriggerMap.callTriggersByContext(pickupItemContext); + } + + @Override + public @Nullable Query getQuery() { + return Player.getComponentType(); + } + } +} From fc3c5e94c38b4080abc616f4872ba411a8458685 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Tue, 3 Feb 2026 08:56:09 -0800 Subject: [PATCH 26/29] ContextValue overhaul --- .../skript/api/skript/event/BlockContext.java | 2 +- .../api/skript/event/PlayerContext.java | 2 +- .../skript/plugin/command/EffectCommands.java | 6 +- .../effects/other/EffSendMessage.java | 19 +++-- .../plugin/elements/events/EventHandler.java | 4 +- .../events/entity/EvtEntityDamage.java | 32 ++++----- .../events/entity/EvtEntityPickupItem.java | 16 ++--- .../events/player/EvtPlayerAddToWorld.java | 10 +-- .../events/player/EvtPlayerBreakBlock.java | 47 +++++++------ .../elements/events/player/EvtPlayerChat.java | 69 +++++++++++++++---- .../events/player/EvtPlayerDamageBlock.java | 34 ++++----- .../events/player/EvtPlayerDropItem.java | 22 +++--- .../player/EvtPlayerDropItemRequest.java | 29 ++++---- .../elements/events/player/EvtPlayerJoin.java | 4 +- .../events/player/EvtPlayerMouseClick.java | 34 ++++----- .../events/player/EvtPlayerMouseMove.java | 34 ++++----- .../events/player/EvtPlayerPlaceBlock.java | 36 +++++----- .../events/player/EvtPlayerUseBlock.java | 22 +++--- .../expressions/player/ExprChatMessage.java | 2 +- .../plugin/elements/sections/SecDropItem.java | 12 ++-- .../plugin/elements/types/TypesWorld.java | 17 +++-- 21 files changed, 254 insertions(+), 199 deletions(-) diff --git a/src/main/java/com/github/skriptdev/skript/api/skript/event/BlockContext.java b/src/main/java/com/github/skriptdev/skript/api/skript/event/BlockContext.java index 83a94bf3..d2bedd68 100644 --- a/src/main/java/com/github/skriptdev/skript/api/skript/event/BlockContext.java +++ b/src/main/java/com/github/skriptdev/skript/api/skript/event/BlockContext.java @@ -8,6 +8,6 @@ */ public interface BlockContext extends TriggerContext { - Block[] getBlock(); + Block getBlock(); } diff --git a/src/main/java/com/github/skriptdev/skript/api/skript/event/PlayerContext.java b/src/main/java/com/github/skriptdev/skript/api/skript/event/PlayerContext.java index 746c6288..839237a1 100644 --- a/src/main/java/com/github/skriptdev/skript/api/skript/event/PlayerContext.java +++ b/src/main/java/com/github/skriptdev/skript/api/skript/event/PlayerContext.java @@ -8,6 +8,6 @@ */ public interface PlayerContext extends TriggerContext { - Player[] getPlayer(); + Player getPlayer(); } diff --git a/src/main/java/com/github/skriptdev/skript/plugin/command/EffectCommands.java b/src/main/java/com/github/skriptdev/skript/plugin/command/EffectCommands.java index e04db8c6..fc285e4e 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/command/EffectCommands.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/command/EffectCommands.java @@ -26,7 +26,7 @@ public class EffectCommands { public static void register(Skript skript, String token, boolean allowOps, String permission) { - skript.getSkriptRegistration().newContextValue(PlayerEffectContext.class, Player.class, true, "me", PlayerEffectContext::getPlayer) + skript.getSkriptRegistration().newSingleContextValue(PlayerEffectContext.class, Player.class, "me", PlayerEffectContext::getPlayer) .setUsage(Usage.EXPRESSION_OR_ALONE) .register(); @@ -99,8 +99,8 @@ public static void register(Skript skript, String token, boolean allowOps, Strin private record PlayerEffectContext(Player player) implements PlayerContext { - public Player[] getPlayer() { - return new Player[]{this.player}; + public Player getPlayer() { + return this.player; } @Override diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/other/EffSendMessage.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/other/EffSendMessage.java index a579c9b9..ec43e251 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/other/EffSendMessage.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/other/EffSendMessage.java @@ -3,7 +3,7 @@ import com.github.skriptdev.skript.api.skript.event.PlayerContext; import com.github.skriptdev.skript.api.utils.Utils; import com.hypixel.hytale.server.core.Message; -import com.hypixel.hytale.server.core.command.system.CommandSender; +import com.hypixel.hytale.server.core.entity.entities.Player; import com.hypixel.hytale.server.core.receiver.IMessageReceiver; import io.github.syst3ms.skriptparser.lang.Effect; import io.github.syst3ms.skriptparser.lang.Expression; @@ -57,15 +57,14 @@ protected void execute(@NotNull TriggerContext ctx) { } } else { if (ctx instanceof PlayerContext playerContext) { - for (CommandSender commandSender : playerContext.getPlayer()) { - for (Object value : messages) { - if (value instanceof String string) { - Utils.sendMessage(commandSender, string); - } else if (value instanceof Message message) { - commandSender.sendMessage(message); - } else { - Utils.sendMessage(commandSender, TypeManager.toString(new Object[]{value})); - } + Player commandSender = playerContext.getPlayer(); + for (Object value : messages) { + if (value instanceof String string) { + Utils.sendMessage(commandSender, string); + } else if (value instanceof Message message) { + commandSender.sendMessage(message); + } else { + Utils.sendMessage(commandSender, TypeManager.toString(new Object[]{value})); } } } else { diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/EventHandler.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/EventHandler.java index 54b1d72a..5f8363fe 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/EventHandler.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/EventHandler.java @@ -68,9 +68,9 @@ public static void register(SkriptRegistration registration) { } private static void registerGlobalContexts(SkriptRegistration reg) { - reg.newContextValue(BlockContext.class, Block.class, true, "block", BlockContext::getBlock) + reg.newSingleContextValue(BlockContext.class, Block.class, "block", BlockContext::getBlock) .register(); - reg.newContextValue(PlayerContext.class, Player.class, true, "player", PlayerContext::getPlayer) + reg.newSingleContextValue(PlayerContext.class, Player.class, "player", PlayerContext::getPlayer) .setUsage(Usage.EXPRESSION_OR_ALONE) .register(); } diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/entity/EvtEntityDamage.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/entity/EvtEntityDamage.java index b731988a..315a5635 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/entity/EvtEntityDamage.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/entity/EvtEntityDamage.java @@ -34,11 +34,11 @@ public static void register(SkriptRegistration reg) { .since("1.0.0") .register(); - reg.addContextValue(EntityDamageContext.class, Entity.class, true, "victim", EntityDamageContext::getVictim); - reg.addContextValue(EntityDamageContext.class, Entity.class, true, "attacker", EntityDamageContext::getAttacker); - reg.addContextValue(EntityDamageContext.class, Float.class, true, "damage-amount", EntityDamageContext::getDamage); - reg.addContextValue(EntityDamageContext.class, Damage.Source.class, true, "damage-source", EntityDamageContext::getDamageSource); - reg.addContextValue(EntityDamageContext.class, DamageCause.class, true, "damage-cause", EntityDamageContext::getDamageCause); + reg.addSingleContextValue(EntityDamageContext.class, Entity.class, "victim", EntityDamageContext::getVictim); + reg.addSingleContextValue(EntityDamageContext.class, Entity.class, "attacker", EntityDamageContext::getAttacker); + reg.addSingleContextValue(EntityDamageContext.class, Float.class, "damage-amount", EntityDamageContext::getDamage); + reg.addSingleContextValue(EntityDamageContext.class, Damage.Source.class, "damage-source", EntityDamageContext::getDamageSource); + reg.addSingleContextValue(EntityDamageContext.class, DamageCause.class, "damage-cause", EntityDamageContext::getDamageCause); } private static EntityDamageSystem SYSTEM; @@ -65,33 +65,33 @@ public String toString(@NotNull TriggerContext ctx, boolean debug) { private record EntityDamageContext(Entity entity, Store store, Damage damage) implements TriggerContext, CancellableContext { - public Entity[] getVictim() { - return new Entity[]{this.entity}; + public Entity getVictim() { + return this.entity; } @SuppressWarnings("DataFlowIssue") - public Entity[] getAttacker() { + public Entity getAttacker() { Damage.Source source = this.damage.getSource(); if (source instanceof Damage.EntitySource entitySource) { Player player = this.store.getComponent(entitySource.getRef(), Player.getComponentType()); - if (player != null) return new Entity[]{player}; + if (player != null) return player; NPCEntity npc = this.store.getComponent(entitySource.getRef(), NPCEntity.getComponentType()); - if (npc != null) return new Entity[]{npc}; + if (npc != null) return npc; } return null; } - public Float[] getDamage() { - return new Float[]{this.damage.getAmount()}; + public Float getDamage() { + return this.damage.getAmount(); } - public Damage.Source[] getDamageSource() { - return new Damage.Source[]{this.damage.getSource()}; + public Damage.Source getDamageSource() { + return this.damage.getSource(); } @SuppressWarnings("deprecation") - public DamageCause[] getDamageCause() { - return new DamageCause[]{this.damage.getCause()}; + public DamageCause getDamageCause() { + return this.damage.getCause(); } @Override diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/entity/EvtEntityPickupItem.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/entity/EvtEntityPickupItem.java index a8c85c76..3bea2f77 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/entity/EvtEntityPickupItem.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/entity/EvtEntityPickupItem.java @@ -35,8 +35,8 @@ public static void register(SkriptRegistration reg) { .setHandledContexts(PickupItemContext.class) .register(); - reg.addContextValue(PickupItemContext.class, Entity.class, true, "entity", PickupItemContext::getEntity); - reg.addContextValue(PickupItemContext.class, ItemStack.class, true, "item-stack", PickupItemContext::getItemStack); + reg.addSingleContextValue(PickupItemContext.class, Entity.class, "entity", PickupItemContext::getEntity); + reg.addSingleContextValue(PickupItemContext.class, ItemStack.class, "item-stack", PickupItemContext::getItemStack); } private static PickupItemSystem SYSTEM; @@ -68,16 +68,16 @@ public String toString(@NotNull TriggerContext ctx, boolean debug) { public record PickupItemContext(InteractivelyPickupItemEvent event, Entity entity, int pattern) implements PlayerContext, CancellableContext { - public Entity[] getEntity() { - return new Entity[]{this.entity}; + public Entity getEntity() { + return this.entity; } - public ItemStack[] getItemStack() { - return new ItemStack[]{this.event.getItemStack()}; + public ItemStack getItemStack() { + return this.event.getItemStack(); } - public Player[] getPlayer() { - if (this.entity instanceof Player p) return new Player[]{p}; + public Player getPlayer() { + if (this.entity instanceof Player p) return p; return null; } diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerAddToWorld.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerAddToWorld.java index 7ea6e2b5..0e980df2 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerAddToWorld.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerAddToWorld.java @@ -27,7 +27,7 @@ public static void register(SkriptRegistration reg) { .since("1.0.0") .register(); - reg.addContextValue(AddContext.class, World.class, true, "world", AddContext::getWorld); + reg.addSingleContextValue(AddContext.class, World.class, "world", AddContext::getWorld); } private static EventRegistration LISTENER; @@ -55,14 +55,14 @@ public String toString(TriggerContext ctx, boolean debug) { private record AddContext(AddPlayerToWorldEvent event) implements PlayerContext { - public World[] getWorld() { - return new World[]{this.event.getWorld()}; + public World getWorld() { + return this.event.getWorld(); } - public Player[] getPlayer() { + public Player getPlayer() { Holder holder = this.event.getHolder(); Player component = holder.getComponent(Player.getComponentType()); - return new Player[]{component}; + return component; } @Override diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerBreakBlock.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerBreakBlock.java index 8593c3a6..3b24bd9c 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerBreakBlock.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerBreakBlock.java @@ -40,11 +40,15 @@ public static void register(SkriptRegistration reg) { .setHandledContexts(BreakBlockEventContext.class) .register(); - reg.addContextValue(BreakBlockEventContext.class, Block.class, true, "block", BreakBlockEventContext::getBlock); - reg.addContextValue(BreakBlockEventContext.class, World.class, true, "world", BreakBlockEventContext::getWorld); - reg.addContextValue(BreakBlockEventContext.class, BlockType.class, true, "blocktype", BreakBlockEventContext::getBlockType); - reg.addContextValue(BreakBlockEventContext.class, Item.class, true, "item-in-hand", BreakBlockEventContext::getItemInHand); - reg.addContextValue(BreakBlockEventContext.class, ItemStack.class, true, "itemstack-in-hand", BreakBlockEventContext::getItemStackInHand); + reg.newSingleContextValue(BreakBlockEventContext.class, Block.class, "block", BreakBlockEventContext::getBlock) + .addSetter(BreakBlockEventContext::setTargetBlock).register(); + reg.addSingleContextValue(BreakBlockEventContext.class, World.class, "world", BreakBlockEventContext::getWorld); + reg.addSingleContextValue(BreakBlockEventContext.class, BlockType.class, "blocktype", BreakBlockEventContext::getBlockType); + reg.addSingleContextValue(BreakBlockEventContext.class, Item.class, "item-in-hand", BreakBlockEventContext::getItemInHand); + reg.addSingleContextValue(BreakBlockEventContext.class, World.class, "world", BreakBlockEventContext::getWorld); + reg.addSingleContextValue(BreakBlockEventContext.class, BlockType.class, "blocktype", BreakBlockEventContext::getBlockType); + reg.addSingleContextValue(BreakBlockEventContext.class, Item.class, "item-in-hand", BreakBlockEventContext::getItemInHand); + reg.addSingleContextValue(BreakBlockEventContext.class, ItemStack.class, "itemstack-in-hand", BreakBlockEventContext::getItemStackInHand); } private static BlockBreakEventSystem SYSTEM; @@ -69,38 +73,41 @@ public String toString(@NotNull TriggerContext ctx, boolean debug) { return "player block break"; } - private record BreakBlockEventContext(BreakBlockEvent event, - Player player) implements PlayerContext, CancellableContext { + private record BreakBlockEventContext(BreakBlockEvent event, Player player) + implements PlayerContext, CancellableContext { - public Player[] getPlayer() { - return new Player[]{this.player}; + public Player getPlayer() { + return this.player; } - private Block[] getBlock() { + private Block getBlock() { BlockType blockType = event.getBlockType(); Vector3i targetBlock = event.getTargetBlock(); World world = this.player.getWorld(); if (world == null || blockType == BlockType.EMPTY) return null; - Block block = new Block(world, targetBlock); - return new Block[]{block}; + return new Block(world, targetBlock); } - private World[] getWorld() { - return new World[]{this.player.getWorld()}; + private void setTargetBlock(Block targetBlock) { + this.event.setTargetBlock(targetBlock.getPos()); } - private BlockType[] getBlockType() { - return new BlockType[]{this.event.getBlockType()}; + private World getWorld() { + return this.player.getWorld(); } - private Item[] getItemInHand() { + private BlockType getBlockType() { + return this.event.getBlockType(); + } + + private Item getItemInHand() { ItemStack itemInHand = this.event.getItemInHand(); if (itemInHand == null) return null; - return new Item[]{itemInHand.getItem()}; + return itemInHand.getItem(); } - private ItemStack[] getItemStackInHand() { - return new ItemStack[]{this.event.getItemInHand()}; + private ItemStack getItemStackInHand() { + return this.event.getItemInHand(); } @Override diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerChat.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerChat.java index 1588a7d4..a1925b06 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerChat.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerChat.java @@ -4,6 +4,7 @@ import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; import com.github.skriptdev.skript.plugin.HySk; import com.hypixel.hytale.event.EventRegistration; +import com.hypixel.hytale.server.core.Message; import com.hypixel.hytale.server.core.event.events.player.PlayerChatEvent; import com.hypixel.hytale.server.core.universe.PlayerRef; import io.github.syst3ms.skriptparser.lang.Expression; @@ -17,8 +18,8 @@ public class EvtPlayerChat extends SkriptEvent { - public static void register(SkriptRegistration registration) { - registration.newEvent(EvtPlayerChat.class, "[player] chat") + public static void register(SkriptRegistration reg) { + reg.newEvent(EvtPlayerChat.class, "[player] chat") .setHandledContexts(PlayerChatContext.class) .name("Player Chat") .description("Event triggered when a player sends a message in chat.") @@ -29,12 +30,22 @@ public static void register(SkriptRegistration registration) { .since("1.0.0") .register(); - registration.addContextValue(PlayerChatContext.class, String.class, - true, "message", PlayerChatContext::getMessage); - registration.addContextValue(PlayerChatContext.class, PlayerRef.class, - true, "sender", PlayerChatContext::getSender); - registration.addContextValue(PlayerChatContext.class, PlayerRef.class, - true, "playerref", PlayerChatContext::getSender); + reg.newSingleContextValue(PlayerChatContext.class, String.class, + "message", PlayerChatContext::getMessage) + .addSetter(PlayerChatContext::setMessage) + .register(); + reg.newSingleContextValue(PlayerChatContext.class, Message.class, + "message-format", PlayerChatContext::getMessageFormat) + .addSetter(PlayerChatContext::setMessageFormat) + .register(); + reg.newSingleContextValue(PlayerChatContext.class, String.class, + "format", PlayerChatContext::getFormat) + .addSetter(PlayerChatContext::setFormat) + .register(); + reg.addSingleContextValue(PlayerChatContext.class, PlayerRef.class, + "sender", PlayerChatContext::getSender); + reg.addSingleContextValue(PlayerChatContext.class, PlayerRef.class, + "playerref", PlayerChatContext::getSender); } private static EventRegistration LISTENER; @@ -72,12 +83,46 @@ public PlayerChatEvent getEvent() { return this.event; } - public String[] getMessage() { - return new String[]{this.event.getContent()}; + public String getMessage() { + return this.event.getContent(); + } + + public void setMessage(String message) { + this.event.setContent(message); + } + + public String getFormat() { + PlayerChatEvent.Formatter formatter = this.event.getFormatter(); + Message format = formatter.format(this.event.getSender(), this.event.getContent()); + return format.toString(); + } + + public Message getMessageFormat() { + PlayerChatEvent.Formatter formatter = this.event.getFormatter(); + return formatter.format(this.event.getSender(), this.event.getContent()); + } + + public void setFormat(String format) { + this.event.setFormatter(new PlayerChatEvent.Formatter() { + @Override + public @NotNull Message format(@NotNull PlayerRef playerRef, @NotNull String s) { + return Message.raw(format).param("message", s).param("player", Message.raw(playerRef.getUsername())); + } + }); + } + + public void setMessageFormat(Message format) { + this.event.setFormatter(new PlayerChatEvent.Formatter() { + @Override + public @NotNull Message format(@NotNull PlayerRef playerRef, @NotNull String s) { + Message insert = Message.empty().insert(format); // Clone what is passed thru + return insert.param("message", s).param("player", Message.raw(playerRef.getUsername())); + } + }); } - public PlayerRef[] getSender() { - return new PlayerRef[]{this.event.getSender()}; + public PlayerRef getSender() { + return this.event.getSender(); } @Override diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerDamageBlock.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerDamageBlock.java index aebad12d..29dd7d66 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerDamageBlock.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerDamageBlock.java @@ -36,11 +36,11 @@ public static void register(SkriptRegistration reg) { .since("1.0.0") .register(); - reg.addContextValue(DamageBlockContext.class, Block.class, true, "block", DamageBlockContext::getBlock); - reg.addContextValue(DamageBlockContext.class, BlockType.class, true, "blocktype", DamageBlockContext::getBlockType); - reg.addContextValue(DamageBlockContext.class, ItemStack.class, true, "itemstack-in-hand", DamageBlockContext::getItemStackInHand); - reg.addContextValue(DamageBlockContext.class, Number.class, true, "damage", DamageBlockContext::getDamage); - reg.addContextValue(DamageBlockContext.class, Number.class, true, "current-damage", DamageBlockContext::getCurrentDamage); + reg.addSingleContextValue(DamageBlockContext.class, Block.class, "block", DamageBlockContext::getBlock); + reg.addSingleContextValue(DamageBlockContext.class, BlockType.class, "blocktype", DamageBlockContext::getBlockType); + reg.addSingleContextValue(DamageBlockContext.class, ItemStack.class, "itemstack-in-hand", DamageBlockContext::getItemStackInHand); + reg.addSingleContextValue(DamageBlockContext.class, Number.class, "damage", DamageBlockContext::getDamage); + reg.addSingleContextValue(DamageBlockContext.class, Number.class, "current-damage", DamageBlockContext::getCurrentDamage); } private static DamageBlockSystem SYSTEM; @@ -68,31 +68,31 @@ public record DamageBlockContext(DamageBlockEvent event, Player player) implements PlayerContext, CancellableContext { @Override - public Player[] getPlayer() { - return new Player[]{this.player}; + public Player getPlayer() { + return this.player; } - public ItemStack[] getItemStackInHand() { - return new ItemStack[]{this.event.getItemInHand()}; + public ItemStack getItemStackInHand() { + return this.event.getItemInHand(); } - public Block[] getBlock() { + public Block getBlock() { Vector3i targetBlock = this.event.getTargetBlock(); World world = this.player.getWorld(); if (world == null) return null; - return new Block[]{new Block(world, targetBlock)}; + return new Block(world, targetBlock); } - public BlockType[] getBlockType() { - return new BlockType[]{this.event.getBlockType()}; + public BlockType getBlockType() { + return this.event.getBlockType(); } - public Number[] getDamage() { - return new Number[]{this.event.getDamage()}; + public Number getDamage() { + return this.event.getDamage(); } - public Number[] getCurrentDamage() { - return new Number[]{this.event.getCurrentDamage()}; + public Number getCurrentDamage() { + return this.event.getCurrentDamage(); } @Override diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerDropItem.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerDropItem.java index 528a018b..33f47049 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerDropItem.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerDropItem.java @@ -37,9 +37,9 @@ public static void register(SkriptRegistration reg) { .since("1.0.0") .register(); - reg.addContextValue(DropItemContext.class, Float.class, true, "throw-speed", DropItemContext::getThrowSpeed); - reg.addContextValue(DropItemContext.class, Item.class, true, "dropped-item", DropItemContext::getItem); - reg.addContextValue(DropItemContext.class, ItemStack.class, true, "dropped-itemstack", DropItemContext::getItemStack); + reg.addSingleContextValue(DropItemContext.class, Float.class, "throw-speed", DropItemContext::getThrowSpeed); + reg.addSingleContextValue(DropItemContext.class, Item.class, "dropped-item", DropItemContext::getItem); + reg.addSingleContextValue(DropItemContext.class, ItemStack.class, "dropped-itemstack", DropItemContext::getItemStack); } private static PlayerDropItemSystem SYSTEM; @@ -65,20 +65,20 @@ public String toString(@NotNull TriggerContext ctx, boolean debug) { private record DropItemContext(Player player, Drop drop) implements PlayerContext, CancellableContext { - public Player[] getPlayer() { - return new Player[]{this.player}; + public Player getPlayer() { + return this.player; } - public Float[] getThrowSpeed() { - return new Float[]{this.drop.getThrowSpeed()}; + public Float getThrowSpeed() { + return this.drop.getThrowSpeed(); } - public Item[] getItem() { - return new Item[]{this.drop.getItemStack().getItem()}; + public Item getItem() { + return this.drop.getItemStack().getItem(); } - public ItemStack[] getItemStack() { - return new ItemStack[]{this.drop.getItemStack()}; + public ItemStack getItemStack() { + return this.drop.getItemStack(); } @Override diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerDropItemRequest.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerDropItemRequest.java index 4c4be00a..b836a5bd 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerDropItemRequest.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerDropItemRequest.java @@ -38,10 +38,10 @@ public static void register(SkriptRegistration reg) { .since("1.0.0") .register(); - reg.addContextValue(RequestDropItemContext.class, Integer.class, true, "slot-id", RequestDropItemContext::getSlotId); - reg.addContextValue(RequestDropItemContext.class, Integer.class, true, "inventory-section-id", RequestDropItemContext::getInventorySectionId); - reg.addContextValue(RequestDropItemContext.class, Item.class, true, "item", RequestDropItemContext::getItem); - reg.addContextValue(RequestDropItemContext.class, ItemStack.class, true, "itemstack", RequestDropItemContext::getItemStack); + reg.addSingleContextValue(RequestDropItemContext.class, Integer.class, "slot-id", RequestDropItemContext::getSlotId); + reg.addSingleContextValue(RequestDropItemContext.class, Integer.class, "inventory-section-id", RequestDropItemContext::getInventorySectionId); + reg.addSingleContextValue(RequestDropItemContext.class, Item.class, "item", RequestDropItemContext::getItem); + reg.addSingleContextValue(RequestDropItemContext.class, ItemStack.class, "itemstack", RequestDropItemContext::getItemStack); } private static PlayerRequestSystem SYSTEM; @@ -68,33 +68,32 @@ public String toString(@NotNull TriggerContext ctx, boolean debug) { private record RequestDropItemContext(Player player, DropItemEvent.PlayerRequest request) implements PlayerContext, CancellableContext { - public Player[] getPlayer() { - return new Player[]{this.player}; + public Player getPlayer() { + return this.player; } - public Integer[] getSlotId() { - return new Integer[]{(int) this.request.getSlotId()}; + public int getSlotId() { + return (int) this.request.getSlotId(); } - public Integer[] getInventorySectionId() { - return new Integer[]{(int) this.request.getInventorySectionId()}; + public int getInventorySectionId() { + return this.request.getInventorySectionId(); } - public Item[] getItem() { + public Item getItem() { Inventory inventory = this.player.getInventory(); ItemContainer container = inventory.getSectionById(this.request.getInventorySectionId()); if (container == null) return null; ItemStack itemStack = container.getItemStack(this.request.getSlotId()); if (itemStack == null) return null; - Item item = itemStack.getItem(); - return new Item[]{item}; + return itemStack.getItem(); } - public ItemStack[] getItemStack() { + public ItemStack getItemStack() { Inventory inventory = this.player.getInventory(); ItemContainer container = inventory.getSectionById(this.request.getInventorySectionId()); if (container == null) return null; - return new ItemStack[]{container.getItemStack(this.request.getSlotId())}; + return container.getItemStack(this.request.getSlotId()); } @Override diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerJoin.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerJoin.java index a3bc6a2f..ea4c61d1 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerJoin.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerJoin.java @@ -89,8 +89,8 @@ public PlayerEventContext(Player player, int pattern) { this.pattern = pattern; } - public Player[] getPlayer() { - return new Player[]{this.player}; + public Player getPlayer() { + return this.player; } public int getPattern() { diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerMouseClick.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerMouseClick.java index 2e586870..2fbdc0f2 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerMouseClick.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerMouseClick.java @@ -32,11 +32,11 @@ public static void register(SkriptRegistration reg) { .setHandledContexts(MouseClickContext.class) .register(); - reg.addContextValue(MouseClickContext.class, Item.class, true, "item", MouseClickContext::getItemInHand); - reg.addContextValue(MouseClickContext.class, Entity.class, true, "target-entity", MouseClickContext::getTargetEntity); - reg.addContextValue(MouseClickContext.class, Vector3i.class, true, "target-block", MouseClickContext::getTargetBlock); - reg.addContextValue(MouseClickContext.class, Vector2f.class, true, "screen-point", MouseClickContext::getScreenPoint); - reg.addContextValue(MouseClickContext.class, MouseButtonEvent.class, true, "mouse-button", MouseClickContext::getMouseButton); + reg.addSingleContextValue(MouseClickContext.class, Item.class, "item", MouseClickContext::getItemInHand); + reg.addSingleContextValue(MouseClickContext.class, Entity.class, "target-entity", MouseClickContext::getTargetEntity); + reg.addSingleContextValue(MouseClickContext.class, Vector3i.class, "target-block", MouseClickContext::getTargetBlock); + reg.addSingleContextValue(MouseClickContext.class, Vector2f.class, "screen-point", MouseClickContext::getScreenPoint); + reg.addSingleContextValue(MouseClickContext.class, MouseButtonEvent.class, "mouse-button", MouseClickContext::getMouseButton); } private static EventRegistration LISTENER; @@ -66,28 +66,28 @@ public String toString(@NotNull TriggerContext ctx, boolean debug) { private record MouseClickContext(PlayerMouseButtonEvent event) implements PlayerContext, CancellableContext { - public Player[] getPlayer() { - return new Player[]{this.event.getPlayer()}; + public Player getPlayer() { + return this.event.getPlayer(); } - private Item[] getItemInHand() { - return new Item[]{this.event.getItemInHand()}; + private Item getItemInHand() { + return this.event.getItemInHand(); } - private Entity[] getTargetEntity() { - return new Entity[]{this.event.getTargetEntity()}; + private Entity getTargetEntity() { + return this.event.getTargetEntity(); } - private Vector3i[] getTargetBlock() { - return new Vector3i[]{this.event.getTargetBlock()}; + private Vector3i getTargetBlock() { + return this.event.getTargetBlock(); } - private Vector2f[] getScreenPoint() { - return new Vector2f[]{this.event.getScreenPoint()}; + private Vector2f getScreenPoint() { + return this.event.getScreenPoint(); } - private MouseButtonEvent[] getMouseButton() { - return new MouseButtonEvent[]{this.event.getMouseButton()}; + private MouseButtonEvent getMouseButton() { + return this.event.getMouseButton(); } @Override diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerMouseMove.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerMouseMove.java index ab6d234c..52bb6f0b 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerMouseMove.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerMouseMove.java @@ -30,11 +30,11 @@ public static void register(SkriptRegistration reg) { .setHandledContexts(MouseMoveContext.class) .register(); - reg.addContextValue(MouseMoveContext.class, Item.class, true, "item", MouseMoveContext::getItemInHand); - reg.addContextValue(MouseMoveContext.class, Entity.class, true, "target-entity", MouseMoveContext::getTargetEntity); - reg.addContextValue(MouseMoveContext.class, Vector3i.class, true, "target-block", MouseMoveContext::getTargetBlock); - reg.addContextValue(MouseMoveContext.class, Vector2f.class, true, "screen-point", MouseMoveContext::getScreenPoint); - reg.addContextValue(MouseMoveContext.class, MouseMotionEvent.class, true, "mouse-motion", MouseMoveContext::getMouseMotion); + reg.addSingleContextValue(MouseMoveContext.class, Item.class, "item", MouseMoveContext::getItemInHand); + reg.addSingleContextValue(MouseMoveContext.class, Entity.class, "target-entity", MouseMoveContext::getTargetEntity); + reg.addSingleContextValue(MouseMoveContext.class, Vector3i.class, "target-block", MouseMoveContext::getTargetBlock); + reg.addSingleContextValue(MouseMoveContext.class, Vector2f.class, "screen-point", MouseMoveContext::getScreenPoint); + reg.addSingleContextValue(MouseMoveContext.class, MouseMotionEvent.class, "mouse-motion", MouseMoveContext::getMouseMotion); } private static EventRegistration LISTENER; @@ -62,28 +62,28 @@ public String toString(@NotNull TriggerContext ctx, boolean debug) { private record MouseMoveContext(PlayerMouseMotionEvent event) implements PlayerContext, CancellableContext { - public Player[] getPlayer() { - return new Player[]{this.event.getPlayer()}; + public Player getPlayer() { + return this.event.getPlayer(); } - private Item[] getItemInHand() { - return new Item[]{this.event.getItemInHand()}; + private Item getItemInHand() { + return this.event.getItemInHand(); } - private Entity[] getTargetEntity() { - return new Entity[]{this.event.getTargetEntity()}; + private Entity getTargetEntity() { + return this.event.getTargetEntity(); } - private Vector3i[] getTargetBlock() { - return new Vector3i[]{this.event.getTargetBlock()}; + private Vector3i getTargetBlock() { + return this.event.getTargetBlock(); } - private Vector2f[] getScreenPoint() { - return new Vector2f[]{this.event.getScreenPoint()}; + private Vector2f getScreenPoint() { + return this.event.getScreenPoint(); } - private MouseMotionEvent[] getMouseMotion() { - return new MouseMotionEvent[]{this.event.getMouseMotion()}; + private MouseMotionEvent getMouseMotion() { + return this.event.getMouseMotion(); } @Override diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerPlaceBlock.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerPlaceBlock.java index 0ac5571b..430ef4ac 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerPlaceBlock.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerPlaceBlock.java @@ -44,10 +44,10 @@ public static void register(SkriptRegistration reg) { .setHandledContexts(PlaceBlockContext.class) .register(); - reg.addContextValue(PlaceBlockContext.class, Item.class, true, "item-in-hand", PlaceBlockContext::getItemInHand); - reg.addContextValue(PlaceBlockContext.class, ItemStack.class, true, "itemstack-in-hand", PlaceBlockContext::getItemStackInHand); - reg.addContextValue(PlaceBlockContext.class, BlockType.class, true, "blocktype", PlaceBlockContext::getPlacedBlockType); - reg.newContextValue(PlaceBlockContext.class, BlockType.class, true, "blocktype", PlaceBlockContext::getPreviousBlockType) + reg.addSingleContextValue(PlaceBlockContext.class, Item.class, "item-in-hand", PlaceBlockContext::getItemInHand); + reg.addSingleContextValue(PlaceBlockContext.class, ItemStack.class, "itemstack-in-hand", PlaceBlockContext::getItemStackInHand); + reg.addSingleContextValue(PlaceBlockContext.class, BlockType.class, "blocktype", PlaceBlockContext::getPlacedBlockType); + reg.newSingleContextValue(PlaceBlockContext.class, BlockType.class, "blocktype", PlaceBlockContext::getPreviousBlockType) .setState(ContextValue.State.PAST) .register(); } @@ -76,40 +76,38 @@ public String toString(@NotNull TriggerContext ctx, boolean debug) { public record PlaceBlockContext(PlaceBlockEvent event, Player player) implements PlayerContext, BlockContext, CancellableContext { - public Player[] getPlayer() { - return new Player[]{this.player}; + public Player getPlayer() { + return this.player; } - public Item[] getItemInHand() { + public Item getItemInHand() { ItemStack itemInHand = this.event.getItemInHand(); if (itemInHand == null) return null; - return new Item[]{itemInHand.getItem()}; + return itemInHand.getItem(); } - public ItemStack[] getItemStackInHand() { - return new ItemStack[]{this.event.getItemInHand()}; + public ItemStack getItemStackInHand() { + return this.event.getItemInHand(); } - public BlockType[] getPreviousBlockType() { - Block[] block = getBlock(); + public BlockType getPreviousBlockType() { + Block block = getBlock(); if (block == null) return null; - Block block1 = block[0]; - if (block1 == null) return null; - return new BlockType[]{block1.getType()}; + return block.getType(); } - public BlockType[] getPlacedBlockType() { + public BlockType getPlacedBlockType() { ItemStack itemInHand = this.event.getItemInHand(); if (itemInHand == null) return null; - return new BlockType[]{AssetStoreUtils.getBlockType(itemInHand.getItem())}; + return AssetStoreUtils.getBlockType(itemInHand.getItem()); } @Override - public Block[] getBlock() { + public Block getBlock() { Vector3i targetBlock = this.event.getTargetBlock(); World world = this.player.getWorld(); if (world == null) return null; - return new Block[]{new Block(world, targetBlock)}; + return new Block(world, targetBlock); } @Override diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerUseBlock.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerUseBlock.java index 9c5f6b01..83781610 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerUseBlock.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerUseBlock.java @@ -42,9 +42,9 @@ public static void register(SkriptRegistration reg) { .since("1.0.0") .register(); - reg.addContextValue(UseBlockContext.class, BlockType.class, true, "blocktype", UseBlockContext::getBlockType); - reg.addContextValue(UseBlockContext.class, Block.class, true, "block", UseBlockContext::getBlock); - reg.addContextValue(UseBlockContext.class, InteractionType.class, true, "interaction-type", UseBlockContext::getInteractionType); + reg.addSingleContextValue(UseBlockContext.class, BlockType.class, "blocktype", UseBlockContext::getBlockType); + reg.addSingleContextValue(UseBlockContext.class, Block.class, "block", UseBlockContext::getBlock); + reg.addSingleContextValue(UseBlockContext.class, InteractionType.class, "interaction-type", UseBlockContext::getInteractionType); } private static PreUseBlockSystem PRE_SYSTEM; @@ -88,22 +88,22 @@ public UseBlockContext(T event, Player player) { } @Override - public Player[] getPlayer() { - return new Player[]{this.player}; + public Player getPlayer() { + return this.player; } - public BlockType[] getBlockType() { - return new BlockType[]{this.event.getBlockType()}; + public BlockType getBlockType() { + return this.event.getBlockType(); } - public InteractionType[] getInteractionType() { - return new InteractionType[]{this.event.getInteractionType()}; + public InteractionType getInteractionType() { + return this.event.getInteractionType(); } - public Block[] getBlock() { + public Block getBlock() { World world = this.player.getWorld(); if (world == null) return null; - return new Block[]{new Block(world, this.event.getTargetBlock())}; + return new Block(world, this.event.getTargetBlock()); } } diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/player/ExprChatMessage.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/player/ExprChatMessage.java index eeaaf2ad..a8819abe 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/player/ExprChatMessage.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/player/ExprChatMessage.java @@ -34,7 +34,7 @@ public boolean init(Expression @NotNull [] expressions, int matchedPattern, @ @Override public String[] getValues(@NotNull TriggerContext ctx) { if (ctx instanceof PlayerChatContext chat) { - return chat.getMessage(); + return new String[]{chat.getMessage()}; } return null; } diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/sections/SecDropItem.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/sections/SecDropItem.java index 809ad682..cf9c8a2c 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/sections/SecDropItem.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/sections/SecDropItem.java @@ -43,8 +43,8 @@ public static void register(SkriptRegistration reg) { .since("1.0.0") .register(); - reg.addContextValue(ItemComponentContext.class, ItemComponent.class, true, "item-component", ItemComponentContext::getItemComponent); - reg.addContextValue(ItemComponentContext.class, Entity.class, true, "item-entity", ItemComponentContext::getEntity); + reg.addSingleContextValue(ItemComponentContext.class, ItemComponent.class, "item-component", ItemComponentContext::getItemComponent); + reg.addSingleContextValue(ItemComponentContext.class, Entity.class, "item-entity", ItemComponentContext::getEntity); } private Expression items; @@ -156,12 +156,12 @@ public ItemComponentContext(@Nullable Entity entity, ItemComponent component) { this.component = component; } - public ItemComponent[] getItemComponent() { - return new ItemComponent[]{this.component}; + public ItemComponent getItemComponent() { + return this.component; } - public Entity[] getEntity() { - return new Entity[]{this.entity}; + public @Nullable Entity getEntity() { + return this.entity; } @Override diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesWorld.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesWorld.java index 612f9aa2..877143e7 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesWorld.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesWorld.java @@ -5,10 +5,17 @@ import com.hypixel.hytale.protocol.SoundCategory; import com.hypixel.hytale.server.core.universe.world.World; import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk; +import com.hypixel.hytale.server.worldgen.zone.Zone; public class TypesWorld { static void register(SkriptRegistration reg) { + reg.newType(WorldChunk.class, "chunk", "chunk@s") + .name("Chunk") + .description("Represents a chunk in a world. A chunk is a 32x32x(world height) set of blocks.") + .since("1.0.0") + .toStringFunction(worldChunk -> "chunk (x=" + worldChunk.getX() + ",z=" + worldChunk.getZ() + ") in world '" + worldChunk.getWorld().getName() + "'") + .register(); EnumRegistry.register(reg, SoundCategory.class, "soundcategory", "soundcategor@y@ies") .name("Sound Category") .description("Represents a sound category.") @@ -20,11 +27,11 @@ static void register(SkriptRegistration reg) { .since("1.0.0") .toStringFunction(World::getName) .register(); - reg.newType(WorldChunk.class, "chunk", "chunk@s") - .name("Chunk") - .description("Represents a chunk in a world. A chunk is a 32x32x(world height) set of blocks.") - .since("1.0.0") - .toStringFunction(worldChunk -> "chunk (x=" + worldChunk.getX() + ",z=" + worldChunk.getZ() + ") in world '" + worldChunk.getWorld().getName() + "'") + reg.newType(Zone.class, "zone", "zone@s") + .name("Zone") + .description("Represents a zone in the game.") + .since("INSERT VERSION") + .toStringFunction(zone -> String.format("Zone{id=%s, name=%s}", zone.id(), zone.name())) .register(); } From 2c4aeb5049440d04e37e7425e28854ef714d480f Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Tue, 3 Feb 2026 09:32:16 -0800 Subject: [PATCH 27/29] EvtPlayerChat - update docs --- .../elements/events/player/EvtPlayerChat.java | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerChat.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerChat.java index a1925b06..b8c15eaf 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerChat.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerChat.java @@ -22,11 +22,17 @@ public static void register(SkriptRegistration reg) { reg.newEvent(EvtPlayerChat.class, "[player] chat") .setHandledContexts(PlayerChatContext.class) .name("Player Chat") - .description("Event triggered when a player sends a message in chat.") + .description("Event triggered when a player sends a message in chat.", + "The message can be changed by setting `context-message`.", + "The message format can be changed by setting `context-message-format` (to a Message) or `context-format` (to a String).") .examples("on player chat:", "\tif name of context-sender = \"bob\":", "\t\tcancel event", - "\t\tsend \"You said: %message% and we cancelled that!!!\" to context-sender") + "\t\tsend \"You said: %message% and we cancelled that!!!\" to context-sender", + "", + "on player chat:", + "\tset {_message} to formatted message from \"[MyServer] %name of context-playerref%: %context-message%\"", + "\tset context-message-format to {_message}") .since("1.0.0") .register(); @@ -106,7 +112,10 @@ public void setFormat(String format) { this.event.setFormatter(new PlayerChatEvent.Formatter() { @Override public @NotNull Message format(@NotNull PlayerRef playerRef, @NotNull String s) { - return Message.raw(format).param("message", s).param("player", Message.raw(playerRef.getUsername())); + return Message.raw(format) + .param("message", s) + .param("player", playerRef.getUsername()) + .param("username", playerRef.getUsername()); } }); } @@ -115,8 +124,10 @@ public void setMessageFormat(Message format) { this.event.setFormatter(new PlayerChatEvent.Formatter() { @Override public @NotNull Message format(@NotNull PlayerRef playerRef, @NotNull String s) { - Message insert = Message.empty().insert(format); // Clone what is passed thru - return insert.param("message", s).param("player", Message.raw(playerRef.getUsername())); + return format + .param("message", s) + .param("player", playerRef.getUsername()) + .param("username", playerRef.getUsername()); } }); } From 957b23bf6ed2f0947e1c07d1d99a09101a3bc923 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Tue, 3 Feb 2026 13:25:10 -0800 Subject: [PATCH 28/29] JsonVariableStorage - fix legacy file loading - when an empty file was created, it still gave the outdated format warning and created a bak file --- .../skript/variables/JsonVariableStorage.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/github/skriptdev/skript/api/skript/variables/JsonVariableStorage.java b/src/main/java/com/github/skriptdev/skript/api/skript/variables/JsonVariableStorage.java index ece2a049..093f9f65 100644 --- a/src/main/java/com/github/skriptdev/skript/api/skript/variables/JsonVariableStorage.java +++ b/src/main/java/com/github/skriptdev/skript/api/skript/variables/JsonVariableStorage.java @@ -119,11 +119,17 @@ private void loadVariablesFromFile() { if (this.bsonDocument.containsKey("variables")) { variablesDocument = this.bsonDocument.getDocument("variables"); } else { - // Legacy file format (TODO remove before first release) - this.logger.warn("Your variables file is outdated. HySkript will create a backup then convert for you."); - Files.move(this.file.toPath(), this.file.toPath().resolveSibling(this.file.getName() + ".bak")); - variablesDocument = this.bsonDocument.clone(); - this.bsonDocument = new BsonDocument(); + if (!this.bsonDocument.isEmpty() && !this.bsonDocument.containsKey("data")) { + // Legacy file format (TODO remove before first release) + this.logger.warn("Your variables file is outdated. HySkript will create a backup then convert for you."); + Files.move(this.file.toPath(), this.file.toPath().resolveSibling(this.file.getName() + ".bak")); + variablesDocument = this.bsonDocument.clone(); + this.bsonDocument.clear(); + this.bsonDocument.put("variables", variablesDocument); + } else { + variablesDocument = this.bsonDocument.getDocument("variables", new BsonDocument()); + } + //this.bsonDocument = new BsonDocument(); } JsonElement jsonElement = BsonUtil.translateBsonToJson(variablesDocument); if (jsonElement instanceof JsonObject jsonObject) { From 5ce340e36eacbd0f1c840847debf63247a55f026 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Tue, 3 Feb 2026 13:34:02 -0800 Subject: [PATCH 29/29] build.gradle.kts - update parser --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 6e33f7a1..86ebaf04 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -25,7 +25,7 @@ repositories { dependencies { compileOnly("com.hypixel.hytale:Server:${hytaleVersion}") compileOnly("org.jetbrains:annotations:26.0.2") - implementation("com.github.SkriptDev:skript-parser:dev~patch-SNAPSHOT") { // TODO change before release + implementation("com.github.SkriptDev:skript-parser:1.0.3") { isTransitive = false } implementation("com.github.Zoltus:TinyMessage:2.0.1") {