X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fgame.cpp;h=bae946f28eaa70a3751901b5e25dd18bc5fc5fb2;hb=58e6d25e033c76dc91aaac18fdeda92ac23fe0e1;hp=ef0d3a556f40b2893ae1ef3f8966054566e2d2cf;hpb=660e63688761dc08558de030a53464d39a6ec85f;p=oweals%2Fminetest.git diff --git a/src/game.cpp b/src/game.cpp index ef0d3a556..bae946f28 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -31,7 +31,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "guiPasswordChange.h" #include "guiVolumeChange.h" #include "guiFormSpecMenu.h" -#include "guiTextInputMenu.h" #include "tool.h" #include "guiChatConsole.h" #include "config.h" @@ -71,6 +70,10 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "drawscene.h" #include "content_cao.h" +#ifdef HAVE_TOUCHSCREENGUI +#include "touchscreengui.h" +#endif + /* Text input system */ @@ -319,7 +322,7 @@ PointedThing getPointedThing(Client *client, v3f player_position, // That didn't work, try to find a pointed at node - + v3s16 pos_i = floatToInt(player_position, BS); /*infostream<<"pos_i=("<0 ? a : 1); s16 zend = pos_i.Z + (camera_direction.Z>0 ? a : 1); s16 xend = pos_i.X + (camera_direction.X>0 ? a : 1); - + // Prevent signed number overflow if(yend==32767) yend=32766; @@ -404,14 +407,16 @@ PointedThing getPointedThing(Client *client, v3f player_position, mindistance = distance; hilightboxes.clear(); - for(std::vector::const_iterator - i2 = boxes.begin(); - i2 != boxes.end(); i2++) - { - aabb3f box = *i2; - box.MinEdge += npf + v3f(-d,-d,-d) - intToFloat(camera_offset, BS); - box.MaxEdge += npf + v3f(d,d,d) - intToFloat(camera_offset, BS); - hilightboxes.push_back(box); + if (!g_settings->getBool("enable_node_highlighting")) { + for(std::vector::const_iterator + i2 = boxes.begin(); + i2 != boxes.end(); i2++) + { + aabb3f box = *i2; + box.MinEdge += npf + v3f(-d,-d,-d) - intToFloat(camera_offset, BS); + box.MaxEdge += npf + v3f(d,d,d) - intToFloat(camera_offset, BS); + hilightboxes.push_back(box); + } } } } @@ -483,7 +488,7 @@ public: while(m_log.size() > m_log_max_size) m_log.erase(m_log.begin()); } - + void draw(s32 x_left, s32 y_bottom, video::IVideoDriver *driver, gui::IGUIFont* font) const { @@ -532,7 +537,7 @@ public: s32 graphh = 50; s32 textx = x_left + m_log_max_size + 15; s32 textx2 = textx + 200 - 15; - + // Draw background /*{ u32 num_graphs = m_meta.size(); @@ -541,7 +546,7 @@ public: video::SColor bgcolor(120,0,0,0); driver->draw2DRectangle(bgcolor, rect, NULL); }*/ - + s32 meta_i = 0; for(std::map::const_iterator i = m_meta.begin(); i != m_meta.end(); i++){ @@ -627,7 +632,7 @@ class NodeDugEvent: public MtEvent public: v3s16 p; MapNode n; - + NodeDugEvent(v3s16 p, MapNode n): p(p), n(n) @@ -800,7 +805,7 @@ public: u32 daynight_ratio = m_client->getEnv().getDayNightRatio(); float daynight_ratio_f = (float)daynight_ratio / 1000.0; services->setPixelShaderConstant("dayNightRatio", &daynight_ratio_f, 1); - + u32 animation_timer = porting::getTimeMs() % 100000; float animation_timer_f = (float)animation_timer / 100000.0; services->setPixelShaderConstant("animationTimer", &animation_timer_f, 1); @@ -943,13 +948,20 @@ static inline void create_formspec_menu(GUIFormSpecMenu** cur_formspec, } } +#ifdef __ANDROID__ +#define SIZE_TAG "size[11,5.5]" +#else +#define SIZE_TAG "size[11,5.5,true]" +#endif + static void show_chat_menu(GUIFormSpecMenu** cur_formspec, InventoryManager *invmgr, IGameDef *gamedef, IWritableTextureSource* tsrc, IrrlichtDevice * device, Client* client, std::string text) { std::string formspec = - "size[11,5.5,true]" + FORMSPEC_VERSION_STRING + SIZE_TAG "field[3,2.35;6,0.5;f_text;;" + text + "]" "button_exit[4,3;3,0.5;btn_send;" + wide_to_narrow(wstrgettext("Proceed")) + "]" ; @@ -968,8 +980,8 @@ static void show_deathscreen(GUIFormSpecMenu** cur_formspec, IWritableTextureSource* tsrc, IrrlichtDevice * device, Client* client) { std::string formspec = - std::string("") + - "size[11,5.5,true]" + std::string(FORMSPEC_VERSION_STRING) + + SIZE_TAG "bgcolor[#320000b4;true]" "label[4.85,1.35;You died.]" "button_exit[4,3;3,0.5;btn_respawn;" + gettext("Respawn") + "]" @@ -990,6 +1002,21 @@ static void show_pause_menu(GUIFormSpecMenu** cur_formspec, IWritableTextureSource* tsrc, IrrlichtDevice * device, bool singleplayermode) { +#ifdef __ANDROID__ + std::string control_text = wide_to_narrow(wstrgettext("Default Controls:\n" + "No menu visible:\n" + "- single tap: button activate\n" + "- double tap: place/use\n" + "- slide finger: look around\n" + "Menu/Inventory visible:\n" + "- double tap (outside):\n" + " -->close\n" + "- touch stack, touch slot:\n" + " --> move stack\n" + "- touch&drag, tap 2nd finger\n" + " --> place single item to slot\n" + )); +#else std::string control_text = wide_to_narrow(wstrgettext("Default Controls:\n" "- WASD: move\n" "- Space: jump/climb\n" @@ -1002,11 +1029,11 @@ static void show_pause_menu(GUIFormSpecMenu** cur_formspec, "- Mouse wheel: select item\n" "- T: chat\n" )); - +#endif float ypos = singleplayermode ? 1.0 : 0.5; std::ostringstream os; - os << "size[11,5.5,true]" + os << FORMSPEC_VERSION_STRING << SIZE_TAG << "button_exit[4," << (ypos++) << ";3,0.5;btn_continue;" << wide_to_narrow(wstrgettext("Continue")) << "]"; @@ -1021,7 +1048,7 @@ static void show_pause_menu(GUIFormSpecMenu** cur_formspec, << wide_to_narrow(wstrgettext("Exit to Menu")) << "]"; os << "button_exit[4," << (ypos++) << ";3,0.5;btn_exit_os;" << wide_to_narrow(wstrgettext("Exit to OS")) << "]" - << "textarea[7.5,0.25;3.75,6;;" << control_text << ";]" + << "textarea[7.5,0.25;3.9,6.25;;" << control_text << ";]" << "textarea[0.4,0.25;3.5,6;;" << "Minetest\n" << minetest_build_info << "\n" << "path_user = " << wrap_rows(porting::path_user, 20) @@ -1034,10 +1061,54 @@ 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); - - if (singleplayermode) { - (*cur_formspec)->doPause = true; + + (*cur_formspec)->doPause = true; +} + +/******************************************************************************/ +static void updateChat(Client& client, f32 dtime, bool show_debug, + const v2u32& screensize, bool show_chat, u32 show_profiler, + ChatBackend& chat_backend, gui::IGUIStaticText* guitext_chat, + gui::IGUIFont* font) +{ + // Add chat log output for errors to be shown in chat + static LogOutputBuffer chat_log_error_buf(LMT_ERROR); + + // Get new messages from error log buffer + while(!chat_log_error_buf.empty()) { + chat_backend.addMessage(L"", narrow_to_wide(chat_log_error_buf.get())); + } + + // Get new messages from client + std::wstring message; + while (client.getChatMessage(message)) { + chat_backend.addUnparsedMessage(message); } + + // Remove old messages + chat_backend.step(dtime); + + // Display all messages in a static text element + unsigned int recent_chat_count = chat_backend.getRecentBuffer().getLineCount(); + std::wstring recent_chat = chat_backend.getRecentChat(); + + // TODO replace by fontengine fcts + unsigned int line_height = font->getDimension(L"Ay").Height + font->getKerningHeight(); + + guitext_chat->setText(recent_chat.c_str()); + + // Update gui element size and position + s32 chat_y = 5 + line_height; + if (show_debug) + chat_y += line_height; + + core::rect rect(10, chat_y, font->getDimension(recent_chat.c_str()).Width +10, + chat_y + (recent_chat_count * line_height)); + + guitext_chat->setRelativePosition(rect); + // Don't show chat if disabled or empty or profiler is enabled + guitext_chat->setVisible( + show_chat && recent_chat_count != 0 && !show_profiler); } /******************************************************************************/ @@ -1052,7 +1123,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, GUIFormSpecMenu* current_formspec = 0; video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); - + // Calculate text height using the font u32 text_height = font->getDimension(L"Random test string").Height; @@ -1065,19 +1136,19 @@ void the_game(bool &kill, bool random_input, InputHandler *input, draw_load_screen(text, device, guienv, font, 0, 0); delete[] text; } - + // Create texture source IWritableTextureSource *tsrc = createTextureSource(device); - + // Create shader source IWritableShaderSource *shsrc = createShaderSource(device); - + // These will be filled by data received from the server // Create item definition manager IWritableItemDefManager *itemdef = createItemDefManager(); // Create node definition manager IWritableNodeDefManager *nodedef = createNodeDefManager(); - + // Sound fetcher (useful when testing) GameOnDemandSoundFetcher soundfetcher; @@ -1109,9 +1180,6 @@ void the_game(bool &kill, bool random_input, InputHandler *input, // Sound maker SoundMaker soundmaker(sound, nodedef); soundmaker.registerReceiver(&eventmgr); - - // Add chat log output for errors to be shown in chat - LogOutputBuffer chat_log_error_buf(LMT_ERROR); // Create UI for modifying quicktune values QuicktuneShortcutter quicktune; @@ -1158,7 +1226,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, } do{ // Client scope (breakable do-while(0)) - + /* Create client */ @@ -1169,9 +1237,9 @@ void the_game(bool &kill, bool random_input, InputHandler *input, delete[] text; } infostream<<"Creating client"<step(dtime); - + // End condition - if(client.getState() == LC_Init){ + if(client.getState() == LC_Init) { could_connect = true; break; } // Break conditions - if(client.accessDenied()){ + if(client.accessDenied()) { error_message = L"Access denied. Reason: " +client.accessDeniedReason(); errorstream<wasKeyDown(EscapeKey)){ + if(input->wasKeyDown(EscapeKey) || input->wasKeyDown(CancelKey)) { connect_aborted = true; infostream<<"Connect aborted [Escape]"<getFloat("fps_max"); bool cloud_menu_background = g_settings->getBool("menu_clouds"); u32 lasttime = device->getTimer()->getTime(); - while(device->run()) - { + while (device->run()) { f32 dtime = 0.033; // in seconds if (cloud_menu_background) { u32 time = device->getTimer()->getTime(); @@ -1343,34 +1410,34 @@ void the_game(bool &kill, bool random_input, InputHandler *input, } // Update client and server client.step(dtime); - if(server != NULL) + if (server != NULL) server->step(dtime); - + // End condition - if(client.mediaReceived() && + if (client.mediaReceived() && client.itemdefReceived() && - client.nodedefReceived()){ + client.nodedefReceived()) { got_content = true; break; } // Break conditions - if(client.accessDenied()){ + if (client.accessDenied()) { error_message = L"Access denied. Reason: " +client.accessDeniedReason(); errorstream<wasKeyDown(EscapeKey)){ + if (input->wasKeyDown(EscapeKey) || input->wasKeyDown(CancelKey)) { content_aborted = true; infostream<<"Connect aborted [Escape]"<getBool("enable_clouds")) { @@ -1481,7 +1548,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, sky = new Sky(smgr->getRootSceneNode(), smgr, -1); scene::ISceneNode* skybox = NULL; - + /* A copy of the local inventory */ @@ -1505,58 +1572,63 @@ void the_game(bool &kill, bool random_input, InputHandler *input, gui::IGUIStaticText *guitext = guienv->addStaticText( L"Minetest", core::rect(0, 0, 0, 0), - false, false); + false, false, guiroot); // Second line of debug text gui::IGUIStaticText *guitext2 = guienv->addStaticText( L"", core::rect(0, 0, 0, 0), - false, false); + false, false, guiroot); // At the middle of the screen // Object infos are shown in this gui::IGUIStaticText *guitext_info = guienv->addStaticText( L"", core::rect(0,0,400,text_height*5+5) + v2s32(100,200), - false, true); - + false, true, guiroot); + // Status text (displays info when showing and hiding GUI stuff, etc.) gui::IGUIStaticText *guitext_status = guienv->addStaticText( L"", core::rect(0,0,0,0), - false, false); + false, false, guiroot); guitext_status->setVisible(false); - + std::wstring statustext; float statustext_time = 0; - + // Chat text gui::IGUIStaticText *guitext_chat = guienv->addStaticText( L"", core::rect(0,0,0,0), //false, false); // Disable word wrap as of now - false, true); + false, true, guiroot); // Remove stale "recent" chat messages from previous connections chat_backend.clearRecentChat(); // Chat backend and console GUIChatConsole *gui_chat_console = new GUIChatConsole(guienv, guienv->getRootGUIElement(), -1, &chat_backend, &client); - + // Profiler text (size is updated when text is updated) gui::IGUIStaticText *guitext_profiler = guienv->addStaticText( L"", core::rect(0,0,0,0), - false, false); + false, false, guiroot); guitext_profiler->setBackgroundColor(video::SColor(120,0,0,0)); guitext_profiler->setVisible(false); guitext_profiler->setWordWrap(true); - + +#ifdef HAVE_TOUCHSCREENGUI + if (g_touchscreengui) + g_touchscreengui->init(tsrc,porting::getDisplayDensity()); +#endif + /* Some statistics are collected in these */ u32 drawtime = 0; u32 beginscenetime = 0; u32 endscenetime = 0; - + float recent_turn_speed = 0.0; - + ProfilerGraph graph; // Initially clear the profiler Profiler::GraphValues dummyvalues; @@ -1624,7 +1696,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, LocalPlayer* player = client.getEnv().getLocalPlayer(); player->hurt_tilt_timer = 0; player->hurt_tilt_strength = 0; - + /* HUD object */ @@ -1641,7 +1713,8 @@ void the_game(bool &kill, bool random_input, InputHandler *input, for(;;) { - if(device->run() == false || kill == true) + if(device->run() == false || kill == true || + g_gamecallback->shutdown_requested) break; v2u32 screensize = driver->getScreenSize(); @@ -1658,7 +1731,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, busytime_u32 = 0; busytime = busytime_u32 / 1000.0; } - + g_profiler->graphAdd("mainloop_other", busytime - (float)drawtime/1000.0f); // Necessary for device->getTimer()->getTime() @@ -1673,7 +1746,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, g_settings->getFloat("pause_fps_max") : g_settings->getFloat("fps_max"); u32 frametime_min = 1000./fps_max; - + if(busytime_u32 < frametime_min) { u32 sleeptime = frametime_min - busytime_u32; @@ -1689,7 +1762,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, Time difference calculation */ f32 dtime; // in seconds - + u32 time = device->getTimer()->getTime(); if(time > lasttime) dtime = (time - lasttime) / 1000.0; @@ -1706,7 +1779,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, if(object_hit_delay_timer >= 0) object_hit_delay_timer -= dtime; time_from_last_punch += dtime; - + g_profiler->add("Elapsed time", dtime); g_profiler->avg("FPS", 1./dtime); @@ -1735,7 +1808,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, jitter1_max = 0.0; } } - + /* Busytime average and jitter calculation */ @@ -1743,7 +1816,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, static f32 busytime_avg1 = 0.0; busytime_avg1 = busytime_avg1 * 0.98 + busytime * 0.02; f32 busytime_jitter1 = busytime - busytime_avg1; - + static f32 busytime_jitter1_max_sample = 0.0; static f32 busytime_jitter1_min_sample = 0.0; { @@ -1767,7 +1840,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, /* Handle miscellaneous stuff */ - + if(client.accessDenied()) { error_message = L"Access denied. Reason: " @@ -1811,7 +1884,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, Random calculations */ hud.resizeHotbar(); - + // Hilight boxes collected during the loop and displayed std::vector hilightboxes; @@ -1843,7 +1916,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, /* Direct handling of user input */ - + // Reset input if window not active or some menu is active if(device->isWindowActive() == false || noMenuActive() == false @@ -1858,6 +1931,15 @@ void the_game(bool &kill, bool random_input, InputHandler *input, // Input handler step() (used by the random input generator) input->step(dtime); +#ifdef HAVE_TOUCHSCREENGUI + if (g_touchscreengui) { + g_touchscreengui->step(dtime); + } +#endif +#ifdef __ANDROID__ + if (current_formspec != 0) + current_formspec->getAndroidUIInput(); +#endif // Increase timer for doubleclick of "jump" if(g_settings->getBool("doubletap_jump") && jump_timer <= 0.2) @@ -1880,7 +1962,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, { infostream<<"the_game: " <<"Launching inventory"<setFormSpec(fs_src->getForm(), inventoryloc); } - else if(input->wasKeyDown(EscapeKey)) + else if(input->wasKeyDown(EscapeKey) || input->wasKeyDown(CancelKey)) { show_pause_menu(¤t_formspec, &client, gamedef, tsrc, device, simple_singleplayer_mode); @@ -1988,31 +2070,41 @@ void the_game(bool &kill, bool random_input, InputHandler *input, } else if(input->wasKeyDown(getKeySetting("keymap_screenshot"))) { - irr::video::IImage* const image = driver->createScreenShot(); - if (image) { - irr::c8 filename[256]; - snprintf(filename, 256, "%s" DIR_DELIM "screenshot_%u.png", + irr::video::IImage* const raw_image = driver->createScreenShot(); + if (raw_image) { + irr::video::IImage* const image = driver->createImage(video::ECF_R8G8B8, + raw_image->getDimension()); + + if (image) { + raw_image->copyTo(image); + irr::c8 filename[256]; + snprintf(filename, sizeof(filename), "%s" DIR_DELIM "screenshot_%u.png", g_settings->get("screenshot_path").c_str(), device->getTimer()->getRealTime()); - if (driver->writeImageToFile(image, filename)) { - std::wstringstream sstr; - sstr<<"Saved screenshot to '"<writeImageToFile(image, filename)) { + std::wstringstream sstr; + sstr << "Saved screenshot to '" << filename << "'"; + infostream << "Saved screenshot to '" << filename << "'" << std::endl; + statustext = sstr.str(); + statustext_time = 0; + } else { + infostream << "Failed to save screenshot '" << filename << "'" << std::endl; + } + image->drop(); } - image->drop(); + raw_image->drop(); } } else if(input->wasKeyDown(getKeySetting("keymap_toggle_hud"))) { show_hud = !show_hud; - if(show_hud) + if(show_hud) { statustext = L"HUD shown"; - else + client.setHighlighted(client.getHighlighted(), true); + } else { statustext = L"HUD hidden"; + client.setHighlighted(client.getHighlighted(), false); + } statustext_time = 0; } else if(input->wasKeyDown(getKeySetting("keymap_toggle_chat"))) @@ -2113,7 +2205,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, + itos(range_new)); statustext_time = 0; } - + // Reset jump_timer if(!input->isKeyDown(getKeySetting("keymap_jump")) && reset_jump_timer) { @@ -2160,7 +2252,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, new_playeritem = max_item; } } - + // Item selection for(u16 i=0; i<10; i++) { @@ -2210,29 +2302,37 @@ void the_game(bool &kill, bool random_input, InputHandler *input, Mouse and camera control NOTE: Do this before client.setPlayerControl() to not cause a camera lag of one frame */ - + float turn_amount = 0; if((device->isWindowActive() && noMenuActive()) || random_input) { +#ifndef __ANDROID__ if(!random_input) { // Mac OSX gets upset if this is set every frame if(device->getCursorControl()->isVisible()) device->getCursorControl()->setVisible(false); } +#endif if(first_loop_after_window_activation){ //infostream<<"window active, first loop"<getMousePos().X - (driver->getScreenSize().Width/2); - s32 dy = input->getMousePos().Y - (driver->getScreenSize().Height/2); - if(invert_mouse || camera.getCameraMode() == CAMERA_MODE_THIRD_FRONT) { + } else { +#ifdef HAVE_TOUCHSCREENGUI + if (g_touchscreengui) { + camera_yaw = g_touchscreengui->getYaw(); + camera_pitch = g_touchscreengui->getPitch(); + } else { +#endif + s32 dx = input->getMousePos().X - (driver->getScreenSize().Width/2); + s32 dy = input->getMousePos().Y - (driver->getScreenSize().Height/2); + if ((invert_mouse) + || (camera.getCameraMode() == CAMERA_MODE_THIRD_FRONT)) { dy = -dy; } //infostream<<"window active, pos difference "<isKeyDown(irr::KEY_UP)) dy -= dtime * keyspeed; @@ -2242,23 +2342,28 @@ void the_game(bool &kill, bool random_input, InputHandler *input, dx -= dtime * keyspeed; if(input->isKeyDown(irr::KEY_RIGHT)) dx += dtime * keyspeed;*/ - + float d = g_settings->getFloat("mouse_sensitivity"); d = rangelim(d, 0.01, 100.0); camera_yaw -= dx*d; camera_pitch += dy*d; + turn_amount = v2f(dx, dy).getLength() * d; + +#ifdef HAVE_TOUCHSCREENGUI + } +#endif if(camera_pitch < -89.5) camera_pitch = -89.5; if(camera_pitch > 89.5) camera_pitch = 89.5; - - turn_amount = v2f(dx, dy).getLength() * d; } input->setMousePos((driver->getScreenSize().Width/2), (driver->getScreenSize().Height/2)); } else{ +#ifndef ANDROID // Mac OSX gets upset if this is set every frame if(device->getCursorControl()->isVisible() == false) device->getCursorControl()->setVisible(true); +#endif //infostream<<"window inactive"<hurt_tilt_timer = 1.5; - player->hurt_tilt_strength = event.player_damage.amount/2; - player->hurt_tilt_strength = rangelim(player->hurt_tilt_strength, 2.0, 10.0); + player->hurt_tilt_strength = event.player_damage.amount/4; + player->hurt_tilt_strength = rangelim(player->hurt_tilt_strength, 1.0, 4.0); MtEvent *e = new SimpleTriggerEvent("PlayerDamage"); gamedef->event()->put(e); } - else if(event.type == CE_PLAYER_FORCE_MOVE) - { + else if(event.type == CE_PLAYER_FORCE_MOVE) { camera_yaw = event.player_force_move.yaw; camera_pitch = event.player_force_move.pitch; } - else if(event.type == CE_DEATHSCREEN) - { + else if(event.type == CE_DEATHSCREEN) { show_deathscreen(¤t_formspec, &client, gamedef, tsrc, device, &client); @@ -2376,8 +2476,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, player->hurt_tilt_strength = 0; } - else if (event.type == CE_SHOW_FORMSPEC) - { + else if (event.type == CE_SHOW_FORMSPEC) { FormspecFormSource* fs_src = new FormspecFormSource(*(event.show_formspec.formspec)); TextDestPlayerInventory* txt_dst = @@ -2389,8 +2488,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, delete(event.show_formspec.formspec); delete(event.show_formspec.formname); } - else if(event.type == CE_SPAWN_PARTICLE) - { + else if(event.type == CE_SPAWN_PARTICLE) { LocalPlayer* player = client.getEnv().getLocalPlayer(); video::ITexture *texture = gamedef->tsrc()->getTexture(*(event.spawn_particle.texture)); @@ -2407,8 +2505,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, v2f(0.0, 0.0), v2f(1.0, 1.0)); } - else if(event.type == CE_ADD_PARTICLESPAWNER) - { + else if(event.type == CE_ADD_PARTICLESPAWNER) { LocalPlayer* player = client.getEnv().getLocalPlayer(); video::ITexture *texture = gamedef->tsrc()->getTexture(*(event.add_particlespawner.texture)); @@ -2431,15 +2528,15 @@ void the_game(bool &kill, bool random_input, InputHandler *input, texture, event.add_particlespawner.id); } - else if(event.type == CE_DELETE_PARTICLESPAWNER) - { + else if(event.type == CE_DELETE_PARTICLESPAWNER) { delete_particlespawner (event.delete_particlespawner.id); } - else if (event.type == CE_HUDADD) - { + else if (event.type == CE_HUDADD) { u32 id = event.hudadd.id; - size_t nhudelem = player->hud.size(); - if (id > nhudelem || (id < nhudelem && player->hud[id])) { + + HudElement *e = player->getHud(id); + + if (e != NULL) { delete event.hudadd.pos; delete event.hudadd.name; delete event.hudadd.scale; @@ -2450,8 +2547,8 @@ void the_game(bool &kill, bool random_input, InputHandler *input, delete event.hudadd.size; continue; } - - HudElement *e = new HudElement; + + e = new HudElement; e->type = (HudElementType)event.hudadd.type; e->pos = *event.hudadd.pos; e->name = *event.hudadd.name; @@ -2464,11 +2561,10 @@ void the_game(bool &kill, bool random_input, InputHandler *input, e->offset = *event.hudadd.offset; e->world_pos = *event.hudadd.world_pos; e->size = *event.hudadd.size; - - if (id == nhudelem) - player->hud.push_back(e); - else - player->hud[id] = e; + + u32 new_id = player->addHud(e); + //if this isn't true our huds aren't consistent + assert(new_id == id); delete event.hudadd.pos; delete event.hudadd.name; @@ -2479,26 +2575,24 @@ void the_game(bool &kill, bool random_input, InputHandler *input, delete event.hudadd.world_pos; delete event.hudadd.size; } - else if (event.type == CE_HUDRM) - { - u32 id = event.hudrm.id; - if (id < player->hud.size() && player->hud[id]) { - delete player->hud[id]; - player->hud[id] = NULL; - } + else if (event.type == CE_HUDRM) { + HudElement* e = player->removeHud(event.hudrm.id); + + if (e != NULL) + delete (e); } - else if (event.type == CE_HUDCHANGE) - { + else if (event.type == CE_HUDCHANGE) { u32 id = event.hudchange.id; - if (id >= player->hud.size() || !player->hud[id]) { + HudElement* e = player->getHud(id); + if (e == NULL) + { delete event.hudchange.v3fdata; delete event.hudchange.v2fdata; delete event.hudchange.sdata; delete event.hudchange.v2s32data; continue; } - - HudElement* e = player->hud[id]; + switch (event.hudchange.stat) { case HUD_STAT_POS: e->pos = *event.hudchange.v2fdata; @@ -2534,25 +2628,24 @@ void the_game(bool &kill, bool random_input, InputHandler *input, e->size = *event.hudchange.v2s32data; break; } - + delete event.hudchange.v3fdata; delete event.hudchange.v2fdata; delete event.hudchange.sdata; delete event.hudchange.v2s32data; } - else if (event.type == CE_SET_SKY) - { + else if (event.type == CE_SET_SKY) { sky->setVisible(false); if(skybox){ - skybox->drop(); + skybox->remove(); skybox = NULL; } // Handle according to type - if(*event.set_sky.type == "regular"){ + if(*event.set_sky.type == "regular") { sky->setVisible(true); } else if(*event.set_sky.type == "skybox" && - event.set_sky.params->size() == 6){ + event.set_sky.params->size() == 6) { sky->setFallbackBgColor(*event.set_sky.bgcolor); skybox = smgr->addSkyBoxSceneNode( tsrc->getTexture((*event.set_sky.params)[0]), @@ -2574,15 +2667,14 @@ void the_game(bool &kill, bool random_input, InputHandler *input, delete event.set_sky.type; delete event.set_sky.params; } - else if (event.type == CE_OVERRIDE_DAY_NIGHT_RATIO) - { + else if (event.type == CE_OVERRIDE_DAY_NIGHT_RATIO) { bool enable = event.override_day_night_ratio.do_override; u32 value = event.override_day_night_ratio.ratio_f * 1000; client.getEnv().setDayNightRatioOverride(enable, value); } } } - + //TimeTaker //timer2("//timer2"); /* @@ -2594,16 +2686,14 @@ void the_game(bool &kill, bool random_input, InputHandler *input, ItemStack playeritem; { InventoryList *mlist = local_inventory.getList("main"); - if(mlist != NULL) - { + if((mlist != NULL) && (client.getPlayerItem() < mlist->getSize())) playeritem = mlist->getItem(client.getPlayerItem()); - } } const ItemDefinition &playeritem_def = playeritem.getDefinition(itemdef); ToolCapabilities playeritem_toolcap = playeritem.getToolCapabilities(itemdef); - + /* Update camera */ @@ -2638,7 +2728,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, v3s16 camera_offset = camera.getOffset(); bool camera_offset_changed = (camera_offset != old_camera_offset); - + if(!disable_camera_update){ client.getEnv().getClientMap().updateCamera(camera_position, camera_direction, camera_fov, camera_offset); @@ -2649,7 +2739,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, clouds->updateCameraOffset(camera_offset); } } - + // Update sound listener sound->updateListener(camera.getCameraNode()->getPosition()+intToFloat(camera_offset, BS), v3f(0,0,0), // velocity @@ -2662,7 +2752,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, */ { soundmaker.step(dtime); - + ClientMap &map = client.getEnv().getClientMap(); MapNode n = map.getNodeNoEx(player->getStandingNodePos()); soundmaker.m_player_step_sound = nodedef->get(n).sound_footstep; @@ -2671,9 +2761,9 @@ void the_game(bool &kill, bool random_input, InputHandler *input, /* Calculate what block is the crosshair pointing to */ - + //u32 t1 = device->getTimer()->getRealTime(); - + f32 d = playeritem_def.range; // max. distance f32 d_hand = itemdef->get("").range; if(d < 0 && d_hand >= 0) @@ -2683,10 +2773,19 @@ void the_game(bool &kill, bool random_input, InputHandler *input, core::line3d shootline(camera_position, camera_position + camera_direction * BS * (d+1)); + // prevent player pointing anything in front-view if (camera.getCameraMode() == CAMERA_MODE_THIRD_FRONT) shootline = core::line3d(0,0,0,0,0,0); +#ifdef HAVE_TOUCHSCREENGUI + if ((g_settings->getBool("touchtarget")) && (g_touchscreengui)) { + shootline = g_touchscreengui->getShootline(); + shootline.start += intToFloat(camera_offset,BS); + shootline.end += intToFloat(camera_offset,BS); + } +#endif + ClientActiveObject *selected_object = NULL; PointedThing pointed = getPointedThing( @@ -2702,7 +2801,8 @@ void the_game(bool &kill, bool random_input, InputHandler *input, if(pointed != pointed_old) { infostream<<"Pointing at "<getBool("enable_node_highlighting")) + client.setHighlighted(pointed.node_undersurface, show_hud); } /* @@ -2767,7 +2867,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, /* Check information text of node */ - + ClientMap &map = client.getEnv().getClientMap(); NodeMetadata *meta = map.getNodeMetadata(nodepos); if(meta){ @@ -2779,11 +2879,11 @@ void the_game(bool &kill, bool random_input, InputHandler *input, infotext += narrow_to_wide(nodedef->get(n).name); } } - + /* Handle digging */ - + if(nodig_delay_timer <= 0.0 && input->getLeftState() && client.checkPrivilege("interact")) { @@ -2795,7 +2895,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, ldown_for_dig = true; } MapNode n = client.getEnv().getClientMap().getNode(nodepos); - + // NOTE: Similar piece of code exists on the server side for // cheat detection. // Get digging parameters @@ -2896,7 +2996,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, float mindelay = 0.15; if(nodig_delay_timer < mindelay) nodig_delay_timer = mindelay; - + // Send event to trigger sound MtEvent *e = new NodeDugEvent(nodepos, wasnode); gamedef->event()->put(e); @@ -2919,34 +3019,15 @@ void the_game(bool &kill, bool random_input, InputHandler *input, { repeat_rightclick_timer = 0; infostream<<"Ground right-clicked"<getString("formspec") == "hack:sign_text_input" - && !random_input - && !input->isKeyDown(getKeySetting("keymap_sneak"))) - { - infostream<<"Launching metadata text input"<getString("text")); - - (new GUITextInputMenu(guienv, guiroot, -1, - &g_menumgr, dest, - wtext))->drop(); - } - // If metadata provides an inventory view, activate it - else if(meta && meta->getString("formspec") != "" && !random_input + if(meta && meta->getString("formspec") != "" && !random_input && !input->isKeyDown(getKeySetting("keymap_sneak"))) { infostream<<"Launching custom inventory view"<getPosition(); v3f dir = (objpos - player_position).normalize(); - + bool disable_send = selected_object->directReportPunch( dir, &playeritem, time_from_last_punch); time_from_last_punch = 0; @@ -3034,7 +3115,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, } pointed_old = pointed; - + if(left_punch || input->getLeftClicked()) { camera.setDigging(0); // left click animation @@ -3045,7 +3126,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, input->resetLeftReleased(); input->resetRightReleased(); - + /* Calculate stuff for drawing */ @@ -3053,7 +3134,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, /* Fog range */ - + if(draw_control.range_all) fog_range = 100000*BS; else { @@ -3080,7 +3161,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, daynight_ratio, (int)(old_brightness*255.5), &sunlight_seen) / 255.0; } - + time_of_day = client.getEnv().getTimeOfDayF(); float maxsm = 0.05; if(fabs(time_of_day - time_of_day_smooth) > maxsm && @@ -3094,11 +3175,11 @@ void the_game(bool &kill, bool random_input, InputHandler *input, else time_of_day_smooth = time_of_day_smooth * (1.0-todsm) + time_of_day * todsm; - + sky->update(time_of_day_smooth, time_brightness, direct_brightness, sunlight_seen,camera.getCameraMode(), player->getYaw(), player->getPitch()); - + video::SColor bgcolor = sky->getBgColor(); video::SColor skycolor = sky->getSkyColor(); @@ -3115,18 +3196,18 @@ void the_game(bool &kill, bool random_input, InputHandler *input, clouds->setVisible(false); } } - + /* Update particles */ allparticles_step(dtime); allparticlespawners_step(dtime, client.getEnv()); - + /* Fog */ - + if(g_settings->getBool("enable_fog") && !force_fog_off) { driver->setFog( @@ -3157,7 +3238,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, */ //TimeTaker guiupdatetimer("Gui updating"); - + if(show_debug) { static float drawtime_avg = 0; @@ -3236,7 +3317,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, { guitext2->setVisible(false); } - + { guitext_info->setText(infotext.c_str()); guitext_info->setVisible(show_hud && g_menumgr.menuCount() == 0); @@ -3262,7 +3343,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, core::rect rect( 10, status_y - guitext_status->getTextHeight(), - screensize.X - 10, + 10 + guitext_status->getTextWidth(), status_y ); guitext_status->setRelativePosition(rect); @@ -3282,52 +3363,17 @@ void the_game(bool &kill, bool random_input, InputHandler *input, guitext_status->enableOverrideColor(true); } } - + /* Get chat messages from client */ - { - // Get new messages from error log buffer - while(!chat_log_error_buf.empty()) - { - chat_backend.addMessage(L"", narrow_to_wide( - chat_log_error_buf.get())); - } - // Get new messages from client - std::wstring message; - while(client.getChatMessage(message)) - { - chat_backend.addUnparsedMessage(message); - } - // Remove old messages - chat_backend.step(dtime); - - // Display all messages in a static text element - u32 recent_chat_count = chat_backend.getRecentBuffer().getLineCount(); - std::wstring recent_chat = chat_backend.getRecentChat(); - guitext_chat->setText(recent_chat.c_str()); - - // Update gui element size and position - s32 chat_y = 5+(text_height+5); - if(show_debug) - chat_y += (text_height+5); - core::rect rect( - 10, - chat_y, - screensize.X - 10, - chat_y + guitext_chat->getTextHeight() - ); - guitext_chat->setRelativePosition(rect); - - // Don't show chat if disabled or empty or profiler is enabled - guitext_chat->setVisible(show_chat && recent_chat_count != 0 - && !show_profiler); - } + updateChat(client, dtime, show_debug, screensize, show_chat, + show_profiler, chat_backend, guitext_chat, font); /* Inventory */ - + if(client.getPlayerItem() != new_playeritem) { client.selectPlayerItem(new_playeritem); @@ -3336,7 +3382,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, { //infostream<<"Updating local inventory"<getSize())) item = mlist->getItem(client.getPlayerItem()); camera.wield(item, client.getPlayerItem()); } @@ -3363,6 +3409,13 @@ void the_game(bool &kill, bool random_input, InputHandler *input, update_draw_list_last_cam_dir = camera_direction; } + /* + make sure menu is on top + */ + if ((!noMenuActive()) && (current_formspec)) { + guiroot->bringToFront(current_formspec); + } + /* Drawing begins */ @@ -3373,17 +3426,10 @@ void the_game(bool &kill, bool random_input, InputHandler *input, beginscenetime = timer.stop(true); } - + draw_scene(driver, smgr, camera, client, player, hud, guienv, hilightboxes, screensize, skycolor, show_hud); - /* - Post effects - */ - { - client.getEnv().getClientMap().renderPostFx(camera.getCameraMode()); - } - /* Profiler graph */ @@ -3401,7 +3447,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, driver->draw2DRectangle(color, core::rect(0,0,screensize.X,screensize.Y), NULL); - + damage_flash -= 100.0*dtime; } @@ -3449,7 +3495,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, if (sky) sky->drop(); clear_particles(); - + /* cleanup menus */ while (g_menumgr.menuCount() > 0) { @@ -3499,7 +3545,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, } - + if(!sound_is_dummy) delete sound;