Example #1
0
void LuaChatForm::OnOptionClicked(int option)
{
    SetMoney(1000000000);

	lua_State *l = Lua::manager->GetLuaState();

	LUA_DEBUG_START(l);

	lua_getfield(l, LUA_REGISTRYINDEX, "PiAdverts");
	assert(lua_istable(l, -1));

	lua_pushinteger(l, GetAdvert()->ref);
	lua_gettable(l, -2);
	assert(!lua_isnil(l, -1));

	lua_getfield(l, -1, "onChat");
	assert(lua_isfunction(l, -1));

	LuaObject<LuaChatForm>::PushToLua(this);
	lua_pushinteger(l, GetAdvert()->ref);
	lua_pushinteger(l, option);
	pi_lua_protected_call(l, 3, 0);

	lua_pop(l, 2);

	LUA_DEBUG_END(l, 0);
}
Example #2
0
void LuaEventQueueBase::Emit()
{
	if (!m_events.size()) return;

	lua_State *l = Pi::luaManager->GetLuaState();

	LUA_DEBUG_START(l);

	lua_getfield(l, LUA_REGISTRYINDEX, "PiEventQueue");
	assert(lua_istable(l, -1));
	lua_getfield(l, -1, m_name);
	assert(lua_istable(l, -1));

	while (m_events.size()) {
		LuaEventBase *e = m_events.front();
		m_events.pop_front();

		lua_pushnil(l);
		while (lua_next(l, -2) != 0) {
			int top = lua_gettop(l);
			PrepareLuaStack(l, e);
			pi_lua_protected_call(l, lua_gettop(l) - top, 0);
		}

		delete e;
	}

	lua_pop(l, 2);

	LUA_DEBUG_END(l, 0);
}
Example #3
0
void Emit()
{
	lua_State *l = Lua::manager->GetLuaState();

	LUA_DEBUG_START(l);
	if (!_get_method_onto_stack(l, "_Emit")) return;
	pi_lua_protected_call(l, 0, 0);
	LUA_DEBUG_END(l, 0);
}
	static void _signal_trampoline(PropertyMap &map, const std::string &k, LuaRef ref, lua_State *l) {
		ref.PushCopyToStack();
		lua_pushlstring(l, k.c_str(), k.size());
		map.PushLuaTable();
		lua_pushvalue(l, -2);
		lua_rawget(l, -2);
		lua_remove(l, -2);
		pi_lua_protected_call(l, 2, 0);
	}
Example #5
0
static void _fail_callback(const std::string &error, void *userdata)
{
	CallbackPair *cp = reinterpret_cast<CallbackPair*>(userdata);
	if (!cp->failCallback.IsValid()) return;

	cp->failCallback.PushCopyToStack();

	lua_pushlstring(cp->lua, error.c_str(), error.size());
	pi_lua_protected_call(cp->lua, 1, 0);

	delete cp;
}
Example #6
0
void LuaTimer::Tick()
{
	assert(Pi::game);
	lua_State *l = Pi::luaManager->GetLuaState();

	LUA_DEBUG_START(l);

	lua_getfield(l, LUA_REGISTRYINDEX, "PiTimerCallbacks");
	if (lua_isnil(l, -1)) {
		lua_pop(l, 1);
		LUA_DEBUG_END(l, 0);
		return;
	}
	assert(lua_istable(l, -1));

	double now = Pi::game->GetTime();

	lua_pushnil(l);
	while (lua_next(l, -2)) {
		assert(lua_istable(l, -1));

		lua_getfield(l, -1, "at");
		double at = lua_tonumber(l, -1);
		lua_pop(l, 1);

		if (at <= now) {
			lua_getfield(l, -1, "callback");
			pi_lua_protected_call(l, 0, 1);
			bool cancel = lua_toboolean(l, -1);
			lua_pop(l, 1);

			lua_getfield(l, -1, "every");
			if (lua_isnil(l, -1) || cancel) {
				lua_pop(l, 1);

				lua_pushvalue(l, -2);
				lua_pushnil(l);
				lua_settable(l, -5);
			}
			else {
				double every = lua_tonumber(l, -1);
				lua_pop(l, 1);

				pi_lua_settable(l, "at", Pi::game->GetTime() + every);
			}
		}

		lua_pop(l, 1);
	}
	lua_pop(l, 1);

	LUA_DEBUG_END(l, 0);
}
Example #7
0
static void _success_callback(const Json &data, void *userdata)
{
	CallbackPair *cp = reinterpret_cast<CallbackPair*>(userdata);
	if (!cp->successCallback.IsValid()) return;

	cp->successCallback.PushCopyToStack();

	_json_to_lua(cp->lua, data);
	pi_lua_protected_call(cp->lua, 1, 0);

	delete cp;
}
Example #8
0
void LuaChatForm::Sold(Equip::Type t) {
	lua_State *l = Lua::manager->GetLuaState();

	LUA_DEBUG_START(l);

	_get_trade_function(l, GetAdvert()->ref, "sold");

	lua_pushinteger(l, GetAdvert()->ref);
	lua_pushstring(l, EnumStrings::GetString("EquipType", t));
	pi_lua_protected_call(l, 2, 0);

	LUA_DEBUG_END(l, 0);
}
Example #9
0
void LuaChatForm::Bought(Equip::Type t) {
	lua_State *l = Lua::manager->GetLuaState();

	LUA_DEBUG_START(l);

	_get_trade_function(l, GetAdvert()->ref, "bought");

	lua_pushinteger(l, GetAdvert()->ref);
	lua_pushstring(l, LuaConstants::GetConstantString(l, "EquipType", t));
	pi_lua_protected_call(l, 2, 0);

	LUA_DEBUG_END(l, 0);
}
Example #10
0
void LuaChatForm::OnClose() {
	StationAdvertForm::OnClose();

	lua_State *l = Lua::manager->GetLuaState();
	int ref = GetAdvert()->ref;

	LUA_DEBUG_START(l);

	if (m_commodityTradeWidget) {
		lua_getfield(l, LUA_REGISTRYINDEX, "PiAdverts");
		assert(lua_istable(l, -1));

		lua_pushinteger(l, ref);
		lua_gettable(l, -2);
		assert(!lua_isnil(l, -1));

		lua_pushstring(l, "tradeWidgetFunctions");
		lua_pushnil(l);
		lua_settable(l, -3);

		lua_pop(l, 2);
	}

	if (!AdTaken()) return;

	lua_getfield(l, LUA_REGISTRYINDEX, "PiAdverts");
	assert(lua_istable(l, -1));

	lua_pushinteger(l, ref);
	lua_gettable(l, -2);
	assert(!lua_isnil(l, -1));

	lua_getfield(l, -1, "onDelete");
	if (!lua_isnil(l, -1)) {
		lua_pushinteger(l, ref);
		pi_lua_protected_call(l, 1, 0);
	}
	else
		lua_pop(l, 1);

	lua_pop(l, 1);

	lua_pushinteger(l, ref);
	lua_pushnil(l);
	lua_settable(l, -3);

	lua_pop(l, 1);

	LUA_DEBUG_END(l, 0);
}
Example #11
0
inline void LuaEventQueueBase::DoEventCall(lua_State *l, LuaEventBase *e)
{
	if (m_debugTimer) {
		int top = lua_gettop(l);

		lua_pushvalue(l, -1);
		lua_Debug ar;
		lua_getinfo(l, ">S", &ar);

		PrepareLuaStack(l, e);

		Uint32 start = SDL_GetTicks();
		pi_lua_protected_call(l, lua_gettop(l) - top, 0);
		Uint32 end = SDL_GetTicks();

		Pi::luaConsole->AddOutput(stringf("DEBUG: %0 %1{u}ms %2:%3{d}", m_name, end-start, ar.source, ar.linedefined));
	}
	else {
		int top = lua_gettop(l);
		PrepareLuaStack(l, e);
		pi_lua_protected_call(l, lua_gettop(l) - top, 0);
	}
}
Example #12
0
void Queue(const char *event, const ArgsBase &args)
{
	lua_State *l = Lua::manager->GetLuaState();

	LUA_DEBUG_START(l);
	if (!_get_method_onto_stack(l, "Queue")) return;

	int top = lua_gettop(l);
    lua_pushstring(l, event);
	args.PrepareStack();
	pi_lua_protected_call(l, lua_gettop(l) - top, 0);

	LUA_DEBUG_END(l, 0);
}
Example #13
0
std::string LuaNameGen::Surname(RefCountedPtr<Random> &rng)
{
	lua_State *l = m_luaManager->GetLuaState();

	if (!GetNameGenFunc(l, "Surname"))
		return DEFAULT_SURNAME;

	LuaObject<Random>::PushToLua(rng.Get());
	pi_lua_protected_call(l, 1, 1);

	std::string surname = luaL_checkstring(l, -1);
	lua_pop(l, 1);

	return surname;
}
Example #14
0
Widget *Context::CallTemplate(const char *name, const LuaTable &args)
{
	lua_State *l = m_lua->GetLuaState();

	m_templateStore.PushCopyToStack();
	const LuaTable t(l, -1);
	if (!t.Get<bool,const char *>(name))
		return 0;

	t.PushValueToStack<const char*>(name);
	lua_pushvalue(l, args.GetIndex());
	pi_lua_protected_call(m_lua->GetLuaState(), 1, 1);

	return LuaObject<UI::Widget>::CheckFromLua(-1);
}
Example #15
0
std::string LuaNameGen::FullName(bool isFemale, RefCountedPtr<Random> &rng)
{
	lua_State *l = m_luaManager->GetLuaState();

	if (!GetNameGenFunc(l, "FullName"))
		return isFemale ? DEFAULT_FULL_NAME_FEMALE : DEFAULT_FULL_NAME_MALE;

	lua_pushboolean(l, isFemale);
	LuaObject<Random>::PushToLua(rng.Get());
	pi_lua_protected_call(l, 2, 1);

	std::string fullname = luaL_checkstring(l, -1);
	lua_pop(l, 1);

	return fullname;
}
Example #16
0
std::string LuaNameGen::BodyName(SystemBody *body, RefCountedPtr<Random> &rng)
{
	lua_State *l = m_luaManager->GetLuaState();

	if (!GetNameGenFunc(l, "BodyName"))
		return DEFAULT_BODY_NAME;

	LuaObject<SystemBody>::PushToLua(body);
	LuaObject<Random>::PushToLua(rng.Get());
	pi_lua_protected_call(l, 2, 1);

	std::string bodyname = luaL_checkstring(l, -1);
	lua_pop(l, 1);

	return bodyname;
}
Example #17
0
void LuaSerializer::Serialize(Serializer::Writer &wr)
{
	lua_State *l = Lua::manager->GetLuaState();

	LUA_DEBUG_START(l);

	lua_newtable(l);
	int savetable = lua_gettop(l);

	lua_getfield(l, LUA_REGISTRYINDEX, "PiSerializerCallbacks");
	if (lua_isnil(l, -1)) {
		lua_pop(l, 1);
		lua_newtable(l);
		lua_pushvalue(l, -1);
		lua_setfield(l, LUA_REGISTRYINDEX, "PiSerializerCallbacks");
	}

	lua_pushnil(l);
	while (lua_next(l, -2) != 0) {
		lua_pushinteger(l, 1);
		lua_gettable(l, -2);
		pi_lua_protected_call(l, 0, 1);
		lua_pushvalue(l, -3);
		lua_insert(l, -2);
		lua_settable(l, savetable);
		lua_pop(l, 1);
	}

	lua_pop(l, 1);

	lua_newtable(l);
	lua_setfield(l, LUA_REGISTRYINDEX, "PiSerializerTableRefs");

	std::string pickled;
	pickle(l, savetable, pickled);

	wr.String(pickled);

	lua_pop(l, 1);

	lua_pushnil(l);
	lua_setfield(l, LUA_REGISTRYINDEX, "PiSerializerTableRefs");

	LUA_DEBUG_END(l, 0);
}
Example #18
0
void LuaSerializer::Unserialize(Serializer::Reader &rd)
{
	lua_State *l = Lua::manager->GetLuaState();

	LUA_DEBUG_START(l);

	lua_newtable(l);
	lua_setfield(l, LUA_REGISTRYINDEX, "PiSerializerTableRefs");

	std::string pickled = rd.String();
	const char *start = pickled.c_str();
	const char *end = unpickle(l, start);
	if (size_t(end - start) != pickled.length()) throw SavedGameCorruptException();
	if (!lua_istable(l, -1)) throw SavedGameCorruptException();
	int savetable = lua_gettop(l);

	lua_pushnil(l);
	lua_setfield(l, LUA_REGISTRYINDEX, "PiSerializerTableRefs");

	lua_getfield(l, LUA_REGISTRYINDEX, "PiSerializerCallbacks");
	if (lua_isnil(l, -1)) {
		lua_pop(l, 1);
		lua_newtable(l);
		lua_pushvalue(l, -1);
		lua_setfield(l, LUA_REGISTRYINDEX, "PiSerializerCallbacks");
	}

	lua_pushnil(l);
	while (lua_next(l, -2) != 0) {
		lua_pushvalue(l, -2);
		lua_pushinteger(l, 2);
		lua_gettable(l, -3);
		lua_getfield(l, savetable, lua_tostring(l, -2));
		if (lua_isnil(l, -1)) {
			lua_pop(l, 1);
			lua_newtable(l);
		}
		pi_lua_protected_call(l, 1, 0);
		lua_pop(l, 2);
	}

	lua_pop(l, 2);

	LUA_DEBUG_END(l, 0);
}
Example #19
0
Sint64 LuaChatForm::GetPrice(Equip::Type t) const {
	lua_State *l = Lua::manager->GetLuaState();

	LUA_DEBUG_START(l);

	_get_trade_function(l, GetAdvert()->ref, "getPrice");

	lua_pushinteger(l, GetAdvert()->ref);
	lua_pushstring(l, EnumStrings::GetString("EquipType", t));
	pi_lua_protected_call(l, 2, 1);

	Sint64 price = Sint64(lua_tonumber(l, -1) * 100.0);
	lua_pop(l, 1);

	LUA_DEBUG_END(l, 0);

	return price;
}
Example #20
0
int LuaChatForm::GetStock(Equip::Type t) const {
	lua_State *l = Lua::manager->GetLuaState();

	LUA_DEBUG_START(l);

	_get_trade_function(l, GetAdvert()->ref, "getStock");

	lua_pushinteger(l, GetAdvert()->ref);
	lua_pushstring(l, EnumStrings::GetString("EquipType", t));
	pi_lua_protected_call(l, 2, 1);

	int stock = lua_tointeger(l, -1);
	lua_pop(l, 1);

	LUA_DEBUG_END(l, 0);

	return stock;
}
Example #21
0
bool LuaChatForm::DoesSell(Equip::Type t) const {
	lua_State *l = Lua::manager->GetLuaState();

	LUA_DEBUG_START(l);

	_get_trade_function(l, GetAdvert()->ref, "canTrade");

	lua_pushinteger(l, GetAdvert()->ref);
	lua_pushstring(l, EnumStrings::GetString("EquipType", t));
	pi_lua_protected_call(l, 2, 1);

	bool can_trade = lua_toboolean(l, -1) != 0;
	lua_pop(l, 1);

	LUA_DEBUG_END(l, 0);

	return can_trade;
}
Example #22
0
/*
 * Method: RemoveAdvert
 *
 * Remove an advertisement from the station's bulletin board
 *
 * > station:RemoveAdvert(ref)
 *
 * If the deletefunc parameter was supplied to <AddAdvert> when the ad was
 * created, it will be called as part of this call.
 *
 * Parameters:
 *
 *   ref - the advert reference number returned by <AddAdvert>
 *
 * Availability:
 *
 *  alpha 10
 *
 * Status:
 *
 *  stable
 */
static int l_spacestation_remove_advert(lua_State *l)
{
	LUA_DEBUG_START(l);

	SpaceStation *s = LuaSpaceStation::GetFromLua(1);
	int ref = luaL_checkinteger(l, 2);

	if (!s->RemoveBBAdvert(ref))
		return 0;

	lua_getfield(l, LUA_REGISTRYINDEX, "PiAdverts");
	if (lua_isnil(l, -1)) {
		lua_pop(l, 1);
		return 0;
	}
	
	lua_pushinteger(l, ref);
	lua_gettable(l, -2);
	if (lua_isnil(l, -1)) {
		lua_pop(l, 2);
		return 0;
	}

	lua_getfield(l, -1, "onDelete");
	if (lua_isnil(l, -1))
		lua_pop(l, 1);
	else {
		lua_pushinteger(l, ref);
		pi_lua_protected_call(l, 1, 0);
	}

	lua_pop(l, 1);

	lua_pushinteger(l, ref);
	lua_pushnil(l);
	lua_settable(l, -3);

	lua_pop(l, 1);

	LUA_DEBUG_END(l,0);

	return 0;
} 
Example #23
0
void LuaSerializer::FromJson(const Json::Value &jsonObj)
{
	if (!jsonObj.isMember("lua_modules")) throw SavedGameCorruptException();

	lua_State *l = Lua::manager->GetLuaState();

	LUA_DEBUG_START(l);

	std::string pickled = JsonToBinStr(jsonObj, "lua_modules");

	const char *start = pickled.c_str();
	const char *end = unpickle(l, start);
	if (size_t(end - start) != pickled.length()) throw SavedGameCorruptException();
	if (!lua_istable(l, -1)) throw SavedGameCorruptException();
	int savetable = lua_gettop(l);

	lua_getfield(l, LUA_REGISTRYINDEX, "PiSerializerCallbacks");
	if (lua_isnil(l, -1)) {
		lua_pop(l, 1);
		lua_newtable(l);
		lua_pushvalue(l, -1);
		lua_setfield(l, LUA_REGISTRYINDEX, "PiSerializerCallbacks");
	}

	lua_pushnil(l);
	while (lua_next(l, -2) != 0) {
		lua_pushvalue(l, -2);
		lua_pushinteger(l, 2);
		lua_gettable(l, -3);
		lua_getfield(l, savetable, lua_tostring(l, -2));
		if (lua_isnil(l, -1)) {
			lua_pop(l, 1);
			lua_newtable(l);
		}
		pi_lua_protected_call(l, 1, 0);
		lua_pop(l, 2);
	}

	lua_pop(l, 2);

	LUA_DEBUG_END(l, 0);
}
Example #24
0
void LuaSerializer::ToJson(Json::Value &jsonObj)
{
	PROFILE_SCOPED()
	lua_State *l = Lua::manager->GetLuaState();

	LUA_DEBUG_START(l);

	lua_newtable(l);
	int savetable = lua_gettop(l);

	lua_getfield(l, LUA_REGISTRYINDEX, "PiSerializerCallbacks");
	if (lua_isnil(l, -1)) {
		lua_pop(l, 1);
		lua_newtable(l);
		lua_pushvalue(l, -1);
		lua_setfield(l, LUA_REGISTRYINDEX, "PiSerializerCallbacks");
	}

	lua_pushnil(l);
	while (lua_next(l, -2) != 0) {
		lua_pushinteger(l, 1); // 1, fntable, key
		lua_gettable(l, -2); // fn, fntable, key
		pi_lua_protected_call(l, 0, 1); // table, fntable, key
		lua_pushvalue(l, -3); // key, table, fntable, key
		lua_insert(l, -2); // table, key, fntable, key
		lua_settable(l, savetable); // fntable, key
		lua_pop(l, 1);
	}

	lua_pop(l, 1);

	std::string pickled;
	pickle(l, savetable, pickled);

	BinStrToJson(jsonObj, pickled, "lua_modules");

	lua_pop(l, 1);

	LUA_DEBUG_END(l, 0);
}
Example #25
0
void LuaChatForm::OnClickSell(int t) {
	lua_State *l = Lua::manager->GetLuaState();

	LUA_DEBUG_START(l);

	_get_trade_function(l, GetAdvert()->ref, "onClickSell");

	lua_pushinteger(l, GetAdvert()->ref);
	lua_pushstring(l, EnumStrings::GetString("EquipType", t));
	pi_lua_protected_call(l, 2, 1);

	bool allow_sell = lua_toboolean(l, -1) != 0;
	lua_pop(l, 1);

	LUA_DEBUG_END(l, 0);

	if (allow_sell) {
		if (BuyFrom(Pi::player, static_cast<Equip::Type>(t), true)) {
			Pi::Message(stringf(Lang::SOLD_1T_OF, formatarg("commodity", Equip::types[t].name)));
		}
		m_commodityTradeWidget->UpdateStock(t);
	}
}
Example #26
0
void LuaEventQueueBase::EmitSingleEvent(LuaEventBase *e)
{
	lua_State *l = Pi::luaManager->GetLuaState();

	LUA_DEBUG_START(l);

	lua_getfield(l, LUA_REGISTRYINDEX, "PiEventQueue");
	assert(lua_istable(l, -1));
	lua_getfield(l, -1, m_name);
	assert(lua_istable(l, -1));

	lua_pushnil(l);
	while (lua_next(l, -2) != 0) {
		int top = lua_gettop(l);
		PrepareLuaStack(l, e);
		pi_lua_protected_call(l, lua_gettop(l) - top, 0);
	}

	lua_pop(l, 2);

	LUA_DEBUG_END(l, 0);

	delete e;
}
Example #27
0
static void _delete_station_ads(SpaceStation *s)
{
	lua_State *l = Pi::luaManager->GetLuaState();

	LUA_DEBUG_START(l);

	lua_getfield(l, LUA_REGISTRYINDEX, "PiAdverts");
	assert(lua_istable(l, -1));

	const std::list<const BBAdvert*> bbadverts = s->GetBBAdverts();
	for (std::list<const BBAdvert*>::const_iterator i = bbadverts.begin(); i != bbadverts.end(); i++) {
		lua_pushinteger(l, (*i)->ref);
		lua_gettable(l, -2);
        if (lua_isnil(l, -1)) {
            lua_pop(l, 1);
            continue;
        }
		assert(lua_istable(l, -1));

		lua_getfield(l, -1, "onDelete");
		if (lua_isnil(l, -1))
			lua_pop(l, 1);
		else {
			lua_pushinteger(l, (*i)->ref);
			pi_lua_protected_call(l, 1, 0);
		}

		lua_pop(l, 1);
	}

	lua_pop(l, 1);

	LUA_DEBUG_END(l, 0);

	_station_delete_conns.erase(s);
}
Example #28
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);
}
Example #29
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);
}
Example #30
0
const char *LuaSerializer::unpickle(lua_State *l, const char *pos)
{
	LUA_DEBUG_START(l);

	char type = *pos++;

	switch (type) {

		case 'f': {
			char *end;
			double f = strtod(pos, &end);
			if (pos == end) throw SavedGameCorruptException();
			lua_pushnumber(l, f);
			pos = end+1; // skip newline
			break;
		}

		case 'b': {
			if (*pos != '0' && *pos != '1') throw SavedGameCorruptException();
			bool b = (*pos == '0') ? false : true;
			lua_pushboolean(l, b);
			pos++;
			break;
		}

		case 's': {
			char *end;
			int len = strtol(pos, const_cast<char**>(&end), 0);
			if (pos == end) throw SavedGameCorruptException();
			end++; // skip newline
			lua_pushlstring(l, end, len);
			pos = end + len;
			break;
		}

		case 't': {
			lua_newtable(l);

			lua_getfield(l, LUA_REGISTRYINDEX, "PiSerializerTableRefs");
			pos = unpickle(l, pos);
			lua_pushvalue(l, -3);
			lua_rawset(l, -3);
			lua_pop(l, 1);

			while (*pos != 'n') {
				pos = unpickle(l, pos);
				pos = unpickle(l, pos);
				lua_rawset(l, -3);
			}
			pos++;

			break;
		}

		case 'r': {
			pos = unpickle(l, pos);

			lua_getfield(l, LUA_REGISTRYINDEX, "PiSerializerTableRefs");
			lua_pushvalue(l, -2);
			lua_rawget(l, -2);

			if (lua_isnil(l, -1))
				throw SavedGameCorruptException();

			lua_insert(l, -3);
			lua_pop(l, 2);

			break;
		}

		case 'u': {
			const char *end = strchr(pos, '\n');
			if (!end) throw SavedGameCorruptException();
			int len = end - pos;
			end++; // skip newline

			if (len == 10 && strncmp(pos, "SystemPath", 10) == 0) {
				pos = end;

				Sint32 sectorX = strtol(pos, const_cast<char**>(&end), 0);
				if (pos == end) throw SavedGameCorruptException();
				pos = end+1; // skip newline

				Sint32 sectorY = strtol(pos, const_cast<char**>(&end), 0);
				if (pos == end) throw SavedGameCorruptException();
				pos = end+1; // skip newline

				Sint32 sectorZ = strtol(pos, const_cast<char**>(&end), 0);
				if (pos == end) throw SavedGameCorruptException();
				pos = end+1; // skip newline

				Uint32 systemNum = strtoul(pos, const_cast<char**>(&end), 0);
				if (pos == end) throw SavedGameCorruptException();
				pos = end+1; // skip newline

				Uint32 sbodyId = strtoul(pos, const_cast<char**>(&end), 0);
				if (pos == end) throw SavedGameCorruptException();
				pos = end+1; // skip newline

				SystemPath *sbp = new SystemPath(sectorX, sectorY, sectorZ, systemNum, sbodyId);
				LuaSystemPath::PushToLuaGC(sbp);

				break;
			}

			if (len == 4 && strncmp(pos, "Body", 4) == 0) {
				pos = end;

				Uint32 n = strtoul(pos, const_cast<char**>(&end), 0);
				if (pos == end) throw SavedGameCorruptException();
				pos = end+1; // skip newline

				Body *body = Pi::game->GetSpace()->GetBodyByIndex(n);
				if (pos == end) throw SavedGameCorruptException();

				switch (body->GetType()) {
					case Object::BODY:
						LuaBody::PushToLua(body);
						break;
					case Object::SHIP:
						LuaShip::PushToLua(dynamic_cast<Ship*>(body));
						break;
					case Object::SPACESTATION:
						LuaSpaceStation::PushToLua(dynamic_cast<SpaceStation*>(body));
						break;
					case Object::PLANET:
						LuaPlanet::PushToLua(dynamic_cast<Planet*>(body));
						break;
					case Object::STAR:
						LuaStar::PushToLua(dynamic_cast<Star*>(body));
						break;
					case Object::PLAYER:
						LuaPlayer::PushToLua(dynamic_cast<Player*>(body));
						break;
					default:
						throw SavedGameCorruptException();
				}

				break;
			}

			throw SavedGameCorruptException();
		}

		case 'o': {
			const char *end = strchr(pos, '\n');
			if (!end) throw SavedGameCorruptException();
			int len = end - pos;
			end++; // skip newline

			const char *cl = pos;

			// unpickle the object, and insert it beneath the method table value
			pos = unpickle(l, end);

			// get _G[typename]
			lua_rawgeti(l, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS);
			lua_pushlstring(l, cl, len);
			lua_gettable(l, -2);
			lua_remove(l, -2);

			if (lua_isnil(l, -1)) {
				lua_pop(l, 2);
				break;
			}

			lua_getfield(l, -1, "Unserialize");
			if (lua_isnil(l, -1)) {
				lua_pushlstring(l, cl, len);
				luaL_error(l, "No Unserialize method found for class '%s'\n", lua_tostring(l, -1));
			}

			lua_insert(l, -3);
			lua_pop(l, 1);

			pi_lua_protected_call(l, 1, 1);

			break;
		}

		default:
			throw SavedGameCorruptException();
	}

	LUA_DEBUG_END(l, 1);

	return pos;
}