Changed the way upgrades on robots are rendered, now using an interface on items instead of item renderer. Closes #1038.

More flexible and should also work in MC1.8...
This commit is contained in:
Florian Nücke 2015-04-22 17:47:34 +02:00
parent 20239780e1
commit 9ac38ad1b2
8 changed files with 185 additions and 132 deletions

View File

@ -16,7 +16,7 @@ import li.cil.oc.api.detail.NetworkAPI;
*/
public class API {
public static final String ID_OWNER = "OpenComputers|Core";
public static final String VERSION = "5.2.0";
public static final String VERSION = "5.2.1";
public static DriverAPI driver = null;
public static FileSystemAPI fileSystem = null;

View File

@ -30,11 +30,11 @@ public interface Keyboard extends Environment, Persistable {
void setUsableOverride(UsabilityChecker callback);
/**
* Contract interface that has to implemented for usability check overides.
* Contract interface that has to implemented for usability check overrides.
*
* @see #setUsableOverride(li.cil.oc.api.component.Keyboard.UsabilityChecker)
*/
public static interface UsabilityChecker {
interface UsabilityChecker {
/**
* Whether the specified keyboard is usable by the specified player.
*

View File

@ -563,7 +563,7 @@ public interface TextBuffer extends ManagedEnvironment, Persistable {
/**
* Used when setting a buffer's maximum color depth.
*/
public static enum ColorDepth {
enum ColorDepth {
/**
* Monochrome color, black and white.
*/

View File

@ -0,0 +1,43 @@
package li.cil.oc.api.driver.item;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import li.cil.oc.api.event.RobotRenderEvent;
import li.cil.oc.api.internal.Robot;
import net.minecraft.item.ItemStack;
/**
* This interface can be implemented by items to allow custom rendering of
* upgrades installed in robots.
* <p/>
* Upgrades installed in a robot can have an external representation. This is
* achieved by implementing this interface on an item that serves as a
* renderable upgrade. When the robot is rendered, each equipped upgrade is
* checked for this interface, and if present, the {@link #render} method
* is called.
*/
public interface UpgradeRenderer {
/**
* Render the specified upgrade on a robot.
* <p/>
* The GL state has not been adjusted to the mount points position, so
* that you can perform rotations without having to revert the translation.
* It is your responsibility to position the rendered model to fit the
* specified mount point. The state will be such that the origin is the
* center of the robot. This is what the offset of the mount-point is
* relative to.
* <p/>
* If the stack cannot be rendered, simply do nothing. This way it's fine
* to implement this on a meta item.
* <p/>
* You usually won't need the robot parameter, but in case you <em>do</em>
* need some contextual information, this should provide you with anything
* you could need.
*
* @param stack the item stack of the upgrade to render.
* @param mountPoint the mount-point to render the upgrade at.
* @param robot the robot the upgrade is rendered on.
*/
@SideOnly(Side.CLIENT)
void render(ItemStack stack, RobotRenderEvent.MountPoint mountPoint, Robot robot);
}

View File

@ -5,11 +5,9 @@ import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.api.detail.ItemInfo
import li.cil.oc.client.KeyBindings
import li.cil.oc.client.Textures
import li.cil.oc.client.renderer.block.Print
import li.cil.oc.client.renderer.entity.DroneRenderer
import li.cil.oc.common.item.data.PrintData
import li.cil.oc.integration.opencomputers.Item
import li.cil.oc.util.Color
import li.cil.oc.util.ExtendedAABB
import li.cil.oc.util.RenderState
@ -19,7 +17,6 @@ import net.minecraft.client.renderer.entity.RenderItem
import net.minecraft.client.renderer.entity.RenderManager
import net.minecraft.client.renderer.texture.TextureMap
import net.minecraft.item.ItemStack
import net.minecraft.util.AxisAlignedBB
import net.minecraft.util.EnumChatFormatting
import net.minecraftforge.client.IItemRenderer
import net.minecraftforge.client.IItemRenderer.ItemRenderType
@ -32,9 +29,6 @@ object ItemRenderer extends IItemRenderer {
val renderItem = new RenderItem()
renderItem.setRenderManager(RenderManager.instance)
lazy val craftingUpgrade = api.Items.get(Constants.ItemName.CraftingUpgrade)
lazy val generatorUpgrade = api.Items.get(Constants.ItemName.GeneratorUpgrade)
lazy val inventoryUpgrade = api.Items.get(Constants.ItemName.InventoryUpgrade)
lazy val drone = api.Items.get(Constants.ItemName.Drone)
lazy val floppy = api.Items.get(Constants.ItemName.Floppy)
@ -43,21 +37,11 @@ object ItemRenderer extends IItemRenderer {
lazy val nullShape = new PrintData.Shape(ExtendedAABB.unitBounds, Settings.resourceDomain + ":White", Some(Color.Lime))
def bounds = AxisAlignedBB.getBoundingBox(-0.1, -0.1, -0.1, 0.1, 0.1, 0.1)
def isUpgrade(descriptor: ItemInfo) =
descriptor == craftingUpgrade ||
descriptor == generatorUpgrade ||
descriptor == inventoryUpgrade
def isFloppy(descriptor: ItemInfo) =
descriptor == floppy ||
descriptor == lootDisk
def isFloppy(descriptor: ItemInfo) = descriptor == floppy || descriptor == lootDisk
override def handleRenderType(stack: ItemStack, renderType: ItemRenderType) = {
val descriptor = api.Items.get(stack)
(renderType == ItemRenderType.EQUIPPED && isUpgrade(api.Items.get(stack))) ||
(renderType == ItemRenderType.INVENTORY && isFloppy(api.Items.get(stack))) ||
(renderType == ItemRenderType.INVENTORY && isFloppy(api.Items.get(stack))) ||
((renderType == ItemRenderType.INVENTORY || renderType == ItemRenderType.ENTITY || renderType == ItemRenderType.EQUIPPED || renderType == ItemRenderType.EQUIPPED_FIRST_PERSON) && descriptor == drone) ||
((renderType == ItemRenderType.INVENTORY || renderType == ItemRenderType.ENTITY || renderType == ItemRenderType.EQUIPPED || renderType == ItemRenderType.EQUIPPED_FIRST_PERSON) && api.Items.get(stack) == print)
}
@ -75,34 +59,8 @@ object ItemRenderer extends IItemRenderer {
val mc = Minecraft.getMinecraft
val tm = mc.getTextureManager
val descriptor = api.Items.get(stack)
if (isUpgrade(descriptor)) {
// Revert offset introduced by the render "helper".
GL11.glTranslatef(0.5f, 0.5f, 0.5f)
if (descriptor == api.Items.get(Constants.ItemName.CraftingUpgrade)) {
tm.bindTexture(Textures.upgradeCrafting)
drawSimpleBlock()
RenderState.checkError(getClass.getName + ".renderItem: crafting upgrade")
}
else if (descriptor == api.Items.get(Constants.ItemName.GeneratorUpgrade)) {
tm.bindTexture(Textures.upgradeGenerator)
drawSimpleBlock(if (Item.dataTag(stack).getInteger("remainingTicks") > 0) 0.5f else 0)
RenderState.checkError(getClass.getName + ".renderItem: generator upgrade")
}
else if (descriptor == api.Items.get(Constants.ItemName.InventoryUpgrade)) {
tm.bindTexture(Textures.upgradeInventory)
drawSimpleBlock()
RenderState.checkError(getClass.getName + ".renderItem: inventory upgrade")
}
}
else if (isFloppy(descriptor)) {
if (isFloppy(descriptor)) {
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS)
renderItem.renderItemIntoGUI(null, tm, stack, 0, 0)
val res = new ScaledResolution(mc, mc.displayWidth, mc.displayHeight)
@ -188,67 +146,6 @@ object ItemRenderer extends IItemRenderer {
RenderState.checkError("ItemRenderer.renderItem: leaving")
}
private def drawSimpleBlock(frontOffset: Float = 0) {
GL11.glBegin(GL11.GL_QUADS)
// Front.
GL11.glNormal3f(0, 0, 1)
GL11.glTexCoord2f(frontOffset, 0.5f)
GL11.glVertex3d(bounds.minX, bounds.minY, bounds.maxZ)
GL11.glTexCoord2f(frontOffset + 0.5f, 0.5f)
GL11.glVertex3d(bounds.maxX, bounds.minY, bounds.maxZ)
GL11.glTexCoord2f(frontOffset + 0.5f, 0)
GL11.glVertex3d(bounds.maxX, bounds.maxY, bounds.maxZ)
GL11.glTexCoord2f(frontOffset, 0)
GL11.glVertex3d(bounds.minX, bounds.maxY, bounds.maxZ)
// Top.
GL11.glNormal3f(0, 1, 0)
GL11.glTexCoord2f(1, 0.5f)
GL11.glVertex3d(bounds.maxX, bounds.maxY, bounds.maxZ)
GL11.glTexCoord2f(1, 1)
GL11.glVertex3d(bounds.maxX, bounds.maxY, bounds.minZ)
GL11.glTexCoord2f(0.5f, 1)
GL11.glVertex3d(bounds.minX, bounds.maxY, bounds.minZ)
GL11.glTexCoord2f(0.5f, 0.5f)
GL11.glVertex3d(bounds.minX, bounds.maxY, bounds.maxZ)
// Bottom.
GL11.glNormal3f(0, -1, 0)
GL11.glTexCoord2f(0.5f, 0.5f)
GL11.glVertex3d(bounds.minX, bounds.minY, bounds.maxZ)
GL11.glTexCoord2f(0.5f, 1)
GL11.glVertex3d(bounds.minX, bounds.minY, bounds.minZ)
GL11.glTexCoord2f(1, 1)
GL11.glVertex3d(bounds.maxX, bounds.minY, bounds.minZ)
GL11.glTexCoord2f(1, 0.5f)
GL11.glVertex3d(bounds.maxX, bounds.minY, bounds.maxZ)
// Left.
GL11.glNormal3f(1, 0, 0)
GL11.glTexCoord2f(0, 0.5f)
GL11.glVertex3d(bounds.maxX, bounds.maxY, bounds.maxZ)
GL11.glTexCoord2f(0, 1)
GL11.glVertex3d(bounds.maxX, bounds.minY, bounds.maxZ)
GL11.glTexCoord2f(0.5f, 1)
GL11.glVertex3d(bounds.maxX, bounds.minY, bounds.minZ)
GL11.glTexCoord2f(0.5f, 0.5f)
GL11.glVertex3d(bounds.maxX, bounds.maxY, bounds.minZ)
// Right.
GL11.glNormal3f(-1, 0, 0)
GL11.glTexCoord2f(0, 1)
GL11.glVertex3d(bounds.minX, bounds.minY, bounds.maxZ)
GL11.glTexCoord2f(0, 0.5f)
GL11.glVertex3d(bounds.minX, bounds.maxY, bounds.maxZ)
GL11.glTexCoord2f(0.5f, 0.5f)
GL11.glVertex3d(bounds.minX, bounds.maxY, bounds.minZ)
GL11.glTexCoord2f(0.5f, 1)
GL11.glVertex3d(bounds.minX, bounds.minY, bounds.minZ)
GL11.glEnd()
}
private def drawShape(shape: PrintData.Shape) {
val bounds = shape.bounds
val texture = Print.resolveTexture(shape.texture)

View File

@ -0,0 +1,109 @@
package li.cil.oc.client.renderer.item
import li.cil.oc.Constants
import li.cil.oc.api
import li.cil.oc.api.event.RobotRenderEvent.MountPoint
import li.cil.oc.client.Textures
import li.cil.oc.integration.opencomputers.Item
import li.cil.oc.util.RenderState
import net.minecraft.client.Minecraft
import net.minecraft.item.ItemStack
import net.minecraft.util.AxisAlignedBB
import org.lwjgl.opengl.GL11
object UpgradeRenderer {
lazy val craftingUpgrade = api.Items.get(Constants.ItemName.CraftingUpgrade)
lazy val generatorUpgrade = api.Items.get(Constants.ItemName.GeneratorUpgrade)
lazy val inventoryUpgrade = api.Items.get(Constants.ItemName.InventoryUpgrade)
def render(stack: ItemStack, mountPoint: MountPoint): Unit = {
val descriptor = api.Items.get(stack)
if (descriptor == api.Items.get(Constants.ItemName.CraftingUpgrade)) {
Minecraft.getMinecraft.getTextureManager.bindTexture(Textures.upgradeCrafting)
drawSimpleBlock(mountPoint)
RenderState.checkError(getClass.getName + ".renderItem: crafting upgrade")
}
else if (descriptor == api.Items.get(Constants.ItemName.GeneratorUpgrade)) {
Minecraft.getMinecraft.getTextureManager.bindTexture(Textures.upgradeGenerator)
drawSimpleBlock(mountPoint, if (Item.dataTag(stack).getInteger("remainingTicks") > 0) 0.5f else 0)
RenderState.checkError(getClass.getName + ".renderItem: generator upgrade")
}
else if (descriptor == api.Items.get(Constants.ItemName.InventoryUpgrade)) {
Minecraft.getMinecraft.getTextureManager.bindTexture(Textures.upgradeInventory)
drawSimpleBlock(mountPoint)
RenderState.checkError(getClass.getName + ".renderItem: inventory upgrade")
}
}
private val bounds = AxisAlignedBB.getBoundingBox(-0.1, -0.1, -0.1, 0.1, 0.1, 0.1)
private def drawSimpleBlock(mountPoint: MountPoint, frontOffset: Float = 0) {
GL11.glRotatef(mountPoint.rotation.getW, mountPoint.rotation.getX, mountPoint.rotation.getY, mountPoint.rotation.getZ)
GL11.glTranslatef(mountPoint.offset.getX, mountPoint.offset.getY, mountPoint.offset.getZ)
GL11.glBegin(GL11.GL_QUADS)
// Front.
GL11.glNormal3f(0, 0, 1)
GL11.glTexCoord2f(frontOffset, 0.5f)
GL11.glVertex3d(bounds.minX, bounds.minY, bounds.maxZ)
GL11.glTexCoord2f(frontOffset + 0.5f, 0.5f)
GL11.glVertex3d(bounds.maxX, bounds.minY, bounds.maxZ)
GL11.glTexCoord2f(frontOffset + 0.5f, 0)
GL11.glVertex3d(bounds.maxX, bounds.maxY, bounds.maxZ)
GL11.glTexCoord2f(frontOffset, 0)
GL11.glVertex3d(bounds.minX, bounds.maxY, bounds.maxZ)
// Top.
GL11.glNormal3f(0, 1, 0)
GL11.glTexCoord2f(1, 0.5f)
GL11.glVertex3d(bounds.maxX, bounds.maxY, bounds.maxZ)
GL11.glTexCoord2f(1, 1)
GL11.glVertex3d(bounds.maxX, bounds.maxY, bounds.minZ)
GL11.glTexCoord2f(0.5f, 1)
GL11.glVertex3d(bounds.minX, bounds.maxY, bounds.minZ)
GL11.glTexCoord2f(0.5f, 0.5f)
GL11.glVertex3d(bounds.minX, bounds.maxY, bounds.maxZ)
// Bottom.
GL11.glNormal3f(0, -1, 0)
GL11.glTexCoord2f(0.5f, 0.5f)
GL11.glVertex3d(bounds.minX, bounds.minY, bounds.maxZ)
GL11.glTexCoord2f(0.5f, 1)
GL11.glVertex3d(bounds.minX, bounds.minY, bounds.minZ)
GL11.glTexCoord2f(1, 1)
GL11.glVertex3d(bounds.maxX, bounds.minY, bounds.minZ)
GL11.glTexCoord2f(1, 0.5f)
GL11.glVertex3d(bounds.maxX, bounds.minY, bounds.maxZ)
// Left.
GL11.glNormal3f(1, 0, 0)
GL11.glTexCoord2f(0, 0.5f)
GL11.glVertex3d(bounds.maxX, bounds.maxY, bounds.maxZ)
GL11.glTexCoord2f(0, 1)
GL11.glVertex3d(bounds.maxX, bounds.minY, bounds.maxZ)
GL11.glTexCoord2f(0.5f, 1)
GL11.glVertex3d(bounds.maxX, bounds.minY, bounds.minZ)
GL11.glTexCoord2f(0.5f, 0.5f)
GL11.glVertex3d(bounds.maxX, bounds.maxY, bounds.minZ)
// Right.
GL11.glNormal3f(-1, 0, 0)
GL11.glTexCoord2f(0, 1)
GL11.glVertex3d(bounds.minX, bounds.minY, bounds.maxZ)
GL11.glTexCoord2f(0, 0.5f)
GL11.glVertex3d(bounds.minX, bounds.maxY, bounds.maxZ)
GL11.glTexCoord2f(0.5f, 0.5f)
GL11.glVertex3d(bounds.minX, bounds.maxY, bounds.minZ)
GL11.glTexCoord2f(0.5f, 1)
GL11.glVertex3d(bounds.minX, bounds.minY, bounds.minZ)
GL11.glEnd()
}
}

View File

@ -3,6 +3,7 @@ package li.cil.oc.client.renderer.tileentity
import com.google.common.base.Strings
import li.cil.oc.OpenComputers
import li.cil.oc.Settings
import li.cil.oc.api.driver.item.UpgradeRenderer
import li.cil.oc.api.event.RobotRenderEvent
import li.cil.oc.client.Textures
import li.cil.oc.common.EventHandler
@ -21,7 +22,6 @@ import net.minecraft.item.ItemBlock
import net.minecraft.tileentity.TileEntity
import net.minecraft.util.EnumChatFormatting
import net.minecraft.util.Vec3
import net.minecraftforge.client.IItemRenderer.ItemRenderType
import net.minecraftforge.client.IItemRenderer.ItemRenderType._
import net.minecraftforge.client.IItemRenderer.ItemRendererHelper._
import net.minecraftforge.client.MinecraftForgeClient
@ -121,7 +121,7 @@ object RobotRenderer extends TileEntitySpecialRenderer {
// Back.
mountPoints(0).offset.setX(0)
mountPoints(0).offset.setY(-0.2f)
mountPoints(0).offset.setY(-0.2f - offset)
mountPoints(0).offset.setZ(0.24f)
mountPoints(0).rotation.setX(0)
mountPoints(0).rotation.setY(1)
@ -129,7 +129,7 @@ object RobotRenderer extends TileEntitySpecialRenderer {
mountPoints(0).rotation.setW(180)
mountPoints(1).offset.setX(0)
mountPoints(1).offset.setY(0.2f + offset)
mountPoints(1).offset.setY(0.2f)
mountPoints(1).offset.setZ(0.24f)
mountPoints(1).rotation.setX(0)
mountPoints(1).rotation.setY(1)
@ -138,7 +138,7 @@ object RobotRenderer extends TileEntitySpecialRenderer {
// Front.
mountPoints(2).offset.setX(0)
mountPoints(2).offset.setY(-0.2f)
mountPoints(2).offset.setY(-0.2f - offset)
mountPoints(2).offset.setZ(0.24f)
mountPoints(2).rotation.setX(0)
mountPoints(2).rotation.setY(1)
@ -147,7 +147,7 @@ object RobotRenderer extends TileEntitySpecialRenderer {
// Left.
mountPoints(3).offset.setX(0)
mountPoints(3).offset.setY(-0.2f)
mountPoints(3).offset.setY(-0.2f - offset)
mountPoints(3).offset.setZ(0.24f)
mountPoints(3).rotation.setX(0)
mountPoints(3).rotation.setY(1)
@ -155,7 +155,7 @@ object RobotRenderer extends TileEntitySpecialRenderer {
mountPoints(3).rotation.setW(90)
mountPoints(4).offset.setX(0)
mountPoints(4).offset.setY(0.2f + offset)
mountPoints(4).offset.setY(0.2f)
mountPoints(4).offset.setZ(0.24f)
mountPoints(4).rotation.setX(0)
mountPoints(4).rotation.setY(1)
@ -164,7 +164,7 @@ object RobotRenderer extends TileEntitySpecialRenderer {
// Right.
mountPoints(5).offset.setX(0)
mountPoints(5).offset.setY(-0.2f)
mountPoints(5).offset.setY(-0.2f - offset)
mountPoints(5).offset.setZ(0.24f)
mountPoints(5).rotation.setX(0)
mountPoints(5).rotation.setY(1)
@ -172,7 +172,7 @@ object RobotRenderer extends TileEntitySpecialRenderer {
mountPoints(5).rotation.setW(-90)
mountPoints(6).offset.setX(0)
mountPoints(6).offset.setY(0.2f + offset)
mountPoints(6).offset.setY(0.2f)
mountPoints(6).offset.setZ(0.24f)
mountPoints(6).rotation.setX(0)
mountPoints(6).rotation.setY(1)
@ -401,22 +401,17 @@ object RobotRenderer extends TileEntitySpecialRenderer {
case _ =>
}
val stacks = (robot.componentSlots ++ robot.containerSlots).map(robot.getStackInSlot).filter(stack => stack != null && MinecraftForgeClient.getItemRenderer(stack, ItemRenderType.EQUIPPED) != null).padTo(mountPoints.length, null).take(mountPoints.length)
for ((stack, mountPoint) <- stacks.zip(mountPoints)) {
try {
if (stack != null && (stack.getItem.requiresMultipleRenderPasses() || MinecraftForgeClient.getRenderPass == 0)) {
val tint = stack.getItem.getColorFromItemStack(stack, MinecraftForgeClient.getRenderPass)
val r = ((tint >> 16) & 0xFF) / 255f
val g = ((tint >> 8) & 0xFF) / 255f
val b = ((tint >> 0) & 0xFF) / 255f
GL11.glColor4f(r, g, b, 1)
if (MinecraftForgeClient.getRenderPass == 0) {
val stacks = (robot.componentSlots ++ robot.containerSlots).map(robot.getStackInSlot).
filter(stack => stack != null && stack.getItem.isInstanceOf[UpgradeRenderer]).
take(mountPoints.length)
for ((stack, mountPoint) <- stacks.zip(mountPoints.take(stacks.length))) try stack.getItem match {
case renderer: UpgradeRenderer =>
GL11.glPushMatrix()
GL11.glTranslatef(0.5f, 0.5f, 0.5f)
GL11.glRotatef(mountPoint.rotation.getW, mountPoint.rotation.getX, mountPoint.rotation.getY, mountPoint.rotation.getZ)
GL11.glTranslatef(mountPoint.offset.getX, mountPoint.offset.getY, mountPoint.offset.getZ)
RenderManager.instance.itemRenderer.renderItem(Minecraft.getMinecraft.thePlayer, stack, MinecraftForgeClient.getRenderPass)
renderer.render(stack, mountPoint, robot)
GL11.glPopMatrix()
}
case _ =>
}
catch {
case e: Throwable =>

View File

@ -8,6 +8,10 @@ import cpw.mods.fml.relauncher.SideOnly
import li.cil.oc.CreativeTab
import li.cil.oc.OpenComputers
import li.cil.oc.Settings
import li.cil.oc.api.driver
import li.cil.oc.api.event.RobotRenderEvent.MountPoint
import li.cil.oc.api.internal.Robot
import li.cil.oc.client.renderer.item.UpgradeRenderer
import li.cil.oc.common.tileentity
import li.cil.oc.util.BlockPosition
import net.minecraft.client.renderer.texture.IIconRegister
@ -34,7 +38,7 @@ object Delegator {
else None
}
class Delegator extends Item {
class Delegator extends Item with driver.item.UpgradeRenderer {
setHasSubtypes(true)
setCreativeTab(CreativeTab)
setUnlocalizedName("oc.multi")
@ -247,4 +251,9 @@ class Delegator extends Item {
}
override def toString = getUnlocalizedName
// ----------------------------------------------------------------------- //
@SideOnly(Side.CLIENT)
def render(stack: ItemStack, mountPoint: MountPoint, robot: Robot): Unit = UpgradeRenderer.render(stack, mountPoint)
}