remote terminal basic stuff. can be bound and used to control servers. servers simply have a neighbor visible built-in screen and keyboard for which the gui can be opened using the terminal item once bound. still missing a couple of checks.

This commit is contained in:
Florian Nücke 2014-01-17 17:34:19 +01:00
parent 125cedeadc
commit 0f067e37c4
23 changed files with 541 additions and 188 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 306 B

View File

@ -0,0 +1,6 @@
{
"animation": {
"frametime": 10,
"frames": [ 0, 1 ]
}
}

View File

@ -1,10 +1,11 @@
package li.cil.oc.client package li.cil.oc.client
import li.cil.oc.Items
import li.cil.oc.common.inventory.ServerInventory import li.cil.oc.common.inventory.ServerInventory
import li.cil.oc.common.{GuiHandler => CommonGuiHandler, item, tileentity, GuiType} import li.cil.oc.common.{GuiHandler => CommonGuiHandler, item, tileentity, GuiType}
import li.cil.oc.{Settings, Items}
import net.minecraft.entity.player.EntityPlayer import net.minecraft.entity.player.EntityPlayer
import net.minecraft.world.World import net.minecraft.world.World
import scala.collection.convert.WrapAsScala._
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) =
@ -20,7 +21,7 @@ object GuiHandler extends CommonGuiHandler {
case rack: tileentity.Rack if id == GuiType.Rack.id => case rack: tileentity.Rack if id == GuiType.Rack.id =>
new gui.Rack(player.inventory, rack) new gui.Rack(player.inventory, rack)
case screen: tileentity.Screen if id == GuiType.Screen.id => case screen: tileentity.Screen if id == GuiType.Screen.id =>
new gui.Screen(screen) new gui.Screen(screen.origin.buffer, screen.tier > 0, () => screen.origin.hasPower)
case _ => Items.multi.subItem(player.getCurrentEquippedItem) match { case _ => Items.multi.subItem(player.getCurrentEquippedItem) match {
case Some(server: item.Server) if id == GuiType.Server.id => case Some(server: item.Server) if id == GuiType.Server.id =>
new gui.Server(player.inventory, new ServerInventory { new gui.Server(player.inventory, new ServerInventory {
@ -29,7 +30,27 @@ object GuiHandler extends CommonGuiHandler {
override def isUseableByPlayer(player: EntityPlayer) = player == player override def isUseableByPlayer(player: EntityPlayer) = player == player
}) })
case Some(terminal: item.Terminal) if id == GuiType.Terminal.id => case Some(terminal: item.Terminal) if id == GuiType.Terminal.id =>
null // TODO val stack = player.getCurrentEquippedItem
if (stack.hasTagCompound) {
val address = stack.getTagCompound.getString(Settings.namespace + "server")
if (address != null && !address.isEmpty) {
// Check if bound to server is loaded. TODO optimize this?
world.loadedTileEntityList.flatMap {
case rack: tileentity.Rack => rack.terminals
case _ => Iterable.empty
} find (_.rack.isPresent.exists {
case Some(value) => value == address
case _ => false
}) match {
case Some(term) =>
// TODO check reachability
new gui.Screen(term.buffer, true, () => true)
case _ => null
}
}
else null
}
else null
case _ => null case _ => null
} }
} }

View File

@ -167,44 +167,53 @@ class PacketHandler extends CommonPacketHandler {
case _ => // Invalid packet. case _ => // Invalid packet.
} }
def onScreenColorChange(p: PacketParser) = def onScreenColorChange(p: PacketParser) {
p.readTileEntity[Buffer]() match { val buffer = p.readTileEntity[TileEntity]() match {
case Some(t) => case Some(t: Buffer) => t.buffer
t.buffer.foreground = p.readInt() case Some(t: Rack) => t.terminals(p.readInt()).buffer
t.buffer.background = p.readInt() case _ => return // Invalid packet.
case _ => // Invalid packet.
} }
buffer.foreground = p.readInt()
buffer.background = p.readInt()
}
def onScreenCopy(p: PacketParser) = def onScreenCopy(p: PacketParser) {
p.readTileEntity[Buffer]() match { val buffer = p.readTileEntity[TileEntity]() match {
case Some(t) => case Some(t: Buffer) => t.buffer
val col = p.readInt() case Some(t: Rack) => t.terminals(p.readInt()).buffer
val row = p.readInt() case _ => return // Invalid packet.
val w = p.readInt()
val h = p.readInt()
val tx = p.readInt()
val ty = p.readInt()
t.buffer.copy(col, row, w, h, tx, ty)
case _ => // Invalid packet.
} }
val col = p.readInt()
val row = p.readInt()
val w = p.readInt()
val h = p.readInt()
val tx = p.readInt()
val ty = p.readInt()
buffer.copy(col, row, w, h, tx, ty)
}
def onScreenDepthChange(p: PacketParser) = def onScreenDepthChange(p: PacketParser) {
p.readTileEntity[Buffer]() match { val buffer = p.readTileEntity[TileEntity]() match {
case Some(t) => t.buffer.depth = PackedColor.Depth(p.readInt()) case Some(t: Buffer) => t.buffer
case _ => // Invalid packet. case Some(t: Rack) => t.terminals(p.readInt()).buffer
case _ => return // Invalid packet.
} }
buffer.depth = PackedColor.Depth(p.readInt())
}
def onScreenFill(p: PacketParser) = def onScreenFill(p: PacketParser) {
p.readTileEntity[Buffer]() match { val buffer = p.readTileEntity[TileEntity]() match {
case Some(t) => case Some(t: Buffer) => t.buffer
val col = p.readInt() case Some(t: Rack) => t.terminals(p.readInt()).buffer
val row = p.readInt() case _ => return // Invalid packet.
val w = p.readInt()
val h = p.readInt()
val c = p.readChar()
t.buffer.fill(col, row, w, h, c)
case _ => // Invalid packet.
} }
val col = p.readInt()
val row = p.readInt()
val w = p.readInt()
val h = p.readInt()
val c = p.readChar()
buffer.fill(col, row, w, h, c)
}
def onScreenPowerChange(p: PacketParser) = def onScreenPowerChange(p: PacketParser) =
p.readTileEntity[Screen]() match { p.readTileEntity[Screen]() match {
@ -212,28 +221,37 @@ class PacketHandler extends CommonPacketHandler {
case _ => // Invalid packet. case _ => // Invalid packet.
} }
def onScreenResolutionChange(p: PacketParser) = def onScreenResolutionChange(p: PacketParser) {
p.readTileEntity[Buffer]() match { val buffer = p.readTileEntity[TileEntity]() match {
case Some(t) => case Some(t: Buffer) => t.buffer
val w = p.readInt() case Some(t: Rack) => t.terminals(p.readInt()).buffer
val h = p.readInt() case _ => return // Invalid packet.
t.buffer.resolution = (w, h)
case _ => // Invalid packet.
} }
val w = p.readInt()
val h = p.readInt()
buffer.resolution = (w, h)
}
def onScreenSet(p: PacketParser) = def onScreenSet(p: PacketParser) {
p.readTileEntity[Buffer]() match { val buffer = p.readTileEntity[TileEntity]() match {
case Some(t) => case Some(t: Buffer) => t.buffer
val col = p.readInt() case Some(t: Rack) => t.terminals(p.readInt()).buffer
val row = p.readInt() case _ => return // Invalid packet.
val s = p.readUTF()
t.buffer.set(col, row, s)
case _ => // Invalid packet.
} }
val col = p.readInt()
val row = p.readInt()
val s = p.readUTF()
buffer.set(col, row, s)
}
def onServerPresence(p: PacketParser) = def onServerPresence(p: PacketParser) =
p.readTileEntity[Rack]() match { p.readTileEntity[Rack]() match {
case Some(t) => for (i <- 0 until t.isPresent.length) t.isPresent(i) = p.readBoolean() case Some(t) => for (i <- 0 until t.isPresent.length) {
if (p.readBoolean()) {
t.isPresent(i) = Some(p.readUTF())
}
else t.isPresent(i) = None
}
case _ => // Invalid packet. case _ => // Invalid packet.
} }
} }

View File

@ -2,6 +2,7 @@ package li.cil.oc.client
import li.cil.oc.common.PacketBuilder import li.cil.oc.common.PacketBuilder
import li.cil.oc.common.PacketType import li.cil.oc.common.PacketType
import li.cil.oc.common.component
import li.cil.oc.common.tileentity._ import li.cil.oc.common.tileentity._
import net.minecraftforge.common.ForgeDirection import net.minecraftforge.common.ForgeDirection
@ -15,61 +16,93 @@ object PacketSender {
pb.sendToServer() pb.sendToServer()
} }
def sendKeyDown(t: Buffer, char: Char, code: Int) = def sendKeyDown(b: component.Buffer, char: Char, code: Int) {
if (t.hasKeyboard) { val pb = new PacketBuilder(PacketType.KeyDown)
val pb = new PacketBuilder(PacketType.KeyDown)
pb.writeTileEntity(t) b.owner match {
pb.writeChar(char) case t: Buffer if t.hasKeyboard =>
pb.writeInt(code) pb.writeTileEntity(t)
case t: component.Terminal =>
pb.sendToServer() pb.writeTileEntity(t.rack)
pb.writeInt(t.number)
case _ => return
} }
pb.writeChar(char)
pb.writeInt(code)
def sendKeyUp(t: Buffer, char: Char, code: Int) = pb.sendToServer()
if (t.hasKeyboard) { }
val pb = new PacketBuilder(PacketType.KeyUp)
pb.writeTileEntity(t) def sendKeyUp(b: component.Buffer, char: Char, code: Int) {
pb.writeChar(char) val pb = new PacketBuilder(PacketType.KeyUp)
pb.writeInt(code)
pb.sendToServer() b.owner match {
case t: Buffer if t.hasKeyboard =>
pb.writeTileEntity(t)
case t: component.Terminal =>
pb.writeTileEntity(t.rack)
pb.writeInt(t.number)
case _ => return
} }
pb.writeChar(char)
pb.writeInt(code)
def sendClipboard(t: Buffer, value: String) = pb.sendToServer()
if (value != null && !value.isEmpty && t.hasKeyboard) { }
def sendClipboard(b: component.Buffer, value: String) {
if (value != null && !value.isEmpty) {
val pb = new PacketBuilder(PacketType.Clipboard) val pb = new PacketBuilder(PacketType.Clipboard)
pb.writeTileEntity(t) b.owner match {
case t: Buffer if t.hasKeyboard =>
pb.writeTileEntity(t)
case t: component.Terminal =>
pb.writeTileEntity(t.rack)
pb.writeInt(t.number)
case _ => return
}
pb.writeUTF(value.substring(0, math.min(value.length, 1024))) pb.writeUTF(value.substring(0, math.min(value.length, 1024)))
pb.sendToServer() pb.sendToServer()
} }
}
def sendMouseClick(t: Buffer, x: Int, y: Int, drag: Boolean) = def sendMouseClick(b: component.Buffer, x: Int, y: Int, drag: Boolean) {
if (t.tier > 0) { val pb = new PacketBuilder(PacketType.MouseClickOrDrag)
val pb = new PacketBuilder(PacketType.MouseClickOrDrag)
pb.writeTileEntity(t) b.owner match {
pb.writeInt(x) case t: Buffer if t.tier > 0 =>
pb.writeInt(y) pb.writeTileEntity(t)
pb.writeBoolean(drag) case t: component.Terminal =>
pb.writeTileEntity(t.rack)
pb.sendToServer() pb.writeInt(t.number)
case _ => return
} }
pb.writeInt(x)
pb.writeInt(y)
pb.writeBoolean(drag)
def sendMouseScroll(t: Buffer, x: Int, y: Int, scroll: Int) = pb.sendToServer()
if (t.tier > 0) { }
val pb = new PacketBuilder(PacketType.MouseScroll)
pb.writeTileEntity(t) def sendMouseScroll(b: component.Buffer, x: Int, y: Int, scroll: Int) {
pb.writeInt(x) val pb = new PacketBuilder(PacketType.MouseScroll)
pb.writeInt(y)
pb.writeByte(scroll)
pb.sendToServer() b.owner match {
case t: Buffer if t.tier > 0 =>
pb.writeTileEntity(t)
case t: component.Terminal =>
pb.writeTileEntity(t.rack)
pb.writeInt(t.number)
case _ => return
} }
pb.writeInt(x)
pb.writeInt(y)
pb.writeByte(scroll)
pb.sendToServer()
}
def sendServerPower(t: Rack, number: Int, power: Boolean) { def sendServerPower(t: Rack, number: Int, power: Boolean) {
val pb = new PacketBuilder(PacketType.ComputerPower) val pb = new PacketBuilder(PacketType.ComputerPower)

View File

@ -43,7 +43,7 @@ trait Buffer extends GuiScreen {
super.onGuiClosed() super.onGuiClosed()
buffer.owner.currentGui = None buffer.owner.currentGui = None
for ((code, char) <- pressedKeys) { for ((code, char) <- pressedKeys) {
PacketSender.sendKeyUp(buffer.owner, char, code) PacketSender.sendKeyUp(buffer, char, code)
} }
Keyboard.enableRepeatEvents(false) Keyboard.enableRepeatEvents(false)
} }
@ -75,17 +75,17 @@ trait Buffer extends GuiScreen {
if (Keyboard.getEventKeyState) { if (Keyboard.getEventKeyState) {
val char = Keyboard.getEventCharacter val char = Keyboard.getEventCharacter
if (!pressedKeys.contains(code) || !ignoreRepeat(char, code)) { if (!pressedKeys.contains(code) || !ignoreRepeat(char, code)) {
PacketSender.sendKeyDown(buffer.owner, char, code) PacketSender.sendKeyDown(buffer, char, code)
pressedKeys += code -> char pressedKeys += code -> char
} }
} }
else pressedKeys.remove(code) match { else pressedKeys.remove(code) match {
case Some(char) => PacketSender.sendKeyUp(buffer.owner, char, code) case Some(char) => PacketSender.sendKeyUp(buffer, char, code)
case _ => // Wasn't pressed while viewing the screen. case _ => // Wasn't pressed while viewing the screen.
} }
if (isPasteShortcutPressed && Keyboard.getEventKeyState) { if (isPasteShortcutPressed && Keyboard.getEventKeyState) {
PacketSender.sendClipboard(buffer.owner, GuiScreen.getClipboardString) PacketSender.sendClipboard(buffer, GuiScreen.getClipboardString)
} }
} }
} }
@ -93,7 +93,7 @@ trait Buffer extends GuiScreen {
override protected def mouseClicked(x: Int, y: Int, button: Int) { override protected def mouseClicked(x: Int, y: Int, button: Int) {
super.mouseClicked(x, y, button) super.mouseClicked(x, y, button)
if (button == 2) { if (button == 2) {
PacketSender.sendClipboard(buffer.owner, GuiScreen.getClipboardString) PacketSender.sendClipboard(buffer, GuiScreen.getClipboardString)
} }
} }

View File

@ -3,14 +3,12 @@ package li.cil.oc.client.gui
import li.cil.oc.client.PacketSender import li.cil.oc.client.PacketSender
import li.cil.oc.client.renderer.MonospaceFontRenderer import li.cil.oc.client.renderer.MonospaceFontRenderer
import li.cil.oc.client.renderer.gui.BufferRenderer import li.cil.oc.client.renderer.gui.BufferRenderer
import li.cil.oc.common.tileentity import li.cil.oc.common
import li.cil.oc.util.RenderState import li.cil.oc.util.RenderState
import org.lwjgl.input.Mouse import org.lwjgl.input.Mouse
import org.lwjgl.opengl.GL11 import org.lwjgl.opengl.GL11
class Screen(val screen: tileentity.Screen) extends Buffer { class Screen(val buffer: common.component.Buffer, val hasMouse: Boolean, val hasPower: () => Boolean) extends Buffer {
protected def buffer = screen.origin.buffer
private val bufferMargin = BufferRenderer.margin + BufferRenderer.innerMargin private val bufferMargin = BufferRenderer.margin + BufferRenderer.innerMargin
private var x, y = 0 private var x, y = 0
@ -27,14 +25,14 @@ class Screen(val screen: tileentity.Screen) extends Buffer {
val (bw, bh) = buffer.resolution val (bw, bh) = buffer.resolution
if (bx > 0 && by > 0 && bx <= bw && by <= bh) { if (bx > 0 && by > 0 && bx <= bw && by <= bh) {
val scroll = math.signum(Mouse.getEventDWheel) val scroll = math.signum(Mouse.getEventDWheel)
PacketSender.sendMouseScroll(buffer.owner, bx, by, scroll) PacketSender.sendMouseScroll(buffer, bx, by, scroll)
} }
} }
} }
override protected def mouseClicked(mouseX: Int, mouseY: Int, button: Int) { override protected def mouseClicked(mouseX: Int, mouseY: Int, button: Int) {
super.mouseClicked(mouseX, mouseY, button) super.mouseClicked(mouseX, mouseY, button)
if (screen.tier > 0) { if (hasMouse) {
if (button == 0) { if (button == 0) {
clickOrDrag(mouseX, mouseY) clickOrDrag(mouseX, mouseY)
} }
@ -43,7 +41,7 @@ class Screen(val screen: tileentity.Screen) extends Buffer {
protected override def mouseClickMove(mouseX: Int, mouseY: Int, button: Int, timeSinceLast: Long) { protected override def mouseClickMove(mouseX: Int, mouseY: Int, button: Int, timeSinceLast: Long) {
super.mouseClickMove(mouseX, mouseY, button, timeSinceLast) super.mouseClickMove(mouseX, mouseY, button, timeSinceLast)
if (screen.tier > 0 && timeSinceLast > 10) { if (hasMouse && timeSinceLast > 10) {
if (button == 0) { if (button == 0) {
clickOrDrag(mouseX, mouseY) clickOrDrag(mouseX, mouseY)
} }
@ -64,7 +62,7 @@ class Screen(val screen: tileentity.Screen) extends Buffer {
val (bw, bh) = buffer.resolution val (bw, bh) = buffer.resolution
if (bx > 0 && by > 0 && bx <= bw && by <= bh) { if (bx > 0 && by > 0 && bx <= bw && by <= bh) {
if (bx != mx || by != my) { if (bx != mx || by != my) {
PacketSender.sendMouseClick(buffer.owner, bx, by, mx > 0 && my > 0) PacketSender.sendMouseClick(buffer, bx, by, mx > 0 && my > 0)
mx = bx mx = bx
my = by my = by
} }
@ -79,7 +77,7 @@ class Screen(val screen: tileentity.Screen) extends Buffer {
def drawBuffer() { def drawBuffer() {
GL11.glTranslatef(x, y, 0) GL11.glTranslatef(x, y, 0)
BufferRenderer.drawBackground() BufferRenderer.drawBackground()
if (screen.origin.hasPower) { if (hasPower()) {
GL11.glTranslatef(bufferMargin, bufferMargin, 0) GL11.glTranslatef(bufferMargin, bufferMargin, 0)
RenderState.makeItBlend() RenderState.makeItBlend()
BufferRenderer.drawText() BufferRenderer.drawText()

View File

@ -103,7 +103,7 @@ object BlockRenderer extends ISimpleBlockRenderingHandler {
val front = rack.facing val front = rack.facing
def renderSide(side: ForgeDirection, lx: Double, lz: Double, hx: Double, hz: Double) { def renderSide(side: ForgeDirection, lx: Double, lz: Double, hx: Double, hz: Double) {
if (side == front) { if (side == front) {
for (i <- 0 until 4 if rack.isPresent(i)) { for (i <- 0 until 4 if rack.isPresent(i).isDefined) {
side match { side match {
case ForgeDirection.WEST => case ForgeDirection.WEST =>
renderer.setRenderBounds(lx, v2 - (i + 1) * fs, lz + u1, u2, v2 - i * fs, hz - u1) renderer.setRenderBounds(lx, v2 - (i + 1) * fs, lz + u1, u2, v2 - i * fs, hz - u1)

View File

@ -8,7 +8,7 @@ import li.cil.oc.{api, Settings}
import net.minecraft.nbt.NBTTagCompound import net.minecraft.nbt.NBTTagCompound
import scala.collection.convert.WrapAsScala._ import scala.collection.convert.WrapAsScala._
class Buffer(val owner: tileentity.Buffer) extends api.network.Environment with Persistable { class Buffer(val owner: Buffer.Owner) extends api.network.Environment with Persistable {
val node = api.Network.newNode(this, Visibility.Network). val node = api.Network.newNode(this, Visibility.Network).
withComponent("screen"). withComponent("screen").
withConnector(). withConnector().
@ -140,3 +140,30 @@ class Buffer(val owner: tileentity.Buffer) extends api.network.Environment with
nbt.setNewCompoundTag("buffer", buffer.save) nbt.setNewCompoundTag("buffer", buffer.save)
} }
} }
object Buffer {
import li.cil.oc.client.gui
trait Owner {
protected var _currentGui: Option[gui.Buffer] = None
def currentGui = _currentGui
def currentGui_=(value: Option[gui.Buffer]) = _currentGui = value
def tier: Int
def onScreenColorChange(foreground: Int, background: Int)
def onScreenCopy(col: Int, row: Int, w: Int, h: Int, tx: Int, ty: Int)
def onScreenDepthChange(depth: PackedColor.Depth.Value)
def onScreenFill(col: Int, row: Int, w: Int, h: Int, c: Char)
def onScreenResolutionChange(w: Int, h: Int)
def onScreenSet(col: Int, row: Int, s: String)
}
}

View File

@ -0,0 +1,94 @@
package li.cil.oc.common.component
import li.cil.oc.api.network.{Node, Visibility}
import li.cil.oc.common.tileentity
import li.cil.oc.server.component
import li.cil.oc.server.{PacketSender => ServerPacketSender}
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.PackedColor.Depth
import li.cil.oc.{Settings, common}
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.nbt.NBTTagCompound
class Terminal(val rack: tileentity.Rack, val number: Int) extends Buffer.Owner {
val buffer = new common.component.Buffer(this)
val keyboard = if (buffer.node != null) {
buffer.node.setVisibility(Visibility.Neighbors)
new component.Keyboard {
override def isUseableByPlayer(p: EntityPlayer) = true // TODO if player has bound terminal
}
}
else null
def isServer = rack.isServer
def connect(node: Node) {
node.connect(buffer.node)
node.connect(keyboard.node)
buffer.node.connect(keyboard.node)
}
def tier = 1
// ----------------------------------------------------------------------- //
def load(nbt: NBTTagCompound) {
buffer.load(nbt.getCompoundTag(Settings.namespace + "buffer"))
keyboard.load(nbt.getCompoundTag(Settings.namespace + "keyboard"))
}
def save(nbt: NBTTagCompound) {
nbt.setNewCompoundTag(Settings.namespace + "buffer", buffer.save)
nbt.setNewCompoundTag(Settings.namespace + "keyboard", keyboard.save)
}
// ----------------------------------------------------------------------- //
def onScreenColorChange(foreground: Int, background: Int) {
if (isServer) {
rack.markAsChanged()
ServerPacketSender.sendScreenColorChange(buffer, foreground, background)
}
else currentGui.foreach(_.recompileDisplayLists())
}
def onScreenCopy(col: Int, row: Int, w: Int, h: Int, tx: Int, ty: Int) {
if (isServer) {
rack.markAsChanged()
ServerPacketSender.sendScreenCopy(buffer, col, row, w, h, tx, ty)
}
else currentGui.foreach(_.recompileDisplayLists())
}
def onScreenDepthChange(depth: Depth.Value) {
if (isServer) {
rack.markAsChanged()
ServerPacketSender.sendScreenDepthChange(buffer, depth)
}
else currentGui.foreach(_.recompileDisplayLists())
}
def onScreenFill(col: Int, row: Int, w: Int, h: Int, c: Char) {
if (isServer) {
rack.markAsChanged()
ServerPacketSender.sendScreenFill(buffer, col, row, w, h, c)
}
else currentGui.foreach(_.recompileDisplayLists())
}
def onScreenResolutionChange(w: Int, h: Int) {
if (isServer) {
rack.markAsChanged()
ServerPacketSender.sendScreenResolutionChange(buffer, w, h)
}
else currentGui.foreach(_.recompileDisplayLists())
}
def onScreenSet(col: Int, row: Int, s: String) {
if (isServer) {
rack.markAsChanged()
ServerPacketSender.sendScreenSet(buffer, col, row, s)
}
else currentGui.foreach(_.recompileDisplayLists())
}
}

View File

@ -6,7 +6,7 @@ import net.minecraft.entity.player.{EntityPlayer, InventoryPlayer}
class Server(playerInventory: InventoryPlayer, serverInventory: ServerInventory) extends Player(playerInventory, serverInventory) { class Server(playerInventory: InventoryPlayer, serverInventory: ServerInventory) extends Player(playerInventory, serverInventory) {
for (i <- 0 to 1) { for (i <- 0 to 1) {
addSlotToContainer(76, 7 + i * slotSize, api.driver.Slot.Card, 1) addSlotToContainer(76, 7 + i * slotSize, api.driver.Slot.Card, 2 - i)
} }
for (i <- 0 to 3) { for (i <- 0 to 3) {

View File

@ -18,7 +18,8 @@ trait ServerInventory extends ItemStackInventory {
override def isItemValidForSlot(slot: Int, stack: ItemStack) = override def isItemValidForSlot(slot: Int, stack: ItemStack) =
(slot, Registry.itemDriverFor(stack)) match { (slot, Registry.itemDriverFor(stack)) match {
case (_, None) => false // Invalid item. case (_, None) => false // Invalid item.
case (0 | 1, Some(driver)) => driver.slot(stack) == Slot.Card && driver.tier(stack) <= 1 case (0, Some(driver)) => driver.slot(stack) == Slot.Card && driver.tier(stack) <= 2
case (1, Some(driver)) => driver.slot(stack) == Slot.Card && driver.tier(stack) <= 1
case (2 | 3 | 4 | 5, Some(driver)) => driver.slot(stack) == Slot.Processor && driver.tier(stack) <= 2 case (2 | 3 | 4 | 5, Some(driver)) => driver.slot(stack) == Slot.Processor && driver.tier(stack) <= 2
case (6 | 7 | 8 | 9, Some(driver)) => driver.slot(stack) == Slot.Memory && driver.tier(stack) <= 2 case (6 | 7 | 8 | 9, Some(driver)) => driver.slot(stack) == Slot.Memory && driver.tier(stack) <= 2
case (10 | 11 | 12 | 13, Some(driver)) => driver.slot(stack) == Slot.HardDiskDrive && driver.tier(stack) <= 2 case (10 | 11 | 12 | 13, Some(driver)) => driver.slot(stack) == Slot.HardDiskDrive && driver.tier(stack) <= 2

View File

@ -1,5 +1,70 @@
package li.cil.oc.common.item package li.cil.oc.common.item
import cpw.mods.fml.relauncher.{SideOnly, Side}
import java.util
import li.cil.oc.common.{GuiType, tileentity}
import li.cil.oc.util.Tooltip
import li.cil.oc.{OpenComputers, Settings}
import net.minecraft.client.renderer.texture.IconRegister
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
import net.minecraft.world.World
class Terminal(val parent: Delegator) extends Delegate { class Terminal(val parent: Delegator) extends Delegate {
val unlocalizedName = "Terminal" val unlocalizedName = "Terminal"
@SideOnly(Side.CLIENT)
override def tooltipLines(stack: ItemStack, player: EntityPlayer, tooltip: util.List[String], advanced: Boolean) {
tooltip.addAll(Tooltip.get(unlocalizedName))
if (stack.hasTagCompound && stack.getTagCompound.hasKey(Settings.namespace + "server")) {
val server = stack.getTagCompound.getString(Settings.namespace + "server")
tooltip.add("§8" + server.substring(0, 13) + "...§7")
}
super.tooltipLines(stack, player, tooltip, advanced)
}
override def registerIcons(iconRegister: IconRegister) = {
super.registerIcons(iconRegister)
icon = iconRegister.registerIcon(Settings.resourceDomain + ":terminal")
}
override def onItemUse(stack: ItemStack, player: EntityPlayer, world: World, x: Int, y: Int, z: Int, side: Int, hitX: Float, hitY: Float, hitZ: Float) = {
world.getBlockTileEntity(x, y, z) match {
case rack: tileentity.Rack if side == rack.facing.ordinal() =>
val l = 2 / 16.0
val h = 14 / 16.0
val s = (((1 - hitY) - l) / (h - l) * 4).toInt
if (s >= 0 && s <= 3 && rack.items(s).isDefined) {
if (!world.isRemote) {
rack.servers(s) match {
case Some(server) =>
if (!stack.hasTagCompound) {
stack.setTagCompound(new NBTTagCompound("tag"))
}
stack.getTagCompound.setString(Settings.namespace + "server", server.machine.address)
player.inventory.onInventoryChanged()
case _ => // Huh?
}
}
true
}
else false
case _ => super.onItemUseFirst(stack, player, world, x, y, z, side, hitX, hitY, hitZ)
}
}
override def onItemRightClick(stack: ItemStack, world: World, player: EntityPlayer) = {
if (!player.isSneaking && stack.hasTagCompound) {
val address = stack.getTagCompound.getString(Settings.namespace + "server")
if (address != null && !address.isEmpty) {
if (world.isRemote) {
player.openGui(OpenComputers, GuiType.Terminal.id, world, 0, 0, 0)
}
player.swingItem()
}
}
super.onItemRightClick(stack, world, player)
}
} }

View File

@ -2,29 +2,22 @@ package li.cil.oc.common.tileentity
import cpw.mods.fml.relauncher.{Side, SideOnly} import cpw.mods.fml.relauncher.{Side, SideOnly}
import li.cil.oc.api.network.Node import li.cil.oc.api.network.Node
import li.cil.oc.client.gui
import li.cil.oc.common.component import li.cil.oc.common.component
import li.cil.oc.server.{PacketSender => ServerPacketSender} import li.cil.oc.server.{PacketSender => ServerPacketSender}
import li.cil.oc.util.PackedColor import li.cil.oc.util.PackedColor
import net.minecraft.nbt.NBTTagCompound import net.minecraft.nbt.NBTTagCompound
trait Buffer extends Environment { trait Buffer extends Environment with component.Buffer.Owner {
protected val _buffer = new component.Buffer(this) protected val _buffer = new component.Buffer(this)
protected var _bufferIsDirty = false protected var _bufferIsDirty = false
protected var _currentGui = None: Option[gui.Buffer]
lazy val buffer = _buffer lazy val buffer = _buffer
def bufferIsDirty = _bufferIsDirty def bufferIsDirty = _bufferIsDirty
def bufferIsDirty_=(value: Boolean) = _bufferIsDirty = value def bufferIsDirty_=(value: Boolean) = _bufferIsDirty = value
def currentGui = _currentGui
def currentGui_=(value: Option[gui.Buffer]) = _currentGui = value
def node: Node = buffer.node def node: Node = buffer.node
def tier: Int def tier: Int
@ -58,47 +51,47 @@ trait Buffer extends Environment {
def onScreenColorChange(foreground: Int, background: Int) { def onScreenColorChange(foreground: Int, background: Int) {
if (isServer) { if (isServer) {
world.markTileEntityChunkModified(x, y, z, this.asInstanceOf[net.minecraft.tileentity.TileEntity]) world.markTileEntityChunkModified(x, y, z, this)
ServerPacketSender.sendScreenColorChange(this, foreground, background) ServerPacketSender.sendScreenColorChange(buffer, foreground, background)
} }
} }
def onScreenCopy(col: Int, row: Int, w: Int, h: Int, tx: Int, ty: Int) { def onScreenCopy(col: Int, row: Int, w: Int, h: Int, tx: Int, ty: Int) {
if (isServer) { if (isServer) {
world.markTileEntityChunkModified(x, y, z, this.asInstanceOf[net.minecraft.tileentity.TileEntity]) world.markTileEntityChunkModified(x, y, z, this)
ServerPacketSender.sendScreenCopy(this, col, row, w, h, tx, ty) ServerPacketSender.sendScreenCopy(buffer, col, row, w, h, tx, ty)
} }
else markForRenderUpdate() else markForRenderUpdate()
} }
def onScreenDepthChange(depth: PackedColor.Depth.Value) { def onScreenDepthChange(depth: PackedColor.Depth.Value) {
if (isServer) { if (isServer) {
world.markTileEntityChunkModified(x, y, z, this.asInstanceOf[net.minecraft.tileentity.TileEntity]) world.markTileEntityChunkModified(x, y, z, this)
ServerPacketSender.sendScreenDepthChange(this, depth) ServerPacketSender.sendScreenDepthChange(buffer, depth)
} }
else markForRenderUpdate() else markForRenderUpdate()
} }
def onScreenFill(col: Int, row: Int, w: Int, h: Int, c: Char) { def onScreenFill(col: Int, row: Int, w: Int, h: Int, c: Char) {
if (isServer) { if (isServer) {
world.markTileEntityChunkModified(x, y, z, this.asInstanceOf[net.minecraft.tileentity.TileEntity]) world.markTileEntityChunkModified(x, y, z, this)
ServerPacketSender.sendScreenFill(this, col, row, w, h, c) ServerPacketSender.sendScreenFill(buffer, col, row, w, h, c)
} }
else markForRenderUpdate() else markForRenderUpdate()
} }
def onScreenResolutionChange(w: Int, h: Int) { def onScreenResolutionChange(w: Int, h: Int) {
if (isServer) { if (isServer) {
world.markTileEntityChunkModified(x, y, z, this.asInstanceOf[net.minecraft.tileentity.TileEntity]) world.markTileEntityChunkModified(x, y, z, this)
ServerPacketSender.sendScreenResolutionChange(this, w, h) ServerPacketSender.sendScreenResolutionChange(buffer, w, h)
} }
else markForRenderUpdate() else markForRenderUpdate()
} }
def onScreenSet(col: Int, row: Int, s: String) { def onScreenSet(col: Int, row: Int, s: String) {
if (isServer) { if (isServer) {
world.markTileEntityChunkModified(x, y, z, this.asInstanceOf[net.minecraft.tileentity.TileEntity]) world.markTileEntityChunkModified(x, y, z, this)
ServerPacketSender.sendScreenSet(this, col, row, s) ServerPacketSender.sendScreenSet(buffer, col, row, s)
} }
else markForRenderUpdate() else markForRenderUpdate()
} }

View File

@ -12,7 +12,11 @@ import net.minecraftforge.common.ForgeDirection
class Keyboard(isRemote: Boolean) extends Environment with SidedEnvironment with Analyzable with Rotatable with PassiveNode { class Keyboard(isRemote: Boolean) extends Environment with SidedEnvironment with Analyzable with Rotatable with PassiveNode {
def this() = this(false) def this() = this(false)
val keyboard = if (isRemote) null else new component.Keyboard(this) val keyboard = if (isRemote) null else new component.Keyboard {
def isUseableByPlayer(p: EntityPlayer) =
world.getBlockTileEntity(x, y, z) == Keyboard.this &&
p.getDistanceSq(x + 0.5, y + 0.5, z + 0.5) <= 64
}
def node = if (isClient) null else keyboard.node def node = if (isClient) null else keyboard.node

View File

@ -3,12 +3,13 @@ package li.cil.oc.common.tileentity
import cpw.mods.fml.common.Optional import cpw.mods.fml.common.Optional
import cpw.mods.fml.relauncher.{Side, SideOnly} import cpw.mods.fml.relauncher.{Side, SideOnly}
import li.cil.oc.api.network.{Visibility, Node, Analyzable} import li.cil.oc.api.network.{Visibility, Node, Analyzable}
import li.cil.oc.common
import li.cil.oc.server.{PacketSender => ServerPacketSender, driver, component} import li.cil.oc.server.{PacketSender => ServerPacketSender, driver, component}
import li.cil.oc.util.ExtendedNBT._ import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.{api, Items, Settings} import li.cil.oc.{api, Items, Settings}
import net.minecraft.entity.player.EntityPlayer import net.minecraft.entity.player.EntityPlayer
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound import net.minecraft.nbt.{NBTTagString, NBTTagCompound}
import net.minecraftforge.common.ForgeDirection import net.minecraftforge.common.ForgeDirection
import stargatetech2.api.bus.IBusDevice import stargatetech2.api.bus.IBusDevice
@ -19,13 +20,15 @@ class Rack extends Hub with PowerBalancer with Inventory with Rotatable with Bun
val sides = Array.fill(servers.length)(ForgeDirection.UNKNOWN) val sides = Array.fill(servers.length)(ForgeDirection.UNKNOWN)
val terminals = (0 until servers.length).map(new common.component.Terminal(this, _)).toArray
// For client side, where we don't create the component. // For client side, where we don't create the component.
private val _isRunning = new Array[Boolean](getSizeInventory) private val _isRunning = new Array[Boolean](getSizeInventory)
private var hasChanged = false private var hasChanged = false
// For client side rendering. // For client side rendering.
var isPresent = new Array[Boolean](getSizeInventory) var isPresent = Array.fill[Option[String]](getSizeInventory)(None)
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
@ -147,8 +150,6 @@ class Rack extends Hub with PowerBalancer with Inventory with Rotatable with Bun
override def readFromNBT(nbt: NBTTagCompound) { override def readFromNBT(nbt: NBTTagCompound) {
super.readFromNBT(nbt) super.readFromNBT(nbt)
val sidesNbt = nbt.getByteArray(Settings.namespace + "sides").byteArray.map(ForgeDirection.getOrientation(_))
Array.copy(sidesNbt, 0, sides, 0, math.min(sidesNbt.length, sides.length))
for (slot <- 0 until getSizeInventory) { for (slot <- 0 until getSizeInventory) {
if (getStackInSlot(slot) != null) { if (getStackInSlot(slot) != null) {
val server = new component.Server(this, slot) val server = new component.Server(this, slot)
@ -161,10 +162,15 @@ class Rack extends Hub with PowerBalancer with Inventory with Rotatable with Bun
case _ => case _ =>
} }
} }
val sidesNbt = nbt.getByteArray(Settings.namespace + "sides").byteArray.map(ForgeDirection.getOrientation(_))
Array.copy(sidesNbt, 0, sides, 0, math.min(sidesNbt.length, sides.length))
val terminalsNbt = nbt.getTagList(Settings.namespace + "terminals").iterator[NBTTagCompound].toArray
for (i <- 0 until math.min(terminals.length, terminalsNbt.length)) {
terminals(i).load(terminalsNbt(i))
}
} }
override def writeToNBT(nbt: NBTTagCompound) { override def writeToNBT(nbt: NBTTagCompound) {
nbt.setByteArray(Settings.namespace + "sides", sides.map(_.ordinal.toByte))
nbt.setNewTagList(Settings.namespace + "servers", servers map { nbt.setNewTagList(Settings.namespace + "servers", servers map {
case Some(server) => case Some(server) =>
val serverNbt = new NBTTagCompound() val serverNbt = new NBTTagCompound()
@ -173,6 +179,12 @@ class Rack extends Hub with PowerBalancer with Inventory with Rotatable with Bun
case _ => new NBTTagCompound() case _ => new NBTTagCompound()
}) })
super.writeToNBT(nbt) super.writeToNBT(nbt)
nbt.setByteArray(Settings.namespace + "sides", sides.map(_.ordinal.toByte))
nbt.setNewTagList(Settings.namespace + "terminals", terminals.map(t => {
val terminalNbt = new NBTTagCompound()
t.save(terminalNbt)
terminalNbt
}))
} }
@SideOnly(Side.CLIENT) @SideOnly(Side.CLIENT)
@ -180,17 +192,26 @@ class Rack extends Hub with PowerBalancer with Inventory with Rotatable with Bun
super.readFromNBTForClient(nbt) super.readFromNBTForClient(nbt)
val isRunningNbt = nbt.getByteArray("isRunning").byteArray.map(_ == 1) val isRunningNbt = nbt.getByteArray("isRunning").byteArray.map(_ == 1)
Array.copy(isRunningNbt, 0, _isRunning, 0, math.min(isRunningNbt.length, _isRunning.length)) Array.copy(isRunningNbt, 0, _isRunning, 0, math.min(isRunningNbt.length, _isRunning.length))
val isPresentNbt = nbt.getByteArray("isPresent").byteArray.map(_ == 1) val isPresentNbt = nbt.getTagList("isPresent").iterator[NBTTagString].map(value => if (value.data == "") None else Some(value.data)).toArray
Array.copy(isPresentNbt, 0, isPresent, 0, math.min(isPresentNbt.length, isPresent.length)) Array.copy(isPresentNbt, 0, isPresent, 0, math.min(isPresentNbt.length, isPresent.length))
val sidesNbt = nbt.getByteArray("sides").byteArray.map(ForgeDirection.getOrientation(_)) val sidesNbt = nbt.getByteArray("sides").byteArray.map(ForgeDirection.getOrientation(_))
Array.copy(sidesNbt, 0, sides, 0, math.min(sidesNbt.length, sides.length)) Array.copy(sidesNbt, 0, sides, 0, math.min(sidesNbt.length, sides.length))
val terminalsNbt = nbt.getTagList("terminals").iterator[NBTTagCompound].toArray
for (i <- 0 until math.min(terminals.length, terminalsNbt.length)) {
terminals(i).buffer.buffer.load(terminalsNbt(i))
}
} }
override def writeToNBTForClient(nbt: NBTTagCompound) { override def writeToNBTForClient(nbt: NBTTagCompound) {
super.writeToNBTForClient(nbt) super.writeToNBTForClient(nbt)
nbt.setByteArray("isRunning", _isRunning.map(value => (if (value) 1 else 0).toByte)) nbt.setByteArray("isRunning", _isRunning.map(value => (if (value) 1 else 0).toByte))
nbt.setByteArray("isPresent", servers.map(value => (if (value.isDefined) 1 else 0).toByte)) nbt.setNewTagList("isPresent", servers.map(value => new NBTTagString(null, value.fold("")(_.machine.address))))
nbt.setByteArray("sides", sides.map(_.ordinal.toByte)) nbt.setByteArray("sides", sides.map(_.ordinal.toByte))
nbt.setNewTagList("terminals", terminals.map(t => {
val terminalNbt = new NBTTagCompound()
t.buffer.buffer.save(terminalNbt)
terminalNbt
}))
} }
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
@ -202,6 +223,7 @@ class Rack extends Hub with PowerBalancer with Inventory with Rotatable with Bun
servers(number) match { servers(number) match {
case Some(server) if toGlobal(serverSide) == plug.side || serverSide == ForgeDirection.UNKNOWN => case Some(server) if toGlobal(serverSide) == plug.side || serverSide == ForgeDirection.UNKNOWN =>
plug.node.connect(server.machine.node) plug.node.connect(server.machine.node)
terminals(number).connect(server.machine.node)
case _ => case _ =>
} }
} }
@ -218,6 +240,7 @@ class Rack extends Hub with PowerBalancer with Inventory with Rotatable with Bun
val server = new component.Server(this, slot) val server = new component.Server(this, slot)
servers(slot) = Some(server) servers(slot) = Some(server)
reconnectServer(slot, server) reconnectServer(slot, server)
terminals(slot).connect(server.machine.node)
} }
} }

View File

@ -61,7 +61,7 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with ISidedInventory w
val gpu = new GraphicsCard.Tier1 { val gpu = new GraphicsCard.Tier1 {
override val maxResolution = (48, 14) override val maxResolution = (48, 14)
} }
val keyboard = new component.Keyboard(this) { val keyboard = new component.Keyboard {
override def isUseableByPlayer(p: EntityPlayer) = override def isUseableByPlayer(p: EntityPlayer) =
world.getBlockTileEntity(x, y, z) == proxy && world.getBlockTileEntity(x, y, z) == proxy &&
p.getDistanceSq(x + 0.5, y + 0.5, z + 0.5) <= 64 p.getDistanceSq(x + 0.5, y + 0.5, z + 0.5) <= 64
@ -306,11 +306,9 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with ISidedInventory w
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
override def readFromNBT(nbt: NBTTagCompound) { override def readFromNBT(nbt: NBTTagCompound) {
if (isServer) { buffer.load(nbt.getCompoundTag(Settings.namespace + "buffer"))
buffer.load(nbt.getCompoundTag(Settings.namespace + "buffer")) gpu.load(nbt.getCompoundTag(Settings.namespace + "gpu"))
gpu.load(nbt.getCompoundTag(Settings.namespace + "gpu")) keyboard.load(nbt.getCompoundTag(Settings.namespace + "keyboard"))
keyboard.load(nbt.getCompoundTag(Settings.namespace + "keyboard"))
}
if (nbt.hasKey(Settings.namespace + "owner")) { if (nbt.hasKey(Settings.namespace + "owner")) {
owner = nbt.getString(Settings.namespace + "owner") owner = nbt.getString(Settings.namespace + "owner")
} }

View File

@ -154,7 +154,7 @@ class Screen(var tier: Int) extends Buffer with SidedEnvironment with Rotatable
// Convert to absolute coordinates and send the packet to the server. // Convert to absolute coordinates and send the packet to the server.
if (world.isRemote) { if (world.isRemote) {
ClientPacketSender.sendMouseClick(this, (brx * bw).toInt + 1, (bry * bh).toInt + 1, drag = false) ClientPacketSender.sendMouseClick(this.buffer, (brx * bw).toInt + 1, (bry * bh).toInt + 1, drag = false)
} }
true true
} }

View File

@ -56,59 +56,68 @@ class PacketHandler extends CommonPacketHandler {
} }
def onKeyDown(p: PacketParser) = def onKeyDown(p: PacketParser) =
p.readTileEntity[Buffer]() match { p.readTileEntity[TileEntity]() match {
case Some(s: Screen) => case Some(t: Screen) =>
val char = Char.box(p.readChar()) val char = Char.box(p.readChar())
val code = Int.box(p.readInt()) val code = Int.box(p.readInt())
s.screens.foreach(_.node.sendToNeighbors("keyboard.keyDown", p.player, char, code)) t.screens.foreach(_.node.sendToNeighbors("keyboard.keyDown", p.player, char, code))
case Some(e) => e.buffer.node.sendToNeighbors("keyboard.keyDown", p.player, Char.box(p.readChar()), Int.box(p.readInt())) case Some(t: Buffer) => t.buffer.node.sendToNeighbors("keyboard.keyDown", p.player, Char.box(p.readChar()), Int.box(p.readInt()))
case Some(t: Rack) => t.terminals(p.readInt()).buffer.node.sendToNeighbors("keyboard.keyDown", p.player, Char.box(p.readChar()), Int.box(p.readInt()))
case _ => // Invalid packet. case _ => // Invalid packet.
} }
def onKeyUp(p: PacketParser) = def onKeyUp(p: PacketParser) =
p.readTileEntity[Buffer]() match { p.readTileEntity[TileEntity]() match {
case Some(s: Screen) => case Some(t: Screen) =>
val char = Char.box(p.readChar()) val char = Char.box(p.readChar())
val code = Int.box(p.readInt()) val code = Int.box(p.readInt())
s.screens.foreach(_.node.sendToNeighbors("keyboard.keyUp", p.player, char, code)) t.screens.foreach(_.node.sendToNeighbors("keyboard.keyUp", p.player, char, code))
case Some(e) => e.buffer.node.sendToNeighbors("keyboard.keyUp", p.player, Char.box(p.readChar()), Int.box(p.readInt())) case Some(t: Buffer) => t.buffer.node.sendToNeighbors("keyboard.keyUp", p.player, Char.box(p.readChar()), Int.box(p.readInt()))
case Some(t: Rack) => t.terminals(p.readInt()).buffer.node.sendToNeighbors("keyboard.keyUp", p.player, Char.box(p.readChar()), Int.box(p.readInt()))
case _ => // Invalid packet. case _ => // Invalid packet.
} }
def onClipboard(p: PacketParser) = def onClipboard(p: PacketParser) =
p.readTileEntity[Buffer]() match { p.readTileEntity[TileEntity]() match {
case Some(s: Screen) => case Some(t: Screen) =>
val value = p.readUTF() val value = p.readUTF()
s.screens.foreach(_.node.sendToNeighbors("keyboard.clipboard", p.player, value)) t.screens.foreach(_.node.sendToNeighbors("keyboard.clipboard", p.player, value))
case Some(e) => e.buffer.node.sendToNeighbors("keyboard.clipboard", p.player, p.readUTF()) case Some(t: Buffer) => t.buffer.node.sendToNeighbors("keyboard.clipboard", p.player, p.readUTF())
case Some(t: Rack) => t.terminals(p.readInt()).buffer.node.sendToNeighbors("keyboard.clipboard", p.player, p.readUTF())
case _ => // Invalid packet. case _ => // Invalid packet.
} }
def onMouseClick(p: PacketParser) = def onMouseClick(p: PacketParser) {
p.readTileEntity[Buffer]() match { p.player match {
case Some(s: Screen) => p.player match { case player: EntityPlayer =>
case player: EntityPlayer => val node = p.readTileEntity[TileEntity]() match {
val x = p.readInt() case Some(t: Screen) => t.origin.node
val y = p.readInt() case Some(t: Rack) => t.terminals(p.readInt()).buffer.node
val what = if (p.readBoolean()) "drag" else "touch" case _ => return // Invalid packet.
s.origin.node.sendToReachable("computer.checked_signal", player, what, Int.box(x), Int.box(y), player.getCommandSenderName) }
case _ => val x = p.readInt()
} val y = p.readInt()
val what = if (p.readBoolean()) "drag" else "touch"
node.sendToReachable("computer.checked_signal", player, what, Int.box(x), Int.box(y), player.getCommandSenderName)
case _ => // Invalid packet. case _ => // Invalid packet.
} }
}
def onMouseScroll(p: PacketParser) = def onMouseScroll(p: PacketParser) {
p.readTileEntity[Buffer]() match { p.player match {
case Some(s: Screen) => p.player match { case player: EntityPlayer =>
case player: EntityPlayer => val node = p.readTileEntity[TileEntity]() match {
val x = p.readInt() case Some(t: Screen) => t.origin.node
val y = p.readInt() case Some(t: Rack) => t.terminals(p.readInt()).buffer.node
val scroll = p.readByte() case _ => return // Invalid packet.
s.origin.node.sendToReachable("computer.checked_signal", player, "scroll", Int.box(x), Int.box(y), Int.box(scroll), player.getCommandSenderName) }
case _ => val x = p.readInt()
} val y = p.readInt()
val scroll = p.readByte()
node.sendToReachable("computer.checked_signal", player, "scroll", Int.box(x), Int.box(y), Int.box(scroll), player.getCommandSenderName)
case _ => // Invalid packet. case _ => // Invalid packet.
} }
}
def onServerSide(p: PacketParser) = def onServerSide(p: PacketParser) =
p.readTileEntity[Rack]() match { p.readTileEntity[Rack]() match {

View File

@ -1,6 +1,7 @@
package li.cil.oc.server package li.cil.oc.server
import cpw.mods.fml.common.network.Player import cpw.mods.fml.common.network.Player
import li.cil.oc.common
import li.cil.oc.common.PacketBuilder import li.cil.oc.common.PacketBuilder
import li.cil.oc.common.PacketType import li.cil.oc.common.PacketType
import li.cil.oc.common.tileentity._ import li.cil.oc.common.tileentity._
@ -156,20 +157,38 @@ object PacketSender {
pb.sendToNearbyPlayers(t) pb.sendToNearbyPlayers(t)
} }
def sendScreenColorChange(t: Buffer, foreground: Int, background: Int) { def sendScreenColorChange(b: common.component.Buffer, foreground: Int, background: Int) {
val pb = new PacketBuilder(PacketType.ScreenColorChange) val pb = new PacketBuilder(PacketType.ScreenColorChange)
pb.writeTileEntity(t) val t = b.owner match {
case t: Buffer =>
pb.writeTileEntity(t)
t
case t: common.component.Terminal =>
pb.writeTileEntity(t.rack)
pb.writeInt(t.number)
t.rack
case _ => return
}
pb.writeInt(foreground) pb.writeInt(foreground)
pb.writeInt(background) pb.writeInt(background)
pb.sendToNearbyPlayers(t) pb.sendToNearbyPlayers(t)
} }
def sendScreenCopy(t: Buffer, col: Int, row: Int, w: Int, h: Int, tx: Int, ty: Int) { def sendScreenCopy(b: common.component.Buffer, col: Int, row: Int, w: Int, h: Int, tx: Int, ty: Int) {
val pb = new PacketBuilder(PacketType.ScreenCopy) val pb = new PacketBuilder(PacketType.ScreenCopy)
pb.writeTileEntity(t) val t = b.owner match {
case t: Buffer =>
pb.writeTileEntity(t)
t
case t: common.component.Terminal =>
pb.writeTileEntity(t.rack)
pb.writeInt(t.number)
t.rack
case _ => return
}
pb.writeInt(col) pb.writeInt(col)
pb.writeInt(row) pb.writeInt(row)
pb.writeInt(w) pb.writeInt(w)
@ -180,19 +199,37 @@ object PacketSender {
pb.sendToNearbyPlayers(t) pb.sendToNearbyPlayers(t)
} }
def sendScreenDepthChange(t: Buffer, value: PackedColor.Depth.Value) { def sendScreenDepthChange(b: common.component.Buffer, value: PackedColor.Depth.Value) {
val pb = new PacketBuilder(PacketType.ScreenDepthChange) val pb = new PacketBuilder(PacketType.ScreenDepthChange)
pb.writeTileEntity(t) val t = b.owner match {
case t: Buffer =>
pb.writeTileEntity(t)
t
case t: common.component.Terminal =>
pb.writeTileEntity(t.rack)
pb.writeInt(t.number)
t.rack
case _ => return
}
pb.writeInt(value.id) pb.writeInt(value.id)
pb.sendToNearbyPlayers(t) pb.sendToNearbyPlayers(t)
} }
def sendScreenFill(t: Buffer, col: Int, row: Int, w: Int, h: Int, c: Char) { def sendScreenFill(b: common.component.Buffer, col: Int, row: Int, w: Int, h: Int, c: Char) {
val pb = new PacketBuilder(PacketType.ScreenFill) val pb = new PacketBuilder(PacketType.ScreenFill)
pb.writeTileEntity(t) val t = b.owner match {
case t: Buffer =>
pb.writeTileEntity(t)
t
case t: common.component.Terminal =>
pb.writeTileEntity(t.rack)
pb.writeInt(t.number)
t.rack
case _ => return
}
pb.writeInt(col) pb.writeInt(col)
pb.writeInt(row) pb.writeInt(row)
pb.writeInt(w) pb.writeInt(w)
@ -211,20 +248,38 @@ object PacketSender {
pb.sendToNearbyPlayers(t, 64) pb.sendToNearbyPlayers(t, 64)
} }
def sendScreenResolutionChange(t: Buffer, w: Int, h: Int) { def sendScreenResolutionChange(b: common.component.Buffer, w: Int, h: Int) {
val pb = new PacketBuilder(PacketType.ScreenResolutionChange) val pb = new PacketBuilder(PacketType.ScreenResolutionChange)
pb.writeTileEntity(t) val t = b.owner match {
case t: Buffer =>
pb.writeTileEntity(t)
t
case t: common.component.Terminal =>
pb.writeTileEntity(t.rack)
pb.writeInt(t.number)
t.rack
case _ => return
}
pb.writeInt(w) pb.writeInt(w)
pb.writeInt(h) pb.writeInt(h)
pb.sendToNearbyPlayers(t) pb.sendToNearbyPlayers(t)
} }
def sendScreenSet(t: Buffer, col: Int, row: Int, s: String) { def sendScreenSet(b: common.component.Buffer, col: Int, row: Int, s: String) {
val pb = new PacketBuilder(PacketType.ScreenSet) val pb = new PacketBuilder(PacketType.ScreenSet)
pb.writeTileEntity(t) val t = b.owner match {
case t: Buffer =>
pb.writeTileEntity(t)
t
case t: common.component.Terminal =>
pb.writeTileEntity(t.rack)
pb.writeInt(t.number)
t.rack
case _ => return
}
pb.writeInt(col) pb.writeInt(col)
pb.writeInt(row) pb.writeInt(row)
pb.writeUTF(s) pb.writeUTF(s)
@ -236,7 +291,13 @@ object PacketSender {
val pb = new PacketBuilder(PacketType.ServerPresence) val pb = new PacketBuilder(PacketType.ServerPresence)
pb.writeTileEntity(t) pb.writeTileEntity(t)
t.servers.foreach(server => pb.writeBoolean(server.isDefined)) t.servers.foreach {
case Some(server) =>
pb.writeBoolean(true)
pb.writeUTF(server.machine.address)
case _ =>
pb.writeBoolean(false)
}
pb.sendToNearbyPlayers(t) pb.sendToNearbyPlayers(t)
} }

View File

@ -3,7 +3,6 @@ package li.cil.oc.server.component
import cpw.mods.fml.common.IPlayerTracker import cpw.mods.fml.common.IPlayerTracker
import li.cil.oc.api.Network import li.cil.oc.api.Network
import li.cil.oc.api.network.{Node, Visibility, Message} import li.cil.oc.api.network.{Node, Visibility, Message}
import li.cil.oc.common.tileentity.Environment
import net.minecraft.entity.player.EntityPlayer import net.minecraft.entity.player.EntityPlayer
import net.minecraftforge.common.MinecraftForge import net.minecraftforge.common.MinecraftForge
import net.minecraftforge.event.{Event, ForgeSubscribe} import net.minecraftforge.event.{Event, ForgeSubscribe}
@ -12,7 +11,7 @@ import scala.collection.mutable
// TODO key up when screen is disconnected from which the key down came // TODO key up when screen is disconnected from which the key down came
// TODO key up after load for anything that was pressed // TODO key up after load for anything that was pressed
class Keyboard(owner: Environment) extends ManagedComponent { abstract class Keyboard extends ManagedComponent {
val node = Network.newNode(this, Visibility.Network). val node = Network.newNode(this, Visibility.Network).
withComponent("keyboard"). withComponent("keyboard").
create() create()
@ -71,9 +70,7 @@ class Keyboard(owner: Environment) extends ManagedComponent {
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
def isUseableByPlayer(p: EntityPlayer) = def isUseableByPlayer(p: EntityPlayer): Boolean
owner.world.getBlockTileEntity(owner.x, owner.y, owner.z) == owner &&
p.getDistanceSq(owner.x + 0.5, owner.y + 0.5, owner.z + 0.5) <= 64
protected def signal(args: AnyRef*) = protected def signal(args: AnyRef*) =
node.sendToReachable("computer.checked_signal", args: _*) node.sendToReachable("computer.checked_signal", args: _*)

View File

@ -711,6 +711,7 @@ class Machine(val owner: Machine.Owner) extends ManagedComponent with Context wi
switchTo(Machine.State.Stopping) switchTo(Machine.State.Stopping)
} }
case result: ExecutionResult.Error => case result: ExecutionResult.Error =>
crash(result.message)
} }
case Machine.State.Paused => case Machine.State.Paused =>
state.pop() // Paused state.pop() // Paused

View File

@ -29,6 +29,8 @@ class Server(val rack: tileentity.Rack, val number: Int) extends Machine.Owner {
override def getInventoryStackLimit = 1 override def getInventoryStackLimit = 1
} }
// ----------------------------------------------------------------------- //
def installedMemory = inventory.items.foldLeft(0)((sum, stack) => sum + (stack match { def installedMemory = inventory.items.foldLeft(0)((sum, stack) => sum + (stack match {
case Some(item) => Registry.itemDriverFor(item) match { case Some(item) => Registry.itemDriverFor(item) match {
case Some(driver: driver.Memory) => driver.amount(item) case Some(driver: driver.Memory) => driver.amount(item)
@ -49,6 +51,8 @@ class Server(val rack: tileentity.Rack, val number: Int) extends Machine.Owner {
def markAsChanged() = rack.markAsChanged() def markAsChanged() = rack.markAsChanged()
// ----------------------------------------------------------------------- //
override def onConnect(node: Node) = inventory.onConnect(node) override def onConnect(node: Node) = inventory.onConnect(node)
override def onDisconnect(node: Node) = inventory.onDisconnect(node) override def onDisconnect(node: Node) = inventory.onDisconnect(node)