Files
Sun1602/Server/GameServer/ComposeOrDecomposeImplement.cpp
2022-10-26 12:25:11 +08:00

638 lines
19 KiB
C++

////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// @file ComposeOrDecomposeImplement.cpp
/// @author hukim
/// @brief [2010/10/14 by hukim] This is created.\n
///
////////////////////////////////////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
#include ".\ComposeOrDecomposeImplement.h" // header
#include "ItemManager.h"
#include "SCItemSlotContainer.h"
#include "ImplementUtil.h"
#include "SocketSystem/SocketSystemImplement.h"
#include "CubeSystem/CubeSystemImplement.h"
#include "ItemTypeList.h"
#include "PacketStruct_DG.h"
#include <EquRecoveryParse.h>
////////////////////////////////////////////////////////////////////////////////////////////////////
// REGION : Constructor & Destructor
////////////////////////////////////////////////////////////////////////////////////////////////////
ComposeOrDecomposeImplement::ComposeOrDecomposeImplement()
{
}
ComposeOrDecomposeImplement::~ComposeOrDecomposeImplement()
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// REGION : Implement
////////////////////////////////////////////////////////////////////////////////////////////////////
namespace util
{
namespace internal
{
static bool CheckGetHistoryFilter(
const MSG_CG_ITEM_COMPOSE_OR_DECOMPOSE_SYN::RequestType request_type, const bool is_composition)
{
return (request_type == MSG_CG_ITEM_COMPOSE_OR_DECOMPOSE_SYN::kCubeRequest) &&
(is_composition == true);
// return true;
}
} // internal
} // util
////////////////////////////////////////////////////////////////////////////////////////////////////
// REGION : Public
////////////////////////////////////////////////////////////////////////////////////////////////////
#ifdef _20220329_ADD_EQU_RECOVERY
void ComposeOrDecomposeImplement::HandleEquRecovery(const MSG_BASE *const message, const MessageSize message_size) const
{
using namespace util::internal;
typedef MSG_CG_ITEM_EQU_RECOVERY_SYN RequestMessage;
const RequestMessage *request(NULL);
Player *requester(NULL);
if (CheckRequestMessage(message, message_size, request, requester) == false)
{
return;
}
struct ResponseSender
{
explicit ResponseSender(const RequestMessage &request, Player &requester) : request_(request), requester_(requester), result_code(0)
{
reward_items.Clear();
}
~ResponseSender()
{
MSG_CG_ITEM_CUBE_COMPOSE_OR_DECOMPOSE_ACK response;
response.is_composition_ = 1;
response.result_code_ = result_code;
response.added_inventory_items_ = reward_items;
requester_.SendPacket(&response, response.GetSize());
}
MSG_CG_ITEM_COMPOSE_OR_DECOMPOSE_ACK::ResultCode result_code;
INVENTORY_TOTAL_INFO reward_items;
private:
const RequestMessage &request_;
Player &requester_;
void operator=(const ResponseSender &) {}
};
ResponseSender response_sender(*request, *requester);
ItemManager *const item_manager = requester->GetItemManager();
SCItemSlotContainer *const inventory = item_manager->GetItemSlotContainer(SI_INVENTORY);
if (inventory->GetEmptySlotNum() == 0)
{
response_sender.result_code = RC::RC_ITEM_HAVENOTSPACE;
SUNLOG(eCRITICAL_LOG,
_T("|%s|库存没有获得奖励的空间.|角色名称 = %s|"),
__FUNCTION__,
requester->GetCharName());
return;
}
POSTYPE RewardPosArray[9] = {0};
ItemCompositionOrDecompositionReward reward;
if (reward.Init(requester, ItemCompositionOrDecompositionReward::kItemCodeReward) == false)
{
response_sender.result_code = RC::RC_ITEM_INVALID_VALUE;
SUNLOG(eCRITICAL_LOG,
_T("|%s|初始化奖励失败.|角色名称 = %s|"),
__FUNCTION__,
requester->GetCharName());
return;
}
for (int i = 0; i < 9; i++)
{
POSTYPE InvePos = request->InvePos[i];
if (InvePos != 0)
{
SCItemSlot &_item = static_cast<SCItemSlot &>(inventory->GetSlot(InvePos));
EquRecoveryInfoParser * const reParse = EquRecoveryInfoParser::Instance();
const EquRecovery * equRecovery = reParse->FindData(_item.GetItemCode());
RC::eITEM_RESULT item_result = RC::RC_ITEM_SUCCESS;
if(!_item.IsLocked() && !_item.IsBlocked()){
if (_item.CanExtractToEtheria(&item_result))
{
if(equRecovery != NULL){
RewardPosArray[i] = InvePos;
ItemCompositionOrDecompositionReward::ItemReward itemReward = ItemCompositionOrDecompositionReward::ItemReward();
itemReward.item_code = equRecovery->rewardCode;
itemReward.number_of_item = equRecovery->rewardCount;
reward.AddObtainItemReward(itemReward);
}
}
}
}
}
const RC::eITEM_RESULT cube_item_using_result = item_manager->UseItemByType(
eITEMTYPE_EQU_RECOVERY, SI_INVENTORY, request->CubdePos, true, __FUNCTION__);
int reward_log_type = ItemCompositionOrDecompositionReward::kDoNotUseLog;
const RC::eITEM_RESULT obtain_result =
reward.ObtainRewardToInventory(reward_log_type, response_sender.reward_items);
if (obtain_result != RC::RC_ITEM_SUCCESS)
{
response_sender.result_code = obtain_result;
SUNLOG(eCRITICAL_LOG,
_T("|%s|库存奖励失败.|失败代码 = %d, 角色名称 = %s|"),
__FUNCTION__,
obtain_result,
requester->GetCharName());
return;
}
if (cube_item_using_result != RC::RC_ITEM_SUCCESS)
{
response_sender.result_code = cube_item_using_result;
return;
}
response_sender.result_code = RC::RC_ITEM_EQU_RECOVERY_SUCCESS;
ItemCompositionOrDecompositionHistory history;
MSG_CG_ITEM_LOSE_ACK item_lose_ack;
for (int i = 0; i < 9; i++)
{
POSTYPE InvePos = RewardPosArray[i];
if (InvePos != 0)
{
INVEN_DELETE_TOTAL_INFO::SLOT_TYPE &lose_slot = item_lose_ack.m_ItemInfo.m_Slot[0]; //要刪除的pos 位置數組
lose_slot.m_Pos = InvePos;
lose_slot.m_Num = 1;
SCItemSlot &inven_item =
static_cast<SCItemSlot &>(inventory->GetSlot(InvePos));
/* if ( reward.IsExistObtainedToInventory())
{
ItemCompositionOrDecompositionHistory::UsedItem used_item;
used_item.is_material = true;
used_item.item_code = inven_item.GetItemCode();
used_item.number_of_item = 1;
used_item.ig_type = nsSlot::ItemTypeChanger::GetKindOfItemType(inven_item);
history.AddUsedItem(used_item);
}*/
GAMELOG->LogItem(
ITEM_EQU_RECOVERY,
requester,
&inven_item,
0,
1);
inventory->DeleteSlot(inven_item.GetPos(), NULL);
item_lose_ack.m_ItemInfo.m_Count = 1;
requester->SendPacket(&item_lose_ack, item_lose_ack.GetSize());
}
}
}
#endif
void ComposeOrDecomposeImplement::HandleComposeOrDecompose(
const MSG_BASE *const message, const MessageSize message_size) const
{
using namespace util::internal;
typedef MSG_CG_ITEM_COMPOSE_OR_DECOMPOSE_SYN RequestMessage;
const RequestMessage *request(NULL);
Player *requester(NULL);
if (CheckRequestMessage(message, message_size, request, requester) == false)
{
return;
}
switch (request->request_type_)
{
case RequestMessage::kZardRequest:
case RequestMessage::kCubeRequest:
break;
default:
SUNLOG(eCRITICAL_LOG,
_T("|%s|请求合成或分解不支持类型的项目.|请求类型 = %d, 角色名称 = %s|"),
__FUNCTION__,
request->request_type_,
requester->GetCharName());
return;
}
struct ResponseSender
{
explicit ResponseSender(const RequestMessage &request, Player &requester) : request_(request), requester_(requester), result_code(0)
{
reward_items.Clear();
}
~ResponseSender()
{
switch (request_.request_type_)
{
//_NA_000251_20100727_SOCKET_SYSTEM
case RequestMessage::kZardRequest:
{
MSG_CG_ITEM_ZARD_COMPOSE_ACK response;
response.is_composition_ = request_.is_composition_;
response.result_code_ = result_code;
response.added_inventory_items_ = reward_items;
requester_.SendPacket(&response, response.GetSize());
}
break;
#ifdef _NA_002253_20100811_CUBE_SYSTEM
case RequestMessage::kCubeRequest:
{
MSG_CG_ITEM_CUBE_COMPOSE_OR_DECOMPOSE_ACK response;
response.is_composition_ = request_.is_composition_;
response.result_code_ = result_code;
response.added_inventory_items_ = reward_items;
requester_.SendPacket(&response, response.GetSize());
}
break;
#endif // _NA_002253_20100811_CUBE_SYSTEM
}
}
MSG_CG_ITEM_COMPOSE_OR_DECOMPOSE_ACK::ResultCode result_code;
INVENTORY_TOTAL_INFO reward_items;
private:
const RequestMessage &request_;
Player &requester_;
void operator=(const ResponseSender &) {}
};
ResponseSender response_sender(*request, *requester);
if (CheckRequesterState(requester, __FUNCTION__, response_sender.result_code) == false)
{
return;
}
if (request->material_list_size_ < 1 ||
request->material_list_size_ > _countof(request->material_list_))
{
response_sender.result_code = RC::RC_ITEM_INVALID_VALUE;
SUNLOG(eCRITICAL_LOG,
_T("|%s|合成或分解的材料数量不正确.|材料数量 = %d, 角色名称 = %s|"),
__FUNCTION__,
request->material_list_size_,
requester->GetCharName());
return;
}
ItemManager *const item_manager = requester->GetItemManager();
SCItemSlotContainer *const inventory = item_manager->GetItemSlotContainer(SI_INVENTORY);
if (inventory->GetEmptySlotNum() == 0)
{
response_sender.result_code = RC::RC_ITEM_HAVENOTSPACE;
SUNLOG(eCRITICAL_LOG,
_T("|%s|库存没有获得奖励的空间.|角色名称 = %s|"),
__FUNCTION__,
requester->GetCharName());
return;
}
util::BitSetOperation<MAX_INVENTORY_SLOT_NUM> duplication_checker;
duplication_checker.ClearAll();
for (RequestMessage::MaterialListSize i = 0; i < request->material_list_size_; ++i)
{
const POSTYPE material_position = ((request->material_list_)[i]).inventory_position_;
if (duplication_checker.IsSet(material_position))
{
response_sender.result_code = RC::RC_ITEM_INVALID_VALUE;
SUNLOG(eCRITICAL_LOG,
_T("|%s|库存的材料位置重复.|材料位置 = %d, 角色名称 = %s|"),
__FUNCTION__,
material_position,
requester->GetCharName());
return;
}
if (item_manager->ValidPos(SI_INVENTORY, material_position) == false)
{
response_sender.result_code = RC::RC_ITEM_INVALID_VALUE;
SUNLOG(eCRITICAL_LOG,
_T("|%s|库存的材料位置不正确.|材料位置 = %d, 角色名称 = %s|"),
__FUNCTION__,
material_position,
requester->GetCharName());
return;
}
duplication_checker.Set(material_position);
}
ItemCompositionOrDecompositionReward reward;
if (reward.Init(requester, ItemCompositionOrDecompositionReward::kItemCodeReward) == false)
{
response_sender.result_code = RC::RC_ITEM_INVALID_VALUE;
SUNLOG(eCRITICAL_LOG,
_T("|%s|初始化奖励失败.|角色名称 = %s|"),
__FUNCTION__,
requester->GetCharName());
return;
}
int reward_log_type = ItemCompositionOrDecompositionReward::kDoNotUseLog;
switch (request->request_type_)
{
//_NA_000251_20100727_SOCKET_SYSTEM
case MSG_CG_ITEM_COMPOSE_OR_DECOMPOSE_SYN::kZardRequest:
{
SocketSystemImplement socket_system_impl;
response_sender.result_code =
socket_system_impl.ZardCompose(*request, *requester, reward);
if (response_sender.result_code != RC::RC_ITEM_SUCCESS_TO_COMPOSE_ZARD)
{
return;
}
reward_log_type = ITEM_ZARD_COMPOSE_REWARD;
}
break;
#ifdef _NA_002253_20100811_CUBE_SYSTEM
case MSG_CG_ITEM_COMPOSE_OR_DECOMPOSE_SYN::kCubeRequest:
{
CubeSystemImplement cube_system_impl;
response_sender.result_code =
cube_system_impl.CubeComposeOrDecompose(*request, *requester, reward);
if (request->is_composition_)
{
if (response_sender.result_code != RC::RC_ITEM_SUCCESS_TO_COMPOSE_CUBE)
{
return;
}
reward_log_type = ITEM_CUBE_COMPOSE_REWARD;
}
else
{
if (response_sender.result_code != RC::RC_ITEM_SUCCESS_TO_DECOMPOSE_CUBE)
{
return;
}
reward_log_type = ITEM_CUBE_DECOMPOSE_REWARD;
}
}
break;
#endif // _NA_002253_20100811_CUBE_SYSTEM
}
const RC::eITEM_RESULT obtain_result =
reward.ObtainRewardToInventory(reward_log_type, response_sender.reward_items);
if (obtain_result != RC::RC_ITEM_SUCCESS)
{
response_sender.result_code = obtain_result;
SUNLOG(eCRITICAL_LOG,
_T("|%s|库存奖励失败.|失败代码 = %d, 角色名称 = %s|"),
__FUNCTION__,
obtain_result,
requester->GetCharName());
return;
}
int material_log_type = ItemCompositionOrDecompositionReward::kDoNotUseLog;
switch (reward_log_type)
{
case ITEM_ZARD_COMPOSE_REWARD:
material_log_type = ITEM_ZARD_COMPOSE_MATERIAL;
break;
case ITEM_CUBE_COMPOSE_REWARD:
material_log_type = ITEM_CUBE_COMPOSE_MATERIAL;
break;
case ITEM_CUBE_DECOMPOSE_REWARD:
material_log_type = ITEM_CUBE_DECOMPOSE_MATERIAL;
break;
}
const bool use_history = CheckGetHistoryFilter(request->request_type_, request->is_composition_);
ItemCompositionOrDecompositionHistory history;
MSG_CG_ITEM_LOSE_ACK item_lose_ack;
for (RequestMessage::MaterialListSize i = 0; i < request->material_list_size_; ++i)
{
const MSG_CG_ITEM_COMPOSE_OR_DECOMPOSE_SYN::MaterialInfo &material =
(request->material_list_)[i];
INVEN_DELETE_TOTAL_INFO::SLOT_TYPE &lose_slot = item_lose_ack.m_ItemInfo.m_Slot[i];
lose_slot.m_Pos = material.inventory_position_;
lose_slot.m_Num = material.selected_number_;
SCItemSlot &inven_item =
static_cast<SCItemSlot &>(inventory->GetSlot(material.inventory_position_));
if (use_history && reward.IsExistObtainedToInventory())
{
ItemCompositionOrDecompositionHistory::UsedItem used_item;
used_item.is_material = true;
used_item.item_code = inven_item.GetItemCode();
used_item.number_of_item = material.selected_number_;
used_item.ig_type = nsSlot::ItemTypeChanger::GetKindOfItemType(inven_item);
history.AddUsedItem(used_item);
}
if (material.selected_number_ < inven_item.GetNum())
{
GAMELOG->LogItem(
material_log_type,
requester,
&inven_item,
0,
material.selected_number_,
NULL,
NULL,
_T("U"));
inventory->UpdateSlot(inven_item.GetPos(), -material.selected_number_);
}
else
{
GAMELOG->LogItem(
material_log_type,
requester,
&inven_item,
0,
material.selected_number_);
inventory->DeleteSlot(inven_item.GetPos(), NULL);
}
}
item_lose_ack.m_ItemInfo.m_Count = request->material_list_size_;
requester->SendPacket(&item_lose_ack, item_lose_ack.GetSize());
if (use_history && reward.IsExistObtainedToInventory())
{
history.request_type = request->request_type_;
history.is_composition = request->is_composition_;
util::GetDateTime_YYYYMMDDHHMMSS(history.history_date_time);
reward.AddToHistory(history);
MSG_DG_OTHER_INSERT_COMPOSITION_OR_DECOMPOSITION_HISTORY_CMD insert_history_cmd;
insert_history_cmd.new_composition_or_decomposition_history = history;
requester->SendToGameDBPServer(&insert_history_cmd, insert_history_cmd.GetSize());
}
}
void ComposeOrDecomposeImplement::HandleGetHistories(
const MSG_BASE *const message, const MessageSize message_size) const
{
const MSG_CG_ITEM_GET_COMPOSITION_OR_DECOMPOSITION_HISTORIES_SYN *get_histories_syn(NULL);
Player *requester(NULL);
if (!util::internal::CheckRequestMessage(message, message_size, get_histories_syn, requester))
{
return;
}
MSG_CG_ITEM_GET_COMPOSITION_OR_DECOMPOSITION_HISTORIES_ACK::ResultCode result_code = 0;
if (!util::internal::CheckRequesterState(requester, __FUNCTION__, result_code))
{
return;
}
if (!util::internal::CheckGetHistoryFilter(
get_histories_syn->request_type, get_histories_syn->is_composition))
{
MSG_CG_ITEM_GET_COMPOSITION_OR_DECOMPOSITION_HISTORIES_ACK response;
response.Init();
response.result_code = RC::RC_ITEM_FAILED_TO_GET_COMPOSITION_OR_DECOMPOSITION_HISTORIES;
requester->SendPacket(&response, response.GetSize());
SUNLOG(eCRITICAL_LOG,
_T("|%s|请求合成或分解不支持类型的项目.|请求类型 = %u, 合成分解与否 = %u, 角色名称 = %s|"),
__FUNCTION__,
get_histories_syn->request_type,
(get_histories_syn->is_composition ? 1 : 0),
requester->GetCharName());
return;
}
#ifdef _CN_000000_20130729_COMPOSE_OR_DECOMPOSE_HISTORY_BLOCK
#else
MSG_DG_OTHER_SELECT_COMPOSITION_OR_DECOMPOSITION_HISTORIES_SYN select_histories_syn;
{
select_histories_syn.Init();
select_histories_syn.request_type = get_histories_syn->request_type;
select_histories_syn.is_composition = get_histories_syn->is_composition;
}
requester->SendToGameDBPServer(&select_histories_syn, select_histories_syn.GetSize());
#endif // _CN_000000_20130729_COMPOSE_OR_DECOMPOSE_HISTORY_BLOCK
}
void ComposeOrDecomposeImplement::HandleGetHistoriesResponseFromDBP(
const MSG_BASE *const message, const MessageSize message_size) const
{
const MSG_DG_OTHER_SELECT_COMPOSITION_OR_DECOMPOSITION_HISTORIES_ACK *dbp_ack(NULL);
Player *requester(NULL);
if (!util::internal::CheckRequestMessage(
message, message_size, dbp_ack, requester))
{
return;
}
MSG_CG_ITEM_GET_COMPOSITION_OR_DECOMPOSITION_HISTORIES_ACK::ResultCode result_code = 0;
if (!util::internal::CheckRequesterState(requester, __FUNCTION__, result_code))
{
return;
}
MSG_CG_ITEM_GET_COMPOSITION_OR_DECOMPOSITION_HISTORIES_ACK response;
{
response.Init();
response.result_code = dbp_ack->result_code;
if (response.result_code ==
RC::RC_ITEM_SUCCESS_TO_GET_COMPOSITION_OR_DECOMPOSITION_HISTORIES)
{
if (dbp_ack->history_list_size > 0)
{
response.history_list_size = dbp_ack->history_list_size;
enum
{
kMaxResponseHistoryListSize = _countof(response.history_list)
};
if (response.history_list_size > kMaxResponseHistoryListSize)
{
response.history_list_size = kMaxResponseHistoryListSize;
}
BOOST_STATIC_ASSERT(sizeof(dbp_ack->history_list[0]) == sizeof(response.history_list[0]));
BOOST_STATIC_ASSERT(sizeof(dbp_ack->history_list) == sizeof(response.history_list));
::CopyMemory(
response.history_list,
dbp_ack->history_list,
sizeof(dbp_ack->history_list[0]) * dbp_ack->history_list_size);
}
}
}
requester->SendPacket(&response, response.GetSize());
}
void ComposeOrDecomposeImplement::HandleModifyHistories(
const MSG_BASE *const message, const MessageSize message_size) const
{
typedef MSG_CG_ITEM_MODIFY_COMPOSITION_OR_DECOMPOSITION_HISTORIES_CMD ModifyHistoriesCmd;
const ModifyHistoriesCmd *modify_histories_cmd(NULL);
Player *requester(NULL);
if (!util::internal::CheckRequestMessage(message, message_size, modify_histories_cmd, requester))
{
return;
}
int result_code = 0;
if (!util::internal::CheckRequesterState(requester, __FUNCTION__, result_code))
{
return;
}
MSG_DG_OTHER_UPDATE_COMPOSITION_OR_DECOMPOSITION_HISTORIES_CMD update_histories_cmd;
{
update_histories_cmd.Init();
ModifyHistoriesCmd::ConditionListSize received_condition_list_size =
modify_histories_cmd->condition_list_size;
enum
{
kMaxUpdateConditionListSize = _countof(update_histories_cmd.modify_condition_list)
};
if (received_condition_list_size > kMaxUpdateConditionListSize)
{
received_condition_list_size = kMaxUpdateConditionListSize;
}
for (ModifyHistoriesCmd::ConditionListSize i = 0; i < received_condition_list_size; ++i)
{
const ModifyHistoriesCmd::ModifyCondition &received_condition =
modify_histories_cmd->modify_condition_list[i];
if (received_condition.history_id > 0)
{
update_histories_cmd.modify_condition_list[i] = received_condition;
++update_histories_cmd.condition_list_size;
}
}
if (update_histories_cmd.condition_list_size < 1)
{
SUNLOG(eCRITICAL_LOG,
_T("|%s|内容修改条件无效.|角色名称 = %s|"),
__FUNCTION__,
requester->GetCharName());
return;
}
}
requester->SendToGameDBPServer(&update_histories_cmd, update_histories_cmd.GetSize());
}