1
0
mirror of synced 2025-02-16 10:52:34 +01:00

Clean up some typing on Tune Street, convert Fantasia to modern routing.

This commit is contained in:
Jennifer Taylor 2021-09-03 04:32:35 +00:00
parent 8fdacf017a
commit cd1ae9b2fd
2 changed files with 166 additions and 174 deletions

View File

@ -1,6 +1,6 @@
# vim: set fileencoding=utf-8
import copy
from typing import Dict, List, Optional
from typing import Dict, List
from bemani.backend.popn.base import PopnMusicBase
from bemani.backend.popn.tunestreet import PopnMusicTuneStreet
@ -43,7 +43,7 @@ class PopnMusicFantasia(PopnMusicBase):
# Maximum music ID for this game
GAME_MAX_MUSIC_ID = 1150
def previous_version(self) -> Optional[PopnMusicBase]:
def previous_version(self) -> PopnMusicBase:
return PopnMusicTuneStreet(self.data, self.config, self.model)
def __format_medal_for_score(self, score: Score) -> int:
@ -360,188 +360,176 @@ class PopnMusicFantasia(PopnMusicBase):
return newprofile
def handle_playerdata_request(self, request: Node) -> Optional[Node]:
method = request.attribute('method')
def handle_playerdata_expire_request(self, request: Node) -> Node:
return Node.void('playerdata')
if method == 'expire':
return Node.void('playerdata')
elif method == 'logout':
return Node.void('playerdata')
elif method == 'get':
modelstring = request.attribute('model')
refid = request.child_value('ref_id')
root = self.get_profile_by_refid(
refid,
self.NEW_PROFILE_ONLY if modelstring is None else self.OLD_PROFILE_ONLY,
)
if root is None:
root = Node.void('playerdata')
root.set_attribute('status', str(Status.NO_PROFILE))
return root
elif method == 'conversion':
refid = request.child_value('ref_id')
name = request.child_value('name')
chara = request.child_value('chara')
root = self.new_profile_by_refid(refid, name, chara)
if root is None:
root = Node.void('playerdata')
root.set_attribute('status', str(Status.NO_PROFILE))
return root
elif method == 'new':
refid = request.child_value('ref_id')
name = request.child_value('name')
root = self.new_profile_by_refid(refid, name)
if root is None:
root = Node.void('playerdata')
root.set_attribute('status', str(Status.NO_PROFILE))
return root
elif method == 'set':
refid = request.attribute('ref_id')
def handle_playerdata_logout_request(self, request: Node) -> Node:
return Node.void('playerdata')
def handle_playerdata_get_request(self, request: Node) -> Node:
modelstring = request.attribute('model')
refid = request.child_value('ref_id')
root = self.get_profile_by_refid(
refid,
self.NEW_PROFILE_ONLY if modelstring is None else self.OLD_PROFILE_ONLY,
)
if root is None:
root = Node.void('playerdata')
root.add_child(Node.s8('pref', -1))
if refid is None:
return root
root.set_attribute('status', str(Status.NO_PROFILE))
return root
userid = self.data.remote.user.from_refid(self.game, self.version, refid)
if userid is None:
return root
def handle_playerdata_conversion_request(self, request: Node) -> Node:
refid = request.child_value('ref_id')
name = request.child_value('name')
chara = request.child_value('chara')
root = self.new_profile_by_refid(refid, name, chara)
if root is None:
root = Node.void('playerdata')
root.set_attribute('status', str(Status.NO_PROFILE))
return root
oldprofile = self.get_profile(userid) or Profile(self.game, self.version, refid, 0)
newprofile = self.unformat_profile(userid, request, oldprofile)
def handle_playerdata_new_request(self, request: Node) -> Node:
refid = request.child_value('ref_id')
name = request.child_value('name')
root = self.new_profile_by_refid(refid, name)
if root is None:
root = Node.void('playerdata')
root.set_attribute('status', str(Status.NO_PROFILE))
return root
if newprofile is not None:
self.put_profile(userid, newprofile)
root.add_child(Node.string('name', newprofile['name']))
def handle_playerdata_set_request(self, request: Node) -> Node:
refid = request.attribute('ref_id')
root = Node.void('playerdata')
root.add_child(Node.s8('pref', -1))
if refid is None:
return root
elif method == 'friend':
refid = request.attribute('ref_id')
root = Node.void('playerdata')
userid = self.data.remote.user.from_refid(self.game, self.version, refid)
if userid is None:
return root
# Look up our own user ID based on the RefID provided.
userid = self.data.remote.user.from_refid(self.game, self.version, refid)
if userid is None:
root.set_attribute('status', str(Status.NO_PROFILE))
return root
oldprofile = self.get_profile(userid) or Profile(self.game, self.version, refid, 0)
newprofile = self.unformat_profile(userid, request, oldprofile)
# Grab the links that we care about.
links = self.data.local.user.get_links(self.game, self.version, userid)
profiles: Dict[UserID, Profile] = {}
rivals: List[Link] = []
for link in links:
if link.type != 'rival':
if newprofile is not None:
self.put_profile(userid, newprofile)
root.add_child(Node.string('name', newprofile['name']))
return root
def handle_playerdata_friend_request(self, request: Node) -> Node:
refid = request.attribute('ref_id')
root = Node.void('playerdata')
# Look up our own user ID based on the RefID provided.
userid = self.data.remote.user.from_refid(self.game, self.version, refid)
if userid is None:
root.set_attribute('status', str(Status.NO_PROFILE))
return root
# Grab the links that we care about.
links = self.data.local.user.get_links(self.game, self.version, userid)
profiles: Dict[UserID, Profile] = {}
rivals: List[Link] = []
for link in links:
if link.type != 'rival':
continue
other_profile = self.get_profile(link.other_userid)
if other_profile is None:
continue
profiles[link.other_userid] = other_profile
rivals.append(link)
for rival in links[:2]:
rivalid = rival.other_userid
rivalprofile = profiles[rivalid]
scores = self.data.remote.music.get_scores(self.game, self.version, rivalid)
# First, output general profile info.
friend = Node.void('friend')
root.add_child(friend)
# This might be for having non-active or non-confirmed friends, but setting to 0 makes the
# ranking numbers disappear and the player icon show a questionmark.
friend.add_child(Node.s8('open', 1))
# Set up some sane defaults.
friend.add_child(Node.string('name', rivalprofile.get_str('name', 'なし')))
friend.add_child(Node.string('g_pm_id', ID.format_extid(rivalprofile.extid)))
friend.add_child(Node.s16('chara', rivalprofile.get_int('chara', -1)))
# Perform hiscore/medal conversion.
hiscore_array = [0] * int((((self.GAME_MAX_MUSIC_ID * 4) * 17) + 7) / 8)
clear_medal = [0] * self.GAME_MAX_MUSIC_ID
for score in scores:
if score.id > self.GAME_MAX_MUSIC_ID:
continue
other_profile = self.get_profile(link.other_userid)
if other_profile is None:
# Skip any scores for chart types we don't support
if score.chart not in [
self.CHART_TYPE_EASY,
self.CHART_TYPE_NORMAL,
self.CHART_TYPE_HYPER,
self.CHART_TYPE_EX,
]:
continue
profiles[link.other_userid] = other_profile
rivals.append(link)
for rival in links[:2]:
rivalid = rival.other_userid
rivalprofile = profiles[rivalid]
scores = self.data.remote.music.get_scores(self.game, self.version, rivalid)
points = score.points
clear_medal[score.id] = clear_medal[score.id] | self.__format_medal_for_score(score)
# First, output general profile info.
friend = Node.void('friend')
root.add_child(friend)
hiscore_index = (score.id * 4) + {
self.CHART_TYPE_EASY: self.GAME_CHART_TYPE_EASY_POSITION,
self.CHART_TYPE_NORMAL: self.GAME_CHART_TYPE_NORMAL_POSITION,
self.CHART_TYPE_HYPER: self.GAME_CHART_TYPE_HYPER_POSITION,
self.CHART_TYPE_EX: self.GAME_CHART_TYPE_EX_POSITION,
}[score.chart]
hiscore_byte_pos = int((hiscore_index * 17) / 8)
hiscore_bit_pos = int((hiscore_index * 17) % 8)
hiscore_value = points << hiscore_bit_pos
hiscore_array[hiscore_byte_pos] = hiscore_array[hiscore_byte_pos] | (hiscore_value & 0xFF)
hiscore_array[hiscore_byte_pos + 1] = hiscore_array[hiscore_byte_pos + 1] | ((hiscore_value >> 8) & 0xFF)
hiscore_array[hiscore_byte_pos + 2] = hiscore_array[hiscore_byte_pos + 2] | ((hiscore_value >> 16) & 0xFF)
# This might be for having non-active or non-confirmed friends, but setting to 0 makes the
# ranking numbers disappear and the player icon show a questionmark.
friend.add_child(Node.s8('open', 1))
hiscore = bytes(hiscore_array)
friend.add_child(Node.u16_array('clear_medal', clear_medal))
friend.add_child(Node.binary('hiscore', hiscore))
# Set up some sane defaults.
friend.add_child(Node.string('name', rivalprofile.get_str('name', 'なし')))
friend.add_child(Node.string('g_pm_id', ID.format_extid(rivalprofile.extid)))
friend.add_child(Node.s16('chara', rivalprofile.get_int('chara', -1)))
return root
# Perform hiscore/medal conversion.
hiscore_array = [0] * int((((self.GAME_MAX_MUSIC_ID * 4) * 17) + 7) / 8)
clear_medal = [0] * self.GAME_MAX_MUSIC_ID
for score in scores:
if score.id > self.GAME_MAX_MUSIC_ID:
continue
def handle_game_get_request(self, request: Node) -> Node:
# TODO: Hook these up to config so we can change this
root = Node.void('game')
root.add_child(Node.s32('game_phase', 2))
root.add_child(Node.s32('ir_phase', 0))
root.add_child(Node.s32('event_phase', 5))
root.add_child(Node.s32('netvs_phase', 0))
root.add_child(Node.s32('card_phase', 6))
root.add_child(Node.s32('illust_phase', 2))
root.add_child(Node.s32('psp_phase', 5))
root.add_child(Node.s32('other_phase', 1))
root.add_child(Node.s32('jubeat_phase', 1))
root.add_child(Node.s32('public_phase', 3))
root.add_child(Node.s32('kac_phase', 2))
root.add_child(Node.s32('local_matching', 1))
root.add_child(Node.s32('n_matching_sec', 60))
root.add_child(Node.s32('l_matching_sec', 60))
root.add_child(Node.s32('is_check_cpu', 0))
root.add_child(Node.s32('week_no', 0))
root.add_child(Node.s32_array('ng_illust', [0] * 10))
root.add_child(Node.s16_array('sel_ranking', [-1] * 10))
root.add_child(Node.s16_array('up_ranking', [-1] * 10))
return root
# Skip any scores for chart types we don't support
if score.chart not in [
self.CHART_TYPE_EASY,
self.CHART_TYPE_NORMAL,
self.CHART_TYPE_HYPER,
self.CHART_TYPE_EX,
]:
continue
def handle_game_active_request(self, request: Node) -> Node:
# Update the name of this cab for admin purposes
self.update_machine_name(request.child_value('shop_name'))
return Node.void('game')
points = score.points
clear_medal[score.id] = clear_medal[score.id] | self.__format_medal_for_score(score)
def handle_game_taxphase_request(self, request: Node) -> Node:
return Node.void('game')
hiscore_index = (score.id * 4) + {
self.CHART_TYPE_EASY: self.GAME_CHART_TYPE_EASY_POSITION,
self.CHART_TYPE_NORMAL: self.GAME_CHART_TYPE_NORMAL_POSITION,
self.CHART_TYPE_HYPER: self.GAME_CHART_TYPE_HYPER_POSITION,
self.CHART_TYPE_EX: self.GAME_CHART_TYPE_EX_POSITION,
}[score.chart]
hiscore_byte_pos = int((hiscore_index * 17) / 8)
hiscore_bit_pos = int((hiscore_index * 17) % 8)
hiscore_value = points << hiscore_bit_pos
hiscore_array[hiscore_byte_pos] = hiscore_array[hiscore_byte_pos] | (hiscore_value & 0xFF)
hiscore_array[hiscore_byte_pos + 1] = hiscore_array[hiscore_byte_pos + 1] | ((hiscore_value >> 8) & 0xFF)
hiscore_array[hiscore_byte_pos + 2] = hiscore_array[hiscore_byte_pos + 2] | ((hiscore_value >> 16) & 0xFF)
hiscore = bytes(hiscore_array)
friend.add_child(Node.u16_array('clear_medal', clear_medal))
friend.add_child(Node.binary('hiscore', hiscore))
return root
# Invalid method
return None
def handle_game_request(self, request: Node) -> Optional[Node]:
method = request.attribute('method')
if method == 'get':
# TODO: Hook these up to config so we can change this
root = Node.void('game')
root.add_child(Node.s32('game_phase', 2))
root.add_child(Node.s32('ir_phase', 0))
root.add_child(Node.s32('event_phase', 5))
root.add_child(Node.s32('netvs_phase', 0))
root.add_child(Node.s32('card_phase', 6))
root.add_child(Node.s32('illust_phase', 2))
root.add_child(Node.s32('psp_phase', 5))
root.add_child(Node.s32('other_phase', 1))
root.add_child(Node.s32('jubeat_phase', 1))
root.add_child(Node.s32('public_phase', 3))
root.add_child(Node.s32('kac_phase', 2))
root.add_child(Node.s32('local_matching', 1))
root.add_child(Node.s32('n_matching_sec', 60))
root.add_child(Node.s32('l_matching_sec', 60))
root.add_child(Node.s32('is_check_cpu', 0))
root.add_child(Node.s32('week_no', 0))
root.add_child(Node.s32_array('ng_illust', [0] * 10))
root.add_child(Node.s16_array('sel_ranking', [-1] * 10))
root.add_child(Node.s16_array('up_ranking', [-1] * 10))
return root
if method == 'active':
# Update the name of this cab for admin purposes
self.update_machine_name(request.child_value('shop_name'))
return Node.void('game')
if method == 'taxphase':
return Node.void('game')
# Invalid method
return None
def handle_lobby_request(self, request: Node) -> Optional[Node]:
def handle_lobby_request(self, request: Node) -> Node:
# Stub out the entire lobby service
return Node.void('lobby')

View File

@ -1,6 +1,6 @@
# vim: set fileencoding=utf-8
import copy
from typing import Dict, Any, Optional
from typing import Dict, Any
from bemani.backend.popn.base import PopnMusicBase
from bemani.backend.popn.stubs import PopnMusicSengokuRetsuden
@ -57,7 +57,7 @@ class PopnMusicTuneStreet(PopnMusicBase):
# Highest song ID we can represent
GAME_MAX_MUSIC_ID = 1045
def previous_version(self) -> Optional[PopnMusicBase]:
def previous_version(self) -> PopnMusicBase:
return PopnMusicSengokuRetsuden(self.data, self.config, self.model)
@classmethod
@ -534,7 +534,7 @@ class PopnMusicTuneStreet(PopnMusicBase):
return newprofile
def handle_game_get_request(self, request: Node) -> Optional[Node]:
def handle_game_get_request(self, request: Node) -> Node:
game_config = self.get_game_config()
game_phase = game_config.get_int('game_phase')
town_phase = game_config.get_int('town_phase')
@ -553,21 +553,21 @@ class PopnMusicTuneStreet(PopnMusicBase):
root.set_attribute('netvs_phase', '0') # Net taisen mode phase, maximum 18 (no lobby support).
return root
def handle_game_active_request(self, request: Node) -> Optional[Node]:
def handle_game_active_request(self, request: Node) -> Node:
# Update the name of this cab for admin purposes
self.update_machine_name(request.attribute('shop_name'))
return Node.void('game')
def handle_game_taxphase_request(self, request: Node) -> Optional[Node]:
def handle_game_taxphase_request(self, request: Node) -> Node:
return Node.void('game')
def handle_playerdata_expire_request(self, request: Node) -> Optional[Node]:
def handle_playerdata_expire_request(self, request: Node) -> Node:
return Node.void('playerdata')
def handle_playerdata_logout_request(self, request: Node) -> Optional[Node]:
def handle_playerdata_logout_request(self, request: Node) -> Node:
return Node.void('playerdata')
def handle_playerdata_get_request(self, request: Node) -> Optional[Node]:
def handle_playerdata_get_request(self, request: Node) -> Node:
modelstring = request.attribute('model')
refid = request.attribute('ref_id')
root = self.get_profile_by_refid(
@ -579,7 +579,7 @@ class PopnMusicTuneStreet(PopnMusicBase):
root.set_attribute('status', str(Status.NO_PROFILE))
return root
def handle_playerdata_town_request(self, request: Node) -> Optional[Node]:
def handle_playerdata_town_request(self, request: Node) -> Node:
refid = request.attribute('ref_id')
root = Node.void('playerdata')
@ -619,7 +619,7 @@ class PopnMusicTuneStreet(PopnMusicBase):
return root
def handle_playerdata_new_request(self, request: Node) -> Optional[Node]:
def handle_playerdata_new_request(self, request: Node) -> Node:
refid = request.attribute('ref_id')
name = request.attribute('name')
root = self.new_profile_by_refid(refid, name)
@ -628,7 +628,7 @@ class PopnMusicTuneStreet(PopnMusicBase):
root.set_attribute('status', str(Status.NO_PROFILE))
return root
def handle_playerdata_set_request(self, request: Node) -> Optional[Node]:
def handle_playerdata_set_request(self, request: Node) -> Node:
refid = request.attribute('ref_id')
root = Node.void('playerdata')
@ -646,3 +646,7 @@ class PopnMusicTuneStreet(PopnMusicBase):
self.put_profile(userid, newprofile)
return root
def handle_lobby_request(self, request: Node) -> Node:
# Stub out the entire lobby service
return Node.void('lobby')