mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-12 16:57:32 -04:00
Scratch that and let's do it again. Might silence the voices in my head (aka @Vexatos).
Changed robot upgrade rendering to allow being picky. A bit more overhead, but hey, what's a few sets among friends?
This commit is contained in:
parent
fda54f2f6f
commit
1528a6ee24
@ -6,6 +6,8 @@ import li.cil.oc.api.event.RobotRenderEvent;
|
||||
import li.cil.oc.api.internal.Robot;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* This interface can be implemented by items to allow custom rendering of
|
||||
* upgrades installed in robots.
|
||||
@ -19,38 +21,32 @@ import net.minecraft.item.ItemStack;
|
||||
@SideOnly(Side.CLIENT)
|
||||
public interface UpgradeRenderer {
|
||||
/**
|
||||
* The priority with which to render this upgrade.
|
||||
* Returns which mount point this renderer wants to render the specified
|
||||
* upgrade in.
|
||||
* <p/>
|
||||
* Upgrades with a higher priority are preferred for rendering over other
|
||||
* upgrades. Upgrades with higher priorities will be rendered in the top
|
||||
* slots, i.e. the assigned slot order is top then bottom.
|
||||
* This method is used to determine which upgrade is rendered where, and is
|
||||
* called for every installed, renderable upgrade. The available mount
|
||||
* point names are defined in {@link MountPointName}, with the two special
|
||||
* values <tt>None</tt> and <tt>Any</tt>.
|
||||
* <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.
|
||||
* <tt>None</tt> means that the upgrade should not be rendered at all. This
|
||||
* can be the case when there is no slot remaining that the upgrade may be
|
||||
* rendered in. Returning <tt>null</tt> is equivalent to returning <tt>None</tt>.
|
||||
* <p/>
|
||||
* <tt>Any</tt> means that the upgrade doesn't really care where it's being
|
||||
* rendered. Mount points not assigned by another upgrade preferring to be
|
||||
* rendered in it will be assigned to such upgrades in the order they are
|
||||
* installed in the robot.
|
||||
* <p/>
|
||||
* Returning a mount point not in the list of available mount points will
|
||||
* be equivalent to returning <tt>None</tt>.
|
||||
*
|
||||
* @param stack the item stack of the upgrade to render.
|
||||
* @param robot the robot the upgrade is rendered on.
|
||||
* @return the priority with which to render the upgrade.
|
||||
* @param stack the item stack of the upgrade to render.
|
||||
* @param robot the robot the upgrade is rendered on.
|
||||
* @param availableMountPoints the mount points available for rendering in.
|
||||
* @return the mount point to reserve for the upgrade.
|
||||
*/
|
||||
int priority(ItemStack stack, Robot robot);
|
||||
|
||||
/**
|
||||
* Whether the upgrade can be rendered in the specified mount point.
|
||||
* <p/>
|
||||
* This is used to determine whether an upgrade can be rendered in a
|
||||
* specific mount point, or not. Note that if the upgrade refuses to
|
||||
* be rendered in the offered mount point, it will not be rendered at all,
|
||||
* i.e. it will not be offered another mount point. To give the upgrade
|
||||
* a better chance to get a usable mount point, specify an appropriate
|
||||
* priority via {@link #priority}.
|
||||
*
|
||||
* @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.
|
||||
* @return whether the upgrade can be rendered in the specified mount point.
|
||||
*/
|
||||
boolean canRender(ItemStack stack, RobotRenderEvent.MountPoint mountPoint, Robot robot);
|
||||
String computePreferredMountPoint(ItemStack stack, Robot robot, Set<String> availableMountPoints);
|
||||
|
||||
/**
|
||||
* Render the specified upgrade on a robot.
|
||||
@ -63,7 +59,8 @@ public interface UpgradeRenderer {
|
||||
* relative to.
|
||||
* <p/>
|
||||
* If the stack cannot be rendered, the renderer should indicate so in
|
||||
* {@link #canRender}, otherwise it will still consume a mount point.
|
||||
* {@link #computePreferredMountPoint}, otherwise it will still consume a mount
|
||||
* point.
|
||||
* <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
|
||||
@ -75,4 +72,23 @@ public interface UpgradeRenderer {
|
||||
* @param pt partial tick time, e.g. for animations.
|
||||
*/
|
||||
void render(ItemStack stack, RobotRenderEvent.MountPoint mountPoint, Robot robot, float pt);
|
||||
|
||||
/**
|
||||
* Mount point names for {@link #computePreferredMountPoint}.
|
||||
*/
|
||||
final class MountPointName {
|
||||
public static final String None = "none";
|
||||
public static final String Any = "any";
|
||||
|
||||
public static final String TopLeft = "top_left";
|
||||
public static final String TopRight = "top_right";
|
||||
public static final String TopBack = "top_back";
|
||||
public static final String BottomLeft = "bottom_left";
|
||||
public static final String BottomRight = "bottom_right";
|
||||
public static final String BottomBack = "bottom_back";
|
||||
public static final String BottomFront = "bottom_front";
|
||||
|
||||
private MountPointName() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package li.cil.oc.client.renderer.item
|
||||
|
||||
import li.cil.oc.Constants
|
||||
import li.cil.oc.api
|
||||
import li.cil.oc.api.driver.item.UpgradeRenderer.MountPointName
|
||||
import li.cil.oc.api.event.RobotRenderEvent.MountPoint
|
||||
import li.cil.oc.client.Textures
|
||||
import li.cil.oc.integration.opencomputers.Item
|
||||
@ -16,12 +17,15 @@ object UpgradeRenderer {
|
||||
lazy val generatorUpgrade = api.Items.get(Constants.ItemName.GeneratorUpgrade)
|
||||
lazy val inventoryUpgrade = api.Items.get(Constants.ItemName.InventoryUpgrade)
|
||||
|
||||
def priority(stack: ItemStack): Int = {
|
||||
def preferredMountPoint(stack: ItemStack, availableMountPoints: java.util.Set[String]): String = {
|
||||
val descriptor = api.Items.get(stack)
|
||||
|
||||
if (descriptor == craftingUpgrade) 5
|
||||
else if (descriptor == generatorUpgrade) 0
|
||||
else 10
|
||||
if (descriptor == craftingUpgrade || descriptor == generatorUpgrade || descriptor == inventoryUpgrade) {
|
||||
if (descriptor == generatorUpgrade && availableMountPoints.contains(MountPointName.BottomBack)) MountPointName.BottomBack
|
||||
else if (descriptor == inventoryUpgrade && availableMountPoints.contains(MountPointName.TopBack)) MountPointName.TopBack
|
||||
else MountPointName.Any
|
||||
}
|
||||
else MountPointName.None
|
||||
}
|
||||
|
||||
def canRender(stack: ItemStack): Boolean = {
|
||||
|
@ -4,6 +4,7 @@ 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.driver.item.UpgradeRenderer.MountPointName
|
||||
import li.cil.oc.api.event.RobotRenderEvent
|
||||
import li.cil.oc.client.Textures
|
||||
import li.cil.oc.common.EventHandler
|
||||
@ -19,6 +20,7 @@ import net.minecraft.client.renderer.entity.RendererLivingEntity
|
||||
import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer
|
||||
import net.minecraft.init.Items
|
||||
import net.minecraft.item.ItemBlock
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.tileentity.TileEntity
|
||||
import net.minecraft.util.EnumChatFormatting
|
||||
import net.minecraft.util.Vec3
|
||||
@ -30,11 +32,24 @@ import net.minecraftforge.common.util.ForgeDirection
|
||||
import org.lwjgl.opengl.GL11
|
||||
import org.lwjgl.opengl.GL12
|
||||
|
||||
import scala.collection.convert.WrapAsJava._
|
||||
import scala.collection.mutable
|
||||
|
||||
object RobotRenderer extends TileEntitySpecialRenderer {
|
||||
private val displayList = GLAllocation.generateDisplayLists(2)
|
||||
|
||||
private val mountPoints = Array.fill(7)(new RobotRenderEvent.MountPoint())
|
||||
|
||||
private val slotNameMapping = Map(
|
||||
UpgradeRenderer.MountPointName.TopLeft -> 0,
|
||||
UpgradeRenderer.MountPointName.TopRight -> 1,
|
||||
UpgradeRenderer.MountPointName.TopBack -> 2,
|
||||
UpgradeRenderer.MountPointName.BottomLeft -> 3,
|
||||
UpgradeRenderer.MountPointName.BottomRight -> 4,
|
||||
UpgradeRenderer.MountPointName.BottomBack -> 5,
|
||||
UpgradeRenderer.MountPointName.BottomFront -> 6
|
||||
)
|
||||
|
||||
private val gap = 1.0f / 28.0f
|
||||
private val gt = 0.5f + gap
|
||||
private val gb = 0.5f - gap
|
||||
@ -405,20 +420,31 @@ object RobotRenderer extends TileEntitySpecialRenderer {
|
||||
}
|
||||
|
||||
if (MinecraftForgeClient.getRenderPass == 0) {
|
||||
var filterMount = 0
|
||||
//noinspection SortFilter We need to sort before we filter, because the filter is index sensitive.
|
||||
val stacks = (robot.componentSlots ++ robot.containerSlots).map(robot.getStackInSlot).
|
||||
collect { case stack if stack != null && stack.getItem.isInstanceOf[UpgradeRenderer] => (stack, stack.getItem.asInstanceOf[UpgradeRenderer]) }.
|
||||
sortBy { case (stack, renderer) => -renderer.priority(stack, robot) }.
|
||||
filter {
|
||||
case (stack, renderer) if filterMount < mountPoints.length && renderer.canRender(stack, mountPoints(filterMount), robot) =>
|
||||
filterMount += 1
|
||||
true
|
||||
case _ => false
|
||||
lazy val availableSlots = slotNameMapping.keys.to[mutable.Set]
|
||||
lazy val wildcardRenderers = mutable.Buffer.empty[(ItemStack, UpgradeRenderer)]
|
||||
lazy val slotMapping = Array.fill(mountPoints.length)(null: (ItemStack, UpgradeRenderer))
|
||||
|
||||
val renderers = (robot.componentSlots ++ robot.containerSlots).map(robot.getStackInSlot).
|
||||
collect { case stack if stack != null && stack.getItem.isInstanceOf[UpgradeRenderer] => (stack, stack.getItem.asInstanceOf[UpgradeRenderer]) }
|
||||
|
||||
for ((stack, renderer) <- renderers) {
|
||||
val preferredSlot = renderer.computePreferredMountPoint(stack, robot, availableSlots)
|
||||
if (availableSlots.remove(preferredSlot)) {
|
||||
slotMapping(slotNameMapping(preferredSlot)) = (stack, renderer)
|
||||
}
|
||||
else if (preferredSlot == MountPointName.Any) {
|
||||
wildcardRenderers += ((stack, renderer))
|
||||
}
|
||||
}
|
||||
|
||||
val minLength = math.min(mountPoints.length, stacks.length)
|
||||
for (((stack, renderer), mountPoint) <- (stacks.take(minLength), mountPoints.take(minLength)).zipped) try {
|
||||
var firstEmpty = slotMapping.indexOf(null)
|
||||
for (entry <- wildcardRenderers if firstEmpty >= 0) {
|
||||
slotMapping(firstEmpty) = entry
|
||||
firstEmpty = slotMapping.indexOf(null)
|
||||
}
|
||||
|
||||
for ((info, mountPoint) <- (slotMapping, mountPoints).zipped if info != null) try {
|
||||
val (stack, renderer) = info
|
||||
GL11.glPushMatrix()
|
||||
GL11.glTranslatef(0.5f, 0.5f, 0.5f)
|
||||
renderer.render(stack, mountPoint, robot, f)
|
||||
|
@ -254,9 +254,7 @@ class Delegator extends Item with driver.item.UpgradeRenderer {
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
def priority(stack: ItemStack, robot: Robot): Int = UpgradeRenderer.priority(stack)
|
||||
override def computePreferredMountPoint(stack: ItemStack, robot: Robot, availableMountPoints: util.Set[String]): String = UpgradeRenderer.preferredMountPoint(stack, availableMountPoints)
|
||||
|
||||
def canRender(stack: ItemStack, mountPoint: MountPoint, robot: Robot): Boolean = UpgradeRenderer.canRender(stack)
|
||||
|
||||
def render(stack: ItemStack, mountPoint: MountPoint, robot: Robot, pt: Float): Unit = UpgradeRenderer.render(stack, mountPoint)
|
||||
override def render(stack: ItemStack, mountPoint: MountPoint, robot: Robot, pt: Float): Unit = UpgradeRenderer.render(stack, mountPoint)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user