Firing PlayerInteractEvent when agents (robots, drones) are interacting with in-world inventories and in the inventory driver. See #900.

Hopefully doesn't break anything...
This commit is contained in:
Florian Nücke 2015-03-11 15:45:29 +01:00
parent ffd38e59ff
commit c0690bb07f
5 changed files with 25 additions and 11 deletions

View File

@ -1,5 +1,6 @@
package li.cil.oc.integration.vanilla;
import cpw.mods.fml.common.eventhandler.Event;
import li.cil.oc.Settings;
import li.cil.oc.api.machine.Arguments;
import li.cil.oc.api.machine.Callback;
@ -7,14 +8,16 @@ import li.cil.oc.api.machine.Context;
import li.cil.oc.api.network.ManagedEnvironment;
import li.cil.oc.api.prefab.DriverTileEntity;
import li.cil.oc.integration.ManagedTileEntityEnvironment;
import li.cil.oc.util.BlockPosition;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Vec3;
import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
import net.minecraftforge.common.util.FakePlayerFactory;
import net.minecraftforge.event.ForgeEventFactory;
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
public final class DriverInventory extends DriverTileEntity {
@Override
@ -29,12 +32,12 @@ public final class DriverInventory extends DriverTileEntity {
public static final class Environment extends ManagedTileEntityEnvironment<IInventory> {
private final EntityPlayer fakePlayer;
private final Vec3 position;
private final BlockPosition position;
public Environment(final TileEntity tileEntity, final World world) {
super((IInventory) tileEntity, "inventory");
fakePlayer = FakePlayerFactory.get((WorldServer) world, Settings.get().fakePlayerProfile());
position = Vec3.createVectorHelper(tileEntity.xCoord + 0.5, tileEntity.yCoord + 0.5, tileEntity.zCoord + 0.5);
position = BlockPosition.apply(tileEntity.xCoord, tileEntity.yCoord, tileEntity.zCoord, world);
}
@Callback(doc = "function():string -- Get the name of this inventory.")
@ -172,8 +175,9 @@ public final class DriverInventory extends DriverTileEntity {
private boolean notPermitted() {
synchronized (fakePlayer) {
fakePlayer.setPosition(position.xCoord, position.yCoord, position.zCoord);
return !tileEntity.isUseableByPlayer(fakePlayer);
fakePlayer.setPosition(position.toVec3().xCoord, position.toVec3().yCoord, position.toVec3().zCoord);
final PlayerInteractEvent event = ForgeEventFactory.onPlayerInteract(fakePlayer, PlayerInteractEvent.Action.RIGHT_CLICK_BLOCK, position.x(), position.y(), position.z(), 0, fakePlayer.getEntityWorld());
return !event.isCanceled() && event.useBlock != Event.Result.DENY && !tileEntity.isUseableByPlayer(fakePlayer);
}
}
}

View File

@ -36,8 +36,9 @@ trait InventoryWorldControl extends InventoryAware with WorldAware with SideRest
val count = args.optionalItemCount(1)
val stack = inventory.getStackInSlot(selectedSlot)
if (stack != null && stack.stackSize > 0) {
InventoryUtils.inventoryAt(position.offset(facing)) match {
case Some(inv) if inv.isUseableByPlayer(fakePlayer) =>
val blockPos = position.offset(facing)
InventoryUtils.inventoryAt(blockPos) match {
case Some(inv) if inv.isUseableByPlayer(fakePlayer) && mayInteract(blockPos, facing.getOpposite) =>
if (!InventoryUtils.insertIntoInventory(stack, inv, Option(facing.getOpposite), count)) {
// Cannot drop into that inventory.
return result(false, "inventory full")
@ -70,8 +71,9 @@ trait InventoryWorldControl extends InventoryAware with WorldAware with SideRest
val facing = checkSideForAction(args, 0)
val count = args.optionalItemCount(1)
if (InventoryUtils.inventoryAt(position.offset(facing)).exists(inventory => {
inventory.isUseableByPlayer(fakePlayer) && InventoryUtils.extractFromInventory(InventoryUtils.insertIntoInventory(_, this.inventory, slots = Option(insertionSlots)), inventory, facing.getOpposite, count)
val blockPos = position.offset(facing)
if (InventoryUtils.inventoryAt(blockPos).exists(inventory => {
inventory.isUseableByPlayer(fakePlayer) && mayInteract(blockPos, facing.getOpposite) && InventoryUtils.extractFromInventory(InventoryUtils.insertIntoInventory(_, this.inventory, slots = Option(insertionSlots)), inventory, facing.getOpposite, count)
})) {
context.pause(Settings.get.suckDelay)
result(true)

View File

@ -56,7 +56,7 @@ trait InventoryWorldControlMk2 extends InventoryAware with WorldAware with SideR
private def withInventory(side: ForgeDirection, f: IInventory => Array[AnyRef]) =
InventoryUtils.inventoryAt(position.offset(side)) match {
case Some(inventory) if inventory.isUseableByPlayer(fakePlayer) => f(inventory)
case Some(inventory) if inventory.isUseableByPlayer(fakePlayer) && mayInteract(position.offset(side), side.getOpposite) => f(inventory)
case _ => result(Unit, "no inventory")
}
}

View File

@ -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.util.BlockPosition
import li.cil.oc.util.ExtendedBlock._
@ -13,6 +14,8 @@ import net.minecraft.world.WorldServer
import net.minecraftforge.common.MinecraftForge
import net.minecraftforge.common.util.FakePlayerFactory
import net.minecraftforge.common.util.ForgeDirection
import net.minecraftforge.event.ForgeEventFactory
import net.minecraftforge.event.entity.player.PlayerInteractEvent.Action
import net.minecraftforge.event.world.BlockEvent
import net.minecraftforge.fluids.FluidRegistry
@ -33,6 +36,11 @@ trait WorldAware {
player
}
def mayInteract(blockPos: BlockPosition, face: ForgeDirection): Boolean = {
val event = ForgeEventFactory.onPlayerInteract(fakePlayer, Action.RIGHT_CLICK_BLOCK, blockPos.x, blockPos.y, blockPos.z, face.ordinal(), world)
!event.isCanceled && event.useBlock != Result.DENY
}
def entitiesInBounds[Type <: Entity : ClassTag](bounds: AxisAlignedBB) = {
world.getEntitiesWithinAABB(classTag[Type].runtimeClass, bounds).map(_.asInstanceOf[Type])
}

View File

@ -66,7 +66,7 @@ trait WorldInventoryAnalytics extends WorldAware with SideRestricted with Networ
private def withInventory(side: ForgeDirection, f: IInventory => Array[AnyRef]) =
InventoryUtils.inventoryAt(position.offset(side)) match {
case Some(inventory) if inventory.isUseableByPlayer(fakePlayer) => f(inventory)
case Some(inventory) if inventory.isUseableByPlayer(fakePlayer) && mayInteract(position.offset(side), side.getOpposite) => f(inventory)
case _ => result(null, "no inventory")
}
}