diff --git a/src/main/scala/li/cil/oc/server/component/traits/InventoryWorldControl.scala b/src/main/scala/li/cil/oc/server/component/traits/InventoryWorldControl.scala index 7d563a06d..a771dc054 100644 --- a/src/main/scala/li/cil/oc/server/component/traits/InventoryWorldControl.scala +++ b/src/main/scala/li/cil/oc/server/component/traits/InventoryWorldControl.scala @@ -1,5 +1,6 @@ package li.cil.oc.server.component.traits +import cpw.mods.fml.common.eventhandler.Event.Result import li.cil.oc.Settings import li.cil.oc.api.machine.Arguments import li.cil.oc.api.machine.Callback @@ -10,7 +11,9 @@ import li.cil.oc.util.InventoryUtils import li.cil.oc.util.ResultWrapper.result import net.minecraft.entity.item.EntityItem import net.minecraft.item.ItemBlock +import net.minecraftforge.common.MinecraftForge import net.minecraftforge.common.util.ForgeDirection +import net.minecraftforge.event.entity.item.ItemTossEvent trait InventoryWorldControl extends InventoryAware with WorldAware with SideRestricted { @Callback(doc = "function(side:number[, fuzzy:boolean=false]):boolean -- Compare the block on the specified side with the one in the selected slot. Returns true if equal.") @@ -54,8 +57,15 @@ trait InventoryWorldControl extends InventoryAware with WorldAware with SideRest case _ => // No inventory to drop into, drop into the world. val dropped = inventory.decrStackSize(selectedSlot, count) + val validator = (item: EntityItem) => { + val event = new ItemTossEvent(item, fakePlayer) + val canceled = MinecraftForge.EVENT_BUS.post(event) + val denied = event.hasResult && event.getResult == Result.DENY + !canceled && !denied + } if (dropped != null && dropped.stackSize > 0) { - InventoryUtils.spawnStackInWorld(position, dropped, Some(facing)) + if (InventoryUtils.spawnStackInWorld(position, dropped, Some(facing), Some(validator)) == null) + fakePlayer.inventory.addItemStackToInventory(dropped) } } diff --git a/src/main/scala/li/cil/oc/util/InventoryUtils.scala b/src/main/scala/li/cil/oc/util/InventoryUtils.scala index ef4c5a2b5..731926027 100644 --- a/src/main/scala/li/cil/oc/util/InventoryUtils.scala +++ b/src/main/scala/li/cil/oc/util/InventoryUtils.scala @@ -227,14 +227,14 @@ object InventoryUtils { } /** - * Extracts an item stack from an inventory. - *

- * This will try to remove items of the same type as the specified item stack - * up to the number of the stack's size for all slots in the specified inventory. - *

- * This uses the extractFromInventorySlot method, and therefore - * handles special cases such as sided inventories and stack size limits. - */ + * Extracts an item stack from an inventory. + *

+ * This will try to remove items of the same type as the specified item stack + * up to the number of the stack's size for all slots in the specified inventory. + *

+ * This uses the extractFromInventorySlot method, and therefore + * handles special cases such as sided inventories and stack size limits. + */ def extractFromInventory(stack: ItemStack, inventory: IInventory, side: ForgeDirection, simulate: Boolean = false) = { val range = inventory match { case sided: ISidedInventory => sided.getAccessibleSlotsFromSide(side.ordinal).toIterable @@ -362,7 +362,7 @@ object InventoryUtils { /** * Utility method for spawning an item stack in the world. */ - def spawnStackInWorld(position: BlockPosition, stack: ItemStack, direction: Option[ForgeDirection] = None): EntityItem = position.world match { + def spawnStackInWorld(position: BlockPosition, stack: ItemStack, direction: Option[ForgeDirection] = None, validator: Option[EntityItem => Boolean] = None): EntityItem = position.world match { case Some(world) if stack != null && stack.stackSize > 0 => val rng = world.rand val (ox, oy, oz) = direction.fold((0, 0, 0))(d => (d.offsetX, d.offsetY, d.offsetZ)) @@ -376,8 +376,11 @@ object InventoryUtils { entity.motionY = 0.0125 * (rng.nextDouble - 0.5) + oy * 0.08 + (ox + oz) * 0.03 entity.motionZ = 0.0125 * (rng.nextDouble - 0.5) + oz * 0.03 entity.delayBeforeCanPickup = 15 - world.spawnEntityInWorld(entity) - entity + if (validator.fold(true)(_(entity))) { + world.spawnEntityInWorld(entity) + entity + } + else null case _ => null } }