"ReliableMessages", networkevents aren't sent if FillNetworkEvent fails
This commit is contained in:
@@ -45,7 +45,7 @@
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<DefineConstants>TRACE;USE_RELEASE_STATISTICS</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
|
||||
@@ -100,6 +100,7 @@
|
||||
<Compile Include="Source\Map\SubmarineHull.cs" />
|
||||
<Compile Include="Source\Networking\NetConfig.cs" />
|
||||
<Compile Include="Source\Networking\NetStats.cs" />
|
||||
<Compile Include="Source\Networking\ReliableSender.cs" />
|
||||
<Compile Include="Source\Particles\ParticleEmitter.cs" />
|
||||
<Compile Include="Source\Screens\ServerListScreen.cs" />
|
||||
<Compile Include="Source\Utils\Rand.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.0.0")]
|
||||
[assembly: AssemblyFileVersion("0.2.0.0")]
|
||||
[assembly: AssemblyVersion("0.2.2.0")]
|
||||
[assembly: AssemblyFileVersion("0.2.2.0")]
|
||||
|
||||
@@ -83,11 +83,11 @@ namespace Barotrauma
|
||||
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)
|
||||
{
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
message.Write((float)NetTime.Now);
|
||||
@@ -127,6 +127,9 @@ namespace Barotrauma
|
||||
|
||||
LargeUpdateTimer = Math.Max(0, LargeUpdateTimer - 1);
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void ReadNetworkData(NetworkEventType type, NetIncomingMessage message)
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
message.Write((int)data);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
else if (type== NetworkEventType.SelectCharacter)
|
||||
{
|
||||
message.Write((int)data);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
else if (type == NetworkEventType.KillCharacter)
|
||||
{
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
var hasInputs =
|
||||
@@ -1160,7 +1160,9 @@ namespace Barotrauma
|
||||
message.Write(AnimController.RefLimb.SimPosition.Y);
|
||||
|
||||
LargeUpdateTimer = Math.Max(0, LargeUpdateTimer-1);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void ReadNetworkData(NetworkEventType type, NetIncomingMessage message)
|
||||
|
||||
@@ -325,6 +325,11 @@ namespace Barotrauma
|
||||
//Ragdoll.DebugDraw = !Ragdoll.DebugDraw;
|
||||
GameMain.DebugDraw = !GameMain.DebugDraw;
|
||||
break;
|
||||
case "netstats":
|
||||
if (GameMain.Server == null) return;
|
||||
|
||||
GameMain.Server.ShowNetStats = !GameMain.Server.ShowNetStats;
|
||||
break;
|
||||
default:
|
||||
NewMessage("Command not found", Color.Red);
|
||||
break;
|
||||
|
||||
@@ -613,6 +613,8 @@ namespace Barotrauma
|
||||
{
|
||||
do
|
||||
{
|
||||
if (enemy == null) break;
|
||||
|
||||
enemy.Health = 50.0f;
|
||||
|
||||
enemy.AIController.State = AIController.AiState.None;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
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++)
|
||||
{
|
||||
message.Write((items[i] == null) ? -1 : items[i].ID);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void ReadNetworkData(NetworkEventType type, NetIncomingMessage message)
|
||||
|
||||
@@ -1156,7 +1156,7 @@ namespace Barotrauma
|
||||
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);
|
||||
|
||||
@@ -1172,7 +1172,7 @@ namespace Barotrauma
|
||||
case NetworkEventType.UpdateComponent:
|
||||
|
||||
int componentIndex = (int)data;
|
||||
if (componentIndex < 0 || componentIndex >= components.Count) return;
|
||||
if (componentIndex < 0 || componentIndex >= components.Count) return false;
|
||||
|
||||
message.Write((byte)componentIndex);
|
||||
components[componentIndex].FillNetworkData(type, message);
|
||||
@@ -1214,6 +1214,8 @@ namespace Barotrauma
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void ReadNetworkData(NetworkEventType type, NetIncomingMessage message)
|
||||
|
||||
@@ -64,7 +64,10 @@ namespace Barotrauma
|
||||
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) { }
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -471,9 +471,11 @@ namespace Barotrauma
|
||||
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);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void ReadNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetIncomingMessage message)
|
||||
|
||||
@@ -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;
|
||||
byte byteIndex = 0;
|
||||
@@ -648,12 +648,14 @@ namespace Barotrauma
|
||||
}
|
||||
catch
|
||||
{
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
message.Write((float)NetTime.Now);
|
||||
message.Write(byteIndex);
|
||||
message.Write(sections[sectionIndex].damage);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void ReadNetworkData(NetworkEventType type, NetIncomingMessage message)
|
||||
|
||||
@@ -149,7 +149,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
base.Remove();
|
||||
ID = -1;
|
||||
ID = -5;
|
||||
}
|
||||
|
||||
//drawing ----------------------------------------------------
|
||||
@@ -378,14 +378,18 @@ namespace Barotrauma
|
||||
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(Position.X);
|
||||
message.Write(Position.Y);
|
||||
|
||||
message.Write(Speed.X);
|
||||
message.Write(Speed.Y);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void ReadNetworkData(Networking.NetworkEventType type, NetIncomingMessage message)
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Diagnostics;
|
||||
using Lidgren.Network;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System.Collections.Generic;
|
||||
using Barotrauma.Networking.ReliableMessages;
|
||||
|
||||
namespace Barotrauma.Networking
|
||||
{
|
||||
@@ -12,6 +13,8 @@ namespace Barotrauma.Networking
|
||||
|
||||
private GUIMessageBox reconnectBox;
|
||||
|
||||
private ReliableChannel reliableChannel;
|
||||
|
||||
private bool connected;
|
||||
|
||||
private int myID;
|
||||
@@ -34,6 +37,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
otherClients = new List<Client>();
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void ConnectToServer(string hostIP, string password = "")
|
||||
@@ -63,6 +67,7 @@ namespace Barotrauma.Networking
|
||||
#if DEBUG
|
||||
config.SimulatedLoss = 0.1f;
|
||||
config.SimulatedMinimumLatency = 0.3f;
|
||||
config.SimulatedRandomLatency = 0.5f;
|
||||
#endif
|
||||
|
||||
config.DisableMessageType(NetIncomingMessageType.DebugMessage | NetIncomingMessageType.WarningMessage | NetIncomingMessageType.Receipt
|
||||
@@ -70,6 +75,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
// Create new client, with previously created configs
|
||||
client = new NetClient(config);
|
||||
reliableChannel = new ReliableChannel(client);
|
||||
|
||||
NetOutgoingMessage outmsg = client.CreateMessage();
|
||||
client.Start();
|
||||
@@ -329,6 +335,8 @@ namespace Barotrauma.Networking
|
||||
new NetworkEvent(myCharacter.ID, true);
|
||||
}
|
||||
}
|
||||
|
||||
reliableChannel.Update(deltaTime);
|
||||
|
||||
foreach (NetworkEvent networkEvent in NetworkEvent.events)
|
||||
{
|
||||
@@ -368,8 +376,17 @@ namespace Barotrauma.Networking
|
||||
while ((inc = client.ReadMessage()) != null)
|
||||
{
|
||||
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:
|
||||
if (gameStarted) continue;
|
||||
@@ -427,6 +444,12 @@ namespace Barotrauma.Networking
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -652,13 +675,13 @@ namespace Barotrauma.Networking
|
||||
//AddChatMessage(message);
|
||||
|
||||
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();
|
||||
msg.Write((byte)PacketTypes.Chatmessage);
|
||||
msg.Write((byte)type);
|
||||
msg.Write(message);
|
||||
|
||||
client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered);
|
||||
reliableChannel.SendMessage(msg, client.ServerConnection);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -5,11 +5,13 @@ using System.Diagnostics;
|
||||
using Lidgren.Network;
|
||||
using Microsoft.Xna.Framework;
|
||||
using RestSharp;
|
||||
using Barotrauma.Networking.ReliableMessages;
|
||||
|
||||
namespace Barotrauma.Networking
|
||||
{
|
||||
class GameServer : NetworkMember
|
||||
{
|
||||
public bool ShowNetStats;
|
||||
|
||||
public List<Client> connectedClients = new List<Client>();
|
||||
|
||||
@@ -64,7 +66,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
#if DEBUG
|
||||
config.SimulatedLoss = 0.2f;
|
||||
config.SimulatedMinimumLatency = 0.3f;
|
||||
config.SimulatedRandomLatency = 0.6f;
|
||||
config.SimulatedDuplicatesChance = 0.05f;
|
||||
config.SimulatedMinimumLatency = 0.1f;
|
||||
#endif
|
||||
@@ -96,9 +98,9 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DebugConsole.ThrowError("Couldn't start the server", e);
|
||||
DebugConsole.ThrowError("Couldn't start the server", e);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (config.EnableUPnP)
|
||||
{
|
||||
@@ -225,7 +227,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
public override void Update(float deltaTime)
|
||||
{
|
||||
if (GameMain.DebugDraw) netStats.Update(deltaTime);
|
||||
if (ShowNetStats) netStats.Update(deltaTime);
|
||||
|
||||
if (!started) return;
|
||||
|
||||
@@ -268,8 +270,13 @@ namespace Barotrauma.Networking
|
||||
disconnectedClients.RemoveAt(i);
|
||||
}
|
||||
|
||||
NetIncomingMessage inc = server.ReadMessage();
|
||||
if (inc != null)
|
||||
foreach (Client c in connectedClients)
|
||||
{
|
||||
c.ReliableChannel.Update(deltaTime);
|
||||
}
|
||||
|
||||
NetIncomingMessage inc = null;
|
||||
while ((inc = server.ReadMessage()) != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -277,7 +284,11 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
catch
|
||||
{
|
||||
#if DEBUG
|
||||
DebugConsole.ThrowError("Failed to read incoming message");
|
||||
#endif
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -416,7 +427,26 @@ namespace Barotrauma.Networking
|
||||
break;
|
||||
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:
|
||||
if (!gameStarted) break;
|
||||
@@ -452,6 +482,13 @@ namespace Barotrauma.Networking
|
||||
case (byte)PacketTypes.CharacterInfo:
|
||||
ReadCharacterData(inc);
|
||||
break;
|
||||
case (byte)PacketTypes.ResendRequest:
|
||||
|
||||
dataSender.ReliableChannel.HandleResendRequest(inc);
|
||||
break;
|
||||
case (byte)PacketTypes.Ack:
|
||||
dataSender.ReliableChannel.HandleAckMessage(inc);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case NetIncomingMessageType.WarningMessage:
|
||||
@@ -552,7 +589,7 @@ namespace Barotrauma.Networking
|
||||
userID++;
|
||||
}
|
||||
|
||||
Client newClient = new Client(name, userID);
|
||||
Client newClient = new Client(server, name, userID);
|
||||
newClient.Connection = inc.SenderConnection;
|
||||
newClient.version = version;
|
||||
|
||||
@@ -581,26 +618,23 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
||||
List<NetConnection> recipients = new List<NetConnection>();
|
||||
|
||||
Entity e = Entity.FindEntityByID(networkEvent.ID);
|
||||
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();
|
||||
message.Write((byte)PacketTypes.NetworkEvent);
|
||||
//if (!networkEvent.IsClient) continue;
|
||||
@@ -872,7 +906,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
base.Draw(spriteBatch);
|
||||
|
||||
if (!GameMain.DebugDraw) return;
|
||||
if (!ShowNetStats) return;
|
||||
|
||||
int width = 200, height = 300;
|
||||
int x = GameMain.GraphicsWidth - width, y = (int)(GameMain.GraphicsHeight*0.3f);
|
||||
@@ -934,27 +968,22 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (server.Connections.Count == 0) return;
|
||||
|
||||
NetOutgoingMessage msg = server.CreateMessage();
|
||||
msg.Write((byte)PacketTypes.Chatmessage);
|
||||
msg.Write((byte)type);
|
||||
msg.Write(message);
|
||||
List<Client> recipients = new List<Client>();
|
||||
|
||||
if (type==ChatMessageType.Dead)
|
||||
foreach (Client c in connectedClients)
|
||||
{
|
||||
List<NetConnection> recipients = new List<NetConnection>();
|
||||
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);
|
||||
}
|
||||
if (type!=ChatMessageType.Dead || (c.character != null && c.character.IsDead)) recipients.Add(c);
|
||||
}
|
||||
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 JobPrefab assignedJob;
|
||||
|
||||
public ReliableChannel ReliableChannel;
|
||||
|
||||
public float deleteDisconnectedTimer;
|
||||
|
||||
public Client(NetPeer server, string name, int ID)
|
||||
: this(name, ID)
|
||||
{
|
||||
ReliableChannel = new ReliableChannel(server);
|
||||
}
|
||||
|
||||
public Client(string name, int ID)
|
||||
{
|
||||
this.name = name;
|
||||
this.ID = ID;
|
||||
|
||||
|
||||
jobPreferences = new List<JobPrefab>(JobPrefab.List.GetRange(0,3));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,13 +79,13 @@ namespace Barotrauma.Networking
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,7 +93,15 @@ namespace Barotrauma.Networking
|
||||
|
||||
message.Write(id);
|
||||
|
||||
e.FillNetworkData(eventType, message, data);
|
||||
try
|
||||
{
|
||||
if (!e.FillNetworkData(eventType, message, data)) return false;
|
||||
}
|
||||
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
enum PacketTypes
|
||||
{
|
||||
Unknown,
|
||||
|
||||
Login,
|
||||
LoggedIn,
|
||||
LogOut,
|
||||
@@ -26,7 +28,12 @@ namespace Barotrauma.Networking
|
||||
|
||||
NetworkEvent,
|
||||
|
||||
Traitor
|
||||
Traitor,
|
||||
|
||||
ResendRequest,
|
||||
ReliableMessage,
|
||||
Ack
|
||||
|
||||
}
|
||||
|
||||
class NetworkMember
|
||||
|
||||
404
Subsurface/Source/Networking/ReliableSender.cs
Normal file
404
Subsurface/Source/Networking/ReliableSender.cs
Normal file
@@ -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)
|
||||
{
|
||||
var msgBox = new GUIMessageBox("Password required", "");
|
||||
var passwordBox = new GUITextBox(new Rectangle(0,0,150,20), Alignment.BottomCenter, GUI.Style, msgBox);
|
||||
var msgBox = new GUIMessageBox("Password required:", "");
|
||||
var passwordBox = new GUITextBox(new Rectangle(0,40,150,25), Alignment.TopLeft, GUI.Style, msgBox);
|
||||
passwordBox.UserData = "password";
|
||||
|
||||
var okButton = msgBox.GetChild<GUIButton>();
|
||||
|
||||
@@ -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
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user