Project Alice
Loading...
Searching...
No Matches
entry_point_nix.cpp
Go to the documentation of this file.
1#include "serialization.hpp"
2#include "system_state.hpp"
3
4static sys::state game_state;
8};
9static std::vector<parsers::mod_file> mod_list;
10static native_string selected_scenario_file;
11static uint32_t max_scenario_count = 0;
12static std::vector<scenario_file> scenario_files;
13//static std::vector arguments;
14
15// Keep mod_list empty for vanilla
18 simple_fs::add_root(dummy, NATIVE("."));
19
20 for(int32_t i = 0; i < int32_t(mod_list.size()); ++i) {
21 if(mod_list[i].mod_selected == false)
22 break;
23
24 mod_list[i].add_to_file_system(dummy);
25 }
26 return simple_fs::extract_state(dummy);
27}
28
31 simple_fs::add_root(fs_root, ".");
32 auto root = get_root(fs_root);
33 auto mod_dir = simple_fs::open_directory(root, NATIVE("mod"));
34 auto mod_files = simple_fs::list_files(mod_dir, NATIVE(".mod"));
36 for (auto& f : mod_files) {
37 auto of = simple_fs::open_file(f);
38 if(of) {
39 auto content = view_contents(*of);
40 parsers::token_generator gen(content.data, content.data + content.file_size );
41 mod_list.push_back(parsers::parse_mod_file(gen, err, parsers::mod_file_context{}));
42 }
43 }
44}
45
48 simple_fs::add_root(fs_root, ".");
49 auto root = get_root(fs_root);
51 auto s_files = simple_fs::list_files(sdir, NATIVE(".bin"));
52 for(auto& f : s_files) {
53 auto of = simple_fs::open_file(f);
54 if(of) {
55 auto content = view_contents(*of);
56 auto desc = sys::extract_mod_information(reinterpret_cast<uint8_t const*>(content.data), content.file_size);
57 if(desc.count != 0) {
58 max_scenario_count = std::max(desc.count, max_scenario_count);
59 scenario_files.push_back(scenario_file{ simple_fs::get_file_name(f) , desc });
60 }
61 }
62 }
63
64 std::sort(scenario_files.begin(), scenario_files.end(), [](scenario_file const& a, scenario_file const& b) {
65 return a.ident.count > b.ident.count;
66 });
67}
68
70 native_string ret;
71 constexpr native_char digits[] = NATIVE("0123456789ABCDEF");
72 do {
73 ret += digits[v & 0x0F];
74 v = v >> 4;
75 } while(v != 0);
76 return ret;
77 };
78
79// Original is void make_mod_file(). This function can also be used to create
80// vanilla scenario, though when there are two bookmarks dates, it will also create
81// additional scenario file alongside with the save file for the bookmark.
82// Unsure how it works in windows build.
84 auto path = produce_mod_path();
86 simple_fs::restore_state(fs_root, path);
88 auto root = get_root(fs_root);
89 auto common = open_directory(root, NATIVE("common"));
90 parsers::bookmark_context bookmark_context;
91 if(auto f = open_file(common, NATIVE("bookmarks.txt")); f) {
92 auto bookmark_content = simple_fs::view_contents(*f);
93 err.file_name = "bookmarks.txt";
94 parsers::token_generator gen(bookmark_content.data, bookmark_content.data + bookmark_content.file_size);
95 parsers::parse_bookmark_file(gen, err, bookmark_context);
96 assert(!bookmark_context.bookmark_dates.empty());
97 } else {
98 err.accumulated_errors += "File common/bookmarks.txt could not be opened\n";
99 }
100
101 sys::checksum_key scenario_key;
102
103 for(uint32_t date_index = 0; date_index < uint32_t(bookmark_context.bookmark_dates.size()); date_index++) {
104 err.accumulated_errors.clear();
105 err.accumulated_warnings.clear();
106 //
107 auto game_state = std::make_unique<sys::state>();
108 simple_fs::restore_state(game_state->common_fs, path);
109 game_state->load_scenario_data(err, bookmark_context.bookmark_dates[date_index].date_);
110 if(err.fatal)
111 break;
112 if(date_index == 0) {
114 int32_t append = 0;
115 auto time_stamp = uint64_t(std::time(0));
116 auto base_name = to_hex(time_stamp);
117 while(simple_fs::peek_file(sdir, base_name + NATIVE("-") + std::to_string(append) + NATIVE(".bin"))) {
118 ++append;
119 }
120 ++max_scenario_count;
121 selected_scenario_file = base_name + NATIVE("-") + std::to_string(append) + NATIVE(".bin");
122 sys::write_scenario_file(*game_state, selected_scenario_file, max_scenario_count);
123 if(auto of = simple_fs::open_file(sdir, selected_scenario_file); of) {
124 auto content = view_contents(*of);
125 auto desc = sys::extract_mod_information(reinterpret_cast<uint8_t const*>(content.data), content.file_size);
126 if(desc.count != 0) {
127 scenario_files.push_back(scenario_file{ selected_scenario_file , desc });
128 }
129 }
130 std::sort(scenario_files.begin(), scenario_files.end(), [](scenario_file const& a, scenario_file const& b) {
131 return a.ident.count > b.ident.count;
132 });
133 scenario_key = game_state->scenario_checksum;
134 } else {
135#ifndef NDEBUG
136 sys::write_scenario_file(*game_state, std::to_string(date_index) + NATIVE(".bin"), 0);
137#endif
138 game_state->scenario_checksum = scenario_key;
139 sys::write_save_file(*game_state, sys::save_type::bookmark, bookmark_context.bookmark_dates[date_index].name_);
140 }
141 }
142
143 if(!err.accumulated_errors.empty() || !err.accumulated_warnings.empty()) {
144 auto assembled_msg = std::string("You can still play the mod, but it might be unstable\r\nThe following problems were encountered while creating the scenario:\r\n\r\nErrors:\r\n") + err.accumulated_errors + "\r\n\r\nWarnings:\r\n" + err.accumulated_warnings;
146 auto fname = NATIVE("scenario_errors.log");
147 simple_fs::write_file(pdir, NATIVE("scenario_errors.log"), assembled_msg.data(), uint32_t(assembled_msg.length()));
148 auto fnamepath = simple_fs::get_full_name(pdir) + NATIVE("/") + NATIVE(fname);
149 //system(xdg-open fnamepath);
150 window::emit_error_message("Some errors were found during generation of scenario file. Please open " + NATIVE(fnamepath) + " to check the errors.\n", false);
151 }
152 window::emit_error_message("Scenario file had been generated and saved to " + native_string(getenv("HOME")) + "/.local/share/Alice/\n", false);
153}
154
155//The function below would better be implemented in a launcher
157 selected_scenario_file = NATIVE("");
158 auto mod_path = produce_mod_path();
159 for(auto& f : scenario_files) {
160 if(f.ident.mod_path == mod_path){
161 selected_scenario_file = f.file_name;
162 break;
163 }
164 }
165}
166
167bool transitively_depends_on_internal(parsers::mod_file const& moda, parsers::mod_file const& modb, std::vector<bool>& seen_indices) {
168 for(auto& dep : moda.dependent_mods) {
169 if(dep == modb.name_)
170 return true;
171
172 for(int32_t i = 0; i < int32_t(mod_list.size()); ++i) {
173 if(seen_indices[i] == false && mod_list[i].name_ == dep) {
174 seen_indices[i] = true;
175 if(transitively_depends_on_internal(mod_list[i], modb, seen_indices))
176 return true;
177 }
178 }
179 }
180 return false;
181}
182
184 std::vector<bool> seen_indices;
185 seen_indices.resize(mod_list.size());
186
187 return transitively_depends_on_internal(moda, modb, seen_indices);
188}
189
191 std::stable_sort(mod_list.begin(), mod_list.end(), [&](parsers::mod_file const& a, parsers::mod_file const& b) {
192 if(a.mod_selected && b.mod_selected) {
193 return transitively_depends_on(b, a);
194 } else if(a.mod_selected && !b.mod_selected) {
195 return true;
196 } else if(!a.mod_selected && b.mod_selected) {
197 return false;
198 } else {
199 return a.name_ < b.name_;
200 }
201 });
202}
203
204int main (int argc, char *argv[]) {
205 add_root(game_state.common_fs, NATIVE("."));
208 if ( argc >= 2) {
209 //TODO: Get all argv as vector and process them before running any codes
210 //for (int args = 1; args < argc; ++args){
211 // arguments.push_back(args);
212 //}
213 for ( int i = 1; i < argc; ++i ) {
214 if (native_string(argv[i]) == NATIVE("--mod")) {
215 //Use closest to standard v2game.exe args structure, i.e. --mod mod/modname.mod
216 //We don't need powerful do-it-all entry point, scenario generation is enough
217 //Always assume that user will run this in the standard way of usage
218 if ( i + 1 < argc ){
219 //Beginning of seemingly unnecessary code
220 std::string fullpath = argv[ i + 1];
221 int idx = fullpath.rfind("/");
222 std::string dir = fullpath.substr(0, idx);
223 if(dir != NATIVE("mod")) {
224 window::emit_error_message("Usage: --mod mod/modname.mod\n", true);
225 }
226 std::string filename = fullpath.substr(idx + 1);
227 //Ending of seemingly unnecessary code
229 simple_fs::add_root(fs_root, ".");
230 auto root = get_root(fs_root);
231 auto mod_dir = simple_fs::open_directory(root, NATIVE(dir));
232 //Implement check of passed argv in mod_list vector, if found, set true to mod_selected
233 //Currently, the code is crude
234 auto of = simple_fs::open_file(mod_dir, NATIVE(filename));
236 std::vector<parsers::mod_file> selected_mod;
237 if(of){
238 auto content = view_contents(*of);
239 parsers::token_generator gen(content.data, content.data + content.file_size);
240 selected_mod.push_back(parsers::parse_mod_file(gen, err, parsers::mod_file_context{}));
241 }
242 //This is to iterate through the content of mod_list
243 for(int32_t modindex = 0; modindex < int32_t(mod_list.size()); ++modindex){
244 if(mod_list[modindex].name_ == selected_mod[0].name_) {
245 mod_list[modindex].mod_selected = true;
246 }
247 }
248 i++;
249 }
250 } else if ( native_string(argv[i]) == NATIVE("--test")) {
251 if (sys::try_read_scenario_and_save_file(game_state, "development_test_file.bin")){
252 selected_scenario_file = "development_test_file.bin";
253 } else {
254 window::emit_error_message("Development test file not found. Proceeding to generate file, this process may take a few minutes to complete.\n", false);
255 parsers::error_handler err{ "" };
256 game_state.load_scenario_data(err, sys::year_month_day{ 1836, 1, 1});
257 if(!err.accumulated_errors.empty() || !err.accumulated_warnings.empty()) {
258 auto assembled_msg = std::string("You can still play the mod, but it might be unstable\r\nThe following problems were encountered while creating the scenario:\r\n\r\nErrors:\r\n") + err.accumulated_errors + "\r\n\r\nWarnings:\r\n" + err.accumulated_warnings;
259 window::emit_error_message(assembled_msg, false);
260 }
261 sys::write_scenario_file(game_state, NATIVE("development_test_file.bin"), 0);
262 selected_scenario_file = "development_test_file.bin";
263 }
264 break;
265 } else if(native_string(argv[i]) == NATIVE("-host")) {
267 } else if(native_string(argv[i]) == NATIVE("-join")) {
269 game_state.network_state.ip_address = "127.0.0.1";
270 if(i + 1 < argc) {
272 i++;
273 }
274 } else if(native_string(argv[i]) == NATIVE("-name")) {
275 if(i + 1 < argc) {
276 std::string nickname = simple_fs::native_to_utf8(native_string(argv[i + 1]));
277 memcpy(game_state.network_state.nickname.data, nickname.data(), std::min<size_t>(nickname.length(), 8));
278 i++;
279 }
280 } else if(native_string(argv[i]) == NATIVE("-password")) {
281 if(i + 1 < argc) {
282 auto str = simple_fs::native_to_utf8(native_string(argv[i + 1]));
283 std::memset(game_state.network_state.password, '\0', sizeof(game_state.network_state.password));
284 std::memcpy(game_state.network_state.password, str.c_str(), std::min(sizeof(game_state.network_state.password), str.length()));
285 i++;
286 }
287 } else if(native_string(argv[i]) == NATIVE("-v6")) {
288 game_state.network_state.as_v6 = true;
289 } else if(native_string(argv[i]) == NATIVE("-v4")) {
290 game_state.network_state.as_v6 = false;
291 }
292 }
294 for (int32_t modindex = 0; modindex < int32_t(mod_list.size()); ++modindex){
295 if(mod_list[modindex].mod_selected){
296 window::emit_error_message("Selected mod: " + NATIVE(mod_list[modindex].name_) + "\n", false);
297 }
298 }
299 //Trying to find the corresponding scenario file before attempting to build
300 //Sacred scenario file = "development_test_file.bin"
301 //Some parts below felt redundant, may not fix
302 if (selected_scenario_file == NATIVE("development_test_file.bin")){
303 } else {
304 //Checking the scenario folder
306 //If any file fits the criteria, then don't build
307 if (!selected_scenario_file.empty()) {
308 window::emit_error_message("Selected scenario file: " + NATIVE(selected_scenario_file) + "\n", false);
309 //If no file fits the critertia, then build
310 } else {
311 window::emit_error_message("Scenario file with selected mods cannot be found. Proceeding to build.\nThis process may take a few minutes to finish.\n", false);
313 }
314 }
315 } else {
316 //Falling back to vanilla
318 if (!selected_scenario_file.empty()) {
319 window::emit_error_message("Selected scenario file: " + NATIVE(selected_scenario_file) + "\n", false);
320 } else {
321 window::emit_error_message("Building the vanilla scenario file. This process may take a few minutes to complete.\n", false);
323 }
324 }
325
326 if (sys::try_read_scenario_and_save_file(game_state, selected_scenario_file)) {
327 auto msg = "Running scenario file " + simple_fs::native_to_utf8(selected_scenario_file) + "\n";
328 window::emit_error_message(msg, false);
329 game_state.loaded_scenario_file = NATIVE(selected_scenario_file);
330 game_state.fill_unsaved_data();
331 } else {
332 window::emit_error_message("Scenario file could not be read.", true);
333 }
334
335 network::init(game_state);
336 game_state.load_user_settings();
338 std::thread update_thread([&]() { game_state.game_loop(); });
339 window::emit_error_message("Starting the game.\n", false);
341 game_state.quit_signaled.store(true, std::memory_order_release);
342 update_thread.join();
343 network::finish(game_state, true);
344
345 return EXIT_SUCCESS;
346}
std::string accumulated_errors
Definition: parsers.hpp:62
std::string accumulated_warnings
Definition: parsers.hpp:63
std::string file_name
Definition: parsers.hpp:61
#define assert(condition)
Definition: debug.h:74
int main(int argc, char *argv[])
native_string produce_mod_path()
void build_scenario_file()
void enforce_list_order()
bool transitively_depends_on_internal(parsers::mod_file const &moda, parsers::mod_file const &modb, std::vector< bool > &seen_indices)
void check_scenario_folder()
bool transitively_depends_on(parsers::mod_file const &moda, parsers::mod_file const &modb)
void find_scenario_file()
void check_mods_folder()
native_string to_hex(uint64_t v)
void finish(sys::state &state, bool notify_host)
Definition: network.cpp:1090
void init(sys::state &state)
Definition: network.cpp:497
std::vector< unopened_file > list_files(directory const &dir, native_char const *extension)
void add_root(file_system &fs, native_string_view root_path)
directory open_directory(directory const &dir, native_string_view directory_name)
native_string extract_state(file_system const &fs)
void restore_state(file_system &fs, native_string_view data)
void write_file(directory const &dir, native_string_view file_name, char const *file_data, uint32_t file_size)
native_string get_full_name(directory const &f)
std::optional< file > open_file(directory const &dir, native_string_view file_name)
std::optional< unopened_file > peek_file(directory const &dir, native_string_view file_name)
std::string native_to_utf8(native_string_view data_in)
file_contents view_contents(file const &f)
native_string get_file_name(unopened_file const &f)
directory get_or_create_scenario_directory()
mod_identifier extract_mod_information(uint8_t const *ptr_in, uint64_t file_size)
@ bookmark
Definition: constants.hpp:568
void write_scenario_file(sys::state &state, native_string_view name, uint32_t count)
void write_save_file(sys::state &state, save_type type, std::string const &name)
bool try_read_scenario_and_save_file(sys::state &state, native_string_view name)
void populate_definitions_map(sys::state &state)
void emit_error_message(std::string const &content, bool fatal)
Definition: window_nix.cpp:355
void create_window(sys::state &game_state, creation_parameters const &params)
Definition: window_nix.cpp:278
char native_char
#define NATIVE(X)
std::string native_string
uint uint32_t
ulong uint64_t
uchar uint8_t
std::string ip_address
Definition: network.hpp:80
sys::player_name nickname
Definition: network.hpp:73
uint8_t password[16]
Definition: network.hpp:90
std::vector< bookmark_definition > bookmark_dates
std::vector< std::string > dependent_mods
sys::mod_identifier ident
native_string file_name
network_mode_type network_mode
user_settings_s user_settings
simple_fs::file_system common_fs
sys::checksum_key scenario_checksum
std::atomic< bool > quit_signaled
void load_user_settings()
void game_loop()
network::network_state network_state
native_string loaded_scenario_file
void load_scenario_data(parsers::error_handler &err, sys::year_month_day bookmark_date)
void fill_unsaved_data()