More work on drone GUI, shows up now, powering works via that, inventory works.

This commit is contained in:
Florian Nücke 2014-12-14 23:02:08 +01:00
parent 8c47a50070
commit fdb834adc9
13 changed files with 307 additions and 162 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 596 B

After

Width:  |  Height:  |  Size: 596 B

View File

@ -1,17 +1,25 @@
package li.cil.oc.client
import li.cil.oc.{Localization, Settings}
import li.cil.oc.Localization
import li.cil.oc.Settings
import li.cil.oc.api.component.TextBuffer
import li.cil.oc.common.GuiType
import li.cil.oc.common.entity
import li.cil.oc.common.init.Items
import li.cil.oc.common.inventory.{DatabaseInventory, ServerInventory}
import li.cil.oc.common.inventory.DatabaseInventory
import li.cil.oc.common.inventory.ServerInventory
import li.cil.oc.common.item
import li.cil.oc.common.item.Tablet
import li.cil.oc.common.{GuiType, item, tileentity, GuiHandler => CommonGuiHandler}
import li.cil.oc.common.tileentity
import li.cil.oc.common.{GuiHandler => CommonGuiHandler}
import net.minecraft.client.Minecraft
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.world.World
object GuiHandler extends CommonGuiHandler {
override def getClientGuiElement(id: Int, player: EntityPlayer, world: World, x: Int, y: Int, z: Int): AnyRef =
override def getClientGuiElement(id: Int, player: EntityPlayer, world: World, x: Int, y: Int, z: Int): AnyRef = {
GuiType.Categories.get(id) match {
case Some(GuiType.Category.Block) =>
world.getTileEntity(x, y, z) match {
case t: tileentity.Adapter if id == GuiType.Adapter.id =>
new gui.Adapter(player.inventory, t)
@ -35,7 +43,16 @@ object GuiHandler extends CommonGuiHandler {
new gui.Screen(t.origin.buffer, t.tier > 0, () => t.origin.hasKeyboard, () => t.origin.buffer.isRenderingEnabled)
case t: tileentity.Switch if id == GuiType.Switch.id =>
new gui.Switch(player.inventory, t)
case _ => Items.multi.subItem(player.getCurrentEquippedItem) match {
case _ => null
}
case Some(GuiType.Category.Entity) =>
world.getEntityByID(x) match {
case drone: entity.Drone if id == GuiType.Drone.id =>
new gui.Drone(player.inventory, drone)
case _ => null
}
case Some(GuiType.Category.Item) =>
Items.multi.subItem(player.getCurrentEquippedItem) match {
case Some(database: item.UpgradeDatabase) if id == GuiType.Database.id =>
new gui.Database(player.inventory, new DatabaseInventory {
override def tier = database.tier
@ -99,5 +116,7 @@ object GuiHandler extends CommonGuiHandler {
null
case _ => null
}
case _ => null
}
}
}

View File

@ -4,6 +4,7 @@ import li.cil.oc.Settings
import li.cil.oc.common.CompressedPacketBuilder
import li.cil.oc.common.PacketType
import li.cil.oc.common.SimplePacketBuilder
import li.cil.oc.common.entity.Drone
import li.cil.oc.common.tileentity._
import li.cil.oc.common.tileentity.traits.Computer
import net.minecraft.client.Minecraft
@ -25,6 +26,15 @@ object PacketSender {
pb.sendToServer()
}
def sendDronePower(e: Drone, power: Boolean) {
val pb = new SimplePacketBuilder(PacketType.DronePower)
pb.writeEntity(e)
pb.writeBoolean(power)
pb.sendToServer()
}
def sendKeyDown(address: String, char: Char, code: Int) {
val pb = new SimplePacketBuilder(PacketType.KeyDown)

View File

@ -18,7 +18,7 @@ import org.lwjgl.opengl.GL11
class Drone(playerInventory: InventoryPlayer, val drone: entity.Drone) extends DynamicGuiContainer(new container.Drone(playerInventory, drone)) {
xSize = 176
ySize = 146
ySize = 148
protected var powerButton: ImageButton = _
@ -27,10 +27,10 @@ class Drone(playerInventory: InventoryPlayer, val drone: entity.Drone) extends D
private val bufferX = 10
private val bufferY = 10
private val inventoryX = 95
private val inventoryY = 5
private val inventoryX = 97
private val inventoryY = 7
private val power = addWidget(new ProgressBar(26, 48))
private val power = addWidget(new ProgressBar(28, 48))
private val selectionSize = 20
private val selectionsStates = 17
@ -40,7 +40,7 @@ class Drone(playerInventory: InventoryPlayer, val drone: entity.Drone) extends D
protected override def actionPerformed(button: GuiButton) {
if (button.id == 0) {
// ClientPacketSender.sendComputerPower(drone, !drone.isRunning)
ClientPacketSender.sendDronePower(drone, !drone.isRunning)
}
}
@ -51,7 +51,7 @@ class Drone(playerInventory: InventoryPlayer, val drone: entity.Drone) extends D
override def initGui() {
super.initGui()
powerButton = new ImageButton(0, guiLeft + 5, guiTop + 43, 18, 18, Textures.guiButtonPower, canToggle = true)
powerButton = new ImageButton(0, guiLeft + 7, guiTop + 45, 18, 18, Textures.guiButtonPower, canToggle = true)
add(buttonList, powerButton)
}
@ -79,6 +79,7 @@ class Drone(playerInventory: InventoryPlayer, val drone: entity.Drone) extends D
mc.renderEngine.bindTexture(Textures.guiDrone)
drawTexturedModalRect(guiLeft, guiTop, 0, 0, xSize, ySize)
// power.level = robot.globalBuffer / robot.globalBufferSize
power.level = 0.5
drawWidgets()
if (drone.inventory.getSizeInventory > 0) {
drawSelection()

View File

@ -2,12 +2,15 @@ package li.cil.oc.common
import cpw.mods.fml.common.network.IGuiHandler
import li.cil.oc.common.init.Items
import li.cil.oc.common.inventory.{DatabaseInventory, ServerInventory}
import li.cil.oc.common.inventory.DatabaseInventory
import li.cil.oc.common.inventory.ServerInventory
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.world.World
abstract class GuiHandler extends IGuiHandler {
override def getServerGuiElement(id: Int, player: EntityPlayer, world: World, x: Int, y: Int, z: Int) =
override def getServerGuiElement(id: Int, player: EntityPlayer, world: World, x: Int, y: Int, z: Int): AnyRef = {
GuiType.Categories.get(id) match {
case Some(GuiType.Category.Block) =>
world.getTileEntity(x, y, z) match {
case t: tileentity.Adapter if id == GuiType.Adapter.id =>
new container.Adapter(player.inventory, t)
@ -29,7 +32,16 @@ abstract class GuiHandler extends IGuiHandler {
new container.ServerRack(player.inventory, t)
case t: tileentity.Switch if id == GuiType.Switch.id =>
new container.Switch(player.inventory, t)
case _ => Items.multi.subItem(player.getCurrentEquippedItem) match {
case _ => null
}
case Some(GuiType.Category.Entity) =>
world.getEntityByID(x) match {
case drone: entity.Drone if id == GuiType.Drone.id =>
new container.Drone(player.inventory, drone)
case _ => null
}
case Some(GuiType.Category.Item) =>
Items.multi.subItem(player.getCurrentEquippedItem) match {
case Some(database: item.UpgradeDatabase) if id == GuiType.Database.id =>
new container.Database(player.inventory, new DatabaseInventory {
override def tier = database.tier
@ -48,5 +60,7 @@ abstract class GuiHandler extends IGuiHandler {
})
case _ => null
}
case _ => null
}
}
}

View File

@ -1,23 +1,40 @@
package li.cil.oc.common
object GuiType extends Enumeration {
val
import li.cil.oc.util.ScalaEnum
Adapter,
Assembler,
Case,
Charger,
Database,
Disassembler,
DiskDrive,
Rack,
Raid,
Robot,
Screen,
Server,
Switch,
Tablet,
Terminal
import scala.collection.mutable
= Value
object GuiType extends ScalaEnum {
val Categories = mutable.Map.empty[Int, Category.Value]
sealed trait EnumVal extends Value {
def id = ordinal
def subType: GuiType.Category.Value
Categories += ordinal -> subType
}
val Adapter = new EnumVal { def name = "Adapter"; def subType = GuiType.Category.Block }
val Assembler = new EnumVal { def name = "Assembler"; def subType = GuiType.Category.Block }
val Case = new EnumVal { def name = "Case"; def subType = GuiType.Category.Block }
val Charger = new EnumVal { def name = "Charger"; def subType = GuiType.Category.Block }
val Database = new EnumVal { def name = "Database"; def subType = GuiType.Category.Item }
val Disassembler = new EnumVal { def name = "Disassembler"; def subType = GuiType.Category.Block }
val DiskDrive = new EnumVal { def name = "DiskDrive"; def subType = GuiType.Category.Block }
val Drone = new EnumVal { def name = "Drone"; def subType = GuiType.Category.Entity }
val Rack = new EnumVal { def name = "Rack"; def subType = GuiType.Category.Block }
val Raid = new EnumVal { def name = "Raid"; def subType = GuiType.Category.Block }
val Robot = new EnumVal { def name = "Robot"; def subType = GuiType.Category.Block }
val Screen = new EnumVal { def name = "Screen"; def subType = GuiType.Category.Block }
val Server = new EnumVal { def name = "Server"; def subType = GuiType.Category.Item }
val Switch = new EnumVal { def name = "Switch"; def subType = GuiType.Category.Block }
val Tablet = new EnumVal { def name = "Tablet"; def subType = GuiType.Category.Item }
val Terminal = new EnumVal { def name = "Terminal"; def subType = GuiType.Category.Item }
object Category extends ScalaEnum {
sealed trait EnumVal extends Value
val Block = new EnumVal { def name = "Block" }
val Entity = new EnumVal { def name = "Entity" }
val Item = new EnumVal { def name = "Item" }
}
}

View File

@ -10,6 +10,7 @@ import cpw.mods.fml.common.network.internal.FMLProxyPacket
import io.netty.buffer.Unpooled
import li.cil.oc.OpenComputers
import li.cil.oc.api.driver.EnvironmentHost
import net.minecraft.entity.Entity
import net.minecraft.entity.player.EntityPlayerMP
import net.minecraft.item.ItemStack
import net.minecraft.nbt.CompressedStreamTools
@ -21,13 +22,18 @@ import net.minecraftforge.common.util.ForgeDirection
import scala.collection.convert.WrapAsScala._
abstract class PacketBuilder(stream: OutputStream) extends DataOutputStream(stream) {
def writeTileEntity(t: TileEntity) = {
def writeTileEntity(t: TileEntity) {
writeInt(t.getWorldObj.provider.dimensionId)
writeInt(t.xCoord)
writeInt(t.yCoord)
writeInt(t.zCoord)
}
def writeEntity(e: Entity) {
writeInt(e.worldObj.provider.dimensionId)
writeInt(e.getEntityId)
}
def writeDirection(d: ForgeDirection) = writeInt(d.ordinal)
def writeItemStack(stack: ItemStack) = {

View File

@ -51,7 +51,6 @@ abstract class PacketHandler {
def getTileEntity[T: ClassTag](dimension: Int, x: Int, y: Int, z: Int): Option[T] = {
world(player, dimension) match {
case None => // Invalid dimension.
case Some(world) if world.blockExists(x, y, z) =>
val t = world.getTileEntity(x, y, z)
if (t != null && classTag[T].runtimeClass.isAssignableFrom(t.getClass)) {
@ -68,6 +67,19 @@ abstract class PacketHandler {
}
case _ =>
}
case _ => // Invalid dimension.
}
None
}
def getEntity[T: ClassTag](dimension: Int, id: Int): Option[T] = {
world(player, dimension) match {
case Some(world) =>
val e = world.getEntityByID(id)
if (e != null && classTag[T].runtimeClass.isAssignableFrom(e.getClass)) {
return Some(e.asInstanceOf[T])
}
case _ =>
}
None
}
@ -80,6 +92,12 @@ abstract class PacketHandler {
getTileEntity(dimension, x, y, z)
}
def readEntity[T: ClassTag](): Option[T] = {
val dimension = readInt()
val id = readInt()
getEntity[T](dimension, id)
}
def readDirection() = ForgeDirection.getOrientation(readInt())
def readItemStack() = {

View File

@ -47,6 +47,7 @@ object PacketType extends Enumeration {
// Client -> Server
ComputerPower,
DronePower,
KeyDown,
KeyUp,
Clipboard,

View File

@ -12,14 +12,14 @@ class Drone(playerInventory: InventoryPlayer, drone: entity.Drone) extends Playe
val deltaY = 0
for (i <- 0 to 1) {
val y = 6 + i * slotSize - deltaY
val y = 8 + i * slotSize - deltaY
for (j <- 0 to 3) {
val x = 96 + j * slotSize
val x = 98 + j * slotSize
addSlotToContainer(new InventorySlot(this, otherInventory, inventorySlots.size, x, y))
}
}
addPlayerInventorySlots(6, 64)
addPlayerInventorySlots(8, 66)
class InventorySlot(container: Player, inventory: IInventory, index: Int, x: Int, y: Int) extends StaticComponentSlot(container, inventory, index, x, y, common.Slot.Any, common.Tier.Any) {
def isValid = (0 until drone.inventory.getSizeInventory).contains(getSlotIndex)

View File

@ -2,6 +2,7 @@ package li.cil.oc.common.entity
import cpw.mods.fml.relauncher.Side
import cpw.mods.fml.relauncher.SideOnly
import li.cil.oc.OpenComputers
import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.api.Driver
@ -11,6 +12,7 @@ import li.cil.oc.api.driver.item.Processor
import li.cil.oc.api.internal
import li.cil.oc.api.machine.MachineHost
import li.cil.oc.api.network._
import li.cil.oc.common.GuiType
import li.cil.oc.common.Slot
import li.cil.oc.common.inventory.ComponentInventory
import li.cil.oc.common.inventory.Inventory
@ -286,11 +288,7 @@ class Drone(val world: World) extends Entity(world) with MachineHost with intern
stack
}
override def interactFirst(player: EntityPlayer) = {
if (player.isSneaking) {
kill()
}
else if (!world.isRemote) {
def preparePowerUp() {
targetX = math.floor(posX).toFloat + 0.5f
targetY = math.floor(posY).toFloat + 0.5f
targetZ = math.floor(posZ).toFloat + 0.5f
@ -299,8 +297,14 @@ class Drone(val world: World) extends Entity(world) with MachineHost with intern
api.Network.joinNewNetwork(machine.node)
components.connectComponents()
machine.node.connect(control.node)
if (machine.isRunning) machine.stop()
else machine.start()
}
override def interactFirst(player: EntityPlayer) = {
if (player.isSneaking) {
kill()
}
else if (!world.isRemote) {
player.openGui(OpenComputers, GuiType.Drone.id, world, getEntityId, 0, 0)
}
true
}

View File

@ -8,6 +8,7 @@ import li.cil.oc.api
import li.cil.oc.api.machine.Machine
import li.cil.oc.common.PacketType
import li.cil.oc.common.component.TextBuffer
import li.cil.oc.common.entity.Drone
import li.cil.oc.common.tileentity._
import li.cil.oc.common.tileentity.traits.Computer
import li.cil.oc.common.tileentity.traits.TileEntity
@ -31,6 +32,7 @@ object PacketHandler extends CommonPacketHandler {
override def dispatch(p: PacketParser) {
p.packetType match {
case PacketType.ComputerPower => onComputerPower(p)
case PacketType.DronePower => onDronePower(p)
case PacketType.KeyDown => onKeyDown(p)
case PacketType.KeyUp => onKeyUp(p)
case PacketType.Clipboard => onClipboard(p)
@ -65,6 +67,20 @@ object PacketHandler extends CommonPacketHandler {
case _ => // Invalid packet.
}
def onDronePower(p: PacketParser) =
p.readEntity[Drone]() match {
case Some(drone) => p.player match {
case player: EntityPlayerMP =>
val power = p.readBoolean()
if (power) {
drone.preparePowerUp()
}
trySetComputerPower(drone.machine, power, player)
case _ =>
}
case _ => // Invalid packet.
}
private def trySetComputerPower(computer: Machine, value: Boolean, player: EntityPlayerMP) {
if (computer.canInteract(player.getCommandSenderName)) {
if (value) {

View File

@ -0,0 +1,39 @@
package li.cil.oc.util
/**
* https://gist.github.com/viktorklang/1057513
*/
trait ScalaEnum {
import java.util.concurrent.atomic.AtomicReference //Concurrency paranoia
type EnumVal <: Value //This is a type that needs to be found in the implementing class
private val _values = new AtomicReference(Vector[EnumVal]()) //Stores our enum values
//Adds an EnumVal to our storage, uses CCAS to make sure it's thread safe, returns the ordinal
private final def addEnumVal(newVal: EnumVal): Int = {
import _values.{get, compareAndSet => CAS}
val oldVec = get
val newVec = oldVec :+ newVal
if ((get eq oldVec) && CAS(oldVec, newVec))
newVec.indexWhere(_ eq newVal)
else
addEnumVal(newVal)
}
def values: Vector[EnumVal] = _values.get //Here you can get all the enums that exist for this type
//This is the trait that we need to extend our EnumVal type with, it does the book-keeping for us
protected trait Value { self: EnumVal => //Enforce that no one mixes in Value in a non-EnumVal type
final val ordinal = addEnumVal(this) //Adds the EnumVal and returns the ordinal
def name: String //All enum values should have a name
override def toString = name //And that name is used for the toString operation
override def equals(other: Any) = this eq other.asInstanceOf[AnyRef]
override def hashCode = 31 * (this.getClass.## + name.## + ordinal)
}
}