using ChatFunc_t = void(__thiscall*)(void* thisptr, uint32_t type, const char* text, const char* prefix, uint32_t color, uint32_t pcolor);
ChatFunc_t g_origChatFunc = nullptr;
void __fastcall ChatDetour(void* thisptr, void* edx, uint32_t type, const char* text, const char* prefix, uint32_t color, uint32_t pcolor) {
std::string texta = text ? text : "";
std::string prefixa = prefix ? prefix : "";
bool shouldHide = ProcessSpecialMessage(texta);
if (!shouldHide) {
std::string colorHex = ARGBtoRGB(color);
if (type == 2) {
std::string prefixColorHex = ARGBtoRGB(pcolor);
texta = "{" + prefixColorHex + "}" + prefixa + " {" + colorHex + "}" + texta;
}
std::string finalMessage = "{" + colorHex + "}" + GetCurrentTimeString() + " " + texta;
ExecuteJSOnCEF(finalMessage);
}
if (g_origChatFunc) g_origChatFunc(thisptr, type, text, prefix, color, pcolor);
}
bool InstallChatHook() {
HMODULE samp = GetModuleHandleA("samp.dll");
uintptr_t addr = reinterpret_cast<uintptr_t>(samp) + 0x64010;
if (MH_CreateHook(reinterpret_cast<LPVOID>(addr), &ChatDetour, reinterpret_cast<LPVOID*>(&g_origChatFunc)) != MH_OK) return false;
if (MH_EnableHook(reinterpret_cast<LPVOID>(addr)) != MH_OK) return false;
return true;
}
void __fastcall ActivateChatBlocker(void* thisptr) {
return;
}
bool InstallActivateChatHook() {
HMODULE samp = GetModuleHandleA("samp.dll");
if (!samp) return false;
uintptr_t addr = reinterpret_cast<uintptr_t>(samp) + 0x657E0;
if (MH_CreateHook(reinterpret_cast<LPVOID>(addr),
reinterpret_cast<LPVOID>(&ActivateChatBlocker),
nullptr) != MH_OK) return false;
return MH_EnableHook(reinterpret_cast<LPVOID>(addr)) == MH_OK;
}
DWORD WINAPI PluginThread(LPVOID) {
while (!GetModuleHandleA("samp.dll")) {
Sleep(100);
}
LoadSettings();
if (MH_Initialize() != MH_OK) {
OutputDebugStringA("MinHook init failed\n");
return 1;
}
if (!InstallChatHook()) {
OutputDebugStringA("Chat hook failed\n");
}
if (!InstallActivateChatHook()) {
OutputDebugStringA("Activate chat hook failed\n");
}
MH_Uninitialize();
return 0;
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hModule);
CreateThread(nullptr, 0, PluginThread, nullptr, 0, nullptr);
break;
case DLL_PROCESS_DETACH:
g_running = false;
break;
}
return TRUE;
}