add a AgentContainer to improve item use detection

This new AgentContainer provides slots for all agent inventory items so
that proper change detection can occur for using items

properly closes #2327
This commit is contained in:
payonel 2018-10-29 21:42:14 -07:00
parent 4ff26e91a0
commit 89c8885624
3 changed files with 92 additions and 78 deletions

View File

@ -0,0 +1,43 @@
package li.cil.oc.server.agent
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.inventory.{Container, IContainerListener, IInventory, Slot}
import li.cil.oc.server.agent
import net.minecraft.item.ItemStack
import net.minecraft.util.NonNullList
class AgentContainer(player: agent.Player) extends Container {
{
for (slot <- 0 until player.agent.equipmentInventory.getSizeInventory) {
this.addSlotToContainer(new Slot(player.inventory, -1 - slot, 0, 0))
}
for (slot <- 0 until player.agent.mainInventory.getSizeInventory) {
this.addSlotToContainer(new Slot(player.inventory, slot, 0, 0))
}
this.addListener(new IContainerListener {
override def sendAllContents(containerToSend: Container, itemsList: NonNullList[ItemStack]): Unit = {}
override def sendWindowProperty(containerIn: Container, varToUpdate: Int, newValue: Int): Unit = {}
override def sendAllWindowProperties(containerIn: Container, inventory: IInventory): Unit = {}
override def sendSlotContents(containerToSend: Container, index: Int, stack: ItemStack): Unit = {
// an action has updated the agent.inventory via slots
// thus the player.inventory is outdated in this regard
val relativeIndex: Int = containerToSend.inventorySlots.get(index).getSlotIndex
if (relativeIndex < 0) {
if (~relativeIndex < player.inventory.armorInventory.size) {
player.inventory.armorInventory.set(~relativeIndex, stack)
}
}
else if (relativeIndex < player.inventory.mainInventory.size) {
player.inventory.mainInventory.set(relativeIndex, stack)
}
}
})
}
override def canInteractWith(player: EntityPlayer): Boolean = true
}

View File

@ -43,17 +43,6 @@ class Inventory(playerEntity: EntityPlayer, val agent: internal.Agent) extends I
}
}
// override def consumeInventoryItem(item: Item): Boolean = {
// for ((slot, stack) <- inventorySlots.map(slot => (slot, getStackInSlot(slot))) if !stack.isEmpty && stack.getItem == item && stack.stackSize > 0) {
// stack.stackSize -= 1
// if (stack.stackSize <= 0) {
// setInventorySlotContents(slot, ItemStack.EMPTY)
// }
// return true
// }
// false
// }
override def addItemStackToInventory(stack: ItemStack): Boolean = {
val slots = this.indices.drop(agent.selectedSlot) ++ this.indices.take(agent.selectedSlot)
InventoryUtils.insertIntoInventory(stack, InventoryUtils.asItemHandler(this), slots = Option(slots))
@ -67,7 +56,7 @@ class Inventory(playerEntity: EntityPlayer, val agent: internal.Agent) extends I
override def readFromNBT(nbt: NBTTagList) {}
override def armorItemInSlot(slot: Int) = ItemStack.EMPTY
override def armorItemInSlot(slot: Int): ItemStack = ItemStack.EMPTY
override def damageArmor(damage: Float) {}

View File

@ -145,7 +145,7 @@ class Player(val agent: internal.Agent) extends FakePlayer(agent.world.asInstanc
this.inventory = new Inventory(this, agent)
this.inventory.player = this
// because the inventory was just overwritten, the container is now detached
this.inventoryContainer = new ContainerPlayer(this.inventory, !world.isRemote, this)
this.inventoryContainer = new AgentContainer(this)
this.openContainer = this.inventoryContainer
def setItemHandler(fieldName: String, handler: IItemHandler): Unit = {
@ -158,29 +158,6 @@ class Player(val agent: internal.Agent) extends FakePlayer(agent.world.asInstanc
setItemHandler("playerMainHandler", new PlayerMainInvWrapper(inventory))
setItemHandler("playerEquipmentHandler", new CombinedInvWrapper(new PlayerArmorInvWrapper(inventory), new PlayerOffhandInvWrapper(inventory)))
setItemHandler("playerJoinedHandler", new PlayerInvWrapper(inventory))
this.inventoryContainer.addListener(new IContainerListener{
override def sendAllContents(containerToSend: Container, itemsList: NonNullList[ItemStack]): Unit = {}
override def sendWindowProperty(containerIn: Container, varToUpdate: Int, newValue: Int): Unit = {}
override def sendAllWindowProperties(containerIn: Container, inventory: IInventory): Unit = {}
override def sendSlotContents(containerToSend: Container, index: Int, stack: ItemStack): Unit = {
// an action has updated the agent.inventory via slots
// thus the player.inventory is outdated in this regard
var relativeIndex: Int = containerToSend.inventorySlots.get(index).getSlotIndex
def tryInv(inv: NonNullList[ItemStack]): Boolean = {
if (relativeIndex >= 0 && relativeIndex < inv.size) {
inv.set(relativeIndex, stack)
true
} else {
relativeIndex -= inv.size
false
}
}
if (!tryInv(Player.this.inventory.mainInventory))
if (!tryInv(Player.this.inventory.armorInventory))
tryInv(Player.this.inventory.offHandInventory)
}
})
}
var facing, side = EnumFacing.SOUTH
@ -279,7 +256,7 @@ class Player(val agent: internal.Agent) extends FakePlayer(agent.world.asInstanc
ActivationType.BlockActivated
else if (duration <= Double.MinPositiveValue && isItemUseAllowed(stack) && tryPlaceBlockWhileHandlingFunnySpecialCases(stack, pos, side, hitX, hitY, hitZ))
ActivationType.ItemPlaced
else if (useEquippedItem(duration))
else if (useEquippedItem(duration, Option(stack)))
ActivationType.ItemUsed
else
ActivationType.None
@ -355,54 +332,59 @@ class Player(val agent: internal.Agent) extends FakePlayer(agent.world.asInstanc
}
}
def useEquippedItem(duration: Double): Boolean = {
callUsingItemInSlot(agent.equipmentInventory, 0, stack => {
if (shouldCancel(() => fireRightClickAir())) {
def useEquippedItem(duration: Double, stackOption: Option[ItemStack] = None): Boolean = {
if (stackOption.isEmpty) {
return callUsingItemInSlot(agent.equipmentInventory, 0, {
case item: ItemStack if item != null => useEquippedItem(duration, Option(item))
case _ => false
})
}
if (shouldCancel(() => fireRightClickAir())) {
return false
}
// setting the active hand will also set its initial duration
var hand: EnumHand = EnumHand.MAIN_HAND
if (!trySetActiveHand(hand, duration)) {
hand = EnumHand.OFF_HAND
if (!trySetActiveHand(hand, duration)) {
return false
}
}
// setting the active hand will also set its initial duration
var hand: EnumHand = EnumHand.MAIN_HAND
if (!trySetActiveHand(hand, duration)) {
hand = EnumHand.OFF_HAND
if (!trySetActiveHand(hand, duration)) {
return false
}
// Change the offset at which items are used, to avoid hitting
// the robot itself (e.g. with bows, potions, mining laser, ...).
posX += facing.getFrontOffsetX / 2.0
posZ += facing.getFrontOffsetZ / 2.0
try {
val stack = getActiveItemStack
val oldStack = stack.copy
var newStack = stack.copy
if (isItemUseAllowed(stack)) {
val maxDuration = stack.getMaxItemUseDuration
val heldTicks = Math.max(0, Math.min(maxDuration, (duration * 20).toInt))
agent.machine.pause(heldTicks / 20.0)
newStack = stack.useItemRightClick(world, this, hand).getResult
}
stopActiveHand()
// Change the offset at which items are used, to avoid hitting
// the robot itself (e.g. with bows, potions, mining laser, ...).
posX += facing.getFrontOffsetX / 2.0
posZ += facing.getFrontOffsetZ / 2.0
val stackChanged: Boolean =
!ItemStack.areItemStacksEqual(oldStack, newStack) ||
!ItemStack.areItemStacksEqual(oldStack, stack)
try {
val stack = getActiveItemStack
val oldStack = stack.copy
var newStack = stack.copy
if (isItemUseAllowed(stack)) {
val maxDuration = stack.getMaxItemUseDuration
val heldTicks = Math.max(0, Math.min(maxDuration, (duration * 20).toInt))
agent.machine.pause(heldTicks / 20.0)
newStack = stack.useItemRightClick(world, this, hand).getResult
}
stopActiveHand()
val stackChanged: Boolean =
!ItemStack.areItemStacksEqual(oldStack, newStack) ||
!ItemStack.areItemStacksEqual(oldStack, stack)
if (stackChanged) {
agent.equipmentInventory.setInventorySlotContents(0, newStack)
}
stackChanged
if (stackChanged) {
agent.equipmentInventory.setInventorySlotContents(0, newStack)
}
finally {
posX -= facing.getFrontOffsetX / 2.0
posZ -= facing.getFrontOffsetZ / 2.0
}
})
stackChanged
}
finally {
posX -= facing.getFrontOffsetX / 2.0
posZ -= facing.getFrontOffsetZ / 2.0
}
}
def placeBlock(slot: Int, pos: BlockPos, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float): Boolean = {