package de.cowtipper.cowlection.util;
import de.cowtipper.cowlection.config.MooConfig;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.Gui;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.ScaledResolution;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.inventory.Slot;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.common.ForgeVersion;
import net.minecraftforge.fml.client.config.GuiUtils;
import net.minecraftforge.fml.relauncher.ReflectionHelper;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.GL11;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public final class GuiHelper extends GuiScreen {
private static GuiHelper instance;
private FontRenderer fontRendererAscii;
private GuiHelper() {
this.mc = Minecraft.getMinecraft();
this.fontRendererObj = mc.fontRendererObj;
if (this.fontRendererObj.getCharWidth('x') != this.fontRendererObj.getCharWidth('·')) {
// we're not using default font (x and · should be the same width) - could be unicode font or a custom font
this.fontRendererAscii = new FontRenderer(mc.gameSettings, new ResourceLocation("textures/font/ascii.png"), mc.renderEngine, false);
this.fontRendererAscii.onResourceManagerReload(null); // load font widths
}
this.itemRender = mc.getRenderItem();
}
private static GuiHelper getInstance() {
if (instance == null) {
instance = new GuiHelper();
}
return instance;
}
public static Slot getSlotUnderMouse(GuiContainer guiContainer) {
try {
return ReflectionHelper.getPrivateValue(GuiContainer.class, guiContainer, "theSlot", "field_147006_u");
} catch (ReflectionHelper.UnableToAccessFieldException e) {
e.printStackTrace();
return null;
}
}
/**
* Draw a 1 pixel wide horizontal line. Args: startX, endX, y, color
*/
public static void drawThinHorizontalLine(int startX, int endX, int y, int color) {
if (endX < startX) {
int i = startX;
startX = endX;
endX = i;
}
GlStateManager.pushMatrix();
int scaleDivisor = 2;
GlStateManager.scale(1f / scaleDivisor, 1f / scaleDivisor, 0);
Gui.drawRect(startX * scaleDivisor, y * scaleDivisor, (endX + 1) * scaleDivisor, y * scaleDivisor + 1, color);
GlStateManager.popMatrix();
}
/**
* Draws a sprite from assets/textures/gui/container/stats_icons.png
*
* from: GuiStats#drawSprite
*/
public static void drawSprite(int x, int y, int width, int height, float zLevel) {
GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
Minecraft.getMinecraft().getTextureManager().bindTexture(statIcons);
float magicNumber = 0.0078125F;
int iconSize = 18;
Tessellator tessellator = Tessellator.getInstance();
WorldRenderer worldrenderer = tessellator.getWorldRenderer();
worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX);
worldrenderer.pos(x, y + iconSize, zLevel).tex((float) (width) * magicNumber, (float) (height + iconSize) * magicNumber).endVertex();
worldrenderer.pos(x + iconSize, y + iconSize, zLevel).tex((float) (width + iconSize) * magicNumber, (float) (height + iconSize) * magicNumber).endVertex();
worldrenderer.pos(x + iconSize, y, zLevel).tex((float) (width + iconSize) * magicNumber, (float) (height) * magicNumber).endVertex();
worldrenderer.pos(x, y, zLevel).tex((float) (width) * magicNumber, (float) (height) * magicNumber).endVertex();
tessellator.draw();
}
public static void drawHoveringTextWithGraph(List toolTip) {
int mouseX = Mouse.getX() * getInstance().width / getInstance().mc.displayWidth;
int mouseY = getInstance().height - Mouse.getY() * getInstance().height / getInstance().mc.displayHeight - 1;
ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
getInstance().width = scaledResolution.getScaledWidth();
getInstance().height = scaledResolution.getScaledHeight();
getInstance().drawHoveringText(toolTip, mouseX, mouseY, scaledResolution.getScaledWidth(), scaledResolution.getScaledHeight(), -1, true);
}
public static void drawHoveringText(List textLines, int mouseX, int mouseY, int screenWidth, int screenHeight, int maxTextWidth) {
if (ForgeVersion.getBuildVersion() < 1808) {
// we're running a forge version from before 24 March 2016 (http://files.minecraftforge.net/maven/net/minecraftforge/forge/index_1.8.9.html for reference)
// using mc built-in method
getInstance().width = screenWidth;
getInstance().height = screenHeight;
getInstance().drawHoveringText(textLines, mouseX, mouseY, screenWidth, screenHeight, maxTextWidth, false);
} else {
// we're on a newer forge version, so we can use the improved tooltip rendering directly added in 1.8.9-11.15.1.1808 (released 03/24/16 09:25 PM) in this pull request: https://github.com/MinecraftForge/MinecraftForge/pull/2649
GuiUtils.drawHoveringText(textLines, mouseX, mouseY, screenWidth, screenHeight, maxTextWidth, getInstance().fontRendererObj);
}
}
/**
* Fixed method for forge versions older than 1.8.9-11.15.1.1808
*
* @see GuiUtils#drawHoveringText
*/
private void drawHoveringText(List textLines, final int mouseX, final int mouseY, final int screenWidth, final int screenHeight, final int maxTextWidth, boolean drawGraph) {
if (!textLines.isEmpty()) {
FontRenderer font = (drawGraph && fontRendererAscii != null) ? fontRendererAscii : fontRendererObj;
GlStateManager.disableRescaleNormal();
RenderHelper.disableStandardItemLighting();
GlStateManager.disableLighting();
GlStateManager.disableDepth();
int tooltipTextWidth = 0;
for (String textLine : textLines) {
int textLineWidth = font.getStringWidth(textLine);
if (textLineWidth > tooltipTextWidth) {
tooltipTextWidth = textLineWidth;
}
}
boolean needsWrap = false;
int titleLinesCount = 1;
int tooltipX = mouseX + 12;
if (tooltipX + tooltipTextWidth + 4 > screenWidth) {
tooltipX = mouseX - 16 - tooltipTextWidth;
if (tooltipX < 4 && !drawGraph) { // if the tooltip doesn't fit on the screen
if (mouseX > screenWidth / 2) {
tooltipTextWidth = mouseX - 12 - 8;
} else {
tooltipTextWidth = screenWidth - 16 - mouseX;
}
needsWrap = true;
}
}
if (maxTextWidth > 0 && tooltipTextWidth > maxTextWidth) {
tooltipTextWidth = maxTextWidth;
needsWrap = true;
}
if (needsWrap && !drawGraph) {
int wrappedTooltipWidth = 0;
List wrappedTextLines = new ArrayList<>();
for (int i = 0; i < textLines.size(); i++) {
String textLine = textLines.get(i);
List wrappedLine = font.listFormattedStringToWidth(textLine, tooltipTextWidth);
if (i == 0) {
titleLinesCount = wrappedLine.size();
}
for (String line : wrappedLine) {
int lineWidth = font.getStringWidth(line);
if (lineWidth > wrappedTooltipWidth) {
wrappedTooltipWidth = lineWidth;
}
wrappedTextLines.add(line);
}
}
tooltipTextWidth = wrappedTooltipWidth;
textLines = wrappedTextLines;
if (mouseX > screenWidth / 2) {
tooltipX = mouseX - 16 - tooltipTextWidth;
} else {
tooltipX = mouseX + 12;
}
}
int tooltipY = mouseY - 12;
int tooltipHeight = 8;
if (textLines.size() > 1) {
tooltipHeight += (textLines.size() - 1) * 10;
if (textLines.size() > titleLinesCount) {
tooltipHeight += 2; // gap between title lines and next lines
}
}
if (tooltipY + tooltipHeight + 6 > screenHeight) {
tooltipY = screenHeight - tooltipHeight - 6;
}
final int backgroundColor = 0xF0100010;
Gui.drawRect(tooltipX - 3, tooltipY - 4, tooltipX + tooltipTextWidth + 3, tooltipY - 3, backgroundColor);
Gui.drawRect(tooltipX - 3, tooltipY + tooltipHeight + 3, tooltipX + tooltipTextWidth + 3, tooltipY + tooltipHeight + 4, backgroundColor);
Gui.drawRect(tooltipX - 3, tooltipY - 3, tooltipX + tooltipTextWidth + 3, tooltipY + tooltipHeight + 3, backgroundColor);
Gui.drawRect(tooltipX - 4, tooltipY - 3, tooltipX - 3, tooltipY + tooltipHeight + 3, backgroundColor);
Gui.drawRect(tooltipX + tooltipTextWidth + 3, tooltipY - 3, tooltipX + tooltipTextWidth + 4, tooltipY + tooltipHeight + 3, backgroundColor);
final int borderColorStart = 0x505000FF;
final int borderColorEnd = (borderColorStart & 0xFEFEFE) >> 1 | borderColorStart & 0xFF000000;
Gui.drawRect(tooltipX - 3, tooltipY - 3 + 1, tooltipX - 3 + 1, tooltipY + tooltipHeight + 3 - 1, borderColorStart);
Gui.drawRect(tooltipX + tooltipTextWidth + 2, tooltipY - 3 + 1, tooltipX + tooltipTextWidth + 3, tooltipY + tooltipHeight + 3 - 1, borderColorStart);
Gui.drawRect(tooltipX - 3, tooltipY - 3, tooltipX + tooltipTextWidth + 3, tooltipY - 3 + 1, borderColorStart);
Gui.drawRect(tooltipX - 3, tooltipY + tooltipHeight + 2, tooltipX + tooltipTextWidth + 3, tooltipY + tooltipHeight + 3, borderColorEnd);
List graphNodes = new ArrayList<>();
if (drawGraph) {
graphNodes.addAll(Collections.nCopies(100, null));
}
int widthCharX = font.getCharWidth('x') / 2;
for (int lineNumber = 0; lineNumber < textLines.size(); ++lineNumber) {
String line = textLines.get(lineNumber);
String lineWithoutFormattingCodes = EnumChatFormatting.getTextWithoutFormattingCodes(line);
if (drawGraph && (lineWithoutFormattingCodes.startsWith("│") || lineWithoutFormattingCodes.startsWith("┌") || lineWithoutFormattingCodes.startsWith("└"))) {
// use default mc font
int substrWidth = 0;
int spaceOffset = 0;
for (int c = 0; c < Math.min(100, lineWithoutFormattingCodes.length()); c++) {
char xOrDot = lineWithoutFormattingCodes.charAt(c);
substrWidth += font.getCharWidth(xOrDot);
if (xOrDot == 'x') {
int index = c - spaceOffset;
int yPos = tooltipY + font.FONT_HEIGHT / 2;
GraphNode graphNode = graphNodes.get(index);
if (graphNode == null) {
graphNode = new GraphNode(tooltipX + substrWidth - widthCharX, yPos);
graphNodes.set(index, graphNode);
} else {
graphNode.addY(yPos);
}
} else if (xOrDot == ' ') {
spaceOffset = 1;
}
}
font.drawStringWithShadow(line, (float) tooltipX, (float) tooltipY, -1);
} else {
// use client's font
fontRendererObj.drawStringWithShadow(line, (float) tooltipX, (float) tooltipY, -1);
}
if (lineNumber + 1 == titleLinesCount) {
tooltipY += 2;
}
tooltipY += 10;
}
GlStateManager.enableLighting();
GlStateManager.enableDepth();
RenderHelper.enableStandardItemLighting();
GlStateManager.enableRescaleNormal();
if (drawGraph) {
GlStateManager.pushMatrix();
GlStateManager.clear(GL11.GL_DEPTH_BUFFER_BIT);
GL11.glLineWidth(MooConfig.bazaarConnectGraphsLineWidth);
GlStateManager.disableTexture2D();
GlStateManager.color(255 / 255F, 170 / 255F, 0 / 255F);
WorldRenderer wr = Tessellator.getInstance().getWorldRenderer();
wr.begin(GL11.GL_LINE_STRIP, DefaultVertexFormats.POSITION);
for (GraphNode graphNode : graphNodes) {
if (graphNode == null) {
continue;
}
wr.pos(graphNode.getX(), graphNode.getY(), 0).endVertex();
}
Tessellator.getInstance().draw();
GlStateManager.popMatrix();
}
}
}
private static class GraphNode {
private final int x;
private final List y = new ArrayList<>();
public GraphNode(int x, int y) {
this.x = x;
this.y.add(y);
}
public int getX() {
return x;
}
public int getY() {
int sum = 0;
for (Integer y : this.y) {
sum += y;
}
return sum / this.y.size();
}
public void addY(int y) {
this.y.add(y);
}
}
}