Move Eventhandling around.
I still want to use fabric still "array backed" events, but these here are just a bit easier to use from kotlin.
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
|
# suppress inspection "UnusedProperty" for whole file
|
||||||
org.gradle.jvmargs=-Xmx4096M
|
org.gradle.jvmargs=-Xmx4096M
|
||||||
|
|
||||||
minecraft_version=1.19
|
minecraft_version=1.19.2
|
||||||
loom.platform=fabric
|
loom.platform=fabric
|
||||||
|
|
||||||
archives_base_name=notenoughupdates
|
archives_base_name=notenoughupdates
|
||||||
@@ -12,7 +13,7 @@ architectury_version=5.10.33
|
|||||||
fabric_loader_version=0.14.8
|
fabric_loader_version=0.14.8
|
||||||
fabric_api_version=0.58.0+1.19
|
fabric_api_version=0.58.0+1.19
|
||||||
fabric_kotlin_version=1.8.2+kotlin.1.7.10
|
fabric_kotlin_version=1.8.2+kotlin.1.7.10
|
||||||
yarn_version=1.19.2+build.8
|
yarn_version=1.19.2+build.9
|
||||||
|
|
||||||
libgui_version=6.0.0+1.19
|
libgui_version=6.0.0+1.19
|
||||||
rei_version=9.1.518
|
rei_version=9.1.518
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import org.freedesktop.dbus.connections.impl.DBusConnectionBuilder
|
|||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import kotlin.coroutines.EmptyCoroutineContext
|
import kotlin.coroutines.EmptyCoroutineContext
|
||||||
|
import moe.nea.notenoughupdates.features.FeatureManager
|
||||||
|
|
||||||
object NotEnoughUpdates : ModInitializer, ClientModInitializer {
|
object NotEnoughUpdates : ModInitializer, ClientModInitializer {
|
||||||
const val MOD_ID = "notenoughupdates"
|
const val MOD_ID = "notenoughupdates"
|
||||||
@@ -71,8 +72,9 @@ object NotEnoughUpdates : ModInitializer, ClientModInitializer {
|
|||||||
override fun onInitialize() {
|
override fun onInitialize() {
|
||||||
dbusConnection.requestBusName("moe.nea.notenoughupdates")
|
dbusConnection.requestBusName("moe.nea.notenoughupdates")
|
||||||
dbusConnection.exportObject(NEUDbusObject)
|
dbusConnection.exportObject(NEUDbusObject)
|
||||||
RepoManager.initialize()
|
|
||||||
ConfigHolder.registerEvents()
|
ConfigHolder.registerEvents()
|
||||||
|
RepoManager.initialize()
|
||||||
|
FeatureManager.autoload()
|
||||||
ClientCommandRegistrationCallback.EVENT.register(this::registerCommands)
|
ClientCommandRegistrationCallback.EVENT.register(this::registerCommands)
|
||||||
ClientLifecycleEvents.CLIENT_STOPPING.register(ClientLifecycleEvents.ClientStopping {
|
ClientLifecycleEvents.CLIENT_STOPPING.register(ClientLifecycleEvents.ClientStopping {
|
||||||
runBlocking {
|
runBlocking {
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package moe.nea.notenoughupdates.events
|
||||||
|
|
||||||
|
abstract class NEUEvent {
|
||||||
|
abstract class Cancellable : NEUEvent() {
|
||||||
|
var cancelled: Boolean = false
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package moe.nea.notenoughupdates.events
|
||||||
|
|
||||||
|
import java.util.concurrent.CopyOnWriteArrayList
|
||||||
|
|
||||||
|
open class NEUEventBus<T : NEUEvent> {
|
||||||
|
data class Handler<T>(val invocation: (T) -> Unit, val receivesCancelled: Boolean)
|
||||||
|
|
||||||
|
private val toHandle: MutableList<Handler<T>> = CopyOnWriteArrayList()
|
||||||
|
fun subscribe(handle: (T) -> Unit) {
|
||||||
|
subscribe(handle, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun subscribe(handle: (T) -> Unit, receivesCancelled: Boolean) {
|
||||||
|
toHandle.add(Handler(handle, receivesCancelled))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun publish(event: T): T {
|
||||||
|
for (function in toHandle) {
|
||||||
|
if (function.receivesCancelled || event !is NEUEvent.Cancellable || !event.cancelled) {
|
||||||
|
function.invocation(event)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return event
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
package moe.nea.notenoughupdates.events
|
|
||||||
|
|
||||||
import moe.nea.notenoughupdates.events.NEUScreenEvents.OnScreenOpen
|
|
||||||
import net.fabricmc.fabric.api.event.EventFactory
|
|
||||||
import net.minecraft.client.gui.screen.Screen
|
|
||||||
import net.minecraft.client.MinecraftClient
|
|
||||||
|
|
||||||
object NEUScreenEvents {
|
|
||||||
fun interface OnScreenOpen {
|
|
||||||
/**
|
|
||||||
* Called when a new Screen is opened via [MinecraftClient.setScreen]. If [new] is null, this corresponds to closing a [Screen].
|
|
||||||
* @return true to prevent this event from happening.
|
|
||||||
*/
|
|
||||||
fun onScreenOpen(old: Screen?, new: Screen?): Boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
val SCREEN_OPEN = EventFactory.createArrayBacked(OnScreenOpen::class.java) { arr ->
|
|
||||||
OnScreenOpen { old, new ->
|
|
||||||
return@OnScreenOpen arr.asSequence().any { it.onScreenOpen(old, new) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package moe.nea.notenoughupdates.events
|
||||||
|
|
||||||
|
import net.minecraft.client.gui.screen.Screen
|
||||||
|
|
||||||
|
data class ScreenOpenEvent(val old: Screen?, val new: Screen?) : NEUEvent.Cancellable() {
|
||||||
|
companion object : NEUEventBus<ScreenOpenEvent>()
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package moe.nea.notenoughupdates.features
|
||||||
|
|
||||||
|
import kotlinx.serialization.serializer
|
||||||
|
import moe.nea.notenoughupdates.NotEnoughUpdates
|
||||||
|
import moe.nea.notenoughupdates.features.world.FairySouls
|
||||||
|
import moe.nea.notenoughupdates.util.ConfigHolder
|
||||||
|
|
||||||
|
object FeatureManager : ConfigHolder<FeatureManager.Config>(serializer(), "features", ::Config) {
|
||||||
|
data class Config(
|
||||||
|
val enabledFeatures: MutableMap<String, Boolean> = mutableMapOf()
|
||||||
|
)
|
||||||
|
|
||||||
|
private val features = mutableMapOf<String, NEUFeature>()
|
||||||
|
|
||||||
|
fun autoload() {
|
||||||
|
loadFeature(FairySouls)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun loadFeature(feature: NEUFeature) {
|
||||||
|
if (feature.identifier in features) {
|
||||||
|
NotEnoughUpdates.logger.error("Double registering feature ${feature.identifier}. Ignoring second instance $feature")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
features[feature.identifier] = feature
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isEnabled(identifier: String): Boolean? =
|
||||||
|
config.enabledFeatures[identifier]
|
||||||
|
|
||||||
|
|
||||||
|
fun setEnabled(identifier: String, value: Boolean) {
|
||||||
|
config.enabledFeatures[identifier] = value
|
||||||
|
markDirty()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package moe.nea.notenoughupdates.features
|
||||||
|
|
||||||
|
interface NEUFeature {
|
||||||
|
val name: String
|
||||||
|
val identifier: String
|
||||||
|
val defaultEnabled: Boolean
|
||||||
|
get() = true
|
||||||
|
var isEnabled: Boolean
|
||||||
|
get() = FeatureManager.isEnabled(identifier) ?: defaultEnabled
|
||||||
|
set(value) {
|
||||||
|
FeatureManager.setEnabled(identifier, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onLoad()
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package moe.nea.notenoughupdates.features.world
|
||||||
|
|
||||||
|
import moe.nea.notenoughupdates.features.NEUFeature
|
||||||
|
|
||||||
|
object FairySouls : NEUFeature {
|
||||||
|
override val name: String get() = "Fairy Souls"
|
||||||
|
override val identifier: String get() = "fairy-souls"
|
||||||
|
|
||||||
|
override fun onLoad() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,19 +1,20 @@
|
|||||||
package moe.nea.notenoughupdates.mixins
|
package moe.nea.notenoughupdates.mixins
|
||||||
|
|
||||||
import moe.nea.notenoughupdates.events.NEUScreenEvents
|
|
||||||
import net.minecraft.client.MinecraftClient
|
|
||||||
import net.minecraft.client.gui.screen.Screen
|
|
||||||
import org.spongepowered.asm.mixin.Mixin
|
import org.spongepowered.asm.mixin.Mixin
|
||||||
import org.spongepowered.asm.mixin.injection.At
|
import org.spongepowered.asm.mixin.injection.At
|
||||||
import org.spongepowered.asm.mixin.injection.Inject
|
import org.spongepowered.asm.mixin.injection.Inject
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo
|
||||||
|
import net.minecraft.client.MinecraftClient
|
||||||
|
import net.minecraft.client.gui.screen.Screen
|
||||||
|
import moe.nea.notenoughupdates.events.ScreenOpenEvent
|
||||||
|
|
||||||
@Suppress("CAST_NEVER_SUCCEEDS")
|
@Suppress("CAST_NEVER_SUCCEEDS")
|
||||||
@Mixin(MinecraftClient::class)
|
@Mixin(MinecraftClient::class)
|
||||||
class MixinMinecraft {
|
class MixinMinecraft {
|
||||||
@Inject(method = ["setScreen"], at = [At("HEAD")], cancellable = true)
|
@Inject(method = ["setScreen"], at = [At("HEAD")], cancellable = true)
|
||||||
fun onScreenChange(screen: Screen?, ci: CallbackInfo) {
|
fun onScreenChange(screen: Screen?, ci: CallbackInfo) {
|
||||||
if (NEUScreenEvents.SCREEN_OPEN.invoker().onScreenOpen((this as MinecraftClient).currentScreen, screen))
|
val event = ScreenOpenEvent((this as MinecraftClient).currentScreen, screen)
|
||||||
|
if (ScreenOpenEvent.publish(event).cancelled)
|
||||||
ci.cancel()
|
ci.cancel()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ object RepoDownloadManager {
|
|||||||
return@withContext false
|
return@withContext false
|
||||||
}
|
}
|
||||||
val currentSha = loadSavedVersionHash()
|
val currentSha = loadSavedVersionHash()
|
||||||
if (latestSha != currentSha) {
|
if (latestSha != currentSha || force) {
|
||||||
val requestUrl = "https://github.com/${RepoManager.config.user}/${RepoManager.config.repo}/archive/$latestSha.zip"
|
val requestUrl = "https://github.com/${RepoManager.config.user}/${RepoManager.config.repo}/archive/$latestSha.zip"
|
||||||
logger.info("Planning to upgrade repository from $currentSha to $latestSha from $requestUrl")
|
logger.info("Planning to upgrade repository from $currentSha to $latestSha from $requestUrl")
|
||||||
val zipFile = downloadGithubArchive(requestUrl)
|
val zipFile = downloadGithubArchive(requestUrl)
|
||||||
|
|||||||
@@ -1,21 +1,20 @@
|
|||||||
package moe.nea.notenoughupdates.util
|
package moe.nea.notenoughupdates.util
|
||||||
|
|
||||||
import kotlinx.serialization.KSerializer
|
|
||||||
import kotlinx.serialization.SerializationException
|
|
||||||
import moe.nea.notenoughupdates.NotEnoughUpdates
|
|
||||||
import moe.nea.notenoughupdates.events.NEUScreenEvents
|
|
||||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents
|
|
||||||
import net.minecraft.client.MinecraftClient
|
|
||||||
import net.minecraft.command.CommandSource
|
|
||||||
import net.minecraft.server.command.CommandOutput
|
|
||||||
import net.minecraft.text.Text
|
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.util.concurrent.CopyOnWriteArrayList
|
import java.util.concurrent.CopyOnWriteArrayList
|
||||||
|
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents
|
||||||
|
import kotlinx.serialization.KSerializer
|
||||||
|
import kotlinx.serialization.SerializationException
|
||||||
import kotlin.io.path.exists
|
import kotlin.io.path.exists
|
||||||
import kotlin.io.path.readText
|
import kotlin.io.path.readText
|
||||||
import kotlin.io.path.writeText
|
import kotlin.io.path.writeText
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
import net.minecraft.client.MinecraftClient
|
||||||
|
import net.minecraft.server.command.CommandOutput
|
||||||
|
import net.minecraft.text.Text
|
||||||
|
import moe.nea.notenoughupdates.NotEnoughUpdates
|
||||||
|
import moe.nea.notenoughupdates.events.ScreenOpenEvent
|
||||||
|
|
||||||
abstract class ConfigHolder<T>(
|
abstract class ConfigHolder<T>(
|
||||||
val serializer: KSerializer<T>,
|
val serializer: KSerializer<T>,
|
||||||
@@ -116,14 +115,13 @@ abstract class ConfigHolder<T>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun registerEvents() {
|
fun registerEvents() {
|
||||||
NEUScreenEvents.SCREEN_OPEN.register(NEUScreenEvents.OnScreenOpen { old, new ->
|
ScreenOpenEvent.subscribe { event ->
|
||||||
performSaves()
|
performSaves()
|
||||||
val p = MinecraftClient.getInstance().player
|
val p = MinecraftClient.getInstance().player
|
||||||
if (p != null) {
|
if (p != null) {
|
||||||
warnForResetConfigs(p)
|
warnForResetConfigs(p)
|
||||||
}
|
}
|
||||||
false
|
}
|
||||||
})
|
|
||||||
ClientLifecycleEvents.CLIENT_STOPPING.register(ClientLifecycleEvents.ClientStopping {
|
ClientLifecycleEvents.CLIENT_STOPPING.register(ClientLifecycleEvents.ClientStopping {
|
||||||
performSaves()
|
performSaves()
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package moe.nea.notenoughupdates.util
|
||||||
|
|
||||||
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
|
import kotlinx.coroutines.Runnable
|
||||||
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
import net.minecraft.client.MinecraftClient
|
||||||
|
|
||||||
|
object MinecraftDispatcher : CoroutineDispatcher() {
|
||||||
|
@ExperimentalCoroutinesApi
|
||||||
|
override fun limitedParallelism(parallelism: Int): CoroutineDispatcher {
|
||||||
|
throw UnsupportedOperationException("limitedParallelism is not supported for MinecraftDispatcher")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isDispatchNeeded(context: CoroutineContext): Boolean =
|
||||||
|
!MinecraftClient.getInstance().isOnThread
|
||||||
|
|
||||||
|
|
||||||
|
override fun dispatch(context: CoroutineContext, block: Runnable) {
|
||||||
|
MinecraftClient.getInstance().execute(block)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user