Skip to content

server.session

Constants #

const players_dir = 'players'
const player_eye_height = f32(1.62)
const player_half_width = f32(0.3)
const player_height = f32(1.8)

fn new #

fn new(mut transport network.Session, mut hub Hub, cfg conf.Config, log &logger.Logger) &NetworkSession

fn new_console_sender #

fn new_console_sender(mut hub Hub, log &logger.Logger) &ConsoleSender

fn new_hub #

fn new_hub(data gamedata.GameData) &Hub

fn State.from #

fn State.from[W](input W) !State

interface WorldJob #

interface WorldJob {
	run(mut h Hub)
}

enum State #

enum State {
	handshake
	login
	resource_packs
	play
	closed
}

struct ConsoleSender #

@[heap]
struct ConsoleSender {
mut:
	hub &Hub
pub mut:
	log &logger.Logger = unsafe { nil }
}

ConsoleSender adapts the server console to the cmd.Sender interface. It has every permission and writes command output to the server log.

fn (ConsoleSender) broadcast_message #

fn (mut c ConsoleSender) broadcast_message(text string)

fn (ConsoleSender) broadcast_title #

fn (mut c ConsoleSender) broadcast_title(kind int, text string)

fn (ConsoleSender) clear_inventory #

fn (mut c ConsoleSender) clear_inventory()

fn (ConsoleSender) clear_scoreboard #

fn (mut c ConsoleSender) clear_scoreboard()

fn (ConsoleSender) find_player #

fn (mut c ConsoleSender) find_player(name string) ?cmd.Sender

fn (ConsoleSender) give_item #

fn (mut c ConsoleSender) give_item(id string, count int) bool

fn (ConsoleSender) has_permission #

fn (c &ConsoleSender) has_permission(name string) bool

fn (ConsoleSender) is_player #

fn (c &ConsoleSender) is_player() bool

fn (ConsoleSender) kill #

fn (mut c ConsoleSender) kill()

fn (ConsoleSender) name #

fn (c &ConsoleSender) name() string

fn (ConsoleSender) place_water #

fn (mut c ConsoleSender) place_water(x int, y int, z int)

fn (ConsoleSender) position #

fn (mut c ConsoleSender) position() (f32, f32, f32)

fn (ConsoleSender) send_form #

fn (mut c ConsoleSender) send_form(f form.Form) !

fn (ConsoleSender) send_message #

fn (mut c ConsoleSender) send_message(message string) !

fn (ConsoleSender) send_translation #

fn (mut c ConsoleSender) send_translation(key string, parameters []string) !

fn (ConsoleSender) set_difficulty #

fn (mut c ConsoleSender) set_difficulty(value int)

fn (ConsoleSender) set_gamemode #

fn (mut c ConsoleSender) set_gamemode(mode int)

fn (ConsoleSender) set_operator #

fn (mut c ConsoleSender) set_operator(value bool)

The console itself is never a valid target for these (find_player never resolves to a ConsoleSender) but every Sender must implement the full interface.

fn (ConsoleSender) show_scoreboard #

fn (mut c ConsoleSender) show_scoreboard(title string, lines []string)

fn (ConsoleSender) show_title #

fn (mut c ConsoleSender) show_title(kind int, text string)

fn (ConsoleSender) teleport #

fn (mut c ConsoleSender) teleport(x f32, y f32, z f32)

fn (ConsoleSender) whitelist_add #

fn (mut c ConsoleSender) whitelist_add(name string)

fn (ConsoleSender) whitelist_enabled #

fn (c &ConsoleSender) whitelist_enabled() bool

fn (ConsoleSender) whitelist_names #

fn (c &ConsoleSender) whitelist_names() []string

fn (ConsoleSender) whitelist_remove #

fn (mut c ConsoleSender) whitelist_remove(name string)

fn (ConsoleSender) whitelist_set_enabled #

fn (mut c ConsoleSender) whitelist_set_enabled(value bool)

fn (ConsoleSender) world_create #

fn (mut c ConsoleSender) world_create(name string, dimension string, generator string) !

fn (ConsoleSender) world_delete #

fn (mut c ConsoleSender) world_delete(name string) !

fn (ConsoleSender) world_info #

fn (mut c ConsoleSender) world_info(name string) ?cmd.WorldSummary

fn (ConsoleSender) world_load #

fn (mut c ConsoleSender) world_load(name string) !

fn (ConsoleSender) world_names #

fn (mut c ConsoleSender) world_names() []string

fn (ConsoleSender) world_teleport #

fn (mut c ConsoleSender) world_teleport(name string) !

struct Hub #

@[heap]
struct Hub {
mut:
	sessions        map[u64]&NetworkSession
	mutex           &sync.Mutex = sync.new_mutex()
	next_runtime_id u64         = 1
	// jobs is the only door into gameplay-mutable state that spans sessions
	// (combat, targeted /gamemode, etc.). run_jobs() is the sole consumer.
	jobs         chan WorldJob             = chan WorldJob{cap: 256}
	tps_bits     &stdatomic.AtomicVal[u64] = stdatomic.new_atomic[u64](math.f64_bits(20.0))
	load_bits    &stdatomic.AtomicVal[u64] = stdatomic.new_atomic[u64](0)
	online_count &stdatomic.AtomicVal[u64] = stdatomic.new_atomic[u64](0)
pub mut:
	world_time         int
	data               gamedata.GameData
	items              item.Registry                = item.new_registry()
	blocks             block.Registry               = block.new_registry()
	lang               &language.Lang               = unsafe { nil }
	commands           cmd.Registry                 = cmd.new_registry()
	events             &event.Bus                   = unsafe { nil }
	scheduler          &scheduler.Scheduler         = unsafe { nil }
	entities           &entity.Manager              = unsafe { nil }
	liquids            &liquid.LiquidManager        = unsafe { nil }
	entity_registry    entity.Registry              = entity.new_registry()
	custom_items       item.CustomRegistry          = item.new_custom_registry()
	custom_blocks      block.CustomRegistry         = block.new_custom_registry()
	custom_entities    entity.CustomRegistry        = entity.new_custom_registry()
	enchantments       enchant.Registry             = enchant.new_registry()
	generators         blockworld.GeneratorRegistry = blockworld.new_generator_registry()
	current_tick       i64
	started_at         i64
	worlds             map[string]&db.World
	default_world_name string
	// worlds_dir is the on-disk root for world folders and world_generator the
	// fallback generator name for freshly created worlds. Both are set at boot.
	worlds_dir      string                   = 'worlds'
	world_generator string                   = 'flat'
	packs           &resource.PackRegistry   = unsafe { nil }
	palette         &blockworld.BlockPalette = unsafe { nil }
	ops             permission.OpList
	player_grants   permission.PlayerGrants
	whitelist       permission.Whitelist
	// needs vedrock.yml storage.
	difficulty int = protocol.difficulty_easy
}

fn (Hub) add #

fn (mut h Hub) add(target &NetworkSession)

fn (Hub) add_world #

fn (mut h Hub) add_world(loaded_world &db.World)

add_world registers a loaded world under its name. The first world added becomes the default unless one is already set.

fn (Hub) allocate_runtime_id #

fn (mut h Hub) allocate_runtime_id() u64

fn (Hub) broadcast #

fn (mut h Hub) broadcast(p protocol.Packet)

fn (Hub) broadcast_except #

fn (mut h Hub) broadcast_except(runtime_id u64, p protocol.Packet)

fn (Hub) broadcast_message #

fn (mut h Hub) broadcast_message(text string)

broadcast_message sends a raw chat line to every connected player. Part of the plugin.ServerView surface.

fn (Hub) broadcast_near #

fn (mut h Hub) broadcast_near(x f32, y f32, z f32, radius f32, p protocol.Packet)

broadcast_near delivers p only to players whose position is within radius of the point (x, y, z). Used by the entity Manager for view-distance culling so spawn and move packets never reach players too far away to render the entity. Distance is compared squared to skip the sqrt.

fn (Hub) build_generator #

fn (h &Hub) build_generator(w &db.World) blockworld.Generator

build_generator resolves a world's own generator by name and dimension through the registry.

fn (Hub) capture_area #

fn (mut h Hub) capture_area(x1 int, y1 int, z1 int, x2 int, y2 int, z2 int) ?&arena.Snapshot

capture_area snapshots the block ids over the box between the two corners in the default world. See arena.max_volume for the size cap.

fn (Hub) close_worlds #

fn (mut h Hub) close_worlds()

close_worlds flushes and releases every loaded world's LevelDB handles. Called once on shutdown after all sessions are disconnected.

fn (Hub) collision_boxes #

fn (mut h Hub) collision_boxes(x int, y int, z int) []world.AABB

fn (Hub) count #

fn (mut h Hub) count() int

fn (Hub) create_world #

fn (mut h Hub) create_world(name string, dim blockworld.Dimension, generator string) !string

create_world creates a fresh empty world on disk and registers it as loaded. Refuses to clobber an already-loaded or already-on-disk world. Safe to call off the actor thread - it only adds to the worlds map, never mutates a player's active world.

fn (Hub) custom_block_names #

fn (mut h Hub) custom_block_names() []string

fn (Hub) custom_entity_names #

fn (mut h Hub) custom_entity_names() []string

fn (Hub) custom_item_names #

fn (mut h Hub) custom_item_names() []string

fn (Hub) default_world #

fn (mut h Hub) default_world() ?&db.World

default_world returns the world new players spawn into, or none when no world could be loaded.

fn (Hub) delete_world #

fn (mut h Hub) delete_world(name string) !

delete_world unloads the named world and removes its on-disk folder. Refuses the default world and any world that still has players in it. The LevelDB handle is always closed before the files are touched.

fn (Hub) disconnect_all #

fn (mut h Hub) disconnect_all(message string)

fn (Hub) entity_type_names #

fn (mut h Hub) entity_type_names() []string

entity_type_names lists every summonable entity type.

fn (Hub) generator_type_names #

fn (mut h Hub) generator_type_names() []string

generator_type_names lists every registered generator name. Part of the plugin.ServerView surface.

fn (Hub) get_block #

fn (mut h Hub) get_block(x int, y int, z int) int

get_block returns the block network id at a position in the default world, preferring a saved override and otherwise falling back to the generator so untouched terrain reads correctly.

fn (Hub) list_worlds #

fn (mut h Hub) list_worlds() []string

list_worlds returns the names of every loaded world.

fn (Hub) load #

fn (mut h Hub) load() f64

fn (Hub) load_world #

fn (mut h Hub) load_world(name string) !string

fn (Hub) next_enchantment_id #

fn (mut h Hub) next_enchantment_id() int

next_enchantment_id returns the next free id in the custom enchantment range.

fn (Hub) on_block_changed #

fn (mut h Hub) on_block_changed(x int, y int, z int)

on_block_changed notifies the liquid manager that a block edit happened so nearby water re-evaluates its flow. Cheap and non-blocking - dropped under a full actor queue since the periodic liquid tick will catch up anyway.

fn (Hub) online_count #

fn (mut h Hub) online_count() int

online_count is the plugin.ServerView alias for count().

fn (Hub) place_water #

fn (mut h Hub) place_water(x int, y int, z int)

place_water sets a water source at the position and enqueues the spread. The write and every spread step run on the actor thread via the liquid tick.

fn (Hub) player_names #

fn (mut h Hub) player_names() []string

player_names lists the display names of every connected player. Part of the plugin.ServerView surface.

fn (Hub) players_in_world #

fn (mut h Hub) players_in_world(name string) int

players_in_world counts the connected players whose active world matches name.

fn (Hub) register_custom_block #

fn (mut h Hub) register_custom_block(def block.CustomBlockDefinition) int

register_custom_block registers a data-driven block definition, allocates its runtime id and adds a matching block class so gameplay lookups (hardness, identifiers) work server-side.

fn (Hub) register_custom_entity #

fn (mut h Hub) register_custom_entity(def entity.CustomEntityDefinition, factory entity.BehaviourFactory) bool

register_custom_entity registers a custom entity type: the definition goes into the AvailableActorIdentifiers list and the factory into the entity registry under the definition's short name, so /summon and spawn_entity work with it.

fn (Hub) register_custom_item #

fn (mut h Hub) register_custom_item(def item.CustomItemDefinition) int

register_custom_item registers a data-driven item definition, allocates its runtime id and exposes it to the item class registry and the numeric id lookup so inventories and creative content resolve it like a vanilla item.

fn (Hub) register_enchantment #

fn (mut h Hub) register_enchantment(e enchant.Enchantment) bool

register_enchantment adds an enchantment to the shared registry, returning false when its id or name is already taken.

fn (Hub) register_generator #

fn (mut h Hub) register_generator(name string, factory fn (dim blockworld.Dimension) blockworld.Generator)

register_generator adds or overrides a named world generator. Part of the plugin.ServerView surface.

fn (Hub) remove #

fn (mut h Hub) remove(runtime_id u64)

fn (Hub) restore_area #

fn (mut h Hub) restore_area(snapshot &arena.Snapshot)

restore_area writes a snapshot back through the block write path so viewers see the arena reset.

fn (Hub) session_by_name #

fn (mut h Hub) session_by_name(name string) ?&NetworkSession

fn (Hub) session_by_runtime #

fn (mut h Hub) session_by_runtime(runtime_id u64) ?&NetworkSession

fn (Hub) set_block #

fn (mut h Hub) set_block(name string, x int, y int, z int) bool

set_block sets a block by namespaced id in the default world and broadcasts the change. Returns false if name isn't a known block. The name is resolved synchronously; the write itself is routed through the actor thread.

fn (Hub) set_block_id #

fn (mut h Hub) set_block_id(id int, x int, y int, z int)

set_block_id writes a raw block network id, used by arena restore. It routes through the same actor-thread write path as set_block.

fn (Hub) set_default_world #

fn (mut h Hub) set_default_world(name string)

fn (Hub) set_world_config #

fn (mut h Hub) set_world_config(worlds_dir string, generator string)

set_world_config records where worlds live on disk and the default generator used for worlds created at runtime. Called once at boot from load_worlds.

fn (Hub) spawn_entity #

fn (mut h Hub) spawn_entity(name string, x f32, y f32, z f32) bool

spawn_entity spawns a registered entity type by name at the given position. Returns false if the type is unknown. Part of the plugin.ServerView surface.

fn (Hub) submit #

fn (mut h Hub) submit(job WorldJob)

submit queues a WorldJob for run_jobs() to execute. Blocks if the queue is full.

fn (Hub) tps #

fn (mut h Hub) tps() f64

fn (Hub) try_submit #

fn (mut h Hub) try_submit(job WorldJob) bool

try_submit queues a job without blocking, returning false if the actor queue is full. Used for high-frequency, client- or plugin-driven jobs (attacks, respawns, block edits) so a flood of them can never back up connection threads or stall the tick loop - the excess job is simply dropped.

fn (Hub) unload_world #

fn (mut h Hub) unload_world(name string) !

unload_world flushes and releases a loaded world without deleting its files. Refuses the default world and any world that still has players in it.

fn (Hub) uptime_seconds #

fn (h &Hub) uptime_seconds() i64

fn (Hub) world #

fn (mut h Hub) world(name string) ?&db.World

fn (Hub) world_count #

fn (mut h Hub) world_count() int

fn (Hub) world_info #

fn (mut h Hub) world_info(name string) ?WorldInfo

world_info gathers a snapshot for the named world, or none when it isn't loaded.

struct NetworkSession #

@[heap]
struct NetworkSession {
mut:
	transport &network.Session = unsafe { nil }
	hub       &Hub             = unsafe { nil }
	state     State            = .handshake
	cfg       conf.Config
	world     &db.World       = unsafe { nil }
	generator world.Generator = world.VoidGenerator{}
	// world_mutex guards world and generator - both are swapped from the Hub
	// job thread on a world change while the session thread reads them.
	world_mutex        &sync.Mutex = sync.new_mutex()
	identity           auth.Identity
	encryption_enabled bool
	runtime_id         u64
	pos_mutex          &sync.Mutex = sync.new_mutex()
	position           types.Vector3
	pitch              f32
	yaw                f32
	head_yaw           f32
	spawned            bool
	inv_opened         bool
	game_mode          int
	health             f32 = 20.0
	prev_y             f32
	vy                 f32
	dead               bool
	held_item          types.ItemStackWrapper
	held_slot          int
	inv_stacks         map[int]types.ItemStack
	inv_slots          map[int]int
	inv_next_id        int = 1
	pending_creative   ?types.ItemStack
	loaded_items       []playerdb.InvItem
	pending_radius     int
	perm               permission.Permissible
	give_next_slot     int
	next_form_id       int
	pending_forms      map[int]form.Form
	last_place_ms      i64
	effects            effect.Manager
	has_last_death     bool
	last_death_pos     types.Vector3
	view_radius        int
	last_chunk_x       int
	last_chunk_z       int
	chunk_cache        map[u64]world.Chunk
	sent_chunks        map[u64]bool
	chunk_cache_mutex  &sync.Mutex = sync.new_mutex()
	chunk_stream_mutex &sync.Mutex = sync.new_mutex()
	cooldown_until     map[string]i64
pub mut:
	log &logger.Logger = unsafe { nil }
}

fn (NetworkSession) add_effect #

fn (mut s NetworkSession) add_effect(e effect.Effect)

fn (NetworkSession) broadcast_message #

fn (mut s NetworkSession) broadcast_message(text string)

fn (NetworkSession) broadcast_title #

fn (mut s NetworkSession) broadcast_title(kind int, text string)

fn (NetworkSession) clear_inventory #

fn (mut s NetworkSession) clear_inventory()

fn (NetworkSession) clear_scoreboard #

fn (mut s NetworkSession) clear_scoreboard()

fn (NetworkSession) deliver #

fn (mut s NetworkSession) deliver(p protocol.Packet)

fn (NetworkSession) disconnect #

fn (mut s NetworkSession) disconnect(message string)

fn (NetworkSession) find_player #

fn (mut s NetworkSession) find_player(name string) ?cmd.Sender

fn (NetworkSession) give_item #

fn (mut s NetworkSession) give_item(id string, count int) bool

fn (NetworkSession) handle_loop #

fn (mut s NetworkSession) handle_loop()

fn (NetworkSession) has_permission #

fn (s &NetworkSession) has_permission(name string) bool

fn (NetworkSession) is_player #

fn (s &NetworkSession) is_player() bool

fn (NetworkSession) kill #

fn (mut s NetworkSession) kill()

fn (NetworkSession) name #

fn (s &NetworkSession) name() string

fn (NetworkSession) place_water #

fn (mut s NetworkSession) place_water(x int, y int, z int)

place_water sets a water source at the block position and starts its spread. Routes through the actor thread via Hub.place_water.

fn (NetworkSession) position #

fn (mut s NetworkSession) position() (f32, f32, f32)

teleport

fn (NetworkSession) refresh_abilities #

fn (mut s NetworkSession) refresh_abilities()

fn (NetworkSession) refresh_available_commands #

fn (mut s NetworkSession) refresh_available_commands()

refresh_available_commands resends the client's command list. The client only reads permission-gated visibility once (Command.execute checks it live, but the client-side autocomplete/menu does not) - anything that changes what s.perm can do after spawn (op/deop today, a future rank/VIP permission grant tomorrow) must call this or the player's command list stays stale until they reconnect.

fn (NetworkSession) remove_effect #

fn (mut s NetworkSession) remove_effect(typ effect.Type)

fn (NetworkSession) send_form #

fn (mut s NetworkSession) send_form(f form.Form) !

fn (NetworkSession) set_difficulty #

fn (mut s NetworkSession) set_difficulty(value int)

fn (NetworkSession) set_operator #

fn (mut s NetworkSession) set_operator(value bool)

fn (NetworkSession) show_scoreboard #

fn (mut s NetworkSession) show_scoreboard(title string, lines []string)

fn (NetworkSession) show_title #

fn (mut s NetworkSession) show_title(kind int, text string)

fn (NetworkSession) teleport #

fn (mut s NetworkSession) teleport(x f32, y f32, z f32)

fn (NetworkSession) teleport_to_world #

fn (mut s NetworkSession) teleport_to_world(name string, x f32, y f32, z f32)

teleport_to_world moves the player into another loaded world at the given position. No-op on the hub thread if the world is not loaded.

fn (NetworkSession) whitelist_add #

fn (mut s NetworkSession) whitelist_add(name string)

fn (NetworkSession) whitelist_enabled #

fn (s &NetworkSession) whitelist_enabled() bool

fn (NetworkSession) whitelist_names #

fn (s &NetworkSession) whitelist_names() []string

fn (NetworkSession) whitelist_remove #

fn (mut s NetworkSession) whitelist_remove(name string)

fn (NetworkSession) whitelist_set_enabled #

fn (mut s NetworkSession) whitelist_set_enabled(value bool)

fn (NetworkSession) world_create #

fn (mut s NetworkSession) world_create(name string, dimension string, generator string) !

fn (NetworkSession) world_delete #

fn (mut s NetworkSession) world_delete(name string) !

fn (NetworkSession) world_info #

fn (mut s NetworkSession) world_info(name string) ?cmd.WorldSummary

fn (NetworkSession) world_load #

fn (mut s NetworkSession) world_load(name string) !

fn (NetworkSession) world_name #

fn (s &NetworkSession) world_name() string

fn (NetworkSession) world_names #

fn (mut s NetworkSession) world_names() []string

world_admin wires the /world command's needs onto the Hub. Create/delete only touch the worlds map (never a player's active world), so they run directly on the Hub which already guards that map. Teleport goes through the existing TeleportJob so the world swap happens on the actor thread.

fn (NetworkSession) world_teleport #

fn (mut s NetworkSession) world_teleport(name string) !

struct TickJob #

struct TickJob {
pub:
	tick       i64
	world_time int
	tps        f64
	load       f64
}

TickJob contains the per tick server state passed from tick_loop to Hub. Each snapshot includes the current world time, tps and tick load.

tick_loop owns the 20 Hz tick cadence and calculates the tps and load metrics on its own thread. It submits one TickJob per tick instead of modifying Hub's fields directly.

struct WorldInfo #

struct WorldInfo {
pub:
	name       string
	generator  string
	dimension  string
	overrides  int
	is_default bool
	players    int
}

WorldInfo is a read-only snapshot describing a loaded world.