Esempio n. 1
0
        public async Task TakeMe(IMyPlayer player, int index)
        {
            if (player == null)
            {
                throw new ArgumentException("calling player not found");
            }

            var entities = _clusters[index];

            if (entities.Length == 0)
            {
                throw new InvalidOperationException("entities not found");
            }

            var(_, center) = VRageUtils.GetBound(entities.Select(e => e.Position));
            player.Character.SetPosition(center);

            DeleteGpss(player.IdentityId);

            await GameLoopObserver.MoveToGameLoop(); // to create gps entities

            foreach (var grid in entities)
            {
                var gps = CreateGridGps($"{GpsNamePrefix}{grid.Name}", grid.Position, "", Color.Purple);
                MySession.Static.Gpss.SendAddGps(player.IdentityId, ref gps);
            }

            await TaskUtils.MoveToThreadPool();
        }
Esempio n. 2
0
        async Task PunishGrid(MyCubeGrid grid)
        {
            var blocks = grid.GetFatBlocks();

            for (var i = 0; i < blocks.Count; i++)
            {
                // move to the next frame so we won't lag the server
                if (i % ProcessedBlockCountPerFrame == 0)
                {
                    await VRageUtils.MoveToGameLoop();
                }

                var block = blocks[i];
                if (block == null)
                {
                    continue;
                }

                switch (_config.PunishType)
                {
                case PunishType.Shutdown:
                {
                    DisableFunctionalBlock(block);
                    break;
                }

                case PunishType.Damage:
                {
                    DamageBlock(block);
                    break;
                }
                }
            }
        }
        async Task BroadcastLaggyGrids(CancellationToken cancellationToken)
        {
            if (_config.PunishType != PunishType.Broadcast)
            {
                _entityGpsBroadcaster.ClearGpss();
                return;
            }

            var allGpsSources = new Dictionary <long, GridGpsSource>();

            foreach (var(player, rank) in _players.Entities.GetLaggiestEntities(true).Indexed())
            {
                var playerId = player.Id;
                if (!_grids.TryGetLaggiestGridOwnedBy(playerId, out var laggiestGrid))
                {
                    continue;
                }

                var gpsSource = new GridGpsSource(laggiestGrid.Id, player.LagNormal, player.PinRemainingTime, rank);
                allGpsSources[gpsSource.GridId] = gpsSource;
            }

            foreach (var(grid, rank) in _grids.Entities.GetLaggiestEntities(true).Indexed())
            {
                var gpsSource = new GridGpsSource(grid.Id, grid.LagNormal, grid.PinRemainingTime, rank);
                allGpsSources[gpsSource.GridId] = gpsSource;
            }

            await VRageUtils.MoveToGameLoop(cancellationToken);

            _entityGpsBroadcaster.ReplaceGpss(allGpsSources.Values);
            await VRageUtils.MoveToThreadPool(cancellationToken);

            Log.Trace("broadcast done");
        }
Esempio n. 4
0
        bool TryCreateGps(GridGpsSource source, out LocalGpsSource gps)
        {
            if (!VRageUtils.TryGetCubeGridById(source.GridId, out var grid))
            {
                Log.Trace($"broadcast: grid not found: {source.GridId}");
                gps = default;
                return(false);
            }

            var playerName = (string)null;

            if (!grid.BigOwners.TryGetFirst(out var playerId))
            {
                Log.Trace($"grid no owner: \"{grid.DisplayName}\"");
            }
            else if (!MySession.Static.Players.TryGetPlayerById(playerId, out var player))
            {
                Log.Trace($"player not found for grid: \"{grid.DisplayName}\": {playerId}");
            }
            else
            {
                playerName = player.DisplayName;
            }

            var faction    = MySession.Static.Factions.GetPlayerFaction(playerId);
            var factionTag = faction?.Tag;

            var name        = Format(_config.GpsNameFormat);
            var description = Format(_config.GpsDescriptionFormat);

            gps = new LocalGpsSource
            {
                Id              = grid.EntityId,
                Name            = name,
                Color           = ColorUtils.TranslateColor(_config.GpsColorCode),
                Description     = description,
                Position        = grid.PositionComp.GetPosition(),
                Radius          = 0,
                EntityId        = grid.EntityId,
                PromoteLevel    = (int)_config.GpsVisiblePromoteLevel,
                ExcludedPlayers = _config.GpsMutedPlayers.ToArray(),
            };

            return(true);

            string Format(string format)
            {
                return(format
                       .Replace("{grid}", grid.DisplayName)
                       .Replace("{player}", playerName ?? "<none>")
                       .Replace("{faction}", factionTag ?? "<none>")
                       .Replace("{ratio}", $"{source.LongLagNormal * 100:0}%")
                       .Replace("{rank}", GpsUtils.RankToString(source.Rank))
                       .Replace("{time}", GpsUtils.RemainingTimeToString(source.RemainingTime)));
            }
        }
        public async Task Main(CancellationToken canceller)
        {
            Log.Info("started main");

            await VRageUtils.MoveToGameLoop(canceller);

            _entityGpsBroadcaster.ClearGpss();
            await VRageUtils.MoveToThreadPool(canceller);

            _questTracker.Clear();

            // Wait for some time during the session startup
            await TaskUtils.Delay(() => _config.FirstIdleTime.Seconds(), 1.Seconds(), canceller);

            IsIdle = false;

            Log.Info("started collector loop");

            // MAIN LOOP
            while (!canceller.IsCancellationRequested)
            {
                if (!_config.IsEnabled)
                {
                    _grids.Clear();
                    _players.Clear();
                    _questTracker.Clear();
                    _punishExecutor.Clear();
                    _punishChatFeed.Clear();

                    await VRageUtils.MoveToGameLoop(canceller);

                    _entityGpsBroadcaster.ClearGpss();

                    await Task.Delay(1.Seconds(), canceller);

                    return;
                }

                using var _ = CustomProfiling.Profile("AutoModerator.Main");

                await Profile(canceller);

                FixExemptBlockTypeCollection();
                Warn();
                AnnouncePunishments();
                await Punish(canceller);
                await AnnounceDeletedGrids(canceller);

                Log.Debug("interval done");
            }
        }
Esempio n. 6
0
        public async Task Update(IReadOnlyDictionary <long, PunishSource> lags)
        {
            // move to the game loop so we can synchronously operate on blocks
            await VRageUtils.MoveToGameLoop();

            foreach (var(gridId, lag) in lags)
            {
                if (!lag.IsPinned)
                {
                    continue;
                }

                if (!VRageUtils.TryGetCubeGridById(gridId, out var grid))
                {
                    Log.Warn($"grid not found for grid id: {gridId}");
                    continue;
                }

                if (!_punishedIds.Contains(gridId))
                {
                    _punishedIds.Add(gridId);
                    Log.Info($"Punished: \"{grid.DisplayName}\" type: {_config.PunishType}");
                }

                await PunishGrid(grid);

                Log.Debug($"block punish: \"{grid.Name}\" <{lag.GridId}> {_config.PunishType}");

                // move to the next frame so we won't lag the server
                await VRageUtils.MoveToGameLoop();
            }

            foreach (var existingId in _punishedIds)
            {
                if (!lags.ContainsKey(existingId))
                {
                    var name = VRageUtils.TryGetCubeGridById(existingId, out var g) ? $"\"{g.DisplayName}\"" : $"<{existingId}>";
                    Log.Info($"Done punishment: {name}");
                }
            }

            _punishedIds.ExceptWith(lags.Keys);

            // back to some worker thread
            await TaskUtils.MoveToThreadPool();
        }
        async Task AnnounceDeletedGrids(CancellationToken canceller)
        {
            // stop tracking deleted grids & report cheating
            // we're doing this right here to get the max chance of grabbing the owner name
            var lostGrids = new List <TrackedEntity>();

            await VRageUtils.MoveToGameLoop(canceller);

            foreach (var(_, trackedGrid) in _grids.Entities)
            {
                if (!MyEntities.TryGetEntityById(trackedGrid.Id, out _))
                {
                    lostGrids.Add(trackedGrid);
                }
            }

            await TaskUtils.MoveToThreadPool(canceller);

            foreach (var lostGrid in lostGrids)
            {
                _grids.StopTracking(lostGrid.Id);

                // high-profile grid deleted
                if (lostGrid.LagNormal >= _config.QuestLagNormal)
                {
                    var gridName  = lostGrid.Name;
                    var ownerName = lostGrid.OwnerName;
                    Log.Warn($"Laggy grid deleted by player: {gridName}: {ownerName}");

                    if (_config.EnablePunishChatFeed)
                    {
                        _chatManager.SendMessage(_config.PunishReportChatName, 0, $"Laggy grid deleted by player: {gridName}: {ownerName}");
                    }
                }
            }

            Log.Trace("announcing deleted entities done");
        }