Esempio n. 1
0
LuaObjectBase* LuaObjectBase::getFromObject(lua_State* state, int object, bool error)
{
#ifdef FULL_USER_DATA
	// Make sure it's some user data!
	LUA->ReferencePush(object);
	int type = LUA->GetType(-1);
	if(type != GarrysMod::Lua::Type::USERDATA && type <= GarrysMod::Lua::Type::COUNT)
	{
		if (error)
		{
			LUA->ThrowError( "Invalid object! (not userdata)\n" );
		}
		return 0;
	}

	// Check the object
	GarrysMod::Lua::UserData* a = (GarrysMod::Lua::UserData*)LUA->GetUserdata(-1);
	LuaObjectBase* data = (LuaObjectBase*)(a->data);
	if (!checkValidity(state, type, data, error))
		return 0;
	
	// Just a simple cast required
	return reinterpret_cast<LuaObjectBase*>(a);
#else
	void* userData = object->GetMemberUserDataLite("_this");

	if (!checkValidity(luaInterface, 0, (LuaObjectBase*)userData, error))
		return 0;

	LuaObjectBase* baseObject = reinterpret_cast<LuaObjectBase*>(userData);
	baseObject->luaRef(object);
	return baseObject;
#endif
}
Esempio n. 2
0
void LuaSerializer::pickle(lua_State *l, int idx, std::string &out, const char *key = NULL)
{
	static char buf[256];

	LUA_DEBUG_START(l);

	idx = lua_absindex(l, idx);

	if (lua_getmetatable(l, idx)) {
		lua_getfield(l, -1, "class");
		if (lua_isnil(l, -1))
			lua_pop(l, 2);

		else {
			const char *cl = lua_tostring(l, -1);
			snprintf(buf, sizeof(buf), "o%s\n", cl);

			lua_getglobal(l, cl);
			if (lua_isnil(l, -1))
				luaL_error(l, "No Serialize method found for class '%s'\n", cl);

			lua_getfield(l, -1, "Serialize");
			if (lua_isnil(l, -1))
				luaL_error(l, "No Serialize method found for class '%s'\n", cl);

			lua_pushvalue(l, idx);
			pi_lua_protected_call(l, 1, 1);

			lua_remove(l, idx);
			lua_insert(l, idx);

			lua_pop(l, 3);

			if (lua_isnil(l, idx)) {
				LUA_DEBUG_END(l, 0);
				return;
			}

			out += buf;
		}
	}

	switch (lua_type(l, idx)) {
		case LUA_TNIL:
			break;

		case LUA_TNUMBER: {
			snprintf(buf, sizeof(buf), "f%f\n", lua_tonumber(l, idx));
			out += buf;
			break;
		}

		case LUA_TBOOLEAN: {
			snprintf(buf, sizeof(buf), "b%d", lua_toboolean(l, idx) ? 1 : 0);
			out += buf;
			break;
		}

		case LUA_TSTRING: {
			lua_pushvalue(l, idx);
			const char *str = lua_tostring(l, -1);
			snprintf(buf, sizeof(buf), "s" SIZET_FMT "\n", strlen(str));
			out += buf;
			out += str;
			lua_pop(l, 1);
			break;
		}

		case LUA_TTABLE: {
			lua_pushinteger(l, lua_Integer(lua_topointer(l, idx)));         // ptr

			lua_getfield(l, LUA_REGISTRYINDEX, "PiSerializerTableRefs");    // ptr reftable
			lua_pushvalue(l, -2);                                           // ptr reftable ptr
			lua_rawget(l, -2);                                              // ptr reftable ???

			if (!lua_isnil(l, -1)) {
				out += "r";
				pickle(l, -3, out, key);
				lua_pop(l, 3);                                              // [empty]
			}

			else {
				out += "t";

				lua_pushvalue(l, -3);                                       // ptr reftable nil ptr
				lua_pushvalue(l, idx);                                      // ptr reftable nil ptr table
				lua_rawset(l, -4);                                          // ptr reftable nil
				pickle(l, -3, out, key);
				lua_pop(l, 3);                                              // [empty]

				lua_pushvalue(l, idx);
				lua_pushnil(l);
				while (lua_next(l, -2)) {
					if (key) {
						pickle(l, -2, out, key);
						pickle(l, -1, out, key);
					}
					else {
						lua_pushvalue(l, -2);
						const char *k = lua_tostring(l, -1);
						pickle(l, -3, out, k);
						pickle(l, -2, out, k);
						lua_pop(l, 1);
					}
					lua_pop(l, 1);
				}
				lua_pop(l, 1);
				out += "n";
			}

			break;
		}

		case LUA_TUSERDATA: {
			out += "u";
			lid *idp = static_cast<lid*>(lua_touserdata(l, idx));
			LuaObjectBase *lo = LuaObjectBase::Lookup(*idp);
			if (!lo)
				Error("Lua serializer '%s' tried to serialize object with id 0x%08x, but it no longer exists", key, *idp);

			// XXX object wrappers should really have Serialize/Unserialize
			// methods to deal with this
			if (lo->Isa("SystemPath")) {
				SystemPath *sbp = dynamic_cast<SystemPath*>(lo->m_object);
				snprintf(buf, sizeof(buf), "SystemPath\n%d\n%d\n%d\n%u\n%u\n",
					sbp->sectorX, sbp->sectorY, sbp->sectorZ, sbp->systemIndex, sbp->bodyIndex);
				out += buf;
				break;
			}

			if (lo->Isa("Body")) {
				Body *b = dynamic_cast<Body*>(lo->m_object);
				snprintf(buf, sizeof(buf), "Body\n%u\n", Pi::game->GetSpace()->GetIndexForBody(b));
				out += buf;
				break;
			}

			Error("Lua serializer '%s' tried to serialize unsupported userdata value", key);
			break;
		}

		default:
			Error("Lua serializer '%s' tried to serialize %s value", key, lua_typename(l, lua_type(l, idx)));
			break;
	}

	LUA_DEBUG_END(l, 0);
}
Esempio n. 3
0
void LuaSerializer::pickle(lua_State *l, int to_serialize, std::string &out, std::string key)
{
	static char buf[256];

	LUA_DEBUG_START(l);

	// tables are pickled recursively, so we can run out of Lua stack space if we're not careful
	// start by ensuring we have enough (this grows the stack if necessary)
	// (20 is somewhat arbitrary)
	if (!lua_checkstack(l, 20))
		luaL_error(l, "The Lua stack couldn't be extended (out of memory?)");

	to_serialize = lua_absindex(l, to_serialize);
	int idx = to_serialize;

	if (lua_getmetatable(l, idx)) {
		lua_getfield(l, -1, "class");
		if (lua_isnil(l, -1))
			lua_pop(l, 2);

		else {
			const char *cl = lua_tostring(l, -1);
			snprintf(buf, sizeof(buf), "o%s\n", cl);

			lua_getfield(l, LUA_REGISTRYINDEX, "PiSerializerClasses");

			lua_getfield(l, -1, cl);
			if (lua_isnil(l, -1))
				luaL_error(l, "No Serialize method found for class '%s'\n", cl);

			lua_getfield(l, -1, "Serialize");
			if (lua_isnil(l, -1))
				luaL_error(l, "No Serialize method found for class '%s'\n", cl);

			lua_pushvalue(l, idx);
			pi_lua_protected_call(l, 1, 1);

			idx = lua_gettop(l);

			if (lua_isnil(l, idx)) {
				lua_pop(l, 5);
				LUA_DEBUG_END(l, 0);
				return;
			}

			out += buf;
		}
	}

	switch (lua_type(l, idx)) {
		case LUA_TNIL:
			break;

		case LUA_TNUMBER: {
			snprintf(buf, sizeof(buf), "f%f\n", lua_tonumber(l, idx));
			out += buf;
			break;
		}

		case LUA_TBOOLEAN: {
			snprintf(buf, sizeof(buf), "b%d", lua_toboolean(l, idx) ? 1 : 0);
			out += buf;
			break;
		}

		case LUA_TSTRING: {
			lua_pushvalue(l, idx);
			size_t len;
			const char *str = lua_tolstring(l, -1, &len);
			snprintf(buf, sizeof(buf), "s" SIZET_FMT "\n", len);
			out += buf;
			out.append(str, len);
			lua_pop(l, 1);
			break;
		}

		case LUA_TTABLE: {
			lua_pushinteger(l, lua_Integer(lua_topointer(l, to_serialize)));         // ptr

			lua_getfield(l, LUA_REGISTRYINDEX, "PiSerializerTableRefs");    // ptr reftable
			lua_pushvalue(l, -2);                                           // ptr reftable ptr
			lua_rawget(l, -2);                                              // ptr reftable ???

			if (!lua_isnil(l, -1)) {
				out += "r";
				pickle(l, -3, out, key);
				lua_pop(l, 3);                                              // [empty]
			}

			else {
				out += "t";

				lua_pushvalue(l, -3);                                       // ptr reftable nil ptr
				lua_pushvalue(l, to_serialize);                                      // ptr reftable nil ptr table
				lua_rawset(l, -4);                                          // ptr reftable nil
				pickle(l, -3, out, key);
				lua_pop(l, 3);                                              // [empty]

				lua_pushvalue(l, idx);
				lua_pushnil(l);
				while (lua_next(l, -2)) {

					lua_pushvalue(l, -2);
					const char *k = lua_tostring(l, -1);
					std::string new_key = key + "." + (k? std::string(k) : "<" + std::string(lua_typename(l, lua_type(l, -1))) + ">");
					lua_pop(l, 1);

					// Copy the values to pickle, as they might be mutated by the pickling process.
					pickle(l, -2, out, new_key);
					pickle(l, -1, out, new_key);
					lua_pop(l, 1);
				}
				lua_pop(l, 1);
				out += "n";
			}

			break;
		}

		case LUA_TUSERDATA: {
			out += "u";

			LuaObjectBase *lo = static_cast<LuaObjectBase*>(lua_touserdata(l, idx));
			void *o = lo->GetObject();
			if (!o)
				Error("Lua serializer '%s' tried to serialize an invalid '%s' object", key.c_str(), lo->GetType());

			out += lo->Serialize();
			break;
		}

		default:
			Error("Lua serializer '%s' tried to serialize %s value", key.c_str(), lua_typename(l, lua_type(l, idx)));
			break;
	}

	if (idx != lua_absindex(l, to_serialize)) // It means we called a transformation function on the data, so we clean it up.
		lua_pop(l, 5);

	LUA_DEBUG_END(l, 0);
}
Esempio n. 4
0
void LuaSerializer::pickle(lua_State *l, int idx, std::string &out, const char *key = NULL)
{
	static char buf[256];

	LUA_DEBUG_START(l);

	switch (lua_type(l, idx)) {
		case LUA_TNIL:
			break;

		case LUA_TNUMBER: {
			snprintf(buf, sizeof(buf), "f%f\n", lua_tonumber(l, idx));
			out += buf;
			break;
		}

		case LUA_TBOOLEAN: {
			snprintf(buf, sizeof(buf), "b%d", lua_toboolean(l, idx) ? 1 : 0);
			out += buf;
			break;
		}

		case LUA_TSTRING: {
			lua_pushvalue(l, idx);
			const char *str = lua_tostring(l, -1);
			snprintf(buf, sizeof(buf), "s%lu\n", strlen(str));
			out += buf;
			out += str;
			lua_pop(l, 1);
			break;
		}

		case LUA_TTABLE: {
			out += "t";
			lua_pushvalue(l, idx);
			lua_pushnil(l);
			while (lua_next(l, -2)) {
				if (key) {
					pickle(l, -2, out, key);
					pickle(l, -1, out, key);
				}
				else {
					lua_pushvalue(l, -2);
					const char *k = lua_tostring(l, -1);
					pickle(l, -3, out, k);
					pickle(l, -2, out, k);
					lua_pop(l, 1);
				}
				lua_pop(l, 1);
			}
			lua_pop(l, 1);
			out += "n";
			break;
		}

		case LUA_TUSERDATA: {
			out += "u";
			lid *idp = static_cast<lid*>(lua_touserdata(l, idx));
			LuaObjectBase *lo = LuaObjectBase::Lookup(*idp);
			if (!lo)
				Error("Lua serializer '%s' tried to serialize object with id 0x%08x, but it no longer exists", key, *idp);

			// XXX object wrappers should really have Serialize/Unserialize
			// methods to deal with this
			if (lo->Isa("SystemPath")) {
				SystemPath *sbp = dynamic_cast<SystemPath*>(lo->m_object);
				snprintf(buf, sizeof(buf), "SystemPath\n%d\n%d\n%d\n%d\n%d\n",
					sbp->sectorX, sbp->sectorY, sbp->sectorZ, sbp->systemIndex, sbp->bodyIndex);
				out += buf;
				break;
			}

			if (lo->Isa("Body")) {
				Body *b = dynamic_cast<Body*>(lo->m_object);
				snprintf(buf, sizeof(buf), "Body\n%d\n", Serializer::LookupBody(b));
				out += buf;
				break;
			}

			Error("Lua serializer '%s' tried to serialize unsupported userdata value", key);
			break;
		}

		default:
			Error("Lua serializer '%s' tried to serialize %s value", key, lua_typename(l, lua_type(l, idx)));
			break;
	}

	LUA_DEBUG_END(l, 0);
}