Reworked component blacklisting logic to use IMC now, allowing other mods to tell OC components not to work in their blocks (e.g. for custom assembler templates).

Only revalidating templates when a slot changed now.
Inventory upgrades properly work in drones now.
Can set status text from drone scripts now.
This commit is contained in:
Florian Nücke 2014-12-15 15:50:22 +01:00
parent 95e2feef65
commit 006935ba06
34 changed files with 198 additions and 138 deletions

View File

@ -12,14 +12,30 @@ import li.cil.oc.common.template.AssemblerTemplates
import li.cil.oc.common.tileentity
import net.minecraft.client.gui.GuiButton
import net.minecraft.entity.player.InventoryPlayer
import net.minecraft.inventory.Slot
import net.minecraft.util.IChatComponent
import org.lwjgl.opengl.GL11
import scala.collection.convert.WrapAsJava._
import scala.collection.convert.WrapAsScala._
class Assembler(playerInventory: InventoryPlayer, val assembler: tileentity.Assembler) extends DynamicGuiContainer(new container.Assembler(playerInventory, assembler)) {
xSize = 176
ySize = 192
for (slot <- inventorySlots.inventorySlots) slot match {
case component: ComponentSlot => component.changeListener = Option(onSlotChanged)
case _ =>
}
private def onSlotChanged(slot: Slot) {
runButton.enabled = canBuild
runButton.toggled = !runButton.enabled
info = validate
}
var info: Option[(Boolean, IChatComponent, Array[IChatComponent])] = None
private def assemblerContainer = inventorySlots.asInstanceOf[container.Assembler]
protected var runButton: ImageButton = _
@ -38,12 +54,6 @@ class Assembler(playerInventory: InventoryPlayer, val assembler: tileentity.Asse
}
}
override def drawScreen(mouseX: Int, mouseY: Int, dt: Float) {
runButton.enabled = canBuild
runButton.toggled = !runButton.enabled
super.drawScreen(mouseX, mouseY, dt)
}
override def initGui() {
super.initGui()
runButton = new ImageButton(0, guiLeft + 7, guiTop + 89, 18, 18, Textures.guiButtonRun, canToggle = true)
@ -53,7 +63,6 @@ class Assembler(playerInventory: InventoryPlayer, val assembler: tileentity.Asse
override def drawGuiContainerForegroundLayer(mouseX: Int, mouseY: Int) = {
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS) // Me lazy... prevents NEI render glitch.
if (!assemblerContainer.isAssembling) {
val info = validate
val message =
if (!assemblerContainer.getSlot(0).getHasStack) {
Localization.Assembler.InsertTemplate

View File

@ -26,7 +26,7 @@ class Drone(playerInventory: InventoryPlayer, val drone: entity.Drone) extends D
protected var powerButton: ImageButton = _
private val buffer = new TextBuffer(20, 2, PackedColor.SingleBitFormat)
private val buffer = new TextBuffer(20, 2, new PackedColor.SingleBitFormat(0x33FF33))
private val bufferRenderer = new TextBufferRenderData {
private var _dirty = true

View File

@ -9,6 +9,7 @@ import li.cil.oc.OpenComputers
import li.cil.oc.Settings
import li.cil.oc.common.template.AssemblerTemplates
import li.cil.oc.integration.util.Wrench
import li.cil.oc.server.driver.Registry
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.item.ItemStack
import net.minecraftforge.common.util.Constants.NBT
@ -51,6 +52,12 @@ object IMC {
Settings.get.peripheralBlacklist.add(message.getStringValue)
}
}
else if (message.key == "blacklistHost" && message.isNBTMessage) {
OpenComputers.log.info(s"Blacklisting component '${message.getNBTValue.getString("name")}' for host '${message.getNBTValue.getString("host")}' as requested by mod ${message.getSender}.")
try Registry.blacklistHost(message.getNBTValue.getCompoundTag("item"), Class.forName(message.getNBTValue.getString("host"))) catch {
case t: Throwable => OpenComputers.log.warn("Failed blacklisting component.", t)
}
}
}
}

View File

@ -19,6 +19,8 @@ trait ComponentSlot extends Slot {
def tierIcon: IIcon
var changeListener: Option[Slot => Unit] = None
// ----------------------------------------------------------------------- //
@SideOnly(Side.CLIENT)
@ -40,6 +42,7 @@ trait ComponentSlot extends Slot {
case dynamic: ComponentSlot => dynamic.clearIfInvalid(container.playerInventory.player)
case _ =>
}
changeListener.foreach(_(this))
}
protected def clearIfInvalid(player: EntityPlayer) {}

View File

@ -7,6 +7,7 @@ import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.api.Driver
import li.cil.oc.api.Machine
import li.cil.oc.api.driver.item
import li.cil.oc.api.driver.item.Memory
import li.cil.oc.api.driver.item.Processor
import li.cil.oc.api.internal
@ -32,11 +33,13 @@ import net.minecraft.world.World
class Drone(val world: World) extends Entity(world) with MachineHost with internal.Drone {
// Some basic constants.
val gravity = 0.05f // low for slow fall (float down)
val gravity = 0.05f
// low for slow fall (float down)
val drag = 0.8f
val maxAcceleration = 0.1f
val maxVelocity = 0.4f
setSize(1, 6/16f)
val maxInventorySize = 8
setSize(1, 6 / 16f)
// Rendering stuff, purely eyecandy.
val targetFlapAngles = Array.fill(4, 2)(0f)
@ -73,9 +76,9 @@ class Drone(val world: World) extends Entity(world) with MachineHost with intern
override def onMessage(message: Message) {}
}
val inventory = new Inventory {
var items = Array.fill[Option[ItemStack]](8)(None)
val items = Array.fill[Option[ItemStack]](8)(None)
override def getSizeInventory = items.length
override def getSizeInventory = inventorySize
override def getInventoryStackLimit = 64
@ -136,6 +139,14 @@ class Drone(val world: World) extends Entity(world) with MachineHost with intern
override def onMachineDisconnect(node: Node) {}
def computeInventorySize() = math.min(maxInventorySize, info.components.foldLeft(0)((acc, component) => acc + (Option(component) match {
case Some(stack) => Option(Driver.driverFor(stack, getClass)) match {
case Some(driver: item.Inventory) => math.max(1, driver.inventoryCapacity(stack) / 4)
case _ => 0
}
case _ => 0
})))
// ----------------------------------------------------------------------- //
override def entityInit() {
@ -154,29 +165,68 @@ class Drone(val world: World) extends Entity(world) with MachineHost with intern
dataWatcher.addObject(9, int2Integer(100))
// Status text.
dataWatcher.addObject(10, "")
// Inventory size for client.
dataWatcher.addObject(11, byte2Byte(0: Byte))
}
def initializeAfterPlacement(stack: ItemStack, player: EntityPlayer, x: Int, y: Int, z: Int, hitX: Float, hitY: Float, hitZ: Float) {
info.load(stack)
inventorySize = computeInventorySize()
setPosition(x + hitX * 1.1f, y + hitY * 1.1f, z + hitZ * 1.1f)
}
def preparePowerUp() {
targetX = math.floor(posX).toFloat + 0.5f
targetY = math.floor(posY).toFloat + 0.5f
targetZ = math.floor(posZ).toFloat + 0.5f
targetAcceleration = maxAcceleration
api.Network.joinNewNetwork(machine.node)
components.connectComponents()
machine.node.connect(control.node)
}
def isRunning = dataWatcher.getWatchableObjectByte(2) != 0
def targetX = dataWatcher.getWatchableObjectFloat(3)
def targetY = dataWatcher.getWatchableObjectFloat(4)
def targetZ = dataWatcher.getWatchableObjectFloat(5)
def targetAcceleration = dataWatcher.getWatchableObjectFloat(6)
def selectedSlot = dataWatcher.getWatchableObjectByte(7) & 0xFF
def globalBuffer = dataWatcher.getWatchableObjectInt(8)
def globalBufferSize = dataWatcher.getWatchableObjectInt(9)
def statusText = dataWatcher.getWatchableObjectString(10)
private def setRunning(value: Boolean) = dataWatcher.updateObject(2, byte2Byte(if (value) 1: Byte else 0: Byte))
def inventorySize = dataWatcher.getWatchableObjectByte(11) & 0xFF
def setRunning(value: Boolean) = dataWatcher.updateObject(2, byte2Byte(if (value) 1: Byte else 0: Byte))
// Round target values to low accuracy to avoid floating point errors accumulating.
def targetX_=(value: Float): Unit = dataWatcher.updateObject(3, float2Float(math.round(value * 5) / 5f))
def targetY_=(value: Float): Unit = dataWatcher.updateObject(4, float2Float(math.round(value * 5) / 5f))
def targetZ_=(value: Float): Unit = dataWatcher.updateObject(5, float2Float(math.round(value * 5) / 5f))
def targetAcceleration_=(value: Float): Unit = dataWatcher.updateObject(6, float2Float(math.max(0, math.min(maxAcceleration, value))))
def selectedSlot_=(value: Int) = dataWatcher.updateObject(7, byte2Byte(value.toByte))
private def globalBuffer_=(value: Int) = dataWatcher.updateObject(8, int2Integer(value))
private def globalBufferSize_=(value: Int) = dataWatcher.updateObject(9, int2Integer(value))
def globalBuffer_=(value: Int) = dataWatcher.updateObject(8, int2Integer(value))
def globalBufferSize_=(value: Int) = dataWatcher.updateObject(9, int2Integer(value))
def statusText_=(value: String) = dataWatcher.updateObject(10, Option(value).map(_.lines.map(_.take(10)).take(2).mkString("\n")).getOrElse(""))
def inventorySize_=(value: Int) = dataWatcher.updateObject(11, byte2Byte(value.toByte))
@SideOnly(Side.CLIENT)
override def setPositionAndRotation2(x: Double, y: Double, z: Double, yaw: Float, pitch: Float, data: Int) {
// Only set exact position if we're too far away from the server's
@ -211,7 +261,8 @@ class Drone(val world: World) extends Entity(world) with MachineHost with intern
super.onEntityUpdate()
if (!world.isRemote) {
if (isInWater) { // We're not water-proof!
if (isInWater) {
// We're not water-proof!
machine.stop()
}
machine.node.asInstanceOf[Connector].changeBuffer(100)
@ -219,12 +270,14 @@ class Drone(val world: World) extends Entity(world) with MachineHost with intern
components.updateComponents()
setRunning(machine.isRunning)
if (math.abs(lastEnergyUpdate - globalBuffer) > 100 || world.getTotalWorldTime % 200 == 0) {
globalBuffer = machine.node.asInstanceOf[Connector].globalBuffer.toInt
if (math.abs(lastEnergyUpdate - globalBuffer) > 50 || world.getTotalWorldTime % 200 == 0) {
globalBuffer = math.round(machine.node.asInstanceOf[Connector].globalBuffer / 50f).toInt * 50
globalBufferSize = machine.node.asInstanceOf[Connector].globalBufferSize.toInt
lastEnergyUpdate = globalBuffer
}
}
else if (isRunning) {
else {
if (isRunning) {
// Client side update; occasionally update wing pitch and rotation to
// make the drones look a bit more dynamic.
val rng = world.rand
@ -260,6 +313,7 @@ class Drone(val world: World) extends Entity(world) with MachineHost with intern
// Update body rotation.
bodyAngle += angularVelocity
}
}
if (isRunning) {
val delta = Vec3.createVectorHelper(targetX - posX, targetY - posY, targetZ - posZ)
@ -306,17 +360,6 @@ class Drone(val world: World) extends Entity(world) with MachineHost with intern
stack
}
def preparePowerUp() {
targetX = math.floor(posX).toFloat + 0.5f
targetY = math.floor(posY).toFloat + 0.5f
targetZ = math.floor(posZ).toFloat + 0.5f
targetAcceleration = maxAcceleration
api.Network.joinNewNetwork(machine.node)
components.connectComponents()
machine.node.connect(control.node)
}
override def interactFirst(player: EntityPlayer) = {
if (player.isSneaking) {
kill()
@ -329,8 +372,9 @@ class Drone(val world: World) extends Entity(world) with MachineHost with intern
// ----------------------------------------------------------------------- //
override def readEntityFromNBT(nbt: NBTTagCompound): Unit = {
override def readEntityFromNBT(nbt: NBTTagCompound) {
info.load(nbt.getCompoundTag("info"))
inventorySize = computeInventorySize()
if (!world.isRemote) {
machine.load(nbt.getCompoundTag("machine"))
control.load(nbt.getCompoundTag("control"))
@ -349,7 +393,7 @@ class Drone(val world: World) extends Entity(world) with MachineHost with intern
statusText = nbt.getString("statusText")
}
override def writeEntityToNBT(nbt: NBTTagCompound): Unit = {
override def writeEntityToNBT(nbt: NBTTagCompound) {
components.saveComponents()
nbt.setNewCompoundTag("info", info.save)
if (!world.isRemote) {

View File

@ -9,8 +9,7 @@ class Drone(val parent: Delegator) extends Delegate {
override def onItemUse(stack: ItemStack, player: EntityPlayer, world: World, x: Int, y: Int, z: Int, side: Int, hitX: Float, hitY: Float, hitZ: Float) = {
if (!world.isRemote) {
val drone = new entity.Drone(world)
drone.info.load(stack)
drone.setPosition(x + hitX, y + hitY, z + hitZ)
drone.initializeAfterPlacement(stack, player, x, y, z, hitX, hitY, hitZ)
world.spawnEntityInWorld(drone)
}
stack.stackSize -= 1

View File

@ -35,7 +35,7 @@ trait Environment extends TileEntity with network.Environment with driver.Enviro
override def updateEntity() {
super.updateEntity()
if (isChangeScheduled) {
markDirty()
world.markTileEntityChunkModified(x, y, z, this)
isChangeScheduled = false
}
}

View File

@ -3,11 +3,12 @@ package li.cil.oc.integration.opencomputers
import li.cil.oc.api
import li.cil.oc.api.driver.EnvironmentAware
import li.cil.oc.api.driver.EnvironmentHost
import li.cil.oc.api.driver.item.HostAware
import li.cil.oc.common.Slot
import li.cil.oc.server.component
import net.minecraft.item.ItemStack
object DriverGeolyzer extends Item with EnvironmentAware {
object DriverGeolyzer extends Item with HostAware with EnvironmentAware {
override def worksWith(stack: ItemStack) =
isOneOf(stack, api.Items.get("geolyzer"))

View File

@ -15,9 +15,6 @@ object DriverGraphicsCard extends Item with HostAware with EnvironmentAware {
override def worksWith(stack: ItemStack) =
isOneOf(stack, api.Items.get("graphicsCard1"), api.Items.get("graphicsCard2"), api.Items.get("graphicsCard3"))
override def worksWith(stack: ItemStack, host: Class[_ <: EnvironmentHost]) =
worksWith(stack) && !isMicrocontroller(host)
override def createEnvironment(stack: ItemStack, host: EnvironmentHost) =
tier(stack) match {
case Tier.One => new component.GraphicsCard.Tier1()

View File

@ -11,9 +11,6 @@ object DriverKeyboard extends Item with HostAware {
override def worksWith(stack: ItemStack) =
isOneOf(stack, api.Items.get("keyboard"))
override def worksWith(stack: ItemStack, host: Class[_ <: EnvironmentHost]) =
worksWith(stack) && !isAdapter(host) && !isMicrocontroller(host)
override def createEnvironment(stack: ItemStack, host: EnvironmentHost) = new component.Keyboard(host)
override def slot(stack: ItemStack) = Slot.Upgrade

View File

@ -12,9 +12,6 @@ object DriverNetworkCard extends Item with HostAware with EnvironmentAware {
override def worksWith(stack: ItemStack) =
isOneOf(stack, api.Items.get("lanCard"))
override def worksWith(stack: ItemStack, host: Class[_ <: EnvironmentHost]) =
worksWith(stack) && !isTablet(host)
override def createEnvironment(stack: ItemStack, host: EnvironmentHost) = new component.NetworkCard(host)
override def slot(stack: ItemStack) = Slot.Card

View File

@ -19,9 +19,6 @@ import net.minecraft.item.ItemStack
object DriverRedstoneCard extends Item with HostAware with EnvironmentAware {
override def worksWith(stack: ItemStack) = isOneOf(stack, api.Items.get("redstoneCard1"), api.Items.get("redstoneCard2"))
override def worksWith(stack: ItemStack, host: Class[_ <: EnvironmentHost]) =
worksWith(stack) && (isComputer(host) || isRobot(host) || isServer(host) || isMicrocontroller(host))
override def createEnvironment(stack: ItemStack, host: EnvironmentHost) =
host match {
case redstone: BundledRedstoneAware if BundledRedstone.isAvailable && tier(stack) == Tier.Two =>

View File

@ -13,9 +13,6 @@ object DriverScreen extends Item with HostAware with EnvironmentAware {
override def worksWith(stack: ItemStack) =
isOneOf(stack, api.Items.get("screen1"))
override def worksWith(stack: ItemStack, host: Class[_ <: EnvironmentHost]) =
worksWith(stack) && !isTablet(host) && !isAdapter(host) && !isMicrocontroller(host)
override def createEnvironment(stack: ItemStack, host: EnvironmentHost) = host match {
case screen: tileentity.Screen if screen.tier > 0 => new component.Screen(screen)
case _ => new component.TextBuffer(host)

View File

@ -12,9 +12,6 @@ object DriverUpgradeAngel extends Item with HostAware {
override def worksWith(stack: ItemStack) =
isOneOf(stack, api.Items.get("angelUpgrade"))
override def worksWith(stack: ItemStack, host: Class[_ <: EnvironmentHost]) =
worksWith(stack) && isRobot(host)
override def createEnvironment(stack: ItemStack, host: EnvironmentHost) = new component.UpgradeAngel()
override def slot(stack: ItemStack) = Slot.Upgrade

View File

@ -14,9 +14,6 @@ object DriverUpgradeBattery extends Item with HostAware {
override def worksWith(stack: ItemStack) =
isOneOf(stack, api.Items.get("batteryUpgrade1"), api.Items.get("batteryUpgrade2"), api.Items.get("batteryUpgrade3"))
override def worksWith(stack: ItemStack, host: Class[_ <: EnvironmentHost]) =
worksWith(stack) && !isAdapter(host)
override def createEnvironment(stack: ItemStack, host: EnvironmentHost) = new component.UpgradeBattery(tier(stack))
override def slot(stack: ItemStack) = Slot.Upgrade

View File

@ -13,9 +13,6 @@ object DriverUpgradeChunkloader extends Item with HostAware with EnvironmentAwar
override def worksWith(stack: ItemStack) =
isOneOf(stack, api.Items.get("chunkloaderUpgrade"))
override def worksWith(stack: ItemStack, host: Class[_ <: EnvironmentHost]) =
worksWith(stack) && isRobot(host)
override def createEnvironment(stack: ItemStack, host: EnvironmentHost) = new component.UpgradeChunkloader(host)
override def slot(stack: ItemStack) = Slot.Upgrade

View File

@ -14,9 +14,6 @@ object DriverUpgradeCrafting extends Item with HostAware with EnvironmentAware {
override def worksWith(stack: ItemStack) =
isOneOf(stack, api.Items.get("craftingUpgrade"))
override def worksWith(stack: ItemStack, host: Class[_ <: EnvironmentHost]) =
worksWith(stack) && isRobot(host)
override def createEnvironment(stack: ItemStack, host: EnvironmentHost) =
host match {
case robot: EnvironmentHost with Robot => new component.UpgradeCrafting(robot)

View File

@ -3,7 +3,6 @@ package li.cil.oc.integration.opencomputers
import li.cil.oc.api
import li.cil.oc.api.driver
import li.cil.oc.api.driver.EnvironmentAware
import li.cil.oc.api.driver.EnvironmentHost
import li.cil.oc.api.driver.item.HostAware
import li.cil.oc.common.Slot
import li.cil.oc.common.Tier
@ -18,9 +17,6 @@ object DriverUpgradeDatabase extends Item with HostAware with EnvironmentAware {
override def worksWith(stack: ItemStack) =
isOneOf(stack, api.Items.get("databaseUpgrade1"), api.Items.get("databaseUpgrade2"), api.Items.get("databaseUpgrade3"))
override def worksWith(stack: ItemStack, host: Class[_ <: EnvironmentHost]) =
worksWith(stack) && !isMicrocontroller(host)
override def createEnvironment(stack: ItemStack, host: driver.EnvironmentHost) =
new component.UpgradeDatabase(new DatabaseInventory {
override def tier = DriverUpgradeDatabase.tier(stack)

View File

@ -13,9 +13,6 @@ object DriverUpgradeExperience extends Item with HostAware with EnvironmentAware
override def worksWith(stack: ItemStack) =
isOneOf(stack, api.Items.get("experienceUpgrade"))
override def worksWith(stack: ItemStack, host: Class[_ <: EnvironmentHost]) =
worksWith(stack) && isRobot(host)
override def createEnvironment(stack: ItemStack, host: EnvironmentHost) = new component.UpgradeExperience()
override def slot(stack: ItemStack) = Slot.Upgrade

View File

@ -14,9 +14,6 @@ object DriverUpgradeGenerator extends Item with HostAware with EnvironmentAware
override def worksWith(stack: ItemStack) =
isOneOf(stack, api.Items.get("generatorUpgrade"))
override def worksWith(stack: ItemStack, host: Class[_ <: EnvironmentHost]) =
worksWith(stack) && isRobot(host)
override def createEnvironment(stack: ItemStack, host: EnvironmentHost) =
host match {
case robot: Robot => new component.UpgradeGenerator(robot)

View File

@ -11,9 +11,6 @@ object DriverUpgradeInventory extends Item with Inventory with HostAware {
override def worksWith(stack: ItemStack) =
isOneOf(stack, api.Items.get("inventoryUpgrade"))
override def worksWith(stack: ItemStack, host: Class[_ <: EnvironmentHost]) =
worksWith(stack) && isRobot(host)
override def createEnvironment(stack: ItemStack, host: EnvironmentHost) = null
override def slot(stack: ItemStack) = Slot.Upgrade

View File

@ -15,9 +15,6 @@ object DriverUpgradeInventoryController extends Item with HostAware with Environ
override def worksWith(stack: ItemStack) =
isOneOf(stack, api.Items.get("inventoryControllerUpgrade"))
override def worksWith(stack: ItemStack, host: Class[_ <: EnvironmentHost]) =
worksWith(stack) && (isRobot(host) || isAdapter(host))
override def createEnvironment(stack: ItemStack, host: EnvironmentHost) = host match {
case robot: EnvironmentHost with Robot => new component.UpgradeInventoryControllerInRobot(robot)
case adapter: EnvironmentHost with Adapter => new component.UpgradeInventoryControllerInAdapter(adapter)

View File

@ -14,9 +14,6 @@ object DriverUpgradeNavigation extends Item with HostAware with EnvironmentAware
override def worksWith(stack: ItemStack) =
isOneOf(stack, api.Items.get("navigationUpgrade"))
override def worksWith(stack: ItemStack, host: Class[_ <: EnvironmentHost]) =
worksWith(stack) && (isRotatable(host) && !isMicrocontroller(host))
override def createEnvironment(stack: ItemStack, host: EnvironmentHost) =
host match {
case rotatable: EnvironmentHost with Rotatable => new component.UpgradeNavigation(rotatable)

View File

@ -13,9 +13,6 @@ object DriverUpgradePiston extends Item with HostAware with EnvironmentAware {
override def worksWith(stack: ItemStack) =
isOneOf(stack, api.Items.get("pistonUpgrade"))
override def worksWith(stack: ItemStack, host: Class[_ <: EnvironmentHost]) =
worksWith(stack) && isRotatable(host)
override def createEnvironment(stack: ItemStack, host: EnvironmentHost) = host match {
case rotatable: Rotatable with EnvironmentHost => new component.UpgradePiston(rotatable)
case _ => null

View File

@ -16,9 +16,6 @@ object DriverUpgradeSign extends Item with HostAware with EnvironmentAware {
override def worksWith(stack: ItemStack) =
isOneOf(stack, api.Items.get("signUpgrade"))
override def worksWith(stack: ItemStack, host: Class[_ <: EnvironmentHost]) =
worksWith(stack) && (isAdapter(host) || isRotatable(host))
override def createEnvironment(stack: ItemStack, host: EnvironmentHost) =
host match {
case rotatable: EnvironmentHost with Rotatable => new UpgradeSignInRotatable(rotatable)

View File

@ -12,9 +12,6 @@ object DriverUpgradeSolarGenerator extends Item with HostAware {
override def worksWith(stack: ItemStack) =
isOneOf(stack, api.Items.get("solarGeneratorUpgrade"))
override def worksWith(stack: ItemStack, host: Class[_ <: EnvironmentHost]) =
worksWith(stack) && !isAdapter(host)
override def createEnvironment(stack: ItemStack, host: EnvironmentHost) = new component.UpgradeSolarGenerator(host)
override def slot(stack: ItemStack) = Slot.Upgrade

View File

@ -11,9 +11,6 @@ object DriverUpgradeTank extends Item with HostAware {
override def worksWith(stack: ItemStack) =
isOneOf(stack, api.Items.get("tankUpgrade"))
override def worksWith(stack: ItemStack, host: Class[_ <: EnvironmentHost]) =
worksWith(stack) && isRobot(host)
override def createEnvironment(stack: ItemStack, host: EnvironmentHost) = new component.UpgradeTank(host, 16000)
override def slot(stack: ItemStack) = Slot.Upgrade

View File

@ -15,9 +15,6 @@ object DriverUpgradeTankController extends Item with HostAware with EnvironmentA
override def worksWith(stack: ItemStack) =
isOneOf(stack, api.Items.get("tankControllerUpgrade"))
override def worksWith(stack: ItemStack, host: Class[_ <: EnvironmentHost]) =
worksWith(stack) && (isRobot(host) || isAdapter(host))
override def createEnvironment(stack: ItemStack, host: EnvironmentHost) = host match {
case robot: EnvironmentHost with Robot => new component.UpgradeTankControllerInRobot(robot)
case adapter: EnvironmentHost with Adapter => new component.UpgradeTankControllerInAdapter(adapter)

View File

@ -15,9 +15,6 @@ object DriverUpgradeTractorBeam extends Item with HostAware with EnvironmentAwar
override def worksWith(stack: ItemStack) =
isOneOf(stack, api.Items.get("tractorBeamUpgrade"))
override def worksWith(stack: ItemStack, host: Class[_ <: EnvironmentHost]) =
worksWith(stack) && (isRobot(host) || isTablet(host))
override def createEnvironment(stack: ItemStack, host: EnvironmentHost) = host match {
case robot: Robot => new component.UpgradeTractorBeam(host, robot.player)
case tablet: TabletWrapper => new component.UpgradeTractorBeam(host, () => tablet.player)

View File

@ -6,10 +6,23 @@ import li.cil.oc.api.driver
import li.cil.oc.api.driver.EnvironmentHost
import li.cil.oc.api.internal
import li.cil.oc.common.Tier
import li.cil.oc.server.driver.Registry
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
trait Item extends driver.Item {
def worksWith(stack: ItemStack, host: Class[_ <: EnvironmentHost]): Boolean =
worksWith(stack) && {
val nbt = new NBTTagCompound()
val copy = stack.copy()
copy.stackSize = 1
copy.writeToNBT(nbt)
Registry.blacklist.get(nbt) match {
case Some(hosts) => !hosts.exists(_.isAssignableFrom(host))
case _ => true
}
}
override def tier(stack: ItemStack) = Tier.One
override def dataTag(stack: ItemStack) = Item.dataTag(stack)
@ -29,6 +42,8 @@ trait Item extends driver.Item {
protected def isTablet(host: Class[_ <: EnvironmentHost]) = classOf[internal.Tablet].isAssignableFrom(host)
protected def isMicrocontroller(host: Class[_ <: EnvironmentHost]) = classOf[internal.Microcontroller].isAssignableFrom(host)
protected def isDrone(host: Class[_ <: EnvironmentHost]) = classOf[internal.Drone].isAssignableFrom(host)
}
object Item {

View File

@ -1,9 +1,11 @@
package li.cil.oc.integration.opencomputers
import cpw.mods.fml.common.FMLCommonHandler
import cpw.mods.fml.common.event.FMLInterModComms
import cpw.mods.fml.common.registry.EntityRegistry
import li.cil.oc.OpenComputers
import li.cil.oc.api
import li.cil.oc.api.internal
import li.cil.oc.common.EventHandler
import li.cil.oc.common.Loot
import li.cil.oc.common.SaveHandler
@ -18,7 +20,10 @@ import li.cil.oc.common.template.RobotTemplate
import li.cil.oc.common.template.TabletTemplate
import li.cil.oc.integration.ModProxy
import li.cil.oc.integration.Mods
import li.cil.oc.integration.util.WirelessRedstone
import li.cil.oc.server.network.WirelessNetwork
import li.cil.oc.util.ExtendedNBT._
import net.minecraft.nbt.NBTTagCompound
import net.minecraftforge.common.ForgeChunkManager
import net.minecraftforge.common.MinecraftForge
@ -97,5 +102,25 @@ object ModOpenComputers extends ModProxy {
api.Driver.add(DriverUpgradeTank)
api.Driver.add(DriverUpgradeTankController)
api.Driver.add(DriverUpgradeTractorBeam)
blacklistHost(classOf[internal.Adapter], "geolyzer", "keyboard", "screen1", "angelUpgrade", "batteryUpgrade1", "batteryUpgrade2", "batteryUpgrade3", "chunkloaderUpgrade", "craftingUpgrade", "experienceUpgrade", "generatorUpgrade", "inventoryUpgrade", "navigationUpgrade", "pistonUpgrade", "solarGeneratorUpgrade", "tankUpgrade", "tractorBeamUpgrade")
blacklistHost(classOf[internal.Microcontroller], "graphicsCard1", "graphicsCard2", "graphicsCard3", "keyboard", "screen1", "angelUpgrade", "chunkloaderUpgrade", "craftingUpgrade", "databaseUpgrade1", "databaseUpgrade2", "databaseUpgrade3", "experienceUpgrade", "generatorUpgrade", "inventoryUpgrade", "inventoryControllerUpgrade", "navigationUpgrade", "tankUpgrade", "tankControllerUpgrade", "tractorBeamUpgrade")
blacklistHost(classOf[internal.Drone], "graphicsCard1", "graphicsCard2", "graphicsCard3", "keyboard", "lanCard", "redstoneCard1", "screen1", "angelUpgrade", "craftingUpgrade", "experienceUpgrade", "generatorUpgrade", "tankUpgrade", "tankControllerUpgrade")
blacklistHost(classOf[internal.Tablet], "lanCard", "redstoneCard1", "screen1", "angelUpgrade", "chunkloaderUpgrade", "craftingUpgrade", "databaseUpgrade1", "databaseUpgrade2", "databaseUpgrade3", "experienceUpgrade", "generatorUpgrade", "inventoryUpgrade", "inventoryControllerUpgrade", "tankUpgrade", "tankControllerUpgrade")
if (!WirelessRedstone.isAvailable) {
blacklistHost(classOf[internal.Drone], "redstoneCard2")
blacklistHost(classOf[internal.Tablet], "redstoneCard2")
}
}
private def blacklistHost(host: Class[_], itemNames: String*) {
for (itemName <- itemNames) {
val nbt = new NBTTagCompound()
nbt.setString("name", itemName)
nbt.setString("host", host.getName)
nbt.setNewCompoundTag("item", api.Items.get(itemName).createItemStack(1).writeToNBT)
FMLInterModComms.sendMessage("OpenComputers", "blacklistHost", nbt)
}
}
}

View File

@ -49,12 +49,23 @@ class Drone(val host: entity.Drone) extends prefab.ManagedEnvironment with trait
override protected def suckableItems(side: ForgeDirection) = entitiesInBlock(BlockPosition(host)) ++ super.suckableItems(side)
override protected def onSuckCollect(entity: EntityItem) = {
if (InventoryUtils.insertIntoInventory(entity.getEntityItem, inventory, slots = Option(insertionSlots))) {
world.playSoundAtEntity(host, "random.pop", 0.2f, ((world.rand.nextFloat - world.rand.nextFloat) * 0.7f + 1) * 2)
InventoryUtils.insertIntoInventory(entity.getEntityItem, inventory, slots = Option(insertionSlots))
}
}
// ----------------------------------------------------------------------- //
@Callback(doc = "function():string -- Get the status text currently being displayed in the GUI.")
def getStatusText(context: Context, args: Arguments): Array[AnyRef] = result(host.statusText)
@Callback(doc = "function(value:string):string -- Set the status text to display in the GUI, returns new value.")
def setStatusText(context: Context, args: Arguments): Array[AnyRef] = {
host.statusText = args.checkString(0)
context.pause(0.1)
result(host.statusText)
}
// ----------------------------------------------------------------------- //
@Callback(doc = "function(dx:number, dy:number, dz:number) -- Change the target position by the specified offset.")

View File

@ -9,6 +9,7 @@ import li.cil.oc.api.driver.EnvironmentHost
import li.cil.oc.api.driver.item.HostAware
import li.cil.oc.api.machine.Value
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
import net.minecraft.world.World
import scala.collection.convert.WrapAsJava._
@ -37,6 +38,9 @@ private[oc] object Registry extends api.detail.DriverAPI {
val converters = mutable.ArrayBuffer.empty[api.driver.Converter]
// Index using NBT representation of stacks because they can be hashed properly.
val blacklist = mutable.Map.empty[NBTTagCompound, mutable.Set[Class[_]]]
/** Used to keep track of whether we're past the init phase. */
var locked = false
@ -55,13 +59,13 @@ private[oc] object Registry extends api.detail.DriverAPI {
if (!converters.contains(converter)) converters += converter
}
def driverFor(world: World, x: Int, y: Int, z: Int) =
override def driverFor(world: World, x: Int, y: Int, z: Int) =
blocks.filter(_.worksWith(world, x, y, z)) match {
case drivers if drivers.nonEmpty => new CompoundBlockDriver(drivers: _*)
case _ => null
}
def driverFor(stack: ItemStack, host: Class[_ <: EnvironmentHost]) =
override def driverFor(stack: ItemStack, host: Class[_ <: EnvironmentHost]) =
if (stack != null) {
val hostAware = items.collect {
case driver: HostAware if driver.worksWith(stack) => driver
@ -73,7 +77,7 @@ private[oc] object Registry extends api.detail.DriverAPI {
}
else null
def driverFor(stack: ItemStack) =
override def driverFor(stack: ItemStack) =
if (stack != null) items.find(_.worksWith(stack)).orNull
else null
@ -81,6 +85,10 @@ private[oc] object Registry extends api.detail.DriverAPI {
override def itemDrivers = items.toSeq
def blacklistHost(item: NBTTagCompound, host: Class[_]) {
blacklist.getOrElseUpdate(item, mutable.Set.empty) += host
}
def convert(value: Array[AnyRef]) = if (value != null) value.map(arg => convertRecursively(arg, new util.IdentityHashMap())) else null
def convertRecursively(value: Any, memo: util.IdentityHashMap[AnyRef, AnyRef], force: Boolean = false): AnyRef = {

View File

@ -52,16 +52,18 @@ object PackedColor {
override def save(nbt: NBTTagCompound) {}
}
object SingleBitFormat extends ColorFormat {
class SingleBitFormat(val color: Int) extends ColorFormat {
override def depth = ColorDepth.OneBit
override def inflate(value: Int) = if (value == 0) 0x000000 else Settings.get.monochromeColor
override def inflate(value: Int) = if (value == 0) 0x000000 else color
override def deflate(value: Color) = {
(if (value.value == 0) 0 else 1).toByte
}
}
object SingleBitFormat extends SingleBitFormat(Settings.get.monochromeColor)
abstract class PaletteFormat extends ColorFormat {
override def inflate(value: Int) = palette(math.max(0, math.min(palette.length - 1, value)))