mirror of
https://github.com/OpenFusionProject/OpenFusion.git
synced 2026-02-06 12:50:02 +00:00
Rewrote DB to use ORM, added all remaining features to LoginServer and refactored it
This commit is contained in:
690
src/Database.cpp
690
src/Database.cpp
@@ -1,424 +1,356 @@
|
||||
#include "contrib/sqlite/sqlite3pp.h"
|
||||
#include "contrib/bcrypt/BCrypt.hpp"
|
||||
#include "CNProtocol.hpp"
|
||||
#include "Database.hpp"
|
||||
#include "contrib/bcrypt/BCrypt.hpp">
|
||||
#include "CNProtocol.hpp"
|
||||
#include <string>
|
||||
#include "contrib/JSON.hpp"
|
||||
#include "CNStructs.hpp"
|
||||
#include "settings.hpp"
|
||||
#include "Player.hpp"
|
||||
#include <regex>
|
||||
#include <fstream>
|
||||
#include "contrib/JSON.hpp"
|
||||
#include "CNStructs.hpp"
|
||||
#include "contrib/sqlite/sqlite_orm.h"
|
||||
|
||||
using namespace sqlite_orm;
|
||||
|
||||
//TODO: replace this sqlite wrapper with something better, clean up queries, get rid of json
|
||||
# pragma region DatabaseScheme
|
||||
auto db = make_storage("database.db",
|
||||
make_table("Accounts",
|
||||
make_column("AccountID", &Database::Account::AccountID, autoincrement(), primary_key()),
|
||||
make_column("Login", &Database::Account::Login),
|
||||
make_column("Password", &Database::Account::Password),
|
||||
make_column("Selected", &Database::Account::Selected)
|
||||
),
|
||||
make_table("Players",
|
||||
make_column("PlayerID", &Database::DbPlayer::PlayerID, autoincrement(), primary_key()),
|
||||
make_column("AccountID", &Database::DbPlayer::AccountID),
|
||||
make_column("Slot", &Database::DbPlayer::slot),
|
||||
make_column("Firstname", &Database::DbPlayer::FirstName),
|
||||
make_column("LastName", &Database::DbPlayer::LastName),
|
||||
make_column("Level", &Database::DbPlayer::Level),
|
||||
make_column("AppearanceFlag", &Database::DbPlayer::AppearanceFlag),
|
||||
make_column("TutorialFlag", &Database::DbPlayer::TutorialFlag),
|
||||
make_column("PayZoneFlag", &Database::DbPlayer::PayZoneFlag),
|
||||
make_column("XCoordinates", &Database::DbPlayer::x_coordinates),
|
||||
make_column("YCoordinates", &Database::DbPlayer::y_coordinates),
|
||||
make_column("ZCoordinates", &Database::DbPlayer::z_coordinates),
|
||||
make_column("Body", &Database::DbPlayer::Body),
|
||||
make_column("Class", &Database::DbPlayer::Class),
|
||||
make_column("EquipFoot", &Database::DbPlayer::EquipFoot),
|
||||
make_column("EquipLB", &Database::DbPlayer::EquipLB),
|
||||
make_column("EquipUB", &Database::DbPlayer::EquipUB),
|
||||
make_column("EquipWeapon1", &Database::DbPlayer::EquipWeapon1),
|
||||
make_column("EyeColor", &Database::DbPlayer::EyeColor),
|
||||
make_column("FaceStyle", &Database::DbPlayer::FaceStyle),
|
||||
make_column("Gender", &Database::DbPlayer::Gender),
|
||||
make_column("HP", &Database::DbPlayer::HP),
|
||||
make_column("HairColor", &Database::DbPlayer::HairColor),
|
||||
make_column("HairStyle", &Database::DbPlayer::HairStyle),
|
||||
make_column("Height", &Database::DbPlayer::Height),
|
||||
make_column("NameCheck", &Database::DbPlayer::NameCheck),
|
||||
make_column("SkinColor", &Database::DbPlayer::SkinColor),
|
||||
make_column("isGM", &Database::DbPlayer::isGM),
|
||||
make_column("FusionMatter", &Database::DbPlayer::FusionMatter),
|
||||
make_column("Taros", &Database::DbPlayer::Taros)
|
||||
),
|
||||
make_table("Inventory",
|
||||
make_column("AccountID", &Database::Inventory::AccountID, primary_key())
|
||||
)
|
||||
);
|
||||
|
||||
sqlite3pp::database db;
|
||||
# pragma endregion DatabaseScheme
|
||||
|
||||
void Database::open() {
|
||||
//checking if database file exists
|
||||
std::ifstream file;
|
||||
file.open("data.db");
|
||||
#pragma region LoginServer
|
||||
|
||||
if (file) {
|
||||
file.close();
|
||||
// if exists, assign it
|
||||
db = sqlite3pp::database("data.db");
|
||||
DEBUGLOG(std::cout << "[DB] Database in operation" << std::endl;)
|
||||
}
|
||||
else {
|
||||
// if doesn't, create all the tables
|
||||
DEBUGLOG(std::cout << "[DB] Creating new database" << std::endl;)
|
||||
db = sqlite3pp::database("data.db");
|
||||
|
||||
// creates accounts
|
||||
db.execute("CREATE TABLE Accounts(AccountID INTEGER PRIMARY KEY AUTOINCREMENT, Login TEXT NOT NULL, Password TEXT NOT NULL);");
|
||||
// creates characters
|
||||
db.execute("CREATE TABLE Players(PlayerID INTEGER PRIMARY KEY AUTOINCREMENT, AccountID INTEGER NOT NULL, Slot INTEGER NOT NULL, FirstName TEXT NOT NULL, LastName TEXT NOT NULL, CharData TEXT NOT NULL);");
|
||||
|
||||
DEBUGLOG(std::cout << "Done" << std::endl;)
|
||||
}
|
||||
void Database::open()
|
||||
{
|
||||
//this parameter means it will try to preserve data during migration
|
||||
bool preserve = true;
|
||||
db.sync_schema(preserve);
|
||||
DEBUGLOG(
|
||||
std::cout << "[DB] Database in operation" << std::endl;
|
||||
)
|
||||
}
|
||||
|
||||
// verifies that the username & passwords are valid
|
||||
bool Database::isLoginDataGood(std::string login, std::string password) {
|
||||
std::regex loginRegex("^([A-Za-z\\d_\\-]){5,20}$");
|
||||
std::regex passwordRegex("^([A-Za-z\\d_\\-@$!%*#?&,.+:;<=>]){2,20}$");
|
||||
return (std::regex_match(login, loginRegex) && std::regex_match(password, passwordRegex));
|
||||
int Database::addAccount(std::string login, std::string password)
|
||||
{
|
||||
password = BCrypt::generateHash(password);
|
||||
Account x;
|
||||
x.Login = login;
|
||||
x.Password = password;
|
||||
x.Selected = 1;
|
||||
return db.insert(x);
|
||||
}
|
||||
|
||||
void Database::addAccount(std::string login, std::string password) {
|
||||
// generates prepared statment
|
||||
sqlite3pp::command cmd(db, "INSERT INTO Accounts (Login, Password) VALUES (:login, :password)");
|
||||
|
||||
// generates a hashed password!
|
||||
password = BCrypt::generateHash(password);
|
||||
|
||||
// binds args to the command
|
||||
cmd.bind(":login", login, sqlite3pp::nocopy);
|
||||
cmd.bind(":password", password, sqlite3pp::nocopy);
|
||||
cmd.execute();
|
||||
void Database::updateSelected(int accountId, int slot)
|
||||
{
|
||||
Account acc = db.get<Account>(accountId);
|
||||
acc.Selected = slot;
|
||||
db.update(acc);
|
||||
}
|
||||
|
||||
bool Database::doesUserExist(std::string login) {
|
||||
// generates prepared statement
|
||||
sqlite3pp::query qry(db, "SELECT COUNT(AccountID) FROM Accounts WHERE Login = :login");
|
||||
// binds to the query
|
||||
qry.bind(":login", login, sqlite3pp::nocopy);
|
||||
|
||||
// executes
|
||||
sqlite3pp::query::iterator i = qry.begin();
|
||||
|
||||
// grabs the first result (the count)
|
||||
int result;
|
||||
std::tie(result) = (*i).get_columns<int>(0);
|
||||
|
||||
// if there is more than 0 results, the user exists :eyes:
|
||||
return (result > 0);
|
||||
std::unique_ptr<Database::Account> Database::findAccount(std::string login)
|
||||
{
|
||||
//this is awful, I've tried everything to improve it
|
||||
auto find = db.get_all<Account>(
|
||||
where(c(&Account::Login) == login), limit(1));
|
||||
if (find.empty())
|
||||
return nullptr;
|
||||
return
|
||||
std::unique_ptr<Account>(new Account(find.front()));
|
||||
}
|
||||
|
||||
bool Database::isPasswordCorrect(std::string login, std::string password) {
|
||||
// generates prepared statement
|
||||
sqlite3pp::query qry(db, "SELECT Password FROM Accounts WHERE Login = :login");
|
||||
// binds username to the query
|
||||
qry.bind(":login", login, sqlite3pp::nocopy);
|
||||
|
||||
// executes
|
||||
sqlite3pp::query::iterator i = qry.begin();
|
||||
|
||||
// grabs the first result
|
||||
const char* actual;
|
||||
std::tie(actual) = (*i).get_columns<const char*>(0);
|
||||
|
||||
// validate password hash with provded password
|
||||
return BCrypt::validatePassword(password, actual);
|
||||
bool Database::isNameFree(sP_CL2LS_REQ_CHECK_CHAR_NAME* nameCheck)
|
||||
{
|
||||
//TODO: add colate nocase
|
||||
std::string First = U16toU8(nameCheck->szFirstName);
|
||||
std::string Last = U16toU8(nameCheck->szLastName);
|
||||
return
|
||||
(db.get_all<DbPlayer>
|
||||
(where((c(&DbPlayer::FirstName) == First)
|
||||
and (c(&DbPlayer::LastName) == Last)))
|
||||
.empty());
|
||||
}
|
||||
|
||||
int Database::getUserID(std::string login) {
|
||||
// generates prep statement
|
||||
sqlite3pp::query qry(db, "SELECT AccountID FROM Accounts WHERE Login = :login");
|
||||
// binds the username to the login param
|
||||
qry.bind(":login", login, sqlite3pp::nocopy);
|
||||
|
||||
// executes the query
|
||||
sqlite3pp::query::iterator i = qry.begin();
|
||||
|
||||
// grabs the first result of the query
|
||||
int result;
|
||||
std::tie(result) = (*i).get_columns<int>(0);
|
||||
|
||||
// returns the result
|
||||
return result;
|
||||
int Database::createCharacter(sP_CL2LS_REQ_SAVE_CHAR_NAME* save, int AccountID)
|
||||
{
|
||||
DbPlayer create;
|
||||
//save packet data
|
||||
create.FirstName = U16toU8(save->szFirstName);
|
||||
create.LastName = U16toU8(save->szLastName);
|
||||
create.slot = save->iSlotNum;
|
||||
create.AccountID = AccountID;
|
||||
//set flags
|
||||
create.AppearanceFlag = 0;
|
||||
create.TutorialFlag = 0;
|
||||
create.PayZoneFlag = 0;
|
||||
//set namecheck based on setting
|
||||
if (settings::APPROVEALLNAMES || save->iFNCode)
|
||||
create.NameCheck = 1;
|
||||
else
|
||||
create.NameCheck = 0;
|
||||
//create default body character
|
||||
create.Body= 0;
|
||||
create.Class= 0;
|
||||
create.EquipFoot= 0;
|
||||
create.EquipLB= 0;
|
||||
create.EquipUB= 0;
|
||||
create.EquipWeapon1= 0;
|
||||
create.EquipWeapon2= 0;
|
||||
create.EyeColor= 1;
|
||||
create.FaceStyle= 1;
|
||||
create.Gender= 1;
|
||||
create.HP= 1000;
|
||||
create.HairColor= 1;
|
||||
create.HairStyle = 1;
|
||||
create.Height= 0;
|
||||
create.Level= 1;
|
||||
create.SkinColor= 1;
|
||||
create.isGM = false;
|
||||
//commented and disabled for now
|
||||
//if (U16toU8(save->szFirstName) == settings::GMPASS) {
|
||||
// create.isGM = true;
|
||||
//}
|
||||
|
||||
create.FusionMatter= 0;
|
||||
create.Taros= 0;
|
||||
create.x_coordinates = settings::SPAWN_X;
|
||||
create.y_coordinates= settings::SPAWN_Y;
|
||||
create.z_coordinates= settings::SPAWN_Z;
|
||||
return db.insert(create);
|
||||
}
|
||||
|
||||
int Database::getUserSlotsNum(int AccountId) {
|
||||
// generates the prepared statement
|
||||
sqlite3pp::query qry(db, "SELECT COUNT(PlayerID) FROM Players WHERE AccountID = :ID");
|
||||
|
||||
// binds the ID to the param
|
||||
qry.bind(":ID", AccountId);
|
||||
|
||||
// executes
|
||||
sqlite3pp::query::iterator i = qry.begin();
|
||||
|
||||
// grabs the first result
|
||||
int result;
|
||||
std::tie(result) = (*i).get_columns<int>(0);
|
||||
|
||||
// returns the result
|
||||
return result;
|
||||
void Database::finishCharacter(sP_CL2LS_REQ_CHAR_CREATE* character)
|
||||
{
|
||||
DbPlayer finish = getDbPlayerById(character->PCStyle.iPC_UID);
|
||||
finish.AppearanceFlag = 1;
|
||||
finish.Body = character->PCStyle.iBody;
|
||||
finish.Class = character->PCStyle.iClass;
|
||||
finish.EquipFoot = character->sOn_Item.iEquipFootID;
|
||||
finish.EquipLB = character->sOn_Item.iEquipLBID;
|
||||
finish.EquipUB = character->sOn_Item.iEquipUBID;
|
||||
finish.EyeColor = character->PCStyle.iEyeColor;
|
||||
finish.FaceStyle = character->PCStyle.iFaceStyle;
|
||||
finish.Gender = character->PCStyle.iGender;
|
||||
finish.HairColor = character->PCStyle.iHairColor;
|
||||
finish.HairStyle = character->PCStyle.iHairStyle;
|
||||
finish.Height = character->PCStyle.iHeight;
|
||||
finish.Level = 1;
|
||||
finish.SkinColor = character->PCStyle.iSkinColor;
|
||||
db.update(finish);
|
||||
}
|
||||
|
||||
bool Database::isNameFree(std::string First, std::string Second) {
|
||||
// generates the prepared statement
|
||||
sqlite3pp::query qry(db, "SELECT COUNT(PlayerID) FROM Players WHERE FirstName = :First COLLATE nocase AND LastName = :Second COLLATE nocase");
|
||||
|
||||
// binds the params
|
||||
qry.bind(":First", First, sqlite3pp::nocopy);
|
||||
qry.bind(":Second", Second, sqlite3pp::nocopy);
|
||||
|
||||
// executes the query
|
||||
sqlite3pp::query::iterator i = qry.begin();
|
||||
|
||||
// grabs the result
|
||||
int result;
|
||||
std::tie(result) = (*i).get_columns<int>(0);
|
||||
|
||||
// if no results return, the the username is unused
|
||||
return (result == 0);
|
||||
void Database::finishTutorial(int PlayerID)
|
||||
{
|
||||
DbPlayer finish = getDbPlayerById(PlayerID);
|
||||
finish.TutorialFlag = 1;
|
||||
//equip lightning gun
|
||||
finish.EquipWeapon1 = 328;
|
||||
db.update(finish);
|
||||
}
|
||||
|
||||
void Database::createCharacter(sP_CL2LS_REQ_SAVE_CHAR_NAME* save, int AccountID) {
|
||||
// generate the command
|
||||
sqlite3pp::command cmd(db, "INSERT INTO Players (AccountID, Slot, FirstName, LastName, CharData) VALUES (:AccountID, :Slot, :FirstName, :LastName, :CharData)");
|
||||
|
||||
// generate character data
|
||||
std::string charData = CharacterToJson(save);
|
||||
std::string first = U16toU8(save->szFirstName);
|
||||
std::string last = U16toU8(save->szLastName);
|
||||
|
||||
// bind to command
|
||||
cmd.bind(":AccountID", AccountID);
|
||||
cmd.bind(":Slot", save->iSlotNum);
|
||||
cmd.bind(":CharData", charData, sqlite3pp::nocopy);
|
||||
cmd.bind(":FirstName", first, sqlite3pp::nocopy);
|
||||
cmd.bind(":LastName", last, sqlite3pp::nocopy);
|
||||
|
||||
// run
|
||||
cmd.execute();
|
||||
int Database::deleteCharacter(int characterID)
|
||||
{
|
||||
auto find =
|
||||
db.get_all<DbPlayer>(where(c(&DbPlayer::PlayerID) == characterID));
|
||||
int slot = find.front().slot;
|
||||
db.remove<DbPlayer>(find.front().PlayerID);
|
||||
return slot;
|
||||
}
|
||||
|
||||
void Database::finishCharacter(sP_CL2LS_REQ_CHAR_CREATE* character) {
|
||||
sqlite3pp::command cmd(db, "UPDATE Players SET CharData = :data WHERE PlayerID = :id");
|
||||
|
||||
// grab the data to add to the command
|
||||
int id = character->PCStyle.iPC_UID;
|
||||
std::string charData = CharacterToJson(character);
|
||||
|
||||
// bind to the command & execute
|
||||
cmd.bind(":data", charData, sqlite3pp::nocopy);
|
||||
cmd.bind(":id", id);
|
||||
cmd.execute();
|
||||
std::vector <Player> Database::getCharacters(int UserID)
|
||||
{
|
||||
std::vector<DbPlayer>characters =
|
||||
db.get_all<DbPlayer>(where
|
||||
(c(&DbPlayer::AccountID) == UserID));
|
||||
//parsing DbPlayer to Player
|
||||
std::vector<Player> result = std::vector<Player>();
|
||||
for (auto &character : characters) {
|
||||
Player toadd = DbToPlayer(character);
|
||||
result.push_back(
|
||||
toadd
|
||||
);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void Database::finishTutorial(int PlayerID) {
|
||||
sqlite3pp::query qry(db, "SELECT CharData FROM Players WHERE PlayerID = :ID");
|
||||
|
||||
// bind to the query and execute
|
||||
qry.bind(":ID", PlayerID);
|
||||
sqlite3pp::query::iterator i = qry.begin();
|
||||
|
||||
// grab the player json from the database
|
||||
std::string json;
|
||||
std::tie(json) = (*i).get_columns<std::string>(0);
|
||||
|
||||
// parse the json into a Player
|
||||
Player player = JsonToPlayer(json, PlayerID);
|
||||
|
||||
// set the tutorial flag & equip lightning gun
|
||||
player.PCStyle2.iTutorialFlag = 1;
|
||||
player.Equip[0].iID = 328;
|
||||
json = PlayerToJson(player);
|
||||
|
||||
// update the database
|
||||
sqlite3pp::command cmd(db, "UPDATE Players SET CharData = :data WHERE PlayerID = :id");
|
||||
cmd.bind(":data", json, sqlite3pp::nocopy);
|
||||
cmd.bind(":id", PlayerID);
|
||||
cmd.execute();
|
||||
void Database::evaluateCustomName(int characterID, CUSTOMNAME decision) {
|
||||
DbPlayer player = getDbPlayerById(characterID);
|
||||
player.NameCheck = (int)decision;
|
||||
db.update(player);
|
||||
}
|
||||
|
||||
int Database::getCharacterID(int AccountID, int slot) {
|
||||
// make the query
|
||||
sqlite3pp::query qry(db, "SELECT PlayerID FROM Players WHERE AccountID = :ID AND Slot = :Slot");
|
||||
|
||||
// bind the params & execute
|
||||
qry.bind(":ID", AccountID);
|
||||
qry.bind(":Slot", slot);
|
||||
sqlite3pp::query::iterator i = qry.begin();
|
||||
|
||||
// grab the result
|
||||
int result;
|
||||
std::tie(result) = (*i).get_columns<int>(0);
|
||||
|
||||
return result;
|
||||
void Database::changeName(sP_CL2LS_REQ_CHANGE_CHAR_NAME* save) {
|
||||
DbPlayer Player = getDbPlayerById(save->iPCUID);
|
||||
Player.FirstName = U16toU8(save->szFirstName);
|
||||
Player.LastName = U16toU8(save->szLastName);
|
||||
if (settings::APPROVEALLNAMES || save->iFNCode)
|
||||
Player.NameCheck = 1;
|
||||
else
|
||||
Player.NameCheck = 0;
|
||||
db.update(Player);
|
||||
}
|
||||
|
||||
int Database::deleteCharacter(int characterID, int accountID) {
|
||||
// checking if requested player exist and is bound to the account
|
||||
Database::DbPlayer Database::playerToDb(Player player)
|
||||
{
|
||||
DbPlayer result;
|
||||
result.PlayerID = player.iID;
|
||||
result.AccountID = player.accountId;
|
||||
result.AppearanceFlag = player.PCStyle2.iAppearanceFlag;
|
||||
result.Body = player.PCStyle.iBody;
|
||||
result.Class = player.PCStyle.iClass;
|
||||
//equipment
|
||||
result.EyeColor = player.PCStyle.iEyeColor;
|
||||
result.FaceStyle = player.PCStyle.iFaceStyle;
|
||||
result.FirstName = U16toU8( player.PCStyle.szFirstName);
|
||||
//fm
|
||||
result.Gender = player.PCStyle.iGender;
|
||||
result.HairColor = player.PCStyle.iHairColor;
|
||||
result.HairStyle = player.PCStyle.iHairStyle;
|
||||
result.Height = player.PCStyle.iHeight;
|
||||
result.HP = player.HP;
|
||||
result.isGM = player.IsGM;
|
||||
result.LastName = U16toU8(player.PCStyle.szLastName);
|
||||
result.Level = player.level;
|
||||
result.NameCheck = player.PCStyle.iNameCheck;
|
||||
result.PayZoneFlag = player.PCStyle2.iPayzoneFlag;
|
||||
result.PlayerID = player.PCStyle.iPC_UID;
|
||||
result.SkinColor = player.PCStyle.iSkinColor;
|
||||
result.slot = player.slot;
|
||||
//taros
|
||||
result.TutorialFlag = player.PCStyle2.iTutorialFlag;
|
||||
result.x_coordinates = player.x;
|
||||
result.y_coordinates = player.y;
|
||||
result.z_coordinates = player.z;
|
||||
|
||||
sqlite3pp::query qry(db, "SELECT COUNT(AccountID) FROM Players WHERE AccountID = :AccID AND PlayerID = :PID");
|
||||
|
||||
qry.bind(":AccID", accountID);
|
||||
qry.bind(":PID", characterID);
|
||||
sqlite3pp::query::iterator i = qry.begin();
|
||||
|
||||
int result;
|
||||
std::tie(result) = (*i).get_columns<int>(0);
|
||||
|
||||
if (result > 0) {
|
||||
// get player character slot
|
||||
sqlite3pp::query qry(db, "SELECT Slot FROM Players WHERE PlayerID = :PID");
|
||||
|
||||
// bind & execute
|
||||
qry.bind(":PID", characterID);
|
||||
sqlite3pp::query::iterator i = qry.begin();
|
||||
|
||||
// grab the slot to return
|
||||
int slot;
|
||||
std::tie(slot) = (*i).get_columns<int>(0);
|
||||
|
||||
// actually delete the record
|
||||
sqlite3pp::command cmd(db, "DELETE FROM Players WHERE PlayerID = :ID");
|
||||
cmd.bind(":ID", characterID);
|
||||
cmd.execute();
|
||||
|
||||
// finally, return the grabbed slot
|
||||
return slot;
|
||||
}
|
||||
|
||||
return -1;
|
||||
return result;
|
||||
}
|
||||
|
||||
// TODO: this should really be std::vector, but for the sake of compatibility with PRs, I'll change this after merging
|
||||
std::list<Player> Database::getCharacters(int userID) {
|
||||
std::list<Player> result = std::list<Player>();
|
||||
Player Database::DbToPlayer(DbPlayer player) {
|
||||
Player result;
|
||||
|
||||
result.accountId = player.AccountID;
|
||||
result.PCStyle2.iAppearanceFlag = player.AppearanceFlag;
|
||||
result.PCStyle.iBody = player.Body;
|
||||
result.PCStyle.iClass = player.Class;
|
||||
result.PCStyle.iEyeColor = player.EyeColor;
|
||||
result.PCStyle.iFaceStyle = player.FaceStyle;
|
||||
U8toU16(player.FirstName, result.PCStyle.szFirstName);
|
||||
result.PCStyle.iGender = player.Gender;
|
||||
result.PCStyle.iHairColor = player.HairColor;
|
||||
result.PCStyle.iHairStyle = player.HairStyle;
|
||||
result.PCStyle.iHeight = player.Height;
|
||||
result.HP = player.HP;
|
||||
result.IsGM = player.isGM;
|
||||
U8toU16(player.LastName, result.PCStyle.szLastName);
|
||||
result.level = player.Level;
|
||||
result.PCStyle.iNameCheck = player.NameCheck;
|
||||
result.PCStyle2.iPayzoneFlag = player.PayZoneFlag;
|
||||
result.iID = player.PlayerID;
|
||||
result.PCStyle.iPC_UID = player.PlayerID;
|
||||
result.PCStyle.iSkinColor = player.SkinColor;
|
||||
result.slot = player.slot;
|
||||
result.PCStyle2.iTutorialFlag = player.TutorialFlag;
|
||||
result.x = player.x_coordinates;
|
||||
result.y = player.y_coordinates;
|
||||
result.z = player.z_coordinates;
|
||||
|
||||
sqlite3pp::query qry(db, "SELECT * FROM Players WHERE AccountID = :ID");
|
||||
//TODO:: implement all of below
|
||||
result.SerialKey = 0;
|
||||
result.money = 0;
|
||||
result.fusionmatter = 0;
|
||||
result.activeNano = 0;
|
||||
result.iPCState = 0;
|
||||
result.equippedNanos[0] = 1;
|
||||
result.equippedNanos[1] = 0;
|
||||
result.equippedNanos[2] = 0;
|
||||
result.isTrading = false;
|
||||
result.isTradeConfirm = false;
|
||||
|
||||
qry.bind(":ID", userID);
|
||||
result.Nanos[1].iID = 1;
|
||||
result.Nanos[1].iSkillID = 1;
|
||||
result.Nanos[1].iStamina = 150;
|
||||
|
||||
// for each character owned by the account,
|
||||
for (sqlite3pp::query::iterator i = qry.begin(); i != qry.end(); ++i) {
|
||||
// grab the data
|
||||
int ID, AccountID, slot;
|
||||
char const* charData, * first, * second;
|
||||
std::tie(ID, AccountID, slot, first, second, charData) =
|
||||
(*i).get_columns<int, int, int, char const*, char const*, char const*>(0, 1, 2, 3, 4, 5);
|
||||
for (int i = 2; i < 37; i++) {
|
||||
result.Nanos[i].iID = 0;
|
||||
result.Nanos[i].iSkillID = 0;
|
||||
result.Nanos[i].iStamina = 0;
|
||||
}
|
||||
|
||||
result.Equip[0].iID = player.EquipWeapon1;
|
||||
result.Equip[0].iType = 0;
|
||||
(player.EquipWeapon1) ? result.Equip[0].iOpt = 1 : result.Equip[0].iOpt = 0;
|
||||
|
||||
// convert to player
|
||||
Player toadd = JsonToPlayer(charData, ID);
|
||||
toadd.slot = slot;
|
||||
result.Equip[1].iID = player.EquipUB;
|
||||
result.Equip[1].iType = 1;
|
||||
(player.EquipUB) ? result.Equip[1].iOpt = 1 : result.Equip[1].iOpt = 0;
|
||||
|
||||
// add it to the results
|
||||
result.push_back(toadd);
|
||||
}
|
||||
return result;
|
||||
result.Equip[2].iID = player.EquipLB;
|
||||
result.Equip[2].iType = 2;
|
||||
(player.EquipLB) ? result.Equip[2].iOpt = 1 : result.Equip[2].iOpt = 0;
|
||||
|
||||
result.Equip[3].iID = player.EquipFoot;
|
||||
result.Equip[3].iType = 3;
|
||||
(player.EquipFoot) ? result.Equip[3].iOpt = 1 : result.Equip[3].iOpt = 0;
|
||||
|
||||
|
||||
|
||||
for (int i = 4; i < AEQUIP_COUNT; i++) {
|
||||
// empty equips
|
||||
result.Equip[i].iID = 0;
|
||||
result.Equip[i].iType = i;
|
||||
result.Equip[i].iOpt = 0;
|
||||
}
|
||||
for (int i = 0; i < AINVEN_COUNT; i++) {
|
||||
// setup inventories
|
||||
result.Inven[i].iID = 0;
|
||||
result.Inven[i].iType = 0;
|
||||
result.Inven[i].iOpt = 0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string Database::CharacterToJson(sP_CL2LS_REQ_SAVE_CHAR_NAME* save) {
|
||||
nlohmann::json json = {
|
||||
{"Level",36},
|
||||
//to check
|
||||
{"HP",1000},
|
||||
{"NameCheck", 1},
|
||||
{"FirstName",U16toU8(save->szFirstName)},
|
||||
{"LastName",U16toU8(save->szLastName)},
|
||||
{"Gender",rand() % 2 + 1 },
|
||||
{"FaceStyle",1},
|
||||
{"HairStyle",1},
|
||||
{"HairColor",(rand() % 19) + 1},
|
||||
{"SkinColor",(rand() % 13) + 1},
|
||||
{"EyeColor",(rand() % 6) + 1},
|
||||
{"Height",(rand() % 6)},
|
||||
{"Body",(rand() % 4)},
|
||||
{"Class",0},
|
||||
{"AppearanceFlag",0},
|
||||
{"PayzoneFlag",1},
|
||||
{"TutorialFlag",0},
|
||||
{"EquipUB", 217},
|
||||
{"EquipLB", 203},
|
||||
{"EquipFoot", 314},
|
||||
{"EquipWeapon", 0},
|
||||
{"x",settings::SPAWN_X},
|
||||
{"y",settings::SPAWN_Y},
|
||||
{"z",settings::SPAWN_Z},
|
||||
{"isGM",false},
|
||||
};
|
||||
return json.dump();
|
||||
Database::DbPlayer Database::getDbPlayerById(int id) {
|
||||
return db.get_all<DbPlayer>(where(c(&DbPlayer::PlayerID) == id))
|
||||
.front();
|
||||
}
|
||||
|
||||
std::string Database::PlayerToJson(Player player) {
|
||||
nlohmann::json json = {
|
||||
{"Level",player.level},
|
||||
//to check
|
||||
{"HP",player.HP},
|
||||
{"NameCheck", 1},
|
||||
{"FirstName",U16toU8(player.PCStyle.szFirstName)},
|
||||
{"LastName",U16toU8(player.PCStyle.szLastName)},
|
||||
{"Gender",player.PCStyle.iGender},
|
||||
{"FaceStyle",player.PCStyle.iFaceStyle},
|
||||
{"HairStyle",player.PCStyle.iHairStyle},
|
||||
{"HairColor",player.PCStyle.iHairColor},
|
||||
{"SkinColor",player.PCStyle.iSkinColor},
|
||||
{"EyeColor",player.PCStyle.iEyeColor},
|
||||
{"Height",player.PCStyle.iHeight},
|
||||
{"Body",player.PCStyle.iBody},
|
||||
{"Class",player.PCStyle.iClass},
|
||||
{"AppearanceFlag",player.PCStyle2.iAppearanceFlag},
|
||||
{"PayzoneFlag",player.PCStyle2.iPayzoneFlag},
|
||||
{"TutorialFlag",player.PCStyle2.iTutorialFlag},
|
||||
{"EquipUB", player.Equip[1].iID},
|
||||
{"EquipLB", player.Equip[2].iID},
|
||||
{"EquipFoot", player.Equip[3].iID},
|
||||
{"EquipWeapon", player.Equip[0].iID},
|
||||
{"x",player.x},
|
||||
{"y",player.y},
|
||||
{"z",player.z},
|
||||
{"isGM",false},
|
||||
};
|
||||
return json.dump();
|
||||
}
|
||||
|
||||
Player Database::JsonToPlayer(std::string input, int PC_UID) {
|
||||
std::string err;
|
||||
const auto json = nlohmann::json::parse(input);
|
||||
Player player;
|
||||
player.PCStyle.iPC_UID = (int64_t)PC_UID;
|
||||
player.level = std::stoi(json["Level"].dump());
|
||||
player.HP = std::stoi(json["HP"].dump());
|
||||
player.PCStyle.iNameCheck = std::stoi(json["NameCheck"].dump());
|
||||
U8toU16(json["FirstName"].get<std::string>(), player.PCStyle.szFirstName);
|
||||
U8toU16(json["LastName"].get<std::string>(), player.PCStyle.szLastName);
|
||||
player.PCStyle.iGender = std::stoi(json["Gender"].dump());
|
||||
player.PCStyle.iFaceStyle = std::stoi(json["FaceStyle"].dump());
|
||||
player.PCStyle.iHairStyle = std::stoi(json["HairStyle"].dump());
|
||||
player.PCStyle.iHairColor = std::stoi(json["HairColor"].dump());
|
||||
player.PCStyle.iSkinColor = std::stoi(json["SkinColor"].dump());
|
||||
player.PCStyle.iEyeColor = std::stoi(json["EyeColor"].dump());
|
||||
player.PCStyle.iHeight = std::stoi(json["Height"].dump());
|
||||
player.PCStyle.iBody = std::stoi(json["Body"].dump());
|
||||
player.PCStyle.iClass = std::stoi(json["Class"].dump());
|
||||
player.PCStyle2.iAppearanceFlag = std::stoi(json["AppearanceFlag"].dump());
|
||||
player.PCStyle2.iPayzoneFlag = std::stoi(json["PayzoneFlag"].dump());
|
||||
player.PCStyle2.iTutorialFlag = std::stoi(json["TutorialFlag"].dump());
|
||||
player.Equip[0].iID = std::stoi(json["EquipWeapon"].dump());
|
||||
if (player.Equip[0].iID != 0)
|
||||
player.Equip[0].iOpt = 1;
|
||||
else
|
||||
player.Equip[0].iOpt = 0;
|
||||
player.Equip[0].iType = 0;
|
||||
player.Equip[1].iID = std::stoi(json["EquipUB"].dump());
|
||||
player.Equip[1].iOpt = 1;
|
||||
player.Equip[1].iType = 1;
|
||||
player.Equip[2].iID = std::stoi(json["EquipLB"].dump());
|
||||
player.Equip[2].iOpt = 1;
|
||||
player.Equip[2].iType = 2;
|
||||
player.Equip[3].iID = std::stoi(json["EquipFoot"].dump());
|
||||
player.Equip[3].iOpt = 1;
|
||||
player.Equip[3].iType = 3;
|
||||
player.x = std::stoi(json["x"].dump());
|
||||
player.y = std::stoi(json["y"].dump());
|
||||
player.z = std::stoi(json["z"].dump());
|
||||
return player;
|
||||
}
|
||||
|
||||
std::string Database::CharacterToJson(sP_CL2LS_REQ_CHAR_CREATE* character) {
|
||||
nlohmann::json json = {
|
||||
{"Level",36},
|
||||
//to check
|
||||
{"HP",1000},
|
||||
{"NameCheck", 1},
|
||||
{"FirstName",U16toU8(character->PCStyle.szFirstName)},
|
||||
{"LastName",U16toU8(character->PCStyle.szLastName)},
|
||||
{"Gender",character->PCStyle.iGender},
|
||||
{"FaceStyle",character->PCStyle.iFaceStyle},
|
||||
{"HairStyle",character->PCStyle.iHairStyle},
|
||||
{"HairColor",character->PCStyle.iHairColor},
|
||||
{"SkinColor",character->PCStyle.iSkinColor},
|
||||
{"EyeColor",character->PCStyle.iEyeColor},
|
||||
{"Height",character->PCStyle.iHeight},
|
||||
{"Body",character->PCStyle.iBody},
|
||||
{"Class",character->PCStyle.iClass},
|
||||
{"AppearanceFlag",1},
|
||||
{"PayzoneFlag",1},
|
||||
{"TutorialFlag",0},
|
||||
{"EquipUB", character->sOn_Item.iEquipUBID},
|
||||
{"EquipLB", character->sOn_Item.iEquipLBID},
|
||||
{"EquipFoot", character->sOn_Item.iEquipFootID},
|
||||
{"EquipWeapon", 0},
|
||||
{"x",settings::SPAWN_X},
|
||||
{"y",settings::SPAWN_Y},
|
||||
{"z",settings::SPAWN_Z},
|
||||
{"isGM",false},
|
||||
};
|
||||
return json.dump();
|
||||
}
|
||||
#pragma endregion LoginServer
|
||||
|
||||
Reference in New Issue
Block a user