示例#1
0
        private async Task<bool> MoveCoreAsync(Point sourcePosition, Point targetPosition, ITransactionWithMoveSupport transaction)
        {
            var source = await GetAsync(sourcePosition);
            var target = await GetAsync(targetPosition);

            var oldSource = source;
            var oldTarget = target;

            source.Tile.EnsureNotNull();
            target.Tile.EnsureNotNull();

            if (source.Tile.Entity == Entity.None)
            {
                // Cancel if there's no entity to move
                transaction.IsSealed = true;
                return false;
            }

            var move = new EntityMoveInfo(source.Tile.Entity, sourcePosition, targetPosition);
            transaction.Moves.Push(move);

            IBeginMoveArgs beginMoveArgs = new GameplayArgs(transaction, this);
            IDetachArgs detachArgs = new GameplayArgs(transaction, this);
            IAttachArgs attachArgs = new GameplayArgs(transaction, this);

            // OnBeginMove: Notify entity that a move has been initiated
            await source.Tile.Entity.BeginMoveAsync(beginMoveArgs);
            beginMoveArgs.ValidateResult();
            if (transaction.IsSealed) return false;

            var newSource = source.WithTile(Tile.Compose(source.Tile, beginMoveArgs.ResultingEntity));
            if (transaction.Set(sourcePosition, source, newSource))
                source = newSource;

            move.Entity = beginMoveArgs.ResultingEntity;

            // Detach: Remove the entity from the source tile
            await source.Tile.DetachEntityAsync(detachArgs);
            detachArgs.ValidateResult();
            if (transaction.IsSealed) return false;

            // Attach: Add the entity to the target tile
            await target.Tile.AttachEntityAsync(attachArgs);
            attachArgs.ValidateResult();
            if (transaction.IsSealed) return false;

            // Detach from old tile, attach to new tile have succeeded
            // => Apply changes to transaction
            var newSource2 = source.WithTile(detachArgs.Result);
            if (transaction.Set(sourcePosition, source, newSource2))
                source = newSource2;

            var newTarget = target.WithTile(attachArgs.Result);
            if (transaction.Set(targetPosition, target, newTarget))
                target = newTarget;

            // Emit events
            var moveEvent = new EntityMoveEvent(sourcePosition, targetPosition, oldSource.Tile, target.Tile);
            transaction.Emit(moveEvent);

            if (source.Tile.Entity != Entity.None)
            {
                // A new entity has been created at source position
                var spawnEvent = new EntitySpawnEvent(sourcePosition, source.Tile.Entity);
                transaction.Emit(spawnEvent);
            }

            if (oldTarget.Tile.Entity != Entity.None)
            {
                // The entity at target position has either been replaced
                // or it has been moved/collected/... during a nested move
                var oldTargetEntityOverwritten =
                    !(transaction.Events.OfType<EntityDespawnEvent>().Any(ev => ev.Position == targetPosition) ||
                    transaction.Events.OfType<EntityMoveEvent>().Any(ev => ev.SourcePosition == targetPosition));

                if (oldTargetEntityOverwritten)
                {
                    // If replaced, emit despawn event
                    var despawnEvent = new EntityDespawnEvent(targetPosition, oldTarget.Tile.Entity);
                    transaction.Emit(despawnEvent);
                }
            }

            transaction.Moves.Pop();
            return true;
        }
示例#2
0
        private void OnChunkUnloaded(KeyValuePair<Point, IChunk> kvp)
        {
            for (var y = 0; y < Chunk.Size; y++)
            {
                for (var x = 0; x < Chunk.Size; x++)
                {
                    var localPosition = new Point(x, y);
                    var globalPosition = kvp.Key * Chunk.Size + localPosition;
                    var tileInfo = kvp.Value[localPosition];
                    Dependencies.RemoveDependenciesOf(tileInfo.Tile, globalPosition);
                    Dependencies.RemoveDependenciesOn(globalPosition);

                    // For entities emit a despawn event
                    if (tileInfo.Tile.Entity != Entity.None)
                    {
                        var despawnEvent = new EntityDespawnEvent(globalPosition, tileInfo.Tile.Entity);
                        _eventSource.OnNext(despawnEvent);
                    }
                }
            }

            _eventSource.OnNext(new ChunkRemovedEvent(kvp.Value));
        }
示例#3
0
 private void OnDespawn(EntityDespawnEvent e)
 {
     _despawnSubscription.Dispose();
     _isDespawned = true;
 }