From 4e1f50035e860a00636ca5d804c267119df99601 Mon Sep 17 00:00:00 2001
From: Kahrl <kahrl@gmx.net>
Date: Sun, 11 Aug 2013 04:09:45 +0200
Subject: [PATCH] Omnicleanup: header cleanup, add ModApiUtil shared between
 game and mainmenu

---
 builtin/mainmenu.lua                          |   3 +
 doc/lua_api.txt                               |   1 +
 doc/menu_lua_api.txt                          |  10 +-
 minetest.conf.example                         |   1 +
 src/CMakeLists.txt                            |   8 +-
 src/activeobject.h                            |   2 +-
 src/ban.cpp                                   |   1 +
 src/chat.cpp                                  |   2 +-
 src/chat.h                                    |   2 +-
 src/client.cpp                                |   3 +-
 src/client.h                                  |  55 +-
 src/clientserver.h                            |   4 -
 src/connection.h                              |   7 +-
 src/constants.h                               |   9 +-
 src/content_abm.cpp                           |   2 +-
 src/content_nodemeta.cpp                      |   3 +
 src/content_nodemeta.h                        |   7 +-
 src/content_sao.cpp                           |  22 +-
 src/craftdef.cpp                              |  18 +-
 src/debug.cpp                                 |  71 ++
 src/debug.h                                   | 147 +--
 src/defaultsettings.cpp                       |   1 +
 src/emerge.cpp                                |  57 +-
 src/emerge.h                                  |  63 +-
 src/environment.cpp                           |  36 +-
 src/environment.h                             |  31 +-
 src/exceptions.h                              |   9 +
 src/filecache.cpp                             |   1 +
 src/filesys.cpp                               |   3 +-
 src/game.cpp                                  |   5 +-
 src/game.h                                    |   1 -
 src/guiEngine.cpp                             | 244 ++---
 src/guiEngine.h                               |  78 +-
 src/guiFormSpecMenu.cpp                       |  87 +-
 src/guiFormSpecMenu.h                         |   7 -
 src/guiVolumeChange.cpp                       |   1 +
 src/hud.cpp                                   | 101 +-
 src/hud.h                                     |  32 +-
 src/inventory.h                               |   3 +-
 src/inventorymanager.cpp                      |   4 +-
 src/irrlichttypes_bloated.h                   |   3 -
 src/irrlichttypes_extrabloated.h              |   3 -
 src/itemgroup.h                               |   1 -
 src/light.h                                   |  10 -
 src/main.cpp                                  |  28 +-
 src/main.h                                    |   3 +
 src/map.cpp                                   |   3 +-
 src/map.h                                     |   7 +-
 src/mapblock.cpp                              |   3 +-
 src/mapblock.h                                |   9 +-
 src/mapgen.cpp                                |   1 +
 src/mapgen.h                                  |   2 +-
 src/mapgen_singlenode.cpp                     |   2 -
 src/mapnode.h                                 |   1 +
 src/mapsector.cpp                             |   5 +-
 src/mapsector.h                               |   5 +-
 src/mesh.cpp                                  |   2 +-
 src/mods.h                                    |   9 +-
 src/nameidmapping.cpp                         |   1 +
 src/nodemetadata.h                            |   2 +-
 src/nodetimer.cpp                             |   1 +
 src/nodetimer.h                               |   2 +-
 src/noise.cpp                                 |   1 +
 src/object_properties.cpp                     |   2 +-
 src/pathfinder.cpp                            |   3 +
 src/pathfinder.h                              |   7 +-
 src/player.cpp                                |   1 -
 src/player.h                                  |   9 +
 src/porting.h                                 |   1 +
 src/profiler.h                                |   3 +-
 src/rollback.cpp                              |   1 -
 src/script/CMakeLists.txt                     |  18 +-
 src/script/common/CMakeLists.txt              |   7 +-
 src/script/common/c_content.cpp               |   9 +-
 src/script/common/c_content.h                 |  13 +-
 src/script/common/c_internal.cpp              | 109 +-
 src/script/common/c_internal.h                |  56 +-
 src/script/common/c_types.h                   |  20 -
 src/script/cpp_api/CMakeLists.txt             |  10 +-
 src/script/cpp_api/s_base.cpp                 | 279 ++---
 src/script/cpp_api/s_base.h                   | 119 +--
 src/script/cpp_api/s_entity.cpp               |   5 +-
 src/script/cpp_api/s_env.cpp                  |  11 +-
 src/script/cpp_api/s_internal.h               |  63 ++
 src/script/cpp_api/s_inventory.cpp            |   1 +
 src/script/cpp_api/s_item.cpp                 |   3 +
 src/script/cpp_api/s_mainmenu.cpp             |  80 ++
 src/script/cpp_api/s_mainmenu.h               |  49 +
 src/script/cpp_api/s_node.cpp                 |   2 +
 src/script/cpp_api/s_nodemeta.cpp             |   6 +-
 src/script/cpp_api/s_player.cpp               |  15 +-
 src/script/cpp_api/s_player.h                 |   2 +
 src/script/cpp_api/s_server.cpp               | 151 +++
 src/script/cpp_api/s_server.h                 |  52 +
 src/script/cpp_api/scriptapi.cpp              | 291 ------
 src/script/lua_api/CMakeLists.txt             |  13 +-
 src/script/lua_api/l_base.cpp                 |  47 +-
 src/script/lua_api/l_base.h                   |  57 +-
 src/script/lua_api/l_craft.cpp                |  31 +-
 src/script/lua_api/l_craft.h                  |  14 +-
 src/script/lua_api/l_env.cpp                  | 276 ++---
 src/script/lua_api/l_env.h                    |  23 +-
 src/script/lua_api/l_internal.h               |  43 +
 src/script/lua_api/l_inventory.cpp            |  52 +-
 src/script/lua_api/l_inventory.h              |  30 +-
 src/script/lua_api/l_item.cpp                 |  66 +-
 src/script/lua_api/l_item.h                   |  30 +-
 .../lua_api/l_mainmenu.cpp}                   | 350 +++----
 .../lua_api/l_mainmenu.h}                     |  78 +-
 src/script/lua_api/l_mapgen.cpp               | 574 +++++++++++
 src/script/lua_api/l_mapgen.h                 |  62 ++
 src/script/lua_api/l_nodemeta.cpp             |  16 +-
 src/script/lua_api/l_nodemeta.h               |  15 +-
 src/script/lua_api/l_nodetimer.cpp            |   6 +-
 src/script/lua_api/l_nodetimer.h              |  11 +-
 src/script/lua_api/l_noise.cpp                |   7 +-
 src/script/lua_api/l_noise.h                  |  26 +-
 src/script/lua_api/l_object.cpp               |  25 +-
 src/script/lua_api/l_object.h                 |   9 +-
 src/script/lua_api/l_particles.cpp            |  24 +-
 src/script/lua_api/l_particles.h              |  12 +-
 src/script/lua_api/l_rollback.cpp             |  80 ++
 .../lua_api/l_rollback.h}                     |  28 +-
 src/script/lua_api/l_server.cpp               | 347 +++++++
 src/script/lua_api/{luaapi.h => l_server.h}   | 114 +--
 src/script/lua_api/l_util.cpp                 | 199 ++++
 src/script/lua_api/l_util.h                   |  76 ++
 src/script/lua_api/l_vmanip.cpp               |  39 +-
 src/script/lua_api/l_vmanip.h                 |  17 +-
 src/script/lua_api/luaapi.cpp                 | 955 ------------------
 src/script/scripting_game.cpp                 |  99 ++
 .../{cpp_api/scriptapi.h => scripting_game.h} |  61 +-
 src/script/scripting_mainmenu.cpp             |  65 ++
 src/script/scripting_mainmenu.h               |  45 +
 src/server.cpp                                | 206 ++--
 src/server.h                                  | 119 +--
 src/settings.h                                |   2 +-
 src/socket.cpp                                |  11 +-
 src/strfnd.h                                  |  40 -
 src/test.cpp                                  |   2 +
 src/threads.h                                 |   4 -
 src/tool.cpp                                  |   3 +-
 src/treegen.cpp                               |   1 +
 src/treegen.h                                 |   1 +
 src/util/container.h                          |   2 +
 src/util/numeric.h                            |   1 -
 src/util/pointedthing.cpp                     |   1 +
 src/util/serialize.cpp                        | 102 ++
 src/util/serialize.h                          |  99 +-
 src/util/string.cpp                           |  24 +
 src/util/string.h                             |  52 +-
 src/voxel.cpp                                 |   1 +
 src/voxel.h                                   |   3 +-
 153 files changed, 3720 insertions(+), 3620 deletions(-)
 create mode 100644 src/script/cpp_api/s_internal.h
 create mode 100644 src/script/cpp_api/s_mainmenu.cpp
 create mode 100644 src/script/cpp_api/s_mainmenu.h
 create mode 100644 src/script/cpp_api/s_server.cpp
 create mode 100644 src/script/cpp_api/s_server.h
 delete mode 100644 src/script/cpp_api/scriptapi.cpp
 create mode 100644 src/script/lua_api/l_internal.h
 rename src/{guiLuaApi.cpp => script/lua_api/l_mainmenu.cpp} (76%)
 rename src/{guiLuaApi.h => script/lua_api/l_mainmenu.h} (60%)
 create mode 100644 src/script/lua_api/l_mapgen.cpp
 create mode 100644 src/script/lua_api/l_mapgen.h
 create mode 100644 src/script/lua_api/l_rollback.cpp
 rename src/{clientserver.cpp => script/lua_api/l_rollback.h} (57%)
 create mode 100644 src/script/lua_api/l_server.cpp
 rename src/script/lua_api/{luaapi.h => l_server.h} (54%)
 create mode 100644 src/script/lua_api/l_util.cpp
 create mode 100644 src/script/lua_api/l_util.h
 delete mode 100644 src/script/lua_api/luaapi.cpp
 create mode 100644 src/script/scripting_game.cpp
 rename src/script/{cpp_api/scriptapi.h => scripting_game.h} (53%)
 create mode 100644 src/script/scripting_mainmenu.cpp
 create mode 100644 src/script/scripting_mainmenu.h

diff --git a/builtin/mainmenu.lua b/builtin/mainmenu.lua
index e0ab82ebb..926f3f2d9 100644
--- a/builtin/mainmenu.lua
+++ b/builtin/mainmenu.lua
@@ -1,3 +1,5 @@
+print = engine.debug
+math.randomseed(os.time())
 os.setlocale("C", "numeric")
 
 local scriptpath = engine.get_scriptdir()
@@ -9,6 +11,7 @@ mt_color_dark_green = "#003300"
 
 --for all other colors ask sfan5 to complete his worK!
 
+dofile(scriptpath .. DIR_DELIM .. "misc_helpers.lua")
 dofile(scriptpath .. DIR_DELIM .. "filterlist.lua")
 dofile(scriptpath .. DIR_DELIM .. "modmgr.lua")
 dofile(scriptpath .. DIR_DELIM .. "modstore.lua")
diff --git a/doc/lua_api.txt b/doc/lua_api.txt
index eefcc68a2..59e70581c 100644
--- a/doc/lua_api.txt
+++ b/doc/lua_api.txt
@@ -1167,6 +1167,7 @@ minetest.register_authentication_handler(handler)
 Setting-related:
 minetest.setting_set(name, value)
 minetest.setting_get(name) -> string or nil
+minetest.setting_setbool(name, value)
 minetest.setting_getbool(name) -> boolean value or nil
 minetest.setting_get_pos(name) -> position or nil
 minetest.setting_save() -> nil, save all settings to config file
diff --git a/doc/menu_lua_api.txt b/doc/menu_lua_api.txt
index 164d7876a..3812f11fd 100644
--- a/doc/menu_lua_api.txt
+++ b/doc/menu_lua_api.txt
@@ -127,11 +127,19 @@ engine.get_favorites(location) -> list of favorites
 }
 engine.delete_favorite(id, location) -> success
 
+Logging:
+engine.debug(line)
+^ Always printed to stderr and logfile (print() is redirected here)
+engine.log(line)
+engine.log(loglevel, line)
+^ loglevel one of "error", "action", "info", "verbose"
+
 Settings:
 engine.setting_set(name, value)
 engine.setting_get(name) -> string or nil
 engine.setting_setbool(name, value)
 engine.setting_getbool(name) -> bool or nil
+engine.setting_save() -> nil, save all settings to config file
 
 Worlds:
 engine.get_worlds() -> list of worlds
@@ -164,4 +172,4 @@ dump(obj, dumped={})
 string:split(separator)
 ^ eg. string:split("a,b", ",") == {"a","b"}
 string:trim()
-^ eg. string.trim("\n \t\tfoo bar\t ") == "foo bar"
\ No newline at end of file
+^ eg. string.trim("\n \t\tfoo bar\t ") == "foo bar"
diff --git a/minetest.conf.example b/minetest.conf.example
index b1732fa07..96f075e76 100644
--- a/minetest.conf.example
+++ b/minetest.conf.example
@@ -383,6 +383,7 @@
 # to IPv6 clients, depending on system configuration.
 #ipv6_server = false
 
+#main_menu_script =
 #main_menu_game_mgr = 0
 #main_menu_mod_mgr = 1
 #modstore_download_url = https://forum.minetest.net/media/
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index a1fcdd965..18cdaa725 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -267,12 +267,11 @@ set(common_SRCS
 	base64.cpp
 	ban.cpp
 	biome.cpp
-	clientserver.cpp
 	staticobject.cpp
 	serverlist.cpp
 	pathfinder.cpp
 	convert_json.cpp
-	${SCRIPT_SRCS}
+	${common_SCRIPT_SRCS}
 	${UTIL_SRCS}
 )
 
@@ -329,9 +328,9 @@ set(minetest_SRCS
 	game.cpp
 	main.cpp
 	guiEngine.cpp
-	guiLuaApi.cpp
 	guiFileSelectMenu.cpp
 	convert_json.cpp
+	${minetest_SCRIPT_SRCS}
 )
 
 if(USE_FREETYPE)
@@ -341,11 +340,14 @@ if(USE_FREETYPE)
 	)
 endif(USE_FREETYPE)
 
+list(SORT minetest_SRCS)
+
 # Server sources
 set(minetestserver_SRCS
 	${common_SRCS}
 	main.cpp
 )
+list(SORT minetestserver_SRCS)
 
 include_directories(
 	${PROJECT_BINARY_DIR}
diff --git a/src/activeobject.h b/src/activeobject.h
index f4d721a55..46880fc7f 100644
--- a/src/activeobject.h
+++ b/src/activeobject.h
@@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #ifndef ACTIVEOBJECT_HEADER
 #define ACTIVEOBJECT_HEADER
 
-#include "irrlichttypes_bloated.h"
+#include "irr_aabb3d.h"
 #include <string>
 
 #define ACTIVEOBJECT_TYPE_INVALID 0
diff --git a/src/ban.cpp b/src/ban.cpp
index 25d7f4ccb..5bb470a67 100644
--- a/src/ban.cpp
+++ b/src/ban.cpp
@@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include <sstream>
 #include <set>
 #include "strfnd.h"
+#include "util/string.h"
 #include "log.h"
 #include "filesys.h"
 
diff --git a/src/chat.cpp b/src/chat.cpp
index 3102e194a..0bd5c1670 100644
--- a/src/chat.cpp
+++ b/src/chat.cpp
@@ -19,7 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 #include "chat.h"
 #include "debug.h"
-#include <cassert>
+#include "strfnd.h"
 #include <cctype>
 #include <sstream>
 #include "util/string.h"
diff --git a/src/chat.h b/src/chat.h
index 19b48456e..e39d97ec2 100644
--- a/src/chat.h
+++ b/src/chat.h
@@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #ifndef CHAT_HEADER
 #define CHAT_HEADER
 
-#include "irrlichttypes_bloated.h"
+#include "irrlichttypes.h"
 #include <string>
 #include <vector>
 #include <list>
diff --git a/src/client.cpp b/src/client.cpp
index f9908ad2c..ecbb32dd2 100644
--- a/src/client.cpp
+++ b/src/client.cpp
@@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "jmutexautolock.h"
 #include "main.h"
 #include <sstream>
+#include "filesys.h"
 #include "porting.h"
 #include "mapsector.h"
 #include "mapblock_mesh.h"
@@ -1356,8 +1357,6 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
 			std::istringstream is(datastring, std::ios_base::binary);
 			//t3.stop();
 			
-			//m_env.printPlayers(infostream);
-
 			//TimeTaker t4("player get", m_device);
 			Player *player = m_env.getLocalPlayer();
 			assert(player != NULL);
diff --git a/src/client.h b/src/client.h
index fc26f3178..9146941e8 100644
--- a/src/client.h
+++ b/src/client.h
@@ -25,12 +25,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "irrlichttypes_extrabloated.h"
 #include "jmutex.h"
 #include <ostream>
+#include <map>
 #include <set>
 #include <vector>
 #include "clientobject.h"
 #include "gamedef.h"
 #include "inventorymanager.h"
-#include "filesys.h"
 #include "filecache.h"
 #include "localplayer.h"
 #include "server.h"
@@ -246,6 +246,57 @@ struct ClientEvent
 	};
 };
 
+/*
+	Packet counter
+*/
+
+class PacketCounter
+{
+public:
+	PacketCounter()
+	{
+	}
+
+	void add(u16 command)
+	{
+		std::map<u16, u16>::iterator n = m_packets.find(command);
+		if(n == m_packets.end())
+		{
+			m_packets[command] = 1;
+		}
+		else
+		{
+			n->second++;
+		}
+	}
+
+	void clear()
+	{
+		for(std::map<u16, u16>::iterator
+				i = m_packets.begin();
+				i != m_packets.end(); ++i)
+		{
+			i->second = 0;
+		}
+	}
+
+	void print(std::ostream &o)
+	{
+		for(std::map<u16, u16>::iterator
+				i = m_packets.begin();
+				i != m_packets.end(); ++i)
+		{
+			o<<"cmd "<<i->first
+					<<" count "<<i->second
+					<<std::endl;
+		}
+	}
+
+private:
+	// command, count
+	std::map<u16, u16> m_packets;
+};
+
 class Client : public con::PeerHandler, public InventoryManager, public IGameDef
 {
 public:
@@ -419,8 +470,6 @@ class Client : public con::PeerHandler, public InventoryManager, public IGameDef
 	void Receive();
 	
 	void sendPlayerPos();
-	// This sends the player's current name etc to the server
-	void sendPlayerInfo();
 	// Send the item number 'item' as player item to the server
 	void sendPlayerItem(u16 item);
 	
diff --git a/src/clientserver.h b/src/clientserver.h
index ebfe7f3c7..fb442cfc0 100644
--- a/src/clientserver.h
+++ b/src/clientserver.h
@@ -20,10 +20,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #ifndef CLIENTSERVER_HEADER
 #define CLIENTSERVER_HEADER
 
-#include "util/pointer.h"
-
-SharedBuffer<u8> makePacket_TOCLIENT_TIME_OF_DAY(u16 time, float time_speed);
-
 /*
 	changes by PROTOCOL_VERSION:
 
diff --git a/src/connection.h b/src/connection.h
index e68557ccd..a1d564849 100644
--- a/src/connection.h
+++ b/src/connection.h
@@ -191,15 +191,14 @@ TODO: Should we have a receiver_peer_id also?
 	[6] u8 channel
 sender_peer_id:
 	Unique to each peer.
-	value 0 is reserved for making new connections
-	value 1 is reserved for server
+	value 0 (PEER_ID_INEXISTENT) is reserved for making new connections
+	value 1 (PEER_ID_SERVER) is reserved for server
+	these constants are defined in constants.h
 channel:
 	The lower the number, the higher the priority is.
 	Only channels 0, 1 and 2 exist.
 */
 #define BASE_HEADER_SIZE 7
-#define PEER_ID_INEXISTENT 0
-#define PEER_ID_SERVER 1
 #define CHANNEL_COUNT 3
 /*
 Packet types:
diff --git a/src/constants.h b/src/constants.h
index e9d9f884a..8c478ac6a 100644
--- a/src/constants.h
+++ b/src/constants.h
@@ -32,6 +32,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
     Connection
 */
 
+#define PEER_ID_INEXISTENT 0
+#define PEER_ID_SERVER 1
+
 // Define for simulating the quirks of sending through internet.
 // Causes the socket class to deliberately drop random packets.
 // This disables unit testing of socket and connection.
@@ -83,12 +86,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 // Size of player's main inventory
 #define PLAYER_INVENTORY_SIZE (8*4)
 
-/*
-	This is good to be a bit different than 0 so that water level is not
-    between two MapBlocks
-*/
-#define WATER_LEVEL 1
-
 // Maximum hit points of a player
 #define PLAYER_MAX_HP 20
 
diff --git a/src/content_abm.cpp b/src/content_abm.cpp
index 57e4637d4..6e2d438fd 100644
--- a/src/content_abm.cpp
+++ b/src/content_abm.cpp
@@ -28,7 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "treegen.h" // For treegen::make_tree
 #include "main.h" // for g_settings
 #include "map.h"
-#include "cpp_api/scriptapi.h"
+#include "scripting_game.h"
 #include "log.h"
 
 #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
diff --git a/src/content_nodemeta.cpp b/src/content_nodemeta.cpp
index a9a8cc60c..f504924f9 100644
--- a/src/content_nodemeta.cpp
+++ b/src/content_nodemeta.cpp
@@ -18,8 +18,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 */
 
 #include "content_nodemeta.h"
+#include "nodemetadata.h"
+#include "nodetimer.h"
 #include "inventory.h"
 #include "log.h"
+#include "serialization.h"
 #include "util/serialize.h"
 #include "util/string.h"
 #include "constants.h" // MAP_BLOCKSIZE
diff --git a/src/content_nodemeta.h b/src/content_nodemeta.h
index 907649b5f..0b08bc6a1 100644
--- a/src/content_nodemeta.h
+++ b/src/content_nodemeta.h
@@ -20,8 +20,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #ifndef CONTENT_NODEMETA_HEADER
 #define CONTENT_NODEMETA_HEADER
 
-#include "nodemetadata.h"
-#include "nodetimer.h"
+#include <iostream>
+
+class NodeMetadataList;
+class NodeTimerList;
+class IGameDef;
 
 /*
 	Legacy nodemeta definitions
diff --git a/src/content_sao.cpp b/src/content_sao.cpp
index f3ccd6db0..347e88929 100644
--- a/src/content_sao.cpp
+++ b/src/content_sao.cpp
@@ -27,7 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "tool.h" // For ToolCapabilities
 #include "gamedef.h"
 #include "player.h"
-#include "cpp_api/scriptapi.h"
+#include "scripting_game.h"
 #include "genericobject.h"
 #include "util/serialize.h"
 #include "util/mathconstants.h"
@@ -399,7 +399,7 @@ LuaEntitySAO::LuaEntitySAO(ServerEnvironment *env, v3f pos,
 LuaEntitySAO::~LuaEntitySAO()
 {
 	if(m_registered){
-		ENV_TO_SA(m_env)->luaentity_Remove(m_id);
+		m_env->getScriptIface()->luaentity_Remove(m_id);
 	}
 }
 
@@ -408,15 +408,18 @@ void LuaEntitySAO::addedToEnvironment(u32 dtime_s)
 	ServerActiveObject::addedToEnvironment(dtime_s);
 	
 	// Create entity from name
-	m_registered = ENV_TO_SA(m_env)->luaentity_Add(m_id, m_init_name.c_str());
+	m_registered = m_env->getScriptIface()->
+		luaentity_Add(m_id, m_init_name.c_str());
 	
 	if(m_registered){
 		// Get properties
-		ENV_TO_SA(m_env)->luaentity_GetProperties(m_id, &m_prop);
+		m_env->getScriptIface()->
+			luaentity_GetProperties(m_id, &m_prop);
 		// Initialize HP from properties
 		m_hp = m_prop.hp_max;
 		// Activate entity, supplying serialized state
-		ENV_TO_SA(m_env)->luaentity_Activate(m_id, m_init_state.c_str(), dtime_s);
+		m_env->getScriptIface()->
+			luaentity_Activate(m_id, m_init_state.c_str(), dtime_s);
 	}
 }
 
@@ -530,7 +533,7 @@ void LuaEntitySAO::step(float dtime, bool send_recommended)
 	}
 
 	if(m_registered){
-		ENV_TO_SA(m_env)->luaentity_Step(m_id, dtime);
+		m_env->getScriptIface()->luaentity_Step(m_id, dtime);
 	}
 
 	if(send_recommended == false)
@@ -640,7 +643,8 @@ std::string LuaEntitySAO::getStaticData()
 	os<<serializeString(m_init_name);
 	// state
 	if(m_registered){
-		std::string state = ENV_TO_SA(m_env)->luaentity_GetStaticdata(m_id);
+		std::string state = m_env->getScriptIface()->
+			luaentity_GetStaticdata(m_id);
 		os<<serializeLongString(state);
 	} else {
 		os<<serializeLongString(m_init_state);
@@ -707,7 +711,7 @@ int LuaEntitySAO::punch(v3f dir,
 			m_removed = true;
 	}
 
-	ENV_TO_SA(m_env)->luaentity_Punch(m_id, puncher,
+	m_env->getScriptIface()->luaentity_Punch(m_id, puncher,
 			time_from_last_punch, toolcap, dir);
 
 	return result.wear;
@@ -720,7 +724,7 @@ void LuaEntitySAO::rightClick(ServerActiveObject *clicker)
 	// It's best that attachments cannot be clicked
 	if(isAttached())
 		return;
-	ENV_TO_SA(m_env)->luaentity_Rightclick(m_id, clicker);
+	m_env->getScriptIface()->luaentity_Rightclick(m_id, clicker);
 }
 
 void LuaEntitySAO::setPos(v3f pos)
diff --git a/src/craftdef.cpp b/src/craftdef.cpp
index c79408f99..5c7c3a465 100644
--- a/src/craftdef.cpp
+++ b/src/craftdef.cpp
@@ -28,6 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "inventory.h"
 #include "util/serialize.h"
 #include "strfnd.h"
+#include "exceptions.h"
 
 // Check if input matches recipe
 // Takes recipe groups into account
@@ -150,23 +151,6 @@ static bool craftGetBounds(const std::vector<std::string> &items, unsigned int w
 	return success;
 }
 
-#if 0
-// This became useless when group support was added to shapeless recipes
-// Convert a list of item names to a multiset
-static std::multiset<std::string> craftMakeMultiset(const std::vector<std::string> &names)
-{
-	std::multiset<std::string> set;
-	for(std::vector<std::string>::const_iterator
-			i = names.begin();
-			i != names.end(); i++)
-	{
-		if(*i != "")
-			set.insert(*i);
-	}
-	return set;
-}
-#endif
-
 // Removes 1 from each item stack
 static void craftDecrementInput(CraftInput &input, IGameDef *gamedef)
 {
diff --git a/src/debug.cpp b/src/debug.cpp
index 2e4992a78..6bdd1bce5 100644
--- a/src/debug.cpp
+++ b/src/debug.cpp
@@ -19,16 +19,34 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 
 #include "debug.h"
+#include "exceptions.h"
+#include "threads.h"
 #include <stdio.h>
 #include <stdlib.h>
 #include <cstring>
+#include <map>
+#include <jmutex.h>
+#include <jmutexautolock.h>
 
 /*
 	Debug output
 */
 
+#define DEBUGSTREAM_COUNT 2
+
 FILE *g_debugstreams[DEBUGSTREAM_COUNT] = {stderr, NULL};
 
+#define DEBUGPRINT(...)\
+{\
+	for(int i=0; i<DEBUGSTREAM_COUNT; i++)\
+	{\
+		if(g_debugstreams[i] != NULL){\
+			fprintf(g_debugstreams[i], __VA_ARGS__);\
+			fflush(g_debugstreams[i]);\
+		}\
+	}\
+}
+
 void debugstreams_init(bool disable_stderr, const char *filename)
 {
 	if(disable_stderr)
@@ -53,6 +71,47 @@ void debugstreams_deinit()
 		fclose(g_debugstreams[1]);
 }
 
+class Debugbuf : public std::streambuf
+{
+public:
+	Debugbuf(bool disable_stderr)
+	{
+		m_disable_stderr = disable_stderr;
+	}
+
+	int overflow(int c)
+	{
+		for(int i=0; i<DEBUGSTREAM_COUNT; i++)
+		{
+			if(g_debugstreams[i] == stderr && m_disable_stderr)
+				continue;
+			if(g_debugstreams[i] != NULL)
+				(void)fwrite(&c, 1, 1, g_debugstreams[i]);
+			//TODO: Is this slow?
+			fflush(g_debugstreams[i]);
+		}
+		
+		return c;
+	}
+	std::streamsize xsputn(const char *s, std::streamsize n)
+	{
+		for(int i=0; i<DEBUGSTREAM_COUNT; i++)
+		{
+			if(g_debugstreams[i] == stderr && m_disable_stderr)
+				continue;
+			if(g_debugstreams[i] != NULL)
+				(void)fwrite(s, 1, n, g_debugstreams[i]);
+			//TODO: Is this slow?
+			fflush(g_debugstreams[i]);
+		}
+
+		return n;
+	}
+	
+private:
+	bool m_disable_stderr;
+};
+
 Debugbuf debugbuf(false);
 std::ostream dstream(&debugbuf);
 Debugbuf debugbuf_no_stderr(true);
@@ -83,6 +142,18 @@ void assert_fail(const char *assertion, const char *file,
 	DebugStack
 */
 
+struct DebugStack
+{
+	DebugStack(threadid_t id);
+	void print(FILE *file, bool everything);
+	void print(std::ostream &os, bool everything);
+	
+	threadid_t threadid;
+	char stack[DEBUG_STACK_SIZE][DEBUG_STACK_TEXT_SIZE];
+	int stack_i; // Points to the lowest empty position
+	int stack_max_i; // Highest i that was seen
+};
+
 DebugStack::DebugStack(threadid_t id)
 {
 	threadid = id;
diff --git a/src/debug.h b/src/debug.h
index 31855cce7..1532be824 100644
--- a/src/debug.h
+++ b/src/debug.h
@@ -20,18 +20,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #ifndef DEBUG_HEADER
 #define DEBUG_HEADER
 
-#include <stdio.h>
-#include <jmutex.h>
-#include <jmutexautolock.h>
 #include <iostream>
-#include "irrlichttypes.h"
-#include <irrMap.h>
-#include "threads.h"
+#include <exception>
 #include "gettime.h"
-#include "exceptions.h"
-#include <map>
 
-#ifdef _WIN32
+#if (defined(WIN32) || defined(_WIN32_WCE))
 	#define WIN32_LEAN_AND_MEAN
 	#ifndef _WIN32_WINNT
 		#define _WIN32_WINNT 0x0501
@@ -40,7 +33,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 	#ifdef _MSC_VER
 		#include <eh.h>
 	#endif
+	#define __NORETURN __declspec(noreturn)
+	#define __FUNCTION_NAME __FUNCTION__
 #else
+	#define __NORETURN __attribute__ ((__noreturn__))
+	#define __FUNCTION_NAME __PRETTY_FUNCTION__
 #endif
 
 // Whether to catch all std::exceptions.
@@ -58,65 +55,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 #define DTIME (getTimestamp()+": ")
 
-#define DEBUGSTREAM_COUNT 2
-
-extern FILE *g_debugstreams[DEBUGSTREAM_COUNT];
-
 extern void debugstreams_init(bool disable_stderr, const char *filename);
 extern void debugstreams_deinit();
 
-#define DEBUGPRINT(...)\
-{\
-	for(int i=0; i<DEBUGSTREAM_COUNT; i++)\
-	{\
-		if(g_debugstreams[i] != NULL){\
-			fprintf(g_debugstreams[i], __VA_ARGS__);\
-			fflush(g_debugstreams[i]);\
-		}\
-	}\
-}
-
-class Debugbuf : public std::streambuf
-{
-public:
-	Debugbuf(bool disable_stderr)
-	{
-		m_disable_stderr = disable_stderr;
-	}
-
-	int overflow(int c)
-	{
-		for(int i=0; i<DEBUGSTREAM_COUNT; i++)
-		{
-			if(g_debugstreams[i] == stderr && m_disable_stderr)
-				continue;
-			if(g_debugstreams[i] != NULL)
-				(void)fwrite(&c, 1, 1, g_debugstreams[i]);
-			//TODO: Is this slow?
-			fflush(g_debugstreams[i]);
-		}
-		
-		return c;
-	}
-	std::streamsize xsputn(const char *s, std::streamsize n)
-	{
-		for(int i=0; i<DEBUGSTREAM_COUNT; i++)
-		{
-			if(g_debugstreams[i] == stderr && m_disable_stderr)
-				continue;
-			if(g_debugstreams[i] != NULL)
-				(void)fwrite(s, 1, n, g_debugstreams[i]);
-			//TODO: Is this slow?
-			fflush(g_debugstreams[i]);
-		}
-
-		return n;
-	}
-	
-private:
-	bool m_disable_stderr;
-};
-
 // This is used to redirect output to /dev/null
 class Nullstream : public std::ostream {
 public:
@@ -127,7 +68,6 @@ class Nullstream : public std::ostream {
 private:
 };
 
-extern Debugbuf debugbuf;
 extern std::ostream dstream;
 extern std::ostream dstream_no_stderr;
 extern Nullstream dummyout;
@@ -154,25 +94,11 @@ __NORETURN extern void assert_fail(
 #define DEBUG_STACK_SIZE 50
 #define DEBUG_STACK_TEXT_SIZE 300
 
-struct DebugStack
-{
-	DebugStack(threadid_t id);
-	void print(FILE *file, bool everything);
-	void print(std::ostream &os, bool everything);
-	
-	threadid_t threadid;
-	char stack[DEBUG_STACK_SIZE][DEBUG_STACK_TEXT_SIZE];
-	int stack_i; // Points to the lowest empty position
-	int stack_max_i; // Highest i that was seen
-};
-
-extern std::map<threadid_t, DebugStack*> g_debug_stacks;
-extern JMutex g_debug_stacks_mutex;
-
 extern void debug_stacks_init();
 extern void debug_stacks_print_to(std::ostream &os);
 extern void debug_stacks_print();
 
+struct DebugStack;
 class DebugStacker
 {
 public:
@@ -193,57 +119,6 @@ class DebugStacker
 			DEBUG_STACK_TEXT_SIZE, __VA_ARGS__);\
 	DebugStacker __debug_stacker(__buf);
 
-/*
-	Packet counter
-*/
-
-class PacketCounter
-{
-public:
-	PacketCounter()
-	{
-	}
-
-	void add(u16 command)
-	{
-		std::map<u16, u16>::iterator n = m_packets.find(command);
-		if(n == m_packets.end())
-		{
-			m_packets[command] = 1;
-		}
-		else
-		{
-			n->second++;
-		}
-	}
-
-	void clear()
-	{
-		for(std::map<u16, u16>::iterator
-				i = m_packets.begin();
-				i != m_packets.end(); ++i)
-		{
-			i->second = 0;
-		}
-	}
-
-	void print(std::ostream &o)
-	{
-		for(std::map<u16, u16>::iterator
-				i = m_packets.begin();
-				i != m_packets.end(); ++i)
-		{
-			o<<"cmd "<<i->first
-					<<" count "<<i->second
-					<<std::endl;
-		}
-	}
-
-private:
-	// command, count
-	std::map<u16, u16> m_packets;
-};
-
 /*
 	These should be put into every thread
 */
@@ -259,14 +134,6 @@ class PacketCounter
 	#ifdef _WIN32 // Windows
 		#ifdef _MSC_VER // MSVC
 void se_trans_func(unsigned int, EXCEPTION_POINTERS*);
-
-class FatalSystemException : public BaseException
-{
-public:
-	FatalSystemException(const char *s):
-		BaseException(s)
-	{}
-};
 			#define BEGIN_DEBUG_EXCEPTION_HANDLER \
 				BEGIN_PORTABLE_DEBUG_EXCEPTION_HANDLER\
 				_set_se_translator(se_trans_func);
diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp
index 38d278ef0..a0adf159a 100644
--- a/src/defaultsettings.cpp
+++ b/src/defaultsettings.cpp
@@ -273,6 +273,7 @@ void set_default_settings(Settings *settings)
 	settings->setDefault("enable_ipv6", "true");
 	settings->setDefault("ipv6_server", "false");
 
+	settings->setDefault("main_menu_script","");
 	settings->setDefault("main_menu_mod_mgr","1");
 	settings->setDefault("old_style_mod_selection","true");
 	settings->setDefault("main_menu_game_mgr","0");
diff --git a/src/emerge.cpp b/src/emerge.cpp
index f97763718..a81ff7d92 100644
--- a/src/emerge.cpp
+++ b/src/emerge.cpp
@@ -19,12 +19,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 */
 
 
+#include "emerge.h"
 #include "server.h"
 #include <iostream>
 #include <queue>
-#include "clientserver.h"
 #include "map.h"
-#include "jmutexautolock.h"
+#include "environment.h"
+#include "util/container.h"
+#include "util/thread.h"
 #include "main.h"
 #include "constants.h"
 #include "voxel.h"
@@ -32,12 +34,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "mapblock.h"
 #include "serverobject.h"
 #include "settings.h"
-#include "cpp_api/scriptapi.h"
+#include "scripting_game.h"
 #include "profiler.h"
 #include "log.h"
 #include "nodedef.h"
 #include "biome.h"
-#include "emerge.h"
 #include "mapgen_v6.h"
 #include "mapgen_v7.h"
 #include "mapgen_indev.h"
@@ -45,6 +46,46 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "mapgen_math.h"
 
 
+class EmergeThread : public SimpleThread
+{
+public:
+	Server *m_server;
+	ServerMap *map;
+	EmergeManager *emerge;
+	Mapgen *mapgen;
+	bool enable_mapgen_debug_info;
+	int id;
+	
+	Event qevent;
+	std::queue<v3s16> blockqueue;
+	
+	EmergeThread(Server *server, int ethreadid):
+		SimpleThread(),
+		m_server(server),
+		map(NULL),
+		emerge(NULL),
+		mapgen(NULL),
+		id(ethreadid)
+	{
+	}
+
+	void *Thread();
+
+	void trigger()
+	{
+		setRun(true);
+		if(IsRunning() == false)
+		{
+			Start();
+		}
+	}
+
+	bool popBlockEmerge(v3s16 *pos, u8 *flags);
+	bool getBlockOrStartGen(v3s16 p, MapBlock **b,
+			BlockMakeData *data, bool allow_generate);
+};
+
+
 /////////////////////////////// Emerge Manager ////////////////////////////////
 
 EmergeManager::EmergeManager(IGameDef *gamedef) {
@@ -183,6 +224,11 @@ Mapgen *EmergeManager::getCurrentMapgen() {
 }
 
 
+void EmergeManager::triggerAllThreads() {
+	for (unsigned int i = 0; i != emergethread.size(); i++)
+		emergethread[i]->trigger();
+}
+
 bool EmergeManager::enqueueBlockEmerge(u16 peer_id, v3s16 p, bool allow_generate) {
 	std::map<v3s16, BlockEmergeData *>::const_iterator iter;
 	BlockEmergeData *bedata;
@@ -466,7 +512,8 @@ void *EmergeThread::Thread() {
 						ign(&m_server->m_ignore_map_edit_events_area,
 						VoxelArea(minp, maxp));
 					{  // takes about 90ms with -O1 on an e3-1230v2
-						SERVER_TO_SA(m_server)->environment_OnGenerated(
+						m_server->getScriptIface()->
+								environment_OnGenerated(
 								minp, maxp, emerge->getBlockSeed(minp));
 					}
 
diff --git a/src/emerge.h b/src/emerge.h
index ee95c348f..458a366fc 100644
--- a/src/emerge.h
+++ b/src/emerge.h
@@ -21,8 +21,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #define EMERGE_HEADER
 
 #include <map>
-#include <queue>
-#include "util/thread.h"
+#include "irr_v3d.h"
+#include "util/container.h"
+#include "map.h" // for ManualMapVoxelManipulator
 
 #define MGPARAMS_SET_MGNAME      1
 #define MGPARAMS_SET_SEED        2
@@ -35,15 +36,16 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 	{ if (enable_mapgen_debug_info) \
 	infostream << "EmergeThread: " x << std::endl; }
 
+class EmergeThread;
 class Mapgen;
 struct MapgenParams;
 struct MapgenFactory;
 class Biome;
 class BiomeDefManager;
-class EmergeThread;
-class ManualMapVoxelManipulator;
-
-#include "server.h"
+class Decoration;
+class Ore;
+class INodeDefManager;
+class Settings;
 
 struct BlockMakeData {
 	ManualMapVoxelManipulator *vmanip;
@@ -68,7 +70,14 @@ struct BlockEmergeData {
 	u8 flags;
 };
 
-class EmergeManager {
+class IBackgroundBlockEmerger
+{
+public:
+	virtual bool enqueueBlockEmerge(u16 peer_id, v3s16 p,
+			bool allow_generate) = 0;
+};
+
+class EmergeManager : public IBackgroundBlockEmerger {
 public:
 	INodeDefManager *ndef;
 
@@ -106,6 +115,7 @@ class EmergeManager {
 	Mapgen *createMapgen(std::string mgname, int mgid,
 						MapgenParams *mgparams);
 	MapgenParams *createMapgenParams(std::string mgname);
+	void triggerAllThreads();
 	bool enqueueBlockEmerge(u16 peer_id, v3s16 p, bool allow_generate);
 	
 	void registerMapgen(std::string name, MapgenFactory *mgfactory);
@@ -119,43 +129,4 @@ class EmergeManager {
 	u32 getBlockSeed(v3s16 p);
 };
 
-class EmergeThread : public SimpleThread
-{
-public:
-	Server *m_server;
-	ServerMap *map;
-	EmergeManager *emerge;
-	Mapgen *mapgen;
-	bool enable_mapgen_debug_info;
-	int id;
-	
-	Event qevent;
-	std::queue<v3s16> blockqueue;
-	
-	EmergeThread(Server *server, int ethreadid):
-		SimpleThread(),
-		m_server(server),
-		map(NULL),
-		emerge(NULL),
-		mapgen(NULL),
-		id(ethreadid)
-	{
-	}
-
-	void *Thread();
-
-	void trigger()
-	{
-		setRun(true);
-		if(IsRunning() == false)
-		{
-			Start();
-		}
-	}
-
-	bool popBlockEmerge(v3s16 *pos, u8 *flags);
-	bool getBlockOrStartGen(v3s16 p, MapBlock **b, 
-							BlockMakeData *data, bool allow_generate);
-};
-
 #endif
diff --git a/src/environment.cpp b/src/environment.cpp
index eacc2a008..86c98f2c2 100644
--- a/src/environment.cpp
+++ b/src/environment.cpp
@@ -17,9 +17,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
 
-#include <set>
-#include <list>
-#include <map>
 #include "environment.h"
 #include "filesys.h"
 #include "porting.h"
@@ -31,7 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "settings.h"
 #include "log.h"
 #include "profiler.h"
-#include "cpp_api/scriptapi.h"
+#include "scripting_game.h"
 #include "nodedef.h"
 #include "nodemetadata.h"
 #include "main.h" // For g_settings, g_profiler
@@ -43,6 +40,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #endif
 #include "daynightratio.h"
 #include "map.h"
+#include "emerge.h"
 #include "util/serialize.h"
 
 #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
@@ -190,17 +188,6 @@ std::list<Player*> Environment::getPlayers(bool ignore_disconnected)
 	return newlist;
 }
 
-void Environment::printPlayers(std::ostream &o)
-{
-	o<<"Players in environment:"<<std::endl;
-	for(std::list<Player*>::iterator i = m_players.begin();
-			i != m_players.end(); i++)
-	{
-		Player *player = *i;
-		o<<"Player peer_id="<<player->peer_id<<std::endl;
-	}
-}
-
 u32 Environment::getDayNightRatio()
 {
 	bool smooth = g_settings->getBool("enable_shaders");
@@ -320,7 +307,8 @@ void ActiveBlockList::update(std::list<v3s16> &active_positions,
 	ServerEnvironment
 */
 
-ServerEnvironment::ServerEnvironment(ServerMap *map, ScriptApi *scriptIface,
+ServerEnvironment::ServerEnvironment(ServerMap *map,
+		GameScripting *scriptIface,
 		IGameDef *gamedef, IBackgroundBlockEmerger *emerger):
 	m_map(map),
 	m_script(scriptIface),
@@ -1149,7 +1137,8 @@ void ServerEnvironment::step(float dtime)
 			MapBlock *block = m_map->getBlockNoCreateNoEx(p);
 			if(block==NULL){
 				// Block needs to be fetched first
-				m_emerger->queueBlockEmerge(p, false);
+				m_emerger->enqueueBlockEmerge(
+						PEER_ID_INEXISTENT, p, false);
 				m_active_blocks.m_list.erase(p);
 				continue;
 			}
@@ -1505,7 +1494,9 @@ ActiveObjectMessage ServerEnvironment::getActiveObjectMessage()
 	if(m_active_object_messages.empty())
 		return ActiveObjectMessage(0);
 	
-	return m_active_object_messages.pop_front();
+	ActiveObjectMessage message = m_active_object_messages.front();
+	m_active_object_messages.pop_front();
+	return message;
 }
 
 /*
@@ -2574,13 +2565,14 @@ void ClientEnvironment::getActiveObjects(v3f origin, f32 max_d,
 
 ClientEnvEvent ClientEnvironment::getClientEvent()
 {
+	ClientEnvEvent event;
 	if(m_client_event_queue.empty())
-	{
-		ClientEnvEvent event;
 		event.type = CEE_NONE;
-		return event;
+	else {
+		event = m_client_event_queue.front();
+		m_client_event_queue.pop_front();
 	}
-	return m_client_event_queue.pop_front();
+	return event;
 }
 
 #endif // #ifndef SERVER
diff --git a/src/environment.h b/src/environment.h
index b59ce83c1..597ad5ff0 100644
--- a/src/environment.h
+++ b/src/environment.h
@@ -32,11 +32,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 #include <set>
 #include <list>
-#include "irrlichttypes_extrabloated.h"
-#include "player.h"
-#include <ostream>
+#include <map>
+#include "irr_v3d.h"
 #include "activeobject.h"
-#include "util/container.h"
 #include "util/numeric.h"
 #include "mapnode.h"
 #include "mapblock.h"
@@ -44,13 +42,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 class ServerEnvironment;
 class ActiveBlockModifier;
 class ServerActiveObject;
-typedef struct lua_State lua_State;
 class ITextureSource;
 class IGameDef;
+class IBackgroundBlockEmerger;
 class Map;
 class ServerMap;
 class ClientMap;
-class ScriptApi;
+class GameScripting;
+class Player;
 
 class Environment
 {
@@ -77,7 +76,6 @@ class Environment
 	Player * getNearestConnectedPlayer(v3f pos);
 	std::list<Player*> getPlayers();
 	std::list<Player*> getPlayers(bool ignore_disconnected);
-	void printPlayers(std::ostream &o);
 	
 	u32 getDayNightRatio();
 	
@@ -176,12 +174,6 @@ class ActiveBlockList
 private:
 };
 
-class IBackgroundBlockEmerger
-{
-public:
-	virtual void queueBlockEmerge(v3s16 blockpos, bool allow_generate)=0;
-};
-
 /*
 	The server-side environment.
 
@@ -191,7 +183,8 @@ class IBackgroundBlockEmerger
 class ServerEnvironment : public Environment
 {
 public:
-	ServerEnvironment(ServerMap *map, ScriptApi *iface, IGameDef *gamedef,
+	ServerEnvironment(ServerMap *map, GameScripting *scriptIface,
+			IGameDef *gamedef,
 			IBackgroundBlockEmerger *emerger);
 	~ServerEnvironment();
 
@@ -200,7 +193,7 @@ class ServerEnvironment : public Environment
 	ServerMap & getServerMap();
 
 	//TODO find way to remove this fct!
-	ScriptApi* getScriptIface()
+	GameScripting* getScriptIface()
 		{ return m_script; }
 
 	IGameDef *getGameDef()
@@ -354,15 +347,15 @@ class ServerEnvironment : public Environment
 	// The map
 	ServerMap *m_map;
 	// Lua state
-	ScriptApi* m_script;
+	GameScripting* m_script;
 	// Game definition
 	IGameDef *m_gamedef;
-	// Background block emerger (the server, in practice)
+	// Background block emerger (the EmergeManager, in practice)
 	IBackgroundBlockEmerger *m_emerger;
 	// Active object list
 	std::map<u16, ServerActiveObject*> m_active_objects;
 	// Outgoing network message buffer for active objects
-	Queue<ActiveObjectMessage> m_active_object_messages;
+	std::list<ActiveObjectMessage> m_active_object_messages;
 	// Some timers
 	float m_random_spawn_timer; // used for experimental code
 	float m_send_recommended_timer;
@@ -503,7 +496,7 @@ class ClientEnvironment : public Environment
 	IrrlichtDevice *m_irr;
 	std::map<u16, ClientActiveObject*> m_active_objects;
 	std::list<ClientSimpleObject*> m_simple_objects;
-	Queue<ClientEnvEvent> m_client_event_queue;
+	std::list<ClientEnvEvent> m_client_event_queue;
 	IntervalLimiter m_active_object_light_update_interval;
 	IntervalLimiter m_lava_hurt_interval;
 	IntervalLimiter m_drowning_interval;
diff --git a/src/exceptions.h b/src/exceptions.h
index 458fb50b1..085b42417 100644
--- a/src/exceptions.h
+++ b/src/exceptions.h
@@ -140,6 +140,15 @@ class ItemNotFoundException : public BaseException
 	{}
 };
 
+// Only used on Windows (SEH)
+class FatalSystemException : public BaseException
+{
+public:
+	FatalSystemException(const char *s):
+		BaseException(s)
+	{}
+};
+
 /*
 	Some "old-style" interrupts:
 */
diff --git a/src/filecache.cpp b/src/filecache.cpp
index 23df1d7d0..c4de6cf82 100644
--- a/src/filecache.cpp
+++ b/src/filecache.cpp
@@ -29,6 +29,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include <iostream>
 #include <fstream>
 #include <sstream>
+#include <stdlib.h>
 
 bool FileCache::loadByPath(const std::string &path, std::ostream &os)
 {
diff --git a/src/filesys.cpp b/src/filesys.cpp
index a1795c8ea..eda36c833 100644
--- a/src/filesys.cpp
+++ b/src/filesys.cpp
@@ -18,12 +18,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 */
 
 #include "filesys.h"
-#include "strfnd.h"
+#include "util/string.h"
 #include <iostream>
 #include <stdio.h>
 #include <string.h>
 #include <errno.h>
-#include <sstream>
 #include <fstream>
 #include "log.h"
 
diff --git a/src/game.cpp b/src/game.cpp
index 7954c8d80..650b5e2f8 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -915,7 +915,6 @@ void the_game(
 	std::string address, // If "", local server is used
 	u16 port,
 	std::wstring &error_message,
-	std::string configpath,
 	ChatBackend &chat_backend,
 	const SubgameSpec &gamespec, // Used for local game,
 	bool simple_singleplayer_mode
@@ -1001,7 +1000,7 @@ void the_game(
 		draw_load_screen(text, device, font,0,25);
 		delete[] text;
 		infostream<<"Creating server"<<std::endl;
-		server = new Server(map_dir, configpath, gamespec,
+		server = new Server(map_dir, gamespec,
 				simple_singleplayer_mode);
 		server->start(port);
 	}
@@ -3340,7 +3339,7 @@ void the_game(
 		*/
 		{
 			TimeTaker timer("endScene");
-			endSceneX(driver);
+			driver->endScene();
 			endscenetime = timer.stop(true);
 		}
 
diff --git a/src/game.h b/src/game.h
index a2c1fc09c..1c831c530 100644
--- a/src/game.h
+++ b/src/game.h
@@ -137,7 +137,6 @@ void the_game(
 	std::string address, // If "", local server is used
 	u16 port,
 	std::wstring &error_message,
-	std::string configpath,
 	ChatBackend &chat_backend,
 	const SubgameSpec &gamespec, // Used for local game
 	bool simple_singleplayer_mode
diff --git a/src/guiEngine.cpp b/src/guiEngine.cpp
index b62c1a547..37f570acf 100644
--- a/src/guiEngine.cpp
+++ b/src/guiEngine.cpp
@@ -17,14 +17,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
 
-extern "C" {
-#include "lua.h"
-#include "lauxlib.h"
-#include "lualib.h"
-}
-
-#include "irrlicht.h"
+#include "guiEngine.h"
 
+#include "scripting_mainmenu.h"
+#include "config.h"
 #include "porting.h"
 #include "filesys.h"
 #include "main.h"
@@ -33,30 +29,13 @@ extern "C" {
 #include "sound.h"
 #include "sound_openal.h"
 
-#include "guiEngine.h"
+#include <IGUIStaticText.h>
+#include <ICameraSceneNode.h>
 
 #if USE_CURL
 #include <curl/curl.h>
 #endif
 
-/******************************************************************************/
-int menuscript_ErrorHandler(lua_State *L) {
-	lua_getfield(L, LUA_GLOBALSINDEX, "debug");
-	if (!lua_istable(L, -1)) {
-	lua_pop(L, 1);
-	return 1;
-	}
-	lua_getfield(L, -1, "traceback");
-	if (!lua_isfunction(L, -1)) {
-	lua_pop(L, 2);
-	return 1;
-	}
-	lua_pushvalue(L, 1);
-	lua_pushinteger(L, 2);
-	lua_call(L, 2, 1);
-	return 1;
-}
-
 /******************************************************************************/
 TextDestGuiEngine::TextDestGuiEngine(GUIEngine* engine)
 {
@@ -66,13 +45,33 @@ TextDestGuiEngine::TextDestGuiEngine(GUIEngine* engine)
 /******************************************************************************/
 void TextDestGuiEngine::gotText(std::map<std::string, std::string> fields)
 {
-	m_engine->handleButtons(fields);
+	m_engine->getScriptIface()->handleMainMenuButtons(fields);
 }
 
 /******************************************************************************/
 void TextDestGuiEngine::gotText(std::wstring text)
 {
-	m_engine->handleEvent(wide_to_narrow(text));
+	m_engine->getScriptIface()->handleMainMenuEvent(wide_to_narrow(text));
+}
+
+/******************************************************************************/
+void MenuMusicFetcher::fetchSounds(const std::string &name,
+			std::set<std::string> &dst_paths,
+			std::set<std::string> &dst_datas)
+{
+	if(m_fetched.count(name))
+		return;
+	m_fetched.insert(name);
+	std::string base;
+	base = porting::path_share + DIR_DELIM + "sounds";
+	dst_paths.insert(base + DIR_DELIM + name + ".ogg");
+	int i;
+	for(i=0; i<10; i++)
+		dst_paths.insert(base + DIR_DELIM + name + "."+itos(i)+".ogg");
+	base = porting::path_user + DIR_DELIM + "sounds";
+	dst_paths.insert(base + DIR_DELIM + name + ".ogg");
+	for(i=0; i<10; i++)
+		dst_paths.insert(base + DIR_DELIM + name + "."+itos(i)+".ogg");
 }
 
 /******************************************************************************/
@@ -91,8 +90,7 @@ GUIEngine::GUIEngine(	irr::IrrlichtDevice* dev,
 	m_buttonhandler(0),
 	m_menu(0),
 	m_startgame(false),
-	m_engineluastack(0),
-	m_luaerrorhandler(-1),
+	m_script(0),
 	m_scriptdir(""),
 	m_irr_toplefttext(0),
 	m_clouds_enabled(true),
@@ -105,26 +103,6 @@ GUIEngine::GUIEngine(	irr::IrrlichtDevice* dev,
 	// is deleted by guiformspec!
 	m_buttonhandler = new TextDestGuiEngine(this);
 
-	//create luastack
-	m_engineluastack = luaL_newstate();
-
-	//load basic lua modules
-	luaL_openlibs(m_engineluastack);
-
-	//init
-	guiLuaApi::initialize(m_engineluastack,this);
-
-	//push errorstring
-	if (m_data->errormessage != "")
-	{
-		lua_getglobal(m_engineluastack, "gamedata");
-		int gamedata_idx = lua_gettop(m_engineluastack);
-		lua_pushstring(m_engineluastack, "errormessage");
-		lua_pushstring(m_engineluastack,m_data->errormessage.c_str());
-		lua_settable(m_engineluastack, gamedata_idx);
-		m_data->errormessage = "";
-	}
-
 	//create soundmanager
 	MenuMusicFetcher soundfetcher;
 #if USE_SOUND
@@ -160,68 +138,76 @@ GUIEngine::GUIEngine(	irr::IrrlichtDevice* dev,
 	m_menu->setTextDest(m_buttonhandler);
 	m_menu->useGettext(true);
 
-	std::string builtin_helpers
-		= porting::path_share + DIR_DELIM + "builtin"
-			+ DIR_DELIM + "misc_helpers.lua";
+	// Initialize scripting
 
-	if (!runScript(builtin_helpers)) {
-		errorstream
-			<< "GUIEngine::GUIEngine unable to load builtin helper script"
-			<< std::endl;
-		return;
-	}
+	infostream<<"GUIEngine: Initializing Lua"<<std::endl;
 
-	std::string menuscript = "";
-	if (g_settings->exists("main_menu_script"))
-		menuscript = g_settings->get("main_menu_script");
-	std::string builtin_menuscript =
-			porting::path_share + DIR_DELIM + "builtin"
-				+ DIR_DELIM + "mainmenu.lua";
+	m_script = new MainMenuScripting(this);
 
-	lua_pushcfunction(m_engineluastack, menuscript_ErrorHandler);
-	m_luaerrorhandler = lua_gettop(m_engineluastack);
+	try {
+		if (m_data->errormessage != "")
+		{
+			m_script->setMainMenuErrorMessage(m_data->errormessage);
+			m_data->errormessage = "";
+		}
 
-	m_scriptdir = menuscript.substr(0,menuscript.find_last_of(DIR_DELIM)-1);
-	if((menuscript == "") || (!runScript(menuscript))) {
-		infostream
-			<< "GUIEngine::GUIEngine execution of custom menu failed!"
-			<< std::endl
-			<< "\tfalling back to builtin menu"
-			<< std::endl;
-		m_scriptdir = fs::RemoveRelativePathComponents(porting::path_share + DIR_DELIM + "builtin"+ DIR_DELIM);
-		if(!runScript(builtin_menuscript)) {
-			errorstream
-				<< "GUIEngine::GUIEngine unable to load builtin menu"
-				<< std::endl;
+		if (!loadMainMenuScript())
 			assert("no future without mainmenu" == 0);
-		}
-	}
 
-	run();
+		run();
+	}
+	catch(LuaError &e) {
+		errorstream << "MAINMENU ERROR: " << e.what() << std::endl;
+		m_data->errormessage = e.what();
+	}
 
-	m_menumanager->deletingMenu(m_menu);
+	m_menu->quitMenu();
 	m_menu->drop();
 	m_menu = 0;
 }
 
 /******************************************************************************/
-bool GUIEngine::runScript(std::string script) {
-
-	int ret = 	luaL_loadfile(m_engineluastack, script.c_str()) ||
-				lua_pcall(m_engineluastack, 0, 0, m_luaerrorhandler);
-	if(ret){
-		errorstream<<"========== ERROR FROM LUA WHILE CREATING MAIN MENU ==========="<<std::endl;
-		errorstream<<"Failed to load and run script from "<<std::endl;
-		errorstream<<script<<":"<<std::endl;
-		errorstream<<std::endl;
-		errorstream<<lua_tostring(m_engineluastack, -1)<<std::endl;
-		errorstream<<std::endl;
-		errorstream<<"=================== END OF ERROR FROM LUA ===================="<<std::endl;
-		lua_pop(m_engineluastack, 1); // Pop error message from stack
-		lua_pop(m_engineluastack, 1); // Pop the error handler from stack
-		return false;
+bool GUIEngine::loadMainMenuScript()
+{
+	// Try custom menu script (main_menu_script)
+
+	std::string menuscript = g_settings->get("main_menu_script");
+	if(menuscript != "") {
+		m_scriptdir = fs::RemoveLastPathComponent(menuscript);
+
+		if(m_script->loadMod(menuscript, "__custommenu")) {
+			// custom menu script loaded
+			return true;
+		}
+		else {
+			infostream
+				<< "GUIEngine: execution of custom menu failed!"
+				<< std::endl
+				<< "\tfalling back to builtin menu"
+				<< std::endl;
+		}
 	}
-	return true;
+
+	// Try builtin menu script (main_menu_script)
+
+	std::string builtin_menuscript =
+			porting::path_share + DIR_DELIM + "builtin"
+				+ DIR_DELIM + "mainmenu.lua";
+
+	m_scriptdir = fs::RemoveRelativePathComponents(
+			fs::RemoveLastPathComponent(builtin_menuscript));
+
+	if(m_script->loadMod(builtin_menuscript, "__builtinmenu")) {
+		// builtin menu script loaded
+		return true;
+	}
+	else {
+		errorstream
+			<< "GUIEngine: unable to load builtin menu"
+			<< std::endl;
+	}
+
+	return false;
 }
 
 /******************************************************************************/
@@ -257,52 +243,6 @@ void GUIEngine::run()
 		else
 			sleep_ms(25);
 	}
-
-	m_menu->quitMenu();
-}
-
-/******************************************************************************/
-void GUIEngine::handleEvent(std::string text)
-{
-	lua_getglobal(m_engineluastack, "engine");
-
-	lua_getfield(m_engineluastack, -1, "event_handler");
-
-	if(lua_isnil(m_engineluastack, -1))
-		return;
-
-	luaL_checktype(m_engineluastack, -1, LUA_TFUNCTION);
-
-	lua_pushstring(m_engineluastack, text.c_str());
-
-	if(lua_pcall(m_engineluastack, 1, 0, m_luaerrorhandler))
-		scriptError("error: %s", lua_tostring(m_engineluastack, -1));
-}
-
-/******************************************************************************/
-void GUIEngine::handleButtons(std::map<std::string, std::string> fields)
-{
-	lua_getglobal(m_engineluastack, "engine");
-
-	lua_getfield(m_engineluastack, -1, "button_handler");
-
-	if(lua_isnil(m_engineluastack, -1))
-		return;
-
-	luaL_checktype(m_engineluastack, -1, LUA_TFUNCTION);
-
-	lua_newtable(m_engineluastack);
-	for(std::map<std::string, std::string>::const_iterator
-		i = fields.begin(); i != fields.end(); i++){
-		const std::string &name = i->first;
-		const std::string &value = i->second;
-		lua_pushstring(m_engineluastack, name.c_str());
-		lua_pushlstring(m_engineluastack, value.c_str(), value.size());
-		lua_settable(m_engineluastack, -3);
-	}
-
-	if(lua_pcall(m_engineluastack, 1, 0, m_luaerrorhandler))
-		scriptError("error: %s", lua_tostring(m_engineluastack, -1));
 }
 
 /******************************************************************************/
@@ -318,7 +258,8 @@ GUIEngine::~GUIEngine()
 
 	//TODO: clean up m_menu here
 
-	lua_close(m_engineluastack);
+	infostream<<"GUIEngine: Deinitializing scripting"<<std::endl;
+	delete m_script;
 
 	m_irr_toplefttext->setText(L"");
 
@@ -565,17 +506,6 @@ bool GUIEngine::downloadFile(std::string url,std::string target) {
 	return false;
 }
 
-/******************************************************************************/
-void GUIEngine::scriptError(const char *fmt, ...)
-{
-	va_list argp;
-	va_start(argp, fmt);
-	char buf[10000];
-	vsnprintf(buf, 10000, fmt, argp);
-	va_end(argp);
-	errorstream<<"MAINMENU ERROR: "<<buf;
-}
-
 /******************************************************************************/
 void GUIEngine::setTopleftText(std::string append) {
 	std::string toset = "Minetest " VERSION_STRING;
diff --git a/src/guiEngine.h b/src/guiEngine.h
index 2f96b0b1c..3987b52c7 100644
--- a/src/guiEngine.h
+++ b/src/guiEngine.h
@@ -26,7 +26,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "irrlichttypes.h"
 #include "modalMenu.h"
 #include "clouds.h"
-#include "guiLuaApi.h"
 #include "guiFormSpecMenu.h"
 #include "sound.h"
 
@@ -50,6 +49,7 @@ typedef enum {
 /* forward declarations                                                       */
 /******************************************************************************/
 class GUIEngine;
+class MainMenuScripting;
 struct MainMenuData;
 struct SimpleSoundSpec;
 
@@ -86,35 +86,17 @@ class MenuMusicFetcher: public OnDemandSoundFetcher
 {
 	std::set<std::string> m_fetched;
 public:
-
 	void fetchSounds(const std::string &name,
 			std::set<std::string> &dst_paths,
-			std::set<std::string> &dst_datas)
-	{
-		if(m_fetched.count(name))
-			return;
-		m_fetched.insert(name);
-		std::string base;
-		base = porting::path_share + DIR_DELIM + "sounds";
-		dst_paths.insert(base + DIR_DELIM + name + ".ogg");
-		int i;
-		for(i=0; i<10; i++)
-			dst_paths.insert(base + DIR_DELIM + name + "."+itos(i)+".ogg");
-		base = porting::path_user + DIR_DELIM + "sounds";
-		dst_paths.insert(base + DIR_DELIM + name + ".ogg");
-		for(i=0; i<10; i++)
-			dst_paths.insert(base + DIR_DELIM + name + "."+itos(i)+".ogg");
-		}
+			std::set<std::string> &dst_datas);
 };
 
 /** implementation of main menu based uppon formspecs */
 class GUIEngine {
-public:
-	/** TextDestGuiEngine needs to transfer data to engine */
-	friend class TextDestGuiEngine;
-	/** guiLuaApi is used to initialize contained stack */
-	friend class guiLuaApi;
+	/** grant ModApiMainMenu access to private members */
+	friend class ModApiMainMenu;
 
+public:
 	/**
 	 * default constructor
 	 * @param dev device to draw at
@@ -132,20 +114,12 @@ class GUIEngine {
 	/** default destructor */
 	virtual ~GUIEngine();
 
-	s32 playSound(SimpleSoundSpec spec, bool looped);
-	void stopSound(s32 handle);
-
-protected:
 	/**
-	 * process field data recieved from formspec
-	 * @param fields data in field format
+	 * return MainMenuScripting interface
 	 */
-	void handleButtons(std::map<std::string, std::string> fields);
-	/**
-	 * process events received from formspec
-	 * @param text events in textual form
-	 */
-	void handleEvent(std::string text);
+	MainMenuScripting* getScriptIface() {
+		return m_script;
+	}
 
 	/**
 	 * return dir of current menuscript
@@ -156,7 +130,10 @@ class GUIEngine {
 
 private:
 
-	/* run main menu loop */
+	/** find and run the main menu script */
+	bool loadMainMenuScript();
+
+	/** run main menu loop */
 	void run();
 
 	/** handler to limit frame rate within main menu */
@@ -185,27 +162,8 @@ class GUIEngine {
 	/** variable used to abort menu and return back to main game handling */
 	bool					m_startgame;
 
-	/**
-	 * initialize lua stack
-	 * @param L stack to initialize
-	 */
-	void initalize_api(lua_State * L);
-
-	/**
-	 * run a lua script
-	 * @param script full path to script to run
-	 */
-	bool runScript(std::string script);
-
-	/**
-	 * script error handler to process errors within lua
-	 */
-	void scriptError(const char *fmt, ...);
-
-	/** lua stack */
-	lua_State*				m_engineluastack;
-	/** lua internal stack number of error handler*/
-	int						m_luaerrorhandler;
+	/** scripting interface */
+	MainMenuScripting*			m_script;
 
 	/** script basefolder */
 	std::string				m_scriptdir;
@@ -284,6 +242,12 @@ class GUIEngine {
 	/** data used to draw clouds */
 	clouddata 				m_cloud;
 
+	/** start playing a sound and return handle */
+	s32 playSound(SimpleSoundSpec spec, bool looped);
+	/** stop playing a sound started with playSound() */
+	void stopSound(s32 handle);
+
+
 };
 
 
diff --git a/src/guiFormSpecMenu.cpp b/src/guiFormSpecMenu.cpp
index 0f09eaf52..f09996ef3 100644
--- a/src/guiFormSpecMenu.cpp
+++ b/src/guiFormSpecMenu.cpp
@@ -39,6 +39,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include <IGUIComboBox.h>
 #include "log.h"
 #include "tile.h" // ITextureSource
+#include "hud.h" // drawItemStack
 #include "util/string.h"
 #include "util/numeric.h"
 #include "filesys.h"
@@ -61,92 +62,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 	}
 
 
-void drawItemStack(video::IVideoDriver *driver,
-		gui::IGUIFont *font,
-		const ItemStack &item,
-		const core::rect<s32> &rect,
-		const core::rect<s32> *clip,
-		IGameDef *gamedef)
-{
-	if(item.empty())
-		return;
-	
-	const ItemDefinition &def = item.getDefinition(gamedef->idef());
-	video::ITexture *texture = gamedef->idef()->getInventoryTexture(def.name, gamedef);
-
-	// Draw the inventory texture
-	if(texture != NULL)
-	{
-		const video::SColor color(255,255,255,255);
-		const video::SColor colors[] = {color,color,color,color};
-		driver->draw2DImage(texture, rect,
-			core::rect<s32>(core::position2d<s32>(0,0),
-			core::dimension2di(texture->getOriginalSize())),
-			clip, colors, true);
-	}
-
-	if(def.type == ITEM_TOOL && item.wear != 0)
-	{
-		// Draw a progressbar
-		float barheight = rect.getHeight()/16;
-		float barpad_x = rect.getWidth()/16;
-		float barpad_y = rect.getHeight()/16;
-		core::rect<s32> progressrect(
-			rect.UpperLeftCorner.X + barpad_x,
-			rect.LowerRightCorner.Y - barpad_y - barheight,
-			rect.LowerRightCorner.X - barpad_x,
-			rect.LowerRightCorner.Y - barpad_y);
-
-		// Shrink progressrect by amount of tool damage
-		float wear = item.wear / 65535.0;
-		int progressmid =
-			wear * progressrect.UpperLeftCorner.X +
-			(1-wear) * progressrect.LowerRightCorner.X;
-
-		// Compute progressbar color
-		//   wear = 0.0: green
-		//   wear = 0.5: yellow
-		//   wear = 1.0: red
-		video::SColor color(255,255,255,255);
-		int wear_i = MYMIN(floor(wear * 600), 511);
-		wear_i = MYMIN(wear_i + 10, 511);
-		if(wear_i <= 255)
-			color.set(255, wear_i, 255, 0);
-		else
-			color.set(255, 255, 511-wear_i, 0);
-
-		core::rect<s32> progressrect2 = progressrect;
-		progressrect2.LowerRightCorner.X = progressmid;
-		driver->draw2DRectangle(color, progressrect2, clip);
-
-		color = video::SColor(255,0,0,0);
-		progressrect2 = progressrect;
-		progressrect2.UpperLeftCorner.X = progressmid;
-		driver->draw2DRectangle(color, progressrect2, clip);
-	}
-
-	if(font != NULL && item.count >= 2)
-	{
-		// Get the item count as a string
-		std::string text = itos(item.count);
-		v2u32 dim = font->getDimension(narrow_to_wide(text).c_str());
-		v2s32 sdim(dim.X,dim.Y);
-
-		core::rect<s32> rect2(
-			/*rect.UpperLeftCorner,
-			core::dimension2d<u32>(rect.getWidth(), 15)*/
-			rect.LowerRightCorner - sdim,
-			sdim
-		);
-
-		video::SColor bgcolor(128,0,0,0);
-		driver->draw2DRectangle(bgcolor, rect2, clip);
-
-		video::SColor color(255,255,255,255);
-		font->draw(text.c_str(), rect2, color, false, false, clip);
-	}
-}
-
 /*
 	GUIFormSpecMenu
 */
diff --git a/src/guiFormSpecMenu.h b/src/guiFormSpecMenu.h
index 116f7b95d..84124afc3 100644
--- a/src/guiFormSpecMenu.h
+++ b/src/guiFormSpecMenu.h
@@ -57,13 +57,6 @@ class IFormSource
 	virtual std::string resolveText(std::string str){ return str; }
 };
 
-void drawItemStack(video::IVideoDriver *driver,
-		gui::IGUIFont *font,
-		const ItemStack &item,
-		const core::rect<s32> &rect,
-		const core::rect<s32> *clip,
-		IGameDef *gamedef);
-
 class GUIFormSpecMenu : public GUIModalMenu
 {
 	struct ItemSpec
diff --git a/src/guiVolumeChange.cpp b/src/guiVolumeChange.cpp
index c272b132d..2f462b772 100644
--- a/src/guiVolumeChange.cpp
+++ b/src/guiVolumeChange.cpp
@@ -27,6 +27,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 #include <IGUIStaticText.h>
 #include <IGUIFont.h>
 #include "main.h"
+#include "settings.h"
 
 #include "gettext.h"
 
diff --git a/src/hud.cpp b/src/hud.cpp
index f1a4ab523..58a6c7cf8 100644
--- a/src/hud.cpp
+++ b/src/hud.cpp
@@ -19,14 +19,18 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
 
-#include <IGUIStaticText.h>
-
-#include "guiFormSpecMenu.h"
+#include "hud.h"
 #include "main.h"
+#include "settings.h"
 #include "util/numeric.h"
 #include "log.h"
-#include "client.h"
-#include "hud.h"
+#include "gamedef.h"
+#include "itemdef.h"
+#include "inventory.h"
+#include "tile.h"
+#include "localplayer.h"
+
+#include <IGUIStaticText.h>
 
 
 Hud::Hud(video::IVideoDriver *driver, gui::IGUIEnvironment* guienv,
@@ -339,3 +343,90 @@ void Hud::resizeHotbar() {
 	else
 		hotbar_imagesize = 64;
 }
+
+void drawItemStack(video::IVideoDriver *driver,
+		gui::IGUIFont *font,
+		const ItemStack &item,
+		const core::rect<s32> &rect,
+		const core::rect<s32> *clip,
+		IGameDef *gamedef)
+{
+	if(item.empty())
+		return;
+	
+	const ItemDefinition &def = item.getDefinition(gamedef->idef());
+	video::ITexture *texture = gamedef->idef()->getInventoryTexture(def.name, gamedef);
+
+	// Draw the inventory texture
+	if(texture != NULL)
+	{
+		const video::SColor color(255,255,255,255);
+		const video::SColor colors[] = {color,color,color,color};
+		driver->draw2DImage(texture, rect,
+			core::rect<s32>(core::position2d<s32>(0,0),
+			core::dimension2di(texture->getOriginalSize())),
+			clip, colors, true);
+	}
+
+	if(def.type == ITEM_TOOL && item.wear != 0)
+	{
+		// Draw a progressbar
+		float barheight = rect.getHeight()/16;
+		float barpad_x = rect.getWidth()/16;
+		float barpad_y = rect.getHeight()/16;
+		core::rect<s32> progressrect(
+			rect.UpperLeftCorner.X + barpad_x,
+			rect.LowerRightCorner.Y - barpad_y - barheight,
+			rect.LowerRightCorner.X - barpad_x,
+			rect.LowerRightCorner.Y - barpad_y);
+
+		// Shrink progressrect by amount of tool damage
+		float wear = item.wear / 65535.0;
+		int progressmid =
+			wear * progressrect.UpperLeftCorner.X +
+			(1-wear) * progressrect.LowerRightCorner.X;
+
+		// Compute progressbar color
+		//   wear = 0.0: green
+		//   wear = 0.5: yellow
+		//   wear = 1.0: red
+		video::SColor color(255,255,255,255);
+		int wear_i = MYMIN(floor(wear * 600), 511);
+		wear_i = MYMIN(wear_i + 10, 511);
+		if(wear_i <= 255)
+			color.set(255, wear_i, 255, 0);
+		else
+			color.set(255, 255, 511-wear_i, 0);
+
+		core::rect<s32> progressrect2 = progressrect;
+		progressrect2.LowerRightCorner.X = progressmid;
+		driver->draw2DRectangle(color, progressrect2, clip);
+
+		color = video::SColor(255,0,0,0);
+		progressrect2 = progressrect;
+		progressrect2.UpperLeftCorner.X = progressmid;
+		driver->draw2DRectangle(color, progressrect2, clip);
+	}
+
+	if(font != NULL && item.count >= 2)
+	{
+		// Get the item count as a string
+		std::string text = itos(item.count);
+		v2u32 dim = font->getDimension(narrow_to_wide(text).c_str());
+		v2s32 sdim(dim.X,dim.Y);
+
+		core::rect<s32> rect2(
+			/*rect.UpperLeftCorner,
+			core::dimension2d<u32>(rect.getWidth(), 15)*/
+			rect.LowerRightCorner - sdim,
+			sdim
+		);
+
+		video::SColor bgcolor(128,0,0,0);
+		driver->draw2DRectangle(bgcolor, rect2, clip);
+
+		video::SColor color(255,255,255,255);
+		font->draw(text.c_str(), rect2, color, false, false, clip);
+	}
+}
+
diff --git a/src/hud.h b/src/hud.h
index c7289f7c4..27e239297 100644
--- a/src/hud.h
+++ b/src/hud.h
@@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #define HUD_HEADER
 
 #include "irrlichttypes_extrabloated.h"
+#include <string>
 
 #define HUD_DIR_LEFT_RIGHT 0
 #define HUD_DIR_RIGHT_LEFT 1
@@ -42,8 +43,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #define HUD_HOTBAR_ITEMCOUNT_DEFAULT 8
 #define HUD_HOTBAR_ITEMCOUNT_MAX     23
 
-class Player;
-
 enum HudElementType {
 	HUD_ELEM_IMAGE     = 0,
 	HUD_ELEM_TEXT      = 1,
@@ -76,23 +75,18 @@ struct HudElement {
 	v2f offset;
 };
 
-
-inline u32 hud_get_free_id(Player *player) {
-	size_t size = player->hud.size();
-	for (size_t i = 0; i != size; i++) {
-		if (!player->hud[i])
-			return i;
-	}
-	return size;
-}
-
 #ifndef SERVER
 
+#include <vector>
 #include <IGUIFont.h>
+#include "irr_aabb3d.h"
 
-#include "gamedef.h"
-#include "inventory.h"
-#include "localplayer.h"
+class IGameDef;
+class ITextureSource;
+class Inventory;
+class InventoryList;
+class LocalPlayer;
+struct ItemStack;
 
 class Hud {
 public:
@@ -130,6 +124,14 @@ class Hud {
 	void drawSelectionBoxes(std::vector<aabb3f> &hilightboxes);
 };
 
+void drawItemStack(video::IVideoDriver *driver,
+		gui::IGUIFont *font,
+		const ItemStack &item,
+		const core::rect<s32> &rect,
+		const core::rect<s32> *clip,
+		IGameDef *gamedef);
+
+
 #endif
 
 #endif
diff --git a/src/inventory.h b/src/inventory.h
index 1a66a13a4..cd592a17a 100644
--- a/src/inventory.h
+++ b/src/inventory.h
@@ -21,10 +21,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #define INVENTORY_HEADER
 
 #include <iostream>
-#include <sstream>
 #include <string>
 #include <vector>
-#include "irrlichttypes_bloated.h"
+#include "irrlichttypes.h"
 #include "debug.h"
 #include "itemdef.h"
 
diff --git a/src/inventorymanager.cpp b/src/inventorymanager.cpp
index 6187675d4..c81f7a19e 100644
--- a/src/inventorymanager.cpp
+++ b/src/inventorymanager.cpp
@@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "inventorymanager.h"
 #include "log.h"
 #include "environment.h"
-#include "cpp_api/scriptapi.h"
+#include "scripting_game.h"
 #include "serverobject.h"
 #include "main.h"  // for g_settings
 #include "settings.h"
@@ -29,6 +29,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
 
+#define PLAYER_TO_SA(p)   p->getEnv()->getScriptIface()
+
 /*
 	InventoryLocation
 */
diff --git a/src/irrlichttypes_bloated.h b/src/irrlichttypes_bloated.h
index 2ce19999e..77aba350c 100644
--- a/src/irrlichttypes_bloated.h
+++ b/src/irrlichttypes_bloated.h
@@ -26,9 +26,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "irr_v3d.h"
 #include "irr_aabb3d.h"
 
-#include <irrMap.h>
-#include <irrList.h>
-#include <irrArray.h>
 #include <SColor.h>
 
 #endif
diff --git a/src/irrlichttypes_extrabloated.h b/src/irrlichttypes_extrabloated.h
index a541b1a02..cd6cb1d2c 100644
--- a/src/irrlichttypes_extrabloated.h
+++ b/src/irrlichttypes_extrabloated.h
@@ -20,9 +20,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #ifndef IRRLICHTTYPES_EXTRABLOATED_HEADER
 #define IRRLICHTTYPES_EXTRABLOATED_HEADER
 
-#define endSceneX(d){d->draw2DLine(v2s32(0,0),v2s32(1,0),\
-video::SColor(255,30,30,30));d->endScene();}
-
 #include "irrlichttypes_bloated.h"
 
 #ifndef SERVER
diff --git a/src/itemgroup.h b/src/itemgroup.h
index 69678064f..f6ae86736 100644
--- a/src/itemgroup.h
+++ b/src/itemgroup.h
@@ -20,7 +20,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #ifndef ITEMGROUP_HEADER
 #define ITEMGROUP_HEADER
 
-#include "irrlichttypes_extrabloated.h"
 #include <string>
 #include <map>
 
diff --git a/src/light.h b/src/light.h
index e847e1ce9..769ca31ce 100644
--- a/src/light.h
+++ b/src/light.h
@@ -21,16 +21,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #define LIGHT_HEADER
 
 #include "irrlichttypes.h"
-#include "debug.h"
-
-/*
-	Day/night cache:
-	Meshes are cached for different day-to-night transition values
-*/
-
-/*#define DAYNIGHT_CACHE_COUNT 3
-// First one is day, last one is night.
-extern u32 daynight_cache_ratios[DAYNIGHT_CACHE_COUNT];*/
 
 /*
 	Lower level lighting stuff
diff --git a/src/main.cpp b/src/main.cpp
index f495a6ba2..7450593d3 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -84,6 +84,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 */
 Settings main_settings;
 Settings *g_settings = &main_settings;
+std::string g_settings_path;
 
 // Global profiler
 Profiler main_profiler;
@@ -913,7 +914,7 @@ int main(int argc, char *argv[])
 	*/
 	
 	// Path of configuration file in use
-	std::string configpath = "";
+	g_settings_path = "";
 	
 	if(cmd_args.exists("config"))
 	{
@@ -924,7 +925,7 @@ int main(int argc, char *argv[])
 					<<cmd_args.get("config")<<"\""<<std::endl;
 			return 1;
 		}
-		configpath = cmd_args.get("config");
+		g_settings_path = cmd_args.get("config");
 	}
 	else
 	{
@@ -946,14 +947,14 @@ int main(int argc, char *argv[])
 			bool r = g_settings->readConfigFile(filenames[i].c_str());
 			if(r)
 			{
-				configpath = filenames[i];
+				g_settings_path = filenames[i];
 				break;
 			}
 		}
 		
 		// If no path found, use the first one (menu creates the file)
-		if(configpath == "")
-			configpath = filenames[0];
+		if(g_settings_path == "")
+			g_settings_path = filenames[0];
 	}
 	
 	// Initialize debug streams
@@ -1193,7 +1194,7 @@ int main(int argc, char *argv[])
 		verbosestream<<_("Using gameid")<<" ["<<gamespec.id<<"]"<<std::endl;
 
 		// Create server
-		Server server(world_path, configpath, gamespec, false);
+		Server server(world_path, gamespec, false);
 		server.start(port);
 		
 		// Run server
@@ -1573,6 +1574,11 @@ int main(int argc, char *argv[])
 
 				}
 
+				if(menudata.errormessage != ""){
+					error_message = narrow_to_wide(menudata.errormessage);
+					continue;
+				}
+
 				//update worldspecs (necessary as new world may have been created)
 				worldspecs = getAvailableWorlds();
 
@@ -1675,7 +1681,10 @@ int main(int argc, char *argv[])
 
 			// Break out of menu-game loop to shut down cleanly
 			if(device->run() == false || kill == true) {
-				g_settings->updateConfigFile(configpath.c_str());
+				if(g_settings_path != "") {
+					g_settings->updateConfigFile(
+						g_settings_path.c_str());
+				}
 				break;
 			}
 
@@ -1694,7 +1703,6 @@ int main(int argc, char *argv[])
 				current_address,
 				current_port,
 				error_message,
-				configpath,
 				chat_backend,
 				gamespec,
 				simple_singleplayer_mode
@@ -1749,8 +1757,8 @@ int main(int argc, char *argv[])
 #endif // !SERVER
 	
 	// Update configuration file
-	if(configpath != "")
-		g_settings->updateConfigFile(configpath.c_str());
+	if(g_settings_path != "")
+		g_settings->updateConfigFile(g_settings_path.c_str());
 	
 	// Print modified quicktune values
 	{
diff --git a/src/main.h b/src/main.h
index df67a6348..191b41887 100644
--- a/src/main.h
+++ b/src/main.h
@@ -20,9 +20,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #ifndef MAIN_HEADER
 #define MAIN_HEADER
 
+#include <string>
+
 // Settings
 class Settings;
 extern Settings *g_settings;
+extern std::string g_settings_path;
 
 // Global profiler
 class Profiler;
diff --git a/src/map.cpp b/src/map.cpp
index 331aa48d9..62ba85c47 100644
--- a/src/map.cpp
+++ b/src/map.cpp
@@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "filesys.h"
 #include "voxel.h"
 #include "porting.h"
+#include "serialization.h"
 #include "nodemetadata.h"
 #include "settings.h"
 #include "log.h"
@@ -33,9 +34,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "util/directiontables.h"
 #include "util/mathconstants.h"
 #include "rollback_interface.h"
+#include "environment.h"
 #include "emerge.h"
 #include "mapgen_v6.h"
-#include "mapgen_indev.h"
 #include "biome.h"
 
 #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
diff --git a/src/map.h b/src/map.h
index c90106ed1..2f8bfaeba 100644
--- a/src/map.h
+++ b/src/map.h
@@ -20,9 +20,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #ifndef MAP_HEADER
 #define MAP_HEADER
 
-#include <jmutex.h>
-#include <jmutexautolock.h>
-#include <jthread.h>
 #include <iostream>
 #include <sstream>
 #include <set>
@@ -33,11 +30,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "mapnode.h"
 #include "constants.h"
 #include "voxel.h"
-#include "mapgen.h" //for MapgenParams
 #include "modifiedstate.h"
 #include "util/container.h"
 #include "nodetimer.h"
-#include "environment.h"
 
 extern "C" {
 	#include "sqlite3.h"
@@ -51,7 +46,9 @@ class NodeMetadata;
 class IGameDef;
 class IRollbackReportSink;
 class EmergeManager;
+class ServerEnvironment;
 struct BlockMakeData;
+struct MapgenParams;
 
 
 /*
diff --git a/src/mapblock.cpp b/src/mapblock.cpp
index 617ba6584..b8278b3be 100644
--- a/src/mapblock.cpp
+++ b/src/mapblock.cpp
@@ -21,8 +21,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 #include <sstream>
 #include "map.h"
-// For g_settings
-#include "main.h"
 #include "light.h"
 #include "nodedef.h"
 #include "nodemetadata.h"
@@ -31,6 +29,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "nameidmapping.h"
 #include "content_mapnode.h" // For legacy name-id mapping
 #include "content_nodemeta.h" // For legacy deserialization
+#include "serialization.h"
 #ifndef SERVER
 #include "mapblock_mesh.h"
 #endif
diff --git a/src/mapblock.h b/src/mapblock.h
index 576122201..de49e6130 100644
--- a/src/mapblock.h
+++ b/src/mapblock.h
@@ -20,19 +20,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #ifndef MAPBLOCK_HEADER
 #define MAPBLOCK_HEADER
 
-#include <jmutex.h>
-#include <jmutexautolock.h>
-#include <exception>
 #include <set>
 #include "debug.h"
-#include "irrlichttypes.h"
 #include "irr_v3d.h"
-#include "irr_aabb3d.h"
 #include "mapnode.h"
 #include "exceptions.h"
-#include "serialization.h"
 #include "constants.h"
-#include "voxel.h"
 #include "staticobject.h"
 #include "nodemetadata.h"
 #include "nodetimer.h"
@@ -43,6 +36,7 @@ class Map;
 class NodeMetadataList;
 class IGameDef;
 class MapBlockMesh;
+class VoxelManipulator;
 
 #define BLOCK_TIMESTAMP_UNDEFINED 0xffffffff
 
@@ -514,7 +508,6 @@ class MapBlock /*: public NodeContainer*/
 
 #ifndef SERVER // Only on client
 	MapBlockMesh *mesh;
-	//JMutex mesh_mutex;
 #endif
 	
 	NodeMetadataList m_node_metadata;
diff --git a/src/mapgen.cpp b/src/mapgen.cpp
index be65694aa..301601b6c 100644
--- a/src/mapgen.cpp
+++ b/src/mapgen.cpp
@@ -35,6 +35,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "treegen.h"
 #include "mapgen_v6.h"
 #include "mapgen_v7.h"
+#include "serialization.h"
 #include "util/serialize.h"
 #include "filesys.h"
 
diff --git a/src/mapgen.h b/src/mapgen.h
index 2e87c62bf..040320f27 100644
--- a/src/mapgen.h
+++ b/src/mapgen.h
@@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #ifndef MAPGEN_HEADER
 #define MAPGEN_HEADER
 
-#include "irrlichttypes_extrabloated.h"
+#include "irrlichttypes_bloated.h"
 #include "util/container.h" // UniqueQueue
 #include "gamedef.h"
 #include "nodedef.h"
diff --git a/src/mapgen_singlenode.cpp b/src/mapgen_singlenode.cpp
index 30787c6bb..fd443995c 100644
--- a/src/mapgen_singlenode.cpp
+++ b/src/mapgen_singlenode.cpp
@@ -25,8 +25,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "nodedef.h"
 #include "voxelalgorithms.h"
 #include "profiler.h"
-#include "settings.h" // For g_settings
-#include "main.h" // For g_profiler
 #include "emerge.h"
 
 //////////////////////// Mapgen Singlenode parameter read/write
diff --git a/src/mapnode.h b/src/mapnode.h
index 785537759..3c6208436 100644
--- a/src/mapnode.h
+++ b/src/mapnode.h
@@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "irr_v3d.h"
 #include "irr_aabb3d.h"
 #include "light.h"
+#include <string>
 #include <vector>
 
 class INodeDefManager;
diff --git a/src/mapsector.cpp b/src/mapsector.cpp
index ebb050ec3..0d40a659d 100644
--- a/src/mapsector.cpp
+++ b/src/mapsector.cpp
@@ -18,12 +18,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 */
 
 #include "mapsector.h"
-#include "jmutexautolock.h"
-#ifndef SERVER
-#include "client.h"
-#endif
 #include "exceptions.h"
 #include "mapblock.h"
+#include "serialization.h"
 
 MapSector::MapSector(Map *parent, v2s16 pos, IGameDef *gamedef):
 		differs_from_disk(false),
diff --git a/src/mapsector.h b/src/mapsector.h
index 4f2b3f31f..dac4ee8d6 100644
--- a/src/mapsector.h
+++ b/src/mapsector.h
@@ -20,9 +20,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #ifndef MAPSECTOR_HEADER
 #define MAPSECTOR_HEADER
 
-#include <jmutex.h>
-#include "irrlichttypes_bloated.h"
-#include "exceptions.h"
+#include "irrlichttypes.h"
+#include "irr_v2d.h"
 #include <ostream>
 #include <map>
 #include <list>
diff --git a/src/mesh.cpp b/src/mesh.cpp
index 14a194b88..5e5f9f863 100644
--- a/src/mesh.cpp
+++ b/src/mesh.cpp
@@ -18,8 +18,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 */
 
 #include "mesh.h"
+#include "debug.h"
 #include "log.h"
-#include <cassert>
 #include <iostream>
 #include <IAnimatedMesh.h>
 #include <SAnimatedMesh.h>
diff --git a/src/mods.h b/src/mods.h
index e10d49324..dedcc9897 100644
--- a/src/mods.h
+++ b/src/mods.h
@@ -21,14 +21,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #define MODS_HEADER
 
 #include "irrlichttypes.h"
-#include <irrList.h>
 #include <list>
 #include <set>
 #include <vector>
 #include <string>
 #include <map>
 #include <exception>
-#include <list>
 #include "json/json.h"
 #include "config.h"
 
@@ -152,10 +150,9 @@ class ModConfiguration
 	// exists. A name conflict happens when two or more mods
 	// at the same level have the same name but different paths.
 	// Levels (mods in higher levels override mods in lower levels):
-	// 1. common mod in modpack; 2. common mod;
-	// 3. game mod in modpack; 4. game mod;
-	// 5. world mod in modpack; 6. world mod;
-	// 7. addon mod in modpack; 8. addon mod.
+	// 1. game mod in modpack; 2. game mod;
+	// 3. world mod in modpack; 4. world mod;
+	// 5. addon mod in modpack; 6. addon mod.
 	std::set<std::string> m_name_conflicts;
 
 };
diff --git a/src/nameidmapping.cpp b/src/nameidmapping.cpp
index bcddb4515..ebe65076e 100644
--- a/src/nameidmapping.cpp
+++ b/src/nameidmapping.cpp
@@ -18,6 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 */
 
 #include "nameidmapping.h"
+#include "exceptions.h"
 #include "util/serialize.h"
 
 void NameIdMapping::serialize(std::ostream &os) const
diff --git a/src/nodemetadata.h b/src/nodemetadata.h
index 5af10d0f0..ce2c9e6d9 100644
--- a/src/nodemetadata.h
+++ b/src/nodemetadata.h
@@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #ifndef NODEMETADATA_HEADER
 #define NODEMETADATA_HEADER
 
-#include "irrlichttypes_bloated.h"
+#include "irr_v3d.h"
 #include <string>
 #include <iostream>
 #include <map>
diff --git a/src/nodetimer.cpp b/src/nodetimer.cpp
index db5fb08b6..5fc652bb7 100644
--- a/src/nodetimer.cpp
+++ b/src/nodetimer.cpp
@@ -19,6 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 #include "nodetimer.h"
 #include "log.h"
+#include "serialization.h"
 #include "util/serialize.h"
 #include "constants.h" // MAP_BLOCKSIZE
 
diff --git a/src/nodetimer.h b/src/nodetimer.h
index bdbd32293..9fb56edec 100644
--- a/src/nodetimer.h
+++ b/src/nodetimer.h
@@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #ifndef NODETIMER_HEADER
 #define NODETIMER_HEADER
 
-#include "irrlichttypes_bloated.h"
+#include "irr_v3d.h"
 #include <iostream>
 #include <map>
 
diff --git a/src/noise.cpp b/src/noise.cpp
index 5788a8320..35057146d 100644
--- a/src/noise.cpp
+++ b/src/noise.cpp
@@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include <math.h>
 #include "noise.h"
 #include <iostream>
+#include <string.h> // memset
 #include "debug.h"
 #include "util/numeric.h"
 
diff --git a/src/object_properties.cpp b/src/object_properties.cpp
index 7fad25cce..b6ad9f6df 100644
--- a/src/object_properties.cpp
+++ b/src/object_properties.cpp
@@ -19,9 +19,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 #include "object_properties.h"
 #include "irrlichttypes_bloated.h"
+#include "exceptions.h"
 #include "util/serialize.h"
 #include <sstream>
-#include <map>
 
 #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
 #define PP2(x) "("<<(x).X<<","<<(x).Y<<")"
diff --git a/src/pathfinder.cpp b/src/pathfinder.cpp
index bbda07362..43e1e287f 100644
--- a/src/pathfinder.cpp
+++ b/src/pathfinder.cpp
@@ -22,6 +22,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 /******************************************************************************/
 
 #include "pathfinder.h"
+#include "environment.h"
+#include "map.h"
+#include "log.h"
 
 #ifdef PATHFINDER_DEBUG
 #include <iomanip>
diff --git a/src/pathfinder.h b/src/pathfinder.h
index 7caf5844e..dd41227f7 100644
--- a/src/pathfinder.h
+++ b/src/pathfinder.h
@@ -25,10 +25,15 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 /******************************************************************************/
 #include <vector>
 
-#include "server.h"
 #include "irr_v3d.h"
 
 
+/******************************************************************************/
+/* Forward declarations                                                       */
+/******************************************************************************/
+
+class ServerEnvironment;
+
 /******************************************************************************/
 /* Typedefs and macros                                                        */
 /******************************************************************************/
diff --git a/src/player.cpp b/src/player.cpp
index 193de55a9..584c00dd0 100644
--- a/src/player.cpp
+++ b/src/player.cpp
@@ -21,7 +21,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "hud.h"
 #include "constants.h"
 #include "gamedef.h"
-#include "connection.h" // PEER_ID_INEXISTENT
 #include "settings.h"
 #include "content_sao.h"
 #include "util/numeric.h"
diff --git a/src/player.h b/src/player.h
index 7ddc40b37..12ea0dba1 100644
--- a/src/player.h
+++ b/src/player.h
@@ -194,6 +194,15 @@ class Player
 		return m_collisionbox;
 	}
 
+	u32 getFreeHudID() const {
+		size_t size = hud.size();
+		for (size_t i = 0; i != size; i++) {
+			if (!hud[i])
+				return i;
+		}
+		return size;
+	}
+
 	virtual bool isLocal() const
 	{ return false; }
 	virtual PlayerSAO *getPlayerSAO()
diff --git a/src/porting.h b/src/porting.h
index 12c390893..ea7f31b13 100644
--- a/src/porting.h
+++ b/src/porting.h
@@ -29,6 +29,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "debug.h"
 #include "constants.h"
 #include "gettime.h"
+#include "threads.h"
 
 #ifdef _MSC_VER
 	#define SWPRINTF_CHARSTRING L"%S"
diff --git a/src/profiler.h b/src/profiler.h
index 271ad70c1..e22a865c0 100644
--- a/src/profiler.h
+++ b/src/profiler.h
@@ -20,13 +20,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #ifndef PROFILER_HEADER
 #define PROFILER_HEADER
 
-#include "irrlichttypes_bloated.h"
+#include "irrlichttypes.h"
 #include <string>
 #include <jmutex.h>
 #include <jmutexautolock.h>
 #include <map>
 #include "util/timetaker.h"
 #include "util/numeric.h" // paging()
+#include "debug.h" // assert()
 
 /*
 	Time profiler
diff --git a/src/rollback.cpp b/src/rollback.cpp
index fe1d59d0c..e11006826 100644
--- a/src/rollback.cpp
+++ b/src/rollback.cpp
@@ -27,7 +27,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "nodedef.h"
 #include "util/serialize.h"
 #include "util/string.h"
-#include "strfnd.h"
 #include "util/numeric.h"
 #include "inventorymanager.h" // deserializing InventoryLocations
 
diff --git a/src/script/CMakeLists.txt b/src/script/CMakeLists.txt
index e1a03b95a..491c05a1e 100644
--- a/src/script/CMakeLists.txt
+++ b/src/script/CMakeLists.txt
@@ -2,8 +2,18 @@ add_subdirectory(common)
 add_subdirectory(cpp_api)
 add_subdirectory(lua_api)
 
-set(SCRIPT_SRCS 
-	${SCRIPT_COMMON_SRCS}
-	${SCRIPT_CPP_API_SRCS}
-	${SCRIPT_LUA_API_SRCS}
+# Used by server and client
+set(common_SCRIPT_SRCS 
+	${CMAKE_CURRENT_SOURCE_DIR}/scripting_game.cpp
+	${common_SCRIPT_COMMON_SRCS}
+	${common_SCRIPT_CPP_API_SRCS}
+	${common_SCRIPT_LUA_API_SRCS}
+	PARENT_SCOPE)
+
+# Used by client only
+set(minetest_SCRIPT_SRCS 
+	${CMAKE_CURRENT_SOURCE_DIR}/scripting_mainmenu.cpp
+	${minetest_SCRIPT_COMMON_SRCS}
+	${minetest_SCRIPT_CPP_API_SRCS}
+	${minetest_SCRIPT_LUA_API_SRCS}
 	PARENT_SCOPE)
diff --git a/src/script/common/CMakeLists.txt b/src/script/common/CMakeLists.txt
index c8f7ef783..27e2fb4d5 100644
--- a/src/script/common/CMakeLists.txt
+++ b/src/script/common/CMakeLists.txt
@@ -1,6 +1,11 @@
-set(SCRIPT_COMMON_SRCS
+# Used by server and client
+set(common_SCRIPT_COMMON_SRCS
 	${CMAKE_CURRENT_SOURCE_DIR}/c_content.cpp
 	${CMAKE_CURRENT_SOURCE_DIR}/c_converter.cpp
 	${CMAKE_CURRENT_SOURCE_DIR}/c_types.cpp
 	${CMAKE_CURRENT_SOURCE_DIR}/c_internal.cpp
 	PARENT_SCOPE)
+
+# Used by client only
+set(minetest_SCRIPT_COMMON_SRCS
+	PARENT_SCOPE)
diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp
index cb2b0e737..2e26adb76 100644
--- a/src/script/common/c_content.cpp
+++ b/src/script/common/c_content.cpp
@@ -29,7 +29,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "server.h"
 #include "log.h"
 #include "tool.h"
-#include "server.h"
+#include "serverobject.h"
 #include "mapgen.h"
 
 struct EnumString es_TileAnimationType[] =
@@ -694,8 +694,7 @@ void push_tool_capabilities(lua_State *L,
 }
 
 /******************************************************************************/
-void push_inventory_list(Inventory *inv, const char *name,
-		lua_State *L)
+void push_inventory_list(lua_State *L, Inventory *inv, const char *name)
 {
 	InventoryList *invlist = inv->getList(name);
 	if(invlist == NULL){
@@ -709,8 +708,8 @@ void push_inventory_list(Inventory *inv, const char *name,
 }
 
 /******************************************************************************/
-void read_inventory_list(Inventory *inv, const char *name,
-		lua_State *L, int tableindex, Server* srv,int forcesize)
+void read_inventory_list(lua_State *L, int tableindex,
+		Inventory *inv, const char *name, Server* srv, int forcesize)
 {
 	if(tableindex < 0)
 		tableindex = lua_gettop(L) + 1 + tableindex;
diff --git a/src/script/common/c_content.h b/src/script/common/c_content.h
index fc00ce089..6d1dfe1d5 100644
--- a/src/script/common/c_content.h
+++ b/src/script/common/c_content.h
@@ -87,14 +87,13 @@ void               read_object_properties    (lua_State *L,
                                               int index,
                                               ObjectProperties *prop);
 
-//TODO fix parameter oreder!
-void               push_inventory_list       (Inventory *inv,
-                                              const char *name,
-                                              lua_State *L);
-void               read_inventory_list       (Inventory *inv,
-                                              const char *name,
-                                              lua_State *L,
+void               push_inventory_list       (lua_State *L,
+                                              Inventory *inv,
+                                              const char *name);
+void               read_inventory_list       (lua_State *L,
                                               int tableindex,
+                                              Inventory *inv,
+                                              const char *name,
                                               Server* srv,
                                               int forcesize=-1);
 
diff --git a/src/script/common/c_internal.cpp b/src/script/common/c_internal.cpp
index 42e9fb3e1..5c16b88d9 100644
--- a/src/script/common/c_internal.cpp
+++ b/src/script/common/c_internal.cpp
@@ -18,17 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 */
 
 #include "common/c_internal.h"
-#include "server.h"
-#include "cpp_api/scriptapi.h"
-
-ScriptApi* get_scriptapi(lua_State *L)
-{
-	// Get server from registry
-	lua_getfield(L, LUA_REGISTRYINDEX, "scriptapi");
-	ScriptApi* sapi_ptr = (ScriptApi*) lua_touserdata(L, -1);
-	lua_pop(L, 1);
-	return sapi_ptr;
-}
+#include "debug.h"
 
 std::string script_get_backtrace(lua_State *L)
 {
@@ -51,15 +41,108 @@ std::string script_get_backtrace(lua_State *L)
 	return s;
 }
 
-void script_error(lua_State* L,const char *fmt, ...)
+void script_error(lua_State *L, const char *fmt, ...)
 {
 	va_list argp;
 	va_start(argp, fmt);
 	char buf[10000];
 	vsnprintf(buf, 10000, fmt, argp);
 	va_end(argp);
-	//errorstream<<"SCRIPT ERROR: "<<buf;
 	throw LuaError(L, buf);
 }
 
+// Push the list of callbacks (a lua table).
+// Then push nargs arguments.
+// Then call this function, which
+// - runs the callbacks
+// - removes the table and arguments from the lua stack
+// - pushes the return value, computed depending on mode
+void script_run_callbacks(lua_State *L, int nargs, RunCallbacksMode mode)
+{
+	// Insert the return value into the lua stack, below the table
+	assert(lua_gettop(L) >= nargs + 1);
+	lua_pushnil(L);
+	lua_insert(L, -(nargs + 1) - 1);
+	// Stack now looks like this:
+	// ... <return value = nil> <table> <arg#1> <arg#2> ... <arg#n>
+
+	int rv = lua_gettop(L) - nargs - 1;
+	int table = rv + 1;
+	int arg = table + 1;
+
+	luaL_checktype(L, table, LUA_TTABLE);
+
+	// Foreach
+	lua_pushnil(L);
+	bool first_loop = true;
+	while(lua_next(L, table) != 0){
+		// key at index -2 and value at index -1
+		luaL_checktype(L, -1, LUA_TFUNCTION);
+		// Call function
+		for(int i = 0; i < nargs; i++)
+			lua_pushvalue(L, arg+i);
+		if(lua_pcall(L, nargs, 1, 0))
+			script_error(L, "error: %s", lua_tostring(L, -1));
+
+		// Move return value to designated space in stack
+		// Or pop it
+		if(first_loop){
+			// Result of first callback is always moved
+			lua_replace(L, rv);
+			first_loop = false;
+		} else {
+			// Otherwise, what happens depends on the mode
+			if(mode == RUN_CALLBACKS_MODE_FIRST)
+				lua_pop(L, 1);
+			else if(mode == RUN_CALLBACKS_MODE_LAST)
+				lua_replace(L, rv);
+			else if(mode == RUN_CALLBACKS_MODE_AND ||
+					mode == RUN_CALLBACKS_MODE_AND_SC){
+				if((bool)lua_toboolean(L, rv) == true &&
+						(bool)lua_toboolean(L, -1) == false)
+					lua_replace(L, rv);
+				else
+					lua_pop(L, 1);
+			}
+			else if(mode == RUN_CALLBACKS_MODE_OR ||
+					mode == RUN_CALLBACKS_MODE_OR_SC){
+				if((bool)lua_toboolean(L, rv) == false &&
+						(bool)lua_toboolean(L, -1) == true)
+					lua_replace(L, rv);
+				else
+					lua_pop(L, 1);
+			}
+			else
+				assert(0);
+		}
+
+		// Handle short circuit modes
+		if(mode == RUN_CALLBACKS_MODE_AND_SC &&
+				(bool)lua_toboolean(L, rv) == false)
+			break;
+		else if(mode == RUN_CALLBACKS_MODE_OR_SC &&
+				(bool)lua_toboolean(L, rv) == true)
+			break;
+
+		// value removed, keep key for next iteration
+	}
+
+	// Remove stuff from stack, leaving only the return value
+	lua_settop(L, rv);
+
+	// Fix return value in case no callbacks were called
+	if(first_loop){
+		if(mode == RUN_CALLBACKS_MODE_AND ||
+				mode == RUN_CALLBACKS_MODE_AND_SC){
+			lua_pop(L, 1);
+			lua_pushboolean(L, true);
+		}
+		else if(mode == RUN_CALLBACKS_MODE_OR ||
+				mode == RUN_CALLBACKS_MODE_OR_SC){
+			lua_pop(L, 1);
+			lua_pushboolean(L, false);
+		}
+	}
+}
+
 
diff --git a/src/script/common/c_internal.h b/src/script/common/c_internal.h
index dafde5843..9a50b8e96 100644
--- a/src/script/common/c_internal.h
+++ b/src/script/common/c_internal.h
@@ -27,34 +27,46 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #ifndef C_INTERNAL_H_
 #define C_INTERNAL_H_
 
-class Server;
-class ScriptApi;
-#include <iostream>
-
-#include "lua_api/l_base.h"
-
 extern "C" {
-#include "lua.h"
+#include <lua.h>
+#include <lauxlib.h>
 }
 
-#define luamethod(class, name) {#name, class::l_##name}
-#define STACK_TO_SERVER(L) get_scriptapi(L)->getServer()
-#define API_FCT(name) registerFunction(L,#name,l_##name,top)
-
-#define REGISTER_LUA_REF(cln)                                                  \
-class ModApi_##cln : public ModApiBase {                                       \
-	public:                                                                    \
-		ModApi_##cln() : ModApiBase() {};                                      \
-		bool Initialize(lua_State* L, int top) {                               \
-			cln::Register(L);                                                  \
-			return true;                                                       \
-		};                                                                     \
-};                                                                             \
-ModApi_##cln macro_generated_prototype__##cln;
+#include "common/c_types.h"
 
+// What script_run_callbacks does with the return values of callbacks.
+// Regardless of the mode, if only one callback is defined,
+// its return value is the total return value.
+// Modes only affect the case where 0 or >= 2 callbacks are defined.
+enum RunCallbacksMode
+{
+	// Returns the return value of the first callback
+	// Returns nil if list of callbacks is empty
+	RUN_CALLBACKS_MODE_FIRST,
+	// Returns the return value of the last callback
+	// Returns nil if list of callbacks is empty
+	RUN_CALLBACKS_MODE_LAST,
+	// If any callback returns a false value, the first such is returned
+	// Otherwise, the first callback's return value (trueish) is returned
+	// Returns true if list of callbacks is empty
+	RUN_CALLBACKS_MODE_AND,
+	// Like above, but stops calling callbacks (short circuit)
+	// after seeing the first false value
+	RUN_CALLBACKS_MODE_AND_SC,
+	// If any callback returns a true value, the first such is returned
+	// Otherwise, the first callback's return value (falseish) is returned
+	// Returns false if list of callbacks is empty
+	RUN_CALLBACKS_MODE_OR,
+	// Like above, but stops calling callbacks (short circuit)
+	// after seeing the first true value
+	RUN_CALLBACKS_MODE_OR_SC,
+	// Note: "a true value" and "a false value" refer to values that
+	// are converted by lua_toboolean to true or false, respectively.
+};
 
-ScriptApi*  get_scriptapi          (lua_State *L);
 std::string script_get_backtrace   (lua_State *L);
 void        script_error           (lua_State *L, const char *fmt, ...);
+void        script_run_callbacks   (lua_State *L, int nargs,
+                                    RunCallbacksMode mode);
 
 #endif /* C_INTERNAL_H_ */
diff --git a/src/script/common/c_types.h b/src/script/common/c_types.h
index 7df869432..bc9f1cb96 100644
--- a/src/script/common/c_types.h
+++ b/src/script/common/c_types.h
@@ -50,26 +50,6 @@ class StackUnroller
 	}
 };
 
-class ModNameStorer
-{
-private:
-	lua_State *L;
-public:
-	ModNameStorer(lua_State *L_, const std::string modname):
-		L(L_)
-	{
-		// Store current modname in registry
-		lua_pushstring(L, modname.c_str());
-		lua_setfield(L, LUA_REGISTRYINDEX, "minetest_current_modname");
-	}
-	~ModNameStorer()
-	{
-		// Clear current modname in registry
-		lua_pushnil(L);
-		lua_setfield(L, LUA_REGISTRYINDEX, "minetest_current_modname");
-	}
-};
-
 class LuaError : public std::exception
 {
 public:
diff --git a/src/script/cpp_api/CMakeLists.txt b/src/script/cpp_api/CMakeLists.txt
index 6f5b51a49..b753eda17 100644
--- a/src/script/cpp_api/CMakeLists.txt
+++ b/src/script/cpp_api/CMakeLists.txt
@@ -1,4 +1,5 @@
-set(SCRIPT_CPP_API_SRCS
+# Used by server and client
+set(common_SCRIPT_CPP_API_SRCS
 	${CMAKE_CURRENT_SOURCE_DIR}/s_base.cpp
 	${CMAKE_CURRENT_SOURCE_DIR}/s_entity.cpp
 	${CMAKE_CURRENT_SOURCE_DIR}/s_env.cpp
@@ -7,5 +8,10 @@ set(SCRIPT_CPP_API_SRCS
 	${CMAKE_CURRENT_SOURCE_DIR}/s_node.cpp
 	${CMAKE_CURRENT_SOURCE_DIR}/s_nodemeta.cpp
 	${CMAKE_CURRENT_SOURCE_DIR}/s_player.cpp
-	${CMAKE_CURRENT_SOURCE_DIR}/scriptapi.cpp
+	${CMAKE_CURRENT_SOURCE_DIR}/s_server.cpp
+	PARENT_SCOPE)
+
+# Used by client only
+set(minetest_SCRIPT_CPP_API_SRCS
+	${CMAKE_CURRENT_SOURCE_DIR}/s_mainmenu.cpp
 	PARENT_SCOPE)
diff --git a/src/script/cpp_api/s_base.cpp b/src/script/cpp_api/s_base.cpp
index e2e586357..e26d54ba7 100644
--- a/src/script/cpp_api/s_base.cpp
+++ b/src/script/cpp_api/s_base.cpp
@@ -17,30 +17,141 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
 
+#include "cpp_api/s_base.h"
+#include "cpp_api/s_internal.h"
+#include "lua_api/l_object.h"
+#include "serverobject.h"
+#include "debug.h"
+#include "log.h"
+#include "mods.h"
+#include "util/string.h"
+
+
+extern "C" {
+#include "lualib.h"
+}
+
 #include <stdio.h>
 #include <cstdarg>
 
-extern "C" {
-#include "lua.h"
-#include "lauxlib.h"
+
+class ModNameStorer
+{
+private:
+	lua_State *L;
+public:
+	ModNameStorer(lua_State *L_, const std::string modname):
+		L(L_)
+	{
+		// Store current modname in registry
+		lua_pushstring(L, modname.c_str());
+		lua_setfield(L, LUA_REGISTRYINDEX, "minetest_current_modname");
+	}
+	~ModNameStorer()
+	{
+		// Clear current modname in registry
+		lua_pushnil(L);
+		lua_setfield(L, LUA_REGISTRYINDEX, "minetest_current_modname");
+	}
+};
+
+static int loadScript_ErrorHandler(lua_State *L) {
+	lua_getfield(L, LUA_GLOBALSINDEX, "debug");
+	if (!lua_istable(L, -1)) {
+		lua_pop(L, 1);
+		return 1;
+	}
+	lua_getfield(L, -1, "traceback");
+	if (!lua_isfunction(L, -1)) {
+		lua_pop(L, 2);
+		return 1;
+	}
+	lua_pushvalue(L, 1);
+	lua_pushinteger(L, 2);
+	lua_call(L, 2, 1);
+	return 1;
 }
 
-#include "cpp_api/s_base.h"
-#include "lua_api/l_object.h"
-#include "serverobject.h"
 
-ScriptApiBase::ScriptApiBase() :
-		m_luastackmutex(),
-#ifdef LOCK_DEBUG
-		m_locked(false),
-#endif
-		m_luastack(0),
-		m_server(0),
-		m_environment(0)
+/*
+	ScriptApiBase
+*/
+
+ScriptApiBase::ScriptApiBase()
 {
+	m_luastackmutex.Init();
+
+	#ifdef SCRIPTAPI_LOCK_DEBUG
+	m_locked = false;
+	#endif
 
+	m_luastack = luaL_newstate();
+	assert(m_luastack);
+
+	// Make the ScriptApiBase* accessible to ModApiBase
+	lua_pushlightuserdata(m_luastack, this);
+	lua_setfield(m_luastack, LUA_REGISTRYINDEX, "scriptapi");
+
+	m_server = 0;
+	m_environment = 0;
+	m_guiengine = 0;
 }
 
+ScriptApiBase::~ScriptApiBase()
+{
+	lua_close(m_luastack);
+}
+
+bool ScriptApiBase::loadMod(const std::string &scriptpath,
+		const std::string &modname)
+{
+	ModNameStorer modnamestorer(getStack(), modname);
+
+	if(!string_allowed(modname, MODNAME_ALLOWED_CHARS)){
+		errorstream<<"Error loading mod \""<<modname
+				<<"\": modname does not follow naming conventions: "
+				<<"Only chararacters [a-z0-9_] are allowed."<<std::endl;
+		return false;
+	}
+
+	bool success = false;
+
+	try{
+		success = loadScript(scriptpath);
+	}
+	catch(LuaError &e){
+		errorstream<<"Error loading mod \""<<modname
+				<<"\": "<<e.what()<<std::endl;
+	}
+
+	return success;
+}
+
+bool ScriptApiBase::loadScript(const std::string &scriptpath)
+{
+	verbosestream<<"Loading and running script from "<<scriptpath<<std::endl;
+
+	lua_State *L = getStack();
+
+	lua_pushcfunction(L, loadScript_ErrorHandler);
+	int errorhandler = lua_gettop(L);
+
+	int ret = luaL_loadfile(L, scriptpath.c_str()) || lua_pcall(L, 0, 0, errorhandler);
+	if(ret){
+		errorstream<<"========== ERROR FROM LUA ==========="<<std::endl;
+		errorstream<<"Failed to load and run script from "<<std::endl;
+		errorstream<<scriptpath<<":"<<std::endl;
+		errorstream<<std::endl;
+		errorstream<<lua_tostring(L, -1)<<std::endl;
+		errorstream<<std::endl;
+		errorstream<<"=======END OF ERROR FROM LUA ========"<<std::endl;
+		lua_pop(L, 1); // Pop error message from stack
+		lua_pop(L, 1); // Pop the error handler from stack
+		return false;
+	}
+	lua_pop(L, 1); // Pop the error handler from stack
+	return true;
+}
 
 void ScriptApiBase::realityCheck()
 {
@@ -52,7 +163,7 @@ void ScriptApiBase::realityCheck()
 	}
 }
 
-void  ScriptApiBase::scriptError(const char *fmt, ...)
+void ScriptApiBase::scriptError(const char *fmt, ...)
 {
 	va_list argp;
 	va_start(argp, fmt);
@@ -65,130 +176,34 @@ void  ScriptApiBase::scriptError(const char *fmt, ...)
 
 void ScriptApiBase::stackDump(std::ostream &o)
 {
-  int i;
-  int top = lua_gettop(m_luastack);
-  for (i = 1; i <= top; i++) {  /* repeat for each level */
-	int t = lua_type(m_luastack, i);
-	switch (t) {
-
-	  case LUA_TSTRING:  /* strings */
-	  	o<<"\""<<lua_tostring(m_luastack, i)<<"\"";
-		break;
-
-	  case LUA_TBOOLEAN:  /* booleans */
-		o<<(lua_toboolean(m_luastack, i) ? "true" : "false");
-		break;
-
-	  case LUA_TNUMBER:  /* numbers */ {
-	  	char buf[10];
-		snprintf(buf, 10, "%g", lua_tonumber(m_luastack, i));
-		o<<buf;
-		break; }
-
-	  default:  /* other values */
-		o<<lua_typename(m_luastack, t);
-		break;
-
-	}
-	o<<" ";
-  }
-  o<<std::endl;
-}
-
-// Push the list of callbacks (a lua table).
-// Then push nargs arguments.
-// Then call this function, which
-// - runs the callbacks
-// - removes the table and arguments from the lua stack
-// - pushes the return value, computed depending on mode
-void ScriptApiBase::runCallbacks(int nargs,RunCallbacksMode mode)
-{
-	lua_State *L = getStack();
-
-	// Insert the return value into the lua stack, below the table
-	assert(lua_gettop(L) >= nargs + 1);
-	lua_pushnil(L);
-	lua_insert(L, -(nargs + 1) - 1);
-	// Stack now looks like this:
-	// ... <return value = nil> <table> <arg#1> <arg#2> ... <arg#n>
+	int i;
+	int top = lua_gettop(m_luastack);
+	for (i = 1; i <= top; i++) {  /* repeat for each level */
+		int t = lua_type(m_luastack, i);
+		switch (t) {
 
-	int rv = lua_gettop(L) - nargs - 1;
-	int table = rv + 1;
-	int arg = table + 1;
+			case LUA_TSTRING:  /* strings */
+				o<<"\""<<lua_tostring(m_luastack, i)<<"\"";
+				break;
 
-	luaL_checktype(L, table, LUA_TTABLE);
+			case LUA_TBOOLEAN:  /* booleans */
+				o<<(lua_toboolean(m_luastack, i) ? "true" : "false");
+				break;
 
-	// Foreach
-	lua_pushnil(L);
-	bool first_loop = true;
-	while(lua_next(L, table) != 0){
-		// key at index -2 and value at index -1
-		luaL_checktype(L, -1, LUA_TFUNCTION);
-		// Call function
-		for(int i = 0; i < nargs; i++)
-			lua_pushvalue(L, arg+i);
-		if(lua_pcall(L, nargs, 1, 0))
-			scriptError("error: %s", lua_tostring(L, -1));
-
-		// Move return value to designated space in stack
-		// Or pop it
-		if(first_loop){
-			// Result of first callback is always moved
-			lua_replace(L, rv);
-			first_loop = false;
-		} else {
-			// Otherwise, what happens depends on the mode
-			if(mode == RUN_CALLBACKS_MODE_FIRST)
-				lua_pop(L, 1);
-			else if(mode == RUN_CALLBACKS_MODE_LAST)
-				lua_replace(L, rv);
-			else if(mode == RUN_CALLBACKS_MODE_AND ||
-					mode == RUN_CALLBACKS_MODE_AND_SC){
-				if((bool)lua_toboolean(L, rv) == true &&
-						(bool)lua_toboolean(L, -1) == false)
-					lua_replace(L, rv);
-				else
-					lua_pop(L, 1);
-			}
-			else if(mode == RUN_CALLBACKS_MODE_OR ||
-					mode == RUN_CALLBACKS_MODE_OR_SC){
-				if((bool)lua_toboolean(L, rv) == false &&
-						(bool)lua_toboolean(L, -1) == true)
-					lua_replace(L, rv);
-				else
-					lua_pop(L, 1);
-			}
-			else
-				assert(0);
-		}
+			case LUA_TNUMBER:  /* numbers */ {
+				char buf[10];
+				snprintf(buf, 10, "%g", lua_tonumber(m_luastack, i));
+				o<<buf;
+				break; }
 
-		// Handle short circuit modes
-		if(mode == RUN_CALLBACKS_MODE_AND_SC &&
-				(bool)lua_toboolean(L, rv) == false)
-			break;
-		else if(mode == RUN_CALLBACKS_MODE_OR_SC &&
-				(bool)lua_toboolean(L, rv) == true)
-			break;
+			default:  /* other values */
+				o<<lua_typename(m_luastack, t);
+				break;
 
-		// value removed, keep key for next iteration
-	}
-
-	// Remove stuff from stack, leaving only the return value
-	lua_settop(L, rv);
-
-	// Fix return value in case no callbacks were called
-	if(first_loop){
-		if(mode == RUN_CALLBACKS_MODE_AND ||
-				mode == RUN_CALLBACKS_MODE_AND_SC){
-			lua_pop(L, 1);
-			lua_pushboolean(L, true);
-		}
-		else if(mode == RUN_CALLBACKS_MODE_OR ||
-				mode == RUN_CALLBACKS_MODE_OR_SC){
-			lua_pop(L, 1);
-			lua_pushboolean(L, false);
 		}
+		o<<" ";
 	}
+	o<<std::endl;
 }
 
 void ScriptApiBase::addObjectReference(ServerActiveObject *cobj)
diff --git a/src/script/cpp_api/s_base.h b/src/script/cpp_api/s_base.h
index 8799d3c00..3cb59634b 100644
--- a/src/script/cpp_api/s_base.h
+++ b/src/script/cpp_api/s_base.h
@@ -21,67 +21,37 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #define S_BASE_H_
 
 #include <iostream>
+#include <string>
+
+extern "C" {
+#include <lua.h>
+}
 
 #include "irrlichttypes.h"
 #include "jmutex.h"
 #include "jmutexautolock.h"
 #include "common/c_types.h"
-#include "debug.h"
 
-#define LOCK_DEBUG
+#define SCRIPTAPI_LOCK_DEBUG
 
 class Server;
 class Environment;
+class GUIEngine;
 class ServerActiveObject;
-class LuaABM;
-class InvRef;
-class ModApiBase;
-class ModApiEnvMod;
-class ObjectRef;
-class NodeMetaRef;
-
-
-/* definitions */
-// What scriptapi_run_callbacks does with the return values of callbacks.
-// Regardless of the mode, if only one callback is defined,
-// its return value is the total return value.
-// Modes only affect the case where 0 or >= 2 callbacks are defined.
-enum RunCallbacksMode
-{
-	// Returns the return value of the first callback
-	// Returns nil if list of callbacks is empty
-	RUN_CALLBACKS_MODE_FIRST,
-	// Returns the return value of the last callback
-	// Returns nil if list of callbacks is empty
-	RUN_CALLBACKS_MODE_LAST,
-	// If any callback returns a false value, the first such is returned
-	// Otherwise, the first callback's return value (trueish) is returned
-	// Returns true if list of callbacks is empty
-	RUN_CALLBACKS_MODE_AND,
-	// Like above, but stops calling callbacks (short circuit)
-	// after seeing the first false value
-	RUN_CALLBACKS_MODE_AND_SC,
-	// If any callback returns a true value, the first such is returned
-	// Otherwise, the first callback's return value (falseish) is returned
-	// Returns false if list of callbacks is empty
-	RUN_CALLBACKS_MODE_OR,
-	// Like above, but stops calling callbacks (short circuit)
-	// after seeing the first true value
-	RUN_CALLBACKS_MODE_OR_SC,
-	// Note: "a true value" and "a false value" refer to values that
-	// are converted by lua_toboolean to true or false, respectively.
-};
-
 
 class ScriptApiBase {
 public:
 
+	ScriptApiBase();
+	virtual ~ScriptApiBase();
+
+	bool loadMod(const std::string &scriptpath, const std::string &modname);
+	bool loadScript(const std::string &scriptpath);
+
 	/* object */
 	void addObjectReference(ServerActiveObject *cobj);
 	void removeObjectReference(ServerActiveObject *cobj);
 
-	ScriptApiBase();
-
 protected:
 	friend class LuaABM;
 	friend class InvRef;
@@ -91,78 +61,35 @@ class ScriptApiBase {
 	friend class ModApiEnvMod;
 	friend class LuaVoxelManip;
 
-
-	inline lua_State* getStack()
+	lua_State* getStack()
 		{ return m_luastack; }
 
-	bool setStack(lua_State* stack) {
-		if (m_luastack == 0) {
-			m_luastack = stack;
-			return true;
-		}
-		return false;
-	}
-
 	void realityCheck();
 	void scriptError(const char *fmt, ...);
 	void stackDump(std::ostream &o);
-	void runCallbacks(int nargs,RunCallbacksMode mode);
 
-	inline Server* getServer() { return m_server; }
+	Server* getServer() { return m_server; }
 	void setServer(Server* server) { m_server = server; }
 
 	Environment* getEnv() { return m_environment; }
 	void setEnv(Environment* env) { m_environment = env; }
 
+	GUIEngine* getGuiEngine() { return m_guiengine; }
+	void setGuiEngine(GUIEngine* guiengine) { m_guiengine = guiengine; }
+
 	void objectrefGetOrCreate(ServerActiveObject *cobj);
 	void objectrefGet(u16 id);
 
-	JMutex			m_luastackmutex;
-#ifdef LOCK_DEBUG
+	JMutex          m_luastackmutex;
+#ifdef SCRIPTAPI_LOCK_DEBUG
 	bool            m_locked;
 #endif
 private:
 	lua_State*      m_luastack;
 
-	Server* 		m_server;
-	Environment*	m_environment;
-
-
-};
-
-#ifdef LOCK_DEBUG
-class LockChecker {
-public:
-	LockChecker(bool* variable) {
-		assert(*variable == false);
-
-		m_variable = variable;
-		*m_variable = true;
-	}
-	~LockChecker() {
-		*m_variable = false;
-	}
-private:
-bool* m_variable;
+	Server*         m_server;
+	Environment*    m_environment;
+	GUIEngine*      m_guiengine;
 };
 
-#define LOCK_CHECK LockChecker(&(this->m_locked))
-#else
-#define LOCK_CHECK while(0)
-#endif
-
-#define LUA_STACK_AUTOLOCK JMutexAutoLock(this->m_luastackmutex)
-
-#define SCRIPTAPI_PRECHECKHEADER                                               \
-		LUA_STACK_AUTOLOCK;                                                    \
-		LOCK_CHECK;                                                            \
-		realityCheck();                                                        \
-		lua_State *L = getStack();                                             \
-		assert(lua_checkstack(L, 20));                                         \
-		StackUnroller stack_unroller(L);
-
-#define PLAYER_TO_SA(p)   p->getEnv()->getScriptIface()
-#define ENV_TO_SA(env)    env->getScriptIface()
-#define SERVER_TO_SA(srv) srv->getScriptIface()
-
 #endif /* S_BASE_H_ */
diff --git a/src/script/cpp_api/s_entity.cpp b/src/script/cpp_api/s_entity.cpp
index c494e8232..cefa27cb1 100644
--- a/src/script/cpp_api/s_entity.cpp
+++ b/src/script/cpp_api/s_entity.cpp
@@ -18,15 +18,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 */
 
 #include "cpp_api/s_entity.h"
+#include "cpp_api/s_internal.h"
 #include "log.h"
 #include "object_properties.h"
 #include "common/c_converter.h"
 #include "common/c_content.h"
 
-extern "C" {
-#include "lauxlib.h"
-}
-
 bool ScriptApiEntity::luaentity_Add(u16 id, const char *name)
 {
 	SCRIPTAPI_PRECHECKHEADER
diff --git a/src/script/cpp_api/s_env.cpp b/src/script/cpp_api/s_env.cpp
index 632b28f45..ef3a1dddf 100644
--- a/src/script/cpp_api/s_env.cpp
+++ b/src/script/cpp_api/s_env.cpp
@@ -18,16 +18,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 */
 
 #include "cpp_api/s_env.h"
+#include "cpp_api/s_internal.h"
 #include "common/c_converter.h"
 #include "log.h"
 #include "environment.h"
 #include "mapgen.h"
 #include "lua_api/l_env.h"
 
-extern "C" {
-#include "lauxlib.h"
-}
-
 void ScriptApiEnv::environment_OnGenerated(v3s16 minp, v3s16 maxp,
 		u32 blockseed)
 {
@@ -40,7 +37,7 @@ void ScriptApiEnv::environment_OnGenerated(v3s16 minp, v3s16 maxp,
 	push_v3s16(L, minp);
 	push_v3s16(L, maxp);
 	lua_pushnumber(L, blockseed);
-	runCallbacks(3, RUN_CALLBACKS_MODE_FIRST);
+	script_run_callbacks(L, 3, RUN_CALLBACKS_MODE_FIRST);
 }
 
 void ScriptApiEnv::environment_Step(float dtime)
@@ -53,7 +50,7 @@ void ScriptApiEnv::environment_Step(float dtime)
 	lua_getfield(L, -1, "registered_globalsteps");
 	// Call callbacks
 	lua_pushnumber(L, dtime);
-	runCallbacks(1, RUN_CALLBACKS_MODE_FIRST);
+	script_run_callbacks(L, 1, RUN_CALLBACKS_MODE_FIRST);
 }
 
 void ScriptApiEnv::environment_OnMapgenInit(MapgenParams *mgparams)
@@ -80,7 +77,7 @@ void ScriptApiEnv::environment_OnMapgenInit(MapgenParams *mgparams)
 	lua_pushstring(L, flagstr.c_str());
 	lua_setfield(L, -2, "flags");
 	
-	runCallbacks(1, RUN_CALLBACKS_MODE_FIRST);
+	script_run_callbacks(L, 1, RUN_CALLBACKS_MODE_FIRST);
 }
 
 void ScriptApiEnv::initializeEnvironment(ServerEnvironment *env)
diff --git a/src/script/cpp_api/s_internal.h b/src/script/cpp_api/s_internal.h
new file mode 100644
index 000000000..10ee1a7de
--- /dev/null
+++ b/src/script/cpp_api/s_internal.h
@@ -0,0 +1,63 @@
+/*
+Minetest
+Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+/******************************************************************************/
+/******************************************************************************/
+/* WARNING!!!! do NOT add this header in any include file or any code file    */
+/*             not being a modapi file!!!!!!!!                                */
+/******************************************************************************/
+/******************************************************************************/
+
+#ifndef S_INTERNAL_H_
+#define S_INTERNAL_H_
+
+#include "common/c_internal.h"
+#include "cpp_api/s_base.h"
+
+#ifdef SCRIPTAPI_LOCK_DEBUG
+#include "debug.h" // assert()
+class LockChecker {
+public:
+	LockChecker(bool* variable) {
+		assert(*variable == false);
+
+		m_variable = variable;
+		*m_variable = true;
+	}
+	~LockChecker() {
+		*m_variable = false;
+	}
+private:
+bool* m_variable;
+};
+
+#define SCRIPTAPI_LOCK_CHECK LockChecker(&(this->m_locked))
+#else
+#define SCRIPTAPI_LOCK_CHECK while(0)
+#endif
+
+#define SCRIPTAPI_PRECHECKHEADER                                               \
+		JMutexAutoLock(this->m_luastackmutex);                                 \
+		SCRIPTAPI_LOCK_CHECK;                                                  \
+		realityCheck();                                                        \
+		lua_State *L = getStack();                                             \
+		assert(lua_checkstack(L, 20));                                         \
+		StackUnroller stack_unroller(L);
+
+#endif /* S_INTERNAL_H_ */
diff --git a/src/script/cpp_api/s_inventory.cpp b/src/script/cpp_api/s_inventory.cpp
index 2402d198c..09f26d80c 100644
--- a/src/script/cpp_api/s_inventory.cpp
+++ b/src/script/cpp_api/s_inventory.cpp
@@ -18,6 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 */
 
 #include "cpp_api/s_inventory.h"
+#include "cpp_api/s_internal.h"
 #include "inventorymanager.h"
 #include "lua_api/l_inventory.h"
 #include "lua_api/l_item.h"
diff --git a/src/script/cpp_api/s_item.cpp b/src/script/cpp_api/s_item.cpp
index 6937ebbeb..b4536ac63 100644
--- a/src/script/cpp_api/s_item.cpp
+++ b/src/script/cpp_api/s_item.cpp
@@ -18,10 +18,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 */
 
 #include "cpp_api/s_item.h"
+#include "cpp_api/s_internal.h"
 #include "common/c_converter.h"
 #include "common/c_content.h"
 #include "lua_api/l_item.h"
 #include "server.h"
+#include "log.h"
+#include "util/pointedthing.h"
 
 bool ScriptApiItem::item_OnDrop(ItemStack &item,
 		ServerActiveObject *dropper, v3f pos)
diff --git a/src/script/cpp_api/s_mainmenu.cpp b/src/script/cpp_api/s_mainmenu.cpp
new file mode 100644
index 000000000..af92c59a9
--- /dev/null
+++ b/src/script/cpp_api/s_mainmenu.cpp
@@ -0,0 +1,80 @@
+/*
+Minetest
+Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "cpp_api/s_mainmenu.h"
+#include "cpp_api/s_internal.h"
+#include "common/c_converter.h"
+
+void ScriptApiMainMenu::setMainMenuErrorMessage(std::string errormessage)
+{
+	SCRIPTAPI_PRECHECKHEADER
+
+	lua_getglobal(L, "gamedata");
+	int gamedata_idx = lua_gettop(L);
+	lua_pushstring(L, "errormessage");
+	lua_pushstring(L, errormessage.c_str());
+	lua_settable(L, gamedata_idx);
+	lua_pop(L, 1);
+}
+
+void ScriptApiMainMenu::handleMainMenuEvent(std::string text)
+{
+	SCRIPTAPI_PRECHECKHEADER
+
+	// Get handler function
+	lua_getglobal(L, "engine");
+	lua_getfield(L, -1, "event_handler");
+	if(lua_isnil(L, -1))
+		return;
+	luaL_checktype(L, -1, LUA_TFUNCTION);
+
+	// Call it
+	lua_pushstring(L, text.c_str());
+	if(lua_pcall(L, 1, 0, 0))
+		scriptError("error running function engine.event_handler: %s\n",
+				lua_tostring(L, -1));
+}
+
+void ScriptApiMainMenu::handleMainMenuButtons(std::map<std::string, std::string> fields)
+{
+	SCRIPTAPI_PRECHECKHEADER
+
+	// Get handler function
+	lua_getglobal(L, "engine");
+	lua_getfield(L, -1, "button_handler");
+	if(lua_isnil(L, -1))
+		return;
+	luaL_checktype(L, -1, LUA_TFUNCTION);
+
+	// Convert fields to lua table
+	lua_newtable(L);
+	for(std::map<std::string, std::string>::const_iterator
+		i = fields.begin(); i != fields.end(); i++){
+		const std::string &name = i->first;
+		const std::string &value = i->second;
+		lua_pushstring(L, name.c_str());
+		lua_pushlstring(L, value.c_str(), value.size());
+		lua_settable(L, -3);
+	}
+
+	// Call it
+	if(lua_pcall(L, 1, 0, 0))
+		scriptError("error running function engine.button_handler: %s\n",
+				lua_tostring(L, -1));
+}
diff --git a/src/script/cpp_api/s_mainmenu.h b/src/script/cpp_api/s_mainmenu.h
new file mode 100644
index 000000000..53dcd37e9
--- /dev/null
+++ b/src/script/cpp_api/s_mainmenu.h
@@ -0,0 +1,49 @@
+/*
+Minetest
+Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef S_MAINMENU_H_
+#define S_MAINMENU_H_
+
+#include "cpp_api/s_base.h"
+#include <map>
+
+class ScriptApiMainMenu
+		: virtual public ScriptApiBase
+{
+public:
+	/**
+	 * set gamedata.errormessage to inform lua of an error
+	 * @param errormessage the error message
+	 */
+	void setMainMenuErrorMessage(std::string errormessage);
+
+	/**
+	 * process events received from formspec
+	 * @param text events in textual form
+	 */
+	void handleMainMenuEvent(std::string text);
+
+	/**
+	 * process field data recieved from formspec
+	 * @param fields data in field format
+	 */
+	void handleMainMenuButtons(std::map<std::string, std::string> fields);
+};
+
+#endif /* S_MAINMENU_H_ */
diff --git a/src/script/cpp_api/s_node.cpp b/src/script/cpp_api/s_node.cpp
index d0b0583c0..92fd00a74 100644
--- a/src/script/cpp_api/s_node.cpp
+++ b/src/script/cpp_api/s_node.cpp
@@ -18,10 +18,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 */
 
 #include "cpp_api/s_node.h"
+#include "cpp_api/s_internal.h"
 #include "common/c_converter.h"
 #include "common/c_content.h"
 #include "nodedef.h"
 #include "server.h"
+#include "environment.h"
 
 
 struct EnumString ScriptApiNode::es_DrawType[] =
diff --git a/src/script/cpp_api/s_nodemeta.cpp b/src/script/cpp_api/s_nodemeta.cpp
index 56cea8e5f..e87464c61 100644
--- a/src/script/cpp_api/s_nodemeta.cpp
+++ b/src/script/cpp_api/s_nodemeta.cpp
@@ -18,16 +18,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 */
 
 #include "cpp_api/s_nodemeta.h"
+#include "cpp_api/s_internal.h"
 #include "common/c_converter.h"
 #include "nodedef.h"
 #include "mapnode.h"
 #include "server.h"
+#include "environment.h"
 #include "lua_api/l_item.h"
 
-extern "C" {
-#include "lauxlib.h"
-}
-
 // Return number of accepted items to be moved
 int ScriptApiNodemeta::nodemeta_inventory_AllowMove(v3s16 p,
 		const std::string &from_list, int from_index,
diff --git a/src/script/cpp_api/s_player.cpp b/src/script/cpp_api/s_player.cpp
index 0dbd52527..215a34d53 100644
--- a/src/script/cpp_api/s_player.cpp
+++ b/src/script/cpp_api/s_player.cpp
@@ -18,6 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 */
 
 #include "cpp_api/s_player.h"
+#include "cpp_api/s_internal.h"
 
 void ScriptApiPlayer::on_newplayer(ServerActiveObject *player)
 {
@@ -28,7 +29,7 @@ void ScriptApiPlayer::on_newplayer(ServerActiveObject *player)
 	lua_getfield(L, -1, "registered_on_newplayers");
 	// Call callbacks
 	objectrefGetOrCreate(player);
-	runCallbacks(1, RUN_CALLBACKS_MODE_FIRST);
+	script_run_callbacks(L, 1, RUN_CALLBACKS_MODE_FIRST);
 }
 
 void ScriptApiPlayer::on_dieplayer(ServerActiveObject *player)
@@ -40,7 +41,7 @@ void ScriptApiPlayer::on_dieplayer(ServerActiveObject *player)
 	lua_getfield(L, -1, "registered_on_dieplayers");
 	// Call callbacks
 	objectrefGetOrCreate(player);
-	runCallbacks(1, RUN_CALLBACKS_MODE_FIRST);
+	script_run_callbacks(L, 1, RUN_CALLBACKS_MODE_FIRST);
 }
 
 bool ScriptApiPlayer::on_respawnplayer(ServerActiveObject *player)
@@ -52,7 +53,7 @@ bool ScriptApiPlayer::on_respawnplayer(ServerActiveObject *player)
 	lua_getfield(L, -1, "registered_on_respawnplayers");
 	// Call callbacks
 	objectrefGetOrCreate(player);
-	runCallbacks(1, RUN_CALLBACKS_MODE_OR);
+	script_run_callbacks(L, 1, RUN_CALLBACKS_MODE_OR);
 	bool positioning_handled_by_some = lua_toboolean(L, -1);
 	return positioning_handled_by_some;
 }
@@ -66,7 +67,7 @@ void ScriptApiPlayer::on_joinplayer(ServerActiveObject *player)
 	lua_getfield(L, -1, "registered_on_joinplayers");
 	// Call callbacks
 	objectrefGetOrCreate(player);
-	runCallbacks(1, RUN_CALLBACKS_MODE_FIRST);
+	script_run_callbacks(L, 1, RUN_CALLBACKS_MODE_FIRST);
 }
 
 void ScriptApiPlayer::on_leaveplayer(ServerActiveObject *player)
@@ -78,7 +79,7 @@ void ScriptApiPlayer::on_leaveplayer(ServerActiveObject *player)
 	lua_getfield(L, -1, "registered_on_leaveplayers");
 	// Call callbacks
 	objectrefGetOrCreate(player);
-	runCallbacks(1, RUN_CALLBACKS_MODE_FIRST);
+	script_run_callbacks(L, 1, RUN_CALLBACKS_MODE_FIRST);
 }
 
 void ScriptApiPlayer::on_cheat(ServerActiveObject *player,
@@ -94,7 +95,7 @@ void ScriptApiPlayer::on_cheat(ServerActiveObject *player,
 	lua_newtable(L);
 	lua_pushlstring(L, cheat_type.c_str(), cheat_type.size());
 	lua_setfield(L, -2, "type");
-	runCallbacks(2, RUN_CALLBACKS_MODE_FIRST);
+	script_run_callbacks(L, 2, RUN_CALLBACKS_MODE_FIRST);
 }
 
 void ScriptApiPlayer::on_playerReceiveFields(ServerActiveObject *player,
@@ -121,7 +122,7 @@ void ScriptApiPlayer::on_playerReceiveFields(ServerActiveObject *player,
 		lua_pushlstring(L, value.c_str(), value.size());
 		lua_settable(L, -3);
 	}
-	runCallbacks(3, RUN_CALLBACKS_MODE_OR_SC);
+	script_run_callbacks(L, 3, RUN_CALLBACKS_MODE_OR_SC);
 }
 ScriptApiPlayer::~ScriptApiPlayer() {
 }
diff --git a/src/script/cpp_api/s_player.h b/src/script/cpp_api/s_player.h
index c0409a481..88221f486 100644
--- a/src/script/cpp_api/s_player.h
+++ b/src/script/cpp_api/s_player.h
@@ -20,6 +20,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #ifndef S_PLAYER_H_
 #define S_PLAYER_H_
 
+#include <map>
+
 #include "cpp_api/s_base.h"
 
 
diff --git a/src/script/cpp_api/s_server.cpp b/src/script/cpp_api/s_server.cpp
new file mode 100644
index 000000000..d41805b7b
--- /dev/null
+++ b/src/script/cpp_api/s_server.cpp
@@ -0,0 +1,151 @@
+/*
+Minetest
+Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "cpp_api/s_server.h"
+#include "cpp_api/s_internal.h"
+#include "common/c_converter.h"
+
+bool ScriptApiServer::getAuth(const std::string &playername,
+		std::string *dst_password,
+		std::set<std::string> *dst_privs)
+{
+	SCRIPTAPI_PRECHECKHEADER
+
+	getAuthHandler();
+	lua_getfield(L, -1, "get_auth");
+	if(lua_type(L, -1) != LUA_TFUNCTION)
+		throw LuaError(L, "Authentication handler missing get_auth");
+	lua_pushstring(L, playername.c_str());
+	if(lua_pcall(L, 1, 1, 0))
+		scriptError("error: %s", lua_tostring(L, -1));
+
+	// nil = login not allowed
+	if(lua_isnil(L, -1))
+		return false;
+	luaL_checktype(L, -1, LUA_TTABLE);
+
+	std::string password;
+	bool found = getstringfield(L, -1, "password", password);
+	if(!found)
+		throw LuaError(L, "Authentication handler didn't return password");
+	if(dst_password)
+		*dst_password = password;
+
+	lua_getfield(L, -1, "privileges");
+	if(!lua_istable(L, -1))
+		throw LuaError(L,
+				"Authentication handler didn't return privilege table");
+	if(dst_privs)
+		readPrivileges(-1, *dst_privs);
+	lua_pop(L, 1);
+
+	return true;
+}
+
+void ScriptApiServer::getAuthHandler()
+{
+	lua_State *L = getStack();
+
+	lua_getglobal(L, "minetest");
+	lua_getfield(L, -1, "registered_auth_handler");
+	if(lua_isnil(L, -1)){
+		lua_pop(L, 1);
+		lua_getfield(L, -1, "builtin_auth_handler");
+	}
+	if(lua_type(L, -1) != LUA_TTABLE)
+		throw LuaError(L, "Authentication handler table not valid");
+}
+
+void ScriptApiServer::readPrivileges(int index, std::set<std::string> &result)
+{
+	lua_State *L = getStack();
+
+	result.clear();
+	lua_pushnil(L);
+	if(index < 0)
+		index -= 1;
+	while(lua_next(L, index) != 0){
+		// key at index -2 and value at index -1
+		std::string key = luaL_checkstring(L, -2);
+		bool value = lua_toboolean(L, -1);
+		if(value)
+			result.insert(key);
+		// removes value, keeps key for next iteration
+		lua_pop(L, 1);
+	}
+}
+
+void ScriptApiServer::createAuth(const std::string &playername,
+		const std::string &password)
+{
+	SCRIPTAPI_PRECHECKHEADER
+
+	getAuthHandler();
+	lua_getfield(L, -1, "create_auth");
+	if(lua_type(L, -1) != LUA_TFUNCTION)
+		throw LuaError(L, "Authentication handler missing create_auth");
+	lua_pushstring(L, playername.c_str());
+	lua_pushstring(L, password.c_str());
+	if(lua_pcall(L, 2, 0, 0))
+		scriptError("error: %s", lua_tostring(L, -1));
+}
+
+bool ScriptApiServer::setPassword(const std::string &playername,
+		const std::string &password)
+{
+	SCRIPTAPI_PRECHECKHEADER
+
+	getAuthHandler();
+	lua_getfield(L, -1, "set_password");
+	if(lua_type(L, -1) != LUA_TFUNCTION)
+		throw LuaError(L, "Authentication handler missing set_password");
+	lua_pushstring(L, playername.c_str());
+	lua_pushstring(L, password.c_str());
+	if(lua_pcall(L, 2, 1, 0))
+		scriptError("error: %s", lua_tostring(L, -1));
+	return lua_toboolean(L, -1);
+}
+
+bool ScriptApiServer::on_chat_message(const std::string &name,
+		const std::string &message)
+{
+	SCRIPTAPI_PRECHECKHEADER
+
+	// Get minetest.registered_on_chat_messages
+	lua_getglobal(L, "minetest");
+	lua_getfield(L, -1, "registered_on_chat_messages");
+	// Call callbacks
+	lua_pushstring(L, name.c_str());
+	lua_pushstring(L, message.c_str());
+	script_run_callbacks(L, 2, RUN_CALLBACKS_MODE_OR_SC);
+	bool ate = lua_toboolean(L, -1);
+	return ate;
+}
+
+void ScriptApiServer::on_shutdown()
+{
+	SCRIPTAPI_PRECHECKHEADER
+
+	// Get registered shutdown hooks
+	lua_getglobal(L, "minetest");
+	lua_getfield(L, -1, "registered_on_shutdown");
+	// Call callbacks
+	script_run_callbacks(L, 0, RUN_CALLBACKS_MODE_FIRST);
+}
+
diff --git a/src/script/cpp_api/s_server.h b/src/script/cpp_api/s_server.h
new file mode 100644
index 000000000..a63e36320
--- /dev/null
+++ b/src/script/cpp_api/s_server.h
@@ -0,0 +1,52 @@
+/*
+Minetest
+Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef S_SERVER_H_
+#define S_SERVER_H_
+
+#include "cpp_api/s_base.h"
+#include <set>
+
+class ScriptApiServer
+		: virtual public ScriptApiBase
+{
+public:
+	// Calls on_chat_message handlers
+	// Returns true if script handled message
+	bool on_chat_message(const std::string &name, const std::string &message);
+
+	// Calls on_shutdown handlers
+	void on_shutdown();
+
+	/* auth */
+	bool getAuth(const std::string &playername,
+			std::string *dst_password,
+			std::set<std::string> *dst_privs);
+	void createAuth(const std::string &playername,
+			const std::string &password);
+	bool setPassword(const std::string &playername,
+			const std::string &password);
+private:
+	void getAuthHandler();
+	void readPrivileges(int index, std::set<std::string> &result);
+};
+
+
+
+#endif /* S_SERVER_H_ */
diff --git a/src/script/cpp_api/scriptapi.cpp b/src/script/cpp_api/scriptapi.cpp
deleted file mode 100644
index b6d376b1f..000000000
--- a/src/script/cpp_api/scriptapi.cpp
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
-Minetest
-Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU Lesser General Public License as published by
-the Free Software Foundation; either version 2.1 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public License along
-with this program; if not, write to the Free Software Foundation, Inc.,
-51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-*/
-
-extern "C" {
-#include "lua.h"
-#include "lauxlib.h"
-#include "lualib.h"
-}
-
-
-#include "scriptapi.h"
-#include "common/c_converter.h"
-#include "lua_api/l_base.h"
-#include "log.h"
-#include "mods.h"
-
-int script_ErrorHandler(lua_State *L) {
-	lua_getfield(L, LUA_GLOBALSINDEX, "debug");
-	if (!lua_istable(L, -1)) {
-		lua_pop(L, 1);
-		return 1;
-	}
-	lua_getfield(L, -1, "traceback");
-	if (!lua_isfunction(L, -1)) {
-		lua_pop(L, 2);
-		return 1;
-	}
-	lua_pushvalue(L, 1);
-	lua_pushinteger(L, 2);
-	lua_call(L, 2, 1);
-	return 1;
-}
-
-
-bool ScriptApi::getAuth(const std::string &playername,
-		std::string *dst_password, std::set<std::string> *dst_privs)
-{
-	SCRIPTAPI_PRECHECKHEADER
-
-	getAuthHandler();
-	lua_getfield(L, -1, "get_auth");
-	if(lua_type(L, -1) != LUA_TFUNCTION)
-		throw LuaError(L, "Authentication handler missing get_auth");
-	lua_pushstring(L, playername.c_str());
-	if(lua_pcall(L, 1, 1, 0))
-		scriptError("error: %s", lua_tostring(L, -1));
-
-	// nil = login not allowed
-	if(lua_isnil(L, -1))
-		return false;
-	luaL_checktype(L, -1, LUA_TTABLE);
-
-	std::string password;
-	bool found = getstringfield(L, -1, "password", password);
-	if(!found)
-		throw LuaError(L, "Authentication handler didn't return password");
-	if(dst_password)
-		*dst_password = password;
-
-	lua_getfield(L, -1, "privileges");
-	if(!lua_istable(L, -1))
-		throw LuaError(L,
-				"Authentication handler didn't return privilege table");
-	if(dst_privs)
-		readPrivileges(-1, *dst_privs);
-	lua_pop(L, 1);
-
-	return true;
-}
-
-void ScriptApi::getAuthHandler()
-{
-	lua_State *L = getStack();
-
-	lua_getglobal(L, "minetest");
-	lua_getfield(L, -1, "registered_auth_handler");
-	if(lua_isnil(L, -1)){
-		lua_pop(L, 1);
-		lua_getfield(L, -1, "builtin_auth_handler");
-	}
-	if(lua_type(L, -1) != LUA_TTABLE)
-		throw LuaError(L, "Authentication handler table not valid");
-}
-
-void ScriptApi::readPrivileges(int index,std::set<std::string> &result)
-{
-	lua_State *L = getStack();
-
-	result.clear();
-	lua_pushnil(L);
-	if(index < 0)
-		index -= 1;
-	while(lua_next(L, index) != 0){
-		// key at index -2 and value at index -1
-		std::string key = luaL_checkstring(L, -2);
-		bool value = lua_toboolean(L, -1);
-		if(value)
-			result.insert(key);
-		// removes value, keeps key for next iteration
-		lua_pop(L, 1);
-	}
-}
-
-void ScriptApi::createAuth(const std::string &playername,
-		const std::string &password)
-{
-	SCRIPTAPI_PRECHECKHEADER
-
-	getAuthHandler();
-	lua_getfield(L, -1, "create_auth");
-	if(lua_type(L, -1) != LUA_TFUNCTION)
-		throw LuaError(L, "Authentication handler missing create_auth");
-	lua_pushstring(L, playername.c_str());
-	lua_pushstring(L, password.c_str());
-	if(lua_pcall(L, 2, 0, 0))
-		scriptError("error: %s", lua_tostring(L, -1));
-}
-
-bool ScriptApi::setPassword(const std::string &playername,
-		const std::string &password)
-{
-	SCRIPTAPI_PRECHECKHEADER
-
-	getAuthHandler();
-	lua_getfield(L, -1, "set_password");
-	if(lua_type(L, -1) != LUA_TFUNCTION)
-		throw LuaError(L, "Authentication handler missing set_password");
-	lua_pushstring(L, playername.c_str());
-	lua_pushstring(L, password.c_str());
-	if(lua_pcall(L, 2, 1, 0))
-		scriptError("error: %s", lua_tostring(L, -1));
-	return lua_toboolean(L, -1);
-}
-
-bool ScriptApi::on_chat_message(const std::string &name,
-		const std::string &message)
-{
-	SCRIPTAPI_PRECHECKHEADER
-
-	// Get minetest.registered_on_chat_messages
-	lua_getglobal(L, "minetest");
-	lua_getfield(L, -1, "registered_on_chat_messages");
-	// Call callbacks
-	lua_pushstring(L, name.c_str());
-	lua_pushstring(L, message.c_str());
-	runCallbacks(2, RUN_CALLBACKS_MODE_OR_SC);
-	bool ate = lua_toboolean(L, -1);
-	return ate;
-}
-
-void ScriptApi::on_shutdown()
-{
-	SCRIPTAPI_PRECHECKHEADER
-
-	// Get registered shutdown hooks
-	lua_getglobal(L, "minetest");
-	lua_getfield(L, -1, "registered_on_shutdown");
-	// Call callbacks
-	runCallbacks(0, RUN_CALLBACKS_MODE_FIRST);
-}
-
-bool ScriptApi::loadMod(const std::string &scriptpath,const std::string &modname)
-{
-	ModNameStorer modnamestorer(getStack(), modname);
-
-	if(!string_allowed(modname, MODNAME_ALLOWED_CHARS)){
-		errorstream<<"Error loading mod \""<<modname
-				<<"\": modname does not follow naming conventions: "
-				<<"Only chararacters [a-z0-9_] are allowed."<<std::endl;
-		return false;
-	}
-
-	bool success = false;
-
-	try{
-		success = scriptLoad(scriptpath.c_str());
-	}
-	catch(LuaError &e){
-		errorstream<<"Error loading mod \""<<modname
-				<<"\": "<<e.what()<<std::endl;
-	}
-
-	return success;
-}
-
-ScriptApi::ScriptApi() {
-	assert("Invalid call to default constructor of scriptapi!" == 0);
-}
-
-ScriptApi::ScriptApi(Server* server)
-{
-
-	setServer(server);
-	setStack(luaL_newstate());
-	assert(getStack());
-
-	//TODO add security
-
-	luaL_openlibs(getStack());
-
-	SCRIPTAPI_PRECHECKHEADER
-
-	lua_pushlightuserdata(L, this);
-	lua_setfield(L, LUA_REGISTRYINDEX, "scriptapi");
-
-	lua_newtable(L);
-	lua_setglobal(L, "minetest");
-
-
-	for (std::vector<ModApiBase*>::iterator i = m_mod_api_modules->begin();
-			i != m_mod_api_modules->end(); i++) {
-		//initializers are called within minetest global table!
-		lua_getglobal(L, "minetest");
-		int top = lua_gettop(L);
-		bool ModInitializedSuccessfull = (*i)->Initialize(L,top);
-		assert(ModInitializedSuccessfull);
-	}
-
-	infostream << "SCRIPTAPI: initialized " << m_mod_api_modules->size()
-													<< " modules" << std::endl;
-
-	// Get the main minetest table
-	lua_getglobal(L, "minetest");
-
-	// Add tables to minetest
-	lua_newtable(L);
-	lua_setfield(L, -2, "object_refs");
-
-	lua_newtable(L);
-	lua_setfield(L, -2, "luaentities");
-}
-
-ScriptApi::~ScriptApi() {
-	lua_close(getStack());
-}
-
-bool ScriptApi::scriptLoad(const char *path)
-{
-	lua_State* L = getStack();
-	setStack(0);
-
-	verbosestream<<"Loading and running script from "<<path<<std::endl;
-
-	lua_pushcfunction(L, script_ErrorHandler);
-	int errorhandler = lua_gettop(L);
-
-	int ret = luaL_loadfile(L, path) || lua_pcall(L, 0, 0, errorhandler);
-	if(ret){
-		errorstream<<"========== ERROR FROM LUA ==========="<<std::endl;
-		errorstream<<"Failed to load and run script from "<<std::endl;
-		errorstream<<path<<":"<<std::endl;
-		errorstream<<std::endl;
-		errorstream<<lua_tostring(L, -1)<<std::endl;
-		errorstream<<std::endl;
-		errorstream<<"=======END OF ERROR FROM LUA ========"<<std::endl;
-		lua_pop(L, 1); // Pop error message from stack
-		lua_pop(L, 1); // Pop the error handler from stack
-		return false;
-	}
-	lua_pop(L, 1); // Pop the error handler from stack
-	return true;
-}
-
-bool ScriptApi::registerModApiModule(ModApiBase* ptr) {
-	if (ScriptApi::m_mod_api_modules == 0)
-		ScriptApi::m_mod_api_modules = new std::vector<ModApiBase*>();
-
-	assert(ScriptApi::m_mod_api_modules != 0);
-
-	ScriptApi::m_mod_api_modules->push_back(ptr);
-
-	return true;
-}
-
-std::vector<ModApiBase*>* ScriptApi::m_mod_api_modules = 0;
diff --git a/src/script/lua_api/CMakeLists.txt b/src/script/lua_api/CMakeLists.txt
index f67cf6886..d75c04335 100644
--- a/src/script/lua_api/CMakeLists.txt
+++ b/src/script/lua_api/CMakeLists.txt
@@ -1,14 +1,23 @@
-set(SCRIPT_LUA_API_SRCS
+# Used by server and client
+set(common_SCRIPT_LUA_API_SRCS
 	${CMAKE_CURRENT_SOURCE_DIR}/l_base.cpp
 	${CMAKE_CURRENT_SOURCE_DIR}/l_craft.cpp
 	${CMAKE_CURRENT_SOURCE_DIR}/l_env.cpp
 	${CMAKE_CURRENT_SOURCE_DIR}/l_inventory.cpp
 	${CMAKE_CURRENT_SOURCE_DIR}/l_item.cpp
-	${CMAKE_CURRENT_SOURCE_DIR}/luaapi.cpp
+	${CMAKE_CURRENT_SOURCE_DIR}/l_mapgen.cpp
 	${CMAKE_CURRENT_SOURCE_DIR}/l_nodemeta.cpp
 	${CMAKE_CURRENT_SOURCE_DIR}/l_nodetimer.cpp
 	${CMAKE_CURRENT_SOURCE_DIR}/l_noise.cpp
 	${CMAKE_CURRENT_SOURCE_DIR}/l_object.cpp
 	${CMAKE_CURRENT_SOURCE_DIR}/l_particles.cpp
+	${CMAKE_CURRENT_SOURCE_DIR}/l_rollback.cpp
+	${CMAKE_CURRENT_SOURCE_DIR}/l_server.cpp
+	${CMAKE_CURRENT_SOURCE_DIR}/l_util.cpp
 	${CMAKE_CURRENT_SOURCE_DIR}/l_vmanip.cpp
 	PARENT_SCOPE)
+
+# Used by client only
+set(minetest_SCRIPT_LUA_API_SRCS
+	${CMAKE_CURRENT_SOURCE_DIR}/l_mainmenu.cpp
+	PARENT_SCOPE)
diff --git a/src/script/lua_api/l_base.cpp b/src/script/lua_api/l_base.cpp
index b1766e6df..b8d673ee4 100644
--- a/src/script/lua_api/l_base.cpp
+++ b/src/script/lua_api/l_base.cpp
@@ -17,32 +17,35 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
 
-#include "cpp_api/scriptapi.h"
 #include "lua_api/l_base.h"
-#include "common/c_internal.h"
-#include "log.h"
-
-extern "C" {
-#include "lua.h"
+#include "lua_api/l_internal.h"
+#include "cpp_api/s_base.h"
+
+ScriptApiBase* ModApiBase::getScriptApiBase(lua_State *L) {
+	// Get server from registry
+	lua_getfield(L, LUA_REGISTRYINDEX, "scriptapi");
+	ScriptApiBase *sapi_ptr = (ScriptApiBase*) lua_touserdata(L, -1);
+	lua_pop(L, 1);
+	return sapi_ptr;
 }
 
-ModApiBase::ModApiBase() {
-	ScriptApi::registerModApiModule(this);
+Server* ModApiBase::getServer(lua_State *L) {
+	return getScriptApiBase(L)->getServer();
 }
 
-Server* ModApiBase::getServer(lua_State* L) {
-	return get_scriptapi(L)->getServer();
+Environment* ModApiBase::getEnv(lua_State *L) {
+	return getScriptApiBase(L)->getEnv();
 }
 
-Environment* ModApiBase::getEnv(lua_State* L) {
-	return get_scriptapi(L)->getEnv();
+GUIEngine* ModApiBase::getGuiEngine(lua_State *L) {
+	return getScriptApiBase(L)->getGuiEngine();
 }
 
-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 fct,
+		int top
+		) {
 	//TODO check presence first!
 
 	lua_pushstring(L,name);
@@ -51,13 +54,3 @@ bool ModApiBase::registerFunction(	lua_State* L,
 
 	return true;
 }
-
-struct EnumString es_BiomeTerrainType[] =
-{
-	{BIOME_TERRAIN_NORMAL, "normal"},
-	{BIOME_TERRAIN_LIQUID, "liquid"},
-	{BIOME_TERRAIN_NETHER, "nether"},
-	{BIOME_TERRAIN_AETHER, "aether"},
-	{BIOME_TERRAIN_FLAT,   "flat"},
-	{0, NULL},
-};
diff --git a/src/script/lua_api/l_base.h b/src/script/lua_api/l_base.h
index f2e0d59a9..71ebd215c 100644
--- a/src/script/lua_api/l_base.h
+++ b/src/script/lua_api/l_base.h
@@ -20,44 +20,43 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #ifndef L_BASE_H_
 #define L_BASE_H_
 
-#include "biome.h"
 #include "common/c_types.h"
 
 extern "C" {
-#include "lua.h"
+#include <lua.h>
+#include <lauxlib.h>
 }
 
-extern struct EnumString es_BiomeTerrainType[];
-
-class ScriptApi;
+class ScriptApiBase;
 class Server;
 class Environment;
+class GUIEngine;
 
-typedef class ModApiBase {
-
-public:
-	ModApiBase();
-
-	virtual bool Initialize(lua_State* L, int top) = 0;
-	virtual ~ModApiBase() {};
+class ModApiBase {
 
 protected:
-	static Server* getServer(      lua_State* L);
-	static Environment* getEnv(    lua_State* L);
-	static bool registerFunction(	lua_State* L,
-									const char* name,
-									lua_CFunction fct,
-									int top
-									);
-} ModApiBase;
-
-#if (defined(WIN32) || defined(_WIN32_WCE))
-#define NO_MAP_LOCK_REQUIRED
-#else
-#include "main.h"
-#include "profiler.h"
-#define NO_MAP_LOCK_REQUIRED ScopeProfiler nolocktime(g_profiler,"Scriptapi: unlockable time",SPT_ADD)
-//#define NO_ENVLOCK_REQUIRED assert(getServer(L).m_env_mutex.IsLocked() == false)
-#endif
+	static ScriptApiBase*   getScriptApiBase(lua_State *L);
+	static Server*          getServer(lua_State *L);
+	static Environment*     getEnv(lua_State *L);
+	static GUIEngine*       getGuiEngine(lua_State *L);
+
+	// Get an arbitrary subclass of ScriptApiBase
+	// by using dynamic_cast<> on getScriptApiBase()
+	template<typename T>
+	static T* getScriptApi(lua_State *L) {
+		ScriptApiBase *scriptIface = getScriptApiBase(L);
+		T *scriptIfaceDowncast = dynamic_cast<T*>(scriptIface);
+		if (!scriptIfaceDowncast) {
+			throw LuaError(L, "Requested unavailable ScriptApi - core engine bug!");
+		}
+		return scriptIfaceDowncast;
+	}
+
+	static bool registerFunction(lua_State *L,
+			const char* name,
+			lua_CFunction fct,
+			int top
+			);
+};
 
 #endif /* L_BASE_H_ */
diff --git a/src/script/lua_api/l_craft.cpp b/src/script/lua_api/l_craft.cpp
index a32fb9dff..b0a47bfc1 100644
--- a/src/script/lua_api/l_craft.cpp
+++ b/src/script/lua_api/l_craft.cpp
@@ -19,20 +19,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 
 #include "lua_api/l_craft.h"
-#include "common/c_internal.h"
+#include "lua_api/l_internal.h"
+#include "lua_api/l_item.h"
 #include "common/c_converter.h"
 #include "common/c_content.h"
 #include "server.h"
-#include "lua_api/l_item.h"
-
-extern "C" {
-#include "lauxlib.h"
-}
-
-ModApiCraft::ModApiCraft()
-	: ModApiBase() {
-
-}
+#include "craftdef.h"
 
 struct EnumString ModApiCraft::es_CraftMethod[] =
 {
@@ -463,15 +455,10 @@ int ModApiCraft::l_get_all_craft_recipes(lua_State *L)
 	return 1;
 }
 
-bool ModApiCraft::Initialize(lua_State* L, int top) {
-	bool retval = true;
-
-	retval &= API_FCT(get_all_craft_recipes);
-	retval &= API_FCT(get_craft_recipe);
-	retval &= API_FCT(get_craft_result);
-	retval &= API_FCT(register_craft);
-
-	return retval;
+void ModApiCraft::Initialize(lua_State *L, int top)
+{
+	API_FCT(get_all_craft_recipes);
+	API_FCT(get_craft_recipe);
+	API_FCT(get_craft_result);
+	API_FCT(register_craft);
 }
-
-ModApiCraft modapicraft_prototype;
diff --git a/src/script/lua_api/l_craft.h b/src/script/lua_api/l_craft.h
index d8319199d..548608776 100644
--- a/src/script/lua_api/l_craft.h
+++ b/src/script/lua_api/l_craft.h
@@ -20,19 +20,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #ifndef L_CRAFT_H_
 #define L_CRAFT_H_
 
+#include <string>
 #include <vector>
 
-extern "C" {
-#include <lua.h>
-}
-
 #include "lua_api/l_base.h"
-#include "craftdef.h"
+
+struct CraftReplacements;
 
 class ModApiCraft : public ModApiBase {
-public:
-	ModApiCraft();
-	bool Initialize(lua_State* L, int top);
 private:
 	static int l_register_craft(lua_State *L);
 	static int l_get_craft_recipe(lua_State *L);
@@ -47,6 +42,9 @@ class ModApiCraft : public ModApiBase {
 			int &width, std::vector<std::string> &recipe);
 
 	static struct EnumString es_CraftMethod[];
+
+public:
+	static void Initialize(lua_State *L, int top);
 };
 
 #endif /* L_CRAFT_H_ */
diff --git a/src/script/lua_api/l_env.cpp b/src/script/lua_api/l_env.cpp
index 47bc9baf7..dbaf6fb36 100644
--- a/src/script/lua_api/l_env.cpp
+++ b/src/script/lua_api/l_env.cpp
@@ -17,53 +17,39 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
 
-#include "cpp_api/scriptapi.h"
-#include "lua_api/l_base.h"
 #include "lua_api/l_env.h"
+#include "lua_api/l_internal.h"
+#include "lua_api/l_nodemeta.h"
+#include "lua_api/l_nodetimer.h"
+#include "lua_api/l_noise.h"
 #include "lua_api/l_vmanip.h"
+#include "common/c_converter.h"
+#include "common/c_content.h"
+#include "scripting_game.h"
 #include "environment.h"
 #include "server.h"
+#include "nodedef.h"
 #include "daynightratio.h"
 #include "util/pointedthing.h"
 #include "content_sao.h"
-
-#include "common/c_converter.h"
-#include "common/c_content.h"
-#include "common/c_internal.h"
-#include "lua_api/l_nodemeta.h"
-#include "lua_api/l_nodetimer.h"
-#include "lua_api/l_noise.h"
 #include "treegen.h"
 #include "pathfinder.h"
-#include "emerge.h"
-#include "mapgen_v7.h"
 
 
 #define GET_ENV_PTR ServerEnvironment* env =                                   \
 				dynamic_cast<ServerEnvironment*>(getEnv(L));                   \
 				if( env == NULL) return 0
 				
-struct EnumString ModApiEnvMod::es_MapgenObject[] =
-{
-	{MGOBJ_VMANIP,    "voxelmanip"},
-	{MGOBJ_HEIGHTMAP, "heightmap"},
-	{MGOBJ_BIOMEMAP,  "biomemap"},
-	{MGOBJ_HEATMAP,   "heatmap"},
-	{MGOBJ_HUMIDMAP,  "humiditymap"},
-	{0, NULL},
-};
-
-
 ///////////////////////////////////////////////////////////////////////////////
 
 
 void LuaABM::trigger(ServerEnvironment *env, v3s16 p, MapNode n,
 		u32 active_object_count, u32 active_object_count_wider)
 {
-	ScriptApi* scriptIface = SERVER_TO_SA(env);
+	GameScripting *scriptIface = env->getScriptIface();
 	scriptIface->realityCheck();
 
-	lua_State* L = scriptIface->getStack();
+	lua_State *L = scriptIface->getStack();
 	assert(lua_checkstack(L, 20));
 	StackUnroller stack_unroller(L);
 
@@ -196,8 +182,13 @@ int ModApiEnvMod::l_place_node(lua_State *L)
 {
 	GET_ENV_PTR;
 
+	ScriptApiItem *scriptIfaceItem = getScriptApi<ScriptApiItem>(L);
+	Server *server = getServer(L);
+	INodeDefManager *ndef = server->ndef();
+	IItemDefManager *idef = server->idef();
+
 	v3s16 pos = read_v3s16(L, 1);
-	MapNode n = readnode(L, 2, env->getGameDef()->ndef());
+	MapNode n = readnode(L, 2, ndef);
 
 	// Don't attempt to load non-loaded area as of now
 	MapNode n_old = env->getMap().getNodeNoEx(pos);
@@ -206,8 +197,6 @@ int ModApiEnvMod::l_place_node(lua_State *L)
 		return 1;
 	}
 	// Create item to place
-	INodeDefManager *ndef = getServer(L)->ndef();
-	IItemDefManager *idef = getServer(L)->idef();
 	ItemStack item(ndef->get(n).name, 1, 0, "", idef);
 	// Make pointed position
 	PointedThing pointed;
@@ -216,7 +205,7 @@ int ModApiEnvMod::l_place_node(lua_State *L)
 	pointed.node_undersurface = pos + v3s16(0,-1,0);
 	// Place it with a NULL placer (appears in Lua as a non-functional
 	// ObjectRef)
-	bool success = get_scriptapi(L)->item_OnPlace(item, NULL, pointed);
+	bool success = scriptIfaceItem->item_OnPlace(item, NULL, pointed);
 	lua_pushboolean(L, success);
 	return 1;
 }
@@ -227,6 +216,8 @@ int ModApiEnvMod::l_dig_node(lua_State *L)
 {
 	GET_ENV_PTR;
 
+	ScriptApiNode *scriptIfaceNode = getScriptApi<ScriptApiNode>(L);
+
 	v3s16 pos = read_v3s16(L, 1);
 
 	// Don't attempt to load non-loaded area as of now
@@ -237,7 +228,7 @@ int ModApiEnvMod::l_dig_node(lua_State *L)
 	}
 	// Dig it out with a NULL digger (appears in Lua as a
 	// non-functional ObjectRef)
-	bool success = get_scriptapi(L)->node_on_dig(pos, n, NULL);
+	bool success = scriptIfaceNode->node_on_dig(pos, n, NULL);
 	lua_pushboolean(L, success);
 	return 1;
 }
@@ -248,6 +239,8 @@ int ModApiEnvMod::l_punch_node(lua_State *L)
 {
 	GET_ENV_PTR;
 
+	ScriptApiNode *scriptIfaceNode = getScriptApi<ScriptApiNode>(L);
+
 	v3s16 pos = read_v3s16(L, 1);
 
 	// Don't attempt to load non-loaded area as of now
@@ -258,7 +251,7 @@ int ModApiEnvMod::l_punch_node(lua_State *L)
 	}
 	// Punch it with a NULL puncher (appears in Lua as a non-functional
 	// ObjectRef)
-	bool success = get_scriptapi(L)->node_on_punch(pos, n, NULL);
+	bool success = scriptIfaceNode->node_on_punch(pos, n, NULL);
 	lua_pushboolean(L, success);
 	return 1;
 }
@@ -361,7 +354,7 @@ int ModApiEnvMod::l_add_entity(lua_State *L)
 	if(objectid == 0)
 		return 0;
 	// Return ObjectRef
-	get_scriptapi(L)->objectrefGetOrCreate(obj);
+	getScriptApiBase(L)->objectrefGetOrCreate(obj);
 	return 1;
 }
 
@@ -420,7 +413,7 @@ int ModApiEnvMod::l_get_player_by_name(lua_State *L)
 		return 1;
 	}
 	// Put player on stack
-	get_scriptapi(L)->objectrefGetOrCreate(sao);
+	getScriptApiBase(L)->objectrefGetOrCreate(sao);
 	return 1;
 }
 
@@ -446,7 +439,7 @@ int ModApiEnvMod::l_get_objects_inside_radius(lua_State *L)
 		// Insert object reference into table
 		lua_pushvalue(L, table_insert);
 		lua_pushvalue(L, table);
-		get_scriptapi(L)->objectrefGetOrCreate(obj);
+		getScriptApiBase(L)->objectrefGetOrCreate(obj);
 		if(lua_pcall(L, 2, 0, 0))
 			script_error(L, "error: %s", lua_tostring(L, -1));
 	}
@@ -624,142 +617,6 @@ int ModApiEnvMod::l_get_voxel_manip(lua_State *L)
 	return 1;
 }
 
-// minetest.get_mapgen_object(objectname)
-// returns the requested object used during map generation
-int ModApiEnvMod::l_get_mapgen_object(lua_State *L)
-{
-	const char *mgobjstr = lua_tostring(L, 1);
-	
-	int mgobjint;
-	if (!string_to_enum(es_MapgenObject, mgobjint, mgobjstr ? mgobjstr : ""))
-		return 0;
-		
-	enum MapgenObject mgobj = (MapgenObject)mgobjint;
-
-	EmergeManager *emerge = getServer(L)->getEmergeManager();
-	Mapgen *mg = emerge->getCurrentMapgen();
-	if (!mg)
-		return 0;
-	
-	size_t maplen = mg->csize.X * mg->csize.Z;
-	
-	int nargs = 1;
-	
-	switch (mgobj) {
-		case MGOBJ_VMANIP: {
-			ManualMapVoxelManipulator *vm = mg->vm;
-			
-			// VoxelManip object
-			LuaVoxelManip *o = new LuaVoxelManip(vm, true);
-			*(void **)(lua_newuserdata(L, sizeof(void *))) = o;
-			luaL_getmetatable(L, "VoxelManip");
-			lua_setmetatable(L, -2);
-			
-			// emerged min pos
-			push_v3s16(L, vm->m_area.MinEdge);
-
-			// emerged max pos
-			push_v3s16(L, vm->m_area.MaxEdge);
-			
-			nargs = 3;
-			
-			break; }
-		case MGOBJ_HEIGHTMAP: {
-			if (!mg->heightmap)
-				return 0;
-			
-			lua_newtable(L);
-			for (size_t i = 0; i != maplen; i++) {
-				lua_pushinteger(L, mg->heightmap[i]);
-				lua_rawseti(L, -2, i + 1);
-			}
-			break; }
-		case MGOBJ_BIOMEMAP: {
-			if (!mg->biomemap)
-				return 0;
-			
-			lua_newtable(L);
-			for (size_t i = 0; i != maplen; i++) {
-				lua_pushinteger(L, mg->biomemap[i]);
-				lua_rawseti(L, -2, i + 1);
-			}
-			break; }
-		case MGOBJ_HEATMAP: { // Mapgen V7 specific objects
-		case MGOBJ_HUMIDMAP:
-			if (strcmp(emerge->params->mg_name.c_str(), "v7"))
-				return 0;
-			
-			MapgenV7 *mgv7 = (MapgenV7 *)mg;
-
-			float *arr = (mgobj == MGOBJ_HEATMAP) ? 
-				mgv7->noise_heat->result : mgv7->noise_humidity->result;
-			if (!arr)
-				return 0;
-			
-			lua_newtable(L);
-			for (size_t i = 0; i != maplen; i++) {
-				lua_pushnumber(L, arr[i]);
-				lua_rawseti(L, -2, i + 1);
-			}
-			break; }
-	}
-	
-	return nargs;
-}
-
-// minetest.set_mapgen_params(params)
-// set mapgen parameters
-int ModApiEnvMod::l_set_mapgen_params(lua_State *L)
-{
-	if (!lua_istable(L, 1))
-		return 0;
-
-	EmergeManager *emerge = getServer(L)->getEmergeManager();
-	if (emerge->mapgen.size())
-		return 0;
-	
-	MapgenParams *oparams = new MapgenParams;
-	u32 paramsmodified = 0;
-	u32 flagmask = 0;
-	
-	lua_getfield(L, 1, "mgname");
-	if (lua_isstring(L, -1)) {
-		oparams->mg_name = std::string(lua_tostring(L, -1));
-		paramsmodified |= MGPARAMS_SET_MGNAME;
-	}
-	
-	lua_getfield(L, 1, "seed");
-	if (lua_isnumber(L, -1)) {
-		oparams->seed = lua_tointeger(L, -1);
-		paramsmodified |= MGPARAMS_SET_SEED;
-	}
-	
-	lua_getfield(L, 1, "water_level");
-	if (lua_isnumber(L, -1)) {
-		oparams->water_level = lua_tointeger(L, -1);
-		paramsmodified |= MGPARAMS_SET_WATER_LEVEL;
-	}
-
-	lua_getfield(L, 1, "flags");
-	if (lua_isstring(L, -1)) {
-		std::string flagstr = std::string(lua_tostring(L, -1));
-		oparams->flags = readFlagString(flagstr, flagdesc_mapgen);
-		paramsmodified |= MGPARAMS_SET_FLAGS;
-	
-		lua_getfield(L, 1, "flagmask");
-		if (lua_isstring(L, -1)) {
-			flagstr = std::string(lua_tostring(L, -1));
-			flagmask = readFlagString(flagstr, flagdesc_mapgen);
-		}
-	}
-	
-	emerge->luaoverride_params          = oparams;
-	emerge->luaoverride_params_modified = paramsmodified;
-	emerge->luaoverride_flagmask        = flagmask;
-	
-	return 0;
-}
-
 // minetest.clear_objects()
 // clear all objects in the environment
 int ModApiEnvMod::l_clear_objects(lua_State *L)
@@ -913,48 +770,39 @@ int ModApiEnvMod::l_get_humidity(lua_State *L)
 }
 
 
-bool ModApiEnvMod::Initialize(lua_State *L,int top)
-{
-
-	bool retval = true;
-
-	retval &= API_FCT(set_node);
-	retval &= API_FCT(add_node);
-	retval &= API_FCT(add_item);
-	retval &= API_FCT(remove_node);
-	retval &= API_FCT(get_node);
-	retval &= API_FCT(get_node_or_nil);
-	retval &= API_FCT(get_node_light);
-	retval &= API_FCT(place_node);
-	retval &= API_FCT(dig_node);
-	retval &= API_FCT(punch_node);
-	retval &= API_FCT(get_node_max_level);
-	retval &= API_FCT(get_node_level);
-	retval &= API_FCT(set_node_level);
-	retval &= API_FCT(add_node_level);
-	retval &= API_FCT(add_entity);
-	retval &= API_FCT(get_meta);
-	retval &= API_FCT(get_node_timer);
-	retval &= API_FCT(get_player_by_name);
-	retval &= API_FCT(get_objects_inside_radius);
-	retval &= API_FCT(set_timeofday);
-	retval &= API_FCT(get_timeofday);
-	retval &= API_FCT(find_node_near);
-	retval &= API_FCT(find_nodes_in_area);
-	retval &= API_FCT(get_perlin);
-	retval &= API_FCT(get_perlin_map);
-	retval &= API_FCT(get_voxel_manip);
-	retval &= API_FCT(get_mapgen_object);
-	retval &= API_FCT(set_mapgen_params);
-	retval &= API_FCT(clear_objects);
-	retval &= API_FCT(spawn_tree);
-	retval &= API_FCT(find_path);
-	retval &= API_FCT(line_of_sight);
-	retval &= API_FCT(transforming_liquid_add);
-	retval &= API_FCT(get_heat);
-	retval &= API_FCT(get_humidity);
-
-	return retval;
-}
-
-ModApiEnvMod modapienv_prototype;
+void ModApiEnvMod::Initialize(lua_State *L, int top)
+{
+	API_FCT(set_node);
+	API_FCT(add_node);
+	API_FCT(add_item);
+	API_FCT(remove_node);
+	API_FCT(get_node);
+	API_FCT(get_node_or_nil);
+	API_FCT(get_node_light);
+	API_FCT(place_node);
+	API_FCT(dig_node);
+	API_FCT(punch_node);
+	API_FCT(get_node_max_level);
+	API_FCT(get_node_level);
+	API_FCT(set_node_level);
+	API_FCT(add_node_level);
+	API_FCT(add_entity);
+	API_FCT(get_meta);
+	API_FCT(get_node_timer);
+	API_FCT(get_player_by_name);
+	API_FCT(get_objects_inside_radius);
+	API_FCT(set_timeofday);
+	API_FCT(get_timeofday);
+	API_FCT(find_node_near);
+	API_FCT(find_nodes_in_area);
+	API_FCT(get_perlin);
+	API_FCT(get_perlin_map);
+	API_FCT(get_voxel_manip);
+	API_FCT(clear_objects);
+	API_FCT(spawn_tree);
+	API_FCT(find_path);
+	API_FCT(line_of_sight);
+	API_FCT(transforming_liquid_add);
+	API_FCT(get_heat);
+	API_FCT(get_humidity);
+}
diff --git a/src/script/lua_api/l_env.h b/src/script/lua_api/l_env.h
index 4122fd037..adb80a8a8 100644
--- a/src/script/lua_api/l_env.h
+++ b/src/script/lua_api/l_env.h
@@ -20,17 +20,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #ifndef L_ENV_H_
 #define L_ENV_H_
 
-extern "C" {
-#include <lua.h>
-#include <lauxlib.h>
-}
-
-#include "environment.h"
 #include "lua_api/l_base.h"
+#include "environment.h"
 
-class ModApiEnvMod
-	:public ModApiBase
-{
+class ModApiEnvMod : public ModApiBase {
 private:
 	// minetest.set_node(pos, node)
 	// pos = {x=num, y=num, z=num}
@@ -131,14 +124,6 @@ class ModApiEnvMod
 	// returns world-specific voxel manipulator
 	static int l_get_voxel_manip(lua_State *L);
 	
-	// minetest.get_mapgen_object(objectname)
-	// returns the requested object used during map generation
-	static int l_get_mapgen_object(lua_State *L);
-	
-	// minetest.set_mapgen_params(params)
-	// set mapgen parameters
-	static int l_set_mapgen_params(lua_State *L);
-
 	// minetest.clear_objects()
 	// clear all objects in the environment
 	static int l_clear_objects(lua_State *L);
@@ -159,10 +144,8 @@ class ModApiEnvMod
 	static int l_get_heat(lua_State *L);
 	static int l_get_humidity(lua_State *L);
 	
-	static struct EnumString es_MapgenObject[];
-	
 public:
-	bool Initialize(lua_State *L, int top);
+	static void Initialize(lua_State *L, int top);
 };
 
 class LuaABM : public ActiveBlockModifier
diff --git a/src/script/lua_api/l_internal.h b/src/script/lua_api/l_internal.h
new file mode 100644
index 000000000..14215ee5d
--- /dev/null
+++ b/src/script/lua_api/l_internal.h
@@ -0,0 +1,43 @@
+/*
+Minetest
+Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+/******************************************************************************/
+/******************************************************************************/
+/* WARNING!!!! do NOT add this header in any include file or any code file    */
+/*             not being a modapi file!!!!!!!!                                */
+/******************************************************************************/
+/******************************************************************************/
+
+#ifndef L_INTERNAL_H_
+#define L_INTERNAL_H_
+
+#include "common/c_internal.h"
+
+#define luamethod(class, name) {#name, class::l_##name}
+#define API_FCT(name) registerFunction(L,#name,l_##name,top)
+
+#if (defined(WIN32) || defined(_WIN32_WCE))
+#define NO_MAP_LOCK_REQUIRED
+#else
+#include "main.h"
+#include "profiler.h"
+#define NO_MAP_LOCK_REQUIRED ScopeProfiler nolocktime(g_profiler,"Scriptapi: unlockable time",SPT_ADD)
+#endif
+
+#endif /* L_INTERNAL_H_ */
diff --git a/src/script/lua_api/l_inventory.cpp b/src/script/lua_api/l_inventory.cpp
index f57a4e8cd..67b78bcaf 100644
--- a/src/script/lua_api/l_inventory.cpp
+++ b/src/script/lua_api/l_inventory.cpp
@@ -17,15 +17,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
 
-#include "cpp_api/scriptapi.h"
-#include "common/c_converter.h"
-#include "common/c_content.h"
 #include "lua_api/l_inventory.h"
+#include "lua_api/l_internal.h"
 #include "lua_api/l_item.h"
-#include "common/c_internal.h"
+#include "common/c_converter.h"
+#include "common/c_content.h"
 #include "server.h"
-#include "log.h"
-#include "inventorymanager.h"
+#include "player.h"
 
 /*
 	InvRef
@@ -40,7 +38,7 @@ InvRef* InvRef::checkobject(lua_State *L, int narg)
 
 Inventory* InvRef::getinv(lua_State *L, InvRef *ref)
 {
-	return STACK_TO_SERVER(L)->getInventory(ref->m_loc);
+	return getServer(L)->getInventory(ref->m_loc);
 }
 
 InventoryList* InvRef::getlist(lua_State *L, InvRef *ref,
@@ -56,7 +54,7 @@ InventoryList* InvRef::getlist(lua_State *L, InvRef *ref,
 void InvRef::reportInventoryChange(lua_State *L, InvRef *ref)
 {
 	// Inform other things that the inventory has changed
-	STACK_TO_SERVER(L)->setInventoryModified(ref->m_loc);
+	getServer(L)->setInventoryModified(ref->m_loc);
 }
 
 // Exported functions
@@ -182,7 +180,7 @@ int InvRef::l_set_stack(lua_State *L)
 	InvRef *ref = checkobject(L, 1);
 	const char *listname = luaL_checkstring(L, 2);
 	int i = luaL_checknumber(L, 3) - 1;
-	ItemStack newitem = read_item(L, 4,STACK_TO_SERVER(L));
+	ItemStack newitem = read_item(L, 4, getServer(L));
 	InventoryList *list = getlist(L, ref, listname);
 	if(list != NULL && i >= 0 && i < (int) list->getSize()){
 		list->changeItem(i, newitem);
@@ -202,7 +200,7 @@ int InvRef::l_get_list(lua_State *L)
 	const char *listname = luaL_checkstring(L, 2);
 	Inventory *inv = getinv(L, ref);
 	if(inv){
-		push_inventory_list(inv, listname, L);
+		push_inventory_list(L, inv, listname);
 	} else {
 		lua_pushnil(L);
 	}
@@ -221,10 +219,10 @@ int InvRef::l_set_list(lua_State *L)
 	}
 	InventoryList *list = inv->getList(listname);
 	if(list)
-		read_inventory_list(inv, listname, L, 3,
-				STACK_TO_SERVER(L),list->getSize());
+		read_inventory_list(L, 3, inv, listname,
+				getServer(L), list->getSize());
 	else
-		read_inventory_list(inv, listname, L, 3,STACK_TO_SERVER(L));
+		read_inventory_list(L, 3, inv, listname, getServer(L));
 	reportInventoryChange(L, ref);
 	return 0;
 }
@@ -236,7 +234,7 @@ int InvRef::l_add_item(lua_State *L)
 	NO_MAP_LOCK_REQUIRED;
 	InvRef *ref = checkobject(L, 1);
 	const char *listname = luaL_checkstring(L, 2);
-	ItemStack item = read_item(L, 3,STACK_TO_SERVER(L));
+	ItemStack item = read_item(L, 3, getServer(L));
 	InventoryList *list = getlist(L, ref, listname);
 	if(list){
 		ItemStack leftover = list->addItem(item);
@@ -256,7 +254,7 @@ int InvRef::l_room_for_item(lua_State *L)
 	NO_MAP_LOCK_REQUIRED;
 	InvRef *ref = checkobject(L, 1);
 	const char *listname = luaL_checkstring(L, 2);
-	ItemStack item = read_item(L, 3,STACK_TO_SERVER(L));
+	ItemStack item = read_item(L, 3, getServer(L));
 	InventoryList *list = getlist(L, ref, listname);
 	if(list){
 		lua_pushboolean(L, list->roomForItem(item));
@@ -273,7 +271,7 @@ int InvRef::l_contains_item(lua_State *L)
 	NO_MAP_LOCK_REQUIRED;
 	InvRef *ref = checkobject(L, 1);
 	const char *listname = luaL_checkstring(L, 2);
-	ItemStack item = read_item(L, 3, STACK_TO_SERVER(L));
+	ItemStack item = read_item(L, 3, getServer(L));
 	InventoryList *list = getlist(L, ref, listname);
 	if(list){
 		lua_pushboolean(L, list->containsItem(item));
@@ -290,7 +288,7 @@ int InvRef::l_remove_item(lua_State *L)
 	NO_MAP_LOCK_REQUIRED;
 	InvRef *ref = checkobject(L, 1);
 	const char *listname = luaL_checkstring(L, 2);
-	ItemStack item = read_item(L, 3,STACK_TO_SERVER(L));
+	ItemStack item = read_item(L, 3, getServer(L));
 	InventoryList *list = getlist(L, ref, listname);
 	if(list){
 		ItemStack removed = list->removeItem(item);
@@ -473,20 +471,8 @@ int ModApiInventory::l_create_detached_inventory_raw(lua_State *L)
 	return 1;
 }
 
-bool ModApiInventory::Initialize(lua_State *L, int top) {
-	bool retval = true;
-
-	retval &= API_FCT(create_detached_inventory_raw);
-	retval &= API_FCT(get_inventory);
-
-	InvRef::Register(L);
-
-	return retval;
-}
-
-ModApiInventory::ModApiInventory()
-	: ModApiBase() {
-
+void ModApiInventory::Initialize(lua_State *L, int top)
+{
+	API_FCT(create_detached_inventory_raw);
+	API_FCT(get_inventory);
 }
-
-ModApiInventory modapiinventory_prototype;
diff --git a/src/script/lua_api/l_inventory.h b/src/script/lua_api/l_inventory.h
index 83e8039b8..ed3249e5f 100644
--- a/src/script/lua_api/l_inventory.h
+++ b/src/script/lua_api/l_inventory.h
@@ -20,23 +20,18 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #ifndef L_INVENTORY_H_
 #define L_INVENTORY_H_
 
-extern "C" {
-#include <lua.h>
-#include <lauxlib.h>
-}
+#include "lua_api/l_base.h"
 
-#include "inventorymanager.h"
-#include "player.h"
-#include "serverobject.h"
 #include "inventory.h"
+#include "inventorymanager.h"
+
+class Player;
 
-#include "lua_api/l_base.h"
 /*
 	InvRef
 */
 
-class InvRef
-{
+class InvRef : public ModApiBase {
 private:
 	InventoryLocation m_loc;
 
@@ -116,22 +111,19 @@ class InvRef
 	static void Register(lua_State *L);
 };
 
-class ModApiInventory
-	: public ModApiBase
-{
-public:
-	ModApiInventory();
-
-	bool Initialize(lua_State *L, int top);
-
+class ModApiInventory : public ModApiBase {
+private:
 	static int l_create_detached_inventory_raw(lua_State *L);
+
 	static int l_get_inventory(lua_State *L);
-private:
+
 	static void inventory_set_list_from_lua(Inventory *inv, const char *name,
 			lua_State *L, int tableindex, int forcesize);
 	static void inventory_get_list_to_lua(Inventory *inv, const char *name,
 			lua_State *L);
 
+public:
+	static void Initialize(lua_State *L, int top);
 };
 
 #endif /* L_INVENTORY_H_ */
diff --git a/src/script/lua_api/l_item.cpp b/src/script/lua_api/l_item.cpp
index 6182c037b..a43b2858f 100644
--- a/src/script/lua_api/l_item.cpp
+++ b/src/script/lua_api/l_item.cpp
@@ -18,11 +18,16 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 */
 
 #include "lua_api/l_item.h"
+#include "lua_api/l_internal.h"
 #include "common/c_converter.h"
 #include "common/c_content.h"
-#include "cpp_api/scriptapi.h"
+#include "itemdef.h"
+#include "nodedef.h"
 #include "server.h"
-#include "common/c_internal.h"
+#include "content_sao.h"
+#include "inventory.h"
+#include "log.h"
+
 
 // garbage collector
 int LuaItemStack::gc_object(lua_State *L)
@@ -97,7 +102,7 @@ int LuaItemStack::l_replace(lua_State *L)
 {
 	NO_MAP_LOCK_REQUIRED;
 	LuaItemStack *o = checkobject(L, 1);
-	o->m_stack = read_item(L,2,STACK_TO_SERVER(L));
+	o->m_stack = read_item(L,2,getServer(L));
 	lua_pushboolean(L, true);
 	return 1;
 }
@@ -143,7 +148,7 @@ int LuaItemStack::l_get_stack_max(lua_State *L)
 	NO_MAP_LOCK_REQUIRED;
 	LuaItemStack *o = checkobject(L, 1);
 	ItemStack &item = o->m_stack;
-	lua_pushinteger(L, item.getStackMax(STACK_TO_SERVER(L)->idef()));
+	lua_pushinteger(L, item.getStackMax(getServer(L)->idef()));
 	return 1;
 }
 
@@ -153,7 +158,7 @@ int LuaItemStack::l_get_free_space(lua_State *L)
 	NO_MAP_LOCK_REQUIRED;
 	LuaItemStack *o = checkobject(L, 1);
 	ItemStack &item = o->m_stack;
-	lua_pushinteger(L, item.freeSpace(STACK_TO_SERVER(L)->idef()));
+	lua_pushinteger(L, item.freeSpace(getServer(L)->idef()));
 	return 1;
 }
 
@@ -164,7 +169,7 @@ int LuaItemStack::l_is_known(lua_State *L)
 	NO_MAP_LOCK_REQUIRED;
 	LuaItemStack *o = checkobject(L, 1);
 	ItemStack &item = o->m_stack;
-	bool is_known = item.isKnown(STACK_TO_SERVER(L)->idef());
+	bool is_known = item.isKnown(getServer(L)->idef());
 	lua_pushboolean(L, is_known);
 	return 1;
 }
@@ -200,7 +205,7 @@ int LuaItemStack::l_get_tool_capabilities(lua_State *L)
 	LuaItemStack *o = checkobject(L, 1);
 	ItemStack &item = o->m_stack;
 	const ToolCapabilities &prop =
-		item.getToolCapabilities(STACK_TO_SERVER(L)->idef());
+		item.getToolCapabilities(getServer(L)->idef());
 	push_tool_capabilities(L, prop);
 	return 1;
 }
@@ -215,7 +220,7 @@ int LuaItemStack::l_add_wear(lua_State *L)
 	LuaItemStack *o = checkobject(L, 1);
 	ItemStack &item = o->m_stack;
 	int amount = lua_tointeger(L, 2);
-	bool result = item.addWear(amount, STACK_TO_SERVER(L)->idef());
+	bool result = item.addWear(amount, getServer(L)->idef());
 	lua_pushboolean(L, result);
 	return 1;
 }
@@ -227,8 +232,8 @@ int LuaItemStack::l_add_item(lua_State *L)
 	NO_MAP_LOCK_REQUIRED;
 	LuaItemStack *o = checkobject(L, 1);
 	ItemStack &item = o->m_stack;
-	ItemStack newitem = read_item(L,-1, STACK_TO_SERVER(L));
-	ItemStack leftover = item.addItem(newitem, STACK_TO_SERVER(L)->idef());
+	ItemStack newitem = read_item(L,-1, getServer(L));
+	ItemStack leftover = item.addItem(newitem, getServer(L)->idef());
 	create(L, leftover);
 	return 1;
 }
@@ -241,9 +246,9 @@ int LuaItemStack::l_item_fits(lua_State *L)
 	NO_MAP_LOCK_REQUIRED;
 	LuaItemStack *o = checkobject(L, 1);
 	ItemStack &item = o->m_stack;
-	ItemStack newitem = read_item(L, 2 ,STACK_TO_SERVER(L));
+	ItemStack newitem = read_item(L, 2, getServer(L));
 	ItemStack restitem;
-	bool fits = item.itemFits(newitem, &restitem, STACK_TO_SERVER(L)->idef());
+	bool fits = item.itemFits(newitem, &restitem, getServer(L)->idef());
 	lua_pushboolean(L, fits);  // first return value
 	create(L, restitem);       // second return value
 	return 2;
@@ -300,7 +305,7 @@ ItemStack& LuaItemStack::getItem()
 int LuaItemStack::create_object(lua_State *L)
 {
 	NO_MAP_LOCK_REQUIRED;
-	ItemStack item = read_item(L,1,STACK_TO_SERVER(L));
+	ItemStack item = read_item(L, 1, getServer(L));
 	LuaItemStack *o = new LuaItemStack(item);
 	*(void **)(lua_newuserdata(L, sizeof(void *))) = o;
 	luaL_getmetatable(L, className);
@@ -378,9 +383,6 @@ const luaL_reg LuaItemStack::methods[] = {
 	{0,0}
 };
 
-ModApiItemMod::ModApiItemMod() {
-}
-
 /*
 	ItemDefinition
 */
@@ -392,13 +394,11 @@ int ModApiItemMod::l_register_item_raw(lua_State *L)
 	luaL_checktype(L, 1, LUA_TTABLE);
 	int table = 1;
 
-	ScriptApi* scriptIface = get_scriptapi(L);
-
 	// Get the writable item and node definition managers from the server
 	IWritableItemDefManager *idef =
-			scriptIface->getServer()->getWritableItemDefManager();
+			getServer(L)->getWritableItemDefManager();
 	IWritableNodeDefManager *ndef =
-			scriptIface->getServer()->getWritableNodeDefManager();
+			getServer(L)->getWritableNodeDefManager();
 
 	// Check if name is defined
 	std::string name;
@@ -455,7 +455,7 @@ int ModApiItemMod::l_register_alias_raw(lua_State *L)
 
 	// Get the writable item definition manager from the server
 	IWritableItemDefManager *idef =
-			STACK_TO_SERVER(L)->getWritableItemDefManager();
+			getServer(L)->getWritableItemDefManager();
 
 	idef->registerAlias(name, convert_to);
 
@@ -468,7 +468,7 @@ int ModApiItemMod::l_get_content_id(lua_State *L)
 	NO_MAP_LOCK_REQUIRED;
 	std::string name = luaL_checkstring(L, 1);
 
-	INodeDefManager *ndef = STACK_TO_SERVER(L)->getNodeDefManager();
+	INodeDefManager *ndef = getServer(L)->getNodeDefManager();
 	content_t c = ndef->getId(name);
 	
 	lua_pushinteger(L, c);
@@ -481,25 +481,17 @@ int ModApiItemMod::l_get_name_from_content_id(lua_State *L)
 	NO_MAP_LOCK_REQUIRED;
 	content_t c = luaL_checkint(L, 1);
 
-	INodeDefManager *ndef = STACK_TO_SERVER(L)->getNodeDefManager();
+	INodeDefManager *ndef = getServer(L)->getNodeDefManager();
 	const char *name = ndef->get(c).name.c_str();
 	
 	lua_pushstring(L, name);
 	return 1; /* number of results */
 }
 
-bool ModApiItemMod::Initialize(lua_State *L,int top) {
-
-	bool retval = true;
-
-	retval &= API_FCT(register_item_raw);
-	retval &= API_FCT(register_alias_raw);
-	retval &= API_FCT(get_content_id);
-	retval &= API_FCT(get_name_from_content_id);
-
-	LuaItemStack::Register(L);
-
-	return retval;
+void ModApiItemMod::Initialize(lua_State *L, int top)
+{
+	API_FCT(register_item_raw);
+	API_FCT(register_alias_raw);
+	API_FCT(get_content_id);
+	API_FCT(get_name_from_content_id);
 }
-
-ModApiItemMod modapi_item_prototyp;
diff --git a/src/script/lua_api/l_item.h b/src/script/lua_api/l_item.h
index bad517e08..7c2e1b098 100644
--- a/src/script/lua_api/l_item.h
+++ b/src/script/lua_api/l_item.h
@@ -20,24 +20,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #ifndef L_ITEM_H_
 #define L_ITEM_H_
 
-extern "C" {
-#include <lua.h>
-#include <lauxlib.h>
-}
-
-#include <vector>
-
-#include "itemdef.h"
-#include "content_sao.h"
-#include "util/pointedthing.h"
-#include "inventory.h"
-
 #include "lua_api/l_base.h"
+#include "inventory.h"  // ItemStack
 
-class ModApiInventory;
-
-class LuaItemStack
-{
+class LuaItemStack : public ModApiBase {
 private:
 	ItemStack m_stack;
 
@@ -134,18 +120,14 @@ class LuaItemStack
 
 };
 
-class ModApiItemMod
-	:virtual public ModApiBase
-{
-public:
-	ModApiItemMod();
-
-	bool Initialize(lua_State *L, int top);
-
+class ModApiItemMod : public ModApiBase {
+private:
 	static int l_register_item_raw(lua_State *L);
 	static int l_register_alias_raw(lua_State *L);
 	static int l_get_content_id(lua_State *L);
 	static int l_get_name_from_content_id(lua_State *L);
+public:
+	static void Initialize(lua_State *L, int top);
 };
 
 
diff --git a/src/guiLuaApi.cpp b/src/script/lua_api/l_mainmenu.cpp
similarity index 76%
rename from src/guiLuaApi.cpp
rename to src/script/lua_api/l_mainmenu.cpp
index 5d3e9dc12..b3ae1f3f1 100644
--- a/src/guiLuaApi.cpp
+++ b/src/script/lua_api/l_mainmenu.cpp
@@ -17,117 +17,27 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
 
-extern "C" {
-#include "lua.h"
-#include "lauxlib.h"
-#include "lualib.h"
-}
-#include "porting.h"
+#include "lua_api/l_mainmenu.h"
+#include "lua_api/l_internal.h"
+#include "common/c_content.h"
+#include "guiEngine.h"
 #include "guiMainMenu.h"
-#include "subgame.h"
 #include "guiKeyChangeMenu.h"
 #include "guiFileSelectMenu.h"
-#include "main.h"
-#include "settings.h"
+#include "subgame.h"
+#include "porting.h"
 #include "filesys.h"
 #include "convert_json.h"
+#include "serverlist.h"
 #include "sound.h"
+#include "settings.h"
+#include "main.h" // for g_settings
 
-
-#include "IFileArchive.h"
-#include "IFileSystem.h"
-
-#include "guiLuaApi.h"
-#include "guiEngine.h"
-
-#define API_FCT(name) registerFunction(L,#name,l_##name,top)
-
-void guiLuaApi::initialize(lua_State* L,GUIEngine* engine)
-{
-	lua_pushlightuserdata(L, engine);
-	lua_setfield(L, LUA_REGISTRYINDEX, "engine");
-
-	lua_pushstring(L, DIR_DELIM);
-	lua_setglobal(L, "DIR_DELIM");
-
-	lua_newtable(L);
-	lua_setglobal(L, "gamedata");
-
-	lua_newtable(L);
-	lua_setglobal(L, "engine");
-
-	lua_getglobal(L, "engine");
-	int top = lua_gettop(L);
-
-	bool retval = true;
-
-	//add api functions
-	retval &= API_FCT(update_formspec);
-	retval &= API_FCT(set_clouds);
-	retval &= API_FCT(get_textlist_index);
-	retval &= API_FCT(get_worlds);
-	retval &= API_FCT(get_games);
-	retval &= API_FCT(start);
-	retval &= API_FCT(close);
-	retval &= API_FCT(get_favorites);
-	retval &= API_FCT(show_keys_menu);
-	retval &= API_FCT(setting_set);
-	retval &= API_FCT(setting_get);
-	retval &= API_FCT(setting_getbool);
-	retval &= API_FCT(setting_setbool);
-	retval &= API_FCT(create_world);
-	retval &= API_FCT(delete_world);
-	retval &= API_FCT(delete_favorite);
-	retval &= API_FCT(set_background);
-	retval &= API_FCT(set_topleft_text);
-	retval &= API_FCT(get_modpath);
-	retval &= API_FCT(get_gamepath);
-	retval &= API_FCT(get_texturepath);
-	retval &= API_FCT(get_dirlist);
-	retval &= API_FCT(create_dir);
-	retval &= API_FCT(delete_dir);
-	retval &= API_FCT(copy_dir);
-	retval &= API_FCT(extract_zip);
-	retval &= API_FCT(get_scriptdir);
-	retval &= API_FCT(show_file_open_dialog);
-	retval &= API_FCT(get_version);
-	retval &= API_FCT(download_file);
-	retval &= API_FCT(get_modstore_details);
-	retval &= API_FCT(get_modstore_list);
-	retval &= API_FCT(sound_play);
-	retval &= API_FCT(sound_stop);
-
-	if (!retval) {
-		//TODO show error
-	}
-}
-
-/******************************************************************************/
-bool guiLuaApi::registerFunction(	lua_State* L,
-									const char* name,
-									lua_CFunction fct,
-									int top
-									)
-{
-	lua_pushstring(L,name);
-	lua_pushcfunction(L,fct);
-	lua_settable(L, top);
-
-	return true;
-}
-
-/******************************************************************************/
-GUIEngine* guiLuaApi::get_engine(lua_State *L)
-{
-	// Get server from registry
-	lua_getfield(L, LUA_REGISTRYINDEX, "engine");
-	GUIEngine* sapi_ptr = (GUIEngine*) lua_touserdata(L, -1);
-	lua_pop(L, 1);
-	return sapi_ptr;
-}
+#include <IFileArchive.h>
+#include <IFileSystem.h>
 
 /******************************************************************************/
-std::string guiLuaApi::getTextData(lua_State *L, std::string name)
+std::string ModApiMainMenu::getTextData(lua_State *L, std::string name)
 {
 	lua_getglobal(L, "gamedata");
 
@@ -140,7 +50,7 @@ std::string guiLuaApi::getTextData(lua_State *L, std::string name)
 }
 
 /******************************************************************************/
-int guiLuaApi::getIntegerData(lua_State *L, std::string name,bool& valid)
+int ModApiMainMenu::getIntegerData(lua_State *L, std::string name,bool& valid)
 {
 	lua_getglobal(L, "gamedata");
 
@@ -156,7 +66,7 @@ int guiLuaApi::getIntegerData(lua_State *L, std::string name,bool& valid)
 }
 
 /******************************************************************************/
-int guiLuaApi::getBoolData(lua_State *L, std::string name,bool& valid)
+int ModApiMainMenu::getBoolData(lua_State *L, std::string name,bool& valid)
 {
 	lua_getglobal(L, "gamedata");
 
@@ -172,9 +82,9 @@ int guiLuaApi::getBoolData(lua_State *L, std::string name,bool& valid)
 }
 
 /******************************************************************************/
-int guiLuaApi::l_update_formspec(lua_State *L)
+int ModApiMainMenu::l_update_formspec(lua_State *L)
 {
-	GUIEngine* engine = get_engine(L);
+	GUIEngine* engine = getGuiEngine(L);
 	assert(engine != 0);
 
 	if (engine->m_startgame)
@@ -191,9 +101,9 @@ int guiLuaApi::l_update_formspec(lua_State *L)
 }
 
 /******************************************************************************/
-int guiLuaApi::l_start(lua_State *L)
+int ModApiMainMenu::l_start(lua_State *L)
 {
-	GUIEngine* engine = get_engine(L);
+	GUIEngine* engine = getGuiEngine(L);
 	assert(engine != 0);
 
 	//update c++ gamedata from lua table
@@ -216,9 +126,9 @@ int guiLuaApi::l_start(lua_State *L)
 }
 
 /******************************************************************************/
-int guiLuaApi::l_close(lua_State *L)
+int ModApiMainMenu::l_close(lua_State *L)
 {
-	GUIEngine* engine = get_engine(L);
+	GUIEngine* engine = getGuiEngine(L);
 	assert(engine != 0);
 
 	engine->m_data->kill = true;
@@ -230,9 +140,9 @@ int guiLuaApi::l_close(lua_State *L)
 }
 
 /******************************************************************************/
-int guiLuaApi::l_set_background(lua_State *L)
+int ModApiMainMenu::l_set_background(lua_State *L)
 {
-	GUIEngine* engine = get_engine(L);
+	GUIEngine* engine = getGuiEngine(L);
 	assert(engine != 0);
 
 	std::string backgroundlevel(luaL_checkstring(L, 1));
@@ -261,9 +171,9 @@ int guiLuaApi::l_set_background(lua_State *L)
 }
 
 /******************************************************************************/
-int guiLuaApi::l_set_clouds(lua_State *L)
+int ModApiMainMenu::l_set_clouds(lua_State *L)
 {
-	GUIEngine* engine = get_engine(L);
+	GUIEngine* engine = getGuiEngine(L);
 	assert(engine != 0);
 
 	bool value = lua_toboolean(L,1);
@@ -274,9 +184,9 @@ int guiLuaApi::l_set_clouds(lua_State *L)
 }
 
 /******************************************************************************/
-int guiLuaApi::l_get_textlist_index(lua_State *L)
+int ModApiMainMenu::l_get_textlist_index(lua_State *L)
 {
-	GUIEngine* engine = get_engine(L);
+	GUIEngine* engine = getGuiEngine(L);
 	assert(engine != 0);
 
 	std::string listboxname(luaL_checkstring(L, 1));
@@ -291,9 +201,9 @@ int guiLuaApi::l_get_textlist_index(lua_State *L)
 }
 
 /******************************************************************************/
-int guiLuaApi::l_get_worlds(lua_State *L)
+int ModApiMainMenu::l_get_worlds(lua_State *L)
 {
-	GUIEngine* engine = get_engine(L);
+	GUIEngine* engine = getGuiEngine(L);
 	assert(engine != 0);
 
 	std::vector<WorldSpec> worlds = getAvailableWorlds();
@@ -328,9 +238,9 @@ int guiLuaApi::l_get_worlds(lua_State *L)
 }
 
 /******************************************************************************/
-int guiLuaApi::l_get_games(lua_State *L)
+int ModApiMainMenu::l_get_games(lua_State *L)
 {
-	GUIEngine* engine = get_engine(L);
+	GUIEngine* engine = getGuiEngine(L);
 	assert(engine != 0);
 
 	std::vector<SubgameSpec> games = getAvailableGames();
@@ -383,7 +293,7 @@ int guiLuaApi::l_get_games(lua_State *L)
 	return 1;
 }
 /******************************************************************************/
-int guiLuaApi::l_get_modstore_details(lua_State *L)
+int ModApiMainMenu::l_get_modstore_details(lua_State *L)
 {
 	const char *modid	= luaL_checkstring(L, 1);
 
@@ -456,9 +366,9 @@ int guiLuaApi::l_get_modstore_details(lua_State *L)
 }
 
 /******************************************************************************/
-int guiLuaApi::l_get_modstore_list(lua_State *L)
+int ModApiMainMenu::l_get_modstore_list(lua_State *L)
 {
-	GUIEngine* engine = get_engine(L);
+	GUIEngine* engine = getGuiEngine(L);
 	assert(engine != 0);
 
 	std::string listtype = "local";
@@ -512,9 +422,9 @@ int guiLuaApi::l_get_modstore_list(lua_State *L)
 }
 
 /******************************************************************************/
-int guiLuaApi::l_get_favorites(lua_State *L)
+int ModApiMainMenu::l_get_favorites(lua_State *L)
 {
-	GUIEngine* engine = get_engine(L);
+	GUIEngine* engine = getGuiEngine(L);
 	assert(engine != 0);
 
 	std::string listtype = "local";
@@ -632,9 +542,9 @@ int guiLuaApi::l_get_favorites(lua_State *L)
 }
 
 /******************************************************************************/
-int guiLuaApi::l_delete_favorite(lua_State *L)
+int ModApiMainMenu::l_delete_favorite(lua_State *L)
 {
-	GUIEngine* engine = get_engine(L);
+	GUIEngine* engine = getGuiEngine(L);
 	assert(engine != 0);
 
 	std::vector<ServerListSpec> servers;
@@ -671,9 +581,9 @@ int guiLuaApi::l_delete_favorite(lua_State *L)
 }
 
 /******************************************************************************/
-int guiLuaApi::l_show_keys_menu(lua_State *L)
+int ModApiMainMenu::l_show_keys_menu(lua_State *L)
 {
-	GUIEngine* engine = get_engine(L);
+	GUIEngine* engine = getGuiEngine(L);
 	assert(engine != 0);
 
 	GUIKeyChangeMenu *kmenu
@@ -686,55 +596,9 @@ int guiLuaApi::l_show_keys_menu(lua_State *L)
 }
 
 /******************************************************************************/
-int guiLuaApi::l_setting_set(lua_State *L)
+int ModApiMainMenu::l_create_world(lua_State *L)
 {
-	const char *name = luaL_checkstring(L, 1);
-	const char *value = luaL_checkstring(L, 2);
-	g_settings->set(name, value);
-	return 0;
-}
-
-/******************************************************************************/
-int guiLuaApi::l_setting_get(lua_State *L)
-{
-	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;
-}
-
-/******************************************************************************/
-int guiLuaApi::l_setting_getbool(lua_State *L)
-{
-	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;
-}
-
-/******************************************************************************/
-int guiLuaApi::l_setting_setbool(lua_State *L)
-{
-	const char *name = luaL_checkstring(L, 1);
-	bool value = lua_toboolean(L,2);
-
-	g_settings->setBool(name,value);
-
-	return 0;
-}
-
-/******************************************************************************/
-int guiLuaApi::l_create_world(lua_State *L)
-{
-	GUIEngine* engine = get_engine(L);
+	GUIEngine* engine = getGuiEngine(L);
 	assert(engine != 0);
 
 	const char *name	= luaL_checkstring(L, 1);
@@ -765,9 +629,9 @@ int guiLuaApi::l_create_world(lua_State *L)
 }
 
 /******************************************************************************/
-int guiLuaApi::l_delete_world(lua_State *L)
+int ModApiMainMenu::l_delete_world(lua_State *L)
 {
-	GUIEngine* engine = get_engine(L);
+	GUIEngine* engine = getGuiEngine(L);
 	assert(engine != 0);
 
 	int worldidx	= luaL_checkinteger(L,1) -1;
@@ -798,9 +662,9 @@ int guiLuaApi::l_delete_world(lua_State *L)
 }
 
 /******************************************************************************/
-int guiLuaApi::l_set_topleft_text(lua_State *L)
+int ModApiMainMenu::l_set_topleft_text(lua_State *L)
 {
-	GUIEngine* engine = get_engine(L);
+	GUIEngine* engine = getGuiEngine(L);
 	assert(engine != 0);
 
 	std::string text = "";
@@ -813,7 +677,7 @@ int guiLuaApi::l_set_topleft_text(lua_State *L)
 }
 
 /******************************************************************************/
-int guiLuaApi::l_get_modpath(lua_State *L)
+int ModApiMainMenu::l_get_modpath(lua_State *L)
 {
 	std::string modpath
 			= fs::RemoveRelativePathComponents(porting::path_user + DIR_DELIM + "mods" + DIR_DELIM);
@@ -822,7 +686,7 @@ int guiLuaApi::l_get_modpath(lua_State *L)
 }
 
 /******************************************************************************/
-int guiLuaApi::l_get_gamepath(lua_State *L)
+int ModApiMainMenu::l_get_gamepath(lua_State *L)
 {
 	std::string gamepath
 			= fs::RemoveRelativePathComponents(porting::path_user + DIR_DELIM + "games" + DIR_DELIM);
@@ -831,7 +695,7 @@ int guiLuaApi::l_get_gamepath(lua_State *L)
 }
 
 /******************************************************************************/
-int guiLuaApi::l_get_texturepath(lua_State *L)
+int ModApiMainMenu::l_get_texturepath(lua_State *L)
 {
 	std::string gamepath
 			= fs::RemoveRelativePathComponents(porting::path_user + DIR_DELIM + "textures");
@@ -840,7 +704,8 @@ int guiLuaApi::l_get_texturepath(lua_State *L)
 }
 
 /******************************************************************************/
-int guiLuaApi::l_get_dirlist(lua_State *L) {
+int ModApiMainMenu::l_get_dirlist(lua_State *L)
+{
 	const char *path	= luaL_checkstring(L, 1);
 	bool dironly		= lua_toboolean(L, 2);
 
@@ -863,10 +728,10 @@ int guiLuaApi::l_get_dirlist(lua_State *L) {
 }
 
 /******************************************************************************/
-int guiLuaApi::l_create_dir(lua_State *L) {
+int ModApiMainMenu::l_create_dir(lua_State *L) {
 	const char *path	= luaL_checkstring(L, 1);
 
-	if (guiLuaApi::isMinetestPath(path)) {
+	if (ModApiMainMenu::isMinetestPath(path)) {
 		lua_pushboolean(L,fs::CreateAllDirs(path));
 		return 1;
 	}
@@ -875,12 +740,13 @@ int guiLuaApi::l_create_dir(lua_State *L) {
 }
 
 /******************************************************************************/
-int guiLuaApi::l_delete_dir(lua_State *L) {
+int ModApiMainMenu::l_delete_dir(lua_State *L)
+{
 	const char *path	= luaL_checkstring(L, 1);
 
 	std::string absolute_path = fs::RemoveRelativePathComponents(path);
 
-	if (guiLuaApi::isMinetestPath(absolute_path)) {
+	if (ModApiMainMenu::isMinetestPath(absolute_path)) {
 		lua_pushboolean(L,fs::RecursiveDelete(absolute_path));
 		return 1;
 	}
@@ -889,7 +755,8 @@ int guiLuaApi::l_delete_dir(lua_State *L) {
 }
 
 /******************************************************************************/
-int guiLuaApi::l_copy_dir(lua_State *L) {
+int ModApiMainMenu::l_copy_dir(lua_State *L)
+{
 	const char *source	= luaL_checkstring(L, 1);
 	const char *destination	= luaL_checkstring(L, 2);
 
@@ -903,8 +770,8 @@ int guiLuaApi::l_copy_dir(lua_State *L) {
 	std::string absolute_destination = fs::RemoveRelativePathComponents(destination);
 	std::string absolute_source = fs::RemoveRelativePathComponents(source);
 
-	if ((guiLuaApi::isMinetestPath(absolute_source)) &&
-			(guiLuaApi::isMinetestPath(absolute_destination))) {
+	if ((ModApiMainMenu::isMinetestPath(absolute_source)) &&
+			(ModApiMainMenu::isMinetestPath(absolute_destination))) {
 		bool retval = fs::CopyDir(absolute_source,absolute_destination);
 
 		if (retval && (!keep_source)) {
@@ -919,9 +786,9 @@ int guiLuaApi::l_copy_dir(lua_State *L) {
 }
 
 /******************************************************************************/
-int guiLuaApi::l_extract_zip(lua_State *L) {
-
-	GUIEngine* engine = get_engine(L);
+int ModApiMainMenu::l_extract_zip(lua_State *L)
+{
+	GUIEngine* engine = getGuiEngine(L);
 	assert(engine != 0);
 
 	const char *zipfile	= luaL_checkstring(L, 1);
@@ -929,7 +796,7 @@ int guiLuaApi::l_extract_zip(lua_State *L) {
 
 	std::string absolute_destination = fs::RemoveRelativePathComponents(destination);
 
-	if (guiLuaApi::isMinetestPath(absolute_destination)) {
+	if (ModApiMainMenu::isMinetestPath(absolute_destination)) {
 		fs::CreateAllDirs(absolute_destination);
 
 		io::IFileSystem* fs = engine->m_device->getFileSystem();
@@ -1005,8 +872,9 @@ int guiLuaApi::l_extract_zip(lua_State *L) {
 }
 
 /******************************************************************************/
-int guiLuaApi::l_get_scriptdir(lua_State *L) {
-	GUIEngine* engine = get_engine(L);
+int ModApiMainMenu::l_get_scriptdir(lua_State *L)
+{
+	GUIEngine* engine = getGuiEngine(L);
 	assert(engine != 0);
 
 	lua_pushstring(L,engine->getScriptDir().c_str());
@@ -1014,9 +882,8 @@ int guiLuaApi::l_get_scriptdir(lua_State *L) {
 }
 
 /******************************************************************************/
-bool guiLuaApi::isMinetestPath(std::string path) {
-
-
+bool ModApiMainMenu::isMinetestPath(std::string path)
+{
 	if (fs::PathStartsWith(path,fs::TempPath()))
 		return true;
 
@@ -1037,9 +904,9 @@ bool guiLuaApi::isMinetestPath(std::string path) {
 }
 
 /******************************************************************************/
-int guiLuaApi::l_show_file_open_dialog(lua_State *L) {
-
-	GUIEngine* engine = get_engine(L);
+int ModApiMainMenu::l_show_file_open_dialog(lua_State *L)
+{
+	GUIEngine* engine = getGuiEngine(L);
 	assert(engine != 0);
 
 	const char *formname= luaL_checkstring(L, 1);
@@ -1058,35 +925,19 @@ int guiLuaApi::l_show_file_open_dialog(lua_State *L) {
 }
 
 /******************************************************************************/
-int guiLuaApi::l_get_version(lua_State *L) {
+int ModApiMainMenu::l_get_version(lua_State *L)
+{
 	lua_pushstring(L,VERSION_STRING);
 	return 1;
 }
 
 /******************************************************************************/
-int guiLuaApi::l_sound_play(lua_State *L) {
-	GUIEngine* engine = get_engine(L);
+int ModApiMainMenu::l_sound_play(lua_State *L)
+{
+	GUIEngine* engine = getGuiEngine(L);
 
 	SimpleSoundSpec spec;
-	if(lua_isnil(L, 1))
-	{
-	} else if(lua_istable(L, 1)){
-		lua_getfield(L, 1, "name");
-		if(lua_isstring(L, -1)){
-			size_t len = 0;
-			spec.name = lua_tolstring(L, -1, &len);
-		}
-		lua_pop(L, 1);
-
-		//luaL_checkfloat(L, 1, "gain", spec.gain);
-		lua_getfield(L, 1, "gain");
-		if(lua_isnumber(L, -1)){
-			spec.gain = lua_tonumber(L, -1);
-		}
-		lua_pop(L, 1);
-	} else if(lua_isstring(L, 1)){
-		spec.name = luaL_checkstring(L, 1);
-	}
+	read_soundspec(L, 1, spec);
 	bool looped = lua_toboolean(L, 2);
 
 	u32 handle = engine->playSound(spec, looped);
@@ -1097,8 +948,9 @@ int guiLuaApi::l_sound_play(lua_State *L) {
 }
 
 /******************************************************************************/
-int guiLuaApi::l_sound_stop(lua_State *L) {
-	GUIEngine* engine = get_engine(L);
+int ModApiMainMenu::l_sound_stop(lua_State *L)
+{
+	GUIEngine* engine = getGuiEngine(L);
 
 	u32 handle = luaL_checkinteger(L, 1);
 	engine->stopSound(handle);
@@ -1107,8 +959,9 @@ int guiLuaApi::l_sound_stop(lua_State *L) {
 }
 
 /******************************************************************************/
-int guiLuaApi::l_download_file(lua_State *L) {
-	GUIEngine* engine = get_engine(L);
+int ModApiMainMenu::l_download_file(lua_State *L)
+{
+	GUIEngine* engine = getGuiEngine(L);
 	assert(engine != 0);
 
 	const char *url    = luaL_checkstring(L, 1);
@@ -1117,7 +970,7 @@ int guiLuaApi::l_download_file(lua_State *L) {
 	//check path
 	std::string absolute_destination = fs::RemoveRelativePathComponents(target);
 
-	if (guiLuaApi::isMinetestPath(absolute_destination)) {
+	if (ModApiMainMenu::isMinetestPath(absolute_destination)) {
 		if (engine->downloadFile(url,absolute_destination)) {
 			lua_pushboolean(L,true);
 			return 1;
@@ -1126,3 +979,38 @@ int guiLuaApi::l_download_file(lua_State *L) {
 	lua_pushboolean(L,false);
 	return 1;
 }
+
+/******************************************************************************/
+void ModApiMainMenu::Initialize(lua_State *L, int top)
+{
+	API_FCT(update_formspec);
+	API_FCT(set_clouds);
+	API_FCT(get_textlist_index);
+	API_FCT(get_worlds);
+	API_FCT(get_games);
+	API_FCT(start);
+	API_FCT(close);
+	API_FCT(get_favorites);
+	API_FCT(show_keys_menu);
+	API_FCT(create_world);
+	API_FCT(delete_world);
+	API_FCT(delete_favorite);
+	API_FCT(set_background);
+	API_FCT(set_topleft_text);
+	API_FCT(get_modpath);
+	API_FCT(get_gamepath);
+	API_FCT(get_texturepath);
+	API_FCT(get_dirlist);
+	API_FCT(create_dir);
+	API_FCT(delete_dir);
+	API_FCT(copy_dir);
+	API_FCT(extract_zip);
+	API_FCT(get_scriptdir);
+	API_FCT(show_file_open_dialog);
+	API_FCT(get_version);
+	API_FCT(download_file);
+	API_FCT(get_modstore_details);
+	API_FCT(get_modstore_list);
+	API_FCT(sound_play);
+	API_FCT(sound_stop);
+}
diff --git a/src/guiLuaApi.h b/src/script/lua_api/l_mainmenu.h
similarity index 60%
rename from src/guiLuaApi.h
rename to src/script/lua_api/l_mainmenu.h
index 9555f00c5..21dd82c68 100644
--- a/src/guiLuaApi.h
+++ b/src/script/lua_api/l_mainmenu.h
@@ -17,42 +17,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
 
-#ifndef GUILUAAPI_H_
-#define GUILUAAPI_H_
+#ifndef L_MAINMENU_H_
+#define L_MAINMENU_H_
 
-/******************************************************************************/
-/* Includes                                                                   */
-/******************************************************************************/
-#include "serverlist.h"
-
-/******************************************************************************/
-/* Typedefs and macros                                                        */
-/******************************************************************************/
-typedef int (*lua_CFunction) (lua_State *L);
-
-/******************************************************************************/
-/* forward declarations                                                       */
-/******************************************************************************/
-class GUIEngine;
-
-
-/******************************************************************************/
-/* declarations                                                               */
-/******************************************************************************/
+#include "lua_api/l_base.h"
 
 /** Implementation of lua api support for mainmenu */
-class guiLuaApi {
-
-public:
-	/**
-	 * initialize given Lua stack
-	 * @param L lua stack to initialize
-	 * @param engine pointer to GUIEngine element to use as reference
-	 */
-	static void initialize(lua_State* L,GUIEngine* engine);
-
-	/** default destructor */
-	virtual ~guiLuaApi() {}
+class ModApiMainMenu : public ModApiBase {
 
 private:
 	/**
@@ -79,27 +50,6 @@ class guiLuaApi {
 	 */
 	static int getBoolData(lua_State *L, std::string name,bool& valid);
 
-	/**
-	 * get the corresponding engine pointer from a lua stack
-	 * @param L stack to read pointer from
-	 * @return pointer to GUIEngine
-	 */
-	static GUIEngine* get_engine(lua_State *L);
-
-
-	/**
-	 * register a static member function as lua api call at current position of stack
-	 * @param L stack to registe fct to
-	 * @param name of function within lua
-	 * @param fct C-Function to call on lua call of function
-	 * @param top current top of stack
-	 */
-	static bool registerFunction(	lua_State* L,
-									const char* name,
-									lua_CFunction fct,
-									int top
-								);
-
 	/**
 	 * check if a path is within some of minetests folders
 	 * @param path path to check
@@ -147,16 +97,6 @@ class guiLuaApi {
 
 	static int l_update_formspec(lua_State *L);
 
-	//settings
-
-	static int l_setting_set(lua_State *L);
-
-	static int l_setting_get(lua_State *L);
-
-	static int l_setting_getbool(lua_State *L);
-
-	static int l_setting_setbool(lua_State *L);
-
 	//filesystem
 
 	static int l_get_scriptdir(lua_State *L);
@@ -184,6 +124,14 @@ class guiLuaApi {
 	static int l_download_file(lua_State *L);
 
 
+public:
+	/**
+	 * initialize this API module
+	 * @param L lua stack to initialize
+	 * @param top index (in lua stack) of global API table
+	 */
+	static void Initialize(lua_State *L, int top);
+
 };
 
-#endif
+#endif /* L_MAINMENU_H_ */
diff --git a/src/script/lua_api/l_mapgen.cpp b/src/script/lua_api/l_mapgen.cpp
new file mode 100644
index 000000000..14693b43f
--- /dev/null
+++ b/src/script/lua_api/l_mapgen.cpp
@@ -0,0 +1,574 @@
+/*
+Minetest
+Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "lua_api/l_mapgen.h"
+#include "lua_api/l_internal.h"
+#include "lua_api/l_vmanip.h"
+#include "common/c_converter.h"
+#include "common/c_content.h"
+#include "server.h"
+#include "environment.h"
+#include "biome.h"
+#include "emerge.h"
+#include "mapgen_v7.h"
+
+
+struct EnumString ModApiMapgen::es_BiomeTerrainType[] =
+{
+	{BIOME_TERRAIN_NORMAL, "normal"},
+	{BIOME_TERRAIN_LIQUID, "liquid"},
+	{BIOME_TERRAIN_NETHER, "nether"},
+	{BIOME_TERRAIN_AETHER, "aether"},
+	{BIOME_TERRAIN_FLAT,   "flat"},
+	{0, NULL},
+};
+
+struct EnumString ModApiMapgen::es_DecorationType[] =
+{
+	{DECO_SIMPLE,    "simple"},
+	{DECO_SCHEMATIC, "schematic"},
+	{DECO_LSYSTEM,   "lsystem"},
+	{0, NULL},
+};
+
+struct EnumString ModApiMapgen::es_MapgenObject[] =
+{
+	{MGOBJ_VMANIP,    "voxelmanip"},
+	{MGOBJ_HEIGHTMAP, "heightmap"},
+	{MGOBJ_BIOMEMAP,  "biomemap"},
+	{MGOBJ_HEATMAP,   "heatmap"},
+	{MGOBJ_HUMIDMAP,  "humiditymap"},
+	{0, NULL},
+};
+
+struct EnumString ModApiMapgen::es_OreType[] =
+{
+	{ORE_SCATTER,  "scatter"},
+	{ORE_SHEET,    "sheet"},
+	{ORE_CLAYLIKE, "claylike"},
+	{0, NULL},
+};
+
+struct EnumString ModApiMapgen::es_Rotation[] =
+{
+	{ROTATE_0,    "0"},
+	{ROTATE_90,   "90"},
+	{ROTATE_180,  "180"},
+	{ROTATE_270,  "270"},
+	{ROTATE_RAND, "random"},
+	{0, NULL},
+};
+
+
+// minetest.get_mapgen_object(objectname)
+// returns the requested object used during map generation
+int ModApiMapgen::l_get_mapgen_object(lua_State *L)
+{
+	const char *mgobjstr = lua_tostring(L, 1);
+	
+	int mgobjint;
+	if (!string_to_enum(es_MapgenObject, mgobjint, mgobjstr ? mgobjstr : ""))
+		return 0;
+		
+	enum MapgenObject mgobj = (MapgenObject)mgobjint;
+
+	EmergeManager *emerge = getServer(L)->getEmergeManager();
+	Mapgen *mg = emerge->getCurrentMapgen();
+	if (!mg)
+		return 0;
+	
+	size_t maplen = mg->csize.X * mg->csize.Z;
+	
+	int nargs = 1;
+	
+	switch (mgobj) {
+		case MGOBJ_VMANIP: {
+			ManualMapVoxelManipulator *vm = mg->vm;
+			
+			// VoxelManip object
+			LuaVoxelManip *o = new LuaVoxelManip(vm, true);
+			*(void **)(lua_newuserdata(L, sizeof(void *))) = o;
+			luaL_getmetatable(L, "VoxelManip");
+			lua_setmetatable(L, -2);
+			
+			// emerged min pos
+			push_v3s16(L, vm->m_area.MinEdge);
+
+			// emerged max pos
+			push_v3s16(L, vm->m_area.MaxEdge);
+			
+			nargs = 3;
+			
+			break; }
+		case MGOBJ_HEIGHTMAP: {
+			if (!mg->heightmap)
+				return 0;
+			
+			lua_newtable(L);
+			for (size_t i = 0; i != maplen; i++) {
+				lua_pushinteger(L, mg->heightmap[i]);
+				lua_rawseti(L, -2, i + 1);
+			}
+			break; }
+		case MGOBJ_BIOMEMAP: {
+			if (!mg->biomemap)
+				return 0;
+			
+			lua_newtable(L);
+			for (size_t i = 0; i != maplen; i++) {
+				lua_pushinteger(L, mg->biomemap[i]);
+				lua_rawseti(L, -2, i + 1);
+			}
+			break; }
+		case MGOBJ_HEATMAP: { // Mapgen V7 specific objects
+		case MGOBJ_HUMIDMAP:
+			if (strcmp(emerge->params->mg_name.c_str(), "v7"))
+				return 0;
+			
+			MapgenV7 *mgv7 = (MapgenV7 *)mg;
+
+			float *arr = (mgobj == MGOBJ_HEATMAP) ? 
+				mgv7->noise_heat->result : mgv7->noise_humidity->result;
+			if (!arr)
+				return 0;
+			
+			lua_newtable(L);
+			for (size_t i = 0; i != maplen; i++) {
+				lua_pushnumber(L, arr[i]);
+				lua_rawseti(L, -2, i + 1);
+			}
+			break; }
+	}
+	
+	return nargs;
+}
+
+// minetest.set_mapgen_params(params)
+// set mapgen parameters
+int ModApiMapgen::l_set_mapgen_params(lua_State *L)
+{
+	if (!lua_istable(L, 1))
+		return 0;
+
+	EmergeManager *emerge = getServer(L)->getEmergeManager();
+	if (emerge->mapgen.size())
+		return 0;
+	
+	MapgenParams *oparams = new MapgenParams;
+	u32 paramsmodified = 0;
+	u32 flagmask = 0;
+	
+	lua_getfield(L, 1, "mgname");
+	if (lua_isstring(L, -1)) {
+		oparams->mg_name = std::string(lua_tostring(L, -1));
+		paramsmodified |= MGPARAMS_SET_MGNAME;
+	}
+	
+	lua_getfield(L, 1, "seed");
+	if (lua_isnumber(L, -1)) {
+		oparams->seed = lua_tointeger(L, -1);
+		paramsmodified |= MGPARAMS_SET_SEED;
+	}
+	
+	lua_getfield(L, 1, "water_level");
+	if (lua_isnumber(L, -1)) {
+		oparams->water_level = lua_tointeger(L, -1);
+		paramsmodified |= MGPARAMS_SET_WATER_LEVEL;
+	}
+
+	lua_getfield(L, 1, "flags");
+	if (lua_isstring(L, -1)) {
+		std::string flagstr = std::string(lua_tostring(L, -1));
+		oparams->flags = readFlagString(flagstr, flagdesc_mapgen);
+		paramsmodified |= MGPARAMS_SET_FLAGS;
+	
+		lua_getfield(L, 1, "flagmask");
+		if (lua_isstring(L, -1)) {
+			flagstr = std::string(lua_tostring(L, -1));
+			flagmask = readFlagString(flagstr, flagdesc_mapgen);
+		}
+	}
+	
+	emerge->luaoverride_params          = oparams;
+	emerge->luaoverride_params_modified = paramsmodified;
+	emerge->luaoverride_flagmask        = flagmask;
+	
+	return 0;
+}
+
+// register_biome({lots of stuff})
+int ModApiMapgen::l_register_biome(lua_State *L)
+{
+	int index = 1;
+	luaL_checktype(L, index, LUA_TTABLE);
+
+	BiomeDefManager *bmgr = getServer(L)->getEmergeManager()->biomedef;
+	if (!bmgr) {
+		verbosestream << "register_biome: BiomeDefManager not active" << std::endl;
+		return 0;
+	}
+
+	enum BiomeTerrainType terrain = (BiomeTerrainType)getenumfield(L, index,
+				"terrain_type", es_BiomeTerrainType, BIOME_TERRAIN_NORMAL);
+	Biome *b = bmgr->createBiome(terrain);
+
+	b->name         = getstringfield_default(L, index, "name",
+												"<no name>");
+	b->nname_top    = getstringfield_default(L, index, "node_top",
+												"mapgen_dirt_with_grass");
+	b->nname_filler = getstringfield_default(L, index, "node_filler",
+												"mapgen_dirt");
+	b->nname_water  = getstringfield_default(L, index, "node_water",
+												"mapgen_water_source");
+	b->nname_dust   = getstringfield_default(L, index, "node_dust",
+												"air");
+	b->nname_dust_water = getstringfield_default(L, index, "node_dust_water",
+												"mapgen_water_source");
+	
+	b->depth_top      = getintfield_default(L, index, "depth_top",    1);
+	b->depth_filler   = getintfield_default(L, index, "depth_filler", 3);
+	b->height_min     = getintfield_default(L, index, "height_min",   0);
+	b->height_max     = getintfield_default(L, index, "height_max",   0);
+	b->heat_point     = getfloatfield_default(L, index, "heat_point",     0.);
+	b->humidity_point = getfloatfield_default(L, index, "humidity_point", 0.);
+
+	b->flags        = 0; //reserved
+	b->c_top        = CONTENT_IGNORE;
+	b->c_filler     = CONTENT_IGNORE;
+	b->c_water      = CONTENT_IGNORE;
+	b->c_dust       = CONTENT_IGNORE;
+	b->c_dust_water = CONTENT_IGNORE;
+	
+	verbosestream << "register_biome: " << b->name << std::endl;
+	bmgr->addBiome(b);
+
+	return 0;
+}
+
+// register_decoration({lots of stuff})
+int ModApiMapgen::l_register_decoration(lua_State *L)
+{
+	int index = 1;
+	luaL_checktype(L, index, LUA_TTABLE);
+
+	EmergeManager *emerge = getServer(L)->getEmergeManager();
+	BiomeDefManager *bdef = emerge->biomedef;
+
+	enum DecorationType decotype = (DecorationType)getenumfield(L, index,
+				"deco_type", es_DecorationType, -1);
+	if (decotype == -1) {
+		errorstream << "register_decoration: unrecognized "
+			"decoration placement type";
+		return 0;
+	}
+	
+	Decoration *deco = createDecoration(decotype);
+	if (!deco) {
+		errorstream << "register_decoration: decoration placement type "
+			<< decotype << " not implemented";
+		return 0;
+	}
+
+	deco->c_place_on    = CONTENT_IGNORE;
+	deco->place_on_name = getstringfield_default(L, index, "place_on", "ignore");
+	deco->fill_ratio    = getfloatfield_default(L, index, "fill_ratio", 0.02);
+	deco->sidelen       = getintfield_default(L, index, "sidelen", 8);
+	if (deco->sidelen <= 0) {
+		errorstream << "register_decoration: sidelen must be "
+			"greater than 0" << std::endl;
+		delete deco;
+		return 0;
+	}
+	
+	lua_getfield(L, index, "noise_params");
+	deco->np = read_noiseparams(L, -1);
+	lua_pop(L, 1);
+	
+	lua_getfield(L, index, "biomes");
+	if (lua_istable(L, -1)) {
+		lua_pushnil(L);
+		while (lua_next(L, -2)) {
+			const char *s = lua_tostring(L, -1);
+			u8 biomeid = bdef->getBiomeIdByName(s);
+			if (biomeid)
+				deco->biomes.insert(biomeid);
+
+			lua_pop(L, 1);
+		}
+		lua_pop(L, 1);
+	}
+	
+	switch (decotype) {
+		case DECO_SIMPLE: {
+			DecoSimple *dsimple = (DecoSimple *)deco;
+			dsimple->c_deco     = CONTENT_IGNORE;
+			dsimple->c_spawnby  = CONTENT_IGNORE;
+			dsimple->spawnby_name    = getstringfield_default(L, index, "spawn_by", "air");
+			dsimple->deco_height     = getintfield_default(L, index, "height", 1);
+			dsimple->deco_height_max = getintfield_default(L, index, "height_max", 0);
+			dsimple->nspawnby        = getintfield_default(L, index, "num_spawn_by", -1);
+			
+			lua_getfield(L, index, "decoration");
+			if (lua_istable(L, -1)) {
+				lua_pushnil(L);
+				while (lua_next(L, -2)) {
+					const char *s = lua_tostring(L, -1);
+					std::string str(s);
+					dsimple->decolist_names.push_back(str);
+
+					lua_pop(L, 1);
+				}
+			} else if (lua_isstring(L, -1)) {
+				dsimple->deco_name = std::string(lua_tostring(L, -1));
+			} else {
+				dsimple->deco_name = std::string("air");
+			}
+			lua_pop(L, 1);
+			
+			if (dsimple->deco_height <= 0) {
+				errorstream << "register_decoration: simple decoration height"
+					" must be greater than 0" << std::endl;
+				delete dsimple;
+				return 0;
+			}
+
+			break; }
+		case DECO_SCHEMATIC: {
+			DecoSchematic *dschem = (DecoSchematic *)deco;
+			dschem->flags    = getflagsfield(L, index, "flags", flagdesc_deco_schematic);
+			dschem->rotation = (Rotation)getenumfield(L, index,
+								"rotation", es_Rotation, ROTATE_0);
+
+			lua_getfield(L, index, "replacements");
+			if (lua_istable(L, -1)) {
+				int i = lua_gettop(L);
+				lua_pushnil(L);
+				while (lua_next(L, i) != 0) {
+					// key at index -2 and value at index -1
+					lua_rawgeti(L, -1, 1);
+					std::string replace_from = lua_tostring(L, -1);
+					lua_pop(L, 1);
+					lua_rawgeti(L, -1, 2);
+					std::string replace_to = lua_tostring(L, -1);
+					lua_pop(L, 1);
+					dschem->replacements[replace_from] = replace_to;
+					// removes value, keeps key for next iteration
+					lua_pop(L, 1);
+				}
+			}
+			lua_pop(L, 1);
+
+			lua_getfield(L, index, "schematic");
+			if (!read_schematic(L, -1, dschem, getServer(L))) {
+				delete dschem;
+				return 0;
+			}
+			lua_pop(L, -1);
+			
+			if (!dschem->filename.empty() && !dschem->loadSchematicFile()) {
+				errorstream << "register_decoration: failed to load schematic file '"
+					<< dschem->filename << "'" << std::endl;
+				delete dschem;
+				return 0;
+			}
+			break; }
+		case DECO_LSYSTEM: {
+			//DecoLSystem *decolsystem = (DecoLSystem *)deco;
+		
+			break; }
+	}
+
+	emerge->decorations.push_back(deco);
+
+	verbosestream << "register_decoration: decoration '" << deco->getName()
+		<< "' registered" << std::endl;
+	return 0;
+}
+
+// register_ore({lots of stuff})
+int ModApiMapgen::l_register_ore(lua_State *L)
+{
+	int index = 1;
+	luaL_checktype(L, index, LUA_TTABLE);
+
+	EmergeManager *emerge = getServer(L)->getEmergeManager();
+
+	enum OreType oretype = (OreType)getenumfield(L, index,
+				"ore_type", es_OreType, ORE_SCATTER);
+	Ore *ore = createOre(oretype);
+	if (!ore) {
+		errorstream << "register_ore: ore_type "
+			<< oretype << " not implemented";
+		return 0;
+	}
+
+	ore->ore_name       = getstringfield_default(L, index, "ore", "");
+	ore->ore_param2     = (u8)getintfield_default(L, index, "ore_param2", 0);
+	ore->clust_scarcity = getintfield_default(L, index, "clust_scarcity", 1);
+	ore->clust_num_ores = getintfield_default(L, index, "clust_num_ores", 1);
+	ore->clust_size     = getintfield_default(L, index, "clust_size", 0);
+	ore->height_min     = getintfield_default(L, index, "height_min", 0);
+	ore->height_max     = getintfield_default(L, index, "height_max", 0);
+	ore->flags          = getflagsfield(L, index, "flags", flagdesc_ore);
+	ore->nthresh        = getfloatfield_default(L, index, "noise_threshhold", 0.);
+
+	lua_getfield(L, index, "wherein");
+	if (lua_istable(L, -1)) {
+		int  i = lua_gettop(L);
+		lua_pushnil(L);
+		while(lua_next(L, i) != 0) {
+			ore->wherein_names.push_back(lua_tostring(L, -1));
+			lua_pop(L, 1);
+		}
+	} else if (lua_isstring(L, -1)) {
+		ore->wherein_names.push_back(lua_tostring(L, -1));
+	} else {
+		ore->wherein_names.push_back("");
+	}
+	lua_pop(L, 1);
+
+	lua_getfield(L, index, "noise_params");
+	ore->np = read_noiseparams(L, -1);
+	lua_pop(L, 1);
+
+	ore->noise = NULL;
+
+	if (ore->clust_scarcity <= 0 || ore->clust_num_ores <= 0) {
+		errorstream << "register_ore: clust_scarcity and clust_num_ores"
+			"must be greater than 0" << std::endl;
+		delete ore;
+		return 0;
+	}
+
+	emerge->ores.push_back(ore);
+
+	verbosestream << "register_ore: ore '" << ore->ore_name
+		<< "' registered" << std::endl;
+	return 0;
+}
+
+// create_schematic(p1, p2, probability_list, filename)
+int ModApiMapgen::l_create_schematic(lua_State *L)
+{
+	DecoSchematic dschem;
+
+	Map *map = &(getEnv(L)->getMap());
+	INodeDefManager *ndef = getServer(L)->getNodeDefManager();
+
+	v3s16 p1 = read_v3s16(L, 1);
+	v3s16 p2 = read_v3s16(L, 2);
+	sortBoxVerticies(p1, p2);
+	
+	std::vector<std::pair<v3s16, u8> > probability_list;
+	if (lua_istable(L, 3)) {
+		lua_pushnil(L);
+		while (lua_next(L, 3)) {
+			if (lua_istable(L, -1)) {
+				lua_getfield(L, -1, "pos");
+				v3s16 pos = read_v3s16(L, -1);
+				lua_pop(L, 1);
+				
+				u8 prob = getintfield_default(L, -1, "prob", 0xFF);
+				probability_list.push_back(std::make_pair(pos, prob));
+			}
+
+			lua_pop(L, 1);
+		}
+	}
+	
+	dschem.filename = std::string(lua_tostring(L, 4));
+
+	if (!dschem.getSchematicFromMap(map, p1, p2)) {
+		errorstream << "create_schematic: failed to get schematic "
+			"from map" << std::endl;
+		return 0;
+	}
+	
+	dschem.applyProbabilities(&probability_list, p1);
+	
+	dschem.saveSchematicFile(ndef);
+	actionstream << "create_schematic: saved schematic file '"
+		<< dschem.filename << "'." << std::endl;
+
+	return 1;
+}
+
+
+// place_schematic(p, schematic, rotation, replacement)
+int ModApiMapgen::l_place_schematic(lua_State *L)
+{
+	DecoSchematic dschem;
+
+	Map *map = &(getEnv(L)->getMap());
+	INodeDefManager *ndef = getServer(L)->getNodeDefManager();
+
+	v3s16 p = read_v3s16(L, 1);
+	if (!read_schematic(L, 2, &dschem, getServer(L)))
+		return 0;
+		
+	Rotation rot = ROTATE_0;
+	if (lua_isstring(L, 3))
+		string_to_enum(es_Rotation, (int &)rot, std::string(lua_tostring(L, 3)));
+		
+	dschem.rotation = rot;
+
+	if (lua_istable(L, 4)) {
+		int index = 4;
+		lua_pushnil(L);
+		while (lua_next(L, index) != 0) {
+			// key at index -2 and value at index -1
+			lua_rawgeti(L, -1, 1);
+			std::string replace_from = lua_tostring(L, -1);
+			lua_pop(L, 1);
+			lua_rawgeti(L, -1, 2);
+			std::string replace_to = lua_tostring(L, -1);
+			lua_pop(L, 1);
+			dschem.replacements[replace_from] = replace_to;
+			// removes value, keeps key for next iteration
+			lua_pop(L, 1);
+		}
+	}
+
+	if (!dschem.filename.empty()) {
+		if (!dschem.loadSchematicFile()) {
+			errorstream << "place_schematic: failed to load schematic file '"
+				<< dschem.filename << "'" << std::endl;
+			return 0;
+		}
+		dschem.resolveNodeNames(ndef);
+	}
+	
+	dschem.placeStructure(map, p);
+
+	return 1;
+}
+
+void ModApiMapgen::Initialize(lua_State *L, int top)
+{
+	API_FCT(get_mapgen_object);
+
+	API_FCT(set_mapgen_params);
+
+	API_FCT(register_biome);
+	API_FCT(register_decoration);
+	API_FCT(register_ore);
+
+	API_FCT(create_schematic);
+	API_FCT(place_schematic);
+}
diff --git a/src/script/lua_api/l_mapgen.h b/src/script/lua_api/l_mapgen.h
new file mode 100644
index 000000000..d0da5bb13
--- /dev/null
+++ b/src/script/lua_api/l_mapgen.h
@@ -0,0 +1,62 @@
+/*
+Minetest
+Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef L_MAPGEN_H_
+#define L_MAPGEN_H_
+
+#include "lua_api/l_base.h"
+
+class ModApiMapgen : public ModApiBase {
+private:
+	// minetest.get_mapgen_object(objectname)
+	// returns the requested object used during map generation
+	static int l_get_mapgen_object(lua_State *L);
+
+	// minetest.set_mapgen_params(params)
+	// set mapgen parameters
+	static int l_set_mapgen_params(lua_State *L);
+
+	// register_biome({lots of stuff})
+	static int l_register_biome(lua_State *L);
+
+	// register_decoration({lots of stuff})
+	static int l_register_decoration(lua_State *L);
+
+	// register_ore({lots of stuff})
+	static int l_register_ore(lua_State *L);
+
+	// create_schematic(p1, p2, probability_list, filename)
+	static int l_create_schematic(lua_State *L);
+
+	// place_schematic(p, schematic, rotation, replacement)
+	static int l_place_schematic(lua_State *L);
+
+	static struct EnumString es_BiomeTerrainType[];
+	static struct EnumString es_DecorationType[];
+	static struct EnumString es_MapgenObject[];
+	static struct EnumString es_OreType[];
+	static struct EnumString es_Rotation[];
+
+public:
+	static void Initialize(lua_State *L, int top);
+};
+
+
+
+#endif /* L_MAPGEN_H_ */
diff --git a/src/script/lua_api/l_nodemeta.cpp b/src/script/lua_api/l_nodemeta.cpp
index 511fb38ce..f9c8794d5 100644
--- a/src/script/lua_api/l_nodemeta.cpp
+++ b/src/script/lua_api/l_nodemeta.cpp
@@ -17,13 +17,15 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
 
-#include "cpp_api/scriptapi.h"
+#include "lua_api/l_nodemeta.h"
+#include "lua_api/l_internal.h"
+#include "lua_api/l_inventory.h"
 #include "common/c_converter.h"
 #include "common/c_content.h"
+#include "environment.h"
 #include "map.h"
-#include "lua_api/l_nodemeta.h"
-#include "common/c_internal.h"
-#include "lua_api/l_inventory.h"
+#include "nodemetadata.h"
+
 
 
 /*
@@ -211,7 +213,7 @@ int NodeMetaRef::l_to_table(lua_State *L)
 		std::vector<const InventoryList*> lists = inv->getLists();
 		for(std::vector<const InventoryList*>::const_iterator
 				i = lists.begin(); i != lists.end(); i++){
-			push_inventory_list(inv, (*i)->getName().c_str(), L);
+			push_inventory_list(L, inv, (*i)->getName().c_str());
 			lua_setfield(L, -2, (*i)->getName().c_str());
 		}
 	}
@@ -257,7 +259,7 @@ int NodeMetaRef::l_from_table(lua_State *L)
 	while(lua_next(L, inventorytable) != 0){
 		// key at index -2 and value at index -1
 		std::string name = lua_tostring(L, -2);
-		read_inventory_list(inv, name.c_str(), L, -1,STACK_TO_SERVER(L));
+		read_inventory_list(L, -1, inv, name.c_str(), getServer(L));
 		lua_pop(L, 1); // removes value, keeps key for next iteration
 	}
 	reportMetadataChange(ref);
@@ -328,5 +330,3 @@ const luaL_reg NodeMetaRef::methods[] = {
 	luamethod(NodeMetaRef, from_table),
 	{0,0}
 };
-
-REGISTER_LUA_REF(NodeMetaRef);
diff --git a/src/script/lua_api/l_nodemeta.h b/src/script/lua_api/l_nodemeta.h
index 23404a084..ed06ff0fa 100644
--- a/src/script/lua_api/l_nodemeta.h
+++ b/src/script/lua_api/l_nodemeta.h
@@ -19,20 +19,17 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #ifndef L_NODEMETA_H_
 #define L_NODEMETA_H_
 
-extern "C" {
-#include <lua.h>
-#include <lauxlib.h>
-}
+#include "lua_api/l_base.h"
+#include "irrlichttypes_bloated.h"
 
-#include "environment.h"
-#include "nodemetadata.h"
+class ServerEnvironment;
+class NodeMetadata;
 
 /*
 	NodeMetaRef
 */
 
-class NodeMetaRef
-{
+class NodeMetaRef : public ModApiBase {
 private:
 	v3s16 m_p;
 	ServerEnvironment *m_env;
@@ -90,4 +87,4 @@ class NodeMetaRef
 	static void Register(lua_State *L);
 };
 
-#endif //L_NODEMETA_H_
+#endif /* L_NODEMETA_H_ */
diff --git a/src/script/lua_api/l_nodetimer.cpp b/src/script/lua_api/l_nodetimer.cpp
index 60e4ec061..c81a7ebc9 100644
--- a/src/script/lua_api/l_nodetimer.cpp
+++ b/src/script/lua_api/l_nodetimer.cpp
@@ -17,9 +17,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
 
-#include "cpp_api/scriptapi.h"
 #include "lua_api/l_nodetimer.h"
-#include "common/c_internal.h"
+#include "lua_api/l_internal.h"
+#include "environment.h"
 #include "map.h"
 
 
@@ -165,5 +165,3 @@ const luaL_reg NodeTimerRef::methods[] = {
 	luamethod(NodeTimerRef, get_elapsed),
 	{0,0}
 };
-
-REGISTER_LUA_REF(NodeTimerRef);
diff --git a/src/script/lua_api/l_nodetimer.h b/src/script/lua_api/l_nodetimer.h
index f652b4900..9f8dd21c8 100644
--- a/src/script/lua_api/l_nodetimer.h
+++ b/src/script/lua_api/l_nodetimer.h
@@ -20,15 +20,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #ifndef L_NODETIMER_H_
 #define L_NODETIMER_H_
 
-extern "C" {
-#include <lua.h>
-#include <lauxlib.h>
-}
+#include "lua_api/l_base.h"
+#include "irr_v3d.h"
 
-#include "environment.h"
+class ServerEnvironment;
 
-class NodeTimerRef
-{
+class NodeTimerRef : public ModApiBase {
 private:
 	v3s16 m_p;
 	ServerEnvironment *m_env;
diff --git a/src/script/lua_api/l_noise.cpp b/src/script/lua_api/l_noise.cpp
index 43149e93c..ecbda9fad 100644
--- a/src/script/lua_api/l_noise.cpp
+++ b/src/script/lua_api/l_noise.cpp
@@ -18,8 +18,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 */
 
 #include "lua_api/l_noise.h"
-#include "common/c_internal.h"
+#include "lua_api/l_internal.h"
 #include "common/c_converter.h"
+#include "common/c_content.h"
 #include "log.h"
 
 // garbage collector
@@ -412,7 +413,3 @@ const luaL_reg LuaPseudoRandom::methods[] = {
 	luamethod(LuaPseudoRandom, next),
 	{0,0}
 };
-
-REGISTER_LUA_REF(LuaPseudoRandom);
-REGISTER_LUA_REF(LuaPerlinNoiseMap);
-REGISTER_LUA_REF(LuaPerlinNoise);
diff --git a/src/script/lua_api/l_noise.h b/src/script/lua_api/l_noise.h
index 6275ca472..65a927882 100644
--- a/src/script/lua_api/l_noise.h
+++ b/src/script/lua_api/l_noise.h
@@ -20,16 +20,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #ifndef L_NOISE_H_
 #define L_NOISE_H_
 
-extern "C" {
-#include <lua.h>
-#include <lauxlib.h>
-}
-
+#include "lua_api/l_base.h"
 #include "irr_v3d.h"
 #include "noise.h"
 
-class LuaPerlinNoise
-{
+/*
+	LuaPerlinNoise
+*/
+class LuaPerlinNoise : public ModApiBase {
 private:
 	int seed;
 	int octaves;
@@ -62,10 +60,9 @@ class LuaPerlinNoise
 };
 
 /*
-  PerlinNoiseMap
- */
-class LuaPerlinNoiseMap
-{
+	LuaPerlinNoiseMap
+*/
+class LuaPerlinNoiseMap : public ModApiBase {
 private:
 	Noise *noise;
 	static const char className[];
@@ -95,10 +92,7 @@ class LuaPerlinNoiseMap
 /*
 	LuaPseudoRandom
 */
-
-
-class LuaPseudoRandom
-{
+class LuaPseudoRandom : public ModApiBase {
 private:
 	PseudoRandom m_pseudo;
 
@@ -130,6 +124,4 @@ class LuaPseudoRandom
 	static void Register(lua_State *L);
 };
 
-NoiseParams *read_noiseparams(lua_State *L, int index);
-
 #endif /* L_NOISE_H_ */
diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp
index ee24789c5..c0da79c29 100644
--- a/src/script/lua_api/l_object.cpp
+++ b/src/script/lua_api/l_object.cpp
@@ -17,13 +17,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
 
-#include "cpp_api/scriptapi.h"
-#include "common/c_converter.h"
-#include "common/c_content.h"
 #include "lua_api/l_object.h"
-#include "common/c_internal.h"
+#include "lua_api/l_internal.h"
 #include "lua_api/l_inventory.h"
 #include "lua_api/l_item.h"
+#include "common/c_converter.h"
+#include "common/c_content.h"
 #include "log.h"
 #include "tool.h"
 #include "serverobject.h"
@@ -275,7 +274,7 @@ int ObjectRef::l_get_inventory(lua_State *L)
 	if(co == NULL) return 0;
 	// Do it
 	InventoryLocation loc = co->getInventoryLocation();
-	if(STACK_TO_SERVER(L)->getInventory(loc) != NULL)
+	if(getServer(L)->getInventory(loc) != NULL)
 		InvRef::create(L, loc);
 	else
 		lua_pushnil(L); // An object may have no inventory (nil)
@@ -330,7 +329,7 @@ int ObjectRef::l_set_wielded_item(lua_State *L)
 	ServerActiveObject *co = getobject(ref);
 	if(co == NULL) return 0;
 	// Do it
-	ItemStack item = read_item(L, 2,STACK_TO_SERVER(L));
+	ItemStack item = read_item(L, 2, getServer(L));
 	bool success = co->setWieldedItem(item);
 	lua_pushboolean(L, success);
 	return 1;
@@ -739,7 +738,7 @@ int ObjectRef::l_set_inventory_formspec(lua_State *L)
 	std::string formspec = luaL_checkstring(L, 2);
 
 	player->inventory_formspec = formspec;
-	STACK_TO_SERVER(L)->reportInventoryFormspecModified(player->getName());
+	getServer(L)->reportInventoryFormspecModified(player->getName());
 	lua_pushboolean(L, true);
 	return 1;
 }
@@ -841,7 +840,7 @@ int ObjectRef::l_hud_add(lua_State *L)
 	elem->offset = lua_istable(L, -1) ? read_v2f(L, -1) : v2f();
 	lua_pop(L, 1);
 
-	u32 id = STACK_TO_SERVER(L)->hudAdd(player, elem);
+	u32 id = getServer(L)->hudAdd(player, elem);
 	if (id == (u32)-1) {
 		delete elem;
 		return 0;
@@ -863,7 +862,7 @@ int ObjectRef::l_hud_remove(lua_State *L)
 	if (!lua_isnil(L, 2))
 		id = lua_tonumber(L, 2);
 
-	if (!STACK_TO_SERVER(L)->hudRemove(player, id))
+	if (!getServer(L)->hudRemove(player, id))
 		return 0;
 
 	lua_pushboolean(L, true);
@@ -929,7 +928,7 @@ int ObjectRef::l_hud_change(lua_State *L)
 			value = &e->offset;
 	}
 
-	STACK_TO_SERVER(L)->hudChange(player, id, stat, value);
+	getServer(L)->hudChange(player, id, stat, value);
 
 	lua_pushboolean(L, true);
 	return 1;
@@ -999,7 +998,7 @@ int ObjectRef::l_hud_set_flags(lua_State *L)
 			mask  |= esp[i].num;
 		}
 	}
-	if (!STACK_TO_SERVER(L)->hudSetFlags(player, flags, mask))
+	if (!getServer(L)->hudSetFlags(player, flags, mask))
 		return 0;
 
 	lua_pushboolean(L, true);
@@ -1016,7 +1015,7 @@ int ObjectRef::l_hud_set_hotbar_itemcount(lua_State *L)
 
 	s32 hotbar_itemcount = lua_tonumber(L, 2);
 
-	if (!STACK_TO_SERVER(L)->hudSetHotbarItemcount(player, hotbar_itemcount))
+	if (!getServer(L)->hudSetHotbarItemcount(player, hotbar_itemcount))
 		return 0;
 
 	lua_pushboolean(L, true);
@@ -1139,5 +1138,3 @@ const luaL_reg ObjectRef::methods[] = {
 	luamethod(ObjectRef, hud_set_hotbar_itemcount),
 	{0,0}
 };
-
-REGISTER_LUA_REF(ObjectRef)
diff --git a/src/script/lua_api/l_object.h b/src/script/lua_api/l_object.h
index a82638442..b6f5cd06f 100644
--- a/src/script/lua_api/l_object.h
+++ b/src/script/lua_api/l_object.h
@@ -20,10 +20,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #ifndef L_OBJECT_H_
 #define L_OBJECT_H_
 
-extern "C" {
-#include <lua.h>
-#include <lauxlib.h>
-}
+#include "lua_api/l_base.h"
+#include "irrlichttypes.h"
 
 class ServerActiveObject;
 class LuaEntitySAO;
@@ -34,8 +32,7 @@ class Player;
 	ObjectRef
 */
 
-class ObjectRef
-{
+class ObjectRef : public ModApiBase {
 private:
 	ServerActiveObject *m_object;
 
diff --git a/src/script/lua_api/l_particles.cpp b/src/script/lua_api/l_particles.cpp
index c291cc21e..6b009149e 100644
--- a/src/script/lua_api/l_particles.cpp
+++ b/src/script/lua_api/l_particles.cpp
@@ -17,22 +17,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
 
-#include "cpp_api/scriptapi.h"
-#include "common/c_converter.h"
-#include "lua_api/l_base.h"
 #include "lua_api/l_particles.h"
+#include "lua_api/l_internal.h"
+#include "common/c_converter.h"
 #include "server.h"
-#include "common/c_internal.h"
-
-bool ModApiParticles::Initialize(lua_State *L, int top) {
-	bool retval = true;
-
-	retval &= API_FCT(add_particle);
-	retval &= API_FCT(add_particlespawner);
-	retval &= API_FCT(delete_particlespawner);
-
-	return retval;
-}
 
 // add_particle(pos, velocity, acceleration, expirationtime,
 // 		size, collisiondetection, texture, player)
@@ -146,4 +134,10 @@ int ModApiParticles::l_delete_particlespawner(lua_State *L)
 	return 1;
 }
 
-ModApiParticles modapiparticles_prototyp;
+void ModApiParticles::Initialize(lua_State *L, int top)
+{
+	API_FCT(add_particle);
+	API_FCT(add_particlespawner);
+	API_FCT(delete_particlespawner);
+}
+
diff --git a/src/script/lua_api/l_particles.h b/src/script/lua_api/l_particles.h
index 3729f8761..c593f47e4 100644
--- a/src/script/lua_api/l_particles.h
+++ b/src/script/lua_api/l_particles.h
@@ -20,20 +20,18 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #ifndef L_PARTICLES_H_
 #define L_PARTICLES_H_
 
-extern "C" {
-#include <lua.h>
-#include <lauxlib.h>
-}
+#include "lua_api/l_base.h"
 
 class ModApiParticles : public ModApiBase {
-public:
-	bool Initialize(lua_State *L, int top);
 private:
 	static int l_add_particle(lua_State *L);
 	static int l_add_particlespawner(lua_State *L);
 	static int l_delete_particlespawner(lua_State *L);
+
+public:
+	static void Initialize(lua_State *L, int top);
 };
 
 
 
-#endif // L_PARTICLES_H_
+#endif /* L_PARTICLES_H_ */
diff --git a/src/script/lua_api/l_rollback.cpp b/src/script/lua_api/l_rollback.cpp
new file mode 100644
index 000000000..6076399ae
--- /dev/null
+++ b/src/script/lua_api/l_rollback.cpp
@@ -0,0 +1,80 @@
+/*
+Minetest
+Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "lua_api/l_rollback.h"
+#include "lua_api/l_internal.h"
+#include "common/c_converter.h"
+#include "server.h"
+#include "rollback.h"
+
+
+// rollback_get_last_node_actor(p, range, seconds) -> actor, p, seconds
+int ModApiRollback::l_rollback_get_last_node_actor(lua_State *L)
+{
+	v3s16 p = read_v3s16(L, 1);
+	int range = luaL_checknumber(L, 2);
+	int seconds = luaL_checknumber(L, 3);
+	Server *server = getServer(L);
+	IRollbackManager *rollback = server->getRollbackManager();
+	v3s16 act_p;
+	int act_seconds = 0;
+	std::string actor = rollback->getLastNodeActor(p, range, seconds, &act_p, &act_seconds);
+	lua_pushstring(L, actor.c_str());
+	push_v3s16(L, act_p);
+	lua_pushnumber(L, act_seconds);
+	return 3;
+}
+
+// rollback_revert_actions_by(actor, seconds) -> bool, log messages
+int ModApiRollback::l_rollback_revert_actions_by(lua_State *L)
+{
+	std::string actor = luaL_checkstring(L, 1);
+	int seconds = luaL_checknumber(L, 2);
+	Server *server = getServer(L);
+	IRollbackManager *rollback = server->getRollbackManager();
+	std::list<RollbackAction> actions = rollback->getRevertActions(actor, seconds);
+	std::list<std::string> log;
+	bool success = server->rollbackRevertActions(actions, &log);
+	// Push boolean result
+	lua_pushboolean(L, success);
+	// Get the table insert function and push the log table
+	lua_getglobal(L, "table");
+	lua_getfield(L, -1, "insert");
+	int table_insert = lua_gettop(L);
+	lua_newtable(L);
+	int table = lua_gettop(L);
+	for(std::list<std::string>::const_iterator i = log.begin();
+			i != log.end(); i++)
+	{
+		lua_pushvalue(L, table_insert);
+		lua_pushvalue(L, table);
+		lua_pushstring(L, i->c_str());
+		if(lua_pcall(L, 2, 0, 0))
+			script_error(L, "error: %s", lua_tostring(L, -1));
+	}
+	lua_remove(L, -2); // Remove table
+	lua_remove(L, -2); // Remove insert
+	return 2;
+}
+
+void ModApiRollback::Initialize(lua_State *L, int top)
+{
+	API_FCT(rollback_get_last_node_actor);
+	API_FCT(rollback_revert_actions_by);
+}
diff --git a/src/clientserver.cpp b/src/script/lua_api/l_rollback.h
similarity index 57%
rename from src/clientserver.cpp
rename to src/script/lua_api/l_rollback.h
index 591a95542..86992a47e 100644
--- a/src/clientserver.cpp
+++ b/src/script/lua_api/l_rollback.h
@@ -1,6 +1,6 @@
 /*
 Minetest
-Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
+Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
 
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU Lesser General Public License as published by
@@ -17,15 +17,21 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
 
-#include "clientserver.h"
-#include "util/serialize.h"
+#ifndef L_ROLLBACK_H_
+#define L_ROLLBACK_H_
 
-SharedBuffer<u8> makePacket_TOCLIENT_TIME_OF_DAY(u16 time, float time_speed)
-{
-	SharedBuffer<u8> data(2+2+4);
-	writeU16(&data[0], TOCLIENT_TIME_OF_DAY);
-	writeU16(&data[2], time);
-	writeF1000(&data[4], time_speed);
-	return data;
-}
+#include "lua_api/l_base.h"
 
+class ModApiRollback : public ModApiBase {
+private:
+	// rollback_get_last_node_actor(p, range, seconds) -> actor, p, seconds
+	static int l_rollback_get_last_node_actor(lua_State *L);
+
+	// rollback_revert_actions_by(actor, seconds) -> bool, log messages
+	static int l_rollback_revert_actions_by(lua_State *L);
+
+public:
+	static void Initialize(lua_State *L, int top);
+};
+
+#endif /* L_ROLLBACK_H_ */
diff --git a/src/script/lua_api/l_server.cpp b/src/script/lua_api/l_server.cpp
new file mode 100644
index 000000000..8e809c36a
--- /dev/null
+++ b/src/script/lua_api/l_server.cpp
@@ -0,0 +1,347 @@
+/*
+Minetest
+Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "lua_api/l_server.h"
+#include "lua_api/l_internal.h"
+#include "common/c_converter.h"
+#include "common/c_content.h"
+#include "server.h"
+#include "environment.h"
+#include "player.h"
+
+// request_shutdown()
+int ModApiServer::l_request_shutdown(lua_State *L)
+{
+	getServer(L)->requestShutdown();
+	return 0;
+}
+
+// get_server_status()
+int ModApiServer::l_get_server_status(lua_State *L)
+{
+	NO_MAP_LOCK_REQUIRED;
+	lua_pushstring(L, wide_to_narrow(getServer(L)->getStatusString()).c_str());
+	return 1;
+}
+
+// chat_send_all(text)
+int ModApiServer::l_chat_send_all(lua_State *L)
+{
+	NO_MAP_LOCK_REQUIRED;
+	const char *text = luaL_checkstring(L, 1);
+	// Get server from registry
+	Server *server = getServer(L);
+	// Send
+	server->notifyPlayers(narrow_to_wide(text));
+	return 0;
+}
+
+// chat_send_player(name, text, prepend)
+int ModApiServer::l_chat_send_player(lua_State *L)
+{
+	NO_MAP_LOCK_REQUIRED;
+	const char *name = luaL_checkstring(L, 1);
+	const char *text = luaL_checkstring(L, 2);
+	bool prepend = true;
+
+	if (lua_isboolean(L, 3))
+		prepend = lua_toboolean(L, 3);
+
+	// Get server from registry
+	Server *server = getServer(L);
+	// Send
+	server->notifyPlayer(name, narrow_to_wide(text), prepend);
+	return 0;
+}
+
+// get_player_privs(name, text)
+int ModApiServer::l_get_player_privs(lua_State *L)
+{
+	NO_MAP_LOCK_REQUIRED;
+	const char *name = luaL_checkstring(L, 1);
+	// Get server from registry
+	Server *server = getServer(L);
+	// Do it
+	lua_newtable(L);
+	int table = lua_gettop(L);
+	std::set<std::string> privs_s = server->getPlayerEffectivePrivs(name);
+	for(std::set<std::string>::const_iterator
+			i = privs_s.begin(); i != privs_s.end(); i++){
+		lua_pushboolean(L, true);
+		lua_setfield(L, table, i->c_str());
+	}
+	lua_pushvalue(L, table);
+	return 1;
+}
+
+// get_player_ip()
+int ModApiServer::l_get_player_ip(lua_State *L)
+{
+	NO_MAP_LOCK_REQUIRED;
+	const char * name = luaL_checkstring(L, 1);
+	Player *player = getEnv(L)->getPlayer(name);
+	if(player == NULL)
+	{
+		lua_pushnil(L); // no such player
+		return 1;
+	}
+	try
+	{
+		Address addr = getServer(L)->getPeerAddress(getEnv(L)->getPlayer(name)->peer_id);
+		std::string ip_str = addr.serializeString();
+		lua_pushstring(L, ip_str.c_str());
+		return 1;
+	}
+	catch(con::PeerNotFoundException) // unlikely
+	{
+		dstream << __FUNCTION_NAME << ": peer was not found" << std::endl;
+		lua_pushnil(L); // error
+		return 1;
+	}
+}
+
+// get_ban_list()
+int ModApiServer::l_get_ban_list(lua_State *L)
+{
+	NO_MAP_LOCK_REQUIRED;
+	lua_pushstring(L, getServer(L)->getBanDescription("").c_str());
+	return 1;
+}
+
+// get_ban_description()
+int ModApiServer::l_get_ban_description(lua_State *L)
+{
+	NO_MAP_LOCK_REQUIRED;
+	const char * ip_or_name = luaL_checkstring(L, 1);
+	lua_pushstring(L, getServer(L)->getBanDescription(std::string(ip_or_name)).c_str());
+	return 1;
+}
+
+// ban_player()
+int ModApiServer::l_ban_player(lua_State *L)
+{
+	NO_MAP_LOCK_REQUIRED;
+	const char * name = luaL_checkstring(L, 1);
+	Player *player = getEnv(L)->getPlayer(name);
+	if(player == NULL)
+	{
+		lua_pushboolean(L, false); // no such player
+		return 1;
+	}
+	try
+	{
+		Address addr = getServer(L)->getPeerAddress(getEnv(L)->getPlayer(name)->peer_id);
+		std::string ip_str = addr.serializeString();
+		getServer(L)->setIpBanned(ip_str, name);
+	}
+	catch(con::PeerNotFoundException) // unlikely
+	{
+		dstream << __FUNCTION_NAME << ": peer was not found" << std::endl;
+		lua_pushboolean(L, false); // error
+		return 1;
+	}
+	lua_pushboolean(L, true);
+	return 1;
+}
+
+// unban_player_or_ip()
+int ModApiServer::l_unban_player_or_ip(lua_State *L)
+{
+	NO_MAP_LOCK_REQUIRED;
+	const char * ip_or_name = luaL_checkstring(L, 1);
+	getServer(L)->unsetIpBanned(ip_or_name);
+	lua_pushboolean(L, true);
+	return 1;
+}
+
+// show_formspec(playername,formname,formspec)
+int ModApiServer::l_show_formspec(lua_State *L)
+{
+	NO_MAP_LOCK_REQUIRED;
+	const char *playername = luaL_checkstring(L, 1);
+	const char *formname = luaL_checkstring(L, 2);
+	const char *formspec = luaL_checkstring(L, 3);
+
+	if(getServer(L)->showFormspec(playername,formspec,formname))
+	{
+		lua_pushboolean(L, true);
+	}else{
+		lua_pushboolean(L, false);
+	}
+	return 1;
+}
+
+// get_current_modname()
+int ModApiServer::l_get_current_modname(lua_State *L)
+{
+	NO_MAP_LOCK_REQUIRED;
+	lua_getfield(L, LUA_REGISTRYINDEX, "minetest_current_modname");
+	return 1;
+}
+
+// get_modpath(modname)
+int ModApiServer::l_get_modpath(lua_State *L)
+{
+	NO_MAP_LOCK_REQUIRED;
+	std::string modname = luaL_checkstring(L, 1);
+	// Do it
+	if(modname == "__builtin"){
+		std::string path = getServer(L)->getBuiltinLuaPath();
+		lua_pushstring(L, path.c_str());
+		return 1;
+	}
+	const ModSpec *mod = getServer(L)->getModSpec(modname);
+	if(!mod){
+		lua_pushnil(L);
+		return 1;
+	}
+	lua_pushstring(L, mod->path.c_str());
+	return 1;
+}
+
+// get_modnames()
+// the returned list is sorted alphabetically for you
+int ModApiServer::l_get_modnames(lua_State *L)
+{
+	NO_MAP_LOCK_REQUIRED;
+	// Get a list of mods
+	std::list<std::string> mods_unsorted, mods_sorted;
+	getServer(L)->getModNames(mods_unsorted);
+
+	// Take unsorted items from mods_unsorted and sort them into
+	// mods_sorted; not great performance but the number of mods on a
+	// server will likely be small.
+	for(std::list<std::string>::iterator i = mods_unsorted.begin();
+		i != mods_unsorted.end(); ++i)
+	{
+		bool added = false;
+		for(std::list<std::string>::iterator x = mods_sorted.begin();
+			x != mods_sorted.end(); ++x)
+		{
+			// I doubt anybody using Minetest will be using
+			// anything not ASCII based :)
+			if((*i).compare(*x) <= 0)
+			{
+				mods_sorted.insert(x, *i);
+				added = true;
+				break;
+			}
+		}
+		if(!added)
+			mods_sorted.push_back(*i);
+	}
+
+	// Get the table insertion function from Lua.
+	lua_getglobal(L, "table");
+	lua_getfield(L, -1, "insert");
+	int insertion_func = lua_gettop(L);
+
+	// Package them up for Lua
+	lua_newtable(L);
+	int new_table = lua_gettop(L);
+	std::list<std::string>::iterator i = mods_sorted.begin();
+	while(i != mods_sorted.end())
+	{
+		lua_pushvalue(L, insertion_func);
+		lua_pushvalue(L, new_table);
+		lua_pushstring(L, (*i).c_str());
+		if(lua_pcall(L, 2, 0, 0) != 0)
+		{
+			script_error(L, "error: %s", lua_tostring(L, -1));
+		}
+		++i;
+	}
+	return 1;
+}
+
+// get_worldpath()
+int ModApiServer::l_get_worldpath(lua_State *L)
+{
+	NO_MAP_LOCK_REQUIRED;
+	std::string worldpath = getServer(L)->getWorldPath();
+	lua_pushstring(L, worldpath.c_str());
+	return 1;
+}
+
+// sound_play(spec, parameters)
+int ModApiServer::l_sound_play(lua_State *L)
+{
+	NO_MAP_LOCK_REQUIRED;
+	SimpleSoundSpec spec;
+	read_soundspec(L, 1, spec);
+	ServerSoundParams params;
+	read_server_sound_params(L, 2, params);
+	s32 handle = getServer(L)->playSound(spec, params);
+	lua_pushinteger(L, handle);
+	return 1;
+}
+
+// sound_stop(handle)
+int ModApiServer::l_sound_stop(lua_State *L)
+{
+	NO_MAP_LOCK_REQUIRED;
+	int handle = luaL_checkinteger(L, 1);
+	getServer(L)->stopSound(handle);
+	return 0;
+}
+
+// is_singleplayer()
+int ModApiServer::l_is_singleplayer(lua_State *L)
+{
+	NO_MAP_LOCK_REQUIRED;
+	lua_pushboolean(L, getServer(L)->isSingleplayer());
+	return 1;
+}
+
+// notify_authentication_modified(name)
+int ModApiServer::l_notify_authentication_modified(lua_State *L)
+{
+	NO_MAP_LOCK_REQUIRED;
+	std::string name = "";
+	if(lua_isstring(L, 1))
+		name = lua_tostring(L, 1);
+	getServer(L)->reportPrivsModified(name);
+	return 0;
+}
+
+void ModApiServer::Initialize(lua_State *L, int top)
+{
+	API_FCT(request_shutdown);
+	API_FCT(get_server_status);
+	API_FCT(get_worldpath);
+	API_FCT(is_singleplayer);
+
+	API_FCT(get_current_modname);
+	API_FCT(get_modpath);
+	API_FCT(get_modnames);
+
+	API_FCT(chat_send_all);
+	API_FCT(chat_send_player);
+	API_FCT(show_formspec);
+	API_FCT(sound_play);
+	API_FCT(sound_stop);
+
+	API_FCT(get_player_privs);
+	API_FCT(get_player_ip);
+	API_FCT(get_ban_list);
+	API_FCT(get_ban_description);
+	API_FCT(ban_player);
+	API_FCT(unban_player_or_ip);
+	API_FCT(notify_authentication_modified);
+}
diff --git a/src/script/lua_api/luaapi.h b/src/script/lua_api/l_server.h
similarity index 54%
rename from src/script/lua_api/luaapi.h
rename to src/script/lua_api/l_server.h
index af73625ba..21f300400 100644
--- a/src/script/lua_api/luaapi.h
+++ b/src/script/lua_api/l_server.h
@@ -17,48 +17,34 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
 
-#ifndef LUAAPI_H_
-#define LUAAPI_H_
+#ifndef L_SERVER_H_
+#define L_SERVER_H_
 
+#include "lua_api/l_base.h"
 
-class ModApiBasic : public ModApiBase {
-
-public:
-	ModApiBasic();
-
-	bool Initialize(lua_State* L,int top);
-
+class ModApiServer : public ModApiBase {
 private:
-	// debug(text)
-	// Writes a line to dstream
-	static int l_debug(lua_State *L);
-
-	// log([level,] text)
-	// Writes a line to the logger.
-	// The one-argument version logs to infostream.
-	// The two-argument version accept a log level: error, action, info, or verbose.
-	static int l_log(lua_State *L);
-
 	// request_shutdown()
 	static int l_request_shutdown(lua_State *L);
 
 	// get_server_status()
 	static int l_get_server_status(lua_State *L);
 
-	// register_biome({lots of stuff})
-	static int l_register_biome(lua_State *L);
+	// get_worldpath()
+	static int l_get_worldpath(lua_State *L);
 
-	// setting_set(name, value)
-	static int l_setting_set(lua_State *L);
+	// is_singleplayer()
+	static int l_is_singleplayer(lua_State *L);
 
-	// setting_get(name)
-	static int l_setting_get(lua_State *L);
+	// get_current_modname()
+	static int l_get_current_modname(lua_State *L);
 
-	// setting_getbool(name)
-	static int l_setting_getbool(lua_State *L);
+	// get_modpath(modname)
+	static int l_get_modpath(lua_State *L);
 
-	// setting_save()
-	static int l_setting_save(lua_State *L);
+	// get_modnames()
+	// the returned list is sorted alphabetically for you
+	static int l_get_modnames(lua_State *L);
 
 	// chat_send_all(text)
 	static int l_chat_send_all(lua_State *L);
@@ -66,6 +52,15 @@ class ModApiBasic : public ModApiBase {
 	// chat_send_player(name, text)
 	static int l_chat_send_player(lua_State *L);
 
+	// show_formspec(playername,formname,formspec)
+	static int l_show_formspec(lua_State *L);
+
+	// sound_play(spec, parameters)
+	static int l_sound_play(lua_State *L);
+
+	// sound_stop(handle)
+	static int l_sound_stop(lua_State *L);
+
 	// get_player_privs(name, text)
 	static int l_get_player_privs(lua_State *L);
 
@@ -84,67 +79,12 @@ class ModApiBasic : public ModApiBase {
 	// unban_player_or_ip()
 	static int l_unban_player_or_ip(lua_State *L);
 
-	// show_formspec(playername,formname,formspec)
-	static int l_show_formspec(lua_State *L);
-
-	// get_dig_params(groups, tool_capabilities[, time_from_last_punch])
-	static int l_get_dig_params(lua_State *L);
-
-	// get_hit_params(groups, tool_capabilities[, time_from_last_punch])
-	static int l_get_hit_params(lua_State *L);
-
-	// get_current_modname()
-	static int l_get_current_modname(lua_State *L);
-
-	// get_modpath(modname)
-	static int l_get_modpath(lua_State *L);
-
-	// get_modnames()
-	// the returned list is sorted alphabetically for you
-	static int l_get_modnames(lua_State *L);
-
-	// get_worldpath()
-	static int l_get_worldpath(lua_State *L);
-
-	// sound_play(spec, parameters)
-	static int l_sound_play(lua_State *L);
-
-	// sound_stop(handle)
-	static int l_sound_stop(lua_State *L);
-
-	// is_singleplayer()
-	static int l_is_singleplayer(lua_State *L);
-
-	// get_password_hash(name, raw_password)
-	static int l_get_password_hash(lua_State *L);
-
 	// notify_authentication_modified(name)
 	static int l_notify_authentication_modified(lua_State *L);
 
-	// rollback_get_last_node_actor(p, range, seconds) -> actor, p, seconds
-	static int l_rollback_get_last_node_actor(lua_State *L);
-
-	// rollback_revert_actions_by(actor, seconds) -> bool, log messages
-	static int l_rollback_revert_actions_by(lua_State *L);
-
-	// register_ore(oredesc)
-	static int l_register_ore(lua_State *L);
-	
-	// register_decoration(deco)
-	static int l_register_decoration(lua_State *L);
-	
-	// create_schematic(p1, p2, filename)
-	static int l_create_schematic(lua_State *L);
-	
-	// place_schematic(p, filename, rotation)
-	static int l_place_schematic(lua_State *L);
-
-	static struct EnumString es_OreType[];
-	static struct EnumString es_DecorationType[];
-	static struct EnumString es_Rotation[];
+public:
+	static void Initialize(lua_State *L, int top);
 
 };
 
-
-
-#endif /* LUAAPI_H_ */
+#endif /* L_SERVER_H_ */
diff --git a/src/script/lua_api/l_util.cpp b/src/script/lua_api/l_util.cpp
new file mode 100644
index 000000000..0e4de9eee
--- /dev/null
+++ b/src/script/lua_api/l_util.cpp
@@ -0,0 +1,199 @@
+/*
+Minetest
+Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "lua_api/l_util.h"
+#include "lua_api/l_internal.h"
+#include "common/c_converter.h"
+#include "common/c_content.h"
+#include "debug.h"
+#include "log.h"
+#include "tool.h"
+#include "settings.h"
+#include "main.h"  //required for g_settings, g_settings_path
+
+// debug(...)
+// Writes a line to dstream
+int ModApiUtil::l_debug(lua_State *L)
+{
+	NO_MAP_LOCK_REQUIRED;
+	// Handle multiple parameters to behave like standard lua print()
+	int n = lua_gettop(L);
+	lua_getglobal(L, "tostring");
+	for (int i = 1; i <= n; i++) {
+		/*
+			Call tostring(i-th argument).
+			This is what print() does, and it behaves a bit
+			differently from directly calling lua_tostring.
+		*/
+		lua_pushvalue(L, -1);  /* function to be called */
+		lua_pushvalue(L, i);   /* value to print */
+		lua_call(L, 1, 1);
+		const char *s = lua_tostring(L, -1);
+		if (i>1)
+			dstream << "\t";
+		if (s)
+			dstream << s;
+		lua_pop(L, 1);
+	}
+	dstream << std::endl;
+	return 0;
+}
+
+// log([level,] text)
+// Writes a line to the logger.
+// The one-argument version logs to infostream.
+// The two-argument version accept a log level: error, action, info, or verbose.
+int ModApiUtil::l_log(lua_State *L)
+{
+	NO_MAP_LOCK_REQUIRED;
+	std::string text;
+	LogMessageLevel level = LMT_INFO;
+	if (lua_isnone(L, 2)) {
+		text = lua_tostring(L, 1);
+	}
+	else {
+		std::string levelname = luaL_checkstring(L, 1);
+		text = luaL_checkstring(L, 2);
+		if(levelname == "error")
+			level = LMT_ERROR;
+		else if(levelname == "action")
+			level = LMT_ACTION;
+		else if(levelname == "verbose")
+			level = LMT_VERBOSE;
+	}
+	log_printline(level, text);
+	return 0;
+}
+
+// setting_set(name, value)
+int ModApiUtil::l_setting_set(lua_State *L)
+{
+	NO_MAP_LOCK_REQUIRED;
+	const char *name = luaL_checkstring(L, 1);
+	const char *value = luaL_checkstring(L, 2);
+	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;
+	const char *name = luaL_checkstring(L, 1);
+	bool value = lua_toboolean(L, 2);
+	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;
+}
+
+// get_dig_params(groups, tool_capabilities[, time_from_last_punch])
+int ModApiUtil::l_get_dig_params(lua_State *L)
+{
+	NO_MAP_LOCK_REQUIRED;
+	std::map<std::string, int> groups;
+	read_groups(L, 1, groups);
+	ToolCapabilities tp = read_tool_capabilities(L, 2);
+	if(lua_isnoneornil(L, 3))
+		push_dig_params(L, getDigParams(groups, &tp));
+	else
+		push_dig_params(L, getDigParams(groups, &tp,
+					luaL_checknumber(L, 3)));
+	return 1;
+}
+
+// get_hit_params(groups, tool_capabilities[, time_from_last_punch])
+int ModApiUtil::l_get_hit_params(lua_State *L)
+{
+	NO_MAP_LOCK_REQUIRED;
+	std::map<std::string, int> groups;
+	read_groups(L, 1, groups);
+	ToolCapabilities tp = read_tool_capabilities(L, 2);
+	if(lua_isnoneornil(L, 3))
+		push_hit_params(L, getHitParams(groups, &tp));
+	else
+		push_hit_params(L, getHitParams(groups, &tp,
+					luaL_checknumber(L, 3)));
+	return 1;
+}
+
+// get_password_hash(name, raw_password)
+int ModApiUtil::l_get_password_hash(lua_State *L)
+{
+	NO_MAP_LOCK_REQUIRED;
+	std::string name = luaL_checkstring(L, 1);
+	std::string raw_password = luaL_checkstring(L, 2);
+	std::string hash = translatePassword(name,
+			narrow_to_wide(raw_password));
+	lua_pushstring(L, hash.c_str());
+	return 1;
+}
+
+void ModApiUtil::Initialize(lua_State *L, int top)
+{
+	API_FCT(debug);
+	API_FCT(log);
+
+	API_FCT(setting_set);
+	API_FCT(setting_get);
+	API_FCT(setting_setbool);
+	API_FCT(setting_getbool);
+	API_FCT(setting_save);
+
+	API_FCT(get_dig_params);
+	API_FCT(get_hit_params);
+
+	API_FCT(get_password_hash);
+}
+
diff --git a/src/script/lua_api/l_util.h b/src/script/lua_api/l_util.h
new file mode 100644
index 000000000..b102e315b
--- /dev/null
+++ b/src/script/lua_api/l_util.h
@@ -0,0 +1,76 @@
+/*
+Minetest
+Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef L_UTIL_H_
+#define L_UTIL_H_
+
+#include "lua_api/l_base.h"
+
+class ModApiUtil : public ModApiBase {
+private:
+	/*
+		NOTE:
+		The functions in this module are available through
+		minetest.<function> in the in-game API as well as
+		engine.<function> in the mainmenu API
+
+		All functions that don't require either a Server or
+		GUIEngine instance should be in here.
+	*/
+
+	// debug(text)
+	// Writes a line to dstream
+	static int l_debug(lua_State *L);
+
+	// log([level,] text)
+	// Writes a line to the logger.
+	// The one-argument version logs to infostream.
+	// The two-argument version accept a log level: error, action, info, or verbose.
+	static int l_log(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);
+
+	// get_dig_params(groups, tool_capabilities[, time_from_last_punch])
+	static int l_get_dig_params(lua_State *L);
+
+	// get_hit_params(groups, tool_capabilities[, time_from_last_punch])
+	static int l_get_hit_params(lua_State *L);
+
+	// get_password_hash(name, raw_password)
+	static int l_get_password_hash(lua_State *L);
+
+public:
+	static void Initialize(lua_State *L, int top);
+
+};
+
+#endif /* L_UTIL_H_ */
diff --git a/src/script/lua_api/l_vmanip.cpp b/src/script/lua_api/l_vmanip.cpp
index 195682579..1e9cc350f 100644
--- a/src/script/lua_api/l_vmanip.cpp
+++ b/src/script/lua_api/l_vmanip.cpp
@@ -18,16 +18,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 */
 
 
-#include "lua_api/l_base.h"
 #include "lua_api/l_vmanip.h"
-
-///////
-
-#include "cpp_api/scriptapi.h"
+#include "lua_api/l_internal.h"
 #include "common/c_converter.h"
-#include "server.h"
 #include "emerge.h"
-#include "common/c_internal.h"
+#include "environment.h"
+#include "map.h"
+#include "server.h"
+#include "mapgen.h"
 
 // garbage collector
 int LuaVoxelManip::gc_object(lua_State *L)
@@ -111,9 +109,13 @@ int LuaVoxelManip::l_write_to_map(lua_State *L)
 int LuaVoxelManip::l_update_liquids(lua_State *L)
 {
 	LuaVoxelManip *o = checkobject(L, 1);
-	
-	INodeDefManager *ndef = STACK_TO_SERVER(L)->getNodeDefManager();
-	Map *map = &(get_scriptapi(L)->getEnv()->getMap());
+
+	Environment *env = getEnv(L);
+	if (!env)
+		return 0;
+
+	Map *map = &(env->getMap());
+	INodeDefManager *ndef = getServer(L)->getNodeDefManager();
 	ManualMapVoxelManipulator *vm = o->vm;
 
 	Mapgen mg;
@@ -134,8 +136,8 @@ int LuaVoxelManip::l_calc_lighting(lua_State *L)
 	if (!o->is_mapgen_vm)
 		return 0;
 		
-	INodeDefManager *ndef = STACK_TO_SERVER(L)->getNodeDefManager();
-	EmergeManager *emerge = STACK_TO_SERVER(L)->getEmergeManager();
+	INodeDefManager *ndef = getServer(L)->getNodeDefManager();
+	EmergeManager *emerge = getServer(L)->getEmergeManager();
 	ManualMapVoxelManipulator *vm = o->vm;
 
 	Mapgen mg;
@@ -182,13 +184,18 @@ int LuaVoxelManip::l_update_map(lua_State *L)
 	if (o->is_mapgen_vm)
 		return 0;
 	
+	Environment *env = getEnv(L);
+	if (!env)
+		return 0;
+
+	Map *map = &(env->getMap());
+
 	// TODO: Optimize this by using Mapgen::calcLighting() instead
 	std::map<v3s16, MapBlock *> lighting_mblocks;
 	std::map<v3s16, MapBlock *> *mblocks = &o->modified_blocks;
 	
 	lighting_mblocks.insert(mblocks->begin(), mblocks->end());
 	
-	Map *map = &(get_scriptapi(L)->getEnv()->getMap());
 	map->updateLighting(lighting_mblocks, *mblocks);
 
 	MapEditEvent event;
@@ -228,7 +235,7 @@ int LuaVoxelManip::create_object(lua_State *L)
 {
 	NO_MAP_LOCK_REQUIRED;
 	
-	Environment *env = get_scriptapi(L)->getEnv();
+	Environment *env = getEnv(L);
 	if (!env)
 		return 0;
 		
@@ -278,7 +285,7 @@ void LuaVoxelManip::Register(lua_State *L)
 	luaL_openlib(L, 0, methods, 0);  // fill methodtable
 	lua_pop(L, 1);  // drop methodtable
 
-	// Can be created from Lua (VoxelManip()
+	// Can be created from Lua (VoxelManip())
 	lua_register(L, className, create_object);
 }
 
@@ -294,5 +301,3 @@ const luaL_reg LuaVoxelManip::methods[] = {
 	luamethod(LuaVoxelManip, set_lighting),
 	{0,0}
 };
-
-REGISTER_LUA_REF(LuaVoxelManip);
diff --git a/src/script/lua_api/l_vmanip.h b/src/script/lua_api/l_vmanip.h
index a7791e56b..d2f035a3e 100644
--- a/src/script/lua_api/l_vmanip.h
+++ b/src/script/lua_api/l_vmanip.h
@@ -20,19 +20,18 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #ifndef L_VMANIP_H_
 #define L_VMANIP_H_
 
-extern "C" {
-#include <lua.h>
-#include <lauxlib.h>
-}
-
+#include "lua_api/l_base.h"
 #include "irr_v3d.h"
-#include "map.h"
+#include <map>
+
+class Map;
+class MapBlock;
+class ManualMapVoxelManipulator;
 
 /*
   VoxelManip
  */
-class LuaVoxelManip
-{
+class LuaVoxelManip : public ModApiBase {
 private:
 	ManualMapVoxelManipulator *vm;
 	std::map<v3s16, MapBlock *> modified_blocks;
@@ -67,4 +66,4 @@ class LuaVoxelManip
 	static void Register(lua_State *L);
 };
 
-#endif // L_VMANIP_H_
+#endif /* L_VMANIP_H_ */
diff --git a/src/script/lua_api/luaapi.cpp b/src/script/lua_api/luaapi.cpp
deleted file mode 100644
index 26fb0c318..000000000
--- a/src/script/lua_api/luaapi.cpp
+++ /dev/null
@@ -1,955 +0,0 @@
-/*
-Minetest
-Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU Lesser General Public License as published by
-the Free Software Foundation; either version 2.1 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public License along
-with this program; if not, write to the Free Software Foundation, Inc.,
-51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-*/
-
-extern "C" {
-#include "lua.h"
-#include "lauxlib.h"
-}
-
-#include "lua_api/l_base.h"
-#include "common/c_internal.h"
-#include "server.h"
-#include "common/c_converter.h"
-#include "common/c_content.h"
-#include "lua_api/luaapi.h"
-#include "settings.h"
-#include "tool.h"
-#include "rollback.h"
-#include "log.h"
-#include "emerge.h"
-#include "main.h"  //required for g_settings
-
-struct EnumString ModApiBasic::es_OreType[] =
-{
-	{ORE_SCATTER,  "scatter"},
-	{ORE_SHEET,    "sheet"},
-	{ORE_CLAYLIKE, "claylike"},
-	{0, NULL},
-};
-
-struct EnumString ModApiBasic::es_DecorationType[] =
-{
-	{DECO_SIMPLE,    "simple"},
-	{DECO_SCHEMATIC, "schematic"},
-	{DECO_LSYSTEM,   "lsystem"},
-	{0, NULL},
-};
-
-struct EnumString ModApiBasic::es_Rotation[] =
-{
-	{ROTATE_0,    "0"},
-	{ROTATE_90,   "90"},
-	{ROTATE_180,  "180"},
-	{ROTATE_270,  "270"},
-	{ROTATE_RAND, "random"},
-	{0, NULL},
-};
-
-
-ModApiBasic::ModApiBasic() : ModApiBase() {
-}
-
-bool ModApiBasic::Initialize(lua_State* L,int top) {
-
-	bool retval = true;
-
-	retval &= API_FCT(debug);
-	retval &= API_FCT(log);
-	retval &= API_FCT(request_shutdown);
-	retval &= API_FCT(get_server_status);
-
-	retval &= API_FCT(register_biome);
-
-	retval &= API_FCT(setting_set);
-	retval &= API_FCT(setting_get);
-	retval &= API_FCT(setting_getbool);
-	retval &= API_FCT(setting_save);
-
-	retval &= API_FCT(chat_send_all);
-	retval &= API_FCT(chat_send_player);
-	retval &= API_FCT(show_formspec);
-
-	retval &= API_FCT(get_player_privs);
-	retval &= API_FCT(get_player_ip);
-	retval &= API_FCT(get_ban_list);
-	retval &= API_FCT(get_ban_description);
-	retval &= API_FCT(ban_player);
-	retval &= API_FCT(unban_player_or_ip);
-	retval &= API_FCT(get_password_hash);
-	retval &= API_FCT(notify_authentication_modified);
-
-	retval &= API_FCT(get_dig_params);
-	retval &= API_FCT(get_hit_params);
-
-	retval &= API_FCT(get_current_modname);
-	retval &= API_FCT(get_modpath);
-	retval &= API_FCT(get_modnames);
-
-	retval &= API_FCT(get_worldpath);
-	retval &= API_FCT(is_singleplayer);
-	retval &= API_FCT(sound_play);
-	retval &= API_FCT(sound_stop);
-
-	retval &= API_FCT(rollback_get_last_node_actor);
-	retval &= API_FCT(rollback_revert_actions_by);
-
-	retval &= API_FCT(register_ore);
-	retval &= API_FCT(register_decoration);
-	retval &= API_FCT(create_schematic);
-	retval &= API_FCT(place_schematic);
-
-	return retval;
-}
-
-// debug(...)
-// Writes a line to dstream
-int ModApiBasic::l_debug(lua_State *L)
-{
-	NO_MAP_LOCK_REQUIRED;
-	// Handle multiple parameters to behave like standard lua print()
-	int n = lua_gettop(L);
-	lua_getglobal(L, "tostring");
-	for(int i = 1; i <= n; i++){
-		/*
-			Call tostring(i-th argument).
-			This is what print() does, and it behaves a bit
-			differently from directly calling lua_tostring.
-		*/
-		lua_pushvalue(L, -1);  /* function to be called */
-		lua_pushvalue(L, i);   /* value to print */
-		lua_call(L, 1, 1);
-		const char *s = lua_tostring(L, -1);
-		if(i>1)
-			dstream << "\t";
-		if(s)
-			dstream << s;
-		lua_pop(L, 1);
-	}
-	dstream << std::endl;
-	return 0;
-}
-
-// log([level,] text)
-// Writes a line to the logger.
-// The one-argument version logs to infostream.
-// The two-argument version accept a log level: error, action, info, or verbose.
-int ModApiBasic::l_log(lua_State *L)
-{
-	NO_MAP_LOCK_REQUIRED;
-	std::string text;
-	LogMessageLevel level = LMT_INFO;
-	if(lua_isnone(L, 2))
-	{
-		text = lua_tostring(L, 1);
-	}
-	else
-	{
-		std::string levelname = luaL_checkstring(L, 1);
-		text = luaL_checkstring(L, 2);
-		if(levelname == "error")
-			level = LMT_ERROR;
-		else if(levelname == "action")
-			level = LMT_ACTION;
-		else if(levelname == "verbose")
-			level = LMT_VERBOSE;
-	}
-	log_printline(level, text);
-	return 0;
-}
-
-// request_shutdown()
-int ModApiBasic::l_request_shutdown(lua_State *L)
-{
-	getServer(L)->requestShutdown();
-	return 0;
-}
-
-// get_server_status()
-int ModApiBasic::l_get_server_status(lua_State *L)
-{
-	NO_MAP_LOCK_REQUIRED;
-	lua_pushstring(L, wide_to_narrow(getServer(L)->getStatusString()).c_str());
-	return 1;
-}
-
-// register_biome({lots of stuff})
-int ModApiBasic::l_register_biome(lua_State *L)
-{
-	int index = 1;
-	luaL_checktype(L, index, LUA_TTABLE);
-
-	BiomeDefManager *bmgr = getServer(L)->getEmergeManager()->biomedef;
-	if (!bmgr) {
-		verbosestream << "register_biome: BiomeDefManager not active" << std::endl;
-		return 0;
-	}
-
-	enum BiomeTerrainType terrain = (BiomeTerrainType)getenumfield(L, index,
-				"terrain_type", es_BiomeTerrainType, BIOME_TERRAIN_NORMAL);
-	Biome *b = bmgr->createBiome(terrain);
-
-	b->name         = getstringfield_default(L, index, "name",
-												"<no name>");
-	b->nname_top    = getstringfield_default(L, index, "node_top",
-												"mapgen_dirt_with_grass");
-	b->nname_filler = getstringfield_default(L, index, "node_filler",
-												"mapgen_dirt");
-	b->nname_water  = getstringfield_default(L, index, "node_water",
-												"mapgen_water_source");
-	b->nname_dust   = getstringfield_default(L, index, "node_dust",
-												"air");
-	b->nname_dust_water = getstringfield_default(L, index, "node_dust_water",
-												"mapgen_water_source");
-	
-	b->depth_top      = getintfield_default(L, index, "depth_top",    1);
-	b->depth_filler   = getintfield_default(L, index, "depth_filler", 3);
-	b->height_min     = getintfield_default(L, index, "height_min",   0);
-	b->height_max     = getintfield_default(L, index, "height_max",   0);
-	b->heat_point     = getfloatfield_default(L, index, "heat_point",     0.);
-	b->humidity_point = getfloatfield_default(L, index, "humidity_point", 0.);
-
-	b->flags        = 0; //reserved
-	b->c_top        = CONTENT_IGNORE;
-	b->c_filler     = CONTENT_IGNORE;
-	b->c_water      = CONTENT_IGNORE;
-	b->c_dust       = CONTENT_IGNORE;
-	b->c_dust_water = CONTENT_IGNORE;
-	
-	verbosestream << "register_biome: " << b->name << std::endl;
-	bmgr->addBiome(b);
-
-	return 0;
-}
-
-// setting_set(name, value)
-int ModApiBasic::l_setting_set(lua_State *L)
-{
-	NO_MAP_LOCK_REQUIRED;
-	const char *name = luaL_checkstring(L, 1);
-	const char *value = luaL_checkstring(L, 2);
-	g_settings->set(name, value);
-	return 0;
-}
-
-// setting_get(name)
-int ModApiBasic::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_getbool(name)
-int ModApiBasic::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 ModApiBasic::l_setting_save(lua_State *L)
-{
-	NO_MAP_LOCK_REQUIRED;
-	getServer(L)->saveConfig();
-	return 0;
-}
-
-// chat_send_all(text)
-int ModApiBasic::l_chat_send_all(lua_State *L)
-{
-	NO_MAP_LOCK_REQUIRED;
-	const char *text = luaL_checkstring(L, 1);
-	// Get server from registry
-	Server *server = getServer(L);
-	// Send
-	server->notifyPlayers(narrow_to_wide(text));
-	return 0;
-}
-
-// chat_send_player(name, text, prepend)
-int ModApiBasic::l_chat_send_player(lua_State *L)
-{
-	NO_MAP_LOCK_REQUIRED;
-	const char *name = luaL_checkstring(L, 1);
-	const char *text = luaL_checkstring(L, 2);
-	bool prepend = true;
-
-	if (lua_isboolean(L, 3))
-		prepend = lua_toboolean(L, 3);
-
-	// Get server from registry
-	Server *server = getServer(L);
-	// Send
-	server->notifyPlayer(name, narrow_to_wide(text), prepend);
-	return 0;
-}
-
-// get_player_privs(name, text)
-int ModApiBasic::l_get_player_privs(lua_State *L)
-{
-	NO_MAP_LOCK_REQUIRED;
-	const char *name = luaL_checkstring(L, 1);
-	// Get server from registry
-	Server *server = getServer(L);
-	// Do it
-	lua_newtable(L);
-	int table = lua_gettop(L);
-	std::set<std::string> privs_s = server->getPlayerEffectivePrivs(name);
-	for(std::set<std::string>::const_iterator
-			i = privs_s.begin(); i != privs_s.end(); i++){
-		lua_pushboolean(L, true);
-		lua_setfield(L, table, i->c_str());
-	}
-	lua_pushvalue(L, table);
-	return 1;
-}
-
-// get_player_ip()
-int ModApiBasic::l_get_player_ip(lua_State *L)
-{
-	NO_MAP_LOCK_REQUIRED;
-	const char * name = luaL_checkstring(L, 1);
-	Player *player = getEnv(L)->getPlayer(name);
-	if(player == NULL)
-	{
-		lua_pushnil(L); // no such player
-		return 1;
-	}
-	try
-	{
-		Address addr = getServer(L)->getPeerAddress(getEnv(L)->getPlayer(name)->peer_id);
-		std::string ip_str = addr.serializeString();
-		lua_pushstring(L, ip_str.c_str());
-		return 1;
-	}
-	catch(con::PeerNotFoundException) // unlikely
-	{
-		dstream << __FUNCTION_NAME << ": peer was not found" << std::endl;
-		lua_pushnil(L); // error
-		return 1;
-	}
-}
-
-// get_ban_list()
-int ModApiBasic::l_get_ban_list(lua_State *L)
-{
-	NO_MAP_LOCK_REQUIRED;
-	lua_pushstring(L, getServer(L)->getBanDescription("").c_str());
-	return 1;
-}
-
-// get_ban_description()
-int ModApiBasic::l_get_ban_description(lua_State *L)
-{
-	NO_MAP_LOCK_REQUIRED;
-	const char * ip_or_name = luaL_checkstring(L, 1);
-	lua_pushstring(L, getServer(L)->getBanDescription(std::string(ip_or_name)).c_str());
-	return 1;
-}
-
-// ban_player()
-int ModApiBasic::l_ban_player(lua_State *L)
-{
-	NO_MAP_LOCK_REQUIRED;
-	const char * name = luaL_checkstring(L, 1);
-	Player *player = getEnv(L)->getPlayer(name);
-	if(player == NULL)
-	{
-		lua_pushboolean(L, false); // no such player
-		return 1;
-	}
-	try
-	{
-		Address addr = getServer(L)->getPeerAddress(getEnv(L)->getPlayer(name)->peer_id);
-		std::string ip_str = addr.serializeString();
-		getServer(L)->setIpBanned(ip_str, name);
-	}
-	catch(con::PeerNotFoundException) // unlikely
-	{
-		dstream << __FUNCTION_NAME << ": peer was not found" << std::endl;
-		lua_pushboolean(L, false); // error
-		return 1;
-	}
-	lua_pushboolean(L, true);
-	return 1;
-}
-
-// unban_player_or_ip()
-int ModApiBasic::l_unban_player_or_ip(lua_State *L)
-{
-	NO_MAP_LOCK_REQUIRED;
-	const char * ip_or_name = luaL_checkstring(L, 1);
-	getServer(L)->unsetIpBanned(ip_or_name);
-	lua_pushboolean(L, true);
-	return 1;
-}
-
-// show_formspec(playername,formname,formspec)
-int ModApiBasic::l_show_formspec(lua_State *L)
-{
-	NO_MAP_LOCK_REQUIRED;
-	const char *playername = luaL_checkstring(L, 1);
-	const char *formname = luaL_checkstring(L, 2);
-	const char *formspec = luaL_checkstring(L, 3);
-
-	if(getServer(L)->showFormspec(playername,formspec,formname))
-	{
-		lua_pushboolean(L, true);
-	}else{
-		lua_pushboolean(L, false);
-	}
-	return 1;
-}
-
-// get_dig_params(groups, tool_capabilities[, time_from_last_punch])
-int ModApiBasic::l_get_dig_params(lua_State *L)
-{
-	NO_MAP_LOCK_REQUIRED;
-	std::map<std::string, int> groups;
-	read_groups(L, 1, groups);
-	ToolCapabilities tp = read_tool_capabilities(L, 2);
-	if(lua_isnoneornil(L, 3))
-		push_dig_params(L, getDigParams(groups, &tp));
-	else
-		push_dig_params(L, getDigParams(groups, &tp,
-					luaL_checknumber(L, 3)));
-	return 1;
-}
-
-// get_hit_params(groups, tool_capabilities[, time_from_last_punch])
-int ModApiBasic::l_get_hit_params(lua_State *L)
-{
-	NO_MAP_LOCK_REQUIRED;
-	std::map<std::string, int> groups;
-	read_groups(L, 1, groups);
-	ToolCapabilities tp = read_tool_capabilities(L, 2);
-	if(lua_isnoneornil(L, 3))
-		push_hit_params(L, getHitParams(groups, &tp));
-	else
-		push_hit_params(L, getHitParams(groups, &tp,
-					luaL_checknumber(L, 3)));
-	return 1;
-}
-
-// get_current_modname()
-int ModApiBasic::l_get_current_modname(lua_State *L)
-{
-	NO_MAP_LOCK_REQUIRED;
-	lua_getfield(L, LUA_REGISTRYINDEX, "minetest_current_modname");
-	return 1;
-}
-
-// get_modpath(modname)
-int ModApiBasic::l_get_modpath(lua_State *L)
-{
-	NO_MAP_LOCK_REQUIRED;
-	std::string modname = luaL_checkstring(L, 1);
-	// Do it
-	if(modname == "__builtin"){
-		std::string path = getServer(L)->getBuiltinLuaPath();
-		lua_pushstring(L, path.c_str());
-		return 1;
-	}
-	const ModSpec *mod = getServer(L)->getModSpec(modname);
-	if(!mod){
-		lua_pushnil(L);
-		return 1;
-	}
-	lua_pushstring(L, mod->path.c_str());
-	return 1;
-}
-
-// get_modnames()
-// the returned list is sorted alphabetically for you
-int ModApiBasic::l_get_modnames(lua_State *L)
-{
-	NO_MAP_LOCK_REQUIRED;
-	// Get a list of mods
-	std::list<std::string> mods_unsorted, mods_sorted;
-	getServer(L)->getModNames(mods_unsorted);
-
-	// Take unsorted items from mods_unsorted and sort them into
-	// mods_sorted; not great performance but the number of mods on a
-	// server will likely be small.
-	for(std::list<std::string>::iterator i = mods_unsorted.begin();
-		i != mods_unsorted.end(); ++i)
-	{
-		bool added = false;
-		for(std::list<std::string>::iterator x = mods_sorted.begin();
-			x != mods_sorted.end(); ++x)
-		{
-			// I doubt anybody using Minetest will be using
-			// anything not ASCII based :)
-			if((*i).compare(*x) <= 0)
-			{
-				mods_sorted.insert(x, *i);
-				added = true;
-				break;
-			}
-		}
-		if(!added)
-			mods_sorted.push_back(*i);
-	}
-
-	// Get the table insertion function from Lua.
-	lua_getglobal(L, "table");
-	lua_getfield(L, -1, "insert");
-	int insertion_func = lua_gettop(L);
-
-	// Package them up for Lua
-	lua_newtable(L);
-	int new_table = lua_gettop(L);
-	std::list<std::string>::iterator i = mods_sorted.begin();
-	while(i != mods_sorted.end())
-	{
-		lua_pushvalue(L, insertion_func);
-		lua_pushvalue(L, new_table);
-		lua_pushstring(L, (*i).c_str());
-		if(lua_pcall(L, 2, 0, 0) != 0)
-		{
-			script_error(L, "error: %s", lua_tostring(L, -1));
-		}
-		++i;
-	}
-	return 1;
-}
-
-// get_worldpath()
-int ModApiBasic::l_get_worldpath(lua_State *L)
-{
-	NO_MAP_LOCK_REQUIRED;
-	std::string worldpath = getServer(L)->getWorldPath();
-	lua_pushstring(L, worldpath.c_str());
-	return 1;
-}
-
-// sound_play(spec, parameters)
-int ModApiBasic::l_sound_play(lua_State *L)
-{
-	NO_MAP_LOCK_REQUIRED;
-	SimpleSoundSpec spec;
-	read_soundspec(L, 1, spec);
-	ServerSoundParams params;
-	read_server_sound_params(L, 2, params);
-	s32 handle = getServer(L)->playSound(spec, params);
-	lua_pushinteger(L, handle);
-	return 1;
-}
-
-// sound_stop(handle)
-int ModApiBasic::l_sound_stop(lua_State *L)
-{
-	NO_MAP_LOCK_REQUIRED;
-	int handle = luaL_checkinteger(L, 1);
-	getServer(L)->stopSound(handle);
-	return 0;
-}
-
-// is_singleplayer()
-int ModApiBasic::l_is_singleplayer(lua_State *L)
-{
-	NO_MAP_LOCK_REQUIRED;
-	lua_pushboolean(L, getServer(L)->isSingleplayer());
-	return 1;
-}
-
-// get_password_hash(name, raw_password)
-int ModApiBasic::l_get_password_hash(lua_State *L)
-{
-	NO_MAP_LOCK_REQUIRED;
-	std::string name = luaL_checkstring(L, 1);
-	std::string raw_password = luaL_checkstring(L, 2);
-	std::string hash = translatePassword(name,
-			narrow_to_wide(raw_password));
-	lua_pushstring(L, hash.c_str());
-	return 1;
-}
-
-// notify_authentication_modified(name)
-int ModApiBasic::l_notify_authentication_modified(lua_State *L)
-{
-	NO_MAP_LOCK_REQUIRED;
-	std::string name = "";
-	if(lua_isstring(L, 1))
-		name = lua_tostring(L, 1);
-	getServer(L)->reportPrivsModified(name);
-	return 0;
-}
-
-// rollback_get_last_node_actor(p, range, seconds) -> actor, p, seconds
-int ModApiBasic::l_rollback_get_last_node_actor(lua_State *L)
-{
-	v3s16 p = read_v3s16(L, 1);
-	int range = luaL_checknumber(L, 2);
-	int seconds = luaL_checknumber(L, 3);
-	Server *server = getServer(L);
-	IRollbackManager *rollback = server->getRollbackManager();
-	v3s16 act_p;
-	int act_seconds = 0;
-	std::string actor = rollback->getLastNodeActor(p, range, seconds, &act_p, &act_seconds);
-	lua_pushstring(L, actor.c_str());
-	push_v3s16(L, act_p);
-	lua_pushnumber(L, act_seconds);
-	return 3;
-}
-
-// rollback_revert_actions_by(actor, seconds) -> bool, log messages
-int ModApiBasic::l_rollback_revert_actions_by(lua_State *L)
-{
-	std::string actor = luaL_checkstring(L, 1);
-	int seconds = luaL_checknumber(L, 2);
-	Server *server = getServer(L);
-	IRollbackManager *rollback = server->getRollbackManager();
-	std::list<RollbackAction> actions = rollback->getRevertActions(actor, seconds);
-	std::list<std::string> log;
-	bool success = server->rollbackRevertActions(actions, &log);
-	// Push boolean result
-	lua_pushboolean(L, success);
-	// Get the table insert function and push the log table
-	lua_getglobal(L, "table");
-	lua_getfield(L, -1, "insert");
-	int table_insert = lua_gettop(L);
-	lua_newtable(L);
-	int table = lua_gettop(L);
-	for(std::list<std::string>::const_iterator i = log.begin();
-			i != log.end(); i++)
-	{
-		lua_pushvalue(L, table_insert);
-		lua_pushvalue(L, table);
-		lua_pushstring(L, i->c_str());
-		if(lua_pcall(L, 2, 0, 0))
-			script_error(L, "error: %s", lua_tostring(L, -1));
-	}
-	lua_remove(L, -2); // Remove table
-	lua_remove(L, -2); // Remove insert
-	return 2;
-}
-
-int ModApiBasic::l_register_ore(lua_State *L)
-{
-	int index = 1;
-	luaL_checktype(L, index, LUA_TTABLE);
-
-	EmergeManager *emerge = getServer(L)->getEmergeManager();
-
-	enum OreType oretype = (OreType)getenumfield(L, index,
-				"ore_type", es_OreType, ORE_SCATTER);
-	Ore *ore = createOre(oretype);
-	if (!ore) {
-		errorstream << "register_ore: ore_type "
-			<< oretype << " not implemented";
-		return 0;
-	}
-
-	ore->ore_name       = getstringfield_default(L, index, "ore", "");
-	ore->ore_param2     = (u8)getintfield_default(L, index, "ore_param2", 0);
-	ore->clust_scarcity = getintfield_default(L, index, "clust_scarcity", 1);
-	ore->clust_num_ores = getintfield_default(L, index, "clust_num_ores", 1);
-	ore->clust_size     = getintfield_default(L, index, "clust_size", 0);
-	ore->height_min     = getintfield_default(L, index, "height_min", 0);
-	ore->height_max     = getintfield_default(L, index, "height_max", 0);
-	ore->flags          = getflagsfield(L, index, "flags", flagdesc_ore);
-	ore->nthresh        = getfloatfield_default(L, index, "noise_threshhold", 0.);
-
-	lua_getfield(L, index, "wherein");
-	if (lua_istable(L, -1)) {
-		int  i = lua_gettop(L);
-		lua_pushnil(L);
-		while(lua_next(L, i) != 0) {
-			ore->wherein_names.push_back(lua_tostring(L, -1));
-			lua_pop(L, 1);
-		}
-	} else if (lua_isstring(L, -1)) {
-		ore->wherein_names.push_back(lua_tostring(L, -1));
-	} else {
-		ore->wherein_names.push_back("");
-	}
-	lua_pop(L, 1);
-
-	lua_getfield(L, index, "noise_params");
-	ore->np = read_noiseparams(L, -1);
-	lua_pop(L, 1);
-
-	ore->noise = NULL;
-
-	if (ore->clust_scarcity <= 0 || ore->clust_num_ores <= 0) {
-		errorstream << "register_ore: clust_scarcity and clust_num_ores"
-			"must be greater than 0" << std::endl;
-		delete ore;
-		return 0;
-	}
-
-	emerge->ores.push_back(ore);
-
-	verbosestream << "register_ore: ore '" << ore->ore_name
-		<< "' registered" << std::endl;
-	return 0;
-}
-
-// register_decoration({lots of stuff})
-int ModApiBasic::l_register_decoration(lua_State *L)
-{
-	int index = 1;
-	luaL_checktype(L, index, LUA_TTABLE);
-
-	EmergeManager *emerge = getServer(L)->getEmergeManager();
-	BiomeDefManager *bdef = emerge->biomedef;
-
-	enum DecorationType decotype = (DecorationType)getenumfield(L, index,
-				"deco_type", es_DecorationType, -1);
-	if (decotype == -1) {
-		errorstream << "register_decoration: unrecognized "
-			"decoration placement type";
-		return 0;
-	}
-	
-	Decoration *deco = createDecoration(decotype);
-	if (!deco) {
-		errorstream << "register_decoration: decoration placement type "
-			<< decotype << " not implemented";
-		return 0;
-	}
-
-	deco->c_place_on    = CONTENT_IGNORE;
-	deco->place_on_name = getstringfield_default(L, index, "place_on", "ignore");
-	deco->fill_ratio    = getfloatfield_default(L, index, "fill_ratio", 0.02);
-	deco->sidelen       = getintfield_default(L, index, "sidelen", 8);
-	if (deco->sidelen <= 0) {
-		errorstream << "register_decoration: sidelen must be "
-			"greater than 0" << std::endl;
-		delete deco;
-		return 0;
-	}
-	
-	lua_getfield(L, index, "noise_params");
-	deco->np = read_noiseparams(L, -1);
-	lua_pop(L, 1);
-	
-	lua_getfield(L, index, "biomes");
-	if (lua_istable(L, -1)) {
-		lua_pushnil(L);
-		while (lua_next(L, -2)) {
-			const char *s = lua_tostring(L, -1);
-			u8 biomeid = bdef->getBiomeIdByName(s);
-			if (biomeid)
-				deco->biomes.insert(biomeid);
-
-			lua_pop(L, 1);
-		}
-		lua_pop(L, 1);
-	}
-	
-	switch (decotype) {
-		case DECO_SIMPLE: {
-			DecoSimple *dsimple = (DecoSimple *)deco;
-			dsimple->c_deco     = CONTENT_IGNORE;
-			dsimple->c_spawnby  = CONTENT_IGNORE;
-			dsimple->spawnby_name    = getstringfield_default(L, index, "spawn_by", "air");
-			dsimple->deco_height     = getintfield_default(L, index, "height", 1);
-			dsimple->deco_height_max = getintfield_default(L, index, "height_max", 0);
-			dsimple->nspawnby        = getintfield_default(L, index, "num_spawn_by", -1);
-			
-			lua_getfield(L, index, "decoration");
-			if (lua_istable(L, -1)) {
-				lua_pushnil(L);
-				while (lua_next(L, -2)) {
-					const char *s = lua_tostring(L, -1);
-					std::string str(s);
-					dsimple->decolist_names.push_back(str);
-
-					lua_pop(L, 1);
-				}
-			} else if (lua_isstring(L, -1)) {
-				dsimple->deco_name = std::string(lua_tostring(L, -1));
-			} else {
-				dsimple->deco_name = std::string("air");
-			}
-			lua_pop(L, 1);
-			
-			if (dsimple->deco_height <= 0) {
-				errorstream << "register_decoration: simple decoration height"
-					" must be greater than 0" << std::endl;
-				delete dsimple;
-				return 0;
-			}
-
-			break; }
-		case DECO_SCHEMATIC: {
-			DecoSchematic *dschem = (DecoSchematic *)deco;
-			dschem->flags    = getflagsfield(L, index, "flags", flagdesc_deco_schematic);
-			dschem->rotation = (Rotation)getenumfield(L, index,
-								"rotation", es_Rotation, ROTATE_0);
-
-			lua_getfield(L, index, "replacements");
-			if (lua_istable(L, -1)) {
-				int i = lua_gettop(L);
-				lua_pushnil(L);
-				while (lua_next(L, i) != 0) {
-					// key at index -2 and value at index -1
-					lua_rawgeti(L, -1, 1);
-					std::string replace_from = lua_tostring(L, -1);
-					lua_pop(L, 1);
-					lua_rawgeti(L, -1, 2);
-					std::string replace_to = lua_tostring(L, -1);
-					lua_pop(L, 1);
-					dschem->replacements[replace_from] = replace_to;
-					// removes value, keeps key for next iteration
-					lua_pop(L, 1);
-				}
-			}
-			lua_pop(L, 1);
-
-			lua_getfield(L, index, "schematic");
-			if (!read_schematic(L, -1, dschem, getServer(L))) {
-				delete dschem;
-				return 0;
-			}
-			lua_pop(L, -1);
-			
-			if (!dschem->filename.empty() && !dschem->loadSchematicFile()) {
-				errorstream << "register_decoration: failed to load schematic file '"
-					<< dschem->filename << "'" << std::endl;
-				delete dschem;
-				return 0;
-			}
-			break; }
-		case DECO_LSYSTEM: {
-			//DecoLSystem *decolsystem = (DecoLSystem *)deco;
-		
-			break; }
-	}
-
-	emerge->decorations.push_back(deco);
-
-	verbosestream << "register_decoration: decoration '" << deco->getName()
-		<< "' registered" << std::endl;
-	return 0;
-}
-
-// create_schematic(p1, p2, probability_list, filename)
-int ModApiBasic::l_create_schematic(lua_State *L)
-{
-	DecoSchematic dschem;
-
-	Map *map = &(getEnv(L)->getMap());
-	INodeDefManager *ndef = getServer(L)->getNodeDefManager();
-
-	v3s16 p1 = read_v3s16(L, 1);
-	v3s16 p2 = read_v3s16(L, 2);
-	sortBoxVerticies(p1, p2);
-	
-	std::vector<std::pair<v3s16, u8> > probability_list;
-	if (lua_istable(L, 3)) {
-		lua_pushnil(L);
-		while (lua_next(L, 3)) {
-			if (lua_istable(L, -1)) {
-				lua_getfield(L, -1, "pos");
-				v3s16 pos = read_v3s16(L, -1);
-				lua_pop(L, 1);
-				
-				u8 prob = getintfield_default(L, -1, "prob", 0xFF);
-				probability_list.push_back(std::make_pair(pos, prob));
-			}
-
-			lua_pop(L, 1);
-		}
-	}
-	
-	dschem.filename = std::string(lua_tostring(L, 4));
-
-	if (!dschem.getSchematicFromMap(map, p1, p2)) {
-		errorstream << "create_schematic: failed to get schematic "
-			"from map" << std::endl;
-		return 0;
-	}
-	
-	dschem.applyProbabilities(&probability_list, p1);
-	
-	dschem.saveSchematicFile(ndef);
-	actionstream << "create_schematic: saved schematic file '"
-		<< dschem.filename << "'." << std::endl;
-
-	return 1;
-}
-
-
-// place_schematic(p, schematic, rotation, replacement)
-int ModApiBasic::l_place_schematic(lua_State *L)
-{
-	DecoSchematic dschem;
-
-	Map *map = &(getEnv(L)->getMap());
-	INodeDefManager *ndef = getServer(L)->getNodeDefManager();
-
-	v3s16 p = read_v3s16(L, 1);
-	if (!read_schematic(L, 2, &dschem, getServer(L)))
-		return 0;
-		
-	Rotation rot = ROTATE_0;
-	if (lua_isstring(L, 3))
-		string_to_enum(es_Rotation, (int &)rot, std::string(lua_tostring(L, 3)));
-		
-	dschem.rotation = rot;
-
-	if (lua_istable(L, 4)) {
-		int index = 4;
-		lua_pushnil(L);
-		while (lua_next(L, index) != 0) {
-			// key at index -2 and value at index -1
-			lua_rawgeti(L, -1, 1);
-			std::string replace_from = lua_tostring(L, -1);
-			lua_pop(L, 1);
-			lua_rawgeti(L, -1, 2);
-			std::string replace_to = lua_tostring(L, -1);
-			lua_pop(L, 1);
-			dschem.replacements[replace_from] = replace_to;
-			// removes value, keeps key for next iteration
-			lua_pop(L, 1);
-		}
-	}
-
-	if (!dschem.filename.empty()) {
-		if (!dschem.loadSchematicFile()) {
-			errorstream << "place_schematic: failed to load schematic file '"
-				<< dschem.filename << "'" << std::endl;
-			return 0;
-		}
-		dschem.resolveNodeNames(ndef);
-	}
-	
-	dschem.placeStructure(map, p);
-
-	return 1;
-}
-
-
-ModApiBasic modapibasic_prototype;
diff --git a/src/script/scripting_game.cpp b/src/script/scripting_game.cpp
new file mode 100644
index 000000000..dfbf471d2
--- /dev/null
+++ b/src/script/scripting_game.cpp
@@ -0,0 +1,99 @@
+/*
+Minetest
+Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "scripting_game.h"
+#include "log.h"
+#include "cpp_api/s_internal.h"
+#include "lua_api/l_base.h"
+#include "lua_api/l_craft.h"
+#include "lua_api/l_env.h"
+#include "lua_api/l_inventory.h"
+#include "lua_api/l_item.h"
+#include "lua_api/l_mapgen.h"
+#include "lua_api/l_nodemeta.h"
+#include "lua_api/l_nodetimer.h"
+#include "lua_api/l_noise.h"
+#include "lua_api/l_object.h"
+#include "lua_api/l_particles.h"
+#include "lua_api/l_rollback.h"
+#include "lua_api/l_server.h"
+#include "lua_api/l_util.h"
+#include "lua_api/l_vmanip.h"
+
+extern "C" {
+#include "lualib.h"
+}
+
+GameScripting::GameScripting(Server* server)
+{
+	setServer(server);
+
+	// setEnv(env) is called by ScriptApiEnv::initializeEnvironment()
+	// once the environment has been created
+
+	//TODO add security
+
+	luaL_openlibs(getStack());
+
+	SCRIPTAPI_PRECHECKHEADER
+
+	// Create the main minetest table
+	lua_newtable(L);
+
+	lua_newtable(L);
+	lua_setfield(L, -2, "object_refs");
+
+	lua_newtable(L);
+	lua_setfield(L, -2, "luaentities");
+
+	lua_setglobal(L, "minetest");
+
+	// Initialize our lua_api modules
+	lua_getglobal(L, "minetest");
+	int top = lua_gettop(L);
+	InitializeModApi(L, top);
+	lua_pop(L, 1);
+
+	infostream << "SCRIPTAPI: initialized game modules" << std::endl;
+}
+
+void GameScripting::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);
+
+	// Register reference classes (userdata)
+	InvRef::Register(L);
+	LuaItemStack::Register(L);
+	LuaPerlinNoise::Register(L);
+	LuaPerlinNoiseMap::Register(L);
+	LuaPseudoRandom::Register(L);
+	LuaVoxelManip::Register(L);
+	NodeMetaRef::Register(L);
+	NodeTimerRef::Register(L);
+	ObjectRef::Register(L);
+}
diff --git a/src/script/cpp_api/scriptapi.h b/src/script/scripting_game.h
similarity index 53%
rename from src/script/cpp_api/scriptapi.h
rename to src/script/scripting_game.h
index bbd0bdda7..ed6567922 100644
--- a/src/script/cpp_api/scriptapi.h
+++ b/src/script/scripting_game.h
@@ -17,66 +17,37 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
 
-#ifndef SCRIPTAPI_H_
-#define SCRIPTAPI_H_
-
-#include <map>
-#include <set>
-#include <vector>
+#ifndef SCRIPTING_GAME_H_
+#define SCRIPTING_GAME_H_
 
 #include "cpp_api/s_base.h"
-#include "cpp_api/s_player.h"
+#include "cpp_api/s_entity.h"
 #include "cpp_api/s_env.h"
-#include "cpp_api/s_node.h"
 #include "cpp_api/s_inventory.h"
-#include "cpp_api/s_entity.h"
-
-class ModApiBase;
+#include "cpp_api/s_node.h"
+#include "cpp_api/s_player.h"
+#include "cpp_api/s_server.h"
 
 /*****************************************************************************/
-/* Scriptapi <-> Core Interface                                              */
+/* Scripting <-> Game Interface                                              */
 /*****************************************************************************/
 
-class ScriptApi
+class GameScripting
 		: virtual public ScriptApiBase,
-		  public ScriptApiPlayer,
+		  public ScriptApiDetached,
+		  public ScriptApiEntity,
 		  public ScriptApiEnv,
 		  public ScriptApiNode,
-		  public ScriptApiDetached,
-		  public ScriptApiEntity
+		  public ScriptApiPlayer,
+		  public ScriptApiServer
 {
 public:
-	ScriptApi();
-	ScriptApi(Server* server);
-	~ScriptApi();
-
-	// Returns true if script handled message
-	bool on_chat_message(const std::string &name, const std::string &message);
-
-	/* server */
-	void on_shutdown();
+	GameScripting(Server* server);
 
-	/* auth */
-	bool getAuth(const std::string &playername,
-			std::string *dst_password, std::set<std::string> *dst_privs);
-	void createAuth(const std::string &playername,
-			const std::string &password);
-	bool setPassword(const std::string &playername,
-			const std::string &password);
-
-	/** register a lua api module to scriptapi */
-	static bool registerModApiModule(ModApiBase* prototype);
-	/** load a mod **/
-	bool loadMod(const std::string &scriptpath,const std::string &modname);
+	// use ScriptApiBase::loadMod() to load mods
 
 private:
-	void getAuthHandler();
-	void readPrivileges(int index,std::set<std::string> &result);
-
-	bool scriptLoad(const char *path);
-
-	static std::vector<ModApiBase*>* m_mod_api_modules;
-
+	void InitializeModApi(lua_State *L, int top);
 };
 
-#endif /* SCRIPTAPI_H_ */
+#endif /* SCRIPTING_GAME_H_ */
diff --git a/src/script/scripting_mainmenu.cpp b/src/script/scripting_mainmenu.cpp
new file mode 100644
index 000000000..47461e7ca
--- /dev/null
+++ b/src/script/scripting_mainmenu.cpp
@@ -0,0 +1,65 @@
+/*
+Minetest
+Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "scripting_mainmenu.h"
+#include "log.h"
+#include "filesys.h"
+#include "cpp_api/s_internal.h"
+#include "lua_api/l_base.h"
+#include "lua_api/l_mainmenu.h"
+#include "lua_api/l_util.h"
+
+extern "C" {
+#include "lualib.h"
+}
+
+MainMenuScripting::MainMenuScripting(GUIEngine* guiengine)
+{
+	setGuiEngine(guiengine);
+
+	//TODO add security
+
+	luaL_openlibs(getStack());
+
+	SCRIPTAPI_PRECHECKHEADER
+
+	lua_pushstring(L, DIR_DELIM);
+	lua_setglobal(L, "DIR_DELIM");
+
+	lua_newtable(L);
+	lua_setglobal(L, "gamedata");
+
+	lua_newtable(L);
+	lua_setglobal(L, "engine");
+
+	// Initialize our lua_api modules
+	lua_getglobal(L, "engine");
+	int top = lua_gettop(L);
+	InitializeModApi(L, top);
+	lua_pop(L, 1);
+
+	infostream << "SCRIPTAPI: initialized mainmenu modules" << std::endl;
+}
+
+void MainMenuScripting::InitializeModApi(lua_State *L, int top)
+{
+	// Initialize mod api modules
+	ModApiMainMenu::Initialize(L, top);
+	ModApiUtil::Initialize(L, top);
+}
diff --git a/src/script/scripting_mainmenu.h b/src/script/scripting_mainmenu.h
new file mode 100644
index 000000000..7592c8e23
--- /dev/null
+++ b/src/script/scripting_mainmenu.h
@@ -0,0 +1,45 @@
+/*
+Minetest
+Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef SCRIPTING_MAINMENU_H_
+#define SCRIPTING_MAINMENU_H_
+
+#include "cpp_api/s_base.h"
+#include "cpp_api/s_mainmenu.h"
+
+/*****************************************************************************/
+/* Scripting <-> Main Menu Interface                                         */
+/*****************************************************************************/
+
+class MainMenuScripting
+		: virtual public ScriptApiBase,
+		  public ScriptApiMainMenu
+{
+public:
+	MainMenuScripting(GUIEngine* guiengine);
+
+	// use ScriptApiBase::loadMod() or ScriptApiBase::loadScript()
+	// to load scripts
+
+private:
+	void InitializeModApi(lua_State *L, int top);
+};
+
+
+#endif /* SCRIPTING_MAINMENU_H_ */
diff --git a/src/server.cpp b/src/server.cpp
index 7926b879f..5ecdddcbc 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -22,6 +22,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include <queue>
 #include <algorithm>
 #include "clientserver.h"
+#include "ban.h"
+#include "environment.h"
 #include "map.h"
 #include "jmutexautolock.h"
 #include "main.h"
@@ -34,7 +36,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "settings.h"
 #include "profiler.h"
 #include "log.h"
-#include "script/cpp_api/scriptapi.h"
+#include "scripting_game.h"
 #include "nodedef.h"
 #include "itemdef.h"
 #include "craftdef.h"
@@ -58,6 +60,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "util/mathconstants.h"
 #include "rollback.h"
 #include "util/serialize.h"
+#include "util/thread.h"
 #include "defaultsettings.h"
 
 class ClientNotFoundException : public BaseException
@@ -68,6 +71,21 @@ class ClientNotFoundException : public BaseException
 	{}
 };
 
+class ServerThread : public SimpleThread
+{
+	Server *m_server;
+
+public:
+
+	ServerThread(Server *server):
+		SimpleThread(),
+		m_server(server)
+	{
+	}
+
+	void * Thread();
+};
+
 void * ServerThread::Thread()
 {
 	ThreadStarted();
@@ -613,46 +631,23 @@ void RemoteClient::SetBlocksNotSent(std::map<v3s16, MapBlock*> &blocks)
 	}
 }
 
-/*
-	PlayerInfo
-*/
-
-PlayerInfo::PlayerInfo()
-{
-	name[0] = 0;
-	avg_rtt = 0;
-}
-
-void PlayerInfo::PrintLine(std::ostream *s)
-{
-	(*s)<<id<<": ";
-	(*s)<<"\""<<name<<"\" ("
-			<<(position.X/10)<<","<<(position.Y/10)
-			<<","<<(position.Z/10)<<") ";
-	address.print(s);
-	(*s)<<" avg_rtt="<<avg_rtt;
-	(*s)<<std::endl;
-}
-
 /*
 	Server
 */
 
 Server::Server(
 		const std::string &path_world,
-		const std::string &path_config,
 		const SubgameSpec &gamespec,
 		bool simple_singleplayer_mode
 	):
 	m_path_world(path_world),
-	m_path_config(path_config),
 	m_gamespec(gamespec),
 	m_simple_singleplayer_mode(simple_singleplayer_mode),
 	m_async_fatal_error(""),
 	m_env(NULL),
 	m_con(PROTOCOL_ID, 512, CONNECTION_TIMEOUT,
 	      g_settings->getBool("enable_ipv6") && g_settings->getBool("ipv6_server"), this),
-	m_banmanager(path_world+DIR_DELIM+"ipban.txt"),
+	m_banmanager(NULL),
 	m_rollback(NULL),
 	m_rollback_sink_enabled(true),
 	m_enable_rollback_recording(false),
@@ -662,7 +657,7 @@ Server::Server(
 	m_nodedef(createNodeDefManager()),
 	m_craftdef(createCraftDefManager()),
 	m_event(new EventManager()),
-	m_thread(this),
+	m_thread(NULL),
 	m_time_of_day_send_timer(0),
 	m_uptime(0),
 	m_shutdown_requested(false),
@@ -695,7 +690,6 @@ Server::Server(
 	else
 		infostream<<std::endl;
 	infostream<<"- world:  "<<m_path_world<<std::endl;
-	infostream<<"- config: "<<m_path_config<<std::endl;
 	infostream<<"- game:   "<<m_gamespec.path<<std::endl;
 
 	// Initialize default settings and override defaults with those provided
@@ -704,10 +698,17 @@ Server::Server(
 	Settings gamedefaults;
 	getGameMinetestConfig(gamespec.path, gamedefaults);
 	override_default_settings(g_settings, &gamedefaults);
-	
+
+	// Create server thread
+	m_thread = new ServerThread(this);
+
 	// Create emerge manager
 	m_emerge = new EmergeManager(this);
-	
+
+	// Create ban manager
+	std::string ban_path = m_path_world+DIR_DELIM+"ipban.txt";
+	m_banmanager = new BanManager(ban_path);
+
 	// Create rollback manager
 	std::string rollback_path = m_path_world+DIR_DELIM+"rollback.txt";
 	m_rollback = createRollbackManager(rollback_path, this);
@@ -773,7 +774,7 @@ Server::Server(
 
 	infostream<<"Server: Initializing Lua"<<std::endl;
 
-	m_script = new ScriptApi(this);
+	m_script = new GameScripting(this);
 
 
 	// Load and run builtin.lua
@@ -816,7 +817,7 @@ Server::Server(
 
 	// Initialize Environment
 	ServerMap *servermap = new ServerMap(path_world, this, m_emerge);
-	m_env = new ServerEnvironment(servermap, m_script, this, this);
+	m_env = new ServerEnvironment(servermap, m_script, this, m_emerge);
 	
 	// Run some callbacks after the MG params have been set up but before activation
 	MapgenParams *mgparams = servermap->getMapgenParams();
@@ -913,6 +914,7 @@ Server::~Server()
 		Stop threads
 	*/
 	stop();
+	delete m_thread;
 
 	//shutdown all emerge threads first!
 	delete m_emerge;
@@ -936,6 +938,7 @@ Server::~Server()
 	// Delete things in the reverse order of creation
 	delete m_env;
 	delete m_rollback;
+	delete m_banmanager;
 	delete m_event;
 	delete m_itemdef;
 	delete m_nodedef;
@@ -961,15 +964,15 @@ void Server::start(unsigned short port)
 	infostream<<"Starting server on port "<<port<<"..."<<std::endl;
 
 	// Stop thread if already running
-	m_thread.stop();
+	m_thread->stop();
 
 	// Initialize connection
 	m_con.SetTimeoutMs(30);
 	m_con.Serve(port);
 
 	// Start thread
-	m_thread.setRun(true);
-	m_thread.Start();
+	m_thread->setRun(true);
+	m_thread->Start();
 
 	// ASCII art for the win!
 	actionstream
@@ -991,9 +994,9 @@ void Server::stop()
 	infostream<<"Server: Stopping and waiting threads"<<std::endl;
 
 	// Stop threads (set run=false first so both start stopping)
-	m_thread.setRun(false);
+	m_thread->setRun(false);
 	//m_emergethread.setRun(false);
-	m_thread.stop();
+	m_thread->stop();
 	//m_emergethread.stop();
 
 	infostream<<"Server: Threads stopped"<<std::endl;
@@ -1086,15 +1089,15 @@ void Server::AsyncRunStep()
 			//JMutexAutoLock envlock(m_env_mutex);
 			JMutexAutoLock conlock(m_con_mutex);
 
+			u16 time = m_env->getTimeOfDay();
+			float time_speed = g_settings->getFloat("time_speed");
+
 			for(std::map<u16, RemoteClient*>::iterator
 				i = m_clients.begin();
 				i != m_clients.end(); ++i)
 			{
 				RemoteClient *client = i->second;
-				SharedBuffer<u8> data = makePacket_TOCLIENT_TIME_OF_DAY(
-						m_env->getTimeOfDay(), g_settings->getFloat("time_speed"));
-				// Send as reliable
-				m_con.Send(client->peer_id, 0, data, true);
+				SendTimeOfDay(client->peer_id, time, time_speed);
 			}
 		}
 	}
@@ -1680,8 +1683,7 @@ void Server::AsyncRunStep()
 		{
 			counter = 0.0;
 
-			for (unsigned int i = 0; i != m_emerge->emergethread.size(); i++)
-				m_emerge->emergethread[i]->trigger();
+			m_emerge->triggerAllThreads();
 
 			// Update m_enable_rollback_recording here too
 			m_enable_rollback_recording =
@@ -1701,8 +1703,8 @@ void Server::AsyncRunStep()
 			ScopeProfiler sp(g_profiler, "Server: saving stuff");
 
 			//Ban stuff
-			if(m_banmanager.isModified())
-				m_banmanager.save();
+			if(m_banmanager->isModified())
+				m_banmanager->save();
 
 			// Save changed parts of map
 			m_env->getMap().save(MOD_STATE_WRITE_NEEDED);
@@ -1772,13 +1774,13 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
 		addr_s = address.serializeString();
 
 		// drop player if is ip is banned
-		if(m_banmanager.isIpBanned(addr_s)){
+		if(m_banmanager->isIpBanned(addr_s)){
 			infostream<<"Server: A banned client tried to connect from "
 					<<addr_s<<"; banned name was "
-					<<m_banmanager.getBanName(addr_s)<<std::endl;
+					<<m_banmanager->getBanName(addr_s)<<std::endl;
 			// This actually doesn't seem to transfer to the client
 			DenyAccess(peer_id, L"Your ip is banned. Banned name was "
-					+narrow_to_wide(m_banmanager.getBanName(addr_s)));
+					+narrow_to_wide(m_banmanager->getBanName(addr_s)));
 			m_con.DeletePeer(peer_id);
 			return;
 		}
@@ -2159,9 +2161,9 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
 
 		// Send time of day
 		{
-			SharedBuffer<u8> data = makePacket_TOCLIENT_TIME_OF_DAY(
-					m_env->getTimeOfDay(), g_settings->getFloat("time_speed"));
-			m_con.Send(peer_id, 0, data, true);
+			u16 time = m_env->getTimeOfDay();
+			float time_speed = g_settings->getFloat("time_speed");
+			SendTimeOfDay(peer_id, time, time_speed);
 		}
 
 		// Note things in chat if not in simple singleplayer mode
@@ -3203,6 +3205,12 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
 	}
 }
 
+void Server::setTimeOfDay(u32 time)
+{
+	m_env->setTimeOfDay(time);
+	m_time_of_day_send_timer = 0;
+}
+
 void Server::onMapEditEvent(MapEditEvent *event)
 {
 	//infostream<<"Server::onMapEditEvent()"<<std::endl;
@@ -3293,48 +3301,6 @@ void Server::setInventoryModified(const InventoryLocation &loc)
 	}
 }
 
-//std::list<PlayerInfo> Server::getPlayerInfo()
-//{
-//	DSTACK(__FUNCTION_NAME);
-//	JMutexAutoLock envlock(m_env_mutex);
-//	JMutexAutoLock conlock(m_con_mutex);
-//
-//	std::list<PlayerInfo> list;
-//
-//	std::list<Player*> players = m_env->getPlayers();
-//
-//	std::list<Player*>::iterator i;
-//	for(i = players.begin();
-//			i != players.end(); ++i)
-//	{
-//		PlayerInfo info;
-//
-//		Player *player = *i;
-//
-//		try{
-//			// Copy info from connection to info struct
-//			info.id = player->peer_id;
-//			info.address = m_con.GetPeerAddress(player->peer_id);
-//			info.avg_rtt = m_con.GetPeerAvgRTT(player->peer_id);
-//		}
-//		catch(con::PeerNotFoundException &e)
-//		{
-//			// Set dummy peer info
-//			info.id = 0;
-//			info.address = Address(0,0,0,0,0);
-//			info.avg_rtt = 0.0;
-//		}
-//
-//		snprintf(info.name, PLAYERNAME_SIZE, "%s", player->getName());
-//		info.position = player->getPosition();
-//
-//		list.push_back(info);
-//	}
-//
-//	return list;
-//}
-
-
 void Server::peerAdded(con::Peer *peer)
 {
 	DSTACK(__FUNCTION_NAME);
@@ -3841,6 +3807,20 @@ void Server::BroadcastChatMessage(const std::wstring &message)
 	}
 }
 
+void Server::SendTimeOfDay(u16 peer_id, u16 time, f32 time_speed)
+{
+	DSTACK(__FUNCTION_NAME);
+
+	// Make packet
+	SharedBuffer<u8> data(2+2+4);
+	writeU16(&data[0], TOCLIENT_TIME_OF_DAY);
+	writeU16(&data[2], time);
+	writeF1000(&data[4], time_speed);
+
+	// Send as reliable
+	m_con.Send(peer_id, 0, data, true);
+}
+
 void Server::SendPlayerHP(u16 peer_id)
 {
 	DSTACK(__FUNCTION_NAME);
@@ -4774,9 +4754,6 @@ void Server::DeleteClient(u16 peer_id, ClientDeletionReason reason)
 	delete m_clients[peer_id];
 	m_clients.erase(peer_id);
 
-	// Send player info to all remaining clients
-	//SendPlayerInfos();
-
 	// Send leave chat message to all remaining clients
 	if(message.length() != 0)
 		BroadcastChatMessage(message);
@@ -4818,6 +4795,22 @@ RemoteClient* Server::getClientNoEx(u16 peer_id)
 	return n->second;
 }
 
+std::string Server::getPlayerName(u16 peer_id)
+{
+	Player *player = m_env->getPlayer(peer_id);
+	if(player == NULL)
+		return "[id="+itos(peer_id)+"]";
+	return player->getName();
+}
+
+PlayerSAO* Server::getPlayerSAO(u16 peer_id)
+{
+	Player *player = m_env->getPlayer(peer_id);
+	if(player == NULL)
+		return NULL;
+	return player->getPlayerSAO();
+}
+
 std::wstring Server::getStatusString()
 {
 	std::wostringstream os(std::ios_base::binary);
@@ -4906,11 +4899,19 @@ void Server::reportInventoryFormspecModified(const std::string &name)
 	SendPlayerInventoryFormspec(player->peer_id);
 }
 
-// Saves g_settings to configpath given at initialization
-void Server::saveConfig()
+void Server::setIpBanned(const std::string &ip, const std::string &name)
 {
-	if(m_path_config != "")
-		g_settings->updateConfigFile(m_path_config.c_str());
+	m_banmanager->add(ip, name);
+}
+
+void Server::unsetIpBanned(const std::string &ip_or_name)
+{
+	m_banmanager->remove(ip_or_name);
+}
+
+std::string Server::getBanDescription(const std::string &ip_or_name)
+{
+	return m_banmanager->getBanDescription(ip_or_name);
 }
 
 void Server::notifyPlayer(const char *name, const std::wstring msg, const bool prepend = true)
@@ -4942,7 +4943,7 @@ u32 Server::hudAdd(Player *player, HudElement *form) {
 	if (!player)
 		return -1;
 
-	u32 id = hud_get_free_id(player);
+	u32 id = player->getFreeHudID();
 	if (id < player->hud.size())
 		player->hud[id] = form;
 	else
@@ -5101,11 +5102,6 @@ void Server::deleteParticleSpawnerAll(u32 id)
 	SendDeleteParticleSpawnerAll(id);
 }
 
-void Server::queueBlockEmerge(v3s16 blockpos, bool allow_generate)
-{
-	m_emerge->enqueueBlockEmerge(PEER_ID_INEXISTENT, blockpos, allow_generate);
-}
-
 Inventory* Server::createDetachedInventory(const std::string &name)
 {
 	if(m_detached_inventories.count(name) > 0){
diff --git a/src/server.h b/src/server.h
index d49ecdf7b..4e7675ecb 100644
--- a/src/server.h
+++ b/src/server.h
@@ -21,37 +21,37 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #define SERVER_HEADER
 
 #include "connection.h"
-#include "environment.h"
-#include "irrlichttypes_bloated.h"
-#include <string>
-#include "porting.h"
+#include "irr_v3d.h"
 #include "map.h"
-#include "inventory.h"
-#include "ban.h"
 #include "hud.h"
 #include "gamedef.h"
 #include "serialization.h" // For SER_FMT_VER_INVALID
 #include "mods.h"
 #include "inventorymanager.h"
 #include "subgame.h"
-#include "sound.h"
-#include "util/thread.h"
-#include "util/string.h"
 #include "rollback_interface.h" // Needed for rollbackRevertActions()
-#include <list> // Needed for rollbackRevertActions()
-#include <algorithm>
+#include "util/numeric.h"
+#include "util/thread.h"
+#include <string>
+#include <list>
+#include <map>
+#include <vector>
 
 #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
 
 class IWritableItemDefManager;
 class IWritableNodeDefManager;
 class IWritableCraftDefManager;
+class BanManager;
 class EventManager;
+class Inventory;
+class Player;
 class PlayerSAO;
 class IRollbackManager;
 class EmergeManager;
-//struct HudElement; ?????????
-class ScriptApi;
+class GameScripting;
+class ServerEnvironment;
+struct SimpleSoundSpec;
 
 
 class ServerError : public std::exception
@@ -128,33 +128,7 @@ class MapEditEventAreaIgnorer
 };
 
 class Server;
-
-class ServerThread : public SimpleThread
-{
-	Server *m_server;
-
-public:
-
-	ServerThread(Server *server):
-		SimpleThread(),
-		m_server(server)
-	{
-	}
-
-	void * Thread();
-};
-
-struct PlayerInfo
-{
-	u16 id;
-	char name[PLAYERNAME_SIZE];
-	v3f position;
-	Address address;
-	float avg_rtt;
-
-	PlayerInfo();
-	void PrintLine(std::ostream *s);
-};
+class ServerThread;
 
 /*
 	Used for queueing and sorting block transfers in containers
@@ -362,8 +336,7 @@ class RemoteClient
 };
 
 class Server : public con::PeerHandler, public MapEventReceiver,
-		public InventoryManager, public IGameDef,
-		public IBackgroundBlockEmerger
+		public InventoryManager, public IGameDef
 {
 public:
 	/*
@@ -372,7 +345,6 @@ class Server : public con::PeerHandler, public MapEventReceiver,
 
 	Server(
 		const std::string &path_world,
-		const std::string &path_config,
 		const SubgameSpec &gamespec,
 		bool simple_singleplayer_mode
 	);
@@ -387,14 +359,8 @@ class Server : public con::PeerHandler, public MapEventReceiver,
 	void Receive();
 	void ProcessData(u8 *data, u32 datasize, u16 peer_id);
 
-	//std::list<PlayerInfo> getPlayerInfo();
-
 	// Environment must be locked when called
-	void setTimeOfDay(u32 time)
-	{
-		m_env->setTimeOfDay(time);
-		m_time_of_day_send_timer = 0;
-	}
+	void setTimeOfDay(u32 time);
 
 	bool getShutdownRequested()
 	{
@@ -433,25 +399,9 @@ class Server : public con::PeerHandler, public MapEventReceiver,
 	void reportPrivsModified(const std::string &name=""); // ""=all
 	void reportInventoryFormspecModified(const std::string &name);
 
-	// Saves g_settings to configpath given at initialization
-	void saveConfig();
-
-	void setIpBanned(const std::string &ip, const std::string &name)
-	{
-		m_banmanager.add(ip, name);
-		return;
-	}
-
-	void unsetIpBanned(const std::string &ip_or_name)
-	{
-		m_banmanager.remove(ip_or_name);
-		return;
-	}
-
-	std::string getBanDescription(const std::string &ip_or_name)
-	{
-		return m_banmanager.getBanDescription(ip_or_name);
-	}
+	void setIpBanned(const std::string &ip, const std::string &name);
+	void unsetIpBanned(const std::string &ip_or_name);
+	std::string getBanDescription(const std::string &ip_or_name);
 
 	Address getPeerAddress(u16 peer_id)
 	{
@@ -490,13 +440,11 @@ class Server : public con::PeerHandler, public MapEventReceiver,
 	void deleteParticleSpawner(const char *playername, u32 id);
 	void deleteParticleSpawnerAll(u32 id);
 
-	void queueBlockEmerge(v3s16 blockpos, bool allow_generate);
-
 	// Creates or resets inventory
 	Inventory* createDetachedInventory(const std::string &name);
 
 	// Envlock and conlock should be locked when using scriptapi
-	ScriptApi *getScriptIface(){ return m_script; }
+	GameScripting *getScriptIface(){ return m_script; }
 
 	// Envlock should be locked when using the rollback manager
 	IRollbackManager *getRollbackManager(){ return m_rollback; }
@@ -581,6 +529,7 @@ class Server : public con::PeerHandler, public MapEventReceiver,
 	void SendInventory(u16 peer_id);
 	void SendChatMessage(u16 peer_id, const std::wstring &message);
 	void BroadcastChatMessage(const std::wstring &message);
+	void SendTimeOfDay(u16 peer_id, u16 time, f32 time_speed);
 	void SendPlayerHP(u16 peer_id);
 	void SendPlayerBreath(u16 peer_id);
 	void SendMovePlayer(u16 peer_id);
@@ -677,22 +626,8 @@ class Server : public con::PeerHandler, public MapEventReceiver,
 	RemoteClient* getClientNoEx(u16 peer_id);
 
 	// When called, environment mutex should be locked
-	std::string getPlayerName(u16 peer_id)
-	{
-		Player *player = m_env->getPlayer(peer_id);
-		if(player == NULL)
-			return "[id="+itos(peer_id)+"]";
-		return player->getName();
-	}
-
-	// When called, environment mutex should be locked
-	PlayerSAO* getPlayerSAO(u16 peer_id)
-	{
-		Player *player = m_env->getPlayer(peer_id);
-		if(player == NULL)
-			return NULL;
-		return player->getPlayerSAO();
-	}
+	std::string getPlayerName(u16 peer_id);
+	PlayerSAO* getPlayerSAO(u16 peer_id);
 
 	/*
 		Get a player from memory or creates one.
@@ -714,8 +649,6 @@ class Server : public con::PeerHandler, public MapEventReceiver,
 
 	// World directory
 	std::string m_path_world;
-	// Path to user's configuration file ("" = no configuration file)
-	std::string m_path_config;
 	// Subgame specification
 	SubgameSpec m_gamespec;
 	// If true, do not allow multiple players and hide some multiplayer
@@ -750,7 +683,7 @@ class Server : public con::PeerHandler, public MapEventReceiver,
 	u16 m_clients_number; //for announcing masterserver
 
 	// Ban checking
-	BanManager m_banmanager;
+	BanManager *m_banmanager;
 
 	// Rollback manager (behind m_env_mutex)
 	IRollbackManager *m_rollback;
@@ -762,7 +695,7 @@ class Server : public con::PeerHandler, public MapEventReceiver,
 
 	// Scripting
 	// Envlock and conlock should be locked when using Lua
-	ScriptApi *m_script;
+	GameScripting *m_script;
 
 	// Item definition manager
 	IWritableItemDefManager *m_itemdef;
@@ -789,7 +722,7 @@ class Server : public con::PeerHandler, public MapEventReceiver,
 	JMutex m_step_dtime_mutex;
 
 	// The server mainly operates in this thread
-	ServerThread m_thread;
+	ServerThread *m_thread;
 
 	/*
 		Time related stuff
diff --git a/src/settings.h b/src/settings.h
index a9e0faa40..62596f869 100644
--- a/src/settings.h
+++ b/src/settings.h
@@ -21,8 +21,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #define SETTINGS_HEADER
 
 #include "irrlichttypes_bloated.h"
+#include "exceptions.h"
 #include <string>
-#include <jthread.h>
 #include <jmutex.h>
 #include <jmutexautolock.h>
 #include "strfnd.h"
diff --git a/src/socket.cpp b/src/socket.cpp
index 8505b24f7..1c07c44d5 100644
--- a/src/socket.cpp
+++ b/src/socket.cpp
@@ -56,6 +56,7 @@ typedef int socket_t;
 #include <string.h>
 #include <errno.h>
 #include <sstream>
+#include <iomanip>
 #include "util/string.h"
 #include "util/numeric.h"
 
@@ -392,9 +393,10 @@ void UDPSocket::Send(const Address & destination, const void * data, int size)
 		for(int i = 0; i < size && i < 20; i++)
 		{
 			if(i % 2 == 0)
-				DEBUGPRINT(" ");
+				dstream << " ";
 			unsigned int a = ((const unsigned char *) data)[i];
-			DEBUGPRINT("%.2X", a);
+			dstream << std::hex << std::setw(2) << std::setfill('0')
+				<< a;
 		}
 		
 		if(size > 20)
@@ -494,9 +496,10 @@ int UDPSocket::Receive(Address & sender, void * data, int size)
 		for(int i = 0; i < received && i < 20; i++)
 		{
 			if(i % 2 == 0)
-				DEBUGPRINT(" ");
+				dstream << " ";
 			unsigned int a = ((const unsigned char *) data)[i];
-			DEBUGPRINT("%.2X", a);
+			dstream << std::hex << std::setw(2) << std::setfill('0')
+				<< a;
 		}
 		if(received > 20)
 			dstream << "...";
diff --git a/src/strfnd.h b/src/strfnd.h
index 4a72edf3c..3142cc10d 100644
--- a/src/strfnd.h
+++ b/src/strfnd.h
@@ -22,8 +22,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 #include <string>
 
-std::string trim(const std::string &str);
-
 class Strfnd{
     std::string tek;
     unsigned int p;
@@ -174,43 +172,5 @@ class WStrfnd{
     }
 };
 
-inline std::string trim(const std::string &s)
-{
-	std::string str = s;
-    while( 
-            str.length()>0
-            &&
-            (
-             str.substr(0,               1)==" "     ||
-             str.substr(0,               1)=="\t"    ||
-             str.substr(0,               1)=="\r"    ||
-             str.substr(0,               1)=="\n"    ||
-             str.substr(str.length()-1,  1)==" "     ||
-             str.substr(str.length()-1,  1)=="\t"    ||
-             str.substr(str.length()-1,  1)=="\r"    ||
-             str.substr(str.length()-1,  1)=="\n"
-            )
-         )
-    {  
-        if      (str.substr(0,              1)==" ")
-			str = str.substr(1,str.length()-1);
-        else if (str.substr(0,              1)=="\t")
-			str = str.substr(1,str.length()-1);
-        else if (str.substr(0,              1)=="\r")
-			str = str.substr(1,str.length()-1);
-        else if (str.substr(0,              1)=="\n")
-			str = str.substr(1,str.length()-1);
-        else if (str.substr(str.length()-1, 1)==" ")
-			str = str.substr(0,str.length()-1);
-        else if (str.substr(str.length()-1, 1)=="\t")
-			str = str.substr(0,str.length()-1);
-        else if (str.substr(str.length()-1, 1)=="\r")
-			str = str.substr(0,str.length()-1);
-        else if (str.substr(str.length()-1, 1)=="\n")
-			str = str.substr(0,str.length()-1);
-    }
-    return str;
-}
-
 #endif
 
diff --git a/src/test.cpp b/src/test.cpp
index fa7a82428..5e025f2f5 100644
--- a/src/test.cpp
+++ b/src/test.cpp
@@ -157,6 +157,8 @@ struct TestUtilities: public TestBase
 		UASSERT(fabs(wrapDegrees(-0.5) - (-0.5)) < 0.001);
 		UASSERT(fabs(wrapDegrees(-365.5) - (-5.5)) < 0.001);
 		UASSERT(lowercase("Foo bAR") == "foo bar");
+		UASSERT(trim("\n \t\r  Foo bAR  \r\n\t\t  ") == "Foo bAR");
+		UASSERT(trim("\n \t\r    \r\n\t\t  ") == "");
 		UASSERT(is_yes("YeS") == true);
 		UASSERT(is_yes("") == false);
 		UASSERT(is_yes("FAlse") == false);
diff --git a/src/threads.h b/src/threads.h
index a3717a1de..18789cf0c 100644
--- a/src/threads.h
+++ b/src/threads.h
@@ -24,12 +24,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 #if (defined(WIN32) || defined(_WIN32_WCE))
 typedef DWORD threadid_t;
-#define __NORETURN __declspec(noreturn)
-#define __FUNCTION_NAME __FUNCTION__
 #else
 typedef pthread_t threadid_t;
-#define __NORETURN __attribute__ ((__noreturn__))
-#define __FUNCTION_NAME __PRETTY_FUNCTION__
 #endif
 
 inline threadid_t get_current_thread_id()
diff --git a/src/tool.cpp b/src/tool.cpp
index 4d809e2c4..f3b3e656f 100644
--- a/src/tool.cpp
+++ b/src/tool.cpp
@@ -18,9 +18,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 */
 
 #include "tool.h"
-#include "itemdef.h" // For itemgroup_get()
+#include "itemgroup.h"
 #include "log.h"
 #include "inventory.h"
+#include "exceptions.h"
 #include "util/serialize.h"
 #include "util/numeric.h"
 
diff --git a/src/treegen.cpp b/src/treegen.cpp
index 808cf916a..6291567d5 100644
--- a/src/treegen.cpp
+++ b/src/treegen.cpp
@@ -19,6 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 #include "irr_v3d.h"
 #include <stack>
+#include "util/pointer.h"
 #include "util/numeric.h"
 #include "util/mathconstants.h"
 #include "map.h"
diff --git a/src/treegen.h b/src/treegen.h
index 16c85cf0a..55da6f9e5 100644
--- a/src/treegen.h
+++ b/src/treegen.h
@@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 class ManualMapVoxelManipulator;
 class INodeDefManager;
+class ServerEnvironment;
 
 
 namespace treegen {
diff --git a/src/util/container.h b/src/util/container.h
index 84616d2db..d5854909a 100644
--- a/src/util/container.h
+++ b/src/util/container.h
@@ -21,11 +21,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #define UTIL_CONTAINER_HEADER
 
 #include "../irrlichttypes.h"
+#include "../exceptions.h"
 #include <jmutex.h>
 #include <jmutexautolock.h>
 #include "../porting.h" // For sleep_ms
 #include <list>
 #include <vector>
+#include <map>
 
 /*
 	Queue with unique values with fast checking of value existence
diff --git a/src/util/numeric.h b/src/util/numeric.h
index 076a08efc..b96c94faa 100644
--- a/src/util/numeric.h
+++ b/src/util/numeric.h
@@ -24,7 +24,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "../irr_v2d.h"
 #include "../irr_v3d.h"
 #include "../irr_aabb3d.h"
-#include <irrList.h>
 #include <list>
 
 // Calculate the borders of a "d-radius" cube
diff --git a/src/util/pointedthing.cpp b/src/util/pointedthing.cpp
index dc39e313a..cd13000b5 100644
--- a/src/util/pointedthing.cpp
+++ b/src/util/pointedthing.cpp
@@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "pointedthing.h"
 
 #include "serialize.h"
+#include "../exceptions.h"
 #include <sstream>
 
 PointedThing::PointedThing():
diff --git a/src/util/serialize.cpp b/src/util/serialize.cpp
index f32813551..d6be5c487 100644
--- a/src/util/serialize.cpp
+++ b/src/util/serialize.cpp
@@ -18,10 +18,112 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 */
 
 #include "serialize.h"
+#include "pointer.h"
+#include "../exceptions.h"
 
 #include <sstream>
 #include <iomanip>
 
+// Creates a string with the length as the first two bytes
+std::string serializeString(const std::string &plain)
+{
+	//assert(plain.size() <= 65535);
+	if(plain.size() > 65535)
+		throw SerializationError("String too long for serializeString");
+	char buf[2];
+	writeU16((u8*)&buf[0], plain.size());
+	std::string s;
+	s.append(buf, 2);
+	s.append(plain);
+	return s;
+}
+
+// Creates a string with the length as the first two bytes from wide string
+std::string serializeWideString(const std::wstring &plain)
+{
+	//assert(plain.size() <= 65535);
+	if(plain.size() > 65535)
+		throw SerializationError("String too long for serializeString");
+	char buf[2];
+	writeU16((u8*)buf, plain.size());
+	std::string s;
+	s.append(buf, 2);
+	for(u32 i=0; i<plain.size(); i++)
+	{
+		writeU16((u8*)buf, plain[i]);
+		s.append(buf, 2);
+	}
+	return s;
+}
+
+// Reads a string with the length as the first two bytes
+std::string deSerializeString(std::istream &is)
+{
+	char buf[2];
+	is.read(buf, 2);
+	if(is.gcount() != 2)
+		throw SerializationError("deSerializeString: size not read");
+	u16 s_size = readU16((u8*)buf);
+	if(s_size == 0)
+		return "";
+	Buffer<char> buf2(s_size);
+	is.read(&buf2[0], s_size);
+	std::string s;
+	s.reserve(s_size);
+	s.append(&buf2[0], s_size);
+	return s;
+}
+
+// Reads a wide string with the length as the first two bytes
+std::wstring deSerializeWideString(std::istream &is)
+{
+	char buf[2];
+	is.read(buf, 2);
+	if(is.gcount() != 2)
+		throw SerializationError("deSerializeString: size not read");
+	u16 s_size = readU16((u8*)buf);
+	if(s_size == 0)
+		return L"";
+	std::wstring s;
+	s.reserve(s_size);
+	for(u32 i=0; i<s_size; i++)
+	{
+		is.read(&buf[0], 2);
+		wchar_t c16 = readU16((u8*)buf);
+		s.append(&c16, 1);
+	}
+	return s;
+}
+
+// Creates a string with the length as the first four bytes
+std::string serializeLongString(const std::string &plain)
+{
+	char buf[4];
+	writeU32((u8*)&buf[0], plain.size());
+	std::string s;
+	s.append(buf, 4);
+	s.append(plain);
+	return s;
+}
+
+// Reads a string with the length as the first four bytes
+std::string deSerializeLongString(std::istream &is)
+{
+	char buf[4];
+	is.read(buf, 4);
+	if(is.gcount() != 4)
+		throw SerializationError("deSerializeLongString: size not read");
+	u32 s_size = readU32((u8*)buf);
+	if(s_size == 0)
+		return "";
+	Buffer<char> buf2(s_size);
+	is.read(&buf2[0], s_size);
+	std::string s;
+	s.reserve(s_size);
+	s.append(&buf2[0], s_size);
+	return s;
+}
+
 // Creates a string encoded in JSON format (almost equivalent to a C string literal)
 std::string serializeJsonString(const std::string &plain)
 {
diff --git a/src/util/serialize.h b/src/util/serialize.h
index bb44c7f96..7a37cd70f 100644
--- a/src/util/serialize.h
+++ b/src/util/serialize.h
@@ -20,14 +20,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #ifndef UTIL_SERIALIZE_HEADER
 #define UTIL_SERIALIZE_HEADER
 
-#include "../irrlichttypes.h"
 #include "../irrlichttypes_bloated.h"
-#include "../irr_v2d.h"
-#include "../irr_v3d.h"
 #include <iostream>
 #include <string>
-#include "../exceptions.h"
-#include "pointer.h"
 
 inline void writeU64(u8 *data, u64 i)
 {
@@ -383,104 +378,22 @@ inline video::SColor readARGB8(std::istream &is)
 */
 
 // Creates a string with the length as the first two bytes
-inline std::string serializeString(const std::string &plain)
-{
-	//assert(plain.size() <= 65535);
-	if(plain.size() > 65535)
-		throw SerializationError("String too long for serializeString");
-	char buf[2];
-	writeU16((u8*)&buf[0], plain.size());
-	std::string s;
-	s.append(buf, 2);
-	s.append(plain);
-	return s;
-}
+std::string serializeString(const std::string &plain);
 
 // Creates a string with the length as the first two bytes from wide string
-inline std::string serializeWideString(const std::wstring &plain)
-{
-	//assert(plain.size() <= 65535);
-	if(plain.size() > 65535)
-		throw SerializationError("String too long for serializeString");
-	char buf[2];
-	writeU16((u8*)buf, plain.size());
-	std::string s;
-	s.append(buf, 2);
-	for(u32 i=0; i<plain.size(); i++)
-	{
-		writeU16((u8*)buf, plain[i]);
-		s.append(buf, 2);
-	}
-	return s;
-}
+std::string serializeWideString(const std::wstring &plain);
 
 // Reads a string with the length as the first two bytes
-inline std::string deSerializeString(std::istream &is)
-{
-	char buf[2];
-	is.read(buf, 2);
-	if(is.gcount() != 2)
-		throw SerializationError("deSerializeString: size not read");
-	u16 s_size = readU16((u8*)buf);
-	if(s_size == 0)
-		return "";
-	Buffer<char> buf2(s_size);
-	is.read(&buf2[0], s_size);
-	std::string s;
-	s.reserve(s_size);
-	s.append(&buf2[0], s_size);
-	return s;
-}
+std::string deSerializeString(std::istream &is);
 
 // Reads a wide string with the length as the first two bytes
-inline std::wstring deSerializeWideString(std::istream &is)
-{
-	char buf[2];
-	is.read(buf, 2);
-	if(is.gcount() != 2)
-		throw SerializationError("deSerializeString: size not read");
-	u16 s_size = readU16((u8*)buf);
-	if(s_size == 0)
-		return L"";
-	std::wstring s;
-	s.reserve(s_size);
-	for(u32 i=0; i<s_size; i++)
-	{
-		is.read(&buf[0], 2);
-		wchar_t c16 = readU16((u8*)buf);
-		s.append(&c16, 1);
-	}
-	return s;
-}
+std::wstring deSerializeWideString(std::istream &is);
 
 // Creates a string with the length as the first four bytes
-inline std::string serializeLongString(const std::string &plain)
-{
-	char buf[4];
-	writeU32((u8*)&buf[0], plain.size());
-	std::string s;
-	s.append(buf, 4);
-	s.append(plain);
-	return s;
-}
+std::string serializeLongString(const std::string &plain);
 
 // Reads a string with the length as the first four bytes
-inline std::string deSerializeLongString(std::istream &is)
-{
-	char buf[4];
-	is.read(buf, 4);
-	if(is.gcount() != 4)
-		throw SerializationError("deSerializeLongString: size not read");
-	u32 s_size = readU32((u8*)buf);
-	if(s_size == 0)
-		return "";
-	Buffer<char> buf2(s_size);
-	is.read(&buf2[0], s_size);
-	std::string s;
-	s.reserve(s_size);
-	s.append(&buf2[0], s_size);
-	return s;
-}
+std::string deSerializeLongString(std::istream &is);
 
 // Creates a string encoded in JSON format (almost equivalent to a C string literal)
 std::string serializeJsonString(const std::string &plain);
diff --git a/src/util/string.cpp b/src/util/string.cpp
index 3bd8b7364..2c1dea497 100644
--- a/src/util/string.cpp
+++ b/src/util/string.cpp
@@ -18,11 +18,35 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 */
 
 #include "string.h"
+#include "pointer.h"
 
 #include "../sha1.h"
 #include "../base64.h"
 #include "../porting.h"
 
+std::wstring narrow_to_wide(const std::string& mbs)
+{
+	size_t wcl = mbs.size();
+	Buffer<wchar_t> wcs(wcl+1);
+	size_t l = mbstowcs(*wcs, mbs.c_str(), wcl);
+	if(l == (size_t)(-1))
+		return L"<invalid multibyte string>";
+	wcs[l] = 0;
+	return *wcs;
+}
+
+std::string wide_to_narrow(const std::wstring& wcs)
+{
+	size_t mbl = wcs.size()*4;
+	SharedBuffer<char> mbs(mbl+1);
+	size_t l = wcstombs(*mbs, wcs.c_str(), mbl);
+	if(l == (size_t)(-1))
+		mbs[0] = 0;
+	else
+		mbs[l] = 0;
+	return *mbs;
+}
+
 // Get an sha-1 hash of the player's name combined with
 // the password entered. That's what the server uses as
 // their password. (Exception : if the password field is
diff --git a/src/util/string.h b/src/util/string.h
index d8cedc3e8..1cb4ae8d8 100644
--- a/src/util/string.h
+++ b/src/util/string.h
@@ -21,8 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #define UTIL_STRING_HEADER
 
 #include "../irrlichttypes.h"
-#include "../strfnd.h" // For trim()
-#include "pointer.h"
+#include <stdlib.h>
 #include <string>
 #include <cstring>
 #include <vector>
@@ -33,6 +32,9 @@ struct FlagDesc {
 	u32 flag;
 };
 
+std::wstring narrow_to_wide(const std::string& mbs);
+std::string wide_to_narrow(const std::wstring& wcs);
+
 static inline std::string padStringRight(std::string s, size_t len)
 {
 	if(len > s.size())
@@ -95,29 +97,6 @@ inline bool str_starts_with(const std::wstring& str, const std::wstring& prefix,
 	return true;
 }
 
-inline std::wstring narrow_to_wide(const std::string& mbs)
-{
-	size_t wcl = mbs.size();
-	Buffer<wchar_t> wcs(wcl+1);
-	size_t l = mbstowcs(*wcs, mbs.c_str(), wcl);
-	if(l == (size_t)(-1))
-		return L"<invalid multibyte string>";
-	wcs[l] = 0;
-	return *wcs;
-}
-
-inline std::string wide_to_narrow(const std::wstring& wcs)
-{
-	size_t mbl = wcs.size()*4;
-	SharedBuffer<char> mbs(mbl+1);
-	size_t l = wcstombs(*mbs, wcs.c_str(), mbl);
-	if(l == (size_t)(-1))
-		mbs[0] = 0;
-	else
-		mbs[l] = 0;
-	return *mbs;
-}
-
 // Split a string using the given delimiter. Returns a vector containing
 // the component parts.
 inline std::vector<std::wstring> str_split(const std::wstring &str, wchar_t delimiter)
@@ -143,6 +122,29 @@ inline std::string lowercase(const std::string &s)
 	return s2;
 }
 
+inline std::string trim(const std::string &s)
+{
+	size_t front = 0;
+	while(s[front] == ' '    ||
+	      s[front] == '\t'   ||
+	      s[front] == '\r'   ||
+	      s[front] == '\n'
+	     )
+		++front;
+
+	size_t back = s.size();
+	while(back > front &&
+	      (s[back-1] == ' '  ||
+	       s[back-1] == '\t' ||
+	       s[back-1] == '\r' ||
+	       s[back-1] == '\n'
+	      )
+	     )
+		--back;
+
+	return s.substr(front, back - front);
+}
+
 inline bool is_yes(const std::string &s)
 {
 	std::string s2 = lowercase(trim(s));
diff --git a/src/voxel.cpp b/src/voxel.cpp
index 58519ed5f..4b523b596 100644
--- a/src/voxel.cpp
+++ b/src/voxel.cpp
@@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "gettime.h"
 #include "nodedef.h"
 #include "util/timetaker.h"
+#include <string.h>  // memcpy, memset
 
 /*
 	Debug stuff
diff --git a/src/voxel.h b/src/voxel.h
index bed35b57e..fa459444f 100644
--- a/src/voxel.h
+++ b/src/voxel.h
@@ -22,12 +22,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 #include "irrlichttypes.h"
 #include "irr_v3d.h"
-#include <irrList.h>
 #include <iostream>
 #include "debug.h"
+#include "exceptions.h"
 #include "mapnode.h"
 #include <set>
 #include <list>
+#include <map>
 
 class INodeDefManager;
 
-- 
GitLab