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