#else
#include "client/sound.h"
#endif
+<<<<<<< HEAD
+=======
+/*
+ Text input system
+*/
+
+struct TextDestNodeMetadata : public TextDest
+{
+ TextDestNodeMetadata(v3s16 p, Client *client)
+ {
+ m_p = p;
+ m_client = client;
+ }
+ // This is deprecated I guess? -celeron55
+ void gotText(const std::wstring &text)
+ {
+ std::string ntext = wide_to_utf8(text);
+ infostream << "Submitting 'text' field of node at (" << m_p.X << ","
+ << m_p.Y << "," << m_p.Z << "): " << ntext << std::endl;
+ StringMap fields;
+ fields["text"] = ntext;
+ m_client->sendNodemetaFields(m_p, "", fields);
+ }
+ void gotText(const StringMap &fields)
+ {
+ m_client->sendNodemetaFields(m_p, "", fields);
+ }
+
+ v3s16 m_p;
+ Client *m_client;
+};
+
+struct TextDestPlayerInventory : public TextDest
+{
+ TextDestPlayerInventory(Client *client)
+ {
+ m_client = client;
+ m_formname = "";
+ }
+ TextDestPlayerInventory(Client *client, const std::string &formname)
+ {
+ m_client = client;
+ m_formname = formname;
+ }
+ void gotText(const StringMap &fields)
+ {
+ m_client->sendInventoryFields(m_formname, fields);
+ }
+
+ Client *m_client;
+};
+
+struct LocalFormspecHandler : public TextDest
+{
+ LocalFormspecHandler(const std::string &formname)
+ {
+ m_formname = formname;
+ }
+
+ LocalFormspecHandler(const std::string &formname, Client *client):
+ m_client(client)
+ {
+ m_formname = formname;
+ }
+
+ void gotText(const StringMap &fields)
+ {
+ if (m_formname == "MT_PAUSE_MENU") {
+ if (fields.find("btn_sound") != fields.end()) {
+ g_gamecallback->changeVolume();
+ return;
+ }
+
+ if (fields.find("btn_key_config") != fields.end()) {
+ g_gamecallback->keyConfig();
+ return;
+ }
+
+ if (fields.find("btn_exit_menu") != fields.end()) {
+ g_gamecallback->disconnect();
+ return;
+ }
+
+ if (fields.find("btn_exit_os") != fields.end()) {
+ g_gamecallback->exitToOS();
+#ifndef __ANDROID__
+ RenderingEngine::get_raw_device()->closeDevice();
+#endif
+ return;
+ }
+
+ if (fields.find("btn_change_password") != fields.end()) {
+ g_gamecallback->changePassword();
+ return;
+ }
+
+ return;
+ }
+
+ if (m_formname == "MT_DEATH_SCREEN") {
+ assert(m_client != 0);
+ m_client->sendRespawn();
+ return;
+ }
+
+ if (m_client->modsLoaded())
+ m_client->getScript()->on_formspec_input(m_formname, fields);
+ }
+
+ Client *m_client = nullptr;
+};
+
+/* Form update callback */
+
+class NodeMetadataFormSource: public IFormSource
+{
+public:
+ NodeMetadataFormSource(ClientMap *map, v3s16 p):
+ m_map(map),
+ m_p(p)
+ {
+ }
+ const std::string &getForm() const
+ {
+ static const std::string empty_string = "";
+ NodeMetadata *meta = m_map->getNodeMetadata(m_p);
+
+ if (!meta)
+ return empty_string;
+
+ return meta->getString("formspec");
+ }
+
+ virtual std::string resolveText(const std::string &str)
+ {
+ NodeMetadata *meta = m_map->getNodeMetadata(m_p);
+
+ if (!meta)
+ return str;
+
+ return meta->resolveString(str);
+ }
+
+ ClientMap *m_map;
+ v3s16 m_p;
+};
+
+class PlayerInventoryFormSource: public IFormSource
+{
+public:
+ PlayerInventoryFormSource(Client *client):
+ m_client(client)
+ {
+ }
+
+ const std::string &getForm() const
+ {
+ LocalPlayer *player = m_client->getEnv().getLocalPlayer();
+ return player->inventory_formspec;
+ }
+
+ Client *m_client;
+};
+
+class NodeDugEvent: public MtEvent
+{
+public:
+ v3s16 p;
+ MapNode n;
+
+ NodeDugEvent(v3s16 p, MapNode n):
+ p(p),
+ n(n)
+ {}
+ MtEvent::Type getType() const
+ {
+ return MtEvent::NODE_DUG;
+ }
+};
+
+class SoundMaker
+{
+ ISoundManager *m_sound;
+ const NodeDefManager *m_ndef;
+public:
+ bool makes_footstep_sound;
+ float m_player_step_timer;
+ float m_player_jump_timer;
+
+ SimpleSoundSpec m_player_step_sound;
+ SimpleSoundSpec m_player_leftpunch_sound;
+ SimpleSoundSpec m_player_rightpunch_sound;
+
+ SoundMaker(ISoundManager *sound, const NodeDefManager *ndef):
+ m_sound(sound),
+ m_ndef(ndef),
+ makes_footstep_sound(true),
+ m_player_step_timer(0.0f),
+ m_player_jump_timer(0.0f)
+ {
+ }
+
+ void playPlayerStep()
+ {
+ if (m_player_step_timer <= 0 && m_player_step_sound.exists()) {
+ m_player_step_timer = 0.03;
+ if (makes_footstep_sound)
+ m_sound->playSound(m_player_step_sound, false);
+ }
+ }
+
+ void playPlayerJump()
+ {
+ if (m_player_jump_timer <= 0.0f) {
+ m_player_jump_timer = 0.2f;
+ m_sound->playSound(SimpleSoundSpec("player_jump", 0.5f), false);
+ }
+ }
+
+ static void viewBobbingStep(MtEvent *e, void *data)
+ {
+ SoundMaker *sm = (SoundMaker *)data;
+ sm->playPlayerStep();
+ }
+
+ static void playerRegainGround(MtEvent *e, void *data)
+ {
+ SoundMaker *sm = (SoundMaker *)data;
+ sm->playPlayerStep();
+ }
+
+ static void playerJump(MtEvent *e, void *data)
+ {
+ SoundMaker *sm = (SoundMaker *)data;
+ sm->playPlayerJump();
+ }
+
+ static void cameraPunchLeft(MtEvent *e, void *data)
+ {
+ SoundMaker *sm = (SoundMaker *)data;
+ sm->m_sound->playSound(sm->m_player_leftpunch_sound, false);
+ }
+
+ static void cameraPunchRight(MtEvent *e, void *data)
+ {
+ SoundMaker *sm = (SoundMaker *)data;
+ sm->m_sound->playSound(sm->m_player_rightpunch_sound, false);
+ }
+
+ static void nodeDug(MtEvent *e, void *data)
+ {
+ SoundMaker *sm = (SoundMaker *)data;
+ NodeDugEvent *nde = (NodeDugEvent *)e;
+ sm->m_sound->playSound(sm->m_ndef->get(nde->n).sound_dug, false);
+ }
+
+ static void playerDamage(MtEvent *e, void *data)
+ {
+ SoundMaker *sm = (SoundMaker *)data;
+ sm->m_sound->playSound(SimpleSoundSpec("player_damage", 0.5), false);
+ }
+
+ static void playerFallingDamage(MtEvent *e, void *data)
+ {
+ SoundMaker *sm = (SoundMaker *)data;
+ sm->m_sound->playSound(SimpleSoundSpec("player_falling_damage", 0.5), false);
+ }
+
+ void registerReceiver(MtEventManager *mgr)
+ {
+ mgr->reg(MtEvent::VIEW_BOBBING_STEP, SoundMaker::viewBobbingStep, this);
+ mgr->reg(MtEvent::PLAYER_REGAIN_GROUND, SoundMaker::playerRegainGround, this);
+ mgr->reg(MtEvent::PLAYER_JUMP, SoundMaker::playerJump, this);
+ mgr->reg(MtEvent::CAMERA_PUNCH_LEFT, SoundMaker::cameraPunchLeft, this);
+ mgr->reg(MtEvent::CAMERA_PUNCH_RIGHT, SoundMaker::cameraPunchRight, this);
+ mgr->reg(MtEvent::NODE_DUG, SoundMaker::nodeDug, this);
+ mgr->reg(MtEvent::PLAYER_DAMAGE, SoundMaker::playerDamage, this);
+ mgr->reg(MtEvent::PLAYER_FALLING_DAMAGE, SoundMaker::playerFallingDamage, this);
+ }
+
+ void step(float dtime)
+ {
+ m_player_step_timer -= dtime;
+ m_player_jump_timer -= dtime;
+ }
+};
+
+// Locally stored sounds don't need to be preloaded because of this
+class GameOnDemandSoundFetcher: public OnDemandSoundFetcher
+{
+ std::set<std::string> m_fetched;
+private:
+ void paths_insert(std::set<std::string> &dst_paths,
+ const std::string &base,
+ const std::string &name)
+ {
+ dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".ogg");
+ dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".0.ogg");
+ dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".1.ogg");
+ dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".2.ogg");
+ dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".3.ogg");
+ dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".4.ogg");
+ dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".5.ogg");
+ dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".6.ogg");
+ dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".7.ogg");
+ dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".8.ogg");
+ dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".9.ogg");
+ }
+public:
+ void fetchSounds(const std::string &name,
+ std::set<std::string> &dst_paths,
+ std::set<std::string> &dst_datas)
+ {
+ if (m_fetched.count(name))
+ return;
+
+ m_fetched.insert(name);
+
+ paths_insert(dst_paths, porting::path_share, name);
+ paths_insert(dst_paths, porting::path_user, name);
+ }
+};
+
+
+// before 1.8 there isn't a "integer interface", only float
+#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8)
+typedef f32 SamplerLayer_t;
+#else
+typedef s32 SamplerLayer_t;
+#endif
+
+
+class GameGlobalShaderConstantSetter : public IShaderConstantSetter
+{
+ Sky *m_sky;
+ bool *m_force_fog_off;
+ f32 *m_fog_range;
+ bool m_fog_enabled;
+ CachedPixelShaderSetting<float, 4> m_sky_bg_color;
+ CachedPixelShaderSetting<float> m_fog_distance;
+ CachedVertexShaderSetting<float> m_animation_timer_vertex;
+ CachedPixelShaderSetting<float> m_animation_timer_pixel;
+ CachedPixelShaderSetting<float, 3> m_day_light;
+ CachedPixelShaderSetting<float, 4> m_star_color;
+ CachedPixelShaderSetting<float, 3> m_eye_position_pixel;
+ CachedVertexShaderSetting<float, 3> m_eye_position_vertex;
+ CachedPixelShaderSetting<float, 3> m_minimap_yaw;
+ CachedPixelShaderSetting<float, 3> m_camera_offset_pixel;
+ CachedPixelShaderSetting<float, 3> m_camera_offset_vertex;
+ CachedPixelShaderSetting<SamplerLayer_t> m_base_texture;
+ Client *m_client;
+
+public:
+ void onSettingsChange(const std::string &name)
+ {
+ if (name == "enable_fog")
+ m_fog_enabled = g_settings->getBool("enable_fog");
+ }
+
+ static void settingsCallback(const std::string &name, void *userdata)
+ {
+ reinterpret_cast<GameGlobalShaderConstantSetter*>(userdata)->onSettingsChange(name);
+ }
+
+ void setSky(Sky *sky) { m_sky = sky; }
+
+ GameGlobalShaderConstantSetter(Sky *sky, bool *force_fog_off,
+ f32 *fog_range, Client *client) :
+ m_sky(sky),
+ m_force_fog_off(force_fog_off),
+ m_fog_range(fog_range),
+ m_sky_bg_color("skyBgColor"),
+ m_fog_distance("fogDistance"),
+ m_animation_timer_vertex("animationTimer"),
+ m_animation_timer_pixel("animationTimer"),
+ m_day_light("dayLight"),
+ m_star_color("starColor"),
+ m_eye_position_pixel("eyePosition"),
+ m_eye_position_vertex("eyePosition"),
+ m_minimap_yaw("yawVec"),
+ m_camera_offset_pixel("cameraOffset"),
+ m_camera_offset_vertex("cameraOffset"),
+ m_base_texture("baseTexture"),
+ m_client(client)
+ {
+ g_settings->registerChangedCallback("enable_fog", settingsCallback, this);
+ m_fog_enabled = g_settings->getBool("enable_fog");
+ }
+
+ ~GameGlobalShaderConstantSetter()
+ {
+ g_settings->deregisterChangedCallback("enable_fog", settingsCallback, this);
+ }
+
+ void onSetConstants(video::IMaterialRendererServices *services) override
+ {
+ // Background color
+ video::SColor bgcolor = m_sky->getBgColor();
+ video::SColorf bgcolorf(bgcolor);
+ float bgcolorfa[4] = {
+ bgcolorf.r,
+ bgcolorf.g,
+ bgcolorf.b,
+ bgcolorf.a,
+ };
+ m_sky_bg_color.set(bgcolorfa, services);
+
+ // Fog distance
+ float fog_distance = 10000 * BS;
+
+ if (m_fog_enabled && !*m_force_fog_off)
+ fog_distance = *m_fog_range;
+
+ m_fog_distance.set(&fog_distance, services);
+
+ u32 daynight_ratio = (float)m_client->getEnv().getDayNightRatio();
+ video::SColorf sunlight;
+ get_sunlight_color(&sunlight, daynight_ratio);
+ float dnc[3] = {
+ sunlight.r,
+ sunlight.g,
+ sunlight.b };
+ m_day_light.set(dnc, services);
+
+ video::SColorf star_color = m_sky->getCurrentStarColor();
+ float clr[4] = {star_color.r, star_color.g, star_color.b, star_color.a};
+ m_star_color.set(clr, services);
+
+ u32 animation_timer = porting::getTimeMs() % 1000000;
+ float animation_timer_f = (float)animation_timer / 100000.f;
+ m_animation_timer_vertex.set(&animation_timer_f, services);
+ m_animation_timer_pixel.set(&animation_timer_f, services);
+
+ float eye_position_array[3];
+ v3f epos = m_client->getEnv().getLocalPlayer()->getEyePosition();
+#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8)
+ eye_position_array[0] = epos.X;
+ eye_position_array[1] = epos.Y;
+ eye_position_array[2] = epos.Z;
+#else
+ epos.getAs3Values(eye_position_array);
+#endif
+ m_eye_position_pixel.set(eye_position_array, services);
+ m_eye_position_vertex.set(eye_position_array, services);
+
+ if (m_client->getMinimap()) {
+ float minimap_yaw_array[3];
+ v3f minimap_yaw = m_client->getMinimap()->getYawVec();
+#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8)
+ minimap_yaw_array[0] = minimap_yaw.X;
+ minimap_yaw_array[1] = minimap_yaw.Y;
+ minimap_yaw_array[2] = minimap_yaw.Z;
+#else
+ minimap_yaw.getAs3Values(minimap_yaw_array);
+#endif
+ m_minimap_yaw.set(minimap_yaw_array, services);
+ }
+
+ float camera_offset_array[3];
+ v3f offset = intToFloat(m_client->getCamera()->getOffset(), BS);
+#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8)
+ camera_offset_array[0] = offset.X;
+ camera_offset_array[1] = offset.Y;
+ camera_offset_array[2] = offset.Z;
+#else
+ offset.getAs3Values(camera_offset_array);
+#endif
+ m_camera_offset_pixel.set(camera_offset_array, services);
+ m_camera_offset_vertex.set(camera_offset_array, services);
+
+ SamplerLayer_t base_tex = 0;
+ m_base_texture.set(&base_tex, services);
+ }
+};
+
+
+class GameGlobalShaderConstantSetterFactory : public IShaderConstantSetterFactory
+{
+ Sky *m_sky;
+ bool *m_force_fog_off;
+ f32 *m_fog_range;
+ Client *m_client;
+ std::vector<GameGlobalShaderConstantSetter *> created_nosky;
+public:
+ GameGlobalShaderConstantSetterFactory(bool *force_fog_off,
+ f32 *fog_range, Client *client) :
+ m_sky(NULL),
+ m_force_fog_off(force_fog_off),
+ m_fog_range(fog_range),
+ m_client(client)
+ {}
+
+ void setSky(Sky *sky) {
+ m_sky = sky;
+ for (GameGlobalShaderConstantSetter *ggscs : created_nosky) {
+ ggscs->setSky(m_sky);
+ }
+ created_nosky.clear();
+ }
+
+ virtual IShaderConstantSetter* create()
+ {
+ auto *scs = new GameGlobalShaderConstantSetter(
+ m_sky, m_force_fog_off, m_fog_range, m_client);
+ if (!m_sky)
+ created_nosky.push_back(scs);
+ return scs;
+ }
+};
+
+#ifdef __ANDROID__
+#define SIZE_TAG "size[11,5.5]"
+#else
+#define SIZE_TAG "size[11,5.5,true]" // Fixed size on desktop
+#endif
+
+/****************************************************************************
+ ****************************************************************************/
+
+const float object_hit_delay = 0.2;
+
+struct FpsControl {
+ u32 last_time, busy_time, sleep_time;
+};
+
+
+/* The reason the following structs are not anonymous structs within the
+ * class is that they are not used by the majority of member functions and
+ * many functions that do require objects of thse types do not modify them
+ * (so they can be passed as a const qualified parameter)
+ */
+
+struct GameRunData {
+ u16 dig_index;
+ u16 new_playeritem;
+ PointedThing pointed_old;
+ bool digging;
+ bool punching;
+ bool btn_down_for_dig;
+ bool dig_instantly;
+ bool digging_blocked;
+ bool reset_jump_timer;
+ float nodig_delay_timer;
+ float dig_time;
+ float dig_time_complete;
+ float repeat_place_timer;
+ float object_hit_delay_timer;
+ float time_from_last_punch;
+ ClientActiveObject *selected_object;
+
+ float jump_timer;
+ float damage_flash;
+ float update_draw_list_timer;
+
+ f32 fog_range;
+
+ v3f update_draw_list_last_cam_dir;
+
+ float time_of_day_smooth;
+};
+
+class Game;
+
+struct ClientEventHandler
+{
+ void (Game::*handler)(ClientEvent *, CameraOrientation *);
+};
+
+/****************************************************************************
+ THE GAME
+ ****************************************************************************/
+
+/* This is not intended to be a public class. If a public class becomes
+ * desirable then it may be better to create another 'wrapper' class that
+ * hides most of the stuff in this class (nothing in this class is required
+ * by any other file) but exposes the public methods/data only.
+ */
+class Game {
+public:
+ Game();
+ ~Game();
+
+ bool startup(bool *kill,
+ InputHandler *input,
+ const GameStartData &game_params,
+ std::string &error_message,
+ bool *reconnect,
+ ChatBackend *chat_backend);
+
+ void run();
+ void shutdown();
+
+protected:
+
+ void extendedResourceCleanup();
+
+ // Basic initialisation
+ bool init(const std::string &map_dir, const std::string &address,
+ u16 port, const SubgameSpec &gamespec);
+ bool initSound();
+ bool createSingleplayerServer(const std::string &map_dir,
+ const SubgameSpec &gamespec, u16 port);
+
+ // Client creation
+ bool createClient(const GameStartData &start_data);
+ bool initGui();
+
+ // Client connection
+ bool connectToServer(const GameStartData &start_data,
+ bool *connect_ok, bool *aborted);
+ bool getServerContent(bool *aborted);
+
+ // Main loop
+
+ void updateInteractTimers(f32 dtime);
+ bool checkConnection();
+ bool handleCallbacks();
+ void processQueues();
+ void updateProfilers(const RunStats &stats, const FpsControl &draw_times, f32 dtime);
+ void updateStats(RunStats *stats, const FpsControl &draw_times, f32 dtime);
+ void updateProfilerGraphs(ProfilerGraph *graph);
+
+ // Input related
+ void processUserInput(f32 dtime);
+ void processKeyInput();
+ void processItemSelection(u16 *new_playeritem);
+
+ void dropSelectedItem(bool single_item = false);
+ void openInventory();
+ void openConsole(float scale, const wchar_t *line=NULL);
+ void toggleFreeMove();
+ void toggleFreeMoveAlt();
+ void togglePitchMove();
+ void toggleFast();
+ void toggleNoClip();
+ void toggleCinematic();
+ void toggleAutoforward();
+
+ void toggleMinimap(bool shift_pressed);
+ void toggleFog();
+ void toggleDebug();
+ void toggleUpdateCamera();
+
+ void increaseViewRange();
+ void decreaseViewRange();
+ void toggleFullViewRange();
+ void checkZoomEnabled();
+
+ void updateCameraDirection(CameraOrientation *cam, float dtime);
+ void updateCameraOrientation(CameraOrientation *cam, float dtime);
+ void updatePlayerControl(const CameraOrientation &cam);
+ void step(f32 *dtime);
+ void processClientEvents(CameraOrientation *cam);
+ void updateCamera(u32 busy_time, f32 dtime);
+ void updateSound(f32 dtime);
+ void processPlayerInteraction(f32 dtime, bool show_hud, bool show_debug);
+ /*!
+ * Returns the object or node the player is pointing at.
+ * Also updates the selected thing in the Hud.
+ *
+ * @param[in] shootline the shootline, starting from
+ * the camera position. This also gives the maximal distance
+ * of the search.
+ * @param[in] liquids_pointable if false, liquids are ignored
+ * @param[in] look_for_object if false, objects are ignored
+ * @param[in] camera_offset offset of the camera
+ * @param[out] selected_object the selected object or
+ * NULL if not found
+ */
+ PointedThing updatePointedThing(
+ const core::line3d<f32> &shootline, bool liquids_pointable,
+ bool look_for_object, const v3s16 &camera_offset);
+ void handlePointingAtNothing(const ItemStack &playerItem);
+ void handlePointingAtNode(const PointedThing &pointed,
+ const ItemStack &selected_item, const ItemStack &hand_item, f32 dtime);
+ void handlePointingAtObject(const PointedThing &pointed, const ItemStack &playeritem,
+ const v3f &player_position, bool show_debug);
+ void handleDigging(const PointedThing &pointed, const v3s16 &nodepos,
+ const ItemStack &selected_item, const ItemStack &hand_item, f32 dtime);
+ void updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime,
+ const CameraOrientation &cam);
+
+ // Misc
+ void limitFps(FpsControl *fps_timings, f32 *dtime);
+
+ void showOverlayMessage(const char *msg, float dtime, int percent,
+ bool draw_clouds = true);
+
+ static void settingChangedCallback(const std::string &setting_name, void *data);
+ void readSettings();
+
+ inline bool isKeyDown(GameKeyType k)
+ {
+ return input->isKeyDown(k);
+ }
+ inline bool wasKeyDown(GameKeyType k)
+ {
+ return input->wasKeyDown(k);
+ }
+ inline bool wasKeyPressed(GameKeyType k)
+ {
+ return input->wasKeyPressed(k);
+ }
+ inline bool wasKeyReleased(GameKeyType k)
+ {
+ return input->wasKeyReleased(k);
+ }
+
+#ifdef __ANDROID__
+ void handleAndroidChatInput();
+#endif
+
+private:
+ struct Flags {
+ bool force_fog_off = false;
+ bool disable_camera_update = false;
+ };
+
+ void showDeathFormspec();
+ 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_SetSun(ClientEvent *event, CameraOrientation *cam);
+ void handleClientEvent_SetMoon(ClientEvent *event, CameraOrientation *cam);
+ void handleClientEvent_SetStars(ClientEvent *event, CameraOrientation *cam);
+ void handleClientEvent_OverrideDayNigthRatio(ClientEvent *event,
+ CameraOrientation *cam);
+ void handleClientEvent_CloudParams(ClientEvent *event, CameraOrientation *cam);
+
+ void updateChat(f32 dtime, const v2u32 &screensize);
+
+ bool nodePlacement(const ItemDefinition &selected_def, const ItemStack &selected_item,
+ const v3s16 &nodepos, const v3s16 &neighbourpos, const PointedThing &pointed,
+ const NodeMetadata *meta);
+ static const ClientEventHandler clientEventHandler[CLIENTEVENT_MAX];
+
+ InputHandler *input = nullptr;
+
+ Client *client = nullptr;
+ Server *server = nullptr;
+
+ IWritableTextureSource *texture_src = nullptr;
+ IWritableShaderSource *shader_src = nullptr;
+
+ // When created, these will be filled with data received from the server
+ IWritableItemDefManager *itemdef_manager = nullptr;
+ NodeDefManager *nodedef_manager = nullptr;
+
+ GameOnDemandSoundFetcher soundfetcher; // useful when testing
+ ISoundManager *sound = nullptr;
+ bool sound_is_dummy = false;
+ SoundMaker *soundmaker = nullptr;
+
+ ChatBackend *chat_backend = nullptr;
+ LogOutputBuffer m_chat_log_buf;
+
+ EventManager *eventmgr = nullptr;
+ QuicktuneShortcutter *quicktune = nullptr;
+ bool registration_confirmation_shown = false;
+
+ std::unique_ptr<GameUI> m_game_ui;
+ GUIChatConsole *gui_chat_console = nullptr; // Free using ->Drop()
+ MapDrawControl *draw_control = nullptr;
+ Camera *camera = nullptr;
+ Clouds *clouds = nullptr; // Free using ->Drop()
+ Sky *sky = nullptr; // Free using ->Drop()
+ Hud *hud = nullptr;
+ Minimap *mapper = nullptr;
+
+ GameRunData runData;
+ Flags m_flags;
+
+ /* 'cache'
+ This class does take ownership/responsibily for cleaning up etc of any of
+ these items (e.g. device)
+ */
+ IrrlichtDevice *device;
+ video::IVideoDriver *driver;
+ scene::ISceneManager *smgr;
+ bool *kill;
+ std::string *error_message;
+ bool *reconnect_requested;
+ scene::ISceneNode *skybox;
+
+ bool simple_singleplayer_mode;
+ /* End 'cache' */
+
+ /* Pre-calculated values
+ */
+ int crack_animation_length;
+
+ IntervalLimiter profiler_interval;
+
+ /*
+ * TODO: Local caching of settings is not optimal and should at some stage
+ * be updated to use a global settings object for getting thse values
+ * (as opposed to the this local caching). This can be addressed in
+ * a later release.
+ */
+ bool m_cache_doubletap_jump;
+ bool m_cache_enable_clouds;
+ bool m_cache_enable_joysticks;
+ bool m_cache_enable_particles;
+ bool m_cache_enable_fog;
+ bool m_cache_enable_noclip;
+ bool m_cache_enable_free_move;
+ f32 m_cache_mouse_sensitivity;
+ f32 m_cache_joystick_frustum_sensitivity;
+ f32 m_repeat_place_time;
+ f32 m_cache_cam_smoothing;
+ f32 m_cache_fog_start;
+
+ bool m_invert_mouse = false;
+ bool m_first_loop_after_window_activation = false;
+ bool m_camera_offset_changed = false;
+
+ bool m_does_lost_focus_pause_game = false;
+
+ int m_reset_HW_buffer_counter = 0;
+#ifdef __ANDROID__
+ bool m_cache_hold_aux1;
+ bool m_android_chat_open;
+#endif
+};
+>>>>>>> 9736b9cea5f841bb0e9bb2c9c05c3b2560327064
Game::Game() :
m_chat_log_buf(g_logger),