Properly implement first use flags

This commit is contained in:
Kamil 2020-12-07 19:01:29 +01:00 committed by Gent S
parent 66ecc45fce
commit bd3a91e530
4 changed files with 47 additions and 19 deletions

View File

@ -214,6 +214,7 @@ void Database::createTables() {
"WarpLocationFlag" INTEGER DEFAULT 0 NOT NULL,
"SkywayLocationFlag" BLOB NOT NULL,
"CurrentMissionID" INTEGER DEFAULT 0 NOT NULL,
"FirstUseFlag" BLOB NOT NULL,
PRIMARY KEY("PlayerID" AUTOINCREMENT),
FOREIGN KEY("AccountID") REFERENCES "Accounts"("AccountID") ON DELETE CASCADE,
UNIQUE ("AccountID", "Slot"),
@ -512,8 +513,8 @@ int Database::createCharacter(sP_CL2LS_REQ_SAVE_CHAR_NAME* save, int AccountID)
const char* sql = R"(
INSERT INTO "Players"
("AccountID", "Slot", "Firstname", "LastName", "XCoordinates" , "YCoordinates", "ZCoordinates", "Angle",
"HP", "NameCheck", "Quests", "SkywayLocationFlag")
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
"HP", "NameCheck", "Quests", "SkywayLocationFlag", "FirstUseFlag")
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
)";
sqlite3_stmt* stmt;
std::string firstName = U16toU8(save->szFirstName);
@ -535,9 +536,10 @@ int Database::createCharacter(sP_CL2LS_REQ_SAVE_CHAR_NAME* save, int AccountID)
sqlite3_bind_int(stmt, 10, nameCheck);
// blobs
unsigned char blobBuffer[128] = { 0 };
sqlite3_bind_blob(stmt, 11, blobBuffer, 128, 0);
sqlite3_bind_blob(stmt, 12, blobBuffer, 16, 0);
unsigned char blobBuffer[sizeof(Player::aQuestFlag)] = { 0 };
sqlite3_bind_blob(stmt, 11, blobBuffer, sizeof(Player::aQuestFlag), 0);
sqlite3_bind_blob(stmt, 12, blobBuffer, sizeof(Player::aSkywayLocationFlag), 0);
sqlite3_bind_blob(stmt, 13, blobBuffer, sizeof(Player::iFirstUseFlag), 0);
int rc = sqlite3_step(stmt);
sqlite3_finalize(stmt);
@ -932,7 +934,7 @@ void Database::getPlayer(Player* plr, int id) {
p.XCoordinates, p.YCoordinates, p.ZCoordinates, p.NameCheck,
p.Angle, p.HP, acc.AccountLevel, p.FusionMatter, p.Taros, p.Quests,
p.BatteryW, p.BatteryN, p.Mentor, p.WarpLocationFlag,
p.SkywayLocationFlag, p.CurrentMissionID,
p.SkywayLocationFlag, p.CurrentMissionID, p.FirstUseFlag,
a.Body, a.EyeColor, a.FaceStyle, a.Gender, a.HairColor, a.HairStyle, a.Height, a.SkinColor
FROM "Players" as p
INNER JOIN "Appearances" as a ON p.PlayerID = a.PlayerID
@ -992,14 +994,16 @@ void Database::getPlayer(Player* plr, int id) {
plr->CurrentMissionID = sqlite3_column_int(stmt, 26);
plr->PCStyle.iBody = sqlite3_column_int(stmt, 27);
plr->PCStyle.iEyeColor = sqlite3_column_int(stmt, 28);
plr->PCStyle.iFaceStyle = sqlite3_column_int(stmt, 29);
plr->PCStyle.iGender = sqlite3_column_int(stmt, 30);
plr->PCStyle.iHairColor = sqlite3_column_int(stmt, 31);
plr->PCStyle.iHairStyle = sqlite3_column_int(stmt, 32);
plr->PCStyle.iHeight = sqlite3_column_int(stmt, 33);
plr->PCStyle.iSkinColor = sqlite3_column_int(stmt, 34);
memcpy(plr->iFirstUseFlag, sqlite3_column_blob(stmt, 27), sizeof(plr->iFirstUseFlag));
plr->PCStyle.iBody = sqlite3_column_int(stmt, 28);
plr->PCStyle.iEyeColor = sqlite3_column_int(stmt, 29);
plr->PCStyle.iFaceStyle = sqlite3_column_int(stmt, 30);
plr->PCStyle.iGender = sqlite3_column_int(stmt, 31);
plr->PCStyle.iHairColor = sqlite3_column_int(stmt, 32);
plr->PCStyle.iHairStyle = sqlite3_column_int(stmt, 33);
plr->PCStyle.iHeight = sqlite3_column_int(stmt, 34);
plr->PCStyle.iSkinColor = sqlite3_column_int(stmt, 35);
// get inventory
@ -1148,7 +1152,7 @@ void Database::updatePlayer(Player *player) {
"Angle" = ?, "HP" = ?, "FusionMatter" = ?, "Taros" = ?, "Quests" = ?,
"BatteryW" = ?, "BatteryN" = ?, "WarplocationFlag" = ?,
"SkywayLocationFlag" = ?, "CurrentMissionID" = ?,
"PayZoneFlag" = ?
"PayZoneFlag" = ?, "FirstUseFlag" = ?
WHERE "PlayerID" = ?
)";
sqlite3_stmt* stmt;
@ -1181,7 +1185,8 @@ void Database::updatePlayer(Player *player) {
sqlite3_bind_blob(stmt, 16, player->aSkywayLocationFlag, sizeof(player->aSkywayLocationFlag), 0);
sqlite3_bind_int(stmt, 17, player->CurrentMissionID);
sqlite3_bind_int(stmt, 18, player->PCStyle2.iPayzoneFlag);
sqlite3_bind_int(stmt, 19, player->iID);
sqlite3_bind_blob(stmt, 19, player->iFirstUseFlag, sizeof(player->iFirstUseFlag), 0);
sqlite3_bind_int(stmt, 20, player->iID);
int rc = sqlite3_step(stmt);
if (rc != SQLITE_DONE) {

View File

@ -79,6 +79,8 @@ struct Player {
int64_t buddyIDs[50];
bool isBuddyBlocked[50];
uint64_t iFirstUseFlag[2];
ChunkPos chunkPos;
std::set<Chunk*>* viewableChunks;
time_t lastHeartbeat;

View File

@ -45,6 +45,7 @@ void PlayerManager::init() {
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_VEHICLE_ON, enterPlayerVehicle);
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_VEHICLE_OFF, exitPlayerVehicle);
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_CHANGE_MENTOR, changePlayerGuide);
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_FIRST_USE_FLAG_SET, setFirstUseFlag);
}
void PlayerManager::addPlayer(CNSocket* key, Player plr) {
@ -257,9 +258,9 @@ void PlayerManager::enterPlayer(CNSocket* sock, CNPacketData* data) {
response.PCLoadData2CL.aQuestFlag[i] = plr.aQuestFlag[i];
}
// shut Computress up
response.PCLoadData2CL.iFirstUseFlag1 = UINT64_MAX;
response.PCLoadData2CL.iFirstUseFlag2 = UINT64_MAX;
// Computress tips
response.PCLoadData2CL.iFirstUseFlag1 = plr.iFirstUseFlag[0];
response.PCLoadData2CL.iFirstUseFlag2 = plr.iFirstUseFlag[1];
plr.SerialKey = enter->iEnterSerialKey;
plr.instanceID = INSTANCE_OVERWORLD; // the player should never be in an instance on enter
@ -858,6 +859,24 @@ void PlayerManager::changePlayerGuide(CNSocket *sock, CNPacketData *data) {
plr->mentor = pkt->iMentor;
}
void PlayerManager::setFirstUseFlag(CNSocket* sock, CNPacketData* data) {
if (data->size != sizeof(sP_CL2FE_REQ_PC_FIRST_USE_FLAG_SET))
return;
sP_CL2FE_REQ_PC_FIRST_USE_FLAG_SET* flag = (sP_CL2FE_REQ_PC_FIRST_USE_FLAG_SET*)data->buf;
Player* plr = getPlayer(sock);
if (flag->iFlagCode < 1 || flag->iFlagCode > 128) {
std::cout << "[WARN] Client submitted invalid first use flag number?!" << std::endl;
return;
}
if (flag->iFlagCode <= 64)
plr->iFirstUseFlag[0] |= (1ULL << (flag->iFlagCode - 1));
else
plr->iFirstUseFlag[1] |= (1ULL << (flag->iFlagCode - 65));
}
#pragma region Helper methods
Player *PlayerManager::getPlayer(CNSocket* key) {
if (players.find(key) != players.end())

View File

@ -50,6 +50,8 @@ namespace PlayerManager {
void enterPlayerVehicle(CNSocket* sock, CNPacketData* data);
void exitPlayerVehicle(CNSocket* sock, CNPacketData* data);
void setFirstUseFlag(CNSocket* sock, CNPacketData* data);
Player *getPlayer(CNSocket* key);
std::string getPlayerName(Player *plr, bool id=true);
WarpLocation* getRespawnPoint(Player *plr);