Compare commits

...

3 commits

Author SHA1 Message Date
PepeElToro41
d7c31b967d
Merge f912866fcb into 65a27a798a 2025-08-12 20:39:13 +02:00
dai
65a27a798a
Separate undefined components and tags (#266)
Some checks failed
analysis / Run Luau Analyze (push) Has been cancelled
deploy-docs / build (push) Has been cancelled
publish-npm / publish (push) Has been cancelled
unit-testing / Run Luau Tests (push) Has been cancelled
deploy-docs / Deploy (push) Has been cancelled
2025-08-12 20:39:04 +02:00
PepeElToro41
f912866fcb add way to check preregistered id creations after world creation 2025-07-29 14:18:15 -06:00
2 changed files with 23 additions and 5 deletions

14
jecs.d.ts vendored
View file

@ -7,10 +7,14 @@ export type Entity<TData = unknown> = number & {
readonly __type_TData: TData; readonly __type_TData: TData;
}; };
type TagDiscriminator = {
readonly __nominal_Tag: unique symbol;
};
/** /**
* An entity with no associated data when used as a component * An entity with no associated data when used as a component
*/ */
export type Tag = Entity<undefined>; export type Tag = Entity<TagDiscriminator>;
/** /**
* A pair of entities: * A pair of entities:
@ -26,12 +30,12 @@ export type Pair<P = unknown, O = unknown> = number & {
* An `Id` can be either a single Entity or a Pair of Entities. * An `Id` can be either a single Entity or a Pair of Entities.
* By providing `TData`, you can specifically require an Id that yields that type. * By providing `TData`, you can specifically require an Id that yields that type.
*/ */
export type Id<TData = unknown> = Entity<TData> | Pair<TData, unknown> | Pair<undefined, TData>; export type Id<TData = unknown> = Entity<TData> | Pair<TData, unknown> | Pair<TagDiscriminator, TData>;
export type InferComponent<E> = E extends Entity<infer D> export type InferComponent<E> = E extends Entity<infer D>
? D ? D
: E extends Pair<infer P, infer O> : E extends Pair<infer P, infer O>
? P extends undefined ? P extends TagDiscriminator
? O ? O
: P : P
: never; : never;
@ -119,7 +123,7 @@ export class World {
* @returns An entity (Tag) with no data. * @returns An entity (Tag) with no data.
*/ */
entity(): Tag; entity(): Tag;
entity<T extends Entity>(id: T): InferComponent<T> extends undefined ? Tag : T; entity<T extends Entity>(id: T): T;
/** /**
* Creates a new entity in the first 256 IDs, typically used for static * Creates a new entity in the first 256 IDs, typically used for static
@ -148,7 +152,7 @@ export class World {
* @param entity The target entity. * @param entity The target entity.
* @param component The component (or tag) to add. * @param component The component (or tag) to add.
*/ */
add<C>(entity: Entity, component: undefined extends InferComponent<C> ? C : Id<undefined>): void; add<C>(entity: Entity, component: TagDiscriminator extends InferComponent<C> ? C : Id<TagDiscriminator>): void;
/** /**
* Installs a hook on the given component. * Installs a hook on the given component.

View file

@ -126,6 +126,8 @@ type world = {
max_component_id: number, max_component_id: number,
max_archetype_id: number, max_archetype_id: number,
start_component_id: number,
start_tag_id: number,
observable: Map<i53, Map<i53, { Observer }>>, observable: Map<i53, Map<i53, { Observer }>>,
@ -163,6 +165,8 @@ export type World = {
max_component_id: number, max_component_id: number,
max_archetype_id: number, max_archetype_id: number,
start_component_id: number,
start_tag_id: number,
observable: Map<Id, Map<Id, { Observer }>>, observable: Map<Id, Map<Id, { Observer }>>,
@ -760,6 +764,12 @@ local function ECS_ID_IS_WILDCARD(e: i53): boolean
return first == EcsWildcard or second == EcsWildcard return first == EcsWildcard or second == EcsWildcard
end end
local function get_max_ids_difference(world: World): (number, number)
local diff_components = world.start_component_id - ecs_max_component_id
local diff_tags = world.start_tag_id - ecs_max_tag_id
return diff_components, diff_tags
end
local function id_record_get(world: World, id: Entity): ComponentRecord? local function id_record_get(world: World, id: Entity): ComponentRecord?
local component_index = world.component_index local component_index = world.component_index
local idr: ComponentRecord = component_index[id] local idr: ComponentRecord = component_index[id]
@ -2264,6 +2274,9 @@ local function world_new()
max_archetype_id = 0, max_archetype_id = 0,
max_component_id = ecs_max_component_id, max_component_id = ecs_max_component_id,
start_component_id = ecs_max_component_id,
start_tag_id = ecs_max_tag_id,
observable = observable, observable = observable,
signals = signals, signals = signals,
} :: world } :: world
@ -3366,6 +3379,7 @@ return {
pair_first = ecs_pair_first :: <P, O>(world: World, pair: Pair<P, O>) -> Id<P>, pair_first = ecs_pair_first :: <P, O>(world: World, pair: Pair<P, O>) -> Id<P>,
pair_second = ecs_pair_second :: <P, O>(world: World, pair: Pair<P, O>) -> Id<O>, pair_second = ecs_pair_second :: <P, O>(world: World, pair: Pair<P, O>) -> Id<O>,
entity_index_get_alive = entity_index_get_alive, entity_index_get_alive = entity_index_get_alive,
get_max_ids_difference = get_max_ids_difference,
archetype_append_to_records = archetype_append_to_records, archetype_append_to_records = archetype_append_to_records,
id_record_ensure = id_record_ensure :: (World, Id) -> ComponentRecord, id_record_ensure = id_record_ensure :: (World, Id) -> ComponentRecord,