mcserver-cli 3.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mcserver/__init__.py +1 -0
- mcserver/__main__.py +3 -0
- mcserver/app.py +24 -0
- mcserver/caching.py +0 -0
- mcserver/cli.py +326 -0
- mcserver/commands/__init__.py +39 -0
- mcserver/commands/add_projects.py +7 -0
- mcserver/commands/import_setup.py +6 -0
- mcserver/commands/initialize_server.py +119 -0
- mcserver/commands/list_projects.py +6 -0
- mcserver/commands/op_grant.py +7 -0
- mcserver/commands/op_list.py +32 -0
- mcserver/commands/op_revoke.py +7 -0
- mcserver/commands/print_help.py +7 -0
- mcserver/commands/remove_projects.py +6 -0
- mcserver/commands/search_projects.py +7 -0
- mcserver/commands/server_status.py +6 -0
- mcserver/commands/show_projects.py +26 -0
- mcserver/commands/start_server.py +150 -0
- mcserver/commands/stop_server.py +46 -0
- mcserver/commands/update_projects.py +6 -0
- mcserver/commands/whitelist_add.py +7 -0
- mcserver/commands/whitelist_list.py +31 -0
- mcserver/commands/whitelist_remove.py +31 -0
- mcserver/commandsa.py +1297 -0
- mcserver/config.py +37 -0
- mcserver/constants.py +14 -0
- mcserver/fabricmc/meta.py +41 -0
- mcserver/legacyfabric/meta.py +37 -0
- mcserver/metadata.py +33 -0
- mcserver/minecraft/api.py +94 -0
- mcserver/minecraft/player_identity.py +21 -0
- mcserver/modrinth/api.py +657 -0
- mcserver/modrinth/modpack.py +101 -0
- mcserver/modrinth/project_records/metadata.py +0 -0
- mcserver/modrinth/project_records/relationships.py +203 -0
- mcserver/modrinth/project_records/shared.py +9 -0
- mcserver/modrinth/projects.py +80 -0
- mcserver/modrinth/shared.py +13 -0
- mcserver/modrinth/slug_index.py +36 -0
- mcserver/mojang/eula.py +28 -0
- mcserver/mojang/manifest.py +69 -0
- mcserver/mysterious.py +5 -0
- mcserver/networking.py +152 -0
- mcserver/papermc/api.py +81 -0
- mcserver/purpurmc/api.py +81 -0
- mcserver/quiltmc/meta.py +54 -0
- mcserver/resolver.py +164 -0
- mcserver/server_files/banned_ips.py +120 -0
- mcserver/server_files/banned_players.py +166 -0
- mcserver/server_files/ops.py +143 -0
- mcserver/server_files/properties.py +41 -0
- mcserver/server_files/usercaches.py +0 -0
- mcserver/server_files/whitelist.py +163 -0
- mcserver/shared.py +198 -0
- mcserver/state.py +77 -0
- mcserver_cli-3.0.0.dist-info/METADATA +63 -0
- mcserver_cli-3.0.0.dist-info/RECORD +61 -0
- mcserver_cli-3.0.0.dist-info/WHEEL +4 -0
- mcserver_cli-3.0.0.dist-info/entry_points.txt +2 -0
- mcserver_cli-3.0.0.dist-info/licenses/LICENSE +9 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def main(args: argparse.Namespace) -> int:
|
|
5
|
+
import logging as log
|
|
6
|
+
|
|
7
|
+
from .. import state
|
|
8
|
+
|
|
9
|
+
# Check MCServer status
|
|
10
|
+
current_state = state.get_state()
|
|
11
|
+
if current_state["is_active"]:
|
|
12
|
+
log.error(
|
|
13
|
+
f"There's another active MCServer process ({current_state["action"]}) running with process ID: {current_state["process_id"]}"
|
|
14
|
+
)
|
|
15
|
+
return 1
|
|
16
|
+
|
|
17
|
+
# Set state
|
|
18
|
+
state.set_state("running_server")
|
|
19
|
+
|
|
20
|
+
import os
|
|
21
|
+
import shutil
|
|
22
|
+
from pathlib import Path
|
|
23
|
+
|
|
24
|
+
from .. import config
|
|
25
|
+
|
|
26
|
+
# Load configs
|
|
27
|
+
launcher_config = config.load_config("launcher")
|
|
28
|
+
|
|
29
|
+
jarfile = Path(launcher_config["jarfile"])
|
|
30
|
+
memory_config = launcher_config["ram"]
|
|
31
|
+
|
|
32
|
+
# Download jarfile
|
|
33
|
+
if not jarfile.exists():
|
|
34
|
+
import json
|
|
35
|
+
|
|
36
|
+
from .. import networking
|
|
37
|
+
|
|
38
|
+
state.set_state("downloading_server")
|
|
39
|
+
|
|
40
|
+
server_config = config.load_config("server")
|
|
41
|
+
game_version = server_config["game_version"]
|
|
42
|
+
server_loader = server_config["loader"]
|
|
43
|
+
|
|
44
|
+
loader_name = server_loader["name"]
|
|
45
|
+
loader_version = server_loader["version"]
|
|
46
|
+
|
|
47
|
+
if loader_name != "vanilla" and loader_version is None:
|
|
48
|
+
log.error(f"Loader version cannot be null")
|
|
49
|
+
return 1
|
|
50
|
+
|
|
51
|
+
match loader_name:
|
|
52
|
+
# Mod loaders
|
|
53
|
+
case "fabric":
|
|
54
|
+
from ..fabricmc import meta as fabricmc_meta
|
|
55
|
+
|
|
56
|
+
log.info(
|
|
57
|
+
f"Downloading Fabric loader {loader_version} for Minecraft version {game_version}..."
|
|
58
|
+
)
|
|
59
|
+
networking.download(
|
|
60
|
+
fabricmc_meta.download_url(game_version, loader_version, "1.0.1"),
|
|
61
|
+
jarfile,
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
# case "quilt":
|
|
65
|
+
# log.info(f"Downloading Quilt loader {loader_version} for Minecraft version {game_version}...")
|
|
66
|
+
# networking.download(f"https://")
|
|
67
|
+
|
|
68
|
+
# case "legacy-fabric":
|
|
69
|
+
# pass
|
|
70
|
+
|
|
71
|
+
# Plugin loaders
|
|
72
|
+
case "paper":
|
|
73
|
+
from ..papermc import api as papermc_api
|
|
74
|
+
|
|
75
|
+
log.info(
|
|
76
|
+
f"Downloading Paper build {loader_version} for Minecraft version {game_version}..."
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
download_prop = papermc_api.get_project_build(
|
|
80
|
+
"paper", game_version, loader_version
|
|
81
|
+
)["download_props"]["server:default"]
|
|
82
|
+
networking.download(download_prop["download_url"], jarfile)
|
|
83
|
+
case "purpur":
|
|
84
|
+
from ..purpurmc import api as purpurmc_api
|
|
85
|
+
|
|
86
|
+
log.info(
|
|
87
|
+
f"Downloading Purpur build {loader_version} for Minecraft version {game_version}..."
|
|
88
|
+
)
|
|
89
|
+
networking.download(
|
|
90
|
+
purpurmc_api.download_url("purpur", game_version, loader_version),
|
|
91
|
+
jarfile,
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
# Vanilla
|
|
95
|
+
case "vanilla":
|
|
96
|
+
from ..mojang import manifest as mojang_manifest
|
|
97
|
+
|
|
98
|
+
log.info(f"Downloading vanilla Minecraft version {game_version}...")
|
|
99
|
+
|
|
100
|
+
version_manifest = mojang_manifest.get_version_manifest()[
|
|
101
|
+
"game_versions"
|
|
102
|
+
]
|
|
103
|
+
package_url = None
|
|
104
|
+
for version in version_manifest:
|
|
105
|
+
if version["version_id"] == game_version:
|
|
106
|
+
package_url = version["package_url"]
|
|
107
|
+
break
|
|
108
|
+
|
|
109
|
+
if package_url is None:
|
|
110
|
+
log.error(f"Minecraft version not found: {game_version}")
|
|
111
|
+
return 1
|
|
112
|
+
|
|
113
|
+
package_data = networking.request(package_url)["text"]
|
|
114
|
+
package_json = json.loads(package_data)
|
|
115
|
+
version_download = package_json["downloads"]["server"]
|
|
116
|
+
|
|
117
|
+
networking.download(
|
|
118
|
+
version_download["url"],
|
|
119
|
+
jarfile,
|
|
120
|
+
hashes={"sha1": version_download["sha1"]},
|
|
121
|
+
)
|
|
122
|
+
case _:
|
|
123
|
+
log.error(f"Loader is not supported: {loader_name}")
|
|
124
|
+
|
|
125
|
+
# Check stuff
|
|
126
|
+
if not shutil.which("java"):
|
|
127
|
+
log.error("Java is not installed in PATH")
|
|
128
|
+
return 1
|
|
129
|
+
|
|
130
|
+
if memory_config["min"] > memory_config["max"]:
|
|
131
|
+
log.error("Minimum RAM is bigger than maximum RAM")
|
|
132
|
+
return 1
|
|
133
|
+
|
|
134
|
+
# Run the server
|
|
135
|
+
java_command_argv = [
|
|
136
|
+
"java",
|
|
137
|
+
f"-Xmx{memory_config['max']}M",
|
|
138
|
+
f"-Xms{memory_config['min']}M",
|
|
139
|
+
"-jar",
|
|
140
|
+
str(jarfile),
|
|
141
|
+
]
|
|
142
|
+
|
|
143
|
+
if launcher_config["is_nogui"]:
|
|
144
|
+
java_command_argv.append("nogui")
|
|
145
|
+
|
|
146
|
+
# Execute java
|
|
147
|
+
log.debug(f"Executing command: {' '.join(java_command_argv)}")
|
|
148
|
+
|
|
149
|
+
state.set_state("server_running")
|
|
150
|
+
os.execvp(java_command_argv[0], java_command_argv)
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def main(args: argparse.Namespace) -> int:
|
|
5
|
+
# CLI arguments
|
|
6
|
+
force_stop: bool = args.force_stop
|
|
7
|
+
|
|
8
|
+
import logging as log
|
|
9
|
+
import os
|
|
10
|
+
from signal import SIGKILL, SIGTERM
|
|
11
|
+
|
|
12
|
+
from .. import state
|
|
13
|
+
|
|
14
|
+
try:
|
|
15
|
+
current_state = state.get_state()
|
|
16
|
+
except FileNotFoundError:
|
|
17
|
+
log.error(f"File '{state.state_file}' not found; MCServer not initialized.")
|
|
18
|
+
return 1
|
|
19
|
+
|
|
20
|
+
if not current_state["is_active"]:
|
|
21
|
+
log.error("Server is not running.")
|
|
22
|
+
return 1
|
|
23
|
+
|
|
24
|
+
log.info("Stopping server...")
|
|
25
|
+
os.kill(current_state["process_id"], SIGTERM)
|
|
26
|
+
|
|
27
|
+
current_state = state.get_state()
|
|
28
|
+
if current_state["is_active"]:
|
|
29
|
+
return 0
|
|
30
|
+
|
|
31
|
+
if not force_stop:
|
|
32
|
+
log.warning(
|
|
33
|
+
"Server appears to still be running, you may stop the server manually."
|
|
34
|
+
)
|
|
35
|
+
return 1
|
|
36
|
+
|
|
37
|
+
import time
|
|
38
|
+
|
|
39
|
+
from .. import config
|
|
40
|
+
|
|
41
|
+
launcher_config = config.load_config("launcher")
|
|
42
|
+
time.sleep(launcher_config["force_stop"])
|
|
43
|
+
|
|
44
|
+
log.warning("Server process is still running, force stopping the server...")
|
|
45
|
+
os.kill(current_state["process_id"], SIGKILL)
|
|
46
|
+
return 1
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def main(args: argparse.Namespace) -> int:
|
|
5
|
+
import logging as log
|
|
6
|
+
|
|
7
|
+
from ..server_files import whitelist
|
|
8
|
+
from ..shared import pluralize
|
|
9
|
+
|
|
10
|
+
if not whitelist.whitelist_file.exists():
|
|
11
|
+
log.error(f"File '{whitelist.whitelist_file}' not found.")
|
|
12
|
+
return 1
|
|
13
|
+
|
|
14
|
+
whitelisted_players = whitelist.list_players()
|
|
15
|
+
|
|
16
|
+
player_list: list[str] = []
|
|
17
|
+
for player in whitelisted_players:
|
|
18
|
+
player_list.append(f"{player['player_name']} ({player['player_uuid']})")
|
|
19
|
+
|
|
20
|
+
player_count: int = len(player_list)
|
|
21
|
+
if player_count == 0:
|
|
22
|
+
log.info("There are no whitelisted players.")
|
|
23
|
+
return 0
|
|
24
|
+
else:
|
|
25
|
+
log.info(
|
|
26
|
+
f"There {pluralize('is', player_count)} whitelisted {pluralize('player', player_count)}:"
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
player_list.sort()
|
|
30
|
+
print("\n".join(player_list))
|
|
31
|
+
return 0
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
from uuid import UUID
|
|
3
|
+
from ..server_files.whitelist import remove_players
|
|
4
|
+
from ..minecraft.player_identity import PlayerID
|
|
5
|
+
|
|
6
|
+
import logging as log
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def main(args: argparse.Namespace) -> int:
|
|
10
|
+
players: list[str] = args.players
|
|
11
|
+
player_ids: list[PlayerID] = []
|
|
12
|
+
for player in players:
|
|
13
|
+
try:
|
|
14
|
+
UUID(player)
|
|
15
|
+
log.debug(f"{player} is likely an UUID")
|
|
16
|
+
player_id: PlayerID = {"player_uuid": player}
|
|
17
|
+
|
|
18
|
+
player_ids.append(player_id)
|
|
19
|
+
except ValueError:
|
|
20
|
+
log.debug(f"{player} is likely a name")
|
|
21
|
+
player_id: PlayerID = {"player_name": player}
|
|
22
|
+
|
|
23
|
+
player_ids.append(player_id)
|
|
24
|
+
|
|
25
|
+
try:
|
|
26
|
+
remove_players(player_ids)
|
|
27
|
+
except FileNotFoundError as error:
|
|
28
|
+
log.error(error)
|
|
29
|
+
return 1
|
|
30
|
+
|
|
31
|
+
return 0
|