X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fgame.cpp;h=aa12e6c3f479b41ba07a57120ed7ea3ee99ab37b;hb=f6912f4241a2dd13d987d27a073a3b76faf2cb7d;hp=a700da8cd43b9788457e9af7150769fa4bee191f;hpb=43bf4324d5f639f338f88a599fe862630f85f787;p=dragonfireclient.git diff --git a/src/game.cpp b/src/game.cpp index a700da8cd..aa12e6c3f 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -70,6 +70,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "util/pointedthing.h" #include "drawscene.h" #include "content_cao.h" +#include "fontengine.h" #ifdef HAVE_TOUCHSCREENGUI #include "touchscreengui.h" @@ -360,12 +361,11 @@ PointedThing getPointedThing(Client *client, v3f player_position, for (s16 z = zstart; z <= zend; z++) for (s16 x = xstart; x <= xend; x++) { MapNode n; + bool is_valid_position; - try { - n = map.getNode(v3s16(x, y, z)); - } catch (InvalidPositionException &e) { + n = map.getNodeNoEx(v3s16(x, y, z), &is_valid_position); + if (!is_valid_position) continue; - } if (!isPointableNode(n, client, liquids_pointable)) continue; @@ -438,9 +438,8 @@ PointedThing getPointedThing(Client *client, v3f player_position, /* Profiler display */ -void update_profiler_gui(gui::IGUIStaticText *guitext_profiler, - gui::IGUIFont *font, u32 text_height, u32 show_profiler, - u32 show_profiler_max) +void update_profiler_gui(gui::IGUIStaticText *guitext_profiler, FontEngine *fe, + u32 show_profiler, u32 show_profiler_max) { if (show_profiler == 0) { guitext_profiler->setVisible(false); @@ -452,14 +451,14 @@ void update_profiler_gui(gui::IGUIStaticText *guitext_profiler, guitext_profiler->setText(text.c_str()); guitext_profiler->setVisible(true); - s32 w = font->getDimension(text.c_str()).Width; + s32 w = fe->getTextWidth(text.c_str()); if (w < 400) w = 400; - core::rect rect(6, 4 + (text_height + 5) * 2, 12 + w, - 8 + (text_height + 5) * 2 + - font->getDimension(text.c_str()).Height); + core::rect rect(6, 4 + (fe->getTextHeight() + 5) * 2, 12 + w, + 8 + (fe->getTextHeight() + 5) * 2 + + fe->getTextHeight()); guitext_profiler->setRelativePosition(rect); guitext_profiler->setVisible(true); } @@ -873,22 +872,31 @@ bool nodePlacementPrediction(Client &client, std::string prediction = playeritem_def.node_placement_prediction; INodeDefManager *nodedef = client.ndef(); ClientMap &map = client.getEnv().getClientMap(); + MapNode node; + bool is_valid_position; + + node = map.getNodeNoEx(nodepos, &is_valid_position); + if (!is_valid_position) + return false; - if (prediction != "" && !nodedef->get(map.getNode(nodepos)).rightclickable) { + if (prediction != "" && !nodedef->get(node).rightclickable) { verbosestream << "Node placement prediction for " << playeritem_def.name << " is " << prediction << std::endl; v3s16 p = neighbourpos; // Place inside node itself if buildable_to - try { - MapNode n_under = map.getNode(nodepos); - + MapNode n_under = map.getNodeNoEx(nodepos, &is_valid_position); + if (is_valid_position) + { if (nodedef->get(n_under).buildable_to) p = nodepos; - else if (!nodedef->get(map.getNode(p)).buildable_to) - return false; - } catch (InvalidPositionException &e) {} + else { + node = map.getNodeNoEx(p, &is_valid_position); + if (is_valid_position &&!nodedef->get(node).buildable_to) + return false; + } + } // Find id of predicted node content_t id; @@ -946,7 +954,7 @@ bool nodePlacementPrediction(Client &client, else pp = p + v3s16(0, -1, 0); - if (!nodedef->get(map.getNode(pp)).walkable) + if (!nodedef->get(map.getNodeNoEx(pp)).walkable) return false; } @@ -959,6 +967,7 @@ bool nodePlacementPrediction(Client &client, // Dont place node when player would be inside new node // NOTE: This is to be eventually implemented by a mod as client-side Lua if (!nodedef->get(n).walkable || + g_settings->getBool("enable_build_where_you_stand") || (client.checkPrivilege("noclip") && g_settings->getBool("noclip")) || (nodedef->get(n).walkable && neighbourpos != player->getStandingNodePos() + v3s16(0, 1, 0) && @@ -1127,8 +1136,7 @@ static void show_pause_menu(GUIFormSpecMenu **cur_formspec, /******************************************************************************/ 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) + ChatBackend &chat_backend, gui::IGUIStaticText *guitext_chat) { // Add chat log output for errors to be shown in chat static LogOutputBuffer chat_log_error_buf(LMT_ERROR); @@ -1151,9 +1159,7 @@ static void updateChat(Client &client, f32 dtime, bool show_debug, // 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(); + unsigned int line_height = g_fontengine->getLineHeight(); guitext_chat->setText(recent_chat.c_str()); @@ -1164,7 +1170,7 @@ static void updateChat(Client &client, f32 dtime, bool show_debug, chat_y += line_height; // first pass to calculate height of text to be set - s32 width = std::min(font->getDimension(recent_chat.c_str()).Width + 10, + s32 width = std::min(g_fontengine->getTextWidth(recent_chat) + 10, porting::getWindowSize().X - 20); core::rect rect(10, chat_y, width, chat_y + porting::getWindowSize().Y); guitext_chat->setRelativePosition(rect); @@ -1181,9 +1187,119 @@ static void updateChat(Client &client, f32 dtime, bool show_debug, } +/**************************************************************************** + Fast key cache for main game loop + ****************************************************************************/ + +/* This is faster than using getKeySetting with the tradeoff that functions + * using it must make sure that it's initialised before using it and there is + * no error handling (for example bounds checking). This is really intended for + * use only in the main running loop of the client (the_game()) where the faster + * (up to 10x faster) key lookup is an asset. Other parts of the codebase + * (e.g. formspecs) should continue using getKeySetting(). + */ +struct KeyCache { + + KeyCache() { populate(); } + + enum { + // Player movement + KEYMAP_ID_FORWARD, + KEYMAP_ID_BACKWARD, + KEYMAP_ID_LEFT, + KEYMAP_ID_RIGHT, + KEYMAP_ID_JUMP, + KEYMAP_ID_SPECIAL1, + KEYMAP_ID_SNEAK, + + // Other + KEYMAP_ID_DROP, + KEYMAP_ID_INVENTORY, + KEYMAP_ID_CHAT, + KEYMAP_ID_CMD, + KEYMAP_ID_CONSOLE, + KEYMAP_ID_FREEMOVE, + KEYMAP_ID_FASTMOVE, + KEYMAP_ID_NOCLIP, + KEYMAP_ID_SCREENSHOT, + KEYMAP_ID_TOGGLE_HUD, + KEYMAP_ID_TOGGLE_CHAT, + KEYMAP_ID_TOGGLE_FORCE_FOG_OFF, + KEYMAP_ID_TOGGLE_UPDATE_CAMERA, + KEYMAP_ID_TOGGLE_DEBUG, + KEYMAP_ID_TOGGLE_PROFILER, + KEYMAP_ID_CAMERA_MODE, + KEYMAP_ID_INCREASE_VIEWING_RANGE, + KEYMAP_ID_DECREASE_VIEWING_RANGE, + KEYMAP_ID_RANGESELECT, + + KEYMAP_ID_QUICKTUNE_NEXT, + KEYMAP_ID_QUICKTUNE_PREV, + KEYMAP_ID_QUICKTUNE_INC, + KEYMAP_ID_QUICKTUNE_DEC, + + KEYMAP_ID_DEBUG_STACKS, + + // Fake keycode for array size and internal checks + KEYMAP_INTERNAL_ENUM_COUNT + + + }; + + void populate(); + + KeyPress key[KEYMAP_INTERNAL_ENUM_COUNT]; +}; + +void KeyCache::populate() +{ + key[KEYMAP_ID_FORWARD] = getKeySetting("keymap_forward"); + key[KEYMAP_ID_BACKWARD] = getKeySetting("keymap_backward"); + key[KEYMAP_ID_LEFT] = getKeySetting("keymap_left"); + key[KEYMAP_ID_RIGHT] = getKeySetting("keymap_right"); + key[KEYMAP_ID_JUMP] = getKeySetting("keymap_jump"); + key[KEYMAP_ID_SPECIAL1] = getKeySetting("keymap_special1"); + key[KEYMAP_ID_SNEAK] = getKeySetting("keymap_sneak"); + + key[KEYMAP_ID_DROP] = getKeySetting("keymap_drop"); + key[KEYMAP_ID_INVENTORY] = getKeySetting("keymap_inventory"); + key[KEYMAP_ID_CHAT] = getKeySetting("keymap_chat"); + key[KEYMAP_ID_CMD] = getKeySetting("keymap_cmd"); + key[KEYMAP_ID_CONSOLE] = getKeySetting("keymap_console"); + key[KEYMAP_ID_FREEMOVE] = getKeySetting("keymap_freemove"); + key[KEYMAP_ID_FASTMOVE] = getKeySetting("keymap_fastmove"); + key[KEYMAP_ID_NOCLIP] = getKeySetting("keymap_noclip"); + key[KEYMAP_ID_SCREENSHOT] = getKeySetting("keymap_screenshot"); + key[KEYMAP_ID_TOGGLE_HUD] = getKeySetting("keymap_toggle_hud"); + key[KEYMAP_ID_TOGGLE_CHAT] = getKeySetting("keymap_toggle_chat"); + key[KEYMAP_ID_TOGGLE_FORCE_FOG_OFF] + = getKeySetting("keymap_toggle_force_fog_off"); + key[KEYMAP_ID_TOGGLE_UPDATE_CAMERA] + = getKeySetting("keymap_toggle_update_camera"); + key[KEYMAP_ID_TOGGLE_DEBUG] + = getKeySetting("keymap_toggle_debug"); + key[KEYMAP_ID_TOGGLE_PROFILER] + = getKeySetting("keymap_toggle_profiler"); + key[KEYMAP_ID_CAMERA_MODE] + = getKeySetting("keymap_camera_mode"); + key[KEYMAP_ID_INCREASE_VIEWING_RANGE] + = getKeySetting("keymap_increase_viewing_range_min"); + key[KEYMAP_ID_DECREASE_VIEWING_RANGE] + = getKeySetting("keymap_decrease_viewing_range_min"); + key[KEYMAP_ID_RANGESELECT] + = getKeySetting("keymap_rangeselect"); + + key[KEYMAP_ID_QUICKTUNE_NEXT] = getKeySetting("keymap_quicktune_next"); + key[KEYMAP_ID_QUICKTUNE_PREV] = getKeySetting("keymap_quicktune_prev"); + key[KEYMAP_ID_QUICKTUNE_INC] = getKeySetting("keymap_quicktune_inc"); + key[KEYMAP_ID_QUICKTUNE_DEC] = getKeySetting("keymap_quicktune_dec"); + + key[KEYMAP_ID_DEBUG_STACKS] = getKeySetting("keymap_print_debug_stacks"); +} + /**************************************************************************** - THE GAME + ****************************************************************************/ const float object_hit_delay = 0.2; @@ -1204,14 +1320,15 @@ struct CameraOrientation { f32 camera_pitch; // "up/down" }; -//TODO: Needs a better name because fog_range etc are included -struct InteractParams { +struct GameRunData { u16 dig_index; u16 new_playeritem; PointedThing pointed_old; bool digging; bool ldown_for_dig; bool left_punch; + bool update_wielded_item_trigger; + bool reset_jump_timer; float nodig_delay_timer; float dig_time; float dig_time_complete; @@ -1231,6 +1348,9 @@ struct InteractParams { u32 profiler_current_page; u32 profiler_max_page; // Number of pages + + float time_of_day; + float time_of_day_smooth; }; struct Jitter { @@ -1260,22 +1380,25 @@ struct VolatileRunFlags { }; +/**************************************************************************** + THE GAME + ****************************************************************************/ + /* This is not intended to be a public class. If a public class becomes * desirable then it may be better to create another 'wrapper' class that * hides most of the stuff in this class (nothing in this class is required * by any other file) but exposes the public methods/data only. */ -class MinetestApp +class Game { public: - MinetestApp(); - ~MinetestApp(); + Game(); + ~Game(); bool startup(bool *kill, bool random_input, InputHandler *input, IrrlichtDevice *device, - gui::IGUIFont *font, const std::string &map_dir, const std::string &playername, const std::string &password, @@ -1316,19 +1439,22 @@ class MinetestApp // Main loop - void updateInteractTimers(InteractParams *args, f32 dtime); + void updateInteractTimers(GameRunData *args, f32 dtime); bool checkConnection(); bool handleCallbacks(); void processQueues(); + void updateProfilers(const GameRunData &run_data, const RunStats &stats, + const FpsControl &draw_times, f32 dtime); void addProfilerGraphs(const RunStats &stats, const FpsControl &draw_times, f32 dtime); void updateStats(RunStats *stats, const FpsControl &draw_times, f32 dtime); - void processUserInput(VolatileRunFlags *flags, InteractParams *interact_args, + void processUserInput(VolatileRunFlags *flags, GameRunData *interact_args, f32 dtime); void processKeyboardInput(VolatileRunFlags *flags, float *statustext_time, float *jump_timer, + bool *reset_jump_timer, u32 *profiler_current_page, u32 profiler_max_page); void processItemSelection(u16 *new_playeritem); @@ -1362,26 +1488,26 @@ class MinetestApp float time_from_last_punch); void updateSound(f32 dtime); void processPlayerInteraction(std::vector &highlight_boxes, - InteractParams *interactArgs, f32 dtime, bool show_hud, + GameRunData *runData, f32 dtime, bool show_hud, bool show_debug); - void handlePointingAtNode(InteractParams *interactArgs, + void handlePointingAtNode(GameRunData *runData, const PointedThing &pointed, const ItemDefinition &playeritem_def, const ToolCapabilities &playeritem_toolcap, f32 dtime); - void handlePointingAtObject(InteractParams *interactArgs, + void handlePointingAtObject(GameRunData *runData, const PointedThing &pointed, const ItemStack &playeritem, const v3f &player_position, bool show_debug); - void handleDigging(InteractParams *interactArgs, const PointedThing &pointed, + void handleDigging(GameRunData *runData, const PointedThing &pointed, const v3s16 &nodepos, const ToolCapabilities &playeritem_toolcap, f32 dtime); void updateFrame(std::vector &highlight_boxes, ProfilerGraph *graph, - RunStats *stats, InteractParams *interactArgs, + RunStats *stats, GameRunData *runData, f32 dtime, const VolatileRunFlags &flags, const CameraOrientation &cam); void updateGui(float *statustext_time, const RunStats &stats, f32 dtime, const VolatileRunFlags &flags, const CameraOrientation &cam); void updateProfilerGraphs(ProfilerGraph *graph); // Misc - void limitFps(FpsControl *params, f32 *dtime); + void limitFps(FpsControl *fps_timings, f32 *dtime); void showOverlayMessage(const char *msg, float dtime, int percent, bool draw_clouds = true); @@ -1392,8 +1518,6 @@ class MinetestApp Client *client; Server *server; - gui::IGUIFont *font; - IWritableTextureSource *texture_src; IWritableShaderSource *shader_src; @@ -1428,7 +1552,6 @@ class MinetestApp IrrlichtDevice *device; video::IVideoDriver *driver; scene::ISceneManager *smgr; - u32 text_height; bool *kill; std::wstring *error_message; IGameDef *gamedef; // Convenience (same as *client) @@ -1453,12 +1576,15 @@ class MinetestApp std::wstring infotext; std::wstring statustext; + + KeyCache keycache; + + IntervalLimiter profiler_interval; }; -MinetestApp::MinetestApp() : +Game::Game() : client(NULL), server(NULL), - font(NULL), texture_src(NULL), shader_src(NULL), itemdef_manager(NULL), @@ -1487,7 +1613,7 @@ MinetestApp::MinetestApp() : MinetestApp Public ****************************************************************************/ -MinetestApp::~MinetestApp() +Game::~Game() { delete client; delete soundmaker; @@ -1510,11 +1636,10 @@ MinetestApp::~MinetestApp() extendedResourceCleanup(); } -bool MinetestApp::startup(bool *kill, +bool Game::startup(bool *kill, bool random_input, InputHandler *input, IrrlichtDevice *device, - gui::IGUIFont *font, const std::string &map_dir, const std::string &playername, const std::string &password, @@ -1527,7 +1652,6 @@ bool MinetestApp::startup(bool *kill, { // "cache" this->device = device; - this->font = font; this->kill = kill; this->error_message = error_message; this->random_input = random_input; @@ -1537,7 +1661,6 @@ bool MinetestApp::startup(bool *kill, driver = device->getVideoDriver(); smgr = device->getSceneManager(); - text_height = font->getDimension(L"Random test string").Height; if (!init(map_dir, address, port, gamespec)) return false; @@ -1549,24 +1672,23 @@ bool MinetestApp::startup(bool *kill, } -void MinetestApp::run() +void Game::run() { ProfilerGraph graph; RunStats stats = { 0 }; CameraOrientation cam_view = { 0 }; - InteractParams interactArgs = { 0 }; + GameRunData runData = { 0 }; FpsControl draw_times = { 0 }; VolatileRunFlags flags = { 0 }; f32 dtime; // in seconds - interactArgs.time_from_last_punch = 10.0; - interactArgs.profiler_max_page = 3; + runData.time_from_last_punch = 10.0; + runData.profiler_max_page = 3; + runData.update_wielded_item_trigger = true; flags.show_chat = true; flags.show_hud = true; - - /* FIXME: This should be updated every iteration, or not stored locally - now that key settings can be changed in-game */ + flags.show_debug = g_settings->getBool("show_debug"); flags.invert_mouse = g_settings->getBool("invert_mouse"); /* Clear the profiler */ @@ -1578,9 +1700,11 @@ void MinetestApp::run() shader_src->addGlobalConstantSetter(new GameGlobalShaderConstantSetter( sky, &flags.force_fog_off, - &interactArgs.fog_range, + &runData.fog_range, client)); + std::vector highlight_boxes; + while (device->run() && !(*kill || g_gamecallback->shutdown_requested)) { /* Must be called immediately after a device->run() call because it @@ -1589,7 +1713,7 @@ void MinetestApp::run() limitFps(&draw_times, &dtime); updateStats(&stats, draw_times, dtime); - updateInteractTimers(&interactArgs, dtime); + updateInteractTimers(&runData, dtime); if (!checkConnection()) break; @@ -1598,30 +1722,29 @@ void MinetestApp::run() processQueues(); - std::vector highlight_boxes; - infotext = L""; hud->resizeHotbar(); - addProfilerGraphs(stats, draw_times, dtime); - processUserInput(&flags, &interactArgs, dtime); + + updateProfilers(runData, stats, draw_times, dtime); + processUserInput(&flags, &runData, dtime); // Update camera before player movement to avoid camera lag of one frame updateCameraDirection(&cam_view, &flags); updatePlayerControl(cam_view); step(&dtime); - processClientEvents(&cam_view, &interactArgs.damage_flash); + processClientEvents(&cam_view, &runData.damage_flash); updateCamera(&flags, draw_times.busy_time, dtime, - interactArgs.time_from_last_punch); + runData.time_from_last_punch); updateSound(dtime); - processPlayerInteraction(highlight_boxes, &interactArgs, dtime, + processPlayerInteraction(highlight_boxes, &runData, dtime, flags.show_hud, flags.show_debug); - updateFrame(highlight_boxes, &graph, &stats, &interactArgs, dtime, + updateFrame(highlight_boxes, &graph, &stats, &runData, dtime, flags, cam_view); updateProfilerGraphs(&graph); } } -void MinetestApp::shutdown() +void Game::shutdown() { showOverlayMessage("Shutting down...", 0, 0, false); @@ -1668,7 +1791,7 @@ void MinetestApp::shutdown() Startup ****************************************************************************/ -bool MinetestApp::init( +bool Game::init( const std::string &map_dir, std::string *address, u16 port, @@ -1701,7 +1824,7 @@ bool MinetestApp::init( return true; } -bool MinetestApp::initSound() +bool Game::initSound() { #if USE_SOUND if (g_settings->getBool("enable_sound")) { @@ -1728,7 +1851,7 @@ bool MinetestApp::initSound() return true; } -bool MinetestApp::createSingleplayerServer(const std::string map_dir, +bool Game::createSingleplayerServer(const std::string map_dir, const SubgameSpec &gamespec, u16 port, std::string *address) { showOverlayMessage("Creating server...", 0, 25); @@ -1765,7 +1888,7 @@ bool MinetestApp::createSingleplayerServer(const std::string map_dir, return true; } -bool MinetestApp::createClient(const std::string &playername, +bool Game::createClient(const std::string &playername, const std::string &password, std::string *address, u16 port, std::wstring *error_message) { @@ -1800,7 +1923,7 @@ bool MinetestApp::createClient(const std::string &playername, } // Update cached textures, meshes and materials - client->afterContentReceived(device, font); + client->afterContentReceived(device, g_fontengine->getFont()); /* Camera */ @@ -1858,8 +1981,7 @@ bool MinetestApp::createClient(const std::string &playername, player->hurt_tilt_timer = 0; player->hurt_tilt_strength = 0; - hud = new Hud(driver, smgr, guienv, font, text_height, gamedef, - player, local_inventory); + hud = new Hud(driver, smgr, guienv, gamedef, player, local_inventory); if (!hud) { *error_message = L"Memory error: could not create HUD"; @@ -1870,7 +1992,7 @@ bool MinetestApp::createClient(const std::string &playername, return true; } -bool MinetestApp::initGui(std::wstring *error_message) +bool Game::initGui(std::wstring *error_message) { // First line of debug text guitext = guienv->addStaticText( @@ -1888,7 +2010,7 @@ bool MinetestApp::initGui(std::wstring *error_message) // Object infos are shown in this guitext_info = guienv->addStaticText( L"", - core::rect(0, 0, 400, text_height * 5 + 5) + v2s32(100, 200), + core::rect(0, 0, 400, g_fontengine->getTextHeight() * 5 + 5) + v2s32(100, 200), false, true, guiroot); // Status text (displays info when showing and hiding GUI stuff, etc.) @@ -1928,14 +2050,14 @@ bool MinetestApp::initGui(std::wstring *error_message) #ifdef HAVE_TOUCHSCREENGUI if (g_touchscreengui) - g_touchscreengui->init(tsrc, porting::getDisplayDensity()); + g_touchscreengui->init(texture_src, porting::getDisplayDensity()); #endif return true; } -bool MinetestApp::connectToServer(const std::string &playername, +bool Game::connectToServer(const std::string &playername, const std::string &password, std::string *address, u16 port, bool *connect_ok, bool *aborted) { @@ -1970,9 +2092,11 @@ bool MinetestApp::connectToServer(const std::string &playername, return false; } - client = new Client(device, playername.c_str(), password, *draw_control, - texture_src, shader_src, itemdef_manager, nodedef_manager, sound, - eventmgr, connect_address.isIPv6()); + client = new Client(device, + playername.c_str(), password, simple_singleplayer_mode, + *draw_control, texture_src, shader_src, + itemdef_manager, nodedef_manager, sound, eventmgr, + connect_address.isIPv6()); if (!client) return false; @@ -2039,7 +2163,7 @@ bool MinetestApp::connectToServer(const std::string &playername, return true; } -bool MinetestApp::getServerContent(bool *aborted) +bool Game::getServerContent(bool *aborted) { input->clear(); @@ -2088,12 +2212,12 @@ bool MinetestApp::getServerContent(bool *aborted) if (!client->itemdefReceived()) { wchar_t *text = wgettext("Item definitions..."); progress = 0; - draw_load_screen(text, device, guienv, font, dtime, progress); + draw_load_screen(text, device, guienv, dtime, progress); delete[] text; } else if (!client->nodedefReceived()) { wchar_t *text = wgettext("Node definitions..."); progress = 25; - draw_load_screen(text, device, guienv, font, dtime, progress); + draw_load_screen(text, device, guienv, dtime, progress); delete[] text; } else { std::stringstream message; @@ -2115,7 +2239,7 @@ bool MinetestApp::getServerContent(bool *aborted) progress = 50 + client->mediaReceiveProgress() * 50 + 0.5; draw_load_screen(narrow_to_wide(message.str().c_str()), device, - guienv, font, dtime, progress); + guienv, dtime, progress); } } @@ -2128,7 +2252,7 @@ bool MinetestApp::getServerContent(bool *aborted) Run ****************************************************************************/ -inline void MinetestApp::updateInteractTimers(InteractParams *args, f32 dtime) +inline void Game::updateInteractTimers(GameRunData *args, f32 dtime) { if (args->nodig_delay_timer >= 0) args->nodig_delay_timer -= dtime; @@ -2140,9 +2264,9 @@ inline void MinetestApp::updateInteractTimers(InteractParams *args, f32 dtime) } -/* returns false if app should exit, otherwise true +/* returns false if game should exit, otherwise true */ -inline bool MinetestApp::checkConnection() +inline bool Game::checkConnection() { if (client->accessDenied()) { *error_message = L"Access denied. Reason: " @@ -2155,9 +2279,9 @@ inline bool MinetestApp::checkConnection() } -/* returns false if app should exit, otherwise true +/* returns false if game should exit, otherwise true */ -inline bool MinetestApp::handleCallbacks() +inline bool Game::handleCallbacks() { if (g_gamecallback->disconnect_requested) { g_gamecallback->disconnect_requested = false; @@ -2182,11 +2306,16 @@ inline bool MinetestApp::handleCallbacks() g_gamecallback->keyconfig_requested = false; } + if (g_gamecallback->keyconfig_changed) { + keycache.populate(); // update the cache with new settings + g_gamecallback->keyconfig_changed = false; + } + return true; } -void MinetestApp::processQueues() +void Game::processQueues() { texture_src->processQueue(); itemdef_manager->processQueue(gamedef); @@ -2194,7 +2323,35 @@ void MinetestApp::processQueues() } -void MinetestApp::addProfilerGraphs(const RunStats &stats, +void Game::updateProfilers(const GameRunData &run_data, const RunStats &stats, + const FpsControl &draw_times, f32 dtime) +{ + float profiler_print_interval = + g_settings->getFloat("profiler_print_interval"); + bool print_to_log = true; + + if (profiler_print_interval == 0) { + print_to_log = false; + profiler_print_interval = 5; + } + + if (profiler_interval.step(dtime, profiler_print_interval)) { + if (print_to_log) { + infostream << "Profiler:" << std::endl; + g_profiler->print(infostream); + } + + update_profiler_gui(guitext_profiler, g_fontengine, + run_data.profiler_current_page, run_data.profiler_max_page); + + g_profiler->clear(); + } + + addProfilerGraphs(stats, draw_times, dtime); +} + + +void Game::addProfilerGraphs(const RunStats &stats, const FpsControl &draw_times, f32 dtime) { g_profiler->graphAdd("mainloop_other", @@ -2209,7 +2366,7 @@ void MinetestApp::addProfilerGraphs(const RunStats &stats, } -void MinetestApp::updateStats(RunStats *stats, const FpsControl &draw_times, +void Game::updateStats(RunStats *stats, const FpsControl &draw_times, f32 dtime) { @@ -2264,8 +2421,8 @@ void MinetestApp::updateStats(RunStats *stats, const FpsControl &draw_times, Input handling ****************************************************************************/ -void MinetestApp::processUserInput(VolatileRunFlags *flags, - InteractParams *interact_args, f32 dtime) +void Game::processUserInput(VolatileRunFlags *flags, + GameRunData *interact_args, f32 dtime) { // Reset input if window not active or some menu is active if (device->isWindowActive() == false @@ -2303,6 +2460,7 @@ void MinetestApp::processUserInput(VolatileRunFlags *flags, flags, &interact_args->statustext_time, &interact_args->jump_timer, + &interact_args->reset_jump_timer, &interact_args->profiler_current_page, interact_args->profiler_max_page); @@ -2310,75 +2468,70 @@ void MinetestApp::processUserInput(VolatileRunFlags *flags, } -void MinetestApp::processKeyboardInput(VolatileRunFlags *flags, +void Game::processKeyboardInput(VolatileRunFlags *flags, float *statustext_time, float *jump_timer, + bool *reset_jump_timer, u32 *profiler_current_page, u32 profiler_max_page) { - if (input->wasKeyDown(getKeySetting("keymap_drop"))) { + + //TimeTaker tt("process kybd input", NULL, PRECISION_NANO); + + if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_DROP])) { dropSelectedItem(); - } else if (input->wasKeyDown(getKeySetting("keymap_inventory"))) { + } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_INVENTORY])) { openInventory(); } else if (input->wasKeyDown(EscapeKey) || input->wasKeyDown(CancelKey)) { show_pause_menu(¤t_formspec, client, gamedef, texture_src, device, simple_singleplayer_mode); - } else if (input->wasKeyDown(getKeySetting("keymap_chat"))) { + } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_CHAT])) { show_chat_menu(¤t_formspec, client, gamedef, texture_src, device, client, ""); - } else if (input->wasKeyDown(getKeySetting("keymap_cmd"))) { + } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_CMD])) { show_chat_menu(¤t_formspec, client, gamedef, texture_src, device, client, "/"); - } else if (input->wasKeyDown(getKeySetting("keymap_console"))) { + } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_CONSOLE])) { openConsole(); - } else if (input->wasKeyDown(getKeySetting("keymap_freemove"))) { + } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_FREEMOVE])) { toggleFreeMove(statustext_time); - } else if (input->wasKeyDown(getKeySetting("keymap_jump"))) { + } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_JUMP])) { toggleFreeMoveAlt(statustext_time, jump_timer); - } else if (input->wasKeyDown(getKeySetting("keymap_fastmove"))) { + *reset_jump_timer = true; + } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_FASTMOVE])) { toggleFast(statustext_time); - } else if (input->wasKeyDown(getKeySetting("keymap_noclip"))) { + } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_NOCLIP])) { toggleNoClip(statustext_time); - } else if (input->wasKeyDown(getKeySetting("keymap_screenshot"))) { + } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_SCREENSHOT])) { client->makeScreenshot(device); - } else if (input->wasKeyDown(getKeySetting("keymap_toggle_hud"))) { + } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_TOGGLE_HUD])) { toggleHud(statustext_time, &flags->show_hud); - } else if (input->wasKeyDown(getKeySetting("keymap_toggle_chat"))) { + } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_TOGGLE_CHAT])) { toggleChat(statustext_time, &flags->show_chat); - } else if (input->wasKeyDown(getKeySetting("keymap_toggle_force_fog_off"))) { + } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_TOGGLE_FORCE_FOG_OFF])) { toggleFog(statustext_time, &flags->force_fog_off); - } else if (input->wasKeyDown(getKeySetting("keymap_toggle_update_camera"))) { + } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_TOGGLE_UPDATE_CAMERA])) { toggleUpdateCamera(statustext_time, &flags->disable_camera_update); - } else if (input->wasKeyDown(getKeySetting("keymap_toggle_debug"))) { + } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_TOGGLE_DEBUG])) { toggleDebug(statustext_time, &flags->show_debug, &flags->show_profiler_graph); - } else if (input->wasKeyDown(getKeySetting("keymap_toggle_profiler"))) { + } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_TOGGLE_PROFILER])) { toggleProfiler(statustext_time, profiler_current_page, profiler_max_page); - } else if (input->wasKeyDown(getKeySetting("keymap_increase_viewing_range_min"))) { + } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_INCREASE_VIEWING_RANGE])) { increaseViewRange(statustext_time); - } else if (input->wasKeyDown(getKeySetting("keymap_decrease_viewing_range_min"))) { + } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_DECREASE_VIEWING_RANGE])) { decreaseViewRange(statustext_time); - } else if (input->wasKeyDown(getKeySetting("keymap_rangeselect"))) { + } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_RANGESELECT])) { toggleFullViewRange(statustext_time); - } - - // Handle QuicktuneShortcutter - if (input->wasKeyDown(getKeySetting("keymap_quicktune_next"))) + } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_QUICKTUNE_NEXT])) quicktune->next(); - else if (input->wasKeyDown(getKeySetting("keymap_quicktune_prev"))) + else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_QUICKTUNE_PREV])) quicktune->prev(); - else if (input->wasKeyDown(getKeySetting("keymap_quicktune_inc"))) + else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_QUICKTUNE_INC])) quicktune->inc(); - else if (input->wasKeyDown(getKeySetting("keymap_quicktune_dec"))) + else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_QUICKTUNE_DEC])) quicktune->dec(); - - std::string msg = quicktune->getMessage(); - if (msg != "") { - statustext = narrow_to_wide(msg); - *statustext_time = 0; - } - - // Print debug stacks - if (input->wasKeyDown(getKeySetting("keymap_print_debug_stacks"))) { + else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_DEBUG_STACKS])) { + // Print debug stacks dstream << "-----------------------------------------" << std::endl; dstream << DTIME << "Printing debug stacks:" << std::endl; @@ -2386,10 +2539,23 @@ void MinetestApp::processKeyboardInput(VolatileRunFlags *flags, << std::endl; debug_stacks_print(); } + + if (!input->isKeyDown(getKeySetting("keymap_jump")) && *reset_jump_timer) { + *reset_jump_timer = false; + *jump_timer = 0.0; + } + + //tt.stop(); + + if (quicktune->hasMessage()) { + std::string msg = quicktune->getMessage(); + statustext = narrow_to_wide(msg); + *statustext_time = 0; + } } -void MinetestApp::processItemSelection(u16 *new_playeritem) +void Game::processItemSelection(u16 *new_playeritem) { LocalPlayer *player = client->getEnv().getLocalPlayer(); @@ -2402,7 +2568,7 @@ void MinetestApp::processItemSelection(u16 *new_playeritem) player->hud_hotbar_itemcount - 1); if (wheel < 0) - *new_playeritem = *new_playeritem < max_item ? *new_playeritem + 1 : max_item; + *new_playeritem = *new_playeritem < max_item ? *new_playeritem + 1 : 0; else if (wheel > 0) *new_playeritem = *new_playeritem > 0 ? *new_playeritem - 1 : max_item; // else wheel == 0 @@ -2428,7 +2594,7 @@ void MinetestApp::processItemSelection(u16 *new_playeritem) } -void MinetestApp::dropSelectedItem() +void Game::dropSelectedItem() { IDropAction *a = new IDropAction(); a->count = 0; @@ -2439,7 +2605,7 @@ void MinetestApp::dropSelectedItem() } -void MinetestApp::openInventory() +void Game::openInventory() { infostream << "the_game: " << "Launching inventory" << std::endl; @@ -2455,7 +2621,7 @@ void MinetestApp::openInventory() } -void MinetestApp::openConsole() +void Game::openConsole() { if (!gui_chat_console->isOpenInhibited()) { // Open up to over half of the screen @@ -2465,7 +2631,7 @@ void MinetestApp::openConsole() } -void MinetestApp::toggleFreeMove(float *statustext_time) +void Game::toggleFreeMove(float *statustext_time) { static const wchar_t *msg[] = { L"free_move disabled", L"free_move enabled" }; @@ -2479,16 +2645,14 @@ void MinetestApp::toggleFreeMove(float *statustext_time) } -void MinetestApp::toggleFreeMoveAlt(float *statustext_time, float *jump_timer) +void Game::toggleFreeMoveAlt(float *statustext_time, float *jump_timer) { - if (g_settings->getBool("doubletap_jump") && *jump_timer < 0.2f) { + if (g_settings->getBool("doubletap_jump") && *jump_timer < 0.2f) toggleFreeMove(statustext_time); - *jump_timer = 0; - } } -void MinetestApp::toggleFast(float *statustext_time) +void Game::toggleFast(float *statustext_time) { static const wchar_t *msg[] = { L"fast_move disabled", L"fast_move enabled" }; bool fast_move = !g_settings->getBool("fast_move"); @@ -2502,7 +2666,7 @@ void MinetestApp::toggleFast(float *statustext_time) } -void MinetestApp::toggleNoClip(float *statustext_time) +void Game::toggleNoClip(float *statustext_time) { static const wchar_t *msg[] = { L"noclip disabled", L"noclip enabled" }; bool noclip = !g_settings->getBool("noclip"); @@ -2516,7 +2680,7 @@ void MinetestApp::toggleNoClip(float *statustext_time) } -void MinetestApp::toggleChat(float *statustext_time, bool *flag) +void Game::toggleChat(float *statustext_time, bool *flag) { static const wchar_t *msg[] = { L"Chat hidden", L"Chat shown" }; @@ -2526,18 +2690,19 @@ void MinetestApp::toggleChat(float *statustext_time, bool *flag) } -void MinetestApp::toggleHud(float *statustext_time, bool *flag) +void Game::toggleHud(float *statustext_time, bool *flag) { static const wchar_t *msg[] = { L"HUD hidden", L"HUD shown" }; *flag = !*flag; *statustext_time = 0; statustext = msg[*flag]; - client->setHighlighted(client->getHighlighted(), *flag); + if (g_settings->getBool("enable_node_highlighting")) + client->setHighlighted(client->getHighlighted(), *flag); } -void MinetestApp::toggleFog(float *statustext_time, bool *flag) +void Game::toggleFog(float *statustext_time, bool *flag) { static const wchar_t *msg[] = { L"Fog enabled", L"Fog disabled" }; @@ -2547,7 +2712,7 @@ void MinetestApp::toggleFog(float *statustext_time, bool *flag) } -void MinetestApp::toggleDebug(float *statustext_time, bool *show_debug, +void Game::toggleDebug(float *statustext_time, bool *show_debug, bool *show_profiler_graph) { // Initial / 3x toggle: Chat only @@ -2569,7 +2734,7 @@ void MinetestApp::toggleDebug(float *statustext_time, bool *show_debug, } -void MinetestApp::toggleUpdateCamera(float *statustext_time, bool *flag) +void Game::toggleUpdateCamera(float *statustext_time, bool *flag) { static const wchar_t *msg[] = { L"Camera update enabled", @@ -2582,14 +2747,14 @@ void MinetestApp::toggleUpdateCamera(float *statustext_time, bool *flag) } -void MinetestApp::toggleProfiler(float *statustext_time, u32 *profiler_current_page, +void Game::toggleProfiler(float *statustext_time, u32 *profiler_current_page, u32 profiler_max_page) { *profiler_current_page = (*profiler_current_page + 1) % (profiler_max_page + 1); // FIXME: This updates the profiler with incomplete values - update_profiler_gui(guitext_profiler, font, text_height, - *profiler_current_page, profiler_max_page); + update_profiler_gui(guitext_profiler, g_fontengine, *profiler_current_page, + profiler_max_page); if (*profiler_current_page != 0) { std::wstringstream sstr; @@ -2603,7 +2768,7 @@ void MinetestApp::toggleProfiler(float *statustext_time, u32 *profiler_current_p } -void MinetestApp::increaseViewRange(float *statustext_time) +void Game::increaseViewRange(float *statustext_time) { s16 range = g_settings->getS16("viewing_range_nodes_min"); s16 range_new = range + 10; @@ -2614,7 +2779,7 @@ void MinetestApp::increaseViewRange(float *statustext_time) } -void MinetestApp::decreaseViewRange(float *statustext_time) +void Game::decreaseViewRange(float *statustext_time) { s16 range = g_settings->getS16("viewing_range_nodes_min"); s16 range_new = range - 10; @@ -2629,7 +2794,7 @@ void MinetestApp::decreaseViewRange(float *statustext_time) } -void MinetestApp::toggleFullViewRange(float *statustext_time) +void Game::toggleFullViewRange(float *statustext_time) { static const wchar_t *msg[] = { L"Disabled full viewing range", @@ -2643,7 +2808,7 @@ void MinetestApp::toggleFullViewRange(float *statustext_time) } -void MinetestApp::updateCameraDirection(CameraOrientation *cam, +void Game::updateCameraDirection(CameraOrientation *cam, VolatileRunFlags *flags) { // float turn_amount = 0; // Deprecated? @@ -2679,8 +2844,8 @@ void MinetestApp::updateCameraDirection(CameraOrientation *cam, #ifdef HAVE_TOUCHSCREENGUI if (g_touchscreengui) { - camera_yaw = g_touchscreengui->getYaw(); - camera_pitch = g_touchscreengui->getPitch(); + cam->camera_yaw = g_touchscreengui->getYaw(); + cam->camera_pitch = g_touchscreengui->getPitch(); } else { #endif s32 dx = input->getMousePos().X - (driver->getScreenSize().Width / 2); @@ -2718,16 +2883,18 @@ void MinetestApp::updateCameraDirection(CameraOrientation *cam, } -void MinetestApp::updatePlayerControl(const CameraOrientation &cam) +void Game::updatePlayerControl(const CameraOrientation &cam) { + //TimeTaker tt("update player control", NULL, PRECISION_NANO); + PlayerControl control( - input->isKeyDown(getKeySetting("keymap_forward")), - input->isKeyDown(getKeySetting("keymap_backward")), - input->isKeyDown(getKeySetting("keymap_left")), - input->isKeyDown(getKeySetting("keymap_right")), - input->isKeyDown(getKeySetting("keymap_jump")), - input->isKeyDown(getKeySetting("keymap_special1")), - input->isKeyDown(getKeySetting("keymap_sneak")), + input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_FORWARD]), + input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_BACKWARD]), + input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_LEFT]), + input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_RIGHT]), + input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_JUMP]), + input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_SPECIAL1]), + input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_SNEAK]), input->getLeftState(), input->getRightState(), cam.camera_pitch, @@ -2736,21 +2903,22 @@ void MinetestApp::updatePlayerControl(const CameraOrientation &cam) client->setPlayerControl(control); LocalPlayer *player = client->getEnv().getLocalPlayer(); player->keyPressed = - ( (u32)(input->isKeyDown(getKeySetting("keymap_forward")) & 0x1) << 0) | - ( (u32)(input->isKeyDown(getKeySetting("keymap_backward")) & 0x1) << 1) | - ( (u32)(input->isKeyDown(getKeySetting("keymap_left")) & 0x1) << 2) | - ( (u32)(input->isKeyDown(getKeySetting("keymap_right")) & 0x1) << 3) | - ( (u32)(input->isKeyDown(getKeySetting("keymap_jump")) & 0x1) << 4) | - ( (u32)(input->isKeyDown(getKeySetting("keymap_special1")) & 0x1) << 5) | - ( (u32)(input->isKeyDown(getKeySetting("keymap_sneak")) & 0x1) << 6) | - ( (u32)(input->getLeftState() & 0x1) << 7) | - ( (u32)(input->getRightState() & 0x1) << 8 + ( (u32)(input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_FORWARD]) & 0x1) << 0) | + ( (u32)(input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_BACKWARD]) & 0x1) << 1) | + ( (u32)(input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_LEFT]) & 0x1) << 2) | + ( (u32)(input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_RIGHT]) & 0x1) << 3) | + ( (u32)(input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_JUMP]) & 0x1) << 4) | + ( (u32)(input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_SPECIAL1]) & 0x1) << 5) | + ( (u32)(input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_SNEAK]) & 0x1) << 6) | + ( (u32)(input->getLeftState() & 0x1) << 7) | + ( (u32)(input->getRightState() & 0x1) << 8 ); + //tt.stop(); } -inline void MinetestApp::step(f32 *dtime) +inline void Game::step(f32 *dtime) { bool can_be_and_is_paused = (simple_singleplayer_mode && g_menumgr.pausesGame()); @@ -2769,7 +2937,7 @@ inline void MinetestApp::step(f32 *dtime) } -void MinetestApp::processClientEvents(CameraOrientation *cam, float *damage_flash) +void Game::processClientEvents(CameraOrientation *cam, float *damage_flash) { ClientEvent event = client->getClientEvent(); @@ -3008,7 +3176,7 @@ void MinetestApp::processClientEvents(CameraOrientation *cam, float *damage_flas } -void MinetestApp::updateCamera(VolatileRunFlags *flags, u32 busy_time, +void Game::updateCamera(VolatileRunFlags *flags, u32 busy_time, f32 dtime, float time_from_last_punch) { LocalPlayer *player = client->getEnv().getLocalPlayer(); @@ -3032,7 +3200,7 @@ void MinetestApp::updateCamera(VolatileRunFlags *flags, u32 busy_time, v3s16 old_camera_offset = camera->getOffset(); - if (input->wasKeyDown(getKeySetting("keymap_camera_mode"))) { + if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_CAMERA_MODE])) { camera->toggleCameraMode(); GenericCAO *playercao = player->getCAO(); @@ -3071,7 +3239,7 @@ void MinetestApp::updateCamera(VolatileRunFlags *flags, u32 busy_time, } -void MinetestApp::updateSound(f32 dtime) +void Game::updateSound(f32 dtime) { // Update sound listener v3s16 camera_offset = camera->getOffset(); @@ -3093,8 +3261,8 @@ void MinetestApp::updateSound(f32 dtime) } -void MinetestApp::processPlayerInteraction(std::vector &highlight_boxes, - InteractParams *interactArgs, f32 dtime, bool show_hud, bool show_debug) +void Game::processPlayerInteraction(std::vector &highlight_boxes, + GameRunData *runData, f32 dtime, bool show_hud, bool show_debug) { LocalPlayer *player = client->getEnv().getLocalPlayer(); @@ -3155,13 +3323,13 @@ void MinetestApp::processPlayerInteraction(std::vector &highlight_boxes, client, player_position, camera_direction, camera_position, shootline, d, playeritem_def.liquids_pointable, - !interactArgs->ldown_for_dig, + !runData->ldown_for_dig, camera_offset, // output highlight_boxes, - interactArgs->selected_object); + runData->selected_object); - if (pointed != interactArgs->pointed_old) { + if (pointed != runData->pointed_old) { infostream << "Pointing at " << pointed.dump() << std::endl; if (g_settings->getBool("enable_node_highlighting")) { @@ -3178,44 +3346,44 @@ void MinetestApp::processPlayerInteraction(std::vector &highlight_boxes, - releasing left mouse button - pointing away from node */ - if (interactArgs->digging) { + if (runData->digging) { if (input->getLeftReleased()) { infostream << "Left button released" << " (stopped digging)" << std::endl; - interactArgs->digging = false; - } else if (pointed != interactArgs->pointed_old) { + runData->digging = false; + } else if (pointed != runData->pointed_old) { if (pointed.type == POINTEDTHING_NODE - && interactArgs->pointed_old.type == POINTEDTHING_NODE + && runData->pointed_old.type == POINTEDTHING_NODE && pointed.node_undersurface - == interactArgs->pointed_old.node_undersurface) { + == runData->pointed_old.node_undersurface) { // Still pointing to the same node, but a different face. // Don't reset. } else { infostream << "Pointing away from node" << " (stopped digging)" << std::endl; - interactArgs->digging = false; + runData->digging = false; } } - if (!interactArgs->digging) { - client->interact(1, interactArgs->pointed_old); + if (!runData->digging) { + client->interact(1, runData->pointed_old); client->setCrack(-1, v3s16(0, 0, 0)); - interactArgs->dig_time = 0.0; + runData->dig_time = 0.0; } } - if (!interactArgs->digging && interactArgs->ldown_for_dig && !input->getLeftState()) { - interactArgs->ldown_for_dig = false; + if (!runData->digging && runData->ldown_for_dig && !input->getLeftState()) { + runData->ldown_for_dig = false; } - interactArgs->left_punch = false; + runData->left_punch = false; soundmaker->m_player_leftpunch_sound.name = ""; if (input->getRightState()) - interactArgs->repeat_rightclick_timer += dtime; + runData->repeat_rightclick_timer += dtime; else - interactArgs->repeat_rightclick_timer = 0; + runData->repeat_rightclick_timer = 0; if (playeritem_def.usable && input->getLeftState()) { if (input->getLeftClicked()) @@ -3223,19 +3391,19 @@ void MinetestApp::processPlayerInteraction(std::vector &highlight_boxes, } else if (pointed.type == POINTEDTHING_NODE) { ToolCapabilities playeritem_toolcap = playeritem.getToolCapabilities(itemdef_manager); - handlePointingAtNode(interactArgs, pointed, playeritem_def, + handlePointingAtNode(runData, pointed, playeritem_def, playeritem_toolcap, dtime); } else if (pointed.type == POINTEDTHING_OBJECT) { - handlePointingAtObject(interactArgs, pointed, playeritem, + handlePointingAtObject(runData, pointed, playeritem, player_position, show_debug); } else if (input->getLeftState()) { // When button is held down in air, show continuous animation - interactArgs->left_punch = true; + runData->left_punch = true; } - interactArgs->pointed_old = pointed; + runData->pointed_old = pointed; - if (interactArgs->left_punch || input->getLeftClicked()) + if (runData->left_punch || input->getLeftClicked()) camera->setDigging(0); // left click animation input->resetLeftClicked(); @@ -3246,7 +3414,7 @@ void MinetestApp::processPlayerInteraction(std::vector &highlight_boxes, } -void MinetestApp::handlePointingAtNode(InteractParams *interactArgs, +void Game::handlePointingAtNode(GameRunData *runData, const PointedThing &pointed, const ItemDefinition &playeritem_def, const ToolCapabilities &playeritem_toolcap, f32 dtime) { @@ -3263,7 +3431,7 @@ void MinetestApp::handlePointingAtNode(InteractParams *interactArgs, if (meta) { infotext = narrow_to_wide(meta->getString("infotext")); } else { - MapNode n = map.getNode(nodepos); + MapNode n = map.getNodeNoEx(nodepos); if (nodedef_manager->get(n).tiledef[0].name == "unknown_node.png") { infotext = L"Unknown node: "; @@ -3271,16 +3439,16 @@ void MinetestApp::handlePointingAtNode(InteractParams *interactArgs, } } - if (interactArgs->nodig_delay_timer <= 0.0 && input->getLeftState() + if (runData->nodig_delay_timer <= 0.0 && input->getLeftState() && client->checkPrivilege("interact")) { - handleDigging(interactArgs, pointed, nodepos, playeritem_toolcap, dtime); + handleDigging(runData, pointed, nodepos, playeritem_toolcap, dtime); } if ((input->getRightClicked() || - interactArgs->repeat_rightclick_timer >= + runData->repeat_rightclick_timer >= g_settings->getFloat("repeat_rightclick_time")) && client->checkPrivilege("interact")) { - interactArgs->repeat_rightclick_timer = 0; + runData->repeat_rightclick_timer = 0; infostream << "Ground right-clicked" << std::endl; if (meta && meta->getString("formspec") != "" && !random_input @@ -3321,33 +3489,33 @@ void MinetestApp::handlePointingAtNode(InteractParams *interactArgs, } if (playeritem_def.node_placement_prediction == "" || - nodedef_manager->get(map.getNode(nodepos)).rightclickable) + nodedef_manager->get(map.getNodeNoEx(nodepos)).rightclickable) client->interact(3, pointed); // Report to server } } } -void MinetestApp::handlePointingAtObject(InteractParams *interactArgs, +void Game::handlePointingAtObject(GameRunData *runData, const PointedThing &pointed, const ItemStack &playeritem, const v3f &player_position, bool show_debug) { - infotext = narrow_to_wide(interactArgs->selected_object->infoText()); + infotext = narrow_to_wide(runData->selected_object->infoText()); if (infotext == L"" && show_debug) { - infotext = narrow_to_wide(interactArgs->selected_object->debugInfoText()); + infotext = narrow_to_wide(runData->selected_object->debugInfoText()); } if (input->getLeftState()) { bool do_punch = false; bool do_punch_damage = false; - if (interactArgs->object_hit_delay_timer <= 0.0) { + if (runData->object_hit_delay_timer <= 0.0) { do_punch = true; do_punch_damage = true; - interactArgs->object_hit_delay_timer = object_hit_delay; + runData->object_hit_delay_timer = object_hit_delay; } if (input->getLeftClicked()) @@ -3355,17 +3523,17 @@ void MinetestApp::handlePointingAtObject(InteractParams *interactArgs, if (do_punch) { infostream << "Left-clicked object" << std::endl; - interactArgs->left_punch = true; + runData->left_punch = true; } if (do_punch_damage) { // Report direct punch - v3f objpos = interactArgs->selected_object->getPosition(); + v3f objpos = runData->selected_object->getPosition(); v3f dir = (objpos - player_position).normalize(); - bool disable_send = interactArgs->selected_object->directReportPunch( - dir, &playeritem, interactArgs->time_from_last_punch); - interactArgs->time_from_last_punch = 0; + bool disable_send = runData->selected_object->directReportPunch( + dir, &playeritem, runData->time_from_last_punch); + runData->time_from_last_punch = 0; if (!disable_send) client->interact(0, pointed); @@ -3377,20 +3545,20 @@ void MinetestApp::handlePointingAtObject(InteractParams *interactArgs, } -void MinetestApp::handleDigging(InteractParams *interactArgs, +void Game::handleDigging(GameRunData *runData, const PointedThing &pointed, const v3s16 &nodepos, const ToolCapabilities &playeritem_toolcap, f32 dtime) { - if (!interactArgs->digging) { + if (!runData->digging) { infostream << "Started digging" << std::endl; client->interact(0, pointed); - interactArgs->digging = true; - interactArgs->ldown_for_dig = true; + runData->digging = true; + runData->ldown_for_dig = true; } LocalPlayer *player = client->getEnv().getLocalPlayer(); ClientMap &map = client->getEnv().getClientMap(); - MapNode n = client->getEnv().getClientMap().getNode(nodepos); + MapNode n = client->getEnv().getClientMap().getNodeNoEx(nodepos); // NOTE: Similar piece of code exists on the server side for // cheat detection. @@ -3409,9 +3577,9 @@ void MinetestApp::handleDigging(InteractParams *interactArgs, if (params.diggable == false) { // I guess nobody will wait for this long - interactArgs->dig_time_complete = 10000000.0; + runData->dig_time_complete = 10000000.0; } else { - interactArgs->dig_time_complete = params.time; + runData->dig_time_complete = params.time; if (g_settings->getBool("enable_particles")) { const ContentFeatures &features = @@ -3421,13 +3589,13 @@ void MinetestApp::handleDigging(InteractParams *interactArgs, } } - if (interactArgs->dig_time_complete >= 0.001) { - interactArgs->dig_index = (float)crack_animation_length - * interactArgs->dig_time - / interactArgs->dig_time_complete; + if (runData->dig_time_complete >= 0.001) { + runData->dig_index = (float)crack_animation_length + * runData->dig_time + / runData->dig_time_complete; } else { // This is for torches - interactArgs->dig_index = crack_animation_length; + runData->dig_index = crack_animation_length; } SimpleSoundSpec sound_dig = nodedef_manager->get(n).sound_dig; @@ -3446,17 +3614,19 @@ void MinetestApp::handleDigging(InteractParams *interactArgs, } // Don't show cracks if not diggable - if (interactArgs->dig_time_complete >= 100000.0) { - } else if (interactArgs->dig_index < crack_animation_length) { + if (runData->dig_time_complete >= 100000.0) { + } else if (runData->dig_index < crack_animation_length) { //TimeTaker timer("client.setTempMod"); //infostream<<"dig_index="<setCrack(interactArgs->dig_index, nodepos); + client->setCrack(runData->dig_index, nodepos); } else { infostream << "Digging completed" << std::endl; client->interact(2, pointed); client->setCrack(-1, v3s16(0, 0, 0)); - MapNode wasnode = map.getNode(nodepos); - client->removeNode(nodepos); + bool is_valid_position; + MapNode wasnode = map.getNodeNoEx(nodepos, &is_valid_position); + if (is_valid_position) + client->removeNode(nodepos); if (g_settings->getBool("enable_particles")) { const ContentFeatures &features = @@ -3466,33 +3636,33 @@ void MinetestApp::handleDigging(InteractParams *interactArgs, nodepos, features.tiles); } - interactArgs->dig_time = 0; - interactArgs->digging = false; + runData->dig_time = 0; + runData->digging = false; - interactArgs->nodig_delay_timer = - interactArgs->dig_time_complete / (float)crack_animation_length; + runData->nodig_delay_timer = + runData->dig_time_complete / (float)crack_animation_length; // We don't want a corresponding delay to // very time consuming nodes - if (interactArgs->nodig_delay_timer > 0.3) - interactArgs->nodig_delay_timer = 0.3; + if (runData->nodig_delay_timer > 0.3) + runData->nodig_delay_timer = 0.3; // We want a slight delay to very little // time consuming nodes const float mindelay = 0.15; - if (interactArgs->nodig_delay_timer < mindelay) - interactArgs->nodig_delay_timer = mindelay; + if (runData->nodig_delay_timer < mindelay) + runData->nodig_delay_timer = mindelay; // Send event to trigger sound MtEvent *e = new NodeDugEvent(nodepos, wasnode); gamedef->event()->put(e); } - if (interactArgs->dig_time_complete < 100000.0) { - interactArgs->dig_time += dtime; + if (runData->dig_time_complete < 100000.0) { + runData->dig_time += dtime; } else { - interactArgs->dig_time = 0; + runData->dig_time = 0; client->setCrack(-1, nodepos); } @@ -3500,8 +3670,8 @@ void MinetestApp::handleDigging(InteractParams *interactArgs, } -void MinetestApp::updateFrame(std::vector &highlight_boxes, - ProfilerGraph *graph, RunStats *stats, InteractParams *interactArgs, +void Game::updateFrame(std::vector &highlight_boxes, + ProfilerGraph *graph, RunStats *stats, GameRunData *runData, f32 dtime, const VolatileRunFlags &flags, const CameraOrientation &cam) { LocalPlayer *player = client->getEnv().getLocalPlayer(); @@ -3511,14 +3681,14 @@ void MinetestApp::updateFrame(std::vector &highlight_boxes, */ if (draw_control->range_all) { - interactArgs->fog_range = 100000 * BS; + runData->fog_range = 100000 * BS; } else { - interactArgs->fog_range = draw_control->wanted_range * BS + runData->fog_range = draw_control->wanted_range * BS + 0.0 * MAP_BLOCKSIZE * BS; - interactArgs->fog_range = MYMIN( - interactArgs->fog_range, + runData->fog_range = MYMIN( + runData->fog_range, (draw_control->farthest_drawn + 20) * BS); - interactArgs->fog_range *= 0.9; + runData->fog_range *= 0.9; } /* @@ -3526,8 +3696,8 @@ void MinetestApp::updateFrame(std::vector &highlight_boxes, */ u32 daynight_ratio = client->getEnv().getDayNightRatio(); float time_brightness = decode_light_f((float)daynight_ratio / 1000.0); - float direct_brightness = 0; - bool sunlight_seen = false; + float direct_brightness; + bool sunlight_seen; if (g_settings->getBool("free_move")) { direct_brightness = time_brightness; @@ -3536,25 +3706,24 @@ void MinetestApp::updateFrame(std::vector &highlight_boxes, ScopeProfiler sp(g_profiler, "Detecting background light", SPT_AVG); float old_brightness = sky->getBrightness(); direct_brightness = client->getEnv().getClientMap() - .getBackgroundBrightness(MYMIN(interactArgs->fog_range * 1.2, 60 * BS), + .getBackgroundBrightness(MYMIN(runData->fog_range * 1.2, 60 * BS), daynight_ratio, (int)(old_brightness * 255.5), &sunlight_seen) / 255.0; } - float time_of_day = 0; - float time_of_day_smooth = 0; + float time_of_day = runData->time_of_day; + float time_of_day_smooth = runData->time_of_day_smooth; time_of_day = client->getEnv().getTimeOfDayF(); const float maxsm = 0.05; + const float todsm = 0.05; if (fabs(time_of_day - time_of_day_smooth) > maxsm && fabs(time_of_day - time_of_day_smooth + 1.0) > maxsm && fabs(time_of_day - time_of_day_smooth - 1.0) > maxsm) time_of_day_smooth = time_of_day; - const float todsm = 0.05; - if (time_of_day_smooth > 0.8 && time_of_day < 0.2) time_of_day_smooth = time_of_day_smooth * (1.0 - todsm) + (time_of_day + 1.0) * todsm; @@ -3562,6 +3731,9 @@ void MinetestApp::updateFrame(std::vector &highlight_boxes, time_of_day_smooth = time_of_day_smooth * (1.0 - todsm) + time_of_day * todsm; + runData->time_of_day = time_of_day; + runData->time_of_day_smooth = time_of_day_smooth; + sky->update(time_of_day_smooth, time_brightness, direct_brightness, sunlight_seen, camera->getCameraMode(), player->getYaw(), player->getPitch()); @@ -3596,8 +3768,8 @@ void MinetestApp::updateFrame(std::vector &highlight_boxes, driver->setFog( sky->getBgColor(), video::EFT_FOG_LINEAR, - interactArgs->fog_range * 0.4, - interactArgs->fog_range * 1.0, + runData->fog_range * 0.4, + runData->fog_range * 1.0, 0.01, false, // pixel fog false // range fog @@ -3621,54 +3793,50 @@ void MinetestApp::updateFrame(std::vector &highlight_boxes, v2u32 screensize = driver->getScreenSize(); updateChat(*client, dtime, flags.show_debug, screensize, - flags.show_chat, interactArgs->profiler_current_page, - *chat_backend, guitext_chat, font); + flags.show_chat, runData->profiler_current_page, + *chat_backend, guitext_chat); /* Inventory */ - bool update_wielded_item_trigger = true; - - if (client->getPlayerItem() != interactArgs->new_playeritem) { - client->selectPlayerItem(interactArgs->new_playeritem); - } + if (client->getPlayerItem() != runData->new_playeritem) + client->selectPlayerItem(runData->new_playeritem); + // Update local inventory if it has changed if (client->getLocalInventoryUpdated()) { //infostream<<"Updating local inventory"<getLocalInventory(*local_inventory); - - update_wielded_item_trigger = true; + runData->update_wielded_item_trigger = true; } - if (update_wielded_item_trigger) { - update_wielded_item_trigger = false; + if (runData->update_wielded_item_trigger) { // Update wielded tool InventoryList *mlist = local_inventory->getList("main"); - ItemStack item; - - if (mlist && (client->getPlayerItem() < mlist->getSize())) - item = mlist->getItem(client->getPlayerItem()); - camera->wield(item, client->getPlayerItem()); + if (mlist && (client->getPlayerItem() < mlist->getSize())) { + ItemStack item = mlist->getItem(client->getPlayerItem()); + camera->wield(item); + } + runData->update_wielded_item_trigger = false; } /* Update block draw list every 200ms or when camera direction has changed much */ - interactArgs->update_draw_list_timer += dtime; + runData->update_draw_list_timer += dtime; v3f camera_direction = camera->getDirection(); - if (interactArgs->update_draw_list_timer >= 0.2 - || interactArgs->update_draw_list_last_cam_dir.getDistanceFrom(camera_direction) > 0.2 + if (runData->update_draw_list_timer >= 0.2 + || runData->update_draw_list_last_cam_dir.getDistanceFrom(camera_direction) > 0.2 || flags.camera_offset_changed) { - interactArgs->update_draw_list_timer = 0; + runData->update_draw_list_timer = 0; client->getEnv().getClientMap().updateDrawList(driver); - interactArgs->update_draw_list_last_cam_dir = camera_direction; + runData->update_draw_list_last_cam_dir = camera_direction; } - updateGui(&interactArgs->statustext_time, *stats, dtime, flags, cam); + updateGui(&runData->statustext_time, *stats, dtime, flags, cam); /* make sure menu is on top @@ -3704,13 +3872,13 @@ void MinetestApp::updateFrame(std::vector &highlight_boxes, Profiler graph */ if (flags.show_profiler_graph) - graph->draw(10, screensize.Y - 10, driver, font); + graph->draw(10, screensize.Y - 10, driver, g_fontengine->getFont()); /* Damage flash */ - if (interactArgs->damage_flash > 0.0) { - video::SColor color(std::min(interactArgs->damage_flash, 180.0f), + if (runData->damage_flash > 0.0) { + video::SColor color(std::min(runData->damage_flash, 180.0f), 180, 0, 0); @@ -3718,7 +3886,7 @@ void MinetestApp::updateFrame(std::vector &highlight_boxes, core::rect(0, 0, screensize.X, screensize.Y), NULL); - interactArgs->damage_flash -= 100.0 * dtime; + runData->damage_flash -= 100.0 * dtime; } /* @@ -3745,7 +3913,7 @@ void MinetestApp::updateFrame(std::vector &highlight_boxes, } -void MinetestApp::updateGui(float *statustext_time, const RunStats& stats, +void Game::updateGui(float *statustext_time, const RunStats& stats, f32 dtime, const VolatileRunFlags &flags, const CameraOrientation &cam) { v2u32 screensize = driver->getScreenSize(); @@ -3757,6 +3925,7 @@ void MinetestApp::updateGui(float *statustext_time, const RunStats& stats, drawtime_avg = drawtime_avg * 0.95 + stats.drawtime * 0.05; u16 fps = 1.0 / stats.dtime_jitter.avg; + //s32 fps = driver->getFPS(); std::ostringstream os(std::ios_base::binary); os << std::fixed @@ -3786,7 +3955,7 @@ void MinetestApp::updateGui(float *statustext_time, const RunStats& stats, if (guitext->isVisible()) { core::rect rect( 5, 5, - screensize.X, 5 + text_height + screensize.X, 5 + g_fontengine->getTextHeight() ); guitext->setRelativePosition(rect); } @@ -3804,8 +3973,8 @@ void MinetestApp::updateGui(float *statustext_time, const RunStats& stats, guitext2->setVisible(true); core::rect rect( - 5, 5 + text_height, - screensize.X, 5 + text_height * 2 + 5, 5 + g_fontengine->getTextHeight(), + screensize.X, 5 + g_fontengine->getTextHeight() * 2 ); guitext2->setRelativePosition(rect); } else { @@ -3855,7 +4024,7 @@ void MinetestApp::updateGui(float *statustext_time, const RunStats& stats, /* Log times and stuff for visualization */ -inline void MinetestApp::updateProfilerGraphs(ProfilerGraph *graph) +inline void Game::updateProfilerGraphs(ProfilerGraph *graph) { Profiler::GraphValues values; g_profiler->graphGet(values); @@ -3869,78 +4038,63 @@ inline void MinetestApp::updateProfilerGraphs(ProfilerGraph *graph) ****************************************************************************/ /* On some computers framerate doesn't seem to be automatically limited - * - * *Must* be called after device->run() so that device->getTimer()->getTime(); - * is correct */ -inline void MinetestApp::limitFps(FpsControl *params, f32 *dtime) +inline void Game::limitFps(FpsControl *fps_timings, f32 *dtime) { // not using getRealTime is necessary for wine + device->getTimer()->tick(); // Maker sure device time is up-to-date u32 time = device->getTimer()->getTime(); - u32 last_time = params->last_time; + u32 last_time = fps_timings->last_time; - if (time > last_time) // Make sure time hasn't overflowed - params->busy_time = time - last_time; + if (time > last_time) // Make sure time hasn't overflowed + fps_timings->busy_time = time - last_time; else - params->busy_time = 0; + fps_timings->busy_time = 0; u32 frametime_min = 1000 / (g_menumgr.pausesGame() ? g_settings->getFloat("pause_fps_max") : g_settings->getFloat("fps_max")); - if (params->busy_time < frametime_min) { - params->sleep_time = frametime_min - params->busy_time; - device->sleep(params->sleep_time); - time += params->sleep_time; + if (fps_timings->busy_time < frametime_min) { + fps_timings->sleep_time = frametime_min - fps_timings->busy_time; + device->sleep(fps_timings->sleep_time); } else { - params->sleep_time = 0; + fps_timings->sleep_time = 0; } - if (time > last_time) // Checking for overflow - *dtime = (time - last_time) / 1000.0; - else - *dtime = 0.03; // Choose 30fps as fallback in overflow case - - params->last_time = time; - -#if 0 - - /* This is the old method for calculating new_time and dtime, and seems - * like overkill considering timings are messed up by expected variation - * in execution speed in other places anyway. (This has nothing to do with - * WINE... the new method above calculates dtime based on sleep_time) + /* Get the new value of the device timer. Note that device->sleep() may + * not sleep for the entire requested time as sleep may be interrupted and + * therefore it is arguably more accurate to get the new time from the + * device rather than calculating it by adding sleep_time to time. */ - // Necessary for device->getTimer()->getTime() - device->run(); + device->getTimer()->tick(); // Update device timer time = device->getTimer()->getTime(); - if (time > last_time) // Make sure last_time hasn't overflowed + if (time > last_time) // Make sure last_time hasn't overflowed *dtime = (time - last_time) / 1000.0; else - *dtime = 0.033; + *dtime = 0; - params->last_time = time; -#endif + fps_timings->last_time = time; } -void MinetestApp::showOverlayMessage(const char *msg, float dtime, +void Game::showOverlayMessage(const char *msg, float dtime, int percent, bool draw_clouds) { wchar_t *text = wgettext(msg); - draw_load_screen(text, device, guienv, font, dtime, percent, draw_clouds); + draw_load_screen(text, device, guienv, dtime, percent, draw_clouds); delete[] text; } - /**************************************************************************** Shutdown / cleanup ****************************************************************************/ -void MinetestApp::extendedResourceCleanup() +void Game::extendedResourceCleanup() { // Extended resource accounting infostream << "Irrlicht resources after cleanup:" << std::endl; @@ -3971,7 +4125,6 @@ void the_game(bool *kill, bool random_input, InputHandler *input, IrrlichtDevice *device, - gui::IGUIFont *font, const std::string &map_dir, const std::string &playername, @@ -3984,7 +4137,7 @@ void the_game(bool *kill, const SubgameSpec &gamespec, // Used for local game bool simple_singleplayer_mode) { - MinetestApp app; + Game game; /* Make a copy of the server address because if a local singleplayer server * is created then this is updated and we don't want to change the value @@ -3994,14 +4147,13 @@ void the_game(bool *kill, try { - if (app.startup(kill, random_input, input, device, font, map_dir, + if (game.startup(kill, random_input, input, device, map_dir, playername, password, &server_address, port, &error_message, &chat_backend, gamespec, simple_singleplayer_mode)) { - //std::cout << "App started" << std::endl; - app.run(); - app.shutdown(); + game.run(); + game.shutdown(); } } catch (SerializationError &e) {