Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
41 changes: 41 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ Wiki: https://holylib.raphaelit7.com/
\- \- [CGameClient](https://github.com/RaphaelIT7/gmod-holylib#cgameclient)<br>
\- \- [Singleplayer](https://github.com/RaphaelIT7/gmod-holylib#singleplayer)<br>
\- \- [128+ Players](https://github.com/RaphaelIT7/gmod-holylib#128-players)<br>
\- [autorefresh](#autorefresh)<br>

[Unfinished Modules](https://github.com/RaphaelIT7/gmod-holylib#unfinished-modules)<br>
\- [serverplugins](https://github.com/RaphaelIT7/gmod-holylib#serverplugins)<br>
Expand Down Expand Up @@ -4554,6 +4555,46 @@ hook.Add("HolyLib:OnPlayerChangedSlot", "Example", function(oldPlayerSlot, newPl
end)
```

## autorefresh
The Autorefresh module currently provides functionalities regarding the in-built lua file autorefresh system.

Supports: Linux32 | LINUX64

### Functions
#### autorefresh.DenyLuaAutoRefresh(string filePath, bool shouldDeny)
Prevents certain Lua files from being autorefreshed. Accepts a string of the relative file path and a bool indicating whether to block or allow the autorefresh.
- `true` - denies the autorefresh
- `false` - allows the autorefresh
```lua
local pathToFile = "lua/test-dir/test.lua"
autorefresh.DenyLuaAutoRefresh(pathToFile, true)
```

### Hooks
#### bool HolyLib:PreLuaAutoRefresh(string filePath, string fileName)
Called before a Lua file is being refreshed. If `true` is returned it will deny the refresh of the lua file.
- string filePath — is the filePath provided relative to the garrysmod folder
- string filename — is the filename without the extension
```lua
hook.Add("HolyLib:PreLuaAutoRefresh", "ExamplePreAutoRefresh", function(filePath, fileName)
print("[BEFORE] FileChanged: " .. filePath .. filename)

if filename == "bogos" then
print("Denying Refresh")
return true -- prevent refresh
end
end)
```

#### HolyLib:PostLuaAutoRefresh(string filePath, string fileName)
Called after a Lua file is refreshed.
Note that if a refresh is being denied by PreLuaAutorefresh or DenyLuaAutoRefresh, this hook won't be called.
```lua
hook.Add("HolyLib:PostLuaAutoRefresh", "ExamplePostAutoRefresh", function(filePath, fileName)
print("[AFTER] FileChanged: " .. filePath .. filename)
end)
```

# Unfinished Modules

## serverplugins
Expand Down
120 changes: 120 additions & 0 deletions source/modules/autorefresh.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
#include "module.h"
#include "LuaInterface.h"
#include "lua.h"
#include "detours.h"

#include <unordered_map>

#include "tier0/memdbgon.h"

class CAutoRefreshModule : public IModule
{
public:
virtual void LuaInit(GarrysMod::Lua::ILuaInterface* pLua, bool bServerInit) OVERRIDE;
virtual void LuaShutdown(GarrysMod::Lua::ILuaInterface* pLua) OVERRIDE;
virtual void InitDetour(bool bPreServer) OVERRIDE;
virtual const char* Name() { return "autorefresh"; };
virtual int Compatibility() { return LINUX32 | LINUX64; };
};

CAutoRefreshModule g_pAutoRefreshModule;
IModule* pAutoRefreshModule = &g_pAutoRefreshModule;

static std::unordered_map<std::string, bool> blockedLuaFilesMap = {};
LUA_FUNCTION_STATIC(DenyLuaAutoRefresh)
{
LUA->CheckType(1, GarrysMod::Lua::Type::String);
LUA->CheckType(2, GarrysMod::Lua::Type::Bool);

const char* inputFilePath = LUA->GetString(1);
bool blockStatus = LUA->GetBool(2);
char normalizedPath[260];
V_FixupPathName(normalizedPath, sizeof(normalizedPath), inputFilePath);
blockedLuaFilesMap.insert_or_assign(std::string(normalizedPath), blockStatus);

return 0;
}

static Detouring::Hook detour_CAutoRefresh_HandleChange_Lua;
static bool hook_CAutoRefresh_HandleChange_Lua(const std::string* pfileRelPath, const std::string* pfileName, const std::string* pfileExt)
{
auto trampoline = detour_CAutoRefresh_HandleChange_Lua.GetTrampoline<Symbols::GarrysMod_AutoRefresh_HandleChange_Lua>();
if (!g_Lua || !pfileRelPath || !pfileName || !pfileExt)
{
return trampoline(pfileRelPath, pfileName, pfileExt);
}

if (std::string(pfileExt->substr(0, 3)) != "lua")
{
return trampoline(pfileRelPath, pfileName, pfileExt);
}

bool bDenyRefresh = false;
if (Lua::PushHook("HolyLib:PreLuaAutoRefresh"))
{
g_Lua->PushString(pfileRelPath->c_str());
g_Lua->PushString(pfileName->c_str());

if (g_Lua->CallFunctionProtected(3, 1, true))
{
bDenyRefresh = g_Lua->GetBool(-1);
g_Lua->Pop(1);
}
}

if (!blockedLuaFilesMap.empty() && !bDenyRefresh)
{
char fullPath[260];
V_ComposeFileName(pfileRelPath->c_str(), pfileName->c_str(), fullPath, sizeof(fullPath));
V_SetExtension(fullPath, "lua", sizeof(fullPath));
if (auto fileSearch = blockedLuaFilesMap.find(fullPath); fileSearch != blockedLuaFilesMap.end())
{
bDenyRefresh = fileSearch->second;
}
}

if (bDenyRefresh)
{
return true;
}

bool originalResult = trampoline(pfileRelPath, pfileName, pfileExt);

if (Lua::PushHook("HolyLib:PostLuaAutoRefresh"))
{
g_Lua->PushString(pfileRelPath->c_str());
g_Lua->PushString(pfileName->c_str());

g_Lua->CallFunctionProtected(3, 0, true);
}

return originalResult;
};

void CAutoRefreshModule::LuaInit(GarrysMod::Lua::ILuaInterface* pLua, bool bServerInit)
{
if (bServerInit)
return;

Util::StartTable(pLua);
Util::AddFunc(pLua, DenyLuaAutoRefresh, "DenyLuaAutoRefresh");
Util::FinishTable(pLua, "autorefresh");
}

void CAutoRefreshModule::LuaShutdown(GarrysMod::Lua::ILuaInterface* pLua)
{
Util::NukeTable(pLua, "autorefresh");
}

void CAutoRefreshModule::InitDetour(bool bPreServer)
{
if (bPreServer)
return;

SourceSDK::FactoryLoader server_loader("server");
Detour::Create(
&detour_CAutoRefresh_HandleChange_Lua, "CAutoRefresh_HandleChange_Lua",
server_loader.GetModule(), Symbols::GarrysMod_AutoRefresh_HandleChange_LuaSym,
(void*)hook_CAutoRefresh_HandleChange_Lua, m_pID
);
}
12 changes: 10 additions & 2 deletions source/symbols.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -894,8 +894,16 @@ namespace Symbols
const std::vector<Symbol> s_NetChannelsSym = {
Symbol::FromName("_ZL13s_NetChannels"),
};

const std::vector<Symbol> NET_SetTimeSym = {
const std::vector<Symbol> NET_SetTimeSym = {
Symbol::FromName("_Z11NET_SetTimed"),
};

//---------------------------------------------------------------------------------
// Purpose: AutoRefresh Symbols
//---------------------------------------------------------------------------------
const std::vector<Symbol> GarrysMod_AutoRefresh_HandleChange_LuaSym = {
Symbol::FromName("_ZN9GarrysMod11AutoRefresh16HandleChange_LuaERKSsS2_S2_"),
Symbol::FromSignature("\x55\x48\x89\xE5\x41\x57\x41\x56\x49\x89\xD6\x41\x55\x49\x89\xFD\x48\x89\xD7\x41\x54"),
};
}
6 changes: 6 additions & 0 deletions source/symbols.h
Original file line number Diff line number Diff line change
Expand Up @@ -658,4 +658,10 @@ namespace Symbols

typedef ConCommandBase* (*CCvar_FindCommandBase)(ICvar*, const char* name);
extern const std::vector<Symbol> CCvar_FindCommandBaseSym;

//---------------------------------------------------------------------------------
// Purpose: AutoRefresh Symbols
//---------------------------------------------------------------------------------
typedef bool (*GarrysMod_AutoRefresh_HandleChange_Lua)(const std::string* fileRelPath, const std::string* fileName, const std::string* fileExt);
extern const std::vector<Symbol> GarrysMod_AutoRefresh_HandleChange_LuaSym;
}
Loading