Esempio n. 1
0
        /// <inheritdoc />
        public void SendGameStateUpdate()
        {
            DebugTools.Assert(_networkManager.IsServer);

            _entityManager.Update();

            if (!_networkManager.IsConnected)
            {
                // Prevent deletions piling up if we have no clients.
                _entityManager.CullDeletionHistory(GameTick.MaxValue);
                _mapManager.CullDeletionHistory(GameTick.MaxValue);
                return;
            }

            var inputSystem = _systemManager.GetEntitySystem <InputSystem>();

            var oldestAck = GameTick.MaxValue;

            var oldDeps = IoCManager.Resolve <IDependencyCollection>();

            var deps = new DependencyCollection();

            deps.RegisterInstance <ILogManager>(new ProxyLogManager(IoCManager.Resolve <ILogManager>()));
            deps.BuildGraph();

            (MsgState, INetChannel) GenerateMail(IPlayerSession session)
            {
                IoCManager.InitThread(deps, true);

                if (session.Status != SessionStatus.InGame)
                {
                    return(default);
        public void SendGameStateUpdate()
        {
            DebugTools.Assert(_networkManager.IsServer);

            if (!_networkManager.IsConnected)
            {
                // Prevent deletions piling up if we have no clients.
                _entityManager.CullDeletionHistory(uint.MaxValue);
                _mapManager.CullDeletionHistory(uint.MaxValue);
                return;
            }

            var oldestAck = uint.MaxValue;

            foreach (var connection in _networkManager.Channels)
            {
                if (!ackedStates.TryGetValue(connection.ConnectionId, out var ack))
                {
                    ackedStates.Add(connection.ConnectionId, 0);
                }
                else if (ack < oldestAck)
                {
                    oldestAck = ack;
                }
            }

            if (oldestAck > lastOldestAck)
            {
                lastOldestAck = oldestAck;
                _entityManager.CullDeletionHistory(oldestAck);
            }

            var entities  = _entityManager.GetEntityStates(oldestAck);
            var players   = _playerManager.GetPlayerStates();
            var deletions = _entityManager.GetDeletedEntities(oldestAck);
            var mapData   = _mapManager.GetStateData(oldestAck);

            var state = new GameState(oldestAck, _gameTiming.CurTick, entities, players, deletions, mapData);

            foreach (var c in _networkManager.Channels)
            {
                var session = _playerManager.GetSessionByChannel(c);

                if (session == null || session.Status != SessionStatus.InGame)
                {
                    continue;
                }

                var stateUpdateMessage = _networkManager.CreateNetMessage <MsgState>();
                stateUpdateMessage.State = state;
                _networkManager.ServerSendMessage(stateUpdateMessage, c);
            }
        }
        /// <inheritdoc />
        public void SendGameStateUpdate()
        {
            DebugTools.Assert(_networkManager.IsServer);

            _entityManager.Update();

            if (!_networkManager.IsConnected)
            {
                // Prevent deletions piling up if we have no clients.
                _entityManager.CullDeletionHistory(GameTick.MaxValue);
                _mapManager.CullDeletionHistory(GameTick.MaxValue);
                return;
            }

            var inputSystem = _systemManager.GetEntitySystem <InputSystem>();

            var oldestAck = GameTick.MaxValue;



            foreach (var session in _playerManager.GetAllPlayers())
            {
                if (session.Status != SessionStatus.InGame)
                {
                    continue;
                }

                var channel = session.ConnectedClient;

                if (!_ackedStates.TryGetValue(channel.ConnectionId, out var lastAck))
                {
                    DebugTools.Assert("Why does this channel not have an entry?");
                }

                var entStates = lastAck == GameTick.Zero || !PvsEnabled
                    ? _entityManager.GetEntityStates(lastAck)
                    : _entityManager.UpdatePlayerSeenEntityStates(lastAck, session, _entityManager.MaxUpdateRange);

                var playerStates = _playerManager.GetPlayerStates(lastAck);
                var deletions    = _entityManager.GetDeletedEntities(lastAck);
                var mapData      = _mapManager.GetStateData(lastAck);


                // lastAck varies with each client based on lag and such, we can't just make 1 global state and send it to everyone
                var lastInputCommand  = inputSystem.GetLastInputCommand(session);
                var lastSystemMessage = _entityNetworkManager.GetLastMessageSequence(session);
                var state             = new GameState(lastAck, _gameTiming.CurTick,
                                                      Math.Max(lastInputCommand, lastSystemMessage), entStates?.ToArray(), playerStates?.ToArray(), deletions?.ToArray(), mapData);
                if (lastAck < oldestAck)
                {
                    oldestAck = lastAck;
                }

                // actually send the state
                var stateUpdateMessage = _networkManager.CreateNetMessage <MsgState>();
                stateUpdateMessage.State = state;
                _networkManager.ServerSendMessage(stateUpdateMessage, channel);

                // If the state is too big we let Lidgren send it reliably.
                // This is to avoid a situation where a state is so large that it consistently gets dropped
                // (or, well, part of it).
                // When we send them reliably, we immediately update the ack so that the next state will not be huge.
                if (stateUpdateMessage.ShouldSendReliably())
                {
                    _ackedStates[channel.ConnectionId] = _gameTiming.CurTick;
                }
            }

            // keep the deletion history buffers clean
            if (oldestAck > _lastOldestAck)
            {
                _lastOldestAck = oldestAck;
                _entityManager.CullDeletionHistory(oldestAck);
                _mapManager.CullDeletionHistory(oldestAck);
            }
        }
Esempio n. 4
0
        /// <inheritdoc />
        public void SendGameStateUpdate()
        {
            DebugTools.Assert(_networkManager.IsServer);

            if (!_networkManager.IsConnected)
            {
                // Prevent deletions piling up if we have no clients.
                _entityManager.CullDeletionHistory(GameTick.MaxValue);
                _mapManager.CullDeletionHistory(GameTick.MaxValue);
                return;
            }

            var oldestAck = GameTick.MaxValue;

            foreach (var channel in _networkManager.Channels)
            {
                var session = _playerManager.GetSessionByChannel(channel);
                if (session == null || session.Status != SessionStatus.InGame) // client still joining, maybe iterate over sessions instead?
                {
                    continue;
                }

                if (!_ackedStates.TryGetValue(channel.ConnectionId, out var lastAck))
                {
                    DebugTools.Assert("Why does this channel not have an entry?");
                }

                //TODO: Cull these based on client view rectangle, remember the issues with transform parenting
                var entities  = _entityManager.GetEntityStates(lastAck);
                var players   = _playerManager.GetPlayerStates(lastAck);
                var deletions = _entityManager.GetDeletedEntities(lastAck);
                var mapData   = _mapManager.GetStateData(lastAck);

                // lastAck varies with each client based on lag and such, we can't just make 1 global state and send it to everyone
                var state = new GameState(lastAck, _gameTiming.CurTick, entities, players, deletions, mapData);

                // actually send the state
                var stateUpdateMessage = _networkManager.CreateNetMessage <MsgState>();
                stateUpdateMessage.State = state;
                _networkManager.ServerSendMessage(stateUpdateMessage, channel);

                // we are not going to send a full state every tick (rip bandwidth) until they ack, so assume they receive it
                // and start the deltas from the full state.
                // the client will signal to us if they need another one.
                if (lastAck == GameTick.Zero)
                {
                    _ackedStates[channel.ConnectionId] = _gameTiming.CurTick;
                }

                if (lastAck < oldestAck)
                {
                    oldestAck = lastAck;
                }
            }

            // keep the deletion history buffers clean
            if (oldestAck > _lastOldestAck)
            {
                _lastOldestAck = oldestAck;
                _entityManager.CullDeletionHistory(oldestAck);
                _mapManager.CullDeletionHistory(oldestAck);
            }
        }
Esempio n. 5
0
        /// <inheritdoc />
        public void SendGameStateUpdate()
        {
            DebugTools.Assert(_networkManager.IsServer);

            if (!_networkManager.IsConnected)
            {
                // Prevent deletions piling up if we have no clients.
                _entityManager.CullDeletionHistory(GameTick.MaxValue);
                _mapManager.CullDeletionHistory(GameTick.MaxValue);
                return;
            }

            var oldestAck = GameTick.MaxValue;

            var work = new List <(INetChannel channel, GameTick lastAck)>();

            foreach (var channel in _networkManager.Channels)
            {
                var session = _playerManager.GetSessionByChannel(channel);
                if (session == null || session.Status != SessionStatus.InGame)
                {
                    // client still joining, maybe iterate over sessions instead?
                    continue;
                }

                if (!_ackedStates.TryGetValue(channel.ConnectionId, out var lastAck))
                {
                    DebugTools.Assert("Why does this channel not have an entry?");
                }

                work.Add((channel, lastAck));

                if (lastAck < oldestAck)
                {
                    oldestAck = lastAck;
                }
            }

            var workDone = ParallelStates
                ? work.AsParallel().Select(GenerateStateFor).ToList()
                : work.Select(GenerateStateFor).ToList();

            foreach (var(channel, state) in workDone)
            {
                // actually send the state
                var stateUpdateMessage = _networkManager.CreateNetMessage <MsgState>();
                stateUpdateMessage.State = state;
                _networkManager.ServerSendMessage(stateUpdateMessage, channel);

                // If the state is too big we let Lidgren send it reliably.
                // This is to avoid a situation where a state is so large that it consistently gets dropped
                // (or, well, part of it).
                // When we send them reliably, we immediately update the ack so that the next state will not be huge.
                if (stateUpdateMessage.ShouldSendReliably())
                {
                    _ackedStates[channel.ConnectionId] = _gameTiming.CurTick;
                }
            }

            // keep the deletion history buffers clean
            if (oldestAck > _lastOldestAck)
            {
                _lastOldestAck = oldestAck;
                _entityManager.CullDeletionHistory(oldestAck);
                _mapManager.CullDeletionHistory(oldestAck);
            }
        }