server
Constants #
const ticks_per_second = 20
const day_length_ticks = 24000
fn new #
fn new(opts Options) !&Server
new builds a Server from opts. Every field of opts is optional - new() (or new(settings: my_config)) boots a fully working default server the same way new_hub(data) does one level down. The only propagated failure is a genuinely fatal one (no language could be loaded at all, not even the "en" fallback); everything else that can degrade gracefully (missing ops file, missing block palette, a world that fails to load) logs a warning and continues, matching the resilience the previous shape already had.
struct Options #
struct Options {
pub:
settings conf.Config
hub_options session.HubOptions
}
Options is the framework's composition-root entry point. settings carries YAML-loadable server tuning; hub_options swaps Hub subsystems such as the command and entity registries. Every field left unset falls back to Vedrock's built-in default, so new() with no arguments still boots a working server.
struct Server #
struct Server {
mut:
hub &session.Hub = unsafe { nil }
// signaling is the LAN discovery channel: the same socket advertises the
// world and carries the offers and answers that negotiate a connection.
signaling &discovery.Listener = unsafe { nil }
listener &nethernet.Listener = unsafe { nil }
// endpoint is the address join channel: a client given this server's
// address asks it over HTTP instead of broadcasting for it.
endpoint &endpoint.EndpointHandler = unsafe { nil }
endpoint_listener &nethernet.Listener = unsafe { nil }
guid i64
running &stdatomic.AtomicVal[bool] = stdatomic.new_atomic[bool](false)
// active_conns bounds concurrent connection handlers so a flood of
// half-open/pre-login peers can't exhaust threads and CPU.
active_conns &stdatomic.AtomicVal[u64] = stdatomic.new_atomic[u64](0)
created_at time.Time
pub mut:
log &logger.Logger
lang &language.Lang
cfg conf.Config
}
Server is the running instance returned by new(). Its hub remains private.
Optional extension layers such as plugins may build on this public API; Server doesn't wire them in directly.
fn (Server) start #
fn (mut s Server) start() !
fn (Server) stop #
fn (mut s Server) stop()
stop disconnects every session and waits for each one to finish leaving including player data saves, before shutting down worlds or the listener. It returns only after all players have fully disconnected.
fn (Server) register_event #
fn (mut s Server) register_event(handler event.Handler, priority event.Priority)
register_event adds handler to the server's global event bus.
fn (Server) unregister_event #
fn (mut s Server) unregister_event(handler event.Handler)
unregister_event removes handler from the global event bus.
fn (Server) register_command #
fn (mut s Server) register_command(command cmd.Command)
register_command adds command to the server's command registry.
fn (Server) unregister_command #
fn (mut s Server) unregister_command(name string)
unregister_command removes a previously registered command.
fn (Server) run_task #
fn (mut s Server) run_task(task scheduler.Task) &scheduler.TaskHandler
run_task schedules task to run on the server's global tick thread on the next tick. Tasks must remain short, non blocking and world independent.
fn (Server) run_delayed #
fn (mut s Server) run_delayed(task scheduler.Task, delay i64) &scheduler.TaskHandler
run_delayed queues task to run once, delay ticks from now.
fn (Server) run_repeating #
fn (mut s Server) run_repeating(task scheduler.Task, period i64) &scheduler.TaskHandler
run_repeating queues task to run every period ticks, starting next tick.
fn (Server) cancel_task #
fn (mut s Server) cancel_task(id int)
See: hub.cancel_task
fn (Server) load_world #
fn (mut s Server) load_world(config WorldConfig) !session.World
load_world returns the loaded world, loading it from storage or creating it when necessary. Repeated calls for the same world return the existing handle.
The underlying world lifecycle remains owned by Hub.
fn (Server) world #
fn (mut s Server) world(name string) ?session.World
world returns the named world's public handle, or none if it's not currently loaded. Use load_world to load or create a world on demand.
fn (Server) worlds #
fn (mut s Server) worlds() []session.World
worlds returns a handle for every currently loaded world.
fn (Server) unload_world #
fn (mut s Server) unload_world(name string) !
unload_world stops and releases a loaded world without deleting its stored data. It refuses to unload the default world or a world that still contains players; callers must move or disconnect them first.
fn (Server) register_generator #
fn (mut s Server) register_generator(name string, factory fn (dim world.Dimension) world.Generator)
fn (Server) player #
fn (mut s Server) player(name string) ?session.PlayerRef
player returns the currently connected player with the given name or none if no such player is connected. The returned PlayerRef is stale checked and may be safely held for later use.
fn (Server) players #
fn (mut s Server) players() []session.PlayerRef
players returns a PlayerRef for every player currently connected to the server across all loaded worlds. It doesn't require a world actor round trip.
fn (Server) player_count #
fn (mut s Server) player_count() int
player_count returns how many players are currently connected.
struct WorldConfig #
struct WorldConfig {
pub:
name string
dimension world.Dimension = world.overworld
generator_name string
}
WorldConfig is what load_world needs to bring a world up: its name, dimension and which registered generator to use.
dimension/generator_name only matter the first time this name is created on disk. Reopening an existing world just reuses whatever generator/dimension it was saved with.
To use a custom generator, register it with Server.register_generator first, then reference it by name here.