private void doPlayerReconciliation(ClientPlayer player, NetworkingData.PlayerStateData playerState) { var reconciledPosition = playerState.Position; var max = player.reconciliationInputs.Count; if (player.reconciliationInputs.Count > 100) { Debug.LogError($"We seem to be leaking reconciliation inputs (count: {player.reconciliationInputs.Count}"); } for (int x = 0; x < max; x++) { var nextInput = player.reconciliationInputs.Dequeue(); if (nextInput.InputSeq >= playerState.LastProcessedInput) { reconciledPosition = PlayerMovement.MovePlayer(nextInput, reconciledPosition, nextInput.DeltaTime); } var renderPosition = player.transform.localPosition; if (Vector2.Distance(new Vector2(renderPosition.x, renderPosition.y), reconciledPosition) > 0.05f) { //TODO may want to really, really re-verify this reconciliation logic isn't causing issues/popping/choppy rendering //TODO remove me Debug.Log($"reconciling position from rendered position: {renderPosition.x}, {renderPosition.y} to server position: {reconciledPosition.X}, {reconciledPosition.Y}"); player.transform.localPosition = new Vector3(reconciledPosition.X, reconciledPosition.Y, 0); } } }
static void SendPlayerStateDataUpdates() { var players = Server.Instance.Players.Values.ToArray(); NetworkingData.PlayerStateData[] positions = new NetworkingData.PlayerStateData[players.Length]; int i = 0; foreach (var player in players) { positions[i] = player.getStateData(); i++; } foreach (KeyValuePair <ushort, Player> p in Server.Instance.Players) { NetworkingData.GameUpdateData data = new NetworkingData.GameUpdateData(positions); using (Message m = Message.Create((ushort)NetworkingData.Tags.GameUpdate, data)) { p.Value.SendMessage(m, SendMode.Reliable); } } }
private void processServerUpdates() { //TODO can we clean up the deep nesting here? if (worldUpdateBuffer.Count > 0) { int numUpdates = worldUpdateBuffer.Count; for (int i = 0; i < numUpdates; i++) { NetworkingData.GameUpdateData nextUpdate = worldUpdateBuffer.Dequeue(); for (int j = 0; j < nextUpdate.UpdateData.Length; j++) { NetworkingData.PlayerStateData playerState = nextUpdate.UpdateData[j]; ClientPlayer player; if (players.TryGetValue(playerState.Id, out player)) { if (player.isOwn) { //server position for us is used for reconciliation doPlayerReconciliation(player, playerState); } else { //server position for others is authoritative (enqueue in positionBuffer since we smooth this with interpolation later) playerState.LocalRenderTimestamp = Time.time * 1000f; player.positionBuffer.Enqueue(playerState); } } else { Debug.Log($"ERROR got update for player (id:{playerState.Id}, {playerState.Position.X}, {playerState.Position.Y}) that we don't know about!"); } } } } }