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