flow: resource loading and synchronization

This commit is contained in:
cha0s 2021-01-16 09:17:08 -06:00
parent 2356ec5011
commit b22e531267
47 changed files with 724 additions and 643 deletions

View File

@ -15,26 +15,17 @@ const decorate = compose(
export default (latus) => class Behaved extends decorate(Trait) {
#context;
#context = new Context({}, latus);
#currentRoutine;
#currentRoutine = '';
#routines;
#routines = {};
constructor(...args) {
super(...args);
this.#context = new Context(
{
entity: [this.entity, 'entity'],
},
latus,
);
this.#currentRoutine = undefined;
this.#routines = mapValues(
this.params.routines,
(routine) => new Actions(compile(routine, latus)),
);
this.updateCurrentRoutine(this.state.currentRoutine);
constructor() {
super();
({
currentRoutine: this.#currentRoutine,
} = this.constructor.defaultState());
}
static behaviorTypes() {
@ -95,6 +86,21 @@ export default (latus) => class Behaved extends decorate(Trait) {
this.#routines = undefined;
}
load(json) {
super.load(json);
this.#context = new Context(
{
entity: [this.entity, 'entity'],
},
latus,
);
this.#routines = mapValues(
this.params.routines,
(routine) => new Actions(compile(routine, latus)),
);
this.updateCurrentRoutine(this.state.currentRoutine);
}
listeners() {
return {

View File

@ -4,8 +4,8 @@
"@avocado/behavior@2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@avocado%2fbehavior/-/behavior-2.0.0.tgz#34cf4235cb85165f4b4bdee108d1efacc6732330"
integrity sha512-wQnnjXp69RW9EWeovUjH3goMoYyD6EHKyiCnkdJMb/Z9h9rwARpYqKTmq1iNgliOJ/8KpJelNi/v1+dvmlJxYA==
resolved "http://npm.cha0sdev/@avocado%2fbehavior/-/behavior-2.0.0.tgz#ec40db5be3e977c64daabf6587787a99ce9eea5f"
integrity sha512-XEt/ESrQINPfwNHUiezM5InMue6TCdNP7a+66AiK6+F9rsjuGGvyrWLKRm7DxwBBqWNlPBNDmAvw98OOwoRKDw==
dependencies:
"@avocado/core" "2.0.0"
"@avocado/traits" "^2.0.0"
@ -16,15 +16,15 @@
"@avocado/core@2.0.0", "@avocado/core@^2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@avocado%2fcore/-/core-2.0.0.tgz#69c736d6a1d8b25d0cc57f07fabdef3f467a5636"
integrity sha512-XqLqDST/gLCbyBNQuZnzj8WN05aEgko8Kh/45pN0cSNA5DRMgkZSynBZh0NMEtiYfC5Od6v6y7FF5uvuzh4+gg==
resolved "http://npm.cha0sdev/@avocado%2fcore/-/core-2.0.0.tgz#2debb82ce9947a22575032af6719531278f6f98a"
integrity sha512-XGikLesJP42xgTOFy0gxPCNp0NnE9NK7xCHNAcs2tU4XOxNPTYv5cPp1FP21cHdf2b6joiNmFnWNBg1mvF0AJA==
dependencies:
debug "4.3.1"
"@avocado/entity@^2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@avocado%2fentity/-/entity-2.0.0.tgz#d758beff5ad6e1069e03529ffce64f04923a0be0"
integrity sha512-ujDS8uWx1aYzmkaq+MPutB4PCtTEH/6LptH5rG4F0YIJHaPKNhl3vaYvRivhqu3FPtT8RFS8DqYr4GvWXm4bGA==
resolved "http://npm.cha0sdev/@avocado%2fentity/-/entity-2.0.0.tgz#e6d8d4f1e2d8b822dada80df5e4b8926b364df31"
integrity sha512-vAmZHbTXm2MwLOLxZf19llTFFwDUlC8nqaLm9FSwZlOhOVr5e2t8YJcjbisjWfGkNvTd6m9AluPj5vHCKjV+ww==
dependencies:
"@avocado/behavior" "2.0.0"
"@avocado/core" "2.0.0"
@ -42,8 +42,8 @@
"@avocado/graphics@2.0.0", "@avocado/graphics@^2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@avocado%2fgraphics/-/graphics-2.0.0.tgz#340660152bddd49a03da787924f431d639f639d3"
integrity sha512-NRj2iQBafrXkhn+4IQnu0uxUQrapGp8OCtwde6Qp4xdbQLlpkndaENLKg6/Q7qxt05yMv8XtI81V7yX3xzsAoQ==
resolved "http://npm.cha0sdev/@avocado%2fgraphics/-/graphics-2.0.0.tgz#2dc43f9a825fa1f9a72064d5e83630185f974e94"
integrity sha512-BsB+MPAhvuLdSSibvU+oLOcBXnUgEJAmaoXOLTIppDQh7ACo+Hqamib+2Zcx75VcmwleEeOIVDtnQJzKLYVInw==
dependencies:
"@avocado/core" "2.0.0"
"@avocado/input" "2.0.0"
@ -66,8 +66,8 @@
"@avocado/input@2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@avocado%2finput/-/input-2.0.0.tgz#bdd839a2c977c3414fd3590a14dde2ef1cb8067e"
integrity sha512-KtGGH82WLdT0699+/Fw9bhimIOsZEhE9hhr5OuXxWDp8JVVzrrD/1jytC6Ue3012Na0rVKtdkMGewoAB0Fv0GQ==
resolved "http://npm.cha0sdev/@avocado%2finput/-/input-2.0.0.tgz#c73ebd8f821663e5c30c572e4efbe7d34bb1bb7f"
integrity sha512-lrv+bsBtsfV9ps3QNfNbcnPXOuzu99XZqtbDB/NK8umGKQogKQg7Ix9tiXbciHibIfTejiG5mapHr+SVbHrO5Q==
dependencies:
"@latus/core" "2.0.0"
"@latus/socket" "2.0.0"
@ -75,8 +75,8 @@
"@avocado/math@2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@avocado%2fmath/-/math-2.0.0.tgz#9e3fb073d93799f8f86a1abbaaabd5021fc753ad"
integrity sha512-vIgwR0p7I9jnXqUr/6cD9i2k/Z8GJuWqNIxksmPF8Odw1SON/4ItbLYk3D5+Z/KnDOeIa2N2Db9IoymcOofBgw==
resolved "http://npm.cha0sdev/@avocado%2fmath/-/math-2.0.0.tgz#9b4c05098f287ebe814b6ef954ac0ab4140c51dc"
integrity sha512-KEX7fkzxUtiXNlSYEOdp/Juv0YFhdvPExgW3zI61kBDZvJr3fNJWJ9slrf1ikSGFWrtcH2tUESlTToRHPLd2Qg==
dependencies:
"@avocado/core" "2.0.0"
"@latus/core" "^2.0.0"
@ -85,8 +85,8 @@
"@avocado/resource@2.0.0", "@avocado/resource@^2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@avocado%2fresource/-/resource-2.0.0.tgz#9eadafaf1ce7a8d6308c59bfa92290830cf91e30"
integrity sha512-85osPtux7MZ+9dAFGrLKzIv1vAPuSBfxEwPZOvKaHMSBa6mnzysC7c2FbU4zfSioDl8ozqknE9ZYZB1bjdw0Hg==
resolved "http://npm.cha0sdev/@avocado%2fresource/-/resource-2.0.0.tgz#12b9b1ee4bcb43ede8ba2172f16c82dc2f115d0f"
integrity sha512-qNTzFfkZMwYX+IEl64Del4uSfQKpWm6kR1KtlOWCbU5nc3sH5d9U+nFfbmGAJArEhC9lo2s2lQITvgkJ7D1VuQ==
dependencies:
"@avocado/core" "2.0.0"
"@latus/core" "2.0.0"
@ -96,8 +96,8 @@
"@avocado/s13n@2.0.0", "@avocado/s13n@^2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@avocado%2fs13n/-/s13n-2.0.0.tgz#2b0ea781520f5c41dcd6c3bfc1a6cd52ce181c69"
integrity sha512-TkxxmQQRS7NbpvNxLQ1RME+7vIpGm198sPSNcDfBLMwcQ2Icl8jTx5HFaIaCLh6XezFN/MhQzDjZ62XVqxWEeg==
resolved "http://npm.cha0sdev/@avocado%2fs13n/-/s13n-2.0.0.tgz#3aff3c15a6e8ef2a405e7b9ff45abd94e63f064d"
integrity sha512-UAmde98frU3TWlK0yIvHYM/PX+dpyx4O+a5QWQakm7ef9vZomPwyN/2Z87ArliOZILO3qhvusFqiLusUf8z7HA==
dependencies:
"@avocado/resource" "^2.0.0"
"@latus/core" "2.0.0"
@ -107,8 +107,8 @@
"@avocado/timing@2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@avocado%2ftiming/-/timing-2.0.0.tgz#9c7ddb24d9f99822a59b6927fcaa09e8614785b0"
integrity sha512-zlLLjrKvYzCRyvtYWDJniM0AtLzmpOxWeEL7U8uPbA9n1fDEdAv90rhpw8rdFOAtGBNi6q2YxcaIJH0vQzs5Iw==
resolved "http://npm.cha0sdev/@avocado%2ftiming/-/timing-2.0.0.tgz#6eec2b614387a199b78dc15b833f2057a6032db9"
integrity sha512-aWpsLrHLrsQnWIUmYMOrJlFg/xwZFecLDU4i9WHwf6FW41SgjjxI8eeVPiiteGt2IUmGcRemuSV9PSBuazL76w==
dependencies:
"@avocado/core" "2.0.0"
"@avocado/graphics" "2.0.0"
@ -122,8 +122,8 @@
"@avocado/traits@^2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@avocado%2ftraits/-/traits-2.0.0.tgz#369ce54e55b6a32c1591efcf31e19785f827b943"
integrity sha512-0+CatzN3YFm1HBUQ1n0a2j2/cmtNo6hjNtjiJINFkqEUmpwGnoub+yB4x7HW837IjnqvLeD53Mu6YUxC9nOstQ==
resolved "http://npm.cha0sdev/@avocado%2ftraits/-/traits-2.0.0.tgz#7aa7c5504e627967189343a58248c123f80e44a4"
integrity sha512-7hoiN/MQmBGeGPg8wtg5erXxS5053IGsRyM0qdbnhkIY0tWLBJ2NjREqkDfC2avsJAc4yK5+x+l2PFpLJivxww==
dependencies:
"@avocado/core" "^2.0.0"
"@avocado/resource" "^2.0.0"
@ -1032,8 +1032,8 @@
"@latus/core@2.0.0", "@latus/core@^2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@latus%2fcore/-/core-2.0.0.tgz#1f001c8deead6c58e51a32aa4cedee7f26403a58"
integrity sha512-0Co6k1MZE5dBwwa8IMtl2Szk69KdvmMBvLQh45JLnGPhSodQ06+carStEn9r8dr+RvaDZpNRQohyxQFZV5ioJw==
resolved "http://npm.cha0sdev/@latus%2fcore/-/core-2.0.0.tgz#24e8313875563b729f32c7d98fb394b116f2adba"
integrity sha512-CKEb7xoyBXwZHlUmPWUU/egXuzpKkIZFVioKfnDTHNydDKaKG0TW0ugg6EX6Le81CFt9RovMALKJm2s4A7UiVQ==
dependencies:
debug "4.3.1"
js-yaml "3.14.0"
@ -1044,8 +1044,8 @@
"@latus/http@2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@latus%2fhttp/-/http-2.0.0.tgz#887a144f8029291818ed85fbe1a6462a2e01740f"
integrity sha512-f0tlfVq5Yp0ioYS/cY24odm4N3jJaqeq/gNshppNKzYf+k9/HzM+8khGBbol+1/6OZLq3zVDoZqYNJRQUci3Rg==
resolved "http://npm.cha0sdev/@latus%2fhttp/-/http-2.0.0.tgz#3589fcb76a5e7a4763b45853d696289b3ce478b3"
integrity sha512-jWhJa93uLksNEEQhFKq36de5jHCKoQZBel57DIxaTk+jAIfzPO+kmWlTaq/wGCiCxlnHLjvTuMGOiDABVew4aQ==
dependencies:
"@latus/core" "2.0.0"
"@neutrinojs/web" "^9.1.0"
@ -1064,8 +1064,8 @@
"@latus/react@2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@latus%2freact/-/react-2.0.0.tgz#09f4699218a73c19ff0c7c299a6c48f053316512"
integrity sha512-HZN9THHkZSWUwDDh8S2k+FiLfrmRbT4eUTs+ZJsQuWCdS6NQpBoTp2kjGe5wG/h0HoHwFfh+tjs728BXZXlLNQ==
resolved "http://npm.cha0sdev/@latus%2freact/-/react-2.0.0.tgz#25fd38202ff83a5ceb9ab0574a45a255db96905a"
integrity sha512-Yy7x2BdDlNe7njxAZONx1fI2MhebnlLjZfT2mz9JkoGNfaFWdDCLdaouYn8WH5u7ihMeGcSCVTizFwr4rZj9UQ==
dependencies:
"@hot-loader/react-dom" "^17.0.1"
"@neutrinojs/react" "^9.4.0"
@ -1079,8 +1079,8 @@
"@latus/socket@2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@latus%2fsocket/-/socket-2.0.0.tgz#8128b1244b3458ac0dfcd4d6d1256cd741b0e73e"
integrity sha512-bH6WZZ2C0FiIZEsJuJQk2M9iHBPzAZZ8gBKB3XYWl+pwb535bHLnoMCkbV3LZhMiguZnIjUt7mSYZAGybvOvNw==
resolved "http://npm.cha0sdev/@latus%2fsocket/-/socket-2.0.0.tgz#ba0d9cc2099474ba1dbba2b4e27e92a6fc271087"
integrity sha512-ZDOxbRwoiEO2E/QeS4GjO1950oVeH+i4Gw4ep6K/TPBbhkaiDrp8MpZyUxM6hDDEDf1Q6V1gAH+4FLPsUncdYw==
dependencies:
"@latus/core" "2.0.0"
"@latus/http" "2.0.0"

View File

@ -92,12 +92,10 @@ export default (latus) => class EntityList extends decorate(JsonResource) {
}
static async extendJson(json) {
const extended = await super.extendJson(json);
if (extended.entities) {
const {fromResourceType: {Entity}} = resource(latus);
extended.entities = await Promise.all(extended.entities.map(Entity.load));
}
return extended;
const {fromResourceType: {Entity}} = resource(latus);
return json.entities
? Promise.all(json.entities.map(Entity.load))
: [];
}
findEntity(uuid) {
@ -106,9 +104,9 @@ export default (latus) => class EntityList extends decorate(JsonResource) {
: undefined;
}
load(entities = []) {
for (let i = 0; i < entities.length; i++) {
this.addEntity(entities[i]);
load(entityInstances = []) {
for (let i = 0; i < entityInstances.length; i++) {
this.addEntity(entityInstances[i]);
}
}

View File

@ -9,7 +9,7 @@ import {compose, EventEmitter} from '@latus/core';
import {defineTraitAccessors, enumerateTraitAccessorKeys} from '../accessors';
const debug = D('@avocado:entity:traits');
const debug = D('@avocado/entity');
const decorate = compose(
EventEmitter,
@ -75,14 +75,15 @@ export default (latus) => class Entity extends decorate(JsonResource) {
});
}
addTrait(Trait, json = {}) {
if (this.is(Trait.type)) {
debug(`Tried to add trait "${Trait.type}" when it already exists!`);
return;
}
async addTrait(type, json = {}) {
const {fromType: {[type]: Trait}} = traits(latus);
if (!Trait) {
debug(`Tried to add trait "${Trait.type}" which isn't registered!`);
return;
debug(`Tried to add trait "${type}" which isn't registered!`);
return undefined;
}
if (this.is(type)) {
debug(`Tried to add trait "${type}" when it already exists!`);
return undefined;
}
// Ensure dependencies.
const dependencies = Trait.dependencies();
@ -90,16 +91,17 @@ export default (latus) => class Entity extends decorate(JsonResource) {
const lacking = without(dependencies, ...allTypes);
if (lacking.length > 0) {
debug(
`Tried to add trait "${Trait.type}" but lack one or more dependents: "${
`Tried to add trait "${type}" but lack one or more dependents: "${
lacking.join('", "')
}"!`,
);
// return;
}
// Instantiate.
// eslint-disable-next-line no-param-reassign
json.entity = this;
const trait = new Trait(json);
const trait = await Trait.load({
entity: this,
...json,
});
// Proxy properties.
defineTraitAccessors(Trait.prototype, this, trait);
// Attach listeners.
@ -121,11 +123,11 @@ export default (latus) => class Entity extends decorate(JsonResource) {
this.#hooks[key] = this.#hooks[key] || [];
this.#hooks[key].push({
fn,
type: Trait.type,
type,
});
}
// Track trait.
this.#traits[Trait.type] = trait;
this.#traits[type] = trait;
this.#traitsFlat.push(trait);
if ('tick' in trait) {
this.#traitTickers.push(trait.tick);
@ -136,13 +138,19 @@ export default (latus) => class Entity extends decorate(JsonResource) {
if ('acceptPacket' in trait) {
this.#traitsAcceptingPackets.push(trait);
}
this.emit('traitAdded', Trait.type, trait);
this.emit('traitAdded', type, trait);
return trait;
}
addTraits(traits) {
for (let i = 0; i < traits.length; i++) {
this.addTrait(traits[i][0], traits[i][1]);
async addTraits(traits) {
const entries = Object.entries(traits);
const promises = [];
for (let i = 0; i < entries.length; i++) {
const [type, json] = entries[i];
promises.push(this.addTrait(type, json));
}
const instances = await Promise.all(promises);
return Object.fromEntries(entries.map(([type], i) => [type, instances[i]]));
}
cleanPackets() {
@ -155,23 +163,6 @@ export default (latus) => class Entity extends decorate(JsonResource) {
this.#markedAsDirty = false;
}
static async extendJson(json) {
const extended = await super.extendJson(json);
if (extended.traits) {
const entries = Object.entries(extended.traits);
const promises = entries.map(async ([type, json]) => {
const {fromType: {[type]: Trait}} = traits(latus);
if (!Trait) {
debug(`Tried to add trait "${type}" which isn't registered!`);
return undefined;
}
return [Trait, await Trait.extendJson(json)];
});
extended.traitInstances = (await Promise.all(promises)).filter((entry) => !!entry);
}
return extended;
}
invokeHook(hook, ...args) {
const results = {};
if (!(hook in this.#hooks)) {
@ -193,11 +184,11 @@ export default (latus) => class Entity extends decorate(JsonResource) {
return type in this.#traits;
}
load(json = {}) {
const {instanceUuid, traitInstances = []} = json;
async load(json = {}) {
const {instanceUuid, traits = {}} = json;
this.#originalJson = json;
this.instanceUuid = instanceUuid || this.numericId;
this.addTraits(traitInstances);
await this.addTraits(traits);
}
markAsDirty() {
@ -319,8 +310,8 @@ export default (latus) => class Entity extends decorate(JsonResource) {
json.traits[type] = trait.toNetwork(informed);
}
return {
...super.toJSON(),
instanceUuid: this.instanceUuid,
uri: this.uri,
...this.mergeDiff(json),
};
}

View File

@ -23,22 +23,17 @@ const decorate = compose(
export default (latus) => class Alive extends decorate(Trait) {
#context;
#context = new Context({}, latus);
#deathActions;
#deathCondition;
constructor(...args) {
super(...args);
this.#context = new Context(
{
entity: [this.entity, 'entity'],
},
latus,
);
this.#deathActions = new Actions(compile(this.params.deathActions, latus));
this.#deathCondition = compile(this.params.deathCondition, latus);
constructor() {
super();
const {deathActions, deathCondition} = this.constructor.defaultParams();
this.#deathActions = deathActions;
this.#deathCondition = deathCondition;
}
acceptPacket(packet) {
@ -165,6 +160,18 @@ export default (latus) => class Alive extends decorate(Trait) {
};
}
load(json) {
super.load(json);
this.#context = new Context(
{
entity: [this.entity, 'entity'],
},
latus,
);
this.#deathActions = new Actions(compile(this.params.deathActions, latus));
this.#deathCondition = compile(this.params.deathCondition, latus);
}
get maxLife() {
return super.maxLife;
}

View File

@ -84,7 +84,7 @@ export default () => class Directional extends decorate(Trait) {
direction.value,
]];
}
return undefined;
return [];
}
};

View File

@ -10,12 +10,7 @@ const decorate = compose(
export default () => class Existent extends decorate(Trait) {
#isDestroying;
constructor(...args) {
super(...args);
this.#isDestroying = false;
}
#isDestroying = false;
static behaviorTypes() {
return {

View File

@ -3,16 +3,9 @@ import {Trait} from '@avocado/traits';
export default () => class Listed extends Trait {
#quadTreeAabb;
#quadTreeAabb = [];
#quadTreeNodes;
constructor(...args) {
super(...args);
this.entity.list = null;
this.#quadTreeAabb = [];
this.#quadTreeNodes = [];
}
#quadTreeNodes = [];
addQuadTreeNodes() {
const {list} = this.entity;
@ -71,6 +64,11 @@ export default () => class Listed extends Trait {
};
}
load(json) {
super.load(json);
this.entity.list = null;
}
methods() {
return {

View File

@ -10,12 +10,7 @@ const decorate = compose(
export default () => class Mobile extends decorate(Trait) {
#appliedMovement;
constructor(...args) {
super(...args);
this.#appliedMovement = [0, 0];
}
#appliedMovement = [0, 0];
static behaviorTypes() {
return {

View File

@ -6,11 +6,13 @@ const decorate = compose(
export default () => class Perishable extends decorate(Trait) {
#ttl;
#ttl = 0;
constructor(...args) {
super(...args);
this.#ttl = this.params.ttl;
constructor() {
super();
({
ttl: this.#ttl,
} = this.constructor.defaultParams());
}
static defaultParams() {
@ -28,6 +30,11 @@ export default () => class Perishable extends decorate(Trait) {
};
}
load(json) {
super.load(json);
this.#ttl = this.params.ttl;
}
tick(elapsed) {
this.#ttl -= elapsed;
if (this.#ttl <= 0) {

View File

@ -15,16 +15,10 @@ const decorate = compose(
// < 16768 will pack into 1 short per axe and give +/- 0.25 precision.
export default () => class Positioned extends decorate(Trait) {
constructor(...args) {
super(...args);
constructor() {
super();
this.on('trackedPositionChanged', this.onTrackedPositionChanged, this);
const {x, y} = this.state;
this.trackedPosition = [x, y];
this.entity.position[0] = x;
this.entity.position[1] = y;
if ('client' === process.env.SIDE) {
this.serverPosition = this.trackedPosition;
this.serverPositionDirty = false;
this.on('serverPositionChanged', this.onServerPositionChanged, this);
}
}
@ -80,6 +74,18 @@ export default () => class Positioned extends decorate(Trait) {
}
}
load(json) {
super.load(json);
const {x, y} = this.state;
this.trackedPosition = [x, y];
this.entity.position[0] = x;
this.entity.position[1] = y;
if ('client' === process.env.SIDE) {
this.serverPosition = this.trackedPosition;
this.serverPositionDirty = false;
}
}
// eslint-disable-next-line camelcase
onTrackedPositionChanged(oldPosition, newPosition) {
[this.entity.position[0], this.entity.position[1]] = newPosition;
@ -102,7 +108,7 @@ export default () => class Positioned extends decorate(Trait) {
this.entity.position,
]];
}
return undefined;
return [];
}
listeners() {

View File

@ -18,11 +18,30 @@ export default (latus) => class Spawner extends decorate(Trait) {
#spawnJSONs;
constructor(...args) {
super(...args);
constructor() {
super();
this.#children = [];
this.#childrenListeners = new Map();
this.#spawnJSONs = this.params.spawns;
}
// eslint-disable-next-line class-methods-use-this
augmentJSONWithPosition(json, position) {
/* eslint-disable no-param-reassign */
if (!json.traits) {
json.traits = {};
}
if (!json.traits.Positioned) {
json.traits.Positioned = {};
}
if (!json.traits.Positioned.state) {
json.traits.Positioned.state = {};
}
[
json.traits.Positioned.state.x,
json.traits.Positioned.state.y,
] = position;
/* eslint-enable no-param-reassign */
return json;
}
static behaviorTypes() {
@ -132,34 +151,6 @@ export default (latus) => class Spawner extends decorate(Trait) {
}
}
static optionsForSpawn(entity) {
if (!entity) {
return undefined;
}
return Object.keys(entity.trait('Spawner').params.spawns)
.reduce((r, key) => ({...r, [key]: key}), {});
}
// eslint-disable-next-line class-methods-use-this
augmentJSONWithPosition(json, position) {
/* eslint-disable no-param-reassign */
if (!json.traits) {
json.traits = {};
}
if (!json.traits.Positioned) {
json.traits.Positioned = {};
}
if (!json.traits.Positioned.state) {
json.traits.Positioned.state = {};
}
[
json.traits.Positioned.state.x,
json.traits.Positioned.state.y,
] = position;
/* eslint-enable no-param-reassign */
return json;
}
destinationEntityList() {
if (
this.entity.is('Listed')
@ -212,7 +203,7 @@ export default (latus) => class Spawner extends decorate(Trait) {
if (!this.maySpawn()) {
return undefined;
}
const spawnJSON = this.#spawnJSONs[key];
const spawnJSON = this.params.spawns[key];
if (!spawnJSON) {
return undefined;
}
@ -260,6 +251,14 @@ export default (latus) => class Spawner extends decorate(Trait) {
};
}
static optionsForSpawn(entity) {
if (!entity) {
return undefined;
}
return Object.keys(entity.trait('Spawner').params.spawns)
.reduce((r, key) => ({...r, [key]: key}), {});
}
removeChild(child) {
const index = this.#children.indexOf(child);
if (-1 !== index) {

View File

@ -29,8 +29,7 @@ it('can add and remove traits', async () => {
};
traits(latus).fromType['TestTrait'] = TestTrait;
const trait = await TestTrait.load();
entity.addTrait(TestTrait);
await entity.addTrait('TestTrait');
expect(entity.is('TestTrait')).to.be.true;
entity.removeTrait('TestTrait');
expect(entity.is('TestTrait')).to.be.false;
@ -86,8 +85,10 @@ it('can invoke hooks', async () => {
}
}
latus.set('%traits.fromType.AnotherTrait', AnotherTrait);
latus.set('%traits.fromType.YetAnotherTrait', YetAnotherTrait);
const entity = new Entity();
entity.addTrait(AnotherTrait);
entity.addTrait(YetAnotherTrait);
await entity.addTrait('AnotherTrait');
await entity.addTrait('YetAnotherTrait');
expect(entity.invokeHook('testHook')).to.deep.equal({AnotherTrait: 69, YetAnotherTrait: 420});
});

View File

@ -66,8 +66,8 @@
"@avocado/resource@2.0.0", "@avocado/resource@^2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@avocado%2fresource/-/resource-2.0.0.tgz#c4cecaae1ce8321966375373445afa5fedec277d"
integrity sha512-opGtIRXqWhtax0/p4E0wroR3GvUBD+NPljIjUNsogFRHtDswfQOt5QVRGTMoariwLfedx4NaPJgvLRsaOa6I9w==
resolved "http://npm.cha0sdev/@avocado%2fresource/-/resource-2.0.0.tgz#12b9b1ee4bcb43ede8ba2172f16c82dc2f115d0f"
integrity sha512-qNTzFfkZMwYX+IEl64Del4uSfQKpWm6kR1KtlOWCbU5nc3sH5d9U+nFfbmGAJArEhC9lo2s2lQITvgkJ7D1VuQ==
dependencies:
"@avocado/core" "2.0.0"
"@latus/core" "2.0.0"
@ -103,8 +103,8 @@
"@avocado/traits@^2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@avocado%2ftraits/-/traits-2.0.0.tgz#e71cb68af6d40e87a43220760021f3e73a322f8a"
integrity sha512-DSXPLrFTelPGBJxciOTUspTKrzkQp8aEchVoTJelsJwbvVtjwqbxPbDLykvivq30iXV5KLRICY63qB0mWKx22w==
resolved "http://npm.cha0sdev/@avocado%2ftraits/-/traits-2.0.0.tgz#f1a9380be8e2dbce6235e565646f0ecdc116afb5"
integrity sha512-CRmBVJHpmiJEH+JHQXrS0/pZPNfLcCkhIVd2hYssKpZ1ipLskftZ9AvN8h4xYifqEMhlgGQqNJ340UYuf5ekuw==
dependencies:
"@avocado/core" "^2.0.0"
"@avocado/resource" "^2.0.0"

View File

@ -14,20 +14,16 @@ const decorate = compose(
export default (latus) => class Pictured extends decorate(Trait) {
#currentImage;
#currentImage = '';
#sprites;
#sprites = {};
constructor(json) {
super(json);
constructor() {
super();
this._cachedAabbs = {};
if (json.sprites) {
Object.entries(json.sprites).forEach(([key, sprite]) => {
// eslint-disable-next-line no-param-reassign
sprite.position = this.offsetFor(key);
});
this.#sprites = json.sprites;
}
({
currentImage: this.#currentImage,
} = this.constructor.defaultState());
}
static defaultParams() {
@ -159,6 +155,17 @@ export default (latus) => class Pictured extends decorate(Trait) {
};
}
load(json) {
super.load(json);
if (json.sprites) {
Object.keys(json.sprites).forEach((key) => {
// eslint-disable-next-line no-param-reassign
json.sprites[key].position = this.offsetFor(key);
});
this.#sprites = json.sprites;
}
}
offsetFor(key) {
if (!this.params.images[key] || !this.params.images[key].offset) {
return [0, 0];

View File

@ -5,6 +5,8 @@ import Primitives from '../primitives';
export default () => class Primitive extends Trait {
#primitives;
static defaultParams() {
return {
primitives: [],
@ -20,19 +22,14 @@ export default () => class Primitive extends Trait {
};
}
constructor(entity, params, state) {
super(entity, params, state);
this._primitives = undefined;
}
drawPrimitives() {
if (!this.entity.container) {
return;
}
if (this._primitives) {
this.entity.container.removeChild(this._primitives);
if (this.#primitives) {
this.entity.container.removeChild(this.#primitives);
}
this._primitives = new Primitives();
this.#primitives = new Primitives();
for (let i = 0; i < this.params.primitives.length; i++) {
const primitive = this.params.primitives[i];
if ('circle' === primitive.type) {
@ -44,7 +41,7 @@ export default () => class Primitive extends Trait {
const fill = primitive.fill ? primitive.fill : {
rgba: [0, 0, 0, 0],
};
this._primitives.drawCircle(
this.#primitives.drawCircle(
primitive.position || [0, 0],
primitive.radius,
Primitives.lineStyle(new Color(...line.rgba), 1),
@ -52,7 +49,7 @@ export default () => class Primitive extends Trait {
);
}
}
this.entity.container.addChild(this._primitives);
this.entity.container.addChild(this.#primitives);
}
listeners() {

View File

@ -11,6 +11,8 @@ const decorate = compose(
export default () => class Textual extends decorate(Trait) {
#text;
static defaultState() {
return {
text: '',
@ -31,21 +33,16 @@ export default () => class Textual extends decorate(Trait) {
};
}
constructor(entity, params, state) {
super(entity, params, state);
this._text = undefined;
}
loadText() {
if (!this.entity.container) {
return;
}
if (this._text) {
this.entity.container.removeChild(this._text);
if (this.#text) {
this.entity.container.removeChild(this.#text);
}
this._text = new Text(this.state.text, this.state.textStyle);
this._text.zIndex = 1000;
this.entity.container.addChild(this._text);
this.#text = new Text(this.state.text, this.state.textStyle);
this.#text.zIndex = 1000;
this.entity.container.addChild(this.#text);
}
listeners() {

View File

@ -1,5 +1,5 @@
import {StateProperty, Trait} from '@avocado/traits';
import {Rectangle} from '@avocado/math';
import {Rectangle, Vector} from '@avocado/math';
import {compose} from '@latus/core';
import Container from '../container';
@ -27,6 +27,33 @@ const decorate = compose(
export default () => class Visible extends decorate(Trait) {
#container;
#rawVisibleAabb = [0, 0, 0, 0];
#scheduledBoundingBoxUpdate = true;
#usingAutoZIndex = true;
#visibleScale = [0, 0];
constructor() {
super();
if ('client' === process.env.SIDE) {
this.#container = new Container();
}
({
visibleScale: this.#visibleScale,
} = this.constructor.defaultState());
}
acceptPacket(packet) {
if ('TraitUpdateVisible' === packet.constructor.type) {
this.entity.isVisible = packet.data.isVisible;
this.entity.opacity = packet.data.opacity;
}
}
static behaviorTypes() {
return {
updateVisibleBoundingBox: {
@ -40,7 +67,6 @@ export default () => class Visible extends decorate(Trait) {
static defaultParams() {
return {
filter: undefined,
trackPosition: true,
};
}
@ -60,10 +86,6 @@ export default () => class Visible extends decorate(Trait) {
type: 'object',
label: 'Filter',
},
trackPosition: {
type: 'bool',
label: 'Track position',
},
};
}
@ -92,46 +114,91 @@ export default () => class Visible extends decorate(Trait) {
};
}
constructor(json) {
super(json);
if ('client' === process.env.SIDE) {
this._container = new Container();
const {filter} = this.params;
if (filter) {
this._container.setFilter(filter);
}
this._container.isVisible = this.state.isVisible;
}
this._rawVisibleAabb = [0, 0, 0, 0];
this.scheduledBoundingBoxUpdate = true;
this.trackPosition = this.params.trackPosition;
const scale = this.state.visibleScale;
this._visibleScale = [scale[0], scale[1]];
this.onZIndexChanged(this.state.zIndex);
}
destroy() {
if (this._container) {
this._container.destroy();
}
}
acceptPacket(packet) {
if ('TraitUpdateVisible' === packet.constructor.type) {
this.entity.isVisible = packet.data.isVisible;
this.entity.opacity = packet.data.opacity;
if (this.#container) {
this.#container.destroy();
}
}
get container() {
return this._container;
return this.#container;
}
listeners() {
return {
isVisibleChanged: () => {
if (!this.#container) {
return;
}
this.#container.visible = this.entity.isVisible;
},
opacityChanged: () => {
if (!this.#container) {
return;
}
this.#container.alpha = this.entity.opacity;
},
positionChanged: () => {
this.translateVisibleAabb();
},
rotationChanged: () => {
if (!this.#container) {
return;
}
this.#container.rotation = this.entity.rotation;
},
traitAdded: (type) => {
if (-1 === [
'visible',
'positioned',
].indexOf(type)) {
return;
}
this.synchronizePosition();
},
updateVisibleBoundingBox: () => {
this.#scheduledBoundingBoxUpdate = true;
},
visibleScaleChanged: () => {
this.#visibleScale = Vector.copy(this.entity.visibleScale);
if (this.#container) {
this.#container.scale = this.#visibleScale;
}
},
zIndexChanged: (old, zIndex) => {
this.onZIndexChanged(zIndex);
},
};
}
load(json) {
super.load(json);
if ('client' === process.env.SIDE) {
const {filter} = this.params;
if (filter) {
this.#container.setFilter(filter);
}
this.#container.isVisible = this.state.isVisible;
}
this.#visibleScale = Vector.copy(this.state.visibleScale);
this.onZIndexChanged(this.state.zIndex);
this.entity.emit('updateVisibleBoundingBox');
}
onZIndexChanged(zIndex) {
this._usingAutoZIndex = AUTO_ZINDEX === zIndex;
if (!this._usingAutoZIndex) {
if (this._container) {
this._container.zIndex = zIndex;
this.#usingAutoZIndex = AUTO_ZINDEX === zIndex;
if (!this.#usingAutoZIndex) {
if (this.#container) {
this.#container.zIndex = zIndex;
}
}
}
@ -147,28 +214,32 @@ export default () => class Visible extends decorate(Trait) {
},
]];
}
return undefined;
return [];
}
get rawVisibleScale() {
return this._visibleScale;
return this.#visibleScale;
}
set rawVisibleScale(scale) {
this.entity.visibleScale = scale;
}
renderTick() {
this.synchronizePosition();
}
synchronizePosition() {
if (!this.entity.is('positioned')) {
return;
}
if (!this._container) {
if (!this.#container) {
return;
}
this._container.position = this.entity.position;
if (this._usingAutoZIndex) {
if (this._container) {
this._container.zIndex = this.entity.y;
this.#container.position = this.entity.position;
if (this.#usingAutoZIndex) {
if (this.#container) {
this.#container.zIndex = this.entity.y;
}
}
}
@ -189,70 +260,34 @@ export default () => class Visible extends decorate(Trait) {
this.rawVisibleScale = [this.visibleScaleX, y];
}
listeners() {
return {
isVisibleChanged: () => {
if (!this._container) {
return;
tick() {
if ('client' !== process.env.SIDE) {
if (this.#scheduledBoundingBoxUpdate) {
// Collect all bounding boxes.
const visibleAabbs = this.entity.invokeHookFlat('visibleAabbs');
if (0 === visibleAabbs.length) {
this.#rawVisibleAabb = [0, 0, 0, 0];
}
this._container.visible = this.entity.isVisible;
},
opacityChanged: () => {
if (!this._container) {
return;
else {
let unifiedBoundingBox = [0, 0, 0, 0];
for (let i = 0; i < visibleAabbs.length; ++i) {
const visibleAabb = visibleAabbs[i];
unifiedBoundingBox = Rectangle.united(
unifiedBoundingBox,
visibleAabb,
);
}
this.#rawVisibleAabb = unifiedBoundingBox;
}
this._container.alpha = this.entity.opacity;
},
positionChanged: () => {
this.translateVisibleAabb();
},
rotationChanged: () => {
if (!this._container) {
return;
}
this._container.rotation = this.entity.rotation;
},
traitAdded: (type) => {
if (-1 === [
'visible',
'positioned',
].indexOf(type)) {
return;
}
this.synchronizePosition();
},
updateVisibleBoundingBox: () => {
this.scheduledBoundingBoxUpdate = true;
},
visibleScaleChanged: () => {
const scale = this.entity.visibleScale;
this._visibleScale = [scale[0], scale[1]];
if (this._container) {
this._container.scale = this._visibleScale;
}
},
zIndexChanged: (old, zIndex) => {
this.onZIndexChanged(zIndex);
},
};
}
renderTick() {
this.synchronizePosition();
this.#scheduledBoundingBoxUpdate = false;
}
}
}
translateVisibleAabb() {
const visibleAabb = Rectangle.translated(
this._rawVisibleAabb,
this.#rawVisibleAabb,
this.entity.position,
);
/* eslint-disable prefer-destructuring */
@ -264,29 +299,4 @@ export default () => class Visible extends decorate(Trait) {
this.entity.emit('visibleAabbChanged');
}
tick() {
if ('client' !== process.env.SIDE) {
if (this.scheduledBoundingBoxUpdate) {
// Collect all bounding boxes.
const visibleAabbs = this.entity.invokeHookFlat('visibleAabbs');
if (0 === visibleAabbs.length) {
this._rawVisibleAabb = [0, 0, 0, 0];
}
else {
let unifiedBoundingBox = [0, 0, 0, 0];
for (let i = 0; i < visibleAabbs.length; ++i) {
const visibleAabb = visibleAabbs[i];
unifiedBoundingBox = Rectangle.united(
unifiedBoundingBox,
visibleAabb,
);
}
this._rawVisibleAabb = unifiedBoundingBox;
}
this.translateVisibleAabb();
this.scheduledBoundingBoxUpdate = false;
}
}
}
};

View File

@ -4,15 +4,15 @@
"@avocado/core@2.0.0", "@avocado/core@^2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@avocado%2fcore/-/core-2.0.0.tgz#69c736d6a1d8b25d0cc57f07fabdef3f467a5636"
integrity sha512-XqLqDST/gLCbyBNQuZnzj8WN05aEgko8Kh/45pN0cSNA5DRMgkZSynBZh0NMEtiYfC5Od6v6y7FF5uvuzh4+gg==
resolved "http://npm.cha0sdev/@avocado%2fcore/-/core-2.0.0.tgz#2debb82ce9947a22575032af6719531278f6f98a"
integrity sha512-XGikLesJP42xgTOFy0gxPCNp0NnE9NK7xCHNAcs2tU4XOxNPTYv5cPp1FP21cHdf2b6joiNmFnWNBg1mvF0AJA==
dependencies:
debug "4.3.1"
"@avocado/input@2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@avocado%2finput/-/input-2.0.0.tgz#bdd839a2c977c3414fd3590a14dde2ef1cb8067e"
integrity sha512-KtGGH82WLdT0699+/Fw9bhimIOsZEhE9hhr5OuXxWDp8JVVzrrD/1jytC6Ue3012Na0rVKtdkMGewoAB0Fv0GQ==
resolved "http://npm.cha0sdev/@avocado%2finput/-/input-2.0.0.tgz#c73ebd8f821663e5c30c572e4efbe7d34bb1bb7f"
integrity sha512-lrv+bsBtsfV9ps3QNfNbcnPXOuzu99XZqtbDB/NK8umGKQogKQg7Ix9tiXbciHibIfTejiG5mapHr+SVbHrO5Q==
dependencies:
"@latus/core" "2.0.0"
"@latus/socket" "2.0.0"
@ -20,8 +20,8 @@
"@avocado/math@2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@avocado%2fmath/-/math-2.0.0.tgz#9e3fb073d93799f8f86a1abbaaabd5021fc753ad"
integrity sha512-vIgwR0p7I9jnXqUr/6cD9i2k/Z8GJuWqNIxksmPF8Odw1SON/4ItbLYk3D5+Z/KnDOeIa2N2Db9IoymcOofBgw==
resolved "http://npm.cha0sdev/@avocado%2fmath/-/math-2.0.0.tgz#9b4c05098f287ebe814b6ef954ac0ab4140c51dc"
integrity sha512-KEX7fkzxUtiXNlSYEOdp/Juv0YFhdvPExgW3zI61kBDZvJr3fNJWJ9slrf1ikSGFWrtcH2tUESlTToRHPLd2Qg==
dependencies:
"@avocado/core" "2.0.0"
"@latus/core" "^2.0.0"
@ -30,8 +30,8 @@
"@avocado/resource@2.0.0", "@avocado/resource@^2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@avocado%2fresource/-/resource-2.0.0.tgz#9eadafaf1ce7a8d6308c59bfa92290830cf91e30"
integrity sha512-85osPtux7MZ+9dAFGrLKzIv1vAPuSBfxEwPZOvKaHMSBa6mnzysC7c2FbU4zfSioDl8ozqknE9ZYZB1bjdw0Hg==
resolved "http://npm.cha0sdev/@avocado%2fresource/-/resource-2.0.0.tgz#12b9b1ee4bcb43ede8ba2172f16c82dc2f115d0f"
integrity sha512-qNTzFfkZMwYX+IEl64Del4uSfQKpWm6kR1KtlOWCbU5nc3sH5d9U+nFfbmGAJArEhC9lo2s2lQITvgkJ7D1VuQ==
dependencies:
"@avocado/core" "2.0.0"
"@latus/core" "2.0.0"
@ -41,8 +41,8 @@
"@avocado/s13n@^2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@avocado%2fs13n/-/s13n-2.0.0.tgz#2b0ea781520f5c41dcd6c3bfc1a6cd52ce181c69"
integrity sha512-TkxxmQQRS7NbpvNxLQ1RME+7vIpGm198sPSNcDfBLMwcQ2Icl8jTx5HFaIaCLh6XezFN/MhQzDjZ62XVqxWEeg==
resolved "http://npm.cha0sdev/@avocado%2fs13n/-/s13n-2.0.0.tgz#3aff3c15a6e8ef2a405e7b9ff45abd94e63f064d"
integrity sha512-UAmde98frU3TWlK0yIvHYM/PX+dpyx4O+a5QWQakm7ef9vZomPwyN/2Z87ArliOZILO3qhvusFqiLusUf8z7HA==
dependencies:
"@avocado/resource" "^2.0.0"
"@latus/core" "2.0.0"
@ -52,8 +52,8 @@
"@avocado/traits@^2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@avocado%2ftraits/-/traits-2.0.0.tgz#369ce54e55b6a32c1591efcf31e19785f827b943"
integrity sha512-0+CatzN3YFm1HBUQ1n0a2j2/cmtNo6hjNtjiJINFkqEUmpwGnoub+yB4x7HW837IjnqvLeD53Mu6YUxC9nOstQ==
resolved "http://npm.cha0sdev/@avocado%2ftraits/-/traits-2.0.0.tgz#7aa7c5504e627967189343a58248c123f80e44a4"
integrity sha512-7hoiN/MQmBGeGPg8wtg5erXxS5053IGsRyM0qdbnhkIY0tWLBJ2NjREqkDfC2avsJAc4yK5+x+l2PFpLJivxww==
dependencies:
"@avocado/core" "^2.0.0"
"@avocado/resource" "^2.0.0"
@ -962,8 +962,8 @@
"@latus/core@2.0.0", "@latus/core@^2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@latus%2fcore/-/core-2.0.0.tgz#1f001c8deead6c58e51a32aa4cedee7f26403a58"
integrity sha512-0Co6k1MZE5dBwwa8IMtl2Szk69KdvmMBvLQh45JLnGPhSodQ06+carStEn9r8dr+RvaDZpNRQohyxQFZV5ioJw==
resolved "http://npm.cha0sdev/@latus%2fcore/-/core-2.0.0.tgz#24e8313875563b729f32c7d98fb394b116f2adba"
integrity sha512-CKEb7xoyBXwZHlUmPWUU/egXuzpKkIZFVioKfnDTHNydDKaKG0TW0ugg6EX6Le81CFt9RovMALKJm2s4A7UiVQ==
dependencies:
debug "4.3.1"
js-yaml "3.14.0"
@ -974,8 +974,8 @@
"@latus/http@2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@latus%2fhttp/-/http-2.0.0.tgz#887a144f8029291818ed85fbe1a6462a2e01740f"
integrity sha512-f0tlfVq5Yp0ioYS/cY24odm4N3jJaqeq/gNshppNKzYf+k9/HzM+8khGBbol+1/6OZLq3zVDoZqYNJRQUci3Rg==
resolved "http://npm.cha0sdev/@latus%2fhttp/-/http-2.0.0.tgz#3589fcb76a5e7a4763b45853d696289b3ce478b3"
integrity sha512-jWhJa93uLksNEEQhFKq36de5jHCKoQZBel57DIxaTk+jAIfzPO+kmWlTaq/wGCiCxlnHLjvTuMGOiDABVew4aQ==
dependencies:
"@latus/core" "2.0.0"
"@neutrinojs/web" "^9.1.0"
@ -994,8 +994,8 @@
"@latus/react@2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@latus%2freact/-/react-2.0.0.tgz#09f4699218a73c19ff0c7c299a6c48f053316512"
integrity sha512-HZN9THHkZSWUwDDh8S2k+FiLfrmRbT4eUTs+ZJsQuWCdS6NQpBoTp2kjGe5wG/h0HoHwFfh+tjs728BXZXlLNQ==
resolved "http://npm.cha0sdev/@latus%2freact/-/react-2.0.0.tgz#25fd38202ff83a5ceb9ab0574a45a255db96905a"
integrity sha512-Yy7x2BdDlNe7njxAZONx1fI2MhebnlLjZfT2mz9JkoGNfaFWdDCLdaouYn8WH5u7ihMeGcSCVTizFwr4rZj9UQ==
dependencies:
"@hot-loader/react-dom" "^17.0.1"
"@neutrinojs/react" "^9.4.0"
@ -1009,8 +1009,8 @@
"@latus/socket@2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@latus%2fsocket/-/socket-2.0.0.tgz#8128b1244b3458ac0dfcd4d6d1256cd741b0e73e"
integrity sha512-bH6WZZ2C0FiIZEsJuJQk2M9iHBPzAZZ8gBKB3XYWl+pwb535bHLnoMCkbV3LZhMiguZnIjUt7mSYZAGybvOvNw==
resolved "http://npm.cha0sdev/@latus%2fsocket/-/socket-2.0.0.tgz#ba0d9cc2099474ba1dbba2b4e27e92a6fc271087"
integrity sha512-ZDOxbRwoiEO2E/QeS4GjO1950oVeH+i4Gw4ep6K/TPBbhkaiDrp8MpZyUxM6hDDEDf1Q6V1gAH+4FLPsUncdYw==
dependencies:
"@latus/core" "2.0.0"
"@latus/http" "2.0.0"

View File

@ -10,40 +10,29 @@ const decorate = compose(
export default () => class Collider extends decorate(Trait) {
#collidesWithGroups;
#collidesWithGroups = [];
#collisionEndActions;
#collisionStartActions;
#collisionGroup;
#collisionGroup = '';
#doesNotCollideWith;
#doesNotCollideWith = [];
#isCollidingWith;
#isCollidingWith = [];
#isSensor;
#isSensor = false;
constructor(...args) {
super(...args);
const {
collidesWithGroups,
collisionEndActions,
collisionGroup,
collisionStartActions,
isSensor,
} = this.params;
this.#collidesWithGroups = collidesWithGroups;
this.#collisionEndActions = collisionEndActions.length > 0
? new Actions(compile(collisionEndActions))
: undefined;
this.#collisionStartActions = collisionStartActions.length > 0
? new Actions(compile(collisionStartActions))
: undefined;
this.#collisionGroup = collisionGroup;
this.#doesNotCollideWith = [];
this.#isCollidingWith = [];
this.#isSensor = isSensor;
constructor() {
super();
({
collisionEndActions: this.#collisionEndActions,
collisionStartActions: this.#collisionStartActions,
collidesWithGroups: this.#collidesWithGroups,
collisionGroup: this.#collisionGroup,
isSensor: this.#isSensor,
} = this.constructor.defaultParams());
}
static behaviorTypes() {
@ -228,6 +217,26 @@ export default () => class Collider extends decorate(Trait) {
return this.#isSensor;
}
load(load) {
super.load(load);
const {
collidesWithGroups,
collisionEndActions,
collisionGroup,
collisionStartActions,
isSensor,
} = this.params;
this.#collidesWithGroups = collidesWithGroups;
this.#collisionEndActions = collisionEndActions.length > 0
? new Actions(compile(collisionEndActions))
: undefined;
this.#collisionStartActions = collisionStartActions.length > 0
? new Actions(compile(collisionStartActions))
: undefined;
this.#collisionGroup = collisionGroup;
this.#isSensor = isSensor;
}
pushCollisionTickingPromise(actions, other) {
const context = new Context({
entity: [this.entity, 'entity'],

View File

@ -33,23 +33,24 @@ export default () => class Emitted extends decorate(Trait) {
constructor(...args) {
super(...args);
this.#alphaStart = new Range(this.params.alpha.start);
this.#alphaEnd = new Range(this.params.alpha.end);
this.#force = new Vector.Range(this.params.force);
this.#mass = this.params.mass;
if (null !== this.params.position) {
this.#position = new Vector.Range(this.params.position);
const params = this.constructor.defaultParams();
this.#alphaStart = new Range(params.alpha.start);
this.#alphaEnd = new Range(params.alpha.end);
this.#force = new Vector.Range(params.force);
this.#mass = params.mass;
if (null !== params.position) {
this.#position = new Vector.Range(params.position);
}
else {
this.#position = null;
}
this.#rotationStart = new Range(this.params.rotation.start);
this.#rotationAdd = new Range(this.params.rotation.add);
this.#scaleStart = new Range(this.params.scale.start);
this.#scaleEnd = new Range(this.params.scale.end);
this.#ttl = this.params.ttl;
this.#velocityAngle = new Range(this.params.velocity.angle);
this.#velocityMagnitude = new Range(this.params.velocity.magnitude);
this.#rotationStart = new Range(params.rotation.start);
this.#rotationAdd = new Range(params.rotation.add);
this.#scaleStart = new Range(params.scale.start);
this.#scaleEnd = new Range(params.scale.end);
this.#ttl = params.ttl;
this.#velocityAngle = new Range(params.velocity.angle);
this.#velocityMagnitude = new Range(params.velocity.magnitude);
}
static behaviorTypes() {
@ -137,6 +138,27 @@ export default () => class Emitted extends decorate(Trait) {
return !!this.params.transient;
}
load(json) {
super.load(json);
this.#alphaStart = new Range(this.params.alpha.start);
this.#alphaEnd = new Range(this.params.alpha.end);
this.#force = new Vector.Range(this.params.force);
this.#mass = this.params.mass;
if (null !== this.params.position) {
this.#position = new Vector.Range(this.params.position);
}
else {
this.#position = null;
}
this.#rotationStart = new Range(this.params.rotation.start);
this.#rotationAdd = new Range(this.params.rotation.add);
this.#scaleStart = new Range(this.params.scale.start);
this.#scaleEnd = new Range(this.params.scale.end);
this.#ttl = this.params.ttl;
this.#velocityAngle = new Range(this.params.velocity.angle);
this.#velocityMagnitude = new Range(this.params.velocity.magnitude);
}
methods() {
return {

View File

@ -13,24 +13,20 @@ const decorate = compose(
export default (latus) => class Emitter extends decorate(Trait) {
#emissions;
#emissions = [];
#emitter;
#emitter = new Proton.Emitter();
#onParticleDead;
#onParticleUpdate;
#particles;
#particles = {};
#proton;
#proton = new Proton();
constructor(...args) {
super(...args);
this.#emissions = [];
this.#emitter = new Proton.Emitter();
this.#particles = {};
this.#proton = new Proton();
constructor() {
super();
this.#proton.addEmitter(this.#emitter);
this.#onParticleDead = this.onParticleDead.bind(this);
this.#onParticleUpdate = this.onParticleUpdate.bind(this);
@ -94,12 +90,9 @@ export default (latus) => class Emitter extends decorate(Trait) {
};
}
emitParticleJson(json, emitter) {
async emitParticleJson(json) {
const {fromResourceType: {Entity}} = resource(latus);
Entity.loadOrInstance(json).then((particle) => {
this.entity.emitParticleEntity(particle);
emitter.emit(particle);
});
return this.entity.emitParticleEntity(await Entity.load(json));
}
gatherParticles() {
@ -208,12 +201,16 @@ export default (latus) => class Emitter extends decorate(Trait) {
const stream = K.stream((emitter) => {
if (0 === rate) {
for (let i = 0; i < count; ++i) {
this.emitParticleJson(json, emitter);
this.emitParticleJson(json).then((particle) => {
emitter.emit(particle);
});
}
}
else {
const ticker = new Ticker(rate);
this.emitParticleJson(json, emitter);
this.emitParticleJson(json).then((particle) => {
emitter.emit(particle);
});
count -= 1;
if (count > 0) {
const removeEmission = () => {
@ -225,7 +222,9 @@ export default (latus) => class Emitter extends decorate(Trait) {
};
this.entity.on('destroy', removeEmission);
ticker.on('tick', () => {
this.emitParticleJson(json, emitter);
this.emitParticleJson(json).then((particle) => {
emitter.emit(particle);
});
if (0 >= --count) {
removeEmission();
}
@ -246,8 +245,7 @@ export default (latus) => class Emitter extends decorate(Trait) {
if (!particleJson) {
return undefined;
}
const mergedJson = merge({}, particleJson, json);
return this.entity.emitParticleJson(mergedJson);
return this.entity.emitParticleJson(merge(particleJson, json));
},
};

View File

@ -12,28 +12,27 @@ const decorate = compose(
export default () => class Physical extends decorate(Trait) {
constructor(entity, params, state) {
super(entity, params, state);
this._body = undefined;
this.bodyView = undefined;
this._world = undefined;
}
#body;
#bodyView;
#world;
addToWorld() {
const world = this._world;
const world = this.#world;
if (world) {
const body = world.createBody(this.entity.shape);
world.associateBodyWithEntity(body, this.entity);
body.setCollisionForEntity(this.entity);
world.addBody(body);
this._body = body;
this.#body = body;
if ('client' === process.env.SIDE) {
if (this.entity.is('visible') && this.entity.is('debuggable')) {
this.bodyView = new BodyView(body);
this.bodyView.position = Vector.scale(this.entity.position, -1);
this.bodyView.visible = this.entity.isDebugging;
this.bodyView.zIndex = 101;
this.entity.container.addChild(this.bodyView);
this.#bodyView = new BodyView(body);
this.#bodyView.position = Vector.scale(this.entity.position, -1);
this.#bodyView.visible = this.entity.isDebugging;
this.#bodyView.zIndex = 101;
this.entity.container.addChild(this.#bodyView);
}
}
}
@ -63,7 +62,7 @@ export default () => class Physical extends decorate(Trait) {
}
get body() {
return this._body;
return this.#body;
}
static defaultState() {
@ -94,11 +93,11 @@ export default () => class Physical extends decorate(Trait) {
addedToPhysicsChanged: () => {
if (this.entity.addedToPhysics) {
if (!this._body) {
if (!this.#body) {
this.addToWorld();
}
}
else if (this._body) {
else if (this.#body) {
this.removeFromWorld();
}
},
@ -108,14 +107,14 @@ export default () => class Physical extends decorate(Trait) {
},
positionChanged: () => {
if (this._body) {
if (this.#body) {
const {position} = this.entity;
this._body.position = position;
this.#body.position = position;
}
},
removedFromRoom: () => {
if (this._body) {
if (this.#body) {
this.removeFromWorld();
}
},
@ -127,14 +126,14 @@ export default () => class Physical extends decorate(Trait) {
return {
applyForce: (force) => {
if (this._world && this._body) {
this._body.applyForce(force);
if (this.#world && this.#body) {
this.#body.applyForce(force);
}
},
applyImpulse: (impulse) => {
if (this._world && this._body) {
this._body.applyImpulse(impulse);
if (this.#world && this.#body) {
this.#body.applyImpulse(impulse);
}
},
@ -142,22 +141,22 @@ export default () => class Physical extends decorate(Trait) {
}
removeFromWorld() {
if (this._world && this._body) {
this._world.removeBody(this._body);
if (this.#world && this.#body) {
this.#world.removeBody(this.#body);
}
this._body = undefined;
if (this.bodyView) {
this.#body = undefined;
if (this.#bodyView) {
if (this.entity.is('visible')) {
this.entity.container.removeChild(this.bodyView);
this.entity.container.removeChild(this.#bodyView);
}
this.bodyView.destroy();
this.#bodyView.destroy();
}
this.bodyView = undefined;
this.#bodyView = undefined;
}
set world(world) {
this.removeFromWorld();
this._world = world;
this.#world = world;
this.addToWorld();
}

View File

@ -13,12 +13,6 @@ export default () => class Shaped extends decorate(Trait) {
#shapeView;
constructor(...args) {
super(...args);
this.#shape = shapeFromJSON(this.params.shape);
this.#shapeView = undefined;
}
static defaultParams() {
return {
shape: undefined,
@ -61,6 +55,11 @@ export default () => class Shaped extends decorate(Trait) {
};
}
load(json) {
super.load(json);
this.#shape = shapeFromJSON(this.params.shape);
}
get shape() {
return this.#shape;
}

View File

@ -4,8 +4,8 @@
"@avocado/behavior@2.0.0", "@avocado/behavior@^2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@avocado%2fbehavior/-/behavior-2.0.0.tgz#34cf4235cb85165f4b4bdee108d1efacc6732330"
integrity sha512-wQnnjXp69RW9EWeovUjH3goMoYyD6EHKyiCnkdJMb/Z9h9rwARpYqKTmq1iNgliOJ/8KpJelNi/v1+dvmlJxYA==
resolved "http://npm.cha0sdev/@avocado%2fbehavior/-/behavior-2.0.0.tgz#a9987223869f14c623b1442976ffa18c6e008cde"
integrity sha512-tu/he7jtSeJEixscClx5zN+VAhhWR5k/If/fnh0WIPET52TIa3TNBuozjPSH3Yw1IiAwIVnMdjD2pv5QXLnAPQ==
dependencies:
"@avocado/core" "2.0.0"
"@avocado/traits" "^2.0.0"
@ -16,15 +16,15 @@
"@avocado/core@2.0.0", "@avocado/core@^2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@avocado%2fcore/-/core-2.0.0.tgz#69c736d6a1d8b25d0cc57f07fabdef3f467a5636"
integrity sha512-XqLqDST/gLCbyBNQuZnzj8WN05aEgko8Kh/45pN0cSNA5DRMgkZSynBZh0NMEtiYfC5Od6v6y7FF5uvuzh4+gg==
resolved "http://npm.cha0sdev/@avocado%2fcore/-/core-2.0.0.tgz#2debb82ce9947a22575032af6719531278f6f98a"
integrity sha512-XGikLesJP42xgTOFy0gxPCNp0NnE9NK7xCHNAcs2tU4XOxNPTYv5cPp1FP21cHdf2b6joiNmFnWNBg1mvF0AJA==
dependencies:
debug "4.3.1"
"@avocado/entity@^2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@avocado%2fentity/-/entity-2.0.0.tgz#d758beff5ad6e1069e03529ffce64f04923a0be0"
integrity sha512-ujDS8uWx1aYzmkaq+MPutB4PCtTEH/6LptH5rG4F0YIJHaPKNhl3vaYvRivhqu3FPtT8RFS8DqYr4GvWXm4bGA==
resolved "http://npm.cha0sdev/@avocado%2fentity/-/entity-2.0.0.tgz#e6d8d4f1e2d8b822dada80df5e4b8926b364df31"
integrity sha512-vAmZHbTXm2MwLOLxZf19llTFFwDUlC8nqaLm9FSwZlOhOVr5e2t8YJcjbisjWfGkNvTd6m9AluPj5vHCKjV+ww==
dependencies:
"@avocado/behavior" "2.0.0"
"@avocado/core" "2.0.0"
@ -42,8 +42,8 @@
"@avocado/graphics@2.0.0", "@avocado/graphics@^2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@avocado%2fgraphics/-/graphics-2.0.0.tgz#340660152bddd49a03da787924f431d639f639d3"
integrity sha512-NRj2iQBafrXkhn+4IQnu0uxUQrapGp8OCtwde6Qp4xdbQLlpkndaENLKg6/Q7qxt05yMv8XtI81V7yX3xzsAoQ==
resolved "http://npm.cha0sdev/@avocado%2fgraphics/-/graphics-2.0.0.tgz#2dc43f9a825fa1f9a72064d5e83630185f974e94"
integrity sha512-BsB+MPAhvuLdSSibvU+oLOcBXnUgEJAmaoXOLTIppDQh7ACo+Hqamib+2Zcx75VcmwleEeOIVDtnQJzKLYVInw==
dependencies:
"@avocado/core" "2.0.0"
"@avocado/input" "2.0.0"
@ -66,8 +66,8 @@
"@avocado/input@2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@avocado%2finput/-/input-2.0.0.tgz#bdd839a2c977c3414fd3590a14dde2ef1cb8067e"
integrity sha512-KtGGH82WLdT0699+/Fw9bhimIOsZEhE9hhr5OuXxWDp8JVVzrrD/1jytC6Ue3012Na0rVKtdkMGewoAB0Fv0GQ==
resolved "http://npm.cha0sdev/@avocado%2finput/-/input-2.0.0.tgz#c73ebd8f821663e5c30c572e4efbe7d34bb1bb7f"
integrity sha512-lrv+bsBtsfV9ps3QNfNbcnPXOuzu99XZqtbDB/NK8umGKQogKQg7Ix9tiXbciHibIfTejiG5mapHr+SVbHrO5Q==
dependencies:
"@latus/core" "2.0.0"
"@latus/socket" "2.0.0"
@ -75,8 +75,8 @@
"@avocado/math@2.0.0", "@avocado/math@^2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@avocado%2fmath/-/math-2.0.0.tgz#9e3fb073d93799f8f86a1abbaaabd5021fc753ad"
integrity sha512-vIgwR0p7I9jnXqUr/6cD9i2k/Z8GJuWqNIxksmPF8Odw1SON/4ItbLYk3D5+Z/KnDOeIa2N2Db9IoymcOofBgw==
resolved "http://npm.cha0sdev/@avocado%2fmath/-/math-2.0.0.tgz#9b4c05098f287ebe814b6ef954ac0ab4140c51dc"
integrity sha512-KEX7fkzxUtiXNlSYEOdp/Juv0YFhdvPExgW3zI61kBDZvJr3fNJWJ9slrf1ikSGFWrtcH2tUESlTToRHPLd2Qg==
dependencies:
"@avocado/core" "2.0.0"
"@latus/core" "^2.0.0"
@ -85,8 +85,8 @@
"@avocado/resource@2.0.0", "@avocado/resource@^2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@avocado%2fresource/-/resource-2.0.0.tgz#9eadafaf1ce7a8d6308c59bfa92290830cf91e30"
integrity sha512-85osPtux7MZ+9dAFGrLKzIv1vAPuSBfxEwPZOvKaHMSBa6mnzysC7c2FbU4zfSioDl8ozqknE9ZYZB1bjdw0Hg==
resolved "http://npm.cha0sdev/@avocado%2fresource/-/resource-2.0.0.tgz#12b9b1ee4bcb43ede8ba2172f16c82dc2f115d0f"
integrity sha512-qNTzFfkZMwYX+IEl64Del4uSfQKpWm6kR1KtlOWCbU5nc3sH5d9U+nFfbmGAJArEhC9lo2s2lQITvgkJ7D1VuQ==
dependencies:
"@avocado/core" "2.0.0"
"@latus/core" "2.0.0"
@ -96,8 +96,8 @@
"@avocado/s13n@2.0.0", "@avocado/s13n@^2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@avocado%2fs13n/-/s13n-2.0.0.tgz#2b0ea781520f5c41dcd6c3bfc1a6cd52ce181c69"
integrity sha512-TkxxmQQRS7NbpvNxLQ1RME+7vIpGm198sPSNcDfBLMwcQ2Icl8jTx5HFaIaCLh6XezFN/MhQzDjZ62XVqxWEeg==
resolved "http://npm.cha0sdev/@avocado%2fs13n/-/s13n-2.0.0.tgz#3aff3c15a6e8ef2a405e7b9ff45abd94e63f064d"
integrity sha512-UAmde98frU3TWlK0yIvHYM/PX+dpyx4O+a5QWQakm7ef9vZomPwyN/2Z87ArliOZILO3qhvusFqiLusUf8z7HA==
dependencies:
"@avocado/resource" "^2.0.0"
"@latus/core" "2.0.0"
@ -107,8 +107,8 @@
"@avocado/timing@2.0.0", "@avocado/timing@^2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@avocado%2ftiming/-/timing-2.0.0.tgz#9c7ddb24d9f99822a59b6927fcaa09e8614785b0"
integrity sha512-zlLLjrKvYzCRyvtYWDJniM0AtLzmpOxWeEL7U8uPbA9n1fDEdAv90rhpw8rdFOAtGBNi6q2YxcaIJH0vQzs5Iw==
resolved "http://npm.cha0sdev/@avocado%2ftiming/-/timing-2.0.0.tgz#6eec2b614387a199b78dc15b833f2057a6032db9"
integrity sha512-aWpsLrHLrsQnWIUmYMOrJlFg/xwZFecLDU4i9WHwf6FW41SgjjxI8eeVPiiteGt2IUmGcRemuSV9PSBuazL76w==
dependencies:
"@avocado/core" "2.0.0"
"@avocado/graphics" "2.0.0"
@ -122,8 +122,8 @@
"@avocado/traits@^2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@avocado%2ftraits/-/traits-2.0.0.tgz#369ce54e55b6a32c1591efcf31e19785f827b943"
integrity sha512-0+CatzN3YFm1HBUQ1n0a2j2/cmtNo6hjNtjiJINFkqEUmpwGnoub+yB4x7HW837IjnqvLeD53Mu6YUxC9nOstQ==
resolved "http://npm.cha0sdev/@avocado%2ftraits/-/traits-2.0.0.tgz#7aa7c5504e627967189343a58248c123f80e44a4"
integrity sha512-7hoiN/MQmBGeGPg8wtg5erXxS5053IGsRyM0qdbnhkIY0tWLBJ2NjREqkDfC2avsJAc4yK5+x+l2PFpLJivxww==
dependencies:
"@avocado/core" "^2.0.0"
"@avocado/resource" "^2.0.0"
@ -1032,8 +1032,8 @@
"@latus/core@2.0.0", "@latus/core@^2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@latus%2fcore/-/core-2.0.0.tgz#1f001c8deead6c58e51a32aa4cedee7f26403a58"
integrity sha512-0Co6k1MZE5dBwwa8IMtl2Szk69KdvmMBvLQh45JLnGPhSodQ06+carStEn9r8dr+RvaDZpNRQohyxQFZV5ioJw==
resolved "http://npm.cha0sdev/@latus%2fcore/-/core-2.0.0.tgz#24e8313875563b729f32c7d98fb394b116f2adba"
integrity sha512-CKEb7xoyBXwZHlUmPWUU/egXuzpKkIZFVioKfnDTHNydDKaKG0TW0ugg6EX6Le81CFt9RovMALKJm2s4A7UiVQ==
dependencies:
debug "4.3.1"
js-yaml "3.14.0"
@ -1044,8 +1044,8 @@
"@latus/http@2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@latus%2fhttp/-/http-2.0.0.tgz#887a144f8029291818ed85fbe1a6462a2e01740f"
integrity sha512-f0tlfVq5Yp0ioYS/cY24odm4N3jJaqeq/gNshppNKzYf+k9/HzM+8khGBbol+1/6OZLq3zVDoZqYNJRQUci3Rg==
resolved "http://npm.cha0sdev/@latus%2fhttp/-/http-2.0.0.tgz#3589fcb76a5e7a4763b45853d696289b3ce478b3"
integrity sha512-jWhJa93uLksNEEQhFKq36de5jHCKoQZBel57DIxaTk+jAIfzPO+kmWlTaq/wGCiCxlnHLjvTuMGOiDABVew4aQ==
dependencies:
"@latus/core" "2.0.0"
"@neutrinojs/web" "^9.1.0"
@ -1064,8 +1064,8 @@
"@latus/react@2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@latus%2freact/-/react-2.0.0.tgz#09f4699218a73c19ff0c7c299a6c48f053316512"
integrity sha512-HZN9THHkZSWUwDDh8S2k+FiLfrmRbT4eUTs+ZJsQuWCdS6NQpBoTp2kjGe5wG/h0HoHwFfh+tjs728BXZXlLNQ==
resolved "http://npm.cha0sdev/@latus%2freact/-/react-2.0.0.tgz#25fd38202ff83a5ceb9ab0574a45a255db96905a"
integrity sha512-Yy7x2BdDlNe7njxAZONx1fI2MhebnlLjZfT2mz9JkoGNfaFWdDCLdaouYn8WH5u7ihMeGcSCVTizFwr4rZj9UQ==
dependencies:
"@hot-loader/react-dom" "^17.0.1"
"@neutrinojs/react" "^9.4.0"
@ -1079,8 +1079,8 @@
"@latus/socket@2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@latus%2fsocket/-/socket-2.0.0.tgz#8128b1244b3458ac0dfcd4d6d1256cd741b0e73e"
integrity sha512-bH6WZZ2C0FiIZEsJuJQk2M9iHBPzAZZ8gBKB3XYWl+pwb535bHLnoMCkbV3LZhMiguZnIjUt7mSYZAGybvOvNw==
resolved "http://npm.cha0sdev/@latus%2fsocket/-/socket-2.0.0.tgz#ba0d9cc2099474ba1dbba2b4e27e92a6fc271087"
integrity sha512-ZDOxbRwoiEO2E/QeS4GjO1950oVeH+i4Gw4ep6K/TPBbhkaiDrp8MpZyUxM6hDDEDf1Q6V1gAH+4FLPsUncdYw==
dependencies:
"@latus/core" "2.0.0"
"@latus/http" "2.0.0"

View File

@ -20,7 +20,7 @@ export default class JsonResource extends Resource {
const {extends: uri} = json;
const resource = new this();
resource.uri = uri;
resource.load(await this.extendJson(json));
await resource.load(await this.extendJson(json));
return resource;
}

View File

@ -9,15 +9,15 @@ Resource.root = 'test/fixtures';
JsonResource.root = 'test/fixtures';
class ResourceSubclass extends Resource {
constructor(buffer) {
super();
load(buffer) {
super.load(buffer);
this.buffer = buffer;
}
}
class JsonResourceSubclass extends JsonResource {
constructor(json) {
super();
load(json) {
super.load(json);
this.json = json;
}
}

View File

@ -1,10 +1,16 @@
import {resource} from '@avocado/resource';
import {Class, compose, EventEmitter} from '@latus/core';
export default class ReceiverSynchronizer {
const decorate = compose(
EventEmitter,
);
export default class ReceiverSynchronizer extends decorate(Class) {
#synchronized = {};
constructor(latus) {
super();
this.latus = latus;
}
@ -18,12 +24,19 @@ export default class ReceiverSynchronizer {
this.#synchronized[type] = {};
}
const json = packet.data.spec;
if (this.#synchronized[type][id]) {
this.#synchronized[type][id].extendAndLoad(json);
try {
if (this.#synchronized[type][id]) {
this.#synchronized[type][id].extendAndLoad(json);
}
else {
this.#synchronized[type][id] = await Resource.load(json);
}
}
else {
this.#synchronized[type][id] = await Resource.load(json);
catch (error) {
// eslint-disable-next-line no-console
console.error(error);
}
this.emit('created', type, this.#synchronized[type][id], id);
break;
}
case 'destroy': {

View File

@ -83,8 +83,9 @@ export default class SenderSynchronizer {
}
this.#queuedPackets = [];
if (socket && this.#nextSyncPackets.length > 0) {
await socket.send(['Bundle', this.#nextSyncPackets]);
const nextSyncPackets = this.#nextSyncPackets;
this.#nextSyncPackets = [];
await socket.send(['Bundle', nextSyncPackets]);
}
}

View File

@ -4,15 +4,15 @@
"@avocado/core@2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@avocado%2fcore/-/core-2.0.0.tgz#69c736d6a1d8b25d0cc57f07fabdef3f467a5636"
integrity sha512-XqLqDST/gLCbyBNQuZnzj8WN05aEgko8Kh/45pN0cSNA5DRMgkZSynBZh0NMEtiYfC5Od6v6y7FF5uvuzh4+gg==
resolved "http://npm.cha0sdev/@avocado%2fcore/-/core-2.0.0.tgz#2debb82ce9947a22575032af6719531278f6f98a"
integrity sha512-XGikLesJP42xgTOFy0gxPCNp0NnE9NK7xCHNAcs2tU4XOxNPTYv5cPp1FP21cHdf2b6joiNmFnWNBg1mvF0AJA==
dependencies:
debug "4.3.1"
"@avocado/resource@^2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@avocado%2fresource/-/resource-2.0.0.tgz#9eadafaf1ce7a8d6308c59bfa92290830cf91e30"
integrity sha512-85osPtux7MZ+9dAFGrLKzIv1vAPuSBfxEwPZOvKaHMSBa6mnzysC7c2FbU4zfSioDl8ozqknE9ZYZB1bjdw0Hg==
resolved "http://npm.cha0sdev/@avocado%2fresource/-/resource-2.0.0.tgz#12b9b1ee4bcb43ede8ba2172f16c82dc2f115d0f"
integrity sha512-qNTzFfkZMwYX+IEl64Del4uSfQKpWm6kR1KtlOWCbU5nc3sH5d9U+nFfbmGAJArEhC9lo2s2lQITvgkJ7D1VuQ==
dependencies:
"@avocado/core" "2.0.0"
"@latus/core" "2.0.0"
@ -921,8 +921,8 @@
"@latus/core@2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@latus%2fcore/-/core-2.0.0.tgz#1f001c8deead6c58e51a32aa4cedee7f26403a58"
integrity sha512-0Co6k1MZE5dBwwa8IMtl2Szk69KdvmMBvLQh45JLnGPhSodQ06+carStEn9r8dr+RvaDZpNRQohyxQFZV5ioJw==
resolved "http://npm.cha0sdev/@latus%2fcore/-/core-2.0.0.tgz#24e8313875563b729f32c7d98fb394b116f2adba"
integrity sha512-CKEb7xoyBXwZHlUmPWUU/egXuzpKkIZFVioKfnDTHNydDKaKG0TW0ugg6EX6Le81CFt9RovMALKJm2s4A7UiVQ==
dependencies:
debug "4.3.1"
js-yaml "3.14.0"
@ -933,8 +933,8 @@
"@latus/http@2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@latus%2fhttp/-/http-2.0.0.tgz#887a144f8029291818ed85fbe1a6462a2e01740f"
integrity sha512-f0tlfVq5Yp0ioYS/cY24odm4N3jJaqeq/gNshppNKzYf+k9/HzM+8khGBbol+1/6OZLq3zVDoZqYNJRQUci3Rg==
resolved "http://npm.cha0sdev/@latus%2fhttp/-/http-2.0.0.tgz#3589fcb76a5e7a4763b45853d696289b3ce478b3"
integrity sha512-jWhJa93uLksNEEQhFKq36de5jHCKoQZBel57DIxaTk+jAIfzPO+kmWlTaq/wGCiCxlnHLjvTuMGOiDABVew4aQ==
dependencies:
"@latus/core" "2.0.0"
"@neutrinojs/web" "^9.1.0"
@ -953,8 +953,8 @@
"@latus/react@2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@latus%2freact/-/react-2.0.0.tgz#09f4699218a73c19ff0c7c299a6c48f053316512"
integrity sha512-HZN9THHkZSWUwDDh8S2k+FiLfrmRbT4eUTs+ZJsQuWCdS6NQpBoTp2kjGe5wG/h0HoHwFfh+tjs728BXZXlLNQ==
resolved "http://npm.cha0sdev/@latus%2freact/-/react-2.0.0.tgz#25fd38202ff83a5ceb9ab0574a45a255db96905a"
integrity sha512-Yy7x2BdDlNe7njxAZONx1fI2MhebnlLjZfT2mz9JkoGNfaFWdDCLdaouYn8WH5u7ihMeGcSCVTizFwr4rZj9UQ==
dependencies:
"@hot-loader/react-dom" "^17.0.1"
"@neutrinojs/react" "^9.4.0"
@ -968,8 +968,8 @@
"@latus/socket@2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@latus%2fsocket/-/socket-2.0.0.tgz#8128b1244b3458ac0dfcd4d6d1256cd741b0e73e"
integrity sha512-bH6WZZ2C0FiIZEsJuJQk2M9iHBPzAZZ8gBKB3XYWl+pwb535bHLnoMCkbV3LZhMiguZnIjUt7mSYZAGybvOvNw==
resolved "http://npm.cha0sdev/@latus%2fsocket/-/socket-2.0.0.tgz#ba0d9cc2099474ba1dbba2b4e27e92a6fc271087"
integrity sha512-ZDOxbRwoiEO2E/QeS4GjO1950oVeH+i4Gw4ep6K/TPBbhkaiDrp8MpZyUxM6hDDEDf1Q6V1gAH+4FLPsUncdYw==
dependencies:
"@latus/core" "2.0.0"
"@latus/http" "2.0.0"

View File

@ -3,12 +3,7 @@ import {Trait} from '@avocado/traits';
export default (latus) => class Audible extends Trait {
#sounds;
constructor(json) {
super(json);
this.#sounds = json.sounds || {};
}
#sounds = {};
static behaviorTypes() {
return {
@ -69,6 +64,13 @@ export default (latus) => class Audible extends Trait {
return extended;
}
load(json) {
super.load(json);
if (json.sounds) {
this.#sounds = json.sounds;
}
}
methods() {
return {

View File

@ -4,15 +4,15 @@
"@avocado/core@2.0.0", "@avocado/core@^2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@avocado%2fcore/-/core-2.0.0.tgz#69c736d6a1d8b25d0cc57f07fabdef3f467a5636"
integrity sha512-XqLqDST/gLCbyBNQuZnzj8WN05aEgko8Kh/45pN0cSNA5DRMgkZSynBZh0NMEtiYfC5Od6v6y7FF5uvuzh4+gg==
resolved "http://npm.cha0sdev/@avocado%2fcore/-/core-2.0.0.tgz#2debb82ce9947a22575032af6719531278f6f98a"
integrity sha512-XGikLesJP42xgTOFy0gxPCNp0NnE9NK7xCHNAcs2tU4XOxNPTYv5cPp1FP21cHdf2b6joiNmFnWNBg1mvF0AJA==
dependencies:
debug "4.3.1"
"@avocado/resource@^2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@avocado%2fresource/-/resource-2.0.0.tgz#9eadafaf1ce7a8d6308c59bfa92290830cf91e30"
integrity sha512-85osPtux7MZ+9dAFGrLKzIv1vAPuSBfxEwPZOvKaHMSBa6mnzysC7c2FbU4zfSioDl8ozqknE9ZYZB1bjdw0Hg==
resolved "http://npm.cha0sdev/@avocado%2fresource/-/resource-2.0.0.tgz#12b9b1ee4bcb43ede8ba2172f16c82dc2f115d0f"
integrity sha512-qNTzFfkZMwYX+IEl64Del4uSfQKpWm6kR1KtlOWCbU5nc3sH5d9U+nFfbmGAJArEhC9lo2s2lQITvgkJ7D1VuQ==
dependencies:
"@avocado/core" "2.0.0"
"@latus/core" "2.0.0"
@ -22,8 +22,8 @@
"@avocado/s13n@^2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@avocado%2fs13n/-/s13n-2.0.0.tgz#2b0ea781520f5c41dcd6c3bfc1a6cd52ce181c69"
integrity sha512-TkxxmQQRS7NbpvNxLQ1RME+7vIpGm198sPSNcDfBLMwcQ2Icl8jTx5HFaIaCLh6XezFN/MhQzDjZ62XVqxWEeg==
resolved "http://npm.cha0sdev/@avocado%2fs13n/-/s13n-2.0.0.tgz#3aff3c15a6e8ef2a405e7b9ff45abd94e63f064d"
integrity sha512-UAmde98frU3TWlK0yIvHYM/PX+dpyx4O+a5QWQakm7ef9vZomPwyN/2Z87ArliOZILO3qhvusFqiLusUf8z7HA==
dependencies:
"@avocado/resource" "^2.0.0"
"@latus/core" "2.0.0"
@ -33,8 +33,8 @@
"@avocado/traits@^2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@avocado%2ftraits/-/traits-2.0.0.tgz#369ce54e55b6a32c1591efcf31e19785f827b943"
integrity sha512-0+CatzN3YFm1HBUQ1n0a2j2/cmtNo6hjNtjiJINFkqEUmpwGnoub+yB4x7HW837IjnqvLeD53Mu6YUxC9nOstQ==
resolved "http://npm.cha0sdev/@avocado%2ftraits/-/traits-2.0.0.tgz#7aa7c5504e627967189343a58248c123f80e44a4"
integrity sha512-7hoiN/MQmBGeGPg8wtg5erXxS5053IGsRyM0qdbnhkIY0tWLBJ2NjREqkDfC2avsJAc4yK5+x+l2PFpLJivxww==
dependencies:
"@avocado/core" "^2.0.0"
"@avocado/resource" "^2.0.0"
@ -943,8 +943,8 @@
"@latus/core@2.0.0", "@latus/core@^2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@latus%2fcore/-/core-2.0.0.tgz#1f001c8deead6c58e51a32aa4cedee7f26403a58"
integrity sha512-0Co6k1MZE5dBwwa8IMtl2Szk69KdvmMBvLQh45JLnGPhSodQ06+carStEn9r8dr+RvaDZpNRQohyxQFZV5ioJw==
resolved "http://npm.cha0sdev/@latus%2fcore/-/core-2.0.0.tgz#24e8313875563b729f32c7d98fb394b116f2adba"
integrity sha512-CKEb7xoyBXwZHlUmPWUU/egXuzpKkIZFVioKfnDTHNydDKaKG0TW0ugg6EX6Le81CFt9RovMALKJm2s4A7UiVQ==
dependencies:
debug "4.3.1"
js-yaml "3.14.0"
@ -955,8 +955,8 @@
"@latus/http@2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@latus%2fhttp/-/http-2.0.0.tgz#887a144f8029291818ed85fbe1a6462a2e01740f"
integrity sha512-f0tlfVq5Yp0ioYS/cY24odm4N3jJaqeq/gNshppNKzYf+k9/HzM+8khGBbol+1/6OZLq3zVDoZqYNJRQUci3Rg==
resolved "http://npm.cha0sdev/@latus%2fhttp/-/http-2.0.0.tgz#3589fcb76a5e7a4763b45853d696289b3ce478b3"
integrity sha512-jWhJa93uLksNEEQhFKq36de5jHCKoQZBel57DIxaTk+jAIfzPO+kmWlTaq/wGCiCxlnHLjvTuMGOiDABVew4aQ==
dependencies:
"@latus/core" "2.0.0"
"@neutrinojs/web" "^9.1.0"
@ -975,8 +975,8 @@
"@latus/react@2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@latus%2freact/-/react-2.0.0.tgz#09f4699218a73c19ff0c7c299a6c48f053316512"
integrity sha512-HZN9THHkZSWUwDDh8S2k+FiLfrmRbT4eUTs+ZJsQuWCdS6NQpBoTp2kjGe5wG/h0HoHwFfh+tjs728BXZXlLNQ==
resolved "http://npm.cha0sdev/@latus%2freact/-/react-2.0.0.tgz#25fd38202ff83a5ceb9ab0574a45a255db96905a"
integrity sha512-Yy7x2BdDlNe7njxAZONx1fI2MhebnlLjZfT2mz9JkoGNfaFWdDCLdaouYn8WH5u7ihMeGcSCVTizFwr4rZj9UQ==
dependencies:
"@hot-loader/react-dom" "^17.0.1"
"@neutrinojs/react" "^9.4.0"
@ -990,8 +990,8 @@
"@latus/socket@2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@latus%2fsocket/-/socket-2.0.0.tgz#8128b1244b3458ac0dfcd4d6d1256cd741b0e73e"
integrity sha512-bH6WZZ2C0FiIZEsJuJQk2M9iHBPzAZZ8gBKB3XYWl+pwb535bHLnoMCkbV3LZhMiguZnIjUt7mSYZAGybvOvNw==
resolved "http://npm.cha0sdev/@latus%2fsocket/-/socket-2.0.0.tgz#ba0d9cc2099474ba1dbba2b4e27e92a6fc271087"
integrity sha512-ZDOxbRwoiEO2E/QeS4GjO1950oVeH+i4Gw4ep6K/TPBbhkaiDrp8MpZyUxM6hDDEDf1Q6V1gAH+4FLPsUncdYw==
dependencies:
"@latus/core" "2.0.0"
"@latus/http" "2.0.0"

View File

@ -24,23 +24,13 @@ export default (latus) => class Animated extends decorate(Trait) {
#cachedAabbs = {};
#currentAnimation;
#currentAnimation = '';
constructor(json) {
super(json);
if (json.animations) {
Object.values(json.animations).forEach((animation) => {
// eslint-disable-next-line no-param-reassign
animation.direction = this.entity.direction;
});
Object.entries(json.animationViews).forEach(([key, animationView]) => {
// eslint-disable-next-line no-param-reassign
animationView.position = this.offsetFor(key);
});
this.#animations = json.animations;
this.#animationViews = json.animationViews;
}
this.#currentAnimation = this.state.currentAnimation;
constructor() {
super();
({
currentAnimation: this.#currentAnimation,
} = this.constructor.defaultParams());
}
acceptPacket(packet) {
@ -225,6 +215,23 @@ export default (latus) => class Animated extends decorate(Trait) {
};
}
load(json) {
super.load(json);
if (json.animations) {
Object.values(json.animations).forEach((animation) => {
// eslint-disable-next-line no-param-reassign
animation.direction = this.entity.direction;
});
Object.entries(json.animationViews).forEach(([key, animationView]) => {
// eslint-disable-next-line no-param-reassign
animationView.position = this.offsetFor(key);
});
this.#animations = json.animations;
this.#animationViews = json.animationViews;
}
this.#currentAnimation = this.state.currentAnimation;
}
offsetFor(key) {
if (!(key in this.params.animations) || !this.params.animations[key].offset) {
return [0, 0];
@ -243,7 +250,7 @@ export default (latus) => class Animated extends decorate(Trait) {
},
]];
}
return undefined;
return [];
}
setSpriteScale() {

View File

@ -4,15 +4,15 @@
"@avocado/core@2.0.0", "@avocado/core@^2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@avocado%2fcore/-/core-2.0.0.tgz#69c736d6a1d8b25d0cc57f07fabdef3f467a5636"
integrity sha512-XqLqDST/gLCbyBNQuZnzj8WN05aEgko8Kh/45pN0cSNA5DRMgkZSynBZh0NMEtiYfC5Od6v6y7FF5uvuzh4+gg==
resolved "http://npm.cha0sdev/@avocado%2fcore/-/core-2.0.0.tgz#2debb82ce9947a22575032af6719531278f6f98a"
integrity sha512-XGikLesJP42xgTOFy0gxPCNp0NnE9NK7xCHNAcs2tU4XOxNPTYv5cPp1FP21cHdf2b6joiNmFnWNBg1mvF0AJA==
dependencies:
debug "4.3.1"
"@avocado/graphics@2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@avocado%2fgraphics/-/graphics-2.0.0.tgz#340660152bddd49a03da787924f431d639f639d3"
integrity sha512-NRj2iQBafrXkhn+4IQnu0uxUQrapGp8OCtwde6Qp4xdbQLlpkndaENLKg6/Q7qxt05yMv8XtI81V7yX3xzsAoQ==
resolved "http://npm.cha0sdev/@avocado%2fgraphics/-/graphics-2.0.0.tgz#2dc43f9a825fa1f9a72064d5e83630185f974e94"
integrity sha512-BsB+MPAhvuLdSSibvU+oLOcBXnUgEJAmaoXOLTIppDQh7ACo+Hqamib+2Zcx75VcmwleEeOIVDtnQJzKLYVInw==
dependencies:
"@avocado/core" "2.0.0"
"@avocado/input" "2.0.0"
@ -35,8 +35,8 @@
"@avocado/input@2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@avocado%2finput/-/input-2.0.0.tgz#bdd839a2c977c3414fd3590a14dde2ef1cb8067e"
integrity sha512-KtGGH82WLdT0699+/Fw9bhimIOsZEhE9hhr5OuXxWDp8JVVzrrD/1jytC6Ue3012Na0rVKtdkMGewoAB0Fv0GQ==
resolved "http://npm.cha0sdev/@avocado%2finput/-/input-2.0.0.tgz#c73ebd8f821663e5c30c572e4efbe7d34bb1bb7f"
integrity sha512-lrv+bsBtsfV9ps3QNfNbcnPXOuzu99XZqtbDB/NK8umGKQogKQg7Ix9tiXbciHibIfTejiG5mapHr+SVbHrO5Q==
dependencies:
"@latus/core" "2.0.0"
"@latus/socket" "2.0.0"
@ -44,8 +44,8 @@
"@avocado/math@2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@avocado%2fmath/-/math-2.0.0.tgz#9e3fb073d93799f8f86a1abbaaabd5021fc753ad"
integrity sha512-vIgwR0p7I9jnXqUr/6cD9i2k/Z8GJuWqNIxksmPF8Odw1SON/4ItbLYk3D5+Z/KnDOeIa2N2Db9IoymcOofBgw==
resolved "http://npm.cha0sdev/@avocado%2fmath/-/math-2.0.0.tgz#9b4c05098f287ebe814b6ef954ac0ab4140c51dc"
integrity sha512-KEX7fkzxUtiXNlSYEOdp/Juv0YFhdvPExgW3zI61kBDZvJr3fNJWJ9slrf1ikSGFWrtcH2tUESlTToRHPLd2Qg==
dependencies:
"@avocado/core" "2.0.0"
"@latus/core" "^2.0.0"
@ -54,8 +54,8 @@
"@avocado/resource@2.0.0", "@avocado/resource@^2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@avocado%2fresource/-/resource-2.0.0.tgz#9eadafaf1ce7a8d6308c59bfa92290830cf91e30"
integrity sha512-85osPtux7MZ+9dAFGrLKzIv1vAPuSBfxEwPZOvKaHMSBa6mnzysC7c2FbU4zfSioDl8ozqknE9ZYZB1bjdw0Hg==
resolved "http://npm.cha0sdev/@avocado%2fresource/-/resource-2.0.0.tgz#12b9b1ee4bcb43ede8ba2172f16c82dc2f115d0f"
integrity sha512-qNTzFfkZMwYX+IEl64Del4uSfQKpWm6kR1KtlOWCbU5nc3sH5d9U+nFfbmGAJArEhC9lo2s2lQITvgkJ7D1VuQ==
dependencies:
"@avocado/core" "2.0.0"
"@latus/core" "2.0.0"
@ -65,8 +65,8 @@
"@avocado/s13n@^2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@avocado%2fs13n/-/s13n-2.0.0.tgz#2b0ea781520f5c41dcd6c3bfc1a6cd52ce181c69"
integrity sha512-TkxxmQQRS7NbpvNxLQ1RME+7vIpGm198sPSNcDfBLMwcQ2Icl8jTx5HFaIaCLh6XezFN/MhQzDjZ62XVqxWEeg==
resolved "http://npm.cha0sdev/@avocado%2fs13n/-/s13n-2.0.0.tgz#3aff3c15a6e8ef2a405e7b9ff45abd94e63f064d"
integrity sha512-UAmde98frU3TWlK0yIvHYM/PX+dpyx4O+a5QWQakm7ef9vZomPwyN/2Z87ArliOZILO3qhvusFqiLusUf8z7HA==
dependencies:
"@avocado/resource" "^2.0.0"
"@latus/core" "2.0.0"
@ -76,8 +76,8 @@
"@avocado/traits@^2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@avocado%2ftraits/-/traits-2.0.0.tgz#369ce54e55b6a32c1591efcf31e19785f827b943"
integrity sha512-0+CatzN3YFm1HBUQ1n0a2j2/cmtNo6hjNtjiJINFkqEUmpwGnoub+yB4x7HW837IjnqvLeD53Mu6YUxC9nOstQ==
resolved "http://npm.cha0sdev/@avocado%2ftraits/-/traits-2.0.0.tgz#7aa7c5504e627967189343a58248c123f80e44a4"
integrity sha512-7hoiN/MQmBGeGPg8wtg5erXxS5053IGsRyM0qdbnhkIY0tWLBJ2NjREqkDfC2avsJAc4yK5+x+l2PFpLJivxww==
dependencies:
"@avocado/core" "^2.0.0"
"@avocado/resource" "^2.0.0"
@ -986,8 +986,8 @@
"@latus/core@2.0.0", "@latus/core@^2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@latus%2fcore/-/core-2.0.0.tgz#1f001c8deead6c58e51a32aa4cedee7f26403a58"
integrity sha512-0Co6k1MZE5dBwwa8IMtl2Szk69KdvmMBvLQh45JLnGPhSodQ06+carStEn9r8dr+RvaDZpNRQohyxQFZV5ioJw==
resolved "http://npm.cha0sdev/@latus%2fcore/-/core-2.0.0.tgz#24e8313875563b729f32c7d98fb394b116f2adba"
integrity sha512-CKEb7xoyBXwZHlUmPWUU/egXuzpKkIZFVioKfnDTHNydDKaKG0TW0ugg6EX6Le81CFt9RovMALKJm2s4A7UiVQ==
dependencies:
debug "4.3.1"
js-yaml "3.14.0"
@ -998,8 +998,8 @@
"@latus/http@2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@latus%2fhttp/-/http-2.0.0.tgz#887a144f8029291818ed85fbe1a6462a2e01740f"
integrity sha512-f0tlfVq5Yp0ioYS/cY24odm4N3jJaqeq/gNshppNKzYf+k9/HzM+8khGBbol+1/6OZLq3zVDoZqYNJRQUci3Rg==
resolved "http://npm.cha0sdev/@latus%2fhttp/-/http-2.0.0.tgz#3589fcb76a5e7a4763b45853d696289b3ce478b3"
integrity sha512-jWhJa93uLksNEEQhFKq36de5jHCKoQZBel57DIxaTk+jAIfzPO+kmWlTaq/wGCiCxlnHLjvTuMGOiDABVew4aQ==
dependencies:
"@latus/core" "2.0.0"
"@neutrinojs/web" "^9.1.0"
@ -1018,8 +1018,8 @@
"@latus/react@2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@latus%2freact/-/react-2.0.0.tgz#09f4699218a73c19ff0c7c299a6c48f053316512"
integrity sha512-HZN9THHkZSWUwDDh8S2k+FiLfrmRbT4eUTs+ZJsQuWCdS6NQpBoTp2kjGe5wG/h0HoHwFfh+tjs728BXZXlLNQ==
resolved "http://npm.cha0sdev/@latus%2freact/-/react-2.0.0.tgz#25fd38202ff83a5ceb9ab0574a45a255db96905a"
integrity sha512-Yy7x2BdDlNe7njxAZONx1fI2MhebnlLjZfT2mz9JkoGNfaFWdDCLdaouYn8WH5u7ihMeGcSCVTizFwr4rZj9UQ==
dependencies:
"@hot-loader/react-dom" "^17.0.1"
"@neutrinojs/react" "^9.4.0"
@ -1033,8 +1033,8 @@
"@latus/socket@2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@latus%2fsocket/-/socket-2.0.0.tgz#8128b1244b3458ac0dfcd4d6d1256cd741b0e73e"
integrity sha512-bH6WZZ2C0FiIZEsJuJQk2M9iHBPzAZZ8gBKB3XYWl+pwb535bHLnoMCkbV3LZhMiguZnIjUt7mSYZAGybvOvNw==
resolved "http://npm.cha0sdev/@latus%2fsocket/-/socket-2.0.0.tgz#ba0d9cc2099474ba1dbba2b4e27e92a6fc271087"
integrity sha512-ZDOxbRwoiEO2E/QeS4GjO1950oVeH+i4Gw4ep6K/TPBbhkaiDrp8MpZyUxM6hDDEDf1Q6V1gAH+4FLPsUncdYw==
dependencies:
"@latus/core" "2.0.0"
"@latus/http" "2.0.0"

View File

@ -6,7 +6,7 @@ export default (latus) => class RoomUpdateLayers extends SynchronizedUpdatePacke
static packData(data) {
const {fromType: {Bundle}} = packets(latus);
// eslint-disable-next-line no-param-reassign
data.layersPackets = Bundle.bundle(data.layerPackets);
data.layersPackets = Bundle.bundle(data.layersPackets);
return data;
}

View File

@ -20,6 +20,9 @@ export default (latus) => class Layer extends decorate(JsonResource) {
super();
this.tileEntities = {};
this.tileGeometry = [];
const {fromResourceType: {EntityList, Tiles}} = resource(latus);
this.setEntityList(new EntityList());
this.setTiles(new Tiles());
}
acceptPacket(packet) {
@ -110,7 +113,7 @@ export default (latus) => class Layer extends decorate(JsonResource) {
extended.entityList = await EntityList.load(extended.entities);
}
if (extended.tilesetUri) {
extended.tileset = await Tileset.load(extended.tilesetUri);
extended.tileset = await Tileset.load({extends: extended.tilesetUri});
}
return extended;
}
@ -223,7 +226,6 @@ export default (latus) => class Layer extends decorate(JsonResource) {
this.entityList = entityList;
this.entityList.on('entityAdded', this.onEntityAddedToLayer, this);
this.entityList.on('entityRemoved', this.onEntityRemovedFromLayer, this);
this.tiles.on('dataChanged', this.onTileDataChanged, this);
}
setTileAt(position, tile) {

View File

@ -44,7 +44,7 @@ export default (latus) => class Layers extends decorate(JsonResource) {
allEntities() {
const allEntities = [];
for (let i = 0; i < this.layers.length; i++) {
const layerEntities = this.layers[i].allEntities();
const layerEntities = this.layers[i].entities;
for (let j = 0; j < layerEntities.length; j++) {
allEntities.push(layerEntities[j]);
}
@ -67,12 +67,8 @@ export default (latus) => class Layers extends decorate(JsonResource) {
}
static async extendJson(json) {
const extended = await super.extendJson(json);
if (extended.layers) {
const {fromResourceType: {Layer}} = resource(latus);
extended.layers = await Promise.all(extended.layers.map((layer) => Layer.load(layer)));
}
return extended;
const {fromResourceType: {Layer}} = resource(latus);
return Promise.all(json.map((layer) => Layer.load(layer)));
}
findEntity(uuid) {
@ -89,7 +85,7 @@ export default (latus) => class Layers extends decorate(JsonResource) {
return this.layers[index];
}
load({layers = []} = {}) {
load(layers = []) {
this.removeAllLayers();
for (let i = 0; i < layers.length; i++) {
this.addLayer(layers[i]);

View File

@ -184,16 +184,16 @@ export default (latus) => class Room extends decorate(JsonResource) {
}
}
toNetwork(informed) {
toJSON() {
return {
layers: this.layers.toNetwork(informed),
layer: this.layers.toJSON(),
size: this.size,
};
}
toJSON() {
toNetwork(informed) {
return {
layer: this.layers.toJSON(),
layers: this.layers.toNetwork(informed),
size: this.size,
};
}

View File

@ -108,6 +108,10 @@ export default () => class Tiles extends decorate(Class) {
return index < 0 || index >= this.data.length ? undefined : this.data[index];
}
toNetwork() {
return this.toJSON();
}
toJSON() {
return {
size: this.size,

View File

@ -4,6 +4,8 @@ import Camera from '../camera';
export default () => class Followed extends Trait {
#camera = new Camera();
static defaultParams() {
return {
viewSize: [320, 180],
@ -19,15 +21,6 @@ export default () => class Followed extends Trait {
};
}
constructor(entity, params, state) {
super(entity, params, state);
const camera = new Camera();
camera.viewSize = this.params.viewSize;
this._camera = camera;
this.updatePosition();
this.onRoomSizeChanged();
}
destroy() {
if (!this.entity.is('roomed')) {
return;
@ -39,7 +32,7 @@ export default () => class Followed extends Trait {
}
get camera() {
return this._camera;
return this.#camera;
}
onRoomSizeChanged() {
@ -48,7 +41,7 @@ export default () => class Followed extends Trait {
}
const {room} = this.entity;
if (room) {
this._camera.areaSize = room.size;
this.#camera.areaSize = room.size;
}
}
@ -56,7 +49,7 @@ export default () => class Followed extends Trait {
if (!this.entity.is('positioned')) {
return;
}
this._camera.position = this.entity.position;
this.#camera.position = this.entity.position;
}
listeners() {
@ -85,12 +78,19 @@ export default () => class Followed extends Trait {
};
}
load(json) {
super.load(json);
this.#camera.viewSize = this.params.viewSize;
this.updatePosition();
this.onRoomSizeChanged();
}
tick() {
this.updatePosition();
}
renderTick(elapsed) {
this._camera.tick(elapsed);
this.#camera.tick(elapsed);
}
};

View File

@ -3,6 +3,10 @@ import {Trait} from '@avocado/traits';
export default () => class Layered extends Trait {
#tile = [0, 0];
#tileOffset = [0, 0];
static behaviorTypes() {
return {
layer: {
@ -25,24 +29,22 @@ export default () => class Layered extends Trait {
};
}
constructor(entity, params, state) {
super(entity, params, state);
this.entity.layer = null;
this._tile = [0, 0];
this._tileOffset = [0, 0];
this.setCurrentTileFromLayer();
}
destroy() {
this.entity.removeFromLayer();
}
get tile() {
return this._tile;
return this.#tile;
}
get tileOffset() {
return this._tileOffset;
return this.#tileOffset;
}
load(json) {
super.load(json);
this.entity.layer = null;
this.setCurrentTileFromLayer();
}
onLayerTilesetChanged() {
@ -61,21 +63,21 @@ export default () => class Layered extends Trait {
if (!tileset) {
return;
}
const oldTile = Vector.copy(this._tile);
this._tile = Vector.div(
const oldTile = Vector.copy(this.#tile);
this.#tile = Vector.div(
this.entity.position,
tileset.tileSize,
);
if (!Vector.equals(oldTile, this._tile)) {
this.entity.emit('tileChanged', oldTile, this._tile);
if (!Vector.equals(oldTile, this.#tile)) {
this.entity.emit('tileChanged', oldTile, this.#tile);
}
const oldTileOffset = Vector.copy(this._tileOffset);
this._tileOffset = Vector.mod(
const oldTileOffset = Vector.copy(this.#tileOffset);
this.#tileOffset = Vector.mod(
this.entity.position,
tileset.tileSize,
);
if (!Vector.equals(oldTileOffset, this._tileOffset)) {
this.entity.emit('tileOffsetChanged', oldTileOffset, this._tileOffset);
if (!Vector.equals(oldTileOffset, this.#tileOffset)) {
this.entity.emit('tileOffsetChanged', oldTileOffset, this.#tileOffset);
}
}

View File

@ -37,23 +37,6 @@ export default () => class TileEntity extends decorate(Trait) {
layer.addTileEntity(this.entity, tileIndex);
}
removeTileEntity(tileIndex) {
const {layer} = this.entity;
if (!layer) {
return;
}
layer.removeTileEntity(this.entity, tileIndex);
}
setTileIndex() {
if (!this.entity.layer) {
return;
}
this.entity.tileIndex = this.entity.layer.indexAt(
Vector.floor(this.entity.tile),
);
}
listeners() {
return {
@ -81,4 +64,21 @@ export default () => class TileEntity extends decorate(Trait) {
};
}
removeTileEntity(tileIndex) {
const {layer} = this.entity;
if (!layer) {
return;
}
layer.removeTileEntity(this.entity, tileIndex);
}
setTileIndex() {
if (!this.entity.layer) {
return;
}
this.entity.tileIndex = this.entity.layer.indexAt(
Vector.floor(this.entity.tile),
);
}
};

View File

@ -33,7 +33,8 @@ describe('Layer', () => {
});
entityList = new EntityList();
entityList.addEntity(entity);
layer = new Layer({entityList});
layer = new Layer();
await layer.load({entityList});
})
it('delegates to entity list', async () => {
expect(Object.keys(layer.entities).length).to.equal(1);

View File

@ -23,8 +23,8 @@
"@avocado/entity@^2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@avocado%2fentity/-/entity-2.0.0.tgz#838f9b2d50ab84f4c1956afabf7abe94c449afdf"
integrity sha512-riPsNlUF/9TGEsfDo5IBJOHPtziMtbvCIFRXKxXX4wY7PW9dpjr9wxb5/P7gexlql3l3/W7dF5cS7jQmu9qnPQ==
resolved "http://npm.cha0sdev/@avocado%2fentity/-/entity-2.0.0.tgz#e6d8d4f1e2d8b822dada80df5e4b8926b364df31"
integrity sha512-vAmZHbTXm2MwLOLxZf19llTFFwDUlC8nqaLm9FSwZlOhOVr5e2t8YJcjbisjWfGkNvTd6m9AluPj5vHCKjV+ww==
dependencies:
"@avocado/behavior" "2.0.0"
"@avocado/core" "2.0.0"
@ -42,8 +42,8 @@
"@avocado/graphics@2.0.0", "@avocado/graphics@^2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@avocado%2fgraphics/-/graphics-2.0.0.tgz#d6b7b82ee4dc0587f9c9f1d395063520a1113f8e"
integrity sha512-oGd6xtGIK1T99sZGKcZNa+xBYc2Jftq3tbVBiEH+4U6GjXgoTa49N/2wmxWd63HHwLYj7wFi6SC4kxEfXfeO6w==
resolved "http://npm.cha0sdev/@avocado%2fgraphics/-/graphics-2.0.0.tgz#2dc43f9a825fa1f9a72064d5e83630185f974e94"
integrity sha512-BsB+MPAhvuLdSSibvU+oLOcBXnUgEJAmaoXOLTIppDQh7ACo+Hqamib+2Zcx75VcmwleEeOIVDtnQJzKLYVInw==
dependencies:
"@avocado/core" "2.0.0"
"@avocado/input" "2.0.0"
@ -85,8 +85,8 @@
"@avocado/resource@2.0.0", "@avocado/resource@^2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@avocado%2fresource/-/resource-2.0.0.tgz#dcdf791f575bbfafe59965f1db6cea279df9a21f"
integrity sha512-8AGNWuhTPIuIMrPtDl2udvgVoktb5PHEiEWQ0dsg3y65mrRRz/9yulBi46s+zR2zkpfCiaNekFm9b1tLDBhwFw==
resolved "http://npm.cha0sdev/@avocado%2fresource/-/resource-2.0.0.tgz#12b9b1ee4bcb43ede8ba2172f16c82dc2f115d0f"
integrity sha512-qNTzFfkZMwYX+IEl64Del4uSfQKpWm6kR1KtlOWCbU5nc3sH5d9U+nFfbmGAJArEhC9lo2s2lQITvgkJ7D1VuQ==
dependencies:
"@avocado/core" "2.0.0"
"@latus/core" "2.0.0"
@ -96,8 +96,8 @@
"@avocado/s13n@2.0.0", "@avocado/s13n@^2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@avocado%2fs13n/-/s13n-2.0.0.tgz#4e8ee6deaedad15179fd5da153722b7e74833b5e"
integrity sha512-mdK+qHI74+lJjGwtmoUNHO9hRw0KEGWc/9NrNMD4M1iLMo/AGHoog4djFrC3fgx+r7I1ekAdSR8ucp60gXqwLQ==
resolved "http://npm.cha0sdev/@avocado%2fs13n/-/s13n-2.0.0.tgz#3aff3c15a6e8ef2a405e7b9ff45abd94e63f064d"
integrity sha512-UAmde98frU3TWlK0yIvHYM/PX+dpyx4O+a5QWQakm7ef9vZomPwyN/2Z87ArliOZILO3qhvusFqiLusUf8z7HA==
dependencies:
"@avocado/resource" "^2.0.0"
"@latus/core" "2.0.0"
@ -107,8 +107,8 @@
"@avocado/timing@2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@avocado%2ftiming/-/timing-2.0.0.tgz#295744a3c722ce4f4ce6880ccbf067dbb598fafc"
integrity sha512-O4/VGyElSezI1wjbthfkmseTnQQZi89T46ii+c2z16m3V6LjkkwlfwsAqj+hoF+5k8r9EdIFoDajN+Rsr7j9dA==
resolved "http://npm.cha0sdev/@avocado%2ftiming/-/timing-2.0.0.tgz#6eec2b614387a199b78dc15b833f2057a6032db9"
integrity sha512-aWpsLrHLrsQnWIUmYMOrJlFg/xwZFecLDU4i9WHwf6FW41SgjjxI8eeVPiiteGt2IUmGcRemuSV9PSBuazL76w==
dependencies:
"@avocado/core" "2.0.0"
"@avocado/graphics" "2.0.0"
@ -122,8 +122,8 @@
"@avocado/traits@^2.0.0":
version "2.0.0"
resolved "http://npm.cha0sdev/@avocado%2ftraits/-/traits-2.0.0.tgz#39276652100f02fe6e5b5cea38947c19285b9206"
integrity sha512-xaBPJRs10nl416b6Xm6NgaLk2FjU0WUG0mrvvI0TUw0SYzHCwUyFbvBDkph71N5N588CuR2V7rLhKOQJjNPWCQ==
resolved "http://npm.cha0sdev/@avocado%2ftraits/-/traits-2.0.0.tgz#7aa7c5504e627967189343a58248c123f80e44a4"
integrity sha512-7hoiN/MQmBGeGPg8wtg5erXxS5053IGsRyM0qdbnhkIY0tWLBJ2NjREqkDfC2avsJAc4yK5+x+l2PFpLJivxww==
dependencies:
"@avocado/core" "^2.0.0"
"@avocado/resource" "^2.0.0"

View File

@ -21,6 +21,14 @@ export default function StateProperty(key, meta = {}) {
this.state['${key}'] = value;
`);
/* eslint-enable func-names, no-new-func, no-param-reassign */
return Property(key, meta)(Superclass);
class Initializable extends Superclass {
initializeStateProperties() {
super.initializeStateProperties();
meta.initialize.call(this);
}
}
return Property(key, meta)(Initializable);
};
}

View File

@ -87,6 +87,9 @@ export default class Trait extends decorate(JsonResource) {
return {};
}
// eslint-disable-next-line class-methods-use-this
initializeStateProperties() {}
// eslint-disable-next-line class-methods-use-this
listeners() {
return {};
@ -97,6 +100,7 @@ export default class Trait extends decorate(JsonResource) {
const {constructor} = this;
this.params = constructor.defaultParamsWith(params);
this.state = constructor.defaultStateWith(state);
this.initializeStateProperties();
this.#previousState = JSON.parse(JSON.stringify(this.state));
}

View File

@ -20,8 +20,8 @@ class TestTrait extends Trait {
}
it('can set and override default params and state', () => {
const testTrait = new TestTrait({
it('can set and override default params and state', async () => {
const testTrait = await TestTrait.load({
params: {
asd: 'boo',
},