Browse Source

Add love.event.restart(optionalvalue) as a shorthand for love.event.quit("restart", optionalvalue). If a Lua value is provided as an argument, a new love.restart field will contain the value after restarting.

--HG--
branch : minor
Alex Szpakowski 5 years ago
parent
commit
b001b2e1d5
6 changed files with 65 additions and 20 deletions
  1. 9 3
      src/common/Variant.cpp
  2. 1 1
      src/common/Variant.h
  3. 22 6
      src/love.cpp
  4. 23 2
      src/modules/event/wrap_Event.cpp
  5. 3 3
      src/scripts/boot.lua
  6. 7 5
      src/scripts/boot.lua.h

+ 9 - 3
src/common/Variant.cpp

@@ -152,7 +152,7 @@ Variant &Variant::operator = (const Variant &v)
 	return *this;
 }
 
-Variant Variant::fromLua(lua_State *L, int n, std::set<const void*> *tableSet)
+Variant Variant::fromLua(lua_State *L, int n, bool allowuserdata, std::set<const void*> *tableSet)
 {
 	size_t len;
 	const char *str;
@@ -173,6 +173,11 @@ Variant Variant::fromLua(lua_State *L, int n, std::set<const void*> *tableSet)
 	case LUA_TLIGHTUSERDATA:
 		return Variant(lua_touserdata(L, n));
 	case LUA_TUSERDATA:
+		if (!allowuserdata)
+		{
+			luax_typerror(L, n, "copyable Lua value");
+			return Variant();
+		}
 		p = tryextractproxy(L, n);
 		if (p != nullptr)
 			return Variant(p->type, p->object);
@@ -187,7 +192,6 @@ Variant Variant::fromLua(lua_State *L, int n, std::set<const void*> *tableSet)
 		{
 			bool success = true;
 			std::set<const void *> topTableSet;
-			SharedTable *table = new SharedTable();
 
 			// We can use a pointer to a stack-allocated variable because it's
 			// never used after the stack-allocated variable is destroyed.
@@ -202,6 +206,8 @@ Variant Variant::fromLua(lua_State *L, int n, std::set<const void*> *tableSet)
 					throw love::Exception("Cycle detected in table");
 			}
 
+			SharedTable *table = new SharedTable();
+
 			size_t len = luax_objlen(L, -1);
 			if (len > 0)
 				table->pairs.reserve(len);
@@ -210,7 +216,7 @@ Variant Variant::fromLua(lua_State *L, int n, std::set<const void*> *tableSet)
 
 			while (lua_next(L, n))
 			{
-				table->pairs.emplace_back(fromLua(L, -2, tableSet), fromLua(L, -1, tableSet));
+				table->pairs.emplace_back(fromLua(L, -2, allowuserdata, tableSet), fromLua(L, -1, allowuserdata, tableSet));
 				lua_pop(L, 1);
 
 				const auto &p = table->pairs.back();

+ 1 - 1
src/common/Variant.h

@@ -111,7 +111,7 @@ public:
 	Type getType() const { return type; }
 	const Data &getData() const { return data; }
 
-	static Variant fromLua(lua_State *L, int n, std::set<const void*> *tableSet = nullptr);
+	static Variant fromLua(lua_State *L, int n, bool allowuserdata = true, std::set<const void*> *tableSet = nullptr);
 	void toLua(lua_State *L) const;
 
 private:

+ 22 - 6
src/love.cpp

@@ -20,6 +20,7 @@
 
 #include "common/version.h"
 #include "common/runtime.h"
+#include "common/Variant.h"
 #include "modules/love/love.h"
 #include <SDL.h>
 
@@ -139,7 +140,7 @@ enum DoneAction
 	DONE_RESTART,
 };
 
-static DoneAction runlove(int argc, char **argv, int &retval)
+static DoneAction runlove(int argc, char **argv, int &retval, love::Variant &restartvalue)
 {
 #ifdef LOVE_LEGENDARY_APP_ARGV_HACK
 	int hack_argc = 0;
@@ -203,6 +204,11 @@ static DoneAction runlove(int argc, char **argv, int &retval)
 		lua_setfield(L, -2, "_exe");
 	}
 
+	// Set love.restart = restartvalue, and clear restartvalue.
+	restartvalue.toLua(L);
+	lua_setfield(L, -2, "restart");
+	restartvalue = love::Variant();
+
 	// Pop the love table returned by require "love".
 	lua_pop(L, 1);
 
@@ -223,10 +229,19 @@ static DoneAction runlove(int argc, char **argv, int &retval)
 
 	// if love.boot() returns "restart", we'll start up again after closing this
 	// Lua state.
-	if (lua_type(L, -1) == LUA_TSTRING && strcmp(lua_tostring(L, -1), "restart") == 0)
-		done = DONE_RESTART;
-	if (lua_isnumber(L, -1))
-		retval = (int) lua_tonumber(L, -1);
+	int retidx = stackpos;
+	if (!lua_isnoneornil(L, retidx))
+	{
+		if (lua_type(L, retidx) == LUA_TSTRING && strcmp(lua_tostring(L, retidx), "restart") == 0)
+			done = DONE_RESTART;
+		if (lua_isnumber(L, retidx))
+			retval = (int) lua_tonumber(L, retidx);
+
+		// Disallow userdata (love objects) from being referenced by the restart
+		// value.
+		if (retidx < lua_gettop(L))
+			restartvalue = love::Variant::fromLua(L, retidx + 1, false);
+	}
 
 	lua_close(L);
 
@@ -253,10 +268,11 @@ int main(int argc, char **argv)
 
 	int retval = 0;
 	DoneAction done = DONE_QUIT;
+	love::Variant restartvalue;
 
 	do
 	{
-		done = runlove(argc, argv, retval);
+		done = runlove(argc, argv, retval, restartvalue);
 
 #ifdef LOVE_IOS
 		// on iOS we should never programmatically exit the app, so we'll just

+ 23 - 2
src/modules/event/wrap_Event.cpp

@@ -22,9 +22,10 @@
 
 // LOVE
 #include "common/runtime.h"
-
 #include "sdl/Event.h"
 
+#include <algorithm>
+
 // Shove the wrap_Event.lua code directly into a raw string literal.
 static const char event_lua[] =
 #include "wrap_Event.lua"
@@ -95,7 +96,26 @@ int w_clear(lua_State *L)
 int w_quit(lua_State *L)
 {
 	luax_catchexcept(L, [&]() {
-		std::vector<Variant> args = {Variant::fromLua(L, 1)};
+		std::vector<Variant> args;
+		for (int i = 1; i <= std::max(1, lua_gettop(L)); i++)
+			args.push_back(Variant::fromLua(L, i));
+
+		StrongRef<Message> m(new Message("quit", args), Acquire::NORETAIN);
+		instance()->push(m);
+	});
+
+	luax_pushboolean(L, true);
+	return 1;
+}
+
+int w_restart(lua_State *L)
+{
+	luax_catchexcept(L, [&]() {
+		std::vector<Variant> args;
+		args.emplace_back("restart", strlen("restart"));
+
+		for (int i = 1; i <= lua_gettop(L); i++)
+			args.push_back(Variant::fromLua(L, i));
 
 		StrongRef<Message> m(new Message("quit", args), Acquire::NORETAIN);
 		instance()->push(m);
@@ -114,6 +134,7 @@ static const luaL_Reg functions[] =
 	{ "push", w_push },
 	{ "clear", w_clear },
 	{ "quit", w_quit },
+	{ "restart", w_restart },
 	{ 0, 0 }
 };
 

+ 3 - 3
src/scripts/boot.lua

@@ -598,7 +598,7 @@ function love.run()
 			for name, a,b,c,d,e,f in love.event.poll() do
 				if name == "quit" then
 					if not love.quit or not love.quit() then
-						return a or 0
+						return a or 0, b
 					end
 				end
 				love.handlers[name](a,b,c,d,e,f)
@@ -799,8 +799,8 @@ return function()
 	func = earlyinit
 
 	while func do
-		local _, retval = xpcall(func, deferErrhand)
-		if retval then return retval end
+		local _, retval, restartvalue = xpcall(func, deferErrhand)
+		if retval then return retval, restartvalue end
 		coroutine.yield()
 	end
 

+ 7 - 5
src/scripts/boot.lua.h

@@ -1208,7 +1208,7 @@ const unsigned char boot_lua[] =
 	0x75, 0x69, 0x74, 0x20, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x71, 0x75, 
 	0x69, 0x74, 0x28, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
 	0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61, 0x20, 0x6f, 0x72, 0x20, 
-	0x30, 0x0a,
+	0x30, 0x2c, 0x20, 0x62, 0x0a,
 	0x09, 0x09, 0x09, 0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
 	0x09, 0x09, 0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
 	0x09, 0x09, 0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x73, 0x5b, 
@@ -1581,11 +1581,13 @@ const unsigned char boot_lua[] =
 	0x09, 0x66, 0x75, 0x6e, 0x63, 0x20, 0x3d, 0x20, 0x65, 0x61, 0x72, 0x6c, 0x79, 0x69, 0x6e, 0x69, 0x74, 0x0a,
 	0x0a,
 	0x09, 0x77, 0x68, 0x69, 0x6c, 0x65, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x20, 0x64, 0x6f, 0x0a,
-	0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x5f, 0x2c, 0x20, 0x72, 0x65, 0x74, 0x76, 0x61, 0x6c, 0x20, 
-	0x3d, 0x20, 0x78, 0x70, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x2c, 0x20, 0x64, 0x65, 0x66, 
-	0x65, 0x72, 0x45, 0x72, 0x72, 0x68, 0x61, 0x6e, 0x64, 0x29, 0x0a,
+	0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x5f, 0x2c, 0x20, 0x72, 0x65, 0x74, 0x76, 0x61, 0x6c, 0x2c, 
+	0x20, 0x72, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x3d, 0x20, 0x78, 0x70, 
+	0x63, 0x61, 0x6c, 0x6c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x2c, 0x20, 0x64, 0x65, 0x66, 0x65, 0x72, 0x45, 0x72, 
+	0x72, 0x68, 0x61, 0x6e, 0x64, 0x29, 0x0a,
 	0x09, 0x09, 0x69, 0x66, 0x20, 0x72, 0x65, 0x74, 0x76, 0x61, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 
-	0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x76, 0x61, 0x6c, 0x20, 0x65, 0x6e, 0x64, 0x0a,
+	0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x76, 0x61, 0x6c, 0x2c, 0x20, 0x72, 0x65, 0x73, 0x74, 
+	0x61, 0x72, 0x74, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x65, 0x6e, 0x64, 0x0a,
 	0x09, 0x09, 0x63, 0x6f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x65, 0x2e, 0x79, 0x69, 0x65, 0x6c, 0x64, 0x28, 
 	0x29, 0x0a,
 	0x09, 0x65, 0x6e, 0x64, 0x0a,