config restructure
This commit is contained in:
@@ -62,17 +62,11 @@ public final class AuthManager {
|
||||
}
|
||||
saveRules(); // creates rules.json on first run and writes newly-added defaults
|
||||
|
||||
if (Files.exists(ConfigPaths.AUTH_ACCOUNTS)) {
|
||||
try (Reader r = Files.newBufferedReader(ConfigPaths.AUTH_ACCOUNTS)) {
|
||||
Map<String, Account> loaded = GSON.fromJson(r, new TypeToken<Map<String, Account>>(){}.getType());
|
||||
if (loaded != null) {
|
||||
accounts.clear();
|
||||
accounts.putAll(loaded);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
saveAccounts();
|
||||
}
|
||||
Map<String, Account> loadedAccounts = PlayerDataStore.loadAuth(
|
||||
new TypeToken<Map<String, Account>>(){}.getType(), new HashMap<>());
|
||||
accounts.clear();
|
||||
if (loadedAccounts != null) accounts.putAll(loadedAccounts);
|
||||
if (!Files.exists(ConfigPaths.PLAYER)) saveAccounts();
|
||||
migrateAccounts();
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
@@ -563,11 +557,8 @@ public final class AuthManager {
|
||||
}
|
||||
|
||||
private void saveAccounts() {
|
||||
try {
|
||||
Files.createDirectories(ConfigPaths.AUTH_DIRECTORY);
|
||||
try (Writer w = Files.newBufferedWriter(ConfigPaths.AUTH_ACCOUNTS)) { GSON.toJson(accounts, w); }
|
||||
} catch (Exception e) {
|
||||
LobbySystemsMod.LOGGER.error("Failed saving auth accounts", e);
|
||||
synchronized (accounts) {
|
||||
PlayerDataStore.saveAuth(accounts, new TypeToken<Map<String, Account>>(){}.getType());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,16 +7,20 @@ import java.nio.file.Path;
|
||||
public final class ConfigPaths {
|
||||
public static final Path DIRECTORY = FabricLoader.getInstance().getConfigDir().resolve("lobby");
|
||||
public static final Path CONFIG = DIRECTORY.resolve("config.json");
|
||||
public static final Path PLAYER_POSITIONS = DIRECTORY.resolve("player-positions.json");
|
||||
public static final Path PLAYER = DIRECTORY.resolve("player.json");
|
||||
public static final Path PORTALS = DIRECTORY.resolve("portals.json");
|
||||
public static final Path DIMENSION_GAMEMODES = DIRECTORY.resolve("dimension-gamemodes.json");
|
||||
public static final Path DIMENSION_GAMERULES = DIRECTORY.resolve("dimension-gamerules.json");
|
||||
public static final Path STARTER_KITS = DIRECTORY.resolve("starterkits.json");
|
||||
public static final Path STARTER_KIT_RECIPIENTS = DIRECTORY.resolve("starterkit-recipients.json");
|
||||
|
||||
public static final Path AUTH_DIRECTORY = DIRECTORY.resolve("auth");
|
||||
public static final Path AUTH_CONFIG = AUTH_DIRECTORY.resolve("config.json");
|
||||
public static final Path AUTH_ACCOUNTS = AUTH_DIRECTORY.resolve("accounts.json");
|
||||
public static final Path AUTH_RULES = AUTH_DIRECTORY.resolve("rules.json");
|
||||
|
||||
public static final Path DIMENSION_DIRECTORY = DIRECTORY.resolve("dimension");
|
||||
public static final Path DIMENSION_GAMEMODES = DIMENSION_DIRECTORY.resolve("gamemodes.json");
|
||||
public static final Path DIMENSION_GAMERULES = DIMENSION_DIRECTORY.resolve("gamerules.json");
|
||||
|
||||
public static final Path STARTER_KIT_DIRECTORY = DIRECTORY.resolve("starterkit");
|
||||
public static final Path STARTER_KITS = STARTER_KIT_DIRECTORY.resolve("list.json");
|
||||
public static final Path STARTER_KIT_RECIPIENTS = STARTER_KIT_DIRECTORY.resolve("recipients.json");
|
||||
|
||||
private ConfigPaths() {}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ import java.util.Map;
|
||||
/**
|
||||
* Persistent per-dimension gamerule overrides owned by Lobby Systems.
|
||||
*
|
||||
* Values are stored in config/lobby/dimension-gamerules.json and are applied
|
||||
* Values are stored in config/lobby/dimension/gamerules.json and are applied
|
||||
* directly to each ServerLevel's independent GameRules instance.
|
||||
*/
|
||||
public final class DimensionGameRuleManager {
|
||||
@@ -31,7 +31,7 @@ public final class DimensionGameRuleManager {
|
||||
public boolean load() {
|
||||
configured.clear();
|
||||
try {
|
||||
Files.createDirectories(ConfigPaths.DIRECTORY);
|
||||
Files.createDirectories(ConfigPaths.DIMENSION_GAMERULES.getParent());
|
||||
if (!Files.exists(ConfigPaths.DIMENSION_GAMERULES)) {
|
||||
save();
|
||||
return true;
|
||||
@@ -45,7 +45,7 @@ public final class DimensionGameRuleManager {
|
||||
|
||||
JsonElement rootElement = JsonParser.parseString(json);
|
||||
if (!rootElement.isJsonObject()) {
|
||||
LobbySystemsMod.LOGGER.error("dimension-gamerules.json root must be a JSON object");
|
||||
LobbySystemsMod.LOGGER.error("dimension/gamerules.json root must be a JSON object");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ public final class DimensionGameRuleManager {
|
||||
|
||||
public boolean save() {
|
||||
try {
|
||||
Files.createDirectories(ConfigPaths.DIRECTORY);
|
||||
Files.createDirectories(ConfigPaths.DIMENSION_GAMERULES.getParent());
|
||||
JsonObject root = new JsonObject();
|
||||
configured.entrySet().stream().sorted(Map.Entry.comparingByKey()).forEach(dimensionEntry -> {
|
||||
JsonObject rules = new JsonObject();
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
package id.dartokloning.lobbysystems;
|
||||
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
|
||||
/**
|
||||
* Satu-satunya tempat yang mengetahui nama file konfigurasi versi lama.
|
||||
* Runtime saat ini hanya membaca/menulis file di config/lobby/.
|
||||
*/
|
||||
public final class LegacyConfigMigrator {
|
||||
private LegacyConfigMigrator() {}
|
||||
|
||||
public static void migrate() {
|
||||
Path oldConfig = FabricLoader.getInstance().getConfigDir().resolve("lobby-systems.json");
|
||||
Path oldPositions = FabricLoader.getInstance().getConfigDir().resolve("lobby-systems-positions.json");
|
||||
|
||||
migrateOne(oldConfig, ConfigPaths.CONFIG, "configuration");
|
||||
migrateOne(oldPositions, ConfigPaths.PLAYER_POSITIONS, "player positions");
|
||||
}
|
||||
|
||||
private static void migrateOne(Path source, Path target, String label) {
|
||||
if (!Files.exists(source) || Files.exists(target)) return;
|
||||
try {
|
||||
Files.createDirectories(target.getParent());
|
||||
Files.move(source, target, StandardCopyOption.REPLACE_EXISTING);
|
||||
LobbySystemsMod.LOGGER.info("Migrated legacy {}: {} -> {}", label, source, target);
|
||||
LobbyLog.state("LEGACY CONFIG MIGRATED", "Type: " + label, "From: " + source, "To: " + target);
|
||||
} catch (Exception moveError) {
|
||||
try {
|
||||
Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
|
||||
LobbySystemsMod.LOGGER.info("Copied legacy {}: {} -> {}", label, source, target);
|
||||
LobbyLog.state("LEGACY CONFIG COPIED", "Type: " + label, "From: " + source, "To: " + target);
|
||||
} catch (Exception copyError) {
|
||||
LobbySystemsMod.LOGGER.error("Failed to migrate legacy {} from {} to {}", label, source, target, copyError);
|
||||
LobbyLog.state("LEGACY MIGRATION FAILED", "Type: " + label, "From: " + source, "To: " + target);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -82,8 +82,6 @@ public final class LobbySystemsMod implements ModInitializer {
|
||||
public void onInitialize() {
|
||||
LobbyLog.startup();
|
||||
|
||||
LegacyConfigMigrator.migrate();
|
||||
|
||||
boolean configLoaded = CONFIG.load();
|
||||
LobbyLog.state(
|
||||
configLoaded ? "CONFIG LOADED" : "CONFIG LOAD FAILED",
|
||||
@@ -95,7 +93,7 @@ public final class LobbySystemsMod implements ModInitializer {
|
||||
LobbyLog.state(
|
||||
authLoaded ? "AUTH SYSTEM READY" : "AUTH SYSTEM LOAD FAILED",
|
||||
"Config: " + ConfigPaths.AUTH_CONFIG,
|
||||
"Accounts: " + ConfigPaths.AUTH_ACCOUNTS,
|
||||
"Player database: " + ConfigPaths.PLAYER,
|
||||
"Rules: " + ConfigPaths.AUTH_RULES,
|
||||
"Enabled: " + AUTH.config().enabled,
|
||||
"Hybrid online-mode support: enabled"
|
||||
@@ -105,7 +103,7 @@ public final class LobbySystemsMod implements ModInitializer {
|
||||
POSITIONS.setExcludedDimension(lobbyKey());
|
||||
LobbyLog.state(
|
||||
"PLAYER POSITIONS READY",
|
||||
"File: " + ConfigPaths.PLAYER_POSITIONS,
|
||||
"File: " + ConfigPaths.PLAYER,
|
||||
"Lobby persistence: excluded"
|
||||
);
|
||||
|
||||
@@ -572,7 +570,7 @@ public final class LobbySystemsMod implements ModInitializer {
|
||||
"Portals: " + ConfigPaths.PORTALS,
|
||||
"Auth config: " + ConfigPaths.AUTH_CONFIG,
|
||||
"Auth rules: " + ConfigPaths.AUTH_RULES,
|
||||
"Auth accounts: " + ConfigPaths.AUTH_ACCOUNTS
|
||||
"Player database: " + ConfigPaths.PLAYER
|
||||
);
|
||||
|
||||
if (!CONFIG.load()) {
|
||||
@@ -596,12 +594,14 @@ public final class LobbySystemsMod implements ModInitializer {
|
||||
}
|
||||
|
||||
if (!AUTH.load()) {
|
||||
source.sendFailure(Component.literal("§eConfig utama direload, tetapi auth config/rules/accounts bermasalah. Cek console."));
|
||||
LobbyLog.state("RELOAD FAILED", "Reason: auth config/rules/accounts gagal dibaca");
|
||||
source.sendFailure(Component.literal("§eConfig utama direload, tetapi auth config/rules/player database bermasalah. Cek console."));
|
||||
LobbyLog.state("RELOAD FAILED", "Reason: auth config/rules/player database gagal dibaca");
|
||||
return 0;
|
||||
}
|
||||
AUTH.applyReload(server);
|
||||
|
||||
// player.json is shared by Auth and last-position; reload both sections.
|
||||
POSITIONS.load();
|
||||
POSITIONS.setExcludedDimension(key);
|
||||
boolean portalOk = PORTALS.load();
|
||||
if (!portalOk) {
|
||||
@@ -613,8 +613,8 @@ public final class LobbySystemsMod implements ModInitializer {
|
||||
|
||||
boolean gameModesOk = DIMENSION_GAMEMODES.load();
|
||||
if (!gameModesOk) {
|
||||
source.sendFailure(Component.literal("§eConfig utama direload, tetapi dimension-gamemodes.json bermasalah. Cek console."));
|
||||
LobbyLog.state("RELOAD FAILED", "Reason: dimension-gamemodes.json gagal dibaca");
|
||||
source.sendFailure(Component.literal("§eConfig utama direload, tetapi dimension/gamemodes.json bermasalah. Cek console."));
|
||||
LobbyLog.state("RELOAD FAILED", "Reason: dimension/gamemodes.json gagal dibaca");
|
||||
return 0;
|
||||
}
|
||||
for (String dimension : DIMENSION_GAMEMODES.all().keySet()) {
|
||||
@@ -625,16 +625,16 @@ public final class LobbySystemsMod implements ModInitializer {
|
||||
|
||||
boolean gameRulesOk = DIMENSION_GAMERULES.load();
|
||||
if (!gameRulesOk) {
|
||||
source.sendFailure(Component.literal("§eConfig utama direload, tetapi dimension-gamerules.json bermasalah. Cek console."));
|
||||
LobbyLog.state("RELOAD FAILED", "Reason: dimension-gamerules.json gagal dibaca");
|
||||
source.sendFailure(Component.literal("§eConfig utama direload, tetapi dimension/gamerules.json bermasalah. Cek console."));
|
||||
LobbyLog.state("RELOAD FAILED", "Reason: dimension/gamerules.json gagal dibaca");
|
||||
return 0;
|
||||
}
|
||||
DimensionGameRuleManager.ApplySummary gameRuleSummary = DIMENSION_GAMERULES.applyAll(server);
|
||||
|
||||
boolean starterKitsOk = STARTER_KITS.load();
|
||||
if (!starterKitsOk) {
|
||||
source.sendFailure(Component.literal("§estarterkits.json atau starterkit-recipients.json bermasalah. Cek console."));
|
||||
LobbyLog.state("RELOAD FAILED", "Reason: starter kit data gagal dibaca");
|
||||
source.sendFailure(Component.literal("§estarterkit/list.json atau starterkit/recipients.json bermasalah. Cek console."));
|
||||
LobbyLog.state("RELOAD FAILED", "Reason: starterkit/list.json atau starterkit/recipients.json gagal dibaca");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -653,6 +653,7 @@ public final class LobbySystemsMod implements ModInitializer {
|
||||
"Dimension gamemodes: " + DIMENSION_GAMEMODES.all().size() + " (authoritative)",
|
||||
"Dimension gamerules: " + DIMENSION_GAMERULES.all().size() + " dimensions / " + gameRuleSummary.applied() + " rules applied",
|
||||
"Starter kits: " + STARTER_KITS.size() + " / active dimensions: " + STARTER_KITS.activeCount(),
|
||||
"Player database: " + ConfigPaths.PLAYER,
|
||||
"Player positions lobby exclusion: active"
|
||||
);
|
||||
return 1;
|
||||
@@ -780,7 +781,7 @@ public final class LobbySystemsMod implements ModInitializer {
|
||||
String normalizedRule = rule.getIdentifierWithFallback().toString();
|
||||
String actualValue = gameRuleValueUnchecked(level, rule);
|
||||
if (!DIMENSION_GAMERULES.set(normalizedDimension, normalizedRule, actualValue)) {
|
||||
source.sendFailure(Component.literal("§cGamerule sudah diterapkan di memory, tetapi gagal menyimpan dimension-gamerules.json."));
|
||||
source.sendFailure(Component.literal("§cGamerule sudah diterapkan di memory, tetapi gagal menyimpan dimension/gamerules.json."));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -869,7 +870,7 @@ public final class LobbySystemsMod implements ModInitializer {
|
||||
String normalizedDimension = level.dimension().identifier().toString();
|
||||
String normalizedMode = rawMode.trim().toLowerCase();
|
||||
if (!DIMENSION_GAMEMODES.set(normalizedDimension, normalizedMode)) {
|
||||
source.sendFailure(Component.literal("§cGagal menyimpan dimension-gamemodes.json. Cek console."));
|
||||
source.sendFailure(Component.literal("§cGagal menyimpan dimension/gamemodes.json. Cek console."));
|
||||
return 0;
|
||||
}
|
||||
int applied = DIMENSION_GAMEMODES.applyToDimension(server, normalizedDimension);
|
||||
@@ -906,7 +907,7 @@ public final class LobbySystemsMod implements ModInitializer {
|
||||
"COMPATIBILITY WARNING",
|
||||
"Dimensional Inventories: detected",
|
||||
"Lobby Systems dimension gamemode management: authoritative / always enabled",
|
||||
"Lobby Systems will enforce dimension-gamemodes.json on join and dimension changes.",
|
||||
"Lobby Systems will enforce dimension/gamemodes.json on join and dimension changes.",
|
||||
"Keep Dimensional Inventories pool gamemodes aligned (or disable its gamemode handling) to avoid conflicting transitions."
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
package id.dartokloning.lobbysystems;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
import java.lang.reflect.Type;
|
||||
import java.nio.file.Files;
|
||||
|
||||
/**
|
||||
* Shared persistent player database. Auth and last-position data intentionally
|
||||
* live in one file while remaining separate logical sections, so either
|
||||
* subsystem can update its own data without overwriting the other.
|
||||
*/
|
||||
public final class PlayerDataStore {
|
||||
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
|
||||
private static final Object LOCK = new Object();
|
||||
private static final String AUTH = "auth";
|
||||
private static final String POSITIONS = "positions";
|
||||
|
||||
private PlayerDataStore() {}
|
||||
|
||||
public static <T> T loadAuth(Type type, T fallback) {
|
||||
return loadSection(AUTH, type, fallback);
|
||||
}
|
||||
|
||||
public static <T> T loadPositions(Type type, T fallback) {
|
||||
return loadSection(POSITIONS, type, fallback);
|
||||
}
|
||||
|
||||
public static void saveAuth(Object value, Type type) {
|
||||
saveSection(AUTH, value, type);
|
||||
}
|
||||
|
||||
public static void savePositions(Object value, Type type) {
|
||||
saveSection(POSITIONS, value, type);
|
||||
}
|
||||
|
||||
private static <T> T loadSection(String name, Type type, T fallback) {
|
||||
synchronized (LOCK) {
|
||||
try {
|
||||
JsonObject root = readRoot();
|
||||
JsonElement section = root.get(name);
|
||||
if (section == null || section.isJsonNull()) return fallback;
|
||||
T loaded = GSON.fromJson(section, type);
|
||||
return loaded == null ? fallback : loaded;
|
||||
} catch (Exception e) {
|
||||
LobbySystemsMod.LOGGER.error("Failed to load '{}' from {}", name, ConfigPaths.PLAYER, e);
|
||||
return fallback;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void saveSection(String name, Object value, Type type) {
|
||||
synchronized (LOCK) {
|
||||
try {
|
||||
JsonObject root = readRoot();
|
||||
root.add(name, GSON.toJsonTree(value, type));
|
||||
Files.createDirectories(ConfigPaths.PLAYER.getParent());
|
||||
try (Writer writer = Files.newBufferedWriter(ConfigPaths.PLAYER)) {
|
||||
GSON.toJson(root, writer);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LobbySystemsMod.LOGGER.error("Failed to save '{}' to {}", name, ConfigPaths.PLAYER, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static JsonObject readRoot() throws Exception {
|
||||
if (!Files.exists(ConfigPaths.PLAYER)) return new JsonObject();
|
||||
try (Reader reader = Files.newBufferedReader(ConfigPaths.PLAYER)) {
|
||||
JsonElement parsed = JsonParser.parseReader(reader);
|
||||
if (parsed == null || parsed.isJsonNull()) return new JsonObject();
|
||||
if (!parsed.isJsonObject()) throw new IllegalArgumentException("player.json root must be a JSON object");
|
||||
return parsed.getAsJsonObject();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,24 +1,16 @@
|
||||
package id.dartokloning.lobbysystems;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.level.Level;
|
||||
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
import java.lang.reflect.Type;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public final class PositionManager {
|
||||
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
|
||||
private static final Path PATH = ConfigPaths.PLAYER_POSITIONS;
|
||||
private static final Type DATA_TYPE = new TypeToken<Map<String, Map<String, PlayerPosition>>>() {}.getType();
|
||||
|
||||
private final Map<String, Map<String, PlayerPosition>> positions = new HashMap<>();
|
||||
@@ -28,17 +20,8 @@ public final class PositionManager {
|
||||
|
||||
public void load() {
|
||||
positions.clear();
|
||||
if (!Files.exists(PATH)) {
|
||||
save();
|
||||
return;
|
||||
}
|
||||
|
||||
try (Reader reader = Files.newBufferedReader(PATH)) {
|
||||
Map<String, Map<String, PlayerPosition>> loaded = GSON.fromJson(reader, DATA_TYPE);
|
||||
if (loaded != null) positions.putAll(loaded);
|
||||
} catch (Exception e) {
|
||||
LobbySystemsMod.LOGGER.error("Failed to load player positions from {}", PATH, e);
|
||||
}
|
||||
Map<String, Map<String, PlayerPosition>> loaded = PlayerDataStore.loadPositions(DATA_TYPE, new HashMap<>());
|
||||
if (loaded != null) positions.putAll(loaded);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,15 +73,8 @@ public final class PositionManager {
|
||||
// Guard terakhir: walaupun ada bug di caller, data lobby tidak boleh masuk file.
|
||||
purgeExcludedDimension();
|
||||
|
||||
try {
|
||||
Files.createDirectories(PATH.getParent());
|
||||
try (Writer writer = Files.newBufferedWriter(PATH)) {
|
||||
GSON.toJson(positions, DATA_TYPE, writer);
|
||||
}
|
||||
dirty = false;
|
||||
} catch (Exception e) {
|
||||
LobbySystemsMod.LOGGER.error("Failed to save player positions to {}", PATH, e);
|
||||
}
|
||||
PlayerDataStore.savePositions(positions, DATA_TYPE);
|
||||
dirty = false;
|
||||
}
|
||||
|
||||
private void store(UUID uuid, ResourceKey<Level> dimension, PlayerPosition position) {
|
||||
|
||||
@@ -225,7 +225,7 @@ public final class StarterKitManager {
|
||||
if (wasActive && !previousDimension.equals(dimension)) {
|
||||
config.activeByDimension.remove(previousDimension);
|
||||
}
|
||||
if (!saveKits()) return OperationResult.fail("Gagal menyimpan starterkits.json.");
|
||||
if (!saveKits()) return OperationResult.fail("Gagal menyimpan starterkit/list.json.");
|
||||
|
||||
String status = name.equals(config.activeByDimension.get(dimension)) ? "ACTIVE" : "INACTIVE";
|
||||
if (wasActive && !previousDimension.equals(dimension)) {
|
||||
@@ -268,7 +268,7 @@ public final class StarterKitManager {
|
||||
if (kit == null) return OperationResult.fail("Starter kit '" + name + "' tidak ditemukan.");
|
||||
String dimension = normalizeDimension(kit.dimension);
|
||||
String previous = config.activeByDimension.put(dimension, name);
|
||||
if (!saveKits()) return OperationResult.fail("Gagal menyimpan starterkits.json.");
|
||||
if (!saveKits()) return OperationResult.fail("Gagal menyimpan starterkit/list.json.");
|
||||
if (name.equals(previous)) return OperationResult.ok("Starter kit '" + name + "' sudah ACTIVE untuk " + dimension + ".");
|
||||
return OperationResult.ok("Starter kit '" + name + "' sekarang ACTIVE untuk " + dimension
|
||||
+ (previous == null ? "." : ". Kit sebelumnya: '" + previous + "' -> INACTIVE."));
|
||||
@@ -283,7 +283,7 @@ public final class StarterKitManager {
|
||||
return OperationResult.ok("Starter kit '" + name + "' sudah INACTIVE.");
|
||||
}
|
||||
config.activeByDimension.remove(dimension);
|
||||
if (!saveKits()) return OperationResult.fail("Gagal menyimpan starterkits.json.");
|
||||
if (!saveKits()) return OperationResult.fail("Gagal menyimpan starterkit/list.json.");
|
||||
return OperationResult.ok("Starter kit '" + name + "' sekarang INACTIVE. Dimension " + dimension + " tidak memiliki active starter kit.");
|
||||
}
|
||||
|
||||
@@ -294,7 +294,7 @@ public final class StarterKitManager {
|
||||
String dimension = normalizeDimension(removed.dimension);
|
||||
boolean wasActive = name.equals(config.activeByDimension.get(dimension));
|
||||
if (wasActive) config.activeByDimension.remove(dimension);
|
||||
if (!saveKits()) return OperationResult.fail("Gagal menyimpan starterkits.json.");
|
||||
if (!saveKits()) return OperationResult.fail("Gagal menyimpan starterkit/list.json.");
|
||||
return OperationResult.ok("Starter kit '" + name + "' dihapus" + (wasActive ? " dan active assignment untuk " + dimension + " dilepas." : "."));
|
||||
}
|
||||
|
||||
@@ -370,7 +370,7 @@ public final class StarterKitManager {
|
||||
return OperationResult.ok("Player belum memiliki recipient history untuk " + dimension + ".");
|
||||
}
|
||||
if (byDimension.isEmpty()) recipients.remove(uuid.toString());
|
||||
if (!saveRecipients()) return OperationResult.fail("Gagal menyimpan starterkit-recipients.json.");
|
||||
if (!saveRecipients()) return OperationResult.fail("Gagal menyimpan starterkit/recipients.json.");
|
||||
return OperationResult.ok("Recipient history untuk " + dimension + " sudah di-reset.");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user