diff --git a/README.md b/README.md index d2c2539..849e894 100644 --- a/README.md +++ b/README.md @@ -257,18 +257,3 @@ Local/cracked identity tidak mempunyai Mojang profile public key. Dengan `enforc ## License All Rights Reserved. Source dan asset Lobby Systems tidak boleh didistribusikan atau digunakan ulang di luar izin pemilik project. - -## v1.10.0 - Configuration GUI - -Operator-only `/ls config` opens a vanilla 6-row chest menu named **Lobby Systems Configuration**. No client-side mod is required for the menu itself. - -The first GUI release focuses on settings that can be changed safely with inventory clicks: - -- **Lobby**: minimum play time, portal check interval, portal cooldown. -- **Authentication**: enabled, premium auto-login, premium username protection, require-login-every-join, authentication timeout, max attempts, minimum password length, PBKDF2 iterations. -- **Server Rules**: enabled, rules version, rules timeout. -- **Dimensions**, **Starter Kits**, and **Portals** are represented in the root menu and direct administrators to their existing `/ls` management commands. This deliberately avoids turning structured lists and world-specific records into unsafe one-click edits. - -Controls: left click increases numeric values, right click decreases them; boolean entries toggle on click. Changes are saved immediately. Auth/Rules changes are also applied to the current runtime state, so a separate `/ls reload` is not required for GUI edits. Manual JSON edits still use `/ls reload`. - -The configuration GUI edits configuration only. `player.json` and `starterkit/recipients.json` remain persistent runtime databases and are not exposed as raw editable GUI data. diff --git a/gradle.properties b/gradle.properties index b62a709..c1ac1c2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,6 +5,6 @@ minecraft_version=26.2 loader_version=0.19.3 loom_version=1.17-SNAPSHOT fabric_api_version=0.156.0+26.2 -mod_version=1.10.1 +mod_version=1.9.0 maven_group=id.dartokloning archives_base_name=lobby-systems diff --git a/src/main/java/id/dartokloning/lobbysystems/AuthManager.java b/src/main/java/id/dartokloning/lobbysystems/AuthManager.java index 7594264..606bd0a 100644 --- a/src/main/java/id/dartokloning/lobbysystems/AuthManager.java +++ b/src/main/java/id/dartokloning/lobbysystems/AuthManager.java @@ -76,17 +76,6 @@ public final class AuthManager { } public AuthConfig config() { return config; } - public RulesConfig rules() { return rules; } - - public void saveConfiguration() { - try { - Files.createDirectories(ConfigPaths.AUTH_DIRECTORY); - saveConfig(); - saveRules(); - } catch (Exception e) { - LobbySystemsMod.LOGGER.error("Failed to save Lobby Systems Auth configuration", e); - } - } /** Re-applies the freshly loaded auth configuration to players already online. */ public void applyReload(MinecraftServer server) { diff --git a/src/main/java/id/dartokloning/lobbysystems/ConfigGui.java b/src/main/java/id/dartokloning/lobbysystems/ConfigGui.java deleted file mode 100644 index 74502b2..0000000 --- a/src/main/java/id/dartokloning/lobbysystems/ConfigGui.java +++ /dev/null @@ -1,225 +0,0 @@ -package id.dartokloning.lobbysystems; - -import net.minecraft.ChatFormatting; -import net.minecraft.core.component.DataComponents; -import net.minecraft.network.chat.Component; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.Container; -import net.minecraft.world.SimpleContainer; -import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.inventory.ChestMenu; -import net.minecraft.world.inventory.ContainerInput; -import net.minecraft.world.inventory.MenuType; -import net.minecraft.world.SimpleMenuProvider; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; - -/** Server-side vanilla chest GUI for Lobby Systems administration. */ -public final class ConfigGui { - private static final int SIZE = 54; - private final ConfigManager configManager; - private final AuthManager authManager; - - public ConfigGui(ConfigManager configManager, AuthManager authManager) { - this.configManager = configManager; - this.authManager = authManager; - } - - public void open(ServerPlayer player) { open(player, Page.ROOT); } - - private void open(ServerPlayer player, Page page) { - Component title = Component.literal(switch (page) { - case ROOT -> "Lobby Systems Configuration"; - case AUTH -> "Authentication Configuration"; - case RULES -> "Server Rules Configuration"; - case LOBBY -> "Lobby Configuration"; - }); - player.openMenu(new SimpleMenuProvider( - (id, inventory, ignored) -> new GuiMenu(id, inventory, player, page), title)); - } - - private final class GuiMenu extends ChestMenu { - private final ServerPlayer viewer; - private final Page page; - private final SimpleContainer gui; - - GuiMenu(int id, Inventory inventory, ServerPlayer viewer, Page page) { - this(id, inventory, viewer, page, new SimpleContainer(SIZE)); - } - - private GuiMenu(int id, Inventory inventory, ServerPlayer viewer, Page page, SimpleContainer gui) { - super(MenuType.GENERIC_9x6, id, inventory, gui, 6); - this.viewer = viewer; - this.page = page; - this.gui = gui; - render(); - } - - @Override - public void clicked(int slotIndex, int buttonNum, ContainerInput input, Player player) { - if (slotIndex < 0 || slotIndex >= SIZE) return; - if (input != ContainerInput.PICKUP && input != ContainerInput.QUICK_MOVE) return; - handle(slotIndex, buttonNum); - } - - @Override - public ItemStack quickMoveStack(Player player, int slotIndex) { return ItemStack.EMPTY; } - - @Override - public boolean stillValid(Player player) { return true; } - - private void handle(int slot, int button) { - boolean right = button == 1; - switch (page) { - case ROOT -> { - if (slot == 20) open(viewer, Page.LOBBY); - else if (slot == 22) open(viewer, Page.AUTH); - else if (slot == 24) open(viewer, Page.RULES); - else if (slot == 38) viewer.sendSystemMessage(Component.literal("Dimension settings are managed by /ls gamemode and /ls gamerule.").withStyle(ChatFormatting.YELLOW)); - else if (slot == 40) viewer.sendSystemMessage(Component.literal("Starter Kits are managed by /ls starterkit commands.").withStyle(ChatFormatting.YELLOW)); - else if (slot == 42) viewer.sendSystemMessage(Component.literal("Portals are managed by /ls portal commands.").withStyle(ChatFormatting.YELLOW)); - else if (slot == 49) viewer.closeContainer(); - } - case AUTH -> handleAuth(slot, right); - case RULES -> handleRules(slot, right); - case LOBBY -> handleLobby(slot, right); - } - } - - private void handleAuth(int slot, boolean right) { - AuthConfig c = authManager.config(); - boolean changed = true; - switch (slot) { - case 10 -> c.enabled = !c.enabled; - case 12 -> c.premiumAutoLogin = !c.premiumAutoLogin; - case 14 -> c.protectPremiumUsernames = !c.protectPremiumUsernames; - case 16 -> c.requireLoginEveryJoin = !c.requireLoginEveryJoin; - case 28 -> c.authenticationTimeoutSeconds = adjust(c.authenticationTimeoutSeconds, right ? -30 : 30, 30, 3600); - case 30 -> c.maxLoginAttempts = adjust(c.maxLoginAttempts, right ? -1 : 1, 1, 20); - case 32 -> c.minimumPasswordLength = adjust(c.minimumPasswordLength, right ? -1 : 1, 4, 128); - case 34 -> c.pbkdf2Iterations = adjust(c.pbkdf2Iterations, right ? -10000 : 10000, 50000, 2000000); - case 45 -> { open(viewer, Page.ROOT); return; } - case 49 -> { viewer.closeContainer(); return; } - default -> changed = false; - } - if (changed) { - authManager.saveConfiguration(); - authManager.applyReload(viewer.level().getServer()); - render(); - } - } - - private void handleRules(int slot, boolean right) { - RulesConfig c = authManager.rules(); - boolean changed = true; - switch (slot) { - case 11 -> c.enabled = !c.enabled; - case 13 -> c.version = adjust(c.version, right ? -1 : 1, 1, Integer.MAX_VALUE); - case 15 -> c.timeoutSeconds = adjust(c.timeoutSeconds, right ? -15 : 15, 15, 3600); - case 45 -> { open(viewer, Page.ROOT); return; } - case 49 -> { viewer.closeContainer(); return; } - default -> changed = false; - } - if (changed) { - authManager.saveConfiguration(); - authManager.applyReload(viewer.level().getServer()); - render(); - } - } - - private void handleLobby(int slot, boolean right) { - LobbyConfig c = configManager.get(); - boolean changed = true; - switch (slot) { - case 20 -> c.minimumPlaySeconds = adjust(c.minimumPlaySeconds, right ? -30 : 30, 0, 86400); - case 22 -> c.portalCheckIntervalTicks = adjust(c.portalCheckIntervalTicks, right ? -1 : 1, 1, 200); - case 24 -> c.portalCooldownTicks = adjust(c.portalCooldownTicks, right ? -10 : 10, 1, 1200); - case 45 -> { open(viewer, Page.ROOT); return; } - case 49 -> { viewer.closeContainer(); return; } - default -> changed = false; - } - if (changed) { configManager.save(); render(); } - } - - private void render() { - gui.clearContent(); - switch (page) { - case ROOT -> renderRoot(); - case AUTH -> renderAuth(); - case RULES -> renderRules(); - case LOBBY -> renderLobby(); - } - broadcastFullState(); - } - - private void renderRoot() { - set(20, Items.COMPASS, "Lobby", ChatFormatting.AQUA); - set(22, Items.IRON_DOOR, "Authentication", ChatFormatting.GREEN); - set(24, Items.WRITABLE_BOOK, "Server Rules", ChatFormatting.YELLOW); - set(38, Items.GRASS_BLOCK, "Dimensions", ChatFormatting.GREEN); - set(40, Items.CHEST, "Starter Kits", ChatFormatting.GOLD); - set(42, Items.ENDER_PEARL, "Portals", ChatFormatting.LIGHT_PURPLE); - set(49, Items.BARRIER, "Close", ChatFormatting.RED); - } - - private void renderAuth() { - AuthConfig c = authManager.config(); - toggle(10, Items.LEVER, "Auth Enabled", c.enabled); - toggle(12, Items.GOLD_INGOT, "Premium Auto Login", c.premiumAutoLogin); - toggle(14, Items.SHIELD, "Protect Premium Usernames", c.protectPremiumUsernames); - toggle(16, Items.NAME_TAG, "Require Login Every Join", c.requireLoginEveryJoin); - number(28, Items.CLOCK, "Authentication Timeout", c.authenticationTimeoutSeconds, "seconds", 30); - number(30, Items.REDSTONE, "Maximum Login Attempts", c.maxLoginAttempts, "attempts", 1); - number(32, Items.PAPER, "Minimum Password Length", c.minimumPasswordLength, "characters", 1); - number(34, Items.REPEATER, "PBKDF2 Iterations", c.pbkdf2Iterations, "iterations", 10000); - navigation(); - } - - private void renderRules() { - RulesConfig c = authManager.rules(); - toggle(11, Items.LEVER, "Rules Enabled", c.enabled); - number(13, Items.BOOK, "Rules Version", c.version, "", 1); - number(15, Items.CLOCK, "Rules Timeout", c.timeoutSeconds, "seconds", 15); - set(31, Items.WRITABLE_BOOK, "Rule text: edit auth/rules.json", ChatFormatting.GRAY); - navigation(); - } - - private void renderLobby() { - LobbyConfig c = configManager.get(); - set(13, Items.COMPASS, "Lobby Dimension: " + c.lobbyDimension, ChatFormatting.AQUA); - number(20, Items.CLOCK, "Minimum Play Time", c.minimumPlaySeconds, "seconds", 30); - number(22, Items.ENDER_EYE, "Portal Check Interval", c.portalCheckIntervalTicks, "ticks", 1); - number(24, Items.RECOVERY_COMPASS, "Portal Cooldown", c.portalCooldownTicks, "ticks", 10); - navigation(); - } - - private void navigation() { - set(45, Items.ARROW, "Back", ChatFormatting.YELLOW); - set(49, Items.BARRIER, "Close", ChatFormatting.RED); - } - - private void toggle(int slot, Item item, String label, boolean value) { - set(slot, item, label + ": " + (value ? "ON" : "OFF"), value ? ChatFormatting.GREEN : ChatFormatting.RED); - } - - private void number(int slot, Item item, String label, int value, String unit, int step) { - String suffix = unit.isBlank() ? "" : " " + unit; - set(slot, item, label + ": " + value + suffix + " (L +" + step + " / R -" + step + ")", ChatFormatting.YELLOW); - } - - private void set(int slot, Item item, String name, ChatFormatting color) { - ItemStack stack = new ItemStack(item); - stack.set(DataComponents.CUSTOM_NAME, Component.literal(name).withStyle(color)); - gui.setItem(slot, stack); - } - } - - private static int adjust(int value, int delta, int min, int max) { - long n = (long) value + delta; - return (int) Math.max(min, Math.min(max, n)); - } - - private enum Page { ROOT, AUTH, RULES, LOBBY } -} diff --git a/src/main/java/id/dartokloning/lobbysystems/LobbySystemsMod.java b/src/main/java/id/dartokloning/lobbysystems/LobbySystemsMod.java index 8de28ce..1e0538f 100644 --- a/src/main/java/id/dartokloning/lobbysystems/LobbySystemsMod.java +++ b/src/main/java/id/dartokloning/lobbysystems/LobbySystemsMod.java @@ -48,7 +48,6 @@ public final class LobbySystemsMod implements ModInitializer { private static final DimensionGameRuleManager DIMENSION_GAMERULES = new DimensionGameRuleManager(); private static final StarterKitManager STARTER_KITS = new StarterKitManager(); private static final AuthManager AUTH = new AuthManager(); - private static final ConfigGui CONFIG_GUI = new ConfigGui(CONFIG, AUTH); private static int saveTicker; private static final java.util.Set LOCAL_LOGIN_NAMES = java.util.concurrent.ConcurrentHashMap.newKeySet(); @@ -272,8 +271,6 @@ public final class LobbySystemsMod implements ModInitializer { dispatcher.register(Commands.literal("ls") .requires(Commands.hasPermission(Commands.LEVEL_ADMINS)) - .then(Commands.literal("config") - .executes(ctx -> { CONFIG_GUI.open(ctx.getSource().getPlayerOrException()); return 1; })) .then(Commands.literal("reload") .executes(ctx -> reloadAll(ctx.getSource().getServer(), ctx.getSource()))) .then(Commands.literal("tp")