/// <summary>
 /// Initializes a new instance of the <see cref="PlayerSynchronizationMessage"/> class.
 /// </summary>
 /// <param name="lastKnownRegion">The last known region.</param>
 /// <param name="position">The players current position.</param>
 /// <param name="regionChanged">if set to <c>true</c> [region changed].</param>
 /// <param name="segment">The current player's synchronization segment.</param>
 /// <param name="localPlayers">The number local players.</param>
 /// <param name="segments">The list of segments.</param>
 public PlayerSynchronizationMessage(Position lastKnownRegion, Position position, bool regionChanged, SynchronizationSegment segment, int localPlayers, List <SynchronizationSegment> segments)
 {
     LastKnownRegion = lastKnownRegion;
     Position        = position;
     RegionChanged   = regionChanged;
     Segment         = segment;
     LocalPlayers    = localPlayers;
     Segments        = segments;
 }
        private void PutMovementUpdate(SynchronizationSegment seg, MessageFrameBuilder builder)
        {
            bool updateRequired = seg.BlockSet.Size() > 0;

            if (seg.Type == SegmentType.Teleport)
            {
                var      teleportSeg = ((TeleportSegment)seg);
                Position position    = teleportSeg.Destination;
                builder.PutBits(1, 1);
                builder.PutBits(2, 3);
                builder.PutBits(1, RegionChanged ? 0 : 1);
                builder.PutBits(1, updateRequired ? 1 : 0);
                builder.PutBits(7, position.GetLocalX(LastKnownRegion));
                builder.PutBits(2, position.Height);
                builder.PutBits(7, position.GetLocalY(LastKnownRegion));
            }
            else if (seg.Type == SegmentType.Run)
            {
                Direction[] directions = ((MovementSegment)seg).Directions;
                builder.PutBits(1, 1);
                builder.PutBits(2, 2);
                builder.PutBits(3, directions[0].IntValue);
                builder.PutBits(3, directions[1].IntValue);
                builder.PutBits(1, updateRequired ? 1 : 0);
            }
            else if (seg.Type == SegmentType.Walk)
            {
                Direction[] directions = ((MovementSegment)seg).Directions;
                builder.PutBits(1, 1);
                builder.PutBits(2, 1);
                builder.PutBits(3, directions[0].IntValue);
                builder.PutBits(1, updateRequired ? 1 : 0);
            }
            else
            {
                if (updateRequired)
                {
                    builder.PutBits(1, 1);
                    builder.PutBits(2, 0);
                }
                else
                {
                    builder.PutBits(1, 0);
                }
            }
        }
        private void PutBlocks(SynchronizationSegment segment, MessageFrameBuilder builder)
        {
            var blockSet = segment.BlockSet;

            if (blockSet.Size() > 0)
            {
                int mask = 0;
                if (blockSet.Contains <AnimationBlock>())
                {
                    mask |= 0x8;
                }

                if (blockSet.Contains <AppearanceBlock>())
                {
                    mask |= 0x10;
                }

                if (mask >= 0x100)
                {
                    mask |= 0x20;
                    builder.Put(MessageType.Byte, (mask & 0xFF));
                    builder.Put(MessageType.Byte, (mask >> 8));
                }
                else
                {
                    builder.Put(MessageType.Byte, mask);
                }

                if (blockSet.Contains <AnimationBlock>())
                {
                    PutAnimationBlock(blockSet.Get <AnimationBlock>(), builder);
                }

                if (blockSet.Contains <AppearanceBlock>())
                {
                    PutAppearanceBlock(blockSet.Get <AppearanceBlock>(), builder);
                }
            }
        }
Exemplo n.º 4
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);
        }