diff --git a/src/main/java/com/lambda/mixin/MinecraftClientMixin.java b/src/main/java/com/lambda/mixin/MinecraftClientMixin.java index a0e5c5b47..de1bfaaf4 100644 --- a/src/main/java/com/lambda/mixin/MinecraftClientMixin.java +++ b/src/main/java/com/lambda/mixin/MinecraftClientMixin.java @@ -95,7 +95,7 @@ void onNetwork(ClientPlayerInteractionManager instance, Operation original @Definition(id = "overlay", field = "Lnet/minecraft/client/MinecraftClient;overlay:Lnet/minecraft/client/gui/screen/Overlay;") @Expression("this.overlay == null") - @ModifyExpressionValue(method = "tick", at = @At("MIXINEXTRAS:EXPRESSION")) + @ModifyExpressionValue(method = "tick", at = @At(value = "MIXINEXTRAS:EXPRESSION", ordinal = 1)) private boolean modifyCurrentScreenNullCheck(boolean original) { if (!original || this.currentScreen != null) { EventFlow.post(TickEvent.Input.Pre.INSTANCE); diff --git a/src/main/kotlin/com/lambda/Lambda.kt b/src/main/kotlin/com/lambda/Lambda.kt index d90bbbaad..45d409749 100644 --- a/src/main/kotlin/com/lambda/Lambda.kt +++ b/src/main/kotlin/com/lambda/Lambda.kt @@ -19,8 +19,8 @@ package com.lambda import com.google.gson.Gson import com.google.gson.GsonBuilder -import com.lambda.config.serializer.BlockPosCodec import com.lambda.config.serializer.BlockCodec +import com.lambda.config.serializer.BlockPosCodec import com.lambda.config.serializer.ColorSerializer import com.lambda.config.serializer.GameProfileCodec import com.lambda.config.serializer.ItemCodec @@ -45,7 +45,6 @@ import net.minecraft.item.Item import net.minecraft.item.ItemStack import net.minecraft.item.PotionItem import net.minecraft.item.RangedWeaponItem -import net.minecraft.registry.DynamicRegistryManager import net.minecraft.text.Text import net.minecraft.util.math.BlockPos import org.apache.logging.log4j.LogManager @@ -92,7 +91,7 @@ object Lambda : ClientModInitializer { init { // We want the opengl context to be created - listenOnceUnsafe(priority = Int.MAX_VALUE) { + listenOnceUnsafe({ Int.MAX_VALUE }) { LOG.info("$MOD_NAME $VERSION initialized in ${Loader.initialize()} ms\n") if (ClickGuiLayout.setLambdaWindowIcon) setLambdaWindowIcon() true diff --git a/src/main/kotlin/com/lambda/config/Configuration.kt b/src/main/kotlin/com/lambda/config/Configuration.kt index c00385c7f..edf62665b 100644 --- a/src/main/kotlin/com/lambda/config/Configuration.kt +++ b/src/main/kotlin/com/lambda/config/Configuration.kt @@ -65,7 +65,7 @@ abstract class Configuration : Jsonable, Loadable { get() = File("${primary.parent}/${primary.nameWithoutExtension}-backup.${primary.extension}") override fun load(): String { - listenUnsafe(Int.MIN_VALUE) { trySave() } + listenUnsafe({ Int.MIN_VALUE }) { trySave() } register() return super.load() } diff --git a/src/main/kotlin/com/lambda/config/Setting.kt b/src/main/kotlin/com/lambda/config/Setting.kt index 75f9ed688..24f048c53 100644 --- a/src/main/kotlin/com/lambda/config/Setting.kt +++ b/src/main/kotlin/com/lambda/config/Setting.kt @@ -90,9 +90,7 @@ import kotlin.reflect.KProperty * ``` * * @property defaultValue The default value of the setting. - * @property description A description of the setting. * @property type The type reflection of the setting. - * @property visibility A function that determines whether the setting is visible. */ abstract class SettingCore( var defaultValue: T, diff --git a/src/main/kotlin/com/lambda/config/UserAutomationConfig.kt b/src/main/kotlin/com/lambda/config/UserAutomationConfig.kt index 5b35780a8..04954dd30 100644 --- a/src/main/kotlin/com/lambda/config/UserAutomationConfig.kt +++ b/src/main/kotlin/com/lambda/config/UserAutomationConfig.kt @@ -24,7 +24,7 @@ import com.lambda.module.Module import com.lambda.module.ModuleRegistry.moduleNameMap class UserAutomationConfig(override val name: String) : AutomationConfig(name, UserAutomationConfigs) { - val linkedModules = setting("Linked Modules", emptySet(), moduleNameMap.filter { it.value.defaultAutomationConfig != Companion.DEFAULT }.keys) + val linkedModules = setting("Linked Modules", emptySet(), moduleNameMap.filter { it.value.defaultAutomationConfig != Companion.DEFAULT }.keys) { false } .onSelect { name -> moduleNameMap[name]?.let { it.removeLink() diff --git a/src/main/kotlin/com/lambda/event/EventFlow.kt b/src/main/kotlin/com/lambda/event/EventFlow.kt index 5fbdabbcd..95185ecc9 100644 --- a/src/main/kotlin/com/lambda/event/EventFlow.kt +++ b/src/main/kotlin/com/lambda/event/EventFlow.kt @@ -97,6 +97,17 @@ object EventFlow { concurrentListeners.unsubscribe(this) } + fun Any.updateListenerSorting() { + syncListeners.values.forEach { listeners -> + val matching = listeners.filter { it.owner === this } + matching.forEach { !listeners.remove(it); it.priority.update(); listeners.add(it) } + } + concurrentListeners.values.forEach { listeners -> + val matching = listeners.filter { it.owner === this } + matching.forEach { listeners.remove(it); it.priority.update(); listeners.add(it) } + } + } + init { // parallel event execution on dedicated threads runConcurrent { diff --git a/src/main/kotlin/com/lambda/event/listener/Listener.kt b/src/main/kotlin/com/lambda/event/listener/Listener.kt index bf30e2f87..151d08c98 100644 --- a/src/main/kotlin/com/lambda/event/listener/Listener.kt +++ b/src/main/kotlin/com/lambda/event/listener/Listener.kt @@ -21,6 +21,7 @@ import com.lambda.event.Event import com.lambda.event.EventFlow import com.lambda.event.Muteable import com.lambda.module.Module +import com.lambda.util.collections.UpdatableLazy /** * An abstract class representing a [Listener] in the [Event] system ([EventFlow]). @@ -45,7 +46,7 @@ import com.lambda.module.Module * @property alwaysListen If true, the [Listener] will always be triggered, even if the [owner] is [Muteable.isMuted]. */ abstract class Listener : Comparable> { - abstract val priority: Int + abstract val priority: UpdatableLazy abstract val owner: Any abstract val alwaysListen: Boolean @@ -61,10 +62,13 @@ abstract class Listener : Comparable> { companion object { val comparator = compareBy> { - it.priority + it.priority.value }.thenBy { // Hashcode is needed because ConcurrentSkipListSet handles insertion based on compareTo it.hashCode() } + + val Any.modulePriorityOr0Getter + get() = (this as? Module)?.let { { prioritySetting.value } } ?: { 0 } } } diff --git a/src/main/kotlin/com/lambda/event/listener/SafeListener.kt b/src/main/kotlin/com/lambda/event/listener/SafeListener.kt index 1b8196c21..65f33fd6b 100644 --- a/src/main/kotlin/com/lambda/event/listener/SafeListener.kt +++ b/src/main/kotlin/com/lambda/event/listener/SafeListener.kt @@ -25,6 +25,7 @@ import com.lambda.threading.runConcurrent import com.lambda.threading.runGameScheduled import com.lambda.threading.runSafe import com.lambda.util.Pointer +import com.lambda.util.collections.updatableLazy import com.lambda.util.selfReference import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.Dispatchers @@ -62,11 +63,13 @@ import kotlin.reflect.KProperty * @property function The function to be executed when the event occurs. This function operates within a [SafeContext]. */ class SafeListener( - override val priority: Int = 0, + priorityProvider: () -> Int, override val owner: Any, override val alwaysListen: Boolean = false, val function: SafeContext.(T) -> Unit ) : Listener(), ReadOnlyProperty { + override val priority = updatableLazy(priorityProvider) + /** * The last processed event signal. */ @@ -118,7 +121,7 @@ class SafeListener( * @return The newly created and registered [SafeListener]. */ inline fun Any.listen( - priority: Int = 0, + noinline priority: () -> Int = modulePriorityOr0Getter, alwaysListen: Boolean = false, noinline function: SafeContext.(T) -> Unit = {} ): SafeListener { @@ -163,7 +166,7 @@ class SafeListener( */ fun Any.listen( kClass: KClass, - priority: Int = 0, + priority: () -> Int = modulePriorityOr0Getter, alwaysListen: Boolean = false, function: SafeContext.(T) -> Unit = {}, ): SafeListener { @@ -205,7 +208,7 @@ class SafeListener( * @return The newly created and registered [SafeListener]. */ inline fun Any.listenOnce( - priority: Int = 0, + noinline priority: () -> Int = modulePriorityOr0Getter, alwaysListen: Boolean = false, noinline predicate: SafeContext.(T) -> Boolean = { true }, ): ReadWriteProperty { @@ -253,7 +256,7 @@ class SafeListener( * @return The newly created and registered [SafeListener]. */ inline fun Any.listenConcurrently( - priority: Int = 0, + noinline priority: () -> Int = modulePriorityOr0Getter, alwaysListen: Boolean = false, scheduler: CoroutineDispatcher = Dispatchers.Default, noinline function: suspend SafeContext.(T) -> Unit = {}, diff --git a/src/main/kotlin/com/lambda/event/listener/UnsafeListener.kt b/src/main/kotlin/com/lambda/event/listener/UnsafeListener.kt index 365a6fa09..13371bcc3 100644 --- a/src/main/kotlin/com/lambda/event/listener/UnsafeListener.kt +++ b/src/main/kotlin/com/lambda/event/listener/UnsafeListener.kt @@ -25,6 +25,7 @@ import com.lambda.event.listener.SafeListener.Companion.listenConcurrently import com.lambda.event.listener.SafeListener.Companion.listenOnce import com.lambda.threading.runConcurrent import com.lambda.util.Pointer +import com.lambda.util.collections.updatableLazy import com.lambda.util.selfReference import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.Dispatchers @@ -60,11 +61,13 @@ import kotlin.reflect.KProperty * @property function The function to be executed when the event occurs. This function operates without a [SafeContext]. */ class UnsafeListener( - override val priority: Int, + priorityProvider: () -> Int, override val owner: Any, override val alwaysListen: Boolean = false, val function: (T) -> Unit, ) : Listener(), ReadOnlyProperty { + override val priority = updatableLazy(priorityProvider) + /** * The last processed event signal. */ @@ -107,7 +110,7 @@ class UnsafeListener( * @return The newly created and registered [UnsafeListener]. */ inline fun Any.listenUnsafe( - priority: Int = 0, + noinline priority: () -> Int = modulePriorityOr0Getter, alwaysListen: Boolean = false, noinline function: (T) -> Unit = {}, ): UnsafeListener { @@ -144,7 +147,7 @@ class UnsafeListener( * @return The newly created and registered [UnsafeListener]. */ inline fun Any.listenOnceUnsafe( - priority: Int = 0, + noinline priority: () -> Int = modulePriorityOr0Getter, alwaysListen: Boolean = false, noinline function: (T) -> Boolean = { true }, ): ReadWriteProperty { @@ -193,7 +196,7 @@ class UnsafeListener( * @return The newly created and registered [UnsafeListener]. */ inline fun Any.listenConcurrentlyUnsafe( - priority: Int = 0, + noinline priority: () -> Int = modulePriorityOr0Getter, alwaysListen: Boolean = false, scheduler: CoroutineDispatcher = Dispatchers.Default, noinline function: suspend (T) -> Unit = {}, diff --git a/src/main/kotlin/com/lambda/gui/components/SettingsWidget.kt b/src/main/kotlin/com/lambda/gui/components/SettingsWidget.kt index dabb904d7..e3415e63f 100644 --- a/src/main/kotlin/com/lambda/gui/components/SettingsWidget.kt +++ b/src/main/kotlin/com/lambda/gui/components/SettingsWidget.kt @@ -37,12 +37,19 @@ object SettingsWidget { fun ImGuiBuilder.buildConfigSettingsContext(config: Configurable) { group { if (config is Module) { - with(config.keybindSetting) { buildLayout() } - with(config.disableOnReleaseSetting) { buildLayout() } - with(config.drawSetting) { buildLayout() } - } - smallButton("Reset") { - config.settings.forEach { it.reset(silent = true) } + button("Module Settings") { + ImGui.openPopup("##module-settings-popup-${config.name}") + } + ImGui.setNextWindowSizeConstraints(0f, 0f, Float.MAX_VALUE, io.displaySize.y * 0.5f) + popupContextItem("##module-settings-popup-${config.name}", ImGuiPopupFlags.None) { + with(config.keybindSetting) { buildLayout() } + with(config.prioritySetting) { buildLayout() } + with(config.disableOnReleaseSetting) { buildLayout() } + with(config.drawSetting) { buildLayout() } + smallButton("Reset") { + config.settings.forEach { it.reset(silent = true) } + } + } } lambdaTooltip("Resets all settings for this module to their default values") if (config is MutableAutomationConfig && config.automationConfig !== AutomationConfig.Companion.DEFAULT) { @@ -74,13 +81,8 @@ object SettingsWidget { } } } - val toIgnoreSettings = - when (config) { - is Module -> setOf(config.keybindSetting, config.disableOnReleaseSetting, config.drawSetting) - is UserAutomationConfig -> setOf(config.linkedModules) - else -> emptySet() - } - val visibleSettings = config.settings.filter { it.visibility() } - toIgnoreSettings + + val visibleSettings = config.settings.filter { it.visibility() } if (visibleSettings.isEmpty()) return else separator() val (grouped, ungrouped) = visibleSettings.partition { it.groups.isNotEmpty() } diff --git a/src/main/kotlin/com/lambda/interaction/managers/Manager.kt b/src/main/kotlin/com/lambda/interaction/managers/Manager.kt index 972572fda..4552d83a7 100644 --- a/src/main/kotlin/com/lambda/interaction/managers/Manager.kt +++ b/src/main/kotlin/com/lambda/interaction/managers/Manager.kt @@ -65,7 +65,7 @@ abstract class Manager( override fun load(): String { openStages.forEach { openRequestsFor(it::class, it) } - listen(Int.MIN_VALUE) { + listen({ Int.MIN_VALUE }) { activeThisTick = false queuedRequest = null } @@ -77,7 +77,7 @@ abstract class Manager( * opens the handler for requests for the duration of the given event */ private inline fun openRequestsFor(instance: KClass, stage: T) { - listen(instance, priority = (Int.MAX_VALUE - 1) - (accumulatedManagerPriority - stagePriority)) { + listen(instance, { (Int.MAX_VALUE - 1) - (accumulatedManagerPriority - stagePriority) }) { tickStage = stage queuedRequest?.let { request -> if (tickStage !in request.tickStageMask) return@let @@ -89,7 +89,7 @@ abstract class Manager( onOpen?.invoke(this) } - listen(instance, priority = (Int.MIN_VALUE + 1) + stagePriority) { + listen(instance, { (Int.MIN_VALUE + 1) + stagePriority }) { onClose?.invoke(this) acceptingRequests = false } diff --git a/src/main/kotlin/com/lambda/interaction/managers/PostActionHandler.kt b/src/main/kotlin/com/lambda/interaction/managers/PostActionHandler.kt index 2d1a73858..6cbe3bb77 100644 --- a/src/main/kotlin/com/lambda/interaction/managers/PostActionHandler.kt +++ b/src/main/kotlin/com/lambda/interaction/managers/PostActionHandler.kt @@ -32,11 +32,11 @@ abstract class PostActionHandler { abstract val pendingActions: LimitedDecayQueue init { - listen(priority = Int.MAX_VALUE) { + listen({ Int.MAX_VALUE }) { pendingActions.cleanUp() } - listenUnsafe(priority = Int.MIN_VALUE) { + listenUnsafe({ Int.MIN_VALUE }) { pendingActions.clear() } } diff --git a/src/main/kotlin/com/lambda/interaction/managers/breaking/BreakManager.kt b/src/main/kotlin/com/lambda/interaction/managers/breaking/BreakManager.kt index 252bad051..3dd2ff9fc 100644 --- a/src/main/kotlin/com/lambda/interaction/managers/breaking/BreakManager.kt +++ b/src/main/kotlin/com/lambda/interaction/managers/breaking/BreakManager.kt @@ -163,11 +163,11 @@ object BreakManager : Manager( override fun load(): String { super.load() - listen(priority = Int.MAX_VALUE) { + listen({ Int.MAX_VALUE }) { if (activeInfos.isEmpty() && breaks.isEmpty()) return@listen } - listen(priority = Int.MIN_VALUE) { + listen({ Int.MIN_VALUE }) { breakInfos.forEach { it?.tickChecks() } if (breakCooldown > 0) { breakCooldown-- @@ -177,7 +177,7 @@ object BreakManager : Manager( breaksThisTick = 0 } - listen(priority = Int.MIN_VALUE) { event -> + listen({ Int.MIN_VALUE }) { event -> if (event.pos == RebreakHandler.rebreak?.context?.blockPos) return@listen breakInfos @@ -204,7 +204,7 @@ object BreakManager : Manager( } // ToDo: Dependent on the tracked data order. When set stack is called after position it wont work - listen(priority = Int.MIN_VALUE) { + listen({ Int.MIN_VALUE }) { if (it.entity !is ItemEntity) return@listen // ToDo: Proper item drop prediction system @@ -279,7 +279,7 @@ object BreakManager : Manager( } } - listenUnsafe(priority = Int.MIN_VALUE) { + listenUnsafe({ Int.MIN_VALUE }) { primaryBreak = null secondaryBreak = null breakCooldown = 0 diff --git a/src/main/kotlin/com/lambda/interaction/managers/breaking/BrokenBlockHandler.kt b/src/main/kotlin/com/lambda/interaction/managers/breaking/BrokenBlockHandler.kt index 454524216..64e2fd2de 100644 --- a/src/main/kotlin/com/lambda/interaction/managers/breaking/BrokenBlockHandler.kt +++ b/src/main/kotlin/com/lambda/interaction/managers/breaking/BrokenBlockHandler.kt @@ -76,7 +76,7 @@ object BrokenBlockHandler : PostActionHandler() { } init { - listen(priority = Int.MIN_VALUE) { event -> + listen({ Int.MIN_VALUE }) { event -> run { pendingActions.firstOrNull { it.context.blockPos == event.pos } ?: if (rebreak?.context?.blockPos == event.pos) rebreak @@ -117,7 +117,7 @@ object BrokenBlockHandler : PostActionHandler() { } } - listen(priority = Int.MIN_VALUE) { + listen({ Int.MIN_VALUE }) { if (it.entity !is ItemEntity) return@listen val pending = pendingActions.firstOrNull { info -> matchesBlockItem(info, it.entity) } diff --git a/src/main/kotlin/com/lambda/interaction/managers/breaking/RebreakHandler.kt b/src/main/kotlin/com/lambda/interaction/managers/breaking/RebreakHandler.kt index 17bd3366d..62370ed0f 100644 --- a/src/main/kotlin/com/lambda/interaction/managers/breaking/RebreakHandler.kt +++ b/src/main/kotlin/com/lambda/interaction/managers/breaking/RebreakHandler.kt @@ -38,7 +38,7 @@ object RebreakHandler { var rebreak: BreakInfo? = null init { - listen(priority = Int.MIN_VALUE + 1) { + listen({ Int.MIN_VALUE + 1 }) { rebreak?.run { if (!progressedThisTick) { breakingTicks++ @@ -47,7 +47,7 @@ object RebreakHandler { } } - listenUnsafe(priority = Int.MIN_VALUE) { + listenUnsafe({ Int.MIN_VALUE }) { rebreak = null } } diff --git a/src/main/kotlin/com/lambda/interaction/managers/hotbar/HotbarManager.kt b/src/main/kotlin/com/lambda/interaction/managers/hotbar/HotbarManager.kt index 945e808f7..dc003e347 100644 --- a/src/main/kotlin/com/lambda/interaction/managers/hotbar/HotbarManager.kt +++ b/src/main/kotlin/com/lambda/interaction/managers/hotbar/HotbarManager.kt @@ -65,7 +65,7 @@ object HotbarManager : Manager( override fun load(): String { super.load() - listen(priority = Int.MIN_VALUE) { + listen({ Int.MIN_VALUE }) { swapsThisTick = 0 if (swapDelay > 0) swapDelay-- diff --git a/src/main/kotlin/com/lambda/interaction/managers/interacting/InteractManager.kt b/src/main/kotlin/com/lambda/interaction/managers/interacting/InteractManager.kt index e9b7b02df..d3ced79a4 100644 --- a/src/main/kotlin/com/lambda/interaction/managers/interacting/InteractManager.kt +++ b/src/main/kotlin/com/lambda/interaction/managers/interacting/InteractManager.kt @@ -82,7 +82,7 @@ object InteractManager : Manager( override fun load(): String { super.load() - listen(priority = Int.MIN_VALUE) { + listen({ Int.MIN_VALUE }) { activeRequest = null placementsThisTick = 0 potentialPlacements.clear() @@ -91,14 +91,14 @@ object InteractManager : Manager( } } - listen(priority = Int.MIN_VALUE) { + listen({ Int.MIN_VALUE }) { if (shouldSneak) { shouldSneak = false it.input.sneaking = true } } - listenUnsafe(priority = Int.MIN_VALUE) { + listenUnsafe({ Int.MIN_VALUE }) { interactCooldown = 0 } diff --git a/src/main/kotlin/com/lambda/interaction/managers/interacting/InteractedBlockHandler.kt b/src/main/kotlin/com/lambda/interaction/managers/interacting/InteractedBlockHandler.kt index bc02a5dcf..fb1e3c6ce 100644 --- a/src/main/kotlin/com/lambda/interaction/managers/interacting/InteractedBlockHandler.kt +++ b/src/main/kotlin/com/lambda/interaction/managers/interacting/InteractedBlockHandler.kt @@ -43,7 +43,7 @@ object InteractedBlockHandler : PostActionHandler() { } init { - listen(priority = Int.MIN_VALUE) { event -> + listen({ Int.MIN_VALUE }) { event -> pendingActions .firstOrNull { it.context.blockPos == event.pos } ?.let { pending -> diff --git a/src/main/kotlin/com/lambda/interaction/managers/inventory/InventoryManager.kt b/src/main/kotlin/com/lambda/interaction/managers/inventory/InventoryManager.kt index 5e3eb89b8..2720ea5ed 100644 --- a/src/main/kotlin/com/lambda/interaction/managers/inventory/InventoryManager.kt +++ b/src/main/kotlin/com/lambda/interaction/managers/inventory/InventoryManager.kt @@ -73,7 +73,7 @@ object InventoryManager : Manager( override fun load(): String { super.load() - listen(priority = Int.MIN_VALUE) { + listen({ Int.MIN_VALUE }) { if (DEFAULT.avoidDesync) indexInventoryChanges() if (++secondCounter >= 20) { secondCounter = 0 diff --git a/src/main/kotlin/com/lambda/interaction/managers/rotating/RotationManager.kt b/src/main/kotlin/com/lambda/interaction/managers/rotating/RotationManager.kt index 7058f9ca1..c46c64639 100644 --- a/src/main/kotlin/com/lambda/interaction/managers/rotating/RotationManager.kt +++ b/src/main/kotlin/com/lambda/interaction/managers/rotating/RotationManager.kt @@ -79,7 +79,7 @@ object RotationManager : Manager( override fun load(): String { super.load() - listen(priority = Int.MAX_VALUE) { + listen({ Int.MAX_VALUE }) { requests.forEachIndexed { index, request -> if (request == null) return@forEachIndexed if (request.keepTicks <= 0 && request.decayTicks <= 0) { @@ -88,7 +88,7 @@ object RotationManager : Manager( } } - listen(priority = Int.MIN_VALUE) { + listen({ Int.MIN_VALUE }) { usingBaritoneRotation = false requests.forEach { request -> request?.age++ @@ -107,7 +107,7 @@ object RotationManager : Manager( mc.crosshairTarget = blockHit } - listen(priority = Int.MIN_VALUE) { event -> + listen({ Int.MIN_VALUE }) { event -> val packet = event.packet if (packet !is PlayerPositionLookS2CPacket) return@listen @@ -116,16 +116,16 @@ object RotationManager : Manager( } } - listenUnsafe(priority = Int.MIN_VALUE) { + listenUnsafe({ Int.MIN_VALUE }) { reset(Rotation.ZERO) } // Override user interactions with max priority - listen(priority = Int.MAX_VALUE) { activeRotation = player.rotation } - listen(priority = Int.MAX_VALUE) { activeRotation = player.rotation } - listen(priority = Int.MAX_VALUE) { activeRotation = player.rotation } - listen(priority = Int.MAX_VALUE) { activeRotation = player.rotation } - listen(priority = Int.MAX_VALUE) { activeRotation = player.rotation } + listen({ Int.MAX_VALUE }) { activeRotation = player.rotation } + listen({ Int.MAX_VALUE }) { activeRotation = player.rotation } + listen({ Int.MAX_VALUE }) { activeRotation = player.rotation } + listen({ Int.MAX_VALUE }) { activeRotation = player.rotation } + listen({ Int.MAX_VALUE }) { activeRotation = player.rotation } return "Loaded Rotation Manager" } diff --git a/src/main/kotlin/com/lambda/module/Module.kt b/src/main/kotlin/com/lambda/module/Module.kt index 2ba08c91b..db3b6ef3e 100644 --- a/src/main/kotlin/com/lambda/module/Module.kt +++ b/src/main/kotlin/com/lambda/module/Module.kt @@ -27,6 +27,7 @@ import com.lambda.config.SettingCore import com.lambda.config.configurations.ModuleConfigs import com.lambda.config.settings.complex.Bind import com.lambda.context.SafeContext +import com.lambda.event.EventFlow.updateListenerSorting import com.lambda.event.Muteable import com.lambda.event.events.ClientEvent import com.lambda.event.events.ConnectionEvent @@ -122,9 +123,11 @@ abstract class Module( autoDisable: Boolean = false ) : Nameable, Muteable, Configurable(ModuleConfigs), MutableAutomationConfig by MutableAutomationConfigImpl() { private val isEnabledSetting = setting("Enabled", enabledByDefault) { false } + open val prioritySetting = setting("Module Priority", 0, -100..100, 1, "Priority over other modules") { false } + .onValueChangeUnsafe { _, _ -> updateListenerSorting() } val keybindSetting = setting("Keybind", defaultKeybind) { false } val disableOnReleaseSetting = setting("Disable On Release", false) { false } - val drawSetting = setting("Draw", true, "Draws the module in the module list hud element") + val drawSetting = setting("Draw", true, "Draws the module in the module list hud element") { false } var isEnabled by isEnabledSetting val isDisabled get() = !isEnabled @@ -213,4 +216,9 @@ abstract class Module( if (from != to) block(to) } } + + protected fun setModulePriority(priority: Int) { + prioritySetting.value = priority + prioritySetting.core.defaultValue = priority + } } diff --git a/src/main/kotlin/com/lambda/module/modules/chat/AntiSpam.kt b/src/main/kotlin/com/lambda/module/modules/chat/AntiSpam.kt index d01d101eb..4156fe216 100644 --- a/src/main/kotlin/com/lambda/module/modules/chat/AntiSpam.kt +++ b/src/main/kotlin/com/lambda/module/modules/chat/AntiSpam.kt @@ -59,13 +59,13 @@ object AntiSpam : Module( private val detectSwears = ReplaceSettings("Swears", this, Group.Swears) private val detectSexual = ReplaceSettings("Sexual", this, Group.Sexual) private val detectDiscord = ReplaceSettings("Discord", this, Group.Discord) - .apply { applyEdits { editTyped(::action) { defaultValue(ReplaceConfig.ActionStrategy.Hide) } } } + .apply { applyEdits { ::action.edit { defaultValue(ReplaceConfig.ActionStrategy.Hide) } } } private val detectAddresses = ReplaceSettings("Addresses", this, Group.Addresses) - .apply { applyEdits { editTyped(::action) { defaultValue(ReplaceConfig.ActionStrategy.Hide) } } } + .apply { applyEdits { ::action.edit { defaultValue(ReplaceConfig.ActionStrategy.Hide) } } } private val detectHexBypass = ReplaceSettings("Hex", this, Group.Hex) - .apply { applyEdits { editTyped(::action) { defaultValue(ReplaceConfig.ActionStrategy.Hide) } } } + .apply { applyEdits { ::action.edit { defaultValue(ReplaceConfig.ActionStrategy.Hide) } } } private val detectColors = ReplaceSettings("Colors", this, Group.Colors) - .apply { applyEdits { editTyped(::action) { defaultValue(ReplaceConfig.ActionStrategy.None) } } } + .apply { applyEdits { ::action.edit { defaultValue(ReplaceConfig.ActionStrategy.None) } } } enum class Group(override val displayName: String) : NamedEnum { General("General"), @@ -79,6 +79,7 @@ object AntiSpam : Module( } init { + setModulePriority(100) listen { event -> var raw = event.message.string val author = MessageParser.playerName(raw) diff --git a/src/main/kotlin/com/lambda/module/modules/combat/AutoDisconnect.kt b/src/main/kotlin/com/lambda/module/modules/combat/AutoDisconnect.kt index da86558f2..0b5254a33 100644 --- a/src/main/kotlin/com/lambda/module/modules/combat/AutoDisconnect.kt +++ b/src/main/kotlin/com/lambda/module/modules/combat/AutoDisconnect.kt @@ -84,7 +84,8 @@ object AutoDisconnect : Module( private val trident by setting("Trident", false, "Disconnect from the server when you get trident damage.") { onDamage } init { - listen(-1000) { + setModulePriority(-100) + listen { Reason.entries.filter { it.check() }.forEach { reason -> diff --git a/src/main/kotlin/com/lambda/module/modules/combat/AutoTotem.kt b/src/main/kotlin/com/lambda/module/modules/combat/AutoTotem.kt index 322486cd7..40bc4cd12 100644 --- a/src/main/kotlin/com/lambda/module/modules/combat/AutoTotem.kt +++ b/src/main/kotlin/com/lambda/module/modules/combat/AutoTotem.kt @@ -55,6 +55,7 @@ object AutoTotem : Module( private val friends by setting("Friends", false, "Exclude friends from triggering player-based swaps") { !always && players }.group(Group.General) init { + setModulePriority(100) setDefaultAutomationConfig { applyEdits { hideAllGroupsExcept(inventoryConfig) diff --git a/src/main/kotlin/com/lambda/module/modules/combat/FakePlayer.kt b/src/main/kotlin/com/lambda/module/modules/combat/FakePlayer.kt index 6a9634899..a31e80b50 100644 --- a/src/main/kotlin/com/lambda/module/modules/combat/FakePlayer.kt +++ b/src/main/kotlin/com/lambda/module/modules/combat/FakePlayer.kt @@ -35,7 +35,6 @@ import com.mojang.datafixers.util.Either import net.minecraft.client.network.OtherClientPlayerEntity import net.minecraft.client.network.PlayerListEntry import java.util.* -import kotlin.jvm.optionals.getOrElse import kotlin.jvm.optionals.getOrNull import kotlin.time.Duration.Companion.seconds @@ -66,7 +65,7 @@ object FakePlayer : Module( ?: spawnFakePlayer(nilProfile, fakePlayer ?: player, addToWorld = false) } - listenConcurrently(priority = 1000) { + listenConcurrently({ 1000 }) { if (!fetchTimer.timePassed(2.seconds)) return@listenConcurrently cachedProfiles.getOrPut(playerName) { fetchProfile(playerName) } diff --git a/src/main/kotlin/com/lambda/module/modules/combat/KillAura.kt b/src/main/kotlin/com/lambda/module/modules/combat/KillAura.kt index 500316a59..1f8a58041 100644 --- a/src/main/kotlin/com/lambda/module/modules/combat/KillAura.kt +++ b/src/main/kotlin/com/lambda/module/modules/combat/KillAura.kt @@ -89,6 +89,7 @@ object KillAura : Module( } init { + setModulePriority(90) setDefaultAutomationConfig { applyEdits { hideAllGroupsExcept(buildConfig, hotbarConfig, rotationConfig) @@ -98,7 +99,7 @@ object KillAura : Module( } } - listen(Int.MIN_VALUE) { event -> + listen({ Int.MIN_VALUE }) { event -> prevY = lastY lastY = event.position.y lastOnGround = event.onGround diff --git a/src/main/kotlin/com/lambda/module/modules/movement/BetterFirework.kt b/src/main/kotlin/com/lambda/module/modules/movement/BetterFirework.kt index 99443f902..b7d0a372e 100644 --- a/src/main/kotlin/com/lambda/module/modules/movement/BetterFirework.kt +++ b/src/main/kotlin/com/lambda/module/modules/movement/BetterFirework.kt @@ -66,6 +66,7 @@ object BetterFirework : Module( get() = !abilities.flying && !isClimbing && !isGliding && !isTouchingWater && !isOnGround && !hasVehicle() && !hasStatusEffect(StatusEffects.LEVITATION) init { + setModulePriority(1) setDefaultAutomationConfig { applyEdits { hideAllGroupsExcept(hotbarConfig, inventoryConfig) diff --git a/src/main/kotlin/com/lambda/module/modules/network/PacketDelay.kt b/src/main/kotlin/com/lambda/module/modules/network/PacketDelay.kt index 20787710a..54a9bb6ed 100644 --- a/src/main/kotlin/com/lambda/module/modules/network/PacketDelay.kt +++ b/src/main/kotlin/com/lambda/module/modules/network/PacketDelay.kt @@ -59,7 +59,7 @@ object PacketDelay : Module( flushPools(System.currentTimeMillis()) } - listen(Int.MIN_VALUE) { event -> + listen({ Int.MIN_VALUE }) { event -> if (!packetScope.filter(event.packet)) return@listen when (mode) { @@ -80,7 +80,7 @@ object PacketDelay : Module( } } - listen(Int.MIN_VALUE) { event -> + listen({ Int.MIN_VALUE }) { event -> if (!packetScope.filter(event.packet)) return@listen when (mode) { diff --git a/src/main/kotlin/com/lambda/module/modules/network/PacketLimiter.kt b/src/main/kotlin/com/lambda/module/modules/network/PacketLimiter.kt index afa377cf0..61fad958c 100644 --- a/src/main/kotlin/com/lambda/module/modules/network/PacketLimiter.kt +++ b/src/main/kotlin/com/lambda/module/modules/network/PacketLimiter.kt @@ -69,7 +69,7 @@ object PacketLimiter : Module( globalQueue.setSizeLimit(globalLimit) } - listen(Int.MAX_VALUE) { + listen({ Int.MAX_VALUE }) { if (it.packet::class.java.name in ignorePackets) return@listen if (!globalQueue.add(it)) { diff --git a/src/main/kotlin/com/lambda/module/modules/player/ClickFriend.kt b/src/main/kotlin/com/lambda/module/modules/player/ClickFriend.kt index a23e6e779..110f4eb20 100644 --- a/src/main/kotlin/com/lambda/module/modules/player/ClickFriend.kt +++ b/src/main/kotlin/com/lambda/module/modules/player/ClickFriend.kt @@ -41,6 +41,7 @@ object ClickFriend : Module( private val unfriendBind by setting("Unfriend Bind", Bind(0, GLFW_MOD_SHIFT, GLFW.GLFW_MOUSE_BUTTON_MIDDLE), "Bind to press to unfriend a player") init { + setModulePriority(100) listen { if (mc.currentScreen != null) return@listen diff --git a/src/main/kotlin/com/lambda/module/modules/player/Freecam.kt b/src/main/kotlin/com/lambda/module/modules/player/Freecam.kt index 30929640f..d44a8cc3f 100644 --- a/src/main/kotlin/com/lambda/module/modules/player/Freecam.kt +++ b/src/main/kotlin/com/lambda/module/modules/player/Freecam.kt @@ -162,7 +162,7 @@ object Freecam : Module( } } - listen(priority = 1) { event -> // Higher priority then RotationManager to run before RotationManager modifies mc.crosshairTarget + listen({ 1 }) { event -> // Higher priority then RotationManager to run before RotationManager modifies mc.crosshairTarget mc.crosshairTarget = rotation .rayCast(reach, lerpPos) .orMiss // Can't be null (otherwise mc will spam "Null returned as 'hitResult', this shouldn't happen!") diff --git a/src/main/kotlin/com/lambda/module/modules/player/RotationLock.kt b/src/main/kotlin/com/lambda/module/modules/player/RotationLock.kt index 870a12f25..92cf01e4f 100644 --- a/src/main/kotlin/com/lambda/module/modules/player/RotationLock.kt +++ b/src/main/kotlin/com/lambda/module/modules/player/RotationLock.kt @@ -52,6 +52,7 @@ object RotationLock : Module( } init { + setModulePriority(100) listen { val yaw = when (yawMode) { Mode.Custom -> customYaw diff --git a/src/main/kotlin/com/lambda/util/ServerTPS.kt b/src/main/kotlin/com/lambda/util/ServerTPS.kt index 0bee62dd9..52c66ad01 100644 --- a/src/main/kotlin/com/lambda/util/ServerTPS.kt +++ b/src/main/kotlin/com/lambda/util/ServerTPS.kt @@ -29,7 +29,7 @@ object ServerTPS { private var lastUpdate = 0L init { - listen(priority = 10000) { + listen({ 10000 }) { if (it.packet !is WorldTimeUpdateS2CPacket) return@listen val currentTime = System.currentTimeMillis() diff --git a/src/main/kotlin/com/lambda/util/collections/UpdatableLazy.kt b/src/main/kotlin/com/lambda/util/collections/UpdatableLazy.kt index 382d2265e..452b37aee 100644 --- a/src/main/kotlin/com/lambda/util/collections/UpdatableLazy.kt +++ b/src/main/kotlin/com/lambda/util/collections/UpdatableLazy.kt @@ -21,15 +21,13 @@ package com.lambda.util.collections * A lazy-initialized value holder that allows the stored value to be reset and re-initialized on demand. */ class UpdatableLazy(private val initializer: () -> T) { - private var _value: T? = null + private var backingField: T? = null + + val value: T + get() = backingField ?: initializer().also { backingField = it } - val value: T? - get() { - if (_value == null) _value = initializer() - return _value - } fun update() { - _value = initializer() + backingField = initializer() } }