1.1 --- a/core/HalfLife2.cpp Thu Jul 09 17:51:12 2009 -0400
1.2 +++ b/core/HalfLife2.cpp Fri Jul 24 12:34:31 2009 +1200
1.3 @@ -37,10 +37,14 @@
1.4 #include "sm_stringutil.h"
1.5 #include "GameConfigs.h"
1.6 #include <compat_wrappers.h>
1.7 +#include <Logger.h>
1.8
1.9 CHalfLife2 g_HL2;
1.10 ConVar *sv_lan = NULL;
1.11
1.12 +static void *g_EntList = NULL;
1.13 +static int entInfoOffset = -1;
1.14 +
1.15 namespace SourceHook
1.16 {
1.17 template<>
1.18 @@ -123,6 +127,51 @@
1.19 g_ShareSys.AddInterface(NULL, this);
1.20 }
1.21
1.22 +void CHalfLife2::OnSourceModAllInitialized_Post()
1.23 +{
1.24 + char *addr = NULL;
1.25 +#ifdef PLATFORM_WINDOWS
1.26 + int offset;
1.27 +
1.28 + /* gEntList and/or g_pEntityList */
1.29 + if (!g_pGameConf->GetMemSig("LevelShutdown", (void **)&addr))
1.30 + {
1.31 + g_Logger.LogError("Logical Entities not supported by this mod (LevelShutdown) - Reverting to networkable entities only");
1.32 + return;
1.33 + }
1.34 + if (!addr)
1.35 + {
1.36 + g_Logger.LogError("Failed lookup of LevelShutdown - Reverting to networkable entities only");
1.37 + return;
1.38 + }
1.39 + if (!g_pGameConf->GetOffset("gEntList", &offset))
1.40 + {
1.41 + g_Logger.LogError("Logical Entities not supported by this mod (gEntList) - Reverting to networkable entities only");
1.42 + return;
1.43 + }
1.44 + g_EntList = *reinterpret_cast<void **>(addr + offset);
1.45 +#elif defined PLATFORM_LINUX
1.46 + /* gEntList and/or g_pEntityList */
1.47 + if (!g_pGameConf->GetMemSig("gEntList", (void **)&addr))
1.48 + {
1.49 + g_Logger.LogError("Logical Entities not supported by this mod (gEntList) - Reverting to networkable entities only");
1.50 + return;
1.51 + }
1.52 + if (!addr)
1.53 + {
1.54 + g_Logger.LogError("Failed lookup of gEntList - Reverting to networkable entities only");
1.55 + return;
1.56 + }
1.57 + g_EntList = reinterpret_cast<void *>(addr);
1.58 +#endif
1.59 +
1.60 + if (!g_pGameConf->GetOffset("EntInfo", &entInfoOffset))
1.61 + {
1.62 + g_Logger.LogError("Logical Entities not supported by this mod (EntInfo) - Reverting to networkable entities only");
1.63 + return;
1.64 + }
1.65 +}
1.66 +
1.67 #if !defined METAMOD_PLAPI_VERSION
1.68 bool CHalfLife2::IsOriginalEngine()
1.69 {
1.70 @@ -642,3 +691,173 @@
1.71 {
1.72 engine->ServerCommand(buffer);
1.73 }
1.74 +
1.75 +cell_t CHalfLife2::EntityToReference(CBaseEntity *pEntity)
1.76 +{
1.77 + IServerUnknown *pUnknown = (IServerUnknown *)pEntity;
1.78 + CBaseHandle hndl = pUnknown->GetRefEHandle();
1.79 + return (hndl.ToInt() | (1<<31));
1.80 +}
1.81 +
1.82 +CBaseEntity *CHalfLife2::ReferenceToEntity(cell_t entRef)
1.83 +{
1.84 + CEntInfo *pInfo = NULL;
1.85 +
1.86 + if (entRef & (1<<31))
1.87 + {
1.88 + /* Proper ent reference */
1.89 + int hndlValue = entRef & ~(1<<31);
1.90 + CBaseHandle hndl(hndlValue);
1.91 +
1.92 + pInfo = LookupEntity(hndl.GetEntryIndex());
1.93 + if (pInfo->m_SerialNumber != hndl.GetSerialNumber())
1.94 + {
1.95 + return NULL;
1.96 + }
1.97 + }
1.98 + else
1.99 + {
1.100 + /* Old style index only */
1.101 + pInfo = LookupEntity(entRef);
1.102 + }
1.103 +
1.104 + if (!pInfo)
1.105 + {
1.106 + return NULL;
1.107 + }
1.108 +
1.109 + IServerUnknown *pUnk = static_cast<IServerUnknown *>(pInfo->m_pEntity);
1.110 + if (pUnk)
1.111 + {
1.112 + return pUnk->GetBaseEntity();
1.113 + }
1.114 +
1.115 + return NULL;
1.116 +}
1.117 +
1.118 +/**
1.119 + * Retrieves the CEntInfo pointer from g_EntList for a given entity index
1.120 + */
1.121 +CEntInfo *CHalfLife2::LookupEntity(int entIndex)
1.122 +{
1.123 + if (!g_EntList || entInfoOffset == -1)
1.124 + {
1.125 + /* Attempt to use engine interface instead */
1.126 + static CEntInfo tempInfo;
1.127 + tempInfo.m_pNext = NULL;
1.128 + tempInfo.m_pPrev = NULL;
1.129 +
1.130 + edict_t *pEdict = engine->PEntityOfEntIndex(entIndex);
1.131 +
1.132 + if (!pEdict)
1.133 + {
1.134 + return NULL;
1.135 + }
1.136 +
1.137 + IServerUnknown *pUnk = pEdict->GetUnknown();
1.138 +
1.139 + if (!pUnk)
1.140 + {
1.141 + return NULL;
1.142 + }
1.143 +
1.144 + tempInfo.m_pEntity = pUnk;
1.145 + tempInfo.m_SerialNumber = pUnk->GetRefEHandle().GetSerialNumber();
1.146 +
1.147 + return &tempInfo;
1.148 + }
1.149 +
1.150 + CEntInfo *pArray = (CEntInfo *)(((unsigned char *)g_EntList) + entInfoOffset);
1.151 + return &pArray[entIndex];
1.152 +}
1.153 +
1.154 +/**
1.155 + SERIAL_MASK = 0x7fff (15 bits)
1.156 +
1.157 + #define MAX_EDICT_BITS 11
1.158 + #define NUM_ENT_ENTRY_BITS (MAX_EDICT_BITS + 1)
1.159 + m_Index = iEntry | (iSerialNumber << NUM_ENT_ENTRY_BITS);
1.160 +
1.161 + Top 5 bits of a handle are unused.
1.162 + Bit 31 - Our 'reference' flag indicator
1.163 +*/
1.164 +
1.165 +cell_t CHalfLife2::IndexToReference(int entIndex)
1.166 +{
1.167 + CBaseEntity *pEnt = ReferenceToEntity(entIndex);
1.168 + if (!pEnt)
1.169 + {
1.170 + return INVALID_EHANDLE_INDEX;
1.171 + }
1.172 +
1.173 + return EntityToReference(pEnt);
1.174 +}
1.175 +
1.176 +int CHalfLife2::ReferenceToIndex(cell_t entRef)
1.177 +{
1.178 + if (entRef == INVALID_EHANDLE_INDEX)
1.179 + {
1.180 + return INVALID_EHANDLE_INDEX;
1.181 + }
1.182 +
1.183 + if (entRef & (1<<31))
1.184 + {
1.185 + /* Proper ent reference */
1.186 + int hndlValue = entRef & ~(1<<31);
1.187 + CBaseHandle hndl(hndlValue);
1.188 +
1.189 + CEntInfo *pInfo = LookupEntity(hndl.GetEntryIndex());
1.190 +
1.191 + if (pInfo->m_SerialNumber != hndl.GetSerialNumber())
1.192 + {
1.193 + return INVALID_EHANDLE_INDEX;
1.194 + }
1.195 +
1.196 + return hndl.GetEntryIndex();
1.197 + }
1.198 +
1.199 + return entRef;
1.200 +}
1.201 +
1.202 +cell_t CHalfLife2::EntityToBCompatRef(CBaseEntity *pEntity)
1.203 +{
1.204 + if (pEntity == NULL)
1.205 + {
1.206 + return INVALID_EHANDLE_INDEX;
1.207 + }
1.208 +
1.209 + IServerUnknown *pUnknown = (IServerUnknown *)pEntity;
1.210 + CBaseHandle hndl = pUnknown->GetRefEHandle();
1.211 +
1.212 + if (hndl.GetEntryIndex() >= MAX_EDICTS)
1.213 + {
1.214 + return (hndl.ToInt() | (1<<31));
1.215 + }
1.216 + else
1.217 + {
1.218 + return hndl.GetEntryIndex();
1.219 + }
1.220 +}
1.221 +
1.222 +cell_t CHalfLife2::ReferenceToBCompatRef(cell_t entRef)
1.223 +{
1.224 + if (entRef == INVALID_EHANDLE_INDEX)
1.225 + {
1.226 + return INVALID_EHANDLE_INDEX;
1.227 + }
1.228 +
1.229 + int hndlValue = entRef & ~(1<<31);
1.230 + CBaseHandle hndl(hndlValue);
1.231 +
1.232 + if (hndl.GetEntryIndex() < MAX_EDICTS)
1.233 + {
1.234 + return hndl.GetEntryIndex();
1.235 + }
1.236 +
1.237 + return entRef;
1.238 +}
1.239 +
1.240 +void *CHalfLife2::GetGlobalEntityList()
1.241 +{
1.242 + return g_EntList;
1.243 +}
1.244 \ No newline at end of file