fix team membership struct
This commit is contained in:
+9
-14
@@ -3044,8 +3044,9 @@ struct S_TournamentEntryList_Ep3_E2 {
|
||||
// E2 (S->C): Set system file contents (BB)
|
||||
|
||||
struct S_SyncSystemFile_BB_E2 {
|
||||
PSOBBBaseSystemFile system_file;
|
||||
PSOBBTeamMembership team_membership;
|
||||
/* 0000 */ PSOBBBaseSystemFile system_file;
|
||||
/* 02B8 */ PSOBBFullTeamMembership team_membership;
|
||||
/* 0AF0 */
|
||||
} __packed_ws__(S_SyncSystemFile_BB_E2, 0xAF0);
|
||||
|
||||
// E3 (S->C): Game or tournament info (Episode 3)
|
||||
@@ -3244,7 +3245,7 @@ struct C_CreateSpectatorTeam_Ep3_E7 {
|
||||
struct SC_SyncSaveFiles_BB_E7 {
|
||||
/* 0000 */ PSOBBCharacterFile char_file;
|
||||
/* 2EA4 */ PSOBBBaseSystemFile system_file;
|
||||
/* 30DC */ PSOBBTeamMembership team_membership;
|
||||
/* 315C */ PSOBBFullTeamMembership team_membership;
|
||||
/* 3994 */
|
||||
} __packed_ws__(SC_SyncSaveFiles_BB_E7, 0x3994);
|
||||
|
||||
@@ -3488,19 +3489,13 @@ struct C_ChangeTeamMemberPrivilegeLevel_BB_11EA {
|
||||
} __packed_ws__(C_ChangeTeamMemberPrivilegeLevel_BB_11EA, 4);
|
||||
|
||||
// 12EA (S->C): Team membership information
|
||||
// If the client is not in a team, all fields should be zero.
|
||||
// This updates the client's view of its system file.
|
||||
|
||||
struct S_TeamMembershipInformation_BB_12EA {
|
||||
le_uint32_t unknown_a1 = 0;
|
||||
le_uint32_t guild_card_number = 0;
|
||||
le_uint32_t team_id = 0;
|
||||
le_uint32_t unknown_a4 = 0;
|
||||
le_uint32_t unknown_a6 = 0;
|
||||
uint8_t privilege_level = 0;
|
||||
uint8_t team_member_count = 0;
|
||||
uint8_t unknown_a8 = 0;
|
||||
uint8_t unknown_a9 = 0;
|
||||
pstring<TextEncoding::UTF16_ALWAYS_MARKED, 0x10> team_name;
|
||||
// If skip_update_system_file is not zero, the client ignores the command.
|
||||
// It's not clear why this field exists.
|
||||
le_uint32_t skip_update_system_file = 0;
|
||||
PSOBBBaseTeamMembership membership;
|
||||
} __packed_ws__(S_TeamMembershipInformation_BB_12EA, 0x38);
|
||||
|
||||
// 13EA: Team info for lobby players
|
||||
|
||||
+9
-42
@@ -5237,9 +5237,7 @@ static void on_EA_BB(shared_ptr<Client> c, uint16_t command, uint32_t flag, stri
|
||||
c->login->account->save();
|
||||
|
||||
send_command(c, 0x02EA, 0x00000000);
|
||||
send_update_team_metadata_for_client(c);
|
||||
send_team_membership_info(c);
|
||||
send_update_team_reward_flags(c);
|
||||
send_team_membership_change_notifications(c);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -5274,8 +5272,7 @@ static void on_EA_BB(shared_ptr<Client> c, uint16_t command, uint32_t flag, stri
|
||||
added_c->login->account->account_id,
|
||||
added_c->character()->disp.name.decode(added_c->language()));
|
||||
|
||||
send_update_team_metadata_for_client(added_c);
|
||||
send_team_membership_info(added_c);
|
||||
send_team_membership_change_notifications(added_c);
|
||||
send_command(c, 0x04EA, 0x00000000);
|
||||
send_command(added_c, 0x04EA, 0x00000000);
|
||||
}
|
||||
@@ -5306,8 +5303,7 @@ static void on_EA_BB(shared_ptr<Client> c, uint16_t command, uint32_t flag, stri
|
||||
}
|
||||
}
|
||||
if (removed_c) {
|
||||
send_update_team_metadata_for_client(removed_c);
|
||||
send_team_membership_info(removed_c);
|
||||
send_team_membership_change_notifications(removed_c);
|
||||
}
|
||||
} else {
|
||||
// TODO: Figure out the right error code to use here.
|
||||
@@ -5352,13 +5348,7 @@ static void on_EA_BB(shared_ptr<Client> c, uint16_t command, uint32_t flag, stri
|
||||
if (team && team->members.at(c->login->account->account_id).check_flag(TeamIndex::Team::Member::Flag::IS_MASTER)) {
|
||||
const auto& cmd = check_size_t<C_SetTeamFlag_BB_0FEA>(data);
|
||||
s->team_index->set_flag_data(team->team_id, cmd.flag_data);
|
||||
for (const auto& it : team->members) {
|
||||
try {
|
||||
auto member_c = s->find_client(nullptr, it.second.account_id);
|
||||
send_update_team_metadata_for_client(member_c);
|
||||
} catch (const out_of_range&) {
|
||||
}
|
||||
}
|
||||
send_team_metadata_change_notifications(s, team, TeamMetadataChange::FLAG_DATA);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -5366,16 +5356,8 @@ static void on_EA_BB(shared_ptr<Client> c, uint16_t command, uint32_t flag, stri
|
||||
auto team = c->team();
|
||||
if (team && team->members.at(c->login->account->account_id).check_flag(TeamIndex::Team::Member::Flag::IS_MASTER)) {
|
||||
s->team_index->disband(team->team_id);
|
||||
|
||||
send_command(c, 0x10EA, 0x00000000);
|
||||
for (const auto& it : team->members) {
|
||||
try {
|
||||
auto member_c = s->find_client(nullptr, it.second.account_id);
|
||||
send_update_team_metadata_for_client(member_c);
|
||||
send_team_membership_info(member_c);
|
||||
} catch (const out_of_range&) {
|
||||
}
|
||||
}
|
||||
send_team_metadata_change_notifications(s, team, TeamMetadataChange::TEAM_DISBANDED);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -5429,14 +5411,12 @@ static void on_EA_BB(shared_ptr<Client> c, uint16_t command, uint32_t flag, stri
|
||||
}
|
||||
}
|
||||
if (send_updates_for_this_m) {
|
||||
send_update_team_metadata_for_client(c);
|
||||
send_team_membership_info(c);
|
||||
send_team_membership_change_notifications(c);
|
||||
}
|
||||
if (send_updates_for_other_m) {
|
||||
try {
|
||||
auto other_c = s->find_client(nullptr, cmd.guild_card_number);
|
||||
send_update_team_metadata_for_client(other_c);
|
||||
send_team_membership_info(other_c);
|
||||
send_team_membership_change_notifications(other_c);
|
||||
} catch (const out_of_range&) {
|
||||
}
|
||||
}
|
||||
@@ -5474,13 +5454,7 @@ static void on_EA_BB(shared_ptr<Client> c, uint16_t command, uint32_t flag, stri
|
||||
s->team_index->buy_reward(team->team_id, reward.key, reward.team_points, reward.reward_flag);
|
||||
|
||||
if (reward.reward_flag != TeamIndex::Team::RewardFlag::NONE) {
|
||||
for (const auto& it : team->members) {
|
||||
try {
|
||||
auto member_c = s->find_client(nullptr, it.second.account_id);
|
||||
send_update_team_reward_flags(member_c);
|
||||
} catch (const out_of_range&) {
|
||||
}
|
||||
}
|
||||
send_team_metadata_change_notifications(s, team, TeamMetadataChange::REWARD_FLAGS);
|
||||
}
|
||||
if (!reward.reward_item.empty()) {
|
||||
c->current_bank().add_item(reward.reward_item, *s->item_stack_limits(c->version()));
|
||||
@@ -5503,14 +5477,7 @@ static void on_EA_BB(shared_ptr<Client> c, uint16_t command, uint32_t flag, stri
|
||||
} else {
|
||||
s->team_index->rename(team->team_id, new_team_name);
|
||||
send_command(c, 0x1FEA, 0x00000000);
|
||||
for (const auto& it : team->members) {
|
||||
try {
|
||||
auto member_c = s->find_client(nullptr, it.second.account_id);
|
||||
send_update_team_metadata_for_client(c);
|
||||
send_team_membership_info(c);
|
||||
} catch (const out_of_range&) {
|
||||
}
|
||||
}
|
||||
send_team_metadata_change_notifications(s, team, TeamMetadataChange::TEAM_NAME);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1173,7 +1173,7 @@ PSOCHARFile::LoadSharedResult PSOCHARFile::load_shared(const string& filename, b
|
||||
if (header.flag != 0x00000000) {
|
||||
throw runtime_error("incorrect flag in character file header");
|
||||
}
|
||||
static_assert(sizeof(PSOBBCharacterFile) + sizeof(PSOBBBaseSystemFile) + sizeof(PSOBBTeamMembership) == 0x3994, ".psochar size is incorrect");
|
||||
static_assert(sizeof(PSOBBCharacterFile) + sizeof(PSOBBBaseSystemFile) + sizeof(PSOBBFullTeamMembership) == 0x3994, ".psochar size is incorrect");
|
||||
|
||||
LoadSharedResult ret;
|
||||
ret.character_file = make_shared<PSOBBCharacterFile>(phosg::freadx<PSOBBCharacterFile>(f.get()));
|
||||
@@ -1188,7 +1188,7 @@ void PSOCHARFile::save(
|
||||
std::shared_ptr<const PSOBBBaseSystemFile> system,
|
||||
std::shared_ptr<const PSOBBCharacterFile> character) {
|
||||
auto f = phosg::fopen_unique(filename, "wb");
|
||||
PSOCommandHeaderBB header = {sizeof(PSOCommandHeaderBB) + sizeof(PSOBBCharacterFile) + sizeof(PSOBBBaseSystemFile) + sizeof(PSOBBTeamMembership), 0x00E7, 0x00000000};
|
||||
PSOCommandHeaderBB header = {sizeof(PSOCommandHeaderBB) + sizeof(PSOBBCharacterFile) + sizeof(PSOBBBaseSystemFile) + sizeof(PSOBBFullTeamMembership), 0x00E7, 0x00000000};
|
||||
phosg::fwritex(f.get(), header);
|
||||
phosg::fwritex(f.get(), *character);
|
||||
phosg::fwritex(f.get(), *system);
|
||||
@@ -1202,7 +1202,7 @@ void PSOCHARFile::save(
|
||||
// be used anyway, and if it's not, then it would presumably have a different
|
||||
// set of teams with a different set of team IDs anyway, so the membership
|
||||
// struct here would be useless either way.
|
||||
static const PSOBBTeamMembership empty_membership;
|
||||
static const PSOBBFullTeamMembership empty_membership;
|
||||
phosg::fwritex(f.get(), empty_membership);
|
||||
}
|
||||
|
||||
|
||||
+21
-14
@@ -198,22 +198,29 @@ check_struct_size(SaveFileShortcutEntryGC, 0x54);
|
||||
check_struct_size(SaveFileShortcutEntryXB, 0x54);
|
||||
check_struct_size(SaveFileShortcutEntryBB, 0xA4);
|
||||
|
||||
struct PSOBBTeamMembership {
|
||||
/* 0000 */ le_uint32_t team_master_guild_card_number = 0;
|
||||
/* 0004 */ le_uint32_t team_id = 0;
|
||||
/* 0008 */ le_uint32_t unknown_a5 = 0;
|
||||
/* 000C */ le_uint32_t unknown_a6 = 0;
|
||||
/* 0010 */ uint8_t privilege_level = 0;
|
||||
/* 0011 */ uint8_t unknown_a7 = 0;
|
||||
/* 0012 */ uint8_t unknown_a8 = 0;
|
||||
/* 0013 */ uint8_t unknown_a9 = 0;
|
||||
/* 0014 */ pstring<TextEncoding::UTF16_ALWAYS_MARKED, 0x10> team_name;
|
||||
struct PSOBBBaseTeamMembership {
|
||||
/* 00 */ le_uint32_t team_master_guild_card_number = 0;
|
||||
/* 04 */ le_uint32_t team_id = 0;
|
||||
/* 08 */ le_uint32_t unknown_a5 = 0;
|
||||
/* 0C */ le_uint32_t unknown_a6 = 0;
|
||||
/* 10 */ uint8_t privilege_level = 0;
|
||||
/* 11 */ uint8_t team_member_count = 0;
|
||||
/* 12 */ uint8_t unknown_a8 = 0;
|
||||
/* 13 */ uint8_t unknown_a9 = 0;
|
||||
/* 14 */ pstring<TextEncoding::UTF16_ALWAYS_MARKED, 0x10> team_name;
|
||||
/* 34 */
|
||||
|
||||
PSOBBBaseTeamMembership() = default;
|
||||
} __packed_ws__(PSOBBBaseTeamMembership, 0x34);
|
||||
|
||||
struct PSOBBFullTeamMembership {
|
||||
/* 0000 */ PSOBBBaseTeamMembership base;
|
||||
/* 0034 */ parray<le_uint16_t, 0x20 * 0x20> flag_data;
|
||||
/* 0834 */ le_uint32_t reward_flags = 0;
|
||||
/* 0838 */
|
||||
|
||||
PSOBBTeamMembership() = default;
|
||||
} __packed_ws__(PSOBBTeamMembership, 0x838);
|
||||
PSOBBFullTeamMembership() = default;
|
||||
} __packed_ws__(PSOBBFullTeamMembership, 0x838);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// System files
|
||||
@@ -847,7 +854,7 @@ struct PSOCHARFile {
|
||||
/* 0000 */ PSOCommandHeaderBB header; // command = 0x00E7, size = 0x399C, flag = 0
|
||||
/* 0008 */ PSOBBCharacterFile character;
|
||||
/* 2EAC */ PSOBBBaseSystemFile system;
|
||||
/* 3164 */ PSOBBTeamMembership team_membership;
|
||||
/* 3164 */ PSOBBFullTeamMembership team_membership;
|
||||
/* 399C */
|
||||
|
||||
struct LoadSharedResult {
|
||||
@@ -1010,7 +1017,7 @@ struct LegacySavedAccountDataBB { // .nsa file format
|
||||
/* 0040 */ parray<le_uint32_t, 0x001E> blocked_senders;
|
||||
/* 00B8 */ PSOBBGuildCardFile guild_card_file;
|
||||
/* D648 */ PSOBBBaseSystemFile system_file;
|
||||
/* D880 */ PSOBBTeamMembership team_membership;
|
||||
/* D880 */ PSOBBFullTeamMembership team_membership;
|
||||
/* E138 */ le_uint32_t unused = 0;
|
||||
/* E13C */ le_uint32_t option_flags = 0x00040058;
|
||||
/* E140 */ parray<SaveFileShortcutEntryBB, 0x10> shortcuts;
|
||||
|
||||
+42
-9
@@ -623,7 +623,7 @@ void send_system_file_bb(shared_ptr<Client> c) {
|
||||
S_SyncSystemFile_BB_E2 cmd;
|
||||
cmd.system_file = *c->system_file();
|
||||
if (team) {
|
||||
cmd.team_membership = team->membership_for_member(c->login->account->account_id);
|
||||
cmd.team_membership = team->full_membership_for_member(c->login->account->account_id);
|
||||
}
|
||||
send_command_t(c, 0x00E2, 0x00000000, cmd);
|
||||
}
|
||||
@@ -757,7 +757,7 @@ void send_complete_player_bb(shared_ptr<Client> c) {
|
||||
cmd.char_file = *p;
|
||||
cmd.system_file = *sys;
|
||||
if (team) {
|
||||
cmd.team_membership = team->membership_for_member(c->login->account->account_id);
|
||||
cmd.team_membership = team->full_membership_for_member(c->login->account->account_id);
|
||||
}
|
||||
send_command_t(c, 0x00E7, 0x00000000, cmd);
|
||||
}
|
||||
@@ -2358,7 +2358,7 @@ void send_player_join_notification(shared_ptr<Client> c,
|
||||
void send_update_lobby_data_bb(std::shared_ptr<Client> c) {
|
||||
auto l = c->require_lobby();
|
||||
for (auto lc : l->clients) {
|
||||
if (lc) {
|
||||
if (lc && lc->version() == Version::BB_V4) {
|
||||
PlayerLobbyDataBB cmd;
|
||||
populate_lobby_data_for_client(cmd, c, lc);
|
||||
send_command_t(lc, 0x00F0, 0x00000000, cmd);
|
||||
@@ -4122,11 +4122,7 @@ void send_team_membership_info(shared_ptr<Client> c) {
|
||||
auto team = c->team();
|
||||
S_TeamMembershipInformation_BB_12EA cmd;
|
||||
if (team) {
|
||||
cmd.guild_card_number = c->login->account->account_id;
|
||||
cmd.team_id = team->team_id;
|
||||
cmd.privilege_level = team->members.at(c->login->account->account_id).privilege_level();
|
||||
cmd.team_member_count = min<size_t>(team->members.size(), 100);
|
||||
cmd.team_name.encode(team->name);
|
||||
cmd.membership = team->base_membership_for_member(c->login->account->account_id);
|
||||
}
|
||||
send_command_t(c, 0x12EA, 0x00000000, cmd);
|
||||
}
|
||||
@@ -4152,7 +4148,12 @@ static S_TeamInfoForPlayer_BB_13EA_15EA_Entry team_metadata_for_client(shared_pt
|
||||
|
||||
void send_update_team_metadata_for_client(shared_ptr<Client> c) {
|
||||
auto l = c->require_lobby();
|
||||
send_command_t(l, 0x15EA, 0x00000001, team_metadata_for_client(c));
|
||||
auto metadata = team_metadata_for_client(c);
|
||||
for (auto lc : l->clients) {
|
||||
if (lc && lc->version() == Version::BB_V4) {
|
||||
send_command_t(lc, 0x15EA, 0x00000001, metadata);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void send_all_nearby_team_metadatas_to_client(shared_ptr<Client> c, bool is_13EA) {
|
||||
@@ -4312,3 +4313,35 @@ void send_team_reward_list(shared_ptr<Client> c, bool show_purchased) {
|
||||
|
||||
send_command_t_vt(c, show_purchased ? 0x19EA : 0x1AEA, 0x00000000, cmd, entries);
|
||||
}
|
||||
|
||||
void send_team_metadata_change_notifications(
|
||||
shared_ptr<ServerState> s,
|
||||
shared_ptr<const TeamIndex::Team> team,
|
||||
uint8_t what) {
|
||||
using TMC = TeamMetadataChange;
|
||||
for (const auto& it : team->members) {
|
||||
try {
|
||||
auto member_c = s->find_client(nullptr, it.second.account_id);
|
||||
if (what & TMC::TEAM_MASTER) {
|
||||
send_update_lobby_data_bb(member_c);
|
||||
}
|
||||
if (what & (TMC::TEAM_MASTER | TMC::TEAM_NAME)) {
|
||||
send_team_membership_info(member_c);
|
||||
}
|
||||
if (what & (TMC::TEAM_MASTER | TMC::FLAG_DATA | TMC::TEAM_NAME)) {
|
||||
send_update_team_metadata_for_client(member_c);
|
||||
}
|
||||
if (what & TMC::REWARD_FLAGS) {
|
||||
send_update_team_reward_flags(member_c);
|
||||
}
|
||||
} catch (const out_of_range&) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void send_team_membership_change_notifications(shared_ptr<Client> changed_c) {
|
||||
send_update_lobby_data_bb(changed_c);
|
||||
send_update_team_metadata_for_client(changed_c);
|
||||
send_team_membership_info(changed_c);
|
||||
send_update_team_reward_flags(changed_c);
|
||||
}
|
||||
|
||||
@@ -455,3 +455,17 @@ void send_team_member_list(std::shared_ptr<Client> c); // 09EA
|
||||
void send_intra_team_ranking(std::shared_ptr<Client> c); // 18EA
|
||||
void send_team_reward_list(std::shared_ptr<Client> c, bool show_purchased); // 19EA, 1AEA
|
||||
void send_cross_team_ranking(std::shared_ptr<Client> c); // 1CEA
|
||||
|
||||
enum TeamMetadataChange : uint8_t {
|
||||
TEAM_MASTER = 0x01,
|
||||
FLAG_DATA = 0x02,
|
||||
REWARD_FLAGS = 0x04,
|
||||
TEAM_NAME = 0x08,
|
||||
TEAM_DISBANDED = 0xFF,
|
||||
};
|
||||
|
||||
void send_team_metadata_change_notifications(
|
||||
std::shared_ptr<ServerState> s,
|
||||
std::shared_ptr<const TeamIndex::Team> team,
|
||||
uint8_t what);
|
||||
void send_team_membership_change_notifications(std::shared_ptr<Client> changed_c);
|
||||
|
||||
+9
-3
@@ -129,19 +129,25 @@ void TeamIndex::Team::delete_files() const {
|
||||
remove(flag_filename.c_str());
|
||||
}
|
||||
|
||||
PSOBBTeamMembership TeamIndex::Team::membership_for_member(uint32_t account_id) const {
|
||||
PSOBBBaseTeamMembership TeamIndex::Team::base_membership_for_member(uint32_t account_id) const {
|
||||
const auto& m = this->members.at(account_id);
|
||||
|
||||
PSOBBTeamMembership ret;
|
||||
PSOBBBaseTeamMembership ret;
|
||||
ret.team_master_guild_card_number = this->master_account_id;
|
||||
ret.team_id = this->team_id;
|
||||
ret.unknown_a5 = 0;
|
||||
ret.unknown_a6 = 0;
|
||||
ret.privilege_level = m.privilege_level();
|
||||
ret.unknown_a7 = 0;
|
||||
ret.team_member_count = this->members.size();
|
||||
ret.unknown_a8 = 0;
|
||||
ret.unknown_a9 = 0;
|
||||
ret.team_name.encode(this->name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
PSOBBFullTeamMembership TeamIndex::Team::full_membership_for_member(uint32_t account_id) const {
|
||||
PSOBBFullTeamMembership ret;
|
||||
ret.base = base_membership_for_member(account_id);
|
||||
if (this->flag_data) {
|
||||
ret.flag_data = *this->flag_data;
|
||||
} else {
|
||||
|
||||
+2
-1
@@ -79,7 +79,8 @@ public:
|
||||
void save_flag() const;
|
||||
void delete_files() const;
|
||||
|
||||
PSOBBTeamMembership membership_for_member(uint32_t account_id) const;
|
||||
PSOBBBaseTeamMembership base_membership_for_member(uint32_t account_id) const;
|
||||
PSOBBFullTeamMembership full_membership_for_member(uint32_t account_id) const;
|
||||
|
||||
[[nodiscard]] inline bool check_reward_flag(RewardFlag flag) const {
|
||||
return !!(static_cast<uint8_t>(flag) & this->reward_flags);
|
||||
|
||||
Reference in New Issue
Block a user