From 006935ba06a60f782c082b429f65407cefc532ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Mon, 15 Dec 2014 15:50:22 +0100 Subject: [PATCH] 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. --- .../li/cil/oc/client/gui/Assembler.scala | 23 ++- .../scala/li/cil/oc/client/gui/Drone.scala | 2 +- src/main/scala/li/cil/oc/common/IMC.scala | 7 + .../oc/common/container/ComponentSlot.scala | 3 + .../scala/li/cil/oc/common/entity/Drone.scala | 154 +++++++++++------- .../scala/li/cil/oc/common/item/Drone.scala | 3 +- .../tileentity/traits/Environment.scala | 2 +- .../opencomputers/DriverGeolyzer.scala | 3 +- .../opencomputers/DriverGraphicsCard.scala | 3 - .../opencomputers/DriverKeyboard.scala | 3 - .../opencomputers/DriverNetworkCard.scala | 3 - .../opencomputers/DriverRedstoneCard.scala | 3 - .../opencomputers/DriverScreen.scala | 3 - .../opencomputers/DriverUpgradeAngel.scala | 3 - .../opencomputers/DriverUpgradeBattery.scala | 3 - .../DriverUpgradeChunkloader.scala | 3 - .../opencomputers/DriverUpgradeCrafting.scala | 3 - .../opencomputers/DriverUpgradeDatabase.scala | 4 - .../DriverUpgradeExperience.scala | 3 - .../DriverUpgradeGenerator.scala | 3 - .../DriverUpgradeInventory.scala | 3 - .../DriverUpgradeInventoryController.scala | 3 - .../DriverUpgradeNavigation.scala | 3 - .../opencomputers/DriverUpgradePiston.scala | 3 - .../opencomputers/DriverUpgradeSign.scala | 3 - .../DriverUpgradeSolarGenerator.scala | 3 - .../opencomputers/DriverUpgradeTank.scala | 3 - .../DriverUpgradeTankController.scala | 3 - .../DriverUpgradeTractorBeam.scala | 3 - .../oc/integration/opencomputers/Item.scala | 15 ++ .../opencomputers/ModOpenComputers.scala | 25 +++ .../li/cil/oc/server/component/Drone.scala | 15 +- .../li/cil/oc/server/driver/Registry.scala | 14 +- .../scala/li/cil/oc/util/PackedColor.scala | 6 +- 34 files changed, 198 insertions(+), 138 deletions(-) diff --git a/src/main/scala/li/cil/oc/client/gui/Assembler.scala b/src/main/scala/li/cil/oc/client/gui/Assembler.scala index 916a49f94..0c563fd87 100644 --- a/src/main/scala/li/cil/oc/client/gui/Assembler.scala +++ b/src/main/scala/li/cil/oc/client/gui/Assembler.scala @@ -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 diff --git a/src/main/scala/li/cil/oc/client/gui/Drone.scala b/src/main/scala/li/cil/oc/client/gui/Drone.scala index 183d181fb..63967af22 100644 --- a/src/main/scala/li/cil/oc/client/gui/Drone.scala +++ b/src/main/scala/li/cil/oc/client/gui/Drone.scala @@ -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 diff --git a/src/main/scala/li/cil/oc/common/IMC.scala b/src/main/scala/li/cil/oc/common/IMC.scala index 9e22d826c..39a4a05cb 100644 --- a/src/main/scala/li/cil/oc/common/IMC.scala +++ b/src/main/scala/li/cil/oc/common/IMC.scala @@ -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) + } + } } } diff --git a/src/main/scala/li/cil/oc/common/container/ComponentSlot.scala b/src/main/scala/li/cil/oc/common/container/ComponentSlot.scala index 4881be624..b7cde9ff1 100644 --- a/src/main/scala/li/cil/oc/common/container/ComponentSlot.scala +++ b/src/main/scala/li/cil/oc/common/container/ComponentSlot.scala @@ -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) {} diff --git a/src/main/scala/li/cil/oc/common/entity/Drone.scala b/src/main/scala/li/cil/oc/common/entity/Drone.scala index 6adbfd408..5a058be2a 100644 --- a/src/main/scala/li/cil/oc/common/entity/Drone.scala +++ b/src/main/scala/li/cil/oc/common/entity/Drone.scala @@ -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,46 +270,49 @@ 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) { - // Client side update; occasionally update wing pitch and rotation to - // make the drones look a bit more dynamic. - val rng = world.rand - nextFlapChange -= 1 - nextAngularVelocityChange -= 1 + 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 + nextFlapChange -= 1 + nextAngularVelocityChange -= 1 - if (nextFlapChange < 0) { - nextFlapChange = 5 + rng.nextInt(10) - for (i <- 0 until 2) { - val flap = rng.nextInt(targetFlapAngles.length) - targetFlapAngles(flap)(0) = math.toRadians(rng.nextFloat() * 4 - 2).toFloat - targetFlapAngles(flap)(1) = math.toRadians(rng.nextFloat() * 4 - 2).toFloat + if (nextFlapChange < 0) { + nextFlapChange = 5 + rng.nextInt(10) + for (i <- 0 until 2) { + val flap = rng.nextInt(targetFlapAngles.length) + targetFlapAngles(flap)(0) = math.toRadians(rng.nextFloat() * 4 - 2).toFloat + targetFlapAngles(flap)(1) = math.toRadians(rng.nextFloat() * 4 - 2).toFloat + } } + + if (nextAngularVelocityChange < 0) { + if (angularVelocity != 0) { + angularVelocity = 0 + nextAngularVelocityChange = 20 + } + else { + angularVelocity = if (rng.nextBoolean()) 0.1f else -0.1f + nextAngularVelocityChange = 100 + } + } + + // Interpolate wing rotations. + (flapAngles, targetFlapAngles).zipped.foreach((f, t) => { + f(0) = f(0) * 0.7f + t(0) * 0.3f + f(1) = f(1) * 0.7f + t(1) * 0.3f + }) + + // Update body rotation. + bodyAngle += angularVelocity } - - if (nextAngularVelocityChange < 0) { - if (angularVelocity != 0) { - angularVelocity = 0 - nextAngularVelocityChange = 20 - } - else { - angularVelocity = if (rng.nextBoolean()) 0.1f else -0.1f - nextAngularVelocityChange = 100 - } - } - - // Interpolate wing rotations. - (flapAngles, targetFlapAngles).zipped.foreach((f, t) => { - f(0) = f(0) * 0.7f + t(0) * 0.3f - f(1) = f(1) * 0.7f + t(1) * 0.3f - }) - - // Update body rotation. - bodyAngle += angularVelocity } if (isRunning) { @@ -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) { diff --git a/src/main/scala/li/cil/oc/common/item/Drone.scala b/src/main/scala/li/cil/oc/common/item/Drone.scala index 309c483bb..5e1b89434 100644 --- a/src/main/scala/li/cil/oc/common/item/Drone.scala +++ b/src/main/scala/li/cil/oc/common/item/Drone.scala @@ -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 diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/Environment.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/Environment.scala index 1efdcbd16..2fc370635 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/traits/Environment.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/traits/Environment.scala @@ -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 } } diff --git a/src/main/scala/li/cil/oc/integration/opencomputers/DriverGeolyzer.scala b/src/main/scala/li/cil/oc/integration/opencomputers/DriverGeolyzer.scala index 53b4fc96d..a9abeb255 100644 --- a/src/main/scala/li/cil/oc/integration/opencomputers/DriverGeolyzer.scala +++ b/src/main/scala/li/cil/oc/integration/opencomputers/DriverGeolyzer.scala @@ -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")) diff --git a/src/main/scala/li/cil/oc/integration/opencomputers/DriverGraphicsCard.scala b/src/main/scala/li/cil/oc/integration/opencomputers/DriverGraphicsCard.scala index 670e25578..27b3122a9 100644 --- a/src/main/scala/li/cil/oc/integration/opencomputers/DriverGraphicsCard.scala +++ b/src/main/scala/li/cil/oc/integration/opencomputers/DriverGraphicsCard.scala @@ -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() diff --git a/src/main/scala/li/cil/oc/integration/opencomputers/DriverKeyboard.scala b/src/main/scala/li/cil/oc/integration/opencomputers/DriverKeyboard.scala index 2bcae0810..8a268c0f2 100644 --- a/src/main/scala/li/cil/oc/integration/opencomputers/DriverKeyboard.scala +++ b/src/main/scala/li/cil/oc/integration/opencomputers/DriverKeyboard.scala @@ -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 diff --git a/src/main/scala/li/cil/oc/integration/opencomputers/DriverNetworkCard.scala b/src/main/scala/li/cil/oc/integration/opencomputers/DriverNetworkCard.scala index 5a753df71..4a541ad00 100644 --- a/src/main/scala/li/cil/oc/integration/opencomputers/DriverNetworkCard.scala +++ b/src/main/scala/li/cil/oc/integration/opencomputers/DriverNetworkCard.scala @@ -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 diff --git a/src/main/scala/li/cil/oc/integration/opencomputers/DriverRedstoneCard.scala b/src/main/scala/li/cil/oc/integration/opencomputers/DriverRedstoneCard.scala index 9a229690d..d950e69b1 100644 --- a/src/main/scala/li/cil/oc/integration/opencomputers/DriverRedstoneCard.scala +++ b/src/main/scala/li/cil/oc/integration/opencomputers/DriverRedstoneCard.scala @@ -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 => diff --git a/src/main/scala/li/cil/oc/integration/opencomputers/DriverScreen.scala b/src/main/scala/li/cil/oc/integration/opencomputers/DriverScreen.scala index a93be4ee1..0d9f3f879 100644 --- a/src/main/scala/li/cil/oc/integration/opencomputers/DriverScreen.scala +++ b/src/main/scala/li/cil/oc/integration/opencomputers/DriverScreen.scala @@ -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) diff --git a/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeAngel.scala b/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeAngel.scala index 629ac8311..4fc50591e 100644 --- a/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeAngel.scala +++ b/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeAngel.scala @@ -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 diff --git a/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeBattery.scala b/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeBattery.scala index 3f0f316f1..b8fdd513d 100644 --- a/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeBattery.scala +++ b/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeBattery.scala @@ -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 diff --git a/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeChunkloader.scala b/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeChunkloader.scala index 950c6b94f..263d76f46 100644 --- a/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeChunkloader.scala +++ b/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeChunkloader.scala @@ -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 diff --git a/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeCrafting.scala b/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeCrafting.scala index aa190c416..9bd08370e 100644 --- a/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeCrafting.scala +++ b/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeCrafting.scala @@ -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) diff --git a/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeDatabase.scala b/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeDatabase.scala index 4a6d18281..b17a84304 100644 --- a/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeDatabase.scala +++ b/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeDatabase.scala @@ -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) diff --git a/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeExperience.scala b/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeExperience.scala index 9ca04d01f..63a19af23 100644 --- a/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeExperience.scala +++ b/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeExperience.scala @@ -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 diff --git a/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeGenerator.scala b/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeGenerator.scala index cdbdc621a..d5ee0f51c 100644 --- a/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeGenerator.scala +++ b/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeGenerator.scala @@ -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) diff --git a/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeInventory.scala b/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeInventory.scala index 21eebe8f7..601189bb8 100644 --- a/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeInventory.scala +++ b/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeInventory.scala @@ -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 diff --git a/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeInventoryController.scala b/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeInventoryController.scala index 5587a3018..b0c4d66b1 100644 --- a/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeInventoryController.scala +++ b/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeInventoryController.scala @@ -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) diff --git a/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeNavigation.scala b/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeNavigation.scala index 5d2b0ce98..2dc04f766 100644 --- a/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeNavigation.scala +++ b/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeNavigation.scala @@ -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) diff --git a/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradePiston.scala b/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradePiston.scala index a8739b13e..86eb52943 100644 --- a/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradePiston.scala +++ b/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradePiston.scala @@ -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 diff --git a/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeSign.scala b/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeSign.scala index 12b123edf..d36777fb3 100644 --- a/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeSign.scala +++ b/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeSign.scala @@ -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) diff --git a/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeSolarGenerator.scala b/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeSolarGenerator.scala index f04425a70..80c6a8b86 100644 --- a/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeSolarGenerator.scala +++ b/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeSolarGenerator.scala @@ -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 diff --git a/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeTank.scala b/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeTank.scala index 28899c924..2c5868161 100644 --- a/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeTank.scala +++ b/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeTank.scala @@ -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 diff --git a/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeTankController.scala b/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeTankController.scala index d77d9673f..90fd0fea0 100644 --- a/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeTankController.scala +++ b/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeTankController.scala @@ -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) diff --git a/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeTractorBeam.scala b/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeTractorBeam.scala index a12ccf0c0..40641eafc 100644 --- a/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeTractorBeam.scala +++ b/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeTractorBeam.scala @@ -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) diff --git a/src/main/scala/li/cil/oc/integration/opencomputers/Item.scala b/src/main/scala/li/cil/oc/integration/opencomputers/Item.scala index 29c3da899..05acad34e 100644 --- a/src/main/scala/li/cil/oc/integration/opencomputers/Item.scala +++ b/src/main/scala/li/cil/oc/integration/opencomputers/Item.scala @@ -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 { diff --git a/src/main/scala/li/cil/oc/integration/opencomputers/ModOpenComputers.scala b/src/main/scala/li/cil/oc/integration/opencomputers/ModOpenComputers.scala index fa832e2eb..c590e7a6b 100644 --- a/src/main/scala/li/cil/oc/integration/opencomputers/ModOpenComputers.scala +++ b/src/main/scala/li/cil/oc/integration/opencomputers/ModOpenComputers.scala @@ -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) + } } } diff --git a/src/main/scala/li/cil/oc/server/component/Drone.scala b/src/main/scala/li/cil/oc/server/component/Drone.scala index 97c504b25..513209b26 100644 --- a/src/main/scala/li/cil/oc/server/component/Drone.scala +++ b/src/main/scala/li/cil/oc/server/component/Drone.scala @@ -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) = { - 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)) + 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) + } } // ----------------------------------------------------------------------- // + @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.") diff --git a/src/main/scala/li/cil/oc/server/driver/Registry.scala b/src/main/scala/li/cil/oc/server/driver/Registry.scala index b87f50c56..bf29c219d 100644 --- a/src/main/scala/li/cil/oc/server/driver/Registry.scala +++ b/src/main/scala/li/cil/oc/server/driver/Registry.scala @@ -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 = { diff --git a/src/main/scala/li/cil/oc/util/PackedColor.scala b/src/main/scala/li/cil/oc/util/PackedColor.scala index 5248611e1..668a077ae 100644 --- a/src/main/scala/li/cil/oc/util/PackedColor.scala +++ b/src/main/scala/li/cil/oc/util/PackedColor.scala @@ -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)))