16 #include "addon/manager.hpp" 59 #include "widgets/button.hpp" 74 #include <boost/iostreams/categories.hpp> 75 #include <boost/iostreams/copy.hpp> 76 #include <boost/iostreams/filter/bzip2.hpp> 80 #pragma warning(disable : 4456) 81 #pragma warning(disable : 4458) 84 #include <boost/iostreams/filter/gzip.hpp> 90 #include <boost/iostreams/filtering_stream.hpp> 91 #include <boost/program_options/errors.hpp> 112 #ifdef INADDR_BROADCAST 113 #undef INADDR_BROADCAST 124 #ifdef DEBUG_WINDOW_LAYOUT_GRAPHS 128 class end_level_exception;
135 #define LOG_CONFIG LOG_STREAM(info, log_config) 137 #define LOG_GENERAL LOG_STREAM(info, lg::general()) 140 #define LOG_PREPROC LOG_STREAM(info, log_preprocessor) 152 template<
typename filter>
153 static void encode(
const std::string& input_file,
const std::string& output_file)
156 std::ifstream ifile(input_file.c_str(),
std::ios_base::in | std::ios_base::binary);
161 <<
" is not good for reading. Exiting to prevent bzip2 from segfaulting";
165 std::ofstream ofile(output_file.c_str(), std::ios_base::out | std::ios_base::binary);
167 boost::iostreams::filtering_stream<boost::iostreams::output> stream;
168 stream.push(filter());
171 boost::iostreams::copy(ifile, stream);
180 template<
typename filter>
181 static void decode(
const std::string& input_file,
const std::string& output_file)
184 std::ofstream ofile(output_file.c_str(), std::ios_base::out | std::ios_base::binary);
185 std::ifstream ifile(input_file.c_str(),
std::ios_base::in | std::ios_base::binary);
187 boost::iostreams::filtering_stream<boost::iostreams::input> stream;
188 stream.push(filter());
191 boost::iostreams::copy(stream, ofile);
200 static void gzip_encode(
const std::string& input_file,
const std::string& output_file)
202 encode<boost::iostreams::gzip_compressor>(input_file, output_file);
205 static void gzip_decode(
const std::string& input_file,
const std::string& output_file)
207 decode<boost::iostreams::gzip_decompressor>(input_file, output_file);
210 static void bzip2_encode(
const std::string& input_file,
const std::string& output_file)
212 encode<boost::iostreams::bzip2_compressor>(input_file, output_file);
215 static void bzip2_decode(
const std::string& input_file,
const std::string& output_file)
217 decode<boost::iostreams::bzip2_decompressor>(input_file, output_file);
227 PLAIN_LOG <<
"please specify an existing file. File " << file <<
" doesn't exist.";
231 PLAIN_LOG << SDL_GetTicks() <<
" Reading cached defines from: " << file;
239 PLAIN_LOG <<
"Caught a config error while parsing file '" << file <<
"':\n" << e.
message;
247 input_macros[def.first] = def.second;
251 PLAIN_LOG << SDL_GetTicks() <<
" Read " << read <<
" defines.";
257 uint32_t startTime = SDL_GetTicks();
260 bool skipCore =
false;
261 bool skipTerrainGFX =
false;
277 if(define ==
"SKIP_CORE") {
280 }
else if(define ==
"NO_TERRAIN_GFX") {
281 PLAIN_LOG <<
"'NO_TERRAIN_GFX' defined.";
282 skipTerrainGFX =
true;
290 PLAIN_LOG <<
"added " << defines_map.size() <<
" defines.";
293 if(skipCore ==
false) {
294 PLAIN_LOG <<
"preprocessing common macros from 'data/core' ...";
299 if(skipTerrainGFX ==
false) {
303 PLAIN_LOG <<
"acquired " << (defines_map.size() - input_macros.size()) <<
" 'data/core' defines.";
309 PLAIN_LOG <<
"preprocessing specified resource: " << resourceToProcess <<
" ...";
312 PLAIN_LOG <<
"acquired " << (defines_map.size() - input_macros.size()) <<
" total defines.";
315 std::string outputFileName =
"_MACROS_.cfg";
320 std::string outputPath = targetDir +
"/" + outputFileName;
322 PLAIN_LOG <<
"writing '" << outputPath <<
"' with " << defines_map.size() <<
" defines.";
328 for(
auto& define_pair : defines_map) {
329 define_pair.second.write(writer, define_pair.first);
336 PLAIN_LOG <<
"preprocessing finished. Took " << SDL_GetTicks() - startTime <<
" ticks.";
344 for(
const std::string& define : defines) {
353 PLAIN_LOG <<
"Validating " << file <<
" against schema " << validator.
name_;
357 read(result, *stream, &validator);
359 std::cout <<
"validation failed\n";
361 std::cout <<
"validation succeeded\n";
371 if(cmdline_opts.
log) {
372 for(
const auto& log_pair : *cmdline_opts.
log) {
373 const std::string log_domain = log_pair.second;
374 const int severity = log_pair.first;
376 PLAIN_LOG <<
"unknown log domain: " << log_domain;
410 const std::string datadir = *cmdline_opts.
data_dir;
413 if(datadir.c_str()[1] ==
':') {
415 if(datadir[0] ==
'/') {
454 const std::string input_file(*cmdline_opts.
gunzip);
456 PLAIN_LOG <<
"file '" << input_file <<
"'isn't a .gz file";
460 const std::string output_file(input_file, 0, input_file.length() - 3);
465 const std::string input_file(*cmdline_opts.
bunzip2);
467 PLAIN_LOG <<
"file '" << input_file <<
"'isn't a .bz2 file";
471 const std::string output_file(input_file, 0, input_file.length() - 4);
475 if(cmdline_opts.
gzip) {
476 const std::string input_file(*cmdline_opts.
gzip);
477 const std::string output_file(*cmdline_opts.
gzip +
".gz");
481 if(cmdline_opts.
bzip2) {
482 const std::string input_file(*cmdline_opts.
bzip2);
483 const std::string output_file(*cmdline_opts.
bzip2 +
".bz2");
487 if(cmdline_opts.
help) {
488 std::cout << cmdline_opts;
506 SDL_setenv(
"SDL_VIDEODRIVER",
"dummy", 1);
540 std::ifstream in_left(cmdline_opts.
diff_left);
541 std::ifstream in_right(cmdline_opts.
diff_right);
543 read(right, in_right);
544 std::ostream* os = &std::cout;
550 if(os != &std::cout)
delete os;
556 std::ifstream in_base(cmdline_opts.
diff_left);
557 std::ifstream in_diff(cmdline_opts.
diff_right);
561 std::ostream* os = &std::cout;
567 if(os != &std::cout)
delete os;
579 std::string schema_path;
585 PLAIN_LOG <<
"Could not find schema file: " << schema_path;
604 PLAIN_LOG <<
"That --preprocess-* option is only supported when using --preprocess or --validate-wml.";
621 #if defined _WIN32 || defined __APPLE__ 622 setlocale(LC_ALL,
"English");
624 std::setlocale(LC_ALL,
"C");
647 <<
"An error at this point during initialization usually indicates that the data\n" 648 <<
"directory above was not correctly set or detected. Try passing the correct path\n" 649 <<
"in the command line with the --data-dir switch or as the only argument.";
658 static bool first_time =
true;
677 if(_controlfp_s(&f_control, 0, 0) == 0) {
679 uint32_t rounding_mode = f_control & _MCW_RC;
681 if(rounding_mode != _RC_NEAR) {
682 PLAIN_LOG <<
"Floating point rounding mode is currently '" 683 << ((rounding_mode == _RC_CHOP)
685 : (rounding_mode == _RC_UP)
687 : (rounding_mode == _RC_DOWN)
689 : (rounding_mode == _RC_NEAR) ?
"near" :
"unknown")
690 <<
"' setting to 'near'";
692 if(_controlfp_s(&unused, _RC_NEAR, _MCW_RC)) {
693 PLAIN_LOG <<
"failed to set floating point rounding type to 'near'";
698 uint32_t precision_mode = f_control & _MCW_PC;
699 if(precision_mode != _PC_53) {
700 PLAIN_LOG <<
"Floating point precision mode is currently '" 701 << ((precision_mode == _PC_53)
703 : (precision_mode == _PC_24)
705 : (precision_mode == _PC_64) ?
"double extended" :
"unknown")
706 <<
"' setting to 'double'";
708 if(_controlfp_s(&unused, _PC_53, _MCW_PC)) {
709 PLAIN_LOG <<
"failed to set floating point precision type to 'double'";
721 switch(fegetround()) {
725 STREAMING_LOG <<
"Floating point precision mode is currently 'downward'";
728 STREAMING_LOG <<
"Floating point precision mode is currently 'toward-zero'";
731 STREAMING_LOG <<
"Floating point precision mode is currently 'upward'";
734 STREAMING_LOG <<
"Floating point precision mode is currently 'unknown'";
738 fesetround(FE_TONEAREST);
750 srand(std::time(
nullptr));
759 std::cerr <<
"Press enter to continue..." << std::endl;
767 const auto game = std::make_unique<game_launcher>(cmdline_opts);
768 const int start_ticks = SDL_GetTicks();
779 PLAIN_LOG <<
"could not initialize fonts";
785 res =
game->init_language();
787 PLAIN_LOG <<
"could not initialize the language";
791 res =
game->init_video();
793 PLAIN_LOG <<
"could not initialize display";
801 #if(defined(_X11) && !defined(__APPLE__)) || defined(_WIN32) 802 SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
820 PLAIN_LOG <<
"could not initialize game config";
828 PLAIN_LOG <<
"could not re-initialize fonts for the current language";
843 LOG_CONFIG <<
"time elapsed: " << (SDL_GetTicks() - start_ticks) <<
" ms";
862 if(!
game->has_load_data()) {
869 config title_music_config;
871 title_music_config[
"append"] =
true;
872 title_music_config[
"immediate"] =
true;
886 return static_cast<int>(
game->unit_test());
889 if(
game->play_test() ==
false) {
893 if(
game->play_screenshot_mode() ==
false) {
897 if(
game->play_render_image_mode() ==
false) {
902 if(
game->goto_campaign() ==
false) {
903 if(
game->jump_to_campaign_id().empty())
911 if(
game->goto_multiplayer() ==
false) {
916 if(
game->play_multiplayer_commandline() ==
false) {
920 if(
game->goto_editor() ==
false) {
929 if(
game->has_load_data() &&
game->load_game()) {
967 game->start_editor();
970 gui2::dialogs::end_credits::display();
987 std::string auto_dir;
992 auto_dir = std::move(exe_dir);
1024 #define error_exit(res) \ 1026 if(lg::using_own_console()) { \ 1027 std::cerr << "Press enter to continue..." << std::endl; \ 1033 #define error_exit(res) return res 1044 assert(!args.empty());
1048 bool nobanner =
false;
1049 bool log_to_file =
true;
1050 for(
const auto& arg : args) {
1051 if(arg ==
"--nobanner") {
1055 else if(arg ==
"--no-log-to-file") {
1056 log_to_file =
false;
1066 bool log_redirect =
true, native_console_implied =
false;
1068 std::optional<bool> native_console_force;
1070 _putenv(
"PANGOCAIRO_BACKEND=fontconfig");
1071 _putenv(
"FONTCONFIG_PATH=fonts");
1082 for(
const auto& arg : args) {
1084 static const std::set<std::string> wincon_switches = {
1085 "--wconsole",
"-h",
"--help",
"-v",
"--version",
"-R",
"--report",
"--logdomains",
1086 "--data-path",
"--userdata-path",
"--userconfig-path",
1092 static const std::set<std::string> wincon_arg_switches = {
1093 "-D",
"--diff",
"-p",
"--preprocess",
"-P",
"--patch",
"--render-image",
1094 "--screenshot",
"-V",
"--validate",
"--validate-schema",
1097 auto switch_matches_arg = [&arg](
const std::string&
sw) {
1098 const auto pos = arg.find(
'=');
1099 return pos == std::string::npos ? arg ==
sw : arg.substr(0, pos) ==
sw;
1102 if(wincon_switches.find(arg) != wincon_switches.end() ||
1103 std::find_if(wincon_arg_switches.begin(), wincon_arg_switches.end(), switch_matches_arg) != wincon_arg_switches.end()) {
1104 native_console_implied =
true;
1107 if(arg ==
"--wnoconsole") {
1108 native_console_force =
false;
1109 }
else if(arg ==
"--wconsole") {
1110 native_console_force =
true;
1111 }
else if(arg ==
"--wnoredirect") {
1112 log_redirect =
false;
1116 if(native_console_force.value_or(native_console_implied)) {
1123 if(SDL_Init(SDL_INIT_TIMER) < 0) {
1124 PLAIN_LOG <<
"Couldn't initialize SDL: " << SDL_GetError();
1130 struct sigaction terminate_handler;
1132 terminate_handler.sa_flags = 0;
1134 sigemptyset(&terminate_handler.sa_mask);
1135 sigaction(SIGTERM, &terminate_handler,
nullptr);
1136 sigaction(SIGINT, &terminate_handler,
nullptr);
1141 #if defined(__APPLE__) && !defined(__IPHONEOS__) 1142 SDL_EventState(SDL_FINGERMOTION, SDL_DISABLE);
1143 SDL_EventState(SDL_FINGERDOWN, SDL_DISABLE);
1144 SDL_EventState(SDL_FINGERUP, SDL_DISABLE);
1150 SDL_StartTextInput();
1155 const std::time_t
t = std::time(
nullptr);
1156 PLAIN_LOG <<
"Started on " << ctime(&t);
1162 PLAIN_LOG <<
"Automatically found a possible data directory at: " << auto_dir;
1170 }
catch(
const boost::program_options::error&
e) {
1171 PLAIN_LOG <<
"Error in command line: " << e.what();
1177 PLAIN_LOG <<
"Could not initialize fonts.\n\n" << e.
what() <<
"\n\nExiting.";
1183 PLAIN_LOG <<
"Could not create button: Image could not be found";
1188 PLAIN_LOG <<
"caught return_to_play_side_exception, please report this bug (quitting)";
1190 PLAIN_LOG <<
"caught quit_game_exception (quitting)";
1203 }
catch(
const std::bad_alloc&) {
1204 PLAIN_LOG <<
"Ran out of memory. Aborted.";
1206 #if !defined(NO_CATCH_AT_GAME_END) 1207 }
catch(
const std::exception& e) {
1209 PLAIN_LOG <<
"Caught general '" <<
typeid(
e).name() <<
"' exception:\n" << e.what();
1211 }
catch(
const std::string& e) {
1212 PLAIN_LOG <<
"Caught a string thrown as an exception:\n" <<
e;
1214 }
catch(
const char* e) {
1215 PLAIN_LOG <<
"Caught a string thrown as an exception:\n" <<
e;
bool log_precise_timestamps
True if –log-precise was given on the command line.
std::optional< std::string > preprocess_path
Path to parse that was given to the –preprocess option.
static void wesnoth_terminate_handler(int)
std::vector< Reg > reg_vec
std::optional< std::string > output_file
Output filename for WML diff or preprocessing.
void set_callback(const std::string &name, callback_function)
std::optional< std::string > preprocess_output_macros
Non-empty if –preprocess-output-macros was given on the command line.
static int handle_validate_command(const std::string &file, abstract_validator &validator, const std::vector< std::string > &defines)
void bind_textdomain(const char *domain, const char *directory, const char *)
const_all_children_itors all_children_range() const
In-order iteration over all children.
bool using_own_console()
Returns true if a console was allocated by the Wesnoth process.
void write(const config &cfg)
bool play_multiplayer(mp_mode mode)
void set(CURSOR_TYPE type)
Use the default parameter to reset cursors.
std::string library_versions_report()
Produce a plain-text report of library versions suitable for stdout/stderr.
static void bzip2_encode(const std::string &input_file, const std::string &output_file)
static void bzip2_decode(const std::string &input_file, const std::string &output_file)
Interfaces for manipulating version numbers of engine, add-ons, etc.
An error specifically indicating video subsystem problems.
static lg::log_domain log_preprocessor("preprocessor")
Add a special kind of assert to validate whether the input from WML doesn't contain any problems that...
std::string optional_features_report()
Produce a plain-text report of features suitable for stdout/stderr.
bool noaddons
True if –noaddons was given on the command line.
Exception used to escape form the ai or ui code to playsingle_controller::play_side.
void set_user_data_dir(std::string newprefdir)
static bool file_exists(const bfs::path &fpath)
child_itors child_range(config_key_type key)
bool userdata_path
True if –userdata-path was given on the command line.
static void gzip_decode(const std::string &input_file, const std::string &output_file)
static void progress(loading_stage stage=loading_stage::none)
Report what is being loaded to the loading screen.
filesystem::scoped_istream istream_file(const std::string &fname, bool treat_failure_as_error)
std::string user_message
The message for the user explaining what went wrong.
This class implements the title screen.
std::optional< std::string > preprocess_target
Target (output) path that was given to the –preprocess option.
std::optional< std::string > preprocess_input_macros
Non-empty if –preprocess-input-macros was given on the command line.
std::optional< std::string > userconfig_dir
Non-empty if –userconfig-dir was given on the command line.
void preprocess_resource(const std::string &res_name, preproc_map *defines_map, bool write_cfg, bool write_plain_cfg, const std::string &parent_directory)
std::vector< std::string > unit_test
Non-empty if –unit was given on the command line.
std::string get_unknown_exception_type()
Utility function for finding the type of thing caught with catch(...).
void early_log_file_setup(bool disable)
Sets up the initial temporary log file.
Don't reload if the previous defines equal the new defines.
static void safe_exit(int res)
std::string normalize_path(const std::string &fpath, bool normalize_separators, bool resolve_dot_entries)
Returns the absolute path of a file.
Contains the exception interfaces used to signal completion of a scenario, campaign or turn...
void set_cache_dir(const std::string &newcachedir)
bool show(const unsigned auto_close_time=0)
Shows the window.
Definitions for the interface to Wesnoth Markup Language (WML).
static void decode(const std::string &input_file, const std::string &output_file)
std::string diff_left
Files for diffing or patching.
filesystem::scoped_ostream ostream_file(const std::string &fname, std::ios_base::openmode mode, bool create_directory)
bool preprocess
True if –preprocess was given on the command line.
config get_diff(const config &c) const
A function to get the differences between this object, and 'c', as another config object...
One of the realizations of serialization/validator.hpp abstract validator.
unsigned in
If equal to search_counter, the node is off the list.
Used in parsing config file.
static void warn_early_init_failure()
Print an alert and instructions to stderr about early initialization errors.
bool report
True if –report was given on the command line.
std::optional< std::string > gzip
Non-empty if –gzip was given on the command line.
void read(config &cfg, std::istream &in, abstract_validator *validator)
Class for writing a config out to a file in pieces.
bool simple_version
True if –simple-version was given on the command line.
std::string get_user_data_dir()
std::optional< unsigned int > rng_seed
RNG seed specified by –rng-seed option.
std::optional< std::vector< std::pair< int, std::string > > > log
Contains parsed arguments of –log-* (e.g.
std::string get_intl_dir()
static lg::log_domain log_config("config")
bool strict_validation_enabled
void init()
Initializes the GUI subsystems.
const game_config_view & game_config() const
std::optional< std::string > bunzip2
Non-empty if –bunzip2 was given on the command line.
void enable_native_console_output()
Switches to using a native console instead of log file redirection.
bool is_directory(const std::string &fname)
Returns true if the given file is a directory.
std::unique_ptr< std::istream > scoped_istream
std::string build_arch()
Obtain the processor architecture for this build.
void set_default_textdomain(const char *domain)
void refresh_addon_version_info_cache()
Refreshes the per-session cache of add-on's version information structs.
void apply_diff(const config &diff, bool track=false)
A function to apply a diff config onto this config object.
const char * what() const noexcept
bool userconfig_path
True if –userconfig-path was given on the command line.
std::optional< std::string > bzip2
Non-empty if –bzip2 was given on the command line.
static void handle_preprocess_command(const commandline_options &cmdline_opts)
bool nobanner
True if –nobanner was given on the command line.
int main(int argc, char **argv)
std::optional< std::string > logdomains
Non-empty if –logdomains was given on the command line.
std::optional< std::string > render_image
Image path to render.
Helper class, don't construct this directly.
static int do_gameloop(const std::vector< std::string > &args)
Setups the game environment and enters the titlescreen or game loops.
std::string dev_message
The message for developers telling which problem was triggered, this shouldn't be translated...
static void gzip_encode(const std::string &input_file, const std::string &output_file)
std::unique_ptr< std::ostream > scoped_ostream
bool is_gzip_file(const std::string &filename)
Returns true if the file ends with '.gz'.
Some defines: VERSION, PACKAGE, MIN_SAVEGAME_VERSION.
std::string get_cache_dir()
static void handle_lua_script_args(game_launcher *game, commandline_options &)
Handles the lua script command line arguments if present.
std::string get_exe_dir()
static void init_locale()
I would prefer to setup locale first so that early error messages can get localized, but we need the game_launcher initialized to have filesystem::get_intl_dir() to work.
Log file control routines for Windows.
void set_user_config_dir(const std::string &newconfigdir)
bool debug_lua
True if –debug-lua was given in the commandline.
std::string get_wml_location(const std::string &filename, const std::string ¤t_dir)
Returns a complete path to the actual WML file or directory or an empty string if the file isn't pres...
bool allow_insecure
True if –allow-insecure was given in the commandline.
const std::string revision
void set_strict_severity(int severity)
bool usercache_path
True if –usercache-path was given on the command line.
static int process_command_args(const commandline_options &cmdline_opts)
Process commandline-arguments.
bool strict_lua
True if –strict-lua was given in the commandline.
std::optional< std::string > gunzip
Non-empty if –gunzip was given on the command line.
An exception object used when an IO error occurs.
structure which will hide all current floating labels, and cause floating labels instantiated after i...
std::optional< std::string > userdata_dir
Non-empty if –userdata-dir was given on the command line.
Declarations for File-IO.
Contains a basic exception class for SDL operations.
Type that can be thrown as an exception to quit to desktop.
const version_info wesnoth_version(VERSION)
static map_location::DIRECTION sw
bool set_log_domain_severity(const std::string &name, int severity)
std::optional< std::string > data_dir
Non-empty if –data-dir was given on the command line.
bool data_path
True if –data-path was given on the command line.
std::vector< std::string > read_argv([[maybe_unused]] int argc, [[maybe_unused]] char **argv)
std::string get_user_config_dir()
bool screenshot
True if –screenshot was given on the command line.
bool is_bzip2_file(const std::string &filename)
Returns true if the file ends with '.bz2'.
int get_retval() const
Returns the cached window exit code.
static void display(std::function< void()> f)
std::vector< aReg > areg_vec
Contains the SDL_Rect helper code.
Base class for all the errors encountered by the engine.
void play_music_config(const config &music_node, bool allow_interrupt_current_track, int i)
std::string list_logdomains(const std::string &filter)
bool version
True if –version was given on the command line.
Standard logging facilities (interface).
std::string str() const
Serializes the version number into string form.
std::optional< std::string > validate_with
Non-empty if –use-schema was given on the command line.
std::optional< std::string > validate_wml
Non-empty if –validate was given on the command line.
bool strict_validation
True if –strict-validation was given on the command line.
std::map< std::string, struct preproc_define > preproc_map
std::optional< std::vector< std::string > > preprocess_defines
Defines that were given to the –preprocess option.
retval
Default window/dialog return values.
static void encode(const std::string &input_file, const std::string &output_file)
Realization of serialization/validator.hpp abstract validator.
void reload_changed_game_config()
void set_create_exceptions(bool value)
A config object defines a single node in a WML file, with access to child nodes.
filesystem::scoped_istream preprocess_file(const std::string &fname, preproc_map *defines)
Function to use the WML preprocessor on a file.
static preproc_map::value_type read_pair(const config &)
int wesnoth_main(int argc, char **argv)
std::optional< std::string > validate_schema
Non-empty if –validate-schema was given on the command line.
bool init_game_config(FORCE_RELOAD_CONFIG force_reload)
bool help
True if –help was given on the command line.
const config & child(config_key_type key) const
std::string directory_name(const std::string &file)
Returns the directory name of a file, with filename stripped.
std::string full_build_report()
Produce a bug report-style info dump.
std::string wesnoth_program_dir
static std::string autodetect_game_data_dir(std::string exe_dir)
Try to autodetect the location of the game data dir.
void precise_timestamps(bool pt)
void set_debug(bool new_debug)
std::optional< std::string > usercache_dir
Non-empty if –usercache-dir was given on the command line.