1
0
mirror of synced 2024-11-27 23:50:47 +01:00

Use arcade/network region for default prefecture/region wherever possible, including in facility.get. Allows changing game region.

This commit is contained in:
Jennifer Taylor 2021-09-07 02:48:57 +00:00
parent d05c3f907d
commit c7affef159
24 changed files with 124 additions and 43 deletions

View File

@ -3,8 +3,8 @@ import traceback
from typing import Any, Dict, Iterator, List, Optional, Set, Tuple, Type
from typing_extensions import Final
from bemani.common import Model, ValidatedDict, Profile, PlayStatistics, GameConstants, Time
from bemani.data import Config, Data, Machine, UserID, RemoteUser
from bemani.common import Model, ValidatedDict, Profile, PlayStatistics, GameConstants, RegionConstants, Time
from bemani.data import Config, Data, Arcade, Machine, UserID, RemoteUser
class ProfileCreationException(Exception):
@ -238,6 +238,12 @@ class Base(ABC):
"""
return True
def requires_extended_regions(self) -> bool:
"""
Override this in your subclass if your game requires an updated region list.
"""
return False
def bind_profile(self, userid: UserID) -> None:
"""
Handling binding the user's profile to this version on this server.
@ -422,6 +428,19 @@ class Base(ABC):
machine.data = newmachine.data
self.data.local.machine.put_machine(machine)
def get_arcade(self) -> Optional[Arcade]:
machine = self.get_machine()
if machine.arcade is None:
return None
return self.data.local.machine.get_arcade(machine.arcade)
def get_machine_region(self) -> int:
arcade = self.get_arcade()
if arcade is None:
return RegionConstants.db_to_game_region(self.requires_extended_regions(), self.config.server.region)
else:
return RegionConstants.db_to_game_region(self.requires_extended_regions(), arcade.region)
def get_game_config(self) -> ValidatedDict:
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
if machine.arcade is not None:

View File

@ -2,7 +2,7 @@ import socket
from bemani.backend.base import Base
from bemani.protocol import Node
from bemani.common import ID
from bemani.common import ID, RegionConstants
class CoreHandler(Base):
@ -120,14 +120,58 @@ class CoreHandler(Base):
which expects to return a bunch of information about the arcade this
cabinet is in, as well as some settings for URLs and the name of the cab.
"""
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
machine = self.get_machine()
if machine.arcade is None:
region = self.config.server.region
else:
arcade = self.data.local.machine.get_arcade(machine.arcade)
region = arcade.region
if region == RegionConstants.HONG_KONG:
country = "HK"
regionstr = ""
elif region == RegionConstants.TAIWAN:
country = "TW"
regionstr = ""
elif region == RegionConstants.KOREA:
country = "KR"
regionstr = ""
elif region == RegionConstants.USA:
country = "US"
regionstr = ""
elif region == RegionConstants.THAILAND:
country = "TH"
regionstr = ""
elif region == RegionConstants.INDONESIA:
country = "ID"
regionstr = ""
elif region == RegionConstants.SINGAPORE:
country = "SG"
regionstr = ""
elif region == RegionConstants.PHILLIPINES:
country = "PH"
regionstr = ""
elif region == RegionConstants.MACAO:
country = "MO"
regionstr = ""
elif region >= RegionConstants.MIN_PREF and region <= RegionConstants.MAX_PREF:
country = "JP"
regionstr = f"JP-{region}"
elif region == RegionConstants.EUROPE:
# Pick a random country in the "Europe" category.
country = "GB"
regionstr = ""
else:
# Pick a random nonsensical code.
country = "XX"
regionstr = ""
root = Node.void('facility')
root.set_attribute('expire', '600')
location = Node.void('location')
location.add_child(Node.string('id', ID.format_machine_id(machine.id)))
location.add_child(Node.string('country', 'US'))
location.add_child(Node.string('region', '.'))
location.add_child(Node.string('id', ID.format_machine_id(machine.id, region=country)))
location.add_child(Node.string('country', country))
location.add_child(Node.string('region', regionstr))
location.add_child(Node.string('name', machine.name))
location.add_child(Node.u8('type', 0))

View File

@ -95,7 +95,7 @@ class DDRGameHiscoreHandler(DDRBase):
typenode.add_child(Node.string('name', users[userid].get_str('name')))
typenode.add_child(Node.u32('score', score.points))
typenode.add_child(Node.u16('area', users[userid].get_int('area', 51)))
typenode.add_child(Node.u16('area', users[userid].get_int('area', self.get_machine_region())))
typenode.add_child(Node.u8('rank', gamerank))
typenode.add_child(Node.u8('combo_type', combo_type))
typenode.add_child(Node.u32('code', users[userid].extid))
@ -111,7 +111,7 @@ class DDRGameAreaHiscoreHandler(DDRBase):
# First, get all users that are in the current shop's area
area_users = {
uid: prof for (uid, prof) in self.data.local.user.get_all_profiles(self.game, self.version)
if prof.get_int('area', 51) == shop_area
if prof.get_int('area', self.get_machine_region()) == shop_area
}
# Second, look up records belonging only to those users
@ -134,7 +134,7 @@ class DDRGameAreaHiscoreHandler(DDRBase):
for chart in area_records[song]:
userid, score = area_records[song][chart]
if area_users[userid].get_int('area', 51) != shop_area:
if area_users[userid].get_int('area', self.get_machine_region()) != shop_area:
# Don't return this, this user isn't in this area
continue
try:
@ -151,7 +151,7 @@ class DDRGameAreaHiscoreHandler(DDRBase):
typenode.add_child(Node.string('name', area_users[userid].get_str('name')))
typenode.add_child(Node.u32('score', score.points))
typenode.add_child(Node.u16('area', area_users[userid].get_int('area', 51)))
typenode.add_child(Node.u16('area', area_users[userid].get_int('area', self.get_machine_region())))
typenode.add_child(Node.u8('rank', gamerank))
typenode.add_child(Node.u8('combo_type', combo_type))
typenode.add_child(Node.u32('code', area_users[userid].extid))
@ -301,7 +301,7 @@ class DDRGameOldHandler(DDRBase):
oldprofile = previous_version.get_profile(userid)
if oldprofile is not None:
game.set_attribute('name', oldprofile.get_str('name'))
game.set_attribute('area', str(oldprofile.get_int('area', 51)))
game.set_attribute('area', str(oldprofile.get_int('area', self.get_machine_region())))
return game
@ -354,7 +354,7 @@ class DDRGameFriendHandler(DDRBase):
game.set_attribute('data', '1')
game.add_child(Node.u32('code', friend.extid))
game.add_child(Node.string('name', friend.get_str('name')))
game.add_child(Node.u8('area', friend.get_int('area', 51)))
game.add_child(Node.u8('area', friend.get_int('area', self.get_machine_region())))
game.add_child(Node.u32('exp', play_stats.get_int('exp')))
game.add_child(Node.u32('star', friend.get_int('star')))

View File

@ -169,7 +169,7 @@ class DDR2013(
flag.set_attribute('t', '0')
flag.set_attribute('s1', '0')
flag.set_attribute('s2', '0')
flag.set_attribute('area', '51')
flag.set_attribute('area', str(self.get_machine_region()))
flag.set_attribute('is_final', '1')
hit_chart = self.data.local.music.get_hit_chart(self.game, self.music_version, self.GAME_MAX_SONGS)
@ -281,7 +281,7 @@ class DDR2013(
root.add_child(Node.string('seq', ''))
root.add_child(Node.u32('code', profile.extid))
root.add_child(Node.string('name', profile.get_str('name')))
root.add_child(Node.u8('area', profile.get_int('area', 51)))
root.add_child(Node.u8('area', profile.get_int('area', self.get_machine_region())))
root.add_child(Node.u32('cnt_s', play_stats.get_int('single_plays')))
root.add_child(Node.u32('cnt_d', play_stats.get_int('double_plays')))
root.add_child(Node.u32('cnt_b', play_stats.get_int('battle_plays'))) # This could be wrong, its a guess
@ -416,7 +416,7 @@ class DDR2013(
friendnode.set_attribute('up', '0')
friendnode.add_child(Node.u32('code', friend.extid))
friendnode.add_child(Node.string('name', friend.get_str('name')))
friendnode.add_child(Node.u8('area', friend.get_int('area', 51)))
friendnode.add_child(Node.u8('area', friend.get_int('area', self.get_machine_region())))
friendnode.add_child(Node.u32('exp', play_stats.get_int('exp')))
friendnode.add_child(Node.u32('star', friend.get_int('star')))

View File

@ -163,7 +163,7 @@ class DDR2014(
flag.set_attribute('t', '0')
flag.set_attribute('s1', '0')
flag.set_attribute('s2', '0')
flag.set_attribute('area', '51')
flag.set_attribute('area', str(self.get_machine_region()))
flag.set_attribute('is_final', '0')
# Last month's hit chart
@ -331,7 +331,7 @@ class DDR2014(
root.add_child(Node.string('seq', ''))
root.add_child(Node.u32('code', profile.extid))
root.add_child(Node.string('name', profile.get_str('name')))
root.add_child(Node.u8('area', profile.get_int('area', 51)))
root.add_child(Node.u8('area', profile.get_int('area', self.get_machine_region())))
root.add_child(Node.u32('cnt_s', play_stats.get_int('single_plays')))
root.add_child(Node.u32('cnt_d', play_stats.get_int('double_plays')))
root.add_child(Node.u32('cnt_b', play_stats.get_int('battle_plays'))) # This could be wrong, its a guess
@ -471,7 +471,7 @@ class DDR2014(
friendnode.set_attribute('up', '0')
friendnode.add_child(Node.u32('code', friend.extid))
friendnode.add_child(Node.string('name', friend.get_str('name')))
friendnode.add_child(Node.u8('area', friend.get_int('area', 51)))
friendnode.add_child(Node.u8('area', friend.get_int('area', self.get_machine_region())))
friendnode.add_child(Node.u32('exp', play_stats.get_int('exp')))
friendnode.add_child(Node.u32('star', friend.get_int('star')))

View File

@ -203,7 +203,7 @@ class DDRX2(
typenode.add_child(Node.string('name', users[userid].get_str('name')))
typenode.add_child(Node.u32('score', score.points))
typenode.add_child(Node.u16('area', users[userid].get_int('area', 51)))
typenode.add_child(Node.u16('area', users[userid].get_int('area', self.get_machine_region())))
typenode.add_child(Node.u8('rank', gamerank))
typenode.add_child(Node.u8('combo_type', combo_type))
@ -307,7 +307,7 @@ class DDRX2(
root.add_child(Node.string('seq', ''))
root.add_child(Node.u32('code', profile.extid))
root.add_child(Node.string('name', profile.get_str('name')))
root.add_child(Node.u8('area', profile.get_int('area', 51)))
root.add_child(Node.u8('area', profile.get_int('area', self.get_machine_region())))
root.add_child(Node.u32('cnt_s', play_stats.get_int('single_plays')))
root.add_child(Node.u32('cnt_d', play_stats.get_int('double_plays')))
root.add_child(Node.u32('cnt_b', play_stats.get_int('battle_plays'))) # This could be wrong, its a guess
@ -472,7 +472,7 @@ class DDRX2(
friendnode.set_attribute('up', '0')
friendnode.add_child(Node.u32('code', friend.extid))
friendnode.add_child(Node.string('name', friend.get_str('name')))
friendnode.add_child(Node.u8('area', friend.get_int('area', 51)))
friendnode.add_child(Node.u8('area', friend.get_int('area', self.get_machine_region())))
friendnode.add_child(Node.u32('exp', play_stats.get_int('exp')))
friendnode.add_child(Node.u32('star', friend.get_int('star')))

View File

@ -356,7 +356,7 @@ class DDRX3(
root.add_child(Node.string('seq', ''))
root.add_child(Node.u32('code', profile.extid))
root.add_child(Node.string('name', profile.get_str('name')))
root.add_child(Node.u8('area', profile.get_int('area', 51)))
root.add_child(Node.u8('area', profile.get_int('area', self.get_machine_region())))
root.add_child(Node.u32('cnt_s', play_stats.get_int('single_plays')))
root.add_child(Node.u32('cnt_d', play_stats.get_int('double_plays')))
root.add_child(Node.u32('cnt_b', play_stats.get_int('battle_plays'))) # This could be wrong, its a guess
@ -491,7 +491,7 @@ class DDRX3(
friendnode.set_attribute('up', '0')
friendnode.add_child(Node.u32('code', friend.extid))
friendnode.add_child(Node.string('name', friend.get_str('name')))
friendnode.add_child(Node.u8('area', friend.get_int('area', 51)))
friendnode.add_child(Node.u8('area', friend.get_int('area', self.get_machine_region())))
friendnode.add_child(Node.u32('exp', play_stats.get_int('exp')))
friendnode.add_child(Node.u32('star', friend.get_int('star')))

View File

@ -149,7 +149,7 @@ class IIDXBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
if name is None:
name = 'なし'
if pid is None:
pid = 51
pid = self.get_machine_region()
userid = self.data.remote.user.from_refid(self.game, self.version, refid)
profile = Profile(

View File

@ -13,3 +13,6 @@ class IIDXBistrover(IIDXBase):
def previous_version(self) -> Optional[IIDXBase]:
return IIDXHeroicVerse(self.data, self.config, self.model)
def requires_extended_regions(self) -> bool:
return True

View File

@ -160,6 +160,9 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase):
],
}
def requires_extended_regions(self) -> bool:
return True
def db_to_game_status(self, db_status: int) -> int:
return {
self.CLEAR_STATUS_NO_PLAY: self.GAME_CLEAR_STATUS_NO_PLAY,
@ -303,7 +306,7 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase):
root = Node.void('IIDX25shop')
root.set_attribute('opname', machine_name)
root.set_attribute('pid', '51')
root.set_attribute('pid', str(self.get_machine_region()))
root.set_attribute('cls_opt', '1' if close else '0')
root.set_attribute('hr', str(hour))
root.set_attribute('mi', str(minute))

View File

@ -296,7 +296,7 @@ class IIDXCopula(IIDXCourse, IIDXBase):
root.set_attribute('cls_opt', '0')
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
root.set_attribute('opname', machine.name)
root.set_attribute('pid', '51')
root.set_attribute('pid', str(self.get_machine_region()))
return root
if method == 'savename':

View File

@ -13,3 +13,6 @@ class IIDXHeroicVerse(IIDXBase):
def previous_version(self) -> Optional[IIDXBase]:
return IIDXRootage(self.data, self.config, self.model)
def requires_extended_regions(self) -> bool:
return True

View File

@ -164,7 +164,7 @@ class IIDXPendual(IIDXCourse, IIDXBase):
root.set_attribute('cls_opt', '0')
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
root.set_attribute('opname', machine.name)
root.set_attribute('pid', '51')
root.set_attribute('pid', str(self.get_machine_region()))
return root
if method == 'savename':

View File

@ -161,6 +161,9 @@ class IIDXRootage(IIDXCourse, IIDXBase):
],
}
def requires_extended_regions(self) -> bool:
return True
def db_to_game_status(self, db_status: int) -> int:
return {
self.CLEAR_STATUS_NO_PLAY: self.GAME_CLEAR_STATUS_NO_PLAY,
@ -304,7 +307,7 @@ class IIDXRootage(IIDXCourse, IIDXBase):
root = Node.void('IIDX26shop')
root.set_attribute('opname', machine_name)
root.set_attribute('pid', '51')
root.set_attribute('pid', str(self.get_machine_region()))
root.set_attribute('cls_opt', '1' if close else '0')
root.set_attribute('hr', str(hour))
root.set_attribute('mi', str(minute))

View File

@ -303,7 +303,7 @@ class IIDXSinobuz(IIDXCourse, IIDXBase):
root = Node.void('IIDX24shop')
root.set_attribute('opname', machine_name)
root.set_attribute('pid', '51')
root.set_attribute('pid', str(self.get_machine_region()))
root.set_attribute('cls_opt', '1' if close else '0')
root.set_attribute('hr', str(hour))
root.set_attribute('mi', str(minute))

View File

@ -269,7 +269,7 @@ class IIDXSpada(IIDXBase):
root.set_attribute('cls_opt', '0')
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
root.set_attribute('opname', machine.name)
root.set_attribute('pid', '51')
root.set_attribute('pid', str(self.get_machine_region()))
return root
if method == 'savename':

View File

@ -268,7 +268,7 @@ class IIDXTricoro(IIDXBase):
root.set_attribute('cls_opt', '0')
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
root.set_attribute('opname', machine.name)
root.set_attribute('pid', '51')
root.set_attribute('pid', str(self.get_machine_region()))
return root
if method == 'savename':

View File

@ -459,7 +459,7 @@ class PopnMusicFantasia(PopnMusicBase):
machine = self.get_machine()
root = Node.void('playerdata')
root.add_child(Node.s8('pref', machine.data.get_int('pref', -1)))
root.add_child(Node.s8('pref', machine.data.get_int('pref', self.get_machine_region())))
if refid is None:
root.add_child(Node.string('name', ''))

View File

@ -396,7 +396,7 @@ class PopnMusicLapistoria(PopnMusicBase):
course_id = request.child_value('course_id')
if course_id is not None:
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
pref = request.child_value('pref') or 51
pref = request.child_value('pref') or self.get_machine_region()
profile = self.get_profile(userid) or Profile(self.game, self.version, refid, 0)
course = self.data.local.user.get_achievement(

View File

@ -543,7 +543,7 @@ class PopnMusicSunnyPark(PopnMusicBase):
machine = self.get_machine()
root = Node.void('playerdata')
root.add_child(Node.s8('pref', machine.data.get_int('pref', -1)))
root.add_child(Node.s8('pref', machine.data.get_int('pref', self.get_machine_region())))
if refid is None:
root.add_child(Node.string('name', ''))
root.add_child(Node.s8('get_coupon_cnt', -1))

View File

@ -96,13 +96,13 @@ class ReflecBeatLimelight(ReflecBeatBase):
close = machine.data.get_bool('close')
hour = machine.data.get_int('hour')
minute = machine.data.get_int('minute')
pref = machine.data.get_int('pref', 51)
pref = machine.data.get_int('pref', self.get_machine_region())
else:
machine_name = ''
close = False
hour = 0
minute = 0
pref = 51
pref = self.get_machine_region()
root = Node.void('pcbinfo')
info = Node.void('info')

View File

@ -89,13 +89,13 @@ class ReflecBeat(ReflecBeatBase):
close = machine.data.get_bool('close')
hour = machine.data.get_int('hour')
minute = machine.data.get_int('minute')
pref = machine.data.get_int('pref', 51)
pref = machine.data.get_int('pref', self.get_machine_region())
else:
machine_name = ''
close = False
hour = 0
minute = 0
pref = 51
pref = self.get_machine_region()
root = Node.void('pcbinfo')
info = Node.void('info')
@ -140,7 +140,7 @@ class ReflecBeat(ReflecBeatBase):
def handle_sysinfo_fan_request(self, request: Node) -> Node:
sysinfo = Node.void('sysinfo')
sysinfo.add_child(Node.u8('pref', 51))
sysinfo.add_child(Node.u8('pref', self.get_machine_region()))
sysinfo.add_child(Node.string('lid', request.child_value('lid')))
return sysinfo

View File

@ -405,6 +405,10 @@ class _RegionConstants:
MIN: Final[int] = 1
MAX: Final[int] = 56
# Min/max valid values for JP prefectures
MIN_PREF: Final[int] = 1
MAX_PREF: Final[int] = 47
# This is a really nasty LUT to attempt to make the frontend display
# the same regardless of the game in question. This is mostly because
# the prefecture/region stored in the profile is editable by IIDX and

View File

@ -42,11 +42,13 @@ class ID:
return None
@staticmethod
def format_machine_id(machine_id: int) -> str:
def format_machine_id(machine_id: int, region: str = 'US') -> str:
"""
Take a machine ID as an integer, format it as a string.
"""
return f'US-{machine_id}'
if region not in {'JP', 'KR', 'TW', 'HK', 'US', 'GB', 'IT', 'ES', 'FR', 'PT'}:
raise Exception(f'Invalid region {region}!')
return f'{region}-{machine_id}'
@staticmethod
def parse_machine_id(machine_id: str) -> Optional[int]:
@ -54,7 +56,7 @@ class ID:
Take a formatted machine ID as a string, returning an int.
"""
try:
if machine_id[:3] == 'US-':
if machine_id[:2] in {'JP', 'KR', 'TW', 'HK', 'US', 'GB', 'IT', 'ES', 'FR', 'PT'} and machine_id[2] == '-':
return int(machine_id[3:])
except ValueError:
pass