From 1a884ab4f56dd60be03251a54c0e1c25a38b5498 Mon Sep 17 00:00:00 2001 From: RappyTV Date: Sat, 22 Nov 2025 14:28:31 +0100 Subject: [PATCH 01/30] chore: Setup workspace --- build.gradle.kts | 23 ++++++++--------- .../autocommand/core/AutoCommandAddon.java | 18 +++++++++++++ .../autocommand/core/AutoCommandConfig.java} | 6 ++--- .../java/org/example/core/ExampleAddon.java | 25 ------------------- .../core/commands/ExamplePingCommand.java | 25 ------------------- .../core/commands/ExamplePingSubCommand.java | 18 ------------- .../listener/ExampleGameTickListener.java | 24 ------------------ .../{example => autocommand}/i18n/en_us.json | 2 +- settings.gradle.kts | 2 +- 9 files changed, 33 insertions(+), 110 deletions(-) create mode 100644 core/src/main/java/com/rappytv/autocommand/core/AutoCommandAddon.java rename core/src/main/java/{org/example/core/ExampleConfiguration.java => com/rappytv/autocommand/core/AutoCommandConfig.java} (69%) delete mode 100644 core/src/main/java/org/example/core/ExampleAddon.java delete mode 100644 core/src/main/java/org/example/core/commands/ExamplePingCommand.java delete mode 100644 core/src/main/java/org/example/core/commands/ExamplePingSubCommand.java delete mode 100644 core/src/main/java/org/example/core/listener/ExampleGameTickListener.java rename core/src/main/resources/assets/{example => autocommand}/i18n/en_us.json (81%) diff --git a/build.gradle.kts b/build.gradle.kts index da5e473..5641e16 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -9,27 +9,26 @@ group = "org.example" version = providers.environmentVariable("VERSION").getOrElse("1.0.0") labyMod { - defaultPackageName = "org.example" //change this to your main package name (used by all modules) + defaultPackageName = "com.rappytv.autocommand" + + addonInfo { + namespace = "autocommand" + displayName = "AutoCommand" + author = "RappyTV" + description = "Lets you automatically send commands when joining on servers" + minecraftVersion = "*" + version = rootProject.version.toString() + } minecraft { registerVersion(versions.toTypedArray()) { runs { getByName("client") { - // When the property is set to true, you can log in with a Minecraft account - // devLogin = true + devLogin = true } } } } - - addonInfo { - namespace = "example" - displayName = "ExampleAddon" - author = "Example Author" - description = "Example Description" - minecraftVersion = "*" - version = rootProject.version.toString() - } } subprojects { diff --git a/core/src/main/java/com/rappytv/autocommand/core/AutoCommandAddon.java b/core/src/main/java/com/rappytv/autocommand/core/AutoCommandAddon.java new file mode 100644 index 0000000..c26ed9d --- /dev/null +++ b/core/src/main/java/com/rappytv/autocommand/core/AutoCommandAddon.java @@ -0,0 +1,18 @@ +package com.rappytv.autocommand.core; + +import net.labymod.api.addon.LabyAddon; +import net.labymod.api.models.addon.annotation.AddonMain; + +@AddonMain +public class AutoCommandAddon extends LabyAddon { + + @Override + protected void enable() { + this.registerSettingCategory(); + } + + @Override + protected Class configurationClass() { + return AutoCommandConfig.class; + } +} diff --git a/core/src/main/java/org/example/core/ExampleConfiguration.java b/core/src/main/java/com/rappytv/autocommand/core/AutoCommandConfig.java similarity index 69% rename from core/src/main/java/org/example/core/ExampleConfiguration.java rename to core/src/main/java/com/rappytv/autocommand/core/AutoCommandConfig.java index 0faafb1..925fc6f 100644 --- a/core/src/main/java/org/example/core/ExampleConfiguration.java +++ b/core/src/main/java/com/rappytv/autocommand/core/AutoCommandConfig.java @@ -1,12 +1,10 @@ -package org.example.core; +package com.rappytv.autocommand.core; import net.labymod.api.addon.AddonConfig; import net.labymod.api.client.gui.screen.widget.widgets.input.SwitchWidget.SwitchSetting; -import net.labymod.api.configuration.loader.annotation.ConfigName; import net.labymod.api.configuration.loader.property.ConfigProperty; -@ConfigName("settings") -public class ExampleConfiguration extends AddonConfig { +public class AutoCommandConfig extends AddonConfig { @SwitchSetting private final ConfigProperty enabled = new ConfigProperty<>(true); diff --git a/core/src/main/java/org/example/core/ExampleAddon.java b/core/src/main/java/org/example/core/ExampleAddon.java deleted file mode 100644 index 47a4563..0000000 --- a/core/src/main/java/org/example/core/ExampleAddon.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.example.core; - -import net.labymod.api.addon.LabyAddon; -import net.labymod.api.models.addon.annotation.AddonMain; -import org.example.core.commands.ExamplePingCommand; -import org.example.core.listener.ExampleGameTickListener; - -@AddonMain -public class ExampleAddon extends LabyAddon { - - @Override - protected void enable() { - this.registerSettingCategory(); - - this.registerListener(new ExampleGameTickListener(this)); - this.registerCommand(new ExamplePingCommand()); - - this.logger().info("Enabled the Addon"); - } - - @Override - protected Class configurationClass() { - return ExampleConfiguration.class; - } -} diff --git a/core/src/main/java/org/example/core/commands/ExamplePingCommand.java b/core/src/main/java/org/example/core/commands/ExamplePingCommand.java deleted file mode 100644 index 5952915..0000000 --- a/core/src/main/java/org/example/core/commands/ExamplePingCommand.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.example.core.commands; - -import net.labymod.api.client.chat.command.Command; -import net.labymod.api.client.component.Component; -import net.labymod.api.client.component.format.NamedTextColor; - -public class ExamplePingCommand extends Command { - - public ExamplePingCommand() { - super("ping", "pong"); - - this.withSubCommand(new ExamplePingSubCommand()); - } - - @Override - public boolean execute(String prefix, String[] arguments) { - if (prefix.equalsIgnoreCase("ping")) { - this.displayMessage(Component.text("Ping!", NamedTextColor.AQUA)); - return false; - } - - this.displayMessage(Component.text("Pong!", NamedTextColor.GOLD)); - return true; - } -} diff --git a/core/src/main/java/org/example/core/commands/ExamplePingSubCommand.java b/core/src/main/java/org/example/core/commands/ExamplePingSubCommand.java deleted file mode 100644 index 8c6a981..0000000 --- a/core/src/main/java/org/example/core/commands/ExamplePingSubCommand.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.example.core.commands; - -import net.labymod.api.client.chat.command.SubCommand; -import net.labymod.api.client.component.Component; -import net.labymod.api.client.component.format.NamedTextColor; - -public class ExamplePingSubCommand extends SubCommand { - - protected ExamplePingSubCommand() { - super("pong"); - } - - @Override - public boolean execute(String prefix, String[] arguments) { - this.displayMessage(Component.text("Ping Pong!", NamedTextColor.GRAY)); - return true; - } -} diff --git a/core/src/main/java/org/example/core/listener/ExampleGameTickListener.java b/core/src/main/java/org/example/core/listener/ExampleGameTickListener.java deleted file mode 100644 index b631b85..0000000 --- a/core/src/main/java/org/example/core/listener/ExampleGameTickListener.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.example.core.listener; - -import net.labymod.api.event.Phase; -import net.labymod.api.event.Subscribe; -import net.labymod.api.event.client.lifecycle.GameTickEvent; -import org.example.core.ExampleAddon; - -public class ExampleGameTickListener { - - private final ExampleAddon addon; - - public ExampleGameTickListener(ExampleAddon addon) { - this.addon = addon; - } - - @Subscribe - public void onGameTick(GameTickEvent event) { - if (event.phase() != Phase.PRE) { - return; - } - - this.addon.logger().info(this.addon.configuration().enabled().get() ? "enabled" : "disabled"); - } -} diff --git a/core/src/main/resources/assets/example/i18n/en_us.json b/core/src/main/resources/assets/autocommand/i18n/en_us.json similarity index 81% rename from core/src/main/resources/assets/example/i18n/en_us.json rename to core/src/main/resources/assets/autocommand/i18n/en_us.json index 0850d97..9beaf0d 100644 --- a/core/src/main/resources/assets/example/i18n/en_us.json +++ b/core/src/main/resources/assets/autocommand/i18n/en_us.json @@ -1,5 +1,5 @@ { - "example": { + "autocommand": { "settings": { "enabled": { "name": "Enabled" diff --git a/settings.gradle.kts b/settings.gradle.kts index 6a0b6df..4cdca31 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,4 +1,4 @@ -rootProject.name = "labymod4-addon-template" +rootProject.name = "autocommand" pluginManagement { val labyGradlePluginVersion = "0.5.9" From e45972e369e10b86fa910ab69320cc2f2ef05362 Mon Sep 17 00:00:00 2001 From: RappyTV Date: Mon, 24 Nov 2025 21:31:36 +0100 Subject: [PATCH 02/30] feat: Implement basic functionality --- .../autocommand/api/AutoCommandMeta.java | 178 ++++++++++++++++++ .../autocommand/core/AutoCommandAddon.java | 11 ++ .../autocommand/core/AutoCommandConfig.java | 27 +++ .../core/listener/WorldEnterListener.java | 57 ++++++ 4 files changed, 273 insertions(+) create mode 100644 api/src/main/java/com/rappytv/autocommand/api/AutoCommandMeta.java create mode 100644 core/src/main/java/com/rappytv/autocommand/core/listener/WorldEnterListener.java diff --git a/api/src/main/java/com/rappytv/autocommand/api/AutoCommandMeta.java b/api/src/main/java/com/rappytv/autocommand/api/AutoCommandMeta.java new file mode 100644 index 0000000..1319e81 --- /dev/null +++ b/api/src/main/java/com/rappytv/autocommand/api/AutoCommandMeta.java @@ -0,0 +1,178 @@ +package com.rappytv.autocommand.api; + +import net.labymod.api.Laby; +import net.labymod.api.event.client.world.WorldEnterEvent; +import net.labymod.api.util.concurrent.task.Task; +import org.jetbrains.annotations.ApiStatus.Internal; +import org.jetbrains.annotations.NotNull; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.TimeUnit; + +public class AutoCommandMeta { + + private final boolean enabled; + private final String name; + private final String command; + private final float delay; + private final List contexts; + private Task task; + + @Internal + public AutoCommandMeta(boolean enabled, String name, String command, float delay, List contexts) { + this.enabled = enabled; + this.name = name; + this.command = command; + this.delay = delay; + this.contexts = contexts; + } + + /** + * Check if the auto command is enabled + * @return If the auto command is enabled + */ + public boolean isEnabled() { + return this.enabled; + } + + /** + * Get the auto command name + * @return The auto command name + */ + public String getName() { + return this.name; + } + + public String getCommand() { + return this.command; + } + + /** + * Get the delay after which the command gets executed + * @return The delay after which the command gets executed + */ + public float getDelay() { + return this.delay; + } + + /** + * Get the command contexts + * @return The command contexts + */ + public List getContexts() { + return this.contexts; + } + + /** + * Get the {@link Task} which runs the auto command + * @return The {@link Task} which runs the auto command + */ + @NotNull + public Task getTask() { + if(this.task == null) { + this.task = Task.builder(() -> Laby.references().chatExecutor().chat(this.command)) + .delay((long) this.delay, TimeUnit.SECONDS) + .build(); + } + return this.task; + } + + /** + * Get a {@link AutoCommandMeta.Builder} instance + * @return A builder instance + */ + public static Builder builder() { + return new Builder(); + } + + public static class Context { + + private final String name; + private final Type type; + + /** + * + * @param name The name of the server or singleplayer world + * @param type The type of the context + */ + public Context(String name, Type type) { + this.name = name; + this.type = type; + } + + /** + * Get the name of the server or singleplayer world + * @return The name of the server or singleplayer world + */ + public String getName() { + return this.name; + } + + /** + * Get the context type + * @return The context type + */ + public Type getType() { + return this.type; + } + + public enum Type { + SINGLEPLAYER(WorldEnterEvent.Type.SINGLEPLAYER), + MULTIPLAYER(WorldEnterEvent.Type.MULTIPLAYER); + + private final WorldEnterEvent.Type worldEnterType; + + Type(WorldEnterEvent.Type type) { + this.worldEnterType = type; + } + + public WorldEnterEvent.Type getWorldEnterType() { + return this.worldEnterType; + } + } + } + + public static class Builder { + + private boolean enabled = true; + private String name; + private String command; + private float delay = 0; + private List contexts = new ArrayList<>(); + + private Builder() {} + + public Builder enabled(boolean enabled) { + this.enabled = enabled; + return this; + } + + public Builder name(String name) { + this.name = name; + return this; + } + + public Builder command(String command) { + this.command = command; + return this; + } + + public Builder delay(float delay) { + this.delay = delay; + return this; + } + + public Builder contexts(List contexts) { + this.contexts = contexts; + return this; + } + + public AutoCommandMeta build() { + Objects.requireNonNull(this.name); + Objects.requireNonNull(this.command); + Objects.requireNonNull(this.contexts); + return new AutoCommandMeta(this.enabled, this.name, this.command, this.delay, this.contexts); + } + } +} diff --git a/core/src/main/java/com/rappytv/autocommand/core/AutoCommandAddon.java b/core/src/main/java/com/rappytv/autocommand/core/AutoCommandAddon.java index c26ed9d..c18587d 100644 --- a/core/src/main/java/com/rappytv/autocommand/core/AutoCommandAddon.java +++ b/core/src/main/java/com/rappytv/autocommand/core/AutoCommandAddon.java @@ -1,6 +1,8 @@ package com.rappytv.autocommand.core; +import com.rappytv.autocommand.core.listener.WorldEnterListener; import net.labymod.api.addon.LabyAddon; +import net.labymod.api.client.chat.command.Command; import net.labymod.api.models.addon.annotation.AddonMain; @AddonMain @@ -9,6 +11,15 @@ public class AutoCommandAddon extends LabyAddon { @Override protected void enable() { this.registerSettingCategory(); + this.registerListener(new WorldEnterListener(this)); + // For testing + this.registerCommand(new Command("test") { + @Override + public boolean execute(String prefix, String[] arguments) { + AutoCommandAddon.this.configuration().addAutoCommand(); + return true; + } + }); } @Override diff --git a/core/src/main/java/com/rappytv/autocommand/core/AutoCommandConfig.java b/core/src/main/java/com/rappytv/autocommand/core/AutoCommandConfig.java index 925fc6f..c66aa8b 100644 --- a/core/src/main/java/com/rappytv/autocommand/core/AutoCommandConfig.java +++ b/core/src/main/java/com/rappytv/autocommand/core/AutoCommandConfig.java @@ -1,11 +1,20 @@ package com.rappytv.autocommand.core; +import com.rappytv.autocommand.api.AutoCommandMeta; import net.labymod.api.addon.AddonConfig; import net.labymod.api.client.gui.screen.widget.widgets.input.SwitchWidget.SwitchSetting; +import net.labymod.api.configuration.loader.annotation.Exclude; import net.labymod.api.configuration.loader.property.ConfigProperty; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.function.Predicate; public class AutoCommandConfig extends AddonConfig { + @Exclude + private final List autoCommands = new ArrayList<>(); + @SwitchSetting private final ConfigProperty enabled = new ConfigProperty<>(true); @@ -13,4 +22,22 @@ public class AutoCommandConfig extends AddonConfig { public ConfigProperty enabled() { return this.enabled; } + + public void addAutoCommand() { + this.autoCommands.add(AutoCommandMeta.builder().name("fly").command("/fly").build()); + } + + public List getAutoCommands() { + return Collections.unmodifiableList(this.autoCommands); + } + + public List getAutoCommands(Predicate filter) { + List autoCommands = new ArrayList<>(); + for (AutoCommandMeta autoCommandMeta : this.autoCommands) { + if (filter.test(autoCommandMeta)) { + autoCommands.add(autoCommandMeta); + } + } + return Collections.unmodifiableList(autoCommands); + } } diff --git a/core/src/main/java/com/rappytv/autocommand/core/listener/WorldEnterListener.java b/core/src/main/java/com/rappytv/autocommand/core/listener/WorldEnterListener.java new file mode 100644 index 0000000..3122e69 --- /dev/null +++ b/core/src/main/java/com/rappytv/autocommand/core/listener/WorldEnterListener.java @@ -0,0 +1,57 @@ +package com.rappytv.autocommand.core.listener; + +import com.rappytv.autocommand.api.AutoCommandMeta; +import com.rappytv.autocommand.api.AutoCommandMeta.Context; +import com.rappytv.autocommand.core.AutoCommandAddon; +import net.labymod.api.Laby; +import net.labymod.api.client.network.server.ServerData; +import net.labymod.api.event.Subscribe; +import net.labymod.api.event.client.world.WorldEnterEvent; +import net.labymod.api.server.LocalWorld; +import org.jetbrains.annotations.Nullable; +import java.util.List; + +public class WorldEnterListener { + + private final AutoCommandAddon addon; + + public WorldEnterListener(AutoCommandAddon addon) { + this.addon = addon; + } + + @Subscribe + public void onWorldEnter(WorldEnterEvent event) { + List commands = this.addon.configuration().getAutoCommands((meta) -> { + String name = this.getContextName(event.type()); + for (Context context : meta.getContexts()) { + boolean isCorrectContext = context.getType().getWorldEnterType() == event.type(); + + if(isCorrectContext && context.getName().equals(name)) { + return true; + } + } + return false; + }); + + for (AutoCommandMeta command : commands) { + command.getTask().execute(); + } + } + + @Nullable + private String getContextName(WorldEnterEvent.Type type) { + return switch (type) { + case SINGLEPLAYER -> { + LocalWorld world = Laby.references().integratedServer().getLocalWorld(); + yield world != null ? world.folderName() : null; + } + case MULTIPLAYER -> { + ServerData server = Laby.labyAPI().serverController().getCurrentServerData(); + if (server == null || server.address().getHost().isEmpty()) { + yield null; + } + yield server.address().getHost(); + } + }; + } +} From 78ca1a57f357318f0924823a7ff8b0064399e089 Mon Sep 17 00:00:00 2001 From: RappyTV Date: Tue, 3 Feb 2026 00:50:33 +0300 Subject: [PATCH 03/30] chore: Keep template up-to-date --- .github/workflows/build.yml | 4 ++-- .gitignore | 2 ++ gradle.properties | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- settings.gradle.kts | 2 +- 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4ced302..c397fb2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,11 +12,11 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - name: Set up JDK 21 + - name: Set up JDK 25 uses: actions/setup-java@v4 with: distribution: 'corretto' - java-version: '21' + java-version: '25' - name: Cache Gradle dependencies uses: actions/cache@v4 with: diff --git a/.gitignore b/.gitignore index 47d9f66..69ec47e 100644 --- a/.gitignore +++ b/.gitignore @@ -73,6 +73,8 @@ run/ # LabyGradle | Addon Plugin build-data.txt .assetsroot +resources_index.json +access_widener_index.json # Don't ignore libraries !libs/*.jar \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 44dc10b..930aef8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,2 +1,2 @@ org.gradle.jvmargs=-Xmx4096m -net.labymod.minecraft-versions=1.8.9;1.12.2;1.16.5;1.17.1;1.18.2;1.19.2;1.19.3;1.19.4;1.20.1;1.20.2;1.20.4;1.20.5;1.20.6;1.21;1.21.1;1.21.3;1.21.4;1.21.5 \ No newline at end of file +versions=1.8.9;1.12.2;1.16.5;1.17.1;1.18.2;1.19.4;1.20.1;1.20.6;1.21;1.21.1;1.21.3;1.21.4;1.21.5;1.21.8;1.21.10;1.21.11 \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e1adfb4..ac57dd1 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/settings.gradle.kts b/settings.gradle.kts index 4cdca31..333eb76 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,7 +1,7 @@ rootProject.name = "autocommand" pluginManagement { - val labyGradlePluginVersion = "0.5.9" + val labyGradlePluginVersion = "0.6.0" buildscript { repositories { maven("https://dist.labymod.net/api/v1/maven/release/") From 28d57bc85689fca033e1f92555a4c7578eccacc6 Mon Sep 17 00:00:00 2001 From: RappyTV Date: Tue, 3 Feb 2026 00:50:50 +0300 Subject: [PATCH 04/30] chore: Make AutoCommandMeta constructor private rather than Internal --- .../java/com/rappytv/autocommand/api/AutoCommandMeta.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/api/src/main/java/com/rappytv/autocommand/api/AutoCommandMeta.java b/api/src/main/java/com/rappytv/autocommand/api/AutoCommandMeta.java index 1319e81..8d2bc71 100644 --- a/api/src/main/java/com/rappytv/autocommand/api/AutoCommandMeta.java +++ b/api/src/main/java/com/rappytv/autocommand/api/AutoCommandMeta.java @@ -3,7 +3,6 @@ import net.labymod.api.Laby; import net.labymod.api.event.client.world.WorldEnterEvent; import net.labymod.api.util.concurrent.task.Task; -import org.jetbrains.annotations.ApiStatus.Internal; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; @@ -19,8 +18,7 @@ public class AutoCommandMeta { private final List contexts; private Task task; - @Internal - public AutoCommandMeta(boolean enabled, String name, String command, float delay, List contexts) { + private AutoCommandMeta(boolean enabled, String name, String command, float delay, List contexts) { this.enabled = enabled; this.name = name; this.command = command; From d57a1349f972aeec642976b6b0d64a416b110b07 Mon Sep 17 00:00:00 2001 From: RappyTV Date: Tue, 3 Feb 2026 00:06:14 +0200 Subject: [PATCH 05/30] feat: Extend config functionality * Add AutoCommandConfig#removeAutoCommand * Deprecate AutoCommandConfig#addAutoCommand() * Add AutoCommandMeta#uuid and corresponding methods --- .../autocommand/api/AutoCommandMeta.java | 28 +++++++++++++++---- .../autocommand/core/AutoCommandAddon.java | 5 ++-- .../autocommand/core/AutoCommandConfig.java | 19 ++++++++++++- 3 files changed, 44 insertions(+), 8 deletions(-) diff --git a/api/src/main/java/com/rappytv/autocommand/api/AutoCommandMeta.java b/api/src/main/java/com/rappytv/autocommand/api/AutoCommandMeta.java index 8d2bc71..c0a9c3d 100644 --- a/api/src/main/java/com/rappytv/autocommand/api/AutoCommandMeta.java +++ b/api/src/main/java/com/rappytv/autocommand/api/AutoCommandMeta.java @@ -7,10 +7,12 @@ import java.util.ArrayList; import java.util.List; import java.util.Objects; +import java.util.UUID; import java.util.concurrent.TimeUnit; public class AutoCommandMeta { + private final UUID uuid; private final boolean enabled; private final String name; private final String command; @@ -18,7 +20,8 @@ public class AutoCommandMeta { private final List contexts; private Task task; - private AutoCommandMeta(boolean enabled, String name, String command, float delay, List contexts) { + private AutoCommandMeta(UUID uuid, boolean enabled, String name, String command, float delay, List contexts) { + this.uuid = uuid; this.enabled = enabled; this.name = name; this.command = command; @@ -26,6 +29,14 @@ private AutoCommandMeta(boolean enabled, String name, String command, float dela this.contexts = contexts; } + /** + * Get the auto command uuid + * @return The auto command uuid + */ + public UUID getUuid() { + return this.uuid; + } + /** * Check if the auto command is enabled * @return If the auto command is enabled @@ -133,6 +144,7 @@ public WorldEnterEvent.Type getWorldEnterType() { public static class Builder { + private UUID uuid = UUID.randomUUID(); private boolean enabled = true; private String name; private String command; @@ -141,17 +153,22 @@ public static class Builder { private Builder() {} + public Builder uuid(@NotNull UUID uuid) { + this.uuid = uuid; + return this; + } + public Builder enabled(boolean enabled) { this.enabled = enabled; return this; } - public Builder name(String name) { + public Builder name(@NotNull String name) { this.name = name; return this; } - public Builder command(String command) { + public Builder command(@NotNull String command) { this.command = command; return this; } @@ -161,16 +178,17 @@ public Builder delay(float delay) { return this; } - public Builder contexts(List contexts) { + public Builder contexts(@NotNull List contexts) { this.contexts = contexts; return this; } public AutoCommandMeta build() { + Objects.requireNonNull(this.uuid); Objects.requireNonNull(this.name); Objects.requireNonNull(this.command); Objects.requireNonNull(this.contexts); - return new AutoCommandMeta(this.enabled, this.name, this.command, this.delay, this.contexts); + return new AutoCommandMeta(this.uuid, this.enabled, this.name, this.command, this.delay, this.contexts); } } } diff --git a/core/src/main/java/com/rappytv/autocommand/core/AutoCommandAddon.java b/core/src/main/java/com/rappytv/autocommand/core/AutoCommandAddon.java index c18587d..fb5fbe3 100644 --- a/core/src/main/java/com/rappytv/autocommand/core/AutoCommandAddon.java +++ b/core/src/main/java/com/rappytv/autocommand/core/AutoCommandAddon.java @@ -12,8 +12,9 @@ public class AutoCommandAddon extends LabyAddon { protected void enable() { this.registerSettingCategory(); this.registerListener(new WorldEnterListener(this)); - // For testing - this.registerCommand(new Command("test") { + // For testing - will be removed as soon as config is done + this.registerCommand( new Command("test") { + @Deprecated @Override public boolean execute(String prefix, String[] arguments) { AutoCommandAddon.this.configuration().addAutoCommand(); diff --git a/core/src/main/java/com/rappytv/autocommand/core/AutoCommandConfig.java b/core/src/main/java/com/rappytv/autocommand/core/AutoCommandConfig.java index c66aa8b..c944ae1 100644 --- a/core/src/main/java/com/rappytv/autocommand/core/AutoCommandConfig.java +++ b/core/src/main/java/com/rappytv/autocommand/core/AutoCommandConfig.java @@ -5,9 +5,12 @@ import net.labymod.api.client.gui.screen.widget.widgets.input.SwitchWidget.SwitchSetting; import net.labymod.api.configuration.loader.annotation.Exclude; import net.labymod.api.configuration.loader.property.ConfigProperty; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Objects; +import java.util.UUID; import java.util.function.Predicate; public class AutoCommandConfig extends AddonConfig { @@ -23,8 +26,22 @@ public ConfigProperty enabled() { return this.enabled; } + @Deprecated public void addAutoCommand() { - this.autoCommands.add(AutoCommandMeta.builder().name("fly").command("/fly").build()); + this.addAutoCommand(AutoCommandMeta.builder().name("fly").command("/fly").build()); + } + + public void addAutoCommand(@NotNull AutoCommandMeta meta) { + Objects.requireNonNull(meta); + this.autoCommands.add(meta); + } + + public void removeAutoCommand(@NotNull AutoCommandMeta meta) { + this.autoCommands.remove(meta); + } + + public void removeAutoCommand(@NotNull UUID uuid) { + this.autoCommands.removeIf(meta -> meta.getUuid().equals(uuid)); } public List getAutoCommands() { From bb34d5b20a7a00574bac33416710dcfb9b0fda55 Mon Sep 17 00:00:00 2001 From: RappyTV Date: Tue, 3 Feb 2026 00:08:26 +0200 Subject: [PATCH 06/30] fix: Use correct path for minecraft versions --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 930aef8..6326517 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,2 +1,2 @@ org.gradle.jvmargs=-Xmx4096m -versions=1.8.9;1.12.2;1.16.5;1.17.1;1.18.2;1.19.4;1.20.1;1.20.6;1.21;1.21.1;1.21.3;1.21.4;1.21.5;1.21.8;1.21.10;1.21.11 \ No newline at end of file +net.labymod.minecraft-versions=1.8.9;1.12.2;1.16.5;1.17.1;1.18.2;1.19.4;1.20.1;1.20.6;1.21;1.21.1;1.21.3;1.21.4;1.21.5;1.21.8;1.21.10;1.21.11 \ No newline at end of file From 9e5a9354ed8377970d481d1b676b22a5057f0b36 Mon Sep 17 00:00:00 2001 From: RappyTV Date: Tue, 3 Feb 2026 00:11:47 +0200 Subject: [PATCH 07/30] chore: Refine AutoCommand predicate * Always include commands without contexts * Don't include disabled commands --- .../core/listener/WorldEnterListener.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/com/rappytv/autocommand/core/listener/WorldEnterListener.java b/core/src/main/java/com/rappytv/autocommand/core/listener/WorldEnterListener.java index 3122e69..0650ae5 100644 --- a/core/src/main/java/com/rappytv/autocommand/core/listener/WorldEnterListener.java +++ b/core/src/main/java/com/rappytv/autocommand/core/listener/WorldEnterListener.java @@ -22,14 +22,24 @@ public WorldEnterListener(AutoCommandAddon addon) { @Subscribe public void onWorldEnter(WorldEnterEvent event) { List commands = this.addon.configuration().getAutoCommands((meta) -> { + if(!meta.isEnabled()) { + return false; + } + List contexts = meta.getContexts(); + + if(contexts.isEmpty()) { + return true; + } String name = this.getContextName(event.type()); - for (Context context : meta.getContexts()) { + + for (Context context : contexts) { boolean isCorrectContext = context.getType().getWorldEnterType() == event.type(); if(isCorrectContext && context.getName().equals(name)) { return true; } } + return false; }); From a6f7af3ebfc000ab3477298ab2b138f9abb8d18e Mon Sep 17 00:00:00 2001 From: RappyTV Date: Sat, 7 Feb 2026 22:33:59 +0200 Subject: [PATCH 08/30] fix: Addon config fails to load --- .../autocommand/api/AutoCommandMeta.java | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/api/src/main/java/com/rappytv/autocommand/api/AutoCommandMeta.java b/api/src/main/java/com/rappytv/autocommand/api/AutoCommandMeta.java index c0a9c3d..f78e1df 100644 --- a/api/src/main/java/com/rappytv/autocommand/api/AutoCommandMeta.java +++ b/api/src/main/java/com/rappytv/autocommand/api/AutoCommandMeta.java @@ -5,20 +5,23 @@ import net.labymod.api.util.concurrent.task.Task; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.UUID; import java.util.concurrent.TimeUnit; public class AutoCommandMeta { + private static final Map tasks = new HashMap<>(); + private final UUID uuid; private final boolean enabled; private final String name; private final String command; private final float delay; private final List contexts; - private Task task; private AutoCommandMeta(UUID uuid, boolean enabled, String name, String command, float delay, List contexts) { this.uuid = uuid; @@ -79,12 +82,13 @@ public List getContexts() { */ @NotNull public Task getTask() { - if(this.task == null) { - this.task = Task.builder(() -> Laby.references().chatExecutor().chat(this.command)) - .delay((long) this.delay, TimeUnit.SECONDS) - .build(); - } - return this.task; + return tasks.computeIfAbsent(this.uuid, (uuid) -> this.buildTask()); + } + + private Task buildTask() { + return Task.builder(() -> Laby.references().chatExecutor().chat(this.command)) + .delay((long) this.delay, TimeUnit.SECONDS) + .build(); } /** From d17842daa9619639fc2814f223ae0832dcd68046 Mon Sep 17 00:00:00 2001 From: RappyTV Date: Sat, 7 Feb 2026 22:34:45 +0200 Subject: [PATCH 09/30] chore: Remove debugging method and command --- .../com/rappytv/autocommand/core/AutoCommandAddon.java | 10 ---------- .../rappytv/autocommand/core/AutoCommandConfig.java | 5 ----- 2 files changed, 15 deletions(-) diff --git a/core/src/main/java/com/rappytv/autocommand/core/AutoCommandAddon.java b/core/src/main/java/com/rappytv/autocommand/core/AutoCommandAddon.java index fb5fbe3..667e841 100644 --- a/core/src/main/java/com/rappytv/autocommand/core/AutoCommandAddon.java +++ b/core/src/main/java/com/rappytv/autocommand/core/AutoCommandAddon.java @@ -2,7 +2,6 @@ import com.rappytv.autocommand.core.listener.WorldEnterListener; import net.labymod.api.addon.LabyAddon; -import net.labymod.api.client.chat.command.Command; import net.labymod.api.models.addon.annotation.AddonMain; @AddonMain @@ -12,15 +11,6 @@ public class AutoCommandAddon extends LabyAddon { protected void enable() { this.registerSettingCategory(); this.registerListener(new WorldEnterListener(this)); - // For testing - will be removed as soon as config is done - this.registerCommand( new Command("test") { - @Deprecated - @Override - public boolean execute(String prefix, String[] arguments) { - AutoCommandAddon.this.configuration().addAutoCommand(); - return true; - } - }); } @Override diff --git a/core/src/main/java/com/rappytv/autocommand/core/AutoCommandConfig.java b/core/src/main/java/com/rappytv/autocommand/core/AutoCommandConfig.java index c944ae1..b734ab7 100644 --- a/core/src/main/java/com/rappytv/autocommand/core/AutoCommandConfig.java +++ b/core/src/main/java/com/rappytv/autocommand/core/AutoCommandConfig.java @@ -26,11 +26,6 @@ public ConfigProperty enabled() { return this.enabled; } - @Deprecated - public void addAutoCommand() { - this.addAutoCommand(AutoCommandMeta.builder().name("fly").command("/fly").build()); - } - public void addAutoCommand(@NotNull AutoCommandMeta meta) { Objects.requireNonNull(meta); this.autoCommands.add(meta); From 5a17ffcbd5336a46edc13157ed56e5f467e23019 Mon Sep 17 00:00:00 2001 From: RappyTV Date: Sat, 7 Feb 2026 22:35:36 +0200 Subject: [PATCH 10/30] chore: Add todo comment --- .../java/com/rappytv/autocommand/core/AutoCommandConfig.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/src/main/java/com/rappytv/autocommand/core/AutoCommandConfig.java b/core/src/main/java/com/rappytv/autocommand/core/AutoCommandConfig.java index b734ab7..509a43e 100644 --- a/core/src/main/java/com/rappytv/autocommand/core/AutoCommandConfig.java +++ b/core/src/main/java/com/rappytv/autocommand/core/AutoCommandConfig.java @@ -26,6 +26,8 @@ public ConfigProperty enabled() { return this.enabled; } + // TODO: Add activity to manage autocommands + public void addAutoCommand(@NotNull AutoCommandMeta meta) { Objects.requireNonNull(meta); this.autoCommands.add(meta); From d247f64892a648ba0684cc43ed27bd8c954a481a Mon Sep 17 00:00:00 2001 From: RappyTV Date: Sat, 13 Jun 2026 00:32:07 +0200 Subject: [PATCH 11/30] sync with addon template --- .github/workflows/build.yml | 29 ++++++++---------------- build.gradle.kts | 5 ++++ gradle.properties | 2 +- gradle/wrapper/gradle-wrapper.properties | 3 ++- scripts/update-gradle-sha.sh | 21 +++++++++++++++++ settings.gradle.kts | 4 ++-- 6 files changed, 41 insertions(+), 23 deletions(-) create mode 100644 scripts/update-gradle-sha.sh diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c397fb2..3a8b074 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -11,32 +11,23 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - name: Set up JDK 25 - uses: actions/setup-java@v4 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 with: distribution: 'corretto' java-version: '25' - - name: Cache Gradle dependencies - uses: actions/cache@v4 + - name: Set up Gradle + uses: gradle/actions/setup-gradle@5e2ebd065dc2488b7a6ad670704656cbbe1e8f60 # v6.1.1 with: - path: ~/.gradle/caches - key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} - restore-keys: | - gradle-${{ runner.os }}- - - name: Cache Gradle wrapper - uses: actions/cache@v4 - with: - path: ~/.gradle/wrapper - key: gradle-wrapper-${{ runner.os }}-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - restore-keys: | - gradle-wrapper-${{ runner.os }}- - - name: Grant execute permission for gradlew - run: chmod +x gradlew + validate-wrappers: true + cache-read-only: ${{ github.ref != format('refs/heads/{0}', github.event.repository.default_branch) }} - name: Build with Gradle run: ./gradlew build --full-stacktrace + - name: Create Release Artifact + run: ./gradlew createReleaseJar - name: Upload Artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: Artifacts - path: build/libs/*-release.jar + path: build/libs/*-release.jar \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 5641e16..59282ca 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -37,4 +37,9 @@ subprojects { group = rootProject.group version = rootProject.version + + extensions.findByType(JavaPluginExtension::class.java)?.apply { + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 + } } \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 6326517..138ade0 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,2 +1,2 @@ org.gradle.jvmargs=-Xmx4096m -net.labymod.minecraft-versions=1.8.9;1.12.2;1.16.5;1.17.1;1.18.2;1.19.4;1.20.1;1.20.6;1.21;1.21.1;1.21.3;1.21.4;1.21.5;1.21.8;1.21.10;1.21.11 \ No newline at end of file +net.labymod.minecraft-versions=1.8.9;1.12.2;1.16.5;1.17.1;1.18.2;1.19.4;1.20.1;1.20.4;1.20.6;1.21;1.21.1;1.21.3;1.21.4;1.21.5;1.21.8;1.21.10;1.21.11;26.1;26.1.1;26.1.2 \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ac57dd1..6ba24c8 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists +distributionSha256Sum=bafc141b619ad6350fd975fc903156dd5c151998cc8b058e8c1044ab5f7b031f diff --git a/scripts/update-gradle-sha.sh b/scripts/update-gradle-sha.sh new file mode 100644 index 0000000..bcb5094 --- /dev/null +++ b/scripts/update-gradle-sha.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash +# Pins distributionSha256Sum in gradle-wrapper.properties to the official +# checksum published by Gradle for the current distributionUrl. +set -euo pipefail + +PROPS="$(dirname "$0")/../gradle/wrapper/gradle-wrapper.properties" + +url="$(grep -E '^distributionUrl=' "$PROPS" | cut -d= -f2- | sed 's|\\:|:|g')" +[ -n "$url" ] || { echo "distributionUrl not found in $PROPS" >&2; exit 1; } + +sha="$(curl -fsSL "${url}.sha256")" +[ -n "$sha" ] || { echo "failed to fetch ${url}.sha256" >&2; exit 1; } + +if grep -qE '^distributionSha256Sum=' "$PROPS"; then + sed -i.bak "s|^distributionSha256Sum=.*|distributionSha256Sum=${sha}|" "$PROPS" + rm -f "${PROPS}.bak" +else + printf 'distributionSha256Sum=%s\n' "$sha" >> "$PROPS" +fi + +echo "pinned $(basename "$url") -> $sha" \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index 333eb76..eb0de36 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,10 +1,10 @@ rootProject.name = "autocommand" pluginManagement { - val labyGradlePluginVersion = "0.6.0" + val labyGradlePluginVersion = "0.8.1" buildscript { repositories { - maven("https://dist.labymod.net/api/v1/maven/release/") + maven("https://maven.laby.net/api/v1/maven/release/") maven("https://maven.neoforged.net/releases/") maven("https://maven.fabricmc.net/") gradlePluginPortal() From 6f784e0bea3153707d43167a9fecc114e2e0e6ca Mon Sep 17 00:00:00 2001 From: RappyTV Date: Sat, 13 Jun 2026 00:35:39 +0200 Subject: [PATCH 12/30] chore: reformat command meta --- .../autocommand/api/AutoCommandMeta.java | 47 ++++++++++--------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/api/src/main/java/com/rappytv/autocommand/api/AutoCommandMeta.java b/api/src/main/java/com/rappytv/autocommand/api/AutoCommandMeta.java index f78e1df..8d1a1d0 100644 --- a/api/src/main/java/com/rappytv/autocommand/api/AutoCommandMeta.java +++ b/api/src/main/java/com/rappytv/autocommand/api/AutoCommandMeta.java @@ -1,9 +1,5 @@ package com.rappytv.autocommand.api; -import net.labymod.api.Laby; -import net.labymod.api.event.client.world.WorldEnterEvent; -import net.labymod.api.util.concurrent.task.Task; -import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -11,6 +7,10 @@ import java.util.Objects; import java.util.UUID; import java.util.concurrent.TimeUnit; +import net.labymod.api.Laby; +import net.labymod.api.event.client.world.WorldEnterEvent; +import net.labymod.api.util.concurrent.task.Task; +import org.jetbrains.annotations.NotNull; public class AutoCommandMeta { @@ -23,7 +23,8 @@ public class AutoCommandMeta { private final float delay; private final List contexts; - private AutoCommandMeta(UUID uuid, boolean enabled, String name, String command, float delay, List contexts) { + private AutoCommandMeta(UUID uuid, boolean enabled, String name, String command, float delay, + List contexts) { this.uuid = uuid; this.enabled = enabled; this.name = name; @@ -34,6 +35,7 @@ private AutoCommandMeta(UUID uuid, boolean enabled, String name, String command, /** * Get the auto command uuid + * * @return The auto command uuid */ public UUID getUuid() { @@ -42,6 +44,7 @@ public UUID getUuid() { /** * Check if the auto command is enabled + * * @return If the auto command is enabled */ public boolean isEnabled() { @@ -50,6 +53,7 @@ public boolean isEnabled() { /** * Get the auto command name + * * @return The auto command name */ public String getName() { @@ -62,6 +66,7 @@ public String getCommand() { /** * Get the delay after which the command gets executed + * * @return The delay after which the command gets executed */ public float getDelay() { @@ -70,6 +75,7 @@ public float getDelay() { /** * Get the command contexts + * * @return The command contexts */ public List getContexts() { @@ -78,6 +84,7 @@ public List getContexts() { /** * Get the {@link Task} which runs the auto command + * * @return The {@link Task} which runs the auto command */ @NotNull @@ -93,40 +100,32 @@ private Task buildTask() { /** * Get a {@link AutoCommandMeta.Builder} instance + * * @return A builder instance */ public static Builder builder() { return new Builder(); } - public static class Context { - - private final String name; - private final Type type; - - /** - * - * @param name The name of the server or singleplayer world - * @param type The type of the context - */ - public Context(String name, Type type) { - this.name = name; - this.type = type; - } + public record Context(String name, Type type) { /** * Get the name of the server or singleplayer world + * * @return The name of the server or singleplayer world */ - public String getName() { + @Override + public String name() { return this.name; } /** * Get the context type + * * @return The context type */ - public Type getType() { + @Override + public Type type() { return this.type; } @@ -155,7 +154,8 @@ public static class Builder { private float delay = 0; private List contexts = new ArrayList<>(); - private Builder() {} + private Builder() { + } public Builder uuid(@NotNull UUID uuid) { this.uuid = uuid; @@ -192,7 +192,8 @@ public AutoCommandMeta build() { Objects.requireNonNull(this.name); Objects.requireNonNull(this.command); Objects.requireNonNull(this.contexts); - return new AutoCommandMeta(this.uuid, this.enabled, this.name, this.command, this.delay, this.contexts); + return new AutoCommandMeta(this.uuid, this.enabled, this.name, this.command, this.delay, + this.contexts); } } } From 1071f3706087b1e920d8b65e59c24cdfcf9b6d06 Mon Sep 17 00:00:00 2001 From: RappyTV Date: Sun, 14 Jun 2026 22:31:20 +0200 Subject: [PATCH 13/30] feat: add autocommand list --- .../autocommand/core/AutoCommandConfig.java | 20 ++- .../core/listener/WorldEnterListener.java | 6 +- .../ui/activity/CommandManagerActivity.java | 157 ++++++++++++++++++ .../core/ui/widget/AutoCommandWidget.java | 70 ++++++++ .../assets/autocommand/i18n/en_us.json | 7 + .../autocommand/textures/command_block.png | Bin 0 -> 8129 bytes .../themes/vanilla/lss/command-manager.lss | 87 ++++++++++ 7 files changed, 338 insertions(+), 9 deletions(-) create mode 100644 core/src/main/java/com/rappytv/autocommand/core/ui/activity/CommandManagerActivity.java create mode 100644 core/src/main/java/com/rappytv/autocommand/core/ui/widget/AutoCommandWidget.java create mode 100644 core/src/main/resources/assets/autocommand/textures/command_block.png create mode 100644 core/src/main/resources/assets/autocommand/themes/vanilla/lss/command-manager.lss diff --git a/core/src/main/java/com/rappytv/autocommand/core/AutoCommandConfig.java b/core/src/main/java/com/rappytv/autocommand/core/AutoCommandConfig.java index 509a43e..b54b6a6 100644 --- a/core/src/main/java/com/rappytv/autocommand/core/AutoCommandConfig.java +++ b/core/src/main/java/com/rappytv/autocommand/core/AutoCommandConfig.java @@ -1,17 +1,21 @@ package com.rappytv.autocommand.core; import com.rappytv.autocommand.api.AutoCommandMeta; -import net.labymod.api.addon.AddonConfig; -import net.labymod.api.client.gui.screen.widget.widgets.input.SwitchWidget.SwitchSetting; -import net.labymod.api.configuration.loader.annotation.Exclude; -import net.labymod.api.configuration.loader.property.ConfigProperty; -import org.jetbrains.annotations.NotNull; +import com.rappytv.autocommand.core.ui.activity.CommandManagerActivity; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.UUID; import java.util.function.Predicate; +import net.labymod.api.addon.AddonConfig; +import net.labymod.api.client.gui.screen.activity.Activity; +import net.labymod.api.client.gui.screen.widget.widgets.activity.settings.ActivitySettingWidget.ActivitySetting; +import net.labymod.api.client.gui.screen.widget.widgets.input.SwitchWidget.SwitchSetting; +import net.labymod.api.configuration.loader.annotation.Exclude; +import net.labymod.api.configuration.loader.property.ConfigProperty; +import net.labymod.api.util.MethodOrder; +import org.jetbrains.annotations.NotNull; public class AutoCommandConfig extends AddonConfig { @@ -26,7 +30,11 @@ public ConfigProperty enabled() { return this.enabled; } - // TODO: Add activity to manage autocommands + @MethodOrder(after = "enabled") + @ActivitySetting + public Activity commandManager() { + return new CommandManagerActivity(this); + } public void addAutoCommand(@NotNull AutoCommandMeta meta) { Objects.requireNonNull(meta); diff --git a/core/src/main/java/com/rappytv/autocommand/core/listener/WorldEnterListener.java b/core/src/main/java/com/rappytv/autocommand/core/listener/WorldEnterListener.java index 0650ae5..6a74ced 100644 --- a/core/src/main/java/com/rappytv/autocommand/core/listener/WorldEnterListener.java +++ b/core/src/main/java/com/rappytv/autocommand/core/listener/WorldEnterListener.java @@ -3,13 +3,13 @@ import com.rappytv.autocommand.api.AutoCommandMeta; import com.rappytv.autocommand.api.AutoCommandMeta.Context; import com.rappytv.autocommand.core.AutoCommandAddon; +import java.util.List; import net.labymod.api.Laby; import net.labymod.api.client.network.server.ServerData; import net.labymod.api.event.Subscribe; import net.labymod.api.event.client.world.WorldEnterEvent; import net.labymod.api.server.LocalWorld; import org.jetbrains.annotations.Nullable; -import java.util.List; public class WorldEnterListener { @@ -33,9 +33,9 @@ public void onWorldEnter(WorldEnterEvent event) { String name = this.getContextName(event.type()); for (Context context : contexts) { - boolean isCorrectContext = context.getType().getWorldEnterType() == event.type(); + boolean isCorrectContext = context.type().getWorldEnterType() == event.type(); - if(isCorrectContext && context.getName().equals(name)) { + if (isCorrectContext && context.name().equals(name)) { return true; } } diff --git a/core/src/main/java/com/rappytv/autocommand/core/ui/activity/CommandManagerActivity.java b/core/src/main/java/com/rappytv/autocommand/core/ui/activity/CommandManagerActivity.java new file mode 100644 index 0000000..7d8fdaf --- /dev/null +++ b/core/src/main/java/com/rappytv/autocommand/core/ui/activity/CommandManagerActivity.java @@ -0,0 +1,157 @@ +package com.rappytv.autocommand.core.ui.activity; + +import com.rappytv.autocommand.api.AutoCommandMeta; +import com.rappytv.autocommand.core.AutoCommandConfig; +import com.rappytv.autocommand.core.ui.widget.AutoCommandWidget; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import net.labymod.api.client.component.Component; +import net.labymod.api.client.component.format.NamedTextColor; +import net.labymod.api.client.gui.screen.Parent; +import net.labymod.api.client.gui.screen.activity.Activity; +import net.labymod.api.client.gui.screen.activity.AutoActivity; +import net.labymod.api.client.gui.screen.activity.Link; +import net.labymod.api.client.gui.screen.widget.widgets.ComponentWidget; +import net.labymod.api.client.gui.screen.widget.widgets.DivWidget; +import net.labymod.api.client.gui.screen.widget.widgets.input.ButtonWidget; +import net.labymod.api.client.gui.screen.widget.widgets.layout.FlexibleContentWidget; +import net.labymod.api.client.gui.screen.widget.widgets.layout.ScrollWidget; +import net.labymod.api.client.gui.screen.widget.widgets.layout.list.HorizontalListWidget; +import net.labymod.api.client.gui.screen.widget.widgets.layout.list.VerticalListWidget; +import net.labymod.api.client.gui.screen.widget.widgets.popup.SimpleAdvancedPopup; +import net.labymod.api.client.gui.screen.widget.widgets.popup.SimpleAdvancedPopup.SimplePopupButton; + +@AutoActivity +@Link("command-manager.lss") +public class CommandManagerActivity extends Activity { + + private final AutoCommandConfig config; + private final Map commandWidgets = new HashMap<>(); + private final VerticalListWidget commandList = new VerticalListWidget<>(); + + private AutoCommandMeta selectedCommand; + + private ButtonWidget editButton; + private ButtonWidget removeButton; + + public CommandManagerActivity(AutoCommandConfig config) { + this.config = config; + this.loadCommands(); + this.commandList.addId("command-list"); + this.commandList.setSelectCallback(selected -> { + this.selectedCommand = selected.getMeta(); + this.editButton.setEnabled(true); + this.removeButton.setEnabled(true); + }); + this.commandList.setDoubleClickCallback(ignored -> this.performAction(Action.EDIT)); + } + + @Override + public void initialize(Parent parent) { + super.initialize(parent); + + AutoCommandWidget selectedEntry = this.commandList.listSession().getSelectedEntry(); + if (selectedEntry != null) { + this.selectedCommand = selectedEntry.getMeta(); + } else { + this.selectedCommand = null; + } + + FlexibleContentWidget container = new FlexibleContentWidget(); + container.addId("command-container"); + for (AutoCommandWidget commandWidget : this.commandWidgets.values()) { + this.commandList.addChild(commandWidget); + } + + HorizontalListWidget buttons = new HorizontalListWidget(); + buttons.addId("buttons"); + + ButtonWidget addButton = ButtonWidget.i18n( + "labymod.ui.button.add", + () -> this.performAction(Action.ADD) + ); + + this.editButton = ButtonWidget.i18n( + "labymod.ui.button.edit", + () -> this.performAction(Action.EDIT) + ); + this.editButton.setEnabled(false); + + this.removeButton = ButtonWidget.i18n( + "labymod.ui.button.remove", + () -> this.performAction(Action.REMOVE) + ); + this.removeButton.setEnabled(false); + + buttons.addEntry(addButton); + buttons.addEntry(this.editButton); + buttons.addEntry(this.removeButton); + + DivWidget content = new DivWidget().addId("content"); + if (this.commandWidgets.isEmpty()) { + ComponentWidget errorComponent = ComponentWidget.i18n("autocommand.activity.empty"); + errorComponent.addId("error-component"); + + content.addChild(errorComponent); + } else { + content.addChild(new ScrollWidget(this.commandList)); + } + container.addFlexibleContent(content); + container.addContent(buttons); + + this.document.addChild(container); + } + + @Override + public void reload() { + this.loadCommands(); + super.reload(); + } + + private void loadCommands() { + this.commandWidgets.clear(); + for (AutoCommandMeta command : this.config.getAutoCommands()) { + this.commandWidgets.put(command.getUuid(), new AutoCommandWidget(command)); + } + } + + private void performAction(Action action) { + switch (action) { + case ADD -> { + AutoCommandMeta meta = AutoCommandMeta.builder() + .name("test") + .command("/joined") + .delay(4.5f) + .build(); + // TODO: show actual popup here + + this.config.addAutoCommand(meta); + this.reload(); + } + case EDIT -> { + // TODO: show edit popup here + this.reload(); + } + case REMOVE -> SimpleAdvancedPopup.builder() + .title(Component.translatable("autocommand.activity.remove.title")) + .description(Component.translatable( + "autocommand.activity.remove.description", + Component.text(this.selectedCommand.getName(), NamedTextColor.AQUA) + )) + .addButton(SimplePopupButton.confirm(simplePopupButton -> { + this.config.removeAutoCommand(this.selectedCommand); + this.reload(); + })) + .addButton(SimplePopupButton.cancel()) + .build() + .displayInOverlay(); + } + } + + private enum Action { + ADD, + EDIT, + REMOVE + } +} diff --git a/core/src/main/java/com/rappytv/autocommand/core/ui/widget/AutoCommandWidget.java b/core/src/main/java/com/rappytv/autocommand/core/ui/widget/AutoCommandWidget.java new file mode 100644 index 0000000..ab523bb --- /dev/null +++ b/core/src/main/java/com/rappytv/autocommand/core/ui/widget/AutoCommandWidget.java @@ -0,0 +1,70 @@ +package com.rappytv.autocommand.core.ui.widget; + +import com.rappytv.autocommand.api.AutoCommandMeta; +import java.text.DecimalFormat; +import net.labymod.api.client.gui.icon.Icon; +import net.labymod.api.client.gui.lss.property.annotation.AutoWidget; +import net.labymod.api.client.gui.screen.Parent; +import net.labymod.api.client.gui.screen.widget.Widget; +import net.labymod.api.client.gui.screen.widget.widgets.ComponentWidget; +import net.labymod.api.client.gui.screen.widget.widgets.layout.list.HorizontalListWidget; +import net.labymod.api.client.gui.screen.widget.widgets.layout.list.VerticalListWidget; +import net.labymod.api.client.gui.screen.widget.widgets.renderer.IconWidget; +import net.labymod.api.client.resources.ResourceLocation; + +@AutoWidget +public class AutoCommandWidget extends HorizontalListWidget { + + private static final ResourceLocation ICON = ResourceLocation.create("autocommand", + "textures/command_block.png"); + private static final DecimalFormat FORMAT = new DecimalFormat("#.##"); + + private final AutoCommandMeta meta; + + public AutoCommandWidget(AutoCommandMeta meta) { + this.meta = meta; + } + + @Override + public void initialize(Parent parent) { + super.initialize(parent); + + IconWidget icon = new IconWidget(Icon.texture(ICON)); + icon.addId("command-icon"); + + VerticalListWidget componentGroup = new VerticalListWidget<>(); + componentGroup.addId("component-group"); + + HorizontalListWidget firstLine = new HorizontalListWidget(); + firstLine.addId("first-line"); + + ComponentWidget nameComponent = ComponentWidget.text(this.meta.getName()); + nameComponent.addId("name-label"); + + firstLine.addEntry(nameComponent); + + if (this.meta.getDelay() > 0f) { + ComponentWidget delayComponent = ComponentWidget.text(this.formatDelay()); + delayComponent.addId("delay-label"); + + firstLine.addEntry(delayComponent); + } + + ComponentWidget commandComponent = ComponentWidget.text(this.meta.getCommand()); + commandComponent.addId("command-label"); + + componentGroup.addChild(firstLine); + componentGroup.addChild(commandComponent); + + this.addEntry(icon); + this.addEntry(componentGroup); + } + + public AutoCommandMeta getMeta() { + return this.meta; + } + + private String formatDelay() { + return String.format("⌚ %ss", FORMAT.format(this.meta.getDelay())); + } +} diff --git a/core/src/main/resources/assets/autocommand/i18n/en_us.json b/core/src/main/resources/assets/autocommand/i18n/en_us.json index 9beaf0d..78d23cd 100644 --- a/core/src/main/resources/assets/autocommand/i18n/en_us.json +++ b/core/src/main/resources/assets/autocommand/i18n/en_us.json @@ -4,6 +4,13 @@ "enabled": { "name": "Enabled" } + }, + "activity": { + "empty": "Nothing here yet.\nGo ahead and create an automated command!", + "remove": { + "title": "Are you sure?", + "description": "Do you want to delete your automated command %s?" + } } } } diff --git a/core/src/main/resources/assets/autocommand/textures/command_block.png b/core/src/main/resources/assets/autocommand/textures/command_block.png new file mode 100644 index 0000000000000000000000000000000000000000..9ee0927719dbbeb2cdc05c29684585aac3fe3698 GIT binary patch literal 8129 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 Date: Wed, 8 Jul 2026 20:45:09 +0200 Subject: [PATCH 14/30] feat: add manage popup --- .../autocommand/api/AutoCommandMeta.java | 42 ++++++++++++---- .../ui/activity/CommandManagerActivity.java | 23 ++++----- .../core/ui/popup/EditAutoCommandPopup.java | 48 +++++++++++++++++++ .../themes/vanilla/lss/command-popup.lss | 0 4 files changed, 91 insertions(+), 22 deletions(-) create mode 100644 core/src/main/java/com/rappytv/autocommand/core/ui/popup/EditAutoCommandPopup.java create mode 100644 core/src/main/resources/assets/autocommand/themes/vanilla/lss/command-popup.lss diff --git a/api/src/main/java/com/rappytv/autocommand/api/AutoCommandMeta.java b/api/src/main/java/com/rappytv/autocommand/api/AutoCommandMeta.java index 8d1a1d0..327771b 100644 --- a/api/src/main/java/com/rappytv/autocommand/api/AutoCommandMeta.java +++ b/api/src/main/java/com/rappytv/autocommand/api/AutoCommandMeta.java @@ -16,12 +16,12 @@ public class AutoCommandMeta { private static final Map tasks = new HashMap<>(); - private final UUID uuid; - private final boolean enabled; - private final String name; - private final String command; - private final float delay; - private final List contexts; + private UUID uuid; + private boolean enabled; + private String name; + private String command; + private float delay; + private List contexts; private AutoCommandMeta(UUID uuid, boolean enabled, String name, String command, float delay, List contexts) { @@ -42,13 +42,21 @@ public UUID getUuid() { return this.uuid; } + public void setUuid(UUID uuid) { + this.uuid = uuid; + } + /** * Check if the auto command is enabled * * @return If the auto command is enabled */ public boolean isEnabled() { - return this.enabled; + return this.enabled && !this.command.isBlank(); + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; } /** @@ -60,10 +68,18 @@ public String getName() { return this.name; } + public void setName(String name) { + this.name = name; + } + public String getCommand() { return this.command; } + public void setCommand(String command) { + this.command = command; + } + /** * Get the delay after which the command gets executed * @@ -73,6 +89,10 @@ public float getDelay() { return this.delay; } + public void setDelay(float delay) { + this.delay = delay; + } + /** * Get the command contexts * @@ -82,6 +102,10 @@ public List getContexts() { return this.contexts; } + public void setContexts(List contexts) { + this.contexts = contexts; + } + /** * Get the {@link Task} which runs the auto command * @@ -149,8 +173,8 @@ public static class Builder { private UUID uuid = UUID.randomUUID(); private boolean enabled = true; - private String name; - private String command; + private String name = ""; + private String command = ""; private float delay = 0; private List contexts = new ArrayList<>(); diff --git a/core/src/main/java/com/rappytv/autocommand/core/ui/activity/CommandManagerActivity.java b/core/src/main/java/com/rappytv/autocommand/core/ui/activity/CommandManagerActivity.java index 7d8fdaf..e60d89a 100644 --- a/core/src/main/java/com/rappytv/autocommand/core/ui/activity/CommandManagerActivity.java +++ b/core/src/main/java/com/rappytv/autocommand/core/ui/activity/CommandManagerActivity.java @@ -2,6 +2,7 @@ import com.rappytv.autocommand.api.AutoCommandMeta; import com.rappytv.autocommand.core.AutoCommandConfig; +import com.rappytv.autocommand.core.ui.popup.EditAutoCommandPopup; import com.rappytv.autocommand.core.ui.widget.AutoCommandWidget; import java.util.HashMap; import java.util.Map; @@ -118,21 +119,17 @@ private void loadCommands() { private void performAction(Action action) { switch (action) { - case ADD -> { - AutoCommandMeta meta = AutoCommandMeta.builder() - .name("test") - .command("/joined") - .delay(4.5f) - .build(); - // TODO: show actual popup here - - this.config.addAutoCommand(meta); + case ADD -> new EditAutoCommandPopup(null, (command) -> { + this.config.addAutoCommand(command); + this.selectedCommand = command; this.reload(); - } - case EDIT -> { - // TODO: show edit popup here + }).displayInOverlay(); + case EDIT -> new EditAutoCommandPopup(this.selectedCommand, (command) -> { + this.config.removeAutoCommand(this.selectedCommand); + this.config.addAutoCommand(command); + this.selectedCommand = command; this.reload(); - } + }).displayInOverlay(); case REMOVE -> SimpleAdvancedPopup.builder() .title(Component.translatable("autocommand.activity.remove.title")) .description(Component.translatable( diff --git a/core/src/main/java/com/rappytv/autocommand/core/ui/popup/EditAutoCommandPopup.java b/core/src/main/java/com/rappytv/autocommand/core/ui/popup/EditAutoCommandPopup.java new file mode 100644 index 0000000..cc87dfa --- /dev/null +++ b/core/src/main/java/com/rappytv/autocommand/core/ui/popup/EditAutoCommandPopup.java @@ -0,0 +1,48 @@ +package com.rappytv.autocommand.core.ui.popup; + +import com.rappytv.autocommand.api.AutoCommandMeta; +import java.util.ArrayList; +import java.util.function.Consumer; +import net.labymod.api.client.component.Component; +import net.labymod.api.client.gui.screen.activity.Link; +import net.labymod.api.client.gui.screen.widget.widgets.input.CheckBoxWidget; +import net.labymod.api.client.gui.screen.widget.widgets.input.CheckBoxWidget.State; +import net.labymod.api.client.gui.screen.widget.widgets.input.SliderWidget; +import net.labymod.api.client.gui.screen.widget.widgets.input.TextFieldWidget; +import net.labymod.api.client.gui.screen.widget.widgets.layout.FlexibleContentWidget; +import net.labymod.api.client.gui.screen.widget.widgets.layout.list.VerticalListWidget; +import net.labymod.api.client.gui.screen.widget.widgets.popup.SimpleAdvancedPopup; + +@Link("command-popup.lss") +public class EditAutoCommandPopup extends SimpleAdvancedPopup { + + private final AutoCommandMeta meta; + + private CheckBoxWidget enabledCheckbox; + private TextFieldWidget nameTextField; + private TextFieldWidget commandTextField; + private SliderWidget delaySlider; + + public EditAutoCommandPopup(AutoCommandMeta meta, Consumer onSubmit) { + boolean create = meta == null; + this.meta = create ? AutoCommandMeta.builder().build() : meta; + + super.title = Component.translatable( + "autocommand.popup.component." + (create ? "add" : "edit")); + super.buttons = new ArrayList<>(); + super.buttons.add(SimplePopupButton.confirm((ignored) -> { + this.meta.setEnabled(this.enabledCheckbox.state() == State.CHECKED); + this.meta.setName(this.nameTextField.getText()); + this.meta.setName(this.commandTextField.getText()); + this.meta.setDelay(this.delaySlider.getValue()); + onSubmit.accept(this.meta); + })); + super.buttons.add(SimplePopupButton.cancel()); + super.widgetFunction = document -> + document.addChild(this.buildOptionArea()); + } + + private VerticalListWidget buildOptionArea() { + return null; + } +} diff --git a/core/src/main/resources/assets/autocommand/themes/vanilla/lss/command-popup.lss b/core/src/main/resources/assets/autocommand/themes/vanilla/lss/command-popup.lss new file mode 100644 index 0000000..e69de29 From cca3893f6185f13f9ea35c080fc492f4648fbd6e Mon Sep 17 00:00:00 2001 From: RappyTV Date: Wed, 8 Jul 2026 22:11:45 +0200 Subject: [PATCH 15/30] feat: implement management popup --- .../autocommand/api/AutoCommandMeta.java | 6 +- .../core/ui/popup/EditAutoCommandPopup.java | 87 ++++++++++++++++++- .../assets/autocommand/i18n/en_us.json | 21 +++++ .../themes/vanilla/lss/command-popup.lss | 29 +++++++ 4 files changed, 138 insertions(+), 5 deletions(-) diff --git a/api/src/main/java/com/rappytv/autocommand/api/AutoCommandMeta.java b/api/src/main/java/com/rappytv/autocommand/api/AutoCommandMeta.java index 327771b..868ec96 100644 --- a/api/src/main/java/com/rappytv/autocommand/api/AutoCommandMeta.java +++ b/api/src/main/java/com/rappytv/autocommand/api/AutoCommandMeta.java @@ -52,7 +52,7 @@ public void setUuid(UUID uuid) { * @return If the auto command is enabled */ public boolean isEnabled() { - return this.enabled && !this.command.isBlank(); + return this.enabled; } public void setEnabled(boolean enabled) { @@ -122,6 +122,10 @@ private Task buildTask() { .build(); } + public boolean isValid() { + return !this.name.isBlank() && !this.command.isBlank(); + } + /** * Get a {@link AutoCommandMeta.Builder} instance * diff --git a/core/src/main/java/com/rappytv/autocommand/core/ui/popup/EditAutoCommandPopup.java b/core/src/main/java/com/rappytv/autocommand/core/ui/popup/EditAutoCommandPopup.java index cc87dfa..db1c4eb 100644 --- a/core/src/main/java/com/rappytv/autocommand/core/ui/popup/EditAutoCommandPopup.java +++ b/core/src/main/java/com/rappytv/autocommand/core/ui/popup/EditAutoCommandPopup.java @@ -4,7 +4,10 @@ import java.util.ArrayList; import java.util.function.Consumer; import net.labymod.api.client.component.Component; +import net.labymod.api.client.component.TranslatableComponent; import net.labymod.api.client.gui.screen.activity.Link; +import net.labymod.api.client.gui.screen.widget.Widget; +import net.labymod.api.client.gui.screen.widget.widgets.ComponentWidget; import net.labymod.api.client.gui.screen.widget.widgets.input.CheckBoxWidget; import net.labymod.api.client.gui.screen.widget.widgets.input.CheckBoxWidget.State; import net.labymod.api.client.gui.screen.widget.widgets.input.SliderWidget; @@ -17,6 +20,7 @@ public class EditAutoCommandPopup extends SimpleAdvancedPopup { private final AutoCommandMeta meta; + private final SimplePopupButton confirmButton; private CheckBoxWidget enabledCheckbox; private TextFieldWidget nameTextField; @@ -27,10 +31,15 @@ public EditAutoCommandPopup(AutoCommandMeta meta, Consumer onSu boolean create = meta == null; this.meta = create ? AutoCommandMeta.builder().build() : meta; - super.title = Component.translatable( - "autocommand.popup.component." + (create ? "add" : "edit")); + TranslatableComponent title = Component.translatable( + "autocommand.popup.title." + (create ? "add" : "edit") + ); + if(!create) { + title.argument(Component.text(this.meta.getName())); + } + super.title = title; super.buttons = new ArrayList<>(); - super.buttons.add(SimplePopupButton.confirm((ignored) -> { + super.buttons.add(this.confirmButton = SimplePopupButton.confirm((ignored) -> { this.meta.setEnabled(this.enabledCheckbox.state() == State.CHECKED); this.meta.setName(this.nameTextField.getText()); this.meta.setName(this.commandTextField.getText()); @@ -43,6 +52,76 @@ public EditAutoCommandPopup(AutoCommandMeta meta, Consumer onSu } private VerticalListWidget buildOptionArea() { - return null; + VerticalListWidget options = new VerticalListWidget<>(); + options.addId("options"); + + options.addChild(this.buildEnabledCheckbox()); + options.addChild(this.buildNameTextField()); + options.addChild(this.buildCommandTextField()); + options.addChild(this.buildDelaySlider()); + this.updateConfirmButton(); + + // TODO: add context management + return options; + } + + private FlexibleContentWidget buildEnabledCheckbox() { + this.enabledCheckbox = new CheckBoxWidget(); + this.enabledCheckbox.addId("enabled-checkbox"); + this.enabledCheckbox.setState(this.meta.isEnabled() ? State.CHECKED : State.UNCHECKED); + + return this.buildOptionArea("enabled", this.enabledCheckbox); + } + + private FlexibleContentWidget buildNameTextField() { + this.nameTextField = new TextFieldWidget(); + this.nameTextField.addId("name-textfield"); + this.nameTextField.maximalLength(48); + this.nameTextField.setText(this.meta.getName()); + + return this.buildOptionArea("name", this.nameTextField); + } + + private FlexibleContentWidget buildCommandTextField() { + this.commandTextField = new TextFieldWidget(); + this.commandTextField.addId("command-textfield"); + this.commandTextField.maximalLength(1024); + this.commandTextField.setText(this.meta.getCommand()); + + return this.buildOptionArea("command", this.commandTextField); + } + + private FlexibleContentWidget buildDelaySlider() { + this.delaySlider = new SliderWidget((value) -> this.updateConfirmButton()); + this.delaySlider.addId("delay-slider"); + this.delaySlider.range(0, 30); + this.delaySlider.setValue(this.meta.getDelay()); + + return this.buildOptionArea("delay", this.delaySlider); + } + + private FlexibleContentWidget buildOptionArea(String id, Widget widget) { + ComponentWidget labelComponent = ComponentWidget.i18n("autocommand.popup." + id + ".name"); + labelComponent.addId("option-label"); + + FlexibleContentWidget area = new FlexibleContentWidget(); + area.addId("option-area"); + area.addId("option-area-" + id); + area.addContent(labelComponent); + area.addContent(widget); + widget.setActionListener(this::updateConfirmButton); + + return area; + } + + private void updateConfirmButton() { + boolean valid = !this.nameTextField.getText().isBlank() && !this.commandTextField.getText().isBlank(); + boolean enabledChanged = this.enabledCheckbox.state() == (this.meta.isEnabled() ? State.UNCHECKED : State.CHECKED); + boolean changed = enabledChanged + || !this.nameTextField.getText().equals(this.meta.getName()) + || !this.commandTextField.getText().equals(this.meta.getCommand()) + || this.delaySlider.getValue() != this.meta.getDelay(); + + this.confirmButton.enabled(valid && changed); } } diff --git a/core/src/main/resources/assets/autocommand/i18n/en_us.json b/core/src/main/resources/assets/autocommand/i18n/en_us.json index 78d23cd..c9b892a 100644 --- a/core/src/main/resources/assets/autocommand/i18n/en_us.json +++ b/core/src/main/resources/assets/autocommand/i18n/en_us.json @@ -3,6 +3,9 @@ "settings": { "enabled": { "name": "Enabled" + }, + "commandManager": { + "name": "Manage automated commands" } }, "activity": { @@ -11,6 +14,24 @@ "title": "Are you sure?", "description": "Do you want to delete your automated command %s?" } + }, + "popup": { + "title": { + "add": "Create automated command", + "edit": "Edit \"%s\"" + }, + "enabled": { + "name": "Enabled" + }, + "name": { + "name": "Name" + }, + "command": { + "name": "Command" + }, + "delay": { + "name": "Delay (in seconds)" + } } } } diff --git a/core/src/main/resources/assets/autocommand/themes/vanilla/lss/command-popup.lss b/core/src/main/resources/assets/autocommand/themes/vanilla/lss/command-popup.lss index e69de29..3038942 100644 --- a/core/src/main/resources/assets/autocommand/themes/vanilla/lss/command-popup.lss +++ b/core/src/main/resources/assets/autocommand/themes/vanilla/lss/command-popup.lss @@ -0,0 +1,29 @@ +.options { + height: fit-content; + width: 150; + space-between-entries: 6; + + .option-area { + height: fit-content; + + .option-label { + font-size: 0.8; + alignment-x: center; + margin-bottom: 3; + } + + .enabled-checkbox { + alignment-x: center; + } + + TextField { + width: 80%; + } + + Slider { + width: 80%; + height: fit-content; + alignment-x: center; + } + } +} \ No newline at end of file From d95de9a9c26180bfc87734af11948c17359de732 Mon Sep 17 00:00:00 2001 From: RappyTV Date: Thu, 9 Jul 2026 01:18:37 +0200 Subject: [PATCH 16/30] chore: add context count to AutoCommandWidget --- .../core/ui/widget/AutoCommandWidget.java | 27 ++++++++++++++++--- .../themes/vanilla/lss/command-manager.lss | 3 +-- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/com/rappytv/autocommand/core/ui/widget/AutoCommandWidget.java b/core/src/main/java/com/rappytv/autocommand/core/ui/widget/AutoCommandWidget.java index ab523bb..7a00520 100644 --- a/core/src/main/java/com/rappytv/autocommand/core/ui/widget/AutoCommandWidget.java +++ b/core/src/main/java/com/rappytv/autocommand/core/ui/widget/AutoCommandWidget.java @@ -2,6 +2,8 @@ import com.rappytv.autocommand.api.AutoCommandMeta; import java.text.DecimalFormat; +import net.labymod.api.client.component.Component; +import net.labymod.api.client.component.format.NamedTextColor; import net.labymod.api.client.gui.icon.Icon; import net.labymod.api.client.gui.lss.property.annotation.AutoWidget; import net.labymod.api.client.gui.screen.Parent; @@ -43,11 +45,24 @@ public void initialize(Parent parent) { firstLine.addEntry(nameComponent); - if (this.meta.getDelay() > 0f) { - ComponentWidget delayComponent = ComponentWidget.text(this.formatDelay()); - delayComponent.addId("delay-label"); + Component metaComponent = Component.empty(); + boolean addDelay = this.meta.getDelay() > 0f; + boolean addContext = !this.meta.getContexts().isEmpty(); - firstLine.addEntry(delayComponent); + if (addDelay) { + metaComponent.append(Component.text(this.formatDelay(), NamedTextColor.YELLOW)); + } + if(addContext) { + if(addDelay) { + metaComponent.append(Component.text(" | ", NamedTextColor.DARK_GRAY)); + } + metaComponent.append(Component.text(this.formatContexts(), NamedTextColor.AQUA)); + } + ComponentWidget metaComponentWidget = ComponentWidget.component(metaComponent); + metaComponentWidget.addId("meta-label"); + + if(addDelay || addContext) { + firstLine.addEntry(metaComponentWidget); } ComponentWidget commandComponent = ComponentWidget.text(this.meta.getCommand()); @@ -67,4 +82,8 @@ public AutoCommandMeta getMeta() { private String formatDelay() { return String.format("⌚ %ss", FORMAT.format(this.meta.getDelay())); } + + private String formatContexts() { + return String.format("🌍 %s", this.meta.getContexts().size()); + } } diff --git a/core/src/main/resources/assets/autocommand/themes/vanilla/lss/command-manager.lss b/core/src/main/resources/assets/autocommand/themes/vanilla/lss/command-manager.lss index 6114218..b574688 100644 --- a/core/src/main/resources/assets/autocommand/themes/vanilla/lss/command-manager.lss +++ b/core/src/main/resources/assets/autocommand/themes/vanilla/lss/command-manager.lss @@ -64,8 +64,7 @@ AutoCommand { alignment-x: left; } - .delay-label { - text-color: yellow; + .meta-label { alignment: right; } } From 348c337c066b884b84552d92d90fb038154f3f20 Mon Sep 17 00:00:00 2001 From: RappyTV Date: Thu, 9 Jul 2026 01:21:15 +0200 Subject: [PATCH 17/30] chore: add textfield placeholders --- .../core/ui/popup/EditAutoCommandPopup.java | 18 +++++++++++++++++- .../assets/autocommand/i18n/en_us.json | 6 ++++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/com/rappytv/autocommand/core/ui/popup/EditAutoCommandPopup.java b/core/src/main/java/com/rappytv/autocommand/core/ui/popup/EditAutoCommandPopup.java index db1c4eb..41e4c95 100644 --- a/core/src/main/java/com/rappytv/autocommand/core/ui/popup/EditAutoCommandPopup.java +++ b/core/src/main/java/com/rappytv/autocommand/core/ui/popup/EditAutoCommandPopup.java @@ -19,6 +19,8 @@ @Link("command-popup.lss") public class EditAutoCommandPopup extends SimpleAdvancedPopup { + private static final String I18N_FORMAT = "autocommand.popup.%s.%s"; + private final AutoCommandMeta meta; private final SimplePopupButton confirmButton; @@ -78,6 +80,11 @@ private FlexibleContentWidget buildNameTextField() { this.nameTextField.addId("name-textfield"); this.nameTextField.maximalLength(48); this.nameTextField.setText(this.meta.getName()); + this.nameTextField.placeholder(Component.translatable(String.format( + I18N_FORMAT, + "name", + "placeholder" + ))); return this.buildOptionArea("name", this.nameTextField); } @@ -87,6 +94,11 @@ private FlexibleContentWidget buildCommandTextField() { this.commandTextField.addId("command-textfield"); this.commandTextField.maximalLength(1024); this.commandTextField.setText(this.meta.getCommand()); + this.commandTextField.placeholder(Component.translatable(String.format( + I18N_FORMAT, + "command", + "placeholder" + ))); return this.buildOptionArea("command", this.commandTextField); } @@ -101,7 +113,11 @@ private FlexibleContentWidget buildDelaySlider() { } private FlexibleContentWidget buildOptionArea(String id, Widget widget) { - ComponentWidget labelComponent = ComponentWidget.i18n("autocommand.popup." + id + ".name"); + ComponentWidget labelComponent = ComponentWidget.i18n(String.format( + I18N_FORMAT, + id, + "name" + )); labelComponent.addId("option-label"); FlexibleContentWidget area = new FlexibleContentWidget(); diff --git a/core/src/main/resources/assets/autocommand/i18n/en_us.json b/core/src/main/resources/assets/autocommand/i18n/en_us.json index c9b892a..b7e586f 100644 --- a/core/src/main/resources/assets/autocommand/i18n/en_us.json +++ b/core/src/main/resources/assets/autocommand/i18n/en_us.json @@ -24,10 +24,12 @@ "name": "Enabled" }, "name": { - "name": "Name" + "name": "Name", + "placeholder": "Example name" }, "command": { - "name": "Command" + "name": "Command", + "placeholder": "/example" }, "delay": { "name": "Delay (in seconds)" From 0f0b1285f544bf0c22359571e85d4e77bd250731 Mon Sep 17 00:00:00 2001 From: RappyTV Date: Thu, 9 Jul 2026 02:43:12 +0200 Subject: [PATCH 18/30] feat: add context manager --- .../ui/activity/CommandManagerActivity.java | 36 ++++++--- .../ui/popup/AutoCommandContextPopup.java | 75 ++++++++++++++++++ .../core/ui/popup/EditAutoCommandPopup.java | 1 - .../ui/widget/AutoCommandContextWidget.java | 76 +++++++++++++++++++ .../assets/autocommand/i18n/en_us.json | 7 +- .../themes/vanilla/lss/context-popup.lss | 65 ++++++++++++++++ 6 files changed, 246 insertions(+), 14 deletions(-) create mode 100644 core/src/main/java/com/rappytv/autocommand/core/ui/popup/AutoCommandContextPopup.java create mode 100644 core/src/main/java/com/rappytv/autocommand/core/ui/widget/AutoCommandContextWidget.java create mode 100644 core/src/main/resources/assets/autocommand/themes/vanilla/lss/context-popup.lss diff --git a/core/src/main/java/com/rappytv/autocommand/core/ui/activity/CommandManagerActivity.java b/core/src/main/java/com/rappytv/autocommand/core/ui/activity/CommandManagerActivity.java index e60d89a..464b10f 100644 --- a/core/src/main/java/com/rappytv/autocommand/core/ui/activity/CommandManagerActivity.java +++ b/core/src/main/java/com/rappytv/autocommand/core/ui/activity/CommandManagerActivity.java @@ -2,17 +2,20 @@ import com.rappytv.autocommand.api.AutoCommandMeta; import com.rappytv.autocommand.core.AutoCommandConfig; +import com.rappytv.autocommand.core.ui.popup.AutoCommandContextPopup; import com.rappytv.autocommand.core.ui.popup.EditAutoCommandPopup; import com.rappytv.autocommand.core.ui.widget.AutoCommandWidget; import java.util.HashMap; import java.util.Map; import java.util.UUID; +import java.util.function.Consumer; import net.labymod.api.client.component.Component; import net.labymod.api.client.component.format.NamedTextColor; import net.labymod.api.client.gui.screen.Parent; import net.labymod.api.client.gui.screen.activity.Activity; import net.labymod.api.client.gui.screen.activity.AutoActivity; import net.labymod.api.client.gui.screen.activity.Link; +import net.labymod.api.client.gui.screen.key.Key; import net.labymod.api.client.gui.screen.widget.widgets.ComponentWidget; import net.labymod.api.client.gui.screen.widget.widgets.DivWidget; import net.labymod.api.client.gui.screen.widget.widgets.input.ButtonWidget; @@ -20,6 +23,7 @@ import net.labymod.api.client.gui.screen.widget.widgets.layout.ScrollWidget; import net.labymod.api.client.gui.screen.widget.widgets.layout.list.HorizontalListWidget; import net.labymod.api.client.gui.screen.widget.widgets.layout.list.VerticalListWidget; +import net.labymod.api.client.gui.screen.widget.widgets.popup.AdvancedPopup; import net.labymod.api.client.gui.screen.widget.widgets.popup.SimpleAdvancedPopup; import net.labymod.api.client.gui.screen.widget.widgets.popup.SimpleAdvancedPopup.SimplePopupButton; @@ -49,7 +53,7 @@ public CommandManagerActivity(AutoCommandConfig config) { } @Override - public void initialize(Parent parent) { + public void initialize(Parent parent) { // TODO: add context menu/hint at context editor super.initialize(parent); AutoCommandWidget selectedEntry = this.commandList.listSession().getSelectedEntry(); @@ -118,18 +122,24 @@ private void loadCommands() { } private void performAction(Action action) { - switch (action) { + if(action == Action.EDIT && (Key.L_SHIFT.isPressed() || Key.L_CONTROL.isPressed())) { + action = Action.MANAGE_CONTEXTS; + } + Consumer editCallback = (command) -> { + this.config.removeAutoCommand(this.selectedCommand); + this.config.addAutoCommand(command); + this.selectedCommand = command; + this.reload(); + }; + + AdvancedPopup popup = switch (action) { case ADD -> new EditAutoCommandPopup(null, (command) -> { this.config.addAutoCommand(command); this.selectedCommand = command; this.reload(); - }).displayInOverlay(); - case EDIT -> new EditAutoCommandPopup(this.selectedCommand, (command) -> { - this.config.removeAutoCommand(this.selectedCommand); - this.config.addAutoCommand(command); - this.selectedCommand = command; - this.reload(); - }).displayInOverlay(); + }); + case EDIT -> new EditAutoCommandPopup(this.selectedCommand, editCallback); + case MANAGE_CONTEXTS -> new AutoCommandContextPopup(this.selectedCommand, editCallback); case REMOVE -> SimpleAdvancedPopup.builder() .title(Component.translatable("autocommand.activity.remove.title")) .description(Component.translatable( @@ -141,14 +151,16 @@ private void performAction(Action action) { this.reload(); })) .addButton(SimplePopupButton.cancel()) - .build() - .displayInOverlay(); - } + .build(); + }; + + popup.displayInOverlay(); } private enum Action { ADD, EDIT, + MANAGE_CONTEXTS, REMOVE } } diff --git a/core/src/main/java/com/rappytv/autocommand/core/ui/popup/AutoCommandContextPopup.java b/core/src/main/java/com/rappytv/autocommand/core/ui/popup/AutoCommandContextPopup.java new file mode 100644 index 0000000..7159ecd --- /dev/null +++ b/core/src/main/java/com/rappytv/autocommand/core/ui/popup/AutoCommandContextPopup.java @@ -0,0 +1,75 @@ +package com.rappytv.autocommand.core.ui.popup; + +import com.rappytv.autocommand.api.AutoCommandMeta; +import com.rappytv.autocommand.core.ui.widget.AutoCommandContextWidget; +import net.labymod.api.client.component.Component; +import net.labymod.api.client.gui.screen.activity.Link; +import net.labymod.api.client.gui.screen.widget.widgets.input.ButtonWidget; +import net.labymod.api.client.gui.screen.widget.widgets.layout.FlexibleContentWidget; +import net.labymod.api.client.gui.screen.widget.widgets.layout.ScrollWidget; +import net.labymod.api.client.gui.screen.widget.widgets.layout.list.VerticalListWidget; +import net.labymod.api.client.gui.screen.widget.widgets.popup.SimpleAdvancedPopup; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + +@Link("context-popup.lss") +public class AutoCommandContextPopup extends SimpleAdvancedPopup { + + // TODO: translate + + private final AutoCommandMeta meta; + private final SimplePopupButton confirmButton; + private final VerticalListWidget contextList = new VerticalListWidget<>(); + + public AutoCommandContextPopup(@NotNull AutoCommandMeta meta, Consumer onSubmit) { + this.meta = meta; + this.contextList.addId("context-list"); + for (AutoCommandMeta.Context context : this.meta.getContexts()) { + this.contextList.addChild(new AutoCommandContextWidget(context)); + } + + super.title = Component.translatable("autocommand.popup.title.contexts", Component.text(this.meta.getName())); + super.buttons = new ArrayList<>(); + super.buttons.add(this.confirmButton = SimplePopupButton.confirm((ignored) -> { + List contexts = new ArrayList<>(); + for (AutoCommandContextWidget child : this.contextList.getChildren()) { + contexts.add(child.getContext()); + } + this.meta.setContexts(contexts); + onSubmit.accept(this.meta); + })); + super.buttons.add(SimplePopupButton.cancel()); + super.widgetFunction = document -> + document.addChild(this.buildContextManagementArea()); + } + + private FlexibleContentWidget buildContextManagementArea() { + FlexibleContentWidget contextManagement = new FlexibleContentWidget(); + contextManagement.addId("context-management"); + + ButtonWidget addButton = ButtonWidget.i18n("Add", () -> + this.contextList.addChildInitialized(new AutoCommandContextWidget(new AutoCommandMeta.Context( + "test", + AutoCommandMeta.Context.Type.SINGLEPLAYER + ))) + ); + addButton.addId("add-button"); + + contextManagement.addContent(addButton); + contextManagement.addContent(new ScrollWidget(this.contextList)); + + this.updateConfirmButton(); + + return contextManagement; + } + + private void updateConfirmButton() { // TODO: make this work + boolean valid = true; + boolean changed = true; + + this.confirmButton.enabled(valid && changed); + } +} diff --git a/core/src/main/java/com/rappytv/autocommand/core/ui/popup/EditAutoCommandPopup.java b/core/src/main/java/com/rappytv/autocommand/core/ui/popup/EditAutoCommandPopup.java index 41e4c95..8e84cd3 100644 --- a/core/src/main/java/com/rappytv/autocommand/core/ui/popup/EditAutoCommandPopup.java +++ b/core/src/main/java/com/rappytv/autocommand/core/ui/popup/EditAutoCommandPopup.java @@ -63,7 +63,6 @@ private VerticalListWidget buildOptionArea() { options.addChild(this.buildDelaySlider()); this.updateConfirmButton(); - // TODO: add context management return options; } diff --git a/core/src/main/java/com/rappytv/autocommand/core/ui/widget/AutoCommandContextWidget.java b/core/src/main/java/com/rappytv/autocommand/core/ui/widget/AutoCommandContextWidget.java new file mode 100644 index 0000000..e9ef97d --- /dev/null +++ b/core/src/main/java/com/rappytv/autocommand/core/ui/widget/AutoCommandContextWidget.java @@ -0,0 +1,76 @@ +package com.rappytv.autocommand.core.ui.widget; + +import com.rappytv.autocommand.api.AutoCommandMeta; +import com.rappytv.autocommand.api.AutoCommandMeta.Context.Type; +import net.labymod.api.client.gui.icon.Icon; +import net.labymod.api.client.gui.lss.property.annotation.AutoWidget; +import net.labymod.api.client.gui.screen.Parent; +import net.labymod.api.client.gui.screen.widget.widgets.ComponentWidget; +import net.labymod.api.client.gui.screen.widget.widgets.input.ButtonWidget; +import net.labymod.api.client.gui.screen.widget.widgets.layout.list.HorizontalListWidget; +import net.labymod.api.client.gui.screen.widget.widgets.layout.list.VerticalListWidget; +import net.labymod.api.client.gui.screen.widget.widgets.renderer.IconWidget; +import net.labymod.api.client.resources.ResourceLocation; + +@AutoWidget +public class AutoCommandContextWidget extends HorizontalListWidget { + + private static final ResourceLocation SINGLEPLAYER_ICON = ResourceLocation.create( + "autocommand", + "textures/command_block.png" + ); + private static final ResourceLocation MULTIPLAYER_ICON = ResourceLocation.create( + "autocommand", + "textures/command_block.png" + ); + + private final AutoCommandMeta.Context context; + + public AutoCommandContextWidget(AutoCommandMeta.Context context) { + this.context = context; + } + + @Override + public void initialize(Parent parent) { + super.initialize(parent); + + IconWidget icon = new IconWidget(Icon.texture( + this.context.type() == Type.SINGLEPLAYER + ? SINGLEPLAYER_ICON + : MULTIPLAYER_ICON + )); + icon.addId("context-icon"); + + VerticalListWidget componentGroup = new VerticalListWidget<>(); + componentGroup.addId("component-group"); + + ComponentWidget typeComponent = ComponentWidget.i18n(this.formatContextType()); + typeComponent.addId("type-label"); + + ComponentWidget valueComponent = ComponentWidget.text(this.context.name()); + valueComponent.addId("value-label"); + + componentGroup.addChild(typeComponent); + componentGroup.addChild(valueComponent); + + ButtonWidget removeButton = ButtonWidget.text("❌", () -> { + System.out.printf("remove %s\n", this.context.name()); // TODO: actually delete context + }); + removeButton.addId("remove-button"); + + this.addEntry(icon); + this.addEntry(componentGroup); + this.addEntry(removeButton); + } + + public AutoCommandMeta.Context getContext() { + return this.context; + } + + private String formatContextType() { + return String.format( + "autocommand.activity.contextType.%s", + this.context.type().name().toLowerCase() + ); + } +} diff --git a/core/src/main/resources/assets/autocommand/i18n/en_us.json b/core/src/main/resources/assets/autocommand/i18n/en_us.json index b7e586f..24426ae 100644 --- a/core/src/main/resources/assets/autocommand/i18n/en_us.json +++ b/core/src/main/resources/assets/autocommand/i18n/en_us.json @@ -13,12 +13,17 @@ "remove": { "title": "Are you sure?", "description": "Do you want to delete your automated command %s?" + }, + "contextType": { + "singleplayer": "Singleplayer World", + "multiplayer": "Multiplayer Server" } }, "popup": { "title": { "add": "Create automated command", - "edit": "Edit \"%s\"" + "edit": "Edit \"%s\"", + "contexts": "Manage contexts of \"%s\"" }, "enabled": { "name": "Enabled" diff --git a/core/src/main/resources/assets/autocommand/themes/vanilla/lss/context-popup.lss b/core/src/main/resources/assets/autocommand/themes/vanilla/lss/context-popup.lss new file mode 100644 index 0000000..b013b50 --- /dev/null +++ b/core/src/main/resources/assets/autocommand/themes/vanilla/lss/context-popup.lss @@ -0,0 +1,65 @@ +.context-management { + height: 150; + width: 200; + + .add-button { + alignment-x: center; + width: 30%; + height: 18; + } + + Scroll { + height: calc(100% - 18); + width: 100%; + margin: 5 0 5 0; + + .context-list { + height: 100%; + space-between-entries: 2; + selectable: true; + } + + Scrollbar { + width: 5; + height: 100%; + margin-left: 5; + } + } +} + +AutoCommandContext { + height: 28; + padding: 1; + space-between-entries: 5; + + .context-icon { + height: 16; + width: 16; + margin-left: 5; + } + + .component-group { + width: fit-content; + height: 70%; + + .type-label { + text-color: aqua; + } + + .value-label { + text-color: dark_gray; + } + } + + .remove-button { + alignment: right; + width: height; + padding: 0; + margin-right: 3; + } + + &:selected { + padding: 0; + border: 1 gray; + } +} \ No newline at end of file From 59f2efee480a2e8a209b87fe05f04eb91cac41b2 Mon Sep 17 00:00:00 2001 From: RappyTV Date: Thu, 9 Jul 2026 16:16:40 +0200 Subject: [PATCH 19/30] feat: add context manager activity instead of popup --- .../autocommand/core/AutoCommandAddon.java | 1 + .../CommandContextManagerActivity.java | 152 ++++++++++++++++++ .../ui/activity/CommandManagerActivity.java | 20 +-- .../ui/popup/AutoCommandContextPopup.java | 75 --------- .../ui/widget/AutoCommandContextWidget.java | 20 +-- .../assets/autocommand/i18n/en_us.json | 22 ++- .../themes/vanilla/lss/command-manager.lss | 45 ------ .../themes/vanilla/lss/command-meta.lss | 44 +++++ ...{context-popup.lss => context-manager.lss} | 51 ++++-- 9 files changed, 273 insertions(+), 157 deletions(-) create mode 100644 core/src/main/java/com/rappytv/autocommand/core/ui/activity/CommandContextManagerActivity.java delete mode 100644 core/src/main/java/com/rappytv/autocommand/core/ui/popup/AutoCommandContextPopup.java create mode 100644 core/src/main/resources/assets/autocommand/themes/vanilla/lss/command-meta.lss rename core/src/main/resources/assets/autocommand/themes/vanilla/lss/{context-popup.lss => context-manager.lss} (54%) diff --git a/core/src/main/java/com/rappytv/autocommand/core/AutoCommandAddon.java b/core/src/main/java/com/rappytv/autocommand/core/AutoCommandAddon.java index 667e841..32a3aaa 100644 --- a/core/src/main/java/com/rappytv/autocommand/core/AutoCommandAddon.java +++ b/core/src/main/java/com/rappytv/autocommand/core/AutoCommandAddon.java @@ -11,6 +11,7 @@ public class AutoCommandAddon extends LabyAddon { protected void enable() { this.registerSettingCategory(); this.registerListener(new WorldEnterListener(this)); + // TODO: add custom config for command storage } @Override diff --git a/core/src/main/java/com/rappytv/autocommand/core/ui/activity/CommandContextManagerActivity.java b/core/src/main/java/com/rappytv/autocommand/core/ui/activity/CommandContextManagerActivity.java new file mode 100644 index 0000000..4f2d333 --- /dev/null +++ b/core/src/main/java/com/rappytv/autocommand/core/ui/activity/CommandContextManagerActivity.java @@ -0,0 +1,152 @@ +package com.rappytv.autocommand.core.ui.activity; + +import com.rappytv.autocommand.api.AutoCommandMeta; +import com.rappytv.autocommand.api.AutoCommandMeta.Context; +import com.rappytv.autocommand.api.AutoCommandMeta.Context.Type; +import com.rappytv.autocommand.core.ui.widget.AutoCommandContextWidget; +import com.rappytv.autocommand.core.ui.widget.AutoCommandWidget; +import java.util.ArrayList; +import java.util.List; +import net.labymod.api.Laby; +import net.labymod.api.Textures.SpriteCommon; +import net.labymod.api.client.component.Component; +import net.labymod.api.client.gui.screen.Parent; +import net.labymod.api.client.gui.screen.activity.Activity; +import net.labymod.api.client.gui.screen.activity.AutoActivity; +import net.labymod.api.client.gui.screen.activity.Link; +import net.labymod.api.client.gui.screen.activity.Links; +import net.labymod.api.client.gui.screen.widget.widgets.ComponentWidget; +import net.labymod.api.client.gui.screen.widget.widgets.input.ButtonWidget; +import net.labymod.api.client.gui.screen.widget.widgets.layout.FlexibleContentWidget; +import net.labymod.api.client.gui.screen.widget.widgets.layout.ScrollWidget; +import net.labymod.api.client.gui.screen.widget.widgets.layout.list.HorizontalListWidget; +import net.labymod.api.client.gui.screen.widget.widgets.layout.list.VerticalListWidget; +import net.labymod.api.client.network.server.ServerData; +import net.labymod.api.server.LocalWorld; +import org.jetbrains.annotations.Nullable; + +@AutoActivity +@Links({@Link("context-manager.lss"), @Link("command-meta.lss")}) +public class CommandContextManagerActivity extends Activity { + + private static final String I18N_PREFIX = "autocommand.activity.context."; + + private final AutoCommandMeta meta; + private final List contextWidgets = new ArrayList<>(); + private final VerticalListWidget contextList = new VerticalListWidget<>(); + + private final Context currentContext; + + public CommandContextManagerActivity(AutoCommandMeta meta) { + this.meta = meta; + this.loadContexts(); + this.contextList.addId("context-list"); + this.currentContext = this.buildCurrentContext(); + } + + @Override + public void initialize(Parent parent) { + super.initialize(parent); + FlexibleContentWidget content = new FlexibleContentWidget(); + content.addId("context-manager"); + + for (AutoCommandContextWidget widget : this.contextWidgets) { + this.contextList.addChild(widget); + } + + AutoCommandWidget commandWidget = new AutoCommandWidget(this.meta); + commandWidget.addId("selected-command"); + + boolean validContext = this.currentContext != null; + boolean duplicateContext = this.hasCurrentContext(); + + ButtonWidget addButton = ButtonWidget.i18n(I18N_PREFIX + "add", this::addCurrentContext); + addButton.addId("add-button"); + addButton.setEnabled(validContext && !duplicateContext); + + if(!validContext) { + addButton.setHoverComponent(Component.translatable(I18N_PREFIX + "invalid")); + } else if(duplicateContext) { + addButton.setHoverComponent(Component.translatable(I18N_PREFIX + "duplicate")); + } + + content.addContent(this.buildBackContainer()); + content.addContent(commandWidget); + content.addContent(addButton); + content.addFlexibleContent(new ScrollWidget(this.contextList)); + + this.document.addChild(content); + } + + @Override + public void reload() { + this.loadContexts(); + super.reload(); + } + + private void loadContexts() { + this.contextWidgets.clear(); + for (AutoCommandMeta.Context context : this.meta.getContexts()) { + this.contextWidgets.add(new AutoCommandContextWidget(context, () -> { + this.meta.getContexts().removeIf(context::equals); + this.reload(); + })); + } + } + + private HorizontalListWidget buildBackContainer() { + HorizontalListWidget backContainer = new HorizontalListWidget(); + backContainer.addId("back-container"); + + ButtonWidget backButton = ButtonWidget.icon(SpriteCommon.BACK_BUTTON, + this::displayPreviousScreen // TODO: this doesn't work ingame + ); + backButton.addId("back-button"); + + ComponentWidget backComponent = ComponentWidget.i18n(I18N_PREFIX + "back"); + backComponent.addId("back-component"); + + backContainer.addEntry(backButton); + backContainer.addEntry(backComponent); + + return backContainer; + } + + @Nullable + private AutoCommandMeta.Context buildCurrentContext() { + if(!Laby.labyAPI().minecraft().isIngame()) { + return null; + } + + String name; + Type type; + + ServerData server = Laby.labyAPI().serverController().getCurrentServerData(); + if (server != null && !server.address().getHost().isEmpty()) { + name = server.address().getHost(); + type = Type.MULTIPLAYER; + } else { + LocalWorld world = Laby.references().integratedServer().getLocalWorld(); + if(world == null) { + return null; + } + + name = world.folderName(); + type = Type.SINGLEPLAYER; + } + + return new Context(name, type); + } + + private void addCurrentContext() { + if(this.currentContext == null || this.hasCurrentContext()) { + return; + } + this.meta.getContexts().add(this.currentContext); + this.reload(); + } + + private boolean hasCurrentContext() { + return this.currentContext != null && this.meta.getContexts().contains(this.currentContext); + } +} diff --git a/core/src/main/java/com/rappytv/autocommand/core/ui/activity/CommandManagerActivity.java b/core/src/main/java/com/rappytv/autocommand/core/ui/activity/CommandManagerActivity.java index 464b10f..bc64e89 100644 --- a/core/src/main/java/com/rappytv/autocommand/core/ui/activity/CommandManagerActivity.java +++ b/core/src/main/java/com/rappytv/autocommand/core/ui/activity/CommandManagerActivity.java @@ -2,7 +2,6 @@ import com.rappytv.autocommand.api.AutoCommandMeta; import com.rappytv.autocommand.core.AutoCommandConfig; -import com.rappytv.autocommand.core.ui.popup.AutoCommandContextPopup; import com.rappytv.autocommand.core.ui.popup.EditAutoCommandPopup; import com.rappytv.autocommand.core.ui.widget.AutoCommandWidget; import java.util.HashMap; @@ -15,6 +14,7 @@ import net.labymod.api.client.gui.screen.activity.Activity; import net.labymod.api.client.gui.screen.activity.AutoActivity; import net.labymod.api.client.gui.screen.activity.Link; +import net.labymod.api.client.gui.screen.activity.Links; import net.labymod.api.client.gui.screen.key.Key; import net.labymod.api.client.gui.screen.widget.widgets.ComponentWidget; import net.labymod.api.client.gui.screen.widget.widgets.DivWidget; @@ -28,9 +28,11 @@ import net.labymod.api.client.gui.screen.widget.widgets.popup.SimpleAdvancedPopup.SimplePopupButton; @AutoActivity -@Link("command-manager.lss") +@Links({@Link("command-manager.lss"), @Link("command-meta.lss")}) public class CommandManagerActivity extends Activity { + private static final String I18N_PREFIX = "autocommand.activity.command."; + private final AutoCommandConfig config; private final Map commandWidgets = new HashMap<>(); private final VerticalListWidget commandList = new VerticalListWidget<>(); @@ -53,7 +55,7 @@ public CommandManagerActivity(AutoCommandConfig config) { } @Override - public void initialize(Parent parent) { // TODO: add context menu/hint at context editor + public void initialize(Parent parent) { super.initialize(parent); AutoCommandWidget selectedEntry = this.commandList.listSession().getSelectedEntry(); @@ -95,7 +97,7 @@ public void initialize(Parent parent) { // TODO: add context menu/hint at contex DivWidget content = new DivWidget().addId("content"); if (this.commandWidgets.isEmpty()) { - ComponentWidget errorComponent = ComponentWidget.i18n("autocommand.activity.empty"); + ComponentWidget errorComponent = ComponentWidget.i18n(I18N_PREFIX + "empty"); errorComponent.addId("error-component"); content.addChild(errorComponent); @@ -123,7 +125,9 @@ private void loadCommands() { private void performAction(Action action) { if(action == Action.EDIT && (Key.L_SHIFT.isPressed() || Key.L_CONTROL.isPressed())) { - action = Action.MANAGE_CONTEXTS; + // TODO: add more intuitive way to open this + this.redirectScreen(new CommandContextManagerActivity(this.selectedCommand)); + return; } Consumer editCallback = (command) -> { this.config.removeAutoCommand(this.selectedCommand); @@ -139,11 +143,10 @@ private void performAction(Action action) { this.reload(); }); case EDIT -> new EditAutoCommandPopup(this.selectedCommand, editCallback); - case MANAGE_CONTEXTS -> new AutoCommandContextPopup(this.selectedCommand, editCallback); case REMOVE -> SimpleAdvancedPopup.builder() - .title(Component.translatable("autocommand.activity.remove.title")) + .title(Component.translatable(I18N_PREFIX + ".remove.title")) .description(Component.translatable( - "autocommand.activity.remove.description", + I18N_PREFIX + ".remove.description", Component.text(this.selectedCommand.getName(), NamedTextColor.AQUA) )) .addButton(SimplePopupButton.confirm(simplePopupButton -> { @@ -160,7 +163,6 @@ private void performAction(Action action) { private enum Action { ADD, EDIT, - MANAGE_CONTEXTS, REMOVE } } diff --git a/core/src/main/java/com/rappytv/autocommand/core/ui/popup/AutoCommandContextPopup.java b/core/src/main/java/com/rappytv/autocommand/core/ui/popup/AutoCommandContextPopup.java deleted file mode 100644 index 7159ecd..0000000 --- a/core/src/main/java/com/rappytv/autocommand/core/ui/popup/AutoCommandContextPopup.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.rappytv.autocommand.core.ui.popup; - -import com.rappytv.autocommand.api.AutoCommandMeta; -import com.rappytv.autocommand.core.ui.widget.AutoCommandContextWidget; -import net.labymod.api.client.component.Component; -import net.labymod.api.client.gui.screen.activity.Link; -import net.labymod.api.client.gui.screen.widget.widgets.input.ButtonWidget; -import net.labymod.api.client.gui.screen.widget.widgets.layout.FlexibleContentWidget; -import net.labymod.api.client.gui.screen.widget.widgets.layout.ScrollWidget; -import net.labymod.api.client.gui.screen.widget.widgets.layout.list.VerticalListWidget; -import net.labymod.api.client.gui.screen.widget.widgets.popup.SimpleAdvancedPopup; -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Consumer; - -@Link("context-popup.lss") -public class AutoCommandContextPopup extends SimpleAdvancedPopup { - - // TODO: translate - - private final AutoCommandMeta meta; - private final SimplePopupButton confirmButton; - private final VerticalListWidget contextList = new VerticalListWidget<>(); - - public AutoCommandContextPopup(@NotNull AutoCommandMeta meta, Consumer onSubmit) { - this.meta = meta; - this.contextList.addId("context-list"); - for (AutoCommandMeta.Context context : this.meta.getContexts()) { - this.contextList.addChild(new AutoCommandContextWidget(context)); - } - - super.title = Component.translatable("autocommand.popup.title.contexts", Component.text(this.meta.getName())); - super.buttons = new ArrayList<>(); - super.buttons.add(this.confirmButton = SimplePopupButton.confirm((ignored) -> { - List contexts = new ArrayList<>(); - for (AutoCommandContextWidget child : this.contextList.getChildren()) { - contexts.add(child.getContext()); - } - this.meta.setContexts(contexts); - onSubmit.accept(this.meta); - })); - super.buttons.add(SimplePopupButton.cancel()); - super.widgetFunction = document -> - document.addChild(this.buildContextManagementArea()); - } - - private FlexibleContentWidget buildContextManagementArea() { - FlexibleContentWidget contextManagement = new FlexibleContentWidget(); - contextManagement.addId("context-management"); - - ButtonWidget addButton = ButtonWidget.i18n("Add", () -> - this.contextList.addChildInitialized(new AutoCommandContextWidget(new AutoCommandMeta.Context( - "test", - AutoCommandMeta.Context.Type.SINGLEPLAYER - ))) - ); - addButton.addId("add-button"); - - contextManagement.addContent(addButton); - contextManagement.addContent(new ScrollWidget(this.contextList)); - - this.updateConfirmButton(); - - return contextManagement; - } - - private void updateConfirmButton() { // TODO: make this work - boolean valid = true; - boolean changed = true; - - this.confirmButton.enabled(valid && changed); - } -} diff --git a/core/src/main/java/com/rappytv/autocommand/core/ui/widget/AutoCommandContextWidget.java b/core/src/main/java/com/rappytv/autocommand/core/ui/widget/AutoCommandContextWidget.java index e9ef97d..3d7fd69 100644 --- a/core/src/main/java/com/rappytv/autocommand/core/ui/widget/AutoCommandContextWidget.java +++ b/core/src/main/java/com/rappytv/autocommand/core/ui/widget/AutoCommandContextWidget.java @@ -5,6 +5,7 @@ import net.labymod.api.client.gui.icon.Icon; import net.labymod.api.client.gui.lss.property.annotation.AutoWidget; import net.labymod.api.client.gui.screen.Parent; +import net.labymod.api.client.gui.screen.widget.action.Pressable; import net.labymod.api.client.gui.screen.widget.widgets.ComponentWidget; import net.labymod.api.client.gui.screen.widget.widgets.input.ButtonWidget; import net.labymod.api.client.gui.screen.widget.widgets.layout.list.HorizontalListWidget; @@ -15,6 +16,7 @@ @AutoWidget public class AutoCommandContextWidget extends HorizontalListWidget { + // TODO: add icons and sprite helper class private static final ResourceLocation SINGLEPLAYER_ICON = ResourceLocation.create( "autocommand", "textures/command_block.png" @@ -25,9 +27,11 @@ public class AutoCommandContextWidget extends HorizontalListWidget { ); private final AutoCommandMeta.Context context; + private final Pressable onDelete; - public AutoCommandContextWidget(AutoCommandMeta.Context context) { + public AutoCommandContextWidget(AutoCommandMeta.Context context, Pressable onDelete) { this.context = context; + this.onDelete = onDelete; } @Override @@ -44,18 +48,16 @@ public void initialize(Parent parent) { VerticalListWidget componentGroup = new VerticalListWidget<>(); componentGroup.addId("component-group"); + ComponentWidget nameComponent = ComponentWidget.text(this.context.name()); + nameComponent.addId("name-label"); + ComponentWidget typeComponent = ComponentWidget.i18n(this.formatContextType()); typeComponent.addId("type-label"); - ComponentWidget valueComponent = ComponentWidget.text(this.context.name()); - valueComponent.addId("value-label"); - + componentGroup.addChild(nameComponent); componentGroup.addChild(typeComponent); - componentGroup.addChild(valueComponent); - ButtonWidget removeButton = ButtonWidget.text("❌", () -> { - System.out.printf("remove %s\n", this.context.name()); // TODO: actually delete context - }); + ButtonWidget removeButton = ButtonWidget.text("✘", this.onDelete); removeButton.addId("remove-button"); this.addEntry(icon); @@ -69,7 +71,7 @@ public AutoCommandMeta.Context getContext() { private String formatContextType() { return String.format( - "autocommand.activity.contextType.%s", + "autocommand.activity.context.type.%s", this.context.type().name().toLowerCase() ); } diff --git a/core/src/main/resources/assets/autocommand/i18n/en_us.json b/core/src/main/resources/assets/autocommand/i18n/en_us.json index 24426ae..4461d61 100644 --- a/core/src/main/resources/assets/autocommand/i18n/en_us.json +++ b/core/src/main/resources/assets/autocommand/i18n/en_us.json @@ -9,14 +9,22 @@ } }, "activity": { - "empty": "Nothing here yet.\nGo ahead and create an automated command!", - "remove": { - "title": "Are you sure?", - "description": "Do you want to delete your automated command %s?" + "command": { + "empty": "Nothing here yet.\nGo ahead and create an automated command!", + "remove": { + "title": "Are you sure?", + "description": "Do you want to delete your automated command %s?" + } }, - "contextType": { - "singleplayer": "Singleplayer World", - "multiplayer": "Multiplayer Server" + "context": { + "back": "Leave context manager", + "add": "Add current world", + "invalid": "You're not in a valid context. If you believe this is an error please contact me.", + "duplicate": "This context already covered.", + "type": { + "singleplayer": "Singleplayer World", + "multiplayer": "Multiplayer Server" + } } }, "popup": { diff --git a/core/src/main/resources/assets/autocommand/themes/vanilla/lss/command-manager.lss b/core/src/main/resources/assets/autocommand/themes/vanilla/lss/command-manager.lss index b574688..b50670d 100644 --- a/core/src/main/resources/assets/autocommand/themes/vanilla/lss/command-manager.lss +++ b/core/src/main/resources/assets/autocommand/themes/vanilla/lss/command-manager.lss @@ -38,49 +38,4 @@ layout: fill; margin: 5 0 5 0; } -} - -AutoCommand { - height: 28; - padding: 1; - space-between-entries: 5; - - .command-icon { - height: 16; - width: 16; - margin-left: 5; - } - - .component-group { - width: calc(100% - 30); - min-height: fit-content; - height: 70%; - - .first-line { - height: fit-content; - - .name-label { - text-color: white; - alignment-x: left; - } - - .meta-label { - alignment: right; - } - } - - .command-label { - text-color: dark_gray; - } - } - - &:selected { - padding: 0; - border: 1 gray; - background-color: black; - } - - &.disabled { - opacity: 0.8; - } } \ No newline at end of file diff --git a/core/src/main/resources/assets/autocommand/themes/vanilla/lss/command-meta.lss b/core/src/main/resources/assets/autocommand/themes/vanilla/lss/command-meta.lss new file mode 100644 index 0000000..af7647c --- /dev/null +++ b/core/src/main/resources/assets/autocommand/themes/vanilla/lss/command-meta.lss @@ -0,0 +1,44 @@ +AutoCommand { + height: 28; + padding: 1; + space-between-entries: 5; + + .command-icon { + height: 16; + width: 16; + margin-left: 5; + } + + .component-group { + width: calc(100% - 30); + min-height: fit-content; + height: 70%; + + .first-line { + height: fit-content; + + .name-label { + text-color: white; + alignment-x: left; + } + + .meta-label { + alignment: right; + } + } + + .command-label { + text-color: dark_gray; + } + } + + &:selected { + padding: 0; + border: 1 gray; + background-color: black; + } + + &.disabled { + opacity: 0.8; + } +} \ No newline at end of file diff --git a/core/src/main/resources/assets/autocommand/themes/vanilla/lss/context-popup.lss b/core/src/main/resources/assets/autocommand/themes/vanilla/lss/context-manager.lss similarity index 54% rename from core/src/main/resources/assets/autocommand/themes/vanilla/lss/context-popup.lss rename to core/src/main/resources/assets/autocommand/themes/vanilla/lss/context-manager.lss index b013b50..e67ff57 100644 --- a/core/src/main/resources/assets/autocommand/themes/vanilla/lss/context-popup.lss +++ b/core/src/main/resources/assets/autocommand/themes/vanilla/lss/context-manager.lss @@ -1,22 +1,41 @@ -.context-management { - height: 150; - width: 200; +.context-manager { + height: 100%; + width: 100%; + + .back-container { + height: fit-content; + width: 100%; + margin-bottom: 5; + space-between-entries: 3; + + .back-button { + padding: 0; + width: height; + + Icon { + height: 8; + width: height; + } + } + } + + .selected-command { + width: 100%; + padding: 0; + border: 1 gold; + } .add-button { + height: 16; alignment-x: center; - width: 30%; - height: 18; + margin-top: 3; } Scroll { - height: calc(100% - 18); - width: 100%; - margin: 5 0 5 0; + margin-bottom: 5; .context-list { height: 100%; - space-between-entries: 2; - selectable: true; } Scrollbar { @@ -42,11 +61,11 @@ AutoCommandContext { width: fit-content; height: 70%; - .type-label { + .name-label { text-color: aqua; } - .value-label { + .type-label { text-color: dark_gray; } } @@ -56,6 +75,14 @@ AutoCommandContext { width: height; padding: 0; margin-right: 3; + + Component { + text-color: white !important; + } + + &:hover Component { + text-color: red !important; + } } &:selected { From e5ad6fb4fb2a3962d16096dc96953fc6921a3b37 Mon Sep 17 00:00:00 2001 From: RappyTV Date: Thu, 9 Jul 2026 17:15:18 +0200 Subject: [PATCH 20/30] fix: disabled commands were not seethrough --- .../autocommand/core/ui/widget/AutoCommandWidget.java | 6 ++++++ .../assets/autocommand/themes/vanilla/lss/command-meta.lss | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/com/rappytv/autocommand/core/ui/widget/AutoCommandWidget.java b/core/src/main/java/com/rappytv/autocommand/core/ui/widget/AutoCommandWidget.java index 7a00520..cf53ce6 100644 --- a/core/src/main/java/com/rappytv/autocommand/core/ui/widget/AutoCommandWidget.java +++ b/core/src/main/java/com/rappytv/autocommand/core/ui/widget/AutoCommandWidget.java @@ -31,6 +31,12 @@ public AutoCommandWidget(AutoCommandMeta meta) { public void initialize(Parent parent) { super.initialize(parent); + if(this.meta.isEnabled()) { + this.removeId("disabled"); + } else { + this.addId("disabled"); + } + IconWidget icon = new IconWidget(Icon.texture(ICON)); icon.addId("command-icon"); diff --git a/core/src/main/resources/assets/autocommand/themes/vanilla/lss/command-meta.lss b/core/src/main/resources/assets/autocommand/themes/vanilla/lss/command-meta.lss index af7647c..76add0f 100644 --- a/core/src/main/resources/assets/autocommand/themes/vanilla/lss/command-meta.lss +++ b/core/src/main/resources/assets/autocommand/themes/vanilla/lss/command-meta.lss @@ -39,6 +39,6 @@ AutoCommand { } &.disabled { - opacity: 0.8; + opacity: 0.6; } } \ No newline at end of file From a563ca6b22d71758bdf8d6d16f7f566962221ce7 Mon Sep 17 00:00:00 2001 From: RappyTV Date: Thu, 9 Jul 2026 17:17:42 +0200 Subject: [PATCH 21/30] feat: move commands into separate config --- .../autocommand/core/AutoCommandAddon.java | 26 ++++++-- .../autocommand/core/AutoCommandConfig.java | 65 ------------------- .../core/config/AutoCommandAddonConfig.java | 27 ++++++++ .../core/config/CommandConfig.java | 49 ++++++++++++++ .../core/listener/WorldEnterListener.java | 8 +-- .../CommandContextManagerActivity.java | 3 + .../ui/activity/CommandManagerActivity.java | 30 ++++----- .../core/ui/popup/EditAutoCommandPopup.java | 2 +- 8 files changed, 115 insertions(+), 95 deletions(-) delete mode 100644 core/src/main/java/com/rappytv/autocommand/core/AutoCommandConfig.java create mode 100644 core/src/main/java/com/rappytv/autocommand/core/config/AutoCommandAddonConfig.java create mode 100644 core/src/main/java/com/rappytv/autocommand/core/config/CommandConfig.java diff --git a/core/src/main/java/com/rappytv/autocommand/core/AutoCommandAddon.java b/core/src/main/java/com/rappytv/autocommand/core/AutoCommandAddon.java index 32a3aaa..d742271 100644 --- a/core/src/main/java/com/rappytv/autocommand/core/AutoCommandAddon.java +++ b/core/src/main/java/com/rappytv/autocommand/core/AutoCommandAddon.java @@ -1,21 +1,37 @@ package com.rappytv.autocommand.core; +import com.rappytv.autocommand.core.config.AutoCommandAddonConfig; +import com.rappytv.autocommand.core.config.CommandConfig; import com.rappytv.autocommand.core.listener.WorldEnterListener; import net.labymod.api.addon.LabyAddon; import net.labymod.api.models.addon.annotation.AddonMain; @AddonMain -public class AutoCommandAddon extends LabyAddon { +public class AutoCommandAddon extends LabyAddon { + + private static AutoCommandAddon INSTANCE; + private CommandConfig commandConfig; @Override protected void enable() { + INSTANCE = this; + this.registerSettingCategory(); - this.registerListener(new WorldEnterListener(this)); - // TODO: add custom config for command storage + this.registerListener(new WorldEnterListener()); + + this.commandConfig = this.addCustomConfiguration(CommandConfig.class); } @Override - protected Class configurationClass() { - return AutoCommandConfig.class; + protected Class configurationClass() { + return AutoCommandAddonConfig.class; + } + + public static CommandConfig getCommandConfig() { + return INSTANCE.commandConfig; + } + + public static void saveCommandConfig() { + INSTANCE.saveCustomConfiguration(CommandConfig.class); } } diff --git a/core/src/main/java/com/rappytv/autocommand/core/AutoCommandConfig.java b/core/src/main/java/com/rappytv/autocommand/core/AutoCommandConfig.java deleted file mode 100644 index b54b6a6..0000000 --- a/core/src/main/java/com/rappytv/autocommand/core/AutoCommandConfig.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.rappytv.autocommand.core; - -import com.rappytv.autocommand.api.AutoCommandMeta; -import com.rappytv.autocommand.core.ui.activity.CommandManagerActivity; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Objects; -import java.util.UUID; -import java.util.function.Predicate; -import net.labymod.api.addon.AddonConfig; -import net.labymod.api.client.gui.screen.activity.Activity; -import net.labymod.api.client.gui.screen.widget.widgets.activity.settings.ActivitySettingWidget.ActivitySetting; -import net.labymod.api.client.gui.screen.widget.widgets.input.SwitchWidget.SwitchSetting; -import net.labymod.api.configuration.loader.annotation.Exclude; -import net.labymod.api.configuration.loader.property.ConfigProperty; -import net.labymod.api.util.MethodOrder; -import org.jetbrains.annotations.NotNull; - -public class AutoCommandConfig extends AddonConfig { - - @Exclude - private final List autoCommands = new ArrayList<>(); - - @SwitchSetting - private final ConfigProperty enabled = new ConfigProperty<>(true); - - @Override - public ConfigProperty enabled() { - return this.enabled; - } - - @MethodOrder(after = "enabled") - @ActivitySetting - public Activity commandManager() { - return new CommandManagerActivity(this); - } - - public void addAutoCommand(@NotNull AutoCommandMeta meta) { - Objects.requireNonNull(meta); - this.autoCommands.add(meta); - } - - public void removeAutoCommand(@NotNull AutoCommandMeta meta) { - this.autoCommands.remove(meta); - } - - public void removeAutoCommand(@NotNull UUID uuid) { - this.autoCommands.removeIf(meta -> meta.getUuid().equals(uuid)); - } - - public List getAutoCommands() { - return Collections.unmodifiableList(this.autoCommands); - } - - public List getAutoCommands(Predicate filter) { - List autoCommands = new ArrayList<>(); - for (AutoCommandMeta autoCommandMeta : this.autoCommands) { - if (filter.test(autoCommandMeta)) { - autoCommands.add(autoCommandMeta); - } - } - return Collections.unmodifiableList(autoCommands); - } -} diff --git a/core/src/main/java/com/rappytv/autocommand/core/config/AutoCommandAddonConfig.java b/core/src/main/java/com/rappytv/autocommand/core/config/AutoCommandAddonConfig.java new file mode 100644 index 0000000..a5158fe --- /dev/null +++ b/core/src/main/java/com/rappytv/autocommand/core/config/AutoCommandAddonConfig.java @@ -0,0 +1,27 @@ +package com.rappytv.autocommand.core.config; + +import com.rappytv.autocommand.core.AutoCommandAddon; +import com.rappytv.autocommand.core.ui.activity.CommandManagerActivity; +import net.labymod.api.addon.AddonConfig; +import net.labymod.api.client.gui.screen.activity.Activity; +import net.labymod.api.client.gui.screen.widget.widgets.activity.settings.ActivitySettingWidget.ActivitySetting; +import net.labymod.api.client.gui.screen.widget.widgets.input.SwitchWidget.SwitchSetting; +import net.labymod.api.configuration.loader.property.ConfigProperty; +import net.labymod.api.util.MethodOrder; + +public class AutoCommandAddonConfig extends AddonConfig { + + @SwitchSetting + private final ConfigProperty enabled = new ConfigProperty<>(true); + + @Override + public ConfigProperty enabled() { + return this.enabled; + } + + @MethodOrder(after = "enabled") + @ActivitySetting + public Activity commandManager() { + return new CommandManagerActivity(AutoCommandAddon.getCommandConfig()); + } +} diff --git a/core/src/main/java/com/rappytv/autocommand/core/config/CommandConfig.java b/core/src/main/java/com/rappytv/autocommand/core/config/CommandConfig.java new file mode 100644 index 0000000..c2e6cb5 --- /dev/null +++ b/core/src/main/java/com/rappytv/autocommand/core/config/CommandConfig.java @@ -0,0 +1,49 @@ +package com.rappytv.autocommand.core.config; + +import com.rappytv.autocommand.api.AutoCommandMeta; +import com.rappytv.autocommand.core.AutoCommandAddon; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.UUID; +import java.util.function.Predicate; +import net.labymod.api.configuration.loader.Config; +import net.labymod.api.configuration.loader.annotation.ConfigName; +import net.labymod.api.configuration.loader.annotation.Exclude; +import org.jetbrains.annotations.NotNull; + +@ConfigName("autocommands") +public class CommandConfig extends Config { + + @Exclude + private final Map autoCommands = new HashMap<>(); + + public void setAutoCommand(@NotNull AutoCommandMeta meta) { + Objects.requireNonNull(meta); + this.autoCommands.put(meta.getUuid(), meta); + AutoCommandAddon.saveCommandConfig(); + } + + public void removeAutoCommand(@NotNull UUID uuid) { + this.autoCommands.remove(uuid); + AutoCommandAddon.saveCommandConfig(); + } + + public Map getAutoCommands() { + return Collections.unmodifiableMap(this.autoCommands); + } + + public List getAutoCommands(Predicate filter) { + List autoCommands = new ArrayList<>(); + for (AutoCommandMeta autoCommandMeta : this.autoCommands.values()) { + if (filter.test(autoCommandMeta)) { + autoCommands.add(autoCommandMeta); + } + } + return Collections.unmodifiableList(autoCommands); + } + +} diff --git a/core/src/main/java/com/rappytv/autocommand/core/listener/WorldEnterListener.java b/core/src/main/java/com/rappytv/autocommand/core/listener/WorldEnterListener.java index 6a74ced..0984dc2 100644 --- a/core/src/main/java/com/rappytv/autocommand/core/listener/WorldEnterListener.java +++ b/core/src/main/java/com/rappytv/autocommand/core/listener/WorldEnterListener.java @@ -13,15 +13,9 @@ public class WorldEnterListener { - private final AutoCommandAddon addon; - - public WorldEnterListener(AutoCommandAddon addon) { - this.addon = addon; - } - @Subscribe public void onWorldEnter(WorldEnterEvent event) { - List commands = this.addon.configuration().getAutoCommands((meta) -> { + List commands = AutoCommandAddon.getCommandConfig().getAutoCommands((meta) -> { if(!meta.isEnabled()) { return false; } diff --git a/core/src/main/java/com/rappytv/autocommand/core/ui/activity/CommandContextManagerActivity.java b/core/src/main/java/com/rappytv/autocommand/core/ui/activity/CommandContextManagerActivity.java index 4f2d333..1da0f2b 100644 --- a/core/src/main/java/com/rappytv/autocommand/core/ui/activity/CommandContextManagerActivity.java +++ b/core/src/main/java/com/rappytv/autocommand/core/ui/activity/CommandContextManagerActivity.java @@ -3,6 +3,7 @@ import com.rappytv.autocommand.api.AutoCommandMeta; import com.rappytv.autocommand.api.AutoCommandMeta.Context; import com.rappytv.autocommand.api.AutoCommandMeta.Context.Type; +import com.rappytv.autocommand.core.AutoCommandAddon; import com.rappytv.autocommand.core.ui.widget.AutoCommandContextWidget; import com.rappytv.autocommand.core.ui.widget.AutoCommandWidget; import java.util.ArrayList; @@ -89,6 +90,7 @@ private void loadContexts() { for (AutoCommandMeta.Context context : this.meta.getContexts()) { this.contextWidgets.add(new AutoCommandContextWidget(context, () -> { this.meta.getContexts().removeIf(context::equals); + AutoCommandAddon.getCommandConfig().setAutoCommand(this.meta); this.reload(); })); } @@ -143,6 +145,7 @@ private void addCurrentContext() { return; } this.meta.getContexts().add(this.currentContext); + AutoCommandAddon.getCommandConfig().setAutoCommand(this.meta); this.reload(); } diff --git a/core/src/main/java/com/rappytv/autocommand/core/ui/activity/CommandManagerActivity.java b/core/src/main/java/com/rappytv/autocommand/core/ui/activity/CommandManagerActivity.java index bc64e89..1d7b904 100644 --- a/core/src/main/java/com/rappytv/autocommand/core/ui/activity/CommandManagerActivity.java +++ b/core/src/main/java/com/rappytv/autocommand/core/ui/activity/CommandManagerActivity.java @@ -1,11 +1,12 @@ package com.rappytv.autocommand.core.ui.activity; import com.rappytv.autocommand.api.AutoCommandMeta; -import com.rappytv.autocommand.core.AutoCommandConfig; +import com.rappytv.autocommand.core.config.CommandConfig; import com.rappytv.autocommand.core.ui.popup.EditAutoCommandPopup; import com.rappytv.autocommand.core.ui.widget.AutoCommandWidget; import java.util.HashMap; import java.util.Map; +import java.util.Map.Entry; import java.util.UUID; import java.util.function.Consumer; import net.labymod.api.client.component.Component; @@ -33,7 +34,7 @@ public class CommandManagerActivity extends Activity { private static final String I18N_PREFIX = "autocommand.activity.command."; - private final AutoCommandConfig config; + private final CommandConfig config; private final Map commandWidgets = new HashMap<>(); private final VerticalListWidget commandList = new VerticalListWidget<>(); @@ -42,7 +43,7 @@ public class CommandManagerActivity extends Activity { private ButtonWidget editButton; private ButtonWidget removeButton; - public CommandManagerActivity(AutoCommandConfig config) { + public CommandManagerActivity(CommandConfig config) { this.config = config; this.loadCommands(); this.commandList.addId("command-list"); @@ -118,8 +119,8 @@ public void reload() { private void loadCommands() { this.commandWidgets.clear(); - for (AutoCommandMeta command : this.config.getAutoCommands()) { - this.commandWidgets.put(command.getUuid(), new AutoCommandWidget(command)); + for (Entry command : this.config.getAutoCommands().entrySet()) { + this.commandWidgets.put(command.getKey(), new AutoCommandWidget(command.getValue())); } } @@ -129,28 +130,23 @@ private void performAction(Action action) { this.redirectScreen(new CommandContextManagerActivity(this.selectedCommand)); return; } - Consumer editCallback = (command) -> { - this.config.removeAutoCommand(this.selectedCommand); - this.config.addAutoCommand(command); + Consumer callback = (command) -> { + this.config.setAutoCommand(command); this.selectedCommand = command; this.reload(); }; AdvancedPopup popup = switch (action) { - case ADD -> new EditAutoCommandPopup(null, (command) -> { - this.config.addAutoCommand(command); - this.selectedCommand = command; - this.reload(); - }); - case EDIT -> new EditAutoCommandPopup(this.selectedCommand, editCallback); + case ADD -> new EditAutoCommandPopup(null, callback); + case EDIT -> new EditAutoCommandPopup(this.selectedCommand, callback); case REMOVE -> SimpleAdvancedPopup.builder() - .title(Component.translatable(I18N_PREFIX + ".remove.title")) + .title(Component.translatable(I18N_PREFIX + "remove.title")) .description(Component.translatable( - I18N_PREFIX + ".remove.description", + I18N_PREFIX + "remove.description", Component.text(this.selectedCommand.getName(), NamedTextColor.AQUA) )) .addButton(SimplePopupButton.confirm(simplePopupButton -> { - this.config.removeAutoCommand(this.selectedCommand); + this.config.removeAutoCommand(this.selectedCommand.getUuid()); this.reload(); })) .addButton(SimplePopupButton.cancel()) diff --git a/core/src/main/java/com/rappytv/autocommand/core/ui/popup/EditAutoCommandPopup.java b/core/src/main/java/com/rappytv/autocommand/core/ui/popup/EditAutoCommandPopup.java index 8e84cd3..b26e917 100644 --- a/core/src/main/java/com/rappytv/autocommand/core/ui/popup/EditAutoCommandPopup.java +++ b/core/src/main/java/com/rappytv/autocommand/core/ui/popup/EditAutoCommandPopup.java @@ -44,7 +44,7 @@ public EditAutoCommandPopup(AutoCommandMeta meta, Consumer onSu super.buttons.add(this.confirmButton = SimplePopupButton.confirm((ignored) -> { this.meta.setEnabled(this.enabledCheckbox.state() == State.CHECKED); this.meta.setName(this.nameTextField.getText()); - this.meta.setName(this.commandTextField.getText()); + this.meta.setCommand(this.commandTextField.getText()); this.meta.setDelay(this.delaySlider.getValue()); onSubmit.accept(this.meta); })); From 95b82b9b9739d0d454c816d04b4ce5b05367fad9 Mon Sep 17 00:00:00 2001 From: RappyTV Date: Thu, 9 Jul 2026 17:18:04 +0200 Subject: [PATCH 22/30] fix: edit/remove button disabled when returning to list --- .../autocommand/core/ui/activity/CommandManagerActivity.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/com/rappytv/autocommand/core/ui/activity/CommandManagerActivity.java b/core/src/main/java/com/rappytv/autocommand/core/ui/activity/CommandManagerActivity.java index 1d7b904..460f0e5 100644 --- a/core/src/main/java/com/rappytv/autocommand/core/ui/activity/CommandManagerActivity.java +++ b/core/src/main/java/com/rappytv/autocommand/core/ui/activity/CommandManagerActivity.java @@ -84,13 +84,13 @@ public void initialize(Parent parent) { "labymod.ui.button.edit", () -> this.performAction(Action.EDIT) ); - this.editButton.setEnabled(false); + this.editButton.setEnabled(selectedEntry != null); this.removeButton = ButtonWidget.i18n( "labymod.ui.button.remove", () -> this.performAction(Action.REMOVE) ); - this.removeButton.setEnabled(false); + this.removeButton.setEnabled(selectedEntry != null); buttons.addEntry(addButton); buttons.addEntry(this.editButton); From 967f3631781883c16b3bd6d66247f33c2310c798 Mon Sep 17 00:00:00 2001 From: RappyTV Date: Thu, 9 Jul 2026 17:19:00 +0200 Subject: [PATCH 23/30] chore: remove unused method --- .../autocommand/core/ui/widget/AutoCommandContextWidget.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/core/src/main/java/com/rappytv/autocommand/core/ui/widget/AutoCommandContextWidget.java b/core/src/main/java/com/rappytv/autocommand/core/ui/widget/AutoCommandContextWidget.java index 3d7fd69..cbdf9c6 100644 --- a/core/src/main/java/com/rappytv/autocommand/core/ui/widget/AutoCommandContextWidget.java +++ b/core/src/main/java/com/rappytv/autocommand/core/ui/widget/AutoCommandContextWidget.java @@ -65,10 +65,6 @@ public void initialize(Parent parent) { this.addEntry(removeButton); } - public AutoCommandMeta.Context getContext() { - return this.context; - } - private String formatContextType() { return String.format( "autocommand.activity.context.type.%s", From bb879a03e9cc2eeee25d0f3279c0d7282124d993 Mon Sep 17 00:00:00 2001 From: RappyTV Date: Thu, 9 Jul 2026 17:25:10 +0200 Subject: [PATCH 24/30] chore: add texture helper class TODO: add icons.png --- .../autocommand/api/AutoCommandTextures.java | 17 ++++++++++++++ .../ui/widget/AutoCommandContextWidget.java | 21 +++++------------- .../core/ui/widget/AutoCommandWidget.java | 7 ++---- .../autocommand/textures/command_block.png | Bin 8129 -> 0 bytes 4 files changed, 24 insertions(+), 21 deletions(-) create mode 100644 api/src/main/java/com/rappytv/autocommand/api/AutoCommandTextures.java delete mode 100644 core/src/main/resources/assets/autocommand/textures/command_block.png diff --git a/api/src/main/java/com/rappytv/autocommand/api/AutoCommandTextures.java b/api/src/main/java/com/rappytv/autocommand/api/AutoCommandTextures.java new file mode 100644 index 0000000..559ddbf --- /dev/null +++ b/api/src/main/java/com/rappytv/autocommand/api/AutoCommandTextures.java @@ -0,0 +1,17 @@ +package com.rappytv.autocommand.api; + +import net.labymod.api.client.gui.icon.Icon; +import net.labymod.api.client.resources.ResourceLocation; + +public class AutoCommandTextures { + + public static final ResourceLocation SPRITE = ResourceLocation.create( + "autocommand", + "textures/icons.png" + ); + + // TODO: tune these + public static final Icon COMMAND_BLOCK = Icon.sprite32(SPRITE, 0, 0); + public static final Icon SINGLE_PLAYER = Icon.sprite32(SPRITE, 1, 0); + public static final Icon MULTI_PLAYER = Icon.sprite32(SPRITE, 2, 0); +} diff --git a/core/src/main/java/com/rappytv/autocommand/core/ui/widget/AutoCommandContextWidget.java b/core/src/main/java/com/rappytv/autocommand/core/ui/widget/AutoCommandContextWidget.java index cbdf9c6..68e5209 100644 --- a/core/src/main/java/com/rappytv/autocommand/core/ui/widget/AutoCommandContextWidget.java +++ b/core/src/main/java/com/rappytv/autocommand/core/ui/widget/AutoCommandContextWidget.java @@ -2,7 +2,7 @@ import com.rappytv.autocommand.api.AutoCommandMeta; import com.rappytv.autocommand.api.AutoCommandMeta.Context.Type; -import net.labymod.api.client.gui.icon.Icon; +import com.rappytv.autocommand.api.AutoCommandTextures; import net.labymod.api.client.gui.lss.property.annotation.AutoWidget; import net.labymod.api.client.gui.screen.Parent; import net.labymod.api.client.gui.screen.widget.action.Pressable; @@ -11,21 +11,10 @@ import net.labymod.api.client.gui.screen.widget.widgets.layout.list.HorizontalListWidget; import net.labymod.api.client.gui.screen.widget.widgets.layout.list.VerticalListWidget; import net.labymod.api.client.gui.screen.widget.widgets.renderer.IconWidget; -import net.labymod.api.client.resources.ResourceLocation; @AutoWidget public class AutoCommandContextWidget extends HorizontalListWidget { - // TODO: add icons and sprite helper class - private static final ResourceLocation SINGLEPLAYER_ICON = ResourceLocation.create( - "autocommand", - "textures/command_block.png" - ); - private static final ResourceLocation MULTIPLAYER_ICON = ResourceLocation.create( - "autocommand", - "textures/command_block.png" - ); - private final AutoCommandMeta.Context context; private final Pressable onDelete; @@ -38,11 +27,11 @@ public AutoCommandContextWidget(AutoCommandMeta.Context context, Pressable onDel public void initialize(Parent parent) { super.initialize(parent); - IconWidget icon = new IconWidget(Icon.texture( + IconWidget icon = new IconWidget( this.context.type() == Type.SINGLEPLAYER - ? SINGLEPLAYER_ICON - : MULTIPLAYER_ICON - )); + ? AutoCommandTextures.SINGLE_PLAYER + : AutoCommandTextures.MULTI_PLAYER + ); icon.addId("context-icon"); VerticalListWidget componentGroup = new VerticalListWidget<>(); diff --git a/core/src/main/java/com/rappytv/autocommand/core/ui/widget/AutoCommandWidget.java b/core/src/main/java/com/rappytv/autocommand/core/ui/widget/AutoCommandWidget.java index cf53ce6..43e0b34 100644 --- a/core/src/main/java/com/rappytv/autocommand/core/ui/widget/AutoCommandWidget.java +++ b/core/src/main/java/com/rappytv/autocommand/core/ui/widget/AutoCommandWidget.java @@ -1,10 +1,10 @@ package com.rappytv.autocommand.core.ui.widget; import com.rappytv.autocommand.api.AutoCommandMeta; +import com.rappytv.autocommand.api.AutoCommandTextures; import java.text.DecimalFormat; import net.labymod.api.client.component.Component; import net.labymod.api.client.component.format.NamedTextColor; -import net.labymod.api.client.gui.icon.Icon; import net.labymod.api.client.gui.lss.property.annotation.AutoWidget; import net.labymod.api.client.gui.screen.Parent; import net.labymod.api.client.gui.screen.widget.Widget; @@ -12,13 +12,10 @@ import net.labymod.api.client.gui.screen.widget.widgets.layout.list.HorizontalListWidget; import net.labymod.api.client.gui.screen.widget.widgets.layout.list.VerticalListWidget; import net.labymod.api.client.gui.screen.widget.widgets.renderer.IconWidget; -import net.labymod.api.client.resources.ResourceLocation; @AutoWidget public class AutoCommandWidget extends HorizontalListWidget { - private static final ResourceLocation ICON = ResourceLocation.create("autocommand", - "textures/command_block.png"); private static final DecimalFormat FORMAT = new DecimalFormat("#.##"); private final AutoCommandMeta meta; @@ -37,7 +34,7 @@ public void initialize(Parent parent) { this.addId("disabled"); } - IconWidget icon = new IconWidget(Icon.texture(ICON)); + IconWidget icon = new IconWidget(AutoCommandTextures.COMMAND_BLOCK); icon.addId("command-icon"); VerticalListWidget componentGroup = new VerticalListWidget<>(); diff --git a/core/src/main/resources/assets/autocommand/textures/command_block.png b/core/src/main/resources/assets/autocommand/textures/command_block.png deleted file mode 100644 index 9ee0927719dbbeb2cdc05c29684585aac3fe3698..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8129 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 Date: Thu, 9 Jul 2026 17:54:51 +0200 Subject: [PATCH 25/30] chore: add hint --- .../ui/activity/CommandManagerActivity.java | 34 +++++++++++++++---- .../assets/autocommand/i18n/en_us.json | 6 ++-- .../themes/vanilla/lss/command-manager.lss | 10 ++++-- 3 files changed, 39 insertions(+), 11 deletions(-) diff --git a/core/src/main/java/com/rappytv/autocommand/core/ui/activity/CommandManagerActivity.java b/core/src/main/java/com/rappytv/autocommand/core/ui/activity/CommandManagerActivity.java index 460f0e5..58c1032 100644 --- a/core/src/main/java/com/rappytv/autocommand/core/ui/activity/CommandManagerActivity.java +++ b/core/src/main/java/com/rappytv/autocommand/core/ui/activity/CommandManagerActivity.java @@ -17,6 +17,8 @@ import net.labymod.api.client.gui.screen.activity.Link; import net.labymod.api.client.gui.screen.activity.Links; import net.labymod.api.client.gui.screen.key.Key; +import net.labymod.api.client.gui.screen.widget.context.ContextMenu; +import net.labymod.api.client.gui.screen.widget.context.ContextMenuEntry; import net.labymod.api.client.gui.screen.widget.widgets.ComponentWidget; import net.labymod.api.client.gui.screen.widget.widgets.DivWidget; import net.labymod.api.client.gui.screen.widget.widgets.input.ButtonWidget; @@ -49,8 +51,7 @@ public CommandManagerActivity(CommandConfig config) { this.commandList.addId("command-list"); this.commandList.setSelectCallback(selected -> { this.selectedCommand = selected.getMeta(); - this.editButton.setEnabled(true); - this.removeButton.setEnabled(true); + this.updateButtonVisibility(true); }); this.commandList.setDoubleClickCallback(ignored -> this.performAction(Action.EDIT)); } @@ -72,6 +73,9 @@ public void initialize(Parent parent) { this.commandList.addChild(commandWidget); } + ComponentWidget hint = ComponentWidget.i18n(I18N_PREFIX + "hint"); + hint.addId("hint-text"); + HorizontalListWidget buttons = new HorizontalListWidget(); buttons.addId("buttons"); @@ -84,13 +88,12 @@ public void initialize(Parent parent) { "labymod.ui.button.edit", () -> this.performAction(Action.EDIT) ); - this.editButton.setEnabled(selectedEntry != null); this.removeButton = ButtonWidget.i18n( "labymod.ui.button.remove", () -> this.performAction(Action.REMOVE) ); - this.removeButton.setEnabled(selectedEntry != null); + this.updateButtonVisibility(selectedEntry != null); buttons.addEntry(addButton); buttons.addEntry(this.editButton); @@ -107,6 +110,7 @@ public void initialize(Parent parent) { } container.addFlexibleContent(content); container.addContent(buttons); + container.addContent(hint); this.document.addChild(container); } @@ -120,13 +124,30 @@ public void reload() { private void loadCommands() { this.commandWidgets.clear(); for (Entry command : this.config.getAutoCommands().entrySet()) { - this.commandWidgets.put(command.getKey(), new AutoCommandWidget(command.getValue())); + ContextMenuEntry entry = ContextMenuEntry.builder() + .text(Component.translatable(I18N_PREFIX + "manageContexts")) + .clickHandler(ignored -> { + this.redirectScreen(new CommandContextManagerActivity(command.getValue())); + return true; + }) + .build(); + + ContextMenu menu = new ContextMenu(); + menu.addEntry(entry); + + AutoCommandWidget widget = new AutoCommandWidget(command.getValue()); + widget.setContextMenu(menu); + this.commandWidgets.put(command.getKey(), widget); } } + private void updateButtonVisibility(boolean visible) { + this.editButton.setEnabled(visible); + this.removeButton.setEnabled(visible); + } + private void performAction(Action action) { if(action == Action.EDIT && (Key.L_SHIFT.isPressed() || Key.L_CONTROL.isPressed())) { - // TODO: add more intuitive way to open this this.redirectScreen(new CommandContextManagerActivity(this.selectedCommand)); return; } @@ -147,6 +168,7 @@ private void performAction(Action action) { )) .addButton(SimplePopupButton.confirm(simplePopupButton -> { this.config.removeAutoCommand(this.selectedCommand.getUuid()); + this.commandList.listSession().setSelectedEntry(null); this.reload(); })) .addButton(SimplePopupButton.cancel()) diff --git a/core/src/main/resources/assets/autocommand/i18n/en_us.json b/core/src/main/resources/assets/autocommand/i18n/en_us.json index 4461d61..c45b15d 100644 --- a/core/src/main/resources/assets/autocommand/i18n/en_us.json +++ b/core/src/main/resources/assets/autocommand/i18n/en_us.json @@ -11,6 +11,8 @@ "activity": { "command": { "empty": "Nothing here yet.\nGo ahead and create an automated command!", + "hint": "Hint: Right-click to limit which worlds a command runs in.", + "manageContexts": "Manage contexts", "remove": { "title": "Are you sure?", "description": "Do you want to delete your automated command %s?" @@ -19,8 +21,8 @@ "context": { "back": "Leave context manager", "add": "Add current world", - "invalid": "You're not in a valid context. If you believe this is an error please contact me.", - "duplicate": "This context already covered.", + "invalid": "You're not in a valid world context.\n\nIf you believe this is an error please create a bug report.", + "duplicate": "This world context is already in the list.", "type": { "singleplayer": "Singleplayer World", "multiplayer": "Multiplayer Server" diff --git a/core/src/main/resources/assets/autocommand/themes/vanilla/lss/command-manager.lss b/core/src/main/resources/assets/autocommand/themes/vanilla/lss/command-manager.lss index b50670d..5cea76a 100644 --- a/core/src/main/resources/assets/autocommand/themes/vanilla/lss/command-manager.lss +++ b/core/src/main/resources/assets/autocommand/themes/vanilla/lss/command-manager.lss @@ -3,9 +3,6 @@ height: 100%; .content { - margin-top: 5; - margin-bottom: 5; - .error-component { width: 80%; text-color: blue; @@ -38,4 +35,11 @@ layout: fill; margin: 5 0 5 0; } + + .hint-text { + text-color: dark_gray; + font-size: 0.8; + alignment-x: center; + margin-bottom: 5; + } } \ No newline at end of file From eceee847d642a29a370adc6d1d01e8482ae079f2 Mon Sep 17 00:00:00 2001 From: RappyTV Date: Thu, 23 Jul 2026 19:10:41 +0200 Subject: [PATCH 26/30] feat: add icons --- .../autocommand/api/AutoCommandTextures.java | 11 ++--------- .../core/ui/widget/AutoCommandContextWidget.java | 6 +++--- .../autocommand/textures/command_block.png | Bin 0 -> 8129 bytes 3 files changed, 5 insertions(+), 12 deletions(-) create mode 100644 core/src/main/resources/assets/autocommand/textures/command_block.png diff --git a/api/src/main/java/com/rappytv/autocommand/api/AutoCommandTextures.java b/api/src/main/java/com/rappytv/autocommand/api/AutoCommandTextures.java index 559ddbf..9570875 100644 --- a/api/src/main/java/com/rappytv/autocommand/api/AutoCommandTextures.java +++ b/api/src/main/java/com/rappytv/autocommand/api/AutoCommandTextures.java @@ -5,13 +5,6 @@ public class AutoCommandTextures { - public static final ResourceLocation SPRITE = ResourceLocation.create( - "autocommand", - "textures/icons.png" - ); - - // TODO: tune these - public static final Icon COMMAND_BLOCK = Icon.sprite32(SPRITE, 0, 0); - public static final Icon SINGLE_PLAYER = Icon.sprite32(SPRITE, 1, 0); - public static final Icon MULTI_PLAYER = Icon.sprite32(SPRITE, 2, 0); + public static final Icon COMMAND_BLOCK = Icon.texture( + ResourceLocation.create("autocommand", "textures/command_block.png")); } diff --git a/core/src/main/java/com/rappytv/autocommand/core/ui/widget/AutoCommandContextWidget.java b/core/src/main/java/com/rappytv/autocommand/core/ui/widget/AutoCommandContextWidget.java index 68e5209..106f124 100644 --- a/core/src/main/java/com/rappytv/autocommand/core/ui/widget/AutoCommandContextWidget.java +++ b/core/src/main/java/com/rappytv/autocommand/core/ui/widget/AutoCommandContextWidget.java @@ -2,7 +2,7 @@ import com.rappytv.autocommand.api.AutoCommandMeta; import com.rappytv.autocommand.api.AutoCommandMeta.Context.Type; -import com.rappytv.autocommand.api.AutoCommandTextures; +import net.labymod.api.Textures.SpriteCommon; import net.labymod.api.client.gui.lss.property.annotation.AutoWidget; import net.labymod.api.client.gui.screen.Parent; import net.labymod.api.client.gui.screen.widget.action.Pressable; @@ -29,8 +29,8 @@ public void initialize(Parent parent) { IconWidget icon = new IconWidget( this.context.type() == Type.SINGLEPLAYER - ? AutoCommandTextures.SINGLE_PLAYER - : AutoCommandTextures.MULTI_PLAYER + ? SpriteCommon.SINGLEPLAYER + : SpriteCommon.MULTIPLAYER ); icon.addId("context-icon"); diff --git a/core/src/main/resources/assets/autocommand/textures/command_block.png b/core/src/main/resources/assets/autocommand/textures/command_block.png new file mode 100644 index 0000000000000000000000000000000000000000..9ee0927719dbbeb2cdc05c29684585aac3fe3698 GIT binary patch literal 8129 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 Date: Thu, 23 Jul 2026 19:11:09 +0200 Subject: [PATCH 27/30] chore: improve hint readability --- .../assets/autocommand/themes/vanilla/lss/command-manager.lss | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core/src/main/resources/assets/autocommand/themes/vanilla/lss/command-manager.lss b/core/src/main/resources/assets/autocommand/themes/vanilla/lss/command-manager.lss index 5cea76a..9378332 100644 --- a/core/src/main/resources/assets/autocommand/themes/vanilla/lss/command-manager.lss +++ b/core/src/main/resources/assets/autocommand/themes/vanilla/lss/command-manager.lss @@ -37,8 +37,7 @@ } .hint-text { - text-color: dark_gray; - font-size: 0.8; + text-color: yellow; alignment-x: center; margin-bottom: 5; } From 9c04e8d090367dadd192e15c4ee78cc623cf32b3 Mon Sep 17 00:00:00 2001 From: RappyTV Date: Thu, 23 Jul 2026 19:19:17 +0200 Subject: [PATCH 28/30] feat: add icon, compress images --- .../autocommand/textures/command_block.png | Bin 8129 -> 6872 bytes .../assets/autocommand/textures/icon.png | Bin 0 -> 151827 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 core/src/main/resources/assets/autocommand/textures/icon.png diff --git a/core/src/main/resources/assets/autocommand/textures/command_block.png b/core/src/main/resources/assets/autocommand/textures/command_block.png index 9ee0927719dbbeb2cdc05c29684585aac3fe3698..c3685c23f490a1937a195fcc27c6ad5e19839650 100644 GIT binary patch literal 6872 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 literal 0 HcmV?d00001 From 2bf17f0d6319acaa150b1b004e4c29b1bf7c009e Mon Sep 17 00:00:00 2001 From: RappyTV Date: Thu, 23 Jul 2026 19:30:42 +0200 Subject: [PATCH 29/30] feat: add config sprite, register revision --- .../autocommand/core/AutoCommandAddon.java | 12 ++++++++++++ .../core/config/AutoCommandAddonConfig.java | 18 +++++++++++++----- .../themes/vanilla/textures/settings.png | Bin 0 -> 1572 bytes 3 files changed, 25 insertions(+), 5 deletions(-) create mode 100644 core/src/main/resources/assets/autocommand/themes/vanilla/textures/settings.png diff --git a/core/src/main/java/com/rappytv/autocommand/core/AutoCommandAddon.java b/core/src/main/java/com/rappytv/autocommand/core/AutoCommandAddon.java index d742271..d0ee1d3 100644 --- a/core/src/main/java/com/rappytv/autocommand/core/AutoCommandAddon.java +++ b/core/src/main/java/com/rappytv/autocommand/core/AutoCommandAddon.java @@ -3,8 +3,11 @@ import com.rappytv.autocommand.core.config.AutoCommandAddonConfig; import com.rappytv.autocommand.core.config.CommandConfig; import com.rappytv.autocommand.core.listener.WorldEnterListener; +import net.labymod.api.Laby; import net.labymod.api.addon.LabyAddon; import net.labymod.api.models.addon.annotation.AddonMain; +import net.labymod.api.revision.SimpleRevision; +import net.labymod.api.util.version.SemanticVersion; @AddonMain public class AutoCommandAddon extends LabyAddon { @@ -12,6 +15,15 @@ public class AutoCommandAddon extends LabyAddon { private static AutoCommandAddon INSTANCE; private CommandConfig commandConfig; + @Override + protected void preConfigurationLoad() { + Laby.references().revisionRegistry().register(new SimpleRevision( + "autocommand", + new SemanticVersion(1, 0, 0), + "2026-07-23" + )); + } + @Override protected void enable() { INSTANCE = this; diff --git a/core/src/main/java/com/rappytv/autocommand/core/config/AutoCommandAddonConfig.java b/core/src/main/java/com/rappytv/autocommand/core/config/AutoCommandAddonConfig.java index a5158fe..6de3381 100644 --- a/core/src/main/java/com/rappytv/autocommand/core/config/AutoCommandAddonConfig.java +++ b/core/src/main/java/com/rappytv/autocommand/core/config/AutoCommandAddonConfig.java @@ -6,22 +6,30 @@ import net.labymod.api.client.gui.screen.activity.Activity; import net.labymod.api.client.gui.screen.widget.widgets.activity.settings.ActivitySettingWidget.ActivitySetting; import net.labymod.api.client.gui.screen.widget.widgets.input.SwitchWidget.SwitchSetting; +import net.labymod.api.configuration.loader.annotation.IntroducedIn; +import net.labymod.api.configuration.loader.annotation.SpriteSlot; +import net.labymod.api.configuration.loader.annotation.SpriteTexture; import net.labymod.api.configuration.loader.property.ConfigProperty; import net.labymod.api.util.MethodOrder; +@SpriteTexture("settings") public class AutoCommandAddonConfig extends AddonConfig { + @IntroducedIn(namespace = "autocommand", value = "1.0.0") + @SpriteSlot @SwitchSetting private final ConfigProperty enabled = new ConfigProperty<>(true); - @Override - public ConfigProperty enabled() { - return this.enabled; - } - + @IntroducedIn(namespace = "autocommand", value = "1.0.0") + @SpriteSlot(x = 1, size = 32) @MethodOrder(after = "enabled") @ActivitySetting public Activity commandManager() { return new CommandManagerActivity(AutoCommandAddon.getCommandConfig()); } + + @Override + public ConfigProperty enabled() { + return this.enabled; + } } diff --git a/core/src/main/resources/assets/autocommand/themes/vanilla/textures/settings.png b/core/src/main/resources/assets/autocommand/themes/vanilla/textures/settings.png new file mode 100644 index 0000000000000000000000000000000000000000..47735a646dfdeda51cac16246f852fdf7bb09652 GIT binary patch literal 1572 zcmV+<2HW|GP)C0005_P)t-s0002i zfB$Pgf2oLbZEJED-D1RiPI^r+cuOt-Qvi~XnWJYw04)Ho{mrY3cL1s^%%qBbWmbJy zL5EBxtf{lHt+%RqS*2-0WH}sOF%fHPb%I+$yKFl_^Mt5|Z-j1PbVeswJ0(dmA2cZ$ z0DBmM_N}?0lhT)Pi+OIxk8ERKWvFyg!+A=$bx5ORJ&I2$Z9pMtJRUtR8LZ| zo~n3whO(7}cXfYraCmQRbf$r8uzp{pbyt02QowmluyIIZO+A}iFKR= zPBa_a|Le7~yx6# zQB{6QNp(m`rAkM?bw<90KxjBPgD57#d?RKfAaei!-^?7I00001bW%=J06^y0W&i*K z+DSw~RCwC$*JpRqP#6brHE9wP3nXEMS)d{t%BB{|DztXjF88*>?$*8c-g|HTnqK?P zD$U`T6Fr>g|Lz{{;r_Thcdc2Obt|&sV}cOrUu}K|to*_BVv$217hlG<_r_1)%Zk&1PlYhE)KjBc{S= z+;H^7iKB-2s0}qG1fcPM0+65*pl6p`<)*rhKYD!Z*prjTyVdhXxBH-Ufcm<+`g&!X zvI4;8pHQh(uV!Kzjpoc5jpoD2?ds@O_rwuGO29^CV+BB~Zz6J9rFu3U?fCLtqxt%& zV|#S>bdM@>m+;F1U;=?iLU)= z2HMBTVv!ti3==-W=hyeLO%ejkjcpYGUcT(qGCv6eyHqG=vnGP@Q^sB^cTK8gsBCL& zY};628Q!rtEoCjkwC?ZOu?1zvS(Cp=a!m^hqnt#5WdZvAe+Fz;Sg=GXz%br}o0gO9 z3x!6O<_G)jlag)48&E23#X$^3q1BEBd2K72d``&BI2?n6o_@O&H6VT%4R2LoiYpHL zSi)ImbVX9=Wv?6>^x)0?_67+6;>WR$*D7WU>Qgz);%w1TMi-m0d2sxG^QHC%365j& z^P0)$Y&+Fm>gRj01V46DZ)N)q;kOOvoBP930K}(=VcI)lbZ2MxW(<3(<$Bq^p%i`r ze~V^7ioZY{5b!!QG#$H57ZRAIBnU2-9mg*iKI7-YdRYKoeo51Lw~MBevsl_WWE2*Y zmp$+BefZ1KNm&4BBbx8r8GBFDxt1VLlH-T)>&^QN-|&5QP8I;#h_-gq^v)N%4U6~k z)U5^29vm;@c(OZpO%^~9D1uuPs##VlP@dME$tUC zUu{wFT29Zh?BVb&&L{{CYh(eSq)Ys8xPZ=tL{M+Fvg~w-Bq_8689>sD6c1* z4qG!JibS(7Cjf;Bq!s8`zRBqYD}{!a8-Nnj?k({oWxR@3pZtL3l=4#)NlE)St@8P- zqojVGuah_8_W_yP0000000000{11S?4BQ85pauW{00000005{qa383>8UO$Q00000 z0HE5yeW3Pg0000000000fNBHxf!eD90000000000stw!+YOe+W000000002^$N2#- W2I^>_x6;Z00000 Date: Thu, 23 Jul 2026 20:48:50 +0200 Subject: [PATCH 30/30] fix: build always fails --- .github/workflows/build.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3a8b074..206c654 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -22,6 +22,8 @@ jobs: with: validate-wrappers: true cache-read-only: ${{ github.ref != format('refs/heads/{0}', github.event.repository.default_branch) }} + - name: Grant execute permission for gradlew + run: chmod +x gradlew - name: Build with Gradle run: ./gradlew build --full-stacktrace - name: Create Release Artifact