Add SQLite-based data storage system & account manager

You can access the account manager by pressing right-shift from the
title screen
This commit is contained in:
Charlotte Som 2022-03-07 23:34:22 +00:00
parent a1cff649dd
commit f96a4fc83d
31 changed files with 387 additions and 82 deletions

View file

@ -19,7 +19,9 @@ version = modVersion
val mavenGroup: String by project
group = mavenGroup
repositories {}
repositories {
mavenCentral()
}
dependencies {
val minecraftVersion: String by project
@ -52,7 +54,12 @@ dependencies {
implementation(files("vendor/libs/lwjgl-util.jar"))
implementation(files("vendor/libs/minecraft_authenticator-2.0.1.jar"))
runtimeOnly("org.joml:joml:1.10.2")
implementation("org.jetbrains.exposed:exposed-core:0.37.3")
implementation("org.jetbrains.exposed:exposed-dao:0.37.3")
implementation("org.jetbrains.exposed:exposed-jdbc:0.37.3")
runtimeOnly("org.xerial:sqlite-jdbc:3.36.0.3")
runtimeOnly("org.joml:joml:1.10.4")
runtimeOnly("org.anarres:jcpp:1.4.14")
modImplementation(files("vendor/mods/baritone-unoptimized-fabric-1.8.2.jar"))

View file

@ -1,6 +1,6 @@
package codes.som.hibiscus.mixins;
import codes.som.hibiscus.HibiscusMod;
import codes.som.hibiscus.Hibiscus;
import codes.som.hibiscus.events.ReceivePacketEvent;
import net.minecraft.network.ClientConnection;
import net.minecraft.network.Packet;
@ -15,7 +15,7 @@ public abstract class MixinClientConnection {
@Inject(method = "handlePacket", at = @At("HEAD"), cancellable = true)
private static <T extends PacketListener> void onHandlePacket(Packet<T> packet, PacketListener listener, CallbackInfo ci) {
var event = new ReceivePacketEvent(packet);
HibiscusMod.bus().fire(event);
Hibiscus.bus().fire(event);
if (event.isCancelled())
ci.cancel();
}

View file

@ -1,6 +1,6 @@
package codes.som.hibiscus.mixins;
import codes.som.hibiscus.HibiscusMod;
import codes.som.hibiscus.Hibiscus;
import codes.som.hibiscus.events.SendPacketEvent;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.network.ClientConnection;
@ -14,7 +14,7 @@ public abstract class MixinClientPlayNetworkHandler {
@Redirect(method = "sendPacket", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/ClientConnection;send(Lnet/minecraft/network/Packet;)V"))
public void onSendPacket(ClientConnection clientConnection, Packet<?> packet) {
var event = new SendPacketEvent(packet);
HibiscusMod.bus().fire(event);
Hibiscus.bus().fire(event);
if (!event.isCancelled()) {
clientConnection.send(event.getPacket());
}

View file

@ -1,6 +1,6 @@
package codes.som.hibiscus.mixins;
import codes.som.hibiscus.HibiscusMod;
import codes.som.hibiscus.Hibiscus;
import codes.som.hibiscus.events.MovePlayerEvent;
import codes.som.hibiscus.events.PlayerPreTickEvent;
import codes.som.hibiscus.events.PlayerTickEvent;
@ -19,18 +19,18 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
public abstract class MixinClientPlayerEntity {
@Inject(method = "tick", at = @At("HEAD"))
private void onPreTick(CallbackInfo ci) {
HibiscusMod.bus().fire(PlayerPreTickEvent.INSTANCE);
Hibiscus.bus().fire(PlayerPreTickEvent.INSTANCE);
}
@Inject(method = "tick", at = @At("RETURN"))
private void onPostTick(CallbackInfo ci) {
HibiscusMod.bus().fire(PlayerTickEvent.INSTANCE);
Hibiscus.bus().fire(PlayerTickEvent.INSTANCE);
}
@Inject(method = "sendChatMessage", at = @At("HEAD"), cancellable = true)
private void onChatMessage(String message, CallbackInfo ci) {
var event = new SendChatEvent(message);
HibiscusMod.bus().fire(event);
Hibiscus.bus().fire(event);
if (event.isCancelled())
ci.cancel();
}
@ -46,7 +46,7 @@ public abstract class MixinClientPlayerEntity {
@ModifyVariable(method = "move", at = @At(value = "HEAD", shift = At.Shift.AFTER), argsOnly = true)
private Vec3d onMovePlayer(Vec3d movement) {
var event = new MovePlayerEvent(movement.x, movement.y, movement.z, this.movementType);
HibiscusMod.bus().fire(event);
Hibiscus.bus().fire(event);
return new Vec3d(event.getX(), event.getY(), event.getZ());
}
}

View file

@ -0,0 +1,14 @@
package codes.som.hibiscus.mixins;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.util.Session;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.gen.Accessor;
@Mixin(MinecraftClient.class)
public interface MixinExtMinecraftClient {
@Accessor
@Mutable
void setSession(Session session);
}

View file

@ -1,6 +1,6 @@
package codes.som.hibiscus.mixins;
import codes.som.hibiscus.HibiscusMod;
import codes.som.hibiscus.Hibiscus;
import codes.som.hibiscus.events.Render3DEvent;
import codes.som.hibiscus.events.RenderHandEvent;
import codes.som.hibiscus.util.graphics.MinecraftRenderPipelineProgress;
@ -44,7 +44,7 @@ public abstract class MixinGameRenderer {
matrices.push();
RenderSystem.applyModelViewMatrix();
HibiscusMod.bus().fire(new Render3DEvent(tickDelta, this.camera, matrices));
Hibiscus.bus().fire(new Render3DEvent(tickDelta, this.camera, matrices));
matrices.pop();
}
@ -68,7 +68,7 @@ public abstract class MixinGameRenderer {
@Inject(method = "renderHand", at = @At("HEAD"), cancellable = true)
private void onRenderHand(MatrixStack matrices, Camera camera, float tickDelta, CallbackInfo ci) {
var event = new RenderHandEvent(tickDelta);
HibiscusMod.bus().fire(event);
Hibiscus.bus().fire(event);
if (event.isCancelled())
ci.cancel();
}

View file

@ -1,6 +1,6 @@
package codes.som.hibiscus.mixins;
import codes.som.hibiscus.HibiscusMod;
import codes.som.hibiscus.Hibiscus;
import codes.som.hibiscus.events.CharEvent;
import codes.som.hibiscus.events.KeyEvent;
import net.minecraft.client.Keyboard;
@ -23,7 +23,7 @@ public abstract class MixinKeyboard {
if (window != this.client.getWindow().getHandle())
return; // Just in case
HibiscusMod.bus().fire(new KeyEvent(key, action));
Hibiscus.bus().fire(new KeyEvent(key, action));
}
@Inject(method = "onChar", at = @At("HEAD"))
@ -31,6 +31,6 @@ public abstract class MixinKeyboard {
if (window != this.client.getWindow().getHandle())
return;
HibiscusMod.bus().fire(new CharEvent((char) character));
Hibiscus.bus().fire(new CharEvent((char) character));
}
}

View file

@ -1,6 +1,6 @@
package codes.som.hibiscus.mixins;
import codes.som.hibiscus.HibiscusMod;
import codes.som.hibiscus.Hibiscus;
import codes.som.hibiscus.events.GetRenderViewEntityEvent;
import codes.som.hibiscus.events.PostRenderAllEvent;
import codes.som.hibiscus.gui.ImGuiRenderer;
@ -43,7 +43,7 @@ public abstract class MixinMinecraftClient {
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gl/Framebuffer;endWrite()V", shift = At.Shift.BEFORE))
private void onPostRenderEverything(boolean tick, CallbackInfo ci) {
float delta = this.paused ? this.pausedTickDelta : this.renderTickCounter.tickDelta;
HibiscusMod.bus().fire(new PostRenderAllEvent(delta));
Hibiscus.bus().fire(new PostRenderAllEvent(delta));
ImGuiRenderer.INSTANCE.finishFrame(delta);
}
@ -53,7 +53,7 @@ public abstract class MixinMinecraftClient {
if (view != null) {
var event = new GetRenderViewEntityEvent(view);
HibiscusMod.bus().fire(event);
Hibiscus.bus().fire(event);
cir.setReturnValue(event.getViewEntity());
}
}

View file

@ -1,6 +1,6 @@
package codes.som.hibiscus.mixins;
import codes.som.hibiscus.HibiscusMod;
import codes.som.hibiscus.Hibiscus;
import codes.som.hibiscus.events.WorldCullingEvent;
import me.jellysquid.mods.sodium.client.render.chunk.RenderSectionManager;
import net.minecraft.client.MinecraftClient;
@ -13,7 +13,7 @@ public abstract class MixinRenderSectionManager {
@Redirect(method = "initSearch", at = @At(value = "FIELD", target = "Lnet/minecraft/client/MinecraftClient;chunkCullingEnabled:Z"))
public boolean cancelCulling(MinecraftClient client) {
var event = new WorldCullingEvent();
HibiscusMod.bus().fire(event);
Hibiscus.bus().fire(event);
return client.chunkCullingEnabled && !event.isCancelled();
}
}

View file

@ -1,6 +1,6 @@
package codes.som.hibiscus.mixins;
import codes.som.hibiscus.HibiscusMod;
import codes.som.hibiscus.Hibiscus;
import codes.som.hibiscus.events.PostRenderEntitiesEvent;
import codes.som.hibiscus.events.PostRenderWorldEvent;
import codes.som.hibiscus.events.PreRenderEntitiesEvent;
@ -21,12 +21,12 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
public abstract class MixinWorldRenderer {
@Inject(method = "render", at = @At("HEAD"))
private void onPreRenderWorld(MatrixStack matrices, float tickDelta, long limitTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightmapTextureManager lightmapTextureManager, Matrix4f matrix4f, CallbackInfo ci) {
HibiscusMod.bus().fire(new PreRenderWorldEvent(tickDelta, camera, matrices));
Hibiscus.bus().fire(new PreRenderWorldEvent(tickDelta, camera, matrices));
}
@Inject(method = "render", at = @At("HEAD"))
private void onPostRenderWorld(MatrixStack matrices, float tickDelta, long limitTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightmapTextureManager lightmapTextureManager, Matrix4f matrix4f, CallbackInfo ci) {
HibiscusMod.bus().fire(new PostRenderWorldEvent(tickDelta, camera, matrices));
Hibiscus.bus().fire(new PostRenderWorldEvent(tickDelta, camera, matrices));
}
/* Obsoleted by Sodium-compatible MixinRenderSectionManager
@ -40,12 +40,12 @@ public abstract class MixinWorldRenderer {
@Inject(method = "render", at = @At(value = "INVOKE_STRING", target = "Lnet/minecraft/util/profiler/Profiler;swap(Ljava/lang/String;)V", args = "ldc=entities"))
private void startRenderEntities(MatrixStack matrices, float tickDelta, long limitTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightmapTextureManager lightmapTextureManager, Matrix4f matrix4f, CallbackInfo ci) {
MinecraftRenderPipelineProgress.INSTANCE.setRenderingEntities(true);
HibiscusMod.bus().fire(new PreRenderEntitiesEvent(tickDelta));
Hibiscus.bus().fire(new PreRenderEntitiesEvent(tickDelta));
}
@Inject(method = "render", at = @At(value = "INVOKE_STRING", target = "Lnet/minecraft/util/profiler/Profiler;swap(Ljava/lang/String;)V", args = "ldc=blockentities"))
private void startRenderBlockEntities(MatrixStack matrices, float tickDelta, long limitTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightmapTextureManager lightmapTextureManager, Matrix4f matrix4f, CallbackInfo ci) {
MinecraftRenderPipelineProgress.INSTANCE.setRenderingEntities(false);
HibiscusMod.bus().fire(new PostRenderEntitiesEvent(tickDelta));
Hibiscus.bus().fire(new PostRenderEntitiesEvent(tickDelta));
}
}

View file

@ -4,22 +4,25 @@ import codes.som.hibiscus.api.event.EventBus
import codes.som.hibiscus.api.event.EventPhase
import codes.som.hibiscus.api.keybinds.KeybindRegistry
import codes.som.hibiscus.commands.CommandRegistry
import codes.som.hibiscus.data.DataManager
import codes.som.hibiscus.events.KeyEvent
import codes.som.hibiscus.features.FeaturesRegistry
import codes.som.hibiscus.features.combat.Criticals
import codes.som.hibiscus.features.exploits.AntiGhost
import codes.som.hibiscus.features.player.NoFallDamage
import codes.som.hibiscus.features.player.NoSprintingPacket
import codes.som.hibiscus.gui.ImGuiScreen
import codes.som.hibiscus.gui.screens.AccountManagerUIScreen
import codes.som.hibiscus.gui.screens.InGameClientUIScreen
import codes.som.hibiscus.util.command.ChatCommandListener
import codes.som.hibiscus.util.input.KeybindDispatcher
import codes.som.hibiscus.util.netmoving.NetworkMovingDispatcher
import net.fabricmc.api.ModInitializer
import net.minecraft.client.gui.screen.TitleScreen
import org.lwjgl.glfw.GLFW
import org.lwjgl.glfw.GLFW.*
@Suppress("UNUSED")
object HibiscusMod : ModInitializer {
object Hibiscus : ModInitializer {
private const val MOD_ID = "hibiscus_client"
@JvmStatic
@ -29,8 +32,11 @@ object HibiscusMod : ModInitializer {
val features = FeaturesRegistry()
val commands = CommandRegistry()
val keybinds = KeybindRegistry()
val data = DataManager()
override fun onInitialize() {
data.runMigrations()
for (feature in features.getAllFeatures()) {
commands.register(feature.createFeatureCommand())
}
@ -39,10 +45,10 @@ object HibiscusMod : ModInitializer {
if (event.key != GLFW_KEY_RIGHT_SHIFT || event.action != GLFW.GLFW_PRESS)
return@register
if (mc.currentScreen != null)
return@register
mc.setScreen(ImGuiScreen)
when (mc.currentScreen) {
null -> mc.setScreen(InGameClientUIScreen)
is TitleScreen -> mc.setScreen(AccountManagerUIScreen)
}
}
bus.register(NetworkMovingDispatcher(), EventPhase.AFTER)
@ -50,12 +56,9 @@ object HibiscusMod : ModInitializer {
bus.register(KeybindDispatcher())
defaultConfig()
// TODO: Load files
}
fun shutdown() {
// TODO: Save files
for (system in sequenceOf(bus, features, commands, keybinds)) {
system.reset()
}

View file

@ -1,6 +1,6 @@
package codes.som.hibiscus.api.feature
import codes.som.hibiscus.HibiscusMod
import codes.som.hibiscus.Hibiscus
import codes.som.hibiscus.api.command.Command
import codes.som.hibiscus.api.event.*
import codes.som.hibiscus.api.feature.values.ValueRegistry
@ -23,9 +23,9 @@ abstract class Feature(val name: String, val category: FeatureCategory) {
field = value
if (value) {
onEnable()
listeners.forEach { HibiscusMod.bus.registerTyped(it) }
listeners.forEach { Hibiscus.bus.registerTyped(it) }
} else {
listeners.forEach { HibiscusMod.bus.unregisterTyped(it) }
listeners.forEach { Hibiscus.bus.unregisterTyped(it) }
onDisable()
}
}

View file

@ -1,7 +1,7 @@
package codes.som.hibiscus.api.feature
import codes.som.hibiscus.HibiscusLog
import codes.som.hibiscus.HibiscusMod
import codes.som.hibiscus.Hibiscus
import codes.som.hibiscus.api.command.Command
import codes.som.hibiscus.api.command.CommandContext
import java.util.*
@ -11,7 +11,7 @@ class FeatureCommand(feature: Feature) : Command(feature.name.replace(" ", "").l
branch {
feature.enabled = !feature.enabled
if (HibiscusMod.commands.context == CommandContext.MANUAL) {
if (Hibiscus.commands.context == CommandContext.MANUAL) {
val state = if (feature.enabled) "enabled" else "disabled"
HibiscusLog.info("${feature.name} is now $state.")
}

View file

@ -1,13 +1,13 @@
package codes.som.hibiscus.commands
import codes.som.hibiscus.HibiscusMod
import codes.som.hibiscus.Hibiscus
import codes.som.hibiscus.api.command.Command
class Reload : Command("reload") {
init {
branch {
HibiscusMod.shutdown()
HibiscusMod.onInitialize()
Hibiscus.shutdown()
Hibiscus.onInitialize()
}
}
}

View file

@ -0,0 +1,20 @@
package codes.som.hibiscus.data
import org.jetbrains.exposed.dao.IntEntity
import org.jetbrains.exposed.dao.IntEntityClass
import org.jetbrains.exposed.dao.id.EntityID
import org.jetbrains.exposed.dao.id.IntIdTable
object MinecraftAccounts : IntIdTable("mc_accounts") {
val name = varchar("name", 64)
val lastKnownDisplayName = varchar("last_display_name", 32).nullable()
val loginData = text("login_data", eagerLoading = true)
}
class MinecraftAccount(id: EntityID<Int>) : IntEntity(id) {
companion object : IntEntityClass<MinecraftAccount>(MinecraftAccounts)
var name by MinecraftAccounts.name
var lastKnownDisplayName by MinecraftAccounts.lastKnownDisplayName
var loginData by MinecraftAccounts.loginData
}

View file

@ -0,0 +1,55 @@
package codes.som.hibiscus.data
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.transactions.TransactionManager
import org.jetbrains.exposed.sql.transactions.transaction
import java.nio.file.Files
import java.nio.file.Paths
import java.sql.Connection
import java.sql.SQLException
class DataManager {
private val db: Database = Database.connect("jdbc:sqlite:${getDatabaseLocation()}").also {
TransactionManager.manager.defaultIsolationLevel = Connection.TRANSACTION_SERIALIZABLE
}
fun runMigrations() {
val latestId = try {
txn {
HibiscusDataMigrations.selectAll().orderBy(
HibiscusDataMigrations.id,
SortOrder.DESC
).limit(1).lastOrNull()?.get(HibiscusDataMigrations.id)?.value
}
} catch (e: SQLException) {
null
} ?: -1
txn {
for ((idx, migration) in HIBISCUS_MIGRATIONS().withIndex()) {
if (idx <= latestId)
continue
migration(this)
HibiscusDataMigrations.insert { it[id] = idx }
}
}
}
private fun getDatabaseLocation(): String {
val osName = System.getProperty("os.name")
val databasePath = when {
osName.contains("Windows") -> {
Paths.get(System.getenv("APPDATA"), "hibiscus-client", "hibiscus-client.db")
}
else -> {
Paths.get(System.getProperty("user.home"), ".config", "hibiscus-client", "hibiscus-client.db")
}
}
Files.createDirectories(databasePath.parent)
return databasePath.toString()
}
fun <T> txn(stmnt: Transaction.() -> T) = transaction(db, stmnt)
}

View file

@ -0,0 +1,13 @@
package codes.som.hibiscus.data
import org.jetbrains.exposed.dao.id.IntIdTable
import org.jetbrains.exposed.sql.SchemaUtils
import org.jetbrains.exposed.sql.Transaction
object HibiscusDataMigrations : IntIdTable("_hibiscus_migrations")
@Suppress("FunctionName")
fun HIBISCUS_MIGRATIONS(): Sequence<Transaction.() -> Unit> = sequenceOf(
{ SchemaUtils.create(HibiscusDataMigrations) },
{ SchemaUtils.create(MinecraftAccounts) }
)

View file

@ -15,7 +15,8 @@ import codes.som.hibiscus.features.visual.Fullbright
import codes.som.hibiscus.features.visual.Xray
import codes.som.hibiscus.util.Resettable
fun allFeatureClasses(): Array<() -> Feature> = arrayOf(
@Suppress("FunctionName")
fun FEATURE_CONSTRUCTORS(): Array<() -> Feature> = arrayOf(
::NoFallDamage,
::Flight,
::Overlay,
@ -46,7 +47,7 @@ class FeaturesRegistry : Resettable {
getAllFeatures().first { it.javaClass == type } as T
private fun registerFeatures() {
features.addAll(allFeatureClasses().map { it() })
features.addAll(FEATURE_CONSTRUCTORS().map { it() })
}
override fun reset() {

View file

@ -1,6 +1,6 @@
package codes.som.hibiscus.features.overlay
import codes.som.hibiscus.HibiscusMod
import codes.som.hibiscus.Hibiscus
import codes.som.hibiscus.api.feature.Feature
import codes.som.hibiscus.api.feature.FeatureCategory
import codes.som.hibiscus.events.PostRenderAllEvent
@ -40,7 +40,7 @@ class Overlay : Feature("Overlay", FeatureCategory.OVERLAY) {
private fun drawEnabledFeatures() {
val displayedFeatures =
HibiscusMod.features.getAllFeatures()
Hibiscus.features.getAllFeatures()
.filter { !it.hiddenInOverlay }
.filter { it.enabled }.toList()

View file

@ -1,6 +1,6 @@
package codes.som.hibiscus.features.visual
import codes.som.hibiscus.HibiscusMod
import codes.som.hibiscus.Hibiscus
import codes.som.hibiscus.api.feature.Feature
import codes.som.hibiscus.api.feature.FeatureCategory
import codes.som.hibiscus.events.*
@ -131,7 +131,7 @@ class Freecam : Feature("Freecam", FeatureCategory.VISUAL) {
var lastMouseY = 0.0
var mouseDeltaX = 0.0
var mouseDeltaY = 0.0
HibiscusMod.bus.register { _: PostRenderWorldEvent ->
Hibiscus.bus.register { _: PostRenderWorldEvent ->
mouseDeltaX = mc.mouse.x - lastMouseX
mouseDeltaY = mc.mouse.y - lastMouseY
lastMouseX = mc.mouse.x

View file

@ -1,6 +1,6 @@
package codes.som.hibiscus.gui
import codes.som.hibiscus.HibiscusMod
import codes.som.hibiscus.Hibiscus
import codes.som.hibiscus.api.feature.Feature
import codes.som.hibiscus.api.feature.FeatureCategory
import codes.som.hibiscus.features.overlay.Overlay
@ -11,13 +11,13 @@ import imgui.flag.ImGuiWindowFlags
import imgui.flag.ImGuiWindowFlags.AlwaysVerticalScrollbar
import imgui.type.ImBoolean
object ModuleControlsUI {
object FeatureControlsUI {
private val moduleValueWindows = mutableMapOf<Feature, ImBoolean>()
private fun drawCategoryPanel(category: FeatureCategory, ) {
private fun drawCategoryPanel(category: FeatureCategory) {
ImGui.begin(category.humanName, AlwaysVerticalScrollbar)
for (feature in HibiscusMod.features.getAllFeatures().filter { it.category == category }) {
for (feature in Hibiscus.features.getAllFeatures().filter { it.category == category }) {
drawFeatureControls(feature)
}
@ -63,34 +63,34 @@ object ModuleControlsUI {
}
}
}
private fun drawOverlaySettings() {
val overlayFeature = HibiscusMod.features.getFeature<Overlay>()
val overlayFeature = Hibiscus.features.getFeature<Overlay>()
if (ImGui.begin("${overlayFeature.name}##Feature Controls"))
for (value in overlayFeature.values)
value.drawUIControl()
ImGui.end()
}
fun render(delta: Float) {
var yOffset = 0f
fun pushInitialPanelConfig() {
val initialX = ImGui.getMainViewport().posX + 10f
val initialY = ImGui.getMainViewport().posY + 10f + yOffset
ImGui.setNextWindowPos(initialX, initialY, Once)
ImGui.setNextWindowCollapsed(true, Once)
ImGui.setNextWindowSize(300f, 0f, Once)
}
for (category in FeatureCategory.values()) {
if (category == FeatureCategory.OVERLAY)
continue
pushInitialPanelConfig()
drawCategoryPanel(category)
yOffset += 30f
}

View file

@ -1,6 +1,6 @@
package codes.som.hibiscus.gui
import codes.som.hibiscus.HibiscusMod
import codes.som.hibiscus.Hibiscus
import imgui.ImFontConfig
import imgui.ImGui
import imgui.ImGuiStyle
@ -83,7 +83,7 @@ fun applyHibiscusImGuiTheme() {
style.setColor(ImGuiCol.TabUnfocusedActive, colMed(1.0f))
with(ImGui.getIO().fonts) {
val interTTF = HibiscusMod.javaClass.getResourceAsStream("/assets/inter/Inter-V.ttf")
val interTTF = Hibiscus.javaClass.getResourceAsStream("/assets/inter/Inter-V.ttf")
?: error("Couldn't find Inter TTF in assets!")
addFontFromMemoryTTF(interTTF.readAllBytes(), 20f, ImFontConfig().apply {
setName("Inter")

View file

@ -0,0 +1,190 @@
package codes.som.hibiscus.gui.screens
import codes.som.hibiscus.Hibiscus
import codes.som.hibiscus.data.MinecraftAccount
import codes.som.hibiscus.mixins.MixinExtMinecraftClient
import imgui.ImGui
import imgui.flag.ImGuiInputTextFlags
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<MinecraftAccount>()
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)
if (ImGui.begin("Accounts")) {
ImGui.text("Available accounts: ${accounts.size}")
ImGui.text("Logged in as: ${client!!.session.username}")
if (ImGui.button("Add Account")) {
createAccountPanelOpen.set(true)
}
val calculatedHeight = (accounts.size.coerceIn(4, 20) * 28f)
if (ImGui.beginListBox("Accounts", 0f, calculatedHeight)) {
for (account in accounts) {
if (ImGui.selectable(account.name, account.id.value == selectedAccountId)) {
selectedAccountId = account.id.value
}
}
ImGui.endListBox()
}
accounts.firstOrNull { it.id.value == selectedAccountId }?.let { account ->
ImGui.text("Selected account: ${account.name}")
ImGui.text("Last known username: ${account.lastKnownDisplayName}")
if (ImGui.button("Log In")) {
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()
}
}
ImGui.sameLine()
if (ImGui.button("Remove")) {
// TODO: Some confirmation modal
Hibiscus.data.txn {
account.delete()
refreshAccounts()
}
}
}
}
ImGui.end()
drawCreateAccountPanel()
}
private val loginType = ImInt(1)
private val yggdrasilUsername = ImString(320)
private val yggdrasilPassword = ImString(256)
private val microsoftToken = ImString(256)
private fun drawCreateAccountPanel() {
if (createAccountPanelOpen.get()) {
if (ImGui.begin("Add Account", createAccountPanelOpen)) {
ImGui.pushItemWidth(ImGui.getContentRegionMaxX() - ImGui.getWindowContentRegionMinX())
ImGui.text("Login Type:")
ImGui.combo(
"Login Type",
loginType,
arrayOf("Yggdrasil", "Microsoft")
)
ImGui.separator()
when (loginType.get()) {
0 -> {
ImGui.text("Login Name (Username or Email):")
ImGui.inputText("##new-account-login-name", yggdrasilUsername)
ImGui.text("Password:")
ImGui.inputText("##new-account-login-password", yggdrasilPassword, ImGuiInputTextFlags.Password)
}
1 -> {
ImGui.text("You may want to visit the Microsoft login site.")
if (ImGui.button("Copy URL")) {
ImGui.setClipboardText(Authenticator.microsoftLogin().toString())
}
ImGui.text("Login Token:")
ImGui.inputText("##new-account-login-token", microsoftToken)
}
}
ImGui.popItemWidth()
ImGui.separator()
if (ImGui.button("Log In")) {
val authenticator = when (loginType.get()) {
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()
val loginData = ByteArrayOutputStream()
.apply { loginResult.resultFile.write(this) }
.toString(Charsets.UTF_8)
yggdrasilUsername.set("")
yggdrasilPassword.set("")
microsoftToken.set("")
Hibiscus.data.txn {
MinecraftAccount.new {
this.name = user.name
this.lastKnownDisplayName = user.name
this.loginData = loginData
}
refreshAccounts()
(client!! as MixinExtMinecraftClient).setSession(user.createSession())
}
}
} catch (e: Exception) {
e.printStackTrace()
// TODO: Display some error
}
}
}
ImGui.end()
}
}
private fun User.createSession() = Session(
name,
uuid,
accessToken,
Optional.empty(),
Optional.empty(),
Session.AccountType.byName(type)
)
}

View file

@ -1,14 +1,15 @@
package codes.som.hibiscus.gui
package codes.som.hibiscus.gui.screens
import codes.som.hibiscus.gui.FeatureControlsUI
import net.minecraft.client.gui.screen.Screen
import net.minecraft.client.util.math.MatrixStack
import net.minecraft.text.Text
object ImGuiScreen : Screen(Text.of("hacker menu")) {
object InGameClientUIScreen : Screen(Text.of("in game hacker menu")) {
override fun render(matrices: MatrixStack?, mouseX: Int, mouseY: Int, delta: Float) {
super.render(matrices, mouseX, mouseY, delta)
ModuleControlsUI.render(delta)
FeatureControlsUI.render(delta)
}
override fun isPauseScreen() = false

View file

@ -1,13 +1,13 @@
package codes.som.hibiscus.subsystems.fullbright
import codes.som.hibiscus.HibiscusMod
import codes.som.hibiscus.Hibiscus
import codes.som.hibiscus.features.visual.Fullbright
object FullbrightSystem {
@JvmStatic
fun shouldRenderFullbright(): Boolean {
try {
return HibiscusMod.features.getFeature<Fullbright>().enabled
return Hibiscus.features.getFeature<Fullbright>().enabled
} catch (_: Exception) {
}

View file

@ -1,6 +1,6 @@
package codes.som.hibiscus.subsystems.xray
import codes.som.hibiscus.HibiscusMod
import codes.som.hibiscus.Hibiscus
import codes.som.hibiscus.features.visual.Xray
import net.minecraft.block.BlockState
import net.minecraft.block.FluidBlock
@ -11,7 +11,7 @@ object XraySystem {
@JvmStatic
fun shouldRenderXray(): Boolean {
try {
return HibiscusMod.features.getFeature<Xray>().enabled
return Hibiscus.features.getFeature<Xray>().enabled
} catch (_: Exception) {
}

View file

@ -1,7 +1,7 @@
package codes.som.hibiscus.util.command
import codes.som.hibiscus.HibiscusLog
import codes.som.hibiscus.HibiscusMod
import codes.som.hibiscus.Hibiscus
import codes.som.hibiscus.api.command.CommandContext
import codes.som.hibiscus.api.command.exceptions.CommandExecutionException
import codes.som.hibiscus.api.event.TypedListener
@ -11,8 +11,8 @@ class ChatCommandListener : TypedListener<SendChatEvent>(SendChatEvent::class.ja
override fun on(event: SendChatEvent) {
if (event.message.startsWith(".")) {
try {
HibiscusMod.commands.context = CommandContext.MANUAL
HibiscusMod.commands.executeCommand(event.message.substring(1))
Hibiscus.commands.context = CommandContext.MANUAL
Hibiscus.commands.executeCommand(event.message.substring(1))
} catch (e: CommandExecutionException) {
// e.printStackTrace()
e.cause?.message?.let { HibiscusLog.error(it) }

View file

@ -1,7 +1,7 @@
package codes.som.hibiscus.util.input
import codes.som.hibiscus.HibiscusLog
import codes.som.hibiscus.HibiscusMod
import codes.som.hibiscus.Hibiscus
import codes.som.hibiscus.api.command.CommandContext
import codes.som.hibiscus.api.command.exceptions.CommandExecutionException
import codes.som.hibiscus.api.event.TypedListener
@ -12,10 +12,10 @@ import org.lwjgl.glfw.GLFW
class KeybindDispatcher : TypedListener<KeyEvent>(KeyEvent::class.java) {
override fun on(event: KeyEvent) {
if (mc.isWindowFocused && mc.currentScreen == null && event.action == GLFW.GLFW_PRESS) {
HibiscusMod.keybinds.getBinds(event.key).forEach { bind ->
Hibiscus.keybinds.getBinds(event.key).forEach { bind ->
try {
HibiscusMod.commands.context = CommandContext.KEYBIND
HibiscusMod.commands.executeCommand(bind)
Hibiscus.commands.context = CommandContext.KEYBIND
Hibiscus.commands.executeCommand(bind)
} catch (e: CommandExecutionException) {
e.cause?.message?.let { HibiscusLog.error(it) }
}

View file

@ -1,6 +1,6 @@
package codes.som.hibiscus.util.netmoving
import codes.som.hibiscus.HibiscusMod
import codes.som.hibiscus.Hibiscus
import codes.som.hibiscus.api.event.TypedListener
import codes.som.hibiscus.events.NetworkMovingEvent
import codes.som.hibiscus.events.SendPacketEvent
@ -21,7 +21,7 @@ class NetworkMovingDispatcher : TypedListener<SendPacketEvent>(SendPacketEvent::
packet.getYaw(player.yaw), packet.getPitch(player.pitch), packet.isOnGround
)
HibiscusMod.bus.fire(movingEvent)
Hibiscus.bus.fire(movingEvent)
if (movingEvent.cancelled)
event.cancel()

View file

@ -17,7 +17,7 @@
"main": [
{
"adapter": "kotlin",
"value": "codes.som.hibiscus.HibiscusMod"
"value": "codes.som.hibiscus.Hibiscus"
}
]
},

View file

@ -11,6 +11,7 @@
"MixinClientPlayNetworkHandler",
"MixinExtClientPlayerEntity",
"MixinExtEntity",
"MixinExtMinecraftClient",
"MixinExtPlayerInteractEntityC2SPacket",
"MixinExtPlayerMoveC2SPacket",
"MixinExtUpdatePlayerAbilitiesC2SPacket",