From 303132ef42186195dbb2ad67ecbb269013e0a876 Mon Sep 17 00:00:00 2001 From: BotoX Date: Wed, 18 Dec 2019 11:55:42 +0100 Subject: [PATCH] CSSFixes: remove some stuff into new extension PhysHooks --- extension.cpp | 388 ------------------------------------------ gamedata/CSSFixes.txt | 24 --- include/CSSFixes.inc | 17 -- smsdk_config.h | 2 +- 4 files changed, 1 insertion(+), 430 deletions(-) diff --git a/extension.cpp b/extension.cpp index 15202f5..564aa07 100644 --- a/extension.cpp +++ b/extension.cpp @@ -89,18 +89,6 @@ public: virtual void SetPassEntity2( const IHandleEntity *pPassEntity2 ) = 0; }; -class CTriggerMoved : public IPartitionEnumerator -{ -public: - virtual IterationRetval_t EnumElement( IHandleEntity *pHandleEntity ) = 0; -}; - -class CTouchLinks : public IPartitionEnumerator -{ -public: - virtual IterationRetval_t EnumElement( IHandleEntity *pHandleEntity ) = 0; -}; - static struct SrcdsPatch { const char *pSignature; @@ -145,14 +133,6 @@ static struct SrcdsPatch (unsigned char *)"\x0F\x85\xA8\x00\x00\x00\x8B\x83\x80\x02\x00\x00\x85\xC0\x0F\x85\x9A\x00\x00\x00\x90\x90\x90\x90\x90\x90\x90\x90", 0, 0, 0, false }, - // 4: Special - { - "_Z25Physics_RunThinkFunctionsb", - (unsigned char *)"\x8B\x04\x9E\x85\xC0\x74\x13\xA1\x00\x00\x00\x00\x89\x78\x0C\x8B\x04\x9E\x89\x04\x24\xE8\x00\x00\x00\x00", - "xxxxxxxx????xxxxxxxxxx????", - NULL, - 0, 0, 0, false - }, // 5: disable alive check in point_viewcontrol->Disable { "_ZN14CTriggerCamera7DisableEv", @@ -218,32 +198,21 @@ uintptr_t FindFunctionCall(uintptr_t BaseAddr, uintptr_t Function, size_t MaxSiz CSSFixes g_Interface; SMEXT_LINK(&g_Interface); -CGlobalVars *gpGlobals = NULL; IGameConfig *g_pGameConf = NULL; -IForward *g_pOnRunThinkFunctions = NULL; -IForward *g_pOnPrePlayerThinkFunctions = NULL; -IForward *g_pOnPostPlayerThinkFunctions = NULL; -IForward *g_pOnRunThinkFunctionsPost = NULL; - CDetour *g_pDetour_InputTestActivator = NULL; CDetour *g_pDetour_PostConstructor = NULL; CDetour *g_pDetour_FindUseEntity = NULL; CDetour *g_pDetour_CTraceFilterSimple = NULL; -CDetour *g_pDetour_RunThinkFunctions = NULL; CDetour *g_pDetour_KeyValue = NULL; CDetour *g_pDetour_FireBullets = NULL; CDetour *g_pDetour_SwingOrStab = NULL; int g_SH_SkipTwoEntitiesShouldHitEntity = 0; int g_SH_SimpleShouldHitEntity = 0; -int g_SH_TriggerMoved = 0; -int g_SH_TouchLinks = 0; uintptr_t g_CTraceFilterNoNPCsOrPlayer = 0; CTraceFilterSkipTwoEntities *g_CTraceFilterSkipTwoEntities = NULL; CTraceFilterSimple *g_CTraceFilterSimple = NULL; -CTriggerMoved *g_CTriggerMoved = 0; -CTouchLinks *g_CTouchLinks = 0; /* Fix crash in CBaseFilter::InputTestActivator */ DETOUR_DECL_MEMBER1(DETOUR_InputTestActivator, void, inputdata_t *, inputdata) @@ -442,230 +411,6 @@ cell_t PhysboxToClientMap(IPluginContext *pContext, const cell_t *params) return 0; } -DETOUR_DECL_STATIC1(DETOUR_RunThinkFunctions, void, bool, simulating) -{ - if(g_pOnRunThinkFunctions->GetFunctionCount()) - { - g_pOnRunThinkFunctions->PushCell(simulating); - g_pOnRunThinkFunctions->Execute(); - } - - if(g_pOnPrePlayerThinkFunctions->GetFunctionCount()) - { - g_pOnPrePlayerThinkFunctions->Execute(); - } - - DETOUR_STATIC_CALL(DETOUR_RunThinkFunctions)(simulating); - - if(g_pOnRunThinkFunctionsPost->GetFunctionCount()) - { - g_pOnRunThinkFunctionsPost->PushCell(simulating); - g_pOnRunThinkFunctionsPost->Execute(); - } -} - -void (*g_pPhysics_SimulateEntity)(CBaseEntity *pEntity) = NULL; -void Physics_SimulateEntity_CustomLoop(CBaseEntity **ppList, int Count, float Startime) -{ - CBaseEntity *apPlayers[SM_MAXPLAYERS]; - int iPlayers = 0; - - // Remove players from list and put into apPlayers - for(int i = 0; i < Count; i++) - { - CBaseEntity *pEntity = ppList[i]; - if(!pEntity) - continue; - - edict_t *pEdict = gamehelpers->EdictOfIndex(gamehelpers->EntityToBCompatRef(pEntity)); - if(!pEdict) - continue; - - int Entity = gamehelpers->IndexOfEdict(pEdict); - if(Entity >= 1 && Entity <= SM_MAXPLAYERS) - { - apPlayers[iPlayers++] = pEntity; - ppList[i] = NULL; - } - } - - // Shuffle players array - for(int i = iPlayers - 1; i > 0; i--) - { - int j = rand() % (i + 1); - CBaseEntity *pTmp = apPlayers[j]; - apPlayers[j] = apPlayers[i]; - apPlayers[i] = pTmp; - } - - // Simulate players first - for(int i = 0; i < iPlayers; i++) - { - gpGlobals->curtime = Startime; - g_pPhysics_SimulateEntity(apPlayers[i]); - } - - // Post Player simulation done - if(g_pOnPostPlayerThinkFunctions->GetFunctionCount()) - { - g_pOnPostPlayerThinkFunctions->Execute(); - } - - // Now simulate the rest - for(int i = 0; i < Count; i++) - { - CBaseEntity *pEntity = ppList[i]; - if(!pEntity) - continue; - - gpGlobals->curtime = Startime; - g_pPhysics_SimulateEntity(pEntity); - } -} - -int g_TriggerEntityMoved; -int *g_pFilterTriggerTouchPlayers = NULL; -int *g_pBlockTriggerMoved = NULL; -// void IVEngineServer::TriggerMoved( edict_t *pTriggerEnt, bool testSurroundingBoundsOnly ) = 0; -SH_DECL_HOOK2_void(IVEngineServer, TriggerMoved, SH_NOATTRIB, 0, edict_t *, bool); -void TriggerMoved(edict_t *pTriggerEnt, bool testSurroundingBoundsOnly) -{ - g_TriggerEntityMoved = gamehelpers->IndexOfEdict(pTriggerEnt); - - // Block if bit is set - if(g_pBlockTriggerMoved && CheckBit(g_pBlockTriggerMoved, g_TriggerEntityMoved)) - { - RETURN_META(MRES_SUPERCEDE); - } - - // Decide per entity in TriggerMoved_EnumElement - RETURN_META(MRES_IGNORED); -} - -// IterationRetval_t CTriggerMoved::EnumElement( IHandleEntity *pHandleEntity ) = 0; -SH_DECL_HOOK1(CTriggerMoved, EnumElement, SH_NOATTRIB, 0, IterationRetval_t, IHandleEntity *); -IterationRetval_t TriggerMoved_EnumElement(IHandleEntity *pHandleEntity) -{ - if(!g_pFilterTriggerTouchPlayers) - { - RETURN_META_VALUE(MRES_IGNORED, ITERATION_CONTINUE); - } - - IServerUnknown *pUnk = static_cast< IServerUnknown* >( pHandleEntity ); - CBaseHandle hndl = pUnk->GetRefEHandle(); - int index = hndl.GetEntryIndex(); - - // We only care about players - if(index > SM_MAXPLAYERS) - { - RETURN_META_VALUE(MRES_IGNORED, ITERATION_CONTINUE); - } - - // block touching any clients here if bit is set - if(CheckBit(g_pFilterTriggerTouchPlayers, g_TriggerEntityMoved)) - { - RETURN_META_VALUE(MRES_SUPERCEDE, ITERATION_CONTINUE); - } - - // allow touch - RETURN_META_VALUE(MRES_IGNORED, ITERATION_CONTINUE); -} - -cell_t BlockTriggerMoved(IPluginContext *pContext, const cell_t *params) -{ - if(params[2]) - pContext->LocalToPhysAddr(params[1], &g_pBlockTriggerMoved); - else - g_pBlockTriggerMoved = NULL; - - return 0; -} - -cell_t FilterTriggerTouchPlayers(IPluginContext *pContext, const cell_t *params) -{ - if(params[2]) - pContext->LocalToPhysAddr(params[1], &g_pFilterTriggerTouchPlayers); - else - g_pFilterTriggerTouchPlayers = NULL; - - return 0; -} - -int g_SolidEntityMoved; -int *g_pBlockSolidMoved = NULL; -int *g_pFilterClientEntityMap = NULL; -// void IVEngineServer::SolidMoved( edict_t *pSolidEnt, ICollideable *pSolidCollide, const Vector* pPrevAbsOrigin, bool testSurroundingBoundsOnly ) = 0; -SH_DECL_HOOK4_void(IVEngineServer, SolidMoved, SH_NOATTRIB, 0, edict_t *, ICollideable *, const Vector *, bool); -void SolidMoved(edict_t *pSolidEnt, ICollideable *pSolidCollide, const Vector *pPrevAbsOrigin, bool testSurroundingBoundsOnly) -{ - g_SolidEntityMoved = gamehelpers->IndexOfEdict(pSolidEnt); - - // Block if bit is set - if(g_pBlockSolidMoved && CheckBit(g_pBlockSolidMoved, g_TriggerEntityMoved)) - { - RETURN_META(MRES_SUPERCEDE); - } - - // Decide per entity in TouchLinks_EnumElement - RETURN_META(MRES_IGNORED); -} - -// IterationRetval_t CTouchLinks::EnumElement( IHandleEntity *pHandleEntity ) = 0; -SH_DECL_HOOK1(CTouchLinks, EnumElement, SH_NOATTRIB, 0, IterationRetval_t, IHandleEntity *); -IterationRetval_t TouchLinks_EnumElement(IHandleEntity *pHandleEntity) -{ - IServerUnknown *pUnk = static_cast< IServerUnknown* >( pHandleEntity ); - CBaseHandle hndl = pUnk->GetRefEHandle(); - int index = hndl.GetEntryIndex(); - - // Optimization: Players shouldn't touch other players - if(g_SolidEntityMoved <= SM_MAXPLAYERS && index <= SM_MAXPLAYERS) - { - RETURN_META_VALUE(MRES_SUPERCEDE, ITERATION_CONTINUE); - } - - // We only care about players - if(g_SolidEntityMoved > SM_MAXPLAYERS) - { - RETURN_META_VALUE(MRES_IGNORED, ITERATION_CONTINUE); - } - - // Do we have our filter map and is the entity within it? (can it even be > 2048?) - if(!g_pFilterClientEntityMap || index >= 2048) - { - RETURN_META_VALUE(MRES_IGNORED, ITERATION_CONTINUE); - } - - // Block player from touching this entity if it's filtered - if(CheckBit(g_pFilterClientEntityMap, g_SolidEntityMoved * 2048 + index)) - { - RETURN_META_VALUE(MRES_SUPERCEDE, ITERATION_CONTINUE); - } - - // Allow otherwise - RETURN_META_VALUE(MRES_IGNORED, ITERATION_CONTINUE); -} - -cell_t BlockSolidMoved(IPluginContext *pContext, const cell_t *params) -{ - if(params[2]) - pContext->LocalToPhysAddr(params[1], &g_pBlockSolidMoved); - else - g_pBlockSolidMoved = NULL; - - return 0; -} - -cell_t FilterClientEntityMap(IPluginContext *pContext, const cell_t *params) -{ - if(params[2]) - pContext->LocalToPhysAddr(params[1], &g_pFilterClientEntityMap); - else - g_pFilterClientEntityMap = NULL; - - return 0; -} - bool CSSFixes::SDK_OnLoad(char *error, size_t maxlength, bool late) { srand((unsigned int)time(NULL)); @@ -713,14 +458,6 @@ bool CSSFixes::SDK_OnLoad(char *error, size_t maxlength, bool late) return false; } - g_pDetour_RunThinkFunctions = DETOUR_CREATE_STATIC(DETOUR_RunThinkFunctions, "Physics_RunThinkFunctions"); - if(g_pDetour_RunThinkFunctions == NULL) - { - snprintf(error, maxlength, "Could not create detour for Physics_RunThinkFunctions"); - SDK_OnUnload(); - return false; - } - g_pDetour_KeyValue = DETOUR_CREATE_MEMBER(DETOUR_KeyValue, "CBaseEntity_KeyValue"); if(g_pDetour_KeyValue == NULL) { @@ -749,7 +486,6 @@ bool CSSFixes::SDK_OnLoad(char *error, size_t maxlength, bool late) g_pDetour_PostConstructor->EnableDetour(); g_pDetour_FindUseEntity->EnableDetour(); g_pDetour_CTraceFilterSimple->EnableDetour(); - g_pDetour_RunThinkFunctions->EnableDetour(); g_pDetour_KeyValue->EnableDetour(); g_pDetour_FireBullets->EnableDetour(); g_pDetour_SwingOrStab->EnableDetour(); @@ -790,41 +526,6 @@ bool CSSFixes::SDK_OnLoad(char *error, size_t maxlength, bool late) g_SH_SkipTwoEntitiesShouldHitEntity = SH_ADD_DVPHOOK(CTraceFilterSkipTwoEntities, ShouldHitEntity, g_CTraceFilterSkipTwoEntities, SH_STATIC(ShouldHitEntity), true); g_SH_SimpleShouldHitEntity = SH_ADD_DVPHOOK(CTraceFilterSimple, ShouldHitEntity, g_CTraceFilterSimple, SH_STATIC(ShouldHitEntity), true); - // Find VTable for CTriggerMoved - uintptr_t pCTriggerMoved; - if(!g_pGameConf->GetMemSig("CTriggerMoved", (void **)(&pCTriggerMoved)) || !pCTriggerMoved) - { - snprintf(error, maxlength, "Failed to find CTriggerMoved.\n"); - SDK_OnUnload(); - return false; - } - // First function in VTable - g_CTriggerMoved = (CTriggerMoved *)(pCTriggerMoved + 8); - - // Find VTable for CTouchLinks - uintptr_t pCTouchLinks; - if(!g_pGameConf->GetMemSig("CTouchLinks", (void **)(&pCTouchLinks)) || !pCTouchLinks) - { - snprintf(error, maxlength, "Failed to find CTouchLinks.\n"); - SDK_OnUnload(); - return false; - } - // First function in VTable - g_CTouchLinks = (CTouchLinks *)(pCTouchLinks + 8); - - g_SH_TriggerMoved = SH_ADD_DVPHOOK(CTriggerMoved, EnumElement, g_CTriggerMoved, SH_STATIC(TriggerMoved_EnumElement), false); - g_SH_TouchLinks = SH_ADD_DVPHOOK(CTouchLinks, EnumElement, g_CTouchLinks, SH_STATIC(TouchLinks_EnumElement), false); - - SH_ADD_HOOK(IVEngineServer, TriggerMoved, engine, SH_STATIC(TriggerMoved), false); - SH_ADD_HOOK(IVEngineServer, SolidMoved, engine, SH_STATIC(SolidMoved), false); - - if(!g_pGameConf->GetMemSig("Physics_SimulateEntity", (void **)(&g_pPhysics_SimulateEntity)) || !g_pPhysics_SimulateEntity) - { - snprintf(error, maxlength, "Failed to find Physics_SimulateEntity.\n"); - SDK_OnUnload(); - return false; - } - void *pServerSo = dlopen("cstrike/bin/server_srv.so", RTLD_NOW); if(!pServerSo) { @@ -841,45 +542,6 @@ bool CSSFixes::SDK_OnLoad(char *error, size_t maxlength, bool late) return false; } - /* 4: Special */ - uintptr_t pAddress = (uintptr_t)memutils->ResolveSymbol(pServerSo, gs_Patches[4].pSignature); - if(!pAddress) - { - snprintf(error, maxlength, "Could not find symbol: %s", gs_Patches[4].pSignature); - dlclose(pServerSo); - dlclose(pEngineSo); - SDK_OnUnload(); - return false; - } - - uintptr_t pPatchAddress = FindPattern(pAddress, gs_Patches[4].pPatchSignature, gs_Patches[4].pPatchPattern, 1024); - if(!pPatchAddress) - { - snprintf(error, maxlength, "Could not find patch signature for symbol: %s", gs_Patches[4].pSignature); - dlclose(pServerSo); - dlclose(pEngineSo); - SDK_OnUnload(); - return false; - } - - // mov [esp+8], edi ; startime - // mov [esp+4], eax ; count - // mov [esp], esi ; **list - // call NULL ; <- our func here - // mov eax, ds:gpGlobals ; restore - // jmp +11 ; jump over useless instructions - static unsigned char aPatch[] = "\x89\x7C\x24\x08\x89\x44\x24\x04\x89\x34\x24\xE8\x00\x00\x00\x00\xA1\x00\x00\x00\x00\xEB\x0B\x90\x90\x90"; - gs_Patches[4].pPatch = aPatch; - - // put our function address into the relative call instruction - // relative call: new PC = PC + imm1 - // call is at + 11 after pPatchAddress - // PC will be past our call instruction so + 5 - *(uintptr_t *)&aPatch[12] = (uintptr_t)Physics_SimulateEntity_CustomLoop - (pPatchAddress + 11 + 5); - - // restore "mov eax, ds:gpGlobals" from original to our patch after the call - *(uintptr_t *)&aPatch[17] = *(uintptr_t *)(pPatchAddress + 8); - // Apply all patches for(size_t i = 0; i < sizeof(gs_Patches) / sizeof(*gs_Patches); i++) { @@ -921,20 +583,11 @@ bool CSSFixes::SDK_OnLoad(char *error, size_t maxlength, bool late) dlclose(pServerSo); dlclose(pEngineSo); - g_pOnRunThinkFunctions = forwards->CreateForward("OnRunThinkFunctions", ET_Ignore, 1, NULL, Param_Cell); - g_pOnPrePlayerThinkFunctions = forwards->CreateForward("OnPrePlayerThinkFunctions", ET_Ignore, 0, NULL); - g_pOnPostPlayerThinkFunctions = forwards->CreateForward("OnPostPlayerThinkFunctions", ET_Ignore, 0, NULL); - g_pOnRunThinkFunctionsPost = forwards->CreateForward("OnRunThinkFunctionsPost", ET_Ignore, 1, NULL, Param_Cell); - return true; } const sp_nativeinfo_t MyNatives[] = { - { "BlockTriggerMoved", BlockTriggerMoved }, - { "BlockSolidMoved", BlockSolidMoved }, - { "FilterClientEntityMap", FilterClientEntityMap }, - { "FilterTriggerTouchPlayers", FilterTriggerTouchPlayers }, { "PhysboxToClientMap", PhysboxToClientMap }, { NULL, NULL } }; @@ -971,12 +624,6 @@ void CSSFixes::SDK_OnUnload() g_pDetour_CTraceFilterSimple = NULL; } - if(g_pDetour_RunThinkFunctions != NULL) - { - g_pDetour_RunThinkFunctions->Destroy(); - g_pDetour_RunThinkFunctions = NULL; - } - if(g_pDetour_KeyValue != NULL) { g_pDetour_KeyValue->Destroy(); @@ -995,45 +642,12 @@ void CSSFixes::SDK_OnUnload() g_pDetour_SwingOrStab = NULL; } - if(g_pOnRunThinkFunctions != NULL) - { - forwards->ReleaseForward(g_pOnRunThinkFunctions); - g_pOnRunThinkFunctions = NULL; - } - - if(g_pOnRunThinkFunctionsPost != NULL) - { - forwards->ReleaseForward(g_pOnRunThinkFunctionsPost); - g_pOnRunThinkFunctionsPost = NULL; - } - - if(g_pOnPrePlayerThinkFunctions != NULL) - { - forwards->ReleaseForward(g_pOnPrePlayerThinkFunctions); - g_pOnPrePlayerThinkFunctions = NULL; - } - - if(g_pOnPostPlayerThinkFunctions != NULL) - { - forwards->ReleaseForward(g_pOnPostPlayerThinkFunctions); - g_pOnPostPlayerThinkFunctions = NULL; - } - if(g_SH_SkipTwoEntitiesShouldHitEntity) SH_REMOVE_HOOK_ID(g_SH_SkipTwoEntitiesShouldHitEntity); if(g_SH_SimpleShouldHitEntity) SH_REMOVE_HOOK_ID(g_SH_SimpleShouldHitEntity); - if(g_SH_TriggerMoved) - SH_REMOVE_HOOK_ID(g_SH_TriggerMoved); - - if(g_SH_TouchLinks) - SH_REMOVE_HOOK_ID(g_SH_TouchLinks); - - SH_REMOVE_HOOK(IVEngineServer, TriggerMoved, engine, SH_STATIC(TriggerMoved), false); - SH_REMOVE_HOOK(IVEngineServer, SolidMoved, engine, SH_STATIC(SolidMoved), false); - gameconfs->CloseGameConfigFile(g_pGameConf); // Revert all applied patches @@ -1059,8 +673,6 @@ void CSSFixes::SDK_OnUnload() bool CSSFixes::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlen, bool late) { - GET_V_IFACE_CURRENT(GetEngineFactory, engine, IVEngineServer, INTERFACEVERSION_VENGINESERVER); - gpGlobals = ismm->GetCGlobals(); return true; } diff --git a/gamedata/CSSFixes.txt b/gamedata/CSSFixes.txt index c0082e8..7fa85d6 100644 --- a/gamedata/CSSFixes.txt +++ b/gamedata/CSSFixes.txt @@ -52,12 +52,6 @@ "linux" "@_ZN27CTraceFilterSkipTwoEntitiesC2EPK13IHandleEntityS2_i" } - "Physics_RunThinkFunctions" - { - "library" "server" - "linux" "@_Z25Physics_RunThinkFunctionsb" - } - "CBaseEntity_KeyValue" { "library" "server" @@ -70,29 +64,11 @@ "linux" "@_Z14FX_FireBulletsiRK6VectorRK6QAngleiiifff" } - "Physics_SimulateEntity" - { - "library" "server" - "linux" "@_Z22Physics_SimulateEntityP11CBaseEntity" - } - "CKnife_SwingOrStab" { "library" "server" "linux" "@_ZN6CKnife11SwingOrStabEb" } - - "CTriggerMoved" - { - "library" "engine" - "linux" "@_ZTV13CTriggerMoved" - } - - "CTouchLinks" - { - "library" "engine" - "linux" "@_ZTV11CTouchLinks" - } } } } diff --git a/include/CSSFixes.inc b/include/CSSFixes.inc index de9998e..a75d293 100644 --- a/include/CSSFixes.inc +++ b/include/CSSFixes.inc @@ -3,23 +3,6 @@ #endif #define _cssfixes_included -forward void OnRunThinkFunctions(bool simulating); -forward void OnPrePlayerThinkFunctions(); -forward void OnPostPlayerThinkFunctions(); -forward void OnRunThinkFunctionsPost(bool simulating); - -// Block TriggerMoved from being called at all for an entity by setting the bit to 1. -native void BlockTriggerMoved(int map[2048 / 32], bool set); - -// Block SolidMoved from being called at all for an entity by setting the bit to 1. -native void BlockSolidMoved(int map[2048 / 32], bool set); - -// Block clients SolidMoved from touching an entity by setting the bit to 1 in the clients map. -native void FilterClientEntityMap(int map[((MAXPLAYERS + 1) * 2048) / 32], bool set); - -// Block triggers TriggerMoved from touching any client by setting the bit to 1 for the entity index. -native void FilterTriggerTouchPlayers(int map[2048 / 32], bool set); - // Map entities to client entity in FireBullets/SwingOrStab ShouldHitEntity. // Aka. shoot and knife through physboxes that are parented to teammates (white knight, gandalf, horse, etc.) native void PhysboxToClientMap(char map[2048], bool set); diff --git a/smsdk_config.h b/smsdk_config.h index 1bb1ff9..c1141c5 100644 --- a/smsdk_config.h +++ b/smsdk_config.h @@ -40,7 +40,7 @@ /* Basic information exposed publicly */ #define SMEXT_CONF_NAME "CSSFixes" #define SMEXT_CONF_DESCRIPTION "Patches bugs in the CSS server binary and more..." -#define SMEXT_CONF_VERSION "1.15" +#define SMEXT_CONF_VERSION "1.16" #define SMEXT_CONF_AUTHOR "BotoX" #define SMEXT_CONF_URL "" #define SMEXT_CONF_LOGTAG "CSSFIXES"