Skip to content

Commit

Permalink
add level-type property compat for newer versions
Browse files Browse the repository at this point in the history
  • Loading branch information
Ableytner committed Mar 12, 2024
1 parent 54b5eaa commit fa2fb32
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 36 deletions.
27 changes: 20 additions & 7 deletions mcserverwrapper/src/mcversion.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,18 +52,31 @@ def __init__(self, name: str, version_type: int) -> None:
self.name = name
self.type = version_type

split_name = [int(item) for item in name.split(".")]
if len(split_name) == 2:
self.id = split_name[0] * 10**4 + split_name[1] * 10**2
elif len(split_name) == 3:
self.id = split_name[0] * 10**4 + split_name[1] * 10**2 + split_name[2]
else:
raise ValueError(f"Expected to version to have at most 3 subparts, but received {split_name}")
self.id = McVersion.version_name_to_id(name)

name: str
type: int
id: int

@staticmethod
def version_name_to_id(name: str) -> int:
"""
Convert the given version name (e.g. "1.7.10") to its id (e.g. 10710)
Args:
name (str): version name to be converted
Returns:
int: the version id
"""

split_name = [int(item) for item in name.split(".")]
if len(split_name) == 2:
return split_name[0] * 10**4 + split_name[1] * 10**2
if len(split_name) == 3:
return split_name[0] * 10**4 + split_name[1] * 10**2 + split_name[2]

raise ValueError(f"Expected to version to have 2 or 3 subparts, but received {split_name} in version {name}")

def __str__(self) -> str:
if self.type == McVersionType.VANILLA:
return f"{self.name}"
Expand Down
45 changes: 39 additions & 6 deletions mcserverwrapper/src/server_properties_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,34 @@
from __future__ import annotations

import os
import re
from typing import Any

# how many different property args are allowed
PROPERTY_ARGS_COUNT = 3
from .mcversion import McVersion

DEFAULT_PORT = 25565
DEFAULT_MAX_PLAYERS = 20
DEFAULT_ONLINE_MODE = "true"
DEFAULT_LEVEL_TYPE_PRE_1_19 = "default"
DEFAULT_LEVEL_TYPE_1_19 = "minecraft\\:normal"

ALL_PROPERTIES = [
"port",
"maxp",
"onli"
"onli",
"levt"
]

def get_properties(server_path: str) -> dict[str, Any]:
# how many different property args are allowed
PROPERTY_ARGS_COUNT = len(ALL_PROPERTIES)

def get_properties(server_path: str, server_version: McVersion) -> dict[str, Any]:
"""Return the currently stored properties"""

return parse_properties_args(server_path, None)
return parse_properties_args(server_path, None, server_version)

def parse_properties_args(server_path: str, server_property_args: dict | None) -> dict[str, Any]:
def parse_properties_args(server_path: str, server_property_args: dict | None, server_version: McVersion) \
-> dict[str, Any]:
"""Parse the given server_properties_args and provide defaults for missing values"""

if server_property_args is None:
Expand Down Expand Up @@ -51,6 +58,9 @@ def parse_properties_args(server_path: str, server_property_args: dict | None) -
if "onli" not in server_property_args:
if "online-mode=" in line:
server_property_args["onli"] = line.split("=")[1]
if "levt" not in server_property_args:
if "level-type=" in line:
server_property_args["levt"] = line.split("=")[1]

# fall back to default values
if "port" not in server_property_args:
Expand All @@ -59,6 +69,24 @@ def parse_properties_args(server_path: str, server_property_args: dict | None) -
server_property_args["maxp"] = DEFAULT_MAX_PLAYERS
if "onli" not in server_property_args:
server_property_args["onli"] = DEFAULT_ONLINE_MODE
if "levt" not in server_property_args:
if server_version.id < McVersion.version_name_to_id("1.19"):
server_property_args["levt"] = DEFAULT_LEVEL_TYPE_PRE_1_19
else:
server_property_args["levt"] = DEFAULT_LEVEL_TYPE_1_19

# set default level type to the correct version
if server_version.id < McVersion.version_name_to_id("1.19"):
if server_property_args["levt"] == DEFAULT_LEVEL_TYPE_1_19:
server_property_args["levt"] = DEFAULT_LEVEL_TYPE_PRE_1_19
elif re.search(r"^minecraft\\\:*", server_property_args["levt"]) is not None:
server_property_args["levt"] = server_property_args["levt"].replace("minecraft\\:", "")

if server_version.id >= McVersion.version_name_to_id("1.19"):
if server_property_args["levt"] == DEFAULT_LEVEL_TYPE_PRE_1_19:
server_property_args["levt"] = DEFAULT_LEVEL_TYPE_1_19
elif re.search(r"^minecraft\\\:*", server_property_args["levt"]) is None:
server_property_args["levt"] = "minecraft\\:" + server_property_args["levt"]

return server_property_args

Expand Down Expand Up @@ -88,6 +116,9 @@ def save_properties(server_path: str, server_property_args: dict[str, Any]) -> N
if "online-mode=" in line:
lines[index] = f"online-mode={server_property_args['onli']}\n"
missing_props.remove("onli")
if "level-type=" in line:
lines[index] = f"level-type={server_property_args['levt']}\n"
missing_props.remove("levt")

# add missing properties
if "port" in missing_props:
Expand All @@ -96,6 +127,8 @@ def save_properties(server_path: str, server_property_args: dict[str, Any]) -> N
lines.append(f"max-players={server_property_args['maxp']}\n")
if "onli" in missing_props:
lines.append(f"online-mode={server_property_args['onli']}\n")
if "levt" in missing_props:
lines.append(f"level-type={server_property_args["levt"]}\n")

with open(props_path, "w", encoding="utf8") as properties:
properties.writelines(lines)
Expand Down
10 changes: 6 additions & 4 deletions mcserverwrapper/src/wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,13 @@ def __init__(self, jarfile_path: str = "server.jar", server_start_command=None,
# delete old logfile
logger.delete_logs()

prop_args_clean = server_properties_helper.parse_properties_args(self.server_path, server_property_args)
server_properties_helper.save_properties(self.server_path, prop_args_clean)
self._server_builder = ServerBuilder.from_jar(jarfile_path)

self._server_builder = ServerBuilder.from_jar(jarfile_path) \
.port(prop_args_clean["port"])
prop_args_clean = server_properties_helper.parse_properties_args(self.server_path,
server_property_args,
self._server_builder._mcv)
server_properties_helper.save_properties(self.server_path, prop_args_clean)
self._server_builder.port(prop_args_clean["port"])

if server_start_command is not None:
self._server_builder.start_command(server_start_command)
Expand Down
3 changes: 2 additions & 1 deletion mcserverwrapper/test/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ def run_vanilla_test(jarfile, offline_mode=False, version_name=None):
server_property_args = None
if offline_mode:
server_property_args = {
"onli": "false"
"onli": "false",
"levt": "flat"
}

wrapper = Wrapper(os.path.join(os.getcwd(), "testdir", jarfile), server_start_command=start_cmd, print_output=False,
Expand Down
51 changes: 33 additions & 18 deletions mcserverwrapper/test/test_server_properties_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import os

from mcserverwrapper.src import server_properties_helper as sph
from mcserverwrapper.src.mcversion import McVersion, McVersionType

def test_get_mixed_params():
"""Tests the helper with mixed params"""
Expand All @@ -12,56 +13,62 @@ def test_get_mixed_params():
"server-port": 25506,
"max-players": 18,
"some-unknown-prop": "hehe",
"online-mode": "true"
"online-mode": "true",
"level-type": "minecraft\\:normal"
}

props_path = os.path.join(pathlib.Path(__file__).parent.resolve(), "temp")
with open(os.path.join(props_path, "server.properties"), "w+", encoding="utf8") as props_file:
props_file.write("\n".join([f"{key}={value}" for key, value in props.items()]))

result = sph.get_properties(props_path)
result = sph.get_properties(props_path, McVersion("1.20", McVersionType.VANILLA))

assert len(result) == 3
assert len(result) == 4
assert result["maxp"] == props["max-players"]
assert result["onli"] == props["online-mode"]
assert result["port"] == props["server-port"]
assert result["levt"] == props["level-type"]

def test_parse_custom_params():
"""Tests the helper with custom params"""

props = {
"port": 25590,
"maxp": 21,
"onli": "false"
"onli": "false",
"levt": "minecraft\\:normal"
}

result = sph.parse_properties_args(os.getcwd(), props)
result = sph.parse_properties_args(os.getcwd(), props, McVersion("1.20", McVersionType.VANILLA))

# ensure that props didn't change
assert props["port"] == 25590
assert props["maxp"] == 21
assert props["onli"] == "false"

assert len(result) == 4
assert result["port"] == 25590
assert result["maxp"] == 21
assert result["onli"] == "false"
assert result["levt"] == "minecraft\\:normal"

def test_parse_default_params():
"""Tests the helper without custom params"""

props = { }

result = sph.parse_properties_args(os.getcwd(), props)
result = sph.parse_properties_args(os.getcwd(), props, McVersion("1.20", McVersionType.VANILLA))

# ensure that props didn't change
assert "port" not in props
assert "maxp" not in props
assert "onli" not in props

assert len(result) == 3
assert len(result) == 4
assert result["port"] == sph.DEFAULT_PORT
assert result["maxp"] == sph.DEFAULT_MAX_PLAYERS
assert result["onli"] == sph.DEFAULT_ONLINE_MODE
assert result["levt"] == sph.DEFAULT_LEVEL_TYPE_1_19

def test_params_with_file():
"""Tests the helper with a server.properties file"""
Expand All @@ -80,17 +87,18 @@ def test_params_with_file():
"maxp": 22
}

result = sph.parse_properties_args(props_path, props)
result = sph.parse_properties_args(props_path, props, McVersion("1.20", McVersionType.VANILLA))

# ensure that props didn't change
assert "port" not in props
assert props["maxp"] == 22
assert "onli" not in props

assert len(result) == 3
assert len(result) == 4
assert result["port"] == 25599
assert result["maxp"] == 22
assert result["onli"] == "true"
assert result["levt"] == "minecraft\\:normal"

def test_parse_mixed_params_1():
"""Tests the helper with custom and default params"""
Expand All @@ -99,37 +107,40 @@ def test_parse_mixed_params_1():
"port": 25541
}

result = sph.parse_properties_args(os.getcwd(), props)
result = sph.parse_properties_args(os.getcwd(), props, McVersion("1.20", McVersionType.VANILLA))

# ensure that props didn't change
assert props["port"] == 25541
assert "maxp" not in props
assert "onli" not in props

assert len(result) == 3
assert len(result) == 4
assert result["port"] == 25541
assert result["maxp"] == sph.DEFAULT_MAX_PLAYERS
assert result["onli"] == sph.DEFAULT_ONLINE_MODE
assert result["levt"] == sph.DEFAULT_LEVEL_TYPE_1_19

def test_parse_mixed_params_2():
"""Tests the helper with custom and default params"""

props = {
"maxp": 43,
"onli": "false"
"onli": "false",
"levt": "default"
}

result = sph.parse_properties_args(os.getcwd(), props)
result = sph.parse_properties_args(os.getcwd(), props, McVersion("1.20", McVersionType.VANILLA))

# ensure that props didn't change
assert "port" not in props
assert props["maxp"] == 43
assert props["onli"] == "false"

assert len(result) == 3
assert len(result) == 4
assert result["port"] == sph.DEFAULT_PORT
assert result["maxp"] == 43
assert result["onli"] == "false"
assert result["levt"] == sph.DEFAULT_LEVEL_TYPE_1_19

def test_save_existing():
"""Tests the helper save function with valid params"""
Expand All @@ -147,7 +158,8 @@ def test_save_existing():
props = {
"port": 25546,
"maxp": 21,
"onli": "true"
"onli": "true",
"levt": sph.DEFAULT_LEVEL_TYPE_1_19
}

sph.save_properties(props_path, props)
Expand All @@ -160,12 +172,13 @@ def test_save_existing():
with open(os.path.join(props_path, "server.properties"), "r", encoding="utf8") as props_file:
lines = props_file.read().splitlines()

assert len(lines) == 5
assert len(lines) == 6
assert lines[0] == "server-port=25546"
assert lines[1] == "some-other-prop=haha"
assert lines[2] == "max-players=21"
assert lines[3] == "a-final-prop=aha"
assert lines[4] == "online-mode=true"
assert lines[5] == "level-type=minecraft\\:normal"

def test_save_new():
"""Tests the helper save function with valid params"""
Expand All @@ -180,7 +193,8 @@ def test_save_new():
props = {
"port": 25546,
"maxp": 21,
"onli": "true"
"onli": "true",
"levt": "minecraft\\:normal"
}

sph.save_properties(props_path, props)
Expand All @@ -193,9 +207,10 @@ def test_save_new():
with open(os.path.join(props_path, "server.properties"), "r", encoding="utf8") as props_file:
lines = props_file.read().splitlines()

assert len(lines) == 5
assert len(lines) == 6
assert lines[0] == "some-other-prop=haha"
assert lines[1] == "a-final-prop=aha"
assert lines[2] == "server-port=25546"
assert lines[3] == "max-players=21"
assert lines[4] == "online-mode=true"
assert lines[5] == "level-type=minecraft\\:normal"

0 comments on commit fa2fb32

Please sign in to comment.