HyCodeYourTale

Configuration

Configuration

Dokumentace ke konfiguraci pluginů a práci s BSON/JSON soubory.

Obsah

| Soubor | Popis |
|--------|-------|
| BSON_JSON.md | Práce s BSON/JSON soubory, BsonUtil API |
| CODECS.md | Codec systém pro serializaci objektů |
| CONFIG_PATTERNS.md | Běžné vzory pro konfigurace |

---

Rychlý Přehled

| Operace | Metoda |
|---------|--------|
| Async čtení | BsonUtil.readDocument(path) |
| Async zápis | BsonUtil.writeDocument(path, doc) |
| Sync čtení | BsonUtil.readDocumentNow(path) |
| BSON → JSON | BsonUtil.toJson(doc) |
| JSON → BSON | BsonDocument.parse(json) |

---

BSON Utility

Hytale používá BSON formát pro konfigurační soubory. Hlavní utility třída je BsonUtil.

Čtení Souboru

Path path = Universe.get().getPath().resolve("myconfig.json");

// Asynchronní čtení
CompletableFuture future = BsonUtil.readDocument(path);
BsonDocument document = future.join(); // Blokující čekání

if (document != null) {
// Zpracování dokumentu
String value = document.getString("key").getValue();
int number = document.getInt32("count").getValue();
}

Zápis Souboru

Path path = Universe.get().getPath().resolve("myconfig.json");

BsonDocument document = new BsonDocument();
document.put("key", new BsonString("value"));
document.put("count", new BsonInt32(42));

// Asynchronní zápis
CompletableFuture future = BsonUtil.writeDocument(path, document);
future.join(); // Počkej na dokončení

---

Příklad: Warps (z TeleportPlugin)

Načítání Warpů

public void loadWarps() {
BsonDocument document = null;
Path universePath = Universe.get().getPath();
Path oldPath = universePath.resolve("warps.bson");
Path path = universePath.resolve("warps.json");

// Migrace starého formátu
if (Files.exists(oldPath) && !Files.exists(path)) {
try {
Files.move(oldPath, path);
} catch (IOException e) {
// Ignoruj chybu
}
}

// Načti dokument
if (Files.exists(path)) {
document = BsonUtil.readDocument(path).join();
}

if (document != null) {
// Podpora obou klíčů (Warps i warps)
BsonArray bsonWarps = document.containsKey("Warps")
? document.getArray("Warps")
: document.getArray("warps");

this.warps.clear();

// Dekódování pomocí codeku
for (Warp warp : Warp.ARRAY_CODEC.decode(bsonWarps)) {
this.warps.put(warp.getId().toLowerCase(), warp);
}

getLogger().atInfo().log("Loaded %d warps", bsonWarps.size());
} else {
getLogger().atInfo().log("Loaded 0 warps (No warps.json found)");
}

this.loaded.set(true);
}

Ukládání Warpů

private void saveWarps0() {
Warp[] array = this.warps.values().toArray(Warp[]::new);

// Enkódování pomocí codeku
BsonDocument document = new BsonDocument("Warps", Warp.ARRAY_CODEC.encode(array));

Path path = Universe.get().getPath().resolve("warps.json");
BsonUtil.writeDocument(path, document).join();

getLogger().atInfo().log("Saved %d warps to warps.json", array.length);
}

// Thread-safe save s lockem
public void saveWarps() {
if (this.saveLock.tryLock()) {
try {
this.saveWarps0();
} catch (Throwable e) {
getLogger().at(Level.SEVERE).withCause(e).log("Failed to save warps:");
} finally {
this.saveLock.unlock();
}

// Pokud někdo chtěl uložit během ukládání
if (this.postSaveRedo.getAndSet(false)) {
this.saveWarps();
}
} else {
// Někdo jiný ukládá, označíme pro opakování
this.postSaveRedo.set(true);
}
}

---

Codecs

Codecs slouží k serializaci/deserializaci objektů do/z BSON.

Použití Codeku

// Enkódování objektu do BSON
BsonValue bson = MyClass.CODEC.encode(myObject);

// Dekódování z BSON
MyClass obj = MyClass.CODEC.decode(bsonValue);

// Array codec
BsonArray array = MyClass.ARRAY_CODEC.encode(objectArray);
MyClass[] objects = MyClass.ARRAY_CODEC.decode(bsonArray);

Příklad Codeku

public class Warp {
private final String id;
private final String world;
private final Transform transform;

// Codec pro serializaci
public static final Codec CODEC = ...;
public static final ArrayCodec ARRAY_CODEC = Codec.array(CODEC);

// Gettery...
}

---

Cesty k Souborům

Universe Path

// Hlavní adresář universe (server data)
Path universePath = Universe.get().getPath();

// Konfigurace pluginu
Path configPath = universePath.resolve("plugins/myplugin/config.json");

// Globální data
Path dataPath = universePath.resolve("data/mydata.json");

Plugin Data Path

// V pluginu
Path pluginDataPath = getDataFolder();
Path configPath = pluginDataPath.resolve("config.json");

---

BSON Typy

| Java Typ | BSON Typ | Příklad |
|----------|----------|---------|
| String | BsonString | new BsonString("text") |
| int | BsonInt32 | new BsonInt32(42) |
| long | BsonInt64 | new BsonInt64(1000L) |
| double | BsonDouble | new BsonDouble(3.14) |
| boolean | BsonBoolean | new BsonBoolean(true) |
| List | BsonArray | new BsonArray() |
| Map | BsonDocument | new BsonDocument() |

Práce s BsonDocument

BsonDocument doc = new BsonDocument();

// Zápis
doc.put("name", new BsonString("Test"));
doc.put("count", new BsonInt32(10));
doc.put("enabled", new BsonBoolean(true));

// Čtení
String name = doc.getString("name").getValue();
int count = doc.getInt32("count").getValue();
boolean enabled = doc.getBoolean("enabled").getValue();

// Kontrola existence klíče
if (doc.containsKey("optional")) {
// ...
}

Práce s BsonArray

BsonArray array = new BsonArray();

// Přidání prvků
array.add(new BsonString("item1"));
array.add(new BsonString("item2"));

// Iterace
for (BsonValue value : array) {
String item = value.asString().getValue();
}

// Z dokumentu
BsonArray items = doc.getArray("items");

---

Thread-Safe Konfigurace

Vzor pro Bezpečné Ukládání

public class ConfigManager {
private final ReentrantLock saveLock = new ReentrantLock();
private final AtomicBoolean pendingSave = new AtomicBoolean(false);
private final Map config = new ConcurrentHashMap<>();

public void save() {
if (saveLock.tryLock()) {
try {
doSave();
} finally {
saveLock.unlock();
}

if (pendingSave.getAndSet(false)) {
save(); // Rekurzivní volání pro čekající save
}
} else {
pendingSave.set(true);
}
}

private void doSave() {
// Async zápis
CompletableFuture.runAsync(() -> {
BsonDocument doc = serialize(config);
BsonUtil.writeDocument(configPath, doc).join();
});
}
}

---

Načítání při Startu

AllWorldsLoadedEvent

@Override
protected void setup() {
// Registruj listener pro načtení konfigurace
getEventRegistry().registerGlobal(AllWorldsLoadedEvent.class, event -> {
loadConfig();
});
}

private void loadConfig() {
Path path = Universe.get().getPath().resolve("myplugin/config.json");

if (Files.exists(path)) {
BsonDocument doc = BsonUtil.readDocument(path).join();
// Zpracování...
} else {
// Vytvoř výchozí konfiguraci
createDefaultConfig();
}
}

---

Shrnutí

| Operace | Metoda |
|---------|--------|
| Čtení | BsonUtil.readDocument(path).join() |
| Zápis | BsonUtil.writeDocument(path, doc).join() |
| Universe path | Universe.get().getPath() |
| Kontrola souboru | Files.exists(path) |
| Migrace | Files.move(oldPath, newPath) |

Last updated: 20. ledna 2026