Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

custom packets using game's network code implementation #213

Merged
merged 19 commits into from
Apr 25, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
1d14f0d
Improved LIVE list download speed by far.
nukeulater Mar 31, 2019
4a34ce7
Fixed wrong offset for masterchief mp max absolute acceleration.
nukeulater Mar 31, 2019
4e1f8c8
Use overlapped structure to indicate the status of some XLocator func…
nukeulater Mar 31, 2019
0d19982
Fill asynchronous information for some functions (took from XLiveless…
nukeulater Apr 1, 2019
3c798e2
Use unordered_map instead of map in the menu labels functions to impr…
nukeulater Apr 2, 2019
462161f
Fixed wrong variable type
nukeulater Apr 2, 2019
8804b59
Add option to change dedi server name on LIVE list.
nukeulater Apr 2, 2019
4b57a95
Set live packet handler to 250 to get ~60 packets/sec instead of 15 p…
nukeulater Apr 3, 2019
179d863
Added statistics for sendto function, and new console command netstats.
nukeulater Apr 9, 2019
0b0c823
Update version number
nukeulater Apr 14, 2019
8c72dfc
Code cleanup
nukeulater Apr 17, 2019
2a3209f
Added true custom packets PoC
nukeulater Apr 22, 2019
d5f95a6
Moved network_session stuff to separate files
nukeulater Apr 23, 2019
12d52da
Added code for map downloading custom packets
nukeulater Apr 23, 2019
ffeea21
Added team change packet and implemented in infection
nukeulater Apr 23, 2019
f29d2db
Fixed issue where objects different than biped type would cause infec…
nukeulater Apr 24, 2019
8d0c361
Added gungame grenade count packet
nukeulater Apr 24, 2019
af23119
Added time countdown for map downloading menu to stop AFK players or …
nukeulater Apr 24, 2019
24b0518
Merge branch 'development' into bs
nukeulater Apr 25, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,4 @@ xliveless.v12.suo
/xlive/Debug
/xlive/Release
*.opensdf
*.user
2 changes: 0 additions & 2 deletions xlive/Globals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ char* replacedNetworkNormalTextWidget;
char* replacedNetworkNormalTextWidget2;

ConsoleCommands* commands = new ConsoleCommands();
GameManager* gameManager = new GameManager();
CustomNetwork *network = new CustomNetwork();

Players* players = new Players();

Expand Down
21 changes: 5 additions & 16 deletions xlive/Globals.h
Original file line number Diff line number Diff line change
@@ -1,19 +1,10 @@
#pragma once

#include <string>
#include <sstream>
#include <vector>
#include <algorithm>
#include "stdafx.h"
#include <unordered_map>
#include <stdlib.h>
#include <mutex>
#include "H2MOD.h"
#include <windows.h>
#include "xliveless.h"
#include "Util\Hooks\Hook.h"
#include "Util\ReadIniArguments.h"
#include <3rdparty/portaudio/include/portaudio.h>
#include "3rdparty/portaudio/include/portaudio.h"

#include "Blam\BlamLibrary.h"
#include "H2MOD\Modules\Players\Players.h"
Expand All @@ -27,16 +18,16 @@
#include "H2MOD\Variants\HeadHunter\HeadHunter.h"
#include "H2MOD\Modules\Console\ConsoleCommands.h"
#include "H2MOD\Modules\MapManager\MapManager.h"
#include "H2MOD\Modules\Networking\Networking.h"
#include "H2MOD\Modules\GameManager\GameManager.h"
#include "H2MOD\Modules\AdvLobbySettings\AdvLobbySettings.h"
#include "H2MOD\Modules\Achievements\Achievements.h"
#include "H2MOD\Modules\AdvLobbySettings\AdvLobbySettings.h"

#define run_async(expression) \
std::thread{ [=] { expression; } }.detach();

using namespace Blam::EngineDefinitions::Tag;
using namespace Blam::EngineDefinitions::Players;
using namespace Blam::EngineDefinitions::Objects;
using namespace Blam::EngineDefinitions::Actors;
using namespace Blam::EngineDefinitions::Tag;

extern GameStatePlayerTable *game_state_players;
extern GameStateObjectHeaderTable* game_state_objects_header;
Expand All @@ -52,9 +43,7 @@ extern bool displayXyz;
extern volatile bool isLobby;
extern bool overrideUnicodeMessage;
extern ConsoleCommands* commands;
extern GameManager* gameManager;
extern Players* players;
extern CustomNetwork *network;
extern char* replacedNetworkNormalTextWidget;
extern char* replacedNetworkNormalTextWidget2;

Expand Down
108 changes: 23 additions & 85 deletions xlive/H2MOD.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#include <stdafx.h>
#include "stdafx.h"
#include "H2MOD.h"
#include <Wincrypt.h>
#include <Mmsystem.h>
#include "H2MOD.h"
#include "Blam\Engine\FileSystem\FiloInterface.h"
#include "H2MOD\Discord\DiscordInterface.h"
#include "H2MOD\Modules\OnScreenDebug\OnscreenDebug.h"
Expand All @@ -16,6 +16,9 @@
#include "H2MOD\Variants\H2X\H2X.h"
#include "H2MOD\Variants\GunGame\GunGame.h"
#include "XLive\UserManagement\CUser.h"
#include "H2MOD\Modules\Networking\Memory\bitstream.h"
#include "H2MOD\Modules\Networking\CustomPackets\CustomPackets.h"
#include "H2MOD\Modules\Networking\NetworkSession\NetworkSession.h"

H2MOD *h2mod = new H2MOD();
GunGame* gunGame = new GunGame();
Expand Down Expand Up @@ -287,63 +290,26 @@ signed int __cdecl object_new_hook(void *pObject)
return result;
}

bool bitstream_write_bool(void *packet, char* string_data, bool value)
{
typedef bool(__thiscall *tbitstream_write_bool)(void* packet, char* string_data, bool value);
tbitstream_write_bool ptbitstream_write_bool = (tbitstream_write_bool)((char*)h2mod->GetBase() + (h2mod->Server ? 0xCDE40 : 0xD1886));

return ptbitstream_write_bool(packet, string_data, value);
}

int bitstream_write_uint(void* packet, char* string_data, unsigned int value, signed int bit_size)
{
typedef int(__thiscall *tbitstream_write_uint)(void* packet, char* string_data, unsigned int value, signed int bit_size);
tbitstream_write_uint pbitstream_write_uint = (tbitstream_write_uint)((char*)h2mod->GetBase() + (h2mod->Server ? 0xCDD80 : 0xD17C6));

return pbitstream_write_uint(packet, string_data, value, bit_size);
}


bool bitstream_read_bool(void *packet, char* string_data)
{
typedef bool(__thiscall *tbitstream_read_bool)(void* packet, char* string_data);
tbitstream_read_bool ptbitstream_read_bool = (tbitstream_read_bool)((char*)h2mod->GetBase() + (h2mod->Server ? 0xCE501 : 0xD1F47));

return ptbitstream_read_bool(packet, string_data);
}

int bitstream_read_uint(void* packet, char* string_data, signed int bit_size)
{
typedef int(__thiscall *tbitstream_read_uint)(void* packet, char* string_data, signed int bit_size);
tbitstream_read_uint pbitstream_read_uint = (tbitstream_read_uint)((char*)h2mod->GetBase() + (h2mod->Server ? 0xCE49F : 0xD1EE5));

return pbitstream_read_uint(packet, string_data,bit_size);
}

typedef int(__stdcall *tc_simulation_unit_entity_definition_creation_encode)(void* thisptr, int creation_data_size, void* creation_data, int a3, void* packet);
tc_simulation_unit_entity_definition_creation_encode pc_simulation_unit_entity_definition_encode;

int __stdcall c_simulation_unit_entity_definition_creation_encode(void *thisptr, int creation_data_size, void* creation_data, int a3, void* packet)
{
//TRACE_GAME_N("c_simulation_unit_entity_definition_creation_encode()\r\nthisptr: %08X, creation_data_size: %i, creation_data: %08X, a3: %i, packet: %08X", thisptr, creation_data_size, creation_data, a3, packet);


int object_permutation_index = *(int*)((char*)creation_data + 0x24);
if( object_permutation_index != -1)
if (object_permutation_index != -1)
{
//TRACE_GAME_N("creation_data+0x24: %08X", object_permutation_index);

bitstream_write_bool(packet, "object-permutation-exists", 1);
bitstream_write_uint(packet, "object-permutation-index", object_permutation_index, 32);
bitstream::p_data_encode_bool()(packet, "object-permutation-exists", 1);
bitstream::p_data_encode_integer()(packet, "object-permutation-index", object_permutation_index, 32);
//TRACE_GAME_N("c_simulation_unit_entity_encode - object-permutation-exists packet: %08X, *packet: %08X", packet, *(int*)packet);

}
else
bitstream_write_bool(packet, "object-permutation-exists", 0);

bitstream::p_data_encode_bool()(packet, "object-permutation-exists", 0);
int ret = pc_simulation_unit_entity_definition_encode(thisptr, creation_data_size, creation_data, a3, packet);


return ret;
}

Expand All @@ -355,19 +321,18 @@ int __stdcall c_simulation_unit_entity_definition_creation_decode(void *thisptr,
{
//TRACE_GAME_N("c_simulation_unit_entity_definition_creation_decode()\r\nthisptr: %08X, creation_data_size: %i, creation_data: %08X, packet: %08X", thisptr, creation_data_size, creation_data, packet);

if (bitstream_read_bool(packet, "object-permutation-exists"))
if (bitstream::p_data_decode_bool()(packet, "object-permutation-exists"))
{
//TRACE_GAME_N("c_simulation_unit_entity_decode - object-permutation-exists packet: %08X, *packet: %08X", packet, *(int*)packet);
int object_permutation_index = bitstream_read_uint(packet, "object-permutation-index", 32);
int object_permutation_index = bitstream::p_data_decode_integer()(packet, "object-permutation-index", 32);
*(int*)((char*)creation_data + 0x24) = object_permutation_index;

//TRACE_GAME_N("object_permutation_index: %08X", object_permutation_index);
}
else
*(int*)((char*)creation_data + 0x24) = -1;

int ret = pc_simulation_unit_entity_definition_decode(thisptr, creation_data_size, creation_data, packet);

int ret = pc_simulation_unit_entity_definition_decode(thisptr, creation_data_size, creation_data, packet);
return ret;
}

Expand Down Expand Up @@ -450,32 +415,6 @@ EngineType H2MOD::GetEngineType()
}
}

char get_lobby_globals_ptr(int* a1)
{
typedef char(__cdecl* get_lobby_globals_ptr)(int *ptr);
auto p_get_lobby_globals_ptr = reinterpret_cast<get_lobby_globals_ptr>(h2mod->GetBase() + ((h2mod->Server) ? 0x1A66B3 : 0x1AD736));

return p_get_lobby_globals_ptr(a1);
}

char get_current_lobby_map_file_location(int thisx, wchar_t* buffer, size_t szBuffer)
{
// host-only
typedef char(__thiscall* get_map_file_location_impl)(int thisx, wchar_t* buffer, size_t szBuffer);
auto p_get_map_file_location_impl = reinterpret_cast<get_map_file_location_impl>(h2mod->GetBase() + ((h2mod->Server) ? 0x19CD4A : 0x1C5678));

return p_get_map_file_location_impl(thisx, buffer, szBuffer);
}

void get_map_internal_name(int a1, wchar_t* buffer)
{
// doesn't work on dedicated servers
typedef void(__cdecl* get_map_internal_name_impl)(int a1, wchar_t* buffer);
auto p_map_internal_name_impl = reinterpret_cast<get_map_internal_name_impl>(h2mod->GetBase() + ((h2mod->Server) ? 0x2094E2 : 0x22E58A));

p_map_internal_name_impl(a1, buffer);
}

inline wchar_t* H2MOD::GetLobbyGameVariantName()
{
return (wchar_t*)(h2mod->GetBase() + ((h2mod->Server) ? 0x534A18 : 0x97777C));
Expand Down Expand Up @@ -1113,7 +1052,7 @@ void __cdecl OnMapLoad(int a1)
addDebugText("GameEngine: Main-Menu");
object_to_variant.clear();

if (!gameManager->isHost()) {
if (!NetworkSession::localPeerIsSessionHost()) {
advLobbySettings->resetLobbySettings();
}

Expand Down Expand Up @@ -1321,7 +1260,7 @@ typedef int(__cdecl *build_gui_list)(int a1, int a2, int a3);
build_gui_list build_gui_list_method;

int __cdecl buildGuiList(int a1, int a2, int a3) {
if (b_Infection && a1 == (DWORD)(h2mod->GetBase() + 0x3d3620) && !gameManager->isHost()) {
if (b_Infection && a1 == (DWORD)(h2mod->GetBase() + 0x3d3620) && !NetworkSession::localPeerIsSessionHost()) {
a2 = 1;
}
return build_gui_list_method(a1, a2, a3);
Expand Down Expand Up @@ -1420,8 +1359,7 @@ on_custom_map_change on_custom_map_change_method;

void __cdecl onCustomMapChange(const void* a1) {
on_custom_map_change_method(a1);
//map changed, send update
mapManager->sendMapInfoPacket();
//map changed, send update to all players
}

typedef char(__stdcall *intercept_map_load)(LPCRITICAL_SECTION* thisx, const void *a2);
Expand Down Expand Up @@ -1624,6 +1562,9 @@ void H2MOD::ApplyUnitHooks()
{
DWORD dwBack;

BYTE packet_sz = 0x30;
WriteBytes(h2mod->GetBase() + (h2mod->Server ? 0x1E1D8F : 0x1F8029), &packet_sz, 1);

//This encodes the unit creation packet, only gets executed on host.
pc_simulation_unit_entity_definition_encode = (tc_simulation_unit_entity_definition_creation_encode)DetourClassFunc((BYTE*)this->GetBase() + (h2mod->Server ? 0x1E2269 : 0x1F8503), (BYTE*)c_simulation_unit_entity_definition_creation_encode, 10);
VirtualProtect(pc_simulation_unit_entity_definition_encode, 4, PAGE_EXECUTE_READWRITE, &dwBack);
Expand All @@ -1642,9 +1583,6 @@ void H2MOD::ApplyUnitHooks()
PatchCall(GetBase() + (h2mod->Server ? 0x1E1DE0 : 0x1F807A), set_unit_creation_data_hook);
pset_unit_creation_data = (tset_unit_creation_data)(GetBase() + (h2mod->Server ? 0x1DD586 : 0x1F24ED));

BYTE packet_sz = 0x28;
WriteBytes(h2mod->GetBase() + (h2mod->Server ? 0x1E1D8F : 0x1F8029), &packet_sz, 1);

// Hooks a call within the creat_unit property on the client side in order to set their permutation index before spawn.
PatchCall(GetBase() + (h2mod->Server ? 0x1E3BD4 : 0x1F9E6C), create_unit_hook);
pcreate_unit_hook = (tcreate_unit_hook)(GetBase() + (h2mod->Server ? 0x1DE374 : 0x1F32DB));
Expand Down Expand Up @@ -1733,7 +1671,7 @@ void H2MOD::ApplyHooks() {
VirtualProtect(change_team_method, 4, PAGE_EXECUTE_READWRITE, &dwBack);

// hook the print command to redirect the output to our console
PatchCall(Base + 0xE9E50, print_to_console);
PatchCall(GetBase() + 0xE9E50, print_to_console);

PatchCall(GetBase() + 0x9B09F, filo_write__encrypted_data_hook);
PatchWinAPICall(GetBase() + 0x9AF9E, CryptUnprotectDataHook);
Expand All @@ -1747,9 +1685,9 @@ void H2MOD::ApplyHooks() {
WriteValue(GetBase() + 0x190B38 + 1, 5);

pfn_c000bd114 = (tfn_c000bd114)DetourFunc((BYTE*)H2BaseAddr + 0x000bd114, (BYTE*)fn_c000bd114_IsSkullEnabled, 5);
PatchCall(Base + 0x00182d6d, GrenadeChainReactIsEngineMPCheck);
PatchCall(Base + 0x00092C05, BansheeBombIsEngineMPCheck);
PatchCall(Base + 0x0013ff75, FlashlightIsEngineSPCheck);
PatchCall(GetBase() + 0x00182d6d, GrenadeChainReactIsEngineMPCheck);
PatchCall(GetBase() + 0x00092C05, BansheeBombIsEngineMPCheck);
PatchCall(GetBase() + 0x0013ff75, FlashlightIsEngineSPCheck);
}
else {

Expand Down
10 changes: 6 additions & 4 deletions xlive/H2MOD.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,6 @@ int __cdecl call_object_placement_data_new(void*, int, int, int);
signed int __cdecl call_object_new(void*);
void GivePlayerWeapon(int PlayerIndex, int WeaponId, bool bReset);
void GivePlayerWeapon2(int PlayerIndex, int WeaponId, short Unk);
char get_lobby_globals_ptr(int* a1);
char get_current_lobby_map_file_location(int thisx, wchar_t* buffer, size_t szBuffer);
void get_map_internal_name(int a1, wchar_t* buffer);


class H2MOD
{
Expand Down Expand Up @@ -149,6 +145,12 @@ class H2MOD
void SetBase(DWORD base) { Base = base; }
DWORD GetBase() { return Base; }

template <typename T = void>
inline T *GetAddress(DWORD client, DWORD server = 0)
{
return reinterpret_cast<T*>(GetBase() + (Server ? server : client));
}

private:
DWORD Base;
std::unordered_map<int, int> playerIndexToDynamicBase;
Expand Down
Loading