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); }