disk drive and floppy disks (disk drives are mountable and act as a "proxy" for the item in them); minor refactoring;

This commit is contained in:
Florian Nücke 2013-10-14 13:26:13 +02:00
parent c3ae449242
commit 8ed48750a3
55 changed files with 553 additions and 273 deletions

View File

@ -3,6 +3,8 @@ oc.block.Computer.name=Computer
oc.block.Keyboard.name=Tastatur oc.block.Keyboard.name=Tastatur
oc.block.Screen.name=Bildschirm oc.block.Screen.name=Bildschirm
oc.container.computer=Computer oc.container.computer=Computer
oc.container.disk_drive=Diskettenlaufwerk
oc.item.Disk.name=Diskette
oc.item.GraphicsCard.name=Grafikkarte oc.item.GraphicsCard.name=Grafikkarte
oc.item.HardDiskDrive2m.name=Festplatte (2MB) oc.item.HardDiskDrive2m.name=Festplatte (2MB)
oc.item.HardDiskDrive4m.name=Festplatte (4MB) oc.item.HardDiskDrive4m.name=Festplatte (4MB)

View File

@ -3,6 +3,8 @@ oc.block.Computer.name=Computer
oc.block.Keyboard.name=Keyboard oc.block.Keyboard.name=Keyboard
oc.block.Screen.name=Screen oc.block.Screen.name=Screen
oc.container.computer=Computer oc.container.computer=Computer
oc.container.disk_drive=Disk Drive
oc.item.Disk.name=Floppy Disk
oc.item.GraphicsCard.name=Graphics Card oc.item.GraphicsCard.name=Graphics Card
oc.item.HardDiskDrive2m.name=Hard Disk Drive (2MB) oc.item.HardDiskDrive2m.name=Hard Disk Drive (2MB)
oc.item.HardDiskDrive4m.name=Hard Disk Drive (4MB) oc.item.HardDiskDrive4m.name=Hard Disk Drive (4MB)

View File

@ -180,7 +180,9 @@ local function main(args)
debug.sethook(co, checkDeadline, "", 10000) debug.sethook(co, checkDeadline, "", 10000)
end end
local result = table.pack(coroutine.resume(co, table.unpack(args, 1, args.n))) local result = table.pack(coroutine.resume(co, table.unpack(args, 1, args.n)))
if result[1] then if coroutine.status(co) == "dead" then
error("computer stopped unexpectedly", 0)
elseif result[1] then
args = table.pack(coroutine.yield(result[2])) -- system yielded value args = table.pack(coroutine.yield(result[2])) -- system yielded value
else else
error(result[2], 0) error(result[2], 0)

View File

@ -109,9 +109,10 @@ end
function event.wait(seconds) function event.wait(seconds)
seconds = seconds or 0/0 seconds = seconds or 0/0
checkArg(1, seconds, "number") checkArg(1, seconds, "number")
local target = os.uptime() + (seconds == seconds and seconds or 0) local function isNaN(n) return n ~= n end
local target = os.uptime() + (isNaN(seconds) and 0 or seconds)
repeat repeat
local closest = seconds == seconds and target or math.huge local closest = isNaN(seconds) and math.huge or target
for _, info in pairs(timers) do for _, info in pairs(timers) do
if info.after < closest then if info.after < closest then
closest = info.after closest = info.after

View File

@ -23,7 +23,8 @@ end
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
local function onComponentAdded(_, address) local function onComponentAdded(_, address)
if component.type(address) == "filesystem" and local componentType = component.type(address)
if (componentType == "filesystem" or componentType == "disk_drive") and
address ~= os.romAddress() and address ~= os.romAddress() and
address ~= os.tmpAddress() address ~= os.tmpAddress()
then then
@ -44,7 +45,8 @@ local function onComponentAdded(_, address)
end end
local function onComponentRemoved(_, address) local function onComponentRemoved(_, address)
if component.type(address) == "filesystem" then local componentType = component.type(address)
if componentType == "filesystem" or componentType == "disk_drive" then
fs.umount(address) fs.umount(address)
end end
end end

Binary file not shown.

Before

Width:  |  Height:  |  Size: 650 B

After

Width:  |  Height:  |  Size: 399 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 592 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 605 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 542 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 583 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 508 B

View File

@ -14,6 +14,7 @@ object Blocks {
var powerDistributor: PowerDistributor = null var powerDistributor: PowerDistributor = null
var adapter: Adapter = null var adapter: Adapter = null
var diskDrive: DiskDrive = null
def init() { def init() {
// IMPORTANT: the multi block must come first, since the sub blocks will // IMPORTANT: the multi block must come first, since the sub blocks will
@ -30,5 +31,6 @@ object Blocks {
powerDistributor = new PowerDistributor(blockSimple) powerDistributor = new PowerDistributor(blockSimple)
adapter = new Adapter(blockSimple) adapter = new Adapter(blockSimple)
diskDrive = new DiskDrive(blockSimple)
} }
} }

View File

@ -9,28 +9,29 @@ object Items {
var rs: item.RedstoneCard = null var rs: item.RedstoneCard = null
var lan: item.NetworkCard = null var lan: item.NetworkCard = null
var ram32k: item.Memory = null var ram1: item.Memory = null
var ram64k: item.Memory = null var ram2: item.Memory = null
var ram128k: item.Memory = null var ram3: item.Memory = null
var hdd2: item.Hdd = null var hdd1: item.HardDiskDrive = null
var hdd4: item.Hdd = null var hdd2: item.HardDiskDrive = null
var hdd8: item.Hdd = null var hdd3: item.HardDiskDrive = null
var disk: item.Disk = null
def init() { def init() {
multi = new item.Delegator(Config.itemId) multi = new item.Delegator(Config.itemId)
gpu = new item.GraphicsCard(multi) gpu = new item.GraphicsCard(multi)
rs = new item.RedstoneCard(multi) rs = new item.RedstoneCard(multi)
ram32k = new item.Memory(multi, 32)
ram64k = new item.Memory(multi, 64)
ram128k = new item.Memory(multi, 128)
hdd2 = new item.Hdd(multi, 2)
hdd4 = new item.Hdd(multi, 4)
hdd8 = new item.Hdd(multi, 8)
lan = new item.NetworkCard(multi) lan = new item.NetworkCard(multi)
ram1 = new item.Memory(multi, 32)
ram2 = new item.Memory(multi, 64)
ram3 = new item.Memory(multi, 128)
hdd1 = new item.HardDiskDrive(multi, 2)
hdd2 = new item.HardDiskDrive(multi, 4)
hdd3 = new item.HardDiskDrive(multi, 8)
disk = new item.Disk(multi)
} }
} }

View File

@ -209,10 +209,12 @@ trait FileSystem extends Persistable {
def file(handle: Int): Option[Handle] def file(handle: Int): Option[Handle]
/** /**
* Called when the file system is deconstructed. * Called when the file system is close.
* <p/> * <p/>
* This should close any open real file handles (e.g. all open I/O streams) * This should close any open real file handles (e.g. all open I/O streams),
* and clear any other internal state. * but keep any internal state that may have to be persisted, for example
* for floppy disks (which are removed before they are saved so they don't
* save any open handles).
* <p/> * <p/>
* When the filesystem is made available as a network node created via * When the filesystem is made available as a network node created via
* `FileSystem.asNode` this will be called whenever the node is disconnected * `FileSystem.asNode` this will be called whenever the node is disconnected

View File

@ -44,6 +44,7 @@ trait Item extends Driver {
* driver supports may go. This will only be called if a previous call to * driver supports may go. This will only be called if a previous call to
* `worksWith` with the same item type returned true. * `worksWith` with the same item type returned true.
* *
* @param item the item to get the slot type for.
* @return the component type of the specified item. * @return the component type of the specified item.
*/ */
def slot(item: ItemStack): Slot.Value def slot(item: ItemStack): Slot.Value

View File

@ -0,0 +1,20 @@
package li.cil.oc.api.driver
import net.minecraft.item.ItemStack
/**
* Use this trait to implement components extending the memory of a computer.
* <p/>
* Note that the item must be installed in the actual computer's inventory to
* work. If it is installed in an external inventory the computer will not
* recognize the memory.
*/
trait Memory extends Item {
/**
* The amount of RAM this component provides, in byte.
*
* @param item the item to get the provided memory for.
* @return the amount of memory the specified component provides.
*/
def amount(item: ItemStack): Int
}

View File

@ -8,8 +8,18 @@ package li.cil.oc.api.driver
* inside the computer, not next to it. * inside the computer, not next to it.
*/ */
object Slot extends Enumeration { object Slot extends Enumeration {
val PSU = Value("PSU") /** Power generating components, such as generators. */
val RAM = Value("RAM") val Power = Value("Power")
val HDD = Value("HDD")
val PCI = Value("PCI") /** Memory extension components. */
val Memory = Value("Memory")
/** Hard disk drives. */
val HardDiskDrive = Value("HardDiskDrive")
/** Extension cards such as graphics or redstone cards. */
val Card = Value("Card")
/** Floppy disks. */
val Disk = Value("Disk")
} }

View File

@ -76,7 +76,7 @@ trait Node extends Persistable {
* they have is to *not* have an address, which can be useful for "dummy" * they have is to *not* have an address, which can be useful for "dummy"
* nodes, such as cables. In that case they may ignore the address being set. * nodes, such as cables. In that case they may ignore the address being set.
*/ */
var address: Option[String] = None final var address: Option[String] = None
/** /**
* The network this node is currently in. * The network this node is currently in.
@ -88,7 +88,7 @@ trait Node extends Persistable {
* This will always be set automatically by the network manager. Do not * This will always be set automatically by the network manager. Do not
* change this value and do not return anything that it wasn't set to. * change this value and do not return anything that it wasn't set to.
*/ */
var network: Option[Network] = None final var network: Option[Network] = None
/** /**
* Makes the node handle a message. * Makes the node handle a message.
@ -183,7 +183,7 @@ trait Node extends Persistable {
* @param args the values to return. * @param args the values to return.
* @return and array option as required by `receive`. * @return and array option as required by `receive`.
*/ */
protected def result(args: Any*): Option[Array[Any]] = { final protected def result(args: Any*): Option[Array[Any]] = {
def unwrap(arg: Any): AnyRef = arg match { def unwrap(arg: Any): AnyRef = arg match {
case x: ScalaNumber => x.underlying case x: ScalaNumber => x.underlying
case x => x.asInstanceOf[AnyRef] case x => x.asInstanceOf[AnyRef]

View File

@ -1,6 +1,6 @@
package li.cil.oc.client package li.cil.oc.client
import li.cil.oc.common.tileentity.{Screen, Computer} import li.cil.oc.common.tileentity
import li.cil.oc.common.{GuiHandler => CommonGuiHandler, GuiType} import li.cil.oc.common.{GuiHandler => CommonGuiHandler, GuiType}
import net.minecraft.entity.player.EntityPlayer import net.minecraft.entity.player.EntityPlayer
import net.minecraft.world.World import net.minecraft.world.World
@ -8,10 +8,12 @@ import net.minecraft.world.World
object GuiHandler extends CommonGuiHandler { object GuiHandler extends CommonGuiHandler {
override def getClientGuiElement(id: Int, player: EntityPlayer, world: World, x: Int, y: Int, z: Int) = override def getClientGuiElement(id: Int, player: EntityPlayer, world: World, x: Int, y: Int, z: Int) =
world.getBlockTileEntity(x, y, z) match { world.getBlockTileEntity(x, y, z) match {
case tileEntity: Computer if id == GuiType.Computer.id => case computer: tileentity.Computer if id == GuiType.Computer.id =>
new gui.Computer(player.inventory, tileEntity) new gui.Computer(player.inventory, computer)
case tileEntity: Screen if id == GuiType.Screen.id => case screen: tileentity.Screen if id == GuiType.Screen.id =>
new gui.Screen(tileEntity) new gui.Screen(screen)
case drive: tileentity.DiskDrive if id == GuiType.DiskDrive.id =>
new gui.DiskDrive(player.inventory, drive)
case _ => null case _ => null
} }
} }

View File

@ -8,6 +8,7 @@ import cpw.mods.fml.relauncher.Side
import li.cil.oc.OpenComputers import li.cil.oc.OpenComputers
import li.cil.oc.common.tileentity import li.cil.oc.common.tileentity
import li.cil.oc.common.{Proxy => CommonProxy} import li.cil.oc.common.{Proxy => CommonProxy}
import li.cil.oc.client.renderer.tileentity.{PowerDistributorRenderer, ScreenRenderer, ComputerRenderer}
private[oc] class Proxy extends CommonProxy { private[oc] class Proxy extends CommonProxy {
override def init(e: FMLInitializationEvent) = { override def init(e: FMLInitializationEvent) = {

View File

@ -3,17 +3,11 @@ package li.cil.oc.client.gui
import li.cil.oc.Config import li.cil.oc.Config
import li.cil.oc.common.container import li.cil.oc.common.container
import li.cil.oc.common.tileentity import li.cil.oc.common.tileentity
import net.minecraft.client.gui.inventory.GuiContainer
import net.minecraft.client.renderer.Tessellator
import net.minecraft.entity.player.InventoryPlayer import net.minecraft.entity.player.InventoryPlayer
import net.minecraft.inventory.Slot import net.minecraft.inventory.Slot
import net.minecraft.util.ResourceLocation import net.minecraft.util.{ResourceLocation, StatCollector}
import net.minecraft.util.StatCollector
import org.lwjgl.opengl.GL11
class Computer(inventory: InventoryPlayer, val tileEntity: tileentity.Computer) extends GuiContainer(new container.Computer(inventory, tileEntity)) {
private val background = new ResourceLocation(Config.resourceDomain, "textures/gui/computer.png")
class Computer(playerInventory: InventoryPlayer, val computer: tileentity.Computer) extends DynamicGuiContainer(new container.Computer(playerInventory, computer)) {
private val iconPsu = new ResourceLocation(Config.resourceDomain, "textures/gui/icon_psu.png") private val iconPsu = new ResourceLocation(Config.resourceDomain, "textures/gui/icon_psu.png")
private val iconPci = new ResourceLocation(Config.resourceDomain, "textures/gui/icon_pci.png") private val iconPci = new ResourceLocation(Config.resourceDomain, "textures/gui/icon_pci.png")
private val iconRam = new ResourceLocation(Config.resourceDomain, "textures/gui/icon_ram.png") private val iconRam = new ResourceLocation(Config.resourceDomain, "textures/gui/icon_ram.png")
@ -21,52 +15,18 @@ class Computer(inventory: InventoryPlayer, val tileEntity: tileentity.Computer)
private val icons = Array(iconPsu, iconPci, iconPci, iconPci, iconRam, iconRam, iconHdd, iconHdd) private val icons = Array(iconPsu, iconPci, iconPci, iconPci, iconRam, iconRam, iconHdd, iconHdd)
private var (x, y) = (0, 0)
override def initGui() = {
super.initGui()
x = (width - xSize) / 2
y = (height - ySize) / 2
}
override def drawSlotInventory(slot: Slot) = {
super.drawSlotInventory(slot)
if (slot.slotNumber < 8 && !slot.getHasStack)
drawSlotIcon(slot, icons(slot.slotNumber))
}
override def drawGuiContainerForegroundLayer(mouseX: Int, mouseY: Int) = { override def drawGuiContainerForegroundLayer(mouseX: Int, mouseY: Int) = {
fontRenderer.drawString( fontRenderer.drawString(
StatCollector.translateToLocal("oc.container.computer"), StatCollector.translateToLocal("oc.container.computer"),
8, 6, 0x404040) 8, 6, 0x404040)
fontRenderer.drawString(
StatCollector.translateToLocal("container.inventory"),
8, ySize - 96 + 2, 0x404040)
} }
override def drawGuiContainerBackgroundLayer(dt: Float, mouseX: Int, mouseY: Int) = { override protected def bindIconBackground(slot: Slot) =
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F) if (slot.slotNumber < 8 && !slot.getHasStack) {
mc.renderEngine.bindTexture(background) mc.renderEngine.bindTexture(icons(slot.slotNumber))
drawTexturedModalRect(x, y, 0, 0, xSize, ySize) true
} }
else false
override def doesGuiPauseGame = false override def doesGuiPauseGame = false
private def drawSlotIcon(slot: Slot, icon: ResourceLocation) = {
GL11.glPushAttrib(0xFFFFFF)
GL11.glDisable(GL11.GL_LIGHTING)
GL11.glDisable(GL11.GL_DEPTH_TEST)
GL11.glEnable(GL11.GL_BLEND)
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA)
GL11.glColor4f(1, 1, 1, 0.25f)
mc.renderEngine.bindTexture(icon)
val t = Tessellator.instance
t.startDrawingQuads()
t.addVertexWithUV(slot.xDisplayPosition, slot.yDisplayPosition + 16, zLevel, 0, 1)
t.addVertexWithUV(slot.xDisplayPosition + 16, slot.yDisplayPosition + 16, zLevel, 1, 1)
t.addVertexWithUV(slot.xDisplayPosition + 16, slot.yDisplayPosition, zLevel, 1, 0)
t.addVertexWithUV(slot.xDisplayPosition, slot.yDisplayPosition, zLevel, 0, 0)
t.draw()
GL11.glPopAttrib()
}
} }

View File

@ -0,0 +1,14 @@
package li.cil.oc.client.gui
import li.cil.oc.common.container
import li.cil.oc.common.tileentity
import net.minecraft.entity.player.InventoryPlayer
import net.minecraft.util.StatCollector
class DiskDrive(playerInventory: InventoryPlayer, val drive: tileentity.DiskDrive) extends DynamicGuiContainer(new container.DiskDrive(playerInventory, drive)) {
override def drawGuiContainerForegroundLayer(mouseX: Int, mouseY: Int) = {
fontRenderer.drawString(
StatCollector.translateToLocal("oc.container.disk_drive"),
8, 6, 0x404040)
}
}

View File

@ -0,0 +1,65 @@
package li.cil.oc.client.gui
import li.cil.oc.Config
import net.minecraft.client.gui.inventory.GuiContainer
import net.minecraft.client.renderer.Tessellator
import net.minecraft.inventory.{Container, Slot}
import net.minecraft.util.{StatCollector, ResourceLocation}
import org.lwjgl.opengl.GL11
abstract class DynamicGuiContainer(container: Container) extends GuiContainer(container) {
protected val slotBackground = new ResourceLocation(Config.resourceDomain, "textures/gui/slot.png")
protected val background = new ResourceLocation(Config.resourceDomain, "textures/gui/background.png")
protected var (x, y) = (0, 0)
override def initGui() = {
super.initGui()
x = (width - xSize) / 2
y = (height - ySize) / 2
}
override def drawGuiContainerForegroundLayer(mouseX: Int, mouseY: Int) = {
fontRenderer.drawString(
StatCollector.translateToLocal("container.inventory"),
8, ySize - 96 + 2, 0x404040)
}
override def drawGuiContainerBackgroundLayer(dt: Float, mouseX: Int, mouseY: Int) = {
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F)
mc.renderEngine.bindTexture(background)
drawTexturedModalRect(x, y, 0, 0, xSize, ySize)
}
override def drawSlotInventory(slot: Slot) = {
if (slot.slotNumber < container.inventorySlots.size() - 36) {
mc.renderEngine.bindTexture(slotBackground)
drawSlot(slot.xDisplayPosition - 1, slot.yDisplayPosition - 1, 18)
}
super.drawSlotInventory(slot)
if (bindIconBackground(slot))
drawSlot(slot.xDisplayPosition, slot.yDisplayPosition, 16, blend = true)
}
protected def bindIconBackground(slot: Slot) = false
private def drawSlot(x: Int, y: Int, size: Int, blend: Boolean = false) {
GL11.glPushAttrib(0xFFFFFF)
GL11.glDisable(GL11.GL_LIGHTING)
GL11.glDisable(GL11.GL_DEPTH_TEST)
if (blend) {
GL11.glEnable(GL11.GL_BLEND)
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA)
GL11.glColor4f(1, 1, 1, 0.25f)
}
else GL11.glColor4f(1, 1, 1, 1)
val t = Tessellator.instance
t.startDrawingQuads()
t.addVertexWithUV(x, y + size, zLevel, 0, 1)
t.addVertexWithUV(x + size, y + size, zLevel, 1, 1)
t.addVertexWithUV(x + size, y, zLevel, 1, 0)
t.addVertexWithUV(x, y, zLevel, 0, 0)
t.draw()
GL11.glPopAttrib()
}
}

View File

@ -1,4 +1,4 @@
package li.cil.oc.client package li.cil.oc.client.renderer.tileentity
import li.cil.oc.Config import li.cil.oc.Config
import li.cil.oc.common.tileentity.Computer import li.cil.oc.common.tileentity.Computer
@ -8,6 +8,7 @@ import net.minecraft.tileentity.TileEntity
import net.minecraft.util.ResourceLocation import net.minecraft.util.ResourceLocation
import net.minecraftforge.common.ForgeDirection import net.minecraftforge.common.ForgeDirection
import org.lwjgl.opengl.GL11 import org.lwjgl.opengl.GL11
import li.cil.oc.util.RenderState
object ComputerRenderer extends TileEntitySpecialRenderer { object ComputerRenderer extends TileEntitySpecialRenderer {
private val frontOn = new ResourceLocation(Config.resourceDomain, "textures/blocks/computer_front_on.png") private val frontOn = new ResourceLocation(Config.resourceDomain, "textures/blocks/computer_front_on.png")
@ -17,8 +18,8 @@ object ComputerRenderer extends TileEntitySpecialRenderer {
if (computer.isOn) { if (computer.isOn) {
GL11.glPushAttrib(0xFFFFFF) GL11.glPushAttrib(0xFFFFFF)
RenderUtil.disableLighting() RenderState.disableLighting()
RenderUtil.makeItBlend() RenderState.makeItBlend()
GL11.glPushMatrix() GL11.glPushMatrix()

View File

@ -1,4 +1,4 @@
package li.cil.oc.client package li.cil.oc.client.renderer.tileentity
import li.cil.oc.Config import li.cil.oc.Config
import li.cil.oc.common.tileentity import li.cil.oc.common.tileentity
@ -7,6 +7,7 @@ import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer
import net.minecraft.tileentity.TileEntity import net.minecraft.tileentity.TileEntity
import net.minecraft.util.ResourceLocation import net.minecraft.util.ResourceLocation
import org.lwjgl.opengl.GL11 import org.lwjgl.opengl.GL11
import li.cil.oc.util.RenderState
object PowerDistributorRenderer extends TileEntitySpecialRenderer { object PowerDistributorRenderer extends TileEntitySpecialRenderer {
private val sideOn = new ResourceLocation(Config.resourceDomain, "textures/blocks/power_distributor_on.png") private val sideOn = new ResourceLocation(Config.resourceDomain, "textures/blocks/power_distributor_on.png")
@ -16,8 +17,8 @@ object PowerDistributorRenderer extends TileEntitySpecialRenderer {
if (distributor.isActive) { if (distributor.isActive) {
GL11.glPushAttrib(0xFFFFFF) GL11.glPushAttrib(0xFFFFFF)
RenderUtil.disableLighting() RenderState.disableLighting()
RenderUtil.makeItBlend() RenderState.makeItBlend()
GL11.glPushMatrix() GL11.glPushMatrix()

View File

@ -1,4 +1,4 @@
package li.cil.oc.client package li.cil.oc.client.renderer.tileentity
import com.google.common.cache.{CacheBuilder, RemovalNotification, RemovalListener} import com.google.common.cache.{CacheBuilder, RemovalNotification, RemovalListener}
import cpw.mods.fml.common.{TickType, ITickHandler} import cpw.mods.fml.common.{TickType, ITickHandler}
@ -12,6 +12,7 @@ import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer
import net.minecraft.tileentity.TileEntity import net.minecraft.tileentity.TileEntity
import net.minecraftforge.common.ForgeDirection import net.minecraftforge.common.ForgeDirection
import org.lwjgl.opengl.{GL14, GL11} import org.lwjgl.opengl.{GL14, GL11}
import li.cil.oc.util.RenderState
object ScreenRenderer extends TileEntitySpecialRenderer with Callable[Int] with RemovalListener[TileEntity, Int] with ITickHandler { object ScreenRenderer extends TileEntitySpecialRenderer with Callable[Int] with RemovalListener[TileEntity, Int] with ITickHandler {
@ -52,8 +53,8 @@ object ScreenRenderer extends TileEntitySpecialRenderer with Callable[Int] with
GL11.glPushAttrib(0xFFFFFF) GL11.glPushAttrib(0xFFFFFF)
RenderUtil.disableLighting() RenderState.disableLighting()
RenderUtil.makeItBlend() RenderState.makeItBlend()
GL11.glPushMatrix() GL11.glPushMatrix()

View File

@ -1,15 +1,16 @@
package li.cil.oc.common package li.cil.oc.common
import cpw.mods.fml.common.network.IGuiHandler import cpw.mods.fml.common.network.IGuiHandler
import li.cil.oc.common.tileentity.Computer
import net.minecraft.entity.player.EntityPlayer import net.minecraft.entity.player.EntityPlayer
import net.minecraft.world.World import net.minecraft.world.World
abstract class GuiHandler extends IGuiHandler { abstract class GuiHandler extends IGuiHandler {
override def getServerGuiElement(id: Int, player: EntityPlayer, world: World, x: Int, y: Int, z: Int) = override def getServerGuiElement(id: Int, player: EntityPlayer, world: World, x: Int, y: Int, z: Int) =
world.getBlockTileEntity(x, y, z) match { world.getBlockTileEntity(x, y, z) match {
case tileEntity: Computer => case computer: tileentity.Computer =>
new container.Computer(player.inventory, tileEntity) new container.Computer(player.inventory, computer)
case drive: tileentity.DiskDrive =>
new container.DiskDrive(player.inventory, drive)
case _ => null case _ => null
} }
} }

View File

@ -3,4 +3,5 @@ package li.cil.oc.common
object GuiType extends Enumeration { object GuiType extends Enumeration {
val Computer = Value("Computer") val Computer = Value("Computer")
val Screen = Value("Screen") val Screen = Value("Screen")
val DiskDrive = Value("DiskDrive")
} }

View File

@ -16,8 +16,6 @@ class Computer(val parent: Delegator) extends Delegate {
val unlocalizedName = "Computer" val unlocalizedName = "Computer"
// ----------------------------------------------------------------------- //
// Rendering stuff
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
private object Icons { private object Icons {
@ -55,16 +53,12 @@ class Computer(val parent: Delegator) extends Delegate {
Icons.on(ForgeDirection.EAST.ordinal) = Icons.on(ForgeDirection.WEST.ordinal) Icons.on(ForgeDirection.EAST.ordinal) = Icons.on(ForgeDirection.WEST.ordinal)
} }
// ----------------------------------------------------------------------- //
// Tile entity
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
override def hasTileEntity = true override def hasTileEntity = true
override def createTileEntity(world: World, metadata: Int) = Some(new tileentity.Computer(world.isRemote)) override def createTileEntity(world: World, metadata: Int) = Some(new tileentity.Computer(world.isRemote))
// ----------------------------------------------------------------------- //
// Destruction / Interaction
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
override def canConnectRedstone(world: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection) = override def canConnectRedstone(world: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection) =
@ -77,8 +71,12 @@ class Computer(val parent: Delegator) extends Delegate {
world.getBlockTileEntity(x, y, z).asInstanceOf[tileentity.Computer].output(side) world.getBlockTileEntity(x, y, z).asInstanceOf[tileentity.Computer].output(side)
override def breakBlock(world: World, x: Int, y: Int, z: Int, blockId: Int, metadata: Int) = { override def breakBlock(world: World, x: Int, y: Int, z: Int, blockId: Int, metadata: Int) = {
if (!world.isRemote) if (!world.isRemote) world.getBlockTileEntity(x, y, z) match {
world.getBlockTileEntity(x, y, z).asInstanceOf[tileentity.Computer].turnOff() case computer: tileentity.Computer =>
computer.turnOff()
computer.dropContent(world, x, y, z)
case _ => // Ignore.
}
super.breakBlock(world, x, y, z, blockId, metadata) super.breakBlock(world, x, y, z, blockId, metadata)
} }

View File

@ -13,9 +13,9 @@ import net.minecraftforge.common.ForgeDirection
/** The base class on which all our blocks are built. */ /** The base class on which all our blocks are built. */
trait Delegate { trait Delegate {
def parent: Delegator val parent: Delegator
def unlocalizedName: String val unlocalizedName: String
val blockId = parent.add(this) val blockId = parent.add(this)

View File

@ -0,0 +1,57 @@
package li.cil.oc.common.block
import cpw.mods.fml.common.registry.GameRegistry
import li.cil.oc.common.{GuiType, tileentity}
import li.cil.oc.{OpenComputers, Config}
import net.minecraft.client.renderer.texture.IconRegister
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.util.Icon
import net.minecraft.world.World
import net.minecraftforge.common.ForgeDirection
class DiskDrive(val parent: Delegator) extends Delegate {
GameRegistry.registerTileEntity(classOf[tileentity.DiskDrive], "oc.disk_drive")
val unlocalizedName = "DiskDrive"
// ----------------------------------------------------------------------- //
private val icons = Array.fill[Icon](6)(null)
override def icon(side: ForgeDirection) = Some(icons(side.ordinal))
override def registerIcons(iconRegister: IconRegister) = {
icons(ForgeDirection.DOWN.ordinal) = iconRegister.registerIcon(Config.resourceDomain + ":computer_top")
icons(ForgeDirection.UP.ordinal) = icons(ForgeDirection.DOWN.ordinal)
icons(ForgeDirection.NORTH.ordinal) = iconRegister.registerIcon(Config.resourceDomain + ":disk_drive_side")
icons(ForgeDirection.SOUTH.ordinal) = iconRegister.registerIcon(Config.resourceDomain + ":disk_drive_front")
icons(ForgeDirection.WEST.ordinal) = icons(ForgeDirection.NORTH.ordinal)
icons(ForgeDirection.EAST.ordinal) = icons(ForgeDirection.NORTH.ordinal)
}
// ----------------------------------------------------------------------- //
override def hasTileEntity = true
override def createTileEntity(world: World, metadata: Int) = Some(new tileentity.DiskDrive)
// ----------------------------------------------------------------------- //
override def breakBlock(world: World, x: Int, y: Int, z: Int, blockId: Int, metadata: Int) = {
if (!world.isRemote) world.getBlockTileEntity(x, y, z) match {
case drive: tileentity.DiskDrive => drive.dropContent(world, x, y, z)
case _ => // Ignore.
}
super.breakBlock(world, x, y, z, blockId, metadata)
}
override def onBlockActivated(world: World, x: Int, y: Int, z: Int, player: EntityPlayer,
side: ForgeDirection, hitX: Float, hitY: Float, hitZ: Float) = {
if (!player.isSneaking) {
player.openGui(OpenComputers, GuiType.DiskDrive.id, world, x, y, z)
true
}
else false
}
}

View File

@ -0,0 +1,18 @@
package li.cil.oc.common.container
import li.cil.oc.common.tileentity
import net.minecraft.entity.player.InventoryPlayer
import net.minecraft.inventory.Slot
import net.minecraft.item.ItemStack
class DiskDrive(playerInventory: InventoryPlayer, drive: tileentity.DiskDrive) extends Player(playerInventory, drive) {
// Floppy slot.
addSlotToContainer(new Slot(drive, 0, 80, 35) {
override def isItemValid(item: ItemStack) = {
drive.isItemValidForSlot(0, item)
}
})
// Show the player's inventory.
addPlayerInventorySlots(8, 84)
}

View File

@ -7,9 +7,9 @@ import net.minecraft.util.Icon
import net.minecraft.world.World import net.minecraft.world.World
trait Delegate { trait Delegate {
def parent: Delegator val parent: Delegator
def unlocalizedName: String val unlocalizedName: String
val itemId = parent.add(this) val itemId = parent.add(this)
@ -23,7 +23,7 @@ trait Delegate {
def icon: Option[Icon] = _icon def icon: Option[Icon] = _icon
protected def icon_=(value: Icon) = _icon = Some(value) protected def icon_=(value: Icon) = _icon = Option(value)
def onItemRightClick(item: ItemStack, world: World, player: EntityPlayer): ItemStack = item def onItemRightClick(item: ItemStack, world: World, player: EntityPlayer): ItemStack = item

View File

@ -0,0 +1,14 @@
package li.cil.oc.common.item
import li.cil.oc.Config
import net.minecraft.client.renderer.texture.IconRegister
class Disk(val parent: Delegator) extends Delegate {
val unlocalizedName = "Disk"
override def registerIcons(iconRegister: IconRegister) {
super.registerIcons(iconRegister)
icon = iconRegister.registerIcon(Config.resourceDomain + ":disk")
}
}

View File

@ -4,7 +4,7 @@ import li.cil.oc.Config
import net.minecraft.client.renderer.texture.IconRegister import net.minecraft.client.renderer.texture.IconRegister
class GraphicsCard(val parent: Delegator) extends Delegate { class GraphicsCard(val parent: Delegator) extends Delegate {
def unlocalizedName = "GraphicsCard" val unlocalizedName = "GraphicsCard"
override def registerIcons(iconRegister: IconRegister) { override def registerIcons(iconRegister: IconRegister) {
super.registerIcons(iconRegister) super.registerIcons(iconRegister)

View File

@ -6,8 +6,8 @@ import net.minecraft.client.renderer.texture.IconRegister
import net.minecraft.entity.player.EntityPlayer import net.minecraft.entity.player.EntityPlayer
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
class Hdd(val parent: Delegator, val megaBytes: Int) extends Delegate { class HardDiskDrive(val parent: Delegator, val megaBytes: Int) extends Delegate {
def unlocalizedName = "HardDiskDrive" + megaBytes + "m" val unlocalizedName = "HardDiskDrive" + megaBytes + "m"
override def addInformation(item: ItemStack, player: EntityPlayer, tooltip: util.List[String], advanced: Boolean) = { override def addInformation(item: ItemStack, player: EntityPlayer, tooltip: util.List[String], advanced: Boolean) = {
super.addInformation(item, player, tooltip, advanced) super.addInformation(item, player, tooltip, advanced)

View File

@ -4,7 +4,7 @@ import li.cil.oc.Config
import net.minecraft.client.renderer.texture.IconRegister import net.minecraft.client.renderer.texture.IconRegister
class Memory(val parent: Delegator, val kiloBytes: Int) extends Delegate { class Memory(val parent: Delegator, val kiloBytes: Int) extends Delegate {
def unlocalizedName = "Memory" + kiloBytes + "k" val unlocalizedName = "Memory" + kiloBytes + "k"
override def registerIcons(iconRegister: IconRegister) { override def registerIcons(iconRegister: IconRegister) {
super.registerIcons(iconRegister) super.registerIcons(iconRegister)

View File

@ -4,7 +4,7 @@ import li.cil.oc.Config
import net.minecraft.client.renderer.texture.IconRegister import net.minecraft.client.renderer.texture.IconRegister
class NetworkCard(val parent: Delegator) extends Delegate { class NetworkCard(val parent: Delegator) extends Delegate {
def unlocalizedName = "NetworkCard" val unlocalizedName = "NetworkCard"
override def registerIcons(iconRegister: IconRegister) = { override def registerIcons(iconRegister: IconRegister) = {
super.registerIcons(iconRegister) super.registerIcons(iconRegister)

View File

@ -4,7 +4,7 @@ import li.cil.oc.Config
import net.minecraft.client.renderer.texture.IconRegister import net.minecraft.client.renderer.texture.IconRegister
class RedstoneCard(val parent: Delegator) extends Delegate { class RedstoneCard(val parent: Delegator) extends Delegate {
def unlocalizedName = "RedstoneCard" val unlocalizedName = "RedstoneCard"
override def registerIcons(iconRegister: IconRegister) { override def registerIcons(iconRegister: IconRegister) {
super.registerIcons(iconRegister) super.registerIcons(iconRegister)

View File

@ -6,6 +6,7 @@ import li.cil.oc.api.network.{Message, Visibility, Node}
import li.cil.oc.server.driver import li.cil.oc.server.driver
import net.minecraftforge.common.ForgeDirection import net.minecraftforge.common.ForgeDirection
import scala.collection.mutable import scala.collection.mutable
import net.minecraft.nbt.NBTTagCompound
class Adapter extends Rotatable with Node with IPeripheral { class Adapter extends Rotatable with Node with IPeripheral {
val name = "adapter" val name = "adapter"
@ -71,6 +72,19 @@ class Adapter extends Rotatable with Node with IPeripheral {
} }
} }
override def readFromNBT(nbt: NBTTagCompound) {
super.readFromNBT(nbt)
load(nbt.getCompoundTag("node"))
}
override def writeToNBT(nbt: NBTTagCompound) {
super.writeToNBT(nbt)
val nodeNbt = new NBTTagCompound
save(nodeNbt)
nbt.setCompoundTag("node", nodeNbt)
}
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
override def getType = "oc_adapter" override def getType = "oc_adapter"

View File

@ -1,33 +1,23 @@
package li.cil.oc.common.tileentity package li.cil.oc.common.tileentity
import li.cil.oc.Items import li.cil.oc.api.driver
import li.cil.oc.api.driver.Slot import li.cil.oc.api.network.Node
import li.cil.oc.api.network.{PoweredNode, Node}
import li.cil.oc.common.item
import li.cil.oc.server.component
import li.cil.oc.server.driver.Registry import li.cil.oc.server.driver.Registry
import net.minecraft.inventory.IInventory
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound import net.minecraft.nbt.NBTTagCompound
import net.minecraft.nbt.NBTTagList import net.minecraft.nbt.NBTTagList
import net.minecraft.world.World import net.minecraft.world.World
trait ComponentInventory extends IInventory with PoweredNode { trait ComponentInventory extends Inventory with Node {
protected val inventory = new Array[ItemStack](inventorySize) protected val components = Array.fill[Option[Node]](getSizeInventory)(None)
protected val itemComponents = Array.fill[Option[Node]](inventorySize)(None)
protected val computer: component.Computer
def world: World def world: World
def inventorySize = 8
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
def installedMemory = inventory.foldLeft(0)((sum, stack) => sum + (Registry.driverFor(stack) match { def installedMemory = inventory.foldLeft(0)((sum, stack) => sum + (stack match {
case Some(driver) if driver.slot(stack) == Slot.RAM => Items.multi.subItem(stack) match { case Some(item) => Registry.driverFor(item) match {
case Some(ram: item.Memory) => ram.kiloBytes * 1024 case Some(driver: driver.Memory) => driver.amount(item)
case _ => 0 case _ => 0
} }
case _ => 0 case _ => 0
@ -37,14 +27,16 @@ trait ComponentInventory extends IInventory with PoweredNode {
override protected def onConnect() { override protected def onConnect() {
super.onConnect() super.onConnect()
for (node <- itemComponents.filter(_.isDefined).map(_.get)) components collect {
network.foreach(_.connect(this, node)) case Some(node) => network.foreach(_.connect(this, node))
}
} }
override protected def onDisconnect() { override protected def onDisconnect() {
super.onDisconnect() super.onDisconnect()
for (node <- itemComponents.filter(_.isDefined).map(_.get)) components collect {
node.network.foreach(_.remove(node)) case Some(node) => node.network.foreach(_.remove(node))
}
} }
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
@ -56,32 +48,37 @@ trait ComponentInventory extends IInventory with PoweredNode {
val slotNbt = list.tagAt(i).asInstanceOf[NBTTagCompound] val slotNbt = list.tagAt(i).asInstanceOf[NBTTagCompound]
val slot = slotNbt.getByte("slot") val slot = slotNbt.getByte("slot")
if (slot >= 0 && slot < inventory.length) { if (slot >= 0 && slot < inventory.length) {
inventory(slot) = ItemStack.loadItemStackFromNBT( val item = ItemStack.loadItemStackFromNBT(slotNbt.getCompoundTag("item"))
slotNbt.getCompoundTag("item")) inventory(slot) = Some(item)
itemComponents(slot) = Registry.driverFor(inventory(slot)) match { components(slot) = Registry.driverFor(item) match {
case None => None case Some(driver) =>
case Some(driver) => driver.node(inventory(slot)) driver.node(item) match {
case Some(node) =>
node.load(driver.nbt(item))
Some(node)
case _ => None
}
case _ => None
} }
} }
} }
computer.recomputeMemory()
} }
override def save(nbt: NBTTagCompound) = { override def save(nbt: NBTTagCompound) = {
super.save(nbt) super.save(nbt)
val list = new NBTTagList val list = new NBTTagList
inventory.zipWithIndex filter { inventory.zipWithIndex collect {
case (stack, slot) => stack != null case (Some(stack), slot) => (stack, slot)
} foreach { } foreach {
case (stack, slot) => { case (stack, slot) => {
val slotNbt = new NBTTagCompound val slotNbt = new NBTTagCompound
slotNbt.setByte("slot", slot.toByte) slotNbt.setByte("slot", slot.toByte)
itemComponents(slot) match { components(slot) match {
case None => // Nothing special to save.
case Some(node) => case Some(node) =>
// We're guaranteed to have a driver for entries. // We're guaranteed to have a driver for entries.
node.save(Registry.driverFor(stack).get.nbt(stack)) node.save(Registry.driverFor(stack).get.nbt(stack))
case _ => // Nothing special to save.
} }
val itemNbt = new NBTTagCompound val itemNbt = new NBTTagCompound
@ -97,75 +94,27 @@ trait ComponentInventory extends IInventory with PoweredNode {
def getInventoryStackLimit = 1 def getInventoryStackLimit = 1
def getInvName = "oc.container.computer" override protected def onItemAdded(slot: Int, item: ItemStack) = if (!world.isRemote) {
Registry.driverFor(item) match {
def getSizeInventory = inventory.length case None => // No driver.
case Some(driver) => driver.node(item) match {
def getStackInSlot(i: Int) = inventory(i) case None => // No node.
case Some(node) =>
def decrStackSize(slot: Int, amount: Int) = { components(slot) = Some(node)
val stack = getStackInSlot(slot) node.load(driver.nbt(item))
val result = if (stack == null) network.foreach(_.connect(this, node))
null
else if (stack.stackSize <= amount) {
setInventorySlotContents(slot, null)
stack
}
else {
val subStack = stack.splitStack(amount)
if (stack.stackSize == 0) {
setInventorySlotContents(slot, null)
} }
subStack
} }
onInventoryChanged()
result
} }
def getStackInSlotOnClosing(slot: Int) = null override protected def onItemRemoved(slot: Int, item: ItemStack) = if (!world.isRemote) {
def setInventorySlotContents(slot: Int, item: ItemStack) = {
// Uninstall component previously in that slot. // Uninstall component previously in that slot.
if (!world.isRemote) itemComponents(slot) match { components(slot) match {
case None => // Nothing to do.
case Some(node) => case Some(node) =>
itemComponents(slot) = None components(slot) = None
node.network.foreach(_.remove(node)) node.network.foreach(_.remove(node))
node.save(Registry.driverFor(inventory(slot)).get.nbt(inventory(slot))) Registry.driverFor(item).foreach(driver => node.save(driver.nbt(item)))
case _ => // Nothing to do.
} }
inventory(slot) = item
if (item != null && item.stackSize > getInventoryStackLimit)
item.stackSize = getInventoryStackLimit
if (!world.isRemote) {
Registry.driverFor(inventory(slot)) match {
case None => // No driver.
case Some(driver) =>
driver.node(inventory(slot)) match {
case None => // No node.
case Some(node) =>
itemComponents(slot) = Some(node)
network.foreach(_.connect(this, node))
}
}
}
onInventoryChanged()
} }
def isItemValidForSlot(slot: Int, item: ItemStack) = (slot, Registry.driverFor(item)) match {
case (_, None) => false // Invalid item.
case (0, Some(driver)) => driver.slot(item) == Slot.PSU
case (1 | 2 | 3, Some(driver)) => driver.slot(item) == Slot.PCI
case (4 | 5, Some(driver)) => driver.slot(item) == Slot.RAM
case (6 | 7, Some(driver)) => driver.slot(item) == Slot.HDD
case _ => false // Invalid slot.
}
def isInvNameLocalized = false
def openChest() {}
def closeChest() {}
} }

View File

@ -1,16 +1,20 @@
package li.cil.oc.common.tileentity package li.cil.oc.common.tileentity
import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.atomic.AtomicBoolean
import li.cil.oc.api.driver.Slot
import li.cil.oc.api.network.PoweredNode
import li.cil.oc.client.{PacketSender => ClientPacketSender} import li.cil.oc.client.{PacketSender => ClientPacketSender}
import li.cil.oc.server.component import li.cil.oc.server.component
import li.cil.oc.server.component.Redstone import li.cil.oc.server.component.Redstone
import li.cil.oc.server.driver import li.cil.oc.server.driver
import li.cil.oc.server.driver.Registry
import li.cil.oc.server.{PacketSender => ServerPacketSender} import li.cil.oc.server.{PacketSender => ServerPacketSender}
import net.minecraft.entity.player.EntityPlayer import net.minecraft.entity.player.EntityPlayer
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound import net.minecraft.nbt.NBTTagCompound
import net.minecraftforge.common.ForgeDirection import net.minecraftforge.common.ForgeDirection
class Computer(isClient: Boolean) extends Rotatable with component.Computer.Environment with ComponentInventory with Redstone { class Computer(isClient: Boolean) extends Rotatable with component.Computer.Environment with ComponentInventory with Redstone with PoweredNode {
def this() = this(false) def this() = this(false)
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
@ -45,15 +49,16 @@ class Computer(isClient: Boolean) extends Rotatable with component.Computer.Envi
override def readFromNBT(nbt: NBTTagCompound) = { override def readFromNBT(nbt: NBTTagCompound) = {
super.readFromNBT(nbt) super.readFromNBT(nbt)
load(nbt.getCompoundTag("data")) load(nbt.getCompoundTag("node"))
computer.recomputeMemory()
} }
override def writeToNBT(nbt: NBTTagCompound) = { override def writeToNBT(nbt: NBTTagCompound) = {
super.writeToNBT(nbt) super.writeToNBT(nbt)
val dataNbt = new NBTTagCompound val nodeNbt = new NBTTagCompound
save(dataNbt) save(nodeNbt)
nbt.setCompoundTag("data", dataNbt) nbt.setCompoundTag("node", nodeNbt)
} }
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
@ -67,7 +72,7 @@ class Computer(isClient: Boolean) extends Rotatable with component.Computer.Envi
ServerPacketSender.sendComputerState(this, computer.isRunning) ServerPacketSender.sendComputerState(this, computer.isRunning)
isRunning = computer.isRunning isRunning = computer.isRunning
for (component <- itemComponents) component match { for (component <- components) component match {
case Some(node) => node.update() case Some(node) => node.update()
case _ => // Empty. case _ => // Empty.
} }
@ -83,6 +88,19 @@ class Computer(isClient: Boolean) extends Rotatable with component.Computer.Envi
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
def getInvName = "oc.container.computer"
def getSizeInventory = 8
def isItemValidForSlot(slot: Int, item: ItemStack) = (slot, Registry.driverFor(item)) match {
case (_, None) => false // Invalid item.
case (0, Some(driver)) => driver.slot(item) == Slot.Power
case (1 | 2 | 3, Some(driver)) => driver.slot(item) == Slot.Card
case (4 | 5, Some(driver)) => driver.slot(item) == Slot.Memory
case (6 | 7, Some(driver)) => driver.slot(item) == Slot.HardDiskDrive
case _ => false // Invalid slot.
}
override def isUseableByPlayer(player: EntityPlayer) = override def isUseableByPlayer(player: EntityPlayer) =
worldObj.getBlockTileEntity(xCoord, yCoord, zCoord) == this && worldObj.getBlockTileEntity(xCoord, yCoord, zCoord) == this &&
player.getDistanceSq(xCoord + 0.5, yCoord + 0.5, zCoord + 0.5) < 64 player.getDistanceSq(xCoord + 0.5, yCoord + 0.5, zCoord + 0.5) < 64
@ -118,6 +136,8 @@ class Computer(isClient: Boolean) extends Rotatable with component.Computer.Envi
else worldObj.markBlockForRenderUpdate(xCoord, yCoord, zCoord) else worldObj.markBlockForRenderUpdate(xCoord, yCoord, zCoord)
} }
private def hasRedstoneCard = private def hasRedstoneCard = inventory.exists {
!inventory.isEmpty && inventory.exists(item => item != null && driver.RedstoneCard.worksWith(item)) case Some(item) => driver.RedstoneCard.worksWith(item)
case _ => false
}
} }

View File

@ -0,0 +1,57 @@
package li.cil.oc.common.tileentity
import li.cil.oc.api.driver.Slot
import li.cil.oc.api.network.{Message, Visibility, Node}
import li.cil.oc.server.driver.Registry
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
class DiskDrive extends Rotatable with Node with ComponentInventory {
val name = "disk_drive"
val visibility = Visibility.Network
def world = worldObj
// ----------------------------------------------------------------------- //
override def receive(message: Message) = super.receive(message) orElse {
components(0) match {
case Some(node) if node.address.isDefined =>
node.receive(message)
case _ if message.name.startsWith("fs.") => result(Unit, "no disk")
case _ => None
}
}
// ----------------------------------------------------------------------- //
override def readFromNBT(nbt: NBTTagCompound) {
super.readFromNBT(nbt)
load(nbt.getCompoundTag("node"))
}
override def writeToNBT(nbt: NBTTagCompound) {
super.writeToNBT(nbt)
val nodeNbt = new NBTTagCompound
save(nodeNbt)
nbt.setCompoundTag("node", nodeNbt)
}
// ----------------------------------------------------------------------- //
def getInvName = "oc.container.disk_drive"
def getSizeInventory = 1
def isItemValidForSlot(slot: Int, item: ItemStack) = (slot, Registry.driverFor(item)) match {
case (0, Some(driver)) => driver.slot(item) == Slot.Disk
case _ => false
}
def isUseableByPlayer(player: EntityPlayer) =
worldObj.getBlockTileEntity(xCoord, yCoord, zCoord) == this &&
player.getDistanceSq(xCoord + 0.5, yCoord + 0.5, zCoord + 0.5) < 64
}

View File

@ -0,0 +1,66 @@
package li.cil.oc.common.tileentity
import net.minecraft.entity.item.EntityItem
import net.minecraft.inventory.IInventory
import net.minecraft.item.ItemStack
import net.minecraft.world.World
trait Inventory extends IInventory {
protected val inventory = Array.fill[Option[ItemStack]](getSizeInventory)(None)
def getStackInSlot(i: Int) = inventory(i).orNull
def decrStackSize(slot: Int, amount: Int) = inventory(slot) match {
case Some(stack) if stack.stackSize <= amount =>
setInventorySlotContents(slot, null)
stack
case Some(stack) =>
val result = stack.splitStack(amount)
onInventoryChanged()
result
case _ => null
}
def setInventorySlotContents(slot: Int, item: ItemStack) = {
if (inventory(slot).isDefined)
onItemRemoved(slot, inventory(slot).get)
inventory(slot) = Option(item)
if (item != null && item.stackSize > getInventoryStackLimit)
item.stackSize = getInventoryStackLimit
if (inventory(slot).isDefined)
onItemAdded(slot, inventory(slot).get)
onInventoryChanged()
}
def getStackInSlotOnClosing(slot: Int) = null
def isInvNameLocalized = false
def openChest() {}
def closeChest() {}
def dropContent(world: World, x: Int, y: Int, z: Int) {
val rng = world.rand
for (slot <- 0 until getSizeInventory) {
inventory(slot) match {
case Some(stack) if stack.stackSize > 0 =>
setInventorySlotContents(slot, null)
val (tx, ty, tz) = (0.25 + (rng.nextDouble() * 0.5), 0.25 + (rng.nextDouble() * 0.5), 0.25 + (rng.nextDouble() * 0.5))
val (vx, vy, vz) = ((rng.nextDouble() - 0.3) * 0.5, (rng.nextDouble() - 0.5) * 0.3, (rng.nextDouble() - 0.5) * 0.3)
val entity = new EntityItem(world, x + tx, y + ty, z + tz, stack.copy())
entity.setVelocity(vx, vy, vz)
entity.delayBeforeCanPickup = 20
world.spawnEntityInWorld(entity)
case _ => // Nothing.
}
}
}
protected def onItemAdded(slot: Int, item: ItemStack) {}
protected def onItemRemoved(slot: Int, item: ItemStack) {}
}

View File

@ -28,15 +28,15 @@ class Keyboard extends Rotatable with Node {
override def readFromNBT(nbt: NBTTagCompound) { override def readFromNBT(nbt: NBTTagCompound) {
super.readFromNBT(nbt) super.readFromNBT(nbt)
load(nbt.getCompoundTag("data")) load(nbt.getCompoundTag("node"))
} }
override def writeToNBT(nbt: NBTTagCompound) { override def writeToNBT(nbt: NBTTagCompound) {
super.writeToNBT(nbt) super.writeToNBT(nbt)
val dataNbt = new NBTTagCompound val nodeNbt = new NBTTagCompound
save(dataNbt) save(nodeNbt)
nbt.setCompoundTag("data", dataNbt) nbt.setCompoundTag("node", nodeNbt)
} }
def isUseableByPlayer(p: Player) = worldObj.getBlockTileEntity(xCoord, yCoord, zCoord) == this && def isUseableByPlayer(p: Player) = worldObj.getBlockTileEntity(xCoord, yCoord, zCoord) == this &&

View File

@ -15,15 +15,15 @@ class Screen extends Rotatable with ScreenEnvironment with PoweredNode {
override def readFromNBT(nbt: NBTTagCompound) = { override def readFromNBT(nbt: NBTTagCompound) = {
super.readFromNBT(nbt) super.readFromNBT(nbt)
load(nbt.getCompoundTag("data")) load(nbt.getCompoundTag("node"))
} }
override def writeToNBT(nbt: NBTTagCompound) = { override def writeToNBT(nbt: NBTTagCompound) = {
super.writeToNBT(nbt) super.writeToNBT(nbt)
val dataNbt = new NBTTagCompound val nodeNbt = new NBTTagCompound
save(dataNbt) save(nodeNbt)
nbt.setCompoundTag("data", dataNbt) nbt.setCompoundTag("node", nodeNbt)
} }
override def validate() = { override def validate() = {

View File

@ -2,34 +2,43 @@ package li.cil.oc.server.driver
import li.cil.oc import li.cil.oc
import li.cil.oc.api.driver.{Item, Slot} import li.cil.oc.api.driver.{Item, Slot}
import li.cil.oc.common.item.Hdd import li.cil.oc.common.item.{Disk, HardDiskDrive}
import li.cil.oc.{Config, Items} import li.cil.oc.{Config, Items}
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
object FileSystem extends Item { object FileSystem extends Item {
override def api = Option(getClass.getResourceAsStream(Config.driverPath + "filesystem.lua")) override def api = Option(getClass.getResourceAsStream(Config.driverPath + "filesystem.lua"))
override def worksWith(item: ItemStack) = WorksWith(Items.hdd2, Items.hdd4, Items.hdd8)(item) override def worksWith(item: ItemStack) = WorksWith(Items.hdd1, Items.hdd2, Items.hdd3, Items.disk)(item)
override def slot(item: ItemStack) = Slot.HDD override def slot(item: ItemStack) = Items.multi.subItem(item) match {
case Some(hdd: HardDiskDrive) => Slot.HardDiskDrive
case Some(disk: Disk) => Slot.Disk
case _ => throw new IllegalArgumentException()
}
override def node(item: ItemStack) = Items.multi.subItem(item) match { override def node(item: ItemStack) = Items.multi.subItem(item) match {
case Some(subItem: Hdd) => case Some(hdd: HardDiskDrive) => createNode(item, hdd.megaBytes * 1024 * 1024)
// We have a bit of a chicken-egg problem here, because we want to use the case Some(disk: Disk) => createNode(item, 512 * 1024)
// node's address as the folder name... so we generate the address here,
// if necessary. No one will know, right? Right!?
val tag = nbt(item)
val address =
if (tag.hasKey("address")) tag.getString("address")
else java.util.UUID.randomUUID().toString
oc.api.FileSystem.fromSaveDirectory(address, subItem.megaBytes * 1024 * 1024, Config.filesBuffered).
flatMap(oc.api.FileSystem.asNode) match {
case None => None
case Some(node) =>
node.address = Some(address)
node.load(tag)
Some(node)
}
case _ => None case _ => None
} }
private def createNode(item: ItemStack, capacity: Int) = {
// We have a bit of a chicken-egg problem here, because we want to use the
// node's address as the folder name... so we generate the address here,
// if necessary. No one will know, right? Right!?
val address = addressFromTag(nbt(item))
oc.api.FileSystem.fromSaveDirectory(address, capacity, Config.filesBuffered).
flatMap(oc.api.FileSystem.asNode) match {
case Some(node) =>
node.address = Some(address)
Some(node)
case None => None
}
}
private def addressFromTag(tag: NBTTagCompound) =
if (tag.hasKey("address")) tag.getString("address")
else java.util.UUID.randomUUID().toString
} }

View File

@ -11,11 +11,7 @@ object GraphicsCard extends driver.Item {
override def worksWith(item: ItemStack) = WorksWith(Items.gpu)(item) override def worksWith(item: ItemStack) = WorksWith(Items.gpu)(item)
override def slot(item: ItemStack) = Slot.PCI override def slot(item: ItemStack) = Slot.Card
override def node(item: ItemStack) = { override def node(item: ItemStack) = Some(new component.GraphicsCard())
val instance = new component.GraphicsCard()
instance.load(nbt(item))
Some(instance)
}
} }

View File

@ -5,8 +5,13 @@ import li.cil.oc.api.driver
import li.cil.oc.api.driver.Slot import li.cil.oc.api.driver.Slot
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
object Memory extends driver.Item { object Memory extends driver.Memory {
override def worksWith(item: ItemStack) = WorksWith(Items.ram128k, Items.ram32k, Items.ram64k)(item) override def amount(item: ItemStack) = if (item.itemID == Items.multi.itemID) Items.multi.subItem(item) match {
case Some(memory: li.cil.oc.common.item.Memory) => memory.kiloBytes * 1024
case _ => 0
} else 0
override def slot(item: ItemStack) = Slot.RAM override def worksWith(item: ItemStack) = WorksWith(Items.ram3, Items.ram1, Items.ram2)(item)
override def slot(item: ItemStack) = Slot.Memory
} }

View File

@ -11,11 +11,7 @@ object NetworkCard extends driver.Item {
def worksWith(item: ItemStack) = WorksWith(Items.lan)(item) def worksWith(item: ItemStack) = WorksWith(Items.lan)(item)
def slot(item: ItemStack) = Slot.PCI def slot(item: ItemStack) = Slot.Card
override def node(item: ItemStack) = { override def node(item: ItemStack) = Some(new component.NetworkCard())
val instance = new component.NetworkCard()
instance.load(nbt(item))
Some(instance)
}
} }

View File

@ -11,11 +11,7 @@ object RedstoneCard extends driver.Item {
override def worksWith(item: ItemStack) = WorksWith(Items.rs)(item) override def worksWith(item: ItemStack) = WorksWith(Items.rs)(item)
override def slot(item: ItemStack) = Slot.PCI override def slot(item: ItemStack) = Slot.Card
override def node(item: ItemStack) = { override def node(item: ItemStack) = Some(new component.RedstoneCard())
val instance = new component.RedstoneCard()
instance.load(nbt(item))
Some(instance)
}
} }

View File

@ -95,13 +95,6 @@ trait VirtualFileSystem extends OutputStreamFileSystem {
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
override def close() = {
super.close()
root.children.clear()
}
// ----------------------------------------------------------------------- //
override protected def openInputStream(path: String) = override protected def openInputStream(path: String) =
root.get(segments(path)) match { root.get(segments(path)) match {
case Some(obj: VirtualFile) => obj.openInputStream() case Some(obj: VirtualFile) => obj.openInputStream()

View File

@ -99,7 +99,7 @@ object LuaStateFactory {
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
def createState(): Option[LuaState] = { def createState(): Option[LuaState] = {
val state = new LuaState(Integer.MAX_VALUE) val state = new LuaState(Int.MaxValue)
try { try {
// Load all libraries. // Load all libraries.
state.openLib(LuaState.Library.BASE) state.openLib(LuaState.Library.BASE)

View File

@ -1,9 +1,9 @@
package li.cil.oc.client package li.cil.oc.util
import net.minecraft.client.renderer.OpenGlHelper import net.minecraft.client.renderer.OpenGlHelper
import org.lwjgl.opengl.{ARBMultitexture, GLContext, GL11, GL13} import org.lwjgl.opengl.{ARBMultitexture, GLContext, GL11, GL13}
object RenderUtil { object RenderState {
val arb = GLContext.getCapabilities.GL_ARB_multitexture && !GLContext.getCapabilities.OpenGL13 val arb = GLContext.getCapabilities.GL_ARB_multitexture && !GLContext.getCapabilities.OpenGL13
def disableLighting() { def disableLighting() {