diff --git a/src/main/kotlin/codes/som/hibiscus/Hibiscus.kt b/src/main/kotlin/codes/som/hibiscus/Hibiscus.kt index 8233b3d..069455a 100644 --- a/src/main/kotlin/codes/som/hibiscus/Hibiscus.kt +++ b/src/main/kotlin/codes/som/hibiscus/Hibiscus.kt @@ -13,6 +13,8 @@ import codes.som.hibiscus.features.player.NoFallDamage import codes.som.hibiscus.features.player.NoSprintingPacket import codes.som.hibiscus.gui.screens.AccountManagerUIScreen import codes.som.hibiscus.gui.screens.InGameClientUIScreen +import codes.som.hibiscus.mixins.MixinExtMinecraftClient +import codes.som.hibiscus.subsystems.accounts.AccountsSubsystem import codes.som.hibiscus.util.command.ChatCommandListener import codes.som.hibiscus.util.input.KeybindDispatcher import codes.som.hibiscus.util.netmoving.NetworkMovingDispatcher @@ -56,6 +58,18 @@ object Hibiscus : ModInitializer { bus.register(KeybindDispatcher()) defaultConfig() + + AccountsSubsystem.reload() + if (mc.session.accessToken == "FabricMC") { // Launched from IDE + try { + AccountsSubsystem.getAccounts().firstOrNull()?.let { account -> + AccountsSubsystem.signIn(account) + ?.let(AccountsSubsystem::createSession) + ?.let((mc as MixinExtMinecraftClient)::setSession) + } + } catch (_: Exception) { + } + } } fun shutdown() { diff --git a/src/main/kotlin/codes/som/hibiscus/gui/screens/AccountManagerUIScreen.kt b/src/main/kotlin/codes/som/hibiscus/gui/screens/AccountManagerUIScreen.kt index 501b20c..674598e 100644 --- a/src/main/kotlin/codes/som/hibiscus/gui/screens/AccountManagerUIScreen.kt +++ b/src/main/kotlin/codes/som/hibiscus/gui/screens/AccountManagerUIScreen.kt @@ -1,8 +1,8 @@ package codes.som.hibiscus.gui.screens -import codes.som.hibiscus.Hibiscus -import codes.som.hibiscus.data.MinecraftAccount +import codes.som.hibiscus.mc import codes.som.hibiscus.mixins.MixinExtMinecraftClient +import codes.som.hibiscus.subsystems.accounts.AccountsSubsystem import imgui.ImGui import imgui.flag.ImGuiInputTextFlags import imgui.flag.ImGuiWindowFlags @@ -10,30 +10,14 @@ import imgui.type.ImBoolean import imgui.type.ImInt import imgui.type.ImString import net.hycrafthd.minecraft_authenticator.login.Authenticator -import net.hycrafthd.minecraft_authenticator.login.User -import net.hycrafthd.minecraft_authenticator.login.file.AuthenticationFile import net.minecraft.client.gui.screen.Screen -import net.minecraft.client.util.Session import net.minecraft.client.util.math.MatrixStack import net.minecraft.text.Text -import java.io.ByteArrayOutputStream -import java.util.* object AccountManagerUIScreen : Screen(Text.of("account management hacker menu")) { - private var accounts = emptyList() private val createAccountPanelOpen = ImBoolean(false) private var selectedAccountId = -1 - init { - refreshAccounts() - } - - private fun refreshAccounts() { - this.accounts = Hibiscus.data.txn { - MinecraftAccount.all().toList() - } - } - override fun render(matrices: MatrixStack?, mouseX: Int, mouseY: Int, delta: Float) { renderBackground(matrices) @@ -42,13 +26,16 @@ object AccountManagerUIScreen : Screen(Text.of("account management hacker menu") } private fun drawAccountsPanel() { + val accounts = AccountsSubsystem.getAccounts().toList() + if (ImGui.begin("Accounts", ImGuiWindowFlags.AlwaysAutoResize)) { ImGui.text("Available accounts: ${accounts.size}") - ImGui.text("Logged in as: ${client!!.session.username}") + ImGui.text("Logged in as: ${mc.session.username}") if (ImGui.button("Add Account")) { createAccountPanelOpen.set(true) } + ImGui.sameLine() if (ImGui.button("Random")) { selectedAccountId = accounts @@ -70,11 +57,18 @@ object AccountManagerUIScreen : Screen(Text.of("account management hacker menu") accounts.firstOrNull { it.id.value == selectedAccountId }?.let { account -> if (ImGui.button("Log In")) { - signInToAccount(account) + try { + val user = AccountsSubsystem.signIn(account) + if (user != null) { + (mc as MixinExtMinecraftClient).setSession(AccountsSubsystem.createSession(user)) + } + } catch (e: Exception) { + e.printStackTrace() + } } ImGui.sameLine() if (ImGui.button("Remove")) { - removeAccount(account) + AccountsSubsystem.deleteAccount(account) } ImGui.text("Selected account: ${account.name}") @@ -86,36 +80,6 @@ object AccountManagerUIScreen : Screen(Text.of("account management hacker menu") ImGui.end() } - private fun signInToAccount(account: MinecraftAccount) { - try { - val loginFile = AuthenticationFile.read(account.loginData.byteInputStream(Charsets.UTF_8)) - val loginResult = Authenticator.of(loginFile).shouldAuthenticate().run() - if (loginResult.user.isPresent) { - val user = loginResult.user.get() - (client!! as MixinExtMinecraftClient).setSession(user.createSession()) - - val loginData = ByteArrayOutputStream() - .apply { loginResult.resultFile.write(this) } - .toString(Charsets.UTF_8) - - Hibiscus.data.txn { - account.lastKnownDisplayName = user.name - account.loginData = loginData - refreshAccounts() - } - } - } catch (e: Exception) { - e.printStackTrace() - } - } - - private fun removeAccount(account: MinecraftAccount) { - Hibiscus.data.txn { - account.delete() - refreshAccounts() - } - } - private val loginType = ImInt(1) private val yggdrasilUsername = ImString(320) private val yggdrasilPassword = ImString(256) @@ -161,35 +125,13 @@ object AccountManagerUIScreen : Screen(Text.of("account management hacker menu") 0 -> Authenticator.ofYggdrasil("-", yggdrasilUsername.get(), yggdrasilPassword.get()) 1 -> Authenticator.ofMicrosoft(microsoftToken.get()) else -> throw IllegalStateException() - }.shouldAuthenticate() + } - try { - val loginResult = authenticator.run() - if (loginResult.user.isPresent) { - val user = loginResult.user.get() - - yggdrasilUsername.set("") - yggdrasilPassword.set("") - microsoftToken.set("") - - val loginData = ByteArrayOutputStream() - .apply { loginResult.resultFile.write(this) } - .toString(Charsets.UTF_8) - - Hibiscus.data.txn { - MinecraftAccount.new { - this.name = user.name - this.lastKnownDisplayName = user.name - this.loginData = loginData - } - - refreshAccounts() - - (client!! as MixinExtMinecraftClient).setSession(user.createSession()) - } + if (AccountsSubsystem.addAccount(authenticator)) { + sequenceOf(yggdrasilUsername, yggdrasilPassword, microsoftToken).forEach { + it.set("") } - } catch (e: Exception) { - e.printStackTrace() + } else { // TODO: Display some error } } @@ -197,13 +139,4 @@ object AccountManagerUIScreen : Screen(Text.of("account management hacker menu") ImGui.end() } } - - private fun User.createSession() = Session( - name, - uuid, - accessToken, - Optional.empty(), - Optional.empty(), - Session.AccountType.byName(type) - ) } diff --git a/src/main/kotlin/codes/som/hibiscus/subsystems/accounts/AccountsSubsystem.kt b/src/main/kotlin/codes/som/hibiscus/subsystems/accounts/AccountsSubsystem.kt new file mode 100644 index 0000000..831f00c --- /dev/null +++ b/src/main/kotlin/codes/som/hibiscus/subsystems/accounts/AccountsSubsystem.kt @@ -0,0 +1,95 @@ +package codes.som.hibiscus.subsystems.accounts + +import codes.som.hibiscus.Hibiscus +import codes.som.hibiscus.data.MinecraftAccount +import codes.som.hibiscus.mc +import codes.som.hibiscus.mixins.MixinExtMinecraftClient +import net.hycrafthd.minecraft_authenticator.login.Authenticator +import net.hycrafthd.minecraft_authenticator.login.User +import net.hycrafthd.minecraft_authenticator.login.file.AuthenticationFile +import net.minecraft.client.util.Session +import java.io.ByteArrayOutputStream +import java.util.* + +object AccountsSubsystem { + private var accounts = emptyList() + + fun getAccounts(): Sequence = accounts.asSequence() + + fun addAccount(authenticator: Authenticator.Builder): Boolean { + try { + val loginResult = authenticator.shouldAuthenticate().run() + if (loginResult.user.isPresent) { + val user = loginResult.user.get() + + val loginData = ByteArrayOutputStream() + .apply { loginResult.resultFile.write(this) } + .toString(Charsets.UTF_8) + + Hibiscus.data.txn { + val account = MinecraftAccount.new { + this.name = user.name + this.lastKnownDisplayName = user.name + this.loginData = loginData + } + accounts = accounts + account + + (mc as MixinExtMinecraftClient).setSession(createSession(user)) + } + + return true + } + } catch (e: Exception) { + e.printStackTrace() + } + + return false + } + + fun deleteAccount(account: MinecraftAccount) { + val id = account.id.value + accounts = accounts.filter { it.id.value == id } + account.delete() + } + + fun reload() { + this.accounts = Hibiscus.data.txn { + MinecraftAccount.all().toList() + } + } + + fun signIn(account: MinecraftAccount): User? { + try { + val loginFile = AuthenticationFile.read(account.loginData.byteInputStream(Charsets.UTF_8)) + val loginResult = Authenticator.of(loginFile).shouldAuthenticate().run() + if (loginResult.user.isPresent) { + val user = loginResult.user.get() + + val loginData = ByteArrayOutputStream() + .apply { loginResult.resultFile.write(this) } + .toString(Charsets.UTF_8) + + Hibiscus.data.txn { + account.lastKnownDisplayName = user.name + account.loginData = loginData + } + + return user + } + } catch (_: Exception) { + } + + return null + } + + fun createSession(user: User) = with(user) { + Session( + name, + uuid, + accessToken, + Optional.empty(), + Optional.empty(), + Session.AccountType.byName(type) + ) + } +}