1
0
mirror of synced 2025-02-17 11:18:33 +01:00

Move emblem unlocks to i tems, correctly allow earned JBOX emblem parts to show up on front end.

This commit is contained in:
Jennifer Taylor 2022-11-13 01:20:51 +00:00
parent d85ccea865
commit c91a3f2ea7
5 changed files with 254 additions and 149 deletions

View File

@ -1,5 +1,6 @@
# vim: set fileencoding=utf-8
from typing import Dict, List, Optional
import random
from typing import Dict, Iterable, List, Optional, Set, Tuple
from typing_extensions import Final
from bemani.backend.base import Base
@ -293,3 +294,65 @@ class JubeatBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
raised,
timestamp=timestamp,
)
def default_select_jbox(self) -> Set[int]:
gameitems = self.data.local.game.get_items(self.game, self.version)
default_main: Set[int] = set()
for gameitem in gameitems:
if gameitem.type == "emblem":
if (
gameitem.data.get_int("layer") == 2
and gameitem.data.get_int("rarity") == 1
):
default_main.add(gameitem.id)
return default_main
def random_select_jbox(self, owned_emblems: Set[int]) -> Tuple[int, int]:
gameitems = self.data.local.game.get_items(self.game, self.version)
normalemblems: Set[int] = set()
premiumemblems: Set[int] = set()
for gameitem in gameitems:
if gameitem.type == "emblem":
if gameitem.id in owned_emblems:
# We don't want to give out random emblems that are already owned.
continue
if gameitem.data.get_int("rarity") in {1, 2, 3}:
normalemblems.add(gameitem.id)
if gameitem.data.get_int("rarity") in {4, 5}:
premiumemblems.add(gameitem.id)
# Default to some emblems in case the catalog is not available.
normalindex = 2
premiumindex = 1
if normalemblems:
normalindex = random.sample(normalemblems, 1)[0]
if premiumemblems:
premiumindex = random.sample(premiumemblems, 1)[0]
return normalindex, premiumindex
def calculate_owned_items(self, item_list: List[int]) -> Set[int]:
owned_items: Set[int] = set()
for index in range(len(item_list) * 32):
offset = 1 << (index % 32)
bucket = index // 32
if (item_list[bucket] & offset) != 0:
owned_items.add(index)
return owned_items
def create_owned_items(self, items: Iterable[int], size: int) -> List[int]:
items_list = [0] * size
for index in items:
offset = 1 << (index % 32)
bucket = index // 32
items_list[bucket] |= offset
return items_list

View File

@ -1401,9 +1401,18 @@ class JubeatClan(
# Grab unlock progress
item = player.child("item")
if item is not None:
profile.replace_int_array(
"emblem_list", 96, item.child_value("emblem_list")
owned_emblems = self.calculate_owned_items(
item.child_value("emblem_list")
)
for index in owned_emblems:
self.data.local.user.put_achievement(
self.game,
self.version,
userid,
index,
"emblem",
{},
)
# jbox stuff
jbox = player.child("jbox")
@ -1540,6 +1549,28 @@ class JubeatClan(
data = Node.void("data")
root.add_child(data)
# Calculate all of our achievement-backed entities.
achievements = self.data.local.user.get_achievements(
self.game, self.version, userid
)
event_completion: Dict[int, bool] = {}
course_completion: Dict[int, ValidatedDict] = {}
owned_emblems: Set[int] = set()
for achievement in achievements:
if achievement.type == "event":
event_completion[achievement.id] = achievement.data.get_bool(
"is_completed"
)
elif achievement.type == "course":
course_completion[achievement.id] = achievement.data
elif achievement.type == "emblem":
owned_emblems.add(achievement.id)
# Make sure we grant ownership of default main parts.
default_emblems = self.default_select_jbox()
owned_emblems.update(default_emblems)
default_main = next(iter(default_emblems)) if default_emblems else 0
# Jubeat Clan appears to allow full event overrides per-player
data.add_child(self.__get_global_info())
@ -1608,13 +1639,16 @@ class JubeatClan(
settings.add_child(Node.s16("parts", lastdict.get_int("parts")))
settings.add_child(Node.s8("rank_sort", lastdict.get_int("rank_sort")))
settings.add_child(Node.s8("combo_disp", lastdict.get_int("combo_disp")))
settings.add_child(
Node.s16_array("emblem", lastdict.get_int_array("emblem", 5))
)
settings.add_child(Node.s8("matching", lastdict.get_int("matching")))
settings.add_child(Node.s8("hard", lastdict.get_int("hard")))
settings.add_child(Node.s8("hazard", lastdict.get_int("hazard")))
# Hack to make the default emblem appear properly.
partslist = lastdict.get_int_array("emblem", 5, [0, default_main, 0, 0, 0])
if partslist[1] == 0:
partslist[1] = default_main
settings.add_child(Node.s16_array("emblem", partslist))
# Secret unlocks
item = Node.void("item")
player.add_child(item)
@ -1649,9 +1683,7 @@ class JubeatClan(
)
)
item.add_child(
Node.s32_array(
"emblem_list", profile.get_int_array("emblem_list", 96, [-1] * 96)
)
Node.s32_array("emblem_list", self.create_owned_items(owned_emblems, 96))
)
item.add_child(
Node.s32_array(
@ -1766,19 +1798,6 @@ class JubeatClan(
# Player status for events
event_info = Node.void("event_info")
player.add_child(event_info)
achievements = self.data.local.user.get_achievements(
self.game, self.version, userid
)
event_completion: Dict[int, bool] = {}
course_completion: Dict[int, ValidatedDict] = {}
for achievement in achievements:
if achievement.type == "event":
event_completion[achievement.id] = achievement.data.get_bool(
"is_completed"
)
if achievement.type == "course":
course_completion[achievement.id] = achievement.data
for eventid, eventdata in self.EVENTS.items():
# There are two significant bits here, bit 0 and bit 1, I think the first
# one is whether the event is started, second is if its finished?
@ -1809,24 +1828,7 @@ class JubeatClan(
# Calculate a random index for normal and premium to give to player
# as a gatcha.
gameitems = self.data.local.game.get_items(self.game, self.version)
normalemblems: Set[int] = set()
premiumemblems: Set[int] = set()
for gameitem in gameitems:
if gameitem.type == "emblem":
if gameitem.data.get_int("rarity") in {1, 2, 3}:
normalemblems.add(gameitem.id)
if gameitem.data.get_int("rarity") in {3, 4, 5}:
premiumemblems.add(gameitem.id)
# Default to some emblems in case the catalog is not available.
normalindex = 2
premiumindex = 1
if normalemblems:
normalindex = random.sample(normalemblems, 1)[0]
if premiumemblems:
premiumindex = random.sample(premiumemblems, 1)[0]
normalindex, premiumindex = self.random_select_jbox(owned_emblems)
normal.add_child(Node.s16("index", normalindex))
premium.add_child(Node.s16("index", premiumindex))
@ -2114,13 +2116,21 @@ class JubeatClan(
newprofile.replace_int_array(
"parts_list", 160, item.child_value("parts_list")
)
newprofile.replace_int_array(
"emblem_list", 96, item.child_value("emblem_list")
)
newprofile.replace_int_array(
"commu_list", 16, item.child_value("commu_list")
)
owned_emblems = self.calculate_owned_items(item.child_value("emblem_list"))
for index in owned_emblems:
self.data.local.user.put_achievement(
self.game,
self.version,
userid,
index,
"emblem",
{},
)
newitem = item.child("new")
if newitem is not None:
newprofile.replace_int_array(

View File

@ -2212,9 +2212,18 @@ class JubeatFesto(
# Grab unlock progress
item = player.child("item")
if item is not None:
profile.replace_int_array(
"emblem_list", 96, item.child_value("emblem_list")
owned_emblems = self.calculate_owned_items(
item.child_value("emblem_list")
)
for index in owned_emblems:
self.data.local.user.put_achievement(
self.game,
self.version,
userid,
index,
"emblem",
{},
)
# jbox stuff
jbox = player.child("jbox")
@ -2417,6 +2426,28 @@ class JubeatFesto(
data = Node.void("data")
root.add_child(data)
# Calculate all of our achievement-backed entities.
achievements = self.data.local.user.get_achievements(
self.game, self.version, userid
)
owned_emblems: Set[int] = set()
event_completion: Dict[int, bool] = {}
course_completion: Dict[int, ValidatedDict] = {}
for achievement in achievements:
if achievement.type == "event":
event_completion[achievement.id] = achievement.data.get_bool(
"is_completed"
)
elif achievement.type == "course":
course_completion[achievement.id] = achievement.data
elif achievement.type == "emblem":
owned_emblems.add(achievement.id)
# Make sure we grant ownership of default main parts.
default_emblems = self.default_select_jbox()
owned_emblems.update(default_emblems)
default_main = next(iter(default_emblems)) if default_emblems else 0
# Jubeat Clan appears to allow full event overrides per-player
data.add_child(self.__get_global_info())
@ -2483,13 +2514,16 @@ class JubeatFesto(
settings.add_child(Node.s16("parts", lastdict.get_int("parts")))
settings.add_child(Node.s8("rank_sort", lastdict.get_int("rank_sort")))
settings.add_child(Node.s8("combo_disp", lastdict.get_int("combo_disp")))
settings.add_child(
Node.s16_array("emblem", lastdict.get_int_array("emblem", 5))
)
settings.add_child(Node.s8("matching", lastdict.get_int("matching")))
settings.add_child(Node.s8("hard", lastdict.get_int("hard")))
settings.add_child(Node.s8("hazard", lastdict.get_int("hazard")))
# Hack to make the default emblem appear properly.
partslist = lastdict.get_int_array("emblem", 5, [0, default_main, 0, 0, 0])
if partslist[1] == 0:
partslist[1] = default_main
settings.add_child(Node.s16_array("emblem", partslist))
# Secret unlocks, the game is too complicated and server-controlled to handle these correctly.
item = Node.void("item")
player.add_child(item)
@ -2503,6 +2537,8 @@ class JubeatFesto(
"secret_list", profile.get_int_array("secret_list", 64, [-1] * 64)
)
)
# We force unlock all themes, markers, titles, and parts, regardless of what the client ended up earning.
item.add_child(
Node.s32_array(
"theme_list", profile.get_int_array("theme_list", 16, [-1] * 16)
@ -2523,11 +2559,13 @@ class JubeatFesto(
"parts_list", profile.get_int_array("parts_list", 160, [-1] * 160)
)
)
# These get earned by unlocking them through JBOX.
item.add_child(
Node.s32_array(
"emblem_list", profile.get_int_array("emblem_list", 96, [-1] * 96)
)
Node.s32_array("emblem_list", self.create_owned_items(owned_emblems, 96))
)
# I got no idea wtf this is, so I'm defaulting it to all on like the above ones.
item.add_child(
Node.s32_array(
"commu_list", profile.get_int_array("commu_list", 16, [-1] * 16)
@ -2640,19 +2678,6 @@ class JubeatFesto(
# Player status for events
event_info = Node.void("event_info")
player.add_child(event_info)
achievements = self.data.local.user.get_achievements(
self.game, self.version, userid
)
event_completion: Dict[int, bool] = {}
course_completion: Dict[int, ValidatedDict] = {}
for achievement in achievements:
if achievement.type == "event":
event_completion[achievement.id] = achievement.data.get_bool(
"is_completed"
)
if achievement.type == "course":
course_completion[achievement.id] = achievement.data
for eventid, eventdata in self.EVENTS.items():
# There are two significant bits here, bit 0 and bit 1, I think the first
# one is whether the event is started, second is if its finished?
@ -2683,24 +2708,7 @@ class JubeatFesto(
# Calculate a random index for normal and premium to give to player
# as a gatcha.
gameitems = self.data.local.game.get_items(self.game, self.version)
normalemblems: Set[int] = set()
premiumemblems: Set[int] = set()
for gameitem in gameitems:
if gameitem.type == "emblem":
if gameitem.data.get_int("rarity") in {1, 2, 3}:
normalemblems.add(gameitem.id)
if gameitem.data.get_int("rarity") in {3, 4, 5}:
premiumemblems.add(gameitem.id)
# Default to some emblems in case the catalog is not available.
normalindex = 2
premiumindex = 1
if normalemblems:
normalindex = random.sample(normalemblems, 1)[0]
if premiumemblems:
premiumindex = random.sample(premiumemblems, 1)[0]
normalindex, premiumindex = self.random_select_jbox(owned_emblems)
normal.add_child(Node.s16("index", normalindex))
premium.add_child(Node.s16("index", premiumindex))
@ -2940,13 +2948,21 @@ class JubeatFesto(
newprofile.replace_int_array(
"parts_list", 160, item.child_value("parts_list")
)
newprofile.replace_int_array(
"emblem_list", 96, item.child_value("emblem_list")
)
newprofile.replace_int_array(
"commu_list", 16, item.child_value("commu_list")
)
owned_emblems = self.calculate_owned_items(item.child_value("emblem_list"))
for index in owned_emblems:
self.data.local.user.put_achievement(
self.game,
self.version,
userid,
index,
"emblem",
{},
)
newitem = item.child("new")
if newitem is not None:
newprofile.replace_int_array(

View File

@ -896,6 +896,21 @@ class JubeatProp(
root = Node.void("gametop")
data = Node.void("data")
root.add_child(data)
# Allow figuring out owned emblems.
achievements = self.data.local.user.get_achievements(
self.game, self.version, userid
)
owned_emblems: Set[int] = set()
for achievement in achievements:
if achievement.type == "emblem":
owned_emblems.add(achievement.id)
# Make sure we grant ownership of default main parts.
default_emblems = self.default_select_jbox()
owned_emblems.update(default_emblems)
default_main = next(iter(default_emblems)) if default_emblems else 0
# Jubeat Prop appears to allow full event overrides per-player
data.add_child(self.__get_global_info())
@ -967,13 +982,16 @@ class JubeatProp(
settings.add_child(Node.s16("parts", lastdict.get_int("parts")))
settings.add_child(Node.s8("rank_sort", lastdict.get_int("rank_sort")))
settings.add_child(Node.s8("combo_disp", lastdict.get_int("combo_disp")))
settings.add_child(
Node.s16_array("emblem", lastdict.get_int_array("emblem", 5))
)
settings.add_child(Node.s8("matching", lastdict.get_int("matching")))
settings.add_child(Node.s8("hazard", lastdict.get_int("hazard")))
settings.add_child(Node.s8("hard", lastdict.get_int("hard")))
# Hack to make the default emblem appear properly.
partslist = lastdict.get_int_array("emblem", 5, [0, default_main, 0, 0, 0])
if partslist[1] == 0:
partslist[1] = default_main
settings.add_child(Node.s16_array("emblem", partslist))
# Secret unlocks
item = Node.void("item")
player.add_child(item)
@ -1004,9 +1022,7 @@ class JubeatProp(
)
)
item.add_child(
Node.s32_array(
"emblem_list", profile.get_int_array("emblem_list", 96, [-1] * 96)
)
Node.s32_array("emblem_list", self.create_owned_items(owned_emblems, 96))
)
new = Node.void("new")
@ -1045,9 +1061,6 @@ class JubeatProp(
# Player status for events
event_info = Node.void("event_info")
player.add_child(event_info)
achievements = self.data.local.user.get_achievements(
self.game, self.version, userid
)
for achievement in achievements:
if achievement.type == "event":
# There are two significant bits here, 0x1 and 0x2, I think the first
@ -1172,24 +1185,7 @@ class JubeatProp(
# Calculate a random index for normal and premium to give to player
# as a gatcha.
gameitems = self.data.local.game.get_items(self.game, self.version)
normalemblems: Set[int] = set()
premiumemblems: Set[int] = set()
for gameitem in gameitems:
if gameitem.type == "emblem":
if gameitem.data.get_int("rarity") in {1, 2, 3}:
normalemblems.add(gameitem.id)
if gameitem.data.get_int("rarity") in {3, 4, 5}:
premiumemblems.add(gameitem.id)
# Default to some emblems in case the catalog is not available.
normalindex = 2
premiumindex = 1
if normalemblems:
normalindex = random.sample(normalemblems, 1)[0]
if premiumemblems:
premiumindex = random.sample(premiumemblems, 1)[0]
normalindex, premiumindex = self.random_select_jbox(owned_emblems)
normal.add_child(Node.s16("index", normalindex))
premium.add_child(Node.s16("index", premiumindex))
@ -1220,8 +1216,8 @@ class JubeatProp(
# Emblem list stuff?
eapass_privilege = Node.void("eapass_privilege")
player.add_child(eapass_privilege)
emblem_list = Node.void("emblem_list")
eapass_privilege.add_child(emblem_list)
emblem_node = Node.void("emblem_list")
eapass_privilege.add_child(emblem_node)
# Bonus music stuff?
bonus_music = Node.void("bonus_music")
@ -1349,9 +1345,17 @@ class JubeatProp(
newprofile.replace_int_array(
"music_list", 32, item.child_value("music_list")
)
newprofile.replace_int_array(
"emblem_list", 96, item.child_value("emblem_list")
)
owned_emblems = self.calculate_owned_items(item.child_value("emblem_list"))
for index in owned_emblems:
self.data.local.user.put_achievement(
self.game,
self.version,
userid,
index,
"emblem",
{},
)
newitem = item.child("new")
if newitem is not None:

View File

@ -671,9 +671,18 @@ class JubeatQubell(
# Grab unlock progress
item = player.child("item")
if item is not None:
profile.replace_int_array(
"emblem_list", 96, item.child_value("emblem_list")
owned_emblems = self.calculate_owned_items(
item.child_value("emblem_list")
)
for index in owned_emblems:
self.data.local.user.put_achievement(
self.game,
self.version,
userid,
index,
"emblem",
{},
)
# jbox stuff
jbox = player.child("jbox")
@ -705,6 +714,20 @@ class JubeatQubell(
root = Node.void("gametop")
data = Node.void("data")
root.add_child(data)
achievements = self.data.local.user.get_achievements(
self.game, self.version, userid
)
owned_emblems: Set[int] = set()
for achievement in achievements:
if achievement.type == "emblem":
owned_emblems.add(achievement.id)
# Make sure we grant ownership of default main parts.
default_emblems = self.default_select_jbox()
owned_emblems.update(default_emblems)
default_main = next(iter(default_emblems)) if default_emblems else 0
# Jubeat Prop appears to allow full event overrides per-player
data.add_child(self.__get_global_info())
@ -780,13 +803,16 @@ class JubeatQubell(
settings.add_child(Node.s16("parts", lastdict.get_int("parts")))
settings.add_child(Node.s8("rank_sort", lastdict.get_int("rank_sort")))
settings.add_child(Node.s8("combo_disp", lastdict.get_int("combo_disp")))
settings.add_child(
Node.s16_array("emblem", lastdict.get_int_array("emblem", 5))
)
settings.add_child(Node.s8("matching", lastdict.get_int("matching")))
settings.add_child(Node.s8("hazard", lastdict.get_int("hazard")))
settings.add_child(Node.s8("hard", lastdict.get_int("hard")))
# Hack to make the default emblem appear properly.
partslist = lastdict.get_int_array("emblem", 5, [0, default_main, 0, 0, 0])
if partslist[1] == 0:
partslist[1] = default_main
settings.add_child(Node.s16_array("emblem", partslist))
# Secret unlocks
item = Node.void("item")
player.add_child(item)
@ -821,9 +847,7 @@ class JubeatQubell(
)
)
item.add_child(
Node.s32_array(
"emblem_list", profile.get_int_array("emblem_list", 96, [-1] * 96)
)
Node.s32_array("emblem_list", self.create_owned_items(owned_emblems, 96))
)
new = Node.void("new")
@ -935,9 +959,6 @@ class JubeatQubell(
# Player status for events
event_info = Node.void("event_info")
player.add_child(event_info)
achievements = self.data.local.user.get_achievements(
self.game, self.version, userid
)
for achievement in achievements:
if achievement.type == "event":
# There are two significant bits here, 0x1 and 0x2, I think the first
@ -966,24 +987,7 @@ class JubeatQubell(
# Calculate a random index for normal and premium to give to player
# as a gatcha.
gameitems = self.data.local.game.get_items(self.game, self.version)
normalemblems: Set[int] = set()
premiumemblems: Set[int] = set()
for gameitem in gameitems:
if gameitem.type == "emblem":
if gameitem.data.get_int("rarity") in {1, 2, 3}:
normalemblems.add(gameitem.id)
if gameitem.data.get_int("rarity") in {3, 4, 5}:
premiumemblems.add(gameitem.id)
# Default to some emblems in case the catalog is not available.
normalindex = 2
premiumindex = 1
if normalemblems:
normalindex = random.sample(normalemblems, 1)[0]
if premiumemblems:
premiumindex = random.sample(premiumemblems, 1)[0]
normalindex, premiumindex = self.random_select_jbox(owned_emblems)
normal.add_child(Node.s16("index", normalindex))
premium.add_child(Node.s16("index", premiumindex))
@ -1331,9 +1335,17 @@ class JubeatQubell(
newprofile.replace_int_array(
"parts_list", 160, item.child_value("parts_list")
)
newprofile.replace_int_array(
"emblem_list", 96, item.child_value("emblem_list")
)
owned_emblems = self.calculate_owned_items(item.child_value("emblem_list"))
for index in owned_emblems:
self.data.local.user.put_achievement(
self.game,
self.version,
userid,
index,
"emblem",
{},
)
newitem = item.child("new")
if newitem is not None: