Config refactor part 2
parent
947b454faf
commit
a1a7bf69ff
44
config.py
44
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'
|
SERVER_IP = os.getenv('SERVER_ADDRESS') or 'unknown ip'
|
||||||
|
|
||||||
# Matrix users who are allowed to run OP commands in Minecraft through Matrix
|
MATRIX_ADMINS = at(['matrix', 'mc-admins']) or []
|
||||||
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'),
|
|
||||||
}
|
|
||||||
|
|
15
config.yaml
15
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 bridge configurations
|
||||||
matrix:
|
matrix:
|
||||||
# Homeserver URL
|
# Homeserver URL
|
||||||
|
@ -14,14 +23,16 @@ matrix:
|
||||||
server_address: unknown ip
|
server_address: unknown ip
|
||||||
|
|
||||||
# List of Matrix users that can send commands to the bridge.
|
# 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
|
# When a message starts with an exclamation mark, (!) the bridge will
|
||||||
# Minecraft command and will put that as a command into the console.
|
# interpret it as a Minecraft command and will put that as a command
|
||||||
|
# into the console.
|
||||||
mc-admins:
|
mc-admins:
|
||||||
- "@bram:matrix.directory"
|
- "@bram:matrix.directory"
|
||||||
# - "@alice:example.org"
|
# - "@alice:example.org"
|
||||||
# -
|
# -
|
||||||
|
|
||||||
# When users have bridged from other platforms, you can indicate accordingly.
|
# When users have bridged from other platforms, you can indicate accordingly.
|
||||||
|
# When multiple RegEx strings apply, all are included.
|
||||||
alternative_platforms:
|
alternative_platforms:
|
||||||
Discord:
|
Discord:
|
||||||
match: "@_?discord_\d+:.+"
|
match: "@_?discord_\d+:.+"
|
||||||
|
|
18
main.py
18
main.py
|
@ -20,11 +20,6 @@ async def message_callback(room: MatrixRoom, event: RoomMessageText) -> None:
|
||||||
if int(event.server_timestamp) < STARTUP_TIME:
|
if int(event.server_timestamp) < STARTUP_TIME:
|
||||||
return
|
return
|
||||||
|
|
||||||
# Determine platform
|
|
||||||
platform = 'Matrix'
|
|
||||||
if re.fullmatch(r"@_discord_\d+:t2bot\.io", event.sender):
|
|
||||||
platform = 'Discord'
|
|
||||||
|
|
||||||
# Determine how to display username
|
# Determine how to display username
|
||||||
name = room.users[event.sender].display_name
|
name = room.users[event.sender].display_name
|
||||||
for user in room.users:
|
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
|
name = room.users[event.sender].disambiguated_name
|
||||||
break
|
break
|
||||||
|
|
||||||
mc_wrapper.reply_to_mc(
|
mc_wrapper.reply_to_mc(event.body, name, event.sender)
|
||||||
event.body, name,
|
|
||||||
admin=(event.sender in config.MC_ADMINS),
|
|
||||||
platform=platform
|
|
||||||
)
|
|
||||||
client.add_event_callback(message_callback, RoomMessageText)
|
client.add_event_callback(message_callback, RoomMessageText)
|
||||||
|
|
||||||
|
|
||||||
|
@ -47,7 +38,7 @@ async def activate_client() -> None:
|
||||||
print(await client.login(config.MATRIX_PASSWORD))
|
print(await client.login(config.MATRIX_PASSWORD))
|
||||||
|
|
||||||
await client.room_send(
|
await client.room_send(
|
||||||
room_id=config.MC_CHANNEL,
|
room_id=config.MATRIX_ROOM,
|
||||||
message_type="m.room.message",
|
message_type="m.room.message",
|
||||||
content = {
|
content = {
|
||||||
"msgtype": "m.text",
|
"msgtype": "m.text",
|
||||||
|
@ -60,8 +51,11 @@ async def activate_client() -> None:
|
||||||
|
|
||||||
async def start():
|
async def start():
|
||||||
await asyncio.gather(
|
await asyncio.gather(
|
||||||
|
# Start the Matrix client
|
||||||
activate_client(),
|
activate_client(),
|
||||||
mc_wrapper.start(client, config.MC_CHANNEL)
|
|
||||||
|
# Start the Minecraft subprocess
|
||||||
|
mc_wrapper.start(client, config.MATRIX_ROOM)
|
||||||
)
|
)
|
||||||
|
|
||||||
asyncio.run(start())
|
asyncio.run(start())
|
|
@ -14,6 +14,9 @@ p = Popen(sys.argv[1:],
|
||||||
nbsr = NBSR(p.stdout)
|
nbsr = NBSR(p.stdout)
|
||||||
|
|
||||||
async def start(client, mc_channel):
|
async def start(client, mc_channel):
|
||||||
|
"""
|
||||||
|
Start reading from the Minecraft subprocess.
|
||||||
|
"""
|
||||||
await asyncio.sleep(3)
|
await asyncio.sleep(3)
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
|
@ -49,6 +52,12 @@ async def start(client, mc_channel):
|
||||||
server_live = False
|
server_live = False
|
||||||
|
|
||||||
def process_message(sentence : str) -> Union[str, None]:
|
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
|
global server_live
|
||||||
|
|
||||||
if (match := re.fullmatch(
|
if (match := re.fullmatch(
|
||||||
|
@ -83,7 +92,8 @@ def process_message(sentence : str) -> Union[str, None]:
|
||||||
sentence)):
|
sentence)):
|
||||||
username, = match.groups()
|
username, = match.groups()
|
||||||
return username + " left the Minecraft server", (
|
return username + " left the Minecraft server", (
|
||||||
"<strong>" + username + " left the Minecraft server</strong>")
|
"<strong>" + username + " left the Minecraft server</strong>"
|
||||||
|
)
|
||||||
|
|
||||||
if (match := re.fullmatch(
|
if (match := re.fullmatch(
|
||||||
r"\[[\d:]+\] \[Server thread\/INFO\]: <([A-Za-z0-9_]{3,16})> (.+)",
|
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
|
return None, None
|
||||||
|
|
||||||
def reply_to_mc(message : str, author : str,
|
def reply_to_mc(message : str, display_name : str, sender : str):
|
||||||
admin : bool = False, platform : str = 'Matrix'):
|
|
||||||
"""
|
"""
|
||||||
Send something back to the Minecraft terminal.
|
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())
|
p.stdin.write((message[1:] + "\r\n").encode())
|
||||||
else:
|
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(
|
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()
|
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__':
|
if __name__ == '__main__':
|
||||||
asyncio.run(start())
|
asyncio.run(start())
|
Loading…
Reference in New Issue