Skip to content

Commit

Permalink
Fire item toss event when agents try to drop items into the world.
Browse files Browse the repository at this point in the history
  • Loading branch information
fnuecke committed Feb 4, 2017
1 parent 7069056 commit 81c34e0
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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.")
Expand Down Expand Up @@ -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)
}
}

Expand Down
25 changes: 14 additions & 11 deletions src/main/scala/li/cil/oc/util/InventoryUtils.scala
Original file line number Diff line number Diff line change
Expand Up @@ -227,14 +227,14 @@ object InventoryUtils {
}

/**
* Extracts an item stack from an inventory.
* <p/>
* 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.
* <p/>
* This uses the <tt>extractFromInventorySlot</tt> method, and therefore
* handles special cases such as sided inventories and stack size limits.
*/
* Extracts an item stack from an inventory.
* <p/>
* 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.
* <p/>
* This uses the <tt>extractFromInventorySlot</tt> 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
Expand Down Expand Up @@ -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))
Expand All @@ -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
}
}

0 comments on commit 81c34e0

Please sign in to comment.