项目由 uv 管理,依赖装在 .venv。此前各处的提示语仍写作 `python main.py ...`,用户若在未激活虚拟环境时照抄,会因缺少 fastapi 而失败——这是正确性问题,不只是措辞。 涉及:main.py(12 行,含 prog 与各条 hint)、ai_player.py(5 行)、farm/client.py、farm/server/__main__.py(3 行,含 prog)、farm/server/__init__.py、farm/server/daemon.py、README(4 处示例与目录树注释)。 刻意保留 main.py:26 与 README:49 的「没装 uv?」兜底说明,那里 `python main.py` 是正确写法。 验收:ruff 全通过 / format 26 文件无改动 / pyright 0 错误 / 97 项测试通过。
78 lines
2.4 KiB
Python
78 lines
2.4 KiB
Python
"""SimpleFarm 服务器包。
|
||
|
||
把原本"一个进程一局游戏"的单机引擎,改造成一个可以多人同时在线、
|
||
可以后台常驻、既能被人玩也能被 AI 调用的小型游戏服务器。
|
||
|
||
模块划分
|
||
--------
|
||
* :mod:`farm.server.app` —— FastAPI 应用(REST + WebSocket)
|
||
* :mod:`farm.server.actions` —— 动作表:所有入口共用的唯一执行通道
|
||
* :mod:`farm.server.session` —— 多牧场会话与统一时钟
|
||
* :mod:`farm.server.hub` —— WebSocket 连接池与状态推送
|
||
* :mod:`farm.server.daemon` —— 守护进程(start/stop/status)
|
||
* :mod:`farm.server.webui` —— 内嵌网页客户端
|
||
|
||
``app`` 依赖 FastAPI,而 ``daemon`` 只依赖标准库。为了让
|
||
``uv run main.py stop`` 在没有装 FastAPI 的机器上也能用,这里采用**惰性导出**:
|
||
真正 import 到用例时才加载对应子模块。
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
from typing import Any
|
||
|
||
_LAZY = {
|
||
"API_VERSION",
|
||
"SERVER_NAME",
|
||
"ServerConfig",
|
||
"ServerHandle",
|
||
"build_app",
|
||
"create_app",
|
||
"rules_text",
|
||
"brief",
|
||
"Action",
|
||
"Param",
|
||
"ACTIONS",
|
||
"run_action",
|
||
"describe_actions",
|
||
"action_names",
|
||
"FarmSession",
|
||
"SessionManager",
|
||
"FarmClock",
|
||
"validate_farm_id",
|
||
"DEFAULT_FARM",
|
||
"Client",
|
||
"ConnectionHub",
|
||
"Publisher",
|
||
"DaemonManager",
|
||
"pid_alive",
|
||
"DASHBOARD_HTML",
|
||
"dashboard_text",
|
||
}
|
||
|
||
__all__ = sorted(_LAZY)
|
||
|
||
|
||
def __getattr__(name: str) -> Any: # PEP 562:模块级惰性属性
|
||
if name not in _LAZY:
|
||
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
||
from importlib import import_module
|
||
|
||
if name in ("DaemonManager", "pid_alive"):
|
||
module = import_module("farm.server.daemon")
|
||
elif name in ("DASHBOARD_HTML", "dashboard_text"):
|
||
module = import_module("farm.server.webui")
|
||
elif name in ("Action", "Param", "ACTIONS", "run_action", "describe_actions", "action_names"):
|
||
module = import_module("farm.server.actions")
|
||
elif name in ("FarmSession", "SessionManager", "FarmClock", "validate_farm_id", "DEFAULT_FARM"):
|
||
module = import_module("farm.server.session")
|
||
elif name in ("Client", "ConnectionHub", "Publisher"):
|
||
module = import_module("farm.server.hub")
|
||
else:
|
||
module = import_module("farm.server.app")
|
||
return getattr(module, name)
|
||
|
||
|
||
def __dir__() -> list:
|
||
return sorted(set(list(globals()) + __all__))
|