Convert Sunny Park to modern routing method.
This commit is contained in:
parent
cbbda0ef7f
commit
06d116007e
@ -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.fantasia import PopnMusicFantasia
|
||||
@ -43,7 +43,7 @@ class PopnMusicSunnyPark(PopnMusicBase):
|
||||
# Maximum music ID for this game
|
||||
GAME_MAX_MUSIC_ID = 1350
|
||||
|
||||
def previous_version(self) -> Optional[PopnMusicBase]:
|
||||
def previous_version(self) -> PopnMusicBase:
|
||||
return PopnMusicFantasia(self.data, self.config, self.model)
|
||||
|
||||
def __format_medal_for_score(self, score: Score) -> int:
|
||||
@ -219,7 +219,6 @@ class PopnMusicSunnyPark(PopnMusicBase):
|
||||
netvs.add_child(Node.s8_array('set_recommend', [0, 0, 0]))
|
||||
netvs.add_child(Node.u8('netvs_play_cnt', 0))
|
||||
for dialog in [0, 1, 2, 3, 4, 5]:
|
||||
# TODO: Configure this, maybe?
|
||||
netvs.add_child(Node.string('dialog', f'dialog#{dialog}'))
|
||||
|
||||
sp_data = Node.void('sp_data')
|
||||
@ -416,191 +415,179 @@ class PopnMusicSunnyPark(PopnMusicBase):
|
||||
|
||||
return newprofile
|
||||
|
||||
def handle_game_request(self, request: Node) -> Optional[Node]:
|
||||
method = request.attribute('method')
|
||||
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('ir_phase', 0))
|
||||
root.add_child(Node.s32('music_open_phase', 8))
|
||||
root.add_child(Node.s32('collabo_phase', 8))
|
||||
root.add_child(Node.s32('personal_event_phase', 10))
|
||||
root.add_child(Node.s32('shop_event_phase', 6))
|
||||
root.add_child(Node.s32('netvs_phase', 0))
|
||||
root.add_child(Node.s32('card_phase', 9))
|
||||
root.add_child(Node.s32('other_phase', 9))
|
||||
root.add_child(Node.s32('local_matching_enable', 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.s16_array('sel_ranking', [-1, -1, -1, -1, -1]))
|
||||
root.add_child(Node.s16_array('up_ranking', [-1, -1, -1, -1, -1]))
|
||||
return root
|
||||
|
||||
if method == 'get':
|
||||
# TODO: Hook these up to config so we can change this
|
||||
root = Node.void('game')
|
||||
root.add_child(Node.s32('ir_phase', 0))
|
||||
root.add_child(Node.s32('music_open_phase', 8))
|
||||
root.add_child(Node.s32('collabo_phase', 8))
|
||||
root.add_child(Node.s32('personal_event_phase', 10))
|
||||
root.add_child(Node.s32('shop_event_phase', 6))
|
||||
root.add_child(Node.s32('netvs_phase', 0))
|
||||
root.add_child(Node.s32('card_phase', 9))
|
||||
root.add_child(Node.s32('other_phase', 9))
|
||||
root.add_child(Node.s32('local_matching_enable', 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.s16_array('sel_ranking', [-1, -1, -1, -1, -1]))
|
||||
root.add_child(Node.s16_array('up_ranking', [-1, -1, -1, -1, -1]))
|
||||
return root
|
||||
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')
|
||||
|
||||
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')
|
||||
def handle_game_taxphase_request(self, request: Node) -> Node:
|
||||
return Node.void('game')
|
||||
|
||||
if method == 'taxphase':
|
||||
return Node.void('game')
|
||||
def handle_playerdata_expire_request(self, request: Node) -> Node:
|
||||
return Node.void('playerdata')
|
||||
|
||||
# Invalid method
|
||||
return None
|
||||
|
||||
def handle_playerdata_request(self, request: Node) -> Optional[Node]:
|
||||
method = request.attribute('method')
|
||||
|
||||
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)))
|
||||
|
||||
# Set up player avatar.
|
||||
avatar_dict = rivalprofile.get_dict('avatar')
|
||||
friend.add_child(Node.u8('hair', avatar_dict.get_int('hair', 0)))
|
||||
friend.add_child(Node.u8('face', avatar_dict.get_int('face', 0)))
|
||||
friend.add_child(Node.u8('body', avatar_dict.get_int('body', 0)))
|
||||
friend.add_child(Node.u8('effect', avatar_dict.get_int('effect', 0)))
|
||||
friend.add_child(Node.u8('object', avatar_dict.get_int('object', 0)))
|
||||
friend.add_child(Node.u8_array('comment', avatar_dict.get_int_array('comment', 2)))
|
||||
|
||||
# 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)
|
||||
clear_medal[score.id] = clear_medal[score.id] | self.__format_medal_for_score(score)
|
||||
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 = score.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)
|
||||
|
||||
# First, output general profile info.
|
||||
friend = Node.void('friend')
|
||||
root.add_child(friend)
|
||||
hiscore = bytes(hiscore_array)
|
||||
friend.add_child(Node.u16_array('clear_medal', clear_medal))
|
||||
friend.add_child(Node.binary('hiscore', hiscore))
|
||||
|
||||
# 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))
|
||||
return root
|
||||
|
||||
# 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)))
|
||||
|
||||
# Set up player avatar.
|
||||
avatar_dict = rivalprofile.get_dict('avatar')
|
||||
friend.add_child(Node.u8('hair', avatar_dict.get_int('hair', 0)))
|
||||
friend.add_child(Node.u8('face', avatar_dict.get_int('face', 0)))
|
||||
friend.add_child(Node.u8('body', avatar_dict.get_int('body', 0)))
|
||||
friend.add_child(Node.u8('effect', avatar_dict.get_int('effect', 0)))
|
||||
friend.add_child(Node.u8('object', avatar_dict.get_int('object', 0)))
|
||||
friend.add_child(Node.u8_array('comment', avatar_dict.get_int_array('comment', 2)))
|
||||
|
||||
# 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
|
||||
|
||||
# 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
|
||||
|
||||
clear_medal[score.id] = clear_medal[score.id] | self.__format_medal_for_score(score)
|
||||
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 = score.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_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')
|
||||
|
Loading…
Reference in New Issue
Block a user