From f7909c568579721c21176ebc9ee72ca2bc990e18 Mon Sep 17 00:00:00 2001 From: Nikky Ai Date: Wed, 24 Jan 2018 04:07:37 +0100 Subject: [PATCH] minecraft message formatting added appropriate events to join / leave fixed crashing connection added systemUser configuration option general cleanup and robustness fixes --- .../CivilEngineeringConfig.kt | 44 +++++++++++++++++-- .../civilengineering/bridge/ApiMessage.kt | 21 ++++++++- .../bridge/HttpStreamConnection.kt | 5 ++- .../civilengineering/bridge/MessageHandler.kt | 25 ++++++----- .../bridge/ServerChatHelper.kt | 23 ++++------ .../eventhandlers/AdvancementEventHandler.kt | 7 +-- .../eventhandlers/ChatMessageHandler.kt | 7 ++- .../eventhandlers/DeathEventHandler.kt | 10 +++-- .../eventhandlers/JoinLeaveHandler.kt | 24 +++++----- src/main/kotlin/civilengineering/util/Util.kt | 13 +++--- 10 files changed, 122 insertions(+), 57 deletions(-) diff --git a/src/main/kotlin/civilengineering/CivilEngineeringConfig.kt b/src/main/kotlin/civilengineering/CivilEngineeringConfig.kt index 4d4f4d9..93713e0 100644 --- a/src/main/kotlin/civilengineering/CivilEngineeringConfig.kt +++ b/src/main/kotlin/civilengineering/CivilEngineeringConfig.kt @@ -7,17 +7,26 @@ var cfg: CivilEngineeringConfig? = null class CivilEngineeringConfig(file: File) { private val CATEGORY_RELAY_OPTIONS = "relay" + private val CATEGORY_FORMATTING = "formatting" private val CATEGORY_CONNECTION = "connection" val relay: RelayOptions val connect: ConnectOptions + val formatting: FormattingOptions data class RelayOptions( + val systemUser: String, val deathEvents: Boolean, val advancements: Boolean, val joinLeave: Boolean ) + data class FormattingOptions( + val chat: String, + val joinLeave: String, + val action: String + ) + data class ConnectOptions( val url: String, val authToken: String, @@ -29,9 +38,14 @@ class CivilEngineeringConfig(file: File) { val config = Configuration(file.resolve("CivilEngineering.cfg")) config.addCustomCategoryComment(CATEGORY_RELAY_OPTIONS, "Relay options") - config.addCustomCategoryComment(CATEGORY_CONNECTION, "Connection settings") - relay = RelayOptions( + + systemUser = config.getString( + "systemUser", + CATEGORY_RELAY_OPTIONS, + "Server", + "name of the server user" + ), deathEvents = config.getBoolean( "deathEvents", CATEGORY_RELAY_OPTIONS, @@ -48,10 +62,34 @@ class CivilEngineeringConfig(file: File) { "joinLeave", CATEGORY_RELAY_OPTIONS, false, - "Relay when a player joins or leaves the game [NOT IMPLEMENTED]" + "Relay when a player joins or leaves the game" ) ) + config.addCustomCategoryComment(CATEGORY_FORMATTING, "Formatting options " + + "available variables: {username}, {text}, {gateway}, {channel}, {protocol}, {username:antiping}") + formatting = FormattingOptions( + chat = config.getString( + "chat", + CATEGORY_FORMATTING, + "<{username}> {text}", + "generic chat event, just talking" + ), + joinLeave = config.getString( + "joinLeave", + CATEGORY_FORMATTING, + "§6-- {username} {text}", + "leave and jon events from other gateways" + ), + action = config.getString( + "action", + CATEGORY_FORMATTING, + "§5* {username} {text}", + "/me sent by users from other gateways" + ) + ) + + config.addCustomCategoryComment(CATEGORY_CONNECTION, "Connection settings") connect = ConnectOptions( url = config.getString( "connectURL", diff --git a/src/main/kotlin/civilengineering/bridge/ApiMessage.kt b/src/main/kotlin/civilengineering/bridge/ApiMessage.kt index c2f5cd8..de4ad10 100644 --- a/src/main/kotlin/civilengineering/bridge/ApiMessage.kt +++ b/src/main/kotlin/civilengineering/bridge/ApiMessage.kt @@ -1,10 +1,11 @@ package civilengineering.bridge import civilengineering.cfg +import civilengineering.util.antiping import com.google.gson.Gson data class ApiMessage( - val username: String = "", + val username: String = cfg!!.relay.systemUser, val text: String = "", val gateway: String = cfg!!.connect.gateway, val channel: String = "", @@ -28,4 +29,22 @@ data class ApiMessage( fun encode(): String { return gson.toJson(this) } + + fun format(fmt: String): String { + var result = fmt + result = result.helpFormat("{username}", username) + result = result.helpFormat("{text}", text) + result = result.helpFormat("{gateway}", gateway) + result = result.helpFormat("{channel}", channel) + result = result.helpFormat("{protocol}", protocol) + result = result.helpFormat("{username:antiping}", username.antiping()) + return result + } + + private fun String.helpFormat(name: String, value: String): String { + if (this.contains(name)) { + return this.replace(name, value) + } + return this + } } \ No newline at end of file diff --git a/src/main/kotlin/civilengineering/bridge/HttpStreamConnection.kt b/src/main/kotlin/civilengineering/bridge/HttpStreamConnection.kt index 475141f..3cd3351 100644 --- a/src/main/kotlin/civilengineering/bridge/HttpStreamConnection.kt +++ b/src/main/kotlin/civilengineering/bridge/HttpStreamConnection.kt @@ -8,7 +8,7 @@ import java.net.SocketException val BUFFER_SIZE = 1000 -class HttpStreamConnection(private val getClosure: () -> HttpGet, private val mhandler: (String) -> Unit) : Thread() { +class HttpStreamConnection(private val getClosure: () -> HttpGet, private val mhandler: (String) -> Unit, private val onClose: () -> Unit) : Thread() { private val client = HttpClients.createDefault() private var stream: InputStream? = null @@ -42,11 +42,12 @@ class HttpStreamConnection(private val getClosure: () -> HttpGet, private val mh } } } catch (e: SocketException) { - +// CivilEngineering.logger.error("Bridge Connection interrupted...") } CivilEngineering.logger.debug("closing stream") content.close() CivilEngineering.logger.debug("thread finished") + onClose() return } diff --git a/src/main/kotlin/civilengineering/bridge/MessageHandler.kt b/src/main/kotlin/civilengineering/bridge/MessageHandler.kt index 018abf8..c493f58 100644 --- a/src/main/kotlin/civilengineering/bridge/MessageHandler.kt +++ b/src/main/kotlin/civilengineering/bridge/MessageHandler.kt @@ -15,6 +15,15 @@ import java.util.concurrent.ConcurrentLinkedQueue object MessageHandler { private var connected = false private var sendErrors = 0 + private var streamConnection: HttpStreamConnection + var rcvQueue = ConcurrentLinkedQueue() + + init { + streamConnection = createThread() + streamConnection.start() + connected = true + } + fun HttpRequestBase.authorize() { if (cfg!!.connect.authToken.isNotEmpty() && getHeaders("Authorization").isEmpty()) setHeader("Authorization", "Bearer " + cfg!!.connect.authToken) @@ -33,14 +42,14 @@ object MessageHandler { ApiMessage.decode(it) ) CivilEngineering.logger.debug("Received: " + it) + }, + { + CivilEngineering.logger.info("Bridge connection closed!") + connected = false } ) } - private var streamConnection: HttpStreamConnection = createThread() - - var rcvQueue = ConcurrentLinkedQueue() - fun transmit(msg: ApiMessage) { if (connected && streamConnection.isAlive) { CivilEngineering.logger.debug("Transmitting: " + msg) @@ -52,15 +61,11 @@ object MessageHandler { CivilEngineering.logger.info("Closing bridge connection...") // MessageHandler.transmit(ApiMessage(text="bridge closing", username="Server")) streamConnection.close() - - CivilEngineering.logger.info("Bridge connection closed!") - connected = false } fun start(): Boolean { - if (streamConnection.cancelled) { + if (!connected) streamConnection = createThread() - } if (!streamConnection.isAlive) { streamConnection.start() // MessageHandler.transmit(ApiMessage(text="bridge connected", username="Server")) @@ -88,7 +93,7 @@ object MessageHandler { } catch (e: IOException) { CivilEngineering.logger.error("sending message caused $e") sendErrors++ - if(sendErrors > 5) { + if (sendErrors > 5) { CivilEngineering.logger.error("caught too many errors, closing bridge") stop() } diff --git a/src/main/kotlin/civilengineering/bridge/ServerChatHelper.kt b/src/main/kotlin/civilengineering/bridge/ServerChatHelper.kt index 96fc56b..2c57709 100644 --- a/src/main/kotlin/civilengineering/bridge/ServerChatHelper.kt +++ b/src/main/kotlin/civilengineering/bridge/ServerChatHelper.kt @@ -2,8 +2,6 @@ package civilengineering.bridge import civilengineering.CivilEngineering import civilengineering.cfg -import civilengineering.util.Color -import civilengineering.util.color import net.minecraft.util.text.TextComponentString import net.minecraftforge.fml.common.FMLCommonHandler import net.minecraftforge.fml.common.eventhandler.SubscribeEvent @@ -17,24 +15,21 @@ class ServerChatHelper { val nextMessage = MessageHandler.rcvQueue.poll() if (nextMessage != null && nextMessage.gateway == cfg!!.connect.gateway) { - val user = nextMessage.username - val text = nextMessage.text.trim() - val chan = nextMessage.channel - - val message: String - - if (!text.isEmpty()) { + if (!nextMessage.text.isBlank()) { val section = '\u00A7' - val event = nextMessage.event - message = when (event) { - "user_action" -> "* $user $text" - "" -> "<$user> $text" - "join_leave" -> "-- $user $text $chan".color(Color.GOLD) + val message = when (nextMessage.event) { + "user_action" -> nextMessage.format(cfg!!.formatting.action) + "" -> nextMessage.format(cfg!!.formatting.chat) + "join_leave" -> nextMessage.format(cfg!!.formatting.joinLeave) else -> { + val user = nextMessage.username + val text = nextMessage.text + val json = nextMessage.encode() CivilEngineering.logger.debug("Threw out message with unhandled event: $event") CivilEngineering.logger.debug(" Message contents:") CivilEngineering.logger.debug(" User: $user") CivilEngineering.logger.debug(" Text: $text") + CivilEngineering.logger.debug(" JSON: $json") return } } diff --git a/src/main/kotlin/civilengineering/eventhandlers/AdvancementEventHandler.kt b/src/main/kotlin/civilengineering/eventhandlers/AdvancementEventHandler.kt index 2de6547..241f16d 100644 --- a/src/main/kotlin/civilengineering/eventhandlers/AdvancementEventHandler.kt +++ b/src/main/kotlin/civilengineering/eventhandlers/AdvancementEventHandler.kt @@ -1,19 +1,20 @@ package civilengineering.eventhandlers -import civilengineering.util.Util.antiping import civilengineering.bridge.ApiMessage import civilengineering.bridge.MessageHandler import civilengineering.cfg +import civilengineering.util.antiping import net.minecraftforge.event.entity.player.AdvancementEvent import net.minecraftforge.fml.common.eventhandler.SubscribeEvent class AdvancementEventHandler { @SubscribeEvent fun handleAdvancements(event: AdvancementEvent) { - if(cfg!!.relay.advancements && event.advancement.display != null) { + if (cfg!!.relay.advancements && event.advancement.display != null) { val player = event.entityPlayer.name.antiping() val content = event.advancement.displayText.unformattedText - MessageHandler.transmit(ApiMessage(username = "Server", + MessageHandler.transmit(ApiMessage( + username = cfg!!.relay.systemUser, text = "$player has earned the advancement $content" )) } diff --git a/src/main/kotlin/civilengineering/eventhandlers/ChatMessageHandler.kt b/src/main/kotlin/civilengineering/eventhandlers/ChatMessageHandler.kt index 76ccfa3..88f6343 100644 --- a/src/main/kotlin/civilengineering/eventhandlers/ChatMessageHandler.kt +++ b/src/main/kotlin/civilengineering/eventhandlers/ChatMessageHandler.kt @@ -8,8 +8,11 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent class ChatMessageHandler { @SubscribeEvent fun handleServerChatEvent(event: ServerChatEvent) { - val message = event.message.trim { it <= ' ' } + val message = event.message.trim() if (message.isNotBlank()) - MessageHandler.transmit(ApiMessage(username = event.username, text = message)) + MessageHandler.transmit(ApiMessage( + username = event.username, + text = message) + ) } } diff --git a/src/main/kotlin/civilengineering/eventhandlers/DeathEventHandler.kt b/src/main/kotlin/civilengineering/eventhandlers/DeathEventHandler.kt index 9ecc9b4..fe5ab48 100644 --- a/src/main/kotlin/civilengineering/eventhandlers/DeathEventHandler.kt +++ b/src/main/kotlin/civilengineering/eventhandlers/DeathEventHandler.kt @@ -1,9 +1,9 @@ package civilengineering.eventhandlers -import civilengineering.util.Util.antiping import civilengineering.bridge.ApiMessage import civilengineering.bridge.MessageHandler import civilengineering.cfg +import civilengineering.util.antiping import net.minecraft.entity.player.EntityPlayer import net.minecraftforge.event.entity.living.LivingDeathEvent import net.minecraftforge.fml.common.eventhandler.SubscribeEvent @@ -14,8 +14,12 @@ class DeathEventHandler { if (cfg!!.relay.deathEvents) { val entity = event.entityLiving if (entity is EntityPlayer) { - var message: String = entity.getCombatTracker().deathMessage.unformattedText - MessageHandler.transmit(ApiMessage(username = "Server", text = message.antiping())) + val message = entity.getCombatTracker().deathMessage.unformattedText + .replace(entity.name, entity.name.antiping()) + MessageHandler.transmit(ApiMessage( + username = cfg!!.relay.systemUser, + text = message + )) } } } diff --git a/src/main/kotlin/civilengineering/eventhandlers/JoinLeaveHandler.kt b/src/main/kotlin/civilengineering/eventhandlers/JoinLeaveHandler.kt index 4aeff28..3435392 100644 --- a/src/main/kotlin/civilengineering/eventhandlers/JoinLeaveHandler.kt +++ b/src/main/kotlin/civilengineering/eventhandlers/JoinLeaveHandler.kt @@ -1,31 +1,33 @@ package civilengineering.eventhandlers -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent -import net.minecraftforge.fml.common.gameevent.PlayerEvent -import civilengineering.util.Util.antiping import civilengineering.bridge.ApiMessage import civilengineering.bridge.MessageHandler import civilengineering.cfg +import civilengineering.util.antiping +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import net.minecraftforge.fml.common.gameevent.PlayerEvent class JoinLeaveHandler { @SubscribeEvent fun handleJoinEvent(event: PlayerEvent.PlayerLoggedInEvent) { - if(cfg!!.relay.joinLeave) { - val player:String = event.player.name.antiping() + if (cfg!!.relay.joinLeave) { + val player: String = event.player.name.antiping() MessageHandler.transmit(ApiMessage( - username = "Server", - text = "$player has connected to the server." + username = cfg!!.relay.systemUser, + text = "$player has connected to the server.", + event = "join_leave" )) } } @SubscribeEvent fun handleLeaveEvent(event: PlayerEvent.PlayerLoggedOutEvent) { - if(cfg!!.relay.joinLeave) { - val player:String = event.player.name.antiping() + if (cfg!!.relay.joinLeave) { + val player = event.player.name.antiping() MessageHandler.transmit(ApiMessage( - username = "Server", - text = "$player has disconnected from the server." + username = cfg!!.relay.systemUser, + text = "$player has disconnected from the server.", + event = "join_leave" )) } } diff --git a/src/main/kotlin/civilengineering/util/Util.kt b/src/main/kotlin/civilengineering/util/Util.kt index ca0a507..924ff0a 100644 --- a/src/main/kotlin/civilengineering/util/Util.kt +++ b/src/main/kotlin/civilengineering/util/Util.kt @@ -1,13 +1,10 @@ package civilengineering.util -object Util { - const val ZWSP: Char = '\u200b' +private const val ZWSP: Char = '\u200b' - //Inserts a zero-width space at index 1 in the string' +//Inserts a zero-width space at index 1 in the string' - fun String.antiping(): String { - return this[0].toString()+ ZWSP +this.substring(1) - } - -} \ No newline at end of file +fun String.antiping(): String { + return this[0].toString() + ZWSP + this.substring(1) +}