From: Kahrl Date: Sun, 11 Aug 2013 02:09:45 +0000 (+0200) Subject: Omnicleanup: header cleanup, add ModApiUtil shared between game and mainmenu X-Git-Url: http://81.2.79.47:8989/gitweb/?a=commitdiff_plain;h=4e1f50035e860a00636ca5d804c267119df99601;p=zefram%2Fminetest%2Fminetest_engine.git Omnicleanup: header cleanup, add ModApiUtil shared between game and mainmenu --- diff --git a/builtin/mainmenu.lua b/builtin/mainmenu.lua index e0ab82eb..926f3f2d 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 eefcc68a..59e70581 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 164d7876..3812f11f 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 b1732fa0..96f075e7 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 a1fcdd96..18cdaa72 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 f4d721a5..46880fc7 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 #define ACTIVEOBJECT_TYPE_INVALID 0 diff --git a/src/ban.cpp b/src/ban.cpp index 25d7f4cc..5bb470a6 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 #include #include "strfnd.h" +#include "util/string.h" #include "log.h" #include "filesys.h" diff --git a/src/chat.cpp b/src/chat.cpp index 3102e194..0bd5c167 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 +#include "strfnd.h" #include #include #include "util/string.h" diff --git a/src/chat.h b/src/chat.h index 19b48456..e39d97ec 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 #include #include diff --git a/src/client.cpp b/src/client.cpp index f9908ad2..ecbb32dd 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 +#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 fc26f317..9146941e 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 +#include #include #include #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::iterator n = m_packets.find(command); + if(n == m_packets.end()) + { + m_packets[command] = 1; + } + else + { + n->second++; + } + } + + void clear() + { + for(std::map::iterator + i = m_packets.begin(); + i != m_packets.end(); ++i) + { + i->second = 0; + } + } + + void print(std::ostream &o) + { + for(std::map::iterator + i = m_packets.begin(); + i != m_packets.end(); ++i) + { + o<<"cmd "<first + <<" count "<second + < 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.cpp b/src/clientserver.cpp deleted file mode 100644 index 591a9554..00000000 --- a/src/clientserver.cpp +++ /dev/null @@ -1,31 +0,0 @@ -/* -Minetest -Copyright (C) 2010-2013 celeron55, Perttu Ahola - -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 "clientserver.h" -#include "util/serialize.h" - -SharedBuffer makePacket_TOCLIENT_TIME_OF_DAY(u16 time, float time_speed) -{ - SharedBuffer data(2+2+4); - writeU16(&data[0], TOCLIENT_TIME_OF_DAY); - writeU16(&data[2], time); - writeF1000(&data[4], time_speed); - return data; -} - diff --git a/src/clientserver.h b/src/clientserver.h index ebfe7f3c..fb442cfc 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 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 e68557cc..a1d56484 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 e9d9f884..8c478ac6 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 57e4637d..6e2d438f 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 a9a8cc60..f504924f 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 907649b5..0b08bc6a 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 + +class NodeMetadataList; +class NodeTimerList; +class IGameDef; /* Legacy nodemeta definitions diff --git a/src/content_sao.cpp b/src/content_sao.cpp index f3ccd6db..347e8892 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<luaentity_GetStaticdata(m_id); + std::string state = m_env->getScriptIface()-> + luaentity_GetStaticdata(m_id); os<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 c79408f9..5c7c3a46 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 &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 craftMakeMultiset(const std::vector &names) -{ - std::multiset set; - for(std::vector::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 2e4992a7..6bdd1bce 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 #include #include +#include +#include +#include /* Debug output */ +#define DEBUGSTREAM_COUNT 2 + FILE *g_debugstreams[DEBUGSTREAM_COUNT] = {stderr, NULL}; +#define DEBUGPRINT(...)\ +{\ + for(int i=0; i -#include -#include #include -#include "irrlichttypes.h" -#include -#include "threads.h" +#include #include "gettime.h" -#include "exceptions.h" -#include -#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 #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 g_debug_stacks; -extern JMutex g_debug_stacks_mutex; - extern void debug_stacks_init(); extern void debug_stacks_print_to(std::ostream &os); extern void debug_stacks_print(); +struct DebugStack; class DebugStacker { public: @@ -193,57 +119,6 @@ private: DEBUG_STACK_TEXT_SIZE, __VA_ARGS__);\ DebugStacker __debug_stacker(__buf); -/* - Packet counter -*/ - -class PacketCounter -{ -public: - PacketCounter() - { - } - - void add(u16 command) - { - std::map::iterator n = m_packets.find(command); - if(n == m_packets.end()) - { - m_packets[command] = 1; - } - else - { - n->second++; - } - } - - void clear() - { - for(std::map::iterator - i = m_packets.begin(); - i != m_packets.end(); ++i) - { - i->second = 0; - } - } - - void print(std::ostream &o) - { - for(std::map::iterator - i = m_packets.begin(); - i != m_packets.end(); ++i) - { - o<<"cmd "<first - <<" count "<second - < 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 38d278ef..a0adf159 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 f9776371..a81ff7d9 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 #include -#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 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::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 ee95c348..458a366f 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 -#include -#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 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 eacc2a00..86c98f2c 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 -#include -#include #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 Environment::getPlayers(bool ignore_disconnected) return newlist; } -void Environment::printPlayers(std::ostream &o) -{ - o<<"Players in environment:"<::iterator i = m_players.begin(); - i != m_players.end(); i++) - { - Player *player = *i; - o<<"Player peer_id="<peer_id<getBool("enable_shaders"); @@ -320,7 +307,8 @@ void ActiveBlockList::update(std::list &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 b59ce83c..597ad5ff 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 #include -#include "irrlichttypes_extrabloated.h" -#include "player.h" -#include +#include +#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 getPlayers(); std::list 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 m_active_objects; // Outgoing network message buffer for active objects - Queue m_active_object_messages; + std::list 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 m_active_objects; std::list m_simple_objects; - Queue m_client_event_queue; + std::list 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 458fb50b..085b4241 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 23df1d7d..c4de6cf8 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 #include #include +#include bool FileCache::loadByPath(const std::string &path, std::ostream &os) { diff --git a/src/filesys.cpp b/src/filesys.cpp index a1795c8e..eda36c83 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 #include #include #include -#include #include #include "log.h" diff --git a/src/game.cpp b/src/game.cpp index 7954c8d8..650b5e2f 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"<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 a2c1fc09..1c831c53 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 b62c1a54..37f570ac 100644 --- a/src/guiEngine.cpp +++ b/src/guiEngine.cpp @@ -17,14 +17,10 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -extern "C" { -#include "lua.h" -#include "lauxlib.h" -#include "lualib.h" -} - -#include "irrlicht.h" +#include "guiEngine.h" +#include "scripting_mainmenu.h" +#include "config.h" #include "porting.h" #include "filesys.h" #include "main.h" @@ -33,30 +29,13 @@ extern "C" { #include "sound.h" #include "sound_openal.h" -#include "guiEngine.h" +#include +#include #if USE_CURL #include #endif -/******************************************************************************/ -int menuscript_ErrorHandler(lua_State *L) { - lua_getfield(L, LUA_GLOBALSINDEX, "debug"); - if (!lua_istable(L, -1)) { - lua_pop(L, 1); - return 1; - } - lua_getfield(L, -1, "traceback"); - if (!lua_isfunction(L, -1)) { - lua_pop(L, 2); - return 1; - } - lua_pushvalue(L, 1); - lua_pushinteger(L, 2); - lua_call(L, 2, 1); - return 1; -} - /******************************************************************************/ TextDestGuiEngine::TextDestGuiEngine(GUIEngine* engine) { @@ -66,13 +45,33 @@ TextDestGuiEngine::TextDestGuiEngine(GUIEngine* engine) /******************************************************************************/ void TextDestGuiEngine::gotText(std::map 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 &dst_paths, + std::set &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"<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 ==========="<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 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::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"<setText(L""); @@ -565,17 +506,6 @@ bool GUIEngine::downloadFile(std::string url,std::string target) { return false; } -/******************************************************************************/ -void GUIEngine::scriptError(const char *fmt, ...) -{ - va_list argp; - va_start(argp, fmt); - char buf[10000]; - vsnprintf(buf, 10000, fmt, argp); - va_end(argp); - errorstream<<"MAINMENU ERROR: "< m_fetched; public: - void fetchSounds(const std::string &name, std::set &dst_paths, - std::set &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 &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 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 0f09eaf5..f09996ef 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 #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 &rect, - const core::rect *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(core::position2d(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 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 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 rect2( - /*rect.UpperLeftCorner, - core::dimension2d(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 116f7b95..84124afc 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 &rect, - const core::rect *clip, - IGameDef *gamedef); - class GUIFormSpecMenu : public GUIModalMenu { struct ItemSpec diff --git a/src/guiLuaApi.cpp b/src/guiLuaApi.cpp deleted file mode 100644 index 5d3e9dc1..00000000 --- a/src/guiLuaApi.cpp +++ /dev/null @@ -1,1128 +0,0 @@ -/* -Minetest -Copyright (C) 2013 sapier - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation; either version 2.1 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along -with this program; if not, write to the Free Software Foundation, Inc., -51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -extern "C" { -#include "lua.h" -#include "lauxlib.h" -#include "lualib.h" -} -#include "porting.h" -#include "guiMainMenu.h" -#include "subgame.h" -#include "guiKeyChangeMenu.h" -#include "guiFileSelectMenu.h" -#include "main.h" -#include "settings.h" -#include "filesys.h" -#include "convert_json.h" -#include "sound.h" - - -#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; -} - -/******************************************************************************/ -std::string guiLuaApi::getTextData(lua_State *L, std::string name) -{ - lua_getglobal(L, "gamedata"); - - lua_getfield(L, -1, name.c_str()); - - if(lua_isnil(L, -1)) - return ""; - - return luaL_checkstring(L, -1); -} - -/******************************************************************************/ -int guiLuaApi::getIntegerData(lua_State *L, std::string name,bool& valid) -{ - lua_getglobal(L, "gamedata"); - - lua_getfield(L, -1, name.c_str()); - - if(lua_isnil(L, -1)) { - valid = false; - return -1; - } - - valid = true; - return luaL_checkinteger(L, -1); -} - -/******************************************************************************/ -int guiLuaApi::getBoolData(lua_State *L, std::string name,bool& valid) -{ - lua_getglobal(L, "gamedata"); - - lua_getfield(L, -1, name.c_str()); - - if(lua_isnil(L, -1)) { - valid = false; - return false; - } - - valid = true; - return lua_toboolean(L, -1); -} - -/******************************************************************************/ -int guiLuaApi::l_update_formspec(lua_State *L) -{ - GUIEngine* engine = get_engine(L); - assert(engine != 0); - - if (engine->m_startgame) - return 0; - - //read formspec - std::string formspec(luaL_checkstring(L, 1)); - - if (engine->m_formspecgui != 0) { - engine->m_formspecgui->setForm(formspec); - } - - return 0; -} - -/******************************************************************************/ -int guiLuaApi::l_start(lua_State *L) -{ - GUIEngine* engine = get_engine(L); - assert(engine != 0); - - //update c++ gamedata from lua table - - bool valid = false; - - - engine->m_data->selected_world = getIntegerData(L, "selected_world",valid) -1; - engine->m_data->simple_singleplayer_mode = getBoolData(L,"singleplayer",valid); - engine->m_data->name = getTextData(L,"playername"); - engine->m_data->password = getTextData(L,"password"); - engine->m_data->address = getTextData(L,"address"); - engine->m_data->port = getTextData(L,"port"); - engine->m_data->serverdescription = getTextData(L,"serverdescription"); - engine->m_data->servername = getTextData(L,"servername"); - - //close menu next time - engine->m_startgame = true; - return 0; -} - -/******************************************************************************/ -int guiLuaApi::l_close(lua_State *L) -{ - GUIEngine* engine = get_engine(L); - assert(engine != 0); - - engine->m_data->kill = true; - - //close menu next time - engine->m_startgame = true; - engine->m_menu->quitMenu(); - return 0; -} - -/******************************************************************************/ -int guiLuaApi::l_set_background(lua_State *L) -{ - GUIEngine* engine = get_engine(L); - assert(engine != 0); - - std::string backgroundlevel(luaL_checkstring(L, 1)); - std::string texturename(luaL_checkstring(L, 2)); - - bool retval = false; - - if (backgroundlevel == "background") { - retval |= engine->setTexture(TEX_LAYER_BACKGROUND,texturename); - } - - if (backgroundlevel == "overlay") { - retval |= engine->setTexture(TEX_LAYER_OVERLAY,texturename); - } - - if (backgroundlevel == "header") { - retval |= engine->setTexture(TEX_LAYER_HEADER,texturename); - } - - if (backgroundlevel == "footer") { - retval |= engine->setTexture(TEX_LAYER_FOOTER,texturename); - } - - lua_pushboolean(L,retval); - return 1; -} - -/******************************************************************************/ -int guiLuaApi::l_set_clouds(lua_State *L) -{ - GUIEngine* engine = get_engine(L); - assert(engine != 0); - - bool value = lua_toboolean(L,1); - - engine->m_clouds_enabled = value; - - return 0; -} - -/******************************************************************************/ -int guiLuaApi::l_get_textlist_index(lua_State *L) -{ - GUIEngine* engine = get_engine(L); - assert(engine != 0); - - std::string listboxname(luaL_checkstring(L, 1)); - - int selection = engine->m_menu->getListboxIndex(listboxname); - - if (selection >= 0) - selection++; - - lua_pushinteger(L, selection); - return 1; -} - -/******************************************************************************/ -int guiLuaApi::l_get_worlds(lua_State *L) -{ - GUIEngine* engine = get_engine(L); - assert(engine != 0); - - std::vector worlds = getAvailableWorlds(); - - lua_newtable(L); - int top = lua_gettop(L); - unsigned int index = 1; - - for (unsigned int i = 0; i < worlds.size(); i++) - { - lua_pushnumber(L,index); - - lua_newtable(L); - int top_lvl2 = lua_gettop(L); - - lua_pushstring(L,"path"); - lua_pushstring(L,worlds[i].path.c_str()); - lua_settable(L, top_lvl2); - - lua_pushstring(L,"name"); - lua_pushstring(L,worlds[i].name.c_str()); - lua_settable(L, top_lvl2); - - lua_pushstring(L,"gameid"); - lua_pushstring(L,worlds[i].gameid.c_str()); - lua_settable(L, top_lvl2); - - lua_settable(L, top); - index++; - } - return 1; -} - -/******************************************************************************/ -int guiLuaApi::l_get_games(lua_State *L) -{ - GUIEngine* engine = get_engine(L); - assert(engine != 0); - - std::vector games = getAvailableGames(); - - lua_newtable(L); - int top = lua_gettop(L); - unsigned int index = 1; - - for (unsigned int i = 0; i < games.size(); i++) - { - lua_pushnumber(L,index); - lua_newtable(L); - int top_lvl2 = lua_gettop(L); - - lua_pushstring(L,"id"); - lua_pushstring(L,games[i].id.c_str()); - lua_settable(L, top_lvl2); - - lua_pushstring(L,"path"); - lua_pushstring(L,games[i].path.c_str()); - lua_settable(L, top_lvl2); - - lua_pushstring(L,"gamemods_path"); - lua_pushstring(L,games[i].gamemods_path.c_str()); - lua_settable(L, top_lvl2); - - lua_pushstring(L,"name"); - lua_pushstring(L,games[i].name.c_str()); - lua_settable(L, top_lvl2); - - lua_pushstring(L,"menuicon_path"); - lua_pushstring(L,games[i].menuicon_path.c_str()); - lua_settable(L, top_lvl2); - - lua_pushstring(L,"addon_mods_paths"); - lua_newtable(L); - int table2 = lua_gettop(L); - int internal_index=1; - for (std::set::iterator iter = games[i].addon_mods_paths.begin(); - iter != games[i].addon_mods_paths.end(); iter++) { - lua_pushnumber(L,internal_index); - lua_pushstring(L,(*iter).c_str()); - lua_settable(L, table2); - internal_index++; - } - lua_settable(L, top_lvl2); - lua_settable(L, top); - index++; - } - return 1; -} -/******************************************************************************/ -int guiLuaApi::l_get_modstore_details(lua_State *L) -{ - const char *modid = luaL_checkstring(L, 1); - - if (modid != 0) { - Json::Value details; - std::string url = ""; - try{ - url = g_settings->get("modstore_details_url"); - } - catch(SettingNotFoundException &e) { - lua_pushnil(L); - return 1; - } - - size_t idpos = url.find("*"); - url.erase(idpos,1); - url.insert(idpos,modid); - - details = getModstoreUrl(url); - - ModStoreModDetails current_mod = readModStoreModDetails(details); - - if ( current_mod.valid) { - lua_newtable(L); - int top = lua_gettop(L); - - lua_pushstring(L,"id"); - lua_pushnumber(L,current_mod.id); - lua_settable(L, top); - - lua_pushstring(L,"title"); - lua_pushstring(L,current_mod.title.c_str()); - lua_settable(L, top); - - lua_pushstring(L,"basename"); - lua_pushstring(L,current_mod.basename.c_str()); - lua_settable(L, top); - - lua_pushstring(L,"description"); - lua_pushstring(L,current_mod.description.c_str()); - lua_settable(L, top); - - lua_pushstring(L,"author"); - lua_pushstring(L,current_mod.author.username.c_str()); - lua_settable(L, top); - - lua_pushstring(L,"download_url"); - lua_pushstring(L,current_mod.versions[0].file.c_str()); - lua_settable(L, top); - - lua_pushstring(L,"screenshot_url"); - lua_pushstring(L,current_mod.titlepic.file.c_str()); - lua_settable(L, top); - - lua_pushstring(L,"license"); - lua_pushstring(L,current_mod.license.shortinfo.c_str()); - lua_settable(L, top); - - lua_pushstring(L,"rating"); - lua_pushnumber(L,current_mod.rating); - lua_settable(L, top); - - //TODO depends - - //TODO softdepends - return 1; - } - } - return 0; -} - -/******************************************************************************/ -int guiLuaApi::l_get_modstore_list(lua_State *L) -{ - GUIEngine* engine = get_engine(L); - assert(engine != 0); - - std::string listtype = "local"; - - if (!lua_isnone(L,1)) { - listtype = luaL_checkstring(L,1); - } - Json::Value mods; - std::string url = ""; - try{ - url = g_settings->get("modstore_listmods_url"); - } - catch(SettingNotFoundException &e) { - lua_pushnil(L); - return 1; - } - - mods = getModstoreUrl(url); - - std::vector moddata = readModStoreList(mods); - - lua_newtable(L); - int top = lua_gettop(L); - unsigned int index = 1; - - for (unsigned int i = 0; i < moddata.size(); i++) - { - if (moddata[i].valid) { - lua_pushnumber(L,index); - lua_newtable(L); - - int top_lvl2 = lua_gettop(L); - - lua_pushstring(L,"id"); - lua_pushnumber(L,moddata[i].id); - lua_settable(L, top_lvl2); - - lua_pushstring(L,"title"); - lua_pushstring(L,moddata[i].title.c_str()); - lua_settable(L, top_lvl2); - - lua_pushstring(L,"basename"); - lua_pushstring(L,moddata[i].basename.c_str()); - lua_settable(L, top_lvl2); - - lua_settable(L, top); - index++; - } - } - return 1; -} - -/******************************************************************************/ -int guiLuaApi::l_get_favorites(lua_State *L) -{ - GUIEngine* engine = get_engine(L); - assert(engine != 0); - - std::string listtype = "local"; - - if (!lua_isnone(L,1)) { - listtype = luaL_checkstring(L,1); - } - - std::vector servers; -#if USE_CURL - if(listtype == "online") { - servers = ServerList::getOnline(); - } else { - servers = ServerList::getLocal(); - } -#else - servers = ServerList::getLocal(); -#endif - - lua_newtable(L); - int top = lua_gettop(L); - unsigned int index = 1; - - for (unsigned int i = 0; i < servers.size(); i++) - { - lua_pushnumber(L,index); - - lua_newtable(L); - int top_lvl2 = lua_gettop(L); - - if (servers[i]["clients"].asString().size()) { - - const char* clients_raw = servers[i]["clients"].asString().c_str(); - char* endptr = 0; - int numbervalue = strtol(clients_raw,&endptr,10); - - if ((*clients_raw != 0) && (*endptr == 0)) { - lua_pushstring(L,"clients"); - lua_pushnumber(L,numbervalue); - lua_settable(L, top_lvl2); - } - } - - if (servers[i]["clients_max"].asString().size()) { - - const char* clients_max_raw = servers[i]["clients_max"].asString().c_str(); - char* endptr = 0; - int numbervalue = strtol(clients_max_raw,&endptr,10); - - if ((*clients_max_raw != 0) && (*endptr == 0)) { - lua_pushstring(L,"clients_max"); - lua_pushnumber(L,numbervalue); - lua_settable(L, top_lvl2); - } - } - - if (servers[i]["version"].asString().size()) { - lua_pushstring(L,"version"); - lua_pushstring(L,servers[i]["version"].asString().c_str()); - lua_settable(L, top_lvl2); - } - - if (servers[i]["password"].asString().size()) { - lua_pushstring(L,"password"); - lua_pushboolean(L,true); - lua_settable(L, top_lvl2); - } - - if (servers[i]["creative"].asString().size()) { - lua_pushstring(L,"creative"); - lua_pushboolean(L,true); - lua_settable(L, top_lvl2); - } - - if (servers[i]["damage"].asString().size()) { - lua_pushstring(L,"damage"); - lua_pushboolean(L,true); - lua_settable(L, top_lvl2); - } - - if (servers[i]["pvp"].asString().size()) { - lua_pushstring(L,"pvp"); - lua_pushboolean(L,true); - lua_settable(L, top_lvl2); - } - - if (servers[i]["description"].asString().size()) { - lua_pushstring(L,"description"); - lua_pushstring(L,servers[i]["description"].asString().c_str()); - lua_settable(L, top_lvl2); - } - - if (servers[i]["name"].asString().size()) { - lua_pushstring(L,"name"); - lua_pushstring(L,servers[i]["name"].asString().c_str()); - lua_settable(L, top_lvl2); - } - - if (servers[i]["address"].asString().size()) { - lua_pushstring(L,"address"); - lua_pushstring(L,servers[i]["address"].asString().c_str()); - lua_settable(L, top_lvl2); - } - - if (servers[i]["port"].asString().size()) { - lua_pushstring(L,"port"); - lua_pushstring(L,servers[i]["port"].asString().c_str()); - lua_settable(L, top_lvl2); - } - - lua_settable(L, top); - index++; - } - return 1; -} - -/******************************************************************************/ -int guiLuaApi::l_delete_favorite(lua_State *L) -{ - GUIEngine* engine = get_engine(L); - assert(engine != 0); - - std::vector servers; - - std::string listtype = "local"; - - if (!lua_isnone(L,2)) { - listtype = luaL_checkstring(L,2); - } - - if ((listtype != "local") && - (listtype != "online")) - return 0; - -#if USE_CURL - if(listtype == "online") { - servers = ServerList::getOnline(); - } else { - servers = ServerList::getLocal(); - } -#else - servers = ServerList::getLocal(); -#endif - - int fav_idx = luaL_checkinteger(L,1) -1; - - if ((fav_idx >= 0) && - (fav_idx < (int) servers.size())) { - - ServerList::deleteEntry(servers[fav_idx]); - } - - return 0; -} - -/******************************************************************************/ -int guiLuaApi::l_show_keys_menu(lua_State *L) -{ - GUIEngine* engine = get_engine(L); - assert(engine != 0); - - GUIKeyChangeMenu *kmenu - = new GUIKeyChangeMenu( engine->m_device->getGUIEnvironment(), - engine->m_parent, - -1, - engine->m_menumanager); - kmenu->drop(); - return 0; -} - -/******************************************************************************/ -int guiLuaApi::l_setting_set(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); - assert(engine != 0); - - const char *name = luaL_checkstring(L, 1); - int gameidx = luaL_checkinteger(L,2) -1; - - std::string path = porting::path_user + DIR_DELIM - "worlds" + DIR_DELIM - + name; - - std::vector games = getAvailableGames(); - - if ((gameidx >= 0) && - (gameidx < (int) games.size())) { - - // Create world if it doesn't exist - if(!initializeWorld(path, games[gameidx].id)){ - lua_pushstring(L, "Failed to initialize world"); - - } - else { - lua_pushnil(L); - } - } - else { - lua_pushstring(L, "Invalid game index"); - } - return 1; -} - -/******************************************************************************/ -int guiLuaApi::l_delete_world(lua_State *L) -{ - GUIEngine* engine = get_engine(L); - assert(engine != 0); - - int worldidx = luaL_checkinteger(L,1) -1; - - std::vector worlds = getAvailableWorlds(); - - if ((worldidx >= 0) && - (worldidx < (int) worlds.size())) { - - WorldSpec spec = worlds[worldidx]; - - std::vector paths; - paths.push_back(spec.path); - fs::GetRecursiveSubPaths(spec.path, paths); - - // Delete files - if (!fs::DeletePaths(paths)) { - lua_pushstring(L, "Failed to delete world"); - } - else { - lua_pushnil(L); - } - } - else { - lua_pushstring(L, "Invalid world index"); - } - return 1; -} - -/******************************************************************************/ -int guiLuaApi::l_set_topleft_text(lua_State *L) -{ - GUIEngine* engine = get_engine(L); - assert(engine != 0); - - std::string text = ""; - - if (!lua_isnone(L,1) && !lua_isnil(L,1)) - text = luaL_checkstring(L, 1); - - engine->setTopleftText(text); - return 0; -} - -/******************************************************************************/ -int guiLuaApi::l_get_modpath(lua_State *L) -{ - std::string modpath - = fs::RemoveRelativePathComponents(porting::path_user + DIR_DELIM + "mods" + DIR_DELIM); - lua_pushstring(L, modpath.c_str()); - return 1; -} - -/******************************************************************************/ -int guiLuaApi::l_get_gamepath(lua_State *L) -{ - std::string gamepath - = fs::RemoveRelativePathComponents(porting::path_user + DIR_DELIM + "games" + DIR_DELIM); - lua_pushstring(L, gamepath.c_str()); - return 1; -} - -/******************************************************************************/ -int guiLuaApi::l_get_texturepath(lua_State *L) -{ - std::string gamepath - = fs::RemoveRelativePathComponents(porting::path_user + DIR_DELIM + "textures"); - lua_pushstring(L, gamepath.c_str()); - return 1; -} - -/******************************************************************************/ -int guiLuaApi::l_get_dirlist(lua_State *L) { - const char *path = luaL_checkstring(L, 1); - bool dironly = lua_toboolean(L, 2); - - std::vector dirlist = fs::GetDirListing(path); - - unsigned int index = 1; - lua_newtable(L); - int table = lua_gettop(L); - - for (unsigned int i=0;i< dirlist.size(); i++) { - if ((dirlist[i].dir) || (dironly == false)) { - lua_pushnumber(L,index); - lua_pushstring(L,dirlist[i].name.c_str()); - lua_settable(L, table); - index++; - } - } - - return 1; -} - -/******************************************************************************/ -int guiLuaApi::l_create_dir(lua_State *L) { - const char *path = luaL_checkstring(L, 1); - - if (guiLuaApi::isMinetestPath(path)) { - lua_pushboolean(L,fs::CreateAllDirs(path)); - return 1; - } - lua_pushboolean(L,false); - return 1; -} - -/******************************************************************************/ -int guiLuaApi::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)) { - lua_pushboolean(L,fs::RecursiveDelete(absolute_path)); - return 1; - } - lua_pushboolean(L,false); - return 1; -} - -/******************************************************************************/ -int guiLuaApi::l_copy_dir(lua_State *L) { - const char *source = luaL_checkstring(L, 1); - const char *destination = luaL_checkstring(L, 2); - - bool keep_source = true; - - if ((!lua_isnone(L,3)) && - (!lua_isnil(L,3))) { - keep_source = lua_toboolean(L,3); - } - - std::string absolute_destination = fs::RemoveRelativePathComponents(destination); - std::string absolute_source = fs::RemoveRelativePathComponents(source); - - if ((guiLuaApi::isMinetestPath(absolute_source)) && - (guiLuaApi::isMinetestPath(absolute_destination))) { - bool retval = fs::CopyDir(absolute_source,absolute_destination); - - if (retval && (!keep_source)) { - - retval &= fs::RecursiveDelete(absolute_source); - } - lua_pushboolean(L,retval); - return 1; - } - lua_pushboolean(L,false); - return 1; -} - -/******************************************************************************/ -int guiLuaApi::l_extract_zip(lua_State *L) { - - GUIEngine* engine = get_engine(L); - assert(engine != 0); - - const char *zipfile = luaL_checkstring(L, 1); - const char *destination = luaL_checkstring(L, 2); - - std::string absolute_destination = fs::RemoveRelativePathComponents(destination); - - if (guiLuaApi::isMinetestPath(absolute_destination)) { - fs::CreateAllDirs(absolute_destination); - - io::IFileSystem* fs = engine->m_device->getFileSystem(); - - fs->addFileArchive(zipfile,true,false,io::EFAT_ZIP); - - assert(fs->getFileArchiveCount() > 0); - - /**********************************************************************/ - /* WARNING this is not threadsafe!! */ - /**********************************************************************/ - io::IFileArchive* opened_zip = - fs->getFileArchive(fs->getFileArchiveCount()-1); - - const io::IFileList* files_in_zip = opened_zip->getFileList(); - - unsigned int number_of_files = files_in_zip->getFileCount(); - - for (unsigned int i=0; i < number_of_files; i++) { - std::string fullpath = destination; - fullpath += DIR_DELIM; - fullpath += files_in_zip->getFullFileName(i).c_str(); - - if (files_in_zip->isDirectory(i)) { - if (! fs::CreateAllDirs(fullpath) ) { - fs->removeFileArchive(fs->getFileArchiveCount()-1); - lua_pushboolean(L,false); - return 1; - } - } - else { - io::IReadFile* toread = opened_zip->createAndOpenFile(i); - - FILE *targetfile = fopen(fullpath.c_str(),"wb"); - - if (targetfile == NULL) { - fs->removeFileArchive(fs->getFileArchiveCount()-1); - lua_pushboolean(L,false); - return 1; - } - - char read_buffer[1024]; - unsigned int total_read = 0; - - while (total_read < toread->getSize()) { - - unsigned int bytes_read = - toread->read(read_buffer,sizeof(read_buffer)); - unsigned int bytes_written; - if ((bytes_read < 0 ) || - (bytes_written = fwrite(read_buffer, 1, bytes_read, targetfile) != bytes_read)) - { - fclose(targetfile); - fs->removeFileArchive(fs->getFileArchiveCount()-1); - lua_pushboolean(L,false); - return 1; - } - total_read += bytes_read; - } - - fclose(targetfile); - } - - } - - fs->removeFileArchive(fs->getFileArchiveCount()-1); - lua_pushboolean(L,true); - return 1; - } - - lua_pushboolean(L,false); - return 1; -} - -/******************************************************************************/ -int guiLuaApi::l_get_scriptdir(lua_State *L) { - GUIEngine* engine = get_engine(L); - assert(engine != 0); - - lua_pushstring(L,engine->getScriptDir().c_str()); - return 1; -} - -/******************************************************************************/ -bool guiLuaApi::isMinetestPath(std::string path) { - - - if (fs::PathStartsWith(path,fs::TempPath())) - return true; - - /* games */ - if (fs::PathStartsWith(path,fs::RemoveRelativePathComponents(porting::path_share + DIR_DELIM + "games"))) - return true; - - /* mods */ - if (fs::PathStartsWith(path,fs::RemoveRelativePathComponents(porting::path_user + DIR_DELIM + "mods"))) - return true; - - /* worlds */ - if (fs::PathStartsWith(path,fs::RemoveRelativePathComponents(porting::path_user + DIR_DELIM + "worlds"))) - return true; - - - return false; -} - -/******************************************************************************/ -int guiLuaApi::l_show_file_open_dialog(lua_State *L) { - - GUIEngine* engine = get_engine(L); - assert(engine != 0); - - const char *formname= luaL_checkstring(L, 1); - const char *title = luaL_checkstring(L, 2); - - GUIFileSelectMenu* fileOpenMenu = - new GUIFileSelectMenu(engine->m_device->getGUIEnvironment(), - engine->m_parent, - -1, - engine->m_menumanager, - title, - formname); - fileOpenMenu->setTextDest(engine->m_buttonhandler); - fileOpenMenu->drop(); - return 0; -} - -/******************************************************************************/ -int guiLuaApi::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); - - 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); - } - bool looped = lua_toboolean(L, 2); - - u32 handle = engine->playSound(spec, looped); - - lua_pushinteger(L, handle); - - return 1; -} - -/******************************************************************************/ -int guiLuaApi::l_sound_stop(lua_State *L) { - GUIEngine* engine = get_engine(L); - - u32 handle = luaL_checkinteger(L, 1); - engine->stopSound(handle); - - return 1; -} - -/******************************************************************************/ -int guiLuaApi::l_download_file(lua_State *L) { - GUIEngine* engine = get_engine(L); - assert(engine != 0); - - const char *url = luaL_checkstring(L, 1); - const char *target = luaL_checkstring(L, 2); - - //check path - std::string absolute_destination = fs::RemoveRelativePathComponents(target); - - if (guiLuaApi::isMinetestPath(absolute_destination)) { - if (engine->downloadFile(url,absolute_destination)) { - lua_pushboolean(L,true); - return 1; - } - } - lua_pushboolean(L,false); - return 1; -} diff --git a/src/guiLuaApi.h b/src/guiLuaApi.h deleted file mode 100644 index 9555f00c..00000000 --- a/src/guiLuaApi.h +++ /dev/null @@ -1,189 +0,0 @@ -/* -Minetest -Copyright (C) 2013 sapier - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation; either version 2.1 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along -with this program; if not, write to the Free Software Foundation, Inc., -51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#ifndef GUILUAAPI_H_ -#define GUILUAAPI_H_ - -/******************************************************************************/ -/* Includes */ -/******************************************************************************/ -#include "serverlist.h" - -/******************************************************************************/ -/* Typedefs and macros */ -/******************************************************************************/ -typedef int (*lua_CFunction) (lua_State *L); - -/******************************************************************************/ -/* forward declarations */ -/******************************************************************************/ -class GUIEngine; - - -/******************************************************************************/ -/* declarations */ -/******************************************************************************/ - -/** 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() {} - -private: - /** - * read a text variable from gamedata table within lua stack - * @param L stack to read variable from - * @param name name of variable to read - * @return string value of requested variable - */ - static std::string getTextData(lua_State *L, std::string name); - - /** - * read a integer variable from gamedata table within lua stack - * @param L stack to read variable from - * @param name name of variable to read - * @return integer value of requested variable - */ - static int getIntegerData(lua_State *L, std::string name,bool& valid); - - /** - * read a bool variable from gamedata table within lua stack - * @param L stack to read variable from - * @param name name of variable to read - * @return bool value of requested variable - */ - static int getBoolData(lua_State *L, std::string name,bool& valid); - - /** - * 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 - */ - static bool isMinetestPath(std::string path); - - //api calls - - static int l_start(lua_State *L); - - static int l_close(lua_State *L); - - static int l_create_world(lua_State *L); - - static int l_delete_world(lua_State *L); - - static int l_get_worlds(lua_State *L); - - static int l_get_games(lua_State *L); - - static int l_get_favorites(lua_State *L); - - static int l_delete_favorite(lua_State *L); - - static int l_get_version(lua_State *L); - - static int l_sound_play(lua_State *L); - - static int l_sound_stop(lua_State *L); - - //gui - - static int l_show_keys_menu(lua_State *L); - - static int l_show_file_open_dialog(lua_State *L); - - static int l_set_topleft_text(lua_State *L); - - static int l_set_clouds(lua_State *L); - - static int l_get_textlist_index(lua_State *L); - - static int l_set_background(lua_State *L); - - static int l_update_formspec(lua_State *L); - - //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); - - static int l_get_modpath(lua_State *L); - - static int l_get_gamepath(lua_State *L); - - static int l_get_texturepath(lua_State *L); - - static int l_get_dirlist(lua_State *L); - - static int l_create_dir(lua_State *L); - - static int l_delete_dir(lua_State *L); - - static int l_copy_dir(lua_State *L); - - static int l_extract_zip(lua_State *L); - - static int l_get_modstore_details(lua_State *L); - - static int l_get_modstore_list(lua_State *L); - - static int l_download_file(lua_State *L); - - -}; - -#endif diff --git a/src/guiVolumeChange.cpp b/src/guiVolumeChange.cpp index c272b132..2f462b77 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 #include #include "main.h" +#include "settings.h" #include "gettext.h" diff --git a/src/hud.cpp b/src/hud.cpp index f1a4ab52..58a6c7cf 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 - -#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 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 &rect, + const core::rect *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(core::position2d(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 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 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 rect2( + /*rect.UpperLeftCorner, + core::dimension2d(rect.getWidth(), 15)*/ + rect.LowerRightCorner - sdim, + sdim + ); + + video::SColor bgcolor(128,0,0,0); + driver->draw2DRectangle(bgcolor, rect2, clip); + + video::SColor color(255,255,255,255); + font->draw(text.c_str(), rect2, color, false, false, clip); + } +} + diff --git a/src/hud.h b/src/hud.h index c7289f7c..27e23929 100644 --- a/src/hud.h +++ b/src/hud.h @@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #define HUD_HEADER #include "irrlichttypes_extrabloated.h" +#include #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 #include +#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 &hilightboxes); }; +void drawItemStack(video::IVideoDriver *driver, + gui::IGUIFont *font, + const ItemStack &item, + const core::rect &rect, + const core::rect *clip, + IGameDef *gamedef); + + #endif #endif diff --git a/src/inventory.h b/src/inventory.h index 1a66a13a..cd592a17 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 -#include #include #include -#include "irrlichttypes_bloated.h" +#include "irrlichttypes.h" #include "debug.h" #include "itemdef.h" diff --git a/src/inventorymanager.cpp b/src/inventorymanager.cpp index 6187675d..c81f7a19 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 2ce19999..77aba350 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 -#include -#include #include #endif diff --git a/src/irrlichttypes_extrabloated.h b/src/irrlichttypes_extrabloated.h index a541b1a0..cd6cb1d2 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 69678064..f6ae8673 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 #include diff --git a/src/light.h b/src/light.h index e847e1ce..769ca31c 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 f495a6ba..7450593d 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[]) <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")<<" ["<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 df67a634..191b4188 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 + // 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 331aa48d..62ba85c4 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "filesys.h" #include "voxel.h" #include "porting.h" +#include "serialization.h" #include "nodemetadata.h" #include "settings.h" #include "log.h" @@ -33,9 +34,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "util/directiontables.h" #include "util/mathconstants.h" #include "rollback_interface.h" +#include "environment.h" #include "emerge.h" #include "mapgen_v6.h" -#include "mapgen_indev.h" #include "biome.h" #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")" diff --git a/src/map.h b/src/map.h index c90106ed..2f8bfaeb 100644 --- a/src/map.h +++ b/src/map.h @@ -20,9 +20,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #ifndef MAP_HEADER #define MAP_HEADER -#include -#include -#include #include #include #include @@ -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 617ba658..b8278b3b 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 #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 57612220..de49e613 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 -#include -#include #include #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 be65694a..301601b6 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 2e87c62b..040320f2 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 30787c6b..fd443995 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 78553775..3c620843 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 #include class INodeDefManager; diff --git a/src/mapsector.cpp b/src/mapsector.cpp index ebb050ec..0d40a659 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 4f2b3f31..dac4ee8d 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 -#include "irrlichttypes_bloated.h" -#include "exceptions.h" +#include "irrlichttypes.h" +#include "irr_v2d.h" #include #include #include diff --git a/src/mesh.cpp b/src/mesh.cpp index 14a194b8..5e5f9f86 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 #include #include #include diff --git a/src/mods.h b/src/mods.h index e10d4932..dedcc989 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 #include #include #include #include #include #include -#include #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 m_name_conflicts; }; diff --git a/src/nameidmapping.cpp b/src/nameidmapping.cpp index bcddb451..ebe65076 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 5af10d0f..ce2c9e6d 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 #include #include diff --git a/src/nodetimer.cpp b/src/nodetimer.cpp index db5fb08b..5fc652bb 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 bdbd3229..9fb56ede 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 #include diff --git a/src/noise.cpp b/src/noise.cpp index 5788a832..35057146 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 #include "noise.h" #include +#include // memset #include "debug.h" #include "util/numeric.h" diff --git a/src/object_properties.cpp b/src/object_properties.cpp index 7fad25cc..b6ad9f6d 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 -#include #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 bbda0736..43e1e287 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 diff --git a/src/pathfinder.h b/src/pathfinder.h index 7caf5844..dd41227f 100644 --- a/src/pathfinder.h +++ b/src/pathfinder.h @@ -25,10 +25,15 @@ with this program; if not, write to the Free Software Foundation, Inc., /******************************************************************************/ #include -#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 193de55a..584c00dd 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 7ddc40b3..12ea0dba 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 12c39089..ea7f31b1 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 271ad70c..e22a865c 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 #include #include #include #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 fe1d59d0..e1100682 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 e1a03b95..491c05a1 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 c8f7ef78..27e2fb4d 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 cb2b0e73..2e26adb7 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 fc00ce08..6d1dfe1d 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 42e9fb3e..5c16b88d 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: "<= nargs + 1); + lua_pushnil(L); + lua_insert(L, -(nargs + 1) - 1); + // Stack now looks like this: + // ... ... + + 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 dafde584..9a50b8e9 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 - -#include "lua_api/l_base.h" - extern "C" { -#include "lua.h" +#include +#include } -#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 7df86943..bc9f1cb9 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 6f5b51a4..b753eda1 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 e2e58635..e26d54ba 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 #include -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 \""<= nargs + 1); - lua_pushnil(L); - lua_insert(L, -(nargs + 1) - 1); - // Stack now looks like this: - // ...
... + 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<<"\""< +#include + +extern "C" { +#include +} #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 c494e823..cefa27cb 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 632b28f4..ef3a1ddd 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 00000000..10ee1a7d --- /dev/null +++ b/src/script/cpp_api/s_internal.h @@ -0,0 +1,63 @@ +/* +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola + +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 2402d198..09f26d80 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 6937ebbe..b4536ac6 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 00000000..af92c59a --- /dev/null +++ b/src/script/cpp_api/s_mainmenu.cpp @@ -0,0 +1,80 @@ +/* +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola + +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 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::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 00000000..53dcd37e --- /dev/null +++ b/src/script/cpp_api/s_mainmenu.h @@ -0,0 +1,49 @@ +/* +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola + +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 + +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 fields); +}; + +#endif /* S_MAINMENU_H_ */ diff --git a/src/script/cpp_api/s_node.cpp b/src/script/cpp_api/s_node.cpp index d0b0583c..92fd00a7 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 56cea8e5..e87464c6 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 0dbd5252..215a34d5 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 c0409a48..88221f48 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 + #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 00000000..d41805b7 --- /dev/null +++ b/src/script/cpp_api/s_server.cpp @@ -0,0 +1,151 @@ +/* +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola + +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 *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 &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 00000000..a63e3632 --- /dev/null +++ b/src/script/cpp_api/s_server.h @@ -0,0 +1,52 @@ +/* +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola + +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 + +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 *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 &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 b6d376b1..00000000 --- a/src/script/cpp_api/scriptapi.cpp +++ /dev/null @@ -1,291 +0,0 @@ -/* -Minetest -Copyright (C) 2013 celeron55, Perttu Ahola - -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 *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 &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 \""<::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 "<(); - - assert(ScriptApi::m_mod_api_modules != 0); - - ScriptApi::m_mod_api_modules->push_back(ptr); - - return true; -} - -std::vector* ScriptApi::m_mod_api_modules = 0; diff --git a/src/script/cpp_api/scriptapi.h b/src/script/cpp_api/scriptapi.h deleted file mode 100644 index bbd0bdda..00000000 --- a/src/script/cpp_api/scriptapi.h +++ /dev/null @@ -1,82 +0,0 @@ -/* -Minetest -Copyright (C) 2013 celeron55, Perttu Ahola - -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 SCRIPTAPI_H_ -#define SCRIPTAPI_H_ - -#include -#include -#include - -#include "cpp_api/s_base.h" -#include "cpp_api/s_player.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; - -/*****************************************************************************/ -/* Scriptapi <-> Core Interface */ -/*****************************************************************************/ - -class ScriptApi - : virtual public ScriptApiBase, - public ScriptApiPlayer, - public ScriptApiEnv, - public ScriptApiNode, - public ScriptApiDetached, - public ScriptApiEntity -{ -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(); - - /* auth */ - bool getAuth(const std::string &playername, - std::string *dst_password, std::set *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); - -private: - void getAuthHandler(); - void readPrivileges(int index,std::set &result); - - bool scriptLoad(const char *path); - - static std::vector* m_mod_api_modules; - -}; - -#endif /* SCRIPTAPI_H_ */ diff --git a/src/script/lua_api/CMakeLists.txt b/src/script/lua_api/CMakeLists.txt index f67cf688..d75c0433 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 b1766e6d..b8d673ee 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 f2e0d59a..71ebd215 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 +#include } -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 + static T* getScriptApi(lua_State *L) { + ScriptApiBase *scriptIface = getScriptApiBase(L); + T *scriptIfaceDowncast = dynamic_cast(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 a32fb9df..b0a47bfc 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 d8319199..54860877 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 #include -extern "C" { -#include -} - #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 &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 47bc9baf..dbaf6fb3 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(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(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(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(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 4122fd03..adb80a8a 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 -#include -} - -#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 00000000..14215ee5 --- /dev/null +++ b/src/script/lua_api/l_internal.h @@ -0,0 +1,43 @@ +/* +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola + +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 f57a4e8c..67b78bca 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 83e8039b..ed3249e5 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 -#include -} +#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 6182c037..a43b2858 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 bad517e0..7c2e1b09 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 -#include -} - -#include - -#include "itemdef.h" -#include "content_sao.h" -#include "util/pointedthing.h" -#include "inventory.h" - #include "lua_api/l_base.h" +#include "inventory.h" // ItemStack -class ModApiInventory; - -class LuaItemStack -{ +class LuaItemStack : public ModApiBase { private: ItemStack m_stack; @@ -134,18 +120,14 @@ public: }; -class ModApiItemMod - :virtual public ModApiBase -{ -public: - ModApiItemMod(); - - bool Initialize(lua_State *L, int top); - +class ModApiItemMod : public ModApiBase { +private: static int l_register_item_raw(lua_State *L); static int l_register_alias_raw(lua_State *L); static int l_get_content_id(lua_State *L); static int l_get_name_from_content_id(lua_State *L); +public: + static void Initialize(lua_State *L, int top); }; diff --git a/src/script/lua_api/l_mainmenu.cpp b/src/script/lua_api/l_mainmenu.cpp new file mode 100644 index 00000000..b3ae1f3f --- /dev/null +++ b/src/script/lua_api/l_mainmenu.cpp @@ -0,0 +1,1016 @@ +/* +Minetest +Copyright (C) 2013 sapier + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "lua_api/l_mainmenu.h" +#include "lua_api/l_internal.h" +#include "common/c_content.h" +#include "guiEngine.h" +#include "guiMainMenu.h" +#include "guiKeyChangeMenu.h" +#include "guiFileSelectMenu.h" +#include "subgame.h" +#include "porting.h" +#include "filesys.h" +#include "convert_json.h" +#include "serverlist.h" +#include "sound.h" +#include "settings.h" +#include "main.h" // for g_settings + +#include +#include + +/******************************************************************************/ +std::string ModApiMainMenu::getTextData(lua_State *L, std::string name) +{ + lua_getglobal(L, "gamedata"); + + lua_getfield(L, -1, name.c_str()); + + if(lua_isnil(L, -1)) + return ""; + + return luaL_checkstring(L, -1); +} + +/******************************************************************************/ +int ModApiMainMenu::getIntegerData(lua_State *L, std::string name,bool& valid) +{ + lua_getglobal(L, "gamedata"); + + lua_getfield(L, -1, name.c_str()); + + if(lua_isnil(L, -1)) { + valid = false; + return -1; + } + + valid = true; + return luaL_checkinteger(L, -1); +} + +/******************************************************************************/ +int ModApiMainMenu::getBoolData(lua_State *L, std::string name,bool& valid) +{ + lua_getglobal(L, "gamedata"); + + lua_getfield(L, -1, name.c_str()); + + if(lua_isnil(L, -1)) { + valid = false; + return false; + } + + valid = true; + return lua_toboolean(L, -1); +} + +/******************************************************************************/ +int ModApiMainMenu::l_update_formspec(lua_State *L) +{ + GUIEngine* engine = getGuiEngine(L); + assert(engine != 0); + + if (engine->m_startgame) + return 0; + + //read formspec + std::string formspec(luaL_checkstring(L, 1)); + + if (engine->m_formspecgui != 0) { + engine->m_formspecgui->setForm(formspec); + } + + return 0; +} + +/******************************************************************************/ +int ModApiMainMenu::l_start(lua_State *L) +{ + GUIEngine* engine = getGuiEngine(L); + assert(engine != 0); + + //update c++ gamedata from lua table + + bool valid = false; + + + engine->m_data->selected_world = getIntegerData(L, "selected_world",valid) -1; + engine->m_data->simple_singleplayer_mode = getBoolData(L,"singleplayer",valid); + engine->m_data->name = getTextData(L,"playername"); + engine->m_data->password = getTextData(L,"password"); + engine->m_data->address = getTextData(L,"address"); + engine->m_data->port = getTextData(L,"port"); + engine->m_data->serverdescription = getTextData(L,"serverdescription"); + engine->m_data->servername = getTextData(L,"servername"); + + //close menu next time + engine->m_startgame = true; + return 0; +} + +/******************************************************************************/ +int ModApiMainMenu::l_close(lua_State *L) +{ + GUIEngine* engine = getGuiEngine(L); + assert(engine != 0); + + engine->m_data->kill = true; + + //close menu next time + engine->m_startgame = true; + engine->m_menu->quitMenu(); + return 0; +} + +/******************************************************************************/ +int ModApiMainMenu::l_set_background(lua_State *L) +{ + GUIEngine* engine = getGuiEngine(L); + assert(engine != 0); + + std::string backgroundlevel(luaL_checkstring(L, 1)); + std::string texturename(luaL_checkstring(L, 2)); + + bool retval = false; + + if (backgroundlevel == "background") { + retval |= engine->setTexture(TEX_LAYER_BACKGROUND,texturename); + } + + if (backgroundlevel == "overlay") { + retval |= engine->setTexture(TEX_LAYER_OVERLAY,texturename); + } + + if (backgroundlevel == "header") { + retval |= engine->setTexture(TEX_LAYER_HEADER,texturename); + } + + if (backgroundlevel == "footer") { + retval |= engine->setTexture(TEX_LAYER_FOOTER,texturename); + } + + lua_pushboolean(L,retval); + return 1; +} + +/******************************************************************************/ +int ModApiMainMenu::l_set_clouds(lua_State *L) +{ + GUIEngine* engine = getGuiEngine(L); + assert(engine != 0); + + bool value = lua_toboolean(L,1); + + engine->m_clouds_enabled = value; + + return 0; +} + +/******************************************************************************/ +int ModApiMainMenu::l_get_textlist_index(lua_State *L) +{ + GUIEngine* engine = getGuiEngine(L); + assert(engine != 0); + + std::string listboxname(luaL_checkstring(L, 1)); + + int selection = engine->m_menu->getListboxIndex(listboxname); + + if (selection >= 0) + selection++; + + lua_pushinteger(L, selection); + return 1; +} + +/******************************************************************************/ +int ModApiMainMenu::l_get_worlds(lua_State *L) +{ + GUIEngine* engine = getGuiEngine(L); + assert(engine != 0); + + std::vector worlds = getAvailableWorlds(); + + lua_newtable(L); + int top = lua_gettop(L); + unsigned int index = 1; + + for (unsigned int i = 0; i < worlds.size(); i++) + { + lua_pushnumber(L,index); + + lua_newtable(L); + int top_lvl2 = lua_gettop(L); + + lua_pushstring(L,"path"); + lua_pushstring(L,worlds[i].path.c_str()); + lua_settable(L, top_lvl2); + + lua_pushstring(L,"name"); + lua_pushstring(L,worlds[i].name.c_str()); + lua_settable(L, top_lvl2); + + lua_pushstring(L,"gameid"); + lua_pushstring(L,worlds[i].gameid.c_str()); + lua_settable(L, top_lvl2); + + lua_settable(L, top); + index++; + } + return 1; +} + +/******************************************************************************/ +int ModApiMainMenu::l_get_games(lua_State *L) +{ + GUIEngine* engine = getGuiEngine(L); + assert(engine != 0); + + std::vector games = getAvailableGames(); + + lua_newtable(L); + int top = lua_gettop(L); + unsigned int index = 1; + + for (unsigned int i = 0; i < games.size(); i++) + { + lua_pushnumber(L,index); + lua_newtable(L); + int top_lvl2 = lua_gettop(L); + + lua_pushstring(L,"id"); + lua_pushstring(L,games[i].id.c_str()); + lua_settable(L, top_lvl2); + + lua_pushstring(L,"path"); + lua_pushstring(L,games[i].path.c_str()); + lua_settable(L, top_lvl2); + + lua_pushstring(L,"gamemods_path"); + lua_pushstring(L,games[i].gamemods_path.c_str()); + lua_settable(L, top_lvl2); + + lua_pushstring(L,"name"); + lua_pushstring(L,games[i].name.c_str()); + lua_settable(L, top_lvl2); + + lua_pushstring(L,"menuicon_path"); + lua_pushstring(L,games[i].menuicon_path.c_str()); + lua_settable(L, top_lvl2); + + lua_pushstring(L,"addon_mods_paths"); + lua_newtable(L); + int table2 = lua_gettop(L); + int internal_index=1; + for (std::set::iterator iter = games[i].addon_mods_paths.begin(); + iter != games[i].addon_mods_paths.end(); iter++) { + lua_pushnumber(L,internal_index); + lua_pushstring(L,(*iter).c_str()); + lua_settable(L, table2); + internal_index++; + } + lua_settable(L, top_lvl2); + lua_settable(L, top); + index++; + } + return 1; +} +/******************************************************************************/ +int ModApiMainMenu::l_get_modstore_details(lua_State *L) +{ + const char *modid = luaL_checkstring(L, 1); + + if (modid != 0) { + Json::Value details; + std::string url = ""; + try{ + url = g_settings->get("modstore_details_url"); + } + catch(SettingNotFoundException &e) { + lua_pushnil(L); + return 1; + } + + size_t idpos = url.find("*"); + url.erase(idpos,1); + url.insert(idpos,modid); + + details = getModstoreUrl(url); + + ModStoreModDetails current_mod = readModStoreModDetails(details); + + if ( current_mod.valid) { + lua_newtable(L); + int top = lua_gettop(L); + + lua_pushstring(L,"id"); + lua_pushnumber(L,current_mod.id); + lua_settable(L, top); + + lua_pushstring(L,"title"); + lua_pushstring(L,current_mod.title.c_str()); + lua_settable(L, top); + + lua_pushstring(L,"basename"); + lua_pushstring(L,current_mod.basename.c_str()); + lua_settable(L, top); + + lua_pushstring(L,"description"); + lua_pushstring(L,current_mod.description.c_str()); + lua_settable(L, top); + + lua_pushstring(L,"author"); + lua_pushstring(L,current_mod.author.username.c_str()); + lua_settable(L, top); + + lua_pushstring(L,"download_url"); + lua_pushstring(L,current_mod.versions[0].file.c_str()); + lua_settable(L, top); + + lua_pushstring(L,"screenshot_url"); + lua_pushstring(L,current_mod.titlepic.file.c_str()); + lua_settable(L, top); + + lua_pushstring(L,"license"); + lua_pushstring(L,current_mod.license.shortinfo.c_str()); + lua_settable(L, top); + + lua_pushstring(L,"rating"); + lua_pushnumber(L,current_mod.rating); + lua_settable(L, top); + + //TODO depends + + //TODO softdepends + return 1; + } + } + return 0; +} + +/******************************************************************************/ +int ModApiMainMenu::l_get_modstore_list(lua_State *L) +{ + GUIEngine* engine = getGuiEngine(L); + assert(engine != 0); + + std::string listtype = "local"; + + if (!lua_isnone(L,1)) { + listtype = luaL_checkstring(L,1); + } + Json::Value mods; + std::string url = ""; + try{ + url = g_settings->get("modstore_listmods_url"); + } + catch(SettingNotFoundException &e) { + lua_pushnil(L); + return 1; + } + + mods = getModstoreUrl(url); + + std::vector moddata = readModStoreList(mods); + + lua_newtable(L); + int top = lua_gettop(L); + unsigned int index = 1; + + for (unsigned int i = 0; i < moddata.size(); i++) + { + if (moddata[i].valid) { + lua_pushnumber(L,index); + lua_newtable(L); + + int top_lvl2 = lua_gettop(L); + + lua_pushstring(L,"id"); + lua_pushnumber(L,moddata[i].id); + lua_settable(L, top_lvl2); + + lua_pushstring(L,"title"); + lua_pushstring(L,moddata[i].title.c_str()); + lua_settable(L, top_lvl2); + + lua_pushstring(L,"basename"); + lua_pushstring(L,moddata[i].basename.c_str()); + lua_settable(L, top_lvl2); + + lua_settable(L, top); + index++; + } + } + return 1; +} + +/******************************************************************************/ +int ModApiMainMenu::l_get_favorites(lua_State *L) +{ + GUIEngine* engine = getGuiEngine(L); + assert(engine != 0); + + std::string listtype = "local"; + + if (!lua_isnone(L,1)) { + listtype = luaL_checkstring(L,1); + } + + std::vector servers; +#if USE_CURL + if(listtype == "online") { + servers = ServerList::getOnline(); + } else { + servers = ServerList::getLocal(); + } +#else + servers = ServerList::getLocal(); +#endif + + lua_newtable(L); + int top = lua_gettop(L); + unsigned int index = 1; + + for (unsigned int i = 0; i < servers.size(); i++) + { + lua_pushnumber(L,index); + + lua_newtable(L); + int top_lvl2 = lua_gettop(L); + + if (servers[i]["clients"].asString().size()) { + + const char* clients_raw = servers[i]["clients"].asString().c_str(); + char* endptr = 0; + int numbervalue = strtol(clients_raw,&endptr,10); + + if ((*clients_raw != 0) && (*endptr == 0)) { + lua_pushstring(L,"clients"); + lua_pushnumber(L,numbervalue); + lua_settable(L, top_lvl2); + } + } + + if (servers[i]["clients_max"].asString().size()) { + + const char* clients_max_raw = servers[i]["clients_max"].asString().c_str(); + char* endptr = 0; + int numbervalue = strtol(clients_max_raw,&endptr,10); + + if ((*clients_max_raw != 0) && (*endptr == 0)) { + lua_pushstring(L,"clients_max"); + lua_pushnumber(L,numbervalue); + lua_settable(L, top_lvl2); + } + } + + if (servers[i]["version"].asString().size()) { + lua_pushstring(L,"version"); + lua_pushstring(L,servers[i]["version"].asString().c_str()); + lua_settable(L, top_lvl2); + } + + if (servers[i]["password"].asString().size()) { + lua_pushstring(L,"password"); + lua_pushboolean(L,true); + lua_settable(L, top_lvl2); + } + + if (servers[i]["creative"].asString().size()) { + lua_pushstring(L,"creative"); + lua_pushboolean(L,true); + lua_settable(L, top_lvl2); + } + + if (servers[i]["damage"].asString().size()) { + lua_pushstring(L,"damage"); + lua_pushboolean(L,true); + lua_settable(L, top_lvl2); + } + + if (servers[i]["pvp"].asString().size()) { + lua_pushstring(L,"pvp"); + lua_pushboolean(L,true); + lua_settable(L, top_lvl2); + } + + if (servers[i]["description"].asString().size()) { + lua_pushstring(L,"description"); + lua_pushstring(L,servers[i]["description"].asString().c_str()); + lua_settable(L, top_lvl2); + } + + if (servers[i]["name"].asString().size()) { + lua_pushstring(L,"name"); + lua_pushstring(L,servers[i]["name"].asString().c_str()); + lua_settable(L, top_lvl2); + } + + if (servers[i]["address"].asString().size()) { + lua_pushstring(L,"address"); + lua_pushstring(L,servers[i]["address"].asString().c_str()); + lua_settable(L, top_lvl2); + } + + if (servers[i]["port"].asString().size()) { + lua_pushstring(L,"port"); + lua_pushstring(L,servers[i]["port"].asString().c_str()); + lua_settable(L, top_lvl2); + } + + lua_settable(L, top); + index++; + } + return 1; +} + +/******************************************************************************/ +int ModApiMainMenu::l_delete_favorite(lua_State *L) +{ + GUIEngine* engine = getGuiEngine(L); + assert(engine != 0); + + std::vector servers; + + std::string listtype = "local"; + + if (!lua_isnone(L,2)) { + listtype = luaL_checkstring(L,2); + } + + if ((listtype != "local") && + (listtype != "online")) + return 0; + +#if USE_CURL + if(listtype == "online") { + servers = ServerList::getOnline(); + } else { + servers = ServerList::getLocal(); + } +#else + servers = ServerList::getLocal(); +#endif + + int fav_idx = luaL_checkinteger(L,1) -1; + + if ((fav_idx >= 0) && + (fav_idx < (int) servers.size())) { + + ServerList::deleteEntry(servers[fav_idx]); + } + + return 0; +} + +/******************************************************************************/ +int ModApiMainMenu::l_show_keys_menu(lua_State *L) +{ + GUIEngine* engine = getGuiEngine(L); + assert(engine != 0); + + GUIKeyChangeMenu *kmenu + = new GUIKeyChangeMenu( engine->m_device->getGUIEnvironment(), + engine->m_parent, + -1, + engine->m_menumanager); + kmenu->drop(); + return 0; +} + +/******************************************************************************/ +int ModApiMainMenu::l_create_world(lua_State *L) +{ + GUIEngine* engine = getGuiEngine(L); + assert(engine != 0); + + const char *name = luaL_checkstring(L, 1); + int gameidx = luaL_checkinteger(L,2) -1; + + std::string path = porting::path_user + DIR_DELIM + "worlds" + DIR_DELIM + + name; + + std::vector games = getAvailableGames(); + + if ((gameidx >= 0) && + (gameidx < (int) games.size())) { + + // Create world if it doesn't exist + if(!initializeWorld(path, games[gameidx].id)){ + lua_pushstring(L, "Failed to initialize world"); + + } + else { + lua_pushnil(L); + } + } + else { + lua_pushstring(L, "Invalid game index"); + } + return 1; +} + +/******************************************************************************/ +int ModApiMainMenu::l_delete_world(lua_State *L) +{ + GUIEngine* engine = getGuiEngine(L); + assert(engine != 0); + + int worldidx = luaL_checkinteger(L,1) -1; + + std::vector worlds = getAvailableWorlds(); + + if ((worldidx >= 0) && + (worldidx < (int) worlds.size())) { + + WorldSpec spec = worlds[worldidx]; + + std::vector paths; + paths.push_back(spec.path); + fs::GetRecursiveSubPaths(spec.path, paths); + + // Delete files + if (!fs::DeletePaths(paths)) { + lua_pushstring(L, "Failed to delete world"); + } + else { + lua_pushnil(L); + } + } + else { + lua_pushstring(L, "Invalid world index"); + } + return 1; +} + +/******************************************************************************/ +int ModApiMainMenu::l_set_topleft_text(lua_State *L) +{ + GUIEngine* engine = getGuiEngine(L); + assert(engine != 0); + + std::string text = ""; + + if (!lua_isnone(L,1) && !lua_isnil(L,1)) + text = luaL_checkstring(L, 1); + + engine->setTopleftText(text); + return 0; +} + +/******************************************************************************/ +int ModApiMainMenu::l_get_modpath(lua_State *L) +{ + std::string modpath + = fs::RemoveRelativePathComponents(porting::path_user + DIR_DELIM + "mods" + DIR_DELIM); + lua_pushstring(L, modpath.c_str()); + return 1; +} + +/******************************************************************************/ +int ModApiMainMenu::l_get_gamepath(lua_State *L) +{ + std::string gamepath + = fs::RemoveRelativePathComponents(porting::path_user + DIR_DELIM + "games" + DIR_DELIM); + lua_pushstring(L, gamepath.c_str()); + return 1; +} + +/******************************************************************************/ +int ModApiMainMenu::l_get_texturepath(lua_State *L) +{ + std::string gamepath + = fs::RemoveRelativePathComponents(porting::path_user + DIR_DELIM + "textures"); + lua_pushstring(L, gamepath.c_str()); + return 1; +} + +/******************************************************************************/ +int ModApiMainMenu::l_get_dirlist(lua_State *L) +{ + const char *path = luaL_checkstring(L, 1); + bool dironly = lua_toboolean(L, 2); + + std::vector dirlist = fs::GetDirListing(path); + + unsigned int index = 1; + lua_newtable(L); + int table = lua_gettop(L); + + for (unsigned int i=0;i< dirlist.size(); i++) { + if ((dirlist[i].dir) || (dironly == false)) { + lua_pushnumber(L,index); + lua_pushstring(L,dirlist[i].name.c_str()); + lua_settable(L, table); + index++; + } + } + + return 1; +} + +/******************************************************************************/ +int ModApiMainMenu::l_create_dir(lua_State *L) { + const char *path = luaL_checkstring(L, 1); + + if (ModApiMainMenu::isMinetestPath(path)) { + lua_pushboolean(L,fs::CreateAllDirs(path)); + return 1; + } + lua_pushboolean(L,false); + return 1; +} + +/******************************************************************************/ +int ModApiMainMenu::l_delete_dir(lua_State *L) +{ + const char *path = luaL_checkstring(L, 1); + + std::string absolute_path = fs::RemoveRelativePathComponents(path); + + if (ModApiMainMenu::isMinetestPath(absolute_path)) { + lua_pushboolean(L,fs::RecursiveDelete(absolute_path)); + return 1; + } + lua_pushboolean(L,false); + return 1; +} + +/******************************************************************************/ +int ModApiMainMenu::l_copy_dir(lua_State *L) +{ + const char *source = luaL_checkstring(L, 1); + const char *destination = luaL_checkstring(L, 2); + + bool keep_source = true; + + if ((!lua_isnone(L,3)) && + (!lua_isnil(L,3))) { + keep_source = lua_toboolean(L,3); + } + + std::string absolute_destination = fs::RemoveRelativePathComponents(destination); + std::string absolute_source = fs::RemoveRelativePathComponents(source); + + if ((ModApiMainMenu::isMinetestPath(absolute_source)) && + (ModApiMainMenu::isMinetestPath(absolute_destination))) { + bool retval = fs::CopyDir(absolute_source,absolute_destination); + + if (retval && (!keep_source)) { + + retval &= fs::RecursiveDelete(absolute_source); + } + lua_pushboolean(L,retval); + return 1; + } + lua_pushboolean(L,false); + return 1; +} + +/******************************************************************************/ +int ModApiMainMenu::l_extract_zip(lua_State *L) +{ + GUIEngine* engine = getGuiEngine(L); + assert(engine != 0); + + const char *zipfile = luaL_checkstring(L, 1); + const char *destination = luaL_checkstring(L, 2); + + std::string absolute_destination = fs::RemoveRelativePathComponents(destination); + + if (ModApiMainMenu::isMinetestPath(absolute_destination)) { + fs::CreateAllDirs(absolute_destination); + + io::IFileSystem* fs = engine->m_device->getFileSystem(); + + fs->addFileArchive(zipfile,true,false,io::EFAT_ZIP); + + assert(fs->getFileArchiveCount() > 0); + + /**********************************************************************/ + /* WARNING this is not threadsafe!! */ + /**********************************************************************/ + io::IFileArchive* opened_zip = + fs->getFileArchive(fs->getFileArchiveCount()-1); + + const io::IFileList* files_in_zip = opened_zip->getFileList(); + + unsigned int number_of_files = files_in_zip->getFileCount(); + + for (unsigned int i=0; i < number_of_files; i++) { + std::string fullpath = destination; + fullpath += DIR_DELIM; + fullpath += files_in_zip->getFullFileName(i).c_str(); + + if (files_in_zip->isDirectory(i)) { + if (! fs::CreateAllDirs(fullpath) ) { + fs->removeFileArchive(fs->getFileArchiveCount()-1); + lua_pushboolean(L,false); + return 1; + } + } + else { + io::IReadFile* toread = opened_zip->createAndOpenFile(i); + + FILE *targetfile = fopen(fullpath.c_str(),"wb"); + + if (targetfile == NULL) { + fs->removeFileArchive(fs->getFileArchiveCount()-1); + lua_pushboolean(L,false); + return 1; + } + + char read_buffer[1024]; + unsigned int total_read = 0; + + while (total_read < toread->getSize()) { + + unsigned int bytes_read = + toread->read(read_buffer,sizeof(read_buffer)); + unsigned int bytes_written; + if ((bytes_read < 0 ) || + (bytes_written = fwrite(read_buffer, 1, bytes_read, targetfile) != bytes_read)) + { + fclose(targetfile); + fs->removeFileArchive(fs->getFileArchiveCount()-1); + lua_pushboolean(L,false); + return 1; + } + total_read += bytes_read; + } + + fclose(targetfile); + } + + } + + fs->removeFileArchive(fs->getFileArchiveCount()-1); + lua_pushboolean(L,true); + return 1; + } + + lua_pushboolean(L,false); + return 1; +} + +/******************************************************************************/ +int ModApiMainMenu::l_get_scriptdir(lua_State *L) +{ + GUIEngine* engine = getGuiEngine(L); + assert(engine != 0); + + lua_pushstring(L,engine->getScriptDir().c_str()); + return 1; +} + +/******************************************************************************/ +bool ModApiMainMenu::isMinetestPath(std::string path) +{ + if (fs::PathStartsWith(path,fs::TempPath())) + return true; + + /* games */ + if (fs::PathStartsWith(path,fs::RemoveRelativePathComponents(porting::path_share + DIR_DELIM + "games"))) + return true; + + /* mods */ + if (fs::PathStartsWith(path,fs::RemoveRelativePathComponents(porting::path_user + DIR_DELIM + "mods"))) + return true; + + /* worlds */ + if (fs::PathStartsWith(path,fs::RemoveRelativePathComponents(porting::path_user + DIR_DELIM + "worlds"))) + return true; + + + return false; +} + +/******************************************************************************/ +int ModApiMainMenu::l_show_file_open_dialog(lua_State *L) +{ + GUIEngine* engine = getGuiEngine(L); + assert(engine != 0); + + const char *formname= luaL_checkstring(L, 1); + const char *title = luaL_checkstring(L, 2); + + GUIFileSelectMenu* fileOpenMenu = + new GUIFileSelectMenu(engine->m_device->getGUIEnvironment(), + engine->m_parent, + -1, + engine->m_menumanager, + title, + formname); + fileOpenMenu->setTextDest(engine->m_buttonhandler); + fileOpenMenu->drop(); + return 0; +} + +/******************************************************************************/ +int ModApiMainMenu::l_get_version(lua_State *L) +{ + lua_pushstring(L,VERSION_STRING); + return 1; +} + +/******************************************************************************/ +int ModApiMainMenu::l_sound_play(lua_State *L) +{ + GUIEngine* engine = getGuiEngine(L); + + SimpleSoundSpec spec; + read_soundspec(L, 1, spec); + bool looped = lua_toboolean(L, 2); + + u32 handle = engine->playSound(spec, looped); + + lua_pushinteger(L, handle); + + return 1; +} + +/******************************************************************************/ +int ModApiMainMenu::l_sound_stop(lua_State *L) +{ + GUIEngine* engine = getGuiEngine(L); + + u32 handle = luaL_checkinteger(L, 1); + engine->stopSound(handle); + + return 1; +} + +/******************************************************************************/ +int ModApiMainMenu::l_download_file(lua_State *L) +{ + GUIEngine* engine = getGuiEngine(L); + assert(engine != 0); + + const char *url = luaL_checkstring(L, 1); + const char *target = luaL_checkstring(L, 2); + + //check path + std::string absolute_destination = fs::RemoveRelativePathComponents(target); + + if (ModApiMainMenu::isMinetestPath(absolute_destination)) { + if (engine->downloadFile(url,absolute_destination)) { + lua_pushboolean(L,true); + return 1; + } + } + lua_pushboolean(L,false); + return 1; +} + +/******************************************************************************/ +void ModApiMainMenu::Initialize(lua_State *L, int top) +{ + API_FCT(update_formspec); + API_FCT(set_clouds); + API_FCT(get_textlist_index); + API_FCT(get_worlds); + API_FCT(get_games); + API_FCT(start); + API_FCT(close); + API_FCT(get_favorites); + API_FCT(show_keys_menu); + API_FCT(create_world); + API_FCT(delete_world); + API_FCT(delete_favorite); + API_FCT(set_background); + API_FCT(set_topleft_text); + API_FCT(get_modpath); + API_FCT(get_gamepath); + API_FCT(get_texturepath); + API_FCT(get_dirlist); + API_FCT(create_dir); + API_FCT(delete_dir); + API_FCT(copy_dir); + API_FCT(extract_zip); + API_FCT(get_scriptdir); + API_FCT(show_file_open_dialog); + API_FCT(get_version); + API_FCT(download_file); + API_FCT(get_modstore_details); + API_FCT(get_modstore_list); + API_FCT(sound_play); + API_FCT(sound_stop); +} diff --git a/src/script/lua_api/l_mainmenu.h b/src/script/lua_api/l_mainmenu.h new file mode 100644 index 00000000..21dd82c6 --- /dev/null +++ b/src/script/lua_api/l_mainmenu.h @@ -0,0 +1,137 @@ +/* +Minetest +Copyright (C) 2013 sapier + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifndef L_MAINMENU_H_ +#define L_MAINMENU_H_ + +#include "lua_api/l_base.h" + +/** Implementation of lua api support for mainmenu */ +class ModApiMainMenu : public ModApiBase { + +private: + /** + * read a text variable from gamedata table within lua stack + * @param L stack to read variable from + * @param name name of variable to read + * @return string value of requested variable + */ + static std::string getTextData(lua_State *L, std::string name); + + /** + * read a integer variable from gamedata table within lua stack + * @param L stack to read variable from + * @param name name of variable to read + * @return integer value of requested variable + */ + static int getIntegerData(lua_State *L, std::string name,bool& valid); + + /** + * read a bool variable from gamedata table within lua stack + * @param L stack to read variable from + * @param name name of variable to read + * @return bool value of requested variable + */ + static int getBoolData(lua_State *L, std::string name,bool& valid); + + /** + * check if a path is within some of minetests folders + * @param path path to check + * @return true/false + */ + static bool isMinetestPath(std::string path); + + //api calls + + static int l_start(lua_State *L); + + static int l_close(lua_State *L); + + static int l_create_world(lua_State *L); + + static int l_delete_world(lua_State *L); + + static int l_get_worlds(lua_State *L); + + static int l_get_games(lua_State *L); + + static int l_get_favorites(lua_State *L); + + static int l_delete_favorite(lua_State *L); + + static int l_get_version(lua_State *L); + + static int l_sound_play(lua_State *L); + + static int l_sound_stop(lua_State *L); + + //gui + + static int l_show_keys_menu(lua_State *L); + + static int l_show_file_open_dialog(lua_State *L); + + static int l_set_topleft_text(lua_State *L); + + static int l_set_clouds(lua_State *L); + + static int l_get_textlist_index(lua_State *L); + + static int l_set_background(lua_State *L); + + static int l_update_formspec(lua_State *L); + + //filesystem + + static int l_get_scriptdir(lua_State *L); + + static int l_get_modpath(lua_State *L); + + static int l_get_gamepath(lua_State *L); + + static int l_get_texturepath(lua_State *L); + + static int l_get_dirlist(lua_State *L); + + static int l_create_dir(lua_State *L); + + static int l_delete_dir(lua_State *L); + + static int l_copy_dir(lua_State *L); + + static int l_extract_zip(lua_State *L); + + static int l_get_modstore_details(lua_State *L); + + static int l_get_modstore_list(lua_State *L); + + static int l_download_file(lua_State *L); + + +public: + /** + * initialize this API module + * @param L lua stack to initialize + * @param top index (in lua stack) of global API table + */ + static void Initialize(lua_State *L, int top); + +}; + +#endif /* L_MAINMENU_H_ */ diff --git a/src/script/lua_api/l_mapgen.cpp b/src/script/lua_api/l_mapgen.cpp new file mode 100644 index 00000000..14693b43 --- /dev/null +++ b/src/script/lua_api/l_mapgen.cpp @@ -0,0 +1,574 @@ +/* +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola + +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", + ""); + 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 > 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 00000000..d0da5bb1 --- /dev/null +++ b/src/script/lua_api/l_mapgen.h @@ -0,0 +1,62 @@ +/* +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola + +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 511fb38c..f9c8794d 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 lists = inv->getLists(); for(std::vector::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 23404a08..ed06ff0f 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 -#include -} +#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 60e4ec06..c81a7ebc 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 f652b490..9f8dd21c 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 -#include -} +#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 43149e93..ecbda9fa 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 6275ca47..65a92788 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 -#include -} - +#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 ee24789c..c0da79c2 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 a8263844..b6f5cd06 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 -#include -} +#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 c291cc21..6b009149 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 3729f876..c593f47e 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 -#include -} +#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 00000000..6076399a --- /dev/null +++ b/src/script/lua_api/l_rollback.cpp @@ -0,0 +1,80 @@ +/* +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola + +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 actions = rollback->getRevertActions(actor, seconds); + std::list 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::const_iterator i = log.begin(); + i != log.end(); i++) + { + lua_pushvalue(L, table_insert); + lua_pushvalue(L, table); + lua_pushstring(L, i->c_str()); + if(lua_pcall(L, 2, 0, 0)) + script_error(L, "error: %s", lua_tostring(L, -1)); + } + lua_remove(L, -2); // Remove table + lua_remove(L, -2); // Remove insert + return 2; +} + +void ModApiRollback::Initialize(lua_State *L, int top) +{ + API_FCT(rollback_get_last_node_actor); + API_FCT(rollback_revert_actions_by); +} diff --git a/src/script/lua_api/l_rollback.h b/src/script/lua_api/l_rollback.h new file mode 100644 index 00000000..86992a47 --- /dev/null +++ b/src/script/lua_api/l_rollback.h @@ -0,0 +1,37 @@ +/* +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifndef L_ROLLBACK_H_ +#define L_ROLLBACK_H_ + +#include "lua_api/l_base.h" + +class ModApiRollback : public ModApiBase { +private: + // rollback_get_last_node_actor(p, range, seconds) -> actor, p, seconds + static int l_rollback_get_last_node_actor(lua_State *L); + + // rollback_revert_actions_by(actor, seconds) -> bool, log messages + static int l_rollback_revert_actions_by(lua_State *L); + +public: + static void Initialize(lua_State *L, int top); +}; + +#endif /* L_ROLLBACK_H_ */ diff --git a/src/script/lua_api/l_server.cpp b/src/script/lua_api/l_server.cpp new file mode 100644 index 00000000..8e809c36 --- /dev/null +++ b/src/script/lua_api/l_server.cpp @@ -0,0 +1,347 @@ +/* +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola + +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 privs_s = server->getPlayerEffectivePrivs(name); + for(std::set::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 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::iterator i = mods_unsorted.begin(); + i != mods_unsorted.end(); ++i) + { + bool added = false; + for(std::list::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::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/l_server.h b/src/script/lua_api/l_server.h new file mode 100644 index 00000000..21f30040 --- /dev/null +++ b/src/script/lua_api/l_server.h @@ -0,0 +1,90 @@ +/* +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola + +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_SERVER_H_ +#define L_SERVER_H_ + +#include "lua_api/l_base.h" + +class ModApiServer : public ModApiBase { +private: + // request_shutdown() + static int l_request_shutdown(lua_State *L); + + // get_server_status() + static int l_get_server_status(lua_State *L); + + // get_worldpath() + static int l_get_worldpath(lua_State *L); + + // is_singleplayer() + static int l_is_singleplayer(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); + + // chat_send_all(text) + static int l_chat_send_all(lua_State *L); + + // 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); + + // get_player_ip() + static int l_get_player_ip(lua_State *L); + + // get_ban_list() + static int l_get_ban_list(lua_State *L); + + // get_ban_description() + static int l_get_ban_description(lua_State *L); + + // ban_player() + static int l_ban_player(lua_State *L); + + // unban_player_or_ip() + static int l_unban_player_or_ip(lua_State *L); + + // notify_authentication_modified(name) + static int l_notify_authentication_modified(lua_State *L); + +public: + static void Initialize(lua_State *L, int top); + +}; + +#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 00000000..0e4de9ee --- /dev/null +++ b/src/script/lua_api/l_util.cpp @@ -0,0 +1,199 @@ +/* +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola + +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 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 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 00000000..b102e315 --- /dev/null +++ b/src/script/lua_api/l_util.h @@ -0,0 +1,76 @@ +/* +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola + +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. in the in-game API as well as + engine. 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 19568257..1e9cc350 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 lighting_mblocks; std::map *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 a7791e56..d2f035a3 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 -#include -} - +#include "lua_api/l_base.h" #include "irr_v3d.h" -#include "map.h" +#include + +class Map; +class MapBlock; +class ManualMapVoxelManipulator; /* VoxelManip */ -class LuaVoxelManip -{ +class LuaVoxelManip : public ModApiBase { private: ManualMapVoxelManipulator *vm; std::map 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 26fb0c31..00000000 --- a/src/script/lua_api/luaapi.cpp +++ /dev/null @@ -1,955 +0,0 @@ -/* -Minetest -Copyright (C) 2013 celeron55, Perttu Ahola - -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", - ""); - 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 privs_s = server->getPlayerEffectivePrivs(name); - for(std::set::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 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 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 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::iterator i = mods_unsorted.begin(); - i != mods_unsorted.end(); ++i) - { - bool added = false; - for(std::list::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::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 actions = rollback->getRevertActions(actor, seconds); - std::list 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::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 > 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/lua_api/luaapi.h b/src/script/lua_api/luaapi.h deleted file mode 100644 index af73625b..00000000 --- a/src/script/lua_api/luaapi.h +++ /dev/null @@ -1,150 +0,0 @@ -/* -Minetest -Copyright (C) 2013 celeron55, Perttu Ahola - -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 LUAAPI_H_ -#define LUAAPI_H_ - - -class ModApiBasic : public ModApiBase { - -public: - ModApiBasic(); - - bool Initialize(lua_State* L,int top); - -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); - - // setting_set(name, value) - static int l_setting_set(lua_State *L); - - // setting_get(name) - static int l_setting_get(lua_State *L); - - // setting_getbool(name) - static int l_setting_getbool(lua_State *L); - - // setting_save() - static int l_setting_save(lua_State *L); - - // chat_send_all(text) - static int l_chat_send_all(lua_State *L); - - // chat_send_player(name, text) - static int l_chat_send_player(lua_State *L); - - // get_player_privs(name, text) - static int l_get_player_privs(lua_State *L); - - // get_player_ip() - static int l_get_player_ip(lua_State *L); - - // get_ban_list() - static int l_get_ban_list(lua_State *L); - - // get_ban_description() - static int l_get_ban_description(lua_State *L); - - // ban_player() - static int l_ban_player(lua_State *L); - - // 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[]; - -}; - - - -#endif /* LUAAPI_H_ */ diff --git a/src/script/scripting_game.cpp b/src/script/scripting_game.cpp new file mode 100644 index 00000000..dfbf471d --- /dev/null +++ b/src/script/scripting_game.cpp @@ -0,0 +1,99 @@ +/* +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola + +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/scripting_game.h b/src/script/scripting_game.h new file mode 100644 index 00000000..ed656792 --- /dev/null +++ b/src/script/scripting_game.h @@ -0,0 +1,53 @@ +/* +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola + +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_GAME_H_ +#define SCRIPTING_GAME_H_ + +#include "cpp_api/s_base.h" +#include "cpp_api/s_entity.h" +#include "cpp_api/s_env.h" +#include "cpp_api/s_inventory.h" +#include "cpp_api/s_node.h" +#include "cpp_api/s_player.h" +#include "cpp_api/s_server.h" + +/*****************************************************************************/ +/* Scripting <-> Game Interface */ +/*****************************************************************************/ + +class GameScripting + : virtual public ScriptApiBase, + public ScriptApiDetached, + public ScriptApiEntity, + public ScriptApiEnv, + public ScriptApiNode, + public ScriptApiPlayer, + public ScriptApiServer +{ +public: + GameScripting(Server* server); + + // use ScriptApiBase::loadMod() to load mods + +private: + void InitializeModApi(lua_State *L, int top); +}; + +#endif /* SCRIPTING_GAME_H_ */ diff --git a/src/script/scripting_mainmenu.cpp b/src/script/scripting_mainmenu.cpp new file mode 100644 index 00000000..47461e7c --- /dev/null +++ b/src/script/scripting_mainmenu.cpp @@ -0,0 +1,65 @@ +/* +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola + +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 00000000..7592c8e2 --- /dev/null +++ b/src/script/scripting_mainmenu.h @@ -0,0 +1,45 @@ +/* +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola + +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 7926b879..5ecdddcb 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 #include #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(); @@ -613,46 +631,23 @@ void RemoteClient::SetBlocksNotSent(std::map &blocks) } } -/* - PlayerInfo -*/ - -PlayerInfo::PlayerInfo() -{ - name[0] = 0; - avg_rtt = 0; -} - -void PlayerInfo::PrintLine(std::ostream *s) -{ - (*s)<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<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 "<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"<setRun(false); //m_emergethread.setRun(false); - m_thread.stop(); + m_thread->stop(); //m_emergethread.stop(); infostream<<"Server: Threads stopped"<getTimeOfDay(); + float time_speed = g_settings->getFloat("time_speed"); + for(std::map::iterator i = m_clients.begin(); i != m_clients.end(); ++i) { RemoteClient *client = i->second; - SharedBuffer 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 " <getBanName(addr_s)<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 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()"< Server::getPlayerInfo() -//{ -// DSTACK(__FUNCTION_NAME); -// JMutexAutoLock envlock(m_env_mutex); -// JMutexAutoLock conlock(m_con_mutex); -// -// std::list list; -// -// std::list players = m_env->getPlayers(); -// -// std::list::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 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 d49ecdf7..4e7675ec 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 -#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 // Needed for rollbackRevertActions() -#include +#include "util/numeric.h" +#include "util/thread.h" +#include +#include +#include +#include #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 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 a9e0faa4..62596f86 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 -#include #include #include #include "strfnd.h" diff --git a/src/socket.cpp b/src/socket.cpp index 8505b24f..1c07c44d 100644 --- a/src/socket.cpp +++ b/src/socket.cpp @@ -56,6 +56,7 @@ typedef int socket_t; #include #include #include +#include #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 4a72edf3..3142cc10 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 -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 fa7a8242..5e025f2f 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 a3717a1d..18789cf0 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 4d809e2c..f3b3e656 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 808cf916..6291567d 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 +#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 16c85cf0..55da6f9e 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 84616d2d..d5854909 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 #include #include "../porting.h" // For sleep_ms #include #include +#include /* Queue with unique values with fast checking of value existence diff --git a/src/util/numeric.h b/src/util/numeric.h index 076a08ef..b96c94fa 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 #include // Calculate the borders of a "d-radius" cube diff --git a/src/util/pointedthing.cpp b/src/util/pointedthing.cpp index dc39e313..cd13000b 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 PointedThing::PointedThing(): diff --git a/src/util/serialize.cpp b/src/util/serialize.cpp index f3281355..d6be5c48 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 #include +// 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 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 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 bb44c7f9..7a37cd70 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 #include -#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 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 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 3bd8b736..2c1dea49 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 wcs(wcl+1); + size_t l = mbstowcs(*wcs, mbs.c_str(), wcl); + if(l == (size_t)(-1)) + return L""; + wcs[l] = 0; + return *wcs; +} + +std::string wide_to_narrow(const std::wstring& wcs) +{ + size_t mbl = wcs.size()*4; + SharedBuffer 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 d8cedc3e..1cb4ae8d 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 #include #include #include @@ -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 wcs(wcl+1); - size_t l = mbstowcs(*wcs, mbs.c_str(), wcl); - if(l == (size_t)(-1)) - return L""; - wcs[l] = 0; - return *wcs; -} - -inline std::string wide_to_narrow(const std::wstring& wcs) -{ - size_t mbl = wcs.size()*4; - SharedBuffer 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 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 58519ed5..4b523b59 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 // memcpy, memset /* Debug stuff diff --git a/src/voxel.h b/src/voxel.h index bed35b57..fa459444 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 #include #include "debug.h" +#include "exceptions.h" #include "mapnode.h" #include #include +#include class INodeDefManager;