diff options
16 files changed, 1057 insertions, 184 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt b/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt index 89980d349..de4bc2585 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt +++ b/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt @@ -66,6 +66,7 @@ import at.hannibal2.skyhanni.features.misc.visualwords.VisualWordGui import at.hannibal2.skyhanni.features.rift.area.westvillage.VerminTracker import at.hannibal2.skyhanni.features.slayer.SlayerProfitTracker import at.hannibal2.skyhanni.test.DebugCommand +import at.hannibal2.skyhanni.test.GraphEditor import at.hannibal2.skyhanni.test.PacketTest import at.hannibal2.skyhanni.test.SkyHanniConfigSearchResetCommand import at.hannibal2.skyhanni.test.SkyHanniDebugsAndTests @@ -112,12 +113,14 @@ object Commands { USERS_NORMAL("§e", "Normal Command", "Normal Command for everyone to use"), USERS_BUG_FIX("§f", "User Bug Fix", "A Command to fix small bugs"), DEVELOPER_CODING_HELP( - "§5", "Developer Coding Help", - "A Command that can help with developing new features. §cIntended for developers only!" + "§5", + "Developer Coding Help", + "A Command that can help with developing new features. §cIntended for developers only!", ), DEVELOPER_DEBUG_FEATURES( - "§9", "Developer Debug Features", - "A Command that is useful for monitoring/debugging existing features. §cIntended for developers only!" + "§9", + "Developer Debug Features", + "A Command that is useful for monitoring/debugging existing features. §cIntended for developers only!", ), INTERNAL("§8", "Internal Command", "A Command that should §cnever §7be called manually!"), SHORTENED_COMMANDS("§b", "Shortened Commands", "Commands that shorten or improve existing Hypixel commands!") @@ -155,128 +158,131 @@ object Commands { registerCommand("skyhanni", "Opens the main SkyHanni config", openMainMenu) registerCommand("ff", "Opens the Farming Fortune Guide") { openFortuneGuide() } registerCommand("shcommands", "Shows this list") { HelpCommand.onCommand(it, commands) } - registerCommand0("shdefaultoptions", "Select default options", { - DefaultConfigFeatures.onCommand( - it.getOrNull(0) ?: "null", it.getOrNull(1) ?: "null" - ) - }, DefaultConfigFeatures::onComplete) + registerCommand0( + "shdefaultoptions", + "Select default options", + { DefaultConfigFeatures.onCommand(it) }, + DefaultConfigFeatures::onComplete, + ) registerCommand("shwords", "Opens the config list for modifying visual words") { openVisualWords() } } + private fun usersNormal() { registerCommand( "shmarkplayer", - "Add a highlight effect to a player for better visibility" + "Add a highlight effect to a player for better visibility", ) { MarkedPlayerManager.command(it) } registerCommand("shtrackcollection", "Tracks your collection gain over time") { CollectionTracker.command(it) } registerCommand( "shcroptime", - "Calculates with your current crop per second speed how long you need to farm a crop to collect this amount of items" + "Calculates with your current crop per second speed " + + "how long you need to farm a crop to collect this amount of items", ) { GardenCropTimeCommand.onCommand(it) } registerCommand( "shcropsin", - "Calculates with your current crop per second how many items you can collect in this amount of time" + "Calculates with your current crop per second how many items you can collect in this amount of time", ) { GardenCropsInCommand.onCommand(it) } registerCommand( "shrpcstart", - "Manually starts the Discord Rich Presence feature" + "Manually starts the Discord Rich Presence feature", ) { DiscordRPCManager.startCommand() } registerCommand( "shcropstartlocation", - "Manually sets the crop start location" + "Manually sets the crop start location", ) { GardenStartLocation.setLocationCommand() } registerCommand( "shclearslayerprofits", - "Clearing the total slayer profit for the current slayer type" + "Clearing the total slayer profit for the current slayer type", ) { SlayerProfitTracker.clearProfitCommand(it) } registerCommand( "shimportghostcounterdata", - "Manually importing the ghost counter data from GhostCounterV3" + "Manually importing the ghost counter data from GhostCounterV3", ) { GhostUtil.importCTGhostCounterData() } registerCommand( "shclearfarmingitems", - "Clear farming items saved for the Farming Fortune Guide" + "Clear farming items saved for the Farming Fortune Guide", ) { clearFarmingItems() } registerCommand("shresetghostcounter", "Resets the ghost counter") { GhostUtil.reset() } registerCommand("shresetpowdertracker", "Resets the Powder Tracker") { PowderTracker.resetCommand() } registerCommand("shresetdicertracker", "Resets the Dicer Drop Tracker") { DicerRngDropTracker.resetCommand() } registerCommand( "shresetendernodetracker", - "Resets the Ender Node Tracker" + "Resets the Ender Node Tracker", ) { EnderNodeTracker.resetCommand() } registerCommand( "shresetarmordroptracker", - "Resets the Armor Drop Tracker" + "Resets the Armor Drop Tracker", ) { ArmorDropTracker.resetCommand() } registerCommand( "shresetfrozentreasuretracker", - "Resets the Frozen Treasure Tracker" + "Resets the Frozen Treasure Tracker", ) { FrozenTreasureTracker.resetCommand() } registerCommand( "shresetfishingtracker", - "Resets the Fishing Profit Tracker" + "Resets the Fishing Profit Tracker", ) { FishingProfitTracker.resetCommand() } registerCommand( "shresetvisitordrops", - "Reset the Visitors Drop Statistics" + "Reset the Visitors Drop Statistics", ) { GardenVisitorDropStatistics.resetCommand() } registerCommand("shbingotoggle", "Toggle the bingo card display mode") { BingoCardDisplay.toggleCommand() } registerCommand( "shfarmingprofile", - "Look up the farming profile from yourself or another player on elitebot.dev" + "Look up the farming profile from yourself or another player on elitebot.dev", ) { FarmingWeightDisplay.lookUpCommand(it) } registerCommand( "shcopytranslation", "Copy the English translation of a message in another language to the clipboard.\n" + - "Uses a 2 letter language code that can be found at the end of a translation message." + "Uses a 2 letter language code that can be found at the end of a translation message.", ) { Translator.fromEnglish(it) } registerCommand( "shtranslate", - "Translate a message in another language to English." + "Translate a message in another language to English.", ) { Translator.toEnglish(it) } registerCommand( "shmouselock", - "Lock/Unlock the mouse so it will no longer rotate the player (for farming)" + "Lock/Unlock the mouse so it will no longer rotate the player (for farming)", ) { LockMouseLook.toggleLock() } registerCommand( "shsensreduce", - "Lowers the mouse sensitivity for easier small adjustments (for farming)" + "Lowers the mouse sensitivity for easier small adjustments (for farming)", ) { SensitivityReducer.manualToggle() } registerCommand( "shresetvermintracker", - "Resets the Vermin Tracker" + "Resets the Vermin Tracker", ) { VerminTracker.resetCommand() } registerCommand( "shresetdianaprofittracker", - "Resets the Diana Profit Tracker" + "Resets the Diana Profit Tracker", ) { DianaProfitTracker.resetCommand() } registerCommand( "shresetpestprofittracker", - "Resets the Pest Profit Tracker" + "Resets the Pest Profit Tracker", ) { PestProfitTracker.resetCommand() } registerCommand( "shresetmythologicalcreaturetracker", - "Resets the Mythological Creature Tracker" + "Resets the Mythological Creature Tracker", ) { MythologicalCreatureTracker.resetCommand() } registerCommand( "shresetseacreaturetracker", - "Resets the Sea Creature Tracker" + "Resets the Sea Creature Tracker", ) { SeaCreatureTracker.resetCommand() } registerCommand( "shfandomwiki", - "Searches the fandom wiki with SkyHanni's own method." + "Searches the fandom wiki with SkyHanni's own method.", ) { WikiManager.otherWikiCommands(it, true) } registerCommand( "shfandomwikithis", - "Searches the fandom wiki with SkyHanni's own method." + "Searches the fandom wiki with SkyHanni's own method.", ) { WikiManager.otherWikiCommands(it, true, true) } registerCommand( "shofficialwiki", - "Searches the official wiki with SkyHanni's own method." + "Searches the official wiki with SkyHanni's own method.", ) { WikiManager.otherWikiCommands(it, false) } registerCommand( "shofficialwikithis", - "Searches the official wiki with SkyHanni's own method." + "Searches the official wiki with SkyHanni's own method.", ) { WikiManager.otherWikiCommands(it, false, true) } registerCommand0( "shcalccrop", @@ -284,7 +290,7 @@ object Commands { { FarmingMilestoneCommand.onCommand(it.getOrNull(0), it.getOrNull(1), it.getOrNull(2), false) }, - FarmingMilestoneCommand::onComplete + FarmingMilestoneCommand::onComplete, ) registerCommand0( "shcalccroptime", @@ -292,39 +298,39 @@ object Commands { { FarmingMilestoneCommand.onCommand(it.getOrNull(0), it.getOrNull(1), it.getOrNull(2), true) }, - FarmingMilestoneCommand::onComplete + FarmingMilestoneCommand::onComplete, ) registerCommand0( "shcropgoal", "Define a custom milestone goal for a crop.", { FarmingMilestoneCommand.setGoal(it) }, - FarmingMilestoneCommand::onComplete + FarmingMilestoneCommand::onComplete, ) registerCommand0( "shskills", "Skills XP/Level related command", { SkillAPI.onCommand(it) }, - SkillAPI::onComplete + SkillAPI::onComplete, ) registerCommand( "shlimbostats", - "Prints your Limbo Stats.\n §7This includes your Personal Best, Playtime, and §aSkyHanni User Luck§7!" + "Prints your Limbo Stats.\n §7This includes your Personal Best, Playtime, and §aSkyHanni User Luck§7!", ) { LimboTimeTracker.printStats() } registerCommand( "shlimbo", - "Warps you to Limbo." + "Warps you to Limbo.", ) { MiscFeatures.goToLimbo() } registerCommand( "shlanedetection", - "Detect a farming lane in garden" + "Detect a farming lane in garden", ) { FarmingLaneCreator.commandLaneDetection() } registerCommand( "shignore", - "Add/Remove a user from your" + "Add/Remove a user from your", ) { PartyChatCommands.blacklist(it) } registerCommand( "shtpinfested", - "Teleports you to the nearest infested plot" + "Teleports you to the nearest infested plot", ) { PestFinder.teleportNearestInfestedPlot() } } @@ -332,73 +338,73 @@ object Commands { registerCommand("shupdaterepo", "Download the SkyHanni repo again") { SkyHanniMod.repo.updateRepo() } registerCommand( "shresetburrowwarps", - "Manually resetting disabled diana burrow warp points" + "Manually resetting disabled diana burrow warp points", ) { BurrowWarpHelper.resetDisabledWarps() } registerCommand( "shtogglehypixelapierrors", - "Show/hide hypixel api error messages in chat" + "Show/hide hypixel api error messages in chat", ) { APIUtil.toggleApiErrorMessages() } registerCommand( "shclearcropspeed", - "Reset garden crop speed data and best crop time data" + "Reset garden crop speed data and best crop time data", ) { GardenAPI.clearCropSpeed() } registerCommand( "shclearminiondata", - "Removed bugged minion locations from your private island" + "Removed bugged minion locations from your private island", ) { MinionFeatures.removeBuggedMinions(isCommand = true) } registerCommand( "shwhereami", - "Print current island in chat" + "Print current island in chat", ) { SkyHanniDebugsAndTests.whereAmI() } registerCommand( "shclearcontestdata", - "Resets Jacob's Contest Data" + "Resets Jacob's Contest Data", ) { SkyHanniDebugsAndTests.clearContestData() } registerCommand( "shconfig", - "Search or reset config elements §c(warning, dangerous!)" + "Search or reset config elements §c(warning, dangerous!)", ) { SkyHanniConfigSearchResetCommand.command(it) } registerCommand( "shdebug", - "Copies SkyHanni debug data in the clipboard." + "Copies SkyHanni debug data in the clipboard.", ) { DebugCommand.command(it) } registerCommand( "shversion", - "Prints the SkyHanni version in the chat" + "Prints the SkyHanni version in the chat", ) { SkyHanniDebugsAndTests.debugVersion() } registerCommand( "shrendertoggle", - "Disables/enables the rendering of all skyhanni guis." + "Disables/enables the rendering of all skyhanni guis.", ) { SkyHanniDebugsAndTests.toggleRender() } registerCommand( "shcarrolyn", - "Toggels if the specified crops effect is active from carrolyn" + "Toggels if the specified crops effect is active from carrolyn", ) { CaptureFarmingGear.handelCarrolyn(it) } registerCommand( "shrepostatus", - "Shows the status of all the mods constants" + "Shows the status of all the mods constants", ) { SkyHanniMod.repo.displayRepoStatus(false) } registerCommand( "shclearkismet", - "Cleares the saved values of the applied kismet feathers in Croesus" + "Cleares the saved values of the applied kismet feathers in Croesus", ) { CroesusChestTracker.resetChest() } registerCommand( "shkingfix", - "Reseting the local King Talisman Helper offset." + "Reseting the local King Talisman Helper offset.", ) { KingTalismanHelper.kingFix() } registerCommand( "shupdate", - "Updates the mod to the specified update stream." + "Updates the mod to the specified update stream.", ) { forceUpdate(it) } registerCommand( "shUpdateBazaarPrices", - "Forcefully updating the bazaar prices right now." + "Forcefully updating the bazaar prices right now.", ) { HypixelBazaarFetcher.fetchNow() } registerCommand( "shclearsavedrabbits", - "Clears the saved rabbits on this profile." + "Clears the saved rabbits on this profile.", ) { HoppityCollectionStats.clearSavedRabbits() } } @@ -415,22 +421,23 @@ object Commands { "shworldedit", "Select regions in the world", { WorldEdit.command(it) }, - { listOf("copy", "reset", "help", "left", "right") }) + { listOf("copy", "reset", "help", "left", "right") }, + ) registerCommand( "shconfigsave", - "Manually saving the config" + "Manually saving the config", ) { SkyHanniMod.configManager.saveConfig(ConfigFileType.FEATURES, "manual-command") } registerCommand( "shtestburrow", - "Sets a test burrow waypoint at your location" + "Sets a test burrow waypoint at your location", ) { GriffinBurrowHelper.setTestBurrow(it) } registerCommand( "shtestsackapi", - "Get the amount of an item in sacks according to internal feature SackAPI" + "Get the amount of an item in sacks according to internal feature SackAPI", ) { SackAPI.testSackAPI(it) } registerCommand( "shtestgriffinspots", - "Show potential griffin spots around you." + "Show potential griffin spots around you.", ) { GriffinBurrowHelper.testGriffinSpots() } } @@ -439,11 +446,11 @@ object Commands { registerCommand("shtest", "Unused test command.") { SkyHanniDebugsAndTests.testCommand(it) } registerCommand( "shtestitem", - "test item internal name resolving" + "test item internal name resolving", ) { SkyHanniDebugsAndTests.testItemCommand(it) } registerCommand( "shfindnullconfig", - "Find config elements that are null and prints them into the console" + "Find config elements that are null and prints them into the console", ) { SkyHanniDebugsAndTests.findNullConfig(it) } registerCommand("shtestwaypoint", "Set a waypoint on that location") { SkyHanniDebugsAndTests.waypoint(it) } registerCommand("shtesttablist", "Set your clipboard as a fake tab list.") { TabListData.toggleDebug() } @@ -451,88 +458,94 @@ object Commands { registerCommand("shchathistory", "Show the unfiltered chat history") { ChatManager.openChatFilterGUI(it) } registerCommand( "shstoplisteners", - "Unregistering all loaded forge event listeners" + "Unregistering all loaded forge event listeners", ) { SkyHanniDebugsAndTests.stopListeners() } registerCommand( "shreloadlisteners", - "Trying to load all forge event listeners again. Might not work at all" + "Trying to load all forge event listeners again. Might not work at all", ) { SkyHanniDebugsAndTests.reloadListeners() } registerCommand( "shcopylocation", - "Copies the player location as LorenzVec format to the clipboard" + "Copies the player location as LorenzVec format to the clipboard", ) { SkyHanniDebugsAndTests.copyLocation(it) } registerCommand( "shcopyentities", - "Copies entities in the specified radius around the player to the clipboard" + "Copies entities in the specified radius around the player to the clipboard", ) { CopyNearbyEntitiesCommand.command(it) } registerCommand( "shtracksounds", - "Tracks the sounds for the specified duration (in seconds) and copies it to the clipboard" + "Tracks the sounds for the specified duration (in seconds) and copies it to the clipboard", ) { TrackSoundsCommand.command(it) } registerCommand( "shtrackparticles", - "Tracks the particles for the specified duration (in seconds) and copies it to the clipboard" + "Tracks the particles for the specified duration (in seconds) and copies it to the clipboard", ) { TrackParticlesCommand.command(it) } registerCommand( "shcopytablist", - "Copies the tab list data to the clipboard" + "Copies the tab list data to the clipboard", ) { TabListData.copyCommand(it) } registerCommand( "shcopyactionbar", - "Copies the action bar to the clipboard, including formatting codes" + "Copies the action bar to the clipboard, including formatting codes", ) { CopyActionBarCommand.command(it) } registerCommand( "shcopyscoreboard", - "Copies the scoreboard data to the clipboard" + "Copies the scoreboard data to the clipboard", ) { CopyScoreboardCommand.command(it) } registerCommand( "shcopybossbar", - "Copies the name of the bossbar to the clipboard, including formatting codes" + "Copies the name of the bossbar to the clipboard, including formatting codes", ) { CopyBossbarCommand.command(it) } registerCommand( "shcopyitem", - "Copies information about the item in hand to the clipboard" + "Copies information about the item in hand to the clipboard", ) { CopyItemCommand.command() } registerCommand("shtestpacket", "Logs incoming and outgoing packets to the console") { PacketTest.command(it) } registerCommand( "shtestmessage", - "Sends a custom chat message client side in the chat" + "Sends a custom chat message client side in the chat", ) { TestChatCommand.command(it) } registerCommand( "shcopyinternalname", - "Copies the internal name of the item in hand to the clipboard." + "Copies the internal name of the item in hand to the clipboard.", ) { SkyHanniDebugsAndTests.copyItemInternalName() } registerCommand( "shpartydebug", - "List persons into the chat SkyHanni thinks are in your party." + "List persons into the chat SkyHanni thinks are in your party.", ) { PartyAPI.listMembers() } registerCommand( "shplaysound", - "Play the specified sound effect at the given pitch and volume." + "Play the specified sound effect at the given pitch and volume.", ) { SoundUtils.command(it) } registerCommand( "shsendtitle", - "Display a title on the screen with the specified settings." + "Display a title on the screen with the specified settings.", ) { TitleManager.command(it) } registerCommand( "shresetconfig", - "Reloads the config manager and rendering processors of MoulConfig. This §cWILL RESET §7your config, but also updating the java config files (names, description, orderings and stuff)." + "Reloads the config manager and rendering processors of MoulConfig. " + + "This §cWILL RESET §7your config, but also updating the java config files " + + "(names, description, orderings and stuff).", ) { SkyHanniDebugsAndTests.resetConfigCommand() } registerCommand( "readcropmilestonefromclipboard", - "Read crop milestone from clipboard. This helps fixing wrong crop milestone data" + "Read crop milestone from clipboard. This helps fixing wrong crop milestone data", ) { GardenCropMilestonesCommunityFix.readDataFromClipboard() } registerCommand( "shcopyfoundburrowlocations", - "Copy all ever found burrow locations to clipboard" + "Copy all ever found burrow locations to clipboard", ) { AllBurrowsList.copyToClipboard() } registerCommand( "shaddfoundburrowlocationsfromclipboard", - "Add all ever found burrow locations from clipboard" + "Add all ever found burrow locations from clipboard", ) { AllBurrowsList.addFromClipboard() } registerCommand( + "shgraph", + "Enables the graph editor", + ) { GraphEditor.commandIn() } + registerCommand( "shtoggleegglocationdebug", - "Shows Hoppity egg locations with their internal API names and status." + "Shows Hoppity egg locations with their internal API names and status.", ) { HoppityEggLocations.toggleDebug() } } @@ -584,13 +597,15 @@ object Commands { else -> currentStream } - if (updateStream == UpdateStream.BETA && (currentStream != UpdateStream.BETA || !UpdateManager.isCurrentlyBeta())) { + val switchingToBeta = updateStream == UpdateStream.BETA && + (currentStream != UpdateStream.BETA || !UpdateManager.isCurrentlyBeta()) + if (switchingToBeta) { ChatUtils.clickableChat( "Are you sure you want to switch to beta? These versions may be less stable.", onClick = { UpdateManager.checkUpdate(true, updateStream) }, - oneTimeClick = true + oneTimeClick = true, ) } else { UpdateManager.checkUpdate(true, updateStream) @@ -623,7 +638,7 @@ object Commands { ): List<String> { return autoComplete(args ?: emptyArray()) } - } + }, ) ClientCommandHandler.instance.registerCommand(command) commands.add(CommandInfo(name, description, currentCategory)) diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/dev/DevConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/dev/DevConfig.java index e99fb656c..041134e41 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/dev/DevConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/dev/DevConfig.java @@ -104,6 +104,10 @@ public class DevConfig { public MinecraftConsoleConfig minecraftConsoles = new MinecraftConsoleConfig(); @Expose + @Category(name = "Dev Tools", desc = "Tooling for devs") + public DevToolConfig devTool = new DevToolConfig(); + + @Expose @Category(name = "Debug Mob", desc = "Every Debug related to the Mob System") public DebugMobConfig mobDebug = new DebugMobConfig(); diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/dev/DevToolConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/dev/DevToolConfig.java new file mode 100644 index 000000000..bd84cacaa --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/config/features/dev/DevToolConfig.java @@ -0,0 +1,14 @@ +package at.hannibal2.skyhanni.config.features.dev; + +import com.google.gson.annotations.Expose; +import io.github.notenoughupdates.moulconfig.annotations.Accordion; +import io.github.notenoughupdates.moulconfig.annotations.ConfigOption; + +public class DevToolConfig { + + @Expose + @ConfigOption(name = "Graph Tools", desc = "") + @Accordion + public GraphConfig graph = new GraphConfig(); + +} diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/dev/GraphConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/dev/GraphConfig.java new file mode 100644 index 000000000..45da2fbc6 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/config/features/dev/GraphConfig.java @@ -0,0 +1,87 @@ +package at.hannibal2.skyhanni.config.features.dev; + +import at.hannibal2.skyhanni.config.core.config.Position; +import com.google.gson.annotations.Expose; +import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorBoolean; +import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorKeybind; +import io.github.notenoughupdates.moulconfig.annotations.ConfigLink; +import io.github.notenoughupdates.moulconfig.annotations.ConfigOption; +import org.lwjgl.input.Keyboard; + +public class GraphConfig { + + @Expose + @ConfigOption(name = "Enabled", desc = "Enables the graphing tool.") + @ConfigEditorBoolean + public boolean enabled = false; + + @Expose + @ConfigOption(name = "Place Key", desc = "Places a new node at the current position. If a node is active automatically connects." + + "Deletes a node if you are only 3 blocks away instead of placing a new one.") + @ConfigEditorKeybind(defaultKey = Keyboard.KEY_F) + public int placeKey = Keyboard.KEY_F; + + @Expose + @ConfigOption(name = "Select Key", desc = "Select the nearest node to be active. Double press to unselect.") + @ConfigEditorKeybind(defaultKey = -98) // Middle Mouse + public int selectKey = -98; + + @Expose + @ConfigOption(name = "Connect Key", desc = "Connects the nearest node with the active node. If the nodes are already connected removes the connection.") + @ConfigEditorKeybind(defaultKey = Keyboard.KEY_C) + public int connectKey = Keyboard.KEY_C; + + @Expose + @ConfigOption(name = "Exit Key", desc = "Exit out of stuff. If nothing active disables the graph editor.") + @ConfigEditorKeybind(defaultKey = Keyboard.KEY_HOME) + public int exitKey = Keyboard.KEY_HOME; + + @Expose + @ConfigOption(name = "Edit Key", desc = "While holding the Key, edit the position of the active node with the minecraft movement controls.") + @ConfigEditorKeybind(defaultKey = Keyboard.KEY_TAB) + public int editKey = Keyboard.KEY_TAB; + + @Expose + @ConfigOption(name = "Text Key", desc = "Starts text mode, which allows editing a name of a node.") + @ConfigEditorKeybind(defaultKey = Keyboard.KEY_Y) + public int textKey = Keyboard.KEY_Y; + + @Expose + @ConfigOption(name = "Test Dijkstra", desc = "On key press, shows the shortest path between the nearest node and the active node.") + @ConfigEditorKeybind(defaultKey = Keyboard.KEY_G) + public int dijkstraKey = Keyboard.KEY_G; + + @Expose + @ConfigOption(name = "Save Key", desc = "Saves the current graph to the clipboard.") + @ConfigEditorKeybind(defaultKey = Keyboard.KEY_O) + public int saveKey = Keyboard.KEY_O; + + @Expose + @ConfigOption(name = "Load Key", desc = "Loads a graph from clipboard, if valid.") + @ConfigEditorKeybind(defaultKey = Keyboard.KEY_I) + public int loadKey = Keyboard.KEY_I; + + @Expose + @ConfigOption(name = "Clear Key", desc = "Clears the graph. Also saves the graph to the clipboard, just in case you miss clicked.") + @ConfigEditorKeybind(defaultKey = Keyboard.KEY_P) + public int clearKey = Keyboard.KEY_P; + + @Expose + @ConfigOption(name = "Vision Key", desc = "Toggles if the graph, should render trough blocks.") + @ConfigEditorKeybind(defaultKey = Keyboard.KEY_M) + public int throughBlocksKey = Keyboard.KEY_M; + + @Expose + @ConfigOption(name = "Tutorial Key", desc = "Toggles the tutorial mode. In this mode you will get feedback for everything you do.") + @ConfigEditorKeybind(defaultKey = Keyboard.KEY_K) + public int tutorialKey = Keyboard.KEY_K; + + @Expose + @ConfigLink(owner = GraphConfig.class, field = "enabled") + public Position infoDisplay = new Position(20, 20); + + @Expose + @ConfigOption(name = "Shows Stats", desc = "Shows funny extra statistics on save. May lag the game a bit.") + @ConfigEditorBoolean + public boolean showsStats = true; +} diff --git a/src/main/java/at/hannibal2/skyhanni/data/model/Graph.kt b/src/main/java/at/hannibal2/skyhanni/data/model/Graph.kt index c25a567fb..76c97e662 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/model/Graph.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/model/Graph.kt @@ -1,5 +1,6 @@ package at.hannibal2.skyhanni.data.model +import at.hannibal2.skyhanni.utils.LorenzUtils.round import at.hannibal2.skyhanni.utils.LorenzVec import at.hannibal2.skyhanni.utils.json.SkyHanniTypeAdapters.registerTypeAdapter import at.hannibal2.skyhanni.utils.json.fromJson @@ -36,7 +37,8 @@ value class Graph( override fun lastIndexOf(element: GraphNode) = graph.lastIndexOf(element) companion object { - val gson = GsonBuilder().setPrettyPrinting().registerTypeAdapter<Graph>({ out, value -> + val gson = GsonBuilder().setPrettyPrinting().registerTypeAdapter<Graph>( + { out, value -> out.beginObject() value.forEach { out.name(it.id.toString()).beginObject() @@ -48,13 +50,14 @@ value class Graph( out.beginObject() it.neighbours.forEach { (node, weight) -> val id = node.id.toString() - out.name(id).value(weight) + out.name(id).value(weight.round(2)) } out.endObject() out.endObject() } out.endObject() - }, { reader -> + }, + { reader -> reader.beginObject() val list = mutableListOf<GraphNode>() val neigbourMap = mutableMapOf<GraphNode, List<Pair<Int, Double>>>() @@ -100,7 +103,8 @@ value class Graph( } reader.endObject() Graph(list) - }).create() + }, + ).create() fun fromJson(json: String): Graph = gson.fromJson<Graph>(json) fun fromJson(json: JsonElement): Graph = gson.fromJson<Graph>(json) @@ -158,14 +162,16 @@ fun Graph.findShortestPathAsGraphWithDistance(start: GraphNode, end: GraphNode): } } - return Graph(buildList { - var current = end - while (current != start) { - add(current) - current = previous[current] ?: return Graph(emptyList()) to 0.0 - } - add(start) - }.reversed()) to distances[end]!! + return Graph( + buildList { + var current = end + while (current != start) { + add(current) + current = previous[current] ?: return Graph(emptyList()) to 0.0 + } + add(start) + }.reversed(), + ) to distances[end]!! } fun Graph.findShortestPath(start: GraphNode, end: GraphNode): List<LorenzVec> = diff --git a/src/main/java/at/hannibal2/skyhanni/data/model/TextInput.kt b/src/main/java/at/hannibal2/skyhanni/data/model/TextInput.kt new file mode 100644 index 000000000..22ac4982b --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/data/model/TextInput.kt @@ -0,0 +1,133 @@ +package at.hannibal2.skyhanni.data.model + +import at.hannibal2.skyhanni.utils.KeyboardManager +import at.hannibal2.skyhanni.utils.KeyboardManager.isKeyClicked +import at.hannibal2.skyhanni.utils.OSUtils +import at.hannibal2.skyhanni.utils.StringUtils.insert +import kotlinx.coroutines.runBlocking +import net.minecraft.client.settings.KeyBinding +import org.lwjgl.input.Keyboard +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable + +class TextInput { + + var textBox: String = "" + private var carriage: Int? = null + + fun editText() = textBox.let { + with(carriage) { + if (this == null) it + else it.insert(this, '|') + } + }.replace("§", "&&") + + fun finalText() = textBox.replace("&&", "§") + + fun makeActive() = Companion.activate(this) + fun disable() = Companion.disable() + fun handle() = Companion.handleTextInput() + fun clear() { + textBox = "" + carriage = null + } + + companion object { + private var activeInstance: TextInput? = null + + fun activate(instance: TextInput) { + activeInstance = instance + timeSinceKeyEvent = Keyboard.getEventNanoseconds() + } + + fun disable() { + activeInstance = null + } + + fun onMinecraftInput(keyBinding: KeyBinding, cir: CallbackInfoReturnable<Boolean>) { + if (activeInstance != null) { + cir.returnValue = false + return + } + } + + private var timeSinceKeyEvent = 0L + + private var carriage + get() = activeInstance?.carriage + set(value) { + activeInstance?.carriage = value + } + + private var textBox + get() = activeInstance?.textBox ?: "" + set(value) { + activeInstance?.textBox = value + } + + private fun handleTextInput() { + if (KeyboardManager.isCopyingKeysDown()) { + OSUtils.copyToClipboard(textBox) + return + } + if (KeyboardManager.isPastingKeysDown()) { + runBlocking { + textBox = OSUtils.readFromClipboard() ?: return@runBlocking + } + return + } + val tcarriage = carriage + + if (Keyboard.KEY_LEFT.isKeyClicked()) { + carriage = tcarriage?.moveCarriageLeft() ?: (textBox.length - 1) + return + } + if (Keyboard.KEY_RIGHT.isKeyClicked()) { + carriage = when { + tcarriage == null -> null + (tcarriage >= textBox.length - 1) -> null + else -> moveCarriageRight(tcarriage) + } + return + } + if (Keyboard.KEY_DELETE.isKeyClicked()) { // Does not work for some reason + if (tcarriage != null) { + textBox.removeRange(tcarriage, tcarriage + 1) + } else { + textBox.dropLast(1) + } + return + } + + if (timeSinceKeyEvent == Keyboard.getEventNanoseconds()) return + timeSinceKeyEvent = Keyboard.getEventNanoseconds() + val char = Keyboard.getEventCharacter() + textBox = when (char) { + Char(0) -> return + '\b' -> if (tcarriage != null) { + if (tcarriage == 0) { + textBox.substring(1) + } else { + carriage = tcarriage.minus(1) + textBox.removeRange(tcarriage - 1, tcarriage) + } + } else { + textBox.dropLast(1) + } + + else -> if (tcarriage != null) { + carriage = tcarriage + 1 + textBox.insert(tcarriage, char) + } else { + textBox + char + } + } + } + + private fun moveCarriageRight(tcarriage: Int) = tcarriage + 1 + + private fun Int.moveCarriageLeft(): Int = when { + this > 0 -> this - 1 + else -> 0 + } + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/DefaultConfigFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/DefaultConfigFeatures.kt index 5fa36943a..8a594259e 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/DefaultConfigFeatures.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/DefaultConfigFeatures.kt @@ -40,7 +40,7 @@ object DefaultConfigFeatures { "Click here to configure default options, or run /shdefaultoptions.", onClick = { onCommand("null", "null") - } + }, ) } else if (updated) { val lastVersion = knownToggles.keys.last { it != SkyHanniMod.version } @@ -50,11 +50,18 @@ object DefaultConfigFeatures { "Click here to configure the newly introduced options, or run $command.", onClick = { onCommand(lastVersion, SkyHanniMod.version) - } + }, ) } } + fun onCommand(args: Array<String>) { + onCommand( + args.getOrNull(0) ?: "null", + args.getOrNull(1) ?: "null", + ) + } + fun onCommand(old: String, new: String) { val processor = FeatureToggleProcessor() ConfigProcessorDriver(processor).processConfig(SkyHanniMod.feature) @@ -108,7 +115,7 @@ object DefaultConfigFeatures { if (strings.size <= 2) return CommandBase.getListOfStringsMatchingLastWord( strings, - SkyHanniMod.knownFeaturesData.knownFeatures.keys + listOf("null") + SkyHanniMod.knownFeaturesData.knownFeatures.keys + listOf("null"), ) return listOf() } diff --git a/src/main/java/at/hannibal2/skyhanni/mixins/transformers/MixinKeyBinding.java b/src/main/java/at/hannibal2/skyhanni/mixins/transformers/MixinKeyBinding.java index 35a9bc780..a070f5e89 100644 --- a/src/main/java/at/hannibal2/skyhanni/mixins/transformers/MixinKeyBinding.java +++ b/src/main/java/at/hannibal2/skyhanni/mixins/transformers/MixinKeyBinding.java @@ -1,6 +1,8 @@ package at.hannibal2.skyhanni.mixins.transformers; +import at.hannibal2.skyhanni.data.model.TextInput; import at.hannibal2.skyhanni.features.garden.farming.GardenCustomKeybinds; +import at.hannibal2.skyhanni.test.GraphEditor; import net.minecraft.client.settings.KeyBinding; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -18,5 +20,13 @@ public class MixinKeyBinding { @Inject(method = "isKeyDown", at = @At("HEAD"), cancellable = true) public void noIsKeyDown(CallbackInfoReturnable<Boolean> cir) { GardenCustomKeybinds.isKeyDown((KeyBinding) (Object) this, cir); + TextInput.Companion.onMinecraftInput((KeyBinding) (Object) this, cir); + GraphEditor.INSTANCE.onMinecraftInput((KeyBinding) (Object) this, cir); + } + + @Inject(method = "isPressed", at = @At("HEAD"), cancellable = true) + public void noIsPressed(CallbackInfoReturnable<Boolean> cir) { + TextInput.Companion.onMinecraftInput((KeyBinding) (Object) this, cir); + GraphEditor.INSTANCE.onMinecraftInput((KeyBinding) (Object) this, cir); } } diff --git a/src/main/java/at/hannibal2/skyhanni/test/GraphEditor.kt b/src/main/java/at/hannibal2/skyhanni/test/GraphEditor.kt new file mode 100644 index 000000000..618e2d861 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/test/GraphEditor.kt @@ -0,0 +1,480 @@ +package at.hannibal2.skyhanni.test + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.data.model.Graph +import at.hannibal2.skyhanni.data.model.GraphNode +import at.hannibal2.skyhanni.data.model.TextInput +import at.hannibal2.skyhanni.data.model.findShortestPathAsGraph +import at.hannibal2.skyhanni.data.model.toJson +import at.hannibal2.skyhanni.events.GuiRenderEvent +import at.hannibal2.skyhanni.events.LorenzRenderWorldEvent +import at.hannibal2.skyhanni.events.LorenzTickEvent +import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule +import at.hannibal2.skyhanni.test.GriffinUtils.drawWaypointFilled +import at.hannibal2.skyhanni.test.command.ErrorManager +import at.hannibal2.skyhanni.utils.ChatUtils +import at.hannibal2.skyhanni.utils.ColorUtils +import at.hannibal2.skyhanni.utils.KeyboardManager +import at.hannibal2.skyhanni.utils.KeyboardManager.isKeyClicked +import at.hannibal2.skyhanni.utils.KeyboardManager.isKeyHeld +import at.hannibal2.skyhanni.utils.LocationUtils +import at.hannibal2.skyhanni.utils.LocationUtils.distanceSqToPlayer +import at.hannibal2.skyhanni.utils.LorenzColor +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.LorenzVec +import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators +import at.hannibal2.skyhanni.utils.OSUtils +import at.hannibal2.skyhanni.utils.RenderUtils.draw3DLine_nea +import at.hannibal2.skyhanni.utils.RenderUtils.drawDynamicText +import at.hannibal2.skyhanni.utils.RenderUtils.renderStrings +import kotlinx.coroutines.runBlocking +import net.minecraft.client.settings.KeyBinding +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable + +@SkyHanniModule +object GraphEditor { + + private val config get() = SkyHanniMod.feature.dev.devTool.graph + + private fun isEnabled() = config != null && config.enabled + + private var id = 0 + + private val nodes = mutableListOf<GraphingNode>() + private val edges = mutableListOf<GraphingEdge>() + + private var activeNode: GraphingNode? = null + private var closedNode: GraphingNode? = null + + private var seeThroughBlocks = true + + private var inEditMode = false + private var inTextMode = false + set(value) { + field = value + if (value) { + activeNode?.name?.let { + textBox.textBox = it + } + textBox.makeActive() + } else { + textBox.clear() + textBox.disable() + } + } + + private var inTutorialMode = false + + private val textBox = TextInput() + + private val nodeColor = LorenzColor.BLUE.addOpacity(200) + private val activeColor = LorenzColor.GREEN.addOpacity(200) + private val closedColor = LorenzColor.YELLOW.addOpacity(200) + private val dijkstraColor = LorenzColor.LIGHT_PURPLE.addOpacity(200) + + private val edgeColor = LorenzColor.GOLD.addOpacity(150) + private val edgeDijkstraColor = LorenzColor.DARK_BLUE.addOpacity(150) + + @SubscribeEvent + fun onRender(event: LorenzRenderWorldEvent) { + if (!isEnabled()) return + nodes.forEach { event.drawNode(it) } + edges.forEach { event.drawEdge(it) } + } + + @SubscribeEvent + fun onOverlay(event: GuiRenderEvent.GuiOverlayRenderEvent) { + if (!isEnabled()) return + config.infoDisplay.renderStrings(buildDisplay(), posLabel = "Graph Info") + } + + private fun buildDisplay(): List<String> = buildList { + add("§eExit: §6${KeyboardManager.getKeyName(config.exitKey)}") + if (!inEditMode && !inTextMode) { + add("§ePlace: §6${KeyboardManager.getKeyName(config.placeKey)}") + add("§eSelect: §6${KeyboardManager.getKeyName(config.selectKey)}") + add("§eConnect: §6${KeyboardManager.getKeyName(config.connectKey)}") + add("§eTest: §6${KeyboardManager.getKeyName(config.dijkstraKey)}") + add("§eVision: §6${KeyboardManager.getKeyName(config.throughBlocksKey)}") + add("§eSave: §6${KeyboardManager.getKeyName(config.saveKey)}") + add("§eLoad: §6${KeyboardManager.getKeyName(config.loadKey)}") + add("§eClear: §6${KeyboardManager.getKeyName(config.clearKey)}") + add("§eTutorial: §6${KeyboardManager.getKeyName(config.tutorialKey)}") + add(" ") + if (activeNode != null) add("§eText: §6${KeyboardManager.getKeyName(config.textKey)}") + } + if (!inTextMode && activeNode != null) { + add("§eEdit: §6${KeyboardManager.getKeyName(config.editKey)}") + } + if (inEditMode) { + add("§ex+ §6${KeyboardManager.getKeyName(KeyboardManager.WasdInputMatrix.w.keyCode)}") + add("§ex- §6${KeyboardManager.getKeyName(KeyboardManager.WasdInputMatrix.s.keyCode)}") + add("§ez+ §6${KeyboardManager.getKeyName(KeyboardManager.WasdInputMatrix.a.keyCode)}") + add("§ez- §6${KeyboardManager.getKeyName(KeyboardManager.WasdInputMatrix.d.keyCode)}") + add("§ey+ §6${KeyboardManager.getKeyName(KeyboardManager.WasdInputMatrix.up.keyCode)}") + add("§ey- §6${KeyboardManager.getKeyName(KeyboardManager.WasdInputMatrix.down.keyCode)}") + } + if (inTextMode) { + add("§eFormat: ${textBox.finalText()}") + add("§eRaw: ${textBox.editText()}") + } + } + + private fun feedBackInTutorial(text: String) { + if (inTutorialMode) { + ChatUtils.chat(text) + } + } + + @SubscribeEvent + fun onTick(event: LorenzTickEvent) { + if (!isEnabled()) return + input() + if (nodes.isEmpty()) return + closedNode = nodes.minBy { it.position.distanceSqToPlayer() } + } + + private fun LorenzRenderWorldEvent.drawNode(node: GraphingNode) { + this.drawWaypointFilled( + node.position, + node.getNodeColor(), + seeThroughBlocks = seeThroughBlocks, + minimumAlpha = 0.2f, + inverseAlphaScale = true, + ) + if (node.name == null) return + this.drawDynamicText( + node.position, + node.name!!, + 0.8, + ignoreBlocks = seeThroughBlocks || node.position.distanceSqToPlayer() < 100, + smallestDistanceVew = 12.0, + ignoreY = true, + yOff = -15f, + ) + } + + private fun LorenzRenderWorldEvent.drawEdge(edge: GraphingEdge) = this.draw3DLine_nea( + edge.node1.position.add(0.5, 0.5, 0.5), + edge.node2.position.add(0.5, 0.5, 0.5), + if (edge !in highlightedEdges) edgeColor else edgeDijkstraColor, + 7, + !seeThroughBlocks, + ) + + private fun GraphingNode.getNodeColor() = when (this) { + activeNode -> if (this == closedNode) ColorUtils.blendRGB(activeColor, closedColor, 0.5) else activeColor + closedNode -> closedColor + in highlightedNodes -> dijkstraColor + else -> nodeColor + } + + fun commandIn() { + config.enabled = !config.enabled + if (config.enabled) { + ChatUtils.chat("Graph Editor is now active.") + } else { + chatAtDisable() + } + } + + private fun chatAtDisable() = + ChatUtils.clickableChat("Graph Editor is now inactive. §lClick to activate.", ::commandIn) + + private fun input() { + if (LorenzUtils.isAnyGuiActive()) return + if (config.exitKey.isKeyClicked()) { + if (inTextMode) { + inTextMode = false + feedBackInTutorial("Exited Text Mode.") + return + } + if (inEditMode) { + inEditMode = false + feedBackInTutorial("Exited Edit Mode.") + return + } + config.enabled = false + chatAtDisable() + } + if (inTextMode) { + textBox.handle() + val text = textBox.finalText() + if (text.isEmpty()) { + activeNode?.name = null + } else { + activeNode?.name = text + } + return + } + if (activeNode != null && config.textKey.isKeyClicked()) { + inTextMode = true + feedBackInTutorial("Entered Text Mode.") + return + } + if (inEditMode) { + editModeClicks() + inEditMode = false + } + if (activeNode != null && config.editKey.isKeyHeld()) { + inEditMode = true + return + } + if (config.saveKey.isKeyClicked()) { + save() + return + } + if (config.loadKey.isKeyClicked()) { + runBlocking { + OSUtils.readFromClipboard()?.let { + try { + Graph.fromJson(it) + } catch (e: Exception) { + ErrorManager.logErrorWithData( + e, + "Import of graph failed.", + "json" to it, + ignoreErrorCache = true, + ) + null + } + }?.let { + import(it) + ChatUtils.chat("Loaded Graph from clip board.") + } + } + return + } + if (config.clearKey.isKeyClicked()) { + val json = compileGraph().toJson() + OSUtils.copyToClipboard(json) + ChatUtils.chat("Copied Graph to Clipboard and cleared the graph.") + clear() + } + if (config.placeKey.isKeyClicked()) { + addNode() + } + if (config.selectKey.isKeyClicked()) { + activeNode = if (activeNode == closedNode) { + feedBackInTutorial("De selected active node.") + null + } else { + feedBackInTutorial("Selected new active node.") + closedNode + } + } + if (activeNode != closedNode && config.connectKey.isKeyClicked()) { + val edge = getEdgeIndex(activeNode, closedNode) + if (edge == null) { + addEdge(activeNode, closedNode) + feedBackInTutorial("Added new edge.") + } else { + this.edges.removeAt(edge) + feedBackInTutorial("Removed edge.") + } + } + if (config.throughBlocksKey.isKeyClicked()) { + seeThroughBlocks = !seeThroughBlocks + feedBackInTutorial( + if (seeThroughBlocks) "Graph is visible though walls." else "Graph is invisible behind walls.", + ) + } + if (config.dijkstraKey.isKeyClicked()) { + feedBackInTutorial("Calculated shortest route and cleared active node.") + testDijkstra() + } + if (config.tutorialKey.isKeyClicked()) { + inTutorialMode = !inTutorialMode + ChatUtils.chat("Tutorial mode is now ${if (inTutorialMode) "active" else "inactive"}.") + } + } + + private fun save() { + if (nodes.isEmpty()) { + ChatUtils.chat("Copied nothing since the graph is empty.") + return + } + val json = compileGraph().toJson() + OSUtils.copyToClipboard(json) + ChatUtils.chat("Copied Graph to Clipboard.") + if (config.showsStats) { + val length = edges.sumOf { it.node1.position.distance(it.node2.position) }.toInt().addSeparators() + ChatUtils.chat( + "§lStats\n" + + "§eNodes: ${nodes.size}\n" + + "§eEdges: ${edges.size}\n" + + "§eLength: $length", + ) + } + } + + private fun editModeClicks() { + KeyboardManager.WasdInputMatrix.w.handleEditClicks(x = 1) + KeyboardManager.WasdInputMatrix.s.handleEditClicks(x = -1) + KeyboardManager.WasdInputMatrix.a.handleEditClicks(z = 1) + KeyboardManager.WasdInputMatrix.d.handleEditClicks(z = -1) + KeyboardManager.WasdInputMatrix.up.handleEditClicks(y = 1) + KeyboardManager.WasdInputMatrix.down.handleEditClicks(y = -1) + } + + private fun KeyBinding.handleEditClicks(x: Int = 0, y: Int = 0, z: Int = 0) { + if (this.keyCode.isKeyClicked()) { + activeNode?.position = activeNode?.position?.add(x, y, z) ?: return + } + } + + fun onMinecraftInput(keyBinding: KeyBinding, cir: CallbackInfoReturnable<Boolean>) { + if (!isEnabled()) return + if (!inEditMode) return + if (keyBinding !in KeyboardManager.WasdInputMatrix) return + cir.returnValue = false + } + + private fun addNode() { + val closedNode = closedNode + if (closedNode != null && closedNode.position.distanceSqToPlayer() < 9.0) { + feedBackInTutorial("Removed node, since you where closer than 3 blocks from a node.") + nodes.remove(closedNode) + edges.removeIf { it.isInEdge(closedNode) } + if (closedNode == activeNode) activeNode = null + this.closedNode = null + return + } + val position = LocationUtils.playerEyeLocation().roundLocationToBlock() + val node = GraphingNode(id++, position) + nodes.add(node) + feedBackInTutorial("Added graph node.") + if (activeNode == null) return + addEdge(activeNode, node) + } + + private fun getEdgeIndex(node1: GraphingNode?, node2: GraphingNode?) = + if (node1 != null && node2 != null && node1 != node2) GraphingEdge( + node1, + node2, + ).let { e -> edges.indexOfFirst { it == e }.takeIf { it != -1 } } + else null + + private fun addEdge(node1: GraphingNode?, node2: GraphingNode?) = + if (node1 != null && node2 != null && node1 != node2) edges.add(GraphingEdge(node1, node2)) else false + + /** Has a side effect on the graphing graph, since it runs [prune] on the graphing graph*/ + private fun compileGraph(): Graph { + prune() + val indexedTable = nodes.mapIndexed { index, node -> node.id to index }.toMap() + val nodes = nodes.mapIndexed { index, it -> GraphNode(index, it.position, it.name) } + val neighbours = this.nodes.map { node -> + edges.filter { it.isInEdge(node) }.map { edge -> + val otherNode = if (node == edge.node1) edge.node2 else edge.node1 + nodes[indexedTable[otherNode.id]!!] to node.position.distance(otherNode.position) + }.sortedBy { it.second } + } + nodes.forEachIndexed { index, it -> it.neighbours = neighbours[index].toMap() } + return Graph(nodes) + } + + fun import(graph: Graph) { + clear() + nodes.addAll(graph.map { GraphingNode(it.id, it.position, it.name) }) + val translation = graph.mapIndexed { index, it -> it to nodes[index] }.toMap() + edges.addAll( + graph.map { node -> + node.neighbours.map { GraphingEdge(translation[node]!!, translation[it.key]!!) } + }.flatten().distinct(), + ) + id = nodes.lastOrNull()?.id?.plus(1) ?: 0 + } + + private val highlightedNodes = mutableSetOf<GraphingNode>() + private val highlightedEdges = mutableSetOf<GraphingEdge>() + + private fun testDijkstra() { + + val savedCurrent = closedNode ?: return + val savedActive = activeNode ?: return + + val compiled = compileGraph() + import(compiled) + highlightedEdges.clear() + highlightedNodes.clear() + + val current = compiled.firstOrNull { it.position == savedCurrent.position } ?: return + val goal = compiled.firstOrNull { it.position == savedActive.position } ?: return + + val path = compiled.findShortestPathAsGraph(current, goal) + + val inGraph = path.map { nodes[it.id] } + highlightedNodes.addAll(inGraph) + + val edge = edges.filter { highlightedNodes.contains(it.node1) && highlightedNodes.contains(it.node2) } + highlightedEdges.addAll(edge) + } + + private fun clear() { + id = 0 + nodes.clear() + edges.clear() + activeNode = null + closedNode = null + } + + private fun prune() { //TODO fix + val hasNeighbours = nodes.associateWith { false }.toMutableMap() + edges.forEach { + hasNeighbours[it.node1] = true + hasNeighbours[it.node2] = true + } + nodes.removeIf { hasNeighbours[it] == false } + } +} + +private class GraphingNode(val id: Int, var position: LorenzVec, var name: String? = null) { + + override fun hashCode(): Int { + return id + } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as GraphingNode + + if (id != other.id) return false + + return true + } +} + +private class GraphingEdge(val node1: GraphingNode, val node2: GraphingNode) { + + fun isInEdge(node: GraphingNode) = node1 == node || node2 == node + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as GraphingEdge + + return (this.node1 == other.node1 && this.node2 == other.node2) || + (this.node1 == other.node2 && this.node2 == other.node1) + } + + override fun hashCode(): Int { + val hash1 = node1.hashCode() + val hash2 = node2.hashCode() + + var result: Int + if (hash1 <= hash2) { + result = hash1 + result = 31 * result + hash2 + } else { + result = hash2 + result = 31 * result + hash1 + } + return result + } + +} + diff --git a/src/main/java/at/hannibal2/skyhanni/test/GriffinUtils.kt b/src/main/java/at/hannibal2/skyhanni/test/GriffinUtils.kt index b957129cc..195f06989 100644 --- a/src/main/java/at/hannibal2/skyhanni/test/GriffinUtils.kt +++ b/src/main/java/at/hannibal2/skyhanni/test/GriffinUtils.kt @@ -18,6 +18,8 @@ object GriffinUtils { extraSize: Double = 0.0, extraSizeTopY: Double = extraSize, extraSizeBottomY: Double = extraSize, + minimumAlpha: Float = 0.2f, + inverseAlphaScale: Boolean = false, ) { val (viewerX, viewerY, viewerZ) = RenderUtils.getViewerPos(partialTicks) val x = location.x - viewerX @@ -27,24 +29,27 @@ object GriffinUtils { if (seeThroughBlocks) { GlStateManager.disableDepth() - GlStateManager.disableCull() } + + GlStateManager.disableCull() RenderUtils.drawFilledBoundingBox( + @Suppress("ktlint:standard:argument-list-wrapping") AxisAlignedBB( x - extraSize, y - extraSizeBottomY, z - extraSize, - x + 1 + extraSize, y + 1 + extraSizeTopY, z + 1 + extraSize + x + 1 + extraSize, y + 1 + extraSizeTopY, z + 1 + extraSize, ).expandBlock(), color, - (0.1f + 0.005f * distSq.toFloat()).coerceAtLeast(0.2f) + if (inverseAlphaScale) (1.0f - 0.005f * distSq.toFloat()).coerceAtLeast(minimumAlpha) + else (0.1f + 0.005f * distSq.toFloat()).coerceAtLeast(minimumAlpha), ) GlStateManager.disableTexture2D() if (distSq > 5 * 5 && beacon) RenderUtils.renderBeaconBeam(x, y + 1, z, color.rgb, 1.0f, partialTicks) GlStateManager.disableLighting() GlStateManager.enableTexture2D() + GlStateManager.enableCull() if (seeThroughBlocks) { GlStateManager.enableDepth() - GlStateManager.enableCull() } } } diff --git a/src/main/java/at/hannibal2/skyhanni/test/ParkourWaypointSaver.kt b/src/main/java/at/hannibal2/skyhanni/test/ParkourWaypointSaver.kt index 15ef4ac5c..d56bf7a66 100644 --- a/src/main/java/at/hannibal2/skyhanni/test/ParkourWaypointSaver.kt +++ b/src/main/java/at/hannibal2/skyhanni/test/ParkourWaypointSaver.kt @@ -30,6 +30,7 @@ object ParkourWaypointSaver { if (!LorenzUtils.inSkyBlock && !config.parkourOutsideSB) return if (Minecraft.getMinecraft().currentScreen != null) return if (NEUItems.neuHasFocus()) return + if (SkyHanniMod.feature.dev.devTool.graph.enabled) return if (timeLastSaved.passedSince() < 250.milliseconds) return when (event.keyCode) { diff --git a/src/main/java/at/hannibal2/skyhanni/utils/ConditionalUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/ConditionalUtils.kt index 00aec1dc5..05e53b802 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/ConditionalUtils.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/ConditionalUtils.kt @@ -30,4 +30,30 @@ object ConditionalUtils { whenChanged { _, new -> observer(new) } } + fun <T : Comparable<T>, K> comparatorFirst(pair1: Pair<T?, K>, pair2: Pair<T?, K>): Int { + val first1 = pair1.first + val first2 = pair2.first + + // Handle null cases + if (first1 == null && first2 == null) return 0 + if (first1 == null) return -1 + if (first2 == null) return 1 + + // Compare the non-null first values + return first1.compareTo(first2) + } + + fun <T, K : Comparable<K>> comparatorSecond(pair1: Pair<T, K?>, pair2: Pair<T, K?>): Int { + val second1 = pair1.second + val second2 = pair2.second + + // Handle null cases + if (second1 == null && second2 == null) return 0 + if (second1 == null) return 1 + if (second2 == null) return -1 + + // Compare the non-null second values + return second1.compareTo(second2) + } + } diff --git a/src/main/java/at/hannibal2/skyhanni/utils/KeyboardManager.kt b/src/main/java/at/hannibal2/skyhanni/utils/KeyboardManager.kt index c04057e72..9bf129be2 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/KeyboardManager.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/KeyboardManager.kt @@ -133,4 +133,43 @@ object KeyboardManager { } fun getKeyName(keyCode: Int): String = KeybindHelper.getKeyName(keyCode) + + object WasdInputMatrix : Iterable<KeyBinding> { + operator fun contains(keyBinding: KeyBinding) = when (keyBinding) { + w, a, s, d, up, down -> true + else -> false + } + + val w get() = Minecraft.getMinecraft().gameSettings.keyBindForward!! + val a get() = Minecraft.getMinecraft().gameSettings.keyBindLeft!! + val s get() = Minecraft.getMinecraft().gameSettings.keyBindBack!! + val d get() = Minecraft.getMinecraft().gameSettings.keyBindRight!! + + val up get() = Minecraft.getMinecraft().gameSettings.keyBindJump!! + val down get() = Minecraft.getMinecraft().gameSettings.keyBindSneak!! + + override fun iterator(): Iterator<KeyBinding> = + object : Iterator<KeyBinding> { + + var current = w + + override fun hasNext(): Boolean = + current != down + + override fun next(): KeyBinding { + return current.also { + current = when (it) { + w -> a + a -> s + s -> d + d -> up + up -> down + else -> throw java.lang.IndexOutOfBoundsException() + } + } + } + + } + + } } diff --git a/src/main/java/at/hannibal2/skyhanni/utils/LorenzUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/LorenzUtils.kt index f52f7f72b..698098306 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/LorenzUtils.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/LorenzUtils.kt @@ -15,10 +15,12 @@ import at.hannibal2.skyhanni.test.TestBingo import at.hannibal2.skyhanni.utils.ChatUtils.lastButtonClicked import at.hannibal2.skyhanni.utils.ItemUtils.getItemCategoryOrNull import at.hannibal2.skyhanni.utils.NEUItems.getItemStackOrNull +import at.hannibal2.skyhanni.utils.SimpleTimeMark.Companion.fromNow import at.hannibal2.skyhanni.utils.StringUtils.capAtMinecraftLength import at.hannibal2.skyhanni.utils.StringUtils.removeColor import at.hannibal2.skyhanni.utils.StringUtils.stripHypixelMessage import at.hannibal2.skyhanni.utils.StringUtils.toDashlessUUID +import at.hannibal2.skyhanni.utils.TimeUtils.ticks import at.hannibal2.skyhanni.utils.renderables.Renderable import com.google.gson.JsonPrimitive import net.minecraft.client.Minecraft @@ -178,7 +180,7 @@ object LorenzUtils { val left = Renderable.hoverTips( entry.left, tips = entry.hover, - highlightsOnHoverSlots = entry.highlightsOnHoverSlots + highlightsOnHoverSlots = entry.highlightsOnHoverSlots, ) val right = Renderable.string(entry.right) outerList.add(listOf(item, left, right)) @@ -239,9 +241,11 @@ object LorenzUtils { add("§a[$display]") } else { add("§e[") - add(Renderable.link("§e$display") { - onChange(entry) - }) + add( + Renderable.link("§e$display") { + onChange(entry) + }, + ) add("§e]") } add(" ") @@ -262,25 +266,29 @@ object LorenzUtils { lastButtonClicked = System.currentTimeMillis() } } - add(buildList { - add(prefix) - add("§a[") - if (tips.isEmpty()) { - add(Renderable.link("§e$getName", false, onClick)) - } else { - add(Renderable.clickAndHover("§e$getName", tips, false, onClick)) - } - add("§a]") - }) + add( + buildList { + add(prefix) + add("§a[") + if (tips.isEmpty()) { + add(Renderable.link("§e$getName", false, onClick)) + } else { + add(Renderable.clickAndHover("§e$getName", tips, false, onClick)) + } + add("§a]") + }, + ) } fun GuiEditSign.isRancherSign(): Boolean { if (this !is AccessorGuiEditSign) return false val tileSign = (this as AccessorGuiEditSign).tileSign - return (tileSign.signText[1].unformattedText.removeColor() == "^^^^^^" - && tileSign.signText[2].unformattedText.removeColor() == "Set your" - && tileSign.signText[3].unformattedText.removeColor() == "speed cap!") + return ( + tileSign.signText[1].unformattedText.removeColor() == "^^^^^^" && + tileSign.signText[2].unformattedText.removeColor() == "Set your" && + tileSign.signText[3].unformattedText.removeColor() == "speed cap!" + ) } fun IslandType.isInIsland() = inSkyBlock && skyBlockIsland == this @@ -291,7 +299,11 @@ object LorenzUtils { if (this.clickedButton == 1 && slot?.stack?.getItemCategoryOrNull() == ItemCategory.SACK) return slot?.slotNumber?.let { slotNumber -> Minecraft.getMinecraft().playerController.windowClick( - container.windowId, slotNumber, 0, 1, Minecraft.getMinecraft().thePlayer + container.windowId, + slotNumber, + 0, + 1, + Minecraft.getMinecraft().thePlayer, ) this.cancel() } @@ -344,14 +356,24 @@ object LorenzUtils { @Deprecated("Use the new one instead", ReplaceWith("RegexUtils.hasGroup")) fun Matcher.hasGroup(groupName: String): Boolean = groupOrNull(groupName) != null - fun inAdvancedMiningIsland() = - IslandType.DWARVEN_MINES.isInIsland() || IslandType.CRYSTAL_HOLLOWS.isInIsland() || IslandType.MINESHAFT.isInIsland() + fun inAdvancedMiningIsland() = IslandType.DWARVEN_MINES.isInIsland() || + IslandType.CRYSTAL_HOLLOWS.isInIsland() || IslandType.MINESHAFT.isInIsland() - fun inMiningIsland() = IslandType.GOLD_MINES.isInIsland() || IslandType.DEEP_CAVERNS.isInIsland() - || inAdvancedMiningIsland() + fun inMiningIsland() = IslandType.GOLD_MINES.isInIsland() || + IslandType.DEEP_CAVERNS.isInIsland() || inAdvancedMiningIsland() fun isBetaVersion() = UpdateManager.isCurrentlyBeta() + private var lastGuiTime = SimpleTimeMark.farPast() + + fun isAnyGuiActive(): Boolean { + val gui = Minecraft.getMinecraft().currentScreen != null + if (gui) { + lastGuiTime = 3.ticks.fromNow() + } + return !lastGuiTime.isInPast() + } + fun AxisAlignedBB.getCorners(y: Double): List<LorenzVec> { val cornerOne = LorenzVec(minX, y, minZ) val cornerTwo = LorenzVec(minX, y, maxZ) diff --git a/src/main/java/at/hannibal2/skyhanni/utils/RenderUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/RenderUtils.kt index 1506882cd..e3c4b6d7b 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/RenderUtils.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/RenderUtils.kt @@ -74,7 +74,7 @@ object RenderUtils { private val beaconBeam = ResourceLocation("textures/entity/beacon_beam.png") - private val matrixBuffer: FloatBuffer = GLAllocation.createDirectFloatBuffer(16); + private val matrixBuffer: FloatBuffer = GLAllocation.createDirectFloatBuffer(16) private val colourBuffer: FloatBuffer = GLAllocation.createDirectFloatBuffer(16) private val bezier2Buffer: FloatBuffer = GLAllocation.createDirectFloatBuffer(9) @@ -166,7 +166,7 @@ object RenderUtils { drawFilledBoundingBox( AxisAlignedBB(x, y, z, x + 1, y + 1, z + 1).expandBlock(), color, - realAlpha + realAlpha, ) GlStateManager.disableTexture2D() if (distSq > 5 * 5 && beacon) renderBeaconBeam(x, y + 1, z, color.rgb, 1.0f, partialTicks) @@ -222,7 +222,7 @@ object RenderUtils { val time = Minecraft.getMinecraft().theWorld.totalWorldTime + partialTicks.toDouble() val d1 = MathHelper.func_181162_h( -time * 0.2 - MathHelper.floor_double(-time * 0.1) - .toDouble() + .toDouble(), ) val r = (rgb shr 16 and 0xFF) / 255f val g = (rgb shr 8 and 0xFF) / 255f @@ -352,7 +352,7 @@ object RenderUtils { Minecraft.getMinecraft().renderManager.playerViewX, 1.0f, 0.0f, - 0.0f + 0.0f, ) GlStateManager.scale(-f1, -f1, f1) GlStateManager.disableLighting() @@ -440,7 +440,7 @@ object RenderUtils { (-width).toFloat(), yOff, LorenzColor.WHITE.toColor().rgb, - shadow + shadow, ) GlStateManager.disableBlend() GlStateManager.popMatrix() @@ -618,8 +618,9 @@ object RenderUtils { } } catch (e: NullPointerException) { ErrorManager.logErrorWithData( - e, "Failed to render an element", - "list" to list + e, + "Failed to render an element", + "list" to list, ) } GuiEditManager.add(this, posLabel, longestX, offsetY) @@ -638,8 +639,11 @@ object RenderUtils { renderRenderables( listOf( Renderable.horizontalContainer( - list.mapNotNull { Renderable.fromAny(it) } - )), posLabel = posLabel) + list.mapNotNull { Renderable.fromAny(it) }, + ), + ), + posLabel = posLabel, + ) // TODO Future write that better } @@ -675,8 +679,9 @@ object RenderUtils { add(Renderable.itemStack(item, scale)) } catch (e: NullPointerException) { ErrorManager.logErrorWithData( - e, "Add item icon to renderable list", - "item" to item + e, + "Add item icon to renderable list", + "item" to item, ) } } @@ -954,6 +959,7 @@ object RenderUtils { hideTooCloseAt: Double = 4.5, smallestDistanceVew: Double = 5.0, ignoreBlocks: Boolean = true, + ignoreY: Boolean = false, ) { val thePlayer = Minecraft.getMinecraft().thePlayer val x = location.x @@ -966,24 +972,29 @@ object RenderUtils { val renderOffsetZ = render.lastTickPosZ + (render.posZ - render.lastTickPosZ) * partialTicks val eyeHeight = thePlayer.eyeHeight - val distToPlayerSq = - (x - renderOffsetX) * (x - renderOffsetX) + (y - (renderOffsetY + eyeHeight)) * (y - (renderOffsetY + eyeHeight)) + (z - renderOffsetZ) * (z - renderOffsetZ) + val dX = (x - renderOffsetX) * (x - renderOffsetX) + val dY = (y - (renderOffsetY + eyeHeight)) * (y - (renderOffsetY + eyeHeight)) + val dZ = (z - renderOffsetZ) * (z - renderOffsetZ) + val distToPlayerSq = dX + dY + dZ var distToPlayer = sqrt(distToPlayerSq) // TODO this is optional maybe? distToPlayer = distToPlayer.coerceAtLeast(smallestDistanceVew) if (distToPlayer < hideTooCloseAt) return + if (ignoreBlocks && distToPlayer > 80) return val distRender = distToPlayer.coerceAtMost(50.0) + var scale = distRender / 12 + scale *= scaleMultiplier + val resultX = renderOffsetX + (x + 0.5 - renderOffsetX) / (distToPlayer / distRender) - val resultY = - (renderOffsetY + eyeHeight) + (y + 20 * distToPlayer / 300 - (renderOffsetY + eyeHeight)) / (distToPlayer / distRender) + val resultY = if (ignoreY) y * distToPlayer / distRender else renderOffsetY + eyeHeight + + (y + 20 * distToPlayer / 300 - (renderOffsetY + eyeHeight)) / (distToPlayer / distRender) val resultZ = renderOffsetZ + (z + 0.5 - renderOffsetZ) / (distToPlayer / distRender) val renderLocation = LorenzVec(resultX, resultY, resultZ) - var scale = distRender / 12 - scale *= scaleMultiplier + render(renderLocation, "§f$text", scale, !ignoreBlocks, true, yOff) } @@ -1010,7 +1021,7 @@ object RenderUtils { GlStateManager.translate( location.x - renderManager.viewerPosX, location.y - renderManager.viewerPosY, - location.z - renderManager.viewerPosZ + location.z - renderManager.viewerPosZ, ) GlStateManager.color(1f, 1f, 1f, 0.5f) GlStateManager.rotate(-renderManager.playerViewY, 0.0f, 1.0f, 0.0f) @@ -1022,14 +1033,14 @@ object RenderUtils { text, (-stringWidth / 2).toFloat(), yOff, - 0 + 0, ) } else { fontRenderer.drawString( text, -stringWidth / 2, 0, - 0 + 0, ) } GlStateManager.color(1f, 1f, 1f) @@ -1088,7 +1099,7 @@ object RenderUtils { c.red / 255f * 0.8f, c.green / 255f * 0.8f, c.blue / 255f * 0.8f, - c.alpha / 255f * alphaMultiplier + c.alpha / 255f * alphaMultiplier, ) // x @@ -1108,7 +1119,7 @@ object RenderUtils { c.red / 255f * 0.9f, c.green / 255f * 0.9f, c.blue / 255f * 0.9f, - c.alpha / 255f * alphaMultiplier + c.alpha / 255f * alphaMultiplier, ) // z worldRenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION) @@ -1142,6 +1153,7 @@ object RenderUtils { drawFilledBoundingBox_nea(aabb, c, alphaMultiplier, renderRelativeToCamera, drawVerticalBarriers, partialTicks) } + @Suppress("ktlint:standard:function-naming") fun drawWireframeBoundingBox_nea( aabb: AxisAlignedBB, color: Color, @@ -1153,6 +1165,8 @@ object RenderUtils { GlStateManager.disableTexture2D() GlStateManager.disableCull() val vp = getViewerPos(partialTicks) + + @Suppress("ktlint:standard:argument-list-wrapping") val effectiveAABB = AxisAlignedBB( aabb.minX - vp.x, aabb.minY - vp.y, aabb.minZ - vp.z, aabb.maxX - vp.x, aabb.maxY - vp.y, aabb.maxZ - vp.z, @@ -1220,7 +1234,7 @@ object RenderUtils { middlePoint, sidePoint1, sidePoint2, - c + c, ) } @@ -1238,9 +1252,10 @@ object RenderUtils { if (path.isEmpty()) return val points = if (startAtEye) { listOf( - this.exactPlayerEyeLocation() - + Minecraft.getMinecraft().thePlayer.getLook(this.partialTicks) - .toLorenzVec()/* .rotateXZ(-Math.PI / 72.0) */.times(2) + this.exactPlayerEyeLocation() + Minecraft.getMinecraft().thePlayer.getLook(this.partialTicks) + .toLorenzVec() + /* .rotateXZ(-Math.PI / 72.0) */ + .times(2), ) } else { emptyList() @@ -1251,7 +1266,7 @@ object RenderUtils { colorLine, lineWidth, depth, - bezierPoint + bezierPoint, ) } path.filter { it.name?.isNotEmpty() == true }.forEach { @@ -1277,7 +1292,7 @@ object RenderUtils { if (index != pathLines.lastIndex) it.second - reduce else it.second, color, lineWidth, - depth + depth, ) } path.zipWithNext3().forEach { @@ -1328,8 +1343,12 @@ object RenderUtils { } bezier2Buffer.flip() GL11.glMap1f( - GL11.GL_MAP1_VERTEX_3, 0.0f, 1.0f, 3, 3, - bezier2Buffer + GL11.GL_MAP1_VERTEX_3, + 0.0f, + 1.0f, + 3, + 3, + bezier2Buffer, ) GL11.glEnable(GL11.GL_MAP1_VERTEX_3) @@ -1475,7 +1494,7 @@ object RenderUtils { c.red / 255f * 0.8f, c.green / 255f * 0.8f, c.blue / 255f * 0.8f, - c.alpha / 255f * alphaMultiplier + c.alpha / 255f * alphaMultiplier, ) // x @@ -1497,7 +1516,7 @@ object RenderUtils { c.red / 255f * 0.9f, c.green / 255f * 0.9f, c.blue / 255f * 0.9f, - c.alpha / 255f * alphaMultiplier + c.alpha / 255f * alphaMultiplier, ) // z worldRenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION) @@ -1525,7 +1544,7 @@ object RenderUtils { colour: Color, depth: Boolean, ) { - val (cornerOne, cornerTwo, cornerThree, cornerFour, ) = boundingBox.getCorners(boundingBox.maxY) + val (cornerOne, cornerTwo, cornerThree, cornerFour) = boundingBox.getCorners(boundingBox.maxY) this.draw3DLine(cornerOne, cornerTwo, colour, lineWidth, depth) this.draw3DLine(cornerTwo, cornerThree, colour, lineWidth, depth) this.draw3DLine(cornerThree, cornerFour, colour, lineWidth, depth) @@ -1536,7 +1555,6 @@ object RenderUtils { fun LorenzRenderWorldEvent.draw3DLine_nea( p1: LorenzVec, p2: LorenzVec, color: Color, lineWidth: Int, depth: Boolean, ) { - GlStateManager.disableDepth() GlStateManager.disableCull() val render = Minecraft.getMinecraft().renderViewEntity @@ -1571,7 +1589,7 @@ object RenderUtils { GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f) GlStateManager.popMatrix() GlStateManager.disableLighting() - GlStateManager.enableDepth() + GlStateManager.enableCull() } fun chromaColor( @@ -1585,8 +1603,8 @@ object RenderUtils { Color.HSBtoRGB( ((offset + timeOverride / timeTillRepeat.toDouble(DurationUnit.MILLISECONDS)) % 1).toFloat(), saturation, - brightness - ) + brightness, + ), ) } @@ -1722,7 +1740,7 @@ object RenderUtils { x + width + borderAdjustment, y + height + borderAdjustment, topColor, - bottomColor + bottomColor, ) ShaderManager.disableShader() diff --git a/src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt index 3ddeb498c..f180e6bf7 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt @@ -230,20 +230,22 @@ object StringUtils { fun String.removeWordsAtEnd(i: Int) = split(" ").dropLast(i).joinToString(" ") - fun String.splitLines(width: Int): String { - val fr = Minecraft.getMinecraft().fontRendererObj - return GuiUtilRenderComponents.splitText( - ChatComponentText(this), width, fr, false, false - ).joinToString("\n") { - val text = it.formattedText - val formatCode = Regex("(?:§[a-f0-9l-or]|\\s)*") - formatCode.matchAt(text, 0)?.let { matcher -> - val codes = matcher.value.replace("\\s".toRegex(), "") - codes + text.removeRange(matcher.range) - } ?: text - } + fun String.splitLines(width: Int): String = GuiUtilRenderComponents.splitText( + ChatComponentText(this), + width, + Minecraft.getMinecraft().fontRendererObj, + false, + false, + ).joinToString("\n") { + val text = it.formattedText + val formatCode = Regex("(?:§[a-f0-9l-or]|\\s)*") + formatCode.matchAt(text, 0)?.let { matcher -> + val codes = matcher.value.replace("\\s".toRegex(), "") + codes + text.removeRange(matcher.range) + } ?: text } + /** * Creates a comma-separated list using natural formatting (a, b, and c). * @param list - the list of strings to join into a string, containing 0 or more elements. @@ -381,6 +383,10 @@ object StringUtils { fun generateRandomId() = UUID.randomUUID().toString() + fun String.insert(pos: Int, chars: CharSequence): String = this.substring(0, pos) + chars + this.substring(pos) + + fun String.insert(pos: Int, char: Char): String = this.substring(0, pos) + char + this.substring(pos) + fun replaceIfNeeded( original: ChatComponentText, newText: String, |