De/Adding Lua

Lua zu Source hinzuzufügen ist ziemlich einfach und mehrere Instanzen einzurichten ist noch einfacher.
== Quellcode ==
Füge diese beiden Datein zu deinem Projekt hinzu:
*
*
== Lua initialisieren == 
Sobald das erledigt ist, muss dein Code die init- und shutdown-Funktionen aufrufen. Füge in gameinterface.cpp dies in DLLInit vor den return true ein (um Zeile 557):
#ifdef GE_LUA
	// LUA starten
	GELua()->InitDll();
#endif
Und in der DLLShutdown-Funktion dies:
#ifdef GE_LUA
	// LUA dtoppen, schließt alle offenen Gameplays
	GELua()->ShutdownDll();
#endif
Gehe außerdem sicher, dden Manager-Header am Anfang einzubinden:
#ifdef GE_LUA
#include "ge_luamanager.h"
#endif
== Eine eigene Lua-Instanz erstellen ==
Du musst eine eigene Klasse erzeugen, die von LuaHandle abgeleitet ist und Funktionalität für Init, Shutdown und RegFunctions und RegGlobals bereitstellt.
=== Initialisierung ===
Init wird aufgerufen, nachdem Lua initialisiert wurde und stellt somit die Beste Stelle zum Laden der Skripte dar.
void MyLuaHandle::Init()
{
	const char* luaFile = "myLuaFile.lua";
	// In den Puffer laden
	FileHandle_t f = filesystem->Open( luaFile, "rb", "MOD" );
	if (!f)
		return;
	// Datei in null-terminierten Puffer laden
	int fileSize = filesystem->Size(f);
	unsigned bufSize = ((IFileSystem *)filesystem)->GetOptimalReadSize( f, fileSize + 1 );
	char *buffer = (char*)((IFileSystem *)filesystem)->AllocOptimalReadBuffer( f, bufSize );
	Assert(buffer);
	((IFileSystem *)filesystem)->ReadEx( buffer, bufSize, fileSize, f ); // in lokalen Puffer lesen
	buffer[fileSize] = '\0'; // terminieren der Datei
	filesystem->Close( f );	// Schließen der Datei nach dem Lesevorgang
	int error = luaL_loadbuffer( GetLua(), buffer, fileSize, luaFile );
	if (error)
	{
		Warning("[LUA-ERR] %s\n", lua_tostring(GetLua(), -1));
		lua_pop(GetLua(), 1); /* Fehlermeldung vom Stack abholen */
		Warning("[LUA-ERR] One or more errors occured while loading lua script!\n");
		return;
	}
	CallLUA(GetLua(), 0, LUA_MULTRET, 0, luaFile );
	m_bLuaLoaded = true;
}
=== Shutdown ===
Shutdown handhabt das Beenden Luas und sollte Funktionen in den Scripten aufrufen, um diese zu beenden.
=== RegGlobals ===
RegGlobals erlaubt es, globale Variablen in Lua zu registrieren.
void MyLuaHandle::RegGlobals()
{
	LG_DEFINE_INT("FOR_ALL_PLAYERS", -1);
	LG_DEFINE_INT("INVALID_ENTITY", -1);
	LG_DEFINE_INT("NULL", 0);
	LG_DEFINE_INT("GE_MAX_HEALTH", MAX_HEALTH);
	LG_DEFINE_INT("GE_MAX_ARMOR", MAX_ARMOR);
	LG_DEFINE_INT("MAX_PLAYERS", gpGlobals->maxClients);
	// Teamindikatoren
	LG_DEFINE_INT("TEAM_NONE",TEAM_UNASSIGNED);
	LG_DEFINE_INT("TEAM_SPECTATOR",TEAM_SPECTATOR);
	LG_DEFINE_INT("TEAM_MI6",TEAM_MI6);
	LG_DEFINE_INT("TEAM_JANUS",TEAM_JANUS);
	//ClientPrintAll-Typen
	LG_DEFINE_INT("HUD_PRINTNOTIFY",HUD_PRINTNOTIFY);
	LG_DEFINE_INT("HUD_PRINTCONSOLE",HUD_PRINTCONSOLE);
	LG_DEFINE_INT("HUD_PRINTTALK",HUD_PRINTTALK);
	LG_DEFINE_INT("HUD_PRINTCENTER",HUD_PRINTCENTER);
}
Die gebotenen Macros erlauben auch verschiedene Typen. LG_DEFINE_INT für int, LG_DEFINE_STRING für string und LG_DEFINE_BOOL für boolean.
=== RegFunctions ===
Wie die Globalen ist RegFunctions das Mittel zum Bekanntmachen der C-Funktionen für Lua.
void MyLuaHandle::RegFunctions()
{
	REG_FUNCTION( Msg );
	REG_FUNCTION( ConMsg );
	REG_FUNCTION( ClientPrintAll );
	REG_FUNCTION( GetTime );
}
Auch dies wurde mit einem Makro abgekürzt. Und somit müssen die Funktionen in einer anderen Datei definiert werden.
extern "C"
{
	#include <lua.h>
	#include <lauxlib.h>
	#include <lualib.h>
}
int luaClientPrintAll(lua_State *L)
{
	int n = lua_gettop(L); /* Anzahl der Argumente */
	switch(n)
	{
	case 2:
		UTIL_ClientPrintAll( lua_tointeger(L,1), lua_tostring(L,2));
		break;
	case 3:
		UTIL_ClientPrintAll( lua_tointeger(L,1), lua_tostring(L,2),lua_tostring(L,3));
		break;
	case 4:
		UTIL_ClientPrintAll( lua_tointeger(L,1), lua_tostring(L,2),lua_tostring(L,3),lua_tostring(L,4));
		break;
	case 5:
		UTIL_ClientPrintAll( lua_tointeger(L,1), lua_tostring(L,2),lua_tostring(L,3),lua_tostring(L,4),lua_tostring(L,5));
		break;
	case 6:
		UTIL_ClientPrintAll( lua_tointeger(L,1), lua_tostring(L,2),lua_tostring(L,3),lua_tostring(L,4),lua_tostring(L,5),lua_tostring(L,6));
		break;
	}
	return 0;
}
int luaMsg(lua_State *L)
{
	Msg("%s\n",lua_tostring(L,1));
	return 0;
}
int luaConMsg(lua_State *L)
{
	return luaMsg(L);
}
int luaGetTime(lua_State *L)
{
	lua_pushnumber( L, gpGlobals->curtime );
	return 1;
}
== Die Instanz erzeugen ==
Am Anfang deiner neuen LuaHandle-Klasse musst du eine Funktion hinzugefügen, die einen globalen Zugriff auf die Lua-Instanz ermöglicht. Füge ungefähr sowas hinzu:
MyLuaHandle* g_LuaHandle = NULL;
MyLuaHandle *GetLuaHandle()
{
	return g_LuaHandle;
}
Und im LuaHandle-Konstruktor musst die Instanz bei der Erzeugung gespeichert werden:
MyLuaHandle::MyLuaHandle() : LuaHandle()
{
	g_LuaHandle = this;
	Register();
}
Und letztendlich muss im GameRules-Konstruktor die neue Instanz erzeugt werden:
CGameRules::CGameRules()
{
	// anderes Zeug hier
	// die Lua GamePlay-Engine starten
	if (!GetLuaHandle())
		new MyLuaHandle();
}
== Projekteinstellungen ==
In den Serverprojekteinstellungen muss GE_LUA den Präprozessoroptionen hinzugefügt werden (Configure properties -> c++ -> Preprocesser -> Preprocesser defines).
Außerdem musst du die Lua-lib (sollte den gleichen Namen wie die lib-Datei haben, z. B. lua5.1.lib) den Linker-Einstellungen hinzufügen (Configure properties -> Linker -> Input -> Additional Dependencies )
Platziere die Lua-lib nun im src/lib-Verzeichnis. Nun sollte es kompilieren und du ein funktionierendes Lua haben.
== Aufrufe von C zu Lua ==
Das ist etwas schwieriger und du must die Lua Dokumentation dafür konsultieren, aber hier ist ein Beispiel:
void CGELUAGamePlay::PostRoundBegin()
{
	if (m_bLuaLoaded)
	{
		lua_getglobal(GetLua(), "RoundStart");
		CallLUA(GetLua(), 0, 0, 0, "RoundStart");
	}
}