ludic/packages/ludic.base/system.ludic

91 lines
3.2 KiB
Text

# ludic.base/system.ludic - a system is a record of what it does at each verb, and the runner
# calls them: init, reset, save and load in the order added, tick phase by phase. A null
# function is a verb the system does not have. The game's list is the order co-op's dice need.
export property System {
key: string = ""
phase: int = 2
version: int = 1
init: fn() -> void = null
reset: fn() -> void = null
tick: fn(Tick) -> void = null
save: fn() -> Val = null
load: fn(Val, int) -> void = null
}
# the declared list: a mechanic or the game writes `def Systems fishing { phase: PH_ACT, tick: fn
# fishing_tick }` from its own module; the runner starts from these, then core_add appends
export open registry Systems of System as SYS
# the declared systems; a registry is not filled when a state's defaults are made, so on first ask
@alloc_ok("once: the runner's list is made the first time it is asked, and kept")
function cs_all(base_st: mut BaseState) -> []System {
if base_st.cs_list == null {
base_st.cs_list = new []System
for i in 0 .. SYS_COUNT { push(base_st.cs_list, Systems[i]) }
}
return base_st.cs_list
}
@alloc_ok("at start: a system made for the runner")
export function system_new(key: string, phase: int) -> System {
let s = new System
s.key = key
s.phase = phase
return s
}
# a key is a save section's name, so two systems may not share one
@alloc_ok("at start: a system added to the runner")
export function core_add(base_st: mut BaseState, s: System) -> void {
let all = cs_all(base_st)
for i in 0 .. len(all) {
if all[i].key == s.key {
print(`ludic.base: two systems are keyed "{s.key}"`)
exit(1)
}
}
push(all, s)
}
export function core_clear(base_st: mut BaseState) -> void { base_st.cs_list = new []System }
export function core_count(base_st: mut BaseState) -> int { return len(cs_all(base_st)) }
export function core_init_all(base_st: mut BaseState) -> void {
let all = cs_all(base_st)
for i in 0 .. len(all) { if all[i].init != null { all[i].init() } }
}
export function core_reset_all(base_st: mut BaseState) -> void {
let all = cs_all(base_st)
for i in 0 .. len(all) { if all[i].reset != null { all[i].reset() } }
}
export function core_tick_all(base_st: mut BaseState, t: Tick) -> void {
let all = cs_all(base_st)
for ph in 0 .. PH_COUNT {
for i in 0 .. len(all) {
if all[i].phase == ph and all[i].tick != null { all[i].tick(t) }
}
drain_actions() # 0.R: the phase's actions, reduced before the next
}
}
# every system that saves, under its key with its version
export function core_save_all(base_st: mut BaseState) -> Val {
let root = save_tree()
let all = cs_all(base_st)
for i in 0 .. len(all) {
if all[i].save != null { save_section(root, all[i].key, all[i].version, all[i].save()) }
}
return root
}
# each system its own section; one with no section (or no load) is reset instead
export function core_load_all(base_st: mut BaseState, root: Val) -> void {
let all = cs_all(base_st)
for i in 0 .. len(all) {
let n = load_section(root, all[i].key)
if n.found and all[i].load != null { all[i].load(n.data, n.version) } else if all[i].reset != null { all[i].reset() }
}
}