Exemplo n.º 1
0
        public async Task OnUpdate(ClientUpdate e)
        {
            foreach (var change in e.TileUpdates)
            {
                await Map.SetAsync(change.Position, change.TileInfo);
            }

            foreach (var ev in e.Events)
            {
                var moveEvent = ev as EntityMoveEvent;

                if (moveEvent != null && !Map.ChunkLoader.IsLoadedOrLoading(moveEvent.SourcePosition / Chunk.Size))
                {
                    // The entity comes from a chunk we have not loaded => spawn it first
                    Map.Emit(new EntitySpawnEvent(moveEvent.SourcePosition, moveEvent.Target.Entity));
                }

                Map.Emit(ev);

                if (moveEvent != null && !Map.ChunkLoader.IsLoadedOrLoading(moveEvent.TargetPosition / Chunk.Size))
                {
                    // The entity moves into an area we have not loaded => despawn it after the move
                    Map.Emit(new EntityDespawnEvent(moveEvent.TargetPosition, moveEvent.Source.Entity));
                }
            }

            AnalyzeEvents(e.Events);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Sends a subset of the changes and events of the specified transaction to the
        /// clients depending on which chunks each client has currently loaded.
        /// </summary>
        /// <param name="transaction">The transaction that contains the changes that are broadcasted</param>
        /// <param name="newVersion">The version to be used for the updates tiles</param>
        /// <param name="excludedConnection">An optional connection that is excluded and does not receive the tile updates</param>
        /// <returns></returns>
        private async Task BroadcastChangesAsync(ITransactionWithMoveSupport transaction, int newVersion, ClientConnection excludedConnection = null)
        {
            // Check which players have moved and update their positions in map metadata
            var playerMoveEvents = transaction.Events
                .OfType<EntityMoveEvent>()
                .Where(e => e.Source.Entity is PlayerEntity)
                .Select(e => new { PlayerId = (e.Source.Entity as PlayerEntity)?.PlayerId, NewPosition = e.TargetPosition });

            foreach (var move in playerMoveEvents)
                Map.Metadata.Players[move.PlayerId] =
                    Map.Metadata.Players[move.PlayerId].WithPosition(move.NewPosition);

            // Notify clients that have loaded the affected chunks
            foreach (var conn in _clients.Values)
            {
                if (conn == excludedConnection)
                    continue; // Skip calling client

                var relevantChanges = transaction.Changes
                    .Where(change => conn.LoadedChunks.Contains(change.Key / Chunk.Size))
                    .Select(change => new TileUpdate(change.Key, change.Value.WithVersion(newVersion)))
                    .ToArray();

                var relevantEvents = transaction.Events
                    .OfType<ILocatedGameEvent>()
                    .Where(ev =>
                        ev.GetPositions().Any(p => conn.LoadedChunks.Contains(p / Chunk.Size)) ||
                        ((ev as EntitySpawnEvent)?.Entity as PlayerEntity)?.PlayerId == conn.ClientInfo.PlayerId)
                    .ToArray();

                if (relevantChanges.Any() || relevantEvents.Any())
                {
                    // If there are any tile changes or any events that are of interest
                    // to the client, push them to the client.
                    var update = new ClientUpdate(relevantChanges, relevantEvents);
                    await conn.ClientStub.OnUpdate(update);
                }
            }
        }