Rudimentary system for interacting with item inventories (via inv controller in robots and drones).

Very basic for now, partially because I can't come up with non-terrible names for the methods.
This commit is contained in:
Florian Nücke 2015-12-16 21:17:38 +01:00
parent 8433f0e446
commit dbb710b708
13 changed files with 113 additions and 20 deletions

View File

@ -1,5 +1,6 @@
package li.cil.oc.api.driver;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
@ -11,17 +12,31 @@ import net.minecraft.item.ItemStack;
* allow agents (robots, drones) to interact with such inventories using
* the inventory controller upgrade, for example.
* <p/>
* Implementations returned by {@link #getInventory(ItemStack)} should
* save changes back to the item stack when {@link IInventory#markDirty()}
* is called. Return <tt>null</tt> if the specified stack is not supported.
* Implementations returned by {@link #getInventory} should save changes
* back to the item stack when {@link IInventory#markDirty()} is called.
* Return <tt>null</tt> if the specified stack is not supported.
*/
public interface InventoryProvider {
/**
* Checks whether this provider works for the specified item stack.
*
* @param stack the item stack to check for.
* @param player the player holding the item, may be <tt>null</tt>.
* @return <tt>true</tt> if the stack is supported, <tt>false</tt> otherwise.
*/
boolean worksWith(ItemStack stack, EntityPlayer player);
/**
* Get an inventory implementation that allows interfacing with the
* item inventory represented by the specified item stack.
* <p/>
* Note that the specified player may be <tt>null</tt>, but will
* usually be the <em>fake player</em> of the agent using the
* inventory controller upgrade to access the item inventory.
*
* @param stack the item stack to get the inventory for.
* @param player the player holding the item, may be <tt>null</tt>.
* @return the inventory representing the contents, or <tt>null</tt>.
*/
IInventory getInventory(ItemStack stack);
IInventory getInventory(ItemStack stack, EntityPlayer player);
}

View File

@ -71,8 +71,6 @@ object GuiHandler extends CommonGuiHandler {
new gui.Drive(player.inventory, () => player.getHeldItem)
case Some(database: item.UpgradeDatabase) if id == GuiType.Database.id =>
new gui.Database(player.inventory, new DatabaseInventory {
override def tier = database.tier
override def container = player.getHeldItem
override def isUseableByPlayer(player: EntityPlayer) = player == player

View File

@ -53,8 +53,6 @@ abstract class GuiHandler extends IGuiHandler {
Delegator.subItem(player.getHeldItem) match {
case Some(database: item.UpgradeDatabase) if id == GuiType.Database.id =>
new container.Database(player.inventory, new DatabaseInventory {
override def tier = database.tier
override def container = player.getHeldItem
override def isUseableByPlayer(player: EntityPlayer) = player == player

View File

@ -1,10 +1,11 @@
package li.cil.oc.common.inventory
import li.cil.oc.Settings
import li.cil.oc.integration.opencomputers.DriverUpgradeDatabase
import net.minecraft.item.ItemStack
trait DatabaseInventory extends ItemStackInventory {
def tier: Int
def tier: Int = DriverUpgradeDatabase.tier(container)
override def getSizeInventory = Settings.get.databaseEntriesPerTier(tier)

View File

@ -21,8 +21,6 @@ object DriverUpgradeDatabase extends Item with api.driver.item.HostAware {
override def createEnvironment(stack: ItemStack, host: api.network.EnvironmentHost) =
if (host.world.isRemote) null
else new component.UpgradeDatabase(new DatabaseInventory {
override def tier = DriverUpgradeDatabase.tier(stack)
override def container = stack
override def isUseableByPlayer(player: EntityPlayer) = false

View File

@ -19,7 +19,7 @@ import net.minecraft.item.ItemStack
* all blocks are present here, because some also serve as upgrades
* and therefore have item drivers.
*/
object BlockEnvironmentProvider extends EnvironmentProvider {
object EnvironmentProviderBlocks extends EnvironmentProvider {
override def getEnvironment(stack: ItemStack): Class[_] = stack.getItem match {
case block: ItemBlock if block.field_150939_a != null =>
if (isOneOf(block.field_150939_a, Constants.BlockName.AccessPoint)) classOf[tileentity.AccessPoint]

View File

@ -0,0 +1,17 @@
package li.cil.oc.integration.opencomputers
import li.cil.oc.api.driver.InventoryProvider
import li.cil.oc.common.inventory.DatabaseInventory
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.inventory.IInventory
import net.minecraft.item.ItemStack
object InventoryProviderDatabase extends InventoryProvider {
override def worksWith(stack: ItemStack, player: EntityPlayer): Boolean = DriverUpgradeDatabase.worksWith(stack)
override def getInventory(stack: ItemStack, player: EntityPlayer): IInventory = new DatabaseInventory {
override def container: ItemStack = stack
override def isUseableByPlayer(player: EntityPlayer): Boolean = player == player
}
}

View File

@ -0,0 +1,15 @@
package li.cil.oc.integration.opencomputers
import li.cil.oc.api.driver.InventoryProvider
import li.cil.oc.common.inventory.ServerInventory
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.inventory.IInventory
import net.minecraft.item.ItemStack
object InventoryProviderServer extends InventoryProvider {
override def worksWith(stack: ItemStack, player: EntityPlayer): Boolean = DriverServer.worksWith(stack)
override def getInventory(stack: ItemStack, player: EntityPlayer): IInventory = new ServerInventory {
override def container: ItemStack = stack
}
}

View File

@ -173,7 +173,10 @@ object ModOpenComputers extends ModProxy {
api.Driver.add(DriverUpgradeTankController.Provider)
api.Driver.add(DriverUpgradeTractorBeam.Provider)
api.Driver.add(BlockEnvironmentProvider)
api.Driver.add(EnvironmentProviderBlocks)
api.Driver.add(InventoryProviderDatabase)
api.Driver.add(InventoryProviderServer)
blacklistHost(classOf[internal.Adapter],
Constants.BlockName.Geolyzer,

View File

@ -1,11 +1,11 @@
package li.cil.oc.server.component
import li.cil.oc.api.Network
import li.cil.oc.api.network.EnvironmentHost
import li.cil.oc.api.internal
import li.cil.oc.api.machine.Arguments
import li.cil.oc.api.machine.Callback
import li.cil.oc.api.machine.Context
import li.cil.oc.api.network.EnvironmentHost
import li.cil.oc.api.network._
import li.cil.oc.api.prefab
import li.cil.oc.common.tileentity
@ -26,7 +26,7 @@ object UpgradeInventoryController {
override protected def checkSideForAction(args: Arguments, n: Int) = args.checkSideAny(n)
}
class Drone(val host: EnvironmentHost with internal.Agent) extends prefab.ManagedEnvironment with traits.InventoryAnalytics with traits.InventoryWorldControlMk2 with traits.WorldInventoryAnalytics {
class Drone(val host: EnvironmentHost with internal.Agent) extends prefab.ManagedEnvironment with traits.InventoryAnalytics with traits.InventoryWorldControlMk2 with traits.WorldInventoryAnalytics with traits.ItemInventoryControl {
override val node = Network.newNode(this, Visibility.Network).
withComponent("inventory_controller", Visibility.Neighbors).
create()
@ -44,7 +44,7 @@ object UpgradeInventoryController {
override protected def checkSideForAction(args: Arguments, n: Int) = args.checkSideAny(n)
}
class Robot(val host: EnvironmentHost with tileentity.Robot) extends prefab.ManagedEnvironment with traits.InventoryAnalytics with traits.InventoryWorldControlMk2 with traits.WorldInventoryAnalytics {
class Robot(val host: EnvironmentHost with tileentity.Robot) extends prefab.ManagedEnvironment with traits.InventoryAnalytics with traits.InventoryWorldControlMk2 with traits.WorldInventoryAnalytics with traits.ItemInventoryControl {
override val node = Network.newNode(this, Visibility.Network).
withComponent("inventory_controller", Visibility.Neighbors).
create()

View File

@ -2,9 +2,12 @@ package li.cil.oc.server.component.traits
import li.cil.oc.api.machine.Arguments
import li.cil.oc.util.ExtendedArguments._
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.inventory.IInventory
trait InventoryAware {
def fakePlayer: EntityPlayer
def inventory: IInventory
def selectedSlot: Int

View File

@ -0,0 +1,45 @@
package li.cil.oc.server.component.traits
import li.cil.oc.api
import li.cil.oc.api.machine.Arguments
import li.cil.oc.api.machine.Callback
import li.cil.oc.api.machine.Context
import li.cil.oc.util.ExtendedArguments._
import li.cil.oc.util.InventoryUtils
import li.cil.oc.util.ResultWrapper.result
import net.minecraft.inventory.IInventory
import net.minecraft.item.ItemStack
import net.minecraftforge.common.util.ForgeDirection
trait ItemInventoryControl extends InventoryAware {
@Callback(doc = "function(slot:number):number -- The size of an item inventory in the specified slot.")
def getItemInventorySize(context: Context, args: Arguments): Array[AnyRef] = {
withItemInventory(args.checkSlot(inventory, 0), itemInventory => result(itemInventory.getSizeInventory))
}
@Callback(doc = "function(inventorySlot:number, slot:number[, count:number=64]):number -- The size of an item inventory in the specified slot.")
def dropIntoItemInventory(context: Context, args: Arguments): Array[AnyRef] = {
withItemInventory(args.checkSlot(inventory, 0), itemInventory => {
val count = args.optItemCount(1)
result(InventoryUtils.extractFromInventory(InventoryUtils.insertIntoInventory(_, itemInventory), inventory, ForgeDirection.UNKNOWN, count))
})
}
@Callback(doc = "function(inventorySlot:number, slot:number[, count:number=64]):number -- The size of an item inventory in the specified slot.")
def suckFromItemInventory(context: Context, args: Arguments): Array[AnyRef] = {
withItemInventory(args.checkSlot(inventory, 0), itemInventory => {
val count = args.optItemCount(1)
result(InventoryUtils.extractFromInventory(InventoryUtils.insertIntoInventory(_, inventory, slots = Option(insertionSlots)), itemInventory, ForgeDirection.UNKNOWN, count))
})
}
private def withItemInventory(slot: Int, f: IInventory => Array[AnyRef]): Array[AnyRef] = {
inventory.getStackInSlot(slot) match {
case stack: ItemStack => api.Driver.inventoryFor(stack, fakePlayer) match {
case inventory: IInventory => f(inventory)
case _ => result(0, "no item inventory")
}
case _ => result(0, "no item inventory")
}
}
}

View File

@ -119,9 +119,9 @@ private[oc] object Registry extends api.detail.DriverAPI {
}
override def inventoryFor(stack: ItemStack, player: EntityPlayer): IInventory = {
inventoryProviders.map(provider => provider.getInventory(stack)).collectFirst {
case inventory: IInventory => inventory
}.orNull
inventoryProviders.find(provider => provider.worksWith(stack, player)).
map(provider => provider.getInventory(stack, player)).
orNull
}
override def blockDrivers = blocks.toSeq