Initial commit

This commit is contained in:
Hash Borgir
2024-04-16 21:45:38 -06:00
commit 3159020c38
533 changed files with 135446 additions and 0 deletions

View File

@@ -0,0 +1,228 @@
#include <d2tweaks/server/server.h>
#include <Windows.h>
#include <spdlog/spdlog.h>
#include <d2tweaks/common/protocol.h>
#include <diablo2/d2game.h>
#include <diablo2/d2net.h>
#include <diablo2/structures/game.h>
#include <diablo2/structures/unit.h>
#include <diablo2/structures/net_client.h>
#include <d2tweaks/common/common.h>
#include <d2tweaks/server/modules/server_module.h>
#include <common/hooking.h>
#include <D2Template.h>
static int32_t(__fastcall* g_get_incoming_packet_info_original)(d2_tweaks::common::packet_header* data, unsigned int dataSize, size_t* packetSizeOut, size_t* someOffset, int* packetGroup, int32_t* a6, int a7, int a8);
static int32_t(__fastcall* g_handle_packet_original)(diablo2::structures::game* game, diablo2::structures::unit* player, d2_tweaks::common::packet_header* data, size_t size);
static int32_t(__fastcall* g_net_tick_original)(diablo2::structures::game*, diablo2::structures::unit*, int32_t, int32_t);
//returns some kind of processing type (i.e. resultGroup == 0x04 means drop packet)
static int32_t __fastcall get_incoming_packet_info(d2_tweaks::common::packet_header* data, unsigned int dataSize, size_t* packetSizeOut, size_t* someOffset, int* packetGroup, int32_t* a6, int a7, int a8) {
static d2_tweaks::common::packet_header dummy;
static auto& instance = singleton<d2_tweaks::common::common>::instance();
const auto resultGroup = g_get_incoming_packet_info_original(data, dataSize, packetSizeOut, someOffset, packetGroup, a6, a7, a8);
if (data->d2_packet_type == dummy.d2_packet_type && resultGroup == 0x04) { //0x04 - drop packet
size_t size;
if (!instance.get_packet_size_cs(data, size))
return resultGroup;
*packetSizeOut = size;
*packetGroup = 1;
*a6 = 100;
return 2;
}
return resultGroup;
}
static int32_t __fastcall handle_packet(diablo2::structures::game* game, diablo2::structures::unit* player, d2_tweaks::common::packet_header* data, size_t size) {
static d2_tweaks::common::packet_header dummy;
static auto& instance = singleton<d2_tweaks::server::server>::instance();
if (data->d2_packet_type == dummy.d2_packet_type) {
if (!instance.handle_packet(game, player, data))
return g_handle_packet_original(game, player, data, size);
return 1;
}
return g_handle_packet_original(game, player, data, size);
}
d2_tweaks::server::server::server(token) {
m_module_id_counter = 0;
m_tick_handler_id_counter = 0;
}
static int32_t g_ebp_send_to_client;
void __fastcall hook_sc_packet_before_sent(uint32_t* client_strc, d2_tweaks::common::packet_header* packet, size_t size) {
#ifndef NDEBUG
__asm {
push [ebp + 0x30];
pop [g_ebp_send_to_client];
}
if (size == -1)
return;
spdlog::error("[d2game SEND] Packet {} Message {} Size {} CallFrom {}", (void*)packet->d2_packet_type, (void*)packet->message_type, size, (void*)g_ebp_send_to_client);
#endif
return;
}
__declspec (naked) void hook_sc_packet_before_sent_wrapper() {
__asm {
pushad;
pushfd;
push [esp+0x28]
call [hook_sc_packet_before_sent]
popfd;
popad;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
push ecx
push ebp
push esi
mov esi, ecx
}
RET_TO_RVA(DLLBASE_D2GAME, 0xC715);
}
// d2game:$0xC710
static const DLLPatchStrc gpt_hook_sc_packet_before_sent[] =
{
{D2DLL_D2GAME, 0xC710 + 0, PATCH_JMP, FALSE, 0x1},
{D2DLL_D2GAME, 0xC710 + 1, (DWORD)hook_sc_packet_before_sent_wrapper, TRUE, 0x0},
{D2DLL_INVALID}
};
void d2_tweaks::server::server::init() {
hooking::hook(reinterpret_cast<void*>(diablo2::d2_game::get_base() + 0x59320), ::handle_packet, &g_handle_packet_original);
hooking::hook(reinterpret_cast<void*>(diablo2::d2_game::get_base() + 0x50F80), net_tick, &g_net_tick_original);
hooking::hook(reinterpret_cast<void*>(diablo2::d2_net::get_base() + 0x1FE0), get_incoming_packet_info, &g_get_incoming_packet_info_original);
//D2TEMPLATE_ApplyPatch(gpt_hook_sc_packet_before_sent);
//disable outgoing packet type checks
DWORD oldProtect;
if (VirtualProtect(diablo2::d2_net::get_base() + 0x18B2, 0x02, PAGE_EXECUTE_READWRITE, &oldProtect))
*reinterpret_cast<uint16_t*>(diablo2::d2_net::get_base() + 0x18B2) = 0xBC3C;
if (VirtualProtect(diablo2::d2_net::get_base() + 0x18D0, 0x02, PAGE_EXECUTE_READWRITE, &oldProtect))
*reinterpret_cast<uint16_t*>(diablo2::d2_net::get_base() + 0x18D0) = 0xBC3C;
for (size_t i = 0; i < sizeof m_modules / sizeof(void*); i++) {
if (m_modules[i] == nullptr)
break;
m_modules[i]->init();
}
}
void d2_tweaks::server::server::send_packet(diablo2::structures::net_client* client, common::packet_header* packet, size_t size) {
diablo2::d2_game::enqueue_packet(client, packet, size);
}
bool d2_tweaks::server::server::handle_packet(diablo2::structures::game* game,
diablo2::structures::unit* player,
common::packet_header* packet) {
auto handler = m_packet_handlers[packet->message_type];
if (!handler)
return false;
return handler->handle_packet(game, player, packet);
}
void d2_tweaks::server::server::register_module(modules::server_module* module) {
m_modules[m_module_id_counter++] = module;
}
void d2_tweaks::server::server::register_tick_handler(modules::server_module* module) {
m_tick_handlers[m_tick_handler_id_counter++] = module;
}
void d2_tweaks::server::server::register_packet_handler(common::message_types_t type, modules::server_module* module) {
if (m_packet_handlers[type] != nullptr) {
spdlog::warn("Serverside packet handler for {0} is already registered!", type);
}
m_packet_handlers[type] = module;
}
diablo2::structures::unit* d2_tweaks::server::server::get_server_unit(diablo2::structures::game* game, uint32_t guid, diablo2::structures::unit_type_t type) {
if (game == nullptr)
return nullptr;
auto typeIndex = static_cast<uint32_t>(type);
if (type == diablo2::structures::unit_type_t::UNIT_TYPE_MISSILE)
typeIndex = 4;
if (type == diablo2::structures::unit_type_t::UNIT_TYPE_ITEM)
typeIndex = 3;
const auto index = guid & 127;
auto result = game->unit_list[typeIndex][index];
while (result != nullptr && result->guid != guid) {
result = result->prev_unit;
}
return result;
}
void d2_tweaks::server::server::iterate_server_units(diablo2::structures::game* game, diablo2::structures::unit_type_t type,
const std::function<bool(diablo2::structures::unit*)>& cb) {
if (!cb)
return;
if (!game)
return;
auto typeIndex = static_cast<uint32_t>(type);
if (type == diablo2::structures::unit_type_t::UNIT_TYPE_MISSILE)
typeIndex = 4;
if (type == diablo2::structures::unit_type_t::UNIT_TYPE_ITEM)
typeIndex = 3;
for (size_t index = 0; index < 128; index++) {
auto unit = game->unit_list[typeIndex][index];
while (unit != nullptr) {
if (!cb(unit))
return;
unit = unit->prev_unit;
}
}
}
int32_t d2_tweaks::server::server::net_tick(diablo2::structures::game* game, diablo2::structures::unit* unit, int32_t a3, int32_t a4) {
static auto& instance = singleton<server>::instance();
for (size_t i = 0; i < sizeof instance.m_modules / sizeof(void*); i++) {
if (instance.m_tick_handlers[i] == nullptr)
break;
instance.m_tick_handlers[i]->tick(game, unit);
}
return g_net_tick_original(game, unit, a3, a4);
}