Merge branch 'develop_official' into feature/xinput

# Conflicts:
#	src/Components/Loader.cpp
This commit is contained in:
Louvenarde 2021-09-08 21:34:37 +02:00
commit 570d2acdac
27 changed files with 161 additions and 106 deletions

7
.github/dependabot.yml vendored Normal file
View File

@ -0,0 +1,7 @@
version: 2
updates:
- package-ecosystem: gitsubmodule
directory: "/"
schedule:
interval: daily
open-pull-requests-limit: 10

36
.github/labeler.yml vendored
View File

@ -1,36 +0,0 @@
"part: game client":
- src/Components/Modules/Stats*
"part: game server":
- src/Components/Modules/Dedicated*
"part: zonebuilder":
- src/Components/Modules/ZoneBuilder*
"area: menus":
- src/Components/Modules/Menus*
"area: anticheat":
- src/Components/Modules/AntiCheat*
"area: serverlist":
- src/Components/Modules/ServerList*
"area: weapons":
- src/Components/Modules/Weapon*
"area: networking":
- src/Components/Modules/Auth*
- src/Components/Modules/Network*
- src/Components/Modules/Node*
- src/Components/Modules/PlayerName*
- src/Components/Modules/RCon*
- src/Components/Modules/Session*
"area: continuous integration":
- "*appveyor*"
- ".github/workflows/**"
- Jenkinsfile
"status: work in progress":
- "**"

View File

@ -1,11 +0,0 @@
name: "Pull Request Labeler"
on:
- pull_request
jobs:
labeler:
runs-on: ubuntu-latest
steps:
- uses: actions/labeler@v2
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"

2
deps/json11 vendored

@ -1 +1 @@
Subproject commit e2e3a11e99672b018e0e0657867e6a3439e180cf
Subproject commit 2df9473fb3605980db55ecddf34392a2e832ad35

2
deps/libtomcrypt vendored

@ -1 +1 @@
Subproject commit 1937f412605e1b04ddb41ef9c2f2f0aab7e61548
Subproject commit 673f5ce29015a9bba3c96792920a10601b5b0718

2
deps/libtommath vendored

@ -1 +1 @@
Subproject commit 6ac0b0c1b69b9a88e1b3b3002c2e3a9062ae99b4
Subproject commit eda0bd6ae5705ab90b866dfb52c5f15c23687f81

2
deps/pdcurses vendored

@ -1 +1 @@
Subproject commit 618e0aaa31b4728eb4df78ec4de6c2b873908eda
Subproject commit 4bc97e287be5d8927405614c193fd0a039df027a

2
deps/protobuf vendored

@ -1 +1 @@
Subproject commit 63cfdafacba6141717a2df97fc123dc0c14ba7c4
Subproject commit df2bce345d4bc8cdc3eba2a866e11e79e1fff4df

2
deps/zlib vendored

@ -1 +1 @@
Subproject commit d71dc66fa8a153fb6e7c626847095d9697a6cf42
Subproject commit c3f3043f7aa80750245f8166a338c4877020b589

View File

@ -1,4 +1,4 @@
@echo off
echo Updating submodules...
call git submodule update --init --recursive
call tools\premake5 %* vs2019
call tools\premake5 %* vs2019 --ac-disable

View File

@ -101,6 +101,7 @@ namespace Components
Loader::Register(new StructuredData());
Loader::Register(new ConnectProtocol());
Loader::Register(new StartupMessages());
Loader::Register(new SoundMutexFix());
Loader::Register(new Gamepad());
Loader::Register(new Client());

View File

@ -130,6 +130,7 @@ namespace Components
#include "Modules/ConnectProtocol.hpp"
#include "Modules/StartupMessages.hpp"
#include "Modules/Stats.hpp"
#include "Modules/SoundMutexFix.hpp"
#include "Modules/Gamepad.hpp"
#include "Modules/Client.hpp"

View File

@ -889,12 +889,8 @@ namespace Components
time(nullptr);
AntiCheat::Flags = NO_FLAG;
#ifdef DISABLE_ANTICHEAT
Command::Add("penis", [](Command::Params*)
{
AntiCheat::CrashClient();
});
#else
#ifndef DISABLE_ANTICHEAT
Utils::Hook(0x507BD5, AntiCheat::PatchWinAPI, HOOK_CALL).install()->quick();
Utils::Hook(0x5082FD, AntiCheat::LostD3DStub, HOOK_CALL).install()->quick();
Utils::Hook(0x51C76C, AntiCheat::CinematicStub, HOOK_CALL).install()->quick();

View File

@ -76,6 +76,29 @@ namespace Components
}
}
void Dedicated::StripMaterialTextIcons(char* text)
{
char* currentChar = text;
bool isEscaped = false;
while (*currentChar)
{
if (*currentChar == '^')
{
isEscaped = true;
}
else if(isEscaped == true && (*currentChar == '\x01' || *currentChar == '\x02'))
{
*currentChar = ' ';
}
else
{
isEscaped = false;
}
currentChar++;
}
}
const char* Dedicated::EvaluateSay(char* text, Game::gentity_t* player)
{
Dedicated::SendChat = true;
@ -87,6 +110,8 @@ namespace Components
++text;
}
StripMaterialTextIcons(text);
Game::Scr_AddEntity(player);
Game::Scr_AddString(text + 1);
Game::Scr_NotifyLevel(Game::SL_GetString("say", 0), 2);
@ -103,7 +128,7 @@ namespace Components
push eax
pushad
push[esp + 100h + 28h]
push [esp + 100h + 28h]
push eax
call Dedicated::EvaluateSay
add esp, 8h

View File

@ -14,6 +14,8 @@ namespace Components
static void Heartbeat();
static void StripMaterialTextIcons(char* text);
private:
static bool SendChat;

View File

@ -186,6 +186,7 @@ namespace Components
"Deity",
"Dizzy",
"Dss0",
"FutureRave",
"H3X1C",
"HardNougat",
"Homura",
@ -193,7 +194,6 @@ namespace Components
"Killera",
"Lithium",
"Louvenarde",
"FutureRave",
"OneFourOne",
"quaK",
"RaidMax",

View File

@ -771,6 +771,7 @@ namespace Components
Maps::AddDlc({ 6, "Freighter", {"mp_cargoship_sh"} });
Maps::AddDlc({ 7, "Resurrection Pack", {"mp_shipment_long", "mp_rust_long", "mp_firingrange"} });
Maps::AddDlc({ 8, "Recycled Pack", {"mp_bloc_sh", "mp_crash_tropical", "mp_estate_tropical", "mp_fav_tropical", "mp_storm_spring"} });
Maps::AddDlc({ 9, "Classics Pack #3", {"mp_farm", "mp_backlot", "mp_pipeline", "mp_countdown", "mp_crash_snow"} });
Maps::UpdateDlcStatus();

View File

@ -161,7 +161,12 @@ namespace Components
Materials::ImageNameLength = 4 + length;
std::string image(imagePtr, length);
return Game::DB_FindXAssetHeader(Game::XAssetType::ASSET_TYPE_MATERIAL, image.data()).material;
auto* material = Game::DB_FindXAssetHeader(Game::XAssetType::ASSET_TYPE_MATERIAL, image.data()).material;
if(material == nullptr || material->techniqueSet == nullptr || material->techniqueSet->name == nullptr || strcmp(material->techniqueSet->name, "2d") != 0)
return Game::DB_FindXAssetHeader(Game::XAssetType::ASSET_TYPE_MATERIAL, "default").material;
return material;
}
Materials::ImageNameLength = 4;

View File

@ -421,8 +421,8 @@ namespace Components
{
int data = false;
const Utils::Library ntdll("ntdll.dll");
ntdll.InvokePascal<void>("RtlAdjustPrivilege", 19, true, false, &data);
ntdll.InvokePascal<void>("NtRaiseHardError", 0xC000007B, 0, nullptr, nullptr, 6, &data);
ntdll.invokePascal<void>("RtlAdjustPrivilege", 19, true, false, &data);
ntdll.invokePascal<void>("NtRaiseHardError", 0xC000007B, 0, nullptr, nullptr, 6, &data);
});
// Filtering any mapents that is intended for Spec:Ops gamemode (CODO) and prevent them from spawning

View File

@ -127,7 +127,7 @@ namespace Components
// show error
pushad;
push[esp + 24h + 20h];
push [esp + 24h + 20h];
push eax;
call R_TextureFromCodeError;
add esp, 8;

View File

@ -469,9 +469,19 @@ namespace Components
server.ping = (Game::Sys_Milliseconds() - i->sendTime);
server.addr = address;
Dedicated::StripMaterialTextIcons(server.hostname.data());
Dedicated::StripMaterialTextIcons(server.mapname.data());
Dedicated::StripMaterialTextIcons(server.gametype.data());
Dedicated::StripMaterialTextIcons(server.mod.data());
// Remove server from queue
i = ServerList::RefreshContainer.servers.erase(i);
// Servers with more than 18 players or less than 0 players are faking for sure
// So lets ignore those
if (server.clients > 18 || server.maxClients > 18 || server.clients < 0 || server.maxClients < 0)
return;
// Check if already inserted and remove
auto list = ServerList::GetList();
if (!list) return;

View File

@ -21,11 +21,11 @@ namespace Components
__asm
{
pushad
push [esp + 20h]
push [esp + 24h]
call SlowMotion::ApplySlowMotion
add esp, 4h
pop ecx
popad
retn
@ -76,10 +76,10 @@ namespace Components
void SlowMotion::DrawConnectionInterruptedStub(int /*a1*/)
{
// if (!*reinterpret_cast<bool*>(0x1AD8ED0) && !*reinterpret_cast<bool*>(0x1AD8EEC) && !*reinterpret_cast<int*>(0x1AD78F8))
// {
// Utils::Hook::Call<void(int)>(0x454A70)(a1);
// }
// if (!*reinterpret_cast<bool*>(0x1AD8ED0) && !*reinterpret_cast<bool*>(0x1AD8EEC) && !*reinterpret_cast<int*>(0x1AD78F8))
// {
// Utils::Hook::Call<void(int)>(0x454A70)(a1);
// }
}
SlowMotion::SlowMotion()
@ -91,4 +91,4 @@ namespace Components
Utils::Hook(0x4A54ED, SlowMotion::DrawConnectionInterruptedStub, HOOK_CALL).install()->quick();
Utils::Hook(0x4A54FB, SlowMotion::DrawConnectionInterruptedStub, HOOK_CALL).install()->quick();
}
}
}

View File

@ -0,0 +1,39 @@
#include "STDInclude.hpp"
namespace Components
{
// This component is a workaround for issue https://github.com/XLabsProject/iw4x-client/issues/80
// In case the link goes down, this is a "game hangs randomly" issue:
//
// Investigations on the issue pointed out it comes from a situation on Intel processors where
// WaitForSingleObjectA is ignored by a thread, for some (?) reason.
//
// This locks up the game randomly, mostly at the end of rounds or when too many things happen at
// once, due to trying to stop sounds (AIL_Stop_sounds) and playing streams at the same time,
// rushing for the same resource via AIL_lock_mutex.
//
// This bug has been reproduced on mp_terminal, mp_overgrown, mp_rust, with and without bots,
// and so far this has been the only way to circumvent it afaik. This component wraps
// miles' mutex into another mutex, created below, and for some reason (?) that mutex is
// respected when miles' is not.
//
// As soon as a real fix is found, please discard this fix. In the meantime, it should not
// have side effects too bad - worst case it might cause a slight performance drop during
// team switch and intermission.
//
std::mutex SoundMutexFix::SNDMutex;
void __stdcall SoundMutexFix::LockSoundMutex(int unk)
{
std::lock_guard lock(SoundMutexFix::SNDMutex);
DWORD funcPtr = *reinterpret_cast<DWORD*>(0x6D7554); // AIL_close_stream
Utils::Hook::Call<void __stdcall(int)>(funcPtr)(unk);
}
SoundMutexFix::SoundMutexFix()
{
Utils::Hook(0x689EFE, &SoundMutexFix::LockSoundMutex, HOOK_JUMP).install()->quick();
}
}

View File

@ -0,0 +1,15 @@
#pragma once
#include <mutex>
namespace Components
{
class SoundMutexFix : public Component
{
public:
SoundMutexFix();
private:
static std::mutex SNDMutex;
static void _stdcall LockSoundMutex(int unk);
};
}

View File

@ -384,25 +384,25 @@ namespace Steam
Proxy::LaunchWatchGuard();
Proxy::Overlay = ::Utils::Library(GAMEOVERLAY_LIB, false);
if (!Proxy::Overlay.IsValid()) return false;
if (!Proxy::Overlay.isValid()) return false;
}
Proxy::Client = ::Utils::Library(STEAMCLIENT_LIB, false);
if (!Proxy::Client.IsValid()) return false;
if (!Proxy::Client.isValid()) return false;
Proxy::SteamClient = Proxy::Client.Get<ISteamClient008*(const char*, int*)>("CreateInterface")("SteamClient008", nullptr);
Proxy::SteamClient = Proxy::Client.get<ISteamClient008*(const char*, int*)>("CreateInterface")("SteamClient008", nullptr);
if(!Proxy::SteamClient) return false;
Proxy::SteamBGetCallback = Proxy::Client.Get<Proxy::SteamBGetCallbackFn>("Steam_BGetCallback");
Proxy::SteamBGetCallback = Proxy::Client.get<Proxy::SteamBGetCallbackFn>("Steam_BGetCallback");
if (!Proxy::SteamBGetCallback) return false;
Proxy::SteamFreeLastCallback = Proxy::Client.Get<Proxy::SteamFreeLastCallbackFn>("Steam_FreeLastCallback");
Proxy::SteamFreeLastCallback = Proxy::Client.get<Proxy::SteamFreeLastCallbackFn>("Steam_FreeLastCallback");
if (!Proxy::SteamFreeLastCallback) return false;
Proxy::SteamGetAPICallResult = Proxy::Client.Get<Proxy::SteamGetAPICallResultFn>("Steam_GetAPICallResult");
Proxy::SteamGetAPICallResult = Proxy::Client.get<Proxy::SteamGetAPICallResultFn>("Steam_GetAPICallResult");
if (!Proxy::SteamGetAPICallResult) return false;
Proxy::SteamClient = Proxy::Client.Get<ISteamClient008*(const char*, int*)>("CreateInterface")("SteamClient008", nullptr);
Proxy::SteamClient = Proxy::Client.get<ISteamClient008*(const char*, int*)>("CreateInterface")("SteamClient008", nullptr);
if (!Proxy::SteamClient) return false;
Proxy::SteamPipe = Proxy::SteamClient->CreateSteamPipe();
@ -411,7 +411,7 @@ namespace Steam
Proxy::SteamUser = Proxy::SteamClient->ConnectToGlobalUser(Proxy::SteamPipe);
if (!Proxy::SteamUser) return false;
Proxy::ClientEngine = Proxy::Client.Get<IClientEngine*(const char*, int*)>("CreateInterface")("CLIENTENGINE_INTERFACE_VERSION005", nullptr);
Proxy::ClientEngine = Proxy::Client.get<IClientEngine*(const char*, int*)>("CreateInterface")("CLIENTENGINE_INTERFACE_VERSION005", nullptr);
if (!Proxy::ClientEngine) return false;
Proxy::ClientUser = Proxy::ClientEngine->GetIClientUser(Proxy::SteamUser, Proxy::SteamPipe);
@ -526,17 +526,17 @@ namespace Steam
void Proxy::SetOverlayNotificationPosition(uint32_t eNotificationPosition)
{
if (Proxy::Overlay.IsValid())
if (Proxy::Overlay.isValid())
{
Proxy::Overlay.Get<void(uint32_t)>("SetNotificationPosition")(eNotificationPosition);
Proxy::Overlay.get<void(uint32_t)>("SetNotificationPosition")(eNotificationPosition);
}
}
bool Proxy::IsOverlayEnabled()
{
if (Proxy::Overlay.IsValid())
if (Proxy::Overlay.isValid())
{
return Proxy::Overlay.Get<bool()>("IsOverlayEnabled")();
return Proxy::Overlay.get<bool()>("IsOverlayEnabled")();
}
return false;
@ -544,9 +544,9 @@ namespace Steam
bool Proxy::BOverlayNeedsPresent()
{
if (Proxy::Overlay.IsValid())
if (Proxy::Overlay.isValid())
{
return Proxy::Overlay.Get<bool()>("BOverlayNeedsPresent")();
return Proxy::Overlay.get<bool()>("BOverlayNeedsPresent")();
}
return false;

View File

@ -40,23 +40,23 @@ namespace Utils
{
if (this->freeOnDestroy)
{
this->Free();
this->free();
}
}
bool Library::IsValid() const
bool Library::isValid() const
{
return this->_module != nullptr;
}
HMODULE Library::GetModule()
HMODULE Library::getModule()
{
return this->_module;
}
void Library::Free()
void Library::free()
{
if (this->IsValid())
if (this->isValid())
{
FreeLibrary(this->_module);
}

View File

@ -15,48 +15,48 @@ namespace Utils
explicit Library(HMODULE handle);
~Library();
bool IsValid() const;
HMODULE GetModule();
bool isValid() const;
HMODULE getModule();
template <typename T>
T GetProc(const std::string& process) const
T getProc(const std::string& process) const
{
if (!this->IsValid()) T{};
if (!this->isValid()) T{};
return reinterpret_cast<T>(GetProcAddress(this->_module, process.data()));
}
template <typename T>
std::function<T> Get(const std::string& process) const
std::function<T> get(const std::string& process) const
{
if (!this->IsValid()) return std::function<T>();
return static_cast<T*>(this->GetProc<void*>(process));
if (!this->isValid()) return std::function<T>();
return static_cast<T*>(this->getProc<void*>(process));
}
template <typename T, typename... Args>
T Invoke(const std::string& process, Args ... args) const
T invoke(const std::string& process, Args ... args) const
{
auto method = this->Get<T(__cdecl)(Args ...)>(process);
auto method = this->get<T(__cdecl)(Args ...)>(process);
if (method) return method(args...);
return T();
}
template <typename T, typename... Args>
T InvokePascal(const std::string& process, Args ... args) const
T invokePascal(const std::string& process, Args ... args) const
{
auto method = this->Get<T(__stdcall)(Args ...)>(process);
auto method = this->get<T(__stdcall)(Args ...)>(process);
if (method) return method(args...);
return T();
}
template <typename T, typename... Args>
T InvokeThis(const std::string& process, void* this_ptr, Args ... args) const
T invokeThis(const std::string& process, void* this_ptr, Args ... args) const
{
auto method = this->Get<T(__thiscall)(void*, Args ...)>(this_ptr, process);
auto method = this->get<T(__thiscall)(void*, Args ...)>(this_ptr, process);
if (method) return method(args...);
return T();
}
void Free();
void free();
private:
HMODULE _module;