]> git.localhorst.tv Git - blank.git/blob - src/standalone/MasterState.cpp
665f8d4708dcd99b042fd71cffd4444172a7da51
[blank.git] / src / standalone / MasterState.cpp
1 #include "MasterState.hpp"
2
3 #include "../app/Config.hpp"
4 #include "../app/Environment.hpp"
5 #include "../app/init.hpp"
6 #include "../io/WorldSave.hpp"
7
8 #include <SDL.h>
9
10
11 namespace blank {
12 namespace standalone {
13
14 MasterState::MasterState(
15         Environment &env,
16         Config &config,
17         const Generator::Config &gc,
18         const World::Config &wc,
19         const WorldSave &save
20 )
21 : config(config)
22 , env(env)
23 , res()
24 , sounds()
25 , save(save)
26 , world(res.block_types, wc)
27 , spawn_index(world.Chunks().MakeIndex(wc.spawn, 3))
28 , player(*world.AddPlayer(config.player.name))
29 , spawn_player(false)
30 , hud(env, config, player)
31 , manip(env.audio, sounds, player.GetEntity())
32 , input(world, player, manip)
33 , interface(config, env.keymap, input, *this)
34 , generator(gc)
35 , chunk_loader(world.Chunks(), generator, save)
36 , chunk_renderer(player.GetChunks())
37 , spawner(world, res.models, env.rng)
38 , sky(env.loader.LoadCubeMap("skybox"))
39 , cli(world)
40 , preload(env, chunk_loader, chunk_renderer)
41 , unload(env, world.Chunks(), save)
42 , chat(env, *this, *this) {
43         res.Load(env.loader, "default");
44         if (res.models.size() < 2) {
45                 throw std::runtime_error("need at least two models to run");
46         }
47         res.models[0].Instantiate(player.GetEntity().GetModel());
48         sounds.Load(env.loader, res.snd_index);
49         spawner.LimitModels(1, res.models.size());
50         interface.SetInventorySlots(res.block_types.size() - 1);
51         generator.LoadTypes(res.block_types);
52         chunk_renderer.LoadTextures(env.loader, res.tex_index);
53         chunk_renderer.FogDensity(wc.fog_density);
54         if (save.Exists(player)) {
55                 save.Read(player);
56         } else {
57                 spawn_player = true;
58         }
59 }
60
61 MasterState::~MasterState() {
62         world.Chunks().UnregisterIndex(spawn_index);
63 }
64
65
66 void MasterState::OnResume() {
67         if (spawn_index.MissingChunks() > 0) {
68                 env.state.Push(&preload);
69                 return;
70         }
71         if (spawn_player) {
72                 // TODO: spawn
73                 spawn_player = false;
74         }
75         hud.KeepMessages(false);
76         OnFocus();
77 }
78
79 void MasterState::OnPause() {
80         OnBlur();
81 }
82
83 void MasterState::OnFocus() {
84         if (config.input.mouse) {
85                 env.window.GrabMouse();
86         }
87         interface.Unlock();
88 }
89
90 void MasterState::OnBlur() {
91         env.window.ReleaseMouse();
92         interface.Lock();
93 }
94
95
96 void MasterState::Handle(const SDL_Event &event) {
97         switch (event.type) {
98                 case SDL_KEYDOWN:
99                         // TODO: move to interface
100                         if (event.key.keysym.sym == SDLK_RETURN) {
101                                 chat.Clear();
102                                 env.state.Push(&chat);
103                                 hud.KeepMessages(true);
104                         } else if (event.key.keysym.sym == SDLK_SLASH) {
105                                 chat.Preset("/");
106                                 env.state.Push(&chat);
107                                 hud.KeepMessages(true);
108                         } else {
109                                 interface.HandlePress(event.key);
110                         }
111                         break;
112                 case SDL_KEYUP:
113                         interface.HandleRelease(event.key);
114                         break;
115                 case SDL_MOUSEBUTTONDOWN:
116                         interface.HandlePress(event.button);
117                         break;
118                 case SDL_MOUSEBUTTONUP:
119                         interface.HandleRelease(event.button);
120                         break;
121                 case SDL_MOUSEMOTION:
122                         interface.Handle(event.motion);
123                         break;
124                 case SDL_MOUSEWHEEL:
125                         interface.Handle(event.wheel);
126                         break;
127                 case SDL_QUIT:
128                         Exit();
129                         break;
130                 default:
131                         break;
132         }
133 }
134
135 void MasterState::Update(int dt) {
136         spawner.Update(dt);
137         world.Update(dt);
138         if (input.BlockFocus()) {
139                 hud.FocusBlock(input.BlockFocus().GetChunk(), input.BlockFocus().block);
140         } else if (input.EntityFocus()) {
141                 hud.FocusEntity(*input.EntityFocus().entity);
142         } else {
143                 hud.FocusNone();
144         }
145         hud.Display(res.block_types[player.GetInventorySlot() + 1]);
146         hud.Update(dt);
147         chunk_loader.Update(dt);
148         chunk_renderer.Update(dt);
149
150         glm::mat4 trans = player.GetEntity().Transform(player.GetEntity().ChunkCoords());
151         glm::vec3 dir(trans * glm::vec4(0.0f, 0.0f, -1.0f, 0.0f));
152         glm::vec3 up(trans * glm::vec4(0.0f, 1.0f, 0.0f, 0.0f));
153         env.audio.Position(player.GetEntity().Position());
154         env.audio.Velocity(player.GetEntity().Velocity());
155         env.audio.Orientation(dir, up);
156 }
157
158 void MasterState::Render(Viewport &viewport) {
159         viewport.WorldPosition(player.GetEntity().ViewTransform(player.GetEntity().ChunkCoords()));
160         if (config.video.world) {
161                 chunk_renderer.Render(viewport);
162                 world.Render(viewport);
163                 if (config.video.debug) {
164                         world.RenderDebug(viewport);
165                 }
166                 sky.Render(viewport);
167         }
168         hud.Render(viewport);
169 }
170
171
172 void MasterState::SetAudio(bool b) {
173         config.audio.enabled = b;
174         if (b) {
175                 hud.PostMessage("Audio enabled");
176         } else {
177                 hud.PostMessage("Audio disabled");
178         }
179 }
180
181 void MasterState::SetVideo(bool b) {
182         config.video.world = b;
183         if (b) {
184                 hud.PostMessage("World rendering enabled");
185         } else {
186                 hud.PostMessage("World rendering disabled");
187         }
188 }
189
190 void MasterState::SetHUD(bool b) {
191         config.video.hud = b;
192         if (b) {
193                 hud.PostMessage("HUD rendering enabled");
194         } else {
195                 hud.PostMessage("HUD rendering disabled");
196         }
197 }
198
199 void MasterState::SetDebug(bool b) {
200         config.video.debug = b;
201         if (b) {
202                 hud.PostMessage("Debug rendering enabled");
203         } else {
204                 hud.PostMessage("Debug rendering disabled");
205         }
206 }
207
208 void MasterState::Exit() {
209         save.Write(player);
210         env.state.Switch(&unload);
211 }
212
213 void MasterState::OnLineSubmit(const std::string &line) {
214         if (line.empty()) {
215                 return;
216         }
217         if (line[0] == '/' && line.size() > 1 && line[1] != '/') {
218                 cli.Execute(player, line.substr(1));
219         } else {
220                 hud.PostMessage(line);
221         }
222 }
223
224 }
225 }