core/logic_bridge.cpp
author Nicholas Hastings <skamonkey@gmail.com>
Tue Jan 22 23:18:27 2013 -0500 (2013-01-22)
changeset 3749 4dc3d723c490
parent 3613 b0740093756d
child 3791 47e1ee9cea86
permissions -rw-r--r--
Triggering build against new mac libprotobuf.
     1 /**
     2  * vim: set ts=4 sw=4 :
     3  * =============================================================================
     4  * SourceMod
     5  * Copyright (C) 2004-2010 AlliedModders LLC.  All rights reserved.
     6  * =============================================================================
     7  *
     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.
    11  * 
    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
    15  * details.
    16  *
    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/>.
    19  *
    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>.
    28  *
    29  * Version: $Id$
    30  */
    31 #include <stdio.h>
    32 #include <assert.h>
    33 #include "sourcemod.h"
    34 #include "sourcemm_api.h"
    35 #include "sm_globals.h"
    36 #include "NativeOwner.h"
    37 #include "sm_autonatives.h"
    38 #include "logic/intercom.h"
    39 #include "LibrarySys.h"
    40 #include "HandleSys.h"
    41 #include "sm_stringutil.h"
    42 #include "Logger.h"
    43 #include "ShareSys.h"
    44 #include "sm_srvcmds.h"
    45 #include "ForwardSys.h"
    46 #include "TimerSys.h"
    47 #include "logic_bridge.h"
    48 #include "DebugReporter.h"
    49 #include "PlayerManager.h"
    50 #include "AdminCache.h"
    51 #include "HalfLife2.h"
    52 #include "CoreConfig.h"
    53 
    54 #if defined _WIN32
    55 	#define MATCHMAKINGDS_SUFFIX	""
    56 	#define MATCHMAKINGDS_EXT	"dll"
    57 #elif defined __APPLE__
    58 	#define MATCHMAKINGDS_SUFFIX	""
    59 	#define MATCHMAKINGDS_EXT	"dylib"
    60 #elif defined __linux__
    61 #if SOURCE_ENGINE < SE_LEFT4DEAD2
    62 	#define MATCHMAKINGDS_SUFFIX	"_i486"
    63 #else
    64 	#define MATCHMAKINGDS_SUFFIX	""
    65 #endif
    66 	#define MATCHMAKINGDS_EXT	"so"
    67 #endif
    68 
    69 static ILibrary *g_pLogic = NULL;
    70 static LogicInitFunction logic_init_fn;
    71 
    72 IThreader *g_pThreader;
    73 ITextParsers *textparsers;
    74 sm_logic_t logicore;
    75 ITranslator *translator;
    76 
    77 class VEngineServer_Logic : public IVEngineServer_Logic
    78 {
    79 public:
    80 	virtual bool IsMapValid(const char *map)
    81 	{
    82 		return engine->IsMapValid(map);
    83 	}
    84 
    85 	virtual void ServerCommand(const char *cmd)
    86 	{
    87 		engine->ServerCommand(cmd);
    88 	}
    89 };
    90 
    91 static VEngineServer_Logic logic_engine;
    92 
    93 static void add_natives(sp_nativeinfo_t *natives)
    94 {
    95 	g_pCoreNatives->AddNatives(natives);
    96 }
    97 
    98 static ConVar *find_convar(const char *name)
    99 {
   100 	return icvar->FindVar(name);
   101 }
   102 
   103 static void log_error(const char *fmt, ...)
   104 {
   105 	va_list ap;
   106 
   107 	va_start(ap, fmt);
   108 	g_Logger.LogErrorEx(fmt, ap);
   109 	va_end(ap);
   110 }
   111 
   112 static void generate_error(IPluginContext *ctx, cell_t func_idx, int err, const char *fmt, ...)
   113 {
   114 	va_list ap;
   115 	
   116 	va_start(ap, fmt);
   117 	g_DbgReporter.GenerateErrorVA(ctx, func_idx, err, fmt, ap);
   118 	va_end(ap);
   119 }
   120 
   121 static const char *get_cvar_string(ConVar* cvar)
   122 {
   123 	return cvar->GetString();
   124 }
   125 
   126 static bool get_game_name(char *buffer, size_t maxlength)
   127 {
   128 	KeyValues *pGameInfo = new KeyValues("GameInfo");
   129 	if (g_HL2.KVLoadFromFile(pGameInfo, basefilesystem, "gameinfo.txt"))
   130 	{
   131 		const char *str;
   132 		if ((str = pGameInfo->GetString("game", NULL)) != NULL)
   133 		{
   134 			strncopy(buffer, str, maxlength);
   135 			return true;
   136 		}
   137 	}
   138 	pGameInfo->deleteThis();
   139 	return false;
   140 }
   141 
   142 static const char *get_game_description()
   143 {
   144 	return SERVER_CALL(GetGameDescription)();
   145 }
   146 
   147 static const char *get_source_engine_name()
   148 {
   149 #if !defined SOURCE_ENGINE
   150 # error "Unknown engine type"
   151 #endif
   152 #if SOURCE_ENGINE == SE_EPISODEONE
   153 	return "original";
   154 #elif SOURCE_ENGINE == SE_DARKMESSIAH
   155 	return "darkmessiah";
   156 #elif SOURCE_ENGINE == SE_ORANGEBOX
   157 	return "orangebox";
   158 #elif SOURCE_ENGINE == SE_BLOODYGOODTIME
   159 	return "bloodygoodtime";
   160 #elif SOURCE_ENGINE == SE_EYE
   161 	return "eye";
   162 #elif SOURCE_ENGINE == SE_CSS
   163 	return "css";
   164 #elif SOURCE_ENGINE == SE_ORANGEBOXVALVE
   165 	return "orangebox_valve";
   166 #elif SOURCE_ENGINE == SE_LEFT4DEAD
   167 	return "left4dead";
   168 #elif SOURCE_ENGINE == SE_LEFT4DEAD2
   169 	return "left4dead2";
   170 #elif SOURCE_ENGINE == SE_ALIENSWARM
   171 	return "alienswarm";
   172 #elif SOURCE_ENGINE == SE_PORTAL2
   173 	return "portal2";
   174 #elif SOURCE_ENGINE == SE_CSGO
   175 	return "csgo";
   176 #endif
   177 }
   178 
   179 static bool symbols_are_hidden()
   180 {
   181 #if (SOURCE_ENGINE == SE_CSS) || (SOURCE_ENGINE == SE_ORANGEBOXVALVE) || (SOURCE_ENGINE == SE_LEFT4DEAD) || (SOURCE_ENGINE == SE_LEFT4DEAD2) || (SOURCE_ENGINE == SE_CSGO)
   182 	return true;
   183 #else
   184 	return false;
   185 #endif
   186 }
   187 
   188 static const char* get_core_config_value(const char* key)
   189 {
   190 	return g_CoreConfig.GetCoreConfigValue(key);
   191 }	
   192 
   193 static ServerGlobals serverGlobals;
   194 
   195 static sm_core_t core_bridge =
   196 {
   197 	/* Objects */
   198 	&g_HandleSys,
   199 	NULL,
   200 	&g_SourceMod,
   201 	&g_LibSys,
   202 	reinterpret_cast<IVEngineServer*>(&logic_engine),
   203 	&g_ShareSys,
   204 	&g_RootMenu,
   205 	&g_PluginSys,
   206 	&g_Forwards,
   207 	&g_Timers,
   208 	&g_Players,
   209 	&g_Admins,
   210 	&g_HL2,
   211 	/* Functions */
   212 	add_natives,
   213 	find_convar,
   214 	strncopy,
   215 	UTIL_TrimWhitespace,
   216 	log_error,
   217 	get_cvar_string,
   218 	UTIL_Format,
   219 	generate_error,
   220 	gnprintf,
   221 	atcprintf,
   222 	get_game_name,
   223 	get_game_description,
   224 	get_source_engine_name,
   225 	symbols_are_hidden,
   226 	get_core_config_value,
   227 	&serverGlobals
   228 };
   229 
   230 void InitLogicBridge()
   231 {
   232 	serverGlobals.universalTime = g_pUniversalTime;
   233 	serverGlobals.frametime = &gpGlobals->frametime;
   234 	serverGlobals.interval_per_tick = &gpGlobals->interval_per_tick;
   235 
   236 	core_bridge.core_ident = g_pCoreIdent;
   237 	core_bridge.engineFactory = (void *)g_SMAPI->GetEngineFactory(false);
   238 	core_bridge.serverFactory = (void *)g_SMAPI->GetServerFactory(false);
   239 
   240 	ILibrary *mmlib;
   241 	char path[PLATFORM_MAX_PATH];
   242 
   243 	g_LibSys.PathFormat(path, sizeof(path), "%s/bin/matchmaking_ds%s.%s", g_SMAPI->GetBaseDir(), MATCHMAKINGDS_SUFFIX, MATCHMAKINGDS_EXT);
   244 
   245 	if ((mmlib = g_LibSys.OpenLibrary(path, NULL, 0)))
   246 	{
   247 		core_bridge.matchmakingDSFactory = mmlib->GetSymbolAddress("CreateInterface");
   248 		mmlib->CloseLibrary();
   249 	}
   250 	
   251 	logic_init_fn(&core_bridge, &logicore);
   252 
   253 	/* Add SMGlobalClass instances */
   254 	SMGlobalClass* glob = SMGlobalClass::head;
   255 	while (glob->m_pGlobalClassNext != NULL)
   256 	{
   257 		glob = glob->m_pGlobalClassNext;
   258 	}
   259 	assert(glob->m_pGlobalClassNext == NULL);
   260 	glob->m_pGlobalClassNext = logicore.head;
   261 
   262 	g_pThreader = logicore.threader;
   263 	g_pSourcePawn2->SetProfiler(logicore.profiler);
   264 	translator = logicore.translator;
   265 }
   266 
   267 bool StartLogicBridge(char *error, size_t maxlength)
   268 {
   269 	char file[PLATFORM_MAX_PATH];
   270 
   271 	/* Now it's time to load the logic binary */
   272 	g_SMAPI->PathFormat(file,
   273 		sizeof(file),
   274 		"%s/bin/sourcemod.logic." PLATFORM_LIB_EXT,
   275 		g_SourceMod.GetSourceModPath());
   276 
   277 	char myerror[255];
   278 	g_pLogic = g_LibSys.OpenLibrary(file, myerror, sizeof(myerror));
   279 
   280 	if (!g_pLogic)
   281 	{
   282 		if (error && maxlength)
   283 		{
   284 			UTIL_Format(error, maxlength, "failed to load %s: %s", file, myerror);
   285 		}
   286 		return false;
   287 	}
   288 
   289 	LogicLoadFunction llf = (LogicLoadFunction)g_pLogic->GetSymbolAddress("logic_load");
   290 	if (llf == NULL)
   291 	{
   292 		g_pLogic->CloseLibrary();
   293 		if (error && maxlength)
   294 		{
   295 			UTIL_Format(error, maxlength, "could not find logic_load function");
   296 		}
   297 		return false;
   298 	}
   299 
   300 	GetITextParsers getitxt = (GetITextParsers)g_pLogic->GetSymbolAddress("get_textparsers");
   301 	textparsers = getitxt();
   302 
   303 	logic_init_fn = llf(SM_LOGIC_MAGIC);
   304 
   305 	return true;
   306 }
   307 
   308 void ShutdownLogicBridge()
   309 {
   310 	g_pLogic->CloseLibrary();
   311 }
   312