aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/at/hannibal2/skyhanni/events/LorenzEvent.kt
blob: aaaa1dd2ed733040ac76c6cc53f0b1383f1fc121 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
package at.hannibal2.skyhanni.events

import at.hannibal2.skyhanni.data.EventCounter
import at.hannibal2.skyhanni.mixins.hooks.getValue
import at.hannibal2.skyhanni.mixins.hooks.setValue
import at.hannibal2.skyhanni.mixins.transformers.AccessorEventBus
import at.hannibal2.skyhanni.test.command.ErrorManager
import at.hannibal2.skyhanni.utils.ChatUtils
import at.hannibal2.skyhanni.utils.LorenzUtils
import net.minecraftforge.common.MinecraftForge
import net.minecraftforge.fml.common.eventhandler.Event
import net.minecraftforge.fml.common.eventhandler.IEventListener

abstract class LorenzEvent : Event() {

    private val eventName by lazy {
        this::class.simpleName!!
    }

    fun postAndCatch() = postAndCatchAndBlock {}

    companion object {

        var eventHandlerDepth by object : ThreadLocal<Int>() {
            override fun initialValue(): Int {
                return 0
            }
        }
        val isInGuardedEventHandler get() = eventHandlerDepth > 0 || LorenzUtils.isInDevEnvironment()
    }

    fun postAndCatchAndBlock(
        printError: Boolean = true,
        stopOnFirstError: Boolean = false,
        ignoreErrorCache: Boolean = false,
        onError: (Throwable) -> Unit,
    ): Boolean {
        EventCounter.count(eventName)
        val visibleErrors = 3
        var errors = 0
        eventHandlerDepth++
        for (listener in getListeners()) {
            try {
                listener.invoke(this)
            } catch (throwable: Throwable) {
                errors++
                if (printError && errors <= visibleErrors) {
                    val callerName = listener.toString().split(" ")[1].split("@")[0].split(".").last()
                    val errorName = throwable::class.simpleName ?: "error"
                    val message = "Caught an $errorName in $callerName at $eventName: ${throwable.message}"
                    ErrorManager.logErrorWithData(throwable, message, ignoreErrorCache = ignoreErrorCache)
                }
                onError(throwable)
                if (stopOnFirstError) break
            }
        }
        eventHandlerDepth--
        if (errors > visibleErrors) {
            val hiddenErrors = errors - visibleErrors
            ChatUtils.error("$hiddenErrors more errors in $eventName are hidden!")
        }
        return if (isCancelable) isCanceled else false
    }

    private fun getListeners(): Array<out IEventListener> {
        val accessorEventBus = MinecraftForge.EVENT_BUS as AccessorEventBus
        return listenerList.getListeners(accessorEventBus.busId)
    }

    fun postWithoutCatch() = MinecraftForge.EVENT_BUS.post(this)

    // TODO let walker use this function for all 101 other uses
    fun cancel() {
        isCanceled = true
    }
}