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