diff --git a/app/Game/Channel/Control/PlayerController.js b/app/Game/Channel/Control/PlayerController.js index 705ed32..d66c679 100755 --- a/app/Game/Channel/Control/PlayerController.js +++ b/app/Game/Channel/Control/PlayerController.js @@ -11,7 +11,6 @@ function(Parent, nc, Parser) { function PlayerController(player) { Parent.call(this, player); - this._lastProcessedSeq = 0; } PlayerController.prototype = Object.create(Parent.prototype); @@ -30,14 +29,7 @@ function(Parent, nc, Parser) { } 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); + this[command].call(this, message[command]); } }; diff --git a/app/Game/Channel/GameController.js b/app/Game/Channel/GameController.js index a010d0b..81126ca 100755 --- a/app/Game/Channel/GameController.js +++ b/app/Game/Channel/GameController.js @@ -120,23 +120,6 @@ function (Parent, PhysicsEngine, Settings, requestAnimFrame, nc, Box2D, Player, nc.trigger(nc.ns.channel.to.client.gameCommand.broadcast, "worldUpdate", update); } - // Send per-user input acknowledgments for server reconciliation - for (var id in this.players) { - var player = this.players[id]; - if (player.isSpawned() && player.playerController._lastProcessedSeq > 0) { - var body = player.doll.body; - nc.trigger( - nc.ns.channel.to.client.user.gameCommand.send + id, - "inputAck", - { - seq: player.playerController._lastProcessedSeq, - p: { x: body.GetPosition().x, y: body.GetPosition().y }, - lv: { x: body.GetLinearVelocity().x, y: body.GetLinearVelocity().y } - } - ); - } - } - this.worldUpdateTimeout = setTimeout(this.updateWorld.bind(this), Settings.NETWORK_UPDATE_INTERVAL); }; diff --git a/app/Game/Client/Control/PlayerController.js b/app/Game/Client/Control/PlayerController.js index c555682..82db175 100755 --- a/app/Game/Client/Control/PlayerController.js +++ b/app/Game/Client/Control/PlayerController.js @@ -14,7 +14,6 @@ function (Parent, nc, KeyboardAndMouse, Gamepad, pointerLockManager) { Parent.call(this, me); - this._inputSeq = 0; this.keyboardAndMouse = new KeyboardAndMouse(this); this.gamepad = new Gamepad(this); } @@ -27,48 +26,34 @@ function (Parent, nc, KeyboardAndMouse, Gamepad, pointerLockManager) { this.gamepad.update(); }; - PlayerController.prototype._recordAndSend = function(command) { - this._inputSeq++; - if (this.player.doll && this.player.doll.body) { - var vel = this.player.doll.body.GetLinearVelocity(); - this.player.inputBuffer.add({ - seq: this._inputSeq, - timestamp: Date.now(), - vx: vel.x, - vy: vel.y - }); - } - nc.trigger(nc.ns.client.to.server.gameCommand.send, command, {_seq: this._inputSeq}); - }; - PlayerController.prototype.moveLeft = function () { if (!this.isPlayerInputAllowed()) return; Parent.prototype.moveLeft.call(this); - this._recordAndSend('moveLeft'); + nc.trigger(nc.ns.client.to.server.gameCommand.send, 'moveLeft'); } PlayerController.prototype.moveRight = function () { if (!this.isPlayerInputAllowed()) return; Parent.prototype.moveRight.call(this); - this._recordAndSend('moveRight'); + nc.trigger(nc.ns.client.to.server.gameCommand.send, 'moveRight'); } // always allow to stop, to prevent endless running PlayerController.prototype.stop = function () { Parent.prototype.stop.call(this); - this._recordAndSend('stop'); + nc.trigger(nc.ns.client.to.server.gameCommand.send, 'stop'); } PlayerController.prototype.jump = function () { if (!this.isPlayerInputAllowed()) return; Parent.prototype.jump.call(this); - this._recordAndSend('jump'); + nc.trigger(nc.ns.client.to.server.gameCommand.send, 'jump'); } // always allow to stop. PlayerController.prototype.jumpStop = function () { Parent.prototype.jumpStop.call(this); - this._recordAndSend('jumpStop'); + nc.trigger(nc.ns.client.to.server.gameCommand.send, 'jumpStop'); } PlayerController.prototype.setXY = function(x, y) { diff --git a/app/Game/Client/GameController.js b/app/Game/Client/GameController.js index 08c6c10..7d3a668 100755 --- a/app/Game/Client/GameController.js +++ b/app/Game/Client/GameController.js @@ -60,35 +60,6 @@ function (Parent, Box2D, PhysicsEngine, ViewManager, PlayerController, nc, reque domController.fpsStep(); }; - GameController.prototype.onInputAck = function(ackData) { - if (!this.me || !this.me.doll) return; - - this.me.inputBuffer.acknowledgeUpTo(ackData.seq); - - var currentPos = this.me.doll.body.GetPosition(); - var diffX = Math.abs(ackData.p.x - currentPos.x); - var diffY = Math.abs(ackData.p.y - currentPos.y); - - // Scale the acceptable drift by how many inputs the server - // hasn't processed yet. More unacked time = more expected drift. - var unacked = this.me.inputBuffer.getUnacknowledged(); - var expectedDrift = 0; - if (unacked.length > 0) { - var unackedTime = (Date.now() - unacked[0].timestamp) / 1000; - expectedDrift = unackedTime * Settings.RUN_SPEED; - } - - var threshold = Settings.RECONCILIATION_THRESHOLD + expectedDrift; - - // Only correct when the error exceeds what latency can explain — - // meaning something unexpected happened (collision, being hit, etc.) - if (diffX > threshold || diffY > threshold) { - this.me.applyReconciliation( - ackData.p.x, ackData.p.y, - ackData.lv.x, ackData.lv.y - ); - } - }; GameController.prototype.onClientReadyResponse = function(options) { var i; @@ -131,7 +102,6 @@ function (Parent, Box2D, PhysicsEngine, ViewManager, PlayerController, nc, reque }; - // Own doll position is handled by onInputAck reconciliation, not worldUpdate GameController.prototype.updateGameObject = function (gameObject, gameObjectUpdate) { if (gameObject === this.me.doll) { return; @@ -165,10 +135,6 @@ function (Parent, Box2D, PhysicsEngine, ViewManager, PlayerController, nc, reque var player = this.players[playerId]; player.spawn(x, y); - if (player === this.me) { - this.me.inputBuffer.clear(); - } - if(options.holdingItemUid) { this.onHandActionResponse({ itemUid: options.holdingItemUid, @@ -224,10 +190,6 @@ function (Parent, Box2D, PhysicsEngine, ViewManager, PlayerController, nc, reque var killedByPlayer = this.players[options.killedByPlayerId]; player.kill(killedByPlayer, options.ragDollId); - if (player === this.me) { - this.me.inputBuffer.clear(); - } - nc.trigger(nc.ns.client.view.gameStats.kill, { victim: { name: player.user.options.nickname, @@ -259,7 +221,6 @@ function (Parent, Box2D, PhysicsEngine, ViewManager, PlayerController, nc, reque GameController.prototype.endRound = function() { this.me.setInBetweenRounds(true); - this.me.inputBuffer.clear(); this.toggleGameStats(true); }; diff --git a/app/Game/Client/GameObjects/Item.js b/app/Game/Client/GameObjects/Item.js index f798416..e6ab7d3 100755 --- a/app/Game/Client/GameObjects/Item.js +++ b/app/Game/Client/GameObjects/Item.js @@ -19,7 +19,30 @@ function (Parent, Settings, nc, Layer) { } Item.prototype = Object.create(Parent.prototype); - + + Item.prototype.setUpdateData = function(update) { + var currentPos = this.body.GetPosition(); + var diffX = update.p.x - currentPos.x; + var diffY = update.p.y - currentPos.y; + var distance = Math.sqrt(diffX * diffX + diffY * diffY); + var speed = Math.sqrt(update.lv.x * update.lv.x + update.lv.y * update.lv.y); + + this.body.SetAwake(true); + + if (distance > 3 || speed < 0.5) { + // Stationary: sync so grab sensor contact is accurate. + // Large error: snap for respawn/warp/grab events. + this.body.SetPosition(update.p); + this.body.SetAngle(update.a); + this.body.SetLinearVelocity(update.lv); + this.body.SetAngularVelocity(update.av); + } + // In-flight: skip correction entirely. Client and server both run the + // same Box2D physics from the same throw impulse, so they stay close + // without per-update snapping. Applying the server's stale state would + // snap the item back to where it was 125 ms ago. + }; + Item.prototype.createMesh = function() { var self = this; diff --git a/app/Game/Client/InputBuffer.js b/app/Game/Client/InputBuffer.js deleted file mode 100644 index 63fd574..0000000 --- a/app/Game/Client/InputBuffer.js +++ /dev/null @@ -1,37 +0,0 @@ -define([ -], - -function () { - - "use strict"; - - var MAX_BUFFER_SIZE = 300; - - function InputBuffer() { - this._buffer = []; - } - - InputBuffer.prototype.add = function(entry) { - this._buffer.push(entry); - if (this._buffer.length > MAX_BUFFER_SIZE) { - this._buffer.shift(); - } - }; - - InputBuffer.prototype.acknowledgeUpTo = function(seq) { - while (this._buffer.length > 0 && this._buffer[0].seq <= seq) { - this._buffer.shift(); - } - }; - - InputBuffer.prototype.getUnacknowledged = function() { - return this._buffer; - }; - - InputBuffer.prototype.clear = function() { - this._buffer = []; - }; - - return InputBuffer; - -}); diff --git a/app/Game/Client/Me.js b/app/Game/Client/Me.js index fb0cdda..3c4c3ce 100644 --- a/app/Game/Client/Me.js +++ b/app/Game/Client/Me.js @@ -4,10 +4,9 @@ define([ "Lib/Utilities/NotificationCenter", "Lib/Utilities/Assert", "Game/Client/Control/PlayerController", - "Game/Client/InputBuffer", ], -function (Parent, Settings, nc, Assert, PlayerController, InputBuffer) { +function (Parent, Settings, nc, Assert, PlayerController) { "use strict"; @@ -20,8 +19,6 @@ function (Parent, Settings, nc, Assert, PlayerController, InputBuffer) { y: 0 }; - this.inputBuffer = new InputBuffer(); - this.arrowMesh = null; this.createAndAddArrow(); this.playerController = new PlayerController(this); @@ -45,27 +42,6 @@ function (Parent, Settings, nc, Assert, PlayerController, InputBuffer) { }; }; - Me.prototype.applyReconciliation = function(x, y, vx, vy) { - var currentPos = this.doll.body.GetPosition(); - var diffX = x - currentPos.x; - var diffY = y - currentPos.y; - var distance = Math.sqrt(diffX * diffX + diffY * diffY); - - if (distance > Settings.RECONCILIATION_SNAP_THRESHOLD) { - // Large error — snap immediately (server-side teleport, respawn, etc.) - this.doll.body.SetPosition({x: x, y: y}); - } else { - // Small error — blend toward reconciled position - var factor = Settings.RECONCILIATION_BLEND_FACTOR; - this.doll.body.SetPosition({ - x: currentPos.x + diffX * factor, - y: currentPos.y + diffY * factor - }); - } - - this.doll.body.SetLinearVelocity({x: vx, y: vy}); - }; - Me.prototype.createAndAddArrow = function() { var self = this; diff --git a/app/Game/Config/Settings.js b/app/Game/Config/Settings.js index f61f1f1..99e96d1 100755 --- a/app/Game/Config/Settings.js +++ b/app/Game/Config/Settings.js @@ -95,10 +95,6 @@ function () { CHANNEL_DEFAULT_LEVELS: ["debug"], CHANNEL_RECORD_SESSION: false, - // RECONCILIATION - RECONCILIATION_THRESHOLD: 1, - RECONCILIATION_SNAP_THRESHOLD: 5.0, - RECONCILIATION_BLEND_FACTOR: 0.2 }; Settings.TILE_RATIO = Settings.ORIGINAL_TILE_SIZE / Settings.TILE_SIZE;