From 43d1f375d18a2fbc547a9b4f23d1354d645856ca Mon Sep 17 00:00:00 2001
From: ShadowNinja <shadowninja@minetest.net>
Date: Fri, 12 Dec 2014 14:49:19 -0500
Subject: Use a settings object for the main settings

This unifies the settings APIs.

This also unifies the sync and async registration APIs, since the async
registration API did not support adding non-functions to the API table.
---
 src/script/cpp_api/s_async.cpp    |  17 ++----
 src/script/cpp_api/s_async.h      |  10 ++--
 src/script/lua_api/l_base.cpp     |  14 ++---
 src/script/lua_api/l_base.h       |   5 +-
 src/script/lua_api/l_internal.h   |   3 +-
 src/script/lua_api/l_mainmenu.cpp |  36 +++++++------
 src/script/lua_api/l_mainmenu.h   |   3 +-
 src/script/lua_api/l_settings.cpp |  83 ++++++++++++++++++++++------
 src/script/lua_api/l_settings.h   |  13 +++--
 src/script/lua_api/l_util.cpp     | 110 +++++++-------------------------------
 src/script/lua_api/l_util.h       |  18 +------
 src/script/scripting_client.cpp   |  10 ++--
 src/script/scripting_mainmenu.cpp |  17 +++---
 src/script/scripting_mainmenu.h   |   1 +
 src/script/scripting_server.cpp   |  26 ++++-----
 15 files changed, 168 insertions(+), 198 deletions(-)

(limited to 'src')

diff --git a/src/script/cpp_api/s_async.cpp b/src/script/cpp_api/s_async.cpp
index 080ae887c..722359066 100644
--- a/src/script/cpp_api/s_async.cpp
+++ b/src/script/cpp_api/s_async.cpp
@@ -76,14 +76,9 @@ AsyncEngine::~AsyncEngine()
 }
 
 /******************************************************************************/
-bool AsyncEngine::registerFunction(const char* name, lua_CFunction func)
+void AsyncEngine::registerStateInitializer(StateInitializer func)
 {
-	if (initDone) {
-		return false;
-	}
-
-	functionList[name] = func;
-	return true;
+	stateInitializers.push_back(func);
 }
 
 /******************************************************************************/
@@ -204,11 +199,9 @@ void AsyncEngine::pushFinishedJobs(lua_State* L) {
 /******************************************************************************/
 void AsyncEngine::prepareEnvironment(lua_State* L, int top)
 {
-	for (UNORDERED_MAP<std::string, lua_CFunction>::iterator it = functionList.begin();
-			it != functionList.end(); ++it) {
-		lua_pushstring(L, it->first.c_str());
-		lua_pushcfunction(L, it->second);
-		lua_settable(L, top);
+	for (std::vector<StateInitializer>::iterator it = stateInitializers.begin();
+			it != stateInitializers.end(); it++) {
+		(*it)(L, top);
 	}
 }
 
diff --git a/src/script/cpp_api/s_async.h b/src/script/cpp_api/s_async.h
index 93e9759b4..dbe0654e2 100644
--- a/src/script/cpp_api/s_async.h
+++ b/src/script/cpp_api/s_async.h
@@ -75,16 +75,16 @@ private:
 // Asynchornous thread and job management
 class AsyncEngine {
 	friend class AsyncWorkerThread;
+	typedef void (*StateInitializer)(lua_State *L, int top);
 public:
 	AsyncEngine();
 	~AsyncEngine();
 
 	/**
-	 * Register function to be used within engine
-	 * @param name Function name to be used within Lua environment
+	 * Register function to be called on new states
 	 * @param func C function to be called
 	 */
-	bool registerFunction(const char* name, lua_CFunction func);
+	void registerStateInitializer(StateInitializer func);
 
 	/**
 	 * Create async engine tasks and lock function registration
@@ -140,8 +140,8 @@ private:
 	// Variable locking the engine against further modification
 	bool initDone;
 
-	// Internal store for registred functions
-	UNORDERED_MAP<std::string, lua_CFunction> functionList;
+	// Internal store for registred state initializers
+	std::vector<StateInitializer> stateInitializers;
 
 	// Internal counter to create job IDs
 	unsigned int jobIdCounter;
diff --git a/src/script/lua_api/l_base.cpp b/src/script/lua_api/l_base.cpp
index dfe743b72..5d7ba9640 100644
--- a/src/script/lua_api/l_base.cpp
+++ b/src/script/lua_api/l_base.cpp
@@ -74,17 +74,13 @@ std::string ModApiBase::getCurrentModPath(lua_State *L)
 }
 
 
-bool ModApiBase::registerFunction(
-	lua_State *L,
-	const char *name,
-	lua_CFunction fct,
-	int top)
+bool ModApiBase::registerFunction(lua_State *L, const char *name,
+		lua_CFunction func, int top)
 {
-	//TODO check presence first!
+	// TODO: Check presence first!
 
-	lua_pushstring(L,name);
-	lua_pushcfunction(L,fct);
-	lua_settable(L, top);
+	lua_pushcfunction(L, func);
+	lua_setfield(L, top, name);
 
 	return true;
 }
diff --git a/src/script/lua_api/l_base.h b/src/script/lua_api/l_base.h
index cd382629d..af89afd93 100644
--- a/src/script/lua_api/l_base.h
+++ b/src/script/lua_api/l_base.h
@@ -68,9 +68,8 @@ public:
 
 	static bool registerFunction(lua_State *L,
 			const char* name,
-			lua_CFunction fct,
-			int top
-			);
+			lua_CFunction func,
+			int top);
 };
 
 #endif /* L_BASE_H_ */
diff --git a/src/script/lua_api/l_internal.h b/src/script/lua_api/l_internal.h
index b7627619e..e9b689931 100644
--- a/src/script/lua_api/l_internal.h
+++ b/src/script/lua_api/l_internal.h
@@ -31,8 +31,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 #define luamethod(class, name) {#name, class::l_##name}
 #define luamethod_aliased(class, name, alias) {#name, class::l_##name}, {#alias, class::l_##name}
-#define API_FCT(name) registerFunction(L, #name, l_##name,top)
-#define ASYNC_API_FCT(name) engine.registerFunction(#name, l_##name)
+#define API_FCT(name) registerFunction(L, #name, l_##name, top)
 
 #define MAP_LOCK_REQUIRED
 #define NO_MAP_LOCK_REQUIRED
diff --git a/src/script/lua_api/l_mainmenu.cpp b/src/script/lua_api/l_mainmenu.cpp
index 4d0be257c..dc8654960 100644
--- a/src/script/lua_api/l_mainmenu.cpp
+++ b/src/script/lua_api/l_mainmenu.cpp
@@ -38,6 +38,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include <IFileArchive.h>
 #include <IFileSystem.h>
 
+
 /******************************************************************************/
 std::string ModApiMainMenu::getTextData(lua_State *L, std::string name)
 {
@@ -1141,23 +1142,24 @@ void ModApiMainMenu::Initialize(lua_State *L, int top)
 }
 
 /******************************************************************************/
-void ModApiMainMenu::InitializeAsync(AsyncEngine& engine)
+void ModApiMainMenu::InitializeAsync(lua_State *L, int top)
 {
 
-	ASYNC_API_FCT(get_worlds);
-	ASYNC_API_FCT(get_games);
-	ASYNC_API_FCT(get_favorites);
-	ASYNC_API_FCT(get_mapgen_names);
-	ASYNC_API_FCT(get_modpath);
-	ASYNC_API_FCT(get_gamepath);
-	ASYNC_API_FCT(get_texturepath);
-	ASYNC_API_FCT(get_texturepath_share);
-	ASYNC_API_FCT(create_dir);
-	ASYNC_API_FCT(delete_dir);
-	ASYNC_API_FCT(copy_dir);
-	//ASYNC_API_FCT(extract_zip); //TODO remove dependency to GuiEngine
-	ASYNC_API_FCT(download_file);
-	ASYNC_API_FCT(get_modstore_details);
-	ASYNC_API_FCT(get_modstore_list);
-	//ASYNC_API_FCT(gettext); (gettext lib isn't threadsafe)
+	API_FCT(get_worlds);
+	API_FCT(get_games);
+	API_FCT(get_favorites);
+	API_FCT(get_mapgen_names);
+	API_FCT(get_modpath);
+	API_FCT(get_gamepath);
+	API_FCT(get_texturepath);
+	API_FCT(get_texturepath_share);
+	API_FCT(create_dir);
+	API_FCT(delete_dir);
+	API_FCT(copy_dir);
+	//API_FCT(extract_zip); //TODO remove dependency to GuiEngine
+	API_FCT(download_file);
+	API_FCT(get_modstore_details);
+	API_FCT(get_modstore_list);
+	//API_FCT(gettext); (gettext lib isn't threadsafe)
 }
+
diff --git a/src/script/lua_api/l_mainmenu.h b/src/script/lua_api/l_mainmenu.h
index e31ac0112..d4946bab1 100644
--- a/src/script/lua_api/l_mainmenu.h
+++ b/src/script/lua_api/l_mainmenu.h
@@ -142,6 +142,7 @@ private:
 	static int l_do_async_callback(lua_State *L);
 
 public:
+
 	/**
 	 * initialize this API module
 	 * @param L lua stack to initialize
@@ -149,7 +150,7 @@ public:
 	 */
 	static void Initialize(lua_State *L, int top);
 
-	static void InitializeAsync(AsyncEngine& engine);
+	static void InitializeAsync(lua_State *L, int top);
 
 };
 
diff --git a/src/script/lua_api/l_settings.cpp b/src/script/lua_api/l_settings.cpp
index 809f7d115..70807f3d2 100644
--- a/src/script/lua_api/l_settings.cpp
+++ b/src/script/lua_api/l_settings.cpp
@@ -23,6 +23,47 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "settings.h"
 #include "log.h"
 
+
+#define SET_SECURITY_CHECK(L, name) \
+	if (o->m_settings == g_settings && ScriptApiSecurity::isSecure(L) && \
+			name.compare(0, 7, "secure.") == 0) { \
+		throw LuaError("Attempt to set secure setting."); \
+	}
+
+LuaSettings::LuaSettings(Settings *settings, const std::string &filename) :
+	m_settings(settings),
+	m_filename(filename),
+	m_is_own_settings(false),
+	m_write_allowed(true)
+{
+}
+
+LuaSettings::LuaSettings(const std::string &filename, bool write_allowed) :
+	m_filename(filename),
+	m_is_own_settings(true),
+	m_write_allowed(write_allowed)
+{
+	m_settings = new Settings();
+	m_settings->readConfigFile(filename.c_str());
+}
+
+LuaSettings::~LuaSettings()
+{
+	if (m_is_own_settings)
+		delete m_settings;
+}
+
+
+void LuaSettings::create(lua_State *L, Settings *settings,
+		const std::string &filename)
+{
+	LuaSettings *o = new LuaSettings(settings, filename);
+	*(void **)(lua_newuserdata(L, sizeof(void *))) = o;
+	luaL_getmetatable(L, className);
+	lua_setmetatable(L, -2);
+}
+
+
 // garbage collector
 int LuaSettings::gc_object(lua_State* L)
 {
@@ -31,6 +72,7 @@ int LuaSettings::gc_object(lua_State* L)
 	return 0;
 }
 
+
 // get(self, key) -> value
 int LuaSettings::l_get(lua_State* L)
 {
@@ -74,12 +116,30 @@ int LuaSettings::l_set(lua_State* L)
 	std::string key = std::string(luaL_checkstring(L, 2));
 	const char* value = luaL_checkstring(L, 3);
 
+	SET_SECURITY_CHECK(L, key);
+
 	if (!o->m_settings->set(key, value))
 		throw LuaError("Invalid sequence found in setting parameters");
 
 	return 0;
 }
 
+// set_bool(self, key, value)
+int LuaSettings::l_set_bool(lua_State* L)
+{
+	NO_MAP_LOCK_REQUIRED;
+	LuaSettings* o = checkobject(L, 1);
+
+	std::string key = std::string(luaL_checkstring(L, 2));
+	bool value = lua_toboolean(L, 3);
+
+	SET_SECURITY_CHECK(L, key);
+
+	o->m_settings->setBool(key, value);
+
+	return 1;
+}
+
 // remove(self, key) -> success
 int LuaSettings::l_remove(lua_State* L)
 {
@@ -88,6 +148,8 @@ int LuaSettings::l_remove(lua_State* L)
 
 	std::string key = std::string(luaL_checkstring(L, 2));
 
+	SET_SECURITY_CHECK(L, key);
+
 	bool success = o->m_settings->remove(key);
 	lua_pushboolean(L, success);
 
@@ -147,19 +209,6 @@ int LuaSettings::l_to_table(lua_State* L)
 	return 1;
 }
 
-LuaSettings::LuaSettings(const char* filename, bool write_allowed)
-{
-	m_write_allowed = write_allowed;
-	m_filename = std::string(filename);
-
-	m_settings = new Settings();
-	m_settings->readConfigFile(m_filename.c_str());
-}
-
-LuaSettings::~LuaSettings()
-{
-	delete m_settings;
-}
 
 void LuaSettings::Register(lua_State* L)
 {
@@ -190,7 +239,7 @@ void LuaSettings::Register(lua_State* L)
 }
 
 // LuaSettings(filename)
-// Creates an LuaSettings and leaves it on top of stack
+// Creates a LuaSettings and leaves it on top of the stack
 int LuaSettings::create_object(lua_State* L)
 {
 	NO_MAP_LOCK_REQUIRED;
@@ -209,8 +258,9 @@ LuaSettings* LuaSettings::checkobject(lua_State* L, int narg)
 	NO_MAP_LOCK_REQUIRED;
 	luaL_checktype(L, narg, LUA_TUSERDATA);
 	void *ud = luaL_checkudata(L, narg, className);
-	if(!ud) luaL_typerror(L, narg, className);
-	return *(LuaSettings**)ud;  // unbox pointer
+	if (!ud)
+		luaL_typerror(L, narg, className);
+	return *(LuaSettings**) ud;  // unbox pointer
 }
 
 const char LuaSettings::className[] = "Settings";
@@ -218,6 +268,7 @@ const luaL_Reg LuaSettings::methods[] = {
 	luamethod(LuaSettings, get),
 	luamethod(LuaSettings, get_bool),
 	luamethod(LuaSettings, set),
+	luamethod(LuaSettings, set_bool),
 	luamethod(LuaSettings, remove),
 	luamethod(LuaSettings, get_names),
 	luamethod(LuaSettings, write),
diff --git a/src/script/lua_api/l_settings.h b/src/script/lua_api/l_settings.h
index b90f0a8f2..f3bc7410b 100644
--- a/src/script/lua_api/l_settings.h
+++ b/src/script/lua_api/l_settings.h
@@ -42,6 +42,9 @@ private:
 	// set(self, key, value)
 	static int l_set(lua_State *L);
 
+	// set_bool(self, key, value)
+	static int l_set_bool(lua_State* L);
+
 	// remove(self, key) -> success
 	static int l_remove(lua_State *L);
 
@@ -54,16 +57,20 @@ private:
 	// to_table(self) -> {[key1]=value1,...}
 	static int l_to_table(lua_State *L);
 
-	bool m_write_allowed;
 	Settings *m_settings;
 	std::string m_filename;
+	bool m_is_own_settings;
+	bool m_write_allowed;
 
 public:
-	LuaSettings(const char *filename, bool write_allowed);
+	LuaSettings(Settings *settings, const std::string &filename);
+	LuaSettings(const std::string &filename, bool write_allowed);
 	~LuaSettings();
 
+	static void create(lua_State *L, Settings *settings, const std::string &filename);
+
 	// LuaSettings(filename)
-	// Creates an LuaSettings and leaves it on top of stack
+	// Creates a LuaSettings and leaves it on top of the stack
 	static int create_object(lua_State *L);
 
 	static LuaSettings *checkobject(lua_State *L, int narg);
diff --git a/src/script/lua_api/l_util.cpp b/src/script/lua_api/l_util.cpp
index 809a2eb68..c4a988e07 100644
--- a/src/script/lua_api/l_util.cpp
+++ b/src/script/lua_api/l_util.cpp
@@ -19,6 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 #include "lua_api/l_util.h"
 #include "lua_api/l_internal.h"
+#include "lua_api/l_settings.h"
 #include "common/c_converter.h"
 #include "common/c_content.h"
 #include "cpp_api/s_async.h"
@@ -77,71 +78,6 @@ int ModApiUtil::l_get_us_time(lua_State *L)
 	return 1;
 }
 
-#define CHECK_SECURE_SETTING(L, name) \
-	if (ScriptApiSecurity::isSecure(L) && \
-			name.compare(0, 7, "secure.") == 0) { \
-		throw LuaError("Attempt to set secure setting."); \
-	}
-
-// setting_set(name, value)
-int ModApiUtil::l_setting_set(lua_State *L)
-{
-	NO_MAP_LOCK_REQUIRED;
-	std::string name = luaL_checkstring(L, 1);
-	std::string value = luaL_checkstring(L, 2);
-	CHECK_SECURE_SETTING(L, name);
-	g_settings->set(name, value);
-	return 0;
-}
-
-// setting_get(name)
-int ModApiUtil::l_setting_get(lua_State *L)
-{
-	NO_MAP_LOCK_REQUIRED;
-	const char *name = luaL_checkstring(L, 1);
-	try{
-		std::string value = g_settings->get(name);
-		lua_pushstring(L, value.c_str());
-	} catch(SettingNotFoundException &e){
-		lua_pushnil(L);
-	}
-	return 1;
-}
-
-// setting_setbool(name)
-int ModApiUtil::l_setting_setbool(lua_State *L)
-{
-	NO_MAP_LOCK_REQUIRED;
-	std::string name = luaL_checkstring(L, 1);
-	bool value = lua_toboolean(L, 2);
-	CHECK_SECURE_SETTING(L, name);
-	g_settings->setBool(name, value);
-	return 0;
-}
-
-// setting_getbool(name)
-int ModApiUtil::l_setting_getbool(lua_State *L)
-{
-	NO_MAP_LOCK_REQUIRED;
-	const char *name = luaL_checkstring(L, 1);
-	try{
-		bool value = g_settings->getBool(name);
-		lua_pushboolean(L, value);
-	} catch(SettingNotFoundException &e){
-		lua_pushnil(L);
-	}
-	return 1;
-}
-
-// setting_save()
-int ModApiUtil::l_setting_save(lua_State *L)
-{
-	NO_MAP_LOCK_REQUIRED;
-	if(g_settings_path != "")
-		g_settings->updateConfigFile(g_settings_path.c_str());
-	return 0;
-}
-
 // parse_json(str[, nullvalue])
 int ModApiUtil::l_parse_json(lua_State *L)
 {
@@ -493,12 +429,6 @@ void ModApiUtil::Initialize(lua_State *L, int top)
 
 	API_FCT(get_us_time);
 
-	API_FCT(setting_set);
-	API_FCT(setting_get);
-	API_FCT(setting_setbool);
-	API_FCT(setting_getbool);
-	API_FCT(setting_save);
-
 	API_FCT(parse_json);
 	API_FCT(write_json);
 
@@ -524,6 +454,9 @@ void ModApiUtil::Initialize(lua_State *L, int top)
 	API_FCT(decode_base64);
 
 	API_FCT(get_version);
+
+	LuaSettings::create(L, g_settings, g_settings_path);
+	lua_setfield(L, top, "settings");
 }
 
 void ModApiUtil::InitializeClient(lua_State *L, int top)
@@ -548,34 +481,31 @@ void ModApiUtil::InitializeClient(lua_State *L, int top)
 	API_FCT(get_version);
 }
 
-void ModApiUtil::InitializeAsync(AsyncEngine& engine)
+void ModApiUtil::InitializeAsync(lua_State *L, int top)
 {
-	ASYNC_API_FCT(log);
+	API_FCT(log);
 
-	ASYNC_API_FCT(get_us_time);
+	API_FCT(get_us_time);
 
-	//ASYNC_API_FCT(setting_set);
-	ASYNC_API_FCT(setting_get);
-	//ASYNC_API_FCT(setting_setbool);
-	ASYNC_API_FCT(setting_getbool);
-	//ASYNC_API_FCT(setting_save);
+	API_FCT(parse_json);
+	API_FCT(write_json);
 
-	ASYNC_API_FCT(parse_json);
-	ASYNC_API_FCT(write_json);
+	API_FCT(is_yes);
 
-	ASYNC_API_FCT(is_yes);
+	API_FCT(get_builtin_path);
 
-	ASYNC_API_FCT(get_builtin_path);
+	API_FCT(compress);
+	API_FCT(decompress);
 
-	ASYNC_API_FCT(compress);
-	ASYNC_API_FCT(decompress);
+	API_FCT(mkdir);
+	API_FCT(get_dir_list);
 
-	ASYNC_API_FCT(mkdir);
-	ASYNC_API_FCT(get_dir_list);
+	API_FCT(encode_base64);
+	API_FCT(decode_base64);
 
-	ASYNC_API_FCT(encode_base64);
-	ASYNC_API_FCT(decode_base64);
+	API_FCT(get_version);
 
-	ASYNC_API_FCT(get_version);
+	LuaSettings::create(L, g_settings, g_settings_path);
+	lua_setfield(L, top, "settings");
 }
 
diff --git a/src/script/lua_api/l_util.h b/src/script/lua_api/l_util.h
index 7325a841a..c36c054e6 100644
--- a/src/script/lua_api/l_util.h
+++ b/src/script/lua_api/l_util.h
@@ -45,21 +45,6 @@ private:
 	// get us precision time
 	static int l_get_us_time(lua_State *L);
 
-	// setting_set(name, value)
-	static int l_setting_set(lua_State *L);
-
-	// setting_get(name)
-	static int l_setting_get(lua_State *L);
-
-	// setting_setbool(name, value)
-	static int l_setting_setbool(lua_State *L);
-
-	// setting_getbool(name)
-	static int l_setting_getbool(lua_State *L);
-
-	// setting_save()
-	static int l_setting_save(lua_State *L);
-
 	// parse_json(str[, nullvalue])
 	static int l_parse_json(lua_State *L);
 
@@ -109,8 +94,9 @@ private:
 	static int l_get_version(lua_State *L);
 
 public:
-	static void Initialize(lua_State *L, int top);
 
+	static void Initialize(lua_State *L, int top);
+	static void InitializeAsync(lua_State *L, int top);
 	static void InitializeClient(lua_State *L, int top);
 
 	static void InitializeAsync(AsyncEngine &engine);
diff --git a/src/script/scripting_client.cpp b/src/script/scripting_client.cpp
index b5a5085be..24f70b8c1 100644
--- a/src/script/scripting_client.cpp
+++ b/src/script/scripting_client.cpp
@@ -62,17 +62,17 @@ ClientScripting::ClientScripting(Client *client):
 
 void ClientScripting::InitializeModApi(lua_State *L, int top)
 {
-	ModApiUtil::InitializeClient(L, top);
-	ModApiClient::Initialize(L, top);
-	ModApiStorage::Initialize(L, top);
-	ModApiEnvMod::InitializeClient(L, top);
-
 	LuaItemStack::Register(L);
 	StorageRef::Register(L);
 	LuaMinimap::Register(L);
 	NodeMetaRef::RegisterClient(L);
 	LuaLocalPlayer::Register(L);
 	LuaCamera::Register(L);
+
+	ModApiUtil::InitializeClient(L, top);
+	ModApiClient::Initialize(L, top);
+	ModApiStorage::Initialize(L, top);
+	ModApiEnvMod::InitializeClient(L, top);
 }
 
 void ClientScripting::on_client_ready(LocalPlayer *localplayer)
diff --git a/src/script/scripting_mainmenu.cpp b/src/script/scripting_mainmenu.cpp
index d79864a95..48957b472 100644
--- a/src/script/scripting_mainmenu.cpp
+++ b/src/script/scripting_mainmenu.cpp
@@ -59,23 +59,28 @@ MainMenuScripting::MainMenuScripting(GUIEngine* guiengine)
 /******************************************************************************/
 void MainMenuScripting::initializeModApi(lua_State *L, int top)
 {
+	registerLuaClasses(L, top);
+
 	// Initialize mod API modules
 	ModApiMainMenu::Initialize(L, top);
 	ModApiUtil::Initialize(L, top);
 	ModApiSound::Initialize(L, top);
 
-	// Register reference classes (userdata)
-	LuaSettings::Register(L);
-
-	// Register functions to async environment
-	ModApiMainMenu::InitializeAsync(asyncEngine);
-	ModApiUtil::InitializeAsync(asyncEngine);
+	asyncEngine.registerStateInitializer(registerLuaClasses);
+	asyncEngine.registerStateInitializer(ModApiMainMenu::InitializeAsync);
+	asyncEngine.registerStateInitializer(ModApiUtil::InitializeAsync);
 
 	// Initialize async environment
 	//TODO possibly make number of async threads configurable
 	asyncEngine.initialize(MAINMENU_NUM_ASYNC_THREADS);
 }
 
+/******************************************************************************/
+void MainMenuScripting::registerLuaClasses(lua_State *L, int top)
+{
+	LuaSettings::Register(L);
+}
+
 /******************************************************************************/
 void MainMenuScripting::step()
 {
diff --git a/src/script/scripting_mainmenu.h b/src/script/scripting_mainmenu.h
index 9aacd55d6..7b3a6eba8 100644
--- a/src/script/scripting_mainmenu.h
+++ b/src/script/scripting_mainmenu.h
@@ -44,6 +44,7 @@ public:
 			const std::string &serialized_params);
 private:
 	void initializeModApi(lua_State *L, int top);
+	static void registerLuaClasses(lua_State *L, int top);
 
 	AsyncEngine asyncEngine;
 	DISABLE_CLASS_COPY(MainMenuScripting);
diff --git a/src/script/scripting_server.cpp b/src/script/scripting_server.cpp
index ce56fcf19..cd01b0773 100644
--- a/src/script/scripting_server.cpp
+++ b/src/script/scripting_server.cpp
@@ -82,19 +82,6 @@ ServerScripting::ServerScripting(Server* server)
 
 void ServerScripting::InitializeModApi(lua_State *L, int top)
 {
-	// Initialize mod api modules
-	ModApiCraft::Initialize(L, top);
-	ModApiEnvMod::Initialize(L, top);
-	ModApiInventory::Initialize(L, top);
-	ModApiItemMod::Initialize(L, top);
-	ModApiMapgen::Initialize(L, top);
-	ModApiParticles::Initialize(L, top);
-	ModApiRollback::Initialize(L, top);
-	ModApiServer::Initialize(L, top);
-	ModApiUtil::Initialize(L, top);
-	ModApiHttp::Initialize(L, top);
-	ModApiStorage::Initialize(L, top);
-
 	// Register reference classes (userdata)
 	InvRef::Register(L);
 	ItemStackMetaRef::Register(L);
@@ -111,6 +98,19 @@ void ServerScripting::InitializeModApi(lua_State *L, int top)
 	ObjectRef::Register(L);
 	LuaSettings::Register(L);
 	StorageRef::Register(L);
+
+	// Initialize mod api modules
+	ModApiCraft::Initialize(L, top);
+	ModApiEnvMod::Initialize(L, top);
+	ModApiInventory::Initialize(L, top);
+	ModApiItemMod::Initialize(L, top);
+	ModApiMapgen::Initialize(L, top);
+	ModApiParticles::Initialize(L, top);
+	ModApiRollback::Initialize(L, top);
+	ModApiServer::Initialize(L, top);
+	ModApiUtil::Initialize(L, top);
+	ModApiHttp::Initialize(L, top);
+	ModApiStorage::Initialize(L, top);
 }
 
 void log_deprecated(const std::string &message)
-- 
cgit v1.2.3