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