204 lines
6.8 KiB
Python
204 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.get_int('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.get_int('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')
|