From 79dbb391d6f123f7bb0e358bc380347e03146138 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Thu, 5 Feb 2026 10:26:26 -0800 Subject: [PATCH 01/61] ScriptsLoader - ensure directories are loaded first --- .../skriptdev/skript/api/skript/ScriptsLoader.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/github/skriptdev/skript/api/skript/ScriptsLoader.java b/src/main/java/com/github/skriptdev/skript/api/skript/ScriptsLoader.java index 5428cdb5..c012c9dc 100644 --- a/src/main/java/com/github/skriptdev/skript/api/skript/ScriptsLoader.java +++ b/src/main/java/com/github/skriptdev/skript/api/skript/ScriptsLoader.java @@ -10,6 +10,8 @@ import java.io.File; import java.nio.file.Path; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; import java.util.List; public class ScriptsLoader { @@ -51,7 +53,14 @@ public List loadScriptsInDirectory(IMessageReceiver receiver, File direc if (directory == null || !directory.isDirectory()) return List.of(); List loadedScripts = new ArrayList<>(); - for (File file : directory.listFiles()) { + File[] files = directory.listFiles(); + if (files == null) return loadedScripts; + + Arrays.sort(files, + Comparator.comparing(File::isDirectory).reversed() // Directories first + .thenComparing(File::getName, String.CASE_INSENSITIVE_ORDER)); // Then sort by name alphabetically + + for (File file : files) { if (file.isDirectory()) { loadedScripts.addAll(loadScriptsInDirectory(receiver, file)); } else { From 1061d32f6be85a69494bd6b980f52893d0084008 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Thu, 5 Feb 2026 10:27:29 -0800 Subject: [PATCH 02/61] SkriptCommand - change reload subcommand "all" to "scripts" --- .../github/skriptdev/skript/plugin/command/SkriptCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/github/skriptdev/skript/plugin/command/SkriptCommand.java b/src/main/java/com/github/skriptdev/skript/plugin/command/SkriptCommand.java index b38748aa..3f26f376 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/command/SkriptCommand.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/command/SkriptCommand.java @@ -56,7 +56,7 @@ private static class ReloadCommand extends AbstractCommand { protected ReloadCommand() { super("reload", "Reloads scripts."); this.stringRequiredArg = withRequiredArg("script", "A script to reload", ArgTypes.STRING); - addSubCommand(new AbstractCommand("all", "Reloads all scripts.") { + addSubCommand(new AbstractCommand("scripts", "Reloads all scripts.") { @Override protected CompletableFuture execute(@NotNull CommandContext commandContext) { return CompletableFuture.runAsync(() -> { From 2de22028deaf0f84b6ae905b8dcaa3bd47c322ad Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Thu, 5 Feb 2026 10:28:16 -0800 Subject: [PATCH 03/61] build.gradle.kts - switch skript-parser back to dev branch --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 2124b425..9ebac41e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -26,7 +26,7 @@ repositories { dependencies { compileOnly("com.hypixel.hytale:Server:${hytaleVersion}") compileOnly("org.jetbrains:annotations:26.0.2") - implementation("com.github.SkriptDev:skript-parser:1.0.4") { + implementation("com.github.SkriptDev:skript-parser:dev~patch-SNAPSHOT") { isTransitive = false } implementation("com.github.Zoltus:TinyMessage:2.0.1") { From 69f22cd54f64be2377bca0149792f7551e0f5494 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Thu, 5 Feb 2026 10:31:57 -0800 Subject: [PATCH 04/61] SkriptCommand - add some more aliases --- .../github/skriptdev/skript/plugin/command/SkriptCommand.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/github/skriptdev/skript/plugin/command/SkriptCommand.java b/src/main/java/com/github/skriptdev/skript/plugin/command/SkriptCommand.java index 3f26f376..d6ffa182 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/command/SkriptCommand.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/command/SkriptCommand.java @@ -37,8 +37,8 @@ public class SkriptCommand extends AbstractCommandCollection { * @hidden */ public SkriptCommand(CommandRegistry registry) { - super("skript", "Skript commands"); - addAliases("sk"); + super("skript", "HySkript commands"); + addAliases("sk", "hyskript", "hysk"); // Keep these in alphabetical order addSubCommand(addonsCommand()); From 31b1ea467f2634b5b167cd6beabcd98035ea263c Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Thu, 5 Feb 2026 10:46:20 -0800 Subject: [PATCH 05/61] EnumRegistry - fix value map names and parsing --- .../skriptdev/skript/api/skript/registration/EnumRegistry.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/github/skriptdev/skript/api/skript/registration/EnumRegistry.java b/src/main/java/com/github/skriptdev/skript/api/skript/registration/EnumRegistry.java index bc1dcd22..45da70fe 100644 --- a/src/main/java/com/github/skriptdev/skript/api/skript/registration/EnumRegistry.java +++ b/src/main/java/com/github/skriptdev/skript/api/skript/registration/EnumRegistry.java @@ -36,7 +36,7 @@ public static > TypeRegistrar register(SkriptRegistration r } EnumRegistry eEnumRegistry = new EnumRegistry<>(); for (T e : enumClass.getEnumConstants()) { - eEnumRegistry.values.put(e.name(), e); + eEnumRegistry.values.put(e.name().toLowerCase(Locale.ROOT), e); } return registration.newType(enumClass, name, pattern) .usage(String.join(", ", eEnumRegistry.values.keySet())) From 6616492bba42c66f2db8cc4fd17c9d1fb41c0bc4 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Thu, 5 Feb 2026 10:55:53 -0800 Subject: [PATCH 06/61] ExprGameMode - small changes and fix threading issue --- .../expressions/player/ExprGameMode.java | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/player/ExprGameMode.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/player/ExprGameMode.java index 601f2c3c..bd709d83 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/player/ExprGameMode.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/player/ExprGameMode.java @@ -1,7 +1,10 @@ package com.github.skriptdev.skript.plugin.elements.expressions.player; +import com.hypixel.hytale.component.Ref; import com.hypixel.hytale.protocol.GameMode; import com.hypixel.hytale.server.core.entity.entities.Player; +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.TriggerContext; import io.github.syst3ms.skriptparser.lang.properties.PropertyExpression; import io.github.syst3ms.skriptparser.registration.SkriptRegistration; @@ -35,15 +38,27 @@ public Optional[]> acceptsChange(@NotNull ChangeMode mode) { @SuppressWarnings("ConstantConditions") @Override - public void change(@NotNull TriggerContext ctx, @NotNull ChangeMode changeMode, @NotNull Object[] changeWith) { + public void change(@NotNull TriggerContext ctx, @NotNull ChangeMode changeMode, Object @NotNull [] changeWith) { if (changeMode != ChangeMode.SET || changeWith == null) return; - GameMode newGameMode = changeWith[0] instanceof GameMode ? (GameMode) changeWith[0] : null; - if (newGameMode == null) return; - Optional owner = getOwner().getSingle(ctx); - if (!(owner.isPresent() && owner.get() instanceof Player player)) return; + GameMode newGameMode = changeWith[0] instanceof GameMode gm ? gm : null; + if (newGameMode == null) { + return; + } - Player.setGameMode(player.getReference(), newGameMode, player.getReference().getStore()); + for (Player player : getOwner().getArray(ctx)) { + if (player == null) continue; + + Ref ref = player.getReference(); + Runnable gamemodeRunnable = () -> Player.setGameMode(ref, newGameMode, ref.getStore()); + + World world = player.getWorld(); + if (world.isInThread()) { + gamemodeRunnable.run(); + } else { + world.execute(gamemodeRunnable); + } + } } @Override From c06d671374dc7e27b15ff28bb95434fd3c3e3c63 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Thu, 5 Feb 2026 11:00:40 -0800 Subject: [PATCH 07/61] ExprEntityHealth - fix threading issue --- .../expressions/entity/ExprEntityHealth.java | 61 +++++++++++-------- 1 file changed, 37 insertions(+), 24 deletions(-) diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/entity/ExprEntityHealth.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/entity/ExprEntityHealth.java index a1477ecb..c7f332ce 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/entity/ExprEntityHealth.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/entity/ExprEntityHealth.java @@ -6,6 +6,7 @@ import com.hypixel.hytale.server.core.modules.entitystats.EntityStatMap; import com.hypixel.hytale.server.core.modules.entitystats.EntityStatValue; import com.hypixel.hytale.server.core.modules.entitystats.asset.DefaultEntityStatTypes; +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.lang.properties.PropertyExpression; @@ -66,38 +67,50 @@ public Optional[]> acceptsChange(@NotNull ChangeMode mode) { public void change(@NotNull TriggerContext ctx, @NotNull ChangeMode changeMode, Object @NotNull [] changeWith) { Optional single = getOwner().getSingle(ctx); if (single.isEmpty()) return; - LivingEntity entity = single.get(); - EntityStatMap statMap = EntityComponentUtils.getEntityStatMap(entity); - if (statMap == null) return; + LivingEntity entity = single.get(); + World world = entity.getWorld(); + if (world == null) return; - if (changeMode == ChangeMode.RESET) { - statMap.resetStatValue(HEALTH_STAT_INDEX); - return; - } + Runnable healthRunnable = () -> { - float newValue; - if (changeWith.length > 0 && changeWith[0] instanceof Number number) { - newValue = number.floatValue(); - } else { - newValue = 0f; - } + EntityStatMap statMap = EntityComponentUtils.getEntityStatMap(entity); + if (statMap == null) return; - if (changeMode != ChangeMode.SET) { - EntityStatValue healthStat = statMap.get(HEALTH_STAT_INDEX); - if (healthStat == null) return; - float oldHealthValue = healthStat.get(); + if (changeMode == ChangeMode.RESET) { + statMap.resetStatValue(HEALTH_STAT_INDEX); + return; + } - if (changeMode == ChangeMode.ADD) { - newValue += oldHealthValue; - } else if (changeMode == ChangeMode.REMOVE) { - newValue = oldHealthValue - newValue; - } else if (changeMode == ChangeMode.DELETE) { + float newValue; + if (changeWith.length > 0 && changeWith[0] instanceof Number number) { + newValue = number.floatValue(); + } else { newValue = 0f; } - } - statMap.setStatValue(HEALTH_STAT_INDEX, newValue); + if (changeMode != ChangeMode.SET) { + EntityStatValue healthStat = statMap.get(HEALTH_STAT_INDEX); + if (healthStat == null) return; + float oldHealthValue = healthStat.get(); + + if (changeMode == ChangeMode.ADD) { + newValue += oldHealthValue; + } else if (changeMode == ChangeMode.REMOVE) { + newValue = oldHealthValue - newValue; + } else if (changeMode == ChangeMode.DELETE) { + newValue = 0f; + } + } + + statMap.setStatValue(HEALTH_STAT_INDEX, newValue); + }; + + if (world.isInThread()) { + healthRunnable.run(); + } else { + world.execute(healthRunnable); + } } } From b37bc4ae018cb9dd51da1088fc6d53b14ba41d48 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Thu, 5 Feb 2026 12:39:21 -0800 Subject: [PATCH 08/61] EffExplosion - add new effect --- .../elements/effects/EffectHandler.java | 2 + .../elements/effects/world/EffExplosion.java | 129 ++++++++++++++++++ 2 files changed, 131 insertions(+) create mode 100644 src/main/java/com/github/skriptdev/skript/plugin/elements/effects/world/EffExplosion.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 4d7e02f2..60198b3f 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 @@ -14,6 +14,7 @@ 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; +import com.github.skriptdev.skript.plugin.elements.effects.world.EffExplosion; public class EffectHandler { @@ -40,6 +41,7 @@ public static void register(SkriptRegistration registration) { // WORLD EffChunkRegenerate.register(registration); + EffExplosion.register(registration); } } diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/world/EffExplosion.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/world/EffExplosion.java new file mode 100644 index 00000000..92105ead --- /dev/null +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/world/EffExplosion.java @@ -0,0 +1,129 @@ +package com.github.skriptdev.skript.plugin.elements.effects.world; + +import com.github.skriptdev.skript.api.hytale.StoreUtils; +import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; +import com.hypixel.hytale.component.CommandBuffer; +import com.hypixel.hytale.component.Store; +import com.hypixel.hytale.math.vector.Location; +import com.hypixel.hytale.server.core.entity.ExplosionConfig; +import com.hypixel.hytale.server.core.entity.ExplosionUtils; +import com.hypixel.hytale.server.core.modules.entity.damage.Damage; +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.ChunkStore; +import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; +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; + +import java.util.Optional; + +public class EffExplosion extends Effect { + + public static void register(SkriptRegistration reg) { + reg.newEffect(EffExplosion.class, + "create explosion at %locations%", + "create explosion with radius %number% at %locations%", + "\"create explosion with block radius %number% [and] with entity radius %number% at %locations%\"") + .name("Explosion") + .description("Creates an explosion at the specified location(s) with " + + "customizable block and entity damage radii.") + .experimental("This doesn't work as I expected it to (Needs some love!).") + .since("INSERT VERSION") + .register(); + } + + private int pattern; + private Expression locations; + private Expression blockRadius; + private Expression entityRadius; + + @SuppressWarnings("unchecked") + @Override + public boolean init(Expression[] expressions, int matchedPattern, @NotNull ParseContext parseContext) { + this.pattern = matchedPattern; + this.locations = (Expression) expressions[matchedPattern]; + if (matchedPattern == 1) { + this.blockRadius = (Expression) expressions[0]; + } else if (matchedPattern == 2) { + this.blockRadius = (Expression) expressions[0]; + this.entityRadius = (Expression) expressions[1]; + } + return true; + } + + @Override + protected void execute(@NotNull TriggerContext ctx) { + Number blockRadius = 3.0f; + Number entityRadius = 5.0f; + if (this.blockRadius != null) { + Optional single = this.blockRadius.getSingle(ctx); + if (single.isPresent()) { + blockRadius = single.get(); + + // If no entity radius is provided, we just add 2 to the bock radius + // This will be fixed below if an entity radius IS provided + entityRadius = blockRadius.floatValue() + 2.0f; + } + } + + if (this.entityRadius != null) { + Optional single = this.entityRadius.getSingle(ctx); + if (single.isPresent()) { + entityRadius = single.get(); + } + } + + Config config = new Config(blockRadius, entityRadius); + + for (Location location : this.locations.getArray(ctx)) { + String worldName = location.getWorld(); + if (worldName == null) continue; + + World world = Universe.get().getWorld(worldName); + if (world == null) continue; + + Runnable worldRunnable = () -> { + Store entityStore = world.getEntityStore().getStore(); + Store chunkStoreStore = world.getChunkStore().getStore(); + CommandBuffer commandBuffer = StoreUtils.getCommandBuffer(entityStore); + + ExplosionUtils.performExplosion(Damage.NULL_SOURCE, + location.getPosition(), + config, + null, + commandBuffer, + chunkStoreStore); + }; + + if (world.isInThread()) { + worldRunnable.run(); + } else { + world.execute(worldRunnable); + } + } + } + + @Override + public String toString(@NotNull TriggerContext ctx, boolean debug) { + return switch (this.pattern) { + case 1 -> + "create explosion with radius " + this.blockRadius.toString(ctx, debug) + " at " + this.locations.toString(ctx, debug); + case 2 -> + "create explosion with block radius " + this.blockRadius.toString(ctx, debug) + " and entity radius " + + this.entityRadius.toString(ctx, debug) + " at " + this.locations.toString(ctx, debug); + default -> "create explosion at " + this.locations.toString(ctx, debug); + }; + } + + private static class Config extends ExplosionConfig { + + private Config(Number blockRadius, Number entityRadius) { + this.blockDamageRadius = blockRadius.intValue(); + this.entityDamageRadius = entityRadius.floatValue(); + } + } + +} From 17d0313e8a2b4775c3b26ce642fd8937db3ef9de Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Thu, 5 Feb 2026 12:40:38 -0800 Subject: [PATCH 09/61] StoreUtils - add method to get command buffer - its reflect because its a private method --- .../skript/api/hytale/StoreUtils.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/main/java/com/github/skriptdev/skript/api/hytale/StoreUtils.java diff --git a/src/main/java/com/github/skriptdev/skript/api/hytale/StoreUtils.java b/src/main/java/com/github/skriptdev/skript/api/hytale/StoreUtils.java new file mode 100644 index 00000000..6481ded3 --- /dev/null +++ b/src/main/java/com/github/skriptdev/skript/api/hytale/StoreUtils.java @@ -0,0 +1,22 @@ +package com.github.skriptdev.skript.api.hytale; + +import com.hypixel.hytale.component.CommandBuffer; +import com.hypixel.hytale.component.Store; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +public class StoreUtils { + + @SuppressWarnings("unchecked") + public static CommandBuffer getCommandBuffer(Store store) { + try { + Method method = store.getClass().getDeclaredMethod("takeCommandBuffer"); + method.setAccessible(true); + return (CommandBuffer) method.invoke(store); + } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { + throw new RuntimeException(e); + } + } + +} From 1ad54e757042398b4a77a65b40193360865e713d Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Thu, 5 Feb 2026 12:48:16 -0800 Subject: [PATCH 10/61] checkstyle.xml - more line length changes --- config/checkstyle/checkstyle.xml | 2 +- .../skript/command/ScriptCommandBuilder.java | 3 ++- .../api/skript/docs/MarkdownDocPrinter.java | 6 +++-- .../skript/variables/JsonVariableStorage.java | 6 +++-- .../skriptdev/skript/api/utils/Utils.java | 3 ++- .../events/player/EvtPlayerBreakBlock.java | 24 ++++++++++++------- .../player/EvtPlayerChangeGameMode.java | 6 +++-- .../elements/events/player/EvtPlayerChat.java | 3 ++- .../player/EvtPlayerDropItemRequest.java | 12 ++++++---- .../entityeffect/ExprActiveEntityEffects.java | 3 ++- .../plugin/elements/sections/SecDropItem.java | 6 +++-- .../elements/sections/SecPlaySound.java | 6 +++-- 12 files changed, 53 insertions(+), 27 deletions(-) diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml index 83c6b26c..e2897427 100644 --- a/config/checkstyle/checkstyle.xml +++ b/config/checkstyle/checkstyle.xml @@ -5,7 +5,7 @@ - + diff --git a/src/main/java/com/github/skriptdev/skript/api/skript/command/ScriptCommandBuilder.java b/src/main/java/com/github/skriptdev/skript/api/skript/command/ScriptCommandBuilder.java index 6369b7fb..81ba7f56 100644 --- a/src/main/java/com/github/skriptdev/skript/api/skript/command/ScriptCommandBuilder.java +++ b/src/main/java/com/github/skriptdev/skript/api/skript/command/ScriptCommandBuilder.java @@ -147,7 +147,8 @@ protected void execute(@NotNull CommandContext commandContext, @NotNull World wo CommandSender sender = commandContext.sender(); Player player = null; if (sender instanceof Player p) player = p; - ScriptCommandContext context = new ScriptCommandContext(ScriptCommandBuilder.this.commandName, sender, player, null); + ScriptCommandContext context = new ScriptCommandContext(ScriptCommandBuilder.this.commandName, + sender, player, null); createLocalVariables(commandContext, context); Statement.runAll(trigger, context); 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 53e5b18b..0c2ba3f3 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 @@ -172,7 +172,8 @@ private static void printStructures(PrintWriter writer, SkriptRegistration regis }); } - private static void printExpressions(PrintWriter exprWriter, PrintWriter condWriter, PrintWriter exprEffWriter, SkriptRegistration registration) { + private static void printExpressions(PrintWriter exprWriter, PrintWriter condWriter, + PrintWriter exprEffWriter, SkriptRegistration registration) { List>> values = new ArrayList<>(registration.getExpressions().values()); values.sort(Comparator.comparing(k -> k.getFirst().getSyntaxClass().getSimpleName())); @@ -299,7 +300,8 @@ private static void printDocumentation(String type, PrintWriter writer, Document // Asset store stuff gets really long, so plop them on another page // GitHub's wiki pages seem to have a limit Utils.log("Creating asset store link for: " + documentation.getName()); - writer.println("[Click Here](https://github.com/SkriptDev/HySkript/wiki/_usage-" + documentation.getName().replace(" ", "-") + ")"); + writer.println("[Click Here](https://github.com/SkriptDev/HySkript/wiki/_usage-" + + documentation.getName().replace(" ", "-") + ")"); File usageFile = getFile("_usage-" + documentation.getName()); try { List values = new ArrayList<>(); 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 0798ae98..fbbf1afd 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 @@ -298,12 +298,14 @@ protected Object deserialize(String varName, @NotNull String typeName, @NotNull } io.github.syst3ms.skriptparser.types.Type type = TypeManager.getByExactName(typeName).orElse(null); if (type == null) { - Utils.error("Variable '%s' with type '%s' cannot be deserialized. No type registered. This variable will be removed.", varName, typeName); + Utils.error("Variable '%s' with type '%s' cannot be deserialized. No type registered. " + + "This variable will be removed.", varName, typeName); return null; } TypeSerializer serializer = type.getSerializer().orElse(null); if (serializer == null) { - Utils.error("Variable '%s' cannot be deserialized. The type '%s' has no serializer. This variable will be removed.", varName, typeName); + Utils.error("Variable '%s' cannot be deserialized. The type '%s' has no serializer. " + + "This variable will be removed.", varName, typeName); return null; } return serializer.deserialize(this.gson, value); diff --git a/src/main/java/com/github/skriptdev/skript/api/utils/Utils.java b/src/main/java/com/github/skriptdev/skript/api/utils/Utils.java index 54584b25..1a402090 100644 --- a/src/main/java/com/github/skriptdev/skript/api/utils/Utils.java +++ b/src/main/java/com/github/skriptdev/skript/api/utils/Utils.java @@ -44,7 +44,8 @@ public static void log(IMessageReceiver receiver, Level level, String message, O if (receiver == null) { HySk.getInstance().getLogger().at(level).log(message); } else { - Color color = level == Level.SEVERE ? Color.RED : level == Level.WARNING ? Color.YELLOW : level == Level.FINE ? Color.PINK : Color.WHITE; + Color color = level == Level.SEVERE ? Color.RED : level == Level.WARNING ? + Color.YELLOW : level == Level.FINE ? Color.PINK : Color.WHITE; Message coloredMessage = Message.raw(message).color(color); Message m = Message.empty().insert(CORE_PREFIX).insert(coloredMessage); 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 3b24bd9c..66c5d874 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,15 +40,23 @@ public static void register(SkriptRegistration reg) { .setHandledContexts(BreakBlockEventContext.class) .register(); - reg.newSingleContextValue(BreakBlockEventContext.class, Block.class, "block", BreakBlockEventContext::getBlock) + 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); + 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; diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerChangeGameMode.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerChangeGameMode.java index 5b7c1921..85a3e5cd 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerChangeGameMode.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerChangeGameMode.java @@ -33,11 +33,13 @@ public static void register(SkriptRegistration reg) { .since("1.0.0") .register(); - reg.newSingleContextValue(PlayerChangeGameModeContext.class, GameMode.class, "game[(-| )]mode", PlayerChangeGameModeContext::getOldGameMode) + reg.newSingleContextValue(PlayerChangeGameModeContext.class, GameMode.class, + "game[(-| )]mode", PlayerChangeGameModeContext::getOldGameMode) .setState(ContextValue.State.PAST) .setUsage(ContextValue.Usage.EXPRESSION_OR_ALONE) .register(); - reg.newSingleContextValue(PlayerChangeGameModeContext.class, GameMode.class, "game[(-| )]mode", PlayerChangeGameModeContext::getNewGameMode) + reg.newSingleContextValue(PlayerChangeGameModeContext.class, GameMode.class, + "game[(-| )]mode", PlayerChangeGameModeContext::getNewGameMode) .setState(ContextValue.State.PRESENT) .setUsage(ContextValue.Usage.EXPRESSION_OR_ALONE) .addSetter(PlayerChangeGameModeContext::setNewGameMode) 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 b8c15eaf..a4b09aeb 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 @@ -31,7 +31,8 @@ public static void register(SkriptRegistration reg) { "\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 {_message} to formatted message from \"[MyServer]" + + " %name of context-playerref%: %context-message%\"", "\tset context-message-format to {_message}") .since("1.0.0") .register(); 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 b836a5bd..23466b3d 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,14 @@ public static void register(SkriptRegistration reg) { .since("1.0.0") .register(); - 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); + 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; diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/entityeffect/ExprActiveEntityEffects.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/entityeffect/ExprActiveEntityEffects.java index 3ed3a382..84f3a249 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/entityeffect/ExprActiveEntityEffects.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/entityeffect/ExprActiveEntityEffects.java @@ -83,7 +83,8 @@ public void change(@NotNull TriggerContext ctx, @NotNull ChangeMode changeMode, if (reference == null) continue; Store store = reference.getStore(); - EffectControllerComponent component = EntityComponentUtils.getComponent(livingEntity, EffectControllerComponent.getComponentType()); + EffectControllerComponent component = EntityComponentUtils.getComponent(livingEntity, + EffectControllerComponent.getComponentType()); if (component == null) continue; if (changeMode == ChangeMode.DELETE) { 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 d347853d..eb688517 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 @@ -44,8 +44,10 @@ public static void register(SkriptRegistration reg) { .since("1.0.0") .register(); - reg.addSingleContextValue(ItemComponentContext.class, ItemComponent.class, "item-component", ItemComponentContext::getItemComponent); - reg.addSingleContextValue(ItemComponentContext.class, Entity.class, "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; 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 index f6e42aea..634852fe 100644 --- 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 @@ -106,14 +106,16 @@ public void playSoundToPlayer(@NotNull PlayerRef[] players, @Nullable Location l if (reference == null || !reference.isValid()) continue; Store store = reference.getStore(); - SoundUtil.playSoundEvent3dToPlayer(reference, soundEvent, category, pos.getX(), pos.getY(), pos.getZ(), volume, pitch, store); + 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) { + public void playSoundAtLocation(@NotNull Location location, int soundEvent, SoundCategory category, + boolean is3d, float volume, float pitch) { String worldName = location.getWorld(); if (worldName == null) return; From 6a9c91a20a6abc9f8ead15be84d14d81d9bb20ee Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Thu, 5 Feb 2026 13:33:21 -0800 Subject: [PATCH 11/61] EvtPlayerCraftRecipe - add recipe event - seems broken tho, server issue?!?! --- .../plugin/elements/events/EventHandler.java | 2 + .../events/player/EvtPlayerCraftRecipe.java | 185 ++++++++++++++++++ 2 files changed, 187 insertions(+) create mode 100644 src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerCraftRecipe.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 a04346eb..8ea9ba77 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 @@ -15,6 +15,7 @@ import com.github.skriptdev.skript.plugin.elements.events.player.EvtPlayerBreakBlock; import com.github.skriptdev.skript.plugin.elements.events.player.EvtPlayerChangeGameMode; import com.github.skriptdev.skript.plugin.elements.events.player.EvtPlayerChat; +import com.github.skriptdev.skript.plugin.elements.events.player.EvtPlayerCraftRecipe; import com.github.skriptdev.skript.plugin.elements.events.player.EvtPlayerDamageBlock; import com.github.skriptdev.skript.plugin.elements.events.player.EvtPlayerDrainFromWorld; import com.github.skriptdev.skript.plugin.elements.events.player.EvtPlayerDropItem; @@ -48,6 +49,7 @@ public static void register(SkriptRegistration registration) { EvtPlayerBreakBlock.register(registration); EvtPlayerChangeGameMode.register(registration); EvtPlayerChat.register(registration); + EvtPlayerCraftRecipe.register(registration); EvtPlayerDamageBlock.register(registration); EvtPlayerDrainFromWorld.register(registration); EvtPlayerDropItem.register(registration); diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerCraftRecipe.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerCraftRecipe.java new file mode 100644 index 00000000..f4762499 --- /dev/null +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerCraftRecipe.java @@ -0,0 +1,185 @@ +package com.github.skriptdev.skript.plugin.elements.events.player; + +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.github.skriptdev.skript.api.utils.Utils; +import com.github.skriptdev.skript.plugin.HySk; +import com.hypixel.hytale.component.ArchetypeChunk; +import com.hypixel.hytale.component.CommandBuffer; +import com.hypixel.hytale.component.ComponentRegistryProxy; +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.asset.type.item.config.CraftingRecipe; +import com.hypixel.hytale.server.core.entity.entities.Player; +import com.hypixel.hytale.server.core.event.events.ecs.CraftRecipeEvent; +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 org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class EvtPlayerCraftRecipe extends SystemEvent> { + + public static void register(SkriptRegistration reg) { + reg.newEvent(EvtPlayerCraftRecipe.class, + "player craft recipe", + "pre player craft recipe", + "post player craft recipe") + .setHandledContexts(CraftRecipeContext.class) + .name("Player Craft Recipe") + .experimental("These events don't seem to be called right now, server issues?!?!") + .description("Called when a player crafts a recipe.") + .examples("on player craft recipe:", + "\tif context-recipe-id = \"Salvage_Rock_Lime_Cobble\":", + "\t\tcancel event") + .since("INSERT VERSION") + .register(); + + reg.addSingleContextValue(CraftRecipeContext.class, int.class, + "quantity", CraftRecipeContext::getQuantity); + reg.addSingleContextValue(CraftRecipeContext.class, CraftingRecipe.class, + "recipe", CraftRecipeContext::getRecipe); + reg.addSingleContextValue(CraftRecipeContext.class, String.class, + "recipe-id", CraftRecipeContext::getRecipeId); + } + + static final ComponentRegistryProxy REGISTRY = HySk.getInstance().getEntityStoreRegistry(); + private static PreCraftRecipeSystem PRE_SYSTEM; + private static PostCraftRecipeSystem POST_SYSTEM; + private int pattern; + + @Override + public boolean init(Expression[] expressions, int matchedPattern, ParseContext parseContext) { + this.pattern = matchedPattern; + Utils.warn("init recipe event"); + if (PRE_SYSTEM == null) { + PRE_SYSTEM = new PreCraftRecipeSystem(); + REGISTRY.registerSystem(PRE_SYSTEM); + Utils.warn("pre Crafting system"); + } + if (POST_SYSTEM == null) { + POST_SYSTEM = new PostCraftRecipeSystem(); + REGISTRY.registerSystem(POST_SYSTEM); + Utils.warn("post Crafting system"); + } + return true; + } + + @Override + public boolean check(TriggerContext ctx) { + if (ctx instanceof CraftRecipeContext craftRecipeContext) { + if (this.pattern == 0) return true; + else if (this.pattern == 1) return craftRecipeContext.getPattern() == 0; + else if (this.pattern == 2) return craftRecipeContext.getPattern() == 1; + } + return false; + } + + @Override + public String toString(@NotNull TriggerContext ctx, boolean debug) { + return "player craft recipe"; + } + + public record CraftRecipeContext(CraftRecipeEvent event, + Player player) implements PlayerContext, CancellableContext { + private int getPattern() { + if (this.event instanceof CraftRecipeEvent.Post) { + return 1; + } + return 0; + } + + @Override + public Player getPlayer() { + return this.player; + } + + private int getQuantity() { + return this.event.getQuantity(); + } + + private CraftingRecipe getRecipe() { + return this.event.getCraftedRecipe(); + } + + private String getRecipeId() { + return this.event.getCraftedRecipe().getId(); + } + + @Override + public boolean isCancelled() { + return this.event.isCancelled(); + } + + @Override + public void setCancelled(boolean cancelled) { + this.event.setCancelled(cancelled); + } + + @Override + public String getName() { + return "craft-recipe-context"; + } + } + + public static class PreCraftRecipeSystem extends EntityEventSystem { + + protected PreCraftRecipeSystem() { + super(CraftRecipeEvent.Pre.class); + } + + @Override + public void handle(int i, @NotNull ArchetypeChunk archetypeChunk, + @NotNull Store store, @NotNull CommandBuffer commandBuffer, + @NotNull CraftRecipeEvent.Pre event) { + + Utils.log("pre Crafting recipe has been called"); + + Ref ref = archetypeChunk.getReferenceTo(i); + Player player = store.getComponent(ref, Player.getComponentType()); + if (player == null) return; + + CraftRecipeContext context = new CraftRecipeContext(event, player); + TriggerMap.callTriggersByContext(context); + } + + @Override + public @Nullable Query getQuery() { + return Player.getComponentType(); + } + } + + public static class PostCraftRecipeSystem extends EntityEventSystem { + + protected PostCraftRecipeSystem() { + super(CraftRecipeEvent.Post.class); + } + + @Override + public void handle(int i, @NotNull ArchetypeChunk archetypeChunk, + @NotNull Store store, @NotNull CommandBuffer commandBuffer, + @NotNull CraftRecipeEvent.Post event) { + + Utils.log("post Crafting recipe has been called"); + + Ref ref = archetypeChunk.getReferenceTo(i); + Player player = store.getComponent(ref, Player.getComponentType()); + if (player == null) return; + + CraftRecipeContext context = new CraftRecipeContext(event, player); + TriggerMap.callTriggersByContext(context); + } + + @Override + public @Nullable Query getQuery() { + return Player.getComponentType(); + } + } + +} From f6b6b83f7b491523352eb2b0aca2251721a64c36 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Thu, 5 Feb 2026 13:34:03 -0800 Subject: [PATCH 12/61] EvtPlayerCraftRecipe - remove debugs --- .../elements/events/player/EvtPlayerCraftRecipe.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerCraftRecipe.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerCraftRecipe.java index f4762499..411d9aa2 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerCraftRecipe.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerCraftRecipe.java @@ -57,16 +57,13 @@ public static void register(SkriptRegistration reg) { @Override public boolean init(Expression[] expressions, int matchedPattern, ParseContext parseContext) { this.pattern = matchedPattern; - Utils.warn("init recipe event"); if (PRE_SYSTEM == null) { PRE_SYSTEM = new PreCraftRecipeSystem(); REGISTRY.registerSystem(PRE_SYSTEM); - Utils.warn("pre Crafting system"); } if (POST_SYSTEM == null) { POST_SYSTEM = new PostCraftRecipeSystem(); REGISTRY.registerSystem(POST_SYSTEM); - Utils.warn("post Crafting system"); } return true; } @@ -139,8 +136,6 @@ public void handle(int i, @NotNull ArchetypeChunk archetypeChunk, @NotNull Store store, @NotNull CommandBuffer commandBuffer, @NotNull CraftRecipeEvent.Pre event) { - Utils.log("pre Crafting recipe has been called"); - Ref ref = archetypeChunk.getReferenceTo(i); Player player = store.getComponent(ref, Player.getComponentType()); if (player == null) return; @@ -166,8 +161,6 @@ public void handle(int i, @NotNull ArchetypeChunk archetypeChunk, @NotNull Store store, @NotNull CommandBuffer commandBuffer, @NotNull CraftRecipeEvent.Post event) { - Utils.log("post Crafting recipe has been called"); - Ref ref = archetypeChunk.getReferenceTo(i); Player player = store.getComponent(ref, Player.getComponentType()); if (player == null) return; From 1ad4e4baaa5950e333bd4162d3512dd2a12e92f3 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Thu, 5 Feb 2026 13:36:48 -0800 Subject: [PATCH 13/61] EvtPlayerCraftRecipe - remove unused import --- .../plugin/elements/events/player/EvtPlayerCraftRecipe.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerCraftRecipe.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerCraftRecipe.java index 411d9aa2..5528182c 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerCraftRecipe.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerCraftRecipe.java @@ -4,7 +4,6 @@ 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.github.skriptdev.skript.api.utils.Utils; import com.github.skriptdev.skript.plugin.HySk; import com.hypixel.hytale.component.ArchetypeChunk; import com.hypixel.hytale.component.CommandBuffer; From 52c48bcb82c41453758180081fd59c33bd181dbf Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Thu, 5 Feb 2026 14:10:47 -0800 Subject: [PATCH 14/61] EffExecuteCommand - add command effect --- .../elements/effects/EffectHandler.java | 2 + .../effects/other/EffExecuteCommand.java | 55 +++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 src/main/java/com/github/skriptdev/skript/plugin/elements/effects/other/EffExecuteCommand.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 60198b3f..d29be33e 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 @@ -6,6 +6,7 @@ import com.github.skriptdev.skript.plugin.elements.effects.entity.EffEntityEffect; 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.EffExecuteCommand; 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; @@ -33,6 +34,7 @@ public static void register(SkriptRegistration registration) { EffBroadcast.register(registration); EffCancelEvent.register(registration); EffDelay.register(registration); + EffExecuteCommand.register(registration); EffSendMessage.register(registration); // PLAYER diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/other/EffExecuteCommand.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/other/EffExecuteCommand.java new file mode 100644 index 00000000..79d8ebb0 --- /dev/null +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/other/EffExecuteCommand.java @@ -0,0 +1,55 @@ +package com.github.skriptdev.skript.plugin.elements.effects.other; + +import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; +import com.hypixel.hytale.server.core.command.system.CommandManager; +import com.hypixel.hytale.server.core.command.system.CommandSender; +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 EffExecuteCommand extends Effect { + + public static void register(SkriptRegistration reg) { + reg.newEffect(EffExecuteCommand.class, "execute %commandsenders% command %string%") + .name("Execute Command") + .description("Execute a command as a player or console.") + .examples("execute player command \"/inv clear\"", + "execute console command \"/stop\"") + .since("INSERT VERSION") + .register(); + } + + private Expression commandSenders; + private Expression command; + + @SuppressWarnings("unchecked") + @Override + public boolean init(Expression[] expressions, int matchedPattern, @NotNull ParseContext parseContext) { + this.commandSenders = (Expression) expressions[0]; + this.command = (Expression) expressions[1]; + return true; + } + + @Override + protected void execute(@NotNull TriggerContext ctx) { + String command = this.command.getSingle(ctx).orElse(null); + if (command == null) return; + + if (command.charAt(0) == '/') command = command.substring(1); + + CommandManager commandManager = CommandManager.get(); + for (CommandSender sender : commandSenders.getArray(ctx)) { + commandManager.handleCommand(sender, command); + } + } + + @Override + public String toString(@NotNull TriggerContext ctx, boolean debug) { + return String.format("execute %s command %s", + this.commandSenders.toString(ctx, debug), + this.command.toString(ctx, debug)); + } + +} From 5e3a74355df1d8fdad03a62a38b2623bbc693307 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Thu, 5 Feb 2026 15:16:27 -0800 Subject: [PATCH 15/61] Add somemore stuff --- .../elements/effects/EffectHandler.java | 2 + .../effects/other/EffExecuteCommand.java | 1 + .../elements/effects/player/EffConnect.java | 68 +++++++++++++++++++ .../events/entity/EvtEntityDeath.java | 63 ++++++++++++++++- 4 files changed, 131 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/github/skriptdev/skript/plugin/elements/effects/player/EffConnect.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 d29be33e..e23f5a2e 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 @@ -6,6 +6,7 @@ import com.github.skriptdev.skript.plugin.elements.effects.entity.EffEntityEffect; 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.player.EffConnect; import com.github.skriptdev.skript.plugin.elements.effects.other.EffExecuteCommand; import com.github.skriptdev.skript.plugin.elements.effects.other.EffSendMessage; import com.github.skriptdev.skript.plugin.elements.effects.entity.EffTeleport; @@ -39,6 +40,7 @@ public static void register(SkriptRegistration registration) { // PLAYER EffBan.register(registration); + EffConnect.register(registration); EffKick.register(registration); // WORLD diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/other/EffExecuteCommand.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/other/EffExecuteCommand.java index 79d8ebb0..c0c79fd1 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/other/EffExecuteCommand.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/other/EffExecuteCommand.java @@ -43,6 +43,7 @@ protected void execute(@NotNull TriggerContext ctx) { for (CommandSender sender : commandSenders.getArray(ctx)) { commandManager.handleCommand(sender, command); } + } @Override diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/player/EffConnect.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/player/EffConnect.java new file mode 100644 index 00000000..751bf838 --- /dev/null +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/player/EffConnect.java @@ -0,0 +1,68 @@ +package com.github.skriptdev.skript.plugin.elements.effects.player; + +import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; +import com.hypixel.hytale.server.core.entity.entities.Player; +import com.hypixel.hytale.server.core.universe.PlayerRef; +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 EffConnect extends Effect { + + public static void register(SkriptRegistration reg) { + reg.newEffect(EffConnect.class, "(connect|transfer|refer) %players/playerrefs% to %string%", + "(connect|transfer|refer) %players/playerrefs% to %string% on port %number%") + .name("Connect") + .description("Connects the specified players to another server.", + "If port is excluded, it defaults to `5520` (Hytale's default port).", + "See [PLAYER REFERRAL](https://support.hytale.com/hc/en-us/articles/45326769420827-Hytale-Server-" + + "Manual#multiserver-architecture) for more info.") + .examples("connect all players to \"https://someserver.net\"") + .register(); + } + + private Expression players; + private Expression address; + private Expression port; + + @SuppressWarnings("unchecked") + @Override + public boolean init(Expression[] expressions, int matchedPattern, @NotNull ParseContext parseContext) { + this.players = expressions[0]; + this.address = (Expression) expressions[1]; + if (matchedPattern == 1) { + this.port = (Expression) expressions[2]; + } + return true; + } + + @SuppressWarnings("removal") // Player#getPlayerRef (replacement?) + @Override + protected void execute(@NotNull TriggerContext ctx) { + String address = this.address.getSingle(ctx).orElse(null); + if (address == null) return; + + int port = 5520; + if (this.port != null) { + Number number = this.port.getSingle(ctx).orElse(null); + if (number != null) port = number.intValue(); + } + + for (Object o : this.players.getArray(ctx)) { + if (o instanceof PlayerRef playerRef) { + playerRef.referToServer(address, port); + } else if (o instanceof Player player) { + player.getPlayerRef().referToServer(address, port); + } + } + } + + @Override + public String toString(@NotNull TriggerContext ctx, boolean debug) { + String port = this.port != null ? " on port " + this.port.toString(ctx, debug) : ""; + return "connect " + this.players.toString(ctx, debug) + " to " + this.address.toString(ctx, debug) + port; + } + +} diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/entity/EvtEntityDeath.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/entity/EvtEntityDeath.java index 316b09a5..e0cfddb0 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/entity/EvtEntityDeath.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/entity/EvtEntityDeath.java @@ -6,6 +6,7 @@ import com.hypixel.hytale.component.Ref; import com.hypixel.hytale.component.Store; import com.hypixel.hytale.component.query.Query; +import com.hypixel.hytale.server.core.Message; import com.hypixel.hytale.server.core.asset.type.item.config.Item; import com.hypixel.hytale.server.core.entity.Entity; import com.hypixel.hytale.server.core.entity.entities.Player; @@ -15,16 +16,19 @@ import com.hypixel.hytale.server.core.modules.entity.damage.DeathComponent; import com.hypixel.hytale.server.core.modules.entity.damage.DeathSystems; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; +import com.hypixel.hytale.server.core.util.MessageUtil; 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.lang.event.SkriptEvent; 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; import java.util.Arrays; +import java.util.List; public class EvtEntityDeath extends SkriptEvent { @@ -57,8 +61,26 @@ public static void register(SkriptRegistration reg) { Damage.class, "death-info", EntityDeathContext::getDamage); reg.addListContextValue(EntityDeathContext.class, Item.class, "lost-items", EntityDeathContext::getItemsLostOnDeath); - reg.addListContextValue(EntityDeathContext.class, - ItemStack.class, "lost-itemstacks", EntityDeathContext::getItemStacksLostOnDeath); + reg.newListContextValue(EntityDeathContext.class, + ItemStack.class, "lost-itemstacks", EntityDeathContext::getItemStacksLostOnDeath) + .setUsage(ContextValue.Usage.EXPRESSION_OR_ALONE) + .addListSetter(EntityDeathContext::setItemStacksLostOnDeath) + .register(); + reg.newSingleContextValue(EntityDeathContext.class, + Boolean.class, "show-death-menu", EntityDeathContext::isShowDeathMenu) + .setUsage(ContextValue.Usage.EXPRESSION_OR_ALONE) + .addSetter(EntityDeathContext::setShowDeathMenu) + .register(); + reg.newSingleContextValue(EntityDeathContext.class, + Message.class, "death-message", EntityDeathContext::getDeathMessage) + .setUsage(ContextValue.Usage.EXPRESSION_OR_ALONE) + .addSetter(EntityDeathContext::setDeathMessage) + .register(); + reg.newSingleContextValue(EntityDeathContext.class, + String.class, "death-message-string", EntityDeathContext::getDeathMessageString) + .setUsage(ContextValue.Usage.EXPRESSION_OR_ALONE) + .addSetter(EntityDeathContext::setDeathMessageString) + .register(); } private static EntityDeathListener LISTENER; @@ -107,7 +129,9 @@ public void onComponentAdded(@NotNull Ref ref, @NotNull DeathCompon } else if (npc != null) { pattern = 2; victim = npc; - } else return; + } else { + return; + } TriggerMap.callTriggersByContext(new EntityDeathContext(pattern, victim, deathComponent)); } @@ -161,6 +185,39 @@ public ItemStack[] getItemStacksLostOnDeath() { return this.component.getItemsLostOnDeath(); } + public void setItemStacksLostOnDeath(ItemStack[] itemStacks) { + this.component.setItemsLostOnDeath(List.of(itemStacks)); + } + + public boolean isShowDeathMenu() { + return this.component.isShowDeathMenu(); + } + + public void setShowDeathMenu(boolean showDeathMenu) { + // this.component.setShowDeathMenu(showDeathMenu); (doesn't seem to work) + // So let's respawn instead + if (!showDeathMenu && this.getVictim() instanceof Player player) { + Ref reference = player.getReference(); + DeathComponent.respawn(reference.getStore(), reference); + } + } + + public Message getDeathMessage() { + return this.component.getDeathMessage(); + } + + public void setDeathMessage(Message deathMessage) { + this.component.setDeathMessage(deathMessage); + } + + public String getDeathMessageString() { + return MessageUtil.toAnsiString(this.component.getDeathMessage()).toAnsi(); + } + + public void setDeathMessageString(String deathMessage) { + this.component.setDeathMessage(Message.raw(deathMessage)); + } + @Override public String getName() { return "entity-death-context"; From e28688dad9881c6bdfd3cebc3c652d938efbadb2 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Thu, 5 Feb 2026 16:57:11 -0800 Subject: [PATCH 16/61] Add some shutdown logic --- .../github/skriptdev/skript/api/skript/ScriptsLoader.java | 5 ++++- .../java/com/github/skriptdev/skript/plugin/Skript.java | 7 +++++++ .../skript/plugin/elements/events/EventHandler.java | 5 +++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/github/skriptdev/skript/api/skript/ScriptsLoader.java b/src/main/java/com/github/skriptdev/skript/api/skript/ScriptsLoader.java index c012c9dc..f690f608 100644 --- a/src/main/java/com/github/skriptdev/skript/api/skript/ScriptsLoader.java +++ b/src/main/java/com/github/skriptdev/skript/api/skript/ScriptsLoader.java @@ -48,7 +48,6 @@ public void loadScripts(IMessageReceiver receiver, Path directory, boolean reloa } } - @SuppressWarnings("DataFlowIssue") public List loadScriptsInDirectory(IMessageReceiver receiver, File directory) { if (directory == null || !directory.isDirectory()) return List.of(); List loadedScripts = new ArrayList<>(); @@ -115,4 +114,8 @@ public void reloadScript(IMessageReceiver receiver, String name) { } } + public void shutdown() { + // TODO clear triggers here + } + } diff --git a/src/main/java/com/github/skriptdev/skript/plugin/Skript.java b/src/main/java/com/github/skriptdev/skript/plugin/Skript.java index 1f18166a..203b5d00 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/Skript.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/Skript.java @@ -9,6 +9,7 @@ import com.github.skriptdev.skript.api.utils.Utils; import com.github.skriptdev.skript.plugin.command.EffectCommands; import com.github.skriptdev.skript.plugin.elements.ElementRegistration; +import com.github.skriptdev.skript.plugin.elements.events.EventHandler; import io.github.syst3ms.skriptparser.Parser; import io.github.syst3ms.skriptparser.config.Config; import io.github.syst3ms.skriptparser.config.Config.ConfigSection; @@ -130,6 +131,12 @@ private void preSetup() { } public void shutdown() { + // SHUTDOWN LISTENERS + EventHandler.shutdown(); + + // SHUTDOWN SCRIPTS + this.scriptsLoader.shutdown(); + // SHUTDOWN VARIABLES Utils.log("Saving variables..."); Variables.shutdown(); 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 8ea9ba77..e55023dc 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 @@ -73,6 +73,11 @@ public static void register(SkriptRegistration registration) { registerGlobalContexts(registration); } + public static void shutdown() { + // Shutdown any events that are running (such as a periodical) + // Nothing yet for now + } + private static void registerGlobalContexts(SkriptRegistration reg) { reg.newSingleContextValue(BlockContext.class, Block.class, "block", BlockContext::getBlock) From fc2a8a19ff03542e7120d73bca83e508449dd9f8 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Thu, 5 Feb 2026 17:37:04 -0800 Subject: [PATCH 17/61] EffExplosion - make it better --- .../elements/effects/world/EffExplosion.java | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/world/EffExplosion.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/world/EffExplosion.java index 92105ead..dfcbdb11 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/world/EffExplosion.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/world/EffExplosion.java @@ -5,9 +5,11 @@ import com.hypixel.hytale.component.CommandBuffer; import com.hypixel.hytale.component.Store; import com.hypixel.hytale.math.vector.Location; +import com.hypixel.hytale.server.core.asset.type.item.config.ItemTool; +import com.hypixel.hytale.server.core.asset.type.item.config.ItemToolSpec; import com.hypixel.hytale.server.core.entity.ExplosionConfig; import com.hypixel.hytale.server.core.entity.ExplosionUtils; -import com.hypixel.hytale.server.core.modules.entity.damage.Damage; +import com.hypixel.hytale.server.core.modules.interaction.interaction.config.client.ExplodeInteraction; 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.ChunkStore; @@ -30,7 +32,10 @@ public static void register(SkriptRegistration reg) { .name("Explosion") .description("Creates an explosion at the specified location(s) with " + "customizable block and entity damage radii.") - .experimental("This doesn't work as I expected it to (Needs some love!).") + .examples("create explosion at {location}", + "create explosion with radius 10 at {location}", + "create explosion with block radius 10 and with entity radius 15 at {location}") + .experimental("Currently no sound/particles.") .since("INSERT VERSION") .register(); } @@ -90,7 +95,7 @@ protected void execute(@NotNull TriggerContext ctx) { Store chunkStoreStore = world.getChunkStore().getStore(); CommandBuffer commandBuffer = StoreUtils.getCommandBuffer(entityStore); - ExplosionUtils.performExplosion(Damage.NULL_SOURCE, + ExplosionUtils.performExplosion(ExplodeInteraction.DAMAGE_SOURCE_EXPLOSION, location.getPosition(), config, null, @@ -123,6 +128,16 @@ private static class Config extends ExplosionConfig { private Config(Number blockRadius, Number entityRadius) { this.blockDamageRadius = blockRadius.intValue(); this.entityDamageRadius = entityRadius.floatValue(); + // The stuff you have to do to make things work in Hytale... + ItemToolSpec[] specs = new ItemToolSpec[]{ + new ItemToolSpec("SoftBlocks", 2, 1), + new ItemToolSpec("Soils", 2, 1), + new ItemToolSpec("Woods", 2, 1), + new ItemToolSpec("Rocks", 2, 1), + new ItemToolSpec("Benches", 2, 1), + new ItemToolSpec("VolcanicRocks", 0.001f, 1), + }; + this.itemTool = new ItemTool(specs, 1, null); } } From 791f6cd2902b9a2f3a16eece7a3769341034dd67 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Thu, 5 Feb 2026 19:38:42 -0800 Subject: [PATCH 18/61] Add some interaction stuff --- .../elements/effects/EffectHandler.java | 2 + .../effects/entity/EffInteraction.java | 138 ++++++++++++++++++ .../elements/types/TypesAssetStore.java | 7 + 3 files changed, 147 insertions(+) create mode 100644 src/main/java/com/github/skriptdev/skript/plugin/elements/effects/entity/EffInteraction.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 e23f5a2e..e2347246 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 @@ -17,6 +17,7 @@ import com.github.skriptdev.skript.plugin.elements.effects.player.EffKick; import com.github.skriptdev.skript.plugin.elements.effects.world.EffChunkRegenerate; import com.github.skriptdev.skript.plugin.elements.effects.world.EffExplosion; +import com.github.skriptdev.skript.plugin.elements.effects.entity.EffInteraction; public class EffectHandler { @@ -27,6 +28,7 @@ public static void register(SkriptRegistration registration) { // ENTITY EffDropItem.register(registration); EffEntityEffect.register(registration); + EffInteraction.register(registration); EffKill.register(registration); EffSpawnEntity.register(registration); EffTeleport.register(registration); diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/entity/EffInteraction.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/entity/EffInteraction.java new file mode 100644 index 00000000..fe028471 --- /dev/null +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/entity/EffInteraction.java @@ -0,0 +1,138 @@ +package com.github.skriptdev.skript.plugin.elements.effects.entity; + +import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; +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.vector.Location; +import com.hypixel.hytale.math.vector.Vector3i; +import com.hypixel.hytale.protocol.BlockPosition; +import com.hypixel.hytale.protocol.InteractionType; +import com.hypixel.hytale.server.core.entity.Entity; +import com.hypixel.hytale.server.core.entity.InteractionChain; +import com.hypixel.hytale.server.core.entity.InteractionContext; +import com.hypixel.hytale.server.core.entity.InteractionManager; +import com.hypixel.hytale.server.core.modules.interaction.InteractionModule; +import com.hypixel.hytale.server.core.modules.interaction.interaction.config.RootInteraction; +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.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; + +import java.util.Objects; + +public class EffInteraction extends Effect { + + public static void register(SkriptRegistration reg) { + reg.newEffect(EffInteraction.class, "perform [root] interaction %rootinteraction% on %entity%", + "perform [root] interaction %rootinteraction% on %entity% at %location%", + "perform %interactiontype% [root] interaction %rootinteraction% on %entity%", + "perform %interactiontype% [root] interaction %rootinteraction% on %entity% at %location%") + .name("Perform Interaction") + .description("Performs a root interaction on an entity.", + "If an InteractionType is not specified, the `primary` InteractionType will be performed.") + .examples("perform interaction Shovel_Dig on player") + .since("INSERT VERSION") + .register(); + } + + private Expression interactionType; + private Expression interaction; + private Expression entity; + private Expression location; + + @SuppressWarnings("unchecked") + @Override + public boolean init(Expression @NotNull [] expressions, int matchedPattern, @NotNull ParseContext parseContext) { + if (matchedPattern == 0) { + this.interaction = (Expression) expressions[0]; + this.entity = (Expression) expressions[1]; + } else if (matchedPattern == 1) { + this.interaction = (Expression) expressions[0]; + this.entity = (Expression) expressions[1]; + this.location = (Expression) expressions[2]; + } else if (matchedPattern == 2) { + this.interactionType = (Expression) expressions[0]; + this.interaction = (Expression) expressions[1]; + this.entity = (Expression) expressions[2]; + } else { + this.interactionType = (Expression) expressions[0]; + this.interaction = (Expression) expressions[1]; + this.entity = (Expression) expressions[2]; + this.location = (Expression) expressions[3]; + } + return true; + } + + @SuppressWarnings("removal") + @Override + protected void execute(@NotNull TriggerContext ctx) { + RootInteraction interaction = this.interaction.getSingle(ctx).orElse(null); + if (interaction == null) return; + + InteractionType type; + if (this.interactionType != null) { + InteractionType interactionType1 = this.interactionType.getSingle(ctx).orElse(null); + type = Objects.requireNonNullElse(interactionType1, InteractionType.Primary); + } else { + type = InteractionType.Primary; + } + + Entity entity = this.entity.getSingle(ctx).orElse(null); + if (entity == null) return; + + World world = entity.getWorld(); + if (world == null) return; + + BlockPosition blockPosition; + if (this.location != null) { + Location location = this.location.getSingle(ctx).orElse(null); + if (location != null) { + Vector3i position = location.getPosition().toVector3i(); + blockPosition = new BlockPosition(position.getX(), position.getY(), position.getZ()); + } else { + blockPosition = null; + } + } else { + blockPosition = null; + } + + Runnable worldRunnable = () -> { + Ref ref = entity.getReference(); + if (ref == null) return; + + Store store = world.getEntityStore().getStore(); + InteractionManager manager = store.getComponent(ref, InteractionModule.get().getInteractionManagerComponent()); + if (manager == null) return; + + InteractionContext context = InteractionContext.forInteraction(manager, ref, type, store); + InteractionChain chain; + if (blockPosition == null) { + Utils.warn("no position specified for interaction"); + chain = manager.initChain(type, context, interaction, true); + } else { + Utils.warn("interaction at position " + blockPosition); + chain = manager.initChain(type, context, interaction, entity.getNetworkId(), blockPosition, true); + } + manager.queueExecuteChain(chain); + }; + + // Ensure running on the correct thread + if (world.isInThread()) { + worldRunnable.run(); + } else { + world.execute(worldRunnable); + } + } + + @Override + public String toString(@NotNull TriggerContext ctx, boolean debug) { + String type = this.interactionType != null ? this.interactionType.toString(ctx, debug) + " " : ""; + return "perform " + type + "interaction " + this.interaction.toString(ctx, debug) + + " on " + this.entity.toString(ctx, debug); + } + +} diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesAssetStore.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesAssetStore.java index 0052ee4d..d7a45b2e 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesAssetStore.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesAssetStore.java @@ -22,6 +22,7 @@ import com.hypixel.hytale.server.core.modules.entity.damage.DamageCause; import com.hypixel.hytale.server.core.modules.entitystats.asset.EntityStatType; import com.hypixel.hytale.server.core.modules.interaction.interaction.config.Interaction; +import com.hypixel.hytale.server.core.modules.interaction.interaction.config.RootInteraction; import io.github.syst3ms.skriptparser.types.changers.TypeSerializer; import org.bson.BsonDocument; import org.bson.BsonValue; @@ -97,6 +98,12 @@ static void register(SkriptRegistration registration) { .since("1.0.0") .toStringFunction(Interaction::getId) .register(); + AssetStoreRegistry.register(registration, RootInteraction.class, RootInteraction.getAssetMap(), + "rootinteraction", "rootinteraction@s") + .name("Interaction - Root") + .description("Represents the types of root interactions that can be performed by entities.", autoGenMessage()) + .since("INSERT VERSION") + .register(); AssetStoreRegistry.register(registration, Item.class, Item.getAssetMap(), "item", "item@s") .name("Item") .description("Represents the types of items in the game.", autoGenMessage()) From 094b89f8e2238b71342590f01193bf305638141a Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Thu, 5 Feb 2026 20:10:31 -0800 Subject: [PATCH 19/61] EvtPlayerCraftRecipe - wrong return type --- .../plugin/elements/events/player/EvtPlayerCraftRecipe.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerCraftRecipe.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerCraftRecipe.java index 5528182c..659c5776 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerCraftRecipe.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerCraftRecipe.java @@ -40,7 +40,7 @@ public static void register(SkriptRegistration reg) { .since("INSERT VERSION") .register(); - reg.addSingleContextValue(CraftRecipeContext.class, int.class, + reg.addSingleContextValue(CraftRecipeContext.class, Integer.class, "quantity", CraftRecipeContext::getQuantity); reg.addSingleContextValue(CraftRecipeContext.class, CraftingRecipe.class, "recipe", CraftRecipeContext::getRecipe); From da179f94ba37a3ff85d9e6543a50060482ba66e7 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Thu, 5 Feb 2026 20:43:45 -0800 Subject: [PATCH 20/61] build.gradle.kts - fix publications... AGAIN! - i swear ive done this several times --- build.gradle.kts | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle.kts b/build.gradle.kts index 9ebac41e..ff2e2287 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -54,6 +54,7 @@ tasks { } shadowJar { archiveFileName = project.name + "-" + projectVersion + ".jar" + archiveClassifier.set("") relocate("io.github.syst3ms", "com.github.skriptdev.skript") relocate("fi.sulku.hytale", "com.github.skriptdev.skript.tinymessage") } From 77e6bd9cc0aa9543ec460bc108ffc5633adaf5cd Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Thu, 5 Feb 2026 20:50:47 -0800 Subject: [PATCH 21/61] HySkriptAddon - change setup to start, to match Hytale plugins - also good incase we end up using setup later --- .../github/skriptdev/skript/api/skript/addon/AddonLoader.java | 2 +- .../github/skriptdev/skript/api/skript/addon/HySkriptAddon.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/github/skriptdev/skript/api/skript/addon/AddonLoader.java b/src/main/java/com/github/skriptdev/skript/api/skript/addon/AddonLoader.java index c78f52c1..370f8722 100644 --- a/src/main/java/com/github/skriptdev/skript/api/skript/addon/AddonLoader.java +++ b/src/main/java/com/github/skriptdev/skript/api/skript/addon/AddonLoader.java @@ -90,7 +90,7 @@ private void loadAddon(File file) { } if (mainClassIntance instanceof HySkriptAddon addon) { addon.setManifest(manifest); - addon.setup(); + addon.start(); this.addonCount++; // Finalize registration and logging for (LogEntry logEntry : addon.getSkriptRegistration().register()) { diff --git a/src/main/java/com/github/skriptdev/skript/api/skript/addon/HySkriptAddon.java b/src/main/java/com/github/skriptdev/skript/api/skript/addon/HySkriptAddon.java index 9ee51f7b..b446348e 100644 --- a/src/main/java/com/github/skriptdev/skript/api/skript/addon/HySkriptAddon.java +++ b/src/main/java/com/github/skriptdev/skript/api/skript/addon/HySkriptAddon.java @@ -25,7 +25,7 @@ public HySkriptAddon(String name) { * Called when the addon starts to load. * This is a good time to set up your syntaxes. */ - abstract public void setup(); + abstract public void start(); /** * Called when the addon is shutting down. From 25d1bd59212b4927c9ccdae603f4c669bfe0f912 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Thu, 5 Feb 2026 21:06:56 -0800 Subject: [PATCH 22/61] manifest.json - update some stuff --- src/main/resources/manifest.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/manifest.json b/src/main/resources/manifest.json index 5b9de4a7..633b0267 100644 --- a/src/main/resources/manifest.json +++ b/src/main/resources/manifest.json @@ -2,13 +2,13 @@ "Group": "skript", "Name": "HySkript", "Version": "$pluginVersion", - "Description": "Skripty Skripty gonna make a script!", + "Description": "Scripting the most out of your Hytale server.", "Authors": [ { "Name": "ShaneBee" } ], - "Website": "null", + "Website": "https://github.com/SkriptDev/HySkript", "ServerVersion": "*", "Dependencies": {}, "OptionalDependencies": {}, From 6bdbf1466e07ca20d40fc268660920e11e635f2f Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Thu, 5 Feb 2026 21:43:38 -0800 Subject: [PATCH 23/61] ScriptCommand - make trigger optional --- .../skript/command/ScriptCommandBuilder.java | 104 +++++++++--------- .../elements/command/ScriptCommand.java | 15 +-- 2 files changed, 63 insertions(+), 56 deletions(-) diff --git a/src/main/java/com/github/skriptdev/skript/api/skript/command/ScriptCommandBuilder.java b/src/main/java/com/github/skriptdev/skript/api/skript/command/ScriptCommandBuilder.java index 81ba7f56..7b95bbfb 100644 --- a/src/main/java/com/github/skriptdev/skript/api/skript/command/ScriptCommandBuilder.java +++ b/src/main/java/com/github/skriptdev/skript/api/skript/command/ScriptCommandBuilder.java @@ -10,6 +10,7 @@ import com.hypixel.hytale.server.core.command.system.arguments.system.Argument; import com.hypixel.hytale.server.core.command.system.arguments.system.OptionalArg; import com.hypixel.hytale.server.core.command.system.arguments.system.RequiredArg; +import com.hypixel.hytale.server.core.command.system.basecommands.AbstractCommandCollection; import com.hypixel.hytale.server.core.command.system.basecommands.AbstractPlayerCommand; import com.hypixel.hytale.server.core.command.system.basecommands.AbstractWorldCommand; import com.hypixel.hytale.server.core.entity.entities.Player; @@ -21,6 +22,7 @@ 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.lang.entries.SectionLoader; import io.github.syst3ms.skriptparser.log.ErrorType; import io.github.syst3ms.skriptparser.log.SkriptLogger; import io.github.syst3ms.skriptparser.parsing.ParserState; @@ -55,7 +57,7 @@ public static ScriptCommandBuilder create(int commandType, SkriptLogger logger) .addOptionalKey("permission") .addOptionalKey("description") .addOptionalList("aliases") - .addSection("trigger") + .addLoader(new SectionLoader("trigger", true)) .build(); public ScriptCommandBuilder(int commandType, SkriptLogger logger) { @@ -92,17 +94,9 @@ public boolean parseCommandLine(String commandLine) { public List setupCommand(FileSection section, ParserState parserState, SkriptLogger logger) { this.sec.loadConfiguration(null, section, parserState, logger); - Optional triggerSec = this.sec.getSection("trigger"); - if (triggerSec.isEmpty()) { - logger.error("Trigger section is missing", ErrorType.SEMANTIC_ERROR); - return List.of(); - } - CodeSection trigger = triggerSec.get(); - if (trigger.getItems().isEmpty()) { - logger.warn("Trigger section should not be empty."); - return List.of(); - } + Optional triggerSec = this.sec.getSection("trigger"); + boolean hasTrigger = triggerSec.isPresent(); Optional descOption = this.sec.getValue("description", String.class); if (descOption.isEmpty()) { @@ -114,50 +108,62 @@ public List setupCommand(FileSection section, ParserState parserState description = ""; } - this.hyCommand = switch (this.commandType) { - case 1 -> new AbstractPlayerCommand(this.commandName, description) { - @Override - protected void execute(@NotNull CommandContext commandContext, @NotNull Store store, - @NotNull Ref ref, @NotNull PlayerRef playerRef, @NotNull World world) { - - CommandSender sender = commandContext.sender(); - Player player = store.getComponent(ref, Player.getComponentType()); - ScriptCommandContext context = new ScriptCommandContext(ScriptCommandBuilder.this.commandName, sender, player, world); - createLocalVariables(commandContext, context); - Statement.runAll(trigger, context); - Variables.clearLocalVariables(context); - } - }; - case 2 -> new AbstractWorldCommand(this.commandName, description) { - - @Override - protected void execute(@NotNull CommandContext commandContext, @NotNull World world, @NotNull Store store) { - ScriptCommandContext context = new ScriptCommandContext(ScriptCommandBuilder.this.commandName, - commandContext.sender(), null, world); - createLocalVariables(commandContext, context); - Statement.runAll(trigger, context); - Variables.clearLocalVariables(context); - } - }; - default -> new AbstractCommand(this.commandName, description) { + if (hasTrigger) { + CodeSection trigger = triggerSec.get(); + if (trigger.getItems().isEmpty()) { + logger.warn("Trigger section should not be empty. Or remove it if you don't need it."); + return List.of(); + } + + this.hyCommand = switch (this.commandType) { + case 1 -> new AbstractPlayerCommand(this.commandName, description) { + @Override + protected void execute(@NotNull CommandContext commandContext, @NotNull Store store, + @NotNull Ref ref, @NotNull PlayerRef playerRef, @NotNull World world) { - @Override - protected @Nullable CompletableFuture execute(@NotNull CommandContext commandContext) { - CompletableFuture.runAsync(() -> { CommandSender sender = commandContext.sender(); - Player player = null; - if (sender instanceof Player p) player = p; - ScriptCommandContext context = new ScriptCommandContext(ScriptCommandBuilder.this.commandName, - sender, player, null); + Player player = store.getComponent(ref, Player.getComponentType()); + ScriptCommandContext context = new ScriptCommandContext(ScriptCommandBuilder.this.commandName, sender, player, world); + createLocalVariables(commandContext, context); + Statement.runAll(trigger, context); + Variables.clearLocalVariables(context); + } + }; + case 2 -> new AbstractWorldCommand(this.commandName, description) { + @Override + protected void execute(@NotNull CommandContext commandContext, @NotNull World world, @NotNull Store store) { + ScriptCommandContext context = new ScriptCommandContext(ScriptCommandBuilder.this.commandName, + commandContext.sender(), null, world); createLocalVariables(commandContext, context); Statement.runAll(trigger, context); Variables.clearLocalVariables(context); - }); - return null; - } + } + }; + default -> new AbstractCommand(this.commandName, description) { + + @Override + protected @Nullable CompletableFuture execute(@NotNull CommandContext commandContext) { + CompletableFuture.runAsync(() -> { + CommandSender sender = commandContext.sender(); + Player player = null; + if (sender instanceof Player p) player = p; + ScriptCommandContext context = new ScriptCommandContext(ScriptCommandBuilder.this.commandName, + sender, player, null); + + createLocalVariables(commandContext, context); + Statement.runAll(trigger, context); + Variables.clearLocalVariables(context); + }); + return null; + } + }; }; - }; + } else { + this.hyCommand = new AbstractCommandCollection(this.commandName, description) { + + }; + } this.args.forEach((key, arg) -> { if (arg.isOptional()) { OptionalArg optionalArg = hyCommand.withOptionalArg(key, arg.getDescription(), arg.getType()); @@ -193,7 +199,7 @@ protected void execute(@NotNull CommandContext commandContext, @NotNull World wo } } }); - return List.of(trigger); + return List.of(); } private void setupArg(CommandArg arg) { diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/command/ScriptCommand.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/command/ScriptCommand.java index e8c95b26..f4b2e9a0 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/command/ScriptCommand.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/command/ScriptCommand.java @@ -63,8 +63,8 @@ public String getName() { } } - public static void register(SkriptRegistration registration) { - registration.newEvent(ScriptCommand.class, + public static void register(SkriptRegistration reg) { + reg.newEvent(ScriptCommand.class, "*[global] command <.+>", "*player command <.+>", "*world command <.+>") @@ -88,7 +88,8 @@ public static void register(SkriptRegistration registration) { "**Entries**:", "- `Description` = The description for your command that will show in the commands gui (optional).", "- `Permission` = The permission required to execute the command (optional).", - "- `Aliases` = A list of aliases for the command (optional).") + "- `Aliases` = A list of aliases for the command (optional).", + "- `Trigger` = The code that will be executed when the command is executed (optional).") .examples("command /kill:", "\tdescription: Kill all the players", "\ttrigger:", @@ -119,22 +120,22 @@ public static void register(SkriptRegistration registration) { .since("1.0.0") .register(); - registration.newSingleContextValue(ScriptCommandContext.class, Player.class, + reg.newSingleContextValue(ScriptCommandContext.class, Player.class, "player", ScriptCommandContext::getPlayer) .setUsage(Usage.EXPRESSION_OR_ALONE) .register(); - registration.newSingleContextValue(ScriptCommandContext.class, CommandSender.class, + reg.newSingleContextValue(ScriptCommandContext.class, CommandSender.class, "sender", ScriptCommandContext::getSender) .setUsage(Usage.EXPRESSION_OR_ALONE) .register(); - registration.newSingleContextValue(ScriptCommandContext.class, World.class, + reg.newSingleContextValue(ScriptCommandContext.class, World.class, "world", ScriptCommandContext::getWorld) .setUsage(Usage.EXPRESSION_OR_ALONE) .register(); - registration.newSingleContextValue(ScriptCommandContext.class, String.class, + reg.newSingleContextValue(ScriptCommandContext.class, String.class, "command", ScriptCommandContext::getCommand) .setUsage(Usage.EXPRESSION_OR_ALONE) .register(); From c3e729d65d636144109ce8642fa585c2af25aabc Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Thu, 5 Feb 2026 21:54:14 -0800 Subject: [PATCH 24/61] ScriptcommandBuilder - fix long line issues --- .../skript/api/skript/command/ScriptCommandBuilder.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/github/skriptdev/skript/api/skript/command/ScriptCommandBuilder.java b/src/main/java/com/github/skriptdev/skript/api/skript/command/ScriptCommandBuilder.java index 7b95bbfb..89b114c1 100644 --- a/src/main/java/com/github/skriptdev/skript/api/skript/command/ScriptCommandBuilder.java +++ b/src/main/java/com/github/skriptdev/skript/api/skript/command/ScriptCommandBuilder.java @@ -123,7 +123,8 @@ protected void execute(@NotNull CommandContext commandContext, @NotNull Store new AbstractWorldCommand(this.commandName, description) { @Override - protected void execute(@NotNull CommandContext commandContext, @NotNull World world, @NotNull Store store) { + protected void execute(@NotNull CommandContext commandContext, @NotNull World world, + @NotNull Store store) { ScriptCommandContext context = new ScriptCommandContext(ScriptCommandBuilder.this.commandName, commandContext.sender(), null, world); createLocalVariables(commandContext, context); From 2994f8388d275dcd6dc3890b1f877ed2f8f52301 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Thu, 5 Feb 2026 21:54:40 -0800 Subject: [PATCH 25/61] ScriptCommand - refactor contexts to allow player default in message sending --- .../elements/command/ScriptCommand.java | 24 +++---------------- 1 file changed, 3 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/command/ScriptCommand.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/command/ScriptCommand.java index f4b2e9a0..63d8ba9f 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/command/ScriptCommand.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/command/ScriptCommand.java @@ -2,6 +2,7 @@ import com.github.skriptdev.skript.api.skript.command.ScriptCommandBuilder; import com.github.skriptdev.skript.api.skript.command.ScriptCommandParent; +import com.github.skriptdev.skript.api.skript.event.PlayerContext; import com.hypixel.hytale.server.core.command.system.CommandSender; import com.hypixel.hytale.server.core.entity.entities.Player; import com.hypixel.hytale.server.core.universe.world.World; @@ -26,19 +27,8 @@ public void loadChild(ScriptCommandBuilder parent, SkriptLogger logger) { // UNUSED IN TOP LEVEL COMMAND } - public static class ScriptCommandContext implements TriggerContext { - - private final String command; - private final CommandSender sender; - private final Player player; - private final World world; - - public ScriptCommandContext(String command, CommandSender sender, Player player, World world) { - this.command = command; - this.sender = sender; - this.player = player; - this.world = world; - } + public record ScriptCommandContext(String command, CommandSender sender, Player player, World world) + implements PlayerContext { public String getCommand() { return this.command; @@ -120,26 +110,18 @@ public static void register(SkriptRegistration reg) { .since("1.0.0") .register(); - reg.newSingleContextValue(ScriptCommandContext.class, Player.class, - "player", ScriptCommandContext::getPlayer) - .setUsage(Usage.EXPRESSION_OR_ALONE) - .register(); - reg.newSingleContextValue(ScriptCommandContext.class, CommandSender.class, "sender", ScriptCommandContext::getSender) .setUsage(Usage.EXPRESSION_OR_ALONE) .register(); - reg.newSingleContextValue(ScriptCommandContext.class, World.class, "world", ScriptCommandContext::getWorld) .setUsage(Usage.EXPRESSION_OR_ALONE) .register(); - reg.newSingleContextValue(ScriptCommandContext.class, String.class, "command", ScriptCommandContext::getCommand) .setUsage(Usage.EXPRESSION_OR_ALONE) .register(); - } private ScriptCommandBuilder commandBuilder; From 056269192c0e85481a39fdd13a700548dc654c56 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Fri, 6 Feb 2026 08:31:02 -0800 Subject: [PATCH 26/61] SkriptRegistration - change asset store registration --- .../registration/AssetStoreRegistry.java | 50 ------ .../registration/SkriptRegistration.java | 160 ++++++++++++++++++ .../elements/types/TypesAssetStore.java | 70 ++++---- 3 files changed, 195 insertions(+), 85 deletions(-) delete mode 100644 src/main/java/com/github/skriptdev/skript/api/skript/registration/AssetStoreRegistry.java diff --git a/src/main/java/com/github/skriptdev/skript/api/skript/registration/AssetStoreRegistry.java b/src/main/java/com/github/skriptdev/skript/api/skript/registration/AssetStoreRegistry.java deleted file mode 100644 index 25dc47f8..00000000 --- a/src/main/java/com/github/skriptdev/skript/api/skript/registration/AssetStoreRegistry.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.github.skriptdev.skript.api.skript.registration; - -import com.hypixel.hytale.assetstore.JsonAsset; -import com.hypixel.hytale.assetstore.map.DefaultAssetMap; -import io.github.syst3ms.skriptparser.registration.SkriptRegistration; -import io.github.syst3ms.skriptparser.registration.SkriptRegistration.TypeRegistrar; - -import java.util.Locale; -import java.util.Map; -import java.util.TreeMap; - -/** - * Registry related to {@link com.hypixel.hytale.assetstore.AssetStore AssetStores}. - * - * @param Asset store type - */ -public class AssetStoreRegistry { - - private final Map assetStoreValues = new TreeMap<>(); - - /** - * Create a new {@link TypeRegistrar} with for an {@link com.hypixel.hytale.assetstore.AssetStore AssetStore}. - * Remember to register it with {@link TypeRegistrar#register()} - * - * @param registration The registration to register to - * @param c Asset store class - * @param assetMap Asset map for the store - * @param name Name of the new type - * @param pattern Pattern for the type - * @param Key type for the asset map - * @param Asset type - * @return New {@link TypeRegistrar} - */ - public static > TypeRegistrar register( - SkriptRegistration registration, - Class c, - DefaultAssetMap assetMap, - String name, - String pattern) { - - AssetStoreRegistry store = new AssetStoreRegistry<>(); - assetMap.getAssetMap().forEach((key, value) -> store.assetStoreValues.put(key.toLowerCase(Locale.ROOT), value)); - return registration.newType(c, name, pattern) - .usage(String.join(", ", store.assetStoreValues.keySet())) - .supplier(() -> store.assetStoreValues.values().stream().iterator()) - .literalParser(s -> store.assetStoreValues.get(s.toLowerCase(Locale.ROOT).replace(" ", "_"))) - .toStringFunction(Object::toString); - } - -} diff --git a/src/main/java/com/github/skriptdev/skript/api/skript/registration/SkriptRegistration.java b/src/main/java/com/github/skriptdev/skript/api/skript/registration/SkriptRegistration.java index 39ae7e25..659d4651 100644 --- a/src/main/java/com/github/skriptdev/skript/api/skript/registration/SkriptRegistration.java +++ b/src/main/java/com/github/skriptdev/skript/api/skript/registration/SkriptRegistration.java @@ -1,10 +1,26 @@ package com.github.skriptdev.skript.api.skript.registration; import com.github.skriptdev.skript.api.utils.Utils; +import com.hypixel.hytale.assetstore.JsonAsset; +import com.hypixel.hytale.assetstore.map.DefaultAssetMap; +import io.github.syst3ms.skriptparser.docs.Documentation; import io.github.syst3ms.skriptparser.log.LogEntry; import io.github.syst3ms.skriptparser.registration.SkriptAddon; +import io.github.syst3ms.skriptparser.types.Type; +import io.github.syst3ms.skriptparser.types.TypeManager; +import io.github.syst3ms.skriptparser.types.changers.Arithmetic; +import io.github.syst3ms.skriptparser.types.changers.Changer; +import io.github.syst3ms.skriptparser.types.changers.TypeSerializer; +import org.jetbrains.annotations.Nullable; +import java.util.Iterator; import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; +import java.util.TreeMap; +import java.util.function.Function; +import java.util.function.Supplier; /** * An extension of {@link io.github.syst3ms.skriptparser.registration.SkriptRegistration} with additional features. @@ -23,4 +39,148 @@ public List register() { return List.of(); } + /** + * Register a new asset store type. + * + * @param assetClass Class of AssetStore + * @param assetMap AssetMap for the AssetStore + * @param name Name of the AssetStore + * @param pattern Pattern for the AssetStore + * @param Type of Asset + * @param Type of Asset ID + * @return AssetStoreRegistrar for further configuration + */ + public , K extends String> AssetStoreRegistrar newAssetStoreType(Class assetClass, + DefaultAssetMap assetMap, + String name, + String pattern) { + return new AssetStoreRegistrar<>(assetClass, assetMap, name, pattern); + } + + public class AssetStoreRegistrar, K extends String> { + private final Class assetClass; + private final String baseName; + private final String pattern; + private Function toStringFunction = o -> Objects.toString(o, TypeManager.NULL_REPRESENTATION); + private final Function literalParser; + @Nullable + private Changer defaultChanger; + @Nullable + private Arithmetic arithmetic; + @Nullable + private TypeSerializer serializer; + private final Supplier> supplier; + private final Documentation documentation = new Documentation(); + @SuppressWarnings("FieldCanBeLocal") + private final DefaultAssetMap assetMap; // Store for later use?!?! + private final Map assetStoreValues = new TreeMap<>(); + + public AssetStoreRegistrar(Class assetClass, DefaultAssetMap assetMap, String name, String pattern) { + this.assetClass = assetClass; + this.baseName = name; + this.pattern = pattern; + this.assetMap = assetMap; + assetMap.getAssetMap().forEach((key, value) -> this.assetStoreValues.put(key.toLowerCase(Locale.ROOT), value)); + this.supplier = () -> assetStoreValues.values().stream().iterator(); + this.literalParser = s -> this.assetStoreValues.get(s.toLowerCase(Locale.ROOT).replace(" ", "_")); + } + + /** + * @param toStringFunction a function converting an instance of the type to a String + * @return the registrar + */ + public AssetStoreRegistrar toStringFunction(Function toStringFunction) { + this.toStringFunction = c -> c == null ? TypeManager.NULL_REPRESENTATION : toStringFunction.apply(c); + return this; + } + + /** + * @param defaultChanger a default {@link Changer} for this type + * @return the registrar + */ + public AssetStoreRegistrar defaultChanger(Changer defaultChanger) { + this.defaultChanger = defaultChanger; + return this; + } + + /** + * @param arithmetic a default {@link Arithmetic} for this type + * @return the registrar + */ + public AssetStoreRegistrar arithmetic(Arithmetic arithmetic) { + this.arithmetic = arithmetic; + return this; + } + + /** + * @param serializer add a type serializer that allows the type to be saved to databases. + * @return the registrar + */ + public AssetStoreRegistrar serializer(TypeSerializer serializer) { + this.serializer = serializer; + return this; + } + + public AssetStoreRegistrar noDoc() { + this.documentation.noDoc(); + return this; + } + + public AssetStoreRegistrar experimental() { + this.documentation.experimental(); + return this; + } + + public AssetStoreRegistrar experimental(String message) { + this.documentation.experimental(message); + return this; + } + + public AssetStoreRegistrar name(String name) { + this.documentation.setName(name); + return this; + } + + public AssetStoreRegistrar description(String... description) { + this.documentation.setDescription(description); + return this; + } + + public AssetStoreRegistrar examples(String... examples) { + this.documentation.setExamples(examples); + return this; + } + + public AssetStoreRegistrar usage(String usage) { + this.documentation.setUsage(usage); + return this; + } + + public AssetStoreRegistrar since(String since) { + this.documentation.setSince(since); + return this; + } + + /** + * Adds this type to the list of currently registered syntaxes + */ + public void register() { + AssetStoreType assetStoreType = new AssetStoreType<>(assetClass, baseName, pattern, literalParser, toStringFunction, + defaultChanger, arithmetic, documentation, serializer, this.supplier); + newTypes = true; + types.add(assetStoreType); + } + } + + public static class AssetStoreType, K extends String> extends Type { + + public AssetStoreType(Class c, String baseName, String pattern, Function literalParser, + Function toStringFunction, Changer defaultChanger, + Arithmetic arithmetic, Documentation documentation, TypeSerializer serializer, + Supplier> supplier) { + super(c, baseName, pattern, literalParser, toStringFunction, defaultChanger, + arithmetic, documentation, serializer, supplier); + } + } + } diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesAssetStore.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesAssetStore.java index d7a45b2e..fad726ae 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesAssetStore.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesAssetStore.java @@ -1,6 +1,5 @@ package com.github.skriptdev.skript.plugin.elements.types; -import com.github.skriptdev.skript.api.skript.registration.AssetStoreRegistry; import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; import com.google.gson.Gson; import com.google.gson.JsonElement; @@ -31,80 +30,75 @@ public class TypesAssetStore { @SuppressWarnings("deprecation") // BlockGroup (maybe we dont keep this?!?!) - static void register(SkriptRegistration registration) { - AssetStoreRegistry.register(registration, BiomeAsset.class, BiomeAsset.getAssetStore().getAssetMap(), "biome", "biome@s") + static void register(SkriptRegistration reg) { + // Please keep in alphabetical order + reg.newAssetStoreType(BiomeAsset.class, BiomeAsset.getAssetStore().getAssetMap(), "biome", "biome@s") .name("Biome") .description("Represents the types of biomes in the game.", autoGenMessage()) .since("1.0.0") .toStringFunction(BiomeAsset::getId) .register(); - AssetStoreRegistry.register(registration, BlockGroup.class, AssetRegistry.getAssetStore(BlockGroup.class).getAssetMap(), + reg.newAssetStoreType(BlockGroup.class, AssetRegistry.getAssetStore(BlockGroup.class).getAssetMap(), "blockgroup", "blockgroup@s") .name("Block Group") .description("Represents the groups of blocks in the game.", autoGenMessage()) .since("1.0.0") .toStringFunction(BlockGroup::getId) .register(); - AssetStoreRegistry.register(registration, CraftingRecipe.class, CraftingRecipe.getAssetMap(), "craftingrecipe", "craftingrecipe@s") - .name("Crafting Recipe") - .description("Represents the crafting recipes in the game.", autoGenMessage()) - .since("1.0.0") - .toStringFunction(CraftingRecipe::getId) - .register(); - AssetStoreRegistry.register(registration, BlockType.class, BlockType.getAssetMap(), "blocktype", "blockType@s") + reg.newAssetStoreType(BlockType.class, BlockType.getAssetMap(), "blocktype", "blockType@s") .name("BlockType") .description("Represents the types of blocks in the game.", autoGenMessage()) .examples("set {_block} to blocktype of block at player") .since("1.0.0") .toStringFunction(BlockType::getId) .register(); - AssetStoreRegistry.register(registration, Fluid.class, Fluid.getAssetMap(), "fluid", "fluid@s") - .name("Fluid") - .description("Represents the types of fluids in the game.", autoGenMessage()) + reg.newAssetStoreType(CraftingRecipe.class, CraftingRecipe.getAssetMap(), "craftingrecipe", "craftingrecipe@s") + .name("Crafting Recipe") + .description("Represents the crafting recipes in the game.", autoGenMessage()) .since("1.0.0") - .toStringFunction(Fluid::getId) + .toStringFunction(CraftingRecipe::getId) + .register(); + reg.newAssetStoreType(DamageCause.class, DamageCause.getAssetMap(), + "damagecause", "damageCause@s") + .name("Damage Cause") + .description("Represents the types of damage that can be caused to entities.", autoGenMessage()) + .since("1.0.0") + .toStringFunction(DamageCause::getId) .register(); - AssetStoreRegistry.register(registration, EntityEffect.class, EntityEffect.getAssetMap(), + reg.newAssetStoreType(EntityEffect.class, EntityEffect.getAssetMap(), "entityeffect", "entityEffect@s") .name("Entity Effect") .description("Represents the types of effects that can be applied to entities.", autoGenMessage()) .since("1.0.0") .toStringFunction(EntityEffect::getId) .register(); - AssetStoreRegistry.register(registration, EntityStatType.class, EntityStatType.getAssetMap(), + reg.newAssetStoreType(EntityStatType.class, EntityStatType.getAssetMap(), "entitystattype", "entityStatType@s") .name("Entity Stat Type") .description("Represents the types of stats that can be applied to entities.", autoGenMessage()) .since("1.0.0") .register(); - AssetStoreRegistry.register(registration, Environment.class, Environment.getAssetMap(), + reg.newAssetStoreType(Environment.class, Environment.getAssetMap(), "environment", "environment@s") .name("Environment") .description("Represents the types of environments in the game.", autoGenMessage()) .since("1.0.0") .toStringFunction(Environment::getId) .register(); - AssetStoreRegistry.register(registration, DamageCause.class, DamageCause.getAssetMap(), - "damagecause", "damageCause@s") - .name("Damage Cause") - .description("Represents the types of damage that can be caused to entities.", autoGenMessage()) + reg.newAssetStoreType(Fluid.class, Fluid.getAssetMap(), "fluid", "fluid@s") + .name("Fluid") + .description("Represents the types of fluids in the game.", autoGenMessage()) .since("1.0.0") - .toStringFunction(DamageCause::getId) + .toStringFunction(Fluid::getId) .register(); - AssetStoreRegistry.register(registration, Interaction.class, Interaction.getAssetMap(), + reg.newAssetStoreType(Interaction.class, Interaction.getAssetMap(), "interaction", "interaction@s") .name("Interaction") .description("Represents the types of interactions that can be performed by entities.", autoGenMessage()) .since("1.0.0") .toStringFunction(Interaction::getId) .register(); - AssetStoreRegistry.register(registration, RootInteraction.class, RootInteraction.getAssetMap(), - "rootinteraction", "rootinteraction@s") - .name("Interaction - Root") - .description("Represents the types of root interactions that can be performed by entities.", autoGenMessage()) - .since("INSERT VERSION") - .register(); - AssetStoreRegistry.register(registration, Item.class, Item.getAssetMap(), "item", "item@s") + reg.newAssetStoreType(Item.class, Item.getAssetMap(), "item", "item@s") .name("Item") .description("Represents the types of items in the game.", autoGenMessage()) .examples("set {_i} to itemstack of Food_Fish_Grilled") @@ -123,25 +117,31 @@ public Item deserialize(@NotNull Gson gson, @NotNull JsonElement element) { } }) .register(); - AssetStoreRegistry.register(registration, Projectile.class, Projectile.getAssetMap(), "projectile", "projectile@s") + reg.newAssetStoreType(Projectile.class, Projectile.getAssetMap(), "projectile", "projectile@s") .name("Projectile") .description("Represents the types of projectiles in the game.", autoGenMessage()) .since("1.0.0") .toStringFunction(Projectile::getId) .register(); - AssetStoreRegistry.register(registration, ResourceType.class, ResourceType.getAssetMap(), "resourcetype", "resourceType@s") + reg.newAssetStoreType(ResourceType.class, ResourceType.getAssetMap(), "resourcetype", "resourceType@s") .name("Resource Type") .description("Represents the types of resources in the game, such as woods and stones.", autoGenMessage()) .since("1.0.0") .toStringFunction(ResourceType::getId) .register(); - AssetStoreRegistry.register(registration, SoundEvent.class, SoundEvent.getAssetMap(), "soundevent", "soundevent@s") + reg.newAssetStoreType(RootInteraction.class, RootInteraction.getAssetMap(), + "rootinteraction", "rootinteraction@s") + .name("Interaction - Root") + .description("Represents the types of root interactions that can be performed by entities.", autoGenMessage()) + .since("INSERT VERSION") + .register(); + reg.newAssetStoreType(SoundEvent.class, SoundEvent.getAssetMap(), "soundevent", "soundevent@s") .name("Sound Event") .description("Represents the types of sounds in the game.", autoGenMessage()) .since("1.0.0") .toStringFunction(SoundEvent::getId) .register(); - AssetStoreRegistry.register(registration, Weather.class, Weather.getAssetMap(), "weather", "weather@s") + reg.newAssetStoreType(Weather.class, Weather.getAssetMap(), "weather", "weather@s") .name("Weather") .description("Represents the types of weather in the game.", autoGenMessage()) .since("1.0.0") From 7867d783e50a1b63f99075421cb28d2ec83975e0 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Fri, 6 Feb 2026 08:56:36 -0800 Subject: [PATCH 27/61] SkriptRegistration - change enum registration --- .../api/skript/registration/EnumRegistry.java | 48 ------ .../registration/SkriptRegistration.java | 151 +++++++++++++++++- .../plugin/elements/types/TypesBlock.java | 7 +- .../plugin/elements/types/TypesItem.java | 13 +- .../plugin/elements/types/TypesPlayer.java | 3 +- .../plugin/elements/types/TypesWorld.java | 3 +- 6 files changed, 160 insertions(+), 65 deletions(-) delete mode 100644 src/main/java/com/github/skriptdev/skript/api/skript/registration/EnumRegistry.java diff --git a/src/main/java/com/github/skriptdev/skript/api/skript/registration/EnumRegistry.java b/src/main/java/com/github/skriptdev/skript/api/skript/registration/EnumRegistry.java deleted file mode 100644 index 45da70fe..00000000 --- a/src/main/java/com/github/skriptdev/skript/api/skript/registration/EnumRegistry.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.github.skriptdev.skript.api.skript.registration; - -import io.github.syst3ms.skriptparser.registration.SkriptRegistration; -import io.github.syst3ms.skriptparser.registration.SkriptRegistration.TypeRegistrar; - -import java.util.Locale; -import java.util.Map; -import java.util.TreeMap; - -/** - * Registry related to enums. - * - * @param Enum class. - */ -public class EnumRegistry> { - - private final Map values = new TreeMap<>(); - - /** - * Create a new {@link TypeRegistrar} with for an enum. - * Remember to register it with {@link TypeRegistrar#register()} - * - * @param registration Registration to register to - * @param enumClass Enum class to register - * @param name Name of the new type - * @param pattern Pattern for the type - * @param Enum class - * @return New {@link TypeRegistrar} - */ - public static > TypeRegistrar register(SkriptRegistration registration, - Class enumClass, - String name, - String pattern) { - if (enumClass == null || !enumClass.isEnum()) { - throw new IllegalArgumentException("Cannot register null enum"); - } - EnumRegistry eEnumRegistry = new EnumRegistry<>(); - for (T e : enumClass.getEnumConstants()) { - eEnumRegistry.values.put(e.name().toLowerCase(Locale.ROOT), e); - } - return registration.newType(enumClass, name, pattern) - .usage(String.join(", ", eEnumRegistry.values.keySet())) - .supplier(() -> eEnumRegistry.values.values().iterator()) - .literalParser(s -> eEnumRegistry.values.get(s.toLowerCase(Locale.ROOT).replace(" ", "_"))) - .toStringFunction(Enum::name); - } - -} diff --git a/src/main/java/com/github/skriptdev/skript/api/skript/registration/SkriptRegistration.java b/src/main/java/com/github/skriptdev/skript/api/skript/registration/SkriptRegistration.java index 659d4651..ba0dd3e0 100644 --- a/src/main/java/com/github/skriptdev/skript/api/skript/registration/SkriptRegistration.java +++ b/src/main/java/com/github/skriptdev/skript/api/skript/registration/SkriptRegistration.java @@ -75,14 +75,15 @@ public class AssetStoreRegistrar, K extends String> { private final DefaultAssetMap assetMap; // Store for later use?!?! private final Map assetStoreValues = new TreeMap<>(); - public AssetStoreRegistrar(Class assetClass, DefaultAssetMap assetMap, String name, String pattern) { + public AssetStoreRegistrar(Class assetClass, DefaultAssetMap assetMap, String baseName, String pattern) { this.assetClass = assetClass; - this.baseName = name; + this.baseName = baseName; this.pattern = pattern; this.assetMap = assetMap; assetMap.getAssetMap().forEach((key, value) -> this.assetStoreValues.put(key.toLowerCase(Locale.ROOT), value)); this.supplier = () -> assetStoreValues.values().stream().iterator(); this.literalParser = s -> this.assetStoreValues.get(s.toLowerCase(Locale.ROOT).replace(" ", "_")); + } /** @@ -183,4 +184,150 @@ public AssetStoreType(Class c, String baseName, String pattern, Function Type parameter for the Enum + * @return EnumRegistrar for configuring the Enum type + */ + public > EnumRegistrar newEnumType(Class enumClass, String baseName, String pattern) { + return new EnumRegistrar<>(enumClass, baseName, pattern); + } + + public class EnumRegistrar> { + private final Class enumClass; + private final String baseName; + private final String pattern; + + private Function toStringFunction; + private final Function literalParser; + @Nullable + private Changer defaultChanger; + @Nullable + private Arithmetic arithmetic; + @Nullable + private TypeSerializer serializer; + private final Supplier> supplier; + private final Documentation documentation = new Documentation(); + private final Map values = new TreeMap<>(); + + public EnumRegistrar(Class enumClass, String name, String pattern) { + for (E e : enumClass.getEnumConstants()) { + this.values.put(e.name().toLowerCase(Locale.ROOT), e); + } + this.enumClass = enumClass; + this.baseName = name; + this.pattern = pattern; + this.documentation.setUsage(String.join(", ", this.values.keySet())); + this.supplier = () -> this.values.values().iterator(); + this.literalParser = s -> this.values.get(s.toLowerCase(Locale.ROOT).replace(" ", "_")); + this.toStringFunction = e -> e.name().toLowerCase(Locale.ROOT); + } + + + /** + * @param toStringFunction a function converting an instance of the type to a String + * @return the registrar + */ + public EnumRegistrar toStringFunction(Function toStringFunction) { + this.toStringFunction = c -> c == null ? TypeManager.NULL_REPRESENTATION : toStringFunction.apply(c); + return this; + } + + /** + * @param defaultChanger a default {@link Changer} for this type + * @return the registrar + */ + public EnumRegistrar defaultChanger(Changer defaultChanger) { + this.defaultChanger = defaultChanger; + return this; + } + + /** + * @param arithmetic a default {@link Arithmetic} for this type + * @return the registrar + */ + public EnumRegistrar arithmetic(Arithmetic arithmetic) { + this.arithmetic = arithmetic; + return this; + } + + /** + * @param serializer add a type serializer that allows the type to be saved to databases. + * @return the registrar + */ + public EnumRegistrar serializer(TypeSerializer serializer) { + this.serializer = serializer; + return this; + } + + /** + * Prevent docs from being printed. + * + * @return the registrar + */ + public EnumRegistrar noDoc() { + this.documentation.noDoc(); + return this; + } + + public EnumRegistrar experimental() { + this.documentation.experimental(); + return this; + } + + public EnumRegistrar experimental(String message) { + this.documentation.experimental(message); + return this; + } + + public EnumRegistrar name(String name) { + this.documentation.setName(name); + return this; + } + + public EnumRegistrar description(String... description) { + this.documentation.setDescription(description); + return this; + } + + public EnumRegistrar examples(String... examples) { + this.documentation.setExamples(examples); + return this; + } + + public EnumRegistrar usage(String usage) { + this.documentation.setUsage(usage); + return this; + } + + public EnumRegistrar since(String since) { + this.documentation.setSince(since); + return this; + } + + /** + * Adds this type to the list of currently registered syntaxes + */ + public void register() { + EnumType enumType = new EnumType<>(this.enumClass, baseName, pattern, literalParser, toStringFunction, + defaultChanger, arithmetic, documentation, serializer, this.supplier); + newTypes = true; + types.add(enumType); + } + } + + public static class EnumType> extends Type { + public EnumType(Class c, String baseName, String pattern, Function literalParser, + Function toStringFunction, Changer defaultChanger, + Arithmetic arithmetic, Documentation documentation, TypeSerializer serializer, + Supplier> supplier) { + super(c, baseName, pattern, literalParser, toStringFunction, defaultChanger, + arithmetic, documentation, serializer, supplier); + } + } + } diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesBlock.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesBlock.java index 5547fbac..921ee231 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesBlock.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesBlock.java @@ -1,20 +1,19 @@ package com.github.skriptdev.skript.plugin.elements.types; import com.github.skriptdev.skript.api.hytale.Block; -import com.github.skriptdev.skript.api.skript.registration.EnumRegistry; import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; import com.hypixel.hytale.protocol.InteractionType; public class TypesBlock { - static void register(SkriptRegistration registration) { - registration.newType(Block.class, "block", "block@s") + static void register(SkriptRegistration reg) { + reg.newType(Block.class, "block", "block@s") .name("Block") .description("Represents a block in a world.") .since("1.0.0") .toStringFunction(Block::toTypeString) .register(); - EnumRegistry.register(registration, InteractionType.class, "interactiontype", "interactiontype@s") + reg.newEnumType(InteractionType.class, "interactiontype", "interactiontype@s") .name("Interaction Type") .description("Represents the types of interactions that can be performed on a block.") .since("1.0.0") diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesItem.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesItem.java index d30a07f8..bfc5aca1 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesItem.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesItem.java @@ -1,6 +1,5 @@ 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.github.skriptdev.skript.api.skript.variables.SerializerUtils; import com.google.gson.Gson; @@ -19,16 +18,16 @@ public class TypesItem { - static void register(SkriptRegistration registration) { + static void register(SkriptRegistration reg) { // Please keep in alphabetical order - registration.newType(ItemComponent.class, "itemcomponent", "itemComponent@s") + reg.newType(ItemComponent.class, "itemcomponent", "itemComponent@s") .name("Item Component") .description("Represents the component of a dropped item.") .since("1.0.0") .toStringFunction(ic -> String.format("ItemComponent{itemstack=%s}", ic.getItemStack())) .serializer(SerializerUtils.getCodecSerializer(ItemComponent.CODEC)) .register(); - registration.newType(ItemContainer.class, "itemcontainer", "itemContainer@s") + reg.newType(ItemContainer.class, "itemcontainer", "itemContainer@s") .name("Item Container") .description("Represents an item container within an inventory (such as the armor container).") .since("1.0.0") @@ -64,7 +63,7 @@ public ItemContainer deserialize(@NotNull Gson gson, @NotNull JsonElement elemen } }) .register(); - registration.newType(ItemStack.class, "itemstack", "itemStack@s") + reg.newType(ItemStack.class, "itemstack", "itemStack@s") .name("Item Stack") .description("Represents an item in an inventory slot.") .examples("set {_i} to itemstack of Food_Fish_Grilled") @@ -87,7 +86,7 @@ public ItemStack deserialize(@NotNull Gson gson, @NotNull JsonElement element) { } }) .register(); - registration.newType(Inventory.class, "inventory", "inventor@y@ies") + reg.newType(Inventory.class, "inventory", "inventor@y@ies") .name("Inventory") .description("Represents an inventory of an entity or block.") .since("1.0.0") @@ -105,7 +104,7 @@ public Inventory deserialize(@NotNull Gson gson, @NotNull JsonElement element) { } }) .register(); - EnumRegistry.register(registration, InventoryActionType.class, "inventoryactiontype", "inventoryActionType@s") + reg.newEnumType(InventoryActionType.class, "inventoryactiontype", "inventoryActionType@s") .name("Inventory Action Type") .description("Represents the types of actions that can be performed in an inventory.") .since("1.0.0") diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesPlayer.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesPlayer.java index 5b094170..7efb63b1 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesPlayer.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesPlayer.java @@ -1,6 +1,5 @@ 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.GameMode; import com.hypixel.hytale.server.core.entity.entities.Player; @@ -10,7 +9,7 @@ public class TypesPlayer { public static void register(SkriptRegistration reg) { // Keep these in alphabetical order - EnumRegistry.register(reg, GameMode.class, "gamemode", "gamemode@s") + reg.newEnumType(GameMode.class, "gamemode", "gamemode@s") .name("GameMode") .description("Represents a game mode.") .since("1.0.0") 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 2d89c1b5..2da4b6e8 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,6 +1,5 @@ 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.command.system.arguments.types.RelativeDoublePosition; @@ -29,7 +28,7 @@ static void register(SkriptRegistration reg) { .description("Represents a block position relative to another block position.") .since("1.0.0") .register(); - EnumRegistry.register(reg, SoundCategory.class, "soundcategory", "soundcategor@y@ies") + reg.newEnumType(SoundCategory.class, "soundcategory", "soundcategor@y@ies") .name("Sound Category") .description("Represents a sound category.") .since("1.0.0") From 975b1ba974f856698f6da16246b1f5aee3dc2538 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Fri, 6 Feb 2026 09:02:59 -0800 Subject: [PATCH 28/61] TypesAssetStore - remove auto gen message - We won't be printing these in json docs --- .../elements/types/TypesAssetStore.java | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesAssetStore.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesAssetStore.java index fad726ae..14a2d477 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesAssetStore.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesAssetStore.java @@ -34,73 +34,73 @@ static void register(SkriptRegistration reg) { // Please keep in alphabetical order reg.newAssetStoreType(BiomeAsset.class, BiomeAsset.getAssetStore().getAssetMap(), "biome", "biome@s") .name("Biome") - .description("Represents the types of biomes in the game.", autoGenMessage()) + .description("Represents the types of biomes in the game.") .since("1.0.0") .toStringFunction(BiomeAsset::getId) .register(); reg.newAssetStoreType(BlockGroup.class, AssetRegistry.getAssetStore(BlockGroup.class).getAssetMap(), "blockgroup", "blockgroup@s") .name("Block Group") - .description("Represents the groups of blocks in the game.", autoGenMessage()) + .description("Represents the groups of blocks in the game.") .since("1.0.0") .toStringFunction(BlockGroup::getId) .register(); reg.newAssetStoreType(BlockType.class, BlockType.getAssetMap(), "blocktype", "blockType@s") .name("BlockType") - .description("Represents the types of blocks in the game.", autoGenMessage()) + .description("Represents the types of blocks in the game.") .examples("set {_block} to blocktype of block at player") .since("1.0.0") .toStringFunction(BlockType::getId) .register(); reg.newAssetStoreType(CraftingRecipe.class, CraftingRecipe.getAssetMap(), "craftingrecipe", "craftingrecipe@s") .name("Crafting Recipe") - .description("Represents the crafting recipes in the game.", autoGenMessage()) + .description("Represents the crafting recipes in the game.") .since("1.0.0") .toStringFunction(CraftingRecipe::getId) .register(); reg.newAssetStoreType(DamageCause.class, DamageCause.getAssetMap(), "damagecause", "damageCause@s") .name("Damage Cause") - .description("Represents the types of damage that can be caused to entities.", autoGenMessage()) + .description("Represents the types of damage that can be caused to entities.") .since("1.0.0") .toStringFunction(DamageCause::getId) .register(); reg.newAssetStoreType(EntityEffect.class, EntityEffect.getAssetMap(), "entityeffect", "entityEffect@s") .name("Entity Effect") - .description("Represents the types of effects that can be applied to entities.", autoGenMessage()) + .description("Represents the types of effects that can be applied to entities.") .since("1.0.0") .toStringFunction(EntityEffect::getId) .register(); reg.newAssetStoreType(EntityStatType.class, EntityStatType.getAssetMap(), "entitystattype", "entityStatType@s") .name("Entity Stat Type") - .description("Represents the types of stats that can be applied to entities.", autoGenMessage()) + .description("Represents the types of stats that can be applied to entities.") .since("1.0.0") .register(); reg.newAssetStoreType(Environment.class, Environment.getAssetMap(), "environment", "environment@s") .name("Environment") - .description("Represents the types of environments in the game.", autoGenMessage()) + .description("Represents the types of environments in the game.") .since("1.0.0") .toStringFunction(Environment::getId) .register(); reg.newAssetStoreType(Fluid.class, Fluid.getAssetMap(), "fluid", "fluid@s") .name("Fluid") - .description("Represents the types of fluids in the game.", autoGenMessage()) + .description("Represents the types of fluids in the game.") .since("1.0.0") .toStringFunction(Fluid::getId) .register(); reg.newAssetStoreType(Interaction.class, Interaction.getAssetMap(), "interaction", "interaction@s") .name("Interaction") - .description("Represents the types of interactions that can be performed by entities.", autoGenMessage()) + .description("Represents the types of interactions that can be performed by entities.") .since("1.0.0") .toStringFunction(Interaction::getId) .register(); reg.newAssetStoreType(Item.class, Item.getAssetMap(), "item", "item@s") .name("Item") - .description("Represents the types of items in the game.", autoGenMessage()) + .description("Represents the types of items in the game.") .examples("set {_i} to itemstack of Food_Fish_Grilled") .since("1.0.0") .toStringFunction(Item::getId) @@ -119,36 +119,37 @@ public Item deserialize(@NotNull Gson gson, @NotNull JsonElement element) { .register(); reg.newAssetStoreType(Projectile.class, Projectile.getAssetMap(), "projectile", "projectile@s") .name("Projectile") - .description("Represents the types of projectiles in the game.", autoGenMessage()) + .description("Represents the types of projectiles in the game.") .since("1.0.0") .toStringFunction(Projectile::getId) .register(); reg.newAssetStoreType(ResourceType.class, ResourceType.getAssetMap(), "resourcetype", "resourceType@s") .name("Resource Type") - .description("Represents the types of resources in the game, such as woods and stones.", autoGenMessage()) + .description("Represents the types of resources in the game, such as woods and stones.") .since("1.0.0") .toStringFunction(ResourceType::getId) .register(); reg.newAssetStoreType(RootInteraction.class, RootInteraction.getAssetMap(), "rootinteraction", "rootinteraction@s") .name("Interaction - Root") - .description("Represents the types of root interactions that can be performed by entities.", autoGenMessage()) + .description("Represents the types of root interactions that can be performed by entities.") .since("INSERT VERSION") .register(); reg.newAssetStoreType(SoundEvent.class, SoundEvent.getAssetMap(), "soundevent", "soundevent@s") .name("Sound Event") - .description("Represents the types of sounds in the game.", autoGenMessage()) + .description("Represents the types of sounds in the game.") .since("1.0.0") .toStringFunction(SoundEvent::getId) .register(); reg.newAssetStoreType(Weather.class, Weather.getAssetMap(), "weather", "weather@s") .name("Weather") - .description("Represents the types of weather in the game.", autoGenMessage()) + .description("Represents the types of weather in the game.") .since("1.0.0") .toStringFunction(Weather::getId) .register(); } + // Keep for later, might use down the road! private static String autoGenMessage() { String serverVersion = ManifestUtil.getImplementationVersion(); String patchline = ManifestUtil.getPatchline(); From 1c06ca5d1de03014c966280ef7d552fcde74d29c Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Fri, 6 Feb 2026 09:45:19 -0800 Subject: [PATCH 29/61] Use new function methods --- .../api/skript/docs/JsonDocPrinter.java | 11 ++++----- .../api/skript/docs/MarkdownDocPrinter.java | 7 +++--- .../plugin/elements/ElementRegistration.java | 2 +- .../elements/functions/DefaultFunctions.java | 23 ++++++++++--------- 4 files changed, 22 insertions(+), 21 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 88b9fa6a..35028c5f 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 @@ -86,8 +86,10 @@ public void printDocs() { // FUNCTIONS Utils.log(this.sender, "Printing functions"); - // TODO functions need to be linked to an addon or something printFunctions(mainDocs, this.registration); + if (this.includeSkriptParser) { + printFunctions(mainDocs, parserRegistration); + } // EFFECTS Utils.log(this.sender, "Printing effects"); @@ -208,9 +210,8 @@ private void printExpressions(BsonDocument mainDocs, SkriptRegistration registra @SuppressWarnings("unchecked") private void printFunctions(BsonDocument mainDocs, SkriptRegistration registration) { - String addonKey = registration.getRegisterer().getAddonName().toLowerCase(Locale.ROOT).replace(" ", "_"); BsonArray functionsArray = mainDocs.getArray("functions", new BsonArray()); - Functions.getJavaFunctions().stream().sorted(Comparator.comparing(Function::getName)).forEach(function -> { + Functions.getJavaFunctions(registration).stream().sorted(Comparator.comparing(Function::getName)).forEach(function -> { if (function instanceof JavaFunction jf) { Documentation documentation = jf.getDocumentation(); if (documentation.isNoDoc()) return; @@ -219,10 +220,8 @@ private void printFunctions(BsonDocument mainDocs, SkriptRegistration registrati String name = documentation.getName(); if (name == null) name = function.getName(); - String id = "function:" + addonKey + ":" + name.toLowerCase(Locale.ROOT).replace(" ", "_"); - functionDoc.put("name", new BsonString(name)); - functionDoc.put("id", new BsonString(id)); + functionDoc.put("id", getId("function", name)); // Create params FunctionParameter[] parameters = jf.getParameters(); 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 0c2ba3f3..b350506a 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 @@ -111,7 +111,8 @@ public static void printDocs() { Utils.log("Printing functions"); file = getFile("functions"); writer = new PrintWriter(file, StandardCharsets.UTF_8); - printFunctions(writer); + printFunctions(writer, registration); + printFunctions(writer, Parser.getMainRegistration()); writer.close(); Utils.log("Documentation printed!"); @@ -200,8 +201,8 @@ private static void printExpressions(PrintWriter exprWriter, PrintWriter condWri } @SuppressWarnings("unchecked") - private static void printFunctions(PrintWriter writer) { - Functions.getJavaFunctions().stream().sorted(Comparator.comparing(Function::getName)).forEach(function -> { + private static void printFunctions(PrintWriter writer, SkriptRegistration reg) { + Functions.getJavaFunctions(reg).stream().sorted(Comparator.comparing(Function::getName)).forEach(function -> { if (function instanceof JavaFunction jf) { FunctionParameter[] parameters = jf.getParameters(); diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/ElementRegistration.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/ElementRegistration.java index ac48ae54..7954536a 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/ElementRegistration.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/ElementRegistration.java @@ -55,7 +55,7 @@ public void registerElements() { EventHandler.register(this.registration); // FUNCTIONS - DefaultFunctions.register(); + DefaultFunctions.register(this.registration); // COMMAND ScriptCommand.register(this.registration); diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/functions/DefaultFunctions.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/functions/DefaultFunctions.java index 373135a0..9074ad04 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/functions/DefaultFunctions.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/functions/DefaultFunctions.java @@ -1,5 +1,6 @@ package com.github.skriptdev.skript.plugin.elements.functions; +import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; import com.hypixel.hytale.math.vector.Location; import com.hypixel.hytale.math.vector.Vector3d; import com.hypixel.hytale.math.vector.Vector3f; @@ -15,13 +16,13 @@ public class DefaultFunctions { - public static void register() { - itemFunctions(); - positionFunctions(); + public static void register(SkriptRegistration reg) { + itemFunctions(reg); + positionFunctions(reg); } - private static void itemFunctions() { - Functions.newJavaFunction(new JavaFunction<>( + private static void itemFunctions(SkriptRegistration reg) { + Functions.newJavaFunction(reg, new JavaFunction<>( "itemstack", new FunctionParameter[]{ new FunctionParameter<>("type", Item.class, true), @@ -50,8 +51,8 @@ public ItemStack[] executeSimple(Object[][] params) { .register(); } - private static void positionFunctions() { - Functions.newJavaFunction(new JavaFunction<>( + private static void positionFunctions(SkriptRegistration reg) { + Functions.newJavaFunction(reg, new JavaFunction<>( "location", new FunctionParameter[]{ new FunctionParameter<>("x", Number.class, true), @@ -76,7 +77,7 @@ public Location[] executeSimple(Object[][] params) { .since("1.0.0") .register(); - Functions.newJavaFunction(new JavaFunction<>( + Functions.newJavaFunction(reg,new JavaFunction<>( "vector3i", new FunctionParameter[]{ new FunctionParameter<>("x", Number.class, true), @@ -99,7 +100,7 @@ public Vector3i[] executeSimple(Object[][] params) { .since("1.0.0") .register(); - Functions.newJavaFunction(new JavaFunction<>( + Functions.newJavaFunction(reg, new JavaFunction<>( "vector3f", new FunctionParameter[]{ new FunctionParameter<>("x", Number.class, true), @@ -122,7 +123,7 @@ public Vector3f[] executeSimple(Object[][] params) { .since("1.0.0") .register(); - Functions.newJavaFunction(new JavaFunction<>( + Functions.newJavaFunction(reg, new JavaFunction<>( "vector3d", new FunctionParameter[]{ new FunctionParameter<>("x", Number.class, true), @@ -145,7 +146,7 @@ public Vector3d[] executeSimple(Object[][] params) { .since("1.0.0") .register(); - Functions.newJavaFunction(new JavaFunction<>( + Functions.newJavaFunction(reg, new JavaFunction<>( "world", new FunctionParameter[]{ new FunctionParameter<>("name", String.class, true) From d96d034308e65cedd3f8f19016511a9cf8396495 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Fri, 6 Feb 2026 09:59:01 -0800 Subject: [PATCH 30/61] JsonDocPrinter - replace parse tags in patterns --- .../skriptdev/skript/api/skript/docs/JsonDocPrinter.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) 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 35028c5f..ad0c3f9e 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 @@ -413,7 +413,11 @@ private void printDocumentation(String type, BsonDocument syntaxDoc, SyntaxInfo< List patterns = syntaxInfo.getPatterns(); if (!patterns.isEmpty()) { BsonArray patternArray = new BsonArray(); - patterns.forEach(pattern -> patternArray.add(new BsonString(pattern.toString()))); + patterns.forEach(pattern -> { + // Remove parse tags in patterns, ex: "(blah:blah|bloop:bloop)" + String removedParseTags = pattern.toString().replaceAll("[^()\\[\\]|:\\s]*:", ""); + patternArray.add(new BsonString(removedParseTags)); + }); syntaxDoc.put("patterns", patternArray); } From e85fbfc743b2389c98c040629b6258a676668a2d Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Fri, 6 Feb 2026 10:13:40 -0800 Subject: [PATCH 31/61] Skript - add a checkstyle test to see if the build fails --- src/main/java/com/github/skriptdev/skript/plugin/Skript.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/github/skriptdev/skript/plugin/Skript.java b/src/main/java/com/github/skriptdev/skript/plugin/Skript.java index 203b5d00..46219e2b 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/Skript.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/Skript.java @@ -93,6 +93,8 @@ private void setup() { this.scriptsLoader = new ScriptsLoader(this); this.scriptsLoader.loadScripts(null, this.scriptsPath, false); + String s = "testing a really long line to make sure build fails with checkstype.... so that i can remove the checksyle workflow because it seems to run twice and i dont really need to have it run twice, plus it keeps failing cause its being silly billy"; + // FINALIZE SCRIPT LOADING Parser.getMainRegistration().getRegisterer().finishedLoading(); } From 06a22583060ecad094d1d86e9be953817952778e Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Fri, 6 Feb 2026 10:16:02 -0800 Subject: [PATCH 32/61] Skript - remove test string --- src/main/java/com/github/skriptdev/skript/plugin/Skript.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/com/github/skriptdev/skript/plugin/Skript.java b/src/main/java/com/github/skriptdev/skript/plugin/Skript.java index 46219e2b..203b5d00 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/Skript.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/Skript.java @@ -93,8 +93,6 @@ private void setup() { this.scriptsLoader = new ScriptsLoader(this); this.scriptsLoader.loadScripts(null, this.scriptsPath, false); - String s = "testing a really long line to make sure build fails with checkstype.... so that i can remove the checksyle workflow because it seems to run twice and i dont really need to have it run twice, plus it keeps failing cause its being silly billy"; - // FINALIZE SCRIPT LOADING Parser.getMainRegistration().getRegisterer().finishedLoading(); } From 8f7abec25956b9b13e30787670b9419b086a7c79 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Fri, 6 Feb 2026 10:19:35 -0800 Subject: [PATCH 33/61] checkstyle.yml - remove as it also runs in build --- .github/workflows/checkstyle.yml | 37 -------------------------------- 1 file changed, 37 deletions(-) delete mode 100644 .github/workflows/checkstyle.yml diff --git a/.github/workflows/checkstyle.yml b/.github/workflows/checkstyle.yml deleted file mode 100644 index 1e583b60..00000000 --- a/.github/workflows/checkstyle.yml +++ /dev/null @@ -1,37 +0,0 @@ -name: checkstyle - -on: - push: - branches: - - master - - 'dev/**' - pull_request: - -jobs: - build: - if: "! contains(toJSON(github.event.commits.*.message), '[ci skip]')" - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v6 - with: - submodules: recursive - - name: validate gradle wrapper - uses: gradle/actions/wrapper-validation@v5 - - name: Set up JDK 25 - uses: actions/setup-java@v5 - with: - java-version: '25' - distribution: 'adopt' - cache: gradle - - name: Grant execute permission for gradlew - run: chmod +x gradlew - - name: Run checkstyle - run: ./gradlew clean checkstyleMain - - name: Upload checkstyle report - uses: actions/upload-artifact@v6 - if: success() - with: - name: checkstyle-report - path: | - build/reports/checkstyle/*.xml - build/reports/checkstyle/*.html From 812542394da55caf38e56fc1641a81fb8604d265 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Fri, 6 Feb 2026 11:50:54 -0800 Subject: [PATCH 34/61] Types - added NotificationStyle --- .../skriptdev/skript/plugin/elements/types/TypesServer.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesServer.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesServer.java index 775c9f53..9cfded47 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesServer.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesServer.java @@ -10,6 +10,7 @@ import com.hypixel.hytale.math.vector.Vector3f; import com.hypixel.hytale.math.vector.Vector3i; import com.hypixel.hytale.protocol.Vector2f; +import com.hypixel.hytale.protocol.packets.interface_.NotificationStyle; import com.hypixel.hytale.server.core.HytaleServer; import com.hypixel.hytale.server.core.Message; import com.hypixel.hytale.server.core.command.system.CommandSender; @@ -70,6 +71,11 @@ public Message deserialize(@NotNull Gson gson, @NotNull JsonElement element) { } }) .register(); + registration.newEnumType(NotificationStyle.class, "notificationstyle", "notificationStyle@s") + .name("Notification Style") + .description("Represents the style of a notification sent to players.") + .since("INSERT VERSION") + .register(); registration.newType(HytaleServer.class, "server", "server@s") .name("Server") .description("Represents the Hytale server.") From 8125d9e01bb10e33b01230440e32b6c71c215174 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Fri, 6 Feb 2026 11:51:09 -0800 Subject: [PATCH 35/61] SecSendNotification - add buggy notification section --- .../sections/SecSendNotification.java | 161 ++++++++++++++++++ .../elements/sections/SectionHandler.java | 1 + 2 files changed, 162 insertions(+) create mode 100644 src/main/java/com/github/skriptdev/skript/plugin/elements/sections/SecSendNotification.java diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/sections/SecSendNotification.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/sections/SecSendNotification.java new file mode 100644 index 00000000..ed200687 --- /dev/null +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/sections/SecSendNotification.java @@ -0,0 +1,161 @@ +package com.github.skriptdev.skript.plugin.elements.sections; + +import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; +import com.hypixel.hytale.component.Store; +import com.hypixel.hytale.protocol.ItemWithAllMetadata; +import com.hypixel.hytale.protocol.packets.interface_.NotificationStyle; +import com.hypixel.hytale.server.core.Message; +import com.hypixel.hytale.server.core.entity.entities.Player; +import com.hypixel.hytale.server.core.inventory.ItemStack; +import com.hypixel.hytale.server.core.io.PacketHandler; +import com.hypixel.hytale.server.core.universe.PlayerRef; +import com.hypixel.hytale.server.core.universe.world.World; +import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; +import com.hypixel.hytale.server.core.util.NotificationUtil; +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 java.util.Optional; + +public class SecSendNotification extends CodeSection { + + public static void register(SkriptRegistration reg) { + reg.newSection(SecSendNotification.class, + "send notification %string/message% [to %players/playerrefs/worlds%]") + .name("Send Notification") + .description("Send a notification to players, worlds, or the universe.", + "**Entries**:", + "- `secondary-message`: Optional secondary message to display in the notification.", + "- `itemstack`: Optional itemstack to display in the notification.", + "- `icon`: Optional icon to display in the notification.", + "- `style`: Optional style to use for the notification.") + .examples("send notification \"Hello Player!\" to player:", + "\titemstack: itemstack of ingredient_stick", + "send notification \"You better be careful!!!\" to world of player:", + "\titemstack: itemstack of deco_fire", + "\tstyle: danger") + .experimental("Notifications are currently experimental and may change in the future." + + "ItemStack seems broken, as well as secondary-message not working. Could be server bugs.") + .since("INSERT VERSION") + .register(); + } + + SectionConfiguration config = new SectionConfiguration.Builder() + .addOptionalExpression("secondary-message", Object.class, false) + .addOptionalExpression("itemstack", ItemStack.class, false) + .addOptionalExpression("icon", String.class, false) + .addOptionalExpression("style", NotificationStyle.class, false) + .build(); + + private Expression message; + private Expression receivers; + + @Override + public boolean init(Expression @NotNull [] expressions, int matchedPattern, @NotNull ParseContext parseContext) { + this.message = expressions[0]; + if (expressions.length > 1) { + this.receivers = expressions[1]; + } + return true; + } + + @Override + public boolean loadSection(@NotNull FileSection section, @NotNull ParserState parserState, @NotNull SkriptLogger logger) { + return this.config.loadConfiguration(null, section, parserState, logger); + } + + @SuppressWarnings({"removal"}) + @Override + public Optional walk(@NotNull TriggerContext ctx) { + Optional nextStatement = getNext(); + + Object o = this.message.getSingle(ctx).orElse(null); + Message message; + if (o instanceof String s) { + message = Message.raw(s); + } else if (o instanceof Message m) { + message = m; + } else { + return nextStatement; + } + + Message secondary = Message.empty(); + Optional> sExp = this.config.getExpression("secondary-message", Object.class); + if (sExp.isPresent()) { + Optional single = sExp.get().getSingle(ctx); + if (single.isPresent()) { + Object o1 = single.get(); + if (o1 instanceof String s1) { + secondary = Message.raw(s1); + } else if (o1 instanceof Message m1) { + secondary = m1; + } + } + } + + ItemStack itemStack = null; + Optional> isExp = this.config.getExpression("itemstack", ItemStack.class); + if (isExp.isPresent()) { + Optional single = isExp.get().getSingle(ctx); + if (single.isPresent()) { + itemStack = single.get(); + } + } + ItemWithAllMetadata itemWithAllMetadata = itemStack != null ? itemStack.toPacket() : null; + + String icon = null; + Optional> iconExp = this.config.getExpression("icon", String.class); + if (iconExp.isPresent()) { + Optional single = iconExp.get().getSingle(ctx); + if (single.isPresent()) { + icon = single.get(); + } + } + + NotificationStyle style = NotificationStyle.Default; + Optional> styleExp = this.config.getExpression("style", NotificationStyle.class); + if (styleExp.isPresent()) { + Optional single = styleExp.get().getSingle(ctx); + if (single.isPresent()) { + style = single.get(); + } + } + + if (this.receivers != null) { + for (Object object : this.receivers.getArray(ctx)) { + if (object instanceof World world) { + Store store = world.getEntityStore().getStore(); + NotificationUtil.sendNotificationToWorld(message, secondary, icon, + itemWithAllMetadata, style, store); + } else if (object instanceof Player player) { + PacketHandler packetHandler = player.getPlayerRef().getPacketHandler(); + NotificationUtil.sendNotification(packetHandler, message, + secondary, icon, itemWithAllMetadata, style); + } else if (object instanceof PlayerRef playerRef) { + PacketHandler packetHandler = playerRef.getPacketHandler(); + NotificationUtil.sendNotification(packetHandler, message, + secondary, icon, itemWithAllMetadata, style); + } + } + } else { + NotificationUtil.sendNotificationToUniverse(message, secondary, icon, itemWithAllMetadata, style); + } + + return nextStatement; + } + + @Override + public String toString(@NotNull TriggerContext ctx, boolean debug) { + String to = this.receivers != null ? this.receivers.toString(ctx, debug) : "the universe"; + return "Send notification " + this.message.toString(ctx, debug) + " to " + to; + } + +} 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 0c25581e..0f5be780 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 @@ -8,6 +8,7 @@ public static void register(SkriptRegistration registration) { SecDropItem.register(registration); SecExecuteInWorld.register(registration); SecPlaySound.register(registration); + SecSendNotification.register(registration); SecSpawnNPC.register(registration); } From a3f10473a22ecb72552d650f0d106ad39e6dc0a3 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Fri, 6 Feb 2026 12:09:32 -0800 Subject: [PATCH 36/61] SecSendNotification - some fixes --- .../plugin/elements/sections/SecSendNotification.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/sections/SecSendNotification.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/sections/SecSendNotification.java index ed200687..da5c5cce 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/sections/SecSendNotification.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/sections/SecSendNotification.java @@ -36,14 +36,14 @@ public static void register(SkriptRegistration reg) { "- `secondary-message`: Optional secondary message to display in the notification.", "- `itemstack`: Optional itemstack to display in the notification.", "- `icon`: Optional icon to display in the notification.", - "- `style`: Optional style to use for the notification.") + "- `style`: Optional style to use for the notification.", + "**NOTE**: Regarding ItemStacks, if you send multiple notifications with the same ItemStack, " + + "the client will stack them and just keep adding quantity.") .examples("send notification \"Hello Player!\" to player:", "\titemstack: itemstack of ingredient_stick", "send notification \"You better be careful!!!\" to world of player:", "\titemstack: itemstack of deco_fire", "\tstyle: danger") - .experimental("Notifications are currently experimental and may change in the future." + - "ItemStack seems broken, as well as secondary-message not working. Could be server bugs.") .since("INSERT VERSION") .register(); } @@ -87,7 +87,7 @@ public Optional walk(@NotNull TriggerContext ctx) { return nextStatement; } - Message secondary = Message.empty(); + Message secondary = null; Optional> sExp = this.config.getExpression("secondary-message", Object.class); if (sExp.isPresent()) { Optional single = sExp.get().getSingle(ctx); From 21fec5dcf1a41dc7d4a634d0e3e1f3c58df4f16f Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Fri, 6 Feb 2026 12:46:07 -0800 Subject: [PATCH 37/61] ScriptsLoader - don't load scripts prefixed with a hyphen - These are disbaled scripts --- .../github/skriptdev/skript/api/skript/ScriptsLoader.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/github/skriptdev/skript/api/skript/ScriptsLoader.java b/src/main/java/com/github/skriptdev/skript/api/skript/ScriptsLoader.java index f690f608..6dd5da7b 100644 --- a/src/main/java/com/github/skriptdev/skript/api/skript/ScriptsLoader.java +++ b/src/main/java/com/github/skriptdev/skript/api/skript/ScriptsLoader.java @@ -63,14 +63,15 @@ public List loadScriptsInDirectory(IMessageReceiver receiver, File direc if (file.isDirectory()) { loadedScripts.addAll(loadScriptsInDirectory(receiver, file)); } else { - if (!file.getName().endsWith(".sk")) continue; - Utils.log(receiver, "Loading script '" + file.getName() + "'..."); + String fileName = file.getName(); + if (!fileName.endsWith(".sk") || fileName.startsWith("-")) continue; + Utils.log(receiver, "Loading script '" + fileName + "'..."); List logEntries = ScriptLoader.loadScript(file.toPath(), false); this.loadedScriptCount++; for (LogEntry logEntry : logEntries) { Utils.log(receiver, logEntry); } - loadedScripts.add(file.getName().substring(0, file.getName().length() - 3)); + loadedScripts.add(fileName.substring(0, fileName.length() - 3)); } } return loadedScripts; From ae46209c0300c561da4861f51eeb8866403fa708 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Fri, 6 Feb 2026 12:53:55 -0800 Subject: [PATCH 38/61] ScriptsLoader - skip loading disable files and hidden files --- .../github/skriptdev/skript/api/skript/ScriptsLoader.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/github/skriptdev/skript/api/skript/ScriptsLoader.java b/src/main/java/com/github/skriptdev/skript/api/skript/ScriptsLoader.java index 6dd5da7b..dd9998c2 100644 --- a/src/main/java/com/github/skriptdev/skript/api/skript/ScriptsLoader.java +++ b/src/main/java/com/github/skriptdev/skript/api/skript/ScriptsLoader.java @@ -60,11 +60,13 @@ public List loadScriptsInDirectory(IMessageReceiver receiver, File direc .thenComparing(File::getName, String.CASE_INSENSITIVE_ORDER)); // Then sort by name alphabetically for (File file : files) { + // Skip disabled files and hidden files + String fileName = file.getName(); + if (fileName.startsWith("-") || fileName.startsWith(".")) continue; if (file.isDirectory()) { loadedScripts.addAll(loadScriptsInDirectory(receiver, file)); } else { - String fileName = file.getName(); - if (!fileName.endsWith(".sk") || fileName.startsWith("-")) continue; + if (!fileName.endsWith(".sk")) continue; Utils.log(receiver, "Loading script '" + fileName + "'..."); List logEntries = ScriptLoader.loadScript(file.toPath(), false); this.loadedScriptCount++; From 06d9f935211b3feabd4cf9c1ff72b0e05e34567d Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Fri, 6 Feb 2026 13:24:32 -0800 Subject: [PATCH 39/61] ScriptCommandBuilder - Fix sub commands not adopting the type of their parent --- .../skript/api/skript/command/ScriptCommandBuilder.java | 5 +++-- .../skript/plugin/elements/command/ScriptCommand.java | 2 +- .../skript/plugin/elements/command/ScriptSubCommand.java | 3 +-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/github/skriptdev/skript/api/skript/command/ScriptCommandBuilder.java b/src/main/java/com/github/skriptdev/skript/api/skript/command/ScriptCommandBuilder.java index 89b114c1..c6c02bf0 100644 --- a/src/main/java/com/github/skriptdev/skript/api/skript/command/ScriptCommandBuilder.java +++ b/src/main/java/com/github/skriptdev/skript/api/skript/command/ScriptCommandBuilder.java @@ -92,7 +92,8 @@ public boolean parseCommandLine(String commandLine) { return true; } - public List setupCommand(FileSection section, ParserState parserState, SkriptLogger logger) { + public List setupCommand(FileSection section, ParserState parserState, SkriptLogger logger, int commandType) { + this.commandType = commandType; this.sec.loadConfiguration(null, section, parserState, logger); Optional triggerSec = this.sec.getSection("trigger"); @@ -115,7 +116,7 @@ public List setupCommand(FileSection section, ParserState parserState return List.of(); } - this.hyCommand = switch (this.commandType) { + this.hyCommand = switch (commandType) { case 1 -> new AbstractPlayerCommand(this.commandName, description) { @Override protected void execute(@NotNull CommandContext commandContext, @NotNull Store store, diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/command/ScriptCommand.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/command/ScriptCommand.java index 63d8ba9f..47a8ca56 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/command/ScriptCommand.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/command/ScriptCommand.java @@ -137,7 +137,7 @@ public boolean init(Expression @NotNull [] expressions, int matchedPattern, P @Override public List loadSection(@NotNull FileSection section, @NotNull ParserState parserState, @NotNull SkriptLogger logger) { - List statements = this.commandBuilder.setupCommand(section, parserState, logger); + List statements = this.commandBuilder.setupCommand(section, parserState, logger, this.commandType); this.commandBuilder.build(null); return statements; } diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/command/ScriptSubCommand.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/command/ScriptSubCommand.java index 991e54f1..1d2d2475 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/command/ScriptSubCommand.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/command/ScriptSubCommand.java @@ -39,8 +39,7 @@ public boolean init(Expression @NotNull [] expressions, int matchedPattern, @ @Override public void loadChild(ScriptCommandBuilder parent, SkriptLogger logger) { - this.commandBuilder.setupCommand(this.section, this.parserState, logger); - this.commandBuilder.commandType = parent.getCommandType(); + this.commandBuilder.setupCommand(this.section, this.parserState, logger, parent.getCommandType()); this.commandBuilder.build(parent); } From 2444f004cb40c4ecd2a208c97450e3e0e2b65e50 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Fri, 6 Feb 2026 13:37:36 -0800 Subject: [PATCH 40/61] EvtPlayerAddToWorld - add should broadcast context --- .../events/player/EvtPlayerAddToWorld.java | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) 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 0e980df2..e9f68d87 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 @@ -14,12 +14,14 @@ import io.github.syst3ms.skriptparser.lang.TriggerMap; import io.github.syst3ms.skriptparser.lang.event.SkriptEvent; import io.github.syst3ms.skriptparser.parsing.ParseContext; +import org.jetbrains.annotations.NotNull; public class EvtPlayerAddToWorld extends SkriptEvent { public static void register(SkriptRegistration reg) { reg.newEvent(EvtPlayerAddToWorld.class, "player added to world", "add player to world") + .setHandledContexts(AddContext.class) .name("Player Add To World") .description("Called when a player joins a world.") .examples("on player added to world:", @@ -28,6 +30,9 @@ public static void register(SkriptRegistration reg) { .register(); reg.addSingleContextValue(AddContext.class, World.class, "world", AddContext::getWorld); + reg.newSingleContextValue(AddContext.class, Boolean.class, "should-broadcast", AddContext::shouldBroadcast) + .addSetter(AddContext::setShouldBroadcast) + .register(); } private static EventRegistration LISTENER; @@ -49,7 +54,7 @@ public boolean check(TriggerContext triggerContext) { } @Override - public String toString(TriggerContext ctx, boolean debug) { + public String toString(@NotNull TriggerContext ctx, boolean debug) { return ""; } @@ -61,8 +66,15 @@ public World getWorld() { public Player getPlayer() { Holder holder = this.event.getHolder(); - Player component = holder.getComponent(Player.getComponentType()); - return component; + return holder.getComponent(Player.getComponentType()); + } + + public boolean shouldBroadcast() { + return this.event.shouldBroadcastJoinMessage(); + } + + public void setShouldBroadcast(boolean shouldBroadcast) { + this.event.setBroadcastJoinMessage(shouldBroadcast); } @Override From 36264ee5dacd5e0bb105e21d6c5ffbb332107447 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Fri, 6 Feb 2026 14:13:18 -0800 Subject: [PATCH 41/61] Add some sample scripts --- .../skript/api/skript/ScriptsLoader.java | 22 +++++++-- .../skriptdev/skript/api/utils/FileUtils.java | 45 +++++++++++++++++++ .../-file-starting-with-hyphen-is-disabled.sk | 1 + .../resources/sample-scripts/chat-format.sk | 5 +++ .../resources/sample-scripts/home-command.sk | 40 +++++++++++++++++ .../resources/sample-scripts/join-message.sk | 10 +++++ 6 files changed, 119 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/github/skriptdev/skript/api/utils/FileUtils.java create mode 100644 src/main/resources/sample-scripts/-file-starting-with-hyphen-is-disabled.sk create mode 100644 src/main/resources/sample-scripts/chat-format.sk create mode 100644 src/main/resources/sample-scripts/home-command.sk create mode 100644 src/main/resources/sample-scripts/join-message.sk diff --git a/src/main/java/com/github/skriptdev/skript/api/skript/ScriptsLoader.java b/src/main/java/com/github/skriptdev/skript/api/skript/ScriptsLoader.java index dd9998c2..3502226a 100644 --- a/src/main/java/com/github/skriptdev/skript/api/skript/ScriptsLoader.java +++ b/src/main/java/com/github/skriptdev/skript/api/skript/ScriptsLoader.java @@ -1,5 +1,6 @@ package com.github.skriptdev.skript.api.skript; +import com.github.skriptdev.skript.api.utils.FileUtils; import com.github.skriptdev.skript.api.utils.Utils; import com.github.skriptdev.skript.plugin.Skript; import com.hypixel.hytale.server.core.receiver.IMessageReceiver; @@ -8,6 +9,8 @@ import io.github.syst3ms.skriptparser.parsing.ScriptLoader; import java.io.File; +import java.io.IOException; +import java.net.URISyntaxException; import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; @@ -28,14 +31,25 @@ public void loadScripts(IMessageReceiver receiver, Path directory, boolean reloa Utils.log(receiver, (reload ? "Reloading" : "Loading") + " scripts..."); long start = System.currentTimeMillis(); - File directoryFile = directory.toFile(); - if (!directoryFile.isDirectory()) { - if (!directoryFile.mkdirs()) { + File scriptsDirectory = directory.toFile(); + if (!scriptsDirectory.isDirectory()) { + if (!scriptsDirectory.mkdirs()) { Utils.error("Failed to create scripts directory!"); + return; + } + try { + // Add sample scripts when creating a new scripts folder + File scriptsDir = new File(scriptsDirectory, "-sample-scripts"); + if (!scriptsDir.mkdir()) { + throw new RuntimeException("Failed to create sample scripts directory"); + } + FileUtils.copyFromJar("/sample-scripts/", scriptsDir.toPath()); + } catch (IOException | URISyntaxException e) { + Utils.error("Failed to load sample scripts, message: %s", e.getMessage()); } } - List scriptNames = loadScriptsInDirectory(receiver, directoryFile); + List scriptNames = loadScriptsInDirectory(receiver, scriptsDirectory); long end = System.currentTimeMillis() - start; Utils.log(receiver, (reload ? "Reloaded" : "Loaded") + " %s scripts in %sms", this.loadedScriptCount, end); diff --git a/src/main/java/com/github/skriptdev/skript/api/utils/FileUtils.java b/src/main/java/com/github/skriptdev/skript/api/utils/FileUtils.java new file mode 100644 index 00000000..b947e486 --- /dev/null +++ b/src/main/java/com/github/skriptdev/skript/api/utils/FileUtils.java @@ -0,0 +1,45 @@ +package com.github.skriptdev.skript.api.utils; + +import com.github.skriptdev.skript.plugin.HySk; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; +import java.util.Collections; + +/** + * Utilities for working with files. + */ +public class FileUtils { + + public static void copyFromJar(String sourceInsideJar, Path targetDir) throws IOException, URISyntaxException { + // Get the URI of the resource inside the JAR + URI uri = HySk.class.getResource(sourceInsideJar).toURI(); + + // If the resource is inside a JAR, we need to create a FileSystem for it + try (FileSystem jarFileSystem = FileSystems.newFileSystem(uri, Collections.emptyMap())) { + Path pathInJar = jarFileSystem.getPath(sourceInsideJar); + + // Walk the tree and copy everything + Files.walk(pathInJar).forEach(source -> { + try { + // Create the corresponding path in the target directory + Path destination = targetDir.resolve(pathInJar.relativize(source).toString()); + + if (Files.isDirectory(source)) { + if (!Files.exists(destination)) Files.createDirectories(destination); + } else { + Files.copy(source, destination, StandardCopyOption.REPLACE_EXISTING); + } + } catch (IOException e) { + throw new RuntimeException("Failed to copy: " + source, e); + } + }); + } +} +} diff --git a/src/main/resources/sample-scripts/-file-starting-with-hyphen-is-disabled.sk b/src/main/resources/sample-scripts/-file-starting-with-hyphen-is-disabled.sk new file mode 100644 index 00000000..90d1fdb9 --- /dev/null +++ b/src/main/resources/sample-scripts/-file-starting-with-hyphen-is-disabled.sk @@ -0,0 +1 @@ +# Any script file or directory starting with a hyphen is disabled. diff --git a/src/main/resources/sample-scripts/chat-format.sk b/src/main/resources/sample-scripts/chat-format.sk new file mode 100644 index 00000000..7c0a84fc --- /dev/null +++ b/src/main/resources/sample-scripts/chat-format.sk @@ -0,0 +1,5 @@ +# Chat Format +# A simple way to make your chat look a little nicer + +on player chat: + set context-message-format to formatted "[MyServer] %name of context-playerref%: %context-message%" diff --git a/src/main/resources/sample-scripts/home-command.sk b/src/main/resources/sample-scripts/home-command.sk new file mode 100644 index 00000000..418c013a --- /dev/null +++ b/src/main/resources/sample-scripts/home-command.sk @@ -0,0 +1,40 @@ +# Home Command +# A little home command where players can set/delete homes and teleport to them + +player command /home: + description: "Access to your homes" + permission: "myscript.homes" + sub command /set : + description: "Set a home" + permission: "myscript.homes.set" + trigger: + set {homes::%uuid of player%::%{_name}%} to location of player + send "Set home %{_name}% to your location" + sub command /delete : + description: "Delete a home" + permission: "myscript.homes.delete" + trigger: + if {homes::%uuid of player%::%{_name}%} is set: + delete {homes::%uuid of player%::%{_name}%} + send "Home %{_name}% delete" + else: + send "No home named %{_name}% was found" + sub command /tp : + description: "Teleport to a home" + permission: "myscript.homes.teleport" + trigger: + if {homes::%uuid of player%::%{_name}%} is set: + teleport player to {homes::%uuid of player%::%{_name}%} + send "Teleport to %{_name}%" + else: + send "No home named %{_name}% was found" + sub command /list: + description: "List all your homes" + permission: "myscript.homes.list" + trigger: + if {homes::%uuid of player%::*} is empty: + send "You have no homes set" + else: + send "Your homes:" + loop {homes::%uuid of player%::*}: + send " - %loop-index%" diff --git a/src/main/resources/sample-scripts/join-message.sk b/src/main/resources/sample-scripts/join-message.sk new file mode 100644 index 00000000..66b82c87 --- /dev/null +++ b/src/main/resources/sample-scripts/join-message.sk @@ -0,0 +1,10 @@ +# Join Message +# Be welcomeing to your players + +on player added to world: + # This prevents the player joined world message + set context-should-broadcast to false + +on player ready: + # When they actually join, let's send a nice message + send formatted "[MyServer] Welcome to our server %name of context-player%" From 1088b02b413ed632b65334831021fc8ad4644e7f Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Fri, 6 Feb 2026 14:30:25 -0800 Subject: [PATCH 42/61] build.gradle.kts - update Hytale to release version and add to manifest --- build.gradle.kts | 4 ++-- src/main/resources/manifest.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index ff2e2287..e02b7483 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -9,7 +9,7 @@ java.sourceCompatibility = JavaVersion.VERSION_25 group = "com.github.SkriptDev" val projectVersion = "1.0.0-beta5" -val hytaleVersion = "2026.01.29-301e13929" +val hytaleVersion = "2026.02.06-aa1b071c2" // You can find Hytale versions on their maven repo: // https://maven.hytale.com/release/com/hypixel/hytale/Server/maven-metadata.xml // https://maven.hytale.com/pre-release/com/hypixel/hytale/Server/maven-metadata.xml @@ -44,7 +44,7 @@ tasks { } processResources { filesNotMatching("assets/**") { - expand("pluginVersion" to projectVersion) + expand("pluginVersion" to projectVersion, "hytaleVersion" to hytaleVersion) } } compileJava { diff --git a/src/main/resources/manifest.json b/src/main/resources/manifest.json index 633b0267..1ce6c831 100644 --- a/src/main/resources/manifest.json +++ b/src/main/resources/manifest.json @@ -9,7 +9,7 @@ } ], "Website": "https://github.com/SkriptDev/HySkript", - "ServerVersion": "*", + "ServerVersion": ">=$hytaleVersion", "Dependencies": {}, "OptionalDependencies": {}, "DisabledByDefault": false, From 3722dd8318a211eea10c9114f31665c738f05ccb Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Fri, 6 Feb 2026 14:38:43 -0800 Subject: [PATCH 43/61] manifest.json - add contributors link to authors --- .editorconfig | 2 ++ src/main/resources/manifest.json | 7 ++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/.editorconfig b/.editorconfig index 89a52330..772fe705 100644 --- a/.editorconfig +++ b/.editorconfig @@ -15,6 +15,8 @@ ij_java_class_count_to_use_import_on_demand = 1024 ij_java_names_count_to_use_import_on_demand = 1024 [*.yml] indent_size = 2 +[*.json] +indent_size = 2 [*.md] trim_trailing_whitespace=false [*.sk] diff --git a/src/main/resources/manifest.json b/src/main/resources/manifest.json index 1ce6c831..eafc5508 100644 --- a/src/main/resources/manifest.json +++ b/src/main/resources/manifest.json @@ -5,7 +5,12 @@ "Description": "Scripting the most out of your Hytale server.", "Authors": [ { - "Name": "ShaneBee" + "Name": "ShaneBee", + "Url": "https://github.com/ShaneBeee" + }, + { + "Name": "SkriptDev Contributors", + "Url": "https://github.com/SkriptDev/HySkript/graphs/contributors" } ], "Website": "https://github.com/SkriptDev/HySkript", From f04228285b8a955b169c26d39707df3dde82e783 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Fri, 6 Feb 2026 17:42:09 -0800 Subject: [PATCH 44/61] join-message.sk - fix spelling mistake --- src/main/resources/sample-scripts/join-message.sk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/sample-scripts/join-message.sk b/src/main/resources/sample-scripts/join-message.sk index 66b82c87..5d56b6c8 100644 --- a/src/main/resources/sample-scripts/join-message.sk +++ b/src/main/resources/sample-scripts/join-message.sk @@ -1,5 +1,5 @@ # Join Message -# Be welcomeing to your players +# Be welcoming to your players on player added to world: # This prevents the player joined world message From 375a247b982b9d8ecbd755737181bef51141a0c8 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Fri, 6 Feb 2026 18:01:56 -0800 Subject: [PATCH 45/61] EffDelay - add world as an option to prevent thread issues - also added a new WorldContext and added it to a bunch of events --- .../skript/api/skript/event/WorldContext.java | 10 ++ .../elements/effects/other/EffDelay.java | 119 ++++++++++++------ .../plugin/elements/events/EventHandler.java | 6 + .../events/entity/EvtEntityDamage.java | 9 +- .../events/entity/EvtEntityDeath.java | 10 +- .../events/entity/EvtEntityPickupItem.java | 9 +- .../events/entity/EvtEntityRemove.java | 7 +- .../entity/EvtLivingEntityInvChange.java | 12 +- .../events/player/EvtPlayerAddToWorld.java | 5 +- .../events/player/EvtPlayerBreakBlock.java | 8 +- .../player/EvtPlayerChangeGameMode.java | 9 +- .../events/player/EvtPlayerDamageBlock.java | 8 +- .../player/EvtPlayerDrainFromWorld.java | 19 ++- .../events/player/EvtPlayerDropItem.java | 9 +- .../player/EvtPlayerDropItemRequest.java | 9 +- .../events/player/EvtPlayerPlaceBlock.java | 10 +- .../events/player/EvtPlayerUseBlock.java | 8 +- 17 files changed, 199 insertions(+), 68 deletions(-) create mode 100644 src/main/java/com/github/skriptdev/skript/api/skript/event/WorldContext.java diff --git a/src/main/java/com/github/skriptdev/skript/api/skript/event/WorldContext.java b/src/main/java/com/github/skriptdev/skript/api/skript/event/WorldContext.java new file mode 100644 index 00000000..13437904 --- /dev/null +++ b/src/main/java/com/github/skriptdev/skript/api/skript/event/WorldContext.java @@ -0,0 +1,10 @@ +package com.github.skriptdev.skript.api.skript.event; + +import com.hypixel.hytale.server.core.universe.world.World; +import io.github.syst3ms.skriptparser.lang.TriggerContext; + +public interface WorldContext extends TriggerContext { + + World getWorld(); + +} diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/other/EffDelay.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/other/EffDelay.java index 468ba060..32ea422e 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/other/EffDelay.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/other/EffDelay.java @@ -1,5 +1,7 @@ package com.github.skriptdev.skript.plugin.elements.effects.other; +import com.github.skriptdev.skript.api.skript.event.PlayerContext; +import com.github.skriptdev.skript.api.skript.event.WorldContext; import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; import com.github.skriptdev.skript.api.utils.Utils; import com.hypixel.hytale.server.core.HytaleServer; @@ -7,7 +9,6 @@ import com.hypixel.hytale.server.core.universe.world.World; import io.github.syst3ms.skriptparser.lang.Effect; import io.github.syst3ms.skriptparser.lang.Expression; -import io.github.syst3ms.skriptparser.lang.Literal; import io.github.syst3ms.skriptparser.lang.Statement; import io.github.syst3ms.skriptparser.lang.TriggerContext; import io.github.syst3ms.skriptparser.parsing.ParseContext; @@ -18,7 +19,6 @@ import java.util.Optional; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; -import java.util.function.Consumer; public class EffDelay extends Effect { @@ -32,30 +32,51 @@ public static void register(SkriptRegistration registration) { DurationUtils.overrideTickLength(defaultWorld.getTickStepNanos()); registration.newEffect(EffDelay.class, "(wait|halt) [for] %duration%", - "(wait|halt) (0:until|1:while) %=boolean% [for %*duration%]") + "(wait|halt) in [world] %world% [for] %duration%", + "(wait|halt) (0:until|1:while) %=boolean%", + "(wait|halt) in [world] %world% (0:until|1:while) %=boolean%") .name("Delay") - .description("Delays the execution of the next statements for a specified duration.") + .description("Delays the execution of the next statements for a specified duration.", + "Allows for conditional delays based on a boolean condition.", + "Supports execution in specific worlds and conditional.", + "If the world is not provided, a world will be chosen based on the event used.") .since("1.0.0") .register(); } private static final ScheduledExecutorService SCHEDULER = HytaleServer.SCHEDULED_EXECUTOR; private Expression duration; + private Expression world; private Expression condition; private boolean isConditional; private boolean negated; + private int pattern; @SuppressWarnings("unchecked") @Override public boolean init(Expression @NotNull [] expressions, int matchedPattern, @NotNull ParseContext parseContext) { - this.isConditional = matchedPattern == 1; - if (this.isConditional) { - this.condition = (Expression) expressions[0]; - if (expressions.length == 2) - this.duration = (Literal) expressions[1]; - this.negated = parseContext.getNumericMark() == 0; - } else { - this.duration = (Expression) expressions[0]; + this.pattern = matchedPattern; + this.isConditional = matchedPattern > 1; + switch (matchedPattern) { + case 0 -> { + this.duration = (Expression) expressions[0]; + } + case 1 -> { + this.world = (Expression) expressions[0]; + this.duration = (Expression) expressions[1]; + } + case 2 -> { + this.condition = (Expression) expressions[0]; + this.negated = parseContext.getNumericMark() == 0; + } + case 3 -> { + this.world = (Expression) expressions[0]; + this.condition = (Expression) expressions[1]; + this.negated = parseContext.getNumericMark() == 0; + } + default -> { + return false; + } } return true; } @@ -65,54 +86,70 @@ protected void execute(@NotNull TriggerContext ctx) { throw new UnsupportedOperationException(); } - @SuppressWarnings("unchecked") @Override public Optional walk(@NotNull TriggerContext ctx) { - if (getNext().isEmpty()) - return Optional.empty(); + Optional nextOpt = getNext(); + if (nextOpt.isEmpty()) return Optional.empty(); + + Statement nextStatement = nextOpt.get(); + + World world; + if (this.world != null) { + world = this.world.getSingle(ctx).orElse(null); + } else if (ctx instanceof WorldContext worldContext) { + world = worldContext.getWorld(); + } else if (ctx instanceof PlayerContext playerContext) { + world = playerContext.getPlayer().getWorld(); + } else { + world = null; + } if (this.isConditional) { var cond = condition.getSingle(ctx); // The code we want to run each check. - Consumer code = exec -> { + Runnable code = () -> { if (cond.filter(b -> negated == b.booleanValue()).isPresent()) { - Statement.runAll(getNext().get(), ctx); + Statement.runAll(nextStatement, ctx); + } + }; + Runnable worldTask = () -> { + if (world == null || world.isInThread()) { + code.run(); + } else { + world.execute(code); } }; - if (this.duration == null) { - SCHEDULER.scheduleAtFixedRate(() -> - code.accept(null), - 0, - DurationUtils.TICK, - TimeUnit.MILLISECONDS); - - } else { - Duration dur = ((Optional) ((Literal) this.duration).getSingle()).orElse(Duration.ZERO); - SCHEDULER.schedule(() -> { - Statement.runAll(getNext().get(), ctx); - }, dur.toMillis(), TimeUnit.MILLISECONDS); - } + SCHEDULER.scheduleAtFixedRate(worldTask, 0, DurationUtils.TICK, TimeUnit.MILLISECONDS); + } else { Optional dur = duration.getSingle(ctx); - if (dur.isEmpty()) - return getNext(); + if (dur.isEmpty()) return nextOpt; - SCHEDULER.schedule(() -> - Statement.runAll(getNext().get(), ctx), - dur.get().toMillis(), - TimeUnit.MILLISECONDS); + Runnable code = () -> Statement.runAll(nextStatement, ctx); + Runnable worldTask = () -> { + if (world == null || world.isInThread()) { + code.run(); + } else { + world.execute(code); + } + }; + + SCHEDULER.schedule(worldTask, dur.get().toMillis(), TimeUnit.MILLISECONDS); } return Optional.empty(); } @Override public String toString(@NotNull TriggerContext ctx, boolean debug) { - if (this.isConditional) { - String duration = this.duration == null ? "" : " for " + this.duration.toString(ctx, debug); - return "wait " + (this.negated ? "until" : "while") + " " + this.condition.toString(ctx, debug) + duration; - } - return "wait " + this.duration.toString(ctx, debug); + return switch (this.pattern) { + case 0 -> "wait " + this.duration.toString(ctx, debug); + case 1 -> "wait in " + this.world.toString(ctx, debug) + " for " + this.duration.toString(ctx, debug); + case 2 -> "wait " + (this.negated ? "until" : "while") + " " + this.condition.toString(ctx, debug); + case 3 -> "wait in " + this.world.toString(ctx, debug) + " " + (this.negated ? "until" : "while") + " " + + this.condition.toString(ctx, debug); + default -> "unknown"; + }; } } 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 e55023dc..3a55a8ce 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 @@ -5,6 +5,7 @@ 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.event.PlayerRefContext; +import com.github.skriptdev.skript.api.skript.event.WorldContext; 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; @@ -32,6 +33,7 @@ import com.github.skriptdev.skript.plugin.elements.events.skript.EvtLoad; import com.hypixel.hytale.server.core.entity.entities.Player; import com.hypixel.hytale.server.core.universe.PlayerRef; +import com.hypixel.hytale.server.core.universe.world.World; import io.github.syst3ms.skriptparser.registration.context.ContextValue.Usage; public class EventHandler { @@ -86,6 +88,10 @@ private static void registerGlobalContexts(SkriptRegistration reg) { "player", PlayerContext::getPlayer) .setUsage(Usage.EXPRESSION_OR_ALONE) .register(); + reg.newSingleContextValue(WorldContext.class, World.class, + "world", WorldContext::getWorld) + .setUsage(Usage.EXPRESSION_OR_ALONE) + .register(); reg.addSingleContextValue(PlayerRefContext.class, PlayerRef.class, "playerref", PlayerRefContext::getPlayerRef); reg.addSingleContextValue(PlayerRefContext.class, PlayerRef.class, 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 d5b4babe..18bc0a52 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 @@ -1,6 +1,7 @@ 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.WorldContext; import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; import com.github.skriptdev.skript.plugin.HySk; import com.hypixel.hytale.component.ArchetypeChunk; @@ -12,6 +13,7 @@ import com.hypixel.hytale.server.core.modules.entity.damage.Damage; import com.hypixel.hytale.server.core.modules.entity.damage.DamageCause; import com.hypixel.hytale.server.core.modules.entity.damage.DamageSystems; +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.entities.NPCEntity; import io.github.syst3ms.skriptparser.lang.Expression; @@ -63,7 +65,7 @@ public String toString(@NotNull TriggerContext ctx, boolean debug) { } private record EntityDamageContext(Entity entity, Store store, Damage damage) - implements TriggerContext, CancellableContext { + implements TriggerContext, CancellableContext, WorldContext { public Entity getVictim() { return this.entity; @@ -94,6 +96,11 @@ public DamageCause getDamageCause() { return this.damage.getCause(); } + @Override + public World getWorld() { + return this.store.getExternalData().getWorld(); + } + @Override public String getName() { return "entity damage context"; diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/entity/EvtEntityDeath.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/entity/EvtEntityDeath.java index e0cfddb0..a42f4f41 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/entity/EvtEntityDeath.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/entity/EvtEntityDeath.java @@ -1,5 +1,6 @@ package com.github.skriptdev.skript.plugin.elements.events.entity; +import com.github.skriptdev.skript.api.skript.event.WorldContext; import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; import com.github.skriptdev.skript.plugin.HySk; import com.hypixel.hytale.component.CommandBuffer; @@ -15,6 +16,7 @@ import com.hypixel.hytale.server.core.modules.entity.damage.DamageCause; import com.hypixel.hytale.server.core.modules.entity.damage.DeathComponent; import com.hypixel.hytale.server.core.modules.entity.damage.DeathSystems; +import com.hypixel.hytale.server.core.universe.world.World; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import com.hypixel.hytale.server.core.util.MessageUtil; import com.hypixel.hytale.server.npc.entities.NPCEntity; @@ -143,7 +145,8 @@ public void onComponentAdded(@NotNull Ref ref, @NotNull DeathCompon } @SuppressWarnings("DataFlowIssue") - private record EntityDeathContext(int pattern, Entity victim, DeathComponent component) implements TriggerContext { + private record EntityDeathContext(int pattern, Entity victim, DeathComponent component) + implements TriggerContext, WorldContext { public Entity getVictim() { return this.victim; @@ -218,6 +221,11 @@ public void setDeathMessageString(String deathMessage) { this.component.setDeathMessage(Message.raw(deathMessage)); } + @Override + public World getWorld() { + return this.victim.getWorld(); + } + @Override public String getName() { return "entity-death-context"; 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 19b1a4f5..2e8a5815 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 @@ -3,6 +3,7 @@ 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.event.WorldContext; import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; import com.hypixel.hytale.component.ArchetypeChunk; import com.hypixel.hytale.component.CommandBuffer; @@ -14,6 +15,7 @@ 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.World; 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; @@ -66,7 +68,7 @@ public String toString(@NotNull TriggerContext ctx, boolean debug) { } public record PickupItemContext(InteractivelyPickupItemEvent event, Entity entity, - int pattern) implements PlayerContext, CancellableContext { + int pattern) implements PlayerContext, CancellableContext, WorldContext { public Entity getEntity() { return this.entity; @@ -81,6 +83,11 @@ public Player getPlayer() { return null; } + @Override + public World getWorld() { + return this.entity.getWorld(); + } + @Override public boolean isCancelled() { return this.event.isCancelled(); diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/entity/EvtEntityRemove.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/entity/EvtEntityRemove.java index dcc6826c..da4108a7 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/entity/EvtEntityRemove.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/entity/EvtEntityRemove.java @@ -1,5 +1,6 @@ package com.github.skriptdev.skript.plugin.elements.events.entity; +import com.github.skriptdev.skript.api.skript.event.WorldContext; import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; import com.github.skriptdev.skript.plugin.HySk; import com.hypixel.hytale.event.EventRegistration; @@ -26,7 +27,6 @@ public static void register(SkriptRegistration reg) { .setHandledContexts(EntityRemoveEventContext.class) .register(); reg.addSingleContextValue(EntityRemoveEventContext.class, Entity.class, "entity", EntityRemoveEventContext::getEntity); - reg.addSingleContextValue(EntityRemoveEventContext.class, World.class, "world", EntityRemoveEventContext::getWorld); } private static EventRegistration LISTENER; @@ -54,7 +54,7 @@ public String toString(@NotNull TriggerContext ctx, boolean debug) { return "entity remove event"; } - private record EntityRemoveEventContext(EntityRemoveEvent event) implements TriggerContext { + private record EntityRemoveEventContext(EntityRemoveEvent event) implements TriggerContext, WorldContext { @Override public String getName() { return "entity remove context"; @@ -64,7 +64,8 @@ private Entity getEntity() { return this.event.getEntity(); } - private World getWorld() { + @Override + public World getWorld() { return getEntity().getWorld(); } } diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/entity/EvtLivingEntityInvChange.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/entity/EvtLivingEntityInvChange.java index 1ec7f4e7..30afdaf5 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/entity/EvtLivingEntityInvChange.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/entity/EvtLivingEntityInvChange.java @@ -1,13 +1,14 @@ package com.github.skriptdev.skript.plugin.elements.events.entity; +import com.github.skriptdev.skript.api.skript.event.WorldContext; 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.entity.Entity; import com.hypixel.hytale.server.core.event.events.entity.LivingEntityInventoryChangeEvent; import com.hypixel.hytale.server.core.inventory.container.ItemContainer; +import com.hypixel.hytale.server.core.universe.world.World; 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.TriggerMap; import io.github.syst3ms.skriptparser.lang.event.SkriptEvent; @@ -37,7 +38,7 @@ public boolean init(Expression[] expressions, int matchedPattern, ParseContex if (LISTENER == null) { LISTENER = HySk.getInstance().getEventRegistry().registerGlobal(LivingEntityInventoryChangeEvent.class, event -> { InvChangeContext ctx = new InvChangeContext(event); - TriggerMap.getTriggersByContext(InvChangeContext.class).forEach(trigger -> Statement.runAll(trigger, ctx)); + TriggerMap.callTriggersByContext(ctx); }); } return true; @@ -53,7 +54,7 @@ public String toString(@NotNull TriggerContext ctx, boolean debug) { return "living entity inventory change"; } - private record InvChangeContext(LivingEntityInventoryChangeEvent event) implements TriggerContext { + private record InvChangeContext(LivingEntityInventoryChangeEvent event) implements TriggerContext, WorldContext { private Entity getEntity() { return this.event.getEntity(); @@ -63,6 +64,11 @@ private ItemContainer getContainer() { return this.event.getItemContainer(); } + @Override + public World getWorld() { + return this.event.getEntity().getWorld(); + } + @Override public String getName() { return "living entity inventory change context"; 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 e9f68d87..3c0b40e5 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 @@ -1,6 +1,7 @@ package com.github.skriptdev.skript.plugin.elements.events.player; import com.github.skriptdev.skript.api.skript.event.PlayerContext; +import com.github.skriptdev.skript.api.skript.event.WorldContext; import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; import com.github.skriptdev.skript.plugin.HySk; import com.hypixel.hytale.component.Holder; @@ -29,7 +30,6 @@ public static void register(SkriptRegistration reg) { .since("1.0.0") .register(); - reg.addSingleContextValue(AddContext.class, World.class, "world", AddContext::getWorld); reg.newSingleContextValue(AddContext.class, Boolean.class, "should-broadcast", AddContext::shouldBroadcast) .addSetter(AddContext::setShouldBroadcast) .register(); @@ -58,8 +58,9 @@ public String toString(@NotNull TriggerContext ctx, boolean debug) { return ""; } - private record AddContext(AddPlayerToWorldEvent event) implements PlayerContext { + private record AddContext(AddPlayerToWorldEvent event) implements PlayerContext, WorldContext { + @Override public World getWorld() { return this.event.getWorld(); } 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 66c5d874..1cf6aecf 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 @@ -4,6 +4,7 @@ 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.event.WorldContext; import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; import com.hypixel.hytale.component.ArchetypeChunk; import com.hypixel.hytale.component.CommandBuffer; @@ -43,8 +44,6 @@ public static void register(SkriptRegistration reg) { 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, @@ -82,7 +81,7 @@ public String toString(@NotNull TriggerContext ctx, boolean debug) { } private record BreakBlockEventContext(BreakBlockEvent event, Player player) - implements PlayerContext, CancellableContext { + implements PlayerContext, CancellableContext, WorldContext { public Player getPlayer() { return this.player; @@ -100,7 +99,8 @@ private void setTargetBlock(Block targetBlock) { this.event.setTargetBlock(targetBlock.getPos()); } - private World getWorld() { + @Override + public World getWorld() { return this.player.getWorld(); } diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerChangeGameMode.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerChangeGameMode.java index 85a3e5cd..f0939251 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerChangeGameMode.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerChangeGameMode.java @@ -3,6 +3,7 @@ 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.event.WorldContext; import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; import com.hypixel.hytale.component.ArchetypeChunk; import com.hypixel.hytale.component.CommandBuffer; @@ -14,6 +15,7 @@ import com.hypixel.hytale.server.core.entity.entities.Player; import com.hypixel.hytale.server.core.event.events.ecs.ChangeGameModeEvent; import com.hypixel.hytale.server.core.universe.PlayerRef; +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; @@ -68,12 +70,17 @@ public String toString(@Nullable TriggerContext triggerContext, boolean debug) { } private record PlayerChangeGameModeContext(ChangeGameModeEvent event, Player player) - implements PlayerContext, CancellableContext { + implements PlayerContext, CancellableContext, WorldContext { public Player getPlayer() { return this.player; } + @Override + public World getWorld() { + return getPlayer().getWorld(); + } + public GameMode getNewGameMode() { return event.getGameMode(); } 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 29dd7d66..f1af6639 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 @@ -4,6 +4,7 @@ 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.event.WorldContext; import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; import com.hypixel.hytale.component.ArchetypeChunk; import com.hypixel.hytale.component.CommandBuffer; @@ -65,13 +66,18 @@ public String toString(@NotNull TriggerContext ctx, boolean debug) { } public record DamageBlockContext(DamageBlockEvent event, Player player) - implements PlayerContext, CancellableContext { + implements PlayerContext, CancellableContext, WorldContext { @Override public Player getPlayer() { return this.player; } + @Override + public World getWorld() { + return this.player.getWorld(); + } + public ItemStack getItemStackInHand() { return this.event.getItemInHand(); } diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerDrainFromWorld.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerDrainFromWorld.java index c2b63fd6..07bf1707 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerDrainFromWorld.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerDrainFromWorld.java @@ -1,8 +1,13 @@ package com.github.skriptdev.skript.plugin.elements.events.player; +import com.github.skriptdev.skript.api.skript.event.PlayerContext; +import com.github.skriptdev.skript.api.skript.event.WorldContext; 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.entity.Entity; +import com.hypixel.hytale.server.core.entity.EntityUtils; +import com.hypixel.hytale.server.core.entity.entities.Player; import com.hypixel.hytale.server.core.event.events.player.DrainPlayerFromWorldEvent; import com.hypixel.hytale.server.core.universe.world.World; import io.github.syst3ms.skriptparser.lang.Expression; @@ -18,12 +23,9 @@ public static void register(SkriptRegistration reg) { reg.newEvent(EvtPlayerDrainFromWorld.class, "drain player from world", "player drained from world", "player drain from world") .name("Player Drain From World") - .description("Really not sure...") // TODO put real docs + .description("Called when a world is unloaded and players are moved out of it.") .since("1.0.0") .register(); - - reg.addSingleContextValue(DrainContext.class, World.class, - "world", DrainContext::getWorld); } private static EventRegistration LISTENER; @@ -49,12 +51,19 @@ public String toString(@NotNull TriggerContext ctx, boolean debug) { return "drain player from world"; } - private record DrainContext(DrainPlayerFromWorldEvent event) implements TriggerContext { + private record DrainContext(DrainPlayerFromWorldEvent event) implements PlayerContext, WorldContext { public World getWorld() { return this.event.getWorld(); } + @SuppressWarnings("deprecation") + @Override + public Player getPlayer() { + Entity entity = EntityUtils.getEntity(this.event.getHolder()); + return entity instanceof Player p ? p : null; + } + @Override public String getName() { return "drain context"; 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 33f47049..931d075d 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 @@ -3,6 +3,7 @@ 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.event.WorldContext; import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; import com.github.skriptdev.skript.plugin.HySk; import com.hypixel.hytale.component.ArchetypeChunk; @@ -16,6 +17,7 @@ import com.hypixel.hytale.server.core.event.events.ecs.DropItemEvent; import com.hypixel.hytale.server.core.event.events.ecs.DropItemEvent.Drop; 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; @@ -63,12 +65,17 @@ public String toString(@NotNull TriggerContext ctx, boolean debug) { return "player drop item event"; } - private record DropItemContext(Player player, Drop drop) implements PlayerContext, CancellableContext { + private record DropItemContext(Player player, Drop drop) implements PlayerContext, WorldContext, CancellableContext { public Player getPlayer() { return this.player; } + @Override + public World getWorld() { + return this.player.getWorld(); + } + public Float getThrowSpeed() { return this.drop.getThrowSpeed(); } 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 23466b3d..67a2a653 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 @@ -3,6 +3,7 @@ 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.event.WorldContext; import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; import com.github.skriptdev.skript.plugin.HySk; import com.hypixel.hytale.component.ArchetypeChunk; @@ -17,6 +18,7 @@ import com.hypixel.hytale.server.core.inventory.Inventory; import com.hypixel.hytale.server.core.inventory.ItemStack; import com.hypixel.hytale.server.core.inventory.container.ItemContainer; +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; @@ -70,12 +72,17 @@ public String toString(@NotNull TriggerContext ctx, boolean debug) { } private record RequestDropItemContext(Player player, DropItemEvent.PlayerRequest request) - implements PlayerContext, CancellableContext { + implements PlayerContext, WorldContext, CancellableContext { public Player getPlayer() { return this.player; } + @Override + public World getWorld() { + return this.player.getWorld(); + } + public int getSlotId() { return (int) this.request.getSlotId(); } 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 35606c99..e2e574c0 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 @@ -6,6 +6,7 @@ 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.event.WorldContext; import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; import com.hypixel.hytale.component.ArchetypeChunk; import com.hypixel.hytale.component.CommandBuffer; @@ -73,13 +74,18 @@ public String toString(@NotNull TriggerContext ctx, boolean debug) { return "player place block"; } - public record PlaceBlockContext(PlaceBlockEvent event, - Player player) implements PlayerContext, BlockContext, CancellableContext { + public record PlaceBlockContext(PlaceBlockEvent event, Player player) + implements PlayerContext, BlockContext, WorldContext, CancellableContext { public Player getPlayer() { return this.player; } + @Override + public World getWorld() { + return this.player.getWorld(); + } + public Item getItemInHand() { ItemStack itemInHand = this.event.getItemInHand(); if (itemInHand == null) return null; 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 f3ed8d7d..5b71ef2f 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 @@ -4,6 +4,7 @@ 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.event.WorldContext; import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; import com.hypixel.hytale.component.ArchetypeChunk; import com.hypixel.hytale.component.CommandBuffer; @@ -78,7 +79,7 @@ public String toString(@NotNull TriggerContext ctx, boolean debug) { return "player use block"; } - public static abstract class UseBlockContext implements PlayerContext { + public static abstract class UseBlockContext implements PlayerContext, WorldContext { final T event; final Player player; @@ -93,6 +94,11 @@ public Player getPlayer() { return this.player; } + @Override + public World getWorld() { + return this.player.getWorld(); + } + public BlockType getBlockType() { return this.event.getBlockType(); } From 08bc329169e7d293f166d83c5a50bd09a33edf45 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Fri, 6 Feb 2026 18:18:29 -0800 Subject: [PATCH 46/61] Add contexts to commands --- .../skript/command/ScriptCommandBuilder.java | 15 +++-- .../elements/command/ScriptCommand.java | 57 +++++++++++++++---- 2 files changed, 54 insertions(+), 18 deletions(-) diff --git a/src/main/java/com/github/skriptdev/skript/api/skript/command/ScriptCommandBuilder.java b/src/main/java/com/github/skriptdev/skript/api/skript/command/ScriptCommandBuilder.java index c6c02bf0..954b19c1 100644 --- a/src/main/java/com/github/skriptdev/skript/api/skript/command/ScriptCommandBuilder.java +++ b/src/main/java/com/github/skriptdev/skript/api/skript/command/ScriptCommandBuilder.java @@ -1,7 +1,9 @@ package com.github.skriptdev.skript.api.skript.command; import com.github.skriptdev.skript.plugin.HySk; +import com.github.skriptdev.skript.plugin.elements.command.ScriptCommand.PlayerScriptCommandContext; import com.github.skriptdev.skript.plugin.elements.command.ScriptCommand.ScriptCommandContext; +import com.github.skriptdev.skript.plugin.elements.command.ScriptCommand.WorldScriptCommandContext; import com.hypixel.hytale.component.Ref; import com.hypixel.hytale.component.Store; import com.hypixel.hytale.server.core.command.system.AbstractCommand; @@ -122,10 +124,10 @@ public List setupCommand(FileSection section, ParserState parserState protected void execute(@NotNull CommandContext commandContext, @NotNull Store store, @NotNull Ref ref, @NotNull PlayerRef playerRef, @NotNull World world) { - CommandSender sender = commandContext.sender(); Player player = store.getComponent(ref, Player.getComponentType()); - ScriptCommandContext context = new ScriptCommandContext(ScriptCommandBuilder.this.commandName, - sender, player, world); + PlayerScriptCommandContext context = new PlayerScriptCommandContext( + ScriptCommandBuilder.this.commandName, player); + createLocalVariables(commandContext, context); Statement.runAll(trigger, context); Variables.clearLocalVariables(context); @@ -136,8 +138,9 @@ protected void execute(@NotNull CommandContext commandContext, @NotNull Store store) { - ScriptCommandContext context = new ScriptCommandContext(ScriptCommandBuilder.this.commandName, - commandContext.sender(), null, world); + WorldScriptCommandContext context = new WorldScriptCommandContext( + ScriptCommandBuilder.this.commandName, commandContext.sender(), world); + createLocalVariables(commandContext, context); Statement.runAll(trigger, context); Variables.clearLocalVariables(context); @@ -152,7 +155,7 @@ protected void execute(@NotNull CommandContext commandContext, @NotNull World wo Player player = null; if (sender instanceof Player p) player = p; ScriptCommandContext context = new ScriptCommandContext(ScriptCommandBuilder.this.commandName, - sender, player, null); + sender); createLocalVariables(commandContext, context); Statement.runAll(trigger, context); diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/command/ScriptCommand.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/command/ScriptCommand.java index 47a8ca56..7f5c4026 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/command/ScriptCommand.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/command/ScriptCommand.java @@ -3,6 +3,7 @@ import com.github.skriptdev.skript.api.skript.command.ScriptCommandBuilder; import com.github.skriptdev.skript.api.skript.command.ScriptCommandParent; import com.github.skriptdev.skript.api.skript.event.PlayerContext; +import com.github.skriptdev.skript.api.skript.event.WorldContext; import com.hypixel.hytale.server.core.command.system.CommandSender; import com.hypixel.hytale.server.core.entity.entities.Player; import com.hypixel.hytale.server.core.universe.world.World; @@ -27,8 +28,15 @@ public void loadChild(ScriptCommandBuilder parent, SkriptLogger logger) { // UNUSED IN TOP LEVEL COMMAND } - public record ScriptCommandContext(String command, CommandSender sender, Player player, World world) - implements PlayerContext { + public static class ScriptCommandContext implements TriggerContext { + + private final String command; + private final CommandSender sender; + + public ScriptCommandContext(String command, CommandSender sender) { + this.command = command; + this.sender = sender; + } public String getCommand() { return this.command; @@ -38,18 +46,45 @@ public CommandSender getSender() { return this.sender; } - public World getWorld() { - return this.world; + @Override + public String getName() { + return "command context"; } + } + + public static class PlayerScriptCommandContext extends ScriptCommandContext implements PlayerContext, WorldContext { + private final Player player; + + public PlayerScriptCommandContext(String command, Player player) { + super(command, player); + this.player = player; + } + + @Override public Player getPlayer() { - if (this.player == null && this.sender instanceof Player p) return p; return this.player; } @Override - public String getName() { - return "command context"; + public World getWorld() { + return this.player.getWorld(); + } + + } + + public static class WorldScriptCommandContext extends ScriptCommandContext implements WorldContext { + + private final World world; + + public WorldScriptCommandContext(String command, CommandSender sender, World world) { + super(command, sender); + this.world = world; + } + + @Override + public World getWorld() { + return this.world; } } @@ -58,7 +93,9 @@ public static void register(SkriptRegistration reg) { "*[global] command <.+>", "*player command <.+>", "*world command <.+>") - .setHandledContexts(ScriptCommandContext.class) + .setHandledContexts(ScriptCommandContext.class, + PlayerScriptCommandContext.class, + WorldScriptCommandContext.class) .name("Command") .description("Create a command.", "**Command Format**:", @@ -114,10 +151,6 @@ public static void register(SkriptRegistration reg) { "sender", ScriptCommandContext::getSender) .setUsage(Usage.EXPRESSION_OR_ALONE) .register(); - reg.newSingleContextValue(ScriptCommandContext.class, World.class, - "world", ScriptCommandContext::getWorld) - .setUsage(Usage.EXPRESSION_OR_ALONE) - .register(); reg.newSingleContextValue(ScriptCommandContext.class, String.class, "command", ScriptCommandContext::getCommand) .setUsage(Usage.EXPRESSION_OR_ALONE) From fd34e932a5019bb798461c6c464618f6b1791ee2 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Fri, 6 Feb 2026 18:37:53 -0800 Subject: [PATCH 47/61] JsonVariableStorage - remove error when thread stopping --- .../skript/api/skript/variables/JsonVariableStorage.java | 1 - 1 file changed, 1 deletion(-) 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 fbbf1afd..f3335856 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 @@ -110,7 +110,6 @@ private void startFileWatcher() { } catch (InterruptedException e) { // Restore interrupt status and exit Thread.currentThread().interrupt(); - Utils.error("Variable Save Thread was interrupted, stopping..."); } },"HySkript-Variable-Save-Thread"); From 78afdc79433a434120380690644dd5e72ed3b0f2 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Fri, 6 Feb 2026 19:27:18 -0800 Subject: [PATCH 48/61] MemoryLeak - Fix local variables never clearing (part 2) --- .../api/skript/command/ScriptCommandBuilder.java | 10 ++++------ .../plugin/elements/events/entity/EvtEntityRemove.java | 6 +----- .../plugin/elements/events/player/EvtPlayerChat.java | 6 +----- .../elements/events/player/EvtPlayerMouseClick.java | 4 +--- .../skript/plugin/elements/events/server/EvtBoot.java | 6 +----- .../skript/plugin/elements/events/skript/EvtLoad.java | 4 ++-- 6 files changed, 10 insertions(+), 26 deletions(-) diff --git a/src/main/java/com/github/skriptdev/skript/api/skript/command/ScriptCommandBuilder.java b/src/main/java/com/github/skriptdev/skript/api/skript/command/ScriptCommandBuilder.java index 954b19c1..f44ce7f6 100644 --- a/src/main/java/com/github/skriptdev/skript/api/skript/command/ScriptCommandBuilder.java +++ b/src/main/java/com/github/skriptdev/skript/api/skript/command/ScriptCommandBuilder.java @@ -23,6 +23,7 @@ import io.github.syst3ms.skriptparser.lang.CodeSection; import io.github.syst3ms.skriptparser.lang.Statement; import io.github.syst3ms.skriptparser.lang.TriggerContext; +import io.github.syst3ms.skriptparser.lang.TriggerMap; import io.github.syst3ms.skriptparser.lang.entries.SectionConfiguration; import io.github.syst3ms.skriptparser.lang.entries.SectionLoader; import io.github.syst3ms.skriptparser.log.ErrorType; @@ -129,8 +130,7 @@ protected void execute(@NotNull CommandContext commandContext, @NotNull Store new AbstractWorldCommand(this.commandName, description) { @@ -142,8 +142,7 @@ protected void execute(@NotNull CommandContext commandContext, @NotNull World wo ScriptCommandBuilder.this.commandName, commandContext.sender(), world); createLocalVariables(commandContext, context); - Statement.runAll(trigger, context); - Variables.clearLocalVariables(context); + TriggerMap.callTriggersByContext(context); } }; default -> new AbstractCommand(this.commandName, description) { @@ -158,8 +157,7 @@ protected void execute(@NotNull CommandContext commandContext, @NotNull World wo sender); createLocalVariables(commandContext, context); - Statement.runAll(trigger, context); - Variables.clearLocalVariables(context); + TriggerMap.callTriggersByContext(context); }); return null; } diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/entity/EvtEntityRemove.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/entity/EvtEntityRemove.java index da4108a7..ffd015e2 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/entity/EvtEntityRemove.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/entity/EvtEntityRemove.java @@ -8,8 +8,6 @@ import com.hypixel.hytale.server.core.event.events.entity.EntityRemoveEvent; import com.hypixel.hytale.server.core.universe.world.World; import io.github.syst3ms.skriptparser.lang.Expression; -import io.github.syst3ms.skriptparser.lang.Statement; -import io.github.syst3ms.skriptparser.lang.Trigger; import io.github.syst3ms.skriptparser.lang.TriggerContext; import io.github.syst3ms.skriptparser.lang.TriggerMap; import io.github.syst3ms.skriptparser.lang.event.SkriptEvent; @@ -36,9 +34,7 @@ public boolean init(Expression[] expressions, int matchedPattern, ParseContex if (LISTENER == null) { LISTENER = HySk.getInstance().getEventRegistry().registerGlobal(EntityRemoveEvent.class, event -> { EntityRemoveEventContext context = new EntityRemoveEventContext(event); - for (Trigger trigger : TriggerMap.getTriggersByContext(EntityRemoveEventContext.class)) { - Statement.runAll(trigger, context); - } + TriggerMap.callTriggersByContext(context); }); } return true; 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 a4b09aeb..42f57613 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 @@ -8,8 +8,6 @@ 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; -import io.github.syst3ms.skriptparser.lang.Statement; -import io.github.syst3ms.skriptparser.lang.Trigger; import io.github.syst3ms.skriptparser.lang.TriggerContext; import io.github.syst3ms.skriptparser.lang.TriggerMap; import io.github.syst3ms.skriptparser.lang.event.SkriptEvent; @@ -64,9 +62,7 @@ public boolean init(Expression @NotNull [] expressions, int matchedPattern, @ LISTENER = HySk.getInstance().getEventRegistry().registerAsyncGlobal(PlayerChatEvent.class, future -> { future.thenAccept(event -> { PlayerChatContext ctx = new PlayerChatContext(event); - for (Trigger trigger : TriggerMap.getTriggersByContext(PlayerChatContext.class)) { - Statement.runAll(trigger, ctx); - } + TriggerMap.callTriggersByContext(ctx); }); return future; }); 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 0bc5eeb2..16fcb7ec 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 @@ -46,9 +46,7 @@ public boolean init(Expression[] expressions, int matchedPattern, ParseContex if (LISTENER == null) { LISTENER = HySk.getInstance().getEventRegistry().registerGlobal(PlayerMouseButtonEvent.class, event -> { MouseClickContext context = new MouseClickContext(event); - for (Trigger trigger : TriggerMap.getTriggersByContext(MouseClickContext.class)) { - Statement.runAll(trigger, context); - } + TriggerMap.callTriggersByContext(context); }); } return true; diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/server/EvtBoot.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/server/EvtBoot.java index c5b2685b..31be021e 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/server/EvtBoot.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/server/EvtBoot.java @@ -5,8 +5,6 @@ import com.hypixel.hytale.event.EventRegistration; import com.hypixel.hytale.server.core.event.events.BootEvent; import io.github.syst3ms.skriptparser.lang.Expression; -import io.github.syst3ms.skriptparser.lang.Statement; -import io.github.syst3ms.skriptparser.lang.Trigger; import io.github.syst3ms.skriptparser.lang.TriggerContext; import io.github.syst3ms.skriptparser.lang.TriggerMap; import io.github.syst3ms.skriptparser.lang.event.SkriptEvent; @@ -30,9 +28,7 @@ public boolean init(Expression[] expressions, int matchedPattern, ParseContex if (LISTENER == null) { LISTENER = HySk.getInstance().getEventRegistry().registerGlobal(BootEvent.class, event -> { BootContext bootContext = new BootContext(event); - for (Trigger trigger : TriggerMap.getTriggersByContext(BootContext.class)) { - Statement.runAll(trigger, bootContext); - } + TriggerMap.callTriggersByContext(bootContext); }); } return true; diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/skript/EvtLoad.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/skript/EvtLoad.java index 433ef35d..f08a9955 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/skript/EvtLoad.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/skript/EvtLoad.java @@ -1,9 +1,9 @@ package com.github.skriptdev.skript.plugin.elements.events.skript; import io.github.syst3ms.skriptparser.lang.Expression; -import io.github.syst3ms.skriptparser.lang.Statement; import io.github.syst3ms.skriptparser.lang.Trigger; import io.github.syst3ms.skriptparser.lang.TriggerContext; +import io.github.syst3ms.skriptparser.lang.TriggerMap; import io.github.syst3ms.skriptparser.lang.event.SkriptEvent; import io.github.syst3ms.skriptparser.lang.event.StartOnLoadEvent; import io.github.syst3ms.skriptparser.parsing.ParseContext; @@ -38,7 +38,7 @@ public String toString(@Nullable TriggerContext ctx, boolean debug) { @Override public void onInitialLoad(Trigger trigger) { - Statement.runAll(trigger, new ScriptLoadContext()); + TriggerMap.callTriggersByContext(new ScriptLoadContext()); } private static class ScriptLoadContext implements TriggerContext { From cf3b9ce217259ab968ca09ca33ed66020b7cf1d2 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Fri, 6 Feb 2026 19:28:40 -0800 Subject: [PATCH 49/61] EvtPlayerMouseClick - remove unused imports (checkstyle) --- .../plugin/elements/events/player/EvtPlayerMouseClick.java | 2 -- 1 file changed, 2 deletions(-) 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 16fcb7ec..94795397 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 @@ -13,8 +13,6 @@ import com.hypixel.hytale.server.core.entity.entities.Player; import com.hypixel.hytale.server.core.event.events.player.PlayerMouseButtonEvent; import io.github.syst3ms.skriptparser.lang.Expression; -import io.github.syst3ms.skriptparser.lang.Statement; -import io.github.syst3ms.skriptparser.lang.Trigger; import io.github.syst3ms.skriptparser.lang.TriggerContext; import io.github.syst3ms.skriptparser.lang.TriggerMap; import io.github.syst3ms.skriptparser.lang.event.SkriptEvent; From 1394c5beb625505132fc2b28fa9218499e81584e Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Fri, 6 Feb 2026 19:59:22 -0800 Subject: [PATCH 50/61] EffDelay - fix local variables being cleared before delay can finish --- .../plugin/elements/effects/other/EffDelay.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/other/EffDelay.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/other/EffDelay.java index 32ea422e..05a6dd0d 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/other/EffDelay.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/other/EffDelay.java @@ -13,6 +13,8 @@ import io.github.syst3ms.skriptparser.lang.TriggerContext; import io.github.syst3ms.skriptparser.parsing.ParseContext; import io.github.syst3ms.skriptparser.util.DurationUtils; +import io.github.syst3ms.skriptparser.variables.VariableMap; +import io.github.syst3ms.skriptparser.variables.Variables; import org.jetbrains.annotations.NotNull; import java.time.Duration; @@ -104,12 +106,18 @@ public Optional walk(@NotNull TriggerContext ctx) { world = null; } + // Copy local variables to reuse after our delay + VariableMap variableMap = Variables.copyLocalVariables(ctx); if (this.isConditional) { var cond = condition.getSingle(ctx); // The code we want to run each check. Runnable code = () -> { if (cond.filter(b -> negated == b.booleanValue()).isPresent()) { + // Copy them back into the original context + Variables.setLocalVariables(ctx, variableMap); Statement.runAll(nextStatement, ctx); + // Now delete it all + Variables.clearLocalVariables(ctx); } }; Runnable worldTask = () -> { @@ -126,7 +134,13 @@ public Optional walk(@NotNull TriggerContext ctx) { Optional dur = duration.getSingle(ctx); if (dur.isEmpty()) return nextOpt; - Runnable code = () -> Statement.runAll(nextStatement, ctx); + Runnable code = () -> { + // Copy them back into the original context + Variables.setLocalVariables(ctx, variableMap); + Statement.runAll(nextStatement, ctx); + // Now delete it all + Variables.clearLocalVariables(ctx); + }; Runnable worldTask = () -> { if (world == null || world.isInThread()) { code.run(); From 58c8ef59b7abbf37b9fee6c204cb5f2c09633ebe Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Fri, 6 Feb 2026 22:08:28 -0800 Subject: [PATCH 51/61] ExprNPCType - add role change --- .../expressions/entity/ExprNPCType.java | 55 ++++++++++++++++++- 1 file changed, 52 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/entity/ExprNPCType.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/entity/ExprNPCType.java index 6be76ccc..1641ca0e 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/entity/ExprNPCType.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/entity/ExprNPCType.java @@ -2,22 +2,34 @@ import com.github.skriptdev.skript.api.skript.registration.NPCRegistry; import com.github.skriptdev.skript.api.skript.registration.NPCRegistry.NPCRole; +import com.hypixel.hytale.component.Ref; +import com.hypixel.hytale.component.Store; import com.hypixel.hytale.server.core.entity.Entity; +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.entities.NPCEntity; +import com.hypixel.hytale.server.npc.role.Role; +import com.hypixel.hytale.server.npc.systems.RoleChangeSystem; +import io.github.syst3ms.skriptparser.lang.Expression; +import io.github.syst3ms.skriptparser.lang.TriggerContext; import io.github.syst3ms.skriptparser.lang.properties.PropertyExpression; import io.github.syst3ms.skriptparser.registration.SkriptRegistration; +import io.github.syst3ms.skriptparser.types.changers.ChangeMode; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Optional; + public class ExprNPCType extends PropertyExpression { public static void register(SkriptRegistration registration) { registration.newPropertyExpression(ExprNPCType.class, NPCRole.class, "npc (type|role)", "entities") - .name("NPC Type of Entity") - .description("Returns the NPC type of an NPC entity.") + .name("NPC Role of Entity") + .description("Get/set the NPC role of an NPC entity.") .examples("set {_type} to npc type of target entity", - "if npc type of {_entity} = sheep:") + "if npc type of {_entity} = sheep:", + "set npc role of target entity of player to cow") .since("1.0.0") .register(); } @@ -30,4 +42,41 @@ public static void register(SkriptRegistration registration) { return null; } + @Override + public Optional[]> acceptsChange(@NotNull ChangeMode mode) { + if (mode == ChangeMode.SET) return Optional.of(new Class[]{NPCRole.class}); + return Optional.empty(); + } + + @SuppressWarnings("ConstantValue") + @Override + public void change(@NotNull TriggerContext ctx, @NotNull ChangeMode changeMode, Object @NotNull [] changeWith) { + Expression owner = getOwner(); + if (owner == null || changeWith == null) return; + + if (changeMode == ChangeMode.SET) { + if (changeWith.length == 1 && changeWith[0] instanceof NPCRole role) { + for (Entity entity : owner.getArray(ctx)) { + if (entity instanceof NPCEntity npcEntity) { + changeRole(npcEntity, role); + } + } + } + } + } + + private void changeRole(NPCEntity npcEntity, NPCRole npcRole) { + Ref reference = npcEntity.getReference(); + if (reference == null) return; + + World world = npcEntity.getWorld(); + if (world == null) return; + + Store store = world.getEntityStore().getStore(); + Role role = npcEntity.getRole(); + if (role == null || role.isRoleChangeRequested()) return; + + RoleChangeSystem.requestRoleChange(reference, role, npcRole.index(), true, store); + } + } From cc8576c92d207b297ab25c017ee0bfdf0a9fe28a Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Sat, 7 Feb 2026 07:47:15 -0800 Subject: [PATCH 52/61] EffDamage - add damage effect --- .../elements/effects/EffectHandler.java | 2 + .../elements/effects/entity/EffDamage.java | 145 ++++++++++++++++++ 2 files changed, 147 insertions(+) create mode 100644 src/main/java/com/github/skriptdev/skript/plugin/elements/effects/entity/EffDamage.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 e2347246..dff7b037 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 @@ -2,6 +2,7 @@ import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; import com.github.skriptdev.skript.plugin.elements.effects.block.EffBreakBlock; +import com.github.skriptdev.skript.plugin.elements.effects.entity.EffDamage; import com.github.skriptdev.skript.plugin.elements.effects.entity.EffDropItem; import com.github.skriptdev.skript.plugin.elements.effects.entity.EffEntityEffect; import com.github.skriptdev.skript.plugin.elements.effects.entity.EffKill; @@ -26,6 +27,7 @@ public static void register(SkriptRegistration registration) { EffBreakBlock.register(registration); // ENTITY + EffDamage.register(registration); EffDropItem.register(registration); EffEntityEffect.register(registration); EffInteraction.register(registration); diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/entity/EffDamage.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/entity/EffDamage.java new file mode 100644 index 00000000..2f8051f5 --- /dev/null +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/entity/EffDamage.java @@ -0,0 +1,145 @@ +package com.github.skriptdev.skript.plugin.elements.effects.entity; + +import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; +import com.github.skriptdev.skript.api.utils.Utils; +import com.hypixel.hytale.component.Ref; +import com.hypixel.hytale.component.Store; +import com.hypixel.hytale.server.core.entity.Entity; +import com.hypixel.hytale.server.core.entity.LivingEntity; +import com.hypixel.hytale.server.core.modules.entity.damage.Damage; +import com.hypixel.hytale.server.core.modules.entity.damage.DamageCause; +import com.hypixel.hytale.server.core.modules.entity.damage.DamageSystems; +import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; +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; + +import java.util.Optional; + +public class EffDamage extends Effect { + + @SuppressWarnings("NotNullFieldNotInitialized") + private static @NotNull DamageCause DEFAULT_CAUSE; + + public static void register(SkriptRegistration reg) { + DamageCause cause = DamageCause.getAssetMap().getAsset("Environment"); + if (cause == null) { + Utils.error("Default damage cause 'Environmental' not found. Skipping EffDamage registration."); + return; + } + DEFAULT_CAUSE = cause; + reg.newEffect(EffDamage.class, "damage %entities% by %number%", + "make %entity% damage %entities% by %number%", + "damage %entities% by %number% with cause %damagecause%", + "make %entity% damage %entities% by %number% with cause %damagecause%") + .name("Damage") + .description("Damages entities with a specified amount of damage.") + .examples("damage player by 5", + "make player damage {_e} by 5", + "damage entities in radius 5 around player by 5 with cause Environmental", + "make player damage {_e::*} by 5 with cause Environmental") + .since("INSERT VERSION") + .register(); + } + + private Expression entities; + private Expression sourceEntity; + private Expression damage; + private Expression cause; + private int pattern; + + @SuppressWarnings("unchecked") + @Override + public boolean init(Expression @NotNull [] expressions, int matchedPattern, @NotNull ParseContext parseContext) { + this.pattern = matchedPattern; + switch (matchedPattern) { + case 0 -> { + this.entities = (Expression) expressions[0]; + this.damage = (Expression) expressions[1]; + } + case 1 -> { + this.sourceEntity = (Expression) expressions[0]; + this.entities = (Expression) expressions[1]; + this.damage = (Expression) expressions[2]; + } + case 2 -> { + this.entities = (Expression) expressions[0]; + this.damage = (Expression) expressions[1]; + this.cause = (Expression) expressions[2]; + } + case 3 -> { + this.sourceEntity = (Expression) expressions[0]; + this.entities = (Expression) expressions[1]; + this.damage = (Expression) expressions[2]; + this.cause = (Expression) expressions[3]; + } + default -> { + Utils.error("Invalid pattern for EffDamage effect: " + matchedPattern); + return false; + } + } + return true; + } + + @Override + protected void execute(@NotNull TriggerContext ctx) { + Number number = this.damage.getSingle(ctx).orElse(null); + if (number == null) return; + + float damage = number.floatValue(); + DamageCause cause; + if (this.cause != null) { + cause = this.cause.getSingle(ctx).orElse(null); + if (cause == null) cause = DEFAULT_CAUSE; + } else { + cause = DEFAULT_CAUSE; + } + + Damage.Source source = Damage.NULL_SOURCE; + if (this.sourceEntity != null) { + Optional single = this.sourceEntity.getSingle(ctx); + if (single.isPresent()) { + Entity sourceEntity = single.get(); + Ref reference = sourceEntity.getReference(); + if (reference != null) { + source = new Damage.EntitySource(sourceEntity.getReference()); + } + } + } + + for (Entity entity : this.entities.getArray(ctx)) { + if (entity instanceof LivingEntity livingEntity) { + causeDamage(livingEntity, source, cause, damage); + } + } + } + + private void causeDamage(@NotNull LivingEntity entity, @NotNull Damage.Source source, @NotNull DamageCause cause, float amount) { + Ref reference = entity.getReference(); + if (reference == null) return; + + Store store = reference.getStore(); + Damage damage = new Damage(source, cause, amount); + + DamageSystems.executeDamage(reference, store, damage); + } + + @Override + public String toString(@NotNull TriggerContext ctx, boolean debug) { + return switch (this.pattern) { + case 0 -> "damage " + this.entities.toString(ctx, debug) + " by " + this.damage.toString(ctx, debug); + case 1 -> + "make " + this.sourceEntity.toString(ctx, debug) + " damage " + this.entities.toString(ctx, debug) + + " by " + this.damage.toString(ctx, debug); + case 2 -> "damage " + this.entities.toString(ctx, debug) + " by " + this.damage.toString(ctx, debug) + + " with cause " + this.cause.toString(ctx, debug); + case 3 -> + "make " + this.sourceEntity.toString(ctx, debug) + " damage " + this.entities.toString(ctx, debug) + + " by " + this.damage.toString(ctx, debug) + " with cause " + this.cause.toString(ctx, debug); + default -> throw new IllegalStateException("Unexpected value: " + this.pattern); + }; + } + +} From 6e0a2d0db07365acbaa2e00704aef5c387146896 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Sat, 7 Feb 2026 07:58:39 -0800 Subject: [PATCH 53/61] ScriptCommandBuilder - fix me breaking commands --- .../api/skript/command/ScriptCommandBuilder.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/github/skriptdev/skript/api/skript/command/ScriptCommandBuilder.java b/src/main/java/com/github/skriptdev/skript/api/skript/command/ScriptCommandBuilder.java index f44ce7f6..954b19c1 100644 --- a/src/main/java/com/github/skriptdev/skript/api/skript/command/ScriptCommandBuilder.java +++ b/src/main/java/com/github/skriptdev/skript/api/skript/command/ScriptCommandBuilder.java @@ -23,7 +23,6 @@ import io.github.syst3ms.skriptparser.lang.CodeSection; import io.github.syst3ms.skriptparser.lang.Statement; import io.github.syst3ms.skriptparser.lang.TriggerContext; -import io.github.syst3ms.skriptparser.lang.TriggerMap; import io.github.syst3ms.skriptparser.lang.entries.SectionConfiguration; import io.github.syst3ms.skriptparser.lang.entries.SectionLoader; import io.github.syst3ms.skriptparser.log.ErrorType; @@ -130,7 +129,8 @@ protected void execute(@NotNull CommandContext commandContext, @NotNull Store new AbstractWorldCommand(this.commandName, description) { @@ -142,7 +142,8 @@ protected void execute(@NotNull CommandContext commandContext, @NotNull World wo ScriptCommandBuilder.this.commandName, commandContext.sender(), world); createLocalVariables(commandContext, context); - TriggerMap.callTriggersByContext(context); + Statement.runAll(trigger, context); + Variables.clearLocalVariables(context); } }; default -> new AbstractCommand(this.commandName, description) { @@ -157,7 +158,8 @@ protected void execute(@NotNull CommandContext commandContext, @NotNull World wo sender); createLocalVariables(commandContext, context); - TriggerMap.callTriggersByContext(context); + Statement.runAll(trigger, context); + Variables.clearLocalVariables(context); }); return null; } From 8632fb494bc4f643091e9598f93cfa26c5eb3726 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Sat, 7 Feb 2026 08:19:36 -0800 Subject: [PATCH 54/61] Skript - improve error --- src/main/java/com/github/skriptdev/skript/plugin/Skript.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/com/github/skriptdev/skript/plugin/Skript.java b/src/main/java/com/github/skriptdev/skript/plugin/Skript.java index 203b5d00..ac241f60 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/Skript.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/Skript.java @@ -126,6 +126,11 @@ private void preSetup() { Utils.error("Original error message: %s", e.getMessage()); } } + } else { + Utils.error("An error ocrrured while executing a script: %s", e.getMessage()); + for (StackTraceElement stackTraceElement : e.getStackTrace()) { + Utils.error(" - %s", stackTraceElement); + } } }); } From c716fd99418887cf73c0f459511388b5c1407f61 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Sat, 7 Feb 2026 12:23:29 -0800 Subject: [PATCH 55/61] ErrorHandler - even more error handling --- .../skript/api/skript/ErrorHandler.java | 110 ++++++++++++++++++ .../skriptdev/skript/plugin/Skript.java | 39 +------ 2 files changed, 114 insertions(+), 35 deletions(-) create mode 100644 src/main/java/com/github/skriptdev/skript/api/skript/ErrorHandler.java diff --git a/src/main/java/com/github/skriptdev/skript/api/skript/ErrorHandler.java b/src/main/java/com/github/skriptdev/skript/api/skript/ErrorHandler.java new file mode 100644 index 00000000..39eeaa7c --- /dev/null +++ b/src/main/java/com/github/skriptdev/skript/api/skript/ErrorHandler.java @@ -0,0 +1,110 @@ +package com.github.skriptdev.skript.api.skript; + +import com.github.skriptdev.skript.api.utils.Utils; +import io.github.syst3ms.skriptparser.lang.Effect; +import io.github.syst3ms.skriptparser.lang.Statement; +import io.github.syst3ms.skriptparser.registration.SkriptEventInfo; +import io.github.syst3ms.skriptparser.registration.SyntaxInfo; +import io.github.syst3ms.skriptparser.registration.SyntaxManager; +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; +import java.util.Map; +import java.util.logging.Level; + +public class ErrorHandler { + + private static final Map> EVENT_MAP = new HashMap<>(); + private static final Map> EFFECT_MAP = new HashMap<>(); + + public static void init() { + for (SyntaxInfo effect : SyntaxManager.getEffects()) { + EFFECT_MAP.put(effect.getSyntaxClass().getSimpleName(), effect); + } + for (SkriptEventInfo event : SyntaxManager.getEvents()) { + EVENT_MAP.put(event.getSyntaxClass().getSimpleName(), event); + } + setup(); + } + + private static @Nullable SkriptEventInfo getEvent(String name) { + return EVENT_MAP.get(name); + } + + private static @Nullable SyntaxInfo getEffect(String name) { + return EFFECT_MAP.get(name); + } + + private static void setup() { + // Set up how HySkript handles IllegalStateExceptions + Statement.setIllegalStateHandler(e -> { + String message = e.getMessage(); + if (message.contains("Assert not in thread!")) { + // Hytale has threads for each world, effects involving a world must happen on a world thread + boolean failedInCommand = false; + for (StackTraceElement ste : e.getStackTrace()) { + if (ste.getClassName().contains("ScriptCommandBuilder")) { + failedInCommand = true; + break; + } + } + if (failedInCommand) { + Utils.logToAdmins(Level.WARNING, "A command was executed on the wrong thread, see console for more info."); + Utils.error("A command was executed on the wrong thread!"); + Utils.warn("If you have a regular/global command that a player is running, which executes code in a world, consider:"); + Utils.warn(" - Using the 'player command' or 'world command' command types."); + Utils.warn(" - Using 'execute in %world%' section."); + Utils.error("Original error message: %s", message); + } else { + Utils.logToAdmins(Level.WARNING, "Something was executed on the wrong thread."); + if (message.contains("World")) { + Utils.error("A world was accessed on the wrong thread!"); + Utils.warn("Consider using 'execute in %world%' section."); + Utils.error("Original error message: %s", message); + } + } + } else if (message.contains("calling a store method from a system")) { + // Hytale doesn't allow store methods to be called within System-based events + String eventName = "unknown event"; + String effectName = "unknown effect"; + + for (StackTraceElement stackTraceElement : e.getStackTrace()) { + String fileName = stackTraceElement.getFileName(); + if (fileName == null) continue; + fileName = fileName.replace(".java", ""); + + // Try to find the event + if (eventName.contains("unknown")) { + SkriptEventInfo event = getEvent(fileName); + if (event != null) { + eventName = event.getDocumentation().getName(); + if (eventName == null) eventName = event.getClass().getSimpleName(); + } + } + + // Try to find the effect + if (effectName.contains("unknown")) { + SyntaxInfo effect = getEffect(fileName); + if (effect != null) { + effectName = effect.getDocumentation().getName(); + if (effectName == null) effectName = effect.getClass().getSimpleName(); + } + + } + + } + Utils.logToAdmins(Level.WARNING, "An effect was executed incorrectly, see console for more info."); + Utils.error("The effect '%s' was executed incorrectly in the event '%s'.", effectName, eventName); + Utils.error("Hytale doesn't allow Store-based effects to be executed within System-based events."); + Utils.warn("Consider waiting a tick before using this effect to prevent this."); + + } else { + Utils.error("An error ocrrured while executing a script: %s", message); + for (StackTraceElement stackTraceElement : e.getStackTrace()) { + Utils.error(" - %s", stackTraceElement); + } + } + }); + } + +} diff --git a/src/main/java/com/github/skriptdev/skript/plugin/Skript.java b/src/main/java/com/github/skriptdev/skript/plugin/Skript.java index ac241f60..6b190307 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/Skript.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/Skript.java @@ -1,5 +1,6 @@ package com.github.skriptdev.skript.plugin; +import com.github.skriptdev.skript.api.skript.ErrorHandler; import com.github.skriptdev.skript.api.skript.ScriptsLoader; import com.github.skriptdev.skript.api.skript.addon.AddonLoader; import com.github.skriptdev.skript.api.skript.command.ArgUtils; @@ -13,7 +14,6 @@ import io.github.syst3ms.skriptparser.Parser; import io.github.syst3ms.skriptparser.config.Config; import io.github.syst3ms.skriptparser.config.Config.ConfigSection; -import io.github.syst3ms.skriptparser.lang.Statement; import io.github.syst3ms.skriptparser.log.LogEntry; import io.github.syst3ms.skriptparser.log.SkriptLogger; import io.github.syst3ms.skriptparser.registration.SkriptAddon; @@ -21,7 +21,6 @@ import org.jetbrains.annotations.NotNull; import java.nio.file.Path; -import java.util.logging.Level; /** * Main class for the Skript aspects of HySkript. @@ -86,6 +85,9 @@ private void setup() { this.addonLoader = new AddonLoader(); this.addonLoader.loadAddonsFromFolder(); + // SETUP ERROR HANDLER + ErrorHandler.init(); + // LOAD VARIABLES loadVariables(); @@ -100,39 +102,6 @@ private void setup() { private void preSetup() { ReflectionUtils.init(); ArgUtils.init(); - - // Set up how HySkript handles IllegalStateExceptions - Statement.setIllegalStateHandler(e -> { - if (e.getMessage().contains("Assert not in thread!")) { - boolean failedInCommand = false; - for (StackTraceElement ste : e.getStackTrace()) { - if (ste.getClassName().contains("ScriptCommandBuilder")) { - failedInCommand = true; - break; - } - } - if (failedInCommand) { - Utils.logToAdmins(Level.WARNING, "A command was executed on the wrong thread, see console for more info."); - Utils.error("A command was executed on the wrong thread!"); - Utils.warn("If you have a regular/global command that a player is running, which executes code in a world, consider:"); - Utils.warn(" - Using the 'player command' or 'world command' command types."); - Utils.warn(" - Using 'execute in %world%' section."); - Utils.error("Original error message: %s", e.getMessage()); - } else { - Utils.logToAdmins(Level.WARNING, "Something was executed on the wrong thread."); - if (e.getMessage().contains("World")) { - Utils.error("A world was accessed on the wrong thread!"); - Utils.warn("Consider using 'execute in %world%' section."); - Utils.error("Original error message: %s", e.getMessage()); - } - } - } else { - Utils.error("An error ocrrured while executing a script: %s", e.getMessage()); - for (StackTraceElement stackTraceElement : e.getStackTrace()) { - Utils.error(" - %s", stackTraceElement); - } - } - }); } public void shutdown() { From 8f9dd194a56448f9cbaf8a4abe406c5def7f96e4 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Sat, 7 Feb 2026 12:36:17 -0800 Subject: [PATCH 56/61] TypesEntity - add ability to delete an entity --- .../plugin/elements/types/TypesEntity.java | 30 ++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesEntity.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesEntity.java index 27bec0cb..997400cc 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesEntity.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesEntity.java @@ -2,10 +2,18 @@ import com.github.skriptdev.skript.api.skript.registration.NPCRegistry; import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; +import com.hypixel.hytale.component.Ref; +import com.hypixel.hytale.component.RemoveReason; import com.hypixel.hytale.server.core.entity.Entity; import com.hypixel.hytale.server.core.entity.LivingEntity; import com.hypixel.hytale.server.core.entity.effect.ActiveEntityEffect; +import com.hypixel.hytale.server.core.entity.entities.Player; +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.entities.NPCEntity; +import io.github.syst3ms.skriptparser.types.changers.ChangeMode; +import io.github.syst3ms.skriptparser.types.changers.Changer; +import org.jetbrains.annotations.NotNull; public class TypesEntity { @@ -20,8 +28,28 @@ static void register(SkriptRegistration reg) { reg.newType(Entity.class, "entity", "entit@y@ies") .toStringFunction(Entity::toString) // TODO get its name or something .name("Entity") - .description("Represents any entity in the game, including players and mobs.") + .description("Represents any Entity in the game, including Players and NPCs.") .since("1.0.0") + .defaultChanger(new Changer<>() { + @Override + public Class[] acceptsChange(@NotNull ChangeMode mode) { + if (mode == ChangeMode.DELETE) return new Class[] {Entity.class}; + return null; + } + + @Override + public void change(Entity @NotNull [] toChange, Object @NotNull [] changeWith, @NotNull ChangeMode mode) { + if (mode != ChangeMode.DELETE) return; + for (Entity entity : toChange) { + if (entity instanceof Player) continue; + Ref reference = entity.getReference(); + if (reference == null) continue; + World world = entity.getWorld(); + if (world == null) continue; + world.getEntityStore().getStore().removeEntity(reference, RemoveReason.REMOVE); + } + } + }) .register(); reg.newType(LivingEntity.class, "livingentity", "livingEntit@y@ies") .name("Living Entity") From e4629a48484b79fc95de5296b65fcd08e3f55271 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Sat, 7 Feb 2026 14:10:57 -0800 Subject: [PATCH 57/61] EffectCommands - fix up OP check and remove local vars --- .../skript/plugin/command/EffectCommands.java | 35 ++++++++++++++----- src/main/resources/config.sk | 1 - 2 files changed, 26 insertions(+), 10 deletions(-) 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 fc285e4e..0bfe8b7a 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 @@ -7,6 +7,7 @@ import com.hypixel.hytale.server.core.entity.entities.Player; import com.hypixel.hytale.server.core.event.events.player.PlayerChatEvent; import com.hypixel.hytale.server.core.permissions.PermissionsModule; +import com.hypixel.hytale.server.core.permissions.provider.PermissionProvider; import com.hypixel.hytale.server.core.universe.PlayerRef; import com.hypixel.hytale.server.core.universe.Universe; import com.hypixel.hytale.server.core.universe.world.World; @@ -17,6 +18,7 @@ import io.github.syst3ms.skriptparser.parsing.ParserState; import io.github.syst3ms.skriptparser.parsing.SyntaxParser; import io.github.syst3ms.skriptparser.registration.context.ContextValue.Usage; +import io.github.syst3ms.skriptparser.variables.Variables; import java.util.List; import java.util.Optional; @@ -35,11 +37,22 @@ public static void register(Skript skript, String token, boolean allowOps, Strin PlayerRef sender = event.getSender(); // PERM CHECK - // Pretty sure the OP stuff doesn't work PermissionsModule perm = PermissionsModule.get(); - Set groupsForUser = perm.getGroupsForUser(sender.getUuid()); if (!allowOps) { - if (groupsForUser.contains("OP") && !perm.hasPermission(sender.getUuid(), permission)) { + PermissionProvider provider = perm.getFirstPermissionProvider(); + Set groupsForUser = perm.getGroupsForUser(sender.getUuid()); + if (groupsForUser.contains("OP")) { + boolean can = false; + // Check all groups + for (String group : groupsForUser) { + // If the group has the explicit permission, they can use effect commands + if (provider.getGroupPermissions(group).contains(permission)) { + can = true; + break; + } + } + if (!can) return; + } else { return; } } else if (!perm.hasPermission(sender.getUuid(), permission)) { @@ -83,14 +96,18 @@ public static void register(Skript skript, String token, boolean allowOps, Strin Utils.log(sender, logEntry); } - if (world.isInThread()) { + Runnable code = () -> { Player player = world.getEntityStore().getStore().getComponent(reference, Player.getComponentType()); - effect.walk(new PlayerEffectContext(player)); + PlayerEffectContext effectContext = new PlayerEffectContext(player); + effect.walk(effectContext); + // Clear local variables to prevent memory leaks + Variables.clearLocalVariables(effectContext); + }; + + if (world.isInThread()) { + code.run(); } else { - world.execute(() -> { - Player player = world.getEntityStore().getStore().getComponent(reference, Player.getComponentType()); - effect.walk(new PlayerEffectContext(player)); - }); + world.execute(code); } } diff --git a/src/main/resources/config.sk b/src/main/resources/config.sk index 2d0f390e..c6fb6722 100644 --- a/src/main/resources/config.sk +++ b/src/main/resources/config.sk @@ -11,7 +11,6 @@ effect-commands: allow-ops: false # Whether or not ops can use effect commands. # If false, they will require the permission specified below in 'required-permission'. - # This currently does not work as Hytale does not support permissions this way. required-permission: hyskript.effect-commands # The permission required to use effect commands (if allow-ops is false). From 6fd528edd105b0855b48496969c0af4e68727035 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Sat, 7 Feb 2026 14:39:28 -0800 Subject: [PATCH 58/61] EvtPlayerDiscoverZone - --- .../plugin/elements/events/EventHandler.java | 2 + .../events/player/EvtPlayerDiscoverZone.java | 120 ++++++++++++++++++ 2 files changed, 122 insertions(+) create mode 100644 src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerDiscoverZone.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 3a55a8ce..c5dce8a2 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 @@ -18,6 +18,7 @@ import com.github.skriptdev.skript.plugin.elements.events.player.EvtPlayerChat; import com.github.skriptdev.skript.plugin.elements.events.player.EvtPlayerCraftRecipe; import com.github.skriptdev.skript.plugin.elements.events.player.EvtPlayerDamageBlock; +import com.github.skriptdev.skript.plugin.elements.events.player.EvtPlayerDiscoverZone; import com.github.skriptdev.skript.plugin.elements.events.player.EvtPlayerDrainFromWorld; import com.github.skriptdev.skript.plugin.elements.events.player.EvtPlayerDropItem; import com.github.skriptdev.skript.plugin.elements.events.player.EvtPlayerDropItemRequest; @@ -53,6 +54,7 @@ public static void register(SkriptRegistration registration) { EvtPlayerChat.register(registration); EvtPlayerCraftRecipe.register(registration); EvtPlayerDamageBlock.register(registration); + EvtPlayerDiscoverZone.register(registration); EvtPlayerDrainFromWorld.register(registration); EvtPlayerDropItem.register(registration); EvtPlayerDropItemRequest.register(registration); diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerDiscoverZone.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerDiscoverZone.java new file mode 100644 index 00000000..9cf09d6a --- /dev/null +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/player/EvtPlayerDiscoverZone.java @@ -0,0 +1,120 @@ +package com.github.skriptdev.skript.plugin.elements.events.player; + +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.event.WorldContext; +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.entities.Player; +import com.hypixel.hytale.server.core.event.events.ecs.DiscoverZoneEvent; +import com.hypixel.hytale.server.core.universe.world.World; +import com.hypixel.hytale.server.core.universe.world.WorldMapTracker; +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 org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class EvtPlayerDiscoverZone extends SystemEvent> { + + public static void register(SkriptRegistration reg) { + reg.newEvent(EvtPlayerDiscoverZone.class, "player discover zone") + .name("Player Discover Zone") + .experimental("This event doesn't seem to be called right now, server issues?!?!") + .setHandledContexts(DiscoverZoneContext.class) + .description("Called when a player discovers a zone.") + .since("INSERT VERSION") + .register(); + + reg.addSingleContextValue(DiscoverZoneContext.class, String.class, + "zone-name", DiscoverZoneContext::getZoneName); + reg.addSingleContextValue(DiscoverZoneContext.class, boolean.class, + "displaying", DiscoverZoneContext::isDisplaying); + reg.addSingleContextValue(DiscoverZoneContext.class, String.class, + "region-name", DiscoverZoneContext::getRegionName); + } + + private static DiscoverZoneSystem SYSTEM; + + @Override + public boolean init(Expression[] expressions, int matchedPattern, ParseContext parseContext) { + if (SYSTEM == null) { + SYSTEM = new DiscoverZoneSystem(); + applySystem(SYSTEM); + } + return true; + } + + @Override + public boolean check(TriggerContext ctx) { + return ctx instanceof DiscoverZoneContext; + } + + @Override + public String toString(@NotNull TriggerContext ctx, boolean debug) { + return "player discover zone"; + } + + public record DiscoverZoneContext(DiscoverZoneEvent event, Player player) + implements PlayerContext, WorldContext { + + @Override + public Player getPlayer() { + return this.player; + } + + @Override + public World getWorld() { + return this.player.getWorld(); + } + + public String getZoneName() { + WorldMapTracker.ZoneDiscoveryInfo discoveryInfo = this.event.getDiscoveryInfo(); + return discoveryInfo.zoneName(); + } + + public boolean isDisplaying() { + return this.event.getDiscoveryInfo().display(); + } + + public String getRegionName() { + return this.event.getDiscoveryInfo().regionName(); + } + + @Override + public String getName() { + return "discover zone context"; + } + } + + public static class DiscoverZoneSystem extends EntityEventSystem { + + protected DiscoverZoneSystem() { + super(DiscoverZoneEvent.class); + } + + @Override + public void handle(int i, @NotNull ArchetypeChunk archetypeChunk, + @NotNull Store store, @NotNull CommandBuffer commandBuffer, + @NotNull DiscoverZoneEvent discoverZoneEvent) { + + Ref ref = archetypeChunk.getReferenceTo(i); + Player player = store.getComponent(ref, Player.getComponentType()); + DiscoverZoneContext context = new DiscoverZoneContext(discoverZoneEvent, player); + TriggerMap.callTriggersByContext(context); + } + + @Override + public @Nullable Query getQuery() { + return Player.getComponentType(); + } + } + +} From 0e3edc6504079e3471c4cbeb26e229592975fb64 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Sat, 7 Feb 2026 15:12:21 -0800 Subject: [PATCH 59/61] EffSendTitle - add send title effect --- .../elements/effects/EffectHandler.java | 2 + .../elements/effects/player/EffSendTitle.java | 109 ++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 src/main/java/com/github/skriptdev/skript/plugin/elements/effects/player/EffSendTitle.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 dff7b037..d42cea73 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 @@ -16,6 +16,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.player.EffSendTitle; import com.github.skriptdev.skript.plugin.elements.effects.world.EffChunkRegenerate; import com.github.skriptdev.skript.plugin.elements.effects.world.EffExplosion; import com.github.skriptdev.skript.plugin.elements.effects.entity.EffInteraction; @@ -46,6 +47,7 @@ public static void register(SkriptRegistration registration) { EffBan.register(registration); EffConnect.register(registration); EffKick.register(registration); + EffSendTitle.register(registration); // WORLD EffChunkRegenerate.register(registration); diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/player/EffSendTitle.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/player/EffSendTitle.java new file mode 100644 index 00000000..d18eb462 --- /dev/null +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/player/EffSendTitle.java @@ -0,0 +1,109 @@ +package com.github.skriptdev.skript.plugin.elements.effects.player; + +import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; +import com.github.skriptdev.skript.api.utils.Utils; +import com.hypixel.hytale.component.Store; +import com.hypixel.hytale.server.core.Message; +import com.hypixel.hytale.server.core.entity.entities.Player; +import com.hypixel.hytale.server.core.universe.PlayerRef; +import com.hypixel.hytale.server.core.universe.world.World; +import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; +import com.hypixel.hytale.server.core.util.EventTitleUtil; +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 EffSendTitle extends Effect { + + public static void register(SkriptRegistration reg) { + reg.newEffect(EffSendTitle.class, "send [:major] title %string/message% to %players/playerrefs/worlds%", + "send [:major] title %string/message% with (subtitle|secondary title) %string/message% to %players/playerrefs/worlds%") + .name("Send Title") + .description("Sends a title to the player with an optional subtitle.", + "The title can be major or minor, depending on the syntax used.", + "Not sure what `major` is for, it doesn't seem to do anything different.") + .examples("send major title \"Hello World!\" to player") + .since("INSERT VERSION") + .register(); + + } + + private boolean major; + private Expression title; + private Expression subtitle; + private Expression receivers; + + @Override + public boolean init(Expression @NotNull [] expressions, int matchedPattern, @NotNull ParseContext parseContext) { + this.major = parseContext.hasMark("major"); + if (matchedPattern == 0) { + this.title = expressions[0]; + this.receivers = expressions[1]; + } else if (matchedPattern == 1) { + this.title = expressions[0]; + this.subtitle = expressions[1]; + this.receivers = expressions[2]; + } + + return true; + } + + @SuppressWarnings("removal") + @Override + protected void execute(@NotNull TriggerContext ctx) { + Object messageObject = this.title.getSingle(ctx).orElse(null); + if (messageObject == null) { + Utils.error("Cannot send title without a message."); + return; + } + + Message title; + if (messageObject instanceof String s) { + title = Message.raw(s); + } else if (messageObject instanceof Message m) { + title = m; + } else { + Utils.error("Cannot send title with invalid message type: %s", messageObject.getClass().getSimpleName()); + return; + } + + Message subtitle = Message.empty(); + if (this.subtitle != null) { + Object o = this.subtitle.getSingle(ctx).orElse(null); + if (o instanceof String s) { + subtitle = Message.raw(s); + } else if (o instanceof Message m) { + subtitle = m; + } + } + + // Defaults from the game + float duration = 4.0f; + float fadein = 1.5f; + float fadeout = 1.5f; + + for (Object object : this.receivers.getArray(ctx)) { + if (object instanceof Player player) { + EventTitleUtil.showEventTitleToPlayer(player.getPlayerRef(), title, subtitle, this.major); + } else if (object instanceof PlayerRef playerRef) { + EventTitleUtil.showEventTitleToPlayer(playerRef, title, subtitle, this.major); + } else if (object instanceof World world) { + Store store = world.getEntityStore().getStore(); + EventTitleUtil.showEventTitleToWorld(title, subtitle, this.major, null, duration, fadein, fadeout, store); + } + } + } + + @Override + public String toString(@NotNull TriggerContext ctx, boolean debug) { + String sub = this.subtitle != null ? "with subtitle " + this.subtitle.toString(ctx, debug) : ""; + return String.format("send %s title %s %s to %s", + this.major ? "major" : "minor", + this.title.toString(ctx, debug), + sub, + this.receivers.toString(ctx, debug)); + } + +} From c7787622663722c2bbcf38aa41fcd8cd5a20d04f Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Sat, 7 Feb 2026 15:16:44 -0800 Subject: [PATCH 60/61] EffSendTitle - move to other package as its not just for players --- .../skript/plugin/elements/effects/EffectHandler.java | 4 ++-- .../elements/effects/{player => other}/EffSendTitle.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) rename src/main/java/com/github/skriptdev/skript/plugin/elements/effects/{player => other}/EffSendTitle.java (96%) 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 d42cea73..d5851a83 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 @@ -16,7 +16,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.player.EffSendTitle; +import com.github.skriptdev.skript.plugin.elements.effects.other.EffSendTitle; import com.github.skriptdev.skript.plugin.elements.effects.world.EffChunkRegenerate; import com.github.skriptdev.skript.plugin.elements.effects.world.EffExplosion; import com.github.skriptdev.skript.plugin.elements.effects.entity.EffInteraction; @@ -42,12 +42,12 @@ public static void register(SkriptRegistration registration) { EffDelay.register(registration); EffExecuteCommand.register(registration); EffSendMessage.register(registration); + EffSendTitle.register(registration); // PLAYER EffBan.register(registration); EffConnect.register(registration); EffKick.register(registration); - EffSendTitle.register(registration); // WORLD EffChunkRegenerate.register(registration); diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/player/EffSendTitle.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/other/EffSendTitle.java similarity index 96% rename from src/main/java/com/github/skriptdev/skript/plugin/elements/effects/player/EffSendTitle.java rename to src/main/java/com/github/skriptdev/skript/plugin/elements/effects/other/EffSendTitle.java index d18eb462..93f3e6d4 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/player/EffSendTitle.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/other/EffSendTitle.java @@ -1,4 +1,4 @@ -package com.github.skriptdev.skript.plugin.elements.effects.player; +package com.github.skriptdev.skript.plugin.elements.effects.other; import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; import com.github.skriptdev.skript.api.utils.Utils; @@ -21,7 +21,7 @@ public static void register(SkriptRegistration reg) { reg.newEffect(EffSendTitle.class, "send [:major] title %string/message% to %players/playerrefs/worlds%", "send [:major] title %string/message% with (subtitle|secondary title) %string/message% to %players/playerrefs/worlds%") .name("Send Title") - .description("Sends a title to the player with an optional subtitle.", + .description("Sends a title to players/worlds with an optional subtitle.", "The title can be major or minor, depending on the syntax used.", "Not sure what `major` is for, it doesn't seem to do anything different.") .examples("send major title \"Hello World!\" to player") From 5438aca9b6190c2a08820a1301736b73e9c9b321 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Sat, 7 Feb 2026 15:28:32 -0800 Subject: [PATCH 61/61] README.md - update description --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 2d8183b2..9a21742c 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,9 @@ ![landscape](https://github.com/user-attachments/assets/2234f5ea-c2dc-4e79-b51c-4300b795e64f) -HySkript is a [**Skript**](https://github.com/SkriptLang/Skript) like plugin for Hytale servers. -It allows writing your own little plugins in English like syntaxes. -This way you can program your server to do marvelous things without having to learn Java. +**HySkript** brings the power of intuitive scripting to Hytale. +Inspired by the legendary Minecraft plugin [**Skript**](https://github.com/SkriptLang/Skript), HySkript allows you to customize your server using a natural, English-like syntax. +Whether you're creating custom commands or complex game mechanics, you can bring your vision to life instantly—no Java knowledge required. ## Docs/Tutorials: Check out our [**wiki**](https://github.com/SkriptDev/HySkript/wiki)