16 #define GETTEXT_DOMAIN "wesnoth-lib"
21 #include "addon/manager.hpp"
67 struct filter_transform
69 explicit filter_transform(
const std::vector<std::string>& filtertext) :
filtertext_(filtertext) {}
70 bool operator()(
const config& cfg)
const
77 std::string val = attribute.second.str();
78 if(std::search(val.begin(),
90 for(
const auto& attribute : child.attribute_range()) {
91 std::string val = attribute.second.str();
107 std::string make_display_dependencies(
108 const std::string& addon_id,
117 for(
const auto& dep_id : deps) {
121 addons_list::const_iterator ali =
addons_list.find(dep_id);
122 addons_tracking_list::const_iterator tli = addon_states.find(dep_id);
130 if(tli == addon_states.end()) {
133 depstate = tli->second;
146 std::string langcode_to_string(
const std::string& lcode)
150 if(ld.localename == lcode || ld.localename.substr(0, 2) == lcode) {
187 {
N_(
"addons_order^Name ($order)"),
"name", 0,
190 {
N_(
"addons_order^Author ($order)"),
"author", 1,
193 {
N_(
"addons_order^Size ($order)"),
"size", 2,
196 {
N_(
"addons_order^Downloads ($order)"),
"downloads", 3,
199 {
N_(
"addons_order^Type ($order)"),
"type", 4,
202 {
N_(
"addons_order^Last updated ($datelike_order)"),
"last_updated", -1,
205 {
N_(
"addons_order^First uploaded ($datelike_order)"),
"first_uploaded", -1,
222 const std::vector<addon_tag> tag_filter_types_{
223 {
"cooperative",
N_(
"addon_tag^Cooperative"),
225 N_(
"addon_tag^All human players are on the same team, versus the AI")},
226 {
"cosmetic",
N_(
"addon_tag^Cosmetic"),
228 N_(
"addon_tag^These make the game look different, without changing gameplay")},
229 {
"difficulty",
N_(
"addon_tag^Difficulty"),
231 N_(
"addon_tag^Can make campaigns easier or harder")},
232 {
"rng",
N_(
"addon_tag^RNG"),
234 N_(
"addon_tag^Modify the randomness in the combat mechanics, or remove it entirely")},
235 {
"survival",
N_(
"addon_tag^Survival"),
237 N_(
"addon_tag^Fight against waves of enemies")},
238 {
"terraforming",
N_(
"addon_tag^Terraforming"),
240 N_(
"addon_tag^Players can change the terrain")},
251 , need_wml_cache_refresh_(false)
261 switch(state.
state) {
264 ?
_(
"addon_state^Not installed")
265 :
_(
"addon_state^Published, not installed");
269 ?
_(
"addon_state^Installed")
270 :
_(
"addon_state^Published");
274 ?
_(
"addon_state^Installed, not tracking local version")
277 :
_(
"addon_state^Published, not tracking local version");
281 ?
_(
"addon_state^Installed ($local_version|), upgradable")
282 :
_(
"addon_state^Published ($local_version| installed), upgradable");
288 ?
_(
"addon_state^Installed ($local_version|), outdated on server")
289 :
_(
"addon_state^Published ($local_version| installed), outdated on server");
295 ?
_(
"addon_state^Installed, not ready to publish")
296 :
_(
"addon_state^Ready to publish");
300 ?
_(
"addon_state^Installed, broken")
301 :
_(
"addon_state^Published, broken");
304 s =
_(
"addon_state^Unknown");
326 auto addr_box =
dynamic_cast<styled_widget*
>(addr_visible->
find(
"server_addr",
false));
334 text_box& filter = find_widget<text_box>(&
window,
"filter",
false);
338 this, std::placeholders::_1));
340 this, std::placeholders::_1));
342 this, std::placeholders::_1));
345 this, std::placeholders::_1));
347 this, std::placeholders::_1));
354 menu_button& status_filter = find_widget<menu_button>(&
window,
"install_status_filter",
false);
356 std::vector<config> status_filter_entries;
361 status_filter.
set_values(status_filter_entries);
367 auto& tag_filter = find_widget<multimenu_button>(&
window,
"tag_filter",
false);
369 std::vector<config> tag_filter_entries;
370 for(
const auto&
f : tag_filter_types_) {
372 if(!
f.tooltip.empty()) {
377 tag_filter.set_values(tag_filter_entries);
384 std::vector<config> type_filter_entries;
396 std::set<std::string> languages_available;
398 for (
const auto&
b :
a.second.locales) {
399 languages_available.insert(
b);
402 std::set<std::string> language_strings_available;
403 for (
const auto&
i: languages_available) {
407 if (std::string lang_code_string = langcode_to_string(
i); !lang_code_string.empty()) {
408 language_strings_available.insert(lang_code_string);
411 for (
auto&
i: language_strings_available) {
416 std::vector<config> language_filter_entries;
418 language_filter_entries.emplace_back(
"label",
f.second,
"checkbox",
false);
421 language_filter.
set_values(language_filter_entries);
427 menu_button& order_dropdown = find_widget<menu_button>(&
window,
"order_dropdown",
false);
429 std::vector<config> order_dropdown_entries;
433 symbols[
"order"] =
_(
"ascending");
435 symbols[
"datelike_order"] =
_(
"oldest to newest");
437 order_dropdown_entries.push_back(entry);
438 symbols[
"order"] =
_(
"descending");
440 symbols[
"datelike_order"] =
_(
"newest to oldest");
441 entry[
"label"] =
VGETTEXT(
f.label.c_str(), symbols);
442 order_dropdown_entries.push_back(entry);
445 order_dropdown.
set_values(order_dropdown_entries);
450 if(!saved_order_name.empty()) {
452 [&saved_order_name](
const addon_order& order) {return order.as_preference == saved_order_name;});
456 if(saved_order_direction == sort_order::type::ascending) {
457 func = order_it->sort_func_asc;
459 func = order_it->sort_func_desc;
462 find_widget<menu_button>(&
window,
"order_dropdown",
false).set_value(
index,
false);
463 auto& addons = find_widget<addon_list>(&
window,
"addons",
false);
464 addons.set_addon_order(func);
465 addons.select_first_addon();
473 label& url_label = find_widget<label>(&
window,
"url",
false);
479 find_widget<button>(&
window,
"install",
false),
483 find_widget<button>(&
window,
"uninstall",
false),
487 find_widget<button>(&
window,
"update",
false),
491 find_widget<button>(&
window,
"publish",
false),
495 find_widget<button>(&
window,
"delete",
false),
499 find_widget<button>(&
window,
"update_all",
false),
503 find_widget<button>(&
window,
"show_help",
false),
507 button& btn = find_widget<button>(&
window,
"details_toggle",
false);
509 stk->select_layer(0);
514 version_filter_parent = stk->get_layer_grid(1);
517 menu_button& version_filter = find_widget<menu_button>(version_filter_parent,
"version_filter",
false);
564 for(std::string
id : publishable_addons) {
573 pbl_cfg[
"name"] =
id;
574 pbl_cfg[
"local_only"] =
true;
587 show_transient_message(
_(
"No Add-ons Available"),
_(
"There are no add-ons available for download from this server."));
593 bool has_upgradable_addons =
false;
598 has_upgradable_addons =
true;
602 find_widget<button>(
get_window(),
"update_all",
false).set_active(has_upgradable_addons);
612 find_widget<addon_list>(
get_window(),
"addons",
false).select_addon(
id);
618 const text_box& name_filter = find_widget<const text_box>(
get_window(),
"filter",
false);
619 const std::string& text = name_filter.
get_value();
622 boost::dynamic_bitset<> res;
628 const config& addon_cfg = *std::find_if(addon_cfgs.begin(), addon_cfgs.end(),
631 return cfg[
"name"] == a.first;
634 res.push_back(filter(addon_cfg));
642 const menu_button& status_filter = find_widget<const menu_button>(
get_window(),
"install_status_filter",
false);
645 boost::dynamic_bitset<> res;
663 const auto& tag_filter = find_widget<const multimenu_button>(
get_window(),
"tag_filter",
false);
664 const auto toggle_states = tag_filter.get_toggle_states();
665 if(toggle_states.none()) {
667 boost::dynamic_bitset<> res_flipped(
addons_.size());
671 std::vector<std::string> selected_tags;
672 for(std::size_t
i = 0;
i < tag_filter_types_.size(); ++
i) {
673 if(toggle_states[
i]) {
674 selected_tags.push_back(tag_filter_types_[
i].
id);
678 boost::dynamic_bitset<> res;
680 bool matched_tag =
false;
681 for(
const auto&
id : selected_tags) {
687 res.push_back(matched_tag);
698 if(toggle_states.none()) {
700 boost::dynamic_bitset<> res_flipped(
addons_.size());
703 boost::dynamic_bitset<> res;
708 [&
a](
const std::pair<ADDON_TYPE, std::string>& entry) {
709 return entry.first == a.second.type;
712 res.push_back(toggle_states[
index]);
724 if(toggle_states.none()) {
725 boost::dynamic_bitset<> res_flipped(
addons_.size());
728 boost::dynamic_bitset<> res;
733 std::vector<std::string> lang_string_vector;
734 for (
long unsigned int i = 0;
i <
a.second.locales.size();
i++) {
735 lang_string_vector.push_back(langcode_to_string(
a.second.locales[
i]));
738 for (
long unsigned int i = 0;
i < toggle_states.size();
i++) {
739 if (toggle_states[
i] ==
true) {
744 if ((contains_lang_code || contains_lang_string) ==
true)
763 auto list = find_widget<addon_list>(
get_window(),
"addons",
false,
false);
768 boost::dynamic_bitset<> res =
774 list->set_addon_shown(res);
779 const menu_button& order_menu = find_widget<const menu_button>(
get_window(),
"order_dropdown",
false);
783 if(order == sort_order::type::ascending) {
789 find_widget<addon_list>(
get_window(),
"addons",
false).set_addon_order(func);
798 [sort_column](
const addon_order& order) {return order.column_index == static_cast<int>(sort_column);});
800 if(order == sort_order::type::descending) {
808 template<
void(addon_manager::*fptr)(const addon_info& addon)>
813 stk->select_layer(0);
814 find_widget<button>(
get_window(),
"details_toggle",
false).set_label(
_(
"Add-on Details"));
820 if(addon ==
nullptr) {
825 (this->*fptr)(*addon);
836 parent = stk->get_layer_grid(1);
838 if(addon.
id == find_widget<addon_list>(
get_window(),
"addons",
false).get_selected_addon()->
id) {
839 versioned_addon.
current_version = find_widget<menu_button>(
parent,
"version_filter",
false).get_value_string();
856 _(
"The following add-on appears to have publishing or version control information stored locally, and will not be removed:") +
" " +
909 std::string server_msg;
911 const std::string addon_id = addon.
id;
915 const version_info& version_to_publish = cfg[
"version"].str();
917 if(version_to_publish <=
tracking_info_[addon_id].remote_version) {
919 _(
"The remote version of this add-on is greater or equal to the version being uploaded. Do you really wish to continue?"),
928 if(cfg[
"passphrase"].empty()) {
930 if(!gui2::dialogs::addon_auth::execute(cfg)) {
935 }
else if(cfg[
"forum_auth"].to_bool()) {
946 }
else if(gui2::dialogs::addon_license_prompt::execute(server_msg)) {
948 const std::string&
msg =
_(
"The add-on was rejected by the server:") +
951 if (!extra_data.empty()) {
973 const std::string addon_id = addon.
id;
975 "Deleting '$addon|' will permanently erase its download and upload counts on the add-ons server. Do you really wish to continue?",
985 std::string server_msg;
1007 VGETTEXT(
"Do you want to uninstall '$addon|'?", symbols),
1034 std::ostringstream ss;
1038 ?
_(
"%B %d %Y, %I:%M %p")
1040 :
_(
"%B %d %Y, %H:%M");
1055 parent = stk->get_layer_grid(1);
1056 parent_of_addons_list = stk->get_layer_grid(0);
1059 const addon_info*
info = find_widget<addon_list>(parent_of_addons_list,
"addons",
false).get_selected_addon();
1061 if(
info ==
nullptr) {
1065 find_widget<drawing>(
parent,
"image",
false).set_label(
info->display_icon());
1067 find_widget<styled_widget>(
parent,
"title",
false).set_label(
info->display_title_translated_or_original());
1068 find_widget<styled_widget>(
parent,
"description",
false).set_label(
info->description_translated());
1069 menu_button& version_filter = find_widget<menu_button>(
parent,
"version_filter",
false);
1070 find_widget<styled_widget>(
parent,
"author",
false).set_label(
info->author);
1071 find_widget<styled_widget>(
parent,
"type",
false).set_label(
info->display_type());
1075 status.set_use_markup(
true);
1078 find_widget<styled_widget>(
parent,
"downloads",
false).set_label(std::to_string(
info->downloads));
1082 find_widget<styled_widget>(
parent,
"dependencies",
false).set_label(!
info->depends.empty()
1084 :
_(
"addon_dependencies^None"));
1086 std::string languages;
1088 for(
const auto& lc :
info->locales) {
1089 const std::string& langlabel = langcode_to_string(lc);
1090 if(!langlabel.empty()) {
1091 if(!languages.empty()) {
1094 languages += langlabel;
1098 find_widget<styled_widget>(
parent,
"translations",
false).set_label(!languages.empty() ? languages :
_(
"translations^None"));
1100 const std::string& feedback_url =
info->feedback_url;
1101 find_widget<label>(
parent,
"url",
false).set_label(!feedback_url.empty() ? feedback_url :
_(
"url^None"));
1102 find_widget<label>(
parent,
"id",
false).set_label(
info->id);
1109 std::vector<config> version_filter_entries;
1114 stacked_widget& install_update_stack = find_widget<stacked_widget>(
parent,
"install_update_stack",
false);
1118 find_widget<button>(
parent,
"install",
false).set_active(!installed);
1120 find_widget<button>(
parent,
"update",
false).set_active(
true);
1123 find_widget<button>(
parent,
"uninstall",
false).set_active(installed);
1125 for(
const auto&
f :
info->versions) {
1126 version_filter_entries.emplace_back(
"label",
f.str());
1132 find_widget<button>(
parent,
"publish",
false).set_active(
true);
1133 find_widget<button>(
parent,
"delete",
false).set_active(!
info->local_only);
1136 version_filter_entries.emplace_back(
"label",
info->current_version.str());
1139 version_filter.
set_values(version_filter_entries);
1140 version_filter.
set_active(version_filter_entries.size() > 1);
1148 parent = stk->get_layer_grid(1);
1149 parent_of_addons_list = stk->get_layer_grid(0);
1152 const addon_info*
info = find_widget<addon_list>(parent_of_addons_list,
"addons",
false).get_selected_addon();
1154 if(
info ==
nullptr) {
1160 != find_widget<menu_button>(
parent,
"version_filter",
false).get_value_string();
1164 stacked_widget& install_update_stack = find_widget<stacked_widget>(
parent,
"install_update_stack",
false);
1166 find_widget<button>(
parent,
"update",
false).set_active(updatable);
bool remove_local_addon(const std::string &addon)
Removes the specified add-on, deleting its full directory structure.
config get_addon_pbl_info(const std::string &addon_name, bool do_validate)
Gets the publish information for an add-on.
bool have_addon_in_vcs_tree(const std::string &addon_name)
Returns whether the specified add-on appears to be managed by a VCS or not.
bool have_addon_pbl_info(const std::string &addon_name)
Returns whether a .pbl file is present for the specified add-on or not.
std::vector< std::string > available_addons()
Returns a list of local add-ons that can be published.
void refresh_addon_version_info_cache()
Refreshes the per-session cache of add-on's version information structs.
Add-ons (campaignd) client class.
install_result install_addon_with_checks(const addons_list &addons, const addon_info &addon)
Performs an add-on download and install cycle.
bool delete_remote_addon(const std::string &id, std::string &response_message)
Requests the specified add-on to be removed from the server.
const std::string & get_last_server_error_data() const
Returns the last error message extra data sent by the server, or an empty string.
@ abort
User aborted the operation because of an issue with dependencies or chose not to overwrite the add-on...
bool request_addons_list(config &cfg)
Request the add-ons list from the server.
bool using_tls() const
Returns whether the current connection uses TLS.
bool request_distribution_terms(std::string &terms)
Request the add-ons server distribution terms message.
const std::string & get_last_server_error() const
Returns the last error message sent by the server, or an empty string.
const std::string & addr() const
Returns the current hostname:port used for this connection.
bool upload_addon(const std::string &id, std::string &response_message, config &cfg, bool local_only)
Uploads an add-on to the server.
A config object defines a single node in a WML file, with access to child nodes.
const_attr_itors attribute_range() const
child_itors child_range(config_key_type key)
boost::iterator_range< const_child_iterator > const_child_itors
config & add_child(config_key_type key)
void set_uninstall_function(addon_op_func_t function)
Sets the function to call when the player clicks the uninstall button.
std::function< bool(const addon_info &, const addon_info &)> addon_sort_func
void set_publish_function(addon_op_func_t function)
Sets the function to upload an addon to the addons server.
void add_list_to_keyboard_chain()
Adds the internal listbox to the keyboard event chain.
void set_install_function(addon_op_func_t function)
Sets the function to call when the player clicks the install button.
void set_delete_function(addon_op_func_t function)
Sets the function to install an addon from the addons server.
const addon_info * get_selected_addon() const
Returns the selected add-on.
void set_update_function(addon_op_func_t function)
Sets the function to call when the player clicks the update button.
void set_modified_signal_handler(const std::function< void()> &callback)
Sets up a callback that will be called when the player selects an add-on.
void set_callback_order_change(std::function< void(unsigned, sort_order::type)> callback)
Sets up a callback that will be called when the player changes the sorting order.
static const int DEFAULT_ACTION_RETVAL
Special retval for the toggle panels in the addons list.
static std::string colorize_addon_state_string(const std::string &str, ADDON_STATUS state, bool verbose=false)
Changes the color of an add-on state string (installed, outdated, etc.) according to the state itself...
void set_addons(const addons_list &addons)
Sets the add-ons to show.
void uninstall_addon(const addon_info &addon)
void on_order_changed(unsigned int sort_column, sort_order::type order)
static const std::vector< std::pair< ADDON_STATUS_FILTER, std::string > > status_filter_types_
boost::dynamic_bitset get_lang_filter_visibility() const
boost::dynamic_bitset get_status_filter_visibility() const
void update_selected_addon()
void execute_default_action(const addon_info &addon)
Called when the player double-clicks an add-on.
std::vector< std::pair< int, std::string > > language_filter_types_
void execute_default_action_on_selected_addon()
boost::dynamic_bitset get_name_filter_visibility() const
void toggle_details(button &btn, stacked_widget &stk)
void reload_list_and_reselect_item(const std::string id)
void delete_addon(const addon_info &addon)
Performs all backend and UI actions for taking down the specified add-on.
addon_manager(addons_client &client)
config cfg_
Config which contains the list with the campaigns.
boost::dynamic_bitset get_type_filter_visibility() const
void install_selected_addon()
void delete_selected_addon()
void execute_action_on_selected_addon()
addons_tracking_list tracking_info_
static const std::vector< addon_order > all_orders_
void uninstall_selected_addon()
boost::dynamic_bitset get_tag_filter_visibility() const
void publish_selected_addon()
virtual void pre_show(window &window) override
Actions to be taken before showing the window.
static const std::vector< std::pair< ADDON_TYPE, std::string > > type_filter_types_
void install_addon(const addon_info &addon)
void update_addon(const addon_info &addon)
bool need_wml_cache_refresh_
void publish_addon(const addon_info &addon)
Performs all backend and UI actions for publishing the specified add-on.
void on_selected_version_change()
@ yes_no_buttons
Shows a yes and no button.
@ ok_cancel_buttons
Shows an ok and cancel button.
Abstract base class for all modal dialogs.
window * get_window()
Returns a pointer to the dialog's window.
widget * find(const std::string &id, const bool must_be_active) override
See widget::find.
A label displays text that can be wrapped but no scrollbars are provided.
void set_link_aware(bool l)
std::string get_value() const
void set_text_changed_callback(std::function< void(text_box_base *textbox, const std::string text)> cb)
Set the text_changed callback.
Class for a single line text area.
base class of top level items, the only item which needs to store the final canvases to draw on.
void set_enter_disabled(const bool enter_disabled)
Disable the enter key.
void keyboard_capture(widget *widget)
void set_exit_hook(exit_hook mode, std::function< bool(window &)> func)
Sets the window's exit hook.
void close()
Requests to close the window.
status
The status of the window.
void set_escape_disabled(const bool escape_disabled)
Disable the escape key.
Represents version numbers.
std::string str() const
Serializes the version number into string form.
static std::string _(const char *str)
std::string label
What to show in the filter's drop-down list.
const std::vector< std::string > filtertext_
std::string tooltip
Shown when hovering over an entry in the filter's drop-down list.
std::string id
Text to match against addon_info.tags()
std::string size_display_string(double size)
Get a human-readable representation of the specified byte count.
std::string make_addon_title(const std::string &id)
Replaces underscores to dress up file or dirnames as add-on titles.
void read_addons_list(const config &cfg, addons_list &dest)
Parse the specified add-ons list WML into an actual addons_list object.
std::map< std::string, addon_info > addons_list
language_list get_languages(bool all)
Return a list of available translations.
#define REGISTER_DIALOG(window_id)
Wrapper for REGISTER_DIALOG2.
std::deque< std::unique_ptr< editor_action > > action_stack
Action stack typedef.
const std::string unicode_em_dash
static std::string describe_status_verbose(const addon_tracking_info &state)
static std::string format_addon_time(std::time_t time)
void connect_signal_notify_modified(dispatcher &dispatcher, const signal_notification &signal)
Connects a signal handler for getting a notification upon modification.
void connect_signal_mouse_left_click(dispatcher &dispatcher, const signal &signal)
Connects a signal handler for a left mouse button click.
void show_transient_message(const std::string &title, const std::string &message, const std::string &image, const bool message_use_markup, const bool title_use_markup)
Shows a transient message to the user.
void show_error_message(const std::string &msg, bool message_use_markup)
Shows an error message to the user.
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.
@ OK
Dialog was closed with the OK button.
void show_help(const std::string &show_topic, int xloc, int yloc)
Open the help browser, show topic with id show_topic.
bool exists(const image::locator &i_locator)
Returns true if the given image actually exists, without loading it.
void set_addon_manager_saved_order_direction(sort_order::type value)
std::string password(const std::string &server, const std::string &login)
sort_order::type addon_manager_saved_order_direction()
bool use_twelve_hour_clock_format()
void set_addon_manager_saved_order_name(const std::string &value)
std::string addon_manager_saved_order_name()
std::string campaign_server()
void set_password(const std::string &server, const std::string &login, const std::string &key)
std::string strftime(const std::string &format, const std::tm *time)
bool ci_search(const std::string &s1, const std::string &s2)
std::size_t index(const std::string &str, const std::size_t index)
Codepoint index corresponding to the nth character in a UTF-8 string.
std::string interpolate_variables_into_string(const std::string &str, const string_map *const symbols)
Function which will interpolate variables, starting with '$' in the string 'str' with the equivalent ...
bool contains(const Container &container, const Value &value)
Returns true iff value is found in container.
bool chars_equal_insensitive(char a, char b)
std::map< std::string, t_string > string_map
std::vector< std::string > split(const config_attribute_value &val)
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
Desktop environment interaction functions.
This file contains the settings handling of the widget library.
addon_tracking_info get_addon_tracking_info(const addon_info &addon)
Get information about an add-on comparing its local state with the add-ons server entry.
bool is_installed_addon_status(ADDON_STATUS s)
@ ADDON_NOT_TRACKED
No tracking information available.
@ ADDON_INSTALLED_OUTDATED
Version in the server is older than local installation.
@ ADDON_NONE
Add-on is not installed.
@ ADDON_INSTALLED_UPGRADABLE
Version in the server is newer than local installation.
@ ADDON_INSTALLED
Version in the server matches local installation.
@ ADDON_INSTALLED_LOCAL_ONLY
No version in the server.
@ ADDON_INSTALLED_BROKEN
Dependencies not satisfied.
ADDON_STATUS_FILTER
Add-on installation status filters for the user interface.
std::map< std::string, addon_tracking_info > addons_tracking_list
version_info current_version
std::string display_title_translated_or_original() const
std::string display_title_full() const
std::set< std::string > resolve_dependencies(const addons_list &addons) const
Resolve an add-on's dependency tree in a recursive fashion.
Stores additional status information about add-ons.
version_info installed_version
Contains the outcome of an add-on install operation.
install_outcome outcome
Overall outcome of the operation.
bool wml_changed
Specifies if WML on disk was altered and needs to be reloaded.
addon_list::addon_sort_func sort_func_desc
addon_list::addon_sort_func sort_func_asc
std::string as_preference
The value used in the preferences file.
Exception thrown when the WML parser fails to read a .pbl file.
static map_location::DIRECTION s
@ ADDON_SP_SCENARIO
Single-player scenario.
@ ADDON_MP_SCENARIO
Multiplayer scenario.
@ ADDON_MP_CAMPAIGN
Multiplayer campaign.
@ ADDON_MP_FACTION
Multiplayer faction.
@ ADDON_MEDIA
Miscellaneous content/media (unit packs, terrain packs, music packs, etc.).
@ ADDON_MP_ERA
Multiplayer era.
@ ADDON_CORE
Total Conversion Core.
@ ADDON_SP_CAMPAIGN
Single-player campaign.
@ ADDON_OTHER
an add-on that fits in no other category
@ ADDON_SP_MP_CAMPAIGN
Hybrid campaign.
@ ADDON_MP_MAPS
Multiplayer plain (no WML) map pack.
@ ADDON_MOD
Modification of the game.