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:
parent
54eb09c652
commit
f7909c5685
|
@ -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",
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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"))
|
||||||
|
@ -88,7 +93,7 @@ object MessageHandler {
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
CivilEngineering.logger.error("sending message caused $e")
|
CivilEngineering.logger.error("sending message caused $e")
|
||||||
sendErrors++
|
sendErrors++
|
||||||
if(sendErrors > 5) {
|
if (sendErrors > 5) {
|
||||||
CivilEngineering.logger.error("caught too many errors, closing bridge")
|
CivilEngineering.logger.error("caught too many errors, closing bridge")
|
||||||
stop()
|
stop()
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,20 @@
|
||||||
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
|
||||||
|
|
||||||
class AdvancementEventHandler {
|
class AdvancementEventHandler {
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
fun handleAdvancements(event: AdvancementEvent) {
|
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 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"
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,31 +1,33 @@
|
||||||
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
|
||||||
fun handleJoinEvent(event: PlayerEvent.PlayerLoggedInEvent) {
|
fun handleJoinEvent(event: PlayerEvent.PlayerLoggedInEvent) {
|
||||||
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"
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@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"
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
|
||||||
return this[0].toString()+ ZWSP +this.substring(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
fun String.antiping(): String {
|
||||||
|
return this[0].toString() + ZWSP + this.substring(1)
|
||||||
}
|
}
|
Loading…
Reference in New Issue