mirror of
https://github.com/OpenFusionProject/OpenFusion.git
synced 2024-11-05 06:50:04 +00:00
[refactor] Extract BuiltinCommands.cpp from PlayerManager.cpp
And move itemGMGiveHandler() from ItemManager.
This commit is contained in:
parent
2d7129111a
commit
f9c2587557
2
Makefile
2
Makefile
@ -44,6 +44,7 @@ CXXSRC=\
|
|||||||
src/ItemManager.cpp\
|
src/ItemManager.cpp\
|
||||||
src/NPCManager.cpp\
|
src/NPCManager.cpp\
|
||||||
src/PlayerManager.cpp\
|
src/PlayerManager.cpp\
|
||||||
|
src/BuiltinCommands.cpp\
|
||||||
src/settings.cpp\
|
src/settings.cpp\
|
||||||
src/TransportManager.cpp\
|
src/TransportManager.cpp\
|
||||||
src/TableData.cpp\
|
src/TableData.cpp\
|
||||||
@ -83,6 +84,7 @@ CXXHDR=\
|
|||||||
src/NPCManager.hpp\
|
src/NPCManager.hpp\
|
||||||
src/Player.hpp\
|
src/Player.hpp\
|
||||||
src/PlayerManager.hpp\
|
src/PlayerManager.hpp\
|
||||||
|
src/BuiltinCommands.hpp\
|
||||||
src/settings.hpp\
|
src/settings.hpp\
|
||||||
src/TransportManager.hpp\
|
src/TransportManager.hpp\
|
||||||
src/TableData.hpp\
|
src/TableData.hpp\
|
||||||
|
356
src/BuiltinCommands.cpp
Normal file
356
src/BuiltinCommands.cpp
Normal file
@ -0,0 +1,356 @@
|
|||||||
|
#include "BuiltinCommands.hpp"
|
||||||
|
#include "PlayerManager.hpp"
|
||||||
|
#include "ChatManager.hpp"
|
||||||
|
#include "ItemManager.hpp"
|
||||||
|
#include "MissionManager.hpp"
|
||||||
|
|
||||||
|
// helper function, not a packet handler
|
||||||
|
void BuiltinCommands::setSpecialState(CNSocket* sock, CNPacketData* data) {
|
||||||
|
if (data->size != sizeof(sP_CL2FE_GM_REQ_PC_SPECIAL_STATE_SWITCH))
|
||||||
|
return; // ignore the malformed packet
|
||||||
|
|
||||||
|
sP_CL2FE_GM_REQ_PC_SPECIAL_STATE_SWITCH* setData = (sP_CL2FE_GM_REQ_PC_SPECIAL_STATE_SWITCH*)data->buf;
|
||||||
|
Player *plr = PlayerManager::getPlayer(sock);
|
||||||
|
|
||||||
|
// HACK: work around the invisible weapon bug
|
||||||
|
if (setData->iSpecialStateFlag == CN_SPECIAL_STATE_FLAG__FULL_UI)
|
||||||
|
ItemManager::updateEquips(sock, plr);
|
||||||
|
|
||||||
|
INITSTRUCT(sP_FE2CL_PC_SPECIAL_STATE_CHANGE, response);
|
||||||
|
|
||||||
|
plr->iSpecialState ^= setData->iSpecialStateFlag;
|
||||||
|
|
||||||
|
response.iPC_ID = setData->iPC_ID;
|
||||||
|
response.iReqSpecialStateFlag = setData->iSpecialStateFlag;
|
||||||
|
response.iSpecialState = plr->iSpecialState;
|
||||||
|
|
||||||
|
sock->sendPacket((void*)&response, P_FE2CL_REP_PC_SPECIAL_STATE_SWITCH_SUCC, sizeof(sP_FE2CL_REP_PC_SPECIAL_STATE_SWITCH_SUCC));
|
||||||
|
PlayerManager::sendToViewable(sock, (void*)&response, P_FE2CL_PC_SPECIAL_STATE_CHANGE, sizeof(sP_FE2CL_PC_SPECIAL_STATE_CHANGE));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setGMSpecialSwitchPlayer(CNSocket* sock, CNPacketData* data) {
|
||||||
|
if (PlayerManager::getPlayer(sock)->accountLevel > 30)
|
||||||
|
return;
|
||||||
|
|
||||||
|
BuiltinCommands::setSpecialState(sock, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gotoPlayer(CNSocket* sock, CNPacketData* data) {
|
||||||
|
if (data->size != sizeof(sP_CL2FE_REQ_PC_GOTO))
|
||||||
|
return; // ignore the malformed packet
|
||||||
|
|
||||||
|
Player *plr = PlayerManager::getPlayer(sock);
|
||||||
|
if (plr->accountLevel > 50)
|
||||||
|
return;
|
||||||
|
|
||||||
|
sP_CL2FE_REQ_PC_GOTO* gotoData = (sP_CL2FE_REQ_PC_GOTO*)data->buf;
|
||||||
|
INITSTRUCT(sP_FE2CL_REP_PC_GOTO_SUCC, response);
|
||||||
|
|
||||||
|
DEBUGLOG(
|
||||||
|
std::cout << "P_CL2FE_REQ_PC_GOTO:" << std::endl;
|
||||||
|
std::cout << "\tX: " << gotoData->iToX << std::endl;
|
||||||
|
std::cout << "\tY: " << gotoData->iToY << std::endl;
|
||||||
|
std::cout << "\tZ: " << gotoData->iToZ << std::endl;
|
||||||
|
)
|
||||||
|
|
||||||
|
PlayerManager::sendPlayerTo(sock, gotoData->iToX, gotoData->iToY, gotoData->iToZ, INSTANCE_OVERWORLD);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setValuePlayer(CNSocket* sock, CNPacketData* data) {
|
||||||
|
if (data->size != sizeof(sP_CL2FE_GM_REQ_PC_SET_VALUE))
|
||||||
|
return; // ignore the malformed packet
|
||||||
|
|
||||||
|
Player *plr = PlayerManager::getPlayer(sock);
|
||||||
|
if (plr->accountLevel > 50)
|
||||||
|
return;
|
||||||
|
|
||||||
|
sP_CL2FE_GM_REQ_PC_SET_VALUE* setData = (sP_CL2FE_GM_REQ_PC_SET_VALUE*)data->buf;
|
||||||
|
|
||||||
|
INITSTRUCT(sP_FE2CL_GM_REP_PC_SET_VALUE, response);
|
||||||
|
|
||||||
|
DEBUGLOG(
|
||||||
|
std::cout << "P_CL2FE_GM_REQ_PC_SET_VALUE:" << std::endl;
|
||||||
|
std::cout << "\tPC_ID: " << setData->iPC_ID << std::endl;
|
||||||
|
std::cout << "\tSetValueType: " << setData->iSetValueType << std::endl;
|
||||||
|
std::cout << "\tSetValue: " << setData->iSetValue << std::endl;
|
||||||
|
)
|
||||||
|
|
||||||
|
// Handle serverside value-changes
|
||||||
|
switch (setData->iSetValueType) {
|
||||||
|
case 1:
|
||||||
|
plr->HP = setData->iSetValue;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
plr->batteryW = setData->iSetValue;
|
||||||
|
// caps
|
||||||
|
if (plr->batteryW > 9999)
|
||||||
|
plr->batteryW = 9999;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
plr->batteryN = setData->iSetValue;
|
||||||
|
// caps
|
||||||
|
if (plr->batteryN > 9999)
|
||||||
|
plr->batteryN = 9999;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
MissionManager::updateFusionMatter(sock, setData->iSetValue - plr->fusionmatter);
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
plr->money = setData->iSetValue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
response.iPC_ID = setData->iPC_ID;
|
||||||
|
response.iSetValue = setData->iSetValue;
|
||||||
|
response.iSetValueType = setData->iSetValueType;
|
||||||
|
|
||||||
|
sock->sendPacket((void*)&response, P_FE2CL_GM_REP_PC_SET_VALUE, sizeof(sP_FE2CL_GM_REP_PC_SET_VALUE));
|
||||||
|
|
||||||
|
// if one lowers their own health to 0, make sure others can see it
|
||||||
|
if (plr->HP <= 0) {
|
||||||
|
INITSTRUCT(sP_FE2CL_PC_SUDDEN_DEAD, dead);
|
||||||
|
|
||||||
|
dead.iPC_ID = plr->iID;
|
||||||
|
dead.iDamage = plr->HP;
|
||||||
|
dead.iHP = plr->HP = 0;
|
||||||
|
|
||||||
|
PlayerManager::sendToViewable(sock, (void*)&dead, P_FE2CL_PC_SUDDEN_DEAD, sizeof(sP_FE2CL_PC_SUDDEN_DEAD));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setGMSpecialOnOff(CNSocket *sock, CNPacketData *data) {
|
||||||
|
if (data->size != sizeof(sP_CL2FE_GM_REQ_TARGET_PC_SPECIAL_STATE_ONOFF))
|
||||||
|
return; // sanity check
|
||||||
|
|
||||||
|
Player *plr = PlayerManager::getPlayer(sock);
|
||||||
|
|
||||||
|
// access check
|
||||||
|
if (plr->accountLevel > 30)
|
||||||
|
return;
|
||||||
|
|
||||||
|
sP_CL2FE_GM_REQ_TARGET_PC_SPECIAL_STATE_ONOFF *req = (sP_CL2FE_GM_REQ_TARGET_PC_SPECIAL_STATE_ONOFF*)data->buf;
|
||||||
|
|
||||||
|
CNSocket *otherSock = PlayerManager::getSockFromAny(req->eTargetSearchBy, req->iTargetPC_ID, req->iTargetPC_UID,
|
||||||
|
U16toU8(req->szTargetPC_FirstName), U16toU8(req->szTargetPC_LastName));
|
||||||
|
if (otherSock == nullptr) {
|
||||||
|
ChatManager::sendServerMessage(sock, "player to teleport not found");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Player *otherPlr = PlayerManager::getPlayer(otherSock);
|
||||||
|
if (req->iONOFF)
|
||||||
|
otherPlr->iSpecialState |= req->iSpecialStateFlag;
|
||||||
|
else
|
||||||
|
otherPlr->iSpecialState &= ~req->iSpecialStateFlag;
|
||||||
|
|
||||||
|
// this is only used for muting players, so no need to update the client since that logic is server-side
|
||||||
|
}
|
||||||
|
|
||||||
|
static void locatePlayer(CNSocket *sock, CNPacketData *data) {
|
||||||
|
if (data->size != sizeof(sP_CL2FE_GM_REQ_PC_LOCATION))
|
||||||
|
return; // sanity check
|
||||||
|
|
||||||
|
Player *plr = PlayerManager::getPlayer(sock);
|
||||||
|
|
||||||
|
// access check
|
||||||
|
if (plr->accountLevel > 30)
|
||||||
|
return;
|
||||||
|
|
||||||
|
sP_CL2FE_GM_REQ_PC_LOCATION *req = (sP_CL2FE_GM_REQ_PC_LOCATION*)data->buf;
|
||||||
|
|
||||||
|
CNSocket *otherSock = PlayerManager::getSockFromAny(req->eTargetSearchBy, req->iTargetPC_ID, req->iTargetPC_UID,
|
||||||
|
U16toU8(req->szTargetPC_FirstName), U16toU8(req->szTargetPC_LastName));
|
||||||
|
if (otherSock == nullptr) {
|
||||||
|
ChatManager::sendServerMessage(sock, "player not found");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
INITSTRUCT(sP_FE2CL_GM_REP_PC_LOCATION, resp);
|
||||||
|
Player *otherPlr = PlayerManager::getPlayer(otherSock);
|
||||||
|
|
||||||
|
resp.iTargetPC_UID = otherPlr->accountId;
|
||||||
|
resp.iTargetPC_ID = otherPlr->iID;
|
||||||
|
resp.iShardID = 0; // sharding is unsupported
|
||||||
|
resp.iMapType = !!PLAYERID(otherPlr->instanceID); // private instance or not
|
||||||
|
resp.iMapID = PLAYERID(otherPlr->instanceID);
|
||||||
|
resp.iMapNum = MAPNUM(otherPlr->instanceID);
|
||||||
|
resp.iX = otherPlr->x;
|
||||||
|
resp.iY = otherPlr->y;
|
||||||
|
resp.iZ = otherPlr->z;
|
||||||
|
|
||||||
|
memcpy(resp.szTargetPC_FirstName, otherPlr->PCStyle.szFirstName, sizeof(resp.szTargetPC_FirstName));
|
||||||
|
memcpy(resp.szTargetPC_LastName, otherPlr->PCStyle.szLastName, sizeof(resp.szTargetPC_LastName));
|
||||||
|
|
||||||
|
sock->sendPacket((void*)&resp, P_FE2CL_GM_REP_PC_LOCATION, sizeof(sP_FE2CL_GM_REP_PC_LOCATION));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void kickPlayer(CNSocket *sock, CNPacketData *data) {
|
||||||
|
if (data->size != sizeof(sP_CL2FE_GM_REQ_KICK_PLAYER))
|
||||||
|
return; // sanity check
|
||||||
|
|
||||||
|
Player *plr = PlayerManager::getPlayer(sock);
|
||||||
|
|
||||||
|
// access check
|
||||||
|
if (plr->accountLevel > 30)
|
||||||
|
return;
|
||||||
|
|
||||||
|
sP_CL2FE_GM_REQ_KICK_PLAYER *req = (sP_CL2FE_GM_REQ_KICK_PLAYER*)data->buf;
|
||||||
|
|
||||||
|
CNSocket *otherSock = PlayerManager::getSockFromAny(req->eTargetSearchBy, req->iTargetPC_ID, req->iTargetPC_UID,
|
||||||
|
U16toU8(req->szTargetPC_FirstName), U16toU8(req->szTargetPC_LastName));
|
||||||
|
if (otherSock == nullptr) {
|
||||||
|
ChatManager::sendServerMessage(sock, "player not found");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Player *otherPlr = PlayerManager::getPlayer(otherSock);
|
||||||
|
|
||||||
|
if (plr->accountLevel > otherPlr->accountLevel) {
|
||||||
|
ChatManager::sendServerMessage(sock, "player has higher access level");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
INITSTRUCT(sP_FE2CL_REP_PC_EXIT_SUCC, response);
|
||||||
|
|
||||||
|
response.iID = otherPlr->iID;
|
||||||
|
response.iExitCode = 3; // "a GM has terminated your connection"
|
||||||
|
|
||||||
|
// send to target player
|
||||||
|
otherSock->sendPacket((void*)&response, P_FE2CL_REP_PC_EXIT_SUCC, sizeof(sP_FE2CL_REP_PC_EXIT_SUCC));
|
||||||
|
|
||||||
|
// ensure that the connection has terminated
|
||||||
|
otherSock->kill();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void warpToPlayer(CNSocket *sock, CNPacketData *data) {
|
||||||
|
if (data->size != sizeof(sP_CL2FE_REQ_PC_WARP_TO_PC))
|
||||||
|
return; // sanity check
|
||||||
|
|
||||||
|
Player *plr = PlayerManager::getPlayer(sock);
|
||||||
|
|
||||||
|
// access check
|
||||||
|
if (plr->accountLevel > 30)
|
||||||
|
return;
|
||||||
|
|
||||||
|
sP_CL2FE_REQ_PC_WARP_TO_PC *req = (sP_CL2FE_REQ_PC_WARP_TO_PC*)data->buf;
|
||||||
|
|
||||||
|
Player *otherPlr = PlayerManager::getPlayerFromID(req->iPC_ID);
|
||||||
|
if (otherPlr == nullptr) {
|
||||||
|
ChatManager::sendServerMessage(sock, "player not found");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PlayerManager::sendPlayerTo(sock, otherPlr->x, otherPlr->y, otherPlr->z, otherPlr->instanceID);
|
||||||
|
}
|
||||||
|
|
||||||
|
// GM teleport command
|
||||||
|
static void teleportPlayer(CNSocket *sock, CNPacketData *data) {
|
||||||
|
if (data->size != sizeof(sP_CL2FE_GM_REQ_TARGET_PC_TELEPORT))
|
||||||
|
return; // sanity check
|
||||||
|
|
||||||
|
Player *plr = PlayerManager::getPlayer(sock);
|
||||||
|
|
||||||
|
// access check
|
||||||
|
if (plr->accountLevel > 30)
|
||||||
|
return;
|
||||||
|
|
||||||
|
sP_CL2FE_GM_REQ_TARGET_PC_TELEPORT *req = (sP_CL2FE_GM_REQ_TARGET_PC_TELEPORT*)data->buf;
|
||||||
|
|
||||||
|
// player to teleport
|
||||||
|
CNSocket *targetSock = PlayerManager::getSockFromAny(req->eTargetPCSearchBy, req->iTargetPC_ID, req->iTargetPC_UID,
|
||||||
|
U16toU8(req->szTargetPC_FirstName), U16toU8(req->szTargetPC_LastName));
|
||||||
|
if (targetSock == nullptr) {
|
||||||
|
ChatManager::sendServerMessage(sock, "player to teleport not found");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CNSocket *goalSock = nullptr;
|
||||||
|
Player *goalPlr = nullptr;
|
||||||
|
Player *targetPlr = nullptr;
|
||||||
|
uint64_t instance = plr->instanceID;
|
||||||
|
const int unstickRange = 400;
|
||||||
|
|
||||||
|
switch (req->eTeleportType) {
|
||||||
|
case eCN_GM_TeleportMapType__MyLocation:
|
||||||
|
PlayerManager::sendPlayerTo(targetSock, plr->x, plr->y, plr->z, instance);
|
||||||
|
break;
|
||||||
|
case eCN_GM_TeleportMapType__MapXYZ:
|
||||||
|
instance = req->iToMap;
|
||||||
|
// fallthrough
|
||||||
|
case eCN_GM_TeleportMapType__XYZ:
|
||||||
|
PlayerManager::sendPlayerTo(targetSock, req->iToX, req->iToY, req->iToZ, instance);
|
||||||
|
break;
|
||||||
|
case eCN_GM_TeleportMapType__SomeoneLocation:
|
||||||
|
// player to teleport to
|
||||||
|
goalSock = PlayerManager::getSockFromAny(req->eGoalPCSearchBy, req->iGoalPC_ID, req->iGoalPC_UID,
|
||||||
|
U16toU8(req->szGoalPC_FirstName), U16toU8(req->szGoalPC_LastName));
|
||||||
|
if (goalSock == nullptr) {
|
||||||
|
ChatManager::sendServerMessage(sock, "teleportation target player not found");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
goalPlr = PlayerManager::getPlayer(goalSock);
|
||||||
|
|
||||||
|
PlayerManager::sendPlayerTo(targetSock, goalPlr->x, goalPlr->y, goalPlr->z, goalPlr->instanceID);
|
||||||
|
break;
|
||||||
|
case eCN_GM_TeleportMapType__Unstick:
|
||||||
|
targetPlr = PlayerManager::getPlayer(targetSock);
|
||||||
|
|
||||||
|
PlayerManager::sendPlayerTo(targetSock, targetPlr->x - unstickRange/2 + rand() % unstickRange,
|
||||||
|
targetPlr->y - unstickRange/2 + rand() % unstickRange, targetPlr->z + 80);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void itemGMGiveHandler(CNSocket* sock, CNPacketData* data) {
|
||||||
|
if (data->size != sizeof(sP_CL2FE_REQ_PC_GIVE_ITEM))
|
||||||
|
return; // ignore the malformed packet
|
||||||
|
|
||||||
|
sP_CL2FE_REQ_PC_GIVE_ITEM* itemreq = (sP_CL2FE_REQ_PC_GIVE_ITEM*)data->buf;
|
||||||
|
Player* plr = PlayerManager::getPlayer(sock);
|
||||||
|
|
||||||
|
if (plr->accountLevel > 50) {
|
||||||
|
// TODO: send fail packet
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (itemreq->eIL == 2) {
|
||||||
|
// Quest item, not a real item, handle this later, stubbed for now
|
||||||
|
// sock->sendPacket(new CNPacketData((void*)resp, P_FE2CL_REP_PC_GIVE_ITEM_FAIL, sizeof(sP_FE2CL_REP_PC_GIVE_ITEM_FAIL), sock->getFEKey()));
|
||||||
|
} else if (itemreq->eIL == 1 && itemreq->Item.iType >= 0 && itemreq->Item.iType <= 10) {
|
||||||
|
|
||||||
|
if (ItemManager::ItemData.find(std::pair<int32_t, int32_t>(itemreq->Item.iID, itemreq->Item.iType)) == ItemManager::ItemData.end()) {
|
||||||
|
// invalid item
|
||||||
|
std::cout << "[WARN] Item id " << itemreq->Item.iID << " with type " << itemreq->Item.iType << " is invalid (give item)" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
INITSTRUCT(sP_FE2CL_REP_PC_GIVE_ITEM_SUCC, resp);
|
||||||
|
|
||||||
|
resp.eIL = itemreq->eIL;
|
||||||
|
resp.iSlotNum = itemreq->iSlotNum;
|
||||||
|
if (itemreq->Item.iType == 10) {
|
||||||
|
// item is vehicle, set expiration date
|
||||||
|
// set time limit: current time + 7days
|
||||||
|
itemreq->Item.iTimeLimit = getTimestamp() + 604800;
|
||||||
|
}
|
||||||
|
resp.Item = itemreq->Item;
|
||||||
|
|
||||||
|
plr->Inven[itemreq->iSlotNum] = itemreq->Item;
|
||||||
|
|
||||||
|
sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_GIVE_ITEM_SUCC, sizeof(sP_FE2CL_REP_PC_GIVE_ITEM_SUCC));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BuiltinCommands::init() {
|
||||||
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_GOTO, gotoPlayer);
|
||||||
|
REGISTER_SHARD_PACKET(P_CL2FE_GM_REQ_PC_SET_VALUE, setValuePlayer);
|
||||||
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_GIVE_ITEM, itemGMGiveHandler);
|
||||||
|
|
||||||
|
REGISTER_SHARD_PACKET(P_CL2FE_GM_REQ_PC_SPECIAL_STATE_SWITCH, setGMSpecialSwitchPlayer);
|
||||||
|
REGISTER_SHARD_PACKET(P_CL2FE_GM_REQ_TARGET_PC_SPECIAL_STATE_ONOFF, setGMSpecialOnOff);
|
||||||
|
|
||||||
|
REGISTER_SHARD_PACKET(P_CL2FE_GM_REQ_PC_LOCATION, locatePlayer);
|
||||||
|
REGISTER_SHARD_PACKET(P_CL2FE_GM_REQ_KICK_PLAYER, kickPlayer);
|
||||||
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_WARP_TO_PC, warpToPlayer);
|
||||||
|
REGISTER_SHARD_PACKET(P_CL2FE_GM_REQ_TARGET_PC_TELEPORT, teleportPlayer);
|
||||||
|
}
|
9
src/BuiltinCommands.hpp
Normal file
9
src/BuiltinCommands.hpp
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CNProtocol.hpp"
|
||||||
|
|
||||||
|
namespace BuiltinCommands {
|
||||||
|
void init();
|
||||||
|
|
||||||
|
void setSpecialState(CNSocket *sock, CNPacketData *data);
|
||||||
|
};
|
@ -25,7 +25,6 @@ std::map<int32_t, int32_t> ItemManager::NanoCapsules; // crate id -> nano id
|
|||||||
void ItemManager::init() {
|
void ItemManager::init() {
|
||||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_ITEM_MOVE, itemMoveHandler);
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_ITEM_MOVE, itemMoveHandler);
|
||||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_ITEM_DELETE, itemDeleteHandler);
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_ITEM_DELETE, itemDeleteHandler);
|
||||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_GIVE_ITEM, itemGMGiveHandler);
|
|
||||||
// this one is for gumballs
|
// this one is for gumballs
|
||||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_ITEM_USE, itemUseHandler);
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_ITEM_USE, itemUseHandler);
|
||||||
// Bank
|
// Bank
|
||||||
@ -213,46 +212,6 @@ void ItemManager::itemDeleteHandler(CNSocket* sock, CNPacketData* data) {
|
|||||||
sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_ITEM_DELETE_SUCC, sizeof(sP_FE2CL_REP_PC_ITEM_DELETE_SUCC));
|
sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_ITEM_DELETE_SUCC, sizeof(sP_FE2CL_REP_PC_ITEM_DELETE_SUCC));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ItemManager::itemGMGiveHandler(CNSocket* sock, CNPacketData* data) {
|
|
||||||
if (data->size != sizeof(sP_CL2FE_REQ_PC_GIVE_ITEM))
|
|
||||||
return; // ignore the malformed packet
|
|
||||||
|
|
||||||
sP_CL2FE_REQ_PC_GIVE_ITEM* itemreq = (sP_CL2FE_REQ_PC_GIVE_ITEM*)data->buf;
|
|
||||||
Player* plr = PlayerManager::getPlayer(sock);
|
|
||||||
|
|
||||||
if (plr->accountLevel > 50) {
|
|
||||||
// TODO: send fail packet
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (itemreq->eIL == 2) {
|
|
||||||
// Quest item, not a real item, handle this later, stubbed for now
|
|
||||||
// sock->sendPacket(new CNPacketData((void*)resp, P_FE2CL_REP_PC_GIVE_ITEM_FAIL, sizeof(sP_FE2CL_REP_PC_GIVE_ITEM_FAIL), sock->getFEKey()));
|
|
||||||
} else if (itemreq->eIL == 1 && itemreq->Item.iType >= 0 && itemreq->Item.iType <= 10) {
|
|
||||||
|
|
||||||
if (ItemData.find(std::pair<int32_t, int32_t>(itemreq->Item.iID, itemreq->Item.iType)) == ItemData.end()) {
|
|
||||||
// invalid item
|
|
||||||
std::cout << "[WARN] Item id " << itemreq->Item.iID << " with type " << itemreq->Item.iType << " is invalid (give item)" << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
INITSTRUCT(sP_FE2CL_REP_PC_GIVE_ITEM_SUCC, resp);
|
|
||||||
|
|
||||||
resp.eIL = itemreq->eIL;
|
|
||||||
resp.iSlotNum = itemreq->iSlotNum;
|
|
||||||
if (itemreq->Item.iType == 10) {
|
|
||||||
// item is vehicle, set expiration date
|
|
||||||
// set time limit: current time + 7days
|
|
||||||
itemreq->Item.iTimeLimit = getTimestamp() + 604800;
|
|
||||||
}
|
|
||||||
resp.Item = itemreq->Item;
|
|
||||||
|
|
||||||
plr->Inven[itemreq->iSlotNum] = itemreq->Item;
|
|
||||||
|
|
||||||
sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_GIVE_ITEM_SUCC, sizeof(sP_FE2CL_REP_PC_GIVE_ITEM_SUCC));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ItemManager::itemUseHandler(CNSocket* sock, CNPacketData* data) {
|
void ItemManager::itemUseHandler(CNSocket* sock, CNPacketData* data) {
|
||||||
if (data->size != sizeof(sP_CL2FE_REQ_ITEM_USE))
|
if (data->size != sizeof(sP_CL2FE_REQ_ITEM_USE))
|
||||||
return; // ignore the malformed packet
|
return; // ignore the malformed packet
|
||||||
|
@ -44,7 +44,6 @@ namespace ItemManager {
|
|||||||
|
|
||||||
void itemMoveHandler(CNSocket* sock, CNPacketData* data);
|
void itemMoveHandler(CNSocket* sock, CNPacketData* data);
|
||||||
void itemDeleteHandler(CNSocket* sock, CNPacketData* data);
|
void itemDeleteHandler(CNSocket* sock, CNPacketData* data);
|
||||||
void itemGMGiveHandler(CNSocket* sock, CNPacketData* data);
|
|
||||||
void itemUseHandler(CNSocket* sock, CNPacketData* data);
|
void itemUseHandler(CNSocket* sock, CNPacketData* data);
|
||||||
// Bank
|
// Bank
|
||||||
void itemBankOpenHandler(CNSocket* sock, CNPacketData* data);
|
void itemBankOpenHandler(CNSocket* sock, CNPacketData* data);
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
#include "CNProtocol.hpp"
|
|
||||||
#include "PlayerManager.hpp"
|
#include "PlayerManager.hpp"
|
||||||
#include "NPCManager.hpp"
|
#include "NPCManager.hpp"
|
||||||
#include "CNShardServer.hpp"
|
#include "CNShardServer.hpp"
|
||||||
#include "CNShared.hpp"
|
|
||||||
#include "MissionManager.hpp"
|
#include "MissionManager.hpp"
|
||||||
#include "ItemManager.hpp"
|
#include "ItemManager.hpp"
|
||||||
#include "NanoManager.hpp"
|
#include "NanoManager.hpp"
|
||||||
@ -12,6 +10,7 @@
|
|||||||
#include "BuddyManager.hpp"
|
#include "BuddyManager.hpp"
|
||||||
#include "MobManager.hpp"
|
#include "MobManager.hpp"
|
||||||
#include "RacingManager.hpp"
|
#include "RacingManager.hpp"
|
||||||
|
#include "BuiltinCommands.hpp"
|
||||||
|
|
||||||
#include "settings.hpp"
|
#include "settings.hpp"
|
||||||
|
|
||||||
@ -36,22 +35,14 @@ void PlayerManager::init() {
|
|||||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_MOVEPLATFORM, movePlatformPlayer);
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_MOVEPLATFORM, movePlatformPlayer);
|
||||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_MOVETRANSPORTATION, moveSliderPlayer);
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_MOVETRANSPORTATION, moveSliderPlayer);
|
||||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_SLOPE, moveSlopePlayer);
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_SLOPE, moveSlopePlayer);
|
||||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_GOTO, gotoPlayer);
|
|
||||||
REGISTER_SHARD_PACKET(P_CL2FE_GM_REQ_PC_SET_VALUE, setValuePlayer);
|
|
||||||
REGISTER_SHARD_PACKET(P_CL2FE_REP_LIVE_CHECK, heartbeatPlayer);
|
REGISTER_SHARD_PACKET(P_CL2FE_REP_LIVE_CHECK, heartbeatPlayer);
|
||||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_REGEN, revivePlayer);
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_REGEN, revivePlayer);
|
||||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_EXIT, exitGame);
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_EXIT, exitGame);
|
||||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_SPECIAL_STATE_SWITCH, setSpecialSwitchPlayer);
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_SPECIAL_STATE_SWITCH, setSpecialSwitchPlayer);
|
||||||
REGISTER_SHARD_PACKET(P_CL2FE_GM_REQ_PC_SPECIAL_STATE_SWITCH, setGMSpecialSwitchPlayer);
|
|
||||||
REGISTER_SHARD_PACKET(P_CL2FE_GM_REQ_TARGET_PC_SPECIAL_STATE_ONOFF, setGMSpecialOnOff);
|
|
||||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_VEHICLE_ON, enterPlayerVehicle);
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_VEHICLE_ON, enterPlayerVehicle);
|
||||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_VEHICLE_OFF, exitPlayerVehicle);
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_VEHICLE_OFF, exitPlayerVehicle);
|
||||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_CHANGE_MENTOR, changePlayerGuide);
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_CHANGE_MENTOR, changePlayerGuide);
|
||||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_FIRST_USE_FLAG_SET, setFirstUseFlag);
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_FIRST_USE_FLAG_SET, setFirstUseFlag);
|
||||||
REGISTER_SHARD_PACKET(P_CL2FE_GM_REQ_PC_LOCATION, locatePlayer);
|
|
||||||
REGISTER_SHARD_PACKET(P_CL2FE_GM_REQ_KICK_PLAYER, kickPlayer);
|
|
||||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_WARP_TO_PC, warpToPlayer);
|
|
||||||
REGISTER_SHARD_PACKET(P_CL2FE_GM_REQ_TARGET_PC_TELEPORT, teleportPlayer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerManager::addPlayer(CNSocket* key, Player plr) {
|
void PlayerManager::addPlayer(CNSocket* key, Player plr) {
|
||||||
@ -670,89 +661,6 @@ void PlayerManager::moveSlopePlayer(CNSocket* sock, CNPacketData* data) {
|
|||||||
sendToViewable(sock, (void*)&slopeResponse, P_FE2CL_PC_SLOPE, sizeof(sP_FE2CL_PC_SLOPE));
|
sendToViewable(sock, (void*)&slopeResponse, P_FE2CL_PC_SLOPE, sizeof(sP_FE2CL_PC_SLOPE));
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerManager::gotoPlayer(CNSocket* sock, CNPacketData* data) {
|
|
||||||
if (data->size != sizeof(sP_CL2FE_REQ_PC_GOTO))
|
|
||||||
return; // ignore the malformed packet
|
|
||||||
|
|
||||||
Player *plr = getPlayer(sock);
|
|
||||||
if (plr->accountLevel > 50)
|
|
||||||
return;
|
|
||||||
|
|
||||||
sP_CL2FE_REQ_PC_GOTO* gotoData = (sP_CL2FE_REQ_PC_GOTO*)data->buf;
|
|
||||||
INITSTRUCT(sP_FE2CL_REP_PC_GOTO_SUCC, response);
|
|
||||||
|
|
||||||
DEBUGLOG(
|
|
||||||
std::cout << "P_CL2FE_REQ_PC_GOTO:" << std::endl;
|
|
||||||
std::cout << "\tX: " << gotoData->iToX << std::endl;
|
|
||||||
std::cout << "\tY: " << gotoData->iToY << std::endl;
|
|
||||||
std::cout << "\tZ: " << gotoData->iToZ << std::endl;
|
|
||||||
)
|
|
||||||
|
|
||||||
sendPlayerTo(sock, gotoData->iToX, gotoData->iToY, gotoData->iToZ, INSTANCE_OVERWORLD);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PlayerManager::setValuePlayer(CNSocket* sock, CNPacketData* data) {
|
|
||||||
if (data->size != sizeof(sP_CL2FE_GM_REQ_PC_SET_VALUE))
|
|
||||||
return; // ignore the malformed packet
|
|
||||||
|
|
||||||
Player *plr = getPlayer(sock);
|
|
||||||
if (plr->accountLevel > 50)
|
|
||||||
return;
|
|
||||||
|
|
||||||
sP_CL2FE_GM_REQ_PC_SET_VALUE* setData = (sP_CL2FE_GM_REQ_PC_SET_VALUE*)data->buf;
|
|
||||||
|
|
||||||
INITSTRUCT(sP_FE2CL_GM_REP_PC_SET_VALUE, response);
|
|
||||||
|
|
||||||
DEBUGLOG(
|
|
||||||
std::cout << "P_CL2FE_GM_REQ_PC_SET_VALUE:" << std::endl;
|
|
||||||
std::cout << "\tPC_ID: " << setData->iPC_ID << std::endl;
|
|
||||||
std::cout << "\tSetValueType: " << setData->iSetValueType << std::endl;
|
|
||||||
std::cout << "\tSetValue: " << setData->iSetValue << std::endl;
|
|
||||||
)
|
|
||||||
|
|
||||||
// Handle serverside value-changes
|
|
||||||
switch (setData->iSetValueType) {
|
|
||||||
case 1:
|
|
||||||
plr->HP = setData->iSetValue;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
plr->batteryW = setData->iSetValue;
|
|
||||||
// caps
|
|
||||||
if (plr->batteryW > 9999)
|
|
||||||
plr->batteryW = 9999;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
plr->batteryN = setData->iSetValue;
|
|
||||||
// caps
|
|
||||||
if (plr->batteryN > 9999)
|
|
||||||
plr->batteryN = 9999;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
MissionManager::updateFusionMatter(sock, setData->iSetValue - plr->fusionmatter);
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
plr->money = setData->iSetValue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
response.iPC_ID = setData->iPC_ID;
|
|
||||||
response.iSetValue = setData->iSetValue;
|
|
||||||
response.iSetValueType = setData->iSetValueType;
|
|
||||||
|
|
||||||
sock->sendPacket((void*)&response, P_FE2CL_GM_REP_PC_SET_VALUE, sizeof(sP_FE2CL_GM_REP_PC_SET_VALUE));
|
|
||||||
|
|
||||||
// if one lowers their own health to 0, make sure others can see it
|
|
||||||
if (plr->HP <= 0) {
|
|
||||||
INITSTRUCT(sP_FE2CL_PC_SUDDEN_DEAD, dead);
|
|
||||||
|
|
||||||
dead.iPC_ID = plr->iID;
|
|
||||||
dead.iDamage = plr->HP;
|
|
||||||
dead.iHP = plr->HP = 0;
|
|
||||||
|
|
||||||
sendToViewable(sock, (void*)&dead, P_FE2CL_PC_SUDDEN_DEAD, sizeof(sP_FE2CL_PC_SUDDEN_DEAD));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PlayerManager::heartbeatPlayer(CNSocket* sock, CNPacketData* data) {
|
void PlayerManager::heartbeatPlayer(CNSocket* sock, CNPacketData* data) {
|
||||||
getPlayer(sock)->lastHeartbeat = getTime();
|
getPlayer(sock)->lastHeartbeat = getTime();
|
||||||
}
|
}
|
||||||
@ -912,38 +820,7 @@ void PlayerManager::exitPlayerVehicle(CNSocket* sock, CNPacketData* data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PlayerManager::setSpecialSwitchPlayer(CNSocket* sock, CNPacketData* data) {
|
void PlayerManager::setSpecialSwitchPlayer(CNSocket* sock, CNPacketData* data) {
|
||||||
setSpecialState(sock, data);
|
BuiltinCommands::setSpecialState(sock, data);
|
||||||
}
|
|
||||||
|
|
||||||
void PlayerManager::setGMSpecialSwitchPlayer(CNSocket* sock, CNPacketData* data) {
|
|
||||||
|
|
||||||
if (getPlayer(sock)->accountLevel > 30)
|
|
||||||
return;
|
|
||||||
|
|
||||||
setSpecialState(sock, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PlayerManager::setSpecialState(CNSocket* sock, CNPacketData* data) {
|
|
||||||
if (data->size != sizeof(sP_CL2FE_GM_REQ_PC_SPECIAL_STATE_SWITCH))
|
|
||||||
return; // ignore the malformed packet
|
|
||||||
|
|
||||||
sP_CL2FE_GM_REQ_PC_SPECIAL_STATE_SWITCH* setData = (sP_CL2FE_GM_REQ_PC_SPECIAL_STATE_SWITCH*)data->buf;
|
|
||||||
Player *plr = getPlayer(sock);
|
|
||||||
|
|
||||||
// HACK: work around the invisible weapon bug
|
|
||||||
if (setData->iSpecialStateFlag == CN_SPECIAL_STATE_FLAG__FULL_UI)
|
|
||||||
ItemManager::updateEquips(sock, plr);
|
|
||||||
|
|
||||||
INITSTRUCT(sP_FE2CL_PC_SPECIAL_STATE_CHANGE, response);
|
|
||||||
|
|
||||||
plr->iSpecialState ^= setData->iSpecialStateFlag;
|
|
||||||
|
|
||||||
response.iPC_ID = setData->iPC_ID;
|
|
||||||
response.iReqSpecialStateFlag = setData->iSpecialStateFlag;
|
|
||||||
response.iSpecialState = plr->iSpecialState;
|
|
||||||
|
|
||||||
sock->sendPacket((void*)&response, P_FE2CL_REP_PC_SPECIAL_STATE_SWITCH_SUCC, sizeof(sP_FE2CL_REP_PC_SPECIAL_STATE_SWITCH_SUCC));
|
|
||||||
sendToViewable(sock, (void*)&response, P_FE2CL_PC_SPECIAL_STATE_CHANGE, sizeof(sP_FE2CL_PC_SPECIAL_STATE_CHANGE));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerManager::changePlayerGuide(CNSocket *sock, CNPacketData *data) {
|
void PlayerManager::changePlayerGuide(CNSocket *sock, CNPacketData *data) {
|
||||||
@ -994,189 +871,6 @@ void PlayerManager::setFirstUseFlag(CNSocket* sock, CNPacketData* data) {
|
|||||||
plr->iFirstUseFlag[1] |= (1ULL << (flag->iFlagCode - 65));
|
plr->iFirstUseFlag[1] |= (1ULL << (flag->iFlagCode - 65));
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerManager::setGMSpecialOnOff(CNSocket *sock, CNPacketData *data) {
|
|
||||||
if (data->size != sizeof(sP_CL2FE_GM_REQ_TARGET_PC_SPECIAL_STATE_ONOFF))
|
|
||||||
return; // sanity check
|
|
||||||
|
|
||||||
Player *plr = getPlayer(sock);
|
|
||||||
|
|
||||||
// access check
|
|
||||||
if (plr->accountLevel > 30)
|
|
||||||
return;
|
|
||||||
|
|
||||||
sP_CL2FE_GM_REQ_TARGET_PC_SPECIAL_STATE_ONOFF *req = (sP_CL2FE_GM_REQ_TARGET_PC_SPECIAL_STATE_ONOFF*)data->buf;
|
|
||||||
|
|
||||||
CNSocket *otherSock = getSockFromAny(req->eTargetSearchBy, req->iTargetPC_ID, req->iTargetPC_UID,
|
|
||||||
U16toU8(req->szTargetPC_FirstName), U16toU8(req->szTargetPC_LastName));
|
|
||||||
if (otherSock == nullptr) {
|
|
||||||
ChatManager::sendServerMessage(sock, "player to teleport not found");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Player *otherPlr = getPlayer(otherSock);
|
|
||||||
if (req->iONOFF)
|
|
||||||
otherPlr->iSpecialState |= req->iSpecialStateFlag;
|
|
||||||
else
|
|
||||||
otherPlr->iSpecialState &= ~req->iSpecialStateFlag;
|
|
||||||
|
|
||||||
// this is only used for muting players, so no need to update the client since that logic is server-side
|
|
||||||
}
|
|
||||||
|
|
||||||
void PlayerManager::locatePlayer(CNSocket *sock, CNPacketData *data) {
|
|
||||||
if (data->size != sizeof(sP_CL2FE_GM_REQ_PC_LOCATION))
|
|
||||||
return; // sanity check
|
|
||||||
|
|
||||||
Player *plr = getPlayer(sock);
|
|
||||||
|
|
||||||
// access check
|
|
||||||
if (plr->accountLevel > 30)
|
|
||||||
return;
|
|
||||||
|
|
||||||
sP_CL2FE_GM_REQ_PC_LOCATION *req = (sP_CL2FE_GM_REQ_PC_LOCATION*)data->buf;
|
|
||||||
|
|
||||||
CNSocket *otherSock = getSockFromAny(req->eTargetSearchBy, req->iTargetPC_ID, req->iTargetPC_UID,
|
|
||||||
U16toU8(req->szTargetPC_FirstName), U16toU8(req->szTargetPC_LastName));
|
|
||||||
if (otherSock == nullptr) {
|
|
||||||
ChatManager::sendServerMessage(sock, "player not found");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
INITSTRUCT(sP_FE2CL_GM_REP_PC_LOCATION, resp);
|
|
||||||
Player *otherPlr = getPlayer(otherSock);
|
|
||||||
|
|
||||||
resp.iTargetPC_UID = otherPlr->accountId;
|
|
||||||
resp.iTargetPC_ID = otherPlr->iID;
|
|
||||||
resp.iShardID = 0; // sharding is unsupported
|
|
||||||
resp.iMapType = !!PLAYERID(otherPlr->instanceID); // private instance or not
|
|
||||||
resp.iMapID = PLAYERID(otherPlr->instanceID);
|
|
||||||
resp.iMapNum = MAPNUM(otherPlr->instanceID);
|
|
||||||
resp.iX = otherPlr->x;
|
|
||||||
resp.iY = otherPlr->y;
|
|
||||||
resp.iZ = otherPlr->z;
|
|
||||||
|
|
||||||
memcpy(resp.szTargetPC_FirstName, otherPlr->PCStyle.szFirstName, sizeof(resp.szTargetPC_FirstName));
|
|
||||||
memcpy(resp.szTargetPC_LastName, otherPlr->PCStyle.szLastName, sizeof(resp.szTargetPC_LastName));
|
|
||||||
|
|
||||||
sock->sendPacket((void*)&resp, P_FE2CL_GM_REP_PC_LOCATION, sizeof(sP_FE2CL_GM_REP_PC_LOCATION));
|
|
||||||
}
|
|
||||||
|
|
||||||
void PlayerManager::kickPlayer(CNSocket *sock, CNPacketData *data) {
|
|
||||||
if (data->size != sizeof(sP_CL2FE_GM_REQ_KICK_PLAYER))
|
|
||||||
return; // sanity check
|
|
||||||
|
|
||||||
Player *plr = getPlayer(sock);
|
|
||||||
|
|
||||||
// access check
|
|
||||||
if (plr->accountLevel > 30)
|
|
||||||
return;
|
|
||||||
|
|
||||||
sP_CL2FE_GM_REQ_KICK_PLAYER *req = (sP_CL2FE_GM_REQ_KICK_PLAYER*)data->buf;
|
|
||||||
|
|
||||||
CNSocket *otherSock = getSockFromAny(req->eTargetSearchBy, req->iTargetPC_ID, req->iTargetPC_UID,
|
|
||||||
U16toU8(req->szTargetPC_FirstName), U16toU8(req->szTargetPC_LastName));
|
|
||||||
if (otherSock == nullptr) {
|
|
||||||
ChatManager::sendServerMessage(sock, "player not found");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Player *otherPlr = getPlayer(otherSock);
|
|
||||||
|
|
||||||
if (plr->accountLevel > otherPlr->accountLevel) {
|
|
||||||
ChatManager::sendServerMessage(sock, "player has higher access level");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
INITSTRUCT(sP_FE2CL_REP_PC_EXIT_SUCC, response);
|
|
||||||
|
|
||||||
response.iID = otherPlr->iID;
|
|
||||||
response.iExitCode = 3; // "a GM has terminated your connection"
|
|
||||||
|
|
||||||
// send to target player
|
|
||||||
otherSock->sendPacket((void*)&response, P_FE2CL_REP_PC_EXIT_SUCC, sizeof(sP_FE2CL_REP_PC_EXIT_SUCC));
|
|
||||||
|
|
||||||
// ensure that the connection has terminated
|
|
||||||
otherSock->kill();
|
|
||||||
}
|
|
||||||
|
|
||||||
void PlayerManager::warpToPlayer(CNSocket *sock, CNPacketData *data) {
|
|
||||||
if (data->size != sizeof(sP_CL2FE_REQ_PC_WARP_TO_PC))
|
|
||||||
return; // sanity check
|
|
||||||
|
|
||||||
Player *plr = getPlayer(sock);
|
|
||||||
|
|
||||||
// access check
|
|
||||||
if (plr->accountLevel > 30)
|
|
||||||
return;
|
|
||||||
|
|
||||||
sP_CL2FE_REQ_PC_WARP_TO_PC *req = (sP_CL2FE_REQ_PC_WARP_TO_PC*)data->buf;
|
|
||||||
|
|
||||||
Player *otherPlr = getPlayerFromID(req->iPC_ID);
|
|
||||||
if (otherPlr == nullptr) {
|
|
||||||
ChatManager::sendServerMessage(sock, "player not found");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
sendPlayerTo(sock, otherPlr->x, otherPlr->y, otherPlr->z, otherPlr->instanceID);
|
|
||||||
}
|
|
||||||
|
|
||||||
// GM teleport command
|
|
||||||
void PlayerManager::teleportPlayer(CNSocket *sock, CNPacketData *data) {
|
|
||||||
if (data->size != sizeof(sP_CL2FE_GM_REQ_TARGET_PC_TELEPORT))
|
|
||||||
return; // sanity check
|
|
||||||
|
|
||||||
Player *plr = getPlayer(sock);
|
|
||||||
|
|
||||||
// access check
|
|
||||||
if (plr->accountLevel > 30)
|
|
||||||
return;
|
|
||||||
|
|
||||||
sP_CL2FE_GM_REQ_TARGET_PC_TELEPORT *req = (sP_CL2FE_GM_REQ_TARGET_PC_TELEPORT*)data->buf;
|
|
||||||
|
|
||||||
// player to teleport
|
|
||||||
CNSocket *targetSock = getSockFromAny(req->eTargetPCSearchBy, req->iTargetPC_ID, req->iTargetPC_UID,
|
|
||||||
U16toU8(req->szTargetPC_FirstName), U16toU8(req->szTargetPC_LastName));
|
|
||||||
if (targetSock == nullptr) {
|
|
||||||
ChatManager::sendServerMessage(sock, "player to teleport not found");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CNSocket *goalSock = nullptr;
|
|
||||||
Player *goalPlr = nullptr;
|
|
||||||
Player *targetPlr = nullptr;
|
|
||||||
uint64_t instance = plr->instanceID;
|
|
||||||
const int unstickRange = 400;
|
|
||||||
|
|
||||||
switch (req->eTeleportType) {
|
|
||||||
case eCN_GM_TeleportMapType__MyLocation:
|
|
||||||
sendPlayerTo(targetSock, plr->x, plr->y, plr->z, instance);
|
|
||||||
break;
|
|
||||||
case eCN_GM_TeleportMapType__MapXYZ:
|
|
||||||
instance = req->iToMap;
|
|
||||||
// fallthrough
|
|
||||||
case eCN_GM_TeleportMapType__XYZ:
|
|
||||||
sendPlayerTo(targetSock, req->iToX, req->iToY, req->iToZ, instance);
|
|
||||||
break;
|
|
||||||
case eCN_GM_TeleportMapType__SomeoneLocation:
|
|
||||||
// player to teleport to
|
|
||||||
goalSock = getSockFromAny(req->eGoalPCSearchBy, req->iGoalPC_ID, req->iGoalPC_UID,
|
|
||||||
U16toU8(req->szGoalPC_FirstName), U16toU8(req->szGoalPC_LastName));
|
|
||||||
if (goalSock == nullptr) {
|
|
||||||
ChatManager::sendServerMessage(sock, "teleportation target player not found");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
goalPlr = getPlayer(goalSock);
|
|
||||||
|
|
||||||
sendPlayerTo(targetSock, goalPlr->x, goalPlr->y, goalPlr->z, goalPlr->instanceID);
|
|
||||||
break;
|
|
||||||
case eCN_GM_TeleportMapType__Unstick:
|
|
||||||
targetPlr = getPlayer(targetSock);
|
|
||||||
|
|
||||||
sendPlayerTo(targetSock, targetPlr->x - unstickRange/2 + rand() % unstickRange,
|
|
||||||
targetPlr->y - unstickRange/2 + rand() % unstickRange, targetPlr->z + 80);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma region Helper methods
|
#pragma region Helper methods
|
||||||
Player *PlayerManager::getPlayer(CNSocket* key) {
|
Player *PlayerManager::getPlayer(CNSocket* key) {
|
||||||
if (players.find(key) != players.end())
|
if (players.find(key) != players.end())
|
||||||
|
@ -37,20 +37,12 @@ namespace PlayerManager {
|
|||||||
void movePlatformPlayer(CNSocket* sock, CNPacketData* data);
|
void movePlatformPlayer(CNSocket* sock, CNPacketData* data);
|
||||||
void moveSliderPlayer(CNSocket* sock, CNPacketData* data);
|
void moveSliderPlayer(CNSocket* sock, CNPacketData* data);
|
||||||
void moveSlopePlayer(CNSocket* sock, CNPacketData* data);
|
void moveSlopePlayer(CNSocket* sock, CNPacketData* data);
|
||||||
void gotoPlayer(CNSocket* sock, CNPacketData* data);
|
|
||||||
void setValuePlayer(CNSocket* sock, CNPacketData* data);
|
|
||||||
void heartbeatPlayer(CNSocket* sock, CNPacketData* data);
|
void heartbeatPlayer(CNSocket* sock, CNPacketData* data);
|
||||||
void revivePlayer(CNSocket* sock, CNPacketData* data);
|
void revivePlayer(CNSocket* sock, CNPacketData* data);
|
||||||
void exitGame(CNSocket* sock, CNPacketData* data);
|
void exitGame(CNSocket* sock, CNPacketData* data);
|
||||||
|
|
||||||
void setSpecialSwitchPlayer(CNSocket* sock, CNPacketData* data);
|
void setSpecialSwitchPlayer(CNSocket* sock, CNPacketData* data);
|
||||||
void setGMSpecialSwitchPlayer(CNSocket* sock, CNPacketData* data);
|
|
||||||
void setGMSpecialOnOff(CNSocket* sock, CNPacketData *data);
|
|
||||||
void changePlayerGuide(CNSocket *sock, CNPacketData *data);
|
void changePlayerGuide(CNSocket *sock, CNPacketData *data);
|
||||||
void locatePlayer(CNSocket *sock, CNPacketData *data);
|
|
||||||
void kickPlayer(CNSocket *sock, CNPacketData *data);
|
|
||||||
void warpToPlayer(CNSocket *sock, CNPacketData *data);
|
|
||||||
void teleportPlayer(CNSocket *sock, CNPacketData *data);
|
|
||||||
|
|
||||||
void enterPlayerVehicle(CNSocket* sock, CNPacketData* data);
|
void enterPlayerVehicle(CNSocket* sock, CNPacketData* data);
|
||||||
void exitPlayerVehicle(CNSocket* sock, CNPacketData* data);
|
void exitPlayerVehicle(CNSocket* sock, CNPacketData* data);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "CNLoginServer.hpp"
|
#include "CNLoginServer.hpp"
|
||||||
#include "CNShardServer.hpp"
|
#include "CNShardServer.hpp"
|
||||||
#include "PlayerManager.hpp"
|
#include "PlayerManager.hpp"
|
||||||
|
#include "BuiltinCommands.hpp"
|
||||||
#include "ChatManager.hpp"
|
#include "ChatManager.hpp"
|
||||||
#include "CustomCommands.hpp"
|
#include "CustomCommands.hpp"
|
||||||
#include "MobManager.hpp"
|
#include "MobManager.hpp"
|
||||||
@ -94,6 +95,7 @@ int main() {
|
|||||||
std::cout << "[INFO] Intializing Packet Managers..." << std::endl;
|
std::cout << "[INFO] Intializing Packet Managers..." << std::endl;
|
||||||
TableData::init();
|
TableData::init();
|
||||||
PlayerManager::init();
|
PlayerManager::init();
|
||||||
|
BuiltinCommands::init();
|
||||||
ChatManager::init();
|
ChatManager::init();
|
||||||
CustomCommands::init();
|
CustomCommands::init();
|
||||||
MobManager::init();
|
MobManager::init();
|
||||||
|
Loading…
Reference in New Issue
Block a user