aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThunderblade73 <85900443+Thunderblade73@users.noreply.github.com>2024-06-10 03:11:42 +0200
committerGitHub <noreply@github.com>2024-06-10 03:11:42 +0200
commit1fe45f026afeff9d87107380bf8c4cf58051b29f (patch)
tree362a2d3cf9f0e1c4dbfabb710cd51ab0c7c11ee3
parentb1ff611e4f764c5fba338571540f0ad2389994ac (diff)
downloadskyhanni-1fe45f026afeff9d87107380bf8c4cf58051b29f.tar.gz
skyhanni-1fe45f026afeff9d87107380bf8c4cf58051b29f.tar.bz2
skyhanni-1fe45f026afeff9d87107380bf8c4cf58051b29f.zip
Backend: Graph Editor (#1454)
Co-authored-by: Cal <cwolfson58@gmail.com> Co-authored-by: CalMWolfs <94038482+CalMWolfs@users.noreply.github.com> Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com>
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt201
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/dev/DevConfig.java4
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/dev/DevToolConfig.java14
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/dev/GraphConfig.java87
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/model/Graph.kt30
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/model/TextInput.kt133
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/DefaultConfigFeatures.kt13
-rw-r--r--src/main/java/at/hannibal2/skyhanni/mixins/transformers/MixinKeyBinding.java10
-rw-r--r--src/main/java/at/hannibal2/skyhanni/test/GraphEditor.kt480
-rw-r--r--src/main/java/at/hannibal2/skyhanni/test/GriffinUtils.kt13
-rw-r--r--src/main/java/at/hannibal2/skyhanni/test/ParkourWaypointSaver.kt1
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/ConditionalUtils.kt26
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/KeyboardManager.kt39
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/LorenzUtils.kt66
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/RenderUtils.kt94
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt30
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,