Skip to content

Commit 2faee16

Browse files
committed
Merge remote-tracking branch 'origin/feature/packetmine-rewrite' into feature/packetmine-rewrite
2 parents 800cd68 + 0f15b30 commit 2faee16

File tree

4 files changed

+69
-27
lines changed

4 files changed

+69
-27
lines changed

common/src/main/kotlin/com/lambda/event/Subscriber.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,14 @@ class Subscriber : ConcurrentHashMap<KClass<out Event>, ConcurrentSkipListSet<Li
3939
inline fun <reified T : Event> subscribe(listener: Listener<T>) =
4040
getOrPut(T::class) { defaultListenerSet }.add(listener)
4141

42+
/**
43+
* Allows a [Listener] to start receiving a specific type of [Event]'s [KClass implementation](KC).
44+
*
45+
* This should only be used in cases where the type of the event is erased.
46+
*/
47+
fun <T : Event> subscribe(kClass: KClass<out T>, listener: Listener<T>) =
48+
getOrPut(kClass) { defaultListenerSet }.add(listener)
49+
4250
/** Allows a [Subscriber] to start receiving all [Event]s of another [Subscriber]. */
4351
infix fun subscribe(subscriber: Subscriber) {
4452
subscriber.forEach { (eventType, listeners) ->
@@ -56,6 +64,7 @@ class Subscriber : ConcurrentHashMap<KClass<out Event>, ConcurrentSkipListSet<Li
5664

5765
/**
5866
* Unsubscribes all listeners associated with the current instance (the caller object).
67+
*
5968
* This method iterates over all values in the `Subscriber`'s map and removes listeners
6069
* whose `owner` property matches the caller object.
6170
*

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

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import kotlinx.coroutines.CoroutineDispatcher
3030
import kotlinx.coroutines.Dispatchers
3131
import kotlin.properties.ReadOnlyProperty
3232
import kotlin.properties.ReadWriteProperty
33+
import kotlin.reflect.KClass
3334
import kotlin.reflect.KProperty
3435

3536

@@ -130,6 +131,51 @@ class SafeListener<T : Event>(
130131
return listener
131132
}
132133

134+
/**
135+
* This function registers a new [SafeListener] for a generic [Event] type [T] with the given [KClass] instance to circumvent type erasure.
136+
* The [function] is executed on the same thread where the [Event] was dispatched.
137+
* The [function] will only be executed when the context satisfies certain safety conditions.
138+
* These conditions are met when none of the following [SafeContext] properties are null:
139+
* - [SafeContext.world]
140+
* - [SafeContext.player]
141+
* - [SafeContext.interaction]
142+
* - [SafeContext.connection]
143+
*
144+
* This typically occurs when the user is in-game.
145+
*
146+
* Usage:
147+
* ```kotlin
148+
* listen(MyEvent::class) { event ->
149+
* player.sendMessage("Event received: $event")
150+
* }
151+
*
152+
* listen(MyEvent::class, priority = 1) { event ->
153+
* player.sendMessage("Event received before the previous listener: $event")
154+
* }
155+
* ```
156+
*
157+
* @param kClass The KClass instance of covariant type [T] used to circumvent type erasure.
158+
* @param T The type of the event to listen for. This should be a subclass of Event.
159+
* @param priority The priority of the listener. Listeners with higher priority will be executed first. The Default value is 0.
160+
* @param alwaysListen If true, the listener will be executed even if it is muted. The Default value is false.
161+
* @param function The function to be executed when the event is posted. This function should take a SafeContext and an event of type T as parameters.
162+
* @return The newly created and registered [SafeListener].
163+
*/
164+
fun <T : Event> Any.listen(
165+
kClass: KClass<out T>,
166+
priority: Int = 0,
167+
alwaysListen: Boolean = false,
168+
function: SafeContext.(T) -> Unit = {},
169+
): SafeListener<T> {
170+
val listener = SafeListener<T>(priority, this, alwaysListen) { event ->
171+
runGameScheduled { function(event) }
172+
}
173+
174+
EventFlow.syncListeners.subscribe(kClass, listener)
175+
176+
return listener
177+
}
178+
133179
/**
134180
* This function registers a new [SafeListener] for a generic [Event] type [T].
135181
* The [predicate] is executed on the same thread where the [Event] was dispatched.
@@ -176,7 +222,7 @@ class SafeListener<T : Event>(
176222
}
177223
}
178224

179-
EventFlow.syncListeners.subscribe<T>(destroyable)
225+
EventFlow.syncListeners.subscribe(destroyable)
180226

181227
return pointer
182228
}
@@ -218,7 +264,7 @@ class SafeListener<T : Event>(
218264
}
219265
}
220266

221-
EventFlow.concurrentListeners.subscribe<T>(listener)
267+
EventFlow.concurrentListeners.subscribe(listener)
222268

223269
return listener
224270
}

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

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ class UnsafeListener<T : Event>(
113113
function(event)
114114
}
115115

116-
EventFlow.syncListeners.subscribe<T>(listener)
116+
EventFlow.syncListeners.subscribe(listener)
117117

118118
return listener
119119
}
@@ -159,7 +159,7 @@ class UnsafeListener<T : Event>(
159159
}
160160
}
161161

162-
EventFlow.syncListeners.subscribe<T>(destroyable)
162+
EventFlow.syncListeners.subscribe(destroyable)
163163

164164
return pointer
165165
}
@@ -202,9 +202,12 @@ class UnsafeListener<T : Event>(
202202
}
203203
}
204204

205-
EventFlow.concurrentListeners.subscribe<T>(listener)
205+
EventFlow.concurrentListeners.subscribe(listener)
206206

207207
return listener
208208
}
209209
}
210+
211+
override fun toString() =
212+
"SafeListener(priority=$priority, owner=${owner::class.simpleName}, alwaysListen=$alwaysListen)"
210213
}

common/src/main/kotlin/com/lambda/interaction/request/RequestHandler.kt

Lines changed: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import com.lambda.event.events.TickEvent
2424
import com.lambda.event.listener.SafeListener.Companion.listen
2525
import com.lambda.interaction.request.ManagerUtils.accumulatedManagerPriority
2626
import com.lambda.threading.runSafe
27+
import kotlin.reflect.KClass
2728

2829
/**
2930
* This class handles requests, offering specific opening times, and an option to queue a request for the
@@ -57,25 +58,7 @@ abstract class RequestHandler<R : Request>(
5758
var activeThisTick = false; protected set
5859

5960
override fun load(): String {
60-
openStages.forEach {
61-
when (it) {
62-
is TickEvent.Pre -> openRequestsFor(it)
63-
is TickEvent.Post -> openRequestsFor(it)
64-
is TickEvent.Network.Pre -> openRequestsFor(it)
65-
is TickEvent.Network.Post -> openRequestsFor(it)
66-
is TickEvent.Input.Pre -> openRequestsFor(it)
67-
is TickEvent.Input.Post -> openRequestsFor(it)
68-
is TickEvent.WorldRender.Pre -> openRequestsFor(it)
69-
is TickEvent.WorldRender.Post -> openRequestsFor(it)
70-
is TickEvent.Sound.Pre -> openRequestsFor(it)
71-
is TickEvent.Sound.Post -> openRequestsFor(it)
72-
is TickEvent.Render.Pre -> openRequestsFor(it)
73-
is TickEvent.Render.Post -> openRequestsFor(it)
74-
is TickEvent.Player.Pre -> openRequestsFor(it)
75-
is TickEvent.Player.Post -> openRequestsFor(it)
76-
else -> throw IllegalArgumentException("Event '$it' is not allowed for requests")
77-
}
78-
}
61+
openStages.forEach { openRequestsFor(it::class, it) }
7962

8063
listen<TickEvent.Post>(Int.MIN_VALUE) {
8164
activeThisTick = false
@@ -87,8 +70,8 @@ abstract class RequestHandler<R : Request>(
8770
/**
8871
* opens the handler for requests for the duration of the given event
8972
*/
90-
private inline fun <reified T : Event> openRequestsFor(stage: T) {
91-
listen<T>(priority = Int.MAX_VALUE - (accumulatedManagerPriority - stagePriority)) {
73+
private inline fun <reified T : Event> openRequestsFor(instance: KClass<out T>, stage: T) {
74+
listen(instance, priority = Int.MAX_VALUE - (accumulatedManagerPriority - stagePriority)) {
9275
tickStage = stage
9376
queuedRequest?.let { request ->
9477
handleRequest(request)
@@ -99,7 +82,8 @@ abstract class RequestHandler<R : Request>(
9982
onOpen?.invoke(this)
10083
preEvent()
10184
}
102-
listen<T>(priority = Int.MIN_VALUE + stagePriority) {
85+
86+
listen(instance, priority = Int.MIN_VALUE + stagePriority) {
10387
onClose?.invoke(this)
10488
acceptingRequests = false
10589
}

0 commit comments

Comments
 (0)