package li.cil.oc.api.driver.item;
import li.cil.oc.api.event.RobotRenderEvent;
import li.cil.oc.api.internal.Robot;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import java.util.Set;
/**
* 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.
* <p/>
* Note that these methods are only ever called on the client side.
*/
public interface UpgradeRenderer {
/**
* Returns which mount point this renderer wants to render the specified
* upgrade in.
* <p/>
* 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/>
* <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.
* @param availableMountPoints the mount points available for rendering in.
* @return the mount point to reserve for the upgrade.
*/
String computePreferredMountPoint(ItemStack stack, Robot robot, Set<String> availableMountPoints);
/**
* 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, the renderer should indicate so in
* {@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
* 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.
* @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() {
}
}
}