]> git.lizzy.rs Git - dragonfireclient.git/commitdiff
Merge branch 'master' of https://github.com/minetest/minetest
authorElias Fleckenstein <eliasfleckenstein@web.de>
Wed, 10 Feb 2021 18:50:36 +0000 (19:50 +0100)
committerElias Fleckenstein <eliasfleckenstein@web.de>
Wed, 10 Feb 2021 18:50:36 +0000 (19:50 +0100)
30 files changed:
1  2 
CMakeLists.txt
builtin/game/item.lua
builtin/mainmenu/dlg_contentstore.lua
builtin/mainmenu/init.lua
builtin/mainmenu/pkgmgr.lua
builtin/settingtypes.txt
doc/client_lua_api.txt
doc/lua_api.txt
po/minetest.pot
src/client/client.cpp
src/client/client.h
src/client/clientenvironment.cpp
src/client/game.cpp
src/client/game.h
src/client/gameui.h
src/client/mapblock_mesh.cpp
src/client/mapblock_mesh.h
src/client/mesh_generator_thread.h
src/client/renderingengine.cpp
src/defaultsettings.cpp
src/gui/guiInventoryList.cpp
src/gui/guiKeyChangeMenu.cpp
src/map.cpp
src/map.h
src/nodedef.cpp
src/script/common/c_content.cpp
src/script/lua_api/l_mainmenu.cpp
src/script/lua_api/l_server.cpp
src/script/lua_api/l_util.cpp
src/unittest/test.cpp

diff --cc CMakeLists.txt
index a00a44ae2fcdbc0dbd02e68d30b8250d187dc99b,2549bd25d257ee8e9ce84bd723cb98c1d04b830e..1a5bd957403bc31cb3a2ba6a499349cfaf33061b
@@@ -1,8 -1,10 +1,10 @@@
  cmake_minimum_required(VERSION 3.5)
  
+ cmake_policy(SET CMP0025 OLD)
  # This can be read from ${PROJECT_NAME} after project() is called
  project(minetest)
 -set(PROJECT_NAME_CAPITALIZED "Minetest")
 +set(PROJECT_NAME_CAPITALIZED "Dragonfire")
  
  set(CMAKE_CXX_STANDARD 11)
  set(GCC_MINIMUM_VERSION "4.8")
Simple merge
index 32703a3b93a9c8e036356a0052b5afbb6ebf50b5,7328f33587eec49d615b6ddf7adc1a3d609dbcb2..b058e4824d1b3309760b1604b6bc012920cbc29c
@@@ -579,8 -582,8 +582,8 @@@ en
  function store.update_paths()
        local mod_hash = {}
        pkgmgr.refresh_globals()
 -      for _, mod in pairs(pkgmgr.global_mods:get_list()) do
 +      for _, mod in pairs(pkgmgr.clientmods:get_list()) do
-               if mod.author then
+               if mod.author and mod.release > 0 then
                        mod_hash[mod.author:lower() .. "/" .. mod.name] = mod
                end
        end
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc doc/lua_api.txt
Simple merge
diff --cc po/minetest.pot
index e544cbfebc5b4b346fd88833bd230cd454447b70,fedfbc75dd3c712efb70d6ea46b5fdbd5fd22a47..6988aca5916886c4092e7f594aa90a4073476dbd
@@@ -8,7 -8,7 +8,11 @@@ msgid "
  msgstr ""
  "Project-Id-Version: minetest\n"
  "Report-Msgid-Bugs-To: \n"
++<<<<<<< HEAD
 +"POT-Creation-Date: 2020-08-22 14:59+0200\n"
++=======
+ "POT-Creation-Date: 2021-01-30 21:13+0100\n"
++>>>>>>> 9736b9cea5f841bb0e9bb2c9c05c3b2560327064
  "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
  "Language-Team: LANGUAGE <LL@li.org>\n"
@@@ -1316,18 -1313,15 +1341,18 @@@ msgid "
  "- %s: move backwards\n"
  "- %s: move left\n"
  "- %s: move right\n"
- "- %s: jump/climb\n"
- "- %s: sneak/go down\n"
+ "- %s: jump/climb up\n"
+ "- %s: dig/punch\n"
+ "- %s: place/use\n"
+ "- %s: sneak/climb down\n"
  "- %s: drop item\n"
  "- %s: inventory\n"
 +"- %s: special inventory\n"
  "- Mouse: turn/look\n"
- "- Mouse left: dig/punch\n"
- "- Mouse right: place/use\n"
  "- Mouse wheel: select item\n"
  "- %s: chat\n"
 +"- %s: Killaura\n"
 +"- %s: Freecam\n"
  msgstr ""
  
  #: src/client/game.cpp
index 9bbb57668062eaf371c9e7164fdd5c22c8b7c030,ef4a3cdfc71dc2742e3a64a73fa6327c5dae36a8..f9ecb20c6f649288cb3075b7a9eb27b2deae7f6f
@@@ -1298,13 -1275,12 +1278,12 @@@ void Client::sendPlayerPos(v3f pos
        // Save bandwidth by only updating position when
        // player is not dead and something changed
  
-       // FIXME: This part causes breakages in mods like 3d_armor, and has been commented for now
-       // if (m_activeobjects_received && player->isDead())
-       //      return;
+       if (m_activeobjects_received && player->isDead())
+               return;
  
        if (
 -                      player->last_position     == player->getPosition() &&
 -                      player->last_speed        == player->getSpeed()    &&
 +                      player->last_position     == pos &&
 +                      player->last_speed        == player->getLegitSpeed()    &&
                        player->last_pitch        == player->getPitch()    &&
                        player->last_yaw          == player->getYaw()      &&
                        player->last_keyPressed   == player->keyPressed    &&
index 979636eba4b41eb78b37cffbc8ce5d035224ba9c,25a1b97ba1346b5f9cffa15642382e01a127f1d2..f7a9030bc02ff00c0a1bdeed0af22d1c57e5de98
@@@ -414,15 -412,9 +414,10 @@@ public
  
        inline bool checkCSMRestrictionFlag(CSMRestrictionFlags flag) const
        {
 -              return m_csm_restriction_flags & flag;
 +              //return m_csm_restriction_flags & flag;
 +              return false;
        }
  
-       u32 getCSMNodeRangeLimit() const
-       {
-               return m_csm_restriction_noderange;
-       }
        inline std::unordered_map<u32, u32> &getHUDTranslationMap()
        {
                return m_hud_server_to_client;
        {
                return m_env.getLocalPlayer()->formspec_prepend;
        }
 +      
 +      void sendPlayerPos(v3f pos);
 +      void sendPlayerPos();
 +      MeshUpdateThread m_mesh_update_thread;
 +      
  private:
        void loadMods();
-       bool checkBuiltinIntegrity();
  
        // Virtual methods from con::PeerHandler
        void peerAdded(con::Peer *peer) override;
Simple merge
index 10c3a7ceb30317d8b4f64c281c340b941d9f1c28,3c58fb46f41635f996dac3032a353437f4ab766f..6cf22debc632b35a2afb118329647728940f0e5c
@@@ -77,6 -77,840 +77,843 @@@ with this program; if not, write to th
  #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),
index fd93ef82d03711303f19a6cd3ed77cdacfb11471,d041532717640a8c1f4109377ca5ee0f297b9d82..af0b7ef543a23311218ef55e5237cb90b1cf2ba4
@@@ -94,836 -42,6 +94,830 @@@ struct CameraOrientation 
        f32 camera_pitch;  // "up/down"
  };
  
-                       if (fields.find("quit") != fields.end()) {
-                               return;
-                       }
-                       if (fields.find("btn_continue") != fields.end()) {
-                               return;
-                       }
 +/*
 +      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 *);
 +};
 +
 +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();
 +
 +      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 openEnderchest();
 +      void openConsole(float scale, const wchar_t *line=NULL);
 +      void toggleFreeMove();
 +      void toggleFreeMoveAlt();
 +      void togglePitchMove();
 +      void toggleFast();
 +      void toggleNoClip();
 +      void toggleKillaura();
 +      void toggleFreecam();
 +      void toggleScaffold();
 +      void toggleNextItem();
 +      void toggleCinematic();
 +      void toggleAutoforward();
 +
 +      void toggleMinimap(bool shift_pressed);
 +      void toggleFog();
 +      void toggleDebug();
 +      void toggleUpdateCamera();
 +      void updatePlayerCAOVisibility();
 +
 +      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 freecamChangedCallback(const std::string &setting_name, void *data);
 +      static void settingChangedCallback(const std::string &setting_name, void *data);
 +      static void updateAllMapBlocksCallback(const std::string &setting_name, void *data);
 +      void readSettings();
 +
 +      bool isKeyDown(GameKeyType k);
 +      bool wasKeyDown(GameKeyType k);
 +      bool wasKeyPressed(GameKeyType k);
 +      bool wasKeyReleased(GameKeyType k);
 +
 +#ifdef __ANDROID__
 +      void handleAndroidChatInput();
 +#endif
 +
 +      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()
 +      CheatMenu *m_cheat_menu = nullptr;
 +      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;
 +
 +      CameraOrientation cam_view_target  = { 0 };
 +      CameraOrientation cam_view  = { 0 };
 +
 +      int m_reset_HW_buffer_counter = 0;
 +#ifdef __ANDROID__
 +      bool m_cache_hold_aux1;
 +      bool m_android_chat_open;
 +#endif
 +};
 +extern Game *g_game;
  
  void the_game(bool *kill,
                InputHandler *input,
Simple merge
Simple merge
index 6f454d34852c801609303f648e0c3dc58af8fa43,3b17c4af9827c4539afb0530cdd0186a7b8433ab..80075fce242ed07c52fdf525249f96b1ff8aa70f
@@@ -125,10 -125,6 +125,8 @@@ public
                        m_animation_force_timer--;
        }
  
-       void updateCameraOffset(v3s16 camera_offset);
 +      std::set<v3s16> esp_nodes;
 +
  private:
        scene::IMesh *m_mesh[MAX_TILE_LAYERS];
        MinimapMapblock *m_minimap_mapblock;
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc src/map.cpp
Simple merge
diff --cc src/map.h
Simple merge
diff --cc src/nodedef.cpp
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge