Skip to content

Commit

Permalink
Add bxt_enable_big_map (#500)
Browse files Browse the repository at this point in the history
* Add bxt_enable_big_map

* some more text

* Created delta.h for delta structures

* Corrected description of Cmd_BXT_Enable_Big_Map

* Make IsInWorld function more flexible to use

* Store flags for some features enabled to BXT runtime data

* Update BunnymodXT/modules/ServerDLL.cpp

i love github

Co-authored-by: Ivan Molodetskikh <[email protected]>

* Update BunnymodXT/modules/HwDLL.cpp

i love github

Co-authored-by: Ivan Molodetskikh <[email protected]>

---------

Co-authored-by: SmileyAG <[email protected]>
Co-authored-by: Ivan Molodetskikh <[email protected]>
  • Loading branch information
3 people authored Feb 8, 2024
1 parent 1196334 commit a0cc469
Show file tree
Hide file tree
Showing 10 changed files with 277 additions and 3 deletions.
76 changes: 76 additions & 0 deletions BunnymodXT/modules/HwDLL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -872,6 +872,8 @@ void HwDLL::Clear()

tas_studio_norefresh_override = 0;

g_sv_delta = nullptr;

if (resetState == ResetState::NORMAL) {
input.Clear();
ResetTASPlaybackState();
Expand Down Expand Up @@ -1314,6 +1316,12 @@ void HwDLL::FindStuff()
} else {
EngineDevWarning("[hw dll] Could not find R_SetFrustum.\n");
}

g_sv_delta = reinterpret_cast<void**>(MemUtils::GetSymbolAddress(m_Handle, "g_sv_delta"));
if (g_sv_delta)
EngineDevMsg("[hw dll] Found g_sv_delta at %p.\n", g_sv_delta);
else
EngineDevWarning("[hw dll] Could not find g_sv_delta.\n");
}
else
{
Expand Down Expand Up @@ -2017,6 +2025,20 @@ void HwDLL::FindStuff()
}
});

void *SV_LookupDelta;
auto fSV_LookupDelta = FindAsync(
SV_LookupDelta,
patterns::engine::SV_LookupDelta,
[&](auto pattern) {
switch (pattern - patterns::engine::SV_LookupDelta.cbegin())
{
default:
case 0: // HL-SteamPipe.
g_sv_delta = *reinterpret_cast<void***>(reinterpret_cast<uintptr_t>(SV_LookupDelta) + 6);
break;
}
});

{
auto pattern = fClientDLL_CheckStudioInterface.get();
if (ClientDLL_CheckStudioInterface) {
Expand Down Expand Up @@ -2293,6 +2315,17 @@ void HwDLL::FindStuff()
}
}

{
auto pattern = fSV_LookupDelta.get();
if (SV_LookupDelta) {
EngineDevMsg("[hw dll] Found SV_LookupDelta at %p (using the %s pattern).\n", SV_LookupDelta, pattern->name());
EngineDevMsg("[hw dll] Found g_sv_delta at %p.\n", g_sv_delta);
} else {
EngineDevWarning("[hw dll] Could not find SV_LookupDelta.\n");
EngineWarning("[hw dll] Loading big maps on the fly is not available.\n");
}
}

#define GET_FUTURE(future_name) \
{ \
auto pattern = f##future_name.get(); \
Expand Down Expand Up @@ -5205,6 +5238,43 @@ struct HwDLL::Cmd_BXT_Skybox_Reload
}
};

void ChangeDeltaForBigMap(delta_s *delta)
{
for (int i = 0; i < delta->fieldCount; ++i) {
delta_description_s *curr_description = delta->pdd + i;
// "origin[0]", "origin[1]", ... so comparing "origin" is enough
if (!strncmp(curr_description->fieldName, "origin", 6)) {
auto curr_map_size = (1 << curr_description->significant_bits) / curr_description->premultiply;
if (curr_map_size < BIG_MAP_SIZE) {
curr_description->significant_bits = (int) std::ceil(std::log(BIG_MAP_SIZE * 2.0f * curr_description->premultiply) / std::log(2));
}
}
}
}

struct HwDLL::Cmd_BXT_Enable_Big_Map
{
USAGE("\
Usage: bxt_enable_big_map\n\n\
After entering this command in main menu, you can load maps beyond +-4096 limit.\n\
Due to shortcomings of the implementation, you must restart your game in order to revert the effect.\n\
Can be called as a command line argument when starting up the game.\n");

static void handler()
{
auto &hw = HwDLL::GetInstance();

if (hw.g_sv_delta == NULL)
hw.ORIG_Con_Printf("Feature is not supported.\n");
else {
hw.ORIG_Con_Printf("Big map support enabled.\nCurrent maximum map size is +-%d\n", BIG_MAP_SIZE);
hw.is_big_map = true;
for (delta_info_s *curr_delta = *reinterpret_cast<delta_info_s**>(hw.g_sv_delta); curr_delta != NULL && curr_delta->delta != NULL; curr_delta = curr_delta->next)
ChangeDeltaForBigMap(curr_delta->delta);
}
}
};

extern "C" DLLEXPORT void bxt_tas_load_script_from_string(const char *script)
{
auto& hw = HwDLL::GetInstance();
Expand Down Expand Up @@ -5600,6 +5670,7 @@ void HwDLL::RegisterCVarsAndCommandsIfNeeded()
wrapper::Add<Cmd_BXT_Splits_Track_Z, Handler<int>, Handler<const char*, int>>("bxt_splits_track_z");
wrapper::Add<Cmd_BXT_Splits_Place_Down, Handler<>, Handler<const char*>>("+bxt_splits_place");
wrapper::Add<Cmd_BXT_Splits_Place_Up, Handler<>, Handler<const char*>>("-bxt_splits_place");
wrapper::Add<Cmd_BXT_Enable_Big_Map, Handler<>>("bxt_enable_big_map");
}

void HwDLL::InsertCommands()
Expand Down Expand Up @@ -7201,6 +7272,11 @@ HOOK_DEF_1(HwDLL, int, __cdecl, Host_FilterTime, float, passedTime)
RuntimeData::Add(RuntimeData::PlayerHealth{playerhealth});

lastRecordedHealth = playerhealth;

int bxt_flags = 0;
if (is_big_map)
bxt_flags |= BXT_FLAGS_BIG_MAP;
RuntimeData::Add(RuntimeData::Flags{bxt_flags});
}

if (runningFrames) {
Expand Down
8 changes: 8 additions & 0 deletions BunnymodXT/modules/HwDLL.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "../cvars.hpp"
#include "taslogger/writer.hpp"
#include "../input_editor.hpp"
#include "../shared.hpp"

enum class TASEditorMode {
DISABLED,
Expand Down Expand Up @@ -534,6 +535,7 @@ class HwDLL : public IHookableNameFilterOrdered
struct Cmd_Minus_BXT_CH_Hook;
struct Cmd_BXT_CH_CheckPoint_Create;
struct Cmd_BXT_CH_CheckPoint_GoTo;
struct Cmd_BXT_Enable_Big_Map;

void RegisterCVarsAndCommandsIfNeeded();
void InsertCommands();
Expand Down Expand Up @@ -783,4 +785,10 @@ class HwDLL : public IHookableNameFilterOrdered
Vector ch_checkpoint_vel;
Vector ch_checkpoint_viewangles;
bool ch_checkpoint_is_duck;

public:
bool is_big_map = false;

protected:
void **g_sv_delta;
};
78 changes: 76 additions & 2 deletions BunnymodXT/modules/ServerDLL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "../runtime_data.hpp"
#include "../custom_triggers.hpp"
#include "../splits.hpp"
#include "../shared.hpp"

// Linux hooks.
#ifndef _WIN32
Expand Down Expand Up @@ -90,6 +91,11 @@ extern "C" Vector __cdecl _ZN11CBaseEntity17FireBulletsPlayerEj6VectorS0_S0_fiii
{
return ServerDLL::HOOKED_CBaseEntity__FireBulletsPlayer_Linux(thisptr, cShots, vecSrc, vecDirShooting, vecSpread, flDistance, iBulletType, iTracerFreq, iDamage, pevAttacker, shared_rand);
}

extern "C" int __cdecl _ZN11CBaseEntity9IsInWorldEv(void *thisptr)
{
return ServerDLL::HOOKED_CBaseEntity__IsInWorld_Linux(thisptr);
}
#endif

void ServerDLL::Hook(const std::wstring& moduleName, void* moduleHandle, void* moduleBase, size_t moduleLength, bool needToIntercept)
Expand Down Expand Up @@ -150,7 +156,9 @@ void ServerDLL::Hook(const std::wstring& moduleName, void* moduleHandle, void* m
ORIG_CTriggerEndSection__EndSectionTouch, HOOKED_CTriggerEndSection__EndSectionTouch,
ORIG_ShiftMonsters, HOOKED_ShiftMonsters,
ORIG_PM_Duck, HOOKED_PM_Duck,
ORIG_PM_UnDuck, HOOKED_PM_UnDuck);
ORIG_PM_UnDuck, HOOKED_PM_UnDuck,
ORIG_CBaseEntity__IsInWorld, HOOKED_CBaseEntity__IsInWorld,
ORIG_CBaseEntity__IsInWorld_Linux, HOOKED_CBaseEntity__IsInWorld_Linux);
}
}

Expand Down Expand Up @@ -201,7 +209,9 @@ void ServerDLL::Unhook()
ORIG_CTriggerEndSection__EndSectionTouch,
ORIG_ShiftMonsters,
ORIG_PM_Duck,
ORIG_PM_UnDuck);
ORIG_PM_UnDuck,
ORIG_CBaseEntity__IsInWorld,
ORIG_CBaseEntity__IsInWorld_Linux);
}

Clear();
Expand Down Expand Up @@ -272,6 +282,8 @@ void ServerDLL::Clear()
ORIG_ShiftMonsters = nullptr;
ORIG_PM_Duck = nullptr;
ORIG_PM_UnDuck = nullptr;
ORIG_CBaseEntity__IsInWorld = nullptr;
ORIG_CBaseEntity__IsInWorld_Linux = nullptr;
ppmove = nullptr;
offPlayerIndex = 0;
offOldbuttons = 0;
Expand Down Expand Up @@ -809,6 +821,7 @@ void ServerDLL::FindStuff()
auto fCBasePlayer__ViewPunch = FindAsync(ORIG_CBasePlayer__ViewPunch, patterns::server::CBasePlayer__ViewPunch);
auto fCBasePlayer__Jump = FindAsync(ORIG_CBasePlayer__Jump, patterns::server::CBasePlayer__Jump);
auto fCBaseDoor__DoorActivate = FindAsync(ORIG_CBaseDoor__DoorActivate, patterns::server::CBaseDoor__DoorActivate);
auto fCBaseEntity__IsInWorld = FindAsync(ORIG_CBaseEntity__IsInWorld, patterns::server::CBaseEntity__IsInWorld);

uintptr_t pDispatchRestore;
auto fDispatchRestore = FindAsync(
Expand Down Expand Up @@ -1566,6 +1579,19 @@ void ServerDLL::FindStuff()
}
}

{
auto pattern = fCBaseEntity__IsInWorld.get();
if (ORIG_CBaseEntity__IsInWorld) {
EngineDevMsg("[server dll] Found CBaseEntity::IsInWorld at %p (using the %s pattern).\n", ORIG_CBaseEntity__IsInWorld, pattern->name());
} else {
ORIG_CBaseEntity__IsInWorld_Linux = reinterpret_cast<_CBaseEntity__IsInWorld_Linux>(MemUtils::GetSymbolAddress(m_Handle, "_ZN11CBaseEntity9IsInWorldEv"));
if (ORIG_CBaseEntity__IsInWorld_Linux)
EngineDevMsg("[server dll] Found CBaseEntity::IsInWorld [Linux] at %p.\n", ORIG_CBaseEntity__IsInWorld_Linux);
else
EngineDevWarning("[server dll] Could not find CBaseEntity::IsInWorld.\n");
}
}

if (!pEngfuncs)
{
pEngfuncs = reinterpret_cast<enginefuncs_t*>(MemUtils::GetSymbolAddress(m_Handle, "g_engfuncs"));
Expand Down Expand Up @@ -3247,3 +3273,51 @@ HOOK_DEF_1(ServerDLL, void, __fastcall, CBasePlayer__Jump, void*, thisptr)
ORIG_CBasePlayer__Jump(thisptr);
insideCBasePlayerJump = false;
}

int ServerDLL::IsInWorld(Vector origin, Vector velocity, int map_size) // https://github.com/ValveSoftware/halflife/blob/c7240b965743a53a29491dd49320c88eecf6257b/dlls/cbase.cpp#L706
{
// Copy pasted from HLSDK, but origin value is changed
// Maybe in the future we should also make velocity check to use sv_maxvelocity value,
// but I don't see any side effect when going beyond it ever

// position
if (origin.x >= map_size) return 0;
if (origin.y >= map_size) return 0;
if (origin.z >= map_size) return 0;
if (origin.x <= -map_size) return 0;
if (origin.y <= -map_size) return 0;
if (origin.z <= -map_size) return 0;
// speed
if (velocity.x >= 2000) return 0;
if (velocity.y >= 2000) return 0;
if (velocity.z >= 2000) return 0;
if (velocity.x <= -2000) return 0;
if (velocity.y <= -2000) return 0;
if (velocity.z <= -2000) return 0;

return 1;
}

HOOK_DEF_1(ServerDLL, int, __fastcall, CBaseEntity__IsInWorld, void*, thisptr)
{
if (HwDLL::GetInstance().is_big_map)
{
entvars_t *pev = *reinterpret_cast<entvars_t**>(reinterpret_cast<uintptr_t>(thisptr) + 4);
if (pev)
return IsInWorld(pev->origin, pev->velocity, BIG_MAP_SIZE);
}

return ORIG_CBaseEntity__IsInWorld(thisptr);
}

HOOK_DEF_1(ServerDLL, int, __cdecl, CBaseEntity__IsInWorld_Linux, void*, thisptr)
{
if (HwDLL::GetInstance().is_big_map)
{
entvars_t *pev = *reinterpret_cast<entvars_t**>(reinterpret_cast<uintptr_t>(thisptr) + 4);
if (pev)
return IsInWorld(pev->origin, pev->velocity, BIG_MAP_SIZE);
}

return ORIG_CBaseEntity__IsInWorld_Linux(thisptr);
}
4 changes: 4 additions & 0 deletions BunnymodXT/modules/ServerDLL.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ class ServerDLL : public IHookableDirFilter
HOOK_DECL(void, __fastcall, CBasePlayer__ViewPunch, void* thisptr, int edx, float p, float y, float r)
HOOK_DECL(void, __fastcall, CBasePlayer__Jump, void* thisptr)
HOOK_DECL(void, __fastcall, CTriggerCamera__FollowTarget, void* thisptr)
HOOK_DECL(int, __fastcall, CBaseEntity__IsInWorld, void* thisptr)
HOOK_DECL(int, __cdecl, CBaseEntity__IsInWorld_Linux, void* thisptr)

public:
static ServerDLL& GetInstance()
Expand Down Expand Up @@ -106,6 +108,8 @@ class ServerDLL : public IHookableDirFilter

void SetStamina(bool makeItZero);

int IsInWorld(Vector origin, Vector velocity, int map_size);

bool is_cof = false; // Cry of Fear-specific
ptrdiff_t offm_fStamina; // Cry of Fear-specific

Expand Down
9 changes: 9 additions & 0 deletions BunnymodXT/patterns.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -792,6 +792,10 @@ namespace patterns
"CoF-5936",
"55 8B EC A1 ?? ?? ?? ?? 3B 05 ?? ?? ?? ?? 75 ?? EB ?? 8B 0D ?? ?? ?? ?? 89 0D ?? ?? ?? ?? E8"
);

PATTERNS(SV_LookupDelta,
"HL-SteamPipe",
"55 8B EC 56 8B 35 ?? ?? ?? ?? 57 8B 7D ?? 85 F6 74 ?? 8B 46 ?? 50 57 E8 ?? ?? ?? ?? 83 C4 08 85 C0 74 ?? 8B 36 85 F6 75 ?? 57")
}

namespace server
Expand Down Expand Up @@ -1158,6 +1162,11 @@ namespace patterns
"CoF-5936",
"55 8B EC 83 EC 0C 56 8B F1 8B 0D"
);

PATTERNS(CBaseEntity__IsInWorld,
"HL-SteamPipe",
"8B 49 04 D9 41 08 D8 1D ?? ?? ?? ?? DF E0"
);
}

namespace client
Expand Down
14 changes: 14 additions & 0 deletions BunnymodXT/runtime_data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ namespace RuntimeData
EDICTS,
PLAYERHEALTH,
SPLIT_MARKER,
FLAGS,
};

// Encrypting filter.
Expand Down Expand Up @@ -358,6 +359,12 @@ namespace RuntimeData
archive(m.map_name);
}

void operator()(const Flags& f) const {
archive(RuntimeDataType::FLAGS);

archive(f.flags);
}

private:
Archive& archive;
};
Expand Down Expand Up @@ -474,6 +481,12 @@ namespace RuntimeData
data = m;
break;
}
case RuntimeDataType::FLAGS: {
Flags f;
archive(f.flags);
data = f;
break;
}
default: {
EngineDevWarning("Read unknown RuntimeDataType %d\n", data_type);
break;
Expand Down Expand Up @@ -538,6 +551,7 @@ namespace RuntimeData
void operator()(const RuntimeData::CustomTriggerCommand& c) const {}
void operator()(const RuntimeData::Edicts& e) const {}
void operator()(const RuntimeData::SplitMarker& m) const {}
void operator()(const RuntimeData::Flags& f) const {}

private:
// bxt commands that should be executed when found during demo playback
Expand Down
7 changes: 6 additions & 1 deletion BunnymodXT/runtime_data.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ namespace RuntimeData
std::string map_name;
};

struct Flags {
int flags;
};

using Data = boost::variant<VersionInfo,
CVarValues,
Time,
Expand All @@ -75,7 +79,8 @@ namespace RuntimeData
CustomTriggerCommand,
Edicts,
PlayerHealth,
SplitMarker>;
SplitMarker,
Flags>;

void Add(Data data);
void Clear();
Expand Down
4 changes: 4 additions & 0 deletions BunnymodXT/shared.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,7 @@ enum class EventType : unsigned char {

#define MQ_NAME "BunnymodXT-TASView"
#define BUNNYSPLIT_PIPE_NAME "BunnymodXT-BunnySplit"

#define BIG_MAP_SIZE 32768 // +-BIG_MAP_SIZE so 64k x 64k map should have value of 32k

#define BXT_FLAGS_BIG_MAP (1<<0)
Loading

0 comments on commit a0cc469

Please sign in to comment.