private void Update() { while (_eventsToHandle.TryDequeue(out var @event)) { switch (@event.Type) { case EventType.Connect: OnConnected(@event.Peer); break; case EventType.Disconnect: case EventType.Timeout: OnDisconnected(@event.Peer); break; case EventType.Receive: unsafe { _receivedUnreliable++; var packet = @event.Packet; var span = new ReadOnlySpan <byte>(packet.Data.ToPointer(), packet.Length); _buffer.FromSpan(ref span, packet.Length); _detector.ReadHeaderOfPeerId((ushort)@event.Peer.ID, _buffer); _buffer.Clear(); packet.Dispose(); break; } } } _detector.ExecuteLostPackets(); }
private unsafe void ExecuteState(IntPtr state) { PackedDataFlags flags; int cursor; if (_firstPacket) { _firstPacket = false; flags = PackedDataFlags.Commands | PackedDataFlags.CreatedEntities; cursor = 0; } else { flags = (PackedDataFlags)Marshal.ReadByte(state); cursor = 1; } #region commands if ((flags & PackedDataFlags.Commands) == PackedDataFlags.Commands) { var commandsHeaderSpan = new ReadOnlySpan <ushort>(IntPtr.Add(state, cursor).ToPointer(), 2); var commandCount = commandsHeaderSpan[0]; var commandLength = commandsHeaderSpan[1]; cursor += 4; if (commandCount > 0) { var dataSpan = new ReadOnlySpan <byte>(IntPtr.Add(state, cursor).ToPointer(), commandLength); _fromServer.Clear(); _fromServer.FromSpan(ref dataSpan, commandLength); ClientCommandExecutor.Execute(_handler, _fromServer, commandCount); cursor += commandLength; } } #endregion #region created entities if ((flags & PackedDataFlags.CreatedEntities) == PackedDataFlags.CreatedEntities) { var createdEntitiesHeaderSpan = new ReadOnlySpan <ushort>(IntPtr.Add(state, cursor).ToPointer(), 2); var createdEntitiesCount = createdEntitiesHeaderSpan[0]; var createdEntitiesLength = createdEntitiesHeaderSpan[1]; cursor += 4; if (createdEntitiesCount > 0) { var dataSpan = new ReadOnlySpan <byte>(IntPtr.Add(state, cursor).ToPointer(), createdEntitiesLength); _fromServer.Clear(); _fromServer.FromSpan(ref dataSpan, createdEntitiesLength); UnpackEntityUtility.CreateEntities(_game, _fromServer, createdEntitiesCount); cursor += createdEntitiesLength; } } #endregion #region removed entities if ((flags & PackedDataFlags.RemovedEntities) == PackedDataFlags.RemovedEntities) { var removedEntitiesHeaderSpan = new ReadOnlySpan <ushort>(IntPtr.Add(state, cursor).ToPointer(), 2); var removedEntitiesCount = removedEntitiesHeaderSpan[0]; var removedEntitiesLength = removedEntitiesHeaderSpan[1]; cursor += 4; if (removedEntitiesCount > 0) { var dataSpan = new ReadOnlySpan <byte>(IntPtr.Add(state, cursor).ToPointer(), removedEntitiesLength); _fromServer.Clear(); _fromServer.FromSpan(ref dataSpan, removedEntitiesLength); UnpackEntityUtility.RemoveEntities(_game, _fromServer, removedEntitiesCount); cursor += removedEntitiesLength; } } #endregion #region removed components if ((flags & PackedDataFlags.RemovedComponents) == PackedDataFlags.RemovedComponents) { var removedComponentsHeaderSpan = new ReadOnlySpan <ushort>(IntPtr.Add(state, cursor).ToPointer(), 2); var removedComponentsCount = removedComponentsHeaderSpan[0]; var removedComponentsLength = removedComponentsHeaderSpan[1]; cursor += 4; if (removedComponentsCount > 0) { var dataSpan = new ReadOnlySpan <byte>(IntPtr.Add(state, cursor).ToPointer(), removedComponentsLength); _fromServer.Clear(); _fromServer.FromSpan(ref dataSpan, removedComponentsLength); UnpackEntityUtility.RemoveComponents(_game, _fromServer, removedComponentsCount); cursor += removedComponentsLength; } } #endregion #region changed components if ((flags & PackedDataFlags.ChangedComponents) == PackedDataFlags.ChangedComponents) { var changedComponentsHeaderSpan = new ReadOnlySpan <ushort>(IntPtr.Add(state, cursor).ToPointer(), 2); var changedComponentsCount = changedComponentsHeaderSpan[0]; var changedComponentsLength = changedComponentsHeaderSpan[1]; cursor += 4; if (changedComponentsCount > 0) { var dataSpan = new ReadOnlySpan <byte>(IntPtr.Add(state, cursor).ToPointer(), changedComponentsLength); _fromServer.Clear(); _fromServer.FromSpan(ref dataSpan, changedComponentsLength); UnpackEntityUtility.ChangeComponents(_game, _fromServer, changedComponentsCount); } } #endregion Marshal.FreeHGlobal(state); }
public void Execute() { while (_responses.TryDequeue(out var response)) { switch (response) { case NetworkThreadResponse.StartSuccess: Logger.I.Log(this, "Server is working"); State = ServerState.Working; break; case NetworkThreadResponse.StartFailure: Logger.I.Log(this, "Server start failed"); State = ServerState.Stopped; break; case NetworkThreadResponse.Stoppoed: Logger.I.Log(this, "Server is stopped"); ClearBuffers(); while (_eventsToHandle.TryDequeue(out _)) { } State = ServerState.Stopped; break; } } if (State != ServerState.Working) { return; } while (_eventsToHandle.TryDequeue(out var @event)) { unsafe { switch (@event.EventType) { case EventType.Connect: _handler.OnClientConnected(@event.Peer); break; case EventType.Disconnect: _handler.OnClientDisconnected(@event.Peer); break; case EventType.Receive: _currentPeerId = (ushort)@event.Peer.ID; _handler.CurrentClientId = _currentPeerId; var e = _game.GetEntityWithConnection(_currentPeerId); if (e == null) { Marshal.FreeHGlobal(@event.Data); break; } var headerSpan = new ReadOnlySpan <ushort>(@event.Data.ToPointer(), 2); var commandCount = headerSpan[0]; var commandLength = headerSpan[1]; if (commandCount > 0) { var commandsSpan = new ReadOnlySpan <byte>(IntPtr.Add(@event.Data, 4).ToPointer(), commandLength); _fromClients.Clear(); _fromClients.FromSpan(ref commandsSpan, commandLength); ServerCommandExecutor.Execute(_handler, _fromClients, commandCount); } Marshal.FreeHGlobal(@event.Data); _currentPeerId = ushort.MaxValue; break; case EventType.Timeout: _handler.OnClientDisconnected(@event.Peer); break; } } } }