diff options
Diffstat (limited to 'src/main/java/at/hannibal2/skyhanni')
11 files changed, 491 insertions, 1 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt index e67ef054b..f7361ad5f 100644 --- a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt +++ b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt @@ -44,6 +44,7 @@ import at.hannibal2.skyhanni.features.misc.* import at.hannibal2.skyhanni.features.misc.discordrpc.DiscordRPCManager import at.hannibal2.skyhanni.features.misc.items.EstimatedItemValue import at.hannibal2.skyhanni.features.misc.items.EstimatedWardrobePrice +import at.hannibal2.skyhanni.features.misc.tabcomplete.WarpTabComplete import at.hannibal2.skyhanni.features.misc.teleportpad.TeleportPadCompactName import at.hannibal2.skyhanni.features.misc.teleportpad.TeleportPadInventoryNumber import at.hannibal2.skyhanni.features.misc.tiarelay.TiaRelayHelper @@ -142,6 +143,8 @@ class SkyHanniMod { loadModule(GardenAPI) loadModule(CollectionAPI()) loadModule(FarmingContestAPI) + loadModule(FriendAPI()) + loadModule(PartyAPI()) // features loadModule(BazaarOrderHelper()) @@ -286,6 +289,7 @@ class SkyHanniMod { loadModule(CityProjectFeatures()) loadModule(GardenPlotIcon) loadModule(ShowFishingItemName()) + loadModule(WarpTabComplete) init() 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 657f675d7..147734b30 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt +++ b/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt @@ -14,9 +14,9 @@ import at.hannibal2.skyhanni.features.garden.GardenCropTimeCommand import at.hannibal2.skyhanni.features.garden.composter.ComposterOverlay import at.hannibal2.skyhanni.features.garden.farming.CropMoneyDisplay import at.hannibal2.skyhanni.features.garden.farming.CropSpeedMeter +import at.hannibal2.skyhanni.features.garden.farming.GardenStartLocation import at.hannibal2.skyhanni.features.garden.fortuneguide.CaptureFarmingGear import at.hannibal2.skyhanni.features.garden.fortuneguide.FFGuideGUI -import at.hannibal2.skyhanni.features.garden.farming.GardenStartLocation import at.hannibal2.skyhanni.features.minion.MinionFeatures import at.hannibal2.skyhanni.features.misc.CollectionCounter import at.hannibal2.skyhanni.features.misc.MarkedPlayerManager diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/Misc.java b/src/main/java/at/hannibal2/skyhanni/config/features/Misc.java index 34659f97c..41d187421 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/Misc.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/Misc.java @@ -385,6 +385,44 @@ public class Misc { public Position pos = new Position(150, 150, false, true); } + @ConfigOption(name = "Tab Complete Commands", desc = "") + @Accordion + @Expose + public TabCompleteCommands tabCompleteCommands = new TabCompleteCommands(); + + public static class TabCompleteCommands { + + @Expose + @ConfigOption(name = "Warps", desc = "Tab complete the warp-point names when typing §e/warp <TAB>§7.") + @ConfigEditorBoolean + public boolean warps = true; + + @Expose + @ConfigOption(name = "Island Players", desc = "Tab complete other players on the same island.") + @ConfigEditorBoolean + public boolean islandPlayers = true; + + @Expose + @ConfigOption(name = "Friends", desc = "Tab complete friends from your friends list.") + @ConfigEditorBoolean + public boolean friends = true; + + @Expose + @ConfigOption(name = "Only Best Friends", desc = "Only Tab Complete best friends.") + @ConfigEditorBoolean + public boolean onlyBestFriends = false; + + @Expose + @ConfigOption(name = "Party", desc = "Tab complete party members.") + @ConfigEditorBoolean + public boolean party = true; + + @Expose + @ConfigOption(name = "VIP Visits", desc = "Tab complete the visit to special users like PortalHub or prtlhub") + @ConfigEditorBoolean + public boolean vipVisits = true; + } + @Expose @ConfigOption(name = "Exp Bottles", desc = "Hides all the experience orbs lying on the ground.") @ConfigEditorBoolean diff --git a/src/main/java/at/hannibal2/skyhanni/data/FriendAPI.kt b/src/main/java/at/hannibal2/skyhanni/data/FriendAPI.kt new file mode 100644 index 000000000..5cc815437 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/data/FriendAPI.kt @@ -0,0 +1,144 @@ +package at.hannibal2.skyhanni.data + +import at.hannibal2.skyhanni.config.ConfigManager +import at.hannibal2.skyhanni.events.HypixelJoinEvent +import at.hannibal2.skyhanni.events.LorenzChatEvent +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.StringUtils.cleanPlayerName +import at.hannibal2.skyhanni.utils.StringUtils.matchMatcher +import at.hannibal2.skyhanni.utils.jsonobjects.FriendsJson +import at.hannibal2.skyhanni.utils.jsonobjects.FriendsJson.PlayerFriends.Friend +import net.minecraft.util.ChatStyle +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import java.io.File +import java.io.FileReader +import java.util.* + +class FriendAPI { + private val file = File("config/skyhanni/friends.json") + private val removedFriendPattern = + ".*\n§r§eYou removed §r(?<name>.*)§e from your friends list!§r§9§m\n.*".toPattern() + private val addedFriendPattern = "§aYou are now friends with (?<name>.*)".toPattern() + private val noBestFriendPattern = ".*\n§r(?<name>.*)§e is no longer a best friend!§r§9§m\n.*".toPattern() + private val bestFriendPattern = ".*\n(?<name>.*)§a is now a best friend!§r§9§m\n.*".toPattern() + + companion object { + + private var friendsJson: FriendsJson? = null + + private fun getFriends(): MutableMap<UUID, Friend> { + val friendsJson = friendsJson ?: error("savedFriends not loaded yet!") + return friendsJson.players.getOrPut(LorenzUtils.getRawPlayerUuid()) { + FriendsJson.PlayerFriends().also { it.friends = mutableMapOf() } + }.friends + } + + private val tempFriends = mutableListOf<Friend>() + + fun getAllFriends(): List<Friend> { + val list = mutableListOf<Friend>() + list.addAll(getFriends().values) + list.addAll(tempFriends) + return list + } + } + + @SubscribeEvent + fun onHypixelJoin(event: HypixelJoinEvent) { + if (file.isFile) { + friendsJson = ConfigManager.gson.fromJson(FileReader(file), FriendsJson::class.java) + } + if (friendsJson == null) { + file.parentFile.mkdirs() + file.createNewFile() + friendsJson = FriendsJson().also { it.players = mutableMapOf() } + saveConfig() + } + } + + fun saveConfig() { + file.writeText(ConfigManager.gson.toJson(friendsJson)) + } + + @SubscribeEvent + fun onChat(event: LorenzChatEvent) { + readFriendsList(event) + + removedFriendPattern.matchMatcher(event.message) { + val name = group("name").cleanPlayerName() + println("removed friend: '$name'") + removedFriend(name) + } + addedFriendPattern.matchMatcher(event.message) { + val name = group("name").cleanPlayerName() + println("added friend: '$name'") + addFriend(name) + } + + noBestFriendPattern.matchMatcher(event.message) { + val name = group("name").cleanPlayerName() + println("no best friend: '$name'") + setBestFriend(name, false) + } + bestFriendPattern.matchMatcher(event.message) { + val name = group("name").cleanPlayerName() + println("best friend: '$name'") + setBestFriend(name, true) + } + } + + private fun setBestFriend(name: String, bestFriend: Boolean) { + getFriends().entries.firstOrNull { it.value.name == name }?.let { + it.value.bestFriend = bestFriend + saveConfig() + } + } + + private fun addFriend(name: String) { + tempFriends.add(Friend().also { it.name = name }) + } + + private fun removedFriend(name: String) { + tempFriends.removeIf { it.name == name } + getFriends().entries.removeIf { it.value.name == name } + saveConfig() + } + + private fun readFriendsList(event: LorenzChatEvent) { + if (!event.message.contains("Friends")) return + + for (sibling in event.chatComponent.siblings) { + val chatStyle = sibling.chatStyle ?: continue + val value = chatStyle.chatClickEvent?.value ?: continue + if (!value.startsWith("/viewprofile")) continue + + val uuid = "/viewprofile (?<uuid>.*)".toPattern().matchMatcher(value) { + group("uuid")?.let { + UUID.fromString(it) + } + } + val bestFriend = sibling.unformattedText.contains("§l") + val name = readName(chatStyle) + if (uuid != null && name != null) { + getFriends()[uuid] = Friend().also { + it.name = name + it.bestFriend = bestFriend + } + } + } + + saveConfig() + } + + private fun readName(chatStyle: ChatStyle): String? { + for (component in chatStyle.chatHoverEvent.value.siblings) { + val rawName = component.unformattedText + val rawNamePattern = "\\n§eClick to view §.(?<name>.*)§e's profile".toPattern() + rawNamePattern.matchMatcher(rawName) { + return group("name") + } + } + + return null + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/data/PartyAPI.kt b/src/main/java/at/hannibal2/skyhanni/data/PartyAPI.kt new file mode 100644 index 000000000..21f76998c --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/data/PartyAPI.kt @@ -0,0 +1,67 @@ +package at.hannibal2.skyhanni.data + +import at.hannibal2.skyhanni.events.LorenzChatEvent +import at.hannibal2.skyhanni.utils.StringUtils.cleanPlayerName +import at.hannibal2.skyhanni.utils.StringUtils.matchMatcher +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent + +class PartyAPI { + companion object { + val partyMembers = mutableListOf<String>() + } + + @SubscribeEvent + fun onChat(event: LorenzChatEvent) { + val message = event.message + // new member joined + "§eYou have joined §r(?<name>.*)'s §r§eparty!".toPattern().matchMatcher(message) { + val name = group("name").cleanPlayerName() + partyMembers.add(name) + println("partyMembers: $partyMembers") + } + "(?<name>.*) §r§ejoined the party.".toPattern().matchMatcher(message) { + val name = group("name").cleanPlayerName() + partyMembers.add(name) + println("partyMembers: $partyMembers") + } + "§eYou'll be partying with: §r(?<names>.*)".toPattern().matchMatcher(message) { + for (name in group("names").split(", ")) { + partyMembers.add(name.cleanPlayerName()) + } + println("partyMembers: $partyMembers") + } + + // one member got removed + "(?<name>.*) §r§ehas left the party.".toPattern().matchMatcher(message) { + val name = group("name").cleanPlayerName() + partyMembers.remove(name) + println("partyMembers: $partyMembers") + } + "(?<name>.*) §r§ehas been removed from the party.".toPattern().matchMatcher(message) { + val name = group("name").cleanPlayerName() + partyMembers.remove(name) + println("partyMembers: $partyMembers") + } + "(?<name>.*) neuberddo§r§e because they were offline.".toPattern().matchMatcher(message) { + val name = group("name").cleanPlayerName() + partyMembers.remove(name) + println("partyMembers: $partyMembers") + } + + // party disbanded + ".* §r§ehas disbanded the party!".toPattern().matchMatcher(message) { + partyMembers.clear() + println("partyMembers: $partyMembers") + } + "§eYou have been kicked from the party by §r.* §r§e".toPattern().matchMatcher(message) { + partyMembers.clear() + println("partyMembers: $partyMembers") + } + if (message == "§eYou left the party." || + message == "§cThe party was disbanded because all invites expired and the party was empty." + ) { + partyMembers.clear() + println("partyMembers: $partyMembers") + } + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/tabcomplete/PlayerTabComplete.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/tabcomplete/PlayerTabComplete.kt new file mode 100644 index 000000000..c20b64b7f --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/tabcomplete/PlayerTabComplete.kt @@ -0,0 +1,76 @@ +package at.hannibal2.skyhanni.features.misc.tabcomplete + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.data.FriendAPI +import at.hannibal2.skyhanni.data.PartyAPI +import at.hannibal2.skyhanni.utils.LorenzUtils + +object PlayerTabComplete { + private val config get() = SkyHanniMod.feature.misc.tabCompleteCommands + + enum class PlayerCategory { + PARTY, + FRIENDS, + ISLAND_PLAYERS, + } + + fun handleTabComplete(command: String, originalArray: Array<String>): List<String>? { + val commands = mapOf( + "p" to listOf(PlayerCategory.PARTY), + "party" to listOf(PlayerCategory.PARTY), + "pt" to listOf(PlayerCategory.FRIENDS, PlayerCategory.ISLAND_PLAYERS), // /party transfer + "f" to listOf(PlayerCategory.FRIENDS), + "friend" to listOf(PlayerCategory.FRIENDS), + + "msg" to listOf(), + "w" to listOf(), + "tell" to listOf(), + "boop" to listOf(), + + "visit" to listOf(), + "invite" to listOf(), + "ah" to listOf(), + + "pv" to listOf(), // NEU's Profile Viewer + "shmarkplayer" to listOf(), // SkyHanni's Mark Player + ) + val ignored = commands[command] ?: return null + + + return buildList { + + if (config.friends) { + if (PlayerCategory.FRIENDS !in ignored) { + FriendAPI.getAllFriends().filter { it.bestFriend || !config.onlyBestFriends } + .forEach { add(it.name) } + } + } + + if (config.islandPlayers) { + if (PlayerCategory.ISLAND_PLAYERS !in ignored) { + for (name in originalArray) { + if (name != LorenzUtils.getPlayerName()) { + add(name) + } + } + } + } + + if (config.party) { + if (PlayerCategory.PARTY !in ignored) { + for (member in PartyAPI.partyMembers) { + add(member) + } + } + + } + + if (config.vipVisits) { + if (command == "visit") { + add("prtlhub") + add("PortalHub") + } + } + } + } +}
\ No newline at end of file diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/tabcomplete/TabComplete.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/tabcomplete/TabComplete.kt new file mode 100644 index 000000000..69d24c4dc --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/tabcomplete/TabComplete.kt @@ -0,0 +1,34 @@ +package at.hannibal2.skyhanni.features.misc.tabcomplete + +object TabComplete { + + @JvmStatic + fun handleTabComplete(leftOfCursor: String, originalArray: Array<String>): Array<String>? { + val splits = leftOfCursor.split(" ") + if (splits.size > 1) { + var command = splits.first().lowercase() + if (command.startsWith("/")) { + command = command.substring(1) + customTabComplete(command, originalArray)?.let { + return buildResponse(splits, it).toTypedArray() + } + } + } + return null + } + + private fun customTabComplete(command: String, originalArray: Array<String>): List<String>? { + WarpTabComplete.handleTabComplete(command)?.let { return it } + PlayerTabComplete.handleTabComplete(command, originalArray)?.let { return it } + + return null + } + + private fun buildResponse(arguments: List<String>, fullResponse: List<String>): List<String> { + if (arguments.size == 2) { + val start = arguments[1].lowercase() + return fullResponse.filter { it.lowercase().startsWith(start) } + } + return emptyList() + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/tabcomplete/WarpTabComplete.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/tabcomplete/WarpTabComplete.kt new file mode 100644 index 000000000..cc948c86e --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/tabcomplete/WarpTabComplete.kt @@ -0,0 +1,26 @@ +package at.hannibal2.skyhanni.features.misc.tabcomplete + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.events.RepositoryReloadEvent +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.jsonobjects.WarpsJson +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent + +object WarpTabComplete { + private val config get() = SkyHanniMod.feature.misc.tabCompleteCommands + private var warpsJson: WarpsJson? = null + + @SubscribeEvent + fun onRepoReload(event: RepositoryReloadEvent) { + warpsJson = event.getConstant<WarpsJson>("Warps") + } + + fun handleTabComplete(command: String): List<String>? { + if (!isEnabled()) return null + if (command != "warp") return null + + return warpsJson?.warpCommands + } + + fun isEnabled() = LorenzUtils.inSkyBlock && config.warps +}
\ No newline at end of file diff --git a/src/main/java/at/hannibal2/skyhanni/mixins/transformers/MixinGuiChat.java b/src/main/java/at/hannibal2/skyhanni/mixins/transformers/MixinGuiChat.java new file mode 100644 index 000000000..87f01f792 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/mixins/transformers/MixinGuiChat.java @@ -0,0 +1,65 @@ +package at.hannibal2.skyhanni.mixins.transformers; + +import at.hannibal2.skyhanni.features.misc.tabcomplete.TabComplete; +import com.google.common.collect.Lists; +import net.minecraft.client.gui.GuiChat; +import net.minecraft.client.gui.GuiTextField; +import net.minecraft.util.EnumChatFormatting; +import org.apache.commons.lang3.StringUtils; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.List; + +@Mixin(GuiChat.class) +public class MixinGuiChat { + + @Shadow + protected GuiTextField inputField; + + @Shadow + private boolean waitingOnAutocomplete; + + @Shadow + private boolean playerNamesFound; + + @Shadow + private List<String> foundPlayerNames = Lists.newArrayList(); + + @Shadow + public void autocompletePlayerNames() { + + } + + @Inject(method = "onAutocompleteResponse", at = @At(value = "HEAD"), cancellable = true) + private void renderItemOverlayPost(String[] originalArray, CallbackInfo ci) { + + if (this.waitingOnAutocomplete) { + String[] result = TabComplete.handleTabComplete(this.inputField.getText(), originalArray); + if (result == null) return; + ci.cancel(); + + this.playerNamesFound = false; + this.foundPlayerNames.clear(); + for (String s : result) { + if (s.length() > 0) { + this.foundPlayerNames.add(s); + } + } + + String s1 = this.inputField.getText().substring(this.inputField.func_146197_a(-1, this.inputField.getCursorPosition(), false)); + String s2 = StringUtils.getCommonPrefix(result); + s2 = EnumChatFormatting.getTextWithoutFormattingCodes(s2); + if (s2.length() > 0 && !s1.equalsIgnoreCase(s2)) { + this.inputField.deleteFromCursor(this.inputField.func_146197_a(-1, this.inputField.getCursorPosition(), false) - this.inputField.getCursorPosition()); + this.inputField.writeText(s2); + } else if (this.foundPlayerNames.size() > 0) { + this.playerNamesFound = true; + this.autocompletePlayerNames(); + } + } + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/utils/jsonobjects/FriendsJson.java b/src/main/java/at/hannibal2/skyhanni/utils/jsonobjects/FriendsJson.java new file mode 100644 index 000000000..4eba238f6 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/utils/jsonobjects/FriendsJson.java @@ -0,0 +1,25 @@ +package at.hannibal2.skyhanni.utils.jsonobjects; + +import com.google.gson.annotations.Expose; + +import java.util.Map; +import java.util.UUID; + +public class FriendsJson { + + @Expose + public Map<UUID, PlayerFriends> players; + + public static class PlayerFriends { + + @Expose + public Map<UUID, Friend> friends; + + public static class Friend { + @Expose + public String name; + @Expose + public boolean bestFriend; + } + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/utils/jsonobjects/WarpsJson.java b/src/main/java/at/hannibal2/skyhanni/utils/jsonobjects/WarpsJson.java new file mode 100644 index 000000000..73ddb9fc6 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/utils/jsonobjects/WarpsJson.java @@ -0,0 +1,11 @@ +package at.hannibal2.skyhanni.utils.jsonobjects; + +import com.google.gson.annotations.Expose; + +import java.util.List; + +public class WarpsJson { + + @Expose + public List<String> warpCommands; +} |