chuck.js/app/Game/Channel/Control/PlayerController.js
Jeena 71e4b4e847 Replace cheat-detection teleport with server reconciliation
The old PUNKBUSTER check compared client-reported position to server
position and snapped the player back when latency made them diverge,
which felt like getting teleported under any real network conditions.

Replaces that with proper client-side prediction + reconciliation:
client tags each input with a sequence number and keeps an input
buffer; server tracks the last processed sequence and reports its
authoritative position via a per-user inputAck alongside each
worldUpdate. The client only corrects when the actual disagreement
exceeds what the unacked input time can explain — so steady-state
movement runs purely on local physics, and only genuine unexpected
events (collisions, being hit) trigger a smooth blend toward the
server state.

Includes adaptive threshold scaling so high-latency sessions don't
false-positive corrections during normal running.
2026-05-11 00:37:42 +00:00

57 lines
No EOL
1.6 KiB
JavaScript
Executable file

define([
"Game/Core/Control/PlayerController",
"Lib/Utilities/NotificationCenter",
"Lib/Utilities/Protocol/Parser"
],
function(Parent, nc, Parser) {
"use strict";
function PlayerController(player) {
Parent.call(this, player);
this._lastProcessedSeq = 0;
}
PlayerController.prototype = Object.create(Parent.prototype);
/*
* retrieves move (and other) commands from client and executes them at the server
*/
PlayerController.prototype.applyCommand = function(options) {
// FIXME: remove this function and use ProtocolHelper.applyCommand() instead
// Don't forget to change the function names to on...
var message;
if (typeof options == "string") {
message = Parser.decode(options);
} else {
message = options;
}
for (var command in message) {
var commandOptions = message[command];
// Track sequence number from client input commands
if (commandOptions && typeof commandOptions === 'object' && commandOptions._seq !== undefined) {
this._lastProcessedSeq = commandOptions._seq;
}
this[command].call(this, commandOptions);
}
};
PlayerController.prototype.handActionRequest = function(options) {
options.x = parseFloat(options.x) || 0.0;
options.y = parseFloat(options.y) || 0.0;
options.av = parseFloat(options.av) || 0.0;
if (options) this.player.handActionRequest(options);
};
PlayerController.prototype.suicide = function() {
this.player.suicide();
};
return PlayerController;
});