aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main/java/de/cowtipper/cowlection/Cowlection.java6
-rw-r--r--src/main/java/de/cowtipper/cowlection/command/MooCommand.java21
-rw-r--r--src/main/java/de/cowtipper/cowlection/config/CredentialStorage.java73
-rw-r--r--src/main/java/de/cowtipper/cowlection/config/MooConfigCategory.java145
-rw-r--r--src/main/java/de/cowtipper/cowlection/listener/ChatListener.java5
-rw-r--r--src/main/java/de/cowtipper/cowlection/util/ApiUtils.java13
-rw-r--r--src/main/java/de/cowtipper/cowlection/util/GuiHelper.java198
-rw-r--r--src/main/java/de/cowtipper/cowlection/util/Utils.java5
8 files changed, 446 insertions, 20 deletions
diff --git a/src/main/java/de/cowtipper/cowlection/Cowlection.java b/src/main/java/de/cowtipper/cowlection/Cowlection.java
index 4aefd5b..e15ab52 100644
--- a/src/main/java/de/cowtipper/cowlection/Cowlection.java
+++ b/src/main/java/de/cowtipper/cowlection/Cowlection.java
@@ -4,6 +4,7 @@ import de.cowtipper.cowlection.command.MooCommand;
import de.cowtipper.cowlection.command.ReplyCommand;
import de.cowtipper.cowlection.command.ShrugCommand;
import de.cowtipper.cowlection.command.TabCompletableCommand;
+import de.cowtipper.cowlection.config.CredentialStorage;
import de.cowtipper.cowlection.config.MooConfig;
import de.cowtipper.cowlection.handler.DungeonCache;
import de.cowtipper.cowlection.handler.FriendsHandler;
@@ -40,6 +41,7 @@ public class Cowlection {
private File configDir;
private File modsDir;
private MooConfig config;
+ private CredentialStorage moo;
private FriendsHandler friendsHandler;
private VersionChecker versionChecker;
private ChatHelper chatHelper;
@@ -94,6 +96,10 @@ public class Cowlection {
return config;
}
+ public CredentialStorage getMoo() {
+ return moo;
+ }
+
public FriendsHandler getFriendsHandler() {
return friendsHandler;
}
diff --git a/src/main/java/de/cowtipper/cowlection/command/MooCommand.java b/src/main/java/de/cowtipper/cowlection/command/MooCommand.java
index 881a446..edbfc62 100644
--- a/src/main/java/de/cowtipper/cowlection/command/MooCommand.java
+++ b/src/main/java/de/cowtipper/cowlection/command/MooCommand.java
@@ -150,8 +150,8 @@ public class MooCommand extends CommandBase {
//region sub commands: Best friends, friends & other players
private void handleStalking(String[] args) throws CommandException {
- if (!Utils.isValidUuid(MooConfig.moo)) {
- throw new MooCommandException("You haven't set your Hypixel API key yet. Use " + EnumChatFormatting.DARK_RED + "/api new" + EnumChatFormatting.RED + " to request a new API key from Hypixel or use " + EnumChatFormatting.DARK_RED + "/" + this.getCommandName() + " apikey <key>" + EnumChatFormatting.RED + " to manually set your existing API key.");
+ if (!CredentialStorage.isMooValid) {
+ throw new MooCommandException("You haven't set your Hypixel API key yet or the API key is invalid. Use " + EnumChatFormatting.DARK_RED + "/api new" + EnumChatFormatting.RED + " to request a new API key from Hypixel or use " + EnumChatFormatting.DARK_RED + "/" + this.getCommandName() + " apikey <key>" + EnumChatFormatting.RED + " to manually set your existing API key.");
}
if (args.length != 2) {
throw new WrongUsageException("/" + getCommandName() + " stalk <playerName>");
@@ -302,8 +302,8 @@ public class MooCommand extends CommandBase {
//region sub commands: SkyBlock
private void handleStalkingSkyBlock(String[] args) throws CommandException {
- if (!Utils.isValidUuid(MooConfig.moo)) {
- throw new MooCommandException("You haven't set your Hypixel API key yet. Use " + EnumChatFormatting.DARK_RED + "/api new" + EnumChatFormatting.RED + " to request a new API key from Hypixel or use " + EnumChatFormatting.DARK_RED + "/" + this.getCommandName() + " apikey <key>" + EnumChatFormatting.RED + " to manually set your existing API key.");
+ if (!CredentialStorage.isMooValid) {
+ throw new MooCommandException("You haven't set your Hypixel API key yet or the API key is invalid. Use " + EnumChatFormatting.DARK_RED + "/api new" + EnumChatFormatting.RED + " to request a new API key from Hypixel or use " + EnumChatFormatting.DARK_RED + "/" + this.getCommandName() + " apikey <key>" + EnumChatFormatting.RED + " to manually set your existing API key.");
}
if (args.length != 2) {
throw new WrongUsageException("/" + getCommandName() + " skyblockstalk <playerName>");
@@ -480,7 +480,11 @@ public class MooCommand extends CommandBase {
main.getChatHelper().sendMessage(sbStats);
} else {
String cause = (hySBStalking != null) ? hySBStalking.getCause() : null;
- throw new ApiContactException("Hypixel", "couldn't stalk " + EnumChatFormatting.DARK_RED + stalkedPlayer.getName() + EnumChatFormatting.RED + (cause != null ? " (Reason: " + EnumChatFormatting.DARK_RED + cause + EnumChatFormatting.RED + ")" : "") + ".");
+ String reason = "";
+ if (cause != null) {
+ reason = " (Reason: " + EnumChatFormatting.DARK_RED + cause + EnumChatFormatting.RED + ")";
+ }
+ throw new ApiContactException("Hypixel", "couldn't stalk " + EnumChatFormatting.DARK_RED + stalkedPlayer.getName() + EnumChatFormatting.RED + reason + ".");
}
});
}
@@ -603,7 +607,7 @@ public class MooCommand extends CommandBase {
String firstSentence;
EnumChatFormatting color;
EnumChatFormatting colorSecondary;
- if (Utils.isValidUuid(MooConfig.moo)) {
+ if (CredentialStorage.isMooValid) {
firstSentence = "You already set your Hypixel API key.";
color = EnumChatFormatting.GREEN;
colorSecondary = EnumChatFormatting.DARK_GREEN;
@@ -616,9 +620,8 @@ public class MooCommand extends CommandBase {
} else {
String key = args[1];
if (Utils.isValidUuid(key)) {
- MooConfig.moo = key;
- main.getConfig().syncFromFields();
- main.getChatHelper().sendMessage(EnumChatFormatting.GREEN, "Updated API key!");
+ main.getChatHelper().sendMessage(EnumChatFormatting.YELLOW, "Validating API key...");
+ main.getMoo().setMooIfValid(key, true);
} else {
throw new SyntaxErrorException("That doesn't look like a valid API key...");
}
diff --git a/src/main/java/de/cowtipper/cowlection/config/CredentialStorage.java b/src/main/java/de/cowtipper/cowlection/config/CredentialStorage.java
new file mode 100644
index 0000000..c7cf35f
--- /dev/null
+++ b/src/main/java/de/cowtipper/cowlection/config/CredentialStorage.java
@@ -0,0 +1,73 @@
+package de.cowtipper.cowlection.config;
+
+import de.cowtipper.cowlection.Cowlection;
+import de.cowtipper.cowlection.util.ApiUtils;
+import de.cowtipper.cowlection.util.Utils;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraftforge.common.config.Configuration;
+import net.minecraftforge.common.config.Property;
+
+/**
+ * Key and secret holder in its own file to avoid people leaking their keys accidentally.
+ */
+public class CredentialStorage {
+ public static String moo;
+ public static boolean isMooValid;
+ private Property propMoo;
+ private Property propIsMooValid;
+ private final Configuration cfg;
+
+ public CredentialStorage(Configuration configuration) {
+ cfg = configuration;
+ initConfig();
+ }
+
+ private void initConfig() {
+ cfg.load();
+ propMoo = cfg.get(Configuration.CATEGORY_CLIENT,
+ "moo", "", "Don't share this with anybody! Do not edit this entry manually either!", Utils.VALID_UUID_PATTERN)
+ .setShowInGui(false);
+ propMoo.setLanguageKey(Cowlection.MODID + ".config." + propMoo.getName());
+
+ propIsMooValid = cfg.get(Configuration.CATEGORY_CLIENT,
+ "isMooValid", false, "Is the value valid?")
+ .setShowInGui(false);
+ moo = propMoo.getString();
+ isMooValid = propIsMooValid.getBoolean();
+ if (cfg.hasChanged()) {
+ cfg.save();
+ }
+ }
+
+ public void setMooIfValid(String moo, boolean commandTriggered) {
+ ApiUtils.fetchApiKeyInfo(moo, hyApiKey -> {
+ if (hyApiKey != null && hyApiKey.isSuccess()) {
+ // api key is valid!
+ Cowlection.getInstance().getMoo().setMoo(moo);
+ if (commandTriggered) {
+ Cowlection.getInstance().getChatHelper().sendMessage(EnumChatFormatting.GREEN, "Successfully verified API key ✔");
+ }
+ } else if (commandTriggered) {
+ // api key is invalid
+ String cause = hyApiKey != null ? hyApiKey.getCause() : null;
+ Cowlection.getInstance().getChatHelper().sendMessage(EnumChatFormatting.RED, "Failed to verify API key: " + (cause != null ? cause : "unknown cause :c"));
+ }
+ });
+ }
+
+ private void setMoo(String moo) {
+ CredentialStorage.moo = moo;
+ propMoo.set(moo);
+ setMooValidity(true);
+ }
+
+ public void setMooValidity(boolean isMooValid) {
+ CredentialStorage.isMooValid = isMooValid;
+ propIsMooValid.set(isMooValid);
+ cfg.save();
+ }
+
+ public Property getPropIsMooValid() {
+ return propIsMooValid;
+ }
+}
diff --git a/src/main/java/de/cowtipper/cowlection/config/MooConfigCategory.java b/src/main/java/de/cowtipper/cowlection/config/MooConfigCategory.java
new file mode 100644
index 0000000..ea2eb37
--- /dev/null
+++ b/src/main/java/de/cowtipper/cowlection/config/MooConfigCategory.java
@@ -0,0 +1,145 @@
+package de.cowtipper.cowlection.config;
+
+import de.cowtipper.cowlection.Cowlection;
+import de.cowtipper.cowlection.config.gui.MooConfigPreview;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraftforge.common.config.Property;
+import net.minecraftforge.fml.client.config.GuiSlider;
+
+import java.util.*;
+
+/**
+ * A config category, contains elements and logic for one specific config category
+ */
+public class MooConfigCategory {
+ private final String displayName;
+ private final String configName;
+ private String menuDisplayName;
+ private final List<SubCategory> subCategories;
+
+ public MooConfigCategory(String displayName, String configName) {
+ this.displayName = displayName;
+ this.configName = configName;
+ this.menuDisplayName = displayName;
+ subCategories = new ArrayList<>();
+ }
+
+ public void setMenuDisplayName(String menuDisplayName) {
+ this.menuDisplayName = menuDisplayName;
+ }
+
+ public String getDisplayName() {
+ return displayName;
+ }
+
+ public String getConfigName() {
+ return this.configName;
+ }
+
+ public String getMenuDisplayName() {
+ return menuDisplayName;
+ }
+
+ public List<SubCategory> getSubCategories() {
+ return subCategories;
+ }
+
+ public SubCategory addSubCategory(String subCatName) {
+ SubCategory subCategory = new SubCategory(subCatName);
+ subCategories.add(subCategory);
+ return subCategory;
+ }
+
+
+ public static class SubCategory {
+ private final String displayName;
+ private final List<String> explanations = new ArrayList<>();
+ private final List<Property> configEntries = new ArrayList<>();
+ private final Map<String, GuiSliderExtra> guiSliderExtras = new HashMap<>();
+ /**
+ * Index 0: preview for sub category
+ * Index >0: preview for one specific property
+ */
+ private final Map<Integer, MooConfigPreview> previews = new HashMap<>();
+
+ public SubCategory(String subCatName) {
+ this.displayName = subCatName;
+ }
+
+ public Property addConfigEntry(Property configEntry, MooConfigPreview configEntryPreview) {
+ Property property = addConfigEntry(configEntry);
+ addPropertyPreview(property, configEntryPreview);
+ return property;
+ }
+
+ public Property addConfigEntry(Property property, String prefix, String suffix, GuiSlider.ISlider onChangeSliderValue) {
+ guiSliderExtras.put(property.getLanguageKey(), new GuiSliderExtra(prefix, suffix, onChangeSliderValue));
+ return addConfigEntry(property);
+ }
+
+ public Property addConfigEntry(Property configEntry) {
+ configEntry.setLanguageKey(Cowlection.MODID + ".config." + configEntry.getName());
+ configEntries.add(configEntry);
+ return configEntry;
+ }
+
+ public void addPropertyPreview(Property property, MooConfigPreview preview) {
+ int propId = configEntries.indexOf(property);
+ if (propId > -1) {
+ this.previews.put(propId + 1, preview);
+ }
+ }
+
+ public void addExplanations(String... explanations) {
+ if (this.explanations.isEmpty()) {
+ // first line is only used for the explanations tooltips, not for in-text:
+ this.explanations.add(EnumChatFormatting.DARK_GREEN + "❢ " + EnumChatFormatting.GOLD + EnumChatFormatting.BOLD + displayName);
+ }
+ this.explanations.addAll(Arrays.asList(explanations));
+ }
+
+ public String getDisplayName() {
+ return displayName;
+ }
+
+ public List<String> getExplanations() {
+ return explanations;
+ }
+
+ public List<Property> getConfigEntries() {
+ return configEntries;
+ }
+
+ public GuiSliderExtra getGuiSliderExtra(String propertyKey) {
+ return guiSliderExtras.get(propertyKey);
+ }
+
+ public Map<Integer, MooConfigPreview> getPreviews() {
+ return previews;
+ }
+
+ public static class GuiSliderExtra {
+ private final String prefix;
+ private final String suffix;
+ private final GuiSlider.ISlider onChangeSliderValue;
+
+ public GuiSliderExtra(String prefix, String suffix, GuiSlider.ISlider onChangeSliderValue) {
+ this.prefix = prefix;
+ this.suffix = suffix;
+ this.onChangeSliderValue = onChangeSliderValue;
+ }
+
+ public String getPrefix() {
+ return prefix != null ? prefix : "";
+ }
+
+ public String getSuffix() {
+ return suffix != null ? suffix : "";
+ }
+
+ public GuiSlider.ISlider getOnChangeSliderValue() {
+ return onChangeSliderValue;
+ }
+ }
+ }
+}
diff --git a/src/main/java/de/cowtipper/cowlection/listener/ChatListener.java b/src/main/java/de/cowtipper/cowlection/listener/ChatListener.java
index e2d2316..318907d 100644
--- a/src/main/java/de/cowtipper/cowlection/listener/ChatListener.java
+++ b/src/main/java/de/cowtipper/cowlection/listener/ChatListener.java
@@ -87,9 +87,8 @@ public class ChatListener {
// Your new API key is 00000000-0000-0000-0000-000000000000
String moo = text.substring(20, 56);
if (Utils.isValidUuid(moo)) {
- MooConfig.moo = moo;
- main.getConfig().syncFromFields();
- main.getChatHelper().sendMessage(EnumChatFormatting.GREEN, "Saved your API key in " + Cowlection.MODNAME + " config!");
+ main.getChatHelper().sendMessage(EnumChatFormatting.YELLOW, "Verifying the new API key...");
+ main.getMoo().setMooIfValid(moo, true);
}
}
}
diff --git a/src/main/java/de/cowtipper/cowlection/util/ApiUtils.java b/src/main/java/de/cowtipper/cowlection/util/ApiUtils.java
index 442c940..03e4a14 100644
--- a/src/main/java/de/cowtipper/cowlection/util/ApiUtils.java
+++ b/src/main/java/de/cowtipper/cowlection/util/ApiUtils.java
@@ -6,11 +6,8 @@ import com.google.gson.JsonSyntaxException;
import com.mojang.util.UUIDTypeAdapter;
import de.cowtipper.cowlection.Cowlection;
import de.cowtipper.cowlection.command.exception.ThrowingConsumer;
-import de.cowtipper.cowlection.config.MooConfig;
-import de.cowtipper.cowlection.data.Friend;
-import de.cowtipper.cowlection.data.HyPlayerData;
-import de.cowtipper.cowlection.data.HySkyBlockStats;
-import de.cowtipper.cowlection.data.HyStalkingData;
+import de.cowtipper.cowlection.config.CredentialStorage;
+import de.cowtipper.cowlection.data.*;
import de.cowtipper.cowlection.event.ApiErrorEvent;
import net.minecraftforge.common.MinecraftForge;
import org.apache.http.HttpStatus;
@@ -79,7 +76,7 @@ public class ApiUtils {
}
private static HyStalkingData stalkPlayer(Friend friend) {
- try (BufferedReader reader = makeApiCall(String.format(ONLINE_STATUS_URL, MooConfig.moo, UUIDTypeAdapter.fromUUID(friend.getUuid())))) {
+ try (BufferedReader reader = makeApiCall(String.format(ONLINE_STATUS_URL, CredentialStorage.moo, UUIDTypeAdapter.fromUUID(friend.getUuid())))) {
if (reader != null) {
return GsonUtils.fromJson(reader, HyStalkingData.class);
}
@@ -94,7 +91,7 @@ public class ApiUtils {
}
private static HySkyBlockStats stalkSkyBlockStats(Friend friend) {
- try (BufferedReader reader = makeApiCall(String.format(SKYBLOCK_STATS_URL, MooConfig.moo, UUIDTypeAdapter.fromUUID(friend.getUuid())))) {
+ try (BufferedReader reader = makeApiCall(String.format(SKYBLOCK_STATS_URL, CredentialStorage.moo, UUIDTypeAdapter.fromUUID(friend.getUuid())))) {
if (reader != null) {
return GsonUtils.fromJson(reader, HySkyBlockStats.class);
}
@@ -109,7 +106,7 @@ public class ApiUtils {
}
private static HyPlayerData stalkHyPlayer(Friend stalkedPlayer) {
- try (BufferedReader reader = makeApiCall(String.format(PLAYER_URL, MooConfig.moo, UUIDTypeAdapter.fromUUID(stalkedPlayer.getUuid())))) {
+ try (BufferedReader reader = makeApiCall(String.format(PLAYER_URL, CredentialStorage.moo, UUIDTypeAdapter.fromUUID(stalkedPlayer.getUuid())))) {
if (reader != null) {
return GsonUtils.fromJson(reader, HyPlayerData.class);
}
diff --git a/src/main/java/de/cowtipper/cowlection/util/GuiHelper.java b/src/main/java/de/cowtipper/cowlection/util/GuiHelper.java
new file mode 100644
index 0000000..a80b1ba
--- /dev/null
+++ b/src/main/java/de/cowtipper/cowlection/util/GuiHelper.java
@@ -0,0 +1,198 @@
+package de.cowtipper.cowlection.util;
+
+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.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.minecraftforge.common.ForgeVersion;
+import net.minecraftforge.fml.client.config.GuiUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public final class GuiHelper extends GuiScreen {
+ private static GuiHelper instance;
+
+ private GuiHelper() {
+ this.mc = Minecraft.getMinecraft();
+ this.fontRendererObj = mc.fontRendererObj;
+ this.itemRender = mc.getRenderItem();
+ }
+
+ private static GuiHelper getInstance() {
+ if (instance == null) {
+ instance = new GuiHelper();
+ }
+ return instance;
+ }
+
+ /**
+ * 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
+ * <p>
+ * 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 drawHoveringText(List<String> 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;
+ drawHoveringText(textLines, mouseX, mouseY, screenWidth, screenHeight, maxTextWidth, getInstance().fontRendererObj);
+ } 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
+ */
+ public static void drawHoveringText(List<String> textLines, final int mouseX, final int mouseY, final int screenWidth, final int screenHeight, final int maxTextWidth, FontRenderer font) {
+ if (!textLines.isEmpty()) {
+ 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) { // 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) {
+ int wrappedTooltipWidth = 0;
+ List<String> wrappedTextLines = new ArrayList<>();
+ for (int i = 0; i < textLines.size(); i++) {
+ String textLine = textLines.get(i);
+ List<String> 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 zLevel = 300;
+ 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);
+
+ for (int lineNumber = 0; lineNumber < textLines.size(); ++lineNumber) {
+ String line = textLines.get(lineNumber);
+ font.drawStringWithShadow(line, (float) tooltipX, (float) tooltipY, -1);
+
+ if (lineNumber + 1 == titleLinesCount) {
+ tooltipY += 2;
+ }
+
+ tooltipY += 10;
+ }
+
+ GlStateManager.enableLighting();
+ GlStateManager.enableDepth();
+ RenderHelper.enableStandardItemLighting();
+ GlStateManager.enableRescaleNormal();
+ }
+ }
+}
diff --git a/src/main/java/de/cowtipper/cowlection/util/Utils.java b/src/main/java/de/cowtipper/cowlection/util/Utils.java
index 24e6b7b..3cf77b5 100644
--- a/src/main/java/de/cowtipper/cowlection/util/Utils.java
+++ b/src/main/java/de/cowtipper/cowlection/util/Utils.java
@@ -250,4 +250,9 @@ public final class Utils {
}
return tierColor;
}
+
+
+ public static String booleanToSymbol(boolean value) {
+ return value ? EnumChatFormatting.GREEN + "✔" : EnumChatFormatting.RED + "✘";
+ }
}