3 * =============================================================================
5 * Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved.
6 * =============================================================================
8 * This program is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, version 3.0, as published by the
10 * Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17 * You should have received a copy of the GNU General Public License along with
18 * this program. If not, see <http://www.gnu.org/licenses/>.
20 * As a special exception, AlliedModders LLC gives you permission to link the
21 * code of this program (as well as its derivative works) to "Half-Life 2," the
22 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
23 * by the Valve Corporation. You must obey the GNU General Public License in
24 * all respects for all other code used. Additionally, AlliedModders LLC grants
25 * this exception to all derivative works. AlliedModders LLC defines further
26 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
27 * or <http://www.sourcemod.net/license.php>.
33 #include "sourcemod.h"
34 #include "sourcemm_api.h"
35 #include "sm_globals.h"
36 #include "sm_autonatives.h"
37 #include "logic/intercom.h"
38 #include "LibrarySys.h"
39 #include "sm_stringutil.h"
41 #include "sm_srvcmds.h"
42 #include "ForwardSys.h"
44 #include "logic_bridge.h"
45 #include "PlayerManager.h"
46 #include "AdminCache.h"
47 #include "HalfLife2.h"
48 #include "CoreConfig.h"
49 #if SOURCE_ENGINE >= SE_ALIENSWARM
50 #include "convar_sm_swarm.h"
51 #elif SOURCE_ENGINE >= SE_LEFT4DEAD
52 #include "convar_sm_l4d.h"
53 #elif SOURCE_ENGINE >= SE_ORANGEBOX
54 #include "convar_sm_ob.h"
56 #include "convar_sm.h"
60 #define MATCHMAKINGDS_SUFFIX ""
61 #define MATCHMAKINGDS_EXT "dll"
62 #elif defined __APPLE__
63 #define MATCHMAKINGDS_SUFFIX ""
64 #define MATCHMAKINGDS_EXT "dylib"
65 #elif defined __linux__
66 #if SOURCE_ENGINE < SE_LEFT4DEAD2
67 #define MATCHMAKINGDS_SUFFIX "_i486"
69 #define MATCHMAKINGDS_SUFFIX ""
71 #define MATCHMAKINGDS_EXT "so"
74 static ILibrary *g_pLogic = NULL;
75 static LogicInitFunction logic_init_fn;
77 IThreader *g_pThreader;
78 ITextParsers *textparsers;
80 ITranslator *translator;
81 IScriptManager *scripts;
83 IExtensionSys *extsys;
84 IHandleSys *handlesys;
86 class VEngineServer_Logic : public IVEngineServer_Logic
89 virtual bool IsMapValid(const char *map)
91 return !!engine->IsMapValid(map);
94 virtual void ServerCommand(const char *cmd)
96 engine->ServerCommand(cmd);
100 static VEngineServer_Logic logic_engine;
102 static ConVar *find_convar(const char *name)
104 return icvar->FindVar(name);
107 static void log_error(const char *fmt, ...)
112 g_Logger.LogErrorEx(fmt, ap);
116 static void log_fatal(const char *fmt, ...)
121 g_Logger.LogFatalEx(fmt, ap);
125 static void log_message(const char *fmt, ...)
129 g_Logger.LogMessageEx(fmt, ap);
133 static void log_to_file(FILE *fp, const char *fmt, ...)
137 g_Logger.LogToOpenFileEx(fp, fmt, ap);
141 static void log_to_game(const char *message)
143 Engine_LogPrintWrapper(message);
146 static bool file_exists(const char *path)
148 return basefilesystem->FileExists(path);
151 static const char *get_cvar_string(ConVar* cvar)
153 return cvar->GetString();
156 static bool get_game_name(char *buffer, size_t maxlength)
158 KeyValues *pGameInfo = new KeyValues("GameInfo");
159 if (g_HL2.KVLoadFromFile(pGameInfo, basefilesystem, "gameinfo.txt"))
162 if ((str = pGameInfo->GetString("game", NULL)) != NULL)
164 strncopy(buffer, str, maxlength);
168 pGameInfo->deleteThis();
172 static const char *get_game_description()
174 return SERVER_CALL(GetGameDescription)();
177 static const char *get_source_engine_name()
179 #if !defined SOURCE_ENGINE
180 # error "Unknown engine type"
182 #if SOURCE_ENGINE == SE_EPISODEONE
184 #elif SOURCE_ENGINE == SE_DARKMESSIAH
185 return "darkmessiah";
186 #elif SOURCE_ENGINE == SE_ORANGEBOX
188 #elif SOURCE_ENGINE == SE_BLOODYGOODTIME
189 return "bloodygoodtime";
190 #elif SOURCE_ENGINE == SE_EYE
192 #elif SOURCE_ENGINE == SE_CSS
194 #elif SOURCE_ENGINE == SE_ORANGEBOXVALVE
195 return "orangebox_valve";
196 #elif SOURCE_ENGINE == SE_LEFT4DEAD
198 #elif SOURCE_ENGINE == SE_LEFT4DEAD2
200 #elif SOURCE_ENGINE == SE_ALIENSWARM
202 #elif SOURCE_ENGINE == SE_PORTAL2
204 #elif SOURCE_ENGINE == SE_CSGO
206 #elif SOURCE_ENGINE == SE_DOTA
211 static bool symbols_are_hidden()
213 #if (SOURCE_ENGINE == SE_CSS) || (SOURCE_ENGINE == SE_ORANGEBOXVALVE) || (SOURCE_ENGINE == SE_LEFT4DEAD) || (SOURCE_ENGINE == SE_LEFT4DEAD2) || (SOURCE_ENGINE == SE_CSGO) || (SOURCE_ENGINE == SE_DOTA)
220 static const char* get_core_config_value(const char* key)
222 return g_CoreConfig.GetCoreConfigValue(key);
225 static bool is_map_loading()
227 return g_SourceMod.IsMapLoading();
230 static bool is_map_running()
232 return g_SourceMod.IsMapRunning();
235 int read_cmd_argc(const CCommand &args)
240 static const char *read_cmd_arg(const CCommand &args, int arg)
242 return args.Arg(arg);
245 static int load_mms_plugin(const char *file, bool *ok, char *error, size_t maxlength)
248 PluginId id = g_pMMPlugins->Load(file, g_PLID, ignore_already, error, maxlength);
252 #ifndef METAMOD_PLAPI_VERSION
258 #ifndef METAMOD_PLAPI_VERSION
259 g_pMMPlugins->Query(id, file, status, source)
261 g_pMMPlugins->Query(id, NULL, &status, NULL)
263 && status < Pl_Paused))
275 static void unload_mms_plugin(int id)
278 g_pMMPlugins->Unload(id, true, ignore, sizeof(ignore));
281 void do_global_plugin_loads()
283 g_SourceMod.DoGlobalPluginLoads();
286 static ServerGlobals serverGlobals;
288 static sm_core_t core_bridge =
293 reinterpret_cast<IVEngineServer*>(&logic_engine),
318 get_game_description,
319 get_source_engine_name,
321 get_core_config_value,
328 do_global_plugin_loads,
329 SM_AreConfigsExecuted,
334 void InitLogicBridge()
336 serverGlobals.universalTime = g_pUniversalTime;
337 serverGlobals.frametime = &gpGlobals->frametime;
338 serverGlobals.interval_per_tick = &gpGlobals->interval_per_tick;
340 core_bridge.engineFactory = (void *)g_SMAPI->GetEngineFactory(false);
341 core_bridge.serverFactory = (void *)g_SMAPI->GetServerFactory(false);
344 char path[PLATFORM_MAX_PATH];
346 g_LibSys.PathFormat(path, sizeof(path), "%s/bin/matchmaking_ds%s.%s", g_SMAPI->GetBaseDir(), MATCHMAKINGDS_SUFFIX, MATCHMAKINGDS_EXT);
348 if ((mmlib = g_LibSys.OpenLibrary(path, NULL, 0)))
350 core_bridge.matchmakingDSFactory = mmlib->GetSymbolAddress("CreateInterface");
351 mmlib->CloseLibrary();
354 logic_init_fn(&core_bridge, &logicore);
356 /* Add SMGlobalClass instances */
357 SMGlobalClass* glob = SMGlobalClass::head;
358 while (glob->m_pGlobalClassNext != NULL)
360 glob = glob->m_pGlobalClassNext;
362 assert(glob->m_pGlobalClassNext == NULL);
363 glob->m_pGlobalClassNext = logicore.head;
365 g_pThreader = logicore.threader;
366 g_pSourcePawn2->SetProfiler(logicore.profiler);
367 translator = logicore.translator;
368 scripts = logicore.scripts;
369 sharesys = logicore.sharesys;
370 extsys = logicore.extsys;
371 g_pCoreIdent = logicore.core_ident;
372 handlesys = logicore.handlesys;
375 bool StartLogicBridge(char *error, size_t maxlength)
377 char file[PLATFORM_MAX_PATH];
379 /* Now it's time to load the logic binary */
380 g_SMAPI->PathFormat(file,
382 "%s/bin/sourcemod.logic." PLATFORM_LIB_EXT,
383 g_SourceMod.GetSourceModPath());
386 g_pLogic = g_LibSys.OpenLibrary(file, myerror, sizeof(myerror));
390 if (error && maxlength)
392 UTIL_Format(error, maxlength, "failed to load %s: %s", file, myerror);
397 LogicLoadFunction llf = (LogicLoadFunction)g_pLogic->GetSymbolAddress("logic_load");
400 g_pLogic->CloseLibrary();
401 if (error && maxlength)
403 UTIL_Format(error, maxlength, "could not find logic_load function");
408 GetITextParsers getitxt = (GetITextParsers)g_pLogic->GetSymbolAddress("get_textparsers");
409 textparsers = getitxt();
411 logic_init_fn = llf(SM_LOGIC_MAGIC);
416 void ShutdownLogicBridge()
418 g_pLogic->CloseLibrary();