From b239fb9331b53abb6cb2d0e7279d612cea68f176 Mon Sep 17 00:00:00 2001 From: Eperty123 Date: Sat, 29 Aug 2020 13:14:21 +0200 Subject: [PATCH 1/3] Add NPC barking, seeing saved characters --- src/CNLoginServer.cpp | 671 +++++++++++++++++++++--------------------- src/Database.cpp | 633 +++++++++++++++++++-------------------- src/NPCManager.cpp | 86 ++++-- src/NPCManager.hpp | 6 +- src/PlayerManager.cpp | 2 +- 5 files changed, 713 insertions(+), 685 deletions(-) diff --git a/src/CNLoginServer.cpp b/src/CNLoginServer.cpp index 3633502..d6e631d 100644 --- a/src/CNLoginServer.cpp +++ b/src/CNLoginServer.cpp @@ -17,155 +17,82 @@ void CNLoginServer::handlePacket(CNSocket* sock, CNPacketData* data) { printPacket(data, CL2LS); switch (data->type) { - case P_CL2LS_REQ_LOGIN: { - if (data->size != sizeof(sP_CL2LS_REQ_LOGIN)) - return; // ignore the malformed packet + case P_CL2LS_REQ_LOGIN: { + if (data->size != sizeof(sP_CL2LS_REQ_LOGIN)) + return; // ignore the malformed packet - sP_CL2LS_REQ_LOGIN* login = (sP_CL2LS_REQ_LOGIN*)data->buf; - bool success = false; - int errorCode = 0; - std::string userLogin = U16toU8(login->szID); - std::string userPassword = U16toU8(login->szPassword); - //checking regex - if (!Database::isLoginDataGood(userLogin, userPassword)) { - errorCode = (int)LOGINERRORID::login_error; - } + sP_CL2LS_REQ_LOGIN* login = (sP_CL2LS_REQ_LOGIN*)data->buf; + bool success = false; + int errorCode = 0; + std::string userLogin = U16toU8(login->szID); + std::string userPassword = U16toU8(login->szPassword); + //checking regex + if (!Database::isLoginDataGood(userLogin, userPassword)) { + errorCode = (int)LOGINERRORID::login_error; + } - //if user does not exist in db, add him to and send succ - else if (!Database::doesUserExist(U16toU8(login->szID))) { - Database::addAccount(U16toU8(login->szID), U16toU8(login->szPassword)); - success = true; - } - //if user exists, check if password is correct - else if (Database::isPasswordCorrect((U16toU8(login->szID)), U16toU8(login->szPassword))) { - success = true; - } - else { - errorCode = (int)LOGINERRORID::id_and_password_do_not_match; - } + //if user does not exist in db, add him to and send succ + else if (!Database::doesUserExist(U16toU8(login->szID))) { + Database::addAccount(U16toU8(login->szID), U16toU8(login->szPassword)); + success = true; + } + //if user exists, check if password is correct + else if (Database::isPasswordCorrect((U16toU8(login->szID)), U16toU8(login->szPassword))) { + success = true; + } + else { + errorCode = (int)LOGINERRORID::id_and_password_do_not_match; + } - if (success) - { - int userID = Database::getUserID(userLogin); - int charCount = Database::getUserSlotsNum(userID); + if (success) + { + int userID = Database::getUserID(userLogin); + int charCount = Database::getUserSlotsNum(userID); - INITSTRUCT(sP_LS2CL_REP_LOGIN_SUCC, resp); - // set username in resp packet - memcpy(resp.szID, login->szID, sizeof(char16_t) * 33); + INITSTRUCT(sP_LS2CL_REP_LOGIN_SUCC, resp); + // set username in resp packet + memcpy(resp.szID, login->szID, sizeof(char16_t) * 33); - resp.iCharCount = charCount; - resp.iSlotNum = 1; - resp.iPaymentFlag = 1; - resp.iOpenBetaFlag = 0; - resp.uiSvrTime = getTime(); + resp.iCharCount = charCount; + resp.iSlotNum = 1; + resp.iPaymentFlag = 1; + resp.iOpenBetaFlag = 0; + resp.uiSvrTime = getTime(); - // send the resp in with original key - sock->sendPacket((void*)&resp, P_LS2CL_REP_LOGIN_SUCC, sizeof(sP_LS2CL_REP_LOGIN_SUCC)); + // send the resp in with original key + sock->sendPacket((void*)&resp, P_LS2CL_REP_LOGIN_SUCC, sizeof(sP_LS2CL_REP_LOGIN_SUCC)); - // update keys - sock->setEKey(CNSocketEncryption::createNewKey(resp.uiSvrTime, resp.iCharCount + 1, resp.iSlotNum + 1)); - sock->setFEKey(CNSocketEncryption::createNewKey((uint64_t)(*(uint64_t*)&CNSocketEncryption::defaultKey[0]), login->iClientVerC, 1)); + // update keys + sock->setEKey(CNSocketEncryption::createNewKey(resp.uiSvrTime, resp.iCharCount + 1, resp.iSlotNum + 1)); + sock->setFEKey(CNSocketEncryption::createNewKey((uint64_t)(*(uint64_t*)&CNSocketEncryption::defaultKey[0]), login->iClientVerC, 1)); - loginSessions[sock] = CNLoginData(); - loginSessions[sock].userID = userID; + loginSessions[sock] = CNLoginData(); + loginSessions[sock].userID = userID; - // now send the characters :) - - /*if (charCount > 0) { + // now send the characters :) - std::list characters = Database::getCharacters(loginSessions[sock].userID); - std::list::iterator it; - for (it = characters.begin(); it != characters.end(); it++) - { - sP_LS2CL_REP_CHAR_INFO charInfo = sP_LS2CL_REP_CHAR_INFO(); + if (charCount > 0) { - charInfo.iSlot = (int8_t)it->slot; - charInfo.iLevel = (int16_t)it->level; - charInfo.sPC_Style = it->PCStyle; - charInfo.sPC_Style2 = it->PCStyle2; - - // position - charInfo.iX = it->x; - charInfo.iY = it->y; - charInfo.iZ = it->z; - - //save character in session (for char select) - int64_t UID = charInfo.sPC_Style.iPC_UID; - loginSessions[sock].characters[UID] = Player(); - loginSessions[sock].characters[UID].level = charInfo.iLevel; - loginSessions[sock].characters[UID].slot = charInfo.iSlot; - loginSessions[sock].characters[UID].FEKey = sock->getFEKey(); - loginSessions[sock].characters[UID].x = charInfo.iX; - loginSessions[sock].characters[UID].y = charInfo.iY; - loginSessions[sock].characters[UID].z = charInfo.iZ; - loginSessions[sock].characters[UID].PCStyle = charInfo.sPC_Style; - loginSessions[sock].characters[UID].PCStyle2 = charInfo.sPC_Style2; - loginSessions[sock].characters[UID].IsGM = false; - loginSessions[sock].characters[UID].money = 9001; - - - - Player test = loginSessions[sock].characters[UID]; - - for (int i = 0; i < 4; i++) { - //equip char creation clothes and lightning rifle - charInfo.aEquip[i] = it->Equip[i]; - loginSessions[sock].characters[UID].Equip[i] = charInfo.aEquip[i]; - } - - for (int i = 5; i < AEQUIP_COUNT; i++) { - // empty equips - charInfo.aEquip[i].iID = 0; - charInfo.aEquip[i].iType = i; - charInfo.aEquip[i].iOpt = 0; - loginSessions[sock].characters[UID].Equip[i] = charInfo.aEquip[i]; - } - - - for (int i = 0; i < AINVEN_COUNT; i++) { - // setup inventories - loginSessions[sock].characters[UID].Inven[i].iID = 0; - loginSessions[sock].characters[UID].Inven[i].iType = 0; - loginSessions[sock].characters[UID].Inven[i].iOpt = 0; - } - - // set default to the first character - if (it == characters.begin()) - loginSessions[sock].selectedChar = UID; - - sock->sendPacket((void*)&charInfo, P_LS2CL_REP_CHAR_INFO, sizeof(sP_LS2CL_REP_CHAR_INFO)); - - for (int i = 0; i < charCount; i++) { + std::list characters = Database::getCharacters(loginSessions[sock].userID); + std::list::iterator it; + for (it = characters.begin(); it != characters.end(); it++) + { sP_LS2CL_REP_CHAR_INFO charInfo = sP_LS2CL_REP_CHAR_INFO(); - charInfo.iSlot = (int8_t)i + 1; - charInfo.iLevel = (int16_t)36; - charInfo.sPC_Style.iPC_UID = rand(); // unique identifier for the character - charInfo.sPC_Style.iNameCheck = 1; - charInfo.sPC_Style.iGender = (i%2)+1; // can be 1(boy) or 2(girl) - charInfo.sPC_Style.iFaceStyle = 1; - charInfo.sPC_Style.iHairStyle = 1; - charInfo.sPC_Style.iHairColor = (rand()%19) + 1; // 1 - 19 - charInfo.sPC_Style.iSkinColor = (rand()%13) + 1; // 1 - 13 - charInfo.sPC_Style.iEyeColor = (rand()%6) + 1; // 1 - 6 - charInfo.sPC_Style.iHeight = (rand()%6); // 0 -5 - charInfo.sPC_Style.iBody = (rand()%4); // 0 - 3 - charInfo.sPC_Style.iClass = 0; - charInfo.sPC_Style2.iAppearanceFlag = 1; - charInfo.sPC_Style2.iPayzoneFlag = 1; - charInfo.sPC_Style2.iTutorialFlag = 1; - // past's town hall - charInfo.iX = settings::SPAWN_X; - charInfo.iY = settings::SPAWN_Y; - charInfo.iZ = settings::SPAWN_Z; + charInfo.iSlot = (int8_t)it->slot; + charInfo.iLevel = (int16_t)it->level; + charInfo.sPC_Style = it->PCStyle; + charInfo.sPC_Style2 = it->PCStyle2; - U8toU16(std::string("Player"), charInfo.sPC_Style.szFirstName); - U8toU16(std::to_string(i + 1), charInfo.sPC_Style.szLastName); + // position + charInfo.iX = it->x; + charInfo.iY = it->y; + charInfo.iZ = it->z; + //save character in session (for char select) int64_t UID = charInfo.sPC_Style.iPC_UID; loginSessions[sock].characters[UID] = Player(); loginSessions[sock].characters[UID].level = charInfo.iLevel; - loginSessions[sock].characters[UID].money = 9001; loginSessions[sock].characters[UID].slot = charInfo.iSlot; loginSessions[sock].characters[UID].FEKey = sock->getFEKey(); loginSessions[sock].characters[UID].x = charInfo.iX; @@ -173,258 +100,334 @@ void CNLoginServer::handlePacket(CNSocket* sock, CNPacketData* data) { loginSessions[sock].characters[UID].z = charInfo.iZ; loginSessions[sock].characters[UID].PCStyle = charInfo.sPC_Style; loginSessions[sock].characters[UID].PCStyle2 = charInfo.sPC_Style2; - loginSessions[sock].characters[UID].isTrading = false; - loginSessions[sock].characters[UID].isTradeConfirm = false; - loginSessions[sock].characters[UID].IsGM = settings::GM; + loginSessions[sock].characters[UID].IsGM = false; + loginSessions[sock].characters[UID].money = 9001; - for (int i = 0; i < AEQUIP_COUNT; i++) { - // setup equips + + + Player test = loginSessions[sock].characters[UID]; + + for (int i = 0; i < 4; i++) { + //equip char creation clothes and lightning rifle + charInfo.aEquip[i] = it->Equip[i]; + loginSessions[sock].characters[UID].Equip[i] = charInfo.aEquip[i]; + } + + for (int i = 5; i < AEQUIP_COUNT; i++) { + // empty equips charInfo.aEquip[i].iID = 0; charInfo.aEquip[i].iType = i; charInfo.aEquip[i].iOpt = 0; loginSessions[sock].characters[UID].Equip[i] = charInfo.aEquip[i]; } - + + for (int i = 0; i < AINVEN_COUNT; i++) { // setup inventories loginSessions[sock].characters[UID].Inven[i].iID = 0; loginSessions[sock].characters[UID].Inven[i].iType = 0; loginSessions[sock].characters[UID].Inven[i].iOpt = 0; - } - }*/ + + // set default to the first character + if (it == characters.begin()) + loginSessions[sock].selectedChar = UID; + + sock->sendPacket((void*)&charInfo, P_LS2CL_REP_CHAR_INFO, sizeof(sP_LS2CL_REP_CHAR_INFO)); + + } } - //Failure - else { + //for (int i = 0; i < charCount; i++) { + // sP_LS2CL_REP_CHAR_INFO charInfo = sP_LS2CL_REP_CHAR_INFO(); + // charInfo.iSlot = (int8_t)i + 1; + // charInfo.iLevel = (int16_t)36; + // charInfo.sPC_Style.iPC_UID = rand(); // unique identifier for the character + // charInfo.sPC_Style.iNameCheck = 1; + // charInfo.sPC_Style.iGender = (i%2)+1; // can be 1(boy) or 2(girl) + // charInfo.sPC_Style.iFaceStyle = 1; + // charInfo.sPC_Style.iHairStyle = 1; + // charInfo.sPC_Style.iHairColor = (rand()%19) + 1; // 1 - 19 + // charInfo.sPC_Style.iSkinColor = (rand()%13) + 1; // 1 - 13 + // charInfo.sPC_Style.iEyeColor = (rand()%6) + 1; // 1 - 6 + // charInfo.sPC_Style.iHeight = (rand()%6); // 0 -5 + // charInfo.sPC_Style.iBody = (rand()%4); // 0 - 3 + // charInfo.sPC_Style.iClass = 0; + // charInfo.sPC_Style2.iAppearanceFlag = 1; + // charInfo.sPC_Style2.iPayzoneFlag = 1; + // charInfo.sPC_Style2.iTutorialFlag = 1; - INITSTRUCT(sP_LS2CL_REP_LOGIN_FAIL, resp); + // // past's town hall + // charInfo.iX = settings::SPAWN_X; + // charInfo.iY = settings::SPAWN_Y; + // charInfo.iZ = settings::SPAWN_Z; - memcpy(resp.szID, login->szID, sizeof(char16_t) * 33); - resp.iErrorCode = errorCode; + // U8toU16(std::string("Player"), charInfo.sPC_Style.szFirstName); + // U8toU16(std::to_string(i + 1), charInfo.sPC_Style.szLastName); - sock->sendPacket((void*)&resp, P_LS2CL_REP_LOGIN_FAIL, sizeof(sP_LS2CL_REP_LOGIN_FAIL)); - } + // int64_t UID = charInfo.sPC_Style.iPC_UID; + // loginSessions[sock].characters[UID] = Player(); + // loginSessions[sock].characters[UID].level = charInfo.iLevel; + // loginSessions[sock].characters[UID].money = 9001; + // loginSessions[sock].characters[UID].slot = charInfo.iSlot; + // loginSessions[sock].characters[UID].FEKey = sock->getFEKey(); + // loginSessions[sock].characters[UID].x = charInfo.iX; + // loginSessions[sock].characters[UID].y = charInfo.iY; + // loginSessions[sock].characters[UID].z = charInfo.iZ; + // loginSessions[sock].characters[UID].PCStyle = charInfo.sPC_Style; + // loginSessions[sock].characters[UID].PCStyle2 = charInfo.sPC_Style2; + // loginSessions[sock].characters[UID].isTrading = false; + // loginSessions[sock].characters[UID].isTradeConfirm = false; + // loginSessions[sock].characters[UID].IsGM = settings::GM; - break; + // for (int i = 0; i < AEQUIP_COUNT; i++) { + // // setup equips + // charInfo.aEquip[i].iID = 0; + // charInfo.aEquip[i].iType = i; + // charInfo.aEquip[i].iOpt = 0; + // loginSessions[sock].characters[UID].Equip[i] = charInfo.aEquip[i]; + // } + // + // for (int i = 0; i < AINVEN_COUNT; i++) { + // // setup inventories + // loginSessions[sock].characters[UID].Inven[i].iID = 0; + // loginSessions[sock].characters[UID].Inven[i].iType = 0; + // loginSessions[sock].characters[UID].Inven[i].iOpt = 0; + + // } + //} } - case P_CL2LS_REP_LIVE_CHECK: { - // stubbed, the client really doesn't care LOL - break; + //Failure + else { + + INITSTRUCT(sP_LS2CL_REP_LOGIN_FAIL, resp); + + memcpy(resp.szID, login->szID, sizeof(char16_t) * 33); + resp.iErrorCode = errorCode; + + sock->sendPacket((void*)&resp, P_LS2CL_REP_LOGIN_FAIL, sizeof(sP_LS2CL_REP_LOGIN_FAIL)); } - case P_CL2LS_REQ_CHECK_CHAR_NAME: { - if (data->size != sizeof(sP_CL2LS_REQ_CHECK_CHAR_NAME)) - return; - - // naughty words allowed!!!!!!!! (also for some reason, the client will always show 'Player 0' if you manually type a name. It will show up for other connected players though) - sP_CL2LS_REQ_CHECK_CHAR_NAME* nameCheck = (sP_CL2LS_REQ_CHECK_CHAR_NAME*)data->buf; - //check if name is occupied - if (Database::isNameFree(U16toU8(nameCheck->szFirstName), U16toU8(nameCheck->szLastName))) - { - // naughty words allowed!!!!!!!! (also for some reason, the client will always show 'Player + ID' if you manually type a name. It will show up for other connected players though) + break; + } + case P_CL2LS_REP_LIVE_CHECK: { + // stubbed, the client really doesn't care LOL + break; + } + case P_CL2LS_REQ_CHECK_CHAR_NAME: { + if (data->size != sizeof(sP_CL2LS_REQ_CHECK_CHAR_NAME)) + return; - INITSTRUCT(sP_LS2CL_REP_CHECK_CHAR_NAME_SUCC, resp); + // naughty words allowed!!!!!!!! (also for some reason, the client will always show 'Player 0' if you manually type a name. It will show up for other connected players though) + sP_CL2LS_REQ_CHECK_CHAR_NAME* nameCheck = (sP_CL2LS_REQ_CHECK_CHAR_NAME*)data->buf; + //check if name is occupied + if (Database::isNameFree(U16toU8(nameCheck->szFirstName), U16toU8(nameCheck->szLastName))) + { - DEBUGLOG( - std::cout << "P_CL2LS_REQ_CHECK_CHAR_NAME:" << std::endl; - std::cout << "\tFirstName: " << U16toU8(nameCheck->szFirstName) << " LastName: " << U16toU8(nameCheck->szLastName) << std::endl; - ) + // naughty words allowed!!!!!!!! (also for some reason, the client will always show 'Player + ID' if you manually type a name. It will show up for other connected players though) - memcpy(resp.szFirstName, nameCheck->szFirstName, sizeof(char16_t) * 9); - memcpy(resp.szLastName, nameCheck->szLastName, sizeof(char16_t) * 17); - - // fr*ck allowed!!! - sock->sendPacket((void*)&resp, P_LS2CL_REP_CHECK_CHAR_NAME_SUCC, sizeof(sP_LS2CL_REP_CHECK_CHAR_NAME_SUCC)); - } - else { - INITSTRUCT(sP_LS2CL_REP_CHECK_CHAR_NAME_FAIL, resp); - resp.iErrorCode = 1; - sock->sendPacket((void*)&resp, P_LS2CL_REP_CHECK_CHAR_NAME_FAIL, sizeof(sP_LS2CL_REP_CHECK_CHAR_NAME_FAIL)); - } - break; - - } - case P_CL2LS_REQ_SAVE_CHAR_NAME: { - if (data->size != sizeof(sP_CL2LS_REQ_SAVE_CHAR_NAME)) - return; - - sP_CL2LS_REQ_SAVE_CHAR_NAME* save = (sP_CL2LS_REQ_SAVE_CHAR_NAME*)data->buf; - Database::createCharacter(save, loginSessions[sock].userID); - - INITSTRUCT(sP_LS2CL_REP_SAVE_CHAR_NAME_SUCC, resp); + INITSTRUCT(sP_LS2CL_REP_CHECK_CHAR_NAME_SUCC, resp); DEBUGLOG( - std::cout << "P_CL2LS_REQ_SAVE_CHAR_NAME:" << std::endl; - std::cout << "\tSlot: " << (int)save->iSlotNum << std::endl; - std::cout << "\tName: " << U16toU8(save->szFirstName) << " " << U16toU8(save->szLastName) << std::endl; + std::cout << "P_CL2LS_REQ_CHECK_CHAR_NAME:" << std::endl; + std::cout << "\tFirstName: " << U16toU8(nameCheck->szFirstName) << " LastName: " << U16toU8(nameCheck->szLastName) << std::endl; ) + memcpy(resp.szFirstName, nameCheck->szFirstName, sizeof(char16_t) * 9); + memcpy(resp.szLastName, nameCheck->szLastName, sizeof(char16_t) * 17); + + // fr*ck allowed!!! + sock->sendPacket((void*)&resp, P_LS2CL_REP_CHECK_CHAR_NAME_SUCC, sizeof(sP_LS2CL_REP_CHECK_CHAR_NAME_SUCC)); + } + else { + INITSTRUCT(sP_LS2CL_REP_CHECK_CHAR_NAME_FAIL, resp); + resp.iErrorCode = 1; + sock->sendPacket((void*)&resp, P_LS2CL_REP_CHECK_CHAR_NAME_FAIL, sizeof(sP_LS2CL_REP_CHECK_CHAR_NAME_FAIL)); + } + break; + + } + case P_CL2LS_REQ_SAVE_CHAR_NAME: { + if (data->size != sizeof(sP_CL2LS_REQ_SAVE_CHAR_NAME)) + return; + + sP_CL2LS_REQ_SAVE_CHAR_NAME* save = (sP_CL2LS_REQ_SAVE_CHAR_NAME*)data->buf; + Database::createCharacter(save, loginSessions[sock].userID); + + INITSTRUCT(sP_LS2CL_REP_SAVE_CHAR_NAME_SUCC, resp); + + DEBUGLOG( + std::cout << "P_CL2LS_REQ_SAVE_CHAR_NAME:" << std::endl; + std::cout << "\tSlot: " << (int)save->iSlotNum << std::endl; + std::cout << "\tName: " << U16toU8(save->szFirstName) << " " << U16toU8(save->szLastName) << std::endl; + ) + resp.iSlotNum = save->iSlotNum; - resp.iGender = save->iGender; - resp.iPC_UID = Database::getCharacterID(loginSessions[sock].userID, save->iSlotNum); - memcpy(resp.szFirstName, save->szFirstName, sizeof(char16_t) * 9); - memcpy(resp.szLastName, save->szLastName, sizeof(char16_t) * 17); + resp.iGender = save->iGender; + resp.iPC_UID = Database::getCharacterID(loginSessions[sock].userID, save->iSlotNum); + memcpy(resp.szFirstName, save->szFirstName, sizeof(char16_t) * 9); + memcpy(resp.szLastName, save->szLastName, sizeof(char16_t) * 17); - sock->sendPacket((void*)&resp, P_LS2CL_REP_SAVE_CHAR_NAME_SUCC, sizeof(sP_LS2CL_REP_SAVE_CHAR_NAME_SUCC)); - break; - } - case P_CL2LS_REQ_CHAR_CREATE: { - if (data->size != sizeof(sP_CL2LS_REQ_CHAR_CREATE)) - return; - - sP_CL2LS_REQ_CHAR_CREATE* character = (sP_CL2LS_REQ_CHAR_CREATE*)data->buf; - Database::finishCharacter(character); + sock->sendPacket((void*)&resp, P_LS2CL_REP_SAVE_CHAR_NAME_SUCC, sizeof(sP_LS2CL_REP_SAVE_CHAR_NAME_SUCC)); + break; + } + case P_CL2LS_REQ_CHAR_CREATE: { + if (data->size != sizeof(sP_CL2LS_REQ_CHAR_CREATE)) + return; - INITSTRUCT(sP_LS2CL_REP_CHAR_CREATE_SUCC, resp); + sP_CL2LS_REQ_CHAR_CREATE* character = (sP_CL2LS_REQ_CHAR_CREATE*)data->buf; + Database::finishCharacter(character); + + INITSTRUCT(sP_LS2CL_REP_CHAR_CREATE_SUCC, resp); + + DEBUGLOG( + std::cout << "P_CL2LS_REQ_CHAR_CREATE:" << std::endl; + std::cout << "\tPC_UID: " << character->PCStyle.iPC_UID << std::endl; + std::cout << "\tNameCheck: " << (int)character->PCStyle.iNameCheck << std::endl; + std::cout << "\tName: " << U16toU8(character->PCStyle.szFirstName) << " " << U16toU8(character->PCStyle.szLastName) << std::endl; + std::cout << "\tGender: " << (int)character->PCStyle.iGender << std::endl; + std::cout << "\tFace: " << (int)character->PCStyle.iFaceStyle << std::endl; + std::cout << "\tHair: " << (int)character->PCStyle.iHairStyle << std::endl; + std::cout << "\tHair Color: " << (int)character->PCStyle.iHairColor << std::endl; + std::cout << "\tSkin Color: " << (int)character->PCStyle.iSkinColor << std::endl; + std::cout << "\tEye Color: " << (int)character->PCStyle.iEyeColor << std::endl; + std::cout << "\tHeight: " << (int)character->PCStyle.iHeight << std::endl; + std::cout << "\tBody: " << (int)character->PCStyle.iBody << std::endl; + std::cout << "\tClass: " << (int)character->PCStyle.iClass << std::endl; + std::cout << "\tiEquipUBID: " << (int)character->sOn_Item.iEquipUBID << std::endl; + std::cout << "\tiEquipLBID: " << (int)character->sOn_Item.iEquipLBID << std::endl; + std::cout << "\tiEquipFootID: " << (int)character->sOn_Item.iEquipFootID << std::endl; + ) - DEBUGLOG( - std::cout << "P_CL2LS_REQ_CHAR_CREATE:" << std::endl; - std::cout << "\tPC_UID: " << character->PCStyle.iPC_UID << std::endl; - std::cout << "\tNameCheck: " << (int)character->PCStyle.iNameCheck << std::endl; - std::cout << "\tName: " << U16toU8(character->PCStyle.szFirstName) << " " << U16toU8(character->PCStyle.szLastName) << std::endl; - std::cout << "\tGender: " << (int)character->PCStyle.iGender << std::endl; - std::cout << "\tFace: " << (int)character->PCStyle.iFaceStyle << std::endl; - std::cout << "\tHair: " << (int)character->PCStyle.iHairStyle << std::endl; - std::cout << "\tHair Color: " << (int)character->PCStyle.iHairColor << std::endl; - std::cout << "\tSkin Color: " << (int)character->PCStyle.iSkinColor << std::endl; - std::cout << "\tEye Color: " << (int)character->PCStyle.iEyeColor << std::endl; - std::cout << "\tHeight: " << (int)character->PCStyle.iHeight << std::endl; - std::cout << "\tBody: " << (int)character->PCStyle.iBody << std::endl; - std::cout << "\tClass: " << (int)character->PCStyle.iClass << std::endl; - std::cout << "\tiEquipUBID: " << (int)character->sOn_Item.iEquipUBID << std::endl; - std::cout << "\tiEquipLBID: " << (int)character->sOn_Item.iEquipLBID << std::endl; - std::cout << "\tiEquipFootID: " << (int)character->sOn_Item.iEquipFootID << std::endl; - ) - int64_t UID = character->PCStyle.iPC_UID; - - // commented and disabled for now - //bool BecomeGM; - - //if (U16toU8(character->PCStyle.szFirstName) == settings::GMPASS) { - // BecomeGM = true; - // U8toU16("GM",character->PCStyle.szFirstName); - //} else { - // BecomeGM = false; - //} - character->PCStyle.iNameCheck = 1; - resp.sPC_Style = character->PCStyle; - resp.sPC_Style2.iAppearanceFlag = 1; - resp.sPC_Style2.iTutorialFlag = 0; - resp.sPC_Style2.iPayzoneFlag = 1; - resp.iLevel = 36; - resp.sOn_Item = character->sOn_Item; + // commented and disabled for now + //bool BecomeGM; - loginSessions[sock].characters[UID] = Player(); - loginSessions[sock].characters[UID].level = 36; - loginSessions[sock].characters[UID].FEKey = sock->getFEKey(); - loginSessions[sock].characters[UID].PCStyle = character->PCStyle; - loginSessions[sock].characters[UID].PCStyle2.iAppearanceFlag = 1; - loginSessions[sock].characters[UID].PCStyle2.iPayzoneFlag = 1; - loginSessions[sock].characters[UID].PCStyle2.iTutorialFlag = 1; - loginSessions[sock].characters[UID].x = settings::SPAWN_X; - loginSessions[sock].characters[UID].y = settings::SPAWN_Y; - loginSessions[sock].characters[UID].z = settings::SPAWN_Z; - loginSessions[sock].characters[UID].Equip[1].iID = character->sOn_Item.iEquipUBID; // upper body - loginSessions[sock].characters[UID].Equip[1].iType = 1; - loginSessions[sock].characters[UID].Equip[2].iID = character->sOn_Item.iEquipLBID; // lower body - loginSessions[sock].characters[UID].Equip[2].iType = 2; - loginSessions[sock].characters[UID].Equip[3].iID = character->sOn_Item.iEquipFootID; // foot! - loginSessions[sock].characters[UID].Equip[3].iType = 3; - loginSessions[sock].characters[UID].IsGM = false; - loginSessions[sock].characters[UID].Equip[3].iType = 3; - loginSessions[sock].characters[UID].isTrading = false; - loginSessions[sock].characters[UID].isTradeConfirm = false; - loginSessions[sock].characters[UID].IsGM = settings::GM; + //if (U16toU8(character->PCStyle.szFirstName) == settings::GMPASS) { + // BecomeGM = true; + // U8toU16("GM",character->PCStyle.szFirstName); + //} else { + // BecomeGM = false; + //} + + character->PCStyle.iNameCheck = 1; + resp.sPC_Style = character->PCStyle; + resp.sPC_Style2.iAppearanceFlag = 1; + resp.sPC_Style2.iTutorialFlag = 0; + resp.sPC_Style2.iPayzoneFlag = 1; + resp.iLevel = 36; + resp.sOn_Item = character->sOn_Item; + + loginSessions[sock].characters[UID] = Player(); + loginSessions[sock].characters[UID].level = 36; + loginSessions[sock].characters[UID].FEKey = sock->getFEKey(); + loginSessions[sock].characters[UID].PCStyle = character->PCStyle; + loginSessions[sock].characters[UID].PCStyle2.iAppearanceFlag = 1; + loginSessions[sock].characters[UID].PCStyle2.iPayzoneFlag = 1; + loginSessions[sock].characters[UID].PCStyle2.iTutorialFlag = 1; + loginSessions[sock].characters[UID].x = settings::SPAWN_X; + loginSessions[sock].characters[UID].y = settings::SPAWN_Y; + loginSessions[sock].characters[UID].z = settings::SPAWN_Z; + loginSessions[sock].characters[UID].Equip[1].iID = character->sOn_Item.iEquipUBID; // upper body + loginSessions[sock].characters[UID].Equip[1].iType = 1; + loginSessions[sock].characters[UID].Equip[2].iID = character->sOn_Item.iEquipLBID; // lower body + loginSessions[sock].characters[UID].Equip[2].iType = 2; + loginSessions[sock].characters[UID].Equip[3].iID = character->sOn_Item.iEquipFootID; // foot! + loginSessions[sock].characters[UID].Equip[3].iType = 3; + loginSessions[sock].characters[UID].IsGM = false; + loginSessions[sock].characters[UID].Equip[3].iType = 3; + loginSessions[sock].characters[UID].isTrading = false; + loginSessions[sock].characters[UID].isTradeConfirm = false; + loginSessions[sock].characters[UID].IsGM = settings::GM; - sock->sendPacket((void*)&resp, P_LS2CL_REP_CHAR_CREATE_SUCC, sizeof(sP_LS2CL_REP_CHAR_CREATE_SUCC)); - break; + sock->sendPacket((void*)&resp, P_LS2CL_REP_CHAR_CREATE_SUCC, sizeof(sP_LS2CL_REP_CHAR_CREATE_SUCC)); + break; + } + case P_CL2LS_REQ_CHAR_DELETE: { + if (data->size != sizeof(sP_CL2LS_REQ_CHAR_DELETE)) + return; + + sP_CL2LS_REQ_CHAR_DELETE* del = (sP_CL2LS_REQ_CHAR_DELETE*)data->buf; + int operationResult = Database::deleteCharacter(del->iPC_UID, loginSessions[sock].userID); + + // success + if (operationResult > 0) { + INITSTRUCT(sP_LS2CL_REP_CHAR_DELETE_SUCC, resp); + resp.iSlotNum = operationResult; + sock->sendPacket((void*)&resp, P_LS2CL_REP_CHAR_DELETE_SUCC, sizeof(sP_LS2CL_REP_CHAR_DELETE_SUCC)); } - case P_CL2LS_REQ_CHAR_DELETE: { - if (data->size != sizeof(sP_CL2LS_REQ_CHAR_DELETE)) - return; - - sP_CL2LS_REQ_CHAR_DELETE* del = (sP_CL2LS_REQ_CHAR_DELETE*)data->buf; - int operationResult = Database::deleteCharacter(del->iPC_UID, loginSessions[sock].userID); - - // success - if (operationResult > 0) { - INITSTRUCT(sP_LS2CL_REP_CHAR_DELETE_SUCC, resp); - resp.iSlotNum = operationResult; - sock->sendPacket((void*)&resp, P_LS2CL_REP_CHAR_DELETE_SUCC, sizeof(sP_LS2CL_REP_CHAR_DELETE_SUCC)); - } else { - // failure - // client doesnt't care about this packet and softlocks - INITSTRUCT(sP_LS2CL_REP_CHAR_DELETE_FAIL, resp); - resp.iErrorCode = 0; - sock->sendPacket((void*)&resp, P_LS2CL_REP_CHAR_DELETE_FAIL, sizeof(sP_LS2CL_REP_CHAR_DELETE_FAIL)); - } - - break; + else { + // failure + // client doesnt't care about this packet and softlocks + INITSTRUCT(sP_LS2CL_REP_CHAR_DELETE_FAIL, resp); + resp.iErrorCode = 0; + sock->sendPacket((void*)&resp, P_LS2CL_REP_CHAR_DELETE_FAIL, sizeof(sP_LS2CL_REP_CHAR_DELETE_FAIL)); } - case P_CL2LS_REQ_CHAR_SELECT: { - if (data->size != sizeof(sP_CL2LS_REQ_CHAR_SELECT)) - return; - - // character selected - sP_CL2LS_REQ_CHAR_SELECT* chararacter = (sP_CL2LS_REQ_CHAR_SELECT*)data->buf; - INITSTRUCT(sP_LS2CL_REP_CHAR_SELECT_SUCC, resp); - DEBUGLOG( - std::cout << "P_CL2LS_REQ_CHAR_SELECT:" << std::endl; - std::cout << "\tPC_UID: " << chararacter->iPC_UID << std::endl; - ) + break; + } + case P_CL2LS_REQ_CHAR_SELECT: { + if (data->size != sizeof(sP_CL2LS_REQ_CHAR_SELECT)) + return; + + // character selected + sP_CL2LS_REQ_CHAR_SELECT* chararacter = (sP_CL2LS_REQ_CHAR_SELECT*)data->buf; + INITSTRUCT(sP_LS2CL_REP_CHAR_SELECT_SUCC, resp); + + DEBUGLOG( + std::cout << "P_CL2LS_REQ_CHAR_SELECT:" << std::endl; + std::cout << "\tPC_UID: " << chararacter->iPC_UID << std::endl; + ) loginSessions[sock].selectedChar = chararacter->iPC_UID; - sock->sendPacket((void*)&resp, P_LS2CL_REP_CHAR_SELECT_SUCC, sizeof(sP_LS2CL_REP_CHAR_SELECT_SUCC)); - break; - } - case P_CL2LS_REQ_SHARD_SELECT: { - if (data->size != sizeof(sP_CL2LS_REQ_SHARD_SELECT)) - return; - - // tell client to connect to the shard server - sP_CL2LS_REQ_SHARD_SELECT* shard = (sP_CL2LS_REQ_SHARD_SELECT*)data->buf; - INITSTRUCT(sP_LS2CL_REP_SHARD_SELECT_SUCC, resp); + sock->sendPacket((void*)&resp, P_LS2CL_REP_CHAR_SELECT_SUCC, sizeof(sP_LS2CL_REP_CHAR_SELECT_SUCC)); + break; + } + case P_CL2LS_REQ_SHARD_SELECT: { + if (data->size != sizeof(sP_CL2LS_REQ_SHARD_SELECT)) + return; - DEBUGLOG( - std::cout << "P_CL2LS_REQ_SHARD_SELECT:" << std::endl; - std::cout << "\tShard: " << (int)shard->ShardNum << std::endl; - ) + // tell client to connect to the shard server + sP_CL2LS_REQ_SHARD_SELECT* shard = (sP_CL2LS_REQ_SHARD_SELECT*)data->buf; + INITSTRUCT(sP_LS2CL_REP_SHARD_SELECT_SUCC, resp); + + DEBUGLOG( + std::cout << "P_CL2LS_REQ_SHARD_SELECT:" << std::endl; + std::cout << "\tShard: " << (int)shard->ShardNum << std::endl; + ) const char* SHARD_IP = settings::SHARDSERVERIP.c_str(); - resp.iEnterSerialKey = rand(); - resp.g_FE_ServerPort = settings::SHARDPORT; + resp.iEnterSerialKey = rand(); + resp.g_FE_ServerPort = settings::SHARDPORT; - // copy IP to resp (this struct uses ASCII encoding so we don't have to goof around converting encodings) - memcpy(resp.g_FE_ServerIP, SHARD_IP, strlen(SHARD_IP)); - resp.g_FE_ServerIP[strlen(SHARD_IP)] = '\0'; + // copy IP to resp (this struct uses ASCII encoding so we don't have to goof around converting encodings) + memcpy(resp.g_FE_ServerIP, SHARD_IP, strlen(SHARD_IP)); + resp.g_FE_ServerIP[strlen(SHARD_IP)] = '\0'; - // pass player to CNSharedData - CNSharedData::setPlayer(resp.iEnterSerialKey, loginSessions[sock].characters[loginSessions[sock].selectedChar]); + // pass player to CNSharedData + CNSharedData::setPlayer(resp.iEnterSerialKey, loginSessions[sock].characters[loginSessions[sock].selectedChar]); - sock->sendPacket((void*)&resp, P_LS2CL_REP_SHARD_SELECT_SUCC, sizeof(sP_LS2CL_REP_SHARD_SELECT_SUCC)); - break; - } - case P_CL2LS_REQ_SAVE_CHAR_TUTOR: { - if (data->size != sizeof(sP_CL2LS_REQ_SAVE_CHAR_TUTOR)) - return; - sP_CL2LS_REQ_SAVE_CHAR_TUTOR* save = (sP_CL2LS_REQ_SAVE_CHAR_TUTOR*)data->buf; - Database::finishTutorial(save->iPC_UID); - loginSessions[sock].characters[save->iPC_UID].PCStyle2.iTutorialFlag = 1; - loginSessions[sock].characters[save->iPC_UID].Equip[0].iID = 328; - loginSessions[sock].characters[save->iPC_UID].Equip[0].iType = 0; - loginSessions[sock].characters[save->iPC_UID].Equip[0].iOpt = 1; + sock->sendPacket((void*)&resp, P_LS2CL_REP_SHARD_SELECT_SUCC, sizeof(sP_LS2CL_REP_SHARD_SELECT_SUCC)); + break; + } + case P_CL2LS_REQ_SAVE_CHAR_TUTOR: { + if (data->size != sizeof(sP_CL2LS_REQ_SAVE_CHAR_TUTOR)) + return; + sP_CL2LS_REQ_SAVE_CHAR_TUTOR* save = (sP_CL2LS_REQ_SAVE_CHAR_TUTOR*)data->buf; + Database::finishTutorial(save->iPC_UID); + loginSessions[sock].characters[save->iPC_UID].PCStyle2.iTutorialFlag = 1; + loginSessions[sock].characters[save->iPC_UID].Equip[0].iID = 328; + loginSessions[sock].characters[save->iPC_UID].Equip[0].iType = 0; + loginSessions[sock].characters[save->iPC_UID].Equip[0].iOpt = 1; - break; - } - default: - if (settings::VERBOSITY) - std::cerr << "OpenFusion: LOGIN UNIMPLM ERR. PacketType: " << Defines::p2str(CL2LS, data->type) << " (" << data->type << ")" << std::endl; - break; + break; + } + default: + if (settings::VERBOSITY) + std::cerr << "OpenFusion: LOGIN UNIMPLM ERR. PacketType: " << Defines::p2str(CL2LS, data->type) << " (" << data->type << ")" << std::endl; + break; } } diff --git a/src/Database.cpp b/src/Database.cpp index 5327c27..52d37fd 100644 --- a/src/Database.cpp +++ b/src/Database.cpp @@ -15,409 +15,410 @@ sqlite3pp::database db; void Database::open() { - //checking if database file exists - std::ifstream file; - file.open("data.db"); + //checking if database file exists + std::ifstream file; + file.open("data.db"); - if (file) { - file.close(); - // if exists, assign it - db = sqlite3pp::database("data.db"); - DEBUGLOG(std::cout << "Database in operation" << std::endl; ) - } else { - // if doesn't, create all the tables - DEBUGLOG(std::cout << "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;) - } + if (file) { + file.close(); + // if exists, assign it + db = sqlite3pp::database("data.db"); + DEBUGLOG(std::cout << "Database in operation" << std::endl; ) + } + else { + // if doesn't, create all the tables + DEBUGLOG(std::cout << "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;) + } } // 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)); + 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)); } 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 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(); + // 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(); } 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); + // 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(); + // executes + sqlite3pp::query::iterator i = qry.begin(); - // grabs the first result (the count) - int result; - std::tie(result) = (*i).get_columns(0); + // grabs the first result (the count) + int result; + std::tie(result) = (*i).get_columns(0); - // if there is more than 0 results, the user exists :eyes: - return (result > 0); + // if there is more than 0 results, the user exists :eyes: + return (result > 0); } 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); + // 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(); + // executes + sqlite3pp::query::iterator i = qry.begin(); - // grabs the first result - const char* actual; - std::tie(actual) = (*i).get_columns(0); + // grabs the first result + const char* actual; + std::tie(actual) = (*i).get_columns(0); - // validate password hash with provded password - return BCrypt::validatePassword(password, actual); + // validate password hash with provded password + return BCrypt::validatePassword(password, actual); } 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); + // 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(); + // executes the query + sqlite3pp::query::iterator i = qry.begin(); - // grabs the first result of the query - int result; - std::tie(result) = (*i).get_columns(0); + // grabs the first result of the query + int result; + std::tie(result) = (*i).get_columns(0); - // returns the result - return result; + // returns the result + return result; } int Database::getUserSlotsNum(int AccountId) { - // generates the prepared statement - sqlite3pp::query qry(db, "SELECT COUNT(PlayerID) FROM Players WHERE AccountID = :ID"); + // 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); + // binds the ID to the param + qry.bind(":ID", AccountId); - // executes - sqlite3pp::query::iterator i = qry.begin(); + // executes + sqlite3pp::query::iterator i = qry.begin(); - // grabs the first result - int result; - std::tie(result) = (*i).get_columns(0); + // grabs the first result + int result; + std::tie(result) = (*i).get_columns(0); - // returns the result - return result; + // returns the result + return result; } 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"); + // 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); + // binds the params + qry.bind(":First", First, sqlite3pp::nocopy); + qry.bind(":Second", Second, sqlite3pp::nocopy); - // executes the query - sqlite3pp::query::iterator i = qry.begin(); + // executes the query + sqlite3pp::query::iterator i = qry.begin(); - // grabs the result - int result; - std::tie(result) = (*i).get_columns(0); + // grabs the result + int result; + std::tie(result) = (*i).get_columns(0); - // if no results return, the the username is unused - return (result == 0); + // if no results return, the the username is unused + return (result == 0); } 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 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); + // 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); + // 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(); + // run + cmd.execute(); } void Database::finishCharacter(sP_CL2LS_REQ_CHAR_CREATE* character) { - sqlite3pp::command cmd(db, "UPDATE Players SET CharData = :data WHERE PlayerID = :id"); + 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); + // 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(); + // bind to the command & execute + cmd.bind(":data", charData, sqlite3pp::nocopy); + cmd.bind(":id", id); + cmd.execute(); } 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(0); + sqlite3pp::query qry(db, "SELECT CharData FROM Players WHERE PlayerID = :ID"); - // parse the json into a Player - Player player = JsonToPlayer(json, PlayerID); + // bind to the query and execute + qry.bind(":ID", PlayerID); + sqlite3pp::query::iterator i = qry.begin(); - // set the tutorial flag & equip lightning gun - player.PCStyle2.iTutorialFlag = 1; - player.Equip[0].iID = 328; - json = PlayerToJson(player); + // grab the player json from the database + std::string json; + std::tie(json) = (*i).get_columns(0); - // 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(); + // 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(); } int Database::getCharacterID(int AccountID, int slot) { - // make the query - sqlite3pp::query qry(db, "SELECT PlayerID FROM Players WHERE AccountID = :ID AND Slot = :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(); + // 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(0); + // grab the result + int result; + std::tie(result) = (*i).get_columns(0); - return result; + return result; } int Database::deleteCharacter(int characterID, int accountID) { - // checking if requested player exist and is bound to the account + // checking if requested player exist and is bound to the account - 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(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(); + sqlite3pp::query qry(db, "SELECT COUNT(AccountID) FROM Players WHERE AccountID = :AccID AND PlayerID = :PID"); - // grab the slot to return - int slot; - std::tie(slot) = (*i).get_columns(0); - - // actually delete the record - sqlite3pp::command cmd(db, "DELETE FROM Players WHERE PlayerID = :ID"); - cmd.bind(":ID", characterID); - cmd.execute(); + qry.bind(":AccID", accountID); + qry.bind(":PID", characterID); + sqlite3pp::query::iterator i = qry.begin(); - // finally, return the grabbed slot - return slot; - } - - return -1; + int result; + std::tie(result) = (*i).get_columns(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(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; } // TODO: this should really be std::vector, but for the sake of compatibility with PRs, I'll change this after merging std::list Database::getCharacters(int userID) { - std::list result = std::list(); + std::list result = std::list(); - sqlite3pp::query qry(db, "SELECT * FROM Players WHERE AccountID = :ID"); + sqlite3pp::query qry(db, "SELECT * FROM Players WHERE AccountID = :ID"); - qry.bind(":ID", userID); + qry.bind(":ID", userID); - // 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(0, 1, 2, 3, 4, 5); - - // convert to player - Player toadd = JsonToPlayer(charData, ID); - toadd.slot = slot; + // 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(0, 1, 2, 3, 4, 5); - // add it to the results - result.push_back(toadd); - } - return result; + // convert to player + Player toadd = JsonToPlayer(charData, ID); + toadd.slot = slot; + + // add it to the results + result.push_back(toadd); + } + return result; } std::string Database::CharacterToJson(sP_CL2LS_REQ_SAVE_CHAR_NAME* save) { - nlohmann::json json = { - {"Level",1}, - //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(); + 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(); } std::string Database::PlayerToJson(Player player) { - nlohmann::json json = { - {"Level",1}, - //to check - {"HP",1000}, - {"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(); + 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(), player.PCStyle.szFirstName); - U8toU16(json["LastName"].get(), 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 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(), player.PCStyle.szFirstName); + U8toU16(json["LastName"].get(), 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",1}, - //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(); -} \ No newline at end of file + 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(); +} diff --git a/src/NPCManager.cpp b/src/NPCManager.cpp index 1e34704..995f3c7 100644 --- a/src/NPCManager.cpp +++ b/src/NPCManager.cpp @@ -28,10 +28,11 @@ void NPCManager::init() { NPCs[tmp.appearanceData.iNPC_ID] = tmp; if (npc.value()["id"] == 641 || npc.value()["id"] == 642) - RespawnPoints.push_back({npc.value()["x"], npc.value()["y"], ((int)npc.value()["z"]) + RESURRECT_HEIGHT}); + RespawnPoints.push_back({ npc.value()["x"], npc.value()["y"], ((int)npc.value()["z"]) + RESURRECT_HEIGHT }); } - } catch (const std::exception& err) { + } + catch (const std::exception& err) { std::cerr << "[WARN] Malformed NPCs.json file! Reason:" << err.what() << std::endl; } @@ -45,13 +46,14 @@ void NPCManager::init() { for (nlohmann::json::iterator npc = npcData.begin(); npc != npcData.end(); npc++) { BaseNPC tmp(npc.value()["iX"], npc.value()["iY"], npc.value()["iZ"], npc.value()["iNPCType"], - npc.value()["iHP"], npc.value()["iConditionBitFlag"], npc.value()["iAngle"], npc.value()["iBarkerType"]); + npc.value()["iHP"], npc.value()["iConditionBitFlag"], npc.value()["iAngle"], npc.value()["iBarkerType"]); NPCs[tmp.appearanceData.iNPC_ID] = tmp; } std::cout << "[INFO] populated " << NPCs.size() << " NPCs" << std::endl; - } catch (const std::exception& err) { + } + catch (const std::exception& err) { std::cerr << "[WARN] Malformed mobs.json file! Reason:" << err.what() << std::endl; } @@ -63,19 +65,21 @@ void NPCManager::init() { infile >> warpData; for (nlohmann::json::iterator warp = warpData.begin(); warp != warpData.end(); warp++) { - WarpLocation warpLoc = {warp.value()["m_iToX"], warp.value()["m_iToY"], warp.value()["m_iToZ"]}; + WarpLocation warpLoc = { warp.value()["m_iToX"], warp.value()["m_iToY"], warp.value()["m_iToZ"] }; int warpID = atoi(warp.key().c_str()); Warps[warpID] = warpLoc; } std::cout << "[INFO] populated " << Warps.size() << " Warps" << std::endl; - } catch (const std::exception& err) { + } + catch (const std::exception& err) { std::cerr << "[WARN] Malformed warps.json file! Reason:" << err.what() << std::endl; } REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_WARP_USE_NPC, npcWarpHandler); REGISTER_SHARD_PACKET(P_CL2FE_REQ_NPC_SUMMON, npcSummonHandler); + REGISTER_SHARD_PACKET(P_CL2FE_REQ_BARKER, npcBarkHandler); } void NPCManager::updatePlayerNPCS(CNSocket* sock, PlayerView& view) { @@ -88,7 +92,8 @@ void NPCManager::updatePlayerNPCS(CNSocket* sock, PlayerView& view) { if (diffX < settings::NPCDISTANCE && diffY < settings::NPCDISTANCE) { yesView.push_back(pair.first); - } else { + } + else { noView.push_back(pair.first); } } @@ -106,7 +111,8 @@ void NPCManager::updatePlayerNPCS(CNSocket* sock, PlayerView& view) { // remove from view view.viewableNPCs.erase(i++); - } else { + } + else { i++; } } @@ -127,6 +133,45 @@ void NPCManager::updatePlayerNPCS(CNSocket* sock, PlayerView& view) { PlayerManager::players[sock].viewableNPCs = view.viewableNPCs; } +void NPCManager::npcBarkHandler(CNSocket* sock, CNPacketData* data) { + sP_CL2FE_REQ_BARKER* bark = (sP_CL2FE_REQ_BARKER*)data->buf; + PlayerView& plr = PlayerManager::players[sock]; + + INITSTRUCT(sP_FE2CL_REP_BARKER, resp); + resp.iMissionStringID = bark->iMissionTaskID; + resp.iNPC_ID = bark->iNPC_ID; + + // Send bark to other players. + for (CNSocket* otherSock : plr.viewable) { + otherSock->sendPacket((void*)&resp, P_FE2CL_REP_BARKER, sizeof(sP_FE2CL_REP_BARKER)); + } + + // Then ourself. + sock->sendPacket((void*)&resp, P_FE2CL_REP_BARKER, sizeof(sP_FE2CL_REP_BARKER)); +} + +void NPCManager::npcSummonHandler(CNSocket* sock, CNPacketData* data) { + if (data->size != sizeof(sP_CL2FE_REQ_NPC_SUMMON)) + return; // malformed packet + + sP_CL2FE_REQ_NPC_SUMMON* req = (sP_CL2FE_REQ_NPC_SUMMON*)data->buf; + INITSTRUCT(sP_FE2CL_NPC_ENTER, resp); + Player* plr = PlayerManager::getPlayer(sock); + + // permission & sanity check + if (!plr->IsGM || req->iNPCType >= 3314) + return; + + resp.NPCAppearanceData.iNPC_ID = rand(); // cpunch-style + resp.NPCAppearanceData.iNPCType = req->iNPCType; + resp.NPCAppearanceData.iHP = 1000; // TODO: placeholder + resp.NPCAppearanceData.iX = plr->x; + resp.NPCAppearanceData.iY = plr->y; + resp.NPCAppearanceData.iZ = plr->z; + + sock->sendPacket((void*)&resp, P_FE2CL_NPC_ENTER, sizeof(sP_FE2CL_NPC_ENTER)); +} + void NPCManager::npcWarpHandler(CNSocket* sock, CNPacketData* data) { if (data->size != sizeof(sP_CL2FE_REQ_PC_WARP_USE_NPC)) return; // malformed packet @@ -149,27 +194,4 @@ void NPCManager::npcWarpHandler(CNSocket* sock, CNPacketData* data) { plrv.viewableNPCs.clear(); sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_WARP_USE_NPC_SUCC, sizeof(sP_FE2CL_REP_PC_WARP_USE_NPC_SUCC)); - -} - -void NPCManager::npcSummonHandler(CNSocket *sock, CNPacketData *data) { - if (data->size != sizeof(sP_CL2FE_REQ_NPC_SUMMON)) - return; // malformed packet - - sP_CL2FE_REQ_NPC_SUMMON* req = (sP_CL2FE_REQ_NPC_SUMMON*)data->buf; - INITSTRUCT(sP_FE2CL_NPC_ENTER, resp); - Player *plr = PlayerManager::getPlayer(sock); - - // permission & sanity check - if (!plr->IsGM || req->iNPCType >= 3314) - return; - - resp.NPCAppearanceData.iNPC_ID = rand(); // cpunch-style - resp.NPCAppearanceData.iNPCType = req->iNPCType; - resp.NPCAppearanceData.iHP = 1000; // TODO: placeholder - resp.NPCAppearanceData.iX = plr->x; - resp.NPCAppearanceData.iY = plr->y; - resp.NPCAppearanceData.iZ = plr->z; - - sock->sendPacket((void*)&resp, P_FE2CL_NPC_ENTER, sizeof(sP_FE2CL_NPC_ENTER)); -} +} \ No newline at end of file diff --git a/src/NPCManager.hpp b/src/NPCManager.hpp index b6a3c10..7686b5e 100644 --- a/src/NPCManager.hpp +++ b/src/NPCManager.hpp @@ -20,7 +20,9 @@ namespace NPCManager { extern std::vector RespawnPoints; void init(); - void updatePlayerNPCS(CNSocket* sock, PlayerView& plr); - void npcWarpHandler(CNSocket* sock, CNPacketData* data); + void npcBarkHandler(CNSocket* sock, CNPacketData* data); void npcSummonHandler(CNSocket* sock, CNPacketData* data); + void npcWarpHandler(CNSocket* sock, CNPacketData* data); + + void updatePlayerNPCS(CNSocket* sock, PlayerView& plr); } diff --git a/src/PlayerManager.cpp b/src/PlayerManager.cpp index 7f87515..6980815 100644 --- a/src/PlayerManager.cpp +++ b/src/PlayerManager.cpp @@ -63,7 +63,7 @@ void PlayerManager::removePlayer(CNSocket* key) { otherSock->sendPacket((void*)&exitPacket, P_FE2CL_PC_EXIT, sizeof(sP_FE2CL_PC_EXIT)); } - std::cout << U16toU8(cachedView.plr->PCStyle.szFirstName) << U16toU8(cachedView.plr->PCStyle.szLastName) << " has left!" << std::endl; + std::cout << U16toU8(cachedView.plr->PCStyle.szFirstName) << " " << U16toU8(cachedView.plr->PCStyle.szLastName) << " has left!" << std::endl; std::cout << players.size() << " players" << std::endl; delete cachedView.plr; From 437063d78a87980d0bb55c64b456e5784cd5aa40 Mon Sep 17 00:00:00 2001 From: Eperty123 Date: Sat, 29 Aug 2020 13:43:33 +0200 Subject: [PATCH 2/3] Add experimental TransportManager --- Makefile | 2 ++ src/TransportManager.cpp | 18 ++++++++++++++++++ src/TransportManager.hpp | 9 +++++++++ src/main.cpp | 2 ++ 4 files changed, 31 insertions(+) create mode 100644 src/TransportManager.cpp create mode 100644 src/TransportManager.hpp diff --git a/Makefile b/Makefile index 0c8b5a5..de68398 100644 --- a/Makefile +++ b/Makefile @@ -46,6 +46,7 @@ CXXSRC=\ src/Player.cpp\ src/PlayerManager.cpp\ src/settings.cpp\ + src/TransportManager.cpp\ # headers (for timestamp purposes) CHDR=\ @@ -81,6 +82,7 @@ CXXHDR=\ src/Player.hpp\ src/PlayerManager.hpp\ src/settings.hpp\ + src/TransportManager.hpp\ COBJ=$(CSRC:.c=.o) CXXOBJ=$(CXXSRC:.cpp=.o) diff --git a/src/TransportManager.cpp b/src/TransportManager.cpp new file mode 100644 index 0000000..135aa7d --- /dev/null +++ b/src/TransportManager.cpp @@ -0,0 +1,18 @@ +#include "CNShardServer.hpp" +#include "CNStructs.hpp" +#include "PlayerManager.hpp" +#include "TransportManager.hpp" + +void TransportManager::init() { + REGISTER_SHARD_PACKET(P_CL2FE_REQ_REGIST_TRANSPORTATION_LOCATION, transportRegisterLocationHandler); +} + +void TransportManager::transportRegisterLocationHandler(CNSocket* sock, CNPacketData* data) { + sP_CL2FE_REQ_REGIST_TRANSPORTATION_LOCATION* transport = (sP_CL2FE_REQ_REGIST_TRANSPORTATION_LOCATION*)data->buf; + + INITSTRUCT(sP_FE2CL_REP_PC_REGIST_TRANSPORTATION_LOCATION_SUCC, resp); + resp.eTT = transport->eTT; + resp.iLocationID = transport->iLocationID; + + sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_REGIST_TRANSPORTATION_LOCATION_SUCC, sizeof(sP_FE2CL_REP_PC_REGIST_TRANSPORTATION_LOCATION_SUCC)); +} diff --git a/src/TransportManager.hpp b/src/TransportManager.hpp new file mode 100644 index 0000000..963925d --- /dev/null +++ b/src/TransportManager.hpp @@ -0,0 +1,9 @@ +#pragma once + +#include "CNShardServer.hpp" + +namespace TransportManager { + void init(); + + void transportRegisterLocationHandler(CNSocket* sock, CNPacketData* data); +} diff --git a/src/main.cpp b/src/main.cpp index 1a1990b..6c36e2c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7,6 +7,7 @@ #include "MissionManager.hpp" #include "NanoManager.hpp" #include "NPCManager.hpp" +#include "TransportManager.hpp" #include "Database.hpp" #include "settings.hpp" @@ -55,6 +56,7 @@ int main() { MissionManager::init(); NanoManager::init(); NPCManager::init(); + TransportManager::init(); Database::open(); From da293ba9b374bd3a5470d5ba6506570d405e6eac Mon Sep 17 00:00:00 2001 From: Eperty123 Date: Sat, 29 Aug 2020 13:47:39 +0200 Subject: [PATCH 3/3] Add DB prefix to db stuff --- src/Database.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Database.cpp b/src/Database.cpp index 52d37fd..2dcaff2 100644 --- a/src/Database.cpp +++ b/src/Database.cpp @@ -23,11 +23,11 @@ void Database::open() { file.close(); // if exists, assign it db = sqlite3pp::database("data.db"); - DEBUGLOG(std::cout << "Database in operation" << std::endl; ) + DEBUGLOG(std::cout << "[DB] Database in operation" << std::endl; ) } else { // if doesn't, create all the tables - DEBUGLOG(std::cout << "Creating new database" << std::endl;) + DEBUGLOG(std::cout << "[DB] Creating new database" << std::endl;) db = sqlite3pp::database("data.db"); // creates accounts