Improve a few bits of Fantasia, including working profile conversions and displaying cards at the end of the round.
This commit is contained in:
parent
4f64cc7e08
commit
cbbda0ef7f
@ -3,7 +3,7 @@ import traceback
|
||||
from typing import Any, Dict, Iterator, List, Optional, Set, Tuple, Type
|
||||
|
||||
from bemani.common import Model, ValidatedDict, Profile, PlayStatistics, GameConstants, Time
|
||||
from bemani.data import Config, Data, UserID, RemoteUser
|
||||
from bemani.data import Config, Data, Machine, UserID, RemoteUser
|
||||
|
||||
|
||||
class ProfileCreationException(Exception):
|
||||
@ -391,18 +391,27 @@ class Base(ABC):
|
||||
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
|
||||
return machine.id
|
||||
|
||||
def get_machine(self) -> Machine:
|
||||
return self.data.local.machine.get_machine(self.config.machine.pcbid)
|
||||
|
||||
def update_machine_name(self, newname: Optional[str]) -> None:
|
||||
if newname is None:
|
||||
return
|
||||
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
|
||||
machine = self.get_machine()
|
||||
machine.name = newname
|
||||
self.data.local.machine.put_machine(machine)
|
||||
|
||||
def update_machine_data(self, newdata: Dict[str, Any]) -> None:
|
||||
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
|
||||
machine = self.get_machine()
|
||||
machine.data.update(newdata)
|
||||
self.data.local.machine.put_machine(machine)
|
||||
|
||||
def update_machine(self, newmachine: Machine) -> None:
|
||||
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
|
||||
machine.name = newmachine.name
|
||||
machine.data = newmachine.data
|
||||
self.data.local.machine.put_machine(machine)
|
||||
|
||||
def get_game_config(self) -> ValidatedDict:
|
||||
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
|
||||
if machine.arcade is not None:
|
||||
|
@ -1,6 +1,6 @@
|
||||
# vim: set fileencoding=utf-8
|
||||
import copy
|
||||
from typing import Dict, List
|
||||
from typing import Any, Dict, List
|
||||
|
||||
from bemani.backend.popn.base import PopnMusicBase
|
||||
from bemani.backend.popn.tunestreet import PopnMusicTuneStreet
|
||||
@ -46,6 +46,41 @@ class PopnMusicFantasia(PopnMusicBase):
|
||||
def previous_version(self) -> PopnMusicBase:
|
||||
return PopnMusicTuneStreet(self.data, self.config, self.model)
|
||||
|
||||
@classmethod
|
||||
def get_settings(cls) -> Dict[str, Any]:
|
||||
"""
|
||||
Return all of our front-end modifiably settings.
|
||||
"""
|
||||
return {
|
||||
'ints': [
|
||||
{
|
||||
'name': 'Game Phase',
|
||||
'tip': 'Game unlock phase for all players.',
|
||||
'category': 'game_config',
|
||||
'setting': 'game_phase',
|
||||
'values': {
|
||||
0: 'NO PHASE',
|
||||
1: 'SECRET DATA RELEASE',
|
||||
2: 'MAX: ALL DATA RELEASE',
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'Soreyuke! pop\'n quest Event Phase',
|
||||
'tip': 'Event phase for all players.',
|
||||
'category': 'game_config',
|
||||
'setting': 'event_phase',
|
||||
'values': {
|
||||
0: 'No event',
|
||||
1: 'Phase 1',
|
||||
2: 'Phase 2',
|
||||
3: 'Phase 3',
|
||||
4: 'Phase 4',
|
||||
5: 'Phase MAX',
|
||||
}
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
def __format_medal_for_score(self, score: Score) -> int:
|
||||
medal = {
|
||||
self.PLAY_MEDAL_CIRCLE_FAILED: self.GAME_PLAY_MEDAL_CIRCLE_FAILED,
|
||||
@ -109,6 +144,7 @@ class PopnMusicFantasia(PopnMusicBase):
|
||||
player_card.add_child(Node.s32('get_frame', player_card_dict.get_int('get_frame')))
|
||||
player_card.add_child(Node.s32('get_base', player_card_dict.get_int('get_base')))
|
||||
player_card.add_child(Node.s32_array('get_seal', player_card_dict.get_int_array('get_seal', 2)))
|
||||
player_card.add_child(Node.s8('is_open', 1))
|
||||
|
||||
# Player card EX section
|
||||
player_card_ex = Node.void('player_card_ex')
|
||||
@ -201,7 +237,6 @@ class PopnMusicFantasia(PopnMusicBase):
|
||||
netvs.add_child(Node.s8_array('set_recommend', [0, 0, 0]))
|
||||
netvs.add_child(Node.s8_array('jewelry', [0] * 15))
|
||||
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')
|
||||
@ -213,17 +248,18 @@ class PopnMusicFantasia(PopnMusicBase):
|
||||
reflec_data.add_child(Node.s8_array('reflec', profile.get_int_array('reflec', 2)))
|
||||
|
||||
# Navigate section
|
||||
navigate_dict = profile.get_dict('navigate')
|
||||
navigate = Node.void('navigate')
|
||||
root.add_child(navigate)
|
||||
navigate.add_child(Node.s8('genre', navigate_dict.get_int('genre')))
|
||||
navigate.add_child(Node.s8('image', navigate_dict.get_int('image')))
|
||||
navigate.add_child(Node.s8('level', navigate_dict.get_int('level')))
|
||||
navigate.add_child(Node.s8('ojama', navigate_dict.get_int('ojama')))
|
||||
navigate.add_child(Node.s16('limit_num', navigate_dict.get_int('limit_num')))
|
||||
navigate.add_child(Node.s8('button', navigate_dict.get_int('button')))
|
||||
navigate.add_child(Node.s8('life', navigate_dict.get_int('life')))
|
||||
navigate.add_child(Node.s16('progress', navigate_dict.get_int('progress')))
|
||||
for i in range(3):
|
||||
navigate_dict = profile.get_dict(f'navigate_{i}')
|
||||
navigate = Node.void('navigate')
|
||||
root.add_child(navigate)
|
||||
navigate.add_child(Node.s8('genre', navigate_dict.get_int('genre', -1)))
|
||||
navigate.add_child(Node.s8('image', navigate_dict.get_int('image', -1)))
|
||||
navigate.add_child(Node.s8('level', navigate_dict.get_int('level', -1)))
|
||||
navigate.add_child(Node.s8('ojama', navigate_dict.get_int('ojama', -1)))
|
||||
navigate.add_child(Node.s16('limit_num', navigate_dict.get_int('limit_num', -1)))
|
||||
navigate.add_child(Node.s8('button', navigate_dict.get_int('button', -1)))
|
||||
navigate.add_child(Node.s8('life', navigate_dict.get_int('life', -1)))
|
||||
navigate.add_child(Node.s16('progress', navigate_dict.get_int('progress', -1)))
|
||||
|
||||
return root
|
||||
|
||||
@ -238,6 +274,7 @@ class PopnMusicFantasia(PopnMusicBase):
|
||||
root.add_child(Node.u8('season', 0))
|
||||
|
||||
clear_medal = [0] * self.GAME_MAX_MUSIC_ID
|
||||
hiscore_array = [0] * int((((self.GAME_MAX_MUSIC_ID * 4) * 17) + 7) / 8)
|
||||
|
||||
scores = self.data.remote.music.get_scores(self.game, self.version, userid)
|
||||
for score in scores:
|
||||
@ -254,8 +291,21 @@ class PopnMusicFantasia(PopnMusicBase):
|
||||
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)
|
||||
|
||||
root.add_child(Node.u16_array('clear_medal', clear_medal))
|
||||
root.add_child(Node.binary('hiscore', bytes(hiscore_array)))
|
||||
|
||||
return root
|
||||
|
||||
@ -317,18 +367,23 @@ class PopnMusicFantasia(PopnMusicBase):
|
||||
newprofile.replace_dict('player_card', player_card_dict)
|
||||
|
||||
# Extract navigate stuff
|
||||
navigate_dict = newprofile.get_dict('navigate')
|
||||
navigate = request.child('navigate')
|
||||
if navigate is not None:
|
||||
navigate_dict.replace_int('genre', navigate.child_value('genre'))
|
||||
navigate_dict.replace_int('image', navigate.child_value('image'))
|
||||
navigate_dict.replace_int('level', navigate.child_value('level'))
|
||||
navigate_dict.replace_int('ojama', navigate.child_value('ojama'))
|
||||
navigate_dict.replace_int('limit_num', navigate.child_value('limit_num'))
|
||||
navigate_dict.replace_int('button', navigate.child_value('button'))
|
||||
navigate_dict.replace_int('life', navigate.child_value('life'))
|
||||
navigate_dict.replace_int('progress', navigate.child_value('progress'))
|
||||
newprofile.replace_dict('navigate', navigate_dict)
|
||||
nav_id = 0
|
||||
for navigate in request.children:
|
||||
if navigate.name == 'navigate':
|
||||
navigate_dict = newprofile.get_dict(f'navigate_{nav_id}')
|
||||
navigate_dict.replace_int('genre', navigate.child_value('genre'))
|
||||
navigate_dict.replace_int('image', navigate.child_value('image'))
|
||||
navigate_dict.replace_int('level', navigate.child_value('level'))
|
||||
navigate_dict.replace_int('ojama', navigate.child_value('ojama'))
|
||||
navigate_dict.replace_int('limit_num', navigate.child_value('limit_num'))
|
||||
navigate_dict.replace_int('button', navigate.child_value('button'))
|
||||
navigate_dict.replace_int('life', navigate.child_value('life'))
|
||||
navigate_dict.replace_int('progress', navigate.child_value('progress'))
|
||||
newprofile.replace_dict(f'navigate_{nav_id}', navigate_dict)
|
||||
nav_id += 1
|
||||
|
||||
if nav_id >= 3:
|
||||
break
|
||||
|
||||
# Extract scores
|
||||
for node in request.children:
|
||||
@ -397,22 +452,61 @@ class PopnMusicFantasia(PopnMusicBase):
|
||||
|
||||
def handle_playerdata_set_request(self, request: Node) -> Node:
|
||||
refid = request.attribute('ref_id')
|
||||
machine = self.get_machine()
|
||||
|
||||
root = Node.void('playerdata')
|
||||
root.add_child(Node.s8('pref', -1))
|
||||
root.add_child(Node.s8('pref', machine.data.get_int('pref', -1)))
|
||||
|
||||
if refid is None:
|
||||
root.add_child(Node.string('name', ''))
|
||||
root.add_child(Node.s16('chara', -1))
|
||||
root.add_child(Node.u8('frame', 0))
|
||||
root.add_child(Node.u8('base', 0))
|
||||
root.add_child(Node.u8('seal_1', 0))
|
||||
root.add_child(Node.u8('seal_2', 0))
|
||||
root.add_child(Node.u8('title_1', 0))
|
||||
root.add_child(Node.u8('title_2', 0))
|
||||
root.add_child(Node.s16('recommend_1', -1))
|
||||
root.add_child(Node.s16('recommend_2', -1))
|
||||
root.add_child(Node.s16('recommend_3', -1))
|
||||
root.add_child(Node.string('message', ''))
|
||||
return root
|
||||
|
||||
userid = self.data.remote.user.from_refid(self.game, self.version, refid)
|
||||
if userid is None:
|
||||
root.add_child(Node.string('name', ''))
|
||||
root.add_child(Node.s16('chara', -1))
|
||||
root.add_child(Node.u8('frame', 0))
|
||||
root.add_child(Node.u8('base', 0))
|
||||
root.add_child(Node.u8('seal_1', 0))
|
||||
root.add_child(Node.u8('seal_2', 0))
|
||||
root.add_child(Node.u8('title_1', 0))
|
||||
root.add_child(Node.u8('title_2', 0))
|
||||
root.add_child(Node.s16('recommend_1', -1))
|
||||
root.add_child(Node.s16('recommend_2', -1))
|
||||
root.add_child(Node.s16('recommend_3', -1))
|
||||
root.add_child(Node.string('message', ''))
|
||||
return root
|
||||
|
||||
oldprofile = self.get_profile(userid) or Profile(self.game, self.version, refid, 0)
|
||||
newprofile = self.unformat_profile(userid, request, oldprofile)
|
||||
|
||||
if newprofile is not None:
|
||||
player_card_dict = newprofile.get_dict('player_card')
|
||||
|
||||
self.put_profile(userid, newprofile)
|
||||
root.add_child(Node.string('name', newprofile['name']))
|
||||
root.add_child(Node.string('name', newprofile.get_str('name', 'なし')))
|
||||
root.add_child(Node.s16('chara', newprofile.get_int('chara', -1)))
|
||||
root.add_child(Node.u8('frame', player_card_dict.get_int('frame')))
|
||||
root.add_child(Node.u8('base', player_card_dict.get_int('base')))
|
||||
root.add_child(Node.u8('seal_1', player_card_dict.get_int_array('seal', 2)[0]))
|
||||
root.add_child(Node.u8('seal_2', player_card_dict.get_int_array('seal', 2)[1]))
|
||||
root.add_child(Node.u8('title_1', player_card_dict.get_int_array('title', 2, [0, 1])[0]))
|
||||
root.add_child(Node.u8('title_2', player_card_dict.get_int_array('title', 2, [0, 1])[1]))
|
||||
root.add_child(Node.s16('recommend_1', -1))
|
||||
root.add_child(Node.s16('recommend_2', -1))
|
||||
root.add_child(Node.s16('recommend_3', -1))
|
||||
root.add_child(Node.string('message', ''))
|
||||
|
||||
return root
|
||||
|
||||
@ -492,38 +586,48 @@ class PopnMusicFantasia(PopnMusicBase):
|
||||
friend.add_child(Node.u16_array('clear_medal', clear_medal))
|
||||
friend.add_child(Node.binary('hiscore', hiscore))
|
||||
|
||||
# Note that if we ever support internet ranking mode, there's an 'ir_hiscore' node here as well.
|
||||
|
||||
# Also note that if we support lobbies, there's a few extra nodes in each friend for current lobby
|
||||
# that they're in as well as previous lobby logs.
|
||||
|
||||
return root
|
||||
|
||||
def handle_game_get_request(self, request: Node) -> Node:
|
||||
# TODO: Hook these up to config so we can change this
|
||||
game_config = self.get_game_config()
|
||||
game_phase = game_config.get_int('game_phase')
|
||||
event_phase = game_config.get_int('event_phase')
|
||||
|
||||
root = Node.void('game')
|
||||
root.add_child(Node.s32('game_phase', 2))
|
||||
root.add_child(Node.s32('game_phase', game_phase))
|
||||
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('event_phase', event_phase))
|
||||
root.add_child(Node.s32('netvs_phase', 0)) # Net taisen mode, we don't support lobbies.
|
||||
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('psp_phase', 5)) # Unlock songs from Pop'n Music Portable.
|
||||
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('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.s32_array('ng_illust', [0] * 10))
|
||||
root.add_child(Node.s32('team_day', 0))
|
||||
root.add_child(Node.s32_array('ng_illust', [-1] * 64))
|
||||
root.add_child(Node.s16_array('sel_ranking', [-1] * 10))
|
||||
root.add_child(Node.s16_array('up_ranking', [-1] * 10))
|
||||
|
||||
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')
|
||||
|
||||
def handle_game_taxphase_request(self, request: Node) -> Node:
|
||||
# Update the name of this cab for admin purposes. Also store the prefecture.
|
||||
machine = self.get_machine()
|
||||
machine.name = request.child_value('shop_name') or machine.name
|
||||
machine.data.replace_int('pref', request.child_value('pref'))
|
||||
self.update_machine(machine)
|
||||
return Node.void('game')
|
||||
|
||||
def handle_lobby_request(self, request: Node) -> Node:
|
||||
|
@ -84,7 +84,7 @@ class PopnMusicFantasiaClient(BaseClient):
|
||||
'jubeat_phase',
|
||||
'public_phase',
|
||||
'kac_phase',
|
||||
'local_matching',
|
||||
'local_matching_enable',
|
||||
'n_matching_sec',
|
||||
'l_matching_sec',
|
||||
'is_check_cpu',
|
||||
@ -101,22 +101,18 @@ class PopnMusicFantasiaClient(BaseClient):
|
||||
up_ranking = resp.child('game').child('up_ranking')
|
||||
ng_illust = resp.child('game').child('ng_illust')
|
||||
|
||||
for nodepair in [
|
||||
('sel_ranking', sel_ranking, 's16'),
|
||||
('up_ranking', up_ranking, 's16'),
|
||||
('ng_illust', ng_illust, 's32'),
|
||||
for name, node, dtype, length in [
|
||||
('sel_ranking', sel_ranking, 's16', 10),
|
||||
('up_ranking', up_ranking, 's16', 10),
|
||||
('ng_illust', ng_illust, 's32', 64),
|
||||
]:
|
||||
name = nodepair[0]
|
||||
node = nodepair[1]
|
||||
dtype = nodepair[2]
|
||||
|
||||
if node is None:
|
||||
raise Exception(f'Missing node \'{name}\' in response!')
|
||||
if node.data_type != dtype:
|
||||
raise Exception(f'Node \'{name}\' has wrong data type!')
|
||||
if not node.is_array:
|
||||
raise Exception(f'Node \'{name}\' is not array!')
|
||||
if len(node.value) != 10:
|
||||
if len(node.value) != length:
|
||||
raise Exception(f'Node \'{name}\' is wrong array length!')
|
||||
|
||||
def verify_playerdata_get(self, ref_id: str, msg_type: str) -> Optional[Dict[str, Any]]:
|
||||
|
Loading…
x
Reference in New Issue
Block a user