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