improve docs and reconnection handling
This commit is contained in:
parent
e5cd059313
commit
c7146ce7df
|
@ -103,6 +103,7 @@ object EventHandler {
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun serverTickEvent(e: TickEvent.ServerTickEvent) {
|
fun serverTickEvent(e: TickEvent.ServerTickEvent) {
|
||||||
TickHandler.handleTick()
|
if(e.phase == TickEvent.Phase.END)
|
||||||
|
TickHandler.handleTick()
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -104,6 +104,7 @@ object EventHandler {
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun serverTickEvent(e: TickEvent.ServerTickEvent) {
|
fun serverTickEvent(e: TickEvent.ServerTickEvent) {
|
||||||
TickHandler.handleTick()
|
if(e.phase == TickEvent.Phase.END)
|
||||||
|
TickHandler.handleTick()
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -96,6 +96,7 @@ object EventHandler {
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun serverTickEvent(e: TickEvent.ServerTickEvent) {
|
fun serverTickEvent(e: TickEvent.ServerTickEvent) {
|
||||||
TickHandler.handleTick()
|
if(e.phase == TickEvent.Phase.END)
|
||||||
|
TickHandler.handleTick()
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -96,6 +96,7 @@ object EventHandler {
|
||||||
//FORGE-DEPENDENT
|
//FORGE-DEPENDENT
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
fun serverTickEvent(e: TickEvent.ServerTickEvent) {
|
fun serverTickEvent(e: TickEvent.ServerTickEvent) {
|
||||||
TickHandler.handleTick()
|
if(e.phase == TickEvent.Phase.END)
|
||||||
|
TickHandler.handleTick()
|
||||||
}
|
}
|
||||||
}
|
}
|
85
README.md
85
README.md
|
@ -5,59 +5,68 @@ A MatterBridge endpoint for MC servers!
|
||||||
THIS MOD REQUIRES YOU TO ALSO RUN A MATTERBRIDGE RELAY
|
THIS MOD REQUIRES YOU TO ALSO RUN A MATTERBRIDGE RELAY
|
||||||
https://github.com/42wim/matterbridge
|
https://github.com/42wim/matterbridge
|
||||||
|
|
||||||
requires api section to be setup along these lines
|
Chat with us on IRC: [#matterbridge @ irc.esper.net](irc://irc.esper.net/matterbridge)
|
||||||
|
|
||||||
|
Requires the matterbridge config api section to be setup along these lines:
|
||||||
|
|
||||||
```
|
```
|
||||||
[api]
|
[api]
|
||||||
[api.local]
|
[api.local]
|
||||||
BindAddress="0.0.0.0:4242" # or listen only to localhost: 127.0.0.1:4242
|
BindAddress="0.0.0.0:4242" # or listen only to localhost: 127.0.0.1:4242
|
||||||
|
|
||||||
#Bearer token used for authentication
|
|
||||||
#curl -H "Authorization: Bearer testtoken" http://localhost:4343/api/messages
|
|
||||||
|
|
||||||
#OPTIONAL (no authorization if token is empty)
|
#OPTIONAL (no authorization if token is empty)
|
||||||
Token="mytoken"
|
Token="mytoken"
|
||||||
|
|
||||||
Buffer=1000
|
Buffer=1000
|
||||||
|
|
||||||
RemoteNickFormat="{NICK}"
|
RemoteNickFormat="{NICK}"
|
||||||
|
|
||||||
ShowJoinPart = true
|
ShowJoinPart = true
|
||||||
```
|
```
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
* Individually configurable relaying of player deaths, achievements/advancements, server join, and server leave
|
* Custom bridge commands, including passthrough to MC!
|
||||||
* Configurable bridge commands sent from chat to MC:
|
Default commands: `help, tps, list, seed, uptime`
|
||||||
|
|
||||||
|
Commands are specified in JSON format as follows:
|
||||||
|
Passthrough command (executes the configured command as if from the MC server console)
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"alias": "tps",
|
||||||
|
"type": "PASSTHROUGH",
|
||||||
|
"execute": "forge tps",
|
||||||
|
"permLevel": 0,
|
||||||
|
"help": "Print server tps",
|
||||||
|
"allowArgs": false
|
||||||
|
}
|
||||||
```
|
```
|
||||||
help: Lists all commands with no arguments,
|
Response command
|
||||||
or displays help for a command
|
```json
|
||||||
players: Lists online players
|
{
|
||||||
uptime: Print server uptime
|
"alias": "uptime",
|
||||||
|
"type": "RESPONSE",
|
||||||
|
"response": "{uptime}",
|
||||||
|
"permLevel": 1,
|
||||||
|
"help": "Print server uptime",
|
||||||
|
"allowArgs": false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
* Command permissions!
|
||||||
|
Higher numbers mean more permissions. Configured on a network-by-network basis.
|
||||||
|
For IRC, this is your hostmask.
|
||||||
|
For Discord, this is your userid (NOT the four-digit number.)
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"irc.esper": {
|
||||||
|
"~DaMachina@hostname.com":1000
|
||||||
|
}
|
||||||
|
}
|
||||||
```
|
```
|
||||||
* Edit and reload the config file without restarting the server!
|
* Edit and reload the config file without restarting the server!
|
||||||
```
|
```
|
||||||
/config <connect|disconnect|reload>
|
/config <connect|disconnect|reload>
|
||||||
Connect or disconnect the bridge,
|
connect: Connects the MC chat to the MatterBridge server
|
||||||
or cycle the connection and reload the config file
|
disconnect: Disconnects the chat from the MatterBridge server
|
||||||
|
reload: Disconnects, reloads the config and custom command files,
|
||||||
|
then reconnects.
|
||||||
```
|
```
|
||||||
* Pass through commands to MineCraft! Fully configurable.
|
|
||||||
```
|
|
||||||
# MC commands that can be executed through the bridge
|
|
||||||
# Separate bridge command and MC command with '=',
|
|
||||||
# separate multiple values with spaces
|
|
||||||
# [default: [tps=forge tps]]
|
|
||||||
S:commandMapping <
|
|
||||||
tps=forge tps
|
|
||||||
>
|
|
||||||
```
|
|
||||||
This default example allows you to run `/forge tps` on the server by typing `$tps` in the chat
|
|
||||||
(replace $ with whatever you've configured as the command prefix).
|
|
||||||
|
|
||||||
**WARNING: There is *NO* permissions checking of any kind for command passthrough!
|
|
||||||
Do not configure passthrough for any commands you would not be comfortable
|
|
||||||
with anyone on your IRC/Discord/etc. executing!**
|
|
||||||
|
|
||||||
|
|
||||||
## Downloads
|
## Downloads
|
||||||
|
|
||||||
|
@ -65,22 +74,26 @@ https://github.com/elytra/MatterLink/releases
|
||||||
|
|
||||||
https://ci.elytradev.com/job/elytra/job/MatterLink/job/master/lastSuccessfulBuild/ - may be unstable
|
https://ci.elytradev.com/job/elytra/job/MatterLink/job/master/lastSuccessfulBuild/ - may be unstable
|
||||||
|
|
||||||
|
https://minecraft.curseforge.com/projects/matterlink
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
|
|
||||||
- forgelin: https://minecraft.curseforge.com/projects/shadowfacts-forgelin
|
- forgelin: https://minecraft.curseforge.com/projects/shadowfacts-forgelin
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
Now you just need to run MatterBridge on the server, the default configuration works with the provided sample.
|
||||||
|
|
||||||
Install matterbridge and try out the basic sample:
|
Install matterbridge and try out the basic sample:
|
||||||
|
|
||||||
```
|
```
|
||||||
go get github.com/42wim/matterbridge
|
go get github.com/42wim/matterbridge
|
||||||
mv matterbridge-sample.toml matterbridge.tom
|
mv matterbridge-sample.toml matterbridge.toml
|
||||||
matterbridge
|
matterbridge
|
||||||
```
|
```
|
||||||
|
|
||||||
Now you just need to run MatterBridge on the server, the default configuration works with the provided sample.
|
now start the server with matterlink (and forgelin )in the mods folder
|
||||||
|
|
||||||
and then [RTFM!!!](https://github.com/42wim/matterbridge#configuration)
|
|
||||||
|
and then [RTFM!!!](https://github.com/42wim/matterbridge#configuration) and configure all your needed gateways, endpoints etc
|
||||||
|
|
||||||
powered by wishful thinking
|
powered by wishful thinking
|
|
@ -49,8 +49,10 @@ class HttpStreamConnection(private val rcvQueue: ConcurrentLinkedQueue<ApiMessag
|
||||||
if (success) {
|
if (success) {
|
||||||
instance.info("connected successfully")
|
instance.info("connected successfully")
|
||||||
messageHandler.connectErrors = 0
|
messageHandler.connectErrors = 0
|
||||||
|
messageHandler.reconnectCoodown = 0
|
||||||
connected = true
|
connected = true
|
||||||
} else {
|
} else {
|
||||||
|
messageHandler.reconnectCoodown = messageHandler.connectErrors
|
||||||
messageHandler.connectErrors++
|
messageHandler.connectErrors++
|
||||||
connected = false
|
connected = false
|
||||||
instance.warn("connectErrors: ${messageHandler.connectErrors}")
|
instance.warn("connectErrors: ${messageHandler.connectErrors}")
|
||||||
|
@ -76,6 +78,8 @@ class HttpStreamConnection(private val rcvQueue: ConcurrentLinkedQueue<ApiMessag
|
||||||
r.entity.content.bufferedReader().forEachLine {
|
r.entity.content.bufferedReader().forEachLine {
|
||||||
instance.debug("skipping $it")
|
instance.debug("skipping $it")
|
||||||
}
|
}
|
||||||
|
//connection was not refused, url and token should be correct
|
||||||
|
setSuccess(true)
|
||||||
}
|
}
|
||||||
val response = client.execute(get)
|
val response = client.execute(get)
|
||||||
if (response.statusLine.statusCode != 200) {
|
if (response.statusLine.statusCode != 200) {
|
||||||
|
|
|
@ -13,6 +13,7 @@ object MessageHandler {
|
||||||
var enabled: Boolean = false
|
var enabled: Boolean = false
|
||||||
private var sendErrors = 0
|
private var sendErrors = 0
|
||||||
var connectErrors = 0
|
var connectErrors = 0
|
||||||
|
var reconnectCoodown = 0
|
||||||
private var streamConnection: HttpStreamConnection
|
private var streamConnection: HttpStreamConnection
|
||||||
var rcvQueue = ConcurrentLinkedQueue<ApiMessage>()
|
var rcvQueue = ConcurrentLinkedQueue<ApiMessage>()
|
||||||
private set
|
private set
|
||||||
|
@ -103,14 +104,18 @@ object MessageHandler {
|
||||||
fun checkConnection() {
|
fun checkConnection() {
|
||||||
if (enabled && !streamConnection.connected && !streamConnection.connecting) {
|
if (enabled && !streamConnection.connected && !streamConnection.connecting) {
|
||||||
|
|
||||||
if (connectErrors > 5) {
|
if (connectErrors >= 10) {
|
||||||
instance.fatal("Caught too many errors, closing bridge")
|
instance.fatal("Caught too many errors, closing bridge")
|
||||||
stop("Interrupting connection to matterbridge API due to accumulated connection errors")
|
stop("Interrupting connection to matterbridge API due to accumulated connection errors")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
instance.info("Trying to reconnect")
|
if (reconnectCoodown <= 0) {
|
||||||
MessageHandler.start(clear = false, message = "Reconnecting to matterbridge API after connection error")
|
instance.info("Trying to reconnect")
|
||||||
|
MessageHandler.start(clear = false, message = "Reconnecting to matterbridge API after connection error")
|
||||||
|
} else {
|
||||||
|
reconnectCoodown--
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,10 +35,10 @@ object CommandConfig {
|
||||||
),
|
),
|
||||||
CustomCommand(
|
CustomCommand(
|
||||||
alias = "uptime",
|
alias = "uptime",
|
||||||
type = CommandType.PASSTHROUGH,
|
type = CommandType.RESPONSE,
|
||||||
permLevel = 1,
|
permLevel = 1,
|
||||||
response = "{uptime}",
|
response = "{uptime}",
|
||||||
help = "Print server world seed",
|
help = "Print server uptime",
|
||||||
allowArgs = false
|
allowArgs = false
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
@ -12,16 +12,15 @@ import matterlink.update.UpdateChecker
|
||||||
object TickHandler {
|
object TickHandler {
|
||||||
private var totalTicks = 0
|
private var totalTicks = 0
|
||||||
private var accumulator = 0
|
private var accumulator = 0
|
||||||
private const val updateInterval = 12 * 60 * 20
|
private const val updateInterval = 12 * 60 * 60 * 20
|
||||||
fun handleTick() {
|
fun handleTick() {
|
||||||
totalTicks++
|
totalTicks++
|
||||||
if (totalTicks % 20 == 0) {
|
if (totalTicks % 100 == 0) {
|
||||||
MessageHandler.checkConnection()
|
MessageHandler.checkConnection()
|
||||||
}
|
}
|
||||||
|
|
||||||
ServerChatHandler.writeIncomingToChat()
|
ServerChatHandler.writeIncomingToChat()
|
||||||
|
|
||||||
|
|
||||||
if(accumulator++ > updateInterval) {
|
if(accumulator++ > updateInterval) {
|
||||||
accumulator -= updateInterval
|
accumulator -= updateInterval
|
||||||
UpdateChecker.run()
|
UpdateChecker.run()
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
#You can configure multiple servers "[irc.name]" or "[irc.name2]"
|
#You can configure multiple servers "[irc.name]" or "[irc.name2]"
|
||||||
#In this example we use [irc.freenode]
|
#In this example we use [irc.freenode]
|
||||||
#REQUIRED
|
#REQUIRED
|
||||||
[irc.freenode]
|
[irc.esper]
|
||||||
#irc server to connect to.
|
#irc server to connect to.
|
||||||
#REQUIRED
|
#REQUIRED
|
||||||
Server="irc.esper.net:6697"
|
Server="irc.esper.net:6697"
|
||||||
|
@ -117,6 +117,10 @@ ReplaceMessages=[ ["cat","dog"] ]
|
||||||
#optional (default empty)
|
#optional (default empty)
|
||||||
ReplaceNicks=[ ["user--","user"] ]
|
ReplaceNicks=[ ["user--","user"] ]
|
||||||
|
|
||||||
|
#extra label that can be used in the RemoteNickFormat
|
||||||
|
#optional (default empty)
|
||||||
|
Label=""
|
||||||
|
|
||||||
#RemoteNickFormat defines how remote users appear on this bridge
|
#RemoteNickFormat defines how remote users appear on this bridge
|
||||||
#The string "{NICK}" (case sensitive) will be replaced by the actual nick / username.
|
#The string "{NICK}" (case sensitive) will be replaced by the actual nick / username.
|
||||||
#The string "{BRIDGE}" (case sensitive) will be replaced by the sending bridge
|
#The string "{BRIDGE}" (case sensitive) will be replaced by the sending bridge
|
||||||
|
@ -161,6 +165,10 @@ Buffer=1000
|
||||||
#OPTIONAL (no authorization if token is empty)
|
#OPTIONAL (no authorization if token is empty)
|
||||||
Token=""
|
Token=""
|
||||||
|
|
||||||
|
#extra label that can be used in the RemoteNickFormat
|
||||||
|
#optional (default empty)
|
||||||
|
Label="minecraft"
|
||||||
|
|
||||||
#RemoteNickFormat defines how remote users appear on this bridge
|
#RemoteNickFormat defines how remote users appear on this bridge
|
||||||
#The string "{NICK}" (case sensitive) will be replaced by the actual nick / username.
|
#The string "{NICK}" (case sensitive) will be replaced by the actual nick / username.
|
||||||
#The string "{BRIDGE}" (case sensitive) will be replaced by the sending bridge
|
#The string "{BRIDGE}" (case sensitive) will be replaced by the sending bridge
|
||||||
|
@ -168,8 +176,6 @@ Token=""
|
||||||
#OPTIONAL (default empty)
|
#OPTIONAL (default empty)
|
||||||
RemoteNickFormat="{NICK}"
|
RemoteNickFormat="{NICK}"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
###################################################################
|
###################################################################
|
||||||
#General configuration
|
#General configuration
|
||||||
###################################################################
|
###################################################################
|
||||||
|
@ -232,56 +238,11 @@ name="minecraft"
|
||||||
##OPTIONAL (default false)
|
##OPTIONAL (default false)
|
||||||
enable=true
|
enable=true
|
||||||
|
|
||||||
#API example
|
# API
|
||||||
[[gateway.inout]]
|
[[gateway.inout]]
|
||||||
account="api.minecraft"
|
account="api.minecraft"
|
||||||
channel="api"
|
channel="api"
|
||||||
#To send data to the api:
|
|
||||||
#curl -XPOST -H 'Content-Type: application/json' -d '{"text":"test","username":"randomuser","gateway":"gateway1"}' http://localhost:4242/api/message
|
|
||||||
#To read from the api:
|
|
||||||
#curl http://localhost:4242/api/messages
|
|
||||||
|
|
||||||
|
|
||||||
#[[gateway.in]] specifies the account and channels we will receive messages from.
|
|
||||||
#The following example bridges between mattermost and irc
|
|
||||||
[[gateway.inout]]
|
[[gateway.inout]]
|
||||||
account="irc.freenode"
|
account="irc.freenode"
|
||||||
channel="#matterlink"
|
channel="#matterlink"
|
||||||
|
|
||||||
# #OPTIONAL - only used for IRC protocol at the moment
|
|
||||||
# [gateway.in.options]
|
|
||||||
# #OPTIONAL - your irc channel key
|
|
||||||
# key="yourkey"
|
|
||||||
|
|
||||||
|
|
||||||
# #[[gateway.inout]] can be used when then channel will be used to receive from
|
|
||||||
# #and send messages to
|
|
||||||
# [[gateway.inout]]
|
|
||||||
# account="irc.freenode"
|
|
||||||
# channel="#matterlink-testing"
|
|
||||||
|
|
||||||
# #OPTIONAL - only used for IRC protocol at the moment
|
|
||||||
# [gateway.out.options]
|
|
||||||
# #OPTIONAL - your irc channel key
|
|
||||||
# key="yourkey"
|
|
||||||
|
|
||||||
# [[gateway.inout]]
|
|
||||||
# account="discord.game"
|
|
||||||
# channel="mygreatgame"
|
|
||||||
#
|
|
||||||
# #OPTIONAL - webhookurl only works for discord (it needs a different URL for each cahnnel)
|
|
||||||
# [gateway.inout.options]
|
|
||||||
# webhookurl=""https://discordapp.com/api/webhooks/123456789123456789/C9WPqExYWONPDZabcdef-def1434FGFjstasJX9pYht73y"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
##If you want to do a 1:1 mapping between protocols where the channelnames are the same
|
|
||||||
##e.g. slack and mattermost you can use the samechannelgateway configuration
|
|
||||||
##the example configuration below send messages from channel testing on mattermost to
|
|
||||||
##channel testing on slack and vice versa. (and for the channel testing2 and testing3)
|
|
||||||
#
|
|
||||||
#[[samechannelgateway]]
|
|
||||||
# name="samechannel1"
|
|
||||||
# enable = false
|
|
||||||
# accounts = [ "mattermost.work","slack.hobby" ]
|
|
||||||
# channels = [ "testing","testing2","testing3"]
|
|
Loading…
Reference in New Issue