This commit is contained in:
Darto KLoning
2026-10-04 00:04:25 +07:00
parent f2dc75d6c8
commit daa48f819e
5 changed files with 1 additions and 255 deletions
-15
View File
@@ -257,18 +257,3 @@ Local/cracked identity tidak mempunyai Mojang profile public key. Dengan `enforc
## License ## License
All Rights Reserved. Source dan asset Lobby Systems tidak boleh didistribusikan atau digunakan ulang di luar izin pemilik project. 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.
+1 -1
View File
@@ -5,6 +5,6 @@ minecraft_version=26.2
loader_version=0.19.3 loader_version=0.19.3
loom_version=1.17-SNAPSHOT loom_version=1.17-SNAPSHOT
fabric_api_version=0.156.0+26.2 fabric_api_version=0.156.0+26.2
mod_version=1.10.1 mod_version=1.9.0
maven_group=id.dartokloning maven_group=id.dartokloning
archives_base_name=lobby-systems archives_base_name=lobby-systems
@@ -76,17 +76,6 @@ public final class AuthManager {
} }
public AuthConfig config() { return config; } 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. */ /** Re-applies the freshly loaded auth configuration to players already online. */
public void applyReload(MinecraftServer server) { public void applyReload(MinecraftServer server) {
@@ -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 }
}
@@ -48,7 +48,6 @@ public final class LobbySystemsMod implements ModInitializer {
private static final DimensionGameRuleManager DIMENSION_GAMERULES = new DimensionGameRuleManager(); private static final DimensionGameRuleManager DIMENSION_GAMERULES = new DimensionGameRuleManager();
private static final StarterKitManager STARTER_KITS = new StarterKitManager(); private static final StarterKitManager STARTER_KITS = new StarterKitManager();
private static final AuthManager AUTH = new AuthManager(); private static final AuthManager AUTH = new AuthManager();
private static final ConfigGui CONFIG_GUI = new ConfigGui(CONFIG, AUTH);
private static int saveTicker; private static int saveTicker;
private static final java.util.Set<String> LOCAL_LOGIN_NAMES = java.util.concurrent.ConcurrentHashMap.newKeySet(); private static final java.util.Set<String> LOCAL_LOGIN_NAMES = java.util.concurrent.ConcurrentHashMap.newKeySet();
@@ -272,8 +271,6 @@ public final class LobbySystemsMod implements ModInitializer {
dispatcher.register(Commands.literal("ls") dispatcher.register(Commands.literal("ls")
.requires(Commands.hasPermission(Commands.LEVEL_ADMINS)) .requires(Commands.hasPermission(Commands.LEVEL_ADMINS))
.then(Commands.literal("config")
.executes(ctx -> { CONFIG_GUI.open(ctx.getSource().getPlayerOrException()); return 1; }))
.then(Commands.literal("reload") .then(Commands.literal("reload")
.executes(ctx -> reloadAll(ctx.getSource().getServer(), ctx.getSource()))) .executes(ctx -> reloadAll(ctx.getSource().getServer(), ctx.getSource())))
.then(Commands.literal("tp") .then(Commands.literal("tp")