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

View File

@ -79,6 +79,8 @@ struct Player {
int64_t buddyIDs[50]; int64_t buddyIDs[50];
bool isBuddyBlocked[50]; bool isBuddyBlocked[50];
uint64_t iFirstUseFlag[2];
ChunkPos chunkPos; ChunkPos chunkPos;
std::set<Chunk*>* viewableChunks; std::set<Chunk*>* viewableChunks;
time_t lastHeartbeat; 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_ON, enterPlayerVehicle);
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_VEHICLE_OFF, exitPlayerVehicle); 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_CHANGE_MENTOR, changePlayerGuide);
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_FIRST_USE_FLAG_SET, setFirstUseFlag);
} }
void PlayerManager::addPlayer(CNSocket* key, Player plr) { 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]; response.PCLoadData2CL.aQuestFlag[i] = plr.aQuestFlag[i];
} }
// shut Computress up // Computress tips
response.PCLoadData2CL.iFirstUseFlag1 = UINT64_MAX; response.PCLoadData2CL.iFirstUseFlag1 = plr.iFirstUseFlag[0];
response.PCLoadData2CL.iFirstUseFlag2 = UINT64_MAX; response.PCLoadData2CL.iFirstUseFlag2 = plr.iFirstUseFlag[1];
plr.SerialKey = enter->iEnterSerialKey; plr.SerialKey = enter->iEnterSerialKey;
plr.instanceID = INSTANCE_OVERWORLD; // the player should never be in an instance on enter 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; 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 #pragma region Helper methods
Player *PlayerManager::getPlayer(CNSocket* key) { Player *PlayerManager::getPlayer(CNSocket* key) {
if (players.find(key) != players.end()) if (players.find(key) != players.end())

View File

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