16 #define GETTEXT_DOMAIN "wesnoth-lib"
21 #include "addon/manager.hpp"
57 struct filter_transform
59 explicit filter_transform(
const std::vector<std::string>& filtertext) :
filtertext_(filtertext) {}
60 bool operator()(
const config& cfg)
const
67 std::string val = attribute.second.str();
68 if(std::search(val.begin(),
80 for(
const auto& attribute : child.attribute_range()) {
81 std::string val = attribute.second.str();
97 std::string make_display_dependencies(
98 const std::string& addon_id,
107 for(
const auto& dep_id : deps) {
111 addons_list::const_iterator ali =
addons_list.find(dep_id);
112 addons_tracking_list::const_iterator tli = addon_states.find(dep_id);
120 if(tli == addon_states.end()) {
123 depstate = tli->second;
136 std::string langcode_to_string(
const std::string& lcode)
140 if(ld.localename == lcode || ld.localename.substr(0, 2) == lcode) {
177 {
N_(
"addons_order^Name ($order)"),
"name", 0,
180 {
N_(
"addons_order^Author ($order)"),
"author", 1,
183 {
N_(
"addons_order^Size ($order)"),
"size", 2,
186 {
N_(
"addons_order^Downloads ($order)"),
"downloads", 3,
189 {
N_(
"addons_order^Type ($order)"),
"type", 4,
192 {
N_(
"addons_order^Last updated ($datelike_order)"),
"last_updated", -1,
195 {
N_(
"addons_order^First uploaded ($datelike_order)"),
"first_uploaded", -1,
212 const std::vector<addon_tag> tag_filter_types_{
213 {
"cooperative",
N_(
"addon_tag^Cooperative"),
215 N_(
"addon_tag^All human players are on the same team, versus the AI")},
216 {
"cosmetic",
N_(
"addon_tag^Cosmetic"),
218 N_(
"addon_tag^These make the game look different, without changing gameplay")},
219 {
"difficulty",
N_(
"addon_tag^Difficulty"),
221 N_(
"addon_tag^Can make campaigns easier or harder")},
222 {
"rng",
N_(
"addon_tag^RNG"),
224 N_(
"addon_tag^Modify the randomness in the combat mechanics, or remove it entirely")},
225 {
"survival",
N_(
"addon_tag^Survival"),
227 N_(
"addon_tag^Fight against waves of enemies")},
228 {
"terraforming",
N_(
"addon_tag^Terraforming"),
230 N_(
"addon_tag^Players can change the terrain")},
241 , need_wml_cache_refresh_(false)
251 switch(state.
state) {
254 ?
_(
"addon_state^Not installed")
255 :
_(
"addon_state^Published, not installed");
259 ?
_(
"addon_state^Installed")
260 :
_(
"addon_state^Published");
264 ?
_(
"addon_state^Installed, not tracking local version")
267 :
_(
"addon_state^Published, not tracking local version");
271 ?
_(
"addon_state^Installed ($local_version|), upgradable")
272 :
_(
"addon_state^Published ($local_version| installed), upgradable");
278 ?
_(
"addon_state^Installed ($local_version|), outdated on server")
279 :
_(
"addon_state^Published ($local_version| installed), outdated on server");
285 ?
_(
"addon_state^Installed, not ready to publish")
286 :
_(
"addon_state^Ready to publish");
290 ?
_(
"addon_state^Installed, broken")
291 :
_(
"addon_state^Published, broken");
294 s =
_(
"addon_state^Unknown");
316 auto addr_box =
dynamic_cast<styled_widget*
>(addr_visible->
find(
"server_addr",
false));
326 addr_box->set_label(full_id.str());
335 text_box& filter = find_widget<text_box>(&
window,
"filter",
false);
339 this, std::placeholders::_1));
341 this, std::placeholders::_1));
343 this, std::placeholders::_1));
346 this, std::placeholders::_1));
348 this, std::placeholders::_1));
355 menu_button& status_filter = find_widget<menu_button>(&
window,
"install_status_filter",
false);
357 std::vector<config> status_filter_entries;
362 status_filter.
set_values(status_filter_entries);
368 auto& tag_filter = find_widget<multimenu_button>(&
window,
"tag_filter",
false);
370 std::vector<config> tag_filter_entries;
371 for(
const auto&
f : tag_filter_types_) {
373 if(!
f.tooltip.empty()) {
378 tag_filter.set_values(tag_filter_entries);
385 std::vector<config> type_filter_entries;
397 std::set<std::string> languages_available;
399 for (
const auto&
b :
a.second.locales) {
400 languages_available.insert(
b);
403 std::set<std::string> language_strings_available;
404 for (
const auto&
i: languages_available) {
408 if (std::string lang_code_string = langcode_to_string(
i); !lang_code_string.empty()) {
409 language_strings_available.insert(lang_code_string);
412 for (
auto&
i: language_strings_available) {
417 std::vector<config> language_filter_entries;
419 language_filter_entries.emplace_back(
"label",
f.second,
"checkbox",
false);
422 language_filter.
set_values(language_filter_entries);
428 menu_button& order_dropdown = find_widget<menu_button>(&
window,
"order_dropdown",
false);
430 std::vector<config> order_dropdown_entries;
434 symbols[
"order"] =
_(
"ascending");
436 symbols[
"datelike_order"] =
_(
"oldest to newest");
438 order_dropdown_entries.push_back(entry);
439 symbols[
"order"] =
_(
"descending");
441 symbols[
"datelike_order"] =
_(
"newest to oldest");
442 entry[
"label"] =
VGETTEXT(
f.label.c_str(), symbols);
443 order_dropdown_entries.push_back(entry);
446 order_dropdown.
set_values(order_dropdown_entries);
451 if(!saved_order_name.empty()) {
453 [&saved_order_name](
const addon_order& order) {return order.as_preference == saved_order_name;});
457 if(saved_order_direction == sort_order::type::ascending) {
458 func = order_it->sort_func_asc;
460 func = order_it->sort_func_desc;
463 find_widget<menu_button>(&
window,
"order_dropdown",
false).set_value(
index,
false);
464 auto& addons = find_widget<addon_list>(&
window,
"addons",
false);
465 addons.set_addon_order(func);
466 addons.select_first_addon();
474 label& url_label = find_widget<label>(&
window,
"url",
false);
480 find_widget<button>(&
window,
"install",
false),
484 find_widget<button>(&
window,
"uninstall",
false),
488 find_widget<button>(&
window,
"update",
false),
492 find_widget<button>(&
window,
"publish",
false),
496 find_widget<button>(&
window,
"delete",
false),
500 find_widget<button>(&
window,
"update_all",
false),
504 find_widget<button>(&
window,
"show_help",
false),
508 button& btn = find_widget<button>(&
window,
"details_toggle",
false);
510 stk->select_layer(0);
515 version_filter_parent = stk->get_layer_grid(1);
518 menu_button& version_filter = find_widget<menu_button>(version_filter_parent,
"version_filter",
false);
565 for(std::string
id : publishable_addons) {
574 pbl_cfg[
"name"] =
id;
575 pbl_cfg[
"local_only"] =
true;
588 show_transient_message(
_(
"No Add-ons Available"),
_(
"There are no add-ons available for download from this server."));
594 bool has_upgradable_addons =
false;
599 has_upgradable_addons =
true;
603 find_widget<button>(
get_window(),
"update_all",
false).set_active(has_upgradable_addons);
613 find_widget<addon_list>(
get_window(),
"addons",
false).select_addon(
id);
619 const text_box& name_filter = find_widget<const text_box>(
get_window(),
"filter",
false);
620 const std::string& text = name_filter.
get_value();
623 boost::dynamic_bitset<> res;
629 const config& addon_cfg = *std::find_if(addon_cfgs.begin(), addon_cfgs.end(),
632 return cfg[
"name"] == a.first;
635 res.push_back(filter(addon_cfg));
643 const menu_button& status_filter = find_widget<const menu_button>(
get_window(),
"install_status_filter",
false);
646 boost::dynamic_bitset<> res;
664 const auto& tag_filter = find_widget<const multimenu_button>(
get_window(),
"tag_filter",
false);
665 const auto toggle_states = tag_filter.get_toggle_states();
666 if(toggle_states.none()) {
668 boost::dynamic_bitset<> res_flipped(
addons_.size());
672 std::vector<std::string> selected_tags;
673 for(std::size_t
i = 0;
i < tag_filter_types_.size(); ++
i) {
674 if(toggle_states[
i]) {
675 selected_tags.push_back(tag_filter_types_[
i].
id);
679 boost::dynamic_bitset<> res;
681 bool matched_tag =
false;
682 for(
const auto&
id : selected_tags) {
688 res.push_back(matched_tag);
699 if(toggle_states.none()) {
701 boost::dynamic_bitset<> res_flipped(
addons_.size());
704 boost::dynamic_bitset<> res;
709 [&
a](
const std::pair<ADDON_TYPE, std::string>& entry) {
710 return entry.first == a.second.type;
713 res.push_back(toggle_states[
index]);
725 if(toggle_states.none()) {
726 boost::dynamic_bitset<> res_flipped(
addons_.size());
729 boost::dynamic_bitset<> res;
734 std::vector<std::string> lang_string_vector;
735 for (
long unsigned int i = 0;
i <
a.second.locales.size();
i++) {
736 lang_string_vector.push_back(langcode_to_string(
a.second.locales[
i]));
739 for (
long unsigned int i = 0;
i < toggle_states.size();
i++) {
740 if (toggle_states[
i] ==
true) {
745 if ((contains_lang_code || contains_lang_string) ==
true)
764 auto list = find_widget<addon_list>(
get_window(),
"addons",
false,
false);
769 boost::dynamic_bitset<> res =
775 list->set_addon_shown(res);
780 const menu_button& order_menu = find_widget<const menu_button>(
get_window(),
"order_dropdown",
false);
784 if(order == sort_order::type::ascending) {
790 find_widget<addon_list>(
get_window(),
"addons",
false).set_addon_order(func);
799 [sort_column](
const addon_order& order) {return order.column_index == static_cast<int>(sort_column);});
801 if(order == sort_order::type::descending) {
809 template<
void(addon_manager::*fptr)(const addon_info& addon)>
814 stk->select_layer(0);
815 find_widget<button>(
get_window(),
"details_toggle",
false).set_label(
_(
"Add-on Details"));
821 if(addon ==
nullptr) {
826 (this->*fptr)(*addon);
837 parent = stk->get_layer_grid(1);
839 if(addon.
id == find_widget<addon_list>(
get_window(),
"addons",
false).get_selected_addon()->
id) {
840 versioned_addon.
current_version = find_widget<menu_button>(
parent,
"version_filter",
false).get_value_string();
857 _(
"The following add-on appears to have publishing or version control information stored locally, and will not be removed:") +
" " +
910 std::string server_msg;
912 const std::string addon_id = addon.
id;
916 const version_info& version_to_publish = cfg[
"version"].str();
918 if(version_to_publish <=
tracking_info_[addon_id].remote_version) {
920 _(
"The remote version of this add-on is greater or equal to the version being uploaded. Do you really wish to continue?"),
929 if(cfg[
"passphrase"].empty()) {
931 if(!gui2::dialogs::addon_auth::execute(cfg)) {
936 }
else if(cfg[
"forum_auth"].to_bool()) {
947 }
else if(gui2::dialogs::addon_license_prompt::execute(server_msg)) {
949 const std::string&
msg =
_(
"The add-on was rejected by the server:") +
952 if (!extra_data.empty()) {
974 const std::string addon_id = addon.
id;
976 "Deleting '$addon|' will permanently erase its download and upload counts on the add-ons server. Do you really wish to continue?",
986 std::string server_msg;
1008 VGETTEXT(
"Do you want to uninstall '$addon|'?", symbols),
1035 std::ostringstream ss;
1040 ?
_(
"%B %d %Y, %I:%M %p")
1043 :
_(
"%B %d %Y, %H:%M");
1058 parent = stk->get_layer_grid(1);
1059 parent_of_addons_list = stk->get_layer_grid(0);
1062 const addon_info*
info = find_widget<addon_list>(parent_of_addons_list,
"addons",
false).get_selected_addon();
1064 if(
info ==
nullptr) {
1068 find_widget<drawing>(
parent,
"image",
false).set_label(
info->display_icon());
1070 find_widget<styled_widget>(
parent,
"title",
false).set_label(
info->display_title_translated_or_original());
1071 find_widget<styled_widget>(
parent,
"description",
false).set_label(
info->description_translated());
1072 menu_button& version_filter = find_widget<menu_button>(
parent,
"version_filter",
false);
1073 find_widget<styled_widget>(
parent,
"author",
false).set_label(
info->author);
1074 find_widget<styled_widget>(
parent,
"type",
false).set_label(
info->display_type());
1078 status.set_use_markup(
true);
1081 find_widget<styled_widget>(
parent,
"downloads",
false).set_label(std::to_string(
info->downloads));
1085 find_widget<styled_widget>(
parent,
"dependencies",
false).set_label(!
info->depends.empty()
1087 :
_(
"addon_dependencies^None"));
1089 std::string languages;
1091 for(
const auto& lc :
info->locales) {
1092 const std::string& langlabel = langcode_to_string(lc);
1093 if(!langlabel.empty()) {
1094 if(!languages.empty()) {
1097 languages += langlabel;
1101 find_widget<styled_widget>(
parent,
"translations",
false).set_label(!languages.empty() ? languages :
_(
"translations^None"));
1103 const std::string& feedback_url =
info->feedback_url;
1104 find_widget<label>(
parent,
"url",
false).set_label(!feedback_url.empty() ? feedback_url :
_(
"url^None"));
1105 find_widget<label>(
parent,
"id",
false).set_label(
info->id);
1112 std::vector<config> version_filter_entries;
1117 stacked_widget& install_update_stack = find_widget<stacked_widget>(
parent,
"install_update_stack",
false);
1121 find_widget<button>(
parent,
"install",
false).set_active(!installed);
1123 find_widget<button>(
parent,
"update",
false).set_active(
true);
1126 find_widget<button>(
parent,
"uninstall",
false).set_active(installed);
1128 for(
const auto&
f :
info->versions) {
1129 version_filter_entries.emplace_back(
"label",
f.str());
1135 find_widget<button>(
parent,
"publish",
false).set_active(
true);
1136 find_widget<button>(
parent,
"delete",
false).set_active(!
info->local_only);
1139 version_filter_entries.emplace_back(
"label",
info->current_version.str());
1142 version_filter.
set_values(version_filter_entries);
1143 version_filter.
set_active(version_filter_entries.size() > 1);
1151 parent = stk->get_layer_grid(1);
1152 parent_of_addons_list = stk->get_layer_grid(0);
1155 const addon_info*
info = find_widget<addon_list>(parent_of_addons_list,
"addons",
false).get_selected_addon();
1157 if(
info ==
nullptr) {
1163 != find_widget<menu_button>(
parent,
"version_filter",
false).get_value_string();
1167 stacked_widget& install_update_stack = find_widget<stacked_widget>(
parent,
"install_update_stack",
false);
1169 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...
const std::string & server_id() const
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.
const std::string & server_version() const
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.
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.
A widget that allows the user to input text in single line.
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.
void set_addon_manager_saved_order_direction(sort_order::type value)
std::string addon_manager_saved_order_name()
void set_password(const std::string &server, const std::string &login, const std::string &key)
sort_order::type addon_manager_saved_order_direction()
void set_addon_manager_saved_order_name(const std::string &value)
bool use_twelve_hour_clock_format()
std::string password(const std::string &server, const std::string &login)
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.
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)
REGISTER_DIALOG(editor_edit_unit)
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.
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="")
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.