-
Notifications
You must be signed in to change notification settings - Fork 69
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
SuperNova 2 Support #86
base: trunk
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -127,6 +127,13 @@ def format_profile(self, userid: UserID, profile: Profile) -> Node: | |
""" | ||
return Node.void("game") | ||
|
||
def format_profile_part(self, userid: UserID, profile: Profile, part: str) -> Node: | ||
""" | ||
Base handler for a profile. Given a userid and a profile dictionary, | ||
return a Node representing a profile. Should be overridden. | ||
""" | ||
return Node.void("game") | ||
|
||
def format_scores(self, userid: UserID, profile: Profile, scores: List[Score]) -> Node: | ||
""" | ||
Base handler for a score list. Given a userid, profile and a score list, | ||
|
@@ -142,6 +149,24 @@ def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) - | |
""" | ||
return oldprofile | ||
|
||
def get_profile_by_refid_and_part(self, refid: Optional[str], part: Optional[str]) -> Optional[Node]: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, this definitely feels weird. But, the pattern is established. Worth a think. |
||
""" | ||
Given a RefID, return a formatted profile node. Basically every game | ||
needs a profile lookup, even if it handles where that happens in | ||
a different request. This is provided for code deduplication. | ||
""" | ||
if refid is None: | ||
return None | ||
|
||
# First try to load the actual profile | ||
userid = self.data.remote.user.from_refid(self.game, self.version, refid) | ||
profile = self.get_profile(userid) | ||
if profile is None: | ||
return None | ||
|
||
# Now, return it | ||
return self.format_profile_part(userid, profile, part) | ||
|
||
def get_profile_by_refid(self, refid: Optional[str]) -> Optional[Node]: | ||
""" | ||
Given a RefID, return a formatted profile node. Basically every game | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
from bemani.backend.ddr.ddrsn2.ddrsn2 import DDRSuperNova2 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Interesting separating this into a module instead of a single file. Any reason for having this across a bunch of files? Don't see a problem with it, just curious. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Honestly, mostly just a leftover from my JS work. A common lint is only one class defined per file. If it's a bit awkward I'm ok with merging them into one file. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IDGAF either way, pattern in the repo is one file, we don't do silly things like have an import system that depends on there being one export/class per file, so you can get away with a lot of stuff. |
||
|
||
__all__ = ["DDRSuperNova2"] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import logging | ||
from ctypes import * | ||
|
||
|
||
class BattleRecordStruct(Structure): | ||
_pack_ = 1 | ||
_fields_ = [ | ||
("name", c_char * 14), | ||
("wins", c_uint16), | ||
("loses", c_uint16), | ||
("draws", c_uint16), | ||
] | ||
|
||
|
||
class BattleRecord: | ||
@staticmethod | ||
def create(name: str, wins: int, losses: int, draws: int) -> BattleRecordStruct: | ||
this_name = name | ||
if len(this_name) > 8: | ||
this_name = this_name[:8] | ||
logging.warning("name {} too long, truncating to {}", name, this_name) | ||
elif len(this_name) < 8: | ||
logging.warning("name too short, padding with spaces") | ||
this_name = this_name.ljust(8, " ") | ||
|
||
return BattleRecordStruct(this_name.encode("ascii"), wins, losses, draws) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Profile for SN2 is split into 3 binary chunks, where to break this logic down, it being here feels wrong
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Honestly the
format_profile
andunformat_profile
convention were both established to just give some sort of unity across games. They don't need to exist outside of the fact that the base of most games assumes it can call that for profile loads. If there's 3 parts here, this can diverge for cleaner code.