From a1c728d207c58f26346abf37a20cfef7862806d3 Mon Sep 17 00:00:00 2001 From: Regalis Date: Wed, 9 Mar 2016 16:49:56 +0200 Subject: [PATCH] Networking bugfixes & improvements: - fixed server not sending kill-events when a monster dies - some interpolation when correcting character positions - physicsbody position lerping improvements - sending AICharacter Dir instead of TargetDir --- .../Source/Characters/AI/EnemyAIController.cs | 2 +- Subsurface/Source/Characters/AICharacter.cs | 6 +- .../Animation/FishAnimController.cs | 20 +++-- .../Source/Characters/Animation/Ragdoll.cs | 75 +++++++++++++------ Subsurface/Source/Characters/Character.cs | 4 +- Subsurface/Source/Events/MonsterEvent.cs | 2 +- .../Source/Events/Quests/MonsterQuest.cs | 2 +- Subsurface/Source/Items/CharacterInventory.cs | 11 ++- .../Items/Components/Holdable/Pickable.cs | 46 ++++++------ Subsurface/Source/Networking/GameClient.cs | 2 +- Subsurface/Source/Networking/NetworkEvent.cs | 22 ++---- .../Source/Networking/ReliableSender.cs | 4 +- Subsurface/Source/Physics/PhysicsBody.cs | 25 ++++--- 13 files changed, 126 insertions(+), 95 deletions(-) diff --git a/Subsurface/Source/Characters/AI/EnemyAIController.cs b/Subsurface/Source/Characters/AI/EnemyAIController.cs index 9de16e3aa..7d02affb6 100644 --- a/Subsurface/Source/Characters/AI/EnemyAIController.cs +++ b/Subsurface/Source/Characters/AI/EnemyAIController.cs @@ -616,7 +616,7 @@ namespace Barotrauma steeringManager.WanderAngle = wanderAngle; if (targetID > 0) targetEntity = Entity.FindEntityByID(targetID) as IDamageable; - updateTargetsTimer = UpdateTargetsInterval; + //updateTargetsTimer = UpdateTargetsInterval; } } diff --git a/Subsurface/Source/Characters/AICharacter.cs b/Subsurface/Source/Characters/AICharacter.cs index f1a8c3c1d..f188c9b89 100644 --- a/Subsurface/Source/Characters/AICharacter.cs +++ b/Subsurface/Source/Characters/AICharacter.cs @@ -108,7 +108,7 @@ namespace Barotrauma return true; case NetworkEventType.EntityUpdate: - message.Write(AnimController.TargetDir == Direction.Right); + message.Write(AnimController.Dir > 0.0f); message.WriteRangedSingle(MathHelper.Clamp(AnimController.TargetMovement.X, -1.0f, 1.0f), -1.0f, 1.0f, 8); message.WriteRangedSingle(MathHelper.Clamp(AnimController.TargetMovement.Y, -1.0f, 1.0f), -1.0f, 1.0f, 8); @@ -216,8 +216,8 @@ namespace Barotrauma AnimController.TargetDir = (targetDir) ? Direction.Right : Direction.Left; AnimController.TargetMovement = targetMovement; - AnimController.RefLimb.body.TargetPosition = - AnimController.EstimateCurrPosition(pos, (float)(NetTime.Now) - sendingTime); + AnimController.RefLimb.body.TargetPosition = pos; + //AnimController.EstimateCurrPosition(pos, (float)(NetTime.Now) - sendingTime); if (inSub) { diff --git a/Subsurface/Source/Characters/Animation/FishAnimController.cs b/Subsurface/Source/Characters/Animation/FishAnimController.cs index 9b8b81393..99e100c4c 100644 --- a/Subsurface/Source/Characters/Animation/FishAnimController.cs +++ b/Subsurface/Source/Characters/Animation/FishAnimController.cs @@ -84,15 +84,19 @@ namespace Barotrauma if (flip) { - //targetDir = (movement.X > 0.0f) ? Direction.Right : Direction.Left; - if (targetMovement.X > 0.1f && targetMovement.X > Math.Abs(targetMovement.Y) * 0.5f) + if (!character.IsNetworkPlayer) { - TargetDir = Direction.Right; - } - else if (targetMovement.X < -0.1f && targetMovement.X < -Math.Abs(targetMovement.Y) * 0.5f) - { - TargetDir = Direction.Left; + //targetDir = (movement.X > 0.0f) ? Direction.Right : Direction.Left; + if (targetMovement.X > 0.1f && targetMovement.X > Math.Abs(targetMovement.Y) * 0.5f) + { + TargetDir = Direction.Right; + } + else if (targetMovement.X < -0.1f && targetMovement.X < -Math.Abs(targetMovement.Y) * 0.5f) + { + TargetDir = Direction.Left; + } } + } else { @@ -117,7 +121,7 @@ namespace Barotrauma if (TargetDir != dir) { - if (flipTimer>1.0f) + if (flipTimer>1.0f || character.IsNetworkPlayer) { Flip(); if (flip) Mirror(); diff --git a/Subsurface/Source/Characters/Animation/Ragdoll.cs b/Subsurface/Source/Characters/Animation/Ragdoll.cs index 9db051c04..d6c3ba420 100644 --- a/Subsurface/Source/Characters/Animation/Ragdoll.cs +++ b/Subsurface/Source/Characters/Animation/Ragdoll.cs @@ -713,7 +713,7 @@ namespace Barotrauma } } - public void SetPosition(Vector2 simPosition) + public void SetPosition(Vector2 simPosition, bool lerp = false) { Vector2 moveAmount = simPosition - refLimb.SimPosition; @@ -721,18 +721,28 @@ namespace Barotrauma { if (limb==refLimb) { - limb.body.SetTransform(simPosition, limb.Rotation); + if (lerp) + { + limb.body.TargetPosition = simPosition; + } + else + { + limb.body.SetTransform(simPosition, limb.Rotation); + } continue; } + //check visibility from the new position of RefLimb to the new position of this limb Vector2 movePos = limb.SimPosition + moveAmount; TrySetLimbPosition(limb, simPosition, movePos); + + } } - protected void TrySetLimbPosition(Limb limb, Vector2 original, Vector2 simPosition) + protected void TrySetLimbPosition(Limb limb, Vector2 original, Vector2 simPosition, bool lerp = false) { if (original == simPosition) return; @@ -746,7 +756,14 @@ namespace Barotrauma movePos = original + ((simPosition - original) * Submarine.LastPickedFraction * 0.9f); } - limb.body.SetTransform(movePos, limb.Rotation); + if (lerp) + { + limb.body.TargetPosition = movePos; + } + else + { + limb.body.SetTransform(movePos, limb.Rotation); + } } public void SetRotation(float rotation) @@ -813,12 +830,15 @@ namespace Barotrauma } else { + + 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 { @@ -843,11 +863,11 @@ namespace Barotrauma 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); + 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)) + 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); } @@ -855,35 +875,42 @@ namespace Barotrauma //newCorrectionMovement.X = Math.Max(newCorrectionMovement.X, 0.5f) * Math.Sign(newCorrectionMovement.X); correctionMovement = Vector2.Lerp(correctionMovement, newCorrectionMovement, 0.5f); - + if (Math.Abs(correctionMovement.Y) < 0.1f) correctionMovement.Y = 0.0f; } } if (resetAll) { - System.Diagnostics.Debug.WriteLine("reset ragdoll limb positions"); + System.Diagnostics.Debug.WriteLine("reset ragdoll limb positions"); - SetPosition(refLimb.body.TargetPosition); + if (this is HumanoidAnimController) + { + + foreach (Limb limb in Limbs) + { + if (limb != refLimb) limb.body.TargetPosition = limb.body.SimPosition + diff; + limb.body.MoveToTargetPosition(Vector2.Distance(limb.SimPosition, limb.body.TargetPosition) < 10.0f); + + limb.body.LinearVelocity = Vector2.Zero; + limb.body.AngularVelocity = 0.0f; + } + } + else + { + + SetPosition(refLimb.body.TargetPosition); + + } //if (character is AICharacter) SetRotation(refLimb.body.TargetRotation); - foreach (Limb limb in Limbs) - { - limb.body.LinearVelocity = Vector2.Zero; - limb.body.AngularVelocity = 0.0f; - // if (limb.body.TargetPosition == Vector2.Zero) - // { - // limb.body.SetTransform(limb.body.SimPosition + diff, limb.body.Rotation); - // continue; - // } - // limb.body.LinearVelocity = limb.body.TargetVelocity; - // limb.body.AngularVelocity = limb.body.TargetAngularVelocity; - - // limb.body.SetTransform(limb.body.TargetPosition, limb.body.TargetRotation); - // limb.body.TargetPosition = Vector2.Zero; - } + //foreach (Limb limb in Limbs) + //{ + // limb.body.LinearVelocity = Vector2.Zero; + // limb.body.AngularVelocity = 0.0f; + //} } } diff --git a/Subsurface/Source/Characters/Character.cs b/Subsurface/Source/Characters/Character.cs index 5df6caa1f..c6fa76fac 100644 --- a/Subsurface/Source/Characters/Character.cs +++ b/Subsurface/Source/Characters/Character.cs @@ -1098,7 +1098,7 @@ namespace Barotrauma if (this == controlled) return; - if (IsNetworkPlayer) + if (IsNetworkPlayer && info!=null) { Vector2 namePos = new Vector2(pos.X, pos.Y - 120.0f) - GUI.Font.MeasureString(Info.Name) * 0.5f; spriteBatch.DrawString(GUI.Font, Info.Name, namePos - new Vector2(1.0f, 1.0f), Color.Black); @@ -1318,7 +1318,7 @@ namespace Barotrauma //if it's an ai Character, only let the server kill it else if (GameMain.Server != null && this is AICharacter) { - new NetworkEvent(NetworkEventType.KillCharacter, ID, true, causeOfDeath); + new NetworkEvent(NetworkEventType.KillCharacter, ID, false, causeOfDeath); } //don't kill the Character unless received a message about the Character dying else if (!isNetworkMessage) diff --git a/Subsurface/Source/Events/MonsterEvent.cs b/Subsurface/Source/Events/MonsterEvent.cs index 3550ede4d..5ff7d7286 100644 --- a/Subsurface/Source/Events/MonsterEvent.cs +++ b/Subsurface/Source/Events/MonsterEvent.cs @@ -49,7 +49,7 @@ namespace Barotrauma position.X += Rand.Range(-0.5f, 0.5f, false); position.Y += Rand.Range(-0.5f, 0.5f, false); - monsters[i] = Character.Create(characterFile, position); + monsters[i] = Character.Create(characterFile, position, null, GameMain.Client != null); } } diff --git a/Subsurface/Source/Events/Quests/MonsterQuest.cs b/Subsurface/Source/Events/Quests/MonsterQuest.cs index 6a7882541..8440aefcb 100644 --- a/Subsurface/Source/Events/Quests/MonsterQuest.cs +++ b/Subsurface/Source/Events/Quests/MonsterQuest.cs @@ -29,7 +29,7 @@ namespace Barotrauma { Vector2 position = level.GetRandomInterestingPosition(true, true); - monster = Character.Create(monsterFile, position); + monster = Character.Create(monsterFile, position, null, GameMain.Client != null); monster.Enabled = false; radarPosition = monster.Position; } diff --git a/Subsurface/Source/Items/CharacterInventory.cs b/Subsurface/Source/Items/CharacterInventory.cs index 6e0318434..942c41c08 100644 --- a/Subsurface/Source/Items/CharacterInventory.cs +++ b/Subsurface/Source/Items/CharacterInventory.cs @@ -415,16 +415,15 @@ namespace Barotrauma Item item = Entity.FindEntityByID(itemId) as Item; if (item == null) continue; - Inventory existingInventory = item.ParentInventory; + //item already in the right slot, no need to do anything + if (Items[i] == item) continue; - if (Items[i] != item && Items[i] != null) Items[i].Drop(character, false); + //some other item already in the slot -> drop it + if (Items[i] != null) Items[i].Drop(character, false); if (TryPutItem(item, i, false, false)) { - if (droppedItems.Contains(item)) - { - droppedItems.Remove(item); - } + if (droppedItems.Contains(item)) droppedItems.Remove(item); } } } diff --git a/Subsurface/Source/Items/Components/Holdable/Pickable.cs b/Subsurface/Source/Items/Components/Holdable/Pickable.cs index 57320290c..c288f88e8 100644 --- a/Subsurface/Source/Items/Components/Holdable/Pickable.cs +++ b/Subsurface/Source/Items/Components/Holdable/Pickable.cs @@ -195,33 +195,35 @@ namespace Barotrauma.Items.Components if (picker == null) { picker = dropper; - - //foreach (Character c in Character.characterList) - //{ - // if (c.Inventory == null) continue; - // if (c.Inventory.FindIndex(item) == -1) continue; - - // picker = c; - // break; - //} } - if (picker == null || picker.Inventory == null) return; + Vector2 bodyDropPos = Vector2.Zero; - DropConnectedWires(picker); - - item.Submarine = picker.Submarine; - - if (item.body!= null && !item.body.Enabled) + if (picker == null || picker.Inventory == null) { - Limb rightHand = picker.AnimController.GetLimb(LimbType.RightHand); - - item.SetTransform(rightHand.SimPosition, 0.0f); - item.body.Enabled = true; - + if (item.ParentInventory!=null && item.ParentInventory.Owner!=null) + { + bodyDropPos = item.ParentInventory.Owner.SimPosition; + } + } + else + { + DropConnectedWires(picker); + + item.Submarine = picker.Submarine; + + Limb rightHand = picker.AnimController.GetLimb(LimbType.RightHand); + bodyDropPos = rightHand.SimPosition; + + picker.Inventory.RemoveItem(item); + picker = null; + } + + if (item.body != null && !item.body.Enabled) + { + item.SetTransform(bodyDropPos, 0.0f); + item.body.Enabled = true; } - picker.Inventory.RemoveItem(item); - picker = null; } } diff --git a/Subsurface/Source/Networking/GameClient.cs b/Subsurface/Source/Networking/GameClient.cs index f03b2f480..191a74f80 100644 --- a/Subsurface/Source/Networking/GameClient.cs +++ b/Subsurface/Source/Networking/GameClient.cs @@ -778,7 +778,7 @@ namespace Barotrauma.Networking Vector2 position = new Vector2(message.ReadFloat(), message.ReadFloat()); - var character = Character.Create(configPath, position); + var character = Character.Create(configPath, position, null, true); if (character != null) character.ID = id; } diff --git a/Subsurface/Source/Networking/NetworkEvent.cs b/Subsurface/Source/Networking/NetworkEvent.cs index c980b87c6..889fbea3e 100644 --- a/Subsurface/Source/Networking/NetworkEvent.cs +++ b/Subsurface/Source/Networking/NetworkEvent.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using Lidgren.Network; using System; +using System.Linq; namespace Barotrauma.Networking { @@ -101,31 +102,24 @@ namespace Barotrauma.Networking get { return eventType; } } - public NetworkEvent(ushort id, bool isClient) - : this(NetworkEventType.EntityUpdate, id, isClient) + public NetworkEvent(ushort id, bool allowClientSend) + : this(NetworkEventType.EntityUpdate, id, allowClientSend) { } - public NetworkEvent(NetworkEventType type, ushort id, bool isClient, object data = null) + public NetworkEvent(NetworkEventType type, ushort id, bool allowClientSend, object data = null) { - if (isClient) - { - if (GameMain.Server != null && GameMain.Server.Character == null) return; - } - else - { - if (GameMain.Server == null) return; - } - + if (!allowClientSend && GameMain.Server != null) return; + eventType = type; if (overridePrevious[(int)type]) { - if (Events.Find(e => e.id == id && e.eventType == type) != null) return; + if (Events.Any(e => e.id == id && e.eventType == type)) return; } this.id = id; - isClientEvent = isClient; + isClientEvent = allowClientSend; this.data = data; diff --git a/Subsurface/Source/Networking/ReliableSender.cs b/Subsurface/Source/Networking/ReliableSender.cs index 27059b237..8469366e0 100644 --- a/Subsurface/Source/Networking/ReliableSender.cs +++ b/Subsurface/Source/Networking/ReliableSender.cs @@ -355,10 +355,10 @@ namespace Barotrauma.Networking.ReliableMessages return; } - if (lastMessageID > messageId && Math.Abs((int)lastMessageID - (int)messageId) < ushort.MaxValue / 2) + if (messageId < lastMessageID && Math.Abs((int)lastMessageID - (int)messageId) < ushort.MaxValue / 2) { //shouldn't happen: we have somehow received messages that the other end hasn't sent - Debug.WriteLine("Reliable message error - recipient last sent: " + messageId + " (current count " + lastMessageID + ")"); + Debug.WriteLine("Received id update message: " + messageId + ": ignoring, already received (" + lastMessageID + ")"); return; } diff --git a/Subsurface/Source/Physics/PhysicsBody.cs b/Subsurface/Source/Physics/PhysicsBody.cs index e255f2e98..39cec79c4 100644 --- a/Subsurface/Source/Physics/PhysicsBody.cs +++ b/Subsurface/Source/Physics/PhysicsBody.cs @@ -51,6 +51,8 @@ namespace Barotrauma //flipped horizontally if the Character holding it turns around) float dir; + Vector2 offsetFromTargetPos; + public Vector2 TargetPosition { get { return targetPosition; } @@ -301,37 +303,40 @@ namespace Barotrauma { if (targetPosition == Vector2.Zero) { - diffToTargetPos = Vector2.Zero; + offsetFromTargetPos = Vector2.Zero; return; } - if (lerp) diffToTargetPos = targetPosition - body.Position; + if (lerp) + { + offsetFromTargetPos = targetPosition - (body.Position - offsetFromTargetPos); + prevPosition = targetPosition; + } body.SetTransform(targetPosition, targetRotation); body.LinearVelocity = targetVelocity; body.AngularVelocity = targetAngularVelocity; - targetPosition = Vector2.Zero; + targetPosition = Vector2.Zero; } - Vector2 diffToTargetPos; public void UpdateDrawPosition() { - drawPosition = Physics.Interpolate(prevPosition, body.Position) - diffToTargetPos; + drawPosition = Physics.Interpolate(prevPosition, body.Position) - offsetFromTargetPos; drawPosition = ConvertUnits.ToDisplayUnits(drawPosition); drawRotation = Physics.Interpolate(prevRotation, body.Rotation); - if (diffToTargetPos == Vector2.Zero) return; + if (offsetFromTargetPos == Vector2.Zero) return; - float diff = diffToTargetPos.Length(); + float diff = offsetFromTargetPos.Length(); if (diff < 0.05f) { - diffToTargetPos = Vector2.Zero; + offsetFromTargetPos = Vector2.Zero; } else { - diffToTargetPos -= (diffToTargetPos / diff) * 0.05f; + offsetFromTargetPos = Vector2.Lerp(offsetFromTargetPos, Vector2.Zero, 0.1f); } } @@ -410,7 +415,7 @@ namespace Barotrauma return; targetPosition = newTargetPos; - targetVelocity = newTargetVel; + TargetVelocity = newTargetVel; targetRotation = newTargetRotation; targetAngularVelocity = newTargetAngularVel;