Files
LuaCsForBarotraumaEP/Subsurface/Source/Networking/NetEntityEvent/ClientEntityEventManager.cs
2017-02-09 23:09:42 +02:00

177 lines
5.9 KiB
C#

using Lidgren.Network;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Barotrauma.Networking
{
class ClientEntityEventManager : NetEntityEventManager
{
private List<ClientEntityEvent> events;
private UInt32 ID;
private GameClient thisClient;
//when was a specific entity event last sent to the client
// key = event id, value = NetTime.Now when sending
public Dictionary<UInt32, float> eventLastSent;
public UInt32 LastReceivedID
{
get { return lastReceivedID; }
}
private UInt32 lastReceivedID;
public ClientEntityEventManager(GameClient client)
{
events = new List<ClientEntityEvent>();
eventLastSent = new Dictionary<uint, float>();
thisClient = client;
}
public void CreateEvent(IClientSerializable entity, object[] extraData = null)
{
if (GameMain.Client == null || GameMain.Client.Character == null) return;
if (!(entity is Entity))
{
DebugConsole.ThrowError("Can't create an entity event for " + entity + "!");
return;
}
ID++;
var newEvent = new ClientEntityEvent(entity, ID);
newEvent.CharacterStateID = GameMain.Client.Character.LastNetworkUpdateID;
if (extraData != null) newEvent.SetData(extraData);
events.Add(newEvent);
}
public void Write(NetOutgoingMessage msg, NetConnection serverConnection)
{
if (events.Count == 0) return;
List<NetEntityEvent> eventsToSync = new List<NetEntityEvent>();
//find the index of the first event the server hasn't received
int startIndex = events.Count;
while (startIndex > 0 &&
events[startIndex-1].ID > thisClient.LastSentEntityEventID)
{
startIndex--;
}
for (int i = startIndex; i < events.Count; i++)
{
//find the first event that hasn't been sent in 1.5 * roundtriptime or at all
float lastSent = 0;
eventLastSent.TryGetValue(events[i].ID, out lastSent);
if (lastSent > NetTime.Now - serverConnection.AverageRoundtripTime * 1.5f)
{
continue;
}
eventsToSync.AddRange(events.GetRange(i, events.Count - i));
break;
}
if (eventsToSync.Count == 0) return;
//too many events for one packet
if (eventsToSync.Count > MaxEventsPerWrite)
{
eventsToSync.RemoveRange(MaxEventsPerWrite, eventsToSync.Count - MaxEventsPerWrite);
}
if (eventsToSync.Count == 0) return;
foreach (NetEntityEvent entityEvent in eventsToSync)
{
eventLastSent[entityEvent.ID] = (float)NetTime.Now;
}
msg.Write((byte)ClientNetObject.ENTITY_STATE);
Write(msg, eventsToSync);
}
/// <summary>
/// Read the events from the message, ignoring ones we've already received
/// </summary>
public void Read(NetIncomingMessage msg, float sendingTime)
{
UInt32 firstEventID = msg.ReadUInt32();
int eventCount = msg.ReadByte();
for (int i = 0; i < eventCount; i++)
{
UInt32 thisEventID = firstEventID + (UInt32)i;
UInt16 entityID = msg.ReadUInt16();
byte msgLength = msg.ReadByte();
IServerSerializable entity = Entity.FindEntityByID(entityID) as IServerSerializable;
//skip the event if we've already received it or if the entity isn't found
if (thisEventID != lastReceivedID + 1 || entity == null)
{
if (thisEventID != lastReceivedID + 1)
{
DebugConsole.NewMessage("received msg " + thisEventID, Microsoft.Xna.Framework.Color.Red);
}
else if (entity == null)
{
DebugConsole.NewMessage("received msg " + thisEventID + ", entity " + entityID + " not found", Microsoft.Xna.Framework.Color.Red);
}
msg.Position += msgLength * 8;
}
else
{
long msgPosition = msg.Position;
DebugConsole.NewMessage("received msg " + thisEventID + " (" + entity.ToString() + ")", Microsoft.Xna.Framework.Color.Green);
lastReceivedID++;
try
{
ReadEvent(msg, entity, sendingTime);
}
catch (Exception e)
{
#if DEBUG
DebugConsole.ThrowError("Failed to read event for entity \"" + entity.ToString() + "\"!", e);
#endif
msg.Position = msgPosition + msgLength * 8;
}
}
msg.ReadPadBits();
}
}
protected override void WriteEvent(NetBuffer buffer, NetEntityEvent entityEvent, Client recipient = null)
{
var clientEvent = entityEvent as ClientEntityEvent;
if (clientEvent == null) return;
clientEvent.Write(buffer);
}
protected void ReadEvent(NetIncomingMessage buffer, IServerSerializable entity, float sendingTime)
{
entity.ClientRead(ServerNetObject.ENTITY_STATE, buffer, sendingTime);
}
public void Clear()
{
ID = 0;
lastReceivedID = 0;
events.Clear();
eventLastSent.Clear();
}
}
}