#include "game.h"
#include <iomanip>
+#include <cmath>
#include "client/renderingengine.h"
#include "camera.h"
#include "client.h"
+#include "client/clientevent.h"
#include "client/inputhandler.h"
#include "client/tile.h" // For TextureSource
#include "client/keys.h"
#include "raycast.h"
#include "server.h"
#include "settings.h"
+#include "shader.h"
#include "sky.h"
#include "subgame.h"
#include "tool.h"
+#include "translation.h"
#include "util/basic_macros.h"
#include "util/directiontables.h"
#include "util/pointedthing.h"
#include "sound_openal.h"
#endif
-extern Settings *g_settings;
-extern Profiler *g_profiler;
/*
Text input system
/* Form update callback */
+static const std::string empty_string = "";
class NodeMetadataFormSource: public IFormSource
{
public:
m_p(p)
{
}
- std::string getForm()
+ const std::string &getForm() const
{
NodeMetadata *meta = m_map->getNodeMetadata(m_p);
if (!meta)
- return "";
+ return empty_string;
return meta->getString("formspec");
}
m_client(client)
{
}
- std::string getForm()
+
+ const std::string &getForm() const
{
LocalPlayer *player = m_client->getEnv().getLocalPlayer();
return player->inventory_formspec;
std::ostringstream os(std::ios_base::binary);
g_profiler->printPage(os, show_profiler, show_profiler_max);
- std::wstring text = utf8_to_wide(os.str());
+ std::wstring text = translate_string(utf8_to_wide(os.str()));
setStaticText(guitext_profiler, text.c_str());
guitext_profiler->setVisible(true);
- s32 w = fe->getTextWidth(text.c_str());
+ s32 w = fe->getTextWidth(text);
if (w < 400)
w = 400;
};
std::deque<Piece> m_log;
public:
- u32 m_log_max_size;
+ u32 m_log_max_size = 200;
- ProfilerGraph():
- m_log_max_size(200)
- {}
+ ProfilerGraph() = default;
void put(const Profiler::GraphValues &values)
{
// to be the same for each call to prevent flickering
std::map<std::string, Meta> m_meta;
- for (std::deque<Piece>::const_iterator k = m_log.begin();
- k != m_log.end(); ++k) {
- const Piece &piece = *k;
-
- for (Profiler::GraphValues::const_iterator i = piece.values.begin();
- i != piece.values.end(); ++i) {
- const std::string &id = i->first;
- const float &value = i->second;
+ for (const Piece &piece : m_log) {
+ for (const auto &i : piece.values) {
+ const std::string &id = i.first;
+ const float &value = i.second;
std::map<std::string, Meta>::iterator j = m_meta.find(id);
if (j == m_meta.end()) {
sizeof(usable_colors) / sizeof(*usable_colors);
u32 next_color_i = 0;
- for (std::map<std::string, Meta>::iterator i = m_meta.begin();
- i != m_meta.end(); ++i) {
- Meta &meta = i->second;
+ for (auto &i : m_meta) {
+ Meta &meta = i.second;
video::SColor color(255, 200, 200, 200);
if (next_color_i < usable_colors_count)
float lastscaledvalue = 0.0;
bool lastscaledvalue_exists = false;
- for (std::deque<Piece>::const_iterator j = m_log.begin();
- j != m_log.end(); ++j) {
- const Piece &piece = *j;
+ for (const Piece &piece : m_log) {
float value = 0;
bool value_exists = false;
Profiler::GraphValues::const_iterator k =
void setSky(Sky *sky) {
m_sky = sky;
- for (size_t i = 0; i < created_nosky.size(); ++i) {
- created_nosky[i]->setSky(m_sky);
+ for (GameGlobalShaderConstantSetter *ggscs : created_nosky) {
+ ggscs->setSky(m_sky);
}
created_nosky.clear();
}
if (!is_valid_position)
return false;
- if (prediction != "" && !nodedef->get(node).rightclickable) {
+ if (!prediction.empty() && !nodedef->get(node).rightclickable) {
verbosestream << "Node placement prediction for "
<< playeritem_def.name << " is "
<< prediction << std::endl;
// Get new messages from client
std::wstring message;
-
while (client.getChatMessage(message)) {
chat_backend.addUnparsedMessage(message);
}
s32 chat_y = 5;
if (show_debug)
- chat_y += 2 * line_height;
+ chat_y += 3 * line_height;
// first pass to calculate height of text to be set
const v2u32 &window_size = RenderingEngine::get_instance()->getWindowSize();
key[KeyType::QUICKTUNE_INC] = getKeySetting("keymap_quicktune_inc");
key[KeyType::QUICKTUNE_DEC] = getKeySetting("keymap_quicktune_dec");
- key[KeyType::DEBUG_STACKS] = getKeySetting("keymap_print_debug_stacks");
+ for (int i = 0; i < 23; i++) {
+ std::string slot_key_name = "keymap_slot" + std::to_string(i + 1);
+ key[KeyType::SLOT_1 + i] = getKeySetting(slot_key_name.c_str());
+ }
if (handler) {
// First clear all keys, then re-add the ones we listen for
handler->dontListenForKeys();
- for (size_t i = 0; i < KeyType::INTERNAL_ENUM_COUNT; i++) {
- handler->listenForKey(key[i]);
+ for (const KeyPress &k : key) {
+ handler->listenForKey(k);
}
handler->listenForKey(EscapeKey);
handler->listenForKey(CancelKey);
- for (size_t i = 0; i < 10; i++) {
- handler->listenForKey(NumberKey[i]);
- }
}
}
bool digging;
bool ldown_for_dig;
bool dig_instantly;
+ bool digging_blocked;
bool left_punch;
bool update_wielded_item_trigger;
bool reset_jump_timer;
Jitter dtime_jitter, busy_time_jitter;
};
+class Game;
+
+struct ClientEventHandler
+{
+ void (Game::*handler)(ClientEvent *, CameraOrientation *);
+};
+
/****************************************************************************
THE GAME
****************************************************************************/
void processKeyInput();
void processItemSelection(u16 *new_playeritem);
- void dropSelectedItem();
+ void dropSelectedItem(bool single_item = false);
void openInventory();
void openConsole(float scale, const wchar_t *line=NULL);
void toggleFreeMove();
void showOverlayMessage(const char *msg, float dtime, int percent,
bool draw_clouds = true);
+ void showStatusTextSimple(const char *msg);
static void settingChangedCallback(const std::string &setting_name, void *data);
void readSettings();
private:
void showPauseMenu();
+ // ClientEvent handlers
+ void handleClientEvent_None(ClientEvent *event, CameraOrientation *cam);
+ void handleClientEvent_PlayerDamage(ClientEvent *event, CameraOrientation *cam);
+ void handleClientEvent_PlayerForceMove(ClientEvent *event, CameraOrientation *cam);
+ void handleClientEvent_Deathscreen(ClientEvent *event, CameraOrientation *cam);
+ void handleClientEvent_ShowFormSpec(ClientEvent *event, CameraOrientation *cam);
+ void handleClientEvent_ShowLocalFormSpec(ClientEvent *event, CameraOrientation *cam);
+ void handleClientEvent_HandleParticleEvent(ClientEvent *event,
+ CameraOrientation *cam);
+ void handleClientEvent_HudAdd(ClientEvent *event, CameraOrientation *cam);
+ void handleClientEvent_HudRemove(ClientEvent *event, CameraOrientation *cam);
+ void handleClientEvent_HudChange(ClientEvent *event, CameraOrientation *cam);
+ void handleClientEvent_SetSky(ClientEvent *event, CameraOrientation *cam);
+ void handleClientEvent_OverrideDayNigthRatio(ClientEvent *event,
+ CameraOrientation *cam);
+ void handleClientEvent_CloudParams(ClientEvent *event, CameraOrientation *cam);
+
+ static const ClientEventHandler clientEventHandler[CLIENTEVENT_MAX];
+
InputHandler *input;
Client *client;
GameOnDemandSoundFetcher soundfetcher; // useful when testing
ISoundManager *sound;
- bool sound_is_dummy;
+ bool sound_is_dummy = false;
SoundMaker *soundmaker;
ChatBackend *chat_backend;
*/
gui::IGUIStaticText *guitext; // First line of debug text
gui::IGUIStaticText *guitext2; // Second line of debug text
+ gui::IGUIStaticText *guitext3; // Third line of debug text
gui::IGUIStaticText *guitext_info; // At the middle of the screen
gui::IGUIStaticText *guitext_status;
gui::IGUIStaticText *guitext_chat; // Chat text
f32 m_cache_cam_smoothing;
f32 m_cache_fog_start;
- bool m_invert_mouse;
- bool m_first_loop_after_window_activation;
- bool m_camera_offset_changed;
+ bool m_invert_mouse = false;
+ bool m_first_loop_after_window_activation = false;
+ bool m_camera_offset_changed = false;
#ifdef __ANDROID__
bool m_cache_hold_aux1;
itemdef_manager(NULL),
nodedef_manager(NULL),
sound(NULL),
- sound_is_dummy(false),
soundmaker(NULL),
chat_backend(NULL),
current_formspec(NULL),
sky(NULL),
local_inventory(NULL),
hud(NULL),
- mapper(NULL),
- m_invert_mouse(false),
- m_first_loop_after_window_activation(false),
- m_camera_offset_changed(false)
+ mapper(NULL)
{
g_settings->registerChangedCallback("doubletap_jump",
&settingChangedCallback, this);
m_invert_mouse = g_settings->getBool("invert_mouse");
m_first_loop_after_window_activation = true;
+ g_translations->clear();
+
if (!init(map_dir, address, port, gamespec))
return false;
return false;
// Create a server if not connecting to an existing one
- if (*address == "") {
+ if (address->empty()) {
if (!createSingleplayerServer(map_dir, gamespec, port, address))
return false;
}
core::rect<s32>(0, 0, 0, 0),
false, false, guiroot);
+ // Third line of debug text
+ guitext3 = addStaticText(guienv,
+ L"",
+ core::rect<s32>(0, 0, 0, 0),
+ false, false, guiroot);
+
// At the middle of the screen
// Object infos are shown in this
guitext_info = addStaticText(guienv,
wait_time += dtime;
// Only time out if we aren't waiting for the server we started
- if ((*address != "") && (wait_time > 10)) {
+ if ((!address->empty()) && (wait_time > 10)) {
bool sent_old_init = g_settings->getFlag("send_pre_v25_init");
// If no pre v25 init was sent, and no answer was received,
// but the low level connection could be established
void Game::processKeyInput()
{
if (wasKeyDown(KeyType::DROP)) {
- dropSelectedItem();
+ dropSelectedItem(isKeyDown(KeyType::SNEAK));
} else if (wasKeyDown(KeyType::AUTOFORWARD)) {
toggleAutoforward();
} else if (wasKeyDown(KeyType::INVENTORY)) {
} else if (wasKeyDown(KeyType::NOCLIP)) {
toggleNoClip();
} else if (wasKeyDown(KeyType::MUTE)) {
- float volume = g_settings->getFloat("sound_volume");
- if (volume < 0.001f) {
- g_settings->setFloat("sound_volume", 1.0f);
- m_statustext = narrow_to_wide(gettext("Volume changed to 100%"));
- } else {
- g_settings->setFloat("sound_volume", 0.0f);
- m_statustext = narrow_to_wide(gettext("Volume changed to 0%"));
- }
+ bool new_mute_sound = !g_settings->getBool("mute_sound");
+ g_settings->setBool("mute_sound", new_mute_sound);
+ if (new_mute_sound)
+ showStatusTextSimple("Sound muted");
+ else
+ showStatusTextSimple("Sound unmuted");
runData.statustext_time = 0;
} else if (wasKeyDown(KeyType::INC_VOLUME)) {
float new_volume = rangelim(g_settings->getFloat("sound_volume") + 0.1f, 0.0f, 1.0f);
- char buf[100];
+ wchar_t buf[100];
g_settings->setFloat("sound_volume", new_volume);
- snprintf(buf, sizeof(buf), gettext("Volume changed to %d%%"), myround(new_volume * 100));
- m_statustext = narrow_to_wide(buf);
+ const wchar_t *str = wgettext("Volume changed to %d%%");
+ swprintf(buf, sizeof(buf) / sizeof(wchar_t), str, myround(new_volume * 100));
+ delete[] str;
+ m_statustext = buf;
runData.statustext_time = 0;
} else if (wasKeyDown(KeyType::DEC_VOLUME)) {
float new_volume = rangelim(g_settings->getFloat("sound_volume") - 0.1f, 0.0f, 1.0f);
- char buf[100];
+ wchar_t buf[100];
g_settings->setFloat("sound_volume", new_volume);
- snprintf(buf, sizeof(buf), gettext("Volume changed to %d%%"), myround(new_volume * 100));
- m_statustext = narrow_to_wide(buf);
+ const wchar_t *str = wgettext("Volume changed to %d%%");
+ swprintf(buf, sizeof(buf) / sizeof(wchar_t), str, myround(new_volume * 100));
+ delete[] str;
+ m_statustext = buf;
runData.statustext_time = 0;
} else if (wasKeyDown(KeyType::CINEMATIC)) {
toggleCinematic();
quicktune->inc();
} else if (wasKeyDown(KeyType::QUICKTUNE_DEC)) {
quicktune->dec();
- } else if (wasKeyDown(KeyType::DEBUG_STACKS)) {
- // Print debug stacks
- dstream << "-----------------------------------------"
- << std::endl;
- dstream << "Printing debug stacks:" << std::endl;
- dstream << "-----------------------------------------"
- << std::endl;
- debug_stacks_print();
}
if (!isKeyDown(KeyType::JUMP) && runData.reset_jump_timer) {
*new_playeritem = *new_playeritem > 0 ? *new_playeritem - 1 : max_item;
// else dir == 0
- /* Item selection using keyboard
+ /* Item selection using hotbar slot keys
*/
- for (u16 i = 0; i < 10; i++) {
- static const KeyPress *item_keys[10] = {
- NumberKey + 1, NumberKey + 2, NumberKey + 3, NumberKey + 4,
- NumberKey + 5, NumberKey + 6, NumberKey + 7, NumberKey + 8,
- NumberKey + 9, NumberKey + 0,
- };
-
- if (input->wasKeyDown(*item_keys[i])) {
+ for (u16 i = 0; i < 23; i++) {
+ if (wasKeyDown((GameKeyType) (KeyType::SLOT_1 + i))) {
if (i < PLAYER_INVENTORY_SIZE && i < player->hud_hotbar_itemcount) {
*new_playeritem = i;
infostream << "Selected item: " << new_playeritem << std::endl;
}
-void Game::dropSelectedItem()
+void Game::dropSelectedItem(bool single_item)
{
IDropAction *a = new IDropAction();
- a->count = 0;
+ a->count = single_item ? 1 : 0;
a->from_inv.setCurrentPlayer();
a->from_list = "main";
a->from_i = client->getPlayerItem();
void Game::toggleFreeMove()
{
- static const wchar_t *msg[] = { L"free_move disabled", L"free_move enabled" };
-
bool free_move = !g_settings->getBool("free_move");
g_settings->set("free_move", bool_to_cstr(free_move));
runData.statustext_time = 0;
- m_statustext = msg[free_move];
- if (free_move && !client->checkPrivilege("fly"))
- m_statustext += L" (note: no 'fly' privilege)";
+
+ if (free_move) {
+ if (client->checkPrivilege("fly")) {
+ showStatusTextSimple("Fly mode enabled");
+ } else {
+ showStatusTextSimple("Fly mode enabled (note: no 'fly' privilege)");
+ }
+ } else {
+ showStatusTextSimple("Fly mode disabled");
+ }
}
void Game::toggleFast()
{
- static const wchar_t *msg[] = { L"fast_move disabled", L"fast_move enabled" };
bool fast_move = !g_settings->getBool("fast_move");
g_settings->set("fast_move", bool_to_cstr(fast_move));
runData.statustext_time = 0;
- m_statustext = msg[fast_move];
-
- bool has_fast_privs = client->checkPrivilege("fast");
- if (fast_move && !has_fast_privs)
- m_statustext += L" (note: no 'fast' privilege)";
+ if (fast_move) {
+ if (client->checkPrivilege("fast")) {
+ showStatusTextSimple("Fast mode enabled");
+ } else {
+ showStatusTextSimple("Fast mode enabled (note: no 'fast' privilege)");
+ }
+ } else {
+ showStatusTextSimple("Fast mode disabled");
+ }
#ifdef __ANDROID__
m_cache_hold_aux1 = fast_move && has_fast_privs;
void Game::toggleNoClip()
{
- static const wchar_t *msg[] = { L"noclip disabled", L"noclip enabled" };
bool noclip = !g_settings->getBool("noclip");
g_settings->set("noclip", bool_to_cstr(noclip));
runData.statustext_time = 0;
- m_statustext = msg[noclip];
-
- if (noclip && !client->checkPrivilege("noclip"))
- m_statustext += L" (note: no 'noclip' privilege)";
+ if (noclip) {
+ if (client->checkPrivilege("noclip")) {
+ showStatusTextSimple("Noclip mode enabled");
+ } else {
+ showStatusTextSimple("Noclip mode enabled (note: no 'noclip' privilege)");
+ }
+ } else {
+ showStatusTextSimple("Noclip mode disabled");
+ }
}
void Game::toggleCinematic()
{
- static const wchar_t *msg[] = { L"cinematic disabled", L"cinematic enabled" };
bool cinematic = !g_settings->getBool("cinematic");
g_settings->set("cinematic", bool_to_cstr(cinematic));
runData.statustext_time = 0;
- m_statustext = msg[cinematic];
+ if (cinematic)
+ showStatusTextSimple("Cinematic mode enabled");
+ else
+ showStatusTextSimple("Cinematic mode disabled");
}
// Autoforward by toggling continuous forward.
void Game::toggleAutoforward()
{
- static const wchar_t *msg[] = { L"autoforward disabled", L"autoforward enabled" };
- bool autoforward_enabled = !g_settings->getBool("continuous_forward");
- g_settings->set("continuous_forward", bool_to_cstr(autoforward_enabled));
+ bool autorun_enabled = !g_settings->getBool("continuous_forward");
+ g_settings->set("continuous_forward", bool_to_cstr(autorun_enabled));
runData.statustext_time = 0;
- m_statustext = msg[autoforward_enabled ? 1 : 0];
+ if (autorun_enabled)
+ showStatusTextSimple("Automatic forwards enabled");
+ else
+ showStatusTextSimple("Automatic forwards disabled");
}
void Game::toggleChat()
{
- static const wchar_t *msg[] = { L"Chat hidden", L"Chat shown" };
-
flags.show_chat = !flags.show_chat;
runData.statustext_time = 0;
- m_statustext = msg[flags.show_chat];
+ if (flags.show_chat)
+ showStatusTextSimple("Chat shown");
+ else
+ showStatusTextSimple("Chat hidden");
}
void Game::toggleHud()
{
- static const wchar_t *msg[] = { L"HUD hidden", L"HUD shown" };
-
flags.show_hud = !flags.show_hud;
runData.statustext_time = 0;
- m_statustext = msg[flags.show_hud];
+ if (flags.show_hud)
+ showStatusTextSimple("HUD shown");
+ else
+ showStatusTextSimple("HUD hidden");
}
void Game::toggleMinimap(bool shift_pressed)
if (hud_flags & HUD_FLAG_MINIMAP_VISIBLE) {
mode = mapper->getMinimapMode();
mode = (MinimapMode)((int)mode + 1);
+ // If radar is disabled and in, or switching to, radar mode
+ if (!(hud_flags & HUD_FLAG_MINIMAP_RADAR_VISIBLE) && mode > 3)
+ mode = MINIMAP_MODE_OFF;
}
flags.show_minimap = true;
switch (mode) {
case MINIMAP_MODE_SURFACEx1:
- m_statustext = L"Minimap in surface mode, Zoom x1";
+ showStatusTextSimple("Minimap in surface mode, Zoom x1");
break;
case MINIMAP_MODE_SURFACEx2:
- m_statustext = L"Minimap in surface mode, Zoom x2";
+ showStatusTextSimple("Minimap in surface mode, Zoom x2");
break;
case MINIMAP_MODE_SURFACEx4:
- m_statustext = L"Minimap in surface mode, Zoom x4";
+ showStatusTextSimple("Minimap in surface mode, Zoom x4");
break;
case MINIMAP_MODE_RADARx1:
- m_statustext = L"Minimap in radar mode, Zoom x1";
+ showStatusTextSimple("Minimap in radar mode, Zoom x1");
break;
case MINIMAP_MODE_RADARx2:
- m_statustext = L"Minimap in radar mode, Zoom x2";
+ showStatusTextSimple("Minimap in radar mode, Zoom x2");
break;
case MINIMAP_MODE_RADARx4:
- m_statustext = L"Minimap in radar mode, Zoom x4";
+ showStatusTextSimple("Minimap in radar mode, Zoom x4");
break;
default:
mode = MINIMAP_MODE_OFF;
flags.show_minimap = false;
- m_statustext = (hud_flags & HUD_FLAG_MINIMAP_VISIBLE) ?
- L"Minimap hidden" : L"Minimap disabled by server";
+ if (hud_flags & HUD_FLAG_MINIMAP_VISIBLE)
+ showStatusTextSimple("Minimap hidden");
+ else
+ showStatusTextSimple("Minimap disabled by server");
}
runData.statustext_time = 0;
void Game::toggleFog()
{
- static const wchar_t *msg[] = { L"Fog enabled", L"Fog disabled" };
-
flags.force_fog_off = !flags.force_fog_off;
runData.statustext_time = 0;
- m_statustext = msg[flags.force_fog_off];
+ if (flags.force_fog_off)
+ showStatusTextSimple("Fog disabled");
+ else
+ showStatusTextSimple("Fog enabled");
}
flags.show_debug = true;
flags.show_profiler_graph = false;
draw_control->show_wireframe = false;
- m_statustext = L"Debug info shown";
+ showStatusTextSimple("Debug info shown");
} else if (!flags.show_profiler_graph && !draw_control->show_wireframe) {
flags.show_profiler_graph = true;
- m_statustext = L"Profiler graph shown";
+ showStatusTextSimple("Profiler graph shown");
} else if (!draw_control->show_wireframe && client->checkPrivilege("debug")) {
flags.show_profiler_graph = false;
draw_control->show_wireframe = true;
- m_statustext = L"Wireframe shown";
+ showStatusTextSimple("Wireframe shown");
} else {
flags.show_debug = false;
flags.show_profiler_graph = false;
draw_control->show_wireframe = false;
if (client->checkPrivilege("debug")) {
- m_statustext = L"Debug info, profiler graph, and wireframe hidden";
+ showStatusTextSimple("Debug info, profiler graph, and wireframe hidden");
} else {
- m_statustext = L"Debug info and profiler graph hidden";
+ showStatusTextSimple("Debug info and profiler graph hidden");
}
}
runData.statustext_time = 0;
void Game::toggleUpdateCamera()
{
- static const wchar_t *msg[] = {
- L"Camera update enabled",
- L"Camera update disabled"
- };
-
flags.disable_camera_update = !flags.disable_camera_update;
runData.statustext_time = 0;
- m_statustext = msg[flags.disable_camera_update];
+ if (flags.disable_camera_update)
+ showStatusTextSimple("Camera update disabled");
+ else
+ showStatusTextSimple("Camera update enabled");
}
runData.profiler_max_page, driver->getScreenSize().Height);
if (runData.profiler_current_page != 0) {
- std::wstringstream sstr;
- sstr << "Profiler shown (page " << runData.profiler_current_page
- << " of " << runData.profiler_max_page << ")";
- m_statustext = sstr.str();
+ wchar_t buf[255];
+ const wchar_t* str = wgettext("Profiler shown (page %d of %d)");
+ swprintf(buf, sizeof(buf) / sizeof(wchar_t), str,
+ runData.profiler_current_page,
+ runData.profiler_max_page);
+ delete[] str;
+ m_statustext = buf;
} else {
- m_statustext = L"Profiler hidden";
+ showStatusTextSimple("Profiler hidden");
}
runData.statustext_time = 0;
}
s16 range = g_settings->getS16("viewing_range");
s16 range_new = range + 10;
+ wchar_t buf[255];
+ const wchar_t *str;
if (range_new > 4000) {
range_new = 4000;
- m_statustext = utf8_to_wide("Viewing range is at maximum: "
- + itos(range_new));
+ str = wgettext("Viewing range is at maximum: %d");
+ swprintf(buf, sizeof(buf) / sizeof(wchar_t), str, range_new);
+ delete[] str;
+ m_statustext = buf;
+
} else {
- m_statustext = utf8_to_wide("Viewing range changed to "
- + itos(range_new));
+ str = wgettext("Viewing range changed to %d");
+ swprintf(buf, sizeof(buf) / sizeof(wchar_t), str, range_new);
+ delete[] str;
+ m_statustext = buf;
}
g_settings->set("viewing_range", itos(range_new));
runData.statustext_time = 0;
s16 range = g_settings->getS16("viewing_range");
s16 range_new = range - 10;
+ wchar_t buf[255];
+ const wchar_t *str;
if (range_new < 20) {
range_new = 20;
- m_statustext = utf8_to_wide("Viewing range is at minimum: "
- + itos(range_new));
+ str = wgettext("Viewing range is at minimum: %d");
+ swprintf(buf, sizeof(buf) / sizeof(wchar_t), str, range_new);
+ delete[] str;
+ m_statustext = buf;
} else {
- m_statustext = utf8_to_wide("Viewing range changed to "
- + itos(range_new));
+ str = wgettext("Viewing range changed to %d");
+ swprintf(buf, sizeof(buf) / sizeof(wchar_t), str, range_new);
+ delete[] str;
+ m_statustext = buf;
}
g_settings->set("viewing_range", itos(range_new));
runData.statustext_time = 0;
void Game::toggleFullViewRange()
{
- static const wchar_t *msg[] = {
- L"Disabled full viewing range",
- L"Enabled full viewing range"
- };
-
draw_control->range_all = !draw_control->range_all;
- infostream << msg[draw_control->range_all] << std::endl;
- m_statustext = msg[draw_control->range_all];
runData.statustext_time = 0;
+ if (draw_control->range_all)
+ showStatusTextSimple("Enabled unlimited viewing range");
+ else
+ showStatusTextSimple("Disabled unlimited viewing range");
}
}
}
+const ClientEventHandler Game::clientEventHandler[CLIENTEVENT_MAX] = {
+ {&Game::handleClientEvent_None},
+ {&Game::handleClientEvent_PlayerDamage},
+ {&Game::handleClientEvent_PlayerForceMove},
+ {&Game::handleClientEvent_Deathscreen},
+ {&Game::handleClientEvent_ShowFormSpec},
+ {&Game::handleClientEvent_ShowLocalFormSpec},
+ {&Game::handleClientEvent_HandleParticleEvent},
+ {&Game::handleClientEvent_HandleParticleEvent},
+ {&Game::handleClientEvent_HandleParticleEvent},
+ {&Game::handleClientEvent_HudAdd},
+ {&Game::handleClientEvent_HudRemove},
+ {&Game::handleClientEvent_HudChange},
+ {&Game::handleClientEvent_SetSky},
+ {&Game::handleClientEvent_OverrideDayNigthRatio},
+ {&Game::handleClientEvent_CloudParams},
+};
-void Game::processClientEvents(CameraOrientation *cam)
+void Game::handleClientEvent_None(ClientEvent *event, CameraOrientation *cam)
{
- LocalPlayer *player = client->getEnv().getLocalPlayer();
-
- while (client->hasClientEvents()) {
- ClientEvent event = client->getClientEvent();
-
- switch (event.type) {
- case CE_PLAYER_DAMAGE:
- if (client->getHP() == 0)
- break;
- if (client->moddingEnabled()) {
- client->getScript()->on_damage_taken(event.player_damage.amount);
- }
-
- runData.damage_flash += 95.0 + 3.2 * event.player_damage.amount;
- runData.damage_flash = MYMIN(runData.damage_flash, 127.0);
-
- player->hurt_tilt_timer = 1.5;
- player->hurt_tilt_strength =
- rangelim(event.player_damage.amount / 4, 1.0, 4.0);
+ FATAL_ERROR("ClientEvent type None received");
+}
- client->event()->put(new SimpleTriggerEvent("PlayerDamage"));
- break;
+void Game::handleClientEvent_PlayerDamage(ClientEvent *event, CameraOrientation *cam)
+{
+ if (client->getHP() == 0)
+ return;
- case CE_PLAYER_FORCE_MOVE:
- cam->camera_yaw = event.player_force_move.yaw;
- cam->camera_pitch = event.player_force_move.pitch;
- break;
+ if (client->moddingEnabled()) {
+ client->getScript()->on_damage_taken(event->player_damage.amount);
+ }
- case CE_DEATHSCREEN:
- // This should be enabled for death formspec in builtin
- client->getScript()->on_death();
+ runData.damage_flash += 95.0 + 3.2 * event->player_damage.amount;
+ runData.damage_flash = MYMIN(runData.damage_flash, 127.0);
- /* Handle visualization */
- runData.damage_flash = 0;
- player->hurt_tilt_timer = 0;
- player->hurt_tilt_strength = 0;
- break;
+ LocalPlayer *player = client->getEnv().getLocalPlayer();
- case CE_SHOW_FORMSPEC:
- if (*(event.show_formspec.formspec) == "") {
- if (current_formspec && ( *(event.show_formspec.formname) == "" || *(event.show_formspec.formname) == cur_formname) ){
- current_formspec->quitMenu();
- }
- } else {
- FormspecFormSource *fs_src =
- new FormspecFormSource(*(event.show_formspec.formspec));
- TextDestPlayerInventory *txt_dst =
- new TextDestPlayerInventory(client, *(event.show_formspec.formname));
-
- create_formspec_menu(¤t_formspec, client, &input->joystick,
- fs_src, txt_dst);
- cur_formname = *(event.show_formspec.formname);
- }
+ player->hurt_tilt_timer = 1.5;
+ player->hurt_tilt_strength =
+ rangelim(event->player_damage.amount / 4, 1.0, 4.0);
- delete event.show_formspec.formspec;
- delete event.show_formspec.formname;
- break;
+ client->event()->put(new SimpleTriggerEvent("PlayerDamage"));
+}
- case CE_SHOW_LOCAL_FORMSPEC:
- {
- FormspecFormSource *fs_src = new FormspecFormSource(*event.show_formspec.formspec);
- LocalFormspecHandler *txt_dst = new LocalFormspecHandler(*event.show_formspec.formname, client);
- create_formspec_menu(¤t_formspec, client, &input->joystick,
- fs_src, txt_dst);
- }
- delete event.show_formspec.formspec;
- delete event.show_formspec.formname;
- break;
+void Game::handleClientEvent_PlayerForceMove(ClientEvent *event, CameraOrientation *cam)
+{
+ cam->camera_yaw = event->player_force_move.yaw;
+ cam->camera_pitch = event->player_force_move.pitch;
+}
- case CE_SPAWN_PARTICLE:
- case CE_ADD_PARTICLESPAWNER:
- case CE_DELETE_PARTICLESPAWNER:
- client->getParticleManager()->handleParticleEvent(&event, client, player);
- break;
+void Game::handleClientEvent_Deathscreen(ClientEvent *event, CameraOrientation *cam)
+{
+ // This should be enabled for death formspec in builtin
+ client->getScript()->on_death();
- case CE_HUDADD:
- {
- u32 id = event.hudadd.id;
-
- HudElement *e = player->getHud(id);
-
- if (e != NULL) {
- delete event.hudadd.pos;
- delete event.hudadd.name;
- delete event.hudadd.scale;
- delete event.hudadd.text;
- delete event.hudadd.align;
- delete event.hudadd.offset;
- delete event.hudadd.world_pos;
- delete event.hudadd.size;
- continue;
- }
+ LocalPlayer *player = client->getEnv().getLocalPlayer();
- e = new HudElement;
- e->type = (HudElementType)event.hudadd.type;
- e->pos = *event.hudadd.pos;
- e->name = *event.hudadd.name;
- e->scale = *event.hudadd.scale;
- e->text = *event.hudadd.text;
- e->number = event.hudadd.number;
- e->item = event.hudadd.item;
- e->dir = event.hudadd.dir;
- e->align = *event.hudadd.align;
- e->offset = *event.hudadd.offset;
- e->world_pos = *event.hudadd.world_pos;
- e->size = *event.hudadd.size;
-
- u32 new_id = player->addHud(e);
- //if this isn't true our huds aren't consistent
- sanity_check(new_id == id);
- }
+ /* Handle visualization */
+ runData.damage_flash = 0;
+ player->hurt_tilt_timer = 0;
+ player->hurt_tilt_strength = 0;
+}
- delete event.hudadd.pos;
- delete event.hudadd.name;
- delete event.hudadd.scale;
- delete event.hudadd.text;
- delete event.hudadd.align;
- delete event.hudadd.offset;
- delete event.hudadd.world_pos;
- delete event.hudadd.size;
- break;
+void Game::handleClientEvent_ShowFormSpec(ClientEvent *event, CameraOrientation *cam)
+{
+ if (event->show_formspec.formspec->empty()) {
+ if (current_formspec && (event->show_formspec.formname->empty()
+ || *(event->show_formspec.formname) == cur_formname)) {
+ current_formspec->quitMenu();
+ }
+ } else {
+ FormspecFormSource *fs_src =
+ new FormspecFormSource(*(event->show_formspec.formspec));
+ TextDestPlayerInventory *txt_dst =
+ new TextDestPlayerInventory(client, *(event->show_formspec.formname));
- case CE_HUDRM:
- {
- HudElement *e = player->removeHud(event.hudrm.id);
+ create_formspec_menu(¤t_formspec, client, &input->joystick,
+ fs_src, txt_dst);
+ cur_formname = *(event->show_formspec.formname);
+ }
- delete e;
- }
- break;
+ delete event->show_formspec.formspec;
+ delete event->show_formspec.formname;
+}
- case CE_HUDCHANGE:
- {
- u32 id = event.hudchange.id;
- HudElement *e = player->getHud(id);
+void Game::handleClientEvent_ShowLocalFormSpec(ClientEvent *event, CameraOrientation *cam)
+{
+ FormspecFormSource *fs_src = new FormspecFormSource(*event->show_formspec.formspec);
+ LocalFormspecHandler *txt_dst =
+ new LocalFormspecHandler(*event->show_formspec.formname, client);
+ create_formspec_menu(¤t_formspec, client, &input->joystick, fs_src, txt_dst);
- if (e == NULL) {
- delete event.hudchange.v3fdata;
- delete event.hudchange.v2fdata;
- delete event.hudchange.sdata;
- delete event.hudchange.v2s32data;
- continue;
- }
+ delete event->show_formspec.formspec;
+ delete event->show_formspec.formname;
+}
- switch (event.hudchange.stat) {
- case HUD_STAT_POS:
- e->pos = *event.hudchange.v2fdata;
- break;
+void Game::handleClientEvent_HandleParticleEvent(ClientEvent *event,
+ CameraOrientation *cam)
+{
+ LocalPlayer *player = client->getEnv().getLocalPlayer();
+ client->getParticleManager()->handleParticleEvent(event, client, player);
+}
- case HUD_STAT_NAME:
- e->name = *event.hudchange.sdata;
- break;
+void Game::handleClientEvent_HudAdd(ClientEvent *event, CameraOrientation *cam)
+{
+ LocalPlayer *player = client->getEnv().getLocalPlayer();
- case HUD_STAT_SCALE:
- e->scale = *event.hudchange.v2fdata;
- break;
+ u32 id = event->hudadd.id;
- case HUD_STAT_TEXT:
- e->text = *event.hudchange.sdata;
- break;
+ HudElement *e = player->getHud(id);
- case HUD_STAT_NUMBER:
- e->number = event.hudchange.data;
- break;
+ if (e != NULL) {
+ delete event->hudadd.pos;
+ delete event->hudadd.name;
+ delete event->hudadd.scale;
+ delete event->hudadd.text;
+ delete event->hudadd.align;
+ delete event->hudadd.offset;
+ delete event->hudadd.world_pos;
+ delete event->hudadd.size;
+ return;
+ }
- case HUD_STAT_ITEM:
- e->item = event.hudchange.data;
- break;
+ e = new HudElement;
+ e->type = (HudElementType)event->hudadd.type;
+ e->pos = *event->hudadd.pos;
+ e->name = *event->hudadd.name;
+ e->scale = *event->hudadd.scale;
+ e->text = *event->hudadd.text;
+ e->number = event->hudadd.number;
+ e->item = event->hudadd.item;
+ e->dir = event->hudadd.dir;
+ e->align = *event->hudadd.align;
+ e->offset = *event->hudadd.offset;
+ e->world_pos = *event->hudadd.world_pos;
+ e->size = *event->hudadd.size;
+
+ u32 new_id = player->addHud(e);
+ //if this isn't true our huds aren't consistent
+ sanity_check(new_id == id);
+
+ delete event->hudadd.pos;
+ delete event->hudadd.name;
+ delete event->hudadd.scale;
+ delete event->hudadd.text;
+ delete event->hudadd.align;
+ delete event->hudadd.offset;
+ delete event->hudadd.world_pos;
+ delete event->hudadd.size;
+}
- case HUD_STAT_DIR:
- e->dir = event.hudchange.data;
- break;
+void Game::handleClientEvent_HudRemove(ClientEvent *event, CameraOrientation *cam)
+{
+ LocalPlayer *player = client->getEnv().getLocalPlayer();
+ HudElement *e = player->removeHud(event->hudrm.id);
+ delete e;
+}
- case HUD_STAT_ALIGN:
- e->align = *event.hudchange.v2fdata;
- break;
+void Game::handleClientEvent_HudChange(ClientEvent *event, CameraOrientation *cam)
+{
+ LocalPlayer *player = client->getEnv().getLocalPlayer();
- case HUD_STAT_OFFSET:
- e->offset = *event.hudchange.v2fdata;
- break;
+ u32 id = event->hudchange.id;
+ HudElement *e = player->getHud(id);
- case HUD_STAT_WORLD_POS:
- e->world_pos = *event.hudchange.v3fdata;
- break;
+ if (e == NULL) {
+ delete event->hudchange.v3fdata;
+ delete event->hudchange.v2fdata;
+ delete event->hudchange.sdata;
+ delete event->hudchange.v2s32data;
+ return;
+ }
- case HUD_STAT_SIZE:
- e->size = *event.hudchange.v2s32data;
- break;
- }
- }
+ switch (event->hudchange.stat) {
+ case HUD_STAT_POS:
+ e->pos = *event->hudchange.v2fdata;
+ break;
- delete event.hudchange.v3fdata;
- delete event.hudchange.v2fdata;
- delete event.hudchange.sdata;
- delete event.hudchange.v2s32data;
+ case HUD_STAT_NAME:
+ e->name = *event->hudchange.sdata;
break;
- case CE_SET_SKY:
- sky->setVisible(false);
- // Whether clouds are visible in front of a custom skybox
- sky->setCloudsEnabled(event.set_sky.clouds);
+ case HUD_STAT_SCALE:
+ e->scale = *event->hudchange.v2fdata;
+ break;
- if (skybox) {
- skybox->remove();
- skybox = NULL;
- }
+ case HUD_STAT_TEXT:
+ e->text = *event->hudchange.sdata;
+ break;
- // Handle according to type
- if (*event.set_sky.type == "regular") {
- sky->setVisible(true);
- sky->setCloudsEnabled(true);
- } else if (*event.set_sky.type == "skybox" &&
- event.set_sky.params->size() == 6) {
- sky->setFallbackBgColor(*event.set_sky.bgcolor);
- skybox = RenderingEngine::get_scene_manager()->addSkyBoxSceneNode(
- texture_src->getTextureForMesh((*event.set_sky.params)[0]),
- texture_src->getTextureForMesh((*event.set_sky.params)[1]),
- texture_src->getTextureForMesh((*event.set_sky.params)[2]),
- texture_src->getTextureForMesh((*event.set_sky.params)[3]),
- texture_src->getTextureForMesh((*event.set_sky.params)[4]),
- texture_src->getTextureForMesh((*event.set_sky.params)[5]));
- }
- // Handle everything else as plain color
- else {
- if (*event.set_sky.type != "plain")
- infostream << "Unknown sky type: "
- << (*event.set_sky.type) << std::endl;
+ case HUD_STAT_NUMBER:
+ e->number = event->hudchange.data;
+ break;
- sky->setFallbackBgColor(*event.set_sky.bgcolor);
- }
+ case HUD_STAT_ITEM:
+ e->item = event->hudchange.data;
+ break;
- delete event.set_sky.bgcolor;
- delete event.set_sky.type;
- delete event.set_sky.params;
+ case HUD_STAT_DIR:
+ e->dir = event->hudchange.data;
break;
- case CE_OVERRIDE_DAY_NIGHT_RATIO:
- client->getEnv().setDayNightRatioOverride(
- event.override_day_night_ratio.do_override,
- event.override_day_night_ratio.ratio_f * 1000);
+ case HUD_STAT_ALIGN:
+ e->align = *event->hudchange.v2fdata;
break;
- case CE_CLOUD_PARAMS:
- if (clouds) {
- clouds->setDensity(event.cloud_params.density);
- clouds->setColorBright(video::SColor(event.cloud_params.color_bright));
- clouds->setColorAmbient(video::SColor(event.cloud_params.color_ambient));
- clouds->setHeight(event.cloud_params.height);
- clouds->setThickness(event.cloud_params.thickness);
- clouds->setSpeed(v2f(
- event.cloud_params.speed_x,
- event.cloud_params.speed_y));
- }
+ case HUD_STAT_OFFSET:
+ e->offset = *event->hudchange.v2fdata;
break;
- default:
- // unknown or unhandled type
+ case HUD_STAT_WORLD_POS:
+ e->world_pos = *event->hudchange.v3fdata;
break;
- }
+ case HUD_STAT_SIZE:
+ e->size = *event->hudchange.v2s32data;
+ break;
}
+
+ delete event->hudchange.v3fdata;
+ delete event->hudchange.v2fdata;
+ delete event->hudchange.sdata;
+ delete event->hudchange.v2s32data;
+}
+
+void Game::handleClientEvent_SetSky(ClientEvent *event, CameraOrientation *cam)
+{
+ sky->setVisible(false);
+ // Whether clouds are visible in front of a custom skybox
+ sky->setCloudsEnabled(event->set_sky.clouds);
+
+ if (skybox) {
+ skybox->remove();
+ skybox = NULL;
+ }
+
+ // Handle according to type
+ if (*event->set_sky.type == "regular") {
+ sky->setVisible(true);
+ sky->setCloudsEnabled(true);
+ } else if (*event->set_sky.type == "skybox" &&
+ event->set_sky.params->size() == 6) {
+ sky->setFallbackBgColor(*event->set_sky.bgcolor);
+ skybox = RenderingEngine::get_scene_manager()->addSkyBoxSceneNode(
+ texture_src->getTextureForMesh((*event->set_sky.params)[0]),
+ texture_src->getTextureForMesh((*event->set_sky.params)[1]),
+ texture_src->getTextureForMesh((*event->set_sky.params)[2]),
+ texture_src->getTextureForMesh((*event->set_sky.params)[3]),
+ texture_src->getTextureForMesh((*event->set_sky.params)[4]),
+ texture_src->getTextureForMesh((*event->set_sky.params)[5]));
+ }
+ // Handle everything else as plain color
+ else {
+ if (*event->set_sky.type != "plain")
+ infostream << "Unknown sky type: "
+ << (*event->set_sky.type) << std::endl;
+
+ sky->setFallbackBgColor(*event->set_sky.bgcolor);
+ }
+
+ delete event->set_sky.bgcolor;
+ delete event->set_sky.type;
+ delete event->set_sky.params;
}
+void Game::handleClientEvent_OverrideDayNigthRatio(ClientEvent *event,
+ CameraOrientation *cam)
+{
+ client->getEnv().setDayNightRatioOverride(
+ event->override_day_night_ratio.do_override,
+ event->override_day_night_ratio.ratio_f * 1000.0f);
+}
+
+void Game::handleClientEvent_CloudParams(ClientEvent *event, CameraOrientation *cam)
+{
+ if (!clouds)
+ return;
+
+ clouds->setDensity(event->cloud_params.density);
+ clouds->setColorBright(video::SColor(event->cloud_params.color_bright));
+ clouds->setColorAmbient(video::SColor(event->cloud_params.color_ambient));
+ clouds->setHeight(event->cloud_params.height);
+ clouds->setThickness(event->cloud_params.thickness);
+ clouds->setSpeed(v2f(event->cloud_params.speed_x, event->cloud_params.speed_y));
+}
+
+void Game::processClientEvents(CameraOrientation *cam)
+{
+ while (client->hasClientEvents()) {
+ std::unique_ptr<ClientEvent> event(client->getClientEvent());
+ FATAL_ERROR_IF(event->type >= CLIENTEVENT_MAX, "Invalid clientevent type");
+ const ClientEventHandler& evHandler = clientEventHandler[event->type];
+ (this->*evHandler.handler)(event.get(), cam);
+ }
+}
void Game::updateCamera(u32 busy_time, f32 dtime)
{
float tool_reload_ratio = runData.time_from_last_punch / full_punch_interval;
tool_reload_ratio = MYMIN(tool_reload_ratio, 1.0);
- camera->update(player, dtime, busy_time / 1000.0f, tool_reload_ratio,
- client->getEnv());
+ camera->update(player, dtime, busy_time / 1000.0f, tool_reload_ratio);
camera->step(dtime);
v3f camera_position = camera->getPosition();
camera->getDirection(),
camera->getCameraNode()->getUpVector());
- // Check if volume is in the proper range, else fix it.
- float old_volume = g_settings->getFloat("sound_volume");
- float new_volume = rangelim(old_volume, 0.0f, 1.0f);
- sound->setListenerGain(new_volume);
+ bool mute_sound = g_settings->getBool("mute_sound");
+ if (mute_sound) {
+ sound->setListenerGain(0.0f);
+ } else {
+ // Check if volume is in the proper range, else fix it.
+ float old_volume = g_settings->getFloat("sound_volume");
+ float new_volume = rangelim(old_volume, 0.0f, 1.0f);
+ sound->setListenerGain(new_volume);
- if (old_volume != new_volume) {
- g_settings->setFloat("sound_volume", new_volume);
+ if (old_volume != new_volume) {
+ g_settings->setFloat("sound_volume", new_volume);
+ }
}
LocalPlayer *player = client->getEnv().getLocalPlayer();
if ((g_settings->getBool("touchtarget")) && (g_touchscreengui)) {
shootline = g_touchscreengui->getShootline();
+ // Scale shootline to the acual distance the player can reach
+ shootline.end = shootline.start
+ + shootline.getVector().normalize() * BS * d;
shootline.start += intToFloat(camera_offset, BS);
shootline.end += intToFloat(camera_offset, BS);
}
hud->updateSelectionMesh(camera_offset);
}
+ if (runData.digging_blocked && !isLeftPressed()) {
+ // allow digging again if button is not pressed
+ runData.digging_blocked = false;
+ }
+
/*
Stop digging when
- releasing left mouse button
soundmaker->m_player_leftpunch_sound.name = "";
- if (isRightPressed())
+ // Prepare for repeating, unless we're not supposed to
+ if (isRightPressed() && !g_settings->getBool("safe_dig_and_place"))
runData.repeat_rightclick_timer += dtime;
else
runData.repeat_rightclick_timer = 0;
}
// Update selection mesh light level and vertex colors
- if (selectionboxes->size() > 0) {
+ if (!selectionboxes->empty()) {
v3f pf = hud->getSelectionPos();
v3s16 p = floatToInt(pf, BS);
u16 node_light = getInteriorLight(n, -1, nodedef);
u16 light_level = node_light;
- for (u8 i = 0; i < 6; i++) {
- n = map.getNodeNoEx(p + g_6dirs[i]);
+ for (const v3s16 &dir : g_6dirs) {
+ n = map.getNodeNoEx(p + dir);
node_light = getInteriorLight(n, -1, nodedef);
if (node_light > light_level)
light_level = node_light;
ClientMap &map = client->getEnv().getClientMap();
if (runData.nodig_delay_timer <= 0.0 && isLeftPressed()
+ && !runData.digging_blocked
&& client->checkPrivilege("interact")) {
handleDigging(pointed, nodepos, playeritem_toolcap, dtime);
}
NodeMetadata *meta = map.getNodeMetadata(nodepos);
if (meta) {
- infotext = unescape_enriched(utf8_to_wide(meta->getString("infotext")));
+ infotext = unescape_translate(utf8_to_wide(meta->getString("infotext")));
} else {
MapNode n = map.getNodeNoEx(nodepos);
runData.repeat_rightclick_timer = 0;
infostream << "Ground right-clicked" << std::endl;
- if (meta && meta->getString("formspec") != "" && !random_input
+ if (meta && !meta->getString("formspec").empty() && !random_input
&& !isKeyDown(KeyType::SNEAK)) {
+ // Report right click to server
+ if (nodedef_manager->get(map.getNodeNoEx(nodepos)).rightclickable) {
+ client->interact(3, pointed);
+ }
+
infostream << "Launching custom inventory view" << std::endl;
InventoryLocation inventoryloc;
soundmaker->m_player_rightpunch_sound =
SimpleSoundSpec();
- if (playeritem_def.node_placement_prediction == "" ||
+ if (playeritem_def.node_placement_prediction.empty() ||
nodedef_manager->get(map.getNodeNoEx(nodepos)).rightclickable) {
client->interact(3, pointed); // Report to server
} else {
void Game::handlePointingAtObject(const PointedThing &pointed, const ItemStack &playeritem,
const v3f &player_position, bool show_debug)
{
- infotext = unescape_enriched(
+ infotext = unescape_translate(
utf8_to_wide(runData.selected_object->infoText()));
if (show_debug) {
- if (infotext != L"") {
+ if (!infotext.empty()) {
infotext += L"\n";
}
- infotext += unescape_enriched(utf8_to_wide(
- runData.selected_object->debugInfoText()));
+ infotext += utf8_to_wide(runData.selected_object->debugInfoText());
}
if (isLeftPressed()) {
if (m_cache_enable_particles) {
const ContentFeatures &features = client->getNodeDefManager()->get(n);
- client->getParticleManager()->addPunchingParticles(client,
+ client->getParticleManager()->addNodeParticle(client,
player, nodepos, n, features);
}
}
if (sound_dig.exists() && params.diggable) {
if (sound_dig.name == "__group") {
- if (params.main_group != "") {
+ if (!params.main_group.empty()) {
soundmaker->m_player_leftpunch_sound.gain = 0.5;
soundmaker->m_player_leftpunch_sound.name =
std::string("default_dig_") +
runData.dig_time = 0;
runData.digging = false;
+ // we successfully dug, now block it from repeating if we want to be safe
+ if (g_settings->getBool("safe_dig_and_place"))
+ runData.digging_blocked = true;
runData.nodig_delay_timer =
runData.dig_time_complete / (float)crack_animation_length;
client->getScript()->on_dignode(nodepos, wasnode)) {
return;
}
- client->removeNode(nodepos);
+
+ const ContentFeatures &f = client->ndef()->get(wasnode);
+ if (f.node_dig_prediction == "air") {
+ client->removeNode(nodepos);
+ } else if (!f.node_dig_prediction.empty()) {
+ content_t id;
+ bool found = client->ndef()->getId(f.node_dig_prediction, id);
+ if (found)
+ client->addNode(nodepos, id, true);
+ }
+ // implicit else: no prediction
}
client->interact(2, pointed);
.getInterpolated(video::SColor(255, 0, 0, 0), 0.9);
sky->overrideColors(clouds_dark, clouds->getColor());
sky->setBodiesVisible(false);
- runData.fog_range = 20.0f * BS;
+ runData.fog_range = std::fmin(runData.fog_range * 0.5f, 32.0f * BS);
// do not draw clouds after all
clouds->setVisible(false);
}
|| runData.update_draw_list_last_cam_dir.getDistanceFrom(camera_direction) > 0.2
|| m_camera_offset_changed) {
runData.update_draw_list_timer = 0;
- client->getEnv().getClientMap().updateDrawList(driver);
+ client->getEnv().getClientMap().updateDrawList();
runData.update_draw_list_last_cam_dir = camera_direction;
}
if (flags.show_debug) {
static float drawtime_avg = 0;
drawtime_avg = drawtime_avg * 0.95 + stats.drawtime * 0.05;
-
u16 fps = 1.0 / stats.dtime_jitter.avg;
std::ostringstream os(std::ios_base::binary);
os << std::fixed
<< PROJECT_NAME_C " " << g_version_hash
- << "; " << fps << " FPS"
- << ", (R: range_all=" << draw_control->range_all << ")"
+ << ", FPS = " << fps
+ << ", range_all = " << draw_control->range_all
<< std::setprecision(0)
<< ", drawtime = " << drawtime_avg << " ms"
<< std::setprecision(1)
<< ", dtime_jitter = "
<< (stats.dtime_jitter.max_fraction * 100.0) << " %"
<< std::setprecision(1)
- << ", v_range = " << draw_control->wanted_range
+ << ", view_range = " << draw_control->wanted_range
<< std::setprecision(3)
<< ", RTT = " << client->getRTT() << " s";
setStaticText(guitext, utf8_to_wide(os.str()).c_str());
if (flags.show_debug) {
std::ostringstream os(std::ios_base::binary);
os << std::setprecision(1) << std::fixed
- << "(" << (player_position.X / BS)
+ << "pos = (" << (player_position.X / BS)
<< ", " << (player_position.Y / BS)
<< ", " << (player_position.Z / BS)
- << ") (yaw=" << (wrapDegrees_0_360(cam.camera_yaw)) << "°"
+ << "), yaw = " << (wrapDegrees_0_360(cam.camera_yaw)) << "°"
<< " " << yawToDirectionString(cam.camera_yaw)
- << ") (seed = " << ((u64)client->getMapSeed())
- << ")";
-
- if (runData.pointed_old.type == POINTEDTHING_NODE) {
- ClientMap &map = client->getEnv().getClientMap();
- const INodeDefManager *nodedef = client->getNodeDefManager();
- MapNode n = map.getNodeNoEx(runData.pointed_old.node_undersurface);
- if (n.getContent() != CONTENT_IGNORE && nodedef->get(n).name != "unknown") {
- const ContentFeatures &features = nodedef->get(n);
- os << " (pointing_at = \"" << nodedef->get(n).name
- << "\", param1 = " << (u64) n.getParam1()
- << ", param2 = " << (u64) n.getParam2()
- << ", tiledef[0] = \"" << features.tiledef[0].name.c_str()
- << "\")";
- }
- }
-
+ << ", seed = " << ((u64)client->getMapSeed());
setStaticText(guitext2, utf8_to_wide(os.str()).c_str());
guitext2->setVisible(true);
+ } else {
+ guitext2->setVisible(false);
+ }
+ if (guitext2->isVisible()) {
core::rect<s32> rect(
5, 5 + g_fontengine->getTextHeight(),
screensize.X, 5 + g_fontengine->getTextHeight() * 2
);
guitext2->setRelativePosition(rect);
+ }
+
+ if (flags.show_debug && runData.pointed_old.type == POINTEDTHING_NODE) {
+ ClientMap &map = client->getEnv().getClientMap();
+ const INodeDefManager *nodedef = client->getNodeDefManager();
+ MapNode n = map.getNodeNoEx(runData.pointed_old.node_undersurface);
+
+ if (n.getContent() != CONTENT_IGNORE && nodedef->get(n).name != "unknown") {
+ std::ostringstream os(std::ios_base::binary);
+ os << "pointing_at = (" << nodedef->get(n).name
+ << ", param2 = " << (u64) n.getParam2()
+ << ")";
+ setStaticText(guitext3, utf8_to_wide(os.str()).c_str());
+ guitext3->setVisible(true);
+ } else {
+ guitext3->setVisible(false);
+ }
} else {
- guitext2->setVisible(false);
+ guitext3->setVisible(false);
+ }
+
+ if (guitext3->isVisible()) {
+ core::rect<s32> rect(
+ 5, 5 + g_fontengine->getTextHeight() * 2,
+ screensize.X, 5 + g_fontengine->getTextHeight() * 3
+ );
+ guitext3->setRelativePosition(rect);
}
- setStaticText(guitext_info, infotext.c_str());
+ setStaticText(guitext_info, translate_string(infotext).c_str());
guitext_info->setVisible(flags.show_hud && g_menumgr.menuCount() == 0);
float statustext_time_max = 1.5;
}
}
- setStaticText(guitext_status, m_statustext.c_str());
+ setStaticText(guitext_status, translate_string(m_statustext).c_str());
guitext_status->setVisible(!m_statustext.empty());
if (!m_statustext.empty()) {
delete[] wmsg;
}
+void Game::showStatusTextSimple(const char *msg)
+{
+ const wchar_t *wmsg = wgettext(msg);
+ m_statustext = wmsg;
+ delete[] wmsg;
+}
+
void Game::settingChangedCallback(const std::string &setting_name, void *data)
{
((Game *)data)->readSettings();
static const std::string mode = strgettext("- Mode: ");
if (!simple_singleplayer_mode) {
Address serverAddress = client->getServerAddress();
- if (address != "") {
+ if (!address.empty()) {
os << mode << strgettext("Remote server") << "\n"
<< strgettext("- Address: ") << address;
} else {
} else {
os << mode << strgettext("Singleplayer") << "\n";
}
- if (simple_singleplayer_mode || address == "") {
+ if (simple_singleplayer_mode || address.empty()) {
static const std::string on = strgettext("On");
static const std::string off = strgettext("Off");
const std::string &damage = g_settings->getBool("enable_damage") ? on : off;
<< strgettext("- Public: ") << announced << "\n";
std::string server_name = g_settings->get("server_name");
str_formspec_escape(server_name);
- if (announced == on && server_name != "")
+ if (announced == on && !server_name.empty())
os << strgettext("- Server Name: ") << server_name;
}