//************************************ // FileName: D:\VisualStudioSource\dnf_project\src\Dispatch.cpp // FullName: D:\VisualStudioSource\dnf_project\src // Date: 2022/09/01 // By: Vance // Copyright (c) 2022. Vance All rights reserved //************************************ #include "dispatch.h" CDispatch::CDispatch() : last_move_map_tickcount(0) { } CDispatch::~CDispatch() { } ENUM_PACK_RET_TYPE CDispatch::UseEquipmentMoveItem(CUser* user, PacketBuf* pBuf) { if (user->get_state() != 3) { return PAK_IGNORE; } int v110 = CSecu_ProtectionField::Get()->Check(user, 38); if (v110) { user->SendCmdErrorPacket(84, v110); return PAK_IGNORE; } LOG(u8"UseEquipmentMoveItem :%s ", Utils::ToHexString((const unsigned char*)pBuf->get_buf_ptr(0), 40).c_str()); short equipment_pos = 0; int equipment_id = 0; short item_pos = 0; if ((unsigned __int8)pBuf->get_short(&equipment_pos) != 1 || (unsigned __int8)pBuf->get_int(&equipment_id) != 1 || (unsigned __int8)pBuf->get_short(&item_pos) != 1) { user->SendCmdErrorPacket(84, -1); return PAK_IGNORE; } //1 物品栏 2 时装 if (user->CheckItemLock(1, equipment_pos)) { user->SendCmdErrorPacket(84, 0xD5); return PAK_IGNORE; } CInventory* invenR = user->getCurCharacInvenR(); if (!invenR) { LOG(u8"user->getCurCharacInvenW : error \n"); return PAK_IGNORE; } Inven_Item* equipment_InvenRef = invenR->GetInvenRef(CInventory::INVENTORY_TYPE_ITEM, equipment_pos); if (!equipment_InvenRef) { LOG(u8"inven->GetInvenRef : error \n"); return PAK_IGNORE; } Inven_Item* item_avartar = invenR->GetInvenRef(CInventory::INVENTORY_TYPE_ITEM, item_pos); if (!item_avartar) { LOG(u8"inven->GetInvenRef : error \n"); return PAK_IGNORE; } if (equipment_InvenRef->isEmpty()) { LOG(u8"equipment_InvenRef->isEmpty"); return PAK_IGNORE; } if (equipment_InvenRef->getKey() != equipment_id) { LOG(u8"equipment_InvenRef->getKey() != equipment_id"); user->SendCmdErrorPacket(4, 0); return PAK_IGNORE; } if (item_avartar->isEmpty()) { LOG(u8"item_avartar->isEmpty"); return PAK_IGNORE; } int item_id = item_avartar->getKey(); CDataManager* DataManager = CDataManager::G_CDataManager(); if (!DataManager) { LOG(u8"G_CDataManager error"); return PAK_IGNORE; } CEquipItem* equipment_citem = (CEquipItem*)DataManager->find_item(equipment_id); CStackableItem* item_citem = (CStackableItem*)DataManager->find_item(item_id); LOG(u8"equipment_citem +12: %p" , *(int*)equipment_citem + 12 ); if (!equipment_citem || !item_citem) { LOG(u8"!equipment_citem || !item_citem"); return PAK_IGNORE; } LOG(u8"UseEquipmentMoveItem [ equipment_pos:%d equipment_id:%d item_pos:%d item_id:%d ]" , equipment_pos , equipment_id , item_pos , item_id ); //Data: equipment_citem->GetItemType=147418664 item_citem->is_stackable=1 item_citem->GetItemType=11 int equipment_Type = ((CEquipItem*)equipment_citem)->GetItemType(); int rarity = equipment_citem->get_rarity(); if (rarity != 4) { return PAK_OK; } LOG(u8"Data: equipment_citem->GetItemType=%d item_citem->is_stackable=%d item_citem->GetItemType=%d" , equipment_Type , item_citem->is_stackable() , item_citem->GetItemType() ); if (equipment_Type <= 9 || equipment_Type > 21 || equipment_Type == 11) { LOG(u8"equipment_Type <= 9 || equipment_Type > 21 || equipment_Type == 11"); user->SendCmdErrorPacket(84, 0xD5); return PAK_IGNORE; } if (item_citem->is_stackable() != true || item_citem->GetItemType() != ITEM_TYPE_CONSUMABLES) { LOG(u8"item_citem->is_stackable() != true || item_citem->GetItemType() != ITEM_TYPE_CONSUMABLES"); //没有镜像手机认证,无法使用该功能 user->SendCmdErrorPacket(205, 209); return PAK_IGNORE; } Inven_Item new_equipment_item = {}; invenR->GetInvenSlot(&new_equipment_item, CInventory::INVENTORY_TYPE_ITEM, equipment_pos); int v9 = 0; //返回给客户端的错误码 if (item_id == ITEM_ID_KUAJIESHI) { LOG(u8"user->CheckInTrade:%d", user->CheckInTrade()); if (user->CheckInTrade()) { v9 = 19; } if (!user->IsExistAccountCargo()) { v9 = 19; LOG(u8"user->IsExistAccountCargo :%d", user->IsExistAccountCargo()); } else { CAccountCargo* AccountCargo = user->GetAccountCargo(); LOG(u8"ins_item.IsTradeLimitAttachTypeItem :%d", new_equipment_item.IsTradeLimitAttachTypeItem()); LOG(u8"AccountCargo->CheckInsertCondition :%d", AccountCargo->CheckInsertCondition(&new_equipment_item)); int empty_slot = 0; if (AccountCargo->CheckSlotEmpty(empty_slot) != 1) { empty_slot = AccountCargo->GetEmptySlot(); if (empty_slot < 0) { v9 = 4; LOG("AccountCargo->CheckSlotEmpty :%d", empty_slot); return PAK_IGNORE; } } LOG(u8"empty_slot :%d", empty_slot); //inven->delete_item(1, emblem_inven_slot, 1, 8, 1); auto invenW = user->getCurCharacInvenW(); InterfacePacketBuf* packet_guard = (InterfacePacketBuf*)PacketGuard::NewPacketGuard(); LOG("%p", invenW); if (invenW->delete_item(CInventory::INVENTORY_TYPE_ITEM, equipment_pos, 1, 37, 1) && invenW->delete_item(CInventory::INVENTORY_TYPE_ITEM, item_pos, 1, 37, 1)) { int a9 = AccountCargo->InsertItem(&new_equipment_item, empty_slot); user->SendUpdateItemList(1, new_equipment_item.GetItemSpace(), equipment_pos); user->SendUpdateItemList(1, item_avartar->GetItemSpace(), item_pos); user->send_itemspace(12); packet_guard->put_header(1, 2000); packet_guard->put_int(1); packet_guard->finalize(1); user->Send((PacketGuard*)packet_guard); PacketGuard::DelPacketGuard((PacketGuard*)packet_guard); SendNoti(user, "已完成装备跨界"); return PAK_OK; } else { packet_guard->put_header(1, 2000); packet_guard->put_int(0); packet_guard->finalize(0); user->Send((PacketGuard*)packet_guard); PacketGuard::DelPacketGuard((PacketGuard*)packet_guard); SendNoti(user, "装备跨界失败"); } return PAK_IGNORE; } } /* 缓冲Call (2000) 密钥Call (装备位置,2) 密钥Call (装备代码,4) 密钥Call (物品位置,2) 发包Call () */ return PAK_OK; } ENUM_PACK_RET_TYPE CDispatch::Dispatcher_ModItemAttr_dispatch_sig(Dispatcher_ModItemAttr* dis_mod, CUser* user, PacketBuf* pBuf) { if (user->get_state() != 3 || !user->getCurCharacR()) { user->SendCmdErrorPacket(84, 0xD1u); return PAK_IGNORE; } short equipment_pos = 0; int equipment_id = 0; short item_pos = 0; if ((unsigned __int8)pBuf->get_short(&equipment_pos) != 1 || (unsigned __int8)pBuf->get_int(&equipment_id) != 1 || (unsigned __int8)pBuf->get_short(&item_pos) != 1) { user->SendCmdErrorPacket(84, -1); return PAK_IGNORE; } auto CurCharacInvenW = (CInventory*)user->getCurCharacInvenW(); Inven_Item equipment_inven = {}; CurCharacInvenW->GetInvenSlot(&equipment_inven, CInventory::INVENTORY_TYPE_ITEM, equipment_pos); if (equipment_inven.isEmpty() || equipment_inven.getKey() != equipment_id) { user->SendCmdErrorPacket(84, 4); return PAK_IGNORE; } CEquipItem* equipment_item = (CEquipItem*)CDataManager::G_CDataManager()->find_item(equipment_id); LOG("(*(int(**)(CItem*))(*(_DWORD*)equipment_item + 12)) :%p %p" , (*(int(**)(CItem*))(*(_DWORD*)equipment_item + 12)) , ((int(**)(CItem*))(*(_DWORD*)equipment_item + 12)) ); if (!equipment_item) { user->SendCmdErrorPacket(84, 4); return PAK_IGNORE; } int equipment_Type = equipment_item->GetItemType(); if (equipment_Type <= 9 || equipment_Type > 21 || equipment_Type == 11) { user->SendCmdErrorPacket(84, 19); return PAK_IGNORE; } Inven_Item item_inven = {}; CurCharacInvenW->GetInvenSlot(&item_inven, CInventory::INVENTORY_TYPE_ITEM, item_pos); if (item_inven.isEmpty()) { user->SendCmdErrorPacket(84, 17); return PAK_IGNORE; } if (user->CheckItemLock(1, equipment_pos)) { user->SendCmdErrorPacket(84, 0xD5u); return PAK_IGNORE; } if (item_inven.getKey() != ITEM_ID_YIJIRUHUN) { user->SendCmdErrorPacket(84, 17); return PAK_IGNORE; } int grade = equipment_item->get_grade(); //掉落等级 int rarity = equipment_item->get_rarity(); //稀有 int attach_type = equipment_item->GetAttachType(); auto add_info = item_inven.get_add_info(); if (equipment_item->GetAttachType() != 3) { user->SendCmdErrorPacket(84, 19); return PAK_IGNORE; } if (equipment_inven.package != 0) { user->SendCmdErrorPacket(84, 18); return PAK_IGNORE; } if (CurCharacInvenW->delete_item(CInventory::INVENTORY_TYPE_ITEM, item_pos, 1, 3, 1) != 1) { user->SendCmdErrorPacket(84, -3); return PAK_IGNORE; } equipment_inven.package = 1; CurCharacInvenW->update_item( CInventory::INVENTORY_TYPE_ITEM, equipment_pos, equipment_inven); dis_mod->_SendResult(user, 1, item_pos, equipment_pos); return PAK_IGNORE; } ENUM_PACK_RET_TYPE CDispatch::UseJewel_dispatch_sig(void* pDispatcher_UseJewel, CUser* user, PacketBuf* pBuf) { printf("getCurCharacName :%s \n", user->getCurCharacName().c_str()); printf("getCurCharacNo :%d \n", user->getCurCharacNo()); printf("get_buf_ptr :%p %p \n", pBuf->get_buf_ptr(0)); printf("get_len :%d \n", pBuf->get_len()); // printf("pBuf :%s \n", Util::ToHexString((const unsigned char*)pBuf->get_buf_ptr(0),40).c_str()); int state = user->get_state(); LOG("state :%d \n", state); //校验角色状态是否允许镶嵌 if (state != 3) return PAK_IGNORE; int isEnableAvatarSocketAction = user->isEnableAvatarSocketAction(); if (isEnableAvatarSocketAction) user->SendCmdErrorPacket(205, (unsigned char)isEnableAvatarSocketAction); //解析packet_buf short avartar_inven_slot = 0; //时装所在的背包槽 int avartar_item_id = 0; //时装item_id char emblem_cnt = 0; //本次镶嵌徽章数量 if ((unsigned __int8)pBuf->get_short(&avartar_inven_slot) != 1 || (unsigned __int8)pBuf->get_int(&avartar_item_id) != 1 || (unsigned __int8)pBuf->get_byte(&emblem_cnt) != 1) { user->SendCmdErrorPacket(205, -1); return PAK_IGNORE; } if (user->CheckItemLock(2, avartar_inven_slot)) { user->SendCmdErrorPacket(205, 213); return PAK_IGNORE; } //获取时装道具 CInventory* CurCharacInvenW = user->getCurCharacInvenW(); if (!CurCharacInvenW) { LOG("pUser->getCurCharacInvenW : error \n"); return PAK_IGNORE; } Inven_Item* avartar_inven_item = CurCharacInvenW->GetInvenRef(CInventory::INVENTORY_TYPE_AVARTAR, avartar_inven_slot); if (!avartar_inven_item) { LOG("inven->GetInvenRef : error \n"); return PAK_IGNORE; } //校验时装 数据是否合法 if (avartar_inven_item->isEmpty() || (avartar_inven_item->getKey() != avartar_item_id) || user->CheckItemLock(2, avartar_inven_slot)) { LOG("avartar->isEmpty() || avartar->getKey() || pUser->CheckItemLock() : error \n"); return PAK_IGNORE; } //获取时装插槽数据 auto avartar_add_info = avartar_inven_item->get_add_info(); auto inven_avartar_mgr = (WongWork::CAvatarItemMgr*)CurCharacInvenW->GetAvatarItemMgrW(); stAvatarEmblemInfo_t* JewelSocketData = (stAvatarEmblemInfo_t*)inven_avartar_mgr->getJewelSocketData(avartar_add_info); if (!JewelSocketData) { LOG("jewel_socket_data : error \n"); return PAK_IGNORE; } LOG("jewel_socket_data 1:%s \n", Utils::ToHexString((const unsigned char*)JewelSocketData, 30).c_str()); if (emblem_cnt <= 3) { std::map> emblems; for (int i = 0; i < emblem_cnt; i++) { //徽章所在的背包槽 short emblem_inven_slot = 0; pBuf->get_short(&emblem_inven_slot); //徽章item_id int emblem_item_id = 0; pBuf->get_int(&emblem_item_id); //该徽章镶嵌的时装插槽id char avartar_socket_slot = 0; pBuf->get_byte(&avartar_socket_slot); LOG("emblem_inven_slot :%d emblem_item_id :%d avartar_socket_slot :%d", emblem_inven_slot, emblem_item_id, avartar_socket_slot); //获取徽章道具 Inven_Item* emblem = CurCharacInvenW->GetInvenRef(CInventory::INVENTORY_TYPE_ITEM, emblem_inven_slot); //校验徽章及插槽数据是否合法 if (emblem->isEmpty() || (emblem->getKey() != emblem_item_id) || (avartar_socket_slot >= 3)) { LOG("emblem->isEmpty() || (emblem->getKey() : error \n"); user->SendCmdErrorPacket(205, 209); return PAK_IGNORE; } //校验徽章是否满足时装插槽颜色要求 //获取徽章pvf数据 CDataManager* DataManager = CDataManager::G_CDataManager(); if (!DataManager) { LOG("CDataManager::G_CDataManager() : error \n"); user->SendCmdErrorPacket(205, 209); return PAK_IGNORE; } CStackableItem* citem = (CStackableItem*)DataManager->find_item(emblem_item_id); if (!citem) { LOG("DataManager->find_item() : error \n"); user->SendCmdErrorPacket(205, 209); return PAK_IGNORE; } //校验徽章类型 if (!citem->is_stackable() || (citem->GetItemType() != 20)) { LOG("citem->is_stackable() || (citem->GetItemType() : error \n"); user->SendCmdErrorPacket(205, 209); return PAK_IGNORE; } //获取徽章支持的插槽 int emblem_socket_type = citem->getJewelTargetSocket(); //01 00 C4 25 26 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 //获取要镶嵌的时装插槽类型 sizeof(stAvatarEmblemInfo_t); int avartar_socket_type = JewelSocketData->EmblemSocketData[avartar_socket_slot].slot_type; LOG("emblem_socket_type :%d avartar_socket_type :%d", emblem_socket_type, avartar_socket_type); if (!(emblem_socket_type & avartar_socket_type)) { //插槽类型不匹配 LOG("emblem_socket_type & avartar_socket_type\n"); user->SendCmdErrorPacket(205, 209); return PAK_IGNORE; } LOG("avartar_socket_slot:%d emblem_inven_slot:%d emblem_item_id:%d\n", avartar_socket_slot, emblem_inven_slot, emblem_item_id); emblems[avartar_socket_slot] = std::make_pair(emblem_inven_slot, emblem_item_id); if (CurCharacInvenW->delete_item(CInventory::INVENTORY_TYPE_ITEM, emblem_inven_slot, 1, 8, 1)) { JewelSocketData->EmblemSocketData[avartar_socket_slot].slot_item_id = emblem_item_id; } } LOG("jewel_socket_data 2:%s \n", Utils::ToHexString((const unsigned char*)JewelSocketData, 30).c_str()); inven_avartar_mgr->setEmblemSocketData(avartar_add_info, JewelSocketData); //时装插槽数据存档 DB_UpdateAvatarJewelSlot::makeRequest(user->getCurCharacNo(), (unsigned int)avartar_add_info, (void*)JewelSocketData); //通知客户端时装数据已更新 user->SendUpdateItemList(1, 1, avartar_inven_slot); //回包给客户端 InterfacePacketBuf* packet_guard = (InterfacePacketBuf*)PacketGuard::NewPacketGuard(); packet_guard->put_header(1, 204); packet_guard->put_int(1); packet_guard->finalize(1); user->Send((PacketGuard*)packet_guard); PacketGuard::DelPacketGuard((PacketGuard*)packet_guard); SendNoti(user, "已完成徽章镶嵌"); return PAK_OK; } return PAK_IGNORE; } ENUM_PACK_RET_TYPE CDispatch::MoveMap_dispatch_sig(void* a1, CUser* user, PacketBuf* pBuf) { USER_DATA data; if (user_map.Find(user, &data)) { auto CurTickCount = CSystemTime::G_CSystemTime()->getCurTickCount(); if (CurTickCount >= last_move_map_tickcount) { if ((CurTickCount - last_move_map_tickcount) <= 1000) { data.abnormal_data_count++; } last_move_map_tickcount = CurTickCount; } user_map.Change(user, data); //判断异常次数是否大于等于3 if (data.abnormal_data_count >= 3) { return PAK_ERROR; } } return PAK_OK; } ENUM_PACK_RET_TYPE CDispatch::Inter_LoadEtc_dispatch_sig(void* a1, CUser* user, char* a3) { user->getCurCharacNo(); user->getCurCharacName(); user_map.Push(user, {}); return PAK_OK; } ENUM_PACK_RET_TYPE CDispatch::DisPatcher_ReturnToSelectCharacter_dispatch_sig(void* a1, CUser* user, char* a3) { user_map.Erase(user); return PAK_OK; } ENUM_PACK_RET_TYPE CDispatch::ProcessIPG_ResultOutput(CUser* user, int Goods_No, int item_id, int Cera_Type, InterfacePacketBuf* pbuf) { if (Cera_Type == 0) //0是点券 1是代币 { if (Goods_No >= CGameDataManager::Get()->get_cera_award_begin_id() && Goods_No <= CGameDataManager::Get()->get_cera_award_end_id()) { int cur_purchase_count = 1; AWARD_ITEM BonusItem; LOG("Size:%d", CGameDataManager::Get()->get_cera_award_item_map()->Size()); if (CGameDataManager::Get()->get_cera_award_item_map()->Find(cur_purchase_count, &BonusItem)) { if (user->getCurCharacR()) { if (BonusItem.item_id == 1) { WongWork::CCeraShop::G_CCeraShop()->_processCoin(user, BonusItem.item_num, 0); } else { auto item = CDataManager::G_CDataManager()->find_item(BonusItem.item_id); if (item) { //if (item->is_stackable() // && ((*(int(**)(CItem*))(*(_DWORD*)item + 12))(item) == 16 // GetItemType // || (*(int(**)(CItem*))(*(_DWORD*)item + 12))(item) == 34)) // GetItemType { int inserted = -1; Inven_Item v60 = {}; *(_DWORD*)((char*)&v60 + 2) = BonusItem.item_id; *(_DWORD*)((char*)&v60 + 7) = BonusItem.item_num; (*(void(**)(CItem*, Inven_Item*))(*(_DWORD*)item + 8))(item, &v60); auto CurCharacInvenW = user->getCurCharacInvenW(); inserted = CurCharacInvenW->insertItemIntoInventory(v60, 15, 1, 0); if (inserted == -1) { auto CurCharacNo = user->getCurCharacNo(); ((WongWork::CMailBoxHelper*)(user))->ReqDBSendNewMailCashShop(&v60, 0, CurCharacNo, 1, 0, 0); } else { user->SendUpdateItemList(1, 0, inserted); } } } } } pbuf->put_int(BonusItem.item_id); pbuf->put_int(BonusItem.item_num); std::vector code; for (int i = 0; i < 0x30; i++) { code.push_back(0x90); } //0817964F 0817967F CMem::WriteBytes((void*)0x0817964F, code.data(), code.size()); return; } } else if (Goods_No >= CGameDataManager::Get()->get_cera_award_package_begin_id() && Goods_No <= CGameDataManager::Get()->get_cera_award_package_end_id()) { int cur_purchase_count = 1; AWARD_ITEM BonusItem; LOG("Size:%d", CGameDataManager::Get()->get_cera_award_package_item_map()->Size()); if (CGameDataManager::Get()->get_cera_award_package_item_map()->Find(cur_purchase_count, &BonusItem)) { if (user->getCurCharacR()) { if (BonusItem.item_id == 1) { WongWork::CCeraShop::G_CCeraShop()->_processCoin(user, BonusItem.item_num, 0); } else { auto item = CDataManager::G_CDataManager()->find_item(BonusItem.item_id); if (item) { //if (item->is_stackable() // && ((*(int(**)(CItem*))(*(_DWORD*)item + 12))(item) == 16 // GetItemType // || (*(int(**)(CItem*))(*(_DWORD*)item + 12))(item) == 34)) // GetItemType { int inserted = -1; Inven_Item v60 = {}; *(_DWORD*)((char*)&v60 + 2) = BonusItem.item_id; *(_DWORD*)((char*)&v60 + 7) = BonusItem.item_num; (*(void(**)(CItem*, Inven_Item*))(*(_DWORD*)item + 8))(item, &v60); auto CurCharacInvenW = user->getCurCharacInvenW(); inserted = CurCharacInvenW->insertItemIntoInventory(v60, 15, 1, 0); if (inserted == -1) { auto CurCharacNo = user->getCurCharacNo(); ((WongWork::CMailBoxHelper*)(user))->ReqDBSendNewMailCashShop(&v60, 0, CurCharacNo, 1, 0, 0); } else { user->SendUpdateItemList(1, 0, inserted); } } } } } pbuf->put_int(BonusItem.item_id); pbuf->put_int(BonusItem.item_num); std::vector code; for (int i = 0; i < 0x30; i++) { code.push_back(0x90); } //0817964F 0817967F CMem::WriteBytes((void*)0x0817964F, code.data(), code.size()); return; } } } std::vector code = { 0x8B, 0x85, 0x04, 0xFF, 0xFF, 0xFF, 0x89, 0x44, 0x24, 0x04, 0x8D, 0x85, 0x14, 0xFF, 0xFF, 0xFF, 0x89, 0x04, 0x24, 0xE8, 0xD5, 0x22, 0xF5, 0xFF, 0x8B, 0x85, 0x00, 0xFF, 0xFF, 0xFF, 0x89, 0x44, 0x24, 0x04, 0x8D, 0x85, 0x14, 0xFF, 0xFF, 0xFF, 0x89, 0x04, 0x24, 0xE8, 0xBD, 0x22, 0xF5, 0xFF }; CMem::WriteBytes((void*)0x0817964F, code.data(), code.size()); return PAK_OK; } void CDispatch::SendMsg(CUser* user, int pack_id, int status, const std::string& str) { char out_str[0xff] = {}; memset(out_str, 0, sizeof(out_str)); DNFFLib::ConvertGBKtoUTF8((char*)str.c_str(), out_str); InterfacePacketBuf* packet_guard = (InterfacePacketBuf*)PacketGuard::NewPacketGuard(); packet_guard->put_header(1, pack_id); packet_guard->put_int(status); packet_guard->put_int(strlen(out_str)); packet_guard->put_str(out_str, strlen(out_str)); user->Send((PacketGuard*)packet_guard); PacketGuard::DelPacketGuard((PacketGuard*)packet_guard); } void CDispatch::SendNoti(CUser* user, const std::string& str, NOTI_PACKETMESSAGE_TYPE type) { char out_str[0xff] = {}; memset(out_str, 0, sizeof(out_str)); DNFFLib::ConvertGBKtoUTF8((char*)str.c_str(), out_str); user->SendNotiPacketMessage(out_str, type); }