1
0
mirror of https://github.com/sehugg/8bitworkshop.git synced 2024-06-01 20:41:36 +00:00

ecs: event2system

This commit is contained in:
Steven Hugg 2022-01-31 09:17:40 -06:00
parent c54b6a1150
commit 87eb8e2f05
3 changed files with 25 additions and 33 deletions

View File

@ -37,6 +37,7 @@
var opcodes = /^[a-z][a-z][a-z]\b/i;
var numbers = /^(0x[\da-f]+|[\da-f]+h|[0-7]+o|[01]+b|\d+d?)\b/i;
var tags = /^\{\{.*\}\}/;
var comment = /\/\/.*/;
var mlcomment = /^---.+?---\b/i;
return {
@ -52,6 +53,9 @@
if (stream.match(tags)) {
return 'meta';
}
if (stream.match(comment)) {
return 'comment';
}
var w;
if (stream.eatWhile(/\w/)) {

View File

@ -1,5 +1,5 @@
import { Tokenizer, TokenType } from "../tokenizer";
import { mergeLocs, Tokenizer, TokenType } from "../tokenizer";
import { SourceLocated } from "../workertypes";
import { Action, ArrayType, ComponentType, DataField, DataType, DataValue, Dialect_CA65, Entity, EntityArchetype, EntityManager, EntityScope, IntType, Query, RefType, SelectType, SourceFileExport, System } from "./ecs";
@ -27,6 +27,7 @@ export class ECSCompiler extends Tokenizer {
{ type: ECSTokenType.Integer, regex: /[-]?\$[A-Fa-f0-9]+/ },
{ type: ECSTokenType.Integer, regex: /[-]?\d+/ },
{ type: TokenType.Ident, regex: /[A-Za-z_][A-Za-z0-9_]*/ },
{ type: TokenType.Ignore, regex: /\/\/.*/ },
{ type: TokenType.Ignore, regex: /\s+/ },
]);
this.errorOnCatchAll = true;
@ -185,10 +186,11 @@ export class ECSCompiler extends Tokenizer {
parseQuery() {
let q: Query = { include: [] };
this.expectToken('[');
let start = this.expectToken('[');
q.include = this.parseList(this.parseComponentRef, ',').map(c => c.name);
// TODO: other params
this.expectToken(']');
let end = this.expectToken(']');
q.$loc = mergeLocs(start.$loc, end.$loc);
return q;
}

View File

@ -77,7 +77,7 @@ export interface ComponentType extends SourceLocated {
optional?: boolean;
}
export interface Query {
export interface Query extends SourceLocated {
include: string[]; // TODO: make ComponentType
listen?: string[];
exclude?: string[];
@ -407,37 +407,14 @@ export class EntityScope implements SourceLocated {
}
return result;
}
getSystems(events: string[]) {
let result : System[] = [];
for (let sys of Object.values(this.em.systems)) {
if (this.systemListensTo(sys, events)) {
result.push(sys);
}
}
return result;
}
systemListensTo(sys: System, events: string[]) {
for (let action of sys.actions) {
if (action.event != null && events.includes(action.event)) {
let archs = this.em.archetypesMatching(action.query);
for (let arch of archs) {
for (let ctype of arch.cmatch) {
if (this.hasComponent(ctype)) {
return true;
}
}
}
}
}
}
hasComponent(ctype: ComponentType) {
return this.componentsInScope.has(ctype.name);
}
getJoinField(action: Action, atypes: ArchetypeMatch[], jtypes: ArchetypeMatch[]) : ComponentFieldPair {
let refs = Array.from(this.iterateArchetypeFields(atypes, (c,f) => f.dtype == 'ref'));
// TODO: better error message
if (refs.length == 0) throw new ECSError(`cannot find join fields`, action);
if (refs.length > 1) throw new ECSError(`cannot join multiple fields`, action);
if (refs.length == 0) throw new ECSError(`cannot find join fields`, action.query);
if (refs.length > 1) throw new ECSError(`cannot join multiple fields`, action.query);
// TODO: check to make sure join works
return refs[0]; // TODO
/* TODO
@ -572,8 +549,8 @@ export class EntityScope implements SourceLocated {
generateCodeForEvent(event: string): string {
// find systems that respond to event
// and have entities in this scope
let systems = this.getSystems([event]);
if (systems.length == 0) {
let systems = this.em.event2system[event];
if (!systems || systems.length == 0) {
console.log(`; warning: no system responds to ${event}`); // TODO: warning
}
let s = '';
@ -620,7 +597,6 @@ export class EntityScope implements SourceLocated {
let label = `${sys.name}__${action.event}`;
let atypes = this.em.archetypesMatching(action.query);
let entities = this.entitiesMatching(atypes);
if (entities.length == 0) throw new ECSError(`action ${label} doesn't match any entities`, action); // TODO
// TODO: detect cycles
// TODO: "source"?
// TODO: what if only 1 item?
@ -631,6 +607,8 @@ export class EntityScope implements SourceLocated {
if (action.select == 'join' && action.join) {
let jtypes = this.em.archetypesMatching(action.join);
let jentities = this.entitiesMatching(jtypes);
if (jentities.length == 0)
throw new ECSError(`join query for ${label} doesn't match any entities`, action.join); // TODO
let joinfield = this.getJoinField(action, atypes, jtypes);
// TODO: what if only 1 item?
// TODO: should be able to access fields via Y reg
@ -643,7 +621,8 @@ export class EntityScope implements SourceLocated {
if (action.limit) {
entities = entities.slice(0, action.limit);
}
if (entities.length == 0) throw new ECSError(`action ${label} doesn't match any entities`); // TODO
if (entities.length == 0)
throw new ECSError(`query for ${label} doesn't match any entities`, action.query); // TODO
// define properties
props['%elo'] = entities[0].id.toString();
props['%ehi'] = entities[entities.length - 1].id.toString();
@ -786,6 +765,7 @@ export class EntityManager {
systems: { [name: string]: System } = {};
scopes: { [name: string]: EntityScope } = {};
symbols: { [name: string] : 'init' | 'const' } = {};
event2system: { [name: string]: System[] } = {};
constructor(public readonly dialect: Dialect_CA65) {
}
@ -801,6 +781,12 @@ export class EntityManager {
}
defineSystem(system: System) {
if (this.systems[system.name]) throw new ECSError(`system ${system.name} already defined`);
for (let a of system.actions) {
let event = a.event;
let list = this.event2system[event];
if (list == null) list = this.event2system[event] = [];
if (!list.includes(system)) list.push(system);
}
return this.systems[system.name] = system;
}
addArchetype(atype: EntityArchetype) : EntityArchetype {