dvander@2726: /** dvander@4029: * vim: set ts=4 sw=4 tw=99 noet: dvander@2726: * ============================================================================= dvander@2726: * SourceMod ds@3099: * Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved. dvander@2726: * ============================================================================= dvander@2726: * dvander@2726: * This program is free software; you can redistribute it and/or modify it under dvander@2726: * the terms of the GNU General Public License, version 3.0, as published by the dvander@2726: * Free Software Foundation. dvander@2726: * dvander@2726: * This program is distributed in the hope that it will be useful, but WITHOUT dvander@2726: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS dvander@2726: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more dvander@2726: * details. dvander@2726: * dvander@2726: * You should have received a copy of the GNU General Public License along with dvander@2726: * this program. If not, see . dvander@2726: * dvander@2726: * As a special exception, AlliedModders LLC gives you permission to link the dvander@2726: * code of this program (as well as its derivative works) to "Half-Life 2," the dvander@2726: * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software dvander@2726: * by the Valve Corporation. You must obey the GNU General Public License in dvander@2726: * all respects for all other code used. Additionally, AlliedModders LLC grants dvander@2726: * this exception to all derivative works. AlliedModders LLC defines further dvander@2726: * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), dvander@2726: * or . dvander@2726: * dvander@2726: * Version: $Id$ dvander@2726: */ dvander@2726: #include dvander@2726: #include dvander@2726: #include "sourcemod.h" dvander@2726: #include "sourcemm_api.h" dvander@2726: #include "sm_globals.h" dvander@2726: #include "sm_autonatives.h" dvander@2726: #include "logic/intercom.h" dvander@2726: #include "LibrarySys.h" dvander@2726: #include "sm_stringutil.h" dvander@2726: #include "Logger.h" dvander@2728: #include "sm_srvcmds.h" dvander@2989: #include "TimerSys.h" dvander@2906: #include "logic_bridge.h" dvander@2996: #include "PlayerManager.h" dvander@3000: #include "AdminCache.h" dvander@3001: #include "HalfLife2.h" fyrenmoo@3366: #include "CoreConfig.h" skamonkey@4138: #include "IDBDriver.h" skamonkey@3899: #if SOURCE_ENGINE == SE_DOTA skamonkey@3899: #include "convar_sm_dota.h" skamonkey@3899: #elif SOURCE_ENGINE >= SE_ALIENSWARM dvander@3872: #include "convar_sm_swarm.h" dvander@3872: #elif SOURCE_ENGINE >= SE_LEFT4DEAD dvander@3872: #include "convar_sm_l4d.h" dvander@3872: #elif SOURCE_ENGINE >= SE_ORANGEBOX dvander@3872: #include "convar_sm_ob.h" dvander@3872: #else dvander@3872: #include "convar_sm.h" dvander@3872: #endif dvander@2726: dvander@3791: #if defined _WIN32 dvander@3791: #define MATCHMAKINGDS_SUFFIX "" dvander@3791: #define MATCHMAKINGDS_EXT "dll" dvander@3791: #elif defined __APPLE__ dvander@3791: #define MATCHMAKINGDS_SUFFIX "" dvander@3791: #define MATCHMAKINGDS_EXT "dylib" dvander@3791: #elif defined __linux__ skamonkey@3320: #if SOURCE_ENGINE < SE_LEFT4DEAD2 skamonkey@3320: #define MATCHMAKINGDS_SUFFIX "_i486" skamonkey@3320: #else skamonkey@3320: #define MATCHMAKINGDS_SUFFIX "" dvander@3791: #endif dvander@3791: #define MATCHMAKINGDS_EXT "so" skamonkey@3320: #endif skamonkey@3320: dvander@2726: static ILibrary *g_pLogic = NULL; dvander@2726: static LogicInitFunction logic_init_fn; dvander@2726: dvander@2726: IThreader *g_pThreader; dvander@2726: ITextParsers *textparsers; dvander@3002: sm_logic_t logicore; dvander@3004: ITranslator *translator; dvander@3872: IScriptManager *scripts; dvander@3872: IShareSys *sharesys; dvander@3872: IExtensionSys *extsys; dvander@3872: IHandleSys *handlesys; skamonkey@4139: IForwardManager *forwardsys; dvander@2726: dvander@2726: class VEngineServer_Logic : public IVEngineServer_Logic dvander@2726: { dvander@2726: public: dvander@2726: virtual bool IsMapValid(const char *map) dvander@2726: { dvander@3872: return !!engine->IsMapValid(map); dvander@2726: } dvander@3001: dvander@3001: virtual void ServerCommand(const char *cmd) dvander@3001: { dvander@3001: engine->ServerCommand(cmd); dvander@3001: } dvander@2726: }; dvander@2726: dvander@2726: static VEngineServer_Logic logic_engine; dvander@2726: voidedweasel@3929: voidedweasel@3929: class VFileSystem_Logic : public IFileSystem_Logic voidedweasel@3929: { voidedweasel@3929: public: voidedweasel@3929: const char *FindFirstEx(const char *pWildCard, const char *pPathID, FileFindHandle_t *pHandle) voidedweasel@3929: { voidedweasel@3929: return filesystem->FindFirstEx(pWildCard, pPathID, pHandle); voidedweasel@3929: } voidedweasel@3929: const char *FindNext(FileFindHandle_t handle) voidedweasel@3929: { voidedweasel@3929: return filesystem->FindNext(handle); voidedweasel@3929: } voidedweasel@3929: void FindClose(FileFindHandle_t handle) voidedweasel@3929: { voidedweasel@3929: filesystem->FindClose(handle); voidedweasel@3929: } skamonkey@4196: FileHandle_t Open(const char *pFileName, const char *pOptions, const char *pathID = 0) skamonkey@4196: { skamonkey@4196: return filesystem->Open(pFileName, pOptions, pathID); skamonkey@4196: } skamonkey@4196: void Close(FileHandle_t file) skamonkey@4196: { skamonkey@4196: filesystem->Close(file); skamonkey@4196: } skamonkey@4196: char *ReadLine(char *pOutput, int maxChars, FileHandle_t file) skamonkey@4196: { skamonkey@4196: return filesystem->ReadLine(pOutput, maxChars, file); skamonkey@4196: } skamonkey@4196: bool EndOfFile(FileHandle_t file) skamonkey@4196: { skamonkey@4196: return filesystem->EndOfFile(file); skamonkey@4196: } skamonkey@4196: bool FileExists(const char *pFileName, const char *pPathID = 0) skamonkey@4196: { skamonkey@4196: return filesystem->FileExists(pFileName, pPathID); skamonkey@4196: } skamonkey@4199: unsigned int Size(const char *pFileName, const char *pPathID = 0) skamonkey@4199: { skamonkey@4199: return filesystem->Size(pFileName, pPathID); skamonkey@4199: } voidedweasel@3929: }; voidedweasel@3929: voidedweasel@3929: static VFileSystem_Logic logic_filesystem; voidedweasel@3929: voidedweasel@3929: dvander@2726: static ConVar *find_convar(const char *name) dvander@2726: { dvander@2726: return icvar->FindVar(name); dvander@2726: } dvander@2726: dvander@2726: static void log_error(const char *fmt, ...) dvander@2726: { dvander@2726: va_list ap; dvander@2726: dvander@2726: va_start(ap, fmt); dvander@2726: g_Logger.LogErrorEx(fmt, ap); dvander@2726: va_end(ap); dvander@2726: } dvander@2726: dvander@3872: static void log_fatal(const char *fmt, ...) dvander@3872: { dvander@3872: va_list ap; dvander@3872: dvander@3872: va_start(ap, fmt); dvander@3872: g_Logger.LogFatalEx(fmt, ap); dvander@3872: va_end(ap); dvander@3872: } dvander@3872: dvander@3791: static void log_message(const char *fmt, ...) dvander@3791: { dvander@3791: va_list ap; dvander@3791: va_start(ap, fmt); dvander@3791: g_Logger.LogMessageEx(fmt, ap); dvander@3791: va_end(ap); dvander@3791: } dvander@3791: dvander@3791: static void log_to_file(FILE *fp, const char *fmt, ...) dvander@3791: { dvander@3791: va_list ap; dvander@3791: va_start(ap, fmt); dvander@3791: g_Logger.LogToOpenFileEx(fp, fmt, ap); dvander@3791: va_end(ap); dvander@3791: } dvander@3791: dvander@3791: static void log_to_game(const char *message) dvander@3791: { dvander@3791: Engine_LogPrintWrapper(message); dvander@3791: } dvander@3791: dvander@2726: static const char *get_cvar_string(ConVar* cvar) dvander@2726: { dvander@2726: return cvar->GetString(); dvander@2726: } dvander@2726: dvander@3010: static bool get_game_name(char *buffer, size_t maxlength) dvander@3010: { dvander@3010: KeyValues *pGameInfo = new KeyValues("GameInfo"); dvander@3010: if (g_HL2.KVLoadFromFile(pGameInfo, basefilesystem, "gameinfo.txt")) dvander@3010: { dvander@3010: const char *str; dvander@3010: if ((str = pGameInfo->GetString("game", NULL)) != NULL) dvander@3010: { dvander@3010: strncopy(buffer, str, maxlength); dvander@4156: pGameInfo->deleteThis(); dvander@3010: return true; dvander@3010: } dvander@3010: } dvander@3010: pGameInfo->deleteThis(); dvander@3010: return false; dvander@3010: } dvander@3010: dvander@3010: static const char *get_game_description() dvander@3010: { dvander@3010: return SERVER_CALL(GetGameDescription)(); dvander@3010: } dvander@3010: dvander@3010: static const char *get_source_engine_name() dvander@3010: { dvander@3010: #if !defined SOURCE_ENGINE dvander@3010: # error "Unknown engine type" dvander@3010: #endif dvander@3010: #if SOURCE_ENGINE == SE_EPISODEONE dvander@3010: return "original"; dvander@3010: #elif SOURCE_ENGINE == SE_DARKMESSIAH dvander@3010: return "darkmessiah"; dvander@3010: #elif SOURCE_ENGINE == SE_ORANGEBOX dvander@3010: return "orangebox"; skamonkey@3180: #elif SOURCE_ENGINE == SE_BLOODYGOODTIME skamonkey@3180: return "bloodygoodtime"; skamonkey@3373: #elif SOURCE_ENGINE == SE_EYE skamonkey@3373: return "eye"; skamonkey@3613: #elif SOURCE_ENGINE == SE_CSS skamonkey@3613: return "css"; skamonkey@3961: #elif SOURCE_ENGINE == SE_HL2DM skamonkey@3961: return "hl2dm"; skamonkey@3961: #elif SOURCE_ENGINE == SE_DODS skamonkey@3961: return "dods"; skamonkey@4141: #elif SOURCE_ENGINE == SE_SDK2013 skamonkey@4141: return "sdk2013"; skamonkey@3961: #elif SOURCE_ENGINE == SE_TF2 skamonkey@3961: return "tf2"; dvander@3010: #elif SOURCE_ENGINE == SE_LEFT4DEAD dvander@3010: return "left4dead"; skamonkey@3961: #elif SOURCE_ENGINE == SE_NUCLEARDAWN skamonkey@3961: return "nucleardawn"; skamonkey@4301: #elif SOURCE_ENGINE == SE_CONTAGION skamonkey@4301: return "contagion"; dvander@3010: #elif SOURCE_ENGINE == SE_LEFT4DEAD2 dvander@3010: return "left4dead2"; ds@3099: #elif SOURCE_ENGINE == SE_ALIENSWARM ds@3099: return "alienswarm"; skamonkey@3515: #elif SOURCE_ENGINE == SE_PORTAL2 skamonkey@3515: return "portal2"; skamonkey@4142: #elif SOURCE_ENGINE == SE_BLADE skamonkey@4142: return "blade"; skamonkey@4144: #elif SOURCE_ENGINE == SE_INSURGENCY skamonkey@4144: return "insurgency"; skamonkey@3515: #elif SOURCE_ENGINE == SE_CSGO skamonkey@3515: return "csgo"; skamonkey@3853: #elif SOURCE_ENGINE == SE_DOTA skamonkey@3853: return "dota"; dvander@3010: #endif dvander@3010: } dvander@3010: dvander@3010: static bool symbols_are_hidden() dvander@3010: { skamonkey@4141: #if (SOURCE_ENGINE == SE_CSS) \ skamonkey@4141: || (SOURCE_ENGINE == SE_HL2DM) \ skamonkey@4141: || (SOURCE_ENGINE == SE_DODS) \ skamonkey@4141: || (SOURCE_ENGINE == SE_SDK2013) \ skamonkey@4141: || (SOURCE_ENGINE == SE_TF2) \ skamonkey@4141: || (SOURCE_ENGINE == SE_LEFT4DEAD) \ skamonkey@4141: || (SOURCE_ENGINE == SE_NUCLEARDAWN) \ skamonkey@4141: || (SOURCE_ENGINE == SE_LEFT4DEAD2) \ skamonkey@4144: || (SOURCE_ENGINE == SE_INSURGENCY) \ skamonkey@4142: || (SOURCE_ENGINE == SE_BLADE) \ skamonkey@4141: || (SOURCE_ENGINE == SE_CSGO) \ skamonkey@4141: || (SOURCE_ENGINE == SE_DOTA) dvander@3010: return true; dvander@3010: #else dvander@3010: return false; dvander@3010: #endif dvander@3010: } dvander@3010: fyrenmoo@3366: static const char* get_core_config_value(const char* key) fyrenmoo@3366: { fyrenmoo@3366: return g_CoreConfig.GetCoreConfigValue(key); dvander@3872: } dvander@3872: dvander@3872: static bool is_map_loading() dvander@3872: { dvander@3872: return g_SourceMod.IsMapLoading(); dvander@3872: } dvander@3872: dvander@3872: static bool is_map_running() dvander@3872: { dvander@3872: return g_SourceMod.IsMapRunning(); dvander@3872: } dvander@3872: skamonkey@4138: static DatabaseInfo keyvalues_to_dbinfo(KeyValues *kv) skamonkey@4138: { skamonkey@4138: DatabaseInfo info; skamonkey@4138: info.database = kv->GetString("database", ""); skamonkey@4138: info.driver = kv->GetString("driver", "default"); skamonkey@4138: info.host = kv->GetString("host", ""); skamonkey@4138: info.maxTimeout = kv->GetInt("timeout", 0); skamonkey@4138: info.pass = kv->GetString("pass", ""); skamonkey@4138: info.port = kv->GetInt("port", 0); skamonkey@4138: info.user = kv->GetString("user", ""); skamonkey@4138: return info; skamonkey@4138: } skamonkey@4138: dvander@3872: int read_cmd_argc(const CCommand &args) dvander@3872: { dvander@3872: return args.ArgC(); dvander@3872: } dvander@3872: dvander@3872: static const char *read_cmd_arg(const CCommand &args, int arg) dvander@3872: { dvander@3872: return args.Arg(arg); dvander@3872: } dvander@3872: dvander@3872: static int load_mms_plugin(const char *file, bool *ok, char *error, size_t maxlength) dvander@3872: { dvander@3872: bool ignore_already; dvander@3872: PluginId id = g_pMMPlugins->Load(file, g_PLID, ignore_already, error, maxlength); dvander@3872: dvander@3872: Pl_Status status; dvander@3872: dvander@3872: #ifndef METAMOD_PLAPI_VERSION dvander@3874: const char *filep; dvander@3872: PluginId source; dvander@3872: #endif dvander@3872: dvander@3872: if (!id || ( dvander@3872: #ifndef METAMOD_PLAPI_VERSION dvander@3874: g_pMMPlugins->Query(id, filep, status, source) dvander@3872: #else dvander@3872: g_pMMPlugins->Query(id, NULL, &status, NULL) dvander@3872: #endif dvander@3872: && status < Pl_Paused)) dvander@3872: { dvander@3872: *ok = false; dvander@3872: } dvander@3872: else dvander@3872: { dvander@3872: *ok = true; dvander@3872: } dvander@3872: dvander@3872: return id; dvander@3872: } dvander@3872: dvander@3872: static void unload_mms_plugin(int id) dvander@3872: { dvander@3872: char ignore[255]; dvander@3872: g_pMMPlugins->Unload(id, true, ignore, sizeof(ignore)); dvander@3872: } dvander@3872: dvander@3872: void do_global_plugin_loads() dvander@3872: { dvander@3872: g_SourceMod.DoGlobalPluginLoads(); dvander@3872: } fyrenmoo@3366: dvander@3882: #if defined METAMOD_PLAPI_VERSION dvander@3882: #if SOURCE_ENGINE == SE_LEFT4DEAD dvander@3882: #define GAMEFIX "2.l4d" dvander@3882: #elif SOURCE_ENGINE == SE_LEFT4DEAD2 dvander@3882: #define GAMEFIX "2.l4d2" skamonkey@4320: #elif SOURCE_ENGINE == SE_NUCLEARDAWN skamonkey@4320: #define GAMEFIX "2.nd" dvander@3882: #elif SOURCE_ENGINE == SE_ALIENSWARM dvander@3882: #define GAMEFIX "2.swarm" dvander@3882: #elif SOURCE_ENGINE == SE_ORANGEBOX dvander@3882: #define GAMEFIX "2.ep2" dvander@3882: #elif SOURCE_ENGINE == SE_BLOODYGOODTIME dvander@3882: #define GAMEFIX "2.bgt" dvander@3882: #elif SOURCE_ENGINE == SE_EYE dvander@3882: #define GAMEFIX "2.eye" dvander@3882: #elif SOURCE_ENGINE == SE_CSS dvander@3882: #define GAMEFIX "2.css" skamonkey@3961: #elif SOURCE_ENGINE == SE_HL2DM skamonkey@3961: #define GAMEFIX "2.hl2dm" skamonkey@3961: #elif SOURCE_ENGINE == SE_DODS skamonkey@3961: #define GAMEFIX "2.dods" skamonkey@4141: #elif SOURCE_ENGINE == SE_SDK2013 skamonkey@4141: #define GAMEFIX "2.sdk2013" skamonkey@3961: #elif SOURCE_ENGINE == SE_TF2 skamonkey@3961: #define GAMEFIX "2.tf2" dvander@3882: #elif SOURCE_ENGINE == SE_DARKMESSIAH dvander@3882: #define GAMEFIX "2.darkm" dvander@3882: #elif SOURCE_ENGINE == SE_PORTAL2 dvander@3882: #define GAMEFIX "2.portal2" skamonkey@4142: #elif SOURCE_ENGINE == SE_BLADE skamonkey@4142: #define GAMEFIX "2.blade" skamonkey@4144: #elif SOURCE_ENGINE == SE_INSURGENCY skamonkey@4144: #define GAMEFIX "2.insurgency" dvander@3882: #elif SOURCE_ENGINE == SE_CSGO dvander@3882: #define GAMEFIX "2.csgo" dvander@3882: #elif SOURCE_ENGINE == SE_DOTA dvander@3882: #define GAMEFIX "2.dota" skamonkey@4301: #elif SOURCE_ENGINE == SE_CONTAGION skamonkey@4301: #define GAMEFIX "2.contagion" dvander@3882: #else dvander@3882: #define GAMEFIX "2.ep1" dvander@3882: #endif //(SOURCE_ENGINE == SE_LEFT4DEAD) || (SOURCE_ENGINE == SE_LEFT4DEAD2) dvander@3882: #else //METAMOD_PLAPI_VERSION dvander@3882: #define GAMEFIX "1.ep1" dvander@3882: #endif //METAMOD_PLAPI_VERSION dvander@3882: dvander@2989: static ServerGlobals serverGlobals; dvander@2989: dvander@2726: static sm_core_t core_bridge = dvander@2726: { dvander@2726: /* Objects */ dvander@2726: &g_SourceMod, dvander@2726: &g_LibSys, dvander@2726: reinterpret_cast(&logic_engine), voidedweasel@3929: reinterpret_cast(&logic_filesystem), dvander@2728: &g_RootMenu, dvander@2989: &g_Timers, dvander@2996: &g_Players, dvander@3000: &g_Admins, dvander@3001: &g_HL2, skamonkey@3800: &g_pSourcePawn, skamonkey@3800: &g_pSourcePawn2, dvander@2726: /* Functions */ dvander@2726: find_convar, dvander@2726: strncopy, dvander@2726: UTIL_TrimWhitespace, dvander@2726: log_error, dvander@3872: log_fatal, dvander@3791: log_message, dvander@3791: log_to_file, dvander@3791: log_to_game, dvander@2726: get_cvar_string, dvander@2884: UTIL_Format, dvander@3792: UTIL_FormatArgs, dvander@3004: gnprintf, dvander@3006: atcprintf, dvander@3010: get_game_name, dvander@3010: get_game_description, dvander@3010: get_source_engine_name, dvander@3010: symbols_are_hidden, fyrenmoo@3366: get_core_config_value, dvander@3872: is_map_loading, dvander@3872: is_map_running, dvander@3872: read_cmd_argc, dvander@3872: read_cmd_arg, dvander@3872: load_mms_plugin, dvander@3872: unload_mms_plugin, dvander@3872: do_global_plugin_loads, dvander@3872: SM_AreConfigsExecuted, dvander@3872: SM_ExecuteForPlugin, skamonkey@4138: keyvalues_to_dbinfo, dvander@3882: GAMEFIX, dvander@2989: &serverGlobals dvander@2726: }; dvander@2726: dvander@2726: void InitLogicBridge() dvander@2726: { dvander@2989: serverGlobals.universalTime = g_pUniversalTime; dvander@2989: serverGlobals.frametime = &gpGlobals->frametime; dvander@2989: serverGlobals.interval_per_tick = &gpGlobals->interval_per_tick; dvander@2989: dvander@3010: core_bridge.engineFactory = (void *)g_SMAPI->GetEngineFactory(false); dvander@3010: core_bridge.serverFactory = (void *)g_SMAPI->GetServerFactory(false); dvander@4029: core_bridge.listeners = SMGlobalClass::head; skamonkey@3320: skamonkey@3320: ILibrary *mmlib; skamonkey@3320: char path[PLATFORM_MAX_PATH]; skamonkey@3320: skamonkey@3320: g_LibSys.PathFormat(path, sizeof(path), "%s/bin/matchmaking_ds%s.%s", g_SMAPI->GetBaseDir(), MATCHMAKINGDS_SUFFIX, MATCHMAKINGDS_EXT); skamonkey@3320: skamonkey@3321: if ((mmlib = g_LibSys.OpenLibrary(path, NULL, 0))) skamonkey@3320: { skamonkey@3320: core_bridge.matchmakingDSFactory = mmlib->GetSymbolAddress("CreateInterface"); skamonkey@3320: mmlib->CloseLibrary(); skamonkey@3320: } skamonkey@3320: dvander@3002: logic_init_fn(&core_bridge, &logicore); dvander@2726: dvander@2726: /* Add SMGlobalClass instances */ dvander@2726: SMGlobalClass* glob = SMGlobalClass::head; dvander@2726: while (glob->m_pGlobalClassNext != NULL) dvander@2726: { dvander@2726: glob = glob->m_pGlobalClassNext; dvander@2726: } dvander@2726: assert(glob->m_pGlobalClassNext == NULL); dvander@3002: glob->m_pGlobalClassNext = logicore.head; dvander@2726: dvander@3002: g_pThreader = logicore.threader; dvander@3002: g_pSourcePawn2->SetProfiler(logicore.profiler); dvander@3004: translator = logicore.translator; dvander@3872: scripts = logicore.scripts; dvander@3872: sharesys = logicore.sharesys; dvander@3872: extsys = logicore.extsys; dvander@3872: g_pCoreIdent = logicore.core_ident; dvander@3872: handlesys = logicore.handlesys; skamonkey@4139: forwardsys = logicore.forwardsys; dvander@2726: } dvander@2726: dvander@2726: bool StartLogicBridge(char *error, size_t maxlength) dvander@2726: { dvander@2726: char file[PLATFORM_MAX_PATH]; dvander@2726: dvander@2726: /* Now it's time to load the logic binary */ dvander@2726: g_SMAPI->PathFormat(file, dvander@2726: sizeof(file), dvander@2726: "%s/bin/sourcemod.logic." PLATFORM_LIB_EXT, dvander@2726: g_SourceMod.GetSourceModPath()); dvander@2726: dvander@2726: char myerror[255]; dvander@2726: g_pLogic = g_LibSys.OpenLibrary(file, myerror, sizeof(myerror)); dvander@2726: dvander@2726: if (!g_pLogic) dvander@2726: { dvander@2726: if (error && maxlength) dvander@2726: { dvander@2726: UTIL_Format(error, maxlength, "failed to load %s: %s", file, myerror); dvander@2726: } dvander@2726: return false; dvander@2726: } dvander@2726: dvander@2726: LogicLoadFunction llf = (LogicLoadFunction)g_pLogic->GetSymbolAddress("logic_load"); dvander@2726: if (llf == NULL) dvander@2726: { dvander@2726: g_pLogic->CloseLibrary(); dvander@2726: if (error && maxlength) dvander@2726: { dvander@2726: UTIL_Format(error, maxlength, "could not find logic_load function"); dvander@2726: } dvander@2726: return false; dvander@2726: } dvander@2726: dvander@2726: GetITextParsers getitxt = (GetITextParsers)g_pLogic->GetSymbolAddress("get_textparsers"); dvander@2726: textparsers = getitxt(); dvander@2726: dvander@2726: logic_init_fn = llf(SM_LOGIC_MAGIC); dvander@2726: dvander@2726: return true; dvander@2726: } dvander@2726: dvander@2726: void ShutdownLogicBridge() dvander@2726: { dvander@2726: g_pLogic->CloseLibrary(); dvander@2726: } dvander@2726: