refactor: unwind client position prediction

This commit is contained in:
cha0s 2022-03-23 02:07:16 -05:00
parent acdb34c612
commit 49ff7a4d05
2 changed files with 34 additions and 45 deletions

View File

@ -65,6 +65,9 @@ export default () => class Mobile extends decorate(Trait) {
default:
return;
}
if ('web' === process.env.FLECKS_CORE_BUILD_TARGET) {
return;
}
this.#rememberedActionMovement = [
this.#movement[1] - this.#movement[3],
this.#movement[2] - this.#movement[0],
@ -210,7 +213,6 @@ export default () => class Mobile extends decorate(Trait) {
tick(elapsed) {
if (this.entity.isMobile && !Vector.isZero(this.actionMovement)) {
this.entity.markSidechannelPositionUpdate();
this.entity.requestMovement(this.actionMovement);
}
if (Vector.isZero(this.#appliedMovement)) {

View File

@ -4,26 +4,21 @@ import {compose, EventEmitter} from '@flecks/core';
const decorate = compose(
EventEmitter,
Vector.Mixin('trackedPosition', 'x', 'y', {
Vector.Mixin('internalPosition', 'x', 'y', {
track: true,
}),
Vector.Mixin('serverPosition', 'serverX', 'serverY'),
);
// < 16768 will pack into 1 short per axe and give +/- 0.25 precision.
export default () => class Positioned extends decorate(Trait) {
#sidechannelUpdate = false;
constructor() {
super();
this.on('trackedPositionChanged', this.onTrackedPositionChanged, this);
this.on('internalPositionChanged', this.onInternalPositionChanged, this);
}
acceptPacket(packet) {
if ('TraitUpdatePositionedPosition' === packet.constructor.type) {
[this.serverX, this.serverY] = packet.data;
this.serverPositionDirty = true;
this.internalPosition = packet.data;
}
}
@ -36,63 +31,71 @@ export default () => class Positioned extends decorate(Trait) {
cleanPackets() {
super.cleanPackets();
this.#sidechannelUpdate = false;
}
destroy() {
super.destroy();
this.off('trackedPositionChanged', this.ontrackedPositionChanged);
this.off('internalPositionChanged', this.onInternalPositionChanged);
}
async load(json) {
await super.load(json);
const {x, y} = this.state;
this.trackedPosition = [x, y];
this.internalPosition = [x, y];
this.entity.position[0] = x;
this.entity.position[1] = y;
if ('web' === process.env.FLECKS_CORE_BUILD_TARGET) {
this.serverPosition = this.trackedPosition;
this.serverPositionDirty = false;
}
}
// eslint-disable-next-line camelcase
onTrackedPositionChanged(oldPosition, newPosition) {
onInternalPositionChanged(oldPosition, newPosition) {
const xChanged = this.entity.position[0] !== newPosition[0];
const yChanged = this.entity.position[1] !== newPosition[1];
[this.entity.position[0], this.entity.position[1]] = newPosition;
if ('web' !== process.env.FLECKS_CORE_BUILD_TARGET) {
[this.state.x, this.state.y] = newPosition;
this.markAsDirty();
}
if (xChanged) {
this.entity.emit('xChanged', oldPosition[0], newPosition[0]);
}
if (yChanged) {
this.entity.emit('yChanged', oldPosition[1], newPosition[1]);
}
this.entity.emit('positionChanged', oldPosition, newPosition);
}
packetsFor(informed) {
packetsFor() {
const {x, y} = this.stateDifferences();
if ((informed === this.entity && this.#sidechannelUpdate) || x || y) {
if (x || y) {
return [[
'TraitUpdatePositionedPosition',
this.entity.position,
this.internalPosition,
]];
}
return [];
}
listeners() {
return {
positionChanged: () => {
if ('web' !== process.env.FLECKS_CORE_BUILD_TARGET) {
[this.state.x, this.state.y] = this.internalPosition;
this.markAsDirty();
}
},
};
}
methods() {
return {
distanceFrom: (other) => Vector.distance(this.entity.position, other.position),
markSidechannelPositionUpdate: () => {
this.#sidechannelUpdate = true;
this.markAsDirty();
},
distanceFrom: (other) => Vector.distance(this.internalPosition, other.position),
pointAround: (radius, angle) => {
if (!this.entity.is('Positioned')) {
return [0, 0];
}
return Vector.add(
this.entity.position,
this.internalPosition,
[
radius * Math.cos(angle),
radius * -Math.sin(angle),
@ -101,26 +104,10 @@ export default () => class Positioned extends decorate(Trait) {
},
setPosition: (position) => {
this.trackedPosition = position;
this.internalPosition = position;
},
};
}
tick(elapsed) {
if (!this.serverPositionDirty) {
return;
}
if (Vector.equals(this.trackedPosition, this.serverPosition)) {
this.serverPositionDirty = false;
return;
}
if (Vector.equalsClose(this.trackedPosition, this.serverPosition, 4)) {
return;
}
const diff = Vector.sub(this.serverPosition, this.trackedPosition);
const lerp = elapsed * 15;
this.trackedPosition = Vector.add(this.trackedPosition, Vector.scale(diff, lerp));
}
};