Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create faster key cache for main game loop (client) #1802

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
233 changes: 178 additions & 55 deletions src/game.cpp
Expand Up @@ -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;
Expand Down Expand Up @@ -1263,6 +1373,10 @@ 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
Expand Down Expand Up @@ -1456,6 +1570,8 @@ class Game

std::wstring infotext;
std::wstring statustext;

KeyCache keycache;
};

Game::Game() :
Expand Down Expand Up @@ -1569,8 +1685,6 @@ void Game::run()
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.invert_mouse = g_settings->getBool("invert_mouse");

/* Clear the profiler */
Expand Down Expand Up @@ -2186,6 +2300,11 @@ inline bool Game::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;
}

Expand Down Expand Up @@ -2320,76 +2439,77 @@ void Game::processKeyboardInput(VolatileRunFlags *flags,
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(&current_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(&current_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(&current_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"))) {
} 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;
dstream << "-----------------------------------------"
<< std::endl;
debug_stacks_print();
}

//tt.stop();

if (quicktune->hasMessage()) {
std::string msg = quicktune->getMessage();
statustext = narrow_to_wide(msg);
*statustext_time = 0;
}
}


Expand Down Expand Up @@ -2724,14 +2844,16 @@ void Game::updateCameraDirection(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,
Expand All @@ -2740,17 +2862,18 @@ void Game::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();
}


Expand Down Expand Up @@ -3036,7 +3159,7 @@ void Game::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();

Expand Down
8 changes: 8 additions & 0 deletions src/guiKeyChangeMenu.cpp
Expand Up @@ -32,8 +32,12 @@
#include "settings.h"
#include <algorithm>

#include "mainmenumanager.h" // for g_gamecallback

#define KMaxButtonPerColumns 12

extern MainGameCallback *g_gamecallback;

enum
{
GUI_ID_BACK_BUTTON = 101, GUI_ID_ABORT_BUTTON, GUI_ID_SCROLL_BAR,
Expand Down Expand Up @@ -234,7 +238,11 @@ bool GUIKeyChangeMenu::acceptInput()
if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
g_settings->setBool("doubletap_jump", ((gui::IGUICheckBox*)e)->isChecked());
}

clearKeyCache();

g_gamecallback->signalKeyConfigChange();

return true;
}

Expand Down
11 changes: 11 additions & 0 deletions src/mainmenumanager.h
Expand Up @@ -35,6 +35,8 @@ class IGameCallback
virtual void disconnect() = 0;
virtual void changePassword() = 0;
virtual void changeVolume() = 0;

virtual void signalKeyConfigChange() = 0;
};

extern gui::IGUIEnvironment* guienv;
Expand Down Expand Up @@ -127,6 +129,7 @@ class MainGameCallback : public IGameCallback
changevolume_requested(false),
keyconfig_requested(false),
shutdown_requested(false),
keyconfig_changed(false),
device(a_device)
{
}
Expand Down Expand Up @@ -159,12 +162,20 @@ class MainGameCallback : public IGameCallback
keyconfig_requested = true;
}

virtual void signalKeyConfigChange()
{
keyconfig_changed = true;
}


bool disconnect_requested;
bool changepassword_requested;
bool changevolume_requested;
bool keyconfig_requested;
bool shutdown_requested;

bool keyconfig_changed;

IrrlichtDevice *device;
};

Expand Down