avocado-old/packages/entity/traits/positioned.trait.js

148 lines
3.7 KiB
JavaScript
Raw Normal View History

2019-04-28 23:45:03 -05:00
import {compose, EventEmitter} from '@avocado/core';
2019-04-10 21:02:42 -05:00
import {Vector} from '@avocado/math';
2019-03-17 23:45:48 -05:00
2019-04-10 21:02:42 -05:00
import {Trait} from '../trait';
2019-05-13 21:07:51 -05:00
import {TraitPositionedPacket} from '../packets/trait-positioned.packet';
2019-03-17 23:45:48 -05:00
const decorate = compose(
2019-04-10 21:02:42 -05:00
EventEmitter,
Vector.Mixin('_position', 'x', 'y', {
2019-03-18 20:05:00 -05:00
track: true,
}),
2019-04-12 09:48:43 -05:00
Vector.Mixin('serverPosition', 'serverX', 'serverY', {
track: true,
}),
2019-03-17 23:45:48 -05:00
);
2019-04-10 21:02:42 -05:00
// < 16768 will pack into 1 short per axe and give +/- 0.25 precision.
2019-05-05 04:26:35 -05:00
export class Positioned extends decorate(Trait) {
2019-03-17 23:45:48 -05:00
static defaultState() {
return {
x: 0,
y: 0,
};
}
2019-05-05 04:26:35 -05:00
static type() {
return 'positioned';
}
constructor(entity, params, state) {
super(entity, params, state);
2019-04-30 17:11:41 -05:00
this.on('_positionChanged', this.on_positionChanged, this);
2019-05-13 21:07:51 -05:00
const x = this.state.x >> 2;
const y = this.state.y >> 2;
2019-04-10 21:02:42 -05:00
this._position = [x, y];
this.entity.position[0] = x;
this.entity.position[1] = y;
2019-04-23 16:57:42 -05:00
if (AVOCADO_CLIENT) {
2019-04-23 16:58:36 -05:00
this._relaxServerPositionConstraintIfNearerThan = 0;
2019-04-23 16:57:42 -05:00
this.serverPosition = this._position;
this.serverPositionDirty = false;
2019-04-30 17:11:41 -05:00
this.on('serverPositionChanged', this.onServerPositionChanged, this);
}
}
destroy() {
this.off('_positionChanged', this.on_positionChanged);
if (AVOCADO_CLIENT) {
this.off('serverPositionChanged', this.onServerPositionChanged);
}
}
2019-05-13 21:07:51 -05:00
acceptPacket(packet) {
if (packet instanceof TraitPositionedPacket) {
this.serverX = (packet.data.position & 0xFFFF) >> 2;
this.serverY = (packet.data.position >> 16) >> 2;
}
}
2019-04-30 17:11:41 -05:00
on_positionChanged(oldPosition, newPosition) {
this.entity.position[0] = newPosition[0];
this.entity.position[1] = newPosition[1];
2019-04-30 17:11:41 -05:00
if (AVOCADO_SERVER) {
2019-05-13 21:07:51 -05:00
this.state.x = newPosition[0] << 2;
this.state.y = newPosition[1] << 2;
2019-04-30 17:11:41 -05:00
}
this.entity.emit('positionChanged', oldPosition, newPosition);
}
onServerPositionChanged() {
this.serverPositionDirty = true;
2019-04-12 09:48:43 -05:00
}
2019-05-13 21:07:51 -05:00
packetsForUpdate() {
const packets = [];
2019-05-14 05:45:22 -05:00
if (this.isDirty) {
// Physics slop can end us up with negatives. Don't allow them in the
// packed representation, even though it means a slight loss in accuracy.
// The world bounds will (should!) keep things *eventually* correct.
const x = Math.max(0, this.state.x);
const y = Math.max(0, this.state.y);
const packed = (y << 16) | (x << 0);
2019-05-13 21:07:51 -05:00
packets.push(new TraitPositionedPacket({
position: packed,
}, this.entity));
2019-05-14 05:45:22 -05:00
this.makeClean();
2019-04-12 09:48:43 -05:00
}
2019-05-13 21:07:51 -05:00
return packets;
2019-04-10 21:02:42 -05:00
}
2019-04-23 16:58:36 -05:00
set relaxServerPositionConstraintIfNearerThan(nearerThan) {
this._relaxServerPositionConstraintIfNearerThan = nearerThan;
}
2019-04-12 09:48:43 -05:00
listeners() {
return {
isTickingChanged: () => {
// Snap position on ticking change.
2019-04-23 16:57:42 -05:00
if (AVOCADO_CLIENT) {
this._position = this.serverPosition;
}
},
2019-04-12 09:48:43 -05:00
};
}
2019-05-01 21:35:38 -05:00
methods() {
return {
setPosition: (position) => {
this._position = position;
},
};
}
2019-04-23 16:56:47 -05:00
renderTick(elapsed) {
if (!this.serverPositionDirty) {
return;
}
if (Vector.equals(this._position, this.serverPosition)) {
2019-05-03 08:47:56 -05:00
this.serverPositionDirty = false;
return;
}
if (Vector.equalsClose(this._position, this.serverPosition, 0.1)) {
this._position = this.serverPosition;
2019-05-03 08:47:56 -05:00
this.serverPositionDirty = false;
return;
}
const diff = Vector.sub(this.serverPosition, this._position);
2019-04-23 17:41:37 -05:00
const nearerThan = this._relaxServerPositionConstraintIfNearerThan;
let lerp;
if (
nearerThan
&& Vector.equalsClose(this._position, this.serverPosition, nearerThan)
) {
lerp = .01;
}
else {
lerp = .5;
}
this._position = Vector.add(this._position, Vector.scale(diff, lerp));
}
2019-03-17 23:45:48 -05:00
}