Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 74 additions & 76 deletions scripts/coreMindustry/contentsTweaker.kts
Original file line number Diff line number Diff line change
@@ -1,58 +1,30 @@
@file:Import("https://www.jitpack.io/", mavenRepository = true)
@file:Import("com.github.way-zer:ContentsTweaker:v3.1.2", mavenDependsSingle = true)
@file:Depends("coreMindustry/menu", "调用菜单")

package coreMindustry

import cf.wayzer.contentsTweaker.ContentsTweaker
import mindustry.gen.Iconc

var patches: String?
get() = state.map.tags.get("ContentsPatch")
set(v) {
state.map.tags.put("ContentsPatch", v)
//back compatibility
state.rules.tags.put("ContentsPatch", v!!)
}
var patchList: List<String>
get() = patches?.split(";").orEmpty()
set(v) {
patches = v.joinToString(";")
}

val ctPlayers = mutableMapOf<String, String>()

class CTHello(val player: Player, val version: String) : Event {
companion object : Event.Handler()
}

registerVar("scoreboard.ext.contents-0-Version", "ContentsTweaker状态显示", DynamicVar {
if (patches == null) return@DynamicVar null
"{cK}CT修改已加载: {cV}{count} 修改".with("count" to patchList.size)
})
registerVar("scoreboard.ext.contents-1-Advice", "ContentsTweaker未安装警告", DynamicVar {
if (patches == null) return@DynamicVar null
val player = VarToken("receiver").get() as? Player
if (player == null || player.uuid() !in ctPlayers) null
else "{cA}(使用ContentsTweakerMOD获得最佳体验)".with()
})
registerVarForType<Player>().apply {
registerChild("suffix.s3-CT", "CT mod 后缀", { p -> Iconc.wrench.takeIf { p.uuid() in ctPlayers } })
}

fun sendPatch(name: String, patch: String) {
Call.clientPacketReliable("ContentsLoader|newPatch", "$name\n$patch")
}
import arc.struct.Seq
import arc.util.serialization.Jval
import mindustry.mod.ContentPatcher.PatchSet

@JvmName("addPatchV3")
fun addPatch(name: String, patch: String) {
if (!name.startsWith("$")) {
state.map.tags.put("CT@$name", patch)
patchList = patchList.toMutableList().apply {
remove(name); add(name)//put last
fun addPatch(name: String, patch: String = "PatchFromContentsTweaker") {
val raw = patch
.replace("+=", "+")
.replace("#", "arg")
.replace(Regex("""(:)([\u4e00-\u9fa5][^,\}\]]*)""")) { m ->
val sep = m.groupValues[1]
val text = m.groupValues[2].trim()
"$sep\"$text\""
}
}
ContentsTweaker.loadPatch(name, patch)
sendPatch(name, patch)
.replace(Regex("(?<=\\{|,|\\s)([a-zA-Z0-9_-]+):"), "\"$1\":")
.replace(Regex(":\\s*([a-zA-Z_-]+)(?=\\s*[},])")) { m ->
":\"${m.groupValues[1]}\""
}

val readPatch = Jval.read(raw).apply { asObject(); put("name", Jval.valueOf(name)) }.toString(Jval.Jformat.plain)
logger.info(readPatch)
state.patcher.apply(state.patcher.patches.map { it.patch }.add(readPatch))
}
@JvmName("addPatch")
fun addPatchOld(name: String, patch: String): String {
Expand All @@ -61,43 +33,69 @@ fun addPatchOld(name: String, patch: String): String {
}
export(::addPatch)
listen<EventType.ResetEvent> {
ContentsTweaker.recoverAll()
ctPlayers.clear()
}

listen<EventType.PlayerLeave> {
ctPlayers.remove(it.player.uuid())
state.patcher.apply(Seq())//may load server global patches
}

listen<EventType.WorldLoadBeginEvent> {
if (ContentsTweaker.worldInReset) return@listen
var needAfterHandle = false
state.map.tags.get("ContentsPatch")?.split(";")?.forEach { name ->
if (name.isBlank()) return@forEach
val patch = state.map.tags.get("CT@$name") ?: return@forEach
ContentsTweaker.loadPatch(name, patch, doAfter = false)
needAfterHandle = true
addPatch(name, patch)
}
if (needAfterHandle) ContentsTweaker.afterHandle()
}

//处理客户端请求
onEnable {
netServer.addPacketHandler("ContentsLoader|version") { p, msg ->
logger.info("${p.name} $msg")
if (msg.contains("2."))
Call.sendMessage(p.con, "你当前安装的CT版本过老,请更新到3.0.1", null, null)
ctPlayers[p.uuid()] = msg
launch(Dispatchers.game) {
CTHello(p, msg).emitAsync()
}
}
netServer.addPacketHandler("ContentsLoader|requestPatch") { p, msg ->
state.map.tags["CT@$msg"]?.let { sendPatch(msg, it) }
command("cp", "查看cp修改") {
type = CommandType.Client
body {
menu(player!!)
}
}

onDisable {
netServer.getPacketHandlers("ContentsLoader|version").clear()
netServer.getPacketHandlers("ContentsLoader|requestPatch").clear()
}
suspend fun menu(player: Player, select: Int = 1) {
object : PagedMenuBuilder<PatchSet>(state.patcher.patches.toList(), selectedPage = select, 6) {
override suspend fun renderItem(item: PatchSet) {
option(if (item.name.isEmpty()) "<unnamed>" else item.name) {
moreMenu(player, selectedPage, item)
}
}

override suspend fun build() {
title = "[yellow]ContentPatcher"
msg = """
[sky]查询服务器patch列表
""".trimIndent()
super.build()
}
}.sendTo(player, 20_000)
}

suspend fun moreMenu(player: Player, select: Int, item: PatchSet) {
MenuBuilder(true){
title = "[yellow]Patch详情"
val jsonFlat = try {
val jval = Jval.read(item.patch)
flater(jval)
} catch (e: Exception) {
"[red]解析失败"
}
msg = """
[white]${jsonFlat}
""".trimIndent()
option ("[red]返回"){
menu(player, select)
}
}.sendTo(player, 20_000)
}

fun flater(jval: Jval, prefix: String = ""): String = buildString {
when {
jval.isObject -> jval.asObject().forEach {
val fullKey = if (prefix.isEmpty()) it.key else "$prefix.${it.key}"
append(flater(it.value, fullKey))
}
jval.isArray -> jval.asArray().forEachIndexed { index, value ->
append(flater(value, "$prefix[$index]"))
}
else -> append("$prefix = $jval\n")
}
}