diff --git a/src/main/java/de/bixilon/minosoft/config/config/Config.kt b/src/main/java/de/bixilon/minosoft/config/config/Config.kt
index 5979917d9..711969ac1 100644
--- a/src/main/java/de/bixilon/minosoft/config/config/Config.kt
+++ b/src/main/java/de/bixilon/minosoft/config/config/Config.kt
@@ -17,7 +17,6 @@ import de.bixilon.minosoft.config.config.account.AccountConfig
import de.bixilon.minosoft.config.config.chat.ChatConfig
import de.bixilon.minosoft.config.config.debug.DebugConfig
import de.bixilon.minosoft.config.config.download.DownloadConfig
-import de.bixilon.minosoft.config.config.eros.ErosConfig
import de.bixilon.minosoft.config.config.game.GameConfig
import de.bixilon.minosoft.config.config.general.GeneralConfig
import de.bixilon.minosoft.config.config.network.NetworkConfig
@@ -32,5 +31,4 @@ data class Config(
val server: ServerConfig = ServerConfig(),
val download: DownloadConfig = DownloadConfig(),
val debug: DebugConfig = DebugConfig(),
- val eros: ErosConfig = ErosConfig(),
)
diff --git a/src/main/java/de/bixilon/minosoft/config/config/eros/ErosConfig.kt b/src/main/java/de/bixilon/minosoft/config/config/eros/ErosConfig.kt
deleted file mode 100644
index 7b6d68e76..000000000
--- a/src/main/java/de/bixilon/minosoft/config/config/eros/ErosConfig.kt
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * 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 .
- *
- * This software is not affiliated with Mojang AB, the original developer of Minecraft.
- */
-
-package de.bixilon.minosoft.config.config.eros
-
-import com.squareup.moshi.Json
-
-data class ErosConfig(
- @Json(name = "show_releases") var showReleases: Boolean = true,
- @Json(name = "show_snapshots") var showSnapshots: Boolean = false,
-)
diff --git a/src/main/java/de/bixilon/minosoft/config/profile/GlobalProfileManager.kt b/src/main/java/de/bixilon/minosoft/config/profile/GlobalProfileManager.kt
index 9bfeb26d5..f6361d3ac 100644
--- a/src/main/java/de/bixilon/minosoft/config/profile/GlobalProfileManager.kt
+++ b/src/main/java/de/bixilon/minosoft/config/profile/GlobalProfileManager.kt
@@ -22,6 +22,15 @@ object GlobalProfileManager {
ErosProfileManager,
)
private val SELECTED_PROFILES_TYPE: MapType = Jackson.MAPPER.typeFactory.constructMapType(HashMap::class.java, ResourceLocation::class.java, String::class.java)
+ val CLASS_MAPPING: Map, ProfileManager<*>>
+
+ init {
+ val classMapping: MutableMap, ProfileManager<*>> = mutableMapOf()
+ for (manager in DEFAULT_MANAGERS) {
+ classMapping[manager.profileClass] = manager
+ }
+ CLASS_MAPPING = classMapping.toMap()
+ }
private var initialized = false
private var loading = true
diff --git a/src/main/java/de/bixilon/minosoft/config/profile/ProfileManager.kt b/src/main/java/de/bixilon/minosoft/config/profile/ProfileManager.kt
index fb728895c..a4bbffd8c 100644
--- a/src/main/java/de/bixilon/minosoft/config/profile/ProfileManager.kt
+++ b/src/main/java/de/bixilon/minosoft/config/profile/ProfileManager.kt
@@ -24,6 +24,7 @@ interface ProfileManager {
val namespace: ResourceLocation
val latestVersion: Int
val saveLock: ReentrantLock
+ val profileClass: Class
val profiles: HashBiMap
var selected: T
@@ -93,7 +94,7 @@ interface ProfileManager {
if (selected == null || profileNames.isEmpty()) {
initDefaultProfile()
}
- var migrated = false
+ var saveFile = false
for (profileName in profileNames) {
val path = getPath(profileName, baseDirectory)
val json: MutableMap?
@@ -110,14 +111,15 @@ interface ProfileManager {
}
Log.log(LogMessageType.LOAD_PROFILES, LogLevels.INFO) { "Migrated profile ($path) from version $version to $latestVersion" }
json["version"] = latestVersion
- migrated = true
+ saveFile = true
}
} else {
json = null
+ saveFile = true
}
val profile = load(profileName, json)
- if (migrated) {
+ if (saveFile) {
profile.saved = false
save(profile)
}
diff --git a/src/main/java/de/bixilon/minosoft/config/profile/change/ProfilesChangeManager.kt b/src/main/java/de/bixilon/minosoft/config/profile/change/ProfilesChangeManager.kt
new file mode 100644
index 000000000..cf3befdd1
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/config/profile/change/ProfilesChangeManager.kt
@@ -0,0 +1,59 @@
+package de.bixilon.minosoft.config.profile.change
+
+import de.bixilon.minosoft.config.profile.GlobalProfileManager
+import de.bixilon.minosoft.config.profile.change.listener.ProfileChangeListener
+import de.bixilon.minosoft.config.profile.profiles.Profile
+import de.bixilon.minosoft.util.KUtil.synchronizedMapOf
+import de.bixilon.minosoft.util.KUtil.synchronizedSetOf
+import de.bixilon.minosoft.util.KUtil.toSynchronizedSet
+import de.bixilon.minosoft.util.KUtil.unsafeCast
+import de.bixilon.minosoft.util.collections.SynchronizedMap
+import java.lang.ref.WeakReference
+import java.lang.reflect.Field
+
+object ProfilesChangeManager {
+ private val listeners: SynchronizedMap, ProfileChangeListener>>>> = synchronizedMapOf()
+
+ fun register(reference: Any, listener: ProfileChangeListener) {
+ this.listeners.getOrPut(listener.field) { synchronizedMapOf() }.getOrPut(listener.profile) { synchronizedSetOf() }.add(Pair(WeakReference(reference), listener.unsafeCast()))
+ }
+
+ fun onChange(profile: Profile, field: Field, previous: Any?, value: Any?) {
+ val fieldListeners = listeners[field] ?: return
+
+ fun work(queue: MutableSet, ProfileChangeListener>>) {
+ val toRemove: MutableSet, ProfileChangeListener>> = mutableSetOf()
+ for (pair in queue.toSynchronizedSet()) {
+ val (reference, listener) = pair
+ if (reference.get() == null) {
+ toRemove += pair
+ }
+ listener.invoke(previous.unsafeCast(), value.unsafeCast())
+ }
+ if (toRemove.isNotEmpty()) {
+ if (queue.size == toRemove.size) {
+ queue.clear()
+ } else {
+ queue.removeAll(toRemove)
+ }
+ }
+ }
+
+ fieldListeners[profile]?.let {
+ work(it)
+ if (it.isEmpty()) {
+ fieldListeners -= profile
+ }
+ }
+
+ val manager = GlobalProfileManager.CLASS_MAPPING[profile::class.java] ?: return
+ if (profile == manager.selected) {
+ fieldListeners[null]?.let {
+ work(it)
+ if (it.isEmpty()) {
+ fieldListeners -= null
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/de/bixilon/minosoft/config/profile/change/listener/ProfileChangeListener.kt b/src/main/java/de/bixilon/minosoft/config/profile/change/listener/ProfileChangeListener.kt
new file mode 100644
index 000000000..b83bab2f7
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/config/profile/change/listener/ProfileChangeListener.kt
@@ -0,0 +1,14 @@
+package de.bixilon.minosoft.config.profile.change.listener
+
+import de.bixilon.minosoft.config.profile.profiles.Profile
+import java.lang.reflect.Field
+import kotlin.reflect.KProperty
+
+interface ProfileChangeListener {
+ val property: KProperty
+ val field: Field
+ val profile: Profile?
+
+
+ fun invoke(previous: T, value: T)
+}
diff --git a/src/main/java/de/bixilon/minosoft/config/profile/change/listener/SimpleProfileChangeListener.kt b/src/main/java/de/bixilon/minosoft/config/profile/change/listener/SimpleProfileChangeListener.kt
new file mode 100644
index 000000000..a5a36ffcf
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/config/profile/change/listener/SimpleProfileChangeListener.kt
@@ -0,0 +1,31 @@
+package de.bixilon.minosoft.config.profile.change.listener
+
+import de.bixilon.minosoft.config.profile.change.ProfilesChangeManager
+import de.bixilon.minosoft.config.profile.profiles.Profile
+import de.bixilon.minosoft.gui.eros.util.JavaFXUtil
+import java.lang.reflect.Field
+import kotlin.reflect.KProperty
+import kotlin.reflect.jvm.javaField
+
+class SimpleProfileChangeListener(
+ override val property: KProperty,
+ override val field: Field,
+ override val profile: Profile?,
+ private val callback: (T) -> Unit,
+) : ProfileChangeListener {
+
+ override fun invoke(previous: T, value: T) {
+ callback(value)
+ }
+
+ companion object {
+
+ fun KProperty.listen(reference: Any, profile: Profile? = null, callback: ((T) -> Unit)) {
+ ProfilesChangeManager.register(reference, SimpleProfileChangeListener(this, javaField!!, profile, callback))
+ }
+
+ fun KProperty.listenFX(reference: Any, profile: Profile? = null, callback: ((T) -> Unit)) {
+ ProfilesChangeManager.register(reference, SimpleProfileChangeListener(this, javaField!!, profile) { JavaFXUtil.runLater { callback(it) } })
+ }
+ }
+}
diff --git a/src/main/java/de/bixilon/minosoft/config/profile/profiles/eros/ErosProfile.kt b/src/main/java/de/bixilon/minosoft/config/profile/profiles/eros/ErosProfile.kt
index 966d05676..afcb9211d 100644
--- a/src/main/java/de/bixilon/minosoft/config/profile/profiles/eros/ErosProfile.kt
+++ b/src/main/java/de/bixilon/minosoft/config/profile/profiles/eros/ErosProfile.kt
@@ -4,6 +4,7 @@ import de.bixilon.minosoft.config.profile.profiles.Profile
import de.bixilon.minosoft.config.profile.profiles.eros.ErosProfileManager.delegate
import de.bixilon.minosoft.config.profile.profiles.eros.ErosProfileManager.latestVersion
import de.bixilon.minosoft.config.profile.profiles.eros.general.GeneralC
+import de.bixilon.minosoft.config.profile.profiles.eros.server.ServerC
class ErosProfile(
description: String? = null,
@@ -16,6 +17,7 @@ class ErosProfile(
override var saved: Boolean = true
val general: GeneralC = GeneralC()
+ val server: ServerC = ServerC()
override fun toString(): String {
return ErosProfileManager.getName(this)
diff --git a/src/main/java/de/bixilon/minosoft/config/profile/profiles/eros/ErosProfileManager.kt b/src/main/java/de/bixilon/minosoft/config/profile/profiles/eros/ErosProfileManager.kt
index 78f086fa4..2a44ba3d3 100644
--- a/src/main/java/de/bixilon/minosoft/config/profile/profiles/eros/ErosProfileManager.kt
+++ b/src/main/java/de/bixilon/minosoft/config/profile/profiles/eros/ErosProfileManager.kt
@@ -14,6 +14,7 @@ object ErosProfileManager : ProfileManager {
override val namespace = "minosoft:eros".toResourceLocation()
override val latestVersion = 1
override val saveLock = ReentrantLock()
+ override val profileClass = ErosProfile::class.java
private var currentLoadingPath: String? = null
diff --git a/src/main/java/de/bixilon/minosoft/config/profile/profiles/eros/server/ServerC.kt b/src/main/java/de/bixilon/minosoft/config/profile/profiles/eros/server/ServerC.kt
new file mode 100644
index 000000000..e7ff37a22
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/config/profile/profiles/eros/server/ServerC.kt
@@ -0,0 +1,7 @@
+package de.bixilon.minosoft.config.profile.profiles.eros.server
+
+import de.bixilon.minosoft.config.profile.profiles.eros.server.modify.ModifyC
+
+class ServerC {
+ val modify = ModifyC()
+}
diff --git a/src/main/java/de/bixilon/minosoft/config/profile/profiles/eros/server/modify/ModifyC.kt b/src/main/java/de/bixilon/minosoft/config/profile/profiles/eros/server/modify/ModifyC.kt
new file mode 100644
index 000000000..7b85faf1b
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/config/profile/profiles/eros/server/modify/ModifyC.kt
@@ -0,0 +1,8 @@
+package de.bixilon.minosoft.config.profile.profiles.eros.server.modify
+
+import de.bixilon.minosoft.config.profile.profiles.eros.ErosProfileManager.delegate
+
+class ModifyC {
+ var showReleases by delegate(true)
+ var showSnapshots by delegate(false)
+}
diff --git a/src/main/java/de/bixilon/minosoft/config/profile/util/ProfileDelegate.kt b/src/main/java/de/bixilon/minosoft/config/profile/util/ProfileDelegate.kt
index 139744b2d..34205dc54 100644
--- a/src/main/java/de/bixilon/minosoft/config/profile/util/ProfileDelegate.kt
+++ b/src/main/java/de/bixilon/minosoft/config/profile/util/ProfileDelegate.kt
@@ -1,11 +1,14 @@
package de.bixilon.minosoft.config.profile.util
import de.bixilon.minosoft.config.profile.ProfileManager
+import de.bixilon.minosoft.config.profile.change.ProfilesChangeManager
+import de.bixilon.minosoft.config.profile.profiles.Profile
import de.bixilon.minosoft.util.logging.Log
import de.bixilon.minosoft.util.logging.LogLevels
import de.bixilon.minosoft.util.logging.LogMessageType
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
+import kotlin.reflect.jvm.javaField
open class ProfileDelegate(
private var value: V,
@@ -13,7 +16,7 @@ open class ProfileDelegate(
private val profileManager: ProfileManager<*>,
private val profileName: String,
) : ReadWriteProperty {
-
+ private lateinit var profile: Profile
override fun getValue(thisRef: Any, property: KProperty<*>): V {
return value
@@ -23,16 +26,24 @@ open class ProfileDelegate(
if (checkEquals && this.value == value) {
return
}
- val profile = profileManager.profiles[profileName]
- if (profile == null || profile.initializing) {
+ if (!this::profile.isInitialized) {
+ val profile = profileManager.profiles[profileName]
+ if (profile == null) {
+ this.value = value
+ return
+ }
+ this.profile = profile
+ }
+ if (profile.initializing) {
this.value = value
return
}
- Log.log(LogMessageType.OTHER, LogLevels.VERBOSE) { "Changed option $property in $thisRef in profile ${profileName::class.java} from ${this.value} to $value" }
+ Log.log(LogMessageType.OTHER, LogLevels.VERBOSE) { "Changed option $property in profile $profileName from ${this.value} to $value" }
profileManager.profiles[profileName]?.saved = false
-
- // ToDo: Fire event
+ val previous = this.value
this.value = value
+
+ ProfilesChangeManager.onChange(profile, property.javaField ?: return, previous, value)
}
}
diff --git a/src/main/java/de/bixilon/minosoft/gui/eros/dialog/UpdateServerDialog.kt b/src/main/java/de/bixilon/minosoft/gui/eros/dialog/UpdateServerDialog.kt
index d1b3c70e4..fe7d59cc0 100644
--- a/src/main/java/de/bixilon/minosoft/gui/eros/dialog/UpdateServerDialog.kt
+++ b/src/main/java/de/bixilon/minosoft/gui/eros/dialog/UpdateServerDialog.kt
@@ -14,6 +14,9 @@
package de.bixilon.minosoft.gui.eros.dialog
import de.bixilon.minosoft.Minosoft
+import de.bixilon.minosoft.config.profile.change.listener.SimpleProfileChangeListener.Companion.listenFX
+import de.bixilon.minosoft.config.profile.profiles.eros.ErosProfileManager
+import de.bixilon.minosoft.config.profile.profiles.eros.server.modify.ModifyC
import de.bixilon.minosoft.config.server.Server
import de.bixilon.minosoft.data.registries.versions.Version
import de.bixilon.minosoft.data.registries.versions.VersionTypes
@@ -106,22 +109,24 @@ class UpdateServerDialog(
cancelButtonFX.ctext = TranslatableComponents.GENERAL_CANCEL
+ val modifyConfig = ErosProfileManager.selected.server.modify
+
+ ModifyC::showReleases.listenFX(this) { showReleasesFX.isSelected = it }
+ ModifyC::showSnapshots.listenFX(this) { showSnapshotsFX.isSelected = it }
showReleasesFX.apply {
- isSelected = Minosoft.config.config.eros.showReleases
+ isSelected = modifyConfig.showReleases
ctext = SHOW_RELEASES
setOnAction {
- Minosoft.config.config.eros.showReleases = isSelected
- Minosoft.config.saveToFile()
+ modifyConfig.showReleases = isSelected
refreshVersions()
}
}
showSnapshotsFX.apply {
- isSelected = Minosoft.config.config.eros.showSnapshots
+ isSelected = modifyConfig.showSnapshots
ctext = SHOW_SNAPSHOTS
setOnAction {
- Minosoft.config.config.eros.showSnapshots = isSelected
- Minosoft.config.saveToFile()
+ modifyConfig.showSnapshots = isSelected
refreshVersions()
}
}