Files
maipulse/astral/api/GetGameSettings.py
shouko 8421898626 maipulse: 脱敏存档
- Python 后端 + 单页前端 + Android(Chaquopy) 壳
- 曲库 1343 首 / 称号 2800 个
- 机台身份与店铺信息已抹除,字段留空
- 打包脚本含 16KB 页对齐与自动脱敏
2026-10-28 22:27:46 +08:00

176 lines
5.7 KiB
Python
Raw Permalink 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.
# -*- coding: utf-8 -*-
"""
GetGameSettings.py —— 获取游戏设置(GetGameSettingApi)
================================================================================
功能:取服务器下发的运行时配置(维护窗口、心跳间隔、包超时、各类上限)。
对应接口:GetGameSettingApi
请求体 :{"placeId": <店铺ID>, "clientId": "<机台短值>"}
source/Assembly-CSharp/Net.VO.Mai2/GameSettingRequestVO.cs
source/Assembly-CSharp/Net.Packet.Mai2/PacketGetGameSetting.cs:21-24
★ 真机调用时机:会话最开始、Ping 之前(source/2026-10-05.log:1)。
调用示例:
from api import GetGameSettings
resp = GetGameSettings()
print(resp.gameSetting.isMaintenance, resp.gameSetting.requestInterval)
"""
from __future__ import annotations
from dataclasses import dataclass, field
from typing import Optional
from config import CLIENT_ID, PLACE_ID, TIMEOUT_MS
from .LogSetup import log_info, log_warning
from .MaimaiNet import MaimaiNetClient, request_dict
# =============================================================================
# VO(字段对照 source/Assembly-CSharp/Net.VO.Mai2/GameSetting.cs 与真机响应)
# =============================================================================
@dataclass
class GameSetting:
"""游戏运行时配置(对应 Net.VO.Mai2.GameSetting)。"""
isMaintenance: bool = False
requestInterval: int = 0
rebootStartTime: str = ""
rebootEndTime: str = ""
rebootInterval: int = 0
movieUploadLimit: int = 0
movieStatus: int = 0
movieServerUri: str = ""
deliverServerUri: str = ""
oldServerUri: str = ""
usbDlServerUri: str = ""
maxCountRivalMusic: int = 0
replicationDelayLimit: int = 0
exclusionStartTime: str = ""
exclusionEndTime: str = ""
pingDisable: bool = False
packetTimeout: int = 0
packetTimeoutLong: int = 0
packetRetryCount: int = 0
userDataDlErrTimeout: int = 0
userDataDlErrRetryCount: int = 0
userDataDlErrSamePacketRetryCount: int = 0
userDataUpSkipTimeout: int = 0
userDataUpSkipRetryCount: int = 0
iconPhotoDisable: bool = False
uploadPhotoDisable: bool = False
photoDisableArea: Optional[str] = None
collectDelayInfoDisable: bool = False
maxCountMusic: int = 0
maxCountItem: int = 0
nameEntryDisable: bool = False
packetRecreateCount: int = 0
@dataclass
class GameSettingRequestVO:
"""请求 VO(对应 GameSettingRequestVO)。"""
placeId: int = 0
clientId: str = ""
@dataclass
class GameSettingResponseVO:
"""响应 VO(对应 GameSettingResponseVO)。"""
isAouAccession: bool = False
gameSetting: GameSetting = field(default_factory=GameSetting)
# =============================================================================
# 公开 API
# =============================================================================
def GetGameSettings(
*,
place_id: int = PLACE_ID,
client_id: str = CLIENT_ID,
timeout_ms: Optional[int] = None,
client: Optional[MaimaiNetClient] = None,
) -> GameSettingResponseVO:
"""
获取游戏设置(服务器下发的运行时配置)。
参数:
place_id: 店铺 ID(可选,默认 config.PLACE_ID)
client_id: 机台短值(可选,默认 config.CLIENT_ID)
timeout_ms: 超时毫秒(可选)
client: 可复用的 MaimaiNetClient(可选)
返回:
GameSettingResponseVO
"""
log_info("获取游戏设置:place_id=" + str(place_id) + " client_id=" + client_id)
raw = request_dict(
"GetGameSettingApi",
GameSettingRequestVO(placeId=place_id, clientId=client_id),
user_id=0, client_id=client_id,
timeout_ms=timeout_ms or TIMEOUT_MS, client=client,
)
gs_raw = raw.get("gameSetting") or {}
known = {f for f in GameSetting.__dataclass_fields__}
gs = GameSetting(**{k: v for k, v in gs_raw.items() if k in known})
resp = GameSettingResponseVO(
isAouAccession=bool(raw.get("isAouAccession", False)),
gameSetting=gs,
)
if gs.isMaintenance:
log_warning("服务器处于维护状态(isMaintenance=True)")
if gs.pingDisable:
log_info("服务器已禁用心跳(pingDisable=True)")
log_info(
"游戏设置获取完成:isMaintenance=" + str(gs.isMaintenance)
+ " requestInterval=" + str(gs.requestInterval)
+ " packetTimeout=" + str(gs.packetTimeout)
+ " packetTimeoutLong=" + str(gs.packetTimeoutLong)
+ " pingDisable=" + str(gs.pingDisable)
)
return resp
def is_maintenance(settings: GameSettingResponseVO) -> bool:
"""便捷判断:服务器是否处于维护状态。"""
return bool(settings.gameSetting.isMaintenance)
def is_ping_disabled(settings: GameSettingResponseVO) -> bool:
"""便捷判断:是否已禁用心跳。"""
return bool(settings.gameSetting.pingDisable)
# =============================================================================
# 单独运行(调试)
# =============================================================================
if __name__ == "__main__":
from .LogSetup import setup_logging, teardown_logging
def _main() -> int:
setup_logging("gamesettings_test")
try:
resp = GetGameSettings()
gs = resp.gameSetting
print("")
for name in GameSetting.__dataclass_fields__:
print(" " + name.ljust(34) + "= " + str(getattr(gs, name)))
return 0
except Exception as exc:
from .LogSetup import log_error
log_error("获取游戏设置失败:" + str(exc))
return 1
finally:
teardown_logging()
raise SystemExit(_main())