From 0d48cbb022dd0a54045013333b4f9429b1d8846f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=A8=E6=B3=A0?= Date: Wed, 14 Jan 2026 22:34:35 +0800 Subject: [PATCH] feat: module mtp_back --- .gitignore | 13 +++++++ back/README.md | 11 ++++++ back/src/mcdreforged.plugin.json | 17 +++++++++ back/src/mtp_back/__init__.py | 60 ++++++++++++++++++++++++++++++ back/src/mtp_back/commands.py | 51 +++++++++++++++++++++++++ back/src/mtp_back/helps.py | 4 ++ back/src/mtp_back/runtime.py | 7 ++++ back/src/mtp_back/utils.py | 64 ++++++++++++++++++++++++++++++++ pyproject.toml | 9 +++++ 9 files changed, 236 insertions(+) create mode 100644 .gitignore create mode 100644 back/README.md create mode 100644 back/src/mcdreforged.plugin.json create mode 100644 back/src/mtp_back/__init__.py create mode 100644 back/src/mtp_back/commands.py create mode 100644 back/src/mtp_back/helps.py create mode 100644 back/src/mtp_back/runtime.py create mode 100644 back/src/mtp_back/utils.py create mode 100644 pyproject.toml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f54d14d --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +# Python-generated files +__pycache__/ +*.py[oc] +build/ +dist/ +wheels/ +*.egg-info + +# Virtual environments +.venv +.python-version +.venv +uv.lock diff --git a/back/README.md b/back/README.md new file mode 100644 index 0000000..b57c328 --- /dev/null +++ b/back/README.md @@ -0,0 +1,11 @@ +# MTP Back +这里是返回死亡点模块的命令帮助信息。 + +## Usage +`!!back` MTP Back的主命令,玩家可当作快速的命令别名,用于便捷返回。 +`!!help back` 显示此命令帮助页面。 +`!!back death` 返回死亡点的命令,默认情况下玩家执行时会直接被传送到上次死亡的地点。 +`!!back death history` 查看死亡点的历史记录信息。 +`!!back return` 返回到上次执行传送相关命令时所在的位置。 +`!!reback` 命令`!!back return`的别名。 + diff --git a/back/src/mcdreforged.plugin.json b/back/src/mcdreforged.plugin.json new file mode 100644 index 0000000..9ae7618 --- /dev/null +++ b/back/src/mcdreforged.plugin.json @@ -0,0 +1,17 @@ +{ + "id": "mtp_back", + "version": "0.0.1", + "name": "MTP Back", + "description": { + "en_us": "Single back module of ModernTeleport.", + "zh_cn": "现代化传送单模块:返回死亡点。" + }, + "author": "Mooling0602", + "link": "https://github.com", + "dependencies": { + "mcdreforged": ">=2.14.1" + }, + "resources": [ + "lang" + ] +} \ No newline at end of file diff --git a/back/src/mtp_back/__init__.py b/back/src/mtp_back/__init__.py new file mode 100644 index 0000000..365ebcb --- /dev/null +++ b/back/src/mtp_back/__init__.py @@ -0,0 +1,60 @@ +from pathlib import Path +import time +import mtp_back.runtime as rt + +from mcdreforged.api.all import PluginServerInterface, event_listener +from mtp_back.utils import write_data, execute_if + +do_reload: bool = False +loaded: bool = False + + +def on_load(s: PluginServerInterface, prev_module): + global do_reload + s.logger.info("init.on_load.start") + if prev_module is None: + if not s.is_server_running(): + s.logger.info("init.need_reload") + else: + loader(s) + else: + if prev_module.do_reload: + loader(s) + s.logger.info("init.on_load.finish") + do_reload = True + + +def loader(s: PluginServerInterface): + global loaded + if "gamemode" in s.get_plugin_list(): + rt.command_node = "mtp:back" + from mtp_back.commands import command_register + + command_register(s) + _config_dir: str = s.get_data_folder() + rt.config_dir = Path(_config_dir) + loaded = True + + +def on_server_start_pre(s: PluginServerInterface): + if not loaded: + s.reload_plugin(s.get_self_metadata().id) + + +@event_listener("PlayerDeathEvent") +@execute_if(lambda: loaded is True) +def on_player_death(s: PluginServerInterface, player: str, event: str, content: list): + message: str = "" + for i in content: + if i.locale == s.get_mcdr_language(): + message = i.raw + death_info: dict = { + "player": player, + "event": event, + "message": message, + "location": "not implemented yet.", + } + timestamp = time.time() + data = {"info": death_info, "time": timestamp} + config_file_path: Path = rt.config_dir / "data.json" + write_data(data, config_file_path) diff --git a/back/src/mtp_back/commands.py b/back/src/mtp_back/commands.py new file mode 100644 index 0000000..d9a5854 --- /dev/null +++ b/back/src/mtp_back/commands.py @@ -0,0 +1,51 @@ +from typing import Callable, Literal +import mtp_back.runtime as rt + +from mcdreforged.api.all import ( + CommandContext, + CommandSource, + PluginServerInterface, + SimpleCommandBuilder, +) + +builder = SimpleCommandBuilder() +CommandSourceType = Literal["admin", "player", "console"] + + +def command_register(s: PluginServerInterface): + builder.register(s) + + +def command_checker( + src: CommandSource, + _: CommandContext, + mode: list[CommandSourceType] | CommandSourceType, +) -> bool: + if not isinstance(mode, list): + mode = [mode] + check_map: dict[str, Callable[[], bool]] = { + "admin": lambda: src.has_permission_higher_than(2), + "player": lambda: src.is_player, + "console": lambda: src.is_console, + } + return all(check_map[m]() for m in mode if m in check_map) + + +@builder.command(f"{rt.command_pfx}{rt.command_node}") +def on_command_back_main(src: CommandSource, ctx: CommandContext): + if command_checker(src, ctx, "player"): + player_command_back_main(src, ctx) + return + if command_checker(src, ctx, "console"): + show_console_back_main_help(src, ctx) + return + + +def player_command_back_main(src: CommandSource, _: CommandContext): + src.reply("back.auto_detect") + src.reply("feature is not implemented.") + src.reply("back.execute") + + +def show_console_back_main_help(src: CommandSource, _: CommandContext): + src.reply("back.help_page_console") diff --git a/back/src/mtp_back/helps.py b/back/src/mtp_back/helps.py new file mode 100644 index 0000000..1cfe407 --- /dev/null +++ b/back/src/mtp_back/helps.py @@ -0,0 +1,4 @@ +# from mcdreforged.api.all import RText + + +HELP_PAGE_MAIN = "" diff --git a/back/src/mtp_back/runtime.py b/back/src/mtp_back/runtime.py new file mode 100644 index 0000000..f3530ca --- /dev/null +++ b/back/src/mtp_back/runtime.py @@ -0,0 +1,7 @@ +from pathlib import Path + + +# Command build part +command_pfx: str = "!!" +command_node: str = "back" +config_dir: Path = Path("mtp_back") diff --git a/back/src/mtp_back/utils.py b/back/src/mtp_back/utils.py new file mode 100644 index 0000000..358d422 --- /dev/null +++ b/back/src/mtp_back/utils.py @@ -0,0 +1,64 @@ +import json + +from typing import Callable, TypeVar, ParamSpec +from functools import wraps +from pathlib import Path +from mcdreforged.api.all import PluginServerInterface + +P = ParamSpec("P") +T = TypeVar("T") + + +class ConditionError(RuntimeError): + pass + + +def execute_if(condition: bool | Callable[[], bool], raise_error: bool = False): + def decorator(func: Callable[P, T]) -> Callable[P, T | None]: + @wraps(func) + def wrapper(*args: P.args, **kwargs: P.kwargs) -> T | None: + _condition: bool = condition() if callable(condition) else condition + if _condition: + return func(*args, **kwargs) + else: + if raise_error: + raise ConditionError("Condition must be satisfied!") + return None + + return wrapper + + return decorator + + +def write_data(data: dict, path: str | Path): + file_path: Path = Path(path) + file_path.parent.mkdir(parents=True, exist_ok=True) + all_data: list[dict] = [] + if not file_path.exists(): + all_data.append(data) + else: + try: + if file_path.stat().st_size != 0: + with open(file_path, "r", encoding="utf-8") as f: + all_data = json.load(f) + except Exception as e: + raise e + all_data.append(data) + with open(file_path, "w", encoding="utf-8") as f: + json.dump(all_data, f, indent=2, ensure_ascii=False) + + +def tr(server: PluginServerInterface, tr_key: str, return_str: bool = True, *args): + plg_self = server.get_self_metadata() + if tr_key.startswith(f"{plg_self.id}"): + translation = server.rtr(f"{tr_key}") + else: + if tr_key.startswith("#"): + translation = server.rtr(tr_key.replace("#", ""), *args) + else: + translation = server.rtr(f"{plg_self.id}.{tr_key}", *args) + if return_str: + tr_to_str: str = str(translation) + return tr_to_str + else: + return translation diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..8be653d --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,9 @@ +[project] +name = "tp-plugins" +version = "0.1.0" +description = "Add your description here" +readme = "README.md" +requires-python = ">=3.11" +dependencies = [ + "mcdreforged>=2.15.7", +]