Example #1
0
        /// <summary>
        ///   Attempts to swap the <see cref="CarriedBlock"/>s currently carried in the
        ///   entity's <paramref name="first"/> and <paramref name="second"/> slots.
        /// </summary>
        /// <example cref="ArgumentNullException"> Thrown if entity is null. </exception>
        public static bool Swap(this Entity entity, CarrySlot first, CarrySlot second)
        {
            if (first == second)
            {
                throw new ArgumentException("Slots can't be the same");
            }

            var carriedFirst  = CarriedBlock.Get(entity, first);
            var carriedSecond = CarriedBlock.Get(entity, second);

            if ((carriedFirst == null) && (carriedSecond == null))
            {
                return(false);
            }

            CarriedBlock.Remove(entity, first);
            CarriedBlock.Remove(entity, second);

            if (carriedFirst != null)
            {
                carriedFirst.Set(entity, second);
            }
            if (carriedSecond != null)
            {
                carriedSecond.Set(entity, first);
            }

            return(true);
        }
Example #2
0
        /// <summary> Attempts to make this entity drop its carried blocks from the
        ///           specified slots around its current position in the specified area. </summary>
        /// <example cref="ArgumentNullException"> Thrown if entity or slots is null. </exception>
        /// <example cref="ArgumentOutOfRangeException"> Thrown if hSize or vSize is negative. </exception>
        public static void DropCarried(this Entity entity, IEnumerable <CarrySlot> slots,
                                       int hSize = 2, int vSize = 4)
        {
            if (entity == null)
            {
                throw new ArgumentNullException(nameof(entity));
            }
            if (slots == null)
            {
                throw new ArgumentNullException(nameof(slots));
            }
            if (hSize < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(hSize));
            }
            if (vSize < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(vSize));
            }

            var remaining = new HashSet <CarriedBlock>(
                slots.Select(s => entity.GetCarried(s))
                .Where(c => (c != null)));

            if (remaining.Count == 0)
            {
                return;
            }

            bool Drop(BlockPos pos, CarriedBlock block)
            {
                if (!block.PlaceDown(entity.World, new BlockSelection {
                    Position = pos
                }, null))
                {
                    return(false);
                }
                CarriedBlock.Remove(entity, block.Slot);
                return(true);
            }

            var centerBlock  = entity.Pos.AsBlockPos;
            var nearbyBlocks = new List <BlockPos>((hSize * 2 + 1) * (hSize * 2 + 1));

            for (int x = -hSize; x <= hSize; x++)
            {
                for (int z = -hSize; z <= hSize; z++)
                {
                    nearbyBlocks.Add(centerBlock.AddCopy(x, 0, z));
                }
            }
            nearbyBlocks = nearbyBlocks.OrderBy(b => b.DistanceTo(centerBlock)).ToList();

            var accessor   = entity.World.BlockAccessor;
            var blockIndex = 0;
            var distance   = 0;

            while (remaining.Count > 0)
            {
                var pos = nearbyBlocks[blockIndex];
                if (Math.Abs(pos.Y - centerBlock.Y) <= vSize)
                {
                    var sign      = Math.Sign(pos.Y - centerBlock.Y);
                    var testBlock = accessor.GetBlock(pos);
                    var placeable = remaining.FirstOrDefault(c => testBlock.IsReplacableBy(c.Block));
                    if (sign == 0)
                    {
                        sign = ((placeable != null) ? -1 : 1);
                    }
                    else if (sign > 0)
                    {
                        if ((placeable != null) && Drop(pos, placeable))
                        {
                            remaining.Remove(placeable);
                        }
                    }
                    else if ((placeable == null))
                    {
                        var above = pos.UpCopy();
                        testBlock = accessor.GetBlock(above);
                        placeable = remaining.FirstOrDefault(c => testBlock.IsReplacableBy(c.Block));
                        if ((placeable != null) && Drop(above, placeable))
                        {
                            remaining.Remove(placeable);
                        }
                    }
                    pos.Add(0, sign, 0);
                }
                else if (blockIndex >= nearbyBlocks.Count)
                {
                    break;
                }

                if (++distance > 2)
                {
                    distance = 0;
                    blockIndex++;
                    if (blockIndex % 4 == 4)
                    {
                        if (++blockIndex >= nearbyBlocks.Count)
                        {
                            blockIndex = 0;
                        }
                    }
                }
            }

            // FIXME: Drop container contents if blocks could not be placed.
            //        Right now, the player just gets to keep them equipped.
        }