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) {
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",

View File

@ -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
}
}

View File

@ -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
}

View File

@ -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<ApiMessage>()
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<ApiMessage>()
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()
}

View File

@ -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
}
}

View File

@ -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"
))
}

View File

@ -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)
)
}
}

View File

@ -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
))
}
}
}

View File

@ -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"
))
}
}

View File

@ -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'
fun String.antiping(): String {
return this[0].toString()+ ZWSP +this.substring(1)
}
//Inserts a zero-width space at index 1 in the string'
fun String.antiping(): String {
return this[0].toString() + ZWSP + this.substring(1)
}