2009-05-14 03:55:50 +02:00
|
|
|
/**
|
|
|
|
* vim: set ts=4 sw=4 :
|
|
|
|
* =============================================================================
|
|
|
|
* SourceMod
|
2010-07-28 00:32:32 +02:00
|
|
|
* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved.
|
2009-05-14 03:55:50 +02:00
|
|
|
* =============================================================================
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify it under
|
|
|
|
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
|
|
* Free Software Foundation.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
|
|
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
|
|
* details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License along with
|
|
|
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*
|
|
|
|
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
|
|
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
|
|
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
|
|
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
|
|
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
|
|
* this exception to all derivative works. AlliedModders LLC defines further
|
|
|
|
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
|
|
* or <http://www.sourcemod.net/license.php>.
|
|
|
|
*
|
|
|
|
* Version: $Id$
|
|
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <assert.h>
|
|
|
|
#include "sourcemod.h"
|
|
|
|
#include "sourcemm_api.h"
|
|
|
|
#include "sm_globals.h"
|
|
|
|
#include "sm_autonatives.h"
|
|
|
|
#include "logic/intercom.h"
|
|
|
|
#include "LibrarySys.h"
|
|
|
|
#include "sm_stringutil.h"
|
|
|
|
#include "Logger.h"
|
2009-05-14 17:24:07 +02:00
|
|
|
#include "sm_srvcmds.h"
|
2009-05-14 17:38:50 +02:00
|
|
|
#include "ForwardSys.h"
|
2010-05-13 10:47:12 +02:00
|
|
|
#include "TimerSys.h"
|
2010-01-18 12:08:52 +01:00
|
|
|
#include "logic_bridge.h"
|
2010-05-13 21:28:51 +02:00
|
|
|
#include "PlayerManager.h"
|
2010-05-15 02:46:19 +02:00
|
|
|
#include "AdminCache.h"
|
2010-05-15 03:22:03 +02:00
|
|
|
#include "HalfLife2.h"
|
2011-07-25 04:52:22 +02:00
|
|
|
#include "CoreConfig.h"
|
2013-03-29 19:37:29 +01:00
|
|
|
#if SOURCE_ENGINE >= SE_ALIENSWARM
|
|
|
|
#include "convar_sm_swarm.h"
|
|
|
|
#elif SOURCE_ENGINE >= SE_LEFT4DEAD
|
|
|
|
#include "convar_sm_l4d.h"
|
|
|
|
#elif SOURCE_ENGINE >= SE_ORANGEBOX
|
|
|
|
#include "convar_sm_ob.h"
|
|
|
|
#else
|
|
|
|
#include "convar_sm.h"
|
|
|
|
#endif
|
2009-05-14 03:55:50 +02:00
|
|
|
|
2013-02-17 00:52:11 +01:00
|
|
|
#if defined _WIN32
|
|
|
|
#define MATCHMAKINGDS_SUFFIX ""
|
|
|
|
#define MATCHMAKINGDS_EXT "dll"
|
|
|
|
#elif defined __APPLE__
|
|
|
|
#define MATCHMAKINGDS_SUFFIX ""
|
|
|
|
#define MATCHMAKINGDS_EXT "dylib"
|
|
|
|
#elif defined __linux__
|
2011-06-27 15:30:52 +02:00
|
|
|
#if SOURCE_ENGINE < SE_LEFT4DEAD2
|
|
|
|
#define MATCHMAKINGDS_SUFFIX "_i486"
|
|
|
|
#else
|
|
|
|
#define MATCHMAKINGDS_SUFFIX ""
|
2013-02-17 00:52:11 +01:00
|
|
|
#endif
|
|
|
|
#define MATCHMAKINGDS_EXT "so"
|
2011-06-27 15:30:52 +02:00
|
|
|
#endif
|
|
|
|
|
2009-05-14 03:55:50 +02:00
|
|
|
static ILibrary *g_pLogic = NULL;
|
|
|
|
static LogicInitFunction logic_init_fn;
|
|
|
|
|
|
|
|
IThreader *g_pThreader;
|
|
|
|
ITextParsers *textparsers;
|
2010-05-15 04:28:10 +02:00
|
|
|
sm_logic_t logicore;
|
2010-05-15 04:43:53 +02:00
|
|
|
ITranslator *translator;
|
2013-03-29 19:37:29 +01:00
|
|
|
IScriptManager *scripts;
|
|
|
|
IShareSys *sharesys;
|
|
|
|
IExtensionSys *extsys;
|
|
|
|
IHandleSys *handlesys;
|
2009-05-14 03:55:50 +02:00
|
|
|
|
|
|
|
class VEngineServer_Logic : public IVEngineServer_Logic
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
virtual bool IsMapValid(const char *map)
|
|
|
|
{
|
2013-03-29 19:37:29 +01:00
|
|
|
return !!engine->IsMapValid(map);
|
2009-05-14 03:55:50 +02:00
|
|
|
}
|
2010-05-15 03:22:03 +02:00
|
|
|
|
|
|
|
virtual void ServerCommand(const char *cmd)
|
|
|
|
{
|
|
|
|
engine->ServerCommand(cmd);
|
|
|
|
}
|
2009-05-14 03:55:50 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
static VEngineServer_Logic logic_engine;
|
|
|
|
|
|
|
|
static ConVar *find_convar(const char *name)
|
|
|
|
{
|
|
|
|
return icvar->FindVar(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void log_error(const char *fmt, ...)
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
va_start(ap, fmt);
|
|
|
|
g_Logger.LogErrorEx(fmt, ap);
|
|
|
|
va_end(ap);
|
|
|
|
}
|
|
|
|
|
2013-03-29 19:37:29 +01:00
|
|
|
static void log_fatal(const char *fmt, ...)
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
va_start(ap, fmt);
|
|
|
|
g_Logger.LogFatalEx(fmt, ap);
|
|
|
|
va_end(ap);
|
|
|
|
}
|
|
|
|
|
2013-02-17 00:52:11 +01:00
|
|
|
static void log_message(const char *fmt, ...)
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
va_start(ap, fmt);
|
|
|
|
g_Logger.LogMessageEx(fmt, ap);
|
|
|
|
va_end(ap);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void log_to_file(FILE *fp, const char *fmt, ...)
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
va_start(ap, fmt);
|
|
|
|
g_Logger.LogToOpenFileEx(fp, fmt, ap);
|
|
|
|
va_end(ap);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void log_to_game(const char *message)
|
|
|
|
{
|
|
|
|
Engine_LogPrintWrapper(message);
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool file_exists(const char *path)
|
|
|
|
{
|
|
|
|
return basefilesystem->FileExists(path);
|
|
|
|
}
|
|
|
|
|
2009-05-14 03:55:50 +02:00
|
|
|
static const char *get_cvar_string(ConVar* cvar)
|
|
|
|
{
|
|
|
|
return cvar->GetString();
|
|
|
|
}
|
|
|
|
|
2010-05-15 08:35:42 +02:00
|
|
|
static bool get_game_name(char *buffer, size_t maxlength)
|
|
|
|
{
|
|
|
|
KeyValues *pGameInfo = new KeyValues("GameInfo");
|
|
|
|
if (g_HL2.KVLoadFromFile(pGameInfo, basefilesystem, "gameinfo.txt"))
|
|
|
|
{
|
|
|
|
const char *str;
|
|
|
|
if ((str = pGameInfo->GetString("game", NULL)) != NULL)
|
|
|
|
{
|
|
|
|
strncopy(buffer, str, maxlength);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pGameInfo->deleteThis();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *get_game_description()
|
|
|
|
{
|
|
|
|
return SERVER_CALL(GetGameDescription)();
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *get_source_engine_name()
|
|
|
|
{
|
|
|
|
#if !defined SOURCE_ENGINE
|
|
|
|
# error "Unknown engine type"
|
|
|
|
#endif
|
|
|
|
#if SOURCE_ENGINE == SE_EPISODEONE
|
|
|
|
return "original";
|
|
|
|
#elif SOURCE_ENGINE == SE_DARKMESSIAH
|
|
|
|
return "darkmessiah";
|
|
|
|
#elif SOURCE_ENGINE == SE_ORANGEBOX
|
|
|
|
return "orangebox";
|
2011-01-12 05:35:58 +01:00
|
|
|
#elif SOURCE_ENGINE == SE_BLOODYGOODTIME
|
|
|
|
return "bloodygoodtime";
|
2011-08-21 00:58:37 +02:00
|
|
|
#elif SOURCE_ENGINE == SE_EYE
|
|
|
|
return "eye";
|
2012-08-21 03:53:59 +02:00
|
|
|
#elif SOURCE_ENGINE == SE_CSS
|
|
|
|
return "css";
|
2010-05-15 08:35:42 +02:00
|
|
|
#elif SOURCE_ENGINE == SE_ORANGEBOXVALVE
|
|
|
|
return "orangebox_valve";
|
|
|
|
#elif SOURCE_ENGINE == SE_LEFT4DEAD
|
|
|
|
return "left4dead";
|
|
|
|
#elif SOURCE_ENGINE == SE_LEFT4DEAD2
|
|
|
|
return "left4dead2";
|
2010-07-28 00:32:32 +02:00
|
|
|
#elif SOURCE_ENGINE == SE_ALIENSWARM
|
|
|
|
return "alienswarm";
|
2012-05-27 22:08:03 +02:00
|
|
|
#elif SOURCE_ENGINE == SE_PORTAL2
|
|
|
|
return "portal2";
|
|
|
|
#elif SOURCE_ENGINE == SE_CSGO
|
|
|
|
return "csgo";
|
2013-03-19 16:18:44 +01:00
|
|
|
#elif SOURCE_ENGINE == SE_DOTA
|
|
|
|
return "dota";
|
2010-05-15 08:35:42 +02:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool symbols_are_hidden()
|
|
|
|
{
|
2013-03-19 16:18:44 +01:00
|
|
|
#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)
|
2010-05-15 08:35:42 +02:00
|
|
|
return true;
|
|
|
|
#else
|
|
|
|
return false;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2011-07-25 04:52:22 +02:00
|
|
|
static const char* get_core_config_value(const char* key)
|
|
|
|
{
|
|
|
|
return g_CoreConfig.GetCoreConfigValue(key);
|
2013-03-29 19:37:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool is_map_loading()
|
|
|
|
{
|
|
|
|
return g_SourceMod.IsMapLoading();
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool is_map_running()
|
|
|
|
{
|
|
|
|
return g_SourceMod.IsMapRunning();
|
|
|
|
}
|
|
|
|
|
|
|
|
int read_cmd_argc(const CCommand &args)
|
|
|
|
{
|
|
|
|
return args.ArgC();
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *read_cmd_arg(const CCommand &args, int arg)
|
|
|
|
{
|
|
|
|
return args.Arg(arg);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int load_mms_plugin(const char *file, bool *ok, char *error, size_t maxlength)
|
|
|
|
{
|
|
|
|
bool ignore_already;
|
|
|
|
PluginId id = g_pMMPlugins->Load(file, g_PLID, ignore_already, error, maxlength);
|
|
|
|
|
|
|
|
Pl_Status status;
|
|
|
|
|
|
|
|
#ifndef METAMOD_PLAPI_VERSION
|
2013-03-29 20:19:41 +01:00
|
|
|
const char *filep;
|
2013-03-29 19:37:29 +01:00
|
|
|
PluginId source;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (!id || (
|
|
|
|
#ifndef METAMOD_PLAPI_VERSION
|
2013-03-29 20:19:41 +01:00
|
|
|
g_pMMPlugins->Query(id, filep, status, source)
|
2013-03-29 19:37:29 +01:00
|
|
|
#else
|
|
|
|
g_pMMPlugins->Query(id, NULL, &status, NULL)
|
|
|
|
#endif
|
|
|
|
&& status < Pl_Paused))
|
|
|
|
{
|
|
|
|
*ok = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*ok = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return id;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void unload_mms_plugin(int id)
|
|
|
|
{
|
|
|
|
char ignore[255];
|
|
|
|
g_pMMPlugins->Unload(id, true, ignore, sizeof(ignore));
|
|
|
|
}
|
|
|
|
|
|
|
|
void do_global_plugin_loads()
|
|
|
|
{
|
|
|
|
g_SourceMod.DoGlobalPluginLoads();
|
|
|
|
}
|
2011-07-25 04:52:22 +02:00
|
|
|
|
2010-05-13 10:47:12 +02:00
|
|
|
static ServerGlobals serverGlobals;
|
|
|
|
|
2009-05-14 03:55:50 +02:00
|
|
|
static sm_core_t core_bridge =
|
|
|
|
{
|
|
|
|
/* Objects */
|
|
|
|
&g_SourceMod,
|
|
|
|
&g_LibSys,
|
|
|
|
reinterpret_cast<IVEngineServer*>(&logic_engine),
|
2009-05-14 17:24:07 +02:00
|
|
|
&g_RootMenu,
|
2009-05-14 17:38:50 +02:00
|
|
|
&g_Forwards,
|
2010-05-13 10:47:12 +02:00
|
|
|
&g_Timers,
|
2010-05-13 21:28:51 +02:00
|
|
|
&g_Players,
|
2010-05-15 02:46:19 +02:00
|
|
|
&g_Admins,
|
2010-05-15 03:22:03 +02:00
|
|
|
&g_HL2,
|
2013-02-19 02:13:08 +01:00
|
|
|
&g_pSourcePawn,
|
|
|
|
&g_pSourcePawn2,
|
2009-05-14 03:55:50 +02:00
|
|
|
/* Functions */
|
|
|
|
find_convar,
|
|
|
|
strncopy,
|
|
|
|
UTIL_TrimWhitespace,
|
|
|
|
log_error,
|
2013-03-29 19:37:29 +01:00
|
|
|
log_fatal,
|
2013-02-17 00:52:11 +01:00
|
|
|
log_message,
|
|
|
|
log_to_file,
|
|
|
|
log_to_game,
|
|
|
|
file_exists,
|
2009-05-14 03:55:50 +02:00
|
|
|
get_cvar_string,
|
2009-12-20 03:18:17 +01:00
|
|
|
UTIL_Format,
|
2013-02-17 00:57:00 +01:00
|
|
|
UTIL_FormatArgs,
|
2010-05-15 04:43:53 +02:00
|
|
|
gnprintf,
|
2010-05-15 05:04:44 +02:00
|
|
|
atcprintf,
|
2010-05-15 08:35:42 +02:00
|
|
|
get_game_name,
|
|
|
|
get_game_description,
|
|
|
|
get_source_engine_name,
|
|
|
|
symbols_are_hidden,
|
2011-07-25 04:52:22 +02:00
|
|
|
get_core_config_value,
|
2013-03-29 19:37:29 +01:00
|
|
|
is_map_loading,
|
|
|
|
is_map_running,
|
|
|
|
read_cmd_argc,
|
|
|
|
read_cmd_arg,
|
|
|
|
load_mms_plugin,
|
|
|
|
unload_mms_plugin,
|
|
|
|
do_global_plugin_loads,
|
|
|
|
SM_AreConfigsExecuted,
|
|
|
|
SM_ExecuteForPlugin,
|
2010-05-13 10:47:12 +02:00
|
|
|
&serverGlobals
|
2009-05-14 03:55:50 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
void InitLogicBridge()
|
|
|
|
{
|
2010-05-13 10:47:12 +02:00
|
|
|
serverGlobals.universalTime = g_pUniversalTime;
|
|
|
|
serverGlobals.frametime = &gpGlobals->frametime;
|
|
|
|
serverGlobals.interval_per_tick = &gpGlobals->interval_per_tick;
|
|
|
|
|
2010-05-15 08:35:42 +02:00
|
|
|
core_bridge.engineFactory = (void *)g_SMAPI->GetEngineFactory(false);
|
|
|
|
core_bridge.serverFactory = (void *)g_SMAPI->GetServerFactory(false);
|
2011-06-27 15:30:52 +02:00
|
|
|
|
|
|
|
ILibrary *mmlib;
|
|
|
|
char path[PLATFORM_MAX_PATH];
|
|
|
|
|
|
|
|
g_LibSys.PathFormat(path, sizeof(path), "%s/bin/matchmaking_ds%s.%s", g_SMAPI->GetBaseDir(), MATCHMAKINGDS_SUFFIX, MATCHMAKINGDS_EXT);
|
|
|
|
|
2011-06-27 15:35:38 +02:00
|
|
|
if ((mmlib = g_LibSys.OpenLibrary(path, NULL, 0)))
|
2011-06-27 15:30:52 +02:00
|
|
|
{
|
|
|
|
core_bridge.matchmakingDSFactory = mmlib->GetSymbolAddress("CreateInterface");
|
|
|
|
mmlib->CloseLibrary();
|
|
|
|
}
|
|
|
|
|
2010-05-15 04:28:10 +02:00
|
|
|
logic_init_fn(&core_bridge, &logicore);
|
2009-05-14 03:55:50 +02:00
|
|
|
|
|
|
|
/* Add SMGlobalClass instances */
|
|
|
|
SMGlobalClass* glob = SMGlobalClass::head;
|
|
|
|
while (glob->m_pGlobalClassNext != NULL)
|
|
|
|
{
|
|
|
|
glob = glob->m_pGlobalClassNext;
|
|
|
|
}
|
|
|
|
assert(glob->m_pGlobalClassNext == NULL);
|
2010-05-15 04:28:10 +02:00
|
|
|
glob->m_pGlobalClassNext = logicore.head;
|
2009-05-14 03:55:50 +02:00
|
|
|
|
2010-05-15 04:28:10 +02:00
|
|
|
g_pThreader = logicore.threader;
|
|
|
|
g_pSourcePawn2->SetProfiler(logicore.profiler);
|
2010-05-15 04:43:53 +02:00
|
|
|
translator = logicore.translator;
|
2013-03-29 19:37:29 +01:00
|
|
|
scripts = logicore.scripts;
|
|
|
|
sharesys = logicore.sharesys;
|
|
|
|
extsys = logicore.extsys;
|
|
|
|
g_pCoreIdent = logicore.core_ident;
|
|
|
|
handlesys = logicore.handlesys;
|
2009-05-14 03:55:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool StartLogicBridge(char *error, size_t maxlength)
|
|
|
|
{
|
|
|
|
char file[PLATFORM_MAX_PATH];
|
|
|
|
|
|
|
|
/* Now it's time to load the logic binary */
|
|
|
|
g_SMAPI->PathFormat(file,
|
|
|
|
sizeof(file),
|
|
|
|
"%s/bin/sourcemod.logic." PLATFORM_LIB_EXT,
|
|
|
|
g_SourceMod.GetSourceModPath());
|
|
|
|
|
|
|
|
char myerror[255];
|
|
|
|
g_pLogic = g_LibSys.OpenLibrary(file, myerror, sizeof(myerror));
|
|
|
|
|
|
|
|
if (!g_pLogic)
|
|
|
|
{
|
|
|
|
if (error && maxlength)
|
|
|
|
{
|
|
|
|
UTIL_Format(error, maxlength, "failed to load %s: %s", file, myerror);
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
LogicLoadFunction llf = (LogicLoadFunction)g_pLogic->GetSymbolAddress("logic_load");
|
|
|
|
if (llf == NULL)
|
|
|
|
{
|
|
|
|
g_pLogic->CloseLibrary();
|
|
|
|
if (error && maxlength)
|
|
|
|
{
|
|
|
|
UTIL_Format(error, maxlength, "could not find logic_load function");
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
GetITextParsers getitxt = (GetITextParsers)g_pLogic->GetSymbolAddress("get_textparsers");
|
|
|
|
textparsers = getitxt();
|
|
|
|
|
|
|
|
logic_init_fn = llf(SM_LOGIC_MAGIC);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ShutdownLogicBridge()
|
|
|
|
{
|
|
|
|
g_pLogic->CloseLibrary();
|
|
|
|
}
|
|
|
|
|