Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
deaf091
refactor: extract shared failsafe activity guard into base class
twiston-7 Sep 22, 2026
bc96847
build: make detekt fail the build again on warnings
twiston-7 Sep 22, 2026
30a9378
fix: close the stream opened by ResourceUtils.read() for remote URLs
twiston-7 Sep 22, 2026
85489dd
fix: use thread-safe collections for state shared across threads
twiston-7 Sep 22, 2026
87dd112
chore: remove unused imports
twiston-7 Sep 22, 2026
02e5f05
chore: remove dead code
twiston-7 Sep 22, 2026
da1be14
refactor: replace positional Int mode branching with enums
twiston-7 Sep 22, 2026
639cebe
build: move DevAuth-fabric into the version catalog
twiston-7 Sep 22, 2026
be3103b
refactor: fold FailsafeUtils into FailsafeManager
twiston-7 Sep 22, 2026
b05fd60
fix: correct the declared import layout to match actual practice
twiston-7 Sep 22, 2026
876b985
refactor: consolidate the repeated 20f UI edge padding into one constant
twiston-7 Sep 22, 2026
0a30432
refactor: extract shared HoverFade helper from IconButton and ButtonS…
twiston-7 Sep 22, 2026
b2bce36
refactor: extract shared TrackSettingSupport from RangeSetting/Slider…
twiston-7 Sep 22, 2026
d9fad24
refactor: extract shared masonry column layout from ModulesPage/Scrip…
twiston-7 Sep 22, 2026
c100d64
refactor: unify GlSurface/VulkanSurface teardown into SkijaSurfaceCache
twiston-7 Sep 22, 2026
fa45f25
revert: keep AddonManager.addons as a plain mutableListOf
twiston-7 Sep 22, 2026
e753fed
refactor: give AttackMode/EspType explicit option indices instead of …
twiston-7 Sep 22, 2026
d1abc42
rename: TrackSettingSupport -> TrackSettingHelper
twiston-7 Sep 22, 2026
c9ab465
chore: remove redundant comments
twiston-7 Sep 22, 2026
64e324b
chore: remove some more redundant comments
twiston-7 Sep 22, 2026
886ad17
fix(audio): play clips on Minecraft's configured sound device
twiston-7 Sep 22, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ indent_size = 2

[*.kt]
max_line_length = 120
ij_kotlin_imports_layout = *, java, javax, kotlin, static *
ij_kotlin_imports_layout = *
ij_kotlin_allow_trailing_comma = true

[*.java]
max_line_length = 120
ij_java_imports_layout = *, java, javax, static *
ij_java_imports_layout = *

[*.{kts,xml,yml,json,md}]
indent_style = space
Expand Down
4 changes: 2 additions & 2 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ base {
detekt {
buildUponDefaultConfig = true
config.setFrom(rootProject.file("config/detekt/detekt.yml"))
failOnSeverity = FailOnSeverity.Never
failOnSeverity = FailOnSeverity.Warning
allRules = false
ignoredBuildTypes = listOf()
}
Expand Down Expand Up @@ -55,7 +55,7 @@ dependencies {
jij(libs.skija.shared)
jij(libs.discordIpc)

runtimeOnly("me.djtheredstoner:DevAuth-fabric:1.2.2")
runtimeOnly(libs.devAuth)
}

addResolvedDependencies(jij, "compileOnly", "include", "api")
Expand Down
2 changes: 2 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ fabric-kotlin = "1.13.12+kotlin.2.4.0"

skija-version = "0.143.11"
discordIpc = "0.6.0-SNAPSHOT"
devAuth = "1.2.2"

# Plugins Versions
kotlin = "2.4.0"
Expand All @@ -23,6 +24,7 @@ fabric-kotlin = { group = "net.fabricmc", name = "fabric-language-kotlin", versi

skija-shared = { group = "io.github.humbleui", name = "skija-shared", version.ref = "skija-version" }
discordIpc = { group = "com.jagrosh", name = "DiscordIPC", version.ref = "discordIpc" }
devAuth = { group = "me.djtheredstoner", name = "DevAuth-fabric", version.ref = "devAuth" }

[plugins]
kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
Expand Down
2 changes: 0 additions & 2 deletions src/main/kotlin/org/cobalt/Cobalt.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import org.cobalt.command.CommandManager
import org.cobalt.module.ModuleManager
import org.cobalt.ui.theme.ThemeManager
import org.cobalt.util.failsafe.FailsafeManager
import org.cobalt.util.failsafe.FailsafeUtils
import org.cobalt.util.input.KeyMappingHandler
import org.cobalt.util.render.skia.SkiaPIP
import org.cobalt.util.scheduling.Multithreading
Expand Down Expand Up @@ -58,7 +57,6 @@ object Cobalt : ClientModInitializer {
CommandManager.registerCommands()

FailsafeManager.initialize()
FailsafeUtils.init()
KeyMappingHandler.registerKeyMappings()

Multithreading.runAsync {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ package org.cobalt.command.annotation

@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FUNCTION)
annotation class SubCommand(val name: String = "")
annotation class SubCommand
5 changes: 0 additions & 5 deletions src/main/kotlin/org/cobalt/command/impl/MainCommand.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package org.cobalt.command.impl

import java.io.File
import net.minecraft.world.entity.Entity
import net.minecraft.world.entity.player.Player
import net.minecraft.world.phys.EntityHitResult
import net.minecraft.world.phys.HitResult
Expand All @@ -12,11 +10,8 @@ import org.cobalt.command.annotation.SubCommand
import org.cobalt.ui.screen.ConfigScreen
import org.cobalt.ui.screen.HudEditorScreen
import org.cobalt.event.EventBus
import org.cobalt.module.impl.failsafes.TeleportFailsafe
import org.cobalt.module.impl.misc.Rotations
import org.cobalt.util.audio.AudioManager
import org.cobalt.util.chat.ChatUtils
import org.cobalt.util.failsafe.FailsafeManager
import org.cobalt.util.rotation.data.Rotation
import org.cobalt.util.scheduling.TickScheduler
import org.cobalt.util.server.Scoreboard
Expand Down
3 changes: 2 additions & 1 deletion src/main/kotlin/org/cobalt/module/ModuleManager.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.cobalt.module

import java.util.concurrent.CopyOnWriteArraySet
import net.minecraft.client.gui.screens.LevelLoadingScreen
import net.minecraft.client.gui.screens.ProgressScreen
import org.cobalt.Cobalt.minecraft
Expand Down Expand Up @@ -27,7 +28,7 @@ import org.cobalt.util.render.skia.SkiaPIP

object ModuleManager {

val modules = mutableSetOf<Module>()
val modules = CopyOnWriteArraySet<Module>()

var lastScript: Script? = null
var currentScript: Script? = null
Expand Down
22 changes: 17 additions & 5 deletions src/main/kotlin/org/cobalt/module/impl/combat/AutoClicker.kt
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ object AutoClicker : Module(
options = arrayOf("All", "Entity Only", "No Blocks"),
)

private val attackModeType: AttackMode
get() = AttackMode.fromOptionIndex(attackMode)

private val mobFilter by TextSetting(
name = "Mob Filter",
description = "Only attack listed names (comma-separated)",
Expand Down Expand Up @@ -104,11 +107,10 @@ object AutoClicker : Module(
val player = minecraft.player ?: return false
val hit = minecraft.hitResult

val attackAllowed = when (attackMode) {
0 -> true
1 -> hit?.type == HitResult.Type.ENTITY
2 -> hit?.type != HitResult.Type.BLOCK
else -> false
val attackAllowed = when (attackModeType) {
AttackMode.ALL -> true
AttackMode.ENTITY_ONLY -> hit?.type == HitResult.Type.ENTITY
AttackMode.NO_BLOCKS -> hit?.type != HitResult.Type.BLOCK
}

if (!attackAllowed || (waitForReload && player.getAttackStrengthScale(0f) < 1.0f)) {
Expand All @@ -134,4 +136,14 @@ object AutoClicker : Module(
return (base + jitter).coerceAtLeast(1.0).toLong()
}

private enum class AttackMode(val optionIndex: Int) {
ALL(0),
ENTITY_ONLY(1),
NO_BLOCKS(2);

companion object {
fun fromOptionIndex(index: Int): AttackMode = entries.firstOrNull { it.optionIndex == index } ?: ALL
}
}

}
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
package org.cobalt.module.impl.failsafes

import net.fabricmc.loader.api.FabricLoader
import net.minecraft.network.chat.Component
import net.minecraft.network.protocol.game.ClientboundPlayerChatPacket
import net.minecraft.network.protocol.game.ClientboundSystemChatPacket
import org.cobalt.event.annotation.SubscribeEvent
import org.cobalt.event.impl.PacketEvent
import org.cobalt.module.ModuleManager
import org.cobalt.module.type.Failsafe
import org.cobalt.ui.component.setting.impl.CheckboxSetting
import org.cobalt.ui.component.setting.impl.ModeSetting
import org.cobalt.ui.component.setting.impl.TextSetting
import org.cobalt.util.chat.ChatUtils
import org.cobalt.util.chat.MessageType
Expand All @@ -32,7 +29,7 @@ object ChatMentionFailsafe : Failsafe("Chat Mention", 10, false) {

@SubscribeEvent
fun onChatMessage(event: PacketEvent.Receive) {
if (!ModuleManager.isScriptRunning() && !FabricLoader.getInstance().isDevelopmentEnvironment) return
if (!shouldReactToEvents()) return
val packet = event.packet as? ClientboundSystemChatPacket ?: return
val message = packet.content.string
val sender = getSenderFromComponent(packet.content)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
package org.cobalt.module.impl.failsafes

import net.fabricmc.loader.api.FabricLoader
import net.minecraft.core.BlockPos
import net.minecraft.world.phys.EntityHitResult
import net.minecraft.world.phys.HitResult
import org.cobalt.Cobalt
import org.cobalt.event.annotation.SubscribeEvent
import org.cobalt.event.impl.TickEvent
import org.cobalt.module.ModuleManager
import org.cobalt.module.type.Failsafe
import org.cobalt.util.client.PlayerUtils
import org.cobalt.util.failsafe.FailsafeManager
Expand All @@ -17,7 +13,7 @@ object PlayerCheckFailsafe : Failsafe("Player Check", 10, false) {

@SubscribeEvent
fun onTick(ignored: TickEvent.End) {
if (!ModuleManager.isScriptRunning() && !FabricLoader.getInstance().isDevelopmentEnvironment) return
if (!shouldReactToEvents()) return

val player = PlayerUtils.player ?: return
val level = Cobalt.minecraft.level ?: return
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
package org.cobalt.module.impl.failsafes

import net.fabricmc.loader.api.FabricLoader
import org.cobalt.Cobalt
import org.cobalt.module.ModuleManager
import org.cobalt.module.type.Failsafe
import org.cobalt.util.failsafe.FailsafeManager
import org.cobalt.util.rotation.data.Rotation

object RotationFailsafe : Failsafe("Rotation", 10, false) {
fun onRotation(currentRot: Rotation, newRot: Rotation) {
if (!ModuleManager.isScriptRunning() && !FabricLoader.getInstance().isDevelopmentEnvironment) return
if (!shouldReactToEvents()) return
val player = Cobalt.minecraft.player ?: return

if (currentRot == newRot) return // I think this is needed? not sure
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
package org.cobalt.module.impl.failsafes

import net.fabricmc.loader.api.FabricLoader
import net.minecraft.network.protocol.game.ClientboundSetHeldSlotPacket
import org.cobalt.Cobalt
import org.cobalt.event.annotation.SubscribeEvent
import org.cobalt.event.impl.PacketEvent
import org.cobalt.module.ModuleManager
import org.cobalt.module.type.Failsafe
import org.cobalt.util.failsafe.FailsafeManager
import org.cobalt.util.inventory.InventoryUtils

object SlotChangeFailsafe : Failsafe("Slot Change", 10, false) {
@SubscribeEvent
fun onServerItemChange(event: PacketEvent.Receive) {
if (!ModuleManager.isScriptRunning() && !FabricLoader.getInstance().isDevelopmentEnvironment) return
if (!shouldReactToEvents()) return
val player = Cobalt.minecraft.player ?: return
val packet = event.packet as? ClientboundSetHeldSlotPacket ?: return

Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,24 @@
package org.cobalt.module.impl.failsafes

import net.fabricmc.loader.api.FabricLoader
import net.minecraft.core.BlockPos
import net.minecraft.network.protocol.game.ClientboundPlayerPositionPacket
import net.minecraft.network.protocol.game.ServerboundChatCommandPacket
import net.minecraft.network.protocol.game.ServerboundUseItemPacket
import org.cobalt.Cobalt.minecraft
import org.cobalt.event.annotation.SubscribeEvent
import org.cobalt.event.impl.PacketEvent
import org.cobalt.module.ModuleManager
import org.cobalt.module.type.Failsafe
import org.cobalt.util.chat.ChatUtils
import org.cobalt.util.chat.MessageType
import org.cobalt.util.client.PlayerUtils.player
import org.cobalt.util.failsafe.FailsafeManager
import org.cobalt.util.inventory.InventoryUtils
import org.cobalt.util.inventory.ItemUtils
import org.cobalt.util.rotation.data.Rotation

object TeleportFailsafe : Failsafe("Teleport", 10, false) {
@SubscribeEvent
fun onTeleport(event: PacketEvent.Any) {
if (!ModuleManager.isScriptRunning() && !FabricLoader.getInstance().isDevelopmentEnvironment) return
if (!shouldReactToEvents()) return
if (minecraft.level == null) return
when (val packet = event.packet) {
is ClientboundPlayerPositionPacket -> {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
package org.cobalt.module.impl.failsafes

import net.fabricmc.loader.api.FabricLoader
import net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket
import net.minecraft.world.level.block.Blocks
import net.minecraft.world.phys.Vec3
import org.cobalt.Cobalt
import org.cobalt.event.annotation.SubscribeEvent
import org.cobalt.event.impl.PacketEvent
import org.cobalt.module.ModuleManager
import org.cobalt.module.type.Failsafe
import org.cobalt.util.client.PlayerUtils
import org.cobalt.util.failsafe.FailsafeManager
Expand All @@ -27,7 +25,7 @@ object VelocityFailsafe : Failsafe("Velocity", 10, false) {

@SubscribeEvent
fun onVelo(event: PacketEvent.Receive) {
if (!ModuleManager.isScriptRunning() && !FabricLoader.getInstance().isDevelopmentEnvironment) return
if (!shouldReactToEvents()) return
val player = Cobalt.minecraft.player ?: return
val packet = event.packet as? ClientboundSetEntityMotionPacket ?: return

Expand Down
30 changes: 20 additions & 10 deletions src/main/kotlin/org/cobalt/module/impl/visual/PlayerESP.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,22 @@ object PlayerESP : Module(name = "PlayerESP", category = ModuleCategory.VISUAL)
options = arrayOf("Box", "Target Beam", "Outline", "Beam & Outline")
)

private enum class EspType(val optionIndex: Int) {
BOX(0),
TARGET_BEAM(1),
OUTLINE(2),
BEAM_AND_OUTLINE(3);

companion object {
fun fromOptionIndex(index: Int): EspType = entries.firstOrNull { it.optionIndex == index } ?: BOX
}
}

private val espTypeMode: EspType
get() = EspType.fromOptionIndex(espType)

fun shouldOutline(entity: Entity): Boolean {
if (espType != 2 && espType != 3) {
if (espTypeMode != EspType.OUTLINE && espTypeMode != EspType.BEAM_AND_OUTLINE) {
return false
}

Expand All @@ -45,7 +59,7 @@ object PlayerESP : Module(name = "PlayerESP", category = ModuleCategory.VISUAL)

@SubscribeEvent
fun onWorldRender(ignored: WorldEvent.BeforeGizmos) {
if (espType == 2) {
if (espTypeMode == EspType.OUTLINE) {
return
}

Expand All @@ -56,24 +70,20 @@ object PlayerESP : Module(name = "PlayerESP", category = ModuleCategory.VISUAL)

if (player.uuid.version() == 2) return@forEach

when (espType) {
0 -> GizmoRenderer.drawEntityOutline(
when (espTypeMode) {
EspType.BOX -> GizmoRenderer.drawEntityOutline(
entity = player,
color = ThemeManager.activeTheme.accentPrimary,
esp = true
)

1 -> GizmoRenderer.drawTargetBeam(
EspType.TARGET_BEAM, EspType.BEAM_AND_OUTLINE -> GizmoRenderer.drawTargetBeam(
entity = player,
color = ThemeManager.activeTheme.accentPrimary,
esp = true
)

3 -> GizmoRenderer.drawTargetBeam( // both beam and esp
entity = player,
color = ThemeManager.activeTheme.accentPrimary,
esp = true
)
EspType.OUTLINE -> Unit
}
}
}
Expand Down
5 changes: 5 additions & 0 deletions src/main/kotlin/org/cobalt/module/type/Failsafe.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package org.cobalt.module.type

import net.fabricmc.loader.api.FabricLoader
import org.cobalt.module.Module
import org.cobalt.module.ModuleCategory
import org.cobalt.module.ModuleManager

abstract class Failsafe @JvmOverloads constructor(
name: String,
Expand All @@ -13,6 +15,9 @@ abstract class Failsafe @JvmOverloads constructor(
startValue = startValue
) {

protected fun shouldReactToEvents(): Boolean =
ModuleManager.isScriptRunning() || FabricLoader.getInstance().isDevelopmentEnvironment

abstract fun resetStates()
abstract fun performReaction(): ReactionResult?

Expand Down
2 changes: 2 additions & 0 deletions src/main/kotlin/org/cobalt/ui/UIComponent.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import net.minecraft.client.input.KeyEvent
import org.cobalt.ui.theme.Theme
import org.cobalt.ui.theme.ThemeManager

const val PADDING = 20f

abstract class UIComponent(
var xPos: Float = 0f,
var yPos: Float = 0f,
Expand Down
Loading
Loading