]> git.lizzy.rs Git - dragonfireclient.git/blob - src/client/game.h
Merge branch 'master' of https://github.com/minetest/minetest
[dragonfireclient.git] / src / client / game.h
1 /*
2 Minetest
3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #pragma once
21
22 #include <iomanip>
23 #include <cmath>
24 #include "client/renderingengine.h"
25 #include "camera.h"
26 #include "client.h"
27 #include "client/clientevent.h"
28 //#include "client/gameui.h"
29 #include "client/inputhandler.h"
30 #include "client/sound.h"
31 #include "client/tile.h"     // For TextureSource
32 #include "client/keys.h"
33 #include "client/joystick_controller.h"
34 #include "clientmap.h"
35 #include "clouds.h"
36 #include "config.h"
37 #include "content_cao.h"
38 #include "client/event_manager.h"
39 #include "fontengine.h"
40 #include "itemdef.h"
41 #include "log.h"
42 #include "filesys.h"
43 #include "gettext.h"
44 #include "gui/cheatMenu.h"
45 #include "gui/guiChatConsole.h"
46 #include "gui/guiConfirmRegistration.h"
47 #include "gui/guiFormSpecMenu.h"
48 #include "gui/guiKeyChangeMenu.h"
49 #include "gui/guiPasswordChange.h"
50 #include "gui/guiVolumeChange.h"
51 #include "gui/mainmenumanager.h"
52 #include "gui/profilergraph.h"
53 #include "mapblock.h"
54 #include "minimap.h"
55 #include "nodedef.h"         // Needed for determining pointing to nodes
56 #include "nodemetadata.h"
57 #include "particles.h"
58 #include "porting.h"
59 #include "profiler.h"
60 #include "raycast.h"
61 #include "server.h"
62 #include "settings.h"
63 #include "shader.h"
64 #include "sky.h"
65 #include "translation.h"
66 #include "util/basic_macros.h"
67 #include "util/directiontables.h"
68 #include "util/pointedthing.h"
69 #include "util/quicktune_shortcutter.h"
70 #include "irrlicht_changes/static_text.h"
71 #include "irr_ptr.h"
72 #include "version.h"
73 #include "script/scripting_client.h"
74 #include "hud.h"
75 #include "irrlichttypes.h"
76 #include <string>
77
78 class InputHandler;
79 class ChatBackend;  /* to avoid having to include chat.h */
80 struct SubgameSpec;
81 struct GameStartData;
82
83 struct Jitter {
84         f32 max, min, avg, counter, max_sample, min_sample, max_fraction;
85 };
86
87 struct RunStats {
88         u32 drawtime;
89
90         Jitter dtime_jitter, busy_time_jitter;
91 };
92
93 struct CameraOrientation {
94         f32 camera_yaw;    // "right/left"
95         f32 camera_pitch;  // "up/down"
96 };
97
98 /*
99         Text input system
100 */
101
102 struct TextDestNodeMetadata : public TextDest
103 {
104         TextDestNodeMetadata(v3s16 p, Client *client)
105         {
106                 m_p = p;
107                 m_client = client;
108         }
109         // This is deprecated I guess? -celeron55
110         void gotText(const std::wstring &text)
111         {
112                 std::string ntext = wide_to_utf8(text);
113                 infostream << "Submitting 'text' field of node at (" << m_p.X << ","
114                            << m_p.Y << "," << m_p.Z << "): " << ntext << std::endl;
115                 StringMap fields;
116                 fields["text"] = ntext;
117                 m_client->sendNodemetaFields(m_p, "", fields);
118         }
119         void gotText(const StringMap &fields)
120         {
121                 m_client->sendNodemetaFields(m_p, "", fields);
122         }
123
124         v3s16 m_p;
125         Client *m_client;
126 };
127
128 struct TextDestPlayerInventory : public TextDest
129 {
130         TextDestPlayerInventory(Client *client)
131         {
132                 m_client = client;
133                 m_formname = "";
134         }
135         TextDestPlayerInventory(Client *client, const std::string &formname)
136         {
137                 m_client = client;
138                 m_formname = formname;
139         }
140         void gotText(const StringMap &fields)
141         {
142                 m_client->sendInventoryFields(m_formname, fields);
143         }
144
145         Client *m_client;
146 };
147
148 struct LocalFormspecHandler : public TextDest
149 {
150         LocalFormspecHandler(const std::string &formname)
151         {
152                 m_formname = formname;
153         }
154
155         LocalFormspecHandler(const std::string &formname, Client *client):
156                 m_client(client)
157         {
158                 m_formname = formname;
159         }
160
161         void gotText(const StringMap &fields)
162         {
163                 if (m_formname == "MT_PAUSE_MENU") {
164                         if (fields.find("btn_sound") != fields.end()) {
165                                 g_gamecallback->changeVolume();
166                                 return;
167                         }
168
169                         if (fields.find("btn_key_config") != fields.end()) {
170                                 g_gamecallback->keyConfig();
171                                 return;
172                         }
173
174                         if (fields.find("btn_exit_menu") != fields.end()) {
175                                 g_gamecallback->disconnect();
176                                 return;
177                         }
178
179                         if (fields.find("btn_exit_os") != fields.end()) {
180                                 g_gamecallback->exitToOS();
181 #ifndef __ANDROID__
182                                 RenderingEngine::get_raw_device()->closeDevice();
183 #endif
184                                 return;
185                         }
186
187                         if (fields.find("btn_change_password") != fields.end()) {
188                                 g_gamecallback->changePassword();
189                                 return;
190                         }
191
192                         return;
193                 }
194
195                 if (m_formname == "MT_DEATH_SCREEN") {
196                         assert(m_client != 0);
197                         m_client->sendRespawn();
198                         return;
199                 }
200
201                 if (m_client->modsLoaded())
202                         m_client->getScript()->on_formspec_input(m_formname, fields);
203         }
204
205         Client *m_client = nullptr;
206 };
207
208 /* Form update callback */
209
210 class NodeMetadataFormSource: public IFormSource
211 {
212 public:
213         NodeMetadataFormSource(ClientMap *map, v3s16 p):
214                 m_map(map),
215                 m_p(p)
216         {
217         }
218         const std::string &getForm() const
219         {
220                 static const std::string empty_string = "";
221                 NodeMetadata *meta = m_map->getNodeMetadata(m_p);
222
223                 if (!meta)
224                         return empty_string;
225
226                 return meta->getString("formspec");
227         }
228
229         virtual std::string resolveText(const std::string &str)
230         {
231                 NodeMetadata *meta = m_map->getNodeMetadata(m_p);
232
233                 if (!meta)
234                         return str;
235
236                 return meta->resolveString(str);
237         }
238
239         ClientMap *m_map;
240         v3s16 m_p;
241 };
242
243 class PlayerInventoryFormSource: public IFormSource
244 {
245 public:
246         PlayerInventoryFormSource(Client *client):
247                 m_client(client)
248         {
249         }
250
251         const std::string &getForm() const
252         {
253                 LocalPlayer *player = m_client->getEnv().getLocalPlayer();
254                 return player->inventory_formspec;
255         }
256
257         Client *m_client;
258 };
259
260 class NodeDugEvent: public MtEvent
261 {
262 public:
263         v3s16 p;
264         MapNode n;
265
266         NodeDugEvent(v3s16 p, MapNode n):
267                 p(p),
268                 n(n)
269         {}
270         MtEvent::Type getType() const
271         {
272                 return MtEvent::NODE_DUG;
273         }
274 };
275
276 class SoundMaker
277 {
278         ISoundManager *m_sound;
279         const NodeDefManager *m_ndef;
280 public:
281         bool makes_footstep_sound;
282         float m_player_step_timer;
283         float m_player_jump_timer;
284
285         SimpleSoundSpec m_player_step_sound;
286         SimpleSoundSpec m_player_leftpunch_sound;
287         SimpleSoundSpec m_player_rightpunch_sound;
288
289         SoundMaker(ISoundManager *sound, const NodeDefManager *ndef):
290                 m_sound(sound),
291                 m_ndef(ndef),
292                 makes_footstep_sound(true),
293                 m_player_step_timer(0.0f),
294                 m_player_jump_timer(0.0f)
295         {
296         }
297
298         void playPlayerStep()
299         {
300                 if (m_player_step_timer <= 0 && m_player_step_sound.exists()) {
301                         m_player_step_timer = 0.03;
302                         if (makes_footstep_sound)
303                                 m_sound->playSound(m_player_step_sound, false);
304                 }
305         }
306
307         void playPlayerJump()
308         {
309                 if (m_player_jump_timer <= 0.0f) {
310                         m_player_jump_timer = 0.2f;
311                         m_sound->playSound(SimpleSoundSpec("player_jump", 0.5f), false);
312                 }
313         }
314
315         static void viewBobbingStep(MtEvent *e, void *data)
316         {
317                 SoundMaker *sm = (SoundMaker *)data;
318                 sm->playPlayerStep();
319         }
320
321         static void playerRegainGround(MtEvent *e, void *data)
322         {
323                 SoundMaker *sm = (SoundMaker *)data;
324                 sm->playPlayerStep();
325         }
326
327         static void playerJump(MtEvent *e, void *data)
328         {
329                 SoundMaker *sm = (SoundMaker *)data;
330                 sm->playPlayerJump();
331         }
332
333         static void cameraPunchLeft(MtEvent *e, void *data)
334         {
335                 SoundMaker *sm = (SoundMaker *)data;
336                 sm->m_sound->playSound(sm->m_player_leftpunch_sound, false);
337         }
338
339         static void cameraPunchRight(MtEvent *e, void *data)
340         {
341                 SoundMaker *sm = (SoundMaker *)data;
342                 sm->m_sound->playSound(sm->m_player_rightpunch_sound, false);
343         }
344
345         static void nodeDug(MtEvent *e, void *data)
346         {
347                 SoundMaker *sm = (SoundMaker *)data;
348                 NodeDugEvent *nde = (NodeDugEvent *)e;
349                 sm->m_sound->playSound(sm->m_ndef->get(nde->n).sound_dug, false);
350         }
351
352         static void playerDamage(MtEvent *e, void *data)
353         {
354                 SoundMaker *sm = (SoundMaker *)data;
355                 sm->m_sound->playSound(SimpleSoundSpec("player_damage", 0.5), false);
356         }
357
358         static void playerFallingDamage(MtEvent *e, void *data)
359         {
360                 SoundMaker *sm = (SoundMaker *)data;
361                 sm->m_sound->playSound(SimpleSoundSpec("player_falling_damage", 0.5), false);
362         }
363
364         void registerReceiver(MtEventManager *mgr)
365         {
366                 mgr->reg(MtEvent::VIEW_BOBBING_STEP, SoundMaker::viewBobbingStep, this);
367                 mgr->reg(MtEvent::PLAYER_REGAIN_GROUND, SoundMaker::playerRegainGround, this);
368                 mgr->reg(MtEvent::PLAYER_JUMP, SoundMaker::playerJump, this);
369                 mgr->reg(MtEvent::CAMERA_PUNCH_LEFT, SoundMaker::cameraPunchLeft, this);
370                 mgr->reg(MtEvent::CAMERA_PUNCH_RIGHT, SoundMaker::cameraPunchRight, this);
371                 mgr->reg(MtEvent::NODE_DUG, SoundMaker::nodeDug, this);
372                 mgr->reg(MtEvent::PLAYER_DAMAGE, SoundMaker::playerDamage, this);
373                 mgr->reg(MtEvent::PLAYER_FALLING_DAMAGE, SoundMaker::playerFallingDamage, this);
374         }
375
376         void step(float dtime)
377         {
378                 m_player_step_timer -= dtime;
379                 m_player_jump_timer -= dtime;
380         }
381 };
382
383 // Locally stored sounds don't need to be preloaded because of this
384 class GameOnDemandSoundFetcher: public OnDemandSoundFetcher
385 {
386         std::set<std::string> m_fetched;
387 private:
388         void paths_insert(std::set<std::string> &dst_paths,
389                 const std::string &base,
390                 const std::string &name)
391         {
392                 dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".ogg");
393                 dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".0.ogg");
394                 dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".1.ogg");
395                 dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".2.ogg");
396                 dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".3.ogg");
397                 dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".4.ogg");
398                 dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".5.ogg");
399                 dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".6.ogg");
400                 dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".7.ogg");
401                 dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".8.ogg");
402                 dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".9.ogg");
403         }
404 public:
405         void fetchSounds(const std::string &name,
406                 std::set<std::string> &dst_paths,
407                 std::set<std::string> &dst_datas)
408         {
409                 if (m_fetched.count(name))
410                         return;
411
412                 m_fetched.insert(name);
413
414                 paths_insert(dst_paths, porting::path_share, name);
415                 paths_insert(dst_paths, porting::path_user,  name);
416         }
417 };
418
419
420 // before 1.8 there isn't a "integer interface", only float
421 #if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8)
422 typedef f32 SamplerLayer_t;
423 #else
424 typedef s32 SamplerLayer_t;
425 #endif
426
427
428 class GameGlobalShaderConstantSetter : public IShaderConstantSetter
429 {
430         Sky *m_sky;
431         bool *m_force_fog_off;
432         f32 *m_fog_range;
433         bool m_fog_enabled;
434         CachedPixelShaderSetting<float, 4> m_sky_bg_color;
435         CachedPixelShaderSetting<float> m_fog_distance;
436         CachedVertexShaderSetting<float> m_animation_timer_vertex;
437         CachedPixelShaderSetting<float> m_animation_timer_pixel;
438         CachedPixelShaderSetting<float, 3> m_day_light;
439         CachedPixelShaderSetting<float, 4> m_star_color;
440         CachedPixelShaderSetting<float, 3> m_eye_position_pixel;
441         CachedVertexShaderSetting<float, 3> m_eye_position_vertex;
442         CachedPixelShaderSetting<float, 3> m_minimap_yaw;
443         CachedPixelShaderSetting<float, 3> m_camera_offset_pixel;
444         CachedPixelShaderSetting<float, 3> m_camera_offset_vertex;
445         CachedPixelShaderSetting<SamplerLayer_t> m_base_texture;
446         CachedPixelShaderSetting<SamplerLayer_t> m_normal_texture;
447         Client *m_client;
448
449 public:
450         void onSettingsChange(const std::string &name)
451         {
452                 if (name == "enable_fog")
453                         m_fog_enabled = g_settings->getBool("enable_fog");
454         }
455
456         static void settingsCallback(const std::string &name, void *userdata)
457         {
458                 reinterpret_cast<GameGlobalShaderConstantSetter*>(userdata)->onSettingsChange(name);
459         }
460
461         void setSky(Sky *sky) { m_sky = sky; }
462
463         GameGlobalShaderConstantSetter(Sky *sky, bool *force_fog_off,
464                         f32 *fog_range, Client *client) :
465                 m_sky(sky),
466                 m_force_fog_off(force_fog_off),
467                 m_fog_range(fog_range),
468                 m_sky_bg_color("skyBgColor"),
469                 m_fog_distance("fogDistance"),
470                 m_animation_timer_vertex("animationTimer"),
471                 m_animation_timer_pixel("animationTimer"),
472                 m_day_light("dayLight"),
473                 m_star_color("starColor"),
474                 m_eye_position_pixel("eyePosition"),
475                 m_eye_position_vertex("eyePosition"),
476                 m_minimap_yaw("yawVec"),
477                 m_camera_offset_pixel("cameraOffset"),
478                 m_camera_offset_vertex("cameraOffset"),
479                 m_base_texture("baseTexture"),
480                 m_normal_texture("normalTexture"),
481                 m_client(client)
482         {
483                 g_settings->registerChangedCallback("enable_fog", settingsCallback, this);
484                 m_fog_enabled = g_settings->getBool("enable_fog");
485         }
486
487         ~GameGlobalShaderConstantSetter()
488         {
489                 g_settings->deregisterChangedCallback("enable_fog", settingsCallback, this);
490         }
491
492         void onSetConstants(video::IMaterialRendererServices *services) override
493         {
494                 // Background color
495                 video::SColor bgcolor = m_sky->getBgColor();
496                 video::SColorf bgcolorf(bgcolor);
497                 float bgcolorfa[4] = {
498                         bgcolorf.r,
499                         bgcolorf.g,
500                         bgcolorf.b,
501                         bgcolorf.a,
502                 };
503                 m_sky_bg_color.set(bgcolorfa, services);
504
505                 // Fog distance
506                 float fog_distance = 10000 * BS;
507
508                 if (m_fog_enabled && !*m_force_fog_off)
509                         fog_distance = *m_fog_range;
510
511                 m_fog_distance.set(&fog_distance, services);
512
513                 u32 daynight_ratio = (float)m_client->getEnv().getDayNightRatio();
514                 video::SColorf sunlight;
515                 get_sunlight_color(&sunlight, daynight_ratio);
516                 float dnc[3] = {
517                         sunlight.r,
518                         sunlight.g,
519                         sunlight.b };
520                 m_day_light.set(dnc, services);
521
522                 video::SColorf star_color = m_sky->getCurrentStarColor();
523                 float clr[4] = {star_color.r, star_color.g, star_color.b, star_color.a};
524                 m_star_color.set(clr, services);
525
526                 u32 animation_timer = porting::getTimeMs() % 1000000;
527                 float animation_timer_f = (float)animation_timer / 100000.f;
528                 m_animation_timer_vertex.set(&animation_timer_f, services);
529                 m_animation_timer_pixel.set(&animation_timer_f, services);
530
531                 float eye_position_array[3];
532                 v3f epos = m_client->getEnv().getLocalPlayer()->getEyePosition();
533 #if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8)
534                 eye_position_array[0] = epos.X;
535                 eye_position_array[1] = epos.Y;
536                 eye_position_array[2] = epos.Z;
537 #else
538                 epos.getAs3Values(eye_position_array);
539 #endif
540                 m_eye_position_pixel.set(eye_position_array, services);
541                 m_eye_position_vertex.set(eye_position_array, services);
542
543                 if (m_client->getMinimap()) {
544                         float minimap_yaw_array[3];
545                         v3f minimap_yaw = m_client->getMinimap()->getYawVec();
546 #if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8)
547                         minimap_yaw_array[0] = minimap_yaw.X;
548                         minimap_yaw_array[1] = minimap_yaw.Y;
549                         minimap_yaw_array[2] = minimap_yaw.Z;
550 #else
551                         minimap_yaw.getAs3Values(minimap_yaw_array);
552 #endif
553                         m_minimap_yaw.set(minimap_yaw_array, services);
554                 }
555
556                 float camera_offset_array[3];
557                 v3f offset = intToFloat(m_client->getCamera()->getOffset(), BS);
558 #if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8)
559                 camera_offset_array[0] = offset.X;
560                 camera_offset_array[1] = offset.Y;
561                 camera_offset_array[2] = offset.Z;
562 #else
563                 offset.getAs3Values(camera_offset_array);
564 #endif
565                 m_camera_offset_pixel.set(camera_offset_array, services);
566                 m_camera_offset_vertex.set(camera_offset_array, services);
567
568                 SamplerLayer_t base_tex = 0, normal_tex = 1;
569                 m_base_texture.set(&base_tex, services);
570                 m_normal_texture.set(&normal_tex, services);
571         }
572 };
573
574
575 class GameGlobalShaderConstantSetterFactory : public IShaderConstantSetterFactory
576 {
577         Sky *m_sky;
578         bool *m_force_fog_off;
579         f32 *m_fog_range;
580         Client *m_client;
581         std::vector<GameGlobalShaderConstantSetter *> created_nosky;
582 public:
583         GameGlobalShaderConstantSetterFactory(bool *force_fog_off,
584                         f32 *fog_range, Client *client) :
585                 m_sky(NULL),
586                 m_force_fog_off(force_fog_off),
587                 m_fog_range(fog_range),
588                 m_client(client)
589         {}
590
591         void setSky(Sky *sky) {
592                 m_sky = sky;
593                 for (GameGlobalShaderConstantSetter *ggscs : created_nosky) {
594                         ggscs->setSky(m_sky);
595                 }
596                 created_nosky.clear();
597         }
598
599         virtual IShaderConstantSetter* create()
600         {
601                 auto *scs = new GameGlobalShaderConstantSetter(
602                                 m_sky, m_force_fog_off, m_fog_range, m_client);
603                 if (!m_sky)
604                         created_nosky.push_back(scs);
605                 return scs;
606         }
607 };
608
609 #ifdef __ANDROID__
610 #define SIZE_TAG "size[11,5.5]"
611 #else
612 #define SIZE_TAG "size[11,5.5,true]" // Fixed size on desktop
613 #endif
614
615 /****************************************************************************
616  ****************************************************************************/
617
618 const float object_hit_delay = 0.2;
619
620 struct FpsControl {
621         u32 last_time, busy_time, sleep_time;
622 };
623
624
625 /* The reason the following structs are not anonymous structs within the
626  * class is that they are not used by the majority of member functions and
627  * many functions that do require objects of thse types do not modify them
628  * (so they can be passed as a const qualified parameter)
629  */
630
631 struct GameRunData {
632         u16 dig_index;
633         u16 new_playeritem;
634         PointedThing pointed_old;
635         bool digging;
636         bool punching;
637         bool btn_down_for_dig;
638         bool dig_instantly;
639         bool digging_blocked;
640         bool reset_jump_timer;
641         float nodig_delay_timer;
642         float dig_time;
643         float dig_time_complete;
644         float repeat_place_timer;
645         float object_hit_delay_timer;
646         float time_from_last_punch;
647         ClientActiveObject *selected_object;
648
649         float jump_timer;
650         float damage_flash;
651         float update_draw_list_timer;
652
653         f32 fog_range;
654
655         v3f update_draw_list_last_cam_dir;
656
657         float time_of_day_smooth;
658 };
659
660 class Game;
661
662 struct ClientEventHandler
663 {
664         void (Game::*handler)(ClientEvent *, CameraOrientation *);
665 };
666
667 using PausedNodesList = std::vector<std::pair<irr_ptr<scene::IAnimatedMeshSceneNode>, float>>;
668
669 class Game {
670 public:
671         Game();
672         ~Game();
673
674         bool startup(bool *kill,
675                         InputHandler *input,
676                         const GameStartData &game_params,
677                         std::string &error_message,
678                         bool *reconnect,
679                         ChatBackend *chat_backend);
680
681
682         void run();
683         void shutdown();
684
685         void extendedResourceCleanup();
686
687         // Basic initialisation
688         bool init(const std::string &map_dir, const std::string &address,
689                         u16 port, const SubgameSpec &gamespec);
690         bool initSound();
691         bool createSingleplayerServer(const std::string &map_dir,
692                         const SubgameSpec &gamespec, u16 port);
693
694         // Client creation
695         bool createClient(const GameStartData &start_data);
696         bool initGui();
697
698         // Client connection
699         bool connectToServer(const GameStartData &start_data,
700                         bool *connect_ok, bool *aborted);
701         bool getServerContent(bool *aborted);
702
703         // Main loop
704
705         void updateInteractTimers(f32 dtime);
706         bool checkConnection();
707         bool handleCallbacks();
708         void processQueues();
709         void updateProfilers(const RunStats &stats, const FpsControl &draw_times, f32 dtime);
710         void updateStats(RunStats *stats, const FpsControl &draw_times, f32 dtime);
711         void updateProfilerGraphs(ProfilerGraph *graph);
712
713         // Input related
714         void processUserInput(f32 dtime);
715         void processKeyInput();
716         void processItemSelection(u16 *new_playeritem);
717
718         void dropSelectedItem(bool single_item = false);
719         void openInventory();
720         void openEnderchest();
721         void openConsole(float scale, const wchar_t *line=NULL);
722         void toggleFreeMove();
723         void toggleFreeMoveAlt();
724         void togglePitchMove();
725         void toggleFast();
726         void toggleNoClip();
727         void toggleKillaura();
728         void toggleFreecam();
729         void toggleScaffold();
730         void toggleNextItem();
731         void toggleCinematic();
732         void toggleAutoforward();
733
734         void toggleMinimap(bool shift_pressed);
735         void toggleFog();
736         void toggleDebug();
737         void toggleUpdateCamera();
738         void updatePlayerCAOVisibility();
739
740         void increaseViewRange();
741         void decreaseViewRange();
742         void toggleFullViewRange();
743         void checkZoomEnabled();
744
745         void updateCameraDirection(CameraOrientation *cam, float dtime);
746         void updateCameraOrientation(CameraOrientation *cam, float dtime);
747         void updatePlayerControl(const CameraOrientation &cam);
748         void step(f32 *dtime);
749         void processClientEvents(CameraOrientation *cam);
750         void updateCamera(u32 busy_time, f32 dtime);
751         void updateSound(f32 dtime);
752         void processPlayerInteraction(f32 dtime, bool show_hud, bool show_debug);
753         /*!
754          * Returns the object or node the player is pointing at.
755          * Also updates the selected thing in the Hud.
756          *
757          * @param[in]  shootline         the shootline, starting from
758          * the camera position. This also gives the maximal distance
759          * of the search.
760          * @param[in]  liquids_pointable if false, liquids are ignored
761          * @param[in]  look_for_object   if false, objects are ignored
762          * @param[in]  camera_offset     offset of the camera
763          * @param[out] selected_object   the selected object or
764          * NULL if not found
765          */
766         PointedThing updatePointedThing(
767                         const core::line3d<f32> &shootline, bool liquids_pointable,
768                         bool look_for_object, const v3s16 &camera_offset);
769         void handlePointingAtNothing(const ItemStack &playerItem);
770         void handlePointingAtNode(const PointedThing &pointed,
771                         const ItemStack &selected_item, const ItemStack &hand_item, f32 dtime);
772         void handlePointingAtObject(const PointedThing &pointed, const ItemStack &playeritem,
773                         const v3f &player_position, bool show_debug);
774         void handleDigging(const PointedThing &pointed, const v3s16 &nodepos,
775                         const ItemStack &selected_item, const ItemStack &hand_item, f32 dtime);
776         void updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime,
777                         const CameraOrientation &cam);
778
779         // Misc
780         void limitFps(FpsControl *fps_timings, f32 *dtime);
781
782         void showOverlayMessage(const char *msg, float dtime, int percent,
783                         bool draw_clouds = true);
784
785         static void freecamChangedCallback(const std::string &setting_name, void *data);
786         static void settingChangedCallback(const std::string &setting_name, void *data);
787         static void updateAllMapBlocksCallback(const std::string &setting_name, void *data);
788         void readSettings();
789
790         bool isKeyDown(GameKeyType k);
791         bool wasKeyDown(GameKeyType k);
792         bool wasKeyPressed(GameKeyType k);
793         bool wasKeyReleased(GameKeyType k);
794
795 #ifdef __ANDROID__
796         void handleAndroidChatInput();
797 #endif
798
799         struct Flags {
800                 bool force_fog_off = false;
801                 bool disable_camera_update = false;
802         };
803
804         void showDeathFormspec();
805         void showPauseMenu();
806
807         void pauseAnimation();
808         void resumeAnimation();
809
810         // ClientEvent handlers
811         void handleClientEvent_None(ClientEvent *event, CameraOrientation *cam);
812         void handleClientEvent_PlayerDamage(ClientEvent *event, CameraOrientation *cam);
813         void handleClientEvent_PlayerForceMove(ClientEvent *event, CameraOrientation *cam);
814         void handleClientEvent_Deathscreen(ClientEvent *event, CameraOrientation *cam);
815         void handleClientEvent_ShowFormSpec(ClientEvent *event, CameraOrientation *cam);
816         void handleClientEvent_ShowLocalFormSpec(ClientEvent *event, CameraOrientation *cam);
817         void handleClientEvent_HandleParticleEvent(ClientEvent *event,
818                 CameraOrientation *cam);
819         void handleClientEvent_HudAdd(ClientEvent *event, CameraOrientation *cam);
820         void handleClientEvent_HudRemove(ClientEvent *event, CameraOrientation *cam);
821         void handleClientEvent_HudChange(ClientEvent *event, CameraOrientation *cam);
822         void handleClientEvent_SetSky(ClientEvent *event, CameraOrientation *cam);
823         void handleClientEvent_SetSun(ClientEvent *event, CameraOrientation *cam);
824         void handleClientEvent_SetMoon(ClientEvent *event, CameraOrientation *cam);
825         void handleClientEvent_SetStars(ClientEvent *event, CameraOrientation *cam);
826         void handleClientEvent_OverrideDayNigthRatio(ClientEvent *event,
827                 CameraOrientation *cam);
828         void handleClientEvent_CloudParams(ClientEvent *event, CameraOrientation *cam);
829
830         void updateChat(f32 dtime, const v2u32 &screensize);
831
832         bool nodePlacement(const ItemDefinition &selected_def, const ItemStack &selected_item,
833                 const v3s16 &nodepos, const v3s16 &neighbourpos, const PointedThing &pointed,
834                 const NodeMetadata *meta, bool force = false);
835         static const ClientEventHandler clientEventHandler[CLIENTEVENT_MAX];
836
837         f32 getSensitivityScaleFactor() const;
838
839         InputHandler *input = nullptr;
840
841         Client *client = nullptr;
842         Server *server = nullptr;
843
844         IWritableTextureSource *texture_src = nullptr;
845         IWritableShaderSource *shader_src = nullptr;
846
847         // When created, these will be filled with data received from the server
848         IWritableItemDefManager *itemdef_manager = nullptr;
849         NodeDefManager *nodedef_manager = nullptr;
850
851         GameOnDemandSoundFetcher soundfetcher; // useful when testing
852         ISoundManager *sound = nullptr;
853         bool sound_is_dummy = false;
854         SoundMaker *soundmaker = nullptr;
855
856         ChatBackend *chat_backend = nullptr;
857         LogOutputBuffer m_chat_log_buf;
858
859         EventManager *eventmgr = nullptr;
860         QuicktuneShortcutter *quicktune = nullptr;
861         bool registration_confirmation_shown = false;
862
863         std::unique_ptr<GameUI> m_game_ui;
864         GUIChatConsole *gui_chat_console = nullptr; // Free using ->Drop()
865         CheatMenu *m_cheat_menu = nullptr;
866         MapDrawControl *draw_control = nullptr;
867         Camera *camera = nullptr;
868         Clouds *clouds = nullptr;                         // Free using ->Drop()
869         Sky *sky = nullptr;                         // Free using ->Drop()
870         Hud *hud = nullptr;
871         Minimap *mapper = nullptr;
872
873         // Map server hud ids to client hud ids
874         std::unordered_map<u32, u32> m_hud_server_to_client;
875
876         GameRunData runData;
877         Flags m_flags;
878
879         /* 'cache'
880            This class does take ownership/responsibily for cleaning up etc of any of
881            these items (e.g. device)
882         */
883         IrrlichtDevice *device;
884         video::IVideoDriver *driver;
885         scene::ISceneManager *smgr;
886         bool *kill;
887         std::string *error_message;
888         bool *reconnect_requested;
889         scene::ISceneNode *skybox;
890         PausedNodesList paused_animated_nodes;
891
892         bool simple_singleplayer_mode;
893         /* End 'cache' */
894
895         /* Pre-calculated values
896          */
897         int crack_animation_length;
898
899         IntervalLimiter profiler_interval;
900
901         /*
902          * TODO: Local caching of settings is not optimal and should at some stage
903          *       be updated to use a global settings object for getting thse values
904          *       (as opposed to the this local caching). This can be addressed in
905          *       a later release.
906          */
907         bool m_cache_doubletap_jump;
908         bool m_cache_enable_clouds;
909         bool m_cache_enable_joysticks;
910         bool m_cache_enable_particles;
911         bool m_cache_enable_fog;
912         bool m_cache_enable_noclip;
913         bool m_cache_enable_free_move;
914         f32  m_cache_mouse_sensitivity;
915         f32  m_cache_joystick_frustum_sensitivity;
916         f32  m_repeat_place_time;
917         f32  m_cache_cam_smoothing;
918         f32  m_cache_fog_start;
919
920         bool m_invert_mouse = false;
921         bool m_first_loop_after_window_activation = false;
922         bool m_camera_offset_changed = false;
923
924         bool m_does_lost_focus_pause_game = false;
925
926         CameraOrientation cam_view_target  = { 0 };
927         CameraOrientation cam_view  = { 0 };
928
929         int m_reset_HW_buffer_counter = 0;
930 #ifdef __ANDROID__
931         bool m_cache_hold_aux1;
932         bool m_android_chat_open;
933 #endif
934 };
935 extern Game *g_game;
936
937 void the_game(bool *kill,
938                 InputHandler *input,
939                 const GameStartData &start_data,
940                 std::string &error_message,
941                 ChatBackend &chat_backend,
942                 bool *reconnect_requested);