server.world.db
Constants #
const container_slot_count = 27
container_slot_count is a chest's fixed slot count.
fn create_world_store #
fn create_world_store(worlds_dir string, name string, dim world.Dimension, generator string) !&WorldStore
create_world_store creates a fresh, empty world on disk under worlds_dir and returns its opened store. Errors if a world by that name already exists.
fn delete_world_files #
fn delete_world_files(worlds_dir string, name string) !
delete_world_files removes the on-disk folder for the named world. The caller is responsible for closing the LevelDB handle first - this only touches the filesystem. Refuses to delete anything outside worlds_dir or a world that isn't actually there.
fn discover_worlds #
fn discover_worlds(worlds_dir string) []string
discover_worlds returns the names of every subdirectory under worlds_dir that looks like a world (has a db folder).
fn load_named #
fn load_named(worlds_dir string, name string, generator_name string, dim world.Dimension) !&World
load_named opens the world stored under worlds_dir/name and pulls its overrides into memory.
fn new_stored_generator #
fn new_stored_generator(store Provider, fallback world.Generator) StoredGenerator
fn new_world #
fn new_world(name string, store ?Provider, generator_name string, dim world.Dimension) &World
fn open_leveldb #
fn open_leveldb(path string) !&LevelDB
fn open_world #
fn open_world(path string, dim world.Dimension) !&WorldStore
fn world_exists #
fn world_exists(worlds_dir string, name string) bool
world_exists reports whether a world folder with a db subdirectory is present under worlds_dir.
interface Factory #
interface Factory {
exists(name string) bool
discover() []string
mut:
create(name string, dim world.Dimension, generator string) !Provider
// open loads a persisted world, resolving its own generator/dimension
// from whatever metadata the backend keeps (falling back to
// fallback_generator/fallback_dim if it can't). Returns a fully loaded
// World, not just a raw Provider, so a caller never has to reread
// overrides a second time.
open(name string, fallback_generator string, fallback_dim world.Dimension) !&World
delete(name string) !
}
Factory creates, opens, lists and deletes named world backends. Hub only ever talks to worlds through this interface (plus the Provider/World it hands back). Swap it for something other than LevelDBFactory to back worlds with an entirely different storage mechanism.
interface Provider #
interface Provider {
dimension() world.Dimension
load_chunk(cx int, cz int) ?world.Chunk
each_block(cb fn (x int, y int, z int, runtime_id int))
each_tile(cb fn (x int, y int, z int, text string))
each_container(cb fn (x int, y int, z int, items []ContainerSlotItem))
mut:
set_block(x int, y int, z int, runtime_id int) !
set_tile_text(x int, y int, z int, text string) !
set_container_items(x int, y int, z int, items []ContainerSlotItem) !
flush() !
close() !
}
Provider is the storage backend contract a world needs, the same shape WorldStore (LevelDB) already implements, extracted so a framework user can bring their own backend instead of being stuck with LevelDB.
struct BlockOverride #
struct BlockOverride {
pub:
x int
y int
z int
id int
}
struct ContainerSlotItem #
struct ContainerSlotItem {
pub mut:
slot int
id int
meta int
count int
block_runtime_id int
raw_extra_data []u8
}
struct LevelDB #
struct LevelDB {
mut:
db &leveldb.DB
}
fn (LevelDB) put #
fn (l &LevelDB) put(key []u8, value []u8) !
put returns write failures to the caller instead of discarding them, allowing persistence code to distinguish rejected writes from success.
fn (LevelDB) get #
fn (l &LevelDB) get(key []u8) ?[]u8
fn (LevelDB) delete #
fn (l &LevelDB) delete(key []u8) !
fn (LevelDB) each #
fn (l &LevelDB) each(cb fn (key []u8, value []u8))
fn (LevelDB) flush #
fn (l &LevelDB) flush() !
flush forces pending writes down to disk without releasing the handle, so a crash after a flush cannot lose the flushed data. close() already syncs, so this is only needed for periodic mid-run durability.
fn (LevelDB) close #
fn (l &LevelDB) close() !
struct LevelDBFactory #
struct LevelDBFactory {
pub:
worlds_dir string
}
LevelDBFactory is Vedrock's own default, one LevelDB-backed folder per world under worlds_dir. It is a thin Factory shaped face over the existing manage.v/world_loader.v functions, not a reimplementation of them.
fn (LevelDBFactory) exists #
fn (f LevelDBFactory) exists(name string) bool
fn (LevelDBFactory) create #
fn (f LevelDBFactory) create(name string, dim world.Dimension, generator string) !Provider
fn (LevelDBFactory) open #
fn (f LevelDBFactory) open(name string, fallback_generator string, fallback_dim world.Dimension) !&World
fn (LevelDBFactory) discover #
fn (f LevelDBFactory) discover() []string
fn (LevelDBFactory) delete #
fn (f LevelDBFactory) delete(name string) !
struct ScheduledEntry #
struct ScheduledEntry {
pub:
x int
y int
z int
due i64
}
ScheduledEntry represents one pending scheduled tick for a block position. It becomes due when current_tick reaches due.
Multiple entries may be queued for the same position; scheduled ticks are not deduplicated.
struct StoredGenerator #
struct StoredGenerator {
store Provider
fallback world.Generator
cache &ChunkCache
}
fn (StoredGenerator) spawn_y #
fn (g StoredGenerator) spawn_y() int
fn (StoredGenerator) uses_blocks #
fn (g StoredGenerator) uses_blocks() bool
fn (StoredGenerator) generate #
fn (g StoredGenerator) generate(chunk_x int, chunk_z int) world.Chunk
fn (StoredGenerator) block_at #
fn (g StoredGenerator) block_at(x int, y int, z int) int
fn (StoredGenerator) biome_at #
fn (g StoredGenerator) biome_at(x int, z int) int
struct TickPosition #
struct TickPosition {
pub:
x int
y int
z int
}
struct TileData #
struct TileData {
pub mut:
text string
}
TileData is a block-entity's persistent data at a position.
struct TileEntry #
struct TileEntry {
pub:
x int
y int
z int
text string
}
TileEntry is a TileData paired with its position, returned by tile_entries_in_chunk for chunk-send enrichment.
struct World #
struct World {
pub:
name string
dimension world.Dimension = world.overworld
mut:
store ?Provider
overrides map[string]int
tile_data map[string]TileData
container_data map[string][]ContainerSlotItem
open_holders map[string]u64
mutex &sync.Mutex = sync.new_mutex()
current_tick i64
scheduled []ScheduledEntry
last_persist_error ?string
// Persistence worker state, only meaningful when store_backed is true.
// A storeless World (tests, void worlds) never starts this thread and
// must never touch these fields.
store_backed bool
persist_mutex &sync.Mutex = sync.new_mutex()
persist_records []QueuedPersistRecord
// persist_head points to the first pending persistence record.
// Records before it have already been applied and are compacted
// periodically, avoiding repeated front deletions from the queue.
persist_head int
persist_wakeup chan bool = chan bool{cap: 1}
persist_stop chan bool = chan bool{cap: 1}
persist_done chan bool = chan bool{cap: 1}
// Monotonic persistence totals used to measure enqueue and commit rates.
persist_enqueued_count &stdatomic.AtomicVal[i64] = stdatomic.new_atomic[i64](0)
persist_committed_count &stdatomic.AtomicVal[i64] = stdatomic.new_atomic[i64](0)
// Provider write latency and error state metrics.
// consecutive_errors resets after the next successful write.
persist_last_write_ns &stdatomic.AtomicVal[i64] = stdatomic.new_atomic[i64](0)
persist_longest_write_ns &stdatomic.AtomicVal[i64] = stdatomic.new_atomic[i64](0)
persist_consecutive_errors &stdatomic.AtomicVal[i64] = stdatomic.new_atomic[i64](0)
// Persistence backlog thresholds. Tests may override these values.
persist_high_water_threshold int = persist_high_water_count
persist_hard_ceiling_threshold int = persist_hard_ceiling_count
// Timeout used while waiting for persistence shutdown to complete.
persist_shutdown_timeout_value time.Duration = persist_shutdown_timeout
// closing and closed make close() idempotent. closing prevents duplicate
// stop signals while shutdown is still in progress; closed is set only
// after the underlying store closes successfully.
closing bool
closed bool
pub mut:
generator_name string
}
World is a single loaded world, its persistent store plus the in memory cache of block overrides layered on top of the generated/vanilla chunks.
World writes become visible in memory immediately and reach disk asynchronously. flush and close wait until all previously queued writes have been persisted.
fn (World) block_count #
fn (w &World) block_count() int
fn (World) block_id #
fn (w &World) block_id(x int, y int, z int) int
block_id returns the block at the given position. It first checks for an in memory override, then falls back to the world's configured generator.
This matches the override first lookup used by session.block_at().
fn (World) block_override #
fn (w &World) block_override(x int, y int, z int) ?int
fn (World) clear_container #
fn (mut w World) clear_container(x int, y int, z int)
clear_container empties a container's contents (e.g. after its block is broken and its items have already been dropped into the world).
fn (World) close #
fn (mut w World) close() !
close waits for all queued persistence work to finish, stops the storage worker and then closes the underlying store.
The operation is idempotent. If a previous close attempt timed out, a retry waits for the existing shutdown to complete instead of sending a second stop signal.
fn (World) container_items #
fn (w &World) container_items(x int, y int, z int) []ContainerSlotItem
fn (World) container_slots #
fn (w &World) container_slots(x int, y int, z int) []types.ItemStack
container_slots resolves a container's contents into slot-indexed ItemStacks, empty ItemStack{} for any slot with nothing stored.
fn (World) due_scheduled_entries #
fn (mut w World) due_scheduled_entries(current i64, max int) []ScheduledEntry
due_scheduled_entries removes and returns up to max entries due at or before current. Additional due entries remain queued, bounding catchup work after stalls and preventing one tick from processing an unbounded backlog.
fn (World) flush #
fn (mut w World) flush() !
flush persists this world's store to disk without unloading it, waiting for every write already handed to the storage worker before this call to actually be applied first. So this reflects everything mutated up to the moment it was called.. Safe to call while the world is live. It doesn't touch the in memory override cache.
fn (World) is_persistent #
fn (w &World) is_persistent() bool
is_persistent reports whether the world is backed by on disk storage. Ephemeral in memory worlds have nothing to load or save, so external persistence tied to the world should only run when this returns true.
fn (World) last_persist_error #
fn (w &World) last_persist_error() ?string
fn (World) last_persist_write_duration #
fn (w &World) last_persist_write_duration() time.Duration
last_persist_write_duration returns the duration of the most recent provider write. Barrier signals are not included.
fn (World) load #
fn (mut w World) load()
load pulls every persisted block override and tile data entry into the in memory cache.
fn (World) longest_persist_write_duration #
fn (w &World) longest_persist_write_duration() time.Duration
fn (World) make_generator #
fn (w &World) make_generator(fallback world.Generator) world.Generator
make_generator wraps the given fallback with a StoredGenerator when this world has a backing store, so saved chunks are served before the fallback.
fn (World) oldest_pending_persist_age #
fn (w &World) oldest_pending_persist_age() time.Duration
oldest_pending_persist_age returns how long the oldest pending persistence record has been waiting. It returns zero when no records are pending.
fn (World) override_positions #
fn (w &World) override_positions() []TickPosition
override_positions returns the positions of all currently overridden blocks. Callers can use the snapshot to perform their own random tick selection.
fn (World) overrides_in_chunk #
fn (w &World) overrides_in_chunk(cx int, cz int) []BlockOverride
fn (World) pending_persist_count #
fn (w &World) pending_persist_count() int
pending_persist_count returns the number of persistence records waiting for the storage worker. It is safe to call from any thread.
fn (World) persist_committed_total #
fn (w &World) persist_committed_total() i64
persist_committed_total returns the total number of persistence records applied since this world started including writes and barriers.
fn (World) persist_consecutive_errors #
fn (w &World) persist_consecutive_errors() i64
persist_consecutive_errors returns the number of consecutive provider write failures since the last successful write.
fn (World) persist_enqueued_total #
fn (w &World) persist_enqueued_total() i64
persist_enqueued_total returns the total number of persistence records enqueued since this world started including writes and barriers.
fn (World) persist_hard_ceiling_threshold_value #
fn (w &World) persist_hard_ceiling_threshold_value() int
fn (World) persist_high_water_threshold_value #
fn (w &World) persist_high_water_threshold_value() int
persist_high_water_threshold_value and persist_hard_ceiling_threshold_value expose the configured overload policy thresholds for metrics/reporting.
fn (World) persist_pressure_level #
fn (w &World) persist_pressure_level() int
persist_pressure_level classifies the current persistence backlog: 0 is normal, 1 is at or above the high-water mark and 2 is at or above the hard ceiling where new persistence enqueues are subject to backpressure.
fn (World) release_container_hold #
fn (mut w World) release_container_hold(x int, y int, z int, runtime_id u64)
fn (World) schedule_tick #
fn (mut w World) schedule_tick(x int, y int, z int, delay int)
schedule_tick queues one scheduled tick for the given position. ScheduledTicker.scheduled_tick callback runs after delay game ticks.
fn (World) scheduled_backlog_count #
fn (w &World) scheduled_backlog_count() int
scheduled_backlog_count reports how many scheduled tick entries are currently queued, for runtime metrics. Safe to call from any thread.
fn (World) set_block #
fn (mut w World) set_block(x int, y int, z int, runtime_id int)
set_block updates the in memory override immediately, under mutex, then hands the actual disk write to the storage worker rather than performing it here. Callers see the new value right away regardless of disk speed; see the World comment above for exactly what that trades away.
fn (World) set_container_items #
fn (mut w World) set_container_items(x int, y int, z int, items []ContainerSlotItem)
set_container_items updates a container's in memory contents immediately, under mutex, then hands the actual disk write to the storage worker.
fn (World) set_container_slot #
fn (mut w World) set_container_slot(x int, y int, z int, slot int, stack types.ItemStack)
fn (World) set_persist_shutdown_timeout #
fn (mut w World) set_persist_shutdown_timeout(d time.Duration)
fn (World) set_tile_text #
fn (mut w World) set_tile_text(x int, y int, z int, text string)
set_tile_text updates the in memory tile data immediately, under mutex, then hands the actual disk write to the storage worker. The same split set_block uses, and for the same reason.
fn (World) tick #
fn (mut w World) tick(registry &block.Registry) []BlockOverride
tick advances this world by one game tick: fires every scheduled entry whose delay has elapsed, then rolls the random tick chance (see block.random_tick_speed) for every currently overridden block position. Only overridden positions are considered.
Returns the positions changed by either pass. World has no session/network knowledge, so broadcasting these to connected players is the caller's responsibility.
fn (World) tile_entries_in_chunk #
fn (w &World) tile_entries_in_chunk(cx int, cz int) []TileEntry
fn (World) tile_text #
fn (w &World) tile_text(x int, y int, z int) ?string
fn (World) try_hold_container #
fn (mut w World) try_hold_container(x int, y int, z int, runtime_id u64) bool
try_hold_container claims a container position for one session at a time.
struct WorldStore #
struct WorldStore {
db &LevelDB
overrides &LevelDB
dimension world.Dimension = world.overworld
}
fn (WorldStore) close #
fn (w &WorldStore) close() !
fn (WorldStore) dimension #
fn (w &WorldStore) dimension() world.Dimension
fn (WorldStore) each_block #
fn (w &WorldStore) each_block(cb fn (x int, y int, z int, runtime_id int))
fn (WorldStore) each_container #
fn (w &WorldStore) each_container(cb fn (x int, y int, z int, items []ContainerSlotItem))
fn (WorldStore) each_tile #
fn (w &WorldStore) each_tile(cb fn (x int, y int, z int, text string))
fn (WorldStore) flush #
fn (w &WorldStore) flush() !
flush persists both backing databases without closing them. Both are always attempted even if the first fails, so one handle's failure never leaves the other silently unflushed; the first error encountered, if any, is what's returned.
fn (WorldStore) load_chunk #
fn (w &WorldStore) load_chunk(cx int, cz int) ?world.Chunk
fn (WorldStore) set_block #
fn (w &WorldStore) set_block(x int, y int, z int, runtime_id int) !
fn (WorldStore) set_container_items #
fn (w &WorldStore) set_container_items(x int, y int, z int, items []ContainerSlotItem) !
set_container_items persists a container's contents.
fn (WorldStore) set_tile_text #
fn (w &WorldStore) set_tile_text(x int, y int, z int, text string) !
set_tile_text persists a block-entity's tex at a position, sharing the overrides handle with a distinct key prefix rather than opening a third LevelDB handle for no isolation benefit.
- Constants
- fn create_world_store
- fn delete_world_files
- fn discover_worlds
- fn load_named
- fn new_stored_generator
- fn new_world
- fn open_leveldb
- fn open_world
- fn world_exists
- interface Factory
- interface Provider
- struct BlockOverride
- struct ContainerSlotItem
- struct LevelDB
- struct LevelDBFactory
- struct ScheduledEntry
- struct StoredGenerator
- struct TickPosition
- struct TileData
- struct TileEntry
- struct World
- fn block_count
- fn block_id
- fn block_override
- fn clear_container
- fn close
- fn container_items
- fn container_slots
- fn due_scheduled_entries
- fn flush
- fn is_persistent
- fn last_persist_error
- fn last_persist_write_duration
- fn load
- fn longest_persist_write_duration
- fn make_generator
- fn oldest_pending_persist_age
- fn override_positions
- fn overrides_in_chunk
- fn pending_persist_count
- fn persist_committed_total
- fn persist_consecutive_errors
- fn persist_enqueued_total
- fn persist_hard_ceiling_threshold_value
- fn persist_high_water_threshold_value
- fn persist_pressure_level
- fn release_container_hold
- fn schedule_tick
- fn scheduled_backlog_count
- fn set_block
- fn set_container_items
- fn set_container_slot
- fn set_persist_shutdown_timeout
- fn set_tile_text
- fn tick
- fn tile_entries_in_chunk
- fn tile_text
- fn try_hold_container
- struct WorldStore