Files
yawn/core/ecs/ecs.ts
T
Heaust Azure 9d2bf4055d added a shitty ecs that I'm confident is way worse than just looping … (#4)
* added a shitty ecs that I'm confident is way worse than just looping objects lol

* mader a rendering system based on ecs
2025-05-06 18:53:21 +05:30

111 lines
2.6 KiB
TypeScript

type ComponentMap<CT> = {
uid: (number | null)[];
} & {
[K in keyof CT]?: Array<CT[K] | null>;
};
namespace ECS {
export type System<ComponentsType extends Record<string | number, any>> = (
arg: ComponentsType & { uid: (number | null)[] },
) => Partial<ComponentsType> | null;
}
class ECS<ComponentsType extends Record<string | number, any>> {
private components: ComponentMap<ComponentsType> = { uid: [] };
private componentDefaults: Record<
string,
null | ComponentsType[keyof ComponentsType]
> = { uid: null };
private systems: Record<string, ECS.System<ComponentsType>> = {};
/**
* System
*/
runSystems() {
const limit = this.components.uid.length;
for (let i = 0; i < limit; i++) {
const obj = {} as Record<string, unknown>;
for (const key in this.components) {
obj[key] = this.components[key]![i];
}
const systems = Object.values(this.systems);
for (let j = 0; j < systems.length; j++) {
const res = systems[j](
obj as ComponentsType & { uid: (number | null)[] },
);
if (!res) continue;
for (const key in res) {
if (!this.components[key]) continue;
this.components[key][i] = res[key]!;
}
}
}
}
addSystem(system: ECS.System<ComponentsType>) {
const id = crypto.randomUUID();
this.systems[id] = system;
return id;
}
removeSystem(id: string) {
delete this.systems[id];
}
getById(uid: number) {
if (this.components.uid.length <= uid) return {};
const obj = {} as Record<string, unknown>;
for (const key in this.components) {
obj[key] = this.components[key]![uid];
}
return obj;
}
/**
* Entity
*/
addEntity(components: ComponentsType) {
for (const key in this.components) {
if (key === "uid") {
this.components[key].push(this.components[key].length);
continue;
}
this.components[key]!.push(
components[key] ?? this.componentDefaults[key],
);
}
return this.components.uid.length - 1;
}
/**
* Component
*/
addComponent(
name: keyof ComponentsType,
fillValue = null as null | ComponentsType[keyof ComponentsType],
defaultValue = null as null | ComponentsType[keyof ComponentsType],
) {
if (this.components[name]) throw new Error("Component already exists");
this.components[name] = new Array(this.components.uid.length).fill(
fillValue,
) as ComponentMap<ComponentsType>[keyof ComponentsType];
this.componentDefaults[name as string] = defaultValue;
}
removeComponent(name: keyof ComponentsType) {
delete this.components[name];
}
}
export { ECS };