Example #1
0
        public async Task UpdateAsync(Player player)
        {
            Position lastKnownRegion = player.LastKnownRegion;
            var      regionChanged   = player.RegionChanged;

            int[] appearanceTickets = player.AppearanceTickets;

            SynchronizationBlockSet blockSet = player.BlockSet;

            Position position = player.Position;

            SynchronizationSegment segment = (player.IsTeleporting || player.RegionChanged) ?
                                             new TeleportSegment(blockSet, position) : new MovementSegment(blockSet, player.GetDirections());

            List <Player> localPlayers = player.LocalPlayerList;
            int           oldCount     = localPlayers.Count;

            List <SynchronizationSegment> segments = new();
            int distance = player.ViewingDistance;

            foreach (var other in localPlayers.ToList())
            {
                if (Removeable(position, distance, other))
                {
                    localPlayers.Remove(other);
                    segments.Add(new RemoveMobSegment());
                }
                else
                {
                    segments.Add(new MovementSegment(other.BlockSet, other.GetDirections()));
                }
            }

            int added = 0, count = localPlayers.Count;

            IRegion current = _regionRepository.FromPosition(position);
            HashSet <RegionCoordinates> regions = current.GetSurrounding();

            regions.Add(current.Coordinates);

            IEnumerable <Player> players = regions.Select(t => _regionRepository.Get(t))
                                           .SelectMany(region => region.GetEntities <Player>(EntityType.Player));

            foreach (var other in players)
            {
                if (count >= MaximumLocalPlayers)
                {
                    player.ExcessivePlayers = true;
                    break;
                }
                else if (added >= NewPlayersPerCycle)
                {
                    break;
                }

                Position local = other.Position;

                if (other != player && local.IsWithinDistance(position, distance) && !localPlayers.Contains(other))
                {
                    localPlayers.Add(other);
                    count++;
                    added++;

                    blockSet = other.BlockSet;

                    int index = other.Index;

                    if (!blockSet.Contains <AppearanceBlock>() && !HasCachedAppearance(appearanceTickets, index - 1, other.AppearanceTicket))
                    {
                        blockSet = (SynchronizationBlockSet)blockSet.Clone();
                        blockSet.Add(SynchronizationBlock.CreateAppearanceBlock(other));
                    }
                    segments.Add(new AddPlayerSegment(blockSet, index, local));
                }
            }

            PlayerSynchronizationMessage message = new PlayerSynchronizationMessage(lastKnownRegion, position,
                                                                                    regionChanged, segment, oldCount, segments);
            await player.SendAsync(message);
        }