The Spatials V3 devblog 2015-10-05
Internal development notes, very slightly cleaned up and commented a week later.
TL;DR: the new generic job state machine has been implemented and most of the week was devoted to fixing everything that broke down. The end result is a much more robust, yet generic and extensible job system. There’s nothing new to show on screen, this week was all about logic coding and bugfixes.
- litter: walking and nonwalking integrity
use dumb transition nodes for enter/exit-like actions for now
- litter picked spc offset? how to fix on cleanup? in general case?
new PositionModifierComponent with info on offsets for iso, screen, Z
remember markDirty on PosC on removal
track at MoverSystem level, so it works even for custom display systems
A few bugs from the litter system state machine were fixed, leaving it ready to serve as the base for a new general purpose, extensible state machine for general jobs.
- job-logistic-sm for replacing the current JobsSystem
- replace uses of JobsSystem with a state machine
building objects
remove state components after build
dismantling objects
building flooring
keep C++ side tilemap scan, create work ent but without JobComponent for the work area
check for invalid floor on work area too
scheme side state machine looks for the work area
the existing TileConstructionJobComponent holds the completion flag
pallet logistics
support -1 amount in job sm
support MaxCarry
- job sm: pick only minimal amount
- whole state machine extension via hashtable merge
- infinite loop is happening related to state machines and find_symbol_unchecked
(outlet (curlet)) used outside of a foreach lambda inside (init-state-machine)
so it was modifying lexical mod scope or similar, and all sm instances used the same slot...
nope! still happens, just build a bunch of beds at the same time
a non-break cycle happens when no items can be found
always (break) on cleanup
- job sm is leaving stacks busy despite not using them
it always leaves the stack busy when not fully consumed
fix by making sure if the stack survives picking, it is de-busied
- build sm and others are leaving workers busy
happens when the extended sm is not cleaning up busy states on owned entities, no cleanup is called
cleanup wont be called because the extended finalize (break)s
cleanup cannot be called since finalize cleans too much stuff, which must remain clean (job and construction comps for example)
just dupe the req cleaning, is just 2-3 calls, extend is not meant as a black box
- job sm endless loop when walk-to-item happens to be in the same tile as the worker is at the moment, AND the not enough not found triggers
very core flaw in ECS complies checks
they dont take into account same-frame component edits, so an item stack is not a child for the same frame
fix: never use getComponents directly for complies checking
now centralized in Entity::complies
it can now take into account same-frame removed and added comps
this introduces inconsistencies in query/complies vs in-frame actual accesible components
getByKind was already patched to return in-frame added
- job sm doesnt survive a forced repathing of the worker
there are two (to cleanup X) rules in walk-to-job-giver
the node struct is a hashtable, so one overrides the other
decide: use a list, or make it a rule to never have more than one to rule for a node inside a another node
list cons: no direct access to vars/extend/etc members
using or cons: this means different evals for the same path cannot have different actions, which is very useful
-> use assoc list, and make sure extend and vars are always at the front when coding the sm
- job sm keeps incrementing even when worker is away from work area
track position, make work condition stronger
- job sm error when impossible to find path
ecs-preferred-center returns floor value of tile offset, so it needs +0.5 to avoid impassables
also ecs-preferred-center, for the non-walkable preferred center, is non determinist, so the over-center check keeps failing
add another version of the random neigh finder that accepts entropy as a parameter, use (e #@entropy) -> now deterministic
- ecs-query wasnt properly filtering path-from results
This was the bulk of the work week, and there’s no easy way to cut it down to smaller pieces. A new general purpose job state machine mas introduced, and the old JobsSystem/WorkerSystem was removed. Along the way many, many bugs were fixed in both the state machine and its runtime library. There’s not much visual result to show from this work, other than a node graph view of the state machine:
Along the way the SM runtime gained the capability of extending state machines into a new state machine, while overriding one or more states. This work was vital in order to reach the goal of not having a monolithic base system that does everything relared to jobs. Now it’s possible to fully customize the job SM for every possible job kind (actually it is mandatory, because the base, generic SM doesn’t know what to do after a job is done). For jobs or actions that require it, it will be also possible to opt out from the base job SM and implement a new SM from scratch while playing nice with it since it’s all still based on the BusyComponent / BusySystem duo.
- bug: same-frame expectations for spatial query in ItemHeldBy for a newly spawned entity
change to a world query
- pallet sm: need to support toggles for pallet, floor picking, avoid pallet rect
extend find-item state to support the custom query
- bug: changing pallet storage prefs mid-job lock-leaks the busy worker
the current debug editor removes BusyC from the entity, so yeah
- bug: dumpings of picked items on pallets that don't go to the central, existing stack
happens because of the child/not child ping-pong for the min-stack rule
also creates "ninja scenario" for workers to race for an available stack in the up to 3secs that may take the pallet system to own it
unify stacks while counting
check for in-storage items on pallet job finalize and stack on them
the fixes make this better but the ninja scenario is still possible when the drop is the first stack
- ugly pallet cliping on walls: fixedZ hack is not required at all
Having more complex item-related semantics, pallets and their delivery jobs were a bit more complicated to port to the new system, but it all worked out in the end.
- remove WorkerS, WorkerC, JobC, JobsS
- re-introduce Officer class, slim down from V2 AgentOfficer
partial V2 model removal, first of many
There’s a large amount of V2 C++ code awaiting deletion. I’m removing it piece by piece, as it becomes obsolete by newer V3 systems.
- actually start using scheme defined room specs
- move resource rules/model to scheme
problem: a lot of the existing C++ rules init depends on having resources already init, and scheme rules init happens after C++
comment out the C++ stuff, it's pending deletion anyway
Resources are the kind of items that can be seen in the V3 screenshots/videos, and they represent countable amounts of stuff that will be later required for building or manufacturing. For now they are the only kind of item supported, and prior to this week they were defined using the old V2 data rules. This has now been replaced with a resource description made from Scheme in V3, so resource (re)declaration is now available to mods.
- switch again to a worker system to enable future priority system
worker-system (new): find jobs matching every worker-component entity ('one), pick closest path-able non-busy one
if found, it sets itself busy with the job giver
somehow the job giver ent sm has to notice a worker wants to work it
worker creates+sets BusyC subject to itself on the giver, marks #@removeCompOnInvalid #t
job sm recoginizes this and moves to next state
fix job sm so it stops using 'worker-ref, uses #@subject instead
- stop using the "-object" job components, replace by the "-job" components
- bug: worker busy leak in delivery jobs
make sure to clean spurious BusyC when not interested in deliveries
always activate reciprocal check in the worker BusyC
The new job SM assumed the task of finding available workers as an intermediate porting step (previously it was handled WorkerSystem). This is very limiting since it means it’s impossible to implement job priorities, for example. After the job SM was proven robust, a new worker system was re-implemented to be prepared for this functionality in the future.