1+ #include " main.hpp"
2+
3+ float g_fTickrate = 0 .0f ;
4+ int g_iMaxClients = 0 ;
5+
6+ void * pCGlobalVars;
7+ void * pCGameServer;
8+
9+ VTFHook* GetTickInterval;
10+ VTFHook* FindParam;
11+
12+ ICommandLine* pCommandLine;
13+ int GAME = -1 ;
14+
15+ typedef void *(*FakeGetCommandLine)();
16+
17+ CSamplePlugin g_SamplePlugin;
18+
19+ InterfaceReg *InterfaceReg::s_pInterfaceRegs = nullptr ;
20+
21+ InterfaceReg::InterfaceReg ( InstantiateInterfaceFn fn , const char *pName ) : m_pName( pName )
22+ {
23+ m_CreateFn = fn;
24+ m_pNext = s_pInterfaceRegs;
25+ s_pInterfaceRegs = this ;
26+ }
27+
28+ void * CreateInterfaceInternal ( const char *pName , int *pReturnCode )
29+ {
30+ InterfaceReg *pCur;
31+
32+ for ( pCur = InterfaceReg::s_pInterfaceRegs; pCur; pCur = pCur->m_pNext )
33+ {
34+ if ( strcmp ( pCur->m_pName , pName ) == 0 )
35+ {
36+ if ( pReturnCode )
37+ {
38+ *pReturnCode = IFACE_OK;
39+ }
40+ return pCur->m_CreateFn ();
41+ }
42+ }
43+
44+ if ( pReturnCode )
45+ *pReturnCode = IFACE_FAILED;
46+
47+ return NULL ;
48+ }
49+
50+ DLL_EXPORT void * CreateInterface ( const char *pName , int *pReturnCode ){
51+ return CreateInterfaceInternal ( pName , pReturnCode );
52+ }
53+
54+ float OnGetTickInterval ()
55+ {
56+ if (g_iMaxClients)
57+ {
58+ if (GAME == CSS90)
59+ {
60+ if (pCGlobalVars)
61+ *((int *)pCGlobalVars+20 ) = g_iMaxClients;
62+ if (pCGameServer)
63+ {
64+ *((int *)pCGameServer + 124 ) = g_iMaxClients; // maxplayers set to %i\n
65+ *((int *)pCGameServer + 83 ) = g_iMaxClients;
66+ }
67+ }
68+ else if (GAME == CSS34)
69+ {
70+ if (pCGlobalVars)
71+ *((int *)pCGlobalVars+20 ) = g_iMaxClients;
72+ if (pCGameServer)
73+ {
74+ *((int *)pCGameServer + 64 ) = g_iMaxClients; // maxplayers set to %i\n
75+ *((int *)pCGameServer + 105 ) = g_iMaxClients;
76+ }
77+ }
78+ }
79+ return g_fTickrate;
80+ }
81+
82+ bool CSamplePlugin::Load ( CreateInterfaceFn interfaceFactory , CreateInterfaceFn gameServerFactory )
83+ {
84+ // interfaces ServerGameDLL
85+ const char strings[3 ][32 ] = {
86+ " ServerGameDLL010" ,
87+ " ServerGameDLL006" ,
88+ " ServerGameDLL005"
89+ };
90+
91+ // identify game
92+ void * server;
93+ for (unsigned int i = 0 ; i < sizeof (strings); i++)
94+ {
95+ if ( (server = (void *)gameServerFactory (strings[i], NULL )) )
96+ {
97+ GAME = i;
98+ break ;
99+ }
100+ }
101+
102+ if (!server)
103+ return false ;
104+
105+ void *pEngineServer = (void *)interfaceFactory (GAME != CSS34 ? " VEngineServer023" :" VEngineServer021" , NULL ); // CVEngineServer : public IVEngineServer
106+
107+ if (!pEngineServer)
108+ return false ;
109+
110+ char buffer[256 ];
111+
112+ switch (GAME)
113+ {
114+ case CSS90: strcpy (buffer," libtier0.so" ); break ;
115+ case CSS34: strcpy (buffer," tier0_i486.so" ); break ;
116+ case CSGO: strcpy (buffer," libtier0.so" ); break ;
117+ }
118+
119+ void *tier0 = dlopen (buffer, RTLD_NOW);
120+ if (!tier0)
121+ return false ;
122+ void * lb = dlsym (tier0,GAME == CSGO ? " CommandLine" :" CommandLine_Tier0" );
123+ if (!lb)
124+ return false ;
125+ pCommandLine = (ICommandLine*)((FakeGetCommandLine)((FakeGetCommandLine *)lb))();
126+
127+ switch (GAME)
128+ {
129+ case CSS90: callvfunc<void (*)(void *,char *,int )>(pEngineServer, 51 )(pEngineServer,buffer,sizeof (buffer)); break ; // GetGameDir(buffer, sizeof(buffer));
130+ case CSS34: callvfunc<void (*)(void *,char *,int )>(pEngineServer, 54 )(pEngineServer,buffer,sizeof (buffer)); break ;
131+ case CSGO: callvfunc<void (*)(void *,char *,int )>(pEngineServer, 52 )(pEngineServer,buffer,sizeof (buffer)); break ; // find text "COM_CheckGameDirectory: game directories don't match" or "asw_build_map %s connecting\n"
132+ }
133+
134+
135+ // load config
136+ strcat (buffer, " /addons/nolimits.ini" );
137+ FILE *fp = fopen (buffer, " r" );
138+ if (fp != NULL )
139+ {
140+ if (fgets (buffer,4 ,fp))
141+ g_fTickrate = atof (buffer);
142+
143+ unsigned int i;
144+
145+ size_t l;
146+ while (fgets (buffer,32 ,fp) != NULL && buffer[0 ])
147+ {
148+ // trim newline character
149+ l = strlen (buffer) - 1 ;
150+ if (buffer[l] == ' \n ' )
151+ buffer[l--] = 0 ;
152+ if (buffer[l] == ' \r ' )
153+ buffer[l] = 0 ;
154+
155+ if (buffer[0 ] == ' #' )
156+ {
157+ if (GAME == CSGO)
158+ pCommandLine->RemoveParamCSGO (&buffer[1 ]);
159+ else
160+ pCommandLine->RemoveParamCSS (&buffer[1 ]);
161+ continue ;
162+ }
163+ for (i = 0 ;i < strlen (buffer);i++)
164+ {
165+ if (buffer[i] == ' ' )
166+ {
167+ buffer[i] = 0 ;
168+ if (GAME == CSGO)
169+ pCommandLine->AppendParamCSGO (buffer,&buffer[i+1 ]);
170+ else
171+ {
172+ if (!strcmp (buffer," -maxplayers" ))
173+ g_iMaxClients = atoi (&buffer[i+1 ]);
174+ pCommandLine->AppendParamCSS (buffer,&buffer[i+1 ]);
175+ }
176+ break ;
177+ }
178+ }
179+ }
180+
181+ if (g_fTickrate > 10 )
182+ g_fTickrate = 1 .0f / g_fTickrate;
183+
184+ // change function in vtable
185+ if (g_fTickrate)
186+ GetTickInterval = new VTFHook (server,(void *)OnGetTickInterval,GAME == CSGO ? 9 :10 );
187+
188+ if (GAME != CSGO)
189+ {
190+ // valid interface on all games
191+ void * pIPlayerInfoManager = (void *)gameServerFactory (" PlayerInfoManager002" ,NULL );
192+
193+ // valid index on all games
194+ pCGlobalVars = callvfunc<void *(*)(void *)>(pIPlayerInfoManager, 1 )(pIPlayerInfoManager);
195+
196+ if (GAME == CSS90)
197+ pCGameServer = callvfunc<void *(*)(void *)>(pEngineServer, 119 )(pEngineServer); // GetIServer
198+ else if (GAME == CSS34)
199+ {
200+ void **pServerVMT = *(void ***)server;
201+ pCGameServer = *(void **)((uintptr_t )pServerVMT[39 ]+0x16 ); // LightStyle
202+ }
203+ }
204+
205+ return true ;
206+ }
207+
208+ return false ;
209+ }
210+
211+ void CSamplePlugin::Unload ()
212+ {
213+ if (GetTickInterval)
214+ delete GetTickInterval;
215+ }
216+
217+ EXPOSE_SINGLE_INTERFACE_GLOBALVAR ( CSamplePlugin , IServerPluginCallbacks , INTERFACEVERSION_ISERVERPLUGINCALLBACKS , g_SamplePlugin );
0 commit comments