2020-08-18 20:42:30 +00:00
|
|
|
#include "CNProtocol.hpp"
|
|
|
|
#include "PlayerManager.hpp"
|
2020-08-20 21:43:48 +00:00
|
|
|
#include "NPCManager.hpp"
|
2020-08-18 20:42:30 +00:00
|
|
|
#include "CNShardServer.hpp"
|
|
|
|
#include "CNShared.hpp"
|
|
|
|
|
|
|
|
#include "settings.hpp"
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
#include <vector>
|
|
|
|
#include <cmath>
|
|
|
|
|
|
|
|
std::map<CNSocket*, PlayerView> PlayerManager::players;
|
|
|
|
|
|
|
|
void PlayerManager::init() {
|
|
|
|
// register packet types
|
|
|
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_ENTER, PlayerManager::enterPlayer);
|
|
|
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_LOADING_COMPLETE, PlayerManager::loadPlayer);
|
|
|
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_MOVE, PlayerManager::movePlayer);
|
|
|
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_STOP, PlayerManager::stopPlayer);
|
|
|
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_JUMP, PlayerManager::jumpPlayer);
|
2020-08-20 16:26:26 +00:00
|
|
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_JUMPPAD, PlayerManager::jumppadPlayer);
|
|
|
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_LAUNCHER, PlayerManager::launchPlayer);
|
|
|
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_ZIPLINE, PlayerManager::ziplinePlayer);
|
2020-08-18 20:42:30 +00:00
|
|
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_MOVEPLATFORM, PlayerManager::movePlatformPlayer);
|
2020-08-20 16:26:26 +00:00
|
|
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_SLOPE, PlayerManager::moveSlopePlayer);
|
2020-08-18 20:42:30 +00:00
|
|
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_GOTO, PlayerManager::gotoPlayer);
|
|
|
|
REGISTER_SHARD_PACKET(P_CL2FE_GM_REQ_PC_SET_VALUE, PlayerManager::setSpecialPlayer);
|
2020-08-19 01:34:39 +00:00
|
|
|
REGISTER_SHARD_PACKET(P_CL2FE_REP_LIVE_CHECK, PlayerManager::heartbeatPlayer);
|
2020-08-19 17:22:54 +00:00
|
|
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_EXIT, PlayerManager::exitGame);
|
2020-08-18 20:42:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void PlayerManager::addPlayer(CNSocket* key, Player plr) {
|
|
|
|
players[key] = PlayerView();
|
|
|
|
players[key].viewable = std::list<CNSocket*>();
|
|
|
|
players[key].plr = plr;
|
2020-08-19 01:34:39 +00:00
|
|
|
players[key].lastHeartbeat = 0;
|
2020-08-19 00:11:31 +00:00
|
|
|
|
2020-08-21 17:38:45 +00:00
|
|
|
std::cout << U16toU8(plr.PCStyle.szFirstName) << " " << U16toU8(plr.PCStyle.szLastName) << " has joined!" << std::endl;
|
2020-08-19 00:11:31 +00:00
|
|
|
std::cout << players.size() << " players" << std::endl;
|
2020-08-18 20:42:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void PlayerManager::removePlayer(CNSocket* key) {
|
|
|
|
PlayerView cachedView = players[key];
|
|
|
|
|
|
|
|
// if players have them in their viewable lists, remove it
|
|
|
|
for (CNSocket* otherSock : players[key].viewable) {
|
|
|
|
players[otherSock].viewable.remove(key); // gone
|
|
|
|
|
|
|
|
// now sent PC_EXIT packet
|
2020-08-22 23:31:09 +00:00
|
|
|
sP_FE2CL_PC_EXIT exitPacket;
|
|
|
|
exitPacket.iID = players[key].plr.iID;
|
2020-08-18 20:42:30 +00:00
|
|
|
|
2020-08-22 23:31:09 +00:00
|
|
|
otherSock->sendPacket((void*)&exitPacket, P_FE2CL_PC_EXIT, sizeof(sP_FE2CL_PC_EXIT));
|
2020-08-18 20:42:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
players.erase(key);
|
2020-08-19 00:11:31 +00:00
|
|
|
|
|
|
|
std::cout << U16toU8(cachedView.plr.PCStyle.szFirstName) << U16toU8(cachedView.plr.PCStyle.szLastName) << " has left!" << std::endl;
|
|
|
|
std::cout << players.size() << " players" << std::endl;
|
2020-08-18 20:42:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Player PlayerManager::getPlayer(CNSocket* key) {
|
|
|
|
return players[key].plr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PlayerManager::updatePlayerPosition(CNSocket* sock, int X, int Y, int Z) {
|
|
|
|
players[sock].plr.x = X;
|
|
|
|
players[sock].plr.y = Y;
|
|
|
|
players[sock].plr.z = Z;
|
|
|
|
|
|
|
|
std::vector<CNSocket*> noView;
|
|
|
|
std::vector<CNSocket*> yesView;
|
|
|
|
|
|
|
|
// TODO: oh god this is sooooo perfomance heavy the more players you have
|
|
|
|
for (auto pair : players) {
|
|
|
|
if (pair.first == sock)
|
|
|
|
continue; // ignore our own connection
|
|
|
|
|
|
|
|
int diffX = abs(pair.second.plr.x - X); // the map is like a grid, X and Y are your position on the map, Z is the height. very different from other games...
|
|
|
|
int diffY = abs(pair.second.plr.y - Y);
|
|
|
|
|
2020-08-20 18:19:03 +00:00
|
|
|
if (diffX < settings::VIEWDISTANCE && diffY < settings::VIEWDISTANCE) {
|
2020-08-18 20:42:30 +00:00
|
|
|
yesView.push_back(pair.first);
|
2020-08-22 18:02:08 +00:00
|
|
|
}
|
|
|
|
else {
|
2020-08-20 18:19:03 +00:00
|
|
|
noView.push_back(pair.first);
|
2020-08-18 20:42:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-23 00:26:18 +00:00
|
|
|
INITSTRUCT(sP_FE2CL_PC_EXIT, exitPacket);
|
2020-08-20 21:59:32 +00:00
|
|
|
std::list<CNSocket*>::iterator i = players[sock].viewable.begin();
|
|
|
|
while (i != players[sock].viewable.end()) {
|
|
|
|
CNSocket* otherSock = *i;
|
2020-08-18 20:42:30 +00:00
|
|
|
if (std::find(noView.begin(), noView.end(), otherSock) != noView.end()) {
|
|
|
|
|
2020-08-22 23:31:09 +00:00
|
|
|
// sock shouldn't be visible, send PC_EXIT packet
|
|
|
|
exitPacket.iID = players[sock].plr.iID;
|
|
|
|
otherSock->sendPacket((void*)&exitPacket, P_FE2CL_PC_EXIT, sizeof(sP_FE2CL_PC_EXIT));
|
|
|
|
exitPacket.iID = players[otherSock].plr.iID;
|
|
|
|
sock->sendPacket((void*)&exitPacket, P_FE2CL_PC_EXIT, sizeof(sP_FE2CL_PC_EXIT));
|
2020-08-18 20:42:30 +00:00
|
|
|
|
2020-08-22 23:31:09 +00:00
|
|
|
// remove them from the viewable list
|
2020-08-20 21:59:32 +00:00
|
|
|
players[sock].viewable.erase(i++);
|
2020-08-18 20:42:30 +00:00
|
|
|
players[otherSock].viewable.remove(sock);
|
2020-08-20 21:59:32 +00:00
|
|
|
continue;
|
2020-08-18 20:42:30 +00:00
|
|
|
}
|
|
|
|
|
2020-08-20 21:59:32 +00:00
|
|
|
++i;
|
|
|
|
}
|
2020-08-18 20:42:30 +00:00
|
|
|
|
2020-08-23 00:26:18 +00:00
|
|
|
INITSTRUCT(sP_FE2CL_PC_NEW, newPlayer);
|
2020-08-18 20:42:30 +00:00
|
|
|
for (CNSocket* otherSock : yesView) {
|
2020-08-20 21:59:32 +00:00
|
|
|
if (std::find(players[sock].viewable.begin(), players[sock].viewable.end(), otherSock) == players[sock].viewable.end()) {
|
2020-08-18 20:42:30 +00:00
|
|
|
// this needs to be added to the viewable players, send PC_ENTER
|
|
|
|
|
|
|
|
Player otherPlr = players[otherSock].plr;
|
|
|
|
Player plr = players[sock].plr;
|
|
|
|
|
2020-08-22 23:31:09 +00:00
|
|
|
newPlayer.PCAppearanceData.iID = plr.iID;
|
|
|
|
newPlayer.PCAppearanceData.iHP = plr.HP;
|
|
|
|
newPlayer.PCAppearanceData.iLv = plr.level;
|
|
|
|
newPlayer.PCAppearanceData.iX = plr.x;
|
|
|
|
newPlayer.PCAppearanceData.iY = plr.y;
|
|
|
|
newPlayer.PCAppearanceData.iZ = plr.z;
|
|
|
|
newPlayer.PCAppearanceData.iAngle = plr.angle;
|
|
|
|
newPlayer.PCAppearanceData.PCStyle = plr.PCStyle;
|
2020-08-23 00:52:54 +00:00
|
|
|
newPlayer.PCAppearanceData.Nano = plr.Nanos[plr.nano];
|
2020-08-22 23:31:09 +00:00
|
|
|
memcpy(newPlayer.PCAppearanceData.ItemEquip, plr.Equip, sizeof(sItemBase) * AEQUIP_COUNT);
|
|
|
|
|
|
|
|
otherSock->sendPacket((void*)&newPlayer, P_FE2CL_PC_NEW, sizeof(sP_FE2CL_PC_NEW));
|
|
|
|
|
|
|
|
newPlayer.PCAppearanceData.iID = otherPlr.iID;
|
|
|
|
newPlayer.PCAppearanceData.iHP = otherPlr.HP;
|
|
|
|
newPlayer.PCAppearanceData.iLv = otherPlr.level;
|
|
|
|
newPlayer.PCAppearanceData.iX = otherPlr.x;
|
|
|
|
newPlayer.PCAppearanceData.iY = otherPlr.y;
|
|
|
|
newPlayer.PCAppearanceData.iZ = otherPlr.z;
|
|
|
|
newPlayer.PCAppearanceData.iAngle = otherPlr.angle;
|
|
|
|
newPlayer.PCAppearanceData.PCStyle = otherPlr.PCStyle;
|
2020-08-23 00:52:54 +00:00
|
|
|
newPlayer.PCAppearanceData.Nano = otherPlr.Nanos[otherPlr.nano];
|
2020-08-22 23:31:09 +00:00
|
|
|
memcpy(newPlayer.PCAppearanceData.ItemEquip, otherPlr.Equip, sizeof(sItemBase) * AEQUIP_COUNT);
|
|
|
|
|
|
|
|
sock->sendPacket((void*)&newPlayer, P_FE2CL_PC_NEW, sizeof(sP_FE2CL_PC_NEW));
|
2020-08-18 20:42:30 +00:00
|
|
|
|
|
|
|
players[sock].viewable.push_back(otherSock);
|
|
|
|
players[otherSock].viewable.push_back(sock);
|
|
|
|
}
|
|
|
|
}
|
2020-08-20 21:43:48 +00:00
|
|
|
|
|
|
|
NPCManager::updatePlayerNPCS(sock, players[sock]);
|
2020-08-18 20:42:30 +00:00
|
|
|
}
|
|
|
|
|
2020-08-23 15:42:37 +00:00
|
|
|
std::list<CNSocket*> PlayerManager::getNearbyPlayers(int x, int y, int dist) {
|
|
|
|
std::list<CNSocket*> plrs;
|
|
|
|
|
|
|
|
for (auto pair : players) {
|
|
|
|
int diffX = abs(pair.second.plr.x - x);
|
|
|
|
int diffY = abs(pair.second.plr.x - x);
|
|
|
|
|
|
|
|
if (diffX < dist && diffY < dist)
|
|
|
|
plrs.push_back(pair.first);
|
|
|
|
}
|
|
|
|
|
|
|
|
return plrs;
|
|
|
|
}
|
|
|
|
|
2020-08-18 20:42:30 +00:00
|
|
|
void PlayerManager::enterPlayer(CNSocket* sock, CNPacketData* data) {
|
2020-08-19 00:11:31 +00:00
|
|
|
if (data->size != sizeof(sP_CL2FE_REQ_PC_ENTER))
|
|
|
|
return; // ignore the malformed packet
|
|
|
|
|
2020-08-18 20:42:30 +00:00
|
|
|
sP_CL2FE_REQ_PC_ENTER* enter = (sP_CL2FE_REQ_PC_ENTER*)data->buf;
|
2020-08-23 00:26:18 +00:00
|
|
|
INITSTRUCT(sP_FE2CL_REP_PC_ENTER_SUCC, response);
|
|
|
|
INITSTRUCT(sP_FE2CL_PC_MOTD_LOGIN, motd);
|
2020-08-18 20:42:30 +00:00
|
|
|
|
|
|
|
// TODO: check if serialkey exists, if it doesn't send sP_FE2CL_REP_PC_ENTER_FAIL
|
|
|
|
Player plr = CNSharedData::getPlayer(enter->iEnterSerialKey);
|
|
|
|
|
|
|
|
DEBUGLOG(
|
|
|
|
std::cout << "P_CL2FE_REQ_PC_ENTER:" << std::endl;
|
2020-08-22 18:02:08 +00:00
|
|
|
std::cout << "\tID: " << U16toU8(enter->szID) << std::endl;
|
|
|
|
std::cout << "\tSerial: " << enter->iEnterSerialKey << std::endl;
|
|
|
|
std::cout << "\tTemp: " << enter->iTempValue << std::endl;
|
|
|
|
std::cout << "\tPC_UID: " << plr.PCStyle.iPC_UID << std::endl;
|
2020-08-18 20:42:30 +00:00
|
|
|
)
|
|
|
|
|
2020-08-22 23:31:09 +00:00
|
|
|
response.iID = rand();
|
|
|
|
response.uiSvrTime = getTime();
|
|
|
|
response.PCLoadData2CL.iUserLevel = 1;
|
|
|
|
response.PCLoadData2CL.iHP = 1000 * plr.level;
|
|
|
|
response.PCLoadData2CL.iLevel = plr.level;
|
|
|
|
response.PCLoadData2CL.iMentor = 1;
|
|
|
|
response.PCLoadData2CL.iMentorCount = 4;
|
|
|
|
response.PCLoadData2CL.iMapNum = 0;
|
|
|
|
response.PCLoadData2CL.iX = plr.x;
|
|
|
|
response.PCLoadData2CL.iY = plr.y;
|
|
|
|
response.PCLoadData2CL.iZ = plr.z;
|
|
|
|
response.PCLoadData2CL.iActiveNanoSlotNum = -1;
|
|
|
|
response.PCLoadData2CL.iFatigue = 50;
|
|
|
|
response.PCLoadData2CL.PCStyle = plr.PCStyle;
|
|
|
|
response.PCLoadData2CL.PCStyle2 = plr.PCStyle2;
|
2020-08-18 20:42:30 +00:00
|
|
|
|
|
|
|
for (int i = 0; i < AEQUIP_COUNT; i++)
|
2020-08-22 23:31:09 +00:00
|
|
|
response.PCLoadData2CL.aEquip[i] = plr.Equip[i];
|
|
|
|
|
|
|
|
for (int i = 0; i < AINVEN_COUNT; i++)
|
|
|
|
response.PCLoadData2CL.aInven[i] = plr.Inven[i];
|
2020-08-21 17:38:45 +00:00
|
|
|
|
2020-08-18 20:42:30 +00:00
|
|
|
// don't ask..
|
|
|
|
for (int i = 1; i < 37; i++) {
|
2020-08-22 23:31:09 +00:00
|
|
|
response.PCLoadData2CL.aNanoBank[i].iID = i;
|
|
|
|
response.PCLoadData2CL.aNanoBank[i].iSkillID = 1;
|
|
|
|
response.PCLoadData2CL.aNanoBank[i].iStamina = 150;
|
2020-08-18 20:42:30 +00:00
|
|
|
}
|
|
|
|
|
2020-08-22 18:02:08 +00:00
|
|
|
// temporarily not add nanos for nano add test through commands
|
2020-08-22 23:31:09 +00:00
|
|
|
//response.PCLoadData2CL.aNanoSlots[0] = 1;
|
|
|
|
//response.PCLoadData2CL.aNanoSlots[1] = 2;
|
|
|
|
//response.PCLoadData2CL.aNanoSlots[2] = 3;
|
2020-08-18 20:42:30 +00:00
|
|
|
|
2020-08-22 23:31:09 +00:00
|
|
|
response.PCLoadData2CL.aQuestFlag[0] = -1;
|
2020-08-18 20:42:30 +00:00
|
|
|
|
2020-08-22 23:31:09 +00:00
|
|
|
plr.iID = response.iID;
|
2020-08-18 20:42:30 +00:00
|
|
|
plr.SerialKey = enter->iEnterSerialKey;
|
2020-08-22 23:31:09 +00:00
|
|
|
plr.HP = response.PCLoadData2CL.iHP;
|
2020-08-18 20:42:30 +00:00
|
|
|
|
2020-08-22 23:31:09 +00:00
|
|
|
motd.iType = 1;
|
|
|
|
U8toU16(settings::MOTDSTRING, (char16_t*)motd.szSystemMsg);
|
2020-08-21 17:38:45 +00:00
|
|
|
|
2020-08-22 23:31:09 +00:00
|
|
|
sock->setEKey(CNSocketEncryption::createNewKey(response.uiSvrTime, response.iID + 1, response.PCLoadData2CL.iFusionMatter + 1));
|
2020-08-18 20:42:30 +00:00
|
|
|
sock->setFEKey(plr.FEKey);
|
2020-08-22 23:31:09 +00:00
|
|
|
sock->setActiveKey(SOCKETKEY_FE); // send all packets using the FE key from now on
|
|
|
|
|
|
|
|
sock->sendPacket((void*)&response, P_FE2CL_REP_PC_ENTER_SUCC, sizeof(sP_FE2CL_REP_PC_ENTER_SUCC));
|
2020-08-18 20:42:30 +00:00
|
|
|
|
2020-08-21 17:38:45 +00:00
|
|
|
// transmit MOTD after entering the game, so the client hopefully changes modes on time
|
2020-08-22 23:31:09 +00:00
|
|
|
sock->sendPacket((void*)&motd, P_FE2CL_PC_MOTD_LOGIN, sizeof(sP_FE2CL_PC_MOTD_LOGIN));
|
2020-08-18 20:42:30 +00:00
|
|
|
|
|
|
|
addPlayer(sock, plr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void PlayerManager::loadPlayer(CNSocket* sock, CNPacketData* data) {
|
2020-08-19 00:11:31 +00:00
|
|
|
if (data->size != sizeof(sP_CL2FE_REQ_PC_LOADING_COMPLETE))
|
|
|
|
return; // ignore the malformed packet
|
|
|
|
|
2020-08-18 20:42:30 +00:00
|
|
|
sP_CL2FE_REQ_PC_LOADING_COMPLETE* complete = (sP_CL2FE_REQ_PC_LOADING_COMPLETE*)data->buf;
|
2020-08-23 00:26:18 +00:00
|
|
|
INITSTRUCT(sP_FE2CL_REP_PC_LOADING_COMPLETE_SUCC, response);
|
2020-08-18 20:42:30 +00:00
|
|
|
|
|
|
|
DEBUGLOG(
|
|
|
|
std::cout << "P_CL2FE_REQ_PC_LOADING_COMPLETE:" << std::endl;
|
2020-08-22 18:02:08 +00:00
|
|
|
std::cout << "\tPC_ID: " << complete->iPC_ID << std::endl;
|
2020-08-18 20:42:30 +00:00
|
|
|
)
|
|
|
|
|
2020-08-22 23:31:09 +00:00
|
|
|
response.iPC_ID = complete->iPC_ID;
|
2020-08-18 20:42:30 +00:00
|
|
|
|
2020-08-22 23:31:09 +00:00
|
|
|
sock->sendPacket((void*)&response, P_FE2CL_REP_PC_LOADING_COMPLETE_SUCC, sizeof(sP_FE2CL_REP_PC_LOADING_COMPLETE_SUCC));
|
2020-08-18 20:42:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void PlayerManager::movePlayer(CNSocket* sock, CNPacketData* data) {
|
2020-08-19 00:11:31 +00:00
|
|
|
if (data->size != sizeof(sP_CL2FE_REQ_PC_MOVE))
|
|
|
|
return; // ignore the malformed packet
|
2020-08-22 18:02:08 +00:00
|
|
|
|
2020-08-18 20:42:30 +00:00
|
|
|
sP_CL2FE_REQ_PC_MOVE* moveData = (sP_CL2FE_REQ_PC_MOVE*)data->buf;
|
|
|
|
updatePlayerPosition(sock, moveData->iX, moveData->iY, moveData->iZ);
|
|
|
|
|
|
|
|
players[sock].plr.angle = moveData->iAngle;
|
|
|
|
uint64_t tm = getTime();
|
|
|
|
|
2020-08-23 00:26:18 +00:00
|
|
|
INITSTRUCT(sP_FE2CL_PC_MOVE, moveResponse);
|
2020-08-18 20:42:30 +00:00
|
|
|
|
2020-08-22 23:31:09 +00:00
|
|
|
moveResponse.iID = players[sock].plr.iID;
|
|
|
|
moveResponse.cKeyValue = moveData->cKeyValue;
|
2020-08-18 20:42:30 +00:00
|
|
|
|
2020-08-22 23:31:09 +00:00
|
|
|
moveResponse.iX = moveData->iX;
|
|
|
|
moveResponse.iY = moveData->iY;
|
|
|
|
moveResponse.iZ = moveData->iZ;
|
|
|
|
moveResponse.iAngle = moveData->iAngle;
|
|
|
|
moveResponse.fVX = moveData->fVX;
|
|
|
|
moveResponse.fVY = moveData->fVY;
|
|
|
|
moveResponse.fVZ = moveData->fVZ;
|
2020-08-22 18:02:08 +00:00
|
|
|
|
2020-08-22 23:31:09 +00:00
|
|
|
moveResponse.iSpeed = moveData->iSpeed;
|
|
|
|
moveResponse.iCliTime = moveData->iCliTime; // maybe don't send this??? seems unneeded...
|
|
|
|
moveResponse.iSvrTime = tm;
|
2020-08-18 20:42:30 +00:00
|
|
|
|
2020-08-22 23:31:09 +00:00
|
|
|
for (CNSocket* otherSock : players[sock].viewable) {
|
|
|
|
otherSock->sendPacket((void*)&moveResponse, P_FE2CL_PC_MOVE, sizeof(sP_FE2CL_PC_MOVE));
|
2020-08-18 20:42:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PlayerManager::stopPlayer(CNSocket* sock, CNPacketData* data) {
|
2020-08-19 00:11:31 +00:00
|
|
|
if (data->size != sizeof(sP_CL2FE_REQ_PC_STOP))
|
|
|
|
return; // ignore the malformed packet
|
|
|
|
|
2020-08-18 20:42:30 +00:00
|
|
|
sP_CL2FE_REQ_PC_STOP* stopData = (sP_CL2FE_REQ_PC_STOP*)data->buf;
|
|
|
|
updatePlayerPosition(sock, stopData->iX, stopData->iY, stopData->iZ);
|
|
|
|
|
|
|
|
uint64_t tm = getTime();
|
|
|
|
|
2020-08-23 00:26:18 +00:00
|
|
|
INITSTRUCT(sP_FE2CL_PC_STOP, stopResponse);
|
2020-08-18 20:42:30 +00:00
|
|
|
|
2020-08-22 23:31:09 +00:00
|
|
|
stopResponse.iID = players[sock].plr.iID;
|
2020-08-18 20:42:30 +00:00
|
|
|
|
2020-08-22 23:31:09 +00:00
|
|
|
stopResponse.iX = stopData->iX;
|
|
|
|
stopResponse.iY = stopData->iY;
|
|
|
|
stopResponse.iZ = stopData->iZ;
|
2020-08-18 20:42:30 +00:00
|
|
|
|
2020-08-22 23:31:09 +00:00
|
|
|
stopResponse.iCliTime = stopData->iCliTime; // maybe don't send this??? seems unneeded...
|
|
|
|
stopResponse.iSvrTime = tm;
|
2020-08-18 20:42:30 +00:00
|
|
|
|
2020-08-22 23:31:09 +00:00
|
|
|
for (CNSocket* otherSock : players[sock].viewable) {
|
|
|
|
otherSock->sendPacket((void*)&stopResponse, P_FE2CL_PC_STOP, sizeof(sP_FE2CL_PC_STOP));
|
2020-08-18 20:42:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PlayerManager::jumpPlayer(CNSocket* sock, CNPacketData* data) {
|
2020-08-19 00:11:31 +00:00
|
|
|
if (data->size != sizeof(sP_CL2FE_REQ_PC_JUMP))
|
|
|
|
return; // ignore the malformed packet
|
2020-08-22 18:02:08 +00:00
|
|
|
|
2020-08-18 20:42:30 +00:00
|
|
|
sP_CL2FE_REQ_PC_JUMP* jumpData = (sP_CL2FE_REQ_PC_JUMP*)data->buf;
|
|
|
|
updatePlayerPosition(sock, jumpData->iX, jumpData->iY, jumpData->iZ);
|
|
|
|
|
|
|
|
uint64_t tm = getTime();
|
|
|
|
|
2020-08-23 00:26:18 +00:00
|
|
|
INITSTRUCT(sP_FE2CL_PC_JUMP, jumpResponse);
|
2020-08-18 20:42:30 +00:00
|
|
|
|
2020-08-22 23:31:09 +00:00
|
|
|
jumpResponse.iID = players[sock].plr.iID;
|
|
|
|
jumpResponse.cKeyValue = jumpData->cKeyValue;
|
2020-08-18 20:42:30 +00:00
|
|
|
|
2020-08-22 23:31:09 +00:00
|
|
|
jumpResponse.iX = jumpData->iX;
|
|
|
|
jumpResponse.iY = jumpData->iY;
|
|
|
|
jumpResponse.iZ = jumpData->iZ;
|
|
|
|
jumpResponse.iAngle = jumpData->iAngle;
|
|
|
|
jumpResponse.iVX = jumpData->iVX;
|
|
|
|
jumpResponse.iVY = jumpData->iVY;
|
|
|
|
jumpResponse.iVZ = jumpData->iVZ;
|
2020-08-22 18:02:08 +00:00
|
|
|
|
2020-08-22 23:31:09 +00:00
|
|
|
jumpResponse.iSpeed = jumpData->iSpeed;
|
|
|
|
jumpResponse.iCliTime = jumpData->iCliTime; // maybe don't send this??? seems unneeded...
|
|
|
|
jumpResponse.iSvrTime = tm;
|
2020-08-18 20:42:30 +00:00
|
|
|
|
2020-08-22 23:31:09 +00:00
|
|
|
for (CNSocket* otherSock : players[sock].viewable) {
|
|
|
|
otherSock->sendPacket((void*)&jumpResponse, P_FE2CL_PC_JUMP, sizeof(sP_FE2CL_PC_JUMP));
|
2020-08-18 20:42:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-20 16:26:26 +00:00
|
|
|
void PlayerManager::jumppadPlayer(CNSocket* sock, CNPacketData* data) {
|
|
|
|
if (data->size != sizeof(sP_CL2FE_REQ_PC_JUMPPAD))
|
|
|
|
return; // ignore the malformed packet
|
2020-08-22 18:02:08 +00:00
|
|
|
|
2020-08-20 16:26:26 +00:00
|
|
|
sP_CL2FE_REQ_PC_JUMPPAD* jumppadData = (sP_CL2FE_REQ_PC_JUMPPAD*)data->buf;
|
|
|
|
updatePlayerPosition(sock, jumppadData->iX, jumppadData->iY, jumppadData->iZ);
|
|
|
|
|
|
|
|
uint64_t tm = getTime();
|
|
|
|
|
2020-08-23 00:26:18 +00:00
|
|
|
INITSTRUCT(sP_FE2CL_PC_JUMPPAD, jumppadResponse);
|
2020-08-20 16:26:26 +00:00
|
|
|
|
2020-08-22 23:31:09 +00:00
|
|
|
jumppadResponse.iPC_ID = players[sock].plr.iID;
|
|
|
|
jumppadResponse.cKeyValue = jumppadData->cKeyValue;
|
2020-08-20 16:26:26 +00:00
|
|
|
|
2020-08-22 23:31:09 +00:00
|
|
|
jumppadResponse.iX = jumppadData->iX;
|
|
|
|
jumppadResponse.iY = jumppadData->iY;
|
|
|
|
jumppadResponse.iZ = jumppadData->iZ;
|
|
|
|
jumppadResponse.iVX = jumppadData->iVX;
|
|
|
|
jumppadResponse.iVY = jumppadData->iVY;
|
|
|
|
jumppadResponse.iVZ = jumppadData->iVZ;
|
2020-08-22 18:02:08 +00:00
|
|
|
|
2020-08-22 23:31:09 +00:00
|
|
|
jumppadResponse.iCliTime = jumppadData->iCliTime;
|
|
|
|
jumppadResponse.iSvrTime = tm;
|
2020-08-20 16:26:26 +00:00
|
|
|
|
2020-08-22 23:31:09 +00:00
|
|
|
for (CNSocket* otherSock : players[sock].viewable) {
|
|
|
|
otherSock->sendPacket((void*)&jumppadResponse, P_FE2CL_PC_JUMPPAD, sizeof(sP_FE2CL_PC_JUMPPAD));
|
2020-08-20 16:26:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PlayerManager::launchPlayer(CNSocket* sock, CNPacketData* data) {
|
|
|
|
if (data->size != sizeof(sP_CL2FE_REQ_PC_LAUNCHER))
|
|
|
|
return; // ignore the malformed packet
|
2020-08-22 18:02:08 +00:00
|
|
|
|
2020-08-20 16:26:26 +00:00
|
|
|
sP_CL2FE_REQ_PC_LAUNCHER* launchData = (sP_CL2FE_REQ_PC_LAUNCHER*)data->buf;
|
|
|
|
updatePlayerPosition(sock, launchData->iX, launchData->iY, launchData->iZ);
|
|
|
|
|
|
|
|
uint64_t tm = getTime();
|
|
|
|
|
2020-08-23 00:26:18 +00:00
|
|
|
INITSTRUCT(sP_FE2CL_PC_LAUNCHER, launchResponse);
|
2020-08-20 16:26:26 +00:00
|
|
|
|
2020-08-22 23:31:09 +00:00
|
|
|
launchResponse.iPC_ID = players[sock].plr.iID;
|
2020-08-20 16:26:26 +00:00
|
|
|
|
2020-08-22 23:31:09 +00:00
|
|
|
launchResponse.iX = launchData->iX;
|
|
|
|
launchResponse.iY = launchData->iY;
|
|
|
|
launchResponse.iZ = launchData->iZ;
|
|
|
|
launchResponse.iVX = launchData->iVX;
|
|
|
|
launchResponse.iVY = launchData->iVY;
|
|
|
|
launchResponse.iVZ = launchData->iVZ;
|
|
|
|
launchResponse.iSpeed = launchData->iSpeed;
|
|
|
|
launchResponse.iAngle = launchData->iAngle;
|
2020-08-22 18:02:08 +00:00
|
|
|
|
2020-08-22 23:31:09 +00:00
|
|
|
launchResponse.iCliTime = launchData->iCliTime;
|
|
|
|
launchResponse.iSvrTime = tm;
|
2020-08-20 16:26:26 +00:00
|
|
|
|
2020-08-22 23:31:09 +00:00
|
|
|
for (CNSocket* otherSock : players[sock].viewable) {
|
|
|
|
otherSock->sendPacket((void*)&launchResponse, P_FE2CL_PC_LAUNCHER, sizeof(sP_FE2CL_PC_LAUNCHER));
|
2020-08-20 16:26:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PlayerManager::ziplinePlayer(CNSocket* sock, CNPacketData* data) {
|
|
|
|
if (data->size != sizeof(sP_CL2FE_REQ_PC_ZIPLINE))
|
|
|
|
return; // ignore the malformed packet
|
|
|
|
|
|
|
|
sP_CL2FE_REQ_PC_ZIPLINE* ziplineData = (sP_CL2FE_REQ_PC_ZIPLINE*)data->buf;
|
|
|
|
updatePlayerPosition(sock, ziplineData->iX, ziplineData->iY, ziplineData->iZ);
|
|
|
|
|
|
|
|
uint64_t tm = getTime();
|
|
|
|
|
2020-08-23 00:26:18 +00:00
|
|
|
INITSTRUCT(sP_FE2CL_PC_ZIPLINE, ziplineResponse);
|
2020-08-22 23:31:09 +00:00
|
|
|
|
|
|
|
ziplineResponse.iPC_ID = players[sock].plr.iID;
|
|
|
|
ziplineResponse.iCliTime = ziplineData->iCliTime;
|
|
|
|
ziplineResponse.iSvrTime = tm;
|
|
|
|
ziplineResponse.iX = ziplineData->iX;
|
|
|
|
ziplineResponse.iY = ziplineData->iY;
|
|
|
|
ziplineResponse.iZ = ziplineData->iZ;
|
|
|
|
ziplineResponse.fVX = ziplineData->fVX;
|
|
|
|
ziplineResponse.fVY = ziplineData->fVY;
|
|
|
|
ziplineResponse.fVZ = ziplineData->fVZ;
|
|
|
|
ziplineResponse.fMovDistance = ziplineData->fMovDistance;
|
|
|
|
ziplineResponse.fMaxDistance = ziplineData->fMaxDistance;
|
|
|
|
ziplineResponse.fDummy = ziplineData->fDummy; //wtf is this for?
|
|
|
|
ziplineResponse.iStX = ziplineData->iStX;
|
|
|
|
ziplineResponse.iStY = ziplineData->iStY;
|
|
|
|
ziplineResponse.iStZ = ziplineData->iStZ;
|
|
|
|
ziplineResponse.bDown = ziplineData->bDown;
|
|
|
|
ziplineResponse.iSpeed = ziplineData->iSpeed;
|
|
|
|
ziplineResponse.iAngle = ziplineData->iAngle;
|
|
|
|
ziplineResponse.iRollMax = ziplineData->iRollMax;
|
|
|
|
ziplineResponse.iRoll = ziplineData->iRoll;
|
2020-08-20 16:26:26 +00:00
|
|
|
|
2020-08-22 23:31:09 +00:00
|
|
|
for (CNSocket* otherSock : players[sock].viewable) {
|
|
|
|
otherSock->sendPacket((void*)&ziplineResponse, P_FE2CL_PC_ZIPLINE, sizeof(sP_FE2CL_PC_ZIPLINE));
|
2020-08-20 16:26:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-18 20:42:30 +00:00
|
|
|
void PlayerManager::movePlatformPlayer(CNSocket* sock, CNPacketData* data) {
|
2020-08-19 00:11:31 +00:00
|
|
|
if (data->size != sizeof(sP_CL2FE_REQ_PC_MOVEPLATFORM))
|
|
|
|
return; // ignore the malformed packet
|
|
|
|
|
2020-08-18 20:42:30 +00:00
|
|
|
sP_CL2FE_REQ_PC_MOVEPLATFORM* platformData = (sP_CL2FE_REQ_PC_MOVEPLATFORM*)data->buf;
|
|
|
|
updatePlayerPosition(sock, platformData->iX, platformData->iY, platformData->iZ);
|
|
|
|
|
|
|
|
uint64_t tm = getTime();
|
|
|
|
|
2020-08-23 00:26:18 +00:00
|
|
|
INITSTRUCT(sP_FE2CL_PC_MOVEPLATFORM, platResponse);
|
2020-08-22 23:31:09 +00:00
|
|
|
|
|
|
|
platResponse.iPC_ID = players[sock].plr.iID;
|
|
|
|
platResponse.iCliTime = platformData->iCliTime;
|
|
|
|
platResponse.iSvrTime = tm;
|
|
|
|
platResponse.iX = platformData->iX;
|
|
|
|
platResponse.iY = platformData->iY;
|
|
|
|
platResponse.iZ = platformData->iZ;
|
|
|
|
platResponse.iAngle = platformData->iAngle;
|
|
|
|
platResponse.fVX = platformData->fVX;
|
|
|
|
platResponse.fVY = platformData->fVY;
|
|
|
|
platResponse.fVZ = platformData->fVZ;
|
|
|
|
platResponse.iLcX = platformData->iLcX;
|
|
|
|
platResponse.iLcY = platformData->iLcY;
|
|
|
|
platResponse.iLcZ = platformData->iLcZ;
|
|
|
|
platResponse.iSpeed = platformData->iSpeed;
|
|
|
|
platResponse.bDown = platformData->bDown;
|
|
|
|
platResponse.cKeyValue = platformData->cKeyValue;
|
|
|
|
platResponse.iPlatformID = platformData->iPlatformID;
|
2020-08-18 20:42:30 +00:00
|
|
|
|
2020-08-22 23:31:09 +00:00
|
|
|
for (CNSocket* otherSock : players[sock].viewable) {
|
|
|
|
otherSock->sendPacket((void*)&platResponse, P_FE2CL_PC_MOVEPLATFORM, sizeof(sP_FE2CL_PC_MOVEPLATFORM));
|
2020-08-18 20:42:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-20 16:26:26 +00:00
|
|
|
void PlayerManager::moveSlopePlayer(CNSocket* sock, CNPacketData* data) {
|
|
|
|
if (data->size != sizeof(sP_CL2FE_REQ_PC_SLOPE))
|
|
|
|
return; // ignore the malformed packet
|
|
|
|
|
|
|
|
sP_CL2FE_REQ_PC_SLOPE* slopeData = (sP_CL2FE_REQ_PC_SLOPE*)data->buf;
|
|
|
|
updatePlayerPosition(sock, slopeData->iX, slopeData->iY, slopeData->iZ);
|
|
|
|
|
|
|
|
uint64_t tm = getTime();
|
|
|
|
|
2020-08-23 00:26:18 +00:00
|
|
|
INITSTRUCT(sP_FE2CL_PC_SLOPE, slopeResponse);
|
2020-08-22 23:31:09 +00:00
|
|
|
|
|
|
|
slopeResponse.iPC_ID = players[sock].plr.iID;
|
|
|
|
slopeResponse.iCliTime = slopeData->iCliTime;
|
|
|
|
slopeResponse.iSvrTime = tm;
|
|
|
|
slopeResponse.iX = slopeData->iX;
|
|
|
|
slopeResponse.iY = slopeData->iY;
|
|
|
|
slopeResponse.iZ = slopeData->iZ;
|
|
|
|
slopeResponse.iAngle = slopeData->iAngle;
|
|
|
|
slopeResponse.fVX = slopeData->fVX;
|
|
|
|
slopeResponse.fVY = slopeData->fVY;
|
|
|
|
slopeResponse.fVZ = slopeData->fVZ;
|
|
|
|
slopeResponse.iSpeed = slopeData->iSpeed;
|
|
|
|
slopeResponse.cKeyValue = slopeData->cKeyValue;
|
|
|
|
slopeResponse.iSlopeID = slopeData->iSlopeID;
|
2020-08-20 16:26:26 +00:00
|
|
|
|
2020-08-22 23:31:09 +00:00
|
|
|
for (CNSocket* otherSock : players[sock].viewable) {
|
|
|
|
otherSock->sendPacket((void*)&slopeResponse, P_FE2CL_PC_SLOPE, sizeof(sP_FE2CL_PC_SLOPE));
|
2020-08-20 16:26:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-18 20:42:30 +00:00
|
|
|
void PlayerManager::gotoPlayer(CNSocket* sock, CNPacketData* data) {
|
2020-08-19 00:11:31 +00:00
|
|
|
if (data->size != sizeof(sP_CL2FE_REQ_PC_GOTO))
|
|
|
|
return; // ignore the malformed packet
|
|
|
|
|
2020-08-18 20:42:30 +00:00
|
|
|
sP_CL2FE_REQ_PC_GOTO* gotoData = (sP_CL2FE_REQ_PC_GOTO*)data->buf;
|
2020-08-23 00:26:18 +00:00
|
|
|
INITSTRUCT(sP_FE2CL_REP_PC_GOTO_SUCC, response);
|
2020-08-18 20:42:30 +00:00
|
|
|
|
|
|
|
DEBUGLOG(
|
|
|
|
std::cout << "P_CL2FE_REQ_PC_GOTO:" << std::endl;
|
2020-08-22 18:02:08 +00:00
|
|
|
std::cout << "\tX: " << gotoData->iToX << std::endl;
|
|
|
|
std::cout << "\tY: " << gotoData->iToY << std::endl;
|
|
|
|
std::cout << "\tZ: " << gotoData->iToZ << std::endl;
|
2020-08-18 20:42:30 +00:00
|
|
|
)
|
|
|
|
|
2020-08-22 23:31:09 +00:00
|
|
|
response.iX = gotoData->iToX;
|
|
|
|
response.iY = gotoData->iToY;
|
|
|
|
response.iZ = gotoData->iToZ;
|
2020-08-18 20:42:30 +00:00
|
|
|
|
2020-08-22 23:31:09 +00:00
|
|
|
sock->sendPacket((void*)&response, P_FE2CL_REP_PC_GOTO_SUCC, sizeof(sP_FE2CL_REP_PC_GOTO_SUCC));
|
2020-08-18 20:42:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void PlayerManager::setSpecialPlayer(CNSocket* sock, CNPacketData* data) {
|
2020-08-19 00:11:31 +00:00
|
|
|
if (data->size != sizeof(sP_CL2FE_GM_REQ_PC_SET_VALUE))
|
|
|
|
return; // ignore the malformed packet
|
|
|
|
|
2020-08-18 20:42:30 +00:00
|
|
|
sP_CL2FE_GM_REQ_PC_SET_VALUE* setData = (sP_CL2FE_GM_REQ_PC_SET_VALUE*)data->buf;
|
2020-08-23 00:26:18 +00:00
|
|
|
INITSTRUCT(sP_FE2CL_GM_REP_PC_SET_VALUE, response);
|
2020-08-18 20:42:30 +00:00
|
|
|
|
|
|
|
DEBUGLOG(
|
|
|
|
std::cout << "P_CL2FE_GM_REQ_PC_SET_VALUE:" << std::endl;
|
2020-08-22 18:02:08 +00:00
|
|
|
std::cout << "\tPC_ID: " << setData->iPC_ID << std::endl;
|
|
|
|
std::cout << "\tSetValueType: " << setData->iSetValueType << std::endl;
|
|
|
|
std::cout << "\tSetValue: " << setData->iSetValue << std::endl;
|
2020-08-18 20:42:30 +00:00
|
|
|
)
|
|
|
|
|
2020-08-22 23:31:09 +00:00
|
|
|
response.iPC_ID = setData->iPC_ID;
|
|
|
|
response.iSetValue = setData->iSetValue;
|
|
|
|
response.iSetValueType = setData->iSetValueType;
|
2020-08-18 20:42:30 +00:00
|
|
|
|
2020-08-22 23:31:09 +00:00
|
|
|
sock->sendPacket((void*)&response, P_FE2CL_GM_REP_PC_SET_VALUE, sizeof(sP_FE2CL_GM_REP_PC_SET_VALUE));
|
2020-08-19 01:34:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void PlayerManager::heartbeatPlayer(CNSocket* sock, CNPacketData* data) {
|
|
|
|
players[sock].lastHeartbeat = getTime();
|
2020-08-19 17:22:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void PlayerManager::exitGame(CNSocket* sock, CNPacketData* data) {
|
2020-08-22 18:08:37 +00:00
|
|
|
if (data->size != sizeof(sP_CL2FE_REQ_PC_EXIT))
|
|
|
|
return;
|
|
|
|
|
2020-08-19 17:22:54 +00:00
|
|
|
sP_CL2FE_REQ_PC_EXIT* exitData = (sP_CL2FE_REQ_PC_EXIT*)data->buf;
|
2020-08-23 00:26:18 +00:00
|
|
|
INITSTRUCT(sP_FE2CL_REP_PC_EXIT_SUCC, response);
|
2020-08-19 17:22:54 +00:00
|
|
|
|
2020-08-22 23:31:09 +00:00
|
|
|
response.iID = exitData->iID;
|
|
|
|
response.iExitCode = 1;
|
2020-08-19 17:22:54 +00:00
|
|
|
|
2020-08-22 23:31:09 +00:00
|
|
|
sock->sendPacket((void*)&response, P_FE2CL_REP_PC_EXIT_SUCC, sizeof(sP_FE2CL_REP_PC_EXIT_SUCC));
|
2020-08-19 17:22:54 +00:00
|
|
|
}
|
2020-08-22 18:02:08 +00:00
|
|
|
|
|
|
|
void PlayerManager::updatePlayer(CNSocket* key, Player plr) {
|
|
|
|
PlayerView plrv = players[key];
|
|
|
|
plrv.plr = plr;
|
|
|
|
|
|
|
|
players[key] = plrv;
|
2020-08-23 00:52:54 +00:00
|
|
|
}
|