Przeglądaj źródła

Fix ScriptWorld not calling lua error handler

Daniele Bartolini 8 lat temu
rodzic
commit
d52596589f

+ 39 - 41
src/lua/lua_environment.cpp

@@ -19,44 +19,6 @@ namespace crown
 {
 {
 extern void load_api(LuaEnvironment& env);
 extern void load_api(LuaEnvironment& env);
 
 
-// When an error occurs, logs the error message and pauses the engine.
-static int error_handler(lua_State* L)
-{
-	lua_getfield(L, LUA_GLOBALSINDEX, "debug");
-	if (!lua_istable(L, -1))
-	{
-		lua_pop(L, 1);
-		return 0;
-	}
-
-	lua_getfield(L, -1, "traceback");
-	if (!lua_isfunction(L, -1))
-	{
-		lua_pop(L, 2);
-		return 0;
-	}
-
-	lua_pushvalue(L, 1); // Pass error message
-	lua_pushinteger(L, 2);
-	lua_call(L, 2, 1); // Call debug.traceback
-
-	loge(LUA, lua_tostring(L, -1)); // Print error message
-	lua_pop(L, 1); // Remove error message from stack
-	lua_pop(L, 1); // Remove debug.traceback from stack
-
-	device()->pause();
-	return 0;
-}
-
-// Redirects require to the resource manager.
-static int require(lua_State* L)
-{
-	LuaStack stack(L);
-	const LuaResource* lr = (LuaResource*)device()->_resource_manager->get(RESOURCE_TYPE_SCRIPT, stack.get_resource_id(1));
-	luaL_loadbuffer(L, lua_resource::program(lr), lr->size, "");
-	return 1;
-}
-
 LuaEnvironment::LuaEnvironment()
 LuaEnvironment::LuaEnvironment()
 	: L(NULL)
 	: L(NULL)
 	, _vec3_used(0)
 	, _vec3_used(0)
@@ -114,7 +76,7 @@ void LuaEnvironment::load_libs()
 LuaStack LuaEnvironment::execute(const LuaResource* lr)
 LuaStack LuaEnvironment::execute(const LuaResource* lr)
 {
 {
 	LuaStack stack(L);
 	LuaStack stack(L);
-	lua_pushcfunction(L, error_handler);
+	lua_pushcfunction(L, LuaEnvironment::error);
 	luaL_loadbuffer(L, lua_resource::program(lr), lr->size, "<unknown>");
 	luaL_loadbuffer(L, lua_resource::program(lr), lr->size, "<unknown>");
 	lua_pcall(L, 0, 1, -2);
 	lua_pcall(L, 0, 1, -2);
 	lua_pop(L, 1);
 	lua_pop(L, 1);
@@ -124,7 +86,7 @@ LuaStack LuaEnvironment::execute(const LuaResource* lr)
 LuaStack LuaEnvironment::execute_string(const char* s)
 LuaStack LuaEnvironment::execute_string(const char* s)
 {
 {
 	LuaStack stack(L);
 	LuaStack stack(L);
-	lua_pushcfunction(L, error_handler);
+	lua_pushcfunction(L, LuaEnvironment::error);
 	luaL_loadstring(L, s);
 	luaL_loadstring(L, s);
 	lua_pcall(L, 0, 0, -2);
 	lua_pcall(L, 0, 0, -2);
 	lua_pop(L, 1);
 	lua_pop(L, 1);
@@ -198,7 +160,7 @@ void LuaEnvironment::call_global(const char* func, u8 argc, ...)
 	va_list vl;
 	va_list vl;
 	va_start(vl, argc);
 	va_start(vl, argc);
 
 
-	lua_pushcfunction(L, error_handler);
+	lua_pushcfunction(L, LuaEnvironment::error);
 	lua_getglobal(L, func);
 	lua_getglobal(L, func);
 
 
 	for (u8 i = 0; i < argc; i++)
 	for (u8 i = 0; i < argc; i++)
@@ -287,4 +249,40 @@ void LuaEnvironment::reset_temporaries()
 	_mat4_used = 0;
 	_mat4_used = 0;
 }
 }
 
 
+int LuaEnvironment::error(lua_State* L)
+{
+	lua_getfield(L, LUA_GLOBALSINDEX, "debug");
+	if (!lua_istable(L, -1))
+	{
+		lua_pop(L, 1);
+		return 0;
+	}
+
+	lua_getfield(L, -1, "traceback");
+	if (!lua_isfunction(L, -1))
+	{
+		lua_pop(L, 2);
+		return 0;
+	}
+
+	lua_pushvalue(L, 1); // Pass error message
+	lua_pushinteger(L, 2);
+	lua_call(L, 2, 1); // Call debug.traceback
+
+	loge(LUA, lua_tostring(L, -1)); // Print error message
+	lua_pop(L, 1); // Remove error message from stack
+	lua_pop(L, 1); // Remove debug.traceback from stack
+
+	device()->pause();
+	return 0;
+}
+
+int LuaEnvironment::require(lua_State* L)
+{
+	LuaStack stack(L);
+	const LuaResource* lr = (LuaResource*)device()->_resource_manager->get(RESOURCE_TYPE_SCRIPT, stack.get_resource_id(1));
+	luaL_loadbuffer(L, lua_resource::program(lr), lr->size, "");
+	return 1;
+}
+
 } // namespace crown
 } // namespace crown

+ 3 - 0
src/lua/lua_environment.h

@@ -89,6 +89,9 @@ struct LuaEnvironment
 	/// Returns whether @a p is a temporary Matrix4x4.
 	/// Returns whether @a p is a temporary Matrix4x4.
 	bool is_matrix4x4(const Matrix4x4* p) const;
 	bool is_matrix4x4(const Matrix4x4* p) const;
 
 
+	static int error(lua_State* L);
+	static int require(lua_State* L);
+
 private:
 private:
 
 
 	// Disable copying
 	// Disable copying

+ 15 - 4
src/world/script_world.cpp

@@ -37,6 +37,7 @@ namespace script_world
 {
 {
 	ScriptInstance create(ScriptWorld& sw, UnitId unit, const ScriptDesc& desc)
 	ScriptInstance create(ScriptWorld& sw, UnitId unit, const ScriptDesc& desc)
 	{
 	{
+
 		CE_ASSERT(!hash_map::has(sw._map, unit), "Unit already has script component");
 		CE_ASSERT(!hash_map::has(sw._map, unit), "Unit already has script component");
 
 
 		u32 script_i = hash_map::get(sw._cache
 		u32 script_i = hash_map::get(sw._cache
@@ -62,6 +63,7 @@ namespace script_world
 			LuaStack stack = sw._lua_environment->execute(lr);
 			LuaStack stack = sw._lua_environment->execute(lr);
 			stack.push_value(0);
 			stack.push_value(0);
 			sd.module_ref = luaL_ref(stack.L, LUA_REGISTRYINDEX);
 			sd.module_ref = luaL_ref(stack.L, LUA_REGISTRYINDEX);
+			stack.pop(1);
 
 
 			array::push_back(sw._script, sd);
 			array::push_back(sw._script, sd);
 			hash_map::set(sw._cache, desc.script_resource, script_i);
 			hash_map::set(sw._cache, desc.script_resource, script_i);
@@ -76,6 +78,7 @@ namespace script_world
 		hash_map::set(sw._map, unit, instance_i);
 		hash_map::set(sw._map, unit, instance_i);
 
 
 		LuaStack stack(sw._lua_environment->L);
 		LuaStack stack(sw._lua_environment->L);
+		stack.push_function(LuaEnvironment::error);
 		lua_rawgeti(stack.L, LUA_REGISTRYINDEX, sd.module_ref);
 		lua_rawgeti(stack.L, LUA_REGISTRYINDEX, sd.module_ref);
 		lua_getfield(stack.L, -1, "spawned");
 		lua_getfield(stack.L, -1, "spawned");
 		stack.push_world(sw._world);
 		stack.push_world(sw._world);
@@ -83,7 +86,8 @@ namespace script_world
 		stack.push_key_begin(1);
 		stack.push_key_begin(1);
 		stack.push_unit(unit);
 		stack.push_unit(unit);
 		stack.push_key_end();
 		stack.push_key_end();
-		stack.call(0);
+		lua_pcall(stack.L, 2, 0, -5);
+		stack.pop(2);
 
 
 		return script_world_internal::make_instance(instance_i);
 		return script_world_internal::make_instance(instance_i);
 	}
 	}
@@ -98,6 +102,7 @@ namespace script_world
 		const u32 script_i  = sw._data[unit_i].script_i;
 		const u32 script_i  = sw._data[unit_i].script_i;
 
 
 		LuaStack stack(sw._lua_environment->L);
 		LuaStack stack(sw._lua_environment->L);
+		stack.push_function(LuaEnvironment::error);
 		lua_rawgeti(stack.L, LUA_REGISTRYINDEX, sw._script[script_i].module_ref);
 		lua_rawgeti(stack.L, LUA_REGISTRYINDEX, sw._script[script_i].module_ref);
 		lua_getfield(stack.L, -1, "unspawned");
 		lua_getfield(stack.L, -1, "unspawned");
 		stack.push_world(sw._world);
 		stack.push_world(sw._world);
@@ -105,7 +110,8 @@ namespace script_world
 		stack.push_key_begin(1);
 		stack.push_key_begin(1);
 		stack.push_unit(unit);
 		stack.push_unit(unit);
 		stack.push_key_end();
 		stack.push_key_end();
-		stack.call(0);
+		lua_pcall(stack.L, 2, 0, -5);
+		stack.pop(2);
 
 
 		sw._data[unit_i] = sw._data[last_i];
 		sw._data[unit_i] = sw._data[last_i];
 		hash_map::set(sw._map, last_u, unit_i);
 		hash_map::set(sw._map, last_u, unit_i);
@@ -119,15 +125,20 @@ namespace script_world
 
 
 	void update(ScriptWorld& sw, f32 dt)
 	void update(ScriptWorld& sw, f32 dt)
 	{
 	{
+		LuaStack stack(sw._lua_environment->L);
+		stack.push_function(LuaEnvironment::error);
+
 		for (u32 i = 0; i < array::size(sw._script); ++i)
 		for (u32 i = 0; i < array::size(sw._script); ++i)
 		{
 		{
-			LuaStack stack(sw._lua_environment->L);
 			lua_rawgeti(stack.L, LUA_REGISTRYINDEX, sw._script[i].module_ref);
 			lua_rawgeti(stack.L, LUA_REGISTRYINDEX, sw._script[i].module_ref);
 			lua_getfield(stack.L, -1, "update");
 			lua_getfield(stack.L, -1, "update");
 			stack.push_world(sw._world);
 			stack.push_world(sw._world);
 			stack.push_float(dt);
 			stack.push_float(dt);
-			stack.call(0);
+			lua_pcall(stack.L, 2, 0, -5);
+			stack.pop(1);
 		}
 		}
+
+		stack.pop(1);
 	}
 	}
 
 
 } // namespace script_world
 } // namespace script_world