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