Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 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
5985f2f
fix: update Notification so it uses regularFont for description inste…
twiston-7 Sep 22, 2026
da523dc
chore: replace TODO stubs with safe no-op defaults to prevent failsaf…
twiston-7 Sep 22, 2026
fb94f6a
fix(failsafes): guard against null player in TeleportFailsafe
twiston-7 Sep 22, 2026
160e3a1
refactor: split RotationFailsafe/TeleportFailsafe packet handling
twiston-7 Sep 22, 2026
d5b339f
fix: clamp interpolated color channels to valid byte range
twiston-7 Sep 22, 2026
5bd5bfa
refactor: unify and fix snap-target matching in SnapHelper
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 Expand Up @@ -89,7 +86,7 @@ object ChatMentionFailsafe : Failsafe("Chat Mention", 10, false) {


override fun resetStates() {
TODO("Not yet implemented")
// TODO
}

override fun performReaction(): ReactionResult? {
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 Expand Up @@ -70,7 +66,8 @@ object PlayerCheckFailsafe : Failsafe("Player Check", 10, false) {
}

override fun performReaction(): ReactionResult? {
TODO("Not yet implemented")
// TODO
return null
}

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

import net.fabricmc.loader.api.FabricLoader
import org.cobalt.Cobalt
import org.cobalt.module.ModuleManager
import net.minecraft.network.protocol.game.ClientboundPlayerPositionPacket
import net.minecraft.network.protocol.game.ServerboundChatCommandPacket
import org.cobalt.event.annotation.SubscribeEvent
import org.cobalt.event.impl.PacketEvent
import org.cobalt.module.type.Failsafe
import org.cobalt.util.client.PlayerUtils.player
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
val player = Cobalt.minecraft.player ?: return
@SubscribeEvent
fun onRotation(event: PacketEvent.Any) {
if (!shouldReactToEvents()) return
if (minecraft.level == null) return

if (currentRot == newRot) return // I think this is needed? not sure
when (val packet = event.packet) {
is ClientboundPlayerPositionPacket -> handlePositionPacket(packet)
is ServerboundChatCommandPacket -> handleChatCommandPacket(packet)
}
}

private fun handlePositionPacket(packet: ClientboundPlayerPositionPacket) {
val currentRotation = try {
Rotation(player!!.yRot, player!!.xRot)
} catch (_: NullPointerException) {
return
}

val newRotation = Rotation(packet.change.yRot, packet.change.xRot)

if (currentRotation == newRotation) {
return
}

FailsafeManager.alertUser(
this,
"<red>ROTATED FROM</red>" +
" <yellow>${currentRot.pitch} & ${currentRot.yaw}</yellow>" +
"<red>FROM</red> <yellow>Pitch: ${currentRotation.pitch}, Yaw: ${currentRotation.yaw}</yellow>" +
" <red>TO</red>" +
" <yellow>${newRot.pitch} & ${newRot.yaw}</yellow>"
" <yellow>Pitch: ${newRotation.pitch}, Yaw: ${newRotation.yaw}</yellow>"
)
}

private fun handleChatCommandPacket(packet: ServerboundChatCommandPacket) {
if (!packet.command.contains("warp")) return
FailsafeManager.ignoreFailsafe(this)
}

override fun resetStates() {
TODO("Not yet implemented")
return
}

override fun performReaction(): ReactionResult? {
TODO("Not yet implemented")
// TODO
return null
}
}
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 All @@ -32,11 +29,12 @@ object SlotChangeFailsafe : Failsafe("Slot Change", 10, false) {
}

override fun resetStates() {
TODO("Not yet implemented")
// TODO
}

override fun performReaction(): ReactionResult {
TODO("Not yet implemented")
override fun performReaction(): ReactionResult? {
// TODO
return null
}

}
Loading
Loading