diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..537ac33 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,6 @@ +{ + "printWidth": 120, + "tabWidth": 4, + "trailingComma": "all", + "useTabs": true +} diff --git a/src/index.d.ts b/src/index.d.ts index 9dc71af..53d436c 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -1,218 +1,213 @@ -/** - * Represents an entity - * The generic type T defines the data type when this entity is used as a component - */ -export type Entity = number & { __T: T }; - -export type Pair = number; - -export type Id = Entity | Pair; - -type FlattenTuple = T extends [infer U] ? U : LuaTuple; -type Nullable = { [K in keyof T]: T[K] | undefined }; -type InferComponents = { [K in keyof A]: A[K] extends Id ? T : never }; -type TupleForWorldGet = [Id] | [Id, Id] | [Id, Id, Id] | [Id, Id, Id, Id]; - -type Item = (this: Query) => LuaTuple<[Entity, ...T]>; - -export type Query = { - /** - * Get the next result in the query. Drain must have been called beforehand or otherwise it will error. - */ - next: Item; - - /** - * Resets the Iterator for a query. - */ - drain: (this: Query) => Query; - - /** - * Modifies the query to include specified components, but will not include the values. - * @param components The components to include - * @returns Modified Query - */ - with: (this: Query, ...components: Id[]) => Query; - - /** - * Modifies the Query to exclude specified components - * @param components The components to exclude - * @returns Modified Query - */ - without: (this: Query, ...components: Id[]) => Query; - - /** - * Modifies component data with a callback function - * @param fn The function to modify data - */ - replace: (this: Query, fn: (...components: T) => FlattenTuple) => void; - - /** - * Returns the archetypes associated with this query. - */ - archetypes: () => Archetype[]; -} & IterableFunction>; - -export type Archetype = { - id: number; - edges: { [key: number]: ArchetypeEdge }; - types: number[]; - type: string | number; - entities: number[]; - columns: unknown[][]; - records: { [key: number]: ArchetypeRecord }; -}; - -type ArchetypeRecord = { - count: number; - column: number; -}; - -type ArchetypeEdge = { - add: Archetype; - remove: Archetype; -}; - -export class World { - /** - * Creates a new World - */ - constructor(); - - /** - * Creates a new entity - * @returns Entity - */ - entity(): Entity; - - /** - * Creates a new entity located in the first 256 ids. - * These should be used for static components for fast access. - * @returns Entity - */ - component(): Entity; - - /** - * Gets the target of a relationship. For example, when a user calls - * `world.target(entity, ChildOf(parent))`, you will obtain the parent entity. - * @param entity Entity - * @param index Target index - * @param relation The Relationship - * @returns The Parent Entity if it exists - */ - target(entity: Entity, relation: Entity, index: number): Entity | undefined; - - /** - * Gets the target of a relationship. For example, when a user calls - * `world.target(entity, ChildOf(parent))`, you will obtain the parent entity. - * @param entity Entity - * @param relation The Relationship - * @returns The Parent Entity if it exists - */ - target(entity: Entity, relation: Entity): Entity | undefined; - - /** - * Clears an entity from the world. - * @param entity Entity to be cleared - */ - clear(entity: Entity): void; - - /** - * Deletes an entity and all its related components and relationships. - * @param entity Entity to be destroyed - */ - delete(entity: Entity): void; - - /** - * Adds a component to the entity with no value - * @param entity Target Entity - * @param component Component - */ - add(entity: Entity, component: Id): void; - - /** - * Assigns a value to a component on the given entity - * @param entity Target Entity - * @param component Target Component - * @param data Component Data - */ - set(entity: Entity, component: Id, data: NoInfer): void; - - /** - * Removes a component from the given entity - * @param entity Target Entity - * @param component Target Component - */ - remove(entity: Entity, component: Id): void; - - /** - * Retrieves the values of specified components for an entity. - * Some values may not exist when called. - * A maximum of 4 components are allowed at a time. - * @param id Target Entity - * @param components Target Components - * @returns Data associated with target components if it exists. - */ - get(id: Entity, ...components: T): FlattenTuple>>; - - /** - * Returns whether the entity has the specified components. - * A maximum of 4 components are allowed at a time. - * @param entity Target Entity - * @param components Target Components - * @returns If the entity contains the components - */ - has(entity: Entity, ...components: Id[]): boolean; - - /** - * Checks if an entity exists in the world - * @param entity Entity to check - * @returns Whether the entity exists in the world - */ - contains(entity: Entity): boolean; - - /** - * Searches the world for entities that match a given query - * @param components Queried Components - * @returns Query - */ - query(...components: T): Query>; - - /** - * Get parent (target of ChildOf relationship) for entity. - * If there is no ChildOf relationship pair, it will return undefined. - * @param entity Target Entity - * @returns Parent Entity or undefined - */ - parent(entity: Entity): Entity | undefined; -} - -/** - * Creates a composite key. - * @param pred The first entity - * @param obj The second entity - * @returns The composite key - */ -export function pair(pred: Entity, obj: Entity): Pair; - -/** - * Checks if the entity is a composite key - * @param e The entity to check - * @returns If the entity is a pair - */ -export function IS_PAIR(e: Id): boolean; - -/** Built-in Component used to find every component id */ -export const Component: Entity; - -export const OnAdd: Entity<(e: Entity) => void>; -export const OnRemove: Entity<(e: Entity) => void>; -export const OnSet: Entity<(e: Entity, value: unknown) => void>; -export const ChildOf: Entity; -export const Wildcard: Entity; -export const w: Entity; -export const OnDelete: Entity; -export const OnDeleteTarget: Entity; -export const Delete: Entity; -export const Remove: Entity; -export const Name: Entity; -export const Rest: Entity; +/** + * A unique identifier in the world, entity. + * The generic type T defines the data type when this entity is used as a component + */ +export type Entity = number & { __jecs_value: T }; + +/** + * An entity with no associated data when used as a component + */ +export type Tag = Entity; + +/** + * A pair of entities + * P is the type of the predicate, O is the type of the object, and V is the type of the value (defaults to P) + */ +export type Pair

= number & { + __jecs_pair_pred: P; + __jecs_pair_obj: O; + __jecs_pair_value: V; +}; + +/** + * Either an Entity or a Pair + */ +export type Id = Entity | Pair; + +type InferComponent = E extends Id ? T : never; +type FlattenTuple = T extends [infer U] ? U : LuaTuple; +type Nullable = { [K in keyof T]: T[K] | undefined }; +type InferComponents = { + [K in keyof A]: InferComponent; +}; +type TupleForWorldGet = [Id] | [Id, Id] | [Id, Id, Id] | [Id, Id, Id, Id]; + +type Iter = IterableFunction>; + +export type Query = { + /** + * Returns an iterator that returns a tuple of an entity and queried components + */ + iter(): Iter; + + /** + * Modifies the query to include specified components + * @param components The components to include + * @returns Modified Query + */ + with(...components: Id[]): Query; + + /** + * Modifies the Query to exclude specified components + * @param components The components to exclude + * @returns Modified Query + */ + without(...components: Id[]): Query; +} & Iter; + +export class World { + /** + * Creates a new World + */ + constructor(); + + /** + * Creates a new entity + * @returns Entity + */ + entity(): Tag; + + /** + * Creates a new entity located in the first 256 ids. + * These should be used for static components for fast access. + * @returns Entity + */ + component(): Entity; + + /** + * Gets the target of a relationship. For example, when a user calls + * `world.target(entity, ChildOf(parent))`, you will obtain the parent entity. + * @param entity Entity + * @param relation The Relationship + * @returns The Parent Entity if it exists + */ + target(entity: Entity, relation: Entity): Entity | undefined; + + /** + * Gets the target of a relationship at a specific index. + * For example, when a user calls `world.target(entity, ChildOf(parent), 0)`, + * you will obtain the parent entity. + * @param entity Entity + * @param relation The Relationship + * @param index Target index + * @returns The Parent Entity if it exists + */ + target(entity: Entity, relation: Entity, index: number): Entity | undefined; + + /** + * Clears an entity from the world + * @param entity Entity to be cleared + */ + clear(entity: Entity): void; + + /** + * Deletes an entity and all its related components and relationships + * @param entity Entity to be destroyed + */ + delete(entity: Entity): void; + + /** + * Adds a component to the entity with no value + * @param entity Target Entity + * @param component Component + */ + add(entity: Entity, component: Id): void; + + /** + * Assigns a value to a component on the given entity + * @param entity Target Entity + * @param component Target Component + * @param value Component Value + */ + set>(entity: Entity, component: E, value: InferComponent): void; + + /** + * Removes a component from the given entity + * @param entity Target Entity + * @param component Target Component + */ + remove(entity: Entity, component: Id): void; + + /** + * Retrieves the values of specified components for an entity. + * Some values may not exist when called. + * A maximum of 4 components are allowed at a time. + * @param id Target Entity + * @param components Target Components + * @returns Data associated with target components if it exists. + */ + get(id: Entity, ...components: T): FlattenTuple>>; + + /** + * Returns whether the entity has the specified components. + * A maximum of 4 components are allowed at a time. + * @param entity Target Entity + * @param components Target Components + * @returns If the entity contains the components + */ + has(entity: Entity, ...components: Id[]): boolean; + + /** + * Checks if an entity exists in the world + * @param entity Entity to check + * @returns Whether the entity exists in the world + */ + contains(entity: Entity): boolean; + + /** + * Get parent (target of ChildOf relationship) for entity. + * If there is no ChildOf relationship pair, it will return undefined. + * @param entity Target Entity + * @returns Parent Entity or undefined + */ + parent(entity: Entity): Entity | undefined; + + /** + * Searches the world for entities that match a given query + * @param components Queried Components + * @returns Query + */ + query(...components: T): Query>; +} + +/** + * Creates a composite key (pair) + * @param pred The first entity (predicate) + * @param obj The second entity (object) + * @returns The composite key (pair) + */ +export function pair(pred: Entity

, obj: Entity): Pair; + +/** + * Checks if the entity is a composite key (pair) + * @param value The entity to check + * @returns If the entity is a pair + */ +export function IS_PAIR(value: Id): value is Pair; + +/** + * Gets the first entity (predicate) of a pair + * @param pair The pair to get the first entity from + * @returns The first entity (predicate) of the pair + */ +export function pair_first(pair: Pair): Entity

; + +/** + * Gets the second entity (object) of a pair + * @param pair The pair to get the second entity from + * @returns The second entity (object) of the pair + */ +export function pair_second(pair: Pair): Entity; + +export const OnAdd: Entity<(e: Entity) => void>; +export const OnRemove: Entity<(e: Entity) => void>; +export const OnSet: Entity<(e: Entity, value: unknown) => void>; +export const ChildOf: Entity; +export const Wildcard: Entity; +export const w: Entity; +export const OnDelete: Entity; +export const OnDeleteTarget: Entity; +export const Delete: Entity; +export const Remove: Entity; +export const Name: Entity; +export const Rest: Entity;