| @@ -0,0 +1,309 @@ | ||
| #include "luaevent.h" | ||
| #include <base/system.h> | ||
| //storage class for the event variables | ||
|
|
||
| CEventVariable::CEventVariable() | ||
| { | ||
| m_Type = EVENT_TYPE_INVALID; | ||
| m_pData = 0; | ||
| m_Size = 0; | ||
| } | ||
|
|
||
| CEventVariable::~CEventVariable() | ||
| { | ||
| if (m_pData) | ||
| delete [](char *)m_pData; | ||
| } | ||
|
|
||
| void CEventVariable::Allocate(int Size) | ||
| { | ||
| if (m_pData) | ||
| delete [](char *)m_pData; | ||
| m_Size = Size; | ||
| m_pData = 0; | ||
| if (Size > 0) | ||
| m_pData = new char[Size]; | ||
| } | ||
|
|
||
| //allocate 16 bytes even if we need 4 or just 1 | ||
| //why? | ||
| //because when we transform this var to something bigger | ||
| //bool -> int | ||
|
|
||
|
|
||
| void CEventVariable::Set(int Value) | ||
| { | ||
| m_Type = EVENT_TYPE_INTEGER; | ||
| Allocate(16); | ||
| mem_copy(m_pData, &Value, sizeof(Value)); | ||
| } | ||
|
|
||
| void CEventVariable::Set(long int Value) | ||
| { | ||
| m_Type = EVENT_TYPE_INTEGER; | ||
| Allocate(16); | ||
| mem_copy(m_pData, &Value, sizeof(Value)); | ||
| } | ||
|
|
||
| void CEventVariable::Set(lua_Number Value) | ||
| { | ||
| if (Value == (int)Value) | ||
| Set((int)Value); | ||
| Set((float)Value); | ||
| } | ||
|
|
||
| void CEventVariable::Set(float Value) | ||
| { | ||
| m_Type = EVENT_TYPE_FLOAT; | ||
| Allocate(16); | ||
| mem_copy(m_pData, &Value, sizeof(Value)); | ||
| } | ||
|
|
||
| void CEventVariable::Set(bool Value) | ||
| { | ||
| m_Type = EVENT_TYPE_BOOL; | ||
| Allocate(16); | ||
| mem_copy(m_pData, &Value, sizeof(Value)); | ||
| } | ||
|
|
||
| void CEventVariable::Set(char Value) | ||
| { | ||
| m_Type = EVENT_TYPE_CHAR; | ||
| Allocate(16); | ||
| mem_copy(m_pData, &Value, sizeof(Value)); | ||
| } | ||
|
|
||
| void CEventVariable::Set(const char *pStr) | ||
| { | ||
| m_Type = EVENT_TYPE_STRING; | ||
| Allocate(str_length(pStr) + 1); | ||
| mem_copy(m_pData, pStr, str_length(pStr) + 1); | ||
| } | ||
|
|
||
| void CEventVariable::Set(const char *pData, int Size) | ||
| { | ||
| m_Type = EVENT_TYPE_DATA; | ||
| Allocate(Size); | ||
| mem_copy(m_pData, pData, Size); | ||
| } | ||
|
|
||
| void *CEventVariable::Get() | ||
| { | ||
| return m_pData; | ||
| } | ||
|
|
||
| int CEventVariable::GetSize() | ||
| { | ||
| return m_Size; | ||
| } | ||
|
|
||
| char *CEventVariable::GetString() | ||
| { | ||
| return (char *)m_pData; | ||
| } | ||
|
|
||
| int CEventVariable::GetInteger() | ||
| { | ||
| if (m_Type == EVENT_TYPE_STRING) | ||
| return str_toint((char *)m_pData); | ||
| if (IsNumeric() == false) | ||
| return 0; | ||
| if (m_Type == EVENT_TYPE_FLOAT) | ||
| return GetFloat(); | ||
| if (!m_pData) | ||
| return 0; | ||
| return *((int *)m_pData); | ||
| } | ||
|
|
||
| float CEventVariable::GetFloat() | ||
| { | ||
| if (m_Type == EVENT_TYPE_STRING) | ||
| return str_tofloat((char *)m_pData); | ||
| if (IsNumeric() == false) | ||
| return 0; | ||
| if (m_Type != EVENT_TYPE_FLOAT) | ||
| return (float)GetInteger(); | ||
| if (!m_pData) | ||
| return 0; | ||
| return *((float *)m_pData); | ||
| } | ||
|
|
||
| bool CEventVariable::GetBool() | ||
| { | ||
| if (IsNumeric() == false) | ||
| return 0; | ||
| if (!m_pData) | ||
| return 0; | ||
| return *((bool *)m_pData); | ||
| } | ||
|
|
||
| char CEventVariable::GetChar() | ||
| { | ||
| if (IsNumeric() == false) | ||
| return 0; | ||
| if (!m_pData) | ||
| return 0; | ||
| return *((char *)m_pData); | ||
| } | ||
|
|
||
| int CEventVariable::GetType() | ||
| { | ||
| return m_Type; | ||
| } | ||
|
|
||
| bool CEventVariable::IsNumeric() | ||
| { | ||
| return !(!(m_Type & (EVENT_TYPE_INTEGER | EVENT_TYPE_FLOAT | EVENT_TYPE_BOOL | EVENT_TYPE_CHAR))); | ||
| } | ||
|
|
||
| void CEventVariable::Reset() | ||
| { | ||
| Allocate(0); //free | ||
| m_Type = EVENT_TYPE_INVALID; | ||
| } | ||
|
|
||
| void CEvent::Reset() | ||
| { | ||
| for (int i = 0; i < MAX_EVENT_VARIABLES; i++) | ||
| { | ||
| m_aVars[i].Reset(); | ||
| } | ||
| } | ||
|
|
||
| CEventVariable *CEvent::FindFree() | ||
| { | ||
| static CEventVariable Workaround; //remove me!! | ||
| Workaround.Reset(); | ||
| for (int i = 0; i < MAX_EVENT_VARIABLES; i++) | ||
| { | ||
| if (m_aVars[i].GetType() == CEventVariable::EVENT_TYPE_INVALID) | ||
| { | ||
| return &m_aVars[i]; | ||
| } | ||
| } | ||
| return &Workaround; | ||
| } | ||
| /* | ||
| //Eventlistener | ||
| template <class T> | ||
| void CLuaEventListener<T>::AddEventListener(T *pLuaFile, char *pEvent, char *pLuaFunction) | ||
| { | ||
| CLuaListenerData Listener; | ||
| Listener.m_pLuaFile = pLuaFile; | ||
| str_copy(Listener.m_aLuaFunction, pLuaFunction, sizeof(Listener.m_aLuaFunction)); | ||
| str_copy(Listener.m_aEvent, pEvent, sizeof(Listener.m_aEvent)); | ||
| m_aListeners.add(Listener); | ||
| } | ||
| template <class T> | ||
| void CLuaEventListener<T>::OnEvent(const char *pEvent) | ||
| { | ||
| /*if (GetState()) | ||
| { | ||
| return; //fixes a event called in an event listener | ||
| //should check for function names! to support event by event | ||
| //to do this we have to copy the result and the parameters -.- | ||
| //have to be done before L1.4 | ||
| }*/ | ||
| /* m_aStackReturns[m_StackSize].Reset(); | ||
| for(plain_range<CLuaListenerData> r = m_aListeners.all(); !r.empty(); r.pop_front()) | ||
| { | ||
| if (r.front().m_aEvent && str_comp_nocase(r.front().m_aEvent, pEvent) == 0) | ||
| { | ||
| if (r.front().m_pLuaFile->FunctionExist(r.front().m_aLuaFunction)) | ||
| { | ||
| int Num = lua_gettop(r.front().m_pLuaFile->m_pLua); //get stack size before calling fx | ||
| int Start = lua_gettop(r.front().m_pLuaFile->m_pLua); //get stack size before calling fx | ||
| r.front().m_pLuaFile->FunctionPrepare(r.front().m_aLuaFunction); | ||
| for (int i = 0; i < MAX_EVENT_VARIABLES; i++) | ||
| { | ||
| if (m_aStackParameters[m_StackSize].m_aVars[i].GetType() == CEventVariable::EVENT_TYPE_INTEGER) | ||
| { | ||
| r.front().m_pLuaFile->PushInteger(m_aStackParameters[m_StackSize].m_aVars[i].GetInteger()); | ||
| } | ||
| else if (m_aStackParameters[m_StackSize].m_aVars[i].GetType() == CEventVariable::EVENT_TYPE_CHAR) | ||
| { | ||
| r.front().m_pLuaFile->PushInteger(m_aStackParameters[m_StackSize].m_aVars[i].GetInteger()); | ||
| } | ||
| else if (m_aStackParameters[m_StackSize].m_aVars[i].GetType() == CEventVariable::EVENT_TYPE_FLOAT) | ||
| { | ||
| r.front().m_pLuaFile->PushFloat(m_aStackParameters[m_StackSize].m_aVars[i].GetFloat()); | ||
| } | ||
| else if (m_aStackParameters[m_StackSize].m_aVars[i].GetType() == CEventVariable::EVENT_TYPE_BOOL) | ||
| { | ||
| r.front().m_pLuaFile->PushBoolean(m_aStackParameters[m_StackSize].m_aVars[i].GetInteger()); | ||
| } | ||
| else if (m_aStackParameters[m_StackSize].m_aVars[i].GetType() == CEventVariable::EVENT_TYPE_STRING) | ||
| { | ||
| r.front().m_pLuaFile->PushString(m_aStackParameters[m_StackSize].m_aVars[i].GetString()); | ||
| } | ||
| else if (m_aStackParameters[m_StackSize].m_aVars[i].GetType() == CEventVariable::EVENT_TYPE_DATA) | ||
| { | ||
| r.front().m_pLuaFile->PushData((char *)m_aStackParameters[m_StackSize].m_aVars[i].Get(), m_aStackParameters[m_StackSize].m_aVars[i].GetSize()); | ||
| } | ||
| else | ||
| { | ||
| break; | ||
| } | ||
| } | ||
| r.front().m_pLuaFile->FunctionExec(); | ||
| Num = lua_gettop(r.front().m_pLuaFile->m_pLua) - Num; //get number of returns | ||
| for (int i = 0; i < Num; i++) //lua stack begins with 1 - so manipulate every i | ||
| { | ||
| if (lua_isnumber(r.front().m_pLuaFile->m_pLua, Start + i + 1)) | ||
| { | ||
| if (lua_tointeger(r.front().m_pLuaFile->m_pLua, Start + i + 1) == lua_tonumber(r.front().m_pLuaFile->m_pLua, Start + i + 1)) | ||
| m_aStackReturns[m_StackSize].m_aVars[i].Set((int)lua_tointeger(r.front().m_pLuaFile->m_pLua, Start + i + 1)); | ||
| else | ||
| m_aStackReturns[m_StackSize].m_aVars[i].Set((float)lua_tonumber(r.front().m_pLuaFile->m_pLua, Start + i + 1)); | ||
| } | ||
| else if (lua_isboolean(r.front().m_pLuaFile->m_pLua, Start + i + 1)) | ||
| { | ||
| m_aStackReturns[m_StackSize].m_aVars[i].Set(lua_toboolean(r.front().m_pLuaFile->m_pLua, Start + i + 1)); | ||
| } | ||
| else if (lua_isstring(r.front().m_pLuaFile->m_pLua, Start + i + 1)) | ||
| { | ||
| int Size = 0; | ||
| const char *pData = lua_tolstring(r.front().m_pLuaFile->m_pLua, Start + i + 1, (size_t *)&Size); | ||
| if (str_length(pData) == Size) | ||
| m_aStackReturns[m_StackSize].m_aVars[i].Set(pData); | ||
| else | ||
| m_aStackReturns[m_StackSize].m_aVars[i].Set(pData, Size); | ||
| } | ||
| } | ||
| for (int i = 0; i < Num; i++) //pop values | ||
| { | ||
| lua_remove(r.front().m_pLuaFile->m_pLua, -1); //remove value last first | ||
| //this solves the recusive-function-call-stack problem | ||
| //lua_pop(r.front().m_pLuaFile->m_pLua, 1); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| m_aStackParameters[m_StackSize].Reset(); // | ||
| m_StackSize--; | ||
| } | ||
| /* | ||
| template <class T> | ||
| void CLuaEventListener<T>::RemoveEventListener(T *pLuaFile, char *pEvent) | ||
| { | ||
| for(plain_range<CLuaListenerData> r = m_aListeners.all(); !r.empty(); r.pop_front()) | ||
| { | ||
| if (r.front().m_pLuaFile == pLuaFile && str_comp_nocase(r.front().m_aEvent, pEvent) == 0) | ||
| { | ||
| m_aListeners.remove(r.front()); | ||
| } | ||
| } | ||
| } | ||
| template <class T> | ||
| void CLuaEventListener<T>::RemoveAllEventListeners(T *pLuaFile) | ||
| { | ||
| for(plain_range<CLuaListenerData> r = m_aListeners.all(); !r.empty(); r.pop_front()) | ||
| { | ||
| if (r.front().m_pLuaFile == pLuaFile) | ||
| { | ||
| m_aListeners.remove(r.front()); | ||
| } | ||
| } | ||
| }*/ |
| @@ -0,0 +1,109 @@ | ||
| #ifndef GAME_LUAEVENT_H | ||
| #define GAME_LUAEVENT_H | ||
|
|
||
| #include <base/tl/array.h> | ||
| #include <lua.hpp> | ||
| #include "client/lua.h" | ||
|
|
||
| //storage class for the event variables | ||
|
|
||
| class CEventVariable | ||
| { | ||
| int m_Type; | ||
| void *m_pData; | ||
| int m_Size; | ||
| void Allocate(int Size); | ||
| public: | ||
| CEventVariable(); | ||
| ~CEventVariable(); | ||
| void Set(int Value); | ||
| void Set(long int Value); | ||
| void Set(lua_Number Value); | ||
| void Set(float Value); | ||
| void Set(bool Value); | ||
| void Set(char Value); | ||
| void Set(const char *pStr); | ||
| void Set(const char *pData, int Size); | ||
| void *Get(); | ||
| int GetSize(); | ||
| int GetInteger(); | ||
| float GetFloat(); | ||
| bool GetBool(); | ||
| char GetChar(); | ||
| char *GetString(); | ||
| int GetType(); | ||
| bool IsNumeric(); | ||
| void Reset(); | ||
|
|
||
| enum | ||
| { | ||
| EVENT_TYPE_INVALID = 0, | ||
| EVENT_TYPE_INTEGER = 1, | ||
| EVENT_TYPE_FLOAT = 2, | ||
| EVENT_TYPE_BOOL = 4, | ||
| EVENT_TYPE_CHAR = 8, | ||
| EVENT_TYPE_STRING = 16, | ||
| EVENT_TYPE_DATA = 32 | ||
| }; | ||
| }; | ||
|
|
||
|
|
||
| #define MAX_EVENT_VARIABLES 64 | ||
| class CEvent | ||
| { | ||
| public: | ||
| CEvent() | ||
| { | ||
| Reset(); | ||
| } | ||
| CEventVariable m_aVars[MAX_EVENT_VARIABLES]; | ||
| void Reset(); | ||
| CEventVariable *FindFree(); | ||
| }; | ||
| /* | ||
| template <class T> | ||
| class CLuaEventListener | ||
| { | ||
| struct CLuaListenerData | ||
| { | ||
| T *m_pLuaFile; | ||
| char m_aLuaFunction[256]; | ||
| char m_aEvent[256]; | ||
| bool operator==(const CLuaListenerData &Other) { return this == &Other; } | ||
| }; | ||
| typedef array<CLuaListenerData> TEventList; | ||
| TEventList m_aListeners; | ||
| public: | ||
| void AddEventListener(T *pLuaFile, char *pEvent, char *pLuaFunction); | ||
| void RemoveEventListener(T *pLuaFile, char *pEvent); | ||
| void RemoveAllEventListeners(T *pLuaFile); | ||
| void OnEvent(const char *pEvent); | ||
| #define EVENTSTACKSIZE 32 | ||
| int m_StackSize; | ||
| CEvent m_aStackParameters[EVENTSTACKSIZE]; | ||
| CEvent m_aStackReturns[EVENTSTACKSIZE]; | ||
| int CreateEventStack() { return ++m_StackSize; } | ||
| CEvent *GetParameters(int StackIndex) | ||
| { | ||
| if (StackIndex < 0 || StackIndex >= EVENTSTACKSIZE) | ||
| return 0; | ||
| return &m_aStackParameters[StackIndex]; | ||
| } | ||
| CEvent *GetReturns(int StackIndex) | ||
| { | ||
| if (StackIndex < 0 || StackIndex >= EVENTSTACKSIZE) | ||
| return 0; | ||
| return &m_aStackReturns[StackIndex];; | ||
| } | ||
| CLuaEventListener() { m_aListeners.clear(); m_StackSize = -1; } | ||
| ~CLuaEventListener() { m_aListeners.clear(); } | ||
| };*/ | ||
|
|
||
| #endif |
| @@ -0,0 +1,106 @@ | ||
| //some macros and helperfunctions | ||
| #include <stdlib.h> | ||
| #include <string.h> | ||
| #include <time.h> | ||
|
|
||
| #ifndef GAME_LUAGLOBAL_H | ||
| #define GAME_LUAGLOBAL_H | ||
|
|
||
|
|
||
| #if defined(LUA_USE_GMTIME_R) | ||
|
|
||
| #define l_gmtime(t,r) gmtime_r(t,r) | ||
| #define l_localtime(t,r) localtime_r(t,r) | ||
|
|
||
| #elif !defined(l_gmtime) | ||
|
|
||
| #define l_gmtime(t,r) ((void)r, gmtime(t)) | ||
| #define l_localtime(t,r) ((void)r, localtime(t)) | ||
|
|
||
| #endif | ||
|
|
||
| #define LUA_FUNCTION_HEADER lua_getglobal(L, "pLUA"); \ | ||
| CLuaFile *pSelf = (CLuaFile *)lua_touserdata(L, -1); \ | ||
| lua_Debug Frame; \ | ||
| lua_getstack(L, 1, &Frame); \ | ||
| lua_getinfo(L, "nlSf", &Frame); \ | ||
| ((void)(pSelf)); | ||
|
|
||
| #if !defined(LUA_USE_POSIX) | ||
| #define LUA_STRFTIMEOPTIONS { "aAbBcdHIjmMpSUwWxXyYz%", "" } | ||
| #else | ||
| #define LUA_STRFTIMEOPTIONS \ | ||
| { "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%", "" \ | ||
| "", "E", "cCxXyY", \ | ||
| "O", "deHImMSuUVwWy" } | ||
| #endif | ||
|
|
||
| static void setfield (lua_State *L, const char *key, int value) | ||
| { | ||
| lua_pushinteger(L, value); | ||
| lua_setfield(L, -2, key); | ||
| } | ||
|
|
||
| static void setboolfield (lua_State *L, const char *key, int value) | ||
| { | ||
| if (value < 0) /* undefined? */ | ||
| return; /* does not set field */ | ||
| lua_pushboolean(L, value); | ||
| lua_setfield(L, -2, key); | ||
| } | ||
|
|
||
| static int getboolfield (lua_State *L, const char *key) | ||
| { | ||
| int res; | ||
| lua_getfield(L, -1, key); | ||
| res = lua_isnil(L, -1) ? -1 : lua_toboolean(L, -1); | ||
| lua_pop(L, 1); | ||
| return res; | ||
| } | ||
|
|
||
|
|
||
| static int getfield (lua_State *L, const char *key, int d) | ||
| { | ||
| int res, isnum; | ||
| lua_getfield(L, -1, key); | ||
| res = (int)lua_tointegerx(L, -1, &isnum); | ||
| if (!isnum) | ||
| { | ||
| if (d < 0) | ||
| return luaL_error(L, "field " LUA_QS " missing in date table", key); | ||
| res = d; | ||
| } | ||
| lua_pop(L, 1); | ||
| return res; | ||
| } | ||
|
|
||
|
|
||
| static const char *checkoption (lua_State *L, const char *conv, char *buff) | ||
| { | ||
| static const char *const options[] = LUA_STRFTIMEOPTIONS; | ||
| unsigned int i; | ||
| for (i = 0; i < sizeof(options)/sizeof(options[0]); i += 2) | ||
| { | ||
| if (*conv != '\0' && strchr(options[i], *conv) != NULL) | ||
| { | ||
| buff[1] = *conv; | ||
| if (*options[i + 1] == '\0') /* one-char conversion specifier? */ | ||
| { | ||
| buff[2] = '\0'; /* end buffer */ | ||
| return conv + 1; | ||
| } | ||
| else if (*(conv + 1) != '\0' && | ||
| strchr(options[i + 1], *(conv + 1)) != NULL) | ||
| { | ||
| buff[2] = *(conv + 1); /* valid two-char conversion specifier */ | ||
| buff[3] = '\0'; /* end buffer */ | ||
| return conv + 2; | ||
| } | ||
| } | ||
| } | ||
| luaL_argerror(L, 1, | ||
| lua_pushfstring(L, "invalid conversion specifier '%%%s'", conv)); | ||
| return conv; /* to avoid warnings */ | ||
| } | ||
|
|
||
| #endif |
| @@ -0,0 +1,313 @@ | ||
| #include "luamap.h" | ||
| #include <base/math.h> | ||
| /*DGI:Doc-Gen-Info*/ | ||
| /*DGI:Type:Map*/ | ||
| /*DGI:Exception:errorfunc*/ | ||
| #include <lua.hpp> | ||
|
|
||
| #define LUA_FUNCTION_HEADER lua_getglobal(L, "pLUA"); \ | ||
| CLuaMapFile *pSelf = (CLuaMapFile *)lua_touserdata(L, -1); \ | ||
| lua_Debug Frame; \ | ||
| lua_getstack(L, 1, &Frame); \ | ||
| lua_getinfo(L, "nlSf", &Frame); \ | ||
| ((void)(pSelf)); | ||
|
|
||
| int CLuaMapFile::StrIsInteger(const char *pStr) | ||
| { | ||
| while(*pStr) | ||
| { | ||
| if(!(*pStr >= '0' && *pStr <= '9')) | ||
| return 0; | ||
| pStr++; | ||
| } | ||
| return 1; | ||
| } | ||
|
|
||
| int CLuaMapFile::StrIsFloat(const char *pStr) | ||
| { | ||
| bool Dot = false; | ||
| while(*pStr) | ||
| { | ||
| if(*pStr < '0' || *pStr > '9') | ||
| { | ||
| if(!Dot && *pStr == '.') | ||
| Dot = true; | ||
| else | ||
| return 0; | ||
| } | ||
| pStr++; | ||
| } | ||
| return 1; | ||
| } | ||
|
|
||
| void CLuaMapFile::PushString(const char *pString) | ||
| { | ||
| if (m_pLua == 0) | ||
| return; | ||
| lua_pushstring(m_pLua, pString); | ||
| m_FunctionVarNum++; | ||
| } | ||
|
|
||
| void CLuaMapFile::PushData(const char *pData, int Size) | ||
| { | ||
| if (m_pLua == 0) | ||
| return; | ||
| lua_pushlstring(m_pLua, pData, Size); | ||
| m_FunctionVarNum++; | ||
| } | ||
|
|
||
| void CLuaMapFile::PushInteger(int value) | ||
| { | ||
| if (m_pLua == 0) | ||
| return; | ||
| lua_pushinteger(m_pLua, value); | ||
| m_FunctionVarNum++; | ||
| } | ||
|
|
||
| void CLuaMapFile::PushFloat(float value) | ||
| { | ||
| if (m_pLua == 0) | ||
| return; | ||
| lua_pushnumber(m_pLua, value); | ||
| m_FunctionVarNum++; | ||
| } | ||
|
|
||
| void CLuaMapFile::PushBoolean(bool value) | ||
| { | ||
| if (m_pLua == 0) | ||
| return; | ||
| lua_pushboolean(m_pLua, value); | ||
| m_FunctionVarNum++; | ||
| } | ||
|
|
||
| void CLuaMapFile::PushParameter(const char *pString) | ||
| { | ||
| if (m_pLua == 0) | ||
| return; | ||
| if (StrIsInteger(pString)) | ||
| { | ||
| PushInteger(str_toint(pString)); | ||
| } | ||
| else if (StrIsFloat(pString)) | ||
| { | ||
| PushInteger(str_tofloat(pString)); | ||
| } | ||
| else | ||
| { | ||
| PushString(pString); | ||
| } | ||
|
|
||
| } | ||
|
|
||
| bool CLuaMapFile::FunctionExist(const char *pFunctionName) | ||
| { | ||
| bool Ret = false; | ||
| if (m_pLua == 0) | ||
| return false; | ||
| lua_getglobal(m_pLua, ToLower(pFunctionName)); | ||
| Ret = lua_isfunction(m_pLua, -1); | ||
| lua_pop(m_pLua, 1); | ||
| return Ret; | ||
| } | ||
|
|
||
| void CLuaMapFile::FunctionPrepare(const char *pFunctionName) | ||
| { | ||
| if (m_pLua == 0) | ||
| return; | ||
|
|
||
| //lua_pushstring (m_pLua, pFunctionName); | ||
| //lua_gettable (m_pLua, LUA_GLOBALSINDEX); | ||
| lua_getglobal(m_pLua, ToLower(pFunctionName)); | ||
| m_FunctionVarNum = 0; | ||
| } | ||
|
|
||
| int CLuaMapFile::FunctionExec(const char *pFunctionName) | ||
| { | ||
| if (m_pLua == 0) | ||
| return 0; | ||
|
|
||
| if (pFunctionName) | ||
| { | ||
| if (FunctionExist(pFunctionName) == false) | ||
| return 0; | ||
| FunctionPrepare(pFunctionName); | ||
| } | ||
| int Ret = lua_pcall(m_pLua, m_FunctionVarNum, LUA_MULTRET, 0); | ||
| if (Ret) | ||
| ErrorFunc(m_pLua); | ||
| m_FunctionVarNum = 0; | ||
| return Ret; | ||
| } | ||
|
|
||
| CLuaMapFile::CLuaMapFile(CTile *pTiles, const char *pCode, int Width, int Height) | ||
| { | ||
| m_pTiles = pTiles; | ||
| m_pLua = luaL_newstate(); | ||
| luaL_openlibs(m_pLua); | ||
|
|
||
| m_Width = Width; | ||
| m_Height = Height; | ||
|
|
||
| //lua_atpanic(m_pLua, &Panic); //Todo | ||
|
|
||
| lua_pushlightuserdata(m_pLua, this); | ||
| lua_setglobal(m_pLua, "pLUA"); | ||
|
|
||
| lua_register(m_pLua, ToLower("errorfunc"), this->ErrorFunc); | ||
| lua_register(m_pLua, ToLower("GetTile"), this->GetTile); | ||
| lua_register(m_pLua, ToLower("SetTile"), this->SetTile); | ||
| lua_register(m_pLua, ToLower("GetFlag"), this->GetFlag); | ||
| lua_register(m_pLua, ToLower("SetFlag"), this->SetFlag); | ||
| lua_register(m_pLua, ToLower("GetWidth"), this->GetWidth); | ||
| lua_register(m_pLua, ToLower("GetHeight"), this->GetHeight); | ||
|
|
||
|
|
||
| luaL_dostring(m_pLua, pCode); | ||
| ErrorFunc(m_pLua); | ||
| } | ||
|
|
||
| CLuaMapFile::~CLuaMapFile() | ||
| { | ||
| if (m_pLua) | ||
| lua_close(m_pLua); | ||
| m_pLua = 0; | ||
| } | ||
|
|
||
| void CLuaMapFile::Tick(int ServerTick) | ||
| { | ||
| FunctionPrepare("Tick"); | ||
| PushInteger((int)(time_get() * 1000 / time_freq())); //time in ms | ||
| PushInteger(ServerTick); | ||
| FunctionExec(); | ||
| } | ||
|
|
||
| int CLuaMapFile::GetTile(lua_State *L) | ||
| { | ||
| LUA_FUNCTION_HEADER | ||
| if (lua_isnumber(L, 1) && lua_isnumber(L, 2)) | ||
| { | ||
| if (lua_tointeger(L, 1) < 0) | ||
| return 0; | ||
| if (lua_tointeger(L, 1) >= pSelf->m_Width) | ||
| return 0; | ||
| if (lua_tointeger(L, 2) < 0) | ||
| return 0; | ||
| if (lua_tointeger(L, 2) >= pSelf->m_Height) | ||
| return 0; | ||
| lua_pushinteger(L, pSelf->m_pTiles[lua_tointeger(L, 2) * pSelf->m_Width + lua_tointeger(L, 1)].m_Index); | ||
| return 1; | ||
| } | ||
| return 0; | ||
| } | ||
|
|
||
| int CLuaMapFile::SetTile(lua_State *L) | ||
| { | ||
| LUA_FUNCTION_HEADER | ||
| if (lua_isnumber(L, 1) && lua_isnumber(L, 2) && lua_isnumber(L, 3)) | ||
| { | ||
| if (lua_tointeger(L, 1) < 0) | ||
| return 0; | ||
| if (lua_tointeger(L, 1) >= pSelf->m_Width) | ||
| return 0; | ||
| if (lua_tointeger(L, 2) < 0) | ||
| return 0; | ||
| if (lua_tointeger(L, 2) >= pSelf->m_Height) | ||
| return 0; | ||
| pSelf->m_pTiles[lua_tointeger(L, 2) * pSelf->m_Width + lua_tointeger(L, 1)].m_Index = clamp((int)lua_tointeger(L, 3), 0, 255); | ||
| return 0; | ||
| } | ||
| return 0; | ||
| } | ||
|
|
||
| int CLuaMapFile::GetFlag(lua_State *L) | ||
| { | ||
| LUA_FUNCTION_HEADER | ||
| return 0; | ||
| } | ||
|
|
||
| int CLuaMapFile::SetFlag(lua_State *L) | ||
| { | ||
| LUA_FUNCTION_HEADER | ||
| return 0; | ||
| } | ||
|
|
||
| int CLuaMapFile::GetWidth(lua_State *L) | ||
| { | ||
| LUA_FUNCTION_HEADER | ||
| lua_pushinteger(L, pSelf->m_Width); | ||
| return 1; | ||
| } | ||
|
|
||
| int CLuaMapFile::GetHeight(lua_State *L) | ||
| { | ||
| LUA_FUNCTION_HEADER | ||
| lua_pushinteger(L, pSelf->m_Height); | ||
| return 1; | ||
| } | ||
|
|
||
| int CLuaMapFile::ErrorFunc(lua_State *L) | ||
| { | ||
| lua_getglobal(L, "pLUA"); | ||
| CLuaMapFile *pSelf = (CLuaMapFile *)lua_touserdata(L, -1); | ||
| ((void)(pSelf)); | ||
|
|
||
| lua_pop(L,1); | ||
|
|
||
| int depth = 0; | ||
| int frameskip = 1; | ||
| lua_Debug frame; | ||
|
|
||
| if (lua_tostring(L, -1) == 0) | ||
| return 0; | ||
|
|
||
| dbg_msg("LuaMap", lua_tostring(L, -1)); | ||
|
|
||
| dbg_msg("LuaMap", "Backtrace:"); | ||
| while(lua_getstack(L, depth, &frame) == 1) | ||
| { | ||
| depth++; | ||
|
|
||
| lua_getinfo(L, "nlSf", &frame); | ||
|
|
||
| /* check for functions that just report errors. these frames just confuses more then they help */ | ||
| if(frameskip && str_comp(frame.short_src, "[C]") == 0 && frame.currentline == -1) | ||
| continue; | ||
| frameskip = 0; | ||
|
|
||
| /* print stack frame */ | ||
| dbg_msg("LuaMap", "%s(%d): %s %s", frame.short_src, frame.currentline, frame.name, frame.namewhat); | ||
| } | ||
| lua_pop(L, 1); // remove error message | ||
| lua_gc(L, LUA_GCCOLLECT, 0); | ||
| return 0; | ||
| } | ||
|
|
||
|
|
||
|
|
||
| CLuaMap::CLuaMap() | ||
| { | ||
| //m_pEventListener = new CLuaEventListener<CLuaMapFile>(); | ||
| } | ||
|
|
||
| CLuaMap::~CLuaMap() | ||
| { | ||
| Clear(); | ||
| } | ||
|
|
||
| void CLuaMap::Tick(int ServerTick, CTile *pTiles) | ||
| { | ||
| for (int i = 0; i < m_lLuaMapFiles.size(); i++) | ||
| { | ||
| if (m_lLuaMapFiles[i]->m_pTiles == pTiles || pTiles == 0) | ||
| m_lLuaMapFiles[i]->Tick(ServerTick); | ||
| } | ||
| } | ||
|
|
||
| void CLuaMap::Clear() | ||
| { | ||
| for (int i = 0; i < m_lLuaMapFiles.size(); i++) | ||
| { | ||
| delete m_lLuaMapFiles[i]; | ||
| } | ||
| m_lLuaMapFiles.clear(); | ||
| } |
| @@ -0,0 +1,58 @@ | ||
| #ifndef GAME_LUAMAP_H | ||
| #define GAME_LUAMAP_H | ||
|
|
||
| #include <game/luaevent.h> | ||
| #include <game/mapitems.h> | ||
| #include <base/tl/array.h> | ||
|
|
||
| #include <lua.hpp> | ||
|
|
||
| class CLuaMapFile | ||
| { | ||
| int StrIsInteger(const char *pStr); | ||
| int StrIsFloat(const char *pStr); | ||
|
|
||
| bool FunctionExist(const char *pFunctionName); | ||
| int FunctionExec(const char *pFunctionName = 0); | ||
| void FunctionPrepare(const char *pFunctionName); | ||
| void PushString(const char *pString); | ||
| void PushData(const char *pData, int Size); | ||
| void PushInteger(int value); | ||
| void PushFloat(float value); | ||
| void PushBoolean(bool value); | ||
| void PushParameter(const char *pString); | ||
| int m_FunctionVarNum; | ||
|
|
||
| public: | ||
| CLuaMapFile(CTile *pTiles, const char *pCode, int Width, int Height); | ||
| ~CLuaMapFile(); | ||
| CTile *m_pTiles; | ||
| int m_Width; | ||
| int m_Height; | ||
| lua_State *m_pLua; | ||
| void Tick(int ServerTick); | ||
|
|
||
|
|
||
| static int ErrorFunc(lua_State *L); | ||
| static int GetTile(lua_State *L); | ||
| static int SetTile(lua_State *L); | ||
| static int GetFlag(lua_State *L); | ||
| static int SetFlag(lua_State *L); | ||
| static int GetWidth(lua_State *L); | ||
| static int GetHeight(lua_State *L); | ||
| }; | ||
|
|
||
| class CLuaMap | ||
| { | ||
| public: | ||
| CLuaMap(); | ||
| ~CLuaMap(); | ||
| void Tick(int ServerTick, CTile *pTiles = 0); | ||
| void Clear(); | ||
|
|
||
| array<CLuaMapFile *> m_lLuaMapFiles; | ||
|
|
||
| //class CLuaEventListener<CLuaMapFile> *m_pEventListener; | ||
| }; | ||
|
|
||
| #endif |