reformat with black in preperation for merge to master
This commit is contained in:
+25
-9
@@ -107,7 +107,9 @@ class AllnetServlet:
|
||||
return self.dict_to_http_form_string([vars(resp)])
|
||||
|
||||
else:
|
||||
self.logger.info(f"Allowed unknown game {req.game_id} v{req.ver} to authenticate from {request_ip} due to 'is_develop' being enabled. S/N: {req.serial}")
|
||||
self.logger.info(
|
||||
f"Allowed unknown game {req.game_id} v{req.ver} to authenticate from {request_ip} due to 'is_develop' being enabled. S/N: {req.serial}"
|
||||
)
|
||||
resp.uri = f"http://{self.config.title.hostname}:{self.config.title.port}/{req.game_id}/{req.ver.replace('.', '')}/"
|
||||
resp.host = f"{self.config.title.hostname}:{self.config.title.port}"
|
||||
return self.dict_to_http_form_string([vars(resp)])
|
||||
@@ -189,35 +191,49 @@ class AllnetServlet:
|
||||
self.logger.error(e)
|
||||
return b""
|
||||
|
||||
self.logger.info(f"DownloadOrder from {request_ip} -> {req.game_id} v{req.ver} serial {req.serial}")
|
||||
self.logger.info(
|
||||
f"DownloadOrder from {request_ip} -> {req.game_id} v{req.ver} serial {req.serial}"
|
||||
)
|
||||
resp = AllnetDownloadOrderResponse()
|
||||
|
||||
if not self.config.allnet.allow_online_updates or not self.config.allnet.update_cfg_folder:
|
||||
if (
|
||||
not self.config.allnet.allow_online_updates
|
||||
or not self.config.allnet.update_cfg_folder
|
||||
):
|
||||
return self.dict_to_http_form_string([vars(resp)])
|
||||
|
||||
else: # TODO: Keychip check
|
||||
if path.exists(f"{self.config.allnet.update_cfg_folder}/{req.game_id}-{req.ver}-app.ini"):
|
||||
if path.exists(
|
||||
f"{self.config.allnet.update_cfg_folder}/{req.game_id}-{req.ver}-app.ini"
|
||||
):
|
||||
resp.uri = f"http://{self.config.title.hostname}:{self.config.title.port}/dl/ini/{req.game_id}-{req.ver.replace('.', '')}-app.ini"
|
||||
|
||||
if path.exists(f"{self.config.allnet.update_cfg_folder}/{req.game_id}-{req.ver}-opt.ini"):
|
||||
if path.exists(
|
||||
f"{self.config.allnet.update_cfg_folder}/{req.game_id}-{req.ver}-opt.ini"
|
||||
):
|
||||
resp.uri += f"|http://{self.config.title.hostname}:{self.config.title.port}/dl/ini/{req.game_id}-{req.ver.replace('.', '')}-opt.ini"
|
||||
|
||||
self.logger.debug(f"Sending download uri {resp.uri}")
|
||||
return self.dict_to_http_form_string([vars(resp)])
|
||||
|
||||
def handle_dlorder_ini(self, request: Request, match: Dict) -> bytes:
|
||||
if "file" not in match: return b""
|
||||
if "file" not in match:
|
||||
return b""
|
||||
|
||||
req_file = match['file'].replace('%0A', '')
|
||||
req_file = match["file"].replace("%0A", "")
|
||||
|
||||
if path.exists(f"{self.config.allnet.update_cfg_folder}/{req_file}"):
|
||||
return open(f"{self.config.allnet.update_cfg_folder}/{req_file}", "rb").read()
|
||||
return open(
|
||||
f"{self.config.allnet.update_cfg_folder}/{req_file}", "rb"
|
||||
).read()
|
||||
|
||||
self.logger.info(f"DL INI File {req_file} not found")
|
||||
return b""
|
||||
|
||||
def handle_dlorder_report(self, request: Request, match: Dict) -> bytes:
|
||||
self.logger.info(f"DLI Report from {Utils.get_ip_addr(request)}: {request.content.getvalue()}")
|
||||
self.logger.info(
|
||||
f"DLI Report from {Utils.get_ip_addr(request)}: {request.content.getvalue()}"
|
||||
)
|
||||
return b""
|
||||
|
||||
def handle_billing_request(self, request: Request, _: Dict):
|
||||
|
||||
@@ -194,6 +194,7 @@ class AllnetConfig:
|
||||
self.__config, "core", "allnet", "update_cfg_folder", default=""
|
||||
)
|
||||
|
||||
|
||||
class BillingConfig:
|
||||
def __init__(self, parent_config: "CoreConfig") -> None:
|
||||
self.__config = parent_config
|
||||
|
||||
+16
-6
@@ -71,7 +71,9 @@ class Data:
|
||||
games = Utils.get_all_titles()
|
||||
for game_dir, game_mod in games.items():
|
||||
try:
|
||||
if hasattr(game_mod, "database") and hasattr(game_mod, "current_schema_version"):
|
||||
if hasattr(game_mod, "database") and hasattr(
|
||||
game_mod, "current_schema_version"
|
||||
):
|
||||
game_mod.database(self.config)
|
||||
metadata.create_all(self.__engine.connect())
|
||||
|
||||
@@ -137,19 +139,24 @@ class Data:
|
||||
titles = Utils.get_all_titles()
|
||||
|
||||
for folder, mod in titles.items():
|
||||
if not mod.game_codes[0] == game: continue
|
||||
if not mod.game_codes[0] == game:
|
||||
continue
|
||||
|
||||
if hasattr(mod, "current_schema_version"):
|
||||
version = mod.current_schema_version
|
||||
|
||||
else:
|
||||
self.logger.warn(f"current_schema_version not found for {folder}")
|
||||
self.logger.warn(
|
||||
f"current_schema_version not found for {folder}"
|
||||
)
|
||||
|
||||
else:
|
||||
version = self.current_schema_version
|
||||
|
||||
if version is None:
|
||||
self.logger.warn(f"Could not determine latest version for {game}, please specify --version")
|
||||
self.logger.warn(
|
||||
f"Could not determine latest version for {game}, please specify --version"
|
||||
)
|
||||
|
||||
if old_ver is None:
|
||||
self.logger.error(
|
||||
@@ -315,11 +322,14 @@ class Data:
|
||||
|
||||
result = self.base.execute(sql)
|
||||
if result is None:
|
||||
self.logger.error(f"Error execuing sql script for game {game} v{y}!")
|
||||
self.logger.error(
|
||||
f"Error execuing sql script for game {game} v{y}!"
|
||||
)
|
||||
failed = True
|
||||
break
|
||||
else:
|
||||
self.logger.warning(f"Could not find script {game}_{y}_upgrade.sql")
|
||||
failed = True
|
||||
|
||||
if not failed: self.base.set_schema_ver(latest_ver, game)
|
||||
if not failed:
|
||||
self.base.set_schema_ver(latest_ver, game)
|
||||
|
||||
+3
-1
@@ -73,7 +73,9 @@ class FrontendServlet(resource.Resource):
|
||||
fe_game.putChild(game_dir.encode(), game_fe)
|
||||
|
||||
except Exception as e:
|
||||
self.logger.error(f"Failed to import frontend from {game_dir} because {e}")
|
||||
self.logger.error(
|
||||
f"Failed to import frontend from {game_dir} because {e}"
|
||||
)
|
||||
|
||||
self.environment.globals["game_list"] = self.game_list
|
||||
self.putChild(b"gate", FE_Gate(cfg, self.environment))
|
||||
|
||||
+3
-9
@@ -46,9 +46,7 @@ class MuchaServlet:
|
||||
if enabled:
|
||||
self.mucha_registry.append(game_cd)
|
||||
|
||||
self.logger.info(
|
||||
f"Serving {len(self.mucha_registry)} games"
|
||||
)
|
||||
self.logger.info(f"Serving {len(self.mucha_registry)} games")
|
||||
|
||||
def handle_boardauth(self, request: Request, _: Dict) -> bytes:
|
||||
req_dict = self.mucha_preprocess(request.content.getvalue())
|
||||
@@ -62,9 +60,7 @@ class MuchaServlet:
|
||||
|
||||
req = MuchaAuthRequest(req_dict)
|
||||
self.logger.debug(f"Mucha request {vars(req)}")
|
||||
self.logger.info(
|
||||
f"Boardauth request from {client_ip} for {req.gameVer}"
|
||||
)
|
||||
self.logger.info(f"Boardauth request from {client_ip} for {req.gameVer}")
|
||||
|
||||
if req.gameCd not in self.mucha_registry:
|
||||
self.logger.warn(f"Unknown gameCd {req.gameCd}")
|
||||
@@ -92,9 +88,7 @@ class MuchaServlet:
|
||||
|
||||
req = MuchaUpdateRequest(req_dict)
|
||||
self.logger.debug(f"Mucha request {vars(req)}")
|
||||
self.logger.info(
|
||||
f"Updatecheck request from {client_ip} for {req.gameVer}"
|
||||
)
|
||||
self.logger.info(f"Updatecheck request from {client_ip} for {req.gameVer}")
|
||||
|
||||
if req.gameCd not in self.mucha_registry:
|
||||
self.logger.warn(f"Unknown gameCd {req.gameCd}")
|
||||
|
||||
+8
-2
@@ -16,7 +16,9 @@ class Utils:
|
||||
if not dir.startswith("__"):
|
||||
try:
|
||||
mod = importlib.import_module(f"titles.{dir}")
|
||||
if hasattr(mod, "game_codes") and hasattr(mod, "index"): # Minimum required to function
|
||||
if hasattr(mod, "game_codes") and hasattr(
|
||||
mod, "index"
|
||||
): # Minimum required to function
|
||||
ret[dir] = mod
|
||||
|
||||
except ImportError as e:
|
||||
@@ -26,4 +28,8 @@ class Utils:
|
||||
|
||||
@classmethod
|
||||
def get_ip_addr(cls, req: Request) -> str:
|
||||
return req.getAllHeaders()[b"x-forwarded-for"].decode() if b"x-forwarded-for" in req.getAllHeaders() else req.getClientAddress().host
|
||||
return (
|
||||
req.getAllHeaders()[b"x-forwarded-for"].decode()
|
||||
if b"x-forwarded-for" in req.getAllHeaders()
|
||||
else req.getClientAddress().host
|
||||
)
|
||||
|
||||
+11
-4
@@ -34,7 +34,7 @@ if __name__ == "__main__":
|
||||
cfg = CoreConfig()
|
||||
if path.exists(f"{args.config}/core.yaml"):
|
||||
cfg_dict = yaml.safe_load(open(f"{args.config}/core.yaml"))
|
||||
cfg_dict.get('database', {})['loglevel'] = 'info'
|
||||
cfg_dict.get("database", {})["loglevel"] = "info"
|
||||
cfg.update(cfg_dict)
|
||||
|
||||
if not path.exists(cfg.server.log_dir):
|
||||
@@ -48,7 +48,6 @@ if __name__ == "__main__":
|
||||
|
||||
data = Data(cfg)
|
||||
|
||||
|
||||
if args.action == "create":
|
||||
data.create_database()
|
||||
|
||||
@@ -61,10 +60,18 @@ if __name__ == "__main__":
|
||||
|
||||
if args.game is None:
|
||||
data.logger.warn("No game set, upgrading core schema")
|
||||
data.migrate_database("CORE", int(args.version) if args.version is not None else None, args.action)
|
||||
data.migrate_database(
|
||||
"CORE",
|
||||
int(args.version) if args.version is not None else None,
|
||||
args.action,
|
||||
)
|
||||
|
||||
else:
|
||||
data.migrate_database(args.game, int(args.version) if args.version is not None else None, args.action)
|
||||
data.migrate_database(
|
||||
args.game,
|
||||
int(args.version) if args.version is not None else None,
|
||||
args.action,
|
||||
)
|
||||
|
||||
elif args.action == "autoupgrade":
|
||||
data.autoupgrade()
|
||||
|
||||
@@ -110,7 +110,6 @@ class HttpDispatcher(resource.Resource):
|
||||
requirements=dict(game=R"S..."),
|
||||
)
|
||||
|
||||
|
||||
def render_GET(self, request: Request) -> bytes:
|
||||
self.logger.debug(request.uri)
|
||||
test = self.map_get.match(request.uri.decode())
|
||||
|
||||
@@ -135,8 +135,7 @@ if __name__ == "__main__":
|
||||
|
||||
for dir, mod in titles.items():
|
||||
if args.series in mod.game_codes:
|
||||
handler = mod.reader(config, args.version,
|
||||
bin_arg, opt_arg, args.extra)
|
||||
handler = mod.reader(config, args.version, bin_arg, opt_arg, args.extra)
|
||||
handler.read()
|
||||
|
||||
logger.info("Done")
|
||||
|
||||
+27
-9
@@ -89,14 +89,26 @@ class ChuniServlet:
|
||||
|
||||
self.hash_table[version] = {}
|
||||
|
||||
method_list = [method for method in dir(self.versions[version]) if not method.startswith('__')]
|
||||
method_list = [
|
||||
method
|
||||
for method in dir(self.versions[version])
|
||||
if not method.startswith("__")
|
||||
]
|
||||
for method in method_list:
|
||||
method_fixed = inflection.camelize(method)[6:-7]
|
||||
hash = PBKDF2(method_fixed, bytes.fromhex(keys[2]), 128, count=44, hmac_hash_module=SHA1)
|
||||
hash = PBKDF2(
|
||||
method_fixed,
|
||||
bytes.fromhex(keys[2]),
|
||||
128,
|
||||
count=44,
|
||||
hmac_hash_module=SHA1,
|
||||
)
|
||||
|
||||
self.hash_table[version][hash.hex()] = method_fixed
|
||||
|
||||
self.logger.debug(f"Hashed v{version} method {method_fixed} with {bytes.fromhex(keys[2])} to get {hash.hex()}")
|
||||
self.logger.debug(
|
||||
f"Hashed v{version} method {method_fixed} with {bytes.fromhex(keys[2])} to get {hash.hex()}"
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def get_allnet_info(
|
||||
@@ -167,11 +179,15 @@ class ChuniServlet:
|
||||
|
||||
else:
|
||||
if internal_ver not in self.hash_table:
|
||||
self.logger.error(f"v{version} does not support encryption or no keys entered")
|
||||
self.logger.error(
|
||||
f"v{version} does not support encryption or no keys entered"
|
||||
)
|
||||
return zlib.compress(b'{"stat": "0"}')
|
||||
|
||||
elif endpoint.lower() not in self.hash_table[internal_ver]:
|
||||
self.logger.error(f"No hash found for v{version} endpoint {endpoint}")
|
||||
self.logger.error(
|
||||
f"No hash found for v{version} endpoint {endpoint}"
|
||||
)
|
||||
return zlib.compress(b'{"stat": "0"}')
|
||||
|
||||
endpoint = self.hash_table[internal_ver][endpoint.lower()]
|
||||
@@ -193,7 +209,11 @@ class ChuniServlet:
|
||||
|
||||
encrtped = True
|
||||
|
||||
if not encrtped and self.game_cfg.crypto.encrypted_only and internal_ver >= ChuniConstants.VER_CHUNITHM_CRYSTAL_PLUS:
|
||||
if (
|
||||
not encrtped
|
||||
and self.game_cfg.crypto.encrypted_only
|
||||
and internal_ver >= ChuniConstants.VER_CHUNITHM_CRYSTAL_PLUS
|
||||
):
|
||||
self.logger.error(
|
||||
f"Unencrypted v{version} {endpoint} request, but config is set to encrypted only: {req_raw}"
|
||||
)
|
||||
@@ -210,9 +230,7 @@ class ChuniServlet:
|
||||
|
||||
req_data = json.loads(unzip)
|
||||
|
||||
self.logger.info(
|
||||
f"v{version} {endpoint} request from {client_ip}"
|
||||
)
|
||||
self.logger.info(f"v{version} {endpoint} request from {client_ip}")
|
||||
self.logger.debug(req_data)
|
||||
|
||||
func_to_find = "handle_" + inflection.underscore(endpoint) + "_request"
|
||||
|
||||
@@ -13,8 +13,12 @@ class ChuniNewPlus(ChuniNew):
|
||||
|
||||
def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
|
||||
ret = super().handle_get_game_setting_api_request(data)
|
||||
ret["gameSetting"]["romVersion"] = self.game_cfg.version.version(self.version)["rom"]
|
||||
ret["gameSetting"]["dataVersion"] = self.game_cfg.version.version(self.version)["data"]
|
||||
ret["gameSetting"]["romVersion"] = self.game_cfg.version.version(self.version)[
|
||||
"rom"
|
||||
]
|
||||
ret["gameSetting"]["dataVersion"] = self.game_cfg.version.version(self.version)[
|
||||
"data"
|
||||
]
|
||||
ret["gameSetting"][
|
||||
"matchingUri"
|
||||
] = f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/SDHD/205/ChuniServlet/"
|
||||
|
||||
@@ -200,7 +200,9 @@ class ChuniStaticData(BaseData):
|
||||
return result.lastrowid
|
||||
|
||||
def get_login_bonus(
|
||||
self, version: int, preset_id: int,
|
||||
self,
|
||||
version: int,
|
||||
preset_id: int,
|
||||
) -> Optional[List[Row]]:
|
||||
sql = login_bonus.select(
|
||||
and_(
|
||||
|
||||
+1
-3
@@ -109,9 +109,7 @@ class CardMakerServlet:
|
||||
|
||||
req_data = json.loads(unzip)
|
||||
|
||||
self.logger.info(
|
||||
f"v{version} {endpoint} request from {client_ip}"
|
||||
)
|
||||
self.logger.info(f"v{version} {endpoint} request from {client_ip}")
|
||||
self.logger.debug(req_data)
|
||||
|
||||
func_to_find = "handle_" + inflection.underscore(endpoint) + "_request"
|
||||
|
||||
+1
-1
@@ -90,7 +90,7 @@ class CardMakerReader(BaseReader):
|
||||
"v2_00": ChuniConstants.VER_CHUNITHM_NEW,
|
||||
"v2_05": ChuniConstants.VER_CHUNITHM_NEW_PLUS,
|
||||
# Chunithm SUN, ignore for now
|
||||
"v2_10": ChuniConstants.VER_CHUNITHM_NEW_PLUS + 1
|
||||
"v2_10": ChuniConstants.VER_CHUNITHM_NEW_PLUS + 1,
|
||||
}
|
||||
|
||||
for root, dirs, files in os.walk(base_dir):
|
||||
|
||||
+1
-3
@@ -101,9 +101,7 @@ class CxbServlet(resource.Resource):
|
||||
f"Ready on ports {self.game_cfg.server.port} & {self.game_cfg.server.port_secure}"
|
||||
)
|
||||
else:
|
||||
self.logger.info(
|
||||
f"Ready on port {self.game_cfg.server.port}"
|
||||
)
|
||||
self.logger.info(f"Ready on port {self.game_cfg.server.port}")
|
||||
|
||||
def render_POST(self, request: Request):
|
||||
version = 0
|
||||
|
||||
@@ -46,15 +46,21 @@ class IDZPortsConfig:
|
||||
|
||||
@property
|
||||
def userdb(self) -> int:
|
||||
return CoreConfig.get_config_field(self.__config, "idz", "ports", "userdb", default=10000)
|
||||
return CoreConfig.get_config_field(
|
||||
self.__config, "idz", "ports", "userdb", default=10000
|
||||
)
|
||||
|
||||
@property
|
||||
def match(self) -> int:
|
||||
return CoreConfig.get_config_field(self.__config, "idz", "ports", "match", default=10010)
|
||||
return CoreConfig.get_config_field(
|
||||
self.__config, "idz", "ports", "match", default=10010
|
||||
)
|
||||
|
||||
@property
|
||||
def echo(self) -> int:
|
||||
return CoreConfig.get_config_field(self.__config, "idz", "ports", "echo", default=10020)
|
||||
return CoreConfig.get_config_field(
|
||||
self.__config, "idz", "ports", "echo", default=10020
|
||||
)
|
||||
|
||||
|
||||
class IDZConfig(dict):
|
||||
|
||||
+17
-4
@@ -1,5 +1,6 @@
|
||||
from enum import Enum
|
||||
|
||||
|
||||
class IDZConstants:
|
||||
GAME_CODE = "SDDF"
|
||||
|
||||
@@ -25,11 +26,23 @@ class IDZConstants:
|
||||
|
||||
HASH_LUT = [
|
||||
# No clue
|
||||
0x9C82E674, 0x5A4738D9, 0x8B8D7AE0, 0x29EC9D81,
|
||||
0x9C82E674,
|
||||
0x5A4738D9,
|
||||
0x8B8D7AE0,
|
||||
0x29EC9D81,
|
||||
# These three are from AES TE0
|
||||
0x1209091B, 0x1D83839E, 0x582C2C74, 0x341A1A2E,
|
||||
0x361B1B2D, 0xDC6E6EB2, 0xB45A5AEE, 0x5BA0A0FB,
|
||||
0xA45252F6, 0x763B3B4D, 0xB7D6D661, 0x7DB3B3CE,
|
||||
0x1209091B,
|
||||
0x1D83839E,
|
||||
0x582C2C74,
|
||||
0x341A1A2E,
|
||||
0x361B1B2D,
|
||||
0xDC6E6EB2,
|
||||
0xB45A5AEE,
|
||||
0x5BA0A0FB,
|
||||
0xA45252F6,
|
||||
0x763B3B4D,
|
||||
0xB7D6D661,
|
||||
0x7DB3B3CE,
|
||||
]
|
||||
HASH_NUM = 0
|
||||
HASH_MUL = [5, 7, 11, 12][HASH_NUM]
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from core.data import Data
|
||||
from core.config import CoreConfig
|
||||
|
||||
|
||||
class IDZData(Data):
|
||||
def __init__(self, cfg: CoreConfig) -> None:
|
||||
super().__init__(cfg)
|
||||
|
||||
+4
-1
@@ -4,6 +4,7 @@ import logging
|
||||
from core.config import CoreConfig
|
||||
from .config import IDZConfig
|
||||
|
||||
|
||||
class IDZEcho(DatagramProtocol):
|
||||
def __init__(self, cfg: CoreConfig, game_cfg: IDZConfig) -> None:
|
||||
super().__init__()
|
||||
@@ -12,5 +13,7 @@ class IDZEcho(DatagramProtocol):
|
||||
self.logger = logging.getLogger("idz")
|
||||
|
||||
def datagramReceived(self, data, addr):
|
||||
self.logger.debug(f"Echo from from {addr[0]}:{addr[1]} -> {self.transport.getHost().port} - {data.hex()}")
|
||||
self.logger.debug(
|
||||
f"Echo from from {addr[0]}:{addr[1]} -> {self.transport.getHost().port} - {data.hex()}"
|
||||
)
|
||||
self.transport.write(data, addr)
|
||||
@@ -5,7 +5,8 @@ from core.config import CoreConfig
|
||||
from ..config import IDZConfig
|
||||
from ..const import IDZConstants
|
||||
|
||||
class IDZHandlerBase():
|
||||
|
||||
class IDZHandlerBase:
|
||||
name = "generic"
|
||||
cmd_codes = [0x0000] * IDZConstants.NUM_VERS
|
||||
rsp_codes = [0x0001] * IDZConstants.NUM_VERS
|
||||
|
||||
@@ -4,9 +4,10 @@ from .base import IDZHandlerBase
|
||||
from core.config import CoreConfig
|
||||
from ..config import IDZConfig
|
||||
|
||||
|
||||
class IDZHandlerCheckTeamName(IDZHandlerBase):
|
||||
cmd_codes = [0x00a2, 0x00a2, 0x0097, 0x0097]
|
||||
rsp_codes = [0x00a3, 0x00a3, 0x0098, 0x0098]
|
||||
cmd_codes = [0x00A2, 0x00A2, 0x0097, 0x0097]
|
||||
rsp_codes = [0x00A3, 0x00A3, 0x0098, 0x0098]
|
||||
name = "check_team_name"
|
||||
|
||||
def __init__(self, core_cfg: CoreConfig, game_cfg: IDZConfig, version: int) -> None:
|
||||
|
||||
@@ -8,23 +8,37 @@ from core.config import CoreConfig
|
||||
from ..config import IDZConfig
|
||||
|
||||
AUTO_TEAM_NAMES = ["スピードスターズ", "レッドサンズ", "ナイトキッズ"]
|
||||
FULL_WIDTH_NUMS = ["\uff10", "\uff11", "\uff12", "\uff13", "\uff14", "\uff15", "\uff16", "\uff17", "\uff18", "\uff19"]
|
||||
FULL_WIDTH_NUMS = [
|
||||
"\uff10",
|
||||
"\uff11",
|
||||
"\uff12",
|
||||
"\uff13",
|
||||
"\uff14",
|
||||
"\uff15",
|
||||
"\uff16",
|
||||
"\uff17",
|
||||
"\uff18",
|
||||
"\uff19",
|
||||
]
|
||||
|
||||
|
||||
class IDZHandlerCreateAutoTeam(IDZHandlerBase):
|
||||
cmd_codes = [0x007b, 0x007b, 0x0077, 0x0077]
|
||||
rsp_codes = [0x007c, 0x007c, 0x0078, 0x0078]
|
||||
cmd_codes = [0x007B, 0x007B, 0x0077, 0x0077]
|
||||
rsp_codes = [0x007C, 0x007C, 0x0078, 0x0078]
|
||||
name = "create_auto_team"
|
||||
|
||||
def __init__(self, core_cfg: CoreConfig, game_cfg: IDZConfig, version: int) -> None:
|
||||
super().__init__(core_cfg, game_cfg, version)
|
||||
self.size = 0x0ca0
|
||||
self.size = 0x0CA0
|
||||
|
||||
def handle(self, data: bytes) -> bytearray:
|
||||
ret = super().handle(data)
|
||||
aime_id = struct.unpack_from("<I", data, 0x04)[0]
|
||||
name = choice(AUTO_TEAM_NAMES)
|
||||
bg = indexOf(AUTO_TEAM_NAMES, name)
|
||||
number = choice(FULL_WIDTH_NUMS) + choice(FULL_WIDTH_NUMS) + choice(FULL_WIDTH_NUMS)
|
||||
number = (
|
||||
choice(FULL_WIDTH_NUMS) + choice(FULL_WIDTH_NUMS) + choice(FULL_WIDTH_NUMS)
|
||||
)
|
||||
|
||||
tdata = {
|
||||
"id": aime_id,
|
||||
@@ -38,7 +52,7 @@ class IDZHandlerCreateAutoTeam(IDZHandlerBase):
|
||||
"bg": bg,
|
||||
"fx": 0,
|
||||
}
|
||||
tname = tdata['name'].encode("shift-jis")
|
||||
tname = tdata["name"].encode("shift-jis")
|
||||
|
||||
struct.pack_into("<I", ret, 0x0C, tdata["id"])
|
||||
struct.pack_into(f"{len(tname)}s", ret, 0x24, tname)
|
||||
|
||||
@@ -6,6 +6,7 @@ from .base import IDZHandlerBase
|
||||
from core.config import CoreConfig
|
||||
from ..config import IDZConfig
|
||||
|
||||
|
||||
class IDZHandlerCreateProfile(IDZHandlerBase):
|
||||
cmd_codes = [0x0066, 0x0066, 0x0064, 0x0064]
|
||||
rsp_codes = [0x0067, 0x0065, 0x0065, 0x0065]
|
||||
@@ -20,26 +21,18 @@ class IDZHandlerCreateProfile(IDZHandlerBase):
|
||||
|
||||
aime_id = struct.unpack_from("<L", data, 0x04)[0]
|
||||
name = data[0x1E:0x0034].decode("shift-jis").replace("\x00", "")
|
||||
car = data[0x40:0xa0].hex()
|
||||
chara = data[0xa8:0xbc].hex()
|
||||
car = data[0x40:0xA0].hex()
|
||||
chara = data[0xA8:0xBC].hex()
|
||||
|
||||
self.logger.info(f"Create profile for {name} (aime id {aime_id})")
|
||||
|
||||
auto_team = None
|
||||
if not auto_team:
|
||||
team = {
|
||||
"bg": 0,
|
||||
"id": 0,
|
||||
"shop": ""
|
||||
}
|
||||
team = {"bg": 0, "id": 0, "shop": ""}
|
||||
else:
|
||||
tdata = json.loads(auto_team["data"])
|
||||
|
||||
team = {
|
||||
"bg": tdata["bg"],
|
||||
"id": tdata["fx"],
|
||||
"shop": ""
|
||||
}
|
||||
team = {"bg": tdata["bg"], "id": tdata["fx"], "shop": ""}
|
||||
|
||||
profile_data = {
|
||||
"profile": {
|
||||
@@ -53,27 +46,16 @@ class IDZHandlerCreateProfile(IDZHandlerBase):
|
||||
"car_str": car, # These should probably be chaged to dicts
|
||||
"chara_str": chara, # But this works for now...
|
||||
},
|
||||
|
||||
"options": {
|
||||
"music": 0,
|
||||
"pack": 13640,
|
||||
"aura": 0,
|
||||
"paper_cup": 0,
|
||||
"gauges": 5,
|
||||
"driving_style": 0
|
||||
"driving_style": 0,
|
||||
},
|
||||
|
||||
"missions": {
|
||||
"team": [],
|
||||
"solo": []
|
||||
},
|
||||
|
||||
"story": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"rows": {}
|
||||
},
|
||||
|
||||
"missions": {"team": [], "solo": []},
|
||||
"story": {"x": 0, "y": 0, "rows": {}},
|
||||
"unlocks": {
|
||||
"auras": 1,
|
||||
"cup": 0,
|
||||
@@ -81,7 +63,7 @@ class IDZHandlerCreateProfile(IDZHandlerBase):
|
||||
"music": 0,
|
||||
"last_mileage_reward": 0,
|
||||
},
|
||||
"team": team
|
||||
"team": team,
|
||||
}
|
||||
|
||||
if self.version > 2:
|
||||
|
||||
@@ -5,9 +5,10 @@ from .base import IDZHandlerBase
|
||||
from core.config import CoreConfig
|
||||
from ..config import IDZConfig
|
||||
|
||||
|
||||
class IDZHandlerDiscoverProfile(IDZHandlerBase):
|
||||
cmd_codes = [0x006b, 0x0067]
|
||||
rsp_codes = [0x006c, 0x0068, 0x0068,0x0068]
|
||||
cmd_codes = [0x006B, 0x0067]
|
||||
rsp_codes = [0x006C, 0x0068, 0x0068, 0x0068]
|
||||
name = "discover_profile"
|
||||
|
||||
def __init__(self, core_cfg: CoreConfig, game_cfg: IDZConfig, version: int) -> None:
|
||||
|
||||
@@ -5,14 +5,15 @@ from core.config import CoreConfig
|
||||
from ..config import IDZConfig
|
||||
from ..const import IDZConstants
|
||||
|
||||
|
||||
class IDZHandlerLoad2on2A(IDZHandlerBase):
|
||||
cmd_codes = [0x00b0, 0x00b0, 0x00a3, 0x00a3]
|
||||
rsp_codes = [0x00b1, 0x00b1, 0x00a4, 0x00a4]
|
||||
cmd_codes = [0x00B0, 0x00B0, 0x00A3, 0x00A3]
|
||||
rsp_codes = [0x00B1, 0x00B1, 0x00A4, 0x00A4]
|
||||
name = "load_2on2A"
|
||||
|
||||
def __init__(self, core_cfg: CoreConfig, game_cfg: IDZConfig, version: int) -> None:
|
||||
super().__init__(core_cfg, game_cfg, version)
|
||||
self.size = 0x04c0
|
||||
self.size = 0x04C0
|
||||
|
||||
if version >= IDZConstants.VER_IDZ_210:
|
||||
self.size = 0x1290
|
||||
@@ -20,6 +21,7 @@ class IDZHandlerLoad2on2A(IDZHandlerBase):
|
||||
def handle(self, data: bytes) -> bytearray:
|
||||
return super().handle(data)
|
||||
|
||||
|
||||
class IDZHandlerLoad2on2B(IDZHandlerBase):
|
||||
cmd_codes = [0x0132] * 4
|
||||
rsp_codes = [0x0133] * 4
|
||||
@@ -27,7 +29,7 @@ class IDZHandlerLoad2on2B(IDZHandlerBase):
|
||||
|
||||
def __init__(self, core_cfg: CoreConfig, game_cfg: IDZConfig, version: int) -> None:
|
||||
super().__init__(core_cfg, game_cfg, version)
|
||||
self.size = 0x04c0
|
||||
self.size = 0x04C0
|
||||
|
||||
if version >= IDZConstants.VER_IDZ_210:
|
||||
self.size = 0x0540
|
||||
|
||||
@@ -5,6 +5,7 @@ from core.config import CoreConfig
|
||||
from ..config import IDZConfig
|
||||
from ..const import IDZConstants
|
||||
|
||||
|
||||
class IDZHandlerLoadConfigA(IDZHandlerBase):
|
||||
cmd_codes = [0x0004] * IDZConstants.NUM_VERS
|
||||
rsp_codes = [0x0005] * IDZConstants.NUM_VERS
|
||||
@@ -12,10 +13,10 @@ class IDZHandlerLoadConfigA(IDZHandlerBase):
|
||||
|
||||
def __init__(self, core_cfg: CoreConfig, game_cfg: IDZConfig, version: int) -> None:
|
||||
super().__init__(core_cfg, game_cfg, version)
|
||||
self.size = 0x01a0
|
||||
self.size = 0x01A0
|
||||
|
||||
if self.version > 1:
|
||||
self.size = 0x05e0
|
||||
self.size = 0x05E0
|
||||
|
||||
def handle(self, data: bytes) -> bytearray:
|
||||
ret = super().handle(data)
|
||||
@@ -23,9 +24,10 @@ class IDZHandlerLoadConfigA(IDZHandlerBase):
|
||||
struct.pack_into("<I", ret, 0x16, 230)
|
||||
return ret
|
||||
|
||||
|
||||
class IDZHandlerLoadConfigB(IDZHandlerBase):
|
||||
cmd_codes = [0x00ab, 0x00ab, 0x00a0, 0x00a0]
|
||||
rsp_codes = [0x00ac, 0x00ac, 0x00a1, 0x00a1]
|
||||
cmd_codes = [0x00AB, 0x00AB, 0x00A0, 0x00A0]
|
||||
rsp_codes = [0x00AC, 0x00AC, 0x00A1, 0x00A1]
|
||||
name = "load_config_b"
|
||||
|
||||
def __init__(self, core_cfg: CoreConfig, game_cfg: IDZConfig, version: int) -> None:
|
||||
|
||||
@@ -4,9 +4,10 @@ from .base import IDZHandlerBase
|
||||
from core.config import CoreConfig
|
||||
from ..config import IDZConfig
|
||||
|
||||
|
||||
class IDZHandlerLoadGhost(IDZHandlerBase):
|
||||
cmd_codes = [0x00a0, 0x00a0, 0x0095, 0x0095]
|
||||
rsp_codes = [0x00a1, 0x00a1, 0x0096, 0x0096]
|
||||
cmd_codes = [0x00A0, 0x00A0, 0x0095, 0x0095]
|
||||
rsp_codes = [0x00A1, 0x00A1, 0x0096, 0x0096]
|
||||
name = "load_ghost"
|
||||
|
||||
def __init__(self, core_cfg: CoreConfig, game_cfg: IDZConfig, version: int) -> None:
|
||||
|
||||
@@ -5,18 +5,19 @@ from core.config import CoreConfig
|
||||
from ..config import IDZConfig
|
||||
from ..const import IDZConstants
|
||||
|
||||
|
||||
class IDZHandlerLoadProfile(IDZHandlerBase):
|
||||
cmd_codes = [0x0067, 0x012f, 0x012f, 0x0142]
|
||||
rsp_codes = [0x0065, 0x012e, 0x012e, 0x0141]
|
||||
cmd_codes = [0x0067, 0x012F, 0x012F, 0x0142]
|
||||
rsp_codes = [0x0065, 0x012E, 0x012E, 0x0141]
|
||||
name = "load_profile"
|
||||
|
||||
def __init__(self, core_cfg: CoreConfig, game_cfg: IDZConfig, version: int) -> None:
|
||||
super().__init__(core_cfg, game_cfg, version)
|
||||
|
||||
if self.version == IDZConstants.VER_IDZ_110:
|
||||
self.size = 0x0d30
|
||||
self.size = 0x0D30
|
||||
elif self.version == IDZConstants.VER_IDZ_130:
|
||||
self.size = 0x0ea0
|
||||
self.size = 0x0EA0
|
||||
elif self.version == IDZConstants.VER_IDZ_210:
|
||||
self.size = 0x1360
|
||||
elif self.version == IDZConstants.VER_IDZ_230:
|
||||
|
||||
@@ -4,6 +4,7 @@ from .base import IDZHandlerBase
|
||||
from core.config import CoreConfig
|
||||
from ..config import IDZConfig
|
||||
|
||||
|
||||
class IDZHandlerLoadRewardTable(IDZHandlerBase):
|
||||
cmd_codes = [0x0086, 0x0086, 0x007F, 0x007F]
|
||||
rsp_codes = [0x0087, 0x0087, 0x0080, 0x0080]
|
||||
@@ -11,7 +12,7 @@ class IDZHandlerLoadRewardTable(IDZHandlerBase):
|
||||
|
||||
def __init__(self, core_cfg: CoreConfig, game_cfg: IDZConfig, version: int) -> None:
|
||||
super().__init__(core_cfg, game_cfg, version)
|
||||
self.size = 0x01c0
|
||||
self.size = 0x01C0
|
||||
|
||||
def handle(self, data: bytes) -> bytearray:
|
||||
return super().handle(data)
|
||||
|
||||
@@ -5,6 +5,7 @@ from core.config import CoreConfig
|
||||
from ..config import IDZConfig
|
||||
from ..const import IDZConstants
|
||||
|
||||
|
||||
class IDZHandlerLoadServerInfo(IDZHandlerBase):
|
||||
cmd_codes = [0x0006] * IDZConstants.NUM_VERS
|
||||
rsp_codes = [0x0007] * IDZConstants.NUM_VERS
|
||||
@@ -12,7 +13,7 @@ class IDZHandlerLoadServerInfo(IDZHandlerBase):
|
||||
|
||||
def __init__(self, core_cfg: CoreConfig, game_cfg: IDZConfig, version: int) -> None:
|
||||
super().__init__(core_cfg, game_cfg, version)
|
||||
self.size = 0x04b0
|
||||
self.size = 0x04B0
|
||||
|
||||
def handle(self, data: bytes) -> bytearray:
|
||||
ret = super().handle(data)
|
||||
@@ -28,33 +29,68 @@ class IDZHandlerLoadServerInfo(IDZHandlerBase):
|
||||
len_error = len(err_str)
|
||||
|
||||
struct.pack_into("<I", ret, 0x2 + offset, 1) # Status
|
||||
struct.pack_into(f"{len_hostname}s", ret, 0x4 + offset, self.core_config.title.hostname.encode())
|
||||
struct.pack_into(
|
||||
f"{len_hostname}s",
|
||||
ret,
|
||||
0x4 + offset,
|
||||
self.core_config.title.hostname.encode(),
|
||||
)
|
||||
struct.pack_into("<I", ret, 0x84 + offset, self.game_cfg.ports.userdb)
|
||||
struct.pack_into("<I", ret, 0x86 + offset, self.game_cfg.ports.userdb + 1)
|
||||
|
||||
struct.pack_into(f"{len_hostname}s", ret, 0x88 + offset, self.core_config.title.hostname.encode())
|
||||
struct.pack_into(
|
||||
f"{len_hostname}s",
|
||||
ret,
|
||||
0x88 + offset,
|
||||
self.core_config.title.hostname.encode(),
|
||||
)
|
||||
struct.pack_into("<I", ret, 0x108 + offset, self.game_cfg.ports.match - 1)
|
||||
struct.pack_into("<I", ret, 0x10a + offset, self.game_cfg.ports.match - 3)
|
||||
struct.pack_into("<I", ret, 0x10c + offset, self.game_cfg.ports.match - 2)
|
||||
struct.pack_into("<I", ret, 0x10A + offset, self.game_cfg.ports.match - 3)
|
||||
struct.pack_into("<I", ret, 0x10C + offset, self.game_cfg.ports.match - 2)
|
||||
|
||||
struct.pack_into("<I", ret, 0x10e + offset, self.game_cfg.ports.match + 2)
|
||||
struct.pack_into("<I", ret, 0x10E + offset, self.game_cfg.ports.match + 2)
|
||||
struct.pack_into("<I", ret, 0x110 + offset, self.game_cfg.ports.match + 3)
|
||||
struct.pack_into("<I", ret, 0x112 + offset, self.game_cfg.ports.match + 1)
|
||||
|
||||
struct.pack_into(f"{len_hostname}s", ret, 0x114 + offset, self.core_config.title.hostname.encode())
|
||||
struct.pack_into(
|
||||
f"{len_hostname}s",
|
||||
ret,
|
||||
0x114 + offset,
|
||||
self.core_config.title.hostname.encode(),
|
||||
)
|
||||
struct.pack_into("<I", ret, 0x194 + offset, self.game_cfg.ports.echo + 2)
|
||||
|
||||
struct.pack_into(f"{len_hostname}s", ret, 0x0199 + offset, self.core_config.title.hostname.encode())
|
||||
struct.pack_into(
|
||||
f"{len_hostname}s",
|
||||
ret,
|
||||
0x0199 + offset,
|
||||
self.core_config.title.hostname.encode(),
|
||||
)
|
||||
struct.pack_into("<I", ret, 0x0219 + offset, self.game_cfg.ports.echo + 3)
|
||||
|
||||
struct.pack_into(f"{len_hostname}s", ret, 0x021c + offset, self.core_config.title.hostname.encode())
|
||||
struct.pack_into(f"{len_hostname}s", ret, 0x029c + offset, self.core_config.title.hostname.encode())
|
||||
struct.pack_into(f"{len_hostname}s", ret, 0x031c + offset, self.core_config.title.hostname.encode())
|
||||
struct.pack_into(
|
||||
f"{len_hostname}s",
|
||||
ret,
|
||||
0x021C + offset,
|
||||
self.core_config.title.hostname.encode(),
|
||||
)
|
||||
struct.pack_into(
|
||||
f"{len_hostname}s",
|
||||
ret,
|
||||
0x029C + offset,
|
||||
self.core_config.title.hostname.encode(),
|
||||
)
|
||||
struct.pack_into(
|
||||
f"{len_hostname}s",
|
||||
ret,
|
||||
0x031C + offset,
|
||||
self.core_config.title.hostname.encode(),
|
||||
)
|
||||
|
||||
struct.pack_into("<I", ret, 0x39c + offset, self.game_cfg.ports.echo)
|
||||
struct.pack_into("<I", ret, 0x39e + offset, self.game_cfg.ports.echo + 1)
|
||||
struct.pack_into("<I", ret, 0x39C + offset, self.game_cfg.ports.echo)
|
||||
struct.pack_into("<I", ret, 0x39E + offset, self.game_cfg.ports.echo + 1)
|
||||
|
||||
struct.pack_into(f"{len_news}s", ret, 0x03a0 + offset, news_str.encode())
|
||||
struct.pack_into(f"{len_news}s", ret, 0x03A0 + offset, news_str.encode())
|
||||
struct.pack_into(f"{len_error}s", ret, 0x0424 + offset, err_str.encode())
|
||||
|
||||
return ret
|
||||
|
||||
@@ -4,26 +4,28 @@ from .base import IDZHandlerBase
|
||||
from core.config import CoreConfig
|
||||
from ..config import IDZConfig
|
||||
|
||||
|
||||
class IDZHandlerLoadTeamRankingA(IDZHandlerBase):
|
||||
cmd_codes = [0x00b9, 0x00b9, 0x00a7, 0x00a7]
|
||||
rsp_codes = [0x00b1] * 4
|
||||
cmd_codes = [0x00B9, 0x00B9, 0x00A7, 0x00A7]
|
||||
rsp_codes = [0x00B1] * 4
|
||||
name = "load_team_ranking_a"
|
||||
|
||||
def __init__(self, core_cfg: CoreConfig, game_cfg: IDZConfig, version: int) -> None:
|
||||
super().__init__(core_cfg, game_cfg, version)
|
||||
self.size = 0x0ba0
|
||||
self.size = 0x0BA0
|
||||
|
||||
def handle(self, data: bytes) -> bytearray:
|
||||
return super().handle(data)
|
||||
|
||||
|
||||
class IDZHandlerLoadTeamRankingB(IDZHandlerBase):
|
||||
cmd_codes = [0x00bb, 0x00bb, 0x00a9, 0x00a9]
|
||||
rsp_codes = [0x00a8] * 4
|
||||
cmd_codes = [0x00BB, 0x00BB, 0x00A9, 0x00A9]
|
||||
rsp_codes = [0x00A8] * 4
|
||||
name = "load_team_ranking_b"
|
||||
|
||||
def __init__(self, core_cfg: CoreConfig, game_cfg: IDZConfig, version: int) -> None:
|
||||
super().__init__(core_cfg, game_cfg, version)
|
||||
self.size = 0x0ba0
|
||||
self.size = 0x0BA0
|
||||
|
||||
def handle(self, data: bytes) -> bytearray:
|
||||
return super().handle(data)
|
||||
|
||||
@@ -5,9 +5,10 @@ from .base import IDZHandlerBase
|
||||
from core.config import CoreConfig
|
||||
from ..config import IDZConfig
|
||||
|
||||
|
||||
class IDZHandlerLoadTopTen(IDZHandlerBase):
|
||||
cmd_codes = [0x012c] * 4
|
||||
rsp_codes = [0x00ce] * 4
|
||||
cmd_codes = [0x012C] * 4
|
||||
rsp_codes = [0x00CE] * 4
|
||||
name = "load_top_ten"
|
||||
|
||||
def __init__(self, core_cfg: CoreConfig, game_cfg: IDZConfig, version: int) -> None:
|
||||
@@ -19,12 +20,16 @@ class IDZHandlerLoadTopTen(IDZHandlerBase):
|
||||
tracks_dates: List[Tuple[int, int]] = []
|
||||
for i in range(32):
|
||||
tracks_dates.append(
|
||||
(struct.unpack_from("<H", data, 0x04 + (2 * i))[0], "little",
|
||||
struct.unpack_from("<I", data, 0x44 + (4 * i))[0], "little")
|
||||
(
|
||||
struct.unpack_from("<H", data, 0x04 + (2 * i))[0],
|
||||
"little",
|
||||
struct.unpack_from("<I", data, 0x44 + (4 * i))[0],
|
||||
"little",
|
||||
)
|
||||
)
|
||||
# TODO: Best scores
|
||||
for i in range(3):
|
||||
offset = 0x16c0 + 0x1c * i
|
||||
struct.pack_into("<B", ret, offset + 0x02, 0xff)
|
||||
offset = 0x16C0 + 0x1C * i
|
||||
struct.pack_into("<B", ret, offset + 0x02, 0xFF)
|
||||
|
||||
return ret
|
||||
|
||||
@@ -7,9 +7,10 @@ from core.config import CoreConfig
|
||||
from ..config import IDZConfig
|
||||
from ..const import IDZConstants
|
||||
|
||||
|
||||
class IDZHandlerLockProfile(IDZHandlerBase):
|
||||
cmd_codes = [0x0069, 0x0069, 0x0065, 0x0065]
|
||||
rsp_codes = [0x006a, 0x006a, 0x0066, 0x0066]
|
||||
rsp_codes = [0x006A, 0x006A, 0x0066, 0x0066]
|
||||
name = "lock_profile"
|
||||
|
||||
def __init__(self, core_cfg: CoreConfig, game_cfg: IDZConfig, version: int) -> None:
|
||||
@@ -20,7 +21,9 @@ class IDZHandlerLockProfile(IDZHandlerBase):
|
||||
ret = super().handle(data)
|
||||
profile_data = {
|
||||
"status": IDZConstants.PROFILE_STATUS.UNLOCKED.value,
|
||||
"expire_time": int((datetime.now() + timedelta(hours=1)).timestamp() / 1000)
|
||||
"expire_time": int(
|
||||
(datetime.now() + timedelta(hours=1)).timestamp() / 1000
|
||||
),
|
||||
}
|
||||
user_id = struct.unpack_from("<I", data, 0x04)[0]
|
||||
profile = None
|
||||
@@ -34,6 +37,6 @@ class IDZHandlerLockProfile(IDZHandlerBase):
|
||||
|
||||
def handle_common(cls, data: Dict, ret: bytearray) -> bytearray:
|
||||
struct.pack_into("<B", ret, 0x18, data["status"])
|
||||
struct.pack_into("<h", ret, 0x1a, -1)
|
||||
struct.pack_into("<I", ret, 0x1c, data["expire_time"])
|
||||
struct.pack_into("<h", ret, 0x1A, -1)
|
||||
struct.pack_into("<I", ret, 0x1C, data["expire_time"])
|
||||
return ret
|
||||
|
||||
@@ -3,8 +3,9 @@ from core.config import CoreConfig
|
||||
from ..config import IDZConfig
|
||||
from ..const import IDZConstants
|
||||
|
||||
|
||||
class IDZHandlerSaveExpedition(IDZHandlerBase):
|
||||
cmd_codes = [0x008c, 0x013f]
|
||||
cmd_codes = [0x008C, 0x013F]
|
||||
name = "save_expedition"
|
||||
|
||||
def __init__(self, core_cfg: CoreConfig, game_cfg: IDZConfig, version: int) -> None:
|
||||
|
||||
@@ -4,6 +4,7 @@ from .base import IDZHandlerBase
|
||||
from core.config import CoreConfig
|
||||
from ..config import IDZConfig
|
||||
|
||||
|
||||
class IDZHandlerSaveProfile(IDZHandlerBase):
|
||||
cmd_codes = [0x0068, 0x0138, 0x0138, 0x0143]
|
||||
name = "save_profile"
|
||||
|
||||
@@ -5,17 +5,18 @@ from core.config import CoreConfig
|
||||
from ..config import IDZConfig
|
||||
from ..const import IDZConstants
|
||||
|
||||
|
||||
class IDZHandlerSaveTimeAttack(IDZHandlerBase):
|
||||
cmd_codes = [0x00CD, 0x0136, 0x0136, 0x0136]
|
||||
rsp_codes = [0x00ce, 0x00ce, 0x00cd, 0x00cd]
|
||||
rsp_codes = [0x00CE, 0x00CE, 0x00CD, 0x00CD]
|
||||
name = "save_time_attack"
|
||||
|
||||
def __init__(self, core_cfg: CoreConfig, game_cfg: IDZConfig, version: int) -> None:
|
||||
super().__init__(core_cfg, game_cfg, version)
|
||||
self.size = 0x00b0
|
||||
self.size = 0x00B0
|
||||
|
||||
if self.version > IDZConstants.VER_IDZ_130:
|
||||
self.size = 0x00f0
|
||||
self.size = 0x00F0
|
||||
|
||||
def handle(self, data: bytes) -> bytearray:
|
||||
ret = super().handle(data)
|
||||
|
||||
@@ -4,6 +4,7 @@ from .base import IDZHandlerBase
|
||||
from core.config import CoreConfig
|
||||
from ..config import IDZConfig
|
||||
|
||||
|
||||
class IDZHandlerSaveTopic(IDZHandlerBase):
|
||||
cmd_codes = [0x009A, 0x009A, 0x0091, 0x0091]
|
||||
rsp_codes = [0x009B, 0x009B, 0x0092, 0x0092]
|
||||
@@ -11,7 +12,7 @@ class IDZHandlerSaveTopic(IDZHandlerBase):
|
||||
|
||||
def __init__(self, core_cfg: CoreConfig, game_cfg: IDZConfig, version: int) -> None:
|
||||
super().__init__(core_cfg, game_cfg, version)
|
||||
self.size = 0x05d0
|
||||
self.size = 0x05D0
|
||||
|
||||
def handle(self, data: bytes) -> bytearray:
|
||||
return super().handle(data)
|
||||
|
||||
@@ -4,8 +4,9 @@ from .base import IDZHandlerBase
|
||||
from core.config import CoreConfig
|
||||
from ..config import IDZConfig
|
||||
|
||||
|
||||
class IDZHandlerUnknown(IDZHandlerBase):
|
||||
cmd_codes = [0x00ad, 0x00ad, 0x00a2, 0x00a2]
|
||||
cmd_codes = [0x00AD, 0x00AD, 0x00A2, 0x00A2]
|
||||
name = "unknown"
|
||||
|
||||
def __init__(self, core_cfg: CoreConfig, game_cfg: IDZConfig, version: int) -> None:
|
||||
|
||||
@@ -5,9 +5,10 @@ from core.config import CoreConfig
|
||||
from ..config import IDZConfig
|
||||
from ..const import IDZConstants
|
||||
|
||||
|
||||
class IDZHandlerUnlockProfile(IDZHandlerBase):
|
||||
cmd_codes = [0x006f, 0x006f, 0x006b, 0x006b]
|
||||
rsp_codes = [0x0070, 0x0070, 0x006c, 0x006c]
|
||||
cmd_codes = [0x006F, 0x006F, 0x006B, 0x006B]
|
||||
rsp_codes = [0x0070, 0x0070, 0x006C, 0x006C]
|
||||
name = "unlock_profile"
|
||||
|
||||
def __init__(self, core_cfg: CoreConfig, game_cfg: IDZConfig, version: int) -> None:
|
||||
|
||||
@@ -4,6 +4,7 @@ from .base import IDZHandlerBase
|
||||
from core.config import CoreConfig
|
||||
from ..config import IDZConfig
|
||||
|
||||
|
||||
class IDZHandlerUpdateProvisionalStoreRank(IDZHandlerBase):
|
||||
cmd_codes = [0x0082, 0x0082, 0x007C, 0x007C]
|
||||
rsp_codes = [0x0083, 0x0083, 0x007D, 0x007D]
|
||||
@@ -11,7 +12,7 @@ class IDZHandlerUpdateProvisionalStoreRank(IDZHandlerBase):
|
||||
|
||||
def __init__(self, core_cfg: CoreConfig, game_cfg: IDZConfig, version: int) -> None:
|
||||
super().__init__(core_cfg, game_cfg, version)
|
||||
self.size = 0x02b0
|
||||
self.size = 0x02B0
|
||||
|
||||
def handle(self, data: bytes) -> bytearray:
|
||||
return super().handle(data)
|
||||
|
||||
@@ -5,9 +5,10 @@ from core.config import CoreConfig
|
||||
from ..config import IDZConfig
|
||||
from ..const import IDZConstants
|
||||
|
||||
|
||||
class IDZHandlerUpdateStoryClearNum(IDZHandlerBase):
|
||||
cmd_codes = [0x007f, 0x097f, 0x013d, 0x0144]
|
||||
rsp_codes = [0x0080, 0x013e, 0x013e, 0x0145]
|
||||
cmd_codes = [0x007F, 0x097F, 0x013D, 0x0144]
|
||||
rsp_codes = [0x0080, 0x013E, 0x013E, 0x0145]
|
||||
name = "update_story_clear_num"
|
||||
|
||||
def __init__(self, core_cfg: CoreConfig, game_cfg: IDZConfig, version: int) -> None:
|
||||
@@ -16,7 +17,7 @@ class IDZHandlerUpdateStoryClearNum(IDZHandlerBase):
|
||||
if self.version == IDZConstants.VER_IDZ_110:
|
||||
self.size = 0x0220
|
||||
elif self.version == IDZConstants.VER_IDZ_130:
|
||||
self.size = 0x04f0
|
||||
self.size = 0x04F0
|
||||
elif self.version == IDZConstants.VER_IDZ_210:
|
||||
self.size = 0x0510
|
||||
elif self.version == IDZConstants.VER_IDZ_230:
|
||||
|
||||
@@ -5,8 +5,9 @@ from core.config import CoreConfig
|
||||
from ..config import IDZConfig
|
||||
from ..const import IDZConstants
|
||||
|
||||
|
||||
class IDZHandleUpdateTeamPoints(IDZHandlerBase):
|
||||
cmd_codes = [0x0081, 0x0081, 0x007b, 0x007b]
|
||||
cmd_codes = [0x0081, 0x0081, 0x007B, 0x007B]
|
||||
name = "unlock_profile"
|
||||
|
||||
def __init__(self, core_cfg: CoreConfig, game_cfg: IDZConfig, version: int) -> None:
|
||||
|
||||
@@ -5,8 +5,9 @@ from core.config import CoreConfig
|
||||
from ..config import IDZConfig
|
||||
from ..const import IDZConstants
|
||||
|
||||
|
||||
class IDZHandleUpdateUIReport(IDZHandlerBase):
|
||||
cmd_codes = [0x0084, 0x0084, 0x007e, 0x007e]
|
||||
cmd_codes = [0x0084, 0x0084, 0x007E, 0x007E]
|
||||
name = "update_ui_report"
|
||||
|
||||
def __init__(self, core_cfg: CoreConfig, game_cfg: IDZConfig, version: int) -> None:
|
||||
|
||||
@@ -5,8 +5,9 @@ from core.config import CoreConfig
|
||||
from ..config import IDZConfig
|
||||
from ..const import IDZConstants
|
||||
|
||||
|
||||
class IDZHandleUpdateUserLog(IDZHandlerBase):
|
||||
cmd_codes = [0x00bd, 0x00bd, 0x00ab, 0x00b3]
|
||||
cmd_codes = [0x00BD, 0x00BD, 0x00AB, 0x00B3]
|
||||
name = "update_user_log"
|
||||
|
||||
def __init__(self, core_cfg: CoreConfig, game_cfg: IDZConfig, version: int) -> None:
|
||||
|
||||
+40
-12
@@ -16,6 +16,7 @@ from .userdb import IDZUserDBFactory, IDZUserDBWeb, IDZKey
|
||||
from .echo import IDZEcho
|
||||
from .handlers import IDZHandlerLoadConfigB
|
||||
|
||||
|
||||
class IDZServlet:
|
||||
def __init__(self, core_cfg: CoreConfig, cfg_dir: str) -> None:
|
||||
self.core_cfg = core_cfg
|
||||
@@ -56,8 +57,11 @@ class IDZServlet:
|
||||
def rsaHashKeyN(cls, data):
|
||||
hash_ = 0
|
||||
for i in data:
|
||||
hash_ = hash_ * IDZConstants.HASH_MUL + (i ^ IDZConstants.HASH_XOR) ^ IDZConstants.HASH_LUT[i & 0xf]
|
||||
hash_ &= 0xffffffff
|
||||
hash_ = (
|
||||
hash_ * IDZConstants.HASH_MUL + (i ^ IDZConstants.HASH_XOR)
|
||||
^ IDZConstants.HASH_LUT[i & 0xF]
|
||||
)
|
||||
hash_ &= 0xFFFFFFFF
|
||||
return hash_
|
||||
|
||||
@classmethod
|
||||
@@ -77,7 +81,11 @@ class IDZServlet:
|
||||
logging.getLogger("idz").error("IDZ: No RSA/AES keys! IDZ cannot start")
|
||||
return (False, "", "")
|
||||
|
||||
hostname = core_cfg.title.hostname if not game_cfg.server.hostname else game_cfg.server.hostname
|
||||
hostname = (
|
||||
core_cfg.title.hostname
|
||||
if not game_cfg.server.hostname
|
||||
else game_cfg.server.hostname
|
||||
)
|
||||
return (
|
||||
True,
|
||||
f"",
|
||||
@@ -119,13 +127,25 @@ class IDZServlet:
|
||||
except AttributeError as e:
|
||||
continue
|
||||
|
||||
endpoints.serverFromString(reactor, f"tcp:{self.game_cfg.ports.userdb}:interface={self.core_cfg.server.listen_address}")\
|
||||
.listen(IDZUserDBFactory(self.core_cfg, self.game_cfg, self.rsa_keys, handler_map))
|
||||
endpoints.serverFromString(
|
||||
reactor,
|
||||
f"tcp:{self.game_cfg.ports.userdb}:interface={self.core_cfg.server.listen_address}",
|
||||
).listen(
|
||||
IDZUserDBFactory(self.core_cfg, self.game_cfg, self.rsa_keys, handler_map)
|
||||
)
|
||||
|
||||
reactor.listenUDP(self.game_cfg.ports.echo, IDZEcho(self.core_cfg, self.game_cfg))
|
||||
reactor.listenUDP(self.game_cfg.ports.echo + 1, IDZEcho(self.core_cfg, self.game_cfg))
|
||||
reactor.listenUDP(self.game_cfg.ports.match, IDZEcho(self.core_cfg, self.game_cfg))
|
||||
reactor.listenUDP(self.game_cfg.ports.userdb + 1, IDZEcho(self.core_cfg, self.game_cfg))
|
||||
reactor.listenUDP(
|
||||
self.game_cfg.ports.echo, IDZEcho(self.core_cfg, self.game_cfg)
|
||||
)
|
||||
reactor.listenUDP(
|
||||
self.game_cfg.ports.echo + 1, IDZEcho(self.core_cfg, self.game_cfg)
|
||||
)
|
||||
reactor.listenUDP(
|
||||
self.game_cfg.ports.match, IDZEcho(self.core_cfg, self.game_cfg)
|
||||
)
|
||||
reactor.listenUDP(
|
||||
self.game_cfg.ports.userdb + 1, IDZEcho(self.core_cfg, self.game_cfg)
|
||||
)
|
||||
|
||||
self.logger.info(f"UserDB Listening on port {self.game_cfg.ports.userdb}")
|
||||
|
||||
@@ -136,10 +156,18 @@ class IDZServlet:
|
||||
|
||||
def render_GET(self, request: Request, version: int, url_path: str) -> bytes:
|
||||
self.logger.info(f"IDZ GET request: {url_path}")
|
||||
request.responseHeaders.setRawHeaders('Content-Type', [b"text/plain; charset=utf-8"])
|
||||
request.responseHeaders.setRawHeaders("Last-Modified", [b"Sun, 23 Apr 2023 05:33:20 GMT"])
|
||||
request.responseHeaders.setRawHeaders(
|
||||
"Content-Type", [b"text/plain; charset=utf-8"]
|
||||
)
|
||||
request.responseHeaders.setRawHeaders(
|
||||
"Last-Modified", [b"Sun, 23 Apr 2023 05:33:20 GMT"]
|
||||
)
|
||||
|
||||
news = self.game_cfg.server.news if self.game_cfg.server.news else f"Welcome to Initial D Arcade Stage Zero on {self.core_cfg.server.name}!"
|
||||
news = (
|
||||
self.game_cfg.server.news
|
||||
if self.game_cfg.server.news
|
||||
else f"Welcome to Initial D Arcade Stage Zero on {self.core_cfg.server.name}!"
|
||||
)
|
||||
news += "\r\n"
|
||||
news = "1979/01/01 00:00:00 2099/12/31 23:59:59 " + news
|
||||
|
||||
|
||||
+45
-12
@@ -19,6 +19,7 @@ from .handlers import IDZHandlerBase
|
||||
|
||||
HANDLER_MAP: List[Dict]
|
||||
|
||||
|
||||
class IDZKey:
|
||||
def __init__(self, n, d, e, hashN: int) -> None:
|
||||
self.N = n
|
||||
@@ -26,9 +27,16 @@ class IDZKey:
|
||||
self.e = e
|
||||
self.hashN = hashN
|
||||
|
||||
|
||||
class IDZUserDBProtocol(Protocol):
|
||||
def __init__(self, core_cfg: CoreConfig, game_cfg: IDZConfig, keys: List[IDZKey], handlers: List[Dict]) -> None:
|
||||
self.logger = logging.getLogger('idz')
|
||||
def __init__(
|
||||
self,
|
||||
core_cfg: CoreConfig,
|
||||
game_cfg: IDZConfig,
|
||||
keys: List[IDZKey],
|
||||
handlers: List[Dict],
|
||||
) -> None:
|
||||
self.logger = logging.getLogger("idz")
|
||||
self.core_config = core_cfg
|
||||
self.game_config = game_cfg
|
||||
self.rsa_keys = keys
|
||||
@@ -57,7 +65,11 @@ class IDZUserDBProtocol(Protocol):
|
||||
|
||||
rsa_key = random.choice(self.rsa_keys)
|
||||
key_enc: int = pow(base, rsa_key.e, rsa_key.N)
|
||||
result = key_enc.to_bytes(0x40, "little") + struct.pack("<I", 0x01020304) + rsa_key.hashN.to_bytes(4, "little")
|
||||
result = (
|
||||
key_enc.to_bytes(0x40, "little")
|
||||
+ struct.pack("<I", 0x01020304)
|
||||
+ rsa_key.hashN.to_bytes(4, "little")
|
||||
)
|
||||
|
||||
self.logger.debug(f"Send handshake {result.hex()}")
|
||||
|
||||
@@ -100,7 +112,9 @@ class IDZUserDBProtocol(Protocol):
|
||||
self.version = None
|
||||
self.version_internal = None
|
||||
|
||||
self.logger.debug(f"Userdb v{self.version} handshake response from {self.transport.getPeer().host}")
|
||||
self.logger.debug(
|
||||
f"Userdb v{self.version} handshake response from {self.transport.getPeer().host}"
|
||||
)
|
||||
return
|
||||
|
||||
elif self.skip_next:
|
||||
@@ -110,19 +124,25 @@ class IDZUserDBProtocol(Protocol):
|
||||
|
||||
elif self.version is None:
|
||||
# We didn't get a handshake before, and this isn't one now, so we're up the creek
|
||||
self.logger.info(f"Bad UserDB request from from {self.transport.getPeer().host}")
|
||||
self.logger.info(
|
||||
f"Bad UserDB request from from {self.transport.getPeer().host}"
|
||||
)
|
||||
self.transport.write(b"\x00")
|
||||
return
|
||||
|
||||
cmd = struct.unpack_from("<H", data_dec, 0)[0]
|
||||
|
||||
handler_cls: Optional[Type[IDZHandlerBase]] = self.handlers[self.version_internal].get(cmd, None)
|
||||
handler_cls: Optional[Type[IDZHandlerBase]] = self.handlers[
|
||||
self.version_internal
|
||||
].get(cmd, None)
|
||||
if handler_cls is None:
|
||||
self.logger.warn(f"No handler for v{self.version} {hex(cmd)} cmd")
|
||||
handler_cls = IDZHandlerBase
|
||||
|
||||
handler = handler_cls(self.core_config, self.game_config, self.version_internal)
|
||||
self.logger.info(f"Userdb v{self.version} {handler.name} request from {self.transport.getPeer().host}")
|
||||
self.logger.info(
|
||||
f"Userdb v{self.version} {handler.name} request from {self.transport.getPeer().host}"
|
||||
)
|
||||
response = handler.handle(data_dec)
|
||||
|
||||
self.logger.debug(f"Response: {response.hex()}")
|
||||
@@ -136,14 +156,23 @@ class IDZUserDBProtocol(Protocol):
|
||||
class IDZUserDBFactory(Factory):
|
||||
protocol = IDZUserDBProtocol
|
||||
|
||||
def __init__(self, cfg: CoreConfig, game_cfg: IDZConfig, keys: List[IDZKey], handlers: List[Dict]) -> None:
|
||||
def __init__(
|
||||
self,
|
||||
cfg: CoreConfig,
|
||||
game_cfg: IDZConfig,
|
||||
keys: List[IDZKey],
|
||||
handlers: List[Dict],
|
||||
) -> None:
|
||||
self.core_config = cfg
|
||||
self.game_config = game_cfg
|
||||
self.keys = keys
|
||||
self.handlers = handlers
|
||||
|
||||
def buildProtocol(self, addr):
|
||||
return IDZUserDBProtocol(self.core_config, self.game_config, self.keys, self.handlers)
|
||||
return IDZUserDBProtocol(
|
||||
self.core_config, self.game_config, self.keys, self.handlers
|
||||
)
|
||||
|
||||
|
||||
class IDZUserDBWeb(resource.Resource):
|
||||
def __init__(self, core_cfg: CoreConfig, game_cfg: IDZConfig):
|
||||
@@ -151,12 +180,16 @@ class IDZUserDBWeb(resource.Resource):
|
||||
self.isLeaf = True
|
||||
self.core_config = core_cfg
|
||||
self.game_config = game_cfg
|
||||
self.logger = logging.getLogger('idz')
|
||||
self.logger = logging.getLogger("idz")
|
||||
|
||||
def render_POST(self, request: Request) -> bytes:
|
||||
self.logger.info(f"IDZUserDBWeb POST from {request.getClientAddress().host} to {request.uri} with data {request.content.getvalue()}")
|
||||
self.logger.info(
|
||||
f"IDZUserDBWeb POST from {request.getClientAddress().host} to {request.uri} with data {request.content.getvalue()}"
|
||||
)
|
||||
return b""
|
||||
|
||||
def render_GET(self, request: Request) -> bytes:
|
||||
self.logger.info(f"IDZUserDBWeb GET from {request.getClientAddress().host} to {request.uri}")
|
||||
self.logger.info(
|
||||
f"IDZUserDBWeb GET from {request.getClientAddress().host} to {request.uri}"
|
||||
)
|
||||
return b""
|
||||
+3
-1
@@ -300,7 +300,9 @@ class Mai2Base:
|
||||
):
|
||||
for fsr in upsert["userFriendSeasonRankingList"]:
|
||||
fsr["recordDate"] = (
|
||||
datetime.strptime(fsr["recordDate"], f"{Mai2Constants.DATE_TIME_FORMAT}.0"),
|
||||
datetime.strptime(
|
||||
fsr["recordDate"], f"{Mai2Constants.DATE_TIME_FORMAT}.0"
|
||||
),
|
||||
)
|
||||
self.data.item.put_friend_season_ranking(user_id, fsr)
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ class Mai2Constants:
|
||||
"maimai DX Splash PLUS",
|
||||
"maimai DX Universe",
|
||||
"maimai DX Universe PLUS",
|
||||
"maimai DX Festival"
|
||||
"maimai DX Festival",
|
||||
)
|
||||
|
||||
@classmethod
|
||||
|
||||
@@ -38,7 +38,7 @@ class Mai2Servlet:
|
||||
Mai2SplashPlus,
|
||||
Mai2Universe,
|
||||
Mai2UniversePlus,
|
||||
Mai2Festival
|
||||
Mai2Festival,
|
||||
]
|
||||
|
||||
self.logger = logging.getLogger("mai2")
|
||||
@@ -134,9 +134,7 @@ class Mai2Servlet:
|
||||
|
||||
req_data = json.loads(unzip)
|
||||
|
||||
self.logger.info(
|
||||
f"v{version} {endpoint} request from {client_ip}"
|
||||
)
|
||||
self.logger.info(f"v{version} {endpoint} request from {client_ip}")
|
||||
self.logger.debug(req_data)
|
||||
|
||||
func_to_find = "handle_" + inflection.underscore(endpoint) + "_request"
|
||||
|
||||
@@ -402,7 +402,7 @@ class Mai2ItemData(BaseData):
|
||||
if result is None:
|
||||
self.logger.warn(
|
||||
f"put_friend_season_ranking: failed to insert",
|
||||
f"friend_season_ranking! aime_id: {aime_id}"
|
||||
f"friend_season_ranking! aime_id: {aime_id}",
|
||||
)
|
||||
return None
|
||||
return result.lastrowid
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user