Skip to content

Commit

Permalink
Merge branch 'master' into radar-jpg-update
Browse files Browse the repository at this point in the history
  • Loading branch information
Dutchman101 authored Nov 21, 2024
2 parents 6b82b56 + a4b4318 commit 1a41f4e
Show file tree
Hide file tree
Showing 33 changed files with 466 additions and 113 deletions.
28 changes: 28 additions & 0 deletions Client/game_sa/CGameSA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -848,6 +848,34 @@ void CGameSA::SetRoadSignsTextEnabled(bool isEnabled)
m_isRoadSignsTextEnabled = isEnabled;
}

void CGameSA::SetIgnoreFireStateEnabled(bool isEnabled)
{
if (isEnabled == m_isIgnoreFireStateEnabled)
return;

if (isEnabled)
{
MemSet((void*)0x6511B9, 0x90, 10); // CCarEnterExit::IsVehicleStealable
MemSet((void*)0x643A95, 0x90, 14); // CTaskComplexEnterCar::CreateFirstSubTask
MemSet((void*)0x6900B5, 0x90, 14); // CTaskComplexCopInCar::ControlSubTask
MemSet((void*)0x64F3DB, 0x90, 14); // CCarEnterExit::IsPlayerToQuitCarEnter

MemSet((void*)0x685A7F, 0x90, 14); // CTaskSimplePlayerOnFoot::ProcessPlayerWeapon
}
else
{
// Restore original bytes
MemCpy((void*)0x6511B9, "\x88\x86\x90\x04\x00\x00\x85\xC0\x75\x3E", 10);
MemCpy((void*)0x643A95, "\x8B\x88\x90\x04\x00\x00\x85\xC9\x0F\x85\x99\x01\x00\x00", 14);
MemCpy((void*)0x6900B5, "\x8B\x81\x90\x04\x00\x00\x85\xC0\x0F\x85\x1A\x01\x00\x00", 14);
MemCpy((void*)0x64F3DB, "\x8B\x85\x90\x04\x00\x00\x85\xC0\x0F\x85\x1B\x01\x00\x00", 14);

MemCpy((void*)0x685A7F, "\x8B\x86\x30\x07\x00\x00\x85\xC0\x0F\x85\x1D\x01\x00\x00", 14);
}

m_isIgnoreFireStateEnabled = isEnabled;
}

bool CGameSA::PerformChecks()
{
std::map<std::string, SCheatSA*>::iterator it;
Expand Down
3 changes: 3 additions & 0 deletions Client/game_sa/CGameSA.h
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,8 @@ class CGameSA : public CGame
bool IsTunnelWeatherBlendEnabled() const noexcept override { return m_isTunnelWeatherBlendEnabled; }
void SetTunnelWeatherBlendEnabled(bool isEnabled) override;

bool IsIgnoreFireStateEnabled() const noexcept override { return m_isIgnoreFireStateEnabled; }
void SetIgnoreFireStateEnabled(bool isEnabled) override;

unsigned long GetMinuteDuration();
void SetMinuteDuration(unsigned long ulTime);
Expand Down Expand Up @@ -378,6 +380,7 @@ class CGameSA : public CGame
bool m_isRoadSignsTextEnabled{true};
bool m_isBuildingsRemoved{false};
bool m_isExtendedWaterCannonsEnabled{false};
bool m_isIgnoreFireStateEnabled{false};

static unsigned int& ClumpOffset;

Expand Down
8 changes: 7 additions & 1 deletion Client/mods/deathmatch/logic/CClientGame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ CClientGame::CClientGame(bool bLocalPlay) : m_ServerInfo(new CServerInfo())
m_Glitches[GLITCH_BADDRIVEBYHITBOX] = false;
m_Glitches[GLITCH_QUICKSTAND] = false;
m_Glitches[GLITCH_KICKOUTOFVEHICLE_ONMODELREPLACE] = false;

g_pMultiplayer->DisableBadDrivebyHitboxes(true);

// Remove Night & Thermal vision view (if enabled).
Expand Down Expand Up @@ -6025,6 +6026,9 @@ bool CClientGame::SetWorldSpecialProperty(WorldSpecialProperty property, bool is
case WorldSpecialProperty::TUNNELWEATHERBLEND:
g_pGame->SetTunnelWeatherBlendEnabled(isEnabled);
return true;
case WorldSpecialProperty::IGNOREFIRESTATE:
g_pGame->SetIgnoreFireStateEnabled(isEnabled);
return true;
}
return false;
}
Expand Down Expand Up @@ -6062,6 +6066,8 @@ bool CClientGame::IsWorldSpecialProperty(WorldSpecialProperty property)
return g_pGame->IsRoadSignsTextEnabled();
case WorldSpecialProperty::TUNNELWEATHERBLEND:
return g_pGame->IsTunnelWeatherBlendEnabled();
case WorldSpecialProperty::IGNOREFIRESTATE:
return g_pGame->IsIgnoreFireStateEnabled();
}
return false;
}
Expand Down Expand Up @@ -6475,7 +6481,7 @@ void CClientGame::OutputServerInfo()
{
SString strEnabledGlitches;
const char* szGlitchNames[] = {"Quick reload", "Fast fire", "Fast move", "Crouch bug", "Close damage", "Hit anim", "Fast sprint",
"Bad driveby hitboxes", "Quick stand"};
"Bad driveby hitboxes", "Quick stand", "Kickout of vehicle on model replace"};
for (uint i = 0; i < NUM_GLITCHES; i++)
{
if (IsGlitchEnabled(i))
Expand Down
5 changes: 5 additions & 0 deletions Client/mods/deathmatch/logic/CPacketHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,10 @@ void CPacketHandler::Packet_ServerDisconnected(NetBitStreamInterface& bitStream)
strReason = _("Disconnected: Serial verification failed");
strErrorCode = _E("CD44");
break;
case ePlayerDisconnectType::SERIAL_DUPLICATE:
strReason = _("Disconnected: Serial already in use");
strErrorCode = _E("CD50");
break;
case ePlayerDisconnectType::CONNECTION_DESYNC:
strReason = _("Disconnected: Connection desync %s");
strErrorCode = _E("CD45");
Expand Down Expand Up @@ -2393,6 +2397,7 @@ void CPacketHandler::Packet_MapInfo(NetBitStreamInterface& bitStream)
g_pClientGame->SetWorldSpecialProperty(WorldSpecialProperty::ROADSIGNSTEXT, wsProps.data3.roadsignstext);
g_pClientGame->SetWorldSpecialProperty(WorldSpecialProperty::EXTENDEDWATERCANNONS, wsProps.data4.extendedwatercannons);
g_pClientGame->SetWorldSpecialProperty(WorldSpecialProperty::TUNNELWEATHERBLEND, wsProps.data5.tunnelweatherblend);
g_pClientGame->SetWorldSpecialProperty(WorldSpecialProperty::IGNOREFIRESTATE, wsProps.data6.ignoreFireState);

float fJetpackMaxHeight = 100;
if (!bitStream.Read(fJetpackMaxHeight))
Expand Down
3 changes: 2 additions & 1 deletion Client/mods/deathmatch/logic/CPacketHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ class CPacketHandler
BAN,
KICK,
CUSTOM,
SHUTDOWN
SHUTDOWN,
SERIAL_DUPLICATE
};

struct SEntityDependantStuff
Expand Down
2 changes: 2 additions & 0 deletions Client/mods/deathmatch/logic/rpc/CWorldRPCs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,8 @@ void CWorldRPCs::SetSyncIntervals(NetBitStreamInterface& bitStream)
bitStream.Read(g_TickRateSettings.iObjectSync);
bitStream.Read(g_TickRateSettings.iKeySyncRotation);
bitStream.Read(g_TickRateSettings.iKeySyncAnalogMove);
bitStream.Read(g_TickRateSettings.iPedSyncerDistance);
bitStream.Read(g_TickRateSettings.iUnoccupiedVehicleSyncerDistance);
}

void CWorldRPCs::SetMoonSize(NetBitStreamInterface& bitStream)
Expand Down
2 changes: 2 additions & 0 deletions Client/multiplayer_sa/CMultiplayerSA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1574,6 +1574,7 @@ void CMultiplayerSA::InitHooks()
MemSet((void*)0x6C4453, 0x90, 0x68);

InitHooks_CrashFixHacks();
InitHooks_DeviceSelection();

// Init our 1.3 hooks.
Init_13();
Expand Down Expand Up @@ -1861,6 +1862,7 @@ void CMultiplayerSA::DisableCloseRangeDamage(bool bDisabled)
MemPut<BYTE>(0x73BA00, 0x86);
}
}

bool CMultiplayerSA::GetInteriorSoundsEnabled()
{
return bInteriorSoundsEnabled;
Expand Down
1 change: 1 addition & 0 deletions Client/multiplayer_sa/CMultiplayerSA.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ class CMultiplayerSA : public CMultiplayer
void InitHooks_ProjectileCollisionFix();
void InitHooks_ObjectStreamerOptimization();
void InitHooks_Postprocess();
void InitHooks_DeviceSelection();
CRemoteDataStorage* CreateRemoteDataStorage();
void DestroyRemoteDataStorage(CRemoteDataStorage* pData);
void AddRemoteDataStorage(CPlayerPed* pPed, CRemoteDataStorage* pData);
Expand Down
155 changes: 155 additions & 0 deletions Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
/*****************************************************************************
*
* PROJECT: Multi Theft Auto v1.0
* LICENSE: See LICENSE in the top level directory
* FILE: multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp
*
* Multi Theft Auto is available from http://www.multitheftauto.com/
*
*****************************************************************************/

#include "StdInc.h"
#define FUNC_rwDeviceSystemRequest 0x7F2AB0
#define FUNC_DialogFunc 0x745E50
#define FUNC_RwEngineGetSubSystemInfo 0x7F2C30
#define CLASS_RwGlobals 0xC97B24
#define CLASS_IDirect3D9 0xC97C20
#define NUM_DialogFuncStackPushAddress 0x746239

// This is copied from SilentPatch:
// https://github.com/CookiePLMonster/SilentPatch/blob/dev/SilentPatch/FriendlyMonitorNames.cpp
std::unordered_map<std::string, std::string> GetFriendlyMonitorNamesForDevicePaths()
{
std::unordered_map<std::string, std::string> monitorNames;

HMODULE user32Lib = LoadLibrary(TEXT("user32"));
if (!user32Lib)
return monitorNames;

auto* getDisplayConfigBufferSizes = (decltype(GetDisplayConfigBufferSizes)*)GetProcAddress(user32Lib, "GetDisplayConfigBufferSizes");
auto* queryDisplayConfig = (decltype(QueryDisplayConfig)*)GetProcAddress(user32Lib, "QueryDisplayConfig");
auto* displayConfigGetDeviceInfo = (decltype(DisplayConfigGetDeviceInfo)*)GetProcAddress(user32Lib, "DisplayConfigGetDeviceInfo");
if (!getDisplayConfigBufferSizes || !queryDisplayConfig || !displayConfigGetDeviceInfo)
{
FreeLibrary(user32Lib);
return monitorNames;
}

UINT32 pathCount, modeCount;
std::unique_ptr<DISPLAYCONFIG_PATH_INFO[]> paths;
std::unique_ptr<DISPLAYCONFIG_MODE_INFO[]> modes;

LONG result = ERROR_SUCCESS;
do
{
result = getDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &pathCount, &modeCount);
if (result != ERROR_SUCCESS)
{
break;
}
paths = std::make_unique<DISPLAYCONFIG_PATH_INFO[]>(pathCount);
modes = std::make_unique<DISPLAYCONFIG_MODE_INFO[]>(modeCount);
result = queryDisplayConfig(QDC_ONLY_ACTIVE_PATHS, &pathCount, paths.get(), &modeCount, modes.get(), nullptr);
} while (result == ERROR_INSUFFICIENT_BUFFER);

if (result != ERROR_SUCCESS)
{
FreeLibrary(user32Lib);
return monitorNames;
}

for (size_t i = 0; i < pathCount; i++)
{
DISPLAYCONFIG_TARGET_DEVICE_NAME targetName = {};
targetName.header.adapterId = paths[i].targetInfo.adapterId;
targetName.header.id = paths[i].targetInfo.id;
targetName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME;
targetName.header.size = sizeof(targetName);
const LONG targetNameResult = DisplayConfigGetDeviceInfo(&targetName.header);

DISPLAYCONFIG_SOURCE_DEVICE_NAME sourceName = {};
sourceName.header.adapterId = paths[i].sourceInfo.adapterId;
sourceName.header.id = paths[i].sourceInfo.id;
sourceName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME;
sourceName.header.size = sizeof(sourceName);
const LONG sourceNameResult = DisplayConfigGetDeviceInfo(&sourceName.header);
if (targetNameResult == ERROR_SUCCESS && sourceNameResult == ERROR_SUCCESS && targetName.monitorFriendlyDeviceName[0] != '\0')
{
char gdiDeviceName[std::size(sourceName.viewGdiDeviceName)];
char monitorFriendlyDeviceName[std::size(targetName.monitorFriendlyDeviceName)];
WideCharToMultiByte(CP_ACP, 0, sourceName.viewGdiDeviceName, -1, gdiDeviceName, static_cast<int>(std::size(gdiDeviceName)), nullptr, nullptr);
WideCharToMultiByte(CP_ACP, 0, targetName.monitorFriendlyDeviceName, -1, monitorFriendlyDeviceName,
static_cast<int>(std::size(monitorFriendlyDeviceName)), nullptr, nullptr);

monitorNames.try_emplace(gdiDeviceName, monitorFriendlyDeviceName);
}
}

FreeLibrary(user32Lib);
return monitorNames;
}

struct RwSubSystemInfo
{
char name[80];
};

using rwDeviceSystemRequest = RwSubSystemInfo*(__cdecl*)(RwDevice* device, std::int32_t requestId, RwSubSystemInfo* pOut, void* pInOut, std::int32_t numIn);
static RwSubSystemInfo* RwEngineGetSubSystemInfo_Hooked(RwSubSystemInfo* subSystemInfo, std::int32_t subSystemIndex)
{
auto* rwGlobals = *(RwGlobals**)CLASS_RwGlobals;
auto* rwDeviceSystemRequestFunc = (rwDeviceSystemRequest)(FUNC_rwDeviceSystemRequest);
if (!rwDeviceSystemRequestFunc(&rwGlobals->dOpenDevice, 14, subSystemInfo, nullptr, subSystemIndex))
return nullptr;

auto* pDxDevice = *(IDirect3D9**)CLASS_IDirect3D9;
if (!pDxDevice)
return subSystemInfo;

D3DADAPTER_IDENTIFIER9 identifier;
if (FAILED(pDxDevice->GetAdapterIdentifier(subSystemIndex, 0, &identifier)))
return subSystemInfo;

static const auto friendlyNames = GetFriendlyMonitorNamesForDevicePaths();

// If we can't find the friendly name, either because it doesn't exist or we're on an ancient Windows, fall back to the device name
auto it = friendlyNames.find(identifier.DeviceName);
if (it != friendlyNames.end())
{
strncpy_s(subSystemInfo->name, it->second.c_str(), _TRUNCATE);
}
else
{
strncpy_s(subSystemInfo->name, identifier.Description, _TRUNCATE);
}

return subSystemInfo;
}

INT_PTR CALLBACK CustomDlgProc(HWND window, UINT msg, WPARAM wParam, LPARAM lParam)
{
auto* orgDialogFunc = (DLGPROC)FUNC_DialogFunc;
if (msg != WM_INITDIALOG)
return orgDialogFunc(window, msg, wParam, lParam);

orgDialogFunc(window, msg, wParam, lParam);

// Set Icon
HMODULE hGameModule = GetModuleHandle(nullptr);
SendMessage(window, WM_SETICON, ICON_SMALL, reinterpret_cast<LPARAM>(LoadIcon(hGameModule, MAKEINTRESOURCE(100))));

// Make the dialog visible in the task bar
// https://stackoverflow.com/a/1462811
SetWindowLongPtr(window, GWL_EXSTYLE, WS_EX_APPWINDOW);
ShowWindow(window, SW_HIDE);
ShowWindow(window, SW_SHOW);
return FALSE;
}

void CMultiplayerSA::InitHooks_DeviceSelection()
{
// 0x746239 -> Exact address where the original DialogFunc address is being pushed as an argument to DialogBoxParamA(),
// we're replacing it with out own proxy function
MemPut<DLGPROC>(NUM_DialogFuncStackPushAddress, (DLGPROC)&CustomDlgProc);
HookInstall(FUNC_RwEngineGetSubSystemInfo, (DWORD)RwEngineGetSubSystemInfo_Hooked, 6);
}
3 changes: 3 additions & 0 deletions Client/sdk/game/CGame.h
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,9 @@ class __declspec(novtable) CGame
virtual bool IsTunnelWeatherBlendEnabled() const noexcept = 0;
virtual void SetTunnelWeatherBlendEnabled(bool isEnabled) = 0;

virtual bool IsIgnoreFireStateEnabled() const noexcept = 0;
virtual void SetIgnoreFireStateEnabled(bool isEnabled) = 0;

virtual CWeapon* CreateWeapon() = 0;
virtual CWeaponStat* CreateWeaponStat(eWeaponType weaponType, eWeaponSkill weaponSkill) = 0;

Expand Down
46 changes: 46 additions & 0 deletions Client/sdk/game/RenderWare.h
Original file line number Diff line number Diff line change
Expand Up @@ -526,3 +526,49 @@ struct RwError
{
int err1, err2;
};

/*****************************************************************************/
/** RenderWare Globals **/
/*****************************************************************************/

typedef bool (*RwSystemFunc)(std::int32_t, void*, void*, std::int32_t);
struct RwDevice
{
float gammaCorrection;
RwSystemFunc fpSystem;
float zBufferNear;
float zBufferFar;
// RwRenderStateSetFunction fpRenderStateSet;
// RwRenderStateGetFunction fpRenderStateGet;
// RwIm2DRenderLineFunction fpIm2DRenderLine;
// RwIm2DRenderTriangleFunction fpIm2DRenderTriangle;
// RwIm2DRenderPrimitiveFunction fpIm2DRenderPrimitive;
// RwIm2DRenderIndexedPrimitiveFunction fpIm2DRenderIndexedPrimitive;
// RwIm3DRenderLineFunction fpIm3DRenderLine;
// RwIm3DRenderTriangleFunction fpIm3DRenderTriangle;
// RwIm3DRenderPrimitiveFunction fpIm3DRenderPrimitive;
// RwIm3DRenderIndexedPrimitiveFunction fpIm3DRenderIndexedPrimitive;
};
// static_assert(sizeof(RwDevice) == 0x38, "Incorrect class size: RwDevice");

typedef bool (*RwStandardFunc)(void*, void*, std::int32_t);
struct RwGlobals
{
void* curCamera;
void* curWorld;
std::uint16_t renderFrame;
std::uint16_t lightFrame;
std::uint16_t pad[2];
RwDevice dOpenDevice;
RwStandardFunc stdFunc[29];
// RwLinkList dirtyFrameList;
// RwFileFunctions fileFuncs;
// RwStringFunctions stringFuncs;
// RwMemoryFunctions memoryFuncs;
// RwMemoryAllocFn memoryAlloc;
// RwMemoryFreeFn memoryFree;
// RwMetrics* metrics;
// RwEngineStatus engineStatus;
// RwUInt32 resArenaInitSize;
};
//static_assert(sizeof(RwGlobals) == 0x158, "Incorrect class size: RwGlobals");
1 change: 1 addition & 0 deletions Server/mods/deathmatch/StdInc.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
#include <bochs_internal/bochs_crc32.h>
#include <pcrecpp.h>
#include <pthread.h>
#include "version.h"

extern class CNetServer* g_pRealNetServer;
extern class CGame* g_pGame;
6 changes: 6 additions & 0 deletions Server/mods/deathmatch/editor.conf
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,12 @@
Values: 0 - Off, 1 - Enabled. Default - 1 -->
<resource_client_file_checks>1</resource_client_file_checks>

<!-- This parameter determines that the server checks when the players connect that there are no other players with the same serial number.
Note that this may break compatibility with virtual machines.
Not guarantees that the player cannot manipulate their serial.
Values: 0 - Off, 1 - Enabled. Default - 1 -->
<check_duplicate_serials>1</check_duplicate_serials>

<!-- Specifies the module(s) which are loaded with the server. To load several modules, add more <module>
parameter(s). Optional parameter. -->
<!-- <module src="sample_win32.dll"/> -->
Expand Down
6 changes: 6 additions & 0 deletions Server/mods/deathmatch/local.conf
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,12 @@
Values: 0 - Off, 1 - Enabled. Default - 0 -->
<elementdata_whitelisted>0</elementdata_whitelisted>

<!-- This parameter determines that the server checks when the players connect that there are no other players with the same serial number.
Note that this may break compatibility with virtual machines.
Not guarantees that the player cannot manipulate their serial.
Values: 0 - Off, 1 - Enabled. Default - 1 -->
<check_duplicate_serials>1</check_duplicate_serials>

<!-- Specifies the module(s) which are loaded with the server. To load several modules, add more <module>
parameter(s). Optional parameter. -->
<!-- <module src="sample_win32.dll"/> -->
Expand Down
Loading

0 comments on commit 1a41f4e

Please sign in to comment.