Skip to content

Commit 71dbb3f

Browse files
committed
mutable module priority setting and event flow modification to update listener sorting
1 parent e7906ce commit 71dbb3f

34 files changed

+114
-82
lines changed

src/main/java/com/lambda/mixin/MinecraftClientMixin.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ void onNetwork(ClientPlayerInteractionManager instance, Operation<Void> original
9595

9696
@Definition(id = "overlay", field = "Lnet/minecraft/client/MinecraftClient;overlay:Lnet/minecraft/client/gui/screen/Overlay;")
9797
@Expression("this.overlay == null")
98-
@ModifyExpressionValue(method = "tick", at = @At("MIXINEXTRAS:EXPRESSION"))
98+
@ModifyExpressionValue(method = "tick", at = @At(value = "MIXINEXTRAS:EXPRESSION", ordinal = 1))
9999
private boolean modifyCurrentScreenNullCheck(boolean original) {
100100
if (!original || this.currentScreen != null) {
101101
EventFlow.post(TickEvent.Input.Pre.INSTANCE);

src/main/kotlin/com/lambda/Lambda.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ package com.lambda
1919

2020
import com.google.gson.Gson
2121
import com.google.gson.GsonBuilder
22-
import com.lambda.config.serializer.BlockPosCodec
2322
import com.lambda.config.serializer.BlockCodec
23+
import com.lambda.config.serializer.BlockPosCodec
2424
import com.lambda.config.serializer.ColorSerializer
2525
import com.lambda.config.serializer.GameProfileCodec
2626
import com.lambda.config.serializer.ItemCodec
@@ -45,7 +45,6 @@ import net.minecraft.item.Item
4545
import net.minecraft.item.ItemStack
4646
import net.minecraft.item.PotionItem
4747
import net.minecraft.item.RangedWeaponItem
48-
import net.minecraft.registry.DynamicRegistryManager
4948
import net.minecraft.text.Text
5049
import net.minecraft.util.math.BlockPos
5150
import org.apache.logging.log4j.LogManager
@@ -92,7 +91,7 @@ object Lambda : ClientModInitializer {
9291

9392
init {
9493
// We want the opengl context to be created
95-
listenOnceUnsafe<ClientEvent.Startup>(priority = Int.MAX_VALUE) {
94+
listenOnceUnsafe<ClientEvent.Startup>({ Int.MAX_VALUE }) {
9695
LOG.info("$MOD_NAME $VERSION initialized in ${Loader.initialize()} ms\n")
9796
if (ClickGuiLayout.setLambdaWindowIcon) setLambdaWindowIcon()
9897
true

src/main/kotlin/com/lambda/config/Configuration.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ abstract class Configuration : Jsonable, Loadable {
6565
get() = File("${primary.parent}/${primary.nameWithoutExtension}-backup.${primary.extension}")
6666

6767
override fun load(): String {
68-
listenUnsafe<ClientEvent.Shutdown>(Int.MIN_VALUE) { trySave() }
68+
listenUnsafe<ClientEvent.Shutdown>({ Int.MIN_VALUE }) { trySave() }
6969
register()
7070
return super.load()
7171
}

src/main/kotlin/com/lambda/config/Setting.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,7 @@ import kotlin.reflect.KProperty
9090
* ```
9191
*
9292
* @property defaultValue The default value of the setting.
93-
* @property description A description of the setting.
9493
* @property type The type reflection of the setting.
95-
* @property visibility A function that determines whether the setting is visible.
9694
*/
9795
abstract class SettingCore<T>(
9896
var defaultValue: T,

src/main/kotlin/com/lambda/config/UserAutomationConfig.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import com.lambda.module.Module
2424
import com.lambda.module.ModuleRegistry.moduleNameMap
2525

2626
class UserAutomationConfig(override val name: String) : AutomationConfig(name, UserAutomationConfigs) {
27-
val linkedModules = setting<String>("Linked Modules", emptySet(), moduleNameMap.filter { it.value.defaultAutomationConfig != Companion.DEFAULT }.keys)
27+
val linkedModules = setting<String>("Linked Modules", emptySet(), moduleNameMap.filter { it.value.defaultAutomationConfig != Companion.DEFAULT }.keys) { false }
2828
.onSelect { name ->
2929
moduleNameMap[name]?.let {
3030
it.removeLink()

src/main/kotlin/com/lambda/event/EventFlow.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,17 @@ object EventFlow {
9797
concurrentListeners.unsubscribe(this)
9898
}
9999

100+
fun Any.updateListenerSorting() {
101+
syncListeners.values.forEach { listeners ->
102+
val matching = listeners.filter { it.owner === this }
103+
matching.forEach { !listeners.remove(it); it.priority.update(); listeners.add(it) }
104+
}
105+
concurrentListeners.values.forEach { listeners ->
106+
val matching = listeners.filter { it.owner === this }
107+
matching.forEach { listeners.remove(it); it.priority.update(); listeners.add(it) }
108+
}
109+
}
110+
100111
init {
101112
// parallel event execution on dedicated threads
102113
runConcurrent {

src/main/kotlin/com/lambda/event/listener/Listener.kt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import com.lambda.event.Event
2121
import com.lambda.event.EventFlow
2222
import com.lambda.event.Muteable
2323
import com.lambda.module.Module
24+
import com.lambda.util.collections.UpdatableLazy
2425

2526
/**
2627
* An abstract class representing a [Listener] in the [Event] system ([EventFlow]).
@@ -45,7 +46,7 @@ import com.lambda.module.Module
4546
* @property alwaysListen If true, the [Listener] will always be triggered, even if the [owner] is [Muteable.isMuted].
4647
*/
4748
abstract class Listener<T : Event> : Comparable<Listener<T>> {
48-
abstract val priority: Int
49+
abstract val priority: UpdatableLazy<Int>
4950
abstract val owner: Any
5051
abstract val alwaysListen: Boolean
5152

@@ -61,10 +62,13 @@ abstract class Listener<T : Event> : Comparable<Listener<T>> {
6162

6263
companion object {
6364
val comparator = compareBy<Listener<out Event>> {
64-
it.priority
65+
it.priority.value
6566
}.thenBy {
6667
// Hashcode is needed because ConcurrentSkipListSet handles insertion based on compareTo
6768
it.hashCode()
6869
}
70+
71+
val Any.modulePriorityOr0Getter
72+
get() = (this as? Module)?.let { { prioritySetting.value } } ?: { 0 }
6973
}
7074
}

src/main/kotlin/com/lambda/event/listener/SafeListener.kt

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import com.lambda.threading.runConcurrent
2525
import com.lambda.threading.runGameScheduled
2626
import com.lambda.threading.runSafe
2727
import com.lambda.util.Pointer
28+
import com.lambda.util.collections.updatableLazy
2829
import com.lambda.util.selfReference
2930
import kotlinx.coroutines.CoroutineDispatcher
3031
import kotlinx.coroutines.Dispatchers
@@ -62,11 +63,13 @@ import kotlin.reflect.KProperty
6263
* @property function The function to be executed when the event occurs. This function operates within a [SafeContext].
6364
*/
6465
class SafeListener<T : Event>(
65-
override val priority: Int = 0,
66+
priorityProvider: () -> Int,
6667
override val owner: Any,
6768
override val alwaysListen: Boolean = false,
6869
val function: SafeContext.(T) -> Unit
6970
) : Listener<T>(), ReadOnlyProperty<Any?, T?> {
71+
override val priority = updatableLazy(priorityProvider)
72+
7073
/**
7174
* The last processed event signal.
7275
*/
@@ -118,7 +121,7 @@ class SafeListener<T : Event>(
118121
* @return The newly created and registered [SafeListener].
119122
*/
120123
inline fun <reified T : Event> Any.listen(
121-
priority: Int = 0,
124+
noinline priority: () -> Int = modulePriorityOr0Getter,
122125
alwaysListen: Boolean = false,
123126
noinline function: SafeContext.(T) -> Unit = {}
124127
): SafeListener<T> {
@@ -163,7 +166,7 @@ class SafeListener<T : Event>(
163166
*/
164167
fun <T : Event> Any.listen(
165168
kClass: KClass<out T>,
166-
priority: Int = 0,
169+
priority: () -> Int = modulePriorityOr0Getter,
167170
alwaysListen: Boolean = false,
168171
function: SafeContext.(T) -> Unit = {},
169172
): SafeListener<T> {
@@ -205,7 +208,7 @@ class SafeListener<T : Event>(
205208
* @return The newly created and registered [SafeListener].
206209
*/
207210
inline fun <reified T : Event> Any.listenOnce(
208-
priority: Int = 0,
211+
noinline priority: () -> Int = modulePriorityOr0Getter,
209212
alwaysListen: Boolean = false,
210213
noinline predicate: SafeContext.(T) -> Boolean = { true },
211214
): ReadWriteProperty<Any?, T?> {
@@ -253,7 +256,7 @@ class SafeListener<T : Event>(
253256
* @return The newly created and registered [SafeListener].
254257
*/
255258
inline fun <reified T : Event> Any.listenConcurrently(
256-
priority: Int = 0,
259+
noinline priority: () -> Int = modulePriorityOr0Getter,
257260
alwaysListen: Boolean = false,
258261
scheduler: CoroutineDispatcher = Dispatchers.Default,
259262
noinline function: suspend SafeContext.(T) -> Unit = {},

src/main/kotlin/com/lambda/event/listener/UnsafeListener.kt

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import com.lambda.event.listener.SafeListener.Companion.listenConcurrently
2525
import com.lambda.event.listener.SafeListener.Companion.listenOnce
2626
import com.lambda.threading.runConcurrent
2727
import com.lambda.util.Pointer
28+
import com.lambda.util.collections.updatableLazy
2829
import com.lambda.util.selfReference
2930
import kotlinx.coroutines.CoroutineDispatcher
3031
import kotlinx.coroutines.Dispatchers
@@ -60,11 +61,13 @@ import kotlin.reflect.KProperty
6061
* @property function The function to be executed when the event occurs. This function operates without a [SafeContext].
6162
*/
6263
class UnsafeListener<T : Event>(
63-
override val priority: Int,
64+
priorityProvider: () -> Int,
6465
override val owner: Any,
6566
override val alwaysListen: Boolean = false,
6667
val function: (T) -> Unit,
6768
) : Listener<T>(), ReadOnlyProperty<Any?, T?> {
69+
override val priority = updatableLazy(priorityProvider)
70+
6871
/**
6972
* The last processed event signal.
7073
*/
@@ -107,7 +110,7 @@ class UnsafeListener<T : Event>(
107110
* @return The newly created and registered [UnsafeListener].
108111
*/
109112
inline fun <reified T : Event> Any.listenUnsafe(
110-
priority: Int = 0,
113+
noinline priority: () -> Int = modulePriorityOr0Getter,
111114
alwaysListen: Boolean = false,
112115
noinline function: (T) -> Unit = {},
113116
): UnsafeListener<T> {
@@ -144,7 +147,7 @@ class UnsafeListener<T : Event>(
144147
* @return The newly created and registered [UnsafeListener].
145148
*/
146149
inline fun <reified T : Event> Any.listenOnceUnsafe(
147-
priority: Int = 0,
150+
noinline priority: () -> Int = modulePriorityOr0Getter,
148151
alwaysListen: Boolean = false,
149152
noinline function: (T) -> Boolean = { true },
150153
): ReadWriteProperty<Any?, T?> {
@@ -193,7 +196,7 @@ class UnsafeListener<T : Event>(
193196
* @return The newly created and registered [UnsafeListener].
194197
*/
195198
inline fun <reified T : Event> Any.listenConcurrentlyUnsafe(
196-
priority: Int = 0,
199+
noinline priority: () -> Int = modulePriorityOr0Getter,
197200
alwaysListen: Boolean = false,
198201
scheduler: CoroutineDispatcher = Dispatchers.Default,
199202
noinline function: suspend (T) -> Unit = {},

src/main/kotlin/com/lambda/gui/components/SettingsWidget.kt

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,19 @@ object SettingsWidget {
3737
fun ImGuiBuilder.buildConfigSettingsContext(config: Configurable) {
3838
group {
3939
if (config is Module) {
40-
with(config.keybindSetting) { buildLayout() }
41-
with(config.disableOnReleaseSetting) { buildLayout() }
42-
with(config.drawSetting) { buildLayout() }
43-
}
44-
smallButton("Reset") {
45-
config.settings.forEach { it.reset(silent = true) }
40+
button("Module Settings") {
41+
ImGui.openPopup("##module-settings-popup-${config.name}")
42+
}
43+
ImGui.setNextWindowSizeConstraints(0f, 0f, Float.MAX_VALUE, io.displaySize.y * 0.5f)
44+
popupContextItem("##module-settings-popup-${config.name}", ImGuiPopupFlags.None) {
45+
with(config.keybindSetting) { buildLayout() }
46+
with(config.prioritySetting) { buildLayout() }
47+
with(config.disableOnReleaseSetting) { buildLayout() }
48+
with(config.drawSetting) { buildLayout() }
49+
smallButton("Reset") {
50+
config.settings.forEach { it.reset(silent = true) }
51+
}
52+
}
4653
}
4754
lambdaTooltip("Resets all settings for this module to their default values")
4855
if (config is MutableAutomationConfig && config.automationConfig !== AutomationConfig.Companion.DEFAULT) {
@@ -74,13 +81,8 @@ object SettingsWidget {
7481
}
7582
}
7683
}
77-
val toIgnoreSettings =
78-
when (config) {
79-
is Module -> setOf(config.keybindSetting, config.disableOnReleaseSetting, config.drawSetting)
80-
is UserAutomationConfig -> setOf(config.linkedModules)
81-
else -> emptySet()
82-
}
83-
val visibleSettings = config.settings.filter { it.visibility() } - toIgnoreSettings
84+
85+
val visibleSettings = config.settings.filter { it.visibility() }
8486
if (visibleSettings.isEmpty()) return
8587
else separator()
8688
val (grouped, ungrouped) = visibleSettings.partition { it.groups.isNotEmpty() }

0 commit comments

Comments
 (0)