mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-17 03:15:35 -04:00
config option listening
This commit is contained in:
parent
b0574500c4
commit
e8c5e94902
@ -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(),
|
||||
)
|
||||
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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,
|
||||
)
|
@ -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<Class<out Profile>, ProfileManager<*>>
|
||||
|
||||
init {
|
||||
val classMapping: MutableMap<Class<out Profile>, ProfileManager<*>> = mutableMapOf()
|
||||
for (manager in DEFAULT_MANAGERS) {
|
||||
classMapping[manager.profileClass] = manager
|
||||
}
|
||||
CLASS_MAPPING = classMapping.toMap()
|
||||
}
|
||||
|
||||
private var initialized = false
|
||||
private var loading = true
|
||||
|
@ -24,6 +24,7 @@ interface ProfileManager<T : Profile> {
|
||||
val namespace: ResourceLocation
|
||||
val latestVersion: Int
|
||||
val saveLock: ReentrantLock
|
||||
val profileClass: Class<T>
|
||||
|
||||
val profiles: HashBiMap<String, T>
|
||||
var selected: T
|
||||
@ -93,7 +94,7 @@ interface ProfileManager<T : Profile> {
|
||||
if (selected == null || profileNames.isEmpty()) {
|
||||
initDefaultProfile()
|
||||
}
|
||||
var migrated = false
|
||||
var saveFile = false
|
||||
for (profileName in profileNames) {
|
||||
val path = getPath(profileName, baseDirectory)
|
||||
val json: MutableMap<String, Any?>?
|
||||
@ -110,14 +111,15 @@ interface ProfileManager<T : Profile> {
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
@ -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<Field, SynchronizedMap<Profile?, MutableSet<Pair<WeakReference<Any>, ProfileChangeListener<Any>>>>> = synchronizedMapOf()
|
||||
|
||||
fun <T> register(reference: Any, listener: ProfileChangeListener<T>) {
|
||||
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<Pair<WeakReference<Any>, ProfileChangeListener<Any>>>) {
|
||||
val toRemove: MutableSet<Pair<WeakReference<Any>, ProfileChangeListener<Any>>> = 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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<T> {
|
||||
val property: KProperty<T>
|
||||
val field: Field
|
||||
val profile: Profile?
|
||||
|
||||
|
||||
fun invoke(previous: T, value: T)
|
||||
}
|
@ -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<T>(
|
||||
override val property: KProperty<T>,
|
||||
override val field: Field,
|
||||
override val profile: Profile?,
|
||||
private val callback: (T) -> Unit,
|
||||
) : ProfileChangeListener<T> {
|
||||
|
||||
override fun invoke(previous: T, value: T) {
|
||||
callback(value)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun <T> KProperty<T>.listen(reference: Any, profile: Profile? = null, callback: ((T) -> Unit)) {
|
||||
ProfilesChangeManager.register(reference, SimpleProfileChangeListener(this, javaField!!, profile, callback))
|
||||
}
|
||||
|
||||
fun <T> KProperty<T>.listenFX(reference: Any, profile: Profile? = null, callback: ((T) -> Unit)) {
|
||||
ProfilesChangeManager.register(reference, SimpleProfileChangeListener(this, javaField!!, profile) { JavaFXUtil.runLater { callback(it) } })
|
||||
}
|
||||
}
|
||||
}
|
@ -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)
|
||||
|
@ -14,6 +14,7 @@ object ErosProfileManager : ProfileManager<ErosProfile> {
|
||||
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
|
||||
|
@ -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()
|
||||
}
|
@ -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)
|
||||
}
|
@ -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<V>(
|
||||
private var value: V,
|
||||
@ -13,7 +16,7 @@ open class ProfileDelegate<V>(
|
||||
private val profileManager: ProfileManager<*>,
|
||||
private val profileName: String,
|
||||
) : ReadWriteProperty<Any, V> {
|
||||
|
||||
private lateinit var profile: Profile
|
||||
|
||||
override fun getValue(thisRef: Any, property: KProperty<*>): V {
|
||||
return value
|
||||
@ -23,16 +26,24 @@ open class ProfileDelegate<V>(
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user