fix parser string

This commit is contained in:
Darto KLoning
2026-09-06 16:19:01 +07:00
parent 5358bf9a8e
commit c8c8d1891b
4 changed files with 55 additions and 18 deletions
+10 -8
View File
@@ -1,7 +1,9 @@
# Lobby Systems v1.3.0 — Fabric 26.2 # Lobby Systems v1.3.1 — Fabric 26.2
Server-side lobby routing untuk Minecraft 26.2/Fabric. Versi 1.3.0 menambahkan viewer gamerule per-dimension dengan pagination dan pengelolaan gamemode player berdasarkan dimension, sambil mempertahankan portal antar-dimensi, last-position, minimum playtime, dan konfigurasi terpusat di `config/lobby/`. Server-side lobby routing untuk Minecraft 26.2/Fabric. Versi 1.3.0 menambahkan viewer gamerule per-dimension dengan pagination dan pengelolaan gamemode player berdasarkan dimension, sambil mempertahankan portal antar-dimensi, last-position, minimum playtime, dan konfigurasi terpusat di `config/lobby/`.
**v1.3.1 bugfix:** parser dimension command sekarang menerima resource identifier seperti `minecraft:lobby` tanpa memakan argumen sesudahnya. Ini memperbaiki `/ls gamerule <dimension>`, `/ls gamemode <dimension>`, dan `/ls gamemode set/remove ...`.
### Reload feedback ### Reload feedback
`/ls reload` menulis banner `RELOAD START` dan `RELOAD COMPLETE` hanya ke console server. Ringkasan reload satu baris dikirim langsung hanya ke player admin/operator yang menjalankan command; ringkasan tersebut tidak dibroadcast ke player lain dan tidak dikirim melalui command feedback ke console. `/ls reload` menulis banner `RELOAD START` dan `RELOAD COMPLETE` hanya ke console server. Ringkasan reload satu baris dikirim langsung hanya ke player admin/operator yang menjalankan command; ringkasan tersebut tidak dibroadcast ke player lain dan tidak dikirim melalui command feedback ke console.
@@ -38,7 +40,7 @@ chmod +x compile.sh release.sh
```text ```text
============================================ ============================================
Lobby Systems - Fabric 26.2 Build Lobby Systems - Fabric 26.2 Build
Version: 1.3.0 Version: 1.3.1
Namespace: id.dartokloning.lobbysystems Namespace: id.dartokloning.lobbysystems
Mod ID: dartokloning Mod ID: dartokloning
============================================ ============================================
@@ -47,7 +49,7 @@ chmod +x compile.sh release.sh
Output utama: Output utama:
```text ```text
build/libs/lobby-systems-1.3.0.jar build/libs/lobby-systems-1.3.1.jar
``` ```
`*-sources.jar` hanya source archive dan tidak perlu dipasang ke server. `*-sources.jar` hanya source archive dan tidak perlu dipasang ke server.
@@ -78,14 +80,14 @@ State penting Lobby Systems memakai separator agar mudah terlihat di server cons
```text ```text
============================================ ============================================
Lobby Systems - READY Lobby Systems - READY
Version: 1.3.0 Version: 1.3.1
Minecraft: 26.2 Minecraft: 26.2
Config directory: config/lobby Config directory: config/lobby
WorldEdit: available WorldEdit: available
============================================ ============================================
``` ```
## Struktur konfigurasi v1.3.0 ## Struktur konfigurasi v1.3.1
```text ```text
config/ config/
@@ -155,7 +157,7 @@ Portal adalah region/cuboid, bukan harus Nether Portal asli. Anda bebas membuat
### `config/lobby/dimension-gamemodes.json` ### `config/lobby/dimension-gamemodes.json`
Minecraft menyimpan gamemode pada player, bukan pada dimension. Lobby Systems v1.3.0 menambahkan mapping dimension → gamemode dan menerapkannya ketika player masuk ke dimension tersebut. File ini dibuat otomatis dan dapat dikelola lewat command admin. Minecraft menyimpan gamemode pada player, bukan pada dimension. Lobby Systems v1.3.1 menambahkan mapping dimension → gamemode dan menerapkannya ketika player masuk ke dimension tersebut. File ini dibuat otomatis dan dapat dikelola lewat command admin.
Contoh: Contoh:
@@ -171,7 +173,7 @@ Gamemode yang didukung: `survival`, `creative`, `adventure`, dan `spectator`.
## Migrasi dari v1.1.x ## Migrasi dari v1.1.x
Pada startup pertama v1.3.0: Pada startup pertama v1.3.1:
```text ```text
config/lobby-systems.json config/lobby-systems.json
@@ -195,7 +197,7 @@ akan dimigrasikan ke:
config/lobby/player-positions.json config/lobby/player-positions.json
``` ```
Nama file lama hanya digunakan oleh `LegacyConfigMigrator` untuk proses migrasi. Runtime v1.3.0 membaca dan menulis file baru di `config/lobby/`. Nama file lama hanya digunakan oleh `LegacyConfigMigrator` untuk proses migrasi. Runtime v1.3.1 membaca dan menulis file baru di `config/lobby/`.
Jika file tujuan baru sudah ada, migrator tidak menimpanya. Jika file tujuan baru sudah ada, migrator tidak menimpanya.
+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.3.0 mod_version=1.3.1
maven_group=id.dartokloning maven_group=id.dartokloning
archives_base_name=lobby-systems archives_base_name=lobby-systems
@@ -0,0 +1,35 @@
package id.dartokloning.lobbysystems;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.arguments.ArgumentType;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
/**
* Brigadier argument type for Minecraft resource/dimension identifiers such as
* {@code minecraft:lobby}. Vanilla Brigadier's word() does not accept ':',
* while greedyString() consumes following arguments. This parser reads exactly
* one whitespace-delimited token and therefore works correctly in the middle
* of commands such as /ls gamemode set <dimension> <mode>.
*/
public final class DimensionIdArgumentType implements ArgumentType<String> {
private DimensionIdArgumentType() {
}
public static DimensionIdArgumentType dimensionId() {
return new DimensionIdArgumentType();
}
public static String getDimensionId(CommandContext<?> context, String name) {
return context.getArgument(name, String.class);
}
@Override
public String parse(StringReader reader) throws CommandSyntaxException {
int start = reader.getCursor();
while (reader.canRead() && !Character.isWhitespace(reader.peek())) {
reader.skip();
}
return reader.getString().substring(start, reader.getCursor());
}
}
@@ -148,26 +148,26 @@ public final class LobbySystemsMod implements ModInitializer {
true, true,
true)))) true))))
.then(Commands.literal("gamerule") .then(Commands.literal("gamerule")
.then(Commands.argument("dimension", StringArgumentType.word()) .then(Commands.argument("dimension", DimensionIdArgumentType.dimensionId())
.suggests((ctx, builder) -> SharedSuggestionProvider.suggestResource( .suggests((ctx, builder) -> SharedSuggestionProvider.suggestResource(
ctx.getSource().getServer().levelKeys().stream().map(ResourceKey::identifier), builder)) ctx.getSource().getServer().levelKeys().stream().map(ResourceKey::identifier), builder))
.executes(ctx -> listGameRules( .executes(ctx -> listGameRules(
ctx.getSource(), ctx.getSource(),
ctx.getSource().getServer(), ctx.getSource().getServer(),
StringArgumentType.getString(ctx, "dimension"), DimensionIdArgumentType.getDimensionId(ctx, "dimension"),
1)) 1))
.then(Commands.literal("--page") .then(Commands.literal("--page")
.then(Commands.argument("page", IntegerArgumentType.integer(1)) .then(Commands.argument("page", IntegerArgumentType.integer(1))
.executes(ctx -> listGameRules( .executes(ctx -> listGameRules(
ctx.getSource(), ctx.getSource(),
ctx.getSource().getServer(), ctx.getSource().getServer(),
StringArgumentType.getString(ctx, "dimension"), DimensionIdArgumentType.getDimensionId(ctx, "dimension"),
IntegerArgumentType.getInteger(ctx, "page"))))))) IntegerArgumentType.getInteger(ctx, "page")))))))
.then(Commands.literal("gamemode") .then(Commands.literal("gamemode")
.then(Commands.literal("list") .then(Commands.literal("list")
.executes(ctx -> listDimensionGameModes(ctx.getSource()))) .executes(ctx -> listDimensionGameModes(ctx.getSource())))
.then(Commands.literal("set") .then(Commands.literal("set")
.then(Commands.argument("dimension", StringArgumentType.word()) .then(Commands.argument("dimension", DimensionIdArgumentType.dimensionId())
.suggests((ctx, builder) -> SharedSuggestionProvider.suggestResource( .suggests((ctx, builder) -> SharedSuggestionProvider.suggestResource(
ctx.getSource().getServer().levelKeys().stream().map(ResourceKey::identifier), builder)) ctx.getSource().getServer().levelKeys().stream().map(ResourceKey::identifier), builder))
.then(Commands.argument("mode", StringArgumentType.word()) .then(Commands.argument("mode", StringArgumentType.word())
@@ -176,21 +176,21 @@ public final class LobbySystemsMod implements ModInitializer {
.executes(ctx -> setDimensionGameMode( .executes(ctx -> setDimensionGameMode(
ctx.getSource(), ctx.getSource(),
ctx.getSource().getServer(), ctx.getSource().getServer(),
StringArgumentType.getString(ctx, "dimension"), DimensionIdArgumentType.getDimensionId(ctx, "dimension"),
StringArgumentType.getString(ctx, "mode")))))) StringArgumentType.getString(ctx, "mode"))))))
.then(Commands.literal("remove") .then(Commands.literal("remove")
.then(Commands.argument("dimension", StringArgumentType.word()) .then(Commands.argument("dimension", DimensionIdArgumentType.dimensionId())
.suggests((ctx, builder) -> SharedSuggestionProvider.suggestResource( .suggests((ctx, builder) -> SharedSuggestionProvider.suggestResource(
ctx.getSource().getServer().levelKeys().stream().map(ResourceKey::identifier), builder)) ctx.getSource().getServer().levelKeys().stream().map(ResourceKey::identifier), builder))
.executes(ctx -> removeDimensionGameMode( .executes(ctx -> removeDimensionGameMode(
ctx.getSource(), ctx.getSource(),
StringArgumentType.getString(ctx, "dimension"))))) DimensionIdArgumentType.getDimensionId(ctx, "dimension")))))
.then(Commands.argument("dimension", StringArgumentType.word()) .then(Commands.argument("dimension", DimensionIdArgumentType.dimensionId())
.suggests((ctx, builder) -> SharedSuggestionProvider.suggestResource( .suggests((ctx, builder) -> SharedSuggestionProvider.suggestResource(
ctx.getSource().getServer().levelKeys().stream().map(ResourceKey::identifier), builder)) ctx.getSource().getServer().levelKeys().stream().map(ResourceKey::identifier), builder))
.executes(ctx -> showDimensionGameMode( .executes(ctx -> showDimensionGameMode(
ctx.getSource(), ctx.getSource(),
StringArgumentType.getString(ctx, "dimension"))))) DimensionIdArgumentType.getDimensionId(ctx, "dimension")))))
.then(Commands.literal("portal") .then(Commands.literal("portal")
.then(Commands.literal("create") .then(Commands.literal("create")
.then(Commands.argument("name", StringArgumentType.word()) .then(Commands.argument("name", StringArgumentType.word())