add Update Check, simplify config access

This commit is contained in:
Nikky Ai 2018-02-17 04:07:22 +01:00
parent 7ea258fdc4
commit 19d7017336
26 changed files with 146 additions and 114 deletions

View File

@ -56,7 +56,10 @@ compileKotlin.doFirst {
from("src/templates/kotlin/matterlink/Constants.kt")
into(target)
}
ant.replaceregexp(match:'@VERSION@', replace: project.mod_version, flags:'g', byline:true) {
ant.replaceregexp(match:'@MODVERSION@', replace: project.mod_version, flags:'g', byline:true) {
fileset(dir: target, includes: 'Constants.kt')
}
ant.replaceregexp(match:'@MCVERSION@', replace: project.mc_version, flags:'g', byline:true) {
fileset(dir: target, includes: 'Constants.kt')
}
ant.replaceregexp(match:'@FORGELIN-VERSION@', replace: project.forgelin_version, flags:'g', byline:true) {

View File

@ -48,7 +48,7 @@ object EventWrapper {
val sender =
when {
e.sender is EntityPlayer -> e.sender.name
e.sender is DedicatedServer -> cfg!!.relay.systemUser
e.sender is DedicatedServer -> cfg.relay.systemUser
e.sender is TileEntityCommandBlock -> "CommandBlock"
else -> return
}

View File

@ -16,7 +16,7 @@ lateinit var logger: Logger
@Mod(
modid = MODID,
name = NAME, version = VERSION,
name = NAME, version = MODVERSION,
serverSideOnly = true,
useMetadata = true,
acceptableRemoteVersions = "*",
@ -52,7 +52,6 @@ object MatterLink : IMatterLink() {
event.registerServerCommand(CommandMatterlink())
serverStartTime = System.currentTimeMillis()
connect()
Thread(UpdateChecker()).start()
}
@Mod.EventHandler
@ -75,6 +74,6 @@ object MatterLink : IMatterLink() {
override var commandSender: IMinecraftCommandSender = MatterlinkCommandSender
override val mcVersion: String = "1.10.2"
override val modVersion: String = VERSION
override val mcVersion: String = MCVERSION
override val modVersion: String = MODVERSION
}

View File

@ -2,6 +2,7 @@ package matterlink
const val MODID = "matterlink"
const val NAME = "MatterLink"
const val VERSION = "@VERSION@"
const val MODVERSION = "@MODVERSION@"
const val MCVERSION = "@MCVERSION@"
//const val DEPENDENCIES = "required-after:forgelin@[@FORGELIN-VERSION@,);required-after:forge@[@FORGE-VERSION@,);"
const val DEPENDENCIES = "required-after:forgelin@[@FORGELIN-VERSION@,);"

View File

@ -55,7 +55,10 @@ compileKotlin.doFirst {
from("src/templates/kotlin/matterlink/Constants.kt")
into(target)
}
ant.replaceregexp(match:'@VERSION@', replace: project.mod_version, flags:'g', byline:true) {
ant.replaceregexp(match:'@MODVERSION@', replace: project.mod_version, flags:'g', byline:true) {
fileset(dir: target, includes: 'Constants.kt')
}
ant.replaceregexp(match:'@MCVERSION@', replace: project.mc_version, flags:'g', byline:true) {
fileset(dir: target, includes: 'Constants.kt')
}
ant.replaceregexp(match:'@FORGELIN-VERSION@', replace: project.forgelin_version, flags:'g', byline:true) {

View File

@ -48,7 +48,7 @@ object EventWrapper {
val sender =
when {
e.sender is EntityPlayer -> e.sender.name
e.sender is DedicatedServer -> cfg!!.relay.systemUser
e.sender is DedicatedServer -> cfg.relay.systemUser
e.sender is TileEntityCommandBlock -> "CommandBlock"
else -> return
}

View File

@ -16,7 +16,7 @@ lateinit var logger: Logger
@Mod(
modid = MODID,
name = NAME, version = VERSION,
name = NAME, version = MODVERSION,
serverSideOnly = true,
useMetadata = true,
acceptableRemoteVersions = "*",
@ -52,7 +52,6 @@ object MatterLink : IMatterLink() {
event.registerServerCommand(CommandMatterlink())
serverStartTime = System.currentTimeMillis()
connect()
Thread(UpdateChecker()).start()
}
@Mod.EventHandler
@ -75,6 +74,6 @@ object MatterLink : IMatterLink() {
override var commandSender: IMinecraftCommandSender = MatterlinkCommandSender
override val mcVersion: String = "1.11.2"
override val modVersion: String = VERSION
override val mcVersion: String = MCVERSION
override val modVersion: String = MODVERSION
}

View File

@ -2,6 +2,7 @@ package matterlink
const val MODID = "matterlink"
const val NAME = "MatterLink"
const val VERSION = "@VERSION@"
const val MODVERSION = "@MODVERSION@"
const val MCVERSION = "@MCVERSION@"
const val DEPENDENCIES = "required-after:forgelin@[@FORGELIN-VERSION@,);required-after:forge@[@FORGE-VERSION@,);"

View File

@ -49,7 +49,8 @@ minecraft {
mappings = project.mcp_mappings
replaceIn 'Constants.kt'
replace '@VERSION@', project.mod_version
replace '@MODVERSION@', project.mod_version
replace '@MCVERSION@', project.mc_version
replace '@FORGELIN-VERSION@', project.forgelin_version
replace '@FORGE-VERSION@', project.forge_version
}

View File

@ -2,6 +2,7 @@ package matterlink
const val MODID = "matterlink"
const val NAME = "MatterLink"
const val VERSION = "@VERSION@"
const val MODVERSION = "@MODVERSION@"
const val MCVERSION = "@MCVERSION@"
const val DEPENDENCIES = "required-after:forgelin@[@FORGELIN-VERSION@,);required-after:forge@[@FORGE-VERSION@,);"

View File

@ -16,7 +16,7 @@ lateinit var logger: Logger
@Mod(
modid = MODID,
name = NAME, version = VERSION,
name = NAME, version = MODVERSION,
serverSideOnly = true,
useMetadata = true,
acceptableRemoteVersions = "*",
@ -52,7 +52,6 @@ object MatterLink : IMatterLink() {
event.registerServerCommand(CommandMatterlink())
serverStartTime = System.currentTimeMillis()
connect()
Thread(UpdateChecker()).start()
}
@Mod.EventHandler
@ -74,6 +73,6 @@ object MatterLink : IMatterLink() {
logger.log(Level.toLevel(level, Level.INFO),formatString, *data)
override var commandSender: IMinecraftCommandSender = MatterlinkCommandSender
override val mcVersion: String = "1.12.2"
override val modVersion: String = VERSION
override val mcVersion: String = MCVERSION
override val modVersion: String = MODVERSION
}

View File

@ -2,17 +2,15 @@ package matterlink
import matterlink.bridge.MessageHandler
import matterlink.bridge.command.BridgeCommandRegistry
import matterlink.bridge.command.HelpCommand
import matterlink.bridge.command.PlayerListCommand
import matterlink.bridge.command.UptimeCommand
import matterlink.command.IMinecraftCommandSender
import matterlink.config.cfg
import matterlink.update.UpdateChecker
lateinit var instance: IMatterLink
abstract class IMatterLink {
abstract val mcVersion : String
abstract val modVersion : String
abstract val mcVersion: String
abstract val modVersion: String
abstract var commandSender: IMinecraftCommandSender
//var interrupted: Boolean = false
@ -21,8 +19,15 @@ abstract class IMatterLink {
abstract fun wrappedPlayerList(): Array<String>
private var updateChecked: Boolean = false
fun connect() {
MessageHandler.start(clear = true)
if (!updateChecked && cfg.update.enable) {
Thread(UpdateChecker()).start()
updateChecked = true
}
}
fun disconnect() {
@ -36,29 +41,30 @@ abstract class IMatterLink {
fun warn(formatString: String, vararg data: Any) = log("WARN", formatString, *data)
fun info(formatString: String, vararg data: Any) = log("INFO", formatString, *data)
fun debug(formatString: String, vararg data: Any) {
if (cfg!!.relay.logLevel == "DEBUG" || cfg!!.relay.logLevel == "TRACE")
if (cfg.relay.logLevel == "DEBUG" || cfg.relay.logLevel == "TRACE")
log("INFO", "DEBUG: " + formatString.replace("\n", "\nDEBUG: "), *data)
}
fun trace(formatString: String, vararg data: Any) {
if (cfg!!.relay.logLevel == "TRACE")
if (cfg.relay.logLevel == "TRACE")
log("INFO", "TRACE: " + formatString.replace("\n", "\nTRACE: "), *data)
}
/**
* in milliseconds
*/
var serverStartTime : Long = 0
fun getUptimeInSeconds() : Int {
var serverStartTime: Long = 0
fun getUptimeInSeconds(): Int {
return ((System.currentTimeMillis() - serverStartTime) / 1000).toInt()
}
fun getUptimeAsString() : String {
fun getUptimeAsString(): String {
val total = this.getUptimeInSeconds()
val sec = total % 60
val min = (total/60)%60
val hr = (total/3600)%24
val day = total/86400
val min = (total / 60) % 60
val hr = (total / 3600) % 24
val day = total / 86400
return "${day}d ${hr}hr ${min}m ${sec}s"
}

View File

@ -9,9 +9,9 @@ const val USER_ACTION: String = "user_action"
const val JOIN_LEAVE: String = "join_leave"
data class ApiMessage(
val username: String = cfg!!.relay.systemUser,
val username: String = cfg.relay.systemUser,
val text: String = "",
val gateway: String = cfg!!.connect.gateway,
val gateway: String = cfg.connect.gateway,
val channel: String = "",
val userid: String = "",
val avatar: String = "",

View File

@ -29,20 +29,20 @@ object MessageHandler {
}
private fun HttpRequestBase.authorize() {
if (cfg!!.connect.authToken.isNotEmpty() && getHeaders("Authorization").isEmpty())
setHeader("Authorization", "Bearer " + cfg!!.connect.authToken)
if (cfg.connect.authToken.isNotEmpty() && getHeaders("Authorization").isEmpty())
setHeader("Authorization", "Bearer " + cfg.connect.authToken)
}
private fun createThread(clear: Boolean = true): HttpStreamConnection {
instance.info("Attempting to open bridge connection.")
return HttpStreamConnection(
{
HttpGet(cfg!!.connect.url + "/api/stream").apply {
HttpGet(cfg.connect.url + "/api/stream").apply {
authorize()
}
},
{
HttpGet(cfg!!.connect.url + "/api/messages").apply {
HttpGet(cfg.connect.url + "/api/messages").apply {
authorize()
}
},
@ -110,7 +110,7 @@ object MessageHandler {
try {
//open a connection
val client = HttpClients.createDefault()
val post = HttpPost(cfg!!.connect.url + "/api/message")
val post = HttpPost(cfg.connect.url + "/api/message")
post.entity = StringEntity(message.encode(), ContentType.APPLICATION_JSON)
post.authorize()

View File

@ -15,15 +15,15 @@ object ServerChatHandler {
instance.debug("incoming: " + MessageHandler.rcvQueue.toString())
val nextMessage = MessageHandler.rcvQueue.poll()
if (nextMessage != null && nextMessage.gateway == cfg!!.connect.gateway) {
if (nextMessage != null && nextMessage.gateway == cfg.connect.gateway) {
if (!nextMessage.text.isBlank()) {
val message = when (nextMessage.event) {
"user_action" -> nextMessage.format(cfg!!.formatting.action)
"user_action" -> nextMessage.format(cfg.formatting.action)
"" -> {
if (BridgeCommandRegistry.handleCommand(nextMessage.text)) return
nextMessage.format(cfg!!.formatting.chat)
nextMessage.format(cfg.formatting.chat)
}
"join_leave" -> nextMessage.format(cfg!!.formatting.joinLeave)
"join_leave" -> nextMessage.format(cfg.formatting.joinLeave)
else -> {
val user = nextMessage.username
val text = nextMessage.text

View File

@ -9,8 +9,8 @@ object BridgeCommandRegistry {
private val commandMap: HashMap<String, IBridgeCommand> = HashMap()
fun handleCommand(input: String): Boolean {
if (!cfg!!.command.enable) return false
if (input[0] != cfg!!.command.prefix[0] || input.length < 2) return false
if (!cfg.command.enable) return false
if (input[0] != cfg.command.prefix[0] || input.length < 2) return false
val cmd = input.substring(1).split(' ', ignoreCase = false, limit = 2)
val args = if (cmd.size == 2)
@ -48,8 +48,8 @@ object BridgeCommandRegistry {
fun reloadCommands() {
commandMap.clear()
registerAll(HelpCommand,PlayerListCommand,UptimeCommand)
for (key : String in cfg!!.command.commandMapping.keys) {
register(PassthroughCommand(key, cfg!!.command.commandMapping.get(key)!!))
for ((key, value) in cfg.command.commandMapping) {
register(PassthroughCommand(key, value))
}
}
}

View File

@ -15,7 +15,7 @@ object HelpCommand : IBridgeCommand {
.joinToString(separator = "\n") { "$it: ${ BridgeCommandRegistry.getHelpString(it) }" }
}
MessageHandler.transmit(ApiMessage(
username = cfg!!.relay.systemUser,
username = cfg.relay.systemUser,
text = msg
))
return true

View File

@ -13,7 +13,7 @@ object PlayerListCommand : IBridgeCommand {
if (args.isNotBlank()) return false
val playerList = instance.wrappedPlayerList()
MessageHandler.transmit(ApiMessage(
username = cfg!!.relay.systemUser,
username = cfg.relay.systemUser,
text = when {
playerList.isNotEmpty() -> "players: " + playerList.joinToString(" ") { it.antiping() }
else -> "No Players online"

View File

@ -12,7 +12,7 @@ object UptimeCommand : IBridgeCommand {
override fun call(args: String): Boolean {
if (args.isNotBlank()) return false
MessageHandler.transmit(ApiMessage(
username = cfg!!.relay.systemUser,
username = cfg.relay.systemUser,
text = instance.getUptimeAsString()
))
return true

View File

@ -24,7 +24,7 @@ object CommandCore {
}
"reload" -> {
if (MessageHandler.connected) instance.disconnect()
cfg = cfg!!.load()
cfg = cfg.load()
BridgeCommandRegistry.reloadCommands()
if (!MessageHandler.connected) instance.connect()
"Bridge config reloaded!"

View File

@ -2,7 +2,7 @@ package matterlink.config
import java.util.regex.Pattern
var cfg: BaseConfig? = null
lateinit var cfg: BaseConfig
abstract class BaseConfig {
companion object {
@ -12,18 +12,20 @@ abstract class BaseConfig {
private val CATEGORY_CONNECTION = "connection"
private val CATEGORY_COMMAND = "command"
private val CATEGORY_DEATH = "death"
private val CATEGORY_UPDATE = "update"
fun reload() {
cfg = cfg!!.load()
cfg = cfg.load()
}
}
var relay: RelayOptions = RelayOptions()
var connect: ConnectOptions = ConnectOptions()
var formatting: FormattingOptions = FormattingOptions()
var joinLeave: FormattingJoinLeave = FormattingJoinLeave()
var command: CommandOptions = CommandOptions()
var death: DeathOptions = DeathOptions()
var relay = RelayOptions()
var connect = ConnectOptions()
var formatting = FormattingOptions()
var joinLeave = FormattingJoinLeave()
var command = CommandOptions()
var death = DeathOptions()
var update = UpdateOptions()
data class RelayOptions(
var systemUser: String = "Server",
@ -58,6 +60,10 @@ abstract class BaseConfig {
)
)
data class UpdateOptions(
var enable: Boolean = true
)
data class DeathOptions(
var showDeath: Boolean = true,
var showDamageType: Boolean = true,
@ -272,6 +278,18 @@ abstract class BaseConfig {
Pair(key, value)
}
)
category = CATEGORY_UPDATE
addCustomCategoryComment(category, "Update Settings")
update = UpdateOptions(
enable = getBoolean(
"enable",
category,
update.enable,
"Enable Update checking"
)
)
}
abstract fun load(): BaseConfig

View File

@ -14,15 +14,15 @@ object DeathHandler {
deathMessage: String,
damageType: String
) {
if (cfg!!.death.showDeath) {
if (cfg.death.showDeath) {
var msg = deathMessage.replace(player, player.antiping())
if(cfg!!.death.showDamageType) {
val emojis = cfg!!.death.damageTypeMapping[damageType]?.split(' ') ?: listOf("\uD83D\uDC7B unknown type '$damageType'")
if(cfg.death.showDamageType) {
val emojis = cfg.death.damageTypeMapping[damageType]?.split(' ') ?: listOf("\uD83D\uDC7B unknown type '$damageType'")
val damageEmoji = emojis[random.nextInt(emojis.size)]
msg += " " + damageEmoji
}
MessageHandler.transmit(ApiMessage(
username = cfg!!.relay.systemUser,
username = cfg.relay.systemUser,
text = msg
))
}

View File

@ -9,15 +9,15 @@ import matterlink.mapFormat
object JoinLeaveHandler {
fun handleJoin(player: String) {
if (cfg!!.joinLeave.showJoin) {
val msg = cfg!!.joinLeave.joinServer.mapFormat(
if (cfg.joinLeave.showJoin) {
val msg = cfg.joinLeave.joinServer.mapFormat(
mapOf(
"{username}" to player,
"{username:antiping}" to player.antiping()
)
)
MessageHandler.transmit(ApiMessage(
username = cfg!!.relay.systemUser,
username = cfg.relay.systemUser,
text = msg,
event = JOIN_LEAVE
))
@ -25,15 +25,15 @@ object JoinLeaveHandler {
}
fun handleLeave(player: String) {
if (cfg!!.joinLeave.showLeave) {
val msg = cfg!!.joinLeave.leaveServer.mapFormat(
if (cfg.joinLeave.showLeave) {
val msg = cfg.joinLeave.leaveServer.mapFormat(
mapOf(
"{username}" to player,
"{username:antiping}" to player.antiping()
)
)
MessageHandler.transmit(ApiMessage(
username = cfg!!.relay.systemUser,
username = cfg.relay.systemUser,
text = msg,
event = JOIN_LEAVE
))

View File

@ -8,10 +8,10 @@ import matterlink.config.cfg
object ProgressHandler {
fun handleProgress(name: String, text: String) {
if (!cfg!!.relay.advancements) return
if (!cfg.relay.advancements) return
val usr = name.antiping()
MessageHandler.transmit(ApiMessage(
username = cfg!!.relay.systemUser,
username = cfg.relay.systemUser,
text = "$usr $text"
))
}

View File

@ -2,17 +2,17 @@ package matterlink.update
import com.google.gson.Gson
data class ApiUpdate (
data class CurseFile(
val downloadURL: String,
val fileName: String,
val gameVersion: Array<String>,
val gameVersion: List<String>,
val releaseType: String
) {
companion object {
val gson = Gson()
fun decode(json: String): ApiUpdate {
return gson.fromJson(json, ApiUpdate::class.java)
fun decode(json: String): CurseFile {
return gson.fromJson(json, CurseFile::class.java)
}
}

View File

@ -10,64 +10,65 @@ import org.apache.http.client.HttpClient
import org.apache.http.client.methods.HttpGet
import org.apache.http.impl.client.HttpClients
import java.io.BufferedReader
import java.util.regex.Pattern
class UpdateChecker : Runnable {
override fun run() {
val gson = Gson()
val currentModVersion = instance.modVersion
val currentMCVersion = instance.mcVersion
val currentVersion = currentMCVersion + "-" + currentModVersion
instance.info("Checking for new versions...")
val ApiUpdateList : Array<ApiUpdate>
val apiUpdateList: List<CurseFile>
val client : HttpClient = HttpClients.createDefault()
val response : HttpResponse = client.execute(HttpGet("https://cursemeta.nikky.moe/api/addon/287323/files"))
if (200 == response.statusLine.statusCode) { //HTTP 200 OK
val buffer : BufferedReader = response.entity.content.bufferedReader()
val client: HttpClient = HttpClients.createDefault()
val response: HttpResponse = client.execute(HttpGet("https://cursemeta.nikky.moe/api/addon/287323/files"))
apiUpdateList = if (200 == response.statusLine.statusCode) { //HTTP 200 OK
val buffer: BufferedReader = response.entity.content.bufferedReader()
//put all of the buffer content onto the string
var content : String = ""
var line : String? = buffer.readLine()
while (line != null) {
instance.debug(line)
content += line
line = buffer.readLine()
}
val content = buffer.readText()
instance.debug("updateData: $content")
val gson = Gson()
ApiUpdateList = gson.fromJson<Array<ApiUpdate>>(content,Array<ApiUpdate>::class.java)
gson.fromJson(content, Array<CurseFile>::class.java)
.filter {
it.gameVersion.contains(currentMCVersion)
}
.sortedByDescending { it.fileName.substringAfterLast(" ") }
} else {
instance.error("Could not check for updates!")
return
}
val possibleUpdates = HashMap<String,ApiUpdate>()
var maxVersion : String = ""
ApiUpdateList.forEach {
val possibleUpdates = mutableListOf<CurseFile>()
apiUpdateList.forEach {
instance.debug(it.toString())
//TODO: fix this if we ever release jars that support multiple versions
if (it.gameVersion[0] == instance.mcVersion) {
if (Pattern.matches("[mM]atter[lL]ink \\d+\\.\\d+\\.\\d+-\\d+\\.\\d+\\.?\\d*",it.fileName) ) {
val version : String = it.fileName.split("-")[1]
instance.debug(version)
possibleUpdates.set(version,it)
if (version.compareTo(maxVersion)>0 || maxVersion.equals("")) maxVersion = version
}
val version = it.fileName.substringAfter("-")
if(version > currentModVersion)
{
possibleUpdates += it
}
}
if(possibleUpdates.isEmpty()) return
val latest= possibleUpdates[0]
if (maxVersion.isEmpty()) return
if (maxVersion.compareTo(instance.modVersion)<0) {
val latest : ApiUpdate? = possibleUpdates[maxVersion]
if (latest != null) {
instance.warn("Mod out of date! New version available at ${latest.downloadURL}")
MessageHandler.transmit(ApiMessage(
username = cfg!!.relay.systemUser,
text = "Matterlink out of date! Please download new version from ${latest.downloadURL}"
))
} else {
instance.fatal("Severe error in update checker!")
}
possibleUpdates.sortByDescending { it.fileName.substringAfter(" ") }
val version = if(possibleUpdates.count() == 1) "version" else "versions"
instance.info("Matterlink out of date! You are {} $version behind", possibleUpdates.count())
possibleUpdates.forEach {
instance.info("version: {} download: {}", it.fileName, it.downloadURL)
}
instance.warn("Mod out of date! New $version available at ${latest.downloadURL}")
MessageHandler.transmit(ApiMessage(
username = cfg.relay.systemUser,
text = "Matterlink out of date! You are {} $version behind! Please download new version from ${latest.downloadURL}"
))
}
}