summaryrefslogtreecommitdiff
path: root/src/script
diff options
context:
space:
mode:
authorKahrl <kahrl@gmx.net>2013-08-11 04:09:45 +0200
committerKahrl <kahrl@gmx.net>2013-08-14 21:03:33 +0200
commit4e1f50035e860a00636ca5d804c267119df99601 (patch)
treec6cab522305ef2a5b9cfdb3685340d57590f1ff1 /src/script
parent6228d634fb31d1ce925d1fdc2dac022629a007ef (diff)
downloadminetest-4e1f50035e860a00636ca5d804c267119df99601.tar.gz
minetest-4e1f50035e860a00636ca5d804c267119df99601.tar.bz2
minetest-4e1f50035e860a00636ca5d804c267119df99601.zip
Omnicleanup: header cleanup, add ModApiUtil shared between game and mainmenu
Diffstat (limited to 'src/script')
-rw-r--r--src/script/CMakeLists.txt18
-rw-r--r--src/script/common/CMakeLists.txt7
-rw-r--r--src/script/common/c_content.cpp9
-rw-r--r--src/script/common/c_content.h13
-rw-r--r--src/script/common/c_internal.cpp109
-rw-r--r--src/script/common/c_internal.h56
-rw-r--r--src/script/common/c_types.h20
-rw-r--r--src/script/cpp_api/CMakeLists.txt10
-rw-r--r--src/script/cpp_api/s_base.cpp279
-rw-r--r--src/script/cpp_api/s_base.h119
-rw-r--r--src/script/cpp_api/s_entity.cpp5
-rw-r--r--src/script/cpp_api/s_env.cpp11
-rw-r--r--src/script/cpp_api/s_internal.h63
-rw-r--r--src/script/cpp_api/s_inventory.cpp1
-rw-r--r--src/script/cpp_api/s_item.cpp3
-rw-r--r--src/script/cpp_api/s_mainmenu.cpp80
-rw-r--r--src/script/cpp_api/s_mainmenu.h49
-rw-r--r--src/script/cpp_api/s_node.cpp2
-rw-r--r--src/script/cpp_api/s_nodemeta.cpp6
-rw-r--r--src/script/cpp_api/s_player.cpp15
-rw-r--r--src/script/cpp_api/s_player.h2
-rw-r--r--src/script/cpp_api/s_server.cpp151
-rw-r--r--src/script/cpp_api/s_server.h52
-rw-r--r--src/script/cpp_api/scriptapi.cpp291
-rw-r--r--src/script/lua_api/CMakeLists.txt13
-rw-r--r--src/script/lua_api/l_base.cpp47
-rw-r--r--src/script/lua_api/l_base.h57
-rw-r--r--src/script/lua_api/l_craft.cpp31
-rw-r--r--src/script/lua_api/l_craft.h14
-rw-r--r--src/script/lua_api/l_env.cpp276
-rw-r--r--src/script/lua_api/l_env.h23
-rw-r--r--src/script/lua_api/l_internal.h43
-rw-r--r--src/script/lua_api/l_inventory.cpp52
-rw-r--r--src/script/lua_api/l_inventory.h30
-rw-r--r--src/script/lua_api/l_item.cpp66
-rw-r--r--src/script/lua_api/l_item.h30
-rw-r--r--src/script/lua_api/l_mainmenu.cpp1016
-rw-r--r--src/script/lua_api/l_mainmenu.h137
-rw-r--r--src/script/lua_api/l_mapgen.cpp574
-rw-r--r--src/script/lua_api/l_mapgen.h62
-rw-r--r--src/script/lua_api/l_nodemeta.cpp16
-rw-r--r--src/script/lua_api/l_nodemeta.h15
-rw-r--r--src/script/lua_api/l_nodetimer.cpp6
-rw-r--r--src/script/lua_api/l_nodetimer.h11
-rw-r--r--src/script/lua_api/l_noise.cpp7
-rw-r--r--src/script/lua_api/l_noise.h26
-rw-r--r--src/script/lua_api/l_object.cpp25
-rw-r--r--src/script/lua_api/l_object.h9
-rw-r--r--src/script/lua_api/l_particles.cpp24
-rw-r--r--src/script/lua_api/l_particles.h12
-rw-r--r--src/script/lua_api/l_rollback.cpp80
-rw-r--r--src/script/lua_api/l_rollback.h37
-rw-r--r--src/script/lua_api/l_server.cpp347
-rw-r--r--src/script/lua_api/l_server.h (renamed from src/script/lua_api/luaapi.h)114
-rw-r--r--src/script/lua_api/l_util.cpp199
-rw-r--r--src/script/lua_api/l_util.h76
-rw-r--r--src/script/lua_api/l_vmanip.cpp39
-rw-r--r--src/script/lua_api/l_vmanip.h17
-rw-r--r--src/script/lua_api/luaapi.cpp955
-rw-r--r--src/script/scripting_game.cpp99
-rw-r--r--src/script/scripting_game.h (renamed from src/script/cpp_api/scriptapi.h)61
-rw-r--r--src/script/scripting_mainmenu.cpp65
-rw-r--r--src/script/scripting_mainmenu.h45
63 files changed, 3872 insertions, 2255 deletions
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 @@ public:
}
};
-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 @@ protected:
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 @@ private:
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 @@ private:
// 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 @@ private:
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 @@ public:
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 @@ public:
};
-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/script/lua_api/l_mainmenu.cpp b/src/script/lua_api/l_mainmenu.cpp
new file mode 100644
index 000000000..b3ae1f3f1
--- /dev/null
+++ b/src/script/lua_api/l_mainmenu.cpp
@@ -0,0 +1,1016 @@
+/*
+Minetest
+Copyright (C) 2013 sapier
+
+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_mainmenu.h"
+#include "lua_api/l_internal.h"
+#include "common/c_content.h"
+#include "guiEngine.h"
+#include "guiMainMenu.h"
+#include "guiKeyChangeMenu.h"
+#include "guiFileSelectMenu.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>
+
+/******************************************************************************/
+std::string ModApiMainMenu::getTextData(lua_State *L, std::string name)
+{
+ lua_getglobal(L, "gamedata");
+
+ lua_getfield(L, -1, name.c_str());
+
+ if(lua_isnil(L, -1))
+ return "";
+
+ return luaL_checkstring(L, -1);
+}
+
+/******************************************************************************/
+int ModApiMainMenu::getIntegerData(lua_State *L, std::string name,bool& valid)
+{
+ lua_getglobal(L, "gamedata");
+
+ lua_getfield(L, -1, name.c_str());
+
+ if(lua_isnil(L, -1)) {
+ valid = false;
+ return -1;
+ }
+
+ valid = true;
+ return luaL_checkinteger(L, -1);
+}
+
+/******************************************************************************/
+int ModApiMainMenu::getBoolData(lua_State *L, std::string name,bool& valid)
+{
+ lua_getglobal(L, "gamedata");
+
+ lua_getfield(L, -1, name.c_str());
+
+ if(lua_isnil(L, -1)) {
+ valid = false;
+ return false;
+ }
+
+ valid = true;
+ return lua_toboolean(L, -1);
+}
+
+/******************************************************************************/
+int ModApiMainMenu::l_update_formspec(lua_State *L)
+{
+ GUIEngine* engine = getGuiEngine(L);
+ assert(engine != 0);
+
+ if (engine->m_startgame)
+ return 0;
+
+ //read formspec
+ std::string formspec(luaL_checkstring(L, 1));
+
+ if (engine->m_formspecgui != 0) {
+ engine->m_formspecgui->setForm(formspec);
+ }
+
+ return 0;
+}
+
+/******************************************************************************/
+int ModApiMainMenu::l_start(lua_State *L)
+{
+ GUIEngine* engine = getGuiEngine(L);
+ assert(engine != 0);
+
+ //update c++ gamedata from lua table
+
+ bool valid = false;
+
+
+ engine->m_data->selected_world = getIntegerData(L, "selected_world",valid) -1;
+ engine->m_data->simple_singleplayer_mode = getBoolData(L,"singleplayer",valid);
+ engine->m_data->name = getTextData(L,"playername");
+ engine->m_data->password = getTextData(L,"password");
+ engine->m_data->address = getTextData(L,"address");
+ engine->m_data->port = getTextData(L,"port");
+ engine->m_data->serverdescription = getTextData(L,"serverdescription");
+ engine->m_data->servername = getTextData(L,"servername");
+
+ //close menu next time
+ engine->m_startgame = true;
+ return 0;
+}
+
+/******************************************************************************/
+int ModApiMainMenu::l_close(lua_State *L)
+{
+ GUIEngine* engine = getGuiEngine(L);
+ assert(engine != 0);
+
+ engine->m_data->kill = true;
+
+ //close menu next time
+ engine->m_startgame = true;
+ engine->m_menu->quitMenu();
+ return 0;
+}
+
+/******************************************************************************/
+int ModApiMainMenu::l_set_background(lua_State *L)
+{
+ GUIEngine* engine = getGuiEngine(L);
+ assert(engine != 0);
+
+ std::string backgroundlevel(luaL_checkstring(L, 1));
+ std::string texturename(luaL_checkstring(L, 2));
+
+ bool retval = false;
+
+ if (backgroundlevel == "background") {
+ retval |= engine->setTexture(TEX_LAYER_BACKGROUND,texturename);
+ }
+
+ if (backgroundlevel == "overlay") {
+ retval |= engine->setTexture(TEX_LAYER_OVERLAY,texturename);
+ }
+
+ if (backgroundlevel == "header") {
+ retval |= engine->setTexture(TEX_LAYER_HEADER,texturename);
+ }
+
+ if (backgroundlevel == "footer") {
+ retval |= engine->setTexture(TEX_LAYER_FOOTER,texturename);
+ }
+
+ lua_pushboolean(L,retval);
+ return 1;
+}
+
+/******************************************************************************/
+int ModApiMainMenu::l_set_clouds(lua_State *L)
+{
+ GUIEngine* engine = getGuiEngine(L);
+ assert(engine != 0);
+
+ bool value = lua_toboolean(L,1);
+
+ engine->m_clouds_enabled = value;
+
+ return 0;
+}
+
+/******************************************************************************/
+int ModApiMainMenu::l_get_textlist_index(lua_State *L)
+{
+ GUIEngine* engine = getGuiEngine(L);
+ assert(engine != 0);
+
+ std::string listboxname(luaL_checkstring(L, 1));
+
+ int selection = engine->m_menu->getListboxIndex(listboxname);
+
+ if (selection >= 0)
+ selection++;
+
+ lua_pushinteger(L, selection);
+ return 1;
+}
+
+/******************************************************************************/
+int ModApiMainMenu::l_get_worlds(lua_State *L)
+{
+ GUIEngine* engine = getGuiEngine(L);
+ assert(engine != 0);
+
+ std::vector<WorldSpec> worlds = getAvailableWorlds();
+
+ lua_newtable(L);
+ int top = lua_gettop(L);
+ unsigned int index = 1;
+
+ for (unsigned int i = 0; i < worlds.size(); i++)
+ {
+ lua_pushnumber(L,index);
+
+ lua_newtable(L);
+ int top_lvl2 = lua_gettop(L);
+
+ lua_pushstring(L,"path");
+ lua_pushstring(L,worlds[i].path.c_str());
+ lua_settable(L, top_lvl2);
+
+ lua_pushstring(L,"name");
+ lua_pushstring(L,worlds[i].name.c_str());
+ lua_settable(L, top_lvl2);
+
+ lua_pushstring(L,"gameid");
+ lua_pushstring(L,worlds[i].gameid.c_str());
+ lua_settable(L, top_lvl2);
+
+ lua_settable(L, top);
+ index++;
+ }
+ return 1;
+}
+
+/******************************************************************************/
+int ModApiMainMenu::l_get_games(lua_State *L)
+{
+ GUIEngine* engine = getGuiEngine(L);
+ assert(engine != 0);
+
+ std::vector<SubgameSpec> games = getAvailableGames();
+
+ lua_newtable(L);
+ int top = lua_gettop(L);
+ unsigned int index = 1;
+
+ for (unsigned int i = 0; i < games.size(); i++)
+ {
+ lua_pushnumber(L,index);
+ lua_newtable(L);
+ int top_lvl2 = lua_gettop(L);
+
+ lua_pushstring(L,"id");
+ lua_pushstring(L,games[i].id.c_str());
+ lua_settable(L, top_lvl2);
+
+ lua_pushstring(L,"path");
+ lua_pushstring(L,games[i].path.c_str());
+ lua_settable(L, top_lvl2);
+
+ lua_pushstring(L,"gamemods_path");
+ lua_pushstring(L,games[i].gamemods_path.c_str());
+ lua_settable(L, top_lvl2);
+
+ lua_pushstring(L,"name");
+ lua_pushstring(L,games[i].name.c_str());
+ lua_settable(L, top_lvl2);
+
+ lua_pushstring(L,"menuicon_path");
+ lua_pushstring(L,games[i].menuicon_path.c_str());
+ lua_settable(L, top_lvl2);
+
+ lua_pushstring(L,"addon_mods_paths");
+ lua_newtable(L);
+ int table2 = lua_gettop(L);
+ int internal_index=1;
+ for (std::set<std::string>::iterator iter = games[i].addon_mods_paths.begin();
+ iter != games[i].addon_mods_paths.end(); iter++) {
+ lua_pushnumber(L,internal_index);
+ lua_pushstring(L,(*iter).c_str());
+ lua_settable(L, table2);
+ internal_index++;
+ }
+ lua_settable(L, top_lvl2);
+ lua_settable(L, top);
+ index++;
+ }
+ return 1;
+}
+/******************************************************************************/
+int ModApiMainMenu::l_get_modstore_details(lua_State *L)
+{
+ const char *modid = luaL_checkstring(L, 1);
+
+ if (modid != 0) {
+ Json::Value details;
+ std::string url = "";
+ try{
+ url = g_settings->get("modstore_details_url");
+ }
+ catch(SettingNotFoundException &e) {
+ lua_pushnil(L);
+ return 1;
+ }
+
+ size_t idpos = url.find("*");
+ url.erase(idpos,1);
+ url.insert(idpos,modid);
+
+ details = getModstoreUrl(url);
+
+ ModStoreModDetails current_mod = readModStoreModDetails(details);
+
+ if ( current_mod.valid) {
+ lua_newtable(L);
+ int top = lua_gettop(L);
+
+ lua_pushstring(L,"id");
+ lua_pushnumber(L,current_mod.id);
+ lua_settable(L, top);
+
+ lua_pushstring(L,"title");
+ lua_pushstring(L,current_mod.title.c_str());
+ lua_settable(L, top);
+
+ lua_pushstring(L,"basename");
+ lua_pushstring(L,current_mod.basename.c_str());
+ lua_settable(L, top);
+
+ lua_pushstring(L,"description");
+ lua_pushstring(L,current_mod.description.c_str());
+ lua_settable(L, top);
+
+ lua_pushstring(L,"author");
+ lua_pushstring(L,current_mod.author.username.c_str());
+ lua_settable(L, top);
+
+ lua_pushstring(L,"download_url");
+ lua_pushstring(L,current_mod.versions[0].file.c_str());
+ lua_settable(L, top);
+
+ lua_pushstring(L,"screenshot_url");
+ lua_pushstring(L,current_mod.titlepic.file.c_str());
+ lua_settable(L, top);
+
+ lua_pushstring(L,"license");
+ lua_pushstring(L,current_mod.license.shortinfo.c_str());
+ lua_settable(L, top);
+
+ lua_pushstring(L,"rating");
+ lua_pushnumber(L,current_mod.rating);
+ lua_settable(L, top);
+
+ //TODO depends
+
+ //TODO softdepends
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/******************************************************************************/
+int ModApiMainMenu::l_get_modstore_list(lua_State *L)
+{
+ GUIEngine* engine = getGuiEngine(L);
+ assert(engine != 0);
+
+ std::string listtype = "local";
+
+ if (!lua_isnone(L,1)) {
+ listtype = luaL_checkstring(L,1);
+ }
+ Json::Value mods;
+ std::string url = "";
+ try{
+ url = g_settings->get("modstore_listmods_url");
+ }
+ catch(SettingNotFoundException &e) {
+ lua_pushnil(L);
+ return 1;
+ }
+
+ mods = getModstoreUrl(url);
+
+ std::vector<ModStoreMod> moddata = readModStoreList(mods);
+
+ lua_newtable(L);
+ int top = lua_gettop(L);
+ unsigned int index = 1;
+
+ for (unsigned int i = 0; i < moddata.size(); i++)
+ {
+ if (moddata[i].valid) {
+ lua_pushnumber(L,index);
+ lua_newtable(L);
+
+ int top_lvl2 = lua_gettop(L);
+
+ lua_pushstring(L,"id");
+ lua_pushnumber(L,moddata[i].id);
+ lua_settable(L, top_lvl2);
+
+ lua_pushstring(L,"title");
+ lua_pushstring(L,moddata[i].title.c_str());
+ lua_settable(L, top_lvl2);
+
+ lua_pushstring(L,"basename");
+ lua_pushstring(L,moddata[i].basename.c_str());
+ lua_settable(L, top_lvl2);
+
+ lua_settable(L, top);
+ index++;
+ }
+ }
+ return 1;
+}
+
+/******************************************************************************/
+int ModApiMainMenu::l_get_favorites(lua_State *L)
+{
+ GUIEngine* engine = getGuiEngine(L);
+ assert(engine != 0);
+
+ std::string listtype = "local";
+
+ if (!lua_isnone(L,1)) {
+ listtype = luaL_checkstring(L,1);
+ }
+
+ std::vector<ServerListSpec> servers;
+#if USE_CURL
+ if(listtype == "online") {
+ servers = ServerList::getOnline();
+ } else {
+ servers = ServerList::getLocal();
+ }
+#else
+ servers = ServerList::getLocal();
+#endif
+
+ lua_newtable(L);
+ int top = lua_gettop(L);
+ unsigned int index = 1;
+
+ for (unsigned int i = 0; i < servers.size(); i++)
+ {
+ lua_pushnumber(L,index);
+
+ lua_newtable(L);
+ int top_lvl2 = lua_gettop(L);
+
+ if (servers[i]["clients"].asString().size()) {
+
+ const char* clients_raw = servers[i]["clients"].asString().c_str();
+ char* endptr = 0;
+ int numbervalue = strtol(clients_raw,&endptr,10);
+
+ if ((*clients_raw != 0) && (*endptr == 0)) {
+ lua_pushstring(L,"clients");
+ lua_pushnumber(L,numbervalue);
+ lua_settable(L, top_lvl2);
+ }
+ }
+
+ if (servers[i]["clients_max"].asString().size()) {
+
+ const char* clients_max_raw = servers[i]["clients_max"].asString().c_str();
+ char* endptr = 0;
+ int numbervalue = strtol(clients_max_raw,&endptr,10);
+
+ if ((*clients_max_raw != 0) && (*endptr == 0)) {
+ lua_pushstring(L,"clients_max");
+ lua_pushnumber(L,numbervalue);
+ lua_settable(L, top_lvl2);
+ }
+ }
+
+ if (servers[i]["version"].asString().size()) {
+ lua_pushstring(L,"version");
+ lua_pushstring(L,servers[i]["version"].asString().c_str());
+ lua_settable(L, top_lvl2);
+ }
+
+ if (servers[i]["password"].asString().size()) {
+ lua_pushstring(L,"password");
+ lua_pushboolean(L,true);
+ lua_settable(L, top_lvl2);
+ }
+
+ if (servers[i]["creative"].asString().size()) {
+ lua_pushstring(L,"creative");
+ lua_pushboolean(L,true);
+ lua_settable(L, top_lvl2);
+ }
+
+ if (servers[i]["damage"].asString().size()) {
+ lua_pushstring(L,"damage");
+ lua_pushboolean(L,true);
+ lua_settable(L, top_lvl2);
+ }
+
+ if (servers[i]["pvp"].asString().size()) {
+ lua_pushstring(L,"pvp");
+ lua_pushboolean(L,true);
+ lua_settable(L, top_lvl2);
+ }
+
+ if (servers[i]["description"].asString().size()) {
+ lua_pushstring(L,"description");
+ lua_pushstring(L,servers[i]["description"].asString().c_str());
+ lua_settable(L, top_lvl2);
+ }
+
+ if (servers[i]["name"].asString().size()) {
+ lua_pushstring(L,"name");
+ lua_pushstring(L,servers[i]["name"].asString().c_str());
+ lua_settable(L, top_lvl2);
+ }
+
+ if (servers[i]["address"].asString().size()) {
+ lua_pushstring(L,"address");
+ lua_pushstring(L,servers[i]["address"].asString().c_str());
+ lua_settable(L, top_lvl2);
+ }
+
+ if (servers[i]["port"].asString().size()) {
+ lua_pushstring(L,"port");
+ lua_pushstring(L,servers[i]["port"].asString().c_str());
+ lua_settable(L, top_lvl2);
+ }
+
+ lua_settable(L, top);
+ index++;
+ }
+ return 1;
+}
+
+/******************************************************************************/
+int ModApiMainMenu::l_delete_favorite(lua_State *L)
+{
+ GUIEngine* engine = getGuiEngine(L);
+ assert(engine != 0);
+
+ std::vector<ServerListSpec> servers;
+
+ std::string listtype = "local";
+
+ if (!lua_isnone(L,2)) {
+ listtype = luaL_checkstring(L,2);
+ }
+
+ if ((listtype != "local") &&
+ (listtype != "online"))
+ return 0;
+
+#if USE_CURL
+ if(listtype == "online") {
+ servers = ServerList::getOnline();
+ } else {
+ servers = ServerList::getLocal();
+ }
+#else
+ servers = ServerList::getLocal();
+#endif
+
+ int fav_idx = luaL_checkinteger(L,1) -1;
+
+ if ((fav_idx >= 0) &&
+ (fav_idx < (int) servers.size())) {
+
+ ServerList::deleteEntry(servers[fav_idx]);
+ }
+
+ return 0;
+}
+
+/******************************************************************************/
+int ModApiMainMenu::l_show_keys_menu(lua_State *L)
+{
+ GUIEngine* engine = getGuiEngine(L);
+ assert(engine != 0);
+
+ GUIKeyChangeMenu *kmenu
+ = new GUIKeyChangeMenu( engine->m_device->getGUIEnvironment(),
+ engine->m_parent,
+ -1,
+ engine->m_menumanager);
+ kmenu->drop();
+ return 0;
+}
+
+/******************************************************************************/
+int ModApiMainMenu::l_create_world(lua_State *L)
+{
+ GUIEngine* engine = getGuiEngine(L);
+ assert(engine != 0);
+
+ const char *name = luaL_checkstring(L, 1);
+ int gameidx = luaL_checkinteger(L,2) -1;
+
+ std::string path = porting::path_user + DIR_DELIM
+ "worlds" + DIR_DELIM
+ + name;
+
+ std::vector<SubgameSpec> games = getAvailableGames();
+
+ if ((gameidx >= 0) &&
+ (gameidx < (int) games.size())) {
+
+ // Create world if it doesn't exist
+ if(!initializeWorld(path, games[gameidx].id)){
+ lua_pushstring(L, "Failed to initialize world");
+
+ }
+ else {
+ lua_pushnil(L);
+ }
+ }
+ else {
+ lua_pushstring(L, "Invalid game index");
+ }
+ return 1;
+}
+
+/******************************************************************************/
+int ModApiMainMenu::l_delete_world(lua_State *L)
+{
+ GUIEngine* engine = getGuiEngine(L);
+ assert(engine != 0);
+
+ int worldidx = luaL_checkinteger(L,1) -1;
+
+ std::vector<WorldSpec> worlds = getAvailableWorlds();
+
+ if ((worldidx >= 0) &&
+ (worldidx < (int) worlds.size())) {
+
+ WorldSpec spec = worlds[worldidx];
+
+ std::vector<std::string> paths;
+ paths.push_back(spec.path);
+ fs::GetRecursiveSubPaths(spec.path, paths);
+
+ // Delete files
+ if (!fs::DeletePaths(paths)) {
+ lua_pushstring(L, "Failed to delete world");
+ }
+ else {
+ lua_pushnil(L);
+ }
+ }
+ else {
+ lua_pushstring(L, "Invalid world index");
+ }
+ return 1;
+}
+
+/******************************************************************************/
+int ModApiMainMenu::l_set_topleft_text(lua_State *L)
+{
+ GUIEngine* engine = getGuiEngine(L);
+ assert(engine != 0);
+
+ std::string text = "";
+
+ if (!lua_isnone(L,1) && !lua_isnil(L,1))
+ text = luaL_checkstring(L, 1);
+
+ engine->setTopleftText(text);
+ return 0;
+}
+
+/******************************************************************************/
+int ModApiMainMenu::l_get_modpath(lua_State *L)
+{
+ std::string modpath
+ = fs::RemoveRelativePathComponents(porting::path_user + DIR_DELIM + "mods" + DIR_DELIM);
+ lua_pushstring(L, modpath.c_str());
+ return 1;
+}
+
+/******************************************************************************/
+int ModApiMainMenu::l_get_gamepath(lua_State *L)
+{
+ std::string gamepath
+ = fs::RemoveRelativePathComponents(porting::path_user + DIR_DELIM + "games" + DIR_DELIM);
+ lua_pushstring(L, gamepath.c_str());
+ return 1;
+}
+
+/******************************************************************************/
+int ModApiMainMenu::l_get_texturepath(lua_State *L)
+{
+ std::string gamepath
+ = fs::RemoveRelativePathComponents(porting::path_user + DIR_DELIM + "textures");
+ lua_pushstring(L, gamepath.c_str());
+ return 1;
+}
+
+/******************************************************************************/
+int ModApiMainMenu::l_get_dirlist(lua_State *L)
+{
+ const char *path = luaL_checkstring(L, 1);
+ bool dironly = lua_toboolean(L, 2);
+
+ std::vector<fs::DirListNode> dirlist = fs::GetDirListing(path);
+
+ unsigned int index = 1;
+ lua_newtable(L);
+ int table = lua_gettop(L);
+
+ for (unsigned int i=0;i< dirlist.size(); i++) {
+ if ((dirlist[i].dir) || (dironly == false)) {
+ lua_pushnumber(L,index);
+ lua_pushstring(L,dirlist[i].name.c_str());
+ lua_settable(L, table);
+ index++;
+ }
+ }
+
+ return 1;
+}
+
+/******************************************************************************/
+int ModApiMainMenu::l_create_dir(lua_State *L) {
+ const char *path = luaL_checkstring(L, 1);
+
+ if (ModApiMainMenu::isMinetestPath(path)) {
+ lua_pushboolean(L,fs::CreateAllDirs(path));
+ return 1;
+ }
+ lua_pushboolean(L,false);
+ return 1;
+}
+
+/******************************************************************************/
+int ModApiMainMenu::l_delete_dir(lua_State *L)
+{
+ const char *path = luaL_checkstring(L, 1);
+
+ std::string absolute_path = fs::RemoveRelativePathComponents(path);
+
+ if (ModApiMainMenu::isMinetestPath(absolute_path)) {
+ lua_pushboolean(L,fs::RecursiveDelete(absolute_path));
+ return 1;
+ }
+ lua_pushboolean(L,false);
+ return 1;
+}
+
+/******************************************************************************/
+int ModApiMainMenu::l_copy_dir(lua_State *L)
+{
+ const char *source = luaL_checkstring(L, 1);
+ const char *destination = luaL_checkstring(L, 2);
+
+ bool keep_source = true;
+
+ if ((!lua_isnone(L,3)) &&
+ (!lua_isnil(L,3))) {
+ keep_source = lua_toboolean(L,3);
+ }
+
+ std::string absolute_destination = fs::RemoveRelativePathComponents(destination);
+ std::string absolute_source = fs::RemoveRelativePathComponents(source);
+
+ if ((ModApiMainMenu::isMinetestPath(absolute_source)) &&
+ (ModApiMainMenu::isMinetestPath(absolute_destination))) {
+ bool retval = fs::CopyDir(absolute_source,absolute_destination);
+
+ if (retval && (!keep_source)) {
+
+ retval &= fs::RecursiveDelete(absolute_source);
+ }
+ lua_pushboolean(L,retval);
+ return 1;
+ }
+ lua_pushboolean(L,false);
+ return 1;
+}
+
+/******************************************************************************/
+int ModApiMainMenu::l_extract_zip(lua_State *L)
+{
+ GUIEngine* engine = getGuiEngine(L);
+ assert(engine != 0);
+
+ const char *zipfile = luaL_checkstring(L, 1);
+ const char *destination = luaL_checkstring(L, 2);
+
+ std::string absolute_destination = fs::RemoveRelativePathComponents(destination);
+
+ if (ModApiMainMenu::isMinetestPath(absolute_destination)) {
+ fs::CreateAllDirs(absolute_destination);
+
+ io::IFileSystem* fs = engine->m_device->getFileSystem();
+
+ fs->addFileArchive(zipfile,true,false,io::EFAT_ZIP);
+
+ assert(fs->getFileArchiveCount() > 0);
+
+ /**********************************************************************/
+ /* WARNING this is not threadsafe!! */
+ /**********************************************************************/
+ io::IFileArchive* opened_zip =
+ fs->getFileArchive(fs->getFileArchiveCount()-1);
+
+ const io::IFileList* files_in_zip = opened_zip->getFileList();
+
+ unsigned int number_of_files = files_in_zip->getFileCount();
+
+ for (unsigned int i=0; i < number_of_files; i++) {
+ std::string fullpath = destination;
+ fullpath += DIR_DELIM;
+ fullpath += files_in_zip->getFullFileName(i).c_str();
+
+ if (files_in_zip->isDirectory(i)) {
+ if (! fs::CreateAllDirs(fullpath) ) {
+ fs->removeFileArchive(fs->getFileArchiveCount()-1);
+ lua_pushboolean(L,false);
+ return 1;
+ }
+ }
+ else {
+ io::IReadFile* toread = opened_zip->createAndOpenFile(i);
+
+ FILE *targetfile = fopen(fullpath.c_str(),"wb");
+
+ if (targetfile == NULL) {
+ fs->removeFileArchive(fs->getFileArchiveCount()-1);
+ lua_pushboolean(L,false);
+ return 1;
+ }
+
+ char read_buffer[1024];
+ unsigned int total_read = 0;
+
+ while (total_read < toread->getSize()) {
+
+ unsigned int bytes_read =
+ toread->read(read_buffer,sizeof(read_buffer));
+ unsigned int bytes_written;
+ if ((bytes_read < 0 ) ||
+ (bytes_written = fwrite(read_buffer, 1, bytes_read, targetfile) != bytes_read))
+ {
+ fclose(targetfile);
+ fs->removeFileArchive(fs->getFileArchiveCount()-1);
+ lua_pushboolean(L,false);
+ return 1;
+ }
+ total_read += bytes_read;
+ }
+
+ fclose(targetfile);
+ }
+
+ }
+
+ fs->removeFileArchive(fs->getFileArchiveCount()-1);
+ lua_pushboolean(L,true);
+ return 1;
+ }
+
+ lua_pushboolean(L,false);
+ return 1;
+}
+
+/******************************************************************************/
+int ModApiMainMenu::l_get_scriptdir(lua_State *L)
+{
+ GUIEngine* engine = getGuiEngine(L);
+ assert(engine != 0);
+
+ lua_pushstring(L,engine->getScriptDir().c_str());
+ return 1;
+}
+
+/******************************************************************************/
+bool ModApiMainMenu::isMinetestPath(std::string path)
+{
+ if (fs::PathStartsWith(path,fs::TempPath()))
+ return true;
+
+ /* games */
+ if (fs::PathStartsWith(path,fs::RemoveRelativePathComponents(porting::path_share + DIR_DELIM + "games")))
+ return true;
+
+ /* mods */
+ if (fs::PathStartsWith(path,fs::RemoveRelativePathComponents(porting::path_user + DIR_DELIM + "mods")))
+ return true;
+
+ /* worlds */
+ if (fs::PathStartsWith(path,fs::RemoveRelativePathComponents(porting::path_user + DIR_DELIM + "worlds")))
+ return true;
+
+
+ return false;
+}
+
+/******************************************************************************/
+int ModApiMainMenu::l_show_file_open_dialog(lua_State *L)
+{
+ GUIEngine* engine = getGuiEngine(L);
+ assert(engine != 0);
+
+ const char *formname= luaL_checkstring(L, 1);
+ const char *title = luaL_checkstring(L, 2);
+
+ GUIFileSelectMenu* fileOpenMenu =
+ new GUIFileSelectMenu(engine->m_device->getGUIEnvironment(),
+ engine->m_parent,
+ -1,
+ engine->m_menumanager,
+ title,
+ formname);
+ fileOpenMenu->setTextDest(engine->m_buttonhandler);
+ fileOpenMenu->drop();
+ return 0;
+}
+
+/******************************************************************************/
+int ModApiMainMenu::l_get_version(lua_State *L)
+{
+ lua_pushstring(L,VERSION_STRING);
+ return 1;
+}
+
+/******************************************************************************/
+int ModApiMainMenu::l_sound_play(lua_State *L)
+{
+ GUIEngine* engine = getGuiEngine(L);
+
+ SimpleSoundSpec spec;
+ read_soundspec(L, 1, spec);
+ bool looped = lua_toboolean(L, 2);
+
+ u32 handle = engine->playSound(spec, looped);
+
+ lua_pushinteger(L, handle);
+
+ return 1;
+}
+
+/******************************************************************************/
+int ModApiMainMenu::l_sound_stop(lua_State *L)
+{
+ GUIEngine* engine = getGuiEngine(L);
+
+ u32 handle = luaL_checkinteger(L, 1);
+ engine->stopSound(handle);
+
+ return 1;
+}
+
+/******************************************************************************/
+int ModApiMainMenu::l_download_file(lua_State *L)
+{
+ GUIEngine* engine = getGuiEngine(L);
+ assert(engine != 0);
+
+ const char *url = luaL_checkstring(L, 1);
+ const char *target = luaL_checkstring(L, 2);
+
+ //check path
+ std::string absolute_destination = fs::RemoveRelativePathComponents(target);
+
+ if (ModApiMainMenu::isMinetestPath(absolute_destination)) {
+ if (engine->downloadFile(url,absolute_destination)) {
+ lua_pushboolean(L,true);
+ return 1;
+ }
+ }
+ 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/script/lua_api/l_mainmenu.h b/src/script/lua_api/l_mainmenu.h
new file mode 100644
index 000000000..21dd82c68
--- /dev/null
+++ b/src/script/lua_api/l_mainmenu.h
@@ -0,0 +1,137 @@
+/*
+Minetest
+Copyright (C) 2013 sapier
+
+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_MAINMENU_H_
+#define L_MAINMENU_H_
+
+#include "lua_api/l_base.h"
+
+/** Implementation of lua api support for mainmenu */
+class ModApiMainMenu : public ModApiBase {
+
+private:
+ /**
+ * read a text variable from gamedata table within lua stack
+ * @param L stack to read variable from
+ * @param name name of variable to read
+ * @return string value of requested variable
+ */
+ static std::string getTextData(lua_State *L, std::string name);
+
+ /**
+ * read a integer variable from gamedata table within lua stack
+ * @param L stack to read variable from
+ * @param name name of variable to read
+ * @return integer value of requested variable
+ */
+ static int getIntegerData(lua_State *L, std::string name,bool& valid);
+
+ /**
+ * read a bool variable from gamedata table within lua stack
+ * @param L stack to read variable from
+ * @param name name of variable to read
+ * @return bool value of requested variable
+ */
+ static int getBoolData(lua_State *L, std::string name,bool& valid);
+
+ /**
+ * check if a path is within some of minetests folders
+ * @param path path to check
+ * @return true/false
+ */
+ static bool isMinetestPath(std::string path);
+
+ //api calls
+
+ static int l_start(lua_State *L);
+
+ static int l_close(lua_State *L);
+
+ static int l_create_world(lua_State *L);
+
+ static int l_delete_world(lua_State *L);
+
+ static int l_get_worlds(lua_State *L);
+
+ static int l_get_games(lua_State *L);
+
+ static int l_get_favorites(lua_State *L);
+
+ static int l_delete_favorite(lua_State *L);
+
+ static int l_get_version(lua_State *L);
+
+ static int l_sound_play(lua_State *L);
+
+ static int l_sound_stop(lua_State *L);
+
+ //gui
+
+ static int l_show_keys_menu(lua_State *L);
+
+ static int l_show_file_open_dialog(lua_State *L);
+
+ static int l_set_topleft_text(lua_State *L);
+
+ static int l_set_clouds(lua_State *L);
+
+ static int l_get_textlist_index(lua_State *L);
+
+ static int l_set_background(lua_State *L);
+
+ static int l_update_formspec(lua_State *L);
+
+ //filesystem
+
+ static int l_get_scriptdir(lua_State *L);
+
+ static int l_get_modpath(lua_State *L);
+
+ static int l_get_gamepath(lua_State *L);
+
+ static int l_get_texturepath(lua_State *L);
+
+ static int l_get_dirlist(lua_State *L);
+
+ static int l_create_dir(lua_State *L);
+
+ static int l_delete_dir(lua_State *L);
+
+ static int l_copy_dir(lua_State *L);
+
+ static int l_extract_zip(lua_State *L);
+
+ static int l_get_modstore_details(lua_State *L);
+
+ static int l_get_modstore_list(lua_State *L);
+
+ 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 /* 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 @@ public:
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 @@ public:
};
/*
- PerlinNoiseMap
- */
-class LuaPerlinNoiseMap
-{
+ LuaPerlinNoiseMap
+*/
+class LuaPerlinNoiseMap : public ModApiBase {
private:
Noise *noise;
static const char className[];
@@ -95,10 +92,7 @@ public:
/*
LuaPseudoRandom
*/
-
-
-class LuaPseudoRandom
-{
+class LuaPseudoRandom : public ModApiBase {
private:
PseudoRandom m_pseudo;
@@ -130,6 +124,4 @@ public:
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/script/lua_api/l_rollback.h b/src/script/lua_api/l_rollback.h
new file mode 100644
index 000000000..86992a47e
--- /dev/null
+++ b/src/script/lua_api/l_rollback.h
@@ -0,0 +1,37 @@
+/*
+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_ROLLBACK_H_
+#define L_ROLLBACK_H_
+
+#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
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 @@ private:
// 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 @@ private:
// 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 @@ public:
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
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_ */