diff --git a/assets/opencomputers/textures/items/upgrade_generator_equipped.png b/assets/opencomputers/textures/items/upgrade_generator_equipped.png new file mode 100644 index 000000000..7c810babf Binary files /dev/null and b/assets/opencomputers/textures/items/upgrade_generator_equipped.png differ diff --git a/li/cil/oc/client/PacketHandler.scala b/li/cil/oc/client/PacketHandler.scala index 44eab9c83..8c6168dd6 100644 --- a/li/cil/oc/client/PacketHandler.scala +++ b/li/cil/oc/client/PacketHandler.scala @@ -32,6 +32,7 @@ class PacketHandler extends CommonPacketHandler { case PacketType.RobotAnimateSwing => onRobotAnimateSwing(p) case PacketType.RobotAnimateTurn => onRobotAnimateTurn(p) case PacketType.RobotEquippedItemChange => onRobotEquippedItemChange(p) + case PacketType.RobotEquippedUpgradeChange => onRobotEquippedUpgradeChange(p) case PacketType.RobotMove => onRobotMove(p) case PacketType.RobotSelectedSlotChange => onRobotSelectedSlotChange(p) case PacketType.RobotXp => onRobotXp(p) @@ -120,6 +121,12 @@ class PacketHandler extends CommonPacketHandler { case _ => // Invalid packet. } + def onRobotEquippedUpgradeChange(p: PacketParser) = + p.readTileEntity[RobotProxy]() match { + case Some(t) => t.robot.equippedUpgrade = Option(p.readItemStack()) + case _ => // Invalid packet. + } + def onRobotMove(p: PacketParser) = p.readTileEntity[RobotProxy]() match { case Some(t) => t.robot.move(p.readDirection()) diff --git a/li/cil/oc/client/Proxy.scala b/li/cil/oc/client/Proxy.scala index 8ead249db..3ac15e079 100644 --- a/li/cil/oc/client/Proxy.scala +++ b/li/cil/oc/client/Proxy.scala @@ -7,10 +7,12 @@ import cpw.mods.fml.common.registry.TickRegistry import cpw.mods.fml.relauncher.Side import li.cil.oc.client.renderer.WirelessNetworkDebugRenderer import li.cil.oc.client.renderer.block.BlockRenderer +import li.cil.oc.client.renderer.item.UpgradeRenderer import li.cil.oc.client.renderer.tileentity._ import li.cil.oc.common.tileentity import li.cil.oc.common.{Proxy => CommonProxy} -import li.cil.oc.{Settings, OpenComputers} +import li.cil.oc.{Items, Settings, OpenComputers} +import net.minecraftforge.client.MinecraftForgeClient import net.minecraftforge.common.MinecraftForge private[oc] class Proxy extends CommonProxy { @@ -29,6 +31,8 @@ private[oc] class Proxy extends CommonProxy { ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Screen], ScreenRenderer) TickRegistry.registerTickHandler(ScreenRenderer, Side.CLIENT) + MinecraftForgeClient.registerItemRenderer(Items.multi.itemID, UpgradeRenderer) + MinecraftForge.EVENT_BUS.register(gui.Icons) } diff --git a/li/cil/oc/client/renderer/item/UpgradeRenderer.scala b/li/cil/oc/client/renderer/item/UpgradeRenderer.scala new file mode 100644 index 000000000..32d110fa0 --- /dev/null +++ b/li/cil/oc/client/renderer/item/UpgradeRenderer.scala @@ -0,0 +1,72 @@ +package li.cil.oc.client.renderer.item + +import li.cil.oc.{Settings, Items} +import net.minecraft.client.Minecraft +import net.minecraft.client.renderer.Tessellator +import net.minecraft.item.ItemStack +import net.minecraft.util.{ResourceLocation, AxisAlignedBB} +import net.minecraftforge.client.IItemRenderer +import net.minecraftforge.client.IItemRenderer.{ItemRendererHelper, ItemRenderType} +import org.lwjgl.opengl.GL11 + +object UpgradeRenderer extends IItemRenderer { + def handleRenderType(item: ItemStack, renderType: ItemRenderType) = { + Items.multi.subItem(item) match { + case Some(subItem) if subItem == Items.generator => renderType == ItemRenderType.EQUIPPED + case _ => false + } + } + + def shouldUseRenderHelper(renderType: ItemRenderType, item: ItemStack, helper: ItemRendererHelper) = helper == ItemRendererHelper.EQUIPPED_BLOCK + + def renderItem(renderType: ItemRenderType, item: ItemStack, data: AnyRef*) { + val tm = Minecraft.getMinecraft.getTextureManager + GL11.glTranslatef(0.5f, 0.5f, 0.5f) + val t = Tessellator.instance + + Items.multi.subItem(item) match { + case Some(subItem) if subItem == Items.generator => + // TODO display lists? + val onOffset = if (true) 0.5 else 0 + val b = AxisAlignedBB.getAABBPool.getAABB(0.4, 0.2, 0.16, 0.6, 0.4, 0.36) + tm.bindTexture(new ResourceLocation(Settings.resourceDomain, "textures/items/upgrade_generator_equipped.png")) + + // Back. + t.startDrawingQuads() + t.addVertexWithUV(b.minX, b.minY, b.minZ, onOffset, 0.5) + t.addVertexWithUV(b.minX, b.maxY, b.minZ, onOffset, 0) + t.addVertexWithUV(b.maxX, b.maxY, b.minZ, onOffset + 0.5, 0) + t.addVertexWithUV(b.maxX, b.minY, b.minZ, onOffset + 0.5, 0.5) + t.setNormal(0, 0, -1) + t.draw() + + // Bottom. + t.startDrawingQuads() + t.addVertexWithUV(b.minX, b.minY, b.minZ, 0.5, 0.5) + t.addVertexWithUV(b.maxX, b.minY, b.minZ, 1, 0.5) + t.addVertexWithUV(b.maxX, b.minY, b.maxZ, 1, 1) + t.addVertexWithUV(b.minX, b.minY, b.maxZ, 0.5, 1) + t.setNormal(0, -1, 0) + t.draw() + + // Left. + t.startDrawingQuads() + t.addVertexWithUV(b.maxX, b.minY, b.minZ, 0, 1) + t.addVertexWithUV(b.maxX, b.maxY, b.minZ, 0, 0.5) + t.addVertexWithUV(b.maxX, b.maxY, b.maxZ, 0.5, 0.5) + t.addVertexWithUV(b.maxX, b.minY, b.maxZ, 0.5, 1) + t.setNormal(1, 0, 0) + t.draw() + + // Right. + t.startDrawingQuads() + t.addVertexWithUV(b.minX, b.minY, b.minZ, 0, 1) + t.addVertexWithUV(b.minX, b.minY, b.maxZ, 0.5, 1) + t.addVertexWithUV(b.minX, b.maxY, b.maxZ, 0.5, 0.5) + t.addVertexWithUV(b.minX, b.maxY, b.minZ, 0, 0.5) + t.setNormal(-1, 0, 0) + t.draw() + case _ => + } + } +} diff --git a/li/cil/oc/client/renderer/tileentity/RobotRenderer.scala b/li/cil/oc/client/renderer/tileentity/RobotRenderer.scala index 989872c2a..f86f420e4 100644 --- a/li/cil/oc/client/renderer/tileentity/RobotRenderer.scala +++ b/li/cil/oc/client/renderer/tileentity/RobotRenderer.scala @@ -9,6 +9,7 @@ import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer import net.minecraft.client.renderer.{Tessellator, GLAllocation} import net.minecraft.tileentity.TileEntity import net.minecraft.util.{Vec3, ResourceLocation} +import net.minecraftforge.client.IItemRenderer.ItemRenderType import net.minecraftforge.client.MinecraftForgeClient import net.minecraftforge.common.ForgeDirection import org.lwjgl.opengl.GL11 @@ -217,6 +218,7 @@ object RobotRenderer extends TileEntitySpecialRenderer { robot.equippedItem match { case Some(stack) => + GL11.glPushMatrix() GL11.glTranslatef(0.1f, 0.25f, 0.75f) GL11.glScalef(0.4f, 0.4f, -0.4f) if (robot.isAnimatingSwing) { @@ -225,6 +227,7 @@ object RobotRenderer extends TileEntitySpecialRenderer { } GL11.glRotatef(-30, 1, 0, 0) GL11.glRotatef(40, 0, 1, 0) + GL11.glDisable(GL11.GL_CULL_FACE) try { RenderManager.instance.itemRenderer.renderItem(robot.player(), stack, MinecraftForgeClient.getRenderPass) } @@ -233,6 +236,23 @@ object RobotRenderer extends TileEntitySpecialRenderer { OpenComputers.log.log(Level.WARNING, "Failed rendering equipped item.", e) robot.equippedItem = None } + GL11.glEnable(GL11.GL_CULL_FACE) + GL11.glPopMatrix() + case _ => + } + + robot.equippedUpgrade match { + case Some(stack) => + try { + if (MinecraftForgeClient.getItemRenderer(stack, ItemRenderType.EQUIPPED) != null) { + RenderManager.instance.itemRenderer.renderItem(robot.player(), stack, MinecraftForgeClient.getRenderPass, ItemRenderType.EQUIPPED) + } + } + catch { + case e: Throwable => + OpenComputers.log.log(Level.WARNING, "Failed rendering equipped upgrade.", e) + robot.equippedUpgrade = None + } case _ => } diff --git a/li/cil/oc/common/PacketType.scala b/li/cil/oc/common/PacketType.scala index 8d3f95a29..c8a8a14c3 100644 --- a/li/cil/oc/common/PacketType.scala +++ b/li/cil/oc/common/PacketType.scala @@ -12,6 +12,7 @@ object PacketType extends Enumeration { RobotAnimateSwing, RobotAnimateTurn, RobotEquippedItemChange, + RobotEquippedUpgradeChange, RobotMove, RobotSelectedSlotChange, RobotXp, diff --git a/li/cil/oc/common/tileentity/Robot.scala b/li/cil/oc/common/tileentity/Robot.scala index 7bd9d199e..dc305e119 100644 --- a/li/cil/oc/common/tileentity/Robot.scala +++ b/li/cil/oc/common/tileentity/Robot.scala @@ -66,6 +66,8 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with ISidedInventory w var equippedItem: Option[ItemStack] = None + var equippedUpgrade: Option[ItemStack] = None + var animationTicksLeft = 0 var animationTicksTotal = 0 @@ -332,6 +334,9 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with ISidedInventory w if (nbt.hasKey("equipped")) { equippedItem = Option(ItemStack.loadItemStackFromNBT(nbt.getCompoundTag("equipped"))) } + if (nbt.hasKey("upgrade")) { + equippedUpgrade = Option(ItemStack.loadItemStackFromNBT(nbt.getCompoundTag("upgrade"))) + } xp = nbt.getDouble(Settings.namespace + "xp") updateXpInfo() animationTicksTotal = nbt.getInteger("animationTicksTotal") @@ -351,6 +356,9 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with ISidedInventory w if (getStackInSlot(0) != null) { nbt.setNewCompoundTag("equipped", getStackInSlot(0).writeToNBT) } + if (getStackInSlot(3) != null) { + nbt.setNewCompoundTag("upgrade", getStackInSlot(3).writeToNBT) + } nbt.setDouble(Settings.namespace + "xp", xp) if (isAnimatingMove || isAnimatingSwing || isAnimatingTurn) { nbt.setInteger("animationTicksTotal", animationTicksTotal) @@ -389,11 +397,14 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with ISidedInventory w override protected def onItemRemoved(slot: Int, stack: ItemStack) { super.onItemRemoved(slot, stack) if (isServer) { - if (slot == 0) { + if (isToolSlot(slot)) { player_.getAttributeMap.removeAttributeModifiers(stack.getAttributeModifiers) ServerPacketSender.sendRobotEquippedItemChange(this, null) } - else if (slot >= actualSlot(0)) { + if (isUpgradeSlot(slot)) { + ServerPacketSender.sendRobotEquippedUpgradeChange(this, null) + } + if (isInventorySlot(slot)) { computer.signal("inventory_changed", Int.box(slot - actualSlot(0) + 1)) } } @@ -401,14 +412,17 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with ISidedInventory w override protected def onItemAdded(slot: Int, stack: ItemStack) { if (isServer) { - if (slot == 0) { + if (isToolSlot(slot)) { player_.getAttributeMap.applyAttributeModifiers(stack.getAttributeModifiers) - ServerPacketSender.sendRobotEquippedItemChange(this, getStackInSlot(0)) + ServerPacketSender.sendRobotEquippedItemChange(this, getStackInSlot(slot)) } - else if (isComponentSlot(slot)) { + if (isUpgradeSlot(slot)) { + ServerPacketSender.sendRobotEquippedUpgradeChange(this, getStackInSlot(slot)) + } + if (isComponentSlot(slot)) { super.onItemAdded(slot, stack) } - else if (slot >= actualSlot(0)) { + if (isInventorySlot(slot)) { computer.signal("inventory_changed", Int.box(slot - actualSlot(0) + 1)) } } @@ -416,6 +430,12 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with ISidedInventory w override protected def isComponentSlot(slot: Int) = slot > 0 && slot < actualSlot(0) + private def isInventorySlot(slot: Int) = slot >= actualSlot(0) + + private def isToolSlot(slot: Int) = slot == 0 + + private def isUpgradeSlot(slot: Int) = slot == 3 + // ----------------------------------------------------------------------- // override def installedMemory = 64 * 1024 diff --git a/li/cil/oc/server/PacketSender.scala b/li/cil/oc/server/PacketSender.scala index afc17e750..66be4fe86 100644 --- a/li/cil/oc/server/PacketSender.scala +++ b/li/cil/oc/server/PacketSender.scala @@ -123,6 +123,15 @@ object PacketSender { pb.sendToNearbyPlayers(t) } + def sendRobotEquippedUpgradeChange(t: Robot, stack: ItemStack) { + val pb = new PacketBuilder(PacketType.RobotEquippedUpgradeChange) + + pb.writeTileEntity(t.proxy) + pb.writeItemStack(stack) + + pb.sendToNearbyPlayers(t) + } + def sendRobotSelectedSlotChange(t: Robot) { val pb = new PacketBuilder(PacketType.RobotSelectedSlotChange)