refactor: predictor next to client, smoothing
This commit is contained in:
parent
336ec04f66
commit
04a0230248
|
@ -17,7 +17,13 @@ export default class LocalClient extends Client {
|
|||
{type: 'module'},
|
||||
);
|
||||
this.interpolator.addEventListener('message', (event) => {
|
||||
this.accept(event.data);
|
||||
const packet = event.data;
|
||||
if (CLIENT_PREDICTION) {
|
||||
this.predictor.postMessage([1, packet]);
|
||||
}
|
||||
else {
|
||||
this.accept(packet);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (CLIENT_PREDICTION) {
|
||||
|
@ -35,12 +41,7 @@ export default class LocalClient extends Client {
|
|||
break;
|
||||
}
|
||||
case 1: {
|
||||
if (CLIENT_INTERPOLATION) {
|
||||
this.interpolator.postMessage(packet);
|
||||
}
|
||||
else {
|
||||
this.accept(packet);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -54,12 +55,12 @@ export default class LocalClient extends Client {
|
|||
}
|
||||
this.throughput.$$down += event.data.byteLength;
|
||||
const packet = decode(event.data);
|
||||
if (CLIENT_PREDICTION) {
|
||||
this.predictor.postMessage([1, packet]);
|
||||
}
|
||||
else if (CLIENT_INTERPOLATION) {
|
||||
if (CLIENT_INTERPOLATION) {
|
||||
this.interpolator.postMessage(packet);
|
||||
}
|
||||
else if (CLIENT_PREDICTION) {
|
||||
this.predictor.postMessage([1, packet]);
|
||||
}
|
||||
else {
|
||||
this.accept(packet);
|
||||
}
|
||||
|
|
|
@ -27,17 +27,8 @@ const Flow = {
|
|||
DOWN: 1,
|
||||
};
|
||||
|
||||
const Stage = {
|
||||
UNACK: 0,
|
||||
ACK: 1,
|
||||
FINISHING: 2,
|
||||
FINISHED: 3,
|
||||
};
|
||||
|
||||
const actions = new Map();
|
||||
|
||||
let ecs = new PredictionEcs({Components, Systems});
|
||||
|
||||
let mainEntityId = 0;
|
||||
|
||||
function applyClientActions(elapsed) {
|
||||
|
@ -46,7 +37,7 @@ function applyClientActions(elapsed) {
|
|||
const {Controlled} = main;
|
||||
const finished = [];
|
||||
for (const [id, action] of actions) {
|
||||
if (Stage.UNACK === action.stage) {
|
||||
if (0 === action.finished && !action.ack) {
|
||||
if (!Controlled.locked) {
|
||||
switch (action.action.type) {
|
||||
case 'moveUp':
|
||||
|
@ -60,7 +51,7 @@ function applyClientActions(elapsed) {
|
|||
}
|
||||
action.steps.push(elapsed);
|
||||
}
|
||||
if (Stage.FINISHING === action.stage) {
|
||||
if (1 === action.finished) {
|
||||
if (!Controlled.locked) {
|
||||
switch (action.action.type) {
|
||||
case 'moveUp':
|
||||
|
@ -72,9 +63,9 @@ function applyClientActions(elapsed) {
|
|||
}
|
||||
}
|
||||
}
|
||||
action.stage = Stage.FINISHED;
|
||||
action.finished = 2;
|
||||
}
|
||||
if (Stage.FINISHED === action.stage) {
|
||||
if (action.ack && 2 === action.finished) {
|
||||
action.steps.shift();
|
||||
if (0 === action.steps.length) {
|
||||
finished.push(id);
|
||||
|
@ -113,13 +104,13 @@ onmessage = async (event) => {
|
|||
if (0 === packet.payload.value) {
|
||||
const ack = pending.get(packet.payload.type);
|
||||
const action = actions.get(ack);
|
||||
action.stage = Stage.FINISHING;
|
||||
action.finished = 1;
|
||||
pending.delete(packet.payload.type);
|
||||
}
|
||||
else {
|
||||
const tx = {
|
||||
action: packet.payload,
|
||||
stage: Stage.UNACK,
|
||||
ack: false,finished: 0,
|
||||
steps: [],
|
||||
};
|
||||
packet.payload.ack = Math.random();
|
||||
|
@ -139,11 +130,12 @@ onmessage = async (event) => {
|
|||
switch (packet.type) {
|
||||
case 'ActionAck': {
|
||||
const action = actions.get(packet.payload.ack);
|
||||
action.stage = Stage.ACK;
|
||||
action.ack = true;
|
||||
return;
|
||||
}
|
||||
case 'EcsChange': {
|
||||
ecs = new PredictionEcs({Components, Systems});
|
||||
mainEntityId = 0;
|
||||
break;
|
||||
}
|
||||
case 'Tick': {
|
||||
|
|
|
@ -27,6 +27,7 @@ const textEncoder = new TextEncoder();
|
|||
|
||||
export default class Engine {
|
||||
|
||||
ackingActions = new Map();
|
||||
connectedPlayers = new Map();
|
||||
ecses = {};
|
||||
frame = 0;
|
||||
|
@ -250,6 +251,15 @@ export default class Engine {
|
|||
}
|
||||
}
|
||||
if (payload.ack) {
|
||||
if (!this.ackingActions.has(connection)) {
|
||||
this.ackingActions.set(connection, []);
|
||||
}
|
||||
this.ackingActions.get(connection).push({
|
||||
type: 'ActionAck',
|
||||
payload: {
|
||||
ack: payload.ack,
|
||||
},
|
||||
})
|
||||
this.server.send(
|
||||
connection,
|
||||
{
|
||||
|
@ -303,6 +313,7 @@ export default class Engine {
|
|||
if (!connectedPlayer) {
|
||||
return;
|
||||
}
|
||||
this.ackingActions.delete(connection);
|
||||
this.connectedPlayers.delete(connection);
|
||||
this.incomingActions.delete(connection);
|
||||
const {entity, heartbeat, id} = connectedPlayer;
|
||||
|
@ -445,6 +456,12 @@ export default class Engine {
|
|||
|
||||
update(elapsed) {
|
||||
for (const [connection, {entity}] of this.connectedPlayers) {
|
||||
if (this.ackingActions.has(connection)) {
|
||||
for (const ack of this.ackingActions.get(connection)) {
|
||||
this.server.send(connection, ack);
|
||||
}
|
||||
this.ackingActions.delete(connection);
|
||||
}
|
||||
if (!entity) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -17,4 +17,4 @@ export const SERVER_LATENCY = 0;
|
|||
|
||||
export const TPS = 60;
|
||||
|
||||
export const UPS = 15;
|
||||
export const UPS = 30;
|
||||
|
|
Loading…
Reference in New Issue
Block a user