/// <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); }
/// <summary> /// Attempts to get this player to place down its /// <see cref="CarriedBlock"/> (if any) at the specified /// selection, returning whether it was successful. /// </summary> /// <example cref="ArgumentNullException"> Thrown if player or selection is null. </exception> public static bool PlaceCarried(this IPlayer player, BlockSelection selection, CarrySlot slot) { if (player == null) { throw new ArgumentNullException(nameof(player)); } if (selection == null) { throw new ArgumentNullException(nameof(selection)); } if (!player.Entity.World.Claims.TryAccess( player, selection.Position, EnumBlockAccessFlags.BuildOrBreak)) { return(false); } var carried = CarriedBlock.Get(player.Entity, slot); if (carried == null) { return(false); } return(carried.PlaceDown(player.Entity.World, selection, player.Entity)); }
/// <summary> /// Attempts to get this entity to pick up the block the /// specified position as a <see cref="CarriedBlock"/>, /// returning whether it was successful. /// </summary> /// <example cref="ArgumentNullException"> Thrown if entity or pos is null. </exception> public static bool Carry(this Entity entity, BlockPos pos, CarrySlot slot, bool checkIsCarryable = true) { if (CarriedBlock.Get(entity, slot) != null) { return(false); } var carried = CarriedBlock.PickUp(entity.World, pos, slot, checkIsCarryable); if (carried == null) { return(false); } carried.Set(entity, slot); carried.PlaySound(pos, entity.World, (entity as EntityPlayer)); return(true); }
/// <summary> /// Attempts to get this player to place down its /// <see cref="CarriedBlock"/> (if any) at the specified /// selection, returning whether it was successful. /// </summary> /// <example cref="ArgumentNullException"> Thrown if player or selection is null. </exception> public static bool PlaceCarried(this IPlayer player, BlockSelection selection, CarrySlot slot) { if (player == null) { throw new ArgumentNullException(nameof(player)); } if (selection == null) { throw new ArgumentNullException(nameof(selection)); } var carried = CarriedBlock.Get(player.Entity, slot); if (carried == null) { return(false); } return(carried.PlaceDown(player.Entity.World, selection, player.Entity)); }
/// <summary> /// Attempts to make this entity drop its <see cref="CarriedBlock"/> /// (if any) at the specified position, returning whether it was successful. /// </summary> /// <example cref="ArgumentNullException"> Thrown if entity or pos is null. </exception> public static bool DropCarried(this IEntity entity, BlockPos pos) { if (pos == null) { throw new ArgumentNullException(nameof(pos)); } var carried = CarriedBlock.Get(entity); if (carried == null) { return(false); } var selection = new BlockSelection { Position = pos, Face = BlockFacing.UP, HitPosition = new Vec3d(0.5, 0.5, 0.5), }; return(carried.PlaceDown(entity.World, selection, entity)); }
/// <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. }
/// <summary> Returns the <see cref="CarriedBlock"/> this entity /// is carrying in the specified slot, or null of none. </summary> /// <example cref="ArgumentNullException"> Thrown if entity or pos is null. </exception> public static CarriedBlock GetCarried(this Entity entity, CarrySlot slot) => CarriedBlock.Get(entity, slot);
/// <summary> Returns the <see cref="CarriedBlock"/> /// this entity is carrying, or null of none. </summary> /// <example cref="ArgumentNullException"> Thrown if entity or pos is null. </exception> public static CarriedBlock GetCarried(this IEntity entity) => CarriedBlock.Get(entity);