mirror of
https://github.com/drmext/MonkeyBusiness.git
synced 2024-11-27 17:00:59 +01:00
Fix
This commit is contained in:
parent
4068f71e48
commit
2ea73c1006
@ -51,7 +51,9 @@ async def core_get_game_version_from_software_version(software_version):
|
|||||||
ext = int(ext)
|
ext = int(ext)
|
||||||
|
|
||||||
if model == "LDJ":
|
if model == "LDJ":
|
||||||
if ext >= 2023101800:
|
if ext >= 2024100900:
|
||||||
|
return 32
|
||||||
|
elif ext >= 2023101800:
|
||||||
return 31
|
return 31
|
||||||
elif ext >= 2022101700:
|
elif ext >= 2022101700:
|
||||||
return 30
|
return 30
|
||||||
|
144
modules/iidx/iidx32gamesystem.py
Normal file
144
modules/iidx/iidx32gamesystem.py
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
from time import time
|
||||||
|
|
||||||
|
import config
|
||||||
|
|
||||||
|
from fastapi import APIRouter, Request, Response
|
||||||
|
|
||||||
|
from core_common import core_process_request, core_prepare_response, E
|
||||||
|
|
||||||
|
router = APIRouter(prefix="/local", tags=["local"])
|
||||||
|
router.model_whitelist = ["LDJ"]
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/{gameinfo}/IIDX32gameSystem/systemInfo")
|
||||||
|
async def iidx32gamesystem_systeminfo(request: Request):
|
||||||
|
request_info = await core_process_request(request)
|
||||||
|
|
||||||
|
unlock = ()
|
||||||
|
# force unlock LM exclusives to complete unlock all songs server side
|
||||||
|
# this makes LM exclusive folder disappear, so just use hex edits
|
||||||
|
# unlock = (30106, 31084, 30077, 31085, 30107, 30028, 30076, 31083, 30098)
|
||||||
|
|
||||||
|
current_time = round(time())
|
||||||
|
|
||||||
|
response = E.response(
|
||||||
|
E.IIDX32gameSystem(
|
||||||
|
# E.option_2pp(),
|
||||||
|
*[
|
||||||
|
E.music_open(
|
||||||
|
E.music_id(mid, __type="s32"),
|
||||||
|
E.kind(0, __type="s32"),
|
||||||
|
)
|
||||||
|
for mid in unlock
|
||||||
|
],
|
||||||
|
E.grade_course(
|
||||||
|
E.play_style(0, __type="s32"),
|
||||||
|
E.grade_id(15, __type="s32"),
|
||||||
|
E.music_id_0(25090, __type="s32"),
|
||||||
|
E.class_id_0(3, __type="s32"),
|
||||||
|
E.music_id_1(23068, __type="s32"),
|
||||||
|
E.class_id_1(3, __type="s32"),
|
||||||
|
E.music_id_2(19004, __type="s32"),
|
||||||
|
E.class_id_2(3, __type="s32"),
|
||||||
|
E.music_id_3(29045, __type="s32"),
|
||||||
|
E.class_id_3(3, __type="s32"),
|
||||||
|
E.is_valid(1, __type="bool"),
|
||||||
|
),
|
||||||
|
E.grade_course(
|
||||||
|
E.play_style(0, __type="s32"),
|
||||||
|
E.grade_id(16, __type="s32"),
|
||||||
|
E.music_id_0(23005, __type="s32"),
|
||||||
|
E.class_id_0(3, __type="s32"),
|
||||||
|
E.music_id_1(27078, __type="s32"),
|
||||||
|
E.class_id_1(3, __type="s32"),
|
||||||
|
E.music_id_2(22065, __type="s32"),
|
||||||
|
E.class_id_2(3, __type="s32"),
|
||||||
|
E.music_id_3(27060, __type="s32"),
|
||||||
|
E.class_id_3(3, __type="s32"),
|
||||||
|
E.is_valid(1, __type="bool"),
|
||||||
|
),
|
||||||
|
E.grade_course(
|
||||||
|
E.play_style(0, __type="s32"),
|
||||||
|
E.grade_id(17, __type="s32"),
|
||||||
|
E.music_id_0(29007, __type="s32"),
|
||||||
|
E.class_id_0(3, __type="s32"),
|
||||||
|
E.music_id_1(26108, __type="s32"),
|
||||||
|
E.class_id_1(3, __type="s32"),
|
||||||
|
E.music_id_2(19002, __type="s32"),
|
||||||
|
E.class_id_2(3, __type="s32"),
|
||||||
|
E.music_id_3(18004, __type="s32"),
|
||||||
|
E.class_id_3(3, __type="s32"),
|
||||||
|
E.is_valid(1, __type="bool"),
|
||||||
|
),
|
||||||
|
E.grade_course(
|
||||||
|
E.play_style(0, __type="s32"),
|
||||||
|
E.grade_id(18, __type="s32"),
|
||||||
|
E.music_id_0(25007, __type="s32"),
|
||||||
|
E.class_id_0(3, __type="s32"),
|
||||||
|
E.music_id_1(18032, __type="s32"),
|
||||||
|
E.class_id_1(3, __type="s32"),
|
||||||
|
E.music_id_2(16020, __type="s32"),
|
||||||
|
E.class_id_2(3, __type="s32"),
|
||||||
|
E.music_id_3(12004, __type="s32"),
|
||||||
|
E.class_id_3(3, __type="s32"),
|
||||||
|
E.is_valid(1, __type="bool"),
|
||||||
|
),
|
||||||
|
E.grade_course(
|
||||||
|
E.play_style(1, __type="s32"),
|
||||||
|
E.grade_id(15, __type="s32"),
|
||||||
|
E.music_id_0(15032, __type="s32"),
|
||||||
|
E.class_id_0(3, __type="s32"),
|
||||||
|
E.music_id_1(29033, __type="s32"),
|
||||||
|
E.class_id_1(3, __type="s32"),
|
||||||
|
E.music_id_2(27092, __type="s32"),
|
||||||
|
E.class_id_2(3, __type="s32"),
|
||||||
|
E.music_id_3(30020, __type="s32"),
|
||||||
|
E.class_id_3(3, __type="s32"),
|
||||||
|
E.is_valid(1, __type="bool"),
|
||||||
|
),
|
||||||
|
E.grade_course(
|
||||||
|
E.play_style(1, __type="s32"),
|
||||||
|
E.grade_id(16, __type="s32"),
|
||||||
|
E.music_id_0(10028, __type="s32"),
|
||||||
|
E.class_id_0(3, __type="s32"),
|
||||||
|
E.music_id_1(26070, __type="s32"),
|
||||||
|
E.class_id_1(3, __type="s32"),
|
||||||
|
E.music_id_2(28091, __type="s32"),
|
||||||
|
E.class_id_2(3, __type="s32"),
|
||||||
|
E.music_id_3(23075, __type="s32"),
|
||||||
|
E.class_id_3(3, __type="s32"),
|
||||||
|
E.is_valid(1, __type="bool"),
|
||||||
|
),
|
||||||
|
E.grade_course(
|
||||||
|
E.play_style(1, __type="s32"),
|
||||||
|
E.grade_id(17, __type="s32"),
|
||||||
|
E.music_id_0(26012, __type="s32"),
|
||||||
|
E.class_id_0(3, __type="s32"),
|
||||||
|
E.music_id_1(28002, __type="s32"),
|
||||||
|
E.class_id_1(3, __type="s32"),
|
||||||
|
E.music_id_2(17017, __type="s32"),
|
||||||
|
E.class_id_2(3, __type="s32"),
|
||||||
|
E.music_id_3(28005, __type="s32"),
|
||||||
|
E.class_id_3(3, __type="s32"),
|
||||||
|
E.is_valid(1, __type="bool"),
|
||||||
|
),
|
||||||
|
E.grade_course(
|
||||||
|
E.play_style(1, __type="s32"),
|
||||||
|
E.grade_id(18, __type="s32"),
|
||||||
|
E.music_id_0(28008, __type="s32"),
|
||||||
|
E.class_id_0(3, __type="s32"),
|
||||||
|
E.music_id_1(15001, __type="s32"),
|
||||||
|
E.class_id_1(3, __type="s32"),
|
||||||
|
E.music_id_2(19002, __type="s32"),
|
||||||
|
E.class_id_2(3, __type="s32"),
|
||||||
|
E.music_id_3(9028, __type="s32"),
|
||||||
|
E.class_id_3(3, __type="s32"),
|
||||||
|
E.is_valid(1, __type="bool"),
|
||||||
|
),
|
||||||
|
E.isNewSongAnother12OpenFlg(val=1),
|
||||||
|
E.OldBPLBattleOpenPhase(val=3),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
response_body, response_headers = await core_prepare_response(request, response)
|
||||||
|
return Response(content=response_body, headers=response_headers)
|
116
modules/iidx/iidx32grade.py
Normal file
116
modules/iidx/iidx32grade.py
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
import time
|
||||||
|
|
||||||
|
from tinydb import Query, where
|
||||||
|
|
||||||
|
from fastapi import APIRouter, Request, Response
|
||||||
|
|
||||||
|
from core_common import core_process_request, core_prepare_response, E
|
||||||
|
from core_database import get_db
|
||||||
|
|
||||||
|
router = APIRouter(prefix="/local", tags=["local"])
|
||||||
|
router.model_whitelist = ["LDJ"]
|
||||||
|
|
||||||
|
|
||||||
|
def get_profile(iidx_id):
|
||||||
|
return get_db().table("iidx_profile").get(where("iidx_id") == iidx_id)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/{gameinfo}/IIDX32grade/raised")
|
||||||
|
async def iidx32grade_raised(request: Request):
|
||||||
|
request_info = await core_process_request(request)
|
||||||
|
game_version = request_info["game_version"]
|
||||||
|
|
||||||
|
timestamp = time.time()
|
||||||
|
|
||||||
|
iidx_id = int(request_info["root"][0].attrib["iidxid"])
|
||||||
|
achi = int(request_info["root"][0].attrib["achi"])
|
||||||
|
cstage = int(request_info["root"][0].attrib["cstage"])
|
||||||
|
gid = int(request_info["root"][0].attrib["gid"])
|
||||||
|
gtype = int(request_info["root"][0].attrib["gtype"])
|
||||||
|
is_ex = int(request_info["root"][0].attrib["is_ex"])
|
||||||
|
is_mirror = int(request_info["root"][0].attrib["is_mirror"])
|
||||||
|
|
||||||
|
db = get_db()
|
||||||
|
db.table("iidx_class").insert(
|
||||||
|
{
|
||||||
|
"timestamp": timestamp,
|
||||||
|
"game_version": game_version,
|
||||||
|
"iidx_id": iidx_id,
|
||||||
|
"achi": achi,
|
||||||
|
"cstage": cstage,
|
||||||
|
"gid": gid,
|
||||||
|
"gtype": gtype,
|
||||||
|
"is_ex": is_ex,
|
||||||
|
"is_mirror": is_mirror,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
profile = get_profile(iidx_id)
|
||||||
|
game_profile = profile["version"].get(str(game_version), {})
|
||||||
|
|
||||||
|
best_class = db.table("iidx_class_best").get(
|
||||||
|
(where("iidx_id") == iidx_id)
|
||||||
|
& (where("game_version") == game_version)
|
||||||
|
& (where("gid") == gid)
|
||||||
|
& (where("gtype") == gtype)
|
||||||
|
)
|
||||||
|
|
||||||
|
best_class = {} if best_class is None else best_class
|
||||||
|
|
||||||
|
best_class_data = {
|
||||||
|
"game_version": game_version,
|
||||||
|
"iidx_id": iidx_id,
|
||||||
|
"achi": max(achi, best_class.get("achi", achi)),
|
||||||
|
"cstage": max(cstage, best_class.get("cstage", cstage)),
|
||||||
|
"gid": gid,
|
||||||
|
"gtype": gtype,
|
||||||
|
"is_ex": is_ex,
|
||||||
|
"is_mirror": is_mirror,
|
||||||
|
}
|
||||||
|
|
||||||
|
db.table("iidx_class_best").upsert(
|
||||||
|
best_class_data,
|
||||||
|
(where("iidx_id") == iidx_id)
|
||||||
|
& (where("game_version") == game_version)
|
||||||
|
& (where("gid") == gid)
|
||||||
|
& (where("gtype") == gtype),
|
||||||
|
)
|
||||||
|
|
||||||
|
best_class_plays = db.table("iidx_class_best").search(
|
||||||
|
(where("game_version") == game_version) & (where("iidx_id") == iidx_id)
|
||||||
|
)
|
||||||
|
|
||||||
|
grades = []
|
||||||
|
for record in best_class_plays:
|
||||||
|
grades.append(
|
||||||
|
[record["gtype"], record["gid"], record["cstage"], record["achi"]]
|
||||||
|
)
|
||||||
|
|
||||||
|
game_profile["grade_values"] = grades
|
||||||
|
|
||||||
|
grade_sp = db.table("iidx_class_best").search(
|
||||||
|
(where("game_version") == game_version)
|
||||||
|
& (where("iidx_id") == iidx_id)
|
||||||
|
& (where("gtype") == 0)
|
||||||
|
& (where("cstage") == 4)
|
||||||
|
)
|
||||||
|
|
||||||
|
game_profile["grade_single"] = max([x["gid"] for x in grade_sp], default=-1)
|
||||||
|
|
||||||
|
grade_dp = db.table("iidx_class_best").search(
|
||||||
|
(where("game_version") == game_version)
|
||||||
|
& (where("iidx_id") == iidx_id)
|
||||||
|
& (where("gtype") == 1)
|
||||||
|
& (where("cstage") == 4)
|
||||||
|
)
|
||||||
|
|
||||||
|
game_profile["grade_double"] = max([x["gid"] for x in grade_dp], default=-1)
|
||||||
|
|
||||||
|
profile["version"][str(game_version)] = game_profile
|
||||||
|
|
||||||
|
db.table("iidx_profile").upsert(profile, where("game_version") == game_version)
|
||||||
|
|
||||||
|
response = E.response(E.IIDX32grade(pnum=1))
|
||||||
|
|
||||||
|
response_body, response_headers = await core_prepare_response(request, response)
|
||||||
|
return Response(content=response_body, headers=response_headers)
|
169
modules/iidx/iidx32lobby.py
Normal file
169
modules/iidx/iidx32lobby.py
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
from time import time
|
||||||
|
|
||||||
|
import config
|
||||||
|
|
||||||
|
from fastapi import APIRouter, Request, Response
|
||||||
|
|
||||||
|
from core_common import core_process_request, core_prepare_response, E
|
||||||
|
|
||||||
|
router = APIRouter(prefix="/lobby", tags=["lobby"])
|
||||||
|
router.model_whitelist = ["LDJ"]
|
||||||
|
|
||||||
|
|
||||||
|
arena_host = {}
|
||||||
|
bpl_host = {}
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/{gameinfo}/IIDX32lobby/entry")
|
||||||
|
async def iidx32lobby_entry(request: Request):
|
||||||
|
request_info = await core_process_request(request)
|
||||||
|
|
||||||
|
root = request_info["root"][0]
|
||||||
|
sp_dp = root.find("play_style").text
|
||||||
|
arena_class = root.find("arena_class").text
|
||||||
|
ga = root.find("address/ga").text.split()
|
||||||
|
gp = root.find("address/gp").text
|
||||||
|
la = root.find("address/la").text.split()
|
||||||
|
|
||||||
|
if arena_host and time() < arena_host["time"]:
|
||||||
|
# test menu reset
|
||||||
|
if arena_host["ga"] == ga:
|
||||||
|
is_arena_host = 1
|
||||||
|
arena_host["time"] = time() + 30
|
||||||
|
else:
|
||||||
|
is_arena_host = 0
|
||||||
|
response = E.response(
|
||||||
|
E.IIDX32lobby(
|
||||||
|
E.host(is_arena_host, __type="bool"),
|
||||||
|
E.matching_class(arena_class, __type="s32"),
|
||||||
|
E.address(
|
||||||
|
E.ga(arena_host["ga"], __type="u8"),
|
||||||
|
E.gp(arena_host["gp"], __type="u16"),
|
||||||
|
E.la(arena_host["la"], __type="u8"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
arena_host["ga"] = ga
|
||||||
|
arena_host["gp"] = gp
|
||||||
|
arena_host["la"] = la
|
||||||
|
arena_host["time"] = time() + 30
|
||||||
|
response = E.response(
|
||||||
|
E.IIDX32lobby(
|
||||||
|
E.host(1, __type="bool"),
|
||||||
|
E.matching_class(arena_class, __type="s32"),
|
||||||
|
E.address(
|
||||||
|
E.ga(ga, __type="u8"),
|
||||||
|
E.gp(gp, __type="u16"),
|
||||||
|
E.la(la, __type="u8"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
response_body, response_headers = await core_prepare_response(request, response)
|
||||||
|
return Response(content=response_body, headers=response_headers)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/{gameinfo}/IIDX32lobby/update")
|
||||||
|
async def iidx32lobby_update(request: Request):
|
||||||
|
request_info = await core_process_request(request)
|
||||||
|
|
||||||
|
response = E.response(E.IIDX32lobby())
|
||||||
|
|
||||||
|
response_body, response_headers = await core_prepare_response(request, response)
|
||||||
|
return Response(content=response_body, headers=response_headers)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/{gameinfo}/IIDX32lobby/delete")
|
||||||
|
async def iidx32lobby_delete(request: Request):
|
||||||
|
request_info = await core_process_request(request)
|
||||||
|
|
||||||
|
# normal reset
|
||||||
|
del arena_host["ga"]
|
||||||
|
del arena_host["gp"]
|
||||||
|
del arena_host["la"]
|
||||||
|
del arena_host["time"]
|
||||||
|
response = E.response(E.IIDX32lobby())
|
||||||
|
|
||||||
|
response_body, response_headers = await core_prepare_response(request, response)
|
||||||
|
return Response(content=response_body, headers=response_headers)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/{gameinfo}/IIDX32lobby/bplbattle_entry")
|
||||||
|
async def iidx32lobby_bplbattle_entry(request: Request):
|
||||||
|
request_info = await core_process_request(request)
|
||||||
|
|
||||||
|
root = request_info["root"][0]
|
||||||
|
sp_dp = root.find("play_style").text
|
||||||
|
arena_class = root.find("arena_class").text
|
||||||
|
password = root.find("passward").text # passward
|
||||||
|
ga = root.find("address/ga").text.split()
|
||||||
|
gp = root.find("address/gp").text
|
||||||
|
la = root.find("address/la").text.split()
|
||||||
|
|
||||||
|
if bpl_host and password in bpl_host and time() < bpl_host[password]["time"]:
|
||||||
|
# test menu reset
|
||||||
|
if bpl_host[password]["ga"] == ga:
|
||||||
|
is_bpl_host = 1
|
||||||
|
bpl_host[password]["time"] = time() + 30
|
||||||
|
else:
|
||||||
|
is_bpl_host = 0
|
||||||
|
response = E.response(
|
||||||
|
E.IIDX32lobby(
|
||||||
|
E.host(is_bpl_host, __type="bool"),
|
||||||
|
E.matching_class(arena_class, __type="s32"),
|
||||||
|
E.address(
|
||||||
|
E.ga(bpl_host[password]["ga"], __type="u8"),
|
||||||
|
E.gp(bpl_host[password]["gp"], __type="u16"),
|
||||||
|
E.la(bpl_host[password]["la"], __type="u8"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
bpl_host[password] = {}
|
||||||
|
bpl_host[password]["ga"] = ga
|
||||||
|
bpl_host[password]["gp"] = gp
|
||||||
|
bpl_host[password]["la"] = la
|
||||||
|
bpl_host[password]["time"] = time() + 30
|
||||||
|
response = E.response(
|
||||||
|
E.IIDX32lobby(
|
||||||
|
E.host(1, __type="bool"),
|
||||||
|
E.matching_class(arena_class, __type="s32"),
|
||||||
|
E.address(
|
||||||
|
E.ga(ga, __type="u8"),
|
||||||
|
E.gp(gp, __type="u16"),
|
||||||
|
E.la(la, __type="u8"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
response_body, response_headers = await core_prepare_response(request, response)
|
||||||
|
return Response(content=response_body, headers=response_headers)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/{gameinfo}/IIDX32lobby/bplbattle_update")
|
||||||
|
async def iidx32lobby_bplbattle_update(request: Request):
|
||||||
|
request_info = await core_process_request(request)
|
||||||
|
|
||||||
|
response = E.response(E.IIDX32lobby())
|
||||||
|
|
||||||
|
response_body, response_headers = await core_prepare_response(request, response)
|
||||||
|
return Response(content=response_body, headers=response_headers)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/{gameinfo}/IIDX32lobby/bplbattle_delete")
|
||||||
|
async def iidx32lobby_bplbattle_delete(request: Request):
|
||||||
|
request_info = await core_process_request(request)
|
||||||
|
|
||||||
|
root = request_info["root"][0]
|
||||||
|
ga = root.find("address/ga").text.split()
|
||||||
|
|
||||||
|
# normal reset
|
||||||
|
for host in bpl_host:
|
||||||
|
if bpl_host[host]["ga"] == ga:
|
||||||
|
del bpl_host[host]
|
||||||
|
break
|
||||||
|
response = E.response(E.IIDX32lobby())
|
||||||
|
|
||||||
|
response_body, response_headers = await core_prepare_response(request, response)
|
||||||
|
return Response(content=response_body, headers=response_headers)
|
592
modules/iidx/iidx32music.py
Normal file
592
modules/iidx/iidx32music.py
Normal file
@ -0,0 +1,592 @@
|
|||||||
|
import time
|
||||||
|
import random
|
||||||
|
from enum import IntEnum
|
||||||
|
|
||||||
|
from fastapi import APIRouter, Request, Response
|
||||||
|
from tinydb import where
|
||||||
|
|
||||||
|
from core_common import core_process_request, core_prepare_response, E
|
||||||
|
from core_database import get_db
|
||||||
|
|
||||||
|
import config
|
||||||
|
|
||||||
|
router = APIRouter(prefix="/local", tags=["local"])
|
||||||
|
router.model_whitelist = ["LDJ"]
|
||||||
|
|
||||||
|
|
||||||
|
class ClearFlags(IntEnum):
|
||||||
|
NO_PLAY = 0
|
||||||
|
FAILED = 1
|
||||||
|
ASSIST_CLEAR = 2
|
||||||
|
EASY_CLEAR = 3
|
||||||
|
CLEAR = 4
|
||||||
|
HARD_CLEAR = 5
|
||||||
|
EX_HARD_CLEAR = 6
|
||||||
|
FULL_COMBO = 7
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/{gameinfo}/IIDX32music/getrank")
|
||||||
|
async def iidx32music_getrank(request: Request):
|
||||||
|
request_info = await core_process_request(request)
|
||||||
|
game_version = request_info["game_version"]
|
||||||
|
|
||||||
|
root = request_info["root"][0]
|
||||||
|
|
||||||
|
play_style = int(root.attrib["cltype"])
|
||||||
|
|
||||||
|
requested_ids = [
|
||||||
|
int(root.get("iidxid", 0)),
|
||||||
|
int(root.get("iidxid0", 0)),
|
||||||
|
int(root.get("iidxid1", 0)),
|
||||||
|
int(root.get("iidxid2", 0)),
|
||||||
|
int(root.get("iidxid3", 0)),
|
||||||
|
int(root.get("iidxid4", 0)),
|
||||||
|
int(root.get("iidxid5", 0)),
|
||||||
|
]
|
||||||
|
|
||||||
|
all_scores = {}
|
||||||
|
db = get_db()
|
||||||
|
|
||||||
|
for rival_idx, iidxid in enumerate(requested_ids, -1):
|
||||||
|
if iidxid == 0:
|
||||||
|
continue
|
||||||
|
|
||||||
|
profile = db.table("iidx_profile").get(where("iidx_id") == iidxid)["version"][
|
||||||
|
str(game_version)
|
||||||
|
]
|
||||||
|
|
||||||
|
for record in db.table("iidx_scores_best").search(
|
||||||
|
(where("music_id") < (game_version + 1) * 1000)
|
||||||
|
& (where("play_style") == play_style)
|
||||||
|
& (where("iidx_id") == iidxid)
|
||||||
|
):
|
||||||
|
music_id = record["music_id"]
|
||||||
|
clear_flg = record["clear_flg"]
|
||||||
|
ex_score = record["ex_score"]
|
||||||
|
miss_count = record["miss_count"]
|
||||||
|
chart_id = record["chart_id"]
|
||||||
|
|
||||||
|
if (rival_idx, music_id) not in all_scores:
|
||||||
|
all_scores[rival_idx, music_id] = {
|
||||||
|
0: {"clear_flg": -1, "ex_score": -1, "miss_count": -1},
|
||||||
|
1: {"clear_flg": -1, "ex_score": -1, "miss_count": -1},
|
||||||
|
2: {"clear_flg": -1, "ex_score": -1, "miss_count": -1},
|
||||||
|
3: {"clear_flg": -1, "ex_score": -1, "miss_count": -1},
|
||||||
|
4: {"clear_flg": -1, "ex_score": -1, "miss_count": -1},
|
||||||
|
}
|
||||||
|
|
||||||
|
all_scores[rival_idx, music_id][chart_id]["clear_flg"] = clear_flg
|
||||||
|
all_scores[rival_idx, music_id][chart_id]["ex_score"] = ex_score
|
||||||
|
all_scores[rival_idx, music_id][chart_id]["miss_count"] = miss_count
|
||||||
|
|
||||||
|
names = {}
|
||||||
|
profiles = get_db().table("iidx_profile")
|
||||||
|
for p in profiles:
|
||||||
|
names[p["iidx_id"]] = {}
|
||||||
|
try:
|
||||||
|
names[p["iidx_id"]]["name"] = p["version"][str(game_version)]["djname"]
|
||||||
|
except KeyError:
|
||||||
|
names[p["iidx_id"]]["name"] = "UNK"
|
||||||
|
|
||||||
|
top_scores = {}
|
||||||
|
for record in db.table("iidx_scores_best").search(
|
||||||
|
(where("music_id") < (game_version + 1) * 1000)
|
||||||
|
& (where("play_style") == play_style)
|
||||||
|
):
|
||||||
|
music_id = record["music_id"]
|
||||||
|
ex_score = record["ex_score"]
|
||||||
|
chart_id = record["chart_id"]
|
||||||
|
iidx_id = record["iidx_id"]
|
||||||
|
|
||||||
|
if music_id not in top_scores:
|
||||||
|
top_scores[music_id] = {
|
||||||
|
0: {"djname": "", "clear_flg": -1, "ex_score": -1},
|
||||||
|
1: {"djname": "", "clear_flg": -1, "ex_score": -1},
|
||||||
|
2: {"djname": "", "clear_flg": -1, "ex_score": -1},
|
||||||
|
3: {"djname": "", "clear_flg": -1, "ex_score": -1},
|
||||||
|
4: {"djname": "", "clear_flg": -1, "ex_score": -1},
|
||||||
|
}
|
||||||
|
|
||||||
|
if ex_score > top_scores[music_id][chart_id]["ex_score"]:
|
||||||
|
top_scores[music_id][chart_id]["djname"] = names[iidx_id]["name"]
|
||||||
|
top_scores[music_id][chart_id]["clear_flg"] = 1
|
||||||
|
top_scores[music_id][chart_id]["ex_score"] = ex_score
|
||||||
|
|
||||||
|
response = E.response(
|
||||||
|
E.IIDX32music(
|
||||||
|
E.style(type=play_style),
|
||||||
|
*[
|
||||||
|
E.m(
|
||||||
|
[
|
||||||
|
i,
|
||||||
|
k,
|
||||||
|
*[all_scores[i, k][d]["clear_flg"] for d in range(5)],
|
||||||
|
*[all_scores[i, k][d]["ex_score"] for d in range(5)],
|
||||||
|
*[all_scores[i, k][d]["miss_count"] for d in range(5)],
|
||||||
|
],
|
||||||
|
__type="s16",
|
||||||
|
)
|
||||||
|
for i, k in all_scores
|
||||||
|
],
|
||||||
|
*[
|
||||||
|
E.top(
|
||||||
|
E.detail(
|
||||||
|
[
|
||||||
|
k,
|
||||||
|
*[top_scores[k][d]["clear_flg"] for d in range(5)],
|
||||||
|
*[top_scores[k][d]["ex_score"] for d in range(5)],
|
||||||
|
],
|
||||||
|
__type="s16",
|
||||||
|
),
|
||||||
|
name0=top_scores[k][0]["djname"],
|
||||||
|
name1=top_scores[k][1]["djname"],
|
||||||
|
name2=top_scores[k][2]["djname"],
|
||||||
|
name3=top_scores[k][3]["djname"],
|
||||||
|
name4=top_scores[k][4]["djname"],
|
||||||
|
)
|
||||||
|
for k in top_scores
|
||||||
|
],
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response is not None
|
||||||
|
|
||||||
|
response_body, response_headers = await core_prepare_response(request, response)
|
||||||
|
return Response(content=response_body, headers=response_headers)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/{gameinfo}/IIDX32music/crate")
|
||||||
|
async def iidx32music_crate(request: Request):
|
||||||
|
request_info = await core_process_request(request)
|
||||||
|
game_version = request_info["game_version"]
|
||||||
|
|
||||||
|
db = get_db()
|
||||||
|
all_score_stats = db.table("iidx_score_stats").search(
|
||||||
|
(where("music_id") < (game_version + 1) * 1000)
|
||||||
|
)
|
||||||
|
|
||||||
|
crate = {}
|
||||||
|
fcrate = {}
|
||||||
|
for stat in all_score_stats:
|
||||||
|
if stat["music_id"] not in crate:
|
||||||
|
crate[stat["music_id"]] = [1001] * 10
|
||||||
|
if stat["music_id"] not in fcrate:
|
||||||
|
fcrate[stat["music_id"]] = [1001] * 10
|
||||||
|
|
||||||
|
if stat["play_style"] == 1:
|
||||||
|
dp_idx = 5
|
||||||
|
else:
|
||||||
|
dp_idx = 0
|
||||||
|
|
||||||
|
crate[stat["music_id"]][stat["chart_id"] + dp_idx] = int(stat["clear_rate"])
|
||||||
|
fcrate[stat["music_id"]][stat["chart_id"] + dp_idx] = int(stat["fc_rate"])
|
||||||
|
|
||||||
|
response = E.response(
|
||||||
|
E.IIDX32music(*[E.c(crate[k] + fcrate[k], mid=k, __type="s32") for k in crate])
|
||||||
|
)
|
||||||
|
|
||||||
|
response_body, response_headers = await core_prepare_response(request, response)
|
||||||
|
return Response(content=response_body, headers=response_headers)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/{gameinfo}/IIDX32music/reg")
|
||||||
|
async def iidx32music_reg(request: Request):
|
||||||
|
request_info = await core_process_request(request)
|
||||||
|
game_version = request_info["game_version"]
|
||||||
|
|
||||||
|
timestamp = time.time()
|
||||||
|
|
||||||
|
log = request_info["root"][0].find("music_play_log")
|
||||||
|
|
||||||
|
clear_flg = int(request_info["root"][0].attrib["cflg"])
|
||||||
|
clid = int(request_info["root"][0].attrib["clid"])
|
||||||
|
is_death = int(request_info["root"][0].attrib["is_death"])
|
||||||
|
pid = int(request_info["root"][0].attrib["pid"])
|
||||||
|
|
||||||
|
play_style = int(log.attrib["play_style"])
|
||||||
|
ex_score = int(log.attrib["ex_score"])
|
||||||
|
folder_type = int(log.attrib["folder_type"])
|
||||||
|
gauge_type = int(log.attrib["gauge_type"])
|
||||||
|
graph_type = int(log.attrib["graph_type"])
|
||||||
|
great_num = int(log.attrib["great_num"])
|
||||||
|
iidx_id = int(log.attrib["iidx_id"])
|
||||||
|
miss_num = int(log.attrib["miss_num"])
|
||||||
|
mode_type = int(log.attrib["mode_type"])
|
||||||
|
music_id = int(log.attrib["music_id"])
|
||||||
|
note_id = int(log.attrib["note_id"])
|
||||||
|
option1 = int(log.attrib["option1"])
|
||||||
|
option2 = int(log.attrib["option2"])
|
||||||
|
pgreat_num = int(log.attrib["pgreat_num"])
|
||||||
|
|
||||||
|
ghost = log.find("ghost").text
|
||||||
|
ghost_gauge = log.find("ghost_gauge").text
|
||||||
|
|
||||||
|
db = get_db()
|
||||||
|
db.table("iidx_scores").insert(
|
||||||
|
{
|
||||||
|
"timestamp": timestamp,
|
||||||
|
"game_version": game_version,
|
||||||
|
"iidx_id": iidx_id,
|
||||||
|
"pid": pid,
|
||||||
|
"clear_flg": clear_flg,
|
||||||
|
"is_death": is_death,
|
||||||
|
"music_id": music_id,
|
||||||
|
"play_style": play_style,
|
||||||
|
"chart_id": note_id,
|
||||||
|
"pgreat_num": pgreat_num,
|
||||||
|
"great_num": great_num,
|
||||||
|
"ex_score": ex_score,
|
||||||
|
"miss_count": miss_num,
|
||||||
|
"folder_type": folder_type,
|
||||||
|
"gauge_type": gauge_type,
|
||||||
|
"graph_type": graph_type,
|
||||||
|
"mode_type": mode_type,
|
||||||
|
"option1": option1,
|
||||||
|
"option2": option2,
|
||||||
|
"ghost": ghost,
|
||||||
|
"ghost_gauge": ghost_gauge,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
best_score = db.table("iidx_scores_best").get(
|
||||||
|
(where("iidx_id") == iidx_id)
|
||||||
|
& (where("play_style") == play_style)
|
||||||
|
& (where("music_id") == music_id)
|
||||||
|
& (where("chart_id") == note_id)
|
||||||
|
)
|
||||||
|
best_score = {} if best_score is None else best_score
|
||||||
|
|
||||||
|
if clear_flg < ClearFlags.EASY_CLEAR:
|
||||||
|
miss_num = -1
|
||||||
|
best_miss_count = best_score.get("miss_count", miss_num)
|
||||||
|
if best_miss_count == -1:
|
||||||
|
miss_count = max(miss_num, best_miss_count)
|
||||||
|
elif clear_flg > ClearFlags.ASSIST_CLEAR:
|
||||||
|
miss_count = min(miss_num, best_miss_count)
|
||||||
|
else:
|
||||||
|
miss_count = best_miss_count
|
||||||
|
best_ex_score = best_score.get("ex_score", ex_score)
|
||||||
|
best_score_data = {
|
||||||
|
"game_version": game_version,
|
||||||
|
"iidx_id": iidx_id,
|
||||||
|
"pid": pid,
|
||||||
|
"play_style": play_style,
|
||||||
|
"music_id": music_id,
|
||||||
|
"chart_id": note_id,
|
||||||
|
"miss_count": miss_count,
|
||||||
|
"ex_score": max(ex_score, best_ex_score),
|
||||||
|
"ghost": ghost if ex_score >= best_ex_score else best_score.get("ghost", ghost),
|
||||||
|
"ghost_gauge": (
|
||||||
|
ghost_gauge
|
||||||
|
if ex_score >= best_ex_score
|
||||||
|
else best_score.get("ghost_gauge", ghost_gauge)
|
||||||
|
),
|
||||||
|
"clear_flg": max(clear_flg, best_score.get("clear_flg", clear_flg)),
|
||||||
|
"gauge_type": (
|
||||||
|
gauge_type
|
||||||
|
if ex_score >= best_ex_score
|
||||||
|
else best_score.get("gauge_type", gauge_type)
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
db.table("iidx_scores_best").upsert(
|
||||||
|
best_score_data,
|
||||||
|
(where("iidx_id") == iidx_id)
|
||||||
|
& (where("play_style") == play_style)
|
||||||
|
& (where("music_id") == music_id)
|
||||||
|
& (where("chart_id") == note_id),
|
||||||
|
)
|
||||||
|
|
||||||
|
score_stats = db.table("iidx_score_stats").get(
|
||||||
|
(where("music_id") == music_id)
|
||||||
|
& (where("play_style") == play_style)
|
||||||
|
& (where("chart_id") == note_id)
|
||||||
|
)
|
||||||
|
score_stats = {} if score_stats is None else score_stats
|
||||||
|
|
||||||
|
score_stats["game_version"] = game_version
|
||||||
|
score_stats["play_style"] = play_style
|
||||||
|
score_stats["music_id"] = music_id
|
||||||
|
score_stats["chart_id"] = note_id
|
||||||
|
score_stats["play_count"] = score_stats.get("play_count", 0) + 1
|
||||||
|
score_stats["fc_count"] = score_stats.get("fc_count", 0) + (
|
||||||
|
1 if clear_flg == ClearFlags.FULL_COMBO else 0
|
||||||
|
)
|
||||||
|
score_stats["clear_count"] = score_stats.get("clear_count", 0) + (
|
||||||
|
1 if clear_flg >= ClearFlags.EASY_CLEAR else 0
|
||||||
|
)
|
||||||
|
score_stats["fc_rate"] = int(
|
||||||
|
(score_stats["fc_count"] / score_stats["play_count"]) * 1000
|
||||||
|
)
|
||||||
|
score_stats["clear_rate"] = int(
|
||||||
|
(score_stats["clear_count"] / score_stats["play_count"]) * 1000
|
||||||
|
)
|
||||||
|
|
||||||
|
db.table("iidx_score_stats").upsert(
|
||||||
|
score_stats,
|
||||||
|
(where("music_id") == music_id)
|
||||||
|
& (where("play_style") == play_style)
|
||||||
|
& (where("chart_id") == note_id),
|
||||||
|
)
|
||||||
|
|
||||||
|
ranklist_data = []
|
||||||
|
ranklist_scores = db.table("iidx_scores_best").search(
|
||||||
|
(where("play_style") == play_style)
|
||||||
|
& (where("music_id") == music_id)
|
||||||
|
& (where("chart_id") == note_id)
|
||||||
|
)
|
||||||
|
ranklist_scores = [] if ranklist_scores is None else ranklist_scores
|
||||||
|
|
||||||
|
ranklist_scores_ranked = []
|
||||||
|
|
||||||
|
for score in ranklist_scores:
|
||||||
|
profile = db.table("iidx_profile").get(where("iidx_id") == score["iidx_id"])
|
||||||
|
|
||||||
|
if profile is None or str(game_version) not in profile["version"]:
|
||||||
|
continue
|
||||||
|
|
||||||
|
game_profile = profile["version"][str(game_version)]
|
||||||
|
|
||||||
|
ranklist_scores_ranked.append(
|
||||||
|
{
|
||||||
|
"opname": config.arcade,
|
||||||
|
"name": game_profile["djname"],
|
||||||
|
"pid": game_profile["region"],
|
||||||
|
"back": game_profile.get("back", 0),
|
||||||
|
"body": game_profile["body"],
|
||||||
|
"face": game_profile["face"],
|
||||||
|
"hair": game_profile["hair"],
|
||||||
|
"hand": game_profile["hand"],
|
||||||
|
"head": game_profile["head"],
|
||||||
|
"dgrade": game_profile["grade_double"],
|
||||||
|
"sgrade": game_profile["grade_single"],
|
||||||
|
"score": score["ex_score"],
|
||||||
|
"iidx_id": score["iidx_id"],
|
||||||
|
"clflg": score["clear_flg"],
|
||||||
|
"myFlg": score["iidx_id"] == iidx_id,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
ranklist_scores_ranked = sorted(
|
||||||
|
ranklist_scores_ranked, key=lambda x: (x["clflg"], x["score"]), reverse=True
|
||||||
|
)
|
||||||
|
|
||||||
|
myRank = 0
|
||||||
|
for rnum, score in enumerate(ranklist_scores_ranked):
|
||||||
|
r = E.data(
|
||||||
|
rnum=rnum + 1,
|
||||||
|
opname=score["opname"],
|
||||||
|
name=score["name"],
|
||||||
|
pid=score["pid"],
|
||||||
|
back=score["back"],
|
||||||
|
body=score["body"],
|
||||||
|
face=score["face"],
|
||||||
|
hair=score["hair"],
|
||||||
|
hand=score["hand"],
|
||||||
|
head=score["head"],
|
||||||
|
dgrade=score["dgrade"],
|
||||||
|
sgrade=score["sgrade"],
|
||||||
|
score=score["score"],
|
||||||
|
iidx_id=score["iidx_id"],
|
||||||
|
clflg=score["clflg"],
|
||||||
|
myFlg=score["myFlg"],
|
||||||
|
achieve=0,
|
||||||
|
)
|
||||||
|
ranklist_data.append(r)
|
||||||
|
|
||||||
|
if score["myFlg"]:
|
||||||
|
myRank = rnum + 1
|
||||||
|
|
||||||
|
response = E.response(
|
||||||
|
E.IIDX32music(
|
||||||
|
E.ranklist(*ranklist_data, total_user_num=len(ranklist_data)),
|
||||||
|
E.shopdata(rank=myRank),
|
||||||
|
clid=clid,
|
||||||
|
crate=score_stats["clear_rate"],
|
||||||
|
frate=score_stats["fc_rate"],
|
||||||
|
mid=music_id,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
response_body, response_headers = await core_prepare_response(request, response)
|
||||||
|
return Response(content=response_body, headers=response_headers)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/{gameinfo}/IIDX32music/appoint")
|
||||||
|
async def iidx32music_appoint(request: Request):
|
||||||
|
request_info = await core_process_request(request)
|
||||||
|
|
||||||
|
root = request_info["root"][0]
|
||||||
|
|
||||||
|
iidxid = int(root.attrib["iidxid"])
|
||||||
|
music_id = int(root.attrib["mid"])
|
||||||
|
chart_id = int(root.attrib["clid"])
|
||||||
|
ctype = int(root.attrib["ctype"])
|
||||||
|
subtype = root.attrib["subtype"]
|
||||||
|
|
||||||
|
db = get_db()
|
||||||
|
record = db.table("iidx_scores_best").get(
|
||||||
|
(where("iidx_id") == iidxid)
|
||||||
|
& (where("music_id") == music_id)
|
||||||
|
& (where("chart_id") == chart_id)
|
||||||
|
)
|
||||||
|
|
||||||
|
vals = []
|
||||||
|
if record is not None:
|
||||||
|
vals.append(
|
||||||
|
E.mydata(
|
||||||
|
record["ghost"],
|
||||||
|
score=record["ex_score"],
|
||||||
|
__type="bin",
|
||||||
|
__size=len(record["ghost"]) // 2,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if ctype == 1:
|
||||||
|
sdata = db.table("iidx_scores_best").get(
|
||||||
|
(where("iidx_id") == int(subtype))
|
||||||
|
& (where("music_id") == music_id)
|
||||||
|
& (where("chart_id") == chart_id)
|
||||||
|
)
|
||||||
|
elif ctype in (2, 4, 10):
|
||||||
|
sdata = {
|
||||||
|
"game_version": 29,
|
||||||
|
"ghost": "",
|
||||||
|
"ex_score": 0,
|
||||||
|
"iidx_id": 0,
|
||||||
|
"name": "",
|
||||||
|
"pid": 13,
|
||||||
|
}
|
||||||
|
|
||||||
|
for record in db.table("iidx_scores_best").search(
|
||||||
|
(where("music_id") == music_id) & (where("chart_id") == chart_id)
|
||||||
|
):
|
||||||
|
if record["ex_score"] > sdata["ex_score"]:
|
||||||
|
sdata["game_version"] = record["game_version"]
|
||||||
|
sdata["ghost"] = record["ghost"]
|
||||||
|
sdata["ex_score"] = record["ex_score"]
|
||||||
|
sdata["iidx_id"] = record["iidx_id"]
|
||||||
|
sdata["pid"] = record["pid"]
|
||||||
|
|
||||||
|
if ctype in (1, 2, 4, 10) and sdata["ex_score"] != 0:
|
||||||
|
vals.append(
|
||||||
|
E.sdata(
|
||||||
|
sdata["ghost"],
|
||||||
|
score=sdata["ex_score"],
|
||||||
|
name=db.table("iidx_profile").get(where("iidx_id") == sdata["iidx_id"])[
|
||||||
|
"version"
|
||||||
|
][str(sdata["game_version"])]["djname"],
|
||||||
|
pid=sdata["pid"],
|
||||||
|
__type="bin",
|
||||||
|
__size=len(sdata["ghost"]) // 2,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
response = E.response(E.IIDX32music(*vals))
|
||||||
|
|
||||||
|
response_body, response_headers = await core_prepare_response(request, response)
|
||||||
|
return Response(content=response_body, headers=response_headers)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/{gameinfo}/IIDX32music/arenaCPU")
|
||||||
|
async def iidx32music_arenacpu(request: Request):
|
||||||
|
request_info = await core_process_request(request)
|
||||||
|
|
||||||
|
root = request_info["root"][0]
|
||||||
|
music_list = root.findall("music_list")
|
||||||
|
music_count = len(music_list)
|
||||||
|
cpu_list = root.findall("cpu_list")
|
||||||
|
cpu_count = len(cpu_list)
|
||||||
|
|
||||||
|
cpu = {}
|
||||||
|
|
||||||
|
for music in music_list:
|
||||||
|
music_idx = int(music.find("index").text)
|
||||||
|
exscore_max = int(music.find("total_notes").text) * 2
|
||||||
|
|
||||||
|
cpu[music_idx] = {}
|
||||||
|
|
||||||
|
for bot_idx in range(cpu_count):
|
||||||
|
cpu[music_idx][bot_idx] = {}
|
||||||
|
|
||||||
|
exscore = round(exscore_max * random.uniform(0.77, 0.93))
|
||||||
|
cpu[music_idx][bot_idx]["exscore"] = exscore
|
||||||
|
|
||||||
|
ghost_len = 64
|
||||||
|
ghost_data = [0] * ghost_len
|
||||||
|
for x in range(ghost_len):
|
||||||
|
ghost_data[x] = exscore // ghost_len
|
||||||
|
if (exscore % ghost_len) > x:
|
||||||
|
ghost_data[x] += 1
|
||||||
|
|
||||||
|
cpu[music_idx][bot_idx]["ghost_data"] = ghost_data
|
||||||
|
|
||||||
|
response = E.response(
|
||||||
|
E.IIDX32music(
|
||||||
|
*[
|
||||||
|
E.cpu_score_list(
|
||||||
|
E.index(bot_idx, __type="s32"),
|
||||||
|
*[
|
||||||
|
E.score_list(
|
||||||
|
E.index(music_idx, __type="s32"),
|
||||||
|
E.score(cpu[music_idx][bot_idx]["exscore"], __type="s32"),
|
||||||
|
E.ghost(cpu[music_idx][bot_idx]["ghost_data"], __type="s8"),
|
||||||
|
E.enable_score(1, __type="bool"),
|
||||||
|
E.enable_ghost(1, __type="bool"),
|
||||||
|
E.location_id("X000000001", __type="str"),
|
||||||
|
)
|
||||||
|
for music_idx in range(music_count)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
for bot_idx in range(cpu_count)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
response_body, response_headers = await core_prepare_response(request, response)
|
||||||
|
return Response(content=response_body, headers=response_headers)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/{gameinfo}/IIDX32music/retry")
|
||||||
|
async def iidx32music_retry(request: Request):
|
||||||
|
request_info = await core_process_request(request)
|
||||||
|
|
||||||
|
response = E.response(
|
||||||
|
E.IIDX32music(
|
||||||
|
E.session(session_id=1),
|
||||||
|
status=0,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
response_body, response_headers = await core_prepare_response(request, response)
|
||||||
|
return Response(content=response_body, headers=response_headers)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/{gameinfo}/IIDX32music/play")
|
||||||
|
async def iidx32music_play(request: Request):
|
||||||
|
request_info = await core_process_request(request)
|
||||||
|
|
||||||
|
response = E.response(E.IIDX32music())
|
||||||
|
|
||||||
|
response_body, response_headers = await core_prepare_response(request, response)
|
||||||
|
return Response(content=response_body, headers=response_headers)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/{gameinfo}/IIDX32music/nosave")
|
||||||
|
async def iidx32music_nosave(request: Request):
|
||||||
|
request_info = await core_process_request(request)
|
||||||
|
|
||||||
|
response = E.response(E.IIDX32music())
|
||||||
|
|
||||||
|
response_body, response_headers = await core_prepare_response(request, response)
|
||||||
|
return Response(content=response_body, headers=response_headers)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/{gameinfo}/IIDX32music/getranksub")
|
||||||
|
async def iidx32music_getranksub(request: Request):
|
||||||
|
request_info = await core_process_request(request)
|
||||||
|
|
||||||
|
response = E.response(E.IIDX32music())
|
||||||
|
|
||||||
|
response_body, response_headers = await core_prepare_response(request, response)
|
||||||
|
return Response(content=response_body, headers=response_headers)
|
1400
modules/iidx/iidx32pc.py
Normal file
1400
modules/iidx/iidx32pc.py
Normal file
File diff suppressed because it is too large
Load Diff
18
modules/iidx/iidx32ranking.py
Normal file
18
modules/iidx/iidx32ranking.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import config
|
||||||
|
|
||||||
|
from fastapi import APIRouter, Request, Response
|
||||||
|
|
||||||
|
from core_common import core_process_request, core_prepare_response, E
|
||||||
|
|
||||||
|
router = APIRouter(prefix="/local", tags=["local"])
|
||||||
|
router.model_whitelist = ["LDJ"]
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/{gameinfo}/IIDX32ranking/getranker")
|
||||||
|
async def iidx32ranking_getranker(request: Request):
|
||||||
|
request_info = await core_process_request(request)
|
||||||
|
|
||||||
|
response = E.response(E.IIDX32ranking())
|
||||||
|
|
||||||
|
response_body, response_headers = await core_prepare_response(request, response)
|
||||||
|
return Response(content=response_body, headers=response_headers)
|
64
modules/iidx/iidx32shop.py
Normal file
64
modules/iidx/iidx32shop.py
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
import config
|
||||||
|
|
||||||
|
from fastapi import APIRouter, Request, Response
|
||||||
|
|
||||||
|
from core_common import core_process_request, core_prepare_response, E
|
||||||
|
|
||||||
|
router = APIRouter(prefix="/local", tags=["local"])
|
||||||
|
router.model_whitelist = ["LDJ"]
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/{gameinfo}/IIDX32shop/getname")
|
||||||
|
async def iidx32shop_getname(request: Request):
|
||||||
|
request_info = await core_process_request(request)
|
||||||
|
|
||||||
|
response = E.response(
|
||||||
|
E.IIDX32shop(
|
||||||
|
cls_opt=0,
|
||||||
|
opname=config.arcade,
|
||||||
|
pid=13,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
response_body, response_headers = await core_prepare_response(request, response)
|
||||||
|
return Response(content=response_body, headers=response_headers)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/{gameinfo}/IIDX32shop/getconvention")
|
||||||
|
async def iidx32shop_getconvention(request: Request):
|
||||||
|
request_info = await core_process_request(request)
|
||||||
|
|
||||||
|
response = E.response(
|
||||||
|
E.IIDX32shop(
|
||||||
|
E.valid(1, __type="bool"),
|
||||||
|
music_0=-1,
|
||||||
|
music_1=-1,
|
||||||
|
music_2=-1,
|
||||||
|
music_3=-1,
|
||||||
|
start_time=0,
|
||||||
|
end_time=0,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
response_body, response_headers = await core_prepare_response(request, response)
|
||||||
|
return Response(content=response_body, headers=response_headers)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/{gameinfo}/IIDX32shop/sentinfo")
|
||||||
|
async def iidx32shop_sentinfo(request: Request):
|
||||||
|
request_info = await core_process_request(request)
|
||||||
|
|
||||||
|
response = E.response(E.IIDX32shop())
|
||||||
|
|
||||||
|
response_body, response_headers = await core_prepare_response(request, response)
|
||||||
|
return Response(content=response_body, headers=response_headers)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/{gameinfo}/IIDX32shop/sendescapepackageinfo")
|
||||||
|
async def iidx32shop_sendescapepackageinfo(request: Request):
|
||||||
|
request_info = await core_process_request(request)
|
||||||
|
|
||||||
|
response = E.response(E.IIDX32shop(expire=1200))
|
||||||
|
|
||||||
|
response_body, response_headers = await core_prepare_response(request, response)
|
||||||
|
return Response(content=response_body, headers=response_headers)
|
28
modules/iidx/iidx32streaming.py
Normal file
28
modules/iidx/iidx32streaming.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import config
|
||||||
|
|
||||||
|
from fastapi import APIRouter, Request, Response
|
||||||
|
|
||||||
|
from core_common import core_process_request, core_prepare_response, E
|
||||||
|
|
||||||
|
router = APIRouter(prefix="/local", tags=["local"])
|
||||||
|
router.model_whitelist = ["LDJ"]
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/{gameinfo}/IIDX32streaming/common")
|
||||||
|
async def iidx32streaming_common(request: Request):
|
||||||
|
request_info = await core_process_request(request)
|
||||||
|
|
||||||
|
response = E.response(E.IIDX32streaming())
|
||||||
|
|
||||||
|
response_body, response_headers = await core_prepare_response(request, response)
|
||||||
|
return Response(content=response_body, headers=response_headers)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/{gameinfo}/IIDX32streaming/getcm")
|
||||||
|
async def iidx32streaming_getcm(request: Request):
|
||||||
|
request_info = await core_process_request(request)
|
||||||
|
|
||||||
|
response = E.response(E.IIDX32streaming())
|
||||||
|
|
||||||
|
response_body, response_headers = await core_prepare_response(request, response)
|
||||||
|
return Response(content=response_body, headers=response_headers)
|
@ -1,7 +1,6 @@
|
|||||||
import argparse
|
import argparse
|
||||||
import ctypes
|
import ctypes
|
||||||
import ujson as json
|
import json
|
||||||
import sys
|
|
||||||
import struct
|
import struct
|
||||||
|
|
||||||
|
|
||||||
@ -10,7 +9,7 @@ def read_string(infile, length, encoding="cp932"):
|
|||||||
try:
|
try:
|
||||||
return string_data.decode(encoding).strip("\0")
|
return string_data.decode(encoding).strip("\0")
|
||||||
except UnicodeDecodeError:
|
except UnicodeDecodeError:
|
||||||
# Cannot decode truncated string with half of a multibyte sequence appended (0x83)
|
# Can't decode truncated string with half multibyte sequence appended (0x83)
|
||||||
return string_data[:-1].decode(encoding).strip("\0")
|
return string_data[:-1].decode(encoding).strip("\0")
|
||||||
|
|
||||||
|
|
||||||
@ -19,13 +18,20 @@ def write_string(outfile, input, length, fill="\0", encoding="cp932"):
|
|||||||
outfile.write(string_data)
|
outfile.write(string_data)
|
||||||
|
|
||||||
if len(input) < length:
|
if len(input) < length:
|
||||||
outfile.write("".join([fill] * (length - len(string_data))).encode(encoding))
|
outfile.write("".join([fill] * (length - len(string_data))).encode("utf-8"))
|
||||||
|
|
||||||
|
|
||||||
def reader(data_ver, infile, song_count):
|
def reader(data_ver, infile, song_count):
|
||||||
song_entries = []
|
song_entries = []
|
||||||
|
|
||||||
for i in range(song_count):
|
for i in range(song_count):
|
||||||
|
if data_ver >= 32:
|
||||||
|
title = read_string(infile, 0x100, encoding="utf-16-le")
|
||||||
|
title_ascii = read_string(infile, 0x40)
|
||||||
|
genre = read_string(infile, 0x80, encoding="utf-16-le")
|
||||||
|
artist = read_string(infile, 0x100, encoding="utf-16-le")
|
||||||
|
unk_sect0 = infile.read(0x100)
|
||||||
|
else:
|
||||||
title = read_string(infile, 0x40)
|
title = read_string(infile, 0x40)
|
||||||
title_ascii = read_string(infile, 0x40)
|
title_ascii = read_string(infile, 0x40)
|
||||||
genre = read_string(infile, 0x40)
|
genre = read_string(infile, 0x40)
|
||||||
@ -38,7 +44,20 @@ def reader(data_ver, infile, song_count):
|
|||||||
texture_load,
|
texture_load,
|
||||||
texture_list,
|
texture_list,
|
||||||
) = struct.unpack("<IIIII", infile.read(20))
|
) = struct.unpack("<IIIII", infile.read(20))
|
||||||
|
if data_ver >= 32:
|
||||||
|
texture_unk = struct.unpack("<I", infile.read(4))[0]
|
||||||
font_idx, game_version = struct.unpack("<IH", infile.read(6))
|
font_idx, game_version = struct.unpack("<IH", infile.read(6))
|
||||||
|
if data_ver >= 32:
|
||||||
|
(
|
||||||
|
other_folder,
|
||||||
|
bemani_folder,
|
||||||
|
unk_folder0,
|
||||||
|
unk_folder1,
|
||||||
|
unk_folder2,
|
||||||
|
splittable_diff,
|
||||||
|
unk_folder3,
|
||||||
|
) = struct.unpack("<HHHHHHH", infile.read(14))
|
||||||
|
else:
|
||||||
other_folder, bemani_folder, splittable_diff = struct.unpack(
|
other_folder, bemani_folder, splittable_diff = struct.unpack(
|
||||||
"<HHH", infile.read(6)
|
"<HHH", infile.read(6)
|
||||||
)
|
)
|
||||||
@ -173,31 +192,44 @@ def reader(data_ver, infile, song_count):
|
|||||||
"afp_data": afp_data,
|
"afp_data": afp_data,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if data_ver >= 32:
|
||||||
# if data_ver == 80:
|
# if data_ver == 80:
|
||||||
# unk = {
|
# unk = {
|
||||||
# 'unk_sect1': unk_sect1.hex(),
|
# "unk_sect1": unk_sect1.hex(),
|
||||||
# 'unk_sect2': unk_sect2.hex(),
|
# "unk_sect2": unk_sect2.hex(),
|
||||||
# 'unk_sect3': unk_sect3.hex(),
|
# "unk_sect3": unk_sect3.hex(),
|
||||||
# 'unk_sect4': unk_sect4.hex(),
|
# "unk_sect4": unk_sect4.hex(),
|
||||||
# }
|
# }
|
||||||
# elif data_ver < 80 and data_ver >= 27:
|
unk = {
|
||||||
|
"unk_sect0": unk_sect0.hex(),
|
||||||
|
"texture_unk": texture_unk,
|
||||||
|
"unk_folder0": unk_folder0,
|
||||||
|
"unk_folder1": unk_folder1,
|
||||||
|
"unk_folder2": unk_folder2,
|
||||||
|
"unk_folder3": unk_folder3,
|
||||||
|
# "unk_sect1": unk_sect1.hex(),
|
||||||
|
# "unk_sect2": unk_sect2.hex(),
|
||||||
|
# "unk_sect3": unk_sect3.hex(),
|
||||||
|
# "unk_sect4": unk_sect4.hex(),
|
||||||
|
}
|
||||||
|
# elif data_ver >= 27:
|
||||||
# unk = {
|
# unk = {
|
||||||
# 'unk_sect1': unk_sect1.hex(),
|
# "unk_sect1": unk_sect1.hex(),
|
||||||
# 'unk_sect4': unk_sect4.hex(),
|
# "unk_sect4": unk_sect4.hex(),
|
||||||
# }
|
# }
|
||||||
# elif data_ver == 26:
|
# elif data_ver == 26:
|
||||||
# unk = {
|
# unk = {
|
||||||
# 'unk_sect1': unk_sect1.hex(),
|
# "unk_sect1": unk_sect1.hex(),
|
||||||
# 'unk_sect2': unk_sect2.hex(),
|
# "unk_sect2": unk_sect2.hex(),
|
||||||
# 'unk_sect4': unk_sect4.hex(),
|
# "unk_sect4": unk_sect4.hex(),
|
||||||
# }
|
# }
|
||||||
# elif data_ver <= 25:
|
# elif data_ver <= 25:
|
||||||
# unk = {
|
# unk = {
|
||||||
# 'unk_sect1': unk_sect1.hex(),
|
# "unk_sect1": unk_sect1.hex(),
|
||||||
# 'unk_sect2': unk_sect2.hex(),
|
# "unk_sect2": unk_sect2.hex(),
|
||||||
# }
|
# }
|
||||||
#
|
|
||||||
# entries.update(unk)
|
entries.update(unk)
|
||||||
|
|
||||||
song_entries.append(entries)
|
song_entries.append(entries)
|
||||||
|
|
||||||
@ -211,7 +243,7 @@ def writer(data_ver, outfile, data):
|
|||||||
|
|
||||||
# Write header
|
# Write header
|
||||||
outfile.write(b"IIDX")
|
outfile.write(b"IIDX")
|
||||||
if data_ver == 80:
|
if data_ver >= 32:
|
||||||
outfile.write(struct.pack("<IHHI", DATA_VERSION, len(data), 0, MAX_ENTRIES))
|
outfile.write(struct.pack("<IHHI", DATA_VERSION, len(data), 0, MAX_ENTRIES))
|
||||||
else:
|
else:
|
||||||
outfile.write(struct.pack("<IHHI", DATA_VERSION, len(data), MAX_ENTRIES, 0))
|
outfile.write(struct.pack("<IHHI", DATA_VERSION, len(data), MAX_ENTRIES, 0))
|
||||||
@ -222,19 +254,35 @@ def writer(data_ver, outfile, data):
|
|||||||
exist_ids[data[i]["song_id"]] = i
|
exist_ids[data[i]["song_id"]] = i
|
||||||
|
|
||||||
cur_song = 0
|
cur_song = 0
|
||||||
|
entries_struct_format = "<i" if data_ver >= 32 else "<h"
|
||||||
|
|
||||||
for i in range(MAX_ENTRIES):
|
for i in range(MAX_ENTRIES):
|
||||||
if i in exist_ids:
|
if i in exist_ids:
|
||||||
outfile.write(struct.pack("<H", cur_song))
|
outfile.write(struct.pack(entries_struct_format, cur_song))
|
||||||
cur_song += 1
|
cur_song += 1
|
||||||
elif i >= CUR_STYLE_ENTRIES:
|
elif i >= CUR_STYLE_ENTRIES:
|
||||||
outfile.write(struct.pack("<H", 0x0000))
|
outfile.write(struct.pack(entries_struct_format, 0))
|
||||||
else:
|
else:
|
||||||
outfile.write(struct.pack("<H", 0xFFFF))
|
outfile.write(struct.pack(entries_struct_format, -1))
|
||||||
|
|
||||||
# Write song entries
|
# Write song entries
|
||||||
for k in sorted(exist_ids.keys()):
|
for k in sorted(exist_ids.keys()):
|
||||||
song_data = data[exist_ids[k]]
|
song_data = data[exist_ids[k]]
|
||||||
|
|
||||||
|
if data_ver >= 32:
|
||||||
|
write_string(outfile, song_data["title"], 0x100, encoding="utf-16-le")
|
||||||
|
write_string(outfile, song_data["title_ascii"], 0x40)
|
||||||
|
write_string(outfile, song_data["genre"], 0x80, encoding="utf-16-le")
|
||||||
|
write_string(outfile, song_data["artist"], 0x100, encoding="utf-16-le")
|
||||||
|
outfile.write(
|
||||||
|
bytes.fromhex(
|
||||||
|
song_data.get(
|
||||||
|
"unk_sect0",
|
||||||
|
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
write_string(outfile, song_data["title"], 0x40)
|
write_string(outfile, song_data["title"], 0x40)
|
||||||
write_string(outfile, song_data["title_ascii"], 0x40)
|
write_string(outfile, song_data["title_ascii"], 0x40)
|
||||||
write_string(outfile, song_data["genre"], 0x40)
|
write_string(outfile, song_data["genre"], 0x40)
|
||||||
@ -250,9 +298,25 @@ def writer(data_ver, outfile, data):
|
|||||||
song_data["texture_list"],
|
song_data["texture_list"],
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
if data_ver >= 32:
|
||||||
|
outfile.write(struct.pack("<I", song_data.get("texture_unk", 0)))
|
||||||
outfile.write(
|
outfile.write(
|
||||||
struct.pack("<IH", song_data["font_idx"], song_data["game_version"])
|
struct.pack("<IH", song_data["font_idx"], song_data["game_version"])
|
||||||
)
|
)
|
||||||
|
if data_ver >= 32:
|
||||||
|
outfile.write(
|
||||||
|
struct.pack(
|
||||||
|
"<HHHHHHH",
|
||||||
|
song_data["other_folder"],
|
||||||
|
song_data["bemani_folder"],
|
||||||
|
song_data.get("unk_folder0", 0),
|
||||||
|
song_data.get("unk_folder1", 0),
|
||||||
|
song_data.get("unk_folder2", 0),
|
||||||
|
song_data["splittable_diff"],
|
||||||
|
song_data.get("unk_folder3", 0),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
outfile.write(
|
outfile.write(
|
||||||
struct.pack(
|
struct.pack(
|
||||||
"<HHH",
|
"<HHH",
|
||||||
@ -299,6 +363,12 @@ def writer(data_ver, outfile, data):
|
|||||||
"0000000000000100000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
|
"0000000000000100000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
elif data_ver >= 32:
|
||||||
|
outfile.write(
|
||||||
|
bytes.fromhex(
|
||||||
|
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||||
|
)
|
||||||
|
)
|
||||||
elif data_ver >= 27:
|
elif data_ver >= 27:
|
||||||
outfile.write(
|
outfile.write(
|
||||||
bytes.fromhex(
|
bytes.fromhex(
|
||||||
@ -454,36 +524,21 @@ def course_writer(outfile, data, data_ver):
|
|||||||
outfile.write(struct.pack("<I", 0xFFFFFFFF))
|
outfile.write(struct.pack("<I", 0xFFFFFFFF))
|
||||||
|
|
||||||
|
|
||||||
read_handlers = {
|
handlers = {
|
||||||
0x14, # TRICORO
|
20, # TRICORO
|
||||||
0x15, # SPADA
|
21, # SPADA
|
||||||
0x16, # PENDUAL
|
22, # PENDUAL
|
||||||
0x17, # COPULA
|
23, # COPULA
|
||||||
0x18, # SINOBUZ
|
24, # SINOBUZ
|
||||||
0x19, # CANNON BALLERS
|
25, # CANNON BALLERS
|
||||||
0x1A, # ROOTAGE
|
26, # ROOTAGE
|
||||||
0x1B, # HEROIC VERSE
|
27, # HEROIC VERSE
|
||||||
0x1C, # BISTROVER
|
28, # BISTROVER
|
||||||
0x1D, # CASTHOUR
|
29, # CASTHOUR
|
||||||
0x1E, # RESIDENT
|
30, # RESIDENT
|
||||||
0x1F, # ???
|
31, # EPOLIS
|
||||||
0x50, # INFINITAS
|
32, # PINKY CRUSH
|
||||||
}
|
80, # INFINITAS
|
||||||
|
|
||||||
write_handlers = {
|
|
||||||
0x14, # TRICORO
|
|
||||||
0x15, # SPADA
|
|
||||||
0x16, # PENDUAL
|
|
||||||
0x17, # COPULA
|
|
||||||
0x18, # SINOBUZ
|
|
||||||
0x19, # CANNON BALLERS
|
|
||||||
0x1A, # ROOTAGE
|
|
||||||
0x1B, # HEROIC VERSE
|
|
||||||
0x1C, # BISTROVER
|
|
||||||
0x1D, # CASTHOUR
|
|
||||||
0x1E, # RESIDENT
|
|
||||||
0x1F, # ???
|
|
||||||
0x50, # INFINITAS
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -496,7 +551,7 @@ def extract_file(input, output, in_memory=False):
|
|||||||
infile.seek(4, 0)
|
infile.seek(4, 0)
|
||||||
data_ver = int.from_bytes(infile.read(4), "little")
|
data_ver = int.from_bytes(infile.read(4), "little")
|
||||||
|
|
||||||
if data_ver == 80:
|
if data_ver >= 32:
|
||||||
available_entries, unk4, total_entries = struct.unpack(
|
available_entries, unk4, total_entries = struct.unpack(
|
||||||
"<HHI", infile.read(8)
|
"<HHI", infile.read(8)
|
||||||
)
|
)
|
||||||
@ -507,12 +562,19 @@ def extract_file(input, output, in_memory=False):
|
|||||||
|
|
||||||
song_ids = {}
|
song_ids = {}
|
||||||
for i in range(total_entries):
|
for i in range(total_entries):
|
||||||
|
if data_ver >= 32:
|
||||||
|
song_id = struct.unpack("<I", infile.read(4))[0]
|
||||||
|
else:
|
||||||
song_id = struct.unpack("<H", infile.read(2))[0]
|
song_id = struct.unpack("<H", infile.read(2))[0]
|
||||||
|
|
||||||
if song_id != 0xFFFF and (len(song_ids) == 0 or song_id != 0):
|
if (
|
||||||
|
song_id != 0xFFFF
|
||||||
|
or song_id != 0xFFFFFFFF
|
||||||
|
and (len(song_ids) == 0 or song_id != 0)
|
||||||
|
):
|
||||||
song_ids[i] = song_id
|
song_ids[i] = song_id
|
||||||
|
|
||||||
if data_ver in read_handlers:
|
if data_ver in handlers:
|
||||||
output_data = reader(data_ver, infile, available_entries)
|
output_data = reader(data_ver, infile, available_entries)
|
||||||
output_data = {
|
output_data = {
|
||||||
"data_ver": data_ver,
|
"data_ver": data_ver,
|
||||||
@ -527,7 +589,6 @@ def extract_file(input, output, in_memory=False):
|
|||||||
open(output, "w", encoding="utf8"),
|
open(output, "w", encoding="utf8"),
|
||||||
indent=4,
|
indent=4,
|
||||||
ensure_ascii=False,
|
ensure_ascii=False,
|
||||||
escape_forward_slashes=False,
|
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
print("Couldn't find a handler for this data version")
|
print("Couldn't find a handler for this data version")
|
||||||
@ -544,7 +605,7 @@ def create_file(input, output, data_version):
|
|||||||
print("Couldn't find data version")
|
print("Couldn't find data version")
|
||||||
exit(-1)
|
exit(-1)
|
||||||
|
|
||||||
if data_ver in write_handlers:
|
if data_ver in handlers:
|
||||||
writer(data_ver, open(output, "wb"), data["data"])
|
writer(data_ver, open(output, "wb"), data["data"])
|
||||||
else:
|
else:
|
||||||
print("Couldn't find a handler for this data version")
|
print("Couldn't find a handler for this data version")
|
||||||
@ -568,7 +629,7 @@ def convert_file(input, output, data_version):
|
|||||||
if song_id != 0xFFFF and (len(song_ids) == 0 or song_id != 0):
|
if song_id != 0xFFFF and (len(song_ids) == 0 or song_id != 0):
|
||||||
song_ids[i] = song_id
|
song_ids[i] = song_id
|
||||||
|
|
||||||
if data_ver in read_handlers:
|
if data_ver in handlers:
|
||||||
output_data = reader(data_ver, infile, available_entries)
|
output_data = reader(data_ver, infile, available_entries)
|
||||||
writer(data_ver, open(output, "wb"), output_data)
|
writer(data_ver, open(output, "wb"), output_data)
|
||||||
else:
|
else:
|
||||||
@ -582,18 +643,33 @@ def merge_files(input, basefile, output, diff=False):
|
|||||||
print("Invalid", input)
|
print("Invalid", input)
|
||||||
exit(-1)
|
exit(-1)
|
||||||
|
|
||||||
data_ver, available_entries, total_entries, unk4 = struct.unpack(
|
infile.seek(4, 0)
|
||||||
"<IHIH", infile.read(12)
|
data_ver = int.from_bytes(infile.read(4), "little")
|
||||||
|
|
||||||
|
if data_ver >= 32:
|
||||||
|
available_entries, unk4, total_entries = struct.unpack(
|
||||||
|
"<HHI", infile.read(8)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
available_entries, total_entries, unk4 = struct.unpack(
|
||||||
|
"<HIH", infile.read(8)
|
||||||
)
|
)
|
||||||
|
|
||||||
song_ids = {}
|
song_ids = {}
|
||||||
for i in range(total_entries):
|
for i in range(total_entries):
|
||||||
|
if data_ver >= 32:
|
||||||
|
song_id = struct.unpack("<I", infile.read(4))[0]
|
||||||
|
else:
|
||||||
song_id = struct.unpack("<H", infile.read(2))[0]
|
song_id = struct.unpack("<H", infile.read(2))[0]
|
||||||
|
|
||||||
if song_id != 0xFFFF and (len(song_ids) == 0 or song_id != 0):
|
if (
|
||||||
|
song_id != 0xFFFF
|
||||||
|
or song_id != 0xFFFFFFFF
|
||||||
|
and (len(song_ids) == 0 or song_id != 0)
|
||||||
|
):
|
||||||
song_ids[i] = song_id
|
song_ids[i] = song_id
|
||||||
|
|
||||||
if data_ver in read_handlers:
|
if data_ver in handlers:
|
||||||
old_data = reader(data_ver, infile, available_entries)
|
old_data = reader(data_ver, infile, available_entries)
|
||||||
else:
|
else:
|
||||||
print("Couldn't find a handler for this input data version")
|
print("Couldn't find a handler for this input data version")
|
||||||
@ -604,18 +680,33 @@ def merge_files(input, basefile, output, diff=False):
|
|||||||
print("Invalid", basefile)
|
print("Invalid", basefile)
|
||||||
exit(-1)
|
exit(-1)
|
||||||
|
|
||||||
data_ver, available_entries, total_entries, unk4 = struct.unpack(
|
infile.seek(4, 0)
|
||||||
"<IHIH", infile.read(12)
|
data_ver = int.from_bytes(infile.read(4), "little")
|
||||||
|
|
||||||
|
if data_ver >= 32:
|
||||||
|
available_entries, unk4, total_entries = struct.unpack(
|
||||||
|
"<HHI", infile.read(8)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
available_entries, total_entries, unk4 = struct.unpack(
|
||||||
|
"<HIH", infile.read(8)
|
||||||
)
|
)
|
||||||
|
|
||||||
song_ids = {}
|
song_ids = {}
|
||||||
for i in range(total_entries):
|
for i in range(total_entries):
|
||||||
|
if data_ver >= 32:
|
||||||
|
song_id = struct.unpack("<I", infile.read(4))[0]
|
||||||
|
else:
|
||||||
song_id = struct.unpack("<H", infile.read(2))[0]
|
song_id = struct.unpack("<H", infile.read(2))[0]
|
||||||
|
|
||||||
if song_id != 0xFFFF and (len(song_ids) == 0 or song_id != 0):
|
if (
|
||||||
|
song_id != 0xFFFF
|
||||||
|
or song_id != 0xFFFFFFFF
|
||||||
|
and (len(song_ids) == 0 or song_id != 0)
|
||||||
|
):
|
||||||
song_ids[i] = song_id
|
song_ids[i] = song_id
|
||||||
|
|
||||||
if data_ver in read_handlers:
|
if data_ver in handlers:
|
||||||
new_data = reader(data_ver, infile, available_entries)
|
new_data = reader(data_ver, infile, available_entries)
|
||||||
else:
|
else:
|
||||||
print("Couldn't find a handler for this input data version")
|
print("Couldn't find a handler for this input data version")
|
||||||
@ -670,19 +761,19 @@ if __name__ == "__main__":
|
|||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
if (
|
if (
|
||||||
args.create == False
|
args.create is False
|
||||||
and args.extract == False
|
and args.extract is False
|
||||||
and args.convert == False
|
and args.convert is False
|
||||||
and args.merge == False
|
and args.merge is False
|
||||||
):
|
):
|
||||||
print("You must specify either --extract or --create or --convert or --merge")
|
print("You must specify either --extract or --create or --convert or --merge")
|
||||||
exit(-1)
|
exit(-1)
|
||||||
|
|
||||||
if args.convert == True:
|
if args.convert is True:
|
||||||
if args.data_version == None:
|
if args.data_version is None:
|
||||||
print("You must specify a target --data-version with --convert")
|
print("You must specify a target --data-version with --convert")
|
||||||
exit(-1)
|
exit(-1)
|
||||||
elif args.data_version not in write_handlers:
|
elif args.data_version not in handlers:
|
||||||
print("Don't know how to handle specified data version")
|
print("Don't know how to handle specified data version")
|
||||||
exit(-1)
|
exit(-1)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user