mirror of
https://github.com/diamante0018/MW3ServerFreezer.git
synced 2025-04-19 19:52:53 +00:00
userinfo spam
This commit is contained in:
parent
1119a5e7a2
commit
45d7c3daf5
@ -91,6 +91,11 @@ namespace cheats
|
||||
{
|
||||
command::execute(utils::string::va("cmd mr %i 2 allies", *game::serverId), true);
|
||||
});
|
||||
|
||||
key_catcher::on_key_press("8", [](const game::LocalClientNum_t&)
|
||||
{
|
||||
command::execute(utils::string::va("cmd mr %i -1 endround", *game::serverId), true);
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
170
src/component/scheduler.cpp
Normal file
170
src/component/scheduler.cpp
Normal file
@ -0,0 +1,170 @@
|
||||
#include <stdinc.hpp>
|
||||
#include "loader/component_loader.hpp"
|
||||
|
||||
#include "utils/concurrency.hpp"
|
||||
#include "utils/hook.hpp"
|
||||
|
||||
#include "scheduler.hpp"
|
||||
|
||||
namespace scheduler
|
||||
{
|
||||
std::thread::id async_thread_id;
|
||||
|
||||
namespace
|
||||
{
|
||||
struct task
|
||||
{
|
||||
std::function<bool()> handler{};
|
||||
std::chrono::milliseconds interval{};
|
||||
std::chrono::high_resolution_clock::time_point last_call{};
|
||||
};
|
||||
|
||||
using task_list = std::vector<task>;
|
||||
|
||||
class task_pipeline
|
||||
{
|
||||
public:
|
||||
void add(task&& task)
|
||||
{
|
||||
new_callbacks_.access([&task, this](task_list& tasks)
|
||||
{
|
||||
tasks.emplace_back(std::move(task));
|
||||
});
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
callbacks_.access([&](task_list& tasks)
|
||||
{
|
||||
this->merge_callbacks();
|
||||
tasks.clear();
|
||||
});
|
||||
}
|
||||
|
||||
void execute()
|
||||
{
|
||||
callbacks_.access([&](task_list& tasks)
|
||||
{
|
||||
this->merge_callbacks();
|
||||
|
||||
for (auto i = tasks.begin(); i != tasks.end();)
|
||||
{
|
||||
const auto now = std::chrono::high_resolution_clock::now();
|
||||
const auto diff = now - i->last_call;
|
||||
|
||||
if (diff < i->interval)
|
||||
{
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
|
||||
i->last_call = now;
|
||||
|
||||
const auto res = i->handler();
|
||||
if (res == cond_end)
|
||||
{
|
||||
i = tasks.erase(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
++i;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
utils::concurrency::container<task_list> new_callbacks_;
|
||||
utils::concurrency::container<task_list, std::recursive_mutex> callbacks_;
|
||||
|
||||
void merge_callbacks()
|
||||
{
|
||||
callbacks_.access([&](task_list& tasks)
|
||||
{
|
||||
new_callbacks_.access([&](task_list& new_tasks)
|
||||
{
|
||||
tasks.insert(tasks.end(), std::move_iterator<task_list::iterator>(new_tasks.begin()), std::move_iterator<task_list::iterator>(new_tasks.end()));
|
||||
new_tasks = {};
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
std::thread thread;
|
||||
task_pipeline pipelines[pipeline::count];
|
||||
|
||||
void execute(const pipeline type)
|
||||
{
|
||||
assert(type >= 0 && type < pipeline::count);
|
||||
pipelines[type].execute();
|
||||
}
|
||||
|
||||
void cl_frame_stub(game::LocalClientNum_t local)
|
||||
{
|
||||
reinterpret_cast<void (*)(game::LocalClientNum_t)>(0x041C9B0)(local);
|
||||
execute(pipeline::client);
|
||||
}
|
||||
}
|
||||
|
||||
void clear_tasks(const pipeline type)
|
||||
{
|
||||
return pipelines[type].clear();
|
||||
}
|
||||
|
||||
void schedule(const std::function<bool()>& callback, const pipeline type,
|
||||
const std::chrono::milliseconds delay)
|
||||
{
|
||||
assert(type >= 0 && type < pipeline::count);
|
||||
|
||||
task task;
|
||||
task.handler = callback;
|
||||
task.interval = delay;
|
||||
task.last_call = std::chrono::high_resolution_clock::now();
|
||||
|
||||
pipelines[type].add(std::move(task));
|
||||
}
|
||||
|
||||
void loop(const std::function<void()>& callback, const pipeline type,
|
||||
const std::chrono::milliseconds delay)
|
||||
{
|
||||
schedule([callback]()
|
||||
{
|
||||
callback();
|
||||
return cond_continue;
|
||||
}, type, delay);
|
||||
}
|
||||
|
||||
void once(const std::function<void()>& callback, const pipeline type,
|
||||
const std::chrono::milliseconds delay)
|
||||
{
|
||||
schedule([callback]()
|
||||
{
|
||||
callback();
|
||||
return cond_end;
|
||||
}, type, delay);
|
||||
}
|
||||
|
||||
unsigned int thread_id;
|
||||
|
||||
class component final : public component_interface
|
||||
{
|
||||
public:
|
||||
void post_unpack() override
|
||||
{
|
||||
thread = std::thread([]()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
execute(pipeline::async);
|
||||
std::this_thread::sleep_for(10ms);
|
||||
}
|
||||
});
|
||||
|
||||
async_thread_id = thread.get_id();
|
||||
|
||||
utils::hook::call(0x04E4A0D, cl_frame_stub);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
REGISTER_COMPONENT(scheduler::component)
|
25
src/component/scheduler.hpp
Normal file
25
src/component/scheduler.hpp
Normal file
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
namespace scheduler
|
||||
{
|
||||
extern std::thread::id async_thread_id;
|
||||
|
||||
enum pipeline
|
||||
{
|
||||
client,
|
||||
async,
|
||||
count,
|
||||
};
|
||||
|
||||
static const bool cond_continue = false;
|
||||
static const bool cond_end = true;
|
||||
|
||||
void clear_tasks(const pipeline type);
|
||||
|
||||
void schedule(const std::function<bool()>& callback, pipeline type = pipeline::client,
|
||||
std::chrono::milliseconds delay = 0ms);
|
||||
void loop(const std::function<void()>& callback, pipeline type = pipeline::client,
|
||||
std::chrono::milliseconds delay = 0ms);
|
||||
void once(const std::function<void()>& callback, pipeline type = pipeline::client,
|
||||
std::chrono::milliseconds delay = 0ms);
|
||||
}
|
81
src/component/user_info.cpp
Normal file
81
src/component/user_info.cpp
Normal file
@ -0,0 +1,81 @@
|
||||
#include <stdinc.hpp>
|
||||
|
||||
#include <loader/component_loader.hpp>
|
||||
#include "utils/hook.hpp"
|
||||
#include "utils/info_string.hpp"
|
||||
#include "utils/string.hpp"
|
||||
|
||||
#include "scheduler.hpp"
|
||||
|
||||
namespace user_info
|
||||
{
|
||||
namespace
|
||||
{
|
||||
int a1 = 0;
|
||||
void cl_check_user_info(int _a1, int force)
|
||||
{
|
||||
a1 = _a1;
|
||||
|
||||
if (*game::connectionState <= game::connstate_t::CA_CHALLENGING)
|
||||
return;
|
||||
|
||||
if (game::cl_paused->current.enabled && !force)
|
||||
return;
|
||||
|
||||
const std::string infoString = game::Dvar_InfoString(_a1, 0x200);
|
||||
utils::info_string info(infoString);
|
||||
|
||||
const auto colorCode = rand() % 10;
|
||||
|
||||
char numbers[_MAX_U64TOSTR_BASE2_COUNT];
|
||||
char name[16];
|
||||
|
||||
_itoa_s(rand() % 10000, numbers, sizeof(numbers), 10);
|
||||
_snprintf_s(name, sizeof(name), _TRUNCATE, "^%d%s", colorCode, numbers);
|
||||
|
||||
info.set("name", name);
|
||||
|
||||
info.set("ec_usingTag", "1");
|
||||
info.set("ec_TagText", utils::string::va("^%dGG", colorCode));
|
||||
|
||||
char bigTitle[_MAX_U64TOSTR_BASE2_COUNT];
|
||||
_itoa_s(rand() % 512, bigTitle, sizeof(bigTitle), 10);
|
||||
|
||||
info.set("ec_TitleBg", bigTitle);
|
||||
|
||||
game::CL_AddReliableCommand(_a1, utils::string::va("userinfo \"%s\"", info.build().data()));
|
||||
}
|
||||
|
||||
__declspec(naked) void cl_check_user_info_stub()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
pushad
|
||||
|
||||
push 0
|
||||
push esi
|
||||
call cl_check_user_info
|
||||
add esp, 8
|
||||
|
||||
popad
|
||||
ret
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class component final : public component_interface
|
||||
{
|
||||
public:
|
||||
void post_unpack() override
|
||||
{
|
||||
utils::hook::call(0x41CA53, cl_check_user_info_stub);
|
||||
|
||||
scheduler::loop([]
|
||||
{
|
||||
cl_check_user_info(a1, TRUE);
|
||||
}, scheduler::pipeline::client, 4s);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
REGISTER_COMPONENT(user_info::component)
|
@ -8,6 +8,7 @@ BOOL APIENTRY DllMain(HMODULE /*hModule*/,
|
||||
{
|
||||
if (ul_reason_for_call == DLL_PROCESS_ATTACH)
|
||||
{
|
||||
srand(uint32_t(time(nullptr)));
|
||||
component_loader::post_unpack();
|
||||
}
|
||||
|
||||
|
@ -204,9 +204,8 @@ namespace game
|
||||
netadrtype_t type;
|
||||
unsigned char ip[4];
|
||||
unsigned __int16 port;
|
||||
netsrc_t localNetID;
|
||||
char __pad0[4];
|
||||
unsigned int index;
|
||||
unsigned char ipx[10];
|
||||
unsigned int addrHandleIndex;
|
||||
};
|
||||
|
||||
static_assert(sizeof(netadr_s) == 24);
|
||||
@ -278,6 +277,21 @@ namespace game
|
||||
LOCAL_CLIENT_COUNT = 4
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CA_DISCONNECTED = 0,
|
||||
CA_CINEMATIC = 1,
|
||||
CA_LOGO = 2,
|
||||
CA_CONNECTING = 3,
|
||||
CA_CHALLENGING = 4,
|
||||
CA_CONNECTED = 5,
|
||||
CA_SENDINGSTATS = 6,
|
||||
CA_REQUESTING_MATCH_RULES = 7,
|
||||
CA_LOADING = 8,
|
||||
CA_PRIMED = 9,
|
||||
CA_ACTIVE = 10
|
||||
} connstate_t;
|
||||
|
||||
struct msg_t
|
||||
{
|
||||
int overflowed;
|
||||
@ -981,45 +995,6 @@ namespace game
|
||||
int hintForcedString;
|
||||
};
|
||||
|
||||
struct trace_t
|
||||
{
|
||||
float fraction;
|
||||
float normal[3];
|
||||
int surfaceFlags;
|
||||
int contents;
|
||||
char material[4];
|
||||
TraceHitType hitType;
|
||||
unsigned __int16 hitId;
|
||||
float fractionForHitType;
|
||||
unsigned __int16 modelIndex;
|
||||
unsigned __int16 partName;
|
||||
unsigned __int16 partGroup;
|
||||
bool allsolid;
|
||||
bool startsolid;
|
||||
bool walkable;
|
||||
};
|
||||
|
||||
static_assert(sizeof(trace_t) == 52);
|
||||
|
||||
struct pml_t
|
||||
{
|
||||
float forward[3];
|
||||
float right[3];
|
||||
float up[3];
|
||||
float frametime;
|
||||
int msec;
|
||||
int walking;
|
||||
int groundPlane;
|
||||
int almostGroundPlane;
|
||||
trace_t groundTrace;
|
||||
float impactSpeed;
|
||||
float previous_origin[3];
|
||||
float previous_velocity[3];
|
||||
int holdrand;
|
||||
};
|
||||
|
||||
static_assert(sizeof(pml_t) == 140);
|
||||
|
||||
struct clientConnection_t
|
||||
{
|
||||
int qport; // 0
|
||||
|
@ -29,6 +29,7 @@ namespace game
|
||||
Dvar_RegisterFloat{0x4A5CF0};
|
||||
WEAK symbol<void(dvar_t* var, bool value)> Dvar_SetBool{0x46DD70};
|
||||
WEAK symbol<void(const char* dvarName, bool value)> Dvar_SetBoolByName{0x48C7D0};
|
||||
WEAK symbol<const char*(int, int)> Dvar_InfoString{0x4028C0};
|
||||
|
||||
WEAK symbol<int(const char* cmd)> Key_GetBindingForCmd{0x47D300};
|
||||
WEAK symbol<int(const char* keyAsText)> Key_StringToKeynum{0x50A710}; // Virtual-Key Code
|
||||
@ -49,6 +50,7 @@ namespace game
|
||||
WEAK symbol<void(const msg_t*, unsigned __int64)> MSG_WriteInt64{0x4906B0};
|
||||
WEAK symbol<void(const msg_t*, int)> MSG_WriteShort{0x4ACD80};
|
||||
WEAK symbol<void(const msg_t*, const void*, int)> MSG_WriteData{0x4F8C20};
|
||||
WEAK symbol<void(int, const char*)> CL_AddReliableCommand{0x4EE3A0};
|
||||
|
||||
WEAK symbol<unsigned __int64()> LiveSteam_GetUid{0x4A4050};
|
||||
WEAK symbol<int(unsigned __int64, const void*, unsigned int)> LiveSteam_Client_ConnectToSteamServer{0x4D6980};
|
||||
@ -60,4 +62,6 @@ namespace game
|
||||
WEAK symbol<HWND> g_wv_hWnd{0x5A86AF0};
|
||||
WEAK symbol<HWND> s_wcd_hWnd{0x5A86330};
|
||||
WEAK symbol<int> serverId{0xFF5058};
|
||||
WEAK symbol<connstate_t> connectionState{0x1060214};
|
||||
WEAK symbol<dvar_t> cl_paused{0x1CE6190};
|
||||
}
|
||||
|
@ -1,7 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#define DLL_EXPORT extern "C" __declspec(dllexport)
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
|
||||
#include <windows.h>
|
||||
#include <WinSock2.h>
|
||||
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
@ -10,7 +14,6 @@
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <queue>
|
||||
#include <unordered_set>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
46
src/utils/concurrency.hpp
Normal file
46
src/utils/concurrency.hpp
Normal file
@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include <mutex>
|
||||
|
||||
namespace utils::concurrency
|
||||
{
|
||||
template <typename T, typename MutexType = std::mutex>
|
||||
class container
|
||||
{
|
||||
public:
|
||||
template <typename R = void, typename F>
|
||||
R access(F&& accessor) const
|
||||
{
|
||||
std::lock_guard<MutexType> _{mutex_};
|
||||
return accessor(object_);
|
||||
}
|
||||
|
||||
template <typename R = void, typename F>
|
||||
R access(F&& accessor)
|
||||
{
|
||||
std::lock_guard<MutexType> _{mutex_};
|
||||
return accessor(object_);
|
||||
}
|
||||
|
||||
template <typename R = void, typename F>
|
||||
R access_with_lock(F&& accessor) const
|
||||
{
|
||||
std::unique_lock<MutexType> lock{mutex_};
|
||||
return accessor(object_, lock);
|
||||
}
|
||||
|
||||
template <typename R = void, typename F>
|
||||
R access_with_lock(F&& accessor)
|
||||
{
|
||||
std::unique_lock<MutexType> lock{mutex_};
|
||||
return accessor(object_, lock);
|
||||
}
|
||||
|
||||
T& get_raw() { return object_; }
|
||||
const T& get_raw() const { return object_; }
|
||||
|
||||
private:
|
||||
mutable MutexType mutex_{};
|
||||
T object_{};
|
||||
};
|
||||
}
|
66
src/utils/info_string.cpp
Normal file
66
src/utils/info_string.cpp
Normal file
@ -0,0 +1,66 @@
|
||||
#include <stdinc.hpp>
|
||||
|
||||
#include "info_string.hpp"
|
||||
#include "string.hpp"
|
||||
|
||||
namespace utils
|
||||
{
|
||||
info_string::info_string(const std::string& buffer)
|
||||
{
|
||||
this->parse(buffer);
|
||||
}
|
||||
|
||||
info_string::info_string(const std::string_view& buffer)
|
||||
: info_string(std::string{buffer})
|
||||
{
|
||||
}
|
||||
|
||||
void info_string::set(const std::string& key, const std::string& value)
|
||||
{
|
||||
this->key_value_pairs_[key] = value;
|
||||
}
|
||||
|
||||
std::string info_string::get(const std::string& key) const
|
||||
{
|
||||
const auto value = this->key_value_pairs_.find(key);
|
||||
if (value != this->key_value_pairs_.end())
|
||||
{
|
||||
return value->second;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
void info_string::parse(std::string buffer)
|
||||
{
|
||||
if (buffer[0] == '\\')
|
||||
{
|
||||
buffer = buffer.substr(1);
|
||||
}
|
||||
|
||||
auto key_values = string::split(buffer, '\\');
|
||||
for (size_t i = 0; !key_values.empty() && i < (key_values.size() - 1); i += 2)
|
||||
{
|
||||
const auto& key = key_values[i];
|
||||
const auto& value = key_values[i + 1];
|
||||
this->key_value_pairs_[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
std::string info_string::build() const
|
||||
{
|
||||
//auto first = true;
|
||||
std::string info_string;
|
||||
for (auto i = this->key_value_pairs_.begin(); i != this->key_value_pairs_.end(); ++i)
|
||||
{
|
||||
//if (first) first = false;
|
||||
/*else*/ info_string.append("\\");
|
||||
|
||||
info_string.append(i->first); // Key
|
||||
info_string.append("\\");
|
||||
info_string.append(i->second); // Value
|
||||
}
|
||||
|
||||
return info_string;
|
||||
}
|
||||
}
|
24
src/utils/info_string.hpp
Normal file
24
src/utils/info_string.hpp
Normal file
@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace utils
|
||||
{
|
||||
class info_string
|
||||
{
|
||||
public:
|
||||
info_string() = default;
|
||||
info_string(const std::string& buffer);
|
||||
info_string(const std::string_view& buffer);
|
||||
|
||||
void set(const std::string& key, const std::string& value);
|
||||
std::string get(const std::string& key) const;
|
||||
std::string build() const;
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, std::string> key_value_pairs_{};
|
||||
|
||||
void parse(std::string buffer);
|
||||
};
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user