Update framework

This commit is contained in:
2022-11-26 02:22:02 +01:00
parent 9a6ce1f832
commit ae057940af
508 changed files with 26011 additions and 14248 deletions

12
framework/ecs/component.d.ts vendored Normal file
View File

@@ -0,0 +1,12 @@
export declare class BaseComponent {
id: number;
properties: any;
constructor();
clone(): BaseComponent;
}
export interface Component {
id: number;
properties: any;
clone(): BaseComponent;
new (): BaseComponent;
}

View File

@@ -0,0 +1,11 @@
export class BaseComponent {
constructor() {
this.id = 0;
this.properties = {};
}
clone() {
const comp = new BaseComponent();
comp.properties = this.properties;
return comp;
}
}

19
framework/ecs/entity.d.ts vendored Normal file
View File

@@ -0,0 +1,19 @@
import { BaseComponent, Component } from './component';
export declare class BaseEntity {
id: number;
components: Map<number, BaseComponent>;
constructor();
addComponent(component: Component): void;
removeComponent(component: BaseComponent): void;
getComponentIDs(): number[];
getComponent(component: BaseComponent): BaseComponent;
getComponentByID(id: number): BaseComponent;
}
export interface Entity {
new (): BaseComponent;
addComponent(component: Component): any;
removeComponent(component: BaseComponent): any;
getComponentIDs(): number[];
getComponent(component: BaseComponent): any;
getComponentByID(id: number): BaseComponent;
}

23
framework/ecs/entity.js Normal file
View File

@@ -0,0 +1,23 @@
export class BaseEntity {
constructor() {
this.components = new Map();
this.id = 0;
}
addComponent(component) {
let comp = new component();
comp.id = component.id;
this.components.set(component.id, comp);
}
removeComponent(component) {
this.components.delete(component.id);
}
getComponentIDs() {
return [...this.components.keys()];
}
getComponent(component) {
return this.components.get(component.id);
}
getComponentByID(id) {
return this.components.get(id);
}
}

28
framework/ecs/index.d.ts vendored Normal file
View File

@@ -0,0 +1,28 @@
import { Component } from './component';
import { BaseEntity, Entity } from './entity';
import { EventBus } from '../event-bus';
import { Query } from './query';
import { System } from './system';
export declare class World {
entities: Array<BaseEntity>;
components: Map<number, Component>;
componentNamesToIDs: Map<string, number>;
systems: Set<System>;
nextEntityID: number;
nextComponentID: number;
nextQueryID: number;
queryCache: Array<Query>;
eventBus: EventBus;
constructor();
run(): void;
createSystem(systemExecutor: Function): void;
addSystem(system: System): void;
addEntity(entity: BaseEntity): void;
removeEntity(entityToRemove: BaseEntity): void;
createEntity(components: Array<Component>): BaseEntity;
extendEntity(entity: Entity, components: Array<Component>): BaseEntity;
createComponent(component: Component): Component;
query(include: Array<Component>, exclude: Array<Component>): Array<BaseEntity>;
createQuery(include: Array<Component>, exclude: Array<Component>): Query;
markQueriesDirty(): void;
}

105
framework/ecs/index.js Normal file
View File

@@ -0,0 +1,105 @@
import { BaseEntity } from './entity';
import { EventBus } from '../event-bus';
import { Query } from './query';
import { System } from './system';
export class World {
constructor() {
this.nextEntityID = 0;
this.nextComponentID = 0;
this.nextQueryID = 0;
this.entities = new Array();
this.systems = new Set();
this.components = new Map();
this.componentNamesToIDs = new Map();
this.queryCache = new Array();
this.eventBus = new EventBus();
}
run() {
this.systems.forEach((system) => {
system.execute(this);
});
}
createSystem(systemExecutor) {
const newSystem = new System(systemExecutor);
this.systems.add(newSystem);
}
addSystem(system) {
this.systems.add(system);
}
addEntity(entity) {
this.entities.push(entity);
this.markQueriesDirty();
}
removeEntity(entityToRemove) {
this.entities = this.entities.filter((entity) => entity !== entityToRemove);
this.markQueriesDirty();
}
createEntity(components) {
const newEntity = new BaseEntity();
newEntity.id = this.nextEntityID;
this.nextEntityID++;
components.forEach((component) => {
if (this.componentNamesToIDs.has(component.name)) {
component.id = this.componentNamesToIDs.get(component.name);
}
else {
this.componentNamesToIDs.set(component.name, this.nextComponentID);
component.id = this.nextComponentID;
this.nextComponentID++;
}
newEntity.addComponent(component);
});
this.entities.push(newEntity);
this.markQueriesDirty();
return newEntity;
}
extendEntity(entity, components) {
const toClone = this.entities.find((found) => entity.name === found.constructor.name);
const cloned = new BaseEntity();
cloned.id = this.nextEntityID;
this.nextEntityID++;
toClone.components.forEach((component) => {
cloned.addComponent(this.components.get(component.id));
});
components.forEach((component) => {
if (this.componentNamesToIDs.has(component.name)) {
component.id = this.componentNamesToIDs.get(component.name);
}
else {
this.componentNamesToIDs.set(component.name, this.nextComponentID);
component.id = this.nextComponentID;
this.nextComponentID++;
}
cloned.addComponent(component);
});
this.entities.push(cloned);
return cloned;
}
createComponent(component) {
const newComponent = component;
newComponent.id = this.nextComponentID;
this.nextComponentID++;
this.components.set(newComponent.id, newComponent);
this.componentNamesToIDs.set(component.name, component.id);
return newComponent;
}
query(include, exclude) {
const query = new Query(include, exclude, this);
const cache = this.queryCache.find((item) => item.include == include && item.exclude == exclude);
if (cache) {
return cache.execute();
}
this.queryCache.push(query);
return query.execute();
}
createQuery(include, exclude) {
const newQuery = new Query(include, exclude, this);
newQuery.id = this.nextQueryID;
this.nextQueryID++;
this.queryCache.push(newQuery);
return newQuery;
}
markQueriesDirty() {
this.queryCache.forEach((query) => (query.isDirty = true));
}
}

15
framework/ecs/query.d.ts vendored Normal file
View File

@@ -0,0 +1,15 @@
import { World } from '.';
import { Component } from './component';
import { BaseEntity } from './entity';
export declare class Query {
include: Array<Component>;
exclude: Array<Component>;
world: World;
id: number;
private results;
isDirty: boolean;
includeComponentIds: number[];
excludeComponentIds: number[];
constructor(include: Array<Component>, exclude: Array<Component>, world: World);
execute(): Array<BaseEntity>;
}

34
framework/ecs/query.js Normal file
View File

@@ -0,0 +1,34 @@
export class Query {
constructor(include, exclude, world) {
this.include = include;
this.exclude = exclude;
this.world = world;
this.isDirty = true;
this.results = new Array();
this.includeComponentIds = include.map((component) => component.id);
this.excludeComponentIds = exclude.map((component) => component.id);
this.id = 0;
}
execute() {
if (!this.isDirty && this.results) {
return this.results;
}
let filtered;
this.includeComponentIds = this.include.map((component) => this.world.componentNamesToIDs.get(component.name));
this.excludeComponentIds = this.exclude.map((component) => this.world.componentNamesToIDs.get(component.name));
const entities = this.world.entities.filter((entity) => {
let ids = entity.getComponentIDs();
// let includes = ids.map(id => this.includeComponentIds.includes(id)).includes(true);
let excludes = ids
.map((id) => this.excludeComponentIds.includes(id))
.includes(true);
let includes = ids.filter((id) => this.includeComponentIds.includes(id));
return includes.length === this.includeComponentIds.length && !excludes;
});
if (entities.length > 0) {
this.isDirty = false;
this.results = entities;
}
return entities;
}
}

6
framework/ecs/system.d.ts vendored Normal file
View File

@@ -0,0 +1,6 @@
import { World } from '.';
export declare class System {
executor: Function;
constructor(executor: Function);
execute(world: World): void;
}

10
framework/ecs/system.js Normal file
View File

@@ -0,0 +1,10 @@
export class System {
constructor(executor) {
this.executor = executor;
}
execute(world) {
if (this.executor) {
this.executor(world);
}
}
}