multi-tier screens and gpus. three tiers, with increasing resolutions and (at some point) color starting with the second tierl; custom "Ordering" implementation so we can just sort screens by their coordinates one by one instead of hashing them; Tuple (and untested Seq) return values supported for driver callbacks (converted to tables); added a field called "n" to all "arrays" returned from driver calls (so also tuples and seqs) mimicking Lua's table.pack
@ -2,11 +2,16 @@ oc.block.Adapter.name=Adapter
|
||||
oc.block.Computer.name=Computer
|
||||
oc.block.DiskDrive.name=Diskettenlaufwerk
|
||||
oc.block.Keyboard.name=Tastatur
|
||||
oc.block.Screen.name=Bildschirm
|
||||
oc.block.ScreenAdvanced.name=Hochwertiger Bildschirm
|
||||
oc.block.ScreenBasic.name=Einfacher Bildschirm
|
||||
oc.block.ScreenProfessional.name=Professioneller Bildschirm
|
||||
oc.container.Computer=Computer
|
||||
oc.container.DiskDrive=Diskettenlaufwerk
|
||||
oc.item.Disk.name=Diskette
|
||||
oc.item.GraphicsCard.name=Grafikkarte
|
||||
oc.item.GraphicsCard.name=
|
||||
oc.item.GraphicsCardAdvanced.name=Hochwertige Grafikkarte
|
||||
oc.item.GraphicsCardBasic.name=Einfache Grafikkarte
|
||||
oc.item.GraphicsCardProfessional.name=Professionelle Grafikkarte
|
||||
oc.item.HardDiskDrive2m.name=Festplatte (2MB)
|
||||
oc.item.HardDiskDrive4m.name=Festplatte (4MB)
|
||||
oc.item.HardDiskDrive8m.name=Festplatte (8MB)
|
||||
|
@ -2,11 +2,15 @@ oc.block.Adapter.name=Adapter
|
||||
oc.block.Computer.name=Computer
|
||||
oc.block.DiskDrive.name=Disk Drive
|
||||
oc.block.Keyboard.name=Keyboard
|
||||
oc.block.Screen.name=Screen
|
||||
oc.block.ScreenAdvanced.name=Advanced Screen
|
||||
oc.block.ScreenBasic.name=Basic Screen
|
||||
oc.block.ScreenProfessional.name=Professional Screen
|
||||
oc.container.Computer=Computer
|
||||
oc.container.DiskDrive=Disk Drive
|
||||
oc.item.Disk.name=Floppy Disk
|
||||
oc.item.GraphicsCard.name=Graphics Card
|
||||
oc.item.GraphicsCardAdvanced.name=Advanced Graphics Card
|
||||
oc.item.GraphicsCardBasic.name=Basic Graphics Card
|
||||
oc.item.GraphicsCardProfessional.name=Professional Graphics Card
|
||||
oc.item.HardDiskDrive2m.name=Hard Disk Drive (2MB)
|
||||
oc.item.HardDiskDrive4m.name=Hard Disk Drive (4MB)
|
||||
oc.item.HardDiskDrive8m.name=Hard Disk Drive (8MB)
|
||||
|
Before Width: | Height: | Size: 325 B After Width: | Height: | Size: 325 B |
Before Width: | Height: | Size: 462 B After Width: | Height: | Size: 462 B |
Before Width: | Height: | Size: 309 B After Width: | Height: | Size: 309 B |
Before Width: | Height: | Size: 442 B After Width: | Height: | Size: 441 B |
Before Width: | Height: | Size: 311 B After Width: | Height: | Size: 311 B |
Before Width: | Height: | Size: 452 B After Width: | Height: | Size: 452 B |
Before Width: | Height: | Size: 316 B After Width: | Height: | Size: 316 B |
Before Width: | Height: | Size: 443 B After Width: | Height: | Size: 443 B |
Before Width: | Height: | Size: 324 B After Width: | Height: | Size: 324 B |
Before Width: | Height: | Size: 445 B After Width: | Height: | Size: 446 B |
Before Width: | Height: | Size: 312 B After Width: | Height: | Size: 312 B |
Before Width: | Height: | Size: 445 B After Width: | Height: | Size: 448 B |
Before Width: | Height: | Size: 320 B After Width: | Height: | Size: 320 B |
Before Width: | Height: | Size: 448 B After Width: | Height: | Size: 447 B |
Before Width: | Height: | Size: 308 B After Width: | Height: | Size: 308 B |
Before Width: | Height: | Size: 290 B After Width: | Height: | Size: 290 B |
Before Width: | Height: | Size: 312 B After Width: | Height: | Size: 312 B |
Before Width: | Height: | Size: 317 B After Width: | Height: | Size: 317 B |
Before Width: | Height: | Size: 317 B After Width: | Height: | Size: 317 B |
Before Width: | Height: | Size: 319 B After Width: | Height: | Size: 318 B |
Before Width: | Height: | Size: 321 B After Width: | Height: | Size: 321 B |
Before Width: | Height: | Size: 436 B After Width: | Height: | Size: 435 B |
Before Width: | Height: | Size: 317 B After Width: | Height: | Size: 317 B |
Before Width: | Height: | Size: 316 B After Width: | Height: | Size: 316 B |
Before Width: | Height: | Size: 268 B After Width: | Height: | Size: 268 B |
Before Width: | Height: | Size: 326 B After Width: | Height: | Size: 327 B |
Before Width: | Height: | Size: 227 B After Width: | Height: | Size: 227 B |
Before Width: | Height: | Size: 251 B After Width: | Height: | Size: 252 B |
Before Width: | Height: | Size: 193 B After Width: | Height: | Size: 193 B |
Before Width: | Height: | Size: 188 B After Width: | Height: | Size: 188 B |
Before Width: | Height: | Size: 219 B After Width: | Height: | Size: 219 B |
Before Width: | Height: | Size: 259 B After Width: | Height: | Size: 259 B |
Before Width: | Height: | Size: 242 B After Width: | Height: | Size: 242 B |
Before Width: | Height: | Size: 290 B After Width: | Height: | Size: 290 B |
Before Width: | Height: | Size: 214 B After Width: | Height: | Size: 215 B |
Before Width: | Height: | Size: 230 B After Width: | Height: | Size: 230 B |
Before Width: | Height: | Size: 248 B After Width: | Height: | Size: 248 B |
Before Width: | Height: | Size: 287 B After Width: | Height: | Size: 285 B |
Before Width: | Height: | Size: 207 B After Width: | Height: | Size: 207 B |
Before Width: | Height: | Size: 195 B After Width: | Height: | Size: 195 B |
Before Width: | Height: | Size: 229 B After Width: | Height: | Size: 230 B |
Before Width: | Height: | Size: 190 B After Width: | Height: | Size: 190 B |
Before Width: | Height: | Size: 220 B After Width: | Height: | Size: 221 B |
Before Width: | Height: | Size: 241 B After Width: | Height: | Size: 241 B |
Before Width: | Height: | Size: 304 B After Width: | Height: | Size: 303 B |
Before Width: | Height: | Size: 239 B After Width: | Height: | Size: 239 B |
Before Width: | Height: | Size: 249 B After Width: | Height: | Size: 249 B |
Before Width: | Height: | Size: 250 B After Width: | Height: | Size: 250 B |
BIN
assets/opencomputers/textures/items/gpu1.png
Normal file
After Width: | Height: | Size: 250 B |
BIN
assets/opencomputers/textures/items/gpu2.png
Normal file
After Width: | Height: | Size: 250 B |
@ -7,7 +7,7 @@ object Blocks {
|
||||
var blockSpecial: SpecialDelegator = null
|
||||
|
||||
var computer: Computer = null
|
||||
var screen: Screen = null
|
||||
var screen1, screen2, screen3: Screen = null
|
||||
var keyboard: Keyboard = null
|
||||
|
||||
var powerSupply: PowerSupply = null
|
||||
@ -24,7 +24,11 @@ object Blocks {
|
||||
blockSpecial = new SpecialDelegator(Config.blockSpecialId)
|
||||
|
||||
computer = new Computer(blockSimple)
|
||||
screen = new Screen(blockSimple)
|
||||
|
||||
screen1 = new ScreenTier1(blockSimple)
|
||||
screen2 = new ScreenTier2(blockSimple)
|
||||
screen3 = new ScreenTier3(blockSimple)
|
||||
|
||||
keyboard = new Keyboard(blockSpecial)
|
||||
|
||||
powerSupply = new PowerSupply(blockSimple)
|
||||
|
@ -8,6 +8,13 @@ object Config {
|
||||
val scriptPath = "/assets/" + resourceDomain + "/lua/"
|
||||
val driverPath = "/assets/" + resourceDomain + "/lua/drivers/"
|
||||
|
||||
// Let's stick to "common" ratios of 4:3 and 16:9, pixel wise. Corrected
|
||||
// for the font size that's 2.4:1 and 3.2:1.
|
||||
val screenResolutionsByTier = Array(
|
||||
List((40, 16)),
|
||||
List((40, 16), (60, 25), (80, 25)),
|
||||
List((40, 16), (60, 25), (80, 25), (120, 50), (160, 50)))
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
var blockRenderId = 0
|
||||
|
@ -5,10 +5,13 @@ import li.cil.oc.common.item
|
||||
object Items {
|
||||
var multi: item.Delegator = null
|
||||
|
||||
var gpu: item.GraphicsCard = null
|
||||
var rs: item.RedstoneCard = null
|
||||
var lan: item.NetworkCard = null
|
||||
|
||||
var gpu1: item.GraphicsCard = null
|
||||
var gpu2: item.GraphicsCard = null
|
||||
var gpu3: item.GraphicsCard = null
|
||||
|
||||
var ram1: item.Memory = null
|
||||
var ram2: item.Memory = null
|
||||
var ram3: item.Memory = null
|
||||
@ -21,10 +24,13 @@ object Items {
|
||||
def init() {
|
||||
multi = new item.Delegator(Config.itemId)
|
||||
|
||||
gpu = new item.GraphicsCard(multi)
|
||||
rs = new item.RedstoneCard(multi)
|
||||
lan = new item.NetworkCard(multi)
|
||||
|
||||
gpu1 = new item.GraphicsCard(multi, 0)
|
||||
gpu2 = new item.GraphicsCard(multi, 1)
|
||||
gpu3 = new item.GraphicsCard(multi, 2)
|
||||
|
||||
ram1 = new item.Memory(multi, 32)
|
||||
ram2 = new item.Memory(multi, 64)
|
||||
ram3 = new item.Memory(multi, 128)
|
||||
|
@ -33,41 +33,40 @@ class PacketHandler extends CommonPacketHandler {
|
||||
|
||||
def onScreenResolutionChange(p: PacketParser) =
|
||||
p.readTileEntity[Screen]() match {
|
||||
case None => // Invalid packet.
|
||||
case Some(t) => {
|
||||
val w = p.readInt()
|
||||
val h = p.readInt()
|
||||
t.screen.resolution = (w, h)
|
||||
t.instance.resolution = (w, h)
|
||||
}
|
||||
case _ => // Invalid packet.
|
||||
}
|
||||
|
||||
def onScreenSet(p: PacketParser) =
|
||||
p.readTileEntity[Screen]() match {
|
||||
case None => // Invalid packet.
|
||||
case Some(t) => {
|
||||
val col = p.readInt()
|
||||
val row = p.readInt()
|
||||
val s = p.readUTF()
|
||||
t.screen.set(col, row, s)
|
||||
t.instance.set(col, row, s)
|
||||
}
|
||||
case _ => // Invalid packet.
|
||||
}
|
||||
|
||||
def onScreenFill(p: PacketParser) =
|
||||
p.readTileEntity[Screen]() match {
|
||||
case None => // Invalid packet.
|
||||
case Some(t) => {
|
||||
val col = p.readInt()
|
||||
val row = p.readInt()
|
||||
val w = p.readInt()
|
||||
val h = p.readInt()
|
||||
val c = p.readChar()
|
||||
t.screen.fill(col, row, w, h, c)
|
||||
t.instance.fill(col, row, w, h, c)
|
||||
}
|
||||
case _ => // Invalid packet.
|
||||
}
|
||||
|
||||
def onScreenCopy(p: PacketParser) =
|
||||
p.readTileEntity[Screen]() match {
|
||||
case None => // Invalid packet.
|
||||
case Some(t) => {
|
||||
val col = p.readInt()
|
||||
val row = p.readInt()
|
||||
@ -75,42 +74,46 @@ class PacketHandler extends CommonPacketHandler {
|
||||
val h = p.readInt()
|
||||
val tx = p.readInt()
|
||||
val ty = p.readInt()
|
||||
t.screen.copy(col, row, w, h, tx, ty)
|
||||
t.instance.copy(col, row, w, h, tx, ty)
|
||||
}
|
||||
case _ => // Invalid packet.
|
||||
}
|
||||
|
||||
def onScreenBufferResponse(p: PacketParser) =
|
||||
p.readTileEntity[Screen]() match {
|
||||
case None => // Invalid packet.
|
||||
case Some(t) =>
|
||||
val w = p.readInt()
|
||||
val h = p.readInt()
|
||||
t.instance.resolution = (w, h)
|
||||
p.readUTF.split('\n').zipWithIndex.foreach {
|
||||
case (line, i) => t.screen.set(0, i, line)
|
||||
case (line, i) => t.instance.set(0, i, line)
|
||||
}
|
||||
case _ => // Invalid packet.
|
||||
}
|
||||
|
||||
def onComputerStateResponse(p: PacketParser) =
|
||||
p.readTileEntity[Computer]() match {
|
||||
case None => // Invalid packet.
|
||||
case Some(t) => {
|
||||
t.isOn = p.readBoolean()
|
||||
}
|
||||
case _ => // Invalid packet.
|
||||
}
|
||||
|
||||
def onRotatableStateResponse(p: PacketParser) =
|
||||
p.readTileEntity[Rotatable]() match {
|
||||
case None => // Invalid packet.
|
||||
case Some(t) =>
|
||||
t.pitch = p.readDirection()
|
||||
t.yaw = p.readDirection()
|
||||
case _ => // Invalid packet.
|
||||
}
|
||||
|
||||
def onRedstoneStateResponse(p: PacketParser) =
|
||||
p.readTileEntity[TileEntity with Redstone]() match {
|
||||
case None => // Invalid packet.
|
||||
case Some(t) =>
|
||||
t.isOutputEnabled = p.readBoolean()
|
||||
for (d <- ForgeDirection.VALID_DIRECTIONS) {
|
||||
t.output(d, p.readByte())
|
||||
}
|
||||
case _ => // Invalid packet.
|
||||
}
|
||||
}
|
@ -47,11 +47,11 @@ class Screen(tileEntity: tileentity.Screen) extends MCGuiScreen {
|
||||
|
||||
// Re-build display lists.
|
||||
Screen.compileBackground(innerWidth, innerHeight)
|
||||
Screen.compileText(scale, screen.screen.lines)
|
||||
Screen.compileText(scale, screen.instance.lines)
|
||||
}
|
||||
|
||||
/** Must be called whenever the buffer of the underlying screen changes. */
|
||||
def updateText() = Screen.compileText(scale, screen.screen.lines)
|
||||
def updateText() = Screen.compileText(scale, screen.instance.lines)
|
||||
|
||||
override def handleKeyboardInput() {
|
||||
super.handleKeyboardInput()
|
||||
@ -83,7 +83,7 @@ class Screen(tileEntity: tileentity.Screen) extends MCGuiScreen {
|
||||
super.initGui()
|
||||
MonospaceFontRenderer.init(mc.renderEngine)
|
||||
Screen.init(mc.renderEngine)
|
||||
val (w, h) = screen.screen.resolution
|
||||
val (w, h) = screen.instance.resolution
|
||||
changeSize(w, h)
|
||||
}
|
||||
|
||||
|
@ -114,13 +114,13 @@ object ScreenRenderer extends TileEntitySpecialRenderer with Callable[Int] with
|
||||
GL11.glTranslatef(0, 0, 0.01f)
|
||||
|
||||
// Scale based on actual buffer size.
|
||||
val (w, h) = screen.screen.resolution
|
||||
val (w, h) = screen.instance.resolution
|
||||
val scaleX = sx.toFloat / (w * MonospaceFontRenderer.fontWidth)
|
||||
val scaleY = sy.toFloat / (h * MonospaceFontRenderer.fontHeight)
|
||||
val scale = scaleX min scaleY
|
||||
GL11.glScalef(scale / sx.toFloat, scale / sy.toFloat, 1)
|
||||
|
||||
for ((line, i) <- screen.screen.lines.zipWithIndex) {
|
||||
for ((line, i) <- screen.instance.lines.zipWithIndex) {
|
||||
MonospaceFontRenderer.drawString(line, 0, i * MonospaceFontRenderer.fontHeight)
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,7 @@ class Adapter(val parent: SimpleDelegator) extends SimpleDelegate {
|
||||
|
||||
override def hasTileEntity = true
|
||||
|
||||
override def createTileEntity(world: World, metadata: Int) = Some(new tileentity.Adapter)
|
||||
override def createTileEntity(world: World) = Some(new tileentity.Adapter)
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
// Block detection
|
||||
|
@ -57,7 +57,7 @@ class Computer(val parent: SimpleDelegator) extends SimpleDelegate {
|
||||
|
||||
override def hasTileEntity = true
|
||||
|
||||
override def createTileEntity(world: World, metadata: Int) = Some(new tileentity.Computer(world.isRemote))
|
||||
override def createTileEntity(world: World) = Some(new tileentity.Computer(world.isRemote))
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
@ -70,7 +70,7 @@ class Computer(val parent: SimpleDelegator) extends SimpleDelegate {
|
||||
override def isProvidingWeakPower(world: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection) =
|
||||
world.getBlockTileEntity(x, y, z).asInstanceOf[tileentity.Computer].output(side)
|
||||
|
||||
override def onBlockPreDestroy(world: World, x: Int, y: Int, z: Int, metadata: Int) =
|
||||
override def onBlockPreDestroy(world: World, x: Int, y: Int, z: Int) =
|
||||
if (!world.isRemote) world.getBlockTileEntity(x, y, z) match {
|
||||
case computer: tileentity.Computer =>
|
||||
computer.turnOff()
|
||||
|
@ -19,18 +19,21 @@ trait Delegate {
|
||||
// Block
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
def breakBlock(world: World, x: Int, y: Int, z: Int, blockId: Int, metadata: Int) {}
|
||||
def breakBlock(world: World, x: Int, y: Int, z: Int, blockId: Int) {}
|
||||
|
||||
def canConnectRedstone(world: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection) = false
|
||||
|
||||
def createTileEntity(world: World, metadata: Int): Option[TileEntity] = None
|
||||
def colorMultiplier(world: IBlockAccess, x: Int, y: Int, z: Int) = getRenderColor
|
||||
|
||||
def getBlockTextureFromSide(world: IBlockAccess, x: Int, y: Int, z: Int, worldSide: ForgeDirection, localSide: ForgeDirection): Option[Icon] = icon(localSide)
|
||||
def createTileEntity(world: World): Option[TileEntity] = None
|
||||
|
||||
def getBlockTextureFromSide(world: IBlockAccess, x: Int, y: Int, z: Int,
|
||||
worldSide: ForgeDirection, localSide: ForgeDirection): Option[Icon] = icon(localSide)
|
||||
|
||||
def getCollisionBoundingBoxFromPool(world: World, x: Int, y: Int, z: Int) =
|
||||
AxisAlignedBB.getAABBPool.getAABB(x, y, z, x + 1, y + 1, z + 1)
|
||||
|
||||
def icon(side: ForgeDirection): Option[Icon] = None
|
||||
def getRenderColor = 0xFFFFFF
|
||||
|
||||
def getLightOpacity(world: World, x: Int, y: Int, z: Int) = 255
|
||||
|
||||
@ -40,6 +43,8 @@ trait Delegate {
|
||||
|
||||
def hasTileEntity = false
|
||||
|
||||
def icon(side: ForgeDirection): Option[Icon] = None
|
||||
|
||||
def isProvidingStrongPower(world: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection) = 0
|
||||
|
||||
def isProvidingWeakPower(world: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection) = 0
|
||||
@ -50,7 +55,7 @@ trait Delegate {
|
||||
|
||||
def onBlockPlacedBy(world: World, x: Int, y: Int, z: Int, player: EntityLivingBase, item: ItemStack) {}
|
||||
|
||||
def onBlockPreDestroy(world: World, x: Int, y: Int, z: Int, metadata: Int) {}
|
||||
def onBlockPreDestroy(world: World, x: Int, y: Int, z: Int) {}
|
||||
|
||||
def onBlockRemovedBy(world: World, x: Int, y: Int, z: Int, player: EntityPlayer) = true
|
||||
|
||||
|
@ -101,23 +101,34 @@ class Delegator[Child <: Delegate](id: Int) extends Block(id, Material.iron) {
|
||||
|
||||
override def breakBlock(world: World, x: Int, y: Int, z: Int, blockId: Int, metadata: Int) = {
|
||||
subBlock(metadata) match {
|
||||
case None => // Invalid but avoid match error.
|
||||
case Some(subBlock) => {
|
||||
world.getBlockTileEntity(x, y, z) match {
|
||||
case node: Node => node.network.foreach(_.remove(node))
|
||||
case _ => // Nothing special to do.
|
||||
}
|
||||
subBlock.breakBlock(world, x, y, z, blockId, metadata)
|
||||
subBlock.breakBlock(world, x, y, z, blockId)
|
||||
}
|
||||
case _ => // Invalid but avoid match error.
|
||||
}
|
||||
super.breakBlock(world, x, y, z, blockId, metadata)
|
||||
}
|
||||
|
||||
override def getRenderColor(metadata: Int) =
|
||||
subBlock(metadata) match {
|
||||
case Some(subBlock) => subBlock.getRenderColor
|
||||
case _ => super.getRenderColor(metadata)
|
||||
}
|
||||
|
||||
override def colorMultiplier(world: IBlockAccess, x: Int, y: Int, z: Int) =
|
||||
subBlock(world, x, y, z) match {
|
||||
case Some(subBlock) => subBlock.colorMultiplier(world, x, y, z)
|
||||
case _ => super.colorMultiplier(world, x, y, z)
|
||||
}
|
||||
|
||||
override def getDamageValue(world: World, x: Int, y: Int, z: Int) = world.getBlockMetadata(x, y, z)
|
||||
|
||||
override def canConnectRedstone(world: IBlockAccess, x: Int, y: Int, z: Int, side: Int) =
|
||||
subBlock(world, x, y, z) match {
|
||||
case None => false
|
||||
case Some(subBlock) => subBlock.canConnectRedstone(
|
||||
world, x, y, z, toLocal(world, x, y, z, side match {
|
||||
case -1 => ForgeDirection.UP
|
||||
@ -126,53 +137,54 @@ class Delegator[Child <: Delegate](id: Int) extends Block(id, Material.iron) {
|
||||
case 2 => ForgeDirection.SOUTH
|
||||
case 3 => ForgeDirection.WEST
|
||||
}))
|
||||
case _ => false
|
||||
}
|
||||
|
||||
override def canProvidePower = true
|
||||
|
||||
override def createTileEntity(world: World, metadata: Int): TileEntity =
|
||||
subBlock(metadata) match {
|
||||
case None => null
|
||||
case Some(subBlock) => subBlock.createTileEntity(world, metadata).orNull
|
||||
case Some(subBlock) => subBlock.createTileEntity(world).orNull
|
||||
case _ => null
|
||||
}
|
||||
|
||||
override def getCollisionBoundingBoxFromPool(world: World, x: Int, y: Int, z: Int) =
|
||||
subBlock(world, x, y, z) match {
|
||||
case None => super.getCollisionBoundingBoxFromPool(world, x, y, z)
|
||||
// TODO Rotate to world space if we have a Rotatable?
|
||||
case Some(subBlock) => subBlock.getCollisionBoundingBoxFromPool(world, x, y, z)
|
||||
case _ => super.getCollisionBoundingBoxFromPool(world, x, y, z)
|
||||
}
|
||||
|
||||
override def getBlockTexture(world: IBlockAccess, x: Int, y: Int, z: Int, side: Int) =
|
||||
subBlock(world, x, y, z) match {
|
||||
case None => super.getBlockTexture(world, x, y, z, side)
|
||||
case Some(subBlock) =>
|
||||
val orientation = ForgeDirection.getOrientation(side)
|
||||
subBlock.getBlockTextureFromSide(world, x, y, z, orientation, toLocal(world, x, y, z, orientation)) match {
|
||||
case None => super.getBlockTexture(world, x, y, z, side)
|
||||
case Some(icon) => icon
|
||||
case _ => super.getBlockTexture(world, x, y, z, side)
|
||||
}
|
||||
case _ => super.getBlockTexture(world, x, y, z, side)
|
||||
}
|
||||
|
||||
override def getLightValue(world: IBlockAccess, x: Int, y: Int, z: Int) =
|
||||
subBlock(world, x, y, z) match {
|
||||
case None => 0
|
||||
case Some(subBlock) => subBlock.getLightValue(world, x, y, z)
|
||||
case _ => 0
|
||||
}
|
||||
|
||||
override def getIcon(side: Int, metadata: Int) =
|
||||
subBlock(metadata) match {
|
||||
case None => super.getIcon(side, metadata)
|
||||
case Some(subBlock) => subBlock.icon(ForgeDirection.getOrientation(side)) match {
|
||||
case None => super.getIcon(side, metadata)
|
||||
case Some(icon) => icon
|
||||
case _ => super.getIcon(side, metadata)
|
||||
}
|
||||
case _ => super.getIcon(side, metadata)
|
||||
}
|
||||
|
||||
override def getLightOpacity(world: World, x: Int, y: Int, z: Int) =
|
||||
subBlock(world, x, y, z) match {
|
||||
case None => 255
|
||||
case Some(subBlock) => subBlock.getLightOpacity(world, x, y, z)
|
||||
case _ => 255
|
||||
}
|
||||
|
||||
override def getSubBlocks(itemId: Int, creativeTab: CreativeTabs, list: util.List[_]) = {
|
||||
@ -186,33 +198,33 @@ class Delegator[Child <: Delegate](id: Int) extends Block(id, Material.iron) {
|
||||
|
||||
def getUnlocalizedName(metadata: Int) =
|
||||
subBlock(metadata) match {
|
||||
case None => "oc.block"
|
||||
case Some(subBlock) => subBlock.unlocalizedName
|
||||
case _ => "oc.block"
|
||||
}
|
||||
|
||||
override def getValidRotations(world: World, x: Int, y: Int, z: Int) =
|
||||
subBlock(world, x, y, z) match {
|
||||
case None => super.getValidRotations(world, x, y, z)
|
||||
case Some(subBlock) => subBlock.getValidRotations(world, x, y, z)
|
||||
case _ => super.getValidRotations(world, x, y, z)
|
||||
}
|
||||
|
||||
override def hasTileEntity(metadata: Int) = subBlock(metadata) match {
|
||||
case None => false
|
||||
case Some(subBlock) => subBlock.hasTileEntity
|
||||
case _ => false
|
||||
}
|
||||
|
||||
override def isProvidingStrongPower(world: IBlockAccess, x: Int, y: Int, z: Int, side: Int) =
|
||||
subBlock(world, x, y, z) match {
|
||||
case None => 0
|
||||
case Some(subBlock) => subBlock.isProvidingStrongPower(
|
||||
world, x, y, z, toLocal(world, x, y, z, ForgeDirection.getOrientation(side).getOpposite))
|
||||
case _ => 0
|
||||
}
|
||||
|
||||
override def isProvidingWeakPower(world: IBlockAccess, x: Int, y: Int, z: Int, side: Int) =
|
||||
subBlock(world, x, y, z) match {
|
||||
case None => 0
|
||||
case Some(subBlock) => subBlock.isProvidingWeakPower(
|
||||
world, x, y, z, toLocal(world, x, y, z, ForgeDirection.getOrientation(side).getOpposite))
|
||||
case _ => 0
|
||||
}
|
||||
|
||||
override def onBlockActivated(world: World, x: Int, y: Int, z: Int, player: EntityPlayer, side: Int, hitX: Float, hitY: Float, hitZ: Float): Boolean = {
|
||||
@ -269,15 +281,14 @@ class Delegator[Child <: Delegate](id: Int) extends Block(id, Material.iron) {
|
||||
|
||||
// No rotating tool in hand or can't rotate: activate the block.
|
||||
subBlock(world, x, y, z) match {
|
||||
case None => false
|
||||
case Some(subBlock) => subBlock.onBlockActivated(
|
||||
world, x, y, z, player, ForgeDirection.getOrientation(side), hitX, hitY, hitZ)
|
||||
case _ => false
|
||||
}
|
||||
}
|
||||
|
||||
override def onBlockAdded(world: World, x: Int, y: Int, z: Int) =
|
||||
subBlock(world, x, y, z) match {
|
||||
case None => // Invalid but avoid match error.
|
||||
case Some(subBlock) => {
|
||||
world.getBlockTileEntity(x, y, z) match {
|
||||
case _: Node => Network.joinOrCreateNetwork(world, x, y, z)
|
||||
@ -285,24 +296,25 @@ class Delegator[Child <: Delegate](id: Int) extends Block(id, Material.iron) {
|
||||
}
|
||||
subBlock.onBlockAdded(world, x, y, z)
|
||||
}
|
||||
case _ => // Invalid but avoid match error.
|
||||
}
|
||||
|
||||
override def onBlockPlacedBy(world: World, x: Int, y: Int, z: Int, player: EntityLivingBase, item: ItemStack) =
|
||||
subBlock(world, x, y, z) match {
|
||||
case None => // Invalid but avoid match error.
|
||||
case Some(subBlock) => subBlock.onBlockPlacedBy(world, x, y, z, player, item)
|
||||
case _ => // Invalid but avoid match error.
|
||||
}
|
||||
|
||||
override def onBlockPreDestroy(world: World, x: Int, y: Int, z: Int, metadata: Int) =
|
||||
subBlock(world, x, y, z) match {
|
||||
case None => // Invalid but avoid match error.
|
||||
case Some(subBlock) => subBlock.onBlockPreDestroy(world, x, y, z, metadata)
|
||||
case Some(subBlock) => subBlock.onBlockPreDestroy(world, x, y, z)
|
||||
case _ => // Invalid but avoid match error.
|
||||
}
|
||||
|
||||
override def onNeighborBlockChange(world: World, x: Int, y: Int, z: Int, blockId: Int) =
|
||||
subBlock(world, x, y, z) match {
|
||||
case None => // Invalid but avoid match error.
|
||||
case Some(subBlock) => subBlock.onNeighborBlockChange(world, x, y, z, blockId)
|
||||
case _ => // Invalid but avoid match error.
|
||||
}
|
||||
|
||||
override def registerIcons(iconRegister: IconRegister) = {
|
||||
@ -312,8 +324,8 @@ class Delegator[Child <: Delegate](id: Int) extends Block(id, Material.iron) {
|
||||
|
||||
override def removeBlockByPlayer(world: World, player: EntityPlayer, x: Int, y: Int, z: Int) =
|
||||
(subBlock(world, x, y, z) match {
|
||||
case None => true
|
||||
case Some(subBlock) => subBlock.onBlockRemovedBy(world, x, y, z, player)
|
||||
case _ => true
|
||||
}) && super.removeBlockByPlayer(world, player, x, y, z)
|
||||
|
||||
override def rotateBlock(world: World, x: Int, y: Int, z: Int, axis: ForgeDirection) = {
|
||||
@ -329,14 +341,14 @@ class SimpleDelegator(id: Int) extends Delegator[SimpleDelegate](id)
|
||||
class SpecialDelegator(id: Int) extends Delegator[SpecialDelegate](id) {
|
||||
override def isBlockNormalCube(world: World, x: Int, y: Int, z: Int) =
|
||||
subBlock(world.getBlockMetadata(x, y, z)) match {
|
||||
case None => false
|
||||
case Some(subBlock) => subBlock.isBlockNormalCube(world, x, y, z)
|
||||
case _ => false
|
||||
}
|
||||
|
||||
override def isBlockSolid(world: IBlockAccess, x: Int, y: Int, z: Int, side: Int) =
|
||||
subBlock(world.getBlockMetadata(x, y, z)) match {
|
||||
case None => true
|
||||
case Some(subBlock) => subBlock.isBlockSolid(world, x, y, z, ForgeDirection.getOrientation(side))
|
||||
case _ => true
|
||||
}
|
||||
|
||||
override def isOpaqueCube = false
|
||||
@ -345,7 +357,7 @@ class SpecialDelegator(id: Int) extends Delegator[SpecialDelegate](id) {
|
||||
|
||||
override def shouldSideBeRendered(world: IBlockAccess, x: Int, y: Int, z: Int, side: Int) =
|
||||
subBlock(world.getBlockMetadata(x, y, z)) match {
|
||||
case None => super.shouldSideBeRendered(world, x, y, z, side)
|
||||
case Some(subBlock) => subBlock.shouldSideBeRendered(world, x, y, z, ForgeDirection.getOrientation(side))
|
||||
case _ => super.shouldSideBeRendered(world, x, y, z, side)
|
||||
}
|
||||
}
|
@ -34,16 +34,15 @@ class DiskDrive(val parent: SimpleDelegator) extends SimpleDelegate {
|
||||
|
||||
override def hasTileEntity = true
|
||||
|
||||
override def createTileEntity(world: World, metadata: Int) = Some(new tileentity.DiskDrive)
|
||||
override def createTileEntity(world: World) = Some(new tileentity.DiskDrive)
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
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) = {
|
||||
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,
|
||||
|
@ -11,5 +11,5 @@ class Keyboard(val parent: SpecialDelegator) extends SpecialDelegate {
|
||||
|
||||
override def hasTileEntity = true
|
||||
|
||||
override def createTileEntity(world: World, metadata: Int) = Some(new tileentity.Keyboard)
|
||||
override def createTileEntity(world: World) = Some(new tileentity.Keyboard)
|
||||
}
|
@ -37,6 +37,6 @@ class PowerDistributor(val parent: SimpleDelegator) extends SimpleDelegate {
|
||||
|
||||
override def hasTileEntity = true
|
||||
|
||||
override def createTileEntity(world: World, metadata: Int) = Some(new tileentity.PowerDistributor)
|
||||
override def createTileEntity(world: World) = Some(new tileentity.PowerDistributor)
|
||||
}
|
||||
|
||||
|
@ -12,9 +12,8 @@ class PowerSupply(val parent: SimpleDelegator) extends SimpleDelegate {
|
||||
GameRegistry.registerTileEntity(classOf[tileentity.PowerSupply], "oc.powersupply")
|
||||
val unlocalizedName = "PowerSupply"
|
||||
|
||||
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) = {
|
||||
world.getBlockTileEntity(x, y, z).asInstanceOf[tileentity.PowerSupply].onUnload()
|
||||
super.breakBlock(world, x, y, z, blockId, metadata)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
@ -39,5 +38,5 @@ class PowerSupply(val parent: SimpleDelegator) extends SimpleDelegate {
|
||||
|
||||
override def hasTileEntity = true
|
||||
|
||||
override def createTileEntity(world: World, metadata: Int) = Some(new tileentity.PowerSupply)
|
||||
override def createTileEntity(world: World) = Some(new tileentity.PowerSupply)
|
||||
}
|
||||
|
@ -12,10 +12,37 @@ import net.minecraft.world.World
|
||||
import net.minecraftforge.common.ForgeDirection
|
||||
import sun.plugin.dom.exception.InvalidStateException
|
||||
|
||||
class Screen(val parent: SimpleDelegator) extends SimpleDelegate {
|
||||
GameRegistry.registerTileEntity(classOf[tileentity.Screen], "oc.screen")
|
||||
class ScreenTier1(parent: SimpleDelegator) extends Screen(parent) {
|
||||
val unlocalizedName = "ScreenBasic"
|
||||
|
||||
val unlocalizedName = "Screen"
|
||||
GameRegistry.registerTileEntity(classOf[tileentity.ScreenTier1], "oc.screen0")
|
||||
|
||||
override def getRenderColor = 0x7F7F7F
|
||||
|
||||
override def createTileEntity(world: World) = Some(new tileentity.ScreenTier1)
|
||||
}
|
||||
|
||||
class ScreenTier2(parent: SimpleDelegator) extends Screen(parent) {
|
||||
val unlocalizedName = "ScreenAdvanced"
|
||||
|
||||
GameRegistry.registerTileEntity(classOf[tileentity.ScreenTier2], "oc.screen1")
|
||||
|
||||
override def getRenderColor = 0xFFFF66
|
||||
|
||||
override def createTileEntity(world: World) = Some(new tileentity.ScreenTier2)
|
||||
}
|
||||
|
||||
class ScreenTier3(parent: SimpleDelegator) extends Screen(parent) {
|
||||
val unlocalizedName = "ScreenProfessional"
|
||||
|
||||
GameRegistry.registerTileEntity(classOf[tileentity.ScreenTier3], "oc.screen2")
|
||||
|
||||
override def getRenderColor = 0x66FFFF
|
||||
|
||||
override def createTileEntity(world: World) = Some(new tileentity.ScreenTier3)
|
||||
}
|
||||
|
||||
abstract class Screen(val parent: SimpleDelegator) extends SimpleDelegate {
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
// Rendering stuff
|
||||
@ -278,8 +305,6 @@ class Screen(val parent: SimpleDelegator) extends SimpleDelegate {
|
||||
|
||||
override def hasTileEntity = true
|
||||
|
||||
override def createTileEntity(world: World, metadata: Int) = Some(new tileentity.Screen)
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
// Interaction
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
@ -4,11 +4,10 @@ import li.cil.oc.api.Persistable
|
||||
import li.cil.oc.api.network.{Component, Message, Visibility}
|
||||
import li.cil.oc.util.TextBuffer
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
import li.cil.oc.common.component
|
||||
|
||||
class Screen(val owner: Screen.Environment) extends Persistable {
|
||||
val supportedResolutions = List((40, 24), (80, 24))
|
||||
|
||||
private val buffer = new TextBuffer(80, 24)
|
||||
class Screen(val owner: Screen.Environment, val resolutions: List[(Int, Int)]) extends Persistable {
|
||||
private val buffer = new TextBuffer(resolutions.head._1, resolutions.head._2)
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
@ -19,7 +18,7 @@ class Screen(val owner: Screen.Environment) extends Persistable {
|
||||
def resolution = buffer.size
|
||||
|
||||
def resolution_=(value: (Int, Int)) =
|
||||
if (supportedResolutions.contains(value) && (buffer.size = value)) {
|
||||
if (resolutions.contains(value) && (buffer.size = value)) {
|
||||
val (w, h) = value
|
||||
owner.onScreenResolutionChange(w, h)
|
||||
true
|
||||
@ -60,30 +59,32 @@ class Screen(val owner: Screen.Environment) extends Persistable {
|
||||
object Screen {
|
||||
|
||||
trait Environment extends Component {
|
||||
final val screen = new Screen(this)
|
||||
final val instance = new component.Screen(this, resolutions)
|
||||
|
||||
override val name = "screen"
|
||||
|
||||
override val visibility = Visibility.Network
|
||||
|
||||
protected def resolutions: List[(Int, Int)]
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override def receive(message: Message): Option[Array[Any]] = super.receive(message).orElse {
|
||||
message.data match {
|
||||
case Array(w: Int, h: Int) if message.name == "screen.resolution=" =>
|
||||
result(screen.resolution = (w, h))
|
||||
result(instance.resolution = (w, h))
|
||||
case Array() if message.name == "screen.resolution" => {
|
||||
val (w, h) = screen.resolution
|
||||
val (w, h) = instance.resolution
|
||||
result(w, h)
|
||||
}
|
||||
case Array() if message.name == "screen.resolutions" =>
|
||||
result(screen.supportedResolutions: _*)
|
||||
result(instance.resolutions: _*)
|
||||
case Array(x: Int, y: Int, value: String) if message.name == "screen.set" =>
|
||||
screen.set(x, y, value); None
|
||||
instance.set(x, y, value); None
|
||||
case Array(x: Int, y: Int, w: Int, h: Int, value: Char) if message.name == "screen.fill" =>
|
||||
screen.fill(x, y, w, h, value); None
|
||||
instance.fill(x, y, w, h, value); None
|
||||
case Array(x: Int, y: Int, w: Int, h: Int, tx: Int, ty: Int) if message.name == "screen.copy" =>
|
||||
screen.copy(x, y, w, h, tx, ty); None
|
||||
instance.copy(x, y, w, h, tx, ty); None
|
||||
case _ => None
|
||||
}
|
||||
}
|
||||
@ -93,14 +94,14 @@ object Screen {
|
||||
override abstract def readFromNBT(nbt: NBTTagCompound) = {
|
||||
super.readFromNBT(nbt)
|
||||
|
||||
screen.readFromNBT(nbt.getCompoundTag("screen"))
|
||||
instance.readFromNBT(nbt.getCompoundTag("screen"))
|
||||
}
|
||||
|
||||
override abstract def writeToNBT(nbt: NBTTagCompound) = {
|
||||
super.writeToNBT(nbt)
|
||||
|
||||
val screenNbt = new NBTTagCompound
|
||||
screen.writeToNBT(screenNbt)
|
||||
instance.writeToNBT(screenNbt)
|
||||
nbt.setCompoundTag("screen", screenNbt)
|
||||
}
|
||||
|
||||
|
@ -3,12 +3,14 @@ package li.cil.oc.common.item
|
||||
import li.cil.oc.Config
|
||||
import net.minecraft.client.renderer.texture.IconRegister
|
||||
|
||||
class GraphicsCard(val parent: Delegator) extends Delegate {
|
||||
val unlocalizedName = "GraphicsCard"
|
||||
class GraphicsCard(val parent: Delegator, val tier: Int) extends Delegate {
|
||||
val unlocalizedName = "GraphicsCard" + Array("Basic", "Advanced", "Professional").apply(tier)
|
||||
|
||||
val resolutions = Config.screenResolutionsByTier(tier)
|
||||
|
||||
override def registerIcons(iconRegister: IconRegister) {
|
||||
super.registerIcons(iconRegister)
|
||||
|
||||
icon = iconRegister.registerIcon(Config.resourceDomain + ":gpu")
|
||||
icon = iconRegister.registerIcon(Config.resourceDomain + ":gpu" + tier)
|
||||
}
|
||||
}
|
@ -12,7 +12,19 @@ import net.minecraft.util.AxisAlignedBB
|
||||
import net.minecraftforge.common.ForgeDirection
|
||||
import scala.collection.mutable
|
||||
|
||||
class Screen extends Rotatable with component.Screen.Environment with Receiver {
|
||||
class ScreenTier1 extends Screen {
|
||||
protected def resolutions = Config.screenResolutionsByTier(0)
|
||||
}
|
||||
|
||||
class ScreenTier2 extends Screen {
|
||||
protected def resolutions = Config.screenResolutionsByTier(1)
|
||||
}
|
||||
|
||||
class ScreenTier3 extends Screen {
|
||||
protected def resolutions = Config.screenResolutionsByTier(2)
|
||||
}
|
||||
|
||||
abstract class Screen extends Rotatable with component.Screen.Environment with Receiver {
|
||||
var guiScreen: Option[gui.Screen] = None
|
||||
|
||||
/**
|
||||
@ -29,6 +41,13 @@ class Screen extends Rotatable with component.Screen.Environment with Receiver {
|
||||
*/
|
||||
private var shouldCheckForMultiBlock = true
|
||||
|
||||
private val ordering = new Ordering[Screen] {
|
||||
def compare(a: Screen, b: Screen) =
|
||||
if (a.xCoord != b.xCoord) a.xCoord - b.xCoord
|
||||
else if (a.yCoord != b.yCoord) a.yCoord - b.yCoord
|
||||
else a.zCoord - b.zCoord
|
||||
}
|
||||
|
||||
var width, height = 1
|
||||
|
||||
var origin = this
|
||||
@ -90,7 +109,7 @@ class Screen extends Rotatable with component.Screen.Environment with Receiver {
|
||||
// any multi-block specific state information.
|
||||
// We use a very primitive hash for the coordinates, which should be
|
||||
// good enough for... "normal" screen sizes.
|
||||
val pending = mutable.SortedSet(this)(Ordering[Int].on[Screen](s => (((23 + s.xCoord * 31) + s.yCoord) * 31) + s.zCoord))
|
||||
val pending = mutable.SortedSet(this)(ordering)
|
||||
val queue = mutable.Queue(this)
|
||||
while (queue.nonEmpty) {
|
||||
val current = queue.dequeue()
|
||||
@ -127,7 +146,7 @@ class Screen extends Rotatable with component.Screen.Environment with Receiver {
|
||||
screen.componentVisibility = Visibility.Network
|
||||
else {
|
||||
screen.componentVisibility = Visibility.None
|
||||
val s = screen.screen
|
||||
val s = screen.instance
|
||||
val (w, h) = s.resolution
|
||||
s.fill(0, 0, w, h, ' ')
|
||||
}
|
||||
@ -148,7 +167,7 @@ class Screen extends Rotatable with component.Screen.Environment with Receiver {
|
||||
def tryMergeTowards(dx: Int, dy: Int) = {
|
||||
val (nx, ny, nz) = unproject(x + dx, y + dy, z)
|
||||
worldObj.getBlockTileEntity(nx, ny, nz) match {
|
||||
case s: Screen if s.pitch == pitch && s.yaw == yaw && !screens.contains(s) =>
|
||||
case s: Screen if s.resolutions == resolutions && s.pitch == pitch && s.yaw == yaw && !screens.contains(s) =>
|
||||
val (sx, sy, _) = project(s.origin)
|
||||
val canMergeAlongX = sy == y && s.height == height && s.width + width <= Config.maxScreenWidth
|
||||
val canMergeAlongY = sx == x && s.width == width && s.height + height <= Config.maxScreenHeight
|
||||
|
@ -2,7 +2,6 @@ package li.cil.oc.server
|
||||
|
||||
import cpw.mods.fml.common.network.Player
|
||||
import li.cil.oc.api.network.Node
|
||||
import li.cil.oc.common.PacketBuilder
|
||||
import li.cil.oc.common.PacketType
|
||||
import li.cil.oc.common.tileentity
|
||||
import li.cil.oc.common.{PacketHandler => CommonPacketHandler}
|
||||
@ -28,64 +27,59 @@ class PacketHandler extends CommonPacketHandler {
|
||||
|
||||
def onScreenBufferRequest(p: PacketParser) =
|
||||
p.readTileEntity[tileentity.Screen]() match {
|
||||
case None => // Invalid packet.
|
||||
case Some(t) => {
|
||||
val pb = new PacketBuilder(PacketType.ScreenBufferResponse)
|
||||
|
||||
pb.writeTileEntity(t)
|
||||
pb.writeUTF(t.screen.text)
|
||||
|
||||
pb.sendToPlayer(p.player)
|
||||
}
|
||||
case Some(t) =>
|
||||
val (w, h) = t.instance.resolution
|
||||
PacketSender.sendScreenBufferState(t, w, h, t.instance.text, Option(p.player))
|
||||
case _ => // Invalid packet.
|
||||
}
|
||||
|
||||
def onComputerStateRequest(p: PacketParser) =
|
||||
p.readTileEntity[tileentity.Computer]() match {
|
||||
case None => // Invalid packet.
|
||||
case Some(t) => PacketSender.sendComputerState(t, t.isOn)
|
||||
case Some(t) => PacketSender.sendComputerState(t, t.isOn, Option(p.player))
|
||||
case _ => // Invalid packet.
|
||||
}
|
||||
|
||||
def onRotatableStateRequest(p: PacketParser) =
|
||||
p.readTileEntity[tileentity.Rotatable]() match {
|
||||
case None => // Invalid packet.
|
||||
case Some(t) => PacketSender.sendRotatableState(t)
|
||||
case Some(t) => PacketSender.sendRotatableState(t, Option(p.player))
|
||||
case _ => // Invalid packet.
|
||||
}
|
||||
|
||||
def onRedstoneStateRequest(p: PacketParser) =
|
||||
p.readTileEntity[TileEntity with Redstone]() match {
|
||||
case None => // Invalid packet.
|
||||
case Some(t) => PacketSender.sendRedstoneState(t)
|
||||
case Some(t) => PacketSender.sendRedstoneState(t, Option(p.player))
|
||||
case _ => // Invalid packet.
|
||||
}
|
||||
|
||||
def onKeyDown(p: PacketParser) =
|
||||
p.readTileEntity[Node]() match {
|
||||
case None => // Invalid packet.
|
||||
case Some(s: tileentity.Screen) =>
|
||||
val char = p.readChar()
|
||||
val code = p.readInt()
|
||||
val network = s.origin.network
|
||||
s.screens.foreach(n => network.foreach(_.sendToNeighbors(n, "keyboard.keyDown", p.player, char, code)))
|
||||
case Some(n) => n.network.foreach(_.sendToNeighbors(n, "keyboard.keyDown", p.player, p.readChar(), p.readInt()))
|
||||
case _ => // Invalid packet.
|
||||
}
|
||||
|
||||
def onKeyUp(p: PacketParser) =
|
||||
p.readTileEntity[Node]() match {
|
||||
case None => // Invalid packet.
|
||||
case Some(s: tileentity.Screen) =>
|
||||
val char = p.readChar()
|
||||
val code = p.readInt()
|
||||
val network = s.origin.network
|
||||
s.screens.foreach(n => network.foreach(_.sendToNeighbors(n, "keyboard.keyUp", p.player, char, code)))
|
||||
case Some(n) => n.network.foreach(_.sendToNeighbors(n, "keyboard.keyUp", p.player, p.readChar(), p.readInt()))
|
||||
case _ => // Invalid packet.
|
||||
}
|
||||
|
||||
def onClipboard(p: PacketParser) =
|
||||
p.readTileEntity[Node]() match {
|
||||
case None => // Invalid packet.
|
||||
case Some(s: tileentity.Screen) =>
|
||||
val value = p.readUTF()
|
||||
val network = s.origin.network
|
||||
s.screens.foreach(n => network.foreach(_.sendToNeighbors(n, "keyboard.clipboard", p.player, value)))
|
||||
case Some(n) => n.network.foreach(_.sendToNeighbors(n, "keyboard.clipboard", p.player, p.readUTF()))
|
||||
case _ => // Invalid packet.
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package li.cil.oc.server
|
||||
|
||||
import cpw.mods.fml.common.network.Player
|
||||
import li.cil.oc.common.PacketBuilder
|
||||
import li.cil.oc.common.PacketType
|
||||
import li.cil.oc.common.tileentity.Rotatable
|
||||
@ -9,6 +10,20 @@ import net.minecraftforge.common.ForgeDirection
|
||||
|
||||
/** Centralized packet dispatcher for sending updates to the client. */
|
||||
object PacketSender {
|
||||
def sendScreenBufferState(t: TileEntity, w: Int, h: Int, text: String, player: Option[Player] = None) = {
|
||||
val pb = new PacketBuilder(PacketType.ScreenBufferResponse)
|
||||
|
||||
pb.writeTileEntity(t)
|
||||
pb.writeInt(w)
|
||||
pb.writeInt(h)
|
||||
pb.writeUTF(text)
|
||||
|
||||
player match {
|
||||
case Some(p) => pb.sendToPlayer(p)
|
||||
case _ => pb.sendToAllPlayers()
|
||||
}
|
||||
}
|
||||
|
||||
def sendScreenResolutionChange(t: TileEntity, w: Int, h: Int) = {
|
||||
val pb = new PacketBuilder(PacketType.ScreenResolutionChange)
|
||||
|
||||
@ -57,26 +72,32 @@ object PacketSender {
|
||||
pb.sendToAllPlayers()
|
||||
}
|
||||
|
||||
def sendComputerState(t: TileEntity, value: Boolean) = {
|
||||
def sendComputerState(t: TileEntity, value: Boolean, player: Option[Player] = None) = {
|
||||
val pb = new PacketBuilder(PacketType.ComputerStateResponse)
|
||||
|
||||
pb.writeTileEntity(t)
|
||||
pb.writeBoolean(value)
|
||||
|
||||
pb.sendToAllPlayers()
|
||||
player match {
|
||||
case Some(p) => pb.sendToPlayer(p)
|
||||
case _ => pb.sendToAllPlayers()
|
||||
}
|
||||
}
|
||||
|
||||
def sendRotatableState(t: Rotatable) = {
|
||||
def sendRotatableState(t: Rotatable, player: Option[Player] = None) = {
|
||||
val pb = new PacketBuilder(PacketType.RotatableStateResponse)
|
||||
|
||||
pb.writeTileEntity(t)
|
||||
pb.writeDirection(t.pitch)
|
||||
pb.writeDirection(t.yaw)
|
||||
|
||||
pb.sendToAllPlayers()
|
||||
player match {
|
||||
case Some(p) => pb.sendToPlayer(p)
|
||||
case _ => pb.sendToAllPlayers()
|
||||
}
|
||||
}
|
||||
|
||||
def sendRedstoneState(t: TileEntity with Redstone) = {
|
||||
def sendRedstoneState(t: TileEntity with Redstone, player: Option[Player] = None) = {
|
||||
val pb = new PacketBuilder(PacketType.RedstoneStateResponse)
|
||||
|
||||
pb.writeTileEntity(t)
|
||||
@ -85,6 +106,9 @@ object PacketSender {
|
||||
pb.writeByte(t.output(d))
|
||||
}
|
||||
|
||||
pb.sendToAllPlayers()
|
||||
player match {
|
||||
case Some(p) => pb.sendToPlayer(p)
|
||||
case _ => pb.sendToAllPlayers()
|
||||
}
|
||||
}
|
||||
}
|
@ -560,6 +560,20 @@ class Computer(val owner: Computer.Environment) extends Persistable with Runnabl
|
||||
def parseArguments(lua: LuaState, start: Int) =
|
||||
for (index <- start to lua.getTop) yield parseArgument(lua, index)
|
||||
|
||||
def pushList(value: Iterator[(Any, Int)]) {
|
||||
lua.newTable()
|
||||
var count = 0
|
||||
value.foreach {
|
||||
case (entry, index) =>
|
||||
pushResult(lua, entry)
|
||||
lua.rawSet(-2, index + 1)
|
||||
count = count + 1
|
||||
}
|
||||
lua.pushString("n")
|
||||
lua.pushInteger(count)
|
||||
lua.rawSet(-3)
|
||||
}
|
||||
|
||||
def pushResult(lua: LuaState, value: Any): Unit = value match {
|
||||
case value: Boolean => lua.pushBoolean(value)
|
||||
case value: Byte => lua.pushNumber(value)
|
||||
@ -570,15 +584,10 @@ class Computer(val owner: Computer.Environment) extends Persistable with Runnabl
|
||||
case value: Double => lua.pushNumber(value)
|
||||
case value: String => lua.pushString(value)
|
||||
case value: Array[Byte] => lua.pushByteArray(value)
|
||||
case value: Array[_] => {
|
||||
lua.newTable()
|
||||
value.zipWithIndex.foreach {
|
||||
case (entry, index) =>
|
||||
pushResult(lua, entry)
|
||||
lua.rawSet(-2, index)
|
||||
}
|
||||
}
|
||||
// TODO maps, tuples/seqs?
|
||||
case value: Array[_] => pushList(value.zipWithIndex.iterator)
|
||||
case value: Product => pushList(value.productIterator.zipWithIndex)
|
||||
case value: Seq[_] => pushList(value.zipWithIndex.iterator)
|
||||
// TODO maps?
|
||||
// TODO I fear they are, but check if the following are really necessary for Java interop.
|
||||
case value: java.lang.Byte => lua.pushNumber(value.byteValue)
|
||||
case value: java.lang.Short => lua.pushNumber(value.shortValue)
|
||||
|
@ -4,9 +4,7 @@ import li.cil.oc.api.network.{Component, Visibility, Message}
|
||||
import li.cil.oc.common.component
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
|
||||
class GraphicsCard extends Component {
|
||||
val supportedResolutions = List(List(40, 24), List(80, 24))
|
||||
|
||||
class GraphicsCard(val resolutions: List[(Int, Int)]) extends Component {
|
||||
private var screen: Option[String] = None
|
||||
|
||||
override val name = "gpu"
|
||||
@ -31,14 +29,14 @@ class GraphicsCard extends Component {
|
||||
})
|
||||
case Array() if message.name == "system.disconnect" && message.source.address == screen => screen = None; None
|
||||
case Array(w: Double, h: Double) if message.name == "gpu.resolution=" =>
|
||||
if (supportedResolutions.contains((w.toInt, h.toInt)))
|
||||
if (resolutions.contains((w.toInt, h.toInt)))
|
||||
trySend("screen.resolution=", w.toInt, h.toInt)
|
||||
else
|
||||
result(Unit, "unsupported resolution")
|
||||
case Array() if message.name == "gpu.resolution" => trySend("screen.resolution")
|
||||
case Array() if message.name == "gpu.resolutions" => trySend("screen.resolutions") match {
|
||||
case Some(Array(resolutions@_*)) =>
|
||||
result(supportedResolutions.intersect(resolutions): _*)
|
||||
result(resolutions.intersect(resolutions): _*)
|
||||
case _ => None
|
||||
}
|
||||
case Array(x: Double, y: Double, value: Array[Byte]) if message.name == "gpu.set" =>
|
||||
|
@ -2,6 +2,7 @@ package li.cil.oc.server.driver
|
||||
|
||||
import li.cil.oc.api.driver
|
||||
import li.cil.oc.api.driver.Slot
|
||||
import li.cil.oc.common
|
||||
import li.cil.oc.server.component
|
||||
import li.cil.oc.{Config, Items}
|
||||
import net.minecraft.item.ItemStack
|
||||
@ -9,9 +10,14 @@ import net.minecraft.item.ItemStack
|
||||
object GraphicsCard extends driver.Item {
|
||||
override def api = Option(getClass.getResourceAsStream(Config.driverPath + "gpu.lua"))
|
||||
|
||||
override def worksWith(item: ItemStack) = WorksWith(Items.gpu)(item)
|
||||
override def worksWith(item: ItemStack) = WorksWith(Items.gpu1, Items.gpu2, Items.gpu3)(item)
|
||||
|
||||
override def slot(item: ItemStack) = Slot.Card
|
||||
|
||||
override def node(item: ItemStack) = Some(new component.GraphicsCard())
|
||||
override def node(item: ItemStack) =
|
||||
Items.multi.subItem(item) match {
|
||||
case Some(gpu: common.item.GraphicsCard) =>
|
||||
Some(new component.GraphicsCard(gpu.resolutions))
|
||||
case _ => throw new IllegalArgumentException()
|
||||
}
|
||||
}
|