Add minimap feature
[oweals/minetest.git] / src / game.cpp
index e27ec37dd2d0d1ebfd1557d5093a2cc96845292d..94fb4185258ae7371c1114ac7d2ff9414b67e5cf 100644 (file)
@@ -57,6 +57,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "util/directiontables.h"
 #include "util/pointedthing.h"
 #include "version.h"
+#include "minimap.h"
 
 #include "sound.h"
 
@@ -87,11 +88,11 @@ struct TextDestNodeMetadata : public TextDest {
                std::string ntext = wide_to_narrow(text);
                infostream << "Submitting 'text' field of node at (" << m_p.X << ","
                           << m_p.Y << "," << m_p.Z << "): " << ntext << std::endl;
-               std::map<std::string, std::string> fields;
+               StringMap fields;
                fields["text"] = ntext;
                m_client->sendNodemetaFields(m_p, "", fields);
        }
-       void gotText(std::map<std::string, std::string> fields)
+       void gotText(const StringMap &fields)
        {
                m_client->sendNodemetaFields(m_p, "", fields);
        }
@@ -111,7 +112,7 @@ struct TextDestPlayerInventory : public TextDest {
                m_client = client;
                m_formname = formname;
        }
-       void gotText(std::map<std::string, std::string> fields)
+       void gotText(const StringMap &fields)
        {
                m_client->sendInventoryFields(m_formname, fields);
        }
@@ -138,7 +139,7 @@ struct LocalFormspecHandler : public TextDest {
                errorstream << "LocalFormspecHandler::gotText old style message received" << std::endl;
        }
 
-       void gotText(std::map<std::string, std::string> fields)
+       void gotText(const StringMap &fields)
        {
                if (m_formname == "MT_PAUSE_MENU") {
                        if (fields.find("btn_sound") != fields.end()) {
@@ -180,9 +181,9 @@ struct LocalFormspecHandler : public TextDest {
 
                        if ((fields.find("btn_send") != fields.end()) ||
                                        (fields.find("quit") != fields.end())) {
-                               if (fields.find("f_text") != fields.end()) {
-                                       m_client->typeChatMessage(narrow_to_wide(fields["f_text"]));
-                               }
+                               StringMap::const_iterator it = fields.find("f_text");
+                               if (it != fields.end())
+                                       m_client->typeChatMessage(narrow_to_wide(it->second));
 
                                return;
                        }
@@ -210,12 +211,14 @@ struct LocalFormspecHandler : public TextDest {
                        return;
                }
 
-               errorstream << "LocalFormspecHandler::gotText unhandled >" << m_formname << "< event" << std::endl;
-               int i = 0;
+               errorstream << "LocalFormspecHandler::gotText unhandled >"
+                       << m_formname << "< event" << std::endl;
 
-               for (std::map<std::string, std::string>::iterator iter = fields.begin();
-                               iter != fields.end(); iter++) {
-                       errorstream << "\t" << i << ": " << iter->first << "=" << iter->second << std::endl;
+               int i = 0;
+               StringMap::const_iterator it;
+               for (it = fields.begin(); it != fields.end(); ++it) {
+                       errorstream << "\t" << i << ": " << it->first
+                               << "=" << it->second << std::endl;
                        i++;
                }
        }
@@ -864,6 +867,9 @@ public:
                services->setPixelShaderConstant("eyePosition", (irr::f32 *)&eye_position, 3);
                services->setVertexShaderConstant("eyePosition", (irr::f32 *)&eye_position, 3);
 
+               v3f minimap_yaw_vec = m_client->getMapper()->getYawVec();
+               services->setPixelShaderConstant("yawVec", (irr::f32 *)&minimap_yaw_vec, 3);
+
                // Uniform sampler layers
                int layer0 = 0;
                int layer1 = 1;
@@ -1146,7 +1152,8 @@ static void show_pause_menu(GUIFormSpecMenu **cur_formspec,
        LocalFormspecHandler *txt_dst = new LocalFormspecHandler("MT_PAUSE_MENU");
 
        create_formspec_menu(cur_formspec, invmgr, gamedef, tsrc, device,  fs_src, txt_dst, NULL);
-       (*cur_formspec)->setFocus(L"btn_continue");
+       std::string con("btn_continue");
+       (*cur_formspec)->setFocus(con);
        (*cur_formspec)->doPause = true;
 }
 
@@ -1235,6 +1242,7 @@ struct KeyCache {
                KEYMAP_ID_CHAT,
                KEYMAP_ID_CMD,
                KEYMAP_ID_CONSOLE,
+               KEYMAP_ID_MINIMAP,
                KEYMAP_ID_FREEMOVE,
                KEYMAP_ID_FASTMOVE,
                KEYMAP_ID_NOCLIP,
@@ -1284,6 +1292,7 @@ void KeyCache::populate()
        key[KEYMAP_ID_CHAT]         = getKeySetting("keymap_chat");
        key[KEYMAP_ID_CMD]          = getKeySetting("keymap_cmd");
        key[KEYMAP_ID_CONSOLE]      = getKeySetting("keymap_console");
+       key[KEYMAP_ID_MINIMAP]      = getKeySetting("keymap_minimap");
        key[KEYMAP_ID_FREEMOVE]     = getKeySetting("keymap_freemove");
        key[KEYMAP_ID_FASTMOVE]     = getKeySetting("keymap_fastmove");
        key[KEYMAP_ID_NOCLIP]       = getKeySetting("keymap_noclip");
@@ -1389,6 +1398,7 @@ struct VolatileRunFlags {
        bool invert_mouse;
        bool show_chat;
        bool show_hud;
+       bool show_minimap;
        bool force_fog_off;
        bool show_debug;
        bool show_profiler_graph;
@@ -1487,6 +1497,8 @@ protected:
 
        void toggleChat(float *statustext_time, bool *flag);
        void toggleHud(float *statustext_time, bool *flag);
+       void toggleMinimap(float *statustext_time, bool *flag1, bool *flag2,
+                       bool shift_pressed);
        void toggleFog(float *statustext_time, bool *flag);
        void toggleDebug(float *statustext_time, bool *show_debug,
                        bool *show_profiler_graph);
@@ -1565,6 +1577,7 @@ private:
        Sky *sky;                         // Free using ->Drop()
        Inventory *local_inventory;
        Hud *hud;
+       Mapper *mapper;
 
        /* 'cache'
           This class does take ownership/responsibily for cleaning up etc of any of
@@ -1618,6 +1631,11 @@ private:
        bool m_cache_enable_fog;
        f32  m_cache_mouse_sensitivity;
        f32  m_repeat_right_click_time;
+
+#ifdef __ANDROID__
+       bool m_cache_hold_aux1;
+#endif
+
 };
 
 Game::Game() :
@@ -1640,7 +1658,8 @@ Game::Game() :
        clouds(NULL),
        sky(NULL),
        local_inventory(NULL),
-       hud(NULL)
+       hud(NULL),
+       mapper(NULL)
 {
        m_cache_doubletap_jump            = g_settings->getBool("doubletap_jump");
        m_cache_enable_node_highlighting  = g_settings->getBool("enable_node_highlighting");
@@ -1651,6 +1670,11 @@ Game::Game() :
        m_repeat_right_click_time         = g_settings->getFloat("repeat_rightclick_time");
 
        m_cache_mouse_sensitivity = rangelim(m_cache_mouse_sensitivity, 0.001, 100.0);
+
+#ifdef __ANDROID__
+       m_cache_hold_aux1 = false;      // This is initialised properly later
+#endif
+
 }
 
 
@@ -1737,6 +1761,7 @@ void Game::run()
 
        flags.show_chat = true;
        flags.show_hud = true;
+       flags.show_minimap = g_settings->getBool("enable_minimap");
        flags.show_debug = g_settings->getBool("show_debug");
        flags.invert_mouse = g_settings->getBool("invert_mouse");
        flags.first_loop_after_window_activation = true;
@@ -1757,6 +1782,11 @@ void Game::run()
 
        set_light_table(g_settings->getFloat("display_gamma"));
 
+#ifdef __ANDROID__
+       m_cache_hold_aux1 = g_settings->getBool("fast_move")
+                       && client->checkPrivilege("fast");
+#endif
+
        while (device->run() && !(*kill || g_gamecallback->shutdown_requested)) {
 
                /* Must be called immediately after a device->run() call because it
@@ -2047,6 +2077,9 @@ bool Game::createClient(const std::string &playername,
                return false;
        }
 
+       mapper = client->getMapper();
+       mapper->setMinimapMode(MINIMAP_MODE_OFF);
+
        return true;
 }
 
@@ -2581,6 +2614,9 @@ void Game::processKeyboardInput(VolatileRunFlags *flags,
                client->makeScreenshot(device);
        } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_TOGGLE_HUD])) {
                toggleHud(statustext_time, &flags->show_hud);
+       } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_MINIMAP])) {
+               toggleMinimap(statustext_time, &flags->show_minimap, &flags->show_hud,
+                       input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_SNEAK]));
        } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_TOGGLE_CHAT])) {
                toggleChat(statustext_time, &flags->show_chat);
        } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_TOGGLE_FORCE_FOG_OFF])) {
@@ -2745,8 +2781,14 @@ void Game::toggleFast(float *statustext_time)
        *statustext_time = 0;
        statustext = msg[fast_move];
 
-       if (fast_move && !client->checkPrivilege("fast"))
+       bool has_fast_privs = client->checkPrivilege("fast");
+
+       if (fast_move && !has_fast_privs)
                statustext += L" (note: no 'fast' privilege)";
+
+#ifdef __ANDROID__
+       m_cache_hold_aux1 = fast_move && has_fast_privs;
+#endif
 }
 
 
@@ -2795,6 +2837,44 @@ void Game::toggleHud(float *statustext_time, bool *flag)
                client->setHighlighted(client->getHighlighted(), *flag);
 }
 
+void Game::toggleMinimap(float *statustext_time, bool *flag, bool *show_hud, bool shift_pressed)
+{
+       if (*show_hud && g_settings->getBool("enable_minimap")) {
+               if (shift_pressed) {
+                       mapper->toggleMinimapShape();
+                       return;
+               }
+               MinimapMode mode = mapper->getMinimapMode();
+               mode = (MinimapMode)((int)(mode) + 1);
+               *flag = true;
+               switch (mode) {
+                       case MINIMAP_MODE_SURFACEx1:
+                               statustext = L"Minimap in surface mode, Zoom x1";
+                               break;
+                       case MINIMAP_MODE_SURFACEx2:
+                               statustext = L"Minimap in surface mode, Zoom x2";
+                               break;
+                       case MINIMAP_MODE_SURFACEx4:
+                               statustext = L"Minimap in surface mode, Zoom x4";
+                               break;
+                       case MINIMAP_MODE_RADARx1:
+                               statustext = L"Minimap in radar mode, Zoom x1";
+                               break;
+                       case MINIMAP_MODE_RADARx2:
+                               statustext = L"Minimap in radar mode, Zoom x2";
+                               break;
+                       case MINIMAP_MODE_RADARx4:
+                               statustext = L"Minimap in radar mode, Zoom x4";
+                               break;
+                       default:
+                               mode = MINIMAP_MODE_OFF;
+                               *flag = false;
+                               statustext = L"Minimap hidden";
+               }
+               *statustext_time = 0;
+               mapper->setMinimapMode(mode);
+       }
+}
 
 void Game::toggleFog(float *statustext_time, bool *flag)
 {
@@ -2996,11 +3076,15 @@ void Game::updatePlayerControl(const CameraOrientation &cam)
                );
 
 #ifdef ANDROID
-       /* For Android, invert the meaning of holding down the fast button (i.e.
-        * holding down the fast button -- if there is one -- means walk)
+       /* For Android, simulate holding down AUX1 (fast move) if the user has
+        * the fast_move setting toggled on. If there is an aux1 key defined for
+        * Android then its meaning is inverted (i.e. holding aux1 means walk and
+        * not fast)
         */
-       control.aux1 = control.aux1 ^ true;
-       keypress_bits ^= ((u32)(1U << 5));
+       if (m_cache_hold_aux1) {
+               control.aux1 = control.aux1 ^ true;
+               keypress_bits ^= ((u32)(1U << 5));
+       }
 #endif
 
        client->setPlayerControl(control);
@@ -3270,6 +3354,7 @@ void Game::updateCamera(VolatileRunFlags *flags, u32 busy_time,
                camera->toggleCameraMode();
 
                playercao->setVisible(camera->getCameraMode() > CAMERA_MODE_FIRST);
+               playercao->setChildrenVisible(camera->getCameraMode() > CAMERA_MODE_FIRST);
        }
 
        float full_punch_interval = playeritem_toolcap.full_punch_interval;
@@ -3924,8 +4009,9 @@ void Game::updateFrame(std::vector<aabb3f> &highlight_boxes,
                stats->beginscenetime = timer.stop(true);
        }
 
-       draw_scene(driver, smgr, *camera, *client, player, *hud, guienv,
-                       highlight_boxes, screensize, skycolor, flags.show_hud);
+       draw_scene(driver, smgr, *camera, *client, player, *hud, *mapper,
+                       guienv, highlight_boxes, screensize, skycolor, flags.show_hud,
+                       flags.show_minimap);
 
        /*
                Profiler graph
@@ -3958,6 +4044,13 @@ void Game::updateFrame(std::vector<aabb3f> &highlight_boxes,
                        player->hurt_tilt_strength = 0;
        }
 
+       /*
+               Update minimap pos
+       */
+       if (flags.show_minimap && flags.show_hud) {
+               mapper->setPos(floatToInt(player->getPosition(), BS));
+       }
+
        /*
                End scene
        */