perf: private

This commit is contained in:
cha0s 2022-03-30 04:09:16 -05:00
parent 4d18c9223a
commit cf91c75630
40 changed files with 1439 additions and 1439 deletions

View File

@ -14,29 +14,29 @@ const STATIC_INTERVAL = 0.25;
export default (flecks) => class Behaved extends decorate(Trait) { export default (flecks) => class Behaved extends decorate(Trait) {
#accumulator = 0; $$accumulator = 0;
#collectives = []; $$collectives = [];
#context = {}; $$context = {};
#currentRoutine = ''; $$currentRoutine = '';
#daemons = {}; $$daemons = {};
#routines = {}; $$routines = {};
constructor() { constructor() {
super(); super();
({ ({
currentRoutine: this.#currentRoutine, currentRoutine: this.$$currentRoutine,
} = this.constructor.defaultState()); } = this.constructor.defaultState());
const {Script} = flecks.get('$avocado/resource.resources'); const {Script} = flecks.get('$avocado/resource.resources');
this.#context = Script.createContext(); this.$$context = Script.createContext();
} }
get context() { get context() {
return this.#context; return this.$$context;
} }
static defaultParams() { static defaultParams() {
@ -58,9 +58,9 @@ export default (flecks) => class Behaved extends decorate(Trait) {
destroy() { destroy() {
super.destroy(); super.destroy();
this.#context = {}; this.$$context = {};
this.#currentRoutine = undefined; this.$$currentRoutine = undefined;
this.#routines = undefined; this.$$routines = undefined;
} }
listeners() { listeners() {
@ -89,15 +89,15 @@ export default (flecks) => class Behaved extends decorate(Trait) {
async load(json) { async load(json) {
await super.load(json); await super.load(json);
const {Script} = flecks.get('$avocado/resource.resources'); const {Script} = flecks.get('$avocado/resource.resources');
this.#context = Script.createContext({ this.$$context = Script.createContext({
entity: this.entity, entity: this.entity,
}); });
const daemons = { const daemons = {
...this.entity.invokeHookReduced('daemons'), ...this.entity.invokeHookReduced('daemons'),
...this.params.daemons, ...this.params.daemons,
}; };
this.#daemons = Object.values(await this.constructor.loadScripts(daemons, this.#context)); this.$$daemons = Object.values(await this.constructor.loadScripts(daemons, this.$$context));
this.#routines = await this.constructor.loadScripts(this.params.routines, this.#context); this.$$routines = await this.constructor.loadScripts(this.params.routines, this.$$context);
this.updateCurrentRoutine(this.state.currentRoutine); this.updateCurrentRoutine(this.state.currentRoutine);
super.isBehaving = 'web' !== process.env.FLECKS_CORE_BUILD_TARGET; super.isBehaving = 'web' !== process.env.FLECKS_CORE_BUILD_TARGET;
} }
@ -114,23 +114,23 @@ export default (flecks) => class Behaved extends decorate(Trait) {
tick(elapsed) { tick(elapsed) {
if (this.entity.isBehaving) { if (this.entity.isBehaving) {
this.#accumulator += elapsed; this.$$accumulator += elapsed;
if (this.#accumulator >= STATIC_INTERVAL) { if (this.$$accumulator >= STATIC_INTERVAL) {
for (let i = 0; i < this.#daemons.length; ++i) { for (let i = 0; i < this.$$daemons.length; ++i) {
this.#daemons[i].tick(elapsed); this.$$daemons[i].tick(elapsed);
} }
this.#accumulator -= STATIC_INTERVAL; this.$$accumulator -= STATIC_INTERVAL;
} }
if (this.#currentRoutine) { if (this.$$currentRoutine) {
this.#currentRoutine.tick(elapsed); this.$$currentRoutine.tick(elapsed);
} }
} }
} }
updateCurrentRoutine(currentRoutine) { updateCurrentRoutine(currentRoutine) {
this.#currentRoutine = this.#routines[currentRoutine]; this.$$currentRoutine = this.$$routines[currentRoutine];
if (this.#currentRoutine) { if (this.$$currentRoutine) {
this.#currentRoutine.reset(); this.$$currentRoutine.reset();
} }
super.currentRoutine = currentRoutine; super.currentRoutine = currentRoutine;
} }

View File

@ -1,8 +1,8 @@
export default (Trait, flecks) => class DialogInitiator extends Trait { export default (Trait, flecks) => class DialogInitiator extends Trait {
#open = []; $$open = [];
#dialogs = []; $$dialogs = [];
acceptPacket(packet) { acceptPacket(packet) {
if ('OpenDialog' === packet.constructor.type) { if ('OpenDialog' === packet.constructor.type) {
@ -11,7 +11,7 @@ export default (Trait, flecks) => class DialogInitiator extends Trait {
} }
cleanPackets() { cleanPackets() {
this.#dialogs = []; this.$$dialogs = [];
} }
hooks() { hooks() {
@ -21,8 +21,8 @@ export default (Trait, flecks) => class DialogInitiator extends Trait {
acceptAction: ({action, value}) => { acceptAction: ({action, value}) => {
acceptAction({action, value}); acceptAction({action, value});
if ('Interact' === action && value) { if ('Interact' === action && value) {
if (this.#open.length > 0) { if (this.$$open.length > 0) {
this.#open[0].skip(); this.$$open[0].skip();
return false; return false;
} }
} }
@ -65,17 +65,17 @@ export default (Trait, flecks) => class DialogInitiator extends Trait {
}, },
}, },
}); });
this.#open.push(dialog); this.$$open.push(dialog);
dialog.once('destroying', () => { dialog.once('destroying', () => {
const index = this.#open.indexOf(dialog); const index = this.$$open.indexOf(dialog);
if (-1 !== index) { if (-1 !== index) {
this.#open.splice(index, 1); this.$$open.splice(index, 1);
} }
}); });
this.entity.list.addEntity(dialog); this.entity.list.addEntity(dialog);
} }
else { else {
this.#dialogs.push({ this.$$dialogs.push({
text, text,
}); });
this.markAsDirty(); this.markAsDirty();
@ -88,7 +88,7 @@ export default (Trait, flecks) => class DialogInitiator extends Trait {
packetsFor(informed) { packetsFor(informed) {
return super.packetsFor(informed).concat( return super.packetsFor(informed).concat(
informed === this.entity informed === this.entity
? this.#dialogs.map((dialog) => ['OpenDialog', dialog]) ? this.$$dialogs.map((dialog) => ['OpenDialog', dialog])
: [], : [],
); );
} }

View File

@ -2,15 +2,15 @@ export default (flecks) => {
const {Trait} = flecks.fleck('@avocado/traits'); const {Trait} = flecks.fleck('@avocado/traits');
return class Dialog extends Trait { return class Dialog extends Trait {
#dialog; $$dialog;
#letters = []; $$letters = [];
#nextLetter = 0; $$nextLetter = 0;
#thisLetter = 0; $$thisLetter = 0;
#words = []; $$words = [];
static defaultParams() { static defaultParams() {
return { return {
@ -41,14 +41,14 @@ export default (flecks) => {
const {text} = this.entity; const {text} = this.entity;
if (text) { if (text) {
({ ({
letters: this.#letters, letters: this.$$letters,
words: this.#words, words: this.$$words,
} = await flecks.get('$avocado/dialog.parser')( } = await flecks.get('$avocado/dialog.parser')(
`<rate frequency={${this.params.rate}}>${text}</rate>`, `<rate frequency={${this.params.rate}}>${text}</rate>`,
)); ));
if (this.#letters.length > 0) { if (this.$$letters.length > 0) {
this.showThisLetter(); this.showThisLetter();
this.#words.forEach((word) => { this.$$words.forEach((word) => {
// eslint-disable-next-line no-param-reassign // eslint-disable-next-line no-param-reassign
word.parentNode = this.entity.node; word.parentNode = this.entity.node;
}); });
@ -61,38 +61,38 @@ export default (flecks) => {
return { return {
skip: () => { skip: () => {
if (this.#nextLetter === Infinity) { if (this.$$nextLetter === Infinity) {
this.entity.destroy(); this.entity.destroy();
return; return;
} }
for (let i = 0; i < this.#letters.length; ++i) { for (let i = 0; i < this.$$letters.length; ++i) {
this.#letters[i].opacity = 1; this.$$letters[i].opacity = 1;
} }
this.#nextLetter = Infinity; this.$$nextLetter = Infinity;
}, },
}; };
} }
showThisLetter() { showThisLetter() {
const letter = this.#letters[this.#thisLetter]; const letter = this.$$letters[this.$$thisLetter];
this.#nextLetter += letter.rate; this.$$nextLetter += letter.rate;
letter.opacity = 1; letter.opacity = 1;
} }
tick(elapsed) { tick(elapsed) {
if ('web' === process.env.FLECKS_CORE_BUILD_TARGET) { if ('web' === process.env.FLECKS_CORE_BUILD_TARGET) {
this.#nextLetter -= elapsed; this.$$nextLetter -= elapsed;
if (this.#nextLetter <= 0) { if (this.$$nextLetter <= 0) {
this.#thisLetter += 1; this.$$thisLetter += 1;
if (this.#thisLetter >= this.#letters.length) { if (this.$$thisLetter >= this.$$letters.length) {
this.#nextLetter = Infinity; this.$$nextLetter = Infinity;
return; return;
} }
this.showThisLetter(); this.showThisLetter();
} }
for (let i = 0; i < this.#words.length; ++i) { for (let i = 0; i < this.$$words.length; ++i) {
this.#words[i].tick(elapsed); this.$$words[i].tick(elapsed);
} }
} }
} }

View File

@ -10,17 +10,17 @@ export default (flecks) => {
); );
return class EntityList extends decorate(JsonResource) { return class EntityList extends decorate(JsonResource) {
#afterDestructionTickers = []; $$afterDestructionTickers = [];
#entities = {}; $$entities = {};
#entityTickers = []; $$entityTickers = [];
#flatEntities = []; $$flatEntities = [];
#informedEntities = new Map(); $$informedEntities = new Map();
#quadTree = new QuadTree(); $$quadTree = new QuadTree();
async acceptPacket(packet) { async acceptPacket(packet) {
await super.acceptPacket(packet); await super.acceptPacket(packet);
@ -38,13 +38,13 @@ export default (flecks) => {
async addEntity(entity) { async addEntity(entity) {
const uuid = entity.instanceUuid; const uuid = entity.instanceUuid;
// Already exists? // Already exists?
if (this.#entities[uuid]) { if (this.$$entities[uuid]) {
return; return;
} }
this.#entities[uuid] = entity; this.$$entities[uuid] = entity;
this.#flatEntities.push(entity); this.$$flatEntities.push(entity);
if (entity.hasTickers()) { if (entity.hasTickers()) {
this.#entityTickers.push(entity.tick); this.$$entityTickers.push(entity.tick);
} }
// eslint-disable-next-line no-param-reassign // eslint-disable-next-line no-param-reassign
entity.list = this; entity.list = this;
@ -52,7 +52,7 @@ export default (flecks) => {
entity.once('destroying', () => this.onEntityDestroying(entity)); entity.once('destroying', () => this.onEntityDestroying(entity));
this.emit('entityAdded', entity); this.emit('entityAdded', entity);
if ('web' !== process.env.FLECKS_CORE_BUILD_TARGET) { if ('web' !== process.env.FLECKS_CORE_BUILD_TARGET) {
this.#informedEntities.set(entity, []); this.$$informedEntities.set(entity, []);
} }
this.startSynchronizing(entity); this.startSynchronizing(entity);
} }
@ -63,20 +63,20 @@ export default (flecks) => {
destroyEntities() { destroyEntities() {
const promises = []; const promises = [];
for (let i = 0; i < this.#flatEntities.length; i++) { for (let i = 0; i < this.$$flatEntities.length; i++) {
promises.push(this.#flatEntities[i].destroy()); promises.push(this.$$flatEntities[i].destroy());
this.#flatEntities[i]?.tick(Infinity); this.$$flatEntities[i]?.tick(Infinity);
} }
return Promise.all(promises); return Promise.all(promises);
} }
get entities() { get entities() {
return this.#entities; return this.$$entities;
} }
findEntity(uuid) { findEntity(uuid) {
return uuid in this.#entities return uuid in this.$$entities
? this.#entities[uuid] ? this.$$entities[uuid]
: undefined; : undefined;
} }
@ -100,7 +100,7 @@ export default (flecks) => {
const tickers = entity.invokeHookFlat('afterDestructionTickers'); const tickers = entity.invokeHookFlat('afterDestructionTickers');
for (let i = 0; i < tickers.length; i++) { for (let i = 0; i < tickers.length; i++) {
const ticker = tickers[i]; const ticker = tickers[i];
this.#afterDestructionTickers.push(ticker); this.$$afterDestructionTickers.push(ticker);
} }
} }
@ -109,7 +109,7 @@ export default (flecks) => {
const {Entity} = flecks.get('$avocado/resource.resources'); const {Entity} = flecks.get('$avocado/resource.resources');
// Visible entities. // Visible entities.
const {areaToInform} = informed; const {areaToInform} = informed;
const previousVisibleEntities = this.#informedEntities.get(informed); const previousVisibleEntities = this.$$informedEntities.get(informed);
const visibleEntities = this.visibleEntities(areaToInform); const visibleEntities = this.visibleEntities(areaToInform);
for (let i = 0; i < visibleEntities.length; i++) { for (let i = 0; i < visibleEntities.length; i++) {
const entity = visibleEntities[i]; const entity = visibleEntities[i];
@ -136,7 +136,7 @@ export default (flecks) => {
} }
} }
// Send updates. // Send updates.
this.#informedEntities.set(informed, visibleEntities); this.$$informedEntities.set(informed, visibleEntities);
// Send destroys. // Send destroys.
for (let i = 0; i < previousVisibleEntities.length; i++) { for (let i = 0; i < previousVisibleEntities.length; i++) {
const entity = previousVisibleEntities[i]; const entity = previousVisibleEntities[i];
@ -149,33 +149,33 @@ export default (flecks) => {
} }
get quadTree() { get quadTree() {
return this.#quadTree; return this.$$quadTree;
} }
removeEntity(entity) { removeEntity(entity) {
const uuid = entity.instanceUuid; const uuid = entity.instanceUuid;
if (!(uuid in this.#entities)) { if (!(uuid in this.$$entities)) {
return; return;
} }
this.stopSynchronizing(entity); this.stopSynchronizing(entity);
if ('web' !== process.env.FLECKS_CORE_BUILD_TARGET) { if ('web' !== process.env.FLECKS_CORE_BUILD_TARGET) {
this.#informedEntities.delete(entity); this.$$informedEntities.delete(entity);
} }
// eslint-disable-next-line no-param-reassign // eslint-disable-next-line no-param-reassign
entity.list = null; entity.list = null;
entity.emit('removedFromList', this); entity.emit('removedFromList', this);
delete this.#entities[uuid]; delete this.$$entities[uuid];
this.#flatEntities.splice(this.#flatEntities.indexOf(entity), 1); this.$$flatEntities.splice(this.$$flatEntities.indexOf(entity), 1);
const index = this.#entityTickers.indexOf(entity.tick); const index = this.$$entityTickers.indexOf(entity.tick);
if (-1 !== index) { if (-1 !== index) {
this.#entityTickers.splice(index, 1); this.$$entityTickers.splice(index, 1);
} }
this.emit('entityRemoved', entity); this.emit('entityRemoved', entity);
} }
tick(elapsed) { tick(elapsed) {
// Run after destruction tickers. // Run after destruction tickers.
if (this.#afterDestructionTickers.length > 0) { if (this.$$afterDestructionTickers.length > 0) {
this.tickAfterDestructionTickers(elapsed); this.tickAfterDestructionTickers(elapsed);
} }
// Run normal tickers. // Run normal tickers.
@ -184,30 +184,30 @@ export default (flecks) => {
tickAfterDestructionTickers(elapsed) { tickAfterDestructionTickers(elapsed) {
const finishedTickers = []; const finishedTickers = [];
for (let i = 0; i < this.#afterDestructionTickers.length; ++i) { for (let i = 0; i < this.$$afterDestructionTickers.length; ++i) {
const ticker = this.#afterDestructionTickers[i]; const ticker = this.$$afterDestructionTickers[i];
if (ticker(elapsed)) { if (ticker(elapsed)) {
finishedTickers.push(ticker); finishedTickers.push(ticker);
} }
} }
for (let i = 0; i < finishedTickers.length; ++i) { for (let i = 0; i < finishedTickers.length; ++i) {
const ticker = finishedTickers[i]; const ticker = finishedTickers[i];
const index = this.#afterDestructionTickers.indexOf(ticker); const index = this.$$afterDestructionTickers.indexOf(ticker);
this.#afterDestructionTickers.splice(index, 1); this.$$afterDestructionTickers.splice(index, 1);
} }
} }
tickEntities(elapsed) { tickEntities(elapsed) {
for (let i = 0; i < this.#entityTickers.length; i++) { for (let i = 0; i < this.$$entityTickers.length; i++) {
this.#entityTickers[i](elapsed); this.$$entityTickers[i](elapsed);
} }
} }
toJSON() { toJSON() {
const {Entity} = flecks.get('$avocado/resource.resources'); const {Entity} = flecks.get('$avocado/resource.resources');
const json = []; const json = [];
for (let i = 0; i < this.#flatEntities.length; i++) { for (let i = 0; i < this.$$flatEntities.length; i++) {
const entity = this.#flatEntities[i]; const entity = this.$$flatEntities[i];
json.push(Entity.withoutDefaults(entity.toJSON())); json.push(Entity.withoutDefaults(entity.toJSON()));
} }
return json; return json;
@ -217,13 +217,13 @@ export default (flecks) => {
const {areaToInform} = informed; const {areaToInform} = informed;
const visibleEntities = this.visibleEntities(areaToInform); const visibleEntities = this.visibleEntities(areaToInform);
// Mark as notified. // Mark as notified.
this.#informedEntities.set(informed, visibleEntities); this.$$informedEntities.set(informed, visibleEntities);
return visibleEntities.map((entity) => entity.toNetwork(informed)); return visibleEntities.map((entity) => entity.toNetwork(informed));
} }
visibleEntities(query) { visibleEntities(query) {
const entities = []; const entities = [];
const quadTree = this.#quadTree; const quadTree = this.$$quadTree;
const entries = Array.from(quadTree.query(query)); const entries = Array.from(quadTree.query(query));
for (let i = 0; i < entries.length; i++) { for (let i = 0; i < entries.length; i++) {
const [entity] = entries[i]; const [entity] = entries[i];

View File

@ -24,25 +24,25 @@ export default (flecks) => {
); );
return class Entity extends decorate(JsonResource) { return class Entity extends decorate(JsonResource) {
#hooks = {}; $$hooks = {};
#isDestroying = false; $$isDestroying = false;
#markedAsDirty = true; $$markedAsDirty = true;
#originalJson; $$originalJson;
#tickingPromisesTickers = []; $$tickingPromisesTickers = [];
#traits = {}; $$traits = {};
#traitsFlat = []; $$traitsFlat = [];
#traitTickers = []; $$traitTickers = [];
#traitRenderTickers = []; $$traitRenderTickers = [];
#traitsAcceptingPackets = []; $$traitsAcceptingPackets = [];
constructor() { constructor() {
super(); super();
@ -66,11 +66,11 @@ export default (flecks) => {
addTickingPromise(tickingPromise) { addTickingPromise(tickingPromise) {
const ticker = tickingPromise.tick.bind(tickingPromise); const ticker = tickingPromise.tick.bind(tickingPromise);
this.#tickingPromisesTickers.push(ticker); this.$$tickingPromisesTickers.push(ticker);
return tickingPromise.then(() => { return tickingPromise.then(() => {
const index = this.#tickingPromisesTickers.indexOf(ticker); const index = this.$$tickingPromisesTickers.indexOf(ticker);
if (-1 !== index) { if (-1 !== index) {
this.#tickingPromisesTickers.splice(index, 1); this.$$tickingPromisesTickers.splice(index, 1);
} }
}); });
} }
@ -83,11 +83,11 @@ export default (flecks) => {
return undefined; return undefined;
} }
if (this.is(type)) { if (this.is(type)) {
await this.#traits[type].load({ await this.$$traits[type].load({
entity: this, entity: this,
...json, ...json,
}); });
this.emit('traitAdded', type, this.#traits[type]); this.emit('traitAdded', type, this.$$traits[type]);
return undefined; return undefined;
} }
// Ensure dependencies. // Ensure dependencies.
@ -124,23 +124,23 @@ export default (flecks) => {
const hooks = Object.entries(trait.hooks()); const hooks = Object.entries(trait.hooks());
for (let i = 0; i < hooks.length; i++) { for (let i = 0; i < hooks.length; i++) {
const [key, fn] = hooks[i]; const [key, fn] = hooks[i];
this.#hooks[key] = this.#hooks[key] || []; this.$$hooks[key] = this.$$hooks[key] || [];
this.#hooks[key].push({ this.$$hooks[key].push({
fn, fn,
type, type,
}); });
} }
// Track trait. // Track trait.
this.#traits[type] = trait; this.$$traits[type] = trait;
this.#traitsFlat.push(trait); this.$$traitsFlat.push(trait);
if ('tick' in trait) { if ('tick' in trait) {
this.#traitTickers.push(trait.tick); this.$$traitTickers.push(trait.tick);
} }
if ('renderTick' in trait) { if ('renderTick' in trait) {
this.#traitRenderTickers.push(trait.renderTick); this.$$traitRenderTickers.push(trait.renderTick);
} }
if ('acceptPacket' in trait) { if ('acceptPacket' in trait) {
this.#traitsAcceptingPackets.push(trait); this.$$traitsAcceptingPackets.push(trait);
} }
this.startSynchronizing(trait); this.startSynchronizing(trait);
this.emit('traitAdded', type, trait); this.emit('traitAdded', type, trait);
@ -179,13 +179,13 @@ export default (flecks) => {
} }
cleanPackets() { cleanPackets() {
if (!this.#markedAsDirty) { if (!this.$$markedAsDirty) {
return; return;
} }
for (let i = 0; i < this.#traitsFlat.length; i++) { for (let i = 0; i < this.$$traitsFlat.length; i++) {
this.#traitsFlat[i].cleanPackets(); this.$$traitsFlat[i].cleanPackets();
} }
this.#markedAsDirty = false; this.$$markedAsDirty = false;
} }
// TODO: behavior decorator // TODO: behavior decorator
@ -202,10 +202,10 @@ export default (flecks) => {
} }
async destroy() { async destroy() {
if (this.#isDestroying) { if (this.$$isDestroying) {
return; return;
} }
this.#isDestroying = true; this.$$isDestroying = true;
if (module.hot) { if (module.hot) {
hotEntities.delete(this); hotEntities.delete(this);
} }
@ -225,15 +225,15 @@ export default (flecks) => {
} }
hasTickers() { hasTickers() {
return this.#traitTickers.length; return this.$$traitTickers.length;
} }
invokeHook(hook, ...args) { invokeHook(hook, ...args) {
const results = {}; const results = {};
if (!(hook in this.#hooks)) { if (!(hook in this.$$hooks)) {
return results; return results;
} }
const values = Object.values(this.#hooks[hook]); const values = Object.values(this.$$hooks[hook]);
for (let i = 0; i < values.length; i++) { for (let i = 0; i < values.length; i++) {
const {fn, type} = values[i]; const {fn, type} = values[i];
results[type] = fastApply(null, fn, args); results[type] = fastApply(null, fn, args);
@ -251,26 +251,26 @@ export default (flecks) => {
} }
is(type) { is(type) {
return type in this.#traits; return type in this.$$traits;
} }
async load(json = {}) { async load(json = {}) {
await super.load(json); await super.load(json);
const {instanceUuid, traits = {}} = json; const {instanceUuid, traits = {}} = json;
if (!this.#originalJson) { if (!this.$$originalJson) {
this.#originalJson = json; this.$$originalJson = json;
} }
this.instanceUuid = instanceUuid || this.numericUid; this.instanceUuid = instanceUuid || this.numericUid;
await this.addTraits(traits); await this.addTraits(traits);
} }
markAsDirty() { markAsDirty() {
this.#markedAsDirty = true; this.$$markedAsDirty = true;
} }
packetsFor(informed) { packetsFor(informed) {
const packets = []; const packets = [];
const traits = Object.values(this.#traits); const traits = Object.values(this.$$traits);
for (let i = 0; i < traits.length; i++) { for (let i = 0; i < traits.length; i++) {
const trait = traits[i]; const trait = traits[i];
const traitPackets = trait.packetsFor(informed); const traitPackets = trait.packetsFor(informed);
@ -291,8 +291,8 @@ export default (flecks) => {
} }
renderTick(elapsed) { renderTick(elapsed) {
for (let i = 0; i < this.#traitRenderTickers.length; i++) { for (let i = 0; i < this.$$traitRenderTickers.length; i++) {
this.#traitRenderTickers[i](elapsed); this.$$traitRenderTickers[i](elapsed);
} }
} }
@ -307,7 +307,7 @@ export default (flecks) => {
return; return;
} }
// Destroy instance. // Destroy instance.
const instance = this.#traits[type]; const instance = this.$$traits[type];
this.stopSynchronizing(instance); this.stopSynchronizing(instance);
// Remove methods, hooks, and properties. // Remove methods, hooks, and properties.
const methods = instance.methods(); const methods = instance.methods();
@ -318,8 +318,8 @@ export default (flecks) => {
const hooks = Object.keys(instance.hooks()); const hooks = Object.keys(instance.hooks());
for (let i = 0; i < hooks.length; i++) { for (let i = 0; i < hooks.length; i++) {
const hook = hooks[i]; const hook = hooks[i];
const implementation = this.#hooks[hook].find(({type: hookType}) => hookType === type); const implementation = this.$$hooks[hook].find(({type: hookType}) => hookType === type);
this.#hooks[hook].splice(this.#hooks[hook].indexOf(implementation), 1); this.$$hooks[hook].splice(this.$$hooks[hook].indexOf(implementation), 1);
} }
const {[type]: Trait} = flecks.get('$avocado/traits.traits'); const {[type]: Trait} = flecks.get('$avocado/traits.traits');
const properties = enumerateTraitAccessorKeys(Trait.prototype); const properties = enumerateTraitAccessorKeys(Trait.prototype);
@ -335,17 +335,17 @@ export default (flecks) => {
} }
instance.destroy(); instance.destroy();
// Remove instance. // Remove instance.
delete this.#traits[type]; delete this.$$traits[type];
this.#traitsFlat.splice(this.#traitsFlat.indexOf(instance), 1); this.$$traitsFlat.splice(this.$$traitsFlat.indexOf(instance), 1);
if ('tick' in instance) { if ('tick' in instance) {
this.#traitTickers.splice(this.#traitTickers.indexOf(instance.tick), 1); this.$$traitTickers.splice(this.$$traitTickers.indexOf(instance.tick), 1);
} }
if ('renderTick' in instance) { if ('renderTick' in instance) {
this.#traitRenderTickers.splice(this.#traitRenderTickers.indexOf(instance.renderTick), 1); this.$$traitRenderTickers.splice(this.$$traitRenderTickers.indexOf(instance.renderTick), 1);
} }
const acceptPacketIndex = this.#traitsAcceptingPackets.indexOf(instance); const acceptPacketIndex = this.$$traitsAcceptingPackets.indexOf(instance);
if (-1 !== acceptPacketIndex) { if (-1 !== acceptPacketIndex) {
this.#traitsAcceptingPackets.splice(acceptPacketIndex, 1); this.$$traitsAcceptingPackets.splice(acceptPacketIndex, 1);
} }
// Unloop. // Unloop.
instance.entity = undefined; instance.entity = undefined;
@ -362,11 +362,11 @@ export default (flecks) => {
tick(elapsed) { tick(elapsed) {
this.elapsed = elapsed; this.elapsed = elapsed;
this.uptime += elapsed; this.uptime += elapsed;
for (let i = 0; i < this.#traitTickers.length; i++) { for (let i = 0; i < this.$$traitTickers.length; i++) {
this.#traitTickers[i](elapsed); this.$$traitTickers[i](elapsed);
} }
for (let i = 0; i < this.#tickingPromisesTickers.length; i++) { for (let i = 0; i < this.$$tickingPromisesTickers.length; i++) {
this.#tickingPromisesTickers[i](elapsed); this.$$tickingPromisesTickers[i](elapsed);
} }
} }
@ -375,12 +375,12 @@ export default (flecks) => {
if (this.uri) { if (this.uri) {
const pristine = {}; const pristine = {};
const json = {}; const json = {};
const traits = Object.entries(this.#traits); const traits = Object.entries(this.$$traits);
for (let i = 0; i < traits.length; i++) { for (let i = 0; i < traits.length; i++) {
const [type, trait] = traits[i]; const [type, trait] = traits[i];
pristine.traits = pristine.traits || {}; pristine.traits = pristine.traits || {};
pristine.traits[type] = trait.constructor.withDefaults( pristine.traits[type] = trait.constructor.withDefaults(
this.#originalJson ? this.#originalJson.traits[type] : {}, this.$$originalJson ? this.$$originalJson.traits[type] : {},
); );
json.traits = json.traits || {}; json.traits = json.traits || {};
json.traits[type] = trait.toJSON(); json.traits[type] = trait.toJSON();
@ -392,7 +392,7 @@ export default (flecks) => {
} }
else { else {
output = {}; output = {};
const traits = Object.entries(this.#traits); const traits = Object.entries(this.$$traits);
for (let i = 0; i < traits.length; i++) { for (let i = 0; i < traits.length; i++) {
const [type, trait] = traits[i]; const [type, trait] = traits[i];
output.traits = {}; output.traits = {};
@ -409,11 +409,11 @@ export default (flecks) => {
const json = { const json = {
traits: {}, traits: {},
}; };
const traits = Object.entries(this.#traits); const traits = Object.entries(this.$$traits);
for (let i = 0; i < traits.length; i++) { for (let i = 0; i < traits.length; i++) {
const [type, trait] = traits[i]; const [type, trait] = traits[i];
pristine.traits[type] = trait.constructor.withDefaults( pristine.traits[type] = trait.constructor.withDefaults(
this.#originalJson ? this.#originalJson.traits[type] : {}, this.$$originalJson ? this.$$originalJson.traits[type] : {},
); );
json.traits[type] = trait.toNetwork(informed); json.traits[type] = trait.toNetwork(informed);
} }
@ -432,15 +432,15 @@ export default (flecks) => {
} }
trait(type) { trait(type) {
return this.#traits[type]; return this.$$traits[type];
} }
get traits() { get traits() {
return this.#traits; return this.$$traits;
} }
traitTypes() { traitTypes() {
return Object.keys(this.#traits); return Object.keys(this.$$traits);
} }
static withDefaults(json = {}) { static withDefaults(json = {}) {

View File

@ -13,13 +13,13 @@ const decorate = compose(
export default (flecks) => class Alive extends decorate(Trait) { export default (flecks) => class Alive extends decorate(Trait) {
#deathCheck; $$deathCheck;
#hasDied = false; $$hasDied = false;
#isDying = false; $$isDying = false;
#packets = []; $$packets = [];
acceptPacket(packet) { acceptPacket(packet) {
switch (packet.constructor.type) { switch (packet.constructor.type) {
@ -36,7 +36,7 @@ export default (flecks) => class Alive extends decorate(Trait) {
cleanPackets() { cleanPackets() {
super.cleanPackets(); super.cleanPackets();
this.#packets = []; this.$$packets = [];
} }
static defaultParams() { static defaultParams() {
@ -80,14 +80,14 @@ export default (flecks) => class Alive extends decorate(Trait) {
} }
}, },
)); ));
this.#hasDied = true; this.$$hasDied = true;
this.entity.destroy(); this.entity.destroy();
} }
hooks() { hooks() {
return { return {
destroy: () => () => (this.#isDying ? this.#hasDied : true), destroy: () => () => (this.$$isDying ? this.$$hasDied : true),
}; };
} }
@ -105,7 +105,7 @@ export default (flecks) => class Alive extends decorate(Trait) {
return { return {
startedDying: () => { startedDying: () => {
this.#packets.push(['Died']); this.$$packets.push(['Died']);
}, },
tookHarm: (harm) => { tookHarm: (harm) => {
@ -118,7 +118,7 @@ export default (flecks) => class Alive extends decorate(Trait) {
async load(json) { async load(json) {
await super.load(json); await super.load(json);
const {Script} = flecks.get('$avocado/resource.resources'); const {Script} = flecks.get('$avocado/resource.resources');
this.#deathCheck = await Script.load(this.params.deathCheck, this.entity.contextOrDefault); this.$$deathCheck = await Script.load(this.params.deathCheck, this.entity.contextOrDefault);
} }
get maxLife() { get maxLife() {
@ -134,17 +134,17 @@ export default (flecks) => class Alive extends decorate(Trait) {
return { return {
die: () => { die: () => {
if (!this.#isDying) { if (!this.$$isDying) {
this.#isDying = this.die(); this.$$isDying = this.die();
} }
return this.#isDying; return this.$$isDying;
}, },
}; };
} }
packetsFor() { packetsFor() {
const packets = this.#packets.concat(); const packets = this.$$packets.concat();
const {life, maxLife} = this.stateDifferences(); const {life, maxLife} = this.stateDifferences();
if (life || maxLife) { if (life || maxLife) {
packets.push([ packets.push([
@ -160,8 +160,8 @@ export default (flecks) => class Alive extends decorate(Trait) {
tick() { tick() {
if ('web' !== process.env.FLECKS_CORE_BUILD_TARGET) { if ('web' !== process.env.FLECKS_CORE_BUILD_TARGET) {
if (!this.#isDying) { if (!this.$$isDying) {
this.#deathCheck.evaluate(({value: died}) => { this.$$deathCheck.evaluate(({value: died}) => {
if (died) { if (died) {
this.entity.die(); this.entity.die();
} }

View File

@ -16,7 +16,7 @@ const decorate = compose(
export default () => class DomNode extends decorate(Trait) { export default () => class DomNode extends decorate(Trait) {
#scheduledRuleApplication = true; $$scheduledRuleApplication = true;
static defaultParams() { static defaultParams() {
return { return {
@ -51,31 +51,31 @@ export default () => class DomNode extends decorate(Trait) {
return { return {
opacityChanged: () => { opacityChanged: () => {
this.#scheduledRuleApplication = true; this.$$scheduledRuleApplication = true;
}, },
positionChanged: () => { positionChanged: () => {
this.#scheduledRuleApplication = true; this.$$scheduledRuleApplication = true;
}, },
rotationChanged: () => { rotationChanged: () => {
this.#scheduledRuleApplication = true; this.$$scheduledRuleApplication = true;
}, },
textChanged: () => { textChanged: () => {
this.#scheduledRuleApplication = true; this.$$scheduledRuleApplication = true;
}, },
visibleScaleChanged: () => { visibleScaleChanged: () => {
this.#scheduledRuleApplication = true; this.$$scheduledRuleApplication = true;
}, },
domScaleXChanged: () => { domScaleXChanged: () => {
this.#scheduledRuleApplication = true; this.$$scheduledRuleApplication = true;
}, },
domScaleYChanged: () => { domScaleYChanged: () => {
this.#scheduledRuleApplication = true; this.$$scheduledRuleApplication = true;
}, },
parentNodeChanged: (oldParentNode, newParentNode) => { parentNodeChanged: (oldParentNode, newParentNode) => {
@ -114,8 +114,8 @@ export default () => class DomNode extends decorate(Trait) {
} }
tick() { tick() {
if ('web' === process.env.FLECKS_CORE_BUILD_TARGET && this.#scheduledRuleApplication) { if ('web' === process.env.FLECKS_CORE_BUILD_TARGET && this.$$scheduledRuleApplication) {
this.#scheduledRuleApplication = false; this.$$scheduledRuleApplication = false;
this.applyStyleRules(); this.applyStyleRules();
} }
} }

View File

@ -2,12 +2,12 @@ import {Trait} from '@avocado/traits';
export default () => class DomText extends Trait { export default () => class DomText extends Trait {
#text; $$text;
constructor() { constructor() {
super(); super();
if ('web' === process.env.FLECKS_CORE_BUILD_TARGET) { if ('web' === process.env.FLECKS_CORE_BUILD_TARGET) {
this.#text = window.document.createElement('span'); this.$$text = window.document.createElement('span');
} }
} }
@ -48,30 +48,30 @@ export default () => class DomText extends Trait {
async load(json) { async load(json) {
await super.load(json); await super.load(json);
if (!this.#text) { if (!this.$$text) {
return; return;
} }
const {text} = this.entity; const {text} = this.entity;
this.#text.innerText = text; this.$$text.innerText = text;
this.#text.style.position = 'relative'; this.$$text.style.position = 'relative';
const {fontSize} = this.params; const {fontSize} = this.params;
if (fontSize) { if (fontSize) {
this.#text.style.fontSize = `${fontSize}px`; this.$$text.style.fontSize = `${fontSize}px`;
if (this.params.centered) { if (this.params.centered) {
this.#text.style.left = `-${(fontSize / 2) * text.length}px`; this.$$text.style.left = `-${(fontSize / 2) * text.length}px`;
this.#text.style.top = `-${(fontSize / 2)}px`; this.$$text.style.top = `-${(fontSize / 2)}px`;
} }
} }
this.entity.node.appendChild(this.#text); this.entity.node.appendChild(this.$$text);
} }
onColorChanged() { onColorChanged() {
if (!this.#text) { if (!this.$$text) {
return; return;
} }
if (this.entity.is('Colorized')) { if (this.entity.is('Colorized')) {
const {red, green, blue} = this.entity; const {red, green, blue} = this.entity;
this.#text.style.color = `rgb(${red}, ${green}, ${blue})`; this.$$text.style.color = `rgb(${red}, ${green}, ${blue})`;
} }
} }

View File

@ -16,11 +16,11 @@ const decorate = compose(
export default () => class Mobile extends decorate(Trait) { export default () => class Mobile extends decorate(Trait) {
#appliedMovement = [0, 0]; $$appliedMovement = [0, 0];
#movement = [0, 0, 0, 0]; $$movement = [0, 0, 0, 0];
#rememberedActionMovement = [0, 0]; $$rememberedActionMovement = [0, 0];
acceptPacket(packet) { acceptPacket(packet) {
switch (packet.constructor.type) { switch (packet.constructor.type) {
@ -51,16 +51,16 @@ export default () => class Mobile extends decorate(Trait) {
acceptAction: ({action, value}) => { acceptAction: ({action, value}) => {
switch (action) { switch (action) {
case 'MoveUp': case 'MoveUp':
this.#movement[0] = value; this.$$movement[0] = value;
break; break;
case 'MoveRight': case 'MoveRight':
this.#movement[1] = value; this.$$movement[1] = value;
break; break;
case 'MoveDown': case 'MoveDown':
this.#movement[2] = value; this.$$movement[2] = value;
break; break;
case 'MoveLeft': case 'MoveLeft':
this.#movement[3] = value; this.$$movement[3] = value;
break; break;
default: default:
return; return;
@ -68,14 +68,14 @@ export default () => class Mobile extends decorate(Trait) {
if ('web' === process.env.FLECKS_CORE_BUILD_TARGET) { if ('web' === process.env.FLECKS_CORE_BUILD_TARGET) {
return; return;
} }
this.#rememberedActionMovement = [ this.$$rememberedActionMovement = [
this.#movement[1] - this.#movement[3], this.$$movement[1] - this.$$movement[3],
this.#movement[2] - this.#movement[0], this.$$movement[2] - this.$$movement[0],
]; ];
if (!this.entity.isAcceptingInput) { if (!this.entity.isAcceptingInput) {
return; return;
} }
this.setActionMovement(this.#rememberedActionMovement); this.setActionMovement(this.$$rememberedActionMovement);
}, },
}; };
@ -83,18 +83,18 @@ export default () => class Mobile extends decorate(Trait) {
hotJSON() { hotJSON() {
return { return {
appliedMovement: this.#appliedMovement, appliedMovement: this.$$appliedMovement,
movement: this.#movement, movement: this.$$movement,
}; };
} }
async load(json) { async load(json) {
await super.load(json); await super.load(json);
if (json.appliedMovement) { if (json.appliedMovement) {
this.#appliedMovement = json.appliedMovement; this.$$appliedMovement = json.appliedMovement;
} }
if (json.movement) { if (json.movement) {
this.#movement = json.movement; this.$$movement = json.movement;
} }
} }
@ -106,7 +106,7 @@ export default () => class Mobile extends decorate(Trait) {
this.setActionMovement([0, 0]); this.setActionMovement([0, 0]);
} }
else { else {
this.setActionMovement(this.#rememberedActionMovement); this.setActionMovement(this.$$rememberedActionMovement);
} }
}, },
@ -117,7 +117,7 @@ export default () => class Mobile extends decorate(Trait) {
return { return {
applyMovement: (vector) => { applyMovement: (vector) => {
this.#appliedMovement = Vector.add(this.#appliedMovement, vector); this.$$appliedMovement = Vector.add(this.$$appliedMovement, vector);
}, },
forceMovement: (movement) => { forceMovement: (movement) => {
@ -215,19 +215,19 @@ export default () => class Mobile extends decorate(Trait) {
if (this.entity.isMobile && !Vector.isZero(this.actionMovement)) { if (this.entity.isMobile && !Vector.isZero(this.actionMovement)) {
this.entity.requestMovement(this.actionMovement); this.entity.requestMovement(this.actionMovement);
} }
if (Vector.isZero(this.#appliedMovement)) { if (Vector.isZero(this.$$appliedMovement)) {
return; return;
} }
if (this.entity.is('Physical')) { if (this.entity.is('Physical')) {
this.entity.applyImpulse(this.#appliedMovement); this.entity.applyImpulse(this.$$appliedMovement);
} }
else { else {
this.entity.forceMovement(Vector.scale( this.entity.forceMovement(Vector.scale(
this.#appliedMovement, this.$$appliedMovement,
elapsed, elapsed,
)); ));
} }
this.#appliedMovement = [0, 0]; this.$$appliedMovement = [0, 0];
} }
}; };

View File

@ -6,12 +6,12 @@ const decorate = compose(
export default () => class Perishable extends decorate(Trait) { export default () => class Perishable extends decorate(Trait) {
#ttl = 0; $$ttl = 0;
constructor() { constructor() {
super(); super();
({ ({
ttl: this.#ttl, ttl: this.$$ttl,
} = this.constructor.defaultParams()); } = this.constructor.defaultParams());
} }
@ -23,12 +23,12 @@ export default () => class Perishable extends decorate(Trait) {
async load(json) { async load(json) {
await super.load(json); await super.load(json);
this.#ttl = this.params.ttl; this.$$ttl = this.params.ttl;
} }
tick(elapsed) { tick(elapsed) {
this.#ttl -= elapsed; this.$$ttl -= elapsed;
if (this.#ttl <= 0) { if (this.$$ttl <= 0) {
this.entity.destroy(); this.entity.destroy();
} }
} }

View File

@ -11,16 +11,16 @@ const decorate = compose(
export default (flecks) => class Spawner extends decorate(Trait) { export default (flecks) => class Spawner extends decorate(Trait) {
#children; $$children;
#childrenListeners; $$childrenListeners;
#spawnJSONs; $$spawnJSONs;
constructor() { constructor() {
super(); super();
this.#children = []; this.$$children = [];
this.#childrenListeners = new Map(); this.$$childrenListeners = new Map();
} }
// eslint-disable-next-line class-methods-use-this // eslint-disable-next-line class-methods-use-this
@ -121,8 +121,8 @@ export default (flecks) => class Spawner extends decorate(Trait) {
destroy() { destroy() {
super.destroy(); super.destroy();
while (this.#children.length > 0) { while (this.$$children.length > 0) {
const child = this.#children.pop(); const child = this.$$children.pop();
if (child) { if (child) {
this.removeChild(child); this.removeChild(child);
} }
@ -153,7 +153,7 @@ export default (flecks) => class Spawner extends decorate(Trait) {
} }
maySpawn() { maySpawn() {
if (this.maxSpawns > 0 && this.maxSpawns <= this.#children.length) { if (this.maxSpawns > 0 && this.maxSpawns <= this.$$children.length) {
return false; return false;
} }
if (!this.destinationEntityList()) { if (!this.destinationEntityList()) {
@ -168,7 +168,7 @@ export default (flecks) => class Spawner extends decorate(Trait) {
killAllChildren: () => { killAllChildren: () => {
// Juggle children since this may cause splices and mess up the array. // Juggle children since this may cause splices and mess up the array.
const promises = []; const promises = [];
const children = this.#children.slice(0); const children = this.$$children.slice(0);
for (let i = 0; i < children.length; i++) { for (let i = 0; i < children.length; i++) {
const child = children[i]; const child = children[i];
promises.push( promises.push(
@ -223,15 +223,15 @@ export default (flecks) => class Spawner extends decorate(Trait) {
return undefined; return undefined;
} }
// Add null to children to prevent race. // Add null to children to prevent race.
const childIndex = this.#children.length; const childIndex = this.$$children.length;
this.#children.push(null); this.$$children.push(null);
const list = this.destinationEntityList(); const list = this.destinationEntityList();
const {Entity} = flecks.get('$avocado/resource.resources'); const {Entity} = flecks.get('$avocado/resource.resources');
const child = await Entity.load(json); const child = await Entity.load(json);
this.#children[childIndex] = child; this.$$children[childIndex] = child;
// Listen for destroy event. // Listen for destroy event.
const listener = this.removeChild.bind(this, child); const listener = this.removeChild.bind(this, child);
this.#childrenListeners.set(child, listener); this.$$childrenListeners.set(child, listener);
child.once('destroying', listener); child.once('destroying', listener);
// Add child to list. // Add child to list.
list.addEntity(child); list.addEntity(child);
@ -266,12 +266,12 @@ export default (flecks) => class Spawner extends decorate(Trait) {
} }
removeChild(child) { removeChild(child) {
const index = this.#children.indexOf(child); const index = this.$$children.indexOf(child);
if (-1 !== index) { if (-1 !== index) {
this.#children.splice(index, 1); this.$$children.splice(index, 1);
const listener = this.#childrenListeners.get(child); const listener = this.$$childrenListeners.get(child);
child.off('destroying', listener); child.off('destroying', listener);
this.#childrenListeners.delete(child); this.$$childrenListeners.delete(child);
} }
} }

View File

@ -5,21 +5,21 @@ import Image from './image';
export default class Atlas extends JsonResource { export default class Atlas extends JsonResource {
#image; $$image;
#size = [0, 0]; $$size = [0, 0];
#subimages = []; $$subimages = [];
destroy() { destroy() {
this.#subimages.forEach((subimage) => { this.$$subimages.forEach((subimage) => {
subimage.destroy(); subimage.destroy();
}); });
this.#subimages = []; this.$$subimages = [];
} }
get image() { get image() {
return this.#image; return this.$$image;
} }
async load(json = {}) { async load(json = {}) {
@ -29,19 +29,19 @@ export default class Atlas extends JsonResource {
if (!imageUri) { if (!imageUri) {
return; return;
} }
this.#image = await Image.load(imageUri); this.$$image = await Image.load(imageUri);
switch (type) { switch (type) {
case 'grid': { case 'grid': {
const {size} = json; const {size} = json;
if (Vector.isNull(size)) { if (Vector.isNull(size)) {
return; return;
} }
const grid = Vector.div(this.#image.size, size); const grid = Vector.div(this.$$image.size, size);
const rectangle = Rectangle.compose([0, 0], size); const rectangle = Rectangle.compose([0, 0], size);
for (let j = 0; j < grid[1]; ++j) { for (let j = 0; j < grid[1]; ++j) {
for (let i = 0; i < grid[0]; ++i) { for (let i = 0; i < grid[0]; ++i) {
const subimage = this.#image.subimage(rectangle); const subimage = this.$$image.subimage(rectangle);
this.#subimages.push(subimage); this.$$subimages.push(subimage);
rectangle[0] += size[0]; rectangle[0] += size[0];
} }
rectangle[0] = 0; rectangle[0] = 0;
@ -54,7 +54,7 @@ export default class Atlas extends JsonResource {
} }
subimage(index) { subimage(index) {
return this.#subimages[index]; return this.$$subimages[index];
} }
} }

View File

@ -7,7 +7,7 @@ import Renderable from './renderable';
export default class Container extends Renderable { export default class Container extends Renderable {
#filterMap = {}; $$filterMap = {};
constructor() { constructor() {
super(); super();
@ -91,10 +91,10 @@ export default class Container extends Renderable {
default: default:
} }
if (filter) { if (filter) {
if (!this.#filterMap[id]) { if (!this.$$filterMap[id]) {
this.#filterMap[id] = {}; this.$$filterMap[id] = {};
} }
this.#filterMap[id][type] = filter; this.$$filterMap[id][type] = filter;
if (!this.container.filters) { if (!this.container.filters) {
this.container.filters = []; this.container.filters = [];
} }
@ -164,7 +164,7 @@ export default class Container extends Renderable {
return; return;
} }
this.container.filters = []; this.container.filters = [];
this.#filterMap = {}; this.$$filterMap = {};
} }
removeChild(child) { removeChild(child) {
@ -188,13 +188,13 @@ export default class Container extends Renderable {
if (this.container.isFake) { if (this.container.isFake) {
return; return;
} }
if (this.#filterMap[id]?.[type]) { if (this.$$filterMap[id]?.[type]) {
const {filters} = this.container; const {filters} = this.container;
const index = filters.indexOf(this.#filterMap[id][type]); const index = filters.indexOf(this.$$filterMap[id][type]);
if (-1 !== index) { if (-1 !== index) {
filters.splice(index, 1); filters.splice(index, 1);
} }
delete this.#filterMap[id][type]; delete this.$$filterMap[id][type];
} }
} }

View File

@ -34,7 +34,7 @@ export default class Primitives extends Renderable {
drawCircle(position, radius, lineStyle, fillStyle) { drawCircle(position, radius, lineStyle, fillStyle) {
if (!this.primitives.isFake) { if (!this.primitives.isFake) {
this.#wrapStyle('drawCircle', '3rd', lineStyle, fillStyle, () => { this.$$wrapStyle('drawCircle', '3rd', lineStyle, fillStyle, () => {
this.primitives.drawCircle(position[0], position[1], radius); this.primitives.drawCircle(position[0], position[1], radius);
}); });
} }
@ -42,7 +42,7 @@ export default class Primitives extends Renderable {
drawLine(p1, p2, lineStyle, fillStyle) { drawLine(p1, p2, lineStyle, fillStyle) {
if (!this.primitives.isFake) { if (!this.primitives.isFake) {
this.#wrapStyle('drawLine', '3rd', lineStyle, fillStyle, () => { this.$$wrapStyle('drawLine', '3rd', lineStyle, fillStyle, () => {
this.primitives.moveTo(p1[0] + 0.5, p1[1] + 0.5); this.primitives.moveTo(p1[0] + 0.5, p1[1] + 0.5);
this.primitives.lineTo(p2[0] + 0.5, p2[1] + 0.5); this.primitives.lineTo(p2[0] + 0.5, p2[1] + 0.5);
}); });
@ -58,7 +58,7 @@ export default class Primitives extends Renderable {
]; ];
const p1 = Vector.add(p, [0.5, 0.5]); const p1 = Vector.add(p, [0.5, 0.5]);
const p2 = Vector.add(p, Vector.sub(Vector.add(v, shift), sign)); const p2 = Vector.add(p, Vector.sub(Vector.add(v, shift), sign));
this.#wrapStyle('drawLine', '3rd', lineStyle, fillStyle, () => { this.$$wrapStyle('drawLine', '3rd', lineStyle, fillStyle, () => {
this.primitives.moveTo(p1[0], p1[1]); this.primitives.moveTo(p1[0], p1[1]);
this.primitives.lineTo(p2[0], p2[1]); this.primitives.lineTo(p2[0], p2[1]);
}); });
@ -71,14 +71,14 @@ export default class Primitives extends Renderable {
const [x, y] = vertices[i]; const [x, y] = vertices[i];
ps.push(x, y); ps.push(x, y);
} }
this.#wrapStyle('drawLine', '2nd', lineStyle, fillStyle, () => { this.$$wrapStyle('drawLine', '2nd', lineStyle, fillStyle, () => {
this.primitives.drawPolygon(ps); this.primitives.drawPolygon(ps);
}); });
} }
drawRectangle(rectangle, lineStyle, fillStyle) { drawRectangle(rectangle, lineStyle, fillStyle) {
if (!this.primitives.isFake) { if (!this.primitives.isFake) {
this.#wrapStyle('drawLine', '2nd', lineStyle, fillStyle, () => { this.$$wrapStyle('drawLine', '2nd', lineStyle, fillStyle, () => {
this.primitives.drawRect( this.primitives.drawRect(
rectangle[0], rectangle[0],
rectangle[1], rectangle[1],
@ -93,7 +93,7 @@ export default class Primitives extends Renderable {
return this.primitives; return this.primitives;
} }
#wrapStyle(method, where, lineStyle, fillStyle, fn) { $$wrapStyle(method, where, lineStyle, fillStyle, fn) {
if (!lineStyle) { if (!lineStyle) {
throw new TypeError(`Primitives::${method} expects lineStyle as ${where} parameter`); throw new TypeError(`Primitives::${method} expects lineStyle as ${where} parameter`);
} }

View File

@ -16,17 +16,17 @@ export default (flecks) => {
return class Pictured extends decorate(Trait) { return class Pictured extends decorate(Trait) {
#currentImage = ''; $$currentImage = '';
#images = {}; $$images = {};
#sprites = {}; $$sprites = {};
constructor() { constructor() {
super(); super();
this.$$cachedAabbs = {}; this.$$cachedAabbs = {};
({ ({
currentImage: this.#currentImage, currentImage: this.$$currentImage,
} = this.constructor.defaultState()); } = this.constructor.defaultState());
} }
@ -50,15 +50,15 @@ export default (flecks) => {
destroy() { destroy() {
super.destroy(); super.destroy();
if (this.#sprites) { if (this.$$sprites) {
const sprites = Object.entries(this.#sprites); const sprites = Object.entries(this.$$sprites);
for (let i = 0; i < sprites.length; i++) { for (let i = 0; i < sprites.length; i++) {
const [key, sprite] = sprites[i]; const [key, sprite] = sprites[i];
this.hideImage(key); this.hideImage(key);
sprite.image.destroy(); sprite.image.destroy();
sprite.destroy(); sprite.destroy();
} }
this.#sprites = undefined; this.$$sprites = undefined;
} }
} }
@ -66,10 +66,10 @@ export default (flecks) => {
if (!this.entity.container) { if (!this.entity.container) {
return; return;
} }
if (!this.#sprites) { if (!this.$$sprites) {
return; return;
} }
const sprite = this.#sprites[key]; const sprite = this.$$sprites[key];
if (!sprite) { if (!sprite) {
return; return;
} }
@ -80,14 +80,14 @@ export default (flecks) => {
return { return {
visibleAabbs: () => { visibleAabbs: () => {
const key = this.#currentImage; const key = this.$$currentImage;
if (this.$$cachedAabbs[key]) { if (this.$$cachedAabbs[key]) {
return this.$$cachedAabbs[key]; return this.$$cachedAabbs[key];
} }
if (!this.#images[key]) { if (!this.$$images[key]) {
return [0, 0, 0, 0]; return [0, 0, 0, 0];
} }
const {size} = this.#images[key]; const {size} = this.$$images[key];
if (Vector.isZero(size)) { if (Vector.isZero(size)) {
return [0, 0, 0, 0]; return [0, 0, 0, 0];
} }
@ -112,7 +112,7 @@ export default (flecks) => {
return { return {
currentImageChanged: (oldKey, currentImage) => { currentImageChanged: (oldKey, currentImage) => {
this.#currentImage = currentImage; this.$$currentImage = currentImage;
this.entity.scheduleBoundingBoxUpdate(); this.entity.scheduleBoundingBoxUpdate();
this.hideImage(oldKey); this.hideImage(oldKey);
this.showImage(currentImage); this.showImage(currentImage);
@ -123,8 +123,8 @@ export default (flecks) => {
}, },
traitAdded: () => { traitAdded: () => {
Object.keys(this.#sprites).forEach((key) => { Object.keys(this.$$sprites).forEach((key) => {
this[`${key === this.#currentImage ? 'show' : 'hide'}Image`](key); this[`${key === this.$$currentImage ? 'show' : 'hide'}Image`](key);
}); });
this.setSpriteScale(); this.setSpriteScale();
this.entity.forceBoundingBoxUpdate(); this.entity.forceBoundingBoxUpdate();
@ -145,19 +145,19 @@ export default (flecks) => {
}) })
.filter(([, {uri}]) => !!uri), .filter(([, {uri}]) => !!uri),
); );
this.#currentImage = this.state.currentImage; this.$$currentImage = this.state.currentImage;
this.#images = await mapValuesAsync(images, ({uri}) => Image.load(uri)); this.$$images = await mapValuesAsync(images, ({uri}) => Image.load(uri));
this.#sprites = await mapValuesAsync(this.#images, async (image) => new Sprite(image)); this.$$sprites = await mapValuesAsync(this.$$images, async (image) => new Sprite(image));
Object.keys(this.#sprites).forEach((key) => { Object.keys(this.$$sprites).forEach((key) => {
// eslint-disable-next-line no-param-reassign // eslint-disable-next-line no-param-reassign
this.#sprites[key].position = this.offsetFor(key); this.$$sprites[key].position = this.offsetFor(key);
}); });
} }
methods() { methods() {
return { return {
image: (key) => this.#sprites[key]?.image, image: (key) => this.$$sprites[key]?.image,
}; };
} }
@ -170,11 +170,11 @@ export default (flecks) => {
} }
setSpriteScale() { setSpriteScale() {
if (!this.#sprites) { if (!this.$$sprites) {
return; return;
} }
const {visibleScale} = this.entity; const {visibleScale} = this.entity;
const sprites = Object.values(this.#sprites); const sprites = Object.values(this.$$sprites);
for (let i = 0; i < sprites.length; i++) { for (let i = 0; i < sprites.length; i++) {
sprites[i].scale = visibleScale; sprites[i].scale = visibleScale;
} }
@ -184,10 +184,10 @@ export default (flecks) => {
if (!this.entity.container) { if (!this.entity.container) {
return; return;
} }
if (!this.#sprites) { if (!this.$$sprites) {
return; return;
} }
const sprite = this.#sprites[key]; const sprite = this.$$sprites[key];
if (!sprite) { if (!sprite) {
return; return;
} }

View File

@ -6,9 +6,9 @@ export default (flecks) => {
return class Primitive extends Trait { return class Primitive extends Trait {
#primitives; $$primitives;
#scheduledDraw = true; $$scheduledDraw = true;
static defaultParams() { static defaultParams() {
return { return {
@ -23,9 +23,9 @@ export default (flecks) => {
} }
destroy() { destroy() {
if (this.#primitives) { if (this.$$primitives) {
this.#primitives.destroy(); this.$$primitives.destroy();
this.#primitives = undefined; this.$$primitives = undefined;
} }
} }
@ -33,12 +33,12 @@ export default (flecks) => {
if (!this.entity.container) { if (!this.entity.container) {
return; return;
} }
if (this.#primitives) { if (this.$$primitives) {
this.#primitives.clear(); this.$$primitives.clear();
} }
else { else {
this.#primitives = new Primitives(); this.$$primitives = new Primitives();
this.entity.addRasterChild(this.#primitives); this.entity.addRasterChild(this.$$primitives);
} }
const colorization = this.entity.is('Colorized') const colorization = this.entity.is('Colorized')
? {rgba: [this.entity.red, this.entity.green, this.entity.blue, 1]} ? {rgba: [this.entity.red, this.entity.green, this.entity.blue, 1]}
@ -57,7 +57,7 @@ export default (flecks) => {
rgba: [0, 0, 0, 0], rgba: [0, 0, 0, 0],
...colorization, ...colorization,
}; };
this.#primitives.drawCircle( this.$$primitives.drawCircle(
primitive.position || [0, 0], primitive.position || [0, 0],
primitive.radius, primitive.radius,
Primitives.lineStyle(new Color(...line.rgba), line.thickness), Primitives.lineStyle(new Color(...line.rgba), line.thickness),
@ -71,27 +71,27 @@ export default (flecks) => {
return { return {
blueChanged: () => { blueChanged: () => {
this.#scheduledDraw = true; this.$$scheduledDraw = true;
}, },
greenChanged: () => { greenChanged: () => {
this.#scheduledDraw = true; this.$$scheduledDraw = true;
}, },
redChanged: () => { redChanged: () => {
this.#scheduledDraw = true; this.$$scheduledDraw = true;
}, },
traitAdded: () => { traitAdded: () => {
this.#scheduledDraw = true; this.$$scheduledDraw = true;
}, },
}; };
} }
renderTick() { renderTick() {
if (this.#scheduledDraw) { if (this.$$scheduledDraw) {
this.#scheduledDraw = false; this.$$scheduledDraw = false;
this.drawPrimitives(); this.drawPrimitives();
} }
} }

View File

@ -5,7 +5,7 @@ export default (flecks) => {
return class RasterText extends Trait { return class RasterText extends Trait {
#text; $$text;
static defaultParams() { static defaultParams() {
return { return {
@ -22,18 +22,18 @@ export default (flecks) => {
destroy() { destroy() {
super.destroy(); super.destroy();
this.entity.removeRasterChild(this.#text); this.entity.removeRasterChild(this.$$text);
} }
loadText() { loadText() {
if (!this.entity.container) { if (!this.entity.container) {
return; return;
} }
if (!this.#text) { if (!this.$$text) {
this.#text = new Text(this.entity.text, this.params.textStyle); this.$$text = new Text(this.entity.text, this.params.textStyle);
this.#text.zIndex = 1000; this.$$text.zIndex = 1000;
} }
this.entity.addRasterChild(this.#text); this.entity.addRasterChild(this.$$text);
} }
listeners() { listeners() {

View File

@ -8,24 +8,24 @@ export default (flecks) => {
return class Rastered extends Trait { return class Rastered extends Trait {
#container; $$container;
#parent; $$parent;
#siblings = new Set(); $$siblings = new Set();
#usingAutoZIndex; $$usingAutoZIndex;
constructor() { constructor() {
super(); super();
if ('web' === process.env.FLECKS_CORE_BUILD_TARGET) { if ('web' === process.env.FLECKS_CORE_BUILD_TARGET) {
this.#container = new Container(); this.$$container = new Container();
this.#container.on('parentChanged', this.onParentChanged, this); this.$$container.on('parentChanged', this.onParentChanged, this);
} }
} }
get container() { get container() {
return this.#container; return this.$$container;
} }
static defaultParams() { static defaultParams() {
@ -42,9 +42,9 @@ export default (flecks) => {
destroy() { destroy() {
super.destroy(); super.destroy();
if (this.#container) { if (this.$$container) {
this.#container.off('parentChanged', this.onParentChanged); this.$$container.off('parentChanged', this.onParentChanged);
this.#container.destroy(); this.$$container.destroy();
} }
} }
@ -52,10 +52,10 @@ export default (flecks) => {
return { return {
isVisibleChanged: () => { isVisibleChanged: () => {
if (!this.#container) { if (!this.$$container) {
return; return;
} }
this.#container.visible = this.entity.isVisible; this.$$container.visible = this.entity.isVisible;
}, },
onYChanged: () => { onYChanged: () => {
@ -63,22 +63,22 @@ export default (flecks) => {
}, },
opacityChanged: () => { opacityChanged: () => {
if (!this.#container) { if (!this.$$container) {
return; return;
} }
this.#container.alpha = this.entity.opacity; this.$$container.alpha = this.entity.opacity;
}, },
rotationChanged: () => { rotationChanged: () => {
if (!this.#container) { if (!this.$$container) {
return; return;
} }
this.#container.rotation = this.entity.rotation; this.$$container.rotation = this.entity.rotation;
}, },
visibleScaleChanged: () => { visibleScaleChanged: () => {
if (this.#container) { if (this.$$container) {
this.#container.scale = this.entity.visibleScale; this.$$container.scale = this.entity.visibleScale;
} }
}, },
@ -92,18 +92,18 @@ export default (flecks) => {
async load(json) { async load(json) {
await super.load(json); await super.load(json);
if ('web' === process.env.FLECKS_CORE_BUILD_TARGET) { if ('web' === process.env.FLECKS_CORE_BUILD_TARGET) {
if (this.#container) { if (this.$$container) {
this.#container.alpha = this.entity.opacity; this.$$container.alpha = this.entity.opacity;
this.#container.rotation = this.entity.rotation; this.$$container.rotation = this.entity.rotation;
this.#container.scale = this.entity.visibleScale; this.$$container.scale = this.entity.visibleScale;
} }
this.onZIndexChanged(this.entity.zIndex); this.onZIndexChanged(this.entity.zIndex);
this.renderTick(); this.renderTick();
const {filter} = this.params; const {filter} = this.params;
if (filter) { if (filter) {
this.#container.setFilter(filter); this.$$container.setFilter(filter);
} }
this.#container.isVisible = this.state.isVisible; this.$$container.isVisible = this.state.isVisible;
} }
} }
@ -115,10 +115,10 @@ export default (flecks) => {
}, },
addRasterSibling: (child) => { addRasterSibling: (child) => {
if (this.#parent) { if (this.$$parent) {
this.#parent.addChild(child); this.$$parent.addChild(child);
} }
this.#siblings.add(child); this.$$siblings.add(child);
}, },
removeRasterChild: (child) => { removeRasterChild: (child) => {
@ -126,39 +126,39 @@ export default (flecks) => {
}, },
removeRasterSibling: (child) => { removeRasterSibling: (child) => {
if (this.#parent) { if (this.$$parent) {
this.#parent.removeChild(child); this.$$parent.removeChild(child);
} }
this.#siblings.remove(child); this.$$siblings.remove(child);
}, },
}; };
} }
onParentChanged(oldParent, newParent) { onParentChanged(oldParent, newParent) {
const siblings = Array.from(this.#siblings); const siblings = Array.from(this.$$siblings);
for (let i = 0; i < siblings.length; i++) { for (let i = 0; i < siblings.length; i++) {
oldParent?.removeChild(siblings[i]); oldParent?.removeChild(siblings[i]);
newParent?.addChild(siblings[i]); newParent?.addChild(siblings[i]);
} }
if (newParent) { if (newParent) {
this.#parent = newParent; this.$$parent = newParent;
} }
} }
onYChanged() { onYChanged() {
if (this.#usingAutoZIndex) { if (this.$$usingAutoZIndex) {
this.#container.zIndex = this.entity.y; this.$$container.zIndex = this.entity.y;
} }
} }
onZIndexChanged(zIndex) { onZIndexChanged(zIndex) {
this.#usingAutoZIndex = AUTO_ZINDEX === zIndex; this.$$usingAutoZIndex = AUTO_ZINDEX === zIndex;
if (!this.#container) { if (!this.$$container) {
return; return;
} }
if (!this.#usingAutoZIndex) { if (!this.$$usingAutoZIndex) {
this.#container.zIndex = zIndex; this.$$container.zIndex = zIndex;
} }
else { else {
this.onYChanged(); this.onYChanged();
@ -171,15 +171,15 @@ export default (flecks) => {
} }
synchronizePosition() { synchronizePosition() {
if (!this.#container) { if (!this.$$container) {
return; return;
} }
this.#container.position = this.entity.position; this.$$container.position = this.entity.position;
} }
synchronizeZIndex() { synchronizeZIndex() {
if (this.#container && this.#usingAutoZIndex) { if (this.$$container && this.$$usingAutoZIndex) {
this.#container.zIndex = this.entity.y; this.$$container.zIndex = this.entity.y;
} }
} }

View File

@ -27,13 +27,13 @@ export default (flecks) => {
return class Visible extends decorate(Trait) { return class Visible extends decorate(Trait) {
#quadTreeAabb = []; $$quadTreeAabb = [];
#rawVisibleAabb = [0, 0, 0, 0]; $$rawVisibleAabb = [0, 0, 0, 0];
#scheduledBoundingBoxUpdate = true; $$scheduledBoundingBoxUpdate = true;
#usingAutoZIndex = true; $$usingAutoZIndex = true;
acceptPacket(packet) { acceptPacket(packet) {
if ('TraitUpdateVisible' === packet.constructor.type) { if ('TraitUpdateVisible' === packet.constructor.type) {
@ -54,7 +54,7 @@ export default (flecks) => {
} }
// Expand the AABB so we don't have to update it every single tick. // Expand the AABB so we don't have to update it every single tick.
const expandedAabb = Rectangle.expand(aabb, [32, 32]); const expandedAabb = Rectangle.expand(aabb, [32, 32]);
this.#quadTreeAabb = expandedAabb; this.$$quadTreeAabb = expandedAabb;
list.quadTree.add(this.entity, expandedAabb); list.quadTree.add(this.entity, expandedAabb);
} }
@ -83,7 +83,7 @@ export default (flecks) => {
// Collect all bounding boxes. // Collect all bounding boxes.
const visibleAabbs = this.entity.invokeHookFlat('visibleAabbs'); const visibleAabbs = this.entity.invokeHookFlat('visibleAabbs');
if (0 === visibleAabbs.length) { if (0 === visibleAabbs.length) {
this.#rawVisibleAabb = [0, 0, 0, 0]; this.$$rawVisibleAabb = [0, 0, 0, 0];
} }
else { else {
let unifiedBoundingBox = [0, 0, 0, 0]; let unifiedBoundingBox = [0, 0, 0, 0];
@ -94,10 +94,10 @@ export default (flecks) => {
visibleAabb, visibleAabb,
); );
} }
this.#rawVisibleAabb = unifiedBoundingBox; this.$$rawVisibleAabb = unifiedBoundingBox;
} }
this.translateVisibleAabb(); this.translateVisibleAabb();
this.#scheduledBoundingBoxUpdate = false; this.$$scheduledBoundingBoxUpdate = false;
} }
listeners() { listeners() {
@ -134,7 +134,7 @@ export default (flecks) => {
}, },
scheduleBoundingBoxUpdate: () => { scheduleBoundingBoxUpdate: () => {
this.#scheduledBoundingBoxUpdate = true; this.$$scheduledBoundingBoxUpdate = true;
}, },
}; };
@ -164,18 +164,18 @@ export default (flecks) => {
return; return;
} }
list.quadTree.remove(this.entity); list.quadTree.remove(this.entity);
this.#quadTreeAabb = []; this.$$quadTreeAabb = [];
} }
tick() { tick() {
if (this.#scheduledBoundingBoxUpdate) { if (this.$$scheduledBoundingBoxUpdate) {
this.forceBoundingBoxUpdate(); this.forceBoundingBoxUpdate();
} }
} }
translateVisibleAabb() { translateVisibleAabb() {
const visibleAabb = Rectangle.translated( const visibleAabb = Rectangle.translated(
this.#rawVisibleAabb, this.$$rawVisibleAabb,
this.entity.position, this.entity.position,
); );
/* eslint-disable prefer-destructuring */ /* eslint-disable prefer-destructuring */
@ -192,8 +192,8 @@ export default (flecks) => {
return; return;
} }
if ( if (
this.#quadTreeAabb.length > 0 this.$$quadTreeAabb.length > 0
&& Rectangle.isInside(this.#quadTreeAabb, this.entity.visibleAabb) && Rectangle.isInside(this.$$quadTreeAabb, this.entity.visibleAabb)
) { ) {
return; return;
} }

View File

@ -6,16 +6,16 @@ const decorate = compose(
export default class ActionRegistry extends decorate(Class) { export default class ActionRegistry extends decorate(Class) {
#listen = { $$listen = {
joystick: {}, joystick: {},
key: {}, key: {},
button: {}, button: {},
wheel: {}, wheel: {},
}; };
#stream = []; $$stream = [];
#transformers = {}; $$transformers = {};
constructor(actions) { constructor(actions) {
super(); super();
@ -26,23 +26,23 @@ export default class ActionRegistry extends decorate(Class) {
for (let j = 0; j < candidates.length; ++j) { for (let j = 0; j < candidates.length; ++j) {
const {index, type, ...rest} = candidates[j]; const {index, type, ...rest} = candidates[j];
if ('joystick' === type) { if ('joystick' === type) {
if (this.#listen[type][index]) { if (this.$$listen[type][index]) {
this.#listen[type][index].push({action, ...rest}); this.$$listen[type][index].push({action, ...rest});
} }
else { else {
this.#listen[type][index] = [{action, ...rest}]; this.$$listen[type][index] = [{action, ...rest}];
} }
} }
else { else {
this.#listen[type][index] = {action}; this.$$listen[type][index] = {action};
} }
} }
} }
} }
drain() { drain() {
const stream = this.#stream; const stream = this.$$stream;
this.#stream = []; this.$$stream = [];
return stream; return stream;
} }
@ -69,21 +69,21 @@ export default class ActionRegistry extends decorate(Class) {
} }
onInput(type, input, value, transforming) { onInput(type, input, value, transforming) {
if (this.#listen[type][input]) { if (this.$$listen[type][input]) {
if ('joystick' === type) { if ('joystick' === type) {
for (let i = 0; i < this.#listen[type][input].length; i++) { for (let i = 0; i < this.$$listen[type][input].length; i++) {
const {action, axis} = this.#listen[type][input][i]; const {action, axis} = this.$$listen[type][input][i];
if ( if (
(axis > 0 && value > 0) (axis > 0 && value > 0)
|| (axis < 0 && value < 0) || (axis < 0 && value < 0)
) { ) {
this.#stream.push({ this.$$stream.push({
action, action,
value: this.transform(action, value * axis, 'joystick'), value: this.transform(action, value * axis, 'joystick'),
}); });
} }
else if (0 === value) { else if (0 === value) {
this.#stream.push({ this.$$stream.push({
action, action,
value: this.transform(action, value, 'joystick'), value: this.transform(action, value, 'joystick'),
}); });
@ -91,8 +91,8 @@ export default class ActionRegistry extends decorate(Class) {
} }
} }
else { else {
const {action} = this.#listen[type][input]; const {action} = this.$$listen[type][input];
this.#stream.push({ this.$$stream.push({
action, action,
value: this.transform(action, value, transforming), value: this.transform(action, value, transforming),
}); });
@ -121,7 +121,7 @@ export default class ActionRegistry extends decorate(Class) {
} }
setTransformerFor(action, transformer) { setTransformerFor(action, transformer) {
this.#transformers[action] = transformer; this.$$transformers[action] = transformer;
} }
stopListening() { stopListening() {
@ -138,7 +138,7 @@ export default class ActionRegistry extends decorate(Class) {
} }
transform(action, value, transforming) { transform(action, value, transforming) {
return this.#transformers[action] ? this.#transformers[action](transforming, value) : value; return this.$$transformers[action] ? this.$$transformers[action](transforming, value) : value;
} }
} }

View File

@ -12,12 +12,12 @@ const decorate = compose(
// Input handling. // Input handling.
export default () => class Controllable extends decorate(Trait) { export default () => class Controllable extends decorate(Trait) {
#actionRegistry; $$actionRegistry;
#queued = []; $$queued = [];
get actionRegistry() { get actionRegistry() {
return this.#actionRegistry; return this.$$actionRegistry;
} }
static defaultParams() { static defaultParams() {
@ -40,7 +40,7 @@ export default () => class Controllable extends decorate(Trait) {
destroy() { destroy() {
super.destroy(); super.destroy();
this.#actionRegistry.stopListening(); this.$$actionRegistry.stopListening();
} }
get inputActions() { get inputActions() {
@ -49,7 +49,7 @@ export default () => class Controllable extends decorate(Trait) {
async load(json) { async load(json) {
await super.load(json); await super.load(json);
this.#actionRegistry = new ActionRegistry(this.params.actions); this.$$actionRegistry = new ActionRegistry(this.params.actions);
} }
methods() { methods() {
@ -63,20 +63,20 @@ export default () => class Controllable extends decorate(Trait) {
.every((result) => false !== result) .every((result) => false !== result)
) { ) {
if ('web' === process.env.FLECKS_CORE_BUILD_TARGET) { if ('web' === process.env.FLECKS_CORE_BUILD_TARGET) {
this.#queued.push(actionStream[i]); this.$$queued.push(actionStream[i]);
} }
} }
} }
}, },
drainInput: () => { drainInput: () => {
const drained = this.#queued; const drained = this.$$queued;
this.#queued = []; this.$$queued = [];
return drained; return drained;
}, },
listenForInput: (inputNormalizer) => { listenForInput: (inputNormalizer) => {
this.#actionRegistry.listen(inputNormalizer); this.$$actionRegistry.listen(inputNormalizer);
}, },
}; };
@ -84,7 +84,7 @@ export default () => class Controllable extends decorate(Trait) {
tick() { tick() {
if ('web' === process.env.FLECKS_CORE_BUILD_TARGET) { if ('web' === process.env.FLECKS_CORE_BUILD_TARGET) {
const drained = this.#actionRegistry.drain(); const drained = this.$$actionRegistry.drain();
this.entity.acceptActionStream(drained); this.entity.acceptActionStream(drained);
} }
} }

View File

@ -5,21 +5,21 @@ import {Trait} from '@avocado/traits';
export default () => class Initiator extends Trait { export default () => class Initiator extends Trait {
#adjustmentThrobber; $$adjustmentThrobber;
#glowThrobber; $$glowThrobber;
#ticker = new Ticker(1 / 20); $$ticker = new Ticker(1 / 20);
#target; $$target;
constructor() { constructor() {
super(); super();
this.#ticker.on('tick', this.determineTarget, this); this.$$ticker.on('tick', this.determineTarget, this);
if ('web' === process.env.FLECKS_CORE_BUILD_TARGET) { if ('web' === process.env.FLECKS_CORE_BUILD_TARGET) {
this.#adjustmentThrobber = {brightness: 1.5}; this.$$adjustmentThrobber = {brightness: 1.5};
this.#adjustmentThrobber.lfo = new LfoResult( this.$$adjustmentThrobber.lfo = new LfoResult(
this.#adjustmentThrobber, this.$$adjustmentThrobber,
{ {
brightness: { brightness: {
frequency: 0.75, frequency: 0.75,
@ -29,9 +29,9 @@ export default () => class Initiator extends Trait {
}, },
}, },
); );
this.#glowThrobber = {outerStrength: 0.125}; this.$$glowThrobber = {outerStrength: 0.125};
this.#glowThrobber.lfo = new LfoResult( this.$$glowThrobber.lfo = new LfoResult(
this.#glowThrobber, this.$$glowThrobber,
{ {
outerStrength: { outerStrength: {
frequency: 0.75, frequency: 0.75,
@ -72,9 +72,9 @@ export default () => class Initiator extends Trait {
interactives.push(entities[i]); interactives.push(entities[i]);
} }
} }
const oldTarget = this.#target; const oldTarget = this.$$target;
if (interactives.length > 0) { if (interactives.length > 0) {
[this.#target] = interactives [this.$$target] = interactives
.filter((interactive) => Rectangle.isTouching(query, interactive.position)) .filter((interactive) => Rectangle.isTouching(query, interactive.position))
.filter((interactive) => interactive.isInteractive) .filter((interactive) => interactive.isInteractive)
.map((interactive) => [interactive.distanceFrom({position: incident}), interactive]) .map((interactive) => [interactive.distanceFrom({position: incident}), interactive])
@ -82,10 +82,10 @@ export default () => class Initiator extends Trait {
.map(([, interactive]) => interactive); .map(([, interactive]) => interactive);
} }
else { else {
this.#target = undefined; this.$$target = undefined;
} }
if (oldTarget !== this.#target) { if (oldTarget !== this.$$target) {
this.targetChanged(oldTarget, this.#target); this.targetChanged(oldTarget, this.$$target);
} }
} }
@ -95,8 +95,8 @@ export default () => class Initiator extends Trait {
acceptAction: ({action, value}) => { acceptAction: ({action, value}) => {
if ('web' !== process.env.FLECKS_CORE_BUILD_TARGET) { if ('web' !== process.env.FLECKS_CORE_BUILD_TARGET) {
if ('Interact' === action && value) { if ('Interact' === action && value) {
if (this.#target) { if (this.$$target) {
this.#target.interact(this.entity); this.$$target.interact(this.entity);
} }
} }
} }
@ -110,10 +110,10 @@ export default () => class Initiator extends Trait {
oldTarget?.container?.removeFilter('interactive', 'adjustment'); oldTarget?.container?.removeFilter('interactive', 'adjustment');
oldTarget?.container?.removeFilter('interactive', 'glow'); oldTarget?.container?.removeFilter('interactive', 'glow');
if ('web' === process.env.FLECKS_CORE_BUILD_TARGET) { if ('web' === process.env.FLECKS_CORE_BUILD_TARGET) {
this.#adjustmentThrobber.lfo.properties.brightness.location = 0; this.$$adjustmentThrobber.lfo.properties.brightness.location = 0;
this.#adjustmentThrobber.lfo.tick(0); this.$$adjustmentThrobber.lfo.tick(0);
this.#glowThrobber.lfo.properties.outerStrength.location = 0; this.$$glowThrobber.lfo.properties.outerStrength.location = 0;
this.#glowThrobber.lfo.tick(0); this.$$glowThrobber.lfo.tick(0);
} }
} }
@ -123,19 +123,19 @@ export default () => class Initiator extends Trait {
} }
tick(elapsed) { tick(elapsed) {
this.#ticker.tick(elapsed); this.$$ticker.tick(elapsed);
} }
tickAdjustment(elapsed) { tickAdjustment(elapsed) {
const {brightness, lfo} = this.#adjustmentThrobber; const {brightness, lfo} = this.$$adjustmentThrobber;
lfo.tick(elapsed); lfo.tick(elapsed);
this.#target?.container?.addFilter('interactive', 'adjustment', {brightness}); this.$$target?.container?.addFilter('interactive', 'adjustment', {brightness});
} }
tickGlow(elapsed) { tickGlow(elapsed) {
const {outerStrength, lfo} = this.#glowThrobber; const {outerStrength, lfo} = this.$$glowThrobber;
lfo.tick(elapsed); lfo.tick(elapsed);
this.#target?.container?.addFilter('interactive', 'glow', {color: 0, outerStrength}); this.$$target?.container?.addFilter('interactive', 'glow', {color: 0, outerStrength});
} }
}; };

View File

@ -7,7 +7,7 @@ const decorate = compose(
export default (flecks) => class Interactive extends decorate(Trait) { export default (flecks) => class Interactive extends decorate(Trait) {
#actions; $$actions;
acceptPacket(packet) { acceptPacket(packet) {
if ('TraitInteractive' === packet.constructor.type) { if ('TraitInteractive' === packet.constructor.type) {

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
export default (EntityList) => class PhysicsEntityList extends EntityList { export default (EntityList) => class PhysicsEntityList extends EntityList {
#world; $$world;
constructor() { constructor() {
super(); super();
@ -10,7 +10,7 @@ export default (EntityList) => class PhysicsEntityList extends EntityList {
onEntityAdded(entity) { onEntityAdded(entity) {
// eslint-disable-next-line no-param-reassign // eslint-disable-next-line no-param-reassign
entity.world = this.#world; entity.world = this.$$world;
} }
// eslint-disable-next-line class-methods-use-this // eslint-disable-next-line class-methods-use-this
@ -27,7 +27,7 @@ export default (EntityList) => class PhysicsEntityList extends EntityList {
entity.world = world; entity.world = world;
} }
} }
this.#world = world; this.$$world = world;
} }
}; };

View File

@ -6,11 +6,11 @@ import PolygonShape from '@avocado/physics/shape/polygon';
export default (Tiles) => class PhysicsTiles extends Tiles { export default (Tiles) => class PhysicsTiles extends Tiles {
#bodies = []; $$bodies = [];
#impassable = {}; $$impassable = {};
#world; $$world;
constructor() { constructor() {
super(); super();
@ -18,27 +18,27 @@ export default (Tiles) => class PhysicsTiles extends Tiles {
} }
addBodies() { addBodies() {
if (!this.#world) { if (!this.$$world) {
return; return;
} }
const hulls = this.indexHulls(this.#impassable); const hulls = this.indexHulls(this.$$impassable);
for (let i = 0; i < hulls.length; ++i) { for (let i = 0; i < hulls.length; ++i) {
const scaled = []; const scaled = [];
for (let j = 0; j < hulls[i].length; ++j) { for (let j = 0; j < hulls[i].length; ++j) {
scaled.push(Vector.mul(hulls[i][j], this.tileSize)); scaled.push(Vector.mul(hulls[i][j], this.tileSize));
} }
const [vertices, position] = Vertice.localize(scaled); const [vertices, position] = Vertice.localize(scaled);
const body = this.#world.createBody(new PolygonShape({position, vertices})); const body = this.$$world.createBody(new PolygonShape({position, vertices}));
body.static = true; body.static = true;
this.#bodies.push(body); this.$$bodies.push(body);
this.#world.addBody(body); this.$$world.addBody(body);
} }
} }
async load(json = {}) { async load(json = {}) {
await super.load(json); await super.load(json);
const {impassable = []} = json; const {impassable = []} = json;
this.#impassable = new Set(impassable); this.$$impassable = new Set(impassable);
} }
onTilesUpdate() { onTilesUpdate() {
@ -47,17 +47,17 @@ export default (Tiles) => class PhysicsTiles extends Tiles {
} }
removeBodies() { removeBodies() {
if (this.#bodies.length > 0 && this.#world) { if (this.$$bodies.length > 0 && this.$$world) {
for (let i = 0; i < this.#bodies.length; i++) { for (let i = 0; i < this.$$bodies.length; i++) {
this.#world.removeBody(this.#bodies[i]); this.$$world.removeBody(this.$$bodies[i]);
} }
this.#bodies = []; this.$$bodies = [];
} }
} }
set world(world) { set world(world) {
this.removeBodies(); this.removeBodies();
this.#world = world; this.$$world = world;
this.addBodies(); this.addBodies();
} }

View File

@ -4,14 +4,14 @@ import Shape from './shape';
export default class PolygonShape extends Shape { export default class PolygonShape extends Shape {
#cachedTranslatedVertices; $$cachedTranslatedVertices;
#vertices; $$vertices;
constructor(shape) { constructor(shape) {
super(shape); super(shape);
this.#cachedTranslatedVertices = []; this.$$cachedTranslatedVertices = [];
this.#vertices = []; this.$$vertices = [];
this.on([ this.on([
'parentOriginChanged', 'parentOriginChanged',
'parentRotationChanged', 'parentRotationChanged',
@ -40,13 +40,13 @@ export default class PolygonShape extends Shape {
} }
get aabb() { get aabb() {
if (0 === this.#vertices.length) { if (0 === this.$$vertices.length) {
return [0, 0, 0, 0]; return [0, 0, 0, 0];
} }
const min = [Infinity, Infinity]; const min = [Infinity, Infinity];
const max = [-Infinity, -Infinity]; const max = [-Infinity, -Infinity];
for (let i = 0; i < this.#cachedTranslatedVertices.length; i++) { for (let i = 0; i < this.$$cachedTranslatedVertices.length; i++) {
const vertice = this.#cachedTranslatedVertices[i]; const vertice = this.$$cachedTranslatedVertices[i];
min[0] = vertice[0] < min[0] ? vertice[0] : min[0]; min[0] = vertice[0] < min[0] ? vertice[0] : min[0];
min[1] = vertice[1] < min[1] ? vertice[1] : min[1]; min[1] = vertice[1] < min[1] ? vertice[1] : min[1];
max[0] = vertice[0] > max[0] ? vertice[0] : max[0]; max[0] = vertice[0] > max[0] ? vertice[0] : max[0];
@ -65,18 +65,18 @@ export default class PolygonShape extends Shape {
const rotation = this.rotation + parentRotation; const rotation = this.rotation + parentRotation;
const parentScale = this.parent ? this.parent.scale : 1; const parentScale = this.parent ? this.parent.scale : 1;
const scale = this.scale * parentScale; const scale = this.scale * parentScale;
this.#cachedTranslatedVertices = this.#vertices.map((vertice) => ( this.$$cachedTranslatedVertices = this.$$vertices.map((vertice) => (
Vertice.translate(vertice, origin, rotation, scale) Vertice.translate(vertice, origin, rotation, scale)
)); ));
this.emit('aabbChanged'); this.emit('aabbChanged');
} }
get vertices() { get vertices() {
return this.#cachedTranslatedVertices; return this.$$cachedTranslatedVertices;
} }
set vertices(vertices) { set vertices(vertices) {
this.#vertices = [...vertices]; this.$$vertices = [...vertices];
this.emit('verticesChanged'); this.emit('verticesChanged');
} }

View File

@ -9,22 +9,22 @@ const decorate = compose(
export default (flecks) => class Collider extends decorate(Trait) { export default (flecks) => class Collider extends decorate(Trait) {
#collidesWithGroups = []; $$collidesWithGroups = [];
#collisionGroup = ''; $$collisionGroup = '';
#doesNotCollideWith = []; $$doesNotCollideWith = [];
#isCollidingWith = []; $$isCollidingWith = [];
#isSensor = false; $$isSensor = false;
constructor() { constructor() {
super(); super();
({ ({
collidesWithGroups: this.#collidesWithGroups, collidesWithGroups: this.$$collidesWithGroups,
collisionGroup: this.#collisionGroup, collisionGroup: this.$$collisionGroup,
isSensor: this.#isSensor, isSensor: this.$$isSensor,
} = this.constructor.defaultParams()); } = this.constructor.defaultParams());
} }
@ -107,21 +107,21 @@ export default (flecks) => class Collider extends decorate(Trait) {
} }
get collisionGroup() { get collisionGroup() {
return this.#collisionGroup; return this.$$collisionGroup;
} }
get collidesWithGroups() { get collidesWithGroups() {
return this.#collidesWithGroups; return this.$$collidesWithGroups;
} }
indexOfCollidingEntity(entity) { indexOfCollidingEntity(entity) {
return this.#isCollidingWith.findIndex( return this.$$isCollidingWith.findIndex(
({entity: collisionEntity}) => entity === collisionEntity, ({entity: collisionEntity}) => entity === collisionEntity,
); );
} }
get isCollidingWith() { get isCollidingWith() {
return this.#isCollidingWith; return this.$$isCollidingWith;
} }
isCollidingWithEntity(entity) { isCollidingWithEntity(entity) {
@ -129,7 +129,7 @@ export default (flecks) => class Collider extends decorate(Trait) {
} }
get isSensor() { get isSensor() {
return this.#isSensor; return this.$$isSensor;
} }
async load(json) { async load(json) {
@ -139,9 +139,9 @@ export default (flecks) => class Collider extends decorate(Trait) {
collisionGroup, collisionGroup,
isSensor, isSensor,
} = this.params; } = this.params;
this.#collidesWithGroups = collidesWithGroups; this.$$collidesWithGroups = collidesWithGroups;
this.#collisionGroup = collisionGroup; this.$$collisionGroup = collisionGroup;
this.#isSensor = isSensor; this.$$isSensor = isSensor;
} }
async pushCollisionTickingPromise(codeOrUri, other, incident) { async pushCollisionTickingPromise(codeOrUri, other, incident) {
@ -154,11 +154,11 @@ export default (flecks) => class Collider extends decorate(Trait) {
} }
releaseAllCollisions() { releaseAllCollisions() {
for (let i = 0; i < this.#isCollidingWith.length; i++) { for (let i = 0; i < this.$$isCollidingWith.length; i++) {
const {entity} = this.#isCollidingWith[i]; const {entity} = this.$$isCollidingWith[i];
entity.emit('collisionEnd', this.entity); entity.emit('collisionEnd', this.entity);
} }
this.#isCollidingWith = []; this.$$isCollidingWith = [];
} }
// eslint-disable-next-line class-methods-use-this // eslint-disable-next-line class-methods-use-this
@ -176,7 +176,7 @@ export default (flecks) => class Collider extends decorate(Trait) {
collisionEnd: (other, incident) => { collisionEnd: (other, incident) => {
const index = this.indexOfCollidingEntity(other); const index = this.indexOfCollidingEntity(other);
if (-1 !== index) { if (-1 !== index) {
this.#isCollidingWith.splice(index, 1); this.$$isCollidingWith.splice(index, 1);
if (this.params.collisionEndScript) { if (this.params.collisionEndScript) {
this.pushCollisionTickingPromise(this.params.collisionEndScript, other, incident); this.pushCollisionTickingPromise(this.params.collisionEndScript, other, incident);
} }
@ -186,7 +186,7 @@ export default (flecks) => class Collider extends decorate(Trait) {
collisionStart: (other, incident) => { collisionStart: (other, incident) => {
const index = this.indexOfCollidingEntity(other); const index = this.indexOfCollidingEntity(other);
if (-1 === index) { if (-1 === index) {
this.#isCollidingWith.push({ this.$$isCollidingWith.push({
entity: other, entity: other,
incident, incident,
}); });
@ -210,25 +210,25 @@ export default (flecks) => class Collider extends decorate(Trait) {
if (!this.entity.isColliding || !entity.isColliding) { if (!this.entity.isColliding || !entity.isColliding) {
return false; return false;
} }
if (-1 !== this.#doesNotCollideWith.indexOf(entity)) { if (-1 !== this.$$doesNotCollideWith.indexOf(entity)) {
return false; return false;
} }
const {collisionGroup} = entity; const {collisionGroup} = entity;
return -1 !== this.#collidesWithGroups.indexOf(collisionGroup); return -1 !== this.$$collidesWithGroups.indexOf(collisionGroup);
}, },
doesNotCollideWith: (entity) => !this.entity.collidesWith(entity), doesNotCollideWith: (entity) => !this.entity.collidesWith(entity),
setDoesCollideWith: (entity) => { setDoesCollideWith: (entity) => {
const index = this.#doesNotCollideWith.indexOf(entity); const index = this.$$doesNotCollideWith.indexOf(entity);
if (-1 !== index) { if (-1 !== index) {
this.#doesNotCollideWith.splice(index, 1); this.$$doesNotCollideWith.splice(index, 1);
} }
}, },
setDoesNotCollideWith: (entity) => { setDoesNotCollideWith: (entity) => {
if (-1 === this.#doesNotCollideWith.indexOf(entity)) { if (-1 === this.$$doesNotCollideWith.indexOf(entity)) {
this.#doesNotCollideWith.push(entity); this.$$doesNotCollideWith.push(entity);
} }
}, },
}; };

View File

@ -7,39 +7,39 @@ const decorate = compose(
export default (flecks) => class Emitted extends decorate(Trait) { export default (flecks) => class Emitted extends decorate(Trait) {
#alphaStart; $$alphaStart;
#alphaEnd; $$alphaEnd;
#force; $$force;
#mass; $$mass;
#position; $$position;
#rotationStart; $$rotationStart;
#rotationAdd; $$rotationAdd;
#ttl; $$ttl;
#velocityAngle; $$velocityAngle;
#velocityMagnitude; $$velocityMagnitude;
constructor(...args) { constructor(...args) {
super(...args); super(...args);
const params = this.constructor.defaultParams(); const params = this.constructor.defaultParams();
this.#alphaStart = new Range(params.alpha.start); this.$$alphaStart = new Range(params.alpha.start);
this.#alphaEnd = new Range(params.alpha.end); this.$$alphaEnd = new Range(params.alpha.end);
this.#force = new Vector.Range(params.force); this.$$force = new Vector.Range(params.force);
this.#mass = params.mass; this.$$mass = params.mass;
this.#position = null; this.$$position = null;
this.#rotationStart = new Range(params.rotation.start); this.$$rotationStart = new Range(params.rotation.start);
this.#rotationAdd = new Range(params.rotation.add); this.$$rotationAdd = new Range(params.rotation.add);
this.#ttl = new Range(params.ttl); this.$$ttl = new Range(params.ttl);
this.#velocityAngle = new Range(params.velocity.angle); this.$$velocityAngle = new Range(params.velocity.angle);
this.#velocityMagnitude = new Range(params.velocity.magnitude); this.$$velocityMagnitude = new Range(params.velocity.magnitude);
} }
static behaviorTypes() { static behaviorTypes() {
@ -85,21 +85,21 @@ export default (flecks) => class Emitted extends decorate(Trait) {
async load(json) { async load(json) {
await super.load(json); await super.load(json);
this.#alphaStart = new Range(this.params.alpha.start); this.$$alphaStart = new Range(this.params.alpha.start);
this.#alphaEnd = new Range(this.params.alpha.end); this.$$alphaEnd = new Range(this.params.alpha.end);
this.#force = new Vector.Range(this.params.force); this.$$force = new Vector.Range(this.params.force);
this.#mass = this.params.mass; this.$$mass = this.params.mass;
if (null !== this.params.position) { if (null !== this.params.position) {
this.#position = new Vector.Range(this.params.position); this.$$position = new Vector.Range(this.params.position);
} }
else { else {
this.#position = null; this.$$position = null;
} }
this.#rotationStart = new Range(this.params.rotation.start); this.$$rotationStart = new Range(this.params.rotation.start);
this.#rotationAdd = new Range(this.params.rotation.add); this.$$rotationAdd = new Range(this.params.rotation.add);
this.#ttl = new Range(this.params.ttl); this.$$ttl = new Range(this.params.ttl);
this.#velocityAngle = new Range(this.params.velocity.angle); this.$$velocityAngle = new Range(this.params.velocity.angle);
this.#velocityMagnitude = new Range(this.params.velocity.magnitude); this.$$velocityMagnitude = new Range(this.params.velocity.magnitude);
} }
listeners() { listeners() {
@ -121,25 +121,25 @@ export default (flecks) => class Emitted extends decorate(Trait) {
return { return {
particle: () => { particle: () => {
const position = null === this.#position ? null : this.#position.value(); const position = null === this.$$position ? null : this.$$position.value();
const force = this.#force.value(); const force = this.$$force.value();
const particle = { const particle = {
alpha: { alpha: {
start: this.#alphaStart.value(), start: this.$$alphaStart.value(),
end: this.#alphaEnd.value(), end: this.$$alphaEnd.value(),
}, },
force, force,
listed: this.params.listed, listed: this.params.listed,
mass: this.#mass, mass: this.$$mass,
position, position,
rotation: { rotation: {
start: this.#rotationStart.value(), start: this.$$rotationStart.value(),
add: this.#rotationAdd.value(), add: this.$$rotationAdd.value(),
}, },
ttl: this.#ttl.value(), ttl: this.$$ttl.value(),
velocity: { velocity: {
angle: this.#velocityAngle.value(), angle: this.$$velocityAngle.value(),
magnitude: this.#velocityMagnitude.value(), magnitude: this.$$velocityMagnitude.value(),
}, },
}; };
if (this.params.scale) { if (this.params.scale) {

View File

@ -12,30 +12,30 @@ const decorate = compose(
export default (flecks) => class Emitter extends decorate(Trait) { export default (flecks) => class Emitter extends decorate(Trait) {
#emissions = []; $$emissions = [];
#emitter = new Proton.Emitter(); $$emitter = new Proton.Emitter();
#emitting = []; $$emitting = [];
#onParticleDead; $$onParticleDead;
#onParticleUpdate; $$onParticleUpdate;
#particles = {}; $$particles = {};
#proton = new Proton(); $$proton = new Proton();
#streams = []; $$streams = [];
constructor() { constructor() {
super(); super();
this.#proton.addEmitter(this.#emitter); this.$$proton.addEmitter(this.$$emitter);
this.#onParticleDead = this.onParticleDead.bind(this); this.$$onParticleDead = this.onParticleDead.bind(this);
this.#onParticleUpdate = this.onParticleUpdate.bind(this); this.$$onParticleUpdate = this.onParticleUpdate.bind(this);
this.#emitter.bindEvent = true; this.$$emitter.bindEvent = true;
this.#emitter.addEventListener('PARTICLE_DEAD', this.#onParticleDead); this.$$emitter.addEventListener('PARTICLE_DEAD', this.$$onParticleDead);
this.#emitter.addEventListener('PARTICLE_UPDATE', this.#onParticleUpdate); this.$$emitter.addEventListener('PARTICLE_UPDATE', this.$$onParticleUpdate);
} }
acceptPacket(packet) { acceptPacket(packet) {
@ -48,7 +48,7 @@ export default (flecks) => class Emitter extends decorate(Trait) {
cleanPackets() { cleanPackets() {
super.cleanPackets(); super.cleanPackets();
this.#emitting = []; this.$$emitting = [];
} }
static defaultParams() { static defaultParams() {
@ -77,20 +77,20 @@ export default (flecks) => class Emitter extends decorate(Trait) {
const [key, particle] = paramParticles[i]; const [key, particle] = paramParticles[i];
particles[key] = merge(particles[key] || {}, particle); particles[key] = merge(particles[key] || {}, particle);
} }
this.#particles = particles; this.$$particles = particles;
} }
hooks() { hooks() {
const hooks = {}; const hooks = {};
hooks.afterDestructionTickers = () => (elapsed) => { hooks.afterDestructionTickers = () => (elapsed) => {
if (0 === this.#emitter.particles.length) { if (0 === this.$$emitter.particles.length) {
this.#emitter.destroy(); this.$$emitter.destroy();
return true; return true;
} }
this.tick(elapsed); this.tick(elapsed);
return false; return false;
}; };
hooks.destroy = () => () => 0 === this.#streams.length; hooks.destroy = () => () => 0 === this.$$streams.length;
return hooks; return hooks;
} }
@ -152,7 +152,7 @@ export default (flecks) => class Emitter extends decorate(Trait) {
), ),
); );
} }
const protonParticle = this.#emitter.createParticle( const protonParticle = this.$$emitter.createParticle(
initializers, initializers,
behaviors, behaviors,
); );
@ -166,7 +166,7 @@ export default (flecks) => class Emitter extends decorate(Trait) {
this.entity.list.addEntity(entity); this.entity.list.addEntity(entity);
} }
// Prime. // Prime.
this.#onParticleUpdate(protonParticle); this.$$onParticleUpdate(protonParticle);
return entity; return entity;
}, },
@ -188,7 +188,7 @@ export default (flecks) => class Emitter extends decorate(Trait) {
json, json,
); );
if (transmit && 'web' !== process.env.FLECKS_CORE_BUILD_TARGET) { if (transmit && 'web' !== process.env.FLECKS_CORE_BUILD_TARGET) {
this.#emitting.push(augmentedJson); this.$$emitting.push(augmentedJson);
this.markAsDirty(); this.markAsDirty();
} }
const stream = K.stream((emitter) => { const stream = K.stream((emitter) => {
@ -209,9 +209,9 @@ export default (flecks) => class Emitter extends decorate(Trait) {
count -= 1; count -= 1;
if (count > 0) { if (count > 0) {
const removeEmission = () => { const removeEmission = () => {
const index = this.#emissions.indexOf(ticker); const index = this.$$emissions.indexOf(ticker);
if (-1 !== index) { if (-1 !== index) {
this.#emissions.splice(index, 1); this.$$emissions.splice(index, 1);
} }
emitter.end(); emitter.end();
}; };
@ -222,27 +222,27 @@ export default (flecks) => class Emitter extends decorate(Trait) {
removeEmission(); removeEmission();
} }
}); });
this.#emissions.push(ticker); this.$$emissions.push(ticker);
} }
} }
}); });
this.#streams.push(stream); this.$$streams.push(stream);
stream.onEnd(() => { stream.onEnd(() => {
const index = this.#streams.indexOf(stream); const index = this.$$streams.indexOf(stream);
this.#streams.splice(index, 1); this.$$streams.splice(index, 1);
}); });
return stream; return stream;
}, },
emitParticle: (key, json = {}) => { emitParticle: (key, json = {}) => {
const particleJson = this.#particles[key]; const particleJson = this.$$particles[key];
if (!particleJson) { if (!particleJson) {
return undefined; return undefined;
} }
return this.entity.emitParticleJson(merge(particleJson, json)); return this.entity.emitParticleJson(merge(particleJson, json));
}, },
jsonForParticle: (key, json = {}) => merge(this.#particles[key] || {}, json), jsonForParticle: (key, json = {}) => merge(this.$$particles[key] || {}, json),
}; };
} }
@ -271,15 +271,15 @@ export default (flecks) => class Emitter extends decorate(Trait) {
} }
packetsFor() { packetsFor() {
return this.#emitting.length > 0 return this.$$emitting.length > 0
? [['EmitParticles', this.#emitting]] ? [['EmitParticles', this.$$emitting]]
: []; : [];
} }
tick(elapsed) { tick(elapsed) {
this.#emitter.update(elapsed); this.$$emitter.update(elapsed);
for (let i = 0; i < this.#emissions.length; i++) { for (let i = 0; i < this.$$emissions.length; i++) {
this.#emissions[i].tick(elapsed); this.$$emissions[i].tick(elapsed);
} }
} }

View File

@ -12,28 +12,28 @@ const decorate = compose(
export default () => class Physical extends decorate(Trait) { export default () => class Physical extends decorate(Trait) {
#body; $$body;
#bodyView; $$bodyView;
#world; $$world;
addToWorld() { addToWorld() {
const world = this.#world; const world = this.$$world;
if (world) { if (world) {
const body = world.createBody(this.entity.shape); const body = world.createBody(this.entity.shape);
body.friction = this.entity.friction; body.friction = this.entity.friction;
world.associateBodyWithEntity(body, this.entity); world.associateBodyWithEntity(body, this.entity);
body.setCollisionForEntity(this.entity); body.setCollisionForEntity(this.entity);
world.addBody(body); world.addBody(body);
this.#body = body; this.$$body = body;
if ('web' === process.env.FLECKS_CORE_BUILD_TARGET) { if ('web' === process.env.FLECKS_CORE_BUILD_TARGET) {
if (this.entity.is('Visible') && this.params.isDebugging) { if (this.entity.is('Visible') && this.params.isDebugging) {
this.#bodyView = new BodyView(body); this.$$bodyView = new BodyView(body);
this.#bodyView.position = Vector.scale(this.entity.position, -1); this.$$bodyView.position = Vector.scale(this.entity.position, -1);
this.#bodyView.visible = true; this.$$bodyView.visible = true;
this.#bodyView.zIndex = 101; this.$$bodyView.zIndex = 101;
this.entity.addRasterChild(this.#bodyView); this.entity.addRasterChild(this.$$bodyView);
} }
} }
} }
@ -63,7 +63,7 @@ export default () => class Physical extends decorate(Trait) {
} }
get body() { get body() {
return this.#body; return this.$$body;
} }
static defaultParams() { static defaultParams() {
@ -101,19 +101,19 @@ export default () => class Physical extends decorate(Trait) {
}, },
frictionChanged: () => { frictionChanged: () => {
if (this.#body) { if (this.$$body) {
this.#body.friction = this.entity.friction; this.$$body.friction = this.entity.friction;
} }
}, },
positionChanged: () => { positionChanged: () => {
if (this.#body) { if (this.$$body) {
this.#body.position = this.entity.position; this.$$body.position = this.entity.position;
} }
}, },
removedFromRoom: () => { removedFromRoom: () => {
if (this.#body) { if (this.$$body) {
this.removeFromWorld(); this.removeFromWorld();
} }
}, },
@ -125,14 +125,14 @@ export default () => class Physical extends decorate(Trait) {
return { return {
applyForce: (force) => { applyForce: (force) => {
if (this.#world && this.#body) { if (this.$$world && this.$$body) {
this.#body.applyForce(force); this.$$body.applyForce(force);
} }
}, },
applyImpulse: (impulse) => { applyImpulse: (impulse) => {
if (this.#world && this.#body) { if (this.$$world && this.$$body) {
this.#body.applyImpulse(impulse); this.$$body.applyImpulse(impulse);
} }
}, },
@ -140,25 +140,25 @@ export default () => class Physical extends decorate(Trait) {
} }
removeFromWorld() { removeFromWorld() {
if (this.#world && this.#body) { if (this.$$world && this.$$body) {
this.#world.removeBody(this.#body); this.$$world.removeBody(this.$$body);
} }
this.#body = undefined; this.$$body = undefined;
if (this.#bodyView) { if (this.$$bodyView) {
if (this.entity.is('Visible')) { if (this.entity.is('Visible')) {
this.entity.removeRasterChild(this.#bodyView); this.entity.removeRasterChild(this.$$bodyView);
} }
this.#bodyView.destroy(); this.$$bodyView.destroy();
} }
this.#bodyView = undefined; this.$$bodyView = undefined;
} }
set world(world) { set world(world) {
if (this.#world === world) { if (this.$$world === world) {
return; return;
} }
this.removeFromWorld(); this.removeFromWorld();
this.#world = world; this.$$world = world;
this.addToWorld(); this.addToWorld();
} }

View File

@ -9,9 +9,9 @@ const decorate = compose(
export default () => class Shaped extends decorate(Trait) { export default () => class Shaped extends decorate(Trait) {
#shape; $$shape;
#shapeView; $$shapeView;
static defaultParams() { static defaultParams() {
return { return {
@ -26,11 +26,11 @@ export default () => class Shaped extends decorate(Trait) {
destroy() { destroy() {
super.destroy(); super.destroy();
this.#shape.destroy(); this.$$shape.destroy();
if (this.#shapeView) { if (this.$$shapeView) {
this.entity.removeRasterChild(this.#shapeView); this.entity.removeRasterChild(this.$$shapeView);
this.#shapeView.destroy(); this.$$shapeView.destroy();
this.#shapeView = undefined; this.$$shapeView = undefined;
} }
} }
@ -40,11 +40,11 @@ export default () => class Shaped extends decorate(Trait) {
traitAdded: () => { traitAdded: () => {
if ('web' === process.env.FLECKS_CORE_BUILD_TARGET) { if ('web' === process.env.FLECKS_CORE_BUILD_TARGET) {
if (this.entity.is('Visible') && this.params.isDebugging) { if (this.entity.is('Visible') && this.params.isDebugging) {
if (!this.#shapeView) { if (!this.$$shapeView) {
this.#shapeView = new ShapeView(this.entity.shape); this.$$shapeView = new ShapeView(this.entity.shape);
this.#shapeView.visible = false; this.$$shapeView.visible = false;
this.#shapeView.zIndex = 100; this.$$shapeView.zIndex = 100;
this.entity.addRasterChild(this.#shapeView); this.entity.addRasterChild(this.$$shapeView);
} }
} }
} }
@ -55,11 +55,11 @@ export default () => class Shaped extends decorate(Trait) {
async load(json) { async load(json) {
await super.load(json); await super.load(json);
this.#shape = shapeFromJSON(this.params.shape); this.$$shape = shapeFromJSON(this.params.shape);
} }
get shape() { get shape() {
return this.#shape; return this.$$shape;
} }
}; };

View File

@ -3,37 +3,37 @@ class Cancellation extends Error {}
export default class Serializer { export default class Serializer {
#pending = new Map(); $$pending = new Map();
#promises = new Map(); $$promises = new Map();
create(id, creator) { create(id, creator) {
const promise = creator.then(async (resource) => { const promise = creator.then(async (resource) => {
if (!this.#pending.has(id)) { if (!this.$$pending.has(id)) {
await resource.destroy(); await resource.destroy();
throw new Cancellation(); throw new Cancellation();
} }
this.#pending.delete(id); this.$$pending.delete(id);
return resource; return resource;
}).catch((error) => { }).catch((error) => {
if (!(error instanceof Cancellation)) { if (!(error instanceof Cancellation)) {
throw error; throw error;
} }
}); });
this.#pending.set(id, () => this.#pending.delete(id)); this.$$pending.set(id, () => this.$$pending.delete(id));
this.#promises.set(id, promise); this.$$promises.set(id, promise);
return promise; return promise;
} }
destroy(id) { destroy(id) {
// Cancel... // Cancel...
this.#pending.get(id)?.(); this.$$pending.get(id)?.();
this.#pending.delete(id); this.$$pending.delete(id);
this.#promises.delete(id); this.$$promises.delete(id);
} }
later(id, fn) { later(id, fn) {
const promise = this.#promises.get(id); const promise = this.$$promises.get(id);
if (!promise) { if (!promise) {
return Promise.resolve(); return Promise.resolve();
} }

View File

@ -51,18 +51,18 @@ if ('web' === process.env.FLECKS_CORE_BUILD_TARGET) {
export default class Sound extends JsonResource { export default class Sound extends JsonResource {
#audio; $$audio;
async load(json = {}) { async load(json = {}) {
await super.load(json); await super.load(json);
const {volume = 1} = json; const {volume = 1} = json;
const src = json.src || json.uri.replace('.sound.json', '.wav'); const src = json.src || json.uri.replace('.sound.json', '.wav');
if ('web' !== process.env.FLECKS_CORE_BUILD_TARGET) { if ('web' !== process.env.FLECKS_CORE_BUILD_TARGET) {
this.#audio = new FakeAudio(); this.$$audio = new FakeAudio();
return; return;
} }
if (cache.has(src)) { if (cache.has(src)) {
this.#audio = await cache.get(src); this.$$audio = await cache.get(src);
return; return;
} }
const promise = new Promise((resolve, reject) => { const promise = new Promise((resolve, reject) => {
@ -83,16 +83,16 @@ export default class Sound extends JsonResource {
}).catch(reject); }).catch(reject);
}); });
cache.set(src, promise); cache.set(src, promise);
this.#audio = await promise; this.$$audio = await promise;
} }
pause() { pause() {
this.#audio.pause(); this.$$audio.pause();
} }
play() { play() {
if ('web' === process.env.FLECKS_CORE_BUILD_TARGET) { if ('web' === process.env.FLECKS_CORE_BUILD_TARGET) {
play(this.#audio, this.uri); play(this.$$audio, this.uri);
} }
} }

View File

@ -7,9 +7,9 @@ const debug = D('@avocado/sound/audible');
export default () => class Audible extends Trait { export default () => class Audible extends Trait {
#playing = {}; $$playing = {};
#sounds = {}; $$sounds = {};
acceptPacket(packet) { acceptPacket(packet) {
if ('PlaySound' === packet.constructor.type) { if ('PlaySound' === packet.constructor.type) {
@ -20,20 +20,20 @@ export default () => class Audible extends Trait {
async addSounds(sounds) { async addSounds(sounds) {
return Promise.all( return Promise.all(
Object.entries(sounds).map(([key, sound]) => { Object.entries(sounds).map(([key, sound]) => {
if (this.#sounds[key]) { if (this.$$sounds[key]) {
return undefined; return undefined;
} }
this.#sounds[key] = Sound.load(sound).then((sound) => { this.$$sounds[key] = Sound.load(sound).then((sound) => {
this.#sounds[key] = sound; this.$$sounds[key] = sound;
}); });
return this.#sounds[key]; return this.$$sounds[key];
}), }),
); );
} }
cleanPackets() { cleanPackets() {
super.cleanPackets(); super.cleanPackets();
this.#playing = {}; this.$$playing = {};
} }
static defaultParams() { static defaultParams() {
@ -44,7 +44,7 @@ export default () => class Audible extends Trait {
destroy() { destroy() {
super.destroy(); super.destroy();
Object.values(this.#sounds).forEach((sound) => { Object.values(this.$$sounds).forEach((sound) => {
Promise.resolve(sound).then((sound) => { Promise.resolve(sound).then((sound) => {
sound.destroy(); sound.destroy();
}); });
@ -69,19 +69,19 @@ export default () => class Audible extends Trait {
methods() { methods() {
return { return {
hasSound: (key) => !!this.#sounds[key], hasSound: (key) => !!this.$$sounds[key],
playSound: (key) => { playSound: (key) => {
debug('Checking %s', key); debug('Checking %s', key);
if (!this.entity.hasSound(key)) { if (!this.entity.hasSound(key)) {
try { try {
this.#sounds[key] = Sound.load({extends: key}) this.$$sounds[key] = Sound.load({extends: key})
.then((sound) => { .then((sound) => {
this.#sounds[key] = sound; this.$$sounds[key] = sound;
return sound; return sound;
}) })
.catch(() => { .catch(() => {
delete this.#sounds[key]; delete this.$$sounds[key];
}); });
this.playSound(key); this.playSound(key);
} }
@ -89,13 +89,13 @@ export default () => class Audible extends Trait {
catch (error) {} catch (error) {}
} }
if ('web' === process.env.FLECKS_CORE_BUILD_TARGET) { if ('web' === process.env.FLECKS_CORE_BUILD_TARGET) {
Promise.resolve(this.#sounds[key]).then((sound) => { Promise.resolve(this.$$sounds[key]).then((sound) => {
debug('Playing %s', key); debug('Playing %s', key);
sound.play(); sound.play();
}); });
} }
else { else {
this.#playing[key] = true; this.$$playing[key] = true;
this.markAsDirty(); this.markAsDirty();
} }
}, },
@ -116,7 +116,7 @@ export default () => class Audible extends Trait {
} }
packetsFor() { packetsFor() {
return Object.keys(this.#playing).map((key) => ['PlaySound', {sound: key}]); return Object.keys(this.$$playing).map((key) => ['PlaySound', {sound: key}]);
} }
}; };

View File

@ -17,20 +17,20 @@ const decorate = compose(
export default (flecks) => class Animated extends decorate(Trait) { export default (flecks) => class Animated extends decorate(Trait) {
#animations = {}; $$animations = {};
#animationViews = {}; $$animationViews = {};
#cachedAabbs = {}; $$cachedAabbs = {};
#currentAnimation = ''; $$currentAnimation = '';
#forceUpdate = false; $$forceUpdate = false;
constructor() { constructor() {
super(); super();
({ ({
currentAnimation: this.#currentAnimation, currentAnimation: this.$$currentAnimation,
} = this.constructor.defaultParams()); } = this.constructor.defaultParams());
} }
@ -43,7 +43,7 @@ export default (flecks) => class Animated extends decorate(Trait) {
} }
get animation() { get animation() {
return this.#animations[this.#currentAnimation]; return this.$$animations[this.$$currentAnimation];
} }
static defaultParams() { static defaultParams() {
@ -67,28 +67,28 @@ export default (flecks) => class Animated extends decorate(Trait) {
destroy() { destroy() {
super.destroy(); super.destroy();
if (this.#animationViews) { if (this.$$animationViews) {
const animationViews = Object.entries(this.#animationViews); const animationViews = Object.entries(this.$$animationViews);
for (let i = 0; i < animationViews.length; i++) { for (let i = 0; i < animationViews.length; i++) {
const [key, animationView] = animationViews[i]; const [key, animationView] = animationViews[i];
this.hideAnimation(key); this.hideAnimation(key);
animationView.destroy(); animationView.destroy();
} }
this.#animationViews = undefined; this.$$animationViews = undefined;
} }
const animations = Object.values(this.#animations); const animations = Object.values(this.$$animations);
for (let i = 0; i < animations.length; i++) { for (let i = 0; i < animations.length; i++) {
animations[i].destroy(); animations[i].destroy();
} }
this.#animations = {}; this.$$animations = {};
this.#cachedAabbs = {}; this.$$cachedAabbs = {};
} }
hideAnimation(key) { hideAnimation(key) {
if (!this.#animationViews) { if (!this.$$animationViews) {
return; return;
} }
const animationView = this.#animationViews[key]; const animationView = this.$$animationViews[key];
if (!animationView) { if (!animationView) {
return; return;
} }
@ -102,14 +102,14 @@ export default (flecks) => class Animated extends decorate(Trait) {
return { return {
visibleAabbs: () => { visibleAabbs: () => {
const key = this.#currentAnimation; const key = this.$$currentAnimation;
if (key in this.#cachedAabbs) { if (key in this.$$cachedAabbs) {
return this.#cachedAabbs[key]; return this.$$cachedAabbs[key];
} }
if (!(key in this.#animations)) { if (!(key in this.$$animations)) {
return [0, 0, 0, 0]; return [0, 0, 0, 0];
} }
const {frameSize} = this.#animations[key]; const {frameSize} = this.$$animations[key];
const scaledSize = Vector.mul(frameSize, this.entity.visibleScale); const scaledSize = Vector.mul(frameSize, this.entity.visibleScale);
const viewPosition = Vector.sub( const viewPosition = Vector.sub(
this.offsetFor(key), this.offsetFor(key),
@ -120,7 +120,7 @@ export default (flecks) => class Animated extends decorate(Trait) {
rectangle, rectangle,
Vector.sub(scaledSize, frameSize), Vector.sub(scaledSize, frameSize),
); );
this.#cachedAabbs[key] = expanded; this.$$cachedAabbs[key] = expanded;
return expanded; return expanded;
}, },
@ -138,16 +138,16 @@ export default (flecks) => class Animated extends decorate(Trait) {
return { return {
currentAnimationChanged: (oldKey, currentAnimation) => { currentAnimationChanged: (oldKey, currentAnimation) => {
this.#currentAnimation = currentAnimation; this.$$currentAnimation = currentAnimation;
// Reset old animation. // Reset old animation.
if (oldKey in this.#animations) { if (oldKey in this.$$animations) {
const oldAnimation = this.#animations[oldKey]; const oldAnimation = this.$$animations[oldKey];
oldAnimation.reset(); oldAnimation.reset();
} }
// Bounding box update. // Bounding box update.
this.entity.scheduleBoundingBoxUpdate(); this.entity.scheduleBoundingBoxUpdate();
// Only client/graphics. // Only client/graphics.
if (!this.#animationViews) { if (!this.$$animationViews) {
return; return;
} }
// Swap the animation. // Swap the animation.
@ -157,7 +157,7 @@ export default (flecks) => class Animated extends decorate(Trait) {
directionChanged: () => { directionChanged: () => {
// All animations track direction. // All animations track direction.
const animations = Object.values(this.#animations); const animations = Object.values(this.$$animations);
for (let i = 0; i < animations.length; i++) { for (let i = 0; i < animations.length; i++) {
animations[i].direction = this.entity.direction; animations[i].direction = this.entity.direction;
} }
@ -169,8 +169,8 @@ export default (flecks) => class Animated extends decorate(Trait) {
traitAdded: () => { traitAdded: () => {
this.setSpriteScale(); this.setSpriteScale();
Object.entries(this.#animations).forEach(([key, animation]) => { Object.entries(this.$$animations).forEach(([key, animation]) => {
const method = key === this.#currentAnimation const method = key === this.$$currentAnimation
? 'showAnimation' ? 'showAnimation'
: 'hideAnimation'; : 'hideAnimation';
this[method](key); this[method](key);
@ -183,7 +183,7 @@ export default (flecks) => class Animated extends decorate(Trait) {
}, },
visibleScaleChanged: () => { visibleScaleChanged: () => {
this.#cachedAabbs = {}; this.$$cachedAabbs = {};
this.setSpriteScale(); this.setSpriteScale();
}, },
@ -206,18 +206,18 @@ export default (flecks) => class Animated extends decorate(Trait) {
// eslint-disable-next-line no-param-reassign // eslint-disable-next-line no-param-reassign
animationView.position = this.offsetFor(key); animationView.position = this.offsetFor(key);
}); });
this.#animations = animations; this.$$animations = animations;
this.#animationViews = animationViews; this.$$animationViews = animationViews;
} }
this.#currentAnimation = this.state.currentAnimation; this.$$currentAnimation = this.state.currentAnimation;
} }
methods() { methods() {
return { return {
setAnimationRate: (rate) => { setAnimationRate: (rate) => {
if (this.#animations[this.#currentAnimation].frameRate !== rate) { if (this.$$animations[this.$$currentAnimation].frameRate !== rate) {
this.#animations[this.#currentAnimation].frameRate = rate; this.$$animations[this.$$currentAnimation].frameRate = rate;
this.#forceUpdate = true; this.$$forceUpdate = true;
} }
}, },
}; };
@ -232,8 +232,8 @@ export default (flecks) => class Animated extends decorate(Trait) {
packetsFor() { packetsFor() {
const {currentAnimation, isAnimating} = this.stateDifferences(); const {currentAnimation, isAnimating} = this.stateDifferences();
if (this.#forceUpdate || currentAnimation || isAnimating) { if (this.$$forceUpdate || currentAnimation || isAnimating) {
this.#forceUpdate = false; this.$$forceUpdate = false;
return [[ return [[
'TraitUpdateAnimated', 'TraitUpdateAnimated',
{ {
@ -247,20 +247,20 @@ export default (flecks) => class Animated extends decorate(Trait) {
} }
setSpriteScale() { setSpriteScale() {
if (!this.#animationViews) { if (!this.$$animationViews) {
return; return;
} }
const animationViews = Object.values(this.#animationViews); const animationViews = Object.values(this.$$animationViews);
for (let i = 0; i < animationViews.length; i++) { for (let i = 0; i < animationViews.length; i++) {
animationViews[i].scale = this.entity.visibleScale; animationViews[i].scale = this.entity.visibleScale;
} }
} }
showAnimation(key) { showAnimation(key) {
if (!this.#animationViews) { if (!this.$$animationViews) {
return; return;
} }
const animationView = this.#animationViews[key]; const animationView = this.$$animationViews[key];
if (!animationView) { if (!animationView) {
return; return;
} }
@ -275,11 +275,11 @@ export default (flecks) => class Animated extends decorate(Trait) {
return; return;
} }
// Only tick current animation. // Only tick current animation.
const currentAnimation = this.#currentAnimation; const currentAnimation = this.$$currentAnimation;
if (!(currentAnimation in this.#animations)) { if (!(currentAnimation in this.$$animations)) {
return; return;
} }
const animation = this.#animations[currentAnimation]; const animation = this.$$animations[currentAnimation];
const jitterAmount = this.jitterFor(currentAnimation); const jitterAmount = this.jitterFor(currentAnimation);
if (jitterAmount > 0) { if (jitterAmount > 0) {
const jitter = Math.random() * jitterAmount; const jitter = Math.random() * jitterAmount;

View File

@ -2,7 +2,7 @@ import {Trait} from '@avocado/traits';
export default () => class Evolving extends Trait { export default () => class Evolving extends Trait {
#evolving; $$evolving;
static defaultParams() { static defaultParams() {
return { return {
@ -15,11 +15,11 @@ export default () => class Evolving extends Trait {
if (0 === Object.keys(this.params.lfo).length) { if (0 === Object.keys(this.params.lfo).length) {
return; return;
} }
this.#evolving = this.entity.lfo(this.params.lfo); this.$$evolving = this.entity.lfo(this.params.lfo);
} }
tick(elapsed) { tick(elapsed) {
this.#evolving.tick(elapsed); this.$$evolving.tick(elapsed);
} }
}; };

View File

@ -35,23 +35,23 @@ export default (flecks) => {
); );
return class Tiles extends decorate(JsonResource) { return class Tiles extends decorate(JsonResource) {
#atlas = new Atlas(); $$atlas = new Atlas();
#data = new Uint16Array(); $$data = new Uint16Array();
#hasUpdates = false; $$hasUpdates = false;
#packets = []; $$packets = [];
#s13nId = 0; $$s13nId = 0;
#tileImageUri; $$tileImageUri;
#tileSize = [0, 0]; $$tileSize = [0, 0];
#updates = []; $$updates = [];
#zIndex = 0; $$zIndex = 0;
acceptPacket(packet) { acceptPacket(packet) {
if ('TilesUpdate' === packet.constructor.type) { if ('TilesUpdate' === packet.constructor.type) {
@ -62,12 +62,12 @@ export default (flecks) => {
} }
cleanPackets() { cleanPackets() {
this.#packets = []; this.$$packets = [];
this.#updates = []; this.$$updates = [];
} }
destroy() { destroy() {
this.#atlas.destroy(); this.$$atlas.destroy();
} }
static indexHulls(indices, data, size) { static indexHulls(indices, data, size) {
@ -132,7 +132,7 @@ export default (flecks) => {
} }
indexHulls(indices) { indexHulls(indices) {
return this.constructor.indexHulls(indices, this.#data, this.area); return this.constructor.indexHulls(indices, this.$$data, this.area);
} }
async load(json) { async load(json) {
@ -149,37 +149,37 @@ export default (flecks) => {
} }
if (data) { if (data) {
const {buffer, byteOffset, length} = inflate(Buffer.from(data, 'base64')); const {buffer, byteOffset, length} = inflate(Buffer.from(data, 'base64'));
this.#data = new Uint16Array(buffer, byteOffset, length / 2); this.$$data = new Uint16Array(buffer, byteOffset, length / 2);
} }
else if (area) { else if (area) {
this.#data = new Uint16Array(Vector.area(area)); this.$$data = new Uint16Array(Vector.area(area));
} }
if (tileImageUri && tileSize) { if (tileImageUri && tileSize) {
this.#tileSize = tileSize; this.$$tileSize = tileSize;
this.#tileImageUri = tileImageUri; this.$$tileImageUri = tileImageUri;
await this.#atlas.load({ await this.$$atlas.load({
imageUri: tileImageUri, imageUri: tileImageUri,
type: 'grid', type: 'grid',
size: tileSize, size: tileSize,
}); });
} }
if (s13nId) { if (s13nId) {
this.#s13nId = s13nId; this.$$s13nId = s13nId;
} }
if (zIndex > 0) { if (zIndex > 0) {
this.#zIndex = zIndex; this.$$zIndex = zIndex;
} }
} }
packetsFor() { packetsFor() {
if (0 === this.#updates.length) { if (0 === this.$$updates.length) {
return []; return [];
} }
if (0 === this.#packets.length) { if (0 === this.$$packets.length) {
// TODO: merge? // TODO: merge?
for (let i = 0; i < this.#updates.length; i++) { for (let i = 0; i < this.$$updates.length; i++) {
const [position, size, tiles] = this.#updates[i]; const [position, size, tiles] = this.$$updates[i];
this.#packets.push([ this.$$packets.push([
'TilesUpdate', 'TilesUpdate',
{ {
position, position,
@ -189,7 +189,7 @@ export default (flecks) => {
]); ]);
} }
} }
return this.#packets; return this.$$packets;
} }
get rectangle() { get rectangle() {
@ -197,19 +197,19 @@ export default (flecks) => {
} }
get s13nId() { get s13nId() {
return this.#s13nId; return this.$$s13nId;
} }
setTileAt([x, y], tile) { setTileAt([x, y], tile) {
const [w, h] = this.area; const [w, h] = this.area;
const index = y * w + x; const index = y * w + x;
if (x < 0 || x >= w || y < 0 || y >= h || this.#data[index] === tile) { if (x < 0 || x >= w || y < 0 || y >= h || this.$$data[index] === tile) {
return; return;
} }
this.#data[index] = tile; this.$$data[index] = tile;
if ('web' !== process.env.FLECKS_CORE_BUILD_TARGET) { if ('web' !== process.env.FLECKS_CORE_BUILD_TARGET) {
this.#updates.push([[x, y], [1, 1], [tile]]); this.$$updates.push([[x, y], [1, 1], [tile]]);
this.#hasUpdates = true; this.$$hasUpdates = true;
} }
} }
@ -225,7 +225,7 @@ export default (flecks) => {
let j = 0; let j = 0;
for (let l = 0; l < h; ++l) { for (let l = 0; l < h; ++l) {
for (let k = 0; k < w; ++k) { for (let k = 0; k < w; ++k) {
slice[j] = x < 0 || x >= fw || y < 0 || y >= fh ? 0 : this.#data[i]; slice[j] = x < 0 || x >= fw || y < 0 || y >= fh ? 0 : this.$$data[i];
x += 1; x += 1;
i += 1; i += 1;
j += 1; j += 1;
@ -254,7 +254,7 @@ export default (flecks) => {
for (let yy = 0; yy < h; ++yy) { for (let yy = 0; yy < h; ++yy) {
for (let xx = 0; xx < w; ++xx) { for (let xx = 0; xx < w; ++xx) {
if (sx >= 0 && sx < fw && sy >= 0 && sy < fh) { if (sx >= 0 && sx < fw && sy >= 0 && sy < fh) {
this.#data[i] = tiles[j]; this.$$data[i] = tiles[j];
isDirty = true; isDirty = true;
} }
i += 1; i += 1;
@ -267,49 +267,49 @@ export default (flecks) => {
sy += 1; sy += 1;
} }
if (isDirty && 'web' !== process.env.FLECKS_CORE_BUILD_TARGET) { if (isDirty && 'web' !== process.env.FLECKS_CORE_BUILD_TARGET) {
this.#updates.push([[x, y], [w, h], tiles]); this.$$updates.push([[x, y], [w, h], tiles]);
this.#hasUpdates = true; this.$$hasUpdates = true;
} }
} }
subimage(index) { subimage(index) {
return this.#atlas.subimage(index); return this.$$atlas.subimage(index);
} }
tick() { tick() {
if (this.#hasUpdates) { if (this.$$hasUpdates) {
this.emit('update'); this.emit('update');
} }
this.#hasUpdates = false; this.$$hasUpdates = false;
} }
tileAt([x, y]) { tileAt([x, y]) {
const [w, h] = this.area; const [w, h] = this.area;
return x < 0 || x >= w || y < 0 || y >= h ? undefined : this.#data[y * w + x]; return x < 0 || x >= w || y < 0 || y >= h ? undefined : this.$$data[y * w + x];
} }
get tileSize() { get tileSize() {
return this.#tileSize; return this.$$tileSize;
} }
toNetwork() { toNetwork() {
return { return {
...this.toJSON(), ...this.toJSON(),
s13nId: this.#s13nId, s13nId: this.$$s13nId,
}; };
} }
toJSON() { toJSON() {
return { return {
area: this.area, area: this.area,
data: deflate(this.#data).toString('base64'), data: deflate(this.$$data).toString('base64'),
tileSize: this.#tileSize, tileSize: this.$$tileSize,
...(this.#tileImageUri ? {tileImageUri: this.#tileImageUri} : []), ...(this.$$tileImageUri ? {tileImageUri: this.$$tileImageUri} : []),
}; };
} }
get zIndex() { get zIndex() {
return this.#zIndex; return this.$$zIndex;
} }
}; };

View File

@ -4,7 +4,7 @@ import Camera from '../camera';
export default (flecks) => class Followed extends Trait { export default (flecks) => class Followed extends Trait {
#camera = new Camera(); $$camera = new Camera();
static defaultParams() { static defaultParams() {
return { return {
@ -19,12 +19,12 @@ export default (flecks) => class Followed extends Trait {
} }
get camera() { get camera() {
return this.#camera; return this.$$camera;
} }
hotJSON() { hotJSON() {
return { return {
camera: this.#camera, camera: this.$$camera,
}; };
} }
@ -42,9 +42,9 @@ export default (flecks) => class Followed extends Trait {
await super.load(json); await super.load(json);
// @hot // @hot
if (json.camera) { if (json.camera) {
this.#camera = json.camera; this.$$camera = json.camera;
} }
this.#camera.viewSize = this.params.viewSize; this.$$camera.viewSize = this.params.viewSize;
this.updatePosition(); this.updatePosition();
this.onRoomSizeChanged(); this.onRoomSizeChanged();
} }
@ -52,12 +52,12 @@ export default (flecks) => class Followed extends Trait {
onRoomSizeChanged() { onRoomSizeChanged() {
const {room} = this.entity; const {room} = this.entity;
if (room) { if (room) {
this.#camera.areaSize = room.size; this.$$camera.areaSize = room.size;
} }
} }
renderTick(elapsed) { renderTick(elapsed) {
this.#camera.tick(elapsed); this.$$camera.tick(elapsed);
} }
tick() { tick() {
@ -65,7 +65,7 @@ export default (flecks) => class Followed extends Trait {
} }
updatePosition() { updatePosition() {
this.#camera.position = this.entity.position; this.$$camera.position = this.entity.position;
} }
}; };

View File

@ -2,18 +2,18 @@ import {JsonResource} from '@avocado/resource';
export default class Trait extends JsonResource { export default class Trait extends JsonResource {
#markedAsDirty = true; $$markedAsDirty = true;
#memoizedListeners = undefined; $$memoizedListeners = undefined;
#previousState = {}; $$previousState = {};
constructor() { constructor() {
super(); super();
const {constructor} = this; const {constructor} = this;
this.params = constructor.defaultParams(); this.params = constructor.defaultParams();
this.state = constructor.defaultState(); this.state = constructor.defaultState();
this.#previousState = JSON.parse(JSON.stringify(this.state)); this.$$previousState = JSON.parse(JSON.stringify(this.state));
if (this.tick) { if (this.tick) {
this.tick = this.tick.bind(this); this.tick = this.tick.bind(this);
} }
@ -26,7 +26,7 @@ export default class Trait extends JsonResource {
acceptPacket(packet) {} acceptPacket(packet) {}
cleanPackets() { cleanPackets() {
if (!this.#markedAsDirty) { if (!this.$$markedAsDirty) {
return; return;
} }
this.markAsClean(); this.markAsClean();
@ -60,7 +60,7 @@ export default class Trait extends JsonResource {
} }
destroy() { destroy() {
this.#memoizedListeners = undefined; this.$$memoizedListeners = undefined;
} }
// eslint-disable-next-line class-methods-use-this // eslint-disable-next-line class-methods-use-this
@ -78,28 +78,28 @@ export default class Trait extends JsonResource {
const {constructor} = this; const {constructor} = this;
this.params = constructor.defaultParamsWith(params); this.params = constructor.defaultParamsWith(params);
this.state = constructor.defaultStateWith(state); this.state = constructor.defaultStateWith(state);
this.#previousState = JSON.parse(JSON.stringify(this.state)); this.$$previousState = JSON.parse(JSON.stringify(this.state));
} }
markAsClean() { markAsClean() {
const state = Object.entries(this.state); const state = Object.entries(this.state);
for (let i = 0; i < state.length; i++) { for (let i = 0; i < state.length; i++) {
const [key, value] = state[i]; const [key, value] = state[i];
this.#previousState[key] = value; this.$$previousState[key] = value;
} }
this.#markedAsDirty = false; this.$$markedAsDirty = false;
} }
markAsDirty() { markAsDirty() {
this.#markedAsDirty = true; this.$$markedAsDirty = true;
this.entity.markAsDirty(); this.entity.markAsDirty();
} }
memoizedListeners() { memoizedListeners() {
if (!this.#memoizedListeners) { if (!this.$$memoizedListeners) {
this.#memoizedListeners = this.listeners(); this.$$memoizedListeners = this.listeners();
} }
return this.#memoizedListeners; return this.$$memoizedListeners;
} }
// eslint-disable-next-line class-methods-use-this // eslint-disable-next-line class-methods-use-this
@ -126,9 +126,9 @@ export default class Trait extends JsonResource {
const state = Object.entries(this.state); const state = Object.entries(this.state);
for (let i = 0; i < state.length; i++) { for (let i = 0; i < state.length; i++) {
const [key, value] = state[i]; const [key, value] = state[i];
if (value !== this.#previousState[key]) { if (value !== this.$$previousState[key]) {
differences[key] = { differences[key] = {
old: this.#previousState[key], old: this.$$previousState[key],
value, value,
}; };
} }