16 #include "addon/manager.hpp"
54 #include "widgets/button.hpp"
69 #include <boost/program_options/errors.hpp>
70 #include <boost/algorithm/string/predicate.hpp>
91 #ifdef INADDR_BROADCAST
92 #undef INADDR_BROADCAST
103 #ifdef DEBUG_WINDOW_LAYOUT_GRAPHS
108 #define LOG_CONFIG LOG_STREAM(info, log_config)
110 #define LOG_GENERAL LOG_STREAM(info, lg::general())
113 #define LOG_PREPROC LOG_STREAM(info, log_preprocessor)
131 PLAIN_LOG <<
"please specify an existing file. File " << file <<
" doesn't exist.";
135 PLAIN_LOG << SDL_GetTicks() <<
" Reading cached defines from: " << file;
143 PLAIN_LOG <<
"Caught a config error while parsing file '" << file <<
"':\n" <<
e.message;
151 input_macros[def.first] = def.second;
155 PLAIN_LOG << SDL_GetTicks() <<
" Read " <<
read <<
" defines.";
161 uint32_t startTime = SDL_GetTicks();
164 bool skipCore =
false;
165 bool skipTerrainGFX =
false;
181 if(define ==
"SKIP_CORE") {
184 }
else if(define ==
"NO_TERRAIN_GFX") {
185 PLAIN_LOG <<
"'NO_TERRAIN_GFX' defined.";
186 skipTerrainGFX =
true;
194 PLAIN_LOG <<
"added " << defines_map.size() <<
" defines.";
197 if(skipCore ==
false) {
198 PLAIN_LOG <<
"preprocessing common macros from 'data/core' ...";
203 if(skipTerrainGFX ==
false) {
207 PLAIN_LOG <<
"acquired " << (defines_map.size() - input_macros.size()) <<
" 'data/core' defines.";
213 PLAIN_LOG <<
"preprocessing specified resource: " << resourceToProcess <<
" ...";
216 PLAIN_LOG <<
"acquired " << (defines_map.size() - input_macros.size()) <<
" total defines.";
219 std::string outputFileName =
"_MACROS_.cfg";
224 std::string outputPath = targetDir +
"/" + outputFileName;
226 PLAIN_LOG <<
"writing '" << outputPath <<
"' with " << defines_map.size() <<
" defines.";
232 for(
auto& define_pair : defines_map) {
233 define_pair.second.write(writer, define_pair.first);
240 PLAIN_LOG <<
"preprocessing finished. Took " << SDL_GetTicks() - startTime <<
" ticks.";
248 for(
const std::string& define : defines) {
257 PLAIN_LOG <<
"Validating " << file <<
" against schema " << validator.
name_;
261 read(result, *stream, &validator);
263 std::cout <<
"validation failed\n";
265 std::cout <<
"validation succeeded\n";
275 if(cmdline_opts.
log) {
276 for(
const auto& log_pair : *cmdline_opts.
log) {
277 const std::string log_domain = log_pair.second;
280 PLAIN_LOG <<
"unknown log domain: " << log_domain;
314 const std::string datadir = *cmdline_opts.
data_dir;
315 PLAIN_LOG <<
"Starting with directory: '" << datadir <<
"'";
318 if(datadir.c_str()[1] ==
':') {
320 if(datadir[0] ==
'/') {
359 if(cmdline_opts.
help) {
360 std::cout << cmdline_opts;
378 SDL_setenv(
"SDL_VIDEODRIVER",
"dummy", 1);
412 std::ifstream in_left(cmdline_opts.
diff_left);
413 std::ifstream in_right(cmdline_opts.
diff_right);
415 read(right, in_right);
416 std::ostream* os = &std::cout;
422 if(os != &std::cout)
delete os;
428 std::ifstream in_base(cmdline_opts.
diff_left);
429 std::ifstream in_diff(cmdline_opts.
diff_right);
433 std::ostream* os = &std::cout;
439 if(os != &std::cout)
delete os;
451 std::string schema_path;
457 PLAIN_LOG <<
"Could not find schema file: " << schema_path;
476 PLAIN_LOG <<
"That --preprocess-* option is only supported when using --preprocess or --validate-wml.";
493 #if defined _WIN32 || defined __APPLE__
494 setlocale(LC_ALL,
"English");
496 std::setlocale(LC_ALL,
"C");
519 <<
"An error at this point during initialization usually indicates that the data\n"
520 <<
"directory above was not correctly set or detected. Try passing the correct path\n"
521 <<
"in the command line with the --data-dir switch or as the only argument.";
530 static bool first_time =
true;
538 if(!
game->init_lua_script()) {
549 if(_controlfp_s(&f_control, 0, 0) == 0) {
551 uint32_t rounding_mode = f_control & _MCW_RC;
553 if(rounding_mode != _RC_NEAR) {
554 PLAIN_LOG <<
"Floating point rounding mode is currently '"
555 << ((rounding_mode == _RC_CHOP)
557 : (rounding_mode == _RC_UP)
559 : (rounding_mode == _RC_DOWN)
561 : (rounding_mode == _RC_NEAR) ?
"near" :
"unknown")
562 <<
"' setting to 'near'";
564 if(_controlfp_s(&unused, _RC_NEAR, _MCW_RC)) {
565 PLAIN_LOG <<
"failed to set floating point rounding type to 'near'";
570 uint32_t precision_mode = f_control & _MCW_PC;
571 if(precision_mode != _PC_53) {
572 PLAIN_LOG <<
"Floating point precision mode is currently '"
573 << ((precision_mode == _PC_53)
575 : (precision_mode == _PC_24)
577 : (precision_mode == _PC_64) ?
"double extended" :
"unknown")
578 <<
"' setting to 'double'";
580 if(_controlfp_s(&unused, _PC_53, _MCW_PC)) {
581 PLAIN_LOG <<
"failed to set floating point precision type to 'double'";
593 switch(fegetround()) {
597 STREAMING_LOG <<
"Floating point precision mode is currently 'downward'";
600 STREAMING_LOG <<
"Floating point precision mode is currently 'toward-zero'";
603 STREAMING_LOG <<
"Floating point precision mode is currently 'upward'";
606 STREAMING_LOG <<
"Floating point precision mode is currently 'unknown'";
610 fesetround(FE_TONEAREST);
622 srand(std::time(
nullptr));
630 std::cerr <<
"Press enter to continue..." << std::endl;
638 const auto game = std::make_unique<game_launcher>(cmdline_opts);
639 const int start_ticks = SDL_GetTicks();
650 PLAIN_LOG <<
"could not initialize fonts";
656 res =
game->init_language();
658 PLAIN_LOG <<
"could not initialize the language";
662 res =
game->init_video();
664 PLAIN_LOG <<
"could not initialize display";
672 #if(defined(_X11) && !defined(__APPLE__)) || defined(_WIN32)
673 SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
685 std::string
msg =
VGETTEXT(
"Unable to create log files in directory $logdir. This is often caused by incorrect folder permissions, anti-virus software restricting folder access, or using OneDrive to manage your My Documents folder.", symbols);
701 PLAIN_LOG <<
"could not initialize game config";
709 PLAIN_LOG <<
"could not re-initialize fonts for the current language";
724 LOG_CONFIG <<
"time elapsed: " << (SDL_GetTicks() - start_ticks) <<
" ms";
741 if(!
game->has_load_data()) {
748 config title_music_config;
750 title_music_config[
"append"] =
true;
751 title_music_config[
"immediate"] =
true;
765 return static_cast<int>(
game->unit_test());
768 if(
game->play_test() ==
false) {
772 if(
game->play_screenshot_mode() ==
false) {
776 if(
game->play_render_image_mode() ==
false) {
781 if(
game->goto_campaign() ==
false) {
782 if(
game->jump_to_campaign_id().empty())
790 if(
game->goto_multiplayer() ==
false) {
795 if(
game->play_multiplayer_commandline() ==
false) {
799 if(
game->goto_editor() ==
false) {
808 if(
game->has_load_data() &&
game->load_game()) {
846 game->start_editor();
849 gui2::dialogs::end_credits::display();
866 std::string auto_dir;
871 auto_dir = std::move(exe_dir);
896 #define error_exit(res) \
898 if(lg::using_own_console()) { \
899 std::cerr << "Press enter to continue..." << std::endl; \
905 #define error_exit(res) return res
912 int main(
int argc,
char** argv)
916 assert(!args.empty());
919 _putenv(
"PANGOCAIRO_BACKEND=fontconfig");
920 _putenv(
"FONTCONFIG_PATH=fonts");
926 bool write_to_log_file = !getenv(
"WESNOTH_NO_LOG_FILE");
932 bool nobanner =
false;
933 for(
const auto& arg : args) {
934 if(arg ==
"--nobanner") {
949 for(
const auto& arg : args) {
951 static const std::set<std::string> terminal_switches = {
952 "--config-path",
"--data-path",
"-h",
"--help",
"--logdomains",
"--nogui",
"-R",
"--report",
953 "--simple-version",
"--userconfig-path",
"--userdata-path",
"-v",
"--version"
959 static const std::set<std::string> terminal_arg_switches = {
960 "-D",
"--diff",
"-p",
"--preprocess",
"-P",
"--patch",
"--render-image",
"--screenshot",
961 "-u",
"--unit",
"-V",
"--validate",
"--validate-schema"
964 auto switch_matches_arg = [&arg](
const std::string&
sw) {
965 const auto pos = arg.find(
'=');
966 return pos == std::string::npos ? arg ==
sw : arg.substr(0, pos) ==
sw;
969 if(terminal_switches.find(arg) != terminal_switches.end() ||
970 std::find_if(terminal_arg_switches.begin(), terminal_arg_switches.end(), switch_matches_arg) != terminal_arg_switches.end()) {
971 write_to_log_file =
false;
974 if(arg ==
"--no-log-to-file") {
975 write_to_log_file =
false;
976 }
else if(arg ==
"--log-to-file") {
977 write_to_log_file =
true;
980 if(arg ==
"--wnoconsole") {
987 if(write_to_log_file) {
997 SDL_SetHint(SDL_HINT_NO_SIGNAL_HANDLERS,
"1");
999 if(SDL_Init(SDL_INIT_TIMER) < 0) {
1000 PLAIN_LOG <<
"Couldn't initialize SDL: " << SDL_GetError();
1007 #if defined(__APPLE__) && !defined(__IPHONEOS__)
1008 SDL_EventState(SDL_FINGERMOTION, SDL_DISABLE);
1009 SDL_EventState(SDL_FINGERDOWN, SDL_DISABLE);
1010 SDL_EventState(SDL_FINGERUP, SDL_DISABLE);
1016 SDL_StartTextInput();
1021 const std::time_t
t = std::time(
nullptr);
1028 PLAIN_LOG <<
"Automatically found a possible data directory at: " << auto_dir;
1032 bool data_dir_specified =
false;
1033 for(
int i=0;
i<argc;
i++) {
1034 if(std::string(argv[
i]) ==
"--data-dir" || boost::algorithm::starts_with(argv[
i],
"--data-dir=")) {
1035 data_dir_specified =
true;
1039 if (!data_dir_specified) {
1040 PLAIN_LOG <<
"Cannot find a data directory. Specify one with --data-dir";
1048 }
catch(
const boost::program_options::error&
e) {
1049 PLAIN_LOG <<
"Error in command line: " <<
e.what();
1052 PLAIN_LOG <<
"Video system error: " <<
e.what();
1055 PLAIN_LOG <<
"Could not initialize fonts.\n\n" <<
e.what() <<
"\n\nExiting.";
1061 PLAIN_LOG <<
"Could not create button: Image could not be found";
1066 PLAIN_LOG <<
"caught return_to_play_side_exception, please report this bug (quitting)";
1068 PLAIN_LOG <<
"caught quit_game_exception (quitting)";
1070 PLAIN_LOG <<
"WML exception:\nUser message: " <<
e.user_message <<
"\nDev message: " <<
e.dev_message;
1073 PLAIN_LOG <<
e.what() <<
"\n\nGame will be aborted.";
1081 }
catch(
const std::bad_alloc&) {
1082 PLAIN_LOG <<
"Ran out of memory. Aborted.";
1084 #if !defined(NO_CATCH_AT_GAME_END)
1085 }
catch(
const std::exception&
e) {
1087 PLAIN_LOG <<
"Caught general '" <<
typeid(
e).name() <<
"' exception:\n" <<
e.what();
1089 }
catch(
const std::string&
e) {
1090 PLAIN_LOG <<
"Caught a string thrown as an exception:\n" <<
e;
1092 }
catch(
const char*
e) {
1093 PLAIN_LOG <<
"Caught a string thrown as an exception:\n" <<
e;
int wesnoth_main(int argc, char **argv)
void refresh_addon_version_info_cache()
Refreshes the per-session cache of add-on's version information structs.
Used in parsing config file.
std::optional< std::string > preprocess_input_macros
Non-empty if –preprocess-input-macros was given on the command line.
bool simple_version
True if –simple-version was given on the command line.
bool report
True if –report was given on the command line.
std::optional< std::string > validate_wml
Non-empty if –validate was given on the command line.
bool strict_lua
True if –strict-lua was given in the commandline.
std::optional< std::string > preprocess_path
Path to parse that was given to the –preprocess option.
std::optional< std::string > userdata_dir
Non-empty if –userdata-dir was given on the command line.
std::optional< std::string > render_image
Image path to render.
std::optional< std::string > preprocess_output_macros
Non-empty if –preprocess-output-macros was given on the command line.
std::optional< std::string > logdomains
Non-empty if –logdomains was given on the command line.
std::optional< unsigned int > rng_seed
RNG seed specified by –rng-seed option.
bool userconfig_path
True if –userconfig-path was given on the command line.
bool nobanner
True if –nobanner was given on the command line.
bool preprocess
True if –preprocess was given on the command line.
std::string diff_left
Files for diffing or patching.
bool data_path
True if –data-path was given on the command line.
bool version
True if –version was given on the command line.
bool allow_insecure
True if –allow-insecure was given in the commandline.
std::optional< std::string > output_file
Output filename for WML diff or preprocessing.
bool noaddons
True if –noaddons was given on the command line.
std::optional< std::string > preprocess_target
Target (output) path that was given to the –preprocess option.
bool debug_lua
True if –debug-lua was given in the commandline.
std::vector< std::string > unit_test
Non-empty if –unit was given on the command line.
bool userdata_path
True if –userdata-path was given on the command line.
bool log_precise_timestamps
True if –log-precise was given on the command line.
std::optional< std::string > data_dir
Non-empty if –data-dir was given on the command line.
std::optional< std::vector< std::string > > preprocess_defines
Defines that were given to the –preprocess option.
std::optional< std::vector< std::pair< lg::severity, std::string > > > log
Contains parsed arguments of –log-* (e.g.
std::optional< std::string > usercache_dir
Non-empty if –usercache-dir was given on the command line.
std::optional< std::string > userconfig_dir
Non-empty if –userconfig-dir was given on the command line.
bool strict_validation
True if –strict-validation was given on the command line.
bool help
True if –help was given on the command line.
std::optional< std::string > validate_with
Non-empty if –use-schema was given on the command line.
bool usercache_path
True if –usercache-path was given on the command line.
std::optional< std::string > validate_schema
Non-empty if –validate-schema was given on the command line.
Class for writing a config out to a file in pieces.
void write(const config &cfg)
A config object defines a single node in a WML file, with access to child nodes.
const_all_children_itors all_children_range() const
In-order iteration over all children.
child_itors child_range(config_key_type key)
void apply_diff(const config &diff, bool track=false)
A function to apply a diff config onto this config object.
config get_diff(const config &c) const
A function to get the differences between this object, and 'c', as another config object.
@ NO_FORCE_RELOAD
Don't reload if the previous defines equal the new defines.
bool init_game_config(FORCE_RELOAD_CONFIG force_reload)
void reload_changed_game_config()
const game_config_view & game_config() const
optional_const_config optional_child(config_key_type key) const
bool play_multiplayer(mp_mode mode)
static void progress(loading_stage stage=loading_stage::none)
Report what is being loaded to the loading screen.
static void display(std::function< void()> f)
@ ok_button
Shows an ok button.
bool show(const unsigned auto_close_time=0)
Shows the window.
int get_retval() const
Returns the cached window exit code.
This class implements the title screen.
std::vector< Reg > reg_vec
std::vector< aReg > areg_vec
void set_callback(const std::string &name, callback_function)
Exception used to escape form the ai or ui code to playsingle_controller::play_side.
Realization of serialization/validator.hpp abstract validator.
void set_create_exceptions(bool value)
std::string str() const
Serializes the version number into string form.
Type that can be thrown as an exception to quit to desktop.
std::vector< std::string > read_argv([[maybe_unused]] int argc, [[maybe_unused]] char **argv)
Declarations for File-IO.
Contains the exception interfaces used to signal completion of a scenario, campaign or turn.
Interfaces for manipulating version numbers of engine, add-ons, etc.
static std::string _(const char *str)
Standard logging facilities (interface).
void set(CURSOR_TYPE type)
Use the default parameter to reset cursors.
std::string get_cache_dir()
filesystem::scoped_istream istream_file(const std::string &fname, bool treat_failure_as_error)
std::string get_user_config_dir()
std::string get_user_data_dir()
static bool file_exists(const bfs::path &fpath)
std::string get_exe_dir()
bool is_directory(const std::string &fname)
Returns true if the given file is a directory.
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...
void set_user_config_dir(const std::string &newconfigdir)
filesystem::scoped_ostream ostream_file(const std::string &fname, std::ios_base::openmode mode, bool create_directory)
void set_cache_dir(const std::string &newcachedir)
std::unique_ptr< std::istream > scoped_istream
std::string get_logs_dir()
std::unique_ptr< std::ostream > scoped_ostream
std::string get_intl_dir()
std::string normalize_path(const std::string &fpath, bool normalize_separators, bool resolve_dot_entries)
Returns the absolute path of a file.
void set_user_data_dir(std::string newprefdir)
std::string full_build_report()
Produce a bug report-style info dump.
std::string library_versions_report()
Produce a plain-text report of library versions suitable for stdout/stderr.
const version_info wesnoth_version(VERSION)
std::string build_arch()
Obtain the processor architecture for this build.
std::string optional_features_report()
Produce a plain-text report of features suitable for stdout/stderr.
const std::string revision
void set_debug(bool new_debug)
void init()
Initializes the GUI subsystems.
void show_message(const std::string &title, const std::string &msg, const std::string &button_caption, const bool auto_close, const bool message_use_markup, const bool title_use_markup)
Shows a message to the user.
retval
Default window/dialog return values.
bool using_own_console()
Returns true if a console was allocated by the Wesnoth process.
std::string list_log_domains(const std::string &filter)
void set_log_to_file()
Do the initial redirection to a log file if the logs directory is writable.
void do_console_redirect()
Allocates a console if needed and redirects output to CONOUT.
void precise_timestamps(bool pt)
std::optional< bool > log_dir_writable()
Returns the result set by check_log_dir_writable().
bool set_log_domain_severity(const std::string &name, severity severity)
void set_strict_severity(severity severity)
void play_music_config(const config &music_node, bool allow_interrupt_current_track, int i)
void bind_textdomain(const char *domain, const char *directory, const char *)
void set_default_textdomain(const char *domain)
std::string get_unknown_exception_type()
Utility function for finding the type of thing caught with catch(...).
std::map< std::string, t_string > string_map
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
void preprocess_resource(const std::string &res_name, preproc_map *defines_map, bool write_cfg, bool write_plain_cfg, const std::string &parent_directory)
filesystem::scoped_istream preprocess_file(const std::string &fname, preproc_map *defines)
Function to use the WML preprocessor on a file.
std::map< std::string, struct preproc_define > preproc_map
One of the realizations of serialization/validator.hpp abstract validator.
Contains a basic exception class for SDL operations.
void read(config &cfg, std::istream &in, abstract_validator *validator)
structure which will hide all current floating labels, and cause floating labels instantiated after i...
Base class for all the errors encountered by the engine.
static preproc_map::value_type read_pair(const config &)
An error specifically indicating video subsystem problems.
Helper class, don't construct this directly.
static map_location::DIRECTION sw
bool strict_validation_enabled
Some defines: VERSION, PACKAGE, MIN_SAVEGAME_VERSION.
static lg::log_domain log_preprocessor("preprocessor")
static void safe_exit(int res)
static std::string autodetect_game_data_dir(std::string exe_dir)
Try to autodetect the location of the game data dir.
static int handle_validate_command(const std::string &file, abstract_validator &validator, const std::vector< std::string > &defines)
int main(int argc, char **argv)
static void handle_preprocess_command(const commandline_options &cmdline_opts)
static int do_gameloop(const std::vector< std::string > &args)
Setups the game environment and enters the titlescreen or game loops.
static void init_locale()
I would prefer to setup locale first so that early error messages can get localized,...
static void handle_lua_script_args(game_launcher *game, commandline_options &)
Handles the lua script command line arguments if present.
static int process_command_args(const commandline_options &cmdline_opts)
Process commandline-arguments.
static void warn_early_init_failure()
Print an alert and instructions to stderr about early initialization errors.
static lg::log_domain log_config("config")
Add a special kind of assert to validate whether the input from WML doesn't contain any problems that...