minecraft message formatting

added appropriate events to join / leave
fixed crashing connection
added systemUser configuration option
general cleanup and robustness fixes
This commit is contained in:
Nikky Ai 2018-01-24 04:07:37 +01:00 committed by DaMachinator
parent 54eb09c652
commit f7909c5685
10 changed files with 122 additions and 57 deletions

View File

@ -7,17 +7,26 @@ var cfg: CivilEngineeringConfig? = null
class CivilEngineeringConfig(file: File) { class CivilEngineeringConfig(file: File) {
private val CATEGORY_RELAY_OPTIONS = "relay" private val CATEGORY_RELAY_OPTIONS = "relay"
private val CATEGORY_FORMATTING = "formatting"
private val CATEGORY_CONNECTION = "connection" private val CATEGORY_CONNECTION = "connection"
val relay: RelayOptions val relay: RelayOptions
val connect: ConnectOptions val connect: ConnectOptions
val formatting: FormattingOptions
data class RelayOptions( data class RelayOptions(
val systemUser: String,
val deathEvents: Boolean, val deathEvents: Boolean,
val advancements: Boolean, val advancements: Boolean,
val joinLeave: Boolean val joinLeave: Boolean
) )
data class FormattingOptions(
val chat: String,
val joinLeave: String,
val action: String
)
data class ConnectOptions( data class ConnectOptions(
val url: String, val url: String,
val authToken: String, val authToken: String,
@ -29,9 +38,14 @@ class CivilEngineeringConfig(file: File) {
val config = Configuration(file.resolve("CivilEngineering.cfg")) val config = Configuration(file.resolve("CivilEngineering.cfg"))
config.addCustomCategoryComment(CATEGORY_RELAY_OPTIONS, "Relay options") config.addCustomCategoryComment(CATEGORY_RELAY_OPTIONS, "Relay options")
config.addCustomCategoryComment(CATEGORY_CONNECTION, "Connection settings")
relay = RelayOptions( relay = RelayOptions(
systemUser = config.getString(
"systemUser",
CATEGORY_RELAY_OPTIONS,
"Server",
"name of the server user"
),
deathEvents = config.getBoolean( deathEvents = config.getBoolean(
"deathEvents", "deathEvents",
CATEGORY_RELAY_OPTIONS, CATEGORY_RELAY_OPTIONS,
@ -48,10 +62,34 @@ class CivilEngineeringConfig(file: File) {
"joinLeave", "joinLeave",
CATEGORY_RELAY_OPTIONS, CATEGORY_RELAY_OPTIONS,
false, 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( connect = ConnectOptions(
url = config.getString( url = config.getString(
"connectURL", "connectURL",

View File

@ -1,10 +1,11 @@
package civilengineering.bridge package civilengineering.bridge
import civilengineering.cfg import civilengineering.cfg
import civilengineering.util.antiping
import com.google.gson.Gson import com.google.gson.Gson
data class ApiMessage( data class ApiMessage(
val username: String = "", val username: String = cfg!!.relay.systemUser,
val text: String = "", val text: String = "",
val gateway: String = cfg!!.connect.gateway, val gateway: String = cfg!!.connect.gateway,
val channel: String = "", val channel: String = "",
@ -28,4 +29,22 @@ data class ApiMessage(
fun encode(): String { fun encode(): String {
return gson.toJson(this) 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
}
} }

View File

@ -8,7 +8,7 @@ import java.net.SocketException
val BUFFER_SIZE = 1000 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 val client = HttpClients.createDefault()
private var stream: InputStream? = null private var stream: InputStream? = null
@ -42,11 +42,12 @@ class HttpStreamConnection(private val getClosure: () -> HttpGet, private val mh
} }
} }
} catch (e: SocketException) { } catch (e: SocketException) {
// CivilEngineering.logger.error("Bridge Connection interrupted...")
} }
CivilEngineering.logger.debug("closing stream") CivilEngineering.logger.debug("closing stream")
content.close() content.close()
CivilEngineering.logger.debug("thread finished") CivilEngineering.logger.debug("thread finished")
onClose()
return return
} }

View File

@ -15,6 +15,15 @@ import java.util.concurrent.ConcurrentLinkedQueue
object MessageHandler { object MessageHandler {
private var connected = false private var connected = false
private var sendErrors = 0 private var sendErrors = 0
private var streamConnection: HttpStreamConnection
var rcvQueue = ConcurrentLinkedQueue<ApiMessage>()
init {
streamConnection = createThread()
streamConnection.start()
connected = true
}
fun HttpRequestBase.authorize() { fun HttpRequestBase.authorize() {
if (cfg!!.connect.authToken.isNotEmpty() && getHeaders("Authorization").isEmpty()) if (cfg!!.connect.authToken.isNotEmpty() && getHeaders("Authorization").isEmpty())
setHeader("Authorization", "Bearer " + cfg!!.connect.authToken) setHeader("Authorization", "Bearer " + cfg!!.connect.authToken)
@ -33,14 +42,14 @@ object MessageHandler {
ApiMessage.decode(it) ApiMessage.decode(it)
) )
CivilEngineering.logger.debug("Received: " + it) CivilEngineering.logger.debug("Received: " + it)
},
{
CivilEngineering.logger.info("Bridge connection closed!")
connected = false
} }
) )
} }
private var streamConnection: HttpStreamConnection = createThread()
var rcvQueue = ConcurrentLinkedQueue<ApiMessage>()
fun transmit(msg: ApiMessage) { fun transmit(msg: ApiMessage) {
if (connected && streamConnection.isAlive) { if (connected && streamConnection.isAlive) {
CivilEngineering.logger.debug("Transmitting: " + msg) CivilEngineering.logger.debug("Transmitting: " + msg)
@ -52,15 +61,11 @@ object MessageHandler {
CivilEngineering.logger.info("Closing bridge connection...") CivilEngineering.logger.info("Closing bridge connection...")
// MessageHandler.transmit(ApiMessage(text="bridge closing", username="Server")) // MessageHandler.transmit(ApiMessage(text="bridge closing", username="Server"))
streamConnection.close() streamConnection.close()
CivilEngineering.logger.info("Bridge connection closed!")
connected = false
} }
fun start(): Boolean { fun start(): Boolean {
if (streamConnection.cancelled) { if (!connected)
streamConnection = createThread() streamConnection = createThread()
}
if (!streamConnection.isAlive) { if (!streamConnection.isAlive) {
streamConnection.start() streamConnection.start()
// MessageHandler.transmit(ApiMessage(text="bridge connected", username="Server")) // MessageHandler.transmit(ApiMessage(text="bridge connected", username="Server"))

View File

@ -2,8 +2,6 @@ package civilengineering.bridge
import civilengineering.CivilEngineering import civilengineering.CivilEngineering
import civilengineering.cfg import civilengineering.cfg
import civilengineering.util.Color
import civilengineering.util.color
import net.minecraft.util.text.TextComponentString import net.minecraft.util.text.TextComponentString
import net.minecraftforge.fml.common.FMLCommonHandler import net.minecraftforge.fml.common.FMLCommonHandler
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
@ -17,24 +15,21 @@ class ServerChatHelper {
val nextMessage = MessageHandler.rcvQueue.poll() val nextMessage = MessageHandler.rcvQueue.poll()
if (nextMessage != null && nextMessage.gateway == cfg!!.connect.gateway) { if (nextMessage != null && nextMessage.gateway == cfg!!.connect.gateway) {
val user = nextMessage.username if (!nextMessage.text.isBlank()) {
val text = nextMessage.text.trim()
val chan = nextMessage.channel
val message: String
if (!text.isEmpty()) {
val section = '\u00A7' val section = '\u00A7'
val event = nextMessage.event val message = when (nextMessage.event) {
message = when (event) { "user_action" -> nextMessage.format(cfg!!.formatting.action)
"user_action" -> "* $user $text" "" -> nextMessage.format(cfg!!.formatting.chat)
"" -> "<$user> $text" "join_leave" -> nextMessage.format(cfg!!.formatting.joinLeave)
"join_leave" -> "-- $user $text $chan".color(Color.GOLD)
else -> { 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("Threw out message with unhandled event: $event")
CivilEngineering.logger.debug(" Message contents:") CivilEngineering.logger.debug(" Message contents:")
CivilEngineering.logger.debug(" User: $user") CivilEngineering.logger.debug(" User: $user")
CivilEngineering.logger.debug(" Text: $text") CivilEngineering.logger.debug(" Text: $text")
CivilEngineering.logger.debug(" JSON: $json")
return return
} }
} }

View File

@ -1,9 +1,9 @@
package civilengineering.eventhandlers package civilengineering.eventhandlers
import civilengineering.util.Util.antiping
import civilengineering.bridge.ApiMessage import civilengineering.bridge.ApiMessage
import civilengineering.bridge.MessageHandler import civilengineering.bridge.MessageHandler
import civilengineering.cfg import civilengineering.cfg
import civilengineering.util.antiping
import net.minecraftforge.event.entity.player.AdvancementEvent import net.minecraftforge.event.entity.player.AdvancementEvent
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
@ -13,7 +13,8 @@ class AdvancementEventHandler {
if (cfg!!.relay.advancements && event.advancement.display != null) { if (cfg!!.relay.advancements && event.advancement.display != null) {
val player = event.entityPlayer.name.antiping() val player = event.entityPlayer.name.antiping()
val content = event.advancement.displayText.unformattedText 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" text = "$player has earned the advancement $content"
)) ))
} }

View File

@ -8,8 +8,11 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
class ChatMessageHandler { class ChatMessageHandler {
@SubscribeEvent @SubscribeEvent
fun handleServerChatEvent(event: ServerChatEvent) { fun handleServerChatEvent(event: ServerChatEvent) {
val message = event.message.trim { it <= ' ' } val message = event.message.trim()
if (message.isNotBlank()) if (message.isNotBlank())
MessageHandler.transmit(ApiMessage(username = event.username, text = message)) MessageHandler.transmit(ApiMessage(
username = event.username,
text = message)
)
} }
} }

View File

@ -1,9 +1,9 @@
package civilengineering.eventhandlers package civilengineering.eventhandlers
import civilengineering.util.Util.antiping
import civilengineering.bridge.ApiMessage import civilengineering.bridge.ApiMessage
import civilengineering.bridge.MessageHandler import civilengineering.bridge.MessageHandler
import civilengineering.cfg import civilengineering.cfg
import civilengineering.util.antiping
import net.minecraft.entity.player.EntityPlayer import net.minecraft.entity.player.EntityPlayer
import net.minecraftforge.event.entity.living.LivingDeathEvent import net.minecraftforge.event.entity.living.LivingDeathEvent
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
@ -14,8 +14,12 @@ class DeathEventHandler {
if (cfg!!.relay.deathEvents) { if (cfg!!.relay.deathEvents) {
val entity = event.entityLiving val entity = event.entityLiving
if (entity is EntityPlayer) { if (entity is EntityPlayer) {
var message: String = entity.getCombatTracker().deathMessage.unformattedText val message = entity.getCombatTracker().deathMessage.unformattedText
MessageHandler.transmit(ApiMessage(username = "Server", text = message.antiping())) .replace(entity.name, entity.name.antiping())
MessageHandler.transmit(ApiMessage(
username = cfg!!.relay.systemUser,
text = message
))
} }
} }
} }

View File

@ -1,11 +1,11 @@
package civilengineering.eventhandlers 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.ApiMessage
import civilengineering.bridge.MessageHandler import civilengineering.bridge.MessageHandler
import civilengineering.cfg import civilengineering.cfg
import civilengineering.util.antiping
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
import net.minecraftforge.fml.common.gameevent.PlayerEvent
class JoinLeaveHandler { class JoinLeaveHandler {
@SubscribeEvent @SubscribeEvent
@ -13,8 +13,9 @@ class JoinLeaveHandler {
if (cfg!!.relay.joinLeave) { if (cfg!!.relay.joinLeave) {
val player: String = event.player.name.antiping() val player: String = event.player.name.antiping()
MessageHandler.transmit(ApiMessage( MessageHandler.transmit(ApiMessage(
username = "Server", username = cfg!!.relay.systemUser,
text = "$player has connected to the server." text = "$player has connected to the server.",
event = "join_leave"
)) ))
} }
} }
@ -22,10 +23,11 @@ class JoinLeaveHandler {
@SubscribeEvent @SubscribeEvent
fun handleLeaveEvent(event: PlayerEvent.PlayerLoggedOutEvent) { fun handleLeaveEvent(event: PlayerEvent.PlayerLoggedOutEvent) {
if (cfg!!.relay.joinLeave) { if (cfg!!.relay.joinLeave) {
val player:String = event.player.name.antiping() val player = event.player.name.antiping()
MessageHandler.transmit(ApiMessage( MessageHandler.transmit(ApiMessage(
username = "Server", username = cfg!!.relay.systemUser,
text = "$player has disconnected from the server." text = "$player has disconnected from the server.",
event = "join_leave"
)) ))
} }
} }

View File

@ -1,13 +1,10 @@
package civilengineering.util package civilengineering.util
object Util { private const val ZWSP: Char = '\u200b'
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 { fun String.antiping(): String {
return this[0].toString() + ZWSP + this.substring(1) return this[0].toString() + ZWSP + this.substring(1)
} }
}