"ReliableMessages", networkevents aren't sent if FillNetworkEvent fails

This commit is contained in:
Regalis
2015-10-19 22:49:38 +03:00
parent c3d1b971dd
commit 5f07d4b0c9
22 changed files with 604 additions and 76 deletions
+1 -1
View File
@@ -45,7 +45,7 @@
<DebugType>pdbonly</DebugType> <DebugType>pdbonly</DebugType>
<Optimize>true</Optimize> <Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath> <OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants> <DefineConstants>TRACE;USE_RELEASE_STATISTICS</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+1
View File
@@ -100,6 +100,7 @@
<Compile Include="Source\Map\SubmarineHull.cs" /> <Compile Include="Source\Map\SubmarineHull.cs" />
<Compile Include="Source\Networking\NetConfig.cs" /> <Compile Include="Source\Networking\NetConfig.cs" />
<Compile Include="Source\Networking\NetStats.cs" /> <Compile Include="Source\Networking\NetStats.cs" />
<Compile Include="Source\Networking\ReliableSender.cs" />
<Compile Include="Source\Particles\ParticleEmitter.cs" /> <Compile Include="Source\Particles\ParticleEmitter.cs" />
<Compile Include="Source\Screens\ServerListScreen.cs" /> <Compile Include="Source\Screens\ServerListScreen.cs" />
<Compile Include="Source\Utils\Rand.cs" /> <Compile Include="Source\Utils\Rand.cs" />
+2 -2
View File
@@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.2.0.0")] [assembly: AssemblyVersion("0.2.2.0")]
[assembly: AssemblyFileVersion("0.2.0.0")] [assembly: AssemblyFileVersion("0.2.2.0")]
+5 -2
View File
@@ -83,11 +83,11 @@ namespace Barotrauma
return result; return result;
} }
public override void FillNetworkData(NetworkEventType type, NetOutgoingMessage message, object data) public override bool FillNetworkData(NetworkEventType type, NetOutgoingMessage message, object data)
{ {
if (type == NetworkEventType.KillCharacter) if (type == NetworkEventType.KillCharacter)
{ {
return; return true;
} }
message.Write((float)NetTime.Now); message.Write((float)NetTime.Now);
@@ -127,6 +127,9 @@ namespace Barotrauma
LargeUpdateTimer = Math.Max(0, LargeUpdateTimer - 1); LargeUpdateTimer = Math.Max(0, LargeUpdateTimer - 1);
} }
return true;
} }
public override void ReadNetworkData(NetworkEventType type, NetIncomingMessage message) public override void ReadNetworkData(NetworkEventType type, NetIncomingMessage message)
+7 -5
View File
@@ -1084,21 +1084,21 @@ namespace Barotrauma
} }
} }
public override void FillNetworkData(NetworkEventType type, NetOutgoingMessage message, object data) public override bool FillNetworkData(NetworkEventType type, NetOutgoingMessage message, object data)
{ {
if (type == NetworkEventType.PickItem) if (type == NetworkEventType.PickItem)
{ {
message.Write((int)data); message.Write((int)data);
return; return true;
} }
else if (type== NetworkEventType.SelectCharacter) else if (type== NetworkEventType.SelectCharacter)
{ {
message.Write((int)data); message.Write((int)data);
return; return true;
} }
else if (type == NetworkEventType.KillCharacter) else if (type == NetworkEventType.KillCharacter)
{ {
return; return true;
} }
var hasInputs = var hasInputs =
@@ -1160,7 +1160,9 @@ namespace Barotrauma
message.Write(AnimController.RefLimb.SimPosition.Y); message.Write(AnimController.RefLimb.SimPosition.Y);
LargeUpdateTimer = Math.Max(0, LargeUpdateTimer-1); LargeUpdateTimer = Math.Max(0, LargeUpdateTimer-1);
} }
return true;
} }
public override void ReadNetworkData(NetworkEventType type, NetIncomingMessage message) public override void ReadNetworkData(NetworkEventType type, NetIncomingMessage message)
+5
View File
@@ -325,6 +325,11 @@ namespace Barotrauma
//Ragdoll.DebugDraw = !Ragdoll.DebugDraw; //Ragdoll.DebugDraw = !Ragdoll.DebugDraw;
GameMain.DebugDraw = !GameMain.DebugDraw; GameMain.DebugDraw = !GameMain.DebugDraw;
break; break;
case "netstats":
if (GameMain.Server == null) return;
GameMain.Server.ShowNetStats = !GameMain.Server.ShowNetStats;
break;
default: default:
NewMessage("Command not found", Color.Red); NewMessage("Command not found", Color.Red);
break; break;
@@ -613,6 +613,8 @@ namespace Barotrauma
{ {
do do
{ {
if (enemy == null) break;
enemy.Health = 50.0f; enemy.Health = 50.0f;
enemy.AIController.State = AIController.AiState.None; enemy.AIController.State = AIController.AiState.None;
+3 -1
View File
@@ -279,12 +279,14 @@ namespace Barotrauma
spriteBatch.DrawString(GUI.Font, (int)item.Condition + " %", new Vector2(rect.X + rect.Width / 2, rect.Y + rect.Height / 2), Color.Red); spriteBatch.DrawString(GUI.Font, (int)item.Condition + " %", new Vector2(rect.X + rect.Width / 2, rect.Y + rect.Height / 2), Color.Red);
} }
public override void FillNetworkData(NetworkEventType type, NetOutgoingMessage message, object data) public override bool FillNetworkData(NetworkEventType type, NetOutgoingMessage message, object data)
{ {
for (int i = 0; i<capacity; i++) for (int i = 0; i<capacity; i++)
{ {
message.Write((items[i] == null) ? -1 : items[i].ID); message.Write((items[i] == null) ? -1 : items[i].ID);
} }
return true;
} }
public override void ReadNetworkData(NetworkEventType type, NetIncomingMessage message) public override void ReadNetworkData(NetworkEventType type, NetIncomingMessage message)
+4 -2
View File
@@ -1156,7 +1156,7 @@ namespace Barotrauma
new NetworkEvent(NetworkEventType.UpdateComponent, ID, isClient, index); new NetworkEvent(NetworkEventType.UpdateComponent, ID, isClient, index);
} }
public override void FillNetworkData(NetworkEventType type, NetOutgoingMessage message, object data) public override bool FillNetworkData(NetworkEventType type, NetOutgoingMessage message, object data)
{ {
message.Write(condition); message.Write(condition);
@@ -1172,7 +1172,7 @@ namespace Barotrauma
case NetworkEventType.UpdateComponent: case NetworkEventType.UpdateComponent:
int componentIndex = (int)data; int componentIndex = (int)data;
if (componentIndex < 0 || componentIndex >= components.Count) return; if (componentIndex < 0 || componentIndex >= components.Count) return false;
message.Write((byte)componentIndex); message.Write((byte)componentIndex);
components[componentIndex].FillNetworkData(type, message); components[componentIndex].FillNetworkData(type, message);
@@ -1214,6 +1214,8 @@ namespace Barotrauma
break; break;
} }
return true;
} }
public override void ReadNetworkData(NetworkEventType type, NetIncomingMessage message) public override void ReadNetworkData(NetworkEventType type, NetIncomingMessage message)
+4 -1
View File
@@ -64,7 +64,10 @@ namespace Barotrauma
dictionary.Add(id, this); dictionary.Add(id, this);
} }
public virtual void FillNetworkData(NetworkEventType type, NetOutgoingMessage message, object data) { } public virtual bool FillNetworkData(NetworkEventType type, NetOutgoingMessage message, object data)
{
return false;
}
public virtual void ReadNetworkData(NetworkEventType type, NetIncomingMessage message) { } public virtual void ReadNetworkData(NetworkEventType type, NetIncomingMessage message) { }
/// <summary> /// <summary>
+3 -1
View File
@@ -471,9 +471,11 @@ namespace Barotrauma
h.ID = int.Parse(element.Attribute("ID").Value); h.ID = int.Parse(element.Attribute("ID").Value);
} }
public override void FillNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetOutgoingMessage message, object data) public override bool FillNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetOutgoingMessage message, object data)
{ {
message.Write(volume); message.Write(volume);
return true;
} }
public override void ReadNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetIncomingMessage message) public override void ReadNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetIncomingMessage message)
+4 -2
View File
@@ -636,7 +636,7 @@ namespace Barotrauma
} }
public override void FillNetworkData(NetworkEventType type, NetOutgoingMessage message, object data) public override bool FillNetworkData(NetworkEventType type, NetOutgoingMessage message, object data)
{ {
int sectionIndex = 0; int sectionIndex = 0;
byte byteIndex = 0; byte byteIndex = 0;
@@ -648,12 +648,14 @@ namespace Barotrauma
} }
catch catch
{ {
return; return false;
} }
message.Write((float)NetTime.Now); message.Write((float)NetTime.Now);
message.Write(byteIndex); message.Write(byteIndex);
message.Write(sections[sectionIndex].damage); message.Write(sections[sectionIndex].damage);
return true;
} }
public override void ReadNetworkData(NetworkEventType type, NetIncomingMessage message) public override void ReadNetworkData(NetworkEventType type, NetIncomingMessage message)
+6 -2
View File
@@ -149,7 +149,7 @@ namespace Barotrauma
} }
base.Remove(); base.Remove();
ID = -1; ID = -5;
} }
//drawing ---------------------------------------------------- //drawing ----------------------------------------------------
@@ -378,14 +378,18 @@ namespace Barotrauma
Level.Loaded.Move(-amount); Level.Loaded.Move(-amount);
} }
public override void FillNetworkData(Networking.NetworkEventType type, NetOutgoingMessage message, object data) public override bool FillNetworkData(Networking.NetworkEventType type, NetOutgoingMessage message, object data)
{ {
if (subBody == null) return false;
message.Write((float)NetTime.Now); message.Write((float)NetTime.Now);
message.Write(Position.X); message.Write(Position.X);
message.Write(Position.Y); message.Write(Position.Y);
message.Write(Speed.X); message.Write(Speed.X);
message.Write(Speed.Y); message.Write(Speed.Y);
return true;
} }
public override void ReadNetworkData(Networking.NetworkEventType type, NetIncomingMessage message) public override void ReadNetworkData(Networking.NetworkEventType type, NetIncomingMessage message)
+31 -8
View File
@@ -3,6 +3,7 @@ using System.Diagnostics;
using Lidgren.Network; using Lidgren.Network;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using System.Collections.Generic; using System.Collections.Generic;
using Barotrauma.Networking.ReliableMessages;
namespace Barotrauma.Networking namespace Barotrauma.Networking
{ {
@@ -12,6 +13,8 @@ namespace Barotrauma.Networking
private GUIMessageBox reconnectBox; private GUIMessageBox reconnectBox;
private ReliableChannel reliableChannel;
private bool connected; private bool connected;
private int myID; private int myID;
@@ -34,6 +37,7 @@ namespace Barotrauma.Networking
otherClients = new List<Client>(); otherClients = new List<Client>();
} }
public void ConnectToServer(string hostIP, string password = "") public void ConnectToServer(string hostIP, string password = "")
@@ -63,6 +67,7 @@ namespace Barotrauma.Networking
#if DEBUG #if DEBUG
config.SimulatedLoss = 0.1f; config.SimulatedLoss = 0.1f;
config.SimulatedMinimumLatency = 0.3f; config.SimulatedMinimumLatency = 0.3f;
config.SimulatedRandomLatency = 0.5f;
#endif #endif
config.DisableMessageType(NetIncomingMessageType.DebugMessage | NetIncomingMessageType.WarningMessage | NetIncomingMessageType.Receipt config.DisableMessageType(NetIncomingMessageType.DebugMessage | NetIncomingMessageType.WarningMessage | NetIncomingMessageType.Receipt
@@ -70,6 +75,7 @@ namespace Barotrauma.Networking
// Create new client, with previously created configs // Create new client, with previously created configs
client = new NetClient(config); client = new NetClient(config);
reliableChannel = new ReliableChannel(client);
NetOutgoingMessage outmsg = client.CreateMessage(); NetOutgoingMessage outmsg = client.CreateMessage();
client.Start(); client.Start();
@@ -329,6 +335,8 @@ namespace Barotrauma.Networking
new NetworkEvent(myCharacter.ID, true); new NetworkEvent(myCharacter.ID, true);
} }
} }
reliableChannel.Update(deltaTime);
foreach (NetworkEvent networkEvent in NetworkEvent.events) foreach (NetworkEvent networkEvent in NetworkEvent.events)
{ {
@@ -368,8 +376,17 @@ namespace Barotrauma.Networking
while ((inc = client.ReadMessage()) != null) while ((inc = client.ReadMessage()) != null)
{ {
if (inc.MessageType != NetIncomingMessageType.Data) continue; if (inc.MessageType != NetIncomingMessageType.Data) continue;
switch (inc.ReadByte()) //todo: exception handling
byte packetType = inc.ReadByte();
if (packetType == (byte)PacketTypes.ReliableMessage)
{
if (!reliableChannel.CheckMessage(inc)) continue;
packetType = inc.ReadByte();
}
switch (packetType)
{ {
case (byte)PacketTypes.StartGame: case (byte)PacketTypes.StartGame:
if (gameStarted) continue; if (gameStarted) continue;
@@ -427,6 +444,12 @@ namespace Barotrauma.Networking
new GUIMessageBox("You are the Traitor!", "Your secret task is to assassinate " + targetName + "!"); new GUIMessageBox("You are the Traitor!", "Your secret task is to assassinate " + targetName + "!");
break;
case (byte)PacketTypes.ResendRequest:
reliableChannel.HandleResendRequest(inc);
break;
case (byte)PacketTypes.Ack:
reliableChannel.HandleAckMessage(inc);
break; break;
} }
} }
@@ -652,13 +675,13 @@ namespace Barotrauma.Networking
//AddChatMessage(message); //AddChatMessage(message);
type = (gameStarted && myCharacter != null && myCharacter.IsDead) ? ChatMessageType.Dead : ChatMessageType.Default; type = (gameStarted && myCharacter != null && myCharacter.IsDead) ? ChatMessageType.Dead : ChatMessageType.Default;
ReliableMessage msg = reliableChannel.CreateMessage();
msg.InnerMessage.Write((byte)PacketTypes.Chatmessage);
msg.InnerMessage.Write((byte)type);
msg.InnerMessage.Write(message);
NetOutgoingMessage msg = client.CreateMessage(); reliableChannel.SendMessage(msg, client.ServerConnection);
msg.Write((byte)PacketTypes.Chatmessage);
msg.Write((byte)type);
msg.Write(message);
client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered);
} }
/// <summary> /// <summary>
+79 -42
View File
@@ -5,11 +5,13 @@ using System.Diagnostics;
using Lidgren.Network; using Lidgren.Network;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using RestSharp; using RestSharp;
using Barotrauma.Networking.ReliableMessages;
namespace Barotrauma.Networking namespace Barotrauma.Networking
{ {
class GameServer : NetworkMember class GameServer : NetworkMember
{ {
public bool ShowNetStats;
public List<Client> connectedClients = new List<Client>(); public List<Client> connectedClients = new List<Client>();
@@ -64,7 +66,7 @@ namespace Barotrauma.Networking
#if DEBUG #if DEBUG
config.SimulatedLoss = 0.2f; config.SimulatedLoss = 0.2f;
config.SimulatedMinimumLatency = 0.3f; config.SimulatedRandomLatency = 0.6f;
config.SimulatedDuplicatesChance = 0.05f; config.SimulatedDuplicatesChance = 0.05f;
config.SimulatedMinimumLatency = 0.1f; config.SimulatedMinimumLatency = 0.1f;
#endif #endif
@@ -96,9 +98,9 @@ namespace Barotrauma.Networking
} }
catch (Exception e) catch (Exception e)
{ {
DebugConsole.ThrowError("Couldn't start the server", e); DebugConsole.ThrowError("Couldn't start the server", e);
} }
if (config.EnableUPnP) if (config.EnableUPnP)
{ {
@@ -225,7 +227,7 @@ namespace Barotrauma.Networking
public override void Update(float deltaTime) public override void Update(float deltaTime)
{ {
if (GameMain.DebugDraw) netStats.Update(deltaTime); if (ShowNetStats) netStats.Update(deltaTime);
if (!started) return; if (!started) return;
@@ -268,8 +270,13 @@ namespace Barotrauma.Networking
disconnectedClients.RemoveAt(i); disconnectedClients.RemoveAt(i);
} }
NetIncomingMessage inc = server.ReadMessage(); foreach (Client c in connectedClients)
if (inc != null) {
c.ReliableChannel.Update(deltaTime);
}
NetIncomingMessage inc = null;
while ((inc = server.ReadMessage()) != null)
{ {
try try
{ {
@@ -277,7 +284,11 @@ namespace Barotrauma.Networking
} }
catch catch
{ {
#if DEBUG
DebugConsole.ThrowError("Failed to read incoming message");
#endif
continue;
} }
} }
@@ -416,7 +427,26 @@ namespace Barotrauma.Networking
break; break;
case NetIncomingMessageType.Data: case NetIncomingMessageType.Data:
switch (inc.ReadByte()) Client dataSender = connectedClients.Find(c => c.Connection == inc.SenderConnection);
if (dataSender == null) return;
byte packetType = 0;
try
{
packetType = inc.ReadByte();
}
catch
{
return;
}
if (packetType == (byte)PacketTypes.ReliableMessage)
{
if (!dataSender.ReliableChannel.CheckMessage(inc)) return;
packetType = inc.ReadByte();
}
switch (packetType)
{ {
case (byte)PacketTypes.NetworkEvent: case (byte)PacketTypes.NetworkEvent:
if (!gameStarted) break; if (!gameStarted) break;
@@ -452,6 +482,13 @@ namespace Barotrauma.Networking
case (byte)PacketTypes.CharacterInfo: case (byte)PacketTypes.CharacterInfo:
ReadCharacterData(inc); ReadCharacterData(inc);
break; break;
case (byte)PacketTypes.ResendRequest:
dataSender.ReliableChannel.HandleResendRequest(inc);
break;
case (byte)PacketTypes.Ack:
dataSender.ReliableChannel.HandleAckMessage(inc);
break;
} }
break; break;
case NetIncomingMessageType.WarningMessage: case NetIncomingMessageType.WarningMessage:
@@ -552,7 +589,7 @@ namespace Barotrauma.Networking
userID++; userID++;
} }
Client newClient = new Client(name, userID); Client newClient = new Client(server, name, userID);
newClient.Connection = inc.SenderConnection; newClient.Connection = inc.SenderConnection;
newClient.version = version; newClient.version = version;
@@ -581,26 +618,23 @@ namespace Barotrauma.Networking
{ {
if (NetworkEvent.events.Count == 0) return; if (NetworkEvent.events.Count == 0) return;
List<NetConnection> recipients = new List<NetConnection>();
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;
recipients.Add(c.Connection);
}
if (recipients.Count == 0) return;
foreach (NetworkEvent networkEvent in NetworkEvent.events) foreach (NetworkEvent networkEvent in NetworkEvent.events)
{ {
List<NetConnection> recipients = new List<NetConnection>();
Entity e = Entity.FindEntityByID(networkEvent.ID); Entity e = Entity.FindEntityByID(networkEvent.ID);
if (e == null) continue; if (e == null) continue;
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;
recipients.Add(c.Connection);
}
if (recipients.Count == 0) return;
NetOutgoingMessage message = server.CreateMessage(); NetOutgoingMessage message = server.CreateMessage();
message.Write((byte)PacketTypes.NetworkEvent); message.Write((byte)PacketTypes.NetworkEvent);
//if (!networkEvent.IsClient) continue; //if (!networkEvent.IsClient) continue;
@@ -872,7 +906,7 @@ namespace Barotrauma.Networking
{ {
base.Draw(spriteBatch); base.Draw(spriteBatch);
if (!GameMain.DebugDraw) return; if (!ShowNetStats) return;
int width = 200, height = 300; int width = 200, height = 300;
int x = GameMain.GraphicsWidth - width, y = (int)(GameMain.GraphicsHeight*0.3f); int x = GameMain.GraphicsWidth - width, y = (int)(GameMain.GraphicsHeight*0.3f);
@@ -934,27 +968,22 @@ namespace Barotrauma.Networking
if (server.Connections.Count == 0) return; if (server.Connections.Count == 0) return;
NetOutgoingMessage msg = server.CreateMessage(); List<Client> recipients = new List<Client>();
msg.Write((byte)PacketTypes.Chatmessage);
msg.Write((byte)type);
msg.Write(message);
if (type==ChatMessageType.Dead) foreach (Client c in connectedClients)
{ {
List<NetConnection> recipients = new List<NetConnection>(); if (type!=ChatMessageType.Dead || (c.character != null && c.character.IsDead)) recipients.Add(c);
foreach (Client c in connectedClients)
{
if (c.character != null && c.character.IsDead) recipients.Add(c.Connection);
}
if (recipients.Count>0)
{
server.SendMessage(msg, recipients, NetDeliveryMethod.ReliableUnordered, 0);
}
} }
else
foreach (Client c in recipients)
{ {
server.SendMessage(msg, server.Connections, NetDeliveryMethod.ReliableUnordered, 0); ReliableMessage msg = c.ReliableChannel.CreateMessage();
} msg.InnerMessage.Write((byte)PacketTypes.Chatmessage);
msg.InnerMessage.Write((byte)type);
msg.InnerMessage.Write(message);
c.ReliableChannel.SendMessage(msg, c.Connection);
}
} }
@@ -1177,13 +1206,21 @@ namespace Barotrauma.Networking
public List<JobPrefab> jobPreferences; public List<JobPrefab> jobPreferences;
public JobPrefab assignedJob; public JobPrefab assignedJob;
public ReliableChannel ReliableChannel;
public float deleteDisconnectedTimer; public float deleteDisconnectedTimer;
public Client(NetPeer server, string name, int ID)
: this(name, ID)
{
ReliableChannel = new ReliableChannel(server);
}
public Client(string name, int ID) public Client(string name, int ID)
{ {
this.name = name; this.name = name;
this.ID = ID; this.ID = ID;
jobPreferences = new List<JobPrefab>(JobPrefab.List.GetRange(0,3)); jobPreferences = new List<JobPrefab>(JobPrefab.List.GetRange(0,3));
} }
} }
+3 -3
View File
@@ -79,13 +79,13 @@ namespace Barotrauma.Networking
graphs[(int)NetStatType.ResentMessages].Draw(spriteBatch, rect, null, 0.0f, Color.Red); graphs[(int)NetStatType.ResentMessages].Draw(spriteBatch, rect, null, 0.0f, Color.Red);
spriteBatch.DrawString(GUI.SmallFont, "Max received: "+graphs[(int)NetStatType.ReceivedBytes].LargestValue()+" bytes/s", spriteBatch.DrawString(GUI.SmallFont, "Peak received: "+graphs[(int)NetStatType.ReceivedBytes].LargestValue()+" bytes/s",
new Vector2(rect.X + 10, rect.Y+10), Color.Cyan); new Vector2(rect.X + 10, rect.Y+10), Color.Cyan);
spriteBatch.DrawString(GUI.SmallFont, "Max sent: " + graphs[(int)NetStatType.SentBytes].LargestValue() + " bytes/s", spriteBatch.DrawString(GUI.SmallFont, "Peak sent: " + graphs[(int)NetStatType.SentBytes].LargestValue() + " bytes/s",
new Vector2(rect.X + 10, rect.Y + 30), Color.Orange); new Vector2(rect.X + 10, rect.Y + 30), Color.Orange);
spriteBatch.DrawString(GUI.SmallFont, "Max resent: " + graphs[(int)NetStatType.ResentMessages].LargestValue() + " messages/s", spriteBatch.DrawString(GUI.SmallFont, "Peak resent: " + graphs[(int)NetStatType.ResentMessages].LargestValue() + " messages/s",
new Vector2(rect.X + 10, rect.Y + 50), Color.Red); new Vector2(rect.X + 10, rect.Y + 50), Color.Red);
} }
} }
+9 -1
View File
@@ -93,7 +93,15 @@ namespace Barotrauma.Networking
message.Write(id); message.Write(id);
e.FillNetworkData(eventType, message, data); try
{
if (!e.FillNetworkData(eventType, message, data)) return false;
}
catch
{
return false;
}
return true; return true;
} }
@@ -8,6 +8,8 @@ namespace Barotrauma.Networking
{ {
enum PacketTypes enum PacketTypes
{ {
Unknown,
Login, Login,
LoggedIn, LoggedIn,
LogOut, LogOut,
@@ -26,7 +28,12 @@ namespace Barotrauma.Networking
NetworkEvent, NetworkEvent,
Traitor Traitor,
ResendRequest,
ReliableMessage,
Ack
} }
class NetworkMember class NetworkMember
@@ -0,0 +1,404 @@
using Lidgren.Network;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
namespace Barotrauma.Networking.ReliableMessages
{
class ReliableChannel
{
ReliableSender sender;
ReliableReceiver receiver;
public ReliableChannel(NetPeer host)
{
sender = new ReliableSender(host);
receiver = new ReliableReceiver(host);
}
public ReliableMessage CreateMessage(int lengthBytes = 0)
{
return sender.CreateMessage();
}
public void SendMessage(ReliableMessage message, NetConnection receiver)
{
sender.SendMessage(message, receiver);
}
public void HandleResendRequest(NetIncomingMessage inc)
{
sender.HandleResendRequest(inc);
}
public void HandleAckMessage(NetIncomingMessage inc)
{
//make sure we've received what's been sent to us, if not, rerequest
receiver.HandleAckMessage(inc);
}
public bool CheckMessage(NetIncomingMessage inc)
{
return receiver.CheckMessage(inc);
}
public void Update(float deltaTime)
{
sender.Update(deltaTime);
//update receiver to rerequest missed messages
receiver.Update(deltaTime);
}
}
internal class ReliableSender
{
private List<ReliableMessage> messageBuffer;
private ushort messageCount;
private NetPeer sender;
private NetConnection recipient;
private float ackTimer;
public ReliableSender(NetPeer sender)
{
this.sender = sender;
messageBuffer = new List<ReliableMessage>();
}
public ReliableMessage CreateMessage()
{
if (messageCount == ushort.MaxValue) messageCount = 0;
messageCount++;
NetOutgoingMessage message = sender.CreateMessage();
var reliableMessage = new ReliableMessage(message, messageCount);
messageBuffer.Add(reliableMessage);
message.Write((byte)PacketTypes.ReliableMessage);
message.Write(messageCount);
while (messageBuffer.Count>100)
{
messageBuffer.RemoveAt(0);
}
return reliableMessage;
//server.SendMessage(msg, server.Connections, NetDeliveryMethod.Unreliable, 0);
}
public void SendMessage(ReliableMessage message, NetConnection connection)
{
message.SaveInnerMessage();
sender.SendMessage(message.InnerMessage, connection, NetDeliveryMethod.Unreliable, 0);
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();
Debug.WriteLine("received resend request for msg id "+messageId);
ResendMessage(messageId, inc.SenderConnection);
}
private void ResendMessage(ushort messageId, NetConnection connection)
{
ReliableMessage message = messageBuffer.Find(m => m.ID == messageId);
if (message == null) return;
Debug.WriteLine("resending " + messageId);
NetOutgoingMessage resendMessage = sender.CreateMessage();
message.RestoreInnerMessage(resendMessage);
sender.SendMessage(resendMessage, connection, NetDeliveryMethod.Unreliable);
}
public void Update(float deltaTime)
{
if (recipient == null) return;
ackTimer -= deltaTime;
if (ackTimer > 0.0f) return;
Debug.WriteLine("Sending ack message: "+messageCount);
NetOutgoingMessage message = sender.CreateMessage();
message.Write((byte)PacketTypes.Ack);
message.Write(messageCount);
sender.SendMessage(message, recipient, NetDeliveryMethod.Unreliable);
ackTimer = Math.Max(recipient.AverageRoundtripTime, 1.0f);
}
}
internal class ReliableReceiver
{
ushort lastMessageID;
Dictionary<ushort, MissingMessage> missingMessages;
private NetPeer receiver;
private NetConnection recipient;
public ReliableReceiver(NetPeer receiver)
{
this.receiver = receiver;
missingMessages = new Dictionary<ushort,MissingMessage>();
}
public void Update(float deltaTime)
{
foreach (var message in missingMessages.Where(m => m.Value.ResendRequestsSent>10).ToList())
{
missingMessages.Remove(message.Key);
}
foreach (KeyValuePair<ushort, MissingMessage> 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+")");
NetOutgoingMessage resendRequest = receiver.CreateMessage();
resendRequest.Write((byte)PacketTypes.ResendRequest);
resendRequest.Write(missingMessage.ID);
receiver.SendMessage(resendRequest, recipient, NetDeliveryMethod.Unreliable);
missingMessage.ResendTimer = Math.Max(recipient.AverageRoundtripTime, 0.2f);
missingMessage.ResendRequestsSent++;
}
}
}
public bool CheckMessage(NetIncomingMessage message)
{
recipient = message.SenderConnection;
ushort id = message.ReadUInt16();
Debug.WriteLine("received message ID " + id + " - last id: " + lastMessageID);
//wrapped around
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)
{
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));
}
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));
}
lastMessageID = id;
}
//we already wrapped around but the message hasn't, check if it's a duplicate
else if (lastMessageID < ushort.MaxValue / 2 && id > ushort.MaxValue / 2 && !missingMessages.ContainsKey(id))
{
Debug.WriteLine("old already received message, ignore");
return false;
}
else
{
if (missingMessages.ContainsKey(id))
{
Debug.WriteLine("remove " + id + " from missed");
missingMessages.Remove(id);
}
}
}
else
{
if (id>lastMessageID+1)
{
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));
}
}
//received an old message and it wasn't marked as missed, lets ignore it
else if (id<=lastMessageID && !missingMessages.ContainsKey(id))
{
Debug.WriteLine("old already received message, ignore");
return false;
}
else
{
if (missingMessages.ContainsKey(id))
{
Debug.WriteLine("remove "+id+" from missed");
missingMessages.Remove(id);
}
}
lastMessageID = Math.Max(lastMessageID, id);
}
return true;
}
public void HandleAckMessage(NetIncomingMessage inc)
{
int 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)
{
//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 + ")");
return;
}
Debug.WriteLine("Received ack message: " + messageId + ", need to rerequest messages");
if (lastMessageID > ushort.MaxValue / 2 && messageId < short.MaxValue / 2)
{
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));
}
for (ushort i = 1; i <= messageId; i++)
{
if (!missingMessages.ContainsKey(i)) missingMessages.Add(i, new MissingMessage(i));
}
}
else
{
for (ushort i = (ushort)Math.Min((int)lastMessageID+1, ushort.MaxValue); i <= messageId; i++)
{
if (!missingMessages.ContainsKey(i)) missingMessages.Add(i, new MissingMessage(i));
}
}
// 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);
}
}
internal class MissingMessage
{
private ushort id;
public byte ResendRequestsSent;
public float ResendTimer;
public ushort ID
{
get { return id; }
}
public MissingMessage(ushort id)
{
this.id = id;
}
}
class ReliableMessage
{
private NetOutgoingMessage innerMessage;
private ushort id;
private byte[] innerMessageBytes;
public NetOutgoingMessage InnerMessage
{
get { return innerMessage; }
}
public ushort ID
{
get { return id; }
}
public ReliableMessage(NetOutgoingMessage message, ushort id)
{
this.innerMessage = message;
this.id = id;
}
public void SaveInnerMessage()
{
innerMessageBytes = innerMessage.PeekBytes(innerMessage.LengthBytes);
//innerMessage = null;
}
public void RestoreInnerMessage(NetOutgoingMessage message)
{
message.Write(innerMessageBytes);
}
}
}
@@ -287,8 +287,8 @@ namespace Barotrauma
if (serverList.Selected!=null && (serverList.Selected.GetChild("password") as GUITickBox).Selected) if (serverList.Selected!=null && (serverList.Selected.GetChild("password") as GUITickBox).Selected)
{ {
var msgBox = new GUIMessageBox("Password required", ""); var msgBox = new GUIMessageBox("Password required:", "");
var passwordBox = new GUITextBox(new Rectangle(0,0,150,20), Alignment.BottomCenter, GUI.Style, msgBox); var passwordBox = new GUITextBox(new Rectangle(0,40,150,25), Alignment.TopLeft, GUI.Style, msgBox);
passwordBox.UserData = "password"; passwordBox.UserData = "password";
var okButton = msgBox.GetChild<GUIButton>(); var okButton = msgBox.GetChild<GUIButton>();
+21
View File
@@ -1,3 +1,24 @@
---------------------------------------------------------------------------------------------------------
v0.2.2
---------------------------------------------------------------------------------------------------------
Multiplayer:
- network statistics view which can be enabled by opening the debug console (F3) and entering "netstats"
(only works if you're running a server)
- updated to latest version of Lidgren networking library, which may or may not have an effect
on the chat lag issues
Items:
- fixed some game-crashing bugs related to detaching and attaching items (such as buttons)
- railgun shells can be bought in single player
Submarine:
- more tools, diving suits and misc supplies in both default subs
Misc:
- fixed Moloch spawning inside the level in the tutorial
- the launcher shows an error message instead of crashing if it can't connect to the update server
--------------------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------------
v0.2.1 v0.2.1
--------------------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------------
Binary file not shown.