rewrite $bbchar implementation

This commit is contained in:
Martin Michelsen
2023-12-04 19:38:42 -08:00
parent 2360beb77b
commit 330dbecada
10 changed files with 80 additions and 61 deletions
+1 -3
View File
@@ -1029,14 +1029,12 @@ static void server_command_convert_char_to_bb(shared_ptr<Client> c, const std::s
}
try {
s->license_index->verify_bb(tokens[0].c_str(), tokens[1].c_str());
c->pending_bb_save_license = s->license_index->verify_bb(tokens[0].c_str(), tokens[1].c_str());
} catch (const exception& e) {
send_text_message_printf(c, "$C6Login failed: %s", e.what());
return;
}
c->pending_bb_save_username = tokens[0];
// Request the player data. The client will respond with a 61, and the handler
// for that command will execute the conversion
send_get_player_info(c);
+1 -1
View File
@@ -201,7 +201,7 @@ struct Client : public std::enable_shared_from_this<Client> {
uint32_t next_exp_value; // next EXP value to give
G_SwitchStateChanged_6x05 last_switch_enabled_command;
bool can_chat;
std::string pending_bb_save_username;
std::shared_ptr<License> pending_bb_save_license;
uint8_t pending_bb_save_character_index;
std::deque<std::function<void(uint32_t, uint32_t)>> function_call_response_queue;
+11 -1
View File
@@ -302,6 +302,16 @@ string ClientGameData::system_filename() const {
return string_printf("system/players/system_%s.psosys", this->bb_username.c_str());
}
string ClientGameData::character_filename(const std::string& bb_username, int8_t index) {
if (bb_username.empty()) {
throw logic_error("non-BB players do not have character data");
}
if (index < 0) {
throw logic_error("character index is not set");
}
return string_printf("system/players/player_%s_%hhd.psochar", bb_username.c_str(), index);
}
string ClientGameData::character_filename(int8_t index) const {
if (this->bb_username.empty()) {
throw logic_error("non-BB players do not have character data");
@@ -312,7 +322,7 @@ string ClientGameData::character_filename(int8_t index) const {
if (index < 0) {
throw logic_error("character index is not set");
}
return string_printf("system/players/player_%s_%hhd.psochar", this->bb_username.c_str(), index);
return this->character_filename(this->bb_username, index);
}
string ClientGameData::guild_card_filename() const {
+9 -8
View File
@@ -112,6 +112,15 @@ public:
const PlayerDispDataBBPreview& preview,
std::shared_ptr<const LevelTable> level_table);
std::string system_filename() const;
static std::string character_filename(const std::string& bb_username, int8_t index);
std::string character_filename(int8_t index = -1) const;
std::string guild_card_filename() const;
std::string shared_bank_filename() const;
std::string legacy_player_filename() const;
std::string legacy_account_filename() const;
void save_all();
void save_system_file() const;
static void save_character_file(
@@ -147,12 +156,4 @@ private:
void save_and_clear_external_bank();
void load_all_files();
std::string system_filename() const;
std::string character_filename(int8_t index = -1) const;
std::string guild_card_filename() const;
std::string shared_bank_filename() const;
std::string legacy_player_filename() const;
std::string legacy_account_filename() const;
};
-7
View File
@@ -194,13 +194,6 @@ PlayerDispDataBBPreview PlayerDispDataBB::to_preview() const {
return pre;
}
void PlayerDispDataBB::apply_preview(const PlayerDispDataBBPreview& pre) {
this->stats.level = pre.level;
this->stats.experience = pre.experience;
this->visual = pre.visual;
this->name = pre.name;
}
void PlayerDispDataBB::apply_dressing_room(const PlayerDispDataBBPreview& pre) {
this->visual.name_color = pre.visual.name_color;
this->visual.extra_model = pre.visual.extra_model;
+1 -1
View File
@@ -112,7 +112,7 @@ struct PlayerDispDataBB;
struct PlayerVisualConfig {
/* 00 */ pstring<TextEncoding::ASCII, 0x10> name;
/* 10 */ parray<uint8_t, 8> unknown_a2;
/* 18 */ le_uint32_t name_color = 0x00000000; // ARGB
/* 18 */ le_uint32_t name_color = 0xFFFFFFFF; // ARGB
/* 1C */ uint8_t extra_model = 0;
/* 1D */ parray<uint8_t, 0x0F> unused;
// See compute_name_color_checksum for details on how this is computed. This
+33 -33
View File
@@ -2973,42 +2973,42 @@ static void on_61_98(shared_ptr<Client> c, uint16_t command, uint32_t flag, stri
s->remove_client_from_lobby(c);
} else if (command == 0x61) {
if (!c->pending_bb_save_username.empty()) {
string prev_bb_username = c->game_data.get_bb_username();
int8_t prev_bb_character_index = c->game_data.bb_character_index;
if (c->pending_bb_save_license) {
shared_ptr<License> dest_license = c->pending_bb_save_license;
c->pending_bb_save_license.reset();
c->game_data.set_bb_username(c->pending_bb_save_username);
c->game_data.bb_character_index = c->pending_bb_save_character_index;
string filename = ClientGameData::character_filename(dest_license->bb_username, c->pending_bb_save_character_index);
if (s->player_files_manager->get_character(filename)) {
send_text_message(c, "$C6The target player\nis currently loaded.\nSign off in Blue\nBurst and try again.");
// Update a few fields for BB
const auto& p = c->game_data.character();
uint8_t prev_version = p->disp.visual.version;
p->disp.visual.version = 4;
uint32_t prev_name_color_checksum = p->disp.visual.name_color_checksum;
p->disp.visual.name_color_checksum = 0x00000000;
bool failure = false;
try {
c->game_data.save_character_file();
} catch (const exception& e) {
send_text_message_printf(c, "$C6PSOBB player data could\nnot be saved:\n%s", e.what());
failure = true;
} else {
auto bb_player = PSOBBCharacterFile::create_from_config(
dest_license->serial_number,
c->language(),
player->disp.visual,
player->disp.name.decode(c->language()),
s->level_table);
bb_player->disp.visual.version = 4;
bb_player->disp.visual.name_color_checksum = 0x00000000;
bb_player->inventory = player->inventory;
bb_player->disp.stats.advance_to_level(bb_player->disp.visual.char_class, player->disp.stats.level, s->level_table);
bb_player->disp.stats.experience = player->disp.stats.experience;
bb_player->disp.technique_levels_v1 = player->disp.technique_levels_v1;
bb_player->auto_reply = player->auto_reply;
bb_player->info_board = player->info_board;
bb_player->battle_records = player->battle_records;
bb_player->challenge_records = player->challenge_records;
bb_player->choice_search_config = player->choice_search_config;
try {
ClientGameData::save_character_file(filename, c->game_data.system(), bb_player);
send_text_message_printf(c,
"$C6BB player data saved\nas player %hhu for user\n%s",
static_cast<uint8_t>(c->pending_bb_save_character_index + 1),
dest_license->bb_username.c_str());
} catch (const exception& e) {
send_text_message_printf(c, "$C6PSOBB player data could\nnot be saved:\n%s", e.what());
}
}
p->disp.visual.version = prev_version;
p->disp.visual.name_color_checksum = prev_name_color_checksum;
if (!failure) {
send_text_message_printf(c,
"$C6BB player data saved\nas player %hhu for user\n%s",
static_cast<uint8_t>(c->pending_bb_save_character_index + 1),
c->pending_bb_save_username.c_str());
}
c->game_data.set_bb_username(prev_bb_username);
c->game_data.bb_character_index = prev_bb_character_index;
c->pending_bb_save_username.clear();
}
// We use 61 during the lobby server init sequence to trigger joining an
+17 -6
View File
@@ -208,10 +208,11 @@ PSOBBBaseSystemFile::PSOBBBaseSystemFile() {
}
}
shared_ptr<PSOBBCharacterFile> PSOBBCharacterFile::create_from_preview(
shared_ptr<PSOBBCharacterFile> PSOBBCharacterFile::create_from_config(
uint32_t guild_card_number,
uint8_t language,
const PlayerDispDataBBPreview& preview,
const PlayerVisualConfig& visual,
const std::string& name,
shared_ptr<const LevelTable> level_table) {
static const array<array<PlayerInventoryItem, 5>, 12> initial_inventory{{
{
@@ -300,7 +301,7 @@ shared_ptr<PSOBBCharacterFile> PSOBBCharacterFile::create_from_preview(
},
}};
array<uint8_t, 0xE8> config_hunter_ranger{
static const array<uint8_t, 0xE8> config_hunter_ranger{
{0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -316,7 +317,7 @@ shared_ptr<PSOBBCharacterFile> PSOBBCharacterFile::create_from_preview(
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
array<uint8_t, 0xE8> config_force{
static const array<uint8_t, 0xE8> config_force{
{0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -334,8 +335,10 @@ shared_ptr<PSOBBCharacterFile> PSOBBCharacterFile::create_from_preview(
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
auto ret = make_shared<PSOBBCharacterFile>();
ret->disp.visual = visual;
ret->disp.name.encode(name, language);
const auto& initial_items = initial_inventory.at(preview.visual.char_class);
const auto& initial_items = initial_inventory.at(visual.char_class);
ret->inventory.num_items = initial_items.size();
for (size_t z = 0; z < initial_items.size(); z++) {
ret->inventory.items[z] = initial_items[z];
@@ -347,7 +350,6 @@ shared_ptr<PSOBBCharacterFile> PSOBBCharacterFile::create_from_preview(
ret->disp.config[z] = config[z];
}
ret->disp.apply_preview(preview);
ret->disp.stats.reset_to_base(ret->disp.visual.char_class, level_table);
ret->disp.technique_levels_v1.clear(0xFF);
if (ret->disp.visual.class_flags & 0x80) {
@@ -369,6 +371,15 @@ shared_ptr<PSOBBCharacterFile> PSOBBCharacterFile::create_from_preview(
return ret;
}
shared_ptr<PSOBBCharacterFile> PSOBBCharacterFile::create_from_preview(
uint32_t guild_card_number,
uint8_t language,
const PlayerDispDataBBPreview& preview,
shared_ptr<const LevelTable> level_table) {
return PSOBBCharacterFile::create_from_config(
guild_card_number, language, preview.visual, preview.name.decode(language), level_table);
}
PSOBBCharacterFile::SymbolChatEntry PSOBBCharacterFile::DefaultSymbolChatEntry::to_entry() const {
SymbolChatEntry ret;
ret.present = 1;
+6
View File
@@ -219,6 +219,12 @@ struct PSOBBCharacterFile {
PSOBBCharacterFile() = default;
static std::shared_ptr<PSOBBCharacterFile> create_from_config(
uint32_t guild_card_number,
uint8_t language,
const PlayerVisualConfig& visual,
const std::string& name,
std::shared_ptr<const LevelTable> level_table);
static std::shared_ptr<PSOBBCharacterFile> create_from_preview(
uint32_t guild_card_number,
uint8_t language,