This commit is contained in:
bridge
2025-11-20 01:21:32 +08:00
parent 32cb34c173
commit bfefb97ea2
5 changed files with 194 additions and 1 deletions

13
debug_client.py Normal file
View File

@@ -0,0 +1,13 @@
import urllib.request
import json
try:
with urllib.request.urlopen("http://localhost:8000/api/state") as response:
print(f"Status: {response.status}")
print(response.read().decode('utf-8'))
except urllib.error.HTTPError as e:
print(f"HTTP Error: {e.code}")
print(e.read().decode('utf-8'))
except Exception as e:
print(f"Error: {e}")

View File

@@ -3,4 +3,7 @@ PyYAML>=6.0
litellm>=1.0.0
omegaconf>=2.3.0
json5>=0.9.0
pandas>=2.0.0
pandas>=2.0.0
fastapi>=0.100.0
uvicorn>=0.20.0
websockets>=11.0

0
src/server/__init__.py Normal file
View File

161
src/server/main.py Normal file
View File

@@ -0,0 +1,161 @@
import sys
import os
import asyncio
from contextlib import asynccontextmanager
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
import uvicorn
# 确保可以导入 src 模块
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..'))
from src.sim.simulator import Simulator
from src.classes.world import World
from src.classes.calendar import Month, Year, create_month_stamp
from src.run.create_map import create_cultivation_world_map, add_sect_headquarters
from src.sim.new_avatar import make_avatars as _new_make
from src.utils.config import CONFIG
from src.classes.sect import sects_by_id
import random
# 全局游戏实例
game_instance = {
"world": None,
"sim": None
}
def init_game():
"""初始化游戏世界,逻辑复用自 src/run/run.py"""
print("正在初始化游戏世界...")
game_map = create_cultivation_world_map()
world = World(map=game_map, month_stamp=create_month_stamp(Year(100), Month.JANUARY))
sim = Simulator(world)
# 宗门初始化逻辑
all_sects = list(sects_by_id.values())
needed_sects = int(getattr(CONFIG.game, "sect_num", 0) or 0)
# 简单的宗门抽样逻辑 (简化版)
existed_sects = []
if needed_sects > 0 and all_sects:
pool = list(all_sects)
random.shuffle(pool)
existed_sects = pool[:needed_sects]
if existed_sects:
add_sect_headquarters(world.map, existed_sects)
# 创建角色
# 注意:这里直接调用 new_avatar 的 make_avatars避免循环导入
all_avatars = _new_make(world, count=CONFIG.game.init_npc_num, current_month_stamp=world.month_stamp, existed_sects=existed_sects)
world.avatar_manager.avatars.update(all_avatars)
game_instance["world"] = world
game_instance["sim"] = sim
print("游戏世界初始化完成!")
@asynccontextmanager
async def lifespan(app: FastAPI):
# 启动时初始化
init_game()
yield
# 关闭时清理(如果需要)
app = FastAPI(lifespan=lifespan)
# 允许跨域,方便前端开发
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.get("/")
def read_root():
return {"status": "online", "app": "Cultivation World Simulator Backend"}
@app.get("/api/state")
def get_state():
"""获取当前世界的一个快照(调试模式)"""
try:
# 1. 基础检查
world = game_instance.get("world")
if world is None:
return {"step": 1, "error": "No world"}
# 2. 时间检查
y = 0
m = 0
try:
y = int(world.month_stamp.get_year())
m = int(world.month_stamp.get_month().value)
except Exception as e:
return {"step": 2, "error": str(e)}
# 3. 角色列表检查
av_list = []
try:
raw_avatars = list(world.avatar_manager.avatars.values())[:50] # 缩小范围
for a in raw_avatars:
# 极其保守的取值
aid = str(getattr(a, "id", "no_id"))
aname = str(getattr(a, "name", "no_name"))
# 修正:使用 pos_x/pos_y
ax = int(getattr(a, "pos_x", 0))
ay = int(getattr(a, "pos_y", 0))
aaction = "unknown"
# 动作检查
curr = getattr(a, "current_action", None)
if curr:
act = getattr(curr, "action", None)
if act:
aaction = getattr(act, "name", "unnamed_action")
else:
aaction = str(curr)
av_list.append({
"id": aid,
"name": aname,
"x": ax,
"y": ay,
"action": str(aaction)
})
except Exception as e:
return {"step": 3, "error": str(e)}
return {
"status": "ok",
"year": y,
"month": m,
"avatar_count": len(world.avatar_manager.avatars),
"avatars": av_list
}
except Exception as e:
return {"step": 0, "error": "Fatal: " + str(e)}
@app.post("/api/step")
async def step_world():
"""手动触发一帧(一个月)"""
sim = game_instance["sim"]
if not sim:
return {"error": "Sim not initialized"}
events = await sim.step()
return {
"message": "Step executed",
"event_count": len(events),
"events_sample": [str(e) for e in events[:5]]
}
def start():
"""启动服务的入口函数"""
# 改为 8002 端口
uvicorn.run("src.server.main:app", host="0.0.0.0", port=8002, reload=False)
if __name__ == "__main__":
start()

16
src/server/main_test.py Normal file
View File

@@ -0,0 +1,16 @@
from fastapi import FastAPI
import uvicorn
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "World"}
@app.get("/api/state")
def get_state():
return {"status": "ok"}
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8001)