diff --git a/.gitignore b/.gitignore index 429f7ba..fa8887b 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ .idea out build +classes #eclipse .project diff --git a/1.11.2/src/main/kotlin/matterlink/MatterLink.kt b/1.11.2/src/main/kotlin/matterlink/MatterLink.kt index b2e7566..f05bf51 100644 --- a/1.11.2/src/main/kotlin/matterlink/MatterLink.kt +++ b/1.11.2/src/main/kotlin/matterlink/MatterLink.kt @@ -1,5 +1,6 @@ package matterlink +import jline.internal.Log import matterlink.bridge.MessageHandler import matterlink.bridge.command.BridgeCommandRegistry import matterlink.bridge.command.HelpCommand @@ -9,6 +10,7 @@ import net.minecraft.util.text.TextComponentString import net.minecraftforge.fml.common.FMLCommonHandler import net.minecraftforge.fml.common.Mod import net.minecraftforge.fml.common.event.* +import org.apache.logging.log4j.Level import org.apache.logging.log4j.Logger const val MODID = "matterlink" @@ -70,5 +72,7 @@ object MatterLink : IMatterLink() { override fun wrappedPlayerList(): Array { return FMLCommonHandler.instance().minecraftServerInstance.playerList.onlinePlayerNames } - + + override fun log(level: String, formatString: String, vararg data: Any) = + logger.log(Level.toLevel(level, Level.INFO),formatString, *data) } diff --git a/1.12.2/src/main/kotlin/matterlink/MatterLink.kt b/1.12.2/src/main/kotlin/matterlink/MatterLink.kt index b2e7566..fdad07e 100644 --- a/1.12.2/src/main/kotlin/matterlink/MatterLink.kt +++ b/1.12.2/src/main/kotlin/matterlink/MatterLink.kt @@ -9,6 +9,7 @@ import net.minecraft.util.text.TextComponentString import net.minecraftforge.fml.common.FMLCommonHandler import net.minecraftforge.fml.common.Mod import net.minecraftforge.fml.common.event.* +import org.apache.logging.log4j.Level import org.apache.logging.log4j.Logger const val MODID = "matterlink" @@ -45,7 +46,7 @@ object MatterLink : IMatterLink() { @Mod.EventHandler fun serverAboutToStart(event: FMLServerAboutToStartEvent) { - MessageHandler.start(clear = true) +// MessageHandler.start(clear = true) } @Mod.EventHandler @@ -70,5 +71,7 @@ object MatterLink : IMatterLink() { override fun wrappedPlayerList(): Array { return FMLCommonHandler.instance().minecraftServerInstance.playerList.onlinePlayerNames } - + + override fun log(level: String, formatString: String, vararg data: Any) = + logger.log(Level.toLevel(level, Level.INFO),formatString, *data) } diff --git a/core/src/main/kotlin/matterlink/IMatterLink.kt b/core/src/main/kotlin/matterlink/IMatterLink.kt index e5865aa..8371c78 100644 --- a/core/src/main/kotlin/matterlink/IMatterLink.kt +++ b/core/src/main/kotlin/matterlink/IMatterLink.kt @@ -1,39 +1,31 @@ package matterlink import matterlink.bridge.MessageHandler -//import org.apache.logging.log4j.Logger lateinit var instance: IMatterLink -//lateinit var logger: Logger abstract class IMatterLink { - var interrupted: Boolean = false +// var interrupted: Boolean = false abstract fun wrappedSendToPlayers(msg: String) abstract fun wrappedPlayerList(): Array fun connect() { - if (MessageHandler.start(clear = true)) { - println("Connected to matterbridge relay") - } else { - System.err.println("Connection to matterbridge relay failed.") - } + MessageHandler.start(clear = true) } - fun disconnect () { + fun disconnect() { MessageHandler.stop() } + abstract fun log(level: String, formatString: String, vararg data: Any) + + fun fatal(formatString: String, vararg data: Any) = log(Level.FATAL.name, formatString, *data) + fun error(formatString: String, vararg data: Any) = log(Level.ERROR.name, formatString, *data) + fun warn(formatString: String, vararg data: Any) = log(Level.WARN.name, formatString, *data) + fun info(formatString: String, vararg data: Any) = log(Level.INFO.name, formatString, *data) + fun debug(formatString: String, vararg data: Any) = log(Level.DEBUG.name, formatString, *data) + fun trace(formatString: String, vararg data: Any) = log(Level.TRACE.name, formatString, *data) - fun reconnect(tick: Int) { - if(tick % 20 == 0 && interrupted) { - println("Trying to reconnect") - if (MessageHandler.start(clear = false)) { - println("Reconnected to matterbridge relay") - } else { - System.err.println("Reconnection to matterbridge relay failed.") - } - } - } } \ No newline at end of file diff --git a/core/src/main/kotlin/matterlink/Level.kt b/core/src/main/kotlin/matterlink/Level.kt new file mode 100644 index 0000000..3675aa6 --- /dev/null +++ b/core/src/main/kotlin/matterlink/Level.kt @@ -0,0 +1,38 @@ +package matterlink + +enum class Level(val level: Int) { + /** + * No events will be logged. + */ + OFF(0), + + /** + * A severe error that will prevent the application from continuing. + */ + FATAL(1), + + /** + * An error in the application, possibly recoverable. + */ + ERROR(2), + + /** + * An event that might possible lead to an error. + */ + WARN(3), + + /** + * An event for informational purposes. + */ + INFO(4), + + /** + * A general debugging event. + */ + DEBUG(5), + + /** + * A fine-grained debug message, typically capturing the flow through the application. + */ + TRACE(6), +} \ No newline at end of file diff --git a/core/src/main/kotlin/matterlink/bridge/HttpStreamConnection.kt b/core/src/main/kotlin/matterlink/bridge/HttpStreamConnection.kt index 81682aa..081241e 100644 --- a/core/src/main/kotlin/matterlink/bridge/HttpStreamConnection.kt +++ b/core/src/main/kotlin/matterlink/bridge/HttpStreamConnection.kt @@ -1,7 +1,6 @@ package matterlink.bridge; import matterlink.instance -//import matterlink.logger import org.apache.http.client.methods.HttpGet import org.apache.http.impl.client.HttpClients import java.io.InputStream @@ -9,7 +8,13 @@ import java.net.SocketException val BUFFER_SIZE = 1000 -class HttpStreamConnection(getClosure: () -> HttpGet, clearClosure: () -> HttpGet, private val mhandler: (String) -> Unit, private val onClose: () -> Unit, private val clear: Boolean = true) : Thread() { +class HttpStreamConnection(getClosure: () -> HttpGet, + clearClosure: () -> HttpGet, + private val mhandler: (String) -> Unit, + private val onClose: () -> Unit, + private val setSuccess: (Boolean) -> Unit, + private val clear: Boolean = true +) : Thread() { private val client = HttpClients.createDefault() private var stream: InputStream? = null @@ -18,28 +23,36 @@ class HttpStreamConnection(getClosure: () -> HttpGet, clearClosure: () -> HttpGe var cancelled: Boolean = false private set - override fun run() { - instance.interrupted = false + if (clear) { val r = client.execute(clearGet) r.entity.content.bufferedReader().forEachLine { - println("DEBUG: skipping $it") + instance.debug("skipping $it") } } - val response = client.execute(get) - val content = response.entity.content.buffered() - stream = content - //val reader = content.bufferedReader() - var buffer = "" - val buf = ByteArray(BUFFER_SIZE) try { + val response = client.execute(get) + if (response.statusLine.statusCode != 200) { + instance.error("Bridge Connection rejected... status code ${response.statusLine.statusCode}") + setSuccess(false) //TODO: pass message + onClose() + return + } else { + setSuccess(true) //TODO: pass message + } + + val content = response.entity.content.buffered() + stream = content + var buffer = "" + val buf = ByteArray(BUFFER_SIZE) + instance.info("initialized buffer") while (!get.isAborted) { val chars = content.read(buf) if (chars > 0) { buffer += String(buf.dropLast(buf.count() - chars).toByteArray()) - println("DEBUG: " + buffer) + instance.debug(buffer) while (buffer.contains("\n")) { val line = buffer.substringBefore("\n") @@ -50,17 +63,20 @@ class HttpStreamConnection(getClosure: () -> HttpGet, clearClosure: () -> HttpGe break } } + + instance.debug("closing stream") + content.close() + } catch (e: SocketException) { + instance.info("error {}", e) if (!cancelled) { - System.err.println("Bridge Connection interrupted...") - instance.interrupted = true - //TODO: mark connection as interrupted and try to reconnect + instance.error("Bridge Connection interrupted...") + setSuccess(false) } + } finally { + instance.debug("thread finished") + onClose() } - println("DEBUG: closing stream") - content.close() - println("DEBUG: thread finished") - onClose() return } diff --git a/core/src/main/kotlin/matterlink/bridge/MessageHandler.kt b/core/src/main/kotlin/matterlink/bridge/MessageHandler.kt index f4d7aba..398b590 100644 --- a/core/src/main/kotlin/matterlink/bridge/MessageHandler.kt +++ b/core/src/main/kotlin/matterlink/bridge/MessageHandler.kt @@ -1,7 +1,7 @@ package matterlink.bridge import matterlink.config.cfg -//import matterlink.logger +import matterlink.instance import org.apache.http.client.methods.HttpGet import org.apache.http.client.methods.HttpPost import org.apache.http.client.methods.HttpRequestBase @@ -9,11 +9,15 @@ import org.apache.http.entity.ContentType import org.apache.http.entity.StringEntity import org.apache.http.impl.client.HttpClients import java.io.IOException +import java.net.SocketException import java.util.concurrent.ConcurrentLinkedQueue object MessageHandler { - private var connected = false + var connected = false + private var connecting = false + private var enabled = true + private var connectErrors = 0 private var sendErrors = 0 private var streamConnection: HttpStreamConnection var rcvQueue = ConcurrentLinkedQueue() @@ -30,7 +34,7 @@ object MessageHandler { } private fun createThread(clear: Boolean = true): HttpStreamConnection { - println("Attempting to open bridge connection.") + instance.info("Attempting to open bridge connection.") return HttpStreamConnection( { HttpGet(cfg!!.connect.url + "/api/stream").apply { @@ -46,11 +50,23 @@ object MessageHandler { rcvQueue.add( ApiMessage.decode(it) ) -// println("Received: " + it) + instance.debug("Received: " + it) }, { - println("Bridge connection closed!") + instance.warn("Bridge connection closed!") connected = false + connecting = false + }, + { success -> + connecting = false + if (success) { + instance.info("connected successfully") + connectErrors = 0 + connected = true + } else { + connectErrors++ + connected = false + } }, clear ) @@ -58,27 +74,32 @@ object MessageHandler { fun transmit(msg: ApiMessage) { if (connected && streamConnection.isAlive) { - println("Transmitting: " + msg) + instance.debug("Transmitting: " + msg) transmitMessage(msg) } } fun stop() { - println("Closing bridge connection...") + enabled = false + instance.info("Closing bridge connection...") // MessageHandler.transmit(ApiMessage(text="bridge closing", username="Server")) - streamConnection.close() + try { + streamConnection.close() + } catch(e: SocketException) { + instance.error("exception: $e") + } } - fun start(clear: Boolean = true): Boolean { + fun start(clear: Boolean = true) { + enabled = true if (!connected) streamConnection = createThread(clear) if (!streamConnection.isAlive) { + connecting = true streamConnection.start() // MessageHandler.transmit(ApiMessage(text="bridge connected", username="Server")) - connected = true - return connected } - return connected + } private fun transmitMessage(message: ApiMessage) { @@ -93,17 +114,36 @@ object MessageHandler { val response = client.execute(post) val code = response.statusLine.statusCode if (code != 200) { - System.err.println("Server returned $code for $post") + instance.error("Server returned $code for $post") + sendErrors++ + if (sendErrors > 5) { + instance.error("caught too many errors, closing bridge") + stop() + } } sendErrors = 0 } catch (e: IOException) { - System.err.println("sending message caused $e") + instance.error("sending message caused $e") sendErrors++ if (sendErrors > 5) { - System.err.println("caught too many errors, closing bridge") + instance.error("caught too many errors, closing bridge") stop() } } } + + fun checkConnection(tick: Int) { + if (enabled && tick % 20 == 0 && !MessageHandler.connected && !connecting) { + + if (connectErrors > 5) { + instance.fatal("caught too many errors, closing bridge") + stop() + return + } + + instance.info("Trying to reconnect") + MessageHandler.start(clear = false) + } + } } diff --git a/core/src/main/kotlin/matterlink/bridge/ServerChatHandler.kt b/core/src/main/kotlin/matterlink/bridge/ServerChatHandler.kt index 4c07e75..99030f1 100644 --- a/core/src/main/kotlin/matterlink/bridge/ServerChatHandler.kt +++ b/core/src/main/kotlin/matterlink/bridge/ServerChatHandler.kt @@ -1,6 +1,5 @@ package matterlink.bridge -//import matterlink.logger import matterlink.instance import matterlink.bridge.command.BridgeCommandRegistry import matterlink.config.cfg @@ -11,14 +10,13 @@ object ServerChatHandler { * This method must be called every server tick with no arguments. */ fun writeIncomingToChat(tick: Int) { - instance.reconnect(tick) + MessageHandler.checkConnection(tick) if (MessageHandler.rcvQueue.isNotEmpty()) - println("incoming: " + MessageHandler.rcvQueue.toString()) + instance.debug("incoming: " + MessageHandler.rcvQueue.toString()) val nextMessage = MessageHandler.rcvQueue.poll() if (nextMessage != null && nextMessage.gateway == cfg!!.connect.gateway) { if (!nextMessage.text.isBlank()) { - val section = '\u00A7' val message = when (nextMessage.event) { "user_action" -> nextMessage.format(cfg!!.formatting.action) "" -> { @@ -30,11 +28,11 @@ object ServerChatHandler { val user = nextMessage.username val text = nextMessage.text val json = nextMessage.encode() - println("Threw out message with unhandled event: ${nextMessage.event}") - println(" Message contents:") - println(" User: $user") - println(" Text: $text") - println(" JSON: $json") + instance.debug("Threw out message with unhandled event: ${nextMessage.event}") + instance.debug(" Message contents:") + instance.debug(" User: $user") + instance.debug(" Text: $text") + instance.debug(" JSON: $json") return } } diff --git a/core/src/main/kotlin/matterlink/bridge/command/BridgeCommandRegistry.kt b/core/src/main/kotlin/matterlink/bridge/command/BridgeCommandRegistry.kt index f240354..9f08948 100644 --- a/core/src/main/kotlin/matterlink/bridge/command/BridgeCommandRegistry.kt +++ b/core/src/main/kotlin/matterlink/bridge/command/BridgeCommandRegistry.kt @@ -1,7 +1,7 @@ package matterlink.bridge.command import matterlink.config.cfg -//import matterlink.logger +import matterlink.instance import java.util.* object BridgeCommandRegistry { @@ -23,7 +23,7 @@ object BridgeCommandRegistry { fun register(cmd: IBridgeCommand): Boolean { if (cmd.name.isBlank() || commandMap.containsKey(cmd.name)) { - System.out.println("Failed to register command: '${cmd.name}'") + instance.info("Failed to register command: '${cmd.name}'") return false } commandMap[cmd.name] = cmd diff --git a/core/src/main/kotlin/matterlink/handlers/ChatHandler.kt b/core/src/main/kotlin/matterlink/handlers/ChatHandler.kt index 48211df..3e98ab2 100644 --- a/core/src/main/kotlin/matterlink/handlers/ChatHandler.kt +++ b/core/src/main/kotlin/matterlink/handlers/ChatHandler.kt @@ -2,7 +2,7 @@ package matterlink.handlers import matterlink.bridge.ApiMessage import matterlink.bridge.MessageHandler -//import matterlink.logger +import matterlink.instance object ChatHandler { fun handleChat(user: String, msg: String) { @@ -12,7 +12,7 @@ object ChatHandler { username = user, text = message )) - else -> println("WARN: dropped blank message by '$user'") + else -> instance.warn("WARN: dropped blank message by '$user'") } } } diff --git a/core/src/main/resources/mcmod.info b/core/src/main/resources/mcmod.info index 950a1ec..33764a4 100644 --- a/core/src/main/resources/mcmod.info +++ b/core/src/main/resources/mcmod.info @@ -4,6 +4,8 @@ "description": "Minecraft Server Matterbridge link", "version": "${version}", "mcversion": "${mcversion}", + "url": "https://github.com/elytra/MatterLink", "authorList":["Arcanitor", "NikkyAi"], - "credits": "Blame Nikky for talking me into this." + "credits": "Blame Nikky for talking me into this.", + "dependencies": ["forgelin"] }] \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 551e3e5..e9664a8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1 +1 @@ -mod_version = 1.2 +mod_version = 1.2.1