#include "nodemetadata.h"
#include "main.h" // For g_settings
#include "itemdef.h"
-#include "tile.h" // For TextureSource
+#include "client/tile.h" // For TextureSource
#include "shader.h" // For ShaderSource
#include "logoutputbuffer.h"
#include "subgame.h"
color(color)
{}
};
- std::list<Piece> m_log;
+ std::vector<Piece> m_log;
public:
u32 m_log_max_size;
{
std::map<std::string, Meta> m_meta;
- for (std::list<Piece>::const_iterator k = m_log.begin();
+ for (std::vector<Piece>::const_iterator k = m_log.begin();
k != m_log.end(); k++) {
const Piece &piece = *k;
float lastscaledvalue = 0.0;
bool lastscaledvalue_exists = false;
- for (std::list<Piece>::const_iterator j = m_log.begin();
+ for (std::vector<Piece>::const_iterator j = m_log.begin();
j != m_log.end(); j++) {
const Piece &piece = *j;
float value = 0;
bool m_fogEnabled;
public:
-
void onSettingsChange(const std::string &name)
{
if (name == "enable_fog")
m_client(client)
{
g_settings->registerChangedCallback("enable_fog", SettingsCallback, this);
+ m_fogEnabled = g_settings->getBool("enable_fog");
}
- ~GameGlobalShaderConstantSetter() {}
+ ~GameGlobalShaderConstantSetter()
+ {
+ g_settings->deregisterChangedCallback("enable_fog", SettingsCallback, this);
+ }
virtual void onSetConstants(video::IMaterialRendererServices *services,
bool is_highlevel)
}
}
+#ifdef __ANDROID__
#define SIZE_TAG "size[11,5.5]"
+#else
+#define SIZE_TAG "size[11,5.5,true]" // Fixed size on desktop
+#endif
static void show_chat_menu(GUIFormSpecMenu **cur_formspec,
InventoryManager *invmgr, IGameDef *gamedef,
std::string(FORMSPEC_VERSION_STRING) +
SIZE_TAG
"bgcolor[#320000b4;true]"
- "label[4.85,1.35;You died.]"
+ "label[4.85,1.35;" + gettext("You died.") + "]"
"button_exit[4,3;3,0.5;btn_respawn;" + gettext("Respawn") + "]"
;
os << "button_exit[4," << (ypos++) << ";3,0.5;btn_change_password;"
<< wide_to_narrow(wstrgettext("Change Password")) << "]";
}
-
+
#ifndef __ANDROID__
os << "button_exit[4," << (ypos++) << ";3,0.5;btn_sound;"
<< wide_to_narrow(wstrgettext("Sound Volume")) << "]";
LocalFormspecHandler *txt_dst = new LocalFormspecHandler("MT_PAUSE_MENU");
create_formspec_menu(cur_formspec, invmgr, gamedef, tsrc, device, fs_src, txt_dst, NULL);
-
+ (*cur_formspec)->setFocus(L"btn_continue");
(*cur_formspec)->doPause = true;
}
KEYMAP_ID_FREEMOVE,
KEYMAP_ID_FASTMOVE,
KEYMAP_ID_NOCLIP,
+ KEYMAP_ID_CINEMATIC,
KEYMAP_ID_SCREENSHOT,
KEYMAP_ID_TOGGLE_HUD,
KEYMAP_ID_TOGGLE_CHAT,
key[KEYMAP_ID_FREEMOVE] = getKeySetting("keymap_freemove");
key[KEYMAP_ID_FASTMOVE] = getKeySetting("keymap_fastmove");
key[KEYMAP_ID_NOCLIP] = getKeySetting("keymap_noclip");
+ key[KEYMAP_ID_CINEMATIC] = getKeySetting("keymap_cinematic");
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");
void toggleFreeMoveAlt(float *statustext_time, float *jump_timer);
void toggleFast(float *statustext_time);
void toggleNoClip(float *statustext_time);
+ void toggleCinematic(float *statustext_time);
void toggleChat(float *statustext_time, bool *flag);
void toggleHud(float *statustext_time, bool *flag);
// Misc
void limitFps(FpsControl *fps_timings, f32 *dtime);
- void showOverlayMessage(const char *msg, float dtime, int percent,
+ void showOverlayMessage(const wchar_t *msg, float dtime, int percent,
bool draw_clouds = true);
private:
{
ProfilerGraph graph;
RunStats stats = { 0 };
+ CameraOrientation cam_view_target = { 0 };
CameraOrientation cam_view = { 0 };
GameRunData runData = { 0 };
FpsControl draw_times = { 0 };
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);
+ updateCameraDirection(&cam_view_target, &flags);
+ float cam_smoothing = 0;
+ if (g_settings->getBool("cinematic"))
+ cam_smoothing = 1 - g_settings->getFloat("cinematic_camera_smoothing");
+ else
+ cam_smoothing = 1 - g_settings->getFloat("camera_smoothing");
+ cam_smoothing = rangelim(cam_smoothing, 0.01f, 1.0f);
+ cam_view.camera_yaw += (cam_view_target.camera_yaw -
+ cam_view.camera_yaw) * cam_smoothing;
+ cam_view.camera_pitch += (cam_view_target.camera_pitch -
+ cam_view.camera_pitch) * cam_smoothing;
updatePlayerControl(cam_view);
step(&dtime);
processClientEvents(&cam_view, &runData.damage_flash);
void Game::shutdown()
{
- showOverlayMessage("Shutting down...", 0, 0, false);
+ showOverlayMessage(wgettext("Shutting down..."), 0, 0, false);
if (clouds)
clouds->drop();
u16 port,
const SubgameSpec &gamespec)
{
- showOverlayMessage("Loading...", 0, 0);
+ showOverlayMessage(wgettext("Loading..."), 0, 0);
texture_src = createTextureSource(device);
shader_src = createShaderSource(device);
bool Game::createSingleplayerServer(const std::string map_dir,
const SubgameSpec &gamespec, u16 port, std::string *address)
{
- showOverlayMessage("Creating server...", 0, 5);
+ showOverlayMessage(wgettext("Creating server..."), 0, 5);
std::string bind_str = g_settings->get("bind_address");
Address bind_addr(0, 0, 0, 0, port);
try {
bind_addr.Resolve(bind_str.c_str());
- *address = bind_str;
} catch (ResolveError &e) {
infostream << "Resolving bind address \"" << bind_str
<< "\" failed: " << e.what()
const std::string &password, std::string *address, u16 port,
std::wstring *error_message)
{
- showOverlayMessage("Creating client...", 0, 10);
+ showOverlayMessage(wgettext("Creating client..."), 0, 10);
draw_control = new MapDrawControl;
if (!draw_control)
const std::string &password, std::string *address, u16 port,
bool *connect_ok, bool *aborted)
{
- showOverlayMessage("Resolving address...", 0, 15);
+ *connect_ok = false; // Let's not be overly optimistic
+ *aborted = false;
+ bool local_server_mode = false;
+
+ showOverlayMessage(wgettext("Resolving address..."), 0, 15);
Address connect_address(0, 0, 0, 0, port);
} else {
connect_address.setAddress(127, 0, 0, 1);
}
+ local_server_mode = true;
}
} catch (ResolveError &e) {
*error_message = L"Couldn't resolve address: " + narrow_to_wide(e.what());
}
client = new Client(device,
- playername.c_str(), password, simple_singleplayer_mode,
+ playername.c_str(), password,
*draw_control, texture_src, shader_src,
itemdef_manager, nodedef_manager, sound, eventmgr,
connect_address.isIPv6());
gamedef = client; // Client acts as our GameDef
-
infostream << "Connecting to server at ";
connect_address.print(&infostream);
infostream << std::endl;
- client->connect(connect_address);
-
+ client->connect(connect_address, *address,
+ simple_singleplayer_mode || local_server_mode);
/*
Wait for server to accept connection
}
// Update status
- showOverlayMessage("Connecting to server...", dtime, 20);
+ showOverlayMessage(wgettext("Connecting to server..."), dtime, 20);
}
} catch (con::PeerNotFoundException &e) {
// TODO: Should something be done here? At least an info/error
int progress = 25;
if (!client->itemdefReceived()) {
- wchar_t *text = wgettext("Item definitions...");
+ const wchar_t *text = wgettext("Item definitions...");
progress = 25;
draw_load_screen(text, device, guienv, dtime, progress);
delete[] text;
} else if (!client->nodedefReceived()) {
- wchar_t *text = wgettext("Node definitions...");
+ const wchar_t *text = wgettext("Node definitions...");
progress = 30;
draw_load_screen(text, device, guienv, dtime, progress);
delete[] text;
}
progress = 30 + client->mediaReceiveProgress() * 35 + 0.5;
- draw_load_screen(narrow_to_wide(message.str().c_str()), device,
+ draw_load_screen(narrow_to_wide(message.str()), device,
guienv, dtime, progress);
}
}
toggleFast(statustext_time);
} else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_NOCLIP])) {
toggleNoClip(statustext_time);
+ } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_CINEMATIC])) {
+ toggleCinematic(statustext_time);
} else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_SCREENSHOT])) {
client->makeScreenshot(device);
} else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_TOGGLE_HUD])) {
void Game::openInventory()
{
+ /*
+ * Don't permit to open inventory is CAO or player doesn't exists.
+ * This prevent showing an empty inventory at player load
+ */
+
+ LocalPlayer *player = client->getEnv().getLocalPlayer();
+ if (player == NULL || player->getCAO() == NULL)
+ return;
+
infostream << "the_game: " << "Launching inventory" << std::endl;
PlayerInventoryFormSource *fs_src = new PlayerInventoryFormSource(client);
statustext += L" (note: no 'noclip' privilege)";
}
+void Game::toggleCinematic(float *statustext_time)
+{
+ 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));
+
+ *statustext_time = 0;
+ statustext = msg[cinematic];
+}
+
void Game::toggleChat(float *statustext_time, bool *flag)
{
u32 new_id = player->addHud(e);
//if this isn't true our huds aren't consistent
- assert(new_id == id);
+ sanity_check(new_id == id);
delete event.hudadd.pos;
delete event.hudadd.name;
v3s16 old_camera_offset = camera->getOffset();
if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_CAMERA_MODE])) {
- camera->toggleCameraMode();
GenericCAO *playercao = player->getCAO();
- assert(playercao != NULL);
+ // If playercao not loaded, don't change camera
+ if (playercao == NULL)
+ return;
+
+ camera->toggleCameraMode();
playercao->setVisible(camera->getCameraMode() > CAMERA_MODE_FIRST);
}
}
+inline static const char *yawToDirectionString(int yaw)
+{
+ // NOTE: TODO: This can be done mathematically without the else/else-if
+ // cascade.
+
+ const char *player_direction;
+
+ yaw = wrapDegrees_0_360(yaw);
+
+ if (yaw >= 45 && yaw < 135)
+ player_direction = "West [-X]";
+ else if (yaw >= 135 && yaw < 225)
+ player_direction = "South [-Z]";
+ else if (yaw >= 225 && yaw < 315)
+ player_direction = "East [+X]";
+ else
+ player_direction = "North [+Z]";
+
+ return player_direction;
+}
+
+
void Game::updateGui(float *statustext_time, const RunStats &stats,
const GameRunData& runData, f32 dtime, const VolatileRunFlags &flags,
const CameraOrientation &cam)
<< ", " << (player_position.Y / BS)
<< ", " << (player_position.Z / BS)
<< ") (yaw=" << (wrapDegrees_0_360(cam.camera_yaw))
+ << " " << yawToDirectionString(cam.camera_yaw)
<< ") (seed = " << ((u64)client->getMapSeed())
<< ")";
fps_timings->last_time = time;
}
-
-void Game::showOverlayMessage(const char *msg, float dtime,
+// Note: This will free (using delete[])! \p msg. If you want to use it later,
+// pass a copy of it to this function
+// Note: \p msg must be allocated using new (not malloc())
+void Game::showOverlayMessage(const wchar_t *msg, float dtime,
int percent, bool draw_clouds)
{
- wchar_t *text = wgettext(msg);
- draw_load_screen(text, device, guienv, dtime, percent, draw_clouds);
- delete[] text;
+ draw_load_screen(msg, device, guienv, dtime, percent, draw_clouds);
+ delete[] msg;
}
errorstream << "ServerError: " << e.what() << std::endl;
} catch (ModError &e) {
errorstream << "ModError: " << e.what() << std::endl;
- error_message = narrow_to_wide(e.what()) + wgettext("\nCheck debug.txt for details.");
+ error_message = narrow_to_wide(e.what()) + wstrgettext("\nCheck debug.txt for details.");
}
}