From 31d679c1edf49df76ea37a561871af1f5d13572d Mon Sep 17 00:00:00 2001 From: sychic <47618543+Sychic@users.noreply.github.com> Date: Sun, 31 Dec 2023 14:13:54 -0500 Subject: [PATCH] feat: async states --- .../gg/skytils/skytilsmod/gui/view/state.kt | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 src/main/kotlin/gg/skytils/skytilsmod/gui/view/state.kt diff --git a/src/main/kotlin/gg/skytils/skytilsmod/gui/view/state.kt b/src/main/kotlin/gg/skytils/skytilsmod/gui/view/state.kt new file mode 100644 index 000000000..19b5fe341 --- /dev/null +++ b/src/main/kotlin/gg/skytils/skytilsmod/gui/view/state.kt @@ -0,0 +1,66 @@ +/* + * Skytils - Hypixel Skyblock Quality of Life Mod + * Copyright (C) 2020-2023 Skytils + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package gg.skytils.skytilsmod.gui.view + +import gg.essential.elementa.state.BasicState +import gg.essential.elementa.state.MappedState +import gg.essential.elementa.state.State +import gg.skytils.skytilsmod.core.mcScope +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +open class LateinitState : State() { + internal open var backer: T? = null + override fun get(): T = + backer ?: error("State should be initialized before get") + + override fun set(value: T) { + backer = value + super.set(value) + } +} + +class AsyncMappedState(val state: State, val scope: CoroutineScope = mcScope, val mapper: suspend (T) -> U, initialValue: U? = null) : LateinitState() { + override var backer: U? = initialValue + + private var removeListener = state.onSetValue { + scope.launch { + set(mapper(it)) + } + } + + init { + if (state !is LateinitState) { + scope.launch { + set(mapper(state.get())) + } + } + } + + fun rebind(newState: State) { + removeListener() + removeListener = state.onSetValue { + scope.launch { + set(mapper(it)) + } + } + } +} + +fun State.asyncMap(initialValue: U? = null, scope: CoroutineScope = mcScope, mapper: suspend (T) -> U) = AsyncMappedState(this, scope, mapper, initialValue) \ No newline at end of file