diff --git a/ElunaTemplate.h b/ElunaTemplate.h index e3dee34..73cf2c0 100644 --- a/ElunaTemplate.h +++ b/ElunaTemplate.h @@ -136,32 +136,24 @@ public: ASSERT(E); ASSERT(name); - // check that metatable isn't already there - luaL_getmetatable(E->L, name); - ASSERT(lua_isnoneornil(E->L, -1)); - // check that metatable isn't already there lua_getglobal(E->L, name); ASSERT(lua_isnoneornil(E->L, -1)); - // pop metatable and methodtable values - lua_pop(E->L, 2); + // pop nil + lua_pop(E->L, 1); tname = name; manageMemory = gc; - // create methodtable for userdata of this type + // create metatable for userdata of this type lua_newtable(E->L); - int methods = lua_gettop(E->L); + int metatable = lua_gettop(E->L); // push methodtable to stack to be accessed and modified by users - lua_pushvalue(E->L, methods); + lua_pushvalue(E->L, metatable); lua_setglobal(E->L, tname); - // create metatable for userdatas of this type - ASSERT(luaL_newmetatable(E->L, tname)); - int metatable = lua_gettop(E->L); - // tostring lua_pushcfunction(E->L, ToString); lua_setfield(E->L, metatable, "__tostring"); @@ -171,13 +163,9 @@ public: lua_setfield(E->L, metatable, "__gc"); // make methods accessible through metatable - lua_pushvalue(E->L, methods); + lua_pushvalue(E->L, metatable); lua_setfield(E->L, metatable, "__index"); - // make new indexes saved to methods - lua_pushvalue(E->L, methods); - lua_setfield(E->L, metatable, "__newindex"); - // make new indexes saved to methods lua_pushcfunction(E->L, Add); lua_setfield(E->L, metatable, "__add"); @@ -232,14 +220,14 @@ public: // special method to get the object type lua_pushcfunction(E->L, GetType); - lua_setfield(E->L, methods, "GetObjectType"); + lua_setfield(E->L, metatable, "GetObjectType"); // special method to decide object invalidation at end of call lua_pushcfunction(E->L, SetInvalidation); - lua_setfield(E->L, methods, "SetInvalidation"); + lua_setfield(E->L, metatable, "SetInvalidation"); - // pop methods and metatable - lua_pop(E->L, 2); + // pop metatable + lua_pop(E->L, 1); } template @@ -250,12 +238,7 @@ public: ASSERT(methodTable); // get metatable - luaL_getmetatable(E->L, tname); - ASSERT(lua_istable(E->L, -1)); - - // get method table - lua_getfield(E->L, -1, "__index"); - lua_remove(E->L, -2); + lua_getglobal(E->L, tname); ASSERT(lua_istable(E->L, -1)); for (; methodTable && methodTable->name && methodTable->mfunc; ++methodTable) @@ -267,7 +250,7 @@ public: lua_settable(E->L, -3); } - lua_remove(E->L, -1); + lua_pop(E->L, 1); } static int Push(lua_State* L, T const* obj) @@ -278,54 +261,50 @@ public: return 1; } - //if (!manageMemory) - //{ - lua_getglobal(L, ELUNA_OBJECT_STORE); - ASSERT(lua_istable(L, -1)); - lua_pushfstring(L, "%p", obj); - lua_gettable(L, -2); - if (ElunaObject* elunaObj = Eluna::CHECKTYPE(L, -1, tname, false)) - { - // set userdata valid - elunaObj->SetValid(true); + void* obj_voidptr = static_cast(const_cast(obj)); - // remove userdata_table, leave userdata - lua_remove(L, -2); - return 1; - } - lua_remove(L, -1); - // left userdata_table in stack - //} + lua_getglobal(L, ELUNA_OBJECT_STORE); + ASSERT(lua_istable(L, -1)); + lua_pushlightuserdata(L, obj_voidptr); + lua_rawget(L, -2); + if (ElunaObject* elunaObj = Eluna::CHECKTYPE(L, -1, tname, false)) + { + // set userdata valid + elunaObj->SetValid(true); + + // remove userdata_table, leave userdata + lua_remove(L, -2); + return 1; + } + lua_pop(L, 1); + // left userdata_table in stack // Create new userdata ElunaObject** ptrHold = static_cast(lua_newuserdata(L, sizeof(ElunaObject*))); if (!ptrHold) { ELUNA_LOG_ERROR("%s could not create new userdata", tname); - lua_pop(L, 2 /*manageMemory ? 1 : 2*/); + lua_pop(L, 2); lua_pushnil(L); return 1; } - *ptrHold = new ElunaObject((void*)(obj), manageMemory); + *ptrHold = new ElunaObject(obj_voidptr, manageMemory); // Set metatable for it - luaL_getmetatable(L, tname); + lua_getglobal(L, tname); if (!lua_istable(L, -1)) { ELUNA_LOG_ERROR("%s missing metatable", tname); - lua_pop(L, 3 /*manageMemory ? 2 : 3*/); + lua_pop(L, 3); lua_pushnil(L); return 1; } lua_setmetatable(L, -2); - //if (!manageMemory) - //{ - lua_pushfstring(L, "%p", obj); - lua_pushvalue(L, -2); - lua_settable(L, -4); - lua_remove(L, -2); - //} + lua_pushlightuserdata(L, obj_voidptr); + lua_pushvalue(L, -2); + lua_rawset(L, -4); + lua_remove(L, -2); return 1; } @@ -335,31 +314,6 @@ public: if (!elunaObj) return NULL; - //if (!manageMemory) - //{ - // // Check pointer validity - // lua_rawgeti(L, LUA_REGISTRYINDEX, sEluna->userdata_table); - // lua_pushfstring(L, "%p", (*ptrHold)->GetObj()); - // lua_gettable(L, -2); - // lua_remove(L, -2); - // bool valid = lua_isuserdata(L, -1) != 0; - // lua_remove(L, -1); - // if (!valid) - // { - // char buff[256]; - // snprintf(buff, 256, "%s expected, got pointer to nonexisting object (%s). This should never happen", tname, luaL_typename(L, narg)); - // if (error) - // { - // luaL_argerror(L, narg, buff); - // } - // else - // { - // ELUNA_LOG_ERROR("%s", buff); - // } - // return NULL; - // } - //} - if (!elunaObj->IsValid()) { char buff[256]; diff --git a/ElunaUtility.cpp b/ElunaUtility.cpp index 06a653e..4415259 100644 --- a/ElunaUtility.cpp +++ b/ElunaUtility.cpp @@ -131,7 +131,7 @@ void ElunaUtil::EncodeData(const unsigned char* data, size_t input_length, std:: unsigned char* ElunaUtil::DecodeData(const char *data, size_t *output_length) { - if (decoding_table['B'] == 0) + if (decoding_table[(unsigned char)'B'] == 0) build_decoding_table(); size_t input_length = strlen(data); @@ -162,10 +162,10 @@ unsigned char* ElunaUtil::DecodeData(const char *data, size_t *output_length) for (size_t i = 0, j = 0; i < input_length;) { - uint32_t sextet_a = data[i] == '=' ? 0 & i++ : decoding_table[data[i++]]; - uint32_t sextet_b = data[i] == '=' ? 0 & i++ : decoding_table[data[i++]]; - uint32_t sextet_c = data[i] == '=' ? 0 & i++ : decoding_table[data[i++]]; - uint32_t sextet_d = data[i] == '=' ? 0 & i++ : decoding_table[data[i++]]; + uint32_t sextet_a = data[i] == '=' ? 0 & i++ : decoding_table[(unsigned char)data[i++]]; + uint32_t sextet_b = data[i] == '=' ? 0 & i++ : decoding_table[(unsigned char)data[i++]]; + uint32_t sextet_c = data[i] == '=' ? 0 & i++ : decoding_table[(unsigned char)data[i++]]; + uint32_t sextet_d = data[i] == '=' ? 0 & i++ : decoding_table[(unsigned char)data[i++]]; uint32_t triple = (sextet_a << (3 * 6)) + (sextet_b << (2 * 6)) diff --git a/GameObjectMethods.h b/GameObjectMethods.h index c739509..0ed04bc 100644 --- a/GameObjectMethods.h +++ b/GameObjectMethods.h @@ -238,21 +238,39 @@ namespace LuaGameObject /** * Removes [GameObject] from the world * + * The object is no longer reachable after this and it is not respawned. + * * @param bool deleteFromDB : if true, it will delete the [GameObject] from the database */ int RemoveFromWorld(Eluna* /*E*/, lua_State* L, GameObject* go) { bool deldb = Eluna::CHECKVAL(L, 2, false); + + // cs_gobject.cpp copy paste + ObjectGuid ownerGuid = go->GetOwnerGUID(); + if (ownerGuid) + { + Unit* owner = ObjectAccessor::GetUnit(*go, ownerGuid); + if (!owner || !ownerGuid.IsPlayer()) + return 0; + + owner->RemoveGameObject(go, false); + } + + go->SetRespawnTime(0); + go->Delete(); + if (deldb) go->DeleteFromDB(); - go->RemoveFromWorld(); + + Eluna::CHECKOBJ(L, 1)->Invalidate(); return 0; } /** - * Changes uses a door or a button type [GameObject] + * Activates a door or a button/lever * - * @param uint32 delay : cooldown time in seconds to restore the [GameObject] back to normal + * @param uint32 delay = 0 : cooldown time in seconds to restore the [GameObject] back to normal. 0 for infinite duration */ int UseDoorOrButton(Eluna* /*E*/, lua_State* L, GameObject* go) { @@ -265,32 +283,35 @@ namespace LuaGameObject /** * Despawns a [GameObject] * - * @param uint32 delay : time in seconds to despawn + * The gameobject may be automatically respawned by the core */ int Despawn(Eluna* /*E*/, lua_State* L, GameObject* go) { - uint32 delay = Eluna::CHECKVAL(L, 2, 1); - if (!delay) - delay = 1; - - go->SetSpawnedByDefault(false); - go->SetRespawnTime(delay); + go->SetLootState(GO_JUST_DEACTIVATED); return 0; } /** * Respawns a [GameObject] - * - * @param uint32 delay : time of respawn in seconds */ int Respawn(Eluna* /*E*/, lua_State* L, GameObject* go) { - uint32 delay = Eluna::CHECKVAL(L, 2, 1); - if (!delay) - delay = 1; + go->Respawn(); + return 0; + } - go->SetSpawnedByDefault(true); - go->SetRespawnTime(delay); + /** + * Sets the respawn or despawn time for the gameobject. + * + * Respawn time is also used as despawn time depending on gameobject settings + * + * @param int32 delay = 0 : cooldown time in seconds to respawn or despawn the object. 0 means never + */ + int SetRespawnTime(Eluna* /*E*/, lua_State* L, GameObject* go) + { + int32 respawn = Eluna::CHECKVAL(L, 2); + + go->SetRespawnTime(respawn); return 0; } }; diff --git a/LuaEngine.cpp b/LuaEngine.cpp index 38e38f5..ccd99aa 100644 --- a/LuaEngine.cpp +++ b/LuaEngine.cpp @@ -178,6 +178,8 @@ CreatureUniqueBindings(NULL) Eluna::~Eluna() { + ASSERT(IsInitialized()); + CloseLua(); delete eventMgr; @@ -901,13 +903,14 @@ ElunaObject* Eluna::CHECKTYPE(lua_State* luastate, int narg, const char* tname, { if (lua_getmetatable(luastate, narg)) { - luaL_getmetatable(luastate, tname); - if (lua_rawequal(luastate, -1, -2) == 1) + lua_getglobal(luastate, tname); + bool equal = lua_rawequal(luastate, -1, -2) == 1; + lua_pop(luastate, 2); + if (equal) { valid = true; ptrHold = static_cast(lua_touserdata(luastate, narg)); } - lua_pop(luastate, 2); } } @@ -916,7 +919,7 @@ ElunaObject* Eluna::CHECKTYPE(lua_State* luastate, int narg, const char* tname, if (error) { char buff[256]; - snprintf(buff, 256, "bad argument : %s expected, got %s", tname ? tname : "userdata", luaL_typename(luastate, narg)); + snprintf(buff, 256, "bad argument : %s expected, got %s", tname ? tname : "ElunaObject", luaL_typename(luastate, narg)); luaL_argerror(luastate, narg, buff); } return NULL; diff --git a/LuaFunctions.cpp b/LuaFunctions.cpp index cd3f5d8..1324997 100644 --- a/LuaFunctions.cpp +++ b/LuaFunctions.cpp @@ -867,6 +867,7 @@ ElunaRegister GameObjectMethods[] = // Setters { "SetGoState", &LuaGameObject::SetGoState }, { "SetLootState", &LuaGameObject::SetLootState }, + { "SetRespawnTime", &LuaGameObject::SetRespawnTime }, // Boolean { "IsTransport", &LuaGameObject::IsTransport }, diff --git a/lmarshal.cpp b/lmarshal.cpp index a70ebde..2775331 100644 --- a/lmarshal.cpp +++ b/lmarshal.cpp @@ -71,7 +71,7 @@ static void buf_init(lua_State *L, mar_Buffer *buf) if (!(buf->data = (char*)malloc(buf->size))) luaL_error(L, "Out of memory!"); } -static void buf_done(lua_State* L, mar_Buffer *buf) +static void buf_done(lua_State* /*L*/, mar_Buffer *buf) { free(buf->data); } @@ -85,9 +85,11 @@ static int buf_write(lua_State* L, const char* str, size_t len, mar_Buffer *buf) while (new_size - cur_head <= len) { new_size = new_size << 1; } - if (!(buf->data = (char*)realloc(buf->data, new_size))) { - luaL_error(L, "Out of memory!"); + char* data = (char*)realloc(buf->data, new_size); + if (!data) { + return luaL_error(L, "Out of memory!"); } + buf->data = data; buf->size = new_size; } memcpy(&buf->data[buf->head], str, len); @@ -95,7 +97,7 @@ static int buf_write(lua_State* L, const char* str, size_t len, mar_Buffer *buf) return 0; } -static const char* buf_read(lua_State *L, mar_Buffer *buf, size_t *len) +static const char* buf_read(lua_State* /*L*/, mar_Buffer *buf, size_t *len) { if (buf->seek < buf->head) { buf->seek = buf->head; @@ -225,7 +227,7 @@ static void mar_encode_value(lua_State *L, mar_Buffer *buf, int val, size_t *idx buf_done(L, &rec_buf); lua_pop(L, 1); - lua_newtable(L); + lua_createtable(L, ar.nups, 0); for (i = 1; i <= ar.nups; i++) { const char* upvalue_name = lua_getupvalue(L, -2, i); if (strcmp("_ENV", upvalue_name) == 0) { @@ -469,7 +471,7 @@ static int mar_decode_table(lua_State *L, const char* buf, size_t len, size_t *i while (p - buf < (ptrdiff_t)len) { mar_decode_value(L, buf, len, &p, idx); mar_decode_value(L, buf, len, &p, idx); - lua_settable(L, -3); + lua_rawset(L, -3); } return 1; }