Storage
Key/value store persistent, di-back JSON file di <config>/Seraph/storage.json. Value-nya tipe Lua yang JSON-serialisable (string, number, boolean, tabel nested) — round-trip lewat serde, jadi tabel yang disimpen balik dengan shape yang sama.
Dua global share backing store yang sama tapi pakai namespace beda:
storage— namespaced ke bot id parent client, jadi key tiap bot terisolasi. Fallback ke__noparent__buat global executor.globalStorage— namespace shared__shared__, semua bot baca/tulis bucket yang sama. Pake buat koordinasi cross-bot (flag "world_busy", round-robin assignment, dll).
Dua-duanya expose lima method yang sama.
Methods
storage:get(key)
| Field | Tipe |
|---|---|
| Signature | (self: Storage, key: string) → any? |
| Returns | any? — value yang sebelumnya disimpen, atau nil kalau key-nya belum pernah di-set (atau udah dihapus) |
| Async | no |
Number balik sebagai number, tabel balik sebagai tabel — shape-nya sama persis kayak yang disimpen.
local v = storage:get("counter")
print(v) -- 1, atau nil kalau belum pernah di-set
storage:set(key, value)
| Field | Tipe |
|---|---|
| Signature | (self: Storage, key: string, value: any) → () |
| Returns | nothing |
| Common errors | raise kalau value-nya ga JSON-serializable (misal value function) |
| Async | no |
Trigger flush storage.json langsung, jadi kalau crash di tengah script ga bakal hilang tulisannya.
storage:set("counter", (storage:get("counter") or 0) + 1)
storage:delete(key)
| Field | Tipe |
|---|---|
| Signature | (self: Storage, key: string) → boolean |
| Returns | boolean — true kalau key-nya ada (dan delete-nya beneran flush); false kalau key-nya emang udah ga ada |
| Async | no |
if storage:delete("counter") then
print("counter ke-clear")
end
storage:keys()
| Field | Tipe |
|---|---|
| Signature | (self: Storage) → {string} |
| Returns | {string} — array 1-indexed semua key di namespace ini |
| Async | no |
Urutannya itu HashMap-iteration order — jangan andelin urutannya stable.
for _, k in ipairs(storage:keys()) do
print(k, "=", storage:get(k))
end
storage:clear()
| Field | Tipe |
|---|---|
| Signature | (self: Storage) → () |
| Returns | nothing |
| Async | no |
Wipe semua key di namespace ini. Idempotent.
storage:clear()
Counter per-bot
storage:set("counter", (storage:get("counter") or 0) + 1)
print(storage:get("counter"))
Lock cross-bot
Bot pertama yang nge-claim "MYWORLD" menang, sisanya skip:
if not globalStorage:get("world_busy") then
globalStorage:set("world_busy", getClient().id)
client:warp("MYWORLD")
-- ... kerjain task
globalStorage:delete("world_busy")
end