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
|
||||
|
||||
minecraft_version=1.19
|
||||
minecraft_version=1.19.2
|
||||
loom.platform=fabric
|
||||
|
||||
archives_base_name=notenoughupdates
|
||||
@@ -12,7 +13,7 @@ architectury_version=5.10.33
|
||||
fabric_loader_version=0.14.8
|
||||
fabric_api_version=0.58.0+1.19
|
||||
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
|
||||
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.Path
|
||||
import kotlin.coroutines.EmptyCoroutineContext
|
||||
import moe.nea.notenoughupdates.features.FeatureManager
|
||||
|
||||
object NotEnoughUpdates : ModInitializer, ClientModInitializer {
|
||||
const val MOD_ID = "notenoughupdates"
|
||||
@@ -71,8 +72,9 @@ object NotEnoughUpdates : ModInitializer, ClientModInitializer {
|
||||
override fun onInitialize() {
|
||||
dbusConnection.requestBusName("moe.nea.notenoughupdates")
|
||||
dbusConnection.exportObject(NEUDbusObject)
|
||||
RepoManager.initialize()
|
||||
ConfigHolder.registerEvents()
|
||||
RepoManager.initialize()
|
||||
FeatureManager.autoload()
|
||||
ClientCommandRegistrationCallback.EVENT.register(this::registerCommands)
|
||||
ClientLifecycleEvents.CLIENT_STOPPING.register(ClientLifecycleEvents.ClientStopping {
|
||||
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
|
||||
|
||||
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.injection.At
|
||||
import org.spongepowered.asm.mixin.injection.Inject
|
||||
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")
|
||||
@Mixin(MinecraftClient::class)
|
||||
class MixinMinecraft {
|
||||
@Inject(method = ["setScreen"], at = [At("HEAD")], cancellable = true)
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ object RepoDownloadManager {
|
||||
return@withContext false
|
||||
}
|
||||
val currentSha = loadSavedVersionHash()
|
||||
if (latestSha != currentSha) {
|
||||
if (latestSha != currentSha || force) {
|
||||
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")
|
||||
val zipFile = downloadGithubArchive(requestUrl)
|
||||
|
||||
@@ -1,21 +1,20 @@
|
||||
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.nio.file.Path
|
||||
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.readText
|
||||
import kotlin.io.path.writeText
|
||||
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>(
|
||||
val serializer: KSerializer<T>,
|
||||
@@ -108,7 +107,7 @@ abstract class ConfigHolder<T>(
|
||||
player.sendMessage(
|
||||
Text.literal(
|
||||
"The following configs have been reset: ${badLoads.joinToString(", ")}. " +
|
||||
"This can be intentional, but probably isn't."
|
||||
"This can be intentional, but probably isn't."
|
||||
)
|
||||
)
|
||||
badLoads.clear()
|
||||
@@ -116,14 +115,13 @@ abstract class ConfigHolder<T>(
|
||||
}
|
||||
|
||||
fun registerEvents() {
|
||||
NEUScreenEvents.SCREEN_OPEN.register(NEUScreenEvents.OnScreenOpen { old, new ->
|
||||
ScreenOpenEvent.subscribe { event ->
|
||||
performSaves()
|
||||
val p = MinecraftClient.getInstance().player
|
||||
if (p != null) {
|
||||
warnForResetConfigs(p)
|
||||
}
|
||||
false
|
||||
})
|
||||
}
|
||||
ClientLifecycleEvents.CLIENT_STOPPING.register(ClientLifecycleEvents.ClientStopping {
|
||||
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