--- a/mc_server.py +++ b/mc_server.py @@ -118,6 +118,30 @@ raise RuntimeError("obs/info contains neither 'image' nor 'pov'") +_INFO_SKIP = {"pov", "image", "location_stats", "equipped_items", "custom"} + + +def info_for_client(info: dict) -> dict: + """Judge-relevant fields of the sim info (the released server returned none).""" + out = {k: convert_numpy_types(dict(v) if isinstance(v, dict) else v) + for k, v in (info or {}).items() if k not in _INFO_SKIP} + inv = {} + for slot in (info or {}).get("inventory", {}).values(): + if slot.get("type") not in (None, "none", "air"): + inv[slot["type"]] = inv.get(slot["type"], 0) + int(slot.get("quantity", 0)) + out["inventory"] = inv + raw = (info or {}).get("inventory", {}) + hotbar = [] + for i in range(9): + slot = raw.get(i) or raw.get(str(i)) or {} + t = slot.get("type") + hotbar.append(None if t in (None, "none", "air") else f"{t} x{int(slot.get('quantity', 0))}") + out["hotbar"] = hotbar + hand = (info or {}).get("equipped_items", {}).get("mainhand", {}) + out["mainhand"] = hand.get("type") if isinstance(hand, dict) else None + return out + + # ========================= # API 实现 # ========================= @@ -224,6 +248,10 @@ return err(f"session '{session_id}' not found") try: + if session.env_type == "minestudio": + # MineRL clears its seed at the end of every reset (even a failed one), so a retried reset + # would build a random world; re-apply the create_env seed each time + session.env.env.seed(session.env.seed) result = session.env.reset() if isinstance(result, tuple): @@ -276,6 +304,7 @@ "screenshot": screenshot, "reward": float(reward), "done": done, + "info": info_for_client(info), "timing": { "env_step_ms": round((t2 - t1) * 1000, 1), "encode_ms": round((t4 - t3) * 1000, 1),