124 lines
2.5 KiB
JavaScript
124 lines
2.5 KiB
JavaScript
import {compose, flatten, mapObject} from '@avocado/core';
|
|
import {StateProperty, Trait} from '@avocado/entity';
|
|
|
|
import Actions from '../actions';
|
|
import compile from '../compile';
|
|
import Context from '../context';
|
|
|
|
const decorate = compose(
|
|
StateProperty('currentRoutine', {
|
|
track: true,
|
|
}),
|
|
StateProperty('isBehaving'),
|
|
);
|
|
|
|
export default class Behaved extends decorate(Trait) {
|
|
|
|
static behaviorTypes() {
|
|
return {
|
|
context: {
|
|
type: 'context',
|
|
label: 'Context',
|
|
},
|
|
};
|
|
}
|
|
|
|
static defaultParams() {
|
|
return {
|
|
routines: {},
|
|
};
|
|
}
|
|
|
|
static defaultState() {
|
|
return {
|
|
currentRoutine: 'initial',
|
|
isBehaving: true,
|
|
}
|
|
}
|
|
|
|
static describeParams() {
|
|
return {
|
|
routines: {
|
|
type: 'routines',
|
|
label: 'Routines',
|
|
},
|
|
}
|
|
}
|
|
|
|
static describeState() {
|
|
return {
|
|
isBehaving: {
|
|
type: 'bool',
|
|
label: 'Is behaving',
|
|
},
|
|
currentRoutine: {
|
|
type: 'string',
|
|
label: 'Current routine',
|
|
options: (entity) => (
|
|
Object.keys(entity.traitInstance('behaved').params.routines)
|
|
.reduce((r, key) => ({...r, [key]: key}), {})
|
|
),
|
|
},
|
|
}
|
|
}
|
|
|
|
static type() {
|
|
return 'behaved';
|
|
}
|
|
|
|
constructor(entity, params, state) {
|
|
super(entity, params, state);
|
|
this._context = new Context({
|
|
entity: [this.entity, 'entity'],
|
|
});
|
|
this._currentRoutine = undefined;
|
|
this._routines = mapObject(
|
|
this.params.routines,
|
|
(routine) => new Actions(compile(routine))
|
|
);
|
|
this.updateCurrentRoutine(this.state.currentRoutine);
|
|
}
|
|
|
|
destroy() {
|
|
this._context.destroy();
|
|
this._currentRoutine = undefined;
|
|
this._routines = undefined;
|
|
}
|
|
|
|
get context() {
|
|
return this._context;
|
|
}
|
|
|
|
updateCurrentRoutine(currentRoutine) {
|
|
this._currentRoutine = this._routines[currentRoutine];
|
|
}
|
|
|
|
listeners() {
|
|
return {
|
|
|
|
currentRoutineChanged: (old, currentRoutine) => {
|
|
this.updateCurrentRoutine(currentRoutine);
|
|
},
|
|
|
|
isDyingChanged: (_, isDying) => {
|
|
this.entity.isBehaving = !isDying;
|
|
},
|
|
|
|
traitAdded: (type) => {
|
|
flatten(this.entity.invokeHookFlat('contextTypeHints'))
|
|
.forEach(([key, type]) => this._context.add(key, undefined, type));
|
|
},
|
|
|
|
};
|
|
}
|
|
|
|
tick(elapsed) {
|
|
if (AVOCADO_SERVER) {
|
|
if (this._currentRoutine && this.entity.isBehaving) {
|
|
this._currentRoutine.tick(this._context, elapsed);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|