1 import ./deferred_command.bend as Deferred 2 import Base 3 import ./change_tick.bend as Tick 4 import ./clock_state.bend as Clock 5 import ./restore_lifecycle.bend as Lifecycle 6 import ./entity_key.bend as Key 7 import ./restore_data.bend as R 8 import ./restore_world.bend as Adapter 9 import ./world.bend as W 10 import ./entity_allocator.bend as Alloc 11 import ./snapshot_data.bend as Snapshot 12 13 type ApplyResult is Type: 14 Applied{world:W.World,state:State,bindings:List<&2,R.Binding>} 15 Refused{world:W.World,state:State,input:Snapshot.Snapshot,error:R.Error} 16 type Spawned is Type: 17 Spawned{world:W.World,bindings:List<&2,R.Binding>} 18 Exhausted{world:W.World,bindings:List<&2,R.Binding>} 19 def spawned(~S:Data,~C:Type,~Resources:Type,~E:Data,~emit:R.Change -> E,+saved:Key.Key,+handle:W.Handle,bindings:List<&2,R.Binding>,next:W.World -> List<&2,R.Binding> -> Spawned,observed:W.World & W.Status) -> Spawned: 20 match observed: 21 case (world,W.Rejected{_}):Exhausted{world,List.reverse(&2,R.Binding,bindings)} 22 case (world,W.Accepted{}):next(W.event_publish(~S,~C,~Resources,~E,world,[emit(R.Spawned{handle})]),R.Binding{saved,handle} <> bindings) 23 def reserved(~S:Data,~C:Type,~Resources:Type,~E:Data,~emit:R.Change -> E,saved:Key.Key,bindings:List<&2,R.Binding>,next:W.World -> List<&2,R.Binding> -> Spawned,observed:W.World & W.Reservation) -> Spawned: 24 match observed: 25 case (world,W.ReservationRejected{_}):Exhausted{world,List.reverse(&2,R.Binding,bindings)} 26 case (world,W.Reserved{+handle}):spawned(~S,~C,~Resources,~E,~emit,saved,handle,bindings,next,(world,W.Accepted{})) 27 def spawn(~S:Data,~C:Type,~Resources:Type,~E:Data,~emit:R.Change -> E,entities:List<&2,Snapshot.Entity>,world:W.World,bindings:List<&2,R.Binding>) -> Spawned: 28 match entities: 29 case []:Spawned{world,List.reverse(&2,R.Binding,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)) 31 def inserted(~S:Data,~C:Type,~Resources:Type,~E:Data,~State:Type,~Custom:Data,+namespace:U32,allocator:Alloc.Allocator,+oldEvents:List<&2,E>,pending:List>>,+registrations:List<&2,W.RegistrationMeta>,+nextSystem:U32,+clock:Clock.State,bindings:List<&2,R.Binding>,observed:(C & Resources) & State) -> ApplyResult: 32 match observed: 33 case ((store,resource),state):Applied{W.World{namespace,allocator,store,resource,oldEvents,pending,registrations,nextSystem,clock},state,bindings} 34 def capacity_error(~Custom:Data,input:Snapshot.Snapshot) -> R.Error: 35 match input: 36 case Snapshot.Snapshot{_,floor,_,_}:R.Capacity{floor} 37 def install(~S:Data,~C:Type,~Resources:Type,~E:Data,~State:Type,~Custom:Data,~insert:C -> Resources -> State -> List<&2,R.Binding> -> Tick.Tick -> (C & Resources) & State,state:State,+input:Snapshot.Snapshot,observed:Spawned) -> ApplyResult: 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))) 41 def progressed(~S:Data,~C:Type,~Resources:Type,~E:Data,~State:Type,~Custom:Data,~insert:C -> Resources -> State -> List<&2,R.Binding> -> Tick.Tick -> (C & Resources) & State,~emit:R.Change -> E,state:State,+input:Snapshot.Snapshot,observed:W.World & Bool) -> ApplyResult: 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,[])) 45 def cleaned(~S:Data,~C:Type,~Resources:Type,~E:Data,~State:Type,~Custom:Data,~insert:C -> Resources -> State -> List<&2,R.Binding> -> Tick.Tick -> (C & Resources) & State,~emit:R.Change -> E,+input:Snapshot.Snapshot,floor:U32,observed:W.World & State) -> ApplyResult: 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)) 48 def handles(~S:Data,~C:Type,~Resources:Type,~E:Data,~State:Type,~Custom:Data,~clear:C -> W.Handle -> C & List<&2,R.Change>,~insert:C -> Resources -> State -> List<&2,R.Binding> -> Tick.Tick -> (C & Resources) & State,~emit:R.Change -> E,state:State,+input:Snapshot.Snapshot,+floor:U32,observed:W.World & List<&2,W.Handle>) -> ApplyResult: 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)) 51 def advanced(~S:Data,~C:Type,~Resources:Type,~E:Data,~State:Type,~Custom:Data,~clear:C -> W.Handle -> C & List<&2,R.Change>,~insert:C -> Resources -> State -> List<&2,R.Binding> -> Tick.Tick -> (C & Resources) & State,~emit:R.Change -> E,state:State,input:Snapshot.Snapshot,floor:U32,observed:W.World & Tick.Tick) -> ApplyResult: 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)) 54 def admitted(~S:Data,~C:Type,~Resources:Type,~E:Data,~State:Type,~Custom:Data,~release:State -> State,~clear:C -> W.Handle -> C & List<&2,R.Change>,~insert:C -> Resources -> State -> List<&2,R.Binding> -> Tick.Tick -> (C & Resources) & State,~emit:R.Change -> E,state:State,+input:Snapshot.Snapshot,+floor:U32,observed:W.World & Bool) -> ApplyResult: 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,[]))) 58 def count_entities(values:List<&2,Snapshot.Entity>) -> Nat: 59 match values: 60 case []:0n 61 case _ <> rest:1n+count_entities(rest) 62 def apply(~S:Data,~C:Type,~Resources:Type,~E:Data,~State:Type,~Custom:Data,~release:State -> State,~clear:C -> W.Handle -> C & List<&2,R.Change>,~insert:C -> Resources -> State -> List<&2,R.Binding> -> Tick.Tick -> (C & Resources) & State,~emit:R.Change -> E,world:W.World,prepared:R.Prepared) -> ApplyResult: 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)))