Entities · class
ComponentStore
Explained in Entities.
class ComponentStoreimport { ComponentStore } from '@driftengine/entities';Constructor
new
constructor(type: ComponentType, options?: ComponentStoreOptions)| Parameter | Type | Description |
|---|---|---|
type | ComponentType | |
options? | ComponentStoreOptions |
Properties
| Name | Type | Description |
|---|---|---|
typereadonly | ComponentType |
Accessors
| Name | Type | Description |
|---|---|---|
sizeget | number | |
denseget | Float64Array | The entities this store holds, oldest first. Valid up to size; the rest is capacity. |
Methods
view
view(): ComponentViewThe live columns of this store, addressable by field name.
More
The same object every call, refreshed after every reallocation — see view.ts for why that is
the contract rather than a convenience.
column
column(field: string): NumericColumn | unknown[]One field's storage, for a caller iterating it directly rather than through read.
| Parameter | Type | Description |
|---|---|---|
field | string |
has
has(entity: Entity): boolean| Parameter | Type | Description |
|---|---|---|
entity | Entity |
add
add(entity: Entity, values?: Readonly<Record<string, unknown>>): void| Parameter | Type | Description |
|---|---|---|
entity | Entity | |
values? | Readonly<Record<string, unknown>> |
remove
remove(entity: Entity): booleanDrop an entity's component. false when it never had one, which is not an error.
| Parameter | Type | Description |
|---|---|---|
entity | Entity |
More
The last entry is swapped into the hole and its sparse entry is fixed — the fix-up being the whole of what makes a constant-time removal correct.
The order of the two sparse writes is load-bearing, and it is the only thing that is. When
the entry being removed is the last, the swap is with itself and moved is entity: writing
the position first and then the -1 leaves it absent, which is right; the other way round leaves
it pointing into the space past size.
There was a position < size guard in positionOf as well, which made the order not matter —
and made a perturbation of the order pass every test. Two defences for one case is one defence
and one comment that cannot be checked, so the guard is gone and the order is what the test
for removing the last entry actually holds.
read
read(entity: Entity, field: string): unknown| Parameter | Type | Description |
|---|---|---|
entity | Entity | |
field | string |
write
write(entity: Entity, field: string, value: unknown): void| Parameter | Type | Description |
|---|---|---|
entity | Entity | |
field | string | |
value | unknown |
saveInto
saveInto(slot: StoreSnapshot): voidCopy this store's contents into a slot, growing the slot to match if it is short.
| Parameter | Type | Description |
|---|---|---|
slot | StoreSnapshot |
More
count bounds every copy, not capacity. A store that once held ten thousand entities and
now holds four has ten thousand slots of stale numbers behind the live four, and copying them
would make a snapshot's cost depend on the world's history instead of its size.
A boxed column copies references. That is correct rather than a shortcut: the one boxed field
type is String, and a string cannot be mutated behind the snapshot's back.
loadFrom
loadFrom(slot: StoreSnapshot): voidPut this store back to a saved slot, rebuilding sparse from the restored dense.
| Parameter | Type | Description |
|---|---|---|
slot | StoreSnapshot |
More
The order of the two sparse passes is load-bearing. The entries this store's current live
set occupies are cleared first, while dense still says which they are; overwriting dense
first loses that record and leaves stale positions behind, and a stale position is worse than a
missing one because positionOf would find a live slot holding a different handle.