Files
Iridium/iridium/config.py
T

217 lines
6.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import json
import shutil
from datetime import date
from pathlib import Path
from typing import List, Optional
from mcdreforged.api.all import *
def _today() -> str:
return date.today().strftime("%Y-%m-%d")
class Config(Serializable):
# 使用 !!share / !!hat / !!head / !!c 所需的最低权限等级
permission: int = 1
# !!head 冷却时间(秒),0 表示不限制
head_cooldown_seconds: int = 60
# !!hat 冷却时间(秒),0 表示不限制
hat_cooldown_seconds: int = 3
# !!share 是否播放提示音
share_sound: bool = True
# 强制指定 MC 版本号(如 "1.12.2"),留空则自动检测
force_version: str = ""
# 玩家加入时是否提示可用命令
join_tip: bool = True
# 加入提示延迟(秒),避免和进服消息挤在一起
join_tip_delay_seconds: float = 1.5
# 是否发送进服 MOTD(开服天数 + 自定义行)
motd_enabled: bool = True
# 开服日期,格式 YYYY-MM-DD;默认为配置生成当天(当天算第 1 天)
motd_start_day: str = _today()
# MOTD 文本行
motd_lines: List[str] = [
"§6欢迎 §e{player}§6 加入服务器!",
"§7服务器已开服 §b{days}§7 天",
"§7官网: {link:§b点击打开官网|https://www.skymirror.top}",
"§7QQ群: {link:§f985402607|https://skymirror.top/qq}",
]
# MCDR data folder: config/<plugin_id>/iridium.json
CONFIG_FILE_NAME = "iridium.json"
# 旧路径(仅用于迁移)
LEGACY_CONFIG_FILE = "config/iridium.json"
def build_default_config_text() -> str:
"""带注释的默认配置;开服日期为生成当天。"""
today = _today()
return f"""{{
// 使用 !!share / !!hat / !!head / !!c 所需的最低权限等级
// 0=控制台 1=普通玩家 2=OP/管理员
"permission": 1,
// !!head 冷却时间(秒),0 表示不限制
"head_cooldown_seconds": 60,
// !!hat 冷却时间(秒),0 表示不限制
"hat_cooldown_seconds": 3,
// !!share 是否播放提示音
"share_sound": true,
// 强制指定 Minecraft 版本(如 "1.12.2"、"1.20.1")
// 留空则自动检测;检测失败时可手动填写
"force_version": "",
// 玩家进服时是否提示可用命令
"join_tip": true,
// 进服消息延迟(秒),0 为立即发送
"join_tip_delay_seconds": 1.5,
// 是否发送进服 MOTD(开服天数 + 自定义文案)
"motd_enabled": true,
// 开服日期,格式 YYYY-MM-DD(当天算第 1 天)
// 默认为本配置文件生成当天,可自行修改为真实开服日
"motd_start_day": "{today}",
// MOTD 文本行
// 占位符: {{player}} 玩家名 {{days}} 开服天数 {{online}} 在线人数
// 链接: {{link:显示文字|https://url}} 或 {{link:https://url}}
// 颜色: 支持原版 § 颜色代码
"motd_lines": [
"§6欢迎 §e{{player}}§6 加入服务器!",
"§7服务器已开服 §b{{days}}§7 天",
"§7官网: {{link:§b点击打开官网|https://www.skymirror.top}}",
"§7QQ群: {{link:§f985402607|https://skymirror.top/qq}}"
]
}}
"""
DEFAULT_CONFIG_TEXT = build_default_config_text()
# 模块级单例;on_load 时原地更新字段,避免各模块持有过期引用
config = Config()
def apply_config(new_cfg: Config) -> None:
config.permission = new_cfg.permission
config.head_cooldown_seconds = new_cfg.head_cooldown_seconds
config.hat_cooldown_seconds = new_cfg.hat_cooldown_seconds
config.share_sound = new_cfg.share_sound
config.force_version = new_cfg.force_version
config.join_tip = new_cfg.join_tip
config.join_tip_delay_seconds = new_cfg.join_tip_delay_seconds
config.motd_enabled = new_cfg.motd_enabled
config.motd_start_day = new_cfg.motd_start_day
config.motd_lines = list(new_cfg.motd_lines)
def _strip_json_comments(text: str) -> str:
"""Remove // line comments outside of strings."""
out = []
i = 0
n = len(text)
in_string = False
while i < n:
c = text[i]
if in_string:
out.append(c)
if c == "\\" and i + 1 < n:
out.append(text[i + 1])
i += 2
continue
if c == '"':
in_string = False
i += 1
continue
if c == '"':
in_string = True
out.append(c)
i += 1
continue
if c == "/" and i + 1 < n and text[i + 1] == "/":
while i < n and text[i] != "\n":
i += 1
continue
out.append(c)
i += 1
return "".join(out)
def config_file_path(server: PluginServerInterface) -> Path:
"""Canonical path: MCDR data folder → config/iridium/iridium.json"""
return Path(server.get_data_folder()) / CONFIG_FILE_NAME
def _legacy_path(server: PluginServerInterface) -> Path:
try:
wd = server.get_mcdr_config().get("working_directory") or "."
return (Path(wd) / LEGACY_CONFIG_FILE).expanduser().resolve()
except Exception:
return Path.cwd() / LEGACY_CONFIG_FILE
def _write_commented_default(path: Path, server: PluginServerInterface) -> bool:
try:
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(build_default_config_text(), encoding="utf-8")
server.logger.info(f"已生成配置文件: {path}")
return True
except Exception as e:
server.logger.error(f"写入配置文件失败 {path}: {e}")
return False
def _migrate_legacy(server: PluginServerInterface, dest: Path) -> None:
"""If old config/iridium.json exists, copy it to the data folder path."""
src = _legacy_path(server)
try:
if src.is_file() and src.resolve() != dest.resolve() and not dest.is_file():
dest.parent.mkdir(parents=True, exist_ok=True)
shutil.copy2(src, dest)
server.logger.info(f"已从旧路径迁移配置: {src} -> {dest}")
except Exception as e:
server.logger.warning(f"迁移旧配置失败 {src}: {e}")
def load_config(server: PluginServerInterface) -> Config:
"""
Load config using MCDR's official data folder (config/iridium/iridium.json).
1. Prefer that path; create commented default if missing
2. Migrate legacy config/iridium.json if present
3. Fallback: load_config_simple
"""
path = config_file_path(server)
_migrate_legacy(server, path)
if not path.is_file():
_write_commented_default(path, server)
if path.is_file():
try:
raw = path.read_text(encoding="utf-8")
data = json.loads(_strip_json_comments(raw))
server.logger.info(f"配置已加载: {path}")
return Config.deserialize(data)
except Exception as e:
server.logger.error(f"读取/解析配置失败 {path}: {e},尝试 load_config_simple")
# Official MCDR loader as last resort
try:
cfg = server.load_config_simple(
CONFIG_FILE_NAME,
target_class=Config,
in_data_folder=True,
)
server.logger.info(f"配置已通过 load_config_simple 加载: {path}")
return cfg
except Exception as e:
server.logger.error(f"load_config_simple 失败: {e},使用内存默认值")
return Config()