dvander@2726: /** dvander@2726: * vim: set ts=4 sw=4 : 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 "NativeOwner.h" dvander@2726: #include "sm_autonatives.h" dvander@2726: #include "logic/intercom.h" dvander@2726: #include "LibrarySys.h" dvander@2726: #include "HandleSys.h" dvander@2726: #include "sm_stringutil.h" dvander@2726: #include "Logger.h" dvander@2726: #include "ShareSys.h" dvander@2728: #include "sm_srvcmds.h" dvander@2730: #include "ForwardSys.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" 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@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@2726: 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: dvander@2726: static void add_natives(sp_nativeinfo_t *natives) dvander@2726: { dvander@2726: g_pCoreNatives->AddNatives(natives); dvander@2726: } dvander@2726: 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@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@3791: static bool file_exists(const char *path) dvander@3791: { dvander@3791: return basefilesystem->FileExists(path); 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@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"; dvander@3010: #elif SOURCE_ENGINE == SE_ORANGEBOXVALVE dvander@3010: return "orangebox_valve"; dvander@3010: #elif SOURCE_ENGINE == SE_LEFT4DEAD dvander@3010: return "left4dead"; 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@3515: #elif SOURCE_ENGINE == SE_CSGO skamonkey@3515: return "csgo"; dvander@3010: #endif dvander@3010: } dvander@3010: dvander@3010: static bool symbols_are_hidden() dvander@3010: { skamonkey@3613: #if (SOURCE_ENGINE == SE_CSS) || (SOURCE_ENGINE == SE_ORANGEBOXVALVE) || (SOURCE_ENGINE == SE_LEFT4DEAD) || (SOURCE_ENGINE == SE_LEFT4DEAD2) || (SOURCE_ENGINE == SE_CSGO) 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); fyrenmoo@3366: } fyrenmoo@3366: dvander@2989: static ServerGlobals serverGlobals; dvander@2989: dvander@2726: static sm_core_t core_bridge = dvander@2726: { dvander@2726: /* Objects */ dvander@2726: &g_HandleSys, dvander@2726: NULL, dvander@2726: &g_SourceMod, dvander@2726: &g_LibSys, dvander@2726: reinterpret_cast(&logic_engine), dvander@2726: &g_ShareSys, dvander@2728: &g_RootMenu, dvander@2728: &g_PluginSys, dvander@2730: &g_Forwards, 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: add_natives, dvander@2726: find_convar, dvander@2726: strncopy, dvander@2726: UTIL_TrimWhitespace, dvander@2726: log_error, dvander@3791: log_message, dvander@3791: log_to_file, dvander@3791: log_to_game, dvander@3791: file_exists, 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@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@2726: core_bridge.core_ident = g_pCoreIdent; dvander@3010: core_bridge.engineFactory = (void *)g_SMAPI->GetEngineFactory(false); dvander@3010: core_bridge.serverFactory = (void *)g_SMAPI->GetServerFactory(false); 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@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: