aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/at/hannibal2/skyhanni
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/at/hannibal2/skyhanni')
-rw-r--r--src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt4
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/Misc.java38
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/FriendAPI.kt144
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/PartyAPI.kt67
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/tabcomplete/PlayerTabComplete.kt76
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/tabcomplete/TabComplete.kt34
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/tabcomplete/WarpTabComplete.kt26
-rw-r--r--src/main/java/at/hannibal2/skyhanni/mixins/transformers/MixinGuiChat.java65
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/jsonobjects/FriendsJson.java25
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/jsonobjects/WarpsJson.java11
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;
+}