Change typings to distinguish dense and sparse stores, and have the container add the "generation" field instead of the container
This commit is contained in:
parent
e8415da145
commit
8434e7046c
5 changed files with 36 additions and 37 deletions
|
@ -5,7 +5,8 @@
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "webpack",
|
"build": "webpack",
|
||||||
"buildProduction": "webpack --mode=production"
|
"buildProduction": "webpack --mode=production",
|
||||||
|
"tsc:check": "tsc --noEmit"
|
||||||
},
|
},
|
||||||
"author": "Tangent 128",
|
"author": "Tangent 128",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
import { Data as CoreData, Store } from "./Data";
|
import { Data as CoreData, Store, SparseStore } from "./Data";
|
||||||
import { Layer, SpriteSheet } from "../Applet/Render";
|
import { Layer, SpriteSheet } from "../Applet/Render";
|
||||||
|
|
||||||
export class Box {
|
export class Box {
|
||||||
|
@ -68,8 +68,8 @@ export class RenderSprite {
|
||||||
export class Data extends CoreData {
|
export class Data extends CoreData {
|
||||||
location: Store<Location> = [];
|
location: Store<Location> = [];
|
||||||
bounds: Store<Polygon> = [];
|
bounds: Store<Polygon> = [];
|
||||||
renderBounds: Store<RenderBounds> = {};
|
renderBounds: SparseStore<RenderBounds> = {};
|
||||||
renderSprite: Store<RenderSprite> = {};
|
renderSprite: SparseStore<RenderSprite> = {};
|
||||||
collisionSourceClass: Store<CollisionClass> = {};
|
collisionSourceClass: SparseStore<CollisionClass> = {};
|
||||||
collisionTargetClass: Store<CollisionClass> = {};
|
collisionTargetClass: SparseStore<CollisionClass> = {};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,25 +1,26 @@
|
||||||
|
|
||||||
export interface Component {
|
|
||||||
generation: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type Id = [number, number];
|
export type Id = [number, number];
|
||||||
|
|
||||||
export enum Liveness {
|
export const enum Liveness {
|
||||||
DEAD = 0,
|
DEAD = 0,
|
||||||
ALIVE = 1,
|
ALIVE = 1,
|
||||||
INACTIVE = 2
|
INACTIVE = 2
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EntityState extends Component {
|
export interface HasGeneration {
|
||||||
|
generation: number;
|
||||||
|
}
|
||||||
|
export interface EntityState {
|
||||||
alive: Liveness;
|
alive: Liveness;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Store<T> = (T & Component)[] | Record<number, T & Component>;
|
export type Store<T> = (T & HasGeneration)[];
|
||||||
|
export type SparseStore<T> = Record<number, T & HasGeneration>;
|
||||||
export class Data {
|
export class Data {
|
||||||
entity: EntityState[] = [];
|
entity: Store<EntityState> = [];
|
||||||
|
|
||||||
[name: string]: Store<{}>;
|
[name: string]: Store<{}> | SparseStore<{}>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -29,11 +30,8 @@ export class Data {
|
||||||
* @param state Liveness state, allows creating an inactive entity
|
* @param state Liveness state, allows creating an inactive entity
|
||||||
* @returns the new entity's ID and generation
|
* @returns the new entity's ID and generation
|
||||||
*/
|
*/
|
||||||
type StripKeys<T, N> = {
|
|
||||||
[P in keyof T]: P extends N ? never : P
|
|
||||||
}[keyof T];
|
|
||||||
type Assigner<DATA extends Data> = {
|
type Assigner<DATA extends Data> = {
|
||||||
[S in keyof DATA]?: Pick<DATA[S][number], StripKeys<DATA[S][number], "generation">>
|
[S in keyof DATA]?: Pick<DATA[S][number], Exclude<keyof DATA[S][number], "generation">>
|
||||||
};
|
};
|
||||||
export function Create<DATA extends Data>(data: DATA, assign: Assigner<DATA>, state = Liveness.ALIVE): Id {
|
export function Create<DATA extends Data>(data: DATA, assign: Assigner<DATA>, state = Liveness.ALIVE): Id {
|
||||||
const entities = data.entity;
|
const entities = data.entity;
|
||||||
|
@ -126,7 +124,7 @@ export function Lookup<
|
||||||
* @param components names of components to look for
|
* @param components names of components to look for
|
||||||
* @returns the cooresponding components, with unfound ones replaced by nulls
|
* @returns the cooresponding components, with unfound ones replaced by nulls
|
||||||
*/
|
*/
|
||||||
export function Lookup<DATA extends Data, K extends keyof DATA>(data: DATA, [id, generation]: Id, ...components: K[]): (Component | null)[] {
|
export function Lookup<DATA extends Data, K extends keyof DATA>(data: DATA, [id, generation]: Id, ...components: K[]): ({} | null)[] {
|
||||||
const entity = data.entity[id];
|
const entity = data.entity[id];
|
||||||
// inactive entities are fine to lookup, but dead ones are not
|
// inactive entities are fine to lookup, but dead ones are not
|
||||||
if(entity && entity.generation == generation && entity.alive != Liveness.DEAD) {
|
if(entity && entity.generation == generation && entity.alive != Liveness.DEAD) {
|
||||||
|
@ -206,11 +204,11 @@ export function Join<
|
||||||
* Query a Data collection for all Alive entities possessing the named set of Components.
|
* Query a Data collection for all Alive entities possessing the named set of Components.
|
||||||
* @returns an array of tuples containing the matching entity [ID, generation]s & associated Components
|
* @returns an array of tuples containing the matching entity [ID, generation]s & associated Components
|
||||||
*/
|
*/
|
||||||
export function Join<DATA extends Data, K extends keyof DATA>(data: DATA, ...components: K[]): [Id, ...Component[]][] {
|
export function Join<DATA extends Data, K extends keyof DATA>(data: DATA, ...components: K[]): [Id, ...{}[]][] {
|
||||||
const entities = data.entity;
|
const entities = data.entity;
|
||||||
const stores: Store<{}>[] = components.map(name => data[name]);
|
const stores: (Store<{}>|SparseStore<{}>)[] = components.map(name => data[name]);
|
||||||
|
|
||||||
const results: [Id, ...Component[]][] = [];
|
const results: [Id, ...{}[]][] = [];
|
||||||
const firstStore = stores[0];
|
const firstStore = stores[0];
|
||||||
if(Array.isArray(firstStore)) {
|
if(Array.isArray(firstStore)) {
|
||||||
for(let id = 0; id < firstStore.length; id++) {
|
for(let id = 0; id < firstStore.length; id++) {
|
||||||
|
@ -223,8 +221,8 @@ export function Join<DATA extends Data, K extends keyof DATA>(data: DATA, ...com
|
||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
function JoinLoop(id: number, entities: Store<EntityState>, stores: Store<{}>[], results: [Id, ...Component[]][]) {
|
function JoinLoop(id: number, entities: Store<EntityState>, stores: (Store<{}>|SparseStore<{}>)[], results: [Id, ...{}[]][]) {
|
||||||
const result: [Id, ...Component[]] = [[id, -1]];
|
const result: [Id, ...{}[]] = [[id, -1]];
|
||||||
|
|
||||||
let generation = -1;
|
let generation = -1;
|
||||||
for (const store of stores) {
|
for (const store of stores) {
|
||||||
|
|
|
@ -4,15 +4,15 @@ import { Loop } from "../Applet/Loop";
|
||||||
import { Layer, DrawSet } from "../Applet/Render";
|
import { Layer, DrawSet } from "../Applet/Render";
|
||||||
import { Data, Location, Polygon, RenderBounds, CollisionClass } from "./Components";
|
import { Data, Location, Polygon, RenderBounds, CollisionClass } from "./Components";
|
||||||
import { FindCollisions } from "./Collision";
|
import { FindCollisions } from "./Collision";
|
||||||
import { Component, Join, Liveness, Remove, Create, Lookup } from "./Data";
|
import { Join, Liveness, Remove, Create, Lookup, Store, SparseStore } from "./Data";
|
||||||
import { DumbMotion } from "./Location";
|
import { DumbMotion } from "./Location";
|
||||||
import { RunRenderBounds } from "./Renderers";
|
import { RunRenderBounds } from "./Renderers";
|
||||||
|
|
||||||
interface Apple extends Component {}
|
interface Apple {}
|
||||||
interface Banana extends Component {
|
interface Banana {
|
||||||
peeled: boolean
|
peeled: boolean
|
||||||
}
|
}
|
||||||
interface Carrot extends Component {
|
interface Carrot {
|
||||||
cronch: number
|
cronch: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ class TestData extends Data {
|
||||||
{generation: 5, alive: Liveness.INACTIVE},
|
{generation: 5, alive: Liveness.INACTIVE},
|
||||||
{generation: 5, alive: Liveness.ALIVE},
|
{generation: 5, alive: Liveness.ALIVE},
|
||||||
];
|
];
|
||||||
apple: Apple[] = [
|
apple: Store<Apple> = [
|
||||||
{generation: 5},
|
{generation: 5},
|
||||||
{generation: 5},
|
{generation: 5},
|
||||||
{generation: -1},
|
{generation: -1},
|
||||||
|
@ -33,11 +33,11 @@ class TestData extends Data {
|
||||||
{generation: 5},
|
{generation: 5},
|
||||||
{generation: 5},
|
{generation: 5},
|
||||||
];
|
];
|
||||||
banana: Record<number, Banana> = {
|
banana: SparseStore<Banana> = {
|
||||||
3: {generation: 5, peeled: false},
|
3: {generation: 5, peeled: false},
|
||||||
4: {generation: 5, peeled: true},
|
4: {generation: 5, peeled: true},
|
||||||
};
|
};
|
||||||
carrot: Record<number, Carrot> = {
|
carrot: SparseStore<Carrot> = {
|
||||||
0: {generation: 5, cronch: 1},
|
0: {generation: 5, cronch: 1},
|
||||||
1: {generation: 5, cronch: 1},
|
1: {generation: 5, cronch: 1},
|
||||||
2: {generation: 4, cronch: 10},
|
2: {generation: 4, cronch: 10},
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Layer, DrawSet } from "../Applet/Render";
|
import { Layer, DrawSet } from "../Applet/Render";
|
||||||
import { Store } from "../Ecs/Data";
|
import { SparseStore } from "../Ecs/Data";
|
||||||
import { Data as EcsData } from "../Ecs/Components";
|
import { Data as EcsData } from "../Ecs/Components";
|
||||||
|
|
||||||
export enum GamePhase {
|
export enum GamePhase {
|
||||||
|
@ -54,11 +54,11 @@ export class World {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Data extends EcsData {
|
export class Data extends EcsData {
|
||||||
boss: Store<Boss> = {};
|
boss: SparseStore<Boss> = {};
|
||||||
bullet: Store<Bullet> = {};
|
bullet: SparseStore<Bullet> = {};
|
||||||
hp: Store<Hp> = {};
|
hp: SparseStore<Hp> = {};
|
||||||
lifetime: Store<Lifetime> = {};
|
lifetime: SparseStore<Lifetime> = {};
|
||||||
message: Store<Message> = {};
|
message: SparseStore<Message> = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum Teams {
|
export enum Teams {
|
||||||
|
|
Loading…
Reference in a new issue