From: Loïc Blot Date: Thu, 16 Mar 2017 09:34:54 +0000 (+0100) Subject: [CSM] Add minimap API modifiers (#5399) X-Git-Tag: 0.4.16~380 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=40ce538aad9af8f7634c4ba7e9f12246fb23b31c;p=oweals%2Fminetest.git [CSM] Add minimap API modifiers (#5399) * Rename Mapper (too generic) to Minimap * Add lua functions to get/set position, angle, mode for minimap * Client: rename m_mapper to m_minimap * Add minimap to core.ui namespace (core.ui.minimap) * Add various functions to manage minimap (show, hide, toggle_shape) * Cleanup trivial declaration in client --- diff --git a/clientmods/preview/init.lua b/clientmods/preview/init.lua index 60dccf304..bdda7fe4e 100644 --- a/clientmods/preview/init.lua +++ b/clientmods/preview/init.lua @@ -47,9 +47,21 @@ core.register_chatcommand("test_node", { end, }) +local function preview_minimap() + local minimap = core.ui.minimap + minimap:show() + minimap:set_mode(4) + minimap:set_pos({x=5, y=50, z=5}) + minimap:toggle_shape() + + print("[PREVIEW] Minimap: mode => " .. dump(minimap:get_mode()) .. + " position => " .. dump(minimap:get_pos()) .. + " angle => " .. dump(minimap:get_angle())) +end core.after(2, function() print("[PREVIEW] loaded " .. modname .. " mod") + preview_minimap() modstorage:set_string("current_mod", modname) print(modstorage:get_string("current_mod")) end) diff --git a/doc/client_lua_api.md b/doc/client_lua_api.md index c07a1c55a..70716ee41 100644 --- a/doc/client_lua_api.md +++ b/doc/client_lua_api.md @@ -789,9 +789,27 @@ Call these functions only at load time! * same as fgettext_ne(), but calls core.formspec_escape before returning result * `show_formspec(formname, formspec)` : returns true on success * Shows a formspec to the player + +### UI +* `minetest.ui.minimap` + * Reference to the minimap object. See `Minimap` class reference for methods. + Class reference --------------- +### `Minimap` +An interface to manipulate minimap on client UI + +* `show()`: shows the minimap (if not disabled by server) +* `hide()`: hides the minimap +* `set_pos(pos)`: sets the minimap position on screen +* `get_pos()`: returns the minimap current position +* `set_angle(deg)`: sets the minimap angle in degrees +* `get_angle()`: returns the current minimap angle in degrees +* `set_mode(mode)`: sets the minimap mode (0 to 6) +* `get_mode()`: returns the current minimap mode +* `toggle_shape()`: toggles minimap shape to round or square. + ### `Settings` An interface to read config files in the format of `minetest.conf`. diff --git a/src/client.cpp b/src/client.cpp index 567ee6dd7..2491db704 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -224,6 +224,7 @@ Client::Client( m_device(device), m_camera(NULL), m_minimap_disabled_by_server(false), + m_minimap_shown_by_mod(false), m_server_ser_ver(SER_FMT_VER_INVALID), m_proto_ver(0), m_playeritem(0), @@ -255,7 +256,7 @@ Client::Client( // Add local player m_env.setLocalPlayer(new LocalPlayer(this, playername)); - m_mapper = new Mapper(device, this); + m_minimap = new Minimap(device, this); m_cache_save_interval = g_settings->getU16("server_map_save_interval"); m_cache_smooth_lighting = g_settings->getBool("smooth_lighting"); @@ -386,7 +387,7 @@ Client::~Client() m_device->getSceneManager()->getMeshCache()->removeMesh(mesh); } - delete m_mapper; + delete m_minimap; } void Client::connect(Address address, @@ -636,7 +637,7 @@ void Client::step(float dtime) } if (do_mapper_update) - m_mapper->addBlock(r.p, minimap_mapblock); + m_minimap->addBlock(r.p, minimap_mapblock); if (r.ack_block_to_server) { /* @@ -1859,23 +1860,17 @@ void Client::afterContentReceived(IrrlichtDevice *device) delete[] text; } -float Client::getRTT(void) +float Client::getRTT() { return m_con.getPeerStat(PEER_ID_SERVER,con::AVG_RTT); } -float Client::getCurRate(void) +float Client::getCurRate() { return ( m_con.getLocalStat(con::CUR_INC_RATE) + m_con.getLocalStat(con::CUR_DL_RATE)); } -float Client::getAvgRate(void) -{ - return ( m_con.getLocalStat(con::AVG_INC_RATE) + - m_con.getLocalStat(con::AVG_DL_RATE)); -} - void Client::makeScreenshot(IrrlichtDevice *device) { irr::video::IVideoDriver *driver = device->getVideoDriver(); @@ -1935,6 +1930,15 @@ void Client::makeScreenshot(IrrlichtDevice *device) raw_image->drop(); } +bool Client::shouldShowMinimap() const +{ + if (m_minimap_disabled_by_server) { + return false; + } + + return m_minimap_shown_by_mod; +} + // IGameDef interface // Under envlock IItemDefManager* Client::getItemDefManager() diff --git a/src/client.h b/src/client.h index d72249315..5c8a0ae25 100644 --- a/src/client.h +++ b/src/client.h @@ -49,7 +49,7 @@ struct MapDrawControl; class MtEventManager; struct PointedThing; class Database; -class Mapper; +class Minimap; struct MinimapMapblock; class Camera; class NetworkPacket; @@ -522,21 +522,17 @@ public: void afterContentReceived(IrrlichtDevice *device); - float getRTT(void); - float getCurRate(void); - float getAvgRate(void); + float getRTT(); + float getCurRate(); - Mapper* getMapper () - { return m_mapper; } - - void setCamera(Camera* camera) - { m_camera = camera; } + Minimap* getMinimap() { return m_minimap; } + void setCamera(Camera* camera) { m_camera = camera; } Camera* getCamera () { return m_camera; } - bool isMinimapDisabledByServer() - { return m_minimap_disabled_by_server; } + bool shouldShowMinimap() const; + void setMinimapShownByMod(bool state) { m_minimap_shown_by_mod = state; } // IGameDef interface virtual IItemDefManager* getItemDefManager(); @@ -636,8 +632,9 @@ private: con::Connection m_con; IrrlichtDevice *m_device; Camera *m_camera; - Mapper *m_mapper; + Minimap *m_minimap; bool m_minimap_disabled_by_server; + bool m_minimap_shown_by_mod; // Server serialization version u8 m_server_ser_ver; diff --git a/src/drawscene.cpp b/src/drawscene.cpp index e3e6301a8..3a03743ee 100644 --- a/src/drawscene.cpp +++ b/src/drawscene.cpp @@ -474,7 +474,7 @@ void draw_plain(Camera &camera, bool show_hud, Hud &hud, void draw_scene(video::IVideoDriver *driver, scene::ISceneManager *smgr, Camera &camera, Client& client, LocalPlayer *player, Hud &hud, - Mapper &mapper, gui::IGUIEnvironment *guienv, + Minimap &mapper, gui::IGUIEnvironment *guienv, const v2u32 &screensize, const video::SColor &skycolor, bool show_hud, bool show_minimap) { diff --git a/src/drawscene.h b/src/drawscene.h index 364fcd499..4965a0889 100644 --- a/src/drawscene.h +++ b/src/drawscene.h @@ -32,7 +32,7 @@ void draw_load_screen(const std::wstring &text, IrrlichtDevice *device, void draw_scene(video::IVideoDriver *driver, scene::ISceneManager *smgr, Camera &camera, Client &client, LocalPlayer *player, - Hud &hud, Mapper &mapper, gui::IGUIEnvironment *guienv, + Hud &hud, Minimap &mapper, gui::IGUIEnvironment *guienv, const v2u32 &screensize, const video::SColor &skycolor, bool show_hud, bool show_minimap); diff --git a/src/game.cpp b/src/game.cpp index 10ec5d594..386267017 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -715,7 +715,7 @@ public: m_eye_position_vertex.set(eye_position_array, services); float minimap_yaw_array[3]; - v3f minimap_yaw = m_client->getMapper()->getYawVec(); + v3f minimap_yaw = m_client->getMinimap()->getYawVec(); #if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8) minimap_yaw_array[0] = minimap_yaw.X; minimap_yaw_array[1] = minimap_yaw.Y; @@ -1473,7 +1473,7 @@ private: Sky *sky; // Free using ->Drop() Inventory *local_inventory; Hud *hud; - Mapper *mapper; + Minimap *mapper; GameRunData runData; VolatileRunFlags flags; @@ -1769,7 +1769,7 @@ void Game::run() updateProfilerGraphs(&graph); // Update if minimap has been disabled by the server - flags.show_minimap &= !client->isMinimapDisabledByServer(); + flags.show_minimap = client->shouldShowMinimap(); } } @@ -2029,7 +2029,7 @@ bool Game::createClient(const std::string &playername, return false; } - mapper = client->getMapper(); + mapper = client->getMinimap(); mapper->setMinimapMode(MINIMAP_MODE_OFF); return true; diff --git a/src/minimap.cpp b/src/minimap.cpp index cfc2c34b0..ee29c58ba 100644 --- a/src/minimap.cpp +++ b/src/minimap.cpp @@ -184,7 +184,7 @@ void MinimapUpdateThread::getMap(v3s16 pos, s16 size, s16 height) //// Mapper //// -Mapper::Mapper(IrrlichtDevice *device, Client *client) +Minimap::Minimap(IrrlichtDevice *device, Client *client) { this->client = client; this->driver = device->getVideoDriver(); @@ -238,7 +238,7 @@ Mapper::Mapper(IrrlichtDevice *device, Client *client) m_minimap_update_thread->start(); } -Mapper::~Mapper() +Minimap::~Minimap() { m_minimap_update_thread->stop(); m_minimap_update_thread->wait(); @@ -258,17 +258,12 @@ Mapper::~Mapper() delete m_minimap_update_thread; } -void Mapper::addBlock(v3s16 pos, MinimapMapblock *data) +void Minimap::addBlock(v3s16 pos, MinimapMapblock *data) { m_minimap_update_thread->enqueueBlock(pos, data); } -MinimapMode Mapper::getMinimapMode() -{ - return data->mode; -} - -void Mapper::toggleMinimapShape() +void Minimap::toggleMinimapShape() { MutexAutoLock lock(m_mutex); @@ -277,7 +272,7 @@ void Mapper::toggleMinimapShape() m_minimap_update_thread->deferUpdate(); } -void Mapper::setMinimapMode(MinimapMode mode) +void Minimap::setMinimapMode(MinimapMode mode) { static const MinimapModeDef modedefs[MINIMAP_MODE_COUNT] = { {false, 0, 0}, @@ -302,7 +297,7 @@ void Mapper::setMinimapMode(MinimapMode mode) m_minimap_update_thread->deferUpdate(); } -void Mapper::setPos(v3s16 pos) +void Minimap::setPos(v3s16 pos) { bool do_update = false; @@ -320,12 +315,12 @@ void Mapper::setPos(v3s16 pos) m_minimap_update_thread->deferUpdate(); } -void Mapper::setAngle(f32 angle) +void Minimap::setAngle(f32 angle) { m_angle = angle; } -void Mapper::blitMinimapPixelsToImageRadar(video::IImage *map_image) +void Minimap::blitMinimapPixelsToImageRadar(video::IImage *map_image) { for (s16 x = 0; x < data->map_size; x++) for (s16 z = 0; z < data->map_size; z++) { @@ -339,7 +334,7 @@ void Mapper::blitMinimapPixelsToImageRadar(video::IImage *map_image) } } -void Mapper::blitMinimapPixelsToImageSurface( +void Minimap::blitMinimapPixelsToImageSurface( video::IImage *map_image, video::IImage *heightmap_image) { for (s16 x = 0; x < data->map_size; x++) @@ -368,7 +363,7 @@ void Mapper::blitMinimapPixelsToImageSurface( } } -video::ITexture *Mapper::getMinimapTexture() +video::ITexture *Minimap::getMinimapTexture() { // update minimap textures when new scan is ready if (data->map_invalidated) @@ -418,7 +413,7 @@ video::ITexture *Mapper::getMinimapTexture() return data->texture; } -v3f Mapper::getYawVec() +v3f Minimap::getYawVec() { if (data->minimap_shape_round) { return v3f( @@ -430,7 +425,7 @@ v3f Mapper::getYawVec() } } -scene::SMeshBuffer *Mapper::getMinimapMeshBuffer() +scene::SMeshBuffer *Minimap::getMinimapMeshBuffer() { scene::SMeshBuffer *buf = new scene::SMeshBuffer(); buf->Vertices.set_used(4); @@ -452,7 +447,7 @@ scene::SMeshBuffer *Mapper::getMinimapMeshBuffer() return buf; } -void Mapper::drawMinimap() +void Minimap::drawMinimap() { video::ITexture *minimap_texture = getMinimapTexture(); if (!minimap_texture) @@ -550,7 +545,7 @@ void Mapper::drawMinimap() } } -void Mapper::updateActiveMarkers () +void Minimap::updateActiveMarkers() { video::IImage *minimap_mask = data->minimap_shape_round ? data->minimap_mask_round : data->minimap_mask_square; diff --git a/src/minimap.h b/src/minimap.h index 60b80d833..eb0ae1cf4 100644 --- a/src/minimap.h +++ b/src/minimap.h @@ -112,19 +112,21 @@ private: std::map m_blocks_cache; }; -class Mapper { +class Minimap { public: - Mapper(IrrlichtDevice *device, Client *client); - ~Mapper(); + Minimap(IrrlichtDevice *device, Client *client); + ~Minimap(); void addBlock(v3s16 pos, MinimapMapblock *data); v3f getYawVec(); - MinimapMode getMinimapMode(); void setPos(v3s16 pos); + v3s16 getPos() const { return data->pos; } void setAngle(f32 angle); + f32 getAngle() const { return m_angle; } void setMinimapMode(MinimapMode mode); + MinimapMode getMinimapMode() const { return data->mode; } void toggleMinimapShape(); diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp index 9bcc58110..dfaebbe53 100644 --- a/src/network/clientpackethandler.cpp +++ b/src/network/clientpackethandler.cpp @@ -1140,7 +1140,7 @@ void Client::handleCommand_HudSetFlags(NetworkPacket* pkt) if (m_minimap_disabled_by_server && was_minimap_visible) { // defers a minimap update, therefore only call it if really // needed, by checking that minimap was visible before - m_mapper->setMinimapMode(MINIMAP_MODE_OFF); + m_minimap->setMinimapMode(MINIMAP_MODE_OFF); } } diff --git a/src/script/clientscripting.cpp b/src/script/clientscripting.cpp index ccdcb928d..1b73fdf0d 100644 --- a/src/script/clientscripting.cpp +++ b/src/script/clientscripting.cpp @@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "client.h" #include "cpp_api/s_internal.h" #include "lua_api/l_client.h" +#include "lua_api/l_minimap.h" #include "lua_api/l_storage.h" #include "lua_api/l_sound.h" #include "lua_api/l_util.h" @@ -40,9 +41,14 @@ ClientScripting::ClientScripting(Client *client): lua_getglobal(L, "core"); int top = lua_gettop(L); + lua_newtable(L); + lua_setfield(L, -2, "ui"); + InitializeModApi(L, top); lua_pop(L, 1); + LuaMinimap::create(L, client->getMinimap()); + // Push builtin initialization type lua_pushstring(L, "client"); lua_setglobal(L, "INIT"); @@ -59,4 +65,5 @@ void ClientScripting::InitializeModApi(lua_State *L, int top) LuaItemStack::Register(L); StorageRef::Register(L); + LuaMinimap::Register(L); } diff --git a/src/script/lua_api/CMakeLists.txt b/src/script/lua_api/CMakeLists.txt index 2d25d845c..f7f22870e 100644 --- a/src/script/lua_api/CMakeLists.txt +++ b/src/script/lua_api/CMakeLists.txt @@ -25,6 +25,7 @@ set(common_SCRIPT_LUA_API_SRCS set(client_SCRIPT_LUA_API_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/l_client.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_mainmenu.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/l_minimap.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_storage.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_sound.cpp PARENT_SCOPE) diff --git a/src/script/lua_api/l_minimap.cpp b/src/script/lua_api/l_minimap.cpp new file mode 100644 index 000000000..bbe9aef82 --- /dev/null +++ b/src/script/lua_api/l_minimap.cpp @@ -0,0 +1,196 @@ +/* +Minetest +Copyright (C) 2017 Loic Blot + +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_minimap.h" +#include "lua_api/l_internal.h" +#include "common/c_converter.h" +#include "minimap.h" + +LuaMinimap::LuaMinimap(Minimap *m) +{ + m_minimap = m; +} + +void LuaMinimap::create(lua_State *L, Minimap *m) +{ + LuaMinimap *o = new LuaMinimap(m); + *(void **)(lua_newuserdata(L, sizeof(void *))) = o; + luaL_getmetatable(L, className); + lua_setmetatable(L, -2); + + // Keep minimap object stack id + int minimap_object = lua_gettop(L); + + lua_getglobal(L, "core"); + lua_getfield(L, -1, "ui"); + luaL_checktype(L, -1, LUA_TTABLE); + int uitable = lua_gettop(L); + + lua_pushvalue(L, minimap_object); // Copy object to top of stack + lua_setfield(L, uitable, "minimap"); +} + +int LuaMinimap::l_get_pos(lua_State *L) +{ + LuaMinimap *ref = checkobject(L, 1); + Minimap *m = getobject(ref); + + push_v3s16(L, m->getPos()); + return 1; +} + +int LuaMinimap::l_set_pos(lua_State *L) +{ + LuaMinimap *ref = checkobject(L, 1); + Minimap *m = getobject(ref); + + m->setPos(read_v3s16(L, 2)); + return 1; +} + +int LuaMinimap::l_get_angle(lua_State *L) +{ + LuaMinimap *ref = checkobject(L, 1); + Minimap *m = getobject(ref); + + lua_pushinteger(L, m->getAngle()); + return 1; +} + +int LuaMinimap::l_set_angle(lua_State *L) +{ + LuaMinimap *ref = checkobject(L, 1); + Minimap *m = getobject(ref); + + m->setAngle(lua_tointeger(L, 2)); + return 1; +} + +int LuaMinimap::l_get_mode(lua_State *L) +{ + LuaMinimap *ref = checkobject(L, 1); + Minimap *m = getobject(ref); + + lua_pushinteger(L, m->getMinimapMode()); + return 1; +} + +int LuaMinimap::l_set_mode(lua_State *L) +{ + LuaMinimap *ref = checkobject(L, 1); + Minimap *m = getobject(ref); + + s32 mode = lua_tointeger(L, 2); + if (mode < MINIMAP_MODE_OFF || + mode >= MINIMAP_MODE_COUNT) { + return 0; + } + + m->setMinimapMode((MinimapMode) mode); + return 1; +} + +int LuaMinimap::l_toggle_shape(lua_State *L) +{ + LuaMinimap *ref = checkobject(L, 1); + Minimap *m = getobject(ref); + + m->toggleMinimapShape(); + return 1; +} + +int LuaMinimap::l_show(lua_State *L) +{ + Client *client = getClient(L); + assert(client); + client->setMinimapShownByMod(true); + return 1; +} + +int LuaMinimap::l_hide(lua_State *L) +{ + Client *client = getClient(L); + assert(client); + client->setMinimapShownByMod(false); + return 1; +} + +LuaMinimap *LuaMinimap::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 *(LuaMinimap **)ud; // unbox pointer +} + +Minimap* LuaMinimap::getobject(LuaMinimap *ref) +{ + return ref->m_minimap; +} + +int LuaMinimap::gc_object(lua_State *L) { + LuaMinimap *o = *(LuaMinimap **)(lua_touserdata(L, 1)); + delete o; + return 0; +} + +void LuaMinimap::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 +} + +const char LuaMinimap::className[] = "Minimap"; +const luaL_reg LuaMinimap::methods[] = { + luamethod(LuaMinimap, show), + luamethod(LuaMinimap, hide), + luamethod(LuaMinimap, get_pos), + luamethod(LuaMinimap, set_pos), + luamethod(LuaMinimap, get_angle), + luamethod(LuaMinimap, set_angle), + luamethod(LuaMinimap, get_mode), + luamethod(LuaMinimap, set_mode), + luamethod(LuaMinimap, toggle_shape), + {0,0} +}; diff --git a/src/script/lua_api/l_minimap.h b/src/script/lua_api/l_minimap.h new file mode 100644 index 000000000..d9bb8842c --- /dev/null +++ b/src/script/lua_api/l_minimap.h @@ -0,0 +1,64 @@ +/* +Minetest +Copyright (C) 2017 Loic Blot + +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_MINIMAP_H_ +#define L_MINIMAP_H_ + +#include "l_base.h" + + +class Minimap; + +class LuaMinimap : public ModApiBase { +private: + + static const char className[]; + static const luaL_reg methods[]; + + // garbage collector + static int gc_object(lua_State *L); + + static int l_get_pos(lua_State *L); + static int l_set_pos(lua_State *L); + + static int l_get_angle(lua_State *L); + static int l_set_angle(lua_State *L); + + static int l_get_mode(lua_State *L); + static int l_set_mode(lua_State *L); + + static int l_show(lua_State *L); + static int l_hide(lua_State *L); + + static int l_toggle_shape(lua_State *L); + + Minimap *m_minimap; +public: + LuaMinimap(Minimap *m); + ~LuaMinimap() {} + + static void create(lua_State *L, Minimap *object); + + static LuaMinimap *checkobject(lua_State *L, int narg); + static Minimap* getobject(LuaMinimap *ref); + + static void Register(lua_State *L); +}; + +#endif // L_MINIMAP_H_