From 57ea246dd77ca8e76de136c04b96bf1cadbd8dfe Mon Sep 17 00:00:00 2001 From: Martin Michelsen Date: Wed, 1 May 2024 23:26:42 -0700 Subject: [PATCH] prep for $loadchar on xbox --- src/ChatCommands.cc | 4 ++-- src/ItemData.cc | 3 +++ src/PlayerInventory.hh | 5 ++++- src/SaveFileFormats.cc | 4 ++++ 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/ChatCommands.cc b/src/ChatCommands.cc index d48136f9..5ca9ec3c 100644 --- a/src/ChatCommands.cc +++ b/src/ChatCommands.cc @@ -1469,8 +1469,8 @@ static void server_command_savechar(shared_ptr c, const std::string& arg } static void server_command_loadchar(shared_ptr c, const std::string& args) { - if (!is_v1_or_v2(c->version()) && c->version() != Version::GC_V3) { - send_text_message(c, "$C7This command can only\nbe used on v1, v2,\nand GC"); + if (!is_v1_or_v2(c->version()) && (c->version() != Version::GC_V3) && (c->version() != Version::XB_V3)) { + send_text_message(c, "$C7This command cannot\nbe used on your\ngame version"); return; } if (c->login->account->check_flag(Account::Flag::IS_SHARED_ACCOUNT)) { diff --git a/src/ItemData.cc b/src/ItemData.cc index d234d8ed..aac18eef 100644 --- a/src/ItemData.cc +++ b/src/ItemData.cc @@ -436,6 +436,9 @@ void ItemData::encode_for_version(Version to_version, shared_ptrdata1[0]) { case 0x00: if (should_encode_v2_data && (this->data1[1] > 0x26)) { + if (!item_parameter_table) { + throw logic_error("item parameter table is required to encode v2 data"); + } if (this->data1[1] < 0x89) { this->data1[5] = this->data1[1]; this->data1[1] = item_parameter_table->get_weapon_v1_replacement(this->data1[1]); diff --git a/src/PlayerInventory.hh b/src/PlayerInventory.hh index a0ef6e85..61f6322b 100644 --- a/src/PlayerInventory.hh +++ b/src/PlayerInventory.hh @@ -47,12 +47,14 @@ class ItemParameterTable; template struct PlayerInventoryItemT { + using U32T = typename std::conditional::type; + /* 00 */ uint8_t present = 0; /* 01 */ uint8_t unknown_a1 = 0; // See note above about these fields /* 02 */ uint8_t extension_data1 = 0; /* 03 */ uint8_t extension_data2 = 0; - /* 04 */ le_uint32_t flags = 0; // 8 = equipped + /* 04 */ U32T flags = 0; // 8 = equipped /* 08 */ ItemData data; /* 1C */ @@ -74,6 +76,7 @@ struct PlayerInventoryItemT { ret.extension_data2 = this->extension_data2; ret.flags = this->flags.load(); ret.data = this->data; + ret.data.id.store_raw(bswap32(ret.data.id.load_raw())); return ret; } } __packed__; diff --git a/src/SaveFileFormats.cc b/src/SaveFileFormats.cc index ec043b2f..ea77f7f9 100644 --- a/src/SaveFileFormats.cc +++ b/src/SaveFileFormats.cc @@ -421,6 +421,7 @@ shared_ptr PSOBBCharacterFile::create_from_preview( shared_ptr PSOBBCharacterFile::create_from_gc(const PSOGCCharacterFile::Character& gc) { auto ret = make_shared(); ret->inventory = gc.inventory; + ret->inventory.decode_from_client(Version::GC_V3); uint8_t language = ret->inventory.language; ret->disp = gc.disp.to_bb(language, language); ret->creation_timestamp = gc.creation_timestamp.load(); @@ -462,6 +463,7 @@ shared_ptr PSOBBCharacterFile::create_from_gc(const PSOGCCha shared_ptr PSOBBCharacterFile::create_from_xb(const PSOXBCharacterFileCharacter& xb) { auto ret = make_shared(); ret->inventory = xb.inventory; + ret->inventory.decode_from_client(Version::XB_V3); uint8_t language = ret->inventory.language; ret->disp = xb.disp.to_bb(language, language); ret->creation_timestamp = xb.creation_timestamp.load(); @@ -505,6 +507,7 @@ PSOGCCharacterFile::Character PSOBBCharacterFile::to_gc() const { PSOGCCharacterFile::Character ret; ret.inventory = this->inventory; + ret.inventory.encode_for_client(Version::GC_V3, nullptr); ret.disp = this->disp.to_dcpcv3(language, language); ret.creation_timestamp = this->creation_timestamp.load(); ret.play_time_seconds = this->play_time_seconds.load(); @@ -547,6 +550,7 @@ PSOXBCharacterFileCharacter PSOBBCharacterFile::to_xb(uint64_t xb_user_id) const PSOXBCharacterFileCharacter ret; ret.inventory = this->inventory; + ret.inventory.encode_for_client(Version::XB_V3, nullptr); ret.disp = this->disp.to_dcpcv3(language, language); ret.creation_timestamp = this->creation_timestamp.load(); ret.play_time_seconds = this->play_time_seconds.load();