eros: replace some javafx custom stuff with events

This commit is contained in:
Bixilon 2021-07-27 20:22:44 +02:00
parent ce4b5e0352
commit c8ef47f56a
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
23 changed files with 120 additions and 47 deletions

View File

@ -47,10 +47,12 @@ import de.bixilon.minosoft.util.task.worker.tasks.Task
object Minosoft {
val MINOSOFT_ASSETS_MANAGER = JarAssetsManager(Minosoft::class.java, mutableSetOf("minosoft"))
val MINECRAFT_FALLBACK_ASSETS_MANAGER = JarAssetsManager(Minosoft::class.java, mutableSetOf("minecraft"))
val GLOBAL_EVENT_MASTER = GlobalEventMaster()
val LANGUAGE_MANAGER = MultiLanguageManager()
val START_UP_LATCH = CountUpAndDownLatch(1)
@Deprecated("Use singleton interface!")
val GLOBAL_EVENT_MASTER = GlobalEventMaster
@Deprecated("Will be singleton interface")
lateinit var config: Configuration

View File

@ -14,9 +14,9 @@
package de.bixilon.minosoft.config.config.account
import com.squareup.moshi.Json
import de.bixilon.minosoft.Minosoft
import de.bixilon.minosoft.data.accounts.Account
import de.bixilon.minosoft.modding.event.events.account.AccountSelectEvent
import de.bixilon.minosoft.modding.event.master.GlobalEventMaster
import java.util.*
data class AccountConfig(
@ -28,7 +28,7 @@ data class AccountConfig(
var selected: Account? = null
get() = entries[selectedAccountId]
set(value) {
Minosoft.GLOBAL_EVENT_MASTER.fireEvent(AccountSelectEvent(selected, value))
GlobalEventMaster.fireEvent(AccountSelectEvent(selected, value))
field // To allow transient for moshi
selectedAccountId = value?.id
}

View File

@ -13,11 +13,11 @@
package de.bixilon.minosoft.gui.eros
import de.bixilon.minosoft.Minosoft
import de.bixilon.minosoft.gui.eros.main.MainErosController
import de.bixilon.minosoft.gui.eros.util.JavaFXUtil
import de.bixilon.minosoft.modding.event.events.FinishInitializingEvent
import de.bixilon.minosoft.modding.event.invoker.CallbackEventInvoker
import de.bixilon.minosoft.modding.event.master.GlobalEventMaster
import de.bixilon.minosoft.util.KUtil.asResourceLocation
import javafx.application.Platform
@ -29,7 +29,7 @@ object Eros {
init {
Minosoft.GLOBAL_EVENT_MASTER.registerEvent(CallbackEventInvoker.of<FinishInitializingEvent> {
GlobalEventMaster.registerEvent(CallbackEventInvoker.of<FinishInitializingEvent> {
Platform.runLater {
mainErosController = JavaFXUtil.openModal(TITLE, LAYOUT)
mainErosController.stage.show()

View File

@ -13,7 +13,9 @@
package de.bixilon.minosoft.gui.eros.controller
import de.bixilon.minosoft.gui.eros.modding.events.ErosControllerTerminateEvent
import de.bixilon.minosoft.gui.eros.util.JavaFXUtil
import de.bixilon.minosoft.modding.event.master.GlobalEventMaster
import de.bixilon.minosoft.util.KUtil.nullCast
import javafx.event.ActionEvent
import javafx.fxml.Initializable
@ -38,5 +40,7 @@ abstract class JavaFXController : Initializable {
open fun postInit() {}
open fun terminate() {}
open fun terminate() {
GlobalEventMaster.fireEvent(ErosControllerTerminateEvent(this))
}
}

View File

@ -22,6 +22,7 @@ import de.bixilon.minosoft.gui.eros.main.play.PlayMainController
import de.bixilon.minosoft.gui.eros.modding.invoker.JavaFXEventInvoker
import de.bixilon.minosoft.gui.eros.util.JavaFXUtil
import de.bixilon.minosoft.modding.event.events.account.AccountSelectEvent
import de.bixilon.minosoft.modding.event.master.GlobalEventMaster
import de.bixilon.minosoft.util.GitInfo
import de.bixilon.minosoft.util.KUtil.asResourceLocation
import de.bixilon.minosoft.util.KUtil.decide
@ -95,7 +96,7 @@ class MainErosController : JavaFXWindowController() {
contentFX.children.setAll(JavaFXUtil.loadEmbeddedController<PlayMainController>("minosoft:eros/main/play/play.fxml".asResourceLocation()).root)
Minosoft.GLOBAL_EVENT_MASTER.registerEvent(JavaFXEventInvoker.of<AccountSelectEvent> {
GlobalEventMaster.registerEvent(JavaFXEventInvoker.of<AccountSelectEvent> {
accountImageFX.image = JavaFXUtil.MINOSOFT_LOGO // ToDo
accountNameFX.text = it.account?.username
})

View File

@ -19,10 +19,13 @@ import de.bixilon.minosoft.gui.eros.main.play.server.Refreshable
import de.bixilon.minosoft.gui.eros.main.play.server.ServerListController
import de.bixilon.minosoft.gui.eros.main.play.server.type.ServerType
import de.bixilon.minosoft.gui.eros.main.play.server.type.ServerTypeCardController
import de.bixilon.minosoft.gui.eros.modding.events.ErosControllerTerminateEvent
import de.bixilon.minosoft.gui.eros.modding.invoker.JavaFXEventInvoker
import de.bixilon.minosoft.gui.eros.util.JavaFXUtil
import de.bixilon.minosoft.gui.eros.util.JavaFXUtil.text
import de.bixilon.minosoft.modding.event.events.LANServerDiscoverEvent
import de.bixilon.minosoft.modding.event.invoker.EventInvoker
import de.bixilon.minosoft.modding.event.master.GlobalEventMaster
import de.bixilon.minosoft.protocol.protocol.LANServerListener
import de.bixilon.minosoft.util.KUtil.asResourceLocation
import javafx.fxml.FXML
@ -46,27 +49,33 @@ class PlayMainController : EmbeddedJavaFXController<Pane>() {
override fun init() {
playTypeListViewFX.setCellFactory { ServerTypeCardController.build() }
playTypeListViewFX.items += ServerType(FontAwesomeSolid.SERVER, "Custom", "0 Servers", "") {
playTypeListViewFX.items += ServerType(FontAwesomeSolid.SERVER, CUSTOM_SERVER_TYPE, "0 Servers", "") {
return@ServerType JavaFXUtil.loadEmbeddedController<ServerListController>(ServerListController.LAYOUT).apply {
servers = Minosoft.config.config.server.entries.values
refreshList()
}
}
playTypeListViewFX.items += ServerType(FontAwesomeSolid.NETWORK_WIRED, "LAN", "12 Servers", "") {
playTypeListViewFX.items += ServerType(FontAwesomeSolid.NETWORK_WIRED, LAN_SERVER_TYPE, "12 Servers", "") {
return@ServerType JavaFXUtil.loadEmbeddedController<ServerListController>(ServerListController.LAYOUT).apply {
val invoker = Minosoft.GLOBAL_EVENT_MASTER.registerEvent(JavaFXEventInvoker.of<LANServerDiscoverEvent> { refreshList() })
val events: MutableList<EventInvoker> = mutableListOf()
events += GlobalEventMaster.registerEvent(JavaFXEventInvoker.of<LANServerDiscoverEvent> { refreshList() })
readOnly = true
customRefresh = {
LANServerListener.clear()
refreshList()
}
customTerminate = {
Minosoft.GLOBAL_EVENT_MASTER.unregisterEvent(invoker)
GlobalEventMaster.registerEvent(JavaFXEventInvoker.of<ErosControllerTerminateEvent>(oneShot = true) {
if (it.controller != this) {
return@of
}
GlobalEventMaster.unregisterEvents(*events.toTypedArray())
LANServerListener.clear()
}
})
LANServerListener.clear()
servers = LANServerListener.SERVERS.values
Minosoft.GLOBAL_EVENT_MASTER.registerEvent(JavaFXEventInvoker.of<LANServerDiscoverEvent> { refreshList() })
refreshList()
}
}
@ -75,7 +84,7 @@ class PlayMainController : EmbeddedJavaFXController<Pane>() {
if (this::currentController.isInitialized) {
currentController.terminate()
}
currentController = new.content()
currentController = new.content(new)
playTypeContentFX.children.setAll(currentController.root)
}
@ -100,6 +109,8 @@ class PlayMainController : EmbeddedJavaFXController<Pane>() {
}
companion object {
private val CUSTOM_SERVER_TYPE = "minosoft:server_type.custom".asResourceLocation()
private val LAN_SERVER_TYPE = "minosoft:server_type.lan".asResourceLocation()
private val REFRESH_HEADER = "minosoft:server_list.refresh.header".asResourceLocation()
private val REFRESH_TEXT1 = "minosoft:server_list.refresh.text1".asResourceLocation()
private val REFRESH_TEXT2 = "minosoft:server_list.refresh.text2".asResourceLocation()

View File

@ -68,8 +68,6 @@ class ServerListController : EmbeddedJavaFXController<Pane>(), Refreshable {
var customRefresh: (() -> Unit)? = null
var customTerminate: (() -> Unit)? = null
var servers: MutableCollection<Server> = mutableListOf()
var readOnly: Boolean = false
@ -294,11 +292,6 @@ class ServerListController : EmbeddedJavaFXController<Pane>(), Refreshable {
}
}
override fun terminate() {
super.terminate()
customTerminate?.invoke()
}
companion object {
val LAYOUT = "minosoft:eros/main/play/server/server_list.fxml".asResourceLocation()

View File

@ -21,5 +21,5 @@ data class ServerType(
val header: Any?,
val text1: Any?,
val text2: Any?,
val content: () -> EmbeddedJavaFXController<*>,
val content: (ServerType) -> EmbeddedJavaFXController<*>,
)

View File

@ -0,0 +1,21 @@
/*
* Minosoft
* Copyright (C) 2021 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.gui.eros.modding.events
import de.bixilon.minosoft.gui.eros.controller.JavaFXController
import de.bixilon.minosoft.modding.event.events.Event
class ErosControllerTerminateEvent(
val controller: JavaFXController,
) : Event

View File

@ -17,6 +17,7 @@ import de.bixilon.minosoft.modding.event.events.CancelableEvent
import de.bixilon.minosoft.modding.event.events.Event
import de.bixilon.minosoft.modding.event.invoker.EventInstantFireable
import de.bixilon.minosoft.modding.event.invoker.EventInvoker
import de.bixilon.minosoft.modding.event.invoker.OneShotInvoker
import de.bixilon.minosoft.modding.loading.Priorities
import javafx.application.Platform
import kotlin.reflect.KClass
@ -27,10 +28,11 @@ import kotlin.reflect.KClass
class JavaFXEventInvoker<E : Event> private constructor(
ignoreCancelled: Boolean,
private val callback: (E) -> Unit,
override val oneShot: Boolean,
override val kEventType: KClass<out Event>,
override val eventType: Class<out Event>,
override val instantFire: Boolean,
) : EventInvoker(ignoreCancelled, Priorities.NORMAL, null), EventInstantFireable {
) : EventInvoker(ignoreCancelled, Priorities.NORMAL, null), EventInstantFireable, OneShotInvoker {
override operator fun invoke(event: Event) {
if (!this.isIgnoreCancelled && event is CancelableEvent && event.cancelled) {
@ -44,10 +46,11 @@ class JavaFXEventInvoker<E : Event> private constructor(
companion object {
@JvmOverloads
@Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE")
inline fun <reified E : Event> of(ignoreCancelled: Boolean = false, instantFire: Boolean = true, noinline callback: (E) -> Unit): JavaFXEventInvoker<E> {
inline fun <reified E : Event> of(ignoreCancelled: Boolean = false, instantFire: Boolean = true, oneShot: Boolean = false, noinline callback: (E) -> Unit): JavaFXEventInvoker<E> {
return JavaFXEventInvoker(
ignoreCancelled = ignoreCancelled,
callback = callback,
oneShot = oneShot,
kEventType = E::class,
eventType = E::class.java,
instantFire = instantFire,

View File

@ -13,4 +13,4 @@
package de.bixilon.minosoft.modding.event.events
abstract class Event
interface Event

View File

@ -12,4 +12,4 @@
*/
package de.bixilon.minosoft.modding.event.events
class FinishInitializingEvent : Event()
class FinishInitializingEvent : Event

View File

@ -19,4 +19,4 @@ import java.net.InetAddress
class LANServerDiscoverEvent(
val remoteAddress: InetAddress,
val serer: Server,
) : Event(), CancelableEvent
) : Event, CancelableEvent

View File

@ -20,7 +20,7 @@ import de.bixilon.minosoft.modding.event.events.Event
class AccountSelectEvent(
val previous: Account?,
val account: Account?,
) : Event() {
) : Event {
companion object : EventInstantFire<AccountSelectEvent> {

View File

@ -19,4 +19,4 @@ import de.bixilon.minosoft.protocol.network.connection.Connection
abstract class ConnectionEvent @JvmOverloads constructor(
open val connection: Connection,
val initiator: EventInitiators = EventInitiators.DEFAULT,
) : Event()
) : Event

View File

@ -0,0 +1,21 @@
/*
* Minosoft
* Copyright (C) 2021 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.modding.event.invoker
/**
* Automatically unregisters the event invoker once it was first (and last) fired
*/
interface OneShotInvoker {
val oneShot: Boolean
}

View File

@ -22,5 +22,18 @@ interface AbstractEventMaster : Iterable<EventInvoker> {
fun fireEvent(event: Event): Boolean
fun <T : EventInvoker> registerEvent(invoker: T): T
fun registerEvents(vararg invoker: EventInvoker)
fun registerEvents(vararg invokers: EventInvoker) {
for (invoker in invokers) {
registerEvent(invoker)
}
}
fun unregisterEvent(invoker: EventInvoker?) {}
fun unregisterEvents(vararg invokers: EventInvoker?) {
for (invoker in invokers) {
unregisterEvent(invoker)
}
}
}

View File

@ -18,6 +18,7 @@ import de.bixilon.minosoft.modding.event.events.CancelableEvent
import de.bixilon.minosoft.modding.event.events.Event
import de.bixilon.minosoft.modding.event.invoker.EventInstantFireable
import de.bixilon.minosoft.modding.event.invoker.EventInvoker
import de.bixilon.minosoft.modding.event.invoker.OneShotInvoker
import de.bixilon.minosoft.util.KUtil.synchronizedSetOf
import de.bixilon.minosoft.util.KUtil.toSynchronizedList
import de.bixilon.minosoft.util.KUtil.toSynchronizedSet
@ -44,13 +45,18 @@ open class EventMaster(vararg parents: AbstractEventMaster) : AbstractEventMaste
parent.fireEvent(event)
}
for (eventInvoker in eventInvokers.toSynchronizedList()) {
if (!eventInvoker.eventType.isAssignableFrom(event::class.java)) {
for (invoker in eventInvokers.toSynchronizedList()) {
if (!invoker.eventType.isAssignableFrom(event::class.java)) {
continue
}
eventInvoker(event)
invoker(event)
if (invoker is OneShotInvoker && invoker.oneShot) {
eventInvokers -= invoker
}
}
if (event is CancelableEvent) {
val cancelled = event.cancelled
event.cancelled = false // Cleanup memory
@ -59,8 +65,8 @@ open class EventMaster(vararg parents: AbstractEventMaster) : AbstractEventMaste
return false
}
fun unregisterEvent(method: EventInvoker?) {
eventInvokers -= method ?: return
override fun unregisterEvent(invoker: EventInvoker?) {
eventInvokers -= invoker ?: return
}
override fun <T : EventInvoker> registerEvent(invoker: T): T {
@ -76,11 +82,6 @@ open class EventMaster(vararg parents: AbstractEventMaster) : AbstractEventMaste
return invoker
}
override fun registerEvents(vararg invokers: EventInvoker) {
for (invoker in invokers) {
registerEvent(invoker)
}
}
override fun iterator(): Iterator<EventInvoker> {
return eventInvokers.toSynchronizedList().iterator()

View File

@ -17,6 +17,6 @@ import de.bixilon.minosoft.modding.event.address.ServerAddressValidator
import de.bixilon.minosoft.modding.event.invoker.EventInvoker
import de.bixilon.minosoft.util.KUtil.synchronizedMapOf
class GlobalEventMaster : EventMaster() {
object GlobalEventMaster : EventMaster() {
val specificEventInvokers: MutableMap<MutableSet<ServerAddressValidator>, MutableSet<EventInvoker>> = synchronizedMapOf()
}

View File

@ -73,7 +73,7 @@ abstract class Connection : AbstractEventMaster {
abstract fun handlePacket(packet: S2CPacket)
open fun unregisterEvent(invoker: EventInvoker?) {
override fun unregisterEvent(invoker: EventInvoker?) {
eventMaster.unregisterEvent(invoker)
}

View File

@ -40,6 +40,7 @@ import de.bixilon.minosoft.modding.event.events.ProtocolStateChangeEvent
import de.bixilon.minosoft.modding.event.events.RegistriesLoadEvent
import de.bixilon.minosoft.modding.event.events.connection.play.PlayConnectionStateChangeEvent
import de.bixilon.minosoft.modding.event.invoker.CallbackEventInvoker
import de.bixilon.minosoft.modding.event.master.GlobalEventMaster
import de.bixilon.minosoft.protocol.network.connection.Connection
import de.bixilon.minosoft.protocol.packets.c2s.handshaking.HandshakeC2SP
import de.bixilon.minosoft.protocol.packets.c2s.login.LoginStartC2SP
@ -114,7 +115,7 @@ class PlayConnection(
when (value) {
ProtocolStates.HANDSHAKING -> {
state = PlayConnectionStates.HANDSHAKING
for ((validators, invokers) in Minosoft.GLOBAL_EVENT_MASTER.specificEventInvokers) {
for ((validators, invokers) in GlobalEventMaster.specificEventInvokers) {
var valid = false
for (serverAddress in validators) {
if (serverAddress.check(address)) {

View File

@ -13,11 +13,11 @@
package de.bixilon.minosoft.protocol.protocol
import com.google.common.collect.HashBiMap
import de.bixilon.minosoft.Minosoft
import de.bixilon.minosoft.config.server.Server
import de.bixilon.minosoft.data.text.BaseComponent
import de.bixilon.minosoft.data.text.ChatComponent
import de.bixilon.minosoft.modding.event.events.LANServerDiscoverEvent
import de.bixilon.minosoft.modding.event.master.GlobalEventMaster
import de.bixilon.minosoft.util.KUtil.toSynchronizedMap
import de.bixilon.minosoft.util.Util
import de.bixilon.minosoft.util.logging.Log
@ -49,7 +49,7 @@ object LANServerListener {
val packet = DatagramPacket(buffer, buffer.size)
socket.receive(packet)
val broadcast = String(buffer, 0, packet.length, StandardCharsets.UTF_8)
Log.log(LogMessageType.NETWORK_PACKETS_IN, LogLevels.INFO) { "Received LAN servers broadcast (${packet.address.hostAddress}:${packet.port}): $broadcast" }
Log.log(LogMessageType.NETWORK_PACKETS_IN, LogLevels.INFO) { "LAN servers broadcast (${packet.address.hostAddress}:${packet.port}): $broadcast" }
val sender = packet.address
if (SERVERS.containsKey(sender)) {
// This guy sent us already a server, maybe just the regular 1.5 second interval, a duplicate or a DOS attack...We don't care
@ -62,7 +62,7 @@ object LANServerListener {
if (SERVERS.size > ProtocolDefinition.LAN_SERVER_MAXIMUM_SERVERS) {
continue
}
if (Minosoft.GLOBAL_EVENT_MASTER.fireEvent(LANServerDiscoverEvent(packet.address, server))) {
if (GlobalEventMaster.fireEvent(LANServerDiscoverEvent(packet.address, server))) {
continue
}
SERVERS[sender] = server

View File

@ -5,6 +5,8 @@ minosoft:general.delete=Delete
minosoft:eros_window_title=Minosoft
minosoft:server_type.custom=Custom
minosoft:server_type.lan=LAN
minosoft:server_info.server_name=Server name
minosoft:server_info.server_address=Server address