Comparing version 0.3.4 to 0.4.0
@@ -5,3 +5,3 @@ import { EventSubscriber } from '@a-type/utils'; | ||
export type ArchetypeEvents = { | ||
entityAdded(entity: Entity<any, any>): any; | ||
entityAdded(entity: Entity<any>): any; | ||
entityRemoved(entityId: number): any; | ||
@@ -29,7 +29,7 @@ }; | ||
*/ | ||
[Symbol.iterator](): IterableIterator<Entity<T[number], any>>; | ||
[Symbol.iterator](): IterableIterator<Entity<T[number]>>; | ||
private setLookup; | ||
private getLookup; | ||
private clearLookup; | ||
addEntity(entity: Entity<any, any>): void; | ||
addEntity(entity: Entity<any>): void; | ||
/** | ||
@@ -39,4 +39,4 @@ * Removes an entity from the archetype table, returning its | ||
*/ | ||
removeEntity(entityId: number): Entity<T[number], any>; | ||
getEntity(entityId: number): Entity<T[number], any>; | ||
removeEntity(entityId: number): Entity<T[number]>; | ||
getEntity(entityId: number): Entity<T[number]>; | ||
hasAll: (types: ComponentHandle[]) => boolean; | ||
@@ -43,0 +43,0 @@ hasSome: (types: ComponentHandle[]) => boolean; |
@@ -24,6 +24,6 @@ import { EventSubscriber } from '@a-type/utils'; | ||
removeComponent(entityId: number, componentType: number): ComponentInstanceInternal | undefined; | ||
destroyEntity(entityId: number): import("./Entity.js").Entity<import("./Component2.js").ComponentHandle, any>; | ||
getEntity(entityId: number): import("./Entity.js").Entity<import("./Component2.js").ComponentHandle, any> | null; | ||
removeEntity(entityId: number): import("./Entity.js").Entity<import("./Component2.js").ComponentHandle>; | ||
getEntity(entityId: number): import("./Entity.js").Entity<import("./Component2.js").ComponentHandle> | null; | ||
private getOrCreate; | ||
private flipBit; | ||
} |
@@ -21,3 +21,4 @@ import { EventSubscriber } from '@a-type/utils'; | ||
const lookupIndex = getIdSignifier(entityId); | ||
return this.entityLookup[lookupIndex]; | ||
const arch = this.entityLookup[lookupIndex]; | ||
return arch; | ||
} | ||
@@ -81,4 +82,4 @@ setEntityArchetype(entityId, archetypeId) { | ||
} | ||
destroyEntity(entityId) { | ||
this.game.logger.debug(`Destroying entity ${entityId}`); | ||
removeEntity(entityId) { | ||
this.game.logger.debug(`Removing entity ${entityId} from all archetypes`); | ||
const archetypeId = this.lookupEntityArchetype(entityId); | ||
@@ -98,3 +99,3 @@ if (archetypeId === undefined) { | ||
if (archetypeId === undefined) { | ||
this.game.logger.debug(`Could not find Archetype for Entity ${entityId}`); | ||
this.game.logger.error(`Could not find Entity ${entityId}`); | ||
return null; | ||
@@ -101,0 +102,0 @@ } |
import { ComponentHandle, ComponentInstance, ComponentInstanceInternal, InstanceFor } from './Component2.js'; | ||
type DefinedInstance<Present extends ComponentHandle, Omitted extends ComponentHandle, Handle extends ComponentHandle> = Handle extends Present ? InstanceFor<Handle> : Handle extends Omitted ? never : InstanceFor<Handle> | null; | ||
export declare class Entity<DefiniteComponents extends ComponentHandle = ComponentHandle, OmittedComponents extends ComponentHandle = any> { | ||
type DefinedInstance<Present extends ComponentHandle, Handle extends ComponentHandle> = Handle extends Present ? InstanceFor<Handle> : InstanceFor<Handle> | null; | ||
export declare class Entity<DefiniteComponents extends ComponentHandle = ComponentHandle> { | ||
private _id; | ||
@@ -15,3 +15,3 @@ readonly components: Map<number, ComponentInstance>; | ||
__markRemoved: () => void; | ||
get: <T extends ComponentHandle>(handle: T) => DefinedInstance<DefiniteComponents, OmittedComponents, T>; | ||
get: <T extends ComponentHandle>(handle: T) => DefinedInstance<DefiniteComponents, T>; | ||
maybeGet: <T extends ComponentHandle>(handle: T) => InstanceFor<T> | null; | ||
@@ -18,0 +18,0 @@ has: <T extends ComponentHandle>(handle: T) => boolean; |
@@ -58,3 +58,3 @@ import { QueryManager } from './QueryManager.js'; | ||
get assets(): Assets<AssetLoaders>; | ||
get entityPool(): ObjectPool<Entity<ComponentHandle, any>>; | ||
get entityPool(): ObjectPool<Entity<ComponentHandle>>; | ||
subscribe: <K extends keyof GameEvents>(event: K, listener: GameEvents[K]) => () => void; | ||
@@ -76,3 +76,3 @@ /** | ||
*/ | ||
remove: <T extends ComponentHandle>(entity: number | Entity, Type: T) => void; | ||
remove: <T extends ComponentHandle, E extends Entity<any>>(entity: number | E, Type: T) => void; | ||
/** | ||
@@ -79,0 +79,0 @@ * Get a single entity by its known ID |
@@ -72,2 +72,11 @@ import { QueryManager } from './QueryManager.js'; | ||
this.remove = (entity, Type) => { | ||
if (!(typeof entity === 'number')) { | ||
// ignore removed entities, their components | ||
// are already gone. | ||
if (entity.removed) { | ||
return; | ||
} | ||
// TODO: find a way to do this when the | ||
// arg isn't an entity | ||
} | ||
const entityId = typeof entity === 'number' ? entity : entity.id; | ||
@@ -138,2 +147,3 @@ this.enqueueStepOperation({ | ||
this.entityPool.release(entity); | ||
this.logger.debug('Destroyed entity', entity.id); | ||
}; | ||
@@ -163,2 +173,8 @@ this.flushPhaseOperations = () => { | ||
break; | ||
this.logger.debug('Removing component', operation.componentType, 'from entity', operation.entityId); | ||
// if entity was removed already, it won't | ||
// be in archetypes anymore, and the component | ||
// will be released in the removal process. | ||
if (this._removedList.get(operation.entityId)) | ||
break; | ||
instance = this.archetypeManager.removeComponent(operation.entityId, operation.componentType); | ||
@@ -179,3 +195,3 @@ if (instance) { | ||
break; | ||
entity = this.archetypeManager.destroyEntity(operation.entityId); | ||
entity = this.archetypeManager.removeEntity(operation.entityId); | ||
this._removedList.add(entity); | ||
@@ -182,0 +198,0 @@ break; |
export * from './Game.js'; | ||
export * from './Query.js'; | ||
export * from './Component2.js'; | ||
export { system } from './System.js'; | ||
export { system, type SystemRunner } from './System.js'; | ||
export * from './filters.js'; | ||
@@ -10,2 +10,3 @@ export { effect } from './Effect.js'; | ||
export { setup } from './Setup.js'; | ||
export type { EntityImpostorFor } from './QueryIterator.js'; | ||
export interface Globals { | ||
@@ -12,0 +13,0 @@ } |
@@ -0,6 +1,7 @@ | ||
export type LogLevel = 'info' | 'warn' | 'error' | 'debug'; | ||
export declare class Logger { | ||
static readonly levels: readonly ["debug", "info", "warn", "error"]; | ||
static readonly levels: LogLevel[]; | ||
private lvl; | ||
doLog: (level: 'info' | 'warn' | 'error' | 'debug', ...messages: unknown[]) => void; | ||
constructor(level: 'info' | 'warn' | 'error' | 'debug'); | ||
doLog: (level: LogLevel, ...messages: unknown[]) => void; | ||
constructor(level: LogLevel); | ||
info: (...args: unknown[]) => void; | ||
@@ -7,0 +8,0 @@ warn: (...args: unknown[]) => void; |
@@ -17,4 +17,9 @@ export class Logger { | ||
} | ||
Logger.levels = ['debug', 'info', 'warn', 'error']; | ||
Logger.levels = [ | ||
'debug', | ||
'info', | ||
'warn', | ||
'error', | ||
]; | ||
export const defaultLogger = new Logger('info'); | ||
//# sourceMappingURL=logger.js.map |
@@ -27,2 +27,4 @@ import { Game } from './Game.js'; | ||
private unsubscribeArchetypes; | ||
private _generation; | ||
get generation(): number; | ||
constructor(game: Game); | ||
@@ -45,2 +47,3 @@ private processDef; | ||
get removedIds(): readonly number[]; | ||
get count(): number; | ||
private addToList; | ||
@@ -47,0 +50,0 @@ private removeFromList; |
@@ -5,2 +5,5 @@ import { isFilter, has } from './filters.js'; | ||
export class Query extends EventSubscriber { | ||
get generation() { | ||
return this._generation; | ||
} | ||
constructor(game) { | ||
@@ -17,2 +20,3 @@ super(); | ||
this.unsubscribeArchetypes = undefined; | ||
this._generation = 0; | ||
this.processDef = (userDef) => { | ||
@@ -55,5 +59,7 @@ return userDef.map((fil) => (isFilter(fil) ? fil : has(fil))); | ||
this.addToList(entity.id); | ||
this._generation++; | ||
}; | ||
this.handleEntityRemoved = (entityId) => { | ||
this.removeFromList(entityId); | ||
this._generation++; | ||
}; | ||
@@ -162,2 +168,5 @@ this.addToList = (entityId) => { | ||
} | ||
get count() { | ||
return this.trackedEntities.length; | ||
} | ||
} | ||
@@ -164,0 +173,0 @@ class AddedIterator { |
@@ -8,7 +8,5 @@ import { ComponentHandle } from './Component2.js'; | ||
type UnwrapAnys<CompUnion extends Filter<ComponentHandle> | ComponentHandle> = CompUnion extends OneOf<any> ? never : CompUnion; | ||
type OnlyNots<CompUnion extends Filter<ComponentHandle> | ComponentHandle> = CompUnion extends Not<infer C> ? C : never; | ||
type UnwrapFilters<CompUnion extends Filter<ComponentHandle> | ComponentHandle> = CompUnion extends Filter<infer C> ? C : CompUnion; | ||
type DefiniteComponentsFromFilter<Fil extends QueryComponentFilter> = UnwrapFilters<UnwrapAnys<FilterNots<Fil[number]>>>; | ||
type OmittedComponentsFromFilter<Fil extends QueryComponentFilter> = OnlyNots<Fil[number]>; | ||
export type EntityImpostorFor<Q extends QueryComponentFilter> = Entity<DefiniteComponentsFromFilter<Q>, OmittedComponentsFromFilter<Q>>; | ||
export type EntityImpostorFor<Q extends QueryComponentFilter> = Entity<DefiniteComponentsFromFilter<Q>>; | ||
export declare class QueryIterator<Def extends QueryComponentFilter> implements Iterator<EntityImpostorFor<Def>> { | ||
@@ -15,0 +13,0 @@ private query; |
@@ -12,3 +12,3 @@ import { Entity } from './Entity.js'; | ||
flush: (callback: (entity: Entity) => void) => void; | ||
get: (entityId: number) => Entity<import("./Component2.js").ComponentHandle, any>; | ||
get: (entityId: number) => Entity<import("./Component2.js").ComponentHandle>; | ||
} |
@@ -5,9 +5,16 @@ import { Game } from './Game.js'; | ||
export declare const allSystems: ((game: Game) => void | (() => void))[]; | ||
type SystemRunner<Filter extends QueryComponentFilter, Result> = (entity: EntityImpostorFor<Filter>, game: Game, previousResult: Result) => Result; | ||
export declare function system<Filter extends QueryComponentFilter, Result = void>(filter: Filter, run: SystemRunner<Filter, Result>, { phase, initialResult, }?: { | ||
export type SystemRunner<Filter extends QueryComponentFilter, Result> = (entity: EntityImpostorFor<Filter>, game: Game, previousResult: Result) => Result; | ||
declare function unregisteredSystem<Filter extends QueryComponentFilter, Result = void>(filter: Filter, run: SystemRunner<Filter, Result>, { phase, initialResult, }?: { | ||
phase?: 'step' | 'preStep' | 'postStep' | (string & {}); | ||
initialResult?: Result; | ||
}): (game: Game) => () => void; | ||
export declare function system<Filter extends QueryComponentFilter, Result = void>(filter: Filter, run: SystemRunner<Filter, Result>, options?: { | ||
phase?: 'step' | 'preStep' | 'postStep' | (string & {}); | ||
initialResult?: Result; | ||
}): (game: Game) => () => void; | ||
export declare namespace system { | ||
var unregistered: typeof unregisteredSystem; | ||
} | ||
/** @deprecated - use system */ | ||
export declare const makeSystem: typeof system; | ||
export {}; |
export const allSystems = new Array(); | ||
export function system(filter, run, { phase = 'step', initialResult = undefined, } = {}) { | ||
function unregisteredSystem(filter, run, { phase = 'step', initialResult = undefined, } = {}) { | ||
function sys(game) { | ||
@@ -17,7 +17,12 @@ const query = game.queryManager.create(filter); | ||
} | ||
return sys; | ||
} | ||
export function system(filter, run, options) { | ||
const sys = unregisteredSystem(filter, run, options); | ||
allSystems.push(sys); | ||
return sys; | ||
} | ||
system.unregistered = unregisteredSystem; | ||
/** @deprecated - use system */ | ||
export const makeSystem = system; | ||
//# sourceMappingURL=System.js.map |
{ | ||
"name": "0g", | ||
"version": "0.3.4", | ||
"version": "0.4.0", | ||
"description": "", | ||
@@ -5,0 +5,0 @@ "type": "module", |
@@ -7,3 +7,3 @@ import { EventSubscriber } from '@a-type/utils'; | ||
export type ArchetypeEvents = { | ||
entityAdded(entity: Entity<any, any>): any; | ||
entityAdded(entity: Entity<any>): any; | ||
entityRemoved(entityId: number): any; | ||
@@ -23,3 +23,3 @@ }; | ||
> extends EventSubscriber<ArchetypeEvents> { | ||
private entities = new Array<Entity<T[number], any>>(); | ||
private entities = new Array<Entity<T[number]>>(); | ||
/** Maps entity ID -> index in entity array */ | ||
@@ -54,3 +54,3 @@ private entityIndexLookup = new Array<number | undefined>(); | ||
addEntity(entity: Entity<any, any>) { | ||
addEntity(entity: Entity<any>) { | ||
// this is the index ("column") of this entity in the table | ||
@@ -57,0 +57,0 @@ const index = this.entities.length; |
@@ -40,3 +40,4 @@ import { EventSubscriber } from '@a-type/utils'; | ||
const lookupIndex = getIdSignifier(entityId); | ||
return this.entityLookup[lookupIndex]; | ||
const arch = this.entityLookup[lookupIndex]; | ||
return arch; | ||
} | ||
@@ -128,4 +129,4 @@ private setEntityArchetype(entityId: number, archetypeId: string) { | ||
destroyEntity(entityId: number) { | ||
this.game.logger.debug(`Destroying entity ${entityId}`); | ||
removeEntity(entityId: number) { | ||
this.game.logger.debug(`Removing entity ${entityId} from all archetypes`); | ||
const archetypeId = this.lookupEntityArchetype(entityId); | ||
@@ -148,3 +149,3 @@ if (archetypeId === undefined) { | ||
if (archetypeId === undefined) { | ||
this.game.logger.debug(`Could not find Archetype for Entity ${entityId}`); | ||
this.game.logger.error(`Could not find Entity ${entityId}`); | ||
return null; | ||
@@ -151,0 +152,0 @@ } |
@@ -13,13 +13,7 @@ import { | ||
Present extends ComponentHandle, | ||
Omitted extends ComponentHandle, | ||
Handle extends ComponentHandle, | ||
> = Handle extends Present | ||
? InstanceFor<Handle> | ||
: Handle extends Omitted | ||
? never | ||
: InstanceFor<Handle> | null; | ||
> = Handle extends Present ? InstanceFor<Handle> : InstanceFor<Handle> | null; | ||
export class Entity< | ||
DefiniteComponents extends ComponentHandle = ComponentHandle, | ||
OmittedComponents extends ComponentHandle = any, | ||
> { | ||
@@ -77,5 +71,5 @@ private _id = 0; | ||
handle: T, | ||
): DefinedInstance<DefiniteComponents, OmittedComponents, T> => { | ||
): DefinedInstance<DefiniteComponents, T> => { | ||
const instance = (this.components.get(handle.id) ?? | ||
null) as DefinedInstance<DefiniteComponents, OmittedComponents, T>; | ||
null) as DefinedInstance<DefiniteComponents, T>; | ||
console.assert( | ||
@@ -82,0 +76,0 @@ !instance || instance.id !== 0, |
@@ -184,3 +184,15 @@ import { QueryManager } from './QueryManager.js'; | ||
*/ | ||
remove = <T extends ComponentHandle>(entity: number | Entity, Type: T) => { | ||
remove = <T extends ComponentHandle, E extends Entity<any>>( | ||
entity: number | E, | ||
Type: T, | ||
) => { | ||
if (!(typeof entity === 'number')) { | ||
// ignore removed entities, their components | ||
// are already gone. | ||
if (entity.removed) { | ||
return; | ||
} | ||
// TODO: find a way to do this when the | ||
// arg isn't an entity | ||
} | ||
const entityId = typeof entity === 'number' ? entity : entity.id; | ||
@@ -266,2 +278,3 @@ this.enqueueStepOperation({ | ||
this.entityPool.release(entity); | ||
this.logger.debug('Destroyed entity', entity.id); | ||
}; | ||
@@ -298,2 +311,14 @@ | ||
this.logger.debug( | ||
'Removing component', | ||
operation.componentType, | ||
'from entity', | ||
operation.entityId, | ||
); | ||
// if entity was removed already, it won't | ||
// be in archetypes anymore, and the component | ||
// will be released in the removal process. | ||
if (this._removedList.get(operation.entityId)) break; | ||
instance = this.archetypeManager.removeComponent( | ||
@@ -317,3 +342,3 @@ operation.entityId, | ||
entity = this.archetypeManager.destroyEntity(operation.entityId); | ||
entity = this.archetypeManager.removeEntity(operation.entityId); | ||
@@ -320,0 +345,0 @@ this._removedList.add(entity); |
export * from './Game.js'; | ||
export * from './Query.js'; | ||
export * from './Component2.js'; | ||
export { system } from './System.js'; | ||
export { system, type SystemRunner } from './System.js'; | ||
export * from './filters.js'; | ||
@@ -10,2 +10,3 @@ export { effect } from './Effect.js'; | ||
export { setup } from './Setup.js'; | ||
export type { EntityImpostorFor } from './QueryIterator.js'; | ||
@@ -12,0 +13,0 @@ export interface Globals {} |
@@ -0,10 +1,14 @@ | ||
export type LogLevel = 'info' | 'warn' | 'error' | 'debug'; | ||
export class Logger { | ||
static readonly levels = ['debug', 'info', 'warn', 'error'] as const; | ||
static readonly levels: LogLevel[] = [ | ||
'debug', | ||
'info', | ||
'warn', | ||
'error', | ||
] as const; | ||
private lvl = 2; | ||
doLog = ( | ||
level: 'info' | 'warn' | 'error' | 'debug', | ||
...messages: unknown[] | ||
) => { | ||
doLog = (level: LogLevel, ...messages: unknown[]) => { | ||
if (Logger.levels.indexOf(level) >= this.lvl) { | ||
@@ -15,3 +19,3 @@ console[level](...messages); | ||
constructor(level: 'info' | 'warn' | 'error' | 'debug') { | ||
constructor(level: LogLevel) { | ||
this.lvl = Logger.levels.indexOf(level); | ||
@@ -18,0 +22,0 @@ } |
@@ -39,2 +39,6 @@ import { Game } from './Game.js'; | ||
private unsubscribeArchetypes: (() => void) | undefined = undefined; | ||
private _generation = 0; | ||
get generation() { | ||
return this._generation; | ||
} | ||
@@ -134,2 +138,3 @@ constructor(private game: Game) { | ||
this.addToList(entity.id); | ||
this._generation++; | ||
}; | ||
@@ -139,2 +144,3 @@ | ||
this.removeFromList(entityId); | ||
this._generation++; | ||
}; | ||
@@ -173,2 +179,6 @@ | ||
get count() { | ||
return this.trackedEntities.length; | ||
} | ||
private addToList = (entityId: number) => { | ||
@@ -175,0 +185,0 @@ this.trackedEntities.push(entityId); |
@@ -23,9 +23,4 @@ import { ComponentHandle } from './Component2.js'; | ||
type OmittedComponentsFromFilter<Fil extends QueryComponentFilter> = OnlyNots< | ||
Fil[number] | ||
>; | ||
export type EntityImpostorFor<Q extends QueryComponentFilter> = Entity< | ||
DefiniteComponentsFromFilter<Q>, | ||
OmittedComponentsFromFilter<Q> | ||
DefiniteComponentsFromFilter<Q> | ||
>; | ||
@@ -37,3 +32,3 @@ | ||
private archetypeIndex = 0; | ||
private archetypeIterator: Iterator<Entity<any, any>> | null = null; | ||
private archetypeIterator: Iterator<Entity<any>> | null = null; | ||
private result: IteratorResult<EntityImpostorFor<Def>> = { | ||
@@ -40,0 +35,0 @@ done: true, |
@@ -7,3 +7,3 @@ import { Game } from './Game.js'; | ||
type SystemRunner<Filter extends QueryComponentFilter, Result> = ( | ||
export type SystemRunner<Filter extends QueryComponentFilter, Result> = ( | ||
entity: EntityImpostorFor<Filter>, | ||
@@ -14,3 +14,3 @@ game: Game, | ||
export function system<Filter extends QueryComponentFilter, Result = void>( | ||
function unregisteredSystem<Filter extends QueryComponentFilter, Result = void>( | ||
filter: Filter, | ||
@@ -44,6 +44,20 @@ run: SystemRunner<Filter, Result>, | ||
return sys; | ||
} | ||
export function system<Filter extends QueryComponentFilter, Result = void>( | ||
filter: Filter, | ||
run: SystemRunner<Filter, Result>, | ||
options?: { | ||
phase?: 'step' | 'preStep' | 'postStep' | (string & {}); | ||
initialResult?: Result; | ||
}, | ||
) { | ||
const sys = unregisteredSystem(filter, run, options); | ||
allSystems.push(sys); | ||
return sys; | ||
} | ||
system.unregistered = unregisteredSystem; | ||
/** @deprecated - use system */ | ||
export const makeSystem = system; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
266229
5004