diff --git a/config.py b/config.py
index 38f7a70..6465f00 100644
--- a/config.py
+++ b/config.py
@@ -39,46 +39,4 @@ MATRIX_ROOM = at(['matrix', 'room_id']) or "!channel_id:example.org"
SERVER_IP = os.getenv('SERVER_ADDRESS') or 'unknown ip'
-# Matrix users who are allowed to run OP commands in Minecraft through Matrix
-MC_ADMINS = [
- "@bramvdnheuvel:nltrix.net", # Bram on Matrix (example, feel free to remove)
- "@_discord_625632515314548736:t2bot.io" # Bram on Discord (example, feel free to remove)
- # Your username on Matrix
-]
-if os.getenv('MATRIX_ADMINS') is not None:
- MC_ADMINS = os.getenv('MATRIX_ADMINS').split(',')
-
-make_bool = lambda os_value, default_value : default_value if not os_value else (
- False if os_value.lower() == 'false' else True
-)
-
-SERVER_SETTINGS = {
- 'level-name': os.getenv('WORLD') or 'world',
-
- # Server settings
- 'port' : 25565 if os.getenv('PORT') == None else int(os.getenv('PORT')),
- 'query.port' : 25565 if os.getenv('PORT') == None else int(os.getenv('PORT')),
- 'max-players' : 7 if os.getenv('MAX_PLAYERS') == None else int(os.getenv('MAX_PLAYERS')),
-
- # Server temperature >:3
- 'view-distance' : 10 if os.getenv('RENDER_DISTANCE') == None else int(os.getenv('RENDER_DISTANCE')),
- 'enable-command-block' : make_bool(os.getenv('COMMAND_BLOCKS'), True),
-
- # Environment
- 'allow-nether' : make_bool(os.getenv('NETHER'), True),
- 'spawn-npcs' : make_bool(os.getenv('NPCS'), True),
- 'spawn-animals' : make_bool(os.getenv('ANIMALS'), True),
- 'spawn-monsters' : make_bool(os.getenv('MONSTERS'), True),
-
- # Gamemode
- 'pvp' : make_bool(os.getenv('PVP'), True),
- 'gamemode' : os.getenv('GAMEMODE') or 'survival',
- 'difficulty': os.getenv('DIFFICULTY') or 'medium',
- 'hardcore' : make_bool(os.getenv('HARDCORE'), False),
-
- # Grief protection
- 'online-mode' : make_bool(os.getenv('VERIFY_ACCOUNTS'), True),
- 'white-list' : make_bool(os.getenv('WHITELIST'), True),
- 'enforce-whitelist' : make_bool(os.getenv('WHITELIST'), True),
- 'spawn-protection' : 16 if os.getenv('SPAWN_PROTECTION') == None else os.getenv('SPAWN_PROTECTION'),
-}
+MATRIX_ADMINS = at(['matrix', 'mc-admins']) or []
diff --git a/config.yaml b/config.yaml
index d15db24..73eed00 100644
--- a/config.yaml
+++ b/config.yaml
@@ -1,3 +1,12 @@
+config:
+ # How much memory the Minecraft server is allowed to take up
+ # Number in megabytes. Defaults to 1024. (= 1 GB)
+ ram: 1024
+
+ # File location of the server jar.
+ # To be downloaded at: https://www.minecraft.net/en-us/download/server
+ server_jar: server.jar
+
# Matrix bridge configurations
matrix:
# Homeserver URL
@@ -14,14 +23,16 @@ matrix:
server_address: unknown ip
# List of Matrix users that can send commands to the bridge.
- # When a message starts with a slash, (/) the bridge will interpret it as a
- # Minecraft command and will put that as a command into the console.
+ # When a message starts with an exclamation mark, (!) the bridge will
+ # interpret it as a Minecraft command and will put that as a command
+ # into the console.
mc-admins:
- "@bram:matrix.directory"
# - "@alice:example.org"
# -
# When users have bridged from other platforms, you can indicate accordingly.
+ # When multiple RegEx strings apply, all are included.
alternative_platforms:
Discord:
match: "@_?discord_\d+:.+"
diff --git a/main.py b/main.py
index 1583264..651aef6 100644
--- a/main.py
+++ b/main.py
@@ -20,11 +20,6 @@ async def message_callback(room: MatrixRoom, event: RoomMessageText) -> None:
if int(event.server_timestamp) < STARTUP_TIME:
return
- # Determine platform
- platform = 'Matrix'
- if re.fullmatch(r"@_discord_\d+:t2bot\.io", event.sender):
- platform = 'Discord'
-
# Determine how to display username
name = room.users[event.sender].display_name
for user in room.users:
@@ -35,11 +30,7 @@ async def message_callback(room: MatrixRoom, event: RoomMessageText) -> None:
name = room.users[event.sender].disambiguated_name
break
- mc_wrapper.reply_to_mc(
- event.body, name,
- admin=(event.sender in config.MC_ADMINS),
- platform=platform
- )
+ mc_wrapper.reply_to_mc(event.body, name, event.sender)
client.add_event_callback(message_callback, RoomMessageText)
@@ -47,7 +38,7 @@ async def activate_client() -> None:
print(await client.login(config.MATRIX_PASSWORD))
await client.room_send(
- room_id=config.MC_CHANNEL,
+ room_id=config.MATRIX_ROOM,
message_type="m.room.message",
content = {
"msgtype": "m.text",
@@ -60,8 +51,11 @@ async def activate_client() -> None:
async def start():
await asyncio.gather(
+ # Start the Matrix client
activate_client(),
- mc_wrapper.start(client, config.MC_CHANNEL)
+
+ # Start the Minecraft subprocess
+ mc_wrapper.start(client, config.MATRIX_ROOM)
)
asyncio.run(start())
\ No newline at end of file
diff --git a/mc_wrapper.py b/mc_wrapper.py
index 6227527..d12f4ab 100644
--- a/mc_wrapper.py
+++ b/mc_wrapper.py
@@ -14,6 +14,9 @@ p = Popen(sys.argv[1:],
nbsr = NBSR(p.stdout)
async def start(client, mc_channel):
+ """
+ Start reading from the Minecraft subprocess.
+ """
await asyncio.sleep(3)
while True:
@@ -49,6 +52,12 @@ async def start(client, mc_channel):
server_live = False
def process_message(sentence : str) -> Union[str, None]:
+ """
+ Process a message that is sent to stdout in the Minecraft terminal.
+
+ If this function deems it relevant, it returns a string that can be
+ sent to Matrix.
+ """
global server_live
if (match := re.fullmatch(
@@ -83,7 +92,8 @@ def process_message(sentence : str) -> Union[str, None]:
sentence)):
username, = match.groups()
return username + " left the Minecraft server", (
- "" + username + " left the Minecraft server")
+ "" + username + " left the Minecraft server"
+ )
if (match := re.fullmatch(
r"\[[\d:]+\] \[Server thread\/INFO\]: <([A-Za-z0-9_]{3,16})> (.+)",
@@ -101,24 +111,39 @@ def process_message(sentence : str) -> Union[str, None]:
return None, None
-def reply_to_mc(message : str, author : str,
- admin : bool = False, platform : str = 'Matrix'):
+def reply_to_mc(message : str, display_name : str, sender : str):
"""
Send something back to the Minecraft terminal.
"""
- if admin and message.startswith('!'):
+ if sender in config.MATRIX_ADMINS and message.startswith('!'):
p.stdin.write((message[1:] + "\r\n").encode())
else:
- msg = [
- "",
- dict(text="M", color="red"),
- dict(text="D", color="aqua") if platform == 'Discord' else None,
- dict(text=f" <{author}> {message}")
- ]
p.stdin.write(
- ("execute as @a run tellraw @s " + json.dumps([m for m in msg if m is not None]) + "\r\n").encode()
+ ("execute as @a run tellraw @s " + format(sender, display_name, message) + "\r\n").encode()
)
p.stdin.flush()
+def format(sender : str, display_name : str, message : str) -> str:
+ """
+ Create a string used to format the user's message.
+ """
+ start = [ "", dict(text="M", color="red" ) ]
+ end = [ dict(text=f" <{display_name}> {message}") ]
+
+ options = config.at(['matrix', 'alternative_platforms']) or {}
+
+ for platform, details in options.items():
+ try:
+ regex = details['match']
+ text = details['text']
+ color = details['color']
+ except KeyError:
+ print("WARNING: Platform `" + platform + "` is missing some configurations.")
+ else:
+ if re.fullmatch(regex, sender):
+ start.append(dict(text=text, color=color))
+
+ return json.dumps(start + end)
+
if __name__ == '__main__':
asyncio.run(start())
\ No newline at end of file