From 2fe4b2bac1b0e093efcb5960f6665b431304097a Mon Sep 17 00:00:00 2001 From: dongresource Date: Fri, 2 Oct 2020 18:55:54 +0200 Subject: [PATCH] Rewrote quest bitfield char[128] <-> int64_t[16] logic. * This should fix the problem with some completed missions being forgotten * We no longer explicitly shuffle bits around. Instead we just cast and copy the full buffer * Character creation initializes the quest blob with 128 zeroes, since that happens later on anyway, but we're robust against different quest flag sizes just in case * I haven't looked at the actual flag-setting logic, so if the bug is in there, this won't fix that one, but it does fix the one where the least significant bit of every 64-bit flag doesn't get saved to the blob * I'm still cautious about storing the various bitfields as signed values even though the client does it that way, since while shifting into the sign bit is undefined behaviour in C/C++, it may *not* be in C#. And of course the client implementation may just be buggy as well. --- src/Database.cpp | 51 ++++++++++-------------------------------------- 1 file changed, 10 insertions(+), 41 deletions(-) diff --git a/src/Database.cpp b/src/Database.cpp index 21ed193..8480f66 100644 --- a/src/Database.cpp +++ b/src/Database.cpp @@ -225,10 +225,12 @@ int Database::createCharacter(sP_CL2LS_REQ_SAVE_CHAR_NAME* save, int AccountID) create.y_coordinates = settings::SPAWN_Y; create.z_coordinates = settings::SPAWN_Z; create.angle = settings::SPAWN_ANGLE; - create.QuestFlag = std::vector(); //set mentor to computress create.Mentor = 5; + // initialize the quest blob to 128 0-bytes + create.QuestFlag = std::vector(128, 0); + return db.insert(create); } @@ -402,17 +404,13 @@ Database::DbPlayer Database::playerToDb(Player *player) result.SkywayLocationFlag2 = player->aSkywayLocationFlag[1]; result.CurrentMissionID = player->CurrentMissionID; - // finished quests: parsing to blob - result.QuestFlag = std::vector(); - for (int i=0; i<16; i++) - { - int64_t flag = player->aQuestFlag[i]; - appendBlob(&result.QuestFlag, flag); - } - //timestamp + // timestamp result.LastLogin = getTimestamp(); result.Created = player->creationTime; + // save completed quests + result.QuestFlag = std::vector((char*)player->aQuestFlag, (char*)player->aQuestFlag + 128); + return result; } @@ -470,22 +468,14 @@ Player Database::DbToPlayer(DbPlayer player) { Database::getNanos(&result); Database::getQuests(&result); - std::vector::iterator it = player.QuestFlag.begin(); - for (int i = 0; i < 16; i++) - { - if (it == player.QuestFlag.end()) - break; - result.aQuestFlag[i] = blobToInt64(it); - //move iterator to the next flag - it += 8; - } + // load completed quests + memcpy(&result.aQuestFlag, player.QuestFlag.data(), std::min(sizeof(result.aQuestFlag), player.QuestFlag.size())); return result; } Database::DbPlayer Database::getDbPlayerById(int id) { - return db.get_all(where(c(&DbPlayer::PlayerID) == id)) - .front(); + return db.get_all(where(c(&DbPlayer::PlayerID) == id)).front(); } Player Database::getPlayer(int id) { @@ -709,24 +699,3 @@ void Database::getQuests(Player* player) { } #pragma endregion ShardServer - -#pragma region parsingBlobs - -void Database::appendBlob(std::vector *blob, int64_t input) { - for (int i = 0; i < 8; i++) { - char toadd = (input >> (8 * (7 - i))); - blob->push_back(toadd); - } -} - -int64_t Database::blobToInt64(std::vector::iterator it) { - int64_t result = 0; - for (int i = 0; i < 8; i++) { - int64_t toAdd = ((int64_t)*it << (8 * (7 - i))); - result += toAdd; - it++; - } - return result; -} - -#pragma endregion parsingBlobs