Implemented crates (dropping and opening).

Also fixed a bug in vaildOutVarPacket().
This commit is contained in:
dongresource 2020-08-28 18:25:03 +02:00
parent 67d899efe6
commit 4df812f996
4 changed files with 107 additions and 13 deletions

View File

@ -82,7 +82,7 @@ inline bool validOutVarPacket(size_t base, int32_t npayloads, size_t plsize) {
size_t trailing = npayloads * plsize; size_t trailing = npayloads * plsize;
// does it fit in a packet? // does it fit in a packet?
if (base + trailing <= CN_PACKET_BUFFER_SIZE) if (base + trailing > CN_PACKET_BUFFER_SIZE)
return false; return false;
// everything is a-ok! // everything is a-ok!

View File

@ -1,8 +1,9 @@
#include "CombatManager.hpp" #include "CombatManager.hpp"
#include "PlayerManager.hpp" #include "PlayerManager.hpp"
#include "NPCManager.hpp" #include "NPCManager.hpp"
#include "ItemManager.hpp"
#include <cstdio> #include <assert.h>
void CombatManager::init() { void CombatManager::init() {
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_ATTACK_NPCs, pcAttackNpcs); REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_ATTACK_NPCs, pcAttackNpcs);
@ -28,7 +29,7 @@ void CombatManager::pcAttackNpcs(CNSocket *sock, CNPacketData *data) {
* both incoming and outgoing variable-length packets must be validated. * both incoming and outgoing variable-length packets must be validated.
*/ */
if (!validOutVarPacket(sizeof(sP_FE2CL_PC_ATTACK_NPCs_SUCC), pkt->iNPCCnt, sizeof(sAttackResult))) { if (!validOutVarPacket(sizeof(sP_FE2CL_PC_ATTACK_NPCs_SUCC), pkt->iNPCCnt, sizeof(sAttackResult))) {
std::cout << "[WARN] bad sP_CL2FE_REQ_PC_ATTACK_NPCs packet size\n"; std::cout << "[WARN] bad sP_FE2CL_PC_ATTACK_NPCs_SUCC packet size\n";
return; return;
} }
@ -44,8 +45,6 @@ void CombatManager::pcAttackNpcs(CNSocket *sock, CNPacketData *data) {
resp->iNPCCnt = pkt->iNPCCnt; resp->iNPCCnt = pkt->iNPCCnt;
for (int i = 0; i < pkt->iNPCCnt; i++) { for (int i = 0; i < pkt->iNPCCnt; i++) {
std::cout << pktdata[i] << std::endl;
if (NPCManager::NPCs.find(pktdata[i]) == NPCManager::NPCs.end()) { if (NPCManager::NPCs.find(pktdata[i]) == NPCManager::NPCs.end()) {
// not sure how to best handle this // not sure how to best handle this
std::cout << "[WARN] pcAttackNpcs: mob ID not found" << std::endl; std::cout << "[WARN] pcAttackNpcs: mob ID not found" << std::endl;
@ -72,18 +71,44 @@ void CombatManager::combatEnd(CNSocket *sock, CNPacketData *data) {} // stub
void CombatManager::dotDamageOnOff(CNSocket *sock, CNPacketData *data) {} // stub void CombatManager::dotDamageOnOff(CNSocket *sock, CNPacketData *data) {} // stub
void CombatManager::giveReward(CNSocket *sock) { void CombatManager::giveReward(CNSocket *sock) {
// reward testing
INITSTRUCT(sP_FE2CL_REP_REWARD_ITEM, reward);
Player *plr = PlayerManager::getPlayer(sock); Player *plr = PlayerManager::getPlayer(sock);
const size_t resplen = sizeof(sP_FE2CL_REP_REWARD_ITEM) + sizeof(sItemReward);
assert(resplen < CN_PACKET_BUFFER_SIZE);
// we know it's only one trailing struct, so we can skip full validation
uint8_t respbuf[resplen]; // not a variable length array, don't worry
sP_FE2CL_REP_REWARD_ITEM *reward = (sP_FE2CL_REP_REWARD_ITEM *)respbuf;
sItemReward *item = (sItemReward *)(respbuf + sizeof(sP_FE2CL_REP_REWARD_ITEM));
// don't forget to zero the buffer!
memset(respbuf, 0, resplen);
// update player // update player
plr->money += 50; plr->money += 50;
plr->fusionmatter += 70; plr->fusionmatter += 70;
reward.m_iCandy = plr->money; // simple rewards
reward.m_iFusionMatter = plr->fusionmatter; reward->m_iCandy = plr->money;
reward.iFatigue = 100; // prevents warning message reward->m_iFusionMatter = plr->fusionmatter;
reward.iFatigue_Level = 1; reward->iFatigue = 100; // prevents warning message
reward->iFatigue_Level = 1;
reward->iItemCnt = 1; // remember to update resplen if you change this
sock->sendPacket((void*)&reward, P_FE2CL_REP_REWARD_ITEM, sizeof(sP_FE2CL_REP_REWARD_ITEM)); int slot = ItemManager::findFreeSlot(plr);
if (slot == -1) {
// no room for an item, but you still get FM and taros
sock->sendPacket((void*)respbuf, P_FE2CL_REP_REWARD_ITEM, sizeof(sP_FE2CL_REP_REWARD_ITEM));
} else {
// item reward
item->sItem.iType = 9;
item->sItem.iID = 1;
item->iSlotNum = slot;
item->eIL = 1; // Inventory Location. 1 means player inventory.
// update player
plr->Inven[slot] = item->sItem;
sock->sendPacket((void*)respbuf, P_FE2CL_REP_REWARD_ITEM, resplen);
}
} }

View File

@ -4,6 +4,9 @@
#include "PlayerManager.hpp" #include "PlayerManager.hpp"
#include "Player.hpp" #include "Player.hpp"
#include <string.h> // for memset() and memcmp()
#include <assert.h>
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);
@ -18,6 +21,7 @@ void ItemManager::init() {
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_TRADE_ITEM_UNREGISTER, itemTradeUnregisterItemHandler); REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_TRADE_ITEM_UNREGISTER, itemTradeUnregisterItemHandler);
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_TRADE_CASH_REGISTER, itemTradeRegisterCashHandler); REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_TRADE_CASH_REGISTER, itemTradeRegisterCashHandler);
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_TRADE_EMOTES_CHAT, itemTradeChatHandler); REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_TRADE_EMOTES_CHAT, itemTradeChatHandler);
REGISTER_SHARD_PACKET(P_CL2FE_REQ_ITEM_CHEST_OPEN, chestOpenHandler);
} }
void ItemManager::itemMoveHandler(CNSocket* sock, CNPacketData* data) { void ItemManager::itemMoveHandler(CNSocket* sock, CNPacketData* data) {
@ -665,3 +669,63 @@ void ItemManager::itemTradeChatHandler(CNSocket* sock, CNPacketData* data) {
sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_TRADE_EMOTES_CHAT, sizeof(sP_FE2CL_REP_PC_TRADE_EMOTES_CHAT)); sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_TRADE_EMOTES_CHAT, sizeof(sP_FE2CL_REP_PC_TRADE_EMOTES_CHAT));
otherSock->sendPacket((void*)&resp, P_FE2CL_REP_PC_TRADE_EMOTES_CHAT, sizeof(sP_FE2CL_REP_PC_TRADE_EMOTES_CHAT)); otherSock->sendPacket((void*)&resp, P_FE2CL_REP_PC_TRADE_EMOTES_CHAT, sizeof(sP_FE2CL_REP_PC_TRADE_EMOTES_CHAT));
} }
void ItemManager::chestOpenHandler(CNSocket *sock, CNPacketData *data) {
if (data->size != sizeof(sP_CL2FE_REQ_ITEM_CHEST_OPEN))
return; // ignore the malformed packet
sP_CL2FE_REQ_ITEM_CHEST_OPEN *pkt = (sP_CL2FE_REQ_ITEM_CHEST_OPEN *)data->buf;
Player *plr = PlayerManager::getPlayer(sock);
// item giving packet
const size_t resplen = sizeof(sP_FE2CL_REP_REWARD_ITEM) + sizeof(sItemReward);
assert(resplen < CN_PACKET_BUFFER_SIZE);
// we know it's only one trailing struct, so we can skip full validation
uint8_t respbuf[resplen]; // not a variable length array, don't worry
sP_FE2CL_REP_REWARD_ITEM *reward = (sP_FE2CL_REP_REWARD_ITEM *)respbuf;
sItemReward *item = (sItemReward *)(respbuf + sizeof(sP_FE2CL_REP_REWARD_ITEM));
// don't forget to zero the buffer!
memset(respbuf, 0, resplen);
// simple rewards
reward->iFatigue = 100; // prevents warning message
reward->iFatigue_Level = 1;
reward->iItemCnt = 1; // remember to update resplen if you change this
// item reward
item->sItem.iType = 0;
item->sItem.iID = 96;
item->iSlotNum = pkt->iSlotNum;
item->eIL = pkt->eIL;
// update player
plr->Inven[pkt->iSlotNum] = item->sItem;
// transmit item
sock->sendPacket((void*)respbuf, P_FE2CL_REP_REWARD_ITEM, resplen);
// chest opening acknowledgement packet
INITSTRUCT(sP_FE2CL_REP_ITEM_CHEST_OPEN_SUCC, resp);
resp.iSlotNum = pkt->iSlotNum;
std::cout << "opening chest..." << std::endl;
sock->sendPacket((void*)&resp, P_FE2CL_REP_ITEM_CHEST_OPEN_SUCC, sizeof(sP_FE2CL_REP_ITEM_CHEST_OPEN_SUCC));
}
// TODO: use this in cleaned up ItemManager
int ItemManager::findFreeSlot(Player *plr) {
int i;
sItemBase free;
memset((void*)&free, 0, sizeof(sItemBase));
for (i = 0; i < AINVEN_COUNT; i++)
if (memcmp((void*)&plr->Inven[i], (void*)&free, sizeof(sItemBase)) == 0)
return i;
// not found
return -1;
}

View File

@ -1,9 +1,11 @@
#pragma once #pragma once
#include "CNShardServer.hpp" #include "CNShardServer.hpp"
#include "Player.hpp"
namespace ItemManager { namespace ItemManager {
void init(); void init();
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 itemGMGiveHandler(CNSocket* sock, CNPacketData* data);
@ -17,4 +19,7 @@ namespace ItemManager {
void itemTradeUnregisterItemHandler(CNSocket* sock, CNPacketData* data); void itemTradeUnregisterItemHandler(CNSocket* sock, CNPacketData* data);
void itemTradeRegisterCashHandler(CNSocket* sock, CNPacketData* data); void itemTradeRegisterCashHandler(CNSocket* sock, CNPacketData* data);
void itemTradeChatHandler(CNSocket* sock, CNPacketData* data); void itemTradeChatHandler(CNSocket* sock, CNPacketData* data);
void chestOpenHandler(CNSocket* sock, CNPacketData* data);
int findFreeSlot(Player *plr);
} }