]> git.localhorst.tv Git - blank.git/blob - src/app/runtime.cpp
5dce72159a439203843581f84cb14fc86fdda08a
[blank.git] / src / app / runtime.cpp
1 #include "Application.hpp"
2 #include "Environment.hpp"
3 #include "PreloadState.hpp"
4 #include "Runtime.hpp"
5 #include "WorldState.hpp"
6
7 #include "init.hpp"
8
9 #include <cctype>
10 #include <cstdlib>
11 #include <iostream>
12 #include <SDL.h>
13
14 using namespace std;
15
16
17 namespace {
18
19 string default_asset_path() {
20         char *base = SDL_GetBasePath();
21         string assets(base);
22         assets += "assets/";
23         SDL_free(base);
24         return assets;
25 }
26
27 string default_save_path() {
28 #ifndef NDEBUG
29         char *base = SDL_GetBasePath();
30         string save(base);
31         save += "saves/";
32         SDL_free(base);
33         return save;
34 #else
35         char *pref = SDL_GetPrefPath("localhorst", "blank");
36         string save(pref);
37         SDL_free(pref);
38         return save;
39 #endif
40 }
41
42 }
43
44 namespace blank {
45
46 Environment::Environment(Window &win, const string &asset_path)
47 : audio()
48 , viewport()
49 , window(win)
50 , assets(asset_path)
51 , counter() {
52
53 }
54
55
56 Runtime::Runtime() noexcept
57 : name("blank")
58 , mode(NORMAL)
59 , n(0)
60 , t(0)
61 , config() {
62
63 }
64
65
66 void Runtime::ReadArgs(int argc, const char *const *argv) {
67         if (argc <= 0) return;
68         name = argv[0];
69
70         bool options = true;
71         bool error = false;
72
73         for (int i = 1; i < argc; ++i) {
74                 const char *arg = argv[i];
75                 if (!arg || arg[0] == '\0') {
76                         cerr << "warning: found empty argument at position " << i << endl;
77                         continue;
78                 }
79                 if (options && arg[0] == '-') {
80                         if (arg[1] == '\0') {
81                                 cerr << "warning: incomplete option list at position " << i << endl;
82                         } else if (arg[1] == '-') {
83                                 if (arg[2] == '\0') {
84                                         // stopper
85                                         options = false;
86                                 } else {
87                                         const char *param = arg + 2;
88                                         // long option
89                                         if (strcmp(param, "no-vsync") == 0) {
90                                                 config.vsync = false;
91                                         } else if (strcmp(param, "no-keyboard") == 0) {
92                                                 config.interface.keyboard_disabled = true;
93                                         } else if (strcmp(param, "no-mouse") == 0) {
94                                                 config.interface.mouse_disabled = true;
95                                         } else if (strcmp(param, "no-hud") == 0) {
96                                                 config.interface.visual_disabled = true;
97                                         } else if (strcmp(param, "no-audio") == 0) {
98                                                 config.interface.audio_disabled = true;
99                                         } else if (strcmp(param, "asset-path") == 0) {
100                                                 ++i;
101                                                 if (i >= argc || argv[i] == nullptr || argv[i][0] == '\0') {
102                                                         cerr << "missing argument to --asset-path" << endl;
103                                                         error = true;
104                                                 } else {
105                                                         config.asset_path = argv[i];
106                                                 }
107                                         } else if (strcmp(param, "save-path") == 0) {
108                                                 ++i;
109                                                 if (i >= argc || argv[i] == nullptr || argv[i][0] == '\0') {
110                                                         cerr << "missing argument to --save-path" << endl;
111                                                         error = true;
112                                                 } else {
113                                                         config.save_path = argv[i];
114                                                 }
115                                         } else {
116                                                 cerr << "unknown option " << arg << endl;
117                                                 error = true;
118                                         }
119                                 }
120                         } else {
121                                 // short options
122                                 for (int j = 1; arg[j] != '\0'; ++j) {
123                                         switch (arg[j]) {
124                                                 case 'd':
125                                                         config.doublebuf = false;
126                                                         break;
127                                                 case 'm':
128                                                         ++i;
129                                                         if (i >= argc || argv[i] == nullptr || argv[i][0] == '\0') {
130                                                                 cerr << "missing argument to -m" << endl;
131                                                                 error = true;
132                                                         } else {
133                                                                 config.multisampling = strtoul(argv[i], nullptr, 10);
134                                                         }
135                                                         break;
136                                                 case 'n':
137                                                         ++i;
138                                                         if (i >= argc || argv[i] == nullptr || argv[i][0] == '\0') {
139                                                                 cerr << "missing argument to -n" << endl;
140                                                                 error = true;
141                                                         } else {
142                                                                 n = strtoul(argv[i], nullptr, 10);
143                                                         }
144                                                         break;
145                                                 case 's':
146                                                         ++i;
147                                                         if (i >= argc || argv[i] == nullptr || argv[i][0] == '\0') {
148                                                                 cerr << "missing argument to -s" << endl;
149                                                                 error = true;
150                                                         } else {
151                                                                 config.world.gen.solid_seed = strtoul(argv[i], nullptr, 10);
152                                                                 config.world.gen.type_seed = config.world.gen.solid_seed;
153                                                         }
154                                                         break;
155                                                 case 't':
156                                                         ++i;
157                                                         if (i >= argc || argv[i] == nullptr || argv[i][0] == '\0') {
158                                                                 cerr << "missing argument to -t" << endl;
159                                                                 error = true;
160                                                         } else {
161                                                                 t = strtoul(argv[i], nullptr, 10);
162                                                         }
163                                                         break;
164                                                 case '-':
165                                                         // stopper
166                                                         options = false;
167                                                         break;
168                                                 default:
169                                                         cerr << "unknown option " << arg[j] << endl;
170                                                         error = true;
171                                                         break;
172                                         }
173                                 }
174                         }
175                 } else {
176                         cerr << "unable to interpret argument "
177                                 << i << " (" << arg << ")" << endl;
178                         error = true;
179                 }
180         }
181
182         if (error) {
183                 mode = ERROR;
184                 return;
185         }
186
187         if (config.asset_path.empty()) {
188                 config.asset_path = default_asset_path();
189         } else if (
190                 config.asset_path[config.asset_path.size() - 1] != '/' &&
191                 config.asset_path[config.asset_path.size() - 1] != '\\'
192         ) {
193                 config.asset_path += '/';
194         }
195         if (config.save_path.empty()) {
196                 config.save_path = default_save_path();
197         } else if (
198                 config.save_path[config.save_path.size() - 1] != '/' &&
199                 config.save_path[config.save_path.size() - 1] != '\\'
200         ) {
201                 config.save_path += '/';
202         }
203
204         if (n > 0) {
205                 if (t > 0) {
206                         mode = FIXED_FRAME_LIMIT;
207                 } else {
208                         mode = FRAME_LIMIT;
209                 }
210         } else if (t > 0) {
211                 mode = TIME_LIMIT;
212         } else {
213                 mode = NORMAL;
214         }
215 }
216
217 int Runtime::Execute() {
218         if (mode == ERROR) {
219                 return 1;
220         }
221
222         Init init(config.doublebuf, config.multisampling);
223
224         Environment env(init.window, config.asset_path);
225         env.viewport.VSync(config.vsync);
226
227         Application app(env);
228
229         WorldState world_state(env, config.interface, config.world);
230         app.PushState(&world_state);
231
232         PreloadState preloader(env, world_state.GetWorld().Loader());
233         app.PushState(&preloader);
234
235         switch (mode) {
236                 default:
237                 case NORMAL:
238                         app.Run();
239                         break;
240                 case FRAME_LIMIT:
241                         app.RunN(n);
242                         break;
243                 case TIME_LIMIT:
244                         app.RunT(t);
245                         break;
246                 case FIXED_FRAME_LIMIT:
247                         app.RunS(n, t);
248                         break;
249         }
250
251         return 0;
252 }
253
254 }