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@2989: #include "DebugReporter.h"
dvander@2996: #include "PlayerManager.h"
dvander@3000: #include "AdminCache.h"
dvander@3001: #include "HalfLife2.h"
fyrenmoo@3366: #include "CoreConfig.h"
dvander@2726:
skamonkey@3320: #if defined _WIN32
skamonkey@3320: #define MATCHMAKINGDS_SUFFIX ""
skamonkey@3320: #define MATCHMAKINGDS_EXT "dll"
skamonkey@3320: #elif defined __APPLE__
skamonkey@3320: #define MATCHMAKINGDS_SUFFIX ""
skamonkey@3320: #define MATCHMAKINGDS_EXT "dylib"
skamonkey@3320: #elif defined __linux__
skamonkey@3320: #if SOURCE_ENGINE < SE_LEFT4DEAD2
skamonkey@3320: #define MATCHMAKINGDS_SUFFIX "_i486"
skamonkey@3320: #else
skamonkey@3320: #define MATCHMAKINGDS_SUFFIX ""
skamonkey@3320: #endif
skamonkey@3320: #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@2989: static void generate_error(IPluginContext *ctx, cell_t func_idx, int err, const char *fmt, ...)
dvander@2989: {
dvander@2989: va_list ap;
dvander@2989:
dvander@2989: va_start(ap, fmt);
dvander@2989: g_DbgReporter.GenerateErrorVA(ctx, func_idx, err, fmt, ap);
dvander@2989: va_end(ap);
dvander@2989: }
dvander@2989:
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,
dvander@2726: /* Functions */
dvander@2726: add_natives,
dvander@2726: find_convar,
dvander@2726: strncopy,
dvander@2726: UTIL_TrimWhitespace,
dvander@2726: log_error,
dvander@2726: get_cvar_string,
dvander@2884: UTIL_Format,
dvander@2989: generate_error,
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: