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.
This commit is contained in:
dongresource 2020-10-02 18:55:54 +02:00
parent 839f9a813c
commit 2fe4b2bac1

View File

@ -225,10 +225,12 @@ int Database::createCharacter(sP_CL2LS_REQ_SAVE_CHAR_NAME* save, int AccountID)
create.y_coordinates = settings::SPAWN_Y; create.y_coordinates = settings::SPAWN_Y;
create.z_coordinates = settings::SPAWN_Z; create.z_coordinates = settings::SPAWN_Z;
create.angle = settings::SPAWN_ANGLE; create.angle = settings::SPAWN_ANGLE;
create.QuestFlag = std::vector<char>();
//set mentor to computress //set mentor to computress
create.Mentor = 5; create.Mentor = 5;
// initialize the quest blob to 128 0-bytes
create.QuestFlag = std::vector<char>(128, 0);
return db.insert(create); return db.insert(create);
} }
@ -402,17 +404,13 @@ Database::DbPlayer Database::playerToDb(Player *player)
result.SkywayLocationFlag2 = player->aSkywayLocationFlag[1]; result.SkywayLocationFlag2 = player->aSkywayLocationFlag[1];
result.CurrentMissionID = player->CurrentMissionID; result.CurrentMissionID = player->CurrentMissionID;
// finished quests: parsing to blob
result.QuestFlag = std::vector<char>();
for (int i=0; i<16; i++)
{
int64_t flag = player->aQuestFlag[i];
appendBlob(&result.QuestFlag, flag);
}
// timestamp // timestamp
result.LastLogin = getTimestamp(); result.LastLogin = getTimestamp();
result.Created = player->creationTime; result.Created = player->creationTime;
// save completed quests
result.QuestFlag = std::vector<char>((char*)player->aQuestFlag, (char*)player->aQuestFlag + 128);
return result; return result;
} }
@ -470,22 +468,14 @@ Player Database::DbToPlayer(DbPlayer player) {
Database::getNanos(&result); Database::getNanos(&result);
Database::getQuests(&result); Database::getQuests(&result);
std::vector<char>::iterator it = player.QuestFlag.begin(); // load completed quests
for (int i = 0; i < 16; i++) memcpy(&result.aQuestFlag, player.QuestFlag.data(), std::min(sizeof(result.aQuestFlag), player.QuestFlag.size()));
{
if (it == player.QuestFlag.end())
break;
result.aQuestFlag[i] = blobToInt64(it);
//move iterator to the next flag
it += 8;
}
return result; return result;
} }
Database::DbPlayer Database::getDbPlayerById(int id) { Database::DbPlayer Database::getDbPlayerById(int id) {
return db.get_all<DbPlayer>(where(c(&DbPlayer::PlayerID) == id)) return db.get_all<DbPlayer>(where(c(&DbPlayer::PlayerID) == id)).front();
.front();
} }
Player Database::getPlayer(int id) { Player Database::getPlayer(int id) {
@ -709,24 +699,3 @@ void Database::getQuests(Player* player) {
} }
#pragma endregion ShardServer #pragma endregion ShardServer
#pragma region parsingBlobs
void Database::appendBlob(std::vector<char> *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<char>::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