diff --git a/Subsurface/Properties/AssemblyInfo.cs b/Subsurface/Properties/AssemblyInfo.cs index 43a9e6164..61b22b369 100644 --- a/Subsurface/Properties/AssemblyInfo.cs +++ b/Subsurface/Properties/AssemblyInfo.cs @@ -31,5 +31,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.2.2.0")] -[assembly: AssemblyFileVersion("0.2.2.0")] +[assembly: AssemblyVersion("0.0.0.1")] +[assembly: AssemblyFileVersion("0.0.0.1")] diff --git a/Subsurface/Source/Characters/Character.cs b/Subsurface/Source/Characters/Character.cs index a36ce84b1..98fc9dfe8 100644 --- a/Subsurface/Source/Characters/Character.cs +++ b/Subsurface/Source/Characters/Character.cs @@ -1107,18 +1107,22 @@ namespace Barotrauma GetInputState(InputType.Up) || GetInputState(InputType.Down) || GetInputState(InputType.ActionHeld) || - GetInputState(InputType.SecondaryHeld)); + GetInputState(InputType.SecondaryHeld)) || LargeUpdateTimer <= 0; + + message.Write(hasInputs); - message.Write(hasInputs || LargeUpdateTimer <= 0); + if (!hasInputs) return true; message.Write((float)NetTime.Now); // Write byte = move direction //message.WriteRangedSingle(MathHelper.Clamp(AnimController.TargetMovement.X, -10.0f, 10.0f), -10.0f, 10.0f, 8); //message.WriteRangedSingle(MathHelper.Clamp(AnimController.TargetMovement.Y, -10.0f, 10.0f), -10.0f, 10.0f, 8); - + message.Write(keys[(int)InputType.ActionHeld].Dequeue); - message.Write(keys[(int)InputType.SecondaryHeld].Dequeue); + + bool secondaryHeld = keys[(int)InputType.SecondaryHeld].Dequeue; + message.Write(secondaryHeld); message.Write(keys[(int)InputType.Left].Dequeue); message.Write(keys[(int)InputType.Right].Dequeue); @@ -1128,8 +1132,15 @@ namespace Barotrauma message.Write(keys[(int)InputType.Run].Dequeue); - message.Write(cursorPosition.X); - message.Write(cursorPosition.Y); + if (secondaryHeld) + { + message.Write(cursorPosition.X); + message.Write(cursorPosition.Y); + } + else + { + message.Write(AnimController.Dir > 0.0f); + } message.Write(LargeUpdateTimer <= 0); @@ -1271,21 +1282,36 @@ namespace Barotrauma keys[(int)InputType.Run].State = runState; + float dir = 1.0f; bool isLargeUpdate; try { - cursorPos = new Vector2( - message.ReadFloat(), - message.ReadFloat()); + if (secondaryKeyState) + { + cursorPos = new Vector2( + message.ReadFloat(), + message.ReadFloat()); + } + else + { + dir = message.ReadBoolean() ? 1.0f : -1.0f; + } + isLargeUpdate = message.ReadBoolean(); } catch { return; } - - cursorPosition = cursorPos; + if (secondaryKeyState) + { + cursorPosition = cursorPos; + } + else + { + cursorPos = Position + new Vector2(1000.0f, 0.0f) * dir; + } if (isLargeUpdate) { diff --git a/Subsurface/Source/Items/Components/Door.cs b/Subsurface/Source/Items/Components/Door.cs index 1d4efc24e..922236ad0 100644 --- a/Subsurface/Source/Items/Components/Door.cs +++ b/Subsurface/Source/Items/Components/Door.cs @@ -238,8 +238,6 @@ namespace Barotrauma.Items.Components public override void Update(float deltaTime, Camera cam) { - convexHull.Enabled = true; - if (convexHull2 != null) convexHull2.Enabled = true; if (!isStuck) { OpenState += deltaTime * ((isOpen) ? 2.0f : -2.0f); @@ -253,8 +251,6 @@ namespace Barotrauma.Items.Components public override void UpdateBroken(float deltaTime, Camera cam) { body.Enabled = false; - convexHull.Enabled = false; - if (convexHull2 != null) convexHull2.Enabled = false; linkedGap.Open = 1.0f; } diff --git a/Subsurface/Source/Networking/GameClient.cs b/Subsurface/Source/Networking/GameClient.cs index 26ef45aa0..e282a0878 100644 --- a/Subsurface/Source/Networking/GameClient.cs +++ b/Subsurface/Source/Networking/GameClient.cs @@ -116,7 +116,7 @@ namespace Barotrauma.Networking } - updateInterval = new TimeSpan(0, 0, 0, 0, 100); + updateInterval = new TimeSpan(0, 0, 0, 0, 150); // Set timer to tick every 50ms //update = new System.Timers.Timer(50); @@ -302,7 +302,7 @@ namespace Barotrauma.Networking { base.Update(deltaTime); - if (!connected || updateTimer > DateTime.Now) return; + if (!connected) return; if (client.ConnectionStatus == NetConnectionStatus.Disconnected) { @@ -323,6 +323,21 @@ namespace Barotrauma.Networking reconnectBox = null; } + try + { + CheckServerMessages(); + } + catch (Exception e) + { +#if DEBUG + DebugConsole.ThrowError("Error while receiving message from server", e); +#endif + } + + reliableChannel.Update(deltaTime); + + if (updateTimer > DateTime.Now) return; + if (myCharacter != null) { if (myCharacter.IsDead) @@ -335,8 +350,6 @@ namespace Barotrauma.Networking new NetworkEvent(myCharacter.ID, true); } } - - reliableChannel.Update(deltaTime); foreach (NetworkEvent networkEvent in NetworkEvent.events) { @@ -353,11 +366,10 @@ namespace Barotrauma.Networking NetworkEvent.events.Clear(); - try + if (PlayerInput.KeyDown(Microsoft.Xna.Framework.Input.Keys.B)) { - CheckServerMessages(); + SendChatMessage("asdfsdaf"); } - catch { } // Update current time updateTimer = DateTime.Now + updateInterval; diff --git a/Subsurface/Source/Networking/GameServer.cs b/Subsurface/Source/Networking/GameServer.cs index 19fb18d3d..e049978d0 100644 --- a/Subsurface/Source/Networking/GameServer.cs +++ b/Subsurface/Source/Networking/GameServer.cs @@ -65,8 +65,8 @@ namespace Barotrauma.Networking netStats = new NetStats(); #if DEBUG - config.SimulatedLoss = 0.2f; - config.SimulatedRandomLatency = 0.6f; + config.SimulatedLoss = 0.05f; + config.SimulatedRandomLatency = 0.3f; config.SimulatedDuplicatesChance = 0.05f; config.SimulatedMinimumLatency = 0.1f; #endif @@ -618,15 +618,13 @@ namespace Barotrauma.Networking { if (NetworkEvent.events.Count == 0) return; - List recipients = new List(); - foreach (Client c in connectedClients) - { - if (c.character == null) continue; - //if (networkEvent.Type == NetworkEventType.UpdateEntity && - // Vector2.Distance(e.SimPosition, c.character.SimPosition) > NetConfig.UpdateEntityDistance) continue; + List recipients = connectedClients.FindAll(c => c.character != null); - recipients.Add(c.Connection); - } + List recipientConnections = new List(); + foreach (Client c in recipients) + { + recipientConnections.Add(c.Connection); + } if (recipients.Count == 0) return; @@ -635,17 +633,38 @@ namespace Barotrauma.Networking Entity e = Entity.FindEntityByID(networkEvent.ID); if (e == null) continue; - NetOutgoingMessage message = server.CreateMessage(); - message.Write((byte)PacketTypes.NetworkEvent); - //if (!networkEvent.IsClient) continue; - - networkEvent.FillData(message); - - if (server.ConnectionsCount>0) + if (networkEvent.IsImportant) { - server.SendMessage(message, recipients, - (networkEvent.IsImportant) ? NetDeliveryMethod.Unreliable : NetDeliveryMethod.ReliableUnordered, 0); - } + foreach (Client c in recipients) + { + ReliableMessage reliableMessage = c.ReliableChannel.CreateMessage(); + reliableMessage.InnerMessage.Write((byte)PacketTypes.NetworkEvent); + + if (!networkEvent.FillData(reliableMessage.InnerMessage)) + { + break; + } + + c.ReliableChannel.SendMessage(reliableMessage, c.Connection); + } + } + else + { + NetOutgoingMessage message = server.CreateMessage(); + message.Write((byte)PacketTypes.NetworkEvent); + //if (!networkEvent.IsClient) continue; + + if (!networkEvent.FillData(message)) + { + continue; + } + + if (server.ConnectionsCount>0) + { + server.SendMessage(message, recipientConnections, + (networkEvent.IsImportant) ? NetDeliveryMethod.Unreliable : NetDeliveryMethod.ReliableUnordered, 0); + } + } } NetworkEvent.events.Clear(); } diff --git a/Subsurface/Source/Networking/NetConfig.cs b/Subsurface/Source/Networking/NetConfig.cs index c9eb500a0..d957dda9b 100644 --- a/Subsurface/Source/Networking/NetConfig.cs +++ b/Subsurface/Source/Networking/NetConfig.cs @@ -22,5 +22,10 @@ namespace Barotrauma.Networking public const float AllowedRagdollDistance = 0.1f; public const float DeleteDisconnectedTime = 10.0f; + + public const float AckInterval = 0.2f; + public const float RerequestInterval = 0.2f; + + public const int ResendAttempts = 8; } } diff --git a/Subsurface/Source/Networking/NetStats.cs b/Subsurface/Source/Networking/NetStats.cs index 709796eb6..371d75d2a 100644 --- a/Subsurface/Source/Networking/NetStats.cs +++ b/Subsurface/Source/Networking/NetStats.cs @@ -18,9 +18,8 @@ namespace Barotrauma.Networking private Graph[] graphs; - private Queue[] valueQueue; - - private float[] lastValues; + private float[] totalValue; + private float[] lastValue; const float UpdateInterval = 1.0f; float updateTimer; @@ -29,23 +28,21 @@ namespace Barotrauma.Networking { graphs = new Graph[3]; - valueQueue = new Queue[3]; + totalValue = new float[3]; + lastValue = new float[3]; for (int i = 0; i < 3; i++ ) - { - valueQueue[i] = new Queue(); + { graphs[i] = new Graph(); - } - - lastValues = new float[3]; + } } public void AddValue(NetStatType statType, float value) { - float valueChange = value - lastValues[(int)statType]; + float valueChange = value - lastValue[(int)statType]; - valueQueue[(int)statType].Enqueue(valueChange); + totalValue[(int)statType] += valueChange; - lastValues[(int)statType] = value; + lastValue[(int)statType] = value; } public void Update(float deltaTime) @@ -56,17 +53,12 @@ namespace Barotrauma.Networking for (int i = 0; i<3; i++) { - int valueCount = valueQueue[i].Count; - float totalValue = 0.0f; - while (valueQueue[i].Count>1) - { - totalValue += valueQueue[i].Dequeue(); - } - graphs[i].Update(valueCount==0 ? 0.0f : totalValue/valueCount); + graphs[i].Update(totalValue[i] * 10.0f); + totalValue[i] = 0.0f; } - updateTimer = UpdateInterval; + updateTimer = UpdateInterval/10.0f; } public void Draw(SpriteBatch spriteBatch, Rectangle rect) diff --git a/Subsurface/Source/Networking/ReliableSender.cs b/Subsurface/Source/Networking/ReliableSender.cs index a16ed7b1d..ba210d44d 100644 --- a/Subsurface/Source/Networking/ReliableSender.cs +++ b/Subsurface/Source/Networking/ReliableSender.cs @@ -56,7 +56,7 @@ namespace Barotrauma.Networking.ReliableMessages internal class ReliableSender { - private List messageBuffer; + private Dictionary messageBuffer; private ushort messageCount; @@ -66,11 +66,15 @@ namespace Barotrauma.Networking.ReliableMessages private float ackTimer; + private float ackInterval; + public ReliableSender(NetPeer sender) { this.sender = sender; - - messageBuffer = new List(); + + messageCount = ushort.MaxValue - 5; + + messageBuffer = new Dictionary(); } public ReliableMessage CreateMessage() @@ -81,14 +85,42 @@ namespace Barotrauma.Networking.ReliableMessages NetOutgoingMessage message = sender.CreateMessage(); var reliableMessage = new ReliableMessage(message, messageCount); - messageBuffer.Add(reliableMessage); + messageBuffer.Add(reliableMessage.ID, reliableMessage); message.Write((byte)PacketTypes.ReliableMessage); message.Write(messageCount); - while (messageBuffer.Count>100) + int bufferSize=100; + if (messageBuffer.Count>bufferSize) { - messageBuffer.RemoveAt(0); + + int end = messageCount-bufferSize; + int start = end - (messageBuffer.Count - bufferSize); + + if (start<=0) + { + int wrappedStart = start + ushort.MaxValue; + if (wrappedStart==0) wrappedStart = ushort.MaxValue; + int wrappedEnd = end + ushort.MaxValue; + if (wrappedEnd==0) wrappedEnd = ushort.MaxValue; + + for (ushort i = (ushort)wrappedStart; i <= (ushort)wrappedEnd; i++) + { + messageBuffer.Remove(i); + if (i == ushort.MaxValue) break; + Debug.WriteLine("removing message " + i); + } + } + + for (ushort i = (ushort)Math.Max(start,1); i <= (ushort)Math.Max(end,1); i++) + { + messageBuffer.Remove(i); + if (i == ushort.MaxValue) break; + Debug.WriteLine("removing message " + i); + } + + + } return reliableMessage; @@ -98,6 +130,9 @@ namespace Barotrauma.Networking.ReliableMessages public void SendMessage(ReliableMessage message, NetConnection connection) { + ackInterval = 0.0f; + ackTimer = connection.AverageRoundtripTime; + message.SaveInnerMessage(); sender.SendMessage(message.InnerMessage, connection, NetDeliveryMethod.Unreliable, 0); @@ -105,14 +140,6 @@ namespace Barotrauma.Networking.ReliableMessages recipient = connection; } - // NetOutgoingMessage msg = server.CreateMessage(); - //reliableSender.CreateMessage(msg); - //msg.Write((byte)PacketTypes.Chatmessage); - //msg.Write((byte)type); - //msg.Write(message); - - - public void HandleResendRequest(NetIncomingMessage inc) { ushort messageId = inc.ReadUInt16(); @@ -124,15 +151,16 @@ namespace Barotrauma.Networking.ReliableMessages private void ResendMessage(ushort messageId, NetConnection connection) { - ReliableMessage message = messageBuffer.Find(m => m.ID == messageId); - if (message == null) return; + ReliableMessage message; + if (!messageBuffer.TryGetValue(messageId, out message)) return; Debug.WriteLine("resending " + messageId); - NetOutgoingMessage resendMessage = sender.CreateMessage(); message.RestoreInnerMessage(resendMessage); + ackTimer = connection.AverageRoundtripTime; + sender.SendMessage(resendMessage, connection, NetDeliveryMethod.Unreliable); } @@ -152,7 +180,8 @@ namespace Barotrauma.Networking.ReliableMessages sender.SendMessage(message, recipient, NetDeliveryMethod.Unreliable); - ackTimer = Math.Max(recipient.AverageRoundtripTime, 1.0f); + ackTimer = Math.Max(recipient.AverageRoundtripTime, NetConfig.AckInterval+ackInterval); + ackInterval += 0.1f; } } @@ -160,6 +189,7 @@ namespace Barotrauma.Networking.ReliableMessages { ushort lastMessageID; + Queue missingMessageIds; Dictionary missingMessages; private NetPeer receiver; @@ -169,38 +199,49 @@ namespace Barotrauma.Networking.ReliableMessages public ReliableReceiver(NetPeer receiver) { this.receiver = receiver; + + lastMessageID = ushort.MaxValue - 5; missingMessages = new Dictionary(); + missingMessageIds = new Queue(); } public void Update(float deltaTime) { - foreach (var message in missingMessages.Where(m => m.Value.ResendRequestsSent>10).ToList()) + foreach (var message in missingMessages.Where(m => m.Value.ResendRequestsSent > NetConfig.ResendAttempts).ToList()) { missingMessages.Remove(message.Key); } + int bufferSize = 20; + + while (missingMessageIds.Count>bufferSize) + { + ushort id = missingMessageIds.Dequeue(); + + missingMessages.Remove(id); + } + foreach (KeyValuePair valuePair in missingMessages) { MissingMessage missingMessage = valuePair.Value; missingMessage.ResendTimer -= deltaTime; - if (missingMessage.ResendRequestsSent==0 - || missingMessage.ResendTimer<0.0f) - { - Debug.WriteLine("rerequest "+missingMessage.ID+" (try #"+missingMessage.ResendRequestsSent+")"); + if (missingMessage.ResendTimer > 0.0f) continue; + + Debug.WriteLine("rerequest "+missingMessage.ID+" (try #"+missingMessage.ResendRequestsSent+")"); - NetOutgoingMessage resendRequest = receiver.CreateMessage(); - resendRequest.Write((byte)PacketTypes.ResendRequest); - resendRequest.Write(missingMessage.ID); + NetOutgoingMessage resendRequest = receiver.CreateMessage(); + resendRequest.Write((byte)PacketTypes.ResendRequest); + resendRequest.Write(missingMessage.ID); - receiver.SendMessage(resendRequest, recipient, NetDeliveryMethod.Unreliable); + receiver.SendMessage(resendRequest, recipient, NetDeliveryMethod.Unreliable); - missingMessage.ResendTimer = Math.Max(recipient.AverageRoundtripTime, 0.2f); - missingMessage.ResendRequestsSent++; - } + missingMessage.ResendTimer = Math.Max(recipient.AverageRoundtripTime, NetConfig.RerequestInterval); + missingMessage.ResendRequestsSent++; + } } @@ -217,23 +258,15 @@ namespace Barotrauma.Networking.ReliableMessages if (Math.Abs((int)lastMessageID - (int)id) > ushort.MaxValue / 2) { //id wrapped around and we missed some messages in between, rerequest them - if (lastMessageID<=ushort.MaxValue && id>1) + if (lastMessageID>ushort.MaxValue/2 && id>=1) { for (ushort i = (ushort)(Math.Min(lastMessageID, (ushort)(ushort.MaxValue-1)) + 1); i < ushort.MaxValue; i++) { - //message already marked as missed, continue - if (missingMessages.ContainsKey((i))) continue; - - Debug.WriteLine("added " + i + " to missed"); - missingMessages.Add(i, new MissingMessage((ushort)i)); + QueueMissingMessage(i); } for (ushort i = 1; i < id; i++) { - //message already marked as missed, continue - if (missingMessages.ContainsKey((i))) continue; - - Debug.WriteLine("added " + i + " to missed"); - missingMessages.Add(i, new MissingMessage((ushort)i)); + QueueMissingMessage(i); } lastMessageID = id; @@ -246,11 +279,7 @@ namespace Barotrauma.Networking.ReliableMessages } else { - if (missingMessages.ContainsKey(id)) - { - Debug.WriteLine("remove " + id + " from missed"); - missingMessages.Remove(id); - } + RemoveMissingMessage(id); } } else @@ -259,11 +288,7 @@ namespace Barotrauma.Networking.ReliableMessages { for (ushort i = (ushort)(lastMessageID+1); i < id; i++ ) { - //message already marked as missed, continue - if (missingMessages.ContainsKey((i))) continue; - - Debug.WriteLine("added "+i+" to missed"); - missingMessages.Add(i, new MissingMessage((ushort)i)); + QueueMissingMessage(i); } } @@ -275,11 +300,7 @@ namespace Barotrauma.Networking.ReliableMessages } else { - if (missingMessages.ContainsKey(id)) - { - Debug.WriteLine("remove "+id+" from missed"); - missingMessages.Remove(id); - } + RemoveMissingMessage(id); } lastMessageID = Math.Max(lastMessageID, id); @@ -288,21 +309,39 @@ namespace Barotrauma.Networking.ReliableMessages return true; } + private void QueueMissingMessage(ushort id) + { + //message already marked as missed, continue + if (missingMessages.ContainsKey(id)) return; + + Debug.WriteLine("added " + id + " to missed"); + missingMessages.Add(id, new MissingMessage(id)); + + missingMessageIds.Enqueue(id); + } + + private void RemoveMissingMessage(ushort id) + { + if (!missingMessages.ContainsKey(id)) return; + + Debug.WriteLine("remove " + id + " from missed"); + missingMessages.Remove(id); + } + public void HandleAckMessage(NetIncomingMessage inc) { - int messageId = inc.ReadUInt16(); + ushort messageId = inc.ReadUInt16(); recipient = inc.SenderConnection; //id matches, all good if (messageId == lastMessageID) { - Debug.WriteLine("Received ack message: " + messageId + ", all good"); return; } - if (lastMessageID > messageId) + if (lastMessageID > messageId && 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 + ")"); @@ -315,11 +354,12 @@ namespace Barotrauma.Networking.ReliableMessages { for (ushort i = (ushort)Math.Min((int)lastMessageID + 1, ushort.MaxValue); i <= ushort.MaxValue; i++) { - - if (!missingMessages.ContainsKey(i)) missingMessages.Add(i, new MissingMessage(i)); + if (i == ushort.MaxValue && lastMessageID == ushort.MaxValue) break; + if (!missingMessages.ContainsKey(i)) missingMessages.Add(i, new MissingMessage(i)); + if (i == ushort.MaxValue) break; } - for (ushort i = 1; i <= messageId; i++) + for (ushort i = 1; i < messageId; i++) { if (!missingMessages.ContainsKey(i)) missingMessages.Add(i, new MissingMessage(i)); } @@ -328,22 +368,12 @@ namespace Barotrauma.Networking.ReliableMessages { for (ushort i = (ushort)Math.Min((int)lastMessageID+1, ushort.MaxValue); i <= messageId; i++) { - - if (!missingMessages.ContainsKey(i)) missingMessages.Add(i, new MissingMessage(i)); + if (!missingMessages.ContainsKey(i)) missingMessages.Add(i, new MissingMessage(i)); + if (i == ushort.MaxValue) break; } } - - - - // Debug.WriteLine("received recent request for msg id " + messageId); - - //ReliableMessage message = messageBuffer.Find(m => m.ID == messageId); - //if (message == null) return; - - //NetOutgoingMessage resendMessage = sender.CreateMessage(); - //message.RestoreInnerMessage(resendMessage); - - //sender.SendMessage(resendMessage, inc.SenderConnection, NetDeliveryMethod.Unreliable); + + lastMessageID = messageId; } } diff --git a/Subsurface/Source/Screens/MainMenuScreen.cs b/Subsurface/Source/Screens/MainMenuScreen.cs index b50efa362..44201ed49 100644 --- a/Subsurface/Source/Screens/MainMenuScreen.cs +++ b/Subsurface/Source/Screens/MainMenuScreen.cs @@ -389,7 +389,7 @@ namespace Barotrauma GUI.Draw((float)deltaTime, spriteBatch, null); - spriteBatch.DrawString(GUI.Font, "Barotrauma v"+GameMain.Version, new Vector2(10, GameMain.GraphicsHeight-20), Color.White); + spriteBatch.DrawString(GUI.Font, "Barotrauma chat lag test build", new Vector2(10, GameMain.GraphicsHeight-20), Color.White); spriteBatch.End(); } diff --git a/Subsurface/Source/Sounds/Sound.cs b/Subsurface/Source/Sounds/Sound.cs index cf7fdccd6..4039fad10 100644 --- a/Subsurface/Source/Sounds/Sound.cs +++ b/Subsurface/Source/Sounds/Sound.cs @@ -5,6 +5,7 @@ using FarseerPhysics; using FarseerPhysics.Dynamics; using Microsoft.Xna.Framework; using Barotrauma.Sounds; +using System; namespace Barotrauma { @@ -41,7 +42,14 @@ namespace Barotrauma if (oggSound == null) { - oggSound = OggSound.Load(file); + try + { + oggSound = OggSound.Load(file); + } + catch (Exception e) + { + DebugConsole.ThrowError("Failed to load sound "+file+"!", e); + } ALHelper.Check(); } diff --git a/Subsurface_Solution.v12.suo b/Subsurface_Solution.v12.suo index 45a8ce9b4..0d1731dae 100644 Binary files a/Subsurface_Solution.v12.suo and b/Subsurface_Solution.v12.suo differ