feat: module mtp_back
This commit is contained in:
13
.gitignore
vendored
Normal file
13
.gitignore
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
# Python-generated files
|
||||
__pycache__/
|
||||
*.py[oc]
|
||||
build/
|
||||
dist/
|
||||
wheels/
|
||||
*.egg-info
|
||||
|
||||
# Virtual environments
|
||||
.venv
|
||||
.python-version
|
||||
.venv
|
||||
uv.lock
|
||||
11
back/README.md
Normal file
11
back/README.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# MTP Back
|
||||
这里是返回死亡点模块的命令帮助信息。
|
||||
|
||||
## Usage
|
||||
`!!back` MTP Back的主命令,玩家可当作快速的命令别名,用于便捷返回。
|
||||
`!!help back` 显示此命令帮助页面。
|
||||
`!!back death` 返回死亡点的命令,默认情况下玩家执行时会直接被传送到上次死亡的地点。
|
||||
`!!back death history` 查看死亡点的历史记录信息。
|
||||
`!!back return` 返回到上次执行传送相关命令时所在的位置。
|
||||
`!!reback` 命令`!!back return`的别名。
|
||||
|
||||
17
back/src/mcdreforged.plugin.json
Normal file
17
back/src/mcdreforged.plugin.json
Normal file
@@ -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"
|
||||
]
|
||||
}
|
||||
60
back/src/mtp_back/__init__.py
Normal file
60
back/src/mtp_back/__init__.py
Normal file
@@ -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)
|
||||
51
back/src/mtp_back/commands.py
Normal file
51
back/src/mtp_back/commands.py
Normal file
@@ -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")
|
||||
4
back/src/mtp_back/helps.py
Normal file
4
back/src/mtp_back/helps.py
Normal file
@@ -0,0 +1,4 @@
|
||||
# from mcdreforged.api.all import RText
|
||||
|
||||
|
||||
HELP_PAGE_MAIN = ""
|
||||
7
back/src/mtp_back/runtime.py
Normal file
7
back/src/mtp_back/runtime.py
Normal file
@@ -0,0 +1,7 @@
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
# Command build part
|
||||
command_pfx: str = "!!"
|
||||
command_node: str = "back"
|
||||
config_dir: Path = Path("mtp_back")
|
||||
64
back/src/mtp_back/utils.py
Normal file
64
back/src/mtp_back/utils.py
Normal file
@@ -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
|
||||
9
pyproject.toml
Normal file
9
pyproject.toml
Normal file
@@ -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",
|
||||
]
|
||||
Reference in New Issue
Block a user