Skip to content

Commit 40f31ce

Browse files
Added support for Chat Image.
1 parent a6d5489 commit 40f31ce

5 files changed

Lines changed: 103 additions & 2 deletions

File tree

build.gradle.kts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ repositories {
2222
url = uri("https://thedarkcolour.github.io/KotlinForForge/")
2323
content { includeGroup("thedarkcolour") }
2424
}
25+
maven {
26+
name = "kituinMavenReleases"
27+
url = uri("https://maven.kituin.fun/releases")
28+
}
2529
}
2630

2731
base {
@@ -148,6 +152,10 @@ dependencies {
148152
externalImplementation("io.ktor:ktor-utils", "[2.0, 4.0)", "2.3.13")
149153
externalImplementation("io.ktor:ktor-network", "[2.0, 4.0)", "2.3.13")
150154

155+
// chatimage
156+
compileOnly("io.github.kituin:ChatImageCode:0.12.1")
157+
compileOnly("io.github.kituin:ChatImage:1.4.6+1.21.0+neoforge")
158+
151159
// Example mod dependency with JEI
152160
// The JEI API is declared for compile time use, while the full JEI artifact is used at runtime
153161
// compileOnly "mezz.jei:jei-${mc_version}-common-api:${jei_version}"

src/main/kotlin/NoMathExpectation/chatExchange/neoForged/ExchangeServer.kt

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package NoMathExpectation.chatExchange.neoForged
22

3+
import NoMathExpectation.chatExchange.neoForged.chatImage.tryParseCICodeFileToData
34
import io.ktor.network.selector.*
45
import io.ktor.network.sockets.*
56
import io.ktor.utils.io.*
@@ -122,11 +123,18 @@ class ExchangeServer(
122123
}
123124

124125
suspend fun sendEvent(event: ExchangeEvent) {
125-
logger.info("Sending event: $event")
126+
var finalEvent = event
127+
if (finalEvent is MessageEvent) {
128+
finalEvent = finalEvent.copy(
129+
content = finalEvent.content.tryParseCICodeFileToData()
130+
)
131+
}
132+
133+
logger.info("Sending event: $finalEvent")
126134
channelMutex.withLock {
127135
sendChannels.forEach {
128136
kotlin.runCatching {
129-
it.writeExchangeEvent(event)
137+
it.writeExchangeEvent(finalEvent)
130138
}.onFailure {
131139
logger.error("Failed to send message to a client.", it)
132140
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package NoMathExpectation.chatExchange.neoForged.chatImage
2+
3+
import net.neoforged.fml.ModList
4+
5+
internal val chatImageLoaded
6+
get() = ModList.get().isLoaded("chatimage")
7+
8+
suspend fun String.tryParseCICodeFileToData(): String {
9+
if (!chatImageLoaded) {
10+
return this
11+
}
12+
return tryParseCICodeFileToData0(this)
13+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package NoMathExpectation.chatExchange.neoForged.chatImage
2+
3+
import NoMathExpectation.chatExchange.neoForged.ChatExchange
4+
import io.github.kituin.ChatImageCode.ChatImageCode
5+
import io.github.kituin.ChatImageCode.ServerStorage
6+
import kotlinx.coroutines.delay
7+
import org.apache.logging.log4j.LogManager
8+
import kotlin.time.Duration.Companion.seconds
9+
10+
private val logger = LogManager.getLogger(ChatExchange.ID)
11+
12+
private val ciCodeRegex = ChatImageCode.pattern.toRegex()
13+
14+
private suspend fun findImageData(query: String): String? {
15+
repeat(10) {
16+
delay(0.5.seconds)
17+
18+
ServerStorage.SERVER_BLOCK_CACHE.getImage(query)?.let {
19+
return it
20+
}
21+
}
22+
//logger.info(ServerStorage.SERVER_BLOCK_CACHE.blockCache)
23+
return null
24+
}
25+
26+
internal suspend fun tryParseCICodeFileToData0(string: String) = buildString {
27+
var codeEnd = 0
28+
ciCodeRegex.findAll(string).forEach { match ->
29+
val start = match.range.first
30+
val end = match.range.last + 1
31+
32+
if (codeEnd < start) {
33+
append(string.substring(codeEnd, start))
34+
}
35+
36+
val data = match.value
37+
.removeSurrounding("[[", "]]")
38+
.trim()
39+
.split(",")
40+
.filter { "=" in it }
41+
.map { it.split("=", limit = 2) }
42+
.associate { it[0].trim() to it[1].trim() }
43+
.toMutableMap()
44+
45+
var url = data["url"]
46+
if (url?.startsWith("file:///") == true) {
47+
val query = url.removePrefix("file:///")
48+
url = "invalid"
49+
findImageData(query)?.let {
50+
url = "base64://$it"
51+
}
52+
}
53+
data["url"] = url ?: "invalid"
54+
if (url == null || url == "invalid") {
55+
logger.warn("Unable to resolve CICode: ${match.value}")
56+
}
57+
58+
val code = data.map { (k, v) -> "$k=$v" }
59+
.joinToString(",", "[[CICode,", "]]")
60+
append(code)
61+
62+
codeEnd = end
63+
}
64+
append(string.substring(codeEnd))
65+
}

src/main/templates/META-INF/neoforge.mods.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,13 @@ versionRange = "${minecraft_version_range}"
7272
ordering = "NONE"
7373
side = "BOTH"
7474

75+
[[dependencies."${mod_id}"]]
76+
modId = "chatimage"
77+
type = "optional"
78+
versionRange = "[1.4.6, 2)"
79+
ordering = "AFTER"
80+
side = "BOTH"
81+
7582
# Features are specific properties of the game environment, that you may want to declare you require. This example declares
7683
# that your mod requires GL version 3.2 or higher. Other features will be added. They are side aware so declaring this won't
7784
# stop your mod loading on the server for example.

0 commit comments

Comments
 (0)