implement rename team command

This commit is contained in:
Martin Michelsen
2023-12-25 11:10:37 -08:00
parent 206552ed63
commit a8061efc0d
4 changed files with 55 additions and 20 deletions
+19 -18
View File
@@ -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,
+23
View File
@@ -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
View File
@@ -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
View File
@@ -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);