aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/moe/nea/firmament
diff options
context:
space:
mode:
authornea <nea@nea.moe>2023-07-23 01:35:16 +0200
committernea <nea@nea.moe>2023-07-23 01:35:16 +0200
commit91febc31ad8b34ad9c2bd158a445f774461286c0 (patch)
treec962dd461dbfa41335672bff2b7862c101ba2aba /src/main/kotlin/moe/nea/firmament
parentcdf3938b778188211ad316d16381e0d8c7beac75 (diff)
downloadFirmament-91febc31ad8b34ad9c2bd158a445f774461286c0.tar.gz
Firmament-91febc31ad8b34ad9c2bd158a445f774461286c0.tar.bz2
Firmament-91febc31ad8b34ad9c2bd158a445f774461286c0.zip
Make image preview scalable
Diffstat (limited to 'src/main/kotlin/moe/nea/firmament')
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/chat/ImagePreview.kt23
-rw-r--r--src/main/kotlin/moe/nea/firmament/gui/config/GuiAppender.kt6
-rw-r--r--src/main/kotlin/moe/nea/firmament/gui/config/HudMetaHandler.kt34
-rw-r--r--src/main/kotlin/moe/nea/firmament/gui/config/JAnyHud.kt46
-rw-r--r--src/main/kotlin/moe/nea/firmament/gui/config/ManagedConfig.kt34
-rw-r--r--src/main/kotlin/moe/nea/firmament/jarvis/JarvisIntegration.kt25
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/propertyutil.kt7
7 files changed, 154 insertions, 21 deletions
diff --git a/src/main/kotlin/moe/nea/firmament/features/chat/ImagePreview.kt b/src/main/kotlin/moe/nea/firmament/features/chat/ImagePreview.kt
index 5dcacc3..90edac3 100644
--- a/src/main/kotlin/moe/nea/firmament/features/chat/ImagePreview.kt
+++ b/src/main/kotlin/moe/nea/firmament/features/chat/ImagePreview.kt
@@ -5,8 +5,11 @@ import io.ktor.client.statement.*
import io.ktor.utils.io.jvm.javaio.*
import java.net.URL
import java.util.*
+import moe.nea.jarvis.api.Point
import kotlinx.coroutines.Deferred
+import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.async
+import kotlin.math.max
import kotlin.math.min
import net.minecraft.client.gui.screen.ChatScreen
import net.minecraft.client.texture.NativeImage
@@ -35,12 +38,13 @@ object ImagePreview : FirmamentFeature {
val allowedHosts by string("allowed-hosts") { "cdn.discordapp.com,media.discordapp.com,media.discordapp.net,i.imgur.com" }
val actualAllowedHosts get() = allowedHosts.split(",").map { it.trim() }
val screenPercentage by integer("percentage", 10, 100) { 50 }
+ val position by position("position", 16 * 20, 9 * 20) { Point(0.0, 0.0) }
}
- fun isHostAllowed(host: String) =
+ private fun isHostAllowed(host: String) =
TConfig.allowAllHosts || TConfig.actualAllowedHosts.any { it.equals(host, ignoreCase = true) }
- fun isUrlAllowed(url: String) = isHostAllowed(url.removePrefix("https://").substringBefore("/"))
+ private fun isUrlAllowed(url: String) = isHostAllowed(url.removePrefix("https://").substringBefore("/"))
override val config get() = TConfig
val urlRegex = "https://[^. ]+\\.[^ ]+(\\.(png|gif|jpe?g))(\\?[^ ]*)?( |$)".toRegex()
@@ -54,7 +58,7 @@ object ImagePreview : FirmamentFeature {
val imageCache: MutableMap<String, Deferred<Image?>> =
Collections.synchronizedMap(mutableMapOf<String, Deferred<Image?>>())
- fun tryCacheUrl(url: String) {
+ private fun tryCacheUrl(url: String) {
if (!isUrlAllowed(url)) {
return
}
@@ -81,6 +85,7 @@ object ImagePreview : FirmamentFeature {
}
}
+ @OptIn(ExperimentalCoroutinesApi::class)
override fun onLoad() {
ClientChatLineReceivedEvent.subscribe {
it.replaceWith = it.text.transformEachRecursively { child ->
@@ -122,16 +127,10 @@ object ImagePreview : FirmamentFeature {
val imageFuture = imageCache[url] ?: return@subscribe
if (!imageFuture.isCompleted) return@subscribe
val image = imageFuture.getCompleted() ?: return@subscribe
- val screen = MC.screen!!
- val scale =
- min(
- 1F,
- min(
- (TConfig.screenPercentage / 100F * screen.width.toFloat()) / image.width,
- screen.height.toFloat() / image.height
- )
- )
it.drawContext.matrices.push()
+ val pos = TConfig.position
+ pos.applyTransformations(it.drawContext.matrices)
+ val scale = min(1F, min((9 * 20F) / image.height, (16 * 20F) / image.width))
it.drawContext.matrices.scale(scale, scale, 1F)
it.drawContext.drawTexture(
image.texture,
diff --git a/src/main/kotlin/moe/nea/firmament/gui/config/GuiAppender.kt b/src/main/kotlin/moe/nea/firmament/gui/config/GuiAppender.kt
index f298c76..af83aee 100644
--- a/src/main/kotlin/moe/nea/firmament/gui/config/GuiAppender.kt
+++ b/src/main/kotlin/moe/nea/firmament/gui/config/GuiAppender.kt
@@ -22,10 +22,14 @@ import io.github.cottonmc.cotton.gui.widget.WGridPanel
import io.github.cottonmc.cotton.gui.widget.WLabel
import io.github.cottonmc.cotton.gui.widget.WWidget
import io.github.cottonmc.cotton.gui.widget.data.VerticalAlignment
+import net.minecraft.client.gui.screen.Screen
import net.minecraft.text.Text
-class GuiAppender(val width: Int) {
+class GuiAppender(val width: Int, val screenAccessor: () -> Screen) {
private var row = 0
+
+
+
internal val panel = WGridPanel().also { it.setGaps(4, 4) }
internal val reloadables = mutableListOf<(() -> Unit)>()
fun set(x: Int, y: Int, w: Int, h: Int, widget: WWidget) {
diff --git a/src/main/kotlin/moe/nea/firmament/gui/config/HudMetaHandler.kt b/src/main/kotlin/moe/nea/firmament/gui/config/HudMetaHandler.kt
new file mode 100644
index 0000000..f8d2c3e
--- /dev/null
+++ b/src/main/kotlin/moe/nea/firmament/gui/config/HudMetaHandler.kt
@@ -0,0 +1,34 @@
+package moe.nea.firmament.gui.config
+
+import io.github.cottonmc.cotton.gui.widget.WButton
+import kotlinx.serialization.json.Json
+import kotlinx.serialization.json.JsonElement
+import kotlinx.serialization.json.decodeFromJsonElement
+import kotlinx.serialization.json.encodeToJsonElement
+import net.minecraft.text.MutableText
+import net.minecraft.text.Text
+import moe.nea.firmament.jarvis.JarvisIntegration
+import moe.nea.firmament.util.MC
+
+class HudMetaHandler(val config: ManagedConfig, val label: MutableText, val width: Int, val height: Int) :
+ ManagedConfig.OptionHandler<HudMeta> {
+ override fun toJson(element: HudMeta): JsonElement? {
+ return Json.encodeToJsonElement(element.position)
+ }
+
+ override fun fromJson(element: JsonElement): HudMeta {
+ return HudMeta(Json.decodeFromJsonElement(element), label, width, height)
+ }
+
+ override fun emitGuiElements(opt: ManagedConfig.Option<HudMeta>, guiAppender: GuiAppender) {
+ guiAppender.appendLabeledRow(opt.labelText, WButton(Text.translatable("firmament.hud.edit", label))
+ .also {
+ it.setOnClick {
+ MC.screen = JarvisIntegration.jarvis.getHudEditor(
+ guiAppender.screenAccessor.invoke(),
+ listOf(opt.value)
+ )
+ }
+ })
+ }
+}
diff --git a/src/main/kotlin/moe/nea/firmament/gui/config/JAnyHud.kt b/src/main/kotlin/moe/nea/firmament/gui/config/JAnyHud.kt
new file mode 100644
index 0000000..5470f9b
--- /dev/null
+++ b/src/main/kotlin/moe/nea/firmament/gui/config/JAnyHud.kt
@@ -0,0 +1,46 @@
+package moe.nea.firmament.gui.config
+
+import moe.nea.jarvis.api.JarvisHud
+import moe.nea.jarvis.api.JarvisScalable
+import kotlinx.serialization.Serializable
+import net.minecraft.text.Text
+
+@Serializable
+data class HudPosition(
+ var x: Double,
+ var y: Double,
+ var scale: Float,
+)
+
+
+data class HudMeta(
+ val position: HudPosition,
+ private val label: Text,
+ private val width: Int,
+ private val height: Int,
+) : JarvisScalable, JarvisHud {
+ override fun getX(): Double = position.x
+
+ override fun setX(newX: Double) {
+ position.x = newX
+ }
+
+ override fun getY(): Double = position.y
+
+ override fun setY(newY: Double) {
+ position.y = newY
+ }
+
+ override fun getLabel(): Text = label
+
+ override fun getWidth(): Int = width
+
+ override fun getHeight(): Int = height
+
+ override fun getScale(): Float = position.scale
+
+ override fun setScale(newScale: Float) {
+ position.scale = newScale
+ }
+
+}
diff --git a/src/main/kotlin/moe/nea/firmament/gui/config/ManagedConfig.kt b/src/main/kotlin/moe/nea/firmament/gui/config/ManagedConfig.kt
index 0204448..83d95ca 100644
--- a/src/main/kotlin/moe/nea/firmament/gui/config/ManagedConfig.kt
+++ b/src/main/kotlin/moe/nea/firmament/gui/config/ManagedConfig.kt
@@ -21,6 +21,7 @@ package moe.nea.firmament.gui.config
import io.github.cottonmc.cotton.gui.client.CottonClientScreen
import io.github.cottonmc.cotton.gui.client.LightweightGuiDescription
import io.github.cottonmc.cotton.gui.widget.data.Insets
+import moe.nea.jarvis.api.Point
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.JsonElement
@@ -150,6 +151,19 @@ abstract class ManagedConfig(val name: String) {
}
+ protected fun position(
+ propertyName: String,
+ width: Int,
+ height: Int,
+ default: () -> Point,
+ ): Option<HudMeta> {
+ val label = Text.translatable("firmament.config.${name}.${propertyName}")
+ return option(propertyName, {
+ val p = default()
+ HudMeta(HudPosition(p.x, p.y, 1F), label, width, height)
+ }, HudMetaHandler(this, label, width, height))
+ }
+
protected fun integer(
propertyName: String,
min: Int,
@@ -175,18 +189,26 @@ abstract class ManagedConfig(val name: String) {
fun getConfigEditor(parent: Screen? = null): CottonClientScreen {
val lwgd = LightweightGuiDescription()
- val guiapp = GuiAppender(20)
+ var screen: Screen? = null
+ val guiapp = GuiAppender(20, { requireNotNull(screen) { "Screen Accessor called too early" } })
latestGuiAppender = guiapp
guiapp.panel.insets = Insets.ROOT_PANEL
sortedOptions.forEach { it.appendToGui(guiapp) }
guiapp.reloadables.forEach { it() }
lwgd.setRootPanel(guiapp.panel)
- return object : CottonClientScreen(lwgd) {
- override fun close() {
- latestGuiAppender = null
- MC.screen = parent
+ screen =
+ object : CottonClientScreen(lwgd) {
+ override fun init() {
+ latestGuiAppender = guiapp
+ super.init()
+ }
+
+ override fun close() {
+ latestGuiAppender = null
+ MC.screen = parent
+ }
}
- }
+ return screen
}
fun showConfigEditor(parent: Screen? = null) {
diff --git a/src/main/kotlin/moe/nea/firmament/jarvis/JarvisIntegration.kt b/src/main/kotlin/moe/nea/firmament/jarvis/JarvisIntegration.kt
index 3dfb7d0..f691dba 100644
--- a/src/main/kotlin/moe/nea/firmament/jarvis/JarvisIntegration.kt
+++ b/src/main/kotlin/moe/nea/firmament/jarvis/JarvisIntegration.kt
@@ -1,21 +1,42 @@
package moe.nea.firmament.jarvis
+import moe.nea.jarvis.api.Jarvis
import moe.nea.jarvis.api.JarvisConfigOption
+import moe.nea.jarvis.api.JarvisHud
import moe.nea.jarvis.api.JarvisPlugin
import net.minecraft.client.gui.screen.Screen
import net.minecraft.text.Text
import moe.nea.firmament.Firmament
import moe.nea.firmament.features.FeatureManager
+import moe.nea.firmament.gui.config.HudMeta
+import moe.nea.firmament.gui.config.HudMetaHandler
import moe.nea.firmament.repo.RepoManager
class JarvisIntegration : JarvisPlugin {
override fun getModId(): String =
Firmament.MOD_ID
- override fun getAllConfigOptions(): List<JarvisConfigOption> {
- val configs = listOf(
+ companion object {
+ lateinit var jarvis: Jarvis
+ }
+
+ override fun onInitialize(jarvis: Jarvis) {
+ Companion.jarvis = jarvis
+ }
+
+ val configs
+ get() = listOf(
RepoManager.Config
) + FeatureManager.allFeatures.mapNotNull { it.config }
+
+
+ override fun getAllHuds(): List<JarvisHud> {
+ return configs.flatMap { config ->
+ config.sortedOptions.mapNotNull { if (it.handler is HudMetaHandler) it.value as HudMeta else null }
+ }
+ }
+
+ override fun getAllConfigOptions(): List<JarvisConfigOption> {
return configs.flatMap { config ->
config.sortedOptions.map {
object : JarvisConfigOption {
diff --git a/src/main/kotlin/moe/nea/firmament/util/propertyutil.kt b/src/main/kotlin/moe/nea/firmament/util/propertyutil.kt
new file mode 100644
index 0000000..89b8251
--- /dev/null
+++ b/src/main/kotlin/moe/nea/firmament/util/propertyutil.kt
@@ -0,0 +1,7 @@
+package moe.nea.firmament.util
+
+import kotlin.properties.ReadOnlyProperty
+
+fun <T, V, M> ReadOnlyProperty<T, V>.map(mapper: (V) -> M): ReadOnlyProperty<T, M> {
+ return ReadOnlyProperty { thisRef, property -> mapper(this@map.getValue(thisRef, property)) }
+}