mirror of
https://github.com/OpenFusionProject/OpenFusion.git
synced 2025-04-02 11:30:08 +00:00
537 lines
17 KiB
C++
537 lines
17 KiB
C++
#include "db/internal.hpp"
|
|
|
|
#include "bcrypt/BCrypt.hpp"
|
|
|
|
void Database::findAccount(Account* account, std::string login) {
|
|
std::lock_guard<std::mutex> lock(dbCrit);
|
|
|
|
const char* sql = R"(
|
|
SELECT AccountID, Password, Selected, BannedUntil, BanReason
|
|
FROM Accounts
|
|
WHERE Login = ?
|
|
LIMIT 1;
|
|
)";
|
|
sqlite3_stmt* stmt;
|
|
|
|
sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
|
|
sqlite3_bind_text(stmt, 1, login.c_str(), -1, NULL);
|
|
|
|
int rc = sqlite3_step(stmt);
|
|
if (rc == SQLITE_ROW) {
|
|
account->AccountID = sqlite3_column_int(stmt, 0);
|
|
account->Password = std::string(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1)));
|
|
account->Selected = sqlite3_column_int(stmt, 2);
|
|
account->BannedUntil = sqlite3_column_int64(stmt, 3);
|
|
account->BanReason = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 4));
|
|
}
|
|
sqlite3_finalize(stmt);
|
|
}
|
|
|
|
int Database::addAccount(std::string login, std::string password) {
|
|
std::lock_guard<std::mutex> lock(dbCrit);
|
|
|
|
const char* sql = R"(
|
|
INSERT INTO Accounts (Login, Password, AccountLevel)
|
|
VALUES (?, ?, ?);
|
|
)";
|
|
sqlite3_stmt* stmt;
|
|
|
|
sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
|
|
sqlite3_bind_text(stmt, 1, login.c_str(), -1, NULL);
|
|
std::string hashedPassword = BCrypt::generateHash(password);
|
|
sqlite3_bind_text(stmt, 2, hashedPassword.c_str(), -1, NULL);
|
|
sqlite3_bind_int(stmt, 3, settings::ACCLEVEL);
|
|
|
|
int rc = sqlite3_step(stmt);
|
|
sqlite3_finalize(stmt);
|
|
if (rc != SQLITE_DONE) {
|
|
std::cout << "[WARN] Database: failed to add new account" << std::endl;
|
|
return 0;
|
|
}
|
|
|
|
return sqlite3_last_insert_rowid(db);
|
|
}
|
|
|
|
void Database::updateSelected(int accountId, int slot) {
|
|
std::lock_guard<std::mutex> lock(dbCrit);
|
|
|
|
if (slot < 1 || slot > 4) {
|
|
std::cout << "[WARN] Invalid slot number passed to updateSelected()! " << std::endl;
|
|
return;
|
|
}
|
|
|
|
const char* sql = R"(
|
|
UPDATE Accounts SET
|
|
Selected = ?,
|
|
LastLogin = (strftime('%s', 'now'))
|
|
WHERE AccountID = ?;
|
|
)";
|
|
|
|
sqlite3_stmt* stmt;
|
|
|
|
sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
|
|
sqlite3_bind_int(stmt, 1, slot);
|
|
sqlite3_bind_int(stmt, 2, accountId);
|
|
int rc = sqlite3_step(stmt);
|
|
sqlite3_finalize(stmt);
|
|
|
|
if (rc != SQLITE_DONE)
|
|
std::cout << "[WARN] Database fail on updateSelected(): " << sqlite3_errmsg(db) << std::endl;
|
|
}
|
|
|
|
bool Database::validateCharacter(int characterID, int userID) {
|
|
std::lock_guard<std::mutex> lock(dbCrit);
|
|
|
|
// query whatever
|
|
const char* sql = R"(
|
|
SELECT PlayerID
|
|
FROM Players
|
|
WHERE PlayerID = ? AND AccountID = ?
|
|
LIMIT 1;
|
|
)";
|
|
sqlite3_stmt* stmt;
|
|
|
|
sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
|
|
sqlite3_bind_int(stmt, 1, characterID);
|
|
sqlite3_bind_int(stmt, 2, userID);
|
|
int rc = sqlite3_step(stmt);
|
|
// if we got a row back, the character is valid
|
|
bool result = (rc == SQLITE_ROW);
|
|
sqlite3_finalize(stmt);
|
|
return result;
|
|
}
|
|
|
|
bool Database::isNameFree(std::string firstName, std::string lastName) {
|
|
std::lock_guard<std::mutex> lock(dbCrit);
|
|
|
|
const char* sql = R"(
|
|
SELECT COUNT(*)
|
|
FROM Players
|
|
WHERE FirstName = ? AND LastName = ?
|
|
LIMIT 1;
|
|
)";
|
|
sqlite3_stmt* stmt;
|
|
|
|
sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
|
|
sqlite3_bind_text(stmt, 1, firstName.c_str(), -1, NULL);
|
|
sqlite3_bind_text(stmt, 2, lastName.c_str(), -1, NULL);
|
|
int rc = sqlite3_step(stmt);
|
|
|
|
bool result = (rc == SQLITE_ROW && sqlite3_column_int(stmt, 0) == 0);
|
|
sqlite3_finalize(stmt);
|
|
return result;
|
|
}
|
|
|
|
bool Database::isSlotFree(int accountId, int slotNum) {
|
|
std::lock_guard<std::mutex> lock(dbCrit);
|
|
|
|
if (slotNum < 1 || slotNum > 4) {
|
|
std::cout << "[WARN] Invalid slot number passed to isSlotFree()! " << slotNum << std::endl;
|
|
return false;
|
|
}
|
|
|
|
const char* sql = R"(
|
|
SELECT COUNT(*)
|
|
FROM Players
|
|
WHERE AccountID = ? AND Slot = ?
|
|
LIMIT 1;
|
|
)";
|
|
sqlite3_stmt* stmt;
|
|
|
|
sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
|
|
sqlite3_bind_int(stmt, 1, accountId);
|
|
sqlite3_bind_int(stmt, 2, slotNum);
|
|
int rc = sqlite3_step(stmt);
|
|
|
|
bool result = (rc == SQLITE_ROW && sqlite3_column_int(stmt, 0) == 0);
|
|
sqlite3_finalize(stmt);
|
|
return result;
|
|
}
|
|
|
|
int Database::createCharacter(sP_CL2LS_REQ_SAVE_CHAR_NAME* save, int AccountID) {
|
|
std::lock_guard<std::mutex> lock(dbCrit);
|
|
|
|
sqlite3_exec(db, "BEGIN TRANSACTION;", NULL, NULL, NULL);
|
|
|
|
const char* sql = R"(
|
|
INSERT INTO Players
|
|
(AccountID, Slot, FirstName, LastName,
|
|
XCoordinate, YCoordinate, ZCoordinate, Angle,
|
|
HP, NameCheck, Quests, SkywayLocationFlag, FirstUseFlag)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
|
|
)";
|
|
sqlite3_stmt* stmt;
|
|
std::string firstName = AUTOU16TOU8(save->szFirstName);
|
|
std::string lastName = AUTOU16TOU8(save->szLastName);
|
|
|
|
sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
|
|
sqlite3_bind_int(stmt, 1, AccountID);
|
|
sqlite3_bind_int(stmt, 2, save->iSlotNum);
|
|
sqlite3_bind_text(stmt, 3, firstName.c_str(), -1, NULL);
|
|
sqlite3_bind_text(stmt, 4, lastName.c_str(), -1, NULL);
|
|
sqlite3_bind_int(stmt, 5, settings::SPAWN_X);
|
|
sqlite3_bind_int(stmt, 6, settings::SPAWN_Y);
|
|
sqlite3_bind_int(stmt, 7, settings::SPAWN_Z);
|
|
sqlite3_bind_int(stmt, 8, settings::SPAWN_ANGLE);
|
|
sqlite3_bind_int(stmt, 9, PC_MAXHEALTH(1));
|
|
|
|
// if FNCode isn't 0, it's a wheel name
|
|
int nameCheck = (settings::APPROVEALLNAMES || save->iFNCode) ? 1 : 0;
|
|
sqlite3_bind_int(stmt, 10, nameCheck);
|
|
|
|
// blobs
|
|
unsigned char blobBuffer[sizeof(Player::aQuestFlag)] = { 0 };
|
|
sqlite3_bind_blob(stmt, 11, blobBuffer, sizeof(Player::aQuestFlag), NULL);
|
|
sqlite3_bind_blob(stmt, 12, blobBuffer, sizeof(Player::aSkywayLocationFlag), NULL);
|
|
sqlite3_bind_blob(stmt, 13, blobBuffer, sizeof(Player::iFirstUseFlag), NULL);
|
|
|
|
if (sqlite3_step(stmt) != SQLITE_DONE) {
|
|
sqlite3_finalize(stmt);
|
|
sqlite3_exec(db, "ROLLBACK TRANSACTION;", NULL, NULL, NULL);
|
|
return 0;
|
|
}
|
|
|
|
int playerId = sqlite3_last_insert_rowid(db);
|
|
|
|
sqlite3_finalize(stmt);
|
|
|
|
sql = R"(
|
|
INSERT INTO Appearances (PlayerID)
|
|
VALUES (?);
|
|
)";
|
|
sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
|
|
sqlite3_bind_int(stmt, 1, playerId);
|
|
|
|
int rc = sqlite3_step(stmt);
|
|
sqlite3_finalize(stmt);
|
|
if (rc != SQLITE_DONE) {
|
|
sqlite3_exec(db, "ROLLBACK TRANSACTION;", NULL, NULL, NULL);
|
|
return 0;
|
|
}
|
|
|
|
sqlite3_exec(db, "COMMIT;", NULL, NULL, NULL);
|
|
return playerId;
|
|
}
|
|
|
|
bool Database::finishCharacter(sP_CL2LS_REQ_CHAR_CREATE* character, int accountId) {
|
|
std::lock_guard<std::mutex> lock(dbCrit);
|
|
|
|
sqlite3_exec(db, "BEGIN TRANSACTION;", NULL, NULL, NULL);
|
|
|
|
const char* sql = R"(
|
|
UPDATE Players
|
|
SET AppearanceFlag = 1
|
|
WHERE PlayerID = ? AND AccountID = ? AND AppearanceFlag = 0;
|
|
)";
|
|
sqlite3_stmt* stmt;
|
|
|
|
sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
|
|
sqlite3_bind_int(stmt, 1, character->PCStyle.iPC_UID);
|
|
sqlite3_bind_int(stmt, 2, accountId);
|
|
|
|
if (sqlite3_step(stmt) != SQLITE_DONE) {
|
|
sqlite3_finalize(stmt);
|
|
sqlite3_exec(db, "ROLLBACK TRANSACTION;", NULL, NULL, NULL);
|
|
return false;
|
|
}
|
|
|
|
sqlite3_finalize(stmt);
|
|
|
|
sql = R"(
|
|
UPDATE Appearances
|
|
SET
|
|
Body = ?,
|
|
EyeColor = ?,
|
|
FaceStyle = ?,
|
|
Gender = ?,
|
|
HairColor = ?,
|
|
HairStyle = ?,
|
|
Height = ?,
|
|
SkinColor = ?
|
|
WHERE PlayerID = ?;
|
|
)";
|
|
sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
|
|
|
|
sqlite3_bind_int(stmt, 1, character->PCStyle.iBody);
|
|
sqlite3_bind_int(stmt, 2, character->PCStyle.iEyeColor);
|
|
sqlite3_bind_int(stmt, 3, character->PCStyle.iFaceStyle);
|
|
sqlite3_bind_int(stmt, 4, character->PCStyle.iGender);
|
|
sqlite3_bind_int(stmt, 5, character->PCStyle.iHairColor);
|
|
sqlite3_bind_int(stmt, 6, character->PCStyle.iHairStyle);
|
|
sqlite3_bind_int(stmt, 7, character->PCStyle.iHeight);
|
|
sqlite3_bind_int(stmt, 8, character->PCStyle.iSkinColor);
|
|
sqlite3_bind_int(stmt, 9, character->PCStyle.iPC_UID);
|
|
|
|
if (sqlite3_step(stmt) != SQLITE_DONE) {
|
|
sqlite3_finalize(stmt);
|
|
sqlite3_exec(db, "ROLLBACK TRANSACTION;", NULL, NULL, NULL);
|
|
return false;
|
|
}
|
|
|
|
sqlite3_finalize(stmt);
|
|
|
|
sql = R"(
|
|
INSERT INTO Inventory (PlayerID, Slot, ID, Type, Opt)
|
|
VALUES (?, ?, ?, ?, 1);
|
|
)";
|
|
sqlite3_prepare_v2(db, sql, -1, &stmt, 0);
|
|
|
|
int items[3] = { character->sOn_Item.iEquipUBID, character->sOn_Item.iEquipLBID, character->sOn_Item.iEquipFootID };
|
|
for (int i = 0; i < 3; i++) {
|
|
sqlite3_bind_int(stmt, 1, character->PCStyle.iPC_UID);
|
|
sqlite3_bind_int(stmt, 2, i+1);
|
|
sqlite3_bind_int(stmt, 3, items[i]);
|
|
sqlite3_bind_int(stmt, 4, i+1);
|
|
|
|
if (sqlite3_step(stmt) != SQLITE_DONE) {
|
|
sqlite3_finalize(stmt);
|
|
sqlite3_exec(db, "ROLLBACK TRANSACTION;", NULL, NULL, NULL);
|
|
return false;
|
|
}
|
|
sqlite3_reset(stmt);
|
|
}
|
|
|
|
sqlite3_finalize(stmt);
|
|
sqlite3_exec(db, "COMMIT;", NULL, NULL, NULL);
|
|
return true;
|
|
}
|
|
|
|
bool Database::finishTutorial(int playerID, int accountID) {
|
|
std::lock_guard<std::mutex> lock(dbCrit);
|
|
|
|
sqlite3_exec(db, "BEGIN TRANSACTION;", NULL, NULL, NULL);
|
|
|
|
const char* sql = R"(
|
|
UPDATE Players SET
|
|
TutorialFlag = 1,
|
|
Nano1 = ?,
|
|
Quests = ?
|
|
WHERE PlayerID = ? AND AccountID = ? AND TutorialFlag = 0;
|
|
)";
|
|
sqlite3_stmt* stmt;
|
|
sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
|
|
|
|
unsigned char questBuffer[128] = { 0 };
|
|
|
|
#ifndef ACADEMY
|
|
// save missions nr 1 & 2; equip Buttercup
|
|
questBuffer[0] = 3;
|
|
sqlite3_bind_int(stmt, 1, 1);
|
|
#else
|
|
// no, none of that
|
|
sqlite3_bind_int(stmt, 1, 0);
|
|
#endif
|
|
|
|
sqlite3_bind_blob(stmt, 2, questBuffer, sizeof(questBuffer), NULL);
|
|
sqlite3_bind_int(stmt, 3, playerID);
|
|
sqlite3_bind_int(stmt, 4, accountID);
|
|
|
|
if (sqlite3_step(stmt) != SQLITE_DONE) {
|
|
sqlite3_finalize(stmt);
|
|
sqlite3_exec(db, "ROLLBACK TRANSACTION;", NULL, NULL, NULL);
|
|
return false;
|
|
}
|
|
|
|
sqlite3_finalize(stmt);
|
|
|
|
#ifndef ACADEMY
|
|
// Lightning Gun
|
|
sql = R"(
|
|
INSERT INTO Inventory
|
|
(PlayerID, Slot, ID, Type, Opt)
|
|
VALUES (?, 0, 328, 0, 1);
|
|
)";
|
|
sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
|
|
|
|
sqlite3_bind_int(stmt, 1, playerID);
|
|
|
|
if (sqlite3_step(stmt) != SQLITE_DONE) {
|
|
sqlite3_finalize(stmt);
|
|
sqlite3_exec(db, "ROLLBACK TRANSACTION;", NULL, NULL, NULL);
|
|
return false;
|
|
}
|
|
|
|
sqlite3_finalize(stmt);
|
|
|
|
// Nano Buttercup
|
|
sql = R"(
|
|
INSERT INTO Nanos
|
|
(PlayerID, ID, Skill)
|
|
VALUES (?, 1, 1);
|
|
)";
|
|
sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
|
|
|
|
sqlite3_bind_int(stmt, 1, playerID);
|
|
|
|
int rc = sqlite3_step(stmt);
|
|
sqlite3_finalize(stmt);
|
|
|
|
if (rc != SQLITE_DONE) {
|
|
sqlite3_exec(db, "ROLLBACK TRANSACTION;", NULL, NULL, NULL);
|
|
return false;
|
|
}
|
|
#endif
|
|
|
|
sqlite3_exec(db, "COMMIT;", NULL, NULL, NULL);
|
|
return true;
|
|
}
|
|
|
|
int Database::deleteCharacter(int characterID, int userID) {
|
|
std::lock_guard<std::mutex> lock(dbCrit);
|
|
|
|
const char* sql = R"(
|
|
SELECT Slot
|
|
FROM Players
|
|
WHERE AccountID = ? AND PlayerID = ?
|
|
LIMIT 1;
|
|
)";
|
|
|
|
sqlite3_stmt* stmt;
|
|
|
|
sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
|
|
sqlite3_bind_int(stmt, 1, userID);
|
|
sqlite3_bind_int(stmt, 2, characterID);
|
|
if (sqlite3_step(stmt) != SQLITE_ROW) {
|
|
sqlite3_finalize(stmt);
|
|
return 0;
|
|
}
|
|
int slot = sqlite3_column_int(stmt, 0);
|
|
|
|
sqlite3_finalize(stmt);
|
|
|
|
sql = R"(
|
|
DELETE FROM Players
|
|
WHERE AccountID = ? AND PlayerID = ?;
|
|
)";
|
|
sqlite3_prepare_v2(db, sql, -1, &stmt, 0);
|
|
sqlite3_bind_int(stmt, 1, userID);
|
|
sqlite3_bind_int(stmt, 2, characterID);
|
|
int rc = sqlite3_step(stmt);
|
|
sqlite3_finalize(stmt);
|
|
|
|
if (rc != SQLITE_DONE)
|
|
return 0;
|
|
|
|
return slot;
|
|
}
|
|
|
|
void Database::getCharInfo(std::vector <sP_LS2CL_REP_CHAR_INFO>* result, int userID) {
|
|
std::lock_guard<std::mutex> lock(dbCrit);
|
|
|
|
const char* sql = R"(
|
|
SELECT
|
|
p.PlayerID, p.Slot, p.FirstName, p.LastName, p.Level, p.AppearanceFlag, p.TutorialFlag, p.PayZoneFlag,
|
|
p.XCoordinate, p.YCoordinate, p.ZCoordinate, p.NameCheck,
|
|
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
|
|
WHERE p.AccountID = ?;
|
|
)";
|
|
sqlite3_stmt* stmt;
|
|
|
|
sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
|
|
sqlite3_bind_int(stmt, 1, userID);
|
|
|
|
while (sqlite3_step(stmt) == SQLITE_ROW) {
|
|
sP_LS2CL_REP_CHAR_INFO toAdd = {};
|
|
toAdd.sPC_Style.iPC_UID = sqlite3_column_int(stmt, 0);
|
|
toAdd.iSlot = sqlite3_column_int(stmt, 1);
|
|
|
|
// parsing const unsigned char* to char16_t
|
|
std::string placeHolder = std::string(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 2)));
|
|
U8toU16(placeHolder, toAdd.sPC_Style.szFirstName, sizeof(toAdd.sPC_Style.szFirstName));
|
|
placeHolder = std::string(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 3)));
|
|
U8toU16(placeHolder, toAdd.sPC_Style.szLastName, sizeof(toAdd.sPC_Style.szLastName));
|
|
|
|
toAdd.iLevel = sqlite3_column_int(stmt, 4);
|
|
toAdd.sPC_Style2.iAppearanceFlag = sqlite3_column_int(stmt, 5);
|
|
toAdd.sPC_Style2.iTutorialFlag = sqlite3_column_int(stmt, 6);
|
|
toAdd.sPC_Style2.iPayzoneFlag = sqlite3_column_int(stmt, 7);
|
|
toAdd.iX = sqlite3_column_int(stmt, 8);
|
|
toAdd.iY = sqlite3_column_int(stmt, 9);
|
|
toAdd.iZ = sqlite3_column_int(stmt, 10);
|
|
toAdd.sPC_Style.iNameCheck = sqlite3_column_int(stmt, 11);
|
|
toAdd.sPC_Style.iBody = sqlite3_column_int(stmt, 12);
|
|
toAdd.sPC_Style.iEyeColor = sqlite3_column_int(stmt, 13);
|
|
toAdd.sPC_Style.iFaceStyle = sqlite3_column_int(stmt, 14);
|
|
toAdd.sPC_Style.iGender = sqlite3_column_int(stmt, 15);
|
|
toAdd.sPC_Style.iHairColor = sqlite3_column_int(stmt, 16);
|
|
toAdd.sPC_Style.iHairStyle = sqlite3_column_int(stmt, 17);
|
|
toAdd.sPC_Style.iHeight = sqlite3_column_int(stmt, 18);
|
|
toAdd.sPC_Style.iSkinColor = sqlite3_column_int(stmt, 19);
|
|
|
|
// request aEquip
|
|
const char* sql2 = R"(
|
|
SELECT Slot, Type, ID, Opt, TimeLimit
|
|
FROM Inventory
|
|
WHERE PlayerID = ? AND Slot < ?;
|
|
)";
|
|
sqlite3_stmt* stmt2;
|
|
|
|
sqlite3_prepare_v2(db, sql2, -1, &stmt2, NULL);
|
|
sqlite3_bind_int(stmt2, 1, toAdd.sPC_Style.iPC_UID);
|
|
sqlite3_bind_int(stmt2, 2, AEQUIP_COUNT);
|
|
|
|
while (sqlite3_step(stmt2) == SQLITE_ROW) {
|
|
sItemBase* item = &toAdd.aEquip[sqlite3_column_int(stmt2, 0)];
|
|
item->iType = sqlite3_column_int(stmt2, 1);
|
|
item->iID = sqlite3_column_int(stmt2, 2);
|
|
item->iOpt = sqlite3_column_int(stmt2, 3);
|
|
item->iTimeLimit = sqlite3_column_int(stmt2, 4);
|
|
}
|
|
sqlite3_finalize(stmt2);
|
|
|
|
result->push_back(toAdd);
|
|
}
|
|
sqlite3_finalize(stmt);
|
|
}
|
|
|
|
// NOTE: This is currently never called.
|
|
void Database::evaluateCustomName(int characterID, CustomName decision) {
|
|
std::lock_guard<std::mutex> lock(dbCrit);
|
|
|
|
const char* sql = R"(
|
|
UPDATE Players
|
|
SET NameCheck = ?
|
|
WHERE PlayerID = ?;
|
|
)";
|
|
sqlite3_stmt* stmt;
|
|
sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
|
|
sqlite3_bind_int(stmt, 1, int(decision));
|
|
sqlite3_bind_int(stmt, 2, characterID);
|
|
|
|
if (sqlite3_step(stmt) != SQLITE_DONE)
|
|
std::cout << "[WARN] Database: Failed to update nameCheck: " << sqlite3_errmsg(db) << std::endl;
|
|
sqlite3_finalize(stmt);
|
|
}
|
|
|
|
bool Database::changeName(sP_CL2LS_REQ_CHANGE_CHAR_NAME* save, int accountId) {
|
|
std::lock_guard<std::mutex> lock(dbCrit);
|
|
|
|
const char* sql = R"(
|
|
UPDATE Players
|
|
SET
|
|
FirstName = ?,
|
|
LastName = ?,
|
|
NameCheck = ?
|
|
WHERE PlayerID = ? AND AccountID = ?;
|
|
)";
|
|
sqlite3_stmt* stmt;
|
|
sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
|
|
|
|
std::string firstName = AUTOU16TOU8(save->szFirstName);
|
|
std::string lastName = AUTOU16TOU8(save->szLastName);
|
|
|
|
sqlite3_bind_text(stmt, 1, firstName.c_str(), -1, NULL);
|
|
sqlite3_bind_text(stmt, 2, lastName.c_str(), -1, NULL);
|
|
// if FNCode isn't 0, it's a wheel name
|
|
int nameCheck = (settings::APPROVEALLNAMES || save->iFNCode) ? 1 : 0;
|
|
sqlite3_bind_int(stmt, 3, nameCheck);
|
|
sqlite3_bind_int(stmt, 4, save->iPCUID);
|
|
sqlite3_bind_int(stmt, 5, accountId);
|
|
|
|
int rc = sqlite3_step(stmt);
|
|
sqlite3_finalize(stmt);
|
|
return rc == SQLITE_DONE;
|
|
}
|