@game-vir/entity
Version:
Entity system for game development.
162 lines (161 loc) • 7.48 kB
TypeScript
import { type AnyObject, type ArrayElement, type Values } from '@augment-vir/common';
import { type ShapeDefinition } from 'object-shape-tester';
import { type Constructor } from 'type-fest';
import { BaseEntity, type EntityDestroyEvent, EntityStore, type EntityStoreConstructorParams, type ParamsMap, type ReverseParamsMap, ViewEntity } from './entity.js';
/**
* Params for both {@link EntitySuite.defineEntity} and {@link EntitySuite.defineLogicEntity}.
*
* @category Internal
*/
export type DefineEntityParams<EntityKey extends string, Shape extends ShapeDefinition<AnyObject, any> | undefined, Events extends ReadonlyArray<Constructor<Event>> = never> = {
/**
* This key is used for deserialization of entities to track which class needs to be
* constructed. Do not use duplicate key strings across multiple entity classes.
*/
key: EntityKey;
/**
* This should contain all parameters necessary to reconstruct this entity from scratch so it
* can be serialized, sent across the network in JSON format, then reconstructed on another
* device (for multiplayer support).
*
* Make sure to include {@link entityPositionParamsShape} if you want to include the base entity
* position parameters.
*/
paramsShape: Shape;
/**
* All events that this entity can emit, in addition to the default {@link EntityDestroyEvent}
* event.
*/
events?: Events | undefined;
/**
* A mapping of the entity's params object (defined by {@link DefineEntityParams.paramsShape})
* keys to hitbox and/or view properties.
*
* @default undefined // no mapping
*/
paramsMap?: ParamsMap<Shape extends ShapeDefinition<AnyObject, any> ? Shape['runtimeType'] : undefined> | undefined;
};
/**
* Static members of both view and logic entity constructors.
*
* @category Internal
*/
export type StaticEntity<EntityKey, Shape extends ShapeDefinition<AnyObject, any> | undefined> = {
/**
* This key is used for deserialization of entities to track which class needs to be
* constructed. You cannot have duplicate keys loaded at the same time.
*/
entityKey: EntityKey;
/** Shape definition of this entity's parameters. */
paramsShape: Shape;
/**
* Defines which properties from {@link BaseEntity.params} will be mapped to hitbox and/or view
* properties.
*/
paramsMap: ParamsMap<Shape extends ShapeDefinition<AnyObject, any> ? Shape['runtimeType'] : undefined>;
/** Parses the serialized params generated by {@link BaseEntity.serialize}. */
deserialize(serialized: string | undefined): AnyObject | undefined;
};
/**
* ========================
*
* # View Entity
*
* Types for entity definitions that have a view.
*
* ========================
*/
/**
* The constructor output of {@link DefinedViewEntityConstructor}.
*
* @category Internal
*/
export type DefinedViewEntityInstance<Context, Shape extends ShapeDefinition<AnyObject, any> | undefined, Events extends Readonly<Event>> = ViewEntity<Context, Shape extends ShapeDefinition<AnyObject, any> ? Shape['runtimeType'] : undefined, Events>;
/**
* Output of {@link DefineViewEntity}.
*
* @category Internal
*/
export type DefinedViewEntityConstructor<EntityKey, Context, Shape extends ShapeDefinition<AnyObject, any> | undefined, Events extends Readonly<Event>> = Constructor<DefinedViewEntityInstance<Context, Shape, Events>, ConstructorParameters<typeof ViewEntity<Context, Shape extends ShapeDefinition<AnyObject, any> ? Shape['runtimeType'] : undefined>>> & StaticEntity<EntityKey, Shape>;
/**
* Type for {@link EntitySuite.defineEntity}.
*
* @category Internal
*/
export type DefineViewEntity<Context> = <const EntityKey extends string, const Shape extends ShapeDefinition<AnyObject, any> | undefined, const Events extends ReadonlyArray<Constructor<Event>> = never>(params: DefineEntityParams<EntityKey, Shape, Events>) => DefinedViewEntityConstructor<EntityKey, Context, Shape, InstanceType<ArrayElement<NoInfer<Events>>> | EntityDestroyEvent>;
/**
* ========================
*
* # Logic Entity
*
* Types for entity definitions that don't have a view. The only difference between these types and
* the view types are that this uses `BaseEntity` instead of `ViewEntity.
*
* ========================
*/
/**
* The constructor output of {@link DefinedLogicEntityConstructor}.
*
* @category Internal
*/
export type DefinedLogicEntityInstance<Context, Shape extends ShapeDefinition<AnyObject, any> | undefined, Events extends Readonly<Event>> = BaseEntity<Context, Shape extends ShapeDefinition<AnyObject, any> ? Shape['runtimeType'] : undefined, Events>;
/**
* Output of {@link DefineLogicEntity}.
*
* @category Internal
*/
export type DefinedLogicEntityConstructor<EntityKey, Context, Shape extends ShapeDefinition<AnyObject, any> | undefined, Events extends Readonly<Event>> = Constructor<DefinedLogicEntityInstance<Context, Shape, Events>, ConstructorParameters<typeof BaseEntity<Context, Shape extends ShapeDefinition<AnyObject, any> ? Shape['runtimeType'] : undefined>>> & StaticEntity<EntityKey, Shape>;
/**
* Type for {@link EntitySuite.defineEntity}.
*
* @category Internal
*/
export type DefineLogicEntity<Context> = <const EntityKey extends string, const Shape extends ShapeDefinition<AnyObject, any> | undefined, const Events extends ReadonlyArray<Constructor<Event>> = never>(params: DefineEntityParams<EntityKey, Shape, Events>) => DefinedLogicEntityConstructor<EntityKey, Context, Shape, InstanceType<ArrayElement<NoInfer<Events>>> | EntityDestroyEvent>;
/**
* ========================
*
* # Entity Suite
*
* ========================
*/
/**
* Output of {@link defineEntitySuite}, used to defining and creating entities.
*
* @category Internal
*/
export type EntitySuite<Context> = {
/**
* The suite's entity store constructor. Instantiate this and to add your first entities.
*
* All defined entities will also have a reference to this store so they can add additional
* entities by themselves.
*/
EntityStore: new <const RegisteredEntities extends Values<EntityStore['entityKeyConstructorMap']>>(params: Readonly<EntityStoreConstructorParams<Context, RegisteredEntities>>) => EntityStore<Context, RegisteredEntities>;
/**
* Define a standard entity (with a view). This is intended to be extended from your entity
* class.
*/
defineEntity: DefineViewEntity<Context>;
/** Define an entity that doesn't have an attached view. These are likely to be rare. */
defineLogicEntity: DefineLogicEntity<Context>;
/**
* A set of entity keys used within this entity suite. This will only be populated by all
* classes that are defined with `defineEntity` or `defineLogicEntity` (so this will miss any
* not-yet-resolved dynamic imports). This will be populated even before the classes are ever
* instantiated.
*/
entityKeys: Set<string>;
};
/**
* This is the starting point of the @game-vir/entity package. Call this to produce the function
* needed to define new entities and the store needed to add entity instances.
*
* @category Main
*/
export declare function defineEntitySuite<Context = undefined>(): EntitySuite<Context>;
/**
* Converts {@link ParamsMap} to {@link ReverseParamsMap}.
*
* @category Internal
*/
export declare function reverseParamsMap(paramsMap: ParamsMap | undefined): ReverseParamsMap | undefined;