refactor: unwind client position prediction
This commit is contained in:
parent
acdb34c612
commit
49ff7a4d05
|
@ -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)) {
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue
Block a user