implement rename team command
This commit is contained in:
+19
-18
@@ -3335,8 +3335,9 @@ struct C_SetTeamFlag_BB_0FEA {
|
||||
parray<le_uint16_t, 0x20 * 0x20> flag_data;
|
||||
} __packed__;
|
||||
|
||||
// 10EA: Delete team result
|
||||
// No arguments except header.flag
|
||||
// 10EA: Delete team (C->S) and result (S->C)
|
||||
// No arguments (C->S)
|
||||
// No arguments except header.flag (S->C)
|
||||
|
||||
// 11EA: Change team member privilege level
|
||||
// The format below is used only when the client sends this command; when the
|
||||
@@ -3371,16 +3372,17 @@ struct S_TeamMembershipInformation_BB_12EA {
|
||||
struct S_TeamInfoForPlayer_BB_13EA_15EA_Entry {
|
||||
// The client uses the first four of these to determine if the player is in a
|
||||
// team or not - if they are all zero, the player is not in a team.
|
||||
le_uint32_t guild_card_number = 0;
|
||||
le_uint32_t team_id = 0;
|
||||
le_uint32_t unknown_a3 = 0;
|
||||
le_uint32_t unknown_a4 = 0;
|
||||
le_uint32_t privilege_level = 0;
|
||||
pstring<TextEncoding::UTF16, 0x10> team_name;
|
||||
le_uint32_t guild_card_number2 = 0;
|
||||
le_uint32_t lobby_client_id = 0;
|
||||
pstring<TextEncoding::UTF16, 0x10> player_name;
|
||||
parray<le_uint16_t, 0x20 * 0x20> flag_data;
|
||||
/* 0000 */ le_uint32_t guild_card_number = 0;
|
||||
/* 0004 */ le_uint32_t team_id = 0;
|
||||
/* 0008 */ le_uint32_t unknown_a3 = 0;
|
||||
/* 000C */ le_uint32_t unknown_a4 = 0;
|
||||
/* 0010 */ le_uint32_t privilege_level = 0;
|
||||
/* 0014 */ pstring<TextEncoding::UTF16, 0x10> team_name;
|
||||
/* 0034 */ le_uint32_t guild_card_number2 = 0;
|
||||
/* 0038 */ le_uint32_t lobby_client_id = 0;
|
||||
/* 003C */ pstring<TextEncoding::UTF16, 0x10> player_name;
|
||||
/* 005C */ parray<le_uint16_t, 0x20 * 0x20> flag_data;
|
||||
/* 085C */
|
||||
} __packed__;
|
||||
|
||||
// 14EA (C->S): Get team info for lobby players
|
||||
@@ -3455,16 +3457,15 @@ struct S_CrossTeamRanking_BB_1CEA {
|
||||
// 1DEA (S->C): Update team rewards bitmask
|
||||
// header.flag specifies the new rewards bitmask.
|
||||
|
||||
// 1EEA (C->S): Unknown
|
||||
// 1EEA (C->S): Rename team
|
||||
// header.flag is used, but it's unknown what the value means.
|
||||
|
||||
struct C_Unknown_BB_1EEA {
|
||||
pstring<TextEncoding::UTF16, 0x10> unknown_a1;
|
||||
struct C_RenameTeam_BB_1EEA {
|
||||
pstring<TextEncoding::UTF16, 0x10> new_team_name;
|
||||
} __packed__;
|
||||
|
||||
// 1FEA (S->C): Action result
|
||||
// This command behaves exactly like 02EA. This command is presumably the
|
||||
// response to whatever 1EEA does.
|
||||
// 1FEA (S->C): Rename team result
|
||||
// This command behaves like 02EA, but is sent in response to 1EEA instead.
|
||||
|
||||
// 20EA: Unknown
|
||||
// header.flag is used, but no other arguments. When sent by the server,
|
||||
|
||||
@@ -4888,6 +4888,29 @@ static void on_EA_BB(shared_ptr<Client> c, uint16_t command, uint32_t flag, stri
|
||||
case 0x1CEA:
|
||||
send_cross_team_ranking(c);
|
||||
break;
|
||||
case 0x1EEA: {
|
||||
const auto& cmd = check_size_t<C_RenameTeam_BB_1EEA>(data);
|
||||
auto team = c->team();
|
||||
string new_team_name = cmd.new_team_name.decode(c->language());
|
||||
if (!team) {
|
||||
// TODO: What's the right error code to use here?
|
||||
send_command(c, 0x1FEA, 0x00000001);
|
||||
} else if (s->team_index->get_by_name(new_team_name)) {
|
||||
send_command(c, 0x1FEA, 0x00000002);
|
||||
} 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.serial_number);
|
||||
send_update_team_metadata_for_client(c);
|
||||
send_team_membership_info(c);
|
||||
} catch (const out_of_range&) {
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw runtime_error("invalid team command");
|
||||
}
|
||||
|
||||
+11
-1
@@ -292,7 +292,7 @@ vector<shared_ptr<const TeamIndex::Team>> TeamIndex::all() const {
|
||||
return ret;
|
||||
}
|
||||
|
||||
shared_ptr<const TeamIndex::Team> TeamIndex::create(string& name, uint32_t master_serial_number, const string& master_name) {
|
||||
shared_ptr<const TeamIndex::Team> TeamIndex::create(const string& name, uint32_t master_serial_number, const string& master_name) {
|
||||
auto team = make_shared<Team>(this->next_team_id++);
|
||||
save_file(this->directory + "/base.json", JSON::dict({{"NextTeamID", this->next_team_id}}).serialize());
|
||||
|
||||
@@ -316,6 +316,16 @@ void TeamIndex::disband(uint32_t team_id) {
|
||||
team->delete_files();
|
||||
}
|
||||
|
||||
void TeamIndex::rename(uint32_t team_id, const std::string& new_team_name) {
|
||||
auto team = this->id_to_team.at(team_id);
|
||||
if (!this->name_to_team.emplace(new_team_name, team).second) {
|
||||
throw runtime_error("team name is already in use");
|
||||
}
|
||||
this->name_to_team.erase(team->name);
|
||||
team->name = new_team_name;
|
||||
team->save_config();
|
||||
}
|
||||
|
||||
void TeamIndex::add_member(uint32_t team_id, uint32_t serial_number, const string& name) {
|
||||
auto team = this->id_to_team.at(team_id);
|
||||
if (!this->serial_number_to_team.emplace(serial_number, team).second) {
|
||||
|
||||
+2
-1
@@ -127,8 +127,9 @@ public:
|
||||
std::shared_ptr<const Team> get_by_serial_number(uint32_t serial_number) const;
|
||||
std::vector<std::shared_ptr<const Team>> all() const;
|
||||
|
||||
std::shared_ptr<const Team> create(std::string& name, uint32_t master_serial_number, const std::string& master_name);
|
||||
std::shared_ptr<const Team> create(const std::string& name, uint32_t master_serial_number, const std::string& master_name);
|
||||
void disband(uint32_t team_id);
|
||||
void rename(uint32_t team_id, const std::string& new_name);
|
||||
|
||||
void add_member(uint32_t team_id, uint32_t serial_number, const std::string& name);
|
||||
void remove_member(uint32_t serial_number);
|
||||
|
||||
Reference in New Issue
Block a user