199 lines
6.8 KiB
Python
199 lines
6.8 KiB
Python
from bemani.backend.museca.base import MusecaBase
|
|
from bemani.common import ID
|
|
from bemani.protocol import Node
|
|
|
|
|
|
class MusecaGameShopHandler(MusecaBase):
|
|
def handle_game_3_shop_request(self, request: Node) -> Node:
|
|
self.update_machine_name(request.child_value("shopname"))
|
|
|
|
# Respond with number of milliseconds until next request
|
|
game = Node.void("game_3")
|
|
game.add_child(Node.u32("nxt_time", 1000 * 5 * 60))
|
|
return game
|
|
|
|
|
|
class MusecaGameHiscoreHandler(MusecaBase):
|
|
def handle_game_3_hiscore_request(self, request: Node) -> Node:
|
|
# Grab location for local scores
|
|
locid = ID.parse_machine_id(request.child_value("locid"))
|
|
|
|
# Start the response packet
|
|
game = Node.void("game_3")
|
|
|
|
# First, grab hit chart
|
|
playcounts = self.data.local.music.get_hit_chart(self.game, self.version, 1024)
|
|
|
|
hitchart = Node.void("hitchart")
|
|
game.add_child(hitchart)
|
|
for songid, count in playcounts:
|
|
info = Node.void("info")
|
|
hitchart.add_child(info)
|
|
info.add_child(Node.u32("id", songid))
|
|
info.add_child(Node.u32("cnt", count))
|
|
|
|
# Now, grab user records
|
|
records = self.data.remote.music.get_all_records(self.game, self.version)
|
|
users = {
|
|
uid: prof for (uid, prof) in self.get_any_profiles([r[0] for r in records])
|
|
}
|
|
|
|
hiscore_allover = Node.void("hiscore_allover")
|
|
game.add_child(hiscore_allover)
|
|
|
|
# Output records
|
|
for userid, score in records:
|
|
info = Node.void("info")
|
|
|
|
if userid not in users:
|
|
raise Exception("Logic error, could not find profile for user!")
|
|
profile = users[userid]
|
|
|
|
info.add_child(Node.u32("id", score.id))
|
|
info.add_child(Node.u32("type", score.chart))
|
|
info.add_child(Node.string("name", profile.get_str("name")))
|
|
info.add_child(Node.string("seq", ID.format_extid(profile.extid)))
|
|
info.add_child(Node.u32("score", score.points))
|
|
|
|
# Add to global scores
|
|
hiscore_allover.add_child(info)
|
|
|
|
# Now, grab local records
|
|
area_users = [
|
|
uid
|
|
for (uid, prof) in self.data.local.user.get_all_profiles(
|
|
self.game, self.version
|
|
)
|
|
if prof.get_int("loc", -1) == locid
|
|
]
|
|
records = self.data.local.music.get_all_records(
|
|
self.game, self.version, userlist=area_users
|
|
)
|
|
missing_players = [uid for (uid, _) in records if uid not in users]
|
|
for uid, prof in self.get_any_profiles(missing_players):
|
|
users[uid] = prof
|
|
|
|
hiscore_location = Node.void("hiscore_location")
|
|
game.add_child(hiscore_location)
|
|
|
|
# Output records
|
|
for userid, score in records:
|
|
info = Node.void("info")
|
|
|
|
if userid not in users:
|
|
raise Exception("Logic error, could not find profile for user!")
|
|
profile = users[userid]
|
|
|
|
info.add_child(Node.u32("id", score.id))
|
|
info.add_child(Node.u32("type", score.chart))
|
|
info.add_child(Node.string("name", profile.get_str("name")))
|
|
info.add_child(Node.string("seq", ID.format_extid(profile.extid)))
|
|
info.add_child(Node.u32("score", score.points))
|
|
|
|
# Add to global scores
|
|
hiscore_location.add_child(info)
|
|
|
|
# Now, grab clear rates
|
|
clear_rate = Node.void("clear_rate")
|
|
game.add_child(clear_rate)
|
|
|
|
clears = self.get_clear_rates()
|
|
for songid in clears:
|
|
for chart in clears[songid]:
|
|
if clears[songid][chart]["total"] > 0:
|
|
rate = float(clears[songid][chart]["clears"]) / float(
|
|
clears[songid][chart]["total"]
|
|
)
|
|
dnode = Node.void("d")
|
|
clear_rate.add_child(dnode)
|
|
dnode.add_child(Node.u32("id", songid))
|
|
dnode.add_child(Node.u32("type", chart))
|
|
dnode.add_child(Node.s16("cr", int(rate * 10000)))
|
|
|
|
return game
|
|
|
|
|
|
class MusecaGameFrozenHandler(MusecaBase):
|
|
def handle_game_3_frozen_request(self, request: Node) -> Node:
|
|
game = Node.void("game_3")
|
|
game.add_child(Node.u8("result", 0))
|
|
return game
|
|
|
|
|
|
class MusecaGameNewHandler(MusecaBase):
|
|
def handle_game_3_new_request(self, request: Node) -> Node:
|
|
refid = request.child_value("refid")
|
|
name = request.child_value("name")
|
|
loc = ID.parse_machine_id(request.child_value("locid"))
|
|
self.new_profile_by_refid(refid, name, loc)
|
|
|
|
root = Node.void("game_3")
|
|
return root
|
|
|
|
|
|
class MusecaGameSaveMusicHandler(MusecaBase):
|
|
def handle_game_3_save_m_request(self, request: Node) -> Node:
|
|
refid = request.child_value("refid")
|
|
|
|
if refid is not None:
|
|
userid = self.data.remote.user.from_refid(self.game, self.version, refid)
|
|
else:
|
|
userid = None
|
|
|
|
# Doesn't matter if userid is None here, that's an anonymous score
|
|
musicid = request.child_value("music_id")
|
|
chart = request.child_value("music_type")
|
|
points = request.child_value("score")
|
|
combo = request.child_value("max_chain")
|
|
clear_type = self.game_to_db_clear_type(request.child_value("clear_type"))
|
|
grade = self.game_to_db_grade(request.child_value("score_grade"))
|
|
stats = {
|
|
"btn_rate": request.child_value("btn_rate"),
|
|
"long_rate": request.child_value("long_rate"),
|
|
"vol_rate": request.child_value("vol_rate"),
|
|
"critical": request.child_value("critical"),
|
|
"near": request.child_value("near"),
|
|
"error": request.child_value("error"),
|
|
}
|
|
|
|
# Save the score
|
|
self.update_score(
|
|
userid,
|
|
musicid,
|
|
chart,
|
|
points,
|
|
clear_type,
|
|
grade,
|
|
combo,
|
|
stats,
|
|
)
|
|
|
|
# Return a blank response
|
|
return Node.void("game_3")
|
|
|
|
|
|
class MusecaGamePlayEndHandler(MusecaBase):
|
|
def handle_game_3_play_e_request(self, request: Node) -> Node:
|
|
return Node.void("game_3")
|
|
|
|
|
|
class MusecaGameSaveHandler(MusecaBase):
|
|
def handle_game_3_save_request(self, request: Node) -> Node:
|
|
refid = request.child_value("refid")
|
|
|
|
if refid is not None:
|
|
userid = self.data.remote.user.from_refid(self.game, self.version, refid)
|
|
else:
|
|
userid = None
|
|
|
|
if userid is not None:
|
|
oldprofile = self.get_profile(userid)
|
|
newprofile = self.unformat_profile(userid, request, oldprofile)
|
|
else:
|
|
newprofile = None
|
|
|
|
if userid is not None and newprofile is not None:
|
|
self.put_profile(userid, newprofile)
|
|
|
|
return Node.void("game_3")
|