implement savechar/loadchar on DCv2 and Xbox
This commit is contained in:
+17
-4
@@ -1469,7 +1469,10 @@ static void server_command_savechar(shared_ptr<Client> c, const std::string& arg
|
||||
}
|
||||
|
||||
static void server_command_loadchar(shared_ptr<Client> c, const std::string& args) {
|
||||
if (!is_v1_or_v2(c->version()) && (c->version() != Version::GC_V3) && (c->version() != Version::XB_V3)) {
|
||||
if (!is_v1_or_v2(c->version()) &&
|
||||
(c->version() != Version::GC_V3) &&
|
||||
(c->version() != Version::XB_V3) &&
|
||||
(c->version() != Version::BB_V4)) {
|
||||
send_text_message(c, "$C7This command cannot\nbe used on your\ngame version");
|
||||
return;
|
||||
}
|
||||
@@ -1487,12 +1490,19 @@ static void server_command_loadchar(shared_ptr<Client> c, const std::string& arg
|
||||
}
|
||||
c->load_backup_character(c->login->account->account_id, index);
|
||||
|
||||
if ((c->version() == Version::GC_V3) || (c->version() == Version::XB_V3)) {
|
||||
if (c->version() == Version::BB_V4) {
|
||||
// On BB, it suffices to simply send the character file again
|
||||
auto s = c->require_server_state();
|
||||
send_complete_player_bb(c);
|
||||
send_player_leave_notification(l, c->lobby_client_id);
|
||||
s->send_lobby_join_notifications(l, c);
|
||||
|
||||
} else if ((c->version() == Version::DC_V2) || (c->version() == Version::GC_V3) || (c->version() == Version::XB_V3)) {
|
||||
// TODO: Support extended player info on other versions
|
||||
auto s = c->require_server_state();
|
||||
if (c->config.check_flag(Client::Flag::NO_SEND_FUNCTION_CALL) ||
|
||||
c->config.check_flag(Client::Flag::SEND_FUNCTION_CALL_CHECKSUM_ONLY)) {
|
||||
send_text_message_printf(c, "Can\'t load character\ndata on PSO Plus");
|
||||
send_text_message_printf(c, "Can\'t load character\ndata on this game\nversion");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1525,7 +1535,10 @@ static void server_command_loadchar(shared_ptr<Client> c, const std::string& arg
|
||||
});
|
||||
};
|
||||
|
||||
if (c->version() == Version::GC_V3) {
|
||||
if (c->version() == Version::DC_V2) {
|
||||
auto dc_char = make_shared<PSODCV2CharacterFile>(c->character()->to_dc_v2());
|
||||
send_set_extended_player_info.operator()<PSODCV2CharacterFile>(c, dc_char);
|
||||
} else if (c->version() == Version::GC_V3) {
|
||||
auto gc_char = make_shared<PSOGCCharacterFile::Character>(c->character()->to_gc());
|
||||
send_set_extended_player_info.operator()<PSOGCCharacterFile::Character>(c, gc_char);
|
||||
} else if (c->version() == Version::XB_V3) {
|
||||
|
||||
@@ -600,6 +600,43 @@ shared_ptr<PSOBBCharacterFile> PSOBBCharacterFile::create_from_xb(const PSOXBCha
|
||||
return ret;
|
||||
}
|
||||
|
||||
PSODCV2CharacterFile PSOBBCharacterFile::to_dc_v2() const {
|
||||
uint8_t language = this->inventory.language;
|
||||
|
||||
PSODCV2CharacterFile ret;
|
||||
ret.inventory = this->inventory;
|
||||
ret.inventory.encode_for_client(Version::DC_V2, nullptr);
|
||||
ret.disp = this->disp.to_dcpcv3<false>(language, language);
|
||||
ret.disp.visual.enforce_lobby_join_limits_for_version(Version::DC_V2);
|
||||
ret.creation_timestamp = this->creation_timestamp.load();
|
||||
ret.play_time_seconds = this->play_time_seconds.load();
|
||||
ret.option_flags = this->option_flags.load();
|
||||
ret.save_count = this->save_count.load();
|
||||
ret.quest_flags = this->quest_flags;
|
||||
ret.bank = this->bank;
|
||||
ret.guild_card = this->guild_card;
|
||||
for (size_t z = 0; z < std::min<size_t>(ret.symbol_chats.size(), this->symbol_chats.size()); z++) {
|
||||
auto& ret_sc = ret.symbol_chats[z];
|
||||
const auto& gc_sc = this->symbol_chats[z];
|
||||
ret_sc.present = gc_sc.present.load();
|
||||
ret_sc.name.encode(gc_sc.name.decode(language), language);
|
||||
ret_sc.spec = gc_sc.spec;
|
||||
}
|
||||
for (size_t z = 0; z < std::min<size_t>(ret.shortcuts.size(), this->shortcuts.size()); z++) {
|
||||
ret.shortcuts[z] = this->shortcuts[z].convert<false, TextEncoding::MARKED, 0x3C>(language);
|
||||
}
|
||||
ret.battle_records = this->battle_records;
|
||||
ret.challenge_records = this->challenge_records;
|
||||
for (size_t z = 0; z < std::min<size_t>(ret.tech_menu_shortcut_entries.size(), this->tech_menu_shortcut_entries.size()); z++) {
|
||||
ret.tech_menu_shortcut_entries[z] = this->tech_menu_shortcut_entries[z].load();
|
||||
}
|
||||
for (size_t z = 0; z < 5; z++) {
|
||||
ret.choice_search_config[z * 2] = this->choice_search_config.entries[z].parent_choice_id.load();
|
||||
ret.choice_search_config[z * 2 + 1] = this->choice_search_config.entries[z].choice_id.load();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
PSOGCCharacterFile::Character PSOBBCharacterFile::to_gc() const {
|
||||
uint8_t language = this->inventory.language;
|
||||
|
||||
@@ -607,6 +644,7 @@ PSOGCCharacterFile::Character PSOBBCharacterFile::to_gc() const {
|
||||
ret.inventory = this->inventory;
|
||||
ret.inventory.encode_for_client(Version::GC_V3, nullptr);
|
||||
ret.disp = this->disp.to_dcpcv3<true>(language, language);
|
||||
ret.disp.visual.enforce_lobby_join_limits_for_version(Version::GC_V3);
|
||||
ret.creation_timestamp = this->creation_timestamp.load();
|
||||
ret.play_time_seconds = this->play_time_seconds.load();
|
||||
ret.option_flags = this->option_flags.load();
|
||||
@@ -650,6 +688,7 @@ PSOXBCharacterFileCharacter PSOBBCharacterFile::to_xb(uint64_t xb_user_id) const
|
||||
ret.inventory = this->inventory;
|
||||
ret.inventory.encode_for_client(Version::XB_V3, nullptr);
|
||||
ret.disp = this->disp.to_dcpcv3<false>(language, language);
|
||||
ret.disp.visual.enforce_lobby_join_limits_for_version(Version::XB_V3);
|
||||
ret.creation_timestamp = this->creation_timestamp.load();
|
||||
ret.play_time_seconds = this->play_time_seconds.load();
|
||||
ret.option_flags = this->option_flags.load();
|
||||
|
||||
@@ -649,6 +649,10 @@ struct PSOBBCharacterFile {
|
||||
static std::shared_ptr<PSOBBCharacterFile> create_from_gc(const PSOGCCharacterFile::Character& gc);
|
||||
static std::shared_ptr<PSOBBCharacterFile> create_from_xb(const PSOXBCharacterFileCharacter& xb);
|
||||
|
||||
PSODCV2CharacterFile to_dc_v2() const;
|
||||
PSOGCCharacterFile::Character to_gc() const;
|
||||
PSOXBCharacterFileCharacter to_xb(uint64_t xb_user_id) const;
|
||||
|
||||
void add_item(const ItemData& item, const ItemData::StackLimits& limits);
|
||||
ItemData remove_item(uint32_t item_id, uint32_t amount, const ItemData::StackLimits& limits);
|
||||
void add_meseta(uint32_t amount);
|
||||
@@ -670,9 +674,6 @@ struct PSOBBCharacterFile {
|
||||
uint8_t get_material_usage(MaterialType which) const;
|
||||
void set_material_usage(MaterialType which, uint8_t usage);
|
||||
void clear_all_material_usage();
|
||||
|
||||
PSOGCCharacterFile::Character to_gc() const;
|
||||
PSOXBCharacterFileCharacter to_xb(uint64_t xb_user_id) const;
|
||||
} __packed_ws__(PSOBBCharacterFile, 0x2EA4);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Reference in New Issue
Block a user