mirror of
https://github.com/fortressforever/fortressforever-2013.git
synced 2024-11-10 07:11:45 +00:00
More ScriptManager stuff
* Split the UIScriptManager and GameScriptManager into their own classes that inherit from ScriptManager so that they can have different implementations of Init, LevelInit, and stuff like that * Not many functionality changes, mostly cleanup
This commit is contained in:
parent
35bd31cb39
commit
5e5f2a4914
12 changed files with 515 additions and 315 deletions
|
@ -35,6 +35,11 @@ $Project "Client (FF)"
|
|||
$File "ff\ff_cl_dll_interface.cpp"
|
||||
$File "ff\ff_cl_dll_interface.h"
|
||||
}
|
||||
$Folder "Lua"
|
||||
{
|
||||
$File "ff\ff_cl_scriptman_ui.cpp"
|
||||
$File "ff\ff_cl_scriptman_ui.h"
|
||||
}
|
||||
$Folder "Player"
|
||||
{
|
||||
$File "ff\ff_cl_player.cpp"
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
#include "ff_cl_dll_interface.h"
|
||||
|
||||
#include "steam/steam_api.h"
|
||||
#include "ff_sh_scriptman.h"
|
||||
#include "ff_cl_scriptman_ui.h"
|
||||
#include "ff_sh_scriptman_game.h"
|
||||
|
||||
#define CLIENT_DLL_INTERFACE_VERSION "VClient017"
|
||||
|
||||
|
@ -13,8 +14,6 @@ int CFF_CL_DLL_Interface::Init( CreateInterfaceFn appSystemFactory, CreateInterf
|
|||
// start the Lua VM
|
||||
g_UIScriptManager.Init();
|
||||
g_GameScriptManager.Init();
|
||||
|
||||
g_UIScriptManager.LoadFile( "ui/init.lua" );
|
||||
|
||||
// Test steam API
|
||||
uint32 appId = steamapicontext->SteamUtils()->GetAppID();
|
||||
|
|
95
mp/src/game/client/ff/ff_cl_scriptman_ui.cpp
Normal file
95
mp/src/game/client/ff/ff_cl_scriptman_ui.cpp
Normal file
|
@ -0,0 +1,95 @@
|
|||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// includes
|
||||
#include "cbase.h"
|
||||
#include "ff_cl_scriptman_ui.h"
|
||||
|
||||
// engine
|
||||
//#include "filesystem.h"
|
||||
|
||||
// dexter note 10/29/2013 these are definitely still needed for lua/luabind
|
||||
#undef MINMAX_H
|
||||
#undef min
|
||||
#undef max
|
||||
//
|
||||
// luabind
|
||||
#include "lua.hpp"
|
||||
#include "luabind/luabind.hpp"
|
||||
//#include "luabind/object.hpp"
|
||||
//#include "luabind/iterator_policy.hpp"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
using namespace luabind;
|
||||
|
||||
CFF_CL_ScriptManager_UI g_UIScriptManager;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
CFF_CL_ScriptManager_UI::CFF_CL_ScriptManager_UI()
|
||||
{
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
CFF_CL_ScriptManager_UI::~CFF_CL_ScriptManager_UI()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void CFF_CL_ScriptManager_UI::Shutdown()
|
||||
{
|
||||
BaseClass::Shutdown();
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
bool CFF_CL_ScriptManager_UI::Init()
|
||||
{
|
||||
bool bInitSuccessful = BaseClass::Init();
|
||||
|
||||
if (bInitSuccessful)
|
||||
{
|
||||
LoadFile( "ui/init.lua" );
|
||||
}
|
||||
|
||||
return bInitSuccessful;
|
||||
}
|
||||
|
||||
void CFF_CL_ScriptManager_UI::LevelInit(const char* szMapName)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void CFF_CL_ScriptManager_UI::LevelShutdown()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
CON_COMMAND( lua_dostring_ui, "Run a client-side Lua string in the UI environment" )
|
||||
{
|
||||
if ( args.ArgC() == 1 )
|
||||
{
|
||||
Msg( "Usage: lua_dostring <string>\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
lua_State *L = g_UIScriptManager.GetLuaState();
|
||||
int status = luaL_dostring(L, args.ArgS());
|
||||
if (status != 0) {
|
||||
Warning( "%s\n", lua_tostring(L, -1) );
|
||||
lua_pop(L, 1);
|
||||
return;
|
||||
}
|
||||
if (status == 0 && lua_gettop(L) > 0) { /* any result to print? */
|
||||
lua_getglobal(L, "print");
|
||||
lua_insert(L, 1);
|
||||
if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0)
|
||||
Warning("%s", lua_pushfstring(L,
|
||||
"error calling " LUA_QL("print") " (%s)",
|
||||
lua_tostring(L, -1)));
|
||||
}
|
||||
lua_settop(L, 0); /* clear stack */
|
||||
}
|
30
mp/src/game/client/ff/ff_cl_scriptman_ui.h
Normal file
30
mp/src/game/client/ff/ff_cl_scriptman_ui.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
#pragma once
|
||||
#ifndef FF_CL_SCRIPTMAN_UI_H
|
||||
#define FF_CL_SCRIPTMAN_UI_H
|
||||
|
||||
#include "ff_sh_scriptman.h"
|
||||
|
||||
class CFF_CL_ScriptManager_UI : public CFF_SH_ScriptManager
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CFF_CL_ScriptManager_UI, CFF_SH_ScriptManager );
|
||||
// 'structors
|
||||
CFF_CL_ScriptManager_UI();
|
||||
~CFF_CL_ScriptManager_UI();
|
||||
|
||||
protected:
|
||||
virtual const char* GetMsgIdentifier() { return "UI"; };
|
||||
virtual const char* GetPackagePathRoot() { return "/ui/"; };
|
||||
|
||||
public:
|
||||
virtual bool Init();
|
||||
virtual void Shutdown();
|
||||
|
||||
virtual void LevelInit(const char* szMapName);
|
||||
virtual void LevelShutdown();
|
||||
|
||||
};
|
||||
|
||||
extern CFF_CL_ScriptManager_UI g_UIScriptManager;
|
||||
|
||||
#endif
|
|
@ -1,7 +1,7 @@
|
|||
#include "cbase.h"
|
||||
#include "ff_sv_dll_interface.h"
|
||||
|
||||
#include "ff_sh_scriptman.h"
|
||||
#include "ff_sh_scriptman_game.h"
|
||||
|
||||
bool CFF_SV_DLL_Interface::DLLInit(CreateInterfaceFn engineFactory, CreateInterfaceFn physicsFactory, CreateInterfaceFn fileSystemFactory, CGlobalVars *pGlobals)
|
||||
{
|
||||
|
|
19
mp/src/game/shared/ff/ff_sh_luautil.cpp
Normal file
19
mp/src/game/shared/ff/ff_sh_luautil.cpp
Normal file
|
@ -0,0 +1,19 @@
|
|||
#include "cbase.h"
|
||||
#include "ff_sh_luautil.h"
|
||||
|
||||
#include "lua.hpp"
|
||||
|
||||
void LUAUTIL_RemoveKeysFromTable( lua_State *L, const char *pszTableName, const char** ppszKeys )
|
||||
{
|
||||
lua_getglobal(L, pszTableName);
|
||||
if (lua_type(L, -1) == LUA_TTABLE)
|
||||
{
|
||||
for( int i=0; ppszKeys[i] != NULL; ++i )
|
||||
{
|
||||
lua_pushstring(L, ppszKeys[i]);
|
||||
lua_pushnil(L);
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
9
mp/src/game/shared/ff/ff_sh_luautil.h
Normal file
9
mp/src/game/shared/ff/ff_sh_luautil.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
#ifndef FF_SH_LUAUTIL_H
|
||||
#define FF_SH_LUAUTIL_H
|
||||
#pragma once
|
||||
|
||||
struct lua_State;
|
||||
|
||||
void LUAUTIL_RemoveKeysFromTable( lua_State *L, const char *pszTableName, const char** ppszKeys );
|
||||
|
||||
#endif
|
|
@ -9,6 +9,7 @@
|
|||
//#include "ff_utils.h"
|
||||
//#include "ff_item_flag.h"
|
||||
//#include "triggers.h"
|
||||
#include "ff_sh_luautil.h"
|
||||
|
||||
// engine
|
||||
#include "filesystem.h"
|
||||
|
@ -28,16 +29,6 @@
|
|||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
#define LUA_CURRENT_CONTEXT "Client"
|
||||
#else
|
||||
#define LUA_CURRENT_CONTEXT "Server"
|
||||
#endif
|
||||
|
||||
// custom game modes made so damn easy
|
||||
ConVar sv_mapluasuffix( "sv_mapluasuffix", "0", FCVAR_NOTIFY, "Have a custom lua file (game mode) loaded when the map loads. If this suffix string is set, maps\\mapname__suffix__.lua (if it exists) is used instead of maps\\mapname.lua. To reset this cvar, make it 0.");
|
||||
ConVar sv_luaglobalscript( "sv_globalluascript", "0", FCVAR_NOTIFY, "Load a custom lua file globally after map scripts. Will overwrite map script. Will be loaded from maps\\globalscripts. To disable, set to 0.");
|
||||
|
||||
// redirect Lua's print function to the console
|
||||
static int print(lua_State *L)
|
||||
{
|
||||
|
@ -60,38 +51,22 @@ static int print(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
using namespace luabind;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// globals
|
||||
CFF_SH_ScriptManager g_GameScriptManager;
|
||||
#ifdef CLIENT_DLL
|
||||
CFF_SH_ScriptManager g_UIScriptManager;
|
||||
#endif
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
CFF_SH_ScriptManager::CFF_SH_ScriptManager()
|
||||
: L(NULL)
|
||||
, m_isLoading(false)
|
||||
, m_scriptCRC(0)
|
||||
, m_ScriptExists(false)
|
||||
{
|
||||
L = NULL;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
CFF_SH_ScriptManager::~CFF_SH_ScriptManager()
|
||||
{
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/** Close the Lua VM
|
||||
*/
|
||||
void CFF_SH_ScriptManager::Shutdown()
|
||||
{
|
||||
m_ScriptExists = false;
|
||||
|
||||
// shtutdown VM
|
||||
if(L)
|
||||
{
|
||||
|
@ -100,46 +75,58 @@ void CFF_SH_ScriptManager::Shutdown()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void CFF_SH_ScriptManager::Init()
|
||||
/** Open the Lua VM
|
||||
@returns True if successful, false if couldn't open Lua VM
|
||||
*/
|
||||
bool CFF_SH_ScriptManager::Init()
|
||||
{
|
||||
// shutdown VM if already running
|
||||
if(L)
|
||||
{
|
||||
lua_close(L);
|
||||
L = NULL;
|
||||
}
|
||||
Shutdown();
|
||||
|
||||
// initialize VM
|
||||
Msg("[SCRIPT:%s] Attempting to start the Lua VM...\n", LUA_CURRENT_CONTEXT);
|
||||
LuaMsg("Attempting to start the Lua VM...\n");
|
||||
L = lua_open();
|
||||
|
||||
// no need to continue if VM failed to initialize
|
||||
if(!L)
|
||||
{
|
||||
Msg("[SCRIPT:%s] Unable to initialize Lua VM.\n", LUA_CURRENT_CONTEXT);
|
||||
return;
|
||||
LuaMsg("Unable to initialize Lua VM.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// initialize all the FF specific stuff
|
||||
SetupEnvironmentForFF();
|
||||
|
||||
// make the standard libraries safe
|
||||
MakeEnvironmentSafe();
|
||||
|
||||
LuaMsg("Lua VM initialization successful.\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Loads the Lua libraries and sets all the variables needed for FF
|
||||
*/
|
||||
void CFF_SH_ScriptManager::SetupEnvironmentForFF()
|
||||
{
|
||||
Assert(L);
|
||||
if (!L) return;
|
||||
|
||||
// load all libraries
|
||||
luaL_openlibs(L);
|
||||
// make the standard libraries safe
|
||||
MakeSafe();
|
||||
|
||||
|
||||
// overwrite Lua's print with our own
|
||||
lua_register(L,"print",print);
|
||||
|
||||
// set package.path to the mod search dirs, so that we can use require
|
||||
char szModSearchPaths[4096] = {0};
|
||||
// FF TODO: This is set to ignore pack files; might need to add support for them (for custom mods packaged as .vpks)
|
||||
// FF TODO: This is set to ignore pack files; might need to add support for them (for custom mods packaged as .vpks?)
|
||||
filesystem->GetSearchPath( "MOD", false, szModSearchPaths, sizeof(szModSearchPaths) );
|
||||
|
||||
char szLuaSearchPaths[4096] = {0};
|
||||
for ( char *szSearchPath = strtok( szModSearchPaths, ";" ); szSearchPath; szSearchPath = strtok( NULL, ";" ) )
|
||||
{
|
||||
char fullpath[MAX_PATH];
|
||||
Q_snprintf( fullpath, sizeof( fullpath ), "%s%s", szSearchPath, "/?.lua;" );
|
||||
Q_snprintf( fullpath, sizeof( fullpath ), "%s%s%s", szSearchPath, GetPackagePathRoot(), "?.lua;" );
|
||||
Q_FixSlashes( fullpath );
|
||||
V_FixDoubleSlashes( fullpath );
|
||||
|
||||
|
@ -156,32 +143,20 @@ void CFF_SH_ScriptManager::Init()
|
|||
|
||||
// initialize luabind
|
||||
luabind::open(L);
|
||||
|
||||
|
||||
// initialize game-specific library
|
||||
//FF_TODO: CFFLuaLib::Init(L);
|
||||
|
||||
Msg("[SCRIPT:%s] Lua VM initialization successful.\n", LUA_CURRENT_CONTEXT);
|
||||
}
|
||||
|
||||
void LUAUTIL_RemoveKeysFromTable( lua_State *L, const char *pszTableName, const char** ppszKeys )
|
||||
{
|
||||
lua_getglobal(L, pszTableName);
|
||||
if (lua_type(L, -1) == LUA_TTABLE)
|
||||
{
|
||||
for( int i=0; ppszKeys[i] != NULL; ++i )
|
||||
{
|
||||
lua_pushstring(L, ppszKeys[i]);
|
||||
lua_pushnil(L);
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
/** Get rid of or alter any unsafe Lua functions
|
||||
/** Gets rid of or alter any unsafe Lua functions in the current environment
|
||||
*/
|
||||
void CFF_SH_ScriptManager::MakeSafe()
|
||||
void CFF_SH_ScriptManager::MakeEnvironmentSafe()
|
||||
{
|
||||
Assert(L);
|
||||
if (!L) return;
|
||||
|
||||
// See: http://lua-users.org/wiki/SandBoxes for a general overview of the safety of Lua functions
|
||||
|
||||
// os.*
|
||||
const char* ppszUnsafeOSFunctions[] = { "execute", "exit", "getenv", "remove", "rename", "setlocale", NULL };
|
||||
LUAUTIL_RemoveKeysFromTable( L, LUA_OSLIBNAME, ppszUnsafeOSFunctions );
|
||||
|
@ -195,7 +170,7 @@ void CFF_SH_ScriptManager::MakeSafe()
|
|||
// the fourth index is an all-in-one loader that can load .so/.dll files
|
||||
lua_getglobal(L, LUA_LOADLIBNAME);
|
||||
lua_pushstring(L, "loaders");
|
||||
lua_gettable(L, -2);
|
||||
lua_gettable(L, -2); // get _G.package.loaders
|
||||
lua_pushnil(L);
|
||||
lua_rawseti(L, -2, 4); // _G.package.loaders[4] = nil
|
||||
lua_pushnil(L);
|
||||
|
@ -203,191 +178,23 @@ void CFF_SH_ScriptManager::MakeSafe()
|
|||
lua_pop(L, 2); // pop _G.package.loaders and _G.package
|
||||
|
||||
// FF TODO: restrict io library, maybe disable it completely
|
||||
// FF TODO: somehow protect package.path? not sure if it's necessary, the "risk" would be allowing execution of .lua files in arbitrary locations
|
||||
}
|
||||
|
||||
void CFF_SH_ScriptManager::LevelInit(const char* szMapName)
|
||||
{
|
||||
const char* default_luafile = "maps/default.lua";
|
||||
//FF_TODO: VPROF_BUDGET("CFF_SH_ScriptManager::LevelInit", VPROF_BUDGETGROUP_FF_LUA);
|
||||
|
||||
if(!szMapName)
|
||||
return;
|
||||
|
||||
//FF_TODO: g_Disable_Timelimit = false;
|
||||
|
||||
// setup VM
|
||||
Init();
|
||||
|
||||
// load lua files
|
||||
BeginScriptLoad();
|
||||
LoadFile("maps/includes/base.lua");
|
||||
|
||||
char filename[256] = {0};
|
||||
char globalscript_filename[256] = {0};
|
||||
// Even though LoadFile already checks to see if the file exists, we'll check now so at least the default map lua file is loaded.
|
||||
// That way servers can keep their suffix set without worrying about every map having whatever game mode they always want to use.
|
||||
if ( sv_mapluasuffix.GetString()[0] != '0' )
|
||||
{
|
||||
Msg( "[SCRIPT] sv_mapluasuffix set to %s | finding maps\\%s__%s__.lua\n", sv_mapluasuffix.GetString(), szMapName, sv_mapluasuffix.GetString() );
|
||||
#ifdef CLIENT_DLL
|
||||
if ( filesystem->FileExists( VarArgs( "maps/%s__%s__.lua", szMapName, sv_mapluasuffix.GetString() ) ) )
|
||||
#else
|
||||
if ( filesystem->FileExists( UTIL_VarArgs( "maps/%s__%s__.lua", szMapName, sv_mapluasuffix.GetString() ) ) )
|
||||
#endif
|
||||
{
|
||||
Q_snprintf( filename, sizeof(filename), "maps/%s__%s__.lua", szMapName, sv_mapluasuffix.GetString() );
|
||||
Msg( "[SCRIPT] maps\\%s__%s__.lua found\n", szMapName, sv_mapluasuffix.GetString() );
|
||||
}
|
||||
else
|
||||
{
|
||||
Msg( "[SCRIPT] maps\\%s__%s__.lua not found | reverting to maps\\%s.lua\n", szMapName, sv_mapluasuffix.GetString(), szMapName);
|
||||
}
|
||||
}
|
||||
|
||||
// Load global include script, overwriting previously loaded stuff per map
|
||||
if( sv_luaglobalscript.GetString()[0] != '0' )
|
||||
{
|
||||
const char* scriptname = sv_luaglobalscript.GetString();
|
||||
Msg("[SCRIPT] sv_luaglobalscript set to %s | loading global script maps maps\\globalscripts\\%s.lua\n", scriptname, scriptname );
|
||||
#ifdef CLIENT_DLL
|
||||
if( filesystem->FileExists( VarArgs( "maps/globalscripts/%s.lua", scriptname ) ) )
|
||||
#else
|
||||
if( filesystem->FileExists( UTIL_VarArgs( "maps/globalscripts/%s.lua", scriptname ) ) )
|
||||
#endif
|
||||
{
|
||||
Q_snprintf( globalscript_filename, sizeof(globalscript_filename), "maps/globalscripts/%s.lua", scriptname );
|
||||
Msg("[SCRIPT] maps\\globalscripts\\%s.lua found\n", scriptname );\
|
||||
}
|
||||
else
|
||||
{
|
||||
Msg("[SCRIPT] global script maps\\globalscripts\\%s.lua not found - nothing loaded post map lua.\n", scriptname );
|
||||
}
|
||||
}
|
||||
|
||||
if ( !filename[0] )
|
||||
Q_snprintf( filename, sizeof(filename), "maps/%s.lua", szMapName );
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Try a precache, rumor has it this will cause the engine to send the lua files to clients
|
||||
// FF_TODO: dexter - disabled for now, doesnt work anyway right?
|
||||
//if(PRECACHE_LUA_FILES)
|
||||
//{
|
||||
// V_FixSlashes(filename);
|
||||
// if(filesystem->FileExists(filename))
|
||||
// {
|
||||
// Util_AddDownload(filename);
|
||||
|
||||
// if(!engine->IsGenericPrecached(filename))
|
||||
// engine->PrecacheGeneric(filename, true);
|
||||
// }
|
||||
// else // - if no map lua is found, send default (for testing mainly)
|
||||
// {
|
||||
// // no check - this file should *always* be there
|
||||
// Util_AddDownload(default_luafile);
|
||||
// if(!engine->IsGenericPrecached(default_luafile))
|
||||
// engine->PrecacheGeneric(default_luafile, true);
|
||||
// }
|
||||
//
|
||||
|
||||
// // if we have a globalscript, precache it as well
|
||||
// if( sv_luaglobalscript.GetString()[0] != '0' && globalscript_filename[0] )
|
||||
// {
|
||||
// V_FixSlashes(globalscript_filename);
|
||||
// if(filesystem->FileExists(globalscript_filename))
|
||||
// {
|
||||
// Util_AddDownload(globalscript_filename);
|
||||
|
||||
// if(!engine->IsGenericPrecached(globalscript_filename))
|
||||
// engine->PrecacheGeneric(globalscript_filename, true);
|
||||
// }
|
||||
// }
|
||||
|
||||
// //////////////////////////////////////////////////////////////////////////
|
||||
// /*char testfile[] = {"maps/ff_dm.txt"};
|
||||
// V_FixSlashes(testfile);
|
||||
// if(filesystem->FileExists(testfile))
|
||||
// {
|
||||
// Util_AddDownload(testfile);
|
||||
|
||||
// if(!engine->IsGenericPrecached(testfile))
|
||||
// engine->PrecacheGeneric(testfile, true);
|
||||
// }*/
|
||||
// //////////////////////////////////////////////////////////////////////////
|
||||
//}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if(filesystem->FileExists(filename))
|
||||
m_ScriptExists = LoadFile(filename);
|
||||
else
|
||||
{
|
||||
Msg("[SCRIPT] File %s not found! Loaded fallback lua %s\n", filename, default_luafile);
|
||||
m_ScriptExists = LoadFile(default_luafile);
|
||||
}
|
||||
|
||||
// force loading global script in another call :/
|
||||
if( sv_luaglobalscript.GetString()[0] != '0' && globalscript_filename[0] )
|
||||
{
|
||||
//BeginScriptLoad();
|
||||
LoadFile(globalscript_filename);
|
||||
//EndScriptLoad();
|
||||
}
|
||||
|
||||
EndScriptLoad();
|
||||
|
||||
// spawn the helper entity
|
||||
//FF_TODO: CFFEntitySystemHelper::Create();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void CFF_SH_ScriptManager::LevelShutdown()
|
||||
{
|
||||
// shutdown the VM
|
||||
if(L)
|
||||
{
|
||||
lua_close(L);
|
||||
L = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void CFF_SH_ScriptManager::OnScriptLoad(const char* szFileName,
|
||||
const char* szFileContents)
|
||||
{
|
||||
// ignore the message if we are not still in the "loading" phase
|
||||
if(!m_isLoading)
|
||||
return;
|
||||
|
||||
// compute checksums of file contents
|
||||
CRC32_ProcessBuffer(&m_scriptCRC,
|
||||
szFileContents,
|
||||
strlen(szFileContents));
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void CFF_SH_ScriptManager::BeginScriptLoad()
|
||||
{
|
||||
CRC32_Init(&m_scriptCRC);
|
||||
m_isLoading = true;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void CFF_SH_ScriptManager::EndScriptLoad()
|
||||
{
|
||||
CRC32_Final(&m_scriptCRC);
|
||||
m_isLoading = false;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/** Loads a Lua file into the current environment relative to a "MOD" search path
|
||||
@returns True if file successfully loaded, false if there were any errors (syntax or execution)
|
||||
*/
|
||||
bool CFF_SH_ScriptManager::LoadFile(const char *filename)
|
||||
{
|
||||
//FF_TODO: VPROF_BUDGET( "CFF_SH_ScriptManager::LoadFile", VPROF_BUDGETGROUP_FF_LUA );
|
||||
|
||||
// open the file
|
||||
Msg("[SCRIPT:%s] Loading Lua File: %s\n", LUA_CURRENT_CONTEXT, filename);
|
||||
LuaMsg("Loading Lua File: %s\n", filename);
|
||||
FileHandle_t hFile = filesystem->Open(filename, "rb", "MOD");
|
||||
|
||||
if (!hFile)
|
||||
{
|
||||
Warning("[SCRIPT:%s] %s either does not exist or could not be opened.\n", LUA_CURRENT_CONTEXT, filename);
|
||||
LuaWarning("%s either does not exist or could not be opened.\n", filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -411,7 +218,7 @@ bool CFF_SH_ScriptManager::LoadFile(const char *filename)
|
|||
if (errorCode != 0)
|
||||
{
|
||||
const char *error = lua_tostring(L, -1);
|
||||
Warning( "[SCRIPT:%s] Error loading %s: %s\n", LUA_CURRENT_CONTEXT, filename, error );
|
||||
LuaWarning( "Error loading %s: %s\n", filename, error );
|
||||
lua_pop( L, 1 );
|
||||
return false;
|
||||
}
|
||||
|
@ -423,46 +230,49 @@ bool CFF_SH_ScriptManager::LoadFile(const char *filename)
|
|||
if (errorCode != 0)
|
||||
{
|
||||
const char *error = lua_tostring(L, -1);
|
||||
Warning( "[SCRIPT:%s] Error loading %s: %s\n", LUA_CURRENT_CONTEXT, filename, error );
|
||||
LuaWarning( "Error loading %s: %s\n", filename, error );
|
||||
lua_pop( L, 1 );
|
||||
return false;
|
||||
}
|
||||
|
||||
Msg( "[SCRIPT:%s] Successfully loaded %s\n", LUA_CURRENT_CONTEXT, filename );
|
||||
LuaMsg( "Successfully loaded %s\n", filename );
|
||||
|
||||
// cleanup
|
||||
MemFreeScratch();
|
||||
return true;
|
||||
}
|
||||
|
||||
int luasrc_dostring (lua_State *L, const char *string) {
|
||||
int iError = luaL_dostring(L, string);
|
||||
if (iError != 0) {
|
||||
Warning( "%s\n", lua_tostring(L, -1) );
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
return iError;
|
||||
}
|
||||
|
||||
// FF TODO: Better way to get this sort of string?
|
||||
#ifdef CLIENT_DLL
|
||||
CON_COMMAND( lua_dostring_ui, "Run a client-side Lua string in the UI environment" )
|
||||
{
|
||||
if ( args.ArgC() == 1 )
|
||||
{
|
||||
Msg( "Usage: lua_dostring <string>\n" );
|
||||
return;
|
||||
}
|
||||
#define LUA_MSG_DLL_CONTEXT "Client"
|
||||
#else
|
||||
#define LUA_MSG_DLL_CONTEXT "Server"
|
||||
#endif
|
||||
|
||||
lua_State *L = g_UIScriptManager.GetLuaState();
|
||||
int status = luasrc_dostring( L, args.ArgS() );
|
||||
if (status == 0 && lua_gettop(L) > 0) { /* any result to print? */
|
||||
lua_getglobal(L, "print");
|
||||
lua_insert(L, 1);
|
||||
if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0)
|
||||
Warning("%s", lua_pushfstring(L,
|
||||
"error calling " LUA_QL("print") " (%s)",
|
||||
lua_tostring(L, -1)));
|
||||
}
|
||||
lua_settop(L, 0); /* clear stack */
|
||||
/** Wrapper for Msg that prefixes the string with info about where it's coming from in the format: [Lua.<GetMsgIdentifier()>:<Client/Server>]
|
||||
*/
|
||||
void CFF_SH_ScriptManager::LuaMsg( const char *pszFormat, ... )
|
||||
{
|
||||
va_list argptr;
|
||||
static char string[4096];
|
||||
|
||||
va_start (argptr, pszFormat);
|
||||
Q_vsnprintf(string, sizeof(string), pszFormat, argptr);
|
||||
va_end (argptr);
|
||||
|
||||
Msg("[Lua.%s:%s] %s", GetMsgIdentifier(), LUA_MSG_DLL_CONTEXT, string );
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Wrapper for Warning that prefixes the string with info about where it's coming from in the format: [Lua.<GetMsgIdentifier()>:<Client/Server>]
|
||||
*/
|
||||
void CFF_SH_ScriptManager::LuaWarning( const char *pszFormat, ... )
|
||||
{
|
||||
va_list argptr;
|
||||
static char string[4096];
|
||||
|
||||
va_start (argptr, pszFormat);
|
||||
Q_vsnprintf(string, sizeof(string), pszFormat, argptr);
|
||||
va_end (argptr);
|
||||
|
||||
Warning("[Lua.%s:%s] %s", GetMsgIdentifier(), LUA_MSG_DLL_CONTEXT, string );
|
||||
}
|
|
@ -1,8 +1,6 @@
|
|||
|
||||
// ff_sh_scriptman.h
|
||||
|
||||
#ifndef FF_SH_SCRIPTMAN_H
|
||||
#define FF_SH_SCRIPTMAN_H
|
||||
#pragma once
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// includes
|
||||
|
@ -30,37 +28,36 @@ class CFFLuaSC;
|
|||
class CFF_SH_ScriptManager
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS_NOBASE( CFF_SH_ScriptManager );
|
||||
// 'structors
|
||||
CFF_SH_ScriptManager();
|
||||
~CFF_SH_ScriptManager();
|
||||
|
||||
public:
|
||||
// inserts the lua file into the script environment
|
||||
bool LoadFile(const char* filePath);
|
||||
void MakeSafe();
|
||||
virtual bool LoadFile(const char* filePath);
|
||||
// removes unsafe functions from the Lua environment or makes them safer
|
||||
virtual void MakeEnvironmentSafe();
|
||||
virtual void SetupEnvironmentForFF();
|
||||
|
||||
public:
|
||||
// initializes the script VM
|
||||
void Init();
|
||||
virtual bool Init();
|
||||
// closes the script VM
|
||||
void Shutdown();
|
||||
virtual void Shutdown();
|
||||
|
||||
virtual void LevelInit(const char* szMapName) {};
|
||||
virtual void LevelShutdown() {};
|
||||
|
||||
// loads the scripts for the level
|
||||
void LevelInit(const char* szMapName);
|
||||
// cleans up the scripts for the most recent level
|
||||
void LevelShutdown();
|
||||
void LuaMsg( const tchar* pMsg, ... ) FMTFUNCTION( 1, 2 );
|
||||
void LuaWarning( const tchar* pMsg, ... ) FMTFUNCTION( 1, 2 );
|
||||
|
||||
private:
|
||||
// surround code that loads scripts to capture crc checksum
|
||||
// of the scripts that are loaded
|
||||
void BeginScriptLoad();
|
||||
void EndScriptLoad();
|
||||
|
||||
private:
|
||||
// called when a script is loaded. internally computes the
|
||||
// crc checksum of the file contents
|
||||
void OnScriptLoad(const char* szFileName, const char* szFileContents);
|
||||
protected:
|
||||
virtual const char* GetMsgIdentifier() { return "Generic"; };
|
||||
virtual const char* GetPackagePathRoot() { return "/"; };
|
||||
|
||||
/// Called from LoadFile
|
||||
virtual void OnScriptLoad(const char* szFileName, const char* szFileContents) {};
|
||||
|
||||
/*
|
||||
public:
|
||||
// sets a global variable in the script environment
|
||||
static void SetVar( lua_State *L, const char *name, const char *value );
|
||||
|
@ -89,29 +86,15 @@ public:
|
|||
public:
|
||||
int RunPredicates( CBaseEntity *pObject, CBaseEntity *pEntity, const char *szFunctionName = NULL);
|
||||
bool RunPredicates_LUA( CBaseEntity *pObject, CFFLuaSC *pContext, const char *szFunctionName );
|
||||
*/
|
||||
|
||||
public:
|
||||
// returns the lua interpreter
|
||||
lua_State* GetLuaState() const { return L; }
|
||||
bool ScriptExists( void ) const { return m_ScriptExists; }
|
||||
|
||||
// returns the crc checksum of the currently active script
|
||||
CRC32_t GetScriptCRC() const { return m_scriptCRC; }
|
||||
|
||||
private:
|
||||
// private data
|
||||
lua_State* L; // lua VM
|
||||
bool m_ScriptExists;
|
||||
bool m_isLoading;
|
||||
CRC32_t m_scriptCRC;
|
||||
protected:
|
||||
lua_State* L; ///< Lua VM
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// global externs
|
||||
extern CFF_SH_ScriptManager g_GameScriptManager;
|
||||
#ifdef CLIENT_DLL
|
||||
extern CFF_SH_ScriptManager g_UIScriptManager;
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif
|
||||
|
|
200
mp/src/game/shared/ff/ff_sh_scriptman_game.cpp
Normal file
200
mp/src/game/shared/ff/ff_sh_scriptman_game.cpp
Normal file
|
@ -0,0 +1,200 @@
|
|||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// includes
|
||||
#include "cbase.h"
|
||||
#include "ff_sh_scriptman_game.h"
|
||||
|
||||
// engine
|
||||
#include "filesystem.h"
|
||||
|
||||
// dexter note 10/29/2013 these are definitely still needed for lua/luabind
|
||||
#undef MINMAX_H
|
||||
#undef min
|
||||
#undef max
|
||||
//
|
||||
// luabind
|
||||
#include "lua.hpp"
|
||||
#include "luabind/luabind.hpp"
|
||||
//#include "luabind/object.hpp"
|
||||
//#include "luabind/iterator_policy.hpp"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
// custom game modes made so damn easy
|
||||
ConVar sv_mapluasuffix( "sv_mapluasuffix", "0", FCVAR_NOTIFY, "Have a custom lua file (game mode) loaded when the map loads. If this suffix string is set, maps\\mapname__suffix__.lua (if it exists) is used instead of maps\\mapname.lua. To reset this cvar, make it 0.");
|
||||
ConVar sv_luaglobalscript( "sv_globalluascript", "0", FCVAR_NOTIFY, "Load a custom lua file globally after map scripts. Will overwrite map script. Will be loaded from maps\\globalscripts. To disable, set to 0.");
|
||||
|
||||
using namespace luabind;
|
||||
|
||||
CFF_SH_ScriptManager_Game g_GameScriptManager;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
CFF_SH_ScriptManager_Game::CFF_SH_ScriptManager_Game()
|
||||
{
|
||||
m_bLoading = m_bScriptLoaded = false;
|
||||
m_ScriptCRC = NULL;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
CFF_SH_ScriptManager_Game::~CFF_SH_ScriptManager_Game()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void CFF_SH_ScriptManager_Game::Shutdown()
|
||||
{
|
||||
BaseClass::Shutdown();
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
bool CFF_SH_ScriptManager_Game::Init()
|
||||
{
|
||||
bool bInitSuccessful = BaseClass::Init();
|
||||
|
||||
if (bInitSuccessful)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
return bInitSuccessful;
|
||||
}
|
||||
|
||||
void CFF_SH_ScriptManager_Game::LevelInit(const char* szMapName)
|
||||
{
|
||||
const char* default_luafile = "maps/default.lua";
|
||||
//FF_TODO: VPROF_BUDGET("CFF_SH_ScriptManager::LevelInit", VPROF_BUDGETGROUP_FF_LUA);
|
||||
|
||||
if(!szMapName)
|
||||
return;
|
||||
|
||||
//FF_TODO: g_Disable_Timelimit = false;
|
||||
|
||||
// setup VM
|
||||
Init();
|
||||
|
||||
// load lua files
|
||||
BeginScriptLoad();
|
||||
LoadFile("maps/includes/base.lua");
|
||||
|
||||
char filename[256] = {0};
|
||||
char globalscript_filename[256] = {0};
|
||||
// Even though LoadFile already checks to see if the file exists, we'll check now so at least the default map lua file is loaded.
|
||||
// That way servers can keep their suffix set without worrying about every map having whatever game mode they always want to use.
|
||||
if ( sv_mapluasuffix.GetString()[0] != '0' )
|
||||
{
|
||||
Msg( "[SCRIPT] sv_mapluasuffix set to %s | finding maps\\%s__%s__.lua\n", sv_mapluasuffix.GetString(), szMapName, sv_mapluasuffix.GetString() );
|
||||
if ( filesystem->FileExists( UTIL_VarArgs( "maps/%s__%s__.lua", szMapName, sv_mapluasuffix.GetString() ) ) )
|
||||
{
|
||||
Q_snprintf( filename, sizeof(filename), "maps/%s__%s__.lua", szMapName, sv_mapluasuffix.GetString() );
|
||||
Msg( "[SCRIPT] maps\\%s__%s__.lua found\n", szMapName, sv_mapluasuffix.GetString() );
|
||||
}
|
||||
else
|
||||
{
|
||||
Msg( "[SCRIPT] maps\\%s__%s__.lua not found | reverting to maps\\%s.lua\n", szMapName, sv_mapluasuffix.GetString(), szMapName);
|
||||
}
|
||||
}
|
||||
|
||||
// Load global include script, overwriting previously loaded stuff per map
|
||||
if( sv_luaglobalscript.GetString()[0] != '0' )
|
||||
{
|
||||
const char* scriptname = sv_luaglobalscript.GetString();
|
||||
Msg("[SCRIPT] sv_luaglobalscript set to %s | loading global script maps maps\\globalscripts\\%s.lua\n", scriptname, scriptname );
|
||||
if( filesystem->FileExists( UTIL_VarArgs( "maps/globalscripts/%s.lua", scriptname ) ) )
|
||||
{
|
||||
Q_snprintf( globalscript_filename, sizeof(globalscript_filename), "maps/globalscripts/%s.lua", scriptname );
|
||||
Msg("[SCRIPT] maps\\globalscripts\\%s.lua found\n", scriptname );\
|
||||
}
|
||||
else
|
||||
{
|
||||
Msg("[SCRIPT] global script maps\\globalscripts\\%s.lua not found - nothing loaded post map lua.\n", scriptname );
|
||||
}
|
||||
}
|
||||
|
||||
if ( !filename[0] )
|
||||
Q_snprintf( filename, sizeof(filename), "maps/%s.lua", szMapName );
|
||||
|
||||
if(filesystem->FileExists(filename))
|
||||
m_bScriptLoaded = LoadFile(filename);
|
||||
else
|
||||
{
|
||||
Msg("[SCRIPT] File %s not found! Loaded fallback lua %s\n", filename, default_luafile);
|
||||
m_bScriptLoaded = LoadFile(default_luafile);
|
||||
}
|
||||
|
||||
// force loading global script in another call :/
|
||||
if( sv_luaglobalscript.GetString()[0] != '0' && globalscript_filename[0] )
|
||||
{
|
||||
LoadFile(globalscript_filename);
|
||||
}
|
||||
|
||||
EndScriptLoad();
|
||||
|
||||
// spawn the helper entity
|
||||
//FF_TODO: CFFEntitySystemHelper::Create();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void CFF_SH_ScriptManager_Game::LevelShutdown()
|
||||
{
|
||||
// shutdown the VM
|
||||
if(L)
|
||||
{
|
||||
lua_close(L);
|
||||
L = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void CFF_SH_ScriptManager_Game::OnScriptLoad(const char* szFileName, const char* szFileContents)
|
||||
{
|
||||
// ignore the message if we are not still in the "loading" phase
|
||||
if(!m_bLoading)
|
||||
return;
|
||||
|
||||
// compute checksums of file contents
|
||||
CRC32_ProcessBuffer( &m_ScriptCRC, szFileContents, strlen(szFileContents) );
|
||||
}
|
||||
|
||||
void CFF_SH_ScriptManager_Game::BeginScriptLoad()
|
||||
{
|
||||
CRC32_Init(&m_ScriptCRC);
|
||||
m_bLoading = true;
|
||||
}
|
||||
|
||||
void CFF_SH_ScriptManager_Game::EndScriptLoad()
|
||||
{
|
||||
CRC32_Final(&m_ScriptCRC);
|
||||
m_bLoading = false;
|
||||
}
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
CON_COMMAND( lua_dostring_game_cl, "Run a client-side Lua string in the Game environment" )
|
||||
#else
|
||||
CON_COMMAND( lua_dostring_game_sv, "Run a server-side Lua string in the Game environment" )
|
||||
#endif
|
||||
{
|
||||
if ( args.ArgC() == 1 )
|
||||
{
|
||||
Msg( "Usage: lua_dostring <string>\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
lua_State *L = g_GameScriptManager.GetLuaState();
|
||||
int status = luaL_dostring(L, args.ArgS());
|
||||
if (status != 0) {
|
||||
Warning( "%s\n", lua_tostring(L, -1) );
|
||||
lua_pop(L, 1);
|
||||
return;
|
||||
}
|
||||
if (status == 0 && lua_gettop(L) > 0) { /* any result to print? */
|
||||
lua_getglobal(L, "print");
|
||||
lua_insert(L, 1);
|
||||
if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0)
|
||||
Warning("%s", lua_pushfstring(L,
|
||||
"error calling " LUA_QL("print") " (%s)",
|
||||
lua_tostring(L, -1)));
|
||||
}
|
||||
lua_settop(L, 0); /* clear stack */
|
||||
}
|
46
mp/src/game/shared/ff/ff_sh_scriptman_game.h
Normal file
46
mp/src/game/shared/ff/ff_sh_scriptman_game.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
#pragma once
|
||||
#ifndef FF_CL_SCRIPTMAN_GAME_H
|
||||
#define FF_CL_SCRIPTMAN_GAME_H
|
||||
|
||||
#include "ff_sh_scriptman.h"
|
||||
|
||||
class CFF_SH_ScriptManager_Game : public CFF_SH_ScriptManager
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CFF_SH_ScriptManager_Game, CFF_SH_ScriptManager );
|
||||
// 'structors
|
||||
CFF_SH_ScriptManager_Game();
|
||||
~CFF_SH_ScriptManager_Game();
|
||||
|
||||
protected:
|
||||
virtual const char* GetMsgIdentifier() { return "Game"; };
|
||||
virtual const char* GetPackagePathRoot() { return "/lua/"; };
|
||||
|
||||
virtual void OnScriptLoad(const char* szFileName, const char* szFileContents);
|
||||
|
||||
public:
|
||||
virtual bool Init();
|
||||
virtual void Shutdown();
|
||||
|
||||
virtual void LevelInit(const char* szMapName);
|
||||
virtual void LevelShutdown();
|
||||
|
||||
bool ScriptLoaded( void ) const { return m_bScriptLoaded; }
|
||||
CRC32_t GetScriptCRC() const { return m_ScriptCRC; }
|
||||
|
||||
private:
|
||||
// surround code that loads scripts to capture crc checksum
|
||||
// of the scripts that are loaded
|
||||
void BeginScriptLoad();
|
||||
void EndScriptLoad();
|
||||
|
||||
private:
|
||||
bool m_bScriptLoaded; ///< Whether or not a script file has been loaded in the current Lua environment
|
||||
bool m_bLoading; ///< True at the start of LevelInit, false at the end
|
||||
CRC32_t m_ScriptCRC; ///< CRC of all scripts loaded while m_isLoading was true
|
||||
|
||||
};
|
||||
|
||||
extern CFF_SH_ScriptManager_Game g_GameScriptManager;
|
||||
|
||||
#endif
|
|
@ -11,6 +11,10 @@ $Project
|
|||
{
|
||||
$File "$SRCDIR\game\shared\ff\ff_sh_scriptman.cpp"
|
||||
$File "$SRCDIR\game\shared\ff\ff_sh_scriptman.h"
|
||||
$File "$SRCDIR\game\shared\ff\ff_sh_scriptman_game.cpp"
|
||||
$File "$SRCDIR\game\shared\ff\ff_sh_scriptman_game.h"
|
||||
$File "$SRCDIR\game\shared\ff\ff_sh_luautil.cpp"
|
||||
$File "$SRCDIR\game\shared\ff\ff_sh_luautil.h"
|
||||
}
|
||||
$Folder "Movement"
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue