From d5ca3b721e049fc4f59718a55c932a06533d4b3c Mon Sep 17 00:00:00 2001 From: PilzAdam Date: Tue, 14 May 2013 12:29:30 +0200 Subject: Fix memory leak in run_tests() --- src/test.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/test.cpp b/src/test.cpp index d1f53f880..e1dbfa6b8 100644 --- a/src/test.cpp +++ b/src/test.cpp @@ -1772,6 +1772,10 @@ void run_tests() TEST(TestConnection); dout_con<<"=== END RUNNING UNIT TESTS FOR CONNECTION ==="< Date: Thu, 16 May 2013 02:19:32 +0200 Subject: Dont drop fonts with ENABLE_FREETYPE=0 --- src/guiChatConsole.cpp | 4 +++- src/main.cpp | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/guiChatConsole.cpp b/src/guiChatConsole.cpp index f31e599dc..3dfd0090a 100644 --- a/src/guiChatConsole.cpp +++ b/src/guiChatConsole.cpp @@ -121,7 +121,9 @@ GUIChatConsole::GUIChatConsole( GUIChatConsole::~GUIChatConsole() { - delete m_font; +#if USE_FREETYPE + m_font->drop(); +#endif } void GUIChatConsole::openConsole(f32 height) diff --git a/src/main.cpp b/src/main.cpp index 7f9ec1ace..d28ba9b9d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2145,7 +2145,9 @@ int main(int argc, char *argv[]) */ device->drop(); - delete font; +#if USE_FREETYPE + font->drop(); +#endif #endif // !SERVER -- cgit v1.2.3 From fedf644635456b85d6168ca98f6dc712b1ce7f2e Mon Sep 17 00:00:00 2001 From: PilzAdam Date: Fri, 17 May 2013 23:15:10 +0200 Subject: Move kahrl to core devs in credits tab --- src/guiMainMenu.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/guiMainMenu.cpp b/src/guiMainMenu.cpp index 36685db84..223bba93c 100644 --- a/src/guiMainMenu.cpp +++ b/src/guiMainMenu.cpp @@ -54,11 +54,11 @@ const wchar_t *contrib_core_strs[] = { L"Lisa Milne (darkrose) ", L"Maciej Kasatkin (RealBadAngel) ", L"proller ", - L"sfan5 " + L"sfan5 ", + L"kahrl " }; const wchar_t *contrib_active_strs[] = { - L"kahrl ", L"sapier ", L"Vanessa Ezekowitz (VanessaE) ", L"Jurgen Doser (doserj) ", -- cgit v1.2.3 From 1369503aba1ae0c64e6c25b32cc5552bbdead8fb Mon Sep 17 00:00:00 2001 From: Aaron Suen Date: Fri, 17 May 2013 17:10:39 -0400 Subject: Fix math for isBlockInSight. Fixes #718 (client-side). --- src/camera.cpp | 3 +-- src/util/numeric.cpp | 33 +++++++++++++++++---------------- 2 files changed, 18 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/camera.cpp b/src/camera.cpp index 6224a2b8e..0dd0a767b 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -342,8 +342,7 @@ void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize, m_fov_y = fov_degrees * M_PI / 180.0; // Increase vertical FOV on lower aspect ratios (<16:10) m_fov_y *= MYMAX(1.0, MYMIN(1.4, sqrt(16./10. / m_aspect))); - // WTF is this? It can't be right - m_fov_x = 2 * atan(0.5 * m_aspect * tan(m_fov_y)); + m_fov_x = 2 * atan(m_aspect * tan(0.5 * m_fov_y)); m_cameranode->setAspectRatio(m_aspect); m_cameranode->setFOV(m_fov_y); diff --git a/src/util/numeric.cpp b/src/util/numeric.cpp index ed83df7d7..0e2772c32 100644 --- a/src/util/numeric.cpp +++ b/src/util/numeric.cpp @@ -159,40 +159,41 @@ bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, // Block position relative to camera v3f blockpos_relative = blockpos - camera_pos; - // Distance in camera direction (+=front, -=back) - f32 dforward = blockpos_relative.dotProduct(camera_dir); - // Total distance f32 d = blockpos_relative.getLength(); if(distance_ptr) *distance_ptr = d; - // If block is very close, it is always in sight - if(d < 1.44*1.44*MAP_BLOCKSIZE*BS/2) - return true; - // If block is far away, it's not in sight if(d > range) return false; - // Maximum radius of a block - f32 block_max_radius = 0.5*1.44*1.44*MAP_BLOCKSIZE*BS; + // Maximum radius of a block. The magic number is + // sqrt(3.0) / 2.0 in literal form. + f32 block_max_radius = 0.866025403784 * MAP_BLOCKSIZE * BS; // If block is (nearly) touching the camera, don't // bother validating further (that is, render it anyway) if(d < block_max_radius) return true; - + + // Adjust camera position, for purposes of computing the angle, + // such that a block that has any portion visible with the + // current camera position will have the center visible at the + // adjusted postion + f32 adjdist = block_max_radius / cos((M_PI - camera_fov) / 2); + + // Block position relative to adjusted camera + v3f blockpos_adj = blockpos - (camera_pos - camera_dir * adjdist); + + // Distance in camera direction (+=front, -=back) + f32 dforward = blockpos_adj.dotProduct(camera_dir); + // Cosine of the angle between the camera direction // and the block direction (camera_dir is an unit vector) - f32 cosangle = dforward / d; + f32 cosangle = dforward / blockpos_adj.getLength(); - // Compensate for the size of the block - // (as the block has to be shown even if it's a bit off FOV) - // This is an estimate, plus an arbitary factor - cosangle += block_max_radius / d * 0.5; - // If block is not in the field of view, skip it if(cosangle < cos(camera_fov / 2)) return false; -- cgit v1.2.3 From 9397b5de083fabe2e93c55de5bf90e5c75bbe9c1 Mon Sep 17 00:00:00 2001 From: PilzAdam Date: Sat, 18 May 2013 01:52:18 +0200 Subject: Fix memory leak in MeshUpdateThread --- src/client.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src') diff --git a/src/client.cpp b/src/client.cpp index 929ed0eab..533c40ab2 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -350,6 +350,11 @@ Client::~Client() m_mesh_update_thread.setRun(false); while(m_mesh_update_thread.IsRunning()) sleep_ms(100); + while(!m_mesh_update_thread.m_queue_out.empty()) { + MeshUpdateResult r = m_mesh_update_thread.m_queue_out.pop_front(); + delete r.mesh; + } + delete m_inventory_from_server; @@ -757,6 +762,8 @@ void Client::step(float dtime) // Replace with the new mesh block->mesh = r.mesh; + } else { + delete r.mesh; } if(r.ack_block_to_server) { -- cgit v1.2.3 From 714ecc5e27c2c01b0f3ce0ba626abb6baca9af13 Mon Sep 17 00:00:00 2001 From: PilzAdam Date: Sat, 18 May 2013 13:01:47 +0200 Subject: Only create SoundManager in main menu if USE_SOUND is true --- src/main.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/main.cpp b/src/main.cpp index d28ba9b9d..e5c8a55d3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1845,7 +1845,9 @@ int main(int argc, char *argv[]) MenuMusicFetcher soundfetcher; ISoundManager *sound = NULL; +#if USE_SOUND sound = createOpenALSoundManager(&soundfetcher); +#endif if(!sound) sound = &dummySoundManager; SimpleSoundSpec spec; -- cgit v1.2.3 From 45fcc9de29de762e8dde20a50db4a3184c830e42 Mon Sep 17 00:00:00 2001 From: PilzAdam Date: Sat, 18 May 2013 17:00:47 +0200 Subject: New modsystem Mods are placed in $path_/mods They can be enabled per world in world.mt or the configure world window --- src/guiConfigureWorld.cpp | 59 +++++++++-------------------------------------- src/guiConfigureWorld.h | 3 --- src/subgame.cpp | 4 ++-- 3 files changed, 13 insertions(+), 53 deletions(-) (limited to 'src') diff --git a/src/guiConfigureWorld.cpp b/src/guiConfigureWorld.cpp index f94ed7d17..e33e87ef5 100644 --- a/src/guiConfigureWorld.cpp +++ b/src/guiConfigureWorld.cpp @@ -116,40 +116,18 @@ GUIConfigureWorld::GUIConfigureWorld(gui::IGUIEnvironment* env, // mod_names if(!mod.is_modpack && mod_names.count(modname) == 0) - m_new_mod_names.insert(modname); + m_settings.setBool("load_mod_"+modname, false); } - if(!m_new_mod_names.empty()) - { - wchar_t* text = wgettext("Warning: Some mods are not configured yet.\n" - "They will be enabled by default when you save the configuration. "); - GUIMessageMenu *menu = - new GUIMessageMenu(Environment, Parent, -1, m_menumgr, text); - menu->drop(); - delete[] text; - } - - // find missing mods (mentioned in world.mt, but not installed) - std::set missing_mods; for(std::set::iterator it = mod_names.begin(); it != mod_names.end(); ++it) { std::string modname = *it; if(m_addonmods.count(modname) == 0) - missing_mods.insert(modname); + m_settings.remove("load_mod_"+modname); } - if(!missing_mods.empty()) - { - wchar_t* text = wgettext("Warning: Some configured mods are missing.\n" - "Their setting will be removed when you save the configuration. "); - GUIMessageMenu *menu = - new GUIMessageMenu(Environment, Parent, -1, m_menumgr, text); - delete[] text; - for(std::set::iterator it = missing_mods.begin(); - it != missing_mods.end(); ++it) - m_settings.remove("load_mod_"+(*it)); - menu->drop(); - } + std::string worldmtfile = m_wspec.path+DIR_DELIM+"world.mt"; + m_settings.updateConfigFile(worldmtfile.c_str()); } void GUIConfigureWorld::drawMenu() @@ -388,11 +366,6 @@ bool GUIConfigureWorld::OnEvent(const SEvent& event) return true; } case GUI_ID_SAVE: { - for(std::set::iterator it = m_new_mod_names.begin(); - it!= m_new_mod_names.end(); ++it) - { - m_settings.setBool("load_mod_"+(*it),true); - } std::string worldmtfile = m_wspec.path+DIR_DELIM+"world.mt"; m_settings.updateConfigFile(worldmtfile.c_str()); @@ -558,22 +531,14 @@ void GUIConfigureWorld::buildTreeView(std::map mods, buildTreeView(mod.modpack_content, new_node); else { - // set icon for node: ? for new mods, x for disabled mods, - // checkmark for enabled mods - if(m_new_mod_names.count(modname) > 0) - { - new_node->setIcon(QUESTIONMARK_STR); - } + // set icon for node: x for disabled mods, checkmark for enabled mods + bool mod_enabled = false; + if(m_settings.exists("load_mod_"+modname)) + mod_enabled = m_settings.getBool("load_mod_"+modname); + if(mod_enabled) + new_node->setIcon(CHECKMARK_STR); else - { - bool mod_enabled = true; - if(m_settings.exists("load_mod_"+modname)) - mod_enabled = m_settings.getBool("load_mod_"+modname); - if(mod_enabled) - new_node->setIcon(CHECKMARK_STR); - else - new_node->setIcon(CROSS_STR); - } + new_node->setIcon(CROSS_STR); } } } @@ -690,7 +655,6 @@ void GUIConfigureWorld::enableMod(std::string modname) m_nodes.find(modname); if(it != m_nodes.end()) (*it).second->setIcon(CHECKMARK_STR); - m_new_mod_names.erase(modname); //also enable all dependencies for(std::set::iterator it=mspec.depends.begin(); it != mspec.depends.end(); ++it) @@ -715,7 +679,6 @@ void GUIConfigureWorld::disableMod(std::string modname) m_nodes.find(modname); if(it != m_nodes.end()) (*it).second->setIcon(CROSS_STR); - m_new_mod_names.erase(modname); //also disable all mods that depend on this one std::pair::iterator, std::multimap::iterator > rdep = diff --git a/src/guiConfigureWorld.h b/src/guiConfigureWorld.h index 8a77c5f89..23ebac66d 100644 --- a/src/guiConfigureWorld.h +++ b/src/guiConfigureWorld.h @@ -69,9 +69,6 @@ private: // the settings in the world.mt file Settings m_settings; - // mods that are installed but not mentioned in world.mt file - std::set m_new_mod_names; - // maps modnames to nodes in m_treeview std::map m_nodes; diff --git a/src/subgame.cpp b/src/subgame.cpp index cdb546619..7fee3899d 100644 --- a/src/subgame.cpp +++ b/src/subgame.cpp @@ -91,9 +91,9 @@ SubgameSpec findSubgame(const std::string &id) // Find mod directories std::set mods_paths; if(!user_game) - mods_paths.insert(share + DIR_DELIM + "mods" + DIR_DELIM + id); + mods_paths.insert(share + DIR_DELIM + "mods"); if(user != share || user_game) - mods_paths.insert(user + DIR_DELIM + "mods" + DIR_DELIM + id); + mods_paths.insert(user + DIR_DELIM + "mods"); std::string game_name = getGameName(game_path); if(game_name == "") game_name = id; -- cgit v1.2.3 From f577facf79729a03bb274a27c9f50f0092cd3a40 Mon Sep 17 00:00:00 2001 From: kwolekr Date: Sun, 19 May 2013 12:07:00 -0400 Subject: Fix regression of world loading caused by 81c863ac --- src/game.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/game.cpp b/src/game.cpp index f63a4a400..746769aee 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -1042,7 +1042,7 @@ void the_game( u32 lasttime = device->getTimer()->getTime(); while(device->run()) { - f32 dtime=0; // in seconds + f32 dtime = 0.033; // in seconds if (cloud_menu_background) { u32 time = device->getTimer()->getTime(); if(time > lasttime) @@ -1136,7 +1136,7 @@ void the_game( u32 lasttime = device->getTimer()->getTime(); while(device->run()) { - f32 dtime=0; // in seconds + f32 dtime = 0.033; // in seconds if (cloud_menu_background) { u32 time = device->getTimer()->getTime(); if(time > lasttime) -- cgit v1.2.3 From 93474c4218eee621a96e24324b1b41a55571f0df Mon Sep 17 00:00:00 2001 From: kwolekr Date: Sat, 18 May 2013 23:26:27 -0400 Subject: Remove no virtual dtor warnings, make MapgenParams contain actual NoiseParams --- src/mapgen.cpp | 52 ++++++++++++++--------------- src/mapgen.h | 10 +++++- src/mapgen_indev.cpp | 88 ++++++++++++++++++++++--------------------------- src/mapgen_indev.h | 59 +++++++++++++++++---------------- src/mapgen_singlenode.h | 4 +-- src/mapgen_v6.cpp | 24 +++++++------- src/mapgen_v6.h | 47 +++++++++++++------------- src/mapgen_v7.cpp | 12 +++---- src/mapgen_v7.h | 26 ++++++++------- src/noise.h | 6 ++-- src/settings.h | 37 +++++++++++---------- 11 files changed, 185 insertions(+), 180 deletions(-) (limited to 'src') diff --git a/src/mapgen.cpp b/src/mapgen.cpp index 0646a8826..835c14be1 100644 --- a/src/mapgen.cpp +++ b/src/mapgen.cpp @@ -71,6 +71,12 @@ Ore *createOre(OreType type) { } +Ore::~Ore() { + delete np; + delete noise; +} + + void Ore::resolveNodeNames(INodeDefManager *ndef) { if (ore == CONTENT_IGNORE) { ore = ndef->getId(ore_name); @@ -347,23 +353,18 @@ bool MapgenV6Params::readParams(Settings *settings) { freq_desert = settings->getFloat("mgv6_freq_desert"); freq_beach = settings->getFloat("mgv6_freq_beach"); - np_terrain_base = settings->getNoiseParams("mgv6_np_terrain_base"); - np_terrain_higher = settings->getNoiseParams("mgv6_np_terrain_higher"); - np_steepness = settings->getNoiseParams("mgv6_np_steepness"); - np_height_select = settings->getNoiseParams("mgv6_np_height_select"); - np_mud = settings->getNoiseParams("mgv6_np_mud"); - np_beach = settings->getNoiseParams("mgv6_np_beach"); - np_biome = settings->getNoiseParams("mgv6_np_biome"); - np_cave = settings->getNoiseParams("mgv6_np_cave"); - np_humidity = settings->getNoiseParams("mgv6_np_humidity"); - np_trees = settings->getNoiseParams("mgv6_np_trees"); - np_apple_trees = settings->getNoiseParams("mgv6_np_apple_trees"); - - bool success = - np_terrain_base && np_terrain_higher && np_steepness && - np_height_select && np_trees && np_mud && - np_beach && np_biome && np_cave && - np_humidity && np_apple_trees; + bool success = + settings->getNoiseParams("mgv6_np_terrain_base", np_terrain_base) && + settings->getNoiseParams("mgv6_np_terrain_higher", np_terrain_higher) && + settings->getNoiseParams("mgv6_np_steepness", np_steepness) && + settings->getNoiseParams("mgv6_np_height_select", np_height_select) && + settings->getNoiseParams("mgv6_np_mud", np_mud) && + settings->getNoiseParams("mgv6_np_beach", np_beach) && + settings->getNoiseParams("mgv6_np_biome", np_biome) && + settings->getNoiseParams("mgv6_np_cave", np_cave) && + settings->getNoiseParams("mgv6_np_humidity", np_humidity) && + settings->getNoiseParams("mgv6_np_trees", np_trees) && + settings->getNoiseParams("mgv6_np_apple_trees", np_apple_trees); return success; } @@ -387,16 +388,13 @@ void MapgenV6Params::writeParams(Settings *settings) { bool MapgenV7Params::readParams(Settings *settings) { - np_terrain_base = settings->getNoiseParams("mgv7_np_terrain_base"); - np_terrain_alt = settings->getNoiseParams("mgv7_np_terrain_alt"); - np_terrain_mod = settings->getNoiseParams("mgv7_np_terrain_mod"); - np_terrain_persist = settings->getNoiseParams("mgv7_np_terrain_persist"); - np_height_select = settings->getNoiseParams("mgv7_np_height_select"); - np_ridge = settings->getNoiseParams("mgv7_np_ridge"); - - bool success = - np_terrain_base && np_terrain_alt && np_terrain_mod && - np_terrain_persist && np_height_select && np_ridge; + bool success = + settings->getNoiseParams("mgv7_np_terrain_base", np_terrain_base) && + settings->getNoiseParams("mgv7_np_terrain_alt", np_terrain_alt) && + settings->getNoiseParams("mgv7_np_terrain_mod", np_terrain_mod) && + settings->getNoiseParams("mgv7_np_terrain_persist", np_terrain_persist) && + settings->getNoiseParams("mgv7_np_height_select", np_height_select) && + settings->getNoiseParams("mgv7_np_ridge", np_ridge); return success; } diff --git a/src/mapgen.h b/src/mapgen.h index 17136a137..5d1e3bdf0 100644 --- a/src/mapgen.h +++ b/src/mapgen.h @@ -74,7 +74,8 @@ struct MapgenParams { } virtual bool readParams(Settings *settings) = 0; - virtual void writeParams(Settings *settings) {}; + virtual void writeParams(Settings *settings) = 0; + virtual ~MapgenParams() {} }; class Mapgen { @@ -86,6 +87,8 @@ public: ManualMapVoxelManipulator *vm; INodeDefManager *ndef; + virtual ~Mapgen() {} + void updateLiquid(UniqueQueue *trans_liquid, v3s16 nmin, v3s16 nmax); void setLighting(v3s16 nmin, v3s16 nmax, u8 light); void lightSpread(VoxelArea &a, v3s16 p, u8 light); @@ -105,6 +108,7 @@ struct MapgenFactory { virtual Mapgen *createMapgen(int mgid, MapgenParams *params, EmergeManager *emerge) = 0; virtual MapgenParams *createMapgenParams() = 0; + virtual ~MapgenFactory() {} }; enum OreType { @@ -140,6 +144,8 @@ public: noise = NULL; } + virtual ~Ore(); + void resolveNodeNames(INodeDefManager *ndef); void placeOre(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax); virtual void generate(ManualMapVoxelManipulator *vm, int seed, @@ -147,11 +153,13 @@ public: }; class OreScatter : public Ore { + ~OreScatter() {} virtual void generate(ManualMapVoxelManipulator *vm, int seed, u32 blockseed, v3s16 nmin, v3s16 nmax); }; class OreSheet : public Ore { + ~OreSheet() {} virtual void generate(ManualMapVoxelManipulator *vm, int seed, u32 blockseed, v3s16 nmin, v3s16 nmax); }; diff --git a/src/mapgen_indev.cpp b/src/mapgen_indev.cpp index 2eeaf13eb..430359be2 100644 --- a/src/mapgen_indev.cpp +++ b/src/mapgen_indev.cpp @@ -84,17 +84,14 @@ void NoiseIndev::transformNoiseMapFarScale(float xx, float yy, float zz) { MapgenIndev::MapgenIndev(int mapgenid, MapgenIndevParams *params, EmergeManager *emerge) : MapgenV6(mapgenid, params, emerge) { - noiseindev_terrain_base = new NoiseIndev(params->npindev_terrain_base, seed, csize.X, csize.Z); - noiseindev_terrain_higher = new NoiseIndev(params->npindev_terrain_higher, seed, csize.X, csize.Z); - noiseindev_steepness = new NoiseIndev(params->npindev_steepness, seed, csize.X, csize.Z); -// noise_height_select = new Noise(params->np_height_select, seed, csize.X, csize.Y); -// noise_trees = new Noise(params->np_trees, seed, csize.X, csize.Y); - noiseindev_mud = new NoiseIndev(params->npindev_mud, seed, csize.X, csize.Z); -// noise_beach = new Noise(params->np_beach, seed, csize.X, csize.Y); - noiseindev_float_islands1 = new NoiseIndev(params->npindev_float_islands1, seed, csize.X, csize.Y, csize.Z); - noiseindev_float_islands2 = new NoiseIndev(params->npindev_float_islands2, seed, csize.X, csize.Y, csize.Z); - noiseindev_float_islands3 = new NoiseIndev(params->npindev_float_islands3, seed, csize.X, csize.Z); - noiseindev_biome = new NoiseIndev(params->npindev_biome, seed, csize.X, csize.Z); + noiseindev_terrain_base = new NoiseIndev(¶ms->npindev_terrain_base, seed, csize.X, csize.Z); + noiseindev_terrain_higher = new NoiseIndev(¶ms->npindev_terrain_higher, seed, csize.X, csize.Z); + noiseindev_steepness = new NoiseIndev(¶ms->npindev_steepness, seed, csize.X, csize.Z); + noiseindev_mud = new NoiseIndev(¶ms->npindev_mud, seed, csize.X, csize.Z); + noiseindev_float_islands1 = new NoiseIndev(¶ms->npindev_float_islands1, seed, csize.X, csize.Y, csize.Z); + noiseindev_float_islands2 = new NoiseIndev(¶ms->npindev_float_islands2, seed, csize.X, csize.Y, csize.Z); + noiseindev_float_islands3 = new NoiseIndev(¶ms->npindev_float_islands3, seed, csize.X, csize.Z); + noiseindev_biome = new NoiseIndev(¶ms->npindev_biome, seed, csize.X, csize.Z); } MapgenIndev::~MapgenIndev() { @@ -170,46 +167,41 @@ void MapgenIndev::calculateNoise() { } bool MapgenIndevParams::readParams(Settings *settings) { - freq_desert = settings->getFloat("mgv6_freq_desert"); - freq_beach = settings->getFloat("mgv6_freq_beach"); - - npindev_terrain_base = settings->getNoiseIndevParams("mgindev_np_terrain_base"); - npindev_terrain_higher = settings->getNoiseIndevParams("mgindev_np_terrain_higher"); - npindev_steepness = settings->getNoiseIndevParams("mgindev_np_steepness"); - np_height_select = settings->getNoiseParams("mgv6_np_height_select"); - np_trees = settings->getNoiseParams("mgv6_np_trees"); - npindev_mud = settings->getNoiseIndevParams("mgindev_np_mud"); - np_beach = settings->getNoiseParams("mgv6_np_beach"); - npindev_biome = settings->getNoiseIndevParams("mgindev_np_biome"); - np_cave = settings->getNoiseParams("mgv6_np_cave"); - npindev_float_islands1 = settings->getNoiseIndevParams("mgindev_np_float_islands1"); - npindev_float_islands2 = settings->getNoiseIndevParams("mgindev_np_float_islands2"); - npindev_float_islands3 = settings->getNoiseIndevParams("mgindev_np_float_islands3"); - - bool success = - npindev_terrain_base && npindev_terrain_higher && npindev_steepness && - np_height_select && np_trees && npindev_mud && - np_beach && np_biome && np_cave && - npindev_float_islands1 && npindev_float_islands2 && npindev_float_islands3; - return success; + freq_desert = settings->getFloat("mgv6_freq_desert"); + freq_beach = settings->getFloat("mgv6_freq_beach"); + + bool success = + settings->getNoiseIndevParams("mgindev_np_terrain_base", npindev_terrain_base) && + settings->getNoiseIndevParams("mgindev_np_terrain_higher", npindev_terrain_higher) && + settings->getNoiseIndevParams("mgindev_np_steepness", npindev_steepness) && + settings->getNoiseParams("mgv6_np_height_select", np_height_select) && + settings->getNoiseParams("mgv6_np_trees", np_trees) && + settings->getNoiseIndevParams("mgindev_np_mud", npindev_mud) && + settings->getNoiseParams("mgv6_np_beach", np_beach) && + settings->getNoiseIndevParams("mgindev_np_biome", npindev_biome) && + settings->getNoiseParams("mgv6_np_cave", np_cave) && + settings->getNoiseIndevParams("mgindev_np_float_islands1", npindev_float_islands1) && + settings->getNoiseIndevParams("mgindev_np_float_islands2", npindev_float_islands2) && + settings->getNoiseIndevParams("mgindev_np_float_islands3", npindev_float_islands3); + return success; } void MapgenIndevParams::writeParams(Settings *settings) { - settings->setFloat("mgv6_freq_desert", freq_desert); - settings->setFloat("mgv6_freq_beach", freq_beach); - - settings->setNoiseIndevParams("mgindev_np_terrain_base", npindev_terrain_base); - settings->setNoiseIndevParams("mgindev_np_terrain_higher", npindev_terrain_higher); - settings->setNoiseIndevParams("mgindev_np_steepness", npindev_steepness); - settings->setNoiseParams("mgv6_np_height_select", np_height_select); - settings->setNoiseParams("mgv6_np_trees", np_trees); - settings->setNoiseIndevParams("mgindev_np_mud", npindev_mud); - settings->setNoiseParams("mgv6_np_beach", np_beach); - settings->setNoiseIndevParams("mgindev_np_biome", npindev_biome); - settings->setNoiseParams("mgv6_np_cave", np_cave); - settings->setNoiseIndevParams("mgindev_np_float_islands1", npindev_float_islands1); - settings->setNoiseIndevParams("mgindev_np_float_islands2", npindev_float_islands2); - settings->setNoiseIndevParams("mgindev_np_float_islands3", npindev_float_islands3); + settings->setFloat("mgv6_freq_desert", freq_desert); + settings->setFloat("mgv6_freq_beach", freq_beach); + + settings->setNoiseIndevParams("mgindev_np_terrain_base", npindev_terrain_base); + settings->setNoiseIndevParams("mgindev_np_terrain_higher", npindev_terrain_higher); + settings->setNoiseIndevParams("mgindev_np_steepness", npindev_steepness); + settings->setNoiseParams("mgv6_np_height_select", np_height_select); + settings->setNoiseParams("mgv6_np_trees", np_trees); + settings->setNoiseIndevParams("mgindev_np_mud", npindev_mud); + settings->setNoiseParams("mgv6_np_beach", np_beach); + settings->setNoiseIndevParams("mgindev_np_biome", npindev_biome); + settings->setNoiseParams("mgv6_np_cave", np_cave); + settings->setNoiseIndevParams("mgindev_np_float_islands1", npindev_float_islands1); + settings->setNoiseIndevParams("mgindev_np_float_islands2", npindev_float_islands2); + settings->setNoiseIndevParams("mgindev_np_float_islands3", npindev_float_islands3); } diff --git a/src/mapgen_indev.h b/src/mapgen_indev.h index 87ae39d09..cfef59041 100644 --- a/src/mapgen_indev.h +++ b/src/mapgen_indev.h @@ -32,30 +32,33 @@ struct NoiseIndevParams : public NoiseParams { float farscale; float farspread; - NoiseIndevParams(){} - NoiseIndevParams(float offset_, float scale_, v3f spread_, int seed_, int octaves_, float persist_, float farscale_ = 1, float farspread_ = 1) + NoiseIndevParams() {} + NoiseIndevParams(float offset_, float scale_, v3f spread_, + int seed_, int octaves_, float persist_, + float farscale_ = 1, float farspread_ = 1) { - offset = offset_; - scale = scale_; - spread = spread_; - seed = seed_; + offset = offset_; + scale = scale_; + spread = spread_; + seed = seed_; octaves = octaves_; persist = persist_; - farscale = farscale_; + farscale = farscale_; farspread = farspread_; } - + + ~NoiseIndevParams() {} }; -#define getNoiseIndevParams(x) getStruct((x), "f,f,v3,s32,s32,f,f,f") -#define setNoiseIndevParams(x, y) setStruct((x), "f,f,v3,s32,s32,f,f,f", (y)) +#define getNoiseIndevParams(x, y) getStruct((x), "f,f,v3,s32,s32,f,f,f", &(y), sizeof(y)) +#define setNoiseIndevParams(x, y) setStruct((x), "f,f,v3,s32,s32,f,f,f", &(y)) class NoiseIndev : public Noise { - public: +public: NoiseIndevParams *npindev; - //NoiseIndev() {}; + virtual ~NoiseIndev() {}; NoiseIndev(NoiseIndevParams *np, int seed, int sx, int sy); NoiseIndev(NoiseIndevParams *np, int seed, int sx, int sy, int sz); void init(NoiseIndevParams *np, int seed, int sx, int sy, int sz); @@ -77,34 +80,34 @@ extern NoiseIndevParams nparams_indev_def_float_islands; */ struct MapgenIndevParams : public MapgenV6Params { - NoiseIndevParams *npindev_terrain_base; - NoiseIndevParams *npindev_terrain_higher; - NoiseIndevParams *npindev_steepness; + NoiseIndevParams npindev_terrain_base; + NoiseIndevParams npindev_terrain_higher; + NoiseIndevParams npindev_steepness; //NoiseParams *np_height_select; //NoiseParams *np_trees; - NoiseIndevParams *npindev_mud; + NoiseIndevParams npindev_mud; //NoiseParams *np_beach; - NoiseIndevParams *npindev_biome; + NoiseIndevParams npindev_biome; //NoiseParams *np_cave; - NoiseIndevParams *npindev_float_islands1; - NoiseIndevParams *npindev_float_islands2; - NoiseIndevParams *npindev_float_islands3; + NoiseIndevParams npindev_float_islands1; + NoiseIndevParams npindev_float_islands2; + NoiseIndevParams npindev_float_islands3; MapgenIndevParams() { //freq_desert = 0.45; //freq_beach = 0.15; - npindev_terrain_base = &nparams_indev_def; //&nparams_indev_def_terrain_base; - npindev_terrain_higher = &nparams_indev_def; //&nparams_indev_def_terrain_higher; - npindev_steepness = &nparams_indev_def; //&nparams_indev_def_steepness; + npindev_terrain_base = nparams_indev_def; //&nparams_indev_def_terrain_base; + npindev_terrain_higher = nparams_indev_def; //&nparams_indev_def_terrain_higher; + npindev_steepness = nparams_indev_def; //&nparams_indev_def_steepness; //np_height_select = &nparams_v6_def_height_select; //np_trees = &nparams_v6_def_trees; - npindev_mud = &nparams_indev_def; //&nparams_indev_def_mud; + npindev_mud = nparams_indev_def; //&nparams_indev_def_mud; //np_beach = &nparams_v6_def_beach; - npindev_biome = &nparams_indev_def; //&nparams_indev_def_biome; + npindev_biome = nparams_indev_def; //&nparams_indev_def_biome; //np_cave = &nparams_v6_def_cave; - npindev_float_islands1 = &nparams_indev_def; //&nparams_indev_def_float_islands; - npindev_float_islands2 = &nparams_indev_def; //&nparams_indev_def_float_islands; - npindev_float_islands3 = &nparams_indev_def; //&nparams_indev_def_float_islands; + npindev_float_islands1 = nparams_indev_def; //&nparams_indev_def_float_islands; + npindev_float_islands2 = nparams_indev_def; //&nparams_indev_def_float_islands; + npindev_float_islands3 = nparams_indev_def; //&nparams_indev_def_float_islands; } diff --git a/src/mapgen_singlenode.h b/src/mapgen_singlenode.h index b86c9a77f..8b816aa25 100644 --- a/src/mapgen_singlenode.h +++ b/src/mapgen_singlenode.h @@ -24,8 +24,8 @@ with this program; if not, write to the Free Software Foundation, Inc., struct MapgenSinglenodeParams : public MapgenParams { - MapgenSinglenodeParams() { - } + MapgenSinglenodeParams() {} + ~MapgenSinglenodeParams() {} bool readParams(Settings *settings); void writeParams(Settings *settings); diff --git a/src/mapgen_v6.cpp b/src/mapgen_v6.cpp index d90d142d5..e5ff72a60 100644 --- a/src/mapgen_v6.cpp +++ b/src/mapgen_v6.cpp @@ -80,18 +80,18 @@ MapgenV6::MapgenV6(int mapgenid, MapgenV6Params *params, EmergeManager *emerge) this->ystride = csize.X; //////fix this - np_cave = params->np_cave; - np_humidity = params->np_humidity; - np_trees = params->np_trees; - np_apple_trees = params->np_apple_trees; - - noise_terrain_base = new Noise(params->np_terrain_base, seed, csize.X, csize.Y); - noise_terrain_higher = new Noise(params->np_terrain_higher, seed, csize.X, csize.Y); - noise_steepness = new Noise(params->np_steepness, seed, csize.X, csize.Y); - noise_height_select = new Noise(params->np_height_select, seed, csize.X, csize.Y); - noise_mud = new Noise(params->np_mud, seed, csize.X, csize.Y); - noise_beach = new Noise(params->np_beach, seed, csize.X, csize.Y); - noise_biome = new Noise(params->np_biome, seed, csize.X, csize.Y); + np_cave = ¶ms->np_cave; + np_humidity = ¶ms->np_humidity; + np_trees = ¶ms->np_trees; + np_apple_trees = ¶ms->np_apple_trees; + + noise_terrain_base = new Noise(¶ms->np_terrain_base, seed, csize.X, csize.Y); + noise_terrain_higher = new Noise(¶ms->np_terrain_higher, seed, csize.X, csize.Y); + noise_steepness = new Noise(¶ms->np_steepness, seed, csize.X, csize.Y); + noise_height_select = new Noise(¶ms->np_height_select, seed, csize.X, csize.Y); + noise_mud = new Noise(¶ms->np_mud, seed, csize.X, csize.Y); + noise_beach = new Noise(¶ms->np_beach, seed, csize.X, csize.Y); + noise_biome = new Noise(¶ms->np_biome, seed, csize.X, csize.Y); } diff --git a/src/mapgen_v6.h b/src/mapgen_v6.h index a0276fb59..8f456fd3f 100644 --- a/src/mapgen_v6.h +++ b/src/mapgen_v6.h @@ -45,35 +45,36 @@ extern NoiseParams nparams_v6_def_apple_trees; struct MapgenV6Params : public MapgenParams { float freq_desert; float freq_beach; - NoiseParams *np_terrain_base; - NoiseParams *np_terrain_higher; - NoiseParams *np_steepness; - NoiseParams *np_height_select; - NoiseParams *np_mud; - NoiseParams *np_beach; - NoiseParams *np_biome; - NoiseParams *np_cave; - NoiseParams *np_humidity; - NoiseParams *np_trees; - NoiseParams *np_apple_trees; + NoiseParams np_terrain_base; + NoiseParams np_terrain_higher; + NoiseParams np_steepness; + NoiseParams np_height_select; + NoiseParams np_mud; + NoiseParams np_beach; + NoiseParams np_biome; + NoiseParams np_cave; + NoiseParams np_humidity; + NoiseParams np_trees; + NoiseParams np_apple_trees; MapgenV6Params() { freq_desert = 0.45; freq_beach = 0.15; - np_terrain_base = &nparams_v6_def_terrain_base; - np_terrain_higher = &nparams_v6_def_terrain_higher; - np_steepness = &nparams_v6_def_steepness; - np_height_select = &nparams_v6_def_height_select; - np_mud = &nparams_v6_def_mud; - np_beach = &nparams_v6_def_beach; - np_biome = &nparams_v6_def_biome; - np_cave = &nparams_v6_def_cave; - np_humidity = &nparams_v6_def_humidity; - np_trees = &nparams_v6_def_trees; - np_apple_trees = &nparams_v6_def_apple_trees; - + np_terrain_base = nparams_v6_def_terrain_base; + np_terrain_higher = nparams_v6_def_terrain_higher; + np_steepness = nparams_v6_def_steepness; + np_height_select = nparams_v6_def_height_select; + np_mud = nparams_v6_def_mud; + np_beach = nparams_v6_def_beach; + np_biome = nparams_v6_def_biome; + np_cave = nparams_v6_def_cave; + np_humidity = nparams_v6_def_humidity; + np_trees = nparams_v6_def_trees; + np_apple_trees = nparams_v6_def_apple_trees; } + ~MapgenV6Params() {} + bool readParams(Settings *settings); void writeParams(Settings *settings); }; diff --git a/src/mapgen_v7.cpp b/src/mapgen_v7.cpp index 4bfc866e2..2fb5d7b9b 100644 --- a/src/mapgen_v7.cpp +++ b/src/mapgen_v7.cpp @@ -85,12 +85,12 @@ MapgenV7::MapgenV7(int mapgenid, MapgenV7Params *params, EmergeManager *emerge) this->ridge_heightmap = new s16[csize.X * csize.Z]; // Terrain noise - noise_terrain_base = new Noise(params->np_terrain_base, seed, csize.X, csize.Z); - noise_terrain_alt = new Noise(params->np_terrain_alt, seed, csize.X, csize.Z); - noise_terrain_mod = new Noise(params->np_terrain_mod, seed, csize.X, csize.Z); - noise_terrain_persist = new Noise(params->np_terrain_persist, seed, csize.X, csize.Z); - noise_height_select = new Noise(params->np_height_select, seed, csize.X, csize.Z); - noise_ridge = new Noise(params->np_ridge, seed, csize.X, csize.Y, csize.Z); + noise_terrain_base = new Noise(¶ms->np_terrain_base, seed, csize.X, csize.Z); + noise_terrain_alt = new Noise(¶ms->np_terrain_alt, seed, csize.X, csize.Z); + noise_terrain_mod = new Noise(¶ms->np_terrain_mod, seed, csize.X, csize.Z); + noise_terrain_persist = new Noise(¶ms->np_terrain_persist, seed, csize.X, csize.Z); + noise_height_select = new Noise(¶ms->np_height_select, seed, csize.X, csize.Z); + noise_ridge = new Noise(¶ms->np_ridge, seed, csize.X, csize.Y, csize.Z); // Biome noise noise_heat = new Noise(bmgr->np_heat, seed, csize.X, csize.Z); diff --git a/src/mapgen_v7.h b/src/mapgen_v7.h index 3391098ea..b6b03689d 100644 --- a/src/mapgen_v7.h +++ b/src/mapgen_v7.h @@ -30,22 +30,24 @@ extern NoiseParams nparams_v7_def_height_select; extern NoiseParams nparams_v7_def_ridge; struct MapgenV7Params : public MapgenParams { - NoiseParams *np_terrain_base; - NoiseParams *np_terrain_alt; - NoiseParams *np_terrain_mod; - NoiseParams *np_terrain_persist; - NoiseParams *np_height_select; - NoiseParams *np_ridge; + NoiseParams np_terrain_base; + NoiseParams np_terrain_alt; + NoiseParams np_terrain_mod; + NoiseParams np_terrain_persist; + NoiseParams np_height_select; + NoiseParams np_ridge; MapgenV7Params() { - np_terrain_base = &nparams_v7_def_terrain_base; - np_terrain_alt = &nparams_v7_def_terrain_alt; - np_terrain_mod = &nparams_v7_def_terrain_mod; - np_terrain_persist = &nparams_v7_def_terrain_persist; - np_height_select = &nparams_v7_def_height_select; - np_ridge = &nparams_v7_def_ridge; + np_terrain_base = nparams_v7_def_terrain_base; + np_terrain_alt = nparams_v7_def_terrain_alt; + np_terrain_mod = nparams_v7_def_terrain_mod; + np_terrain_persist = nparams_v7_def_terrain_persist; + np_height_select = nparams_v7_def_height_select; + np_ridge = nparams_v7_def_ridge; } + ~MapgenV7Params() {} + bool readParams(Settings *settings); void writeParams(Settings *settings); }; diff --git a/src/noise.h b/src/noise.h index ace6d7eb4..0bf1a2f13 100644 --- a/src/noise.h +++ b/src/noise.h @@ -72,8 +72,8 @@ struct NoiseParams { // Convenience macros for getting/setting NoiseParams in Settings -#define getNoiseParams(x) getStruct((x), "f,f,v3,s32,s32,f") -#define setNoiseParams(x, y) setStruct((x), "f,f,v3,s32,s32,f", (y)) +#define getNoiseParams(x, y) getStruct((x), "f,f,v3,s32,s32,f", &(y), sizeof(y)) +#define setNoiseParams(x, y) setStruct((x), "f,f,v3,s32,s32,f", &(y)) class Noise { public: @@ -88,7 +88,7 @@ public: Noise(NoiseParams *np, int seed, int sx, int sy); Noise(NoiseParams *np, int seed, int sx, int sy, int sz); - ~Noise(); + virtual ~Noise(); virtual void init(NoiseParams *np, int seed, int sx, int sy, int sz); void setSize(int sx, int sy); diff --git a/src/settings.h b/src/settings.h index 1b7e3cb09..e7b49b6d7 100644 --- a/src/settings.h +++ b/src/settings.h @@ -577,15 +577,15 @@ public: return (isdigit(val[0])) ? stoi(val) : readFlagString(val, flagdesc); } - template T *getStruct(std::string name, std::string format) + bool getStruct(std::string name, std::string format, void *out, size_t olen) { - size_t len = sizeof(T); + size_t len = olen; std::vector strs_alloced; std::string *str; std::string valstr = get(name); char *s = &valstr[0]; - T *buf = new T; - char *bufpos = (char *)buf; + char *buf = new char[len]; + char *bufpos = buf; char *f, *snext; size_t pos; @@ -608,7 +608,7 @@ public: case 'i': if (width == 16) { bufpos += PADDING(bufpos, u16); - if ((bufpos - (char *)buf) + sizeof(u16) <= len) { + if ((bufpos - buf) + sizeof(u16) <= len) { if (is_unsigned) *(u16 *)bufpos = (u16)strtoul(s, &s, 10); else @@ -617,7 +617,7 @@ public: bufpos += sizeof(u16); } else if (width == 32) { bufpos += PADDING(bufpos, u32); - if ((bufpos - (char *)buf) + sizeof(u32) <= len) { + if ((bufpos - buf) + sizeof(u32) <= len) { if (is_unsigned) *(u32 *)bufpos = (u32)strtoul(s, &s, 10); else @@ -626,7 +626,7 @@ public: bufpos += sizeof(u32); } else if (width == 64) { bufpos += PADDING(bufpos, u64); - if ((bufpos - (char *)buf) + sizeof(u64) <= len) { + if ((bufpos - buf) + sizeof(u64) <= len) { if (is_unsigned) *(u64 *)bufpos = (u64)strtoull(s, &s, 10); else @@ -642,7 +642,7 @@ public: *snext++ = 0; bufpos += PADDING(bufpos, bool); - if ((bufpos - (char *)buf) + sizeof(bool) <= len) + if ((bufpos - buf) + sizeof(bool) <= len) *(bool *)bufpos = is_yes(std::string(s)); bufpos += sizeof(bool); @@ -650,7 +650,7 @@ public: break; case 'f': bufpos += PADDING(bufpos, float); - if ((bufpos - (char *)buf) + sizeof(float) <= len) + if ((bufpos - buf) + sizeof(float) <= len) *(float *)bufpos = strtof(s, &s); bufpos += sizeof(float); @@ -674,7 +674,7 @@ public: while ((pos = str->find("\\\"", pos)) != std::string::npos) str->erase(pos, 1); - if ((bufpos - (char *)buf) + sizeof(std::string *) <= len) + if ((bufpos - buf) + sizeof(std::string *) <= len) *(std::string **)bufpos = str; bufpos += sizeof(std::string *); strs_alloced.push_back(str); @@ -690,7 +690,7 @@ public: if (width == 2) { bufpos += PADDING(bufpos, v2f); - if ((bufpos - (char *)buf) + sizeof(v2f) <= len) { + if ((bufpos - buf) + sizeof(v2f) <= len) { v2f *v = (v2f *)bufpos; v->X = strtof(s, &s); s++; @@ -700,7 +700,7 @@ public: bufpos += sizeof(v2f); } else if (width == 3) { bufpos += PADDING(bufpos, v3f); - if ((bufpos - (char *)buf) + sizeof(v3f) <= len) { + if ((bufpos - buf) + sizeof(v3f) <= len) { v3f *v = (v3f *)bufpos; v->X = strtof(s, &s); s++; @@ -720,20 +720,21 @@ public: if (s && *s == ',') s++; - if ((size_t)(bufpos - (char *)buf) > len) //error, buffer too small + if ((size_t)(bufpos - buf) > len) //error, buffer too small goto fail; } if (f && *f) { //error, mismatched number of fields and values fail: - for (unsigned int i = 0; i != strs_alloced.size(); i++) + for (size_t i = 0; i != strs_alloced.size(); i++) delete strs_alloced[i]; - delete buf; - //delete[] buf; - buf = NULL; + delete[] buf; + return false; } - return buf; + memcpy(out, buf, olen); + delete[] buf; + return true; } bool setStruct(std::string name, std::string format, void *value) -- cgit v1.2.3 From dcd0b63f645bccf497a030b6b1cec97178542eb1 Mon Sep 17 00:00:00 2001 From: PilzAdam Date: Sun, 19 May 2013 19:46:50 +0200 Subject: Dont load mods that have no entry in world.mt --- src/mods.cpp | 11 +++++------ src/server.cpp | 10 ++-------- 2 files changed, 7 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/mods.cpp b/src/mods.cpp index 64c319992..a0a37afb9 100644 --- a/src/mods.cpp +++ b/src/mods.cpp @@ -220,7 +220,7 @@ ModConfiguration::ModConfiguration(std::string worldpath) Settings worldmt_settings; worldmt_settings.readConfigFile(worldmt.c_str()); std::vector names = worldmt_settings.getNames(); - std::set exclude_mod_names; + std::set include_mod_names; for(std::vector::iterator it = names.begin(); it != names.end(); ++it) { @@ -229,14 +229,13 @@ ModConfiguration::ModConfiguration(std::string worldpath) // explicitely excluded. if mod is not mentioned at all, it is // enabled. So by default, all installed mods are enabled. if (name.compare(0,9,"load_mod_") == 0 && - !worldmt_settings.getBool(name)) + worldmt_settings.getBool(name)) { - exclude_mod_names.insert(name.substr(9)); + include_mod_names.insert(name.substr(9)); } } - // Collect all mods in gamespec.addon_mods_paths, - // excluding those in the set exclude_mod_names + // Collect all mods that are also in include_mod_names std::vector addon_mods; for(std::set::const_iterator it_path = gamespec.addon_mods_paths.begin(); it_path != gamespec.addon_mods_paths.end(); ++it_path) @@ -246,7 +245,7 @@ ModConfiguration::ModConfiguration(std::string worldpath) it != addon_mods_in_path.end(); ++it) { ModSpec& mod = *it; - if(exclude_mod_names.count(mod.name) == 0) + if(include_mod_names.count(mod.name) != 0) addon_mods.push_back(mod); } } diff --git a/src/server.cpp b/src/server.cpp index 40a4f8a02..0d724b1cb 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -727,19 +727,13 @@ Server::Server( std::string worldmt = m_path_world + DIR_DELIM + "world.mt"; worldmt_settings.readConfigFile(worldmt.c_str()); std::vector names = worldmt_settings.getNames(); - std::set exclude_mod_names; std::set load_mod_names; for(std::vector::iterator it = names.begin(); it != names.end(); ++it) { std::string name = *it; - if (name.compare(0,9,"load_mod_")==0) - { - if(worldmt_settings.getBool(name)) - load_mod_names.insert(name.substr(9)); - else - exclude_mod_names.insert(name.substr(9)); - } + if(name.compare(0,9,"load_mod_")==0 && worldmt_settings.getBool(name)) + load_mod_names.insert(name.substr(9)); } // complain about mods declared to be loaded, but not found for(std::vector::iterator it = m_mods.begin(); -- cgit v1.2.3 From b2253e5b42aed74365cb6d10b90fea4a30dee5fa Mon Sep 17 00:00:00 2001 From: PilzAdam Date: Sun, 19 May 2013 19:52:29 +0200 Subject: Write mods that are not in world.mt into it at world startup --- src/mods.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/mods.cpp b/src/mods.cpp index a0a37afb9..9097f5708 100644 --- a/src/mods.cpp +++ b/src/mods.cpp @@ -247,8 +247,11 @@ ModConfiguration::ModConfiguration(std::string worldpath) ModSpec& mod = *it; if(include_mod_names.count(mod.name) != 0) addon_mods.push_back(mod); + else + worldmt_settings.setBool("load_mod_" + mod.name, false); } } + worldmt_settings.updateConfigFile(worldmt.c_str()); addMods(addon_mods); -- cgit v1.2.3 From cc92e45b78dd8955e43b2828eafb4b4e3a0a1b99 Mon Sep 17 00:00:00 2001 From: Kahrl Date: Sun, 19 May 2013 19:58:01 +0200 Subject: Fix EmergeThread names in log Concatenate the thread id as string instead of adding it to the pointer --- src/emerge.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/emerge.cpp b/src/emerge.cpp index 2d8b01819..b31a942e3 100644 --- a/src/emerge.cpp +++ b/src/emerge.cpp @@ -349,7 +349,7 @@ bool EmergeThread::getBlockOrStartGen(v3s16 p, MapBlock **b, void *EmergeThread::Thread() { ThreadStarted(); - log_register_thread("EmergeThread" + id); + log_register_thread("EmergeThread" + itos(id)); DSTACK(__FUNCTION_NAME); BEGIN_DEBUG_EXCEPTION_HANDLER -- cgit v1.2.3 From bc66f4632372e62be53f3b61cd5cc4a82ee44741 Mon Sep 17 00:00:00 2001 From: PilzAdam Date: Sun, 19 May 2013 20:56:25 +0200 Subject: Dont teleport back if holding sneak when detaching/turn freemove off --- src/localplayer.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/localplayer.cpp b/src/localplayer.cpp index 13117d881..f8dfca050 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -73,6 +73,7 @@ void LocalPlayer::move(f32 dtime, ClientEnvironment *env, f32 pos_max_d, if(isAttached) { setPosition(overridePosition); + m_sneak_node_exists = false; return; } @@ -85,6 +86,7 @@ void LocalPlayer::move(f32 dtime, ClientEnvironment *env, f32 pos_max_d, { position += m_speed * dtime; setPosition(position); + m_sneak_node_exists = false; return; } -- cgit v1.2.3 From 3e2efdf18ab95d3c88f66c7a1f6caf6b1c7231e5 Mon Sep 17 00:00:00 2001 From: PilzAdam Date: Mon, 20 May 2013 00:20:42 +0200 Subject: Add a little animation when changing the wielded item --- src/camera.cpp | 61 +++++++++++++++++++++++++++++++++++++++++++++++----------- src/camera.h | 8 +++++++- src/game.cpp | 2 +- 3 files changed, 58 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/camera.cpp b/src/camera.cpp index 0dd0a767b..f227bd98a 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -71,7 +71,12 @@ Camera::Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control, m_digging_anim(0), m_digging_button(-1), - m_dummymesh(createCubeMesh(v3f(1,1,1))) + m_dummymesh(createCubeMesh(v3f(1,1,1))), + + m_wield_change_timer(0.125), + m_wield_mesh_next(NULL), + m_previous_playeritem(-1), + m_previous_itemname("") { //dstream<<__FUNCTION_NAME< 0.125) + m_wield_change_timer = 0.125; + + if(m_wield_change_timer >= 0 && m_wield_change_timer - dtime < 0) { + if(m_wield_mesh_next) { + m_wieldnode->setMesh(m_wield_mesh_next); + m_wieldnode->setVisible(true); + } else { + m_wieldnode->setVisible(false); + } + m_wield_mesh_next = NULL; + } + if (m_view_bobbing_state != 0) { //f32 offset = dtime * m_view_bobbing_speed * 0.035; @@ -351,6 +371,10 @@ void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize, v3f wield_position = v3f(55, -35, 65); //v3f wield_rotation = v3f(-100, 120, -100); v3f wield_rotation = v3f(-100, 120, -100); + if(m_wield_change_timer < 0) + wield_position.Y -= 40 + m_wield_change_timer*320; + else + wield_position.Y -= 40 - m_wield_change_timer*320; if(m_digging_anim < 0.05 || m_digging_anim > 0.5){ f32 frac = 1.0; if(m_digging_anim > 0.5) @@ -559,18 +583,33 @@ void Camera::setDigging(s32 button) m_digging_button = button; } -void Camera::wield(const ItemStack &item) +void Camera::wield(const ItemStack &item, u16 playeritem) { IItemDefManager *idef = m_gamedef->idef(); - scene::IMesh *wield_mesh = idef->getWieldMesh(item.getDefinition(idef).name, m_gamedef); - if(wield_mesh) - { - m_wieldnode->setMesh(wield_mesh); - m_wieldnode->setVisible(true); - } - else - { - m_wieldnode->setVisible(false); + std::string itemname = item.getDefinition(idef).name; + m_wield_mesh_next = idef->getWieldMesh(itemname, m_gamedef); + if(playeritem != m_previous_playeritem) { + m_previous_playeritem = playeritem; + m_previous_itemname = itemname; + if(m_wield_change_timer >= 0.125) + m_wield_change_timer = -0.125; + else if(m_wield_change_timer > 0) { + m_wield_change_timer = -m_wield_change_timer; + } + } else { + if(m_wield_mesh_next) { + m_wieldnode->setMesh(m_wield_mesh_next); + m_wieldnode->setVisible(true); + } else { + m_wieldnode->setVisible(false); + } + m_wield_mesh_next = NULL; + if(m_previous_itemname != itemname) { + m_previous_itemname = itemname; + m_wield_change_timer = 0; + } + else + m_wield_change_timer = 0.125; } } diff --git a/src/camera.h b/src/camera.h index 0ed5c20d2..c8a6e0bb8 100644 --- a/src/camera.h +++ b/src/camera.h @@ -117,7 +117,7 @@ public: void setDigging(s32 button); // Replace the wielded item mesh - void wield(const ItemStack &item); + void wield(const ItemStack &item, u16 playeritem); // Draw the wielded tool. // This has to happen *after* the main scene is drawn. @@ -178,6 +178,12 @@ private: //dummymesh for camera irr::scene::IAnimatedMesh* m_dummymesh; + + // Animation when changing wielded item + f32 m_wield_change_timer; + scene::IMesh *m_wield_mesh_next; + u16 m_previous_playeritem; + std::string m_previous_itemname; }; #endif diff --git a/src/game.cpp b/src/game.cpp index 746769aee..185f42eae 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -3084,7 +3084,7 @@ void the_game( ItemStack item; if(mlist != NULL) item = mlist->getItem(client.getPlayerItem()); - camera.wield(item); + camera.wield(item, client.getPlayerItem()); } /* -- cgit v1.2.3 From 55a97f4605a263f4b670b447cd4af9ffa1a8d472 Mon Sep 17 00:00:00 2001 From: sapier Date: Sun, 5 May 2013 01:44:55 +0200 Subject: Allow nil as puncher e.g. to do damage by tnt --- src/content_sao.cpp | 15 +++++++++++++-- src/scriptapi_object.cpp | 23 ++++++++++++++++------- 2 files changed, 29 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/content_sao.cpp b/src/content_sao.cpp index 24a9186f7..47b94a5d9 100644 --- a/src/content_sao.cpp +++ b/src/content_sao.cpp @@ -673,8 +673,14 @@ int LuaEntitySAO::punch(v3f dir, { setHP(getHP() - result.damage); + + std::string punchername = "nil"; + + if ( puncher != 0 ) + punchername = puncher->getDescription(); + actionstream<getDescription()<<", damage "<getDescription(); + actionstream<<"Player "<getName()<<" punched by " - <getDescription()<<", damage "<getBasePosition() - puncher->getBasePosition(); - else - dir = read_v3f(L, 5); + } + float time_from_last_punch = 1000000; if(lua_isnumber(L, 3)) time_from_last_punch = lua_tonumber(L, 3); + ToolCapabilities toolcap = read_tool_capabilities(L, 4); + + if(lua_type(L, 5) == LUA_TTABLE) + dir = read_v3f(L, 5); dir.normalize(); + // Do it co->punch(dir, &toolcap, puncher, time_from_last_punch); return 0; -- cgit v1.2.3 From d00e8bd31a185a4000807de6d21eccce9f86671e Mon Sep 17 00:00:00 2001 From: kwolekr Date: Sun, 19 May 2013 21:26:08 -0400 Subject: Fix nearly all warnings --- src/collision.cpp | 2 +- src/emerge.h | 4 ++-- src/environment.cpp | 6 ------ src/guiConfigureWorld.cpp | 2 -- src/guiCreateWorld.cpp | 2 -- src/guiPasswordChange.cpp | 1 - src/guiVolumeChange.cpp | 1 - src/map.cpp | 10 +++++----- src/mapgen_v6.cpp | 2 -- src/mapgen_v7.cpp | 2 -- src/player.h | 2 +- src/scriptapi_env.cpp | 3 +-- src/scriptapi_types.cpp | 2 +- src/test.cpp | 2 +- src/voxel.cpp | 2 +- 15 files changed, 13 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/collision.cpp b/src/collision.cpp index 673966b6e..3058426eb 100644 --- a/src/collision.cpp +++ b/src/collision.cpp @@ -298,7 +298,7 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef, f32 distance = speed_f.getLength(); std::vector clientobjects; c_env->getActiveObjects(pos_f,distance * 1.5,clientobjects); - for (int i=0; i < clientobjects.size(); i++) + for (size_t i=0; i < clientobjects.size(); i++) { if ((self == 0) || (self != clientobjects[i].obj)) { objects.push_back((ActiveObject*)clientobjects[i].obj); diff --git a/src/emerge.h b/src/emerge.h index fdca93c06..b42e82d38 100644 --- a/src/emerge.h +++ b/src/emerge.h @@ -31,8 +31,8 @@ with this program; if not, write to the Free Software Foundation, Inc., infostream << "EmergeThread: " x << std::endl; } class Mapgen; -class MapgenParams; -class MapgenFactory; +struct MapgenParams; +struct MapgenFactory; class Biome; class BiomeDefManager; class EmergeThread; diff --git a/src/environment.cpp b/src/environment.cpp index e06b032f2..03b8ef7f6 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -910,7 +910,6 @@ void ServerEnvironment::clearAllObjects() if(obj->getType() == ACTIVEOBJECT_TYPE_PLAYER) continue; u16 id = i->first; - v3f objectpos = obj->getBasePosition(); // Delete static object if block is loaded if(obj->m_static_exists){ MapBlock *block = m_map->getBlockNoCreateNoEx(obj->m_static_block); @@ -1031,8 +1030,6 @@ void ServerEnvironment::step(float dtime) // Ignore disconnected players if(player->peer_id == 0) continue; - - v3f playerpos = player->getPosition(); // Move player->move(dtime, *m_map, 100*BS); @@ -2072,8 +2069,6 @@ void ClientEnvironment::step(float dtime) */ { - v3f lplayerpos = lplayer->getPosition(); - // Apply physics if(free_move == false && is_climbing == false) { @@ -2197,7 +2192,6 @@ void ClientEnvironment::step(float dtime) i != m_players.end(); ++i) { Player *player = *i; - v3f playerpos = player->getPosition(); /* Handle non-local players diff --git a/src/guiConfigureWorld.cpp b/src/guiConfigureWorld.cpp index e33e87ef5..8f5ef937d 100644 --- a/src/guiConfigureWorld.cpp +++ b/src/guiConfigureWorld.cpp @@ -165,8 +165,6 @@ void GUIConfigureWorld::regenerateGui(v2u32 screensize) DesiredRect = rect; recalculateAbsolutePosition(false); - v2s32 size = rect.getSize(); - v2s32 topleft = v2s32(10, 10); /* diff --git a/src/guiCreateWorld.cpp b/src/guiCreateWorld.cpp index caa884bc0..9fc764214 100644 --- a/src/guiCreateWorld.cpp +++ b/src/guiCreateWorld.cpp @@ -112,8 +112,6 @@ void GUICreateWorld::regenerateGui(v2u32 screensize) DesiredRect = rect; recalculateAbsolutePosition(false); - v2s32 size = rect.getSize(); - v2s32 topleft = v2s32(10+80, 10+70); /* diff --git a/src/guiPasswordChange.cpp b/src/guiPasswordChange.cpp index a4d16444d..8b55234c2 100644 --- a/src/guiPasswordChange.cpp +++ b/src/guiPasswordChange.cpp @@ -95,7 +95,6 @@ void GUIPasswordChange::regenerateGui(v2u32 screensize) v2s32 size = rect.getSize(); v2s32 topleft_client(40, 0); - v2s32 size_client = size - v2s32(40, 0); /* Add stuff diff --git a/src/guiVolumeChange.cpp b/src/guiVolumeChange.cpp index 4e92b82c2..c272b132d 100644 --- a/src/guiVolumeChange.cpp +++ b/src/guiVolumeChange.cpp @@ -96,7 +96,6 @@ void GUIVolumeChange::regenerateGui(v2u32 screensize) v2s32 size = rect.getSize(); v2s32 topleft_client(40, 0); - v2s32 size_client = size - v2s32(40, 0); int volume=(int)(g_settings->getFloat("sound_volume")*100); /* Add stuff diff --git a/src/map.cpp b/src/map.cpp index 821805d4e..d5ab8eb1e 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -288,10 +288,10 @@ void Map::unspreadLight(enum LightBank bank, continue; // Calculate relative position in block - v3s16 relpos = pos - blockpos_last * MAP_BLOCKSIZE; + //v3s16 relpos = pos - blockpos_last * MAP_BLOCKSIZE; // Get node straight from the block - MapNode n = block->getNode(relpos); + //MapNode n = block->getNode(relpos); u8 oldlight = j->second; @@ -937,7 +937,7 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n, */ v3s16 toppos = p + v3s16(0,1,0); - v3s16 bottompos = p + v3s16(0,-1,0); + //v3s16 bottompos = p + v3s16(0,-1,0); bool node_under_sunlight = true; std::set light_sources; @@ -1246,7 +1246,7 @@ void Map::removeNodeAndUpdate(v3s16 p, // Get the brightest neighbour node and propagate light from it v3s16 n2p = getBrightestNeighbour(bank, p); try{ - MapNode n2 = getNode(n2p); + //MapNode n2 = getNode(n2p); lightNeighbors(bank, n2p, modified_blocks); } catch(InvalidPositionException &e) @@ -2831,7 +2831,7 @@ ServerMapSector * ServerMap::createSector(v2s16 p2d) sector = new ServerMapSector(this, p2d, m_gamedef); // Sector position on map in nodes - v2s16 nodepos2d = p2d * MAP_BLOCKSIZE; + //v2s16 nodepos2d = p2d * MAP_BLOCKSIZE; /* Insert to container diff --git a/src/mapgen_v6.cpp b/src/mapgen_v6.cpp index e5ff72a60..eaca33988 100644 --- a/src/mapgen_v6.cpp +++ b/src/mapgen_v6.cpp @@ -375,8 +375,6 @@ void MapgenV6::makeChunk(BlockMakeData *data) { v3s16 blockpos = data->blockpos_requested; v3s16 blockpos_min = data->blockpos_min; v3s16 blockpos_max = data->blockpos_max; - v3s16 blockpos_full_min = blockpos_min - v3s16(1,1,1); - v3s16 blockpos_full_max = blockpos_max + v3s16(1,1,1); // Area of central chunk node_min = blockpos_min*MAP_BLOCKSIZE; diff --git a/src/mapgen_v7.cpp b/src/mapgen_v7.cpp index 2fb5d7b9b..6daa5fc6a 100644 --- a/src/mapgen_v7.cpp +++ b/src/mapgen_v7.cpp @@ -152,8 +152,6 @@ void MapgenV7::makeChunk(BlockMakeData *data) { v3s16 blockpos_min = data->blockpos_min; v3s16 blockpos_max = data->blockpos_max; - v3s16 blockpos_full_min = blockpos_min - v3s16(1, 1, 1); - v3s16 blockpos_full_max = blockpos_max + v3s16(1, 1, 1); node_min = blockpos_min * MAP_BLOCKSIZE; node_max = (blockpos_max + v3s16(1, 1, 1)) * MAP_BLOCKSIZE - v3s16(1, 1, 1); full_node_min = (blockpos_min - 1) * MAP_BLOCKSIZE; diff --git a/src/player.h b/src/player.h index fade6de01..63e166b4b 100644 --- a/src/player.h +++ b/src/player.h @@ -87,7 +87,7 @@ class Map; class IGameDef; struct CollisionInfo; class PlayerSAO; -class HudElement; +struct HudElement; class Player { diff --git a/src/scriptapi_env.cpp b/src/scriptapi_env.cpp index efed58e66..a9d9391a7 100644 --- a/src/scriptapi_env.cpp +++ b/src/scriptapi_env.cpp @@ -227,7 +227,6 @@ int EnvRef::l_get_node_light(lua_State *L) time_of_day = 24000.0 * lua_tonumber(L, 3); time_of_day %= 24000; u32 dnr = time_to_daynight_ratio(time_of_day, true); - MapNode n = env->getMap().getNodeNoEx(pos); try{ MapNode n = env->getMap().getNode(pos); INodeDefManager *ndef = env->getGameDef()->ndef(); @@ -373,7 +372,7 @@ int EnvRef::l_add_item(lua_State *L) ServerEnvironment *env = o->m_env; if(env == NULL) return 0; // pos - v3f pos = checkFloatPos(L, 2); + //v3f pos = checkFloatPos(L, 2); // item ItemStack item = read_item(L, 3); if(item.empty() || !item.isKnown(get_server(L)->idef())) diff --git a/src/scriptapi_types.cpp b/src/scriptapi_types.cpp index f30451108..f2f6b6bd8 100644 --- a/src/scriptapi_types.cpp +++ b/src/scriptapi_types.cpp @@ -147,7 +147,7 @@ v3s16 check_v3s16(lua_State *L, int index) video::SColor readARGB8(lua_State *L, int index) { - video::SColor color; + video::SColor color(0); luaL_checktype(L, index, LUA_TTABLE); lua_getfield(L, index, "a"); if(lua_isnumber(L, -1)) diff --git a/src/test.cpp b/src/test.cpp index e1dbfa6b8..3a0316e17 100644 --- a/src/test.cpp +++ b/src/test.cpp @@ -464,7 +464,7 @@ struct TestCompress: public TestBase std::string str_decompressed = os_decompressed.str(); UTEST(str_decompressed.size() == data_in.size(), "Output size not" " equal (output: %u, input: %u)", - str_decompressed.size(), data_in.size()); + (unsigned int)str_decompressed.size(), (unsigned int)data_in.size()); for(u32 i=0; i Date: Sun, 19 May 2013 21:29:49 -0400 Subject: Fix lava damage on player's upper body --- src/environment.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/environment.cpp b/src/environment.cpp index 03b8ef7f6..9f87b8c91 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -2169,7 +2169,7 @@ void ClientEnvironment::step(float dtime) v3s16 p2 = floatToInt(pf + v3f(0, BS*0.8, 0), BS); MapNode n2 = m_map->getNodeNoEx(p2); v3s16 p3 = floatToInt(pf + v3f(0, BS*1.6, 0), BS); - MapNode n3 = m_map->getNodeNoEx(p2); + MapNode n3 = m_map->getNodeNoEx(p3); u32 damage_per_second = 0; damage_per_second = MYMAX(damage_per_second, -- cgit v1.2.3 From 127c48835573f9e7bd89137ecb2176c2a8e5f783 Mon Sep 17 00:00:00 2001 From: ShadowNinja Date: Sun, 14 Apr 2013 03:01:27 -0400 Subject: Use the group "soil" for nodes that saplings grow on --- src/content_abm.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/content_abm.cpp b/src/content_abm.cpp index e20201dcf..f19caf74e 100644 --- a/src/content_abm.cpp +++ b/src/content_abm.cpp @@ -99,14 +99,10 @@ class MakeTreesFromSaplingsABM : public ActiveBlockModifier { private: content_t c_junglesapling; - content_t c_dirt; - content_t c_dirt_with_grass; public: MakeTreesFromSaplingsABM(ServerEnvironment *env, INodeDefManager *nodemgr) { - c_junglesapling = nodemgr->getId("junglesapling"); - c_dirt = nodemgr->getId("mapgen_dirt"); - c_dirt_with_grass = nodemgr->getId("mapgen_dirt_with_grass"); + c_junglesapling = nodemgr->getId("junglesapling"); } virtual std::set getTriggerContents() @@ -127,8 +123,7 @@ public: ServerMap *map = &env->getServerMap(); MapNode n_below = map->getNodeNoEx(p - v3s16(0, 1, 0)); - if (n_below.getContent() != c_dirt && - n_below.getContent() != c_dirt_with_grass) + if (!((ItemGroupList) ndef->get(n_below).groups)["soil"]) return; bool is_jungle_tree = n.getContent() == c_junglesapling; -- cgit v1.2.3 From c135e9c7d4bfaf038a2236f17f6e246d03461b8a Mon Sep 17 00:00:00 2001 From: elagin Date: Thu, 31 Jan 2013 21:03:14 +0400 Subject: Save settings after dropping main menu --- src/main.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/main.cpp b/src/main.cpp index e5c8a55d3..eda992793 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1942,6 +1942,9 @@ int main(int argc, char *argv[]) sound = NULL; } + // Save controls status + menu->readInput(&menudata); + infostream<<"Dropping main menu"<drop(); -- cgit v1.2.3 From 5e80df46b8c42e71c376da50ffb0ef06636073f2 Mon Sep 17 00:00:00 2001 From: MetaDucky Date: Mon, 20 May 2013 16:09:11 +0200 Subject: Fix typo in particle spawning --- src/client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/client.cpp b/src/client.cpp index 533c40ab2..e4ca52dd5 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -1987,7 +1987,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) event.spawn_particle.expirationtime = expirationtime; event.spawn_particle.size = size; - event.add_particlespawner.collisiondetection = + event.spawn_particle.collisiondetection = collisiondetection; event.spawn_particle.texture = new std::string(texture); -- cgit v1.2.3 From e57dc4ef1899fd172b94dc67c3a70be49803145e Mon Sep 17 00:00:00 2001 From: PilzAdam Date: Mon, 20 May 2013 20:31:38 +0200 Subject: Dont animate changing wielditem from hand to hand --- src/camera.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/camera.cpp b/src/camera.cpp index f227bd98a..acefff7e7 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -588,7 +588,8 @@ void Camera::wield(const ItemStack &item, u16 playeritem) IItemDefManager *idef = m_gamedef->idef(); std::string itemname = item.getDefinition(idef).name; m_wield_mesh_next = idef->getWieldMesh(itemname, m_gamedef); - if(playeritem != m_previous_playeritem) { + if(playeritem != m_previous_playeritem && + !(m_previous_itemname == "" && itemname == "")) { m_previous_playeritem = playeritem; m_previous_itemname = itemname; if(m_wield_change_timer >= 0.125) -- cgit v1.2.3 From 4a9fe1a1d5d19565bca67c0dcb3dbf43bd06f278 Mon Sep 17 00:00:00 2001 From: Kahrl Date: Tue, 21 May 2013 14:56:43 +0200 Subject: Log non-fatal mod name conflict to actionstream instead of errorstream --- src/mods.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/mods.cpp b/src/mods.cpp index 9097f5708..9bcf73aa7 100644 --- a/src/mods.cpp +++ b/src/mods.cpp @@ -309,7 +309,7 @@ void ModConfiguration::addMods(std::vector new_mods) // BAD CASE: name conflict in different levels. u32 oldindex = existing_mods[mod.name]; const ModSpec &oldmod = m_unsatisfied_mods[oldindex]; - errorstream<<"WARNING: Mod name conflict detected: \"" + actionstream<<"WARNING: Mod name conflict detected: \"" < Date: Tue, 21 May 2013 20:16:22 +0200 Subject: Fix disappearing of wielditem --- src/camera.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/camera.cpp b/src/camera.cpp index acefff7e7..3d8713d6a 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -147,12 +147,13 @@ void Camera::step(f32 dtime) m_view_bobbing_fall = -1; // Mark the effect as finished } + bool was_under_zero = m_wield_change_timer < 0; if(m_wield_change_timer < 0.125) m_wield_change_timer += dtime; if(m_wield_change_timer > 0.125) m_wield_change_timer = 0.125; - if(m_wield_change_timer >= 0 && m_wield_change_timer - dtime < 0) { + if(m_wield_change_timer >= 0 && was_under_zero) { if(m_wield_mesh_next) { m_wieldnode->setMesh(m_wield_mesh_next); m_wieldnode->setVisible(true); -- cgit v1.2.3 From 3abbe7efd1d1da7c24725ae49c2df1013a7afb09 Mon Sep 17 00:00:00 2001 From: Jeija Date: Wed, 6 Feb 2013 19:36:14 +0100 Subject: Make raillike nodes connect to any other raillike nodes if both are in the group connect_to_raillike --- src/content_mapblock.cpp | 76 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 62 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/content_mapblock.cpp b/src/content_mapblock.cpp index 155b39ab6..84408e776 100644 --- a/src/content_mapblock.cpp +++ b/src/content_mapblock.cpp @@ -1188,34 +1188,81 @@ void mapblock_mesh_generate_special(MeshMakeData *data, MapNode n_minus_z_plus_y = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x, y+1, z-1)); MapNode n_plus_z_minus_y = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x, y-1, z+1)); MapNode n_minus_z_minus_y = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x, y-1, z-1)); - + content_t thiscontent = n.getContent(); - if(n_minus_x.getContent() == thiscontent) + std::string groupname = "connect_to_raillike"; // name of the group that enables connecting to raillike nodes of different kind + bool self_connect_to_raillike = ((ItemGroupList) nodedef->get(n).groups)[groupname] != 0; + + if ((nodedef->get(n_minus_x).drawtype == NDT_RAILLIKE + && ((ItemGroupList) nodedef->get(n_minus_x).groups)[groupname] != 0 + && self_connect_to_raillike) + || n_minus_x.getContent() == thiscontent) is_rail_x[0] = true; - if (n_minus_x_minus_y.getContent() == thiscontent) + + if ((nodedef->get(n_minus_x_minus_y).drawtype == NDT_RAILLIKE + && ((ItemGroupList) nodedef->get(n_minus_x_minus_y).groups)[groupname] != 0 + && self_connect_to_raillike) + || n_minus_x_minus_y.getContent() == thiscontent) is_rail_x_minus_y[0] = true; - if(n_minus_x_plus_y.getContent() == thiscontent) + + if ((nodedef->get(n_minus_x_plus_y).drawtype == NDT_RAILLIKE + && ((ItemGroupList) nodedef->get(n_minus_x_plus_y).groups)[groupname] != 0 + && self_connect_to_raillike) + || n_minus_x_plus_y.getContent() == thiscontent) is_rail_x_plus_y[0] = true; - if(n_plus_x.getContent() == thiscontent) + if ((nodedef->get(n_plus_x).drawtype == NDT_RAILLIKE + && ((ItemGroupList) nodedef->get(n_plus_x).groups)[groupname] != 0 + && self_connect_to_raillike) + || n_plus_x.getContent() == thiscontent) is_rail_x[1] = true; - if (n_plus_x_minus_y.getContent() == thiscontent) + + if ((nodedef->get(n_plus_x_minus_y).drawtype == NDT_RAILLIKE + && ((ItemGroupList) nodedef->get(n_plus_x_minus_y).groups)[groupname] != 0 + && self_connect_to_raillike) + || n_plus_x_minus_y.getContent() == thiscontent) is_rail_x_minus_y[1] = true; - if(n_plus_x_plus_y.getContent() == thiscontent) + + if ((nodedef->get(n_plus_x_plus_y).drawtype == NDT_RAILLIKE + && ((ItemGroupList) nodedef->get(n_plus_x_plus_y).groups)[groupname] != 0 + && self_connect_to_raillike) + || n_plus_x_plus_y.getContent() == thiscontent) is_rail_x_plus_y[1] = true; - if(n_minus_z.getContent() == thiscontent) + if ((nodedef->get(n_minus_z).drawtype == NDT_RAILLIKE + && ((ItemGroupList) nodedef->get(n_minus_z).groups)[groupname] != 0 + && self_connect_to_raillike) + || n_minus_z.getContent() == thiscontent) is_rail_z[0] = true; - if (n_minus_z_minus_y.getContent() == thiscontent) + + if ((nodedef->get(n_minus_z_minus_y).drawtype == NDT_RAILLIKE + && ((ItemGroupList) nodedef->get(n_minus_z_minus_y).groups)[groupname] != 0 + && self_connect_to_raillike) + || n_minus_z_minus_y.getContent() == thiscontent) is_rail_z_minus_y[0] = true; - if(n_minus_z_plus_y.getContent() == thiscontent) + + if ((nodedef->get(n_minus_z_plus_y).drawtype == NDT_RAILLIKE + && ((ItemGroupList) nodedef->get(n_minus_z_plus_y).groups)[groupname] != 0 + && self_connect_to_raillike) + || n_minus_z_plus_y.getContent() == thiscontent) is_rail_z_plus_y[0] = true; - if(n_plus_z.getContent() == thiscontent) + if ((nodedef->get(n_plus_z).drawtype == NDT_RAILLIKE + && ((ItemGroupList) nodedef->get(n_plus_z).groups)[groupname] != 0 + && self_connect_to_raillike) + || n_plus_z.getContent() == thiscontent) is_rail_z[1] = true; - if (n_plus_z_minus_y.getContent() == thiscontent) + + if ((nodedef->get(n_plus_z_minus_y).drawtype == NDT_RAILLIKE + && ((ItemGroupList) nodedef->get(n_plus_z_minus_y).groups)[groupname] != 0 + && self_connect_to_raillike) + || n_plus_z_minus_y.getContent() == thiscontent) is_rail_z_minus_y[1] = true; - if(n_plus_z_plus_y.getContent() == thiscontent) + + if ((nodedef->get(n_plus_z_plus_y).drawtype == NDT_RAILLIKE + && ((ItemGroupList) nodedef->get(n_plus_z_plus_y).groups)[groupname] != 0 + && self_connect_to_raillike) + || n_plus_z_plus_y.getContent() == thiscontent) is_rail_z_plus_y[1] = true; bool is_rail_x_all[] = {false, false}; @@ -1255,7 +1302,8 @@ void mapblock_mesh_generate_special(MeshMakeData *data, if(is_rail_x_all[0] && is_rail_x_all[1]) angle = 90; if(is_rail_z_all[0] && is_rail_z_all[1]){ - if (n_minus_z_plus_y.getContent() == thiscontent) angle = 180; + if (is_rail_z_plus_y[0]) + angle = 180; } else if(is_rail_x_all[0] && is_rail_z_all[0]) angle = 270; -- cgit v1.2.3 From 865f380c91ced850d1a499c91aa2ab5489624802 Mon Sep 17 00:00:00 2001 From: PilzAdam Date: Fri, 24 May 2013 01:38:57 +0200 Subject: Predict param2 of facedir nodes and attachment of attached_node nodes --- src/game.cpp | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/game.cpp b/src/game.cpp index 185f42eae..921cce327 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -847,7 +847,7 @@ void nodePlacementPrediction(Client &client, <<") - Name not known"<get(id).param_type_2 == CPT2_WALLMOUNTED){ v3s16 dir = nodepos - neighbourpos; @@ -859,8 +859,33 @@ void nodePlacementPrediction(Client &client, param2 = dir.Z < 0 ? 5 : 4; } } - // TODO: Facedir prediction - // TODO: If predicted node is in attached_node group, check attachment + if(nodedef->get(id).param_type_2 == CPT2_FACEDIR){ + v3s16 dir = nodepos - floatToInt(client.getEnv().getLocalPlayer()->getPosition(), BS); + if(abs(dir.X) > abs(dir.Z)){ + param2 = dir.X < 0 ? 3 : 1; + } else { + param2 = dir.Z < 0 ? 2 : 0; + } + } + assert(param2 >= 0 && param2 <= 5); + //Check attachment if node is in group attached_node + if(((ItemGroupList) nodedef->get(id).groups)["attached_node"] != 0){ + static v3s16 wallmounted_dirs[8] = { + v3s16(0,1,0), + v3s16(0,-1,0), + v3s16(1,0,0), + v3s16(-1,0,0), + v3s16(0,0,1), + v3s16(0,0,-1), + }; + v3s16 pp; + if(nodedef->get(id).param_type_2 == CPT2_WALLMOUNTED) + pp = p + wallmounted_dirs[param2]; + else + pp = p + v3s16(0,-1,0); + if(!nodedef->get(map.getNode(pp)).walkable) + return; + } // Add node to client map MapNode n(id, 0, param2); try{ -- cgit v1.2.3 From ab433775777c4f5055bcf4d2a1cffc506c4f9961 Mon Sep 17 00:00:00 2001 From: sapier Date: Sat, 25 May 2013 00:51:02 +0200 Subject: Move scriptapi to separate folder (by sapier) On the lua side, notably minetest.env:() should now be replaced by minetest.(). The old way is and will stay supported for a long time. Also: Update and clean up lua_api.txt (by celeron55) Move EnvRef to lua and remove add_rat and add_firefly (by kahrl) Add separate src/util/CMakeLists.txt, other minor fixes (by kahrl) --- src/CMakeLists.txt | 29 +- src/content_sao.cpp | 24 +- src/emerge.cpp | 5 +- src/environment.cpp | 30 +- src/environment.h | 10 +- src/hud.h | 2 +- src/inventorymanager.cpp | 84 +-- src/jthread/jmutex.h | 9 + src/script.cpp | 126 ---- src/script.h | 49 -- src/script/CMakeLists.txt | 9 + src/script/common/CMakeLists.txt | 6 + src/script/common/c_content.cpp | 923 +++++++++++++++++++++++++++ src/script/common/c_content.h | 146 +++++ src/script/common/c_converter.cpp | 343 ++++++++++ src/script/common/c_converter.h | 96 +++ src/script/common/c_internal.cpp | 65 ++ src/script/common/c_internal.h | 60 ++ src/script/common/c_types.cpp | 40 ++ src/script/common/c_types.h | 90 +++ src/script/cpp_api/CMakeLists.txt | 11 + src/script/cpp_api/s_base.cpp | 264 ++++++++ src/script/cpp_api/s_base.h | 167 +++++ src/script/cpp_api/s_entity.cpp | 267 ++++++++ src/script/cpp_api/s_entity.h | 50 ++ src/script/cpp_api/s_env.cpp | 132 ++++ src/script/cpp_api/s_env.h | 40 ++ src/script/cpp_api/s_inventory.cpp | 260 ++++++++ src/script/cpp_api/s_inventory.h | 71 +++ src/script/cpp_api/s_item.cpp | 164 +++++ src/script/cpp_api/s_item.h | 55 ++ src/script/cpp_api/s_node.cpp | 233 +++++++ src/script/cpp_api/s_node.h | 62 ++ src/script/cpp_api/s_nodemeta.cpp | 261 ++++++++ src/script/cpp_api/s_nodemeta.h | 67 ++ src/script/cpp_api/s_player.cpp | 113 ++++ src/script/cpp_api/s_player.h | 44 ++ src/script/cpp_api/scriptapi.cpp | 291 +++++++++ src/script/cpp_api/scriptapi.h | 82 +++ src/script/lua_api/CMakeLists.txt | 13 + src/script/lua_api/l_base.cpp | 63 ++ src/script/lua_api/l_base.h | 63 ++ src/script/lua_api/l_craft.cpp | 477 ++++++++++++++ src/script/lua_api/l_craft.h | 52 ++ src/script/lua_api/l_env.cpp | 687 ++++++++++++++++++++ src/script/lua_api/l_env.h | 172 +++++ src/script/lua_api/l_inventory.cpp | 483 ++++++++++++++ src/script/lua_api/l_inventory.h | 137 ++++ src/script/lua_api/l_item.cpp | 472 ++++++++++++++ src/script/lua_api/l_item.h | 151 +++++ src/script/lua_api/l_nodemeta.cpp | 332 ++++++++++ src/script/lua_api/l_nodemeta.h | 93 +++ src/script/lua_api/l_nodetimer.cpp | 169 +++++ src/script/lua_api/l_nodetimer.h | 70 +++ src/script/lua_api/l_noise.cpp | 373 +++++++++++ src/script/lua_api/l_noise.h | 134 ++++ src/script/lua_api/l_object.cpp | 1095 ++++++++++++++++++++++++++++++++ src/script/lua_api/l_object.h | 226 +++++++ src/script/lua_api/l_particles.cpp | 149 +++++ src/script/lua_api/l_particles.h | 39 ++ src/script/lua_api/luaapi.cpp | 653 +++++++++++++++++++ src/script/lua_api/luaapi.h | 140 +++++ src/scriptapi.cpp | 1181 ---------------------------------- src/scriptapi.h | 75 --- src/scriptapi_common.cpp | 311 --------- src/scriptapi_common.h | 112 ---- src/scriptapi_content.cpp | 327 ---------- src/scriptapi_content.h | 37 -- src/scriptapi_craft.cpp | 453 -------------- src/scriptapi_craft.h | 51 -- src/scriptapi_entity.cpp | 293 --------- src/scriptapi_entity.h | 54 -- src/scriptapi_env.cpp | 975 ----------------------------- src/scriptapi_env.h | 170 ----- src/scriptapi_inventory.cpp | 726 --------------------- src/scriptapi_inventory.h | 165 ----- src/scriptapi_item.cpp | 718 --------------------- src/scriptapi_item.h | 166 ----- src/scriptapi_node.cpp | 244 -------- src/scriptapi_node.h | 55 -- src/scriptapi_nodemeta.cpp | 571 ----------------- src/scriptapi_nodemeta.h | 123 ---- src/scriptapi_nodetimer.cpp | 166 ----- src/scriptapi_nodetimer.h | 70 --- src/scriptapi_noise.cpp | 388 ------------ src/scriptapi_noise.h | 133 ---- src/scriptapi_object.cpp | 1218 ------------------------------------ src/scriptapi_object.h | 238 ------- src/scriptapi_particles.cpp | 143 ----- src/scriptapi_particles.h | 32 - src/scriptapi_types.cpp | 388 ------------ src/scriptapi_types.h | 90 --- src/server.cpp | 144 +++-- src/server.h | 14 +- src/util/CMakeLists.txt | 8 + 95 files changed, 10824 insertions(+), 10038 deletions(-) delete mode 100644 src/script.cpp delete mode 100644 src/script.h create mode 100644 src/script/CMakeLists.txt create mode 100644 src/script/common/CMakeLists.txt create mode 100644 src/script/common/c_content.cpp create mode 100644 src/script/common/c_content.h create mode 100644 src/script/common/c_converter.cpp create mode 100644 src/script/common/c_converter.h create mode 100644 src/script/common/c_internal.cpp create mode 100644 src/script/common/c_internal.h create mode 100644 src/script/common/c_types.cpp create mode 100644 src/script/common/c_types.h create mode 100644 src/script/cpp_api/CMakeLists.txt create mode 100644 src/script/cpp_api/s_base.cpp create mode 100644 src/script/cpp_api/s_base.h create mode 100644 src/script/cpp_api/s_entity.cpp create mode 100644 src/script/cpp_api/s_entity.h create mode 100644 src/script/cpp_api/s_env.cpp create mode 100644 src/script/cpp_api/s_env.h create mode 100644 src/script/cpp_api/s_inventory.cpp create mode 100644 src/script/cpp_api/s_inventory.h create mode 100644 src/script/cpp_api/s_item.cpp create mode 100644 src/script/cpp_api/s_item.h create mode 100644 src/script/cpp_api/s_node.cpp create mode 100644 src/script/cpp_api/s_node.h create mode 100644 src/script/cpp_api/s_nodemeta.cpp create mode 100644 src/script/cpp_api/s_nodemeta.h create mode 100644 src/script/cpp_api/s_player.cpp create mode 100644 src/script/cpp_api/s_player.h create mode 100644 src/script/cpp_api/scriptapi.cpp create mode 100644 src/script/cpp_api/scriptapi.h create mode 100644 src/script/lua_api/CMakeLists.txt create mode 100644 src/script/lua_api/l_base.cpp create mode 100644 src/script/lua_api/l_base.h create mode 100644 src/script/lua_api/l_craft.cpp create mode 100644 src/script/lua_api/l_craft.h create mode 100644 src/script/lua_api/l_env.cpp create mode 100644 src/script/lua_api/l_env.h create mode 100644 src/script/lua_api/l_inventory.cpp create mode 100644 src/script/lua_api/l_inventory.h create mode 100644 src/script/lua_api/l_item.cpp create mode 100644 src/script/lua_api/l_item.h create mode 100644 src/script/lua_api/l_nodemeta.cpp create mode 100644 src/script/lua_api/l_nodemeta.h create mode 100644 src/script/lua_api/l_nodetimer.cpp create mode 100644 src/script/lua_api/l_nodetimer.h create mode 100644 src/script/lua_api/l_noise.cpp create mode 100644 src/script/lua_api/l_noise.h create mode 100644 src/script/lua_api/l_object.cpp create mode 100644 src/script/lua_api/l_object.h create mode 100644 src/script/lua_api/l_particles.cpp create mode 100644 src/script/lua_api/l_particles.h create mode 100644 src/script/lua_api/luaapi.cpp create mode 100644 src/script/lua_api/luaapi.h delete mode 100644 src/scriptapi.cpp delete mode 100644 src/scriptapi.h delete mode 100644 src/scriptapi_common.cpp delete mode 100644 src/scriptapi_common.h delete mode 100644 src/scriptapi_content.cpp delete mode 100644 src/scriptapi_content.h delete mode 100644 src/scriptapi_craft.cpp delete mode 100644 src/scriptapi_craft.h delete mode 100644 src/scriptapi_entity.cpp delete mode 100644 src/scriptapi_entity.h delete mode 100644 src/scriptapi_env.cpp delete mode 100644 src/scriptapi_env.h delete mode 100644 src/scriptapi_inventory.cpp delete mode 100644 src/scriptapi_inventory.h delete mode 100644 src/scriptapi_item.cpp delete mode 100644 src/scriptapi_item.h delete mode 100644 src/scriptapi_node.cpp delete mode 100644 src/scriptapi_node.h delete mode 100644 src/scriptapi_nodemeta.cpp delete mode 100644 src/scriptapi_nodemeta.h delete mode 100644 src/scriptapi_nodetimer.cpp delete mode 100644 src/scriptapi_nodetimer.h delete mode 100644 src/scriptapi_noise.cpp delete mode 100644 src/scriptapi_noise.h delete mode 100644 src/scriptapi_object.cpp delete mode 100644 src/scriptapi_object.h delete mode 100644 src/scriptapi_particles.cpp delete mode 100644 src/scriptapi_particles.h delete mode 100644 src/scriptapi_types.cpp delete mode 100644 src/scriptapi_types.h create mode 100644 src/util/CMakeLists.txt (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 74c5fabb8..51ed27837 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -206,6 +206,9 @@ configure_file( "${PROJECT_BINARY_DIR}/cmake_config.h" ) +add_subdirectory(script) +add_subdirectory(util) + set(common_SRCS rollback_interface.cpp rollback.cpp @@ -222,22 +225,6 @@ set(common_SRCS itemdef.cpp nodedef.cpp object_properties.cpp - scriptapi_types.cpp - scriptapi_common.cpp - scriptapi_content.cpp - scriptapi_craft.cpp - scriptapi_node.cpp - scriptapi_item.cpp - scriptapi_env.cpp - scriptapi_nodetimer.cpp - scriptapi_noise.cpp - scriptapi_entity.cpp - scriptapi_object.cpp - scriptapi_nodemeta.cpp - scriptapi_inventory.cpp - scriptapi_particles.cpp - scriptapi.cpp - script.cpp log.cpp content_sao.cpp emerge.cpp @@ -283,12 +270,8 @@ set(common_SRCS staticobject.cpp serverlist.cpp pathfinder.cpp - util/serialize.cpp - util/directiontables.cpp - util/numeric.cpp - util/pointedthing.cpp - util/string.cpp - util/timetaker.cpp + ${SCRIPT_SRCS} + ${UTIL_SRCS} ) # This gives us the icon @@ -365,6 +348,7 @@ set(minetestserver_SRCS include_directories( ${PROJECT_BINARY_DIR} + ${PROJECT_SOURCE_DIR} ${IRRLICHT_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR} ${CMAKE_BUILD_TYPE} @@ -375,6 +359,7 @@ include_directories( ${SQLITE3_INCLUDE_DIR} ${LUA_INCLUDE_DIR} ${JSON_INCLUDE_DIR} + ${PROJECT_SOURCE_DIR}/script ) if(USE_FREETYPE) diff --git a/src/content_sao.cpp b/src/content_sao.cpp index 47b94a5d9..cc02a7431 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 "scriptapi.h" +#include "cpp_api/scriptapi.h" #include "genericobject.h" #include "util/serialize.h" @@ -387,8 +387,7 @@ LuaEntitySAO::LuaEntitySAO(ServerEnvironment *env, v3f pos, LuaEntitySAO::~LuaEntitySAO() { if(m_registered){ - lua_State *L = m_env->getLua(); - scriptapi_luaentity_rm(L, m_id); + ENV_TO_SA(m_env)->luaentity_Remove(m_id); } } @@ -397,16 +396,15 @@ void LuaEntitySAO::addedToEnvironment(u32 dtime_s) ServerActiveObject::addedToEnvironment(dtime_s); // Create entity from name - lua_State *L = m_env->getLua(); - m_registered = scriptapi_luaentity_add(L, m_id, m_init_name.c_str()); + m_registered = ENV_TO_SA(m_env)->luaentity_Add(m_id, m_init_name.c_str()); if(m_registered){ // Get properties - scriptapi_luaentity_get_properties(L, m_id, &m_prop); + ENV_TO_SA(m_env)->luaentity_GetProperties(m_id, &m_prop); // Initialize HP from properties m_hp = m_prop.hp_max; // Activate entity, supplying serialized state - scriptapi_luaentity_activate(L, m_id, m_init_state.c_str(), dtime_s); + ENV_TO_SA(m_env)->luaentity_Activate(m_id, m_init_state.c_str(), dtime_s); } } @@ -515,8 +513,7 @@ void LuaEntitySAO::step(float dtime, bool send_recommended) } if(m_registered){ - lua_State *L = m_env->getLua(); - scriptapi_luaentity_step(L, m_id, dtime); + ENV_TO_SA(m_env)->luaentity_Step(m_id, dtime); } if(send_recommended == false) @@ -626,8 +623,7 @@ std::string LuaEntitySAO::getStaticData() os<getLua(); - std::string state = scriptapi_luaentity_get_staticdata(L, m_id); + std::string state = ENV_TO_SA(m_env)->luaentity_GetStaticdata(m_id); os<getLua(); - scriptapi_luaentity_punch(L, m_id, puncher, + ENV_TO_SA(m_env)->luaentity_Punch(m_id, puncher, time_from_last_punch, toolcap, dir); return result.wear; @@ -708,8 +703,7 @@ void LuaEntitySAO::rightClick(ServerActiveObject *clicker) // It's best that attachments cannot be clicked if(isAttached()) return; - lua_State *L = m_env->getLua(); - scriptapi_luaentity_rightclick(L, m_id, clicker); + ENV_TO_SA(m_env)->luaentity_Rightclick(m_id, clicker); } void LuaEntitySAO::setPos(v3f pos) diff --git a/src/emerge.cpp b/src/emerge.cpp index b31a942e3..fd6c0e91f 100644 --- a/src/emerge.cpp +++ b/src/emerge.cpp @@ -32,8 +32,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mapblock.h" #include "serverobject.h" #include "settings.h" -#include "script.h" -#include "scriptapi.h" +#include "cpp_api/scriptapi.h" #include "profiler.h" #include "log.h" #include "nodedef.h" @@ -418,7 +417,7 @@ void *EmergeThread::Thread() { ign(&m_server->m_ignore_map_edit_events_area, VoxelArea(minp, maxp)); { // takes about 90ms with -O1 on an e3-1230v2 - scriptapi_environment_on_generated(m_server->m_lua, + SERVER_TO_SA(m_server)->environment_OnGenerated( minp, maxp, emerge->getBlockSeed(minp)); } diff --git a/src/environment.cpp b/src/environment.cpp index 9f87b8c91..83ae59014 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -32,7 +32,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "settings.h" #include "log.h" #include "profiler.h" -#include "scriptapi.h" +#include "cpp_api/scriptapi.h" #include "nodedef.h" #include "nodemetadata.h" #include "main.h" // For g_settings, g_profiler @@ -320,10 +320,10 @@ void ActiveBlockList::update(std::list &active_positions, ServerEnvironment */ -ServerEnvironment::ServerEnvironment(ServerMap *map, lua_State *L, +ServerEnvironment::ServerEnvironment(ServerMap *map, ScriptApi *scriptIface, IGameDef *gamedef, IBackgroundBlockEmerger *emerger): m_map(map), - m_lua(L), + m_script(scriptIface), m_gamedef(gamedef), m_emerger(emerger), m_random_spawn_timer(3), @@ -826,7 +826,7 @@ void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime) i != elapsed_timers.end(); i++){ n = block->getNodeNoEx(i->first); v3s16 p = i->first + block->getPosRelative(); - if(scriptapi_node_on_timer(m_lua,p,n,i->second.elapsed)) + if(m_script->node_on_timer(p,n,i->second.elapsed)) block->setNodeTimer(i->first,NodeTimer(i->second.timeout,0)); } } @@ -847,17 +847,17 @@ bool ServerEnvironment::setNode(v3s16 p, const MapNode &n) MapNode n_old = m_map->getNodeNoEx(p); // Call destructor if(ndef->get(n_old).has_on_destruct) - scriptapi_node_on_destruct(m_lua, p, n_old); + m_script->node_on_destruct(p, n_old); // Replace node bool succeeded = m_map->addNodeWithEvent(p, n); if(!succeeded) return false; // Call post-destructor if(ndef->get(n_old).has_after_destruct) - scriptapi_node_after_destruct(m_lua, p, n_old); + m_script->node_after_destruct(p, n_old); // Call constructor if(ndef->get(n).has_on_construct) - scriptapi_node_on_construct(m_lua, p, n); + m_script->node_on_construct(p, n); return true; } @@ -867,7 +867,7 @@ bool ServerEnvironment::removeNode(v3s16 p) MapNode n_old = m_map->getNodeNoEx(p); // Call destructor if(ndef->get(n_old).has_on_destruct) - scriptapi_node_on_destruct(m_lua, p, n_old); + m_script->node_on_destruct(p, n_old); // Replace with air // This is slightly optimized compared to addNodeWithEvent(air) bool succeeded = m_map->removeNodeWithEvent(p); @@ -875,7 +875,7 @@ bool ServerEnvironment::removeNode(v3s16 p) return false; // Call post-destructor if(ndef->get(n_old).has_after_destruct) - scriptapi_node_after_destruct(m_lua, p, n_old); + m_script->node_after_destruct(p, n_old); // Air doesn't require constructor return true; } @@ -930,7 +930,7 @@ void ServerEnvironment::clearAllObjects() // Tell the object about removal obj->removingFromEnvironment(); // Deregister in scripting api - scriptapi_rm_object_reference(m_lua, obj); + m_script->removeObjectReference(obj); // Delete active object if(obj->environmentDeletes()) @@ -1159,7 +1159,7 @@ void ServerEnvironment::step(float dtime) i != elapsed_timers.end(); i++){ n = block->getNodeNoEx(i->first); p = i->first + block->getPosRelative(); - if(scriptapi_node_on_timer(m_lua,p,n,i->second.elapsed)) + if(m_script->node_on_timer(p,n,i->second.elapsed)) block->setNodeTimer(i->first,NodeTimer(i->second.timeout,0)); } } @@ -1213,7 +1213,7 @@ void ServerEnvironment::step(float dtime) /* Step script environment (run global on_step()) */ - scriptapi_environment_step(m_lua, dtime); + m_script->environment_Step(dtime); /* Step active objects @@ -1507,7 +1507,7 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object, <addObjectReference(object); // Post-initialize object object->addedToEnvironment(dtime_s); @@ -1595,7 +1595,7 @@ void ServerEnvironment::removeRemovedObjects() // Tell the object about removal obj->removingFromEnvironment(); // Deregister in scripting api - scriptapi_rm_object_reference(m_lua, obj); + m_script->removeObjectReference(obj); // Delete if(obj->environmentDeletes()) @@ -1901,7 +1901,7 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete) // Tell the object about removal obj->removingFromEnvironment(); // Deregister in scripting api - scriptapi_rm_object_reference(m_lua, obj); + m_script->removeObjectReference(obj); // Delete active object if(obj->environmentDeletes()) diff --git a/src/environment.h b/src/environment.h index a3e43dbb4..a62173a11 100644 --- a/src/environment.h +++ b/src/environment.h @@ -50,6 +50,7 @@ class IGameDef; class Map; class ServerMap; class ClientMap; +class ScriptApi; class Environment { @@ -190,7 +191,7 @@ public: class ServerEnvironment : public Environment { public: - ServerEnvironment(ServerMap *map, lua_State *L, IGameDef *gamedef, + ServerEnvironment(ServerMap *map, ScriptApi *iface, IGameDef *gamedef, IBackgroundBlockEmerger *emerger); ~ServerEnvironment(); @@ -198,8 +199,9 @@ public: ServerMap & getServerMap(); - lua_State* getLua() - { return m_lua; } + //TODO find way to remove this fct! + ScriptApi* getScriptIface() + { return m_script; } IGameDef *getGameDef() { return m_gamedef; } @@ -348,7 +350,7 @@ private: // The map ServerMap *m_map; // Lua state - lua_State *m_lua; + ScriptApi* m_script; // Game definition IGameDef *m_gamedef; // Background block emerger (the server, in practice) diff --git a/src/hud.h b/src/hud.h index 00e44dd80..54b7e7f36 100644 --- a/src/hud.h +++ b/src/hud.h @@ -46,7 +46,7 @@ enum HudElementType { }; enum HudElementStat { - HUD_STAT_POS, + HUD_STAT_POS = 0, HUD_STAT_NAME, HUD_STAT_SCALE, HUD_STAT_TEXT, diff --git a/src/inventorymanager.cpp b/src/inventorymanager.cpp index 08cae6d40..6187675d4 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 "scriptapi.h" +#include "cpp_api/scriptapi.h" #include "serverobject.h" #include "main.h" // for g_settings #include "settings.h" @@ -226,9 +226,8 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame to_inv.type == InventoryLocation::DETACHED && from_inv.name == to_inv.name) { - lua_State *L = player->getEnv()->getLua(); - src_can_take_count = scriptapi_detached_inventory_allow_move( - L, from_inv.name, from_list, from_i, + src_can_take_count = PLAYER_TO_SA(player)->detached_inventory_AllowMove( + from_inv.name, from_list, from_i, to_list, to_i, try_take_count, player); dst_can_put_count = src_can_take_count; } @@ -237,20 +236,18 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame // Destination is detached if(to_inv.type == InventoryLocation::DETACHED) { - lua_State *L = player->getEnv()->getLua(); ItemStack src_item = list_from->getItem(from_i); src_item.count = try_take_count; - dst_can_put_count = scriptapi_detached_inventory_allow_put( - L, to_inv.name, to_list, to_i, src_item, player); + dst_can_put_count = PLAYER_TO_SA(player)->detached_inventory_AllowPut( + to_inv.name, to_list, to_i, src_item, player); } // Source is detached if(from_inv.type == InventoryLocation::DETACHED) { - lua_State *L = player->getEnv()->getLua(); ItemStack src_item = list_from->getItem(from_i); src_item.count = try_take_count; - src_can_take_count = scriptapi_detached_inventory_allow_take( - L, from_inv.name, from_list, from_i, src_item, player); + src_can_take_count = PLAYER_TO_SA(player)->detached_inventory_AllowTake( + from_inv.name, from_list, from_i, src_item, player); } } @@ -262,9 +259,8 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame to_inv.type == InventoryLocation::NODEMETA && from_inv.p == to_inv.p) { - lua_State *L = player->getEnv()->getLua(); - src_can_take_count = scriptapi_nodemeta_inventory_allow_move( - L, from_inv.p, from_list, from_i, + src_can_take_count = PLAYER_TO_SA(player)->nodemeta_inventory_AllowMove( + from_inv.p, from_list, from_i, to_list, to_i, try_take_count, player); dst_can_put_count = src_can_take_count; } @@ -273,20 +269,18 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame // Destination is nodemeta if(to_inv.type == InventoryLocation::NODEMETA) { - lua_State *L = player->getEnv()->getLua(); ItemStack src_item = list_from->getItem(from_i); src_item.count = try_take_count; - dst_can_put_count = scriptapi_nodemeta_inventory_allow_put( - L, to_inv.p, to_list, to_i, src_item, player); + dst_can_put_count = PLAYER_TO_SA(player)->nodemeta_inventory_AllowPut( + to_inv.p, to_list, to_i, src_item, player); } // Source is nodemeta if(from_inv.type == InventoryLocation::NODEMETA) { - lua_State *L = player->getEnv()->getLua(); ItemStack src_item = list_from->getItem(from_i); src_item.count = try_take_count; - src_can_take_count = scriptapi_nodemeta_inventory_allow_take( - L, from_inv.p, from_list, from_i, src_item, player); + src_can_take_count = PLAYER_TO_SA(player)->nodemeta_inventory_AllowTake( + from_inv.p, from_list, from_i, src_item, player); } } @@ -412,9 +406,8 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame to_inv.type == InventoryLocation::DETACHED && from_inv.name == to_inv.name) { - lua_State *L = player->getEnv()->getLua(); - scriptapi_detached_inventory_on_move( - L, from_inv.name, from_list, from_i, + PLAYER_TO_SA(player)->detached_inventory_OnMove( + from_inv.name, from_list, from_i, to_list, to_i, count, player); } else @@ -422,16 +415,14 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame // Destination is detached if(to_inv.type == InventoryLocation::DETACHED) { - lua_State *L = player->getEnv()->getLua(); - scriptapi_detached_inventory_on_put( - L, to_inv.name, to_list, to_i, src_item, player); + PLAYER_TO_SA(player)->detached_inventory_OnPut( + to_inv.name, to_list, to_i, src_item, player); } // Source is detached if(from_inv.type == InventoryLocation::DETACHED) { - lua_State *L = player->getEnv()->getLua(); - scriptapi_detached_inventory_on_take( - L, from_inv.name, from_list, from_i, src_item, player); + PLAYER_TO_SA(player)->detached_inventory_OnTake( + from_inv.name, from_list, from_i, src_item, player); } } @@ -442,25 +433,22 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame to_inv.type == InventoryLocation::NODEMETA && from_inv.p == to_inv.p) { - lua_State *L = player->getEnv()->getLua(); - scriptapi_nodemeta_inventory_on_move( - L, from_inv.p, from_list, from_i, + PLAYER_TO_SA(player)->nodemeta_inventory_OnMove( + from_inv.p, from_list, from_i, to_list, to_i, count, player); } else{ // Destination is nodemeta if(to_inv.type == InventoryLocation::NODEMETA) { - lua_State *L = player->getEnv()->getLua(); - scriptapi_nodemeta_inventory_on_put( - L, to_inv.p, to_list, to_i, src_item, player); + PLAYER_TO_SA(player)->nodemeta_inventory_OnPut( + to_inv.p, to_list, to_i, src_item, player); } // Source is nodemeta else if(from_inv.type == InventoryLocation::NODEMETA) { - lua_State *L = player->getEnv()->getLua(); - scriptapi_nodemeta_inventory_on_take( - L, from_inv.p, from_list, from_i, src_item, player); + PLAYER_TO_SA(player)->nodemeta_inventory_OnTake( + from_inv.p, from_list, from_i, src_item, player); } } @@ -563,21 +551,19 @@ void IDropAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame // Source is detached if(from_inv.type == InventoryLocation::DETACHED) { - lua_State *L = player->getEnv()->getLua(); ItemStack src_item = list_from->getItem(from_i); src_item.count = take_count; - src_can_take_count = scriptapi_detached_inventory_allow_take( - L, from_inv.name, from_list, from_i, src_item, player); + src_can_take_count = PLAYER_TO_SA(player)->detached_inventory_AllowTake( + from_inv.name, from_list, from_i, src_item, player); } // Source is nodemeta if(from_inv.type == InventoryLocation::NODEMETA) { - lua_State *L = player->getEnv()->getLua(); ItemStack src_item = list_from->getItem(from_i); src_item.count = take_count; - src_can_take_count = scriptapi_nodemeta_inventory_allow_take( - L, from_inv.p, from_list, from_i, src_item, player); + src_can_take_count = PLAYER_TO_SA(player)->nodemeta_inventory_AllowTake( + from_inv.p, from_list, from_i, src_item, player); } if(src_can_take_count != -1 && src_can_take_count < take_count) @@ -590,7 +576,7 @@ void IDropAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame // Drop the item ItemStack item1 = list_from->getItem(from_i); item1.count = take_count; - if(scriptapi_item_on_drop(player->getEnv()->getLua(), item1, player, + if(PLAYER_TO_SA(player)->item_OnDrop(item1, player, player->getBasePosition() + v3f(0,1,0))) { actually_dropped_count = take_count - item1.count; @@ -627,17 +613,15 @@ void IDropAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame // Source is detached if(from_inv.type == InventoryLocation::DETACHED) { - lua_State *L = player->getEnv()->getLua(); - scriptapi_detached_inventory_on_take( - L, from_inv.name, from_list, from_i, src_item, player); + PLAYER_TO_SA(player)->detached_inventory_OnTake( + from_inv.name, from_list, from_i, src_item, player); } // Source is nodemeta if(from_inv.type == InventoryLocation::NODEMETA) { - lua_State *L = player->getEnv()->getLua(); - scriptapi_nodemeta_inventory_on_take( - L, from_inv.p, from_list, from_i, src_item, player); + PLAYER_TO_SA(player)->nodemeta_inventory_OnTake( + from_inv.p, from_list, from_i, src_item, player); } /* diff --git a/src/jthread/jmutex.h b/src/jthread/jmutex.h index e528aeb4a..383150f3f 100644 --- a/src/jthread/jmutex.h +++ b/src/jthread/jmutex.h @@ -57,6 +57,7 @@ public: int Lock(); int Unlock(); bool IsInitialized() { return initialized; } + private: #if (defined(WIN32) || defined(_WIN32_WCE)) #ifdef JMUTEX_CRITICALSECTION @@ -66,6 +67,14 @@ private: #endif // JMUTEX_CRITICALSECTION #else // pthread mutex pthread_mutex_t mutex; + + bool IsLocked() { + if (pthread_mutex_trylock(&mutex)) { + pthread_mutex_unlock(&mutex); + return true; + } + return false; + } #endif // WIN32 bool initialized; }; diff --git a/src/script.cpp b/src/script.cpp deleted file mode 100644 index 4619fa636..000000000 --- a/src/script.cpp +++ /dev/null @@ -1,126 +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. -*/ - -#include "script.h" -#include -#include -#include -#include -#include "log.h" -#include - -extern "C" { -#include -#include -#include -} - -LuaError::LuaError(lua_State *L, const std::string &s) -{ - m_s = "LuaError: "; - m_s += s + "\n"; - m_s += script_get_backtrace(L); -} - -std::string script_get_backtrace(lua_State *L) -{ - std::string s; - lua_getfield(L, LUA_GLOBALSINDEX, "debug"); - if(lua_istable(L, -1)){ - lua_getfield(L, -1, "traceback"); - if(lua_isfunction(L, -1)){ - lua_call(L, 0, 1); - if(lua_isstring(L, -1)){ - s += lua_tostring(L, -1); - } - lua_pop(L, 1); - } - else{ - lua_pop(L, 1); - } - } - lua_pop(L, 1); - return s; -} - -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: "< - -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 SCRIPT_HEADER -#define SCRIPT_HEADER - -#include -#include - -typedef struct lua_State lua_State; - -class LuaError : public std::exception -{ -public: - LuaError(lua_State *L, const std::string &s); - - virtual ~LuaError() throw() - {} - virtual const char * what() const throw() - { - return m_s.c_str(); - } - std::string m_s; -}; - -lua_State* script_init(); -void script_deinit(lua_State *L); -std::string script_get_backtrace(lua_State *L); -void script_error(lua_State *L, const char *fmt, ...); -bool script_load(lua_State *L, const char *path); - -#endif - diff --git a/src/script/CMakeLists.txt b/src/script/CMakeLists.txt new file mode 100644 index 000000000..e1a03b95a --- /dev/null +++ b/src/script/CMakeLists.txt @@ -0,0 +1,9 @@ +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} + PARENT_SCOPE) diff --git a/src/script/common/CMakeLists.txt b/src/script/common/CMakeLists.txt new file mode 100644 index 000000000..c8f7ef783 --- /dev/null +++ b/src/script/common/CMakeLists.txt @@ -0,0 +1,6 @@ +set(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) diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp new file mode 100644 index 000000000..c7966a0be --- /dev/null +++ b/src/script/common/c_content.cpp @@ -0,0 +1,923 @@ +/* +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 "common/c_content.h" +#include "common/c_converter.h" +#include "common/c_types.h" +#include "nodedef.h" +#include "itemdef.h" +#include "object_properties.h" +#include "cpp_api/s_node.h" +#include "lua_api/l_object.h" +#include "lua_api/l_item.h" +#include "common/c_internal.h" +#include "server.h" +#include "log.h" +#include "tool.h" +#include "server.h" + +struct EnumString es_TileAnimationType[] = +{ + {TAT_NONE, "none"}, + {TAT_VERTICAL_FRAMES, "vertical_frames"}, + {0, NULL}, +}; + +/******************************************************************************/ +ItemDefinition read_item_definition(lua_State* L,int index, + ItemDefinition default_def) +{ + if(index < 0) + index = lua_gettop(L) + 1 + index; + + // Read the item definition + ItemDefinition def = default_def; + + def.type = (ItemType)getenumfield(L, index, "type", + es_ItemType, ITEM_NONE); + getstringfield(L, index, "name", def.name); + getstringfield(L, index, "description", def.description); + getstringfield(L, index, "inventory_image", def.inventory_image); + getstringfield(L, index, "wield_image", def.wield_image); + + lua_getfield(L, index, "wield_scale"); + if(lua_istable(L, -1)){ + def.wield_scale = check_v3f(L, -1); + } + lua_pop(L, 1); + + def.stack_max = getintfield_default(L, index, "stack_max", def.stack_max); + if(def.stack_max == 0) + def.stack_max = 1; + + lua_getfield(L, index, "on_use"); + def.usable = lua_isfunction(L, -1); + lua_pop(L, 1); + + getboolfield(L, index, "liquids_pointable", def.liquids_pointable); + + warn_if_field_exists(L, index, "tool_digging_properties", + "deprecated: use tool_capabilities"); + + lua_getfield(L, index, "tool_capabilities"); + if(lua_istable(L, -1)){ + def.tool_capabilities = new ToolCapabilities( + read_tool_capabilities(L, -1)); + } + + // If name is "" (hand), ensure there are ToolCapabilities + // because it will be looked up there whenever any other item has + // no ToolCapabilities + if(def.name == "" && def.tool_capabilities == NULL){ + def.tool_capabilities = new ToolCapabilities(); + } + + lua_getfield(L, index, "groups"); + read_groups(L, -1, def.groups); + lua_pop(L, 1); + + lua_getfield(L, index, "sounds"); + if(lua_istable(L, -1)){ + lua_getfield(L, -1, "place"); + read_soundspec(L, -1, def.sound_place); + lua_pop(L, 1); + } + lua_pop(L, 1); + + // Client shall immediately place this node when player places the item. + // Server will update the precise end result a moment later. + // "" = no prediction + getstringfield(L, index, "node_placement_prediction", + def.node_placement_prediction); + + return def; +} + +/******************************************************************************/ +void read_object_properties(lua_State *L, int index, + ObjectProperties *prop) +{ + if(index < 0) + index = lua_gettop(L) + 1 + index; + if(!lua_istable(L, index)) + return; + + prop->hp_max = getintfield_default(L, -1, "hp_max", 10); + + getboolfield(L, -1, "physical", prop->physical); + + getfloatfield(L, -1, "weight", prop->weight); + + lua_getfield(L, -1, "collisionbox"); + if(lua_istable(L, -1)) + prop->collisionbox = read_aabb3f(L, -1, 1.0); + lua_pop(L, 1); + + getstringfield(L, -1, "visual", prop->visual); + + getstringfield(L, -1, "mesh", prop->mesh); + + lua_getfield(L, -1, "visual_size"); + if(lua_istable(L, -1)) + prop->visual_size = read_v2f(L, -1); + lua_pop(L, 1); + + lua_getfield(L, -1, "textures"); + if(lua_istable(L, -1)){ + prop->textures.clear(); + int table = lua_gettop(L); + lua_pushnil(L); + while(lua_next(L, table) != 0){ + // key at index -2 and value at index -1 + if(lua_isstring(L, -1)) + prop->textures.push_back(lua_tostring(L, -1)); + else + prop->textures.push_back(""); + // removes value, keeps key for next iteration + lua_pop(L, 1); + } + } + lua_pop(L, 1); + + lua_getfield(L, -1, "colors"); + if(lua_istable(L, -1)){ + prop->colors.clear(); + int table = lua_gettop(L); + lua_pushnil(L); + while(lua_next(L, table) != 0){ + // key at index -2 and value at index -1 + if(lua_isstring(L, -1)) + prop->colors.push_back(readARGB8(L, -1)); + else + prop->colors.push_back(video::SColor(255, 255, 255, 255)); + // removes value, keeps key for next iteration + lua_pop(L, 1); + } + } + lua_pop(L, 1); + + lua_getfield(L, -1, "spritediv"); + if(lua_istable(L, -1)) + prop->spritediv = read_v2s16(L, -1); + lua_pop(L, 1); + + lua_getfield(L, -1, "initial_sprite_basepos"); + if(lua_istable(L, -1)) + prop->initial_sprite_basepos = read_v2s16(L, -1); + lua_pop(L, 1); + + getboolfield(L, -1, "is_visible", prop->is_visible); + getboolfield(L, -1, "makes_footstep_sound", prop->makes_footstep_sound); + getfloatfield(L, -1, "automatic_rotate", prop->automatic_rotate); +} + +/******************************************************************************/ +TileDef read_tiledef(lua_State *L, int index) +{ + if(index < 0) + index = lua_gettop(L) + 1 + index; + + TileDef tiledef; + + // key at index -2 and value at index + if(lua_isstring(L, index)){ + // "default_lava.png" + tiledef.name = lua_tostring(L, index); + } + else if(lua_istable(L, index)) + { + // {name="default_lava.png", animation={}} + tiledef.name = ""; + getstringfield(L, index, "name", tiledef.name); + getstringfield(L, index, "image", tiledef.name); // MaterialSpec compat. + tiledef.backface_culling = getboolfield_default( + L, index, "backface_culling", true); + // animation = {} + lua_getfield(L, index, "animation"); + if(lua_istable(L, -1)){ + // {type="vertical_frames", aspect_w=16, aspect_h=16, length=2.0} + tiledef.animation.type = (TileAnimationType) + getenumfield(L, -1, "type", es_TileAnimationType, + TAT_NONE); + tiledef.animation.aspect_w = + getintfield_default(L, -1, "aspect_w", 16); + tiledef.animation.aspect_h = + getintfield_default(L, -1, "aspect_h", 16); + tiledef.animation.length = + getfloatfield_default(L, -1, "length", 1.0); + } + lua_pop(L, 1); + } + + return tiledef; +} + +/******************************************************************************/ +ContentFeatures read_content_features(lua_State *L, int index) +{ + if(index < 0) + index = lua_gettop(L) + 1 + index; + + ContentFeatures f; + + /* Cache existence of some callbacks */ + lua_getfield(L, index, "on_construct"); + if(!lua_isnil(L, -1)) f.has_on_construct = true; + lua_pop(L, 1); + lua_getfield(L, index, "on_destruct"); + if(!lua_isnil(L, -1)) f.has_on_destruct = true; + lua_pop(L, 1); + lua_getfield(L, index, "after_destruct"); + if(!lua_isnil(L, -1)) f.has_after_destruct = true; + lua_pop(L, 1); + + lua_getfield(L, index, "on_rightclick"); + f.rightclickable = lua_isfunction(L, -1); + lua_pop(L, 1); + + /* Name */ + getstringfield(L, index, "name", f.name); + + /* Groups */ + lua_getfield(L, index, "groups"); + read_groups(L, -1, f.groups); + lua_pop(L, 1); + + /* Visual definition */ + + f.drawtype = (NodeDrawType)getenumfield(L, index, "drawtype", + ScriptApiNode::es_DrawType,NDT_NORMAL); + getfloatfield(L, index, "visual_scale", f.visual_scale); + + // tiles = {} + lua_getfield(L, index, "tiles"); + // If nil, try the deprecated name "tile_images" instead + if(lua_isnil(L, -1)){ + lua_pop(L, 1); + warn_if_field_exists(L, index, "tile_images", + "Deprecated; new name is \"tiles\"."); + lua_getfield(L, index, "tile_images"); + } + if(lua_istable(L, -1)){ + int table = lua_gettop(L); + lua_pushnil(L); + int i = 0; + while(lua_next(L, table) != 0){ + // Read tiledef from value + f.tiledef[i] = read_tiledef(L, -1); + // removes value, keeps key for next iteration + lua_pop(L, 1); + i++; + if(i==6){ + lua_pop(L, 1); + break; + } + } + // Copy last value to all remaining textures + if(i >= 1){ + TileDef lasttile = f.tiledef[i-1]; + while(i < 6){ + f.tiledef[i] = lasttile; + i++; + } + } + } + lua_pop(L, 1); + + // special_tiles = {} + lua_getfield(L, index, "special_tiles"); + // If nil, try the deprecated name "special_materials" instead + if(lua_isnil(L, -1)){ + lua_pop(L, 1); + warn_if_field_exists(L, index, "special_materials", + "Deprecated; new name is \"special_tiles\"."); + lua_getfield(L, index, "special_materials"); + } + if(lua_istable(L, -1)){ + int table = lua_gettop(L); + lua_pushnil(L); + int i = 0; + while(lua_next(L, table) != 0){ + // Read tiledef from value + f.tiledef_special[i] = read_tiledef(L, -1); + // removes value, keeps key for next iteration + lua_pop(L, 1); + i++; + if(i==6){ + lua_pop(L, 1); + break; + } + } + } + lua_pop(L, 1); + + f.alpha = getintfield_default(L, index, "alpha", 255); + + bool usealpha = getboolfield_default(L, index, + "use_texture_alpha", false); + if (usealpha) + f.alpha = 0; + + /* Other stuff */ + + lua_getfield(L, index, "post_effect_color"); + if(!lua_isnil(L, -1)) + f.post_effect_color = readARGB8(L, -1); + lua_pop(L, 1); + + f.param_type = (ContentParamType)getenumfield(L, index, "paramtype", + ScriptApiNode::es_ContentParamType, CPT_NONE); + f.param_type_2 = (ContentParamType2)getenumfield(L, index, "paramtype2", + ScriptApiNode::es_ContentParamType2, CPT2_NONE); + + // Warn about some deprecated fields + warn_if_field_exists(L, index, "wall_mounted", + "deprecated: use paramtype2 = 'wallmounted'"); + warn_if_field_exists(L, index, "light_propagates", + "deprecated: determined from paramtype"); + warn_if_field_exists(L, index, "dug_item", + "deprecated: use 'drop' field"); + warn_if_field_exists(L, index, "extra_dug_item", + "deprecated: use 'drop' field"); + warn_if_field_exists(L, index, "extra_dug_item_rarity", + "deprecated: use 'drop' field"); + warn_if_field_exists(L, index, "metadata_name", + "deprecated: use on_add and metadata callbacks"); + + // True for all ground-like things like stone and mud, false for eg. trees + getboolfield(L, index, "is_ground_content", f.is_ground_content); + f.light_propagates = (f.param_type == CPT_LIGHT); + getboolfield(L, index, "sunlight_propagates", f.sunlight_propagates); + // This is used for collision detection. + // Also for general solidness queries. + getboolfield(L, index, "walkable", f.walkable); + // Player can point to these + getboolfield(L, index, "pointable", f.pointable); + // Player can dig these + getboolfield(L, index, "diggable", f.diggable); + // Player can climb these + getboolfield(L, index, "climbable", f.climbable); + // Player can build on these + getboolfield(L, index, "buildable_to", f.buildable_to); + // Whether the node is non-liquid, source liquid or flowing liquid + f.liquid_type = (LiquidType)getenumfield(L, index, "liquidtype", + ScriptApiNode::es_LiquidType, LIQUID_NONE); + // If the content is liquid, this is the flowing version of the liquid. + getstringfield(L, index, "liquid_alternative_flowing", + f.liquid_alternative_flowing); + // If the content is liquid, this is the source version of the liquid. + getstringfield(L, index, "liquid_alternative_source", + f.liquid_alternative_source); + // Viscosity for fluid flow, ranging from 1 to 7, with + // 1 giving almost instantaneous propagation and 7 being + // the slowest possible + f.liquid_viscosity = getintfield_default(L, index, + "liquid_viscosity", f.liquid_viscosity); + getboolfield(L, index, "liquid_renewable", f.liquid_renewable); + // Amount of light the node emits + f.light_source = getintfield_default(L, index, + "light_source", f.light_source); + f.damage_per_second = getintfield_default(L, index, + "damage_per_second", f.damage_per_second); + + lua_getfield(L, index, "node_box"); + if(lua_istable(L, -1)) + f.node_box = read_nodebox(L, -1); + lua_pop(L, 1); + + lua_getfield(L, index, "selection_box"); + if(lua_istable(L, -1)) + f.selection_box = read_nodebox(L, -1); + lua_pop(L, 1); + + // Set to true if paramtype used to be 'facedir_simple' + getboolfield(L, index, "legacy_facedir_simple", f.legacy_facedir_simple); + // Set to true if wall_mounted used to be set to true + getboolfield(L, index, "legacy_wallmounted", f.legacy_wallmounted); + + // Sound table + lua_getfield(L, index, "sounds"); + if(lua_istable(L, -1)){ + lua_getfield(L, -1, "footstep"); + read_soundspec(L, -1, f.sound_footstep); + lua_pop(L, 1); + lua_getfield(L, -1, "dig"); + read_soundspec(L, -1, f.sound_dig); + lua_pop(L, 1); + lua_getfield(L, -1, "dug"); + read_soundspec(L, -1, f.sound_dug); + lua_pop(L, 1); + } + lua_pop(L, 1); + + return f; +} + +/******************************************************************************/ +void read_server_sound_params(lua_State *L, int index, + ServerSoundParams ¶ms) +{ + if(index < 0) + index = lua_gettop(L) + 1 + index; + // Clear + params = ServerSoundParams(); + if(lua_istable(L, index)){ + getfloatfield(L, index, "gain", params.gain); + getstringfield(L, index, "to_player", params.to_player); + lua_getfield(L, index, "pos"); + if(!lua_isnil(L, -1)){ + v3f p = read_v3f(L, -1)*BS; + params.pos = p; + params.type = ServerSoundParams::SSP_POSITIONAL; + } + lua_pop(L, 1); + lua_getfield(L, index, "object"); + if(!lua_isnil(L, -1)){ + ObjectRef *ref = ObjectRef::checkobject(L, -1); + ServerActiveObject *sao = ObjectRef::getobject(ref); + if(sao){ + params.object = sao->getId(); + params.type = ServerSoundParams::SSP_OBJECT; + } + } + lua_pop(L, 1); + params.max_hear_distance = BS*getfloatfield_default(L, index, + "max_hear_distance", params.max_hear_distance/BS); + getboolfield(L, index, "loop", params.loop); + } +} + +/******************************************************************************/ +void read_soundspec(lua_State *L, int index, SimpleSoundSpec &spec) +{ + if(index < 0) + index = lua_gettop(L) + 1 + index; + if(lua_isnil(L, index)){ + } else if(lua_istable(L, index)){ + getstringfield(L, index, "name", spec.name); + getfloatfield(L, index, "gain", spec.gain); + } else if(lua_isstring(L, index)){ + spec.name = lua_tostring(L, index); + } +} + +/******************************************************************************/ +NodeBox read_nodebox(lua_State *L, int index) +{ + NodeBox nodebox; + if(lua_istable(L, -1)){ + nodebox.type = (NodeBoxType)getenumfield(L, index, "type", + ScriptApiNode::es_NodeBoxType, NODEBOX_REGULAR); + + lua_getfield(L, index, "fixed"); + if(lua_istable(L, -1)) + nodebox.fixed = read_aabb3f_vector(L, -1, BS); + lua_pop(L, 1); + + lua_getfield(L, index, "wall_top"); + if(lua_istable(L, -1)) + nodebox.wall_top = read_aabb3f(L, -1, BS); + lua_pop(L, 1); + + lua_getfield(L, index, "wall_bottom"); + if(lua_istable(L, -1)) + nodebox.wall_bottom = read_aabb3f(L, -1, BS); + lua_pop(L, 1); + + lua_getfield(L, index, "wall_side"); + if(lua_istable(L, -1)) + nodebox.wall_side = read_aabb3f(L, -1, BS); + lua_pop(L, 1); + } + return nodebox; +} + +/******************************************************************************/ +MapNode readnode(lua_State *L, int index, INodeDefManager *ndef) +{ + lua_getfield(L, index, "name"); + const char *name = luaL_checkstring(L, -1); + lua_pop(L, 1); + u8 param1; + lua_getfield(L, index, "param1"); + if(lua_isnil(L, -1)) + param1 = 0; + else + param1 = lua_tonumber(L, -1); + lua_pop(L, 1); + u8 param2; + lua_getfield(L, index, "param2"); + if(lua_isnil(L, -1)) + param2 = 0; + else + param2 = lua_tonumber(L, -1); + lua_pop(L, 1); + return MapNode(ndef, name, param1, param2); +} + +/******************************************************************************/ +void pushnode(lua_State *L, const MapNode &n, INodeDefManager *ndef) +{ + lua_newtable(L); + lua_pushstring(L, ndef->get(n).name.c_str()); + lua_setfield(L, -2, "name"); + lua_pushnumber(L, n.getParam1()); + lua_setfield(L, -2, "param1"); + lua_pushnumber(L, n.getParam2()); + lua_setfield(L, -2, "param2"); +} + +/******************************************************************************/ +void warn_if_field_exists(lua_State *L, int table, + const char *fieldname, const std::string &message) +{ + lua_getfield(L, table, fieldname); + if(!lua_isnil(L, -1)){ +//TODO find way to access backtrace fct from here + // infostream<str){ + if(str == std::string(esp->str)){ + result = esp->num; + return true; + } + esp++; + } + return false; +} + +/******************************************************************************/ +ItemStack read_item(lua_State* L, int index,Server* srv) +{ + if(index < 0) + index = lua_gettop(L) + 1 + index; + + if(lua_isnil(L, index)) + { + return ItemStack(); + } + else if(lua_isuserdata(L, index)) + { + // Convert from LuaItemStack + LuaItemStack *o = LuaItemStack::checkobject(L, index); + return o->getItem(); + } + else if(lua_isstring(L, index)) + { + // Convert from itemstring + std::string itemstring = lua_tostring(L, index); + IItemDefManager *idef = srv->idef(); + try + { + ItemStack item; + item.deSerialize(itemstring, idef); + return item; + } + catch(SerializationError &e) + { + infostream<<"WARNING: unable to create item from itemstring" + <<": "<idef(); + std::string name = getstringfield_default(L, index, "name", ""); + int count = getintfield_default(L, index, "count", 1); + int wear = getintfield_default(L, index, "wear", 0); + std::string metadata = getstringfield_default(L, index, "metadata", ""); + return ItemStack(name, count, wear, metadata, idef); + } + else + { + throw LuaError(L, "Expecting itemstack, itemstring, table or nil"); + } +} + +/******************************************************************************/ +void push_tool_capabilities(lua_State *L, + const ToolCapabilities &toolcap) +{ + lua_newtable(L); + setfloatfield(L, -1, "full_punch_interval", toolcap.full_punch_interval); + setintfield(L, -1, "max_drop_level", toolcap.max_drop_level); + // Create groupcaps table + lua_newtable(L); + // For each groupcap + for(std::map::const_iterator + i = toolcap.groupcaps.begin(); i != toolcap.groupcaps.end(); i++){ + // Create groupcap table + lua_newtable(L); + const std::string &name = i->first; + const ToolGroupCap &groupcap = i->second; + // Create subtable "times" + lua_newtable(L); + for(std::map::const_iterator + i = groupcap.times.begin(); i != groupcap.times.end(); i++){ + int rating = i->first; + float time = i->second; + lua_pushinteger(L, rating); + lua_pushnumber(L, time); + lua_settable(L, -3); + } + // Set subtable "times" + lua_setfield(L, -2, "times"); + // Set simple parameters + setintfield(L, -1, "maxlevel", groupcap.maxlevel); + setintfield(L, -1, "uses", groupcap.uses); + // Insert groupcap table into groupcaps table + lua_setfield(L, -2, name.c_str()); + } + // Set groupcaps table + lua_setfield(L, -2, "groupcaps"); + //Create damage_groups table + lua_newtable(L); + // For each damage group + for(std::map::const_iterator + i = toolcap.damageGroups.begin(); i != toolcap.damageGroups.end(); i++){ + // Create damage group table + lua_pushinteger(L, i->second); + lua_setfield(L, -2, i->first.c_str()); + } + lua_setfield(L, -2, "damage_groups"); +} + +/******************************************************************************/ +void push_inventory_list(Inventory *inv, const char *name, + lua_State *L) +{ + InventoryList *invlist = inv->getList(name); + if(invlist == NULL){ + lua_pushnil(L); + return; + } + std::vector items; + for(u32 i=0; igetSize(); i++) + items.push_back(invlist->getItem(i)); + push_items(L, items); +} + +/******************************************************************************/ +void read_inventory_list(Inventory *inv, const char *name, + lua_State *L, int tableindex, Server* srv,int forcesize) +{ + if(tableindex < 0) + tableindex = lua_gettop(L) + 1 + tableindex; + // If nil, delete list + if(lua_isnil(L, tableindex)){ + inv->deleteList(name); + return; + } + // Otherwise set list + std::vector items = read_items(L, tableindex,srv); + int listsize = (forcesize != -1) ? forcesize : items.size(); + InventoryList *invlist = inv->addList(name, listsize); + int index = 0; + for(std::vector::const_iterator + i = items.begin(); i != items.end(); i++){ + if(forcesize != -1 && index == forcesize) + break; + invlist->changeItem(index, *i); + index++; + } + while(forcesize != -1 && index < forcesize){ + invlist->deleteItem(index); + index++; + } +} + +/******************************************************************************/ +ToolCapabilities read_tool_capabilities( + lua_State *L, int table) +{ + ToolCapabilities toolcap; + getfloatfield(L, table, "full_punch_interval", toolcap.full_punch_interval); + getintfield(L, table, "max_drop_level", toolcap.max_drop_level); + lua_getfield(L, table, "groupcaps"); + if(lua_istable(L, -1)){ + int table_groupcaps = lua_gettop(L); + lua_pushnil(L); + while(lua_next(L, table_groupcaps) != 0){ + // key at index -2 and value at index -1 + std::string groupname = luaL_checkstring(L, -2); + if(lua_istable(L, -1)){ + int table_groupcap = lua_gettop(L); + // This will be created + ToolGroupCap groupcap; + // Read simple parameters + getintfield(L, table_groupcap, "maxlevel", groupcap.maxlevel); + getintfield(L, table_groupcap, "uses", groupcap.uses); + // DEPRECATED: maxwear + float maxwear = 0; + if(getfloatfield(L, table_groupcap, "maxwear", maxwear)){ + if(maxwear != 0) + groupcap.uses = 1.0/maxwear; + else + groupcap.uses = 0; + infostream< &result) +{ + if (!lua_istable(L,index)) + return; + 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 name = luaL_checkstring(L, -2); + int rating = luaL_checkinteger(L, -1); + result[name] = rating; + // removes value, keeps key for next iteration + lua_pop(L, 1); + } +} + +/******************************************************************************/ +void push_items(lua_State *L, const std::vector &items) +{ + // Get the table insert function + lua_getglobal(L, "table"); + lua_getfield(L, -1, "insert"); + int table_insert = lua_gettop(L); + // Create and fill table + lua_newtable(L); + int table = lua_gettop(L); + for(u32 i=0; i read_items(lua_State *L, int index,Server* srv) +{ + if(index < 0) + index = lua_gettop(L) + 1 + index; + + std::vector items; + luaL_checktype(L, index, LUA_TTABLE); + lua_pushnil(L); + while(lua_next(L, index) != 0){ + // key at index -2 and value at index -1 + items.push_back(read_item(L, -1, srv)); + // removes value, keeps key for next iteration + lua_pop(L, 1); + } + return items; +} + +/******************************************************************************/ +void luaentity_get(lua_State *L, u16 id) +{ + // Get minetest.luaentities[i] + lua_getglobal(L, "minetest"); + lua_getfield(L, -1, "luaentities"); + luaL_checktype(L, -1, LUA_TTABLE); + lua_pushnumber(L, id); + lua_gettable(L, -2); + lua_remove(L, -2); // luaentities + lua_remove(L, -2); // minetest +} + +/******************************************************************************/ +NoiseParams *read_noiseparams(lua_State *L, int index) +{ + if (index < 0) + index = lua_gettop(L) + 1 + index; + + if (!lua_istable(L, index)) + return NULL; + + NoiseParams *np = new NoiseParams; + + np->offset = getfloatfield_default(L, index, "offset", 0.0); + np->scale = getfloatfield_default(L, index, "scale", 0.0); + lua_getfield(L, index, "spread"); + np->spread = read_v3f(L, -1); + lua_pop(L, 1); + np->seed = getintfield_default(L, index, "seed", 0); + np->octaves = getintfield_default(L, index, "octaves", 0); + np->persist = getfloatfield_default(L, index, "persist", 0.0); + + return np; +} diff --git a/src/script/common/c_content.h b/src/script/common/c_content.h new file mode 100644 index 000000000..251a72e27 --- /dev/null +++ b/src/script/common/c_content.h @@ -0,0 +1,146 @@ +/* +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 script/modapi file!!!!!!!! */ +/******************************************************************************/ +/******************************************************************************/ + +#ifndef C_CONTENT_H_ +#define C_CONTENT_H_ + +extern "C" { +#include +} + +#include +#include +#include + +#include "irrlichttypes_bloated.h" +#include "util/string.h" + +class MapNode; +class INodeDefManager; +class PointedThing; +class ItemStack; +class ItemDefinition; +class ToolCapabilities; +class ObjectProperties; +class SimpleSoundSpec; +class ServerSoundParams; +class Inventory; +class NodeBox; +class ContentFeatures; +class TileDef; +class Server; +struct DigParams; +struct HitParams; +struct EnumString; +struct NoiseParams; + + +ContentFeatures read_content_features (lua_State *L, int index); +TileDef read_tiledef (lua_State *L, int index); +void read_soundspec (lua_State *L, int index, + SimpleSoundSpec &spec); +NodeBox read_nodebox (lua_State *L, int index); + +void read_server_sound_params (lua_State *L, int index, + ServerSoundParams ¶ms); + +void push_dig_params (lua_State *L,const DigParams ¶ms); +void push_hit_params (lua_State *L,const HitParams ¶ms); + +ItemStack read_item (lua_State *L, int index, Server* srv); + + +ToolCapabilities read_tool_capabilities (lua_State *L, + int table); +void push_tool_capabilities (lua_State *L, + const ToolCapabilities &prop); + +ItemDefinition read_item_definition (lua_State *L, + int index, + ItemDefinition default_def); +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, + int tableindex, + Server* srv, + int forcesize=-1); + +MapNode readnode (lua_State *L, + int index, + INodeDefManager *ndef); +void pushnode (lua_State *L, + const MapNode &n, + INodeDefManager *ndef); + +NodeBox read_nodebox (lua_State *L, int index); + +void read_groups (lua_State *L, + int index, + std::map &result); + +//TODO rename to "read_enum_field" +int getenumfield (lua_State *L, + int table, + const char *fieldname, + const EnumString *spec, + int default_); + +u32 getflagsfield (lua_State *L, int table, + const char *fieldname, + FlagDesc *flagdesc); + +void push_items (lua_State *L, + const std::vector &items); + +std::vector read_items (lua_State *L, + int index, + Server* srv); + +void read_soundspec (lua_State *L, + int index, + SimpleSoundSpec &spec); + + +bool string_to_enum (const EnumString *spec, + int &result, + const std::string &str); + +NoiseParams* read_noiseparams (lua_State *L, int index); + +void luaentity_get (lua_State *L,u16 id); + +extern struct EnumString es_TileAnimationType[]; + +#endif /* C_CONTENT_H_ */ diff --git a/src/script/common/c_converter.cpp b/src/script/common/c_converter.cpp new file mode 100644 index 000000000..65c3654ae --- /dev/null +++ b/src/script/common/c_converter.cpp @@ -0,0 +1,343 @@ +/* +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 "util/numeric.h" +#include "common/c_converter.h" +#include "constants.h" + +void push_v3f(lua_State *L, v3f p) +{ + lua_newtable(L); + lua_pushnumber(L, p.X); + lua_setfield(L, -2, "x"); + lua_pushnumber(L, p.Y); + lua_setfield(L, -2, "y"); + lua_pushnumber(L, p.Z); + lua_setfield(L, -2, "z"); +} + +void push_v2f(lua_State *L, v2f p) +{ + lua_newtable(L); + lua_pushnumber(L, p.X); + lua_setfield(L, -2, "x"); + lua_pushnumber(L, p.Y); + lua_setfield(L, -2, "y"); +} + +v2s16 read_v2s16(lua_State *L, int index) +{ + v2s16 p; + luaL_checktype(L, index, LUA_TTABLE); + lua_getfield(L, index, "x"); + p.X = lua_tonumber(L, -1); + lua_pop(L, 1); + lua_getfield(L, index, "y"); + p.Y = lua_tonumber(L, -1); + lua_pop(L, 1); + return p; +} + +v2f read_v2f(lua_State *L, int index) +{ + v2f p; + luaL_checktype(L, index, LUA_TTABLE); + lua_getfield(L, index, "x"); + p.X = lua_tonumber(L, -1); + lua_pop(L, 1); + lua_getfield(L, index, "y"); + p.Y = lua_tonumber(L, -1); + lua_pop(L, 1); + return p; +} + +v3f read_v3f(lua_State *L, int index) +{ + v3f pos; + luaL_checktype(L, index, LUA_TTABLE); + lua_getfield(L, index, "x"); + pos.X = lua_tonumber(L, -1); + lua_pop(L, 1); + lua_getfield(L, index, "y"); + pos.Y = lua_tonumber(L, -1); + lua_pop(L, 1); + lua_getfield(L, index, "z"); + pos.Z = lua_tonumber(L, -1); + lua_pop(L, 1); + return pos; +} + +v3f check_v3f(lua_State *L, int index) +{ + v3f pos; + luaL_checktype(L, index, LUA_TTABLE); + lua_getfield(L, index, "x"); + pos.X = luaL_checknumber(L, -1); + lua_pop(L, 1); + lua_getfield(L, index, "y"); + pos.Y = luaL_checknumber(L, -1); + lua_pop(L, 1); + lua_getfield(L, index, "z"); + pos.Z = luaL_checknumber(L, -1); + lua_pop(L, 1); + return pos; +} + +void pushFloatPos(lua_State *L, v3f p) +{ + p /= BS; + push_v3f(L, p); +} + +v3f checkFloatPos(lua_State *L, int index) +{ + return check_v3f(L, index) * BS; +} + +void push_v3s16(lua_State *L, v3s16 p) +{ + lua_newtable(L); + lua_pushnumber(L, p.X); + lua_setfield(L, -2, "x"); + lua_pushnumber(L, p.Y); + lua_setfield(L, -2, "y"); + lua_pushnumber(L, p.Z); + lua_setfield(L, -2, "z"); +} + +v3s16 read_v3s16(lua_State *L, int index) +{ + // Correct rounding at <0 + v3f pf = read_v3f(L, index); + return floatToInt(pf, 1.0); +} + +v3s16 check_v3s16(lua_State *L, int index) +{ + // Correct rounding at <0 + v3f pf = check_v3f(L, index); + return floatToInt(pf, 1.0); +} + +video::SColor readARGB8(lua_State *L, int index) +{ + video::SColor color(0); + luaL_checktype(L, index, LUA_TTABLE); + lua_getfield(L, index, "a"); + if(lua_isnumber(L, -1)) + color.setAlpha(lua_tonumber(L, -1)); + lua_pop(L, 1); + lua_getfield(L, index, "r"); + color.setRed(lua_tonumber(L, -1)); + lua_pop(L, 1); + lua_getfield(L, index, "g"); + color.setGreen(lua_tonumber(L, -1)); + lua_pop(L, 1); + lua_getfield(L, index, "b"); + color.setBlue(lua_tonumber(L, -1)); + lua_pop(L, 1); + return color; +} + +aabb3f read_aabb3f(lua_State *L, int index, f32 scale) +{ + aabb3f box; + if(lua_istable(L, index)){ + lua_rawgeti(L, index, 1); + box.MinEdge.X = lua_tonumber(L, -1) * scale; + lua_pop(L, 1); + lua_rawgeti(L, index, 2); + box.MinEdge.Y = lua_tonumber(L, -1) * scale; + lua_pop(L, 1); + lua_rawgeti(L, index, 3); + box.MinEdge.Z = lua_tonumber(L, -1) * scale; + lua_pop(L, 1); + lua_rawgeti(L, index, 4); + box.MaxEdge.X = lua_tonumber(L, -1) * scale; + lua_pop(L, 1); + lua_rawgeti(L, index, 5); + box.MaxEdge.Y = lua_tonumber(L, -1) * scale; + lua_pop(L, 1); + lua_rawgeti(L, index, 6); + box.MaxEdge.Z = lua_tonumber(L, -1) * scale; + lua_pop(L, 1); + } + return box; +} + +std::vector read_aabb3f_vector(lua_State *L, int index, f32 scale) +{ + std::vector boxes; + if(lua_istable(L, index)){ + int n = lua_objlen(L, index); + // Check if it's a single box or a list of boxes + bool possibly_single_box = (n == 6); + for(int i = 1; i <= n && possibly_single_box; i++){ + lua_rawgeti(L, index, i); + if(!lua_isnumber(L, -1)) + possibly_single_box = false; + lua_pop(L, 1); + } + if(possibly_single_box){ + // Read a single box + boxes.push_back(read_aabb3f(L, index, scale)); + } else { + // Read a list of boxes + for(int i = 1; i <= n; i++){ + lua_rawgeti(L, index, i); + boxes.push_back(read_aabb3f(L, -1, scale)); + lua_pop(L, 1); + } + } + } + return boxes; +} + +/* + Table field getters +*/ + +bool getstringfield(lua_State *L, int table, + const char *fieldname, std::string &result) +{ + lua_getfield(L, table, fieldname); + bool got = false; + if(lua_isstring(L, -1)){ + size_t len = 0; + const char *ptr = lua_tolstring(L, -1, &len); + result.assign(ptr, len); + got = true; + } + lua_pop(L, 1); + return got; +} + +bool getintfield(lua_State *L, int table, + const char *fieldname, int &result) +{ + lua_getfield(L, table, fieldname); + bool got = false; + if(lua_isnumber(L, -1)){ + result = lua_tonumber(L, -1); + got = true; + } + lua_pop(L, 1); + return got; +} + +bool getfloatfield(lua_State *L, int table, + const char *fieldname, float &result) +{ + lua_getfield(L, table, fieldname); + bool got = false; + if(lua_isnumber(L, -1)){ + result = lua_tonumber(L, -1); + got = true; + } + lua_pop(L, 1); + return got; +} + +bool getboolfield(lua_State *L, int table, + const char *fieldname, bool &result) +{ + lua_getfield(L, table, fieldname); + bool got = false; + if(lua_isboolean(L, -1)){ + result = lua_toboolean(L, -1); + got = true; + } + lua_pop(L, 1); + return got; +} + +std::string checkstringfield(lua_State *L, int table, + const char *fieldname) +{ + lua_getfield(L, table, fieldname); + std::string s = luaL_checkstring(L, -1); + lua_pop(L, 1); + return s; +} + +std::string getstringfield_default(lua_State *L, int table, + const char *fieldname, const std::string &default_) +{ + std::string result = default_; + getstringfield(L, table, fieldname, result); + return result; +} + +int getintfield_default(lua_State *L, int table, + const char *fieldname, int default_) +{ + int result = default_; + getintfield(L, table, fieldname, result); + return result; +} + +float getfloatfield_default(lua_State *L, int table, + const char *fieldname, float default_) +{ + float result = default_; + getfloatfield(L, table, fieldname, result); + return result; +} + +bool getboolfield_default(lua_State *L, int table, + const char *fieldname, bool default_) +{ + bool result = default_; + getboolfield(L, table, fieldname, result); + return result; +} + +void setintfield(lua_State *L, int table, + const char *fieldname, int value) +{ + lua_pushinteger(L, value); + if(table < 0) + table -= 1; + lua_setfield(L, table, fieldname); +} + +void setfloatfield(lua_State *L, int table, + const char *fieldname, float value) +{ + lua_pushnumber(L, value); + if(table < 0) + table -= 1; + lua_setfield(L, table, fieldname); +} + +void setboolfield(lua_State *L, int table, + const char *fieldname, bool value) +{ + lua_pushboolean(L, value); + if(table < 0) + table -= 1; + lua_setfield(L, table, fieldname); +} + + diff --git a/src/script/common/c_converter.h b/src/script/common/c_converter.h new file mode 100644 index 000000000..ab0083124 --- /dev/null +++ b/src/script/common/c_converter.h @@ -0,0 +1,96 @@ +/* +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 script/modapi file!!!!!!!! */ +/******************************************************************************/ +/******************************************************************************/ +#ifndef C_CONVERTER_H_ +#define C_CONVERTER_H_ + +#include +#include + +#include "irrlichttypes_bloated.h" +#include "common/c_types.h" + +extern "C" { +#include +} + +std::string getstringfield_default (lua_State *L, int table, + const char *fieldname, const std::string &default_); +bool getboolfield_default(lua_State *L, int table, + const char *fieldname, bool default_); +float getfloatfield_default(lua_State *L, int table, + const char *fieldname, float default_); +int getintfield_default (lua_State *L, int table, + const char *fieldname, int default_); + +bool getstringfield(lua_State *L, int table, + const char *fieldname, std::string &result); +bool getintfield(lua_State *L, int table, + const char *fieldname, int &result); +void read_groups (lua_State *L, int index, + std::map &result); +bool getboolfield(lua_State *L, int table, + const char *fieldname, bool &result); +bool getfloatfield(lua_State *L, int table, + const char *fieldname, float &result); + +std::string checkstringfield(lua_State *L, int table, + const char *fieldname); + +void setintfield(lua_State *L, int table, + const char *fieldname, int value); +void setfloatfield(lua_State *L, int table, + const char *fieldname, float value); +void setboolfield(lua_State *L, int table, + const char *fieldname, bool value); + + +v3f checkFloatPos (lua_State *L, int index); +v3f check_v3f (lua_State *L, int index); +v3s16 check_v3s16 (lua_State *L, int index); + +v3f read_v3f (lua_State *L, int index); +v2f read_v2f (lua_State *L, int index); +v2s16 read_v2s16 (lua_State *L, int index); +video::SColor readARGB8 (lua_State *L, int index); +aabb3f read_aabb3f (lua_State *L, int index, f32 scale); +v3s16 read_v3s16 (lua_State *L, int index); +std::vector + read_aabb3f_vector (lua_State *L, int index, f32 scale); + +void push_v3s16 (lua_State *L, v3s16 p); +void pushFloatPos (lua_State *L, v3f p); +void push_v3f (lua_State *L, v3f p); +void push_v2f (lua_State *L, v2f p); + + + +void warn_if_field_exists (lua_State *L, + int table, + const char *fieldname, + const std::string &message); + +#endif /* C_CONVERTER_H_ */ diff --git a/src/script/common/c_internal.cpp b/src/script/common/c_internal.cpp new file mode 100644 index 000000000..42e9fb3e1 --- /dev/null +++ b/src/script/common/c_internal.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 "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; +} + +std::string script_get_backtrace(lua_State *L) +{ + std::string s; + lua_getfield(L, LUA_GLOBALSINDEX, "debug"); + if(lua_istable(L, -1)){ + lua_getfield(L, -1, "traceback"); + if(lua_isfunction(L, -1)){ + lua_call(L, 0, 1); + if(lua_isstring(L, -1)){ + s += lua_tostring(L, -1); + } + lua_pop(L, 1); + } + else{ + lua_pop(L, 1); + } + } + lua_pop(L, 1); + return s; +} + +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: "< + +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 C_INTERNAL_H_ +#define C_INTERNAL_H_ + +class Server; +class ScriptApi; +#include + +#include "lua_api/l_base.h" + +extern "C" { +#include "lua.h" +} + +#define luamethod(class, name) {#name, class::l_##name} +#define STACK_TO_SERVER(L) get_scriptapi(L)->getServer() +#define API_FCT(name) registerFunction(L,#name,l_##name,top) + +#define REGISTER_LUA_REF(cln) \ +class ModApi_##cln : public ModApiBase { \ + public: \ + ModApi_##cln() : ModApiBase() {}; \ + bool Initialize(lua_State* L, int top) { \ + cln::Register(L); \ + return true; \ + }; \ +}; \ +ModApi_##cln macro_generated_prototype__##cln; + + +ScriptApi* get_scriptapi (lua_State *L); +std::string script_get_backtrace (lua_State *L); +void script_error (lua_State *L, const char *fmt, ...); + +#endif /* C_INTERNAL_H_ */ diff --git a/src/script/common/c_types.cpp b/src/script/common/c_types.cpp new file mode 100644 index 000000000..ac724c42c --- /dev/null +++ b/src/script/common/c_types.cpp @@ -0,0 +1,40 @@ +/* +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 + +#include "common/c_types.h" +#include "common/c_internal.h" +#include "itemdef.h" + +LuaError::LuaError(lua_State *L, const std::string &s) +{ + m_s = "LuaError: "; + m_s += s + "\n"; + m_s += script_get_backtrace(L); +} + +struct EnumString es_ItemType[] = + { + {ITEM_NONE, "none"}, + {ITEM_NODE, "node"}, + {ITEM_CRAFT, "craft"}, + {ITEM_TOOL, "tool"}, + {0, NULL}, + }; diff --git a/src/script/common/c_types.h b/src/script/common/c_types.h new file mode 100644 index 000000000..7df869432 --- /dev/null +++ b/src/script/common/c_types.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 C_TYPES_H_ +#define C_TYPES_H_ + +extern "C" { +#include "lua.h" +} + +#include + +struct EnumString +{ + int num; + const char *str; +}; + +class StackUnroller +{ +private: + lua_State *m_lua; + int m_original_top; +public: + StackUnroller(lua_State *L): + m_lua(L), + m_original_top(-1) + { + m_original_top = lua_gettop(m_lua); // store stack height + } + ~StackUnroller() + { + lua_settop(m_lua, m_original_top); // restore stack height + } +}; + +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: + LuaError(lua_State *L, const std::string &s); + + virtual ~LuaError() throw() + {} + virtual const char * what() const throw() + { + return m_s.c_str(); + } + std::string m_s; +}; + + +extern EnumString es_ItemType[]; + +#endif /* C_TYPES_H_ */ diff --git a/src/script/cpp_api/CMakeLists.txt b/src/script/cpp_api/CMakeLists.txt new file mode 100644 index 000000000..6f5b51a49 --- /dev/null +++ b/src/script/cpp_api/CMakeLists.txt @@ -0,0 +1,11 @@ +set(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 + ${CMAKE_CURRENT_SOURCE_DIR}/s_inventory.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/s_item.cpp + ${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 + PARENT_SCOPE) diff --git a/src/script/cpp_api/s_base.cpp b/src/script/cpp_api/s_base.cpp new file mode 100644 index 000000000..e2e586357 --- /dev/null +++ b/src/script/cpp_api/s_base.cpp @@ -0,0 +1,264 @@ +/* +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 +#include + +extern "C" { +#include "lua.h" +#include "lauxlib.h" +} + +#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) +{ + +} + + +void ScriptApiBase::realityCheck() +{ + int top = lua_gettop(m_luastack); + if(top >= 30){ + dstream<<"Stack is over 30:"<= 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)) + scriptError("error: %s", lua_tostring(L, -1)); + + // Move return value to designated space in stack + // Or pop it + if(first_loop){ + // Result of first callback is always moved + lua_replace(L, rv); + first_loop = false; + } else { + // Otherwise, what happens depends on the mode + if(mode == RUN_CALLBACKS_MODE_FIRST) + lua_pop(L, 1); + else if(mode == RUN_CALLBACKS_MODE_LAST) + lua_replace(L, rv); + else if(mode == RUN_CALLBACKS_MODE_AND || + mode == RUN_CALLBACKS_MODE_AND_SC){ + if((bool)lua_toboolean(L, rv) == true && + (bool)lua_toboolean(L, -1) == false) + lua_replace(L, rv); + else + lua_pop(L, 1); + } + else if(mode == RUN_CALLBACKS_MODE_OR || + mode == RUN_CALLBACKS_MODE_OR_SC){ + if((bool)lua_toboolean(L, rv) == false && + (bool)lua_toboolean(L, -1) == true) + lua_replace(L, rv); + else + lua_pop(L, 1); + } + else + assert(0); + } + + // 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); + } + } +} + +void ScriptApiBase::addObjectReference(ServerActiveObject *cobj) +{ + SCRIPTAPI_PRECHECKHEADER + //infostream<<"scriptapi_add_object_reference: id="<getId()<getId()); // Push id + lua_pushvalue(L, object); // Copy object to top of stack + lua_settable(L, objectstable); +} + +void ScriptApiBase::removeObjectReference(ServerActiveObject *cobj) +{ + SCRIPTAPI_PRECHECKHEADER + //infostream<<"scriptapi_rm_object_reference: id="<getId()<getId()); // Push id + lua_gettable(L, objectstable); + // Set object reference to NULL + ObjectRef::set_null(L); + lua_pop(L, 1); // pop object + + // Set object_refs[id] = nil + lua_pushnumber(L, cobj->getId()); // Push id + lua_pushnil(L); + lua_settable(L, objectstable); +} + +// Creates a new anonymous reference if cobj=NULL or id=0 +void ScriptApiBase::objectrefGetOrCreate( + ServerActiveObject *cobj) +{ + lua_State *L = getStack(); + + if(cobj == NULL || cobj->getId() == 0){ + ObjectRef::create(L, cobj); + } else { + objectrefGet(cobj->getId()); + } +} + +void ScriptApiBase::objectrefGet(u16 id) +{ + lua_State *L = getStack(); + + // Get minetest.object_refs[i] + lua_getglobal(L, "minetest"); + lua_getfield(L, -1, "object_refs"); + luaL_checktype(L, -1, LUA_TTABLE); + lua_pushnumber(L, id); + lua_gettable(L, -2); + lua_remove(L, -2); // object_refs + lua_remove(L, -2); // minetest +} diff --git a/src/script/cpp_api/s_base.h b/src/script/cpp_api/s_base.h new file mode 100644 index 000000000..da4e17d89 --- /dev/null +++ b/src/script/cpp_api/s_base.h @@ -0,0 +1,167 @@ +/* +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_BASE_H_ +#define S_BASE_H_ + +#include + +#include "irrlichttypes.h" +#include "jmutex.h" +#include "jmutexautolock.h" +#include "common/c_types.h" +#include "debug.h" + +#define LOCK_DEBUG + +class Server; +class Environment; +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: + + /* object */ + void addObjectReference(ServerActiveObject *cobj); + void removeObjectReference(ServerActiveObject *cobj); + + ScriptApiBase(); + +protected: + friend class LuaABM; + friend class InvRef; + friend class ObjectRef; + friend class NodeMetaRef; + friend class ModApiBase; + friend class ModApiEnvMod; + + + inline 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; } + void setServer(Server* server) { m_server = server; } + + Environment* getEnv() { return m_environment; } + void setEnv(Environment* env) { m_environment = env; } + + void objectrefGetOrCreate(ServerActiveObject *cobj); + void objectrefGet(u16 id); + + JMutex m_luastackmutex; +#ifdef 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; +}; + +#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 new file mode 100644 index 000000000..2a5a6066d --- /dev/null +++ b/src/script/cpp_api/s_entity.cpp @@ -0,0 +1,267 @@ +/* +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_entity.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 + + verbosestream<<"scriptapi_luaentity_add: id="<physical); + + getfloatfield(L, -1, "weight", prop->weight); + + lua_getfield(L, -1, "collisionbox"); + if(lua_istable(L, -1)) + prop->collisionbox = read_aabb3f(L, -1, 1.0); + lua_pop(L, 1); + + getstringfield(L, -1, "visual", prop->visual); + + getstringfield(L, -1, "mesh", prop->mesh); + + // Deprecated: read object properties directly + read_object_properties(L, -1, prop); + + // Read initial_properties + lua_getfield(L, -1, "initial_properties"); + read_object_properties(L, -1, prop); + lua_pop(L, 1); +} + +void ScriptApiEntity::luaentity_Step(u16 id, float dtime) +{ + SCRIPTAPI_PRECHECKHEADER + + //infostream<<"scriptapi_luaentity_step: id="< + +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_ENTITY_H_ +#define S_ENTITY_H_ + +#include "cpp_api/s_base.h" +#include "irr_v3d.h" + +class ObjectProperties; +class ToolCapabilities; + +class ScriptApiEntity + : virtual public ScriptApiBase +{ +public: + bool luaentity_Add(u16 id, const char *name); + void luaentity_Activate(u16 id, + const std::string &staticdata, u32 dtime_s); + void luaentity_Remove(u16 id); + std::string luaentity_GetStaticdata(u16 id); + void luaentity_GetProperties(u16 id, + ObjectProperties *prop); + void luaentity_Step(u16 id, float dtime); + void luaentity_Punch(u16 id, + ServerActiveObject *puncher, float time_from_last_punch, + const ToolCapabilities *toolcap, v3f dir); + void luaentity_Rightclick(u16 id, + ServerActiveObject *clicker); +}; + + + +#endif /* S_ENTITY_H_ */ diff --git a/src/script/cpp_api/s_env.cpp b/src/script/cpp_api/s_env.cpp new file mode 100644 index 000000000..334d196bc --- /dev/null +++ b/src/script/cpp_api/s_env.cpp @@ -0,0 +1,132 @@ +/* +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_env.h" +#include "common/c_converter.h" +#include "log.h" +#include "environment.h" +#include "lua_api/l_env.h" + +extern "C" { +#include "lauxlib.h" +} + +void ScriptApiEnv::environment_OnGenerated(v3s16 minp, v3s16 maxp, + u32 blockseed) +{ + SCRIPTAPI_PRECHECKHEADER + + // Get minetest.registered_on_generateds + lua_getglobal(L, "minetest"); + lua_getfield(L, -1, "registered_on_generateds"); + // Call callbacks + push_v3s16(L, minp); + push_v3s16(L, maxp); + lua_pushnumber(L, blockseed); + runCallbacks(3, RUN_CALLBACKS_MODE_FIRST); +} + +void ScriptApiEnv::environment_Step(float dtime) +{ + SCRIPTAPI_PRECHECKHEADER + //infostream<<"scriptapi_environment_step"< trigger_contents; + lua_getfield(L, current_abm, "nodenames"); + if(lua_istable(L, -1)){ + int table = lua_gettop(L); + lua_pushnil(L); + while(lua_next(L, table) != 0){ + // key at index -2 and value at index -1 + luaL_checktype(L, -1, LUA_TSTRING); + trigger_contents.insert(lua_tostring(L, -1)); + // removes value, keeps key for next iteration + lua_pop(L, 1); + } + } else if(lua_isstring(L, -1)){ + trigger_contents.insert(lua_tostring(L, -1)); + } + lua_pop(L, 1); + + std::set required_neighbors; + lua_getfield(L, current_abm, "neighbors"); + if(lua_istable(L, -1)){ + int table = lua_gettop(L); + lua_pushnil(L); + while(lua_next(L, table) != 0){ + // key at index -2 and value at index -1 + luaL_checktype(L, -1, LUA_TSTRING); + required_neighbors.insert(lua_tostring(L, -1)); + // removes value, keeps key for next iteration + lua_pop(L, 1); + } + } else if(lua_isstring(L, -1)){ + required_neighbors.insert(lua_tostring(L, -1)); + } + lua_pop(L, 1); + + float trigger_interval = 10.0; + getfloatfield(L, current_abm, "interval", trigger_interval); + + int trigger_chance = 50; + getintfield(L, current_abm, "chance", trigger_chance); + + LuaABM *abm = new LuaABM(L, id, trigger_contents, + required_neighbors, trigger_interval, trigger_chance); + + env->addActiveBlockModifier(abm); + + // removes value, keeps key for next iteration + lua_pop(L, 1); + } + } + lua_pop(L, 1); +} diff --git a/src/script/cpp_api/s_env.h b/src/script/cpp_api/s_env.h new file mode 100644 index 000000000..c5b739eb4 --- /dev/null +++ b/src/script/cpp_api/s_env.h @@ -0,0 +1,40 @@ +/* +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_ENV_H_ +#define S_ENV_H_ + +#include "cpp_api/s_base.h" +#include "irr_v3d.h" + +class ServerEnvironment; + +class ScriptApiEnv + : virtual public ScriptApiBase +{ +public: + // On environment step + void environment_Step(float dtime); + // After generating a piece of map + void environment_OnGenerated(v3s16 minp, v3s16 maxp,u32 blockseed); + + void initializeEnvironment(ServerEnvironment *env); +}; + +#endif /* S_ENV_H_ */ diff --git a/src/script/cpp_api/s_inventory.cpp b/src/script/cpp_api/s_inventory.cpp new file mode 100644 index 000000000..2402d198c --- /dev/null +++ b/src/script/cpp_api/s_inventory.cpp @@ -0,0 +1,260 @@ +/* +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_inventory.h" +#include "inventorymanager.h" +#include "lua_api/l_inventory.h" +#include "lua_api/l_item.h" +#include "log.h" + +// Return number of accepted items to be moved +int ScriptApiDetached::detached_inventory_AllowMove( + const std::string &name, + const std::string &from_list, int from_index, + const std::string &to_list, int to_index, + int count, ServerActiveObject *player) +{ + SCRIPTAPI_PRECHECKHEADER + + // Push callback function on stack + if(!getDetachedInventoryCallback(name, "allow_move")) + return count; + + // function(inv, from_list, from_index, to_list, to_index, count, player) + // inv + InventoryLocation loc; + loc.setDetached(name); + InvRef::create(L, loc); + // from_list + lua_pushstring(L, from_list.c_str()); + // from_index + lua_pushinteger(L, from_index + 1); + // to_list + lua_pushstring(L, to_list.c_str()); + // to_index + lua_pushinteger(L, to_index + 1); + // count + lua_pushinteger(L, count); + // player + objectrefGetOrCreate(player); + if(lua_pcall(L, 7, 1, 0)) + scriptError("error: %s", lua_tostring(L, -1)); + if(!lua_isnumber(L, -1)) + throw LuaError(L, "allow_move should return a number"); + return luaL_checkinteger(L, -1); +} + +// Return number of accepted items to be put +int ScriptApiDetached::detached_inventory_AllowPut( + const std::string &name, + const std::string &listname, int index, ItemStack &stack, + ServerActiveObject *player) +{ + SCRIPTAPI_PRECHECKHEADER + + // Push callback function on stack + if(!getDetachedInventoryCallback(name, "allow_put")) + return stack.count; // All will be accepted + + // Call function(inv, listname, index, stack, player) + // inv + InventoryLocation loc; + loc.setDetached(name); + InvRef::create(L, loc); + // listname + lua_pushstring(L, listname.c_str()); + // index + lua_pushinteger(L, index + 1); + // stack + LuaItemStack::create(L, stack); + // player + objectrefGetOrCreate(player); + if(lua_pcall(L, 5, 1, 0)) + scriptError("error: %s", lua_tostring(L, -1)); + if(!lua_isnumber(L, -1)) + throw LuaError(L, "allow_put should return a number"); + return luaL_checkinteger(L, -1); +} + +// Return number of accepted items to be taken +int ScriptApiDetached::detached_inventory_AllowTake( + const std::string &name, + const std::string &listname, int index, ItemStack &stack, + ServerActiveObject *player) +{ + SCRIPTAPI_PRECHECKHEADER + + // Push callback function on stack + if(!getDetachedInventoryCallback(name, "allow_take")) + return stack.count; // All will be accepted + + // Call function(inv, listname, index, stack, player) + // inv + InventoryLocation loc; + loc.setDetached(name); + InvRef::create(L, loc); + // listname + lua_pushstring(L, listname.c_str()); + // index + lua_pushinteger(L, index + 1); + // stack + LuaItemStack::create(L, stack); + // player + objectrefGetOrCreate(player); + if(lua_pcall(L, 5, 1, 0)) + scriptError("error: %s", lua_tostring(L, -1)); + if(!lua_isnumber(L, -1)) + throw LuaError(L, "allow_take should return a number"); + return luaL_checkinteger(L, -1); +} + +// Report moved items +void ScriptApiDetached::detached_inventory_OnMove( + const std::string &name, + const std::string &from_list, int from_index, + const std::string &to_list, int to_index, + int count, ServerActiveObject *player) +{ + SCRIPTAPI_PRECHECKHEADER + + // Push callback function on stack + if(!getDetachedInventoryCallback(name, "on_move")) + return; + + // function(inv, from_list, from_index, to_list, to_index, count, player) + // inv + InventoryLocation loc; + loc.setDetached(name); + InvRef::create(L, loc); + // from_list + lua_pushstring(L, from_list.c_str()); + // from_index + lua_pushinteger(L, from_index + 1); + // to_list + lua_pushstring(L, to_list.c_str()); + // to_index + lua_pushinteger(L, to_index + 1); + // count + lua_pushinteger(L, count); + // player + objectrefGetOrCreate(player); + if(lua_pcall(L, 7, 0, 0)) + scriptError("error: %s", lua_tostring(L, -1)); +} + +// Report put items +void ScriptApiDetached::detached_inventory_OnPut( + const std::string &name, + const std::string &listname, int index, ItemStack &stack, + ServerActiveObject *player) +{ + SCRIPTAPI_PRECHECKHEADER + + // Push callback function on stack + if(!getDetachedInventoryCallback(name, "on_put")) + return; + + // Call function(inv, listname, index, stack, player) + // inv + InventoryLocation loc; + loc.setDetached(name); + InvRef::create(L, loc); + // listname + lua_pushstring(L, listname.c_str()); + // index + lua_pushinteger(L, index + 1); + // stack + LuaItemStack::create(L, stack); + // player + objectrefGetOrCreate(player); + if(lua_pcall(L, 5, 0, 0)) + scriptError("error: %s", lua_tostring(L, -1)); +} + +// Report taken items +void ScriptApiDetached::detached_inventory_OnTake( + const std::string &name, + const std::string &listname, int index, ItemStack &stack, + ServerActiveObject *player) +{ + SCRIPTAPI_PRECHECKHEADER + + // Push callback function on stack + if(!getDetachedInventoryCallback(name, "on_take")) + return; + + // Call function(inv, listname, index, stack, player) + // inv + InventoryLocation loc; + loc.setDetached(name); + InvRef::create(L, loc); + // listname + lua_pushstring(L, listname.c_str()); + // index + lua_pushinteger(L, index + 1); + // stack + LuaItemStack::create(L, stack); + // player + objectrefGetOrCreate(player); + if(lua_pcall(L, 5, 0, 0)) + scriptError("error: %s", lua_tostring(L, -1)); +} + +// Retrieves minetest.detached_inventories[name][callbackname] +// If that is nil or on error, return false and stack is unchanged +// If that is a function, returns true and pushes the +// function onto the stack +bool ScriptApiDetached::getDetachedInventoryCallback( + const std::string &name, const char *callbackname) +{ + lua_State *L = getStack(); + + lua_getglobal(L, "minetest"); + lua_getfield(L, -1, "detached_inventories"); + lua_remove(L, -2); + luaL_checktype(L, -1, LUA_TTABLE); + lua_getfield(L, -1, name.c_str()); + lua_remove(L, -2); + // Should be a table + if(lua_type(L, -1) != LUA_TTABLE) + { + errorstream<<"Item \""< + +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_INVENTORY_H_ +#define S_INVENTORY_H_ + +#include "cpp_api/s_base.h" + +class ItemStack; + +class ScriptApiDetached + : virtual public ScriptApiBase +{ +public: + /* Detached inventory callbacks */ + // Return number of accepted items to be moved + int detached_inventory_AllowMove( + const std::string &name, + const std::string &from_list, int from_index, + const std::string &to_list, int to_index, + int count, ServerActiveObject *player); + // Return number of accepted items to be put + int detached_inventory_AllowPut( + const std::string &name, + const std::string &listname, int index, ItemStack &stack, + ServerActiveObject *player); + // Return number of accepted items to be taken + int detached_inventory_AllowTake( + const std::string &name, + const std::string &listname, int index, ItemStack &stack, + ServerActiveObject *player); + // Report moved items + void detached_inventory_OnMove( + const std::string &name, + const std::string &from_list, int from_index, + const std::string &to_list, int to_index, + int count, ServerActiveObject *player); + // Report put items + void detached_inventory_OnPut( + const std::string &name, + const std::string &listname, int index, ItemStack &stack, + ServerActiveObject *player); + // Report taken items + void detached_inventory_OnTake( + const std::string &name, + const std::string &listname, int index, ItemStack &stack, + ServerActiveObject *player); +private: + bool getDetachedInventoryCallback( + const std::string &name, const char *callbackname); +}; + + + +#endif /* S_INVENTORY_H_ */ diff --git a/src/script/cpp_api/s_item.cpp b/src/script/cpp_api/s_item.cpp new file mode 100644 index 000000000..6937ebbeb --- /dev/null +++ b/src/script/cpp_api/s_item.cpp @@ -0,0 +1,164 @@ +/* +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_item.h" +#include "common/c_converter.h" +#include "common/c_content.h" +#include "lua_api/l_item.h" +#include "server.h" + +bool ScriptApiItem::item_OnDrop(ItemStack &item, + ServerActiveObject *dropper, v3f pos) +{ + SCRIPTAPI_PRECHECKHEADER + + // Push callback function on stack + if(!getItemCallback(item.name.c_str(), "on_drop")) + return false; + + // Call function + LuaItemStack::create(L, item); + objectrefGetOrCreate(dropper); + pushFloatPos(L, pos); + if(lua_pcall(L, 3, 1, 0)) + scriptError("error: %s", lua_tostring(L, -1)); + if(!lua_isnil(L, -1)) + item = read_item(L,-1, getServer()); + return true; +} + +bool ScriptApiItem::item_OnPlace(ItemStack &item, + ServerActiveObject *placer, const PointedThing &pointed) +{ + SCRIPTAPI_PRECHECKHEADER + + // Push callback function on stack + if(!getItemCallback(item.name.c_str(), "on_place")) + return false; + + // Call function + LuaItemStack::create(L, item); + objectrefGetOrCreate(placer); + pushPointedThing(pointed); + if(lua_pcall(L, 3, 1, 0)) + scriptError("error: %s", lua_tostring(L, -1)); + if(!lua_isnil(L, -1)) + item = read_item(L,-1, getServer()); + return true; +} + +bool ScriptApiItem::item_OnUse(ItemStack &item, + ServerActiveObject *user, const PointedThing &pointed) +{ + SCRIPTAPI_PRECHECKHEADER + + // Push callback function on stack + if(!getItemCallback(item.name.c_str(), "on_use")) + return false; + + // Call function + LuaItemStack::create(L, item); + objectrefGetOrCreate(user); + pushPointedThing(pointed); + if(lua_pcall(L, 3, 1, 0)) + scriptError("error: %s", lua_tostring(L, -1)); + if(!lua_isnil(L, -1)) + item = read_item(L,-1, getServer()); + return true; +} + +// Retrieves minetest.registered_items[name][callbackname] +// If that is nil or on error, return false and stack is unchanged +// If that is a function, returns true and pushes the +// function onto the stack +// If minetest.registered_items[name] doesn't exist, minetest.nodedef_default +// is tried instead so unknown items can still be manipulated to some degree +bool ScriptApiItem::getItemCallback(const char *name, const char *callbackname) +{ + lua_State* L = getStack(); + + lua_getglobal(L, "minetest"); + lua_getfield(L, -1, "registered_items"); + lua_remove(L, -2); + luaL_checktype(L, -1, LUA_TTABLE); + lua_getfield(L, -1, name); + lua_remove(L, -2); + // Should be a table + if(lua_type(L, -1) != LUA_TTABLE) + { + // Report error and clean up + errorstream<<"Item \""< + +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_ITEM_H_ +#define S_ITEM_H_ + +#include "cpp_api/s_base.h" +#include "irr_v3d.h" + +class PointedThing; +class ItemStack; +class ServerActiveObject; +class ItemDefinition; +class LuaItemStack; +class ModApiItemMod; + +class ScriptApiItem +: virtual public ScriptApiBase +{ +public: + bool item_OnDrop(ItemStack &item, + ServerActiveObject *dropper, v3f pos); + bool item_OnPlace(ItemStack &item, + ServerActiveObject *placer, const PointedThing &pointed); + bool item_OnUse(ItemStack &item, + ServerActiveObject *user, const PointedThing &pointed); + +protected: + friend class LuaItemStack; + friend class ModApiItemMod; + + bool getItemCallback(const char *name, const char *callbackname); +private: + void pushPointedThing(const PointedThing& pointed); + +}; + + +#endif /* S_ITEM_H_ */ diff --git a/src/script/cpp_api/s_node.cpp b/src/script/cpp_api/s_node.cpp new file mode 100644 index 000000000..969e2f4d9 --- /dev/null +++ b/src/script/cpp_api/s_node.cpp @@ -0,0 +1,233 @@ +/* +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_node.h" +#include "common/c_converter.h" +#include "common/c_content.h" +#include "nodedef.h" +#include "server.h" + + +struct EnumString ScriptApiNode::es_DrawType[] = + { + {NDT_NORMAL, "normal"}, + {NDT_AIRLIKE, "airlike"}, + {NDT_LIQUID, "liquid"}, + {NDT_FLOWINGLIQUID, "flowingliquid"}, + {NDT_GLASSLIKE, "glasslike"}, + {NDT_GLASSLIKE_FRAMED, "glasslike_framed"}, + {NDT_ALLFACES, "allfaces"}, + {NDT_ALLFACES_OPTIONAL, "allfaces_optional"}, + {NDT_TORCHLIKE, "torchlike"}, + {NDT_SIGNLIKE, "signlike"}, + {NDT_PLANTLIKE, "plantlike"}, + {NDT_FENCELIKE, "fencelike"}, + {NDT_RAILLIKE, "raillike"}, + {NDT_NODEBOX, "nodebox"}, + {0, NULL}, + }; + +struct EnumString ScriptApiNode::es_ContentParamType2[] = + { + {CPT2_NONE, "none"}, + {CPT2_FULL, "full"}, + {CPT2_FLOWINGLIQUID, "flowingliquid"}, + {CPT2_FACEDIR, "facedir"}, + {CPT2_WALLMOUNTED, "wallmounted"}, + {0, NULL}, + }; + +struct EnumString ScriptApiNode::es_LiquidType[] = + { + {LIQUID_NONE, "none"}, + {LIQUID_FLOWING, "flowing"}, + {LIQUID_SOURCE, "source"}, + {0, NULL}, + }; + +struct EnumString ScriptApiNode::es_ContentParamType[] = + { + {CPT_NONE, "none"}, + {CPT_LIGHT, "light"}, + {0, NULL}, + }; + +struct EnumString ScriptApiNode::es_NodeBoxType[] = + { + {NODEBOX_REGULAR, "regular"}, + {NODEBOX_FIXED, "fixed"}, + {NODEBOX_WALLMOUNTED, "wallmounted"}, + {0, NULL}, + }; + +ScriptApiNode::ScriptApiNode() { +} + +ScriptApiNode::~ScriptApiNode() { +} + +bool ScriptApiNode::node_on_punch(v3s16 p, MapNode node, + ServerActiveObject *puncher) +{ + SCRIPTAPI_PRECHECKHEADER + + INodeDefManager *ndef = getServer()->ndef(); + + // Push callback function on stack + if(!getItemCallback(ndef->get(node).name.c_str(), "on_punch")) + return false; + + // Call function + push_v3s16(L, p); + pushnode(L, node, ndef); + objectrefGetOrCreate(puncher); + if(lua_pcall(L, 3, 0, 0)) + scriptError("error: %s", lua_tostring(L, -1)); + return true; +} + +bool ScriptApiNode::node_on_dig(v3s16 p, MapNode node, + ServerActiveObject *digger) +{ + SCRIPTAPI_PRECHECKHEADER + + INodeDefManager *ndef = getServer()->ndef(); + + // Push callback function on stack + if(!getItemCallback(ndef->get(node).name.c_str(), "on_dig")) + return false; + + // Call function + push_v3s16(L, p); + pushnode(L, node, ndef); + objectrefGetOrCreate(digger); + if(lua_pcall(L, 3, 0, 0)) + scriptError("error: %s", lua_tostring(L, -1)); + return true; +} + +void ScriptApiNode::node_on_construct(v3s16 p, MapNode node) +{ + SCRIPTAPI_PRECHECKHEADER + + INodeDefManager *ndef = getServer()->ndef(); + + // Push callback function on stack + if(!getItemCallback(ndef->get(node).name.c_str(), "on_construct")) + return; + + // Call function + push_v3s16(L, p); + if(lua_pcall(L, 1, 0, 0)) + scriptError("error: %s", lua_tostring(L, -1)); +} + +void ScriptApiNode::node_on_destruct(v3s16 p, MapNode node) +{ + SCRIPTAPI_PRECHECKHEADER + + INodeDefManager *ndef = getServer()->ndef(); + + // Push callback function on stack + if(!getItemCallback(ndef->get(node).name.c_str(), "on_destruct")) + return; + + // Call function + push_v3s16(L, p); + if(lua_pcall(L, 1, 0, 0)) + scriptError("error: %s", lua_tostring(L, -1)); +} + +void ScriptApiNode::node_after_destruct(v3s16 p, MapNode node) +{ + SCRIPTAPI_PRECHECKHEADER + + INodeDefManager *ndef = getServer()->ndef(); + + // Push callback function on stack + if(!getItemCallback(ndef->get(node).name.c_str(), "after_destruct")) + return; + + // Call function + push_v3s16(L, p); + pushnode(L, node, ndef); + if(lua_pcall(L, 2, 0, 0)) + scriptError("error: %s", lua_tostring(L, -1)); +} + +bool ScriptApiNode::node_on_timer(v3s16 p, MapNode node, f32 dtime) +{ + SCRIPTAPI_PRECHECKHEADER + + INodeDefManager *ndef = getServer()->ndef(); + + // Push callback function on stack + if(!getItemCallback(ndef->get(node).name.c_str(), "on_timer")) + return false; + + // Call function + push_v3s16(L, p); + lua_pushnumber(L,dtime); + if(lua_pcall(L, 2, 1, 0)) + scriptError("error: %s", lua_tostring(L, -1)); + if((bool)lua_isboolean(L,-1) && (bool)lua_toboolean(L,-1) == true) + return true; + + return false; +} + +void ScriptApiNode::node_on_receive_fields(v3s16 p, + const std::string &formname, + const std::map &fields, + ServerActiveObject *sender) +{ + SCRIPTAPI_PRECHECKHEADER + + INodeDefManager *ndef = getServer()->ndef(); + + // If node doesn't exist, we don't know what callback to call + MapNode node = getEnv()->getMap().getNodeNoEx(p); + if(node.getContent() == CONTENT_IGNORE) + return; + + // Push callback function on stack + if(!getItemCallback(ndef->get(node).name.c_str(), "on_receive_fields")) + return; + + // Call function + // param 1 + push_v3s16(L, p); + // param 2 + lua_pushstring(L, formname.c_str()); + // param 3 + 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); + } + // param 4 + objectrefGetOrCreate(sender); + if(lua_pcall(L, 4, 0, 0)) + scriptError("error: %s", lua_tostring(L, -1)); +} + diff --git a/src/script/cpp_api/s_node.h b/src/script/cpp_api/s_node.h new file mode 100644 index 000000000..bff6072b9 --- /dev/null +++ b/src/script/cpp_api/s_node.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 S_NODE_H_ +#define S_NODE_H_ + +#include + +#include "irr_v3d.h" +#include "cpp_api/s_base.h" +#include "cpp_api/s_nodemeta.h" + +class MapNode; +class ServerActiveObject; + +class ScriptApiNode + : virtual public ScriptApiBase, + public ScriptApiNodemeta +{ +public: + ScriptApiNode(); + virtual ~ScriptApiNode(); + + bool node_on_punch(v3s16 p, MapNode node, + ServerActiveObject *puncher); + bool node_on_dig(v3s16 p, MapNode node, + ServerActiveObject *digger); + void node_on_construct(v3s16 p, MapNode node); + void node_on_destruct(v3s16 p, MapNode node); + void node_after_destruct(v3s16 p, MapNode node); + bool node_on_timer(v3s16 p, MapNode node, f32 dtime); + void node_on_receive_fields(v3s16 p, + const std::string &formname, + const std::map &fields, + ServerActiveObject *sender); +public: + static struct EnumString es_DrawType[]; + static struct EnumString es_ContentParamType[]; + static struct EnumString es_ContentParamType2[]; + static struct EnumString es_LiquidType[]; + static struct EnumString es_NodeBoxType[]; +}; + + + +#endif /* S_NODE_H_ */ diff --git a/src/script/cpp_api/s_nodemeta.cpp b/src/script/cpp_api/s_nodemeta.cpp new file mode 100644 index 000000000..56cea8e5f --- /dev/null +++ b/src/script/cpp_api/s_nodemeta.cpp @@ -0,0 +1,261 @@ +/* +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_nodemeta.h" +#include "common/c_converter.h" +#include "nodedef.h" +#include "mapnode.h" +#include "server.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, + const std::string &to_list, int to_index, + int count, ServerActiveObject *player) +{ + SCRIPTAPI_PRECHECKHEADER + + INodeDefManager *ndef = getServer()->ndef(); + + // If node doesn't exist, we don't know what callback to call + MapNode node = getEnv()->getMap().getNodeNoEx(p); + if(node.getContent() == CONTENT_IGNORE) + return 0; + + // Push callback function on stack + if(!getItemCallback(ndef->get(node).name.c_str(), + "allow_metadata_inventory_move")) + return count; + + // function(pos, from_list, from_index, to_list, to_index, count, player) + // pos + push_v3s16(L, p); + // from_list + lua_pushstring(L, from_list.c_str()); + // from_index + lua_pushinteger(L, from_index + 1); + // to_list + lua_pushstring(L, to_list.c_str()); + // to_index + lua_pushinteger(L, to_index + 1); + // count + lua_pushinteger(L, count); + // player + objectrefGetOrCreate(player); + if(lua_pcall(L, 7, 1, 0)) + scriptError("error: %s", lua_tostring(L, -1)); + if(!lua_isnumber(L, -1)) + throw LuaError(L, "allow_metadata_inventory_move should return a number"); + return luaL_checkinteger(L, -1); +} + +// Return number of accepted items to be put +int ScriptApiNodemeta::nodemeta_inventory_AllowPut(v3s16 p, + const std::string &listname, int index, ItemStack &stack, + ServerActiveObject *player) +{ + SCRIPTAPI_PRECHECKHEADER + + INodeDefManager *ndef = getServer()->ndef(); + + // If node doesn't exist, we don't know what callback to call + MapNode node = getEnv()->getMap().getNodeNoEx(p); + if(node.getContent() == CONTENT_IGNORE) + return 0; + + // Push callback function on stack + if(!getItemCallback(ndef->get(node).name.c_str(), + "allow_metadata_inventory_put")) + return stack.count; + + // Call function(pos, listname, index, stack, player) + // pos + push_v3s16(L, p); + // listname + lua_pushstring(L, listname.c_str()); + // index + lua_pushinteger(L, index + 1); + // stack + LuaItemStack::create(L, stack); + // player + objectrefGetOrCreate(player); + if(lua_pcall(L, 5, 1, 0)) + scriptError("error: %s", lua_tostring(L, -1)); + if(!lua_isnumber(L, -1)) + throw LuaError(L, "allow_metadata_inventory_put should return a number"); + return luaL_checkinteger(L, -1); +} + +// Return number of accepted items to be taken +int ScriptApiNodemeta::nodemeta_inventory_AllowTake(v3s16 p, + const std::string &listname, int index, ItemStack &stack, + ServerActiveObject *player) +{ + SCRIPTAPI_PRECHECKHEADER + + INodeDefManager *ndef = getServer()->ndef(); + + // If node doesn't exist, we don't know what callback to call + MapNode node = getEnv()->getMap().getNodeNoEx(p); + if(node.getContent() == CONTENT_IGNORE) + return 0; + + // Push callback function on stack + if(!getItemCallback(ndef->get(node).name.c_str(), + "allow_metadata_inventory_take")) + return stack.count; + + // Call function(pos, listname, index, count, player) + // pos + push_v3s16(L, p); + // listname + lua_pushstring(L, listname.c_str()); + // index + lua_pushinteger(L, index + 1); + // stack + LuaItemStack::create(L, stack); + // player + objectrefGetOrCreate(player); + if(lua_pcall(L, 5, 1, 0)) + scriptError("error: %s", lua_tostring(L, -1)); + if(!lua_isnumber(L, -1)) + throw LuaError(L, "allow_metadata_inventory_take should return a number"); + return luaL_checkinteger(L, -1); +} + +// Report moved items +void ScriptApiNodemeta::nodemeta_inventory_OnMove(v3s16 p, + const std::string &from_list, int from_index, + const std::string &to_list, int to_index, + int count, ServerActiveObject *player) +{ + SCRIPTAPI_PRECHECKHEADER + + INodeDefManager *ndef = getServer()->ndef(); + + // If node doesn't exist, we don't know what callback to call + MapNode node = getEnv()->getMap().getNodeNoEx(p); + if(node.getContent() == CONTENT_IGNORE) + return; + + // Push callback function on stack + if(!getItemCallback(ndef->get(node).name.c_str(), + "on_metadata_inventory_move")) + return; + + // function(pos, from_list, from_index, to_list, to_index, count, player) + // pos + push_v3s16(L, p); + // from_list + lua_pushstring(L, from_list.c_str()); + // from_index + lua_pushinteger(L, from_index + 1); + // to_list + lua_pushstring(L, to_list.c_str()); + // to_index + lua_pushinteger(L, to_index + 1); + // count + lua_pushinteger(L, count); + // player + objectrefGetOrCreate(player); + if(lua_pcall(L, 7, 0, 0)) + scriptError("error: %s", lua_tostring(L, -1)); +} + +// Report put items +void ScriptApiNodemeta::nodemeta_inventory_OnPut(v3s16 p, + const std::string &listname, int index, ItemStack &stack, + ServerActiveObject *player) +{ + SCRIPTAPI_PRECHECKHEADER + + INodeDefManager *ndef = getServer()->ndef(); + + // If node doesn't exist, we don't know what callback to call + MapNode node = getEnv()->getMap().getNodeNoEx(p); + if(node.getContent() == CONTENT_IGNORE) + return; + + // Push callback function on stack + if(!getItemCallback(ndef->get(node).name.c_str(), + "on_metadata_inventory_put")) + return; + + // Call function(pos, listname, index, stack, player) + // pos + push_v3s16(L, p); + // listname + lua_pushstring(L, listname.c_str()); + // index + lua_pushinteger(L, index + 1); + // stack + LuaItemStack::create(L, stack); + // player + objectrefGetOrCreate(player); + if(lua_pcall(L, 5, 0, 0)) + scriptError("error: %s", lua_tostring(L, -1)); +} + +// Report taken items +void ScriptApiNodemeta::nodemeta_inventory_OnTake(v3s16 p, + const std::string &listname, int index, ItemStack &stack, + ServerActiveObject *player) +{ + SCRIPTAPI_PRECHECKHEADER + + INodeDefManager *ndef = getServer()->ndef(); + + // If node doesn't exist, we don't know what callback to call + MapNode node = getEnv()->getMap().getNodeNoEx(p); + if(node.getContent() == CONTENT_IGNORE) + return; + + // Push callback function on stack + if(!getItemCallback(ndef->get(node).name.c_str(), + "on_metadata_inventory_take")) + return; + + // Call function(pos, listname, index, stack, player) + // pos + push_v3s16(L, p); + // listname + lua_pushstring(L, listname.c_str()); + // index + lua_pushinteger(L, index + 1); + // stack + LuaItemStack::create(L, stack); + // player + objectrefGetOrCreate(player); + if(lua_pcall(L, 5, 0, 0)) + scriptError("error: %s", lua_tostring(L, -1)); +} + +ScriptApiNodemeta::ScriptApiNodemeta() { +} + +ScriptApiNodemeta::~ScriptApiNodemeta() { +} + + + diff --git a/src/script/cpp_api/s_nodemeta.h b/src/script/cpp_api/s_nodemeta.h new file mode 100644 index 000000000..9be126c62 --- /dev/null +++ b/src/script/cpp_api/s_nodemeta.h @@ -0,0 +1,67 @@ +/* +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_NODEMETA_H_ +#define S_NODEMETA_H_ + +#include "cpp_api/s_base.h" +#include "cpp_api/s_item.h" +#include "irr_v3d.h" + +class ItemStack; + +class ScriptApiNodemeta + : virtual public ScriptApiBase, + public ScriptApiItem +{ +public: + ScriptApiNodemeta(); + virtual ~ScriptApiNodemeta(); + + // Return number of accepted items to be moved + int nodemeta_inventory_AllowMove(v3s16 p, + const std::string &from_list, int from_index, + const std::string &to_list, int to_index, + int count, ServerActiveObject *player); + // Return number of accepted items to be put + int nodemeta_inventory_AllowPut(v3s16 p, + const std::string &listname, int index, ItemStack &stack, + ServerActiveObject *player); + // Return number of accepted items to be taken + int nodemeta_inventory_AllowTake(v3s16 p, + const std::string &listname, int index, ItemStack &stack, + ServerActiveObject *player); + // Report moved items + void nodemeta_inventory_OnMove(v3s16 p, + const std::string &from_list, int from_index, + const std::string &to_list, int to_index, + int count, ServerActiveObject *player); + // Report put items + void nodemeta_inventory_OnPut(v3s16 p, + const std::string &listname, int index, ItemStack &stack, + ServerActiveObject *player); + // Report taken items + void nodemeta_inventory_OnTake(v3s16 p, + const std::string &listname, int index, ItemStack &stack, + ServerActiveObject *player); +private: + +}; + +#endif /* S_NODEMETA_H_ */ diff --git a/src/script/cpp_api/s_player.cpp b/src/script/cpp_api/s_player.cpp new file mode 100644 index 000000000..e736d745d --- /dev/null +++ b/src/script/cpp_api/s_player.cpp @@ -0,0 +1,113 @@ +/* +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_player.h" + +void ScriptApiPlayer::on_newplayer(ServerActiveObject *player) +{ + SCRIPTAPI_PRECHECKHEADER + + // Get minetest.registered_on_newplayers + lua_getglobal(L, "minetest"); + lua_getfield(L, -1, "registered_on_newplayers"); + // Call callbacks + objectrefGetOrCreate(player); + runCallbacks(1, RUN_CALLBACKS_MODE_FIRST); +} + +void ScriptApiPlayer::on_dieplayer(ServerActiveObject *player) +{ + SCRIPTAPI_PRECHECKHEADER + + // Get minetest.registered_on_dieplayers + lua_getglobal(L, "minetest"); + lua_getfield(L, -1, "registered_on_dieplayers"); + // Call callbacks + objectrefGetOrCreate(player); + runCallbacks(1, RUN_CALLBACKS_MODE_FIRST); +} + +bool ScriptApiPlayer::on_respawnplayer(ServerActiveObject *player) +{ + SCRIPTAPI_PRECHECKHEADER + + // Get minetest.registered_on_respawnplayers + lua_getglobal(L, "minetest"); + lua_getfield(L, -1, "registered_on_respawnplayers"); + // Call callbacks + objectrefGetOrCreate(player); + runCallbacks(1, RUN_CALLBACKS_MODE_OR); + bool positioning_handled_by_some = lua_toboolean(L, -1); + return positioning_handled_by_some; +} + +void ScriptApiPlayer::on_joinplayer(ServerActiveObject *player) +{ + SCRIPTAPI_PRECHECKHEADER + + // Get minetest.registered_on_joinplayers + lua_getglobal(L, "minetest"); + lua_getfield(L, -1, "registered_on_joinplayers"); + // Call callbacks + objectrefGetOrCreate(player); + runCallbacks(1, RUN_CALLBACKS_MODE_FIRST); +} + +void ScriptApiPlayer::on_leaveplayer(ServerActiveObject *player) +{ + SCRIPTAPI_PRECHECKHEADER + + // Get minetest.registered_on_leaveplayers + lua_getglobal(L, "minetest"); + lua_getfield(L, -1, "registered_on_leaveplayers"); + // Call callbacks + objectrefGetOrCreate(player); + runCallbacks(1, RUN_CALLBACKS_MODE_FIRST); +} + +void ScriptApiPlayer::on_playerReceiveFields(ServerActiveObject *player, + const std::string &formname, + const std::map &fields) +{ + SCRIPTAPI_PRECHECKHEADER + + // Get minetest.registered_on_chat_messages + lua_getglobal(L, "minetest"); + lua_getfield(L, -1, "registered_on_player_receive_fields"); + // Call callbacks + // param 1 + objectrefGetOrCreate(player); + // param 2 + lua_pushstring(L, formname.c_str()); + // param 3 + 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); + } + runCallbacks(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 new file mode 100644 index 000000000..663e3c2ab --- /dev/null +++ b/src/script/cpp_api/s_player.h @@ -0,0 +1,44 @@ +/* +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_PLAYER_H_ +#define S_PLAYER_H_ + +#include "cpp_api/s_base.h" + + +class ScriptApiPlayer + : virtual public ScriptApiBase +{ +public: + virtual ~ScriptApiPlayer(); + + void on_newplayer(ServerActiveObject *player); + void on_dieplayer(ServerActiveObject *player); + bool on_respawnplayer(ServerActiveObject *player); + void on_joinplayer(ServerActiveObject *player); + void on_leaveplayer(ServerActiveObject *player); + + void on_playerReceiveFields(ServerActiveObject *player, + const std::string &formname, + const std::map &fields); +}; + + +#endif /* S_PLAYER_H_ */ diff --git a/src/script/cpp_api/scriptapi.cpp b/src/script/cpp_api/scriptapi.cpp new file mode 100644 index 000000000..b6d376b1f --- /dev/null +++ b/src/script/cpp_api/scriptapi.cpp @@ -0,0 +1,291 @@ +/* +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 new file mode 100644 index 000000000..bbd0bdda7 --- /dev/null +++ b/src/script/cpp_api/scriptapi.h @@ -0,0 +1,82 @@ +/* +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 new file mode 100644 index 000000000..7610ce8f1 --- /dev/null +++ b/src/script/lua_api/CMakeLists.txt @@ -0,0 +1,13 @@ +set(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_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 + PARENT_SCOPE) diff --git a/src/script/lua_api/l_base.cpp b/src/script/lua_api/l_base.cpp new file mode 100644 index 000000000..b1766e6df --- /dev/null +++ b/src/script/lua_api/l_base.cpp @@ -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. +*/ + +#include "cpp_api/scriptapi.h" +#include "lua_api/l_base.h" +#include "common/c_internal.h" +#include "log.h" + +extern "C" { +#include "lua.h" +} + +ModApiBase::ModApiBase() { + ScriptApi::registerModApiModule(this); +} + +Server* ModApiBase::getServer(lua_State* L) { + return get_scriptapi(L)->getServer(); +} + +Environment* ModApiBase::getEnv(lua_State* L) { + return get_scriptapi(L)->getEnv(); +} + +bool ModApiBase::registerFunction( lua_State* L, + const char* name, + lua_CFunction fct, + int top + ) { + //TODO check presence first! + + lua_pushstring(L,name); + lua_pushcfunction(L,fct); + lua_settable(L, top); + + 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 new file mode 100644 index 000000000..f2e0d59a9 --- /dev/null +++ b/src/script/lua_api/l_base.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. +*/ + +#ifndef L_BASE_H_ +#define L_BASE_H_ + +#include "biome.h" +#include "common/c_types.h" + +extern "C" { +#include "lua.h" +} + +extern struct EnumString es_BiomeTerrainType[]; + +class ScriptApi; +class Server; +class Environment; + +typedef class ModApiBase { + +public: + ModApiBase(); + + virtual bool Initialize(lua_State* L, int top) = 0; + virtual ~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 + +#endif /* L_BASE_H_ */ diff --git a/src/script/lua_api/l_craft.cpp b/src/script/lua_api/l_craft.cpp new file mode 100644 index 000000000..a32fb9dff --- /dev/null +++ b/src/script/lua_api/l_craft.cpp @@ -0,0 +1,477 @@ +/* +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_craft.h" +#include "common/c_internal.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() { + +} + +struct EnumString ModApiCraft::es_CraftMethod[] = +{ + {CRAFT_METHOD_NORMAL, "normal"}, + {CRAFT_METHOD_COOKING, "cooking"}, + {CRAFT_METHOD_FUEL, "fuel"}, + {0, NULL}, +}; + + +// helper for register_craft +bool ModApiCraft::readCraftRecipeShaped(lua_State *L, int index, + int &width, std::vector &recipe) +{ + if(index < 0) + index = lua_gettop(L) + 1 + index; + + if(!lua_istable(L, index)) + return false; + + lua_pushnil(L); + int rowcount = 0; + while(lua_next(L, index) != 0){ + int colcount = 0; + // key at index -2 and value at index -1 + if(!lua_istable(L, -1)) + return false; + int table2 = lua_gettop(L); + lua_pushnil(L); + while(lua_next(L, table2) != 0){ + // key at index -2 and value at index -1 + if(!lua_isstring(L, -1)) + return false; + recipe.push_back(lua_tostring(L, -1)); + // removes value, keeps key for next iteration + lua_pop(L, 1); + colcount++; + } + if(rowcount == 0){ + width = colcount; + } else { + if(colcount != width) + return false; + } + // removes value, keeps key for next iteration + lua_pop(L, 1); + rowcount++; + } + return width != 0; +} + +// helper for register_craft +bool ModApiCraft::readCraftRecipeShapeless(lua_State *L, int index, + std::vector &recipe) +{ + if(index < 0) + index = lua_gettop(L) + 1 + index; + + if(!lua_istable(L, index)) + return false; + + lua_pushnil(L); + while(lua_next(L, index) != 0){ + // key at index -2 and value at index -1 + if(!lua_isstring(L, -1)) + return false; + recipe.push_back(lua_tostring(L, -1)); + // removes value, keeps key for next iteration + lua_pop(L, 1); + } + return true; +} + +// helper for register_craft +bool ModApiCraft::readCraftReplacements(lua_State *L, int index, + CraftReplacements &replacements) +{ + if(index < 0) + index = lua_gettop(L) + 1 + index; + + if(!lua_istable(L, index)) + return false; + + lua_pushnil(L); + while(lua_next(L, index) != 0){ + // key at index -2 and value at index -1 + if(!lua_istable(L, -1)) + return false; + lua_rawgeti(L, -1, 1); + if(!lua_isstring(L, -1)) + return false; + std::string replace_from = lua_tostring(L, -1); + lua_pop(L, 1); + lua_rawgeti(L, -1, 2); + if(!lua_isstring(L, -1)) + return false; + std::string replace_to = lua_tostring(L, -1); + lua_pop(L, 1); + replacements.pairs.push_back( + std::make_pair(replace_from, replace_to)); + // removes value, keeps key for next iteration + lua_pop(L, 1); + } + return true; +} +// register_craft({output=item, recipe={{item00,item10},{item01,item11}}) +int ModApiCraft::l_register_craft(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + //infostream<<"register_craft"<getWritableCraftDefManager(); + + std::string type = getstringfield_default(L, table, "type", "shaped"); + + /* + CraftDefinitionShaped + */ + if(type == "shaped"){ + std::string output = getstringfield_default(L, table, "output", ""); + if(output == "") + throw LuaError(L, "Crafting definition is missing an output"); + + int width = 0; + std::vector recipe; + lua_getfield(L, table, "recipe"); + if(lua_isnil(L, -1)) + throw LuaError(L, "Crafting definition is missing a recipe" + " (output=\"" + output + "\")"); + if(!readCraftRecipeShaped(L, -1, width, recipe)) + throw LuaError(L, "Invalid crafting recipe" + " (output=\"" + output + "\")"); + + CraftReplacements replacements; + lua_getfield(L, table, "replacements"); + if(!lua_isnil(L, -1)) + { + if(!readCraftReplacements(L, -1, replacements)) + throw LuaError(L, "Invalid replacements" + " (output=\"" + output + "\")"); + } + + CraftDefinition *def = new CraftDefinitionShaped( + output, width, recipe, replacements); + craftdef->registerCraft(def); + } + /* + CraftDefinitionShapeless + */ + else if(type == "shapeless"){ + std::string output = getstringfield_default(L, table, "output", ""); + if(output == "") + throw LuaError(L, "Crafting definition (shapeless)" + " is missing an output"); + + std::vector recipe; + lua_getfield(L, table, "recipe"); + if(lua_isnil(L, -1)) + throw LuaError(L, "Crafting definition (shapeless)" + " is missing a recipe" + " (output=\"" + output + "\")"); + if(!readCraftRecipeShapeless(L, -1, recipe)) + throw LuaError(L, "Invalid crafting recipe" + " (output=\"" + output + "\")"); + + CraftReplacements replacements; + lua_getfield(L, table, "replacements"); + if(!lua_isnil(L, -1)) + { + if(!readCraftReplacements(L, -1, replacements)) + throw LuaError(L, "Invalid replacements" + " (output=\"" + output + "\")"); + } + + CraftDefinition *def = new CraftDefinitionShapeless( + output, recipe, replacements); + craftdef->registerCraft(def); + } + /* + CraftDefinitionToolRepair + */ + else if(type == "toolrepair"){ + float additional_wear = getfloatfield_default(L, table, + "additional_wear", 0.0); + + CraftDefinition *def = new CraftDefinitionToolRepair( + additional_wear); + craftdef->registerCraft(def); + } + /* + CraftDefinitionCooking + */ + else if(type == "cooking"){ + std::string output = getstringfield_default(L, table, "output", ""); + if(output == "") + throw LuaError(L, "Crafting definition (cooking)" + " is missing an output"); + + std::string recipe = getstringfield_default(L, table, "recipe", ""); + if(recipe == "") + throw LuaError(L, "Crafting definition (cooking)" + " is missing a recipe" + " (output=\"" + output + "\")"); + + float cooktime = getfloatfield_default(L, table, "cooktime", 3.0); + + CraftReplacements replacements; + lua_getfield(L, table, "replacements"); + if(!lua_isnil(L, -1)) + { + if(!readCraftReplacements(L, -1, replacements)) + throw LuaError(L, "Invalid replacements" + " (cooking output=\"" + output + "\")"); + } + + CraftDefinition *def = new CraftDefinitionCooking( + output, recipe, cooktime, replacements); + craftdef->registerCraft(def); + } + /* + CraftDefinitionFuel + */ + else if(type == "fuel"){ + std::string recipe = getstringfield_default(L, table, "recipe", ""); + if(recipe == "") + throw LuaError(L, "Crafting definition (fuel)" + " is missing a recipe"); + + float burntime = getfloatfield_default(L, table, "burntime", 1.0); + + CraftReplacements replacements; + lua_getfield(L, table, "replacements"); + if(!lua_isnil(L, -1)) + { + if(!readCraftReplacements(L, -1, replacements)) + throw LuaError(L, "Invalid replacements" + " (fuel recipe=\"" + recipe + "\")"); + } + + CraftDefinition *def = new CraftDefinitionFuel( + recipe, burntime, replacements); + craftdef->registerCraft(def); + } + else + { + throw LuaError(L, "Unknown crafting definition type: \"" + type + "\""); + } + + lua_pop(L, 1); + return 0; /* number of results */ +} + +// get_craft_result(input) +int ModApiCraft::l_get_craft_result(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + + int input_i = 1; + std::string method_s = getstringfield_default(L, input_i, "method", "normal"); + enum CraftMethod method = (CraftMethod)getenumfield(L, input_i, "method", + es_CraftMethod, CRAFT_METHOD_NORMAL); + int width = 1; + lua_getfield(L, input_i, "width"); + if(lua_isnumber(L, -1)) + width = luaL_checkinteger(L, -1); + lua_pop(L, 1); + lua_getfield(L, input_i, "items"); + std::vector items = read_items(L, -1,getServer(L)); + lua_pop(L, 1); // items + + IGameDef *gdef = getServer(L); + ICraftDefManager *cdef = gdef->cdef(); + CraftInput input(method, width, items); + CraftOutput output; + bool got = cdef->getCraftResult(input, output, true, gdef); + lua_newtable(L); // output table + if(got){ + ItemStack item; + item.deSerialize(output.item, gdef->idef()); + LuaItemStack::create(L, item); + lua_setfield(L, -2, "item"); + setintfield(L, -1, "time", output.time); + } else { + LuaItemStack::create(L, ItemStack()); + lua_setfield(L, -2, "item"); + setintfield(L, -1, "time", 0); + } + lua_newtable(L); // decremented input table + lua_pushstring(L, method_s.c_str()); + lua_setfield(L, -2, "method"); + lua_pushinteger(L, width); + lua_setfield(L, -2, "width"); + push_items(L, input.items); + lua_setfield(L, -2, "items"); + return 2; +} + +// get_craft_recipe(result item) +int ModApiCraft::l_get_craft_recipe(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + + int k = 1; + int input_i = 1; + std::string o_item = luaL_checkstring(L,input_i); + + IGameDef *gdef = getServer(L); + ICraftDefManager *cdef = gdef->cdef(); + CraftInput input; + CraftOutput output(o_item,0); + bool got = cdef->getCraftRecipe(input, output, gdef); + lua_newtable(L); // output table + if(got){ + lua_newtable(L); + for(std::vector::const_iterator + i = input.items.begin(); + i != input.items.end(); i++, k++) + { + if (i->empty()) + { + continue; + } + lua_pushinteger(L,k); + lua_pushstring(L,i->name.c_str()); + lua_settable(L, -3); + } + lua_setfield(L, -2, "items"); + setintfield(L, -1, "width", input.width); + switch (input.method) { + case CRAFT_METHOD_NORMAL: + lua_pushstring(L,"normal"); + break; + case CRAFT_METHOD_COOKING: + lua_pushstring(L,"cooking"); + break; + case CRAFT_METHOD_FUEL: + lua_pushstring(L,"fuel"); + break; + default: + lua_pushstring(L,"unknown"); + } + lua_setfield(L, -2, "type"); + } else { + lua_pushnil(L); + lua_setfield(L, -2, "items"); + setintfield(L, -1, "width", 0); + } + return 1; +} + +// get_all_craft_recipes(result item) +int ModApiCraft::l_get_all_craft_recipes(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + + std::string o_item = luaL_checkstring(L,1); + IGameDef *gdef = getServer(L); + ICraftDefManager *cdef = gdef->cdef(); + CraftInput input; + CraftOutput output(o_item,0); + std::vector recipes_list = cdef->getCraftRecipes(output, gdef); + if (recipes_list.empty()) + { + lua_pushnil(L); + return 1; + } + // Get the table insert function + 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::vector::const_iterator + i = recipes_list.begin(); + i != recipes_list.end(); i++) + { + CraftOutput tmpout; + tmpout.item = ""; + tmpout.time = 0; + CraftDefinition *def = *i; + tmpout = def->getOutput(input, gdef); + std::string query = tmpout.item; + char *fmtpos, *fmt = &query[0]; + if (strtok_r(fmt, " ", &fmtpos) == output.item) + { + input = def->getInput(output, gdef); + lua_pushvalue(L, table_insert); + lua_pushvalue(L, table); + lua_newtable(L); + int k = 1; + lua_newtable(L); + for(std::vector::const_iterator + i = input.items.begin(); + i != input.items.end(); i++, k++) + { + if (i->empty()) + continue; + lua_pushinteger(L,k); + lua_pushstring(L,i->name.c_str()); + lua_settable(L, -3); + } + lua_setfield(L, -2, "items"); + setintfield(L, -1, "width", input.width); + switch (input.method) { + case CRAFT_METHOD_NORMAL: + lua_pushstring(L,"normal"); + break; + case CRAFT_METHOD_COOKING: + lua_pushstring(L,"cooking"); + break; + case CRAFT_METHOD_FUEL: + lua_pushstring(L,"fuel"); + break; + default: + lua_pushstring(L,"unknown"); + } + lua_setfield(L, -2, "type"); + lua_pushstring(L, &tmpout.item[0]); + lua_setfield(L, -2, "output"); + if (lua_pcall(L, 2, 0, 0)) + script_error(L, "error: %s", lua_tostring(L, -1)); + } + } + 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; +} + +ModApiCraft modapicraft_prototype; diff --git a/src/script/lua_api/l_craft.h b/src/script/lua_api/l_craft.h new file mode 100644 index 000000000..d8319199d --- /dev/null +++ b/src/script/lua_api/l_craft.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 L_CRAFT_H_ +#define L_CRAFT_H_ + +#include + +extern "C" { +#include +} + +#include "lua_api/l_base.h" +#include "craftdef.h" + +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); + static int l_get_all_craft_recipes(lua_State *L); + static int l_get_craft_result(lua_State *L); + + static bool readCraftReplacements(lua_State *L, int index, + CraftReplacements &replacements); + static bool readCraftRecipeShapeless(lua_State *L, int index, + std::vector &recipe); + static bool readCraftRecipeShaped(lua_State *L, int index, + int &width, std::vector &recipe); + + static struct EnumString es_CraftMethod[]; +}; + +#endif /* L_CRAFT_H_ */ diff --git a/src/script/lua_api/l_env.cpp b/src/script/lua_api/l_env.cpp new file mode 100644 index 000000000..58cf337ed --- /dev/null +++ b/src/script/lua_api/l_env.cpp @@ -0,0 +1,687 @@ +/* +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/scriptapi.h" +#include "lua_api/l_base.h" +#include "lua_api/l_env.h" +#include "environment.h" +#include "server.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" + + +#define GET_ENV_PTR ServerEnvironment* env = \ + dynamic_cast(getEnv(L)); \ + if( env == NULL) return 0 + +void LuaABM::trigger(ServerEnvironment *env, v3s16 p, MapNode n, + u32 active_object_count, u32 active_object_count_wider) +{ + ScriptApi* scriptIface = SERVER_TO_SA(env); + scriptIface->realityCheck(); + + lua_State* L = scriptIface->getStack(); + assert(lua_checkstack(L, 20)); + StackUnroller stack_unroller(L); + + // Get minetest.registered_abms + lua_getglobal(L, "minetest"); + lua_getfield(L, -1, "registered_abms"); + luaL_checktype(L, -1, LUA_TTABLE); + int registered_abms = lua_gettop(L); + + // Get minetest.registered_abms[m_id] + lua_pushnumber(L, m_id); + lua_gettable(L, registered_abms); + if(lua_isnil(L, -1)) + assert(0); + + // Call action + luaL_checktype(L, -1, LUA_TTABLE); + lua_getfield(L, -1, "action"); + luaL_checktype(L, -1, LUA_TFUNCTION); + push_v3s16(L, p); + pushnode(L, n, env->getGameDef()->ndef()); + lua_pushnumber(L, active_object_count); + lua_pushnumber(L, active_object_count_wider); + if(lua_pcall(L, 4, 0, 0)) + script_error(L, "error: %s", lua_tostring(L, -1)); +} + +// Exported functions + +// minetest.set_node(pos, node) +// pos = {x=num, y=num, z=num} +int ModApiEnvMod::l_set_node(lua_State *L) +{ + GET_ENV_PTR; + + INodeDefManager *ndef = env->getGameDef()->ndef(); + // parameters + v3s16 pos = read_v3s16(L, 1); + MapNode n = readnode(L, 2, ndef); + // Do it + bool succeeded = env->setNode(pos, n); + lua_pushboolean(L, succeeded); + return 1; +} + +int ModApiEnvMod::l_add_node(lua_State *L) +{ + return l_set_node(L); +} + +// minetest.remove_node(pos) +// pos = {x=num, y=num, z=num} +int ModApiEnvMod::l_remove_node(lua_State *L) +{ + GET_ENV_PTR; + + // parameters + v3s16 pos = read_v3s16(L, 1); + // Do it + bool succeeded = env->removeNode(pos); + lua_pushboolean(L, succeeded); + return 1; +} + +// minetest.get_node(pos) +// pos = {x=num, y=num, z=num} +int ModApiEnvMod::l_get_node(lua_State *L) +{ + GET_ENV_PTR; + + // pos + v3s16 pos = read_v3s16(L, 1); + // Do it + MapNode n = env->getMap().getNodeNoEx(pos); + // Return node + pushnode(L, n, env->getGameDef()->ndef()); + return 1; +} + +// minetest.get_node_or_nil(pos) +// pos = {x=num, y=num, z=num} +int ModApiEnvMod::l_get_node_or_nil(lua_State *L) +{ + GET_ENV_PTR; + + // pos + v3s16 pos = read_v3s16(L, 1); + // Do it + try{ + MapNode n = env->getMap().getNode(pos); + // Return node + pushnode(L, n, env->getGameDef()->ndef()); + return 1; + } catch(InvalidPositionException &e) + { + lua_pushnil(L); + return 1; + } +} + +// minetest.get_node_light(pos, timeofday) +// pos = {x=num, y=num, z=num} +// timeofday: nil = current time, 0 = night, 0.5 = day +int ModApiEnvMod::l_get_node_light(lua_State *L) +{ + GET_ENV_PTR; + + // Do it + v3s16 pos = read_v3s16(L, 1); + u32 time_of_day = env->getTimeOfDay(); + if(lua_isnumber(L, 2)) + time_of_day = 24000.0 * lua_tonumber(L, 2); + time_of_day %= 24000; + u32 dnr = time_to_daynight_ratio(time_of_day, true); + try{ + MapNode n = env->getMap().getNode(pos); + INodeDefManager *ndef = env->getGameDef()->ndef(); + lua_pushinteger(L, n.getLightBlend(dnr, ndef)); + return 1; + } catch(InvalidPositionException &e) + { + lua_pushnil(L); + return 1; + } +} + +// minetest.place_node(pos, node) +// pos = {x=num, y=num, z=num} +int ModApiEnvMod::l_place_node(lua_State *L) +{ + GET_ENV_PTR; + + v3s16 pos = read_v3s16(L, 1); + MapNode n = readnode(L, 2, env->getGameDef()->ndef()); + + // Don't attempt to load non-loaded area as of now + MapNode n_old = env->getMap().getNodeNoEx(pos); + if(n_old.getContent() == CONTENT_IGNORE){ + lua_pushboolean(L, false); + 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; + pointed.type = POINTEDTHING_NODE; + pointed.node_abovesurface = pos; + 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); + lua_pushboolean(L, success); + return 1; +} + +// minetest.dig_node(pos) +// pos = {x=num, y=num, z=num} +int ModApiEnvMod::l_dig_node(lua_State *L) +{ + GET_ENV_PTR; + + v3s16 pos = read_v3s16(L, 1); + + // Don't attempt to load non-loaded area as of now + MapNode n = env->getMap().getNodeNoEx(pos); + if(n.getContent() == CONTENT_IGNORE){ + lua_pushboolean(L, false); + return 1; + } + // 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); + lua_pushboolean(L, success); + return 1; +} + +// minetest.punch_node(pos) +// pos = {x=num, y=num, z=num} +int ModApiEnvMod::l_punch_node(lua_State *L) +{ + GET_ENV_PTR; + + v3s16 pos = read_v3s16(L, 1); + + // Don't attempt to load non-loaded area as of now + MapNode n = env->getMap().getNodeNoEx(pos); + if(n.getContent() == CONTENT_IGNORE){ + lua_pushboolean(L, false); + return 1; + } + // 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); + lua_pushboolean(L, success); + return 1; +} + +// minetest.get_meta(pos) +int ModApiEnvMod::l_get_meta(lua_State *L) +{ + GET_ENV_PTR; + + // Do it + v3s16 p = read_v3s16(L, 1); + NodeMetaRef::create(L, p, env); + return 1; +} + +// minetest.get_node_timer(pos) +int ModApiEnvMod::l_get_node_timer(lua_State *L) +{ + GET_ENV_PTR; + + // Do it + v3s16 p = read_v3s16(L, 1); + NodeTimerRef::create(L, p, env); + return 1; +} + +// minetest.add_entity(pos, entityname) -> ObjectRef or nil +// pos = {x=num, y=num, z=num} +int ModApiEnvMod::l_add_entity(lua_State *L) +{ + GET_ENV_PTR; + + // pos + v3f pos = checkFloatPos(L, 1); + // content + const char *name = luaL_checkstring(L, 2); + // Do it + ServerActiveObject *obj = new LuaEntitySAO(env, pos, name, ""); + int objectid = env->addActiveObject(obj); + // If failed to add, return nothing (reads as nil) + if(objectid == 0) + return 0; + // Return ObjectRef + get_scriptapi(L)->objectrefGetOrCreate(obj); + return 1; +} + +// minetest.add_item(pos, itemstack or itemstring or table) -> ObjectRef or nil +// pos = {x=num, y=num, z=num} +int ModApiEnvMod::l_add_item(lua_State *L) +{ + GET_ENV_PTR; + + // pos + //v3f pos = checkFloatPos(L, 1); + // item + ItemStack item = read_item(L, 2,getServer(L)); + if(item.empty() || !item.isKnown(getServer(L)->idef())) + return 0; + // Use minetest.spawn_item to spawn a __builtin:item + lua_getglobal(L, "minetest"); + lua_getfield(L, -1, "spawn_item"); + if(lua_isnil(L, -1)) + return 0; + lua_pushvalue(L, 1); + lua_pushstring(L, item.getItemString().c_str()); + if(lua_pcall(L, 2, 1, 0)) + script_error(L, "error: %s", lua_tostring(L, -1)); + return 1; + /*lua_pushvalue(L, 1); + lua_pushstring(L, "__builtin:item"); + lua_pushstring(L, item.getItemString().c_str()); + return l_add_entity(L);*/ + /*// Do it + ServerActiveObject *obj = createItemSAO(env, pos, item.getItemString()); + int objectid = env->addActiveObject(obj); + // If failed to add, return nothing (reads as nil) + if(objectid == 0) + return 0; + // Return ObjectRef + objectrefGetOrCreate(L, obj); + return 1;*/ +} + +// minetest.get_player_by_name(name) +int ModApiEnvMod::l_get_player_by_name(lua_State *L) +{ + GET_ENV_PTR; + + // Do it + const char *name = luaL_checkstring(L, 1); + Player *player = env->getPlayer(name); + if(player == NULL){ + lua_pushnil(L); + return 1; + } + PlayerSAO *sao = player->getPlayerSAO(); + if(sao == NULL){ + lua_pushnil(L); + return 1; + } + // Put player on stack + get_scriptapi(L)->objectrefGetOrCreate(sao); + return 1; +} + +// minetest.get_objects_inside_radius(pos, radius) +int ModApiEnvMod::l_get_objects_inside_radius(lua_State *L) +{ + // Get the table insert function + lua_getglobal(L, "table"); + lua_getfield(L, -1, "insert"); + int table_insert = lua_gettop(L); + + GET_ENV_PTR; + + // Do it + v3f pos = checkFloatPos(L, 1); + float radius = luaL_checknumber(L, 2) * BS; + std::set ids = env->getObjectsInsideRadius(pos, radius); + lua_newtable(L); + int table = lua_gettop(L); + for(std::set::const_iterator + i = ids.begin(); i != ids.end(); i++){ + ServerActiveObject *obj = env->getActiveObject(*i); + // Insert object reference into table + lua_pushvalue(L, table_insert); + lua_pushvalue(L, table); + get_scriptapi(L)->objectrefGetOrCreate(obj); + if(lua_pcall(L, 2, 0, 0)) + script_error(L, "error: %s", lua_tostring(L, -1)); + } + return 1; +} + +// minetest.set_timeofday(val) +// val = 0...1 +int ModApiEnvMod::l_set_timeofday(lua_State *L) +{ + GET_ENV_PTR; + + // Do it + float timeofday_f = luaL_checknumber(L, 1); + assert(timeofday_f >= 0.0 && timeofday_f <= 1.0); + int timeofday_mh = (int)(timeofday_f * 24000.0); + // This should be set directly in the environment but currently + // such changes aren't immediately sent to the clients, so call + // the server instead. + //env->setTimeOfDay(timeofday_mh); + getServer(L)->setTimeOfDay(timeofday_mh); + return 0; +} + +// minetest.get_timeofday() -> 0...1 +int ModApiEnvMod::l_get_timeofday(lua_State *L) +{ + GET_ENV_PTR; + + // Do it + int timeofday_mh = env->getTimeOfDay(); + float timeofday_f = (float)timeofday_mh / 24000.0; + lua_pushnumber(L, timeofday_f); + return 1; +} + + +// minetest.find_node_near(pos, radius, nodenames) -> pos or nil +// nodenames: eg. {"ignore", "group:tree"} or "default:dirt" +int ModApiEnvMod::l_find_node_near(lua_State *L) +{ + GET_ENV_PTR; + + INodeDefManager *ndef = getServer(L)->ndef(); + v3s16 pos = read_v3s16(L, 1); + int radius = luaL_checkinteger(L, 2); + std::set filter; + if(lua_istable(L, 3)){ + int table = 3; + lua_pushnil(L); + while(lua_next(L, table) != 0){ + // key at index -2 and value at index -1 + luaL_checktype(L, -1, LUA_TSTRING); + ndef->getIds(lua_tostring(L, -1), filter); + // removes value, keeps key for next iteration + lua_pop(L, 1); + } + } else if(lua_isstring(L, 3)){ + ndef->getIds(lua_tostring(L, 3), filter); + } + + for(int d=1; d<=radius; d++){ + std::list list; + getFacePositions(list, d); + for(std::list::iterator i = list.begin(); + i != list.end(); ++i){ + v3s16 p = pos + (*i); + content_t c = env->getMap().getNodeNoEx(p).getContent(); + if(filter.count(c) != 0){ + push_v3s16(L, p); + return 1; + } + } + } + return 0; +} + +// minetest.find_nodes_in_area(minp, maxp, nodenames) -> list of positions +// nodenames: eg. {"ignore", "group:tree"} or "default:dirt" +int ModApiEnvMod::l_find_nodes_in_area(lua_State *L) +{ + GET_ENV_PTR; + + INodeDefManager *ndef = getServer(L)->ndef(); + v3s16 minp = read_v3s16(L, 1); + v3s16 maxp = read_v3s16(L, 2); + std::set filter; + if(lua_istable(L, 3)){ + int table = 3; + lua_pushnil(L); + while(lua_next(L, table) != 0){ + // key at index -2 and value at index -1 + luaL_checktype(L, -1, LUA_TSTRING); + ndef->getIds(lua_tostring(L, -1), filter); + // removes value, keeps key for next iteration + lua_pop(L, 1); + } + } else if(lua_isstring(L, 3)){ + ndef->getIds(lua_tostring(L, 3), filter); + } + + // Get the table insert function + lua_getglobal(L, "table"); + lua_getfield(L, -1, "insert"); + int table_insert = lua_gettop(L); + + lua_newtable(L); + int table = lua_gettop(L); + for(s16 x=minp.X; x<=maxp.X; x++) + for(s16 y=minp.Y; y<=maxp.Y; y++) + for(s16 z=minp.Z; z<=maxp.Z; z++) + { + v3s16 p(x,y,z); + content_t c = env->getMap().getNodeNoEx(p).getContent(); + if(filter.count(c) != 0){ + lua_pushvalue(L, table_insert); + lua_pushvalue(L, table); + push_v3s16(L, p); + if(lua_pcall(L, 2, 0, 0)) + script_error(L, "error: %s", lua_tostring(L, -1)); + } + } + return 1; +} + +// minetest.get_perlin(seeddiff, octaves, persistence, scale) +// returns world-specific PerlinNoise +int ModApiEnvMod::l_get_perlin(lua_State *L) +{ + GET_ENV_PTR; + + int seeddiff = luaL_checkint(L, 1); + int octaves = luaL_checkint(L, 2); + float persistence = luaL_checknumber(L, 3); + float scale = luaL_checknumber(L, 4); + + LuaPerlinNoise *n = new LuaPerlinNoise(seeddiff + int(env->getServerMap().getSeed()), octaves, persistence, scale); + *(void **)(lua_newuserdata(L, sizeof(void *))) = n; + luaL_getmetatable(L, "PerlinNoise"); + lua_setmetatable(L, -2); + return 1; +} + +// minetest.get_perlin_map(noiseparams, size) +// returns world-specific PerlinNoiseMap +int ModApiEnvMod::l_get_perlin_map(lua_State *L) +{ + GET_ENV_PTR; + + NoiseParams *np = read_noiseparams(L, 1); + if (!np) + return 0; + v3s16 size = read_v3s16(L, 2); + + int seed = (int)(env->getServerMap().getSeed()); + LuaPerlinNoiseMap *n = new LuaPerlinNoiseMap(np, seed, size); + *(void **)(lua_newuserdata(L, sizeof(void *))) = n; + luaL_getmetatable(L, "PerlinNoiseMap"); + lua_setmetatable(L, -2); + return 1; +} + +// minetest.clear_objects() +// clear all objects in the environment +int ModApiEnvMod::l_clear_objects(lua_State *L) +{ + GET_ENV_PTR; + + env->clearAllObjects(); + return 0; +} + +// minetest.line_of_sight(pos1, pos2, stepsize) -> true/false +int ModApiEnvMod::l_line_of_sight(lua_State *L) { + float stepsize = 1.0; + + GET_ENV_PTR; + + // read position 1 from lua + v3f pos1 = checkFloatPos(L, 2); + // read position 2 from lua + v3f pos2 = checkFloatPos(L, 2); + //read step size from lua + if(lua_isnumber(L, 3)) + stepsize = lua_tonumber(L, 3); + + return (env->line_of_sight(pos1,pos2,stepsize)); +} + +// minetest.find_path(pos1, pos2, searchdistance, +// max_jump, max_drop, algorithm) -> table containing path +int ModApiEnvMod::l_find_path(lua_State *L) +{ + GET_ENV_PTR; + + v3s16 pos1 = read_v3s16(L, 2); + v3s16 pos2 = read_v3s16(L, 3); + unsigned int searchdistance = luaL_checkint(L, 4); + unsigned int max_jump = luaL_checkint(L, 5); + unsigned int max_drop = luaL_checkint(L, 6); + algorithm algo = A_PLAIN_NP; + if(! lua_isnil(L, 7)) { + std::string algorithm = luaL_checkstring(L,7); + + if (algorithm == "A*") + algo = A_PLAIN; + + if (algorithm == "Dijkstra") + algo = DIJKSTRA; + } + + std::vector path = + get_Path(env,pos1,pos2,searchdistance,max_jump,max_drop,algo); + + if (path.size() > 0) + { + lua_newtable(L); + int top = lua_gettop(L); + unsigned int index = 1; + for (std::vector::iterator i = path.begin(); i != path.end();i++) + { + lua_pushnumber(L,index); + push_v3s16(L, *i); + lua_settable(L, top); + index++; + } + return 1; + } + + return 0; +} + +// minetest.spawn_tree(pos, treedef) +int ModApiEnvMod::l_spawn_tree(lua_State *L) +{ + GET_ENV_PTR; + + v3s16 p0 = read_v3s16(L, 1); + + treegen::TreeDef tree_def; + std::string trunk,leaves,fruit; + INodeDefManager *ndef = env->getGameDef()->ndef(); + + if(lua_istable(L, 2)) + { + getstringfield(L, 2, "axiom", tree_def.initial_axiom); + getstringfield(L, 2, "rules_a", tree_def.rules_a); + getstringfield(L, 2, "rules_b", tree_def.rules_b); + getstringfield(L, 2, "rules_c", tree_def.rules_c); + getstringfield(L, 2, "rules_d", tree_def.rules_d); + getstringfield(L, 2, "trunk", trunk); + tree_def.trunknode=ndef->getId(trunk); + getstringfield(L, 2, "leaves", leaves); + tree_def.leavesnode=ndef->getId(leaves); + tree_def.leaves2_chance=0; + getstringfield(L, 2, "leaves2", leaves); + if (leaves !="") + { + tree_def.leaves2node=ndef->getId(leaves); + getintfield(L, 2, "leaves2_chance", tree_def.leaves2_chance); + } + getintfield(L, 2, "angle", tree_def.angle); + getintfield(L, 2, "iterations", tree_def.iterations); + getintfield(L, 2, "random_level", tree_def.iterations_random_level); + getstringfield(L, 2, "trunk_type", tree_def.trunk_type); + getboolfield(L, 2, "thin_branches", tree_def.thin_branches); + tree_def.fruit_chance=0; + getstringfield(L, 2, "fruit", fruit); + if (fruit != "") + { + tree_def.fruitnode=ndef->getId(fruit); + getintfield(L, 2, "fruit_chance",tree_def.fruit_chance); + } + getintfield(L, 2, "seed", tree_def.seed); + } + else + return 0; + treegen::spawn_ltree (env, p0, ndef, tree_def); + return 1; +} + +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(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(clear_objects); + retval &= API_FCT(spawn_tree); + + return retval; +} + +ModApiEnvMod modapienv_prototype; diff --git a/src/script/lua_api/l_env.h b/src/script/lua_api/l_env.h new file mode 100644 index 000000000..61ecaecc8 --- /dev/null +++ b/src/script/lua_api/l_env.h @@ -0,0 +1,172 @@ +/* +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_ENV_H_ +#define L_ENV_H_ + +extern "C" { +#include +#include +} + +#include "environment.h" +#include "lua_api/l_base.h" + +class ModApiEnvMod + :public ModApiBase +{ +private: + // minetest.set_node(pos, node) + // pos = {x=num, y=num, z=num} + static int l_set_node(lua_State *L); + + static int l_add_node(lua_State *L); + + // minetest.remove_node(pos) + // pos = {x=num, y=num, z=num} + static int l_remove_node(lua_State *L); + + // minetest.get_node(pos) + // pos = {x=num, y=num, z=num} + static int l_get_node(lua_State *L); + + // minetest.get_node_or_nil(pos) + // pos = {x=num, y=num, z=num} + static int l_get_node_or_nil(lua_State *L); + + // minetest.get_node_light(pos, timeofday) + // pos = {x=num, y=num, z=num} + // timeofday: nil = current time, 0 = night, 0.5 = day + static int l_get_node_light(lua_State *L); + + // minetest.place_node(pos, node) + // pos = {x=num, y=num, z=num} + static int l_place_node(lua_State *L); + + // minetest.dig_node(pos) + // pos = {x=num, y=num, z=num} + static int l_dig_node(lua_State *L); + + // minetest.punch_node(pos) + // pos = {x=num, y=num, z=num} + static int l_punch_node(lua_State *L); + + // minetest.get_meta(pos) + static int l_get_meta(lua_State *L); + + // minetest.get_node_timer(pos) + static int l_get_node_timer(lua_State *L); + + // minetest.add_entity(pos, entityname) -> ObjectRef or nil + // pos = {x=num, y=num, z=num} + static int l_add_entity(lua_State *L); + + // minetest.add_item(pos, itemstack or itemstring or table) -> ObjectRef or nil + // pos = {x=num, y=num, z=num} + static int l_add_item(lua_State *L); + + // minetest.get_player_by_name(name) + static int l_get_player_by_name(lua_State *L); + + // minetest.get_objects_inside_radius(pos, radius) + static int l_get_objects_inside_radius(lua_State *L); + + // minetest.set_timeofday(val) + // val = 0...1 + static int l_set_timeofday(lua_State *L); + + // minetest.get_timeofday() -> 0...1 + static int l_get_timeofday(lua_State *L); + + // minetest.find_node_near(pos, radius, nodenames) -> pos or nil + // nodenames: eg. {"ignore", "group:tree"} or "default:dirt" + static int l_find_node_near(lua_State *L); + + // minetest.find_nodes_in_area(minp, maxp, nodenames) -> list of positions + // nodenames: eg. {"ignore", "group:tree"} or "default:dirt" + static int l_find_nodes_in_area(lua_State *L); + + // minetest.get_perlin(seeddiff, octaves, persistence, scale) + // returns world-specific PerlinNoise + static int l_get_perlin(lua_State *L); + + // minetest.get_perlin_map(noiseparams, size) + // returns world-specific PerlinNoiseMap + static int l_get_perlin_map(lua_State *L); + + // minetest.clear_objects() + // clear all objects in the environment + static int l_clear_objects(lua_State *L); + + // minetest.spawn_tree(pos, treedef) + static int l_spawn_tree(lua_State *L); + + // minetest.line_of_sight(pos1, pos2, stepsize) -> true/false + static int l_line_of_sight(lua_State *L); + + // minetest.find_path(pos1, pos2, searchdistance, + // max_jump, max_drop, algorithm) -> table containing path + static int l_find_path(lua_State *L); + +public: + bool Initialize(lua_State *L, int top); +}; + +class LuaABM : public ActiveBlockModifier +{ +private: + int m_id; + + std::set m_trigger_contents; + std::set m_required_neighbors; + float m_trigger_interval; + u32 m_trigger_chance; +public: + LuaABM(lua_State *L, int id, + const std::set &trigger_contents, + const std::set &required_neighbors, + float trigger_interval, u32 trigger_chance): + m_id(id), + m_trigger_contents(trigger_contents), + m_required_neighbors(required_neighbors), + m_trigger_interval(trigger_interval), + m_trigger_chance(trigger_chance) + { + } + virtual std::set getTriggerContents() + { + return m_trigger_contents; + } + virtual std::set getRequiredNeighbors() + { + return m_required_neighbors; + } + virtual float getTriggerInterval() + { + return m_trigger_interval; + } + virtual u32 getTriggerChance() + { + return m_trigger_chance; + } + virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n, + u32 active_object_count, u32 active_object_count_wider); +}; + +#endif /* L_ENV_H_ */ diff --git a/src/script/lua_api/l_inventory.cpp b/src/script/lua_api/l_inventory.cpp new file mode 100644 index 000000000..884b33e67 --- /dev/null +++ b/src/script/lua_api/l_inventory.cpp @@ -0,0 +1,483 @@ +/* +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/scriptapi.h" +#include "common/c_converter.h" +#include "common/c_content.h" +#include "lua_api/l_inventory.h" +#include "lua_api/l_item.h" +#include "common/c_internal.h" +#include "server.h" +#include "log.h" +#include "inventorymanager.h" + +/* + InvRef +*/ +InvRef* InvRef::checkobject(lua_State *L, int narg) +{ + luaL_checktype(L, narg, LUA_TUSERDATA); + void *ud = luaL_checkudata(L, narg, className); + if(!ud) luaL_typerror(L, narg, className); + return *(InvRef**)ud; // unbox pointer +} + +Inventory* InvRef::getinv(lua_State *L, InvRef *ref) +{ + return STACK_TO_SERVER(L)->getInventory(ref->m_loc); +} + +InventoryList* InvRef::getlist(lua_State *L, InvRef *ref, + const char *listname) +{ + NO_MAP_LOCK_REQUIRED; + Inventory *inv = getinv(L, ref); + if(!inv) + return NULL; + return inv->getList(listname); +} + +void InvRef::reportInventoryChange(lua_State *L, InvRef *ref) +{ + // Inform other things that the inventory has changed + STACK_TO_SERVER(L)->setInventoryModified(ref->m_loc); +} + +// Exported functions + +// garbage collector +int InvRef::gc_object(lua_State *L) { + InvRef *o = *(InvRef **)(lua_touserdata(L, 1)); + delete o; + return 0; +} + +// is_empty(self, listname) -> true/false +int InvRef::l_is_empty(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + InvRef *ref = checkobject(L, 1); + const char *listname = luaL_checkstring(L, 2); + InventoryList *list = getlist(L, ref, listname); + if(list && list->getUsedSlots() > 0){ + lua_pushboolean(L, false); + } else { + lua_pushboolean(L, true); + } + return 1; +} + +// get_size(self, listname) +int InvRef::l_get_size(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + InvRef *ref = checkobject(L, 1); + const char *listname = luaL_checkstring(L, 2); + InventoryList *list = getlist(L, ref, listname); + if(list){ + lua_pushinteger(L, list->getSize()); + } else { + lua_pushinteger(L, 0); + } + return 1; +} + +// get_width(self, listname) +int InvRef::l_get_width(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + InvRef *ref = checkobject(L, 1); + const char *listname = luaL_checkstring(L, 2); + InventoryList *list = getlist(L, ref, listname); + if(list){ + lua_pushinteger(L, list->getWidth()); + } else { + lua_pushinteger(L, 0); + } + return 1; +} + +// set_size(self, listname, size) +int InvRef::l_set_size(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + InvRef *ref = checkobject(L, 1); + const char *listname = luaL_checkstring(L, 2); + int newsize = luaL_checknumber(L, 3); + Inventory *inv = getinv(L, ref); + if(newsize == 0){ + inv->deleteList(listname); + reportInventoryChange(L, ref); + return 0; + } + InventoryList *list = inv->getList(listname); + if(list){ + list->setSize(newsize); + } else { + list = inv->addList(listname, newsize); + } + reportInventoryChange(L, ref); + return 0; +} + +// set_width(self, listname, size) +int InvRef::l_set_width(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + InvRef *ref = checkobject(L, 1); + const char *listname = luaL_checkstring(L, 2); + int newwidth = luaL_checknumber(L, 3); + Inventory *inv = getinv(L, ref); + InventoryList *list = inv->getList(listname); + if(list){ + list->setWidth(newwidth); + } else { + return 0; + } + reportInventoryChange(L, ref); + return 0; +} + +// get_stack(self, listname, i) -> itemstack +int InvRef::l_get_stack(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + InvRef *ref = checkobject(L, 1); + const char *listname = luaL_checkstring(L, 2); + int i = luaL_checknumber(L, 3) - 1; + InventoryList *list = getlist(L, ref, listname); + ItemStack item; + if(list != NULL && i >= 0 && i < (int) list->getSize()) + item = list->getItem(i); + LuaItemStack::create(L, item); + return 1; +} + +// set_stack(self, listname, i, stack) -> true/false +int InvRef::l_set_stack(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + 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)); + InventoryList *list = getlist(L, ref, listname); + if(list != NULL && i >= 0 && i < (int) list->getSize()){ + list->changeItem(i, newitem); + reportInventoryChange(L, ref); + lua_pushboolean(L, true); + } else { + lua_pushboolean(L, false); + } + return 1; +} + +// get_list(self, listname) -> list or nil +int InvRef::l_get_list(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + InvRef *ref = checkobject(L, 1); + const char *listname = luaL_checkstring(L, 2); + Inventory *inv = getinv(L, ref); + push_inventory_list(inv, listname, L); + return 1; +} + +// set_list(self, listname, list) +int InvRef::l_set_list(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + InvRef *ref = checkobject(L, 1); + const char *listname = luaL_checkstring(L, 2); + Inventory *inv = getinv(L, ref); + InventoryList *list = inv->getList(listname); + if(list) + read_inventory_list(inv, listname, L, 3, + STACK_TO_SERVER(L),list->getSize()); + else + read_inventory_list(inv, listname, L, 3,STACK_TO_SERVER(L)); + reportInventoryChange(L, ref); + return 0; +} + +// add_item(self, listname, itemstack or itemstring or table or nil) -> itemstack +// Returns the leftover stack +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)); + InventoryList *list = getlist(L, ref, listname); + if(list){ + ItemStack leftover = list->addItem(item); + if(leftover.count != item.count) + reportInventoryChange(L, ref); + LuaItemStack::create(L, leftover); + } else { + LuaItemStack::create(L, item); + } + return 1; +} + +// room_for_item(self, listname, itemstack or itemstring or table or nil) -> true/false +// Returns true if the item completely fits into the list +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)); + InventoryList *list = getlist(L, ref, listname); + if(list){ + lua_pushboolean(L, list->roomForItem(item)); + } else { + lua_pushboolean(L, false); + } + return 1; +} + +// contains_item(self, listname, itemstack or itemstring or table or nil) -> true/false +// Returns true if the list contains the given count of the given item name +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)); + InventoryList *list = getlist(L, ref, listname); + if(list){ + lua_pushboolean(L, list->containsItem(item)); + } else { + lua_pushboolean(L, false); + } + return 1; +} + +// remove_item(self, listname, itemstack or itemstring or table or nil) -> itemstack +// Returns the items that were actually removed +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)); + InventoryList *list = getlist(L, ref, listname); + if(list){ + ItemStack removed = list->removeItem(item); + if(!removed.empty()) + reportInventoryChange(L, ref); + LuaItemStack::create(L, removed); + } else { + LuaItemStack::create(L, ItemStack()); + } + return 1; +} + +// get_location() -> location (like minetest.get_inventory(location)) +int InvRef::l_get_location(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + InvRef *ref = checkobject(L, 1); + const InventoryLocation &loc = ref->m_loc; + switch(loc.type){ + case InventoryLocation::PLAYER: + lua_newtable(L); + lua_pushstring(L, "player"); + lua_setfield(L, -2, "type"); + lua_pushstring(L, loc.name.c_str()); + lua_setfield(L, -2, "name"); + return 1; + case InventoryLocation::NODEMETA: + lua_newtable(L); + lua_pushstring(L, "nodemeta"); + lua_setfield(L, -2, "type"); + push_v3s16(L, loc.p); + lua_setfield(L, -2, "name"); + return 1; + case InventoryLocation::DETACHED: + lua_newtable(L); + lua_pushstring(L, "detached"); + lua_setfield(L, -2, "type"); + lua_pushstring(L, loc.name.c_str()); + lua_setfield(L, -2, "name"); + return 1; + case InventoryLocation::UNDEFINED: + case InventoryLocation::CURRENT_PLAYER: + break; + } + lua_newtable(L); + lua_pushstring(L, "undefined"); + lua_setfield(L, -2, "type"); + return 1; +} + + +InvRef::InvRef(const InventoryLocation &loc): + m_loc(loc) +{ +} + +InvRef::~InvRef() +{ +} + +// Creates an InvRef and leaves it on top of stack +// Not callable from Lua; all references are created on the C side. +void InvRef::create(lua_State *L, const InventoryLocation &loc) +{ + NO_MAP_LOCK_REQUIRED; + InvRef *o = new InvRef(loc); + *(void **)(lua_newuserdata(L, sizeof(void *))) = o; + luaL_getmetatable(L, className); + lua_setmetatable(L, -2); +} +void InvRef::createPlayer(lua_State *L, Player *player) +{ + NO_MAP_LOCK_REQUIRED; + InventoryLocation loc; + loc.setPlayer(player->getName()); + create(L, loc); +} +void InvRef::createNodeMeta(lua_State *L, v3s16 p) +{ + InventoryLocation loc; + loc.setNodeMeta(p); + create(L, loc); +} + +void InvRef::Register(lua_State *L) +{ + lua_newtable(L); + int methodtable = lua_gettop(L); + luaL_newmetatable(L, className); + int metatable = lua_gettop(L); + + lua_pushliteral(L, "__metatable"); + lua_pushvalue(L, methodtable); + lua_settable(L, metatable); // hide metatable from Lua getmetatable() + + lua_pushliteral(L, "__index"); + lua_pushvalue(L, methodtable); + lua_settable(L, metatable); + + lua_pushliteral(L, "__gc"); + lua_pushcfunction(L, gc_object); + lua_settable(L, metatable); + + lua_pop(L, 1); // drop metatable + + luaL_openlib(L, 0, methods, 0); // fill methodtable + lua_pop(L, 1); // drop methodtable + + // Cannot be created from Lua + //lua_register(L, className, create_object); +} + +const char InvRef::className[] = "InvRef"; +const luaL_reg InvRef::methods[] = { + luamethod(InvRef, is_empty), + luamethod(InvRef, get_size), + luamethod(InvRef, set_size), + luamethod(InvRef, get_width), + luamethod(InvRef, set_width), + luamethod(InvRef, get_stack), + luamethod(InvRef, set_stack), + luamethod(InvRef, get_list), + luamethod(InvRef, set_list), + luamethod(InvRef, add_item), + luamethod(InvRef, room_for_item), + luamethod(InvRef, contains_item), + luamethod(InvRef, remove_item), + luamethod(InvRef, get_location), + {0,0} +}; + +// get_inventory(location) +int ModApiInventory::l_get_inventory(lua_State *L) +{ + InventoryLocation loc; + + std::string type = checkstringfield(L, 1, "type"); + + if(type != "pos"){ + NO_MAP_LOCK_REQUIRED; + + if(type == "player"){ + std::string name = checkstringfield(L, 1, "name"); + loc.setPlayer(name); + } else if(type == "detached"){ + std::string name = checkstringfield(L, 1, "name"); + loc.setDetached(name); + } + + if(getServer(L)->getInventory(loc) != NULL) + InvRef::create(L, loc); + else + lua_pushnil(L); + + return 1; + } + else { + if(type == "node"){ + lua_getfield(L, 1, "pos"); + v3s16 pos = check_v3s16(L, -1); + loc.setNodeMeta(pos); + } + if(getServer(L)->getInventory(loc) != NULL) + InvRef::create(L, loc); + else + lua_pushnil(L); + return 1; + } + +} + +// create_detached_inventory_raw(name) +int ModApiInventory::l_create_detached_inventory_raw(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + const char *name = luaL_checkstring(L, 1); + if(getServer(L)->createDetachedInventory(name) != NULL){ + InventoryLocation loc; + loc.setDetached(name); + InvRef::create(L, loc); + }else{ + lua_pushnil(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() { + +} + +ModApiInventory modapiinventory_prototype; diff --git a/src/script/lua_api/l_inventory.h b/src/script/lua_api/l_inventory.h new file mode 100644 index 000000000..83e8039b8 --- /dev/null +++ b/src/script/lua_api/l_inventory.h @@ -0,0 +1,137 @@ +/* +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_INVENTORY_H_ +#define L_INVENTORY_H_ + +extern "C" { +#include +#include +} + +#include "inventorymanager.h" +#include "player.h" +#include "serverobject.h" +#include "inventory.h" + +#include "lua_api/l_base.h" +/* + InvRef +*/ + +class InvRef +{ +private: + InventoryLocation m_loc; + + static const char className[]; + static const luaL_reg methods[]; + + static InvRef *checkobject(lua_State *L, int narg); + + static Inventory* getinv(lua_State *L, InvRef *ref); + + static InventoryList* getlist(lua_State *L, InvRef *ref, + const char *listname); + + static void reportInventoryChange(lua_State *L, InvRef *ref); + + // Exported functions + + // garbage collector + static int gc_object(lua_State *L); + + // is_empty(self, listname) -> true/false + static int l_is_empty(lua_State *L); + + // get_size(self, listname) + static int l_get_size(lua_State *L); + + // get_width(self, listname) + static int l_get_width(lua_State *L); + + // set_size(self, listname, size) + static int l_set_size(lua_State *L); + + // set_width(self, listname, size) + static int l_set_width(lua_State *L); + + // get_stack(self, listname, i) -> itemstack + static int l_get_stack(lua_State *L); + + // set_stack(self, listname, i, stack) -> true/false + static int l_set_stack(lua_State *L); + + // get_list(self, listname) -> list or nil + static int l_get_list(lua_State *L); + + // set_list(self, listname, list) + static int l_set_list(lua_State *L); + + // add_item(self, listname, itemstack or itemstring or table or nil) -> itemstack + // Returns the leftover stack + static int l_add_item(lua_State *L); + + // room_for_item(self, listname, itemstack or itemstring or table or nil) -> true/false + // Returns true if the item completely fits into the list + static int l_room_for_item(lua_State *L); + + // contains_item(self, listname, itemstack or itemstring or table or nil) -> true/false + // Returns true if the list contains the given count of the given item name + static int l_contains_item(lua_State *L); + + // remove_item(self, listname, itemstack or itemstring or table or nil) -> itemstack + // Returns the items that were actually removed + static int l_remove_item(lua_State *L); + + // get_location() -> location (like minetest.get_inventory(location)) + static int l_get_location(lua_State *L); + +public: + InvRef(const InventoryLocation &loc); + + ~InvRef(); + + // Creates an InvRef and leaves it on top of stack + // Not callable from Lua; all references are created on the C side. + static void create(lua_State *L, const InventoryLocation &loc); + static void createPlayer(lua_State *L, Player *player); + static void createNodeMeta(lua_State *L, v3s16 p); + static void Register(lua_State *L); +}; + +class ModApiInventory + : public ModApiBase +{ +public: + ModApiInventory(); + + bool Initialize(lua_State *L, int top); + + 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); + +}; + +#endif /* L_INVENTORY_H_ */ diff --git a/src/script/lua_api/l_item.cpp b/src/script/lua_api/l_item.cpp new file mode 100644 index 000000000..e9997d489 --- /dev/null +++ b/src/script/lua_api/l_item.cpp @@ -0,0 +1,472 @@ +/* +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_item.h" +#include "common/c_converter.h" +#include "common/c_content.h" +#include "cpp_api/scriptapi.h" +#include "server.h" +#include "common/c_internal.h" + +// garbage collector +int LuaItemStack::gc_object(lua_State *L) +{ + LuaItemStack *o = *(LuaItemStack **)(lua_touserdata(L, 1)); + delete o; + return 0; +} + +// is_empty(self) -> true/false +int LuaItemStack::l_is_empty(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + LuaItemStack *o = checkobject(L, 1); + ItemStack &item = o->m_stack; + lua_pushboolean(L, item.empty()); + return 1; +} + +// get_name(self) -> string +int LuaItemStack::l_get_name(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + LuaItemStack *o = checkobject(L, 1); + ItemStack &item = o->m_stack; + lua_pushstring(L, item.name.c_str()); + return 1; +} + +// get_count(self) -> number +int LuaItemStack::l_get_count(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + LuaItemStack *o = checkobject(L, 1); + ItemStack &item = o->m_stack; + lua_pushinteger(L, item.count); + return 1; +} + +// get_wear(self) -> number +int LuaItemStack::l_get_wear(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + LuaItemStack *o = checkobject(L, 1); + ItemStack &item = o->m_stack; + lua_pushinteger(L, item.wear); + return 1; +} + +// get_metadata(self) -> string +int LuaItemStack::l_get_metadata(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + LuaItemStack *o = checkobject(L, 1); + ItemStack &item = o->m_stack; + lua_pushlstring(L, item.metadata.c_str(), item.metadata.size()); + return 1; +} + +// clear(self) -> true +int LuaItemStack::l_clear(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + LuaItemStack *o = checkobject(L, 1); + o->m_stack.clear(); + lua_pushboolean(L, true); + return 1; +} + +// replace(self, itemstack or itemstring or table or nil) -> true +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)); + lua_pushboolean(L, true); + return 1; +} + +// to_string(self) -> string +int LuaItemStack::l_to_string(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + LuaItemStack *o = checkobject(L, 1); + std::string itemstring = o->m_stack.getItemString(); + lua_pushstring(L, itemstring.c_str()); + return 1; +} + +// to_table(self) -> table or nil +int LuaItemStack::l_to_table(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + LuaItemStack *o = checkobject(L, 1); + const ItemStack &item = o->m_stack; + if(item.empty()) + { + lua_pushnil(L); + } + else + { + lua_newtable(L); + lua_pushstring(L, item.name.c_str()); + lua_setfield(L, -2, "name"); + lua_pushinteger(L, item.count); + lua_setfield(L, -2, "count"); + lua_pushinteger(L, item.wear); + lua_setfield(L, -2, "wear"); + lua_pushlstring(L, item.metadata.c_str(), item.metadata.size()); + lua_setfield(L, -2, "metadata"); + } + return 1; +} + +// get_stack_max(self) -> number +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())); + return 1; +} + +// get_free_space(self) -> number +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())); + return 1; +} + +// is_known(self) -> true/false +// Checks if the item is defined. +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()); + lua_pushboolean(L, is_known); + return 1; +} + +// get_definition(self) -> table +// Returns the item definition table from minetest.registered_items, +// or a fallback one (name="unknown") +int LuaItemStack::l_get_definition(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + LuaItemStack *o = checkobject(L, 1); + ItemStack &item = o->m_stack; + + // Get minetest.registered_items[name] + lua_getglobal(L, "minetest"); + lua_getfield(L, -1, "registered_items"); + luaL_checktype(L, -1, LUA_TTABLE); + lua_getfield(L, -1, item.name.c_str()); + if(lua_isnil(L, -1)) + { + lua_pop(L, 1); + lua_getfield(L, -1, "unknown"); + } + return 1; +} + +// get_tool_capabilities(self) -> table +// Returns the effective tool digging properties. +// Returns those of the hand ("") if this item has none associated. +int LuaItemStack::l_get_tool_capabilities(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + LuaItemStack *o = checkobject(L, 1); + ItemStack &item = o->m_stack; + const ToolCapabilities &prop = + item.getToolCapabilities(STACK_TO_SERVER(L)->idef()); + push_tool_capabilities(L, prop); + return 1; +} + +// add_wear(self, amount) -> true/false +// The range for "amount" is [0,65535]. Wear is only added if the item +// is a tool. Adding wear might destroy the item. +// Returns true if the item is (or was) a tool. +int LuaItemStack::l_add_wear(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + 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()); + lua_pushboolean(L, result); + return 1; +} + +// add_item(self, itemstack or itemstring or table or nil) -> itemstack +// Returns leftover item stack +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,-2, STACK_TO_SERVER(L)); + ItemStack leftover = item.addItem(newitem, STACK_TO_SERVER(L)->idef()); + create(L, leftover); + return 1; +} + +// item_fits(self, itemstack or itemstring or table or nil) -> true/false, itemstack +// First return value is true iff the new item fits fully into the stack +// Second return value is the would-be-left-over item stack +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 restitem; + bool fits = item.itemFits(newitem, &restitem, STACK_TO_SERVER(L)->idef()); + lua_pushboolean(L, fits); // first return value + create(L, restitem); // second return value + return 2; +} + +// take_item(self, takecount=1) -> itemstack +int LuaItemStack::l_take_item(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + LuaItemStack *o = checkobject(L, 1); + ItemStack &item = o->m_stack; + u32 takecount = 1; + if(!lua_isnone(L, 2)) + takecount = luaL_checkinteger(L, 2); + ItemStack taken = item.takeItem(takecount); + create(L, taken); + return 1; +} + +// peek_item(self, peekcount=1) -> itemstack +int LuaItemStack::l_peek_item(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + LuaItemStack *o = checkobject(L, 1); + ItemStack &item = o->m_stack; + u32 peekcount = 1; + if(!lua_isnone(L, 2)) + peekcount = lua_tointeger(L, 2); + ItemStack peekaboo = item.peekItem(peekcount); + create(L, peekaboo); + return 1; +} + +LuaItemStack::LuaItemStack(const ItemStack &item): + m_stack(item) +{ +} + +LuaItemStack::~LuaItemStack() +{ +} + +const ItemStack& LuaItemStack::getItem() const +{ + return m_stack; +} +ItemStack& LuaItemStack::getItem() +{ + return m_stack; +} + +// LuaItemStack(itemstack or itemstring or table or nil) +// Creates an LuaItemStack and leaves it on top of stack +int LuaItemStack::create_object(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ItemStack item = read_item(L,1,STACK_TO_SERVER(L)); + LuaItemStack *o = new LuaItemStack(item); + *(void **)(lua_newuserdata(L, sizeof(void *))) = o; + luaL_getmetatable(L, className); + lua_setmetatable(L, -2); + return 1; +} +// Not callable from Lua +int LuaItemStack::create(lua_State *L, const ItemStack &item) +{ + NO_MAP_LOCK_REQUIRED; + LuaItemStack *o = new LuaItemStack(item); + *(void **)(lua_newuserdata(L, sizeof(void *))) = o; + luaL_getmetatable(L, className); + lua_setmetatable(L, -2); + return 1; +} + +LuaItemStack* LuaItemStack::checkobject(lua_State *L, int narg) +{ + luaL_checktype(L, narg, LUA_TUSERDATA); + void *ud = luaL_checkudata(L, narg, className); + if(!ud) luaL_typerror(L, narg, className); + return *(LuaItemStack**)ud; // unbox pointer +} + +void LuaItemStack::Register(lua_State *L) +{ + lua_newtable(L); + int methodtable = lua_gettop(L); + luaL_newmetatable(L, className); + int metatable = lua_gettop(L); + + lua_pushliteral(L, "__metatable"); + lua_pushvalue(L, methodtable); + lua_settable(L, metatable); // hide metatable from Lua getmetatable() + + lua_pushliteral(L, "__index"); + lua_pushvalue(L, methodtable); + lua_settable(L, metatable); + + lua_pushliteral(L, "__gc"); + lua_pushcfunction(L, gc_object); + lua_settable(L, metatable); + + lua_pop(L, 1); // drop metatable + + luaL_openlib(L, 0, methods, 0); // fill methodtable + lua_pop(L, 1); // drop methodtable + + // Can be created from Lua (LuaItemStack(itemstack or itemstring or table or nil)) + lua_register(L, className, create_object); +} + +const char LuaItemStack::className[] = "ItemStack"; +const luaL_reg LuaItemStack::methods[] = { + luamethod(LuaItemStack, is_empty), + luamethod(LuaItemStack, get_name), + luamethod(LuaItemStack, get_count), + luamethod(LuaItemStack, get_wear), + luamethod(LuaItemStack, get_metadata), + luamethod(LuaItemStack, clear), + luamethod(LuaItemStack, replace), + luamethod(LuaItemStack, to_string), + luamethod(LuaItemStack, to_table), + luamethod(LuaItemStack, get_stack_max), + luamethod(LuaItemStack, get_free_space), + luamethod(LuaItemStack, is_known), + luamethod(LuaItemStack, get_definition), + luamethod(LuaItemStack, get_tool_capabilities), + luamethod(LuaItemStack, add_wear), + luamethod(LuaItemStack, add_item), + luamethod(LuaItemStack, item_fits), + luamethod(LuaItemStack, take_item), + luamethod(LuaItemStack, peek_item), + {0,0} +}; + +ModApiItemMod::ModApiItemMod() { +} + +/* + ItemDefinition +*/ + +// register_item_raw({lots of stuff}) +int ModApiItemMod::l_register_item_raw(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + 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(); + IWritableNodeDefManager *ndef = + scriptIface->getServer()->getWritableNodeDefManager(); + + // Check if name is defined + std::string name; + lua_getfield(L, table, "name"); + if(lua_isstring(L, -1)){ + name = lua_tostring(L, -1); + verbosestream<<"register_item_raw: "<registerItem(def); + + // Read the node definition (content features) and register it + if(def.type == ITEM_NODE) + { + ContentFeatures f = read_content_features(L, table); + ndef->set(f.name, f); + } + + return 0; /* number of results */ +} + +// register_alias_raw(name, convert_to_name) +int ModApiItemMod::l_register_alias_raw(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + std::string name = luaL_checkstring(L, 1); + std::string convert_to = luaL_checkstring(L, 2); + + // Get the writable item definition manager from the server + IWritableItemDefManager *idef = + STACK_TO_SERVER(L)->getWritableItemDefManager(); + + idef->registerAlias(name, convert_to); + + return 0; /* 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); + + LuaItemStack::Register(L); + + return retval; +} + +ModApiItemMod modapi_item_prototyp; diff --git a/src/script/lua_api/l_item.h b/src/script/lua_api/l_item.h new file mode 100644 index 000000000..cbed4ae0b --- /dev/null +++ b/src/script/lua_api/l_item.h @@ -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. +*/ + +#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" + +class ModApiInventory; + +class LuaItemStack +{ +private: + ItemStack m_stack; + + static const char className[]; + static const luaL_reg methods[]; + + // Exported functions + + // garbage collector + static int gc_object(lua_State *L); + + // is_empty(self) -> true/false + static int l_is_empty(lua_State *L); + + // get_name(self) -> string + static int l_get_name(lua_State *L); + + // get_count(self) -> number + static int l_get_count(lua_State *L); + + // get_wear(self) -> number + static int l_get_wear(lua_State *L); + + // get_metadata(self) -> string + static int l_get_metadata(lua_State *L); + + // clear(self) -> true + static int l_clear(lua_State *L); + + // replace(self, itemstack or itemstring or table or nil) -> true + static int l_replace(lua_State *L); + + // to_string(self) -> string + static int l_to_string(lua_State *L); + + // to_table(self) -> table or nil + static int l_to_table(lua_State *L); + + // get_stack_max(self) -> number + static int l_get_stack_max(lua_State *L); + + // get_free_space(self) -> number + static int l_get_free_space(lua_State *L); + + // is_known(self) -> true/false + // Checks if the item is defined. + static int l_is_known(lua_State *L); + + // get_definition(self) -> table + // Returns the item definition table from minetest.registered_items, + // or a fallback one (name="unknown") + static int l_get_definition(lua_State *L); + + // get_tool_capabilities(self) -> table + // Returns the effective tool digging properties. + // Returns those of the hand ("") if this item has none associated. + static int l_get_tool_capabilities(lua_State *L); + + // add_wear(self, amount) -> true/false + // The range for "amount" is [0,65535]. Wear is only added if the item + // is a tool. Adding wear might destroy the item. + // Returns true if the item is (or was) a tool. + static int l_add_wear(lua_State *L); + + // add_item(self, itemstack or itemstring or table or nil) -> itemstack + // Returns leftover item stack + static int l_add_item(lua_State *L); + + // item_fits(self, itemstack or itemstring or table or nil) -> true/false, itemstack + // First return value is true iff the new item fits fully into the stack + // Second return value is the would-be-left-over item stack + static int l_item_fits(lua_State *L); + + // take_item(self, takecount=1) -> itemstack + static int l_take_item(lua_State *L); + + // peek_item(self, peekcount=1) -> itemstack + static int l_peek_item(lua_State *L); + +public: + LuaItemStack(const ItemStack &item); + ~LuaItemStack(); + + const ItemStack& getItem() const; + ItemStack& getItem(); + + // LuaItemStack(itemstack or itemstring or table or nil) + // Creates an LuaItemStack and leaves it on top of stack + static int create_object(lua_State *L); + // Not callable from Lua + static int create(lua_State *L, const ItemStack &item); + static LuaItemStack* checkobject(lua_State *L, int narg); + static void Register(lua_State *L); + +}; + +class ModApiItemMod + :virtual public ModApiBase +{ +public: + ModApiItemMod(); + + bool Initialize(lua_State *L,int top); + + static int l_register_item_raw(lua_State *L); + static int l_register_alias_raw(lua_State *L); +}; + + + +#endif /* L_ITEM_H_ */ diff --git a/src/script/lua_api/l_nodemeta.cpp b/src/script/lua_api/l_nodemeta.cpp new file mode 100644 index 000000000..511fb38ce --- /dev/null +++ b/src/script/lua_api/l_nodemeta.cpp @@ -0,0 +1,332 @@ +/* +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/scriptapi.h" +#include "common/c_converter.h" +#include "common/c_content.h" +#include "map.h" +#include "lua_api/l_nodemeta.h" +#include "common/c_internal.h" +#include "lua_api/l_inventory.h" + + +/* + NodeMetaRef +*/ +NodeMetaRef* NodeMetaRef::checkobject(lua_State *L, int narg) +{ + luaL_checktype(L, narg, LUA_TUSERDATA); + void *ud = luaL_checkudata(L, narg, className); + if(!ud) luaL_typerror(L, narg, className); + return *(NodeMetaRef**)ud; // unbox pointer +} + +NodeMetadata* NodeMetaRef::getmeta(NodeMetaRef *ref, bool auto_create) +{ + NodeMetadata *meta = ref->m_env->getMap().getNodeMetadata(ref->m_p); + if(meta == NULL && auto_create) + { + meta = new NodeMetadata(ref->m_env->getGameDef()); + ref->m_env->getMap().setNodeMetadata(ref->m_p, meta); + } + return meta; +} + +void NodeMetaRef::reportMetadataChange(NodeMetaRef *ref) +{ + // NOTE: This same code is in rollback_interface.cpp + // Inform other things that the metadata has changed + v3s16 blockpos = getNodeBlockPos(ref->m_p); + MapEditEvent event; + event.type = MEET_BLOCK_NODE_METADATA_CHANGED; + event.p = blockpos; + ref->m_env->getMap().dispatchEvent(&event); + // Set the block to be saved + MapBlock *block = ref->m_env->getMap().getBlockNoCreateNoEx(blockpos); + if(block) + block->raiseModified(MOD_STATE_WRITE_NEEDED, + "NodeMetaRef::reportMetadataChange"); +} + +// Exported functions + +// garbage collector +int NodeMetaRef::gc_object(lua_State *L) { + NodeMetaRef *o = *(NodeMetaRef **)(lua_touserdata(L, 1)); + delete o; + return 0; +} + +// get_string(self, name) +int NodeMetaRef::l_get_string(lua_State *L) +{ + NodeMetaRef *ref = checkobject(L, 1); + std::string name = luaL_checkstring(L, 2); + + NodeMetadata *meta = getmeta(ref, false); + if(meta == NULL){ + lua_pushlstring(L, "", 0); + return 1; + } + std::string str = meta->getString(name); + lua_pushlstring(L, str.c_str(), str.size()); + return 1; +} + +// set_string(self, name, var) +int NodeMetaRef::l_set_string(lua_State *L) +{ + NodeMetaRef *ref = checkobject(L, 1); + std::string name = luaL_checkstring(L, 2); + size_t len = 0; + const char *s = lua_tolstring(L, 3, &len); + std::string str(s, len); + + NodeMetadata *meta = getmeta(ref, !str.empty()); + if(meta == NULL || str == meta->getString(name)) + return 0; + meta->setString(name, str); + reportMetadataChange(ref); + return 0; +} + +// get_int(self, name) +int NodeMetaRef::l_get_int(lua_State *L) +{ + NodeMetaRef *ref = checkobject(L, 1); + std::string name = lua_tostring(L, 2); + + NodeMetadata *meta = getmeta(ref, false); + if(meta == NULL){ + lua_pushnumber(L, 0); + return 1; + } + std::string str = meta->getString(name); + lua_pushnumber(L, stoi(str)); + return 1; +} + +// set_int(self, name, var) +int NodeMetaRef::l_set_int(lua_State *L) +{ + NodeMetaRef *ref = checkobject(L, 1); + std::string name = lua_tostring(L, 2); + int a = lua_tointeger(L, 3); + std::string str = itos(a); + + NodeMetadata *meta = getmeta(ref, true); + if(meta == NULL || str == meta->getString(name)) + return 0; + meta->setString(name, str); + reportMetadataChange(ref); + return 0; +} + +// get_float(self, name) +int NodeMetaRef::l_get_float(lua_State *L) +{ + NodeMetaRef *ref = checkobject(L, 1); + std::string name = lua_tostring(L, 2); + + NodeMetadata *meta = getmeta(ref, false); + if(meta == NULL){ + lua_pushnumber(L, 0); + return 1; + } + std::string str = meta->getString(name); + lua_pushnumber(L, stof(str)); + return 1; +} + +// set_float(self, name, var) +int NodeMetaRef::l_set_float(lua_State *L) +{ + NodeMetaRef *ref = checkobject(L, 1); + std::string name = lua_tostring(L, 2); + float a = lua_tonumber(L, 3); + std::string str = ftos(a); + + NodeMetadata *meta = getmeta(ref, true); + if(meta == NULL || str == meta->getString(name)) + return 0; + meta->setString(name, str); + reportMetadataChange(ref); + return 0; +} + +// get_inventory(self) +int NodeMetaRef::l_get_inventory(lua_State *L) +{ + NodeMetaRef *ref = checkobject(L, 1); + getmeta(ref, true); // try to ensure the metadata exists + InvRef::createNodeMeta(L, ref->m_p); + return 1; +} + +// to_table(self) +int NodeMetaRef::l_to_table(lua_State *L) +{ + NodeMetaRef *ref = checkobject(L, 1); + + NodeMetadata *meta = getmeta(ref, true); + if(meta == NULL){ + lua_pushnil(L); + return 1; + } + lua_newtable(L); + // fields + lua_newtable(L); + { + std::map fields = meta->getStrings(); + 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_pushlstring(L, name.c_str(), name.size()); + lua_pushlstring(L, value.c_str(), value.size()); + lua_settable(L, -3); + } + } + lua_setfield(L, -2, "fields"); + // inventory + lua_newtable(L); + Inventory *inv = meta->getInventory(); + if(inv){ + 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); + lua_setfield(L, -2, (*i)->getName().c_str()); + } + } + lua_setfield(L, -2, "inventory"); + return 1; +} + +// from_table(self, table) +int NodeMetaRef::l_from_table(lua_State *L) +{ + NodeMetaRef *ref = checkobject(L, 1); + int base = 2; + + if(lua_isnil(L, base)){ + // No metadata + ref->m_env->getMap().removeNodeMetadata(ref->m_p); + lua_pushboolean(L, true); + return 1; + } + + // Has metadata; clear old one first + ref->m_env->getMap().removeNodeMetadata(ref->m_p); + // Create new metadata + NodeMetadata *meta = getmeta(ref, true); + // Set fields + lua_getfield(L, base, "fields"); + int fieldstable = lua_gettop(L); + lua_pushnil(L); + while(lua_next(L, fieldstable) != 0){ + // key at index -2 and value at index -1 + std::string name = lua_tostring(L, -2); + size_t cl; + const char *cs = lua_tolstring(L, -1, &cl); + std::string value(cs, cl); + meta->setString(name, value); + lua_pop(L, 1); // removes value, keeps key for next iteration + } + // Set inventory + Inventory *inv = meta->getInventory(); + lua_getfield(L, base, "inventory"); + int inventorytable = lua_gettop(L); + lua_pushnil(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)); + lua_pop(L, 1); // removes value, keeps key for next iteration + } + reportMetadataChange(ref); + lua_pushboolean(L, true); + return 1; +} + + +NodeMetaRef::NodeMetaRef(v3s16 p, ServerEnvironment *env): + m_p(p), + m_env(env) +{ +} + +NodeMetaRef::~NodeMetaRef() +{ +} + +// Creates an NodeMetaRef and leaves it on top of stack +// Not callable from Lua; all references are created on the C side. +void NodeMetaRef::create(lua_State *L, v3s16 p, ServerEnvironment *env) +{ + NodeMetaRef *o = new NodeMetaRef(p, env); + //infostream<<"NodeMetaRef::create: o="< + +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_NODEMETA_H_ +#define L_NODEMETA_H_ + +extern "C" { +#include +#include +} + +#include "environment.h" +#include "nodemetadata.h" + +/* + NodeMetaRef +*/ + +class NodeMetaRef +{ +private: + v3s16 m_p; + ServerEnvironment *m_env; + + static const char className[]; + static const luaL_reg methods[]; + + static NodeMetaRef *checkobject(lua_State *L, int narg); + + static NodeMetadata* getmeta(NodeMetaRef *ref, bool auto_create); + + static void reportMetadataChange(NodeMetaRef *ref); + + // Exported functions + + // garbage collector + static int gc_object(lua_State *L); + + // get_string(self, name) + static int l_get_string(lua_State *L); + + // set_string(self, name, var) + static int l_set_string(lua_State *L); + + // get_int(self, name) + static int l_get_int(lua_State *L); + + // set_int(self, name, var) + static int l_set_int(lua_State *L); + + // get_float(self, name) + static int l_get_float(lua_State *L); + + // set_float(self, name, var) + static int l_set_float(lua_State *L); + + // get_inventory(self) + static int l_get_inventory(lua_State *L); + + // to_table(self) + static int l_to_table(lua_State *L); + + // from_table(self, table) + static int l_from_table(lua_State *L); + +public: + NodeMetaRef(v3s16 p, ServerEnvironment *env); + + ~NodeMetaRef(); + + // Creates an NodeMetaRef and leaves it on top of stack + // Not callable from Lua; all references are created on the C side. + static void create(lua_State *L, v3s16 p, ServerEnvironment *env); + + static void Register(lua_State *L); +}; + +#endif //L_NODEMETA_H_ diff --git a/src/script/lua_api/l_nodetimer.cpp b/src/script/lua_api/l_nodetimer.cpp new file mode 100644 index 000000000..60e4ec061 --- /dev/null +++ b/src/script/lua_api/l_nodetimer.cpp @@ -0,0 +1,169 @@ +/* +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/scriptapi.h" +#include "lua_api/l_nodetimer.h" +#include "common/c_internal.h" +#include "map.h" + + +int NodeTimerRef::gc_object(lua_State *L) { + NodeTimerRef *o = *(NodeTimerRef **)(lua_touserdata(L, 1)); + delete o; + return 0; +} + +NodeTimerRef* NodeTimerRef::checkobject(lua_State *L, int narg) +{ + luaL_checktype(L, narg, LUA_TUSERDATA); + void *ud = luaL_checkudata(L, narg, className); + if(!ud) luaL_typerror(L, narg, className); + return *(NodeTimerRef**)ud; // unbox pointer +} + +int NodeTimerRef::l_set(lua_State *L) +{ + NodeTimerRef *o = checkobject(L, 1); + ServerEnvironment *env = o->m_env; + if(env == NULL) return 0; + f32 t = luaL_checknumber(L,2); + f32 e = luaL_checknumber(L,3); + env->getMap().setNodeTimer(o->m_p,NodeTimer(t,e)); + return 0; +} + +int NodeTimerRef::l_start(lua_State *L) +{ + NodeTimerRef *o = checkobject(L, 1); + ServerEnvironment *env = o->m_env; + if(env == NULL) return 0; + f32 t = luaL_checknumber(L,2); + env->getMap().setNodeTimer(o->m_p,NodeTimer(t,0)); + return 0; +} + +int NodeTimerRef::l_stop(lua_State *L) +{ + NodeTimerRef *o = checkobject(L, 1); + ServerEnvironment *env = o->m_env; + if(env == NULL) return 0; + env->getMap().removeNodeTimer(o->m_p); + return 0; +} + +int NodeTimerRef::l_is_started(lua_State *L) +{ + NodeTimerRef *o = checkobject(L, 1); + ServerEnvironment *env = o->m_env; + if(env == NULL) return 0; + + NodeTimer t = env->getMap().getNodeTimer(o->m_p); + lua_pushboolean(L,(t.timeout != 0)); + return 1; +} + +int NodeTimerRef::l_get_timeout(lua_State *L) +{ + NodeTimerRef *o = checkobject(L, 1); + ServerEnvironment *env = o->m_env; + if(env == NULL) return 0; + + NodeTimer t = env->getMap().getNodeTimer(o->m_p); + lua_pushnumber(L,t.timeout); + return 1; +} + +int NodeTimerRef::l_get_elapsed(lua_State *L) +{ + NodeTimerRef *o = checkobject(L, 1); + ServerEnvironment *env = o->m_env; + if(env == NULL) return 0; + + NodeTimer t = env->getMap().getNodeTimer(o->m_p); + lua_pushnumber(L,t.elapsed); + return 1; +} + + +NodeTimerRef::NodeTimerRef(v3s16 p, ServerEnvironment *env): + m_p(p), + m_env(env) +{ +} + +NodeTimerRef::~NodeTimerRef() +{ +} + +// Creates an NodeTimerRef and leaves it on top of stack +// Not callable from Lua; all references are created on the C side. +void NodeTimerRef::create(lua_State *L, v3s16 p, ServerEnvironment *env) +{ + NodeTimerRef *o = new NodeTimerRef(p, env); + *(void **)(lua_newuserdata(L, sizeof(void *))) = o; + luaL_getmetatable(L, className); + lua_setmetatable(L, -2); +} + +void NodeTimerRef::set_null(lua_State *L) +{ + NodeTimerRef *o = checkobject(L, -1); + o->m_env = NULL; +} + +void NodeTimerRef::Register(lua_State *L) +{ + lua_newtable(L); + int methodtable = lua_gettop(L); + luaL_newmetatable(L, className); + int metatable = lua_gettop(L); + + lua_pushliteral(L, "__metatable"); + lua_pushvalue(L, methodtable); + lua_settable(L, metatable); // hide metatable from Lua getmetatable() + + lua_pushliteral(L, "__index"); + lua_pushvalue(L, methodtable); + lua_settable(L, metatable); + + lua_pushliteral(L, "__gc"); + lua_pushcfunction(L, gc_object); + lua_settable(L, metatable); + + lua_pop(L, 1); // drop metatable + + luaL_openlib(L, 0, methods, 0); // fill methodtable + lua_pop(L, 1); // drop methodtable + + // Cannot be created from Lua + //lua_register(L, className, create_object); +} + +const char NodeTimerRef::className[] = "NodeTimerRef"; +const luaL_reg NodeTimerRef::methods[] = { + luamethod(NodeTimerRef, start), + luamethod(NodeTimerRef, set), + luamethod(NodeTimerRef, stop), + luamethod(NodeTimerRef, is_started), + luamethod(NodeTimerRef, get_timeout), + 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 new file mode 100644 index 000000000..f652b4900 --- /dev/null +++ b/src/script/lua_api/l_nodetimer.h @@ -0,0 +1,70 @@ +/* +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_NODETIMER_H_ +#define L_NODETIMER_H_ + +extern "C" { +#include +#include +} + +#include "environment.h" + +class NodeTimerRef +{ +private: + v3s16 m_p; + ServerEnvironment *m_env; + + static const char className[]; + static const luaL_reg methods[]; + + static int gc_object(lua_State *L); + + static NodeTimerRef *checkobject(lua_State *L, int narg); + + static int l_set(lua_State *L); + + static int l_start(lua_State *L); + + static int l_stop(lua_State *L); + + static int l_is_started(lua_State *L); + + static int l_get_timeout(lua_State *L); + + static int l_get_elapsed(lua_State *L); + +public: + NodeTimerRef(v3s16 p, ServerEnvironment *env); + ~NodeTimerRef(); + + // Creates an NodeTimerRef and leaves it on top of stack + // Not callable from Lua; all references are created on the C side. + static void create(lua_State *L, v3s16 p, ServerEnvironment *env); + + static void set_null(lua_State *L); + + static void Register(lua_State *L); +}; + + + +#endif /* L_NODETIMER_H_ */ diff --git a/src/script/lua_api/l_noise.cpp b/src/script/lua_api/l_noise.cpp new file mode 100644 index 000000000..e0abeae94 --- /dev/null +++ b/src/script/lua_api/l_noise.cpp @@ -0,0 +1,373 @@ +/* +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_noise.h" +#include "common/c_internal.h" +#include "common/c_converter.h" +#include "log.h" + +// garbage collector +int LuaPerlinNoise::gc_object(lua_State *L) +{ + LuaPerlinNoise *o = *(LuaPerlinNoise **)(lua_touserdata(L, 1)); + delete o; + return 0; +} + +int LuaPerlinNoise::l_get2d(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + LuaPerlinNoise *o = checkobject(L, 1); + v2f pos2d = read_v2f(L,2); + lua_Number val = noise2d_perlin(pos2d.X/o->scale, pos2d.Y/o->scale, o->seed, o->octaves, o->persistence); + lua_pushnumber(L, val); + return 1; +} +int LuaPerlinNoise::l_get3d(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + LuaPerlinNoise *o = checkobject(L, 1); + v3f pos3d = read_v3f(L,2); + lua_Number val = noise3d_perlin(pos3d.X/o->scale, pos3d.Y/o->scale, pos3d.Z/o->scale, o->seed, o->octaves, o->persistence); + lua_pushnumber(L, val); + return 1; +} + + +LuaPerlinNoise::LuaPerlinNoise(int a_seed, int a_octaves, float a_persistence, + float a_scale): + seed(a_seed), + octaves(a_octaves), + persistence(a_persistence), + scale(a_scale) +{ +} + +LuaPerlinNoise::~LuaPerlinNoise() +{ +} + +// LuaPerlinNoise(seed, octaves, persistence, scale) +// Creates an LuaPerlinNoise and leaves it on top of stack +int LuaPerlinNoise::create_object(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + int seed = luaL_checkint(L, 1); + int octaves = luaL_checkint(L, 2); + float persistence = luaL_checknumber(L, 3); + float scale = luaL_checknumber(L, 4); + LuaPerlinNoise *o = new LuaPerlinNoise(seed, octaves, persistence, scale); + *(void **)(lua_newuserdata(L, sizeof(void *))) = o; + luaL_getmetatable(L, className); + lua_setmetatable(L, -2); + return 1; +} + +LuaPerlinNoise* LuaPerlinNoise::checkobject(lua_State *L, int narg) +{ + NO_MAP_LOCK_REQUIRED; + luaL_checktype(L, narg, LUA_TUSERDATA); + void *ud = luaL_checkudata(L, narg, className); + if(!ud) luaL_typerror(L, narg, className); + return *(LuaPerlinNoise**)ud; // unbox pointer +} + +void LuaPerlinNoise::Register(lua_State *L) +{ + lua_newtable(L); + int methodtable = lua_gettop(L); + luaL_newmetatable(L, className); + int metatable = lua_gettop(L); + + lua_pushliteral(L, "__metatable"); + lua_pushvalue(L, methodtable); + lua_settable(L, metatable); // hide metatable from Lua getmetatable() + + lua_pushliteral(L, "__index"); + lua_pushvalue(L, methodtable); + lua_settable(L, metatable); + + lua_pushliteral(L, "__gc"); + lua_pushcfunction(L, gc_object); + lua_settable(L, metatable); + + lua_pop(L, 1); // drop metatable + + luaL_openlib(L, 0, methods, 0); // fill methodtable + lua_pop(L, 1); // drop methodtable + + // Can be created from Lua (PerlinNoise(seed, octaves, persistence) + lua_register(L, className, create_object); +} + +const char LuaPerlinNoise::className[] = "PerlinNoise"; +const luaL_reg LuaPerlinNoise::methods[] = { + luamethod(LuaPerlinNoise, get2d), + luamethod(LuaPerlinNoise, get3d), + {0,0} +}; + +/* + PerlinNoiseMap + */ + + +int LuaPerlinNoiseMap::gc_object(lua_State *L) +{ + LuaPerlinNoiseMap *o = *(LuaPerlinNoiseMap **)(lua_touserdata(L, 1)); + delete o; + return 0; +} + +int LuaPerlinNoiseMap::l_get2dMap(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + int i = 0; + + LuaPerlinNoiseMap *o = checkobject(L, 1); + v2f p = read_v2f(L, 2); + + Noise *n = o->noise; + n->perlinMap2D(p.X, p.Y); + + lua_newtable(L); + for (int y = 0; y != n->sy; y++) { + lua_newtable(L); + for (int x = 0; x != n->sx; x++) { + float noiseval = n->np->offset + n->np->scale * n->result[i++]; + lua_pushnumber(L, noiseval); + lua_rawseti(L, -2, x + 1); + } + lua_rawseti(L, -2, y + 1); + } + return 1; +} + +int LuaPerlinNoiseMap::l_get3dMap(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + int i = 0; + + LuaPerlinNoiseMap *o = checkobject(L, 1); + v3f p = read_v3f(L, 2); + + Noise *n = o->noise; + n->perlinMap3D(p.X, p.Y, p.Z); + + lua_newtable(L); + for (int z = 0; z != n->sz; z++) { + lua_newtable(L); + for (int y = 0; y != n->sy; y++) { + lua_newtable(L); + for (int x = 0; x != n->sx; x++) { + lua_pushnumber(L, n->np->offset + n->np->scale * n->result[i++]); + lua_rawseti(L, -2, x + 1); + } + lua_rawseti(L, -2, y + 1); + } + lua_rawseti(L, -2, z + 1); + } + return 1; +} + +LuaPerlinNoiseMap::LuaPerlinNoiseMap(NoiseParams *np, int seed, v3s16 size) { + noise = new Noise(np, seed, size.X, size.Y, size.Z); +} + +LuaPerlinNoiseMap::~LuaPerlinNoiseMap() +{ + delete noise->np; + delete noise; +} + +// LuaPerlinNoiseMap(np, size) +// Creates an LuaPerlinNoiseMap and leaves it on top of stack +int LuaPerlinNoiseMap::create_object(lua_State *L) +{ + NoiseParams *np = read_noiseparams(L, 1); + if (!np) + return 0; + v3s16 size = read_v3s16(L, 2); + + LuaPerlinNoiseMap *o = new LuaPerlinNoiseMap(np, 0, size); + *(void **)(lua_newuserdata(L, sizeof(void *))) = o; + luaL_getmetatable(L, className); + lua_setmetatable(L, -2); + return 1; +} + +LuaPerlinNoiseMap* LuaPerlinNoiseMap::checkobject(lua_State *L, int narg) +{ + luaL_checktype(L, narg, LUA_TUSERDATA); + + void *ud = luaL_checkudata(L, narg, className); + if (!ud) + luaL_typerror(L, narg, className); + + return *(LuaPerlinNoiseMap **)ud; // unbox pointer +} + +void LuaPerlinNoiseMap::Register(lua_State *L) +{ + lua_newtable(L); + int methodtable = lua_gettop(L); + luaL_newmetatable(L, className); + int metatable = lua_gettop(L); + + lua_pushliteral(L, "__metatable"); + lua_pushvalue(L, methodtable); + lua_settable(L, metatable); // hide metatable from Lua getmetatable() + + lua_pushliteral(L, "__index"); + lua_pushvalue(L, methodtable); + lua_settable(L, metatable); + + lua_pushliteral(L, "__gc"); + lua_pushcfunction(L, gc_object); + lua_settable(L, metatable); + + lua_pop(L, 1); // drop metatable + + luaL_openlib(L, 0, methods, 0); // fill methodtable + lua_pop(L, 1); // drop methodtable + + // Can be created from Lua (PerlinNoiseMap(np, size) + lua_register(L, className, create_object); +} + +const char LuaPerlinNoiseMap::className[] = "PerlinNoiseMap"; +const luaL_reg LuaPerlinNoiseMap::methods[] = { + luamethod(LuaPerlinNoiseMap, get2dMap), + luamethod(LuaPerlinNoiseMap, get3dMap), + {0,0} +}; + +/* + LuaPseudoRandom +*/ + +// garbage collector +int LuaPseudoRandom::gc_object(lua_State *L) +{ + LuaPseudoRandom *o = *(LuaPseudoRandom **)(lua_touserdata(L, 1)); + delete o; + return 0; +} + +// next(self, min=0, max=32767) -> get next value +int LuaPseudoRandom::l_next(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + LuaPseudoRandom *o = checkobject(L, 1); + int min = 0; + int max = 32767; + lua_settop(L, 3); // Fill 2 and 3 with nil if they don't exist + if(!lua_isnil(L, 2)) + min = luaL_checkinteger(L, 2); + if(!lua_isnil(L, 3)) + max = luaL_checkinteger(L, 3); + if(max < min){ + errorstream<<"PseudoRandom.next(): max="< 32767/5) + throw LuaError(L, "PseudoRandom.next() max-min is not 32767 and is > 32768/5. This is disallowed due to the bad random distribution the implementation would otherwise make."); + PseudoRandom &pseudo = o->m_pseudo; + int val = pseudo.next(); + val = (val % (max-min+1)) + min; + lua_pushinteger(L, val); + return 1; +} + + +LuaPseudoRandom::LuaPseudoRandom(int seed): + m_pseudo(seed) +{ +} + +LuaPseudoRandom::~LuaPseudoRandom() +{ +} + +const PseudoRandom& LuaPseudoRandom::getItem() const +{ + return m_pseudo; +} +PseudoRandom& LuaPseudoRandom::getItem() +{ + return m_pseudo; +} + +// LuaPseudoRandom(seed) +// Creates an LuaPseudoRandom and leaves it on top of stack +int LuaPseudoRandom::create_object(lua_State *L) +{ + int seed = luaL_checknumber(L, 1); + LuaPseudoRandom *o = new LuaPseudoRandom(seed); + *(void **)(lua_newuserdata(L, sizeof(void *))) = o; + luaL_getmetatable(L, className); + lua_setmetatable(L, -2); + return 1; +} + +LuaPseudoRandom* LuaPseudoRandom::checkobject(lua_State *L, int narg) +{ + luaL_checktype(L, narg, LUA_TUSERDATA); + void *ud = luaL_checkudata(L, narg, className); + if(!ud) luaL_typerror(L, narg, className); + return *(LuaPseudoRandom**)ud; // unbox pointer +} + +void LuaPseudoRandom::Register(lua_State *L) +{ + lua_newtable(L); + int methodtable = lua_gettop(L); + luaL_newmetatable(L, className); + int metatable = lua_gettop(L); + + lua_pushliteral(L, "__metatable"); + lua_pushvalue(L, methodtable); + lua_settable(L, metatable); // hide metatable from Lua getmetatable() + + lua_pushliteral(L, "__index"); + lua_pushvalue(L, methodtable); + lua_settable(L, metatable); + + lua_pushliteral(L, "__gc"); + lua_pushcfunction(L, gc_object); + lua_settable(L, metatable); + + lua_pop(L, 1); // drop metatable + + luaL_openlib(L, 0, methods, 0); // fill methodtable + lua_pop(L, 1); // drop methodtable + + // Can be created from Lua (LuaPseudoRandom(seed)) + lua_register(L, className, create_object); +} + +const char LuaPseudoRandom::className[] = "PseudoRandom"; +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 new file mode 100644 index 000000000..d0b51d756 --- /dev/null +++ b/src/script/lua_api/l_noise.h @@ -0,0 +1,134 @@ +/* +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_NOISE_H_ +#define L_NOISE_H_ + +extern "C" { +#include +#include +} + +#include "irr_v3d.h" +#include "noise.h" + +class LuaPerlinNoise +{ +private: + int seed; + int octaves; + float persistence; + float scale; + static const char className[]; + static const luaL_reg methods[]; + + // Exported functions + + // garbage collector + static int gc_object(lua_State *L); + + static int l_get2d(lua_State *L); + static int l_get3d(lua_State *L); + +public: + LuaPerlinNoise(int a_seed, int a_octaves, float a_persistence, + float a_scale); + + ~LuaPerlinNoise(); + + // LuaPerlinNoise(seed, octaves, persistence, scale) + // Creates an LuaPerlinNoise and leaves it on top of stack + static int create_object(lua_State *L); + + static LuaPerlinNoise* checkobject(lua_State *L, int narg); + + static void Register(lua_State *L); +}; + +/* + PerlinNoiseMap + */ +class LuaPerlinNoiseMap +{ +private: + Noise *noise; + static const char className[]; + static const luaL_reg methods[]; + + static int gc_object(lua_State *L); + + static int l_get2dMap(lua_State *L); + + static int l_get3dMap(lua_State *L); + +public: + LuaPerlinNoiseMap(NoiseParams *np, int seed, v3s16 size); + + ~LuaPerlinNoiseMap(); + + // LuaPerlinNoiseMap(np, size) + // Creates an LuaPerlinNoiseMap and leaves it on top of stack + static int create_object(lua_State *L); + + static LuaPerlinNoiseMap *checkobject(lua_State *L, int narg); + + static void Register(lua_State *L); +}; + +/* + LuaPseudoRandom +*/ + + +class LuaPseudoRandom +{ +private: + PseudoRandom m_pseudo; + + static const char className[]; + static const luaL_reg methods[]; + + // Exported functions + + // garbage collector + static int gc_object(lua_State *L); + + // next(self, min=0, max=32767) -> get next value + static int l_next(lua_State *L); + +public: + LuaPseudoRandom(int seed); + + ~LuaPseudoRandom(); + + const PseudoRandom& getItem() const; + PseudoRandom& getItem(); + + // LuaPseudoRandom(seed) + // Creates an LuaPseudoRandom and leaves it on top of stack + static int create_object(lua_State *L); + + static LuaPseudoRandom* checkobject(lua_State *L, int narg); + + 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 new file mode 100644 index 000000000..6dec3db85 --- /dev/null +++ b/src/script/lua_api/l_object.cpp @@ -0,0 +1,1095 @@ +/* +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/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_inventory.h" +#include "lua_api/l_item.h" +#include "log.h" +#include "tool.h" +#include "serverobject.h" +#include "content_object.h" +#include "content_sao.h" +#include "server.h" +#include "hud.h" + + +struct EnumString es_HudElementType[] = +{ + {HUD_ELEM_IMAGE, "image"}, + {HUD_ELEM_TEXT, "text"}, + {HUD_ELEM_STATBAR, "statbar"}, + {HUD_ELEM_INVENTORY, "inventory"}, +{0, NULL}, +}; + +struct EnumString es_HudElementStat[] = +{ + {HUD_STAT_POS, "pos"}, + {HUD_STAT_NAME, "name"}, + {HUD_STAT_SCALE, "scale"}, + {HUD_STAT_TEXT, "text"}, + {HUD_STAT_NUMBER, "number"}, + {HUD_STAT_ITEM, "item"}, + {HUD_STAT_DIR, "direction"}, + {HUD_STAT_ALIGN, "alignment"}, + {HUD_STAT_OFFSET, "offset"}, + {0, NULL}, +}; + +struct EnumString es_HudBuiltinElement[] = +{ + {HUD_FLAG_HOTBAR_VISIBLE, "hotbar"}, + {HUD_FLAG_HEALTHBAR_VISIBLE, "healthbar"}, + {HUD_FLAG_CROSSHAIR_VISIBLE, "crosshair"}, + {HUD_FLAG_WIELDITEM_VISIBLE, "wielditem"}, + {0, NULL}, +}; + +/* + ObjectRef +*/ + + +ObjectRef* ObjectRef::checkobject(lua_State *L, int narg) +{ + luaL_checktype(L, narg, LUA_TUSERDATA); + void *ud = luaL_checkudata(L, narg, className); + if(!ud) luaL_typerror(L, narg, className); + return *(ObjectRef**)ud; // unbox pointer +} + +ServerActiveObject* ObjectRef::getobject(ObjectRef *ref) +{ + ServerActiveObject *co = ref->m_object; + return co; +} + +LuaEntitySAO* ObjectRef::getluaobject(ObjectRef *ref) +{ + ServerActiveObject *obj = getobject(ref); + if(obj == NULL) + return NULL; + if(obj->getType() != ACTIVEOBJECT_TYPE_LUAENTITY) + return NULL; + return (LuaEntitySAO*)obj; +} + +PlayerSAO* ObjectRef::getplayersao(ObjectRef *ref) +{ + ServerActiveObject *obj = getobject(ref); + if(obj == NULL) + return NULL; + if(obj->getType() != ACTIVEOBJECT_TYPE_PLAYER) + return NULL; + return (PlayerSAO*)obj; +} + +Player* ObjectRef::getplayer(ObjectRef *ref) +{ + PlayerSAO *playersao = getplayersao(ref); + if(playersao == NULL) + return NULL; + return playersao->getPlayer(); +} + +// Exported functions + +// garbage collector +int ObjectRef::gc_object(lua_State *L) { + ObjectRef *o = *(ObjectRef **)(lua_touserdata(L, 1)); + //infostream<<"ObjectRef::gc_object: o="<setPos(pos); + return 0; +} + +// moveto(self, pos, continuous=false) +int ObjectRef::l_moveto(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + //LuaEntitySAO *co = getluaobject(ref); + ServerActiveObject *co = getobject(ref); + if(co == NULL) return 0; + // pos + v3f pos = checkFloatPos(L, 2); + // continuous + bool continuous = lua_toboolean(L, 3); + // Do it + co->moveTo(pos, continuous); + return 0; +} + +// punch(self, puncher, time_from_last_punch, tool_capabilities, dir) +int ObjectRef::l_punch(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + ObjectRef *puncher_ref = checkobject(L, 2); + ServerActiveObject *co = getobject(ref); + ServerActiveObject *puncher = getobject(puncher_ref); + if(co == NULL) return 0; + if(puncher == NULL) return 0; + v3f dir; + if(lua_type(L, 5) != LUA_TTABLE) + dir = co->getBasePosition() - puncher->getBasePosition(); + else + dir = read_v3f(L, 5); + float time_from_last_punch = 1000000; + if(lua_isnumber(L, 3)) + time_from_last_punch = lua_tonumber(L, 3); + ToolCapabilities toolcap = read_tool_capabilities(L, 4); + dir.normalize(); + // Do it + co->punch(dir, &toolcap, puncher, time_from_last_punch); + return 0; +} + +// right_click(self, clicker); clicker = an another ObjectRef +int ObjectRef::l_right_click(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + ObjectRef *ref2 = checkobject(L, 2); + ServerActiveObject *co = getobject(ref); + ServerActiveObject *co2 = getobject(ref2); + if(co == NULL) return 0; + if(co2 == NULL) return 0; + // Do it + co->rightClick(co2); + return 0; +} + +// set_hp(self, hp) +// hp = number of hitpoints (2 * number of hearts) +// returns: nil +int ObjectRef::l_set_hp(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + luaL_checknumber(L, 2); + ServerActiveObject *co = getobject(ref); + if(co == NULL) return 0; + int hp = lua_tonumber(L, 2); + /*infostream<<"ObjectRef::l_set_hp(): id="<getId() + <<" hp="<setHP(hp); + // Return + return 0; +} + +// get_hp(self) +// returns: number of hitpoints (2 * number of hearts) +// 0 if not applicable to this type of object +int ObjectRef::l_get_hp(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + ServerActiveObject *co = getobject(ref); + if(co == NULL){ + // Default hp is 1 + lua_pushnumber(L, 1); + return 1; + } + int hp = co->getHP(); + /*infostream<<"ObjectRef::l_get_hp(): id="<getId() + <<" hp="<getInventoryLocation(); + if(STACK_TO_SERVER(L)->getInventory(loc) != NULL) + InvRef::create(L, loc); + else + lua_pushnil(L); // An object may have no inventory (nil) + return 1; +} + +// get_wield_list(self) +int ObjectRef::l_get_wield_list(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + ServerActiveObject *co = getobject(ref); + if(co == NULL) return 0; + // Do it + lua_pushstring(L, co->getWieldList().c_str()); + return 1; +} + +// get_wield_index(self) +int ObjectRef::l_get_wield_index(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + ServerActiveObject *co = getobject(ref); + if(co == NULL) return 0; + // Do it + lua_pushinteger(L, co->getWieldIndex() + 1); + return 1; +} + +// get_wielded_item(self) +int ObjectRef::l_get_wielded_item(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + ServerActiveObject *co = getobject(ref); + if(co == NULL){ + // Empty ItemStack + LuaItemStack::create(L, ItemStack()); + return 1; + } + // Do it + LuaItemStack::create(L, co->getWieldedItem()); + return 1; +} + +// set_wielded_item(self, itemstack or itemstring or table or nil) +int ObjectRef::l_set_wielded_item(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + ServerActiveObject *co = getobject(ref); + if(co == NULL) return 0; + // Do it + ItemStack item = read_item(L, 2,STACK_TO_SERVER(L)); + bool success = co->setWieldedItem(item); + lua_pushboolean(L, success); + return 1; +} + +// set_armor_groups(self, groups) +int ObjectRef::l_set_armor_groups(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + ServerActiveObject *co = getobject(ref); + if(co == NULL) return 0; + // Do it + ItemGroupList groups; + read_groups(L, 2, groups); + co->setArmorGroups(groups); + return 0; +} + +// set_physics_override(self, physics_override_speed, physics_override_jump, physics_override_gravity) +int ObjectRef::l_set_physics_override(lua_State *L) +{ + ObjectRef *ref = checkobject(L, 1); + PlayerSAO *co = (PlayerSAO *) getobject(ref); + if(co == NULL) return 0; + // Do it + if(!lua_isnil(L, 2)){ + co->m_physics_override_speed = lua_tonumber(L, 2); + co->m_physics_override_sent = false; + } + if(!lua_isnil(L, 3)){ + co->m_physics_override_jump = lua_tonumber(L, 3); + co->m_physics_override_sent = false; + } + if(!lua_isnil(L, 4)){ + co->m_physics_override_gravity = lua_tonumber(L, 4); + co->m_physics_override_sent = false; + } + return 0; +} + +// set_animation(self, frame_range, frame_speed, frame_blend) +int ObjectRef::l_set_animation(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + ServerActiveObject *co = getobject(ref); + if(co == NULL) return 0; + // Do it + v2f frames = v2f(1, 1); + if(!lua_isnil(L, 2)) + frames = read_v2f(L, 2); + float frame_speed = 15; + if(!lua_isnil(L, 3)) + frame_speed = lua_tonumber(L, 3); + float frame_blend = 0; + if(!lua_isnil(L, 4)) + frame_blend = lua_tonumber(L, 4); + co->setAnimation(frames, frame_speed, frame_blend); + return 0; +} + +// set_bone_position(self, std::string bone, v3f position, v3f rotation) +int ObjectRef::l_set_bone_position(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + ServerActiveObject *co = getobject(ref); + if(co == NULL) return 0; + // Do it + std::string bone = ""; + if(!lua_isnil(L, 2)) + bone = lua_tostring(L, 2); + v3f position = v3f(0, 0, 0); + if(!lua_isnil(L, 3)) + position = read_v3f(L, 3); + v3f rotation = v3f(0, 0, 0); + if(!lua_isnil(L, 4)) + rotation = read_v3f(L, 4); + co->setBonePosition(bone, position, rotation); + return 0; +} + +// set_attach(self, parent, bone, position, rotation) +int ObjectRef::l_set_attach(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + ObjectRef *parent_ref = checkobject(L, 2); + ServerActiveObject *co = getobject(ref); + ServerActiveObject *parent = getobject(parent_ref); + if(co == NULL) return 0; + if(parent == NULL) return 0; + // Do it + std::string bone = ""; + if(!lua_isnil(L, 3)) + bone = lua_tostring(L, 3); + v3f position = v3f(0, 0, 0); + if(!lua_isnil(L, 4)) + position = read_v3f(L, 4); + v3f rotation = v3f(0, 0, 0); + if(!lua_isnil(L, 5)) + rotation = read_v3f(L, 5); + co->setAttachment(parent->getId(), bone, position, rotation); + return 0; +} + +// set_detach(self) +int ObjectRef::l_set_detach(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + ServerActiveObject *co = getobject(ref); + if(co == NULL) return 0; + // Do it + co->setAttachment(0, "", v3f(0,0,0), v3f(0,0,0)); + return 0; +} + +// set_properties(self, properties) +int ObjectRef::l_set_properties(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + ServerActiveObject *co = getobject(ref); + if(co == NULL) return 0; + ObjectProperties *prop = co->accessObjectProperties(); + if(!prop) + return 0; + read_object_properties(L, 2, prop); + co->notifyObjectPropertiesModified(); + return 0; +} + +/* LuaEntitySAO-only */ + +// setvelocity(self, {x=num, y=num, z=num}) +int ObjectRef::l_setvelocity(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + LuaEntitySAO *co = getluaobject(ref); + if(co == NULL) return 0; + v3f pos = checkFloatPos(L, 2); + // Do it + co->setVelocity(pos); + return 0; +} + +// getvelocity(self) +int ObjectRef::l_getvelocity(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + LuaEntitySAO *co = getluaobject(ref); + if(co == NULL) return 0; + // Do it + v3f v = co->getVelocity(); + pushFloatPos(L, v); + return 1; +} + +// setacceleration(self, {x=num, y=num, z=num}) +int ObjectRef::l_setacceleration(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + LuaEntitySAO *co = getluaobject(ref); + if(co == NULL) return 0; + // pos + v3f pos = checkFloatPos(L, 2); + // Do it + co->setAcceleration(pos); + return 0; +} + +// getacceleration(self) +int ObjectRef::l_getacceleration(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + LuaEntitySAO *co = getluaobject(ref); + if(co == NULL) return 0; + // Do it + v3f v = co->getAcceleration(); + pushFloatPos(L, v); + return 1; +} + +// setyaw(self, radians) +int ObjectRef::l_setyaw(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + LuaEntitySAO *co = getluaobject(ref); + if(co == NULL) return 0; + float yaw = luaL_checknumber(L, 2) * core::RADTODEG; + // Do it + co->setYaw(yaw); + return 0; +} + +// getyaw(self) +int ObjectRef::l_getyaw(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + LuaEntitySAO *co = getluaobject(ref); + if(co == NULL) return 0; + // Do it + float yaw = co->getYaw() * core::DEGTORAD; + lua_pushnumber(L, yaw); + return 1; +} + +// settexturemod(self, mod) +int ObjectRef::l_settexturemod(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + LuaEntitySAO *co = getluaobject(ref); + if(co == NULL) return 0; + // Do it + std::string mod = luaL_checkstring(L, 2); + co->setTextureMod(mod); + return 0; +} + +// setsprite(self, p={x=0,y=0}, num_frames=1, framelength=0.2, +// select_horiz_by_yawpitch=false) +int ObjectRef::l_setsprite(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + LuaEntitySAO *co = getluaobject(ref); + if(co == NULL) return 0; + // Do it + v2s16 p(0,0); + if(!lua_isnil(L, 2)) + p = read_v2s16(L, 2); + int num_frames = 1; + if(!lua_isnil(L, 3)) + num_frames = lua_tonumber(L, 3); + float framelength = 0.2; + if(!lua_isnil(L, 4)) + framelength = lua_tonumber(L, 4); + bool select_horiz_by_yawpitch = false; + if(!lua_isnil(L, 5)) + select_horiz_by_yawpitch = lua_toboolean(L, 5); + co->setSprite(p, num_frames, framelength, select_horiz_by_yawpitch); + return 0; +} + +// DEPRECATED +// get_entity_name(self) +int ObjectRef::l_get_entity_name(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + LuaEntitySAO *co = getluaobject(ref); + if(co == NULL) return 0; + // Do it + std::string name = co->getName(); + lua_pushstring(L, name.c_str()); + return 1; +} + +// get_luaentity(self) +int ObjectRef::l_get_luaentity(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + LuaEntitySAO *co = getluaobject(ref); + if(co == NULL) return 0; + // Do it + luaentity_get(L, co->getId()); + return 1; +} + +/* Player-only */ + +// is_player(self) +int ObjectRef::l_is_player(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + Player *player = getplayer(ref); + lua_pushboolean(L, (player != NULL)); + return 1; +} + +// get_player_name(self) +int ObjectRef::l_get_player_name(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + Player *player = getplayer(ref); + if(player == NULL){ + lua_pushlstring(L, "", 0); + return 1; + } + // Do it + lua_pushstring(L, player->getName()); + return 1; +} + +// get_look_dir(self) +int ObjectRef::l_get_look_dir(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + Player *player = getplayer(ref); + if(player == NULL) return 0; + // Do it + float pitch = player->getRadPitch(); + float yaw = player->getRadYaw(); + v3f v(cos(pitch)*cos(yaw), sin(pitch), cos(pitch)*sin(yaw)); + push_v3f(L, v); + return 1; +} + +// get_look_pitch(self) +int ObjectRef::l_get_look_pitch(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + Player *player = getplayer(ref); + if(player == NULL) return 0; + // Do it + lua_pushnumber(L, player->getRadPitch()); + return 1; +} + +// get_look_yaw(self) +int ObjectRef::l_get_look_yaw(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + Player *player = getplayer(ref); + if(player == NULL) return 0; + // Do it + lua_pushnumber(L, player->getRadYaw()); + return 1; +} + +// set_look_pitch(self, radians) +int ObjectRef::l_set_look_pitch(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + PlayerSAO* co = getplayersao(ref); + if(co == NULL) return 0; + float pitch = luaL_checknumber(L, 2) * core::RADTODEG; + // Do it + co->setPitch(pitch); + return 1; +} + +// set_look_yaw(self, radians) +int ObjectRef::l_set_look_yaw(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + PlayerSAO* co = getplayersao(ref); + if(co == NULL) return 0; + float yaw = luaL_checknumber(L, 2) * core::RADTODEG; + // Do it + co->setYaw(yaw); + return 1; +} + +// set_inventory_formspec(self, formspec) +int ObjectRef::l_set_inventory_formspec(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + Player *player = getplayer(ref); + if(player == NULL) return 0; + std::string formspec = luaL_checkstring(L, 2); + + player->inventory_formspec = formspec; + STACK_TO_SERVER(L)->reportInventoryFormspecModified(player->getName()); + lua_pushboolean(L, true); + return 1; +} + +// get_inventory_formspec(self) -> formspec +int ObjectRef::l_get_inventory_formspec(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + Player *player = getplayer(ref); + if(player == NULL) return 0; + + std::string formspec = player->inventory_formspec; + lua_pushlstring(L, formspec.c_str(), formspec.size()); + return 1; +} + +// get_player_control(self) +int ObjectRef::l_get_player_control(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + Player *player = getplayer(ref); + if(player == NULL){ + lua_pushlstring(L, "", 0); + return 1; + } + // Do it + PlayerControl control = player->getPlayerControl(); + lua_newtable(L); + lua_pushboolean(L, control.up); + lua_setfield(L, -2, "up"); + lua_pushboolean(L, control.down); + lua_setfield(L, -2, "down"); + lua_pushboolean(L, control.left); + lua_setfield(L, -2, "left"); + lua_pushboolean(L, control.right); + lua_setfield(L, -2, "right"); + lua_pushboolean(L, control.jump); + lua_setfield(L, -2, "jump"); + lua_pushboolean(L, control.aux1); + lua_setfield(L, -2, "aux1"); + lua_pushboolean(L, control.sneak); + lua_setfield(L, -2, "sneak"); + lua_pushboolean(L, control.LMB); + lua_setfield(L, -2, "LMB"); + lua_pushboolean(L, control.RMB); + lua_setfield(L, -2, "RMB"); + return 1; +} + +// get_player_control_bits(self) +int ObjectRef::l_get_player_control_bits(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + Player *player = getplayer(ref); + if(player == NULL){ + lua_pushlstring(L, "", 0); + return 1; + } + // Do it + lua_pushnumber(L, player->keyPressed); + return 1; +} + +// hud_add(self, form) +int ObjectRef::l_hud_add(lua_State *L) +{ + ObjectRef *ref = checkobject(L, 1); + Player *player = getplayer(ref); + if (player == NULL) + return 0; + + HudElement *elem = new HudElement; + + elem->type = (HudElementType)getenumfield(L, 2, "hud_elem_type", + es_HudElementType, HUD_ELEM_TEXT); + + lua_getfield(L, 2, "position"); + elem->pos = lua_istable(L, -1) ? read_v2f(L, -1) : v2f(); + lua_pop(L, 1); + + lua_getfield(L, 2, "scale"); + elem->scale = lua_istable(L, -1) ? read_v2f(L, -1) : v2f(); + lua_pop(L, 1); + + elem->name = getstringfield_default(L, 2, "name", ""); + elem->text = getstringfield_default(L, 2, "text", ""); + elem->number = getintfield_default(L, 2, "number", 0); + elem->item = getintfield_default(L, 2, "item", 0); + elem->dir = getintfield_default(L, 2, "dir", 0); + + lua_getfield(L, 2, "alignment"); + elem->align = lua_istable(L, -1) ? read_v2f(L, -1) : v2f(); + lua_pop(L, 1); + + lua_getfield(L, 2, "offset"); + elem->offset = lua_istable(L, -1) ? read_v2f(L, -1) : v2f(); + lua_pop(L, 1); + + u32 id = STACK_TO_SERVER(L)->hudAdd(player, elem); + if (id == (u32)-1) { + delete elem; + return 0; + } + + lua_pushnumber(L, id); + return 1; +} + +// hud_remove(self, id) +int ObjectRef::l_hud_remove(lua_State *L) +{ + ObjectRef *ref = checkobject(L, 1); + Player *player = getplayer(ref); + if (player == NULL) + return 0; + + u32 id = -1; + if (!lua_isnil(L, 2)) + id = lua_tonumber(L, 2); + + if (!STACK_TO_SERVER(L)->hudRemove(player, id)) + return 0; + + lua_pushboolean(L, true); + return 1; +} + +// hud_change(self, id, stat, data) +int ObjectRef::l_hud_change(lua_State *L) +{ + ObjectRef *ref = checkobject(L, 1); + Player *player = getplayer(ref); + if (player == NULL) + return 0; + + u32 id = -1; + if (!lua_isnil(L, 2)) + id = lua_tonumber(L, 2); + + HudElementStat stat = (HudElementStat)getenumfield(L, 3, "stat", + es_HudElementStat, HUD_STAT_NUMBER); + + if (id >= player->hud.size()) + return 0; + + void *value = NULL; + HudElement *e = player->hud[id]; + if (!e) + return 0; + + switch (stat) { + case HUD_STAT_POS: + e->pos = read_v2f(L, 4); + value = &e->pos; + break; + case HUD_STAT_NAME: + e->name = lua_tostring(L, 4); + value = &e->name; + break; + case HUD_STAT_SCALE: + e->scale = read_v2f(L, 4); + value = &e->scale; + break; + case HUD_STAT_TEXT: + e->text = lua_tostring(L, 4); + value = &e->text; + break; + case HUD_STAT_NUMBER: + e->number = lua_tonumber(L, 4); + value = &e->number; + break; + case HUD_STAT_ITEM: + e->item = lua_tonumber(L, 4); + value = &e->item; + break; + case HUD_STAT_DIR: + e->dir = lua_tonumber(L, 4); + value = &e->dir; + case HUD_STAT_ALIGN: + e->align = read_v2f(L, 4); + value = &e->align; + case HUD_STAT_OFFSET: + e->offset = read_v2f(L, 4); + value = &e->offset; + } + + STACK_TO_SERVER(L)->hudChange(player, id, stat, value); + + lua_pushboolean(L, true); + return 1; +} + +// hud_get(self, id) +int ObjectRef::l_hud_get(lua_State *L) +{ + ObjectRef *ref = checkobject(L, 1); + Player *player = getplayer(ref); + if (player == NULL) + return 0; + + u32 id = lua_tonumber(L, -1); + if (id >= player->hud.size()) + return 0; + + HudElement *e = player->hud[id]; + if (!e) + return 0; + + lua_newtable(L); + + lua_pushstring(L, es_HudElementType[(u8)e->type].str); + lua_setfield(L, -2, "type"); + + push_v2f(L, e->pos); + lua_setfield(L, -2, "position"); + + lua_pushstring(L, e->name.c_str()); + lua_setfield(L, -2, "name"); + + push_v2f(L, e->scale); + lua_setfield(L, -2, "scale"); + + lua_pushstring(L, e->text.c_str()); + lua_setfield(L, -2, "text"); + + lua_pushnumber(L, e->number); + lua_setfield(L, -2, "number"); + + lua_pushnumber(L, e->item); + lua_setfield(L, -2, "item"); + + lua_pushnumber(L, e->dir); + lua_setfield(L, -2, "dir"); + + return 1; +} + +// hud_set_flags(self, flags) +int ObjectRef::l_hud_set_flags(lua_State *L) +{ + ObjectRef *ref = checkobject(L, 1); + Player *player = getplayer(ref); + if (player == NULL) + return 0; + + u32 flags = 0; + u32 mask = 0; + bool flag; + + const EnumString *esp = es_HudBuiltinElement; + for (int i = 0; esp[i].str; i++) { + if (getboolfield(L, 2, esp[i].str, flag)) { + flags |= esp[i].num * flag; + mask |= esp[i].num; + } + } + if (!STACK_TO_SERVER(L)->hudSetFlags(player, flags, mask)) + return 0; + + lua_pushboolean(L, true); + return 1; +} + +ObjectRef::ObjectRef(ServerActiveObject *object): + m_object(object) +{ + //infostream<<"ObjectRef created for id="<getId()< + +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_OBJECT_H_ +#define L_OBJECT_H_ + +extern "C" { +#include +#include +} + +class ServerActiveObject; +class LuaEntitySAO; +class PlayerSAO; +class Player; + +/* + ObjectRef +*/ + +class ObjectRef +{ +private: + ServerActiveObject *m_object; + + static const char className[]; + static const luaL_reg methods[]; +public: + static ObjectRef *checkobject(lua_State *L, int narg); + + static ServerActiveObject* getobject(ObjectRef *ref); +private: + static LuaEntitySAO* getluaobject(ObjectRef *ref); + + static PlayerSAO* getplayersao(ObjectRef *ref); + + static Player* getplayer(ObjectRef *ref); + + // Exported functions + + // garbage collector + static int gc_object(lua_State *L); + + // remove(self) + static int l_remove(lua_State *L); + + // getpos(self) + // returns: {x=num, y=num, z=num} + static int l_getpos(lua_State *L); + + // setpos(self, pos) + static int l_setpos(lua_State *L); + + // moveto(self, pos, continuous=false) + static int l_moveto(lua_State *L); + + // punch(self, puncher, time_from_last_punch, tool_capabilities, dir) + static int l_punch(lua_State *L); + + // right_click(self, clicker); clicker = an another ObjectRef + static int l_right_click(lua_State *L); + + // set_hp(self, hp) + // hp = number of hitpoints (2 * number of hearts) + // returns: nil + static int l_set_hp(lua_State *L); + + // get_hp(self) + // returns: number of hitpoints (2 * number of hearts) + // 0 if not applicable to this type of object + static int l_get_hp(lua_State *L); + + // get_inventory(self) + static int l_get_inventory(lua_State *L); + + // get_wield_list(self) + static int l_get_wield_list(lua_State *L); + + // get_wield_index(self) + static int l_get_wield_index(lua_State *L); + + // get_wielded_item(self) + static int l_get_wielded_item(lua_State *L); + + // set_wielded_item(self, itemstack or itemstring or table or nil) + static int l_set_wielded_item(lua_State *L); + + // set_armor_groups(self, groups) + static int l_set_armor_groups(lua_State *L); + + // set_physics_override(self, physics_override_speed, physics_override_jump, physics_override_gravity) + static int l_set_physics_override(lua_State *L); + + // set_animation(self, frame_range, frame_speed, frame_blend) + static int l_set_animation(lua_State *L); + + // set_bone_position(self, std::string bone, v3f position, v3f rotation) + static int l_set_bone_position(lua_State *L); + + // set_attach(self, parent, bone, position, rotation) + static int l_set_attach(lua_State *L); + + // set_detach(self) + static int l_set_detach(lua_State *L); + + // set_properties(self, properties) + static int l_set_properties(lua_State *L); + + /* LuaEntitySAO-only */ + + // setvelocity(self, {x=num, y=num, z=num}) + static int l_setvelocity(lua_State *L); + + // getvelocity(self) + static int l_getvelocity(lua_State *L); + + // setacceleration(self, {x=num, y=num, z=num}) + static int l_setacceleration(lua_State *L); + + // getacceleration(self) + static int l_getacceleration(lua_State *L); + + // setyaw(self, radians) + static int l_setyaw(lua_State *L); + + // getyaw(self) + static int l_getyaw(lua_State *L); + + // settexturemod(self, mod) + static int l_settexturemod(lua_State *L); + + // setsprite(self, p={x=0,y=0}, num_frames=1, framelength=0.2, + // select_horiz_by_yawpitch=false) + static int l_setsprite(lua_State *L); + + // DEPRECATED + // get_entity_name(self) + static int l_get_entity_name(lua_State *L); + + // get_luaentity(self) + static int l_get_luaentity(lua_State *L); + + /* Player-only */ + + // is_player(self) + static int l_is_player(lua_State *L); + + // get_player_name(self) + static int l_get_player_name(lua_State *L); + + // get_look_dir(self) + static int l_get_look_dir(lua_State *L); + + // get_look_pitch(self) + static int l_get_look_pitch(lua_State *L); + + // get_look_yaw(self) + static int l_get_look_yaw(lua_State *L); + + // set_look_pitch(self, radians) + static int l_set_look_pitch(lua_State *L); + + // set_look_yaw(self, radians) + static int l_set_look_yaw(lua_State *L); + + // set_inventory_formspec(self, formspec) + static int l_set_inventory_formspec(lua_State *L); + + // get_inventory_formspec(self) -> formspec + static int l_get_inventory_formspec(lua_State *L); + + // get_player_control(self) + static int l_get_player_control(lua_State *L); + + // get_player_control_bits(self) + static int l_get_player_control_bits(lua_State *L); + + // hud_add(self, id, form) + static int l_hud_add(lua_State *L); + + // hud_rm(self, id) + static int l_hud_remove(lua_State *L); + + // hud_change(self, id, stat, data) + static int l_hud_change(lua_State *L); + + // hud_get_next_id(self) + static u32 hud_get_next_id(lua_State *L); + + // hud_get(self, id) + static int l_hud_get(lua_State *L); + + // hud_set_flags(self, flags) + static int l_hud_set_flags(lua_State *L); + +public: + ObjectRef(ServerActiveObject *object); + + ~ObjectRef(); + + // Creates an ObjectRef and leaves it on top of stack + // Not callable from Lua; all references are created on the C side. + static void create(lua_State *L, ServerActiveObject *object); + + static void set_null(lua_State *L); + + static void Register(lua_State *L); +}; + +#endif /* L_OBJECT_H_ */ diff --git a/src/script/lua_api/l_particles.cpp b/src/script/lua_api/l_particles.cpp new file mode 100644 index 000000000..c291cc21e --- /dev/null +++ b/src/script/lua_api/l_particles.cpp @@ -0,0 +1,149 @@ +/* +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/scriptapi.h" +#include "common/c_converter.h" +#include "lua_api/l_base.h" +#include "lua_api/l_particles.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) +// pos/velocity/acceleration = {x=num, y=num, z=num} +// expirationtime = num (seconds) +// size = num +// texture = e.g."default_wood.png" +int ModApiParticles::l_add_particle(lua_State *L) +{ + // Get parameters + v3f pos = check_v3f(L, 1); + v3f vel = check_v3f(L, 2); + v3f acc = check_v3f(L, 3); + float expirationtime = luaL_checknumber(L, 4); + float size = luaL_checknumber(L, 5); + bool collisiondetection = lua_toboolean(L, 6); + std::string texture = luaL_checkstring(L, 7); + + if (lua_gettop(L) == 8) // only spawn for a single player + { + const char *playername = luaL_checkstring(L, 8); + getServer(L)->spawnParticle(playername, + pos, vel, acc, expirationtime, + size, collisiondetection, texture); + } + else // spawn for all players + { + getServer(L)->spawnParticleAll(pos, vel, acc, + expirationtime, size, collisiondetection, texture); + } + return 1; +} + +// add_particlespawner(amount, time, +// minpos, maxpos, +// minvel, maxvel, +// minacc, maxacc, +// minexptime, maxexptime, +// minsize, maxsize, +// collisiondetection, +// texture, +// player) +// minpos/maxpos/minvel/maxvel/minacc/maxacc = {x=num, y=num, z=num} +// minexptime/maxexptime = num (seconds) +// minsize/maxsize = num +// collisiondetection = bool +// texture = e.g."default_wood.png" +int ModApiParticles::l_add_particlespawner(lua_State *L) +{ + // Get parameters + u16 amount = luaL_checknumber(L, 1); + float time = luaL_checknumber(L, 2); + v3f minpos = check_v3f(L, 3); + v3f maxpos = check_v3f(L, 4); + v3f minvel = check_v3f(L, 5); + v3f maxvel = check_v3f(L, 6); + v3f minacc = check_v3f(L, 7); + v3f maxacc = check_v3f(L, 8); + float minexptime = luaL_checknumber(L, 9); + float maxexptime = luaL_checknumber(L, 10); + float minsize = luaL_checknumber(L, 11); + float maxsize = luaL_checknumber(L, 12); + bool collisiondetection = lua_toboolean(L, 13); + std::string texture = luaL_checkstring(L, 14); + + if (lua_gettop(L) == 15) // only spawn for a single player + { + const char *playername = luaL_checkstring(L, 15); + u32 id = getServer(L)->addParticleSpawner(playername, + amount, time, + minpos, maxpos, + minvel, maxvel, + minacc, maxacc, + minexptime, maxexptime, + minsize, maxsize, + collisiondetection, + texture); + lua_pushnumber(L, id); + } + else // spawn for all players + { + u32 id = getServer(L)->addParticleSpawnerAll( amount, time, + minpos, maxpos, + minvel, maxvel, + minacc, maxacc, + minexptime, maxexptime, + minsize, maxsize, + collisiondetection, + texture); + lua_pushnumber(L, id); + } + return 1; +} + +// delete_particlespawner(id, player) +// player (string) is optional +int ModApiParticles::l_delete_particlespawner(lua_State *L) +{ + // Get parameters + u32 id = luaL_checknumber(L, 1); + + if (lua_gettop(L) == 2) // only delete for one player + { + const char *playername = luaL_checkstring(L, 2); + getServer(L)->deleteParticleSpawner(playername, id); + } + else // delete for all players + { + getServer(L)->deleteParticleSpawnerAll(id); + } + return 1; +} + +ModApiParticles modapiparticles_prototyp; diff --git a/src/script/lua_api/l_particles.h b/src/script/lua_api/l_particles.h new file mode 100644 index 000000000..3729f8761 --- /dev/null +++ b/src/script/lua_api/l_particles.h @@ -0,0 +1,39 @@ +/* +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_PARTICLES_H_ +#define L_PARTICLES_H_ + +extern "C" { +#include +#include +} + +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); +}; + + + +#endif // L_PARTICLES_H_ diff --git a/src/script/lua_api/luaapi.cpp b/src/script/lua_api/luaapi.cpp new file mode 100644 index 000000000..b75304b3a --- /dev/null +++ b/src/script/lua_api/luaapi.cpp @@ -0,0 +1,653 @@ +/* +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}, +}; + + +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_of_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); + + return retval; +} + +// debug(text) +// Writes a line to dstream +int ModApiBasic::l_debug(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + std::string text = lua_tostring(L, 1); + dstream << text << 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->top_nodename = getstringfield_default(L, index, "top_node", ""); + b->top_depth = getintfield_default(L, index, "top_depth", 0); + b->filler_nodename = getstringfield_default(L, index, "filler_node", ""); + b->filler_height = getintfield_default(L, index, "filler_height", 0); + 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; + bmgr->addBiome(b); + + verbosestream << "register_biome: " << b->name << std::endl; + 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_of_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->wherein_name = getstringfield_default(L, index, "wherein", ""); + 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, "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; +} + +ModApiBasic modapibasic_prototype; diff --git a/src/script/lua_api/luaapi.h b/src/script/lua_api/luaapi.h new file mode 100644 index 000000000..592046965 --- /dev/null +++ b/src/script/lua_api/luaapi.h @@ -0,0 +1,140 @@ +/* +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_groups({frequencies}) + static int l_register_biome_groups(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_of_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); + + static int l_register_ore(lua_State *L); + + static struct EnumString es_OreType[]; +}; + + + +#endif /* LUAAPI_H_ */ diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp deleted file mode 100644 index 26759a059..000000000 --- a/src/scriptapi.cpp +++ /dev/null @@ -1,1181 +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. -*/ - -#include "scriptapi.h" - -#include -#include -extern "C" { -#include -#include -#include -} - -#include "settings.h" // For accessing g_settings -#include "main.h" // For g_settings -#include "biome.h" -#include "emerge.h" -#include "script.h" -#include "rollback.h" - -#include "scriptapi_types.h" -#include "scriptapi_env.h" -#include "scriptapi_nodetimer.h" -#include "scriptapi_inventory.h" -#include "scriptapi_nodemeta.h" -#include "scriptapi_object.h" -#include "scriptapi_noise.h" -#include "scriptapi_common.h" -#include "scriptapi_item.h" -#include "scriptapi_content.h" -#include "scriptapi_craft.h" -#include "scriptapi_particles.h" - -/*****************************************************************************/ -/* Mod related */ -/*****************************************************************************/ - -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"); - } -}; - -bool scriptapi_loadmod(lua_State *L, const std::string &scriptpath, - const std::string &modname) -{ - ModNameStorer modnamestorer(L, modname); - - if(!string_allowed(modname, MODNAME_ALLOWED_CHARS)){ - errorstream<<"Error loading mod \""< &result) -{ - 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); - } -} - -static void get_auth_handler(lua_State *L) -{ - 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"); -} - -bool scriptapi_get_auth(lua_State *L, const std::string &playername, - std::string *dst_password, std::set *dst_privs) -{ - realitycheck(L); - assert(lua_checkstack(L, 20)); - StackUnroller stack_unroller(L); - - get_auth_handler(L); - 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)) - script_error(L, "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) - read_privileges(L, -1, *dst_privs); - lua_pop(L, 1); - - return true; -} - -void scriptapi_create_auth(lua_State *L, const std::string &playername, - const std::string &password) -{ - realitycheck(L); - assert(lua_checkstack(L, 20)); - StackUnroller stack_unroller(L); - - get_auth_handler(L); - 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)) - script_error(L, "error: %s", lua_tostring(L, -1)); -} - -bool scriptapi_set_password(lua_State *L, const std::string &playername, - const std::string &password) -{ - realitycheck(L); - assert(lua_checkstack(L, 20)); - StackUnroller stack_unroller(L); - - get_auth_handler(L); - 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)) - script_error(L, "error: %s", lua_tostring(L, -1)); - return lua_toboolean(L, -1); -} - -/*****************************************************************************/ -/* Misc */ -/*****************************************************************************/ -/* - Groups -*/ -void read_groups(lua_State *L, int index, - std::map &result) -{ - if (!lua_istable(L,index)) - return; - 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 name = luaL_checkstring(L, -2); - int rating = luaL_checkinteger(L, -1); - result[name] = rating; - // removes value, keeps key for next iteration - lua_pop(L, 1); - } -} - -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}, -}; - -struct EnumString es_OreType[] = -{ - {ORE_SCATTER, "scatter"}, - {ORE_SHEET, "sheet"}, - {ORE_CLAYLIKE, "claylike"}, - {0, NULL}, -}; - -/*****************************************************************************/ -/* Parameters */ -/*****************************************************************************/ -/* - DigParams -*/ - -static void set_dig_params(lua_State *L, int table, - const DigParams ¶ms) -{ - setboolfield(L, table, "diggable", params.diggable); - setfloatfield(L, table, "time", params.time); - setintfield(L, table, "wear", params.wear); -} - -static void push_dig_params(lua_State *L, - const DigParams ¶ms) -{ - lua_newtable(L); - set_dig_params(L, -1, params); -} - -/* - HitParams -*/ - -static void set_hit_params(lua_State *L, int table, - const HitParams ¶ms) -{ - setintfield(L, table, "hp", params.hp); - setintfield(L, table, "wear", params.wear); -} - -static void push_hit_params(lua_State *L, - const HitParams ¶ms) -{ - lua_newtable(L); - set_hit_params(L, -1, params); -} - -/* - ServerSoundParams -*/ - -static void read_server_sound_params(lua_State *L, int index, - ServerSoundParams ¶ms) -{ - if(index < 0) - index = lua_gettop(L) + 1 + index; - // Clear - params = ServerSoundParams(); - if(lua_istable(L, index)){ - getfloatfield(L, index, "gain", params.gain); - getstringfield(L, index, "to_player", params.to_player); - lua_getfield(L, index, "pos"); - if(!lua_isnil(L, -1)){ - v3f p = read_v3f(L, -1)*BS; - params.pos = p; - params.type = ServerSoundParams::SSP_POSITIONAL; - } - lua_pop(L, 1); - lua_getfield(L, index, "object"); - if(!lua_isnil(L, -1)){ - ObjectRef *ref = ObjectRef::checkobject(L, -1); - ServerActiveObject *sao = ObjectRef::getobject(ref); - if(sao){ - params.object = sao->getId(); - params.type = ServerSoundParams::SSP_OBJECT; - } - } - lua_pop(L, 1); - params.max_hear_distance = BS*getfloatfield_default(L, index, - "max_hear_distance", params.max_hear_distance/BS); - getboolfield(L, index, "loop", params.loop); - } -} - -/*****************************************************************************/ -/* callbacks */ -/*****************************************************************************/ - -// Push the list of callbacks (a lua table). -// Then push nargs arguments. -// Then call this function, which -// - runs the callbacks -// - removes the table and arguments from the lua stack -// - pushes the return value, computed depending on mode -void scriptapi_run_callbacks(lua_State *L, int nargs, - RunCallbacksMode mode) -{ - // Insert the return value into the lua stack, below the table - assert(lua_gettop(L) >= nargs + 1); - lua_pushnil(L); - lua_insert(L, -(nargs + 1) - 1); - // Stack now looks like this: - // ...
... - - 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); - } - } -} - -bool scriptapi_on_chat_message(lua_State *L, const std::string &name, - const std::string &message) -{ - realitycheck(L); - assert(lua_checkstack(L, 20)); - StackUnroller stack_unroller(L); - - // 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()); - scriptapi_run_callbacks(L, 2, RUN_CALLBACKS_MODE_OR_SC); - bool ate = lua_toboolean(L, -1); - return ate; -} - -void scriptapi_on_shutdown(lua_State *L) -{ - realitycheck(L); - assert(lua_checkstack(L, 20)); - StackUnroller stack_unroller(L); - - // Get registered shutdown hooks - lua_getglobal(L, "minetest"); - lua_getfield(L, -1, "registered_on_shutdown"); - // Call callbacks - scriptapi_run_callbacks(L, 0, RUN_CALLBACKS_MODE_FIRST); -} - -void scriptapi_on_newplayer(lua_State *L, ServerActiveObject *player) -{ - realitycheck(L); - assert(lua_checkstack(L, 20)); - StackUnroller stack_unroller(L); - - // Get minetest.registered_on_newplayers - lua_getglobal(L, "minetest"); - lua_getfield(L, -1, "registered_on_newplayers"); - // Call callbacks - objectref_get_or_create(L, player); - scriptapi_run_callbacks(L, 1, RUN_CALLBACKS_MODE_FIRST); -} - -void scriptapi_on_dieplayer(lua_State *L, ServerActiveObject *player) -{ - realitycheck(L); - assert(lua_checkstack(L, 20)); - StackUnroller stack_unroller(L); - - // Get minetest.registered_on_dieplayers - lua_getglobal(L, "minetest"); - lua_getfield(L, -1, "registered_on_dieplayers"); - // Call callbacks - objectref_get_or_create(L, player); - scriptapi_run_callbacks(L, 1, RUN_CALLBACKS_MODE_FIRST); -} - -bool scriptapi_on_respawnplayer(lua_State *L, ServerActiveObject *player) -{ - realitycheck(L); - assert(lua_checkstack(L, 20)); - StackUnroller stack_unroller(L); - - // Get minetest.registered_on_respawnplayers - lua_getglobal(L, "minetest"); - lua_getfield(L, -1, "registered_on_respawnplayers"); - // Call callbacks - objectref_get_or_create(L, player); - scriptapi_run_callbacks(L, 1, RUN_CALLBACKS_MODE_OR); - bool positioning_handled_by_some = lua_toboolean(L, -1); - return positioning_handled_by_some; -} - -void scriptapi_on_joinplayer(lua_State *L, ServerActiveObject *player) -{ - realitycheck(L); - assert(lua_checkstack(L, 20)); - StackUnroller stack_unroller(L); - - // Get minetest.registered_on_joinplayers - lua_getglobal(L, "minetest"); - lua_getfield(L, -1, "registered_on_joinplayers"); - // Call callbacks - objectref_get_or_create(L, player); - scriptapi_run_callbacks(L, 1, RUN_CALLBACKS_MODE_FIRST); -} - -void scriptapi_on_leaveplayer(lua_State *L, ServerActiveObject *player) -{ - realitycheck(L); - assert(lua_checkstack(L, 20)); - StackUnroller stack_unroller(L); - - // Get minetest.registered_on_leaveplayers - lua_getglobal(L, "minetest"); - lua_getfield(L, -1, "registered_on_leaveplayers"); - // Call callbacks - objectref_get_or_create(L, player); - scriptapi_run_callbacks(L, 1, RUN_CALLBACKS_MODE_FIRST); -} - -/* - player -*/ -void scriptapi_on_player_receive_fields(lua_State *L, - ServerActiveObject *player, - const std::string &formname, - const std::map &fields) -{ - realitycheck(L); - assert(lua_checkstack(L, 20)); - StackUnroller stack_unroller(L); - - // Get minetest.registered_on_chat_messages - lua_getglobal(L, "minetest"); - lua_getfield(L, -1, "registered_on_player_receive_fields"); - // Call callbacks - // param 1 - objectref_get_or_create(L, player); - // param 2 - lua_pushstring(L, formname.c_str()); - // param 3 - 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); - } - scriptapi_run_callbacks(L, 3, RUN_CALLBACKS_MODE_OR_SC); -} -/*****************************************************************************/ -/* Api functions */ -/*****************************************************************************/ - -// debug(text) -// Writes a line to dstream -static int l_debug(lua_State *L) -{ - std::string text = lua_tostring(L, 1); - dstream << text << 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. -static int l_log(lua_State *L) -{ - 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() -static int l_request_shutdown(lua_State *L) -{ - get_server(L)->requestShutdown(); - return 0; -} - -// get_server_status() -static int l_get_server_status(lua_State *L) -{ - lua_pushstring(L, wide_to_narrow(get_server(L)->getStatusString()).c_str()); - return 1; -} - - -// register_biome({lots of stuff}) -static int l_register_biome(lua_State *L) -{ - int index = 1; - luaL_checktype(L, index, LUA_TTABLE); - - BiomeDefManager *bmgr = get_server(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->top_nodename = getstringfield_default(L, index, "top_node", ""); - b->top_depth = getintfield_default(L, index, "top_depth", 0); - b->filler_nodename = getstringfield_default(L, index, "filler_node", ""); - b->filler_height = getintfield_default(L, index, "filler_height", 0); - 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; - bmgr->addBiome(b); - - verbosestream << "register_biome: " << b->name << std::endl; - return 0; -} - - -static int l_register_ore(lua_State *L) -{ - int index = 1; - luaL_checktype(L, index, LUA_TTABLE); - - EmergeManager *emerge = get_server(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->wherein_name = getstringfield_default(L, index, "wherein", ""); - 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, "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; -} - - -// setting_set(name, value) -static int 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; -} - -// setting_get(name) -static int 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; -} - -// setting_getbool(name) -static int 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; -} - -// setting_save() -static int l_setting_save(lua_State *L) -{ - get_server(L)->saveConfig(); - return 0; -} - -// chat_send_all(text) -static int l_chat_send_all(lua_State *L) -{ - const char *text = luaL_checkstring(L, 1); - // Get server from registry - Server *server = get_server(L); - // Send - server->notifyPlayers(narrow_to_wide(text)); - return 0; -} - -// chat_send_player(name, text, prepend) -static int l_chat_send_player(lua_State *L) -{ - 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 = get_server(L); - // Send - server->notifyPlayer(name, narrow_to_wide(text), prepend); - return 0; -} - -// get_player_privs(name, text) -static int l_get_player_privs(lua_State *L) -{ - const char *name = luaL_checkstring(L, 1); - // Get server from registry - Server *server = get_server(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() -static int l_get_player_ip(lua_State *L) -{ - const char * name = luaL_checkstring(L, 1); - Player *player = get_env(L)->getPlayer(name); - if(player == NULL) - { - lua_pushnil(L); // no such player - return 1; - } - try - { - Address addr = get_server(L)->getPeerAddress(get_env(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() -static int l_get_ban_list(lua_State *L) -{ - lua_pushstring(L, get_server(L)->getBanDescription("").c_str()); - return 1; -} - -// get_ban_description() -static int l_get_ban_description(lua_State *L) -{ - const char * ip_or_name = luaL_checkstring(L, 1); - lua_pushstring(L, get_server(L)->getBanDescription(std::string(ip_or_name)).c_str()); - return 1; -} - -// ban_player() -static int l_ban_player(lua_State *L) -{ - const char * name = luaL_checkstring(L, 1); - Player *player = get_env(L)->getPlayer(name); - if(player == NULL) - { - lua_pushboolean(L, false); // no such player - return 1; - } - try - { - Address addr = get_server(L)->getPeerAddress(get_env(L)->getPlayer(name)->peer_id); - std::string ip_str = addr.serializeString(); - get_server(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() -static int l_unban_player_of_ip(lua_State *L) -{ - const char * ip_or_name = luaL_checkstring(L, 1); - get_server(L)->unsetIpBanned(ip_or_name); - lua_pushboolean(L, true); - return 1; -} - -// show_formspec(playername,formname,formspec) -static int l_show_formspec(lua_State *L) -{ - const char *playername = luaL_checkstring(L, 1); - const char *formname = luaL_checkstring(L, 2); - const char *formspec = luaL_checkstring(L, 3); - - if(get_server(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]) -static int l_get_dig_params(lua_State *L) -{ - 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]) -static int l_get_hit_params(lua_State *L) -{ - 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() -static int l_get_current_modname(lua_State *L) -{ - lua_getfield(L, LUA_REGISTRYINDEX, "minetest_current_modname"); - return 1; -} - -// get_modpath(modname) -static int l_get_modpath(lua_State *L) -{ - std::string modname = luaL_checkstring(L, 1); - // Do it - if(modname == "__builtin"){ - std::string path = get_server(L)->getBuiltinLuaPath(); - lua_pushstring(L, path.c_str()); - return 1; - } - const ModSpec *mod = get_server(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 -static int l_get_modnames(lua_State *L) -{ - // Get a list of mods - std::list mods_unsorted, mods_sorted; - get_server(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() -static int l_get_worldpath(lua_State *L) -{ - std::string worldpath = get_server(L)->getWorldPath(); - lua_pushstring(L, worldpath.c_str()); - return 1; -} - -// sound_play(spec, parameters) -static int l_sound_play(lua_State *L) -{ - SimpleSoundSpec spec; - read_soundspec(L, 1, spec); - ServerSoundParams params; - read_server_sound_params(L, 2, params); - s32 handle = get_server(L)->playSound(spec, params); - lua_pushinteger(L, handle); - return 1; -} - -// sound_stop(handle) -static int l_sound_stop(lua_State *L) -{ - int handle = luaL_checkinteger(L, 1); - get_server(L)->stopSound(handle); - return 0; -} - -// is_singleplayer() -static int l_is_singleplayer(lua_State *L) -{ - lua_pushboolean(L, get_server(L)->isSingleplayer()); - return 1; -} - -// get_password_hash(name, raw_password) -static int l_get_password_hash(lua_State *L) -{ - 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) -static int l_notify_authentication_modified(lua_State *L) -{ - std::string name = ""; - if(lua_isstring(L, 1)) - name = lua_tostring(L, 1); - get_server(L)->reportPrivsModified(name); - return 0; -} - -// rollback_get_last_node_actor(p, range, seconds) -> actor, p, seconds -static int 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 = get_server(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 -static int l_rollback_revert_actions_by(lua_State *L) -{ - std::string actor = luaL_checkstring(L, 1); - int seconds = luaL_checknumber(L, 2); - Server *server = get_server(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; -} - -static const struct luaL_Reg minetest_f [] = { - {"debug", l_debug}, - {"log", l_log}, - {"request_shutdown", l_request_shutdown}, - {"get_server_status", l_get_server_status}, - {"register_item_raw", l_register_item_raw}, - {"register_alias_raw", l_register_alias_raw}, - {"register_craft", l_register_craft}, - {"register_biome", l_register_biome}, - {"register_ore", l_register_ore}, - {"setting_set", l_setting_set}, - {"setting_get", l_setting_get}, - {"setting_getbool", l_setting_getbool}, - {"setting_save",l_setting_save}, - {"chat_send_all", l_chat_send_all}, - {"chat_send_player", l_chat_send_player}, - {"get_player_privs", l_get_player_privs}, - {"get_player_ip", l_get_player_ip}, - {"get_ban_list", l_get_ban_list}, - {"get_ban_description", l_get_ban_description}, - {"ban_player", l_ban_player}, - {"unban_player_or_ip", l_unban_player_of_ip}, - {"get_inventory", l_get_inventory}, - {"create_detached_inventory_raw", l_create_detached_inventory_raw}, - {"show_formspec", l_show_formspec}, - {"get_dig_params", l_get_dig_params}, - {"get_hit_params", l_get_hit_params}, - {"get_current_modname", l_get_current_modname}, - {"get_modpath", l_get_modpath}, - {"get_modnames", l_get_modnames}, - {"get_worldpath", l_get_worldpath}, - {"sound_play", l_sound_play}, - {"sound_stop", l_sound_stop}, - {"is_singleplayer", l_is_singleplayer}, - {"get_password_hash", l_get_password_hash}, - {"notify_authentication_modified", l_notify_authentication_modified}, - {"get_craft_result", l_get_craft_result}, - {"get_craft_recipe", l_get_craft_recipe}, - {"get_all_craft_recipes", l_get_all_craft_recipes}, - {"rollback_get_last_node_actor", l_rollback_get_last_node_actor}, - {"rollback_revert_actions_by", l_rollback_revert_actions_by}, - {"add_particle", l_add_particle}, - {"add_particlespawner", l_add_particlespawner}, - {"delete_particlespawner", l_delete_particlespawner}, - {NULL, NULL} -}; - - -/* - Main export function -*/ - -void scriptapi_export(lua_State *L, Server *server) -{ - realitycheck(L); - assert(lua_checkstack(L, 20)); - verbosestream<<"scriptapi_export()"< - -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_HEADER -#define SCRIPTAPI_HEADER - -#include -#include -#include -#include "irr_v3d.h" -#include "irr_v2d.h" - -extern "C" { -#include -} -#include "scriptapi_inventory.h" -#include "scriptapi_nodemeta.h" -#include "scriptapi_entity.h" -#include "scriptapi_object.h" -#include "scriptapi_env.h" -#include "scriptapi_item.h" -#include "scriptapi_node.h" - -#define luamethod(class, name) {#name, class::l_##name} - -class Server; - -void scriptapi_export(lua_State *L, Server *server); -bool scriptapi_loadmod(lua_State *L, const std::string &scriptpath, - const std::string &modname); - -// Returns true if script handled message -bool scriptapi_on_chat_message(lua_State *L, const std::string &name, - const std::string &message); - -/* server */ -void scriptapi_on_shutdown(lua_State *L); - -/* misc */ -void scriptapi_on_newplayer(lua_State *L, ServerActiveObject *player); -void scriptapi_on_dieplayer(lua_State *L, ServerActiveObject *player); -bool scriptapi_on_respawnplayer(lua_State *L, ServerActiveObject *player); -void scriptapi_on_joinplayer(lua_State *L, ServerActiveObject *player); -void scriptapi_on_leaveplayer(lua_State *L, ServerActiveObject *player); -bool scriptapi_get_auth(lua_State *L, const std::string &playername, - std::string *dst_password, std::set *dst_privs); -void scriptapi_create_auth(lua_State *L, const std::string &playername, - const std::string &password); -bool scriptapi_set_password(lua_State *L, const std::string &playername, - const std::string &password); - -/* player */ -void scriptapi_on_player_receive_fields(lua_State *L, - ServerActiveObject *player, - const std::string &formname, - const std::map &fields); - -#endif - diff --git a/src/scriptapi_common.cpp b/src/scriptapi_common.cpp deleted file mode 100644 index 2d6f6c72b..000000000 --- a/src/scriptapi_common.cpp +++ /dev/null @@ -1,311 +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. -*/ - -#include "scriptapi.h" -#include "scriptapi_common.h" - -extern "C" { -#include "lauxlib.h" -} - -#include "script.h" -#include "scriptapi_types.h" -#include "scriptapi_object.h" - - -Server* get_server(lua_State *L) -{ - // Get server from registry - lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server"); - Server *server = (Server*)lua_touserdata(L, -1); - lua_pop(L, 1); - return server; -} - -ServerEnvironment* get_env(lua_State *L) -{ - // Get environment from registry - lua_getfield(L, LUA_REGISTRYINDEX, "minetest_env"); - ServerEnvironment *env = (ServerEnvironment*)lua_touserdata(L, -1); - lua_pop(L, 1); - return env; -} - -void warn_if_field_exists(lua_State *L, int table, - const char *fieldname, const std::string &message) -{ - lua_getfield(L, table, fieldname); - if(!lua_isnil(L, -1)){ - infostream<::const_iterator - i = toolcap.groupcaps.begin(); i != toolcap.groupcaps.end(); i++){ - // Create groupcap table - lua_newtable(L); - const std::string &name = i->first; - const ToolGroupCap &groupcap = i->second; - // Create subtable "times" - lua_newtable(L); - for(std::map::const_iterator - i = groupcap.times.begin(); i != groupcap.times.end(); i++){ - int rating = i->first; - float time = i->second; - lua_pushinteger(L, rating); - lua_pushnumber(L, time); - lua_settable(L, -3); - } - // Set subtable "times" - lua_setfield(L, -2, "times"); - // Set simple parameters - setintfield(L, -1, "maxlevel", groupcap.maxlevel); - setintfield(L, -1, "uses", groupcap.uses); - // Insert groupcap table into groupcaps table - lua_setfield(L, -2, name.c_str()); - } - // Set groupcaps table - lua_setfield(L, -2, "groupcaps"); - //Create damage_groups table - lua_newtable(L); - // For each damage group - for(std::map::const_iterator - i = toolcap.damageGroups.begin(); i != toolcap.damageGroups.end(); i++){ - // Create damage group table - lua_pushinteger(L, i->second); - lua_setfield(L, -2, i->first.c_str()); - } - lua_setfield(L, -2, "damage_groups"); -} - -void push_tool_capabilities(lua_State *L, - const ToolCapabilities &prop) -{ - lua_newtable(L); - set_tool_capabilities(L, -1, prop); -} - -void realitycheck(lua_State *L) -{ - int top = lua_gettop(L); - if(top >= 30){ - dstream<<"Stack is over 30:"<str){ - if(str == std::string(esp->str)){ - result = esp->num; - return true; - } - esp++; - } - return false; -} - -/*bool enum_to_string(const EnumString *spec, std::string &result, - int num) -{ - const EnumString *esp = spec; - while(esp){ - if(num == esp->num){ - result = esp->str; - return true; - } - esp++; - } - return false; -}*/ - -int getenumfield(lua_State *L, int table, - const char *fieldname, const EnumString *spec, int default_) -{ - int result = default_; - string_to_enum(spec, result, - getstringfield_default(L, table, fieldname, "")); - return result; -} diff --git a/src/scriptapi_common.h b/src/scriptapi_common.h deleted file mode 100644 index d029b48d3..000000000 --- a/src/scriptapi_common.h +++ /dev/null @@ -1,112 +0,0 @@ -/* -Minetest-c55 -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 LUA_COMMON_H_ -#define LUA_COMMON_H_ - -extern "C" { -#include -} - -#include "server.h" -#include "environment.h" -#include "nodedef.h" -#include "util/pointedthing.h" -#include "tool.h" - -Server* get_server(lua_State *L); -ServerEnvironment* get_env(lua_State *L); - -void warn_if_field_exists(lua_State *L, int table, - const char *fieldname, const std::string &message); - -ToolCapabilities read_tool_capabilities (lua_State *L, int table); -void push_tool_capabilities (lua_State *L, - const ToolCapabilities &prop); -void set_tool_capabilities (lua_State *L, int table, - const ToolCapabilities &toolcap); - -void realitycheck (lua_State *L); - -void push_pointed_thing (lua_State *L, - const PointedThing& pointed); - -void stackDump (lua_State *L, std::ostream &o); - -class StackUnroller -{ -private: - lua_State *m_lua; - int m_original_top; -public: - StackUnroller(lua_State *L): - m_lua(L), - m_original_top(-1) - { - m_original_top = lua_gettop(m_lua); // store stack height - } - ~StackUnroller() - { - lua_settop(m_lua, m_original_top); // restore stack height - } -}; - -/* 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. -}; - -struct EnumString -{ - int num; - const char *str; -}; - -bool string_to_enum(const EnumString *spec, int &result, - const std::string &str); - -int getenumfield(lua_State *L, int table, - const char *fieldname, const EnumString *spec, int default_); -#endif /* LUA_COMMON_H_ */ diff --git a/src/scriptapi_content.cpp b/src/scriptapi_content.cpp deleted file mode 100644 index 30fd70349..000000000 --- a/src/scriptapi_content.cpp +++ /dev/null @@ -1,327 +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. -*/ - -#include "scriptapi.h" -#include "scriptapi_content.h" -#include "scriptapi_types.h" -#include "scriptapi_common.h" -#include "scriptapi_node.h" - - -NodeBox read_nodebox(lua_State *L, int index) -{ - NodeBox nodebox; - if(lua_istable(L, -1)){ - nodebox.type = (NodeBoxType)getenumfield(L, index, "type", - es_NodeBoxType, NODEBOX_REGULAR); - - lua_getfield(L, index, "fixed"); - if(lua_istable(L, -1)) - nodebox.fixed = read_aabb3f_vector(L, -1, BS); - lua_pop(L, 1); - - lua_getfield(L, index, "wall_top"); - if(lua_istable(L, -1)) - nodebox.wall_top = read_aabb3f(L, -1, BS); - lua_pop(L, 1); - - lua_getfield(L, index, "wall_bottom"); - if(lua_istable(L, -1)) - nodebox.wall_bottom = read_aabb3f(L, -1, BS); - lua_pop(L, 1); - - lua_getfield(L, index, "wall_side"); - if(lua_istable(L, -1)) - nodebox.wall_side = read_aabb3f(L, -1, BS); - lua_pop(L, 1); - } - return nodebox; -} - -/* - SimpleSoundSpec -*/ - -void read_soundspec(lua_State *L, int index, SimpleSoundSpec &spec) -{ - if(index < 0) - index = lua_gettop(L) + 1 + index; - if(lua_isnil(L, index)){ - } else if(lua_istable(L, index)){ - getstringfield(L, index, "name", spec.name); - getfloatfield(L, index, "gain", spec.gain); - } else if(lua_isstring(L, index)){ - spec.name = lua_tostring(L, index); - } -} - -struct EnumString es_TileAnimationType[] = -{ - {TAT_NONE, "none"}, - {TAT_VERTICAL_FRAMES, "vertical_frames"}, - {0, NULL}, -}; - -/* - TileDef -*/ - -TileDef read_tiledef(lua_State *L, int index) -{ - if(index < 0) - index = lua_gettop(L) + 1 + index; - - TileDef tiledef; - - // key at index -2 and value at index - if(lua_isstring(L, index)){ - // "default_lava.png" - tiledef.name = lua_tostring(L, index); - } - else if(lua_istable(L, index)) - { - // {name="default_lava.png", animation={}} - tiledef.name = ""; - getstringfield(L, index, "name", tiledef.name); - getstringfield(L, index, "image", tiledef.name); // MaterialSpec compat. - tiledef.backface_culling = getboolfield_default( - L, index, "backface_culling", true); - // animation = {} - lua_getfield(L, index, "animation"); - if(lua_istable(L, -1)){ - // {type="vertical_frames", aspect_w=16, aspect_h=16, length=2.0} - tiledef.animation.type = (TileAnimationType) - getenumfield(L, -1, "type", es_TileAnimationType, - TAT_NONE); - tiledef.animation.aspect_w = - getintfield_default(L, -1, "aspect_w", 16); - tiledef.animation.aspect_h = - getintfield_default(L, -1, "aspect_h", 16); - tiledef.animation.length = - getfloatfield_default(L, -1, "length", 1.0); - } - lua_pop(L, 1); - } - - return tiledef; -} - -/* - ContentFeatures -*/ - -ContentFeatures read_content_features(lua_State *L, int index) -{ - if(index < 0) - index = lua_gettop(L) + 1 + index; - - ContentFeatures f; - - /* Cache existence of some callbacks */ - lua_getfield(L, index, "on_construct"); - if(!lua_isnil(L, -1)) f.has_on_construct = true; - lua_pop(L, 1); - lua_getfield(L, index, "on_destruct"); - if(!lua_isnil(L, -1)) f.has_on_destruct = true; - lua_pop(L, 1); - lua_getfield(L, index, "after_destruct"); - if(!lua_isnil(L, -1)) f.has_after_destruct = true; - lua_pop(L, 1); - - lua_getfield(L, index, "on_rightclick"); - f.rightclickable = lua_isfunction(L, -1); - lua_pop(L, 1); - - /* Name */ - getstringfield(L, index, "name", f.name); - - /* Groups */ - lua_getfield(L, index, "groups"); - read_groups(L, -1, f.groups); - lua_pop(L, 1); - - /* Visual definition */ - - f.drawtype = (NodeDrawType)getenumfield(L, index, "drawtype", es_DrawType, - NDT_NORMAL); - getfloatfield(L, index, "visual_scale", f.visual_scale); - - // tiles = {} - lua_getfield(L, index, "tiles"); - // If nil, try the deprecated name "tile_images" instead - if(lua_isnil(L, -1)){ - lua_pop(L, 1); - warn_if_field_exists(L, index, "tile_images", - "Deprecated; new name is \"tiles\"."); - lua_getfield(L, index, "tile_images"); - } - if(lua_istable(L, -1)){ - int table = lua_gettop(L); - lua_pushnil(L); - int i = 0; - while(lua_next(L, table) != 0){ - // Read tiledef from value - f.tiledef[i] = read_tiledef(L, -1); - // removes value, keeps key for next iteration - lua_pop(L, 1); - i++; - if(i==6){ - lua_pop(L, 1); - break; - } - } - // Copy last value to all remaining textures - if(i >= 1){ - TileDef lasttile = f.tiledef[i-1]; - while(i < 6){ - f.tiledef[i] = lasttile; - i++; - } - } - } - lua_pop(L, 1); - - // special_tiles = {} - lua_getfield(L, index, "special_tiles"); - // If nil, try the deprecated name "special_materials" instead - if(lua_isnil(L, -1)){ - lua_pop(L, 1); - warn_if_field_exists(L, index, "special_materials", - "Deprecated; new name is \"special_tiles\"."); - lua_getfield(L, index, "special_materials"); - } - if(lua_istable(L, -1)){ - int table = lua_gettop(L); - lua_pushnil(L); - int i = 0; - while(lua_next(L, table) != 0){ - // Read tiledef from value - f.tiledef_special[i] = read_tiledef(L, -1); - // removes value, keeps key for next iteration - lua_pop(L, 1); - i++; - if(i==6){ - lua_pop(L, 1); - break; - } - } - } - lua_pop(L, 1); - - f.alpha = getintfield_default(L, index, "alpha", 255); - - bool usealpha = getboolfield_default(L, index, - "use_texture_alpha", false); - if (usealpha) - f.alpha = 0; - - /* Other stuff */ - - lua_getfield(L, index, "post_effect_color"); - if(!lua_isnil(L, -1)) - f.post_effect_color = readARGB8(L, -1); - lua_pop(L, 1); - - f.param_type = (ContentParamType)getenumfield(L, index, "paramtype", - es_ContentParamType, CPT_NONE); - f.param_type_2 = (ContentParamType2)getenumfield(L, index, "paramtype2", - es_ContentParamType2, CPT2_NONE); - - // Warn about some deprecated fields - warn_if_field_exists(L, index, "wall_mounted", - "deprecated: use paramtype2 = 'wallmounted'"); - warn_if_field_exists(L, index, "light_propagates", - "deprecated: determined from paramtype"); - warn_if_field_exists(L, index, "dug_item", - "deprecated: use 'drop' field"); - warn_if_field_exists(L, index, "extra_dug_item", - "deprecated: use 'drop' field"); - warn_if_field_exists(L, index, "extra_dug_item_rarity", - "deprecated: use 'drop' field"); - warn_if_field_exists(L, index, "metadata_name", - "deprecated: use on_add and metadata callbacks"); - - // True for all ground-like things like stone and mud, false for eg. trees - getboolfield(L, index, "is_ground_content", f.is_ground_content); - f.light_propagates = (f.param_type == CPT_LIGHT); - getboolfield(L, index, "sunlight_propagates", f.sunlight_propagates); - // This is used for collision detection. - // Also for general solidness queries. - getboolfield(L, index, "walkable", f.walkable); - // Player can point to these - getboolfield(L, index, "pointable", f.pointable); - // Player can dig these - getboolfield(L, index, "diggable", f.diggable); - // Player can climb these - getboolfield(L, index, "climbable", f.climbable); - // Player can build on these - getboolfield(L, index, "buildable_to", f.buildable_to); - // Whether the node is non-liquid, source liquid or flowing liquid - f.liquid_type = (LiquidType)getenumfield(L, index, "liquidtype", - es_LiquidType, LIQUID_NONE); - // If the content is liquid, this is the flowing version of the liquid. - getstringfield(L, index, "liquid_alternative_flowing", - f.liquid_alternative_flowing); - // If the content is liquid, this is the source version of the liquid. - getstringfield(L, index, "liquid_alternative_source", - f.liquid_alternative_source); - // Viscosity for fluid flow, ranging from 1 to 7, with - // 1 giving almost instantaneous propagation and 7 being - // the slowest possible - f.liquid_viscosity = getintfield_default(L, index, - "liquid_viscosity", f.liquid_viscosity); - getboolfield(L, index, "liquid_renewable", f.liquid_renewable); - // Amount of light the node emits - f.light_source = getintfield_default(L, index, - "light_source", f.light_source); - f.damage_per_second = getintfield_default(L, index, - "damage_per_second", f.damage_per_second); - - lua_getfield(L, index, "node_box"); - if(lua_istable(L, -1)) - f.node_box = read_nodebox(L, -1); - lua_pop(L, 1); - - lua_getfield(L, index, "selection_box"); - if(lua_istable(L, -1)) - f.selection_box = read_nodebox(L, -1); - lua_pop(L, 1); - - // Set to true if paramtype used to be 'facedir_simple' - getboolfield(L, index, "legacy_facedir_simple", f.legacy_facedir_simple); - // Set to true if wall_mounted used to be set to true - getboolfield(L, index, "legacy_wallmounted", f.legacy_wallmounted); - - // Sound table - lua_getfield(L, index, "sounds"); - if(lua_istable(L, -1)){ - lua_getfield(L, -1, "footstep"); - read_soundspec(L, -1, f.sound_footstep); - lua_pop(L, 1); - lua_getfield(L, -1, "dig"); - read_soundspec(L, -1, f.sound_dig); - lua_pop(L, 1); - lua_getfield(L, -1, "dug"); - read_soundspec(L, -1, f.sound_dug); - lua_pop(L, 1); - } - lua_pop(L, 1); - - return f; -} diff --git a/src/scriptapi_content.h b/src/scriptapi_content.h deleted file mode 100644 index 801f3856e..000000000 --- a/src/scriptapi_content.h +++ /dev/null @@ -1,37 +0,0 @@ -/* -Minetest-c55 -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 LUA_CONTENT_H_ -#define LUA_CONTENT_H_ - -extern "C" { -#include -} - -#include "nodedef.h" - -ContentFeatures read_content_features (lua_State *L, int index); -TileDef read_tiledef (lua_State *L, int index); -void read_soundspec (lua_State *L, int index, - SimpleSoundSpec &spec); -NodeBox read_nodebox (lua_State *L, int index); - -extern struct EnumString es_TileAnimationType[]; - -#endif /* LUA_CONTENT_H_ */ diff --git a/src/scriptapi_craft.cpp b/src/scriptapi_craft.cpp deleted file mode 100644 index 459908237..000000000 --- a/src/scriptapi_craft.cpp +++ /dev/null @@ -1,453 +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. -*/ - -#include "scriptapi.h" -#include "scriptapi_craft.h" - -extern "C" { -#include -} - -#include "script.h" -#include "scriptapi_types.h" -#include "scriptapi_common.h" -#include "scriptapi_item.h" - - -struct EnumString es_CraftMethod[] = -{ - {CRAFT_METHOD_NORMAL, "normal"}, - {CRAFT_METHOD_COOKING, "cooking"}, - {CRAFT_METHOD_FUEL, "fuel"}, - {0, NULL}, -}; - - -// helper for register_craft -bool read_craft_recipe_shaped(lua_State *L, int index, - int &width, std::vector &recipe) -{ - if(index < 0) - index = lua_gettop(L) + 1 + index; - - if(!lua_istable(L, index)) - return false; - - lua_pushnil(L); - int rowcount = 0; - while(lua_next(L, index) != 0){ - int colcount = 0; - // key at index -2 and value at index -1 - if(!lua_istable(L, -1)) - return false; - int table2 = lua_gettop(L); - lua_pushnil(L); - while(lua_next(L, table2) != 0){ - // key at index -2 and value at index -1 - if(!lua_isstring(L, -1)) - return false; - recipe.push_back(lua_tostring(L, -1)); - // removes value, keeps key for next iteration - lua_pop(L, 1); - colcount++; - } - if(rowcount == 0){ - width = colcount; - } else { - if(colcount != width) - return false; - } - // removes value, keeps key for next iteration - lua_pop(L, 1); - rowcount++; - } - return width != 0; -} - -// helper for register_craft -bool read_craft_recipe_shapeless(lua_State *L, int index, - std::vector &recipe) -{ - if(index < 0) - index = lua_gettop(L) + 1 + index; - - if(!lua_istable(L, index)) - return false; - - lua_pushnil(L); - while(lua_next(L, index) != 0){ - // key at index -2 and value at index -1 - if(!lua_isstring(L, -1)) - return false; - recipe.push_back(lua_tostring(L, -1)); - // removes value, keeps key for next iteration - lua_pop(L, 1); - } - return true; -} - -// helper for register_craft -bool read_craft_replacements(lua_State *L, int index, - CraftReplacements &replacements) -{ - if(index < 0) - index = lua_gettop(L) + 1 + index; - - if(!lua_istable(L, index)) - return false; - - lua_pushnil(L); - while(lua_next(L, index) != 0){ - // key at index -2 and value at index -1 - if(!lua_istable(L, -1)) - return false; - lua_rawgeti(L, -1, 1); - if(!lua_isstring(L, -1)) - return false; - std::string replace_from = lua_tostring(L, -1); - lua_pop(L, 1); - lua_rawgeti(L, -1, 2); - if(!lua_isstring(L, -1)) - return false; - std::string replace_to = lua_tostring(L, -1); - lua_pop(L, 1); - replacements.pairs.push_back( - std::make_pair(replace_from, replace_to)); - // removes value, keeps key for next iteration - lua_pop(L, 1); - } - return true; -} -// register_craft({output=item, recipe={{item00,item10},{item01,item11}}) -int l_register_craft(lua_State *L) -{ - //infostream<<"register_craft"<getWritableCraftDefManager(); - - std::string type = getstringfield_default(L, table, "type", "shaped"); - - /* - CraftDefinitionShaped - */ - if(type == "shaped"){ - std::string output = getstringfield_default(L, table, "output", ""); - if(output == "") - throw LuaError(L, "Crafting definition is missing an output"); - - int width = 0; - std::vector recipe; - lua_getfield(L, table, "recipe"); - if(lua_isnil(L, -1)) - throw LuaError(L, "Crafting definition is missing a recipe" - " (output=\"" + output + "\")"); - if(!read_craft_recipe_shaped(L, -1, width, recipe)) - throw LuaError(L, "Invalid crafting recipe" - " (output=\"" + output + "\")"); - - CraftReplacements replacements; - lua_getfield(L, table, "replacements"); - if(!lua_isnil(L, -1)) - { - if(!read_craft_replacements(L, -1, replacements)) - throw LuaError(L, "Invalid replacements" - " (output=\"" + output + "\")"); - } - - CraftDefinition *def = new CraftDefinitionShaped( - output, width, recipe, replacements); - craftdef->registerCraft(def); - } - /* - CraftDefinitionShapeless - */ - else if(type == "shapeless"){ - std::string output = getstringfield_default(L, table, "output", ""); - if(output == "") - throw LuaError(L, "Crafting definition (shapeless)" - " is missing an output"); - - std::vector recipe; - lua_getfield(L, table, "recipe"); - if(lua_isnil(L, -1)) - throw LuaError(L, "Crafting definition (shapeless)" - " is missing a recipe" - " (output=\"" + output + "\")"); - if(!read_craft_recipe_shapeless(L, -1, recipe)) - throw LuaError(L, "Invalid crafting recipe" - " (output=\"" + output + "\")"); - - CraftReplacements replacements; - lua_getfield(L, table, "replacements"); - if(!lua_isnil(L, -1)) - { - if(!read_craft_replacements(L, -1, replacements)) - throw LuaError(L, "Invalid replacements" - " (output=\"" + output + "\")"); - } - - CraftDefinition *def = new CraftDefinitionShapeless( - output, recipe, replacements); - craftdef->registerCraft(def); - } - /* - CraftDefinitionToolRepair - */ - else if(type == "toolrepair"){ - float additional_wear = getfloatfield_default(L, table, - "additional_wear", 0.0); - - CraftDefinition *def = new CraftDefinitionToolRepair( - additional_wear); - craftdef->registerCraft(def); - } - /* - CraftDefinitionCooking - */ - else if(type == "cooking"){ - std::string output = getstringfield_default(L, table, "output", ""); - if(output == "") - throw LuaError(L, "Crafting definition (cooking)" - " is missing an output"); - - std::string recipe = getstringfield_default(L, table, "recipe", ""); - if(recipe == "") - throw LuaError(L, "Crafting definition (cooking)" - " is missing a recipe" - " (output=\"" + output + "\")"); - - float cooktime = getfloatfield_default(L, table, "cooktime", 3.0); - - CraftReplacements replacements; - lua_getfield(L, table, "replacements"); - if(!lua_isnil(L, -1)) - { - if(!read_craft_replacements(L, -1, replacements)) - throw LuaError(L, "Invalid replacements" - " (cooking output=\"" + output + "\")"); - } - - CraftDefinition *def = new CraftDefinitionCooking( - output, recipe, cooktime, replacements); - craftdef->registerCraft(def); - } - /* - CraftDefinitionFuel - */ - else if(type == "fuel"){ - std::string recipe = getstringfield_default(L, table, "recipe", ""); - if(recipe == "") - throw LuaError(L, "Crafting definition (fuel)" - " is missing a recipe"); - - float burntime = getfloatfield_default(L, table, "burntime", 1.0); - - CraftReplacements replacements; - lua_getfield(L, table, "replacements"); - if(!lua_isnil(L, -1)) - { - if(!read_craft_replacements(L, -1, replacements)) - throw LuaError(L, "Invalid replacements" - " (fuel recipe=\"" + recipe + "\")"); - } - - CraftDefinition *def = new CraftDefinitionFuel( - recipe, burntime, replacements); - craftdef->registerCraft(def); - } - else - { - throw LuaError(L, "Unknown crafting definition type: \"" + type + "\""); - } - - lua_pop(L, 1); - return 0; /* number of results */ -} - -// get_craft_result(input) -int l_get_craft_result(lua_State *L) -{ - int input_i = 1; - std::string method_s = getstringfield_default(L, input_i, "method", "normal"); - enum CraftMethod method = (CraftMethod)getenumfield(L, input_i, "method", - es_CraftMethod, CRAFT_METHOD_NORMAL); - int width = 1; - lua_getfield(L, input_i, "width"); - if(lua_isnumber(L, -1)) - width = luaL_checkinteger(L, -1); - lua_pop(L, 1); - lua_getfield(L, input_i, "items"); - std::vector items = read_items(L, -1); - lua_pop(L, 1); // items - - IGameDef *gdef = get_server(L); - ICraftDefManager *cdef = gdef->cdef(); - CraftInput input(method, width, items); - CraftOutput output; - bool got = cdef->getCraftResult(input, output, true, gdef); - lua_newtable(L); // output table - if(got){ - ItemStack item; - item.deSerialize(output.item, gdef->idef()); - LuaItemStack::create(L, item); - lua_setfield(L, -2, "item"); - setintfield(L, -1, "time", output.time); - } else { - LuaItemStack::create(L, ItemStack()); - lua_setfield(L, -2, "item"); - setintfield(L, -1, "time", 0); - } - lua_newtable(L); // decremented input table - lua_pushstring(L, method_s.c_str()); - lua_setfield(L, -2, "method"); - lua_pushinteger(L, width); - lua_setfield(L, -2, "width"); - push_items(L, input.items); - lua_setfield(L, -2, "items"); - return 2; -} - -// get_craft_recipe(result item) -int l_get_craft_recipe(lua_State *L) -{ - int k = 1; - int input_i = 1; - std::string o_item = luaL_checkstring(L,input_i); - - IGameDef *gdef = get_server(L); - ICraftDefManager *cdef = gdef->cdef(); - CraftInput input; - CraftOutput output(o_item,0); - bool got = cdef->getCraftRecipe(input, output, gdef); - lua_newtable(L); // output table - if(got){ - lua_newtable(L); - for(std::vector::const_iterator - i = input.items.begin(); - i != input.items.end(); i++, k++) - { - if (i->empty()) - { - continue; - } - lua_pushinteger(L,k); - lua_pushstring(L,i->name.c_str()); - lua_settable(L, -3); - } - lua_setfield(L, -2, "items"); - setintfield(L, -1, "width", input.width); - switch (input.method) { - case CRAFT_METHOD_NORMAL: - lua_pushstring(L,"normal"); - break; - case CRAFT_METHOD_COOKING: - lua_pushstring(L,"cooking"); - break; - case CRAFT_METHOD_FUEL: - lua_pushstring(L,"fuel"); - break; - default: - lua_pushstring(L,"unknown"); - } - lua_setfield(L, -2, "type"); - } else { - lua_pushnil(L); - lua_setfield(L, -2, "items"); - setintfield(L, -1, "width", 0); - } - return 1; -} - -// get_all_craft_recipes(result item) -int l_get_all_craft_recipes(lua_State *L) -{ - std::string o_item = luaL_checkstring(L,1); - IGameDef *gdef = get_server(L); - ICraftDefManager *cdef = gdef->cdef(); - CraftInput input; - CraftOutput output(o_item,0); - std::vector recipes_list = cdef->getCraftRecipes(output, gdef); - if (recipes_list.empty()) - { - lua_pushnil(L); - return 1; - } - // Get the table insert function - 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::vector::const_iterator - i = recipes_list.begin(); - i != recipes_list.end(); i++) - { - CraftOutput tmpout; - tmpout.item = ""; - tmpout.time = 0; - CraftDefinition *def = *i; - tmpout = def->getOutput(input, gdef); - std::string query = tmpout.item; - char *fmtpos, *fmt = &query[0]; - if (strtok_r(fmt, " ", &fmtpos) == output.item) - { - input = def->getInput(output, gdef); - lua_pushvalue(L, table_insert); - lua_pushvalue(L, table); - lua_newtable(L); - int k = 1; - lua_newtable(L); - for(std::vector::const_iterator - i = input.items.begin(); - i != input.items.end(); i++, k++) - { - if (i->empty()) - continue; - lua_pushinteger(L, k); - lua_pushstring(L, i->name.c_str()); - lua_settable(L, -3); - } - lua_setfield(L, -2, "items"); - setintfield(L, -1, "width", input.width); - switch (input.method) { - case CRAFT_METHOD_NORMAL: - lua_pushstring(L,"normal"); - break; - case CRAFT_METHOD_COOKING: - lua_pushstring(L,"cooking"); - break; - case CRAFT_METHOD_FUEL: - lua_pushstring(L,"fuel"); - break; - default: - lua_pushstring(L,"unknown"); - } - lua_setfield(L, -2, "type"); - lua_pushstring(L, &tmpout.item[0]); - lua_setfield(L, -2, "output"); - if (lua_pcall(L, 2, 0, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); - } - } - return 1; -} diff --git a/src/scriptapi_craft.h b/src/scriptapi_craft.h deleted file mode 100644 index f28989fd9..000000000 --- a/src/scriptapi_craft.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -Minetest-c55 -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 LUA_CRAFT_H_ -#define LUA_CRAFT_H_ - -#include - -extern "C" { -#include -} - -#include "craftdef.h" - -/*****************************************************************************/ -/* Mod API */ -/*****************************************************************************/ -int l_register_craft(lua_State *L); -int l_get_craft_recipe(lua_State *L); -int l_get_all_craft_recipes(lua_State *L); -int l_get_craft_result(lua_State *L); - -/*****************************************************************************/ -/* scriptapi internal */ -/*****************************************************************************/ -bool read_craft_replacements(lua_State *L, int index, - CraftReplacements &replacements); -bool read_craft_recipe_shapeless(lua_State *L, int index, - std::vector &recipe); -bool read_craft_recipe_shaped(lua_State *L, int index, - int &width, std::vector &recipe); - -extern struct EnumString es_CraftMethod[]; - -#endif /* LUA_CRAFT_H_ */ diff --git a/src/scriptapi_entity.cpp b/src/scriptapi_entity.cpp deleted file mode 100644 index c15f801a6..000000000 --- a/src/scriptapi_entity.cpp +++ /dev/null @@ -1,293 +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. -*/ - -#include "scriptapi.h" -#include "scriptapi_entity.h" - -extern "C" { -#include -} - -#include "log.h" -#include "script.h" -#include "scriptapi_types.h" -#include "scriptapi_object.h" -#include "scriptapi_common.h" - - -void luaentity_get(lua_State *L, u16 id) -{ - // Get minetest.luaentities[i] - lua_getglobal(L, "minetest"); - lua_getfield(L, -1, "luaentities"); - luaL_checktype(L, -1, LUA_TTABLE); - lua_pushnumber(L, id); - lua_gettable(L, -2); - lua_remove(L, -2); // luaentities - lua_remove(L, -2); // minetest -} - -/* - luaentity -*/ - -bool scriptapi_luaentity_add(lua_State *L, u16 id, const char *name) -{ - realitycheck(L); - assert(lua_checkstack(L, 20)); - verbosestream<<"scriptapi_luaentity_add: id="<physical); - - getfloatfield(L, -1, "weight", prop->weight); - - lua_getfield(L, -1, "collisionbox"); - if(lua_istable(L, -1)) - prop->collisionbox = read_aabb3f(L, -1, 1.0); - lua_pop(L, 1); - - getstringfield(L, -1, "visual", prop->visual); - - getstringfield(L, -1, "mesh", prop->mesh); - - // Deprecated: read object properties directly - read_object_properties(L, -1, prop); - - // Read initial_properties - lua_getfield(L, -1, "initial_properties"); - read_object_properties(L, -1, prop); - lua_pop(L, 1); -} - -void scriptapi_luaentity_step(lua_State *L, u16 id, float dtime) -{ - realitycheck(L); - assert(lua_checkstack(L, 20)); - //infostream<<"scriptapi_luaentity_step: id="< - -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 LUA_ENTITY_H_ -#define LUA_ENTITY_H_ - -extern "C" { -#include -} - -#include "object_properties.h" -#include "content_sao.h" -#include "tool.h" - -/*****************************************************************************/ -/* scriptapi internal */ -/*****************************************************************************/ -void luaentity_get(lua_State *L, u16 id); - -/*****************************************************************************/ -/* Minetest interface */ -/*****************************************************************************/ -// Returns true if succesfully added into Lua; false otherwise. -bool scriptapi_luaentity_add(lua_State *L, u16 id, const char *name); -void scriptapi_luaentity_activate(lua_State *L, u16 id, - const std::string &staticdata, u32 dtime_s); -void scriptapi_luaentity_rm(lua_State *L, u16 id); -std::string scriptapi_luaentity_get_staticdata(lua_State *L, u16 id); -void scriptapi_luaentity_get_properties(lua_State *L, u16 id, - ObjectProperties *prop); -void scriptapi_luaentity_step(lua_State *L, u16 id, float dtime); -void scriptapi_luaentity_punch(lua_State *L, u16 id, - ServerActiveObject *puncher, float time_from_last_punch, - const ToolCapabilities *toolcap, v3f dir); -void scriptapi_luaentity_rightclick(lua_State *L, u16 id, - ServerActiveObject *clicker); - -#endif /* LUA_ENTITY_H_ */ diff --git a/src/scriptapi_env.cpp b/src/scriptapi_env.cpp deleted file mode 100644 index a9d9391a7..000000000 --- a/src/scriptapi_env.cpp +++ /dev/null @@ -1,975 +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. -*/ - -#include "scriptapi.h" -#include "scriptapi_env.h" -#include "nodedef.h" -#include "gamedef.h" -#include "map.h" -#include "daynightratio.h" -#include "content_sao.h" -#include "script.h" -#include "treegen.h" -#include "pathfinder.h" -#include "util/pointedthing.h" -#include "scriptapi_types.h" -#include "scriptapi_noise.h" -#include "scriptapi_nodemeta.h" -#include "scriptapi_nodetimer.h" -#include "scriptapi_object.h" -#include "scriptapi_common.h" -#include "scriptapi_item.h" -#include "scriptapi_node.h" - - -//TODO -extern void scriptapi_run_callbacks(lua_State *L, int nargs, - RunCallbacksMode mode); - - -class LuaABM : public ActiveBlockModifier -{ -private: - lua_State *m_lua; - int m_id; - - std::set m_trigger_contents; - std::set m_required_neighbors; - float m_trigger_interval; - u32 m_trigger_chance; -public: - LuaABM(lua_State *L, int id, - const std::set &trigger_contents, - const std::set &required_neighbors, - float trigger_interval, u32 trigger_chance): - m_lua(L), - m_id(id), - m_trigger_contents(trigger_contents), - m_required_neighbors(required_neighbors), - m_trigger_interval(trigger_interval), - m_trigger_chance(trigger_chance) - { - } - virtual std::set getTriggerContents() - { - return m_trigger_contents; - } - virtual std::set getRequiredNeighbors() - { - return m_required_neighbors; - } - virtual float getTriggerInterval() - { - return m_trigger_interval; - } - virtual u32 getTriggerChance() - { - return m_trigger_chance; - } - virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n, - u32 active_object_count, u32 active_object_count_wider) - { - lua_State *L = m_lua; - - realitycheck(L); - assert(lua_checkstack(L, 20)); - StackUnroller stack_unroller(L); - - // Get minetest.registered_abms - lua_getglobal(L, "minetest"); - lua_getfield(L, -1, "registered_abms"); - luaL_checktype(L, -1, LUA_TTABLE); - int registered_abms = lua_gettop(L); - - // Get minetest.registered_abms[m_id] - lua_pushnumber(L, m_id); - lua_gettable(L, registered_abms); - if(lua_isnil(L, -1)) - assert(0); - - // Call action - luaL_checktype(L, -1, LUA_TTABLE); - lua_getfield(L, -1, "action"); - luaL_checktype(L, -1, LUA_TFUNCTION); - push_v3s16(L, p); - pushnode(L, n, env->getGameDef()->ndef()); - lua_pushnumber(L, active_object_count); - lua_pushnumber(L, active_object_count_wider); - if(lua_pcall(L, 4, 0, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); - } -}; - -/* - EnvRef -*/ - -int EnvRef::gc_object(lua_State *L) { - EnvRef *o = *(EnvRef **)(lua_touserdata(L, 1)); - delete o; - return 0; -} - -EnvRef* EnvRef::checkobject(lua_State *L, int narg) -{ - luaL_checktype(L, narg, LUA_TUSERDATA); - void *ud = luaL_checkudata(L, narg, className); - if(!ud) luaL_typerror(L, narg, className); - return *(EnvRef**)ud; // unbox pointer -} - -// Exported functions - -// EnvRef:set_node(pos, node) -// pos = {x=num, y=num, z=num} -int EnvRef::l_set_node(lua_State *L) -{ - EnvRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - if(env == NULL) return 0; - INodeDefManager *ndef = env->getGameDef()->ndef(); - // parameters - v3s16 pos = read_v3s16(L, 2); - MapNode n = readnode(L, 3, ndef); - // Do it - bool succeeded = env->setNode(pos, n); - lua_pushboolean(L, succeeded); - return 1; -} - -int EnvRef::l_add_node(lua_State *L) -{ - return l_set_node(L); -} - -// EnvRef:remove_node(pos) -// pos = {x=num, y=num, z=num} -int EnvRef::l_remove_node(lua_State *L) -{ - EnvRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - if(env == NULL) return 0; - - // parameters - v3s16 pos = read_v3s16(L, 2); - // Do it - bool succeeded = env->removeNode(pos); - lua_pushboolean(L, succeeded); - return 1; -} - -// EnvRef:get_node(pos) -// pos = {x=num, y=num, z=num} -int EnvRef::l_get_node(lua_State *L) -{ - EnvRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - if(env == NULL) return 0; - // pos - v3s16 pos = read_v3s16(L, 2); - // Do it - MapNode n = env->getMap().getNodeNoEx(pos); - // Return node - pushnode(L, n, env->getGameDef()->ndef()); - return 1; -} - -// EnvRef:get_node_or_nil(pos) -// pos = {x=num, y=num, z=num} -int EnvRef::l_get_node_or_nil(lua_State *L) -{ - EnvRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - if(env == NULL) return 0; - // pos - v3s16 pos = read_v3s16(L, 2); - // Do it - try{ - MapNode n = env->getMap().getNode(pos); - // Return node - pushnode(L, n, env->getGameDef()->ndef()); - return 1; - } catch(InvalidPositionException &e) - { - lua_pushnil(L); - return 1; - } -} - -// EnvRef:get_node_light(pos, timeofday) -// pos = {x=num, y=num, z=num} -// timeofday: nil = current time, 0 = night, 0.5 = day -int EnvRef::l_get_node_light(lua_State *L) -{ - EnvRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - if(env == NULL) return 0; - // Do it - v3s16 pos = read_v3s16(L, 2); - u32 time_of_day = env->getTimeOfDay(); - if(lua_isnumber(L, 3)) - time_of_day = 24000.0 * lua_tonumber(L, 3); - time_of_day %= 24000; - u32 dnr = time_to_daynight_ratio(time_of_day, true); - try{ - MapNode n = env->getMap().getNode(pos); - INodeDefManager *ndef = env->getGameDef()->ndef(); - lua_pushinteger(L, n.getLightBlend(dnr, ndef)); - return 1; - } catch(InvalidPositionException &e) - { - lua_pushnil(L); - return 1; - } -} - -// EnvRef:place_node(pos, node) -// pos = {x=num, y=num, z=num} -int EnvRef::l_place_node(lua_State *L) -{ - EnvRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - if(env == NULL) return 0; - v3s16 pos = read_v3s16(L, 2); - MapNode n = readnode(L, 3, env->getGameDef()->ndef()); - - // Don't attempt to load non-loaded area as of now - MapNode n_old = env->getMap().getNodeNoEx(pos); - if(n_old.getContent() == CONTENT_IGNORE){ - lua_pushboolean(L, false); - return 1; - } - // Create item to place - INodeDefManager *ndef = get_server(L)->ndef(); - IItemDefManager *idef = get_server(L)->idef(); - ItemStack item(ndef->get(n).name, 1, 0, "", idef); - // Make pointed position - PointedThing pointed; - pointed.type = POINTEDTHING_NODE; - pointed.node_abovesurface = pos; - pointed.node_undersurface = pos + v3s16(0,-1,0); - // Place it with a NULL placer (appears in Lua as a non-functional - // ObjectRef) - bool success = scriptapi_item_on_place(L, item, NULL, pointed); - lua_pushboolean(L, success); - return 1; -} - -// EnvRef:dig_node(pos) -// pos = {x=num, y=num, z=num} -int EnvRef::l_dig_node(lua_State *L) -{ - EnvRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - if(env == NULL) return 0; - v3s16 pos = read_v3s16(L, 2); - - // Don't attempt to load non-loaded area as of now - MapNode n = env->getMap().getNodeNoEx(pos); - if(n.getContent() == CONTENT_IGNORE){ - lua_pushboolean(L, false); - return 1; - } - // Dig it out with a NULL digger (appears in Lua as a - // non-functional ObjectRef) - bool success = scriptapi_node_on_dig(L, pos, n, NULL); - lua_pushboolean(L, success); - return 1; -} - -// EnvRef:punch_node(pos) -// pos = {x=num, y=num, z=num} -int EnvRef::l_punch_node(lua_State *L) -{ - EnvRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - if(env == NULL) return 0; - v3s16 pos = read_v3s16(L, 2); - - // Don't attempt to load non-loaded area as of now - MapNode n = env->getMap().getNodeNoEx(pos); - if(n.getContent() == CONTENT_IGNORE){ - lua_pushboolean(L, false); - return 1; - } - // Punch it with a NULL puncher (appears in Lua as a non-functional - // ObjectRef) - bool success = scriptapi_node_on_punch(L, pos, n, NULL); - lua_pushboolean(L, success); - return 1; -} - -// EnvRef:get_meta(pos) -int EnvRef::l_get_meta(lua_State *L) -{ - //infostream<<"EnvRef::l_get_meta()"<m_env; - if(env == NULL) return 0; - // Do it - v3s16 p = read_v3s16(L, 2); - NodeMetaRef::create(L, p, env); - return 1; -} - -// EnvRef:get_node_timer(pos) -int EnvRef::l_get_node_timer(lua_State *L) -{ - EnvRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - if(env == NULL) return 0; - // Do it - v3s16 p = read_v3s16(L, 2); - NodeTimerRef::create(L, p, env); - return 1; -} - -// EnvRef:add_entity(pos, entityname) -> ObjectRef or nil -// pos = {x=num, y=num, z=num} -int EnvRef::l_add_entity(lua_State *L) -{ - //infostream<<"EnvRef::l_add_entity()"<m_env; - if(env == NULL) return 0; - // pos - v3f pos = checkFloatPos(L, 2); - // content - const char *name = luaL_checkstring(L, 3); - // Do it - ServerActiveObject *obj = new LuaEntitySAO(env, pos, name, ""); - int objectid = env->addActiveObject(obj); - // If failed to add, return nothing (reads as nil) - if(objectid == 0) - return 0; - // Return ObjectRef - objectref_get_or_create(L, obj); - return 1; -} - -// EnvRef:add_item(pos, itemstack or itemstring or table) -> ObjectRef or nil -// pos = {x=num, y=num, z=num} -int EnvRef::l_add_item(lua_State *L) -{ - //infostream<<"EnvRef::l_add_item()"<m_env; - if(env == NULL) return 0; - // pos - //v3f pos = checkFloatPos(L, 2); - // item - ItemStack item = read_item(L, 3); - if(item.empty() || !item.isKnown(get_server(L)->idef())) - return 0; - // Use minetest.spawn_item to spawn a __builtin:item - lua_getglobal(L, "minetest"); - lua_getfield(L, -1, "spawn_item"); - if(lua_isnil(L, -1)) - return 0; - lua_pushvalue(L, 2); - lua_pushstring(L, item.getItemString().c_str()); - if(lua_pcall(L, 2, 1, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); - return 1; - /*lua_pushvalue(L, 1); - lua_pushstring(L, "__builtin:item"); - lua_pushstring(L, item.getItemString().c_str()); - return l_add_entity(L);*/ - /*// Do it - ServerActiveObject *obj = createItemSAO(env, pos, item.getItemString()); - int objectid = env->addActiveObject(obj); - // If failed to add, return nothing (reads as nil) - if(objectid == 0) - return 0; - // Return ObjectRef - objectref_get_or_create(L, obj); - return 1;*/ -} - -// EnvRef:add_rat(pos) -// pos = {x=num, y=num, z=num} -int EnvRef::l_add_rat(lua_State *L) -{ - infostream<<"EnvRef::l_add_rat(): C++ mobs have been removed." - <<" Doing nothing."<m_env; - if(env == NULL) return 0; - // Do it - const char *name = luaL_checkstring(L, 2); - Player *player = env->getPlayer(name); - if(player == NULL){ - lua_pushnil(L); - return 1; - } - PlayerSAO *sao = player->getPlayerSAO(); - if(sao == NULL){ - lua_pushnil(L); - return 1; - } - // Put player on stack - objectref_get_or_create(L, sao); - return 1; -} - -// EnvRef:get_objects_inside_radius(pos, radius) -int EnvRef::l_get_objects_inside_radius(lua_State *L) -{ - // Get the table insert function - lua_getglobal(L, "table"); - lua_getfield(L, -1, "insert"); - int table_insert = lua_gettop(L); - // Get environemnt - EnvRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - if(env == NULL) return 0; - // Do it - v3f pos = checkFloatPos(L, 2); - float radius = luaL_checknumber(L, 3) * BS; - std::set ids = env->getObjectsInsideRadius(pos, radius); - lua_newtable(L); - int table = lua_gettop(L); - for(std::set::const_iterator - i = ids.begin(); i != ids.end(); i++){ - ServerActiveObject *obj = env->getActiveObject(*i); - // Insert object reference into table - lua_pushvalue(L, table_insert); - lua_pushvalue(L, table); - objectref_get_or_create(L, obj); - if(lua_pcall(L, 2, 0, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); - } - return 1; -} - -// EnvRef:set_timeofday(val) -// val = 0...1 -int EnvRef::l_set_timeofday(lua_State *L) -{ - EnvRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - if(env == NULL) return 0; - // Do it - float timeofday_f = luaL_checknumber(L, 2); - assert(timeofday_f >= 0.0 && timeofday_f <= 1.0); - int timeofday_mh = (int)(timeofday_f * 24000.0); - // This should be set directly in the environment but currently - // such changes aren't immediately sent to the clients, so call - // the server instead. - //env->setTimeOfDay(timeofday_mh); - get_server(L)->setTimeOfDay(timeofday_mh); - return 0; -} - -// EnvRef:get_timeofday() -> 0...1 -int EnvRef::l_get_timeofday(lua_State *L) -{ - EnvRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - if(env == NULL) return 0; - // Do it - int timeofday_mh = env->getTimeOfDay(); - float timeofday_f = (float)timeofday_mh / 24000.0; - lua_pushnumber(L, timeofday_f); - return 1; -} - - -// EnvRef:find_node_near(pos, radius, nodenames) -> pos or nil -// nodenames: eg. {"ignore", "group:tree"} or "default:dirt" -int EnvRef::l_find_node_near(lua_State *L) -{ - EnvRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - if(env == NULL) return 0; - INodeDefManager *ndef = get_server(L)->ndef(); - v3s16 pos = read_v3s16(L, 2); - int radius = luaL_checkinteger(L, 3); - std::set filter; - if(lua_istable(L, 4)){ - int table = 4; - lua_pushnil(L); - while(lua_next(L, table) != 0){ - // key at index -2 and value at index -1 - luaL_checktype(L, -1, LUA_TSTRING); - ndef->getIds(lua_tostring(L, -1), filter); - // removes value, keeps key for next iteration - lua_pop(L, 1); - } - } else if(lua_isstring(L, 4)){ - ndef->getIds(lua_tostring(L, 4), filter); - } - - for(int d=1; d<=radius; d++){ - std::list list; - getFacePositions(list, d); - for(std::list::iterator i = list.begin(); - i != list.end(); ++i){ - v3s16 p = pos + (*i); - content_t c = env->getMap().getNodeNoEx(p).getContent(); - if(filter.count(c) != 0){ - push_v3s16(L, p); - return 1; - } - } - } - return 0; -} - -// EnvRef:find_nodes_in_area(minp, maxp, nodenames) -> list of positions -// nodenames: eg. {"ignore", "group:tree"} or "default:dirt" -int EnvRef::l_find_nodes_in_area(lua_State *L) -{ - EnvRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - if(env == NULL) return 0; - INodeDefManager *ndef = get_server(L)->ndef(); - v3s16 minp = read_v3s16(L, 2); - v3s16 maxp = read_v3s16(L, 3); - std::set filter; - if(lua_istable(L, 4)){ - int table = 4; - lua_pushnil(L); - while(lua_next(L, table) != 0){ - // key at index -2 and value at index -1 - luaL_checktype(L, -1, LUA_TSTRING); - ndef->getIds(lua_tostring(L, -1), filter); - // removes value, keeps key for next iteration - lua_pop(L, 1); - } - } else if(lua_isstring(L, 4)){ - ndef->getIds(lua_tostring(L, 4), filter); - } - - // Get the table insert function - lua_getglobal(L, "table"); - lua_getfield(L, -1, "insert"); - int table_insert = lua_gettop(L); - - lua_newtable(L); - int table = lua_gettop(L); - for(s16 x=minp.X; x<=maxp.X; x++) - for(s16 y=minp.Y; y<=maxp.Y; y++) - for(s16 z=minp.Z; z<=maxp.Z; z++) - { - v3s16 p(x,y,z); - content_t c = env->getMap().getNodeNoEx(p).getContent(); - if(filter.count(c) != 0){ - lua_pushvalue(L, table_insert); - lua_pushvalue(L, table); - push_v3s16(L, p); - if(lua_pcall(L, 2, 0, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); - } - } - return 1; -} - -// EnvRef:get_perlin(seeddiff, octaves, persistence, scale) -// returns world-specific PerlinNoise -int EnvRef::l_get_perlin(lua_State *L) -{ - EnvRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - if(env == NULL) return 0; - - int seeddiff = luaL_checkint(L, 2); - int octaves = luaL_checkint(L, 3); - float persistence = luaL_checknumber(L, 4); - float scale = luaL_checknumber(L, 5); - - LuaPerlinNoise *n = new LuaPerlinNoise(seeddiff + int(env->getServerMap().getSeed()), octaves, persistence, scale); - *(void **)(lua_newuserdata(L, sizeof(void *))) = n; - luaL_getmetatable(L, "PerlinNoise"); - lua_setmetatable(L, -2); - return 1; -} - -// EnvRef:get_perlin_map(noiseparams, size) -// returns world-specific PerlinNoiseMap -int EnvRef::l_get_perlin_map(lua_State *L) -{ - EnvRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - if (env == NULL) - return 0; - - NoiseParams *np = read_noiseparams(L, 2); - if (!np) - return 0; - v3s16 size = read_v3s16(L, 3); - - int seed = (int)(env->getServerMap().getSeed()); - LuaPerlinNoiseMap *n = new LuaPerlinNoiseMap(np, seed, size); - *(void **)(lua_newuserdata(L, sizeof(void *))) = n; - luaL_getmetatable(L, "PerlinNoiseMap"); - lua_setmetatable(L, -2); - return 1; -} - -// EnvRef:clear_objects() -// clear all objects in the environment -int EnvRef::l_clear_objects(lua_State *L) -{ - EnvRef *o = checkobject(L, 1); - o->m_env->clearAllObjects(); - return 0; -} - -int EnvRef::l_line_of_sight(lua_State *L) { - float stepsize = 1.0; - - //infostream<<"EnvRef::l_get_node()"<m_env; - if(env == NULL) return 0; - - // read position 1 from lua - v3f pos1 = checkFloatPos(L, 2); - // read position 2 from lua - v3f pos2 = checkFloatPos(L, 2); - //read step size from lua - if(lua_isnumber(L, 3)) - stepsize = lua_tonumber(L, 3); - - lua_pushboolean(L, env->line_of_sight(pos1,pos2,stepsize)); - - return 1; -} - -int EnvRef::l_find_path(lua_State *L) -{ - EnvRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - - if(env == NULL) return 0; - - v3s16 pos1 = read_v3s16(L, 2); - v3s16 pos2 = read_v3s16(L, 3); - unsigned int searchdistance = luaL_checkint(L, 4); - unsigned int max_jump = luaL_checkint(L, 5); - unsigned int max_drop = luaL_checkint(L, 6); - algorithm algo = A_PLAIN_NP; - if(! lua_isnil(L, 7)) { - std::string algorithm = luaL_checkstring(L,7); - - if (algorithm == "A*") - algo = A_PLAIN; - - if (algorithm == "Dijkstra") - algo = DIJKSTRA; - } - - std::vector path = - get_Path(env,pos1,pos2,searchdistance,max_jump,max_drop,algo); - - if (path.size() > 0) - { - lua_newtable(L); - int top = lua_gettop(L); - unsigned int index = 1; - for (std::vector::iterator i = path.begin(); i != path.end();i++) - { - lua_pushnumber(L,index); - push_v3s16(L, *i); - lua_settable(L, top); - index++; - } - return 1; - } - - return 0; -} - -int EnvRef::l_spawn_tree(lua_State *L) -{ - EnvRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - if(env == NULL) return 0; - v3s16 p0 = read_v3s16(L, 2); - - treegen::TreeDef tree_def; - std::string trunk,leaves,fruit; - INodeDefManager *ndef = env->getGameDef()->ndef(); - - if(lua_istable(L, 3)) - { - getstringfield(L, 3, "axiom", tree_def.initial_axiom); - getstringfield(L, 3, "rules_a", tree_def.rules_a); - getstringfield(L, 3, "rules_b", tree_def.rules_b); - getstringfield(L, 3, "rules_c", tree_def.rules_c); - getstringfield(L, 3, "rules_d", tree_def.rules_d); - getstringfield(L, 3, "trunk", trunk); - tree_def.trunknode=ndef->getId(trunk); - getstringfield(L, 3, "leaves", leaves); - tree_def.leavesnode=ndef->getId(leaves); - tree_def.leaves2_chance=0; - getstringfield(L, 3, "leaves2", leaves); - if (leaves !="") - { - tree_def.leaves2node=ndef->getId(leaves); - getintfield(L, 3, "leaves2_chance", tree_def.leaves2_chance); - } - getintfield(L, 3, "angle", tree_def.angle); - getintfield(L, 3, "iterations", tree_def.iterations); - getintfield(L, 3, "random_level", tree_def.iterations_random_level); - getstringfield(L, 3, "trunk_type", tree_def.trunk_type); - getboolfield(L, 3, "thin_branches", tree_def.thin_branches); - tree_def.fruit_chance=0; - getstringfield(L, 3, "fruit", fruit); - if (fruit != "") - { - tree_def.fruitnode=ndef->getId(fruit); - getintfield(L, 3, "fruit_chance",tree_def.fruit_chance); - } - getintfield(L, 3, "seed", tree_def.seed); - } - else - return 0; - treegen::spawn_ltree (env, p0, ndef, tree_def); - return 1; -} - - -EnvRef::EnvRef(ServerEnvironment *env): - m_env(env) -{ - //infostream<<"EnvRef created"< trigger_contents; - lua_getfield(L, current_abm, "nodenames"); - if(lua_istable(L, -1)){ - int table = lua_gettop(L); - lua_pushnil(L); - while(lua_next(L, table) != 0){ - // key at index -2 and value at index -1 - luaL_checktype(L, -1, LUA_TSTRING); - trigger_contents.insert(lua_tostring(L, -1)); - // removes value, keeps key for next iteration - lua_pop(L, 1); - } - } else if(lua_isstring(L, -1)){ - trigger_contents.insert(lua_tostring(L, -1)); - } - lua_pop(L, 1); - - std::set required_neighbors; - lua_getfield(L, current_abm, "neighbors"); - if(lua_istable(L, -1)){ - int table = lua_gettop(L); - lua_pushnil(L); - while(lua_next(L, table) != 0){ - // key at index -2 and value at index -1 - luaL_checktype(L, -1, LUA_TSTRING); - required_neighbors.insert(lua_tostring(L, -1)); - // removes value, keeps key for next iteration - lua_pop(L, 1); - } - } else if(lua_isstring(L, -1)){ - required_neighbors.insert(lua_tostring(L, -1)); - } - lua_pop(L, 1); - - float trigger_interval = 10.0; - getfloatfield(L, current_abm, "interval", trigger_interval); - - int trigger_chance = 50; - getintfield(L, current_abm, "chance", trigger_chance); - - LuaABM *abm = new LuaABM(L, id, trigger_contents, - required_neighbors, trigger_interval, trigger_chance); - - env->addActiveBlockModifier(abm); - - // removes value, keeps key for next iteration - lua_pop(L, 1); - } - } - lua_pop(L, 1); -} diff --git a/src/scriptapi_env.h b/src/scriptapi_env.h deleted file mode 100644 index 2b7ea9573..000000000 --- a/src/scriptapi_env.h +++ /dev/null @@ -1,170 +0,0 @@ -/* -Minetest-c55 -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 LUA_ENVIRONMENT_H_ -#define LUA_ENVIRONMENT_H_ - -extern "C" { -#include -#include -} - -#include "environment.h" - -/* - EnvRef -*/ - -class EnvRef -{ -private: - ServerEnvironment *m_env; - - static const char className[]; - static const luaL_reg methods[]; - - static int gc_object(lua_State *L) ; - - static EnvRef *checkobject(lua_State *L, int narg); - - // Exported functions - - // EnvRef:set_node(pos, node) - // pos = {x=num, y=num, z=num} - static int l_set_node(lua_State *L); - - static int l_add_node(lua_State *L); - - // EnvRef:remove_node(pos) - // pos = {x=num, y=num, z=num} - static int l_remove_node(lua_State *L); - - // EnvRef:get_node(pos) - // pos = {x=num, y=num, z=num} - static int l_get_node(lua_State *L); - - // EnvRef:get_node_or_nil(pos) - // pos = {x=num, y=num, z=num} - static int l_get_node_or_nil(lua_State *L); - - // EnvRef:get_node_light(pos, timeofday) - // pos = {x=num, y=num, z=num} - // timeofday: nil = current time, 0 = night, 0.5 = day - static int l_get_node_light(lua_State *L); - - // EnvRef:place_node(pos, node) - // pos = {x=num, y=num, z=num} - static int l_place_node(lua_State *L); - - // EnvRef:dig_node(pos) - // pos = {x=num, y=num, z=num} - static int l_dig_node(lua_State *L); - - // EnvRef:punch_node(pos) - // pos = {x=num, y=num, z=num} - static int l_punch_node(lua_State *L); - - // EnvRef:get_meta(pos) - static int l_get_meta(lua_State *L); - - // EnvRef:get_node_timer(pos) - static int l_get_node_timer(lua_State *L); - - // EnvRef:add_entity(pos, entityname) -> ObjectRef or nil - // pos = {x=num, y=num, z=num} - static int l_add_entity(lua_State *L); - - // EnvRef:add_item(pos, itemstack or itemstring or table) -> ObjectRef or nil - // pos = {x=num, y=num, z=num} - static int l_add_item(lua_State *L); - - // EnvRef:add_rat(pos) - // pos = {x=num, y=num, z=num} - static int l_add_rat(lua_State *L); - - // EnvRef:add_firefly(pos) - // pos = {x=num, y=num, z=num} - static int l_add_firefly(lua_State *L); - - // EnvRef:get_player_by_name(name) - static int l_get_player_by_name(lua_State *L); - - // EnvRef:get_objects_inside_radius(pos, radius) - static int l_get_objects_inside_radius(lua_State *L); - - // EnvRef:set_timeofday(val) - // val = 0...1 - static int l_set_timeofday(lua_State *L); - - // EnvRef:get_timeofday() -> 0...1 - static int l_get_timeofday(lua_State *L); - - // EnvRef:find_node_near(pos, radius, nodenames) -> pos or nil - // nodenames: eg. {"ignore", "group:tree"} or "default:dirt" - static int l_find_node_near(lua_State *L); - - // EnvRef:find_nodes_in_area(minp, maxp, nodenames) -> list of positions - // nodenames: eg. {"ignore", "group:tree"} or "default:dirt" - static int l_find_nodes_in_area(lua_State *L); - - // EnvRef:get_perlin(seeddiff, octaves, persistence, scale) - // returns world-specific PerlinNoise - static int l_get_perlin(lua_State *L); - - // EnvRef:get_perlin_map(noiseparams, size) - // returns world-specific PerlinNoiseMap - static int l_get_perlin_map(lua_State *L); - - // EnvRef:clear_objects() - // clear all objects in the environment - static int l_clear_objects(lua_State *L); - - static int l_spawn_tree(lua_State *L); - - - static int l_line_of_sight(lua_State *L); - - //find a path between two positions - static int l_find_path(lua_State *L); - -public: - EnvRef(ServerEnvironment *env); - - ~EnvRef(); - - // Creates an EnvRef and leaves it on top of stack - // Not callable from Lua; all references are created on the C side. - static void create(lua_State *L, ServerEnvironment *env); - - static void set_null(lua_State *L); - - static void Register(lua_State *L); -}; - -/*****************************************************************************/ -/* Minetest interface */ -/*****************************************************************************/ -// On environment step -void scriptapi_environment_step(lua_State *L, float dtime); -// After generating a piece of map -void scriptapi_environment_on_generated(lua_State *L, v3s16 minp, v3s16 maxp, - u32 blockseed); -void scriptapi_add_environment(lua_State *L, ServerEnvironment *env); - -#endif /* LUA_ENVIRONMENT_H_ */ diff --git a/src/scriptapi_inventory.cpp b/src/scriptapi_inventory.cpp deleted file mode 100644 index bb40748db..000000000 --- a/src/scriptapi_inventory.cpp +++ /dev/null @@ -1,726 +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. -*/ - -#include "scriptapi.h" -#include "scriptapi_inventory.h" -#include "server.h" -#include "script.h" -#include "log.h" -#include "scriptapi_types.h" -#include "scriptapi_common.h" -#include "scriptapi_inventory.h" -#include "scriptapi_item.h" -#include "scriptapi_object.h" - - -/* - InvRef -*/ -InvRef* InvRef::checkobject(lua_State *L, int narg) -{ - luaL_checktype(L, narg, LUA_TUSERDATA); - void *ud = luaL_checkudata(L, narg, className); - if(!ud) luaL_typerror(L, narg, className); - return *(InvRef**)ud; // unbox pointer -} - -Inventory* InvRef::getinv(lua_State *L, InvRef *ref) -{ - return get_server(L)->getInventory(ref->m_loc); -} - -InventoryList* InvRef::getlist(lua_State *L, InvRef *ref, - const char *listname) -{ - Inventory *inv = getinv(L, ref); - if(!inv) - return NULL; - return inv->getList(listname); -} - -void InvRef::reportInventoryChange(lua_State *L, InvRef *ref) -{ - // Inform other things that the inventory has changed - get_server(L)->setInventoryModified(ref->m_loc); -} - -// Exported functions - -// garbage collector -int InvRef::gc_object(lua_State *L) { - InvRef *o = *(InvRef **)(lua_touserdata(L, 1)); - delete o; - return 0; -} - -// is_empty(self, listname) -> true/false -int InvRef::l_is_empty(lua_State *L) -{ - InvRef *ref = checkobject(L, 1); - const char *listname = luaL_checkstring(L, 2); - InventoryList *list = getlist(L, ref, listname); - if(list && list->getUsedSlots() > 0){ - lua_pushboolean(L, false); - } else { - lua_pushboolean(L, true); - } - return 1; -} - -// get_size(self, listname) -int InvRef::l_get_size(lua_State *L) -{ - InvRef *ref = checkobject(L, 1); - const char *listname = luaL_checkstring(L, 2); - InventoryList *list = getlist(L, ref, listname); - if(list){ - lua_pushinteger(L, list->getSize()); - } else { - lua_pushinteger(L, 0); - } - return 1; -} - -// get_width(self, listname) -int InvRef::l_get_width(lua_State *L) -{ - InvRef *ref = checkobject(L, 1); - const char *listname = luaL_checkstring(L, 2); - InventoryList *list = getlist(L, ref, listname); - if(list){ - lua_pushinteger(L, list->getWidth()); - } else { - lua_pushinteger(L, 0); - } - return 1; -} - -// set_size(self, listname, size) -int InvRef::l_set_size(lua_State *L) -{ - InvRef *ref = checkobject(L, 1); - const char *listname = luaL_checkstring(L, 2); - int newsize = luaL_checknumber(L, 3); - Inventory *inv = getinv(L, ref); - if(newsize == 0){ - inv->deleteList(listname); - reportInventoryChange(L, ref); - return 0; - } - InventoryList *list = inv->getList(listname); - if(list){ - list->setSize(newsize); - } else { - list = inv->addList(listname, newsize); - } - reportInventoryChange(L, ref); - return 0; -} - -// set_width(self, listname, size) -int InvRef::l_set_width(lua_State *L) -{ - InvRef *ref = checkobject(L, 1); - const char *listname = luaL_checkstring(L, 2); - int newwidth = luaL_checknumber(L, 3); - Inventory *inv = getinv(L, ref); - InventoryList *list = inv->getList(listname); - if(list){ - list->setWidth(newwidth); - } else { - return 0; - } - reportInventoryChange(L, ref); - return 0; -} - -// get_stack(self, listname, i) -> itemstack -int InvRef::l_get_stack(lua_State *L) -{ - InvRef *ref = checkobject(L, 1); - const char *listname = luaL_checkstring(L, 2); - int i = luaL_checknumber(L, 3) - 1; - InventoryList *list = getlist(L, ref, listname); - ItemStack item; - if(list != NULL && i >= 0 && i < (int) list->getSize()) - item = list->getItem(i); - LuaItemStack::create(L, item); - return 1; -} - -// set_stack(self, listname, i, stack) -> true/false -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); - InventoryList *list = getlist(L, ref, listname); - if(list != NULL && i >= 0 && i < (int) list->getSize()){ - list->changeItem(i, newitem); - reportInventoryChange(L, ref); - lua_pushboolean(L, true); - } else { - lua_pushboolean(L, false); - } - return 1; -} - -// get_list(self, listname) -> list or nil -int InvRef::l_get_list(lua_State *L) -{ - InvRef *ref = checkobject(L, 1); - const char *listname = luaL_checkstring(L, 2); - Inventory *inv = getinv(L, ref); - inventory_get_list_to_lua(inv, listname, L); - return 1; -} - -// set_list(self, listname, list) -int InvRef::l_set_list(lua_State *L) -{ - InvRef *ref = checkobject(L, 1); - const char *listname = luaL_checkstring(L, 2); - Inventory *inv = getinv(L, ref); - InventoryList *list = inv->getList(listname); - if(list) - inventory_set_list_from_lua(inv, listname, L, 3, - list->getSize()); - else - inventory_set_list_from_lua(inv, listname, L, 3); - reportInventoryChange(L, ref); - return 0; -} - -// add_item(self, listname, itemstack or itemstring or table or nil) -> itemstack -// Returns the leftover stack -int InvRef::l_add_item(lua_State *L) -{ - InvRef *ref = checkobject(L, 1); - const char *listname = luaL_checkstring(L, 2); - ItemStack item = read_item(L, 3); - InventoryList *list = getlist(L, ref, listname); - if(list){ - ItemStack leftover = list->addItem(item); - if(leftover.count != item.count) - reportInventoryChange(L, ref); - LuaItemStack::create(L, leftover); - } else { - LuaItemStack::create(L, item); - } - return 1; -} - -// room_for_item(self, listname, itemstack or itemstring or table or nil) -> true/false -// Returns true if the item completely fits into the list -int InvRef::l_room_for_item(lua_State *L) -{ - InvRef *ref = checkobject(L, 1); - const char *listname = luaL_checkstring(L, 2); - ItemStack item = read_item(L, 3); - InventoryList *list = getlist(L, ref, listname); - if(list){ - lua_pushboolean(L, list->roomForItem(item)); - } else { - lua_pushboolean(L, false); - } - return 1; -} - -// contains_item(self, listname, itemstack or itemstring or table or nil) -> true/false -// Returns true if the list contains the given count of the given item name -int InvRef::l_contains_item(lua_State *L) -{ - InvRef *ref = checkobject(L, 1); - const char *listname = luaL_checkstring(L, 2); - ItemStack item = read_item(L, 3); - InventoryList *list = getlist(L, ref, listname); - if(list){ - lua_pushboolean(L, list->containsItem(item)); - } else { - lua_pushboolean(L, false); - } - return 1; -} - -// remove_item(self, listname, itemstack or itemstring or table or nil) -> itemstack -// Returns the items that were actually removed -int InvRef::l_remove_item(lua_State *L) -{ - InvRef *ref = checkobject(L, 1); - const char *listname = luaL_checkstring(L, 2); - ItemStack item = read_item(L, 3); - InventoryList *list = getlist(L, ref, listname); - if(list){ - ItemStack removed = list->removeItem(item); - if(!removed.empty()) - reportInventoryChange(L, ref); - LuaItemStack::create(L, removed); - } else { - LuaItemStack::create(L, ItemStack()); - } - return 1; -} - -// get_location() -> location (like minetest.get_inventory(location)) -int InvRef::l_get_location(lua_State *L) -{ - InvRef *ref = checkobject(L, 1); - const InventoryLocation &loc = ref->m_loc; - switch(loc.type){ - case InventoryLocation::PLAYER: - lua_newtable(L); - lua_pushstring(L, "player"); - lua_setfield(L, -2, "type"); - lua_pushstring(L, loc.name.c_str()); - lua_setfield(L, -2, "name"); - return 1; - case InventoryLocation::NODEMETA: - lua_newtable(L); - lua_pushstring(L, "nodemeta"); - lua_setfield(L, -2, "type"); - push_v3s16(L, loc.p); - lua_setfield(L, -2, "name"); - return 1; - case InventoryLocation::DETACHED: - lua_newtable(L); - lua_pushstring(L, "detached"); - lua_setfield(L, -2, "type"); - lua_pushstring(L, loc.name.c_str()); - lua_setfield(L, -2, "name"); - return 1; - case InventoryLocation::UNDEFINED: - case InventoryLocation::CURRENT_PLAYER: - break; - } - lua_newtable(L); - lua_pushstring(L, "undefined"); - lua_setfield(L, -2, "type"); - return 1; -} - - -InvRef::InvRef(const InventoryLocation &loc): - m_loc(loc) -{ -} - -InvRef::~InvRef() -{ -} - -// Creates an InvRef and leaves it on top of stack -// Not callable from Lua; all references are created on the C side. -void InvRef::create(lua_State *L, const InventoryLocation &loc) -{ - InvRef *o = new InvRef(loc); - *(void **)(lua_newuserdata(L, sizeof(void *))) = o; - luaL_getmetatable(L, className); - lua_setmetatable(L, -2); -} -void InvRef::createPlayer(lua_State *L, Player *player) -{ - InventoryLocation loc; - loc.setPlayer(player->getName()); - create(L, loc); -} -void InvRef::createNodeMeta(lua_State *L, v3s16 p) -{ - InventoryLocation loc; - loc.setNodeMeta(p); - create(L, loc); -} - -void InvRef::Register(lua_State *L) -{ - lua_newtable(L); - int methodtable = lua_gettop(L); - luaL_newmetatable(L, className); - int metatable = lua_gettop(L); - - lua_pushliteral(L, "__metatable"); - lua_pushvalue(L, methodtable); - lua_settable(L, metatable); // hide metatable from Lua getmetatable() - - lua_pushliteral(L, "__index"); - lua_pushvalue(L, methodtable); - lua_settable(L, metatable); - - lua_pushliteral(L, "__gc"); - lua_pushcfunction(L, gc_object); - lua_settable(L, metatable); - - lua_pop(L, 1); // drop metatable - - luaL_openlib(L, 0, methods, 0); // fill methodtable - lua_pop(L, 1); // drop methodtable - - // Cannot be created from Lua - //lua_register(L, className, create_object); -} - -const char InvRef::className[] = "InvRef"; -const luaL_reg InvRef::methods[] = { - luamethod(InvRef, is_empty), - luamethod(InvRef, get_size), - luamethod(InvRef, set_size), - luamethod(InvRef, get_width), - luamethod(InvRef, set_width), - luamethod(InvRef, get_stack), - luamethod(InvRef, set_stack), - luamethod(InvRef, get_list), - luamethod(InvRef, set_list), - luamethod(InvRef, add_item), - luamethod(InvRef, room_for_item), - luamethod(InvRef, contains_item), - luamethod(InvRef, remove_item), - luamethod(InvRef, get_location), - {0,0} -}; - -void inventory_get_list_to_lua(Inventory *inv, const char *name, - lua_State *L) -{ - InventoryList *invlist = inv->getList(name); - if(invlist == NULL){ - lua_pushnil(L); - return; - } - std::vector items; - for(u32 i=0; igetSize(); i++) - items.push_back(invlist->getItem(i)); - push_items(L, items); -} - -void inventory_set_list_from_lua(Inventory *inv, const char *name, - lua_State *L, int tableindex, int forcesize) -{ - if(tableindex < 0) - tableindex = lua_gettop(L) + 1 + tableindex; - // If nil, delete list - if(lua_isnil(L, tableindex)){ - inv->deleteList(name); - return; - } - // Otherwise set list - std::vector items = read_items(L, tableindex); - int listsize = (forcesize != -1) ? forcesize : items.size(); - InventoryList *invlist = inv->addList(name, listsize); - int index = 0; - for(std::vector::const_iterator - i = items.begin(); i != items.end(); i++){ - if(forcesize != -1 && index == forcesize) - break; - invlist->changeItem(index, *i); - index++; - } - while(forcesize != -1 && index < forcesize){ - invlist->deleteItem(index); - index++; - } -} - -// get_inventory(location) -int l_get_inventory(lua_State *L) -{ - InventoryLocation loc; - - std::string type = checkstringfield(L, 1, "type"); - if(type == "player"){ - std::string name = checkstringfield(L, 1, "name"); - loc.setPlayer(name); - } else if(type == "node"){ - lua_getfield(L, 1, "pos"); - v3s16 pos = check_v3s16(L, -1); - loc.setNodeMeta(pos); - } else if(type == "detached"){ - std::string name = checkstringfield(L, 1, "name"); - loc.setDetached(name); - } - - if(get_server(L)->getInventory(loc) != NULL) - InvRef::create(L, loc); - else - lua_pushnil(L); - return 1; -} - -/* - Detached inventory callbacks -*/ - -// Retrieves minetest.detached_inventories[name][callbackname] -// If that is nil or on error, return false and stack is unchanged -// If that is a function, returns true and pushes the -// function onto the stack -static bool get_detached_inventory_callback(lua_State *L, - const std::string &name, const char *callbackname) -{ - lua_getglobal(L, "minetest"); - lua_getfield(L, -1, "detached_inventories"); - lua_remove(L, -2); - luaL_checktype(L, -1, LUA_TTABLE); - lua_getfield(L, -1, name.c_str()); - lua_remove(L, -2); - // Should be a table - if(lua_type(L, -1) != LUA_TTABLE) - { - errorstream<<"Item \""<createDetachedInventory(name) != NULL){ - InventoryLocation loc; - loc.setDetached(name); - InvRef::create(L, loc); - }else{ - lua_pushnil(L); - } - return 1; -} diff --git a/src/scriptapi_inventory.h b/src/scriptapi_inventory.h deleted file mode 100644 index 14f4fe026..000000000 --- a/src/scriptapi_inventory.h +++ /dev/null @@ -1,165 +0,0 @@ -/* -Minetest-c55 -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 LUA_INVENTORY_H_ -#define LUA_INVENTORY_H_ - -extern "C" { -#include -#include -} - -#include "inventorymanager.h" -#include "player.h" -#include "serverobject.h" -#include "inventory.h" - -/* - InvRef -*/ - -class InvRef -{ -private: - InventoryLocation m_loc; - - static const char className[]; - static const luaL_reg methods[]; - - static InvRef *checkobject(lua_State *L, int narg); - - static Inventory* getinv(lua_State *L, InvRef *ref); - - static InventoryList* getlist(lua_State *L, InvRef *ref, - const char *listname); - - static void reportInventoryChange(lua_State *L, InvRef *ref); - - // Exported functions - - // garbage collector - static int gc_object(lua_State *L); - - // is_empty(self, listname) -> true/false - static int l_is_empty(lua_State *L); - - // get_size(self, listname) - static int l_get_size(lua_State *L); - - // get_width(self, listname) - static int l_get_width(lua_State *L); - - // set_size(self, listname, size) - static int l_set_size(lua_State *L); - - // set_width(self, listname, size) - static int l_set_width(lua_State *L); - - // get_stack(self, listname, i) -> itemstack - static int l_get_stack(lua_State *L); - - // set_stack(self, listname, i, stack) -> true/false - static int l_set_stack(lua_State *L); - - // get_list(self, listname) -> list or nil - static int l_get_list(lua_State *L); - - // set_list(self, listname, list) - static int l_set_list(lua_State *L); - - // add_item(self, listname, itemstack or itemstring or table or nil) -> itemstack - // Returns the leftover stack - static int l_add_item(lua_State *L); - - // room_for_item(self, listname, itemstack or itemstring or table or nil) -> true/false - // Returns true if the item completely fits into the list - static int l_room_for_item(lua_State *L); - - // contains_item(self, listname, itemstack or itemstring or table or nil) -> true/false - // Returns true if the list contains the given count of the given item name - static int l_contains_item(lua_State *L); - - // remove_item(self, listname, itemstack or itemstring or table or nil) -> itemstack - // Returns the items that were actually removed - static int l_remove_item(lua_State *L); - - // get_location() -> location (like minetest.get_inventory(location)) - static int l_get_location(lua_State *L); - -public: - InvRef(const InventoryLocation &loc); - - ~InvRef(); - - // Creates an InvRef and leaves it on top of stack - // Not callable from Lua; all references are created on the C side. - static void create(lua_State *L, const InventoryLocation &loc); - static void createPlayer(lua_State *L, Player *player); - static void createNodeMeta(lua_State *L, v3s16 p); - static void Register(lua_State *L); -}; - -void inventory_get_list_to_lua(Inventory *inv, const char *name,lua_State *L); -void inventory_set_list_from_lua(Inventory *inv, const char *name, - lua_State *L, int tableindex, int forcesize=-1); - -/*****************************************************************************/ -/* Minetest interface */ -/*****************************************************************************/ -/* Detached inventory callbacks */ -// Return number of accepted items to be moved -int scriptapi_detached_inventory_allow_move(lua_State *L, - const std::string &name, - const std::string &from_list, int from_index, - const std::string &to_list, int to_index, - int count, ServerActiveObject *player); -// Return number of accepted items to be put -int scriptapi_detached_inventory_allow_put(lua_State *L, - const std::string &name, - const std::string &listname, int index, ItemStack &stack, - ServerActiveObject *player); -// Return number of accepted items to be taken -int scriptapi_detached_inventory_allow_take(lua_State *L, - const std::string &name, - const std::string &listname, int index, ItemStack &stack, - ServerActiveObject *player); -// Report moved items -void scriptapi_detached_inventory_on_move(lua_State *L, - const std::string &name, - const std::string &from_list, int from_index, - const std::string &to_list, int to_index, - int count, ServerActiveObject *player); -// Report put items -void scriptapi_detached_inventory_on_put(lua_State *L, - const std::string &name, - const std::string &listname, int index, ItemStack &stack, - ServerActiveObject *player); -// Report taken items -void scriptapi_detached_inventory_on_take(lua_State *L, - const std::string &name, - const std::string &listname, int index, ItemStack &stack, - ServerActiveObject *player); - -/*****************************************************************************/ -/* Mod API */ -/*****************************************************************************/ -int l_create_detached_inventory_raw(lua_State *L); -int l_get_inventory(lua_State *L); - -#endif /* LUA_INVENTORY_H_ */ diff --git a/src/scriptapi_item.cpp b/src/scriptapi_item.cpp deleted file mode 100644 index b266d856d..000000000 --- a/src/scriptapi_item.cpp +++ /dev/null @@ -1,718 +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. -*/ - -#include "scriptapi.h" -#include "server.h" -#include "script.h" -#include "tool.h" -#include "nodedef.h" -#include "util/pointedthing.h" -#include "scriptapi_item.h" -#include "scriptapi_types.h" -#include "scriptapi_common.h" -#include "scriptapi_object.h" -#include "scriptapi_content.h" - - -struct EnumString es_ItemType[] = -{ - {ITEM_NONE, "none"}, - {ITEM_NODE, "node"}, - {ITEM_CRAFT, "craft"}, - {ITEM_TOOL, "tool"}, - {0, NULL}, -}; - - -/* - ItemDefinition -*/ - -ItemDefinition read_item_definition(lua_State *L, int index, - ItemDefinition default_def) -{ - if(index < 0) - index = lua_gettop(L) + 1 + index; - - // Read the item definition - ItemDefinition def = default_def; - - def.type = (ItemType)getenumfield(L, index, "type", - es_ItemType, ITEM_NONE); - getstringfield(L, index, "name", def.name); - getstringfield(L, index, "description", def.description); - getstringfield(L, index, "inventory_image", def.inventory_image); - getstringfield(L, index, "wield_image", def.wield_image); - - lua_getfield(L, index, "wield_scale"); - if(lua_istable(L, -1)){ - def.wield_scale = check_v3f(L, -1); - } - lua_pop(L, 1); - - def.stack_max = getintfield_default(L, index, "stack_max", def.stack_max); - if(def.stack_max == 0) - def.stack_max = 1; - - lua_getfield(L, index, "on_use"); - def.usable = lua_isfunction(L, -1); - lua_pop(L, 1); - - getboolfield(L, index, "liquids_pointable", def.liquids_pointable); - - warn_if_field_exists(L, index, "tool_digging_properties", - "deprecated: use tool_capabilities"); - - lua_getfield(L, index, "tool_capabilities"); - if(lua_istable(L, -1)){ - def.tool_capabilities = new ToolCapabilities( - read_tool_capabilities(L, -1)); - } - - // If name is "" (hand), ensure there are ToolCapabilities - // because it will be looked up there whenever any other item has - // no ToolCapabilities - if(def.name == "" && def.tool_capabilities == NULL){ - def.tool_capabilities = new ToolCapabilities(); - } - - lua_getfield(L, index, "groups"); - read_groups(L, -1, def.groups); - lua_pop(L, 1); - - lua_getfield(L, index, "sounds"); - if(lua_istable(L, -1)){ - lua_getfield(L, -1, "place"); - read_soundspec(L, -1, def.sound_place); - lua_pop(L, 1); - } - lua_pop(L, 1); - - // Client shall immediately place this node when player places the item. - // Server will update the precise end result a moment later. - // "" = no prediction - getstringfield(L, index, "node_placement_prediction", - def.node_placement_prediction); - - return def; -} - -// register_item_raw({lots of stuff}) -int l_register_item_raw(lua_State *L) -{ - luaL_checktype(L, 1, LUA_TTABLE); - int table = 1; - - // Get the writable item and node definition managers from the server - IWritableItemDefManager *idef = - get_server(L)->getWritableItemDefManager(); - IWritableNodeDefManager *ndef = - get_server(L)->getWritableNodeDefManager(); - - // Check if name is defined - std::string name; - lua_getfield(L, table, "name"); - if(lua_isstring(L, -1)){ - name = lua_tostring(L, -1); - verbosestream<<"register_item_raw: "<registerItem(def); - - // Read the node definition (content features) and register it - if(def.type == ITEM_NODE) - { - ContentFeatures f = read_content_features(L, table); - ndef->set(f.name, f); - } - - return 0; /* number of results */ -} - -// register_alias_raw(name, convert_to_name) -int l_register_alias_raw(lua_State *L) -{ - std::string name = luaL_checkstring(L, 1); - std::string convert_to = luaL_checkstring(L, 2); - - // Get the writable item definition manager from the server - IWritableItemDefManager *idef = - get_server(L)->getWritableItemDefManager(); - - idef->registerAlias(name, convert_to); - - return 0; /* number of results */ -} - -// Retrieves minetest.registered_items[name][callbackname] -// If that is nil or on error, return false and stack is unchanged -// If that is a function, returns true and pushes the -// function onto the stack -// If minetest.registered_items[name] doesn't exist, minetest.nodedef_default -// is tried instead so unknown items can still be manipulated to some degree -bool get_item_callback(lua_State *L, - const char *name, const char *callbackname) -{ - lua_getglobal(L, "minetest"); - lua_getfield(L, -1, "registered_items"); - lua_remove(L, -2); - luaL_checktype(L, -1, LUA_TTABLE); - lua_getfield(L, -1, name); - lua_remove(L, -2); - // Should be a table - if(lua_type(L, -1) != LUA_TTABLE) - { - // Report error and clean up - errorstream<<"Item \""< true/false -int LuaItemStack::l_is_empty(lua_State *L) -{ - LuaItemStack *o = checkobject(L, 1); - ItemStack &item = o->m_stack; - lua_pushboolean(L, item.empty()); - return 1; -} - -// get_name(self) -> string -int LuaItemStack::l_get_name(lua_State *L) -{ - LuaItemStack *o = checkobject(L, 1); - ItemStack &item = o->m_stack; - lua_pushstring(L, item.name.c_str()); - return 1; -} - -// get_count(self) -> number -int LuaItemStack::l_get_count(lua_State *L) -{ - LuaItemStack *o = checkobject(L, 1); - ItemStack &item = o->m_stack; - lua_pushinteger(L, item.count); - return 1; -} - -// get_wear(self) -> number -int LuaItemStack::l_get_wear(lua_State *L) -{ - LuaItemStack *o = checkobject(L, 1); - ItemStack &item = o->m_stack; - lua_pushinteger(L, item.wear); - return 1; -} - -// get_metadata(self) -> string -int LuaItemStack::l_get_metadata(lua_State *L) -{ - LuaItemStack *o = checkobject(L, 1); - ItemStack &item = o->m_stack; - lua_pushlstring(L, item.metadata.c_str(), item.metadata.size()); - return 1; -} - -// clear(self) -> true -int LuaItemStack::l_clear(lua_State *L) -{ - LuaItemStack *o = checkobject(L, 1); - o->m_stack.clear(); - lua_pushboolean(L, true); - return 1; -} - -// replace(self, itemstack or itemstring or table or nil) -> true -int LuaItemStack::l_replace(lua_State *L) -{ - LuaItemStack *o = checkobject(L, 1); - o->m_stack = read_item(L, 2); - lua_pushboolean(L, true); - return 1; -} - -// to_string(self) -> string -int LuaItemStack::l_to_string(lua_State *L) -{ - LuaItemStack *o = checkobject(L, 1); - std::string itemstring = o->m_stack.getItemString(); - lua_pushstring(L, itemstring.c_str()); - return 1; -} - -// to_table(self) -> table or nil -int LuaItemStack::l_to_table(lua_State *L) -{ - LuaItemStack *o = checkobject(L, 1); - const ItemStack &item = o->m_stack; - if(item.empty()) - { - lua_pushnil(L); - } - else - { - lua_newtable(L); - lua_pushstring(L, item.name.c_str()); - lua_setfield(L, -2, "name"); - lua_pushinteger(L, item.count); - lua_setfield(L, -2, "count"); - lua_pushinteger(L, item.wear); - lua_setfield(L, -2, "wear"); - lua_pushlstring(L, item.metadata.c_str(), item.metadata.size()); - lua_setfield(L, -2, "metadata"); - } - return 1; -} - -// get_stack_max(self) -> number -int LuaItemStack::l_get_stack_max(lua_State *L) -{ - LuaItemStack *o = checkobject(L, 1); - ItemStack &item = o->m_stack; - lua_pushinteger(L, item.getStackMax(get_server(L)->idef())); - return 1; -} - -// get_free_space(self) -> number -int LuaItemStack::l_get_free_space(lua_State *L) -{ - LuaItemStack *o = checkobject(L, 1); - ItemStack &item = o->m_stack; - lua_pushinteger(L, item.freeSpace(get_server(L)->idef())); - return 1; -} - -// is_known(self) -> true/false -// Checks if the item is defined. -int LuaItemStack::l_is_known(lua_State *L) -{ - LuaItemStack *o = checkobject(L, 1); - ItemStack &item = o->m_stack; - bool is_known = item.isKnown(get_server(L)->idef()); - lua_pushboolean(L, is_known); - return 1; -} - -// get_definition(self) -> table -// Returns the item definition table from minetest.registered_items, -// or a fallback one (name="unknown") -int LuaItemStack::l_get_definition(lua_State *L) -{ - LuaItemStack *o = checkobject(L, 1); - ItemStack &item = o->m_stack; - - // Get minetest.registered_items[name] - lua_getglobal(L, "minetest"); - lua_getfield(L, -1, "registered_items"); - luaL_checktype(L, -1, LUA_TTABLE); - lua_getfield(L, -1, item.name.c_str()); - if(lua_isnil(L, -1)) - { - lua_pop(L, 1); - lua_getfield(L, -1, "unknown"); - } - return 1; -} - -// get_tool_capabilities(self) -> table -// Returns the effective tool digging properties. -// Returns those of the hand ("") if this item has none associated. -int LuaItemStack::l_get_tool_capabilities(lua_State *L) -{ - LuaItemStack *o = checkobject(L, 1); - ItemStack &item = o->m_stack; - const ToolCapabilities &prop = - item.getToolCapabilities(get_server(L)->idef()); - push_tool_capabilities(L, prop); - return 1; -} - -// add_wear(self, amount) -> true/false -// The range for "amount" is [0,65535]. Wear is only added if the item -// is a tool. Adding wear might destroy the item. -// Returns true if the item is (or was) a tool. -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, get_server(L)->idef()); - lua_pushboolean(L, result); - return 1; -} - -// add_item(self, itemstack or itemstring or table or nil) -> itemstack -// Returns leftover item stack -int LuaItemStack::l_add_item(lua_State *L) -{ - LuaItemStack *o = checkobject(L, 1); - ItemStack &item = o->m_stack; - ItemStack newitem = read_item(L, 2); - ItemStack leftover = item.addItem(newitem, get_server(L)->idef()); - create(L, leftover); - return 1; -} - -// item_fits(self, itemstack or itemstring or table or nil) -> true/false, itemstack -// First return value is true iff the new item fits fully into the stack -// Second return value is the would-be-left-over item stack -int LuaItemStack::l_item_fits(lua_State *L) -{ - LuaItemStack *o = checkobject(L, 1); - ItemStack &item = o->m_stack; - ItemStack newitem = read_item(L, 2); - ItemStack restitem; - bool fits = item.itemFits(newitem, &restitem, get_server(L)->idef()); - lua_pushboolean(L, fits); // first return value - create(L, restitem); // second return value - return 2; -} - -// take_item(self, takecount=1) -> itemstack -int LuaItemStack::l_take_item(lua_State *L) -{ - LuaItemStack *o = checkobject(L, 1); - ItemStack &item = o->m_stack; - u32 takecount = 1; - if(!lua_isnone(L, 2)) - takecount = luaL_checkinteger(L, 2); - ItemStack taken = item.takeItem(takecount); - create(L, taken); - return 1; -} - -// peek_item(self, peekcount=1) -> itemstack -int LuaItemStack::l_peek_item(lua_State *L) -{ - LuaItemStack *o = checkobject(L, 1); - ItemStack &item = o->m_stack; - u32 peekcount = 1; - if(!lua_isnone(L, 2)) - peekcount = lua_tointeger(L, 2); - ItemStack peekaboo = item.peekItem(peekcount); - create(L, peekaboo); - return 1; -} - -LuaItemStack::LuaItemStack(const ItemStack &item): - m_stack(item) -{ -} - -LuaItemStack::~LuaItemStack() -{ -} - -const ItemStack& LuaItemStack::getItem() const -{ - return m_stack; -} -ItemStack& LuaItemStack::getItem() -{ - return m_stack; -} - -// LuaItemStack(itemstack or itemstring or table or nil) -// Creates an LuaItemStack and leaves it on top of stack -int LuaItemStack::create_object(lua_State *L) -{ - ItemStack item = read_item(L, 1); - LuaItemStack *o = new LuaItemStack(item); - *(void **)(lua_newuserdata(L, sizeof(void *))) = o; - luaL_getmetatable(L, className); - lua_setmetatable(L, -2); - return 1; -} -// Not callable from Lua -int LuaItemStack::create(lua_State *L, const ItemStack &item) -{ - LuaItemStack *o = new LuaItemStack(item); - *(void **)(lua_newuserdata(L, sizeof(void *))) = o; - luaL_getmetatable(L, className); - lua_setmetatable(L, -2); - return 1; -} - -LuaItemStack* LuaItemStack::checkobject(lua_State *L, int narg) -{ - luaL_checktype(L, narg, LUA_TUSERDATA); - void *ud = luaL_checkudata(L, narg, className); - if(!ud) luaL_typerror(L, narg, className); - return *(LuaItemStack**)ud; // unbox pointer -} - -void LuaItemStack::Register(lua_State *L) -{ - lua_newtable(L); - int methodtable = lua_gettop(L); - luaL_newmetatable(L, className); - int metatable = lua_gettop(L); - - lua_pushliteral(L, "__metatable"); - lua_pushvalue(L, methodtable); - lua_settable(L, metatable); // hide metatable from Lua getmetatable() - - lua_pushliteral(L, "__index"); - lua_pushvalue(L, methodtable); - lua_settable(L, metatable); - - lua_pushliteral(L, "__gc"); - lua_pushcfunction(L, gc_object); - lua_settable(L, metatable); - - lua_pop(L, 1); // drop metatable - - luaL_openlib(L, 0, methods, 0); // fill methodtable - lua_pop(L, 1); // drop methodtable - - // Can be created from Lua (LuaItemStack(itemstack or itemstring or table or nil)) - lua_register(L, className, create_object); -} - -const char LuaItemStack::className[] = "ItemStack"; -const luaL_reg LuaItemStack::methods[] = { - luamethod(LuaItemStack, is_empty), - luamethod(LuaItemStack, get_name), - luamethod(LuaItemStack, get_count), - luamethod(LuaItemStack, get_wear), - luamethod(LuaItemStack, get_metadata), - luamethod(LuaItemStack, clear), - luamethod(LuaItemStack, replace), - luamethod(LuaItemStack, to_string), - luamethod(LuaItemStack, to_table), - luamethod(LuaItemStack, get_stack_max), - luamethod(LuaItemStack, get_free_space), - luamethod(LuaItemStack, is_known), - luamethod(LuaItemStack, get_definition), - luamethod(LuaItemStack, get_tool_capabilities), - luamethod(LuaItemStack, add_wear), - luamethod(LuaItemStack, add_item), - luamethod(LuaItemStack, item_fits), - luamethod(LuaItemStack, take_item), - luamethod(LuaItemStack, peek_item), - {0,0} -}; - -ItemStack read_item(lua_State *L, int index) -{ - if(index < 0) - index = lua_gettop(L) + 1 + index; - - if(lua_isnil(L, index)) - { - return ItemStack(); - } - else if(lua_isuserdata(L, index)) - { - // Convert from LuaItemStack - LuaItemStack *o = LuaItemStack::checkobject(L, index); - return o->getItem(); - } - else if(lua_isstring(L, index)) - { - // Convert from itemstring - std::string itemstring = lua_tostring(L, index); - IItemDefManager *idef = get_server(L)->idef(); - try - { - ItemStack item; - item.deSerialize(itemstring, idef); - return item; - } - catch(SerializationError &e) - { - infostream<<"WARNING: unable to create item from itemstring" - <<": "<idef(); - std::string name = getstringfield_default(L, index, "name", ""); - int count = getintfield_default(L, index, "count", 1); - int wear = getintfield_default(L, index, "wear", 0); - std::string metadata = getstringfield_default(L, index, "metadata", ""); - return ItemStack(name, count, wear, metadata, idef); - } - else - { - throw LuaError(L, "Expecting itemstack, itemstring, table or nil"); - } -} - -std::vector read_items(lua_State *L, int index) -{ - if(index < 0) - index = lua_gettop(L) + 1 + index; - - std::vector items; - luaL_checktype(L, index, LUA_TTABLE); - lua_pushnil(L); - while(lua_next(L, index) != 0){ - // key at index -2 and value at index -1 - items.push_back(read_item(L, -1)); - // removes value, keeps key for next iteration - lua_pop(L, 1); - } - return items; -} - -// creates a table of ItemStacks -void push_items(lua_State *L, const std::vector &items) -{ - // Get the table insert function - lua_getglobal(L, "table"); - lua_getfield(L, -1, "insert"); - int table_insert = lua_gettop(L); - // Create and fill table - lua_newtable(L); - int table = lua_gettop(L); - for(u32 i=0; i - -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 LUA_ITEM_H_ -#define LUA_ITEM_H_ - -extern "C" { -#include -#include -} - -#include - -#include "itemdef.h" -#include "content_sao.h" -#include "util/pointedthing.h" -#include "inventory.h" - -#include "inventory.h" - -ItemStack read_item(lua_State *L, int index); -std::vector read_items(lua_State *L, int index); -void push_items(lua_State *L, const std::vector &items); - -class LuaItemStack -{ -private: - ItemStack m_stack; - - static const char className[]; - static const luaL_reg methods[]; - - // Exported functions - - // garbage collector - static int gc_object(lua_State *L); - - // is_empty(self) -> true/false - static int l_is_empty(lua_State *L); - - // get_name(self) -> string - static int l_get_name(lua_State *L); - - // get_count(self) -> number - static int l_get_count(lua_State *L); - - // get_wear(self) -> number - static int l_get_wear(lua_State *L); - - // get_metadata(self) -> string - static int l_get_metadata(lua_State *L); - - // clear(self) -> true - static int l_clear(lua_State *L); - - // replace(self, itemstack or itemstring or table or nil) -> true - static int l_replace(lua_State *L); - - // to_string(self) -> string - static int l_to_string(lua_State *L); - - // to_table(self) -> table or nil - static int l_to_table(lua_State *L); - - // get_stack_max(self) -> number - static int l_get_stack_max(lua_State *L); - - // get_free_space(self) -> number - static int l_get_free_space(lua_State *L); - - // is_known(self) -> true/false - // Checks if the item is defined. - static int l_is_known(lua_State *L); - - // get_definition(self) -> table - // Returns the item definition table from minetest.registered_items, - // or a fallback one (name="unknown") - static int l_get_definition(lua_State *L); - - // get_tool_capabilities(self) -> table - // Returns the effective tool digging properties. - // Returns those of the hand ("") if this item has none associated. - static int l_get_tool_capabilities(lua_State *L); - - // add_wear(self, amount) -> true/false - // The range for "amount" is [0,65535]. Wear is only added if the item - // is a tool. Adding wear might destroy the item. - // Returns true if the item is (or was) a tool. - static int l_add_wear(lua_State *L); - - // add_item(self, itemstack or itemstring or table or nil) -> itemstack - // Returns leftover item stack - static int l_add_item(lua_State *L); - - // item_fits(self, itemstack or itemstring or table or nil) -> true/false, itemstack - // First return value is true iff the new item fits fully into the stack - // Second return value is the would-be-left-over item stack - static int l_item_fits(lua_State *L); - - // take_item(self, takecount=1) -> itemstack - static int l_take_item(lua_State *L); - - // peek_item(self, peekcount=1) -> itemstack - static int l_peek_item(lua_State *L); - -public: - LuaItemStack(const ItemStack &item); - ~LuaItemStack(); - - const ItemStack& getItem() const; - ItemStack& getItem(); - - // LuaItemStack(itemstack or itemstring or table or nil) - // Creates an LuaItemStack and leaves it on top of stack - static int create_object(lua_State *L); - // Not callable from Lua - static int create(lua_State *L, const ItemStack &item); - static LuaItemStack* checkobject(lua_State *L, int narg); - static void Register(lua_State *L); - -}; - -/*****************************************************************************/ -/* Mod API */ -/*****************************************************************************/ -int l_register_item_raw(lua_State *L); -int l_register_alias_raw(lua_State *L); - -/*****************************************************************************/ -/* scriptapi internal */ -/*****************************************************************************/ -bool get_item_callback(lua_State *L, - const char *name, const char *callbackname); -ItemDefinition read_item_definition(lua_State *L, int index, - ItemDefinition default_def = ItemDefinition()); - -extern struct EnumString es_ItemType[]; - -/*****************************************************************************/ -/* Minetest interface */ -/*****************************************************************************/ -bool scriptapi_item_on_drop(lua_State *L, ItemStack &item, - ServerActiveObject *dropper, v3f pos); -bool scriptapi_item_on_place(lua_State *L, ItemStack &item, - ServerActiveObject *placer, const PointedThing &pointed); -bool scriptapi_item_on_use(lua_State *L, ItemStack &item, - ServerActiveObject *user, const PointedThing &pointed); - - -#endif /* LUA_ITEM_H_ */ diff --git a/src/scriptapi_node.cpp b/src/scriptapi_node.cpp deleted file mode 100644 index 2fea50fa1..000000000 --- a/src/scriptapi_node.cpp +++ /dev/null @@ -1,244 +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. -*/ - -#include "scriptapi.h" -#include "scriptapi_node.h" -#include "util/pointedthing.h" -#include "script.h" -#include "scriptapi_common.h" -#include "scriptapi_types.h" -#include "scriptapi_item.h" -#include "scriptapi_object.h" - - -struct EnumString es_DrawType[] = -{ - {NDT_NORMAL, "normal"}, - {NDT_AIRLIKE, "airlike"}, - {NDT_LIQUID, "liquid"}, - {NDT_FLOWINGLIQUID, "flowingliquid"}, - {NDT_GLASSLIKE, "glasslike"}, - {NDT_GLASSLIKE_FRAMED, "glasslike_framed"}, - {NDT_ALLFACES, "allfaces"}, - {NDT_ALLFACES_OPTIONAL, "allfaces_optional"}, - {NDT_TORCHLIKE, "torchlike"}, - {NDT_SIGNLIKE, "signlike"}, - {NDT_PLANTLIKE, "plantlike"}, - {NDT_FENCELIKE, "fencelike"}, - {NDT_RAILLIKE, "raillike"}, - {NDT_NODEBOX, "nodebox"}, - {0, NULL}, -}; - -struct EnumString es_ContentParamType[] = -{ - {CPT_NONE, "none"}, - {CPT_LIGHT, "light"}, - {0, NULL}, -}; - -struct EnumString es_ContentParamType2[] = -{ - {CPT2_NONE, "none"}, - {CPT2_FULL, "full"}, - {CPT2_FLOWINGLIQUID, "flowingliquid"}, - {CPT2_FACEDIR, "facedir"}, - {CPT2_WALLMOUNTED, "wallmounted"}, - {0, NULL}, -}; - -struct EnumString es_LiquidType[] = -{ - {LIQUID_NONE, "none"}, - {LIQUID_FLOWING, "flowing"}, - {LIQUID_SOURCE, "source"}, - {0, NULL}, -}; - -struct EnumString es_NodeBoxType[] = -{ - {NODEBOX_REGULAR, "regular"}, - {NODEBOX_FIXED, "fixed"}, - {NODEBOX_WALLMOUNTED, "wallmounted"}, - {0, NULL}, -}; - - -bool scriptapi_node_on_punch(lua_State *L, v3s16 p, MapNode node, - ServerActiveObject *puncher) -{ - realitycheck(L); - assert(lua_checkstack(L, 20)); - StackUnroller stack_unroller(L); - - INodeDefManager *ndef = get_server(L)->ndef(); - - // Push callback function on stack - if(!get_item_callback(L, ndef->get(node).name.c_str(), "on_punch")) - return false; - - // Call function - push_v3s16(L, p); - pushnode(L, node, ndef); - objectref_get_or_create(L, puncher); - if(lua_pcall(L, 3, 0, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); - return true; -} - -bool scriptapi_node_on_dig(lua_State *L, v3s16 p, MapNode node, - ServerActiveObject *digger) -{ - realitycheck(L); - assert(lua_checkstack(L, 20)); - StackUnroller stack_unroller(L); - - INodeDefManager *ndef = get_server(L)->ndef(); - - // Push callback function on stack - if(!get_item_callback(L, ndef->get(node).name.c_str(), "on_dig")) - return false; - - // Call function - push_v3s16(L, p); - pushnode(L, node, ndef); - objectref_get_or_create(L, digger); - if(lua_pcall(L, 3, 0, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); - return true; -} - -void scriptapi_node_on_construct(lua_State *L, v3s16 p, MapNode node) -{ - realitycheck(L); - assert(lua_checkstack(L, 20)); - StackUnroller stack_unroller(L); - - INodeDefManager *ndef = get_server(L)->ndef(); - - // Push callback function on stack - if(!get_item_callback(L, ndef->get(node).name.c_str(), "on_construct")) - return; - - // Call function - push_v3s16(L, p); - if(lua_pcall(L, 1, 0, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); -} - -void scriptapi_node_on_destruct(lua_State *L, v3s16 p, MapNode node) -{ - realitycheck(L); - assert(lua_checkstack(L, 20)); - StackUnroller stack_unroller(L); - - INodeDefManager *ndef = get_server(L)->ndef(); - - // Push callback function on stack - if(!get_item_callback(L, ndef->get(node).name.c_str(), "on_destruct")) - return; - - // Call function - push_v3s16(L, p); - if(lua_pcall(L, 1, 0, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); -} - -void scriptapi_node_after_destruct(lua_State *L, v3s16 p, MapNode node) -{ - realitycheck(L); - assert(lua_checkstack(L, 20)); - StackUnroller stack_unroller(L); - - INodeDefManager *ndef = get_server(L)->ndef(); - - // Push callback function on stack - if(!get_item_callback(L, ndef->get(node).name.c_str(), "after_destruct")) - return; - - // Call function - push_v3s16(L, p); - pushnode(L, node, ndef); - if(lua_pcall(L, 2, 0, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); -} - -bool scriptapi_node_on_timer(lua_State *L, v3s16 p, MapNode node, f32 dtime) -{ - realitycheck(L); - assert(lua_checkstack(L, 20)); - StackUnroller stack_unroller(L); - - INodeDefManager *ndef = get_server(L)->ndef(); - - // Push callback function on stack - if(!get_item_callback(L, ndef->get(node).name.c_str(), "on_timer")) - return false; - - // Call function - push_v3s16(L, p); - lua_pushnumber(L,dtime); - if(lua_pcall(L, 2, 1, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); - if((bool)lua_isboolean(L,-1) && (bool)lua_toboolean(L,-1) == true) - return true; - - return false; -} - -void scriptapi_node_on_receive_fields(lua_State *L, v3s16 p, - const std::string &formname, - const std::map &fields, - ServerActiveObject *sender) -{ - realitycheck(L); - assert(lua_checkstack(L, 20)); - StackUnroller stack_unroller(L); - - INodeDefManager *ndef = get_server(L)->ndef(); - - // If node doesn't exist, we don't know what callback to call - MapNode node = get_env(L)->getMap().getNodeNoEx(p); - if(node.getContent() == CONTENT_IGNORE) - return; - - // Push callback function on stack - if(!get_item_callback(L, ndef->get(node).name.c_str(), "on_receive_fields")) - return; - - // Call function - // param 1 - push_v3s16(L, p); - // param 2 - lua_pushstring(L, formname.c_str()); - // param 3 - 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); - } - // param 4 - objectref_get_or_create(L, sender); - if(lua_pcall(L, 4, 0, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); -} diff --git a/src/scriptapi_node.h b/src/scriptapi_node.h deleted file mode 100644 index 665b58bfc..000000000 --- a/src/scriptapi_node.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -Minetest-c55 -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 LUA_NODE_H_ -#define LUA_NODE_H_ - -#include -#include - -extern "C" { -#include -} - -#include "content_sao.h" -#include "map.h" - -/*****************************************************************************/ -/* Minetest interface */ -/*****************************************************************************/ -bool scriptapi_node_on_punch(lua_State *L, v3s16 p, MapNode node, - ServerActiveObject *puncher); -bool scriptapi_node_on_dig(lua_State *L, v3s16 p, MapNode node, - ServerActiveObject *digger); -void scriptapi_node_on_construct(lua_State *L, v3s16 p, MapNode node); -void scriptapi_node_on_destruct(lua_State *L, v3s16 p, MapNode node); -void scriptapi_node_after_destruct(lua_State *L, v3s16 p, MapNode node); -bool scriptapi_node_on_timer(lua_State *L, v3s16 p, MapNode node, f32 dtime); -void scriptapi_node_on_receive_fields(lua_State *L, v3s16 p, - const std::string &formname, - const std::map &fields, - ServerActiveObject *sender); - -extern struct EnumString es_DrawType[]; -extern struct EnumString es_ContentParamType[]; -extern struct EnumString es_ContentParamType2[]; -extern struct EnumString es_LiquidType[]; -extern struct EnumString es_NodeBoxType[]; - -#endif /* LUA_NODE_H_ */ diff --git a/src/scriptapi_nodemeta.cpp b/src/scriptapi_nodemeta.cpp deleted file mode 100644 index b66c9a023..000000000 --- a/src/scriptapi_nodemeta.cpp +++ /dev/null @@ -1,571 +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. -*/ - -#include "scriptapi.h" -#include "scriptapi_nodemeta.h" -#include "map.h" -#include "script.h" -#include "scriptapi_types.h" -#include "scriptapi_inventory.h" -#include "scriptapi_common.h" -#include "scriptapi_item.h" -#include "scriptapi_object.h" - - -/* - NodeMetaRef -*/ -NodeMetaRef* NodeMetaRef::checkobject(lua_State *L, int narg) -{ - luaL_checktype(L, narg, LUA_TUSERDATA); - void *ud = luaL_checkudata(L, narg, className); - if(!ud) luaL_typerror(L, narg, className); - return *(NodeMetaRef**)ud; // unbox pointer -} - -NodeMetadata* NodeMetaRef::getmeta(NodeMetaRef *ref, bool auto_create) -{ - NodeMetadata *meta = ref->m_env->getMap().getNodeMetadata(ref->m_p); - if(meta == NULL && auto_create) - { - meta = new NodeMetadata(ref->m_env->getGameDef()); - ref->m_env->getMap().setNodeMetadata(ref->m_p, meta); - } - return meta; -} - -void NodeMetaRef::reportMetadataChange(NodeMetaRef *ref) -{ - // NOTE: This same code is in rollback_interface.cpp - // Inform other things that the metadata has changed - v3s16 blockpos = getNodeBlockPos(ref->m_p); - MapEditEvent event; - event.type = MEET_BLOCK_NODE_METADATA_CHANGED; - event.p = blockpos; - ref->m_env->getMap().dispatchEvent(&event); - // Set the block to be saved - MapBlock *block = ref->m_env->getMap().getBlockNoCreateNoEx(blockpos); - if(block) - block->raiseModified(MOD_STATE_WRITE_NEEDED, - "NodeMetaRef::reportMetadataChange"); -} - -// Exported functions - -// garbage collector -int NodeMetaRef::gc_object(lua_State *L) { - NodeMetaRef *o = *(NodeMetaRef **)(lua_touserdata(L, 1)); - delete o; - return 0; -} - -// get_string(self, name) -int NodeMetaRef::l_get_string(lua_State *L) -{ - NodeMetaRef *ref = checkobject(L, 1); - std::string name = luaL_checkstring(L, 2); - - NodeMetadata *meta = getmeta(ref, false); - if(meta == NULL){ - lua_pushlstring(L, "", 0); - return 1; - } - std::string str = meta->getString(name); - lua_pushlstring(L, str.c_str(), str.size()); - return 1; -} - -// set_string(self, name, var) -int NodeMetaRef::l_set_string(lua_State *L) -{ - NodeMetaRef *ref = checkobject(L, 1); - std::string name = luaL_checkstring(L, 2); - size_t len = 0; - const char *s = lua_tolstring(L, 3, &len); - std::string str(s, len); - - NodeMetadata *meta = getmeta(ref, !str.empty()); - if(meta == NULL || str == meta->getString(name)) - return 0; - meta->setString(name, str); - reportMetadataChange(ref); - return 0; -} - -// get_int(self, name) -int NodeMetaRef::l_get_int(lua_State *L) -{ - NodeMetaRef *ref = checkobject(L, 1); - std::string name = lua_tostring(L, 2); - - NodeMetadata *meta = getmeta(ref, false); - if(meta == NULL){ - lua_pushnumber(L, 0); - return 1; - } - std::string str = meta->getString(name); - lua_pushnumber(L, stoi(str)); - return 1; -} - -// set_int(self, name, var) -int NodeMetaRef::l_set_int(lua_State *L) -{ - NodeMetaRef *ref = checkobject(L, 1); - std::string name = lua_tostring(L, 2); - int a = lua_tointeger(L, 3); - std::string str = itos(a); - - NodeMetadata *meta = getmeta(ref, true); - if(meta == NULL || str == meta->getString(name)) - return 0; - meta->setString(name, str); - reportMetadataChange(ref); - return 0; -} - -// get_float(self, name) -int NodeMetaRef::l_get_float(lua_State *L) -{ - NodeMetaRef *ref = checkobject(L, 1); - std::string name = lua_tostring(L, 2); - - NodeMetadata *meta = getmeta(ref, false); - if(meta == NULL){ - lua_pushnumber(L, 0); - return 1; - } - std::string str = meta->getString(name); - lua_pushnumber(L, stof(str)); - return 1; -} - -// set_float(self, name, var) -int NodeMetaRef::l_set_float(lua_State *L) -{ - NodeMetaRef *ref = checkobject(L, 1); - std::string name = lua_tostring(L, 2); - float a = lua_tonumber(L, 3); - std::string str = ftos(a); - - NodeMetadata *meta = getmeta(ref, true); - if(meta == NULL || str == meta->getString(name)) - return 0; - meta->setString(name, str); - reportMetadataChange(ref); - return 0; -} - -// get_inventory(self) -int NodeMetaRef::l_get_inventory(lua_State *L) -{ - NodeMetaRef *ref = checkobject(L, 1); - getmeta(ref, true); // try to ensure the metadata exists - InvRef::createNodeMeta(L, ref->m_p); - return 1; -} - -// to_table(self) -int NodeMetaRef::l_to_table(lua_State *L) -{ - NodeMetaRef *ref = checkobject(L, 1); - - NodeMetadata *meta = getmeta(ref, true); - if(meta == NULL){ - lua_pushnil(L); - return 1; - } - lua_newtable(L); - // fields - lua_newtable(L); - { - std::map fields = meta->getStrings(); - 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_pushlstring(L, name.c_str(), name.size()); - lua_pushlstring(L, value.c_str(), value.size()); - lua_settable(L, -3); - } - } - lua_setfield(L, -2, "fields"); - // inventory - lua_newtable(L); - Inventory *inv = meta->getInventory(); - if(inv){ - std::vector lists = inv->getLists(); - for(std::vector::const_iterator - i = lists.begin(); i != lists.end(); i++){ - inventory_get_list_to_lua(inv, (*i)->getName().c_str(), L); - lua_setfield(L, -2, (*i)->getName().c_str()); - } - } - lua_setfield(L, -2, "inventory"); - return 1; -} - -// from_table(self, table) -int NodeMetaRef::l_from_table(lua_State *L) -{ - NodeMetaRef *ref = checkobject(L, 1); - int base = 2; - - if(lua_isnil(L, base)){ - // No metadata - ref->m_env->getMap().removeNodeMetadata(ref->m_p); - lua_pushboolean(L, true); - return 1; - } - - // Has metadata; clear old one first - ref->m_env->getMap().removeNodeMetadata(ref->m_p); - // Create new metadata - NodeMetadata *meta = getmeta(ref, true); - // Set fields - lua_getfield(L, base, "fields"); - int fieldstable = lua_gettop(L); - lua_pushnil(L); - while(lua_next(L, fieldstable) != 0){ - // key at index -2 and value at index -1 - std::string name = lua_tostring(L, -2); - size_t cl; - const char *cs = lua_tolstring(L, -1, &cl); - std::string value(cs, cl); - meta->setString(name, value); - lua_pop(L, 1); // removes value, keeps key for next iteration - } - // Set inventory - Inventory *inv = meta->getInventory(); - lua_getfield(L, base, "inventory"); - int inventorytable = lua_gettop(L); - lua_pushnil(L); - while(lua_next(L, inventorytable) != 0){ - // key at index -2 and value at index -1 - std::string name = lua_tostring(L, -2); - inventory_set_list_from_lua(inv, name.c_str(), L, -1); - lua_pop(L, 1); // removes value, keeps key for next iteration - } - reportMetadataChange(ref); - lua_pushboolean(L, true); - return 1; -} - - -NodeMetaRef::NodeMetaRef(v3s16 p, ServerEnvironment *env): - m_p(p), - m_env(env) -{ -} - -NodeMetaRef::~NodeMetaRef() -{ -} - -// Creates an NodeMetaRef and leaves it on top of stack -// Not callable from Lua; all references are created on the C side. -void NodeMetaRef::create(lua_State *L, v3s16 p, ServerEnvironment *env) -{ - NodeMetaRef *o = new NodeMetaRef(p, env); - //infostream<<"NodeMetaRef::create: o="<ndef(); - - // If node doesn't exist, we don't know what callback to call - MapNode node = get_env(L)->getMap().getNodeNoEx(p); - if(node.getContent() == CONTENT_IGNORE) - return 0; - - // Push callback function on stack - if(!get_item_callback(L, ndef->get(node).name.c_str(), - "allow_metadata_inventory_move")) - return count; - - // function(pos, from_list, from_index, to_list, to_index, count, player) - // pos - push_v3s16(L, p); - // from_list - lua_pushstring(L, from_list.c_str()); - // from_index - lua_pushinteger(L, from_index + 1); - // to_list - lua_pushstring(L, to_list.c_str()); - // to_index - lua_pushinteger(L, to_index + 1); - // count - lua_pushinteger(L, count); - // player - objectref_get_or_create(L, player); - if(lua_pcall(L, 7, 1, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); - if(!lua_isnumber(L, -1)) - throw LuaError(L, "allow_metadata_inventory_move should return a number"); - return luaL_checkinteger(L, -1); -} - -// Return number of accepted items to be put -int scriptapi_nodemeta_inventory_allow_put(lua_State *L, v3s16 p, - const std::string &listname, int index, ItemStack &stack, - ServerActiveObject *player) -{ - realitycheck(L); - assert(lua_checkstack(L, 20)); - StackUnroller stack_unroller(L); - - INodeDefManager *ndef = get_server(L)->ndef(); - - // If node doesn't exist, we don't know what callback to call - MapNode node = get_env(L)->getMap().getNodeNoEx(p); - if(node.getContent() == CONTENT_IGNORE) - return 0; - - // Push callback function on stack - if(!get_item_callback(L, ndef->get(node).name.c_str(), - "allow_metadata_inventory_put")) - return stack.count; - - // Call function(pos, listname, index, stack, player) - // pos - push_v3s16(L, p); - // listname - lua_pushstring(L, listname.c_str()); - // index - lua_pushinteger(L, index + 1); - // stack - LuaItemStack::create(L, stack); - // player - objectref_get_or_create(L, player); - if(lua_pcall(L, 5, 1, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); - if(!lua_isnumber(L, -1)) - throw LuaError(L, "allow_metadata_inventory_put should return a number"); - return luaL_checkinteger(L, -1); -} - -// Return number of accepted items to be taken -int scriptapi_nodemeta_inventory_allow_take(lua_State *L, v3s16 p, - const std::string &listname, int index, ItemStack &stack, - ServerActiveObject *player) -{ - realitycheck(L); - assert(lua_checkstack(L, 20)); - StackUnroller stack_unroller(L); - - INodeDefManager *ndef = get_server(L)->ndef(); - - // If node doesn't exist, we don't know what callback to call - MapNode node = get_env(L)->getMap().getNodeNoEx(p); - if(node.getContent() == CONTENT_IGNORE) - return 0; - - // Push callback function on stack - if(!get_item_callback(L, ndef->get(node).name.c_str(), - "allow_metadata_inventory_take")) - return stack.count; - - // Call function(pos, listname, index, count, player) - // pos - push_v3s16(L, p); - // listname - lua_pushstring(L, listname.c_str()); - // index - lua_pushinteger(L, index + 1); - // stack - LuaItemStack::create(L, stack); - // player - objectref_get_or_create(L, player); - if(lua_pcall(L, 5, 1, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); - if(!lua_isnumber(L, -1)) - throw LuaError(L, "allow_metadata_inventory_take should return a number"); - return luaL_checkinteger(L, -1); -} - -// Report moved items -void scriptapi_nodemeta_inventory_on_move(lua_State *L, v3s16 p, - const std::string &from_list, int from_index, - const std::string &to_list, int to_index, - int count, ServerActiveObject *player) -{ - realitycheck(L); - assert(lua_checkstack(L, 20)); - StackUnroller stack_unroller(L); - - INodeDefManager *ndef = get_server(L)->ndef(); - - // If node doesn't exist, we don't know what callback to call - MapNode node = get_env(L)->getMap().getNodeNoEx(p); - if(node.getContent() == CONTENT_IGNORE) - return; - - // Push callback function on stack - if(!get_item_callback(L, ndef->get(node).name.c_str(), - "on_metadata_inventory_move")) - return; - - // function(pos, from_list, from_index, to_list, to_index, count, player) - // pos - push_v3s16(L, p); - // from_list - lua_pushstring(L, from_list.c_str()); - // from_index - lua_pushinteger(L, from_index + 1); - // to_list - lua_pushstring(L, to_list.c_str()); - // to_index - lua_pushinteger(L, to_index + 1); - // count - lua_pushinteger(L, count); - // player - objectref_get_or_create(L, player); - if(lua_pcall(L, 7, 0, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); -} - -// Report put items -void scriptapi_nodemeta_inventory_on_put(lua_State *L, v3s16 p, - const std::string &listname, int index, ItemStack &stack, - ServerActiveObject *player) -{ - realitycheck(L); - assert(lua_checkstack(L, 20)); - StackUnroller stack_unroller(L); - - INodeDefManager *ndef = get_server(L)->ndef(); - - // If node doesn't exist, we don't know what callback to call - MapNode node = get_env(L)->getMap().getNodeNoEx(p); - if(node.getContent() == CONTENT_IGNORE) - return; - - // Push callback function on stack - if(!get_item_callback(L, ndef->get(node).name.c_str(), - "on_metadata_inventory_put")) - return; - - // Call function(pos, listname, index, stack, player) - // pos - push_v3s16(L, p); - // listname - lua_pushstring(L, listname.c_str()); - // index - lua_pushinteger(L, index + 1); - // stack - LuaItemStack::create(L, stack); - // player - objectref_get_or_create(L, player); - if(lua_pcall(L, 5, 0, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); -} - -// Report taken items -void scriptapi_nodemeta_inventory_on_take(lua_State *L, v3s16 p, - const std::string &listname, int index, ItemStack &stack, - ServerActiveObject *player) -{ - realitycheck(L); - assert(lua_checkstack(L, 20)); - StackUnroller stack_unroller(L); - - INodeDefManager *ndef = get_server(L)->ndef(); - - // If node doesn't exist, we don't know what callback to call - MapNode node = get_env(L)->getMap().getNodeNoEx(p); - if(node.getContent() == CONTENT_IGNORE) - return; - - // Push callback function on stack - if(!get_item_callback(L, ndef->get(node).name.c_str(), - "on_metadata_inventory_take")) - return; - - // Call function(pos, listname, index, stack, player) - // pos - push_v3s16(L, p); - // listname - lua_pushstring(L, listname.c_str()); - // index - lua_pushinteger(L, index + 1); - // stack - LuaItemStack::create(L, stack); - // player - objectref_get_or_create(L, player); - if(lua_pcall(L, 5, 0, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); -} diff --git a/src/scriptapi_nodemeta.h b/src/scriptapi_nodemeta.h deleted file mode 100644 index 017abe181..000000000 --- a/src/scriptapi_nodemeta.h +++ /dev/null @@ -1,123 +0,0 @@ -/* -Minetest-c55 -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 LUA_NODEMETA_H_ -#define LUA_NODEMETA_H_ - -extern "C" { -#include -#include -} - -#include "environment.h" -#include "nodemetadata.h" - -/* - NodeMetaRef -*/ - -class NodeMetaRef -{ -private: - v3s16 m_p; - ServerEnvironment *m_env; - - static const char className[]; - static const luaL_reg methods[]; - - static NodeMetaRef *checkobject(lua_State *L, int narg); - - static NodeMetadata* getmeta(NodeMetaRef *ref, bool auto_create); - - static void reportMetadataChange(NodeMetaRef *ref); - - // Exported functions - - // garbage collector - static int gc_object(lua_State *L); - - // get_string(self, name) - static int l_get_string(lua_State *L); - - // set_string(self, name, var) - static int l_set_string(lua_State *L); - - // get_int(self, name) - static int l_get_int(lua_State *L); - - // set_int(self, name, var) - static int l_set_int(lua_State *L); - - // get_float(self, name) - static int l_get_float(lua_State *L); - - // set_float(self, name, var) - static int l_set_float(lua_State *L); - - // get_inventory(self) - static int l_get_inventory(lua_State *L); - - // to_table(self) - static int l_to_table(lua_State *L); - - // from_table(self, table) - static int l_from_table(lua_State *L); - -public: - NodeMetaRef(v3s16 p, ServerEnvironment *env); - - ~NodeMetaRef(); - - // Creates an NodeMetaRef and leaves it on top of stack - // Not callable from Lua; all references are created on the C side. - static void create(lua_State *L, v3s16 p, ServerEnvironment *env); - - static void Register(lua_State *L); -}; - -/*****************************************************************************/ -/* Minetest interface */ -/*****************************************************************************/ -// Return number of accepted items to be moved -int scriptapi_nodemeta_inventory_allow_move(lua_State *L, v3s16 p, - const std::string &from_list, int from_index, - const std::string &to_list, int to_index, - int count, ServerActiveObject *player); -// Return number of accepted items to be put -int scriptapi_nodemeta_inventory_allow_put(lua_State *L, v3s16 p, - const std::string &listname, int index, ItemStack &stack, - ServerActiveObject *player); -// Return number of accepted items to be taken -int scriptapi_nodemeta_inventory_allow_take(lua_State *L, v3s16 p, - const std::string &listname, int index, ItemStack &stack, - ServerActiveObject *player); -// Report moved items -void scriptapi_nodemeta_inventory_on_move(lua_State *L, v3s16 p, - const std::string &from_list, int from_index, - const std::string &to_list, int to_index, - int count, ServerActiveObject *player); -// Report put items -void scriptapi_nodemeta_inventory_on_put(lua_State *L, v3s16 p, - const std::string &listname, int index, ItemStack &stack, - ServerActiveObject *player); -// Report taken items -void scriptapi_nodemeta_inventory_on_take(lua_State *L, v3s16 p, - const std::string &listname, int index, ItemStack &stack, - ServerActiveObject *player); - -#endif //LUA_NODEMETA_H_ diff --git a/src/scriptapi_nodetimer.cpp b/src/scriptapi_nodetimer.cpp deleted file mode 100644 index 5e3289aee..000000000 --- a/src/scriptapi_nodetimer.cpp +++ /dev/null @@ -1,166 +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. -*/ - -#include "scriptapi.h" -#include "scriptapi_nodetimer.h" -#include "map.h" - - -int NodeTimerRef::gc_object(lua_State *L) { - NodeTimerRef *o = *(NodeTimerRef **)(lua_touserdata(L, 1)); - delete o; - return 0; -} - -NodeTimerRef* NodeTimerRef::checkobject(lua_State *L, int narg) -{ - luaL_checktype(L, narg, LUA_TUSERDATA); - void *ud = luaL_checkudata(L, narg, className); - if(!ud) luaL_typerror(L, narg, className); - return *(NodeTimerRef**)ud; // unbox pointer -} - -int NodeTimerRef::l_set(lua_State *L) -{ - NodeTimerRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - if(env == NULL) return 0; - f32 t = luaL_checknumber(L,2); - f32 e = luaL_checknumber(L,3); - env->getMap().setNodeTimer(o->m_p,NodeTimer(t,e)); - return 0; -} - -int NodeTimerRef::l_start(lua_State *L) -{ - NodeTimerRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - if(env == NULL) return 0; - f32 t = luaL_checknumber(L,2); - env->getMap().setNodeTimer(o->m_p,NodeTimer(t,0)); - return 0; -} - -int NodeTimerRef::l_stop(lua_State *L) -{ - NodeTimerRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - if(env == NULL) return 0; - env->getMap().removeNodeTimer(o->m_p); - return 0; -} - -int NodeTimerRef::l_is_started(lua_State *L) -{ - NodeTimerRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - if(env == NULL) return 0; - - NodeTimer t = env->getMap().getNodeTimer(o->m_p); - lua_pushboolean(L,(t.timeout != 0)); - return 1; -} - -int NodeTimerRef::l_get_timeout(lua_State *L) -{ - NodeTimerRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - if(env == NULL) return 0; - - NodeTimer t = env->getMap().getNodeTimer(o->m_p); - lua_pushnumber(L,t.timeout); - return 1; -} - -int NodeTimerRef::l_get_elapsed(lua_State *L) -{ - NodeTimerRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - if(env == NULL) return 0; - - NodeTimer t = env->getMap().getNodeTimer(o->m_p); - lua_pushnumber(L,t.elapsed); - return 1; -} - - -NodeTimerRef::NodeTimerRef(v3s16 p, ServerEnvironment *env): - m_p(p), - m_env(env) -{ -} - -NodeTimerRef::~NodeTimerRef() -{ -} - -// Creates an NodeTimerRef and leaves it on top of stack -// Not callable from Lua; all references are created on the C side. -void NodeTimerRef::create(lua_State *L, v3s16 p, ServerEnvironment *env) -{ - NodeTimerRef *o = new NodeTimerRef(p, env); - *(void **)(lua_newuserdata(L, sizeof(void *))) = o; - luaL_getmetatable(L, className); - lua_setmetatable(L, -2); -} - -void NodeTimerRef::set_null(lua_State *L) -{ - NodeTimerRef *o = checkobject(L, -1); - o->m_env = NULL; -} - -void NodeTimerRef::Register(lua_State *L) -{ - lua_newtable(L); - int methodtable = lua_gettop(L); - luaL_newmetatable(L, className); - int metatable = lua_gettop(L); - - lua_pushliteral(L, "__metatable"); - lua_pushvalue(L, methodtable); - lua_settable(L, metatable); // hide metatable from Lua getmetatable() - - lua_pushliteral(L, "__index"); - lua_pushvalue(L, methodtable); - lua_settable(L, metatable); - - lua_pushliteral(L, "__gc"); - lua_pushcfunction(L, gc_object); - lua_settable(L, metatable); - - lua_pop(L, 1); // drop metatable - - luaL_openlib(L, 0, methods, 0); // fill methodtable - lua_pop(L, 1); // drop methodtable - - // Cannot be created from Lua - //lua_register(L, className, create_object); -} - -const char NodeTimerRef::className[] = "NodeTimerRef"; -const luaL_reg NodeTimerRef::methods[] = { - luamethod(NodeTimerRef, start), - luamethod(NodeTimerRef, set), - luamethod(NodeTimerRef, stop), - luamethod(NodeTimerRef, is_started), - luamethod(NodeTimerRef, get_timeout), - luamethod(NodeTimerRef, get_elapsed), - {0,0} -}; diff --git a/src/scriptapi_nodetimer.h b/src/scriptapi_nodetimer.h deleted file mode 100644 index a4536d947..000000000 --- a/src/scriptapi_nodetimer.h +++ /dev/null @@ -1,70 +0,0 @@ -/* -Minetest-c55 -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 LUA_NODETIMER_H_ -#define LUA_NODETIMER_H_ - -extern "C" { -#include -#include -} - -#include "environment.h" - -class NodeTimerRef -{ -private: - v3s16 m_p; - ServerEnvironment *m_env; - - static const char className[]; - static const luaL_reg methods[]; - - static int gc_object(lua_State *L); - - static NodeTimerRef *checkobject(lua_State *L, int narg); - - static int l_set(lua_State *L); - - static int l_start(lua_State *L); - - static int l_stop(lua_State *L); - - static int l_is_started(lua_State *L); - - static int l_get_timeout(lua_State *L); - - static int l_get_elapsed(lua_State *L); - -public: - NodeTimerRef(v3s16 p, ServerEnvironment *env); - ~NodeTimerRef(); - - // Creates an NodeTimerRef and leaves it on top of stack - // Not callable from Lua; all references are created on the C side. - static void create(lua_State *L, v3s16 p, ServerEnvironment *env); - - static void set_null(lua_State *L); - - static void Register(lua_State *L); -}; - - - -#endif /* LUA_NODETIMER_H_ */ diff --git a/src/scriptapi_noise.cpp b/src/scriptapi_noise.cpp deleted file mode 100644 index 2c1a83c4c..000000000 --- a/src/scriptapi_noise.cpp +++ /dev/null @@ -1,388 +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. -*/ - -#include "scriptapi.h" -#include "scriptapi_noise.h" -#include "scriptapi_types.h" -#include "script.h" - -// garbage collector -int LuaPerlinNoise::gc_object(lua_State *L) -{ - LuaPerlinNoise *o = *(LuaPerlinNoise **)(lua_touserdata(L, 1)); - delete o; - return 0; -} - -int LuaPerlinNoise::l_get2d(lua_State *L) -{ - LuaPerlinNoise *o = checkobject(L, 1); - v2f pos2d = read_v2f(L,2); - lua_Number val = noise2d_perlin(pos2d.X/o->scale, pos2d.Y/o->scale, o->seed, o->octaves, o->persistence); - lua_pushnumber(L, val); - return 1; -} -int LuaPerlinNoise::l_get3d(lua_State *L) -{ - LuaPerlinNoise *o = checkobject(L, 1); - v3f pos3d = read_v3f(L,2); - lua_Number val = noise3d_perlin(pos3d.X/o->scale, pos3d.Y/o->scale, pos3d.Z/o->scale, o->seed, o->octaves, o->persistence); - lua_pushnumber(L, val); - return 1; -} - - -LuaPerlinNoise::LuaPerlinNoise(int a_seed, int a_octaves, float a_persistence, - float a_scale): - seed(a_seed), - octaves(a_octaves), - persistence(a_persistence), - scale(a_scale) -{ -} - -LuaPerlinNoise::~LuaPerlinNoise() -{ -} - -// LuaPerlinNoise(seed, octaves, persistence, scale) -// Creates an LuaPerlinNoise and leaves it on top of stack -int LuaPerlinNoise::create_object(lua_State *L) -{ - int seed = luaL_checkint(L, 1); - int octaves = luaL_checkint(L, 2); - float persistence = luaL_checknumber(L, 3); - float scale = luaL_checknumber(L, 4); - LuaPerlinNoise *o = new LuaPerlinNoise(seed, octaves, persistence, scale); - *(void **)(lua_newuserdata(L, sizeof(void *))) = o; - luaL_getmetatable(L, className); - lua_setmetatable(L, -2); - return 1; -} - -LuaPerlinNoise* LuaPerlinNoise::checkobject(lua_State *L, int narg) -{ - luaL_checktype(L, narg, LUA_TUSERDATA); - void *ud = luaL_checkudata(L, narg, className); - if(!ud) luaL_typerror(L, narg, className); - return *(LuaPerlinNoise**)ud; // unbox pointer -} - -void LuaPerlinNoise::Register(lua_State *L) -{ - lua_newtable(L); - int methodtable = lua_gettop(L); - luaL_newmetatable(L, className); - int metatable = lua_gettop(L); - - lua_pushliteral(L, "__metatable"); - lua_pushvalue(L, methodtable); - lua_settable(L, metatable); // hide metatable from Lua getmetatable() - - lua_pushliteral(L, "__index"); - lua_pushvalue(L, methodtable); - lua_settable(L, metatable); - - lua_pushliteral(L, "__gc"); - lua_pushcfunction(L, gc_object); - lua_settable(L, metatable); - - lua_pop(L, 1); // drop metatable - - luaL_openlib(L, 0, methods, 0); // fill methodtable - lua_pop(L, 1); // drop methodtable - - // Can be created from Lua (PerlinNoise(seed, octaves, persistence) - lua_register(L, className, create_object); -} - -const char LuaPerlinNoise::className[] = "PerlinNoise"; -const luaL_reg LuaPerlinNoise::methods[] = { - luamethod(LuaPerlinNoise, get2d), - luamethod(LuaPerlinNoise, get3d), - {0,0} -}; - -/* - PerlinNoiseMap - */ - - -int LuaPerlinNoiseMap::gc_object(lua_State *L) -{ - LuaPerlinNoiseMap *o = *(LuaPerlinNoiseMap **)(lua_touserdata(L, 1)); - delete o; - return 0; -} - -int LuaPerlinNoiseMap::l_get2dMap(lua_State *L) -{ - int i = 0; - - LuaPerlinNoiseMap *o = checkobject(L, 1); - v2f p = read_v2f(L, 2); - - Noise *n = o->noise; - n->perlinMap2D(p.X, p.Y); - - lua_newtable(L); - for (int y = 0; y != n->sy; y++) { - lua_newtable(L); - for (int x = 0; x != n->sx; x++) { - float noiseval = n->np->offset + n->np->scale * n->result[i++]; - lua_pushnumber(L, noiseval); - lua_rawseti(L, -2, x + 1); - } - lua_rawseti(L, -2, y + 1); - } - return 1; -} - -int LuaPerlinNoiseMap::l_get3dMap(lua_State *L) -{ - int i = 0; - - LuaPerlinNoiseMap *o = checkobject(L, 1); - v3f p = read_v3f(L, 2); - - Noise *n = o->noise; - n->perlinMap3D(p.X, p.Y, p.Z); - - lua_newtable(L); - for (int z = 0; z != n->sz; z++) { - lua_newtable(L); - for (int y = 0; y != n->sy; y++) { - lua_newtable(L); - for (int x = 0; x != n->sx; x++) { - lua_pushnumber(L, n->np->offset + n->np->scale * n->result[i++]); - lua_rawseti(L, -2, x + 1); - } - lua_rawseti(L, -2, y + 1); - } - lua_rawseti(L, -2, z + 1); - } - return 1; -} - -LuaPerlinNoiseMap::LuaPerlinNoiseMap(NoiseParams *np, int seed, v3s16 size) { - noise = new Noise(np, seed, size.X, size.Y, size.Z); -} - -LuaPerlinNoiseMap::~LuaPerlinNoiseMap() -{ - delete noise->np; - delete noise; -} - -// LuaPerlinNoiseMap(np, size) -// Creates an LuaPerlinNoiseMap and leaves it on top of stack -int LuaPerlinNoiseMap::create_object(lua_State *L) -{ - NoiseParams *np = read_noiseparams(L, 1); - if (!np) - return 0; - v3s16 size = read_v3s16(L, 2); - - LuaPerlinNoiseMap *o = new LuaPerlinNoiseMap(np, 0, size); - *(void **)(lua_newuserdata(L, sizeof(void *))) = o; - luaL_getmetatable(L, className); - lua_setmetatable(L, -2); - return 1; -} - -LuaPerlinNoiseMap* LuaPerlinNoiseMap::checkobject(lua_State *L, int narg) -{ - luaL_checktype(L, narg, LUA_TUSERDATA); - - void *ud = luaL_checkudata(L, narg, className); - if (!ud) - luaL_typerror(L, narg, className); - - return *(LuaPerlinNoiseMap **)ud; // unbox pointer -} - -void LuaPerlinNoiseMap::Register(lua_State *L) -{ - lua_newtable(L); - int methodtable = lua_gettop(L); - luaL_newmetatable(L, className); - int metatable = lua_gettop(L); - - lua_pushliteral(L, "__metatable"); - lua_pushvalue(L, methodtable); - lua_settable(L, metatable); // hide metatable from Lua getmetatable() - - lua_pushliteral(L, "__index"); - lua_pushvalue(L, methodtable); - lua_settable(L, metatable); - - lua_pushliteral(L, "__gc"); - lua_pushcfunction(L, gc_object); - lua_settable(L, metatable); - - lua_pop(L, 1); // drop metatable - - luaL_openlib(L, 0, methods, 0); // fill methodtable - lua_pop(L, 1); // drop methodtable - - // Can be created from Lua (PerlinNoiseMap(np, size) - lua_register(L, className, create_object); -} - -const char LuaPerlinNoiseMap::className[] = "PerlinNoiseMap"; -const luaL_reg LuaPerlinNoiseMap::methods[] = { - luamethod(LuaPerlinNoiseMap, get2dMap), - luamethod(LuaPerlinNoiseMap, get3dMap), - {0,0} -}; - -/* - NoiseParams -*/ -NoiseParams *read_noiseparams(lua_State *L, int index) -{ - if (index < 0) - index = lua_gettop(L) + 1 + index; - - if (!lua_istable(L, index)) - return NULL; - - NoiseParams *np = new NoiseParams; - - np->offset = getfloatfield_default(L, index, "offset", 0.0); - np->scale = getfloatfield_default(L, index, "scale", 0.0); - lua_getfield(L, index, "spread"); - np->spread = read_v3f(L, -1); - lua_pop(L, 1); - np->seed = getintfield_default(L, index, "seed", 0); - np->octaves = getintfield_default(L, index, "octaves", 0); - np->persist = getfloatfield_default(L, index, "persist", 0.0); - - return np; -} - - -/* - LuaPseudoRandom -*/ - -// garbage collector -int LuaPseudoRandom::gc_object(lua_State *L) -{ - LuaPseudoRandom *o = *(LuaPseudoRandom **)(lua_touserdata(L, 1)); - delete o; - return 0; -} - -// next(self, min=0, max=32767) -> get next value -int LuaPseudoRandom::l_next(lua_State *L) -{ - LuaPseudoRandom *o = checkobject(L, 1); - int min = 0; - int max = 32767; - lua_settop(L, 3); // Fill 2 and 3 with nil if they don't exist - if(!lua_isnil(L, 2)) - min = luaL_checkinteger(L, 2); - if(!lua_isnil(L, 3)) - max = luaL_checkinteger(L, 3); - if(max < min){ - errorstream<<"PseudoRandom.next(): max="< 32767/5) - throw LuaError(L, "PseudoRandom.next() max-min is not 32767 and is > 32768/5. This is disallowed due to the bad random distribution the implementation would otherwise make."); - PseudoRandom &pseudo = o->m_pseudo; - int val = pseudo.next(); - val = (val % (max-min+1)) + min; - lua_pushinteger(L, val); - return 1; -} - - -LuaPseudoRandom::LuaPseudoRandom(int seed): - m_pseudo(seed) -{ -} - -LuaPseudoRandom::~LuaPseudoRandom() -{ -} - -const PseudoRandom& LuaPseudoRandom::getItem() const -{ - return m_pseudo; -} -PseudoRandom& LuaPseudoRandom::getItem() -{ - return m_pseudo; -} - -// LuaPseudoRandom(seed) -// Creates an LuaPseudoRandom and leaves it on top of stack -int LuaPseudoRandom::create_object(lua_State *L) -{ - int seed = luaL_checknumber(L, 1); - LuaPseudoRandom *o = new LuaPseudoRandom(seed); - *(void **)(lua_newuserdata(L, sizeof(void *))) = o; - luaL_getmetatable(L, className); - lua_setmetatable(L, -2); - return 1; -} - -LuaPseudoRandom* LuaPseudoRandom::checkobject(lua_State *L, int narg) -{ - luaL_checktype(L, narg, LUA_TUSERDATA); - void *ud = luaL_checkudata(L, narg, className); - if(!ud) luaL_typerror(L, narg, className); - return *(LuaPseudoRandom**)ud; // unbox pointer -} - -void LuaPseudoRandom::Register(lua_State *L) -{ - lua_newtable(L); - int methodtable = lua_gettop(L); - luaL_newmetatable(L, className); - int metatable = lua_gettop(L); - - lua_pushliteral(L, "__metatable"); - lua_pushvalue(L, methodtable); - lua_settable(L, metatable); // hide metatable from Lua getmetatable() - - lua_pushliteral(L, "__index"); - lua_pushvalue(L, methodtable); - lua_settable(L, metatable); - - lua_pushliteral(L, "__gc"); - lua_pushcfunction(L, gc_object); - lua_settable(L, metatable); - - lua_pop(L, 1); // drop metatable - - luaL_openlib(L, 0, methods, 0); // fill methodtable - lua_pop(L, 1); // drop methodtable - - // Can be created from Lua (LuaPseudoRandom(seed)) - lua_register(L, className, create_object); -} - -const char LuaPseudoRandom::className[] = "PseudoRandom"; -const luaL_reg LuaPseudoRandom::methods[] = { - luamethod(LuaPseudoRandom, next), - {0,0} -}; diff --git a/src/scriptapi_noise.h b/src/scriptapi_noise.h deleted file mode 100644 index a02383fde..000000000 --- a/src/scriptapi_noise.h +++ /dev/null @@ -1,133 +0,0 @@ -/* -Minetest-c55 -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 LUA_PERLIN_H_ -#define LUA_PERLIN_H_ - -extern "C" { -#include -#include -} - -#include "noise.h" - -class LuaPerlinNoise -{ -private: - int seed; - int octaves; - float persistence; - float scale; - static const char className[]; - static const luaL_reg methods[]; - - // Exported functions - - // garbage collector - static int gc_object(lua_State *L); - - static int l_get2d(lua_State *L); - static int l_get3d(lua_State *L); - -public: - LuaPerlinNoise(int a_seed, int a_octaves, float a_persistence, - float a_scale); - - ~LuaPerlinNoise(); - - // LuaPerlinNoise(seed, octaves, persistence, scale) - // Creates an LuaPerlinNoise and leaves it on top of stack - static int create_object(lua_State *L); - - static LuaPerlinNoise* checkobject(lua_State *L, int narg); - - static void Register(lua_State *L); -}; - -/* - PerlinNoiseMap - */ -class LuaPerlinNoiseMap -{ -private: - Noise *noise; - static const char className[]; - static const luaL_reg methods[]; - - static int gc_object(lua_State *L); - - static int l_get2dMap(lua_State *L); - - static int l_get3dMap(lua_State *L); - -public: - LuaPerlinNoiseMap(NoiseParams *np, int seed, v3s16 size); - - ~LuaPerlinNoiseMap(); - - // LuaPerlinNoiseMap(np, size) - // Creates an LuaPerlinNoiseMap and leaves it on top of stack - static int create_object(lua_State *L); - - static LuaPerlinNoiseMap *checkobject(lua_State *L, int narg); - - static void Register(lua_State *L); -}; - -/* - LuaPseudoRandom -*/ - - -class LuaPseudoRandom -{ -private: - PseudoRandom m_pseudo; - - static const char className[]; - static const luaL_reg methods[]; - - // Exported functions - - // garbage collector - static int gc_object(lua_State *L); - - // next(self, min=0, max=32767) -> get next value - static int l_next(lua_State *L); - -public: - LuaPseudoRandom(int seed); - - ~LuaPseudoRandom(); - - const PseudoRandom& getItem() const; - PseudoRandom& getItem(); - - // LuaPseudoRandom(seed) - // Creates an LuaPseudoRandom and leaves it on top of stack - static int create_object(lua_State *L); - - static LuaPseudoRandom* checkobject(lua_State *L, int narg); - - static void Register(lua_State *L); -}; - -NoiseParams *read_noiseparams(lua_State *L, int index); - -#endif /* LUA_PERLIN_H_ */ diff --git a/src/scriptapi_object.cpp b/src/scriptapi_object.cpp deleted file mode 100644 index 851f1761f..000000000 --- a/src/scriptapi_object.cpp +++ /dev/null @@ -1,1218 +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. -*/ - -#include "scriptapi.h" -#include "scriptapi_object.h" -#include "log.h" -#include "tool.h" -#include "scriptapi_types.h" -#include "scriptapi_inventory.h" -#include "scriptapi_item.h" -#include "scriptapi_entity.h" -#include "scriptapi_common.h" -#include "hud.h" - - -struct EnumString es_HudElementType[] = -{ - {HUD_ELEM_IMAGE, "image"}, - {HUD_ELEM_TEXT, "text"}, - {HUD_ELEM_STATBAR, "statbar"}, - {HUD_ELEM_INVENTORY, "inventory"}, - {0, NULL}, -}; - -struct EnumString es_HudElementStat[] = -{ - {HUD_STAT_POS, "pos"}, - {HUD_STAT_NAME, "name"}, - {HUD_STAT_SCALE, "scale"}, - {HUD_STAT_TEXT, "text"}, - {HUD_STAT_NUMBER, "number"}, - {HUD_STAT_ITEM, "item"}, - {HUD_STAT_DIR, "direction"}, - {HUD_STAT_ALIGN, "alignment"}, - {HUD_STAT_OFFSET, "offset"}, - {0, NULL}, -}; - -struct EnumString es_HudBuiltinElement[] = -{ - {HUD_FLAG_HOTBAR_VISIBLE, "hotbar"}, - {HUD_FLAG_HEALTHBAR_VISIBLE, "healthbar"}, - {HUD_FLAG_CROSSHAIR_VISIBLE, "crosshair"}, - {HUD_FLAG_WIELDITEM_VISIBLE, "wielditem"}, - {0, NULL}, -}; - - -/* - ObjectRef -*/ - - -ObjectRef* ObjectRef::checkobject(lua_State *L, int narg) -{ - luaL_checktype(L, narg, LUA_TUSERDATA); - void *ud = luaL_checkudata(L, narg, className); - if(!ud) luaL_typerror(L, narg, className); - return *(ObjectRef**)ud; // unbox pointer -} - -ServerActiveObject* ObjectRef::getobject(ObjectRef *ref) -{ - ServerActiveObject *co = ref->m_object; - return co; -} - -LuaEntitySAO* ObjectRef::getluaobject(ObjectRef *ref) -{ - ServerActiveObject *obj = getobject(ref); - if(obj == NULL) - return NULL; - if(obj->getType() != ACTIVEOBJECT_TYPE_LUAENTITY) - return NULL; - return (LuaEntitySAO*)obj; -} - -PlayerSAO* ObjectRef::getplayersao(ObjectRef *ref) -{ - ServerActiveObject *obj = getobject(ref); - if(obj == NULL) - return NULL; - if(obj->getType() != ACTIVEOBJECT_TYPE_PLAYER) - return NULL; - return (PlayerSAO*)obj; -} - -Player* ObjectRef::getplayer(ObjectRef *ref) -{ - PlayerSAO *playersao = getplayersao(ref); - if(playersao == NULL) - return NULL; - return playersao->getPlayer(); -} - -// Exported functions - -// garbage collector -int ObjectRef::gc_object(lua_State *L) { - ObjectRef *o = *(ObjectRef **)(lua_touserdata(L, 1)); - //infostream<<"ObjectRef::gc_object: o="<setPos(pos); - return 0; -} - -// moveto(self, pos, continuous=false) -int ObjectRef::l_moveto(lua_State *L) -{ - ObjectRef *ref = checkobject(L, 1); - //LuaEntitySAO *co = getluaobject(ref); - ServerActiveObject *co = getobject(ref); - if(co == NULL) return 0; - // pos - v3f pos = checkFloatPos(L, 2); - // continuous - bool continuous = lua_toboolean(L, 3); - // Do it - co->moveTo(pos, continuous); - return 0; -} - -// punch(self, puncher, time_from_last_punch, tool_capabilities, dir) -int ObjectRef::l_punch(lua_State *L) -{ - ObjectRef *ref = checkobject(L, 1); - ServerActiveObject *co = getobject(ref); - if(co == NULL) return 0; - - ServerActiveObject *puncher = 0; - v3f dir(0,0,0); - - if (!lua_isnil(L,2)) { - ObjectRef *puncher_ref = checkobject(L, 2); - puncher = getobject(puncher_ref); - if(puncher == NULL) return 0; - - dir = co->getBasePosition() - puncher->getBasePosition(); - } - - float time_from_last_punch = 1000000; - if(lua_isnumber(L, 3)) - time_from_last_punch = lua_tonumber(L, 3); - - ToolCapabilities toolcap = read_tool_capabilities(L, 4); - - if(lua_type(L, 5) == LUA_TTABLE) - dir = read_v3f(L, 5); - dir.normalize(); - - // Do it - co->punch(dir, &toolcap, puncher, time_from_last_punch); - return 0; -} - -// right_click(self, clicker); clicker = an another ObjectRef -int ObjectRef::l_right_click(lua_State *L) -{ - ObjectRef *ref = checkobject(L, 1); - ObjectRef *ref2 = checkobject(L, 2); - ServerActiveObject *co = getobject(ref); - ServerActiveObject *co2 = getobject(ref2); - if(co == NULL) return 0; - if(co2 == NULL) return 0; - // Do it - co->rightClick(co2); - return 0; -} - -// set_hp(self, hp) -// hp = number of hitpoints (2 * number of hearts) -// returns: nil -int ObjectRef::l_set_hp(lua_State *L) -{ - ObjectRef *ref = checkobject(L, 1); - luaL_checknumber(L, 2); - ServerActiveObject *co = getobject(ref); - if(co == NULL) return 0; - int hp = lua_tonumber(L, 2); - /*infostream<<"ObjectRef::l_set_hp(): id="<getId() - <<" hp="<setHP(hp); - // Return - return 0; -} - -// get_hp(self) -// returns: number of hitpoints (2 * number of hearts) -// 0 if not applicable to this type of object -int ObjectRef::l_get_hp(lua_State *L) -{ - ObjectRef *ref = checkobject(L, 1); - ServerActiveObject *co = getobject(ref); - if(co == NULL){ - // Default hp is 1 - lua_pushnumber(L, 1); - return 1; - } - int hp = co->getHP(); - /*infostream<<"ObjectRef::l_get_hp(): id="<getId() - <<" hp="<getInventoryLocation(); - if(get_server(L)->getInventory(loc) != NULL) - InvRef::create(L, loc); - else - lua_pushnil(L); // An object may have no inventory (nil) - return 1; -} - -// get_wield_list(self) -int ObjectRef::l_get_wield_list(lua_State *L) -{ - ObjectRef *ref = checkobject(L, 1); - ServerActiveObject *co = getobject(ref); - if(co == NULL) return 0; - // Do it - lua_pushstring(L, co->getWieldList().c_str()); - return 1; -} - -// get_wield_index(self) -int ObjectRef::l_get_wield_index(lua_State *L) -{ - ObjectRef *ref = checkobject(L, 1); - ServerActiveObject *co = getobject(ref); - if(co == NULL) return 0; - // Do it - lua_pushinteger(L, co->getWieldIndex() + 1); - return 1; -} - -// get_wielded_item(self) -int ObjectRef::l_get_wielded_item(lua_State *L) -{ - ObjectRef *ref = checkobject(L, 1); - ServerActiveObject *co = getobject(ref); - if(co == NULL){ - // Empty ItemStack - LuaItemStack::create(L, ItemStack()); - return 1; - } - // Do it - LuaItemStack::create(L, co->getWieldedItem()); - return 1; -} - -// set_wielded_item(self, itemstack or itemstring or table or nil) -int ObjectRef::l_set_wielded_item(lua_State *L) -{ - ObjectRef *ref = checkobject(L, 1); - ServerActiveObject *co = getobject(ref); - if(co == NULL) return 0; - // Do it - ItemStack item = read_item(L, 2); - bool success = co->setWieldedItem(item); - lua_pushboolean(L, success); - return 1; -} - -// set_armor_groups(self, groups) -int ObjectRef::l_set_armor_groups(lua_State *L) -{ - ObjectRef *ref = checkobject(L, 1); - ServerActiveObject *co = getobject(ref); - if(co == NULL) return 0; - // Do it - ItemGroupList groups; - read_groups(L, 2, groups); - co->setArmorGroups(groups); - return 0; -} - -// set_physics_override(self, physics_override_speed, physics_override_jump, physics_override_gravity) -int ObjectRef::l_set_physics_override(lua_State *L) -{ - ObjectRef *ref = checkobject(L, 1); - PlayerSAO *co = (PlayerSAO *) getobject(ref); - if(co == NULL) return 0; - // Do it - if(!lua_isnil(L, 2)){ - co->m_physics_override_speed = lua_tonumber(L, 2); - co->m_physics_override_sent = false; - } - if(!lua_isnil(L, 3)){ - co->m_physics_override_jump = lua_tonumber(L, 3); - co->m_physics_override_sent = false; - } - if(!lua_isnil(L, 4)){ - co->m_physics_override_gravity = lua_tonumber(L, 4); - co->m_physics_override_sent = false; - } - return 0; -} - -// set_animation(self, frame_range, frame_speed, frame_blend) -int ObjectRef::l_set_animation(lua_State *L) -{ - ObjectRef *ref = checkobject(L, 1); - ServerActiveObject *co = getobject(ref); - if(co == NULL) return 0; - // Do it - v2f frames = v2f(1, 1); - if(!lua_isnil(L, 2)) - frames = read_v2f(L, 2); - float frame_speed = 15; - if(!lua_isnil(L, 3)) - frame_speed = lua_tonumber(L, 3); - float frame_blend = 0; - if(!lua_isnil(L, 4)) - frame_blend = lua_tonumber(L, 4); - co->setAnimation(frames, frame_speed, frame_blend); - return 0; -} - -// set_bone_position(self, std::string bone, v3f position, v3f rotation) -int ObjectRef::l_set_bone_position(lua_State *L) -{ - ObjectRef *ref = checkobject(L, 1); - ServerActiveObject *co = getobject(ref); - if(co == NULL) return 0; - // Do it - std::string bone = ""; - if(!lua_isnil(L, 2)) - bone = lua_tostring(L, 2); - v3f position = v3f(0, 0, 0); - if(!lua_isnil(L, 3)) - position = read_v3f(L, 3); - v3f rotation = v3f(0, 0, 0); - if(!lua_isnil(L, 4)) - rotation = read_v3f(L, 4); - co->setBonePosition(bone, position, rotation); - return 0; -} - -// set_attach(self, parent, bone, position, rotation) -int ObjectRef::l_set_attach(lua_State *L) -{ - ObjectRef *ref = checkobject(L, 1); - ObjectRef *parent_ref = checkobject(L, 2); - ServerActiveObject *co = getobject(ref); - ServerActiveObject *parent = getobject(parent_ref); - if(co == NULL) return 0; - if(parent == NULL) return 0; - // Do it - std::string bone = ""; - if(!lua_isnil(L, 3)) - bone = lua_tostring(L, 3); - v3f position = v3f(0, 0, 0); - if(!lua_isnil(L, 4)) - position = read_v3f(L, 4); - v3f rotation = v3f(0, 0, 0); - if(!lua_isnil(L, 5)) - rotation = read_v3f(L, 5); - co->setAttachment(parent->getId(), bone, position, rotation); - return 0; -} - -// set_detach(self) -int ObjectRef::l_set_detach(lua_State *L) -{ - ObjectRef *ref = checkobject(L, 1); - ServerActiveObject *co = getobject(ref); - if(co == NULL) return 0; - // Do it - co->setAttachment(0, "", v3f(0,0,0), v3f(0,0,0)); - return 0; -} - -// set_properties(self, properties) -int ObjectRef::l_set_properties(lua_State *L) -{ - ObjectRef *ref = checkobject(L, 1); - ServerActiveObject *co = getobject(ref); - if(co == NULL) return 0; - ObjectProperties *prop = co->accessObjectProperties(); - if(!prop) - return 0; - read_object_properties(L, 2, prop); - co->notifyObjectPropertiesModified(); - return 0; -} - -/* LuaEntitySAO-only */ - -// setvelocity(self, {x=num, y=num, z=num}) -int ObjectRef::l_setvelocity(lua_State *L) -{ - ObjectRef *ref = checkobject(L, 1); - LuaEntitySAO *co = getluaobject(ref); - if(co == NULL) return 0; - v3f pos = checkFloatPos(L, 2); - // Do it - co->setVelocity(pos); - return 0; -} - -// getvelocity(self) -int ObjectRef::l_getvelocity(lua_State *L) -{ - ObjectRef *ref = checkobject(L, 1); - LuaEntitySAO *co = getluaobject(ref); - if(co == NULL) return 0; - // Do it - v3f v = co->getVelocity(); - pushFloatPos(L, v); - return 1; -} - -// setacceleration(self, {x=num, y=num, z=num}) -int ObjectRef::l_setacceleration(lua_State *L) -{ - ObjectRef *ref = checkobject(L, 1); - LuaEntitySAO *co = getluaobject(ref); - if(co == NULL) return 0; - // pos - v3f pos = checkFloatPos(L, 2); - // Do it - co->setAcceleration(pos); - return 0; -} - -// getacceleration(self) -int ObjectRef::l_getacceleration(lua_State *L) -{ - ObjectRef *ref = checkobject(L, 1); - LuaEntitySAO *co = getluaobject(ref); - if(co == NULL) return 0; - // Do it - v3f v = co->getAcceleration(); - pushFloatPos(L, v); - return 1; -} - -// setyaw(self, radians) -int ObjectRef::l_setyaw(lua_State *L) -{ - ObjectRef *ref = checkobject(L, 1); - LuaEntitySAO *co = getluaobject(ref); - if(co == NULL) return 0; - float yaw = luaL_checknumber(L, 2) * core::RADTODEG; - // Do it - co->setYaw(yaw); - return 0; -} - -// getyaw(self) -int ObjectRef::l_getyaw(lua_State *L) -{ - ObjectRef *ref = checkobject(L, 1); - LuaEntitySAO *co = getluaobject(ref); - if(co == NULL) return 0; - // Do it - float yaw = co->getYaw() * core::DEGTORAD; - lua_pushnumber(L, yaw); - return 1; -} - -// settexturemod(self, mod) -int ObjectRef::l_settexturemod(lua_State *L) -{ - ObjectRef *ref = checkobject(L, 1); - LuaEntitySAO *co = getluaobject(ref); - if(co == NULL) return 0; - // Do it - std::string mod = luaL_checkstring(L, 2); - co->setTextureMod(mod); - return 0; -} - -// setsprite(self, p={x=0,y=0}, num_frames=1, framelength=0.2, -// select_horiz_by_yawpitch=false) -int ObjectRef::l_setsprite(lua_State *L) -{ - ObjectRef *ref = checkobject(L, 1); - LuaEntitySAO *co = getluaobject(ref); - if(co == NULL) return 0; - // Do it - v2s16 p(0,0); - if(!lua_isnil(L, 2)) - p = read_v2s16(L, 2); - int num_frames = 1; - if(!lua_isnil(L, 3)) - num_frames = lua_tonumber(L, 3); - float framelength = 0.2; - if(!lua_isnil(L, 4)) - framelength = lua_tonumber(L, 4); - bool select_horiz_by_yawpitch = false; - if(!lua_isnil(L, 5)) - select_horiz_by_yawpitch = lua_toboolean(L, 5); - co->setSprite(p, num_frames, framelength, select_horiz_by_yawpitch); - return 0; -} - -// DEPRECATED -// get_entity_name(self) -int ObjectRef::l_get_entity_name(lua_State *L) -{ - ObjectRef *ref = checkobject(L, 1); - LuaEntitySAO *co = getluaobject(ref); - if(co == NULL) return 0; - // Do it - std::string name = co->getName(); - lua_pushstring(L, name.c_str()); - return 1; -} - -// get_luaentity(self) -int ObjectRef::l_get_luaentity(lua_State *L) -{ - ObjectRef *ref = checkobject(L, 1); - LuaEntitySAO *co = getluaobject(ref); - if(co == NULL) return 0; - // Do it - luaentity_get(L, co->getId()); - return 1; -} - -/* Player-only */ - -// is_player(self) -int ObjectRef::l_is_player(lua_State *L) -{ - ObjectRef *ref = checkobject(L, 1); - Player *player = getplayer(ref); - lua_pushboolean(L, (player != NULL)); - return 1; -} - -// get_player_name(self) -int ObjectRef::l_get_player_name(lua_State *L) -{ - ObjectRef *ref = checkobject(L, 1); - Player *player = getplayer(ref); - if(player == NULL){ - lua_pushlstring(L, "", 0); - return 1; - } - // Do it - lua_pushstring(L, player->getName()); - return 1; -} - -// get_look_dir(self) -int ObjectRef::l_get_look_dir(lua_State *L) -{ - ObjectRef *ref = checkobject(L, 1); - Player *player = getplayer(ref); - if(player == NULL) return 0; - // Do it - float pitch = player->getRadPitch(); - float yaw = player->getRadYaw(); - v3f v(cos(pitch)*cos(yaw), sin(pitch), cos(pitch)*sin(yaw)); - push_v3f(L, v); - return 1; -} - -// get_look_pitch(self) -int ObjectRef::l_get_look_pitch(lua_State *L) -{ - ObjectRef *ref = checkobject(L, 1); - Player *player = getplayer(ref); - if(player == NULL) return 0; - // Do it - lua_pushnumber(L, player->getRadPitch()); - return 1; -} - -// get_look_yaw(self) -int ObjectRef::l_get_look_yaw(lua_State *L) -{ - ObjectRef *ref = checkobject(L, 1); - Player *player = getplayer(ref); - if(player == NULL) return 0; - // Do it - lua_pushnumber(L, player->getRadYaw()); - return 1; -} - -// set_look_pitch(self, radians) -int ObjectRef::l_set_look_pitch(lua_State *L) -{ - ObjectRef *ref = checkobject(L, 1); - PlayerSAO* co = getplayersao(ref); - if(co == NULL) return 0; - float pitch = luaL_checknumber(L, 2) * core::RADTODEG; - // Do it - co->setPitch(pitch); - return 1; -} - -// set_look_yaw(self, radians) -int ObjectRef::l_set_look_yaw(lua_State *L) -{ - ObjectRef *ref = checkobject(L, 1); - PlayerSAO* co = getplayersao(ref); - if(co == NULL) return 0; - float yaw = luaL_checknumber(L, 2) * core::RADTODEG; - // Do it - co->setYaw(yaw); - return 1; -} - -// set_inventory_formspec(self, formspec) -int ObjectRef::l_set_inventory_formspec(lua_State *L) -{ - ObjectRef *ref = checkobject(L, 1); - Player *player = getplayer(ref); - if(player == NULL) return 0; - std::string formspec = luaL_checkstring(L, 2); - - player->inventory_formspec = formspec; - get_server(L)->reportInventoryFormspecModified(player->getName()); - lua_pushboolean(L, true); - return 1; -} - -// get_inventory_formspec(self) -> formspec -int ObjectRef::l_get_inventory_formspec(lua_State *L) -{ - ObjectRef *ref = checkobject(L, 1); - Player *player = getplayer(ref); - if(player == NULL) return 0; - - std::string formspec = player->inventory_formspec; - lua_pushlstring(L, formspec.c_str(), formspec.size()); - return 1; -} - -// get_player_control(self) -int ObjectRef::l_get_player_control(lua_State *L) -{ - ObjectRef *ref = checkobject(L, 1); - Player *player = getplayer(ref); - if(player == NULL){ - lua_pushlstring(L, "", 0); - return 1; - } - // Do it - PlayerControl control = player->getPlayerControl(); - lua_newtable(L); - lua_pushboolean(L, control.up); - lua_setfield(L, -2, "up"); - lua_pushboolean(L, control.down); - lua_setfield(L, -2, "down"); - lua_pushboolean(L, control.left); - lua_setfield(L, -2, "left"); - lua_pushboolean(L, control.right); - lua_setfield(L, -2, "right"); - lua_pushboolean(L, control.jump); - lua_setfield(L, -2, "jump"); - lua_pushboolean(L, control.aux1); - lua_setfield(L, -2, "aux1"); - lua_pushboolean(L, control.sneak); - lua_setfield(L, -2, "sneak"); - lua_pushboolean(L, control.LMB); - lua_setfield(L, -2, "LMB"); - lua_pushboolean(L, control.RMB); - lua_setfield(L, -2, "RMB"); - return 1; -} - -// get_player_control_bits(self) -int ObjectRef::l_get_player_control_bits(lua_State *L) -{ - ObjectRef *ref = checkobject(L, 1); - Player *player = getplayer(ref); - if(player == NULL){ - lua_pushlstring(L, "", 0); - return 1; - } - // Do it - lua_pushnumber(L, player->keyPressed); - return 1; -} - -// hud_add(self, form) -int ObjectRef::l_hud_add(lua_State *L) -{ - ObjectRef *ref = checkobject(L, 1); - Player *player = getplayer(ref); - if (player == NULL) - return 0; - - HudElement *elem = new HudElement; - - elem->type = (HudElementType)getenumfield(L, 2, "hud_elem_type", - es_HudElementType, HUD_ELEM_TEXT); - - lua_getfield(L, 2, "position"); - elem->pos = lua_istable(L, -1) ? read_v2f(L, -1) : v2f(); - lua_pop(L, 1); - - lua_getfield(L, 2, "scale"); - elem->scale = lua_istable(L, -1) ? read_v2f(L, -1) : v2f(); - lua_pop(L, 1); - - elem->name = getstringfield_default(L, 2, "name", ""); - elem->text = getstringfield_default(L, 2, "text", ""); - elem->number = getintfield_default(L, 2, "number", 0); - elem->item = getintfield_default(L, 2, "item", 0); - elem->dir = getintfield_default(L, 2, "direction", 0); - - lua_getfield(L, 2, "alignment"); - elem->align = lua_istable(L, -1) ? read_v2f(L, -1) : v2f(); - lua_pop(L, 1); - - lua_getfield(L, 2, "offset"); - elem->offset = lua_istable(L, -1) ? read_v2f(L, -1) : v2f(); - lua_pop(L, 1); - - u32 id = get_server(L)->hudAdd(player, elem); - if (id == (u32)-1) { - delete elem; - return 0; - } - - lua_pushnumber(L, id); - return 1; -} - -// hud_remove(self, id) -int ObjectRef::l_hud_remove(lua_State *L) -{ - ObjectRef *ref = checkobject(L, 1); - Player *player = getplayer(ref); - if (player == NULL) - return 0; - - u32 id = -1; - if (!lua_isnil(L, 2)) - id = lua_tonumber(L, 2); - - if (!get_server(L)->hudRemove(player, id)) - return 0; - - lua_pushboolean(L, true); - return 1; -} - -// hud_change(self, id, stat, data) -int ObjectRef::l_hud_change(lua_State *L) -{ - ObjectRef *ref = checkobject(L, 1); - Player *player = getplayer(ref); - if (player == NULL) - return 0; - - u32 id = !lua_isnil(L, 2) ? lua_tonumber(L, 2) : -1; - if (id >= player->hud.size()) - return 0; - - HudElementStat stat = HUD_STAT_NUMBER; - if (!lua_isnil(L, 3)) { - int statint; - std::string statstr = lua_tostring(L, 3); - stat = string_to_enum(es_HudElementStat, statint, statstr) ? - (HudElementStat)statint : HUD_STAT_NUMBER; - } - - void *value = NULL; - HudElement *e = player->hud[id]; - if (!e) - return 0; - - switch (stat) { - case HUD_STAT_POS: - e->pos = read_v2f(L, 4); - value = &e->pos; - break; - case HUD_STAT_NAME: - e->name = lua_tostring(L, 4); - value = &e->name; - break; - case HUD_STAT_SCALE: - e->scale = read_v2f(L, 4); - value = &e->scale; - break; - case HUD_STAT_TEXT: - e->text = lua_tostring(L, 4); - value = &e->text; - break; - case HUD_STAT_NUMBER: - e->number = lua_tonumber(L, 4); - value = &e->number; - break; - case HUD_STAT_ITEM: - e->item = lua_tonumber(L, 4); - value = &e->item; - break; - case HUD_STAT_DIR: - e->dir = lua_tonumber(L, 4); - value = &e->dir; - case HUD_STAT_ALIGN: - e->align = read_v2f(L, 4); - value = &e->align; - case HUD_STAT_OFFSET: - e->offset = read_v2f(L, 4); - value = &e->offset; - } - - get_server(L)->hudChange(player, id, stat, value); - - lua_pushboolean(L, true); - return 1; -} - -// hud_get(self, id) -int ObjectRef::l_hud_get(lua_State *L) -{ - ObjectRef *ref = checkobject(L, 1); - Player *player = getplayer(ref); - if (player == NULL) - return 0; - - u32 id = lua_tonumber(L, -1); - if (id >= player->hud.size()) - return 0; - - HudElement *e = player->hud[id]; - if (!e) - return 0; - - lua_newtable(L); - - lua_pushstring(L, es_HudElementType[(u8)e->type].str); - lua_setfield(L, -2, "type"); - - push_v2f(L, e->pos); - lua_setfield(L, -2, "position"); - - lua_pushstring(L, e->name.c_str()); - lua_setfield(L, -2, "name"); - - push_v2f(L, e->scale); - lua_setfield(L, -2, "scale"); - - lua_pushstring(L, e->text.c_str()); - lua_setfield(L, -2, "text"); - - lua_pushnumber(L, e->number); - lua_setfield(L, -2, "number"); - - lua_pushnumber(L, e->item); - lua_setfield(L, -2, "item"); - - lua_pushnumber(L, e->dir); - lua_setfield(L, -2, "dir"); - - return 1; -} - -// hud_set_flags(self, flags) -int ObjectRef::l_hud_set_flags(lua_State *L) -{ - ObjectRef *ref = checkobject(L, 1); - Player *player = getplayer(ref); - if (player == NULL) - return 0; - - u32 flags = 0; - u32 mask = 0; - bool flag; - - const EnumString *esp = es_HudBuiltinElement; - for (int i = 0; esp[i].str; i++) { - if (getboolfield(L, 2, esp[i].str, flag)) { - flags |= esp[i].num * flag; - mask |= esp[i].num; - } - } - if (!get_server(L)->hudSetFlags(player, flags, mask)) - return 0; - - lua_pushboolean(L, true); - return 1; -} - -ObjectRef::ObjectRef(ServerActiveObject *object): - m_object(object) -{ - //infostream<<"ObjectRef created for id="<getId()<getId() == 0){ - ObjectRef::create(L, cobj); - } else { - objectref_get(L, cobj->getId()); - } -} - -void objectref_get(lua_State *L, u16 id) -{ - // Get minetest.object_refs[i] - lua_getglobal(L, "minetest"); - lua_getfield(L, -1, "object_refs"); - luaL_checktype(L, -1, LUA_TTABLE); - lua_pushnumber(L, id); - lua_gettable(L, -2); - lua_remove(L, -2); // object_refs - lua_remove(L, -2); // minetest -} - -/* - ObjectProperties -*/ - -void read_object_properties(lua_State *L, int index, - ObjectProperties *prop) -{ - if(index < 0) - index = lua_gettop(L) + 1 + index; - if(!lua_istable(L, index)) - return; - - prop->hp_max = getintfield_default(L, -1, "hp_max", 10); - - getboolfield(L, -1, "physical", prop->physical); - - getfloatfield(L, -1, "weight", prop->weight); - - lua_getfield(L, -1, "collisionbox"); - if(lua_istable(L, -1)) - prop->collisionbox = read_aabb3f(L, -1, 1.0); - lua_pop(L, 1); - - getstringfield(L, -1, "visual", prop->visual); - - getstringfield(L, -1, "mesh", prop->mesh); - - lua_getfield(L, -1, "visual_size"); - if(lua_istable(L, -1)) - prop->visual_size = read_v2f(L, -1); - lua_pop(L, 1); - - lua_getfield(L, -1, "textures"); - if(lua_istable(L, -1)){ - prop->textures.clear(); - int table = lua_gettop(L); - lua_pushnil(L); - while(lua_next(L, table) != 0){ - // key at index -2 and value at index -1 - if(lua_isstring(L, -1)) - prop->textures.push_back(lua_tostring(L, -1)); - else - prop->textures.push_back(""); - // removes value, keeps key for next iteration - lua_pop(L, 1); - } - } - lua_pop(L, 1); - - lua_getfield(L, -1, "colors"); - if(lua_istable(L, -1)){ - prop->colors.clear(); - int table = lua_gettop(L); - lua_pushnil(L); - while(lua_next(L, table) != 0){ - // key at index -2 and value at index -1 - if(lua_isstring(L, -1)) - prop->colors.push_back(readARGB8(L, -1)); - else - prop->colors.push_back(video::SColor(255, 255, 255, 255)); - // removes value, keeps key for next iteration - lua_pop(L, 1); - } - } - lua_pop(L, 1); - - lua_getfield(L, -1, "spritediv"); - if(lua_istable(L, -1)) - prop->spritediv = read_v2s16(L, -1); - lua_pop(L, 1); - - lua_getfield(L, -1, "initial_sprite_basepos"); - if(lua_istable(L, -1)) - prop->initial_sprite_basepos = read_v2s16(L, -1); - lua_pop(L, 1); - - getboolfield(L, -1, "is_visible", prop->is_visible); - getboolfield(L, -1, "makes_footstep_sound", prop->makes_footstep_sound); - getfloatfield(L, -1, "automatic_rotate", prop->automatic_rotate); -} - -/* - object_reference -*/ - -void scriptapi_add_object_reference(lua_State *L, ServerActiveObject *cobj) -{ - realitycheck(L); - assert(lua_checkstack(L, 20)); - //infostream<<"scriptapi_add_object_reference: id="<getId()<getId()); // Push id - lua_pushvalue(L, object); // Copy object to top of stack - lua_settable(L, objectstable); -} - -void scriptapi_rm_object_reference(lua_State *L, ServerActiveObject *cobj) -{ - realitycheck(L); - assert(lua_checkstack(L, 20)); - //infostream<<"scriptapi_rm_object_reference: id="<getId()<getId()); // Push id - lua_gettable(L, objectstable); - // Set object reference to NULL - ObjectRef::set_null(L); - lua_pop(L, 1); // pop object - - // Set object_refs[id] = nil - lua_pushnumber(L, cobj->getId()); // Push id - lua_pushnil(L); - lua_settable(L, objectstable); -} diff --git a/src/scriptapi_object.h b/src/scriptapi_object.h deleted file mode 100644 index 82535ee94..000000000 --- a/src/scriptapi_object.h +++ /dev/null @@ -1,238 +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 LUA_OBJECT_H_ -#define LUA_OBJECT_H_ - -extern "C" { -#include -#include -} - -#include "serverobject.h" -#include "content_sao.h" -#include "player.h" - -/* - ObjectRef -*/ - -class ObjectRef -{ -private: - ServerActiveObject *m_object; - - static const char className[]; - static const luaL_reg methods[]; -public: - static ObjectRef *checkobject(lua_State *L, int narg); - - static ServerActiveObject* getobject(ObjectRef *ref); -private: - static LuaEntitySAO* getluaobject(ObjectRef *ref); - - static PlayerSAO* getplayersao(ObjectRef *ref); - - static Player* getplayer(ObjectRef *ref); - - // Exported functions - - // garbage collector - static int gc_object(lua_State *L); - - // remove(self) - static int l_remove(lua_State *L); - - // getpos(self) - // returns: {x=num, y=num, z=num} - static int l_getpos(lua_State *L); - - // setpos(self, pos) - static int l_setpos(lua_State *L); - - // moveto(self, pos, continuous=false) - static int l_moveto(lua_State *L); - - // punch(self, puncher, time_from_last_punch, tool_capabilities, dir) - static int l_punch(lua_State *L); - - // right_click(self, clicker); clicker = an another ObjectRef - static int l_right_click(lua_State *L); - - // set_hp(self, hp) - // hp = number of hitpoints (2 * number of hearts) - // returns: nil - static int l_set_hp(lua_State *L); - - // get_hp(self) - // returns: number of hitpoints (2 * number of hearts) - // 0 if not applicable to this type of object - static int l_get_hp(lua_State *L); - - // get_inventory(self) - static int l_get_inventory(lua_State *L); - - // get_wield_list(self) - static int l_get_wield_list(lua_State *L); - - // get_wield_index(self) - static int l_get_wield_index(lua_State *L); - - // get_wielded_item(self) - static int l_get_wielded_item(lua_State *L); - - // set_wielded_item(self, itemstack or itemstring or table or nil) - static int l_set_wielded_item(lua_State *L); - - // set_armor_groups(self, groups) - static int l_set_armor_groups(lua_State *L); - - // set_physics_override(self, physics_override_speed, physics_override_jump, physics_override_gravity) - static int l_set_physics_override(lua_State *L); - - // set_animation(self, frame_range, frame_speed, frame_blend) - static int l_set_animation(lua_State *L); - - // set_bone_position(self, std::string bone, v3f position, v3f rotation) - static int l_set_bone_position(lua_State *L); - - // set_attach(self, parent, bone, position, rotation) - static int l_set_attach(lua_State *L); - - // set_detach(self) - static int l_set_detach(lua_State *L); - - // set_properties(self, properties) - static int l_set_properties(lua_State *L); - - /* LuaEntitySAO-only */ - - // setvelocity(self, {x=num, y=num, z=num}) - static int l_setvelocity(lua_State *L); - - // getvelocity(self) - static int l_getvelocity(lua_State *L); - - // setacceleration(self, {x=num, y=num, z=num}) - static int l_setacceleration(lua_State *L); - - // getacceleration(self) - static int l_getacceleration(lua_State *L); - - // setyaw(self, radians) - static int l_setyaw(lua_State *L); - - // getyaw(self) - static int l_getyaw(lua_State *L); - - // settexturemod(self, mod) - static int l_settexturemod(lua_State *L); - - // setsprite(self, p={x=0,y=0}, num_frames=1, framelength=0.2, - // select_horiz_by_yawpitch=false) - static int l_setsprite(lua_State *L); - - // DEPRECATED - // get_entity_name(self) - static int l_get_entity_name(lua_State *L); - - // get_luaentity(self) - static int l_get_luaentity(lua_State *L); - - /* Player-only */ - - // is_player(self) - static int l_is_player(lua_State *L); - - // get_player_name(self) - static int l_get_player_name(lua_State *L); - - // get_look_dir(self) - static int l_get_look_dir(lua_State *L); - - // get_look_pitch(self) - static int l_get_look_pitch(lua_State *L); - - // get_look_yaw(self) - static int l_get_look_yaw(lua_State *L); - - // set_look_pitch(self, radians) - static int l_set_look_pitch(lua_State *L); - - // set_look_yaw(self, radians) - static int l_set_look_yaw(lua_State *L); - - // set_inventory_formspec(self, formspec) - static int l_set_inventory_formspec(lua_State *L); - - // get_inventory_formspec(self) -> formspec - static int l_get_inventory_formspec(lua_State *L); - - // get_player_control(self) - static int l_get_player_control(lua_State *L); - - // get_player_control_bits(self) - static int l_get_player_control_bits(lua_State *L); - - // hud_add(self, id, form) - static int l_hud_add(lua_State *L); - - // hud_rm(self, id) - static int l_hud_remove(lua_State *L); - - // hud_change(self, id, stat, data) - static int l_hud_change(lua_State *L); - - // hud_get(self, id) - static int l_hud_get(lua_State *L); - - // hud_set_flags(self, flags) - static int l_hud_set_flags(lua_State *L); - -public: - ObjectRef(ServerActiveObject *object); - - ~ObjectRef(); - - // Creates an ObjectRef and leaves it on top of stack - // Not callable from Lua; all references are created on the C side. - static void create(lua_State *L, ServerActiveObject *object); - - static void set_null(lua_State *L); - - static void Register(lua_State *L); -}; - -/*****************************************************************************/ -/* scriptapi internal */ -/*****************************************************************************/ -// Creates a new anonymous reference if cobj=NULL or id=0 -void objectref_get_or_create(lua_State *L, - ServerActiveObject *cobj); -void objectref_get(lua_State *L, u16 id); -void read_object_properties(lua_State *L, int index, - ObjectProperties *prop); - -/*****************************************************************************/ -/* Minetest interface */ -/*****************************************************************************/ -void scriptapi_add_object_reference(lua_State *L, ServerActiveObject *cobj); -void scriptapi_rm_object_reference(lua_State *L, ServerActiveObject *cobj); - -#endif /* LUA_OBJECT_H_ */ diff --git a/src/scriptapi_particles.cpp b/src/scriptapi_particles.cpp deleted file mode 100644 index dc9b3776e..000000000 --- a/src/scriptapi_particles.cpp +++ /dev/null @@ -1,143 +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. -*/ - -#include "scriptapi.h" -#include "scriptapi_particles.h" -#include "server.h" -#include "script.h" -#include "scriptapi_types.h" -#include "scriptapi_common.h" - -// add_particle(pos, velocity, acceleration, expirationtime, -// size, collisiondetection, texture, player) -// pos/velocity/acceleration = {x=num, y=num, z=num} -// expirationtime = num (seconds) -// size = num -// texture = e.g."default_wood.png" -int l_add_particle(lua_State *L) -{ - // Get server from registry - Server *server = get_server(L); - // Get parameters - v3f pos = check_v3f(L, 1); - v3f vel = check_v3f(L, 2); - v3f acc = check_v3f(L, 3); - float expirationtime = luaL_checknumber(L, 4); - float size = luaL_checknumber(L, 5); - bool collisiondetection = lua_toboolean(L, 6); - std::string texture = luaL_checkstring(L, 7); - - if (lua_gettop(L) == 8) // only spawn for a single player - { - const char *playername = luaL_checkstring(L, 8); - server->spawnParticle(playername, - pos, vel, acc, expirationtime, - size, collisiondetection, texture); - } - else // spawn for all players - { - server->spawnParticleAll(pos, vel, acc, - expirationtime, size, collisiondetection, texture); - } - return 1; -} - -// add_particlespawner(amount, time, -// minpos, maxpos, -// minvel, maxvel, -// minacc, maxacc, -// minexptime, maxexptime, -// minsize, maxsize, -// collisiondetection, -// texture, -// player) -// minpos/maxpos/minvel/maxvel/minacc/maxacc = {x=num, y=num, z=num} -// minexptime/maxexptime = num (seconds) -// minsize/maxsize = num -// collisiondetection = bool -// texture = e.g."default_wood.png" -int l_add_particlespawner(lua_State *L) -{ - // Get server from registry - Server *server = get_server(L); - // Get parameters - u16 amount = luaL_checknumber(L, 1); - float time = luaL_checknumber(L, 2); - v3f minpos = check_v3f(L, 3); - v3f maxpos = check_v3f(L, 4); - v3f minvel = check_v3f(L, 5); - v3f maxvel = check_v3f(L, 6); - v3f minacc = check_v3f(L, 7); - v3f maxacc = check_v3f(L, 8); - float minexptime = luaL_checknumber(L, 9); - float maxexptime = luaL_checknumber(L, 10); - float minsize = luaL_checknumber(L, 11); - float maxsize = luaL_checknumber(L, 12); - bool collisiondetection = lua_toboolean(L, 13); - std::string texture = luaL_checkstring(L, 14); - - if (lua_gettop(L) == 15) // only spawn for a single player - { - const char *playername = luaL_checkstring(L, 15); - u32 id = server->addParticleSpawner(playername, - amount, time, - minpos, maxpos, - minvel, maxvel, - minacc, maxacc, - minexptime, maxexptime, - minsize, maxsize, - collisiondetection, - texture); - lua_pushnumber(L, id); - } - else // spawn for all players - { - u32 id = server->addParticleSpawnerAll( amount, time, - minpos, maxpos, - minvel, maxvel, - minacc, maxacc, - minexptime, maxexptime, - minsize, maxsize, - collisiondetection, - texture); - lua_pushnumber(L, id); - } - return 1; -} - -// delete_particlespawner(id, player) -// player (string) is optional -int l_delete_particlespawner(lua_State *L) -{ - // Get server from registry - Server *server = get_server(L); - // Get parameters - u32 id = luaL_checknumber(L, 1); - - if (lua_gettop(L) == 2) // only delete for one player - { - const char *playername = luaL_checkstring(L, 2); - server->deleteParticleSpawner(playername, id); - } - else // delete for all players - { - server->deleteParticleSpawnerAll(id); - } - return 1; -} diff --git a/src/scriptapi_particles.h b/src/scriptapi_particles.h deleted file mode 100644 index 4b37d7ce1..000000000 --- a/src/scriptapi_particles.h +++ /dev/null @@ -1,32 +0,0 @@ -/* -Minetest-c55 -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 LUA_PARTICLES_H_ -#define LUA_PARTICLES_H_ - -extern "C" { -#include -#include -} - -int l_add_particle(lua_State *L); -int l_add_particlespawner(lua_State *L); -int l_delete_particlespawner(lua_State *L); - -#endif diff --git a/src/scriptapi_types.cpp b/src/scriptapi_types.cpp deleted file mode 100644 index f2f6b6bd8..000000000 --- a/src/scriptapi_types.cpp +++ /dev/null @@ -1,388 +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. -*/ - -#include "scriptapi.h" -#include "scriptapi_types.h" - -extern "C" { -#include -} - -#include "util/numeric.h" -#include "nodedef.h" - -/* - C struct <-> Lua table converter functions -*/ - -void push_v3f(lua_State *L, v3f p) -{ - lua_newtable(L); - lua_pushnumber(L, p.X); - lua_setfield(L, -2, "x"); - lua_pushnumber(L, p.Y); - lua_setfield(L, -2, "y"); - lua_pushnumber(L, p.Z); - lua_setfield(L, -2, "z"); -} - -void push_v2f(lua_State *L, v2f p) -{ - lua_newtable(L); - lua_pushnumber(L, p.X); - lua_setfield(L, -2, "x"); - lua_pushnumber(L, p.Y); - lua_setfield(L, -2, "y"); -} - -v2s16 read_v2s16(lua_State *L, int index) -{ - v2s16 p; - luaL_checktype(L, index, LUA_TTABLE); - lua_getfield(L, index, "x"); - p.X = lua_tonumber(L, -1); - lua_pop(L, 1); - lua_getfield(L, index, "y"); - p.Y = lua_tonumber(L, -1); - lua_pop(L, 1); - return p; -} - -v2f read_v2f(lua_State *L, int index) -{ - v2f p; - luaL_checktype(L, index, LUA_TTABLE); - lua_getfield(L, index, "x"); - p.X = lua_tonumber(L, -1); - lua_pop(L, 1); - lua_getfield(L, index, "y"); - p.Y = lua_tonumber(L, -1); - lua_pop(L, 1); - return p; -} - -v3f read_v3f(lua_State *L, int index) -{ - v3f pos; - luaL_checktype(L, index, LUA_TTABLE); - lua_getfield(L, index, "x"); - pos.X = lua_tonumber(L, -1); - lua_pop(L, 1); - lua_getfield(L, index, "y"); - pos.Y = lua_tonumber(L, -1); - lua_pop(L, 1); - lua_getfield(L, index, "z"); - pos.Z = lua_tonumber(L, -1); - lua_pop(L, 1); - return pos; -} - -v3f check_v3f(lua_State *L, int index) -{ - v3f pos; - luaL_checktype(L, index, LUA_TTABLE); - lua_getfield(L, index, "x"); - pos.X = luaL_checknumber(L, -1); - lua_pop(L, 1); - lua_getfield(L, index, "y"); - pos.Y = luaL_checknumber(L, -1); - lua_pop(L, 1); - lua_getfield(L, index, "z"); - pos.Z = luaL_checknumber(L, -1); - lua_pop(L, 1); - return pos; -} - -void pushFloatPos(lua_State *L, v3f p) -{ - p /= BS; - push_v3f(L, p); -} - -v3f checkFloatPos(lua_State *L, int index) -{ - return check_v3f(L, index) * BS; -} - -void push_v3s16(lua_State *L, v3s16 p) -{ - lua_newtable(L); - lua_pushnumber(L, p.X); - lua_setfield(L, -2, "x"); - lua_pushnumber(L, p.Y); - lua_setfield(L, -2, "y"); - lua_pushnumber(L, p.Z); - lua_setfield(L, -2, "z"); -} - -v3s16 read_v3s16(lua_State *L, int index) -{ - // Correct rounding at <0 - v3f pf = read_v3f(L, index); - return floatToInt(pf, 1.0); -} - -v3s16 check_v3s16(lua_State *L, int index) -{ - // Correct rounding at <0 - v3f pf = check_v3f(L, index); - return floatToInt(pf, 1.0); -} - -video::SColor readARGB8(lua_State *L, int index) -{ - video::SColor color(0); - luaL_checktype(L, index, LUA_TTABLE); - lua_getfield(L, index, "a"); - if(lua_isnumber(L, -1)) - color.setAlpha(lua_tonumber(L, -1)); - lua_pop(L, 1); - lua_getfield(L, index, "r"); - color.setRed(lua_tonumber(L, -1)); - lua_pop(L, 1); - lua_getfield(L, index, "g"); - color.setGreen(lua_tonumber(L, -1)); - lua_pop(L, 1); - lua_getfield(L, index, "b"); - color.setBlue(lua_tonumber(L, -1)); - lua_pop(L, 1); - return color; -} - -aabb3f read_aabb3f(lua_State *L, int index, f32 scale) -{ - aabb3f box; - if(lua_istable(L, index)){ - lua_rawgeti(L, index, 1); - box.MinEdge.X = lua_tonumber(L, -1) * scale; - lua_pop(L, 1); - lua_rawgeti(L, index, 2); - box.MinEdge.Y = lua_tonumber(L, -1) * scale; - lua_pop(L, 1); - lua_rawgeti(L, index, 3); - box.MinEdge.Z = lua_tonumber(L, -1) * scale; - lua_pop(L, 1); - lua_rawgeti(L, index, 4); - box.MaxEdge.X = lua_tonumber(L, -1) * scale; - lua_pop(L, 1); - lua_rawgeti(L, index, 5); - box.MaxEdge.Y = lua_tonumber(L, -1) * scale; - lua_pop(L, 1); - lua_rawgeti(L, index, 6); - box.MaxEdge.Z = lua_tonumber(L, -1) * scale; - lua_pop(L, 1); - } - return box; -} - -std::vector read_aabb3f_vector(lua_State *L, int index, f32 scale) -{ - std::vector boxes; - if(lua_istable(L, index)){ - int n = lua_objlen(L, index); - // Check if it's a single box or a list of boxes - bool possibly_single_box = (n == 6); - for(int i = 1; i <= n && possibly_single_box; i++){ - lua_rawgeti(L, index, i); - if(!lua_isnumber(L, -1)) - possibly_single_box = false; - lua_pop(L, 1); - } - if(possibly_single_box){ - // Read a single box - boxes.push_back(read_aabb3f(L, index, scale)); - } else { - // Read a list of boxes - for(int i = 1; i <= n; i++){ - lua_rawgeti(L, index, i); - boxes.push_back(read_aabb3f(L, -1, scale)); - lua_pop(L, 1); - } - } - } - return boxes; -} - -/* - Table field getters -*/ - -bool getstringfield(lua_State *L, int table, - const char *fieldname, std::string &result) -{ - lua_getfield(L, table, fieldname); - bool got = false; - if(lua_isstring(L, -1)){ - size_t len = 0; - const char *ptr = lua_tolstring(L, -1, &len); - result.assign(ptr, len); - got = true; - } - lua_pop(L, 1); - return got; -} - -bool getintfield(lua_State *L, int table, - const char *fieldname, int &result) -{ - lua_getfield(L, table, fieldname); - bool got = false; - if(lua_isnumber(L, -1)){ - result = lua_tonumber(L, -1); - got = true; - } - lua_pop(L, 1); - return got; -} - -bool getfloatfield(lua_State *L, int table, - const char *fieldname, float &result) -{ - lua_getfield(L, table, fieldname); - bool got = false; - if(lua_isnumber(L, -1)){ - result = lua_tonumber(L, -1); - got = true; - } - lua_pop(L, 1); - return got; -} - -bool getboolfield(lua_State *L, int table, - const char *fieldname, bool &result) -{ - lua_getfield(L, table, fieldname); - bool got = false; - if(lua_isboolean(L, -1)){ - result = lua_toboolean(L, -1); - got = true; - } - lua_pop(L, 1); - return got; -} - -std::string checkstringfield(lua_State *L, int table, - const char *fieldname) -{ - lua_getfield(L, table, fieldname); - std::string s = luaL_checkstring(L, -1); - lua_pop(L, 1); - return s; -} - -std::string getstringfield_default(lua_State *L, int table, - const char *fieldname, const std::string &default_) -{ - std::string result = default_; - getstringfield(L, table, fieldname, result); - return result; -} - -int getintfield_default(lua_State *L, int table, - const char *fieldname, int default_) -{ - int result = default_; - getintfield(L, table, fieldname, result); - return result; -} - -float getfloatfield_default(lua_State *L, int table, - const char *fieldname, float default_) -{ - float result = default_; - getfloatfield(L, table, fieldname, result); - return result; -} - -bool getboolfield_default(lua_State *L, int table, - const char *fieldname, bool default_) -{ - bool result = default_; - getboolfield(L, table, fieldname, result); - return result; -} - -void setintfield(lua_State *L, int table, - const char *fieldname, int value) -{ - lua_pushinteger(L, value); - if(table < 0) - table -= 1; - lua_setfield(L, table, fieldname); -} - -void setfloatfield(lua_State *L, int table, - const char *fieldname, float value) -{ - lua_pushnumber(L, value); - if(table < 0) - table -= 1; - lua_setfield(L, table, fieldname); -} - -void setboolfield(lua_State *L, int table, - const char *fieldname, bool value) -{ - lua_pushboolean(L, value); - if(table < 0) - table -= 1; - lua_setfield(L, table, fieldname); -} - -u32 getflagsfield(lua_State *L, int table, - const char *fieldname, FlagDesc *flagdesc) { - std::string flagstring; - - flagstring = getstringfield_default(L, table, fieldname, ""); - return readFlagString(flagstring, flagdesc); -} - -/* minetest specific types */ -MapNode readnode(lua_State *L, int index, INodeDefManager *ndef) -{ - lua_getfield(L, index, "name"); - const char *name = luaL_checkstring(L, -1); - lua_pop(L, 1); - u8 param1; - lua_getfield(L, index, "param1"); - if(lua_isnil(L, -1)) - param1 = 0; - else - param1 = lua_tonumber(L, -1); - lua_pop(L, 1); - u8 param2; - lua_getfield(L, index, "param2"); - if(lua_isnil(L, -1)) - param2 = 0; - else - param2 = lua_tonumber(L, -1); - lua_pop(L, 1); - return MapNode(ndef, name, param1, param2); -} - -void pushnode(lua_State *L, const MapNode &n, INodeDefManager *ndef) -{ - lua_newtable(L); - lua_pushstring(L, ndef->get(n).name.c_str()); - lua_setfield(L, -2, "name"); - lua_pushnumber(L, n.getParam1()); - lua_setfield(L, -2, "param1"); - lua_pushnumber(L, n.getParam2()); - lua_setfield(L, -2, "param2"); -} diff --git a/src/scriptapi_types.h b/src/scriptapi_types.h deleted file mode 100644 index dd0b125e6..000000000 --- a/src/scriptapi_types.h +++ /dev/null @@ -1,90 +0,0 @@ -/* -Minetest-c55 -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 LUA_TYPES_H_ -#define LUA_TYPES_H_ - -#include -#include -#include - -#include "irrlichttypes_bloated.h" -#include "porting.h" -#include "map.h" - -extern "C" { -#include -} - -std::string getstringfield_default (lua_State *L, int table, - const char *fieldname, const std::string &default_); -bool getboolfield_default(lua_State *L, int table, - const char *fieldname, bool default_); -float getfloatfield_default(lua_State *L, int table, - const char *fieldname, float default_); -int getintfield_default (lua_State *L, int table, - const char *fieldname, int default_); - -bool getstringfield(lua_State *L, int table, - const char *fieldname, std::string &result); -bool getintfield(lua_State *L, int table, - const char *fieldname, int &result); -void read_groups (lua_State *L, int index, - std::map &result); -bool getboolfield(lua_State *L, int table, - const char *fieldname, bool &result); -bool getfloatfield(lua_State *L, int table, - const char *fieldname, float &result); -u32 getflagsfield(lua_State *L, int table, - const char *fieldname, FlagDesc *flagdesc); - -std::string checkstringfield(lua_State *L, int table, - const char *fieldname); - -void setintfield(lua_State *L, int table, - const char *fieldname, int value); -void setfloatfield(lua_State *L, int table, - const char *fieldname, float value); -void setboolfield(lua_State *L, int table, - const char *fieldname, bool value); - - -v3f checkFloatPos (lua_State *L, int index); -v3f check_v3f (lua_State *L, int index); -v3s16 check_v3s16 (lua_State *L, int index); - -v3f read_v3f (lua_State *L, int index); -v2f read_v2f (lua_State *L, int index); -v2s16 read_v2s16 (lua_State *L, int index); -video::SColor readARGB8 (lua_State *L, int index); -aabb3f read_aabb3f (lua_State *L, int index, f32 scale); -v3s16 read_v3s16 (lua_State *L, int index); -std::vector - read_aabb3f_vector (lua_State *L, int index, f32 scale); - -void push_v3s16 (lua_State *L, v3s16 p); -void pushFloatPos (lua_State *L, v3f p); -void push_v3f (lua_State *L, v3f p); -void push_v2f (lua_State *L, v2f p); - - -MapNode readnode(lua_State *L, int index, INodeDefManager *ndef); -void pushnode(lua_State *L, const MapNode &n, INodeDefManager *ndef); - -#endif /* LUA_TYPES_H_ */ diff --git a/src/server.cpp b/src/server.cpp index 0d724b1cb..12695e1b4 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -34,8 +34,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "settings.h" #include "profiler.h" #include "log.h" -#include "script.h" -#include "scriptapi.h" +#include "script/cpp_api/scriptapi.h" #include "nodedef.h" #include "itemdef.h" #include "craftdef.h" @@ -646,7 +645,7 @@ Server::Server( m_rollback_sink_enabled(true), m_enable_rollback_recording(false), m_emerge(NULL), - m_lua(NULL), + m_script(NULL), m_itemdef(createItemDefManager()), m_nodedef(createNodeDefManager()), m_craftdef(createCraftDefManager()), @@ -761,14 +760,14 @@ Server::Server( // Initialize scripting infostream<<"Server: Initializing Lua"<loadMod(builtinpath, "__builtin"); if(!success){ errorstream<<"Server: Failed to load and run " <loadMod(scriptpath, mod.name); if(!success){ errorstream<<"Server: Failed to load and run " <initMapgens(servermap->getMapgenParams()); // Give environment reference to scripting api - scriptapi_add_environment(m_lua, m_env); + m_script->initializeEnvironment(m_env); // Register us to receive map edit events servermap->addEventReceiver(this); @@ -874,7 +873,7 @@ Server::~Server() /* Execute script shutdown hooks */ - scriptapi_on_shutdown(m_lua); + m_script->on_shutdown(); } { @@ -927,7 +926,7 @@ Server::~Server() // Deinitialize scripting infostream<<"Server: Deinitializing scripting"<getAuth(playername, &checkpwd, NULL); // If no authentication info exists for user, create it if(!has_auth){ @@ -1964,10 +1963,10 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) if (raw_default_password.length() == 0) initial_password = given_password; - scriptapi_create_auth(m_lua, playername, initial_password); + m_script->createAuth(playername, initial_password); } - has_auth = scriptapi_get_auth(m_lua, playername, &checkpwd, NULL); + has_auth = m_script->getAuth(playername, &checkpwd, NULL); if(!has_auth){ SendAccessDenied(m_con, peer_id, L"Not allowed to login"); @@ -2469,7 +2468,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) std::wstring name = narrow_to_wide(player->getName()); // Run script hook - bool ate = scriptapi_on_chat_message(m_lua, player->getName(), + bool ate = m_script->on_chat_message(player->getName(), wide_to_narrow(message)); // If script ate the message, don't proceed if(ate) @@ -2601,7 +2600,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) std::string playername = player->getName(); std::string checkpwd; - scriptapi_get_auth(m_lua, playername, &checkpwd, NULL); + m_script->getAuth(playername, &checkpwd, NULL); if(oldpwd != checkpwd) { @@ -2611,7 +2610,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) return; } - bool success = scriptapi_set_password(m_lua, playername, newpwd); + bool success = m_script->setPassword(playername, newpwd); if(success){ actionstream<getName()<<" changes password"<enqueueBlockEmerge(peer_id, getNodeBlockPos(p_above), false); } if(n.getContent() != CONTENT_IGNORE) - scriptapi_node_on_punch(m_lua, p_under, n, playersao); + m_script->node_on_punch(p_under, n, playersao); // Cheat prevention playersao->noCheatDigStart(p_under); } @@ -2925,7 +2924,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) /* Actually dig node */ if(is_valid_dig && n.getContent() != CONTENT_IGNORE) - scriptapi_node_on_dig(m_lua, p_under, n, playersao); + m_script->node_on_dig(p_under, n, playersao); // Send unusual result (that is, node not being removed) if(m_env->getMap().getNodeNoEx(p_under).getContent() != CONTENT_AIR) @@ -2965,7 +2964,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) // Do stuff pointed_object->rightClick(playersao); } - else if(scriptapi_item_on_place(m_lua, + else if(m_script->item_OnPlace( item, playersao, pointed)) { // Placement was handled in lua @@ -2997,7 +2996,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) actionstream<getName()<<" uses "<item_OnUse( item, playersao, pointed)) { // Apply returned ItemStack @@ -3056,8 +3055,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) // Check the target node for rollback data; leave others unnoticed RollbackNode rn_old(&m_env->getMap(), p, this); - scriptapi_node_on_receive_fields(m_lua, p, formname, fields, - playersao); + m_script->node_on_receive_fields(p, formname, fields,playersao); // Report rollback data RollbackNode rn_new(&m_env->getMap(), p, this); @@ -3081,7 +3079,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) fields[fieldname] = fieldvalue; } - scriptapi_on_player_receive_fields(m_lua, playersao, formname, fields); + m_script->on_playerReceiveFields(playersao, formname, fields); } else { @@ -3188,46 +3186,46 @@ void Server::setInventoryModified(const InventoryLocation &loc) } } -std::list 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; -} +//std::list 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) @@ -3752,7 +3750,7 @@ void Server::SendPlayerPrivileges(u16 peer_id) return; std::set privs; - scriptapi_get_auth(m_lua, player->getName(), NULL, &privs); + m_script->getAuth(player->getName(), NULL, &privs); std::ostringstream os(std::ios_base::binary); writeU16(os, TOCLIENT_PRIVILEGES); @@ -4472,7 +4470,7 @@ void Server::DiePlayer(u16 peer_id) playersao->setHP(0); // Trigger scripted stuff - scriptapi_on_dieplayer(m_lua, playersao); + m_script->on_dieplayer(playersao); SendPlayerHP(peer_id); SendDeathscreen(m_con, peer_id, false, v3f(0,0,0)); @@ -4491,7 +4489,7 @@ void Server::RespawnPlayer(u16 peer_id) playersao->setHP(PLAYER_MAX_HP); - bool repositioned = scriptapi_on_respawnplayer(m_lua, playersao); + bool repositioned = m_script->on_respawnplayer(playersao); if(!repositioned){ v3f pos = findSpawnPos(m_env->getServerMap()); playersao->setPos(pos); @@ -4571,7 +4569,7 @@ std::wstring Server::getStatusString() std::set Server::getPlayerEffectivePrivs(const std::string &name) { std::set privs; - scriptapi_get_auth(m_lua, name, NULL, &privs); + m_script->getAuth(name, NULL, &privs); return privs; } @@ -5079,9 +5077,9 @@ PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id) /* Run scripts */ if(newplayer) - scriptapi_on_newplayer(m_lua, playersao); + m_script->on_newplayer(playersao); - scriptapi_on_joinplayer(m_lua, playersao); + m_script->on_joinplayer(playersao); return playersao; } @@ -5176,7 +5174,7 @@ void Server::handlePeerChange(PeerChange &c) PlayerSAO *playersao = player->getPlayerSAO(); assert(playersao); - scriptapi_on_leaveplayer(m_lua, playersao); + m_script->on_leaveplayer(playersao); playersao->disconnected(); } diff --git a/src/server.h b/src/server.h index dcd007d23..3906f43b8 100644 --- a/src/server.h +++ b/src/server.h @@ -43,8 +43,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")" -struct LuaState; -typedef struct lua_State lua_State; class IWritableItemDefManager; class IWritableNodeDefManager; class IWritableCraftDefManager; @@ -52,7 +50,9 @@ class EventManager; class PlayerSAO; class IRollbackManager; class EmergeManager; -//struct HudElement; +//struct HudElement; ????????? +class ScriptApi; + class ServerError : public std::exception { @@ -384,7 +384,7 @@ public: void Receive(); void ProcessData(u8 *data, u32 datasize, u16 peer_id); - std::list getPlayerInfo(); + //std::list getPlayerInfo(); // Environment must be locked when called void setTimeOfDay(u32 time) @@ -492,8 +492,8 @@ public: // Creates or resets inventory Inventory* createDetachedInventory(const std::string &name); - // Envlock and conlock should be locked when using Lua - lua_State *getLua(){ return m_lua; } + // Envlock and conlock should be locked when using scriptapi + ScriptApi *getScriptIface(){ return m_script; } // Envlock should be locked when using the rollback manager IRollbackManager *getRollbackManager(){ return m_rollback; } @@ -746,7 +746,7 @@ private: // Scripting // Envlock and conlock should be locked when using Lua - lua_State *m_lua; + ScriptApi *m_script; // Item definition manager IWritableItemDefManager *m_itemdef; diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt new file mode 100644 index 000000000..9cb8a19b6 --- /dev/null +++ b/src/util/CMakeLists.txt @@ -0,0 +1,8 @@ +set(UTIL_SRCS + ${CMAKE_CURRENT_SOURCE_DIR}/directiontables.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/numeric.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/pointedthing.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/serialize.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/string.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/timetaker.cpp + PARENT_SCOPE) -- cgit v1.2.3 From e464f193566b3c4173b44d3bf6c82aa032d9fed7 Mon Sep 17 00:00:00 2001 From: sapier Date: Sat, 25 May 2013 19:23:10 +0200 Subject: Fix itemstack:add item not working correct --- src/script/lua_api/l_item.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/script/lua_api/l_item.cpp b/src/script/lua_api/l_item.cpp index e9997d489..730dfd49b 100644 --- a/src/script/lua_api/l_item.cpp +++ b/src/script/lua_api/l_item.cpp @@ -227,7 +227,7 @@ 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,-2, STACK_TO_SERVER(L)); + ItemStack newitem = read_item(L,-1, STACK_TO_SERVER(L)); ItemStack leftover = item.addItem(newitem, STACK_TO_SERVER(L)->idef()); create(L, leftover); return 1; -- cgit v1.2.3 From 96fe1de8322a57ad82fcab3540c1eb44f74b9989 Mon Sep 17 00:00:00 2001 From: Kahrl Date: Sat, 4 May 2013 02:08:52 +0200 Subject: Add ObjectRef.hud_set_hotbar_itemcount and add TOCLIENT_HUD_SET_PARAM --- src/client.cpp | 17 +++++++++++++++++ src/clientserver.h | 8 ++++++++ src/game.cpp | 4 ++-- src/hud.cpp | 2 +- src/hud.h | 6 +++++- src/player.cpp | 2 ++ src/player.h | 1 + src/script/lua_api/l_object.cpp | 18 ++++++++++++++++++ src/script/lua_api/l_object.h | 3 +++ src/server.cpp | 28 ++++++++++++++++++++++++++++ src/server.h | 2 ++ 11 files changed, 87 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/client.cpp b/src/client.cpp index e4ca52dd5..6b1789fe0 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -2136,6 +2136,23 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) player->hud_flags &= ~mask; player->hud_flags |= flags; } + else if(command == TOCLIENT_HUD_SET_PARAM) + { + std::string datastring((char *)&data[2], datasize - 2); + std::istringstream is(datastring, std::ios_base::binary); + + Player *player = m_env.getLocalPlayer(); + assert(player != NULL); + + u16 param = readU16(is); + std::string value = deSerializeString(is); + + if(param == HUD_PARAM_HOTBAR_ITEMCOUNT && value.size() == 4){ + s32 hotbar_itemcount = readS32((u8*) value.c_str()); + if(hotbar_itemcount > 0 && hotbar_itemcount <= HUD_HOTBAR_ITEMCOUNT_MAX) + player->hud_hotbar_itemcount = hotbar_itemcount; + } + } else { infostream<<"Client: Ignoring unknown command " diff --git a/src/clientserver.h b/src/clientserver.h index ee9271bbc..a43baab23 100644 --- a/src/clientserver.h +++ b/src/clientserver.h @@ -480,6 +480,14 @@ enum ToClientCommand u32 flags u32 mask */ + + TOCLIENT_HUD_SET_PARAM = 0x4d, + /* + u16 command + u16 param + u16 len + u8[len] value + */ }; enum ToServerCommand diff --git a/src/game.cpp b/src/game.cpp index 921cce327..4f0d1b663 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -1987,7 +1987,7 @@ void the_game( { s32 wheel = input->getMouseWheel(); u16 max_item = MYMIN(PLAYER_INVENTORY_SIZE-1, - hud.hotbar_itemcount-1); + player->hud_hotbar_itemcount-1); if(wheel < 0) { @@ -2011,7 +2011,7 @@ void the_game( const KeyPress *kp = NumberKey + (i + 1) % 10; if(input->wasKeyDown(*kp)) { - if(i < PLAYER_INVENTORY_SIZE && i < hud.hotbar_itemcount) + if(i < PLAYER_INVENTORY_SIZE && i < player->hud_hotbar_itemcount) { new_playeritem = i; diff --git a/src/hud.cpp b/src/hud.cpp index 65c78ca50..a3ae38bcb 100644 --- a/src/hud.cpp +++ b/src/hud.cpp @@ -43,7 +43,6 @@ Hud::Hud(video::IVideoDriver *driver, gui::IGUIEnvironment* guienv, screensize = v2u32(0, 0); displaycenter = v2s32(0, 0); hotbar_imagesize = 48; - hotbar_itemcount = 8; tsrc = gamedef->getTextureSource(); @@ -286,6 +285,7 @@ void Hud::drawHotbar(v2s32 centerlowerpos, s32 halfheartcount, u16 playeritem) { return; } + s32 hotbar_itemcount = player->hud_hotbar_itemcount; s32 padding = hotbar_imagesize / 12; s32 width = hotbar_itemcount * (hotbar_imagesize + padding * 2); v2s32 pos = centerlowerpos - v2s32(width / 2, hotbar_imagesize + padding * 2); diff --git a/src/hud.h b/src/hud.h index 54b7e7f36..fa9d33f8b 100644 --- a/src/hud.h +++ b/src/hud.h @@ -36,6 +36,11 @@ with this program; if not, write to the Free Software Foundation, Inc., #define HUD_FLAG_CROSSHAIR_VISIBLE (1 << 2) #define HUD_FLAG_WIELDITEM_VISIBLE (1 << 3) +#define HUD_PARAM_HOTBAR_ITEMCOUNT 1 + +#define HUD_HOTBAR_ITEMCOUNT_DEFAULT 8 +#define HUD_HOTBAR_ITEMCOUNT_MAX 23 + class Player; enum HudElementType { @@ -102,7 +107,6 @@ public: v2u32 screensize; v2s32 displaycenter; s32 hotbar_imagesize; - s32 hotbar_itemcount; video::SColor crosshair_argb; video::SColor selectionbox_argb; diff --git a/src/player.cpp b/src/player.cpp index 34f0fda08..4eb5955c0 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -81,6 +81,8 @@ Player::Player(IGameDef *gamedef): hud_flags = HUD_FLAG_HOTBAR_VISIBLE | HUD_FLAG_HEALTHBAR_VISIBLE | HUD_FLAG_CROSSHAIR_VISIBLE | HUD_FLAG_WIELDITEM_VISIBLE; + + hud_hotbar_itemcount = HUD_HOTBAR_ITEMCOUNT_DEFAULT; } Player::~Player() diff --git a/src/player.h b/src/player.h index 63e166b4b..d3738fd52 100644 --- a/src/player.h +++ b/src/player.h @@ -250,6 +250,7 @@ public: std::vector hud; u32 hud_flags; + s32 hud_hotbar_itemcount; protected: IGameDef *m_gamedef; diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index 6dec3db85..1e45610a6 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -978,6 +978,23 @@ int ObjectRef::l_hud_set_flags(lua_State *L) return 1; } +// hud_set_hotbar_itemcount(self, hotbar_itemcount) +int ObjectRef::l_hud_set_hotbar_itemcount(lua_State *L) +{ + ObjectRef *ref = checkobject(L, 1); + Player *player = getplayer(ref); + if (player == NULL) + return 0; + + s32 hotbar_itemcount = lua_tonumber(L, 2); + + if (!STACK_TO_SERVER(L)->hudSetHotbarItemcount(player, hotbar_itemcount)) + return 0; + + lua_pushboolean(L, true); + return 1; +} + ObjectRef::ObjectRef(ServerActiveObject *object): m_object(object) { @@ -1089,6 +1106,7 @@ const luaL_reg ObjectRef::methods[] = { luamethod(ObjectRef, hud_change), luamethod(ObjectRef, hud_get), luamethod(ObjectRef, hud_set_flags), + luamethod(ObjectRef, hud_set_hotbar_itemcount), {0,0} }; diff --git a/src/script/lua_api/l_object.h b/src/script/lua_api/l_object.h index 88f980a27..57dac0e64 100644 --- a/src/script/lua_api/l_object.h +++ b/src/script/lua_api/l_object.h @@ -209,6 +209,9 @@ private: // hud_set_flags(self, flags) static int l_hud_set_flags(lua_State *L); + // hud_set_hotbar_itemcount(self, hotbar_itemcount) + static int l_hud_set_hotbar_itemcount(lua_State *L); + public: ObjectRef(ServerActiveObject *object); diff --git a/src/server.cpp b/src/server.cpp index 12695e1b4..4268bb809 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -3687,6 +3687,22 @@ void Server::SendHUDSetFlags(u16 peer_id, u32 flags, u32 mask) m_con.Send(peer_id, 0, data, true); } +void Server::SendHUDSetParam(u16 peer_id, u16 param, const std::string &value) +{ + std::ostringstream os(std::ios_base::binary); + + // Write command + writeU16(os, TOCLIENT_HUD_SET_PARAM); + writeU16(os, param); + os< data((u8 *)s.c_str(), s.size()); + // Send as reliable + m_con.Send(peer_id, 0, data, true); +} + void Server::BroadcastChatMessage(const std::wstring &message) { for(std::map::iterator @@ -4684,6 +4700,18 @@ bool Server::hudSetFlags(Player *player, u32 flags, u32 mask) { return true; } +bool Server::hudSetHotbarItemcount(Player *player, s32 hotbar_itemcount) { + if (!player) + return false; + if (hotbar_itemcount <= 0 || hotbar_itemcount > HUD_HOTBAR_ITEMCOUNT_MAX) + return false; + + std::ostringstream os(std::ios::binary); + writeS32(os, hotbar_itemcount); + SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_ITEMCOUNT, os.str()); + return true; +} + void Server::notifyPlayers(const std::wstring msg) { BroadcastChatMessage(msg); diff --git a/src/server.h b/src/server.h index 3906f43b8..edc5c4895 100644 --- a/src/server.h +++ b/src/server.h @@ -541,6 +541,7 @@ public: bool hudRemove(Player *player, u32 id); bool hudChange(Player *player, u32 id, HudElementStat stat, void *value); bool hudSetFlags(Player *player, u32 flags, u32 mask); + bool hudSetHotbarItemcount(Player *player, s32 hotbar_itemcount); private: @@ -585,6 +586,7 @@ private: void SendHUDRemove(u16 peer_id, u32 id); void SendHUDChange(u16 peer_id, u32 id, HudElementStat stat, void *value); void SendHUDSetFlags(u16 peer_id, u32 flags, u32 mask); + void SendHUDSetParam(u16 peer_id, u16 param, const std::string &value); /* Send a node removal/addition event to all clients except ignore_id. -- cgit v1.2.3 From f62ddf9022588f6c93fe6cdf2244640dd96dc186 Mon Sep 17 00:00:00 2001 From: MetaDucky Date: Thu, 23 May 2013 19:27:00 +0200 Subject: Fixed wrongly named invref:get_location() table members for nodes. Makes the result compatible with the minetest.get_inventory(location) param. --- src/script/lua_api/l_inventory.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/script/lua_api/l_inventory.cpp b/src/script/lua_api/l_inventory.cpp index 884b33e67..6dfb7a28c 100644 --- a/src/script/lua_api/l_inventory.cpp +++ b/src/script/lua_api/l_inventory.cpp @@ -306,10 +306,10 @@ int InvRef::l_get_location(lua_State *L) return 1; case InventoryLocation::NODEMETA: lua_newtable(L); - lua_pushstring(L, "nodemeta"); + lua_pushstring(L, "node"); lua_setfield(L, -2, "type"); push_v3s16(L, loc.p); - lua_setfield(L, -2, "name"); + lua_setfield(L, -2, "pos"); return 1; case InventoryLocation::DETACHED: lua_newtable(L); -- cgit v1.2.3 From efc75db76458dc473043043ca72c18701436dec8 Mon Sep 17 00:00:00 2001 From: sapier Date: Sun, 7 Apr 2013 16:34:35 +0200 Subject: Bugfix: Update formname on showing new formspec while already one shown --- src/game.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/game.cpp b/src/game.cpp index 4f0d1b663..ffc69d739 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -134,6 +134,10 @@ struct TextDestPlayerInventory : public TextDest m_client->sendInventoryFields(m_formname, fields); } + void setFormName(std::string formname) { + m_formname = formname; + } + Client *m_client; std::string m_formname; }; @@ -920,6 +924,7 @@ void the_game( ) { FormspecFormSource* current_formspec = 0; + TextDestPlayerInventory* current_textdest = 0; video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); @@ -2236,19 +2241,23 @@ void the_game( if (current_formspec == 0) { /* Create menu */ + /* Note: FormspecFormSource and TextDestPlayerInventory + * are deleted by guiFormSpecMenu */ current_formspec = new FormspecFormSource(*(event.show_formspec.formspec),¤t_formspec); - + current_textdest = new TextDestPlayerInventory(&client,*(event.show_formspec.formname)); GUIFormSpecMenu *menu = new GUIFormSpecMenu(device, guiroot, -1, &g_menumgr, &client, gamedef); menu->setFormSource(current_formspec); - menu->setTextDest(new TextDestPlayerInventory(&client,*(event.show_formspec.formname))); + menu->setTextDest(current_textdest); menu->drop(); } else { + assert(current_textdest != 0); /* update menu */ + current_textdest->setFormName(*(event.show_formspec.formname)); current_formspec->setForm(*(event.show_formspec.formspec)); } delete(event.show_formspec.formspec); -- cgit v1.2.3 From 6b2c46c4316cb5d2d153c13565c894a1ebec085c Mon Sep 17 00:00:00 2001 From: proller Date: Fri, 31 May 2013 22:57:59 +0400 Subject: Liquid adjusting: continue to drop --- src/content_abm.cpp | 47 ++++++++++++++++++++++++++++++++++++++++++++--- src/map.cpp | 2 +- 2 files changed, 45 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/content_abm.cpp b/src/content_abm.cpp index f19caf74e..3704fe83d 100644 --- a/src/content_abm.cpp +++ b/src/content_abm.cpp @@ -191,17 +191,58 @@ public: virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n) { ServerMap *map = &env->getServerMap(); - if (map->transforming_liquid_size() < 500) - map->transforming_liquid_add(p); + if (map->transforming_liquid_size() > 500) + return; + map->transforming_liquid_add(p); //if ((*map).m_transforming_liquid.size() < 500) (*map).m_transforming_liquid.push_back(p); } }; +class LiquidDropABM : public ActiveBlockModifier +{ +private: + std::set contents; + +public: + LiquidDropABM(ServerEnvironment *env, INodeDefManager *nodemgr) + { + std::set liquids; + nodemgr->getIds("group:liquid", liquids); + for(std::set::const_iterator k = liquids.begin(); k != liquids.end(); k++) + contents.insert(nodemgr->get(*k).liquid_alternative_source); + } + virtual std::set getTriggerContents() + { return contents; } + virtual std::set getRequiredNeighbors() + { + std::set neighbors; + neighbors.insert("mapgen_air"); + return neighbors; + } + virtual float getTriggerInterval() + { return 20.0; } + virtual u32 getTriggerChance() + { return 10; } + virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n) + { + ServerMap *map = &env->getServerMap(); + if (map->transforming_liquid_size() > 500) + return; + //todo: look around except top + MapNode n_below = map->getNodeNoEx(p - v3s16(0, 1, 0)); + if (n_below.getContent() != CONTENT_AIR) + return; + map->transforming_liquid_add(p); + } +}; + void add_legacy_abms(ServerEnvironment *env, INodeDefManager *nodedef) { env->addActiveBlockModifier(new GrowGrassABM()); env->addActiveBlockModifier(new RemoveGrassABM()); env->addActiveBlockModifier(new MakeTreesFromSaplingsABM(env, nodedef)); - if (g_settings->getBool("liquid_finite")) + if (g_settings->getBool("liquid_finite")) { env->addActiveBlockModifier(new LiquidFlowABM(env, nodedef)); + env->addActiveBlockModifier(new LiquidDropABM(env, nodedef)); + } } diff --git a/src/map.cpp b/src/map.cpp index d5ab8eb1e..43502253b 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -1755,7 +1755,7 @@ void Map::transformLiquidsFinite(std::map & modified_blocks) } //relax up - if (relax && p0.Y <= water_level && liquid_levels[D_TOP] == 0 && + if (relax && ((p0.Y == water_level) || (fast_flood && p0.Y <= water_level)) && liquid_levels[D_TOP] == 0 && liquid_levels[D_BOTTOM] == LIQUID_LEVEL_SOURCE && total_level >= LIQUID_LEVEL_SOURCE * can_liquid_same_level- (can_liquid_same_level - relax) && -- cgit v1.2.3 From 7721948a2fbd101bc8530e4d3ae7c1552bdf9490 Mon Sep 17 00:00:00 2001 From: Kahrl Date: Sat, 1 Jun 2013 01:49:59 +0200 Subject: Generate debug HUD text with ostringstream instead of snprintf. This should fix #730. --- src/game.cpp | 50 ++++++++++++++++++++++++-------------------------- 1 file changed, 24 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/game.cpp b/src/game.cpp index ffc69d739..22bd8c429 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -66,6 +66,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "sound_openal.h" #endif #include "event_manager.h" +#include #include #include "util/directiontables.h" @@ -2961,21 +2962,20 @@ void the_game( static float endscenetime_avg = 0; endscenetime_avg = endscenetime_avg * 0.95 + (float)endscenetime*0.05;*/ - char temptext[300]; - snprintf(temptext, 300, "%s (" - "R: range_all=%i" - ")" - " drawtime=%.0f, dtime_jitter = % .1f %%" - ", v_range = %.1f, RTT = %.3f", - program_name_and_version, - draw_control.range_all, - drawtime_avg, - dtime_jitter1_max_fraction * 100.0, - draw_control.wanted_range, - client.getRTT() - ); - - guitext->setText(narrow_to_wide(temptext).c_str()); + std::ostringstream os(std::ios_base::binary); + os<setText(narrow_to_wide(temptext).c_str()); + std::ostringstream os(std::ios_base::binary); + os<setText(narrow_to_wide(os.str()).c_str()); guitext2->setVisible(true); } else -- cgit v1.2.3 From a61aa6690b5a5bf804c6de22eed95a68ba480e7d Mon Sep 17 00:00:00 2001 From: MetaDucky Date: Mon, 27 May 2013 19:33:33 +0200 Subject: Fix editbox default text being pre-selected in some cases --- src/guiCreateWorld.cpp | 3 +++ src/guiFormSpecMenu.cpp | 5 ++++- src/guiTextInputMenu.cpp | 3 +++ 3 files changed, 10 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/guiCreateWorld.cpp b/src/guiCreateWorld.cpp index 9fc764214..f9afe9592 100644 --- a/src/guiCreateWorld.cpp +++ b/src/guiCreateWorld.cpp @@ -135,6 +135,9 @@ void GUICreateWorld::regenerateGui(v2u32 screensize) evt.EventType = EET_KEY_INPUT_EVENT; evt.KeyInput.Key = KEY_END; evt.KeyInput.PressedDown = true; + evt.KeyInput.Char = 0; + evt.KeyInput.Control = 0; + evt.KeyInput.Shift = 0; e->OnEvent(evt); } { diff --git a/src/guiFormSpecMenu.cpp b/src/guiFormSpecMenu.cpp index 6ada77698..3e0d7fd46 100644 --- a/src/guiFormSpecMenu.cpp +++ b/src/guiFormSpecMenu.cpp @@ -418,9 +418,12 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize) e->setTextAlignment(gui::EGUIA_UPPERLEFT, gui::EGUIA_UPPERLEFT); } else { irr::SEvent evt; - evt.KeyInput.Key = KEY_END; evt.EventType = EET_KEY_INPUT_EVENT; + evt.KeyInput.Key = KEY_END; evt.KeyInput.PressedDown = true; + evt.KeyInput.Char = 0; + evt.KeyInput.Control = 0; + evt.KeyInput.Shift = 0; e->OnEvent(evt); } diff --git a/src/guiTextInputMenu.cpp b/src/guiTextInputMenu.cpp index c15eeedc5..d5229f415 100644 --- a/src/guiTextInputMenu.cpp +++ b/src/guiTextInputMenu.cpp @@ -121,6 +121,9 @@ void GUITextInputMenu::regenerateGui(v2u32 screensize) evt.EventType = EET_KEY_INPUT_EVENT; evt.KeyInput.Key = KEY_END; evt.KeyInput.PressedDown = true; + evt.KeyInput.Char = 0; + evt.KeyInput.Control = 0; + evt.KeyInput.Shift = 0; e->OnEvent(evt); } changeCtype(""); -- cgit v1.2.3 From 64627817fcca52f20948c24b60ce192b218f6ce2 Mon Sep 17 00:00:00 2001 From: MetaDucky Date: Sun, 26 May 2013 11:27:06 +0200 Subject: Fix minetest.get_inventory(loc) always returning nil for "node" type loc --- src/script/lua_api/l_inventory.cpp | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/script/lua_api/l_inventory.cpp b/src/script/lua_api/l_inventory.cpp index 6dfb7a28c..1404c3c8a 100644 --- a/src/script/lua_api/l_inventory.cpp +++ b/src/script/lua_api/l_inventory.cpp @@ -416,9 +416,18 @@ int ModApiInventory::l_get_inventory(lua_State *L) std::string type = checkstringfield(L, 1, "type"); - if(type != "pos"){ - NO_MAP_LOCK_REQUIRED; + if(type == "node"){ + lua_getfield(L, 1, "pos"); + v3s16 pos = check_v3s16(L, -1); + loc.setNodeMeta(pos); + if(getServer(L)->getInventory(loc) != NULL) + InvRef::create(L, loc); + else + lua_pushnil(L); + return 1; + } else { + NO_MAP_LOCK_REQUIRED; if(type == "player"){ std::string name = checkstringfield(L, 1, "name"); loc.setPlayer(name); @@ -431,22 +440,9 @@ int ModApiInventory::l_get_inventory(lua_State *L) InvRef::create(L, loc); else lua_pushnil(L); - - return 1; - } - else { - if(type == "node"){ - lua_getfield(L, 1, "pos"); - v3s16 pos = check_v3s16(L, -1); - loc.setNodeMeta(pos); - } - if(getServer(L)->getInventory(loc) != NULL) - InvRef::create(L, loc); - else - lua_pushnil(L); - return 1; + return 1; + // END NO_MAP_LOCK_REQUIRED; } - } // create_detached_inventory_raw(name) -- cgit v1.2.3