Create faster key cache for main game loop (client)

This commit is contained in:
Craig Robbins 2014-11-10 12:26:19 +10:00
parent 18c583ee0b
commit 987e565eeb
4 changed files with 202 additions and 53 deletions

@ -1181,9 +1181,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; const float object_hit_delay = 0.2;
@ -1264,6 +1374,10 @@ struct VolatileRunFlags {
}; };
/****************************************************************************
THE GAME
****************************************************************************/
/* This is not intended to be a public class. If a public class becomes /* 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 * 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 * hides most of the stuff in this class (nothing in this class is required
@ -1458,6 +1572,8 @@ private:
std::wstring infotext; std::wstring infotext;
std::wstring statustext; std::wstring statustext;
KeyCache keycache;
}; };
Game::Game() : Game::Game() :
@ -2186,6 +2302,11 @@ inline bool Game::handleCallbacks()
g_gamecallback->keyconfig_requested = false; 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; return true;
} }
@ -2322,70 +2443,63 @@ void Game::processKeyboardInput(VolatileRunFlags *flags,
u32 *profiler_current_page, u32 *profiler_current_page,
u32 profiler_max_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(); dropSelectedItem();
} else if (input->wasKeyDown(getKeySetting("keymap_inventory"))) { } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_INVENTORY])) {
openInventory(); openInventory();
} else if (input->wasKeyDown(EscapeKey) || input->wasKeyDown(CancelKey)) { } else if (input->wasKeyDown(EscapeKey) || input->wasKeyDown(CancelKey)) {
show_pause_menu(&current_formspec, client, gamedef, texture_src, device, show_pause_menu(&current_formspec, client, gamedef, texture_src, device,
simple_singleplayer_mode); simple_singleplayer_mode);
} else if (input->wasKeyDown(getKeySetting("keymap_chat"))) { } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_CHAT])) {
show_chat_menu(&current_formspec, client, gamedef, texture_src, device, show_chat_menu(&current_formspec, client, gamedef, texture_src, device,
client, ""); client, "");
} else if (input->wasKeyDown(getKeySetting("keymap_cmd"))) { } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_CMD])) {
show_chat_menu(&current_formspec, client, gamedef, texture_src, device, show_chat_menu(&current_formspec, client, gamedef, texture_src, device,
client, "/"); client, "/");
} else if (input->wasKeyDown(getKeySetting("keymap_console"))) { } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_CONSOLE])) {
openConsole(); openConsole();
} else if (input->wasKeyDown(getKeySetting("keymap_freemove"))) { } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_FREEMOVE])) {
toggleFreeMove(statustext_time); 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); toggleFreeMoveAlt(statustext_time, jump_timer);
*reset_jump_timer = true; *reset_jump_timer = true;
} else if (input->wasKeyDown(getKeySetting("keymap_fastmove"))) { } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_FASTMOVE])) {
toggleFast(statustext_time); toggleFast(statustext_time);
} else if (input->wasKeyDown(getKeySetting("keymap_noclip"))) { } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_NOCLIP])) {
toggleNoClip(statustext_time); toggleNoClip(statustext_time);
} else if (input->wasKeyDown(getKeySetting("keymap_screenshot"))) { } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_SCREENSHOT])) {
client->makeScreenshot(device); 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); 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); 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); 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); 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); 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); 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); 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); decreaseViewRange(statustext_time);
} else if (input->wasKeyDown(getKeySetting("keymap_rangeselect"))) { } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_RANGESELECT])) {
toggleFullViewRange(statustext_time); toggleFullViewRange(statustext_time);
} } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_QUICKTUNE_NEXT]))
// Handle QuicktuneShortcutter
if (input->wasKeyDown(getKeySetting("keymap_quicktune_next")))
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(); quicktune->prev();
else if (input->wasKeyDown(getKeySetting("keymap_quicktune_inc"))) else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_QUICKTUNE_INC]))
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(); quicktune->dec();
else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_DEBUG_STACKS])) {
std::string msg = quicktune->getMessage(); // Print debug stacks
if (msg != "") {
statustext = narrow_to_wide(msg);
*statustext_time = 0;
}
// Print debug stacks
if (input->wasKeyDown(getKeySetting("keymap_print_debug_stacks"))) {
dstream << "-----------------------------------------" dstream << "-----------------------------------------"
<< std::endl; << std::endl;
dstream << DTIME << "Printing debug stacks:" << std::endl; dstream << DTIME << "Printing debug stacks:" << std::endl;
@ -2398,6 +2512,14 @@ void Game::processKeyboardInput(VolatileRunFlags *flags,
*reset_jump_timer = false; *reset_jump_timer = false;
*jump_timer = 0.0; *jump_timer = 0.0;
} }
//tt.stop();
if (quicktune->hasMessage()) {
std::string msg = quicktune->getMessage();
statustext = narrow_to_wide(msg);
*statustext_time = 0;
}
} }
@ -2730,14 +2852,16 @@ void Game::updateCameraDirection(CameraOrientation *cam,
void Game::updatePlayerControl(const CameraOrientation &cam) void Game::updatePlayerControl(const CameraOrientation &cam)
{ {
//TimeTaker tt("update player control", NULL, PRECISION_NANO);
PlayerControl control( PlayerControl control(
input->isKeyDown(getKeySetting("keymap_forward")), input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_FORWARD]),
input->isKeyDown(getKeySetting("keymap_backward")), input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_BACKWARD]),
input->isKeyDown(getKeySetting("keymap_left")), input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_LEFT]),
input->isKeyDown(getKeySetting("keymap_right")), input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_RIGHT]),
input->isKeyDown(getKeySetting("keymap_jump")), input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_JUMP]),
input->isKeyDown(getKeySetting("keymap_special1")), input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_SPECIAL1]),
input->isKeyDown(getKeySetting("keymap_sneak")), input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_SNEAK]),
input->getLeftState(), input->getLeftState(),
input->getRightState(), input->getRightState(),
cam.camera_pitch, cam.camera_pitch,
@ -2746,17 +2870,18 @@ void Game::updatePlayerControl(const CameraOrientation &cam)
client->setPlayerControl(control); client->setPlayerControl(control);
LocalPlayer *player = client->getEnv().getLocalPlayer(); LocalPlayer *player = client->getEnv().getLocalPlayer();
player->keyPressed = player->keyPressed =
( (u32)(input->isKeyDown(getKeySetting("keymap_forward")) & 0x1) << 0) | ( (u32)(input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_FORWARD]) & 0x1) << 0) |
( (u32)(input->isKeyDown(getKeySetting("keymap_backward")) & 0x1) << 1) | ( (u32)(input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_BACKWARD]) & 0x1) << 1) |
( (u32)(input->isKeyDown(getKeySetting("keymap_left")) & 0x1) << 2) | ( (u32)(input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_LEFT]) & 0x1) << 2) |
( (u32)(input->isKeyDown(getKeySetting("keymap_right")) & 0x1) << 3) | ( (u32)(input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_RIGHT]) & 0x1) << 3) |
( (u32)(input->isKeyDown(getKeySetting("keymap_jump")) & 0x1) << 4) | ( (u32)(input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_JUMP]) & 0x1) << 4) |
( (u32)(input->isKeyDown(getKeySetting("keymap_special1")) & 0x1) << 5) | ( (u32)(input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_SPECIAL1]) & 0x1) << 5) |
( (u32)(input->isKeyDown(getKeySetting("keymap_sneak")) & 0x1) << 6) | ( (u32)(input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_SNEAK]) & 0x1) << 6) |
( (u32)(input->getLeftState() & 0x1) << 7) | ( (u32)(input->getLeftState() & 0x1) << 7) |
( (u32)(input->getRightState() & 0x1) << 8 ( (u32)(input->getRightState() & 0x1) << 8
); );
//tt.stop();
} }
@ -3042,7 +3167,7 @@ void Game::updateCamera(VolatileRunFlags *flags, u32 busy_time,
v3s16 old_camera_offset = camera->getOffset(); 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(); camera->toggleCameraMode();
GenericCAO *playercao = player->getCAO(); GenericCAO *playercao = player->getCAO();

@ -32,8 +32,12 @@
#include "settings.h" #include "settings.h"
#include <algorithm> #include <algorithm>
#include "mainmenumanager.h" // for g_gamecallback
#define KMaxButtonPerColumns 12 #define KMaxButtonPerColumns 12
extern MainGameCallback *g_gamecallback;
enum enum
{ {
GUI_ID_BACK_BUTTON = 101, GUI_ID_ABORT_BUTTON, GUI_ID_SCROLL_BAR, GUI_ID_BACK_BUTTON = 101, GUI_ID_ABORT_BUTTON, GUI_ID_SCROLL_BAR,
@ -234,7 +238,11 @@ bool GUIKeyChangeMenu::acceptInput()
if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX) if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
g_settings->setBool("doubletap_jump", ((gui::IGUICheckBox*)e)->isChecked()); g_settings->setBool("doubletap_jump", ((gui::IGUICheckBox*)e)->isChecked());
} }
clearKeyCache(); clearKeyCache();
g_gamecallback->signalKeyConfigChange();
return true; return true;
} }

@ -35,6 +35,8 @@ public:
virtual void disconnect() = 0; virtual void disconnect() = 0;
virtual void changePassword() = 0; virtual void changePassword() = 0;
virtual void changeVolume() = 0; virtual void changeVolume() = 0;
virtual void signalKeyConfigChange() = 0;
}; };
extern gui::IGUIEnvironment* guienv; extern gui::IGUIEnvironment* guienv;
@ -127,6 +129,7 @@ public:
changevolume_requested(false), changevolume_requested(false),
keyconfig_requested(false), keyconfig_requested(false),
shutdown_requested(false), shutdown_requested(false),
keyconfig_changed(false),
device(a_device) device(a_device)
{ {
} }
@ -159,12 +162,20 @@ public:
keyconfig_requested = true; keyconfig_requested = true;
} }
virtual void signalKeyConfigChange()
{
keyconfig_changed = true;
}
bool disconnect_requested; bool disconnect_requested;
bool changepassword_requested; bool changepassword_requested;
bool changevolume_requested; bool changevolume_requested;
bool keyconfig_requested; bool keyconfig_requested;
bool shutdown_requested; bool shutdown_requested;
bool keyconfig_changed;
IrrlichtDevice *device; IrrlichtDevice *device;
}; };

@ -29,6 +29,11 @@ private:
u32 m_selected_i; u32 m_selected_i;
std::string m_message; std::string m_message;
public: public:
bool hasMessage()
{
return m_message != "";
}
std::string getMessage() std::string getMessage()
{ {
std::string s = m_message; std::string s = m_message;