From 8f3bce7d6fe41e85f2654f7557bbb564305e58b5 Mon Sep 17 00:00:00 2001 From: matthias-luger <58751503+matthias-luger@users.noreply.github.com> Date: Fri, 17 Feb 2023 17:32:26 +0100 Subject: Add TFM Purchase UI to Mod (#78) * Add TFM Purchase UI to Mod * fix up opening flips by hotkey fix up flip message in tfm ui * readded check if the auction should be drawn mod doesnt crash anymore if a non flip auction is opened * added /cofl set gui command changed gui title * added /fc toggle command dont store toggle locally * rename purchaseOverlay config removed unused code renamed gui command to /cofl set ahbuygui * fix message not available if flip opened by mouse fix old message shown for non flip auctions * added /cofl setGui command added cofl purchase gui * Add sound on flip * Fixed new flip sound Optimized cofl gui Removed flickering of default mc gui Move mouse to middle on screen open * remove unused code * remove debug code * don't open guis if not in skyblock * fix sound being null * fix bed flips fix opening /cofl blocked * remove logging * Rewrote cofl gui to render before the chest gui opens * - fix bed flips - invalidate best flips after open * - fix scrolling * - fix description not updating - case insensitive commands - fix up , at the end of the message * - add gui if item was already bought - fix bug that invalidated too many flips - added missing "break" * fix merge error * add .vscode to gitignore formatting * fix formatting issue * - remove comment - remove emty line --- .gitignore | 1 + build.gradle.kts | 2 +- src/main/java/de/torui/coflsky/CoflSky.java | 82 ++-- src/main/java/de/torui/coflsky/CoflSkyCommand.java | 432 ++++++++++++--------- src/main/java/de/torui/coflsky/FlipHandler.java | 235 +++++------ .../java/de/torui/coflsky/FlipperChatCommand.java | 86 ++-- .../java/de/torui/coflsky/WSCommandHandler.java | 383 +++++++++--------- .../de/torui/coflsky/commands/models/FlipData.java | 22 +- .../torui/coflsky/configuration/LocalConfig.java | 12 +- src/main/java/de/torui/coflsky/gui/GUIType.java | 6 + .../de/torui/coflsky/gui/bingui/BinGuiCurrent.java | 415 ++++++++++++++++++++ .../de/torui/coflsky/gui/bingui/BinGuiManager.java | 19 + .../java/de/torui/coflsky/gui/bingui/BuyState.java | 8 + .../coflsky/gui/bingui/helper/ColorPallet.java | 25 ++ .../coflsky/gui/bingui/helper/GuiUtilsClone.java | 349 +++++++++++++++++ .../coflsky/gui/bingui/helper/RenderUtils.java | 367 +++++++++++++++++ .../de/torui/coflsky/gui/tfm/ButtonRemapper.java | 338 ++++++++++++++++ .../coflsky/gui/tfm/ChatMessageSendHandler.java | 32 ++ .../de/torui/coflsky/gui/tfm/ToolTipHelper.java | 55 +++ .../de/torui/coflsky/handlers/EventRegistry.java | 394 +++++++++---------- 20 files changed, 2473 insertions(+), 790 deletions(-) create mode 100644 src/main/java/de/torui/coflsky/gui/GUIType.java create mode 100644 src/main/java/de/torui/coflsky/gui/bingui/BinGuiCurrent.java create mode 100644 src/main/java/de/torui/coflsky/gui/bingui/BinGuiManager.java create mode 100644 src/main/java/de/torui/coflsky/gui/bingui/BuyState.java create mode 100644 src/main/java/de/torui/coflsky/gui/bingui/helper/ColorPallet.java create mode 100644 src/main/java/de/torui/coflsky/gui/bingui/helper/GuiUtilsClone.java create mode 100644 src/main/java/de/torui/coflsky/gui/bingui/helper/RenderUtils.java create mode 100644 src/main/java/de/torui/coflsky/gui/tfm/ButtonRemapper.java create mode 100644 src/main/java/de/torui/coflsky/gui/tfm/ChatMessageSendHandler.java create mode 100644 src/main/java/de/torui/coflsky/gui/tfm/ToolTipHelper.java diff --git a/.gitignore b/.gitignore index 2c770e0..b6455ce 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,4 @@ build # other eclipse run +.vscode \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 6012b51..e92e772 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,7 +7,7 @@ plugins { } group = "de.torui.coflmod" -version = "1.4.4-alpha" +version = "1.5.0-alpha" // Toolchains: java { diff --git a/src/main/java/de/torui/coflsky/CoflSky.java b/src/main/java/de/torui/coflsky/CoflSky.java index 7eba195..a1498ba 100644 --- a/src/main/java/de/torui/coflsky/CoflSky.java +++ b/src/main/java/de/torui/coflsky/CoflSky.java @@ -6,15 +6,16 @@ import java.net.URISyntaxException; import java.nio.file.Files; import java.nio.file.Paths; - import com.google.gson.Gson; import de.torui.coflsky.configuration.LocalConfig; +import de.torui.coflsky.gui.GUIType; import de.torui.coflsky.handlers.EventRegistry; import de.torui.coflsky.listeners.ChatListener; import de.torui.coflsky.proxy.APIKeyManager; +import de.torui.coflsky.gui.tfm.ButtonRemapper; +import de.torui.coflsky.gui.tfm.ChatMessageSendHandler; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; import org.lwjgl.input.Keyboard; - import de.torui.coflsky.network.WSClientWrapper; import net.minecraft.client.settings.KeyBinding; import net.minecraftforge.client.ClientCommandHandler; @@ -26,11 +27,10 @@ import net.minecraftforge.fml.common.event.FMLInitializationEvent; import net.minecraftforge.fml.relauncher.Side; @Mod(modid = CoflSky.MODID, version = CoflSky.VERSION) -public class CoflSky -{ +public class CoflSky { public static final String MODID = "CoflSky"; - public static final String VERSION = "1.4.4-Alpha"; - + public static final String VERSION = "1.5.0-Alpha"; + public static WSClientWrapper Wrapper; public static KeyBinding[] keyBindings; @@ -38,14 +38,14 @@ public class CoflSky public static File configFile; private File coflDir; public static LocalConfig config; - - public static final String[] webSocketURIPrefix = new String [] { - "wss://sky.coflnet.com/modsocket", - "wss://sky-mod.coflnet.com/modsocket", - "ws://sky.coflnet.com/modsocket", - "ws://sky-mod.coflnet.com/modsocket", + + public static final String[] webSocketURIPrefix = new String[]{ + "wss://sky.coflnet.com/modsocket", + "wss://sky-mod.coflnet.com/modsocket", + "ws://sky.coflnet.com/modsocket", + "ws://sky-mod.coflnet.com/modsocket", }; - + public static String CommandUri = Config.BaseUrl + "/api/mod/commands"; private final static APIKeyManager apiKeyManager = new APIKeyManager(); @@ -66,12 +66,12 @@ public class CoflSky e.printStackTrace(); } if (config == null) { - config = LocalConfig.createDefaultConfig(); + config = LocalConfig.createDefaultConfig(); } try { this.apiKeyManager.loadIfExists(); - }catch (Exception exception){ + } catch (Exception exception) { exception.printStackTrace(); } @@ -82,44 +82,42 @@ public class CoflSky } @EventHandler - public void init(FMLInitializationEvent event) throws URISyntaxException - { - System.out.println(">>>Started"); - + public void init(FMLInitializationEvent event) { CoflSky.Wrapper = new WSClientWrapper(webSocketURIPrefix); - - keyBindings = new KeyBinding[] { - new KeyBinding("key.replay_last.onclick", Keyboard.KEY_NONE, "SkyCofl"), - new KeyBinding("key.start_highest_bid", Keyboard.KEY_NONE, "SkyCofl") + + keyBindings = new KeyBinding[]{ + new KeyBinding("key.replay_last.onclick", Keyboard.KEY_NONE, "SkyCofl"), + new KeyBinding("key.start_highest_bid", Keyboard.KEY_NONE, "SkyCofl") }; - - if(event.getSide() == Side.CLIENT) { - ClientCommandHandler.instance.registerCommand(new CoflSkyCommand()); - ClientCommandHandler.instance.registerCommand(new ColfCommand()); - ClientCommandHandler.instance.registerCommand(new FlipperChatCommand()); - - for (int i = 0; i < keyBindings.length; ++i) - { - ClientRegistry.registerKeyBinding(keyBindings[i]); - } - - - } + + if (event.getSide() == Side.CLIENT) { + ClientCommandHandler.instance.registerCommand(new CoflSkyCommand()); + ClientCommandHandler.instance.registerCommand(new ColfCommand()); + ClientCommandHandler.instance.registerCommand(new FlipperChatCommand()); + + for (int i = 0; i < keyBindings.length; ++i) { + ClientRegistry.registerKeyBinding(keyBindings[i]); + } + + + } Events = new EventRegistry(); MinecraftForge.EVENT_BUS.register(Events); - + if (config.purchaseOverlay == GUIType.TFM) { + MinecraftForge.EVENT_BUS.register(ButtonRemapper.getInstance()); + } + MinecraftForge.EVENT_BUS.register(new ChatMessageSendHandler()); Runtime.getRuntime().addShutdownHook(new Thread(() -> { - config.saveConfig(configFile , config); + config.saveConfig(configFile, config); try { apiKeyManager.saveKey(); - }catch (Exception exception){ + } catch (Exception exception) { exception.printStackTrace(); } })); - } - + } - public static APIKeyManager getAPIKeyManager(){ + public static APIKeyManager getAPIKeyManager() { return apiKeyManager; } diff --git a/src/main/java/de/torui/coflsky/CoflSkyCommand.java b/src/main/java/de/torui/coflsky/CoflSkyCommand.java index de82f12..880127c 100644 --- a/src/main/java/de/torui/coflsky/CoflSkyCommand.java +++ b/src/main/java/de/torui/coflsky/CoflSkyCommand.java @@ -1,14 +1,16 @@ package de.torui.coflsky; import java.io.IOException; -import java.util.Arrays; -import java.util.Base64; -import java.util.List; +import java.util.*; import de.torui.coflsky.commands.Command; import de.torui.coflsky.commands.CommandType; import de.torui.coflsky.commands.JsonStringCommand; import de.torui.coflsky.commands.RawCommand; +import de.torui.coflsky.commands.models.FlipData; +import de.torui.coflsky.gui.GUIType; +import de.torui.coflsky.gui.bingui.BinGuiManager; +import de.torui.coflsky.gui.tfm.ButtonRemapper; import de.torui.coflsky.minecraft_integration.CoflSessionManager; import de.torui.coflsky.minecraft_integration.CoflSessionManager.CoflSession; import de.torui.coflsky.network.QueryServerCommands; @@ -20,201 +22,245 @@ import net.minecraft.command.CommandException; import net.minecraft.command.ICommandSender; import net.minecraft.event.ClickEvent; import net.minecraft.event.ClickEvent.Action; -import net.minecraft.server.MinecraftServer; -import net.minecraft.util.BlockPos; import net.minecraft.util.ChatComponentText; import net.minecraft.util.ChatStyle; import net.minecraft.util.EnumChatFormatting; -import net.minecraft.util.IChatComponent; -import java.util.ArrayList; +import net.minecraftforge.common.MinecraftForge; public class CoflSkyCommand extends CommandBase { - - @Override - public int getRequiredPermissionLevel() { - // TODO Auto-generated method stub - return 0; - } - - @Override - public String getCommandName() { - return "cofl"; - } - @Override - public List getCommandAliases() - { - ArrayList al = new ArrayList(); - al.add("Cofl"); - al.add("coflnet"); - al.add("cl"); - return al; - } - - @Override - public String getCommandUsage(ICommandSender sender) { - return HelpText; - } - - public static final String HelpText = "Available local sub-commands:\n" - + "§bstart: §7starts a new connection\n" - + "§bstop: §7stops the connection\n" - + "§bconnect: §7Connects to a different server\n" - + "§breset: §7resets all local session information and stops the connection\n" - + "§bstatus: §7Emits status information\nServer-Only Commands:"; - @Override - public void processCommand(ICommandSender sender, String[] args) throws CommandException { - new Thread(()->{ - System.out.println(Arrays.toString(args)); - - if(args.length >= 1) { - switch(args[0]) { - case "start": - //todo: start - //possible workaround for https://github.com/Coflnet/SkyblockMod/issues/48 - CoflSky.Wrapper.stop(); - sender.addChatMessage(new ChatComponentText("starting connection...")); - CoflSky.Wrapper.startConnection(); - break; - case "stop": - CoflSky.Wrapper.stop(); - sender.addChatMessage(new ChatComponentText("you stopped the connection to ") - .appendSibling(new ChatComponentText("C").setChatStyle(new ChatStyle().setColor(EnumChatFormatting.DARK_BLUE))) - .appendSibling(new ChatComponentText("oflnet").setChatStyle(new ChatStyle().setColor(EnumChatFormatting.GOLD))) - .appendSibling(new ChatComponentText(".\n To reconnect enter ")) - .appendSibling(new ChatComponentText("\"").setChatStyle(new ChatStyle().setColor(EnumChatFormatting.AQUA))) - .appendSibling(new ChatComponentText("/cofl start")) - .appendSibling(new ChatComponentText("\"").setChatStyle(new ChatStyle().setColor(EnumChatFormatting.AQUA))) - .appendSibling(new ChatComponentText(" or click this message")) - .setChatStyle(new ChatStyle().setChatClickEvent(new ClickEvent(Action.RUN_COMMAND, "/cofl start"))) - ); - break; - case "debug": - // WSCommandHandler.HandleCommand(new Command(CommandType.Execute, "/me hewwo"), sender.getCommandSenderEntity()); - // WSCommandHandler.HandleCommand(new Command(CommandType.WriteToChat, " {\"type\":\"writeToChat\",\"data\":\"{\\\"text\\\":\\\"\\\\nFLIP: º9Goblin Eg\r\n" - // + "g º87,000 -> 13,999 ºg[BUY]\\\",\\\"onClick\\\":\\\"/viewauction f7d7295ca72f43e9876bf6da7424000c\\\",\\\"hover\\\":\\\"\\\"}\"}"), sender.getCommandSenderEntity()); - //WSCommandHandler.HandleCommand(new Command(CommandType.PlaySound, "{\"name\":\"random.orb\",\"pitch\":0.5}"), sender.getCommandSenderEntity()); - break; - case "callback": - CallbackCommand(args); - break; - case "dev": - if(Config.BaseUrl.contains("localhost")) { - CoflSky.Wrapper.startConnection(); - Config.BaseUrl = "https://sky.coflnet.com"; - } else { - CoflSky.Wrapper.initializeNewSocket("ws://localhost:8009/modsocket"); - Config.BaseUrl = "http://localhost:5005"; - } - sender.addChatMessage(new ChatComponentText("toggled dev mode, now using " + Config.BaseUrl)); - break; - case "status": - sender.addChatMessage(new ChatComponentText(StatusMessage())); - break; - case "reset": - HandleReset(); - break; - case "connect": - - if(args.length == 2) { - String destination = args[1]; - - if(!destination.contains("://")) { - destination = new String(Base64.getDecoder().decode(destination)); - } - sender.addChatMessage(new ChatComponentText("Stopping connection!")); - CoflSky.Wrapper.stop(); - sender.addChatMessage(new ChatComponentText("Opening connection to " + destination)); - if(CoflSky.Wrapper.initializeNewSocket(destination)) { - sender.addChatMessage(new ChatComponentText("Success")); - } else { - sender.addChatMessage(new ChatComponentText("Could not open connection, please check the logs")); - } - } else { - sender.addChatMessage(new ChatComponentText("§cPleace specify a server to connect to")); - } - break; - default: - SendCommandToServer(args, sender); - return; - } - } - - else { - ListHelp(sender); - } - }).start(); - } - - private void HandleReset() { - CoflSky.Wrapper.SendMessage(new Command(CommandType.Reset,"")); - CoflSky.Wrapper.stop(); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("Stopping Connection to CoflNet")); - CoflSessionManager.DeleteAllCoflSessions(); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("Deleting CoflNet sessions...")); - if(CoflSky.Wrapper.startConnection()) - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("Started the Connection to CoflNet")); - } - - public String StatusMessage() { - - String vendor = System.getProperty("java.vm.vendor"); - String name = System.getProperty("java.vm.name"); - String version = System.getProperty("java.version"); - String detailedVersion = System.getProperty("java.vm.version"); - - String status = vendor + " " + name + " " + version + " " + detailedVersion + "|Connection = " + (CoflSky.Wrapper!=null?CoflSky.Wrapper.GetStatus():"UNINITIALIZED_WRAPPER"); - try { - status += " uri=" + CoflSky.Wrapper.socket.uri.toString(); - } catch(NullPointerException npe) {} - - - try { - CoflSession session = CoflSessionManager.GetCoflSession(PlayerDataProvider.getUsername()); - String sessionString = CoflSessionManager.gson.toJson(session); - status += " session=" + sessionString; - } catch (IOException e) { - } - - return status; - } - - public void SendCommandToServer(String[] args, ICommandSender sender) { - String command = String.join(" ", Arrays.copyOfRange(args, 1, args.length)); - - //JsonStringCommand sc = new JsonStringCommand(args[0], WSClient.gson.toJson(command)); - RawCommand rc = new RawCommand(args[0], WSClient.gson.toJson(command)); - if(CoflSky.Wrapper.isRunning) { - CoflSky.Wrapper.SendMessage(rc); - } else { - SendAfterStart(sender, rc); - } - } - - private static synchronized void SendAfterStart(ICommandSender sender, RawCommand rc) { - sender.addChatMessage(new ChatComponentText("CoflSky wasn't active.").setChatStyle(new ChatStyle().setColor(EnumChatFormatting.RED))); - //CoflSky.Wrapper.stop(); - CoflSky.Wrapper.startConnection(); - CoflSky.Wrapper.SendMessage(rc); - } - - public void ListHelp(ICommandSender sender) { - sender.addChatMessage(new ChatComponentText(HelpText)); - sender.addChatMessage(new ChatComponentText(QueryServerCommands.QueryCommands())); - } - - public void CallbackCommand(String[] args) { - - String command = String.join(" ", Arrays.copyOfRange(args, 1, args.length)); - System.out.println("CallbackData: " + command); - //new Thread(()->{ - System.out.println("Callback: " + command); - WSCommandHandler.HandleCommand(new JsonStringCommand(CommandType.Execute, WSClient.gson.toJson(command)), Minecraft.getMinecraft().thePlayer); - CoflSky.Wrapper.SendMessage(new JsonStringCommand(CommandType.Clicked, WSClient.gson.toJson(command))); - - System.out.println("Sent!"); - //}).start(); - - } + + @Override + public int getRequiredPermissionLevel() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public String getCommandName() { + return "cofl"; + } + + @Override + public List getCommandAliases() { + ArrayList al = new ArrayList(); + al.add("Cofl"); + al.add("coflnet"); + al.add("cl"); + return al; + } + + @Override + public String getCommandUsage(ICommandSender sender) { + return HelpText; + } + + public static final String HelpText = "Available local sub-commands:\n" + + "§bstart: §7starts a new connection\n" + + "§bstop: §7stops the connection\n" + + "§bconnect: §7Connects to a different server\n" + + "§breset: §7resets all local session information and stops the connection\n" + + "§bstatus: §7Emits status information\nServer-Only Commands:"; + + @Override + public void processCommand(ICommandSender sender, String[] args) throws CommandException { + new Thread(() -> { + System.out.println(Arrays.toString(args)); + + if (args.length >= 1) { + switch (args[0].toLowerCase()) { + case "start": + //todo: start + //possible workaround for https://github.com/Coflnet/SkyblockMod/issues/48 + CoflSky.Wrapper.stop(); + sender.addChatMessage(new ChatComponentText("starting connection...")); + CoflSky.Wrapper.startConnection(); + break; + case "stop": + CoflSky.Wrapper.stop(); + sender.addChatMessage(new ChatComponentText("you stopped the connection to ") + .appendSibling(new ChatComponentText("C").setChatStyle(new ChatStyle().setColor(EnumChatFormatting.DARK_BLUE))) + .appendSibling(new ChatComponentText("oflnet").setChatStyle(new ChatStyle().setColor(EnumChatFormatting.GOLD))) + .appendSibling(new ChatComponentText(".\n To reconnect enter ")) + .appendSibling(new ChatComponentText("\"").setChatStyle(new ChatStyle().setColor(EnumChatFormatting.AQUA))) + .appendSibling(new ChatComponentText("/cofl start")) + .appendSibling(new ChatComponentText("\"").setChatStyle(new ChatStyle().setColor(EnumChatFormatting.AQUA))) + .appendSibling(new ChatComponentText(" or click this message")) + .setChatStyle(new ChatStyle().setChatClickEvent(new ClickEvent(Action.RUN_COMMAND, "/cofl start"))) + ); + break; + case "debug": + // WSCommandHandler.HandleCommand(new Command(CommandType.Execute, "/me hewwo"), sender.getCommandSenderEntity()); + // WSCommandHandler.HandleCommand(new Command(CommandType.WriteToChat, " {\"type\":\"writeToChat\",\"data\":\"{\\\"text\\\":\\\"\\\\nFLIP: º9Goblin Eg\r\n" + // + "g º87,000 -> 13,999 ºg[BUY]\\\",\\\"onClick\\\":\\\"/viewauction f7d7295ca72f43e9876bf6da7424000c\\\",\\\"hover\\\":\\\"\\\"}\"}"), sender.getCommandSenderEntity()); + //WSCommandHandler.HandleCommand(new Command(CommandType.PlaySound, "{\"name\":\"random.orb\",\"pitch\":0.5}"), sender.getCommandSenderEntity()); + break; + case "callback": + CallbackCommand(args); + break; + case "dev": + if (Config.BaseUrl.contains("localhost")) { + CoflSky.Wrapper.startConnection(); + Config.BaseUrl = "https://sky.coflnet.com"; + } else { + CoflSky.Wrapper.initializeNewSocket("ws://localhost:8009/modsocket"); + Config.BaseUrl = "http://localhost:5005"; + } + sender.addChatMessage(new ChatComponentText("toggled dev mode, now using " + Config.BaseUrl)); + break; + case "status": + sender.addChatMessage(new ChatComponentText(StatusMessage())); + break; + case "reset": + HandleReset(); + break; + case "connect": + if (args.length == 2) { + String destination = args[1]; + + if (!destination.contains("://")) { + destination = new String(Base64.getDecoder().decode(destination)); + } + sender.addChatMessage(new ChatComponentText("Stopping connection!")); + CoflSky.Wrapper.stop(); + sender.addChatMessage(new ChatComponentText("Opening connection to " + destination)); + if (CoflSky.Wrapper.initializeNewSocket(destination)) { + sender.addChatMessage(new ChatComponentText("Success")); + } else { + sender.addChatMessage(new ChatComponentText("Could not open connection, please check the logs")); + } + } else { + sender.addChatMessage(new ChatComponentText("§cPleace specify a server to connect to")); + } + break; + case "openauctiongui": + FlipData flip = WSCommandHandler.flipHandler.fds.getFlipById(args[1]); + boolean shouldInvalidate = args.length >= 3 && args[2].equals("true"); + + + // Is not a stored flip -> just open the auction + if (flip == null) { + WSCommandHandler.flipHandler.lastClickedFlipMessage = ""; + Minecraft.getMinecraft().thePlayer.sendChatMessage("/viewauction " + args[1]); + return; + } + + String oneLineMessage = String.join(" ", flip.getMessageAsString()).replaceAll("\n", "").split(",§7 sellers ah")[0]; + + if (shouldInvalidate) { + WSCommandHandler.flipHandler.fds.InvalidateFlip(flip); + } + + WSCommandHandler.flipHandler.lastClickedFlipMessage = oneLineMessage; + + BinGuiManager.openNewFlipGui(oneLineMessage, flip.Render); + + Minecraft.getMinecraft().thePlayer.sendChatMessage("/viewauction " + flip.Id); + break; + case "setgui": + if (args.length != 2) { + sender.addChatMessage(new ChatComponentText("[§1C§6oflnet§f]§7: §7Available GUIs:")); + sender.addChatMessage(new ChatComponentText("[§1C§6oflnet§f]§7: §7Cofl")); + sender.addChatMessage(new ChatComponentText("[§1C§6oflnet§f]§7: §7TFM")); + sender.addChatMessage(new ChatComponentText("[§1C§6oflnet§f]§7: §7Off")); + return; + } + + if (args[1].equalsIgnoreCase("cofl")) { + CoflSky.config.purchaseOverlay = GUIType.COFL; + sender.addChatMessage(new ChatComponentText("[§1C§6oflnet§f]§7: §7Set §bPurchase Overlay §7to: §fCofl")); + MinecraftForge.EVENT_BUS.unregister(ButtonRemapper.getInstance()); + } + if (args[1].equalsIgnoreCase("tfm")) { + CoflSky.config.purchaseOverlay = GUIType.TFM; + sender.addChatMessage(new ChatComponentText("[§1C§6oflnet§f]§7: §7Set §bPurchase Overlay §7to: §fTFM")); + MinecraftForge.EVENT_BUS.register(ButtonRemapper.getInstance()); + } + if (args[1].equalsIgnoreCase("off") || args[1].equalsIgnoreCase("false")) { + CoflSky.config.purchaseOverlay = null; + sender.addChatMessage(new ChatComponentText("[§1C§6oflnet§f]§7: §7Set §bPurchase Overlay §7to: §fOff")); + MinecraftForge.EVENT_BUS.unregister(ButtonRemapper.getInstance()); + } + break; + default: + SendCommandToServer(args, sender); + } + } else { + ListHelp(sender); + } + }).start(); + } + + private void HandleReset() { + CoflSky.Wrapper.SendMessage(new Command(CommandType.Reset, "")); + CoflSky.Wrapper.stop(); + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("Stopping Connection to CoflNet")); + CoflSessionManager.DeleteAllCoflSessions(); + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("Deleting CoflNet sessions...")); + if (CoflSky.Wrapper.startConnection()) + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("Started the Connection to CoflNet")); + } + + public String StatusMessage() { + + String vendor = System.getProperty("java.vm.vendor"); + String name = System.getProperty("java.vm.name"); + String version = System.getProperty("java.version"); + String detailedVersion = System.getProperty("java.vm.version"); + + String status = vendor + " " + name + " " + version + " " + detailedVersion + "|Connection = " + (CoflSky.Wrapper != null ? CoflSky.Wrapper.GetStatus() : "UNINITIALIZED_WRAPPER"); + try { + status += " uri=" + CoflSky.Wrapper.socket.uri.toString(); + } catch (NullPointerException npe) { + } + + + try { + CoflSession session = CoflSessionManager.GetCoflSession(PlayerDataProvider.getUsername()); + String sessionString = CoflSessionManager.gson.toJson(session); + status += " session=" + sessionString; + } catch (IOException e) { + } + + return status; + } + + public void SendCommandToServer(String[] args, ICommandSender sender) { + String command = String.join(" ", Arrays.copyOfRange(args, 1, args.length)); + + //JsonStringCommand sc = new JsonStringCommand(args[0], WSClient.gson.toJson(command)); + RawCommand rc = new RawCommand(args[0], WSClient.gson.toJson(command)); + if (CoflSky.Wrapper.isRunning) { + CoflSky.Wrapper.SendMessage(rc); + } else { + SendAfterStart(sender, rc); + } + } + + private static synchronized void SendAfterStart(ICommandSender sender, RawCommand rc) { + sender.addChatMessage(new ChatComponentText("CoflSky wasn't active.").setChatStyle(new ChatStyle().setColor(EnumChatFormatting.RED))); + //CoflSky.Wrapper.stop(); + CoflSky.Wrapper.startConnection(); + CoflSky.Wrapper.SendMessage(rc); + } + + public void ListHelp(ICommandSender sender) { + sender.addChatMessage(new ChatComponentText(HelpText)); + sender.addChatMessage(new ChatComponentText(QueryServerCommands.QueryCommands())); + } + + public void CallbackCommand(String[] args) { + + String command = String.join(" ", Arrays.copyOfRange(args, 1, args.length)); + System.out.println("CallbackData: " + command); + //new Thread(()->{ + System.out.println("Callback: " + command); + WSCommandHandler.HandleCommand(new JsonStringCommand(CommandType.Execute, WSClient.gson.toJson(command)), Minecraft.getMinecraft().thePlayer); + CoflSky.Wrapper.SendMessage(new JsonStringCommand(CommandType.Clicked, WSClient.gson.toJson(command))); + + System.out.println("Sent!"); + //}).start(); + + } } diff --git a/src/main/java/de/torui/coflsky/FlipHandler.java b/src/main/java/de/torui/coflsky/FlipHandler.java index 0c89f21..d3b683e 100644 --- a/src/main/java/de/torui/coflsky/FlipHandler.java +++ b/src/main/java/de/torui/coflsky/FlipHandler.java @@ -1,122 +1,127 @@ package de.torui.coflsky; -import java.util.ConcurrentModificationException; -import java.util.HashMap; -import java.util.Map; -import java.util.Timer; -import java.util.TimerTask; +import de.torui.coflsky.commands.models.FlipData; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; public class FlipHandler { - public static class Flip { - public String id; - public int worth; - - public Flip(String id, int worth) { - super(); - this.id = id; - this.worth = worth; - } - - public Flip() { - - } - - } - - public static class FlipDataStructure { - - private Map Flips = new ConcurrentHashMap <>(); - private Map ReverseMap = new ConcurrentHashMap <>(); - - private Flip HighestFlip = null; - - private Timer t = new Timer(); - private TimerTask CurrentTask = null; - - public synchronized void RunHouseKeeping() { - synchronized (Flips) { - - Long RemoveAllPrior = System.currentTimeMillis() - (Config.KeepFlipsForSeconds*1000); - Flips.keySet().stream().filter(l -> l <= RemoveAllPrior).forEach(l -> RemoveLong(l)); - if (!Flips.isEmpty()) { - HighestFlip = Flips.values().stream().max((f1, f2) -> f1.worth - f2.worth).orElse(null); - } else { - HighestFlip = null; - } - } - - if (CurrentTask != null) { - CurrentTask.cancel(); - CurrentTask = null; - t.purge(); - } - if (!Flips.isEmpty()) { - CurrentTask = new TimerTask() { - @Override - public void run() { - RunHouseKeeping(); - } - }; - t.schedule(CurrentTask, Config.KeepFlipsForSeconds * 1000 + /* small arbitrary delay */150); - } - } - - public synchronized void Insert(Flip flip) { - Long l = System.currentTimeMillis(); - - synchronized(Flips) { - Flips.put(l, flip); - ReverseMap.put(flip, l); - } - - RunHouseKeeping(); - } - - private void RemoveLong(Long l) { - if (l == null) - return; - synchronized(Flips) { - Flip f = Flips.get(l); - if (f != null) { - ReverseMap.remove(f); - Flips.remove(l); - } - } - } - - private void RemoveFlip(Flip f) { - if (f == null) - return; - - synchronized(Flips) { - Long l = ReverseMap.get(f); - if (l != null) { - Flips.remove(l); - ReverseMap.remove(f); - } - } - } - - public Flip GetHighestFlip() { - return HighestFlip; - } - - public void InvalidateFlip(Flip flip) { - RemoveFlip(flip); - RunHouseKeeping(); - } - - public int CurrentFlips() { - return Flips.size(); - } - - } - - public FlipDataStructure fds; - - public FlipHandler() { - fds = new FlipDataStructure(); - } + + public static class FlipDataStructure { + + private Map Flips = new ConcurrentHashMap<>(); + private Map ReverseMap = new ConcurrentHashMap<>(); + + private FlipData HighestFlip = null; + private FlipData LastFlip = null; + + private Timer t = new Timer(); + private TimerTask CurrentTask = null; + + public synchronized void RunHouseKeeping() { + synchronized (Flips) { + + Long RemoveAllPrior = System.currentTimeMillis() - (Config.KeepFlipsForSeconds * 1000); + Flips.keySet().stream().filter(l -> l <= RemoveAllPrior).forEach(l -> RemoveLong(l)); + if (!Flips.isEmpty()) { + HighestFlip = Flips.values().stream().max((f1, f2) -> f1.Worth - f2.Worth).orElse(null); + } else { + HighestFlip = null; + } + } + + if (CurrentTask != null) { + CurrentTask.cancel(); + CurrentTask = null; + t.purge(); + } + if (!Flips.isEmpty()) { + CurrentTask = new TimerTask() { + @Override + public void run() { + RunHouseKeeping(); + } + }; + t.schedule(CurrentTask, Config.KeepFlipsForSeconds * 1000 + /* small arbitrary delay */150); + } + } + + public synchronized void Insert(FlipData flip) { + Long l = System.currentTimeMillis(); + LastFlip = flip; + + synchronized (Flips) { + Flips.put(l, flip); + ReverseMap.put(flip, l); + } + + RunHouseKeeping(); + } + + private void RemoveLong(Long l) { + if (l == null) + return; + synchronized (Flips) { + FlipData f = Flips.get(l); + if (f != null) { + ReverseMap.remove(f); + Flips.remove(l); + } + } + } + + private void RemoveFlip(FlipData f) { + if (f == null) + return; + + synchronized (Flips) { + Long l = ReverseMap.get(f); + if (l != null) { + Flips.remove(l); + ReverseMap.remove(f); + } + } + } + + public FlipData GetHighestFlip() { + return HighestFlip; + } + + public FlipData GetLastFlip() { + if (LastFlip == null) { + return null; + } + Long l = ReverseMap.get(LastFlip); + if (l == null) { + LastFlip = null; + } + return LastFlip; + } + + public FlipData getFlipById(String id) { + FlipData[] flips = Flips.values().stream().filter(flipData -> flipData.Id.equals(id)).toArray(FlipData[]::new); + Flips.forEach((key, value) -> System.out.println(value.Id)); + if (flips.length == 0) { + return null; + } + return flips[0]; + } + + public void InvalidateFlip(FlipData flip) { + RemoveFlip(flip); + RunHouseKeeping(); + } + + public int CurrentFlips() { + return Flips.size(); + } + + } + + public FlipDataStructure fds; + public String lastClickedFlipMessage; + + public FlipHandler() { + fds = new FlipDataStructure(); + } } diff --git a/src/main/java/de/torui/coflsky/FlipperChatCommand.java b/src/main/java/de/torui/coflsky/FlipperChatCommand.java index 618348e..9fe597f 100644 --- a/src/main/java/de/torui/coflsky/FlipperChatCommand.java +++ b/src/main/java/de/torui/coflsky/FlipperChatCommand.java @@ -1,61 +1,47 @@ package de.torui.coflsky; -import java.io.IOException; -import java.util.Arrays; -import java.util.Base64; import java.util.List; - -import de.torui.coflsky.commands.Command; -import de.torui.coflsky.commands.CommandType; -import de.torui.coflsky.commands.JsonStringCommand; -import de.torui.coflsky.commands.RawCommand; -import de.torui.coflsky.minecraft_integration.CoflSessionManager; -import de.torui.coflsky.minecraft_integration.CoflSessionManager.CoflSession; -import de.torui.coflsky.network.QueryServerCommands; -import de.torui.coflsky.network.WSClient; -import de.torui.coflsky.minecraft_integration.PlayerDataProvider; -import net.minecraft.client.Minecraft; -import net.minecraft.command.CommandBase; import net.minecraft.command.CommandException; import net.minecraft.command.ICommandSender; -import net.minecraft.event.ClickEvent; -import net.minecraft.event.ClickEvent.Action; -import net.minecraft.server.MinecraftServer; -import net.minecraft.util.BlockPos; import net.minecraft.util.ChatComponentText; -import net.minecraft.util.ChatStyle; -import net.minecraft.util.EnumChatFormatting; -import net.minecraft.util.IChatComponent; + import java.util.ArrayList; public class FlipperChatCommand extends CoflSkyCommand { - - @Override - public String getCommandName() { - return "fc"; - } - - @Override - public List getCommandAliases() - { - ArrayList al = new ArrayList(); - al.add("coflchat"); - return al; - } - - @Override - public String getCommandUsage(ICommandSender sender) { - return "Shorthand for /cofl chat"; - } - - @Override - public void processCommand(ICommandSender sender, String[] args) throws CommandException { - new Thread(()->{ - String[] newArgs = new String[args.length +1]; - System.arraycopy(args, 0, newArgs, 1, args.length); - newArgs[0] = "chat"; - SendCommandToServer(newArgs, sender); - }).start(); - } + public static boolean useChatOnlyMode = false; + + + @Override + public String getCommandName() { + return "fc"; + } + + @Override + public List getCommandAliases() { + ArrayList al = new ArrayList(); + al.add("coflchat"); + return al; + } + + @Override + public String getCommandUsage(ICommandSender sender) { + return "Shorthand for /cofl chat"; + } + + @Override + public void processCommand(ICommandSender sender, String[] args) throws CommandException { + new Thread(() -> { + + if (args.length == 1 && args[0].equals("toggle")) { + FlipperChatCommand.useChatOnlyMode = !FlipperChatCommand.useChatOnlyMode; + sender.addChatMessage(new ChatComponentText("[§1C§6oflnet§f]§7: §7Set §bChat only mode §7to: §f" + (FlipperChatCommand.useChatOnlyMode ? "true" : "false"))); + } else { + String[] newArgs = new String[args.length + 1]; + System.arraycopy(args, 0, newArgs, 1, args.length); + newArgs[0] = "chat"; + SendCommandToServer(newArgs, sender); + } + }).start(); + } } diff --git a/src/main/java/de/torui/coflsky/WSCommandHandler.java b/src/main/java/de/torui/coflsky/WSCommandHandler.java index 0d37851..83e9222 100644 --- a/src/main/java/de/torui/coflsky/WSCommandHandler.java +++ b/src/main/java/de/torui/coflsky/WSCommandHandler.java @@ -12,6 +12,7 @@ import de.torui.coflsky.configuration.ConfigurationManager; import de.torui.coflsky.handlers.EventRegistry; import de.torui.coflsky.proxy.ProxyManager; import de.torui.coflsky.utils.FileUtils; +import de.torui.coflsky.commands.models.TimerData; import net.minecraft.client.Minecraft; import net.minecraft.client.audio.PositionedSoundRecord; import net.minecraft.client.audio.SoundHandler; @@ -30,190 +31,206 @@ import net.minecraftforge.fml.common.ModContainer; import java.io.File; +import java.util.Arrays; +import java.util.stream.Stream; + public class WSCommandHandler { - public static transient String lastOnClickEvent; - public static FlipHandler flipHandler = new FlipHandler(); - private static final ModListData modListData = new ModListData(); - private static final Gson gson = new Gson(); - private static final ProxyManager proxyManager = new ProxyManager(); - - public static boolean HandleCommand(JsonStringCommand cmd, Entity sender) { - // Entity sender = Minecraft.getMinecraft().thePlayer; - System.out.println("Handling Command=" + cmd.toString()); - - switch (cmd.getType()) { - case WriteToChat: - WriteToChat(cmd.GetAs(new TypeToken() {})); - break; - case Execute: - Execute(cmd.GetAs(new TypeToken() {}), sender); - break; - case PlaySound: - PlaySound(cmd.GetAs(new TypeToken() {}), sender); - break; - case ChatMessage: - ChatMessage(cmd.GetAs(new TypeToken() {})); - break; - case Flip: - Flip(cmd.GetAs(new TypeToken() {})); - break; - case PrivacySettings: - new ConfigurationManager().UpdateConfiguration(cmd.getData()); - case Countdown: - StartTimer(cmd.GetAs(new TypeToken() {})); - break; - case GetMods: - getMods(); - break; - case ProxyRequest: - handleProxyRequest(cmd.GetAs(new TypeToken() {}).getData()); - break; - default: - break; - } - - return true; - } - - private static void handleProxyRequest(ProxyRequest[] request){ - for(ProxyRequest req : request){ - proxyManager.handleRequestAsync(req); - } - } - - - public static void cacheMods(){ - File modFolder = new File(Minecraft.getMinecraft().mcDataDir, "mods"); - for(File mods : modFolder.listFiles()){ - modListData.addFilename(mods.getName()); - try { - modListData.addFileHashes(FileUtils.getMD5Checksum(mods)); - } catch (Exception exception){ - // Highly less likely to happen unless something goes wrong - exception.printStackTrace(); - } - } - - for(ModContainer mod : Loader.instance().getModList()){ - modListData.addModname(mod.getName()); - modListData.addModname(mod.getModId()); - } - } - - private static void getMods(){ - // the Cofl server has asked for an mod list now let's respond with all the info - CoflSky.Wrapper.SendMessage(new RawCommand("foundMods",gson.toJson(modListData))); - } - - - private static void Flip(Command cmd) { - //handle chat message - ChatMessageData[] messages = cmd.getData().Messages; - Command showCmd = new Command(CommandType.ChatMessage, messages); - ChatMessage(showCmd); - flipHandler.fds.Insert(new de.torui.coflsky.FlipHandler.Flip(cmd.getData().Id, cmd.getData().Worth)); - - // trigger the keyevent to execute the event handler - CoflSky.Events.onKeyEvent(null); - } - - private static void PlaySound(Command cmd, Entity sender) { - - SoundData sc = cmd.getData(); - - SoundHandler handler = Minecraft.getMinecraft().getSoundHandler(); - - // random.explode - PositionedSoundRecord psr = PositionedSoundRecord - .create(new ResourceLocation(sc.Name), sc.Pitch); - - handler.playSound(psr); - } - - private static void Execute(Command cmd, Entity sender) { - System.out.println("Execute: " + cmd.getData() + " sender:" + sender); - //String dummy = WSClient.gson.fromJson(cmd.getData(), String.class); - Execute(cmd.getData(),sender); - } - - /** - * Starts a countdown - */ - private static void StartTimer(Command cmd) { - de.torui.coflsky.CountdownTimer.startCountdown(cmd.getData()); - } - - public static void Execute(String cmd, Entity sender) - { - if(cmd.startsWith("/viewauction")){ - String[] args = cmd.split(" "); - - String uuid = args[args.length-1]; - EventRegistry.LastViewAuctionUUID = uuid; - EventRegistry.LastViewAuctionInvocation = System.currentTimeMillis(); - } - - if(cmd.startsWith("/cofl") || cmd.startsWith("http")) { - ClientCommandHandler.instance.executeCommand(sender, cmd); - } else { - Minecraft.getMinecraft().thePlayer.sendChatMessage(cmd); - } - } - - - private static IChatComponent CommandToChatComponent(ChatMessageData wcmd) { - if(wcmd.OnClick != null) - lastOnClickEvent = "/cofl callback " + wcmd.OnClick; - if (wcmd.Text != null) { - IChatComponent comp = new ChatComponentText(wcmd.Text); - - ChatStyle style; - if (wcmd.OnClick != null) { - if (wcmd.OnClick.startsWith("http")) { - style = new ChatStyle().setChatClickEvent(new ClickEvent(Action.OPEN_URL, wcmd.OnClick)); - } else { - style = new ChatStyle() - .setChatClickEvent(new ClickEvent(Action.RUN_COMMAND, "/cofl callback " + wcmd.OnClick)); - } - comp.setChatStyle(style); - } - - if (wcmd.Hover != null && !wcmd.Hover.isEmpty()) { - if (comp.getChatStyle() == null) - comp.setChatStyle(new ChatStyle()); - comp.getChatStyle().setChatHoverEvent( - new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ChatComponentText(wcmd.Hover))); - } - return comp; - } - return null; - } - - private static void ChatMessage(Command cmd) { - ChatMessageData[] list = cmd.getData() ;//WSClient.gson.fromJson(cmd.getData(), WriteToChatCommand[].class); - - IChatComponent master = new ChatComponentText(""); - - for (ChatMessageData wcmd : list) { - IChatComponent comp = CommandToChatComponent(wcmd); - if (comp != null) - master.appendSibling(comp); - } - Minecraft.getMinecraft().thePlayer.addChatMessage(master); - } - - - - private static void WriteToChat(Command cmd) { - ChatMessageData wcmd = cmd.getData(); - - IChatComponent comp = CommandToChatComponent(wcmd); - if (comp != null) - { - Minecraft.getMinecraft().thePlayer.addChatMessage(comp); - } - - } + public static transient String lastOnClickEvent; + public static FlipHandler flipHandler = new FlipHandler(); + private static final ModListData modListData = new ModListData(); + private static final Gson gson = new Gson(); + private static final ProxyManager proxyManager = new ProxyManager(); + + public static boolean HandleCommand(JsonStringCommand cmd, Entity sender) { + System.out.println("Handling Command=" + cmd.toString()); + + switch (cmd.getType()) { + case WriteToChat: + WriteToChat(cmd.GetAs(new TypeToken() { + })); + break; + case Execute: + Execute(cmd.GetAs(new TypeToken() { + }), sender); + break; + case PlaySound: + SoundData sc = cmd.GetAs(new TypeToken() { + }).getData(); + PlaySound(sc.Name, sc.Pitch); + break; + case ChatMessage: + ChatMessage(cmd.GetAs(new TypeToken() { + })); + break; + case Flip: + Flip(cmd.GetAs(new TypeToken() { + })); + break; + case PrivacySettings: + new ConfigurationManager().UpdateConfiguration(cmd.getData()); + case Countdown: + StartTimer(cmd.GetAs(new TypeToken() { + })); + break; + case GetMods: + getMods(); + break; + case ProxyRequest: + handleProxyRequest(cmd.GetAs(new TypeToken() { + }).getData()); + break; + default: + break; + } + + return true; + } + + private static void Flip(Command cmd) { + //handle chat message + ChatMessageData[] messages = cmd.getData().Messages; + SoundData sound = cmd.getData().Sound; + if (sound != null && sound.Name != null) { + PlaySound(sound.Name, sound.Pitch); + } + Command showCmd = new Command(CommandType.ChatMessage, messages); + ChatMessage(showCmd); + flipHandler.fds.Insert(cmd.getData()); + // trigger the keyevent to execute the event handler + CoflSky.Events.onKeyEvent(null); + } + + private static void handleProxyRequest(ProxyRequest[] request) { + for (ProxyRequest req : request) { + proxyManager.handleRequestAsync(req); + } + } + + + public static void cacheMods() { + File modFolder = new File(Minecraft.getMinecraft().mcDataDir, "mods"); + for (File mods : modFolder.listFiles()) { + modListData.addFilename(mods.getName()); + try { + modListData.addFileHashes(FileUtils.getMD5Checksum(mods)); + } catch (Exception exception) { + // Highly less likely to happen unless something goes wrong + exception.printStackTrace(); + } + } + + for (ModContainer mod : Loader.instance().getModList()) { + modListData.addModname(mod.getName()); + modListData.addModname(mod.getModId()); + } + } + + private static void getMods() { + // the Cofl server has asked for an mod list now let's respond with all the info + CoflSky.Wrapper.SendMessage(new RawCommand("foundMods", gson.toJson(modListData))); + } + + private static void PlaySound(String soundName, float pitch) { + SoundHandler handler = Minecraft.getMinecraft().getSoundHandler(); + + // random.explode + PositionedSoundRecord psr = PositionedSoundRecord + .create(new ResourceLocation(soundName), pitch); + + handler.playSound(psr); + } + + private static void Execute(Command cmd, Entity sender) { + System.out.println("Execute: " + cmd.getData() + " sender:" + sender); + //String dummy = WSClient.gson.fromJson(cmd.getData(), String.class); + Execute(cmd.getData(), sender); + } + + /** + * Starts a countdown + */ + private static void StartTimer(Command cmd) { + de.torui.coflsky.CountdownTimer.startCountdown(cmd.getData()); + } + + public static void Execute(String cmd, Entity sender) { + if (cmd.startsWith("/cofl") || cmd.startsWith("http")) { + ClientCommandHandler.instance.executeCommand(sender, cmd); + } else { + Minecraft.getMinecraft().thePlayer.sendChatMessage(cmd); + } + } + + + private static IChatComponent CommandToChatComponent(ChatMessageData wcmd, String fullMessage) { + if (wcmd.OnClick != null) { + if (wcmd.Text != null && wcmd.OnClick.startsWith("/viewauction")) { + lastOnClickEvent = "/cofl openAuctionGUI " + wcmd.OnClick.split(" ")[1] + " false"; + } else { + lastOnClickEvent = "/cofl callback " + wcmd.OnClick; + } + } + if (wcmd.Text != null) { + IChatComponent comp = new ChatComponentText(wcmd.Text); + + ChatStyle style; + if (wcmd.OnClick != null) { + if (wcmd.OnClick.startsWith("http")) { + style = new ChatStyle().setChatClickEvent(new ClickEvent(Action.OPEN_URL, wcmd.OnClick)); + } else { + style = new ChatStyle() + .setChatClickEvent(new ClickEvent(Action.RUN_COMMAND, lastOnClickEvent)); + } + comp.setChatStyle(style); + } + + if (wcmd.Hover != null && !wcmd.Hover.isEmpty()) { + if (comp.getChatStyle() == null) + comp.setChatStyle(new ChatStyle()); + comp.getChatStyle().setChatHoverEvent( + new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ChatComponentText(wcmd.Hover))); + } + return comp; + } + return null; + } + + public static void sendChatMessage(IChatComponent message) { + Minecraft.getMinecraft().thePlayer.addChatMessage(message); + } + + public static IChatComponent ChatMessage(Command cmd) { + ChatMessageData[] list = cmd.getData(); + + IChatComponent master = new ChatComponentText(""); + String fullMessage = ChatMessageDataToString(list); + + for (ChatMessageData wcmd : list) { + IChatComponent comp = CommandToChatComponent(wcmd, fullMessage); + if (comp != null) + master.appendSibling(comp); + } + Minecraft.getMinecraft().thePlayer.addChatMessage(master); + return master; + } + + + private static void WriteToChat(Command cmd) { + ChatMessageData wcmd = cmd.getData(); + + IChatComponent comp = CommandToChatComponent(wcmd, wcmd.Text); + if (comp != null) { + Minecraft.getMinecraft().thePlayer.addChatMessage(comp); + } + + } + + public static String ChatMessageDataToString(ChatMessageData[] messages) { + Stream stream = Arrays.stream(messages).map(message -> message.Text); + String s = String.join(",", stream.toArray(String[]::new)); + stream.close(); + return s; + } } diff --git a/src/main/java/de/torui/coflsky/commands/models/FlipData.java b/src/main/java/de/torui/coflsky/commands/models/FlipData.java index 88836d2..0fb9357 100644 --- a/src/main/java/de/torui/coflsky/commands/models/FlipData.java +++ b/src/main/java/de/torui/coflsky/commands/models/FlipData.java @@ -1,24 +1,34 @@ package de.torui.coflsky.commands.models; import com.google.gson.annotations.SerializedName; +import de.torui.coflsky.WSCommandHandler; public class FlipData { - + @SerializedName("messages") public ChatMessageData[] Messages; - @SerializedName("id") public String Id; - @SerializedName("worth") public int Worth; - - public FlipData() {} + @SerializedName("sound") + public SoundData Sound; + @SerializedName("render") + public String Render; + + public FlipData() { + } - public FlipData(ChatMessageData[] messages, String id, int worth) { + public FlipData(ChatMessageData[] messages, String id, int worth, SoundData sound, String render) { super(); Messages = messages; Id = id; Worth = worth; + Sound = sound; + Render = render; + } + + public String getMessageAsString(){ + return WSCommandHandler.ChatMessageDataToString(this.Messages); } } diff --git a/src/main/java/de/torui/coflsky/configuration/LocalConfig.java b/src/main/java/de/torui/coflsky/configuration/LocalConfig.java index 749d0bc..7e3c5f9 100644 --- a/src/main/java/de/torui/coflsky/configuration/LocalConfig.java +++ b/src/main/java/de/torui/coflsky/configuration/LocalConfig.java @@ -1,7 +1,7 @@ package de.torui.coflsky.configuration; import com.google.gson.Gson; -import com.google.gson.JsonObject; +import de.torui.coflsky.gui.GUIType; import java.io.File; import java.io.IOException; @@ -12,10 +12,14 @@ import java.nio.file.Paths; public class LocalConfig { public boolean autoStart; public boolean extendedtooltips; - public LocalConfig(boolean autoStart,boolean extendedtooltips) { + public GUIType purchaseOverlay; + + public LocalConfig(boolean autoStart, boolean extendedtooltips, GUIType purchaseOverlay) { this.autoStart = autoStart; this.extendedtooltips = extendedtooltips; + this.purchaseOverlay = purchaseOverlay; } + public static void saveConfig(File file, LocalConfig Config) { Gson gson = new Gson(); try { @@ -24,12 +28,12 @@ public class LocalConfig { } Files.write(Paths.get(file.getAbsolutePath()), gson.toJson(Config).getBytes(StandardCharsets.UTF_8)); - }catch (IOException e){ + } catch (IOException e) { e.printStackTrace(); } } public static LocalConfig createDefaultConfig() { - return new LocalConfig(true,true); + return new LocalConfig(true, true, null); } } diff --git a/src/main/java/de/torui/coflsky/gui/GUIType.java b/src/main/java/de/torui/coflsky/gui/GUIType.java new file mode 100644 index 0000000..586ac72 --- /dev/null +++ b/src/main/java/de/torui/coflsky/gui/GUIType.java @@ -0,0 +1,6 @@ +package de.torui.coflsky.gui; + +public enum GUIType { + TFM, + COFL +} diff --git a/src/main/java/de/torui/coflsky/gui/bingui/BinGuiCurrent.java b/src/main/java/de/torui/coflsky/gui/bingui/BinGuiCurrent.java new file mode 100644 index 0000000..ef5ec9c --- /dev/null +++ b/src/main/java/de/torui/coflsky/gui/bingui/BinGuiCurrent.java @@ -0,0 +1,415 @@ +package de.torui.coflsky.gui.bingui; + + +import de.torui.coflsky.CoflSky; +import de.torui.coflsky.gui.GUIType; +import de.torui.coflsky.gui.bingui.helper.ColorPallet; +import de.torui.coflsky.gui.bingui.helper.RenderUtils; +import de.torui.coflsky.handlers.EventHandler; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.gui.inventory.GuiChest; +import net.minecraft.command.NumberInvalidException; +import net.minecraft.init.Items; +import net.minecraft.inventory.ContainerChest; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.Item; +import net.minecraft.item.ItemArmor; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.client.event.ClientChatReceivedEvent; +import net.minecraftforge.client.event.GuiOpenEvent; +import net.minecraftforge.client.event.GuiScreenEvent; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.common.eventhandler.EventPriority; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; +import org.lwjgl.input.Mouse; + +import java.awt.event.MouseWheelEvent; +import java.util.Base64; +import java.util.List; +import java.util.Locale; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class BinGuiCurrent extends GuiChest { + private String message; + private String[] lore; + private ItemStack itemStack; + private String buyText = "Buy(You can click anywhere)"; + private BuyState buyState = BuyState.INIT; + private int pixelsScrolled = 0; + private boolean wasMouseDown; + private boolean isRendered = false; + private boolean hasInitialMouseSet = false; + + // set if the auction was already bought + private String buyer = null; + + private static final Pattern CAN_BUY_IN_MATCHER = Pattern.compile("Can buy in: (.*)"); + private static final Pattern BUYER_MATCHER = Pattern.compile("Buyer: (.*)"); + + private GuiChest chestGui; + + public BinGuiCurrent(IInventory playerInventory, IInventory chestInventory, String message, String extraData) { + super(chestInventory, playerInventory); + this.message = message; + this.lore = new String[]{"Loading..."}; + if (extraData.length() >= 32) { + itemStack = getSkull("Name", "00000000-0000-0000-0000-000000000000", extraData); + } else { + itemStack = new ItemStack(getItemByText(extraData)); + //if it is an armor item, we color it black + if (itemStack.getItem() == null) return; + if (itemStack.getItem() instanceof ItemArmor && (itemStack.getItem() == Items.leather_helmet || itemStack.getItem() == Items.leather_chestplate || itemStack.getItem() == Items.leather_leggings || itemStack.getItem() == Items.leather_boots)) { + ((ItemArmor) itemStack.getItem()).setColor(itemStack, 0); + } + } + MinecraftForge.EVENT_BUS.register(this); + } + + private boolean shouldSkip(GuiScreen screen) { + return !(screen instanceof GuiChest) || CoflSky.config.purchaseOverlay != GUIType.COFL || !EventHandler.isInSkyblock; + } + + @SubscribeEvent(priority = EventPriority.HIGHEST) + public void onGuiOpen(GuiOpenEvent event) { + + if (event.gui == null) { + resetGUI(); + } + + isRendered = false; + GuiScreen gui = event.gui; + + if (message == null || message.isEmpty()) { + return; + } + + if (shouldSkip(gui)) { + return; + } + + GuiChest chest = (GuiChest) gui; + + IInventory inventory = ((ContainerChest) chest.inventorySlots).getLowerChestInventory(); + if (inventory == null) return; + + String guiName = inventory.getDisplayName().getUnformattedText().trim(); + if (guiName.equalsIgnoreCase("BIN Auction View") || guiName.equalsIgnoreCase("Confirm Purchase")) { + this.chestGui = (GuiChest) event.gui; + this.inventorySlots = ((GuiChest) event.gui).inventorySlots; + event.gui = this; + } + } + + @SubscribeEvent(priority = EventPriority.HIGHEST) + public void onDrawGuiScreen(GuiScreenEvent.DrawScreenEvent.Pre event) { + isRendered = false; + GuiScreen gui = event.gui; + + if (message == null || message.isEmpty()) { + return; + } + + if (shouldSkip(gui)) { + return; + } + + GuiChest chest = (GuiChest) gui; + + IInventory inventory = ((ContainerChest) chest.inventorySlots).getLowerChestInventory(); + if (inventory == null) return; + + String guiName = inventory.getDisplayName().getUnformattedText().trim(); + if (guiName.equalsIgnoreCase("auction view")) { + return; + } + + ItemStack item = inventory.getStackInSlot(13); + if (item == null) return; + + String[] tooltip = item.getTooltip(mc.thePlayer, false).toArray(new String[0]); + + itemStack = item; + + if (guiName.equalsIgnoreCase("BIN Auction View")) { + lore = tooltip; + buyer = isAlreadyBought(tooltip); + } + if (guiName.equalsIgnoreCase("BIN Auction View") && buyState == BuyState.PURCHASE) { + if (waitingForBed(chest)) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("[§1C§6oflnet§f]§7: §cBed is not purchasable yet.")); + buyState = BuyState.INIT; + } else { + mc.playerController.windowClick(this.chestGui.inventorySlots.windowId, 31, 2, 3, mc.thePlayer); + wasMouseDown = false; + buyState = BuyState.CONFIRM; + } + } else if (guiName.equalsIgnoreCase("Confirm Purchase") && buyState == BuyState.BUYING) { + mc.playerController.windowClick(this.chestGui.inventorySlots.windowId, 11, 2, 3, mc.thePlayer); + resetGUI(); + } + } + + @Override + public void drawScreen(int mouseX, int mouseY, float partialTicks) { + Mouse.setGrabbed(false); + isRendered = true; + + int screenWidth = this.width; + int screenHeight = this.height; + + int width = mc.fontRendererObj.getStringWidth(message) > 500 ? mc.fontRendererObj.getStringWidth(message) + 5 : 500; + int height = 300; + + //RenderUtils.drawRoundedRect(screenWidth / 2, 10 + 5 + 14 + 5 + (height - 100) + 5, (width - 10) / 2 + 20, 60, 5, ColorPallet.SUCCESS.getColor()); + if (!hasInitialMouseSet) { + Mouse.setCursorPosition(mc.displayWidth / 2, mc.displayHeight / 2); + hasInitialMouseSet = true; + } + + //if (lore.length > 25) { + // height = 300 + (lore.length - 25) * 10; + //} + + //first i draw the main background + RenderUtils.drawRoundedRect(screenWidth / 2 - width / 2, 10, width, height, 10, ColorPallet.PRIMARY.getColor()); + + //next i draw the title + RenderUtils.drawRoundedRect(screenWidth / 2 - width / 2 + 5, 10 + 5, (width - 10), 14, 5, ColorPallet.SECONDARY.getColor()); + RenderUtils.drawString(message, screenWidth / 2 - width / 2 + 7, 10 + 8, ColorPallet.WHITE.getColor()); + + //now i draw the backround of the icon + RenderUtils.drawRoundedRect(screenWidth / 2 - width / 2 + 5, 10 + 5 + 14 + 5, 20, 20, 5, ColorPallet.TERTIARY.getColor()); + + //now i draw the icon + if (itemStack == null) { + //draw a question mark in the icon + RenderUtils.drawString("?", screenWidth / 2 - width / 2 + 5 + 5, 10 + 5 + 14 + 5 + 2, ColorPallet.WHITE.getColor(), 40); + } else { + RenderUtils.drawItemStack(itemStack, screenWidth / 2 - width / 2 + 5 + 2, 10 + 5 + 14 + 5 + 2); + } + + + //draw the backorund for the lore + RenderUtils.drawRoundedRect(screenWidth / 2 - width / 2 + 5 + 20 + 5, 10 + 5 + 14 + 5, (width - 10) - 25, (height - 100), 5, ColorPallet.SECONDARY.getColor()); + + //draw the lore, every line that is out of the lore background will not be drawn + int y = 10 + 5 + 14 + 5 + 2; + for (int i = 0; i < lore.length; i++) { + if (y + pixelsScrolled > 10 + 5 + 14 + 5 && y + pixelsScrolled < 10 + 5 + 14 + 5 + (height - 100)) { + RenderUtils.drawString(lore[i], screenWidth / 2 - width / 2 + 5 + 20 + 5 + 2, y + pixelsScrolled, ColorPallet.WHITE.getColor()); + } + y += 10; + } + + + //now i draw the buttons buy and sell under the lore + //cancel button + RenderUtils.drawRoundedRect(screenWidth / 2 - width / 2 + 5, 10 + 5 + 14 + 5 + (height - 100) + 5, (width - 10) / 2 - 25, 60, 5, ColorPallet.ERROR.getColor()); + RenderUtils.drawString("Cancel", screenWidth / 2 - width / 2 + 5 + 5, 10 + 5 + 14 + 5 + (height - 100) + 5 + 5, ColorPallet.WHITE.getColor(), 40); + if (isMouseOverCancel(mouseX, mouseY, screenWidth, screenHeight, width, height)) { + RenderUtils.drawRoundedRect(screenWidth / 2 - width / 2 + 5, 10 + 5 + 14 + 5 + (height - 100) + 5, (width - 10) / 2 - 25, 60, 5, RenderUtils.setAlpha(ColorPallet.WHITE.getColor(), 100)); + RenderUtils.drawString("Cancel", screenWidth / 2 - width / 2 + 5 + 5, 10 + 5 + 14 + 5 + (height - 100) + 5 + 5, ColorPallet.WHITE.getColor(), 40); + if (isClicked()) { + //play a anvilsound + mc.thePlayer.playSound("random.anvil_land", 1, 1); + resetGUI(); + mc.thePlayer.closeScreen(); + } + } + + + //buy button + if (buyer == null) { + RenderUtils.drawRoundedRect(screenWidth / 2 - width / 2 + 5 + (width - 10) / 2 - 20, 10 + 5 + 14 + 5 + (height - 100) + 5, (width - 10) / 2 + 20, 60, 5, ColorPallet.SUCCESS.getColor()); + RenderUtils.drawString(buyText, screenWidth / 2 - width / 2 + 5 + (width - 10) / 2 + 5 - 20, 10 + 5 + 14 + 5 + (height - 100) + 5 + 5, ColorPallet.WHITE.getColor(), 40); + } else { + RenderUtils.drawRoundedRect(screenWidth / 2 - width / 2 + 5 + (width - 10) / 2 - 20, 10 + 5 + 14 + 5 + (height - 100) + 5, (width - 10) / 2 + 20, 60, 5, ColorPallet.WARNING.getColor()); + RenderUtils.drawString(getAlreadyBoughtText(buyer), screenWidth / 2 - width / 2 + 5 + (width - 10) / 2 + 5 - 20, 10 + 5 + 14 + 5 + (height - 100) + 5 + 5, ColorPallet.WHITE.getColor(), 40); + } + if (!isMouseOverCancel(mouseX, mouseY, screenWidth, screenHeight, width, height)) { + if (buyer == null) { + RenderUtils.drawRoundedRect(screenWidth / 2 - width / 2 + 5 + (width - 10) / 2 - 20, 10 + 5 + 14 + 5 + (height - 100) + 5, (width - 10) / 2 + 20, 60, 5, RenderUtils.setAlpha(ColorPallet.WHITE.getColor(), 50)); + RenderUtils.drawString(buyText, screenWidth / 2 - width / 2 + 5 + (width - 10) / 2 + 5 - 20, 10 + 5 + 14 + 5 + (height - 100) + 5 + 5, ColorPallet.WHITE.getColor(), 40); + } + if (isClicked() && buyer == null) { + if (buyState == BuyState.INIT) { + //play a sound + mc.thePlayer.playSound("random.click", 1, 1); + buyText = "Click again to confirm"; + buyState = BuyState.PURCHASE; + } else if (buyState == BuyState.CONFIRM) { + mc.thePlayer.playSound("random.click", 1, 1); + buyText = "Buying"; + buyState = BuyState.BUYING; + } + } + } + + } + + public String getAlreadyBoughtText(String buyer) { + return "§5§o§7Bought by §b" + buyer; + } + + @SubscribeEvent + public void onGuiMouseInput(GuiScreenEvent.MouseInputEvent event) { + if (event.gui instanceof BinGuiCurrent) { + int dwheel = Mouse.getDWheel(); + pixelsScrolled += dwheel / 4; + } + } + + public void resetGUI() { + buyState = BuyState.INIT; + buyText = "Buy (You can click anywhere)"; + itemStack = null; + hasInitialMouseSet = false; + isRendered = false; + Mouse.setGrabbed(true); + MinecraftForge.EVENT_BUS.unregister(this); + } + + public static Item getItemByText(String id) { + try { + ResourceLocation resourcelocation = new ResourceLocation(id); + if (!Item.itemRegistry.containsKey(resourcelocation)) { + throw new NumberInvalidException("block.notFound", resourcelocation); + } + Item item = Item.itemRegistry.getObject(resourcelocation); + if (item == null) { + throw new NumberInvalidException("block.notFound", resourcelocation); + } + return item; + } catch (Exception e) { + System.out.println("Error: " + e.getMessage()); + return null; + } + + } + + public static ItemStack getSkull(String displayName, String uuid, String value) { + String url = "https://textures.minecraft.net/texture/" + value; + ItemStack render = new ItemStack(Items.skull, 1, 3); + + NBTTagCompound skullOwner = new NBTTagCompound(); + skullOwner.setString("Id", uuid); + skullOwner.setString("Name", uuid); + + byte[] encodedData = Base64.getEncoder().encode(String.format("{textures:{SKIN:{url:\"%s\"}}}", url).getBytes()); + NBTTagCompound textures_0 = new NBTTagCompound(); + textures_0.setString("Value", new String(encodedData)); + + NBTTagList textures = new NBTTagList(); + textures.appendTag(textures_0); + + NBTTagCompound display = new NBTTagCompound(); + display.setString("Name", displayName); + + NBTTagCompound tag = new NBTTagCompound(); + tag.setTag("display", display); + + NBTTagCompound properties = new NBTTagCompound(); + properties.setTag("textures", textures); + skullOwner.setTag("Properties", properties); + tag.setTag("SkullOwner", skullOwner); + render.setTagCompound(tag); + return render; + } + + @SubscribeEvent + public void onChatEvent(ClientChatReceivedEvent event) { + String message = event.message.getFormattedText().toLowerCase(Locale.ROOT); + if ( + message.contains("you have bought") || + message.contains("you don't have enough coins") || + message.contains("this auction wasn't found") || + message.contains("there was an error with the auction house") || + message.contains("you didn't participate in this auction") || + message.contains("you claimed") || + message.contains("you purchased") || + message.contains("you cannot view this auction") + ) { + //close the gui + resetGUI(); + mc.thePlayer.closeScreen(); + } + } + + public ItemStack getItem(int slotNum, GuiChest currentScreen) { + ContainerChest container = (ContainerChest) currentScreen.inventorySlots; + return container.getSlot(slotNum).getStack(); + } + + public boolean waitingForBed(GuiChest currentScreen) { + ItemStack bedStack = getItem(31, currentScreen); + if (bedStack == null || !bedStack.getItem().equals(Item.getByNameOrId("minecraft:bed"))) { + return false; + } + + ItemStack itemStack = getItem(13, currentScreen); + if (itemStack == null) { + return false; + } + List itemTooltip = itemStack.getTooltip(Minecraft.getMinecraft().thePlayer, false); + for (String data : itemTooltip) { + Matcher matcher = CAN_BUY_IN_MATCHER.matcher(EnumChatFormatting.getTextWithoutFormattingCodes(data)); + if (!matcher.find()) { + continue; + } + String timeData = matcher.group(1); + if (timeData.equals("Soon!")) { + return true; + } + } + return false; + } + + public String isAlreadyBought(String[] tooltip) { + for (String data : tooltip) { + Matcher matcher = BUYER_MATCHER.matcher(EnumChatFormatting.getTextWithoutFormattingCodes(data)); + if (!matcher.find()) { + continue; + } + return data.replaceAll("§5§o§7Buyer: ", ""); + } + return null; + } + + private static boolean isMouseOverCancel(int mouseX, int mouseY, int screenWidth, int screenHeight, int width, int height) { + return mouseX > screenWidth / 2 - width / 2 + 5 && mouseX < screenWidth / 2 - width / 2 + 5 + (width - 10) / 2 - 25 && mouseY > 10 + 5 + 14 + 5 + (height - 100) + 5 && mouseY < 10 + 5 + 14 + 5 + (height - 100) + 5 + 60; + } + + private static boolean isMouseOverAccept(int mouseX, int mouseY, int screenWidth, int screenHeight, int width, int height) { + return mouseX > screenWidth / 2 - width / 2 + 5 + (width - 10) / 2 - 20 && mouseX < (screenWidth / 2 - width / 2 + 5 + (width - 10) / 2 - 20) + (width - 10) / 2 + 20 && mouseY > 10 + 5 + 14 + 5 + (height - 100) + 5 && mouseY < 10 + 5 + 14 + 5 + (height - 100) + 5 + 60; + } + + public boolean isClicked() { + return wasMouseDown && !Mouse.isButtonDown(0); + } + + @SubscribeEvent + public void onRenderEvent(TickEvent.RenderTickEvent event) { + if (Minecraft.getMinecraft() == null) return; + if (event.phase == TickEvent.Phase.END) { + wasMouseDown = Mouse.isButtonDown(0); + } + } + + @SubscribeEvent + public void onMouseClicked(GuiScreenEvent.MouseInputEvent.Pre event) { + if (!Mouse.getEventButtonState()) { + return; + } + if (isRendered) { + event.setCanceled(true); + } + } +} diff --git a/src/main/java/de/torui/coflsky/gui/bingui/BinGuiManager.java b/src/main/java/de/torui/coflsky/gui/bingui/BinGuiManager.java new file mode 100644 index 0000000..db0b110 --- /dev/null +++ b/src/main/java/de/torui/coflsky/gui/bingui/BinGuiManager.java @@ -0,0 +1,19 @@ +package de.torui.coflsky.gui.bingui; + +import de.torui.coflsky.CoflSky; +import de.torui.coflsky.gui.GUIType; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.inventory.GuiChest; +import org.lwjgl.input.Mouse; + +public class BinGuiManager { + + public static void openNewFlipGui(String message, String extraData) { + if( CoflSky.config.purchaseOverlay != GUIType.COFL){ + return; + } + GuiChest currentGui = new BinGuiCurrent(Minecraft.getMinecraft().thePlayer.inventory, null, message, extraData); + Mouse.setGrabbed(false); + Minecraft.getMinecraft().displayGuiScreen(currentGui); + } +} \ No newline at end of file diff --git a/src/main/java/de/torui/coflsky/gui/bingui/BuyState.java b/src/main/java/de/torui/coflsky/gui/bingui/BuyState.java new file mode 100644 index 0000000..7e935e2 --- /dev/null +++ b/src/main/java/de/torui/coflsky/gui/bingui/BuyState.java @@ -0,0 +1,8 @@ +package de.torui.coflsky.gui.bingui; + +public enum BuyState { + INIT, + PURCHASE, + CONFIRM, + BUYING +} diff --git a/src/main/java/de/torui/coflsky/gui/bingui/helper/ColorPallet.java b/src/main/java/de/torui/coflsky/gui/bingui/helper/ColorPallet.java new file mode 100644 index 0000000..c67f9be --- /dev/null +++ b/src/main/java/de/torui/coflsky/gui/bingui/helper/ColorPallet.java @@ -0,0 +1,25 @@ +package de.torui.coflsky.gui.bingui.helper; + +import java.awt.*; + +public enum ColorPallet { + //could be changed through a config or something + PRIMARY(new Color(34, 40, 49, 255)), + SECONDARY(new Color(57, 62, 70, 255)), + TERTIARY(new Color(0, 173, 181, 255)), + WHITE(new Color(238, 238, 238, 255)), + ERROR(new Color(178, 30, 30, 255)), + SUCCESS(new Color(114, 208, 0, 255)), + WARNING(new Color(208, 121, 22, 255)), + INFO(new Color(204, 253, 233, 255)); + + private Color color; + + ColorPallet(Color color) { + this.color = color; + } + + public Color getColor() { + return color; + } +} diff --git a/src/main/java/de/torui/coflsky/gui/bingui/helper/GuiUtilsClone.java b/src/main/java/de/torui/coflsky/gui/bingui/helper/GuiUtilsClone.java new file mode 100644 index 0000000..d59d3af --- /dev/null +++ b/src/main/java/de/torui/coflsky/gui/bingui/helper/GuiUtilsClone.java @@ -0,0 +1,349 @@ +/* + * Forge Mod Loader + * Copyright (c) 2012-2014 cpw. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser Public License v2.1 + * which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * + * Contributors (this class): + * bspkrs - implementation + */ + +package de.torui.coflsky.gui.bingui.helper; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +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.util.ResourceLocation; +import org.lwjgl.opengl.GL11; + +import java.util.ArrayList; +import java.util.List; + +/** + * This class provides several methods and constants used by the Config GUI classes. + * + * @author bspkrs + */ +public class GuiUtilsClone { + public static final String UNDO_CHAR = "\u21B6"; + public static final String RESET_CHAR = "\u2604"; + public static final String VALID = "\u2714"; + public static final String INVALID = "\u2715"; + + public static int[] colorCodes = new int[]{0, 170, 43520, 43690, 11141120, 11141290, 16755200, 11184810, 5592405, 5592575, 5635925, 5636095, 16733525, 16733695, 16777045, 16777215, + 0, 42, 10752, 10794, 2752512, 2752554, 2763264, 2763306, 1381653, 1381695, 1392405, 1392447, 4134165, 4134207, 4144917, 4144959}; + + public static int getColorCode(char c, boolean isLighter) { + return colorCodes[isLighter ? "0123456789abcdef".indexOf(c) : "0123456789abcdef".indexOf(c) + 16]; + } + + /** + * Draws a textured box of any size (smallest size is borderSize * 2 square) based on a fixed size textured box with continuous borders + * and filler. It is assumed that the desired texture ResourceLocation object has been bound using + * Minecraft.getMinecraft().getTextureManager().bindTexture(resourceLocation). + * + * @param x x axis offset + * @param y y axis offset + * @param u bound resource location image x offset + * @param v bound resource location image y offset + * @param width the desired box width + * @param height the desired box height + * @param textureWidth the width of the box texture in the resource location image + * @param textureHeight the height of the box texture in the resource location image + * @param borderSize the size of the box's borders + * @param zLevel the zLevel to draw at + */ + public static void drawContinuousTexturedBox(int x, int y, int u, int v, int width, int height, int textureWidth, int textureHeight, + int borderSize, float zLevel) { + drawContinuousTexturedBox(x, y, u, v, width, height, textureWidth, textureHeight, borderSize, borderSize, borderSize, borderSize, zLevel); + } + + /** + * Draws a textured box of any size (smallest size is borderSize * 2 square) based on a fixed size textured box with continuous borders + * and filler. The provided ResourceLocation object will be bound using + * Minecraft.getMinecraft().getTextureManager().bindTexture(resourceLocation). + * + * @param res the ResourceLocation object that contains the desired image + * @param x x axis offset + * @param y y axis offset + * @param u bound resource location image x offset + * @param v bound resource location image y offset + * @param width the desired box width + * @param height the desired box height + * @param textureWidth the width of the box texture in the resource location image + * @param textureHeight the height of the box texture in the resource location image + * @param borderSize the size of the box's borders + * @param zLevel the zLevel to draw at + */ + public static void drawContinuousTexturedBox(ResourceLocation res, int x, int y, int u, int v, int width, int height, int textureWidth, int textureHeight, + int borderSize, float zLevel) { + drawContinuousTexturedBox(res, x, y, u, v, width, height, textureWidth, textureHeight, borderSize, borderSize, borderSize, borderSize, zLevel); + } + + /** + * Draws a textured box of any size (smallest size is borderSize * 2 square) based on a fixed size textured box with continuous borders + * and filler. The provided ResourceLocation object will be bound using + * Minecraft.getMinecraft().getTextureManager().bindTexture(resourceLocation). + * + * @param res the ResourceLocation object that contains the desired image + * @param x x axis offset + * @param y y axis offset + * @param u bound resource location image x offset + * @param v bound resource location image y offset + * @param width the desired box width + * @param height the desired box height + * @param textureWidth the width of the box texture in the resource location image + * @param textureHeight the height of the box texture in the resource location image + * @param topBorder the size of the box's top border + * @param bottomBorder the size of the box's bottom border + * @param leftBorder the size of the box's left border + * @param rightBorder the size of the box's right border + * @param zLevel the zLevel to draw at + */ + public static void drawContinuousTexturedBox(ResourceLocation res, int x, int y, int u, int v, int width, int height, int textureWidth, int textureHeight, + int topBorder, int bottomBorder, int leftBorder, int rightBorder, float zLevel) { + Minecraft.getMinecraft().getTextureManager().bindTexture(res); + drawContinuousTexturedBox(x, y, u, v, width, height, textureWidth, textureHeight, topBorder, bottomBorder, leftBorder, rightBorder, zLevel); + } + + /** + * Draws a textured box of any size (smallest size is borderSize * 2 square) based on a fixed size textured box with continuous borders + * and filler. It is assumed that the desired texture ResourceLocation object has been bound using + * Minecraft.getMinecraft().getTextureManager().bindTexture(resourceLocation). + * + * @param x x axis offset + * @param y y axis offset + * @param u bound resource location image x offset + * @param v bound resource location image y offset + * @param width the desired box width + * @param height the desired box height + * @param textureWidth the width of the box texture in the resource location image + * @param textureHeight the height of the box texture in the resource location image + * @param topBorder the size of the box's top border + * @param bottomBorder the size of the box's bottom border + * @param leftBorder the size of the box's left border + * @param rightBorder the size of the box's right border + * @param zLevel the zLevel to draw at + */ + public static void drawContinuousTexturedBox(int x, int y, int u, int v, int width, int height, int textureWidth, int textureHeight, + int topBorder, int bottomBorder, int leftBorder, int rightBorder, float zLevel) { + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + GlStateManager.enableBlend(); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, 1, 0); + + int fillerWidth = textureWidth - leftBorder - rightBorder; + int fillerHeight = textureHeight - topBorder - bottomBorder; + int canvasWidth = width - leftBorder - rightBorder; + int canvasHeight = height - topBorder - bottomBorder; + int xPasses = canvasWidth / fillerWidth; + int remainderWidth = canvasWidth % fillerWidth; + int yPasses = canvasHeight / fillerHeight; + int remainderHeight = canvasHeight % fillerHeight; + + // Draw Border + // Top Left + drawTexturedModalRect(x, y, u, v, leftBorder, topBorder, zLevel); + // Top Right + drawTexturedModalRect(x + leftBorder + canvasWidth, y, u + leftBorder + fillerWidth, v, rightBorder, topBorder, zLevel); + // Bottom Left + drawTexturedModalRect(x, y + topBorder + canvasHeight, u, v + topBorder + fillerHeight, leftBorder, bottomBorder, zLevel); + // Bottom Right + drawTexturedModalRect(x + leftBorder + canvasWidth, y + topBorder + canvasHeight, u + leftBorder + fillerWidth, v + topBorder + fillerHeight, rightBorder, bottomBorder, zLevel); + + for (int i = 0; i < xPasses + (remainderWidth > 0 ? 1 : 0); i++) { + // Top Border + drawTexturedModalRect(x + leftBorder + (i * fillerWidth), y, u + leftBorder, v, (i == xPasses ? remainderWidth : fillerWidth), topBorder, zLevel); + // Bottom Border + drawTexturedModalRect(x + leftBorder + (i * fillerWidth), y + topBorder + canvasHeight, u + leftBorder, v + topBorder + fillerHeight, (i == xPasses ? remainderWidth : fillerWidth), bottomBorder, zLevel); + + // Throw in some filler for good measure + for (int j = 0; j < yPasses + (remainderHeight > 0 ? 1 : 0); j++) + drawTexturedModalRect(x + leftBorder + (i * fillerWidth), y + topBorder + (j * fillerHeight), u + leftBorder, v + topBorder, (i == xPasses ? remainderWidth : fillerWidth), (j == yPasses ? remainderHeight : fillerHeight), zLevel); + } + + // Side Borders + for (int j = 0; j < yPasses + (remainderHeight > 0 ? 1 : 0); j++) { + // Left Border + drawTexturedModalRect(x, y + topBorder + (j * fillerHeight), u, v + topBorder, leftBorder, (j == yPasses ? remainderHeight : fillerHeight), zLevel); + // Right Border + drawTexturedModalRect(x + leftBorder + canvasWidth, y + topBorder + (j * fillerHeight), u + leftBorder + fillerWidth, v + topBorder, rightBorder, (j == yPasses ? remainderHeight : fillerHeight), zLevel); + } + } + + public static void drawTexturedModalRect(int x, int y, int u, int v, int width, int height, float zLevel) { + float uScale = 1f / 0x100; + float vScale = 1f / 0x100; + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer wr = tessellator.getWorldRenderer(); + wr.begin(7, DefaultVertexFormats.POSITION_TEX); + wr.pos(x, y + height, zLevel).tex(u * uScale, ((v + height) * vScale)).endVertex(); + wr.pos(x + width, y + height, zLevel).tex((u + width) * uScale, ((v + height) * vScale)).endVertex(); + wr.pos(x + width, y, zLevel).tex((u + width) * uScale, (v * vScale)).endVertex(); + wr.pos(x, y, zLevel).tex(u * uScale, (v * vScale)).endVertex(); + tessellator.draw(); + } + + /** + * Draws a tooltip box on the screen with text in it. + * Automatically positions the box relative to the mouse to match Mojang's implementation. + * Automatically wraps text when there is not enough space on the screen to display the text without wrapping. + * Can have a maximum width set to avoid creating very wide tooltips. + * + * @param textLines the lines of text to be drawn in a hovering tooltip box. + * @param mouseX the mouse X position + * @param mouseY the mouse Y position + * @param screenWidth the available screen width for the tooltip to drawn in + * @param screenHeight the available screen height for the tooltip to drawn in + * @param maxTextWidth the maximum width of the text in the tooltip box. + * Set to a negative number to have no max width. + * @param font the font for drawing the text in the tooltip box + */ + public static void drawHoveringText(List 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 + 4; + 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 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 + 4; + 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; + drawGradientRect(zLevel, tooltipX - 3, tooltipY - 4, tooltipX + tooltipTextWidth + 3, tooltipY - 3, backgroundColor, backgroundColor); + drawGradientRect(zLevel, tooltipX - 3, tooltipY + tooltipHeight + 3, tooltipX + tooltipTextWidth + 3, tooltipY + tooltipHeight + 4, backgroundColor, backgroundColor); + drawGradientRect(zLevel, tooltipX - 3, tooltipY - 3, tooltipX + tooltipTextWidth + 3, tooltipY + tooltipHeight + 3, backgroundColor, backgroundColor); + drawGradientRect(zLevel, tooltipX - 4, tooltipY - 3, tooltipX - 3, tooltipY + tooltipHeight + 3, backgroundColor, backgroundColor); + drawGradientRect(zLevel, tooltipX + tooltipTextWidth + 3, tooltipY - 3, tooltipX + tooltipTextWidth + 4, tooltipY + tooltipHeight + 3, backgroundColor, backgroundColor); + final int borderColorStart = 0x505000FF; + final int borderColorEnd = (borderColorStart & 0xFEFEFE) >> 1 | borderColorStart & 0xFF000000; + drawGradientRect(zLevel, tooltipX - 3, tooltipY - 3 + 1, tooltipX - 3 + 1, tooltipY + tooltipHeight + 3 - 1, borderColorStart, borderColorEnd); + drawGradientRect(zLevel, tooltipX + tooltipTextWidth + 2, tooltipY - 3 + 1, tooltipX + tooltipTextWidth + 3, tooltipY + tooltipHeight + 3 - 1, borderColorStart, borderColorEnd); + drawGradientRect(zLevel, tooltipX - 3, tooltipY - 3, tooltipX + tooltipTextWidth + 3, tooltipY - 3 + 1, borderColorStart, borderColorStart); + drawGradientRect(zLevel, tooltipX - 3, tooltipY + tooltipHeight + 2, tooltipX + tooltipTextWidth + 3, tooltipY + tooltipHeight + 3, borderColorEnd, 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(); + } + } + + public static void drawGradientRect(int zLevel, int left, int top, int right, int bottom, int startColor, int endColor) { + float startAlpha = (float) (startColor >> 24 & 255) / 255.0F; + float startRed = (float) (startColor >> 16 & 255) / 255.0F; + float startGreen = (float) (startColor >> 8 & 255) / 255.0F; + float startBlue = (float) (startColor & 255) / 255.0F; + float endAlpha = (float) (endColor >> 24 & 255) / 255.0F; + float endRed = (float) (endColor >> 16 & 255) / 255.0F; + float endGreen = (float) (endColor >> 8 & 255) / 255.0F; + float endBlue = (float) (endColor & 255) / 255.0F; + + GlStateManager.disableTexture2D(); + GlStateManager.enableBlend(); + GlStateManager.disableAlpha(); + GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0); + GlStateManager.shadeModel(7425); + + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer worldrenderer = tessellator.getWorldRenderer(); + worldrenderer.begin(7, DefaultVertexFormats.POSITION_COLOR); + worldrenderer.pos(right, top, zLevel).color(startRed, startGreen, startBlue, startAlpha).endVertex(); + worldrenderer.pos(left, top, zLevel).color(startRed, startGreen, startBlue, startAlpha).endVertex(); + worldrenderer.pos(left, bottom, zLevel).color(endRed, endGreen, endBlue, endAlpha).endVertex(); + worldrenderer.pos(right, bottom, zLevel).color(endRed, endGreen, endBlue, endAlpha).endVertex(); + tessellator.draw(); + + GlStateManager.shadeModel(7424); + GlStateManager.disableBlend(); + GlStateManager.enableAlpha(); + GlStateManager.enableTexture2D(); + } +} diff --git a/src/main/java/de/torui/coflsky/gui/bingui/helper/RenderUtils.java b/src/main/java/de/torui/coflsky/gui/bingui/helper/RenderUtils.java new file mode 100644 index 0000000..64b2594 --- /dev/null +++ b/src/main/java/de/torui/coflsky/gui/bingui/helper/RenderUtils.java @@ -0,0 +1,367 @@ +package de.torui.coflsky.gui.bingui.helper; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.client.renderer.entity.RenderItem; +import net.minecraft.item.ItemStack; +import org.jetbrains.annotations.NotNull; +import org.lwjgl.opengl.GL11; + +import java.awt.*; + + +/** + * Created by ForBai + */ +public class RenderUtils { + public static Minecraft mc = Minecraft.getMinecraft(); + + //draw a rectangle + public static void drawRect(float x, float y, float width, float height, int color) { + float alpha = (float) (color >> 24 & 255) / 255.0F; + float red = (float) (color >> 16 & 255) / 255.0F; + float green = (float) (color >> 8 & 255) / 255.0F; + float blue = (float) (color & 255) / 255.0F; + GL11.glEnable(GL11.GL_BLEND); + GL11.glDisable(GL11.GL_TEXTURE_2D); + GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + GL11.glColor4f(red, green, blue, alpha); + GL11.glBegin(GL11.GL_QUADS); + GL11.glVertex2d(x, y); + GL11.glVertex2d(x, y + height); + GL11.glVertex2d(x + width, y + height); + GL11.glVertex2d(x + width, y); + GL11.glEnd(); + GL11.glEnable(GL11.GL_TEXTURE_2D); + GL11.glDisable(GL11.GL_BLEND); + } + + + //draws an outlined rectangle with a given color and size and a given line width + public static void drawRectOutline(int x, int y, int width, int height, float lineWidth, Color color) { + GL11.glEnable(GL11.GL_BLEND); + GL11.glDisable(GL11.GL_TEXTURE_2D); + GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + setColor(color); + GL11.glLineWidth(lineWidth); + GL11.glBegin(GL11.GL_LINE_LOOP); + GL11.glVertex2d(x, y); + GL11.glVertex2d(x + width, y); + GL11.glVertex2d(x + width, y + height); + GL11.glVertex2d(x, y + height); + GL11.glEnd(); + GL11.glEnable(GL11.GL_TEXTURE_2D); + GL11.glDisable(GL11.GL_BLEND); + } + + //draws a circle with a given radius and thickness + public static void drawCircle(int x, int y, int radius, Color color) { + GL11.glEnable(GL11.GL_BLEND); + GL11.glDisable(GL11.GL_TEXTURE_2D); + GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + setColor(color); + GL11.glBegin(GL11.GL_TRIANGLE_FAN); + GL11.glVertex2d(x, y); + for (int i = 0; i <= 360; i++) { + GL11.glVertex2d(x + Math.sin(i * Math.PI / 180) * radius, y + Math.cos(i * Math.PI / 180) * radius); + } + GL11.glEnd(); + GL11.glEnable(GL11.GL_TEXTURE_2D); + GL11.glDisable(GL11.GL_BLEND); + } + + //draws a circle outline with a given radius and thickness + public static void drawCircleOutline(int x, int y, float radius, float thickness, Color color) { + GL11.glEnable(GL11.GL_BLEND); + GL11.glDisable(GL11.GL_TEXTURE_2D); + GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + setColor(color); + GL11.glBegin(GL11.GL_LINE_LOOP); + for (int i = 0; i <= 360; i++) { + GL11.glVertex2d(x + Math.sin(i * Math.PI / 180) * radius, y + Math.cos(i * Math.PI / 180) * radius); + } + GL11.glEnd(); + GL11.glEnable(GL11.GL_TEXTURE_2D); + GL11.glDisable(GL11.GL_BLEND); + } + + //draws line from x1,y1 to x2,y2 with a given color and thickness + public static void drawLine(float x1, float y1, float x2, float y2, float thickness, Color color) { + GL11.glEnable(GL11.GL_BLEND); + GL11.glDisable(GL11.GL_TEXTURE_2D); + GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + setColor(color); + GL11.glLineWidth(thickness); + GL11.glBegin(GL11.GL_LINES); + GL11.glVertex2d(x1, y1); + GL11.glVertex2d(x2, y2); + GL11.glEnd(); + GL11.glEnable(GL11.GL_TEXTURE_2D); + GL11.glDisable(GL11.GL_BLEND); + } + + //draws a triangle from x1,y1 to x2,y2 to x3,y3 + public static void drawTriangle(int x, int y, int x2, int y2, int x3, int y3, Color color) { + GL11.glEnable(GL11.GL_BLEND); + GL11.glDisable(GL11.GL_TEXTURE_2D); + GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + setColor(color); + GL11.glBegin(GL11.GL_TRIANGLES); + GL11.glVertex2d(x, y); + GL11.glVertex2d(x2, y2); + GL11.glVertex2d(x3, y3); + GL11.glEnd(); + GL11.glEnable(GL11.GL_TEXTURE_2D); + GL11.glDisable(GL11.GL_BLEND); + } + + //draws a triangle outline from x1,y1 to x2,y2 to x3,y3 + public static void drawTriangleOutline(int x, int y, int x2, int y2, int x3, int y3, Color color) { + GL11.glEnable(GL11.GL_BLEND); + GL11.glDisable(GL11.GL_TEXTURE_2D); + GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + setColor(color); + GL11.glBegin(GL11.GL_LINE_LOOP); + GL11.glVertex2d(x, y); + GL11.glVertex2d(x2, y2); + GL11.glVertex2d(x3, y3); + GL11.glEnd(); + GL11.glEnable(GL11.GL_TEXTURE_2D); + GL11.glDisable(GL11.GL_BLEND); + } + + //draws an arc with a given radius, start angle, and end angle + public static void drawArc(int x, int y, int radius, int startAngle, int endAngle, Color color) { + GL11.glEnable(GL11.GL_BLEND); + GL11.glDisable(GL11.GL_TEXTURE_2D); + GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + setColor(color); + GL11.glBegin(GL11.GL_TRIANGLE_FAN); + GL11.glVertex2d(x, y); + for (int i = startAngle; i <= endAngle; i++) { + GL11.glVertex2d(x + Math.sin(i * Math.PI / 180) * radius, y + Math.cos(i * Math.PI / 180) * radius); + } + GL11.glEnd(); + GL11.glEnable(GL11.GL_TEXTURE_2D); + GL11.glDisable(GL11.GL_BLEND); + } + + + //draw a loading circle with a given radius, thickness, and speed + public static void drawLoadingCircle(float x, float y, float radius, float thickness, float speed, Color color) { + GL11.glEnable(GL11.GL_BLEND); + GL11.glDisable(GL11.GL_TEXTURE_2D); + GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + setColor(color); + GL11.glLineWidth(thickness); + GL11.glBegin(GL11.GL_LINE_STRIP); + for (int i = 0; i <= 360; i++) { + GL11.glVertex2d(x + Math.sin((i + speed) * Math.PI / 180) * radius, y + Math.cos((i + speed) * Math.PI / 180) * radius); + } + GL11.glEnd(); + GL11.glEnable(GL11.GL_TEXTURE_2D); + GL11.glDisable(GL11.GL_BLEND); + } + + //draws a rounded rectangle with a given radius and color and size + public static void drawRoundedRect(int x, int y, int width, int height, int radius, @NotNull Color color) { + + //draw the two rectangles + drawRect(x + radius, y, width - radius * 2, height, color.getRGB()); + drawRect(x, y + radius, radius, height - radius * 2, color.getRGB()); + drawRect(x + width - radius, y + radius, radius, height - radius * 2, color.getRGB()); + + //drawRect(x + radius, y, width - radius - radius, height, color.getRGB()); + //drawRect(x, y + radius, width, height - radius - radius, color.getRGB()); + //draw the circles + drawArc(x + radius, y + radius, radius, 180, 270, color); + drawArc(x + width - radius, y + radius, radius, 90, 180, color); + drawArc(x + radius, y + height - radius, radius, 270, 360, color); + drawArc(x + width - radius, y + height - radius, radius, 0, 90, color); + + //drawCircle(x + radius, y + radius, radius, color); + //drawCircle(x + width - radius, y + radius, radius, color); + //drawCircle(x + radius, y + height - radius, radius, color); + //drawCircle(x + width - radius, y + height - radius, radius, color); + + //drawRectOutline(x, y, width, height, 1, Color.GREEN); + } + + //draws a gradient rectangle with a given color and size + public static void drawGradientRect(int x, int y, int width, int height, Color color1, Color color2) { + GL11.glEnable(GL11.GL_BLEND); + GL11.glDisable(GL11.GL_TEXTURE_2D); + GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + GL11.glShadeModel(GL11.GL_SMOOTH); + GL11.glBegin(GL11.GL_QUADS); + setColor(color1); + GL11.glVertex2d(x, y); + GL11.glVertex2d(x + width, y); + setColor(color2); + GL11.glVertex2d(x + width, y + height); + GL11.glVertex2d(x, y + height); + GL11.glEnd(); + GL11.glShadeModel(GL11.GL_FLAT); + GL11.glEnable(GL11.GL_TEXTURE_2D); + GL11.glDisable(GL11.GL_BLEND); + } + + + public static void drawString(String text, int x, int y, Color color) { + setColor(color); + mc.fontRendererObj.drawString(text, x, y, color.getRGB()); + } + + public static void drawStringWithShadow(String text, int x, int y, Color color) { + setColor(color); + mc.fontRendererObj.drawStringWithShadow(text, x, y, color.getRGB()); + } + + public static void drawCenteredString(String text, int x, int y, Color color) { + setColor(color); + mc.fontRendererObj.drawString(text, x - mc.fontRendererObj.getStringWidth(text) / 2, y, color.getRGB()); + } + + public static void drawCenteredStringWithShadow(String text, int x, int y, Color color) { + setColor(color); + mc.fontRendererObj.drawStringWithShadow(text, x - mc.fontRendererObj.getStringWidth(text) / 2, y, color.getRGB()); + } + + //draws a string with custom scale + public static void drawString(String text, int x, int y, Color color, int scale) { + setColor(color); + FontRenderer fr = mc.fontRendererObj; + fr.drawString(text, x, y, color.getRGB()); + } + + //draws a string with custom scale and shadow + public static void drawStringWithShadow(String text, int x, int y, Color color, int scale) { + setColor(color); + FontRenderer fr = mc.fontRendererObj; + fr.drawStringWithShadow(text, x, y, color.getRGB()); + } + + public static void drawCenteredString(String text, int x, int y, Color color, int scale) { + setColor(color); + FontRenderer fr = mc.fontRendererObj; + fr.drawString(text, x - fr.getStringWidth(text) / 2, y, color.getRGB()); + } + + public static void drawCenteredStringWithShadow(String text, int x, int y, Color color, int scale) { + setColor(color); + FontRenderer fr = mc.fontRendererObj; + fr.drawStringWithShadow(text, x - fr.getStringWidth(text) / 2, y, color.getRGB()); + } + + public static void drawCenteredStringWithShadow(String text, int x, int y, Color color, int scale, boolean centered) { + setColor(color); + FontRenderer fr = mc.fontRendererObj; + if (centered) { + fr.drawStringWithShadow(text, x - fr.getStringWidth(text) / 2, y, color.getRGB()); + } else { + fr.drawStringWithShadow(text, x, y, color.getRGB()); + } + } + + //draws an ItemStack at a given position with a given scale + public static void drawItemStack(ItemStack itemStack, int x, int y, float scale) { + GL11.glPushMatrix(); + GL11.glScalef(scale, scale, scale); + mc.getRenderItem().renderItemIntoGUI(itemStack, x, y); + GL11.glPopMatrix(); + } + + public static void drawItemStackWithText(ItemStack stack, int x, int y, String text) { + if (stack == null) return; + RenderItem itemRender = Minecraft.getMinecraft().getRenderItem(); + setColor(Color.WHITE); + RenderHelper.enableGUIStandardItemLighting(); + itemRender.zLevel = -145; + itemRender.renderItemAndEffectIntoGUI(stack, x, y); + itemRender.renderItemOverlayIntoGUI(Minecraft.getMinecraft().fontRendererObj, stack, x, y, text); + itemRender.zLevel = 0; + RenderHelper.disableStandardItemLighting(); + } + + public static void drawItemStack(ItemStack stack, int x, int y) { + drawItemStackWithText(stack, x, y, null); + } + + public static void drawItemStack(ItemStack itemStack, int x, int y, float scaleX, float scaleY) { + GL11.glPushMatrix(); + GL11.glScalef(scaleX, scaleY, 0); + drawItemStack(itemStack, x, y); + GL11.glPopMatrix(); + } + + //draw centered ItemStack at a given position with a given scale + public static void drawCenteredItemStack(ItemStack itemStack, int x, int y, float scale) { + GL11.glPushMatrix(); + GL11.glScalef(scale, scale, scale); + drawItemStack(itemStack, (int) (x - (scale / 2)), (int) (y - (scale / 2))); + GL11.glPopMatrix(); + } + + //draw a check mar with a given color and size using lines + public static void drawCheckMark(int x, int y, int size, Color color) { + GL11.glPushMatrix(); + GL11.glEnable(GL11.GL_BLEND); + GL11.glDisable(GL11.GL_TEXTURE_2D); + GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + GL11.glLineWidth(2); + setColor(color); + GL11.glBegin(GL11.GL_LINES); + GL11.glVertex2d(x, y + size / 2); + GL11.glVertex2d(x + size / 2, y + size); + GL11.glVertex2d(x + size / 2, y + size); + GL11.glVertex2d(x + size, y); + GL11.glEnd(); + GL11.glEnable(GL11.GL_TEXTURE_2D); + GL11.glDisable(GL11.GL_BLEND); + GL11.glPopMatrix(); + } + + //draw a cross mark with a given color and start and end points + public static void drawCrossMark(int x, int y, int x2, int y2, Color color) { + GL11.glPushMatrix(); + GL11.glEnable(GL11.GL_BLEND); + GL11.glDisable(GL11.GL_TEXTURE_2D); + GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + GL11.glLineWidth(2); + setColor(color); + GL11.glBegin(GL11.GL_LINES); + GL11.glVertex2d(x, y); + GL11.glVertex2d(x2, y2); + GL11.glVertex2d(x2, y); + GL11.glVertex2d(x, y2); + GL11.glEnd(); + GL11.glEnable(GL11.GL_TEXTURE_2D); + GL11.glDisable(GL11.GL_BLEND); + GL11.glPopMatrix(); + } + + + //set alpha of color + public static Color setAlpha(Color color, int alpha) { + return new Color(color.getRed(), color.getGreen(), color.getBlue(), alpha); + } + + //set color + public static void setColor(int color) { + float alpha = (float) (color >> 24 & 255) / 255.0F; + float red = (float) (color >> 16 & 255) / 255.0F; + float green = (float) (color >> 8 & 255) / 255.0F; + float blue = (float) (color & 255) / 255.0F; + GL11.glColor4f(red, green, blue, alpha); + } + + public static void setColor(Color color) { + setColor(color.getRGB()); + } + + //rotate + public static void rotate(float angle) { + GL11.glRotatef(angle, 0.0F, 0.0F, 1.0F); + } +} diff --git a/src/main/java/de/torui/coflsky/gui/tfm/ButtonRemapper.java b/src/main/java/de/torui/coflsky/gui/tfm/ButtonRemapper.java new file mode 100644 index 0000000..2d48434 --- /dev/null +++ b/src/main/java/de/torui/coflsky/gui/tfm/ButtonRemapper.java @@ -0,0 +1,338 @@ +package de.torui.coflsky.gui.tfm; + +import de.torui.coflsky.CoflSky; +import de.torui.coflsky.WSCommandHandler; +import de.torui.coflsky.gui.GUIType; +import de.torui.coflsky.handlers.EventHandler; +import de.torui.coflsky.handlers.EventRegistry; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.gui.inventory.GuiChest; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.inventory.ContainerChest; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumChatFormatting; +import net.minecraftforge.client.event.GuiScreenEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.relauncher.ReflectionHelper; +import org.lwjgl.input.Mouse; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static net.minecraft.client.gui.Gui.drawRect; + +public class ButtonRemapper { + private static ButtonRemapper instance; + private final static int BUY_BUTTON_SLOT = 31; + private final static int ITEM_SLOT = 13; + private final static int CONFIRM_BUTTON_SLOT = 11; + private final static int CANCEL_CONFIRM_SLOT = 15; + private final static int BACK_BUTTON_SLOT = 49; + private final static double SCALE_VALUE = 2.0d; + private final static Pattern BED_TIME_PATTERN = Pattern.compile("Can buy in: (.*)"); + + private final Method drawItemMethod; + private final Method renderToolTipMethod; + + private ButtonRemapper() { + // drawItemStack obfuscated + String[] methodNames = new String[]{"drawItemStack", "func_146982_a"}; + drawItemMethod = ReflectionHelper.findMethod(GuiContainer.class, null, methodNames, ItemStack.class, int.class, int.class, String.class); + drawItemMethod.setAccessible(true); + // obfuscated renderToolTip method + methodNames = new String[]{"renderToolTip", "func_146285_a"}; + renderToolTipMethod = ReflectionHelper.findMethod(GuiScreen.class, null, methodNames, ItemStack.class, int.class, int.class); + } + + public static ButtonRemapper getInstance() { + if (instance == null) { + instance = new ButtonRemapper(); + } + return instance; + } + + public ItemStack getItem(int slotNum, GuiChest currentScreen) { + ContainerChest container = (ContainerChest) currentScreen.inventorySlots; + return container.getSlot(slotNum).getStack(); + } + + public boolean waitingForBed(GuiChest currentScreen) { + ItemStack bedStack = getItem(BUY_BUTTON_SLOT, currentScreen); + if (bedStack == null || !bedStack.getItem().equals(Item.getByNameOrId("minecraft:bed"))) { + return false; + } + + ItemStack itemStack = getItem(ITEM_SLOT, currentScreen); + if (itemStack == null) { + return false; + } + List itemTooltip = itemStack.getTooltip(Minecraft.getMinecraft().thePlayer, false); + for (String data : itemTooltip) { + Matcher matcher = BED_TIME_PATTERN.matcher(EnumChatFormatting.getTextWithoutFormattingCodes(data)); + if (!matcher.find()) { + continue; + } + String timeData = matcher.group(1); + if (!timeData.equals("Soon!")) { + return true; + } + } + return false; + } + + private int[] getBuyBoxDimensions() { + int centerX = getGuiCenterX(); + int centerY = getGuiCenterY(); + double multiplier = 0.1; + return new int[]{(int) (centerX - (centerX * multiplier)), (int) (centerY + (centerY * multiplier)), + (int) (centerX + (centerX * multiplier)), (int) (centerY - (centerY * multiplier))}; + } + + private int[] getCancelBoxDimensions() { + int centerX = getGuiCenterX(); + int centerY = (int) (getGuiCenterY() * 1.25); + double multiplier = 0.05; + return new int[]{(int) (centerX - (centerX * multiplier)), (int) (centerY + (centerY * multiplier)), + (int) (centerX + (centerX * multiplier)), (int) (centerY - (centerY * multiplier))}; + } + + @SuppressWarnings("SameParameterValue") + private void drawBoxWithShadow(int leftX, int topY, int rightX, int bottomY, int colour, int shadowSize, int shadowColour) { + drawRect(leftX - shadowSize, topY + shadowSize, rightX + shadowSize, bottomY - shadowSize, shadowColour); + drawRect(leftX, topY, rightX, bottomY, colour); + } + + private void drawTfmBox(boolean isConfirm) { + String titleText; + if (isConfirm) { + titleText = "Cofl - Confirm Purchase"; + } else { + titleText = "Cofl - Auction View"; + } + int outerBox = 0xff4f4f4f; // gray colour + // draw the outer tfm box + drawBoxWithShadow((int) (getGuiCenterX() * 0.5), (int) (getGuiCenterY() * 1.6), (int) (getGuiCenterX() * 1.5), (int) (getGuiCenterY() * 0.4), outerBox, 1, 0xff000000); + Minecraft.getMinecraft().fontRendererObj.drawStringWithShadow(titleText, (int) (getGuiCenterX() * 0.55), (int) (getGuiCenterY() * 0.45), 0xFFFFFFFF); + } + + private void renderTooltip(GuiChest chest, ItemStack item) { + ToolTipHelper toolTipData = new ToolTipHelper(item); + int toolTipY = getGuiCenterY() - (toolTipData.determineHeight() / 2); + int toolTipX = (int) (getGuiCenterX() * 1.25) - (toolTipData.determineWidth() / 2); + if (toolTipX < getGuiCenterX()) { + toolTipX = getGuiCenterX() + 10; + } + try { + renderToolTipMethod.invoke(chest, item, toolTipX, toolTipY); + } catch (IllegalAccessException | InvocationTargetException e) { + e.printStackTrace(); + } + } + + private void renderItem(GuiChest chest, ItemStack item) { + GlStateManager.pushMatrix(); + GlStateManager.scale(SCALE_VALUE, SCALE_VALUE, 0); + int itemX = (int) ((getGuiCenterX() - 16) / SCALE_VALUE); + int itemY = (int) ((getGuiCenterY() - 16) / SCALE_VALUE); + try { + drawItemMethod.invoke(chest, item, itemX, itemY, null); + } catch (IllegalAccessException | InvocationTargetException e) { + e.printStackTrace(); + } + GlStateManager.popMatrix(); + } + + private void drawBuyBox(boolean shouldBeRed) { + int colour = shouldBeRed ? 255 << 16 : 255 << 8; + colour += 128 << 24; + int[] dim = getBuyBoxDimensions(); + drawBoxWithShadow(dim[0], dim[1], dim[2], dim[3], colour, 1, 0xff000000); + } + + private void drawCancelBox() { + int colour = 0x7FFF0000; + int[] dim = getCancelBoxDimensions(); + drawBoxWithShadow(dim[0], dim[1], dim[2], dim[3], colour, 1, 0xff000000); + } + + public void drawProfitInfo() { + FontRenderer font = Minecraft.getMinecraft().fontRendererObj; + String text = WSCommandHandler.flipHandler.lastClickedFlipMessage; + + if (text == null) { + return; + } + + StringBuilder current = new StringBuilder(); + int lineNo = 0; + for (int i = 0; i < text.length(); i++) { + char character = text.charAt(i); + current.append(character); + if (current.length() > 50 && character == ' ') { + font.drawStringWithShadow(current.toString(), (int) (getGuiCenterX() * 0.55), (int) (getGuiCenterY() * 0.5 + (15 * lineNo)), 0xFF8F8F8F); + current = new StringBuilder(); + lineNo++; + } + } + font.drawStringWithShadow(current.toString(), (int) (getGuiCenterX() * 0.55), (int) (getGuiCenterY() * 0.5 + (15 * lineNo)), 0xFF8F8F8F); + } + + private void drawBox(GuiChest chest, boolean shouldBeRed, boolean isConfirm) { + GlStateManager.pushMatrix(); + // in front of the items displayed on screen + GlStateManager.translate(0, 0, 512.0D); + ItemStack item = getItem(ITEM_SLOT, chest); + + drawTfmBox(isConfirm); + drawBuyBox(shouldBeRed); + drawCancelBox(); + + if (item != null) { + drawProfitInfo(); + renderItem(chest, item); + renderTooltip(chest, item); + } + + GlStateManager.popMatrix(); + } + + private int getGuiCenterX() { + ScaledResolution resolution = new ScaledResolution(Minecraft.getMinecraft()); + return resolution.getScaledWidth() / 2; + } + + private int getGuiCenterY() { + ScaledResolution resolution = new ScaledResolution(Minecraft.getMinecraft()); + return resolution.getScaledHeight() / 2; + } + + private boolean isInBox(int x, int y) { + int[] dim = getBuyBoxDimensions(); + return x > dim[0] && x < dim[2] + && y > dim[3] && y < dim[1]; + } + + private boolean isInCancelBox(int x, int y) { + int[] dim = getCancelBoxDimensions(); + return x > dim[0] && x < dim[2] + && y > dim[3] && y < dim[1]; + } + + public void drawBuyButton(GuiChest currentScreen) { + if (!shouldDrawGui(currentScreen)) { + return; + } + drawBox(currentScreen, waitingForBed(currentScreen), false); + } + + public boolean shouldDrawGui(GuiChest currentScreen) { + ItemStack stack = getItem(BUY_BUTTON_SLOT, currentScreen); + return stack != null && (stack.getItem().equals(Item.getByNameOrId("minecraft:bed")) || stack.getItem().equals(Item.getByNameOrId("minecraft:gold_nugget"))); + } + + public void drawConfirmButton(GuiChest currentScreen) { + drawBox(currentScreen, false, true); + } + + private boolean shouldSkip(GuiScreen screen) { + return !(screen instanceof GuiChest) || CoflSky.config.purchaseOverlay != GUIType.TFM || !EventHandler.isInSkyblock; + } + + @SubscribeEvent + public void onPostRenderEvent(GuiScreenEvent.DrawScreenEvent.Post event) { + if (shouldSkip(event.gui)) { + return; + } + + GuiChest auctionView = (GuiChest) event.gui; + ContainerChest container = (ContainerChest) auctionView.inventorySlots; + String containerName = container.getLowerChestInventory().getDisplayName().getUnformattedText(); + if (containerName.trim().equals("BIN Auction View")) { + drawBuyButton(auctionView); + } else if (containerName.trim().equals("Confirm Purchase")) { + drawConfirmButton(auctionView); + } + } + + private void clickSlot(int windowId, int slot) { + Minecraft.getMinecraft().playerController.windowClick(windowId, + slot, 2, 3, Minecraft.getMinecraft().thePlayer); + } + + private void handleBuyClick(GuiChest currentScreen, GuiScreenEvent.MouseInputEvent.Pre event) { + if (waitingForBed(currentScreen) || !shouldDrawGui(currentScreen)) { + return; + } + event.setCanceled(true); + clickSlot(currentScreen.inventorySlots.windowId, BUY_BUTTON_SLOT); + } + + private void handleConfirmClick(GuiChest currentScreen, int windowId) { + clickSlot(windowId, CONFIRM_BUTTON_SLOT); + } + + private void handlePositiveClick(GuiScreen screen, GuiScreenEvent.MouseInputEvent.Pre event) { + if (shouldSkip(screen)) { + return; + } + + GuiChest auctionView = (GuiChest) screen; + ContainerChest container = (ContainerChest) auctionView.inventorySlots; + String containerName = container.getLowerChestInventory().getDisplayName().getUnformattedText(); + if (containerName.trim().equals("BIN Auction View")) { + handleBuyClick(auctionView, event); + } else if (containerName.trim().equals("Confirm Purchase")) { + handleConfirmClick(auctionView, container.windowId); + event.setCanceled(true); + } + } + + private void doCancelClick(ContainerChest chest, int slotId) { + clickSlot(chest.windowId, slotId); + } + + private void handleCancelClick(GuiScreen screen, GuiScreenEvent.MouseInputEvent.Pre event) { + if (shouldSkip(screen)) { + return; + } + + GuiChest auctionView = (GuiChest) screen; + ContainerChest container = (ContainerChest) auctionView.inventorySlots; + String containerName = container.getLowerChestInventory().getDisplayName().getUnformattedText(); + if (containerName.trim().equals("BIN Auction View")) { + doCancelClick(container, BACK_BUTTON_SLOT); + } else if (containerName.trim().equals("Confirm Purchase")) { + doCancelClick(container, CANCEL_CONFIRM_SLOT); + } else { + return; + } + event.setCanceled(true); + } + + @SubscribeEvent + public void onMouseClicked(GuiScreenEvent.MouseInputEvent.Pre event) { + if (!Mouse.getEventButtonState()) { + return; + } + GuiScreen screen = event.gui; + if (screen == null) { + return; + } + int x = Mouse.getEventX() * screen.width / Minecraft.getMinecraft().displayWidth; + int y = screen.height - Mouse.getEventY() * screen.height / Minecraft.getMinecraft().displayHeight - 1; + if (isInBox(x, y)) { + handlePositiveClick(screen, event); + } else if (isInCancelBox(x, y)) { + handleCancelClick(screen, event); + } + } + +} diff --git a/src/main/java/de/torui/coflsky/gui/tfm/ChatMessageSendHandler.java b/src/main/java/de/torui/coflsky/gui/tfm/ChatMessageSendHandler.java new file mode 100644 index 0000000..da1376e --- /dev/null +++ b/src/main/java/de/torui/coflsky/gui/tfm/ChatMessageSendHandler.java @@ -0,0 +1,32 @@ +package de.torui.coflsky.gui.tfm; + +import de.torui.coflsky.FlipperChatCommand; +import de.torui.coflsky.WSCommandHandler; +import io.netty.channel.*; +import net.minecraft.client.Minecraft; +import net.minecraft.network.play.client.C01PacketChatMessage; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.network.FMLNetworkEvent; + +@ChannelHandler.Sharable +public class ChatMessageSendHandler extends ChannelOutboundHandlerAdapter { + @Override + public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) { + if (msg instanceof C01PacketChatMessage) { + if (FlipperChatCommand.useChatOnlyMode) { + String message = ((C01PacketChatMessage) msg).getMessage(); + if (!message.startsWith("/")) { + WSCommandHandler.Execute("/cofl chat " + message, Minecraft.getMinecraft().thePlayer); + return; + } + } + } + ctx.write(msg, promise); + } + + @SubscribeEvent + public void connect(FMLNetworkEvent.ClientConnectedToServerEvent event) { + ChannelPipeline pipeline = event.manager.channel().pipeline(); + pipeline.addBefore("packet_handler", this.getClass().getName(), this); + } +} diff --git a/src/main/java/de/torui/coflsky/gui/tfm/ToolTipHelper.java b/src/main/java/de/torui/coflsky/gui/tfm/ToolTipHelper.java new file mode 100644 index 0000000..34e855e --- /dev/null +++ b/src/main/java/de/torui/coflsky/gui/tfm/ToolTipHelper.java @@ -0,0 +1,55 @@ +package de.torui.coflsky.gui.tfm; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumChatFormatting; + +import java.util.List; + +public class ToolTipHelper { + Minecraft mc; + ItemStack stack; + List toolTipLines; + FontRenderer font; + + public ToolTipHelper(ItemStack stack) { + mc = Minecraft.getMinecraft(); + this.stack = stack; + toolTipLines = stack.getTooltip(this.mc.thePlayer, this.mc.gameSettings.advancedItemTooltips); + for (int i = 0; i < toolTipLines.size(); ++i) { + if (i == 0) { + toolTipLines.set(i, stack.getRarity().rarityColor + toolTipLines.get(i)); + } else { + toolTipLines.set(i, EnumChatFormatting.GRAY + toolTipLines.get(i)); + } + } + + font = stack.getItem().getFontRenderer(stack); + if (font == null) { + font = mc.fontRendererObj; + } + } + + public int determineWidth() { + int width = 0; + + for (String textLine : toolTipLines) { + int textWidth = font.getStringWidth(textLine); + if (textWidth > width) { + width = textWidth; + } + } + + return width; + } + + public int determineHeight() { + int height = 8; + if (toolTipLines.size() > 1) { + height += (toolTipLines.size() - 1) * 10; + } + return height; + } + +} diff --git a/src/main/java/de/torui/coflsky/handlers/EventRegistry.java b/src/main/java/de/torui/coflsky/handlers/EventRegistry.java index 354dfb9..4bf800b 100644 --- a/src/main/java/de/torui/coflsky/handlers/EventRegistry.java +++ b/src/main/java/de/torui/coflsky/handlers/EventRegistry.java @@ -7,14 +7,13 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import com.mojang.realmsclient.util.Pair; - import de.torui.coflsky.CoflSky; -import de.torui.coflsky.FlipHandler.Flip; import de.torui.coflsky.WSCommandHandler; import de.torui.coflsky.commands.Command; import de.torui.coflsky.commands.CommandType; import de.torui.coflsky.commands.JsonStringCommand; import de.torui.coflsky.commands.models.AuctionData; +import de.torui.coflsky.commands.models.FlipData; import de.torui.coflsky.configuration.Configuration; import de.torui.coflsky.network.WSClient; import net.minecraft.client.Minecraft; @@ -44,199 +43,202 @@ import static de.torui.coflsky.handlers.DescriptionHandler.*; import static de.torui.coflsky.handlers.EventHandler.*; public class EventRegistry { - public static Pattern chatpattern = Pattern.compile("a^", Pattern.CASE_INSENSITIVE); - public final ExecutorService chatThreadPool = Executors.newFixedThreadPool(2); - public final ExecutorService tickThreadPool = Executors.newFixedThreadPool(2); - @SubscribeEvent - public void onDisconnectedFromServerEvent(ClientDisconnectionFromServerEvent event) { - if(CoflSky.Wrapper.isRunning) { - System.out.println("Disconnected from server"); - CoflSky.Wrapper.stop(); - System.out.println("CoflSky stopped"); - } - } - - public long LastClick = System.currentTimeMillis(); - private DescriptionHandler descriptionHandler; - - @SideOnly(Side.CLIENT) - @SubscribeEvent(priority = EventPriority.NORMAL, receiveCanceled = true) - public void onKeyEvent(KeyInputEvent event) { - - if (CoflSky.keyBindings[0].isPressed()) { - if (WSCommandHandler.lastOnClickEvent != null) { - - String command = WSCommandHandler.lastOnClickEvent; - WSCommandHandler.lastOnClickEvent = null; - WSCommandHandler.HandleCommand( - new JsonStringCommand(CommandType.Execute, WSClient.gson.toJson(command)), - Minecraft.getMinecraft().thePlayer); - } - - } - if(CoflSky.keyBindings[1].isKeyDown()) { - if((System.currentTimeMillis() - LastClick) >= 300) { - - Flip f = WSCommandHandler.flipHandler.fds.GetHighestFlip(); - - if(f != null) { - WSCommandHandler.Execute("/viewauction " + f.id, null); - LastClick = System.currentTimeMillis(); - String command = WSClient.gson.toJson("/viewauction " + f.id); - WSCommandHandler.flipHandler.fds.InvalidateFlip(f); - - WSCommandHandler.Execute("/cofl track besthotkey " + f.id, Minecraft.getMinecraft().thePlayer); - CoflSky.Wrapper.SendMessage(new JsonStringCommand(CommandType.Clicked, command)); - } else { - // only display message once (if this is the key down event) - if(CoflSky.keyBindings[1].isPressed()) - WSCommandHandler.Execute("/cofl dialog nobestflip", Minecraft.getMinecraft().thePlayer); - } - } - } - } - - @SideOnly(Side.CLIENT) - //@SubscribeEvent - public void DrawOntoGUI(RenderGameOverlayEvent rgoe) { - - if (rgoe.type == ElementType.CROSSHAIRS) { - Minecraft mc = Minecraft.getMinecraft(); - mc.ingameGUI.drawString(Minecraft.getMinecraft().fontRendererObj, "Flips in Pipeline:" + WSCommandHandler.flipHandler.fds.CurrentFlips(), 0, 0, Integer.MAX_VALUE); - } - } - - public static String ExtractUuidFromInventory(IInventory inventory) { - - ItemStack stack = inventory.getStackInSlot(13); - if (stack != null) { - try { - String uuid = stack.serializeNBT().getCompoundTag("tag").getCompoundTag("ExtraAttributes") - .getString("uuid"); - if (uuid.length() == 0) { - throw new Exception(); - } - System.out.println("Item has the UUID: " + uuid); - return uuid; - } catch (Exception e) { - System.out.println("Clicked item " + stack.getDisplayName() + " has the following meta: " - + stack.serializeNBT()); - } - } - return ""; - } - - public static ItemStack GOLD_NUGGET = new ItemStack( - Item.itemRegistry.getObject(new ResourceLocation("minecraft:gold_nugget"))); - - public static final Pair> EMPTY = Pair.of(null, Pair.of("",LocalDateTime.MIN)); - public static Pair> last = EMPTY; - - @SubscribeEvent - public void HandleChatEvent(ClientChatReceivedEvent sce) { - if(CoflSky.Wrapper.isRunning && Configuration.getInstance().collectChat) { - chatThreadPool.submit(() -> { - String msg = sce.message.getUnformattedText(); - Matcher matcher = chatpattern.matcher(msg); - boolean matchFound = matcher.find(); - if (matchFound) { - Command data = new Command<>(CommandType.chatBatch, new String[]{msg}); - CoflSky.Wrapper.SendMessage(data); - } - }); - } - - } - - public static long lastStartTime = Long.MIN_VALUE; - - public static long LastViewAuctionInvocation = Long.MIN_VALUE; - public static String LastViewAuctionUUID =null; - - @SideOnly(Side.CLIENT) - @SubscribeEvent - public void OnGuiClick(GuiScreenEvent.MouseInputEvent mie) { - if (!CoflSky.Wrapper.isRunning) return; - if (!(mie.gui instanceof GuiChest)) return; // verify that it's really a chest - if (!(((GuiChest) mie.gui).inventorySlots instanceof ContainerChest)) return; - ContainerChest chest = (ContainerChest) ((GuiChest) mie.gui).inventorySlots; - IInventory inv = chest.getLowerChestInventory(); - if (inv.hasCustomName()) { // verify that the chest actually has a custom name - String chestName = inv.getName(); - if (chestName.equalsIgnoreCase("BIN Auction View")) { - - ItemStack heldItem = Minecraft.getMinecraft().thePlayer.inventory.getItemStack(); - - if (heldItem != null) { - System.out.println("Clicked on: " + heldItem.getItem().getRegistryName()); - - String itemUUID = ExtractUuidFromInventory(inv); - - if(System.currentTimeMillis() > lastStartTime) { - - if (heldItem.isItemEqual(GOLD_NUGGET)) { - AuctionData ad = new AuctionData(); - ad.setItemId(itemUUID); - - if((LastViewAuctionInvocation+60*1000) >= System.currentTimeMillis()) { - ad.setAuctionId(LastViewAuctionUUID); - } else { - ad.setAuctionId(""); - } - - Command data = new Command<>(CommandType.PurchaseStart, ad); - CoflSky.Wrapper.SendMessage(data); - System.out.println("PurchaseStart"); - last = Pair.of("You claimed ", Pair.of(itemUUID, LocalDateTime.now())); - lastStartTime = System.currentTimeMillis() + 200 /*ensure a small debounce*/; - } - } - } - } - } - } - - @SubscribeEvent + public static Pattern chatpattern = Pattern.compile("a^", Pattern.CASE_INSENSITIVE); + public final ExecutorService chatThreadPool = Executors.newFixedThreadPool(2); + public final ExecutorService tickThreadPool = Executors.newFixedThreadPool(2); + + @SubscribeEvent + public void onDisconnectedFromServerEvent(ClientDisconnectionFromServerEvent event) { + if (CoflSky.Wrapper.isRunning) { + System.out.println("Disconnected from server"); + CoflSky.Wrapper.stop(); + System.out.println("CoflSky stopped"); + } + } + + public long LastClick = System.currentTimeMillis(); + private DescriptionHandler descriptionHandler; + + @SideOnly(Side.CLIENT) + @SubscribeEvent(priority = EventPriority.NORMAL, receiveCanceled = true) + public void onKeyEvent(KeyInputEvent event) { + + if (CoflSky.keyBindings[0].isPressed()) { + if (WSCommandHandler.lastOnClickEvent != null) { + FlipData f = WSCommandHandler.flipHandler.fds.GetLastFlip(); + if (f != null) { + WSCommandHandler.Execute("/cofl openAuctionGUI " + f.Id + " false", Minecraft.getMinecraft().thePlayer); + } + } + + } + if (CoflSky.keyBindings[1].isKeyDown()) { + if ((System.currentTimeMillis() - LastClick) >= 300) { + + FlipData f = WSCommandHandler.flipHandler.fds.GetHighestFlip(); + + if (f != null) { + WSCommandHandler.Execute("/cofl openAuctionGUI " + f.Id + " true", Minecraft.getMinecraft().thePlayer); + EventRegistry.LastViewAuctionUUID = f.Id; + EventRegistry.LastViewAuctionInvocation = System.currentTimeMillis(); + LastClick = System.currentTimeMillis(); + String command = WSClient.gson.toJson("/viewauction " + f.Id); + + CoflSky.Wrapper.SendMessage(new JsonStringCommand(CommandType.Clicked, command)); + WSCommandHandler.Execute("/cofl track besthotkey " + f.Id, Minecraft.getMinecraft().thePlayer); + } else { + // only display message once (if this is the key down event) + if (CoflSky.keyBindings[1].isPressed()) + WSCommandHandler.Execute("/cofl dialog nobestflip", Minecraft.getMinecraft().thePlayer); + } + } + } + } + + @SideOnly(Side.CLIENT) + //@SubscribeEvent + public void DrawOntoGUI(RenderGameOverlayEvent rgoe) { + + if (rgoe.type == ElementType.CROSSHAIRS) { + Minecraft mc = Minecraft.getMinecraft(); + mc.ingameGUI.drawString(Minecraft.getMinecraft().fontRendererObj, "Flips in Pipeline:" + WSCommandHandler.flipHandler.fds.CurrentFlips(), 0, 0, Integer.MAX_VALUE); + } + } + + public static String ExtractUuidFromInventory(IInventory inventory) { + + ItemStack stack = inventory.getStackInSlot(13); + if (stack != null) { + try { + String uuid = stack.serializeNBT().getCompoundTag("tag").getCompoundTag("ExtraAttributes").getString("uuid"); + if (uuid.length() == 0) { + throw new Exception(); + } + System.out.println("Item has the UUID: " + uuid); + return uuid; + } catch (Exception e) { + System.out.println("Clicked item " + stack.getDisplayName() + " has the following meta: " + stack.serializeNBT()); + } + } + return ""; + } + + public static ItemStack GOLD_NUGGET = new ItemStack(Item.itemRegistry.getObject(new ResourceLocation("minecraft:gold_nugget"))); + + public static final Pair> EMPTY = Pair.of(null, Pair.of("", LocalDateTime.MIN)); + public static Pair> last = EMPTY; + + @SubscribeEvent + public void HandleChatEvent(ClientChatReceivedEvent sce) { + if (CoflSky.Wrapper.isRunning && Configuration.getInstance().collectChat) { + chatThreadPool.submit(() -> { + String msg = sce.message.getUnformattedText(); + Matcher matcher = chatpattern.matcher(msg); + boolean matchFound = matcher.find(); + if (matchFound) { + Command data = new Command<>(CommandType.chatBatch, new String[]{msg}); + CoflSky.Wrapper.SendMessage(data); + } + }); + } + + } + + public static long lastStartTime = Long.MIN_VALUE; + + public static long LastViewAuctionInvocation = Long.MIN_VALUE; + public static String LastViewAuctionUUID = null; + + @SideOnly(Side.CLIENT) + @SubscribeEvent + public void OnGuiClick(GuiScreenEvent.MouseInputEvent mie) { + if (!CoflSky.Wrapper.isRunning) return; + if (!(mie.gui instanceof GuiChest)) return; // verify that it's really a chest + if (!(((GuiChest) mie.gui).inventorySlots instanceof ContainerChest)) return; + ContainerChest chest = (ContainerChest) ((GuiChest) mie.gui).inventorySlots; + IInventory inv = chest.getLowerChestInventory(); + if (inv.hasCustomName()) { // verify that the chest actually has a custom name + String chestName = inv.getName(); + if (chestName.equalsIgnoreCase("BIN Auction View")) { + + ItemStack heldItem = Minecraft.getMinecraft().thePlayer.inventory.getItemStack(); + + if (heldItem != null) { + System.out.println("Clicked on: " + heldItem.getItem().getRegistryName()); + + String itemUUID = ExtractUuidFromInventory(inv); + + if (System.currentTimeMillis() > lastStartTime) { + + if (heldItem.isItemEqual(GOLD_NUGGET)) { + AuctionData ad = new AuctionData(); + ad.setItemId(itemUUID); + + if ((LastViewAuctionInvocation + 60 * 1000) >= System.currentTimeMillis()) { + ad.setAuctionId(LastViewAuctionUUID); + } else { + ad.setAuctionId(""); + } + + Command data = new Command<>(CommandType.PurchaseStart, ad); + CoflSky.Wrapper.SendMessage(data); + System.out.println("PurchaseStart"); + last = Pair.of("You claimed ", Pair.of(itemUUID, LocalDateTime.now())); + lastStartTime = System.currentTimeMillis() + 200 /*ensure a small debounce*/; + } + } + } + } + } + } + + @SubscribeEvent public void OnRenderTick(TickEvent.RenderTickEvent event) { - de.torui.coflsky.CountdownTimer.onRenderTick(event); - } - - int UpdateThisTick = 0; - @SubscribeEvent(priority = EventPriority.LOWEST) - public void onTick(TickEvent.ClientTickEvent event) { - UpdateThisTick++; - if (UpdateThisTick >= 200) UpdateThisTick = 0; - if (UpdateThisTick == 0) { - tickThreadPool.submit(() -> { - ScoreboardData(); - TabMenuData(); - }); - } - } - - @SubscribeEvent(priority = EventPriority.LOWEST) - public void onGuiOpen(GuiOpenEvent event) { - if (!config.extendedtooltips) return; - if(descriptionHandler != null) - descriptionHandler.Close(); - if(event.gui == null) - emptyTooltipData(); - - if (!(event.gui instanceof GuiContainer)) return; - new Thread(() -> { - try { - descriptionHandler = new DescriptionHandler(); - descriptionHandler.loadDescriptionAndListenForChanges(event); - } catch (Exception e) - { - System.out.println("failed to update description " + e); - } - }).start(); - } - @SubscribeEvent(priority = EventPriority.HIGHEST) - public void onItemTooltipEvent(ItemTooltipEvent event) { - if (!config.extendedtooltips) return; - if(descriptionHandler == null) return; - descriptionHandler.setTooltips(event); - } + de.torui.coflsky.CountdownTimer.onRenderTick(event); + } + + int UpdateThisTick = 0; + + @SubscribeEvent(priority = EventPriority.LOWEST) + public void onTick(TickEvent.ClientTickEvent event) { + UpdateThisTick++; + if (UpdateThisTick >= 200) UpdateThisTick = 0; + if (UpdateThisTick == 0) { + tickThreadPool.submit(() -> { + ScoreboardData(); + TabMenuData(); + }); + } + } + + @SubscribeEvent(priority = EventPriority.LOWEST) + public void onGuiOpen(GuiOpenEvent event) { + + // if gui is null, a gui was closed + // therefore clear the lastClickFlipMessage, so it doesn't show on other auctions + if (event.gui == null) { + WSCommandHandler.flipHandler.lastClickedFlipMessage = ""; + } + + if (!config.extendedtooltips) return; + if (descriptionHandler != null) descriptionHandler.Close(); + if (event.gui == null) emptyTooltipData(); + + if (!(event.gui instanceof GuiContainer)) return; + new Thread(() -> { + try { + descriptionHandler = new DescriptionHandler(); + descriptionHandler.loadDescriptionAndListenForChanges(event); + } catch (Exception e) { + System.out.println("failed to update description " + e); + } + }).start(); + } + + @SubscribeEvent(priority = EventPriority.HIGHEST) + public void onItemTooltipEvent(ItemTooltipEvent event) { + if (!config.extendedtooltips) return; + if (descriptionHandler == null) return; + descriptionHandler.setTooltips(event); + } } -- cgit