From de203cc424854ff00d74da09b7a7a75d558b2b03 Mon Sep 17 00:00:00 2001 From: Regalis Date: Wed, 19 Oct 2016 00:15:21 +0300 Subject: [PATCH] - a WIP attempt to correct the position of the controlled character based on updates from the server - fixed server not being able to move character controllers - renamed IsNetworkPlayer -> IsRemotePlayer --- .../Animation/FishAnimController.cs | 4 +- .../Animation/HumanoidAnimController.cs | 14 +- .../Source/Characters/Animation/Ragdoll.cs | 126 ++++++------------ Subsurface/Source/Characters/Character.cs | 43 ++++-- Subsurface/Source/DebugConsole.cs | 2 +- .../Items/Components/Holdable/Pickable.cs | 2 +- .../Items/Components/Machines/Controller.cs | 2 +- Subsurface/Source/Networking/GameServer.cs | 2 +- 8 files changed, 87 insertions(+), 108 deletions(-) diff --git a/Subsurface/Source/Characters/Animation/FishAnimController.cs b/Subsurface/Source/Characters/Animation/FishAnimController.cs index 362ed8c1b..32d40e46e 100644 --- a/Subsurface/Source/Characters/Animation/FishAnimController.cs +++ b/Subsurface/Source/Characters/Animation/FishAnimController.cs @@ -113,7 +113,7 @@ namespace Barotrauma if (mirror || !inWater) { - if (!character.IsNetworkPlayer) + if (!character.IsRemotePlayer) { //targetDir = (movement.X > 0.0f) ? Direction.Right : Direction.Left; if (targetMovement.X > 0.1f && targetMovement.X > Math.Abs(targetMovement.Y) * 0.5f) @@ -153,7 +153,7 @@ namespace Barotrauma if (TargetDir != dir) { - if (flipTimer>1.0f || character.IsNetworkPlayer) + if (flipTimer>1.0f || character.IsRemotePlayer) { Flip(); if (mirror || !inWater) Mirror(); diff --git a/Subsurface/Source/Characters/Animation/HumanoidAnimController.cs b/Subsurface/Source/Characters/Animation/HumanoidAnimController.cs index 22e0becb8..fda35715c 100644 --- a/Subsurface/Source/Characters/Animation/HumanoidAnimController.cs +++ b/Subsurface/Source/Characters/Animation/HumanoidAnimController.cs @@ -84,7 +84,7 @@ namespace Barotrauma } - if (!character.IsNetworkPlayer || true) + if (!character.IsRemotePlayer || true) { //re-enable collider if (!collider.FarseerBody.Enabled) @@ -215,7 +215,7 @@ namespace Barotrauma } aiming = false; - if (character.IsNetworkPlayer) collider.LinearVelocity = Vector2.Zero; + if (character.IsRemotePlayer && GameMain.Server == null) collider.LinearVelocity = Vector2.Zero; } @@ -312,7 +312,7 @@ namespace Barotrauma //if (LowestLimb == null) return; - if (onGround && !character.IsNetworkPlayer) + if (onGround && (!character.IsRemotePlayer || GameMain.Server != null)) { collider.LinearVelocity = new Vector2( movement.X, @@ -535,7 +535,7 @@ namespace Barotrauma rotation = MathHelper.ToDegrees(rotation); if (rotation < 0.0f) rotation += 360; - if (!character.IsNetworkPlayer && !aiming) + if (!character.IsRemotePlayer && !aiming) { if (rotation > 20 && rotation < 170) TargetDir = Direction.Left; @@ -608,7 +608,7 @@ namespace Barotrauma movement.Y = movement.Y - (surfaceLimiter - 1.0f) * 0.01f; } - if (!character.IsNetworkPlayer) + if (!character.IsRemotePlayer || GameMain.Server != null) { collider.LinearVelocity = Vector2.Lerp(collider.LinearVelocity, movement * swimSpeed, movementLerp); } @@ -730,7 +730,7 @@ namespace Barotrauma MoveLimb(torso, new Vector2(ladderSimPos.X - 0.27f * Dir, collider.SimPosition.Y+0.5f), 10.5f); MoveLimb(waist, new Vector2(ladderSimPos.X - 0.35f * Dir, collider.SimPosition.Y+0.4f), 10.5f); - if (!character.IsNetworkPlayer) + if (!character.IsRemotePlayer) { collider.MoveToPos(new Vector2(ladderSimPos.X - 0.2f * Dir, collider.SimPosition.Y), 10.5f); } @@ -802,7 +802,7 @@ namespace Barotrauma trigger = character.SelectedConstruction.TransformTrigger(trigger); bool notClimbing = false; - if (character.IsNetworkPlayer) + if (character.IsRemotePlayer) { notClimbing = character.IsKeyDown(InputType.Left) || character.IsKeyDown(InputType.Right); } diff --git a/Subsurface/Source/Characters/Animation/Ragdoll.cs b/Subsurface/Source/Characters/Animation/Ragdoll.cs index 470750c6e..14cc04bb9 100644 --- a/Subsurface/Source/Characters/Animation/Ragdoll.cs +++ b/Subsurface/Source/Characters/Animation/Ragdoll.cs @@ -458,7 +458,7 @@ namespace Barotrauma } else if (f1.Body == collider.FarseerBody) { - if (!character.IsNetworkPlayer || GameMain.Server != null) + if (!character.IsRemotePlayer || GameMain.Server != null) { if (impact > 8.0f) { @@ -1050,6 +1050,47 @@ namespace Barotrauma private void UpdateNetPlayerPosition(float deltaTime) { if (character.MemPos.Count < 2) return; + + if (character == GameMain.NetworkMember.Character) + { + PosInfo serverPos = character.MemPos.Last(); + + //this doesn't work correctly, because the delay caused by the 150ms update interval isn't taken into account + //and the server may have unprocessed inputs in memInput (causing a 0-1s delay) + float localizedTimestamp = serverPos.Timestamp - GameMain.Client.ServerConnection.AverageRoundtripTime / 2; + + int index = 0; + for (index = 0; index < character.MemLocalPos.Count; index++) + { + if (character.MemLocalPos[index].Timestamp > localizedTimestamp) + { + break; + } + } + + if (index > character.MemLocalPos.Count-1 || index < 1) return; + + //local positions before and after the timestamp + PosInfo prevLocalPos = character.MemLocalPos[index - 1]; + PosInfo nextLocalPos = character.MemLocalPos[index]; + + Vector2 localPos = Vector2.Lerp( + prevLocalPos.Position, + nextLocalPos.Position, + (localizedTimestamp - prevLocalPos.Timestamp) / (nextLocalPos.Timestamp - prevLocalPos.Timestamp)); + + + if (Vector2.Distance(localPos, serverPos.Position) > 0.5f) + { + //collider.SetTransform(collider.SimPosition + (pos.Position - remotePos), collider.Rotation); + collider.SetTransform(serverPos.Position, collider.Rotation); + } + + if (character.MemLocalPos.Count > 120) character.MemLocalPos.RemoveRange(0, character.MemLocalPos.Count - 120); + character.MemPos.Clear(); + + return; + } PosInfo prev = character.MemPos[0]; PosInfo next = character.MemPos[1]; @@ -1082,89 +1123,6 @@ namespace Barotrauma t = 0.0f; character.MemPos.RemoveAt(0); } - - //if (refLimb.body.TargetPosition == Vector2.Zero) - //{ - // correctionMovement = Vector2.Zero; - // return; - //} - - ////if the limb is closer than alloweddistance, just ignore the difference - //float allowedDistance = NetConfig.AllowedRagdollDistance * ((inWater) ? 2.0f : 1.0f); - - //if (currentHull == null) - //{ - // var overLappingHull = Hull.FindHull(ConvertUnits.ToDisplayUnits(refLimb.body.TargetPosition), null, true); - - // if (overLappingHull != null) - // { - // Submarine.PickBody(refLimb.SimPosition, refLimb.body.TargetPosition, null, Physics.CollisionWall); - - // refLimb.body.TargetPosition = refLimb.SimPosition + (refLimb.body.TargetPosition - refLimb.SimPosition) * Submarine.LastPickedFraction * 0.9f; - // } - //} - - - //float dist = Vector2.Distance(collider.SimPosition, character.MemPos[0].Position); - - ////if the limb is further away than resetdistance, all limbs are immediately snapped to their targetpositions - //bool resetAll = dist > NetConfig.ResetRagdollDistance; - - //Vector2 diff = (refLimb.body.TargetPosition - refLimb.body.SimPosition); - - //if (diff == Vector2.Zero || diff.Length() < allowedDistance) - //{ - // refLimb.body.TargetPosition = Vector2.Zero; - // foreach (Limb limb in Limbs) - // { - // limb.body.TargetPosition = Vector2.Zero; - // } - - // correctionMovement = Vector2.Zero; - // return; - //} - - //if (resetAll) - //{ - // System.Diagnostics.Debug.WriteLine("reset ragdoll limb positions"); - - // SetPosition(refLimb.body.TargetPosition, dist < 10.0f); - - // return; - //} - - //if (inWater) - //{ - // if (targetMovement.LengthSquared() > 0.01f) - // { - // correctionMovement = - // Vector2.Lerp(targetMovement, Vector2.Normalize(diff) * MathHelper.Clamp(dist * 5.0f, 0.1f, 5.0f), 0.2f); - - // } - // else - // { - // refLimb.body.LinearVelocity = Vector2.Lerp( - // refLimb.LinearVelocity, - // Vector2.Normalize(diff) * MathHelper.Clamp(dist, 0.0f, 5.0f), - // 0.2f); - // } - //} - //else - //{ - // //clamp the magnitude of the correction movement between 0.5f - 5.0f - // Vector2 newCorrectionMovement = Vector2.Normalize(diff) * MathHelper.Clamp(dist * 2.0f, 0.5f, 5.0f); - - // //heading in the right direction -> use the \"normal\" movement if it's faster than correctionMovement - // //i.e. the character is close to the targetposition but the character is still running - // if (Math.Sign(targetMovement.X) == Math.Sign(newCorrectionMovement.X)) - // { - // newCorrectionMovement.X = Math.Max(Math.Abs(targetMovement.X), Math.Abs(newCorrectionMovement.X)) * Math.Sign(targetMovement.X); - // } - - // correctionMovement = Vector2.Lerp(correctionMovement, newCorrectionMovement, 0.5f); - - // if (Math.Abs(correctionMovement.Y) < 0.1f) correctionMovement.Y = 0.0f; - //} } public virtual Vector2 EstimateCurrPosition(Vector2 prevPosition, float timePassed) diff --git a/Subsurface/Source/Characters/Character.cs b/Subsurface/Source/Characters/Character.cs index e023e19e9..b569c1c0b 100644 --- a/Subsurface/Source/Characters/Character.cs +++ b/Subsurface/Source/Characters/Character.cs @@ -45,6 +45,9 @@ namespace Barotrauma List memMousePos = new List(); List memPos = new List(); + + List memLocalPos = new List(); + //the Character that the player is currently controlling private static Character controlled; @@ -84,7 +87,7 @@ namespace Barotrauma public Hull PreviousHull = null; public Hull CurrentHull = null; - public readonly bool IsNetworkPlayer; + public readonly bool IsRemotePlayer; private CharacterInventory inventory; @@ -225,6 +228,12 @@ namespace Barotrauma get { return memPos; } } + + public List MemLocalPos + { + get { return memLocalPos; } + } + public Character ClosestCharacter { get { return closestCharacter; } @@ -459,12 +468,12 @@ namespace Barotrauma public delegate void OnDeathHandler(Character character, CauseOfDeath causeOfDeath); public OnDeathHandler OnDeath; - public static Character Create(CharacterInfo characterInfo, Vector2 position, bool isNetworkPlayer = false, bool hasAi=true) + public static Character Create(CharacterInfo characterInfo, Vector2 position, bool isRemotePlayer = false, bool hasAi=true) { - return Create(characterInfo.File, position, characterInfo, isNetworkPlayer, hasAi); + return Create(characterInfo.File, position, characterInfo, isRemotePlayer, hasAi); } - public static Character Create(string file, Vector2 position, CharacterInfo characterInfo = null, bool isNetworkPlayer = false, bool hasAi=true) + public static Character Create(string file, Vector2 position, CharacterInfo characterInfo = null, bool isRemotePlayer = false, bool hasAi=true) { #if LINUX if (!System.IO.File.Exists(file)) @@ -497,7 +506,7 @@ namespace Barotrauma if (file != humanConfigFile) { - var enemyCharacter = new AICharacter(file, position, characterInfo, isNetworkPlayer); + var enemyCharacter = new AICharacter(file, position, characterInfo, isRemotePlayer); var ai = new EnemyAIController(enemyCharacter, file); enemyCharacter.SetAI(ai); @@ -507,7 +516,7 @@ namespace Barotrauma } else if (hasAi) { - var aiCharacter = new AICharacter(file, position, characterInfo, isNetworkPlayer); + var aiCharacter = new AICharacter(file, position, characterInfo, isRemotePlayer); var ai = new HumanAIController(aiCharacter); aiCharacter.SetAI(ai); @@ -516,13 +525,13 @@ namespace Barotrauma return aiCharacter; } - var character = new Character(file, position, characterInfo, isNetworkPlayer); + var character = new Character(file, position, characterInfo, isRemotePlayer); character.minHealth = -100.0f; return character; } - protected Character(string file, Vector2 position, CharacterInfo characterInfo = null, bool isNetworkPlayer = false) + protected Character(string file, Vector2 position, CharacterInfo characterInfo = null, bool isRemotePlayer = false) : base(null) { @@ -539,7 +548,7 @@ namespace Barotrauma hudProgressBars = new Dictionary(); - IsNetworkPlayer = isNetworkPlayer; + IsRemotePlayer = isRemotePlayer; oxygen = 100.0f; oxygenAvailable = 100.0f; @@ -927,7 +936,7 @@ namespace Barotrauma } - if (IsNetworkPlayer) + if (IsRemotePlayer) { foreach (Key key in keys) { @@ -1123,6 +1132,18 @@ namespace Barotrauma } cam.OffsetAmount = MathHelper.Lerp(cam.OffsetAmount, (Submarine == null ? 400.0f : 250.0f)+pressureEffect, 0.05f); } + + if (GameMain.NetworkMember != null && GameMain.NetworkMember.Character == this) + { + if (memLocalPos.Count == 0 || NetTime.Now > memLocalPos.Last().Timestamp + 0.1f) + { + memLocalPos.Add( + new PosInfo( + SimPosition, + AnimController.Dir > 0.0f ? Direction.Right : Direction.Left, + (float)NetTime.Now)); + } + } cursorPosition = cam.ScreenToWorld(PlayerInput.MousePosition); if (AnimController.CurrentHull != null && AnimController.CurrentHull.Submarine != null) @@ -1944,7 +1965,7 @@ namespace Barotrauma CharacterInfo ch = new CharacterInfo(configPath, newName, isFemale ? Gender.Female : Gender.Male, jobPrefab); ch.HeadSpriteId = headSpriteID; - character = Character.Create(configPath, position, ch, true, hasAi); + character = Character.Create(configPath, position, ch, GameMain.Client.MyCharacterID != id, hasAi); character.ID = id; if (GameMain.Client.MyCharacterID == id) diff --git a/Subsurface/Source/DebugConsole.cs b/Subsurface/Source/DebugConsole.cs index 38250136e..f3bae7522 100644 --- a/Subsurface/Source/DebugConsole.cs +++ b/Subsurface/Source/DebugConsole.cs @@ -427,7 +427,7 @@ namespace Barotrauma characterIndex = -1; } - var matchingCharacters = Character.CharacterList.FindAll(c => !c.IsNetworkPlayer && c.Name.ToLowerInvariant() == characterName); + var matchingCharacters = Character.CharacterList.FindAll(c => !c.IsRemotePlayer && c.Name.ToLowerInvariant() == characterName); if (!matchingCharacters.Any()) { diff --git a/Subsurface/Source/Items/Components/Holdable/Pickable.cs b/Subsurface/Source/Items/Components/Holdable/Pickable.cs index 480914585..4c3a0d16a 100644 --- a/Subsurface/Source/Items/Components/Holdable/Pickable.cs +++ b/Subsurface/Source/Items/Components/Holdable/Pickable.cs @@ -141,7 +141,7 @@ namespace Barotrauma.Items.Components StopPicking(picker); - if (!picker.IsNetworkPlayer) OnPicked(picker); + if (!picker.IsRemotePlayer) OnPicked(picker); yield return CoroutineStatus.Success; } diff --git a/Subsurface/Source/Items/Components/Machines/Controller.cs b/Subsurface/Source/Items/Components/Machines/Controller.cs index a3a1a84a2..ae10f6b79 100644 --- a/Subsurface/Source/Items/Components/Machines/Controller.cs +++ b/Subsurface/Source/Items/Components/Machines/Controller.cs @@ -191,7 +191,7 @@ namespace Barotrauma.Items.Components cam.OffsetAmount = MathHelper.Lerp(cam.OffsetAmount, (focusTarget as Item).Prefab.OffsetOnSelected, deltaTime*10.0f); } - if (!character.IsNetworkPlayer || character.ViewTarget == focusTarget) + if (!character.IsRemotePlayer || character.ViewTarget == focusTarget) { item.SendSignal(0, ToolBox.Vector2ToString(character.CursorWorldPosition), "position_out"); } diff --git a/Subsurface/Source/Networking/GameServer.cs b/Subsurface/Source/Networking/GameServer.cs index 33cdb898c..eb7e41aac 100644 --- a/Subsurface/Source/Networking/GameServer.cs +++ b/Subsurface/Source/Networking/GameServer.cs @@ -648,7 +648,7 @@ namespace Barotrauma.Networking foreach (Character character in Character.CharacterList) { - if (character is AICharacter || character == c.Character) continue; + if (character is AICharacter) continue; outmsg.Write((byte)ServerNetObject.CHARACTER_POSITION); character.ServerWrite(outmsg, c);