/// <summary> /// Responsible for encoding and decoding packet information. /// </summary> //public class Interpreter /// <summary> /// Interpreter for converting byte input to a BitBuffer. /// </summary> //protected Interpreter Interpreter { get; } = new Interpreter(); protected void ProcessPayload(Controller connection, Packet reusableIncoming, Func <T, bool> getSafeToExecute) { /// <summary> /// Records acknowledging information for the packet. /// </summary> // Connection.ProcessPacket connection.RemoteClock.UpdateLatest(reusableIncoming.SenderTick); foreach (var evnt in FilterIncomingEvents(reusableIncoming.Events)) { /// <summary> /// Handles the execution of an incoming event. /// </summary> // private void ProcessEvent(Event evnt) { if (evnt.EntityId.IsValid) { World_Entities.TryGetValue(evnt.EntityId, out var entity); if (getSafeToExecute(entity)) { Event_InvokeEntity(evnt, connection, entity); } } else { Event_Invoke(evnt, connection); } connection.ProcessedEventHistory = connection.ProcessedEventHistory.Store(evnt.EventId); } } var ackedEventId = reusableIncoming.AckEventId; { /// <summary> /// Removes any acked or expired outgoing events. /// </summary> //void CleanOutgoingEvents(SequenceId ackedEventId) if (ackedEventId.IsValid != false) { while (connection.OutgoingEvents.Count > 0) { var top = connection.OutgoingEvents.Peek(); // Stop if we hit an un-acked reliable event if (top.IsReliable) { if (top.EventId > ackedEventId) { break; } } // Stop if we hit an unreliable event with remaining attempts else { if (top.Attempts > 0) { break; } } var val = connection.OutgoingEvents.Dequeue(); val.Pool.Deallocate(val); } } } /// <summary> /// Gets all events that we haven't processed yet, in order with no gaps. /// </summary> IEnumerable <Event> FilterIncomingEvents(IEnumerable <Event> events) { foreach (var evnt in events) { if (connection.ProcessedEventHistory.IsNewId(evnt.EventId)) { yield return(evnt); } } } }
/// <summary> /// Wraps an incoming connection in a peer and stores it. /// </summary> public void AddConnection(IConnection connection) { if (!clients.ContainsKey(connection)) { var controller = new ServerController(connection); // ServerConnection.ctor controller.Connection.PayloadReceived += (data, length) => { //Console.WriteLine($"data {data.Length} length {length}"); // 253 245 var reusableIncoming = _protocol.Decode(data, length); if (reusableIncoming != default) { ProcessPayload(controller, reusableIncoming, entity => { // Entity events can only be executed on controlled entities return(entity != null && entity.Controller == controller); }); //onProcessPacket(); // Integrate foreach (var pair in reusableIncoming.View.LatestUpdates) { controller.Scope.AckedByClient.RecordUpdate(pair.Key, pair.Value); } // client.PacketReceived.Invoke(client, clientPacket); { // client.PacketReceived += (_peer, clientPacket) => foreach (var update in reusableIncoming.ReceivedCommandUpdates) { { // ServerManager.ProcessCommandUpdate if (World_Entities.TryGetValue(update.EntityId, out var entity)) { foreach (var command in update.Commands.GetValues()) { if (entity.Controller == controller && entity.IncomingCommands.Store(command)) { command.IsNewCommand = true; } else { command.Pool.Deallocate(command); } } } } } } } else { Console.WriteLine("Bad packet read, discarding..."); } reusableIncoming.Reset(); }; clients.Add(connection, controller); ControllerJoined.Invoke(controller); } }