restore_apply.bend
bendvy-ecs-core@0.1.0.1 · 65 lines · 0 definitions
1import bendvy-ecs-core@0.1.0.1/deferred_command.bend as Deferred
2import Base
3import bendvy-ecs-core@0.1.0.1/change_tick.bend as Tick
4import bendvy-ecs-core@0.1.0.1/clock_state.bend as Clock
5import bendvy-ecs-core@0.1.0.1/restore_lifecycle.bend as Lifecycle
6import bendvy-ecs-core@0.1.0.1/entity_key.bend as Key
7import bendvy-ecs-core@0.1.0.1/restore_data.bend as R
8import bendvy-ecs-core@0.1.0.1/restore_world.bend as Adapter
9import bendvy-ecs-core@0.1.0.1/world.bend as W
10import bendvy-ecs-core@0.1.0.1/entity_allocator.bend as Alloc
11import bendvy-ecs-core@0.1.0.1/snapshot_data.bend as Snapshot
12
13type ApplyResult<S:Data,C:Type,Resources:Type,E:Data,State:Type,Custom:Data> is Type:
14 Applied{world:W.World<S,C,Resources,E>,state:State,bindings:List<&2,R.Binding<S>>}
15 Refused{world:W.World<S,C,Resources,E>,state:State,input:Snapshot.Snapshot,error:R.Error<Custom>}
16type Spawned<S:Data,C:Type,Resources:Type,E:Data> is Type:
17 Spawned{world:W.World<S,C,Resources,E>,bindings:List<&2,R.Binding<S>>}
18 Exhausted{world:W.World<S,C,Resources,E>,bindings:List<&2,R.Binding<S>>}
19def spawned(~S:Data,~C:Type,~Resources:Type,~E:Data,~emit:R.Change<S> -> E,+saved:Key.Key,+handle:W.Handle<S>,bindings:List<&2,R.Binding<S>>,next:W.World<S,C,Resources,E> -> List<&2,R.Binding<S>> -> Spawned<S,C,Resources,E>,observed:W.World<S,C,Resources,E> & W.Status) -> Spawned<S,C,Resources,E>:
20 match observed:
21 case (world,W.Rejected{_}):Exhausted{world,List.reverse(&2,R.Binding<S>,bindings)}
22 case (world,W.Accepted{}):next(W.event_publish(~S,~C,~Resources,~E,world,[emit(R.Spawned{handle})]),R.Binding{saved,handle} <> bindings)
23def reserved(~S:Data,~C:Type,~Resources:Type,~E:Data,~emit:R.Change<S> -> E,saved:Key.Key,bindings:List<&2,R.Binding<S>>,next:W.World<S,C,Resources,E> -> List<&2,R.Binding<S>> -> Spawned<S,C,Resources,E>,observed:W.World<S,C,Resources,E> & W.Reservation<S>) -> Spawned<S,C,Resources,E>:
24 match observed:
25 case (world,W.ReservationRejected{_}):Exhausted{world,List.reverse(&2,R.Binding<S>,bindings)}
26 case (world,W.Reserved{+handle}):spawned(~S,~C,~Resources,~E,~emit,saved,handle,bindings,next,(world,W.Accepted{}))
27def spawn(~S:Data,~C:Type,~Resources:Type,~E:Data,~emit:R.Change<S> -> E,entities:List<&2,Snapshot.Entity>,world:W.World<S,C,Resources,E>,bindings:List<&2,R.Binding<S>>) -> Spawned<S,C,Resources,E>:
28 match entities:
29 case []:Spawned{world,List.reverse(&2,R.Binding<S>,bindings)}
30 case Snapshot.Entity{saved,_} <> rest:reserved(~S,~C,~Resources,~E,~emit,saved,bindings,world => bindings => spawn(~S,~C,~Resources,~E,~emit,rest,world,bindings),Lifecycle.spawn(~S,~C,~Resources,~E,world))
31def inserted(~S:Data,~C:Type,~Resources:Type,~E:Data,~State:Type,~Custom:Data,+namespace:U32,allocator:Alloc.Allocator,+oldEvents:List<&2,E>,pending:List<Deferred.Command<W.World<S,C,Resources,E>>>,+registrations:List<&2,W.RegistrationMeta>,+nextSystem:U32,+clock:Clock.State,bindings:List<&2,R.Binding<S>>,observed:(C & Resources) & State) -> ApplyResult<S,C,Resources,E,State,Custom>:
32 match observed:
33 case ((store,resource),state):Applied{W.World{namespace,allocator,store,resource,oldEvents,pending,registrations,nextSystem,clock},state,bindings}
34def capacity_error(~Custom:Data,input:Snapshot.Snapshot) -> R.Error<Custom>:
35 match input:
36 case Snapshot.Snapshot{_,floor,_,_}:R.Capacity{floor}
37def install(~S:Data,~C:Type,~Resources:Type,~E:Data,~State:Type,~Custom:Data,~insert:C -> Resources -> State -> List<&2,R.Binding<S>> -> Tick.Tick -> (C & Resources) & State,state:State,+input:Snapshot.Snapshot,observed:Spawned<S,C,Resources,E>) -> ApplyResult<S,C,Resources,E,State,Custom>:
38 match observed:
39 case Exhausted{world,_}:Refused{world,state,input,capacity_error(~Custom,input)}
40 case Spawned{W.World{namespace,allocator,store,resource,oldEvents,pending,registrations,nextSystem,+clock},+bindings}:inserted(~S,~C,~Resources,~E,~State,~Custom,namespace,allocator,oldEvents,pending,registrations,nextSystem,clock,bindings,insert(store,resource,state,bindings,Clock.current(clock)))
41def progressed(~S:Data,~C:Type,~Resources:Type,~E:Data,~State:Type,~Custom:Data,~insert:C -> Resources -> State -> List<&2,R.Binding<S>> -> Tick.Tick -> (C & Resources) & State,~emit:R.Change<S> -> E,state:State,+input:Snapshot.Snapshot,observed:W.World<S,C,Resources,E> & Bool) -> ApplyResult<S,C,Resources,E,State,Custom>:
42 match input observed:
43 case Snapshot.Snapshot{version,floor,entities,resources},(world,False{}):Refused{world,state,Snapshot.Snapshot{version,floor,entities,resources},R.Capacity{floor}}
44 case Snapshot.Snapshot{+version,+floor,+entities,+resources},(world,True{}):install(~S,~C,~Resources,~E,~State,~Custom,~insert,state,Snapshot.Snapshot{version,floor,entities,resources},spawn(~S,~C,~Resources,~E,~emit,entities,world,[]))
45def cleaned(~S:Data,~C:Type,~Resources:Type,~E:Data,~State:Type,~Custom:Data,~insert:C -> Resources -> State -> List<&2,R.Binding<S>> -> Tick.Tick -> (C & Resources) & State,~emit:R.Change<S> -> E,+input:Snapshot.Snapshot,floor:U32,observed:W.World<S,C,Resources,E> & State) -> ApplyResult<S,C,Resources,E,State,Custom>:
46 match observed:
47 case (world,state):progressed(~S,~C,~Resources,~E,~State,~Custom,~insert,~emit,state,input,Adapter.advance_floor(~S,~C,~Resources,~E,world,floor))
48def handles(~S:Data,~C:Type,~Resources:Type,~E:Data,~State:Type,~Custom:Data,~clear:C -> W.Handle<S> -> C & List<&2,R.Change<S>>,~insert:C -> Resources -> State -> List<&2,R.Binding<S>> -> Tick.Tick -> (C & Resources) & State,~emit:R.Change<S> -> E,state:State,+input:Snapshot.Snapshot,+floor:U32,observed:W.World<S,C,Resources,E> & List<&2,W.Handle<S>>) -> ApplyResult<S,C,Resources,E,State,Custom>:
49 match observed:
50 case (world,values):cleaned(~S,~C,~Resources,~E,~State,~Custom,~insert,~emit,input,floor,(Lifecycle.clean(~S,~C,~Resources,~E,~clear,~emit,values,world),state))
51def advanced(~S:Data,~C:Type,~Resources:Type,~E:Data,~State:Type,~Custom:Data,~clear:C -> W.Handle<S> -> C & List<&2,R.Change<S>>,~insert:C -> Resources -> State -> List<&2,R.Binding<S>> -> Tick.Tick -> (C & Resources) & State,~emit:R.Change<S> -> E,state:State,input:Snapshot.Snapshot,floor:U32,observed:W.World<S,C,Resources,E> & Tick.Tick) -> ApplyResult<S,C,Resources,E,State,Custom>:
52 match observed:
53 case (world,_):handles(~S,~C,~Resources,~E,~State,~Custom,~clear,~insert,~emit,state,input,floor,W.handles(~S,~C,~Resources,~E,world))
54def admitted(~S:Data,~C:Type,~Resources:Type,~E:Data,~State:Type,~Custom:Data,~release:State -> State,~clear:C -> W.Handle<S> -> C & List<&2,R.Change<S>>,~insert:C -> Resources -> State -> List<&2,R.Binding<S>> -> Tick.Tick -> (C & Resources) & State,~emit:R.Change<S> -> E,state:State,+input:Snapshot.Snapshot,+floor:U32,observed:W.World<S,C,Resources,E> & Bool) -> ApplyResult<S,C,Resources,E,State,Custom>:
55 match observed:
56 case (world,False{}):Refused{world,release(state),input,R.Capacity{floor}}
57 case (world,True{}):advanced(~S,~C,~Resources,~E,~State,~Custom,~clear,~insert,~emit,state,input,floor,W.clock(~S,~C,~Resources,~E,W.events_replace(~S,~C,~Resources,~E,world,[])))
58def count_entities(values:List<&2,Snapshot.Entity>) -> Nat:
59 match values:
60 case []:0n
61 case _ <> rest:1n+count_entities(rest)
62def apply(~S:Data,~C:Type,~Resources:Type,~E:Data,~State:Type,~Custom:Data,~release:State -> State,~clear:C -> W.Handle<S> -> C & List<&2,R.Change<S>>,~insert:C -> Resources -> State -> List<&2,R.Binding<S>> -> Tick.Tick -> (C & Resources) & State,~emit:R.Change<S> -> E,world:W.World<S,C,Resources,E>,prepared:R.Prepared<State,Custom>) -> ApplyResult<S,C,Resources,E,State,Custom>:
63 match prepared:
64 case R.Refused{state,input,error}:Refused{world,state,input,error}
65 case R.BendvyReady{state,Snapshot.Snapshot{+version,+floor,+entities,+resources}}:admitted(~S,~C,~Resources,~E,~State,~Custom,~release,~clear,~insert,~emit,state,Snapshot.Snapshot{version,floor,entities,resources},floor,Adapter.room(~S,~C,~Resources,~E,world,floor,count_entities(entities)))