<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.wesnoth.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Pentarctagon</id>
	<title>The Battle for Wesnoth Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.wesnoth.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Pentarctagon"/>
	<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/Special:Contributions/Pentarctagon"/>
	<updated>2026-05-09T12:17:22Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.31.16</generator>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=PblWML&amp;diff=75029</id>
		<title>PblWML</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=PblWML&amp;diff=75029"/>
		<updated>2026-05-02T15:44:44Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: /* primary_authors */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{WML Tags}}&lt;br /&gt;
&lt;br /&gt;
To upload an add-on you have made, you need a '''_server.pbl''' file in your add-on's directory, at the same level as the '''_main.cfg''' file. When you upload the add-on, the entire directory and subdirectories containing the _server.pbl file will be published. Your add-on must be based entirely on these paths.&lt;br /&gt;
&lt;br /&gt;
See [[AddonStructure]] for more on setting up the add-on folder if you have not done so, and [[Distributing_content]] for more on uploading an add-on to the server with this file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Note:&amp;lt;/b&amp;gt; Be aware that translations in the .pbl-files are '''not''' used, so don't mark these strings as translatable. {{DevFeature1.15|4}} The translations in the .pbl-files are used, but they are used as a plain text instead of Gettext strings, so don't mark these strings as translatable.&lt;br /&gt;
&lt;br /&gt;
== What goes into a .pbl file? ==&lt;br /&gt;
&lt;br /&gt;
'''Note:''' ''You should '''not''' use special formatting or coloring in any of these keys when uploading to the official server.'''''&lt;br /&gt;
&lt;br /&gt;
The following keys are recognized for .pbl files:&lt;br /&gt;
&lt;br /&gt;
=== icon ===&lt;br /&gt;
: An image, displayed leftmost in the add-ons download dialog. It must be a standard Wesnoth file and '''not a custom one'''. A custom file will only work for users who already have the relevant add-on installed. This is not related to the icon used for entries in the campaigns menu -- see [[CampaignWML]] for more information.&lt;br /&gt;
&lt;br /&gt;
: If the icon is a unit with magenta team-color bits, please use [[ImagePathFunctions]] to recolor it. For example: &lt;br /&gt;
&lt;br /&gt;
::icon=&amp;quot;units/elves-wood/archer+female-sword-1.png~RC(magenta&amp;gt;brightorange)&amp;quot;&lt;br /&gt;
:or&lt;br /&gt;
::icon=&amp;quot;units/human-peasants/peasant-ranged.png~RC(magenta&amp;gt;white)~CS(24,24,24)&amp;quot;&lt;br /&gt;
:or&lt;br /&gt;
::icon=&amp;quot;units/human-peasants/ruffian.png~RC(magenta&amp;gt;green)~BLIT(units/human-peasants/woodsman.png~RC(magenta&amp;gt;lightblue),18,12)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
: Because the add-on manager's UI is dark, recoloring to light colors looks usually better. [https://irydacea.me/projects/wespal Wespal] is a tool that provides a convenient way to preview recolored unit sprites without needing to launch the game with specific WML or Lua edits.&lt;br /&gt;
&lt;br /&gt;
: {{DevFeature1.13|12}} Instead of a standard Wesnoth image, a [[DataURI]] can also be used. This way, an image can be directly included into the _server.pbl file. Take care to leave no trailing newline.&lt;br /&gt;
&lt;br /&gt;
=== title ===&lt;br /&gt;
: Displayed to the right of the icon, it is just text. It should usually be the same as the name of your add-on when it is played.&lt;br /&gt;
: '''This value is required'''.&lt;br /&gt;
&lt;br /&gt;
=== version ===&lt;br /&gt;
: Displayed to the right of the title; it is merely text. However, starting with Wesnoth 1.6, the required format is '''x.y.z''' where '''x''', '''y''' and '''z''' are numbers — and a value for '''x''' greater than ''0'' implies the add-on is complete, feature-wise. Trailing non-numeric elements are allowed, but nothing should appear before or between these numbers. The string of numbers will be modified on the server by inserting or appending zeros as neccesary to meet the required format. All this is necessary for the “Update All” button to work correctly. ([[#Version Key Examples|See Examples]])&lt;br /&gt;
: '''This value is required'''.&lt;br /&gt;
&lt;br /&gt;
=== author ===&lt;br /&gt;
: Displayed to the right of the version; it is merely text. Put your name or nickname here. If several people have contributed significantly to the add-on you may want to list all of their names.&lt;br /&gt;
&lt;br /&gt;
: {{DevFeature1.17|3}} When using forum_auth, this value is a single forum account name which will have the ability to upload new versions of the add-on, delete the add-on from the add-ons server, and update the secondary_authors field.&lt;br /&gt;
&lt;br /&gt;
: {{DevFeature1.19|7}} This value is now used the same as it was pre-forum_auth. It is only used to display in the addons manager.&lt;br /&gt;
&lt;br /&gt;
: '''This value is required'''.&lt;br /&gt;
&lt;br /&gt;
=== passphrase ===&lt;br /&gt;
: Not displayed. It prevents others from modifying the version of your add-on on the server. You do not need to input a passphrase when initially publishing a add-on; if you do not, one will be randomly generated for you and replaced in your local copy of the .pbl file.&lt;br /&gt;
: '''SECURITY NOTE:''' If you do specify a passphrase of your own, note that it is stored in '''clear text''' form in the server; '''do NOT use a password you would normally use for any other services or web sites!'''&lt;br /&gt;
&lt;br /&gt;
: {{DevFeature1.15|12}}&lt;br /&gt;
&lt;br /&gt;
: It is no longer required to keep the passphrase in the .pbl file at all. If it is not present, then Wesnoth will prompt for it to be entered when uploading or deleting an add-on.&lt;br /&gt;
&lt;br /&gt;
=== description ===&lt;br /&gt;
: This can be used to provide a brief description of your add-on, and for pre-1.0 versions, let people know how playable it is. The description can be viewed by users by clicking on the Description button in the built-in client, or by moving their mouse over the add-on's icon in the web interface.&lt;br /&gt;
: '''This value is required'''.&lt;br /&gt;
&lt;br /&gt;
=== dependencies ===&lt;br /&gt;
: An optional list of dependencies (a comma separated list of ''addon-name'' – the directory names of the needed add-ons), which should be provided if your add-on relies on other user-made content to work properly. ([[#Dependency Key Example|See Example]])&lt;br /&gt;
&lt;br /&gt;
=== tags ===&lt;br /&gt;
{{DevFeature1.13|12}}&lt;br /&gt;
: An optional string including a comma-separated list of keywords used for matching add-ons when typing terms into the Filter box on the top left of the Add-ons Manager. There are no specific requirements on the syntax of the keywords listed here, but a general recommendation is to keep them relevant for players. For example, one might include the add-on's acronym in the tags, the names or acronyms of add-ons to which it is related, and so on.&lt;br /&gt;
&lt;br /&gt;
{{DevFeature1.15|13}} The in-game add-ons manager will show all the tags in the UI, and also includes a drop-down list of tags to filter by. Not all tags are listed in the filter box, and the exact list of tags supported may change before 1.16 is released, but the list is currently:&lt;br /&gt;
&lt;br /&gt;
* '''cooperative''': All human players are on the same team, versus the AI&lt;br /&gt;
* '''cosmetic''': These make the game look different, without changing gameplay&lt;br /&gt;
* '''difficulty''': Can make campaigns easier or harder&lt;br /&gt;
* '''rng''': Modify the randomness in the combat mechanics, or remove it entirely&lt;br /&gt;
* '''survival''': Fight against waves of enemies&lt;br /&gt;
* '''terraforming''': Players can change the terrain&lt;br /&gt;
&lt;br /&gt;
For example, if an A New Land style add-on had tags ''building'', ''terraforming'', ''anl'', ''city'', and ''survival'' then it would be shown if either ''Terraforming'' or ''Survival'' was selected in the drop-down; the other tags wouldn't affect the filtering.&lt;br /&gt;
&lt;br /&gt;
=== core ===&lt;br /&gt;
{{DevFeature1.13|0}}&lt;br /&gt;
: An optional string defining the id of the core which the addon is designed for. Defaults to &amp;quot;''default''&amp;quot;. Don't specify for an addon which is of type &amp;quot;''core''&amp;quot; itself. Note: DO NOT SET this unless you know why you need it! Giving it an invalid value can lead to mysterious errors with your campaign failing to load!&lt;br /&gt;
&lt;br /&gt;
=== translate ===&lt;br /&gt;
: If set to ''true'', the add-on would have been sent to and updated with [[WesCamp|WesCamp-i18n]], if that project were still active. However, as WesCamp is no longer active, this no longer does anything.&lt;br /&gt;
&lt;br /&gt;
: You should make sure your add-on complies with some very specific [[WesCamp#Preparing_your_add-on_for_WesCamp|conventions]] required to ease the process for translators as well as technical requirements.&lt;br /&gt;
&lt;br /&gt;
: Note: WesCamp was abandoned in 2014. Instead, please refer to:&lt;br /&gt;
* [[GettextForWesnothDevelopers]]&lt;br /&gt;
* [[GettextForTranslators#For_add-ons]]&lt;br /&gt;
* forum thread: [https://r.wesnoth.org/t46366 Guide: Translating your UMC without WesCamp].&lt;br /&gt;
&lt;br /&gt;
=== type ===&lt;br /&gt;
: Indicates the type of the add-on; used to filter listings in the downloads manager dialog. Acceptable values are:&lt;br /&gt;
&lt;br /&gt;
:* ''core'': replaces the whole wml tree. {{DevFeature1.13|0}}&lt;br /&gt;
:* ''campaign'': single player campaign.&lt;br /&gt;
:* ''scenario'': single player scenario.&lt;br /&gt;
:* ''campaign_sp_mp'': hybrid campaign.&lt;br /&gt;
:* ''era'': multiplayer era.&lt;br /&gt;
:* ''faction'': multiplayer stand-alone faction, or add-on for other available era.&lt;br /&gt;
:* ''map_pack'': multiplayer map-pack.&lt;br /&gt;
:* ''campaign_mp'': multiplayer campaign.&lt;br /&gt;
:* ''scenario_mp'': multiplayer scenario. (See the note below.)&lt;br /&gt;
:* ''mod_mp'': multiplayer modification ({{DevFeature1.13|11}} can also used for single-player modifications, although it's still called ''mod_mp'').&lt;br /&gt;
:* ''media'': miscellaneous resources for UMC authors/users, for example, music packs, packages of general-purpose WML, etc. &amp;lt;small&amp;gt;Note: Shows as Resources, not Media, in the add-ons interface&amp;lt;/small&amp;gt;&lt;br /&gt;
:* ''other'': The type to use when no other type fits.&lt;br /&gt;
: '''Note:''' If your add-on contains two or more separate multiplayer scenarios, use ''map_pack''.&lt;br /&gt;
&lt;br /&gt;
: '''This value is required'''.&lt;br /&gt;
&lt;br /&gt;
=== email ===&lt;br /&gt;
: Hidden e-mail address used by the server administrators to contact content authors in case of major issues. Again, this will only be seen by the server administrators and it is required that you provide one in case you need to be contacted about your add-on.&lt;br /&gt;
&lt;br /&gt;
: '''This value is required if forum_auth is not set to true'''.&lt;br /&gt;
&lt;br /&gt;
=== forum_auth ===&lt;br /&gt;
{{DevFeature1.17|3}}&lt;br /&gt;
: When set to ''true'', you will be prompted for your forum password when uploading your add-on. The username(s) available to select will be populated from the '''author''' field (before 1.19.7) or the '''primary_authors''' field (1.19.7+). If the username dropdown is empty, make sure to confirm that either the '''author''' or '''primary_authors''' field is present and spelled correctly, depending on what version of Wesnoth you are running.&lt;br /&gt;
&lt;br /&gt;
When set to true, the ''passphrase'' and ''email'' fields are also not required.&lt;br /&gt;
&lt;br /&gt;
=== primary_authors ===&lt;br /&gt;
{{DevFeature1.19|7}}&lt;br /&gt;
: A comma-delimited list of forum accounts that are allowed to upload new versions of the add-on or delete the add-on from the add-ons server.&lt;br /&gt;
&lt;br /&gt;
: '''Note:''' Due to limitations with Wesnoth's schema validation, this attribute needs to be on the line after '''forum_auth'''.&lt;br /&gt;
&lt;br /&gt;
=== secondary_authors ===&lt;br /&gt;
: A comma-delimited list of forum accounts that are allowed to upload new versions of the add-on, but aren't allowed to delete the add-on.&lt;br /&gt;
&lt;br /&gt;
=== [feedback] ===&lt;br /&gt;
: The [feedback] tag includes information used by the server to provide the client with a website URL for players to post feedback on an add-on and communicate with the maintainers. At this time, the official add-ons server is configured to take a single parameter described below.&lt;br /&gt;
&lt;br /&gt;
==== topic_id ====&lt;br /&gt;
: Topic id from the [http://forums.wesnoth.org/ Wesnoth.org forums] for the add-on's feedback or development topic maintained by the add-on uploader or author. For existing topics, this topic_id corresponds to the series of digits in the ''t=YYYYY'' portion of a URL like &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;http://forums.wesnoth.org/viewtopic.php?f=XX&amp;amp;t=YYYYY&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;. You must take special care to ensure this information is valid before uploading if you want players to be able to reach you!&lt;br /&gt;
&lt;br /&gt;
=== [translation] ===&lt;br /&gt;
{{DevFeature1.15|4}}&lt;br /&gt;
: Multiple [translation] tags can be used to provide the addon with a localized title and description to be seen in the addons manager. However, it should be noted that the declared translations won't influence the list of supported locales as it depends only on the presence of .mo and .po files for corresponding languages.&lt;br /&gt;
&lt;br /&gt;
==== language ====&lt;br /&gt;
: The target language code for the translation. The codes for each language are given in the big table on [https://www.wesnoth.org/gettext/] . You can use either its contracted version (like ''sv'' for Swedish) or a more precise variety (like ''zh_CN'' or ''ca_ES@valencia'').&lt;br /&gt;
: '''This value is required'''.&lt;br /&gt;
&lt;br /&gt;
==== title ====&lt;br /&gt;
: The translation of addon's title for the target language.&lt;br /&gt;
: '''This value is required'''.&lt;br /&gt;
&lt;br /&gt;
==== description ====&lt;br /&gt;
: The translation of addon's description for the target language.&lt;br /&gt;
&lt;br /&gt;
The add-on server keeps track of some other information about uploaded content, including when they were uploaded, what languages they have been at least partly translated into, how large they are on the server and the number of times they have been downloaded. For more information about this you can read [[CampaignServerWML]].&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
=== Dependency Key Example ===&lt;br /&gt;
&lt;br /&gt;
The following dependency key could be used when the add-on needs the ''Imperial_Era'' and ''Era_of_Myths'' to be installed before it will work properly:&lt;br /&gt;
&lt;br /&gt;
 dependencies=Imperial_Era,Era_of_Myths&lt;br /&gt;
&lt;br /&gt;
=== Version Key Examples ===&lt;br /&gt;
&lt;br /&gt;
{{DevFeature1.17|13}} the schema validation rejects many of the '''good''' examples. https://github.com/wesnoth/wesnoth/issues/7396&lt;br /&gt;
&lt;br /&gt;
The following are examples of '''good''' version values:&lt;br /&gt;
&lt;br /&gt;
 version=&amp;quot;1.5&amp;quot;&lt;br /&gt;
 version=&amp;quot;0.11.4&amp;quot;&lt;br /&gt;
 version=&amp;quot;0.1.4beta&amp;quot;&lt;br /&gt;
 version=&amp;quot;1.5c&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The following are examples of '''bad''' version values:&lt;br /&gt;
&lt;br /&gt;
 version=&amp;quot;Beta1.5&amp;quot;&lt;br /&gt;
 version=&amp;quot;Incomplete (0.3.4)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
In both of the above examples the version number as read by the server will be '''0.0.0Beta1.5''' and '''0.0.0Incomplete (0.3.4)'''. You can clearly see why this will not be a good thing with the ''Update add-ons'' feature.&lt;br /&gt;
&lt;br /&gt;
Finally, here are some example version numbers and how they will be interpreted by the ''Update add-ons'' button. The number on the left will be considered an earlier number than the number on the right in each example.&lt;br /&gt;
&lt;br /&gt;
 0.5 &amp;lt; 1.0&lt;br /&gt;
 1.5 &amp;lt; 1.5c&lt;br /&gt;
 1.0 &amp;lt; 1.0.1&lt;br /&gt;
 1.0c &amp;lt; 1.0.1a&lt;br /&gt;
 1.0.1a &amp;lt; 1.0.1c&lt;br /&gt;
 1.0 Final &amp;lt; 1.0.1 Beta&lt;br /&gt;
&lt;br /&gt;
=== Example .pbl File ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
title=&amp;quot;My Campaign&amp;quot;&lt;br /&gt;
type=&amp;quot;campaign&amp;quot;&lt;br /&gt;
icon=&amp;quot;misc/ball.png&amp;quot;&lt;br /&gt;
version=&amp;quot;0.1.2&amp;quot;&lt;br /&gt;
author=&amp;quot;Me, artwork by myself&amp;quot;&lt;br /&gt;
passphrase=&amp;quot;This is like a password; see the security note in the documentation above before choosing a value of your own&amp;quot;&lt;br /&gt;
description=&amp;quot;You get to kill a lot of bad guys. But only the first map is done.&amp;quot;&lt;br /&gt;
email=&amp;quot;name@example.com&amp;quot;&lt;br /&gt;
[feedback]&lt;br /&gt;
    topic_id=12345&lt;br /&gt;
[/feedback]&lt;br /&gt;
# Note: the translation feature works on version 1.14.14, 1.15.4 and later only&lt;br /&gt;
[translation]&lt;br /&gt;
    language=&amp;quot;ru&amp;quot;&lt;br /&gt;
	title=&amp;quot;Моя Кампания&amp;quot;&lt;br /&gt;
    description=&amp;quot;Вам придётся завалить немало плохишей. Но пока что готова лишь первая карта.&amp;quot;&lt;br /&gt;
[/translation]&lt;br /&gt;
[translation]&lt;br /&gt;
    language=&amp;quot;zh_CN&amp;quot;&lt;br /&gt;
	title=&amp;quot;我的竞选&amp;quot;&lt;br /&gt;
    description=&amp;quot;你会杀死很多坏人。 但是只完成了第一张地图。(translated online)&amp;quot;&lt;br /&gt;
[/translation]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
&lt;br /&gt;
* [[IGNFileFormat]]&lt;br /&gt;
* [[FancyAddonIcons]]&lt;br /&gt;
* [[ReferenceWML]]&lt;br /&gt;
* [[CampaignServerWML]]&lt;br /&gt;
&lt;br /&gt;
[[Category: WML Reference]]&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Template:DevDownload&amp;diff=74999</id>
		<title>Template:DevDownload</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Template:DevDownload&amp;diff=74999"/>
		<updated>2026-04-23T23:50:42Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
== Development (1.19 branch) ==&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
==== Windows (10 1903 and later) {{{4|}}} ====&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.23 | filename=wesnoth-1.19.23-win64.exe |&lt;br /&gt;
hash=69d2d16d491d1cb374a9a687cd23b803b44775ecb8339641abe45bef4bd273d9}}&lt;br /&gt;
&lt;br /&gt;
==== macOS (10.13 and later) {{{5|}}} ====&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.23 | filename=Wesnoth_1.19.23.dmg |&lt;br /&gt;
hash=44ecfc8257a0bb48baa958b86e300b2f01d46952deddd0e1770e87160f3958e7}}&lt;br /&gt;
&lt;br /&gt;
==== Source code ====&lt;br /&gt;
* [https://github.com/wesnoth/wesnoth/blob/master/INSTALL.md Compiling Wesnoth] - How to compile the source code&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.23 | filename=wesnoth-1.19.23.tar.bz2 |&lt;br /&gt;
hash=f5bd748ead5b0b9c838fa95ac6142cceac74354db4e57e1f9de5b9369bd39d48}}&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Template:DevDownload&amp;diff=74997</id>
		<title>Template:DevDownload</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Template:DevDownload&amp;diff=74997"/>
		<updated>2026-04-23T16:05:26Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
== Development (1.19 branch) ==&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
==== Windows (10 1903 and later) {{{4|}}} ====&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.22 | filename=wesnoth-1.19.22-win64.exe |&lt;br /&gt;
hash=805a9da0b230f4334431704ba0cea6b8dcb4613da2530fcf1f315ff382ec67e2}}&lt;br /&gt;
&lt;br /&gt;
==== macOS (10.13 and later) {{{5|}}} ====&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.22 | filename=Wesnoth_1.19.22.dmg |&lt;br /&gt;
hash=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855}}&lt;br /&gt;
&lt;br /&gt;
==== Source code ====&lt;br /&gt;
* [https://github.com/wesnoth/wesnoth/blob/master/INSTALL.md Compiling Wesnoth] - How to compile the source code&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.22 | filename=wesnoth-1.19.22.tar.bz2 |&lt;br /&gt;
hash=dccf874092cf42dfbef61e30217f55d40ab4608532ff6dba3be7c052ca3e0c66}}&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Template:StableDownload&amp;diff=74996</id>
		<title>Template:StableDownload</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Template:StableDownload&amp;diff=74996"/>
		<updated>2026-04-23T16:05:08Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
== Stable (1.18 branch) ==&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
==== Windows (10 1903 and later, 64-bit only) {{{4|}}} ====&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth-1.18 |&lt;br /&gt;
version=1.18.7 | filename=wesnoth-1.18.7-win64.exe |&lt;br /&gt;
hash=1ebe433b8f7b526944b63d15caf11f42481375130431237b3f1139a517c7c7bb}}&lt;br /&gt;
&lt;br /&gt;
==== macOS (10.12 and later) {{{5|}}} ====&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth-1.18 |&lt;br /&gt;
version=1.18.7 | filename=Wesnoth_1.18.7.dmg |&lt;br /&gt;
hash=258f797ad4ae1f82b4479706875a372857c17130e221689c56647234513eca5f}}&lt;br /&gt;
&lt;br /&gt;
==== Source code ====&lt;br /&gt;
* [https://github.com/wesnoth/wesnoth/blob/master/INSTALL.md Compiling Wesnoth] - How to compile the source code&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth-1.18 |&lt;br /&gt;
version=1.18.7 | filename=wesnoth-1.18.7.tar.bz2 |&lt;br /&gt;
hash=d6b50cfdf4388954a1c3da66a61abacdc7643a17aa78a16196e16e720a661fc2}}&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=CompatibilityStandardsV2&amp;diff=74995</id>
		<title>CompatibilityStandardsV2</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=CompatibilityStandardsV2&amp;diff=74995"/>
		<updated>2026-04-23T15:57:16Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: /* Deprecation levels - When to remove deprecated features */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;As a piece of software matures, there are often new designs, paradigms, and idioms developed which are superior to old ones. This creates an inherent conflict between the need for progress and the need for compatibility. Wesnoth is no exception. This document describes Wesnoth's approach toward resolving that conflict in a way which is most beneficial to both goals, as well as the rationale behind this approach.&lt;br /&gt;
&lt;br /&gt;
== Policy ==&lt;br /&gt;
This policy defines how the creation of new Wesnoth APIs and the deprecation and removal of old ones are to be handled. For the purposes of this document &amp;quot;API&amp;quot; means &amp;quot;any technical channel by which a content creator interacts with the game engine&amp;quot;. This includes, but is not limited to: preprocessor macros, WML tags, WFL functions, IPFs, and the Lua API. Note that this policy applies only to software APIs. Core content such as sprites, portraits, animations, lore, etc. are to be updated freely, without consideration for stylistic or literary conflicts that such content changes may present to add-ons.&lt;br /&gt;
&lt;br /&gt;
=== When to deprecate ===&lt;br /&gt;
==== Adding a better API ====&lt;br /&gt;
Any time a superior API is introduced which has '''complete feature-parity''' with an existing API, the old one should be immediately deprecated. Note that in most cases, in order to be considered to have &amp;quot;complete feature-parity&amp;quot;, the API should be available in the same language or area of the code as the obsolete one was. For example, the introduction of a more powerful API in Lua which can accomplish a superset of the functionality which had previously been available with a certain WML tag would not obsolete that WML tag. Exceptions can be made to this rule in cases where it is clear that the feature does not make a lot of sense in its current language or area, and was merely there for legacy reasons (such as the proper place for it not having been introduced yet at the time of its creation). Such exceptions should be determined by developer consensus.&lt;br /&gt;
&lt;br /&gt;
==== Preventing needed fixes or improvements ====&lt;br /&gt;
In such cases where a feature is preventing an important new feature from being added or makes it impossible to fix a problem impacting players, it can be preferable to deprecate the API to allow for the necessary changes to be made. APIs deprecated for this reason should still follow the deprecation schedule as normal, unless the fix or improvement is urgently needed.&lt;br /&gt;
&lt;br /&gt;
==== Actively harmful ====&lt;br /&gt;
If an API is found to cause significant problems for players or UMC authors, such as being prone to causing crashes while also very difficult to properly fix, corrupting saves and replays when not used correctly while being difficult to use correctly, or other similar situations, then such APIs should be deprecated and removed regardless of whether there is a replacement available.&lt;br /&gt;
&lt;br /&gt;
==== Unused ====&lt;br /&gt;
Any API that is not used in mainline and also is not used by the most recent version of an add-on on the add-ons server of the current or previous stable release can be deprecated. For example, if an add-on for 1.16 uses a deprecated API but the updated version of the add-on for 1.18 does not, then that add-on is not considered as currently using the API. Once deprecated for this reason, a new add-on being uploaded that uses the API is not a reason to undeprecate it.&lt;br /&gt;
&lt;br /&gt;
This does not need to be a passive process where developers simply check the add-ons server for whether an API is used - developers who want to deprecate an API for removal can proactively talk to and work with UMC authors to help update their add-ons to remove usage of said API. This can be anything from talking with them online about how to update to submitting updated code directly (ie: opening a PR against an add-on's public git repository).&lt;br /&gt;
&lt;br /&gt;
Deprecating and then removing APIs that are unused is the most preferred approach since their removal does not have any impact on UMC authors.&lt;br /&gt;
&lt;br /&gt;
=== When NOT to deprecate ===&lt;br /&gt;
==== Style ====&lt;br /&gt;
Deprecation should not be done purely for reasons of style. This is very subjective and prone to change as new contributors join and current contributors leave or become less active. As such, allowing deprecation for stylistic reasons would lead to entirely unnecessary work for UMC authors as developer preferences change over time.&lt;br /&gt;
&lt;br /&gt;
==== Renaming ====&lt;br /&gt;
While there can be exceptions, it is rarely a net positive to deprecate an API simply for the sake of renaming it to something else. It is preferable to either add a second name for the same function, leaving the old name as-is, or simply live with the current name rather than expecting all UMC authors using the API to update to the new name.&lt;br /&gt;
&lt;br /&gt;
==== Any other reason ====&lt;br /&gt;
Accepted reasons for deprecating APIs should be something that's discussed and agreed upon by the development team while also, ideally, including UMC authors. It should not become the norm that additional reasons to deprecate APIs are treated as exceptions and left as an increasingly forgotten discussion on Discord, IRC, or the forums - they should be added to here with the reasoning behind them.&lt;br /&gt;
&lt;br /&gt;
=== Deprecation awareness ===&lt;br /&gt;
==== Conflicting goals ====&lt;br /&gt;
When deprecating APIs there is an inherent conflict in terms of how to make UMC authors aware of the deprecation. After all, if they aren't aware something is deprecated, they can't know they may need to update their add-on. Therefore, deprecations need to be displayed in a place where they will see them and most UMC authors don't look at Wesnoth's logs unless there's some other issue they're investigating. At the same time, deprecation warnings aren't relevant to players and spamming deprecation warnings is not an effective way of communicating what the issues are.&lt;br /&gt;
&lt;br /&gt;
==== A middle ground ====&lt;br /&gt;
Each deprecated feature should make use of an appropriate deprecation function call for that language or subsystem to ensure that the appropriate deprecation notice is printed to the log output. Additionally, deprecation warnings should be displayed in-game in the following cases:&lt;br /&gt;
* If the player is running a development version, level 3 and level 4 deprecations should be shown in-game by default.&lt;br /&gt;
* If the player enables debug mode then all deprecation warnings should be shown, regardless of whether they're using a stable release or a development release.&lt;br /&gt;
&lt;br /&gt;
==== Documentation ====&lt;br /&gt;
It is also not enough to only display a warning at runtime when something deprecated is encountered. It is the responsibility of the development team to proactively make UMC authors aware of the deprecations and removals being done. To accomplish this:&lt;br /&gt;
* When an API is deprecated, and again if it's later removed, its deprecation or removal must be documented in the appropriate section of the changelog for the version it was deprecated or removed in.&lt;br /&gt;
* Likewise, it should be added to https://wiki.wesnoth.org/CompatibilityBreakingChanges&lt;br /&gt;
&lt;br /&gt;
Additionally, it is not enough to simply say that an API is deprecated. In the deprecation message itself as well as in the changelog and https://wiki.wesnoth.org/CompatibilityBreakingChanges, a description must be included as to why it was deprecated or removed and how UMC authors can update their add-ons to address it.&lt;br /&gt;
&lt;br /&gt;
Lastly, it should be understood that &amp;quot;removed&amp;quot; doesn't necessarily mean that the API is entirely gone from Wesnoth's codebase. There is no maintenance burden to keeping macro or method stubs that do nothing aside from printing an error message describing what was removed and why. Keeping such stubs around is highly encouraged as it is helpful for UMC authors trying to update very old add-ons to the current version of Wesnoth.&lt;br /&gt;
&lt;br /&gt;
=== How to deprecate ===&lt;br /&gt;
Every effort should be made to create the simplest possible wrappers which will translate from an obsolete API to the updated one. Such wrappers should ideally be organized into their own compatibility file or module, and set up in such a way that the internals of the updated API will not affect how the old calls get wrapped to the new one. Essentially, the idea is to create a set-it-and-forget-it compatibility wrapper which will continue to work regardless of updates made to the newer API.&lt;br /&gt;
&lt;br /&gt;
Additionally, in all cases where it's practical, the wmllint tool must be updated to be able to automatically handle updating add-ons for anything that's been deprecated except for APIs deprecated at level 1. While developers are still heavily encouraged to add wmllint support for level 1 deprecations, it is not required as these do not show deprecation warnings by default and are expected to continue working indefinitely.&lt;br /&gt;
&lt;br /&gt;
=== Deprecation levels - When to remove deprecated features ===&lt;br /&gt;
While creating simple compatibility wrappers should be possible most of the time, it would be unreasonable to assume that this approach will be viable in absolutely every case. Wesnoth's compatibility policy therefore has four different levels of deprecation which are used to set expectations for when and if an API is expected to be removed:&lt;br /&gt;
&lt;br /&gt;
#Deprecated indefinitely &amp;amp;mdash; This deprecation level is for changes which have newer preferred alternatives but, barring any unforeseen issues, have little to no maintenance impact and should be kept indefinitely in order to reduce the work required for UMC authors to maintain their content. For example, functions or attributes which have had their names changed, macros which have been replaced with tags, or simple wrappers with little to no maintenance overhead. If future large scale changes make it impractical to maintain an API deprecated at this level then the deprecation level should be raised accordingly. This is generally the preferred deprecation level - higher deprecation levels are for APIs which are intended for eventual removal and must be weighed against the maintenance work this forces upon UMC authors.&lt;br /&gt;
#Deprecated with the intention of future removal &amp;amp;mdash; This deprecation level is for APIs which will be removed in a future version, but the version they are removed in has not yet have been decided. Barring urgent circumstances, all APIs that are deprecated with the intention of being removed '''must''' start with being deprecated at level 2 for 1-2 development cycles at minimum depending on the impact of the API's removal on UMC authors. Once the API has spent the necessary amount of time at deprecation level 2, it can be moved to deprecation level 3. It is not allowed to deprecate an API at level 2 and change it to level 3 in the same development cycle. There is no maximum amount of time that an API can remain deprecated at level 2.&lt;br /&gt;
#Deprecated for removal in a specific version &amp;amp;mdash; This deprecation level is for APIs which were previously deprecated at level 2 and now have a future version at which they will be removed. The version an API is removed in must be at least two development cycles after the API was deprecated at level 2. It is not allowed to move an API to deprecation level 3 and then remove it in the same development cycle.&lt;br /&gt;
#Removed without deprecation &amp;amp;mdash; This level should be used EXTREMELY rarely, and only in cases where it is ABSOLUTELY NECESSARY. Occasionally, an update to a feature will change the underlying architecture in such a fundamental way that the old paradigm cannot coexist with the new one no matter how much redundant code one would create. While this kind of scenario is extremely rare, and every effort should be made to find creative solutions to avoid it, there are occasionally cases where it truly is impossible to maintain both methods even in the short term. This level should only be used with broad developer consensus, after the majority of active developers familiar with the feature in question have given at least some thought to trying to deprecate gracefully and failed. This level should also be used for macro and method stubs containing only an error message describing what was removed and why, as well as if an API feature is found to have a security vulnerability which can't be fixed.&lt;br /&gt;
&lt;br /&gt;
APIs that are clearly labeled as being experimental, such as a WML tag having &amp;quot;experimental&amp;quot; in the name or a lua function having &amp;quot;experimental&amp;quot; in its name or package, can be be removed or deprecated at any level at any time. These are APIs which UMC authors use at their own risk.&lt;br /&gt;
&lt;br /&gt;
== Rationale ==&lt;br /&gt;
The above policy is the result of a large amount of thought, discussion, and debate. Following is a brief outline of the considerations and goals on both sides of the problem, why there is an inherent conflict between them, some failed approaches to resolving the conflict, and how the final policy ultimately maximizes the pursuit of both goals.&lt;br /&gt;
&lt;br /&gt;
=== The Problem - The paradox of progress ===&lt;br /&gt;
Invariably, as development on any project moves forward, developers will realize that there are better, cleaner, or more elegant ways to structure things than they had been previously. These changes can be to improve efficiency, make an API more intuitive, keep code better organized, make common tasks more straightforward, or accomplish any number of other positive things. These changes can also make the development of additional features much more viable. In short, progress is good.&lt;br /&gt;
&lt;br /&gt;
On the other hand, a content-heavy program such as Wesnoth relies on the ability of content creators to efficiently create, maintain, and update their content. Too many changes all at once will force creators of existing content to spend obscene amounts time updating their creations just to keeping them up-to-date and in working order. This can lead to a high amount of frustration, a drop in motivation, and a decline in content being created. In short, progress is bad.&lt;br /&gt;
&lt;br /&gt;
=== Backwards Compatibility - benefits and drawbacks ===&lt;br /&gt;
Most of the time, older paradigms can still be maintained in a manner in which they coexist with the newer ones. This allows for existing content to continue functioning, while at the same time allowing and encouraging new content to be created using the newer methods. However, maintaining such code can be problematic in the following ways:&lt;br /&gt;
#There may eventually be architectural changes a developer would want to make where the old method's square peg no longer fits, even forcibly, into the new method's round hole.&lt;br /&gt;
#Having compatibility code hanging around may, depending on how it is implemented, mean that any updates made to the feature, module, or subsystem in question would have to made in both the new, cleaner design, and the older, poorly structured one, adding more work for developers.&lt;br /&gt;
&lt;br /&gt;
=== The Naive Approach - Deprecate and remove everything old ===&lt;br /&gt;
One approach to balancing old and new is to deprecate the old and slate its eventual removal after either a certain amount of time has passed or a certain number of subsequent versions have been released. This sounds good in theory, but in practice, there will be many changes which are minor or cosmetic in nature and which will add up. Things like replacing macros with WML tags, updating the name of an API call or order of parameters to be more consistent with other similar functions, or switching from a functional to an object-oriented structure are very good for organizational purposes, but will result in a large amount of maintenance required on the part of content creators to keep existing code operational, and for very little real gain. This approach invariably leads to the situation where so much is being changed from one version to the next that creators turn into maintainers, forced to spend nearly all of their time trying to stay ahead of the update curve in an attempt to keep their existing content working, and leaving them very little time and motivation to create new content. And of course, by the time they're finished painstakingly updating their existing code for every little change made for the current release, whoops, there's a new release with a whole slew of new changes that need accounting for. It simply becomes unmanageable.&lt;br /&gt;
&lt;br /&gt;
=== The Naive Approach - Deprecate and remove only when necessary ===&lt;br /&gt;
The opposite approach would be to keep all existing paradigms until they actively interfere with a new architecture or create a double-maintenance problem. While this approach does cut down on the maintenance burden by ensuring that content using an older design continues to work, it hinders progress by the fact that the moment at which it first becomes clear that an architectural or double-maintenance problem will occur is exactly the same moment at which keeping the old structure around becomes problematic. Beginning a deprecation cycle at that point and then having to &amp;quot;wait out&amp;quot; the old paradigm will cause an unacceptable delay in development.&lt;br /&gt;
&lt;br /&gt;
=== The Middle Ground - Deprecate everything old, remove only when necessary ===&lt;br /&gt;
Most of the time, older APIs can be implemented in terms of their newer, cleaner counterparts through the use of things like simple wrappers, parse-translators which re-write the older paradigm's code in terms of the new one, or other relatively low-maintenance &amp;quot;set-it-and-forget-it&amp;quot; approaches. These simple wrappers are not really detrimental to making progress, don't require updating when the new APIs internals are changed, and can usually be organized into their own files and/or modules so that they don't clutter the cleaner code. Many such wrappers will never truly present either of the backwards compatibility drawbacks mentioned above. As such, there is really no detriment to keeping them around indefinitely. However, occasionally, a new idea or approach will be put forth that updates the newer paradigm in such a way that the older one can no longer cleanly wrap to it. This usually happens, as inspiration is wont to do, suddenly, unexpectedly, and without warning. As such developers need the flexibility to be able to remove outdated code as freely as possible when the situation requires. Therefore, the ideal solution would be to deprecate any API which has newer, feature-complete ways to do it, while leaving it in the codebase until such time as its presence becomes a hindrance. Essentially, deprecation need not necessarily mean &amp;quot;this WILL be removed&amp;quot; so much as &amp;quot;this is now a candidate for removal&amp;quot;. By separating the concepts of deprecation and removal, both goals can be better served.&lt;br /&gt;
&lt;br /&gt;
=== Undefined removal timeline - issues encountered ===&lt;br /&gt;
In practice however, simply stating something is a candidate for removal while providing no further information on when it will actually be removed causes multiple issues:&lt;br /&gt;
* When a deprecated API is causing a maintenance burden worthy of removal is a subjective decision, often leading to debates over removal any time a developer decides it's time for an API to be removed, initially deprecated, or moved to a higher deprecation level.&lt;br /&gt;
* Lack of developer incentive to provide good documentation and support for the deprecation of the API given there's no particular timeline for when it will actually cause issues for UMC authors.&lt;br /&gt;
* UMC authors often don't find out about deprecated APIs and so can't possibly migrate to the new APIs.&lt;br /&gt;
* UMC authors aren't provided the documentation or tooling support needed to make updating their add-ons easier.&lt;br /&gt;
* UMC authors may simply decide there's no reason to update to the new API even if they know it's deprecated and how to update their add-on. After all, why spend time updating APIs that may stick around forever?&lt;br /&gt;
* Giving a version that an API '''may''' be removed instead of a version that it '''will''' be removed is not as clear as it may seem to UMC authors who aren't already aware of how Wesnoth handles deprecation. This can lead to UMC authors ignoring deprecation warnings after seeing such warnings for APIs which provide a version that's years old.&lt;br /&gt;
&lt;br /&gt;
=== Certainty is also a benefit ===&lt;br /&gt;
Wesnoth continues to exist today in large part because of the content made by its community. As such, developers should always be sparing in what they choose to deprecate and what they choose to remove, so that UMC authors can update their content to the latest version of Wesnoth without needing to make a herculean effort every couple of years.&lt;br /&gt;
&lt;br /&gt;
But, for cases where APIs are removed, the benefit of providing certainty for when that will happen outweighs the flexibility of being able remove them at any time after they been marked as deprecated. It encourages developers to provide the documentation and tooling support to make it easier for UMC authors to update their add-ons, and it lets UMC authors know when they can expect deprecated APIs to be removed rather than it effectively happening at random when a developer decides a deprecated API needs to be dropped.&lt;br /&gt;
&lt;br /&gt;
=== More Complex Cases - One size does not fit all ===&lt;br /&gt;
There may, however, be cases where the obsolete API cannot be implemented cleanly in terms of the updated one and must be maintained separately, or, in extremely rare cases, cannot coexist at all. There needs to be some leeway for such cases as well. In the former case, it therefore makes sense to allow for a feature to be deprecated pending removal after the shortest reasonable deprecation period. In the latter case, there is obviously no choice but to make the change and remove the old immediately. Developers should, naturally, be encouraged to find creative solutions to avoid such cases, but it is inevitable that there will eventually be a few cases where no graceful transition procedure can be found. These more aggressive forms of deprecation should only be done with developer consensus, and only after all options of creating a backwards-compatible transition have been exhausted.&lt;br /&gt;
&lt;br /&gt;
=== Graphics - The exception that proves the rule ===&lt;br /&gt;
The one area where backwards compatibility should NOT be a factor is graphical changes. Any change to the terrain graphics, unit sprites, or portrait images has the potential to result in visually-incompatible custom content. Core content creators cannot be expected to maintain a deprecated visual style alongside a more modern one, as any approach toward doing so would add an unreasonable amount of bloat and overhead, and make it very difficult for core graphics to be updated without having to do double the work. In addition, add-ons will continue to function even with such visual incompatibilities present, they just won't look right. As such, it can be said that stylistic incompatibilities fall more within the realm of content than of code, and it is not unreasonable to expect a content creator to... well...  create content. Expecting the graphical style to remain backwards-compatible would be just as unreasonable as expecting stories, help descriptions, or other forms of lore to never change because they may introduce plot holes into add-on stories. Essentially, since the goal of the software portion of Wesnoth is, at its heart, merely to facilitate the creation and advancement of this kind of content, core content needs to be free to develop unhindered by considerations for add-on content.&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=CompatibilityStandardsV2&amp;diff=74994</id>
		<title>CompatibilityStandardsV2</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=CompatibilityStandardsV2&amp;diff=74994"/>
		<updated>2026-04-23T15:54:15Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: /* Deprecation levels - When to remove deprecated features */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;As a piece of software matures, there are often new designs, paradigms, and idioms developed which are superior to old ones. This creates an inherent conflict between the need for progress and the need for compatibility. Wesnoth is no exception. This document describes Wesnoth's approach toward resolving that conflict in a way which is most beneficial to both goals, as well as the rationale behind this approach.&lt;br /&gt;
&lt;br /&gt;
== Policy ==&lt;br /&gt;
This policy defines how the creation of new Wesnoth APIs and the deprecation and removal of old ones are to be handled. For the purposes of this document &amp;quot;API&amp;quot; means &amp;quot;any technical channel by which a content creator interacts with the game engine&amp;quot;. This includes, but is not limited to: preprocessor macros, WML tags, WFL functions, IPFs, and the Lua API. Note that this policy applies only to software APIs. Core content such as sprites, portraits, animations, lore, etc. are to be updated freely, without consideration for stylistic or literary conflicts that such content changes may present to add-ons.&lt;br /&gt;
&lt;br /&gt;
=== When to deprecate ===&lt;br /&gt;
==== Adding a better API ====&lt;br /&gt;
Any time a superior API is introduced which has '''complete feature-parity''' with an existing API, the old one should be immediately deprecated. Note that in most cases, in order to be considered to have &amp;quot;complete feature-parity&amp;quot;, the API should be available in the same language or area of the code as the obsolete one was. For example, the introduction of a more powerful API in Lua which can accomplish a superset of the functionality which had previously been available with a certain WML tag would not obsolete that WML tag. Exceptions can be made to this rule in cases where it is clear that the feature does not make a lot of sense in its current language or area, and was merely there for legacy reasons (such as the proper place for it not having been introduced yet at the time of its creation). Such exceptions should be determined by developer consensus.&lt;br /&gt;
&lt;br /&gt;
==== Preventing needed fixes or improvements ====&lt;br /&gt;
In such cases where a feature is preventing an important new feature from being added or makes it impossible to fix a problem impacting players, it can be preferable to deprecate the API to allow for the necessary changes to be made. APIs deprecated for this reason should still follow the deprecation schedule as normal, unless the fix or improvement is urgently needed.&lt;br /&gt;
&lt;br /&gt;
==== Actively harmful ====&lt;br /&gt;
If an API is found to cause significant problems for players or UMC authors, such as being prone to causing crashes while also very difficult to properly fix, corrupting saves and replays when not used correctly while being difficult to use correctly, or other similar situations, then such APIs should be deprecated and removed regardless of whether there is a replacement available.&lt;br /&gt;
&lt;br /&gt;
==== Unused ====&lt;br /&gt;
Any API that is not used in mainline and also is not used by the most recent version of an add-on on the add-ons server of the current or previous stable release can be deprecated. For example, if an add-on for 1.16 uses a deprecated API but the updated version of the add-on for 1.18 does not, then that add-on is not considered as currently using the API. Once deprecated for this reason, a new add-on being uploaded that uses the API is not a reason to undeprecate it.&lt;br /&gt;
&lt;br /&gt;
This does not need to be a passive process where developers simply check the add-ons server for whether an API is used - developers who want to deprecate an API for removal can proactively talk to and work with UMC authors to help update their add-ons to remove usage of said API. This can be anything from talking with them online about how to update to submitting updated code directly (ie: opening a PR against an add-on's public git repository).&lt;br /&gt;
&lt;br /&gt;
Deprecating and then removing APIs that are unused is the most preferred approach since their removal does not have any impact on UMC authors.&lt;br /&gt;
&lt;br /&gt;
=== When NOT to deprecate ===&lt;br /&gt;
==== Style ====&lt;br /&gt;
Deprecation should not be done purely for reasons of style. This is very subjective and prone to change as new contributors join and current contributors leave or become less active. As such, allowing deprecation for stylistic reasons would lead to entirely unnecessary work for UMC authors as developer preferences change over time.&lt;br /&gt;
&lt;br /&gt;
==== Renaming ====&lt;br /&gt;
While there can be exceptions, it is rarely a net positive to deprecate an API simply for the sake of renaming it to something else. It is preferable to either add a second name for the same function, leaving the old name as-is, or simply live with the current name rather than expecting all UMC authors using the API to update to the new name.&lt;br /&gt;
&lt;br /&gt;
==== Any other reason ====&lt;br /&gt;
Accepted reasons for deprecating APIs should be something that's discussed and agreed upon by the development team while also, ideally, including UMC authors. It should not become the norm that additional reasons to deprecate APIs are treated as exceptions and left as an increasingly forgotten discussion on Discord, IRC, or the forums - they should be added to here with the reasoning behind them.&lt;br /&gt;
&lt;br /&gt;
=== Deprecation awareness ===&lt;br /&gt;
==== Conflicting goals ====&lt;br /&gt;
When deprecating APIs there is an inherent conflict in terms of how to make UMC authors aware of the deprecation. After all, if they aren't aware something is deprecated, they can't know they may need to update their add-on. Therefore, deprecations need to be displayed in a place where they will see them and most UMC authors don't look at Wesnoth's logs unless there's some other issue they're investigating. At the same time, deprecation warnings aren't relevant to players and spamming deprecation warnings is not an effective way of communicating what the issues are.&lt;br /&gt;
&lt;br /&gt;
==== A middle ground ====&lt;br /&gt;
Each deprecated feature should make use of an appropriate deprecation function call for that language or subsystem to ensure that the appropriate deprecation notice is printed to the log output. Additionally, deprecation warnings should be displayed in-game in the following cases:&lt;br /&gt;
* If the player is running a development version, level 3 and level 4 deprecations should be shown in-game by default.&lt;br /&gt;
* If the player enables debug mode then all deprecation warnings should be shown, regardless of whether they're using a stable release or a development release.&lt;br /&gt;
&lt;br /&gt;
==== Documentation ====&lt;br /&gt;
It is also not enough to only display a warning at runtime when something deprecated is encountered. It is the responsibility of the development team to proactively make UMC authors aware of the deprecations and removals being done. To accomplish this:&lt;br /&gt;
* When an API is deprecated, and again if it's later removed, its deprecation or removal must be documented in the appropriate section of the changelog for the version it was deprecated or removed in.&lt;br /&gt;
* Likewise, it should be added to https://wiki.wesnoth.org/CompatibilityBreakingChanges&lt;br /&gt;
&lt;br /&gt;
Additionally, it is not enough to simply say that an API is deprecated. In the deprecation message itself as well as in the changelog and https://wiki.wesnoth.org/CompatibilityBreakingChanges, a description must be included as to why it was deprecated or removed and how UMC authors can update their add-ons to address it.&lt;br /&gt;
&lt;br /&gt;
Lastly, it should be understood that &amp;quot;removed&amp;quot; doesn't necessarily mean that the API is entirely gone from Wesnoth's codebase. There is no maintenance burden to keeping macro or method stubs that do nothing aside from printing an error message describing what was removed and why. Keeping such stubs around is highly encouraged as it is helpful for UMC authors trying to update very old add-ons to the current version of Wesnoth.&lt;br /&gt;
&lt;br /&gt;
=== How to deprecate ===&lt;br /&gt;
Every effort should be made to create the simplest possible wrappers which will translate from an obsolete API to the updated one. Such wrappers should ideally be organized into their own compatibility file or module, and set up in such a way that the internals of the updated API will not affect how the old calls get wrapped to the new one. Essentially, the idea is to create a set-it-and-forget-it compatibility wrapper which will continue to work regardless of updates made to the newer API.&lt;br /&gt;
&lt;br /&gt;
Additionally, in all cases where it's practical, the wmllint tool must be updated to be able to automatically handle updating add-ons for anything that's been deprecated except for APIs deprecated at level 1. While developers are still heavily encouraged to add wmllint support for level 1 deprecations, it is not required as these do not show deprecation warnings by default and are expected to continue working indefinitely.&lt;br /&gt;
&lt;br /&gt;
=== Deprecation levels - When to remove deprecated features ===&lt;br /&gt;
While creating simple compatibility wrappers should be possible most of the time, it would be unreasonable to assume that this approach will be viable in absolutely every case. Wesnoth's compatibility policy therefore has four different levels of deprecation which are used to set expectations for when and if an API is expected to be removed:&lt;br /&gt;
&lt;br /&gt;
#Deprecated indefinitely &amp;amp;mdash; This deprecation level is for changes which have newer preferred alternatives but, barring any unforeseen issues, have little to no maintenance impact and should be kept indefinitely in order to reduce the work required for UMC authors to maintain their content. For example, functions or attributes which have had their names changed, macros which have been replaced with tags, or simple wrappers with little to no maintenance overhead. If future large scale changes make it impractical to maintain an API deprecated at this level then the deprecation level should be raised accordingly. This is generally the preferred deprecation level - higher deprecation levels are for APIs which are intended for eventual removal and must be weighed against the maintenance work this forces upon UMC authors.&lt;br /&gt;
#Deprecated with the intention of future removal &amp;amp;mdash; This deprecation level is for APIs which will be removed in a future version, but the version they are removed in has not yet have been decided. Barring urgent circumstances, all APIs that are deprecated with the intention of being removed '''must''' start with being deprecated at level 2 for 1-2 development cycles at minimum depending on the impact of the API's removal on UMC authors. Once the API has spent the necessary amount of time at deprecation level 2, it can be moved to deprecation level 3. It is not allowed to deprecate an API at level 2 and change it to level 3 in the same development cycle. There is no maximum amount of time that an API can remain deprecated at level 2.&lt;br /&gt;
#Deprecated for removal in a specific version &amp;amp;mdash; This deprecation level is for APIs which were previously deprecated at level 2 and now have a future version at which they will be removed. The version an API is removed in must be at least two development cycles after the API was deprecated at level 2. It is not allowed to move an API to deprecation level 3 and then remove it in the same development cycle.&lt;br /&gt;
#Removed without deprecation &amp;amp;mdash; This level should be used EXTREMELY rarely, and only in cases where it is ABSOLUTELY NECESSARY. Occasionally, an update to a feature will change the underlying architecture in such a fundamental way that the old paradigm cannot coexist with the new one no matter how much redundant code one would create. While this kind of scenario is extremely rare, and every effort should be made to find creative solutions to avoid it, there are occasionally cases where it truly is impossible to maintain both methods even in the short term. This level should only be used with broad developer consensus, after the majority of active developers familiar with the feature in question have given at least some thought to trying to deprecate gracefully and failed. This level should also be used for macro and method stubs containing only an error message describing what was removed and why, as well as if an API feature is found to have a security vulnerability which can't be fixed.&lt;br /&gt;
&lt;br /&gt;
APIs that are clearly labeled as being experimental, such as a WML tag having &amp;quot;experimental&amp;quot; in the name or a lua function having &amp;quot;experimental&amp;quot; in its name or package, can be be removed at any time. These are APIs which UMC authors use at their own risk.&lt;br /&gt;
&lt;br /&gt;
== Rationale ==&lt;br /&gt;
The above policy is the result of a large amount of thought, discussion, and debate. Following is a brief outline of the considerations and goals on both sides of the problem, why there is an inherent conflict between them, some failed approaches to resolving the conflict, and how the final policy ultimately maximizes the pursuit of both goals.&lt;br /&gt;
&lt;br /&gt;
=== The Problem - The paradox of progress ===&lt;br /&gt;
Invariably, as development on any project moves forward, developers will realize that there are better, cleaner, or more elegant ways to structure things than they had been previously. These changes can be to improve efficiency, make an API more intuitive, keep code better organized, make common tasks more straightforward, or accomplish any number of other positive things. These changes can also make the development of additional features much more viable. In short, progress is good.&lt;br /&gt;
&lt;br /&gt;
On the other hand, a content-heavy program such as Wesnoth relies on the ability of content creators to efficiently create, maintain, and update their content. Too many changes all at once will force creators of existing content to spend obscene amounts time updating their creations just to keeping them up-to-date and in working order. This can lead to a high amount of frustration, a drop in motivation, and a decline in content being created. In short, progress is bad.&lt;br /&gt;
&lt;br /&gt;
=== Backwards Compatibility - benefits and drawbacks ===&lt;br /&gt;
Most of the time, older paradigms can still be maintained in a manner in which they coexist with the newer ones. This allows for existing content to continue functioning, while at the same time allowing and encouraging new content to be created using the newer methods. However, maintaining such code can be problematic in the following ways:&lt;br /&gt;
#There may eventually be architectural changes a developer would want to make where the old method's square peg no longer fits, even forcibly, into the new method's round hole.&lt;br /&gt;
#Having compatibility code hanging around may, depending on how it is implemented, mean that any updates made to the feature, module, or subsystem in question would have to made in both the new, cleaner design, and the older, poorly structured one, adding more work for developers.&lt;br /&gt;
&lt;br /&gt;
=== The Naive Approach - Deprecate and remove everything old ===&lt;br /&gt;
One approach to balancing old and new is to deprecate the old and slate its eventual removal after either a certain amount of time has passed or a certain number of subsequent versions have been released. This sounds good in theory, but in practice, there will be many changes which are minor or cosmetic in nature and which will add up. Things like replacing macros with WML tags, updating the name of an API call or order of parameters to be more consistent with other similar functions, or switching from a functional to an object-oriented structure are very good for organizational purposes, but will result in a large amount of maintenance required on the part of content creators to keep existing code operational, and for very little real gain. This approach invariably leads to the situation where so much is being changed from one version to the next that creators turn into maintainers, forced to spend nearly all of their time trying to stay ahead of the update curve in an attempt to keep their existing content working, and leaving them very little time and motivation to create new content. And of course, by the time they're finished painstakingly updating their existing code for every little change made for the current release, whoops, there's a new release with a whole slew of new changes that need accounting for. It simply becomes unmanageable.&lt;br /&gt;
&lt;br /&gt;
=== The Naive Approach - Deprecate and remove only when necessary ===&lt;br /&gt;
The opposite approach would be to keep all existing paradigms until they actively interfere with a new architecture or create a double-maintenance problem. While this approach does cut down on the maintenance burden by ensuring that content using an older design continues to work, it hinders progress by the fact that the moment at which it first becomes clear that an architectural or double-maintenance problem will occur is exactly the same moment at which keeping the old structure around becomes problematic. Beginning a deprecation cycle at that point and then having to &amp;quot;wait out&amp;quot; the old paradigm will cause an unacceptable delay in development.&lt;br /&gt;
&lt;br /&gt;
=== The Middle Ground - Deprecate everything old, remove only when necessary ===&lt;br /&gt;
Most of the time, older APIs can be implemented in terms of their newer, cleaner counterparts through the use of things like simple wrappers, parse-translators which re-write the older paradigm's code in terms of the new one, or other relatively low-maintenance &amp;quot;set-it-and-forget-it&amp;quot; approaches. These simple wrappers are not really detrimental to making progress, don't require updating when the new APIs internals are changed, and can usually be organized into their own files and/or modules so that they don't clutter the cleaner code. Many such wrappers will never truly present either of the backwards compatibility drawbacks mentioned above. As such, there is really no detriment to keeping them around indefinitely. However, occasionally, a new idea or approach will be put forth that updates the newer paradigm in such a way that the older one can no longer cleanly wrap to it. This usually happens, as inspiration is wont to do, suddenly, unexpectedly, and without warning. As such developers need the flexibility to be able to remove outdated code as freely as possible when the situation requires. Therefore, the ideal solution would be to deprecate any API which has newer, feature-complete ways to do it, while leaving it in the codebase until such time as its presence becomes a hindrance. Essentially, deprecation need not necessarily mean &amp;quot;this WILL be removed&amp;quot; so much as &amp;quot;this is now a candidate for removal&amp;quot;. By separating the concepts of deprecation and removal, both goals can be better served.&lt;br /&gt;
&lt;br /&gt;
=== Undefined removal timeline - issues encountered ===&lt;br /&gt;
In practice however, simply stating something is a candidate for removal while providing no further information on when it will actually be removed causes multiple issues:&lt;br /&gt;
* When a deprecated API is causing a maintenance burden worthy of removal is a subjective decision, often leading to debates over removal any time a developer decides it's time for an API to be removed, initially deprecated, or moved to a higher deprecation level.&lt;br /&gt;
* Lack of developer incentive to provide good documentation and support for the deprecation of the API given there's no particular timeline for when it will actually cause issues for UMC authors.&lt;br /&gt;
* UMC authors often don't find out about deprecated APIs and so can't possibly migrate to the new APIs.&lt;br /&gt;
* UMC authors aren't provided the documentation or tooling support needed to make updating their add-ons easier.&lt;br /&gt;
* UMC authors may simply decide there's no reason to update to the new API even if they know it's deprecated and how to update their add-on. After all, why spend time updating APIs that may stick around forever?&lt;br /&gt;
* Giving a version that an API '''may''' be removed instead of a version that it '''will''' be removed is not as clear as it may seem to UMC authors who aren't already aware of how Wesnoth handles deprecation. This can lead to UMC authors ignoring deprecation warnings after seeing such warnings for APIs which provide a version that's years old.&lt;br /&gt;
&lt;br /&gt;
=== Certainty is also a benefit ===&lt;br /&gt;
Wesnoth continues to exist today in large part because of the content made by its community. As such, developers should always be sparing in what they choose to deprecate and what they choose to remove, so that UMC authors can update their content to the latest version of Wesnoth without needing to make a herculean effort every couple of years.&lt;br /&gt;
&lt;br /&gt;
But, for cases where APIs are removed, the benefit of providing certainty for when that will happen outweighs the flexibility of being able remove them at any time after they been marked as deprecated. It encourages developers to provide the documentation and tooling support to make it easier for UMC authors to update their add-ons, and it lets UMC authors know when they can expect deprecated APIs to be removed rather than it effectively happening at random when a developer decides a deprecated API needs to be dropped.&lt;br /&gt;
&lt;br /&gt;
=== More Complex Cases - One size does not fit all ===&lt;br /&gt;
There may, however, be cases where the obsolete API cannot be implemented cleanly in terms of the updated one and must be maintained separately, or, in extremely rare cases, cannot coexist at all. There needs to be some leeway for such cases as well. In the former case, it therefore makes sense to allow for a feature to be deprecated pending removal after the shortest reasonable deprecation period. In the latter case, there is obviously no choice but to make the change and remove the old immediately. Developers should, naturally, be encouraged to find creative solutions to avoid such cases, but it is inevitable that there will eventually be a few cases where no graceful transition procedure can be found. These more aggressive forms of deprecation should only be done with developer consensus, and only after all options of creating a backwards-compatible transition have been exhausted.&lt;br /&gt;
&lt;br /&gt;
=== Graphics - The exception that proves the rule ===&lt;br /&gt;
The one area where backwards compatibility should NOT be a factor is graphical changes. Any change to the terrain graphics, unit sprites, or portrait images has the potential to result in visually-incompatible custom content. Core content creators cannot be expected to maintain a deprecated visual style alongside a more modern one, as any approach toward doing so would add an unreasonable amount of bloat and overhead, and make it very difficult for core graphics to be updated without having to do double the work. In addition, add-ons will continue to function even with such visual incompatibilities present, they just won't look right. As such, it can be said that stylistic incompatibilities fall more within the realm of content than of code, and it is not unreasonable to expect a content creator to... well...  create content. Expecting the graphical style to remain backwards-compatible would be just as unreasonable as expecting stories, help descriptions, or other forms of lore to never change because they may introduce plot holes into add-on stories. Essentially, since the goal of the software portion of Wesnoth is, at its heart, merely to facilitate the creation and advancement of this kind of content, core content needs to be free to develop unhindered by considerations for add-on content.&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=CompatibilityStandardsV2&amp;diff=74993</id>
		<title>CompatibilityStandardsV2</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=CompatibilityStandardsV2&amp;diff=74993"/>
		<updated>2026-04-23T15:33:54Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: /* Deprecation levels - When to remove deprecated features */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;As a piece of software matures, there are often new designs, paradigms, and idioms developed which are superior to old ones. This creates an inherent conflict between the need for progress and the need for compatibility. Wesnoth is no exception. This document describes Wesnoth's approach toward resolving that conflict in a way which is most beneficial to both goals, as well as the rationale behind this approach.&lt;br /&gt;
&lt;br /&gt;
== Policy ==&lt;br /&gt;
This policy defines how the creation of new Wesnoth APIs and the deprecation and removal of old ones are to be handled. For the purposes of this document &amp;quot;API&amp;quot; means &amp;quot;any technical channel by which a content creator interacts with the game engine&amp;quot;. This includes, but is not limited to: preprocessor macros, WML tags, WFL functions, IPFs, and the Lua API. Note that this policy applies only to software APIs. Core content such as sprites, portraits, animations, lore, etc. are to be updated freely, without consideration for stylistic or literary conflicts that such content changes may present to add-ons.&lt;br /&gt;
&lt;br /&gt;
=== When to deprecate ===&lt;br /&gt;
==== Adding a better API ====&lt;br /&gt;
Any time a superior API is introduced which has '''complete feature-parity''' with an existing API, the old one should be immediately deprecated. Note that in most cases, in order to be considered to have &amp;quot;complete feature-parity&amp;quot;, the API should be available in the same language or area of the code as the obsolete one was. For example, the introduction of a more powerful API in Lua which can accomplish a superset of the functionality which had previously been available with a certain WML tag would not obsolete that WML tag. Exceptions can be made to this rule in cases where it is clear that the feature does not make a lot of sense in its current language or area, and was merely there for legacy reasons (such as the proper place for it not having been introduced yet at the time of its creation). Such exceptions should be determined by developer consensus.&lt;br /&gt;
&lt;br /&gt;
==== Preventing needed fixes or improvements ====&lt;br /&gt;
In such cases where a feature is preventing an important new feature from being added or makes it impossible to fix a problem impacting players, it can be preferable to deprecate the API to allow for the necessary changes to be made. APIs deprecated for this reason should still follow the deprecation schedule as normal, unless the fix or improvement is urgently needed.&lt;br /&gt;
&lt;br /&gt;
==== Actively harmful ====&lt;br /&gt;
If an API is found to cause significant problems for players or UMC authors, such as being prone to causing crashes while also very difficult to properly fix, corrupting saves and replays when not used correctly while being difficult to use correctly, or other similar situations, then such APIs should be deprecated and removed regardless of whether there is a replacement available.&lt;br /&gt;
&lt;br /&gt;
==== Unused ====&lt;br /&gt;
Any API that is not used in mainline and also is not used by the most recent version of an add-on on the add-ons server of the current or previous stable release can be deprecated. For example, if an add-on for 1.16 uses a deprecated API but the updated version of the add-on for 1.18 does not, then that add-on is not considered as currently using the API. Once deprecated for this reason, a new add-on being uploaded that uses the API is not a reason to undeprecate it.&lt;br /&gt;
&lt;br /&gt;
This does not need to be a passive process where developers simply check the add-ons server for whether an API is used - developers who want to deprecate an API for removal can proactively talk to and work with UMC authors to help update their add-ons to remove usage of said API. This can be anything from talking with them online about how to update to submitting updated code directly (ie: opening a PR against an add-on's public git repository).&lt;br /&gt;
&lt;br /&gt;
Deprecating and then removing APIs that are unused is the most preferred approach since their removal does not have any impact on UMC authors.&lt;br /&gt;
&lt;br /&gt;
=== When NOT to deprecate ===&lt;br /&gt;
==== Style ====&lt;br /&gt;
Deprecation should not be done purely for reasons of style. This is very subjective and prone to change as new contributors join and current contributors leave or become less active. As such, allowing deprecation for stylistic reasons would lead to entirely unnecessary work for UMC authors as developer preferences change over time.&lt;br /&gt;
&lt;br /&gt;
==== Renaming ====&lt;br /&gt;
While there can be exceptions, it is rarely a net positive to deprecate an API simply for the sake of renaming it to something else. It is preferable to either add a second name for the same function, leaving the old name as-is, or simply live with the current name rather than expecting all UMC authors using the API to update to the new name.&lt;br /&gt;
&lt;br /&gt;
==== Any other reason ====&lt;br /&gt;
Accepted reasons for deprecating APIs should be something that's discussed and agreed upon by the development team while also, ideally, including UMC authors. It should not become the norm that additional reasons to deprecate APIs are treated as exceptions and left as an increasingly forgotten discussion on Discord, IRC, or the forums - they should be added to here with the reasoning behind them.&lt;br /&gt;
&lt;br /&gt;
=== Deprecation awareness ===&lt;br /&gt;
==== Conflicting goals ====&lt;br /&gt;
When deprecating APIs there is an inherent conflict in terms of how to make UMC authors aware of the deprecation. After all, if they aren't aware something is deprecated, they can't know they may need to update their add-on. Therefore, deprecations need to be displayed in a place where they will see them and most UMC authors don't look at Wesnoth's logs unless there's some other issue they're investigating. At the same time, deprecation warnings aren't relevant to players and spamming deprecation warnings is not an effective way of communicating what the issues are.&lt;br /&gt;
&lt;br /&gt;
==== A middle ground ====&lt;br /&gt;
Each deprecated feature should make use of an appropriate deprecation function call for that language or subsystem to ensure that the appropriate deprecation notice is printed to the log output. Additionally, deprecation warnings should be displayed in-game in the following cases:&lt;br /&gt;
* If the player is running a development version, level 3 and level 4 deprecations should be shown in-game by default.&lt;br /&gt;
* If the player enables debug mode then all deprecation warnings should be shown, regardless of whether they're using a stable release or a development release.&lt;br /&gt;
&lt;br /&gt;
==== Documentation ====&lt;br /&gt;
It is also not enough to only display a warning at runtime when something deprecated is encountered. It is the responsibility of the development team to proactively make UMC authors aware of the deprecations and removals being done. To accomplish this:&lt;br /&gt;
* When an API is deprecated, and again if it's later removed, its deprecation or removal must be documented in the appropriate section of the changelog for the version it was deprecated or removed in.&lt;br /&gt;
* Likewise, it should be added to https://wiki.wesnoth.org/CompatibilityBreakingChanges&lt;br /&gt;
&lt;br /&gt;
Additionally, it is not enough to simply say that an API is deprecated. In the deprecation message itself as well as in the changelog and https://wiki.wesnoth.org/CompatibilityBreakingChanges, a description must be included as to why it was deprecated or removed and how UMC authors can update their add-ons to address it.&lt;br /&gt;
&lt;br /&gt;
Lastly, it should be understood that &amp;quot;removed&amp;quot; doesn't necessarily mean that the API is entirely gone from Wesnoth's codebase. There is no maintenance burden to keeping macro or method stubs that do nothing aside from printing an error message describing what was removed and why. Keeping such stubs around is highly encouraged as it is helpful for UMC authors trying to update very old add-ons to the current version of Wesnoth.&lt;br /&gt;
&lt;br /&gt;
=== How to deprecate ===&lt;br /&gt;
Every effort should be made to create the simplest possible wrappers which will translate from an obsolete API to the updated one. Such wrappers should ideally be organized into their own compatibility file or module, and set up in such a way that the internals of the updated API will not affect how the old calls get wrapped to the new one. Essentially, the idea is to create a set-it-and-forget-it compatibility wrapper which will continue to work regardless of updates made to the newer API.&lt;br /&gt;
&lt;br /&gt;
Additionally, in all cases where it's practical, the wmllint tool must be updated to be able to automatically handle updating add-ons for anything that's been deprecated except for APIs deprecated at level 1. While developers are still heavily encouraged to add wmllint support for level 1 deprecations, it is not required as these do not show deprecation warnings by default and are expected to continue working indefinitely.&lt;br /&gt;
&lt;br /&gt;
=== Deprecation levels - When to remove deprecated features ===&lt;br /&gt;
While creating simple compatibility wrappers should be possible most of the time, it would be unreasonable to assume that this approach will be viable in absolutely every case. Wesnoth's compatibility policy therefore has four different levels of deprecation which are used to set expectations for when and if an API is expected to be removed:&lt;br /&gt;
&lt;br /&gt;
#Deprecated indefinitely &amp;amp;mdash; This deprecation level is for changes which have newer preferred alternatives but, barring any unforeseen issues, have little to no maintenance impact and should be kept indefinitely in order to reduce the work required for UMC authors to maintain their content. For example, functions or attributes which have had their names changed, macros which have been replaced with tags, or simple wrappers with little to no maintenance overhead. If future large scale changes make it impractical to maintain an API deprecated at this level then the deprecation level should be raised accordingly. This is generally the preferred deprecation level - higher deprecation levels are for APIs which are intended for eventual removal and must be weighed against the maintenance work this forces upon UMC authors.&lt;br /&gt;
#Deprecated with the intention of future removal &amp;amp;mdash; This deprecation level is for APIs which will be removed in a future version, but the version they are removed in has not yet have been decided. Barring urgent circumstances, all APIs that are deprecated with the intention of being removed '''must''' start with being deprecated at level 2 for 1-2 development cycles at minimum depending on the impact of the API's removal on UMC authors. Once the API has spent the necessary amount of time at deprecation level 2, it can be moved to deprecation level 3. It is not allowed to deprecate an API at level 2 and change it to level 3 in the same development cycle. There is no maximum amount of time that an API can remain deprecated at level 2.&lt;br /&gt;
#Deprecated for removal in a specific version &amp;amp;mdash; This deprecation level is for APIs which were previously deprecated at level 2 and now have a future version at which they will be removed. The version an API is removed in must be at least two development cycles after the API was deprecated at level 2. It is not allowed to move an API to deprecation level 3 and then remove it in the same development cycle.&lt;br /&gt;
#Removed without deprecation &amp;amp;mdash; This level should be used EXTREMELY rarely, and only in cases where it is ABSOLUTELY NECESSARY. Occasionally, an update to a feature will change the underlying architecture in such a fundamental way that the old paradigm cannot coexist with the new one no matter how much redundant code one would create. While this kind of scenario is extremely rare, and every effort should be made to find creative solutions to avoid it, there are occasionally cases where it truly is impossible to maintain both methods even in the short term. This level should only be used with broad developer consensus, after the majority of active developers familiar with the feature in question have given at least some thought to trying to deprecate gracefully and failed. This level should also be used for macro and method stubs containing only an error message describing what was removed and why, as well as if an API feature is found to have a security vulnerability which can't be fixed.&lt;br /&gt;
&lt;br /&gt;
== Rationale ==&lt;br /&gt;
The above policy is the result of a large amount of thought, discussion, and debate. Following is a brief outline of the considerations and goals on both sides of the problem, why there is an inherent conflict between them, some failed approaches to resolving the conflict, and how the final policy ultimately maximizes the pursuit of both goals.&lt;br /&gt;
&lt;br /&gt;
=== The Problem - The paradox of progress ===&lt;br /&gt;
Invariably, as development on any project moves forward, developers will realize that there are better, cleaner, or more elegant ways to structure things than they had been previously. These changes can be to improve efficiency, make an API more intuitive, keep code better organized, make common tasks more straightforward, or accomplish any number of other positive things. These changes can also make the development of additional features much more viable. In short, progress is good.&lt;br /&gt;
&lt;br /&gt;
On the other hand, a content-heavy program such as Wesnoth relies on the ability of content creators to efficiently create, maintain, and update their content. Too many changes all at once will force creators of existing content to spend obscene amounts time updating their creations just to keeping them up-to-date and in working order. This can lead to a high amount of frustration, a drop in motivation, and a decline in content being created. In short, progress is bad.&lt;br /&gt;
&lt;br /&gt;
=== Backwards Compatibility - benefits and drawbacks ===&lt;br /&gt;
Most of the time, older paradigms can still be maintained in a manner in which they coexist with the newer ones. This allows for existing content to continue functioning, while at the same time allowing and encouraging new content to be created using the newer methods. However, maintaining such code can be problematic in the following ways:&lt;br /&gt;
#There may eventually be architectural changes a developer would want to make where the old method's square peg no longer fits, even forcibly, into the new method's round hole.&lt;br /&gt;
#Having compatibility code hanging around may, depending on how it is implemented, mean that any updates made to the feature, module, or subsystem in question would have to made in both the new, cleaner design, and the older, poorly structured one, adding more work for developers.&lt;br /&gt;
&lt;br /&gt;
=== The Naive Approach - Deprecate and remove everything old ===&lt;br /&gt;
One approach to balancing old and new is to deprecate the old and slate its eventual removal after either a certain amount of time has passed or a certain number of subsequent versions have been released. This sounds good in theory, but in practice, there will be many changes which are minor or cosmetic in nature and which will add up. Things like replacing macros with WML tags, updating the name of an API call or order of parameters to be more consistent with other similar functions, or switching from a functional to an object-oriented structure are very good for organizational purposes, but will result in a large amount of maintenance required on the part of content creators to keep existing code operational, and for very little real gain. This approach invariably leads to the situation where so much is being changed from one version to the next that creators turn into maintainers, forced to spend nearly all of their time trying to stay ahead of the update curve in an attempt to keep their existing content working, and leaving them very little time and motivation to create new content. And of course, by the time they're finished painstakingly updating their existing code for every little change made for the current release, whoops, there's a new release with a whole slew of new changes that need accounting for. It simply becomes unmanageable.&lt;br /&gt;
&lt;br /&gt;
=== The Naive Approach - Deprecate and remove only when necessary ===&lt;br /&gt;
The opposite approach would be to keep all existing paradigms until they actively interfere with a new architecture or create a double-maintenance problem. While this approach does cut down on the maintenance burden by ensuring that content using an older design continues to work, it hinders progress by the fact that the moment at which it first becomes clear that an architectural or double-maintenance problem will occur is exactly the same moment at which keeping the old structure around becomes problematic. Beginning a deprecation cycle at that point and then having to &amp;quot;wait out&amp;quot; the old paradigm will cause an unacceptable delay in development.&lt;br /&gt;
&lt;br /&gt;
=== The Middle Ground - Deprecate everything old, remove only when necessary ===&lt;br /&gt;
Most of the time, older APIs can be implemented in terms of their newer, cleaner counterparts through the use of things like simple wrappers, parse-translators which re-write the older paradigm's code in terms of the new one, or other relatively low-maintenance &amp;quot;set-it-and-forget-it&amp;quot; approaches. These simple wrappers are not really detrimental to making progress, don't require updating when the new APIs internals are changed, and can usually be organized into their own files and/or modules so that they don't clutter the cleaner code. Many such wrappers will never truly present either of the backwards compatibility drawbacks mentioned above. As such, there is really no detriment to keeping them around indefinitely. However, occasionally, a new idea or approach will be put forth that updates the newer paradigm in such a way that the older one can no longer cleanly wrap to it. This usually happens, as inspiration is wont to do, suddenly, unexpectedly, and without warning. As such developers need the flexibility to be able to remove outdated code as freely as possible when the situation requires. Therefore, the ideal solution would be to deprecate any API which has newer, feature-complete ways to do it, while leaving it in the codebase until such time as its presence becomes a hindrance. Essentially, deprecation need not necessarily mean &amp;quot;this WILL be removed&amp;quot; so much as &amp;quot;this is now a candidate for removal&amp;quot;. By separating the concepts of deprecation and removal, both goals can be better served.&lt;br /&gt;
&lt;br /&gt;
=== Undefined removal timeline - issues encountered ===&lt;br /&gt;
In practice however, simply stating something is a candidate for removal while providing no further information on when it will actually be removed causes multiple issues:&lt;br /&gt;
* When a deprecated API is causing a maintenance burden worthy of removal is a subjective decision, often leading to debates over removal any time a developer decides it's time for an API to be removed, initially deprecated, or moved to a higher deprecation level.&lt;br /&gt;
* Lack of developer incentive to provide good documentation and support for the deprecation of the API given there's no particular timeline for when it will actually cause issues for UMC authors.&lt;br /&gt;
* UMC authors often don't find out about deprecated APIs and so can't possibly migrate to the new APIs.&lt;br /&gt;
* UMC authors aren't provided the documentation or tooling support needed to make updating their add-ons easier.&lt;br /&gt;
* UMC authors may simply decide there's no reason to update to the new API even if they know it's deprecated and how to update their add-on. After all, why spend time updating APIs that may stick around forever?&lt;br /&gt;
* Giving a version that an API '''may''' be removed instead of a version that it '''will''' be removed is not as clear as it may seem to UMC authors who aren't already aware of how Wesnoth handles deprecation. This can lead to UMC authors ignoring deprecation warnings after seeing such warnings for APIs which provide a version that's years old.&lt;br /&gt;
&lt;br /&gt;
=== Certainty is also a benefit ===&lt;br /&gt;
Wesnoth continues to exist today in large part because of the content made by its community. As such, developers should always be sparing in what they choose to deprecate and what they choose to remove, so that UMC authors can update their content to the latest version of Wesnoth without needing to make a herculean effort every couple of years.&lt;br /&gt;
&lt;br /&gt;
But, for cases where APIs are removed, the benefit of providing certainty for when that will happen outweighs the flexibility of being able remove them at any time after they been marked as deprecated. It encourages developers to provide the documentation and tooling support to make it easier for UMC authors to update their add-ons, and it lets UMC authors know when they can expect deprecated APIs to be removed rather than it effectively happening at random when a developer decides a deprecated API needs to be dropped.&lt;br /&gt;
&lt;br /&gt;
=== More Complex Cases - One size does not fit all ===&lt;br /&gt;
There may, however, be cases where the obsolete API cannot be implemented cleanly in terms of the updated one and must be maintained separately, or, in extremely rare cases, cannot coexist at all. There needs to be some leeway for such cases as well. In the former case, it therefore makes sense to allow for a feature to be deprecated pending removal after the shortest reasonable deprecation period. In the latter case, there is obviously no choice but to make the change and remove the old immediately. Developers should, naturally, be encouraged to find creative solutions to avoid such cases, but it is inevitable that there will eventually be a few cases where no graceful transition procedure can be found. These more aggressive forms of deprecation should only be done with developer consensus, and only after all options of creating a backwards-compatible transition have been exhausted.&lt;br /&gt;
&lt;br /&gt;
=== Graphics - The exception that proves the rule ===&lt;br /&gt;
The one area where backwards compatibility should NOT be a factor is graphical changes. Any change to the terrain graphics, unit sprites, or portrait images has the potential to result in visually-incompatible custom content. Core content creators cannot be expected to maintain a deprecated visual style alongside a more modern one, as any approach toward doing so would add an unreasonable amount of bloat and overhead, and make it very difficult for core graphics to be updated without having to do double the work. In addition, add-ons will continue to function even with such visual incompatibilities present, they just won't look right. As such, it can be said that stylistic incompatibilities fall more within the realm of content than of code, and it is not unreasonable to expect a content creator to... well...  create content. Expecting the graphical style to remain backwards-compatible would be just as unreasonable as expecting stories, help descriptions, or other forms of lore to never change because they may introduce plot holes into add-on stories. Essentially, since the goal of the software portion of Wesnoth is, at its heart, merely to facilitate the creation and advancement of this kind of content, core content needs to be free to develop unhindered by considerations for add-on content.&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=CompatibilityStandardsV2&amp;diff=74992</id>
		<title>CompatibilityStandardsV2</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=CompatibilityStandardsV2&amp;diff=74992"/>
		<updated>2026-04-23T15:33:26Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: /* When to deprecate */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;As a piece of software matures, there are often new designs, paradigms, and idioms developed which are superior to old ones. This creates an inherent conflict between the need for progress and the need for compatibility. Wesnoth is no exception. This document describes Wesnoth's approach toward resolving that conflict in a way which is most beneficial to both goals, as well as the rationale behind this approach.&lt;br /&gt;
&lt;br /&gt;
== Policy ==&lt;br /&gt;
This policy defines how the creation of new Wesnoth APIs and the deprecation and removal of old ones are to be handled. For the purposes of this document &amp;quot;API&amp;quot; means &amp;quot;any technical channel by which a content creator interacts with the game engine&amp;quot;. This includes, but is not limited to: preprocessor macros, WML tags, WFL functions, IPFs, and the Lua API. Note that this policy applies only to software APIs. Core content such as sprites, portraits, animations, lore, etc. are to be updated freely, without consideration for stylistic or literary conflicts that such content changes may present to add-ons.&lt;br /&gt;
&lt;br /&gt;
=== When to deprecate ===&lt;br /&gt;
==== Adding a better API ====&lt;br /&gt;
Any time a superior API is introduced which has '''complete feature-parity''' with an existing API, the old one should be immediately deprecated. Note that in most cases, in order to be considered to have &amp;quot;complete feature-parity&amp;quot;, the API should be available in the same language or area of the code as the obsolete one was. For example, the introduction of a more powerful API in Lua which can accomplish a superset of the functionality which had previously been available with a certain WML tag would not obsolete that WML tag. Exceptions can be made to this rule in cases where it is clear that the feature does not make a lot of sense in its current language or area, and was merely there for legacy reasons (such as the proper place for it not having been introduced yet at the time of its creation). Such exceptions should be determined by developer consensus.&lt;br /&gt;
&lt;br /&gt;
==== Preventing needed fixes or improvements ====&lt;br /&gt;
In such cases where a feature is preventing an important new feature from being added or makes it impossible to fix a problem impacting players, it can be preferable to deprecate the API to allow for the necessary changes to be made. APIs deprecated for this reason should still follow the deprecation schedule as normal, unless the fix or improvement is urgently needed.&lt;br /&gt;
&lt;br /&gt;
==== Actively harmful ====&lt;br /&gt;
If an API is found to cause significant problems for players or UMC authors, such as being prone to causing crashes while also very difficult to properly fix, corrupting saves and replays when not used correctly while being difficult to use correctly, or other similar situations, then such APIs should be deprecated and removed regardless of whether there is a replacement available.&lt;br /&gt;
&lt;br /&gt;
==== Unused ====&lt;br /&gt;
Any API that is not used in mainline and also is not used by the most recent version of an add-on on the add-ons server of the current or previous stable release can be deprecated. For example, if an add-on for 1.16 uses a deprecated API but the updated version of the add-on for 1.18 does not, then that add-on is not considered as currently using the API. Once deprecated for this reason, a new add-on being uploaded that uses the API is not a reason to undeprecate it.&lt;br /&gt;
&lt;br /&gt;
This does not need to be a passive process where developers simply check the add-ons server for whether an API is used - developers who want to deprecate an API for removal can proactively talk to and work with UMC authors to help update their add-ons to remove usage of said API. This can be anything from talking with them online about how to update to submitting updated code directly (ie: opening a PR against an add-on's public git repository).&lt;br /&gt;
&lt;br /&gt;
Deprecating and then removing APIs that are unused is the most preferred approach since their removal does not have any impact on UMC authors.&lt;br /&gt;
&lt;br /&gt;
=== When NOT to deprecate ===&lt;br /&gt;
==== Style ====&lt;br /&gt;
Deprecation should not be done purely for reasons of style. This is very subjective and prone to change as new contributors join and current contributors leave or become less active. As such, allowing deprecation for stylistic reasons would lead to entirely unnecessary work for UMC authors as developer preferences change over time.&lt;br /&gt;
&lt;br /&gt;
==== Renaming ====&lt;br /&gt;
While there can be exceptions, it is rarely a net positive to deprecate an API simply for the sake of renaming it to something else. It is preferable to either add a second name for the same function, leaving the old name as-is, or simply live with the current name rather than expecting all UMC authors using the API to update to the new name.&lt;br /&gt;
&lt;br /&gt;
==== Any other reason ====&lt;br /&gt;
Accepted reasons for deprecating APIs should be something that's discussed and agreed upon by the development team while also, ideally, including UMC authors. It should not become the norm that additional reasons to deprecate APIs are treated as exceptions and left as an increasingly forgotten discussion on Discord, IRC, or the forums - they should be added to here with the reasoning behind them.&lt;br /&gt;
&lt;br /&gt;
=== Deprecation awareness ===&lt;br /&gt;
==== Conflicting goals ====&lt;br /&gt;
When deprecating APIs there is an inherent conflict in terms of how to make UMC authors aware of the deprecation. After all, if they aren't aware something is deprecated, they can't know they may need to update their add-on. Therefore, deprecations need to be displayed in a place where they will see them and most UMC authors don't look at Wesnoth's logs unless there's some other issue they're investigating. At the same time, deprecation warnings aren't relevant to players and spamming deprecation warnings is not an effective way of communicating what the issues are.&lt;br /&gt;
&lt;br /&gt;
==== A middle ground ====&lt;br /&gt;
Each deprecated feature should make use of an appropriate deprecation function call for that language or subsystem to ensure that the appropriate deprecation notice is printed to the log output. Additionally, deprecation warnings should be displayed in-game in the following cases:&lt;br /&gt;
* If the player is running a development version, level 3 and level 4 deprecations should be shown in-game by default.&lt;br /&gt;
* If the player enables debug mode then all deprecation warnings should be shown, regardless of whether they're using a stable release or a development release.&lt;br /&gt;
&lt;br /&gt;
==== Documentation ====&lt;br /&gt;
It is also not enough to only display a warning at runtime when something deprecated is encountered. It is the responsibility of the development team to proactively make UMC authors aware of the deprecations and removals being done. To accomplish this:&lt;br /&gt;
* When an API is deprecated, and again if it's later removed, its deprecation or removal must be documented in the appropriate section of the changelog for the version it was deprecated or removed in.&lt;br /&gt;
* Likewise, it should be added to https://wiki.wesnoth.org/CompatibilityBreakingChanges&lt;br /&gt;
&lt;br /&gt;
Additionally, it is not enough to simply say that an API is deprecated. In the deprecation message itself as well as in the changelog and https://wiki.wesnoth.org/CompatibilityBreakingChanges, a description must be included as to why it was deprecated or removed and how UMC authors can update their add-ons to address it.&lt;br /&gt;
&lt;br /&gt;
Lastly, it should be understood that &amp;quot;removed&amp;quot; doesn't necessarily mean that the API is entirely gone from Wesnoth's codebase. There is no maintenance burden to keeping macro or method stubs that do nothing aside from printing an error message describing what was removed and why. Keeping such stubs around is highly encouraged as it is helpful for UMC authors trying to update very old add-ons to the current version of Wesnoth.&lt;br /&gt;
&lt;br /&gt;
=== How to deprecate ===&lt;br /&gt;
Every effort should be made to create the simplest possible wrappers which will translate from an obsolete API to the updated one. Such wrappers should ideally be organized into their own compatibility file or module, and set up in such a way that the internals of the updated API will not affect how the old calls get wrapped to the new one. Essentially, the idea is to create a set-it-and-forget-it compatibility wrapper which will continue to work regardless of updates made to the newer API.&lt;br /&gt;
&lt;br /&gt;
Additionally, in all cases where it's practical, the wmllint tool must be updated to be able to automatically handle updating add-ons for anything that's been deprecated except for APIs deprecated at level 1. While developers are still heavily encouraged to add wmllint support for level 1 deprecations, it is not required as these do not show deprecation warnings by default and are expected to continue working indefinitely.&lt;br /&gt;
&lt;br /&gt;
=== Deprecation levels - When to remove deprecated features ===&lt;br /&gt;
While creating simple compatibility wrappers should be possible most of the time, it would be unreasonable to assume that this approach will be viable in absolutely every case. Wesnoth's compatibility policy therefore has four different levels of deprecation which are used to set expectations for when and if an API is expected to be removed:&lt;br /&gt;
&lt;br /&gt;
#Deprecated indefinitely &amp;amp;mdash; This deprecation level is for changes which have newer preferred alternatives but, barring any unforeseen issues, have little to no maintenance impact and should be kept indefinitely in order to reduce the work required for UMC authors to maintain their content. For example, functions or attributes which have had their names changed, macros which have been replaced with tags, or simple wrappers with little to no maintenance overhead. If future large scale changes make it impractical to maintain an API deprecated at this level then the deprecation level should be raised accordingly. This is generally the preferred deprecation level - higher deprecation levels are for APIs which are intended for eventual removal and must be weighed against the maintenance work this forces upon UMC authors.&lt;br /&gt;
#Deprecated with the intention of future removal &amp;amp;mdash; This deprecation level is for APIs which will be removed in a future version, but the version they are removed in has not yet have been decided. Barring urgent circumstances, all APIs that are deprecated with the intention of being removed '''must''' start with being deprecated at level 2 for 1-2 development cycles at minimum depending on the impact of the API's removal on UMC authors. Once the API has spent the necessary amount of time at deprecation level 2, it can be moved to deprecation level 3. It is not allowed to deprecate an API at level 2 and change it to level 3 in the same development cycle. There is no maximum amount of time that an API can remain deprecated at level 2.&lt;br /&gt;
#Deprecated for removal in a specific version &amp;amp;mdash; This deprecation level is for APIs which were previously deprecated at level 2 and now have a future version at which they will be removed. The version an API is removed in must be at least two development cycles after the API was deprecated at level 2. It is not allowed to move an API to deprecation level 3 and then remove it in the same development cycle.&lt;br /&gt;
#Removed without deprecation &amp;amp;mdash; This level should be used EXTREMELY rarely, and only in cases where it is ABSOLUTELY NECESSARY. Occasionally, an update to a feature will change the underlying architecture in such a fundamental way that the old paradigm cannot coexist with the new one no matter how much redundant code one would create. While this kind of scenario is extremely rare, and every effort should be made to find creative solutions to avoid it, there are occasionally cases where it truly is impossible to maintain both methods even in the short term. This level should only be used with broad developer consensus, after the majority of active developers familiar with the feature in question have given at least some thought to trying to deprecate gracefully and failed. This level should also be used for macro and method stubs containing only an error message describing what was removed and why.&lt;br /&gt;
&lt;br /&gt;
== Rationale ==&lt;br /&gt;
The above policy is the result of a large amount of thought, discussion, and debate. Following is a brief outline of the considerations and goals on both sides of the problem, why there is an inherent conflict between them, some failed approaches to resolving the conflict, and how the final policy ultimately maximizes the pursuit of both goals.&lt;br /&gt;
&lt;br /&gt;
=== The Problem - The paradox of progress ===&lt;br /&gt;
Invariably, as development on any project moves forward, developers will realize that there are better, cleaner, or more elegant ways to structure things than they had been previously. These changes can be to improve efficiency, make an API more intuitive, keep code better organized, make common tasks more straightforward, or accomplish any number of other positive things. These changes can also make the development of additional features much more viable. In short, progress is good.&lt;br /&gt;
&lt;br /&gt;
On the other hand, a content-heavy program such as Wesnoth relies on the ability of content creators to efficiently create, maintain, and update their content. Too many changes all at once will force creators of existing content to spend obscene amounts time updating their creations just to keeping them up-to-date and in working order. This can lead to a high amount of frustration, a drop in motivation, and a decline in content being created. In short, progress is bad.&lt;br /&gt;
&lt;br /&gt;
=== Backwards Compatibility - benefits and drawbacks ===&lt;br /&gt;
Most of the time, older paradigms can still be maintained in a manner in which they coexist with the newer ones. This allows for existing content to continue functioning, while at the same time allowing and encouraging new content to be created using the newer methods. However, maintaining such code can be problematic in the following ways:&lt;br /&gt;
#There may eventually be architectural changes a developer would want to make where the old method's square peg no longer fits, even forcibly, into the new method's round hole.&lt;br /&gt;
#Having compatibility code hanging around may, depending on how it is implemented, mean that any updates made to the feature, module, or subsystem in question would have to made in both the new, cleaner design, and the older, poorly structured one, adding more work for developers.&lt;br /&gt;
&lt;br /&gt;
=== The Naive Approach - Deprecate and remove everything old ===&lt;br /&gt;
One approach to balancing old and new is to deprecate the old and slate its eventual removal after either a certain amount of time has passed or a certain number of subsequent versions have been released. This sounds good in theory, but in practice, there will be many changes which are minor or cosmetic in nature and which will add up. Things like replacing macros with WML tags, updating the name of an API call or order of parameters to be more consistent with other similar functions, or switching from a functional to an object-oriented structure are very good for organizational purposes, but will result in a large amount of maintenance required on the part of content creators to keep existing code operational, and for very little real gain. This approach invariably leads to the situation where so much is being changed from one version to the next that creators turn into maintainers, forced to spend nearly all of their time trying to stay ahead of the update curve in an attempt to keep their existing content working, and leaving them very little time and motivation to create new content. And of course, by the time they're finished painstakingly updating their existing code for every little change made for the current release, whoops, there's a new release with a whole slew of new changes that need accounting for. It simply becomes unmanageable.&lt;br /&gt;
&lt;br /&gt;
=== The Naive Approach - Deprecate and remove only when necessary ===&lt;br /&gt;
The opposite approach would be to keep all existing paradigms until they actively interfere with a new architecture or create a double-maintenance problem. While this approach does cut down on the maintenance burden by ensuring that content using an older design continues to work, it hinders progress by the fact that the moment at which it first becomes clear that an architectural or double-maintenance problem will occur is exactly the same moment at which keeping the old structure around becomes problematic. Beginning a deprecation cycle at that point and then having to &amp;quot;wait out&amp;quot; the old paradigm will cause an unacceptable delay in development.&lt;br /&gt;
&lt;br /&gt;
=== The Middle Ground - Deprecate everything old, remove only when necessary ===&lt;br /&gt;
Most of the time, older APIs can be implemented in terms of their newer, cleaner counterparts through the use of things like simple wrappers, parse-translators which re-write the older paradigm's code in terms of the new one, or other relatively low-maintenance &amp;quot;set-it-and-forget-it&amp;quot; approaches. These simple wrappers are not really detrimental to making progress, don't require updating when the new APIs internals are changed, and can usually be organized into their own files and/or modules so that they don't clutter the cleaner code. Many such wrappers will never truly present either of the backwards compatibility drawbacks mentioned above. As such, there is really no detriment to keeping them around indefinitely. However, occasionally, a new idea or approach will be put forth that updates the newer paradigm in such a way that the older one can no longer cleanly wrap to it. This usually happens, as inspiration is wont to do, suddenly, unexpectedly, and without warning. As such developers need the flexibility to be able to remove outdated code as freely as possible when the situation requires. Therefore, the ideal solution would be to deprecate any API which has newer, feature-complete ways to do it, while leaving it in the codebase until such time as its presence becomes a hindrance. Essentially, deprecation need not necessarily mean &amp;quot;this WILL be removed&amp;quot; so much as &amp;quot;this is now a candidate for removal&amp;quot;. By separating the concepts of deprecation and removal, both goals can be better served.&lt;br /&gt;
&lt;br /&gt;
=== Undefined removal timeline - issues encountered ===&lt;br /&gt;
In practice however, simply stating something is a candidate for removal while providing no further information on when it will actually be removed causes multiple issues:&lt;br /&gt;
* When a deprecated API is causing a maintenance burden worthy of removal is a subjective decision, often leading to debates over removal any time a developer decides it's time for an API to be removed, initially deprecated, or moved to a higher deprecation level.&lt;br /&gt;
* Lack of developer incentive to provide good documentation and support for the deprecation of the API given there's no particular timeline for when it will actually cause issues for UMC authors.&lt;br /&gt;
* UMC authors often don't find out about deprecated APIs and so can't possibly migrate to the new APIs.&lt;br /&gt;
* UMC authors aren't provided the documentation or tooling support needed to make updating their add-ons easier.&lt;br /&gt;
* UMC authors may simply decide there's no reason to update to the new API even if they know it's deprecated and how to update their add-on. After all, why spend time updating APIs that may stick around forever?&lt;br /&gt;
* Giving a version that an API '''may''' be removed instead of a version that it '''will''' be removed is not as clear as it may seem to UMC authors who aren't already aware of how Wesnoth handles deprecation. This can lead to UMC authors ignoring deprecation warnings after seeing such warnings for APIs which provide a version that's years old.&lt;br /&gt;
&lt;br /&gt;
=== Certainty is also a benefit ===&lt;br /&gt;
Wesnoth continues to exist today in large part because of the content made by its community. As such, developers should always be sparing in what they choose to deprecate and what they choose to remove, so that UMC authors can update their content to the latest version of Wesnoth without needing to make a herculean effort every couple of years.&lt;br /&gt;
&lt;br /&gt;
But, for cases where APIs are removed, the benefit of providing certainty for when that will happen outweighs the flexibility of being able remove them at any time after they been marked as deprecated. It encourages developers to provide the documentation and tooling support to make it easier for UMC authors to update their add-ons, and it lets UMC authors know when they can expect deprecated APIs to be removed rather than it effectively happening at random when a developer decides a deprecated API needs to be dropped.&lt;br /&gt;
&lt;br /&gt;
=== More Complex Cases - One size does not fit all ===&lt;br /&gt;
There may, however, be cases where the obsolete API cannot be implemented cleanly in terms of the updated one and must be maintained separately, or, in extremely rare cases, cannot coexist at all. There needs to be some leeway for such cases as well. In the former case, it therefore makes sense to allow for a feature to be deprecated pending removal after the shortest reasonable deprecation period. In the latter case, there is obviously no choice but to make the change and remove the old immediately. Developers should, naturally, be encouraged to find creative solutions to avoid such cases, but it is inevitable that there will eventually be a few cases where no graceful transition procedure can be found. These more aggressive forms of deprecation should only be done with developer consensus, and only after all options of creating a backwards-compatible transition have been exhausted.&lt;br /&gt;
&lt;br /&gt;
=== Graphics - The exception that proves the rule ===&lt;br /&gt;
The one area where backwards compatibility should NOT be a factor is graphical changes. Any change to the terrain graphics, unit sprites, or portrait images has the potential to result in visually-incompatible custom content. Core content creators cannot be expected to maintain a deprecated visual style alongside a more modern one, as any approach toward doing so would add an unreasonable amount of bloat and overhead, and make it very difficult for core graphics to be updated without having to do double the work. In addition, add-ons will continue to function even with such visual incompatibilities present, they just won't look right. As such, it can be said that stylistic incompatibilities fall more within the realm of content than of code, and it is not unreasonable to expect a content creator to... well...  create content. Expecting the graphical style to remain backwards-compatible would be just as unreasonable as expecting stories, help descriptions, or other forms of lore to never change because they may introduce plot holes into add-on stories. Essentially, since the goal of the software portion of Wesnoth is, at its heart, merely to facilitate the creation and advancement of this kind of content, core content needs to be free to develop unhindered by considerations for add-on content.&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=CompatibilityStandardsV2&amp;diff=74988</id>
		<title>CompatibilityStandardsV2</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=CompatibilityStandardsV2&amp;diff=74988"/>
		<updated>2026-04-20T22:54:45Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: /* Deprecation levels - When to remove deprecated features */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;As a piece of software matures, there are often new designs, paradigms, and idioms developed which are superior to old ones. This creates an inherent conflict between the need for progress and the need for compatibility. Wesnoth is no exception. This document describes Wesnoth's approach toward resolving that conflict in a way which is most beneficial to both goals, as well as the rationale behind this approach.&lt;br /&gt;
&lt;br /&gt;
== Policy ==&lt;br /&gt;
This policy defines how the creation of new Wesnoth APIs and the deprecation and removal of old ones are to be handled. For the purposes of this document &amp;quot;API&amp;quot; means &amp;quot;any technical channel by which a content creator interacts with the game engine&amp;quot;. This includes, but is not limited to: preprocessor macros, WML tags, WFL functions, IPFs, and the Lua API. Note that this policy applies only to software APIs. Core content such as sprites, portraits, animations, lore, etc. are to be updated freely, without consideration for stylistic or literary conflicts that such content changes may present to add-ons.&lt;br /&gt;
&lt;br /&gt;
=== When to deprecate ===&lt;br /&gt;
==== Adding a better API ====&lt;br /&gt;
Any time a superior API is introduced which has '''complete feature-parity''' with an existing API, the old one should be immediately deprecated. Note that in most cases, in order to be considered to have &amp;quot;complete feature-parity&amp;quot;, the API should be available in the same language or area of the code as the obsolete one was. For example, the introduction of a more powerful API in Lua which can accomplish a superset of the functionality which had previously been available with a certain WML tag would not obsolete that WML tag. Exceptions can be made to this rule in cases where it is clear that the feature does not make a lot of sense in its current language or area, and was merely there for legacy reasons (such as the proper place for it not having been introduced yet at the time of its creation). Such exceptions should be determined by developer consensus.&lt;br /&gt;
&lt;br /&gt;
==== Preventing needed fixes or improvements ====&lt;br /&gt;
In such cases where a feature is preventing an important new feature from being added or makes it impossible to fix a problem impacting players, it can be preferable to deprecate the API to allow for the necessary changes to be made. APIs deprecated for this reason should still follow the deprecation schedule as normal, unless the fix or improvement is urgently needed.&lt;br /&gt;
&lt;br /&gt;
==== Actively harmful ====&lt;br /&gt;
If an API is found to cause significant problems for players or UMC authors, such as being prone to causing crashes while also very difficult to properly fix, corrupting saves and replays when not used correctly while being difficult to use correctly, or other similar situations, then such APIs should be deprecated and removed regardless of whether there is a replacement available.&lt;br /&gt;
&lt;br /&gt;
==== Security ====&lt;br /&gt;
If an API is found to have a security flaw that can't be fixed, then it should not be deprecated, it should be immediately removed.&lt;br /&gt;
&lt;br /&gt;
==== Unused ====&lt;br /&gt;
Any API that is not used in mainline and also is not used by the most recent version of an add-on on the add-ons server of the current or previous stable release can be deprecated. For example, if an add-on for 1.16 uses a deprecated API but the updated version of the add-on for 1.18 does not, then that add-on is not considered as currently using the API. Once deprecated for this reason, a new add-on being uploaded that uses the API is not a reason to undeprecate it.&lt;br /&gt;
&lt;br /&gt;
This does not need to be a passive process where developers simply check the add-ons server for whether an API is used - developers who want to deprecate an API for removal can proactively talk to and work with UMC authors to help update their add-ons to remove usage of said API. This can be anything from talking with them online about how to update to submitting updated code directly (ie: opening a PR against an add-on's public git repository).&lt;br /&gt;
&lt;br /&gt;
Deprecating and then removing APIs that are unused is the most preferred approach since their removal does not have any impact on UMC authors.&lt;br /&gt;
&lt;br /&gt;
=== When NOT to deprecate ===&lt;br /&gt;
==== Style ====&lt;br /&gt;
Deprecation should not be done purely for reasons of style. This is very subjective and prone to change as new contributors join and current contributors leave or become less active. As such, allowing deprecation for stylistic reasons would lead to entirely unnecessary work for UMC authors as developer preferences change over time.&lt;br /&gt;
&lt;br /&gt;
==== Renaming ====&lt;br /&gt;
While there can be exceptions, it is rarely a net positive to deprecate an API simply for the sake of renaming it to something else. It is preferable to either add a second name for the same function, leaving the old name as-is, or simply live with the current name rather than expecting all UMC authors using the API to update to the new name.&lt;br /&gt;
&lt;br /&gt;
==== Any other reason ====&lt;br /&gt;
Accepted reasons for deprecating APIs should be something that's discussed and agreed upon by the development team while also, ideally, including UMC authors. It should not become the norm that additional reasons to deprecate APIs are treated as exceptions and left as an increasingly forgotten discussion on Discord, IRC, or the forums - they should be added to here with the reasoning behind them.&lt;br /&gt;
&lt;br /&gt;
=== Deprecation awareness ===&lt;br /&gt;
==== Conflicting goals ====&lt;br /&gt;
When deprecating APIs there is an inherent conflict in terms of how to make UMC authors aware of the deprecation. After all, if they aren't aware something is deprecated, they can't know they may need to update their add-on. Therefore, deprecations need to be displayed in a place where they will see them and most UMC authors don't look at Wesnoth's logs unless there's some other issue they're investigating. At the same time, deprecation warnings aren't relevant to players and spamming deprecation warnings is not an effective way of communicating what the issues are.&lt;br /&gt;
&lt;br /&gt;
==== A middle ground ====&lt;br /&gt;
Each deprecated feature should make use of an appropriate deprecation function call for that language or subsystem to ensure that the appropriate deprecation notice is printed to the log output. Additionally, deprecation warnings should be displayed in-game in the following cases:&lt;br /&gt;
* If the player is running a development version, level 3 and level 4 deprecations should be shown in-game by default.&lt;br /&gt;
* If the player enables debug mode then all deprecation warnings should be shown, regardless of whether they're using a stable release or a development release.&lt;br /&gt;
&lt;br /&gt;
==== Documentation ====&lt;br /&gt;
It is also not enough to only display a warning at runtime when something deprecated is encountered. It is the responsibility of the development team to proactively make UMC authors aware of the deprecations and removals being done. To accomplish this:&lt;br /&gt;
* When an API is deprecated, and again if it's later removed, its deprecation or removal must be documented in the appropriate section of the changelog for the version it was deprecated or removed in.&lt;br /&gt;
* Likewise, it should be added to https://wiki.wesnoth.org/CompatibilityBreakingChanges&lt;br /&gt;
&lt;br /&gt;
Additionally, it is not enough to simply say that an API is deprecated. In the deprecation message itself as well as in the changelog and https://wiki.wesnoth.org/CompatibilityBreakingChanges, a description must be included as to why it was deprecated or removed and how UMC authors can update their add-ons to address it.&lt;br /&gt;
&lt;br /&gt;
Lastly, it should be understood that &amp;quot;removed&amp;quot; doesn't necessarily mean that the API is entirely gone from Wesnoth's codebase. There is no maintenance burden to keeping macro or method stubs that do nothing aside from printing an error message describing what was removed and why. Keeping such stubs around is highly encouraged as it is helpful for UMC authors trying to update very old add-ons to the current version of Wesnoth.&lt;br /&gt;
&lt;br /&gt;
=== How to deprecate ===&lt;br /&gt;
Every effort should be made to create the simplest possible wrappers which will translate from an obsolete API to the updated one. Such wrappers should ideally be organized into their own compatibility file or module, and set up in such a way that the internals of the updated API will not affect how the old calls get wrapped to the new one. Essentially, the idea is to create a set-it-and-forget-it compatibility wrapper which will continue to work regardless of updates made to the newer API.&lt;br /&gt;
&lt;br /&gt;
Additionally, in all cases where it's practical, the wmllint tool must be updated to be able to automatically handle updating add-ons for anything that's been deprecated except for APIs deprecated at level 1. While developers are still heavily encouraged to add wmllint support for level 1 deprecations, it is not required as these do not show deprecation warnings by default and are expected to continue working indefinitely.&lt;br /&gt;
&lt;br /&gt;
=== Deprecation levels - When to remove deprecated features ===&lt;br /&gt;
While creating simple compatibility wrappers should be possible most of the time, it would be unreasonable to assume that this approach will be viable in absolutely every case. Wesnoth's compatibility policy therefore has four different levels of deprecation which are used to set expectations for when and if an API is expected to be removed:&lt;br /&gt;
&lt;br /&gt;
#Deprecated indefinitely &amp;amp;mdash; This deprecation level is for changes which have newer preferred alternatives but, barring any unforeseen issues, have little to no maintenance impact and should be kept indefinitely in order to reduce the work required for UMC authors to maintain their content. For example, functions or attributes which have had their names changed, macros which have been replaced with tags, or simple wrappers with little to no maintenance overhead. If future large scale changes make it impractical to maintain an API deprecated at this level then the deprecation level should be raised accordingly. This is generally the preferred deprecation level - higher deprecation levels are for APIs which are intended for eventual removal and must be weighed against the maintenance work this forces upon UMC authors.&lt;br /&gt;
#Deprecated with the intention of future removal &amp;amp;mdash; This deprecation level is for APIs which will be removed in a future version, but the version they are removed in has not yet have been decided. Barring urgent circumstances, all APIs that are deprecated with the intention of being removed '''must''' start with being deprecated at level 2 for 1-2 development cycles at minimum depending on the impact of the API's removal on UMC authors. Once the API has spent the necessary amount of time at deprecation level 2, it can be moved to deprecation level 3. It is not allowed to deprecate an API at level 2 and change it to level 3 in the same development cycle. There is no maximum amount of time that an API can remain deprecated at level 2.&lt;br /&gt;
#Deprecated for removal in a specific version &amp;amp;mdash; This deprecation level is for APIs which were previously deprecated at level 2 and now have a future version at which they will be removed. The version an API is removed in must be at least two development cycles after the API was deprecated at level 2. It is not allowed to move an API to deprecation level 3 and then remove it in the same development cycle.&lt;br /&gt;
#Removed without deprecation &amp;amp;mdash; This level should be used EXTREMELY rarely, and only in cases where it is ABSOLUTELY NECESSARY. Occasionally, an update to a feature will change the underlying architecture in such a fundamental way that the old paradigm cannot coexist with the new one no matter how much redundant code one would create. While this kind of scenario is extremely rare, and every effort should be made to find creative solutions to avoid it, there are occasionally cases where it truly is impossible to maintain both methods even in the short term. This level should only be used with broad developer consensus, after the majority of active developers familiar with the feature in question have given at least some thought to trying to deprecate gracefully and failed. This level should also be used for macro and method stubs containing only an error message describing what was removed and why.&lt;br /&gt;
&lt;br /&gt;
== Rationale ==&lt;br /&gt;
The above policy is the result of a large amount of thought, discussion, and debate. Following is a brief outline of the considerations and goals on both sides of the problem, why there is an inherent conflict between them, some failed approaches to resolving the conflict, and how the final policy ultimately maximizes the pursuit of both goals.&lt;br /&gt;
&lt;br /&gt;
=== The Problem - The paradox of progress ===&lt;br /&gt;
Invariably, as development on any project moves forward, developers will realize that there are better, cleaner, or more elegant ways to structure things than they had been previously. These changes can be to improve efficiency, make an API more intuitive, keep code better organized, make common tasks more straightforward, or accomplish any number of other positive things. These changes can also make the development of additional features much more viable. In short, progress is good.&lt;br /&gt;
&lt;br /&gt;
On the other hand, a content-heavy program such as Wesnoth relies on the ability of content creators to efficiently create, maintain, and update their content. Too many changes all at once will force creators of existing content to spend obscene amounts time updating their creations just to keeping them up-to-date and in working order. This can lead to a high amount of frustration, a drop in motivation, and a decline in content being created. In short, progress is bad.&lt;br /&gt;
&lt;br /&gt;
=== Backwards Compatibility - benefits and drawbacks ===&lt;br /&gt;
Most of the time, older paradigms can still be maintained in a manner in which they coexist with the newer ones. This allows for existing content to continue functioning, while at the same time allowing and encouraging new content to be created using the newer methods. However, maintaining such code can be problematic in the following ways:&lt;br /&gt;
#There may eventually be architectural changes a developer would want to make where the old method's square peg no longer fits, even forcibly, into the new method's round hole.&lt;br /&gt;
#Having compatibility code hanging around may, depending on how it is implemented, mean that any updates made to the feature, module, or subsystem in question would have to made in both the new, cleaner design, and the older, poorly structured one, adding more work for developers.&lt;br /&gt;
&lt;br /&gt;
=== The Naive Approach - Deprecate and remove everything old ===&lt;br /&gt;
One approach to balancing old and new is to deprecate the old and slate its eventual removal after either a certain amount of time has passed or a certain number of subsequent versions have been released. This sounds good in theory, but in practice, there will be many changes which are minor or cosmetic in nature and which will add up. Things like replacing macros with WML tags, updating the name of an API call or order of parameters to be more consistent with other similar functions, or switching from a functional to an object-oriented structure are very good for organizational purposes, but will result in a large amount of maintenance required on the part of content creators to keep existing code operational, and for very little real gain. This approach invariably leads to the situation where so much is being changed from one version to the next that creators turn into maintainers, forced to spend nearly all of their time trying to stay ahead of the update curve in an attempt to keep their existing content working, and leaving them very little time and motivation to create new content. And of course, by the time they're finished painstakingly updating their existing code for every little change made for the current release, whoops, there's a new release with a whole slew of new changes that need accounting for. It simply becomes unmanageable.&lt;br /&gt;
&lt;br /&gt;
=== The Naive Approach - Deprecate and remove only when necessary ===&lt;br /&gt;
The opposite approach would be to keep all existing paradigms until they actively interfere with a new architecture or create a double-maintenance problem. While this approach does cut down on the maintenance burden by ensuring that content using an older design continues to work, it hinders progress by the fact that the moment at which it first becomes clear that an architectural or double-maintenance problem will occur is exactly the same moment at which keeping the old structure around becomes problematic. Beginning a deprecation cycle at that point and then having to &amp;quot;wait out&amp;quot; the old paradigm will cause an unacceptable delay in development.&lt;br /&gt;
&lt;br /&gt;
=== The Middle Ground - Deprecate everything old, remove only when necessary ===&lt;br /&gt;
Most of the time, older APIs can be implemented in terms of their newer, cleaner counterparts through the use of things like simple wrappers, parse-translators which re-write the older paradigm's code in terms of the new one, or other relatively low-maintenance &amp;quot;set-it-and-forget-it&amp;quot; approaches. These simple wrappers are not really detrimental to making progress, don't require updating when the new APIs internals are changed, and can usually be organized into their own files and/or modules so that they don't clutter the cleaner code. Many such wrappers will never truly present either of the backwards compatibility drawbacks mentioned above. As such, there is really no detriment to keeping them around indefinitely. However, occasionally, a new idea or approach will be put forth that updates the newer paradigm in such a way that the older one can no longer cleanly wrap to it. This usually happens, as inspiration is wont to do, suddenly, unexpectedly, and without warning. As such developers need the flexibility to be able to remove outdated code as freely as possible when the situation requires. Therefore, the ideal solution would be to deprecate any API which has newer, feature-complete ways to do it, while leaving it in the codebase until such time as its presence becomes a hindrance. Essentially, deprecation need not necessarily mean &amp;quot;this WILL be removed&amp;quot; so much as &amp;quot;this is now a candidate for removal&amp;quot;. By separating the concepts of deprecation and removal, both goals can be better served.&lt;br /&gt;
&lt;br /&gt;
=== Undefined removal timeline - issues encountered ===&lt;br /&gt;
In practice however, simply stating something is a candidate for removal while providing no further information on when it will actually be removed causes multiple issues:&lt;br /&gt;
* When a deprecated API is causing a maintenance burden worthy of removal is a subjective decision, often leading to debates over removal any time a developer decides it's time for an API to be removed, initially deprecated, or moved to a higher deprecation level.&lt;br /&gt;
* Lack of developer incentive to provide good documentation and support for the deprecation of the API given there's no particular timeline for when it will actually cause issues for UMC authors.&lt;br /&gt;
* UMC authors often don't find out about deprecated APIs and so can't possibly migrate to the new APIs.&lt;br /&gt;
* UMC authors aren't provided the documentation or tooling support needed to make updating their add-ons easier.&lt;br /&gt;
* UMC authors may simply decide there's no reason to update to the new API even if they know it's deprecated and how to update their add-on. After all, why spend time updating APIs that may stick around forever?&lt;br /&gt;
* Giving a version that an API '''may''' be removed instead of a version that it '''will''' be removed is not as clear as it may seem to UMC authors who aren't already aware of how Wesnoth handles deprecation. This can lead to UMC authors ignoring deprecation warnings after seeing such warnings for APIs which provide a version that's years old.&lt;br /&gt;
&lt;br /&gt;
=== Certainty is also a benefit ===&lt;br /&gt;
Wesnoth continues to exist today in large part because of the content made by its community. As such, developers should always be sparing in what they choose to deprecate and what they choose to remove, so that UMC authors can update their content to the latest version of Wesnoth without needing to make a herculean effort every couple of years.&lt;br /&gt;
&lt;br /&gt;
But, for cases where APIs are removed, the benefit of providing certainty for when that will happen outweighs the flexibility of being able remove them at any time after they been marked as deprecated. It encourages developers to provide the documentation and tooling support to make it easier for UMC authors to update their add-ons, and it lets UMC authors know when they can expect deprecated APIs to be removed rather than it effectively happening at random when a developer decides a deprecated API needs to be dropped.&lt;br /&gt;
&lt;br /&gt;
=== More Complex Cases - One size does not fit all ===&lt;br /&gt;
There may, however, be cases where the obsolete API cannot be implemented cleanly in terms of the updated one and must be maintained separately, or, in extremely rare cases, cannot coexist at all. There needs to be some leeway for such cases as well. In the former case, it therefore makes sense to allow for a feature to be deprecated pending removal after the shortest reasonable deprecation period. In the latter case, there is obviously no choice but to make the change and remove the old immediately. Developers should, naturally, be encouraged to find creative solutions to avoid such cases, but it is inevitable that there will eventually be a few cases where no graceful transition procedure can be found. These more aggressive forms of deprecation should only be done with developer consensus, and only after all options of creating a backwards-compatible transition have been exhausted.&lt;br /&gt;
&lt;br /&gt;
=== Graphics - The exception that proves the rule ===&lt;br /&gt;
The one area where backwards compatibility should NOT be a factor is graphical changes. Any change to the terrain graphics, unit sprites, or portrait images has the potential to result in visually-incompatible custom content. Core content creators cannot be expected to maintain a deprecated visual style alongside a more modern one, as any approach toward doing so would add an unreasonable amount of bloat and overhead, and make it very difficult for core graphics to be updated without having to do double the work. In addition, add-ons will continue to function even with such visual incompatibilities present, they just won't look right. As such, it can be said that stylistic incompatibilities fall more within the realm of content than of code, and it is not unreasonable to expect a content creator to... well...  create content. Expecting the graphical style to remain backwards-compatible would be just as unreasonable as expecting stories, help descriptions, or other forms of lore to never change because they may introduce plot holes into add-on stories. Essentially, since the goal of the software portion of Wesnoth is, at its heart, merely to facilitate the creation and advancement of this kind of content, core content needs to be free to develop unhindered by considerations for add-on content.&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=CompatibilityStandardsV2&amp;diff=74987</id>
		<title>CompatibilityStandardsV2</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=CompatibilityStandardsV2&amp;diff=74987"/>
		<updated>2026-04-20T22:54:33Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: /* Deprecation levels - When to remove deprecated features */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;As a piece of software matures, there are often new designs, paradigms, and idioms developed which are superior to old ones. This creates an inherent conflict between the need for progress and the need for compatibility. Wesnoth is no exception. This document describes Wesnoth's approach toward resolving that conflict in a way which is most beneficial to both goals, as well as the rationale behind this approach.&lt;br /&gt;
&lt;br /&gt;
== Policy ==&lt;br /&gt;
This policy defines how the creation of new Wesnoth APIs and the deprecation and removal of old ones are to be handled. For the purposes of this document &amp;quot;API&amp;quot; means &amp;quot;any technical channel by which a content creator interacts with the game engine&amp;quot;. This includes, but is not limited to: preprocessor macros, WML tags, WFL functions, IPFs, and the Lua API. Note that this policy applies only to software APIs. Core content such as sprites, portraits, animations, lore, etc. are to be updated freely, without consideration for stylistic or literary conflicts that such content changes may present to add-ons.&lt;br /&gt;
&lt;br /&gt;
=== When to deprecate ===&lt;br /&gt;
==== Adding a better API ====&lt;br /&gt;
Any time a superior API is introduced which has '''complete feature-parity''' with an existing API, the old one should be immediately deprecated. Note that in most cases, in order to be considered to have &amp;quot;complete feature-parity&amp;quot;, the API should be available in the same language or area of the code as the obsolete one was. For example, the introduction of a more powerful API in Lua which can accomplish a superset of the functionality which had previously been available with a certain WML tag would not obsolete that WML tag. Exceptions can be made to this rule in cases where it is clear that the feature does not make a lot of sense in its current language or area, and was merely there for legacy reasons (such as the proper place for it not having been introduced yet at the time of its creation). Such exceptions should be determined by developer consensus.&lt;br /&gt;
&lt;br /&gt;
==== Preventing needed fixes or improvements ====&lt;br /&gt;
In such cases where a feature is preventing an important new feature from being added or makes it impossible to fix a problem impacting players, it can be preferable to deprecate the API to allow for the necessary changes to be made. APIs deprecated for this reason should still follow the deprecation schedule as normal, unless the fix or improvement is urgently needed.&lt;br /&gt;
&lt;br /&gt;
==== Actively harmful ====&lt;br /&gt;
If an API is found to cause significant problems for players or UMC authors, such as being prone to causing crashes while also very difficult to properly fix, corrupting saves and replays when not used correctly while being difficult to use correctly, or other similar situations, then such APIs should be deprecated and removed regardless of whether there is a replacement available.&lt;br /&gt;
&lt;br /&gt;
==== Security ====&lt;br /&gt;
If an API is found to have a security flaw that can't be fixed, then it should not be deprecated, it should be immediately removed.&lt;br /&gt;
&lt;br /&gt;
==== Unused ====&lt;br /&gt;
Any API that is not used in mainline and also is not used by the most recent version of an add-on on the add-ons server of the current or previous stable release can be deprecated. For example, if an add-on for 1.16 uses a deprecated API but the updated version of the add-on for 1.18 does not, then that add-on is not considered as currently using the API. Once deprecated for this reason, a new add-on being uploaded that uses the API is not a reason to undeprecate it.&lt;br /&gt;
&lt;br /&gt;
This does not need to be a passive process where developers simply check the add-ons server for whether an API is used - developers who want to deprecate an API for removal can proactively talk to and work with UMC authors to help update their add-ons to remove usage of said API. This can be anything from talking with them online about how to update to submitting updated code directly (ie: opening a PR against an add-on's public git repository).&lt;br /&gt;
&lt;br /&gt;
Deprecating and then removing APIs that are unused is the most preferred approach since their removal does not have any impact on UMC authors.&lt;br /&gt;
&lt;br /&gt;
=== When NOT to deprecate ===&lt;br /&gt;
==== Style ====&lt;br /&gt;
Deprecation should not be done purely for reasons of style. This is very subjective and prone to change as new contributors join and current contributors leave or become less active. As such, allowing deprecation for stylistic reasons would lead to entirely unnecessary work for UMC authors as developer preferences change over time.&lt;br /&gt;
&lt;br /&gt;
==== Renaming ====&lt;br /&gt;
While there can be exceptions, it is rarely a net positive to deprecate an API simply for the sake of renaming it to something else. It is preferable to either add a second name for the same function, leaving the old name as-is, or simply live with the current name rather than expecting all UMC authors using the API to update to the new name.&lt;br /&gt;
&lt;br /&gt;
==== Any other reason ====&lt;br /&gt;
Accepted reasons for deprecating APIs should be something that's discussed and agreed upon by the development team while also, ideally, including UMC authors. It should not become the norm that additional reasons to deprecate APIs are treated as exceptions and left as an increasingly forgotten discussion on Discord, IRC, or the forums - they should be added to here with the reasoning behind them.&lt;br /&gt;
&lt;br /&gt;
=== Deprecation awareness ===&lt;br /&gt;
==== Conflicting goals ====&lt;br /&gt;
When deprecating APIs there is an inherent conflict in terms of how to make UMC authors aware of the deprecation. After all, if they aren't aware something is deprecated, they can't know they may need to update their add-on. Therefore, deprecations need to be displayed in a place where they will see them and most UMC authors don't look at Wesnoth's logs unless there's some other issue they're investigating. At the same time, deprecation warnings aren't relevant to players and spamming deprecation warnings is not an effective way of communicating what the issues are.&lt;br /&gt;
&lt;br /&gt;
==== A middle ground ====&lt;br /&gt;
Each deprecated feature should make use of an appropriate deprecation function call for that language or subsystem to ensure that the appropriate deprecation notice is printed to the log output. Additionally, deprecation warnings should be displayed in-game in the following cases:&lt;br /&gt;
* If the player is running a development version, level 3 and level 4 deprecations should be shown in-game by default.&lt;br /&gt;
* If the player enables debug mode then all deprecation warnings should be shown, regardless of whether they're using a stable release or a development release.&lt;br /&gt;
&lt;br /&gt;
==== Documentation ====&lt;br /&gt;
It is also not enough to only display a warning at runtime when something deprecated is encountered. It is the responsibility of the development team to proactively make UMC authors aware of the deprecations and removals being done. To accomplish this:&lt;br /&gt;
* When an API is deprecated, and again if it's later removed, its deprecation or removal must be documented in the appropriate section of the changelog for the version it was deprecated or removed in.&lt;br /&gt;
* Likewise, it should be added to https://wiki.wesnoth.org/CompatibilityBreakingChanges&lt;br /&gt;
&lt;br /&gt;
Additionally, it is not enough to simply say that an API is deprecated. In the deprecation message itself as well as in the changelog and https://wiki.wesnoth.org/CompatibilityBreakingChanges, a description must be included as to why it was deprecated or removed and how UMC authors can update their add-ons to address it.&lt;br /&gt;
&lt;br /&gt;
Lastly, it should be understood that &amp;quot;removed&amp;quot; doesn't necessarily mean that the API is entirely gone from Wesnoth's codebase. There is no maintenance burden to keeping macro or method stubs that do nothing aside from printing an error message describing what was removed and why. Keeping such stubs around is highly encouraged as it is helpful for UMC authors trying to update very old add-ons to the current version of Wesnoth.&lt;br /&gt;
&lt;br /&gt;
=== How to deprecate ===&lt;br /&gt;
Every effort should be made to create the simplest possible wrappers which will translate from an obsolete API to the updated one. Such wrappers should ideally be organized into their own compatibility file or module, and set up in such a way that the internals of the updated API will not affect how the old calls get wrapped to the new one. Essentially, the idea is to create a set-it-and-forget-it compatibility wrapper which will continue to work regardless of updates made to the newer API.&lt;br /&gt;
&lt;br /&gt;
Additionally, in all cases where it's practical, the wmllint tool must be updated to be able to automatically handle updating add-ons for anything that's been deprecated except for APIs deprecated at level 1. While developers are still heavily encouraged to add wmllint support for level 1 deprecations, it is not required as these do not show deprecation warnings by default and are expected to continue working indefinitely.&lt;br /&gt;
&lt;br /&gt;
=== Deprecation levels - When to remove deprecated features ===&lt;br /&gt;
While creating simple compatibility wrappers should be possible most of the time, it would be unreasonable to assume that this approach will be viable in absolutely every case. Wesnoth's compatibility policy therefore has four different levels of deprecation which are used to set expectations for when and if an API is expected to be removed:&lt;br /&gt;
&lt;br /&gt;
#Deprecated indefinitely &amp;amp;mdash; This deprecation level is for changes which have newer preferred alternatives but, barring any unforeseen issues, have little to no maintenance impact and should be kept indefinitely in order to reduce the work required for UMC authors to maintain their content. For example, functions or attributes which have had their names changed, macros which have been replaced with tags, or simple wrappers with little to no maintenance overhead. If future large scale changes make it impractical to maintain an API deprecated at this level then the deprecation level should be raised accordingly. This is generally the preferred deprecation level - higher deprecation levels are for APIs which are intended for eventual removal and must be weighed against the maintenance work this forces upon UMC authors.&lt;br /&gt;
#Deprecated with the intention of future removal &amp;amp;mdash; This deprecation level is for APIs which will be removed in a future version, but the version they are removed in has not yet have been decided. Barring urgent circumstances, all APIs that are deprecated with the intention of being removed '''must''' start with being deprecated at level 2 for 1-2 development cycles at minimum depending on the impact of the API's removal on UMC authors. Once the API has spent the necessary amount of time at deprecation level 2, it can be moved to deprecation level 3. It is not allowed to deprecate an API at level 2 and change it to level 3 in the same development cycle. There is no maximum amount of time that an API can remain deprecated at level 2.&lt;br /&gt;
#Deprecated for removal in a specific version &amp;amp;mdash; This deprecation level is for APIs which were previously deprecated at level 2 and now have a future version at which they will be removed. The version an API is removed in must be at least two development cycles after the API was deprecated at level 2. It is not allowed to move an API to deprecation level 3 and then remove it in the same development cycle.&lt;br /&gt;
#Removed without deprecation &amp;amp;mdash; This level should be used EXTREMELY rarely, and only in cases where it is ABSOLUTELY NECESSARY. Occasionally, an update to a feature will change the underlying architecture in such a fundamental way that the old paradigm cannot coexist with the new one no matter how much redundant code one would create. While this kind of scenario is extremely rare, and every effort should be made to find creative solutions to avoid it, there are occasionally cases where it truly is impossible to maintain both methods even in the short term. This level should only be used with broad developer consensus, after the majority of active developers familiar with the feature in question have given at least some thought to trying to deprecate gracefully and failed.&lt;br /&gt;
&lt;br /&gt;
This level should also be used for macro and method stubs containing only an error message describing what was removed and why.&lt;br /&gt;
&lt;br /&gt;
== Rationale ==&lt;br /&gt;
The above policy is the result of a large amount of thought, discussion, and debate. Following is a brief outline of the considerations and goals on both sides of the problem, why there is an inherent conflict between them, some failed approaches to resolving the conflict, and how the final policy ultimately maximizes the pursuit of both goals.&lt;br /&gt;
&lt;br /&gt;
=== The Problem - The paradox of progress ===&lt;br /&gt;
Invariably, as development on any project moves forward, developers will realize that there are better, cleaner, or more elegant ways to structure things than they had been previously. These changes can be to improve efficiency, make an API more intuitive, keep code better organized, make common tasks more straightforward, or accomplish any number of other positive things. These changes can also make the development of additional features much more viable. In short, progress is good.&lt;br /&gt;
&lt;br /&gt;
On the other hand, a content-heavy program such as Wesnoth relies on the ability of content creators to efficiently create, maintain, and update their content. Too many changes all at once will force creators of existing content to spend obscene amounts time updating their creations just to keeping them up-to-date and in working order. This can lead to a high amount of frustration, a drop in motivation, and a decline in content being created. In short, progress is bad.&lt;br /&gt;
&lt;br /&gt;
=== Backwards Compatibility - benefits and drawbacks ===&lt;br /&gt;
Most of the time, older paradigms can still be maintained in a manner in which they coexist with the newer ones. This allows for existing content to continue functioning, while at the same time allowing and encouraging new content to be created using the newer methods. However, maintaining such code can be problematic in the following ways:&lt;br /&gt;
#There may eventually be architectural changes a developer would want to make where the old method's square peg no longer fits, even forcibly, into the new method's round hole.&lt;br /&gt;
#Having compatibility code hanging around may, depending on how it is implemented, mean that any updates made to the feature, module, or subsystem in question would have to made in both the new, cleaner design, and the older, poorly structured one, adding more work for developers.&lt;br /&gt;
&lt;br /&gt;
=== The Naive Approach - Deprecate and remove everything old ===&lt;br /&gt;
One approach to balancing old and new is to deprecate the old and slate its eventual removal after either a certain amount of time has passed or a certain number of subsequent versions have been released. This sounds good in theory, but in practice, there will be many changes which are minor or cosmetic in nature and which will add up. Things like replacing macros with WML tags, updating the name of an API call or order of parameters to be more consistent with other similar functions, or switching from a functional to an object-oriented structure are very good for organizational purposes, but will result in a large amount of maintenance required on the part of content creators to keep existing code operational, and for very little real gain. This approach invariably leads to the situation where so much is being changed from one version to the next that creators turn into maintainers, forced to spend nearly all of their time trying to stay ahead of the update curve in an attempt to keep their existing content working, and leaving them very little time and motivation to create new content. And of course, by the time they're finished painstakingly updating their existing code for every little change made for the current release, whoops, there's a new release with a whole slew of new changes that need accounting for. It simply becomes unmanageable.&lt;br /&gt;
&lt;br /&gt;
=== The Naive Approach - Deprecate and remove only when necessary ===&lt;br /&gt;
The opposite approach would be to keep all existing paradigms until they actively interfere with a new architecture or create a double-maintenance problem. While this approach does cut down on the maintenance burden by ensuring that content using an older design continues to work, it hinders progress by the fact that the moment at which it first becomes clear that an architectural or double-maintenance problem will occur is exactly the same moment at which keeping the old structure around becomes problematic. Beginning a deprecation cycle at that point and then having to &amp;quot;wait out&amp;quot; the old paradigm will cause an unacceptable delay in development.&lt;br /&gt;
&lt;br /&gt;
=== The Middle Ground - Deprecate everything old, remove only when necessary ===&lt;br /&gt;
Most of the time, older APIs can be implemented in terms of their newer, cleaner counterparts through the use of things like simple wrappers, parse-translators which re-write the older paradigm's code in terms of the new one, or other relatively low-maintenance &amp;quot;set-it-and-forget-it&amp;quot; approaches. These simple wrappers are not really detrimental to making progress, don't require updating when the new APIs internals are changed, and can usually be organized into their own files and/or modules so that they don't clutter the cleaner code. Many such wrappers will never truly present either of the backwards compatibility drawbacks mentioned above. As such, there is really no detriment to keeping them around indefinitely. However, occasionally, a new idea or approach will be put forth that updates the newer paradigm in such a way that the older one can no longer cleanly wrap to it. This usually happens, as inspiration is wont to do, suddenly, unexpectedly, and without warning. As such developers need the flexibility to be able to remove outdated code as freely as possible when the situation requires. Therefore, the ideal solution would be to deprecate any API which has newer, feature-complete ways to do it, while leaving it in the codebase until such time as its presence becomes a hindrance. Essentially, deprecation need not necessarily mean &amp;quot;this WILL be removed&amp;quot; so much as &amp;quot;this is now a candidate for removal&amp;quot;. By separating the concepts of deprecation and removal, both goals can be better served.&lt;br /&gt;
&lt;br /&gt;
=== Undefined removal timeline - issues encountered ===&lt;br /&gt;
In practice however, simply stating something is a candidate for removal while providing no further information on when it will actually be removed causes multiple issues:&lt;br /&gt;
* When a deprecated API is causing a maintenance burden worthy of removal is a subjective decision, often leading to debates over removal any time a developer decides it's time for an API to be removed, initially deprecated, or moved to a higher deprecation level.&lt;br /&gt;
* Lack of developer incentive to provide good documentation and support for the deprecation of the API given there's no particular timeline for when it will actually cause issues for UMC authors.&lt;br /&gt;
* UMC authors often don't find out about deprecated APIs and so can't possibly migrate to the new APIs.&lt;br /&gt;
* UMC authors aren't provided the documentation or tooling support needed to make updating their add-ons easier.&lt;br /&gt;
* UMC authors may simply decide there's no reason to update to the new API even if they know it's deprecated and how to update their add-on. After all, why spend time updating APIs that may stick around forever?&lt;br /&gt;
* Giving a version that an API '''may''' be removed instead of a version that it '''will''' be removed is not as clear as it may seem to UMC authors who aren't already aware of how Wesnoth handles deprecation. This can lead to UMC authors ignoring deprecation warnings after seeing such warnings for APIs which provide a version that's years old.&lt;br /&gt;
&lt;br /&gt;
=== Certainty is also a benefit ===&lt;br /&gt;
Wesnoth continues to exist today in large part because of the content made by its community. As such, developers should always be sparing in what they choose to deprecate and what they choose to remove, so that UMC authors can update their content to the latest version of Wesnoth without needing to make a herculean effort every couple of years.&lt;br /&gt;
&lt;br /&gt;
But, for cases where APIs are removed, the benefit of providing certainty for when that will happen outweighs the flexibility of being able remove them at any time after they been marked as deprecated. It encourages developers to provide the documentation and tooling support to make it easier for UMC authors to update their add-ons, and it lets UMC authors know when they can expect deprecated APIs to be removed rather than it effectively happening at random when a developer decides a deprecated API needs to be dropped.&lt;br /&gt;
&lt;br /&gt;
=== More Complex Cases - One size does not fit all ===&lt;br /&gt;
There may, however, be cases where the obsolete API cannot be implemented cleanly in terms of the updated one and must be maintained separately, or, in extremely rare cases, cannot coexist at all. There needs to be some leeway for such cases as well. In the former case, it therefore makes sense to allow for a feature to be deprecated pending removal after the shortest reasonable deprecation period. In the latter case, there is obviously no choice but to make the change and remove the old immediately. Developers should, naturally, be encouraged to find creative solutions to avoid such cases, but it is inevitable that there will eventually be a few cases where no graceful transition procedure can be found. These more aggressive forms of deprecation should only be done with developer consensus, and only after all options of creating a backwards-compatible transition have been exhausted.&lt;br /&gt;
&lt;br /&gt;
=== Graphics - The exception that proves the rule ===&lt;br /&gt;
The one area where backwards compatibility should NOT be a factor is graphical changes. Any change to the terrain graphics, unit sprites, or portrait images has the potential to result in visually-incompatible custom content. Core content creators cannot be expected to maintain a deprecated visual style alongside a more modern one, as any approach toward doing so would add an unreasonable amount of bloat and overhead, and make it very difficult for core graphics to be updated without having to do double the work. In addition, add-ons will continue to function even with such visual incompatibilities present, they just won't look right. As such, it can be said that stylistic incompatibilities fall more within the realm of content than of code, and it is not unreasonable to expect a content creator to... well...  create content. Expecting the graphical style to remain backwards-compatible would be just as unreasonable as expecting stories, help descriptions, or other forms of lore to never change because they may introduce plot holes into add-on stories. Essentially, since the goal of the software portion of Wesnoth is, at its heart, merely to facilitate the creation and advancement of this kind of content, core content needs to be free to develop unhindered by considerations for add-on content.&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=CompatibilityStandardsV2&amp;diff=74986</id>
		<title>CompatibilityStandardsV2</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=CompatibilityStandardsV2&amp;diff=74986"/>
		<updated>2026-04-19T02:40:35Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: Created page with &amp;quot;As a piece of software matures, there are often new designs, paradigms, and idioms developed which are superior to old ones. This creates an inherent conflict between the need...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;As a piece of software matures, there are often new designs, paradigms, and idioms developed which are superior to old ones. This creates an inherent conflict between the need for progress and the need for compatibility. Wesnoth is no exception. This document describes Wesnoth's approach toward resolving that conflict in a way which is most beneficial to both goals, as well as the rationale behind this approach.&lt;br /&gt;
&lt;br /&gt;
== Policy ==&lt;br /&gt;
This policy defines how the creation of new Wesnoth APIs and the deprecation and removal of old ones are to be handled. For the purposes of this document &amp;quot;API&amp;quot; means &amp;quot;any technical channel by which a content creator interacts with the game engine&amp;quot;. This includes, but is not limited to: preprocessor macros, WML tags, WFL functions, IPFs, and the Lua API. Note that this policy applies only to software APIs. Core content such as sprites, portraits, animations, lore, etc. are to be updated freely, without consideration for stylistic or literary conflicts that such content changes may present to add-ons.&lt;br /&gt;
&lt;br /&gt;
=== When to deprecate ===&lt;br /&gt;
==== Adding a better API ====&lt;br /&gt;
Any time a superior API is introduced which has '''complete feature-parity''' with an existing API, the old one should be immediately deprecated. Note that in most cases, in order to be considered to have &amp;quot;complete feature-parity&amp;quot;, the API should be available in the same language or area of the code as the obsolete one was. For example, the introduction of a more powerful API in Lua which can accomplish a superset of the functionality which had previously been available with a certain WML tag would not obsolete that WML tag. Exceptions can be made to this rule in cases where it is clear that the feature does not make a lot of sense in its current language or area, and was merely there for legacy reasons (such as the proper place for it not having been introduced yet at the time of its creation). Such exceptions should be determined by developer consensus.&lt;br /&gt;
&lt;br /&gt;
==== Preventing needed fixes or improvements ====&lt;br /&gt;
In such cases where a feature is preventing an important new feature from being added or makes it impossible to fix a problem impacting players, it can be preferable to deprecate the API to allow for the necessary changes to be made. APIs deprecated for this reason should still follow the deprecation schedule as normal, unless the fix or improvement is urgently needed.&lt;br /&gt;
&lt;br /&gt;
==== Actively harmful ====&lt;br /&gt;
If an API is found to cause significant problems for players or UMC authors, such as being prone to causing crashes while also very difficult to properly fix, corrupting saves and replays when not used correctly while being difficult to use correctly, or other similar situations, then such APIs should be deprecated and removed regardless of whether there is a replacement available.&lt;br /&gt;
&lt;br /&gt;
==== Security ====&lt;br /&gt;
If an API is found to have a security flaw that can't be fixed, then it should not be deprecated, it should be immediately removed.&lt;br /&gt;
&lt;br /&gt;
==== Unused ====&lt;br /&gt;
Any API that is not used in mainline and also is not used by the most recent version of an add-on on the add-ons server of the current or previous stable release can be deprecated. For example, if an add-on for 1.16 uses a deprecated API but the updated version of the add-on for 1.18 does not, then that add-on is not considered as currently using the API. Once deprecated for this reason, a new add-on being uploaded that uses the API is not a reason to undeprecate it.&lt;br /&gt;
&lt;br /&gt;
This does not need to be a passive process where developers simply check the add-ons server for whether an API is used - developers who want to deprecate an API for removal can proactively talk to and work with UMC authors to help update their add-ons to remove usage of said API. This can be anything from talking with them online about how to update to submitting updated code directly (ie: opening a PR against an add-on's public git repository).&lt;br /&gt;
&lt;br /&gt;
Deprecating and then removing APIs that are unused is the most preferred approach since their removal does not have any impact on UMC authors.&lt;br /&gt;
&lt;br /&gt;
=== When NOT to deprecate ===&lt;br /&gt;
==== Style ====&lt;br /&gt;
Deprecation should not be done purely for reasons of style. This is very subjective and prone to change as new contributors join and current contributors leave or become less active. As such, allowing deprecation for stylistic reasons would lead to entirely unnecessary work for UMC authors as developer preferences change over time.&lt;br /&gt;
&lt;br /&gt;
==== Renaming ====&lt;br /&gt;
While there can be exceptions, it is rarely a net positive to deprecate an API simply for the sake of renaming it to something else. It is preferable to either add a second name for the same function, leaving the old name as-is, or simply live with the current name rather than expecting all UMC authors using the API to update to the new name.&lt;br /&gt;
&lt;br /&gt;
==== Any other reason ====&lt;br /&gt;
Accepted reasons for deprecating APIs should be something that's discussed and agreed upon by the development team while also, ideally, including UMC authors. It should not become the norm that additional reasons to deprecate APIs are treated as exceptions and left as an increasingly forgotten discussion on Discord, IRC, or the forums - they should be added to here with the reasoning behind them.&lt;br /&gt;
&lt;br /&gt;
=== Deprecation awareness ===&lt;br /&gt;
==== Conflicting goals ====&lt;br /&gt;
When deprecating APIs there is an inherent conflict in terms of how to make UMC authors aware of the deprecation. After all, if they aren't aware something is deprecated, they can't know they may need to update their add-on. Therefore, deprecations need to be displayed in a place where they will see them and most UMC authors don't look at Wesnoth's logs unless there's some other issue they're investigating. At the same time, deprecation warnings aren't relevant to players and spamming deprecation warnings is not an effective way of communicating what the issues are.&lt;br /&gt;
&lt;br /&gt;
==== A middle ground ====&lt;br /&gt;
Each deprecated feature should make use of an appropriate deprecation function call for that language or subsystem to ensure that the appropriate deprecation notice is printed to the log output. Additionally, deprecation warnings should be displayed in-game in the following cases:&lt;br /&gt;
* If the player is running a development version, level 3 and level 4 deprecations should be shown in-game by default.&lt;br /&gt;
* If the player enables debug mode then all deprecation warnings should be shown, regardless of whether they're using a stable release or a development release.&lt;br /&gt;
&lt;br /&gt;
==== Documentation ====&lt;br /&gt;
It is also not enough to only display a warning at runtime when something deprecated is encountered. It is the responsibility of the development team to proactively make UMC authors aware of the deprecations and removals being done. To accomplish this:&lt;br /&gt;
* When an API is deprecated, and again if it's later removed, its deprecation or removal must be documented in the appropriate section of the changelog for the version it was deprecated or removed in.&lt;br /&gt;
* Likewise, it should be added to https://wiki.wesnoth.org/CompatibilityBreakingChanges&lt;br /&gt;
&lt;br /&gt;
Additionally, it is not enough to simply say that an API is deprecated. In the deprecation message itself as well as in the changelog and https://wiki.wesnoth.org/CompatibilityBreakingChanges, a description must be included as to why it was deprecated or removed and how UMC authors can update their add-ons to address it.&lt;br /&gt;
&lt;br /&gt;
Lastly, it should be understood that &amp;quot;removed&amp;quot; doesn't necessarily mean that the API is entirely gone from Wesnoth's codebase. There is no maintenance burden to keeping macro or method stubs that do nothing aside from printing an error message describing what was removed and why. Keeping such stubs around is highly encouraged as it is helpful for UMC authors trying to update very old add-ons to the current version of Wesnoth.&lt;br /&gt;
&lt;br /&gt;
=== How to deprecate ===&lt;br /&gt;
Every effort should be made to create the simplest possible wrappers which will translate from an obsolete API to the updated one. Such wrappers should ideally be organized into their own compatibility file or module, and set up in such a way that the internals of the updated API will not affect how the old calls get wrapped to the new one. Essentially, the idea is to create a set-it-and-forget-it compatibility wrapper which will continue to work regardless of updates made to the newer API.&lt;br /&gt;
&lt;br /&gt;
Additionally, in all cases where it's practical, the wmllint tool must be updated to be able to automatically handle updating add-ons for anything that's been deprecated except for APIs deprecated at level 1. While developers are still heavily encouraged to add wmllint support for level 1 deprecations, it is not required as these do not show deprecation warnings by default and are expected to continue working indefinitely.&lt;br /&gt;
&lt;br /&gt;
=== Deprecation levels - When to remove deprecated features ===&lt;br /&gt;
While creating simple compatibility wrappers should be possible most of the time, it would be unreasonable to assume that this approach will be viable in absolutely every case. Wesnoth's compatibility policy therefore has four different levels of deprecation which are used to set expectations for when and if an API is expected to be removed:&lt;br /&gt;
&lt;br /&gt;
#Deprecated indefinitely &amp;amp;mdash; This deprecation level is for changes which have newer preferred alternatives but, barring any unforeseen issues, have little to no maintenance impact and should be kept indefinitely in order to reduce the work required for UMC authors to maintain their content. For example, functions or attributes which have had their names changed, macros which have been replaced with tags, macro stubs containing only an error message describing what was removed and why, or simple wrappers with little to no maintenance overhead. If future large scale changes make it impractical to maintain an API deprecated at this level then the deprecation level should be raised accordingly. This is generally the preferred deprecation level - higher deprecation levels are for APIs which are intended for eventual removal and must be weighed against the maintenance work this forces upon UMC authors.&lt;br /&gt;
#Deprecated with the intention of future removal &amp;amp;mdash; This deprecation level is for APIs which will be removed in a future version, but the version they are removed in has not yet have been decided. Barring urgent circumstances, all APIs that are deprecated with the intention of being removed '''must''' start with being deprecated at level 2 for 1-2 development cycles at minimum depending on the impact of the API's removal on UMC authors. Once the API has spent the necessary amount of time at deprecation level 2, it can be moved to deprecation level 3. It is not allowed to deprecate an API at level 2 and change it to level 3 in the same development cycle. There is no maximum amount of time that an API can remain deprecated at level 2.&lt;br /&gt;
#Deprecated for removal in a specific version &amp;amp;mdash; This deprecation level is for APIs which were previously deprecated at level 2 and now have a future version at which they will be removed. The version an API is removed in must be at least two development cycles after the API was deprecated at level 2. It is not allowed to move an API to deprecation level 3 and then remove it in the same development cycle.&lt;br /&gt;
#Removed without deprecation &amp;amp;mdash; This level should be used EXTREMELY rarely, and only in cases where it is ABSOLUTELY NECESSARY. Occasionally, an update to a feature will change the underlying architecture in such a fundamental way that the old paradigm cannot coexist with the new one no matter how much redundant code one would create. While this kind of scenario is extremely rare, and every effort should be made to find creative solutions to avoid it, there are occasionally cases where it truly is impossible to maintain both methods even in the short term. This level should only be used with broad developer consensus, after the majority of active developers familiar with the feature in question have given at least some thought to trying to deprecate gracefully and failed.&lt;br /&gt;
&lt;br /&gt;
== Rationale ==&lt;br /&gt;
The above policy is the result of a large amount of thought, discussion, and debate. Following is a brief outline of the considerations and goals on both sides of the problem, why there is an inherent conflict between them, some failed approaches to resolving the conflict, and how the final policy ultimately maximizes the pursuit of both goals.&lt;br /&gt;
&lt;br /&gt;
=== The Problem - The paradox of progress ===&lt;br /&gt;
Invariably, as development on any project moves forward, developers will realize that there are better, cleaner, or more elegant ways to structure things than they had been previously. These changes can be to improve efficiency, make an API more intuitive, keep code better organized, make common tasks more straightforward, or accomplish any number of other positive things. These changes can also make the development of additional features much more viable. In short, progress is good.&lt;br /&gt;
&lt;br /&gt;
On the other hand, a content-heavy program such as Wesnoth relies on the ability of content creators to efficiently create, maintain, and update their content. Too many changes all at once will force creators of existing content to spend obscene amounts time updating their creations just to keeping them up-to-date and in working order. This can lead to a high amount of frustration, a drop in motivation, and a decline in content being created. In short, progress is bad.&lt;br /&gt;
&lt;br /&gt;
=== Backwards Compatibility - benefits and drawbacks ===&lt;br /&gt;
Most of the time, older paradigms can still be maintained in a manner in which they coexist with the newer ones. This allows for existing content to continue functioning, while at the same time allowing and encouraging new content to be created using the newer methods. However, maintaining such code can be problematic in the following ways:&lt;br /&gt;
#There may eventually be architectural changes a developer would want to make where the old method's square peg no longer fits, even forcibly, into the new method's round hole.&lt;br /&gt;
#Having compatibility code hanging around may, depending on how it is implemented, mean that any updates made to the feature, module, or subsystem in question would have to made in both the new, cleaner design, and the older, poorly structured one, adding more work for developers.&lt;br /&gt;
&lt;br /&gt;
=== The Naive Approach - Deprecate and remove everything old ===&lt;br /&gt;
One approach to balancing old and new is to deprecate the old and slate its eventual removal after either a certain amount of time has passed or a certain number of subsequent versions have been released. This sounds good in theory, but in practice, there will be many changes which are minor or cosmetic in nature and which will add up. Things like replacing macros with WML tags, updating the name of an API call or order of parameters to be more consistent with other similar functions, or switching from a functional to an object-oriented structure are very good for organizational purposes, but will result in a large amount of maintenance required on the part of content creators to keep existing code operational, and for very little real gain. This approach invariably leads to the situation where so much is being changed from one version to the next that creators turn into maintainers, forced to spend nearly all of their time trying to stay ahead of the update curve in an attempt to keep their existing content working, and leaving them very little time and motivation to create new content. And of course, by the time they're finished painstakingly updating their existing code for every little change made for the current release, whoops, there's a new release with a whole slew of new changes that need accounting for. It simply becomes unmanageable.&lt;br /&gt;
&lt;br /&gt;
=== The Naive Approach - Deprecate and remove only when necessary ===&lt;br /&gt;
The opposite approach would be to keep all existing paradigms until they actively interfere with a new architecture or create a double-maintenance problem. While this approach does cut down on the maintenance burden by ensuring that content using an older design continues to work, it hinders progress by the fact that the moment at which it first becomes clear that an architectural or double-maintenance problem will occur is exactly the same moment at which keeping the old structure around becomes problematic. Beginning a deprecation cycle at that point and then having to &amp;quot;wait out&amp;quot; the old paradigm will cause an unacceptable delay in development.&lt;br /&gt;
&lt;br /&gt;
=== The Middle Ground - Deprecate everything old, remove only when necessary ===&lt;br /&gt;
Most of the time, older APIs can be implemented in terms of their newer, cleaner counterparts through the use of things like simple wrappers, parse-translators which re-write the older paradigm's code in terms of the new one, or other relatively low-maintenance &amp;quot;set-it-and-forget-it&amp;quot; approaches. These simple wrappers are not really detrimental to making progress, don't require updating when the new APIs internals are changed, and can usually be organized into their own files and/or modules so that they don't clutter the cleaner code. Many such wrappers will never truly present either of the backwards compatibility drawbacks mentioned above. As such, there is really no detriment to keeping them around indefinitely. However, occasionally, a new idea or approach will be put forth that updates the newer paradigm in such a way that the older one can no longer cleanly wrap to it. This usually happens, as inspiration is wont to do, suddenly, unexpectedly, and without warning. As such developers need the flexibility to be able to remove outdated code as freely as possible when the situation requires. Therefore, the ideal solution would be to deprecate any API which has newer, feature-complete ways to do it, while leaving it in the codebase until such time as its presence becomes a hindrance. Essentially, deprecation need not necessarily mean &amp;quot;this WILL be removed&amp;quot; so much as &amp;quot;this is now a candidate for removal&amp;quot;. By separating the concepts of deprecation and removal, both goals can be better served.&lt;br /&gt;
&lt;br /&gt;
=== Undefined removal timeline - issues encountered ===&lt;br /&gt;
In practice however, simply stating something is a candidate for removal while providing no further information on when it will actually be removed causes multiple issues:&lt;br /&gt;
* When a deprecated API is causing a maintenance burden worthy of removal is a subjective decision, often leading to debates over removal any time a developer decides it's time for an API to be removed, initially deprecated, or moved to a higher deprecation level.&lt;br /&gt;
* Lack of developer incentive to provide good documentation and support for the deprecation of the API given there's no particular timeline for when it will actually cause issues for UMC authors.&lt;br /&gt;
* UMC authors often don't find out about deprecated APIs and so can't possibly migrate to the new APIs.&lt;br /&gt;
* UMC authors aren't provided the documentation or tooling support needed to make updating their add-ons easier.&lt;br /&gt;
* UMC authors may simply decide there's no reason to update to the new API even if they know it's deprecated and how to update their add-on. After all, why spend time updating APIs that may stick around forever?&lt;br /&gt;
* Giving a version that an API '''may''' be removed instead of a version that it '''will''' be removed is not as clear as it may seem to UMC authors who aren't already aware of how Wesnoth handles deprecation. This can lead to UMC authors ignoring deprecation warnings after seeing such warnings for APIs which provide a version that's years old.&lt;br /&gt;
&lt;br /&gt;
=== Certainty is also a benefit ===&lt;br /&gt;
Wesnoth continues to exist today in large part because of the content made by its community. As such, developers should always be sparing in what they choose to deprecate and what they choose to remove, so that UMC authors can update their content to the latest version of Wesnoth without needing to make a herculean effort every couple of years.&lt;br /&gt;
&lt;br /&gt;
But, for cases where APIs are removed, the benefit of providing certainty for when that will happen outweighs the flexibility of being able remove them at any time after they been marked as deprecated. It encourages developers to provide the documentation and tooling support to make it easier for UMC authors to update their add-ons, and it lets UMC authors know when they can expect deprecated APIs to be removed rather than it effectively happening at random when a developer decides a deprecated API needs to be dropped.&lt;br /&gt;
&lt;br /&gt;
=== More Complex Cases - One size does not fit all ===&lt;br /&gt;
There may, however, be cases where the obsolete API cannot be implemented cleanly in terms of the updated one and must be maintained separately, or, in extremely rare cases, cannot coexist at all. There needs to be some leeway for such cases as well. In the former case, it therefore makes sense to allow for a feature to be deprecated pending removal after the shortest reasonable deprecation period. In the latter case, there is obviously no choice but to make the change and remove the old immediately. Developers should, naturally, be encouraged to find creative solutions to avoid such cases, but it is inevitable that there will eventually be a few cases where no graceful transition procedure can be found. These more aggressive forms of deprecation should only be done with developer consensus, and only after all options of creating a backwards-compatible transition have been exhausted.&lt;br /&gt;
&lt;br /&gt;
=== Graphics - The exception that proves the rule ===&lt;br /&gt;
The one area where backwards compatibility should NOT be a factor is graphical changes. Any change to the terrain graphics, unit sprites, or portrait images has the potential to result in visually-incompatible custom content. Core content creators cannot be expected to maintain a deprecated visual style alongside a more modern one, as any approach toward doing so would add an unreasonable amount of bloat and overhead, and make it very difficult for core graphics to be updated without having to do double the work. In addition, add-ons will continue to function even with such visual incompatibilities present, they just won't look right. As such, it can be said that stylistic incompatibilities fall more within the realm of content than of code, and it is not unreasonable to expect a content creator to... well...  create content. Expecting the graphical style to remain backwards-compatible would be just as unreasonable as expecting stories, help descriptions, or other forms of lore to never change because they may introduce plot holes into add-on stories. Essentially, since the goal of the software portion of Wesnoth is, at its heart, merely to facilitate the creation and advancement of this kind of content, core content needs to be free to develop unhindered by considerations for add-on content.&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=CompatibilityBreakingChanges&amp;diff=74974</id>
		<title>CompatibilityBreakingChanges</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=CompatibilityBreakingChanges&amp;diff=74974"/>
		<updated>2026-04-14T02:07:13Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: Pentarctagon moved page User:Bssarkar/CompatibilityBreakingChanges to CompatibilityBreakingChanges&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This lists removed WML functionality and helpful hints for avoiding pitfalls.&lt;br /&gt;
&lt;br /&gt;
The previous list is available [https://forums.wesnoth.org/viewtopic.php?t=58532 here].&lt;br /&gt;
&lt;br /&gt;
== Compatibility breaking changes between 1.18 and 1.19/1.20 ==&lt;br /&gt;
&lt;br /&gt;
=== Compatibility breaking (requires updates to work) ===&lt;br /&gt;
&lt;br /&gt;
* '''[kill]''' now reduces target unit hitpoints to 0 before triggering '''last_breath, die''' events. This affects mentioned events that rely on [have_unit] conditions.&lt;br /&gt;
* WFL Removed properties '''unit.side''' and '''terrain.owner'''. Use '''unit.side_number''' and '''terrain.owner_side''' instead. They return 1-indexed side, removed properties returned 0-indexed side.&lt;br /&gt;
* Abilities with both '''add''' and '''sub''' now calculate value differently&lt;br /&gt;
* rotate_loc_around formula now works&lt;br /&gt;
* [era] with id=era_dunefolk does not exist anymore&lt;br /&gt;
* [side]'s leader attribute has been removed&lt;br /&gt;
* [side]'s [variables] tag is now used to set side variables. Use [side]'s [leader] tag to set a unit variable.&lt;br /&gt;
* Setting gold to decimal value fails with error. Previously it was converted to int automatically. As of 1.19.21, automatic conversion is only done in [gold], but not in Lua or [modify_side].&lt;br /&gt;
* The following macros were removed ([https://github.com/wesnoth/wesnoth/pull/11126 #11126])&lt;br /&gt;
** EARLY_FINISH_BONUS_NOTE&lt;br /&gt;
** NO_EARLY_FINISH_BONUS_NOTE&lt;br /&gt;
** NO_GOLD_CARRYOVER_NOTE&lt;br /&gt;
** NEW_GOLD_CARRYOVER_NOTE_100&lt;br /&gt;
** NEW_GOLD_CARRYOVER_NOTE_40&lt;br /&gt;
** NEW_GOLD_CARRYOVER_NOTE_20&lt;br /&gt;
** MISSILE_FRAME_FIREBALL&lt;br /&gt;
** MESSAGE&lt;br /&gt;
** STORY_PART_SPEECH&lt;br /&gt;
** LOYAL_UNDEAD_UNIT&lt;br /&gt;
** ON_SIGHTING&lt;br /&gt;
** MAKE_AI_SIDE_PERSISTENT&lt;br /&gt;
** DRAKE_FLYING_ANIM&lt;br /&gt;
** NO_INTERRUPT_NO_UNDO&lt;br /&gt;
** ENABLE_NIGHTBLADE&lt;br /&gt;
&lt;br /&gt;
=== Deprecations (will continue to work for now) ===&lt;br /&gt;
* rechange [experimental_filter_ability/active] and [experimental_filter_specials] to [filter_ability] and [filter_specials] and make &amp;quot;experimental_&amp;quot; deprecated.&lt;br /&gt;
&lt;br /&gt;
=== New features (help fill this list, https://wiki.wesnoth.org/Special:WhatLinksHere/Template:DevFeature1.19) ===&lt;br /&gt;
* StandardAbilityFilter, including [https://github.com/wesnoth/wesnoth/pull/7814 7814]&lt;br /&gt;
* [resistance] min_value&lt;br /&gt;
* [attack] alignment&lt;br /&gt;
* New events '''unit_hits''', '''unit_misses'''&lt;br /&gt;
* Positive '''attack_weight''' now affects weapon selection&lt;br /&gt;
* Unit attack [effect]+Lua+formula API min_range and max_range&lt;br /&gt;
* Lua unit attributes fearless and healthy&lt;br /&gt;
* wesnoth.game_config shows some color-related values&lt;br /&gt;
* wesnoth.units.rebuild&lt;br /&gt;
* stringx.ends_with, stringx.starts_with&lt;br /&gt;
* Unit formula new attributes objects, advancements_taken, traits_count, objects_count, advancements_taken_count, fearless, healthy&lt;br /&gt;
* Formula functions lerp_index, ends_with, replace_all, starts_with, get_palette&lt;br /&gt;
* Custom themes https://wiki.wesnoth.org/GUIToolkit#Custom_themes&lt;br /&gt;
* Abilities and specials now support [event] (does not work correctly due to [issue]10819[/issue])&lt;br /&gt;
* Ability &amp;amp; Weapon specials registry ([https://github.com/wesnoth/wesnoth/pull/10644 10644]) (does not work correctly if ability contains [event] due to [issue]10819[/issue])&lt;br /&gt;
* [effect][remove_specials]&lt;br /&gt;
* Expose unit pick dialog to Lua as a simple API call ([https://github.com/wesnoth/wesnoth/pull/8829 8829])&lt;br /&gt;
* [fire_event][data] can be accessed from other event as $data&lt;br /&gt;
* Unit Type Editor&lt;br /&gt;
* [era]auto_sort allows to use custom faction ordering&lt;br /&gt;
* [terrain_defaults] formula is now working as expected in case formula evaluates to null&lt;br /&gt;
* [set_menu_item] description substitutes variables when rightclick is used&lt;br /&gt;
* [defense]&lt;br /&gt;
* [resistance_defaults] is not causing OOS in random maps anymore&lt;br /&gt;
* Ability/weapon special descriptions support po variables in descriptions like '''$add''', '''$sub''' etc that contain the value of the relevant key. ([https://github.com/wesnoth/wesnoth/pull/10053 10053], [https://github.com/wesnoth/wesnoth/pull/10293 10293], [https://github.com/wesnoth/wesnoth/pull/10749 10749])&lt;br /&gt;
* Ability/weapon special help page ids now follow the format: '''ability_&amp;lt;unique_id&amp;gt;''' or '''weaponspecial_&amp;lt;unique_id&amp;gt;''' ([https://github.com/wesnoth/wesnoth/pull/11012 11012]).&lt;br /&gt;
* A lot more functions were added to https://wiki.wesnoth.org/LuaAPI/types/widget with https://wiki.wesnoth.org/index.php?title=LuaAPI%2Ftypes%2Fwidget&amp;amp;type=revision&amp;amp;diff=74843&amp;amp;oldid=74842&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=User:Bssarkar/CompatibilityBreakingChanges&amp;diff=74975</id>
		<title>User:Bssarkar/CompatibilityBreakingChanges</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=User:Bssarkar/CompatibilityBreakingChanges&amp;diff=74975"/>
		<updated>2026-04-14T02:07:13Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: Pentarctagon moved page User:Bssarkar/CompatibilityBreakingChanges to CompatibilityBreakingChanges&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[CompatibilityBreakingChanges]]&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=PreprocessorRef&amp;diff=74973</id>
		<title>PreprocessorRef</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=PreprocessorRef&amp;diff=74973"/>
		<updated>2026-04-13T15:42:13Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: /* #deprecated */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{WML Tags}}&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
Wesnoth loads just one configuration file directly: '''data/_main.cfg'''. However, the '''WML preprocessor''' allows the inclusion of more files. Whenever a WML file is read by Wesnoth, it is passed through the preprocessor.&lt;br /&gt;
&lt;br /&gt;
The preprocessor can interpret a simple language of string expansions known as ''macros''. A macro should always be defined '''before''' the place where it needs to be used.&lt;br /&gt;
&lt;br /&gt;
The preprocessor is applied recursively, so included files will be parsed for macros, and after macro expansion will be parsed for macros again, and so on. As a result, you should not write a recursive macro that references itself, because it will cause errors (but, alas, not necessarily error messages).&lt;br /&gt;
&lt;br /&gt;
== Preprocessor directives ==&lt;br /&gt;
&lt;br /&gt;
The following directives are used to create and use ''macros'', i.e. shortcuts which reduce repetition of information. See [https://www.wesnoth.org/macro-reference.html the macro reference] for the list of predefined core macros.&lt;br /&gt;
&lt;br /&gt;
Macros have scoping rules such that addons have separate preprocessing contexts, meaning that they can be overridden however an author of UMC wishes to override them, without worrying about breaking other add-ons.&lt;br /&gt;
&lt;br /&gt;
The preprocessor has changed several times, so don't expect old Wesnoth versions to behave exactly the same as the current stable and development series.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' In multiplayer scenarios, these directives will appear to work only for the host and not for other clients. This is because the preprocessor is run only on the host, and the clients receive the resultant WML from the server. It's particularly important to keep this in mind before using preprocessor conditionals.&lt;br /&gt;
&lt;br /&gt;
=== #define ===&lt;br /&gt;
&lt;br /&gt;
'''Syntax: #define ''symbol'' [''parameters''] ''&amp;lt;newline&amp;gt;'' ''substitution'' #enddef'''&lt;br /&gt;
&lt;br /&gt;
All subsequent occurences of '''{''symbol'' [''arguments'']}''' (see below) will be replaced by the contents of the ''substitution'' block, with all occurrences of any parameter {''parameter''} within ''substitution'' replaced by the corresponding value in ''arguments''. &amp;lt;code&amp;gt;#define-#enddef&amp;lt;/code&amp;gt; blocks cannot be nested inside another &amp;lt;code&amp;gt;#define&amp;lt;/code&amp;gt;, as of Wesnoth 1.19.&lt;br /&gt;
&lt;br /&gt;
As an example, the ENEMY_UNIT macro for the [[#Macro inclusions|macro inclusion]] example below could be defined as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;wml&amp;quot;&amp;gt;&lt;br /&gt;
#define ENEMY_UNIT TYPE X Y&lt;br /&gt;
## the ordering above is important, since the preprocessor does not distinguish&lt;br /&gt;
## data into different types; only the ordering is used to determine which&lt;br /&gt;
## arguments apply to which parameters.&lt;br /&gt;
[unit]&lt;br /&gt;
    type={TYPE} ## the unit will be of type TYPE, so different&lt;br /&gt;
                ## instantiations&lt;br /&gt;
                ## of this macro can create different units.&lt;br /&gt;
    x={X}&lt;br /&gt;
    y={Y}&lt;br /&gt;
    side=2 ## the unit will be an enemy, regardless of the parameter&lt;br /&gt;
           ## values. This reduces &amp;quot;repetition of information&amp;quot;,&lt;br /&gt;
           ## since it is no longer necessary to specify&lt;br /&gt;
           ## each created unit as an enemy.&lt;br /&gt;
[/unit]&lt;br /&gt;
#enddef&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(See [[SingleUnitWML]] for further information on creating units using WML.)&lt;br /&gt;
&lt;br /&gt;
'''Important note:''' Although macros may look like they're simplifying the code, they do not help with wml bloating. Macros are very good at ''disguising'' WML bloat, but they do nothing to ''alleviate'' it. So instead of using macros to generate redundant and repetitive instructions, you should be considering how to eliminate redundancy through programming techniques of abstraction. The most popular way to improve your code is using custom [[EventWML|events]] and [[InternalActionsWML#.5Bfire_event.5D|fire_event]] tags. See also: [[Wml_optimisation|WML Optimisation]].&lt;br /&gt;
&lt;br /&gt;
==== Whitespace in Macros ====&lt;br /&gt;
&lt;br /&gt;
When expanding a macro, '''''all''''' whitespace in the definition of the macro is preserved. The &amp;lt;tt&amp;gt;#arg&amp;lt;/tt&amp;gt; declarations for optional arguments are removed including the final newline. The body of the optional argument (the default value) is similarly processed just as if it were a macro, so all whitespace is preserved.&lt;br /&gt;
&lt;br /&gt;
There are two main practical implications of these rules:&lt;br /&gt;
&lt;br /&gt;
* When using a macro to define simple constants to be used inline in the middle of an attribute value, the entire content and the &amp;lt;tt&amp;gt;#enddef&amp;lt;/tt&amp;gt; must be on one line, like so:&lt;br /&gt;
: &amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
#define MY_CONSTANT&lt;br /&gt;
42#enddef&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* If using a macro inside a quoted string, you should not indent the contents of the macro, as the indentation will be preserved upon macro substitution.&lt;br /&gt;
* Similarly if you use an optional argument in the middle of an attribute value, the entire content and the &amp;lt;tt&amp;gt;#endarg&amp;lt;/tt&amp;gt; must be on one line, like so:&lt;br /&gt;
: &amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
#define MY_MACRO&lt;br /&gt;
#arg OPTIONAL_ARG&lt;br /&gt;
default#endarg&lt;br /&gt;
  key = &amp;quot;composite {OPTIONAL_ARG} value&amp;quot;&lt;br /&gt;
#enddef&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== #arg ===&lt;br /&gt;
&lt;br /&gt;
{{DevFeature1.13|7}} &lt;br /&gt;
&lt;br /&gt;
'''Syntax: #arg ''symbol'' ''&amp;lt;newline&amp;gt;'' ''default value'' #endarg'''&lt;br /&gt;
&lt;br /&gt;
Defines an optional argument for a macro along with its default value. Optional arguments can be used to make a macro more flexible and to allow its user to specify certain parameters only when necessary.&lt;br /&gt;
&lt;br /&gt;
For example, one could define a shortcut macro for [message] with only one required argument (the text displayed), but several optional ones:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;wml&amp;quot;&amp;gt;&lt;br /&gt;
#define MESSAGE TEXT&lt;br /&gt;
&lt;br /&gt;
#arg SPEAKER_ID&lt;br /&gt;
narrator#endarg&lt;br /&gt;
&lt;br /&gt;
#arg CAPTION&lt;br /&gt;
#endarg&lt;br /&gt;
&lt;br /&gt;
#arg SOUND&lt;br /&gt;
#endarg&lt;br /&gt;
&lt;br /&gt;
#arg IMG&lt;br /&gt;
#endarg&lt;br /&gt;
&lt;br /&gt;
[message]&lt;br /&gt;
    speaker={SPEAKER_ID}&lt;br /&gt;
    message={TEXT}&lt;br /&gt;
    caption={CAPTION}&lt;br /&gt;
    sound={SOUND}&lt;br /&gt;
    image={IMG}&lt;br /&gt;
[/message]&lt;br /&gt;
#enddef&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The caller of the macro can then decide which, if any, of the default values to override:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;wml&amp;quot;&amp;gt;&lt;br /&gt;
{MESSAGE _&amp;quot;Halt!&amp;quot; SPEAKER_ID=&amp;quot;Guard Captain&amp;quot;}&lt;br /&gt;
{MESSAGE _&amp;quot;Two days pass...&amp;quot; IMG=wesnoth-icon.png SOUND=ambient/morning.ogg}&lt;br /&gt;
{MESSAGE _&amp;quot;...&amp;quot;}&lt;br /&gt;
{MESSAGE _&amp;quot;Welcome!&amp;quot; CAPTION=_&amp;quot;Elóndra's shop of wonders&amp;quot; IMG=portraits/elves/shyde.png}&lt;br /&gt;
{MESSAGE _&amp;quot;*smash*&amp;quot; SPEAKER_ID=&amp;quot;Bridge Troll&amp;quot; SOUND=mace.ogg}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a multiline optional argument defined and called as follows:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;wml&amp;quot;&amp;gt;&lt;br /&gt;
#define MY_MACRO&lt;br /&gt;
#arg MULTILINE&lt;br /&gt;
[some_tag]&lt;br /&gt;
    some_attribute = &amp;quot;some value&amp;quot;&lt;br /&gt;
[/some_tag]&lt;br /&gt;
#endarg&lt;br /&gt;
...&lt;br /&gt;
#enddef&lt;br /&gt;
&lt;br /&gt;
{MY_MACRO (MULTILINE=[other_tag]&lt;br /&gt;
    other_attribute = &amp;quot;other value&amp;quot;&lt;br /&gt;
[/other_tag])}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note:''' As with #enddef, the final line break before #endarg is included in the default value. This means that if the symbol is used in the middle of a line, you should place the #endarg immediately after the value has ended, without a line break in between.&lt;br /&gt;
&lt;br /&gt;
=== #undef ===&lt;br /&gt;
&lt;br /&gt;
'''Syntax:''' '''#undef ''symbol'' '''&lt;br /&gt;
&lt;br /&gt;
Removes the previous definition of the macro named ''symbol''. Wesnoth expects this to be done when overriding an existing macro, and will warn you if you redefine an existing macro without an explicit #undef before it.&lt;br /&gt;
&lt;br /&gt;
=== Inclusion directive {} ===&lt;br /&gt;
&lt;br /&gt;
This directive can be used to include macros, single files or sets of files from a target directory.&lt;br /&gt;
&lt;br /&gt;
==== File/directory inclusions ====&lt;br /&gt;
&lt;br /&gt;
'''Syntax: {''path''}'''&lt;br /&gt;
&lt;br /&gt;
Includes the file with the specified ''path'', which will in turn run the preprocessor on it and perform any required substitutions or inclusions within it. The ''path'' may not contain ''..'' or the inclusion will be skipped.&lt;br /&gt;
&lt;br /&gt;
The exact location in which the ''path'' will be resolved will depend on its prefix:&lt;br /&gt;
&lt;br /&gt;
* '''{''path''}''': If ''path'' isn't a known macro (see below), the game will assume it's a relative path to a file in the main game '''data/''' directory and include it.&lt;br /&gt;
* '''{~''path''}''': As above, but instead of the game data directory, the path is resolved relative to the user '''data/''' directory, where user made add-ons can normally be found.&lt;br /&gt;
* '''{./''path''}''': The path is resolved relative to the location of the current file containing this inclusion.&lt;br /&gt;
&lt;br /&gt;
Information for locating the user data and game data directories can be found in [[EditingWesnoth]].&lt;br /&gt;
&lt;br /&gt;
Forward slashes ('''/''') should '''always''' be used as the path delimiter, even if your platform uses a different symbol such as colons (''':''') or backslashes ('''\''')! It is also very important to respect the '''actual letter case''' used to name files and directories for compatibility with case-sensitive filesystems on Unix-based operating systems.&lt;br /&gt;
&lt;br /&gt;
When ''path'' points to a directory instead of a file, the preprocessor will include all files found within with the '''.cfg''' extension, in alphabetical order; files without this extension (such as '''.map''' or '''.png''' files) are ignored.&lt;br /&gt;
&lt;br /&gt;
Some directories are handled in a special fashion according to their contents:&lt;br /&gt;
&lt;br /&gt;
* If there's a file named '''_main.cfg''' in the target directory, only that file will be included and preprocessed. It may include other files from its own directory or subdirectories within it, of course. This is used for managing WML directories as self-contained packages, like user made add-ons.&lt;br /&gt;
* If there are files named '''_main.cfg''' in subdirectories of the target and there isn't one in the target itself, they will be all preprocessed. Given the following layout:&lt;br /&gt;
 dir/&lt;br /&gt;
 dir/a/_main.cfg&lt;br /&gt;
 dir/a/other.cfg&lt;br /&gt;
 dir/b/_main.cfg&lt;br /&gt;
 dir/b/other.cfg&lt;br /&gt;
 dir/other.cfg&lt;br /&gt;
Using '''{dir}''' will cause dir/a/_main.cfg, dir/b/_main.cfg and dir/other.cfg to be included.&lt;br /&gt;
* If there's a file named '''_final.cfg''' but no '''_main.cfg''', the file is guaranteed to be included and processed ''after'' all the other files in the directory.&lt;br /&gt;
* If there's a file named '''_initial.cfg''' but no '''_main.cfg''', the file is guaranteed to be included and processed ''before'' all the other files in the directory.&lt;br /&gt;
&lt;br /&gt;
==== Macro inclusions ====&lt;br /&gt;
&lt;br /&gt;
'''Syntax: {''symbol'' [''arguments''] [''optional arguments'']}'''&lt;br /&gt;
&lt;br /&gt;
If the macro named ''symbol'' is defined, the preprocessor will replace this instruction by the expression ''symbol'' was previously defined as, using ''arguments'' as parameters. The number of normal arguments must be exactly the same as in the original definition or an error will occur. Optional arguments can only be placed '''after''' all normal arguments, however they can be specified in any order desired.&lt;br /&gt;
&lt;br /&gt;
You can create multiple word arguments by using parentheses to delimit the contents. If they are already quoted, space inside quotes will be preserved even without parentheses. For example, in '''{ENEMY_UNIT Wolf Rider 18 24}''' the four words will be interpreted as separate arguments and cause the preprocessor to fail since the macro was defined above with only three; instead, you should use '''{ENEMY_UNIT (Wolf Rider) 18 24}'''.&lt;br /&gt;
&lt;br /&gt;
Optional arguments can also be delimited by placing parentheses, however they must be placed around both the argument name '''and''' content:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;wml&amp;quot;&amp;gt;&lt;br /&gt;
{MESSAGE _&amp;quot;I'll smash you!&amp;quot; (SPEAKER_ID=Bridge Troll) } # Correct&lt;br /&gt;
{MESSAGE _&amp;quot;I'll smash you!&amp;quot; SPEAKER_ID=(Bridge Troll) } # Wrong&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This way even complex arguments can be passed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;wml&amp;quot;&amp;gt;&lt;br /&gt;
{MODIFY_UNIT (&lt;br /&gt;
    [filter_adjacent]&lt;br /&gt;
        canrecruit=yes&lt;br /&gt;
    [/filter_adjacent]&lt;br /&gt;
    ) side 2}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using the name of an existing macro as the name of a macro argument is possible, but the argument will always take precedence over the original macro:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;wml&amp;quot;&amp;gt;&lt;br /&gt;
#define VARIABLE&lt;br /&gt;
#enddef&lt;br /&gt;
#define MACRO VARIABLE&lt;br /&gt;
    {VARIABLE} # is calling for the argument, not for the macro above&lt;br /&gt;
#enddef&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== #ifdef and #ifndef ===&lt;br /&gt;
&lt;br /&gt;
Unlike the other preprocessor directives, '''#ifdef''' and '''#ifndef''' are not mere conveniences. They are often necessary to distinguish between different gameplay modes or difficulties (see [[#Built-in macros|Built-in macros]] below).&lt;br /&gt;
&lt;br /&gt;
'''Syntax:''' '''#ifdef ''symbol'' ''substitution-if-defined'' [#else ''substitution-if-not-defined'' ] #endif'''&lt;br /&gt;
&lt;br /&gt;
If ''symbol'' has been defined with '''#define''' or as a built-in macro, the whole block will be replaced by ''substitution-if-defined''.  If not, it will be replaced by ''substitution-if-not-defined'' if it is available.&lt;br /&gt;
&lt;br /&gt;
'''#ifndef''' is the exact opposite of '''#ifdef''', reversing the logic:&lt;br /&gt;
&lt;br /&gt;
'''Syntax:''' '''#ifndef ''symbol'' ''substitution-if-not-defined''  [#else ''substitution-if-defined''] #endif'''&lt;br /&gt;
&lt;br /&gt;
=== #ifhave and #ifnhave ===&lt;br /&gt;
&lt;br /&gt;
'''Syntax:''' '''#ifhave ''path'' ''substitution-if-path-exists'' [#else ''substitution-if-path-does-not-exist''] #endif'''&lt;br /&gt;
&lt;br /&gt;
Checks for the existence of a file. Uses the same relative paths as [[#Inclusion_directive_.7B.7D|include directives]].&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;wml&amp;quot;&amp;gt;&lt;br /&gt;
#ifhave ~add-ons/My_Addon/_main.cfg&lt;br /&gt;
    {MY_ADDON_MACROS}&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''#ifnhave'''  does the opposite of '''#ifhave''':&lt;br /&gt;
&lt;br /&gt;
'''Syntax:''' '''#ifnhave ''path'' ''substitution-if-path-does-not-exist'' [#else ''substitution-if-path-exists''] #endif'''&lt;br /&gt;
&lt;br /&gt;
=== #ifver and #ifnver ===&lt;br /&gt;
&lt;br /&gt;
'''Syntax:''' '''#ifver ''symbol'' ''operator'' ''version-number'' ''&amp;lt;newline&amp;gt;'' ''substitution-if-condition-met'' [#else ''substitution-if-condition-not-met''] #endif'''&lt;br /&gt;
&lt;br /&gt;
Compares a version number defined in a macro against an argument for conditional block inclusions, like ''#ifdef'' and ''#ifhave''. ''operator'' is one of ''=='' (equal), ''!='' (not equal), ''&amp;lt;'' (less), ''&amp;lt;='' (less or equal), ''&amp;gt;'' (greater), ''&amp;gt;='' (greater or equal). The specified ''symbol'' should have been previously defined as plain text without more macro inclusions within it, and it must not require any arguments.&lt;br /&gt;
&lt;br /&gt;
Versions with text suffixes are sorted in binary order and come after all versions with the same number. The most common suffixes begin with &amp;quot;+&amp;quot;, but as this represents multiple possible versions, comparing versions against it is not recommended.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;wml&amp;quot;&amp;gt;&lt;br /&gt;
#ifver WESNOTH_VERSION &amp;gt;= 1.9.7+&lt;br /&gt;
    [message]&lt;br /&gt;
        speaker=narrator&lt;br /&gt;
        message= _ &amp;quot;I’m on Wesnoth 1.9.7+, 1.9.8 or later!&amp;quot;&lt;br /&gt;
    [/message]&lt;br /&gt;
#else&lt;br /&gt;
#ifver WESNOTH_VERSION == 1.9.7&lt;br /&gt;
    [message]&lt;br /&gt;
        speaker=narrator&lt;br /&gt;
        message= _ &amp;quot;I’m on Wesnoth 1.9.7, and I’ll include some workaround code for bug #9001!&amp;quot;&lt;br /&gt;
    [/message]&lt;br /&gt;
#endif&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''#ifnver'''  does the opposite of '''#ifver''':&lt;br /&gt;
&lt;br /&gt;
'''Syntax:''' '''#ifnver ''symbol'' ''operator'' ''version-number'' ''&amp;lt;newline&amp;gt;'' ''substitution-if-condition-not-met'' [#else ''substitution-if-condition-met''] #endif'''&lt;br /&gt;
&lt;br /&gt;
=== #error ===&lt;br /&gt;
&lt;br /&gt;
'''Syntax:''' '''#error [''message'']'''&lt;br /&gt;
&lt;br /&gt;
Causes the WML preprocessor to fail unconditionally upon encountering the line. For add-ons, this will cause the game to display an error and return to the titlescreen if the add-on is required for the user's action (such as playing a campaign or loading a saved game). For core WML, this will cause the game to quit entirely.&lt;br /&gt;
&lt;br /&gt;
Please note that in spite of the example below, it is '''not''' advisable to use this mechanism in published add-ons for version or feature-checking, since the message is not displayed in a form that permits translation and the additional trace information may confuse players. This directive is only intended as a debugging aid for content creators.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;wml&amp;quot;&amp;gt;&lt;br /&gt;
#ifver WESNOTH_VERSION &amp;lt; 1.11.10&lt;br /&gt;
#error This add-on does not support Wesnoth 1.11.10!&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== #warning ===&lt;br /&gt;
&lt;br /&gt;
'''Syntax:''' '''#warning [''message'']'''&lt;br /&gt;
&lt;br /&gt;
Causes the WML preprocessor to emit a warning upon encountering the line. The message will '''only''' be relayed to stderr, not to the player in the game UI. This directive is only intended as a debugging aid for content creators.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;wml&amp;quot;&amp;gt;&lt;br /&gt;
#ifver WESNOTH_VERSION &amp;lt; 1.11.10&lt;br /&gt;
#warning On Wesnoth 1.11.9 or earlier, bug workarounds enabled!&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== #deprecated ===&lt;br /&gt;
&lt;br /&gt;
{{DevFeature1.13|11}}&lt;br /&gt;
&lt;br /&gt;
'''Syntax:''' '''#deprecated 1 [''message'']'''&lt;br /&gt;
&lt;br /&gt;
'''Syntax:''' '''#deprecated 2 ''version'' [''message'']'''&lt;br /&gt;
&lt;br /&gt;
'''Syntax:''' '''#deprecated 3 ''version'' [''message'']'''&lt;br /&gt;
&lt;br /&gt;
'''Syntax:''' '''#deprecated 4 [''message'']'''&lt;br /&gt;
&lt;br /&gt;
The first argument is the deprecation level, while ''version'' is the first Wesnoth version where this deprecated file/macro might to be removed. ''message'' is the optional deprecation message. The recommended usage is to provide ''message''.&lt;br /&gt;
&lt;br /&gt;
The effect of this directive depends on whether it appears within a macro definition.&lt;br /&gt;
&lt;br /&gt;
* If it appears at file level, outside any macro definition, then it immediately outputs a warning saying that the file is deprecated, with the provided message. Multiple '''#deprecated''' directives at toplevel in a single file will result in separate messages.&lt;br /&gt;
* If it appears inside a macro definition ('''#define ... #enddef'''), then it doesn't output anything. Instead, it marks the macro as deprecated. When that macro is later used, only then will the preprocessor output a warning saying that the macro is deprecated, with the provided message. Multiple '''#deprecated''' directives within a single macro will be merged into one message.&lt;br /&gt;
&lt;br /&gt;
Note that deprecation messages will only appear if they have been set to. {{DevFeature1.13|12}} This can be done by enabling debug mode, or by going to Advanced Preferences and setting the log-level for the deprecation logdomain. (This can also be done on the command-line.)&lt;br /&gt;
&lt;br /&gt;
If you provide a deprecation level of 2 or 3, it is required to indicate the earliest version in which the feature could be removed. However, if you provide a deprecation level of 1 or 4, any provided ''version'' will instead be parsed as part of the message, so you will probably not want to provide one at all. Other deprecation levels are not valid. See the documentation for [[InterfaceActionsWML#.5Bdeprecated_message.5D|[deprecated_message]]] for the meaning of the various ''level'' values.&lt;br /&gt;
&lt;br /&gt;
== Built-in macros ==&lt;br /&gt;
&lt;br /&gt;
The following macros are automatically defined with empty contents (unless specified otherwise) by the game engine depending on the configuration or gameplay mode.&lt;br /&gt;
&lt;br /&gt;
Note that except during an actual game, '''MULTIPLAYER''', '''EDITOR''' and previous campaign defines, are not guaranteed to be undefined, especially when coming back to the titlescreen. So it is not enough to hide contents inside of an #ifdef to prevent them from being seen by the campaign selection dialog, for example for multiplayer specific '''[campaign]'''s or '''[modification]'''s '''type=mp''' must be used. &lt;br /&gt;
&lt;br /&gt;
* A campaign define symbol (see ''define'' in [[CampaignWML]]): defined when playing a single-player campaign.&lt;br /&gt;
* A campaign difficulty level, usually '''EASY''', '''NORMAL''' or '''HARD''' (see ''difficulties'' in [[CampaignWML]]): defined according to the chosen difficulty when starting a single-player campaign, also stored in saved games.&lt;br /&gt;
* '''MULTIPLAYER''': defined when in multiplayer mode.&lt;br /&gt;
* '''EDITOR''': defined when running the built-in map editor.&lt;br /&gt;
* '''DEBUG_MODE''': defined when the game has been launched in debug mode (i.e. with '''-d''' or '''--debug''' in the command line). Can also be set by typing &amp;lt;code&amp;gt;:&amp;lt;/code&amp;gt; to bring up [[CommandMode]], then typing &amp;lt;code&amp;gt;debug&amp;lt;/code&amp;gt;, and then restarting the scenario.&lt;br /&gt;
* '''APPLE''': defined while processing the main game data when running on Mac OS X. This primarily exists to switch Control for Command in hotkeys, which is why there are no defines for other platforms.&lt;br /&gt;
* '''WESNOTH_VERSION''': defined containing just the game version number when running the WML preprocessor.&lt;br /&gt;
* '''CURRENT_FILE''': Expands to the name of the current WML file.&lt;br /&gt;
* '''CURRENT_DIRECTORY''': Expands to the preprocessor path of the parent directory for the current WML file (e.g. for &amp;lt;code&amp;gt;&amp;amp;lt;user data dir&amp;amp;gt;/data/add-ons/My_Addon/_main.cfg&amp;lt;/code&amp;gt; this evaluates to &amp;lt;code&amp;gt;~add-ons/My_Addon&amp;lt;/code&amp;gt;). &lt;br /&gt;
* '''LEFT_BRACE''': {{DevFeature1.15|2}} Expands to &amp;lt;code&amp;gt;{&amp;lt;/code&amp;gt;.&lt;br /&gt;
* '''RIGHT_BRACE''': {{DevFeature1.15|2}} Expands to &amp;lt;code&amp;gt;}&amp;lt;/code&amp;gt;.&lt;br /&gt;
* '''SCHEMA_VALIDATION''': defined if the validator is being run.&lt;br /&gt;
* '''__WMLUNITS__''': defined when the tool to create [https://units.wesnoth.org units.wesnoth.org] is being run.&lt;br /&gt;
&lt;br /&gt;
A ''very large'' number of additional macros are provided as part of the default game core WML. For a full list of those, check the [https://www.wesnoth.org/macro-reference.html macro reference].&lt;br /&gt;
&lt;br /&gt;
== Command-line preprocessor ==&lt;br /&gt;
&lt;br /&gt;
'''Syntax: --preprocess ''&amp;amp;lt;source file/directory&amp;gt;'' ''&amp;lt;target directory&amp;gt;'' '''&lt;br /&gt;
&lt;br /&gt;
Or the short form:&lt;br /&gt;
&lt;br /&gt;
'''Syntax: -p ''&amp;amp;lt;source file/directory&amp;gt;'' ''&amp;lt;target directory&amp;gt;'' '''&lt;br /&gt;
&lt;br /&gt;
You can specify a list of predefined defines with:&lt;br /&gt;
&lt;br /&gt;
'''Syntax: --preprocess-defines=DEFINE1,DEFINE2,etc'''&lt;br /&gt;
&lt;br /&gt;
comma separated list of defines to be used by '--preprocess' command. If 'SKIP_CORE' is in the define list the data/core won't be preprocessed.&lt;br /&gt;
&lt;br /&gt;
The command will first preprocess '''data/core/macros''' and '''data/core/terrain-graphics''', and afterwards the specified path. You can specify a single file to be preprocessed (if you want to preprocess multiple separate files, you'll need to run a different command line for each one), or an entire directory, which will be preprocessed according to the rules used by the inclusion directive above.&lt;br /&gt;
&lt;br /&gt;
The resulting preprocessed files will be written in the target directory. There will be two types of files: .cfg files --- the normal ones, and .plain files containing line markers and textdomain changes.&lt;br /&gt;
&lt;br /&gt;
If by chance, the simple macro define doesn't suffice, you can use:&lt;br /&gt;
&lt;br /&gt;
'''Syntax: --preprocess-input-macros &amp;lt;file&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
To import an existing file that contains macros, and they will be available in the defines database before processing the specified files.&lt;br /&gt;
&lt;br /&gt;
There is also the possibility to export the preprocessed defines/macro list with:&lt;br /&gt;
&lt;br /&gt;
'''Syntax: --preprocess-output-macros [&amp;lt;target file&amp;gt;]'''&lt;br /&gt;
&lt;br /&gt;
This file could be fed to the 'input-macros' argument next time you run it. For example, a scenario would be: parsing just the core first time, and for the intended target files, you would add SKIP_CORE but import the generated macros file - that will be faster than preprocessing the core again. If the target file is not specified, the output file will be _MACROS_.cfg in the target directory of the preprocess's command.&lt;br /&gt;
&lt;br /&gt;
If ''file/directory'' and ''target directory'' are not absolute paths, they will be considered relative to the current directory.&lt;br /&gt;
&lt;br /&gt;
Some examples:&lt;br /&gt;
&lt;br /&gt;
* Preprocess the entire tutorial dir, and write the results in the ~/result folder:&lt;br /&gt;
 -p ~/wesnoth/data/campaigns/tutorial ~/result&lt;br /&gt;
* Add the MULTIPLAYER define to the list and preprocess a scenario's config file:&lt;br /&gt;
 -p ~/.wesnoth/data/add-ons/My_Campaign/scenarios/01_First_Scenario.cfg ~/result --preprocess-defines=MULTIPLAYER&lt;br /&gt;
* Add the MY_CAMPAIGN and HARD defines before preprocessing a campaign's files:&lt;br /&gt;
 -p ~/.wesnoth/data/add-ons/My_Campaign ~/result --preprocess-defines=MY_CAMPAIGN,HARD&lt;br /&gt;
* File myfile.cfg depends on macros defined in data/gui/macros/_initial.cfg:&lt;br /&gt;
 -p data/gui/macros/_initial.cfg  /tmp --preprocess-output-macros=macros&lt;br /&gt;
 -p myfile.cfg ~/result --preprocess-input-macros=/tmp/macros&lt;br /&gt;
&lt;br /&gt;
When it starts getting complicated, such as a file that depends on multiple other files, it is probably easiest to simply &amp;quot;include&amp;quot; the dependencies:&lt;br /&gt;
&lt;br /&gt;
* File myfile.cfg depends on macros defined in data/gui/macros/_initial.cfg:&lt;br /&gt;
  Add {gui/macros/_initial.cfg} to the beginning of  myfile.cfg&lt;br /&gt;
  -p myfile.cfg ~/result&lt;br /&gt;
&lt;br /&gt;
If you want a more detailed (and potentially overwhelming) log, you can simply add the switches '''--log-debug=all''' or '''--log-info=all''' to the command line, so you can see how things are preprocessed in detail.&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
&lt;br /&gt;
* [[SyntaxWML]] (explains relationship between comments and preprocessor directives)&lt;br /&gt;
* [[ReferenceWML]]&lt;br /&gt;
&lt;br /&gt;
[[Category: WML Reference]]&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Template:DevDownload&amp;diff=74962</id>
		<title>Template:DevDownload</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Template:DevDownload&amp;diff=74962"/>
		<updated>2026-04-09T00:19:14Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
== Development (1.19 branch) ==&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
==== Windows (10 1903 and later) {{{4|}}} ====&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.22 | filename=wesnoth-1.19.22-win64.exe |&lt;br /&gt;
hash=805a9da0b230f4334431704ba0cea6b8dcb4613da2530fcf1f315ff382ec67e2}}&lt;br /&gt;
&lt;br /&gt;
==== macOS (10.13 and later) {{{5|}}} ====&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.21 | filename=Wesnoth_1.19.21.dmg |&lt;br /&gt;
hash=ef44157e1056fae915df935b8cb32af88d2072eaa8e8ac2c856a4d78d40e7fd9}}&lt;br /&gt;
&lt;br /&gt;
==== Source code ====&lt;br /&gt;
* [https://github.com/wesnoth/wesnoth/blob/master/INSTALL.md Compiling Wesnoth] - How to compile the source code&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.22 | filename=wesnoth-1.19.22.tar.bz2 |&lt;br /&gt;
hash=dccf874092cf42dfbef61e30217f55d40ab4608532ff6dba3be7c052ca3e0c66}}&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Template:StableDownload&amp;diff=74961</id>
		<title>Template:StableDownload</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Template:StableDownload&amp;diff=74961"/>
		<updated>2026-04-09T00:18:43Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
== Stable (1.18 branch) ==&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
==== Windows (10 1903 and later, 64-bit only) {{{4|}}} ====&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth-1.18 |&lt;br /&gt;
version=1.18.7 | filename=wesnoth-1.18.7-win64.exe |&lt;br /&gt;
hash=1ebe433b8f7b526944b63d15caf11f42481375130431237b3f1139a517c7c7bb}}&lt;br /&gt;
&lt;br /&gt;
==== macOS (10.12 and later) {{{5|}}} ====&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth-1.18 |&lt;br /&gt;
version=1.18.6 | filename=Wesnoth_1.18.6.dmg |&lt;br /&gt;
hash=1b9a0ba71c11a386ea0daef357cb508f5c9dc792eed71eff1a3783c056214c93}}&lt;br /&gt;
&lt;br /&gt;
==== Source code ====&lt;br /&gt;
* [https://github.com/wesnoth/wesnoth/blob/master/INSTALL.md Compiling Wesnoth] - How to compile the source code&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth-1.18 |&lt;br /&gt;
version=1.18.7 | filename=wesnoth-1.18.7.tar.bz2 |&lt;br /&gt;
hash=d6b50cfdf4388954a1c3da66a61abacdc7643a17aa78a16196e16e720a661fc2}}&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Template:DevDownload&amp;diff=74953</id>
		<title>Template:DevDownload</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Template:DevDownload&amp;diff=74953"/>
		<updated>2026-03-30T01:57:23Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
== Development (1.19 branch) ==&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
==== Windows (10 1903 and later) {{{4|}}} ====&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.22 | filename=wesnoth-1.19.22-win64.exe |&lt;br /&gt;
hash=805a9da0b230f4334431704ba0cea6b8dcb4613da2530fcf1f315ff382ec67e2}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.21 | filename=wesnoth-1.19.21-win64.exe |&lt;br /&gt;
hash=7492d586fa192b5d60dfbc4265567e344993401aed6a63d03dc53db130cbbcbb}}&lt;br /&gt;
&lt;br /&gt;
==== macOS (10.13 and later) {{{5|}}} ====&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.21 | filename=Wesnoth_1.19.21.dmg |&lt;br /&gt;
hash=ef44157e1056fae915df935b8cb32af88d2072eaa8e8ac2c856a4d78d40e7fd9}}&lt;br /&gt;
&lt;br /&gt;
==== Source code ====&lt;br /&gt;
* [https://github.com/wesnoth/wesnoth/blob/master/INSTALL.md Compiling Wesnoth] - How to compile the source code&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.22 | filename=wesnoth-1.19.22.tar.bz2 |&lt;br /&gt;
hash=dccf874092cf42dfbef61e30217f55d40ab4608532ff6dba3be7c052ca3e0c66}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.21 | filename=wesnoth-1.19.21.tar.bz2 |&lt;br /&gt;
hash=d97521cda6717c0a76f3830d68e8918975ca88310e0f6d693db9b62c0585b16d}}&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=PblWML&amp;diff=74932</id>
		<title>PblWML</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=PblWML&amp;diff=74932"/>
		<updated>2026-03-29T03:38:43Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: /* forum_auth */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{WML Tags}}&lt;br /&gt;
&lt;br /&gt;
To upload an add-on you have made, you need a '''_server.pbl''' file in your add-on's directory, at the same level as the '''_main.cfg''' file. When you upload the add-on, the entire directory and subdirectories containing the _server.pbl file will be published. Your add-on must be based entirely on these paths.&lt;br /&gt;
&lt;br /&gt;
See [[AddonStructure]] for more on setting up the add-on folder if you have not done so, and [[Distributing_content]] for more on uploading an add-on to the server with this file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Note:&amp;lt;/b&amp;gt; Be aware that translations in the .pbl-files are '''not''' used, so don't mark these strings as translatable. {{DevFeature1.15|4}} The translations in the .pbl-files are used, but they are used as a plain text instead of Gettext strings, so don't mark these strings as translatable.&lt;br /&gt;
&lt;br /&gt;
== What goes into a .pbl file? ==&lt;br /&gt;
&lt;br /&gt;
'''Note:''' ''You should '''not''' use special formatting or coloring in any of these keys when uploading to the official server.'''''&lt;br /&gt;
&lt;br /&gt;
The following keys are recognized for .pbl files:&lt;br /&gt;
&lt;br /&gt;
=== icon ===&lt;br /&gt;
: An image, displayed leftmost in the add-ons download dialog. It must be a standard Wesnoth file and '''not a custom one'''. A custom file will only work for users who already have the relevant add-on installed. This is not related to the icon used for entries in the campaigns menu -- see [[CampaignWML]] for more information.&lt;br /&gt;
&lt;br /&gt;
: If the icon is a unit with magenta team-color bits, please use [[ImagePathFunctions]] to recolor it. For example: &lt;br /&gt;
&lt;br /&gt;
::icon=&amp;quot;units/elves-wood/archer+female-sword-1.png~RC(magenta&amp;gt;brightorange)&amp;quot;&lt;br /&gt;
:or&lt;br /&gt;
::icon=&amp;quot;units/human-peasants/peasant-ranged.png~RC(magenta&amp;gt;white)~CS(24,24,24)&amp;quot;&lt;br /&gt;
:or&lt;br /&gt;
::icon=&amp;quot;units/human-peasants/ruffian.png~RC(magenta&amp;gt;green)~BLIT(units/human-peasants/woodsman.png~RC(magenta&amp;gt;lightblue),18,12)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
: Because the add-on manager's UI is dark, recoloring to light colors looks usually better. [https://irydacea.me/projects/wespal Wespal] is a tool that provides a convenient way to preview recolored unit sprites without needing to launch the game with specific WML or Lua edits.&lt;br /&gt;
&lt;br /&gt;
: {{DevFeature1.13|12}} Instead of a standard Wesnoth image, a [[DataURI]] can also be used. This way, an image can be directly included into the _server.pbl file. Take care to leave no trailing newline.&lt;br /&gt;
&lt;br /&gt;
=== title ===&lt;br /&gt;
: Displayed to the right of the icon, it is just text. It should usually be the same as the name of your add-on when it is played.&lt;br /&gt;
: '''This value is required'''.&lt;br /&gt;
&lt;br /&gt;
=== version ===&lt;br /&gt;
: Displayed to the right of the title; it is merely text. However, starting with Wesnoth 1.6, the required format is '''x.y.z''' where '''x''', '''y''' and '''z''' are numbers — and a value for '''x''' greater than ''0'' implies the add-on is complete, feature-wise. Trailing non-numeric elements are allowed, but nothing should appear before or between these numbers. The string of numbers will be modified on the server by inserting or appending zeros as neccesary to meet the required format. All this is necessary for the “Update All” button to work correctly. ([[#Version Key Examples|See Examples]])&lt;br /&gt;
: '''This value is required'''.&lt;br /&gt;
&lt;br /&gt;
=== author ===&lt;br /&gt;
: Displayed to the right of the version; it is merely text. Put your name or nickname here. If several people have contributed significantly to the add-on you may want to list all of their names.&lt;br /&gt;
&lt;br /&gt;
: {{DevFeature1.17|3}} When using forum_auth, this value is a single forum account name which will have the ability to upload new versions of the add-on, delete the add-on from the add-ons server, and update the secondary_authors field.&lt;br /&gt;
&lt;br /&gt;
: {{DevFeature1.19|7}} This value is now used the same as it was pre-forum_auth. It is only used to display in the addons manager.&lt;br /&gt;
&lt;br /&gt;
: '''This value is required'''.&lt;br /&gt;
&lt;br /&gt;
=== passphrase ===&lt;br /&gt;
: Not displayed. It prevents others from modifying the version of your add-on on the server. You do not need to input a passphrase when initially publishing a add-on; if you do not, one will be randomly generated for you and replaced in your local copy of the .pbl file.&lt;br /&gt;
: '''SECURITY NOTE:''' If you do specify a passphrase of your own, note that it is stored in '''clear text''' form in the server; '''do NOT use a password you would normally use for any other services or web sites!'''&lt;br /&gt;
&lt;br /&gt;
: {{DevFeature1.15|12}}&lt;br /&gt;
&lt;br /&gt;
: It is no longer required to keep the passphrase in the .pbl file at all. If it is not present, then Wesnoth will prompt for it to be entered when uploading or deleting an add-on.&lt;br /&gt;
&lt;br /&gt;
=== description ===&lt;br /&gt;
: This can be used to provide a brief description of your add-on, and for pre-1.0 versions, let people know how playable it is. The description can be viewed by users by clicking on the Description button in the built-in client, or by moving their mouse over the add-on's icon in the web interface.&lt;br /&gt;
: '''This value is required'''.&lt;br /&gt;
&lt;br /&gt;
=== dependencies ===&lt;br /&gt;
: An optional list of dependencies (a comma separated list of ''addon-name'' – the directory names of the needed add-ons), which should be provided if your add-on relies on other user-made content to work properly. ([[#Dependency Key Example|See Example]])&lt;br /&gt;
&lt;br /&gt;
=== tags ===&lt;br /&gt;
{{DevFeature1.13|12}}&lt;br /&gt;
: An optional string including a comma-separated list of keywords used for matching add-ons when typing terms into the Filter box on the top left of the Add-ons Manager. There are no specific requirements on the syntax of the keywords listed here, but a general recommendation is to keep them relevant for players. For example, one might include the add-on's acronym in the tags, the names or acronyms of add-ons to which it is related, and so on.&lt;br /&gt;
&lt;br /&gt;
{{DevFeature1.15|13}} The in-game add-ons manager will show all the tags in the UI, and also includes a drop-down list of tags to filter by. Not all tags are listed in the filter box, and the exact list of tags supported may change before 1.16 is released, but the list is currently:&lt;br /&gt;
&lt;br /&gt;
* '''cooperative''': All human players are on the same team, versus the AI&lt;br /&gt;
* '''cosmetic''': These make the game look different, without changing gameplay&lt;br /&gt;
* '''difficulty''': Can make campaigns easier or harder&lt;br /&gt;
* '''rng''': Modify the randomness in the combat mechanics, or remove it entirely&lt;br /&gt;
* '''survival''': Fight against waves of enemies&lt;br /&gt;
* '''terraforming''': Players can change the terrain&lt;br /&gt;
&lt;br /&gt;
For example, if an A New Land style add-on had tags ''building'', ''terraforming'', ''anl'', ''city'', and ''survival'' then it would be shown if either ''Terraforming'' or ''Survival'' was selected in the drop-down; the other tags wouldn't affect the filtering.&lt;br /&gt;
&lt;br /&gt;
=== core ===&lt;br /&gt;
{{DevFeature1.13|0}}&lt;br /&gt;
: An optional string defining the id of the core which the addon is designed for. Defaults to &amp;quot;''default''&amp;quot;. Don't specify for an addon which is of type &amp;quot;''core''&amp;quot; itself. Note: DO NOT SET this unless you know why you need it! Giving it an invalid value can lead to mysterious errors with your campaign failing to load!&lt;br /&gt;
&lt;br /&gt;
=== translate ===&lt;br /&gt;
: If set to ''true'', the add-on would have been sent to and updated with [[WesCamp|WesCamp-i18n]], if that project were still active. However, as WesCamp is no longer active, this no longer does anything.&lt;br /&gt;
&lt;br /&gt;
: You should make sure your add-on complies with some very specific [[WesCamp#Preparing_your_add-on_for_WesCamp|conventions]] required to ease the process for translators as well as technical requirements.&lt;br /&gt;
&lt;br /&gt;
: Note: WesCamp was abandoned in 2014. Instead, please refer to:&lt;br /&gt;
* [[GettextForWesnothDevelopers]]&lt;br /&gt;
* [[GettextForTranslators#For_add-ons]]&lt;br /&gt;
* forum thread: [https://r.wesnoth.org/t46366 Guide: Translating your UMC without WesCamp].&lt;br /&gt;
&lt;br /&gt;
=== type ===&lt;br /&gt;
: Indicates the type of the add-on; used to filter listings in the downloads manager dialog. Acceptable values are:&lt;br /&gt;
&lt;br /&gt;
:* ''core'': replaces the whole wml tree. {{DevFeature1.13|0}}&lt;br /&gt;
:* ''campaign'': single player campaign.&lt;br /&gt;
:* ''scenario'': single player scenario.&lt;br /&gt;
:* ''campaign_sp_mp'': hybrid campaign.&lt;br /&gt;
:* ''era'': multiplayer era.&lt;br /&gt;
:* ''faction'': multiplayer stand-alone faction, or add-on for other available era.&lt;br /&gt;
:* ''map_pack'': multiplayer map-pack.&lt;br /&gt;
:* ''campaign_mp'': multiplayer campaign.&lt;br /&gt;
:* ''scenario_mp'': multiplayer scenario. (See the note below.)&lt;br /&gt;
:* ''mod_mp'': multiplayer modification ({{DevFeature1.13|11}} can also used for single-player modifications, although it's still called ''mod_mp'').&lt;br /&gt;
:* ''media'': miscellaneous resources for UMC authors/users, for example, music packs, packages of general-purpose WML, etc. &amp;lt;small&amp;gt;Note: Shows as Resources, not Media, in the add-ons interface&amp;lt;/small&amp;gt;&lt;br /&gt;
:* ''other'': The type to use when no other type fits.&lt;br /&gt;
: '''Note:''' If your add-on contains two or more separate multiplayer scenarios, use ''map_pack''.&lt;br /&gt;
&lt;br /&gt;
: '''This value is required'''.&lt;br /&gt;
&lt;br /&gt;
=== email ===&lt;br /&gt;
: Hidden e-mail address used by the server administrators to contact content authors in case of major issues. Again, this will only be seen by the server administrators and it is required that you provide one in case you need to be contacted about your add-on.&lt;br /&gt;
&lt;br /&gt;
: '''This value is required if forum_auth is not set to true'''.&lt;br /&gt;
&lt;br /&gt;
=== forum_auth ===&lt;br /&gt;
{{DevFeature1.17|3}}&lt;br /&gt;
: When set to ''true'', you will be prompted for your forum password when uploading your add-on. The username(s) available to select will be populated from the '''author''' field (before 1.19.7) or the '''primary_authors''' field (1.19.7+). If the username dropdown is empty, make sure to confirm that either the '''author''' or '''primary_authors''' field is present and spelled correctly, depending on what version of Wesnoth you are running.&lt;br /&gt;
&lt;br /&gt;
When set to true, the ''passphrase'' and ''email'' fields are also not required.&lt;br /&gt;
&lt;br /&gt;
=== primary_authors ===&lt;br /&gt;
{{DevFeature1.19|7}}&lt;br /&gt;
: A comma-delimited list of forum accounts that are allowed to upload new versions of the add-on or delete the add-on from the add-ons server.&lt;br /&gt;
&lt;br /&gt;
=== secondary_authors ===&lt;br /&gt;
: A comma-delimited list of forum accounts that are allowed to upload new versions of the add-on, but aren't allowed to delete the add-on.&lt;br /&gt;
&lt;br /&gt;
=== [feedback] ===&lt;br /&gt;
: The [feedback] tag includes information used by the server to provide the client with a website URL for players to post feedback on an add-on and communicate with the maintainers. At this time, the official add-ons server is configured to take a single parameter described below.&lt;br /&gt;
&lt;br /&gt;
==== topic_id ====&lt;br /&gt;
: Topic id from the [http://forums.wesnoth.org/ Wesnoth.org forums] for the add-on's feedback or development topic maintained by the add-on uploader or author. For existing topics, this topic_id corresponds to the series of digits in the ''t=YYYYY'' portion of a URL like &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;http://forums.wesnoth.org/viewtopic.php?f=XX&amp;amp;t=YYYYY&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;. You must take special care to ensure this information is valid before uploading if you want players to be able to reach you!&lt;br /&gt;
&lt;br /&gt;
=== [translation] ===&lt;br /&gt;
{{DevFeature1.15|4}}&lt;br /&gt;
: Multiple [translation] tags can be used to provide the addon with a localized title and description to be seen in the addons manager. However, it should be noted that the declared translations won't influence the list of supported locales as it depends only on the presence of .mo and .po files for corresponding languages.&lt;br /&gt;
&lt;br /&gt;
==== language ====&lt;br /&gt;
: The target language code for the translation. The codes for each language are given in the big table on [https://www.wesnoth.org/gettext/] . You can use either its contracted version (like ''sv'' for Swedish) or a more precise variety (like ''zh_CN'' or ''ca_ES@valencia'').&lt;br /&gt;
: '''This value is required'''.&lt;br /&gt;
&lt;br /&gt;
==== title ====&lt;br /&gt;
: The translation of addon's title for the target language.&lt;br /&gt;
: '''This value is required'''.&lt;br /&gt;
&lt;br /&gt;
==== description ====&lt;br /&gt;
: The translation of addon's description for the target language.&lt;br /&gt;
&lt;br /&gt;
The add-on server keeps track of some other information about uploaded content, including when they were uploaded, what languages they have been at least partly translated into, how large they are on the server and the number of times they have been downloaded. For more information about this you can read [[CampaignServerWML]].&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
=== Dependency Key Example ===&lt;br /&gt;
&lt;br /&gt;
The following dependency key could be used when the add-on needs the ''Imperial_Era'' and ''Era_of_Myths'' to be installed before it will work properly:&lt;br /&gt;
&lt;br /&gt;
 dependencies=Imperial_Era,Era_of_Myths&lt;br /&gt;
&lt;br /&gt;
=== Version Key Examples ===&lt;br /&gt;
&lt;br /&gt;
{{DevFeature1.17|13}} the schema validation rejects many of the '''good''' examples. https://github.com/wesnoth/wesnoth/issues/7396&lt;br /&gt;
&lt;br /&gt;
The following are examples of '''good''' version values:&lt;br /&gt;
&lt;br /&gt;
 version=&amp;quot;1.5&amp;quot;&lt;br /&gt;
 version=&amp;quot;0.11.4&amp;quot;&lt;br /&gt;
 version=&amp;quot;0.1.4beta&amp;quot;&lt;br /&gt;
 version=&amp;quot;1.5c&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The following are examples of '''bad''' version values:&lt;br /&gt;
&lt;br /&gt;
 version=&amp;quot;Beta1.5&amp;quot;&lt;br /&gt;
 version=&amp;quot;Incomplete (0.3.4)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
In both of the above examples the version number as read by the server will be '''0.0.0Beta1.5''' and '''0.0.0Incomplete (0.3.4)'''. You can clearly see why this will not be a good thing with the ''Update add-ons'' feature.&lt;br /&gt;
&lt;br /&gt;
Finally, here are some example version numbers and how they will be interpreted by the ''Update add-ons'' button. The number on the left will be considered an earlier number than the number on the right in each example.&lt;br /&gt;
&lt;br /&gt;
 0.5 &amp;lt; 1.0&lt;br /&gt;
 1.5 &amp;lt; 1.5c&lt;br /&gt;
 1.0 &amp;lt; 1.0.1&lt;br /&gt;
 1.0c &amp;lt; 1.0.1a&lt;br /&gt;
 1.0.1a &amp;lt; 1.0.1c&lt;br /&gt;
 1.0 Final &amp;lt; 1.0.1 Beta&lt;br /&gt;
&lt;br /&gt;
=== Example .pbl File ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
title=&amp;quot;My Campaign&amp;quot;&lt;br /&gt;
type=&amp;quot;campaign&amp;quot;&lt;br /&gt;
icon=&amp;quot;misc/ball.png&amp;quot;&lt;br /&gt;
version=&amp;quot;0.1.2&amp;quot;&lt;br /&gt;
author=&amp;quot;Me, artwork by myself&amp;quot;&lt;br /&gt;
passphrase=&amp;quot;This is like a password; see the security note in the documentation above before choosing a value of your own&amp;quot;&lt;br /&gt;
description=&amp;quot;You get to kill a lot of bad guys. But only the first map is done.&amp;quot;&lt;br /&gt;
email=&amp;quot;name@example.com&amp;quot;&lt;br /&gt;
[feedback]&lt;br /&gt;
    topic_id=12345&lt;br /&gt;
[/feedback]&lt;br /&gt;
# Note: the translation feature works on version 1.14.14, 1.15.4 and later only&lt;br /&gt;
[translation]&lt;br /&gt;
    language=&amp;quot;ru&amp;quot;&lt;br /&gt;
	title=&amp;quot;Моя Кампания&amp;quot;&lt;br /&gt;
    description=&amp;quot;Вам придётся завалить немало плохишей. Но пока что готова лишь первая карта.&amp;quot;&lt;br /&gt;
[/translation]&lt;br /&gt;
[translation]&lt;br /&gt;
    language=&amp;quot;zh_CN&amp;quot;&lt;br /&gt;
	title=&amp;quot;我的竞选&amp;quot;&lt;br /&gt;
    description=&amp;quot;你会杀死很多坏人。 但是只完成了第一张地图。(translated online)&amp;quot;&lt;br /&gt;
[/translation]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
&lt;br /&gt;
* [[IGNFileFormat]]&lt;br /&gt;
* [[FancyAddonIcons]]&lt;br /&gt;
* [[ReferenceWML]]&lt;br /&gt;
* [[CampaignServerWML]]&lt;br /&gt;
&lt;br /&gt;
[[Category: WML Reference]]&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Template:DevDownload&amp;diff=74892</id>
		<title>Template:DevDownload</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Template:DevDownload&amp;diff=74892"/>
		<updated>2026-03-09T01:08:56Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
== Development (1.19 branch) ==&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
==== Windows (10 1903 and later) {{{4|}}} ====&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.21 | filename=wesnoth-1.19.21-win64.exe |&lt;br /&gt;
hash=7492d586fa192b5d60dfbc4265567e344993401aed6a63d03dc53db130cbbcbb}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.20 | filename=wesnoth-1.19.20-win64.exe |&lt;br /&gt;
hash=c55a71350f5aab18074a5cc781bc66a56a29086624df85f4e155d5a1a4e966f9}}&lt;br /&gt;
&lt;br /&gt;
==== macOS (10.13 and later) {{{5|}}} ====&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.21 | filename=Wesnoth_1.19.21.dmg |&lt;br /&gt;
hash=ef44157e1056fae915df935b8cb32af88d2072eaa8e8ac2c856a4d78d40e7fd9}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.20 | filename=Wesnoth_1.19.20.dmg |&lt;br /&gt;
hash=9a0df54edbbffb503f527a1b8007b7860eace3cfb9b94207c2ad21047171eb94}}&lt;br /&gt;
&lt;br /&gt;
==== Source code ====&lt;br /&gt;
* [https://github.com/wesnoth/wesnoth/blob/master/INSTALL.md Compiling Wesnoth] - How to compile the source code&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.21 | filename=wesnoth-1.19.21.tar.bz2 |&lt;br /&gt;
hash=d97521cda6717c0a76f3830d68e8918975ca88310e0f6d693db9b62c0585b16d}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.20 | filename=wesnoth-1.19.20.tar.bz2 |&lt;br /&gt;
hash=48f883f8cd3ea008f9170aeaa9fb9ebb486202dd72f455ae131363fc3d164f8f}}&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=MultiplayerServerWML&amp;diff=74861</id>
		<title>MultiplayerServerWML</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=MultiplayerServerWML&amp;diff=74861"/>
		<updated>2026-02-22T15:17:36Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: /* Game setup (the phase from creation to start) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page describes the [[WML]] used to communicate with the multiplayer server for Wesnoth, [[wesnothd]].&lt;br /&gt;
&lt;br /&gt;
== The handshake ==&lt;br /&gt;
&lt;br /&gt;
The client sends four bytes, then the server replies with four bytes. To get a new connection number, the client will send these four bytes: 0x00 0x00 0x00 0x00. The server then sends back the connection number (wesnothd calls this number the &amp;quot;socket number&amp;quot;). Since 1.13+ the server no longer is using socket numbers to keep track of clients and always sends the same number to them all. Since 1.15+ client can also send 0x00 0x00 0x00 0x01 instead to request entire connection to be [https://github.com/wesnoth/wesnoth/blob/2f8136951cd77526188cf8d0fb2cf21eaa2ebe63/src/server/common/server_base.hpp#L60-L76 encapsulated in TLS] immediately '''after'''. If the handshake is successful, the server will be the first to send a data package. All packages are in [http://en.wikipedia.org/wiki/Gzip gzip] format and are preceded by four bytes that specify the size of the package to come in '''big-endian''' (network byte order). Below you'll find information about what data the (unzipped) packages contain. Unpacked WML uses utf-8 charset.&lt;br /&gt;
&lt;br /&gt;
== The login procedure ==&lt;br /&gt;
&lt;br /&gt;
* server request (optional)&lt;br /&gt;
** '''[version]'''&lt;br /&gt;
&lt;br /&gt;
* client response&lt;br /&gt;
** '''[version]'''&lt;br /&gt;
*** '''version''': The client's version string.&lt;br /&gt;
*** '''client_source''': The client's distribution info. (Steam, SourceForge, App Store, etc.)&lt;br /&gt;
&lt;br /&gt;
* server response (if the server does not accept this version)&lt;br /&gt;
** '''[redirect]'''&lt;br /&gt;
*** '''host''': The host you should connect to.&lt;br /&gt;
*** '''port''': The port you should connect to.&lt;br /&gt;
*** '''version''': A comma-separated list of globs that this server should accept (e.g. &amp;quot;1.0*,1.2*,1.4*,1.7*,1.8*&amp;quot;)&lt;br /&gt;
** or '''[reject]''' (if the version is unknown)&lt;br /&gt;
*** '''accepted_versions''': A comma-separated list of globs that this server does accept&lt;br /&gt;
&lt;br /&gt;
* server request&lt;br /&gt;
** '''[mustlogin]'''&lt;br /&gt;
&lt;br /&gt;
* client response&lt;br /&gt;
** '''[login]'''&lt;br /&gt;
*** '''username''': The username the client would like to have.&lt;br /&gt;
*** '''password''': The hashed password, created from the password and salt received from the server. More information about how this password is being generated, including a real world example, can be found in the file [http://forum.wesnoth.org/download/file.php?id=41145 HashedPasswords.pdf] (885 KiB). Since version 1.15+ if TLS was successfully established before then password will be passed as is, without hashing, relying on TLS for secrecy. Passing password hashes is no longer supported to free the client from responsibility to support all hash schemes the forum can potentially use. Client will emit error instead of trying to send password if TLS wasn't established.&lt;br /&gt;
&lt;br /&gt;
* server response&lt;br /&gt;
** '''[join_lobby]'''&lt;br /&gt;
*** '''is_moderator''': &amp;quot;yes&amp;quot; if the user is a moderator, &amp;quot;no&amp;quot; otherwise.&lt;br /&gt;
*** '''profile_url_prefix''': The external URL prefix for player profiles (empty if the server doesn't have an attached database)&lt;br /&gt;
** or '''[error]''' (server is waiting for another '''[login]''' message now)&lt;br /&gt;
*** '''message''': The error message.&lt;br /&gt;
*** '''password_request''': If not empty the server asks the client to provide a password for its desired username.&lt;br /&gt;
*** '''phpbb_encryption''': If &amp;quot;yes&amp;quot; the client will encrypt the password using phpbb's algorithm.&lt;br /&gt;
*** '''random_salt''': Random salt sent to the client for mixing with the password hash.&lt;br /&gt;
*** '''hash_seed''': Salt generated from the original hash that is required to recreate it.&lt;br /&gt;
*** '''salt''': Salt generated from the original hash that is required to recreate it.&lt;br /&gt;
*** '''force_confirmation''': Display an ok/cancel dialog with the content of the 'message' key.&lt;br /&gt;
&lt;br /&gt;
* server response&lt;br /&gt;
** '''[gamelist]'''&lt;br /&gt;
*** '''[game]''' (repeated)&lt;br /&gt;
**** '''id''': A unique id of the game.&lt;br /&gt;
**** '''name''': The title of the game.&lt;br /&gt;
**** '''mp_scenario''': The id of the scenario.&lt;br /&gt;
**** '''mp_era''': The id of the used era.&lt;br /&gt;
**** '''mp_use_map_settings''': Does the game use the map settings specified in the scenario.&lt;br /&gt;
**** '''mp_fog''': Does the game use fog.&lt;br /&gt;
**** '''mp_shroud''': Does the game use shroud.&lt;br /&gt;
**** '''mp_village_gold''': The number of gold per village.&lt;br /&gt;
**** '''experience_modifier''': The experience setting.&lt;br /&gt;
**** '''mp_countdown''': Does the game use a timer.&lt;br /&gt;
**** '''mp_countdown_reservoir_time''': Upper limit of the possibly available time.&lt;br /&gt;
**** '''mp_countdown_init_time''': Initial time.&lt;br /&gt;
**** '''mp_countdown_action_bonus''': Time bonus per action.&lt;br /&gt;
**** '''mp_countdown_turn_bonus''': Time bonus per turn.&lt;br /&gt;
**** '''map_data''': The map data. ''Notice: not sent to lobby if the game uses shroud''&lt;br /&gt;
**** '''hash''': The hash value of the map_data.&lt;br /&gt;
**** '''observer''': Are observers allowed or not.&lt;br /&gt;
**** '''human_sides''': The number of sides played by humans.&lt;br /&gt;
**** '''slots''': The number of vacant/max slots.&lt;br /&gt;
**** '''[slot_data]''' replaces '''slots''' since {{DevFeature1.13|12}}&lt;br /&gt;
***** '''max''': The number of total slots.&lt;br /&gt;
***** '''vacant''': The number of vacant slots.&lt;br /&gt;
**** '''turn''': The current turn/max turn.&lt;br /&gt;
**** '''[turn_data]''' replaces '''turn''' since {{DevFeature1.13|12}}&lt;br /&gt;
***** '''current''': The current turn number.&lt;br /&gt;
***** '''max''': The total number of turns.&lt;br /&gt;
**** '''[modification]''' Modifications used in this game. See [[ModificationWML]].&lt;br /&gt;
***** '''id''': ID of the modification.&lt;br /&gt;
***** '''name''': Name of the modification.&lt;br /&gt;
***** '''addon_id''': ID of the addon the modification is from.&lt;br /&gt;
***** '''require_modification''': A boolean value; if set to yes, all players have to have this modification installed to join the game.&lt;br /&gt;
**** '''[options]''' Options selected for this game. See [[OptionWML]].&lt;br /&gt;
***** '''[campaign|era|modification|multiplayer]'''&lt;br /&gt;
****** '''id''': ID of the addon the campaign|era|modification|multiplayer (scenario) is from.&lt;br /&gt;
****** '''[option]'''&lt;br /&gt;
******* '''id''': ID of the option.&lt;br /&gt;
******* '''value''': Value of the option.&lt;br /&gt;
** '''[user]''' (repeated)&lt;br /&gt;
*** '''name''': The username of the player.&lt;br /&gt;
*** '''game_id''': The ID of the game the player is in.&lt;br /&gt;
*** '''location''': The name of the game the player is in.&lt;br /&gt;
*** '''available''': &amp;quot;yes&amp;quot; if the player is in the lobby; &amp;quot;no&amp;quot; if in a game.&lt;br /&gt;
Many of the keys under [game] are described more indepth on the [[ScenarioWML]] page.&lt;br /&gt;
&lt;br /&gt;
== Error messages ==&lt;br /&gt;
&lt;br /&gt;
* '''[error]'''&lt;br /&gt;
** '''message''': The error message.&lt;br /&gt;
** '''password_request''': This is a response to a login attempt. The client needs to send a password on another login attempt.&lt;br /&gt;
** '''force_confirmation''': Confirmation to login even if there is an existing client with the same name. If login is continued then that existing client is getting kicked.&lt;br /&gt;
&lt;br /&gt;
== Chat (lobby and in-game) ==&lt;br /&gt;
&lt;br /&gt;
* '''[message]'''&lt;br /&gt;
** '''sender''': (optional - filled by the server) The sender of the message.&lt;br /&gt;
** '''message''': The message itself.&lt;br /&gt;
** '''room''': The room the message is from/to&lt;br /&gt;
* '''[whisper]'''&lt;br /&gt;
** '''receiver''': The receiver of the whisper&lt;br /&gt;
** '''sender''': (optional - filled by the server) The sender of the whisper.&lt;br /&gt;
** '''message''': The message itself.&lt;br /&gt;
&lt;br /&gt;
== Nickname registration related commands (lobby and in-game) ==&lt;br /&gt;
&lt;br /&gt;
* '''[nickserv]'''&lt;br /&gt;
** '''[info]''': Request info about another username.&lt;br /&gt;
*** '''name''': The username.&lt;br /&gt;
&lt;br /&gt;
== Updating the lobby state ==&lt;br /&gt;
&lt;br /&gt;
* '''[gamelist_diff]''': server message - basically a [[DiffWML|diff]] from two gamelists, which also includes the user list.&lt;br /&gt;
&lt;br /&gt;
* '''[observer]''' or '''[observer_quit]''': server message - players joining([observer_quit] - quitting the lobby &amp;quot;game&amp;quot;)/quitting([observer] - joining the lobby &amp;quot;game&amp;quot;) a game&lt;br /&gt;
** '''name''': Username of the player/observer.&lt;br /&gt;
* '''[refresh_lobby]''': Request the full gamelist.&lt;br /&gt;
&lt;br /&gt;
== Game setup (the phase from creation to start) ==&lt;br /&gt;
To create a game the client sends:&lt;br /&gt;
* '''[create_game]'''&lt;br /&gt;
** '''name''': The title of the game.&lt;br /&gt;
** '''password''': The password to use to join the game.&lt;br /&gt;
** '''ignored''': The list of ignored players from the host.&lt;br /&gt;
** '''auto_hosted''': True if this request is from a bot or a server-side queue, false otherwise.&lt;br /&gt;
** '''queue_type''': Either &amp;quot;normal&amp;quot; or &amp;quot;server_preset&amp;quot;.&lt;br /&gt;
** '''queue_id''': The ID of the queue this game is being created from.&lt;br /&gt;
&lt;br /&gt;
followed by a message with the scenario options as under [game] (see above) plus the scenario data ([time], [era], [side], etc. see [[ScenarioWML]])&lt;br /&gt;
&lt;br /&gt;
* '''[join]'''&lt;br /&gt;
** '''id''': The id of the game.&lt;br /&gt;
** '''observe''': Join the game as an observer.&lt;br /&gt;
&lt;br /&gt;
* '''[scenario_diff]''': [[DiffWML|diff]] of the [[ScenarioWML]] (side changes, etc.)&lt;br /&gt;
&lt;br /&gt;
* '''[start_game]''': sent by the host to start a game&lt;br /&gt;
* '''[leave_game]''': sent by the client when it leaves a game; sent by the server to make a client leave a game&lt;br /&gt;
** '''reason''': optional reason if sent by the server and was initiated by moderator action&lt;br /&gt;
&lt;br /&gt;
== In-game communication ==&lt;br /&gt;
&lt;br /&gt;
Normal scenario communication ([[ReplayWML]]):&lt;br /&gt;
* '''[turn]'''&lt;br /&gt;
** '''[command]''': (repeated) can contain all the tags you can find in a [[ReplayWML|replay]]: [recruit], [move], [end_turn], etc.&lt;br /&gt;
*** '''[speak]'''&lt;br /&gt;
**** '''message''': text of the message&lt;br /&gt;
**** '''id''': the sender&lt;br /&gt;
**** '''team_name''': the name of the team the message is for - empty if it's a public message&lt;br /&gt;
&lt;br /&gt;
Multiplayer specific communication:&lt;br /&gt;
* '''[request_choice]'''&lt;br /&gt;
** '''request_id''': unique ID of the choice request&lt;br /&gt;
** '''[random_seed]''': client requests a random number (used for attacks for example)&lt;br /&gt;
** '''[change_controller_wml]''': change controller request from scenario WML&lt;br /&gt;
*** '''side''': side number&lt;br /&gt;
*** '''old_controller''': old [[SideWML#controller|controller]] value&lt;br /&gt;
*** '''new_controller''': new [[SideWML#controller|controller]] value&lt;br /&gt;
* '''[store_next_scenario]''': sent by the host - the scenario data (see [[ScenarioWML]]) to advance to the next scenario&lt;br /&gt;
* '''[notify_next_scenario]''': sent by the server to tell players that the data for the next scenario is available&lt;br /&gt;
* '''[load_next_scenario]''': sent by the client to request the data for the next scenario&lt;br /&gt;
* '''[next_scenario]''': data for the next scenario (see [[ScenarioWML]]), sent by the server on request&lt;br /&gt;
&lt;br /&gt;
* '''[info]''': sent by the host on game end - info about the game state&lt;br /&gt;
** '''type''': &amp;quot;termination&amp;quot; &lt;br /&gt;
** '''condition''': the termination reason&lt;br /&gt;
&lt;br /&gt;
If a player leaves this is sent to the host for all sides he owned.&lt;br /&gt;
* '''side_drop''': The number of a side that dropped because a player left.&lt;br /&gt;
* '''controller''': The controller of that side. (&amp;quot;ai&amp;quot;, &amp;quot;network&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
Client commands:&lt;br /&gt;
* '''[change_controller]''': a player (un)droids one of his sides or assigns control to someone else (The host can assign control for any side.)&lt;br /&gt;
** '''side''': the side to change controller&lt;br /&gt;
** '''player''': the nickname of the player to take control&lt;br /&gt;
** '''controller''': the new controller: &amp;quot;human&amp;quot; or &amp;quot;human_ai&amp;quot;&lt;br /&gt;
** '''own_side''': &amp;quot;yes&amp;quot;&lt;br /&gt;
* '''[muteall]''': the host mutes/unmutes all observers - toggles&lt;br /&gt;
* '''[mute]''': the host mutes an observer - toggles&lt;br /&gt;
** '''username''': the username of the observer - if not specified the servers returns a list of muted usernames&lt;br /&gt;
* '''[kick]''' or '''[ban]''': the host kicks/bans a player/observer&lt;br /&gt;
** '''username''': the username of the player/observer&lt;br /&gt;
&lt;br /&gt;
== Game history ==&lt;br /&gt;
This is a request to query a set of 11 rows of game history data based on the provided search criteria. The official client calls this from the Match History button in the  multiplayer lobby to display 10 rows of data. The 11th row is used as a flag to indicate whether there is more data to be queried or not via the right/left arrows on the dialog.&lt;br /&gt;
&lt;br /&gt;
* '''[game_history_request]'''&lt;br /&gt;
** '''offset''': where in the result set to start returning data from. If there are 50 results and offset 10 is given, then rows 10-21 will be returned.&lt;br /&gt;
** '''search_player''': the forum username of the player to search for.&lt;br /&gt;
** '''search_game_name''': the name of the game to filter results by. Can use the * (matches any character before or after it's used) and _ (matches any single character) wildcards.&lt;br /&gt;
** '''search_content_type''': the type of content to filter by. Must be one of:&lt;br /&gt;
*** '''0''': scenario&lt;br /&gt;
*** '''1''': era&lt;br /&gt;
*** '''2''':modification&lt;br /&gt;
** '''search_content''': The content to filter by. This is the ID of the content, not the name displayed on the UI, due to the translated name getting stored in the database.&lt;br /&gt;
&lt;br /&gt;
== Queues ==&lt;br /&gt;
Queue info sent to the client on join or when the server's config is reloaded and the queue information has changed:&lt;br /&gt;
* '''[queue_update]'''&lt;br /&gt;
** '''queue_id''': The server's unique ID for the queue.&lt;br /&gt;
** '''action''': One of add/update/remove.&lt;br /&gt;
** '''display_name''': The text to show in the list of queues in the lobby. Only used by add/update.&lt;br /&gt;
** '''players_required''': How many players are required before a game is started. Only used by add/update.&lt;br /&gt;
&lt;br /&gt;
When there are enough players to start a game, the last player to join the queue is chosen as the host and their client is told to create the game with the provided settings. This skips the game creation screen and goes straight to the staging screen. The other players in the queue are then told to join that game using the normal [join] command:&lt;br /&gt;
* '''[create_game]'''&lt;br /&gt;
** '''queue_id''': The ID of the queue to create the game for.&lt;br /&gt;
** '''[game]'''&lt;br /&gt;
*** '''scenario''': The ID of the scenario to create the game for.&lt;br /&gt;
*** '''era''': The ID of the era to use.&lt;br /&gt;
*** '''fog''': Whether to have fog enabled.&lt;br /&gt;
*** '''shroud''': Whether to have shroud enabled.&lt;br /&gt;
*** '''village_gold''': How much gold each village provides.&lt;br /&gt;
*** '''village_support''': How much unit support each village provides&lt;br /&gt;
*** '''experience_modifier''': The experience modifier to use.&lt;br /&gt;
*** '''countdown''': Not currently used, set to false.&lt;br /&gt;
*** '''random_start_time''': Whether to start at a random time of day.&lt;br /&gt;
*** '''shuffle_sides''': Whether to shuffle the sides' starting positions.&lt;br /&gt;
&lt;br /&gt;
== Administrative commands ==&lt;br /&gt;
* '''[query]'''&lt;br /&gt;
** '''type''': The type of query. See [[ServerAdministration]] for details.&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
[https://github.com/renom/fastbot fastbot] -  the bot for tournaments which implements the protocol, can log in into the lobby and host games. Written in Go. &lt;br /&gt;
[[Category:WML Reference]]&lt;br /&gt;
[[Category:Server Documentation]]&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=MultiplayerServerWML&amp;diff=74860</id>
		<title>MultiplayerServerWML</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=MultiplayerServerWML&amp;diff=74860"/>
		<updated>2026-02-22T15:14:33Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: /* Queues */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page describes the [[WML]] used to communicate with the multiplayer server for Wesnoth, [[wesnothd]].&lt;br /&gt;
&lt;br /&gt;
== The handshake ==&lt;br /&gt;
&lt;br /&gt;
The client sends four bytes, then the server replies with four bytes. To get a new connection number, the client will send these four bytes: 0x00 0x00 0x00 0x00. The server then sends back the connection number (wesnothd calls this number the &amp;quot;socket number&amp;quot;). Since 1.13+ the server no longer is using socket numbers to keep track of clients and always sends the same number to them all. Since 1.15+ client can also send 0x00 0x00 0x00 0x01 instead to request entire connection to be [https://github.com/wesnoth/wesnoth/blob/2f8136951cd77526188cf8d0fb2cf21eaa2ebe63/src/server/common/server_base.hpp#L60-L76 encapsulated in TLS] immediately '''after'''. If the handshake is successful, the server will be the first to send a data package. All packages are in [http://en.wikipedia.org/wiki/Gzip gzip] format and are preceded by four bytes that specify the size of the package to come in '''big-endian''' (network byte order). Below you'll find information about what data the (unzipped) packages contain. Unpacked WML uses utf-8 charset.&lt;br /&gt;
&lt;br /&gt;
== The login procedure ==&lt;br /&gt;
&lt;br /&gt;
* server request (optional)&lt;br /&gt;
** '''[version]'''&lt;br /&gt;
&lt;br /&gt;
* client response&lt;br /&gt;
** '''[version]'''&lt;br /&gt;
*** '''version''': The client's version string.&lt;br /&gt;
*** '''client_source''': The client's distribution info. (Steam, SourceForge, App Store, etc.)&lt;br /&gt;
&lt;br /&gt;
* server response (if the server does not accept this version)&lt;br /&gt;
** '''[redirect]'''&lt;br /&gt;
*** '''host''': The host you should connect to.&lt;br /&gt;
*** '''port''': The port you should connect to.&lt;br /&gt;
*** '''version''': A comma-separated list of globs that this server should accept (e.g. &amp;quot;1.0*,1.2*,1.4*,1.7*,1.8*&amp;quot;)&lt;br /&gt;
** or '''[reject]''' (if the version is unknown)&lt;br /&gt;
*** '''accepted_versions''': A comma-separated list of globs that this server does accept&lt;br /&gt;
&lt;br /&gt;
* server request&lt;br /&gt;
** '''[mustlogin]'''&lt;br /&gt;
&lt;br /&gt;
* client response&lt;br /&gt;
** '''[login]'''&lt;br /&gt;
*** '''username''': The username the client would like to have.&lt;br /&gt;
*** '''password''': The hashed password, created from the password and salt received from the server. More information about how this password is being generated, including a real world example, can be found in the file [http://forum.wesnoth.org/download/file.php?id=41145 HashedPasswords.pdf] (885 KiB). Since version 1.15+ if TLS was successfully established before then password will be passed as is, without hashing, relying on TLS for secrecy. Passing password hashes is no longer supported to free the client from responsibility to support all hash schemes the forum can potentially use. Client will emit error instead of trying to send password if TLS wasn't established.&lt;br /&gt;
&lt;br /&gt;
* server response&lt;br /&gt;
** '''[join_lobby]'''&lt;br /&gt;
*** '''is_moderator''': &amp;quot;yes&amp;quot; if the user is a moderator, &amp;quot;no&amp;quot; otherwise.&lt;br /&gt;
*** '''profile_url_prefix''': The external URL prefix for player profiles (empty if the server doesn't have an attached database)&lt;br /&gt;
** or '''[error]''' (server is waiting for another '''[login]''' message now)&lt;br /&gt;
*** '''message''': The error message.&lt;br /&gt;
*** '''password_request''': If not empty the server asks the client to provide a password for its desired username.&lt;br /&gt;
*** '''phpbb_encryption''': If &amp;quot;yes&amp;quot; the client will encrypt the password using phpbb's algorithm.&lt;br /&gt;
*** '''random_salt''': Random salt sent to the client for mixing with the password hash.&lt;br /&gt;
*** '''hash_seed''': Salt generated from the original hash that is required to recreate it.&lt;br /&gt;
*** '''salt''': Salt generated from the original hash that is required to recreate it.&lt;br /&gt;
*** '''force_confirmation''': Display an ok/cancel dialog with the content of the 'message' key.&lt;br /&gt;
&lt;br /&gt;
* server response&lt;br /&gt;
** '''[gamelist]'''&lt;br /&gt;
*** '''[game]''' (repeated)&lt;br /&gt;
**** '''id''': A unique id of the game.&lt;br /&gt;
**** '''name''': The title of the game.&lt;br /&gt;
**** '''mp_scenario''': The id of the scenario.&lt;br /&gt;
**** '''mp_era''': The id of the used era.&lt;br /&gt;
**** '''mp_use_map_settings''': Does the game use the map settings specified in the scenario.&lt;br /&gt;
**** '''mp_fog''': Does the game use fog.&lt;br /&gt;
**** '''mp_shroud''': Does the game use shroud.&lt;br /&gt;
**** '''mp_village_gold''': The number of gold per village.&lt;br /&gt;
**** '''experience_modifier''': The experience setting.&lt;br /&gt;
**** '''mp_countdown''': Does the game use a timer.&lt;br /&gt;
**** '''mp_countdown_reservoir_time''': Upper limit of the possibly available time.&lt;br /&gt;
**** '''mp_countdown_init_time''': Initial time.&lt;br /&gt;
**** '''mp_countdown_action_bonus''': Time bonus per action.&lt;br /&gt;
**** '''mp_countdown_turn_bonus''': Time bonus per turn.&lt;br /&gt;
**** '''map_data''': The map data. ''Notice: not sent to lobby if the game uses shroud''&lt;br /&gt;
**** '''hash''': The hash value of the map_data.&lt;br /&gt;
**** '''observer''': Are observers allowed or not.&lt;br /&gt;
**** '''human_sides''': The number of sides played by humans.&lt;br /&gt;
**** '''slots''': The number of vacant/max slots.&lt;br /&gt;
**** '''[slot_data]''' replaces '''slots''' since {{DevFeature1.13|12}}&lt;br /&gt;
***** '''max''': The number of total slots.&lt;br /&gt;
***** '''vacant''': The number of vacant slots.&lt;br /&gt;
**** '''turn''': The current turn/max turn.&lt;br /&gt;
**** '''[turn_data]''' replaces '''turn''' since {{DevFeature1.13|12}}&lt;br /&gt;
***** '''current''': The current turn number.&lt;br /&gt;
***** '''max''': The total number of turns.&lt;br /&gt;
**** '''[modification]''' Modifications used in this game. See [[ModificationWML]].&lt;br /&gt;
***** '''id''': ID of the modification.&lt;br /&gt;
***** '''name''': Name of the modification.&lt;br /&gt;
***** '''addon_id''': ID of the addon the modification is from.&lt;br /&gt;
***** '''require_modification''': A boolean value; if set to yes, all players have to have this modification installed to join the game.&lt;br /&gt;
**** '''[options]''' Options selected for this game. See [[OptionWML]].&lt;br /&gt;
***** '''[campaign|era|modification|multiplayer]'''&lt;br /&gt;
****** '''id''': ID of the addon the campaign|era|modification|multiplayer (scenario) is from.&lt;br /&gt;
****** '''[option]'''&lt;br /&gt;
******* '''id''': ID of the option.&lt;br /&gt;
******* '''value''': Value of the option.&lt;br /&gt;
** '''[user]''' (repeated)&lt;br /&gt;
*** '''name''': The username of the player.&lt;br /&gt;
*** '''game_id''': The ID of the game the player is in.&lt;br /&gt;
*** '''location''': The name of the game the player is in.&lt;br /&gt;
*** '''available''': &amp;quot;yes&amp;quot; if the player is in the lobby; &amp;quot;no&amp;quot; if in a game.&lt;br /&gt;
Many of the keys under [game] are described more indepth on the [[ScenarioWML]] page.&lt;br /&gt;
&lt;br /&gt;
== Error messages ==&lt;br /&gt;
&lt;br /&gt;
* '''[error]'''&lt;br /&gt;
** '''message''': The error message.&lt;br /&gt;
** '''password_request''': This is a response to a login attempt. The client needs to send a password on another login attempt.&lt;br /&gt;
** '''force_confirmation''': Confirmation to login even if there is an existing client with the same name. If login is continued then that existing client is getting kicked.&lt;br /&gt;
&lt;br /&gt;
== Chat (lobby and in-game) ==&lt;br /&gt;
&lt;br /&gt;
* '''[message]'''&lt;br /&gt;
** '''sender''': (optional - filled by the server) The sender of the message.&lt;br /&gt;
** '''message''': The message itself.&lt;br /&gt;
** '''room''': The room the message is from/to&lt;br /&gt;
* '''[whisper]'''&lt;br /&gt;
** '''receiver''': The receiver of the whisper&lt;br /&gt;
** '''sender''': (optional - filled by the server) The sender of the whisper.&lt;br /&gt;
** '''message''': The message itself.&lt;br /&gt;
&lt;br /&gt;
== Nickname registration related commands (lobby and in-game) ==&lt;br /&gt;
&lt;br /&gt;
* '''[nickserv]'''&lt;br /&gt;
** '''[info]''': Request info about another username.&lt;br /&gt;
*** '''name''': The username.&lt;br /&gt;
&lt;br /&gt;
== Updating the lobby state ==&lt;br /&gt;
&lt;br /&gt;
* '''[gamelist_diff]''': server message - basically a [[DiffWML|diff]] from two gamelists, which also includes the user list.&lt;br /&gt;
&lt;br /&gt;
* '''[observer]''' or '''[observer_quit]''': server message - players joining([observer_quit] - quitting the lobby &amp;quot;game&amp;quot;)/quitting([observer] - joining the lobby &amp;quot;game&amp;quot;) a game&lt;br /&gt;
** '''name''': Username of the player/observer.&lt;br /&gt;
* '''[refresh_lobby]''': Request the full gamelist.&lt;br /&gt;
&lt;br /&gt;
== Game setup (the phase from creation to start) ==&lt;br /&gt;
To create a game the client sends:&lt;br /&gt;
* '''[create_game]'''&lt;br /&gt;
** '''name''': The title of the game.&lt;br /&gt;
** '''password''': The password to use to join the game.&lt;br /&gt;
** '''ignored''': The list of ignored players from the host.&lt;br /&gt;
** '''auto_hosted''': True if this request is from a bot, false otherwise.&lt;br /&gt;
&lt;br /&gt;
followed by a message with the scenario options as under [game] (see above) plus the scenario data ([time], [era], [side], etc. see [[ScenarioWML]])&lt;br /&gt;
&lt;br /&gt;
* '''[join]'''&lt;br /&gt;
** '''id''': The id of the game.&lt;br /&gt;
** '''observe''': Join the game as an observer.&lt;br /&gt;
&lt;br /&gt;
* '''[scenario_diff]''': [[DiffWML|diff]] of the [[ScenarioWML]] (side changes, etc.)&lt;br /&gt;
&lt;br /&gt;
* '''[start_game]''': sent by the host to start a game&lt;br /&gt;
* '''[leave_game]''': sent by the client when it leaves a game; sent by the server to make a client leave a game&lt;br /&gt;
** '''reason''': optional reason if sent by the server and was initiated by moderator action&lt;br /&gt;
&lt;br /&gt;
== In-game communication ==&lt;br /&gt;
&lt;br /&gt;
Normal scenario communication ([[ReplayWML]]):&lt;br /&gt;
* '''[turn]'''&lt;br /&gt;
** '''[command]''': (repeated) can contain all the tags you can find in a [[ReplayWML|replay]]: [recruit], [move], [end_turn], etc.&lt;br /&gt;
*** '''[speak]'''&lt;br /&gt;
**** '''message''': text of the message&lt;br /&gt;
**** '''id''': the sender&lt;br /&gt;
**** '''team_name''': the name of the team the message is for - empty if it's a public message&lt;br /&gt;
&lt;br /&gt;
Multiplayer specific communication:&lt;br /&gt;
* '''[request_choice]'''&lt;br /&gt;
** '''request_id''': unique ID of the choice request&lt;br /&gt;
** '''[random_seed]''': client requests a random number (used for attacks for example)&lt;br /&gt;
** '''[change_controller_wml]''': change controller request from scenario WML&lt;br /&gt;
*** '''side''': side number&lt;br /&gt;
*** '''old_controller''': old [[SideWML#controller|controller]] value&lt;br /&gt;
*** '''new_controller''': new [[SideWML#controller|controller]] value&lt;br /&gt;
* '''[store_next_scenario]''': sent by the host - the scenario data (see [[ScenarioWML]]) to advance to the next scenario&lt;br /&gt;
* '''[notify_next_scenario]''': sent by the server to tell players that the data for the next scenario is available&lt;br /&gt;
* '''[load_next_scenario]''': sent by the client to request the data for the next scenario&lt;br /&gt;
* '''[next_scenario]''': data for the next scenario (see [[ScenarioWML]]), sent by the server on request&lt;br /&gt;
&lt;br /&gt;
* '''[info]''': sent by the host on game end - info about the game state&lt;br /&gt;
** '''type''': &amp;quot;termination&amp;quot; &lt;br /&gt;
** '''condition''': the termination reason&lt;br /&gt;
&lt;br /&gt;
If a player leaves this is sent to the host for all sides he owned.&lt;br /&gt;
* '''side_drop''': The number of a side that dropped because a player left.&lt;br /&gt;
* '''controller''': The controller of that side. (&amp;quot;ai&amp;quot;, &amp;quot;network&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
Client commands:&lt;br /&gt;
* '''[change_controller]''': a player (un)droids one of his sides or assigns control to someone else (The host can assign control for any side.)&lt;br /&gt;
** '''side''': the side to change controller&lt;br /&gt;
** '''player''': the nickname of the player to take control&lt;br /&gt;
** '''controller''': the new controller: &amp;quot;human&amp;quot; or &amp;quot;human_ai&amp;quot;&lt;br /&gt;
** '''own_side''': &amp;quot;yes&amp;quot;&lt;br /&gt;
* '''[muteall]''': the host mutes/unmutes all observers - toggles&lt;br /&gt;
* '''[mute]''': the host mutes an observer - toggles&lt;br /&gt;
** '''username''': the username of the observer - if not specified the servers returns a list of muted usernames&lt;br /&gt;
* '''[kick]''' or '''[ban]''': the host kicks/bans a player/observer&lt;br /&gt;
** '''username''': the username of the player/observer&lt;br /&gt;
&lt;br /&gt;
== Game history ==&lt;br /&gt;
This is a request to query a set of 11 rows of game history data based on the provided search criteria. The official client calls this from the Match History button in the  multiplayer lobby to display 10 rows of data. The 11th row is used as a flag to indicate whether there is more data to be queried or not via the right/left arrows on the dialog.&lt;br /&gt;
&lt;br /&gt;
* '''[game_history_request]'''&lt;br /&gt;
** '''offset''': where in the result set to start returning data from. If there are 50 results and offset 10 is given, then rows 10-21 will be returned.&lt;br /&gt;
** '''search_player''': the forum username of the player to search for.&lt;br /&gt;
** '''search_game_name''': the name of the game to filter results by. Can use the * (matches any character before or after it's used) and _ (matches any single character) wildcards.&lt;br /&gt;
** '''search_content_type''': the type of content to filter by. Must be one of:&lt;br /&gt;
*** '''0''': scenario&lt;br /&gt;
*** '''1''': era&lt;br /&gt;
*** '''2''':modification&lt;br /&gt;
** '''search_content''': The content to filter by. This is the ID of the content, not the name displayed on the UI, due to the translated name getting stored in the database.&lt;br /&gt;
&lt;br /&gt;
== Queues ==&lt;br /&gt;
Queue info sent to the client on join or when the server's config is reloaded and the queue information has changed:&lt;br /&gt;
* '''[queue_update]'''&lt;br /&gt;
** '''queue_id''': The server's unique ID for the queue.&lt;br /&gt;
** '''action''': One of add/update/remove.&lt;br /&gt;
** '''display_name''': The text to show in the list of queues in the lobby. Only used by add/update.&lt;br /&gt;
** '''players_required''': How many players are required before a game is started. Only used by add/update.&lt;br /&gt;
&lt;br /&gt;
When there are enough players to start a game, the last player to join the queue is chosen as the host and their client is told to create the game with the provided settings. This skips the game creation screen and goes straight to the staging screen. The other players in the queue are then told to join that game using the normal [join] command:&lt;br /&gt;
* '''[create_game]'''&lt;br /&gt;
** '''queue_id''': The ID of the queue to create the game for.&lt;br /&gt;
** '''[game]'''&lt;br /&gt;
*** '''scenario''': The ID of the scenario to create the game for.&lt;br /&gt;
*** '''era''': The ID of the era to use.&lt;br /&gt;
*** '''fog''': Whether to have fog enabled.&lt;br /&gt;
*** '''shroud''': Whether to have shroud enabled.&lt;br /&gt;
*** '''village_gold''': How much gold each village provides.&lt;br /&gt;
*** '''village_support''': How much unit support each village provides&lt;br /&gt;
*** '''experience_modifier''': The experience modifier to use.&lt;br /&gt;
*** '''countdown''': Not currently used, set to false.&lt;br /&gt;
*** '''random_start_time''': Whether to start at a random time of day.&lt;br /&gt;
*** '''shuffle_sides''': Whether to shuffle the sides' starting positions.&lt;br /&gt;
&lt;br /&gt;
== Administrative commands ==&lt;br /&gt;
* '''[query]'''&lt;br /&gt;
** '''type''': The type of query. See [[ServerAdministration]] for details.&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
[https://github.com/renom/fastbot fastbot] -  the bot for tournaments which implements the protocol, can log in into the lobby and host games. Written in Go. &lt;br /&gt;
[[Category:WML Reference]]&lt;br /&gt;
[[Category:Server Documentation]]&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=MultiplayerServerWML&amp;diff=74859</id>
		<title>MultiplayerServerWML</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=MultiplayerServerWML&amp;diff=74859"/>
		<updated>2026-02-22T15:13:08Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: /* Queues */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page describes the [[WML]] used to communicate with the multiplayer server for Wesnoth, [[wesnothd]].&lt;br /&gt;
&lt;br /&gt;
== The handshake ==&lt;br /&gt;
&lt;br /&gt;
The client sends four bytes, then the server replies with four bytes. To get a new connection number, the client will send these four bytes: 0x00 0x00 0x00 0x00. The server then sends back the connection number (wesnothd calls this number the &amp;quot;socket number&amp;quot;). Since 1.13+ the server no longer is using socket numbers to keep track of clients and always sends the same number to them all. Since 1.15+ client can also send 0x00 0x00 0x00 0x01 instead to request entire connection to be [https://github.com/wesnoth/wesnoth/blob/2f8136951cd77526188cf8d0fb2cf21eaa2ebe63/src/server/common/server_base.hpp#L60-L76 encapsulated in TLS] immediately '''after'''. If the handshake is successful, the server will be the first to send a data package. All packages are in [http://en.wikipedia.org/wiki/Gzip gzip] format and are preceded by four bytes that specify the size of the package to come in '''big-endian''' (network byte order). Below you'll find information about what data the (unzipped) packages contain. Unpacked WML uses utf-8 charset.&lt;br /&gt;
&lt;br /&gt;
== The login procedure ==&lt;br /&gt;
&lt;br /&gt;
* server request (optional)&lt;br /&gt;
** '''[version]'''&lt;br /&gt;
&lt;br /&gt;
* client response&lt;br /&gt;
** '''[version]'''&lt;br /&gt;
*** '''version''': The client's version string.&lt;br /&gt;
*** '''client_source''': The client's distribution info. (Steam, SourceForge, App Store, etc.)&lt;br /&gt;
&lt;br /&gt;
* server response (if the server does not accept this version)&lt;br /&gt;
** '''[redirect]'''&lt;br /&gt;
*** '''host''': The host you should connect to.&lt;br /&gt;
*** '''port''': The port you should connect to.&lt;br /&gt;
*** '''version''': A comma-separated list of globs that this server should accept (e.g. &amp;quot;1.0*,1.2*,1.4*,1.7*,1.8*&amp;quot;)&lt;br /&gt;
** or '''[reject]''' (if the version is unknown)&lt;br /&gt;
*** '''accepted_versions''': A comma-separated list of globs that this server does accept&lt;br /&gt;
&lt;br /&gt;
* server request&lt;br /&gt;
** '''[mustlogin]'''&lt;br /&gt;
&lt;br /&gt;
* client response&lt;br /&gt;
** '''[login]'''&lt;br /&gt;
*** '''username''': The username the client would like to have.&lt;br /&gt;
*** '''password''': The hashed password, created from the password and salt received from the server. More information about how this password is being generated, including a real world example, can be found in the file [http://forum.wesnoth.org/download/file.php?id=41145 HashedPasswords.pdf] (885 KiB). Since version 1.15+ if TLS was successfully established before then password will be passed as is, without hashing, relying on TLS for secrecy. Passing password hashes is no longer supported to free the client from responsibility to support all hash schemes the forum can potentially use. Client will emit error instead of trying to send password if TLS wasn't established.&lt;br /&gt;
&lt;br /&gt;
* server response&lt;br /&gt;
** '''[join_lobby]'''&lt;br /&gt;
*** '''is_moderator''': &amp;quot;yes&amp;quot; if the user is a moderator, &amp;quot;no&amp;quot; otherwise.&lt;br /&gt;
*** '''profile_url_prefix''': The external URL prefix for player profiles (empty if the server doesn't have an attached database)&lt;br /&gt;
** or '''[error]''' (server is waiting for another '''[login]''' message now)&lt;br /&gt;
*** '''message''': The error message.&lt;br /&gt;
*** '''password_request''': If not empty the server asks the client to provide a password for its desired username.&lt;br /&gt;
*** '''phpbb_encryption''': If &amp;quot;yes&amp;quot; the client will encrypt the password using phpbb's algorithm.&lt;br /&gt;
*** '''random_salt''': Random salt sent to the client for mixing with the password hash.&lt;br /&gt;
*** '''hash_seed''': Salt generated from the original hash that is required to recreate it.&lt;br /&gt;
*** '''salt''': Salt generated from the original hash that is required to recreate it.&lt;br /&gt;
*** '''force_confirmation''': Display an ok/cancel dialog with the content of the 'message' key.&lt;br /&gt;
&lt;br /&gt;
* server response&lt;br /&gt;
** '''[gamelist]'''&lt;br /&gt;
*** '''[game]''' (repeated)&lt;br /&gt;
**** '''id''': A unique id of the game.&lt;br /&gt;
**** '''name''': The title of the game.&lt;br /&gt;
**** '''mp_scenario''': The id of the scenario.&lt;br /&gt;
**** '''mp_era''': The id of the used era.&lt;br /&gt;
**** '''mp_use_map_settings''': Does the game use the map settings specified in the scenario.&lt;br /&gt;
**** '''mp_fog''': Does the game use fog.&lt;br /&gt;
**** '''mp_shroud''': Does the game use shroud.&lt;br /&gt;
**** '''mp_village_gold''': The number of gold per village.&lt;br /&gt;
**** '''experience_modifier''': The experience setting.&lt;br /&gt;
**** '''mp_countdown''': Does the game use a timer.&lt;br /&gt;
**** '''mp_countdown_reservoir_time''': Upper limit of the possibly available time.&lt;br /&gt;
**** '''mp_countdown_init_time''': Initial time.&lt;br /&gt;
**** '''mp_countdown_action_bonus''': Time bonus per action.&lt;br /&gt;
**** '''mp_countdown_turn_bonus''': Time bonus per turn.&lt;br /&gt;
**** '''map_data''': The map data. ''Notice: not sent to lobby if the game uses shroud''&lt;br /&gt;
**** '''hash''': The hash value of the map_data.&lt;br /&gt;
**** '''observer''': Are observers allowed or not.&lt;br /&gt;
**** '''human_sides''': The number of sides played by humans.&lt;br /&gt;
**** '''slots''': The number of vacant/max slots.&lt;br /&gt;
**** '''[slot_data]''' replaces '''slots''' since {{DevFeature1.13|12}}&lt;br /&gt;
***** '''max''': The number of total slots.&lt;br /&gt;
***** '''vacant''': The number of vacant slots.&lt;br /&gt;
**** '''turn''': The current turn/max turn.&lt;br /&gt;
**** '''[turn_data]''' replaces '''turn''' since {{DevFeature1.13|12}}&lt;br /&gt;
***** '''current''': The current turn number.&lt;br /&gt;
***** '''max''': The total number of turns.&lt;br /&gt;
**** '''[modification]''' Modifications used in this game. See [[ModificationWML]].&lt;br /&gt;
***** '''id''': ID of the modification.&lt;br /&gt;
***** '''name''': Name of the modification.&lt;br /&gt;
***** '''addon_id''': ID of the addon the modification is from.&lt;br /&gt;
***** '''require_modification''': A boolean value; if set to yes, all players have to have this modification installed to join the game.&lt;br /&gt;
**** '''[options]''' Options selected for this game. See [[OptionWML]].&lt;br /&gt;
***** '''[campaign|era|modification|multiplayer]'''&lt;br /&gt;
****** '''id''': ID of the addon the campaign|era|modification|multiplayer (scenario) is from.&lt;br /&gt;
****** '''[option]'''&lt;br /&gt;
******* '''id''': ID of the option.&lt;br /&gt;
******* '''value''': Value of the option.&lt;br /&gt;
** '''[user]''' (repeated)&lt;br /&gt;
*** '''name''': The username of the player.&lt;br /&gt;
*** '''game_id''': The ID of the game the player is in.&lt;br /&gt;
*** '''location''': The name of the game the player is in.&lt;br /&gt;
*** '''available''': &amp;quot;yes&amp;quot; if the player is in the lobby; &amp;quot;no&amp;quot; if in a game.&lt;br /&gt;
Many of the keys under [game] are described more indepth on the [[ScenarioWML]] page.&lt;br /&gt;
&lt;br /&gt;
== Error messages ==&lt;br /&gt;
&lt;br /&gt;
* '''[error]'''&lt;br /&gt;
** '''message''': The error message.&lt;br /&gt;
** '''password_request''': This is a response to a login attempt. The client needs to send a password on another login attempt.&lt;br /&gt;
** '''force_confirmation''': Confirmation to login even if there is an existing client with the same name. If login is continued then that existing client is getting kicked.&lt;br /&gt;
&lt;br /&gt;
== Chat (lobby and in-game) ==&lt;br /&gt;
&lt;br /&gt;
* '''[message]'''&lt;br /&gt;
** '''sender''': (optional - filled by the server) The sender of the message.&lt;br /&gt;
** '''message''': The message itself.&lt;br /&gt;
** '''room''': The room the message is from/to&lt;br /&gt;
* '''[whisper]'''&lt;br /&gt;
** '''receiver''': The receiver of the whisper&lt;br /&gt;
** '''sender''': (optional - filled by the server) The sender of the whisper.&lt;br /&gt;
** '''message''': The message itself.&lt;br /&gt;
&lt;br /&gt;
== Nickname registration related commands (lobby and in-game) ==&lt;br /&gt;
&lt;br /&gt;
* '''[nickserv]'''&lt;br /&gt;
** '''[info]''': Request info about another username.&lt;br /&gt;
*** '''name''': The username.&lt;br /&gt;
&lt;br /&gt;
== Updating the lobby state ==&lt;br /&gt;
&lt;br /&gt;
* '''[gamelist_diff]''': server message - basically a [[DiffWML|diff]] from two gamelists, which also includes the user list.&lt;br /&gt;
&lt;br /&gt;
* '''[observer]''' or '''[observer_quit]''': server message - players joining([observer_quit] - quitting the lobby &amp;quot;game&amp;quot;)/quitting([observer] - joining the lobby &amp;quot;game&amp;quot;) a game&lt;br /&gt;
** '''name''': Username of the player/observer.&lt;br /&gt;
* '''[refresh_lobby]''': Request the full gamelist.&lt;br /&gt;
&lt;br /&gt;
== Game setup (the phase from creation to start) ==&lt;br /&gt;
To create a game the client sends:&lt;br /&gt;
* '''[create_game]'''&lt;br /&gt;
** '''name''': The title of the game.&lt;br /&gt;
** '''password''': The password to use to join the game.&lt;br /&gt;
** '''ignored''': The list of ignored players from the host.&lt;br /&gt;
** '''auto_hosted''': True if this request is from a bot, false otherwise.&lt;br /&gt;
&lt;br /&gt;
followed by a message with the scenario options as under [game] (see above) plus the scenario data ([time], [era], [side], etc. see [[ScenarioWML]])&lt;br /&gt;
&lt;br /&gt;
* '''[join]'''&lt;br /&gt;
** '''id''': The id of the game.&lt;br /&gt;
** '''observe''': Join the game as an observer.&lt;br /&gt;
&lt;br /&gt;
* '''[scenario_diff]''': [[DiffWML|diff]] of the [[ScenarioWML]] (side changes, etc.)&lt;br /&gt;
&lt;br /&gt;
* '''[start_game]''': sent by the host to start a game&lt;br /&gt;
* '''[leave_game]''': sent by the client when it leaves a game; sent by the server to make a client leave a game&lt;br /&gt;
** '''reason''': optional reason if sent by the server and was initiated by moderator action&lt;br /&gt;
&lt;br /&gt;
== In-game communication ==&lt;br /&gt;
&lt;br /&gt;
Normal scenario communication ([[ReplayWML]]):&lt;br /&gt;
* '''[turn]'''&lt;br /&gt;
** '''[command]''': (repeated) can contain all the tags you can find in a [[ReplayWML|replay]]: [recruit], [move], [end_turn], etc.&lt;br /&gt;
*** '''[speak]'''&lt;br /&gt;
**** '''message''': text of the message&lt;br /&gt;
**** '''id''': the sender&lt;br /&gt;
**** '''team_name''': the name of the team the message is for - empty if it's a public message&lt;br /&gt;
&lt;br /&gt;
Multiplayer specific communication:&lt;br /&gt;
* '''[request_choice]'''&lt;br /&gt;
** '''request_id''': unique ID of the choice request&lt;br /&gt;
** '''[random_seed]''': client requests a random number (used for attacks for example)&lt;br /&gt;
** '''[change_controller_wml]''': change controller request from scenario WML&lt;br /&gt;
*** '''side''': side number&lt;br /&gt;
*** '''old_controller''': old [[SideWML#controller|controller]] value&lt;br /&gt;
*** '''new_controller''': new [[SideWML#controller|controller]] value&lt;br /&gt;
* '''[store_next_scenario]''': sent by the host - the scenario data (see [[ScenarioWML]]) to advance to the next scenario&lt;br /&gt;
* '''[notify_next_scenario]''': sent by the server to tell players that the data for the next scenario is available&lt;br /&gt;
* '''[load_next_scenario]''': sent by the client to request the data for the next scenario&lt;br /&gt;
* '''[next_scenario]''': data for the next scenario (see [[ScenarioWML]]), sent by the server on request&lt;br /&gt;
&lt;br /&gt;
* '''[info]''': sent by the host on game end - info about the game state&lt;br /&gt;
** '''type''': &amp;quot;termination&amp;quot; &lt;br /&gt;
** '''condition''': the termination reason&lt;br /&gt;
&lt;br /&gt;
If a player leaves this is sent to the host for all sides he owned.&lt;br /&gt;
* '''side_drop''': The number of a side that dropped because a player left.&lt;br /&gt;
* '''controller''': The controller of that side. (&amp;quot;ai&amp;quot;, &amp;quot;network&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
Client commands:&lt;br /&gt;
* '''[change_controller]''': a player (un)droids one of his sides or assigns control to someone else (The host can assign control for any side.)&lt;br /&gt;
** '''side''': the side to change controller&lt;br /&gt;
** '''player''': the nickname of the player to take control&lt;br /&gt;
** '''controller''': the new controller: &amp;quot;human&amp;quot; or &amp;quot;human_ai&amp;quot;&lt;br /&gt;
** '''own_side''': &amp;quot;yes&amp;quot;&lt;br /&gt;
* '''[muteall]''': the host mutes/unmutes all observers - toggles&lt;br /&gt;
* '''[mute]''': the host mutes an observer - toggles&lt;br /&gt;
** '''username''': the username of the observer - if not specified the servers returns a list of muted usernames&lt;br /&gt;
* '''[kick]''' or '''[ban]''': the host kicks/bans a player/observer&lt;br /&gt;
** '''username''': the username of the player/observer&lt;br /&gt;
&lt;br /&gt;
== Game history ==&lt;br /&gt;
This is a request to query a set of 11 rows of game history data based on the provided search criteria. The official client calls this from the Match History button in the  multiplayer lobby to display 10 rows of data. The 11th row is used as a flag to indicate whether there is more data to be queried or not via the right/left arrows on the dialog.&lt;br /&gt;
&lt;br /&gt;
* '''[game_history_request]'''&lt;br /&gt;
** '''offset''': where in the result set to start returning data from. If there are 50 results and offset 10 is given, then rows 10-21 will be returned.&lt;br /&gt;
** '''search_player''': the forum username of the player to search for.&lt;br /&gt;
** '''search_game_name''': the name of the game to filter results by. Can use the * (matches any character before or after it's used) and _ (matches any single character) wildcards.&lt;br /&gt;
** '''search_content_type''': the type of content to filter by. Must be one of:&lt;br /&gt;
*** '''0''': scenario&lt;br /&gt;
*** '''1''': era&lt;br /&gt;
*** '''2''':modification&lt;br /&gt;
** '''search_content''': The content to filter by. This is the ID of the content, not the name displayed on the UI, due to the translated name getting stored in the database.&lt;br /&gt;
&lt;br /&gt;
== Queues ==&lt;br /&gt;
Queue info sent to the client on join or when the server's config is reloaded and the queue information has changed:&lt;br /&gt;
* '''[queue_update]'''&lt;br /&gt;
** '''queue_id''': The server's unique ID for the queue.&lt;br /&gt;
** '''action''': One of add/update/remove.&lt;br /&gt;
** '''display_name''': The text to show in the list of queues in the lobby. Only used by add/update.&lt;br /&gt;
** '''players_required''': How many players are required before a game is started. Only used by add/update.&lt;br /&gt;
&lt;br /&gt;
When there are enough players to start a game, the last player to join the queue is chosen as the host and their client is told to create the game with the provided settings. This skips the game creation screen and goes straight to the staging screen. The other players in the queue are then told to join that game:&lt;br /&gt;
* '''[create_game]'''&lt;br /&gt;
** '''queue_id''': The ID of the queue to create the game for.&lt;br /&gt;
** '''[game]'''&lt;br /&gt;
*** '''scenario''': The ID of the scenario to create the game for.&lt;br /&gt;
*** '''era''': The ID of the era to use.&lt;br /&gt;
*** '''fog''': Whether to have fog enabled.&lt;br /&gt;
*** '''shroud''': Whether to have shroud enabled.&lt;br /&gt;
*** '''village_gold''': How much gold each village provides.&lt;br /&gt;
*** '''village_support''': How much unit support each village provides&lt;br /&gt;
*** '''experience_modifier''': The experience modifier to use.&lt;br /&gt;
*** '''countdown''': Not currently used, set to false.&lt;br /&gt;
*** '''random_start_time''': Whether to start at a random time of day.&lt;br /&gt;
*** '''shuffle_sides''': Whether to shuffle the sides' starting positions.&lt;br /&gt;
&lt;br /&gt;
== Administrative commands ==&lt;br /&gt;
* '''[query]'''&lt;br /&gt;
** '''type''': The type of query. See [[ServerAdministration]] for details.&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
[https://github.com/renom/fastbot fastbot] -  the bot for tournaments which implements the protocol, can log in into the lobby and host games. Written in Go. &lt;br /&gt;
[[Category:WML Reference]]&lt;br /&gt;
[[Category:Server Documentation]]&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=MultiplayerServerWML&amp;diff=74858</id>
		<title>MultiplayerServerWML</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=MultiplayerServerWML&amp;diff=74858"/>
		<updated>2026-02-22T14:46:30Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: /* Queues */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page describes the [[WML]] used to communicate with the multiplayer server for Wesnoth, [[wesnothd]].&lt;br /&gt;
&lt;br /&gt;
== The handshake ==&lt;br /&gt;
&lt;br /&gt;
The client sends four bytes, then the server replies with four bytes. To get a new connection number, the client will send these four bytes: 0x00 0x00 0x00 0x00. The server then sends back the connection number (wesnothd calls this number the &amp;quot;socket number&amp;quot;). Since 1.13+ the server no longer is using socket numbers to keep track of clients and always sends the same number to them all. Since 1.15+ client can also send 0x00 0x00 0x00 0x01 instead to request entire connection to be [https://github.com/wesnoth/wesnoth/blob/2f8136951cd77526188cf8d0fb2cf21eaa2ebe63/src/server/common/server_base.hpp#L60-L76 encapsulated in TLS] immediately '''after'''. If the handshake is successful, the server will be the first to send a data package. All packages are in [http://en.wikipedia.org/wiki/Gzip gzip] format and are preceded by four bytes that specify the size of the package to come in '''big-endian''' (network byte order). Below you'll find information about what data the (unzipped) packages contain. Unpacked WML uses utf-8 charset.&lt;br /&gt;
&lt;br /&gt;
== The login procedure ==&lt;br /&gt;
&lt;br /&gt;
* server request (optional)&lt;br /&gt;
** '''[version]'''&lt;br /&gt;
&lt;br /&gt;
* client response&lt;br /&gt;
** '''[version]'''&lt;br /&gt;
*** '''version''': The client's version string.&lt;br /&gt;
*** '''client_source''': The client's distribution info. (Steam, SourceForge, App Store, etc.)&lt;br /&gt;
&lt;br /&gt;
* server response (if the server does not accept this version)&lt;br /&gt;
** '''[redirect]'''&lt;br /&gt;
*** '''host''': The host you should connect to.&lt;br /&gt;
*** '''port''': The port you should connect to.&lt;br /&gt;
*** '''version''': A comma-separated list of globs that this server should accept (e.g. &amp;quot;1.0*,1.2*,1.4*,1.7*,1.8*&amp;quot;)&lt;br /&gt;
** or '''[reject]''' (if the version is unknown)&lt;br /&gt;
*** '''accepted_versions''': A comma-separated list of globs that this server does accept&lt;br /&gt;
&lt;br /&gt;
* server request&lt;br /&gt;
** '''[mustlogin]'''&lt;br /&gt;
&lt;br /&gt;
* client response&lt;br /&gt;
** '''[login]'''&lt;br /&gt;
*** '''username''': The username the client would like to have.&lt;br /&gt;
*** '''password''': The hashed password, created from the password and salt received from the server. More information about how this password is being generated, including a real world example, can be found in the file [http://forum.wesnoth.org/download/file.php?id=41145 HashedPasswords.pdf] (885 KiB). Since version 1.15+ if TLS was successfully established before then password will be passed as is, without hashing, relying on TLS for secrecy. Passing password hashes is no longer supported to free the client from responsibility to support all hash schemes the forum can potentially use. Client will emit error instead of trying to send password if TLS wasn't established.&lt;br /&gt;
&lt;br /&gt;
* server response&lt;br /&gt;
** '''[join_lobby]'''&lt;br /&gt;
*** '''is_moderator''': &amp;quot;yes&amp;quot; if the user is a moderator, &amp;quot;no&amp;quot; otherwise.&lt;br /&gt;
*** '''profile_url_prefix''': The external URL prefix for player profiles (empty if the server doesn't have an attached database)&lt;br /&gt;
** or '''[error]''' (server is waiting for another '''[login]''' message now)&lt;br /&gt;
*** '''message''': The error message.&lt;br /&gt;
*** '''password_request''': If not empty the server asks the client to provide a password for its desired username.&lt;br /&gt;
*** '''phpbb_encryption''': If &amp;quot;yes&amp;quot; the client will encrypt the password using phpbb's algorithm.&lt;br /&gt;
*** '''random_salt''': Random salt sent to the client for mixing with the password hash.&lt;br /&gt;
*** '''hash_seed''': Salt generated from the original hash that is required to recreate it.&lt;br /&gt;
*** '''salt''': Salt generated from the original hash that is required to recreate it.&lt;br /&gt;
*** '''force_confirmation''': Display an ok/cancel dialog with the content of the 'message' key.&lt;br /&gt;
&lt;br /&gt;
* server response&lt;br /&gt;
** '''[gamelist]'''&lt;br /&gt;
*** '''[game]''' (repeated)&lt;br /&gt;
**** '''id''': A unique id of the game.&lt;br /&gt;
**** '''name''': The title of the game.&lt;br /&gt;
**** '''mp_scenario''': The id of the scenario.&lt;br /&gt;
**** '''mp_era''': The id of the used era.&lt;br /&gt;
**** '''mp_use_map_settings''': Does the game use the map settings specified in the scenario.&lt;br /&gt;
**** '''mp_fog''': Does the game use fog.&lt;br /&gt;
**** '''mp_shroud''': Does the game use shroud.&lt;br /&gt;
**** '''mp_village_gold''': The number of gold per village.&lt;br /&gt;
**** '''experience_modifier''': The experience setting.&lt;br /&gt;
**** '''mp_countdown''': Does the game use a timer.&lt;br /&gt;
**** '''mp_countdown_reservoir_time''': Upper limit of the possibly available time.&lt;br /&gt;
**** '''mp_countdown_init_time''': Initial time.&lt;br /&gt;
**** '''mp_countdown_action_bonus''': Time bonus per action.&lt;br /&gt;
**** '''mp_countdown_turn_bonus''': Time bonus per turn.&lt;br /&gt;
**** '''map_data''': The map data. ''Notice: not sent to lobby if the game uses shroud''&lt;br /&gt;
**** '''hash''': The hash value of the map_data.&lt;br /&gt;
**** '''observer''': Are observers allowed or not.&lt;br /&gt;
**** '''human_sides''': The number of sides played by humans.&lt;br /&gt;
**** '''slots''': The number of vacant/max slots.&lt;br /&gt;
**** '''[slot_data]''' replaces '''slots''' since {{DevFeature1.13|12}}&lt;br /&gt;
***** '''max''': The number of total slots.&lt;br /&gt;
***** '''vacant''': The number of vacant slots.&lt;br /&gt;
**** '''turn''': The current turn/max turn.&lt;br /&gt;
**** '''[turn_data]''' replaces '''turn''' since {{DevFeature1.13|12}}&lt;br /&gt;
***** '''current''': The current turn number.&lt;br /&gt;
***** '''max''': The total number of turns.&lt;br /&gt;
**** '''[modification]''' Modifications used in this game. See [[ModificationWML]].&lt;br /&gt;
***** '''id''': ID of the modification.&lt;br /&gt;
***** '''name''': Name of the modification.&lt;br /&gt;
***** '''addon_id''': ID of the addon the modification is from.&lt;br /&gt;
***** '''require_modification''': A boolean value; if set to yes, all players have to have this modification installed to join the game.&lt;br /&gt;
**** '''[options]''' Options selected for this game. See [[OptionWML]].&lt;br /&gt;
***** '''[campaign|era|modification|multiplayer]'''&lt;br /&gt;
****** '''id''': ID of the addon the campaign|era|modification|multiplayer (scenario) is from.&lt;br /&gt;
****** '''[option]'''&lt;br /&gt;
******* '''id''': ID of the option.&lt;br /&gt;
******* '''value''': Value of the option.&lt;br /&gt;
** '''[user]''' (repeated)&lt;br /&gt;
*** '''name''': The username of the player.&lt;br /&gt;
*** '''game_id''': The ID of the game the player is in.&lt;br /&gt;
*** '''location''': The name of the game the player is in.&lt;br /&gt;
*** '''available''': &amp;quot;yes&amp;quot; if the player is in the lobby; &amp;quot;no&amp;quot; if in a game.&lt;br /&gt;
Many of the keys under [game] are described more indepth on the [[ScenarioWML]] page.&lt;br /&gt;
&lt;br /&gt;
== Error messages ==&lt;br /&gt;
&lt;br /&gt;
* '''[error]'''&lt;br /&gt;
** '''message''': The error message.&lt;br /&gt;
** '''password_request''': This is a response to a login attempt. The client needs to send a password on another login attempt.&lt;br /&gt;
** '''force_confirmation''': Confirmation to login even if there is an existing client with the same name. If login is continued then that existing client is getting kicked.&lt;br /&gt;
&lt;br /&gt;
== Chat (lobby and in-game) ==&lt;br /&gt;
&lt;br /&gt;
* '''[message]'''&lt;br /&gt;
** '''sender''': (optional - filled by the server) The sender of the message.&lt;br /&gt;
** '''message''': The message itself.&lt;br /&gt;
** '''room''': The room the message is from/to&lt;br /&gt;
* '''[whisper]'''&lt;br /&gt;
** '''receiver''': The receiver of the whisper&lt;br /&gt;
** '''sender''': (optional - filled by the server) The sender of the whisper.&lt;br /&gt;
** '''message''': The message itself.&lt;br /&gt;
&lt;br /&gt;
== Nickname registration related commands (lobby and in-game) ==&lt;br /&gt;
&lt;br /&gt;
* '''[nickserv]'''&lt;br /&gt;
** '''[info]''': Request info about another username.&lt;br /&gt;
*** '''name''': The username.&lt;br /&gt;
&lt;br /&gt;
== Updating the lobby state ==&lt;br /&gt;
&lt;br /&gt;
* '''[gamelist_diff]''': server message - basically a [[DiffWML|diff]] from two gamelists, which also includes the user list.&lt;br /&gt;
&lt;br /&gt;
* '''[observer]''' or '''[observer_quit]''': server message - players joining([observer_quit] - quitting the lobby &amp;quot;game&amp;quot;)/quitting([observer] - joining the lobby &amp;quot;game&amp;quot;) a game&lt;br /&gt;
** '''name''': Username of the player/observer.&lt;br /&gt;
* '''[refresh_lobby]''': Request the full gamelist.&lt;br /&gt;
&lt;br /&gt;
== Game setup (the phase from creation to start) ==&lt;br /&gt;
To create a game the client sends:&lt;br /&gt;
* '''[create_game]'''&lt;br /&gt;
** '''name''': The title of the game.&lt;br /&gt;
** '''password''': The password to use to join the game.&lt;br /&gt;
** '''ignored''': The list of ignored players from the host.&lt;br /&gt;
** '''auto_hosted''': True if this request is from a bot, false otherwise.&lt;br /&gt;
&lt;br /&gt;
followed by a message with the scenario options as under [game] (see above) plus the scenario data ([time], [era], [side], etc. see [[ScenarioWML]])&lt;br /&gt;
&lt;br /&gt;
* '''[join]'''&lt;br /&gt;
** '''id''': The id of the game.&lt;br /&gt;
** '''observe''': Join the game as an observer.&lt;br /&gt;
&lt;br /&gt;
* '''[scenario_diff]''': [[DiffWML|diff]] of the [[ScenarioWML]] (side changes, etc.)&lt;br /&gt;
&lt;br /&gt;
* '''[start_game]''': sent by the host to start a game&lt;br /&gt;
* '''[leave_game]''': sent by the client when it leaves a game; sent by the server to make a client leave a game&lt;br /&gt;
** '''reason''': optional reason if sent by the server and was initiated by moderator action&lt;br /&gt;
&lt;br /&gt;
== In-game communication ==&lt;br /&gt;
&lt;br /&gt;
Normal scenario communication ([[ReplayWML]]):&lt;br /&gt;
* '''[turn]'''&lt;br /&gt;
** '''[command]''': (repeated) can contain all the tags you can find in a [[ReplayWML|replay]]: [recruit], [move], [end_turn], etc.&lt;br /&gt;
*** '''[speak]'''&lt;br /&gt;
**** '''message''': text of the message&lt;br /&gt;
**** '''id''': the sender&lt;br /&gt;
**** '''team_name''': the name of the team the message is for - empty if it's a public message&lt;br /&gt;
&lt;br /&gt;
Multiplayer specific communication:&lt;br /&gt;
* '''[request_choice]'''&lt;br /&gt;
** '''request_id''': unique ID of the choice request&lt;br /&gt;
** '''[random_seed]''': client requests a random number (used for attacks for example)&lt;br /&gt;
** '''[change_controller_wml]''': change controller request from scenario WML&lt;br /&gt;
*** '''side''': side number&lt;br /&gt;
*** '''old_controller''': old [[SideWML#controller|controller]] value&lt;br /&gt;
*** '''new_controller''': new [[SideWML#controller|controller]] value&lt;br /&gt;
* '''[store_next_scenario]''': sent by the host - the scenario data (see [[ScenarioWML]]) to advance to the next scenario&lt;br /&gt;
* '''[notify_next_scenario]''': sent by the server to tell players that the data for the next scenario is available&lt;br /&gt;
* '''[load_next_scenario]''': sent by the client to request the data for the next scenario&lt;br /&gt;
* '''[next_scenario]''': data for the next scenario (see [[ScenarioWML]]), sent by the server on request&lt;br /&gt;
&lt;br /&gt;
* '''[info]''': sent by the host on game end - info about the game state&lt;br /&gt;
** '''type''': &amp;quot;termination&amp;quot; &lt;br /&gt;
** '''condition''': the termination reason&lt;br /&gt;
&lt;br /&gt;
If a player leaves this is sent to the host for all sides he owned.&lt;br /&gt;
* '''side_drop''': The number of a side that dropped because a player left.&lt;br /&gt;
* '''controller''': The controller of that side. (&amp;quot;ai&amp;quot;, &amp;quot;network&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
Client commands:&lt;br /&gt;
* '''[change_controller]''': a player (un)droids one of his sides or assigns control to someone else (The host can assign control for any side.)&lt;br /&gt;
** '''side''': the side to change controller&lt;br /&gt;
** '''player''': the nickname of the player to take control&lt;br /&gt;
** '''controller''': the new controller: &amp;quot;human&amp;quot; or &amp;quot;human_ai&amp;quot;&lt;br /&gt;
** '''own_side''': &amp;quot;yes&amp;quot;&lt;br /&gt;
* '''[muteall]''': the host mutes/unmutes all observers - toggles&lt;br /&gt;
* '''[mute]''': the host mutes an observer - toggles&lt;br /&gt;
** '''username''': the username of the observer - if not specified the servers returns a list of muted usernames&lt;br /&gt;
* '''[kick]''' or '''[ban]''': the host kicks/bans a player/observer&lt;br /&gt;
** '''username''': the username of the player/observer&lt;br /&gt;
&lt;br /&gt;
== Game history ==&lt;br /&gt;
This is a request to query a set of 11 rows of game history data based on the provided search criteria. The official client calls this from the Match History button in the  multiplayer lobby to display 10 rows of data. The 11th row is used as a flag to indicate whether there is more data to be queried or not via the right/left arrows on the dialog.&lt;br /&gt;
&lt;br /&gt;
* '''[game_history_request]'''&lt;br /&gt;
** '''offset''': where in the result set to start returning data from. If there are 50 results and offset 10 is given, then rows 10-21 will be returned.&lt;br /&gt;
** '''search_player''': the forum username of the player to search for.&lt;br /&gt;
** '''search_game_name''': the name of the game to filter results by. Can use the * (matches any character before or after it's used) and _ (matches any single character) wildcards.&lt;br /&gt;
** '''search_content_type''': the type of content to filter by. Must be one of:&lt;br /&gt;
*** '''0''': scenario&lt;br /&gt;
*** '''1''': era&lt;br /&gt;
*** '''2''':modification&lt;br /&gt;
** '''search_content''': The content to filter by. This is the ID of the content, not the name displayed on the UI, due to the translated name getting stored in the database.&lt;br /&gt;
&lt;br /&gt;
== Queues ==&lt;br /&gt;
Queue info sent to the client on join or when the server's config is reloaded and the queue information has changed:&lt;br /&gt;
* '''[queue_update]'''&lt;br /&gt;
** '''queue_id''': The server's unique ID for the queue.&lt;br /&gt;
** '''action''': One of add/update/remove.&lt;br /&gt;
** '''display_name''': The text to show in the list of queues in the lobby. Only used by add/update.&lt;br /&gt;
** '''players_required''': How many players are required before a game is started. Only used by add/update.&lt;br /&gt;
&lt;br /&gt;
== Administrative commands ==&lt;br /&gt;
* '''[query]'''&lt;br /&gt;
** '''type''': The type of query. See [[ServerAdministration]] for details.&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
[https://github.com/renom/fastbot fastbot] -  the bot for tournaments which implements the protocol, can log in into the lobby and host games. Written in Go. &lt;br /&gt;
[[Category:WML Reference]]&lt;br /&gt;
[[Category:Server Documentation]]&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=MultiplayerServerWML&amp;diff=74857</id>
		<title>MultiplayerServerWML</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=MultiplayerServerWML&amp;diff=74857"/>
		<updated>2026-02-22T14:46:00Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page describes the [[WML]] used to communicate with the multiplayer server for Wesnoth, [[wesnothd]].&lt;br /&gt;
&lt;br /&gt;
== The handshake ==&lt;br /&gt;
&lt;br /&gt;
The client sends four bytes, then the server replies with four bytes. To get a new connection number, the client will send these four bytes: 0x00 0x00 0x00 0x00. The server then sends back the connection number (wesnothd calls this number the &amp;quot;socket number&amp;quot;). Since 1.13+ the server no longer is using socket numbers to keep track of clients and always sends the same number to them all. Since 1.15+ client can also send 0x00 0x00 0x00 0x01 instead to request entire connection to be [https://github.com/wesnoth/wesnoth/blob/2f8136951cd77526188cf8d0fb2cf21eaa2ebe63/src/server/common/server_base.hpp#L60-L76 encapsulated in TLS] immediately '''after'''. If the handshake is successful, the server will be the first to send a data package. All packages are in [http://en.wikipedia.org/wiki/Gzip gzip] format and are preceded by four bytes that specify the size of the package to come in '''big-endian''' (network byte order). Below you'll find information about what data the (unzipped) packages contain. Unpacked WML uses utf-8 charset.&lt;br /&gt;
&lt;br /&gt;
== The login procedure ==&lt;br /&gt;
&lt;br /&gt;
* server request (optional)&lt;br /&gt;
** '''[version]'''&lt;br /&gt;
&lt;br /&gt;
* client response&lt;br /&gt;
** '''[version]'''&lt;br /&gt;
*** '''version''': The client's version string.&lt;br /&gt;
*** '''client_source''': The client's distribution info. (Steam, SourceForge, App Store, etc.)&lt;br /&gt;
&lt;br /&gt;
* server response (if the server does not accept this version)&lt;br /&gt;
** '''[redirect]'''&lt;br /&gt;
*** '''host''': The host you should connect to.&lt;br /&gt;
*** '''port''': The port you should connect to.&lt;br /&gt;
*** '''version''': A comma-separated list of globs that this server should accept (e.g. &amp;quot;1.0*,1.2*,1.4*,1.7*,1.8*&amp;quot;)&lt;br /&gt;
** or '''[reject]''' (if the version is unknown)&lt;br /&gt;
*** '''accepted_versions''': A comma-separated list of globs that this server does accept&lt;br /&gt;
&lt;br /&gt;
* server request&lt;br /&gt;
** '''[mustlogin]'''&lt;br /&gt;
&lt;br /&gt;
* client response&lt;br /&gt;
** '''[login]'''&lt;br /&gt;
*** '''username''': The username the client would like to have.&lt;br /&gt;
*** '''password''': The hashed password, created from the password and salt received from the server. More information about how this password is being generated, including a real world example, can be found in the file [http://forum.wesnoth.org/download/file.php?id=41145 HashedPasswords.pdf] (885 KiB). Since version 1.15+ if TLS was successfully established before then password will be passed as is, without hashing, relying on TLS for secrecy. Passing password hashes is no longer supported to free the client from responsibility to support all hash schemes the forum can potentially use. Client will emit error instead of trying to send password if TLS wasn't established.&lt;br /&gt;
&lt;br /&gt;
* server response&lt;br /&gt;
** '''[join_lobby]'''&lt;br /&gt;
*** '''is_moderator''': &amp;quot;yes&amp;quot; if the user is a moderator, &amp;quot;no&amp;quot; otherwise.&lt;br /&gt;
*** '''profile_url_prefix''': The external URL prefix for player profiles (empty if the server doesn't have an attached database)&lt;br /&gt;
** or '''[error]''' (server is waiting for another '''[login]''' message now)&lt;br /&gt;
*** '''message''': The error message.&lt;br /&gt;
*** '''password_request''': If not empty the server asks the client to provide a password for its desired username.&lt;br /&gt;
*** '''phpbb_encryption''': If &amp;quot;yes&amp;quot; the client will encrypt the password using phpbb's algorithm.&lt;br /&gt;
*** '''random_salt''': Random salt sent to the client for mixing with the password hash.&lt;br /&gt;
*** '''hash_seed''': Salt generated from the original hash that is required to recreate it.&lt;br /&gt;
*** '''salt''': Salt generated from the original hash that is required to recreate it.&lt;br /&gt;
*** '''force_confirmation''': Display an ok/cancel dialog with the content of the 'message' key.&lt;br /&gt;
&lt;br /&gt;
* server response&lt;br /&gt;
** '''[gamelist]'''&lt;br /&gt;
*** '''[game]''' (repeated)&lt;br /&gt;
**** '''id''': A unique id of the game.&lt;br /&gt;
**** '''name''': The title of the game.&lt;br /&gt;
**** '''mp_scenario''': The id of the scenario.&lt;br /&gt;
**** '''mp_era''': The id of the used era.&lt;br /&gt;
**** '''mp_use_map_settings''': Does the game use the map settings specified in the scenario.&lt;br /&gt;
**** '''mp_fog''': Does the game use fog.&lt;br /&gt;
**** '''mp_shroud''': Does the game use shroud.&lt;br /&gt;
**** '''mp_village_gold''': The number of gold per village.&lt;br /&gt;
**** '''experience_modifier''': The experience setting.&lt;br /&gt;
**** '''mp_countdown''': Does the game use a timer.&lt;br /&gt;
**** '''mp_countdown_reservoir_time''': Upper limit of the possibly available time.&lt;br /&gt;
**** '''mp_countdown_init_time''': Initial time.&lt;br /&gt;
**** '''mp_countdown_action_bonus''': Time bonus per action.&lt;br /&gt;
**** '''mp_countdown_turn_bonus''': Time bonus per turn.&lt;br /&gt;
**** '''map_data''': The map data. ''Notice: not sent to lobby if the game uses shroud''&lt;br /&gt;
**** '''hash''': The hash value of the map_data.&lt;br /&gt;
**** '''observer''': Are observers allowed or not.&lt;br /&gt;
**** '''human_sides''': The number of sides played by humans.&lt;br /&gt;
**** '''slots''': The number of vacant/max slots.&lt;br /&gt;
**** '''[slot_data]''' replaces '''slots''' since {{DevFeature1.13|12}}&lt;br /&gt;
***** '''max''': The number of total slots.&lt;br /&gt;
***** '''vacant''': The number of vacant slots.&lt;br /&gt;
**** '''turn''': The current turn/max turn.&lt;br /&gt;
**** '''[turn_data]''' replaces '''turn''' since {{DevFeature1.13|12}}&lt;br /&gt;
***** '''current''': The current turn number.&lt;br /&gt;
***** '''max''': The total number of turns.&lt;br /&gt;
**** '''[modification]''' Modifications used in this game. See [[ModificationWML]].&lt;br /&gt;
***** '''id''': ID of the modification.&lt;br /&gt;
***** '''name''': Name of the modification.&lt;br /&gt;
***** '''addon_id''': ID of the addon the modification is from.&lt;br /&gt;
***** '''require_modification''': A boolean value; if set to yes, all players have to have this modification installed to join the game.&lt;br /&gt;
**** '''[options]''' Options selected for this game. See [[OptionWML]].&lt;br /&gt;
***** '''[campaign|era|modification|multiplayer]'''&lt;br /&gt;
****** '''id''': ID of the addon the campaign|era|modification|multiplayer (scenario) is from.&lt;br /&gt;
****** '''[option]'''&lt;br /&gt;
******* '''id''': ID of the option.&lt;br /&gt;
******* '''value''': Value of the option.&lt;br /&gt;
** '''[user]''' (repeated)&lt;br /&gt;
*** '''name''': The username of the player.&lt;br /&gt;
*** '''game_id''': The ID of the game the player is in.&lt;br /&gt;
*** '''location''': The name of the game the player is in.&lt;br /&gt;
*** '''available''': &amp;quot;yes&amp;quot; if the player is in the lobby; &amp;quot;no&amp;quot; if in a game.&lt;br /&gt;
Many of the keys under [game] are described more indepth on the [[ScenarioWML]] page.&lt;br /&gt;
&lt;br /&gt;
== Error messages ==&lt;br /&gt;
&lt;br /&gt;
* '''[error]'''&lt;br /&gt;
** '''message''': The error message.&lt;br /&gt;
** '''password_request''': This is a response to a login attempt. The client needs to send a password on another login attempt.&lt;br /&gt;
** '''force_confirmation''': Confirmation to login even if there is an existing client with the same name. If login is continued then that existing client is getting kicked.&lt;br /&gt;
&lt;br /&gt;
== Chat (lobby and in-game) ==&lt;br /&gt;
&lt;br /&gt;
* '''[message]'''&lt;br /&gt;
** '''sender''': (optional - filled by the server) The sender of the message.&lt;br /&gt;
** '''message''': The message itself.&lt;br /&gt;
** '''room''': The room the message is from/to&lt;br /&gt;
* '''[whisper]'''&lt;br /&gt;
** '''receiver''': The receiver of the whisper&lt;br /&gt;
** '''sender''': (optional - filled by the server) The sender of the whisper.&lt;br /&gt;
** '''message''': The message itself.&lt;br /&gt;
&lt;br /&gt;
== Nickname registration related commands (lobby and in-game) ==&lt;br /&gt;
&lt;br /&gt;
* '''[nickserv]'''&lt;br /&gt;
** '''[info]''': Request info about another username.&lt;br /&gt;
*** '''name''': The username.&lt;br /&gt;
&lt;br /&gt;
== Updating the lobby state ==&lt;br /&gt;
&lt;br /&gt;
* '''[gamelist_diff]''': server message - basically a [[DiffWML|diff]] from two gamelists, which also includes the user list.&lt;br /&gt;
&lt;br /&gt;
* '''[observer]''' or '''[observer_quit]''': server message - players joining([observer_quit] - quitting the lobby &amp;quot;game&amp;quot;)/quitting([observer] - joining the lobby &amp;quot;game&amp;quot;) a game&lt;br /&gt;
** '''name''': Username of the player/observer.&lt;br /&gt;
* '''[refresh_lobby]''': Request the full gamelist.&lt;br /&gt;
&lt;br /&gt;
== Game setup (the phase from creation to start) ==&lt;br /&gt;
To create a game the client sends:&lt;br /&gt;
* '''[create_game]'''&lt;br /&gt;
** '''name''': The title of the game.&lt;br /&gt;
** '''password''': The password to use to join the game.&lt;br /&gt;
** '''ignored''': The list of ignored players from the host.&lt;br /&gt;
** '''auto_hosted''': True if this request is from a bot, false otherwise.&lt;br /&gt;
&lt;br /&gt;
followed by a message with the scenario options as under [game] (see above) plus the scenario data ([time], [era], [side], etc. see [[ScenarioWML]])&lt;br /&gt;
&lt;br /&gt;
* '''[join]'''&lt;br /&gt;
** '''id''': The id of the game.&lt;br /&gt;
** '''observe''': Join the game as an observer.&lt;br /&gt;
&lt;br /&gt;
* '''[scenario_diff]''': [[DiffWML|diff]] of the [[ScenarioWML]] (side changes, etc.)&lt;br /&gt;
&lt;br /&gt;
* '''[start_game]''': sent by the host to start a game&lt;br /&gt;
* '''[leave_game]''': sent by the client when it leaves a game; sent by the server to make a client leave a game&lt;br /&gt;
** '''reason''': optional reason if sent by the server and was initiated by moderator action&lt;br /&gt;
&lt;br /&gt;
== In-game communication ==&lt;br /&gt;
&lt;br /&gt;
Normal scenario communication ([[ReplayWML]]):&lt;br /&gt;
* '''[turn]'''&lt;br /&gt;
** '''[command]''': (repeated) can contain all the tags you can find in a [[ReplayWML|replay]]: [recruit], [move], [end_turn], etc.&lt;br /&gt;
*** '''[speak]'''&lt;br /&gt;
**** '''message''': text of the message&lt;br /&gt;
**** '''id''': the sender&lt;br /&gt;
**** '''team_name''': the name of the team the message is for - empty if it's a public message&lt;br /&gt;
&lt;br /&gt;
Multiplayer specific communication:&lt;br /&gt;
* '''[request_choice]'''&lt;br /&gt;
** '''request_id''': unique ID of the choice request&lt;br /&gt;
** '''[random_seed]''': client requests a random number (used for attacks for example)&lt;br /&gt;
** '''[change_controller_wml]''': change controller request from scenario WML&lt;br /&gt;
*** '''side''': side number&lt;br /&gt;
*** '''old_controller''': old [[SideWML#controller|controller]] value&lt;br /&gt;
*** '''new_controller''': new [[SideWML#controller|controller]] value&lt;br /&gt;
* '''[store_next_scenario]''': sent by the host - the scenario data (see [[ScenarioWML]]) to advance to the next scenario&lt;br /&gt;
* '''[notify_next_scenario]''': sent by the server to tell players that the data for the next scenario is available&lt;br /&gt;
* '''[load_next_scenario]''': sent by the client to request the data for the next scenario&lt;br /&gt;
* '''[next_scenario]''': data for the next scenario (see [[ScenarioWML]]), sent by the server on request&lt;br /&gt;
&lt;br /&gt;
* '''[info]''': sent by the host on game end - info about the game state&lt;br /&gt;
** '''type''': &amp;quot;termination&amp;quot; &lt;br /&gt;
** '''condition''': the termination reason&lt;br /&gt;
&lt;br /&gt;
If a player leaves this is sent to the host for all sides he owned.&lt;br /&gt;
* '''side_drop''': The number of a side that dropped because a player left.&lt;br /&gt;
* '''controller''': The controller of that side. (&amp;quot;ai&amp;quot;, &amp;quot;network&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
Client commands:&lt;br /&gt;
* '''[change_controller]''': a player (un)droids one of his sides or assigns control to someone else (The host can assign control for any side.)&lt;br /&gt;
** '''side''': the side to change controller&lt;br /&gt;
** '''player''': the nickname of the player to take control&lt;br /&gt;
** '''controller''': the new controller: &amp;quot;human&amp;quot; or &amp;quot;human_ai&amp;quot;&lt;br /&gt;
** '''own_side''': &amp;quot;yes&amp;quot;&lt;br /&gt;
* '''[muteall]''': the host mutes/unmutes all observers - toggles&lt;br /&gt;
* '''[mute]''': the host mutes an observer - toggles&lt;br /&gt;
** '''username''': the username of the observer - if not specified the servers returns a list of muted usernames&lt;br /&gt;
* '''[kick]''' or '''[ban]''': the host kicks/bans a player/observer&lt;br /&gt;
** '''username''': the username of the player/observer&lt;br /&gt;
&lt;br /&gt;
== Game history ==&lt;br /&gt;
This is a request to query a set of 11 rows of game history data based on the provided search criteria. The official client calls this from the Match History button in the  multiplayer lobby to display 10 rows of data. The 11th row is used as a flag to indicate whether there is more data to be queried or not via the right/left arrows on the dialog.&lt;br /&gt;
&lt;br /&gt;
* '''[game_history_request]'''&lt;br /&gt;
** '''offset''': where in the result set to start returning data from. If there are 50 results and offset 10 is given, then rows 10-21 will be returned.&lt;br /&gt;
** '''search_player''': the forum username of the player to search for.&lt;br /&gt;
** '''search_game_name''': the name of the game to filter results by. Can use the * (matches any character before or after it's used) and _ (matches any single character) wildcards.&lt;br /&gt;
** '''search_content_type''': the type of content to filter by. Must be one of:&lt;br /&gt;
*** '''0''': scenario&lt;br /&gt;
*** '''1''': era&lt;br /&gt;
*** '''2''':modification&lt;br /&gt;
** '''search_content''': The content to filter by. This is the ID of the content, not the name displayed on the UI, due to the translated name getting stored in the database.&lt;br /&gt;
&lt;br /&gt;
== Queues ==&lt;br /&gt;
Queue info sent to the client on join or when the server's config is reloaded and the queue information has changed:&lt;br /&gt;
* '''[queue_update]'''&lt;br /&gt;
** '''queue_id''': The server's unique ID for the queue.&lt;br /&gt;
** '''action''': One of add/update/remove.&lt;br /&gt;
** '''display_name''': The text to show in the list of queues in the lobby.&lt;br /&gt;
** '''players_required''': How many players are required before a game is started.&lt;br /&gt;
&lt;br /&gt;
== Administrative commands ==&lt;br /&gt;
* '''[query]'''&lt;br /&gt;
** '''type''': The type of query. See [[ServerAdministration]] for details.&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
[https://github.com/renom/fastbot fastbot] -  the bot for tournaments which implements the protocol, can log in into the lobby and host games. Written in Go. &lt;br /&gt;
[[Category:WML Reference]]&lt;br /&gt;
[[Category:Server Documentation]]&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Template:DevDownload&amp;diff=74798</id>
		<title>Template:DevDownload</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Template:DevDownload&amp;diff=74798"/>
		<updated>2026-02-05T00:41:55Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
== Development (1.19 branch) ==&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
==== Windows (10 1903 and later) {{{4|}}} ====&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.20 | filename=wesnoth-1.19.20-win64.exe |&lt;br /&gt;
hash=c55a71350f5aab18074a5cc781bc66a56a29086624df85f4e155d5a1a4e966f9}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.19 | filename=wesnoth-1.19.19-win64.exe |&lt;br /&gt;
hash=1d2529daa2c585579176a88655133297b7e2b4ca634f45468bc2f13866604565}}&lt;br /&gt;
&lt;br /&gt;
==== macOS (10.13 and later) {{{5|}}} ====&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.20 | filename=Wesnoth_1.19.20.dmg |&lt;br /&gt;
hash=9a0df54edbbffb503f527a1b8007b7860eace3cfb9b94207c2ad21047171eb94}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.19 | filename=Wesnoth_1.19.19.dmg |&lt;br /&gt;
hash=ac733dd52d01026448e7127b48eedfe69ad4b0d0c6089a367592c6d2d1c8d3fc}}&lt;br /&gt;
&lt;br /&gt;
==== Source code ====&lt;br /&gt;
* [https://github.com/wesnoth/wesnoth/blob/master/INSTALL.md Compiling Wesnoth] - How to compile the source code&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.20 | filename=wesnoth-1.19.20.tar.bz2 |&lt;br /&gt;
hash=48f883f8cd3ea008f9170aeaa9fb9ebb486202dd72f455ae131363fc3d164f8f}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.19 | filename=wesnoth-1.19.19.tar.bz2 |&lt;br /&gt;
hash=d4fba3ecc1a92293f90d623edfef97be7ed6abe963bdcd7134de256fb6977c1d}}&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Template:DevDownload&amp;diff=74796</id>
		<title>Template:DevDownload</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Template:DevDownload&amp;diff=74796"/>
		<updated>2026-02-01T17:57:57Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
== Development (1.19 branch) ==&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
==== Windows (10 1903 and later) {{{4|}}} ====&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.20 | filename=wesnoth-1.19.20-win64.exe |&lt;br /&gt;
hash=c55a71350f5aab18074a5cc781bc66a56a29086624df85f4e155d5a1a4e966f9}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.19 | filename=wesnoth-1.19.19-win64.exe |&lt;br /&gt;
hash=1d2529daa2c585579176a88655133297b7e2b4ca634f45468bc2f13866604565}}&lt;br /&gt;
&lt;br /&gt;
==== macOS (10.13 and later) {{{5|}}} ====&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.19 | filename=Wesnoth_1.19.19.dmg |&lt;br /&gt;
hash=ac733dd52d01026448e7127b48eedfe69ad4b0d0c6089a367592c6d2d1c8d3fc}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.18 | filename=Wesnoth_1.19.18.dmg |&lt;br /&gt;
hash=e3c7490086c6d4200c991e54e541eb830ce2252a453a10ce07dfc0913fd3df23}}&lt;br /&gt;
&lt;br /&gt;
==== Source code ====&lt;br /&gt;
* [https://github.com/wesnoth/wesnoth/blob/master/INSTALL.md Compiling Wesnoth] - How to compile the source code&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.20 | filename=wesnoth-1.19.20.tar.bz2 |&lt;br /&gt;
hash=48f883f8cd3ea008f9170aeaa9fb9ebb486202dd72f455ae131363fc3d164f8f}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.19 | filename=wesnoth-1.19.19.tar.bz2 |&lt;br /&gt;
hash=d4fba3ecc1a92293f90d623edfef97be7ed6abe963bdcd7134de256fb6977c1d}}&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Template:DevDownload&amp;diff=74693</id>
		<title>Template:DevDownload</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Template:DevDownload&amp;diff=74693"/>
		<updated>2025-12-31T01:45:23Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
== Development (1.19 branch) ==&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
==== Windows (10 1903 and later) {{{4|}}} ====&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.19 | filename=wesnoth-1.19.19-win64.exe |&lt;br /&gt;
hash=1d2529daa2c585579176a88655133297b7e2b4ca634f45468bc2f13866604565}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.18 | filename=wesnoth-1.19.18-win64.exe |&lt;br /&gt;
hash=3bea895b5ac6520af3c7217283afcc7e17eb96924c3859e559fd04adb35f6fe8}}&lt;br /&gt;
&lt;br /&gt;
==== macOS (10.13 and later) {{{5|}}} ====&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.19 | filename=Wesnoth_1.19.19.dmg |&lt;br /&gt;
hash=ac733dd52d01026448e7127b48eedfe69ad4b0d0c6089a367592c6d2d1c8d3fc}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.18 | filename=Wesnoth_1.19.18.dmg |&lt;br /&gt;
hash=e3c7490086c6d4200c991e54e541eb830ce2252a453a10ce07dfc0913fd3df23}}&lt;br /&gt;
&lt;br /&gt;
==== Source code ====&lt;br /&gt;
* [https://github.com/wesnoth/wesnoth/blob/master/INSTALL.md Compiling Wesnoth] - How to compile the source code&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.19 | filename=wesnoth-1.19.19.tar.bz2 |&lt;br /&gt;
hash=d4fba3ecc1a92293f90d623edfef97be7ed6abe963bdcd7134de256fb6977c1d}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.18 | filename=wesnoth-1.19.18.tar.bz2 |&lt;br /&gt;
hash=22c788998a7555def490ca559844a8721029e25a5529d8584dfbc15f2a579b72}}&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Template:StableDownload&amp;diff=74692</id>
		<title>Template:StableDownload</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Template:StableDownload&amp;diff=74692"/>
		<updated>2025-12-31T01:19:29Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
== Stable (1.18 branch) ==&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
==== Windows (10 1903 and later, 64-bit only) {{{4|}}} ====&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth-1.18 |&lt;br /&gt;
version=1.18.6 | filename=wesnoth-1.18.6-win64.exe |&lt;br /&gt;
hash=7365efdc70c127f6d0bfbc6a8f976e6cba1eec59f2bbfb6dc27644534670b162}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth-1.18 |&lt;br /&gt;
version=1.18.5 | filename=wesnoth-1.18.5-win64.exe |&lt;br /&gt;
hash=915d9c0374221782fbfaecd3ac8d8833b470c6ed6c059e6086d5082a28edf80f}}&lt;br /&gt;
&lt;br /&gt;
==== macOS (10.12 and later) {{{5|}}} ====&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth-1.18 |&lt;br /&gt;
version=1.18.6 | filename=Wesnoth_1.18.6.dmg |&lt;br /&gt;
hash=1b9a0ba71c11a386ea0daef357cb508f5c9dc792eed71eff1a3783c056214c93}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth-1.18 |&lt;br /&gt;
version=1.18.5 | filename=Wesnoth_1.18.5.dmg |&lt;br /&gt;
hash=73e34ee58a7c81055bdf94f1b0646a524a992235682ce227fb8d3829af4061f1}}&lt;br /&gt;
&lt;br /&gt;
==== Source code ====&lt;br /&gt;
* [https://github.com/wesnoth/wesnoth/blob/master/INSTALL.md Compiling Wesnoth] - How to compile the source code&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth-1.18 |&lt;br /&gt;
version=1.18.6 | filename=wesnoth-1.18.6.tar.bz2 |&lt;br /&gt;
hash=6bb8b17854c974bc66cb7a2574a53fe9efb4d2c138bb1373032e57788204985e}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth-1.18 |&lt;br /&gt;
version=1.18.5 | filename=wesnoth-1.18.5.tar.bz2 |&lt;br /&gt;
hash=e15db3caf446d91d389fc275f10c1a9e7ca3c6176c3b8ce94f5ee4a7a0c81bd6}}&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Release_Steps&amp;diff=74680</id>
		<title>Release Steps</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Release_Steps&amp;diff=74680"/>
		<updated>2025-12-19T18:07:07Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Pre-release (stable only) ==&lt;br /&gt;
* Start the string freeze two weeks before the release.&lt;br /&gt;
* Do the pot update:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
scons pot-update update-po4a manual&lt;br /&gt;
git add -A&lt;br /&gt;
git commit -am &amp;quot;pot-update and regenerate doc files&amp;quot;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Email the translator's mailing list stating that the string freeze is starting.&lt;br /&gt;
&lt;br /&gt;
== Release (stable and master branches) ==&lt;br /&gt;
* Update [http://www.wesnoth.org/macro-reference.html macro-reference.html]:&lt;br /&gt;
&lt;br /&gt;
 cd data/tools/&lt;br /&gt;
 make macro-reference.html&lt;br /&gt;
* If stable&lt;br /&gt;
 scp macro-reference.html wesnoth@wesnoth.org:WWW/html/macro-reference.html&lt;br /&gt;
* If master&lt;br /&gt;
 scp macro-reference.html wesnoth@wesnoth.org:WWW/html/macro-reference-1.&amp;lt;version&amp;gt;.html&lt;br /&gt;
&lt;br /&gt;
* Regenerate the game credits and paste the contents to [[Credits]] on the wiki:&lt;br /&gt;
&lt;br /&gt;
 data/tools/about_cfg_to_wiki -w ./wesnoth &amp;gt; ./about.wiki&lt;br /&gt;
&lt;br /&gt;
* Check the '''changelog_entries''' folder for entries and update the changelog as necessary.&lt;br /&gt;
* Run the pot update (second time if this is a stable release).&lt;br /&gt;
* Do the pre-tag commit (check a previous commit as an example - this removes the &amp;quot;+dev&amp;quot; suffix everywhere).&lt;br /&gt;
* The the post-tag commit (check a previous commit as an example - this re-adds the &amp;quot;+dev&amp;quot; suffix everywhere).&lt;br /&gt;
* Tag the pre-tag commit with:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;git tag -a &amp;lt;version&amp;gt; -m &amp;quot;Wesnoth &amp;lt;version&amp;gt; (Alpha)&amp;quot; &amp;lt;commit hash&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
::- (Alpha)/(Beta) is only added for dev releases depending on where we are in the release cycle.&lt;br /&gt;
* Push the commits and the tag:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;git push&lt;br /&gt;
git push origin &amp;lt;version&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Ping the packagers on Discord that the release has been tagged:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;@packagers &amp;lt;version&amp;gt; has been tagged.&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Check that the new version is allowed on its respective multiplayer server.&lt;br /&gt;
* Update the header in Discord's #development channel.&lt;br /&gt;
* Upload master.zip and the patch to SourceForge to the respective version's folder for use by Android&lt;br /&gt;
** master.zip contains the folders&lt;br /&gt;
*** data (data/core/music/ is removed)&lt;br /&gt;
*** fonts&lt;br /&gt;
*** images&lt;br /&gt;
*** sounds&lt;br /&gt;
*** translations&lt;br /&gt;
** For the patch, go to packaging/android/ and run &lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;./create_patch.sh oldtag newtag&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then upload the resulting patch.zip and manifest.txt next to master.zip.&lt;br /&gt;
* Upload source code tarball to SourceForge and files.wesnoth.org (done by loonycyborg).&lt;br /&gt;
* Send an email to the packagers mailing list (done by loonycyborg).&lt;br /&gt;
* Upload the release to the various places Wesnoth is distributed (Steam, itch.io, SourceForge, macOS App Store, Flathub, F-Droid).&lt;br /&gt;
** Windows/Linux - handled by loonycyborg.&lt;br /&gt;
** macOS - handled by hrubymar.&lt;br /&gt;
** Android (F-Droid) - handled by LumiousE&lt;br /&gt;
* Post the forum announcements.&lt;br /&gt;
* Update the Downloads wiki page.&lt;br /&gt;
** url: https://wiki.wesnoth.org/Download&lt;br /&gt;
** dev template: https://wiki.wesnoth.org/Template:DevDownload#Development_.281.15_branch.29&lt;br /&gt;
** stable template: https://wiki.wesnoth.org/Template:StableDownload&lt;br /&gt;
* Add the News forum post.&lt;br /&gt;
* Post the Discord announcement.&lt;br /&gt;
** Make sure to publish it.&lt;br /&gt;
** Short link is: '''&amp;lt;nowiki&amp;gt;https://r.wesnoth.org/t#####&amp;lt;/nowiki&amp;gt;'''&lt;br /&gt;
* Post the itch.io devlog (copy of the Discord announcement).&lt;br /&gt;
* Update the wesnoth.org front page.&lt;br /&gt;
** See a previous version update commit to the '''wesmere''' repository.&lt;br /&gt;
** ssh into the website VM and execute the following shell commands (yes, it is specifically ''''make'''', not ''''make install''''!):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;sudo -iu wesnoth&lt;br /&gt;
cd ~/git/wesmere/static&lt;br /&gt;
git pull&lt;br /&gt;
make&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Generate the Steam announcement by running the following command in your local wesnoth repository root:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;python3 data/tools/steam-changelog changelog.md &amp;lt;version&amp;gt; &amp;gt; &amp;lt;version&amp;gt;.txt&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Post the Steam announcement.&lt;br /&gt;
* Log into Wesnoth's Steam page.&lt;br /&gt;
** Click &amp;quot;A Game Update&amp;quot;.&lt;br /&gt;
** Pick &amp;quot;Small Update&amp;quot;.&lt;br /&gt;
** Paste the output of of the above python command into the event description.&lt;br /&gt;
** Click &amp;quot;Link To Build&amp;quot; and select the appropriate branch.&lt;br /&gt;
** Edit the appropriate .xcf file from the [https://github.com/wesnoth/resources/tree/master/social-media-assets Resources repository] ('''wesnoth_event_header.xcf''' for stable releases, '''wesnoth_beta_header.xcf''' for development releases) and export it to PNG.&lt;br /&gt;
*** This requires the '''oldania''' font to be installed, which on Linux/Ubuntu-derivatives can be installed via the command:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;apt install fonts-adf-oldania&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Post the announcement to Fosstodon.&lt;br /&gt;
* Post the announcement to Reddit. (Elvish_Hunter)&lt;br /&gt;
** Add the &amp;quot;Development release&amp;quot;/&amp;quot;Stable release&amp;quot; flair.&lt;br /&gt;
** Don't paste the link in the post, directly post it as a link.&lt;br /&gt;
&lt;br /&gt;
== New Stable Series ==&lt;br /&gt;
=== Beta 1 ===&lt;br /&gt;
Write up the new Start page (ie: https://www.wesnoth.org/start/1.16/).&lt;br /&gt;
&lt;br /&gt;
=== Beta 2 ===&lt;br /&gt;
Make the new Start page available to Translators.&lt;br /&gt;
&lt;br /&gt;
=== RC1 ===&lt;br /&gt;
Before release, the new multiplayer server and add-ons server instances need to be setup. The server running the website status is owned by Iris - she needs to push updates to it.&lt;br /&gt;
* Multiplayer server&lt;br /&gt;
** Needs no changes since it goes to port 15000 and then that redirects based on version. The existing dev multiplayer server will be reused as the new stable instance.&lt;br /&gt;
** The Discord website status bot and the site status page (https://status.wesnoth.org/ - bin/valen.pl) need to be updated to rename the dev version to the stable version.&lt;br /&gt;
** A new stable multiplayer instance needs to be added to the alternate server.&lt;br /&gt;
&lt;br /&gt;
* Add-ons server - The port is the version number, for example 1.16 is 15016, 1.18 is 15018, etc.&lt;br /&gt;
** C++ update (currently default_campaignd_port in addon/validation.cpp)&lt;br /&gt;
** Python update (data/tools/wesnoth/campaignserver_client.py)&lt;br /&gt;
** Website update (bin/valen.pl) in the valen repository to add the new instance.&lt;br /&gt;
** The Discord website status bot and the site status page (https://status.wesnoth.org/ - bin/valen.pl) need to be updated to add the new version.&lt;br /&gt;
** Add a 1.18 cron job for ~wesnoth/bin/update_addons in the websites VM and remove the 1.17 cron job.&lt;br /&gt;
&lt;br /&gt;
* Flatpak&lt;br /&gt;
** &lt;br /&gt;
&lt;br /&gt;
* Add screenshots to https://wiki.wesnoth.org/Screenshots&lt;br /&gt;
&lt;br /&gt;
* Start page - soft link the folder from the repository to the folder that shows up on the actual website:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
cd /srv/www/html/start&lt;br /&gt;
ln -s /home/git/wesnoth/start/&amp;lt;version&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Update ci_main.yml to use the new branch instead of the master branch.&lt;br /&gt;
&lt;br /&gt;
[[Category:Release_Notes]]&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Release_Steps&amp;diff=74679</id>
		<title>Release Steps</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Release_Steps&amp;diff=74679"/>
		<updated>2025-12-19T18:05:48Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Pre-release (stable only) ==&lt;br /&gt;
* Start the string freeze two weeks before the release.&lt;br /&gt;
* Do the pot update:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
scons pot-update update-po4a manual&lt;br /&gt;
git add -A&lt;br /&gt;
git commit -am &amp;quot;pot-update and regenerate doc files&amp;quot;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Email the translator's mailing list stating that the string freeze is starting.&lt;br /&gt;
&lt;br /&gt;
== Release (stable and master branches) ==&lt;br /&gt;
* Update [http://www.wesnoth.org/macro-reference.html macro-reference.html]:&lt;br /&gt;
&lt;br /&gt;
 cd data/tools/&lt;br /&gt;
 make macro-reference.html&lt;br /&gt;
* If stable&lt;br /&gt;
 scp macro-reference.html wesnoth@wesnoth.org:WWW/html/macro-reference.html&lt;br /&gt;
* If master&lt;br /&gt;
 scp macro-reference.html wesnoth@wesnoth.org:WWW/html/macro-reference-1.&amp;lt;version&amp;gt;.html&lt;br /&gt;
&lt;br /&gt;
* Regenerate the game credits and paste the contents to [[Credits]] on the wiki:&lt;br /&gt;
&lt;br /&gt;
 data/tools/about_cfg_to_wiki -w ./wesnoth &amp;gt; ./about.wiki&lt;br /&gt;
&lt;br /&gt;
* Check the '''changelog_entries''' folder for entries and update the changelog as necessary.&lt;br /&gt;
* Run the pot update (second time if this is a stable release).&lt;br /&gt;
* Do the pre-tag commit (check a previous commit as an example - this removes the &amp;quot;+dev&amp;quot; suffix everywhere).&lt;br /&gt;
* The the post-tag commit (check a previous commit as an example - this re-adds the &amp;quot;+dev&amp;quot; suffix everywhere).&lt;br /&gt;
* Tag the pre-tag commit with:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;git tag -a &amp;lt;version&amp;gt; -m &amp;quot;Wesnoth &amp;lt;version&amp;gt; (Alpha)&amp;quot; &amp;lt;commit hash&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
::- (Alpha)/(Beta) is only added for dev releases depending on where we are in the release cycle.&lt;br /&gt;
* Push the commits and the tag:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;git push&lt;br /&gt;
git push origin &amp;lt;version&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Ping the packagers on Discord that the release has been tagged:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;@packagers &amp;lt;version&amp;gt; has been tagged.&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Check that the new version is allowed on its respective multiplayer server.&lt;br /&gt;
* Update the header in Discord's #development channel.&lt;br /&gt;
* Upload master.zip and the patch to SourceForge to the respective version's folder for use by Android&lt;br /&gt;
** master.zip contains the folders&lt;br /&gt;
*** data (data/core/music/ is removed)&lt;br /&gt;
*** fonts&lt;br /&gt;
*** images&lt;br /&gt;
*** sounds&lt;br /&gt;
*** translations&lt;br /&gt;
** For the patch, go to packaging/android/ and run &amp;lt;nowiki&amp;gt;./create_patch.sh oldtag newtag&amp;lt;/nowiki&amp;gt;. Then upload the resulting patch.zip and manifest.txt next to master.zip.&lt;br /&gt;
* Upload source code tarball to SourceForge and files.wesnoth.org (done by loonycyborg).&lt;br /&gt;
* Send an email to the packagers mailing list (done by loonycyborg).&lt;br /&gt;
* Upload the release to the various places Wesnoth is distributed (Steam, itch.io, SourceForge, macOS App Store, Flathub, F-Droid).&lt;br /&gt;
** Windows/Linux - handled by loonycyborg.&lt;br /&gt;
** macOS - handled by hrubymar.&lt;br /&gt;
** Android (F-Droid) - handled by LumiousE&lt;br /&gt;
* Post the forum announcements.&lt;br /&gt;
* Update the Downloads wiki page.&lt;br /&gt;
** url: https://wiki.wesnoth.org/Download&lt;br /&gt;
** dev template: https://wiki.wesnoth.org/Template:DevDownload#Development_.281.15_branch.29&lt;br /&gt;
** stable template: https://wiki.wesnoth.org/Template:StableDownload&lt;br /&gt;
* Add the News forum post.&lt;br /&gt;
* Post the Discord announcement.&lt;br /&gt;
** Make sure to publish it.&lt;br /&gt;
** Short link is: '''&amp;lt;nowiki&amp;gt;https://r.wesnoth.org/t#####&amp;lt;/nowiki&amp;gt;'''&lt;br /&gt;
* Post the itch.io devlog (copy of the Discord announcement).&lt;br /&gt;
* Update the wesnoth.org front page.&lt;br /&gt;
** See a previous version update commit to the '''wesmere''' repository.&lt;br /&gt;
** ssh into the website VM and execute the following shell commands (yes, it is specifically ''''make'''', not ''''make install''''!):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;sudo -iu wesnoth&lt;br /&gt;
cd ~/git/wesmere/static&lt;br /&gt;
git pull&lt;br /&gt;
make&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Generate the Steam announcement by running the following command in your local wesnoth repository root:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;python3 data/tools/steam-changelog changelog.md &amp;lt;version&amp;gt; &amp;gt; &amp;lt;version&amp;gt;.txt&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Post the Steam announcement.&lt;br /&gt;
* Log into Wesnoth's Steam page.&lt;br /&gt;
** Click &amp;quot;A Game Update&amp;quot;.&lt;br /&gt;
** Pick &amp;quot;Small Update&amp;quot;.&lt;br /&gt;
** Paste the output of of the above python command into the event description.&lt;br /&gt;
** Click &amp;quot;Link To Build&amp;quot; and select the appropriate branch.&lt;br /&gt;
** Edit the appropriate .xcf file from the [https://github.com/wesnoth/resources/tree/master/social-media-assets Resources repository] ('''wesnoth_event_header.xcf''' for stable releases, '''wesnoth_beta_header.xcf''' for development releases) and export it to PNG.&lt;br /&gt;
*** This requires the '''oldania''' font to be installed, which on Linux/Ubuntu-derivatives can be installed via the command:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;apt install fonts-adf-oldania&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Post the announcement to Fosstodon.&lt;br /&gt;
* Post the announcement to Reddit. (Elvish_Hunter)&lt;br /&gt;
** Add the &amp;quot;Development release&amp;quot;/&amp;quot;Stable release&amp;quot; flair.&lt;br /&gt;
** Don't paste the link in the post, directly post it as a link.&lt;br /&gt;
&lt;br /&gt;
== New Stable Series ==&lt;br /&gt;
=== Beta 1 ===&lt;br /&gt;
Write up the new Start page (ie: https://www.wesnoth.org/start/1.16/).&lt;br /&gt;
&lt;br /&gt;
=== Beta 2 ===&lt;br /&gt;
Make the new Start page available to Translators.&lt;br /&gt;
&lt;br /&gt;
=== RC1 ===&lt;br /&gt;
Before release, the new multiplayer server and add-ons server instances need to be setup. The server running the website status is owned by Iris - she needs to push updates to it.&lt;br /&gt;
* Multiplayer server&lt;br /&gt;
** Needs no changes since it goes to port 15000 and then that redirects based on version. The existing dev multiplayer server will be reused as the new stable instance.&lt;br /&gt;
** The Discord website status bot and the site status page (https://status.wesnoth.org/ - bin/valen.pl) need to be updated to rename the dev version to the stable version.&lt;br /&gt;
** A new stable multiplayer instance needs to be added to the alternate server.&lt;br /&gt;
&lt;br /&gt;
* Add-ons server - The port is the version number, for example 1.16 is 15016, 1.18 is 15018, etc.&lt;br /&gt;
** C++ update (currently default_campaignd_port in addon/validation.cpp)&lt;br /&gt;
** Python update (data/tools/wesnoth/campaignserver_client.py)&lt;br /&gt;
** Website update (bin/valen.pl) in the valen repository to add the new instance.&lt;br /&gt;
** The Discord website status bot and the site status page (https://status.wesnoth.org/ - bin/valen.pl) need to be updated to add the new version.&lt;br /&gt;
** Add a 1.18 cron job for ~wesnoth/bin/update_addons in the websites VM and remove the 1.17 cron job.&lt;br /&gt;
&lt;br /&gt;
* Flatpak&lt;br /&gt;
** &lt;br /&gt;
&lt;br /&gt;
* Add screenshots to https://wiki.wesnoth.org/Screenshots&lt;br /&gt;
&lt;br /&gt;
* Start page - soft link the folder from the repository to the folder that shows up on the actual website:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
cd /srv/www/html/start&lt;br /&gt;
ln -s /home/git/wesnoth/start/&amp;lt;version&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Update ci_main.yml to use the new branch instead of the master branch.&lt;br /&gt;
&lt;br /&gt;
[[Category:Release_Notes]]&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Template:DevDownload&amp;diff=74633</id>
		<title>Template:DevDownload</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Template:DevDownload&amp;diff=74633"/>
		<updated>2025-11-19T04:56:37Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
== Development (1.19 branch) ==&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
==== Windows (10 1903 and later) {{{4|}}} ====&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.18 | filename=wesnoth-1.19.18-win64.exe |&lt;br /&gt;
hash=3bea895b5ac6520af3c7217283afcc7e17eb96924c3859e559fd04adb35f6fe8}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.17 | filename=wesnoth-1.19.17-win64.exe |&lt;br /&gt;
hash=3043cf6db1dcd17c341ee8af7d625a9d561cc06fbf091297a0aa6d3f413b21bb}}&lt;br /&gt;
&lt;br /&gt;
==== macOS (10.13 and later) {{{5|}}} ====&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.18 | filename=Wesnoth_1.19.18.dmg |&lt;br /&gt;
hash=e3c7490086c6d4200c991e54e541eb830ce2252a453a10ce07dfc0913fd3df23}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.17 | filename=Wesnoth_1.19.17.dmg |&lt;br /&gt;
hash=0216cd5837af30de1b072d325d11477fa8a1409b22e9fc3ebf46fcc78b8f10b2}}&lt;br /&gt;
&lt;br /&gt;
==== Source code ====&lt;br /&gt;
* [https://github.com/wesnoth/wesnoth/blob/master/INSTALL.md Compiling Wesnoth] - How to compile the source code&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.18 | filename=wesnoth-1.19.18.tar.bz2 |&lt;br /&gt;
hash=22c788998a7555def490ca559844a8721029e25a5529d8584dfbc15f2a579b72}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.17 | filename=wesnoth-1.19.17.tar.bz2 |&lt;br /&gt;
hash=7a4f65b3bd845fc923a8f745591062061f5f72cedd4f81edb93e42b8e6b162ea}}&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Credits&amp;diff=74632</id>
		<title>Credits</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Credits&amp;diff=74632"/>
		<updated>2025-11-18T02:08:09Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&amp;quot;tright&amp;quot;&amp;gt; __TOC__ &amp;lt;/div&amp;gt;&lt;br /&gt;
__NOEDITSECTION__&lt;br /&gt;
In July 2003, '''David White''' released the first version of Wesnoth. Since&lt;br /&gt;
then, many people have joined the project, contributing in very different ways.&lt;br /&gt;
&lt;br /&gt;
To make any changes to this list, please modify&lt;br /&gt;
&amp;lt;code class=&amp;quot;noframe&amp;quot;&amp;gt;about.cfg&amp;lt;/code&amp;gt; in the repo or ask any developer to do&lt;br /&gt;
it for you.&lt;br /&gt;
&lt;br /&gt;
== Core Contributors ==&lt;br /&gt;
=== Programming ===&lt;br /&gt;
* [mailto:dave&amp;amp;#x40;whitevine&amp;amp;#x2E;net David White] (Sirp) &amp;amp;#8212; Founding Developer&lt;br /&gt;
&amp;lt;hr style='clear:none'&amp;gt;&lt;br /&gt;
* [mailto:AI0867&amp;amp;#x40;gmail&amp;amp;#x2E;com Alexander van Gessel] (AI/AI0867)&lt;br /&gt;
* Alfredo Beaumont (ziberpunk) &amp;amp;#8212; autotools&lt;br /&gt;
* Ali El Gariani ([[User:Alink|alink]]) &amp;amp;#8212; coder, bug fixes, optimizations, interface usability&lt;br /&gt;
* András Salamon ([[User:Ott|ott]]) &amp;amp;#8212; QA, bug fixing, subediting, game mechanics&lt;br /&gt;
* Andreas Löf (Aginor)&lt;br /&gt;
* Anonymissimus &amp;amp;#8212; bug fixes and features mostly related to the wml engine or lua interface&lt;br /&gt;
* [mailto:artemkhrapov2001ATyandexDOTru Artem Khrapov] ([[User:Kabachuha|kabachuha]]) &amp;amp;#8212; addons server rework, incremental updates and uploads feature; i18n, UI and quality of life improvements; bugfixes&lt;br /&gt;
* [mailto:dragonking&amp;amp;#x40;o2&amp;amp;#x2E;pl Bartek Waresiak] (Dragonking) &amp;amp;#8212; unit balancing, Formula AI&lt;br /&gt;
* Benoît Timbert ([[User:Noyga|Noyga]])&lt;br /&gt;
* Bram Ridder (Morloth) &amp;amp;#8212; editor improvements&lt;br /&gt;
* [mailto:bruno&amp;amp;#x40;wolff&amp;amp;#x2E;to Bruno Wolff III] ([[User:bruno|bruno]]) &amp;amp;#8212; campaign web interface, bug fixing, minor coder&lt;br /&gt;
* Cameron Morland&lt;br /&gt;
* Cédric Duval &amp;amp;#8212; coder, internationalization manager&lt;br /&gt;
* Charles Dang (vultraz) &amp;amp;#8212; General fixes, cleanup and improvements to various areas.&lt;br /&gt;
* Chris Beck (iceiceice/involution) &amp;amp;#8212; Bug fixes and features esp. engine-related or multiplayer-related. Added WML unit testing system, improvements to travis-CI.&lt;br /&gt;
* Celtic Minstrel&lt;br /&gt;
* Daniel Franke (dfranke)&lt;br /&gt;
* Daniel (gfgtdf)&lt;br /&gt;
* David Hilton&lt;br /&gt;
* Descacharrado&lt;br /&gt;
* Dominic Bolin (Xan)&lt;br /&gt;
* Elias Pschernig (allefant)&lt;br /&gt;
* Elvish_Hunter&lt;br /&gt;
* Eric S. Raymond (ESR) &amp;amp;#8212; Macro library reorganization, major UI makeover introducing lightweight transparent popups and linger mode, maintenance tools for WML, eight campaigns lifted from UMC, one all-original campaign, editor refactoring, many many code cleanups, and svn-to-git migration.&lt;br /&gt;
* Eugen Jiresch (euschn) &amp;amp;#8212; savegame improvements&lt;br /&gt;
* [mailto:fabianmueller5_at_gmx&amp;amp;#x2E;de Fabian Müller] ([[User:fabi|fabi/fendrin]])&lt;br /&gt;
* [mailto:gabrielmorin~_-AT-_~gmail&amp;amp;#x2E;com Gabriel Morin] (gabba) &amp;amp;#8212; Whiteboard project, naming hotseat players, delay shroud updates on game start.&lt;br /&gt;
* Greg Copeland (Oracle) &amp;amp;#8212; coding; Server optimizations.&lt;br /&gt;
* Gregory Lundberg (TadCarlucci) &amp;amp;#8212; Cleanup of campaigns code&lt;br /&gt;
* [mailto:cornmander&amp;amp;#x40;cornmander&amp;amp;#x2E;com Gregory Shikhman] (corn) &amp;amp;#8212; coding; upload log maintenance/improvements&lt;br /&gt;
* Guillaume Melquiond (silene) &amp;amp;#8212; coding, bug fixes&lt;br /&gt;
* [mailto:billybiset&amp;amp;#x40;gmail&amp;amp;#x2E;com Guillermo Biset] (billynux) &amp;amp;#8212; Bug fixer, remover of upload stats, network module rewrite, ANA, boost::asio&lt;br /&gt;
* [mailto:shadowm2006&amp;amp;#x40;gmail&amp;amp;#x2E;com Iris Morelle] ([[User:Shadowm|Irydacea/shadowm]]) &amp;amp;#8212; Miscellaneous WML, i18n and UI features, improvements and bugfixes; refactoring and extension of add-ons management code; features and refactoring of image-path functions mechanism; cache manager UI and paths/game version dialog; campaignd refactoring and maintenance&lt;br /&gt;
* Jérémy Rosen ([[User:Boucman|Boucman]]) &amp;amp;#8212; coder&lt;br /&gt;
* [mailto:mcnabb&amp;amp;#x40;gravity&amp;amp;#x2E;psu&amp;amp;#x2E;edu John W. C. McNabb] (Darth Fool) &amp;amp;#8212; coder, graphics&lt;br /&gt;
* Jon Daniel (worduk) &amp;amp;#8212; coder, bug fixes&lt;br /&gt;
* Jörg Hinrichs (Yogi Bear/YogiHH)&lt;br /&gt;
* [mailto:justin&amp;amp;#x2E;zaun&amp;amp;#x40;gmail&amp;amp;#x2E;com Justin Zaun] (jzaun) &amp;amp;#8212; coder, scenario designer&lt;br /&gt;
* Jyrki Vesterinen&lt;br /&gt;
* Karol Nowak (grzywacz) &amp;amp;#8212; bug fixes, sound sources, gp2x port&lt;br /&gt;
* [mailto:erl&amp;amp;#x40;erl&amp;amp;#x2E;se Kristoffer Erlandsson] (erl) &amp;amp;#8212; help system, editor&lt;br /&gt;
* [mailto:lao&amp;amp;#x2E;geek&amp;amp;#x40;gmail&amp;amp;#x2E;com Lao] ([[User:lao|lao]]) &amp;amp;#8212; bug fixes and candidate to GSoC 2008&lt;br /&gt;
* macabeus &amp;amp;#8212; wesnoth-map-diff author&lt;br /&gt;
* Mark de Wever ([[User:SkeletonCrew|Mordante/SkeletonCrew]]) &amp;amp;#8212; coder, bug fixes, various features, multi-letter terrain system, gui system.&lt;br /&gt;
* Martin Renold (maxy/martinxyz) &amp;amp;#8212; performance and gui bug fixes&lt;br /&gt;
* Matthias Kretz &amp;amp;#8212; optimizations&lt;br /&gt;
* Moritz Göbelbecker (mog) &amp;amp;#8212; Work on the terrain engine&lt;br /&gt;
* Nicolas Weeger (Ryo) &amp;amp;#8212; Python API&lt;br /&gt;
* [mailto:patrick_x99&amp;amp;#x40;hotmail&amp;amp;#x2E;com Patrick Parker] ([[User:Sapient|Sapient]]) &amp;amp;#8212; improvements to user interface, WML engine, various features&lt;br /&gt;
* [mailto:paniemin&amp;amp;#x40;cc&amp;amp;#x2E;hut&amp;amp;#x2E;fi Pauli Nieminen] (suokko) &amp;amp;#8212; Bug fixing; usually targeting MP or WML engine&lt;br /&gt;
* [mailto:philippe&amp;amp;#x2E;plantier&amp;amp;#x40;naema&amp;amp;#x2E;org Philippe Plantier] ([[User:Ayin|Ayin]]) &amp;amp;#8212; several parts of the code, notably terrain graphics code&lt;br /&gt;
* Rusty Russell (rusty)&lt;br /&gt;
* Sergey Popov (loonycyborg) &amp;amp;#8212; scons&lt;br /&gt;
* singalen &amp;amp;#8212; iOS port&lt;br /&gt;
* slayer95&lt;br /&gt;
* Soliton &amp;amp;#8212; bug fixes and various small features usually in multiplayer context&lt;br /&gt;
* Steve Cotton (octalot)&lt;br /&gt;
* Steven Oxley (xonev)&lt;br /&gt;
* [mailto:suvrax&amp;amp;#x40;gmail&amp;amp;#x2E;com Subhraman Sarkar] (LumiousE/babaissarkar) &amp;amp;#8212; UI features, with bugfixes in various areas. Co-creator of Celes theme. WIP Android port (1.19).&lt;br /&gt;
* Thomas Baumhauer (Baufo)&lt;br /&gt;
* [mailto:timotei21&amp;amp;#x40;gmail&amp;amp;#x2E;com Timotei Dolean] (timotei) &amp;amp;#8212; Eclipse UMC plugin&lt;br /&gt;
* Tomasz Śniatowski (ilor) &amp;amp;#8212; Editor&lt;br /&gt;
* [mailto:ydirson&amp;amp;#x40;altern&amp;amp;#x2E;org Yann Dirson] &amp;amp;#8212; gettext support, tinygui&lt;br /&gt;
* [mailto:terraninfo&amp;amp;#x40;terraninfo&amp;amp;#x2E;net Yurii Chernyi] (Crab) &amp;amp;#8212; AI&lt;br /&gt;
=== General Purpose Administration and Coordination ===&lt;br /&gt;
* Pentarctagon &amp;amp;#8212; Current release manager (1.15.4-present)&lt;br /&gt;
&amp;lt;hr style='clear:none'&amp;gt;&lt;br /&gt;
* Charles Dang (vultraz) &amp;amp;#8212; Past release manager (1.13.3-1.15.3)&lt;br /&gt;
* Crossbow/Miyo &amp;amp;#8212; Past release manager&lt;br /&gt;
* [mailto:shadowm2006&amp;amp;#x40;gmail&amp;amp;#x2E;com Iris Morelle] ([[User:Shadowm|Irydacea/shadowm]]) &amp;amp;#8212; Past release manager (1.12.1-1.12.6 / 1.13.0-1.13.2)&lt;br /&gt;
* [mailto:isaac&amp;amp;#x40;sindominio&amp;amp;#x2E;net Isaac Clerencia] &amp;amp;#8212; Past release manager, Debian packager&lt;br /&gt;
* [mailto:Crazy-Ivanovic&amp;amp;#x40;gmx&amp;amp;#x2E;net Nils Kneuper] (Ivanovic) &amp;amp;#8212; Past release manager, internationalization manager, OpenPandora packager, A Tale of Two Brothers, German translation&lt;br /&gt;
* Noy &amp;amp;#8212; General purpose administration, unit balancing&lt;br /&gt;
=== Internationalization Managers ===&lt;br /&gt;
* Cédric Duval &amp;amp;#8212; coder, internationalization manager&lt;br /&gt;
* David Philippi (Torangan) &amp;amp;#8212; internationalization manager, wescamp&lt;br /&gt;
* Mark Michelsen (skovbaer) &amp;amp;#8212; Slackware packager&lt;br /&gt;
* [mailto:Crazy-Ivanovic&amp;amp;#x40;gmx&amp;amp;#x2E;net Nils Kneuper] (Ivanovic) &amp;amp;#8212; administrator, release manager, internationalization manager, OpenPandora packager, A Tale of Two Brothers, german translation&lt;br /&gt;
* [mailto:susanna&amp;amp;#x2E;bjorverud&amp;amp;#x40;telia&amp;amp;#x2E;com Susanna Björverud] (sanna)&lt;br /&gt;
=== Trailers ===&lt;br /&gt;
* ancestral &amp;amp;#8212; 1.12 trailer&lt;br /&gt;
* Pedro Caseiro (Kasdel) &amp;amp;#8212; 1.14 trailer&lt;br /&gt;
* Felix Merveille (felixmerveille) &amp;amp;#8212; 1.16 trailer edits and additions&lt;br /&gt;
=== Artwork and Graphics ===&lt;br /&gt;
* Emilien Rotival (LordBob) &amp;amp;#8212; portrait director - focus on loyalists, trolls, monsters&lt;br /&gt;
* Francisco Muñoz (fmunoz) &amp;amp;#8212; founding artist and former lead artist, worked consistently on all aspects till around v0.7-0.9.&lt;br /&gt;
* Hogne Håskjold (frame/freim) &amp;amp;#8212; terrain art director, made much of the current terrains (esp. mountains)&lt;br /&gt;
* J.W. Bjerk ([[User:Eleazar|Eleazar]]) &amp;amp;#8212; terrain art director (esp. Chasm, Cave, Water), sprite animations, various visual tweaks&lt;br /&gt;
* James Woo (Pickslide) &amp;amp;#8212; portraits (major focus on orcs and campaigns, especially UtBS, TEI, TSoF)&lt;br /&gt;
* Kathrin Polikeit (Kitty) &amp;amp;#8212; portrait director - focus on mages/necromancers, elvish, naga, merfolk, and troll unit trees&lt;br /&gt;
* Lari Nieminen (zookeeper) &amp;amp;#8212; sprite animation, various visual tweaks, titlescreen and campaign maps (v1.11+), water animations (v1.13+)&lt;br /&gt;
* Neoriceisgood &amp;amp;#8212; sprite creator and animator (major focus on drakes, dwarves, saurians)&lt;br /&gt;
* Pekka Aikio (pekka) &amp;amp;#8212; tiles, esp. castles, and attack icons&lt;br /&gt;
* Phil Barber (thespaceinvader) &amp;amp;#8212; Dwarf and Saurian portraits, most of the drake animations, and a large amount on other stuff, esp. the dwarves.&lt;br /&gt;
* Richard Kettering ([[User:Jetryl|Jetrel]]) &amp;amp;#8212; art director/slave, major focus on sprites, portraits, buildings, and icons&lt;br /&gt;
* Timo Honkasalo (Sgt. Groovy) &amp;amp;#8212; New high-res logo for the game&lt;br /&gt;
&amp;lt;hr style='clear:none'&amp;gt;&lt;br /&gt;
* Alex Jarocha-Ernst (Jormungandr) &amp;amp;#8212; portraits&lt;br /&gt;
* Christophe Anjard (Christophe33) &amp;amp;#8212; made many of the old (c. v0.6) terrains, and some sprites for the dwarves&lt;br /&gt;
* Erkki Lonkainen (Eternal) &amp;amp;#8212; created and animated many replacement sprites (esp. ogre, orc assassin &amp;amp; spear units, and cockatrice)&lt;br /&gt;
* Jason Lutes &amp;amp;#8212; portraits (major focus on humans, some campaign portraits)&lt;br /&gt;
* Johann de Venecia (Johann) &amp;amp;#8212; drew the new campaign story art for HttT&lt;br /&gt;
* Leonhard &amp;amp;#8212; made several of the new attack icons&lt;br /&gt;
* Marcus Rosén (sleepwalker) &amp;amp;#8212; Animations (esp. Saurians, Dwarves, Horseman), dunefolk sprites, and portraits (Mermaid Initiate &amp;amp; Dune Herbalist)&lt;br /&gt;
* Mark Goodenough (Ranger M) &amp;amp;#8212; sprite animator&lt;br /&gt;
* Maximiliano Buis (Redeth) &amp;amp;#8212; Made nearly all of the idle animations, and some death animations (as of 1.3.1)&lt;br /&gt;
* Michael Gil de Muro (grp21) &amp;amp;#8212; portraits (for the campaign ‘The Rise of Wesnoth’)&lt;br /&gt;
* MJ (czyzby) &amp;amp;#8212; adjustments of the saurian sprites; animations for saurian spearthrower, javelineer, seer, and prophet&lt;br /&gt;
* Moritz Göbelbecker (mog) &amp;amp;#8212; tiles, esp. swamp, encampment, ice, and work with lava/chasm&lt;br /&gt;
* Niall Burton (Leonard03) &amp;amp;#8212; Minimalistic logo render&lt;br /&gt;
* Peter Geinitz (Shadow/Wayfarer) &amp;amp;#8212; sprite creator and animator&lt;br /&gt;
* Robert Bolin (Zebulon) &amp;amp;#8212; tiles, sprite editing and animations&lt;br /&gt;
&amp;lt;hr style='clear:none'&amp;gt;&lt;br /&gt;
* Andrew James Patterson (Kamahawk) &amp;amp;#8212; sprites&lt;br /&gt;
* antwerpz &amp;amp;#8212; sprite creator/animator for old saurian units&lt;br /&gt;
* Diego Brea (Cobretti) &amp;amp;#8212; sprite creator/animator&lt;br /&gt;
* EEL (EELuminatus) &amp;amp;#8212; sprite animator, provided death animations for the woses, some of the orcs, and an attack animation for the revenant&lt;br /&gt;
* Eli Dupree (Elvish Pillager) &amp;amp;#8212; sprites and animations&lt;br /&gt;
* Eric Holdos (Rev. V!)&lt;br /&gt;
* Gareth Miller (Gafgarion) &amp;amp;#8212; made some early sprites/tiles&lt;br /&gt;
* Gerald Clears (Smok'em Jags) &amp;amp;#8212; sprite animator&lt;br /&gt;
* James Barton (Sangel) &amp;amp;#8212; sprites&lt;br /&gt;
* Jami &amp;amp;#8212; rogue death and red mage idle animations&lt;br /&gt;
* Jerzy Brzozowski (Mefisto) &amp;amp;#8212; Various sprites and animations, tropical forests.&lt;br /&gt;
* Jesse Holland (Kestenvarn) &amp;amp;#8212; map illustrator of old titlescreen and campaign maps (v1.1 - v1.10)&lt;br /&gt;
* Johanna Manninen (lohari) &amp;amp;#8212; edited tiles, ported freeciv tiles used in very early versions of wesnoth&lt;br /&gt;
* John Muccigrosso (Eponymous Archon) &amp;amp;#8212; made some early sprites, such as the human bowmen&lt;br /&gt;
* Kuno Raffin (lurker) &amp;amp;#8212; Various terrain artwork&lt;br /&gt;
* Michael Mielewczik (Mille) &amp;amp;#8212; sprite animator&lt;br /&gt;
* Mikko Kraft (Deserter) &amp;amp;#8212; sprite animator&lt;br /&gt;
* Musketaquid &amp;amp;#8212; animated windmill / stone path&lt;br /&gt;
* Slainte &amp;amp;#8212; made sprites for c. v0.6 mages, also made many of the old attack icons&lt;br /&gt;
* Simon Forsyth (Alarantalara) &amp;amp;#8212; cave terrain&lt;br /&gt;
* Stephen Metcalf (Neoskel) &amp;amp;#8212; major help with shadow standardization (over half the units), made some missing zombie variants&lt;br /&gt;
* Stephen Stone (Disto) &amp;amp;#8212; sprite animator&lt;br /&gt;
* Svetac &amp;amp;#8212; made many of the old attack icons&lt;br /&gt;
* Tristan Millner (tatmf) &amp;amp;#8212; made old portrait of dwarven fighter&lt;br /&gt;
* Zhukov &amp;amp;#8212; sprite animator&lt;br /&gt;
&amp;lt;hr style='clear:none'&amp;gt;&lt;br /&gt;
* Aaron Redfern (A-Red) &amp;amp;#8212; Sprites and animations&lt;br /&gt;
* Adrian Sheehy (Major) &amp;amp;#8212; various sprites animations&lt;br /&gt;
* Alexander Brown (Cloud) &amp;amp;#8212; Sprite animations&lt;br /&gt;
* Anton Ecker (Kaldred) &amp;amp;#8212; burnt villages&lt;br /&gt;
* battlestar &amp;amp;#8212; - some scenery graphics including burnt tent.&lt;br /&gt;
* Ben Wenzel (artisticdude) &amp;amp;#8212; Sprite animations&lt;br /&gt;
* Blarumyrran &amp;amp;#8212; New storm trident, staff and ankh item pictures, various attack icons, river ford tiles, drake and human city villages&lt;br /&gt;
* Bora Orcal (bera) &amp;amp;#8212; Goblin portrait sketches&lt;br /&gt;
* Cernunnos &amp;amp;#8212; merfolk villages&lt;br /&gt;
* Charles Dang (vultraz) &amp;amp;#8212; Icons for new editor and updated terrain icons&lt;br /&gt;
* Chris Wilson (Valkier) &amp;amp;#8212; portraits&lt;br /&gt;
* Christian Sirviö (Girgistian) &amp;amp;#8212; portraits (sketches), and some attack animations for the orcs&lt;br /&gt;
* Clinton Bell &amp;amp;#8212; various animations&lt;br /&gt;
* Dan Gerhards (beetlenaut) &amp;amp;#8212; various sprites and animations&lt;br /&gt;
* Daniel Borgmann (dborg) &amp;amp;#8212; semi-transparent map grid&lt;br /&gt;
* Daniel Foerster (pydsigner/pyndragon) &amp;amp;#8212; Icon overlays for the About dialog button&lt;br /&gt;
* Kwandulin &amp;amp;#8212; Standing animations (Skeleton Archer, Bone Shooter, Orcish Archer, Dwarvish Fighter, Ulfserker, Stalwart, Runesmith), minor fixes&lt;br /&gt;
* doofus-01 &amp;amp;#8212; orcish fort and villages, desert mountains, mine walls, sea forts, portraits for walking corpse and soulless&lt;br /&gt;
* Elena Astanina (ayona) &amp;amp;#8212; log-cabin villages&lt;br /&gt;
* Eric Butler (Erk) &amp;amp;#8212; desert and merfolk villages&lt;br /&gt;
* Evan Crook (Flametrooper) &amp;amp;#8212; sprite animator (TC conversion)&lt;br /&gt;
* Garrett Wessner (Stilgar) &amp;amp;#8212; gold coin pile&lt;br /&gt;
* Gideon Chia (Deonjo) &amp;amp;#8212; new ‘units’ icon for general status bar&lt;br /&gt;
* Guangcong Luo (Zarel) &amp;amp;#8212; Multiplayer status icons for 1.7.x&lt;br /&gt;
* Highhole &amp;amp;#8212; revised storm trident&lt;br /&gt;
* Homunculus &amp;amp;#8212; dead great tree terrain&lt;br /&gt;
* [mailto:shadowm2006&amp;amp;#x40;gmail&amp;amp;#x2E;com Iris Morelle] ([[User:Shadowm|Irydacea/shadowm]]) &amp;amp;#8212; Minor item/unit edits; animated lit brazier; ported gryphon rider animation to generic gryphon; Ancient Lich for 1.12.x&lt;br /&gt;
* Irrevenant &amp;amp;#8212; Skeleton archer death and recruit animations, new ankh touch ups, new dark adept touch ups, elvish marshal standing animation&lt;br /&gt;
* Irwin Ismail (Swordy) &amp;amp;#8212; original projectile/attack icon for chakram&lt;br /&gt;
* Jason Frailey (Valdroni) &amp;amp;#8212; scorpion portrait&lt;br /&gt;
* Jimmy Olsson (Azlan) &amp;amp;#8212; made old icons for windows version&lt;br /&gt;
* Joakim Persson (JAP) &amp;amp;#8212; Knalgan flag set&lt;br /&gt;
* John Mercer (Stern) &amp;amp;#8212; Giant Rat graphics&lt;br /&gt;
* John-Robert Funck (XJaPaN) &amp;amp;#8212; sprite animator&lt;br /&gt;
* Jonatan Alamà (tin) &amp;amp;#8212; made red logo used until before v1.0&lt;br /&gt;
* Justin Nichols (JustinOperable) &amp;amp;#8212; Portrait artwork&lt;br /&gt;
* Kim Holm (DUHH) &amp;amp;#8212; Portrait artwork&lt;br /&gt;
* Lukasz Wawrowski (inferno8) &amp;amp;#8212; Drake attack icons with fmunoz and map backgrounds for Isar’s Cross&lt;br /&gt;
* Lordlewis &amp;amp;#8212; mace item sprite&lt;br /&gt;
* Luke Bunday (Amorphous) &amp;amp;#8212; New (1.17) swordsman attack animation&lt;br /&gt;
* Mattias Westlund (West) &amp;amp;#8212; new color cursors&lt;br /&gt;
* Nicholas Kerpan (Thrawn) &amp;amp;#8212; human thief portrait&lt;br /&gt;
* Pixelmind &amp;amp;#8212; various animations&lt;br /&gt;
* Randall Walls (slightcrazed) &amp;amp;#8212; sprite animator&lt;br /&gt;
* rhyging5 &amp;amp;#8212; various animations&lt;br /&gt;
* RusHHouR &amp;amp;#8212; New signpost (1.4.1)&lt;br /&gt;
* Samuel Wilson (megane) &amp;amp;#8212; random dice icon fix after 1.4.0&lt;br /&gt;
* Santiago Iborra (Quellion) &amp;amp;#8212; Portrait artwork&lt;br /&gt;
* Simeon Dear (Trilby) &amp;amp;#8212; Sprite animations&lt;br /&gt;
* Zoomo &amp;amp;#8212; Sprite animations&lt;br /&gt;
* Zaggy1024 &amp;amp;#8212; Wolf rider death animation&lt;br /&gt;
* Eisfrei &amp;amp;#8212; Elvish shaman idle animations&lt;br /&gt;
* Happy Wose &amp;amp;#8212; Wose idle frames and Elder wose death animation&lt;br /&gt;
* Wolfy &amp;amp;#8212; Female arch mage idle animation&lt;br /&gt;
* mystic x the unknown &amp;amp;#8212; Mage death animation&lt;br /&gt;
* Sonny T Yamada (SkyOne) &amp;amp;#8212; shadow standardization of many campaign units&lt;br /&gt;
* Vincent Langner (Vyncyn) &amp;amp;#8212; Walking Corpse and Soulless wolf variations, young roc base and attack sprite&lt;br /&gt;
* ZygoUgo &amp;amp;#8212; Giant Rat portrait&lt;br /&gt;
* ghype &amp;amp;#8212; sprite animation and dunefolk base frames&lt;br /&gt;
* Tony Moseley (Helmet) &amp;amp;#8212; initial dragonfly sprites&lt;br /&gt;
=== Music ===&lt;br /&gt;
* Aleksi Aubry-Carlson (Aleksi)&lt;br /&gt;
* Doug Kaufman (dkaufman) &amp;amp;#8212; http://dougkaufman.net/&lt;br /&gt;
* Gianmarco Leone (gmlion)&lt;br /&gt;
* Jeremy Nicoll (jeremy2/eltiare)&lt;br /&gt;
* Joseph Toscano (ZhayTee) &amp;amp;#8212; zhaymusic.com&lt;br /&gt;
* Mattias Westlund (West) &amp;amp;#8212; music coordinator/composer&lt;br /&gt;
* Ryan Reilly (Rain)&lt;br /&gt;
* Stephen Rozanc (TreizeCouleurs)&lt;br /&gt;
* Timothy Pinkham (TimothyP)&lt;br /&gt;
* Tyler Johnson&lt;br /&gt;
=== Sound Effects ===&lt;br /&gt;
* Corey Woodworth (woodwizzle) &amp;amp;#8212; hit and die sounds&lt;br /&gt;
* J.W. Bjerk ([[User:Eleazar|Eleazar]])&lt;br /&gt;
* Lari Nieminen (zookeeper) &amp;amp;#8212; focus on attack, weapon and user interface sounds&lt;br /&gt;
* Adam Rinsky (Action Jack) &amp;amp;#8212; dwarf hit and die sounds&lt;br /&gt;
* Leonardo Magno Sampaio (leorock116) &amp;amp;#8212; mace, staff and club sounds&lt;br /&gt;
=== Campaign Design ===&lt;br /&gt;
* Asa Swain (quartex) &amp;amp;#8212; Under the Burning Suns&lt;br /&gt;
* Astrid Halberkamp &amp;amp;#8212; Campaign maintenance and various improvements&lt;br /&gt;
* Benjamin Drieu&lt;br /&gt;
* Charles Dang (vultraz) &amp;amp;#8212; Campaign maintenance and various improvements&lt;br /&gt;
* Dacyn&lt;br /&gt;
* Dan Gerhards (beetlenaut) &amp;amp;#8212; Dead Water, Secrets of the Ancients&lt;br /&gt;
* David White (Sirp) &amp;amp;#8212; Heir to the Throne&lt;br /&gt;
* Eric J. Mesoy (Circon) &amp;amp;#8212; A Tale of Two Brothers&lt;br /&gt;
* Eric S. Raymond (ESR) &amp;amp;#8212; The Hammer of Thursagan&lt;br /&gt;
* esci &amp;amp;#8212; Descent into Darkness&lt;br /&gt;
* Francisco Muñoz (fmunoz) &amp;amp;#8212; founding artist and former lead artist, worked consistently on all aspects till around v0.7-0.9.&lt;br /&gt;
* James Spencer (Shade) &amp;amp;#8212; The Rise of Wesnoth&lt;br /&gt;
* Jeffrey ‘Sigurd’ Westcoat (SigurdFireDragon) &amp;amp;#8212; Winds of Fate&lt;br /&gt;
* Jonathan Kelly (name) &amp;amp;#8212; Winds of Fate&lt;br /&gt;
* Joseph Simmons (Turin) &amp;amp;#8212; The Eastern Invasion, The Sceptre of Fire&lt;br /&gt;
* Justin Zaun (jzaun) &amp;amp;#8212; coder, scenario designer&lt;br /&gt;
* Lari Nieminen (zookeeper) &amp;amp;#8212; redesign of various scenarios and other enhancement&lt;br /&gt;
* [mailto:Crazy-Ivanovic&amp;amp;#x40;gmx&amp;amp;#x2E;net Nils Kneuper] (Ivanovic) &amp;amp;#8212; A Tale of Two Brothers&lt;br /&gt;
* Santi/fnaek &amp;amp;#8212; The Legend of Wesmere&lt;br /&gt;
* Scott Klempner &amp;amp;#8212; Heir to the Throne, The Rise of Wesnoth, Liberty&lt;br /&gt;
* Taurus &amp;amp;#8212; Northern Rebirth, Son of the Black-Eye&lt;br /&gt;
* William Carey (aelius) &amp;amp;#8212; The South Guard&lt;br /&gt;
=== Multiplayer Maps and Balancing ===&lt;br /&gt;
* George Birthisel (happygrue/Wintermute) &amp;amp;#8212; Unit balancing, Dunefolk Era&lt;br /&gt;
* Hejnewar &amp;amp;#8212; balancing for Age of Heroes, revised dunefolk&lt;br /&gt;
* Jake Bailey (jb) &amp;amp;#8212; multiplayer maps&lt;br /&gt;
* Joshua Northey (Becephalus) &amp;amp;#8212; multiplayer maps (mostly 2vs2 and up)&lt;br /&gt;
* Mike Quiñones (Doc Paterson) &amp;amp;#8212; multiplayer maps (mostly 1vs1)&lt;br /&gt;
* Noy &amp;amp;#8212; general purpose administration, unit balancing&lt;br /&gt;
* Peter Groen (pg) &amp;amp;#8212; multiplayer maps&lt;br /&gt;
* Ruben Philipp Wickenhäuser (The Very Uhu) &amp;amp;#8212; multiplayer maps&lt;br /&gt;
* Soliton &amp;amp;#8212; unit balancing&lt;br /&gt;
* Tom Chance (telex4) &amp;amp;#8212; multiplayer maps&lt;br /&gt;
* [mailto:kleinfel&amp;amp;#x40;wpi&amp;amp;#x2E;edu Zack Kleinfeld] &amp;amp;#8212; multiplayer maps, unit balancing&lt;br /&gt;
=== Packagers ===&lt;br /&gt;
* ancestral &amp;amp;#8212; Apple OS X packager (1.12.1 and later)&lt;br /&gt;
* [mailto:hrubymar10&amp;amp;#x40;gmail&amp;amp;#x2E;com Martin Hrubý] ([[User:hrubymar10|hrubymar10]]) &amp;amp;#8212; Apple macOS packager (1.13.11 and later)&lt;br /&gt;
* Matthias Schoeck (mattsc) &amp;amp;#8212; Apple OS X packager (1.11.8 and later)&lt;br /&gt;
* [mailto:Crazy-Ivanovic&amp;amp;#x40;gmx&amp;amp;#x2E;net Nils Kneuper] (Ivanovic) &amp;amp;#8212; OpenPandora packager&lt;br /&gt;
* [mailto:pj&amp;amp;#x40;pehjota&amp;amp;#x2E;net P. J. McDermott] (pehjota) &amp;amp;#8212; Debian/Ubuntu packager&lt;br /&gt;
* Rhonda D'Vine (Rhonda) &amp;amp;#8212; Debian/Ubuntu packager&lt;br /&gt;
* Sebastian Kölle (aquileia) &amp;amp;#8212; Visual Studio SDK maintainer&lt;br /&gt;
* Sergey Popov (loonycyborg) &amp;amp;#8212; Microsoft Windows packager and MinGW SDK maintainer&lt;br /&gt;
* [mailto:ports&amp;amp;#x40;toco-domains&amp;amp;#x2E;de Torsten Zühlsdorff] &amp;amp;#8212; FreeBSD Packager&lt;br /&gt;
* Vincent Cheng (vincent_c) &amp;amp;#8212; Debian/Ubuntu packager&lt;br /&gt;
&amp;lt;hr style='clear:none'&amp;gt;&lt;br /&gt;
* [mailto:ben&amp;amp;#x40;happyspork&amp;amp;#x2E;com Ben Anderman] (crimson_penguin) &amp;amp;#8212; Apple OS X packager (for 1.5.6 and later)&lt;br /&gt;
* Cyril Bouthors (CyrilB) &amp;amp;#8212; Debian packager, patron&lt;br /&gt;
* Darryl Dixon&lt;br /&gt;
* edge&lt;br /&gt;
* Isaac Clerencia &amp;amp;#8212; Debian packager&lt;br /&gt;
* Jay Hopping&lt;br /&gt;
* Jörg Hinrichs (Yogi Bear/YogiHH) &amp;amp;#8212; Microsoft Windows packager&lt;br /&gt;
* Laurent Wacrenier (lwa) &amp;amp;#8212; Apple OS X packager (for v1.4 and before)&lt;br /&gt;
* Marcin Konicki (ahwayakchih) &amp;amp;#8212; BeOS packager&lt;br /&gt;
* Marcus Phillips (Sithrandel) &amp;amp;#8212; Apple OS X packager (for v1.0 and before)&lt;br /&gt;
* Mark Michelsen (skovbaer) &amp;amp;#8212; Slackware packager&lt;br /&gt;
* Muhammad Amir Ayub (anakayub) &amp;amp;#8212; Apple OS X packager&lt;br /&gt;
* Piotr Cychowski (Mist/cycholka) &amp;amp;#8212; Microsoft Windows packager&lt;br /&gt;
* singalen &amp;amp;#8212; iOS port&lt;br /&gt;
* Simon Forsyth (Alarantalara) &amp;amp;#8212; Apple OS X Packager (1.9.6 and later)&lt;br /&gt;
* Vlad Glagolev (Stealth) &amp;amp;#8212; OpenBSD packager&lt;br /&gt;
=== Miscellaneous Contributors ===&lt;br /&gt;
* Aaron Keisch-Walter (Exasperation)&lt;br /&gt;
* Aaron Winter (Byteron)&lt;br /&gt;
* Adam Leffew&lt;br /&gt;
* Adrian Iosif (Zappaman)&lt;br /&gt;
* Aishiko &amp;amp;#8212; Unit instance recall cost implementation&lt;br /&gt;
* Alek Bollig (binarycoder)&lt;br /&gt;
* Alesis Novik&lt;br /&gt;
* Alexander Lacson (max_torch)&lt;br /&gt;
* Aline Riss (akihara)&lt;br /&gt;
* Amir Hassan (kallaballa)&lt;br /&gt;
* Andris Szell (bandita137)&lt;br /&gt;
* André Knispel&lt;br /&gt;
* Andrea Palmatè (afxgroup)&lt;br /&gt;
* Andrius Šilinskas (thunderstruck)&lt;br /&gt;
* Andrius Štikonas&lt;br /&gt;
* Anja Keicher (ayne)&lt;br /&gt;
* Astrid Halberkamp&lt;br /&gt;
* August Vesterbacka&lt;br /&gt;
* Ben Anderman (crimson_penguin) &amp;amp;#8212; unit list&lt;br /&gt;
* Boldizsár Lipka (lipk)&lt;br /&gt;
* Brilliand&lt;br /&gt;
* Burkay Özdemir (Velory) &amp;amp;#8212; Poisoning improvement for Formula AI&lt;br /&gt;
* chisquare130&lt;br /&gt;
* Chris Carpenter (mordocai)&lt;br /&gt;
* Chris Hopman (cjhopman)&lt;br /&gt;
* Chris Mann (WildPenguin) &amp;amp;#8212; Emacs WML-mode&lt;br /&gt;
* Chusslove Illich (caslav.ilic) &amp;amp;#8212; wmlxgetext improvements&lt;br /&gt;
* Cody Burchell (nullmoose)&lt;br /&gt;
* David Slabý (blaf)&lt;br /&gt;
* Daniel Bruegmann&lt;br /&gt;
* Daniel Santos&lt;br /&gt;
* David Mikos (Coffee) &amp;amp;#8212; Coder, animation framework improvements.&lt;br /&gt;
* Denny Vaccaro (endercoaster)&lt;br /&gt;
* Derek (Gambit)&lt;br /&gt;
* devnexen&lt;br /&gt;
* Discontinuum&lt;br /&gt;
* DisherProject&lt;br /&gt;
* Dmitry K. (nephro)&lt;br /&gt;
* Doug Rosvick ([[User:dlr365|dlr365]])&lt;br /&gt;
* dorng&lt;br /&gt;
* dreamer-88&lt;br /&gt;
* Dugi &amp;amp;#8212; Context-free name generator&lt;br /&gt;
* Duthlet&lt;br /&gt;
* EarthCake&lt;br /&gt;
* Edward Chernenko&lt;br /&gt;
* Ekdohibs&lt;br /&gt;
* elvish_sovereign&lt;br /&gt;
* Ely Levy (Nakee)&lt;br /&gt;
* Eric Gallager (egallager/cooljeanius)&lt;br /&gt;
* Étienne Simon (ejls)&lt;br /&gt;
* Etkin Baris Ozgul (pokhbocee) &amp;amp;#8212; Lua AI&lt;br /&gt;
* Eugene Kosov (kevg)&lt;br /&gt;
* evanmiller&lt;br /&gt;
* [mailto:eugeni&amp;amp;#x2E;stepanov&amp;amp;#x40;gmail&amp;amp;#x2E;com Evgeniy Stepanov] &amp;amp;#8212; NativeClient port&lt;br /&gt;
* Evgeny Kapun&lt;br /&gt;
* FAAB&lt;br /&gt;
* Federico Pasco (neverEnough)&lt;br /&gt;
* Fedor Khod'kov (teddy/fkhodkov)&lt;br /&gt;
* Felix Bauer (flix)&lt;br /&gt;
* Fernando Carmona (Ferk)&lt;br /&gt;
* Floris Kint (Grimling)&lt;br /&gt;
* Francesco Gigli (Jaramir)&lt;br /&gt;
* Frank Richter (res)&lt;br /&gt;
* Frédéric Wagner&lt;br /&gt;
* Fredrik Wikstrom (salass00)&lt;br /&gt;
* galegosimpatico&lt;br /&gt;
* Galen Brooks (fluffbeast)&lt;br /&gt;
* gh0st &amp;amp;#8212; 2012 Google Code-in Students’ Micro AI development&lt;br /&gt;
* Gothyoba&lt;br /&gt;
* Gregory Gauthier (rjaguar3)&lt;br /&gt;
* Groggy Dice (groggydice) &amp;amp;#8212; wmllint enhancements&lt;br /&gt;
* Guillaume Lestringant&lt;br /&gt;
* [mailto:kevin&amp;amp;#x2E;xgr&amp;amp;#x40;gmail&amp;amp;#x2E;com Guorui Xi] (Kevin_Xi)&lt;br /&gt;
* Hans-Joachim Gurt (HaJo)&lt;br /&gt;
* Herb Pah (haiz)&lt;br /&gt;
* holius-fr&lt;br /&gt;
* IceTyp&lt;br /&gt;
* ilyapopov&lt;br /&gt;
* J. Tyne (JaMiT)&lt;br /&gt;
* J.R. Blain (Cowboy)&lt;br /&gt;
* jstitch&lt;br /&gt;
* Jacek Kominek (BroodKiller)&lt;br /&gt;
* [mailto:benetnash&amp;amp;#x40;icpnet&amp;amp;#x2E;pl Jan Polak] (benetnash) &amp;amp;#8212; Formula AI contributions&lt;br /&gt;
* Jan Zvánovec (jaz)&lt;br /&gt;
* [mailto:babataz&amp;amp;#x40;gmail&amp;amp;#x2E;com Jean-Baptiste Poittevin] (BBT)&lt;br /&gt;
* Jeff Breidenbach (jab) &amp;amp;#8212; Bilinear interpolation&lt;br /&gt;
* [mailto:jleldridge27&amp;amp;#x40;gmail&amp;amp;#x2E;com Jeffrey Eldridge] (jleldridge)&lt;br /&gt;
* Jérôme (segfault)&lt;br /&gt;
* Jim Carroll (Jimm)&lt;br /&gt;
* Jody Northup (Upthorn) &amp;amp;#8212; Prospective student (world persistence)&lt;br /&gt;
* Joeri Melis&lt;br /&gt;
* Joey L. Maalouf (JDog)&lt;br /&gt;
* [mailto:john&amp;amp;#x40;jo&amp;amp;#x2E;hnanthony&amp;amp;#x2E;com John Anthony] &amp;amp;#8212; campaignd work, mainly security-based&lt;br /&gt;
* John B. Messerly (jbm)&lt;br /&gt;
* John Harvey (johndh) &amp;amp;#8212; minor race descriptions; bats, goblins, mechanical, merfolk, monster, naga, ogre&lt;br /&gt;
* Jonathan Combs (ScegfOd) &amp;amp;#8212; log activating dialog&lt;br /&gt;
* Jonas Lihnell (Roze)&lt;br /&gt;
* Jonas Kölker&lt;br /&gt;
* [mailto:jorda&amp;amp;#x40;ettin&amp;amp;#x2E;org Jordà Polo] (ettin) &amp;amp;#8212; website, i18n, ui&lt;br /&gt;
* Josef Reidinger (qk)&lt;br /&gt;
* Joseph Gelfand&lt;br /&gt;
* Joshua Hudson&lt;br /&gt;
* josteph&lt;br /&gt;
* Jozrael&lt;br /&gt;
* Justin DiSabatino (Turuk)&lt;br /&gt;
* Kamil Kaczmarczyk (lampak)&lt;br /&gt;
* [mailto:karl&amp;amp;#x2E;miller&amp;amp;#x2E;km&amp;amp;#x40;gmail&amp;amp;#x2E;com Karl Miller] (karlm)&lt;br /&gt;
* Karol Kozub (automagic)&lt;br /&gt;
* Kevin Montalva (Ryckes)&lt;br /&gt;
* Kevin Yap (iKevinY)&lt;br /&gt;
* Konrad Schwede (Konrad2)&lt;br /&gt;
* Kristoffer Grönlund (kegie)&lt;br /&gt;
* Krogen&lt;br /&gt;
* Larkin Nickle (larbob/larb0b/larbawb)&lt;br /&gt;
* Laurent Birtz&lt;br /&gt;
* legoktm&lt;br /&gt;
* leonardoInf&lt;br /&gt;
* lilinitsy&lt;br /&gt;
* Lovens Weche (LovCAPONE)&lt;br /&gt;
* Luiz Fernando de Faria Pereira (lfernando)&lt;br /&gt;
* [mailto:lutheroto&amp;amp;#x40;gmail&amp;amp;#x2E;com Luther Thompson]&lt;br /&gt;
* lv-zheng&lt;br /&gt;
* [mailto:code&amp;amp;#x40;hryniuk&amp;amp;#x2E;pl Łukasz Hryniuk]&lt;br /&gt;
* Maksim Orlovich (SadEagle)&lt;br /&gt;
* Mark McGuire (TronPaul)&lt;br /&gt;
* Martin Bede &amp;amp;#8212; 2012 Google Code-in Students’ Micro AI development&lt;br /&gt;
* [mailto:hrubymar10&amp;amp;#x40;gmail&amp;amp;#x2E;com Martin Hrubý] ([[User:hrubymar10|hrubymar10]])&lt;br /&gt;
* Mateusz Kolaczek (PL_kolek)&lt;br /&gt;
* Matt Renfer (Des) &amp;amp;#8212; Prose revision&lt;br /&gt;
* Matthias Schoeck (mattsc) &amp;amp;#8212; AI improvements&lt;br /&gt;
* matthiaskrgr &amp;amp;#8212; Running address sanitizer to catch leaks&lt;br /&gt;
* Maxim Biro (nurupo)&lt;br /&gt;
* Maximilian Fricke (madmax28)&lt;br /&gt;
* Maximilian Lupke (malumalu)&lt;br /&gt;
* Marius Spix (spixi)&lt;br /&gt;
* Michael Flowers (MJ)&lt;br /&gt;
* Michael Schmahl&lt;br /&gt;
* Michael Strebel (Nostromus)&lt;br /&gt;
* midzer&lt;br /&gt;
* Miguel Zapico (elricz)&lt;br /&gt;
* mstrebel&lt;br /&gt;
* [mailto:greywhind&amp;amp;#x40;users&amp;amp;#x2E;sourceforge&amp;amp;#x2E;net Nathan Partlan] ([[User:Greywhind|Greywhind]])&lt;br /&gt;
* [mailto:nathan&amp;amp;#x2E;b&amp;amp;#x2E;walker&amp;amp;#x40;vanderbilt&amp;amp;#x2E;edu Nathan Walker] (RiftWalker)&lt;br /&gt;
* neoedmund&lt;br /&gt;
* newfrenchy83&lt;br /&gt;
* Niall Burton (Leonard03)&lt;br /&gt;
* niegenug&lt;br /&gt;
* Nobun &amp;amp;#8212; wmlxgettext&lt;br /&gt;
* [mailto:zabivator&amp;amp;#x40;gmail&amp;amp;#x2E;com Oleg Tsarev]&lt;br /&gt;
* Olivier Faure (PoignardAzur)&lt;br /&gt;
* [mailto:pj&amp;amp;#x40;pehjota&amp;amp;#x2E;net P. J. McDermott] (pehjota) &amp;amp;#8212; horizontal scrolling regression fix, systemd _wesnoth user, system Lua, update_copyrights improvements&lt;br /&gt;
* [mailto:asqueados&amp;amp;#x40;gmail&amp;amp;#x2E;com Pablo J. Urbano Santos] ([[User:Lord Ork|Lord Ork]])&lt;br /&gt;
* Patryk Obara (dreamer_)&lt;br /&gt;
* Paul Smedley (Creeping)&lt;br /&gt;
* Paŭlo Ebermann ([[User:Pauxlo|Pauxlo]])&lt;br /&gt;
* PBechon&lt;br /&gt;
* Peter Elmers&lt;br /&gt;
* Peter Mawhorter ([[User:solsword|solsword]]) &amp;amp;#8212; Python TC script upgrade&lt;br /&gt;
* Petr Sobotka (Pietro)&lt;br /&gt;
* [mailto:root&amp;amp;#x40;delroth&amp;amp;#x2E;is-a-geek&amp;amp;#x2E;org Pierre Bourdon] (delroth)&lt;br /&gt;
* pquentin&lt;br /&gt;
* Pranav Deshpande (universecoder)&lt;br /&gt;
* Priit Laes (plaes)&lt;br /&gt;
* Pubudu Gunawardena (ugudu)&lt;br /&gt;
* Qi Mo (qmo2015)&lt;br /&gt;
* Quetzalcoatl&lt;br /&gt;
* Randy Kostiuk (Randypk) &amp;amp;#8212; Bug fixes&lt;br /&gt;
* RatArmy (fujimo-t)&lt;br /&gt;
* Reuben Rakete (rocketbang)&lt;br /&gt;
* Richard Yao (srk9) &amp;amp;#8212; Bug fixes&lt;br /&gt;
* Rikard Falkeborn&lt;br /&gt;
* Robert Spencer &amp;amp;#8212; 2012 Google Code-in Students’ Micro AI development&lt;br /&gt;
* Robert Wallace (Robertdebrus)&lt;br /&gt;
* Rocco J Carello (rogue)&lt;br /&gt;
* Roland Hautz (duncan_shriek)&lt;br /&gt;
* Rolf Sievers (Lizard)&lt;br /&gt;
* Ronny Standtke&lt;br /&gt;
* rrigby&lt;br /&gt;
* Ryan Frame&lt;br /&gt;
* Ryan Henszey&lt;br /&gt;
* Ryan Roden-Corrent (rcorre) &amp;amp;#8212; Hotkey release and scroll key rebinding&lt;br /&gt;
* [mailto:sachith500&amp;amp;#x40;gmail&amp;amp;#x2E;com Sachith Seneviratne] (sachith500) &amp;amp;#8212; Bug fixes at the moment. GSoC Aspirant&lt;br /&gt;
* Samuel Kim &amp;amp;#8212; 2012 Google Code-in Students’ Micro AI development&lt;br /&gt;
* Sean Yeh&lt;br /&gt;
* Sebastian Goll (afran)&lt;br /&gt;
* Sebastian Kölle (aquileia)&lt;br /&gt;
* Serge Martin (EdB)&lt;br /&gt;
* [mailto:stomasortiz&amp;amp;#x40;gmail&amp;amp;#x2E;com Sergio Tomás Ortiz]&lt;br /&gt;
* Severin Glöckner (Shiki, Sevu)&lt;br /&gt;
* Simon Forsyth (Alarantalara)&lt;br /&gt;
* [mailto:simon_smith&amp;amp;#x40;zen&amp;amp;#x2E;co&amp;amp;#x2E;uk Simon Smith] ([[User:Simons_Mith|Simons Mith]]) &amp;amp;#8212; Style guide, help with the application of the style guide, and some tips&lt;br /&gt;
* SoapGentoo&lt;br /&gt;
* starius&lt;br /&gt;
* Stéphane Gimenez (gim)&lt;br /&gt;
* [mailto:Majora700&amp;amp;#x40;gmail&amp;amp;#x2E;com Steven Panek] ([[User:Espreon|Espreon]])&lt;br /&gt;
* [mailto:sylecn&amp;amp;#x40;gmail&amp;amp;#x2E;com sylecn]&lt;br /&gt;
* [mailto:nsytyi&amp;amp;#x40;gmail&amp;amp;#x2E;com Sytyi Nick] (Sytyi) &amp;amp;#8212; WML validation&lt;br /&gt;
* [mailto:ptablot&amp;amp;#x40;mopong&amp;amp;#x2E;net Talbot Pierre] (Trademark)&lt;br /&gt;
* Tamas K. (negusnyul)&lt;br /&gt;
* techtonik&lt;br /&gt;
* the_beagle &amp;amp;#8212; Wose race description&lt;br /&gt;
* The Gnat&lt;br /&gt;
* Thewodoros &amp;amp;#8212; Eastern Invasion Maintenance&lt;br /&gt;
* Thibault Févry (iwontbecreative) &amp;amp;#8212; Some GCI tasks and utils/wiki_grabber.py cleanup.&lt;br /&gt;
* Thom Diment (UnwiseOwl)&lt;br /&gt;
* [mailto:hankerspace&amp;amp;#x40;gmail&amp;amp;#x2E;com Thomas Martinet] (hankerspace)&lt;br /&gt;
* [mailto:thomas&amp;amp;#x2E;prevost&amp;amp;#x40;gmail&amp;amp;#x2E;com Thomas Prevost] (zancdar)&lt;br /&gt;
* Thonsew&lt;br /&gt;
* Thorny23&lt;br /&gt;
* Tobias Frei (ToBeFree)&lt;br /&gt;
* Tomasz Sikorski (Tomsik)&lt;br /&gt;
* Tommy Schmitz&lt;br /&gt;
* Tommy (yobbo)&lt;br /&gt;
* Toom Lõhmus (Ravana)&lt;br /&gt;
* tsr&lt;br /&gt;
* Valentin Deschaintre (Zazweda, Epyde) &amp;amp;#8212; Zone guardian Micro AI&lt;br /&gt;
* vitiv &amp;amp;#8212; 2012 Google Code-in Students’ Micro AI development&lt;br /&gt;
* [mailto:viy&amp;amp;#x40;altlinux&amp;amp;#x2E;org viy]&lt;br /&gt;
* Vladimír Slávik &amp;amp;#8212; Miscellaneous text formatting and translation engine related help&lt;br /&gt;
* vn971, vgaming&lt;br /&gt;
* walodar&lt;br /&gt;
* Wedge009&lt;br /&gt;
* Yang Yifan (Xara)&lt;br /&gt;
* Zas&lt;br /&gt;
=== Bots ===&lt;br /&gt;
* CIA&lt;br /&gt;
* irker&lt;br /&gt;
* janebot&lt;br /&gt;
* shikadibot&lt;br /&gt;
* wesbot&lt;br /&gt;
== Translators ==&lt;br /&gt;
=== Afrikaans Translation ===&lt;br /&gt;
* András Salamon (ott)&lt;br /&gt;
* Erhard Eiselen&lt;br /&gt;
* Len van Dalsen (Numbers13) &amp;amp;#8212; current maintainer&lt;br /&gt;
* Nico Oliver (nicoza)&lt;br /&gt;
* Renier Maritz&lt;br /&gt;
=== Ancient Greek Translation ===&lt;br /&gt;
* Mejri Ziad (hermestrismi) &amp;amp;#8212; current maintainer&lt;br /&gt;
=== Arabic Translation ===&lt;br /&gt;
* Amnay Mokhtari&lt;br /&gt;
* Mejri Ziad (hermestrismi) &amp;amp;#8212; current maintainer&lt;br /&gt;
=== Asturian Translation ===&lt;br /&gt;
=== Basque Translation ===&lt;br /&gt;
* Alfredo Beaumont (ziberpunk)&lt;br /&gt;
* Julen Landa (genars)&lt;br /&gt;
* Mikel Olasagasti (Hey_neken)&lt;br /&gt;
=== Bengali Translation ===&lt;br /&gt;
* [mailto:suvrax&amp;amp;#x40;gmail&amp;amp;#x2E;com Subhraman Sarkar] (LumiousE/babaissarkar) &amp;amp;#8212; current maintainer&lt;br /&gt;
* Tahsin J Khalid (Lord-Knightmare) &amp;amp;#8212; maintainer (former)&lt;br /&gt;
=== Bulgarian Translation ===&lt;br /&gt;
* Anton Tsigularov (Atilla)&lt;br /&gt;
* Bono Nonchev&lt;br /&gt;
* Denica Mincheva (Deni)&lt;br /&gt;
* Georgi Dimitrov (oblak)&lt;br /&gt;
* Ivan Petrov (TheWhiteKnight) &amp;amp;#8212; current maintainer&lt;br /&gt;
* Nikolay Vladimirov (Turki)&lt;br /&gt;
* Steven Genchev (blademaster83) &lt;br /&gt;
* Valentin Yankov  (kartacha) &lt;br /&gt;
=== Catalan Translation ===&lt;br /&gt;
* Carles Company (brrr)&lt;br /&gt;
* Dan Rosàs Garcia (focks)&lt;br /&gt;
* Daniel López (Azazelo)&lt;br /&gt;
* Joan Queralt&lt;br /&gt;
* Jonatan Alamà (tin)&lt;br /&gt;
* [mailto:jorda&amp;amp;#x40;ettin&amp;amp;#x2E;org Jordà Polo] (ettin)&lt;br /&gt;
* Jose Gordillo (kilder)&lt;br /&gt;
* J.R. Dolcet Castro (Malin Keshar)&lt;br /&gt;
* Marc Orcau&lt;br /&gt;
* Mark Recasens&lt;br /&gt;
* [mailto:miquel&amp;amp;#x2E;angel&amp;amp;#x2E;burgos&amp;amp;#x40;gmail&amp;amp;#x2E;com Miquel-Àngel Burgos i Fradeja] &amp;amp;#8212; current maintainer&lt;br /&gt;
* Pau Rul·lan Ferragut&lt;br /&gt;
* Roberto Garcia (Motxales)&lt;br /&gt;
=== Chinese Translation ===&lt;br /&gt;
* AxalaraFlameheart (AxalaraFlame)&lt;br /&gt;
* Brian lee&lt;br /&gt;
* chisquare130&lt;br /&gt;
* [mailto:cloudidust&amp;amp;#x40;gmail&amp;amp;#x2E;com CloudiDust] ([[User:CloudiDust|CloudiDust]]) &amp;amp;#8212; former maintainer&lt;br /&gt;
* cryaciccl&lt;br /&gt;
* D3dSun&lt;br /&gt;
* Dionysus&lt;br /&gt;
* 逆天的高级菜鸟 (Gaojicainiao)&lt;br /&gt;
* Henry Zhu (Hardwood) &amp;amp;#8212; iOS announcements translation into Chinese&lt;br /&gt;
* Huang Hongye (Dugucloud) &amp;amp;#8212; translation and image localization&lt;br /&gt;
* Huang Huan&lt;br /&gt;
* Huang Lechuan&lt;br /&gt;
* leaf&lt;br /&gt;
* Luojie-dune&lt;br /&gt;
* MrKing&lt;br /&gt;
* 网上佳公子&lt;br /&gt;
* Owlet&lt;br /&gt;
* pianton&lt;br /&gt;
* SealMe&lt;br /&gt;
* spider5&lt;br /&gt;
* StephDC&lt;br /&gt;
* [mailto:sylecn&amp;amp;#x40;gmail&amp;amp;#x2E;com sylecn]&lt;br /&gt;
* Teamzhangmeng&lt;br /&gt;
* vimacs &amp;amp;#8212; current maintainer&lt;br /&gt;
* vinneymail&lt;br /&gt;
* wind&lt;br /&gt;
* Yifan&lt;br /&gt;
* yym514&lt;br /&gt;
* zen&lt;br /&gt;
=== Chinese (Taiwan) Translation ===&lt;br /&gt;
* 楊綮銘&lt;br /&gt;
* 李昆融&lt;br /&gt;
* 李信融&lt;br /&gt;
=== Croatian Translation ===&lt;br /&gt;
* Ivica Đurenec (charlieh65)&lt;br /&gt;
* Nino Gunjača&lt;br /&gt;
=== Czech Translation ===&lt;br /&gt;
* Alexander Slávik (Olin)&lt;br /&gt;
* Anežka Bubeníčková (Bubu)&lt;br /&gt;
* Čestmír Houska&lt;br /&gt;
* David Nečas (Yeti)&lt;br /&gt;
* David Novotný (Draqen)&lt;br /&gt;
* [mailto:jan&amp;amp;#x2E;dedic&amp;amp;#x40;gmail&amp;amp;#x2E;com Jaromír Dědič]&lt;br /&gt;
* Karel Doleček&lt;br /&gt;
* Lukáš Faltýnek&lt;br /&gt;
* [mailto:hrubymar10&amp;amp;#x40;gmail&amp;amp;#x2E;com Martin Hrubý] ([[User:hrubymar10|hrubymar10]])&lt;br /&gt;
* Martin Šín&lt;br /&gt;
* Michal Žejdl&lt;br /&gt;
* Mintaka&lt;br /&gt;
* [mailto:tapik&amp;amp;#x40;buchtovi&amp;amp;#x2E;cz Oto Buchta] ([[User:Tapik|tapik]])&lt;br /&gt;
* Petr Kopač (Ferda)&lt;br /&gt;
* Petr Kovár (Juans)&lt;br /&gt;
* Rudolf Orság&lt;br /&gt;
* Septim&lt;br /&gt;
* Sofronius&lt;br /&gt;
* Vít Komárek&lt;br /&gt;
* Vít Krčál&lt;br /&gt;
* Vladimír Slávik&lt;br /&gt;
=== Danish Translation ===&lt;br /&gt;
* Anders K. Madsen (madsen)&lt;br /&gt;
* Ask Hjorth Larsen&lt;br /&gt;
* Bjarke Sørensen (basher)&lt;br /&gt;
* Jesper Fuglsang Wolff (ulven)&lt;br /&gt;
* Joe Hansen&lt;br /&gt;
* Kenneth Nielsen&lt;br /&gt;
* Mark Michelsen (skovbaer)&lt;br /&gt;
* Mathias Bundgaard Svensson (freaken)&lt;br /&gt;
* Ole Laursen&lt;br /&gt;
=== Dutch Translation ===&lt;br /&gt;
* [mailto:AI0867&amp;amp;#x40;gmail&amp;amp;#x2E;com Alexander van Gessel] (AI/AI0867) &amp;amp;#8212; previous translation maintainer&lt;br /&gt;
* Arne Deprez&lt;br /&gt;
* Astrid Halberkamp&lt;br /&gt;
* Floris Kint (Grimling)&lt;br /&gt;
* Foppe Benedictus&lt;br /&gt;
* [mailto:oudshoorn&amp;amp;#x40;eitri&amp;amp;#x2E;nl IJsbrand Oudshoorn]&lt;br /&gt;
* Joeri Melis&lt;br /&gt;
* Jon Jacobs&lt;br /&gt;
* Koen Douterloigne&lt;br /&gt;
* Koen Vervloesem (koan)&lt;br /&gt;
* Lala&lt;br /&gt;
* Maarten Albrecht&lt;br /&gt;
* Merijn de Vet &amp;amp;#8212; translation maintainer&lt;br /&gt;
* Orange_Pumpkin&lt;br /&gt;
* Pieter Vermeylen (Onne)&lt;br /&gt;
* Rico van Coevorden&lt;br /&gt;
* Rob van der Vleugel&lt;br /&gt;
* Roel Thijs (Roel)&lt;br /&gt;
* Roger Koot&lt;br /&gt;
* Thomas Hugo de Groot&lt;br /&gt;
* Tobe Deprez&lt;br /&gt;
* WimPapa&lt;br /&gt;
=== English (GB) Translation ===&lt;br /&gt;
* András Salamon (ott)&lt;br /&gt;
* Eric S. Raymond (ESR)&lt;br /&gt;
* pjr&lt;br /&gt;
* [mailto:Majora700&amp;amp;#x40;gmail&amp;amp;#x2E;com Steven Panek] ([[User:Espreon|Espreon]])&lt;br /&gt;
* Thomas Hockings ([[User:Deusite|Deusite]])&lt;br /&gt;
* Wedge009&lt;br /&gt;
=== English (Shaw) Translation ===&lt;br /&gt;
* [mailto:arcriley&amp;amp;#x40;ubuntu&amp;amp;#x2E;com Arc Riley] ([[User:ArcRiley|ArcRiley]]) &amp;amp;#8212; translation maintainer&lt;br /&gt;
* [mailto:reportingsjr&amp;amp;#x40;gmail&amp;amp;#x2E;com Jon Neal] (reportingsjr)&lt;br /&gt;
* [mailto:thomas&amp;amp;#x40;thurman&amp;amp;#x2E;org&amp;amp;#x2E;uk Thomas Thurman] (marnanel)&lt;br /&gt;
=== Esperanto Translation ===&lt;br /&gt;
* Aleksej Korgenkov (Grimpanto)&lt;br /&gt;
* Alís Martínez&lt;br /&gt;
* Francesco Lorenzon (Likso)&lt;br /&gt;
* Ľubo Fajth&lt;br /&gt;
* Luther Thompson&lt;br /&gt;
* Maarten Albrecht&lt;br /&gt;
* Mariano Street (mctpyt) &amp;amp;#8212; translation maintainer&lt;br /&gt;
* Rastislav Šarišský (Asto)&lt;br /&gt;
=== Estonian Translation ===&lt;br /&gt;
* Kaido Kikkas (UncleOwl)&lt;br /&gt;
* Mart Tõnso&lt;br /&gt;
=== Filipino Translation ===&lt;br /&gt;
* Joset Anthony Zamora (eradicus)&lt;br /&gt;
* Karen Eve Eso (keeve)&lt;br /&gt;
=== Finnish Translation ===&lt;br /&gt;
* Ankka&lt;br /&gt;
* Jaakko Muilu&lt;br /&gt;
* Jaakko Saarikko &amp;amp;#8212; translation maintainer&lt;br /&gt;
* Jarkko Patteri (Jarkko)&lt;br /&gt;
* Juhana Uuttu&lt;br /&gt;
* Jussi Rautio (jgrr)&lt;br /&gt;
* kko&lt;br /&gt;
* Matias Parmala&lt;br /&gt;
* Matias Pigg&lt;br /&gt;
* Mikko Nikkilä (Miccoh)&lt;br /&gt;
* Mikko Kraft (deserter)&lt;br /&gt;
* Miriam Green&lt;br /&gt;
* Niklas Laxström (Nikerabbit)&lt;br /&gt;
* Olavi Peltoniemi (MrPringles)&lt;br /&gt;
* Otto Oikarinen&lt;br /&gt;
* paxed&lt;br /&gt;
* Samu Voutilainen (Smar)&lt;br /&gt;
* Santtu Pajukanta (Japsu)&lt;br /&gt;
* Simo Sutela&lt;br /&gt;
* Veikko Pukkila (swege)&lt;br /&gt;
=== French Translation ===&lt;br /&gt;
* alberic89&lt;br /&gt;
* Antoine Garnier&lt;br /&gt;
* Antoine Imboden&lt;br /&gt;
* Aurélien Brevers (Breversa)&lt;br /&gt;
* Aurélien Paulus&lt;br /&gt;
* Arnaud Garoux (La vie en wose)&lt;br /&gt;
* Benoit Astruc&lt;br /&gt;
* [mailto:benoit&amp;amp;#x2E;timbert&amp;amp;#x40;free&amp;amp;#x2E;fr Benoît Timbert] ([[User:Noyga|Noyga]]) &amp;amp;#8212; former translation maintainer&lt;br /&gt;
* Bruno Fève (PP)&lt;br /&gt;
* Cédric Duval&lt;br /&gt;
* Damian Gryski (dmg)&lt;br /&gt;
* [[User:Damien|Damien Jacquot]] &amp;amp;#8212; former lead translator&lt;br /&gt;
* DaringTremayne&lt;br /&gt;
* David Pradier&lt;br /&gt;
* Éric Pierre (Gari)&lt;br /&gt;
* Fabrice Boulakia&lt;br /&gt;
* Florence Guettaa (inflow)&lt;br /&gt;
* François Mariage (Paquito)&lt;br /&gt;
* François Orieux&lt;br /&gt;
* Geoffroy Douillié ([[User:Gdou|gdou]])&lt;br /&gt;
* Gérard Bodin (Gnork)&lt;br /&gt;
* Guillaume Delacourt&lt;br /&gt;
* Guillaume Duwelz-Rebert&lt;br /&gt;
* Guillaume Guigou&lt;br /&gt;
* [mailto:massart&amp;amp;#x2E;guillaume&amp;amp;#x40;wanadoo&amp;amp;#x2E;fr Guillaume Massart] (Piou2fois)&lt;br /&gt;
* Guillaume Melquiond (silene)&lt;br /&gt;
* Guillaume Pascal&lt;br /&gt;
* Ismaël Brunet Pac&lt;br /&gt;
* Jean Privat (Tout)&lt;br /&gt;
* Jean-Louis Passerin (Zoltic)&lt;br /&gt;
* Jean-Luc Menut&lt;br /&gt;
* Jean-Luc Richard (Le Gnome)&lt;br /&gt;
* Jean-Joseph Paget&lt;br /&gt;
* Jehan Hysseo (Jey)&lt;br /&gt;
* Jérémy Rosen (Boucman)&lt;br /&gt;
* Julien Moncel&lt;br /&gt;
* Julien Tailleur&lt;br /&gt;
* Marc Scheffer&lt;br /&gt;
* Mathieu Guilbaud&lt;br /&gt;
* Mendes Oulamara&lt;br /&gt;
* Michel Poléni (Thanatloc)&lt;br /&gt;
* Nicolas Boudin (Blurgk)&lt;br /&gt;
* [mailto:philippe&amp;amp;#x2E;plantier&amp;amp;#x40;naema&amp;amp;#x2E;org Philippe Plantier] ([[User:Ayin|Ayin]])&lt;br /&gt;
* Philippe Rasquinet&lt;br /&gt;
* Pierre Rudloff&lt;br /&gt;
* Sébastien Raynaud (Galactic turkey)&lt;br /&gt;
* Sylvain Jeanne&lt;br /&gt;
* Thierry Bothorel&lt;br /&gt;
* Solena Le Moigne&lt;br /&gt;
* William Dupré&lt;br /&gt;
* [mailto:ydirson&amp;amp;#x40;altern&amp;amp;#x2E;org Yann Dirson]&lt;br /&gt;
=== Friulian Translation ===&lt;br /&gt;
=== Galician Translation ===&lt;br /&gt;
* [mailto:adriyetichaves&amp;amp;#x40;gmail&amp;amp;#x2E;com Adrián Chaves Fernández] (Gallaecio)&lt;br /&gt;
* Fran Diéguez&lt;br /&gt;
* Jacobo Abel Fernández García &amp;amp;#8212; inactive&lt;br /&gt;
* Javier Pico&lt;br /&gt;
* Manuel Meixide&lt;br /&gt;
* Marce Villarino&lt;br /&gt;
* [mailto:leandro&amp;amp;#x2E;regueiro&amp;amp;#x40;gmail&amp;amp;#x2E;com Leandro Regueiro] (unho) &amp;amp;#8212; translation maintainer&lt;br /&gt;
* Victor Portela&lt;br /&gt;
* Proxecto Trasno &amp;amp;#8212; translation project (http://trasno.net)&lt;br /&gt;
=== German Translation ===&lt;br /&gt;
* Aaron Winter (Bitron)&lt;br /&gt;
* Alexander Ginschel (mcpgal)&lt;br /&gt;
* Alexander Laux&lt;br /&gt;
* Alexander Zurek (Alresu)&lt;br /&gt;
* Andre Schmidt (schmidta)&lt;br /&gt;
* Boris Stumm (quijote_)&lt;br /&gt;
* Celina Mainz (Mailina)&lt;br /&gt;
* Chewan&lt;br /&gt;
* Christoph Berg (chrber) &amp;amp;#8212; former translation maintainer&lt;br /&gt;
* Christoph Lange (madelgijs)&lt;br /&gt;
* Drakefriend&lt;br /&gt;
* Elias Fromm (Karpadorsch)&lt;br /&gt;
* Elias Pschernig (allefant)&lt;br /&gt;
* ghype&lt;br /&gt;
* Iwan Gabovitch (qubodup)&lt;br /&gt;
* Lennard&lt;br /&gt;
* Lorenzo Hardt (HeroOfGaming)&lt;br /&gt;
* Rhonda D'Vine (Rhonda)&lt;br /&gt;
* Jan Greve (Jan)&lt;br /&gt;
* Jan Heiner Laberenz (jan-heiner)&lt;br /&gt;
* [mailto:loehnert&amp;amp;#x2E;kde&amp;amp;#x40;gmx&amp;amp;#x2E;de Johannes Löhnert]&lt;br /&gt;
* Kai Ensenbach&lt;br /&gt;
* Konrad Schwede (Konrad2)&lt;br /&gt;
* [mailto:marcel_miebach&amp;amp;#x40;gmx&amp;amp;#x2E;de Marcel Miebach] (retr0virus)&lt;br /&gt;
* Mark de Wever ([[User:SkeletonCrew|Mordante/SkeletonCrew]])&lt;br /&gt;
* Matthias Gianfelice (MatthiasG)&lt;br /&gt;
* [mailto:Crazy-Ivanovic&amp;amp;#x40;gmx&amp;amp;#x2E;net Nils Kneuper] (Ivanovic)&lt;br /&gt;
* Oliver Lange (Crommy)&lt;br /&gt;
* René Genz (Sobek)&lt;br /&gt;
* Ronny Standtke&lt;br /&gt;
* Ruben Philipp Wickenhäuser (The Very Uhu)&lt;br /&gt;
* Severin Glöckner (Shiki, Sevu) &amp;amp;#8212; former translation maintainer&lt;br /&gt;
* Simon Waldek (s1m0n)&lt;br /&gt;
* Stephan Grochtmann (Schattenstephan)&lt;br /&gt;
* Steve Cotton (octalot)&lt;br /&gt;
* Tobias Schönau (SonIcco)&lt;br /&gt;
* Uz-Valentin Friedrich&lt;br /&gt;
* vonHalenbach&lt;br /&gt;
* [mailto:Wuzzy&amp;amp;#x40;disroot&amp;amp;#x2E;org Wuzzy]&lt;br /&gt;
=== Greek Translation ===&lt;br /&gt;
* Alexander Alexiou (Santi/fnaek)&lt;br /&gt;
* Evangelos Papakirikou&lt;br /&gt;
* Harry Kaimenas&lt;br /&gt;
* Katerina Sykioti&lt;br /&gt;
* Konstantinos Egarhos&lt;br /&gt;
* Konstantinos Karasavvas&lt;br /&gt;
* Mik2303&lt;br /&gt;
* Nikos Astroylakis (Greek Dubbings Maker)&lt;br /&gt;
* Nikos Papadopoulos (galicae)&lt;br /&gt;
* Nikos the Great&lt;br /&gt;
* Panagiotis Famelis (Kesnar)&lt;br /&gt;
* Papadopoulos Themistoklis&lt;br /&gt;
* Spiros, Giorgis&lt;br /&gt;
=== Hebrew Translation ===&lt;br /&gt;
* Ariel Ben-Yehuda&lt;br /&gt;
* Oron Peled&lt;br /&gt;
* Ely Levy (Nakee)&lt;br /&gt;
=== Hungarian Translation ===&lt;br /&gt;
* Barthalos Márton (Aldebaran Ghrelin)&lt;br /&gt;
* Czakó Csaba (Horus)&lt;br /&gt;
* Erdélyi Kristóf&lt;br /&gt;
* Fábián Balázs (nermal93)&lt;br /&gt;
* Hamar Krisztián&lt;br /&gt;
* Kádár-Németh Krisztián (Rudanar Firmus)&lt;br /&gt;
* Kékkői László (BlackEvil)&lt;br /&gt;
* Kelemen Zoltán (kele)&lt;br /&gt;
* Kovács Dániel (Consalamander)&lt;br /&gt;
* Majsa Norbert (wias)&lt;br /&gt;
* Máthé Katalin (katkadu)&lt;br /&gt;
* Németh Tamás (nTOMasz)&lt;br /&gt;
* Pintér Csaba (piere)&lt;br /&gt;
* Salamon András (ott)&lt;br /&gt;
* Soltész Adrián (majominia)&lt;br /&gt;
* Széll Tamás (TomJoad)&lt;br /&gt;
* Udvari Gábor (Udi)&lt;br /&gt;
* Udvari Zsolt&lt;br /&gt;
* Vasvári Péter (honorshark)&lt;br /&gt;
=== Icelandic Translation ===&lt;br /&gt;
* Arngrímur Stefánsson&lt;br /&gt;
* Gabríel A. Pétursson&lt;br /&gt;
=== Indonesian Translation ===&lt;br /&gt;
* Ardhi (earthboy)&lt;br /&gt;
* Benny Lin&lt;br /&gt;
* [mailto:sevennightmare&amp;amp;#x40;tutanota&amp;amp;#x2E;de Irsyad Musthafa] &amp;amp;#8212; translation maintainer&lt;br /&gt;
* Iwan&lt;br /&gt;
* [mailto:inkraiswitras&amp;amp;#x40;yahoo&amp;amp;#x2E;com Nicky Inkrais Witras] &amp;amp;#8212; previous translation maintainer&lt;br /&gt;
* [mailto:yuris_wicaksana&amp;amp;#x40;yahoo&amp;amp;#x2E;com Yuristyawan Pambudi Wicaksana] &amp;amp;#8212; previous translation maintainer&lt;br /&gt;
=== Irish Translation ===&lt;br /&gt;
* Mountain_King &amp;amp;#8212; translation maintainer&lt;br /&gt;
=== Italian Translation ===&lt;br /&gt;
* Alessandro Barbazza&lt;br /&gt;
* Alessio D'Ascanio (otaku)&lt;br /&gt;
* Americo Iacovizzi (DarkAmex)&lt;br /&gt;
* [mailto:arosella&amp;amp;#x40;yahoo&amp;amp;#x2E;com Antonio Rosella]&lt;br /&gt;
* crys0000&lt;br /&gt;
* Elvish_Hunter&lt;br /&gt;
* Eugenio Favalli (ElvenProgrammer)&lt;br /&gt;
* Federico Tomassetti&lt;br /&gt;
* Filippo Abbruzzo (Gwain)&lt;br /&gt;
* isazi&lt;br /&gt;
* Luciano Montanaro (Luciano)&lt;br /&gt;
* Michele Maresi (mich)&lt;br /&gt;
* RokStar&lt;br /&gt;
* Stefano Coccato (BioHazardX)&lt;br /&gt;
=== Japanese Translation ===&lt;br /&gt;
* BlueStar&lt;br /&gt;
* clearpotion&lt;br /&gt;
* h22&lt;br /&gt;
* [mailto:broadbarredfirefish&amp;amp;#x40;gmail&amp;amp;#x2E;com Hironori Fujimoto] (RatArmy) &amp;amp;#8212; translation maintainer&lt;br /&gt;
* [mailto:iwaim&amp;amp;#x2E;sub&amp;amp;#x40;gmail&amp;amp;#x2E;com IWAI, Masaharu] ([[User:Iwaim|iwaim]])&lt;br /&gt;
* [mailto:kateitekino_hito&amp;amp;#x40;yahoo&amp;amp;#x2E;co&amp;amp;#x2E;jp kateiteki]&lt;br /&gt;
* kudoh&lt;br /&gt;
* Maxwell Stibbard Hawkes&lt;br /&gt;
* [mailto:mishanhideaki88&amp;amp;#x40;gmail&amp;amp;#x2E;com mishan]&lt;br /&gt;
* いいむらなおき (amatubu) — Naoki Iimura&lt;br /&gt;
* [mailto:okyada&amp;amp;#x40;gmail&amp;amp;#x2E;com 岡田信人 — Nobuhito Okada]&lt;br /&gt;
* np&lt;br /&gt;
* [mailto:pasta0915[at]gmail&amp;amp;#x2E;com Shoot MORII] (pastak)&lt;br /&gt;
* OOTA, Masato(oo)&lt;br /&gt;
* Q&lt;br /&gt;
* R.N&lt;br /&gt;
* rouiza&lt;br /&gt;
* [mailto:le&amp;amp;#x2E;sahara&amp;amp;#x40;gmail&amp;amp;#x2E;com sahara]&lt;br /&gt;
* Shigerello&lt;br /&gt;
* [mailto:suto3suto3&amp;amp;#x40;gmail&amp;amp;#x2E;com suto3]&lt;br /&gt;
* 瀟湘夜雨&lt;br /&gt;
* Taigaku Okuiso&lt;br /&gt;
* Takanobu Hirai&lt;br /&gt;
* tamanegi&lt;br /&gt;
* [mailto:yma9yma&amp;amp;#x40;gmail&amp;amp;#x2E;com yma]&lt;br /&gt;
* Yuji Matsumoto&lt;br /&gt;
=== Korean Translation ===&lt;br /&gt;
* mistzone &amp;amp;#8212; current maintainer&lt;br /&gt;
=== Latin Translation ===&lt;br /&gt;
* Eric S. Raymond (ESR) &amp;amp;#8212; general semantician&lt;br /&gt;
* Mark Polo (mpolo) &amp;amp;#8212; original maintainer&lt;br /&gt;
* Michael Babich ([[User:Aethaeryn|Aethaeryn]]) &amp;amp;#8212; current maintainer&lt;br /&gt;
* [mailto:Majora700&amp;amp;#x40;gmail&amp;amp;#x2E;com Steven Panek] ([[User:Espreon|Espreon]])&lt;br /&gt;
* Thomas Hockings ([[User:Deusite|Deusite]])&lt;br /&gt;
=== Latvian Translation ===&lt;br /&gt;
* Artis Rozentāls&lt;br /&gt;
* Gvido Bruveris &amp;amp;#8212; Maintainer&lt;br /&gt;
* [mailto:rei4dan&amp;amp;#x40;gmail&amp;amp;#x2E;com Reinis Danne]&lt;br /&gt;
=== Lithuanian Translation ===&lt;br /&gt;
* Andrius Štikonas&lt;br /&gt;
* Deimantė Tankus (Diamond)&lt;br /&gt;
* Jurgis Sūdžius (Dievas)&lt;br /&gt;
* Lukas Gasiūnas (LucasLT)&lt;br /&gt;
* Marius Tauba (morlock)&lt;br /&gt;
* Raimundas Zabarauskas&lt;br /&gt;
* Vytautas Šaltenis (rtfb)&lt;br /&gt;
=== Macedonian Translation ===&lt;br /&gt;
* Dimitar Ilccov (Mythological)&lt;br /&gt;
=== Marathi Translation ===&lt;br /&gt;
* [mailto:sujitrjadhav&amp;amp;#x40;gmail&amp;amp;#x2E;com सुजित जाधव] ([[User:sujitrjadhav|Sujit R Jadhav]])&lt;br /&gt;
=== Norwegian Translation ===&lt;br /&gt;
* Asgeir Aakre (YbeRn00b)&lt;br /&gt;
* Elias Nykrem (Bloodaxe) &amp;amp;#8212; Maintainer&lt;br /&gt;
* Erik J. Mesoy (Circon)&lt;br /&gt;
* Gaute Jao (Gauteamus)&lt;br /&gt;
* Hallvard Norheim Bø (Lysander)&lt;br /&gt;
* Håvard Korsvoll&lt;br /&gt;
* Pål Inge Larsen (PsyBird)&lt;br /&gt;
* Susanne Mesoy (Rarlgland)&lt;br /&gt;
=== Old English Translation ===&lt;br /&gt;
* [mailto:eirikvw&amp;amp;#x40;aim&amp;amp;#x2E;com Eirik Westcoat]&lt;br /&gt;
* [mailto:axonfifty&amp;amp;#x40;gmail&amp;amp;#x2E;com Gottweiß]&lt;br /&gt;
* [mailto:Majora700&amp;amp;#x40;gmail&amp;amp;#x2E;com Steven Panek] ([[User:Espreon|Espreon]]) &amp;amp;#8212; Maintainer&lt;br /&gt;
=== Polish Translation ===&lt;br /&gt;
* Adrian Pezda (Deidara)&lt;br /&gt;
* Agata Chmiel&lt;br /&gt;
* Arkadiusz Danilecki (szopen)&lt;br /&gt;
* Bartek Waresiak (Dragonking)&lt;br /&gt;
* Gabriela Waleńczak (Nalianora)&lt;br /&gt;
* Jadwiga Bączkiewicz (Dwisia)&lt;br /&gt;
* Jarom&lt;br /&gt;
* Kamil Matuszewski (LiamTailor)&lt;br /&gt;
* Karol Nowak (grzywacz)&lt;br /&gt;
* Magdalena Chmiel (Ryouko)&lt;br /&gt;
* Marek Kalnik (wdev)&lt;br /&gt;
* Michał Hartliński&lt;br /&gt;
* Michał Jedynak (Artanis)&lt;br /&gt;
* Michał Ligowski (misiorysio)&lt;br /&gt;
* Paweł Albecki (gidgnulur)&lt;br /&gt;
* Paweł Jackowski (fatality)&lt;br /&gt;
* Piotr Kruszewski (Hejnewar) &amp;amp;#8212; Current maintainer&lt;br /&gt;
* Piotr Makarewicz (ForPeace) &amp;amp;#8212; Previous maintainer&lt;br /&gt;
* Robert Wolniak (Szkodnix)&lt;br /&gt;
* Roman Polesek (rimskij)&lt;br /&gt;
* Sebastian Basierski&lt;br /&gt;
* Tadeusz Kopeć&lt;br /&gt;
* Zbigniew Banach (vonBureck)&lt;br /&gt;
=== Portuguese Translation ===&lt;br /&gt;
* Carlos Sousa&lt;br /&gt;
* Luis Passos&lt;br /&gt;
* trewe &amp;amp;#8212; Current maintainer&lt;br /&gt;
=== Portuguese (Brazil) Translation ===&lt;br /&gt;
* Ambra Viviani Loos&lt;br /&gt;
* Andrei Machado &amp;amp;#8212; Current maintainer&lt;br /&gt;
* Antonio Vildes Barbosa&lt;br /&gt;
* Bruno Macabeus&lt;br /&gt;
* Celso Goya&lt;br /&gt;
* [mailto:cbterra&amp;amp;#x40;gmail&amp;amp;#x2E;com Claudio Terra]&lt;br /&gt;
* Claus Aranha&lt;br /&gt;
* Di Teixeira (Moroder)&lt;br /&gt;
* Diego Inácio Goergen&lt;br /&gt;
* [mailto:fred&amp;amp;#x2E;maranhao&amp;amp;#x40;gmail&amp;amp;#x2E;com Fred Maranhão]&lt;br /&gt;
* Hugo Neiva de Melo&lt;br /&gt;
* Michel Loos&lt;br /&gt;
* Renato Cunha&lt;br /&gt;
* Ricardo Sodré Andrade&lt;br /&gt;
* Romero Gonçalves&lt;br /&gt;
* Sérgio de Miranda Costa&lt;br /&gt;
* Tiago Souza (Salvador)&lt;br /&gt;
=== Romanian Translation ===&lt;br /&gt;
* Unknown&lt;br /&gt;
=== Russian Translation ===&lt;br /&gt;
* Aldarisvet &amp;amp;#8212; Previous maintainer&lt;br /&gt;
* [mailto:allryn&amp;amp;#x40;pisem&amp;amp;#x2E;net Aleksandr Aleks]&lt;br /&gt;
* Alexandr Gridnev&lt;br /&gt;
* Alexandr Menovchicov&lt;br /&gt;
* Alexey Remizov&lt;br /&gt;
* Alexey Zakharchenko&lt;br /&gt;
* Andrey Tikhonov ([[User:tiandrey|tiandrey]])&lt;br /&gt;
* Anthony Kolesov&lt;br /&gt;
* Artem Khrapov ([[User:Kabachuha|kabachuha]]) &amp;amp;#8212; Current maintainer&lt;br /&gt;
* Azamat Hackimov ([[User:Winterheart|winterheart]])&lt;br /&gt;
* [mailto:BabylonASАТyandexDОTru BabylonAS] ([[User:BabylonAS|BabylonAS]])&lt;br /&gt;
* [[User:catbegemot|catbegemot]]&lt;br /&gt;
* Danila Evstifeyev (MyOtheHedgeFox)&lt;br /&gt;
* Denis Revin (Dut_Norshi)&lt;br /&gt;
* Dmitry Brilev (dobryl)&lt;br /&gt;
* Fardeil&lt;br /&gt;
* Fedor Gavrilov (gallowzbird)&lt;br /&gt;
* Fedor Khod'kov (teddy/fkhodkov)&lt;br /&gt;
* Ilya Kaznacheev&lt;br /&gt;
* Ilya Kotov&lt;br /&gt;
* Ishayahu Lastov (Ishayahu)&lt;br /&gt;
* Kirill Baranov&lt;br /&gt;
* Mikhail Melnik (ZumZoom)&lt;br /&gt;
* Nikita Ushkin&lt;br /&gt;
* Roman Tuchin (Sankt)&lt;br /&gt;
* Sergey Popov (loonycyborg)&lt;br /&gt;
* Valentina Mukhamedzhanova (umirra)&lt;br /&gt;
* Victor Sergienko (singalen)&lt;br /&gt;
* [mailto:vicza&amp;amp;#x40;zmail&amp;amp;#x2E;ru Victor Zabavin]&lt;br /&gt;
* Vlad Glagolev&lt;br /&gt;
* Yellow Horror&lt;br /&gt;
=== Scottish Gaelic Translation ===&lt;br /&gt;
* [mailto:fios&amp;amp;#x40;foramnagaidhlig&amp;amp;#x2E;net GunChleoc] &amp;amp;#8212; Current maintainer&lt;br /&gt;
=== Serbian Translation ===&lt;br /&gt;
* Branko Kokanovic (kokan)&lt;br /&gt;
* [mailto:caslav&amp;amp;#x2E;ilic&amp;amp;#x40;gmx&amp;amp;#x2E;net Caslav Ilic]&lt;br /&gt;
* [mailto:daliborddjuric&amp;amp;#x40;gmail&amp;amp;#x2E;com Dalibor Djuric]&lt;br /&gt;
* [mailto:sreckotoroman&amp;amp;#x40;gmail&amp;amp;#x2E;com Srecko Toroman] (FreeCraft)&lt;br /&gt;
=== Slovak Translation ===&lt;br /&gt;
* Aceman&lt;br /&gt;
* Ivan Kovacs&lt;br /&gt;
* Ján Sučan (Bhujanga)&lt;br /&gt;
* Marian Kluvanec&lt;br /&gt;
* Martin Dzbor&lt;br /&gt;
* Martin Plávala (Empy)&lt;br /&gt;
* Michal Fusatý&lt;br /&gt;
* [mailto:shoferek&amp;amp;#x40;gmail&amp;amp;#x2E;com Stanislav Hoferek] ([[User:Elven|Elven, Greenie knižnica]]) &amp;amp;#8212; Current maintainer&lt;br /&gt;
* [[User:Viliam|Viliam Bur]]&lt;br /&gt;
=== Slovenian Translation ===&lt;br /&gt;
* Gregor Petrin&lt;br /&gt;
* Jaka Kranjc (lynx)&lt;br /&gt;
* Klemen Košir (nNa)&lt;br /&gt;
* Matej Repinc&lt;br /&gt;
=== Spanish Translation ===&lt;br /&gt;
* Alvin Eloy Luna Castro&lt;br /&gt;
* Chucho Pulgoso&lt;br /&gt;
* David Martínez Moreno&lt;br /&gt;
* Diego Grande Rodríguez (Buhako)&lt;br /&gt;
* Diego J.&lt;br /&gt;
* Fernando Cerezal&lt;br /&gt;
* Flamma&lt;br /&gt;
* Francisco Muñoz (fmunoz)&lt;br /&gt;
* Gabriel Rodríguez (Chewie)&lt;br /&gt;
* [mailto:gusgins&amp;amp;#x40;gmail&amp;amp;#x2E;com Gustavo Gingins] (gins)&lt;br /&gt;
* [mailto:shadowm2006&amp;amp;#x40;gmail&amp;amp;#x2E;com Iris Morelle] ([[User:Shadowm|Irydacea/shadowm]])&lt;br /&gt;
* Iván Herrero (navitux)&lt;br /&gt;
* Javier C.H. (perseo)&lt;br /&gt;
* Jose Gordillo (kilder)&lt;br /&gt;
* Jose Manuel Gomez (joseg)&lt;br /&gt;
* Josu Díaz de Arcaya&lt;br /&gt;
* Masacroso&lt;br /&gt;
* Martín R. Dapás&lt;br /&gt;
* Pedro Llorens (PeterPorty)&lt;br /&gt;
* Roberto Romero (sildur)&lt;br /&gt;
* Sebastián Lecchini (Sebas38760) &amp;amp;#8212; current maintainer&lt;br /&gt;
* Sergi March (sergi34)&lt;br /&gt;
* [mailto:Majora700&amp;amp;#x40;gmail&amp;amp;#x2E;com Steven Panek] ([[User:Espreon|Espreon]])&lt;br /&gt;
* [mailto:quianaaelonin&amp;amp;#x40;gmail&amp;amp;#x2E;com Víctor M. Estrada] (Aelonin/Darkmage)&lt;br /&gt;
* Xavier Novella Sinde (XavierNovella)&lt;br /&gt;
=== Swedish Translation ===&lt;br /&gt;
* Alex Alowersson &amp;amp;#8212; current maintainer&lt;br /&gt;
* Alexander Kjäll (capitol)&lt;br /&gt;
* Andreas Tyrberg&lt;br /&gt;
* Åse Petersson (tintin)&lt;br /&gt;
* Elias Sevelin (aXidal)&lt;br /&gt;
* Gustav Tiger&lt;br /&gt;
* Hugo Gerlach (Entrimo)&lt;br /&gt;
* Leo Danielson (Lugo Moll)&lt;br /&gt;
* Niklas Bolmdahl&lt;br /&gt;
* Stefan Bergström (tephlon)&lt;br /&gt;
* [mailto:susanna&amp;amp;#x2E;bjorverud&amp;amp;#x40;telia&amp;amp;#x2E;com Susanna Björverud] (sanna)&lt;br /&gt;
* Ulrika Uddeborg&lt;br /&gt;
* wint3r&lt;br /&gt;
=== Turkish Translation ===&lt;br /&gt;
* Ali Erdem Karaçay(Arsivnet)&lt;br /&gt;
* Enes Akın (yekialem)&lt;br /&gt;
* İhsan Akın&lt;br /&gt;
* Kosif&lt;br /&gt;
* Nilgün Belma Bugüner&lt;br /&gt;
* Pınar Yanardağ (moonquelle)&lt;br /&gt;
* Selim Farsakoğlu&lt;br /&gt;
=== Ukrainian Translation ===&lt;br /&gt;
* Anton Okhrimenko (AncientGeneral)&lt;br /&gt;
* Andrii Serbovets (archdron)&lt;br /&gt;
* ForestDragon&lt;br /&gt;
* [mailto:mansonigor&amp;amp;#x40;gmail&amp;amp;#x2E;com Igor Paliychuk]&lt;br /&gt;
* igorko&lt;br /&gt;
* Oleksii Okhrimenko (lexa04)&lt;br /&gt;
* [mailto:arobson&amp;amp;#x40;yandex&amp;amp;#x2E;ru robson] ([[User:Robson|Robson]])&lt;br /&gt;
* Sergiy Tkach (Apromix)&lt;br /&gt;
* singalen&lt;br /&gt;
=== Valencian (southern Catalan) Translation ===&lt;br /&gt;
* Bernardo Arlandis&lt;br /&gt;
* Robert Millan&lt;br /&gt;
* Tomás Roig&lt;br /&gt;
=== Vietnamese Translation ===&lt;br /&gt;
* Huynh Yen Loc&lt;br /&gt;
* Le Ngoc Nguyen Chinh&lt;br /&gt;
* Pham Hoang Duy&lt;br /&gt;
* Pham Thanh Nam&lt;br /&gt;
* Pham Thi Yen&lt;br /&gt;
=== Welsh Translation ===&lt;br /&gt;
* Adam Pearce &amp;amp;#8212; current maintainer&lt;br /&gt;
=== RACV’s Translation ===&lt;br /&gt;
* Mario Rodríguez (Mavorte)&lt;br /&gt;
== Descent Into Darkness ==&lt;br /&gt;
=== Original Campaign Design ===&lt;br /&gt;
* esci&lt;br /&gt;
=== Latest Campaign Revision ===&lt;br /&gt;
* nemaara&lt;br /&gt;
=== Artwork and Graphics Design ===&lt;br /&gt;
* Blarumyrran &amp;amp;#8212; story images&lt;br /&gt;
* Emilien Rotival (LordBob) &amp;amp;#8212; current portraits&lt;br /&gt;
* theycallmerooster &amp;amp;#8212; old portraits&lt;br /&gt;
=== Miscellaneous ===&lt;br /&gt;
* josteph &amp;amp;#8212; dialogue comments and revisions&lt;br /&gt;
== The South Guard ==&lt;br /&gt;
=== Newest Campaign Version Rewrite ===&lt;br /&gt;
* Dalas&lt;br /&gt;
=== Campaign Design ===&lt;br /&gt;
* nemaara&lt;br /&gt;
* William Carey (aelius) &amp;amp;#8212; original campaign design&lt;br /&gt;
=== Campaign Maintenance ===&lt;br /&gt;
* Dalas &amp;amp;#8212; current maintainer&lt;br /&gt;
* nemaara&lt;br /&gt;
* Lari Nieminen (zookeeper)&lt;br /&gt;
* Eric S. Raymond (ESR)&lt;br /&gt;
* Wintermute&lt;br /&gt;
=== Artwork and Graphics Design ===&lt;br /&gt;
* J.W. Bjerk (eleazar)&lt;br /&gt;
* Kathrin Polikeit (Kitty) &amp;amp;#8212; portraits&lt;br /&gt;
* Lari Nieminen (zookeeper)&lt;br /&gt;
* Scavenger &amp;amp;#8212; new story images and Mal M'Brin portrait&lt;br /&gt;
* rhyging5&lt;br /&gt;
* Shadow&lt;br /&gt;
* William Carey (aelius)&lt;br /&gt;
== Winds of Fate ==&lt;br /&gt;
=== Authors ===&lt;br /&gt;
* Jeffrey ‘Sigurd’ Westcoat (SigurdFireDragon)&lt;br /&gt;
* Jonathan Kelly (name)&lt;br /&gt;
=== Graphics ===&lt;br /&gt;
* Emilien Rotival (LordBob) &amp;amp;#8212; story artwork&lt;br /&gt;
* Lukasz Wawrowski (inferno8) &amp;amp;#8212; storm wisp unit sprite and attack icons from Era of Magic&lt;br /&gt;
* L. Shelby (velensk) &amp;amp;#8212; stymphalian unit sprite from Era of Four Moons campaign&lt;br /&gt;
* Lari Nieminen (zookeeper) &amp;amp;#8212; journey map&lt;br /&gt;
* Vincent Langner (Vyncyn) &amp;amp;#8212; caravel unit sprite from Rashy Era&lt;br /&gt;
=== Alpha Testing ===&lt;br /&gt;
* almkglor&lt;br /&gt;
* Argesilao2&lt;br /&gt;
* benkenobiwan&lt;br /&gt;
* Cosmic&lt;br /&gt;
* Hejnewar&lt;br /&gt;
* IceTyp&lt;br /&gt;
* josteph&lt;br /&gt;
* Konrad2&lt;br /&gt;
* Lord-Knightmare&lt;br /&gt;
* Mirion147&lt;br /&gt;
* octalot&lt;br /&gt;
* Whiskeyjack&lt;br /&gt;
=== Based on Wings of Victory by: ===&lt;br /&gt;
* Eric S. Raymond (esr)&lt;br /&gt;
* Fabi/Fendrin&lt;br /&gt;
== Northern Rebirth ==&lt;br /&gt;
=== Campaign Design ===&lt;br /&gt;
* Taurus&lt;br /&gt;
=== Artwork and Graphics Design ===&lt;br /&gt;
* Battlesquid&lt;br /&gt;
* Nicholas Kerpan (Thrawn)&lt;br /&gt;
* Richard Kettering (Jetrel)&lt;br /&gt;
* Xandar86&lt;br /&gt;
=== Prose and Story Editing ===&lt;br /&gt;
* Eric S. Raymond (ESR) &amp;amp;#8212; prose, grammar, and WML assistance&lt;br /&gt;
* Nathanel K. Stottlemyer (ShadowOfHassen) &amp;amp;#8212; dialogue and narration revisions&lt;br /&gt;
=== Code and Translation Assistance ===&lt;br /&gt;
* David Philippi (Torangan)&lt;br /&gt;
* Scott Klempner&lt;br /&gt;
=== Campaign Maintenance ===&lt;br /&gt;
* Charles Dang (vultraz)&lt;br /&gt;
== The Rise Of Wesnoth ==&lt;br /&gt;
=== Campaign Design ===&lt;br /&gt;
* James Spencer (Shade)&lt;br /&gt;
=== Campaign Maintenance ===&lt;br /&gt;
* Dimitar Ilccov (Mythological)&lt;br /&gt;
* Lari Nieminen (zookeeper) &amp;amp;#8212; former maintainer&lt;br /&gt;
* Scott Klempner&lt;br /&gt;
=== Artwork and Graphics Design ===&lt;br /&gt;
* Blarumyrran &amp;amp;#8212; the new Vampire Lady sprite&lt;br /&gt;
* J.W. Bjerk (eleazar)&lt;br /&gt;
* Lari Nieminen (zookeeper)&lt;br /&gt;
* Emilien Rotival (LordBob) &amp;amp;#8212; new portraits and story art&lt;br /&gt;
* Michael Gil de Muro (grp21) &amp;amp;#8212; old portraits&lt;br /&gt;
* pixelmind &amp;amp;#8212; Shek’kahan portrait&lt;br /&gt;
=== WML Contributors ===&lt;br /&gt;
* Iris Morelle (Irydacea/shadowm)&lt;br /&gt;
* Lari Nieminen (zookeeper)&lt;br /&gt;
== Under the Burning Suns ==&lt;br /&gt;
=== Campaign Design ===&lt;br /&gt;
* Asa Swain&lt;br /&gt;
* Piotr Cychowski (Mist/cycholka)&lt;br /&gt;
=== Campaign Maintenance ===&lt;br /&gt;
* Iris Morelle (Irydacea/shadowm)&lt;br /&gt;
* Jan Rietema (Rhuvaen)&lt;br /&gt;
* Lari Nieminen (zookeeper)&lt;br /&gt;
* Piotr Cychowski (Mist/cycholka)&lt;br /&gt;
* Simon Forsyth (Alarantalara)&lt;br /&gt;
* Steven Panek (Espreon)&lt;br /&gt;
=== Artwork and Graphics Design ===&lt;br /&gt;
* Dan Gerhards (beetlenaut) &amp;amp;#8212; new Flesh Golem sprites&lt;br /&gt;
* Kwandulin &amp;amp;#8212; New Kaleh and Nym sprites&lt;br /&gt;
* doofus-01 &amp;amp;#8212; Monster Crab sprite&lt;br /&gt;
* Hogne Haskjold (Frame)&lt;br /&gt;
* Iris Morelle (Irydacea/shadowm)&lt;br /&gt;
* J.W. Bjerk (Eleazar)&lt;br /&gt;
* James Woo (Pickslide)&lt;br /&gt;
* Javier Hoyos (Vendanna)&lt;br /&gt;
* Marcus Rosén (sleepwalker) &amp;amp;#8212; Dark Assassin sprite and animations&lt;br /&gt;
* Mark Goodenough (Ranger M)&lt;br /&gt;
* Mikolaj Machowski (Emdot)&lt;br /&gt;
* Murray Cook (Zhukov)&lt;br /&gt;
* Peter Geinitz (Shadow)&lt;br /&gt;
* Richard Kettering (Jetrel)&lt;br /&gt;
* Sangel&lt;br /&gt;
* Samuel Wilson (megane)&lt;br /&gt;
* Scott Klempner&lt;br /&gt;
* Vincent Langner (Vyncyn) &amp;amp;#8212; Spider Lich and Human Commander sprites&lt;br /&gt;
* Zerovirus &amp;amp;#8212; Naga Hunter sprite&lt;br /&gt;
=== Miscellaneous ===&lt;br /&gt;
* Fabian Müller (Fabi/Fendrin)&lt;br /&gt;
* Mark Polo&lt;br /&gt;
* Matthias Schoeck (mattsc) &amp;amp;#8212; Messenger AI&lt;br /&gt;
* Isaac&lt;br /&gt;
* Ringcaat (Thorin N. Tatge)&lt;br /&gt;
* And special thanks to everyone else who I forgot to mention.&lt;br /&gt;
== Dead Water ==&lt;br /&gt;
=== Campaign design and programming ===&lt;br /&gt;
* Dan Gerhards (beetlenaut)&lt;br /&gt;
=== Script-doctoring and cleanup for mainline ===&lt;br /&gt;
* Eric S. Raymond (ESR)&lt;br /&gt;
=== Artwork ===&lt;br /&gt;
* Kathrin Polikeit (Kitty) &amp;amp;#8212; Portraits for brawler, Kai Krellis, Gwabbo, and Caladon&lt;br /&gt;
* Justin Nichols (JustinOperable) &amp;amp;#8212; Portrait for Cylanna&lt;br /&gt;
* Zerovirus &amp;amp;#8212; Kai Krellis sprites&lt;br /&gt;
* Francisco Muñoz (fmunoz) &amp;amp;#8212; Attack icons&lt;br /&gt;
== Dusk of Dawn ==&lt;br /&gt;
=== Author ===&lt;br /&gt;
* GreenScarab&lt;br /&gt;
=== Prose and Story Editing, Code Preparation ===&lt;br /&gt;
* Dalas&lt;br /&gt;
=== Art - Sprites ===&lt;br /&gt;
* GreenScarab &amp;amp;#8212; Stone Golem, Troll Earth-Shaker and Troll Initiate sprites&lt;br /&gt;
=== Wild and Beast Saurian Sprites ===&lt;br /&gt;
* Skizzaltix, Faehen Era, add-ons server 1.2&lt;br /&gt;
=== Text Proofreading ===&lt;br /&gt;
* Konrad2&lt;br /&gt;
=== WML Assistance ===&lt;br /&gt;
* Refumee&lt;br /&gt;
=== Beta Testing ===&lt;br /&gt;
* Refumee&lt;br /&gt;
== Legend of Wesmere ==&lt;br /&gt;
=== Creator and Lead Designer ===&lt;br /&gt;
* [mailto:moka1&amp;amp;#x40;otenet&amp;amp;#x2E;gr Spiros, George and Alexander Alexiou] ([[User:Santi|Santi/fnaek]]) &amp;amp;#8212; Main designers, former maintainers.&lt;br /&gt;
=== Campaign Maintenance ===&lt;br /&gt;
* Fabi/Fendrin &amp;amp;#8212; Former maintainer&lt;br /&gt;
* Spiros, George and Alexander Alexiou (Santi/fnaek)&lt;br /&gt;
=== Prose-doctoring and adaptation for mainline ===&lt;br /&gt;
* Eric S. Raymond (esr)&lt;br /&gt;
* Fabi/Fendrin &amp;amp;#8212; Major WML rewrite for mainline&lt;br /&gt;
=== WML Assistance ===&lt;br /&gt;
* Alexander van Gessel (AI/AI0867) &amp;amp;#8212; bugfixing and general WML cleanups&lt;br /&gt;
* Iris Morelle (Irydacea/shadowm) &amp;amp;#8212; for A LOT of help with WML and interesting campaign suggestions&lt;br /&gt;
* Lari Nieminen (zookeeper) &amp;amp;#8212; for A LOT of help with WML&lt;br /&gt;
=== Artificial Intelligence ===&lt;br /&gt;
* Yurii Chernyi (crab) &amp;amp;#8212; coding of the new ai and help with corresponding redesigns&lt;br /&gt;
=== Graphics ===&lt;br /&gt;
* Bora Orcal (bera) &amp;amp;#8212; goblin horn rouser&lt;br /&gt;
* Kathrin Polikeit (Kitty) &amp;amp;#8212; who did a great job with portraits and other graphics&lt;br /&gt;
-the main reason for having a polished campaign&lt;br /&gt;
* Steven Panek (Espreon) &amp;amp;#8212; map artist&lt;br /&gt;
=== Additional thanks to ===&lt;br /&gt;
* Scott &amp;amp;#8212; for help with WML, especially the use of store/unstore&lt;br /&gt;
* WhiteWizard &amp;amp;#8212; Initial porting to 1.2&lt;br /&gt;
* Disto &amp;amp;#8212; for elvish units&lt;br /&gt;
* RedLTeut &amp;amp;#8212; for great improvements to the initial invisible elvish units&lt;br /&gt;
* Dacyn &amp;amp;#8212; who was of great help in the beginning of this project&lt;br /&gt;
* Big Bad Joe&lt;br /&gt;
* breversa&lt;br /&gt;
* Invisible Philosopher&lt;br /&gt;
* js138&lt;br /&gt;
* l'ultimo cruco&lt;br /&gt;
* Mad Max&lt;br /&gt;
* Rhuvaen&lt;br /&gt;
* SelfishWeirdo&lt;br /&gt;
* Scott&lt;br /&gt;
* Sly&lt;br /&gt;
* Teldar&lt;br /&gt;
* Turin&lt;br /&gt;
* And the rest of the Wesnoth community for feedback,&lt;br /&gt;
criticism, help with WML code and graphics.&lt;br /&gt;
== Son Of The Black Eye ==&lt;br /&gt;
=== Campaign Design ===&lt;br /&gt;
* Benjamin Drieu (Benj) &amp;amp;#8212; conception and original design&lt;br /&gt;
* Taurus &amp;amp;#8212; completion&lt;br /&gt;
=== Current Campaign Maintainer ===&lt;br /&gt;
* Tahsin Jahin Khalid (Lord-Knightmare)&lt;br /&gt;
=== Campaign Maintainers (former) ===&lt;br /&gt;
* Lari Nieminen (zookeeper)&lt;br /&gt;
* Taurus&lt;br /&gt;
=== Prose, Grammatical and WML Assistance ===&lt;br /&gt;
* Eric S. Raymond (ESR)&lt;br /&gt;
=== Artwork and Graphics ===&lt;br /&gt;
* Christian Sirviö (Girgistian) &amp;amp;#8212; portraits (sketches)&lt;br /&gt;
* Phil Barber (thespaceinvader) &amp;amp;#8212; portraits (coloring)&lt;br /&gt;
* Sonny T Yamada (SkyOne) &amp;amp;#8212; Sprite animations (defense and magic) of orcish shamans&lt;br /&gt;
== Eastern Invasion ==&lt;br /&gt;
=== Newest Campaign Version Rewrite ===&lt;br /&gt;
* Dalas&lt;br /&gt;
=== Original Campaign Design ===&lt;br /&gt;
* Joseph Simmons (turin)&lt;br /&gt;
=== Prose and Story Editing, Code Preparation ===&lt;br /&gt;
* nemaara&lt;br /&gt;
=== Artwork and Graphics Design ===&lt;br /&gt;
* Aaron Redfern (A-Red) &amp;amp;#8212; New Owaec sprites&lt;br /&gt;
* Emilien Rotival (LordBob) &amp;amp;#8212; new portraits&lt;br /&gt;
* James Woo (Pickslide) &amp;amp;#8212; old portraits&lt;br /&gt;
* Neoriceisgood&lt;br /&gt;
=== Campaign Redesign Playtesters ===&lt;br /&gt;
* Konrad2&lt;br /&gt;
* Lord-Knightmare&lt;br /&gt;
* Toranks&lt;br /&gt;
=== Campaign Maintenance ===&lt;br /&gt;
* Dalas&lt;br /&gt;
* Thewodoros&lt;br /&gt;
=== Previous Campaign Maintenance ===&lt;br /&gt;
* Dimitar Ilccov (Mythological)&lt;br /&gt;
* Lari Nieminen (zookeeper)&lt;br /&gt;
* Astrid Halberkamp&lt;br /&gt;
=== Others ===&lt;br /&gt;
* Eric S. Raymond (ESR)&lt;br /&gt;
* Loci&lt;br /&gt;
== Liberty ==&lt;br /&gt;
=== Original Campaign Design ===&lt;br /&gt;
* Scott Klempner&lt;br /&gt;
=== Latest Rewrite ===&lt;br /&gt;
* nemaara&lt;br /&gt;
=== Campaign Maintenance ===&lt;br /&gt;
* Lari Nieminen (zookeeper)&lt;br /&gt;
* Eric S. Raymond (ESR) &amp;amp;#8212; Original prose-doctoring and preparation for mainline&lt;br /&gt;
=== Artwork and Graphics Design ===&lt;br /&gt;
* Brendan Sellner&lt;br /&gt;
* Kathrin Polikeit (Kitty) &amp;amp;#8212; portraits&lt;br /&gt;
* Shadow&lt;br /&gt;
* Blarumyrran &amp;amp;#8212; story images, Rogue Mage line sprites&lt;br /&gt;
* Sonny T Yamada (SkyOne) &amp;amp;#8212; Sprite animations (defense and attack) of Rogue Mage line&lt;br /&gt;
* Dalas &amp;amp;#8212; Modifying Harper's portrait&lt;br /&gt;
== Secrets of the Ancients ==&lt;br /&gt;
=== Campaign Design, Programming, and Artwork ===&lt;br /&gt;
* Dan Gerhards (beetlenaut)&lt;br /&gt;
=== Campaign Maintenance ===&lt;br /&gt;
* Jeffrey ‘Sigurd’ Westcoat (SigurdFireDragon) &amp;amp;#8212; former maintainer&lt;br /&gt;
=== Additional Artwork ===&lt;br /&gt;
* Wussel &amp;amp;#8212; Some improvements to the ship.&lt;br /&gt;
== Sceptre of Fire ==&lt;br /&gt;
=== Campaign Design ===&lt;br /&gt;
* Joseph Simmons (turin)&lt;br /&gt;
=== Campaign Maintenance ===&lt;br /&gt;
* Lari Nieminen (zookeeper)&lt;br /&gt;
* doofus-01&lt;br /&gt;
* nemaara&lt;br /&gt;
=== WML Assistance ===&lt;br /&gt;
* David Simmons (Dacyn)&lt;br /&gt;
* Eli Dupree (Elvish Pillager)&lt;br /&gt;
* Lari Nieminen (zookeeper)&lt;br /&gt;
* MadMax&lt;br /&gt;
=== Artwork and Graphics Design ===&lt;br /&gt;
* Asereje&lt;br /&gt;
* Blarumyrran &amp;amp;#8212; the new Dwarvish Miner sprite&lt;br /&gt;
* Emilien Rotival (LordBob) &amp;amp;#8212; new portraits&lt;br /&gt;
* James Woo (Pickslide) &amp;amp;#8212; old portraits&lt;br /&gt;
* John-Robert Funck (XJaPaN)&lt;br /&gt;
* JonasNL &amp;amp;#8212; Dwarvish Miner attack and defense animations&lt;br /&gt;
* Peter Geinitz (Wayfarer)&lt;br /&gt;
* Pixelmind &amp;amp;#8212; Khrakrahs portrait&lt;br /&gt;
* Richard Kettering (Jetrel)&lt;br /&gt;
* RusHHouR &amp;amp;#8212; old gold and coal piles&lt;br /&gt;
* doofus-01&lt;br /&gt;
== Two Brothers ==&lt;br /&gt;
=== Campaign Design ===&lt;br /&gt;
* Eric J. Mesoy (Circon)&lt;br /&gt;
* Nils Kneuper (Ivanovic)&lt;br /&gt;
=== Prose and Story Edits ===&lt;br /&gt;
* Eric S. Raymond (esr)&lt;br /&gt;
* A-Red&lt;br /&gt;
=== Campaign Maintenance ===&lt;br /&gt;
* Nils Kneuper (Ivanovic)&lt;br /&gt;
* Charles Dang (vultraz)&lt;br /&gt;
=== Artwork and Graphics Design ===&lt;br /&gt;
* Arkadiusz Danileki (szopen)&lt;br /&gt;
* Kathrin Polikeit (Kitty) &amp;amp;#8212; current portraits&lt;br /&gt;
* MadMax&lt;br /&gt;
* Stefan&lt;br /&gt;
=== Miscellaneous ===&lt;br /&gt;
* Bartek Waresiak (Dragonking)&lt;br /&gt;
* Christoph Berg (chrber)&lt;br /&gt;
* Daravel&lt;br /&gt;
* Jozrael&lt;br /&gt;
* And special thanks to everyone else who I forgot to mention.&lt;br /&gt;
== Heir To The Throne Classic ==&lt;br /&gt;
=== Campaign Design ===&lt;br /&gt;
* David White (Sirp)&lt;br /&gt;
=== Campaign Maintenance ===&lt;br /&gt;
* Dimitar Ilccov (Mythological)&lt;br /&gt;
* Lari Nieminen (zookeeper) &amp;amp;#8212; former maintainer&lt;br /&gt;
* Scott Klempner&lt;br /&gt;
=== Artwork and Graphics Design ===&lt;br /&gt;
* doofus-01 &amp;amp;#8212; new sprites and animations (Princess, Battle Princess, Dark Queen, Sea Orc)&lt;br /&gt;
* Emilien Rotival (LordBob) &amp;amp;#8212; portraits (Delfador, Asheviere, Moremirmu)&lt;br /&gt;
* Francisco Muñoz (fmunoz)&lt;br /&gt;
* Kathrin Polikeit (Kitty) &amp;amp;#8212; portraits (Konrad, Li'sar, Kalenz, Chantal)&lt;br /&gt;
* Neoriceisgood&lt;br /&gt;
* Richard Kettering (Jetrel)&lt;br /&gt;
=== Miscellaneous ===&lt;br /&gt;
* Patrick Parker (Sapient) &amp;amp;#8212; WML assistance&lt;br /&gt;
== The Deceivers Gambit ==&lt;br /&gt;
=== Campaign Design ===&lt;br /&gt;
* Dalas&lt;br /&gt;
=== Setting and Story ===&lt;br /&gt;
* nemaara&lt;br /&gt;
=== Miscellaneous Graphics ===&lt;br /&gt;
* inferno8&lt;br /&gt;
* Maksiu&lt;br /&gt;
* Mechanical&lt;br /&gt;
== Heir To The Throne ==&lt;br /&gt;
=== Campaign Design ===&lt;br /&gt;
* Dalas&lt;br /&gt;
=== Artwork and Graphics Design ===&lt;br /&gt;
* doofus-01 &amp;amp;#8212; new sprites and animations (Princess, Battle Princess, Dark Queen, Sea Orc)&lt;br /&gt;
* Emilien Rotival (LordBob) &amp;amp;#8212; portraits (Delfador, Asheviere, Moremirmu)&lt;br /&gt;
* Francisco Muñoz (fmunoz)&lt;br /&gt;
* Kathrin Polikeit (Kitty) &amp;amp;#8212; portraits (Konrad, Li'sar, Kalenz, Chantal)&lt;br /&gt;
* Neoriceisgood&lt;br /&gt;
* Richard Kettering (Jetrel)&lt;br /&gt;
=== Miscellaneous ===&lt;br /&gt;
* Patrick Parker (Sapient) &amp;amp;#8212; WML assistance&lt;br /&gt;
== The Hammer of Thursagan ==&lt;br /&gt;
=== Author ===&lt;br /&gt;
* Eric S. Raymond (esr)&lt;br /&gt;
=== Special Guest Designer ===&lt;br /&gt;
* Taurus&lt;br /&gt;
=== Art ===&lt;br /&gt;
* Kim Holm (DUHH)&lt;br /&gt;
* Phil Barber (thespaceinvader)&lt;br /&gt;
* Vincent Langner (Vyncyn) &amp;amp;#8212; New Dwarvish Witness line sprites and animations&lt;br /&gt;
=== Brainstorming, playtesting, and spousal support ===&lt;br /&gt;
* Cathy O. Raymond&lt;br /&gt;
=== Campaign Maintenance ===&lt;br /&gt;
* Charles Dang (vultraz)&lt;br /&gt;
[[Category:Generated]]&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Template:DevDownload&amp;diff=74625</id>
		<title>Template:DevDownload</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Template:DevDownload&amp;diff=74625"/>
		<updated>2025-11-11T00:55:56Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
== Development (1.19 branch) ==&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
==== Windows (10 1903 and later) {{{4|}}} ====&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.17 | filename=wesnoth-1.19.17-win64.exe |&lt;br /&gt;
hash=3043cf6db1dcd17c341ee8af7d625a9d561cc06fbf091297a0aa6d3f413b21bb}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.16 | filename=wesnoth-1.19.16-win64.exe |&lt;br /&gt;
hash=4b52b3546c9c0d625058b60b018c967fdb793a04cf4700bc18388bb97f174907}}&lt;br /&gt;
&lt;br /&gt;
==== macOS (10.13 and later) {{{5|}}} ====&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.17 | filename=Wesnoth_1.19.17.dmg |&lt;br /&gt;
hash=0216cd5837af30de1b072d325d11477fa8a1409b22e9fc3ebf46fcc78b8f10b2}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.16 | filename=Wesnoth_1.19.16.dmg |&lt;br /&gt;
hash=730ddcf8b7f4d0cafa6bf924598528ff1e71e152d91dc3d8e9974e62a93bb8b8}}&lt;br /&gt;
&lt;br /&gt;
==== Source code ====&lt;br /&gt;
* [https://github.com/wesnoth/wesnoth/blob/master/INSTALL.md Compiling Wesnoth] - How to compile the source code&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.17 | filename=wesnoth-1.19.17.tar.bz2 |&lt;br /&gt;
hash=7a4f65b3bd845fc923a8f745591062061f5f72cedd4f81edb93e42b8e6b162ea}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.16 | filename=wesnoth-1.19.16.tar.bz2 |&lt;br /&gt;
hash=280c24868b19148278e3dd2604efecdf93b376f2652823453abafb55e94d0130}}&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=InterfaceActionsWML&amp;diff=74624</id>
		<title>InterfaceActionsWML</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=InterfaceActionsWML&amp;diff=74624"/>
		<updated>2025-11-10T17:18:21Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: /* [sound_source] */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{WML Tags}}&lt;br /&gt;
== Interface actions ==&lt;br /&gt;
&lt;br /&gt;
Part of [[ActionWML]], interface actions are actions that do not have a direct effect on gameplay;&lt;br /&gt;
instead, they show something to the player.  The main interface tags&lt;br /&gt;
are '''[message]''' and '''[objectives]''', but several other tags affect&lt;br /&gt;
the interface also.&lt;br /&gt;
&lt;br /&gt;
== [inspect] ==&lt;br /&gt;
This user interface instantly displays the gamestate inspector dialog at the current scenario state (the same one that can be brought up with [[CommandMode|the ''':inspect''' command]]), which can be used to inspect the values of WML variables, AI configuration, recall lists, and more.&lt;br /&gt;
&lt;br /&gt;
* '''name''': optional attribute to specify the name of this gamestate inspector dialog. It is just a label to help differentiate between different invocations of gamestate inspector dialog.&lt;br /&gt;
&lt;br /&gt;
== [message] ==&lt;br /&gt;
The most commonly used interface action is [message], which displays a message to the user in a dialog box. It can also be used to take input from the user.&lt;br /&gt;
&lt;br /&gt;
The following key/tags are accepted for [message]:&lt;br /&gt;
* [[StandardUnitFilter]]: The unit whose profile and name are displayed. Do not use a [filter] tag. If no unit matching this filter is found, the message is not displayed (The unit has probably been killed).&amp;lt;br&amp;gt;[message] elements should be constructed so that it is either guaranteed that a certain unit is alive, or so that dialog flows smoothly even if the message isn't displayed.&lt;br /&gt;
&lt;br /&gt;
* '''speaker''': an alternative to standard unit filter. You may specify as the value of the speaker attribute a unit id or any of the following special values:&lt;br /&gt;
** '''narrator''': the dialog box is displayed without a caption for the unit speaking or a unit image&lt;br /&gt;
** '''unit''': the primary unit for the event is speaking&lt;br /&gt;
** '''second_unit''': the secondary unit for the event is speaking&lt;br /&gt;
&lt;br /&gt;
* '''message''': (translatable) the text to display to the right of the image. ''message'' is sometimes multiple lines; if it is, be sure to use quotes(''' ' ''' or ''' &amp;quot; ''')&lt;br /&gt;
* '''male_message''', '''female_message''': {{DevFeature1.13|2}} (translatable) Used instead of ''message'' if the unit's gender matches. Never used if there is no unit (ie ''speaker=narrator''). {{DevFeature1.13|6}} This matches the primary unit, not the secondary unit.&lt;br /&gt;
* '''wait_description''': {{DevFeature1.13|2}} the description of this message displayed when other players in a mp game wait for one player doing input in a [message] (with [option]s or [text_input]).&lt;br /&gt;
* '''[show_if]''': if present then this message will only be displayed if the conditional statement in this tag is passed (see [[ConditionalActionsWML#Condition_Tags|ConditionalActionsWML]])&lt;br /&gt;
* '''side_for''': (default: all sides) comma-separated list of sides for who message is shown. This will &amp;lt;b&amp;gt;not&amp;lt;/b&amp;gt; work with messages that take user input ([option]/[text_input]), which can only ever be shown to the current player. {{DevFeature1.13|0}} side_for= is now also accepted for messages with user input, it specifies on which side the message is shown (defaults to the currently playing side). For messages with input it does not accept a comma seperated list only a single number.&lt;br /&gt;
* '''image''': (default: profile image of speaker) the image to display to the left of the message text. Append ~RIGHT() if you want the image to appear on the right side. &lt;br /&gt;
** {{DevFeature1.13|0}} &amp;lt;b&amp;gt;none:&amp;lt;/b&amp;gt; display no image&lt;br /&gt;
* '''mirror''': {{DevFeature1.13|5}} whether to mirror the image specified by the '''image''' attribute.&lt;br /&gt;
* '''second_image''': {{DevFeature1.13|6}} same as the '''image''' attribute, but the image is displayed on the right of the message text. {{DevFeature1.17|7}} not working anymore {{DevFeature1.19|9}} working again&lt;br /&gt;
* '''second_mirror''': {{DevFeature1.13|6}} same as '''mirror''', but for the '''second_image''' attribute.&lt;br /&gt;
* '''image_pos''': {{DevFeature1.13|5}} whether to show the image on the left or right; supercedes the use of ~RIGHT() described above&lt;br /&gt;
* '''caption''': (default: name of speaker) the caption to display beside the image. Name to be displayed. Note: use a translation mark to avoid wmllint errors.&lt;br /&gt;
* '''scroll''': Boolean specifying whether the game view should scroll to the speaking unit. Defaults to ''yes''.&lt;br /&gt;
* '''highlight''': {{DevFeature1.13|5}} Boolean specifying whether to highlight the speaker. Defaults to ''yes''.&lt;br /&gt;
* '''sound''': a sound effect (wav file) to play as the message is displayed. This can be a comma-separated list, from which one will be randomly chosen.&lt;br /&gt;
* '''voice''', '''male_voice''', '''female_voice''': {{DevFeature1.13|?}} a sound to be played as the message is displayed. This can also be a comma-separated list, from which one will be randomly chosen. This is intended for voiceovers for the message. The gendered forms are applied the same as for '''message'''. They are never used when the speaker is the narrator - only '''voice''' is used in that case.&lt;br /&gt;
* {{anchor|message-option|'''[option]'''}}: No '''[option]''' elements have to be used. If '''[option]''' elements are present, then each option will be displayed in a menu for the user to select one option. ''Note: Messages with options will not be shown at all in prestart events''&lt;br /&gt;
** '''message''': (translatable) the text displayed for the option. {{DevFeature1.15|1}} This is now a synonym for '''description='''.&lt;br /&gt;
** '''image''', '''label''', '''description''', '''default''': See [[DescriptionWML#WML_Format|DescriptionWML]].&lt;br /&gt;
** '''value''': {{DevFeature1.13|?}} Gives the option a value to be stored in a variable.&lt;br /&gt;
** '''[show_if]''': if present then this option will only be displayed if the conditional statement in this tag is passed (see [[ConditionalActionsWML#Condition_Tags|ConditionalActionsWML]])&lt;br /&gt;
** '''[command]''': an element containing actions which are executed if the option is selected.&lt;br /&gt;
* '''variable''': {{DevFeature1.13|?}} If present, either the index or the value of the chosen option will be stored in the specified variable. Option indexing starts from 1. If option has '''[show_if]''' condition evaluated as false, then it is hidden and excluded from the indexing.&lt;br /&gt;
* {{anchor|message-text_input|'''[text_input]'''}}: there can be only one [text_input] tag. this adds a text input field to the message. ''Note: Messages with text_input will not be shown at all in prestart events''&lt;br /&gt;
** '''variable''': the variable that the user's input will be written to&lt;br /&gt;
** '''label''': a text label to the left of the input field&lt;br /&gt;
** '''max_length''': the maximum number of characters that may be typed into the field&lt;br /&gt;
** '''text''': text that is written into the field in the beginning&lt;br /&gt;
* Check [[EventWML#Multiplayer_safety]] to find out in which events you can safely use '''[option]''' and '''[text_input]''' without causing OOS.&lt;br /&gt;
&lt;br /&gt;
=== Formatting ===&lt;br /&gt;
'''[message]''' and other tags such as unit names (user_description), objectives, and floating text can make use of [https://docs.gtk.org/Pango/pango_markup.html#pango-markup Pango markup formatting codes].&lt;br /&gt;
&lt;br /&gt;
Prefer to use single quotes (') instead of double quotes (&amp;quot;) within the formatting string, as double quotes would need to be escaped in WML (&amp;quot;&amp;quot;). Escaping markup can be done with [https://github.com/wesnoth/wesnoth/blob/9daa10a9f27c5a95520e871417bbd72aa52aa688/src/font/pango/escape.hpp#L38-L42 HTML entities].&lt;br /&gt;
&lt;br /&gt;
For example, if you wanted to write &amp;quot;You are victorious!&amp;quot; in large, italic, gold letters, you might write it this way:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;span color='#BCB088' size='large' font-style='italic'&amp;gt;You are victorious!&amp;lt;/span&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
These are the codes taken from the Pango markup formatting guide:&lt;br /&gt;
&lt;br /&gt;
*'''font''', '''font_desc''': A font description string, such as &amp;quot;Sans Italic 12&amp;quot;.&lt;br /&gt;
*'''font_family''', '''face''': A font family name.&lt;br /&gt;
*'''font_size''', '''size''': Font size in 1024ths of a point, or one of the absolute sizes 'xx-small', 'x-small', 'small', 'medium', 'large', 'x-large', 'xx-large', or one of the relative sizes 'smaller' or 'larger'.&lt;br /&gt;
*'''font_style''', '''style''': One of 'normal', 'oblique', 'italic'.&lt;br /&gt;
*'''font_weight''', '''weight''': One of 'ultralight', 'light', 'normal', 'bold', 'ultrabold', 'heavy', or a numeric weight.&lt;br /&gt;
*'''font_variant''', '''variant''': One of 'normal' or 'smallcaps'.&lt;br /&gt;
*'''font_stretch''', '''stretch''': One of 'ultracondensed', 'extracondensed', 'condensed', 'semicondensed', 'normal', 'semiexpanded', 'expanded', 'extraexpanded', 'ultraexpanded'.&lt;br /&gt;
*'''foreground''', '''fgcolor''', '''color''': An RGB color specification such as '#00FF00' or a color name such as 'red'. The full list of color names may be found in Pango's [https://github.com/GNOME/pango/blob/main/tools/rgb.txt rgb.txt] file.&lt;br /&gt;
*'''background, bgcolor''': An RGB color specification such as '#00FF00' or a color name such as 'red'.&lt;br /&gt;
*'''underline''': One of 'none', 'single', 'double', 'low', 'error'.&lt;br /&gt;
*'''underline_color''': The color of underlines; an RGB color specification such as '#00FF00' or a color name such as 'red'.&lt;br /&gt;
*'''rise''': Vertical displacement, in 10000ths of an em. Can be negative for subscript, positive for superscript.&lt;br /&gt;
*'''strikethrough''': 'true' or 'false' whether to strike through the text.&lt;br /&gt;
*'''strikethrough_color''': The color of strikethrough lines; an RGB color specification such as '#00FF00' or a color name such as 'red'&lt;br /&gt;
*'''fallback''': 'true' or 'false' whether to enable fallback. If disabled, then characters will only be used from the closest matching font on the system. No fallback will be done to other fonts on the system that might contain the characters in the text. Fallback is enabled by default. Most applications should not disable fallback.&lt;br /&gt;
*'''letter_spacing''': Inter-letter spacing in 1024ths of a point.&lt;br /&gt;
*'''gravity''': One of 'south', 'east', 'north', 'west', 'auto'.&lt;br /&gt;
*'''gravity_hint''': One of 'natural', 'strong', 'line'.&lt;br /&gt;
&lt;br /&gt;
The following pango attributes are also available directly as attributes of the '''[message]''' tag:&lt;br /&gt;
{{DevFeature1.13|4}}&lt;br /&gt;
&lt;br /&gt;
*'''font'''&lt;br /&gt;
*'''font_family'''&lt;br /&gt;
*'''font_size'''&lt;br /&gt;
*'''font_style'''&lt;br /&gt;
*'''font_weight'''&lt;br /&gt;
*'''font_variant'''&lt;br /&gt;
*'''font_stretch'''&lt;br /&gt;
*'''color'''&lt;br /&gt;
*'''bgcolor'''&lt;br /&gt;
*'''underline'''&lt;br /&gt;
*'''underline_color'''&lt;br /&gt;
*'''rise'''&lt;br /&gt;
*'''strikethrough'''&lt;br /&gt;
*'''strikethrough_color'''&lt;br /&gt;
*'''fallback'''&lt;br /&gt;
*'''letter_spacing'''&lt;br /&gt;
*'''gravity'''&lt;br /&gt;
*'''gravity_hint'''&lt;br /&gt;
&lt;br /&gt;
== [objectives] ==&lt;br /&gt;
The other tag used for plot development is '''[objectives]'''.&lt;br /&gt;
The '''[objectives]''' tag overwrites any previously set objectives,&lt;br /&gt;
and displays text which should describe the objectives of the scenario.&lt;br /&gt;
Scenario objectives are displayed on the player's first turn after the tag is used,&lt;br /&gt;
or as part of the event if it triggers during that player's turn.&lt;br /&gt;
Objectives can also be accessed at any time in a scenario using the&lt;br /&gt;
&amp;quot;Scenario Objectives&amp;quot; game menu option, making this tag useful for&lt;br /&gt;
scenario-specific information that the player may need to refer to during play.&lt;br /&gt;
&lt;br /&gt;
Attributes of '''[objectives]''':&lt;br /&gt;
* '''side''': Default '0'. The side to set the objectives for. A value of 0 sets objectives for all sides. note: There are side-specific objectives and default objectives, which are used in case a side doesn't have specific ones. Specifying 0 sets the default ones.&lt;br /&gt;
* '''[[StandardSideFilter]]''' tags and keys: Sets the objectives of all matching sides to these passed specifications (the rest of this [objectives] tag). If no sides (such as when passing side=0) or all sides match, sets the default objectives, and the side specific ones for the matching sides otherwise.&lt;br /&gt;
* '''bullet''': Default '• '. Replaces the default bullet, with whatever is passed, for all objectives, gold carryover notes, and notes defined with [note].&lt;br /&gt;
* '''summary''': Displayed first in the objectives text, this should describe the basic objective for the overall scenario.  Can be omitted.&lt;br /&gt;
* '''note''': Displayed last in the objectives text, this is sometimes used for hints or additional information.  Can be omitted.&lt;br /&gt;
* '''victory_string''': Default ' _ &amp;quot;Victory:&amp;quot;', this text precedes the victory objectives. Can be set to &amp;quot;&amp;quot; too.&lt;br /&gt;
* '''defeat_string''': Default ' _ &amp;quot;Defeat:&amp;quot;', this text precedes the defeat objectives. Can be set to &amp;quot;&amp;quot; too.&lt;br /&gt;
* '''gold_carryover_string''': Default ' _ &amp;quot;Gold carryover:&amp;quot;', this text precedes the gold carryover information.&lt;br /&gt;
* '''notes_string''': Default ' _ &amp;quot;Notes:&amp;quot;', this text precedes the notes.&lt;br /&gt;
* '''silent''': Default: not present. If set to &amp;quot;yes&amp;quot;, the objectives are silently changed. Else, they will be shown to the user when appropriate.&lt;br /&gt;
* '''delayed_variable_substitution''': {{DevFeature1.13|8}} If set to yes, any variables or [insert_tag] are not substituted right away. Instead, they are substituted whenever the objectives are actually viewed.&lt;br /&gt;
&lt;br /&gt;
Tags of '''[objectives]''':&lt;br /&gt;
* {{anchor|objectives-objective|'''[objective]'''}}: describes a win or loss condition. Most scenarios have multiple win or loss conditions, so use a separate [objective] subtag for each line; this helps with translations.&lt;br /&gt;
** '''bullet''': Default '• ' or whatever is set in the parent [objectives] block. Replaces the default bullet, with whatever is provided, for the objective defined by the [objective] block.&lt;br /&gt;
** '''red''': Default '0' for winning objectives, '255' for losing objectives. Overrides the default red coloring of the entire objective, including the bullet.&lt;br /&gt;
** '''green''': Default '255' for winning objectives, '0' for losing objectives. Overrides the default green coloring of the entire objective, including the bullet.&lt;br /&gt;
** '''blue''': Default '0'. Overrides the default blue coloring of the entire objective, including the bullet.&lt;br /&gt;
** '''description''': text for the specific win or loss condition.&lt;br /&gt;
** '''caption''': a text which will be displayed above the ''description''. This can be used to display a subcategory of objectives below ''victory_string'' or ''defeat_string''.&lt;br /&gt;
** '''condition''': The color and placement of the text. Values are 'win'(colored green, placed after ''victory_string'') and 'lose'(colored red, placed after ''defeat_string'').&lt;br /&gt;
** '''show_turn_counter''': If set to yes, displays the number of turns remaining in the scenario. Default is no.&lt;br /&gt;
** '''[show_if]''': A condition that disables the objective if it doesn't hold. Conditional objectives are refreshed at '''[show_objectives]''' time only, or when manually opening the scenario objectives.&lt;br /&gt;
* {{anchor|objectives-gold_carryover|'''[gold_carryover]'''}}: describes how the gold carryover works in this scenario. This is intended to be a more convenient way of displaying carryover information than using the note= key in [objectives].&lt;br /&gt;
** '''bullet''': Default '• ' or whatever is set in the parent [objectives] block. Replaces the default bullet with whatever is provided.&lt;br /&gt;
** '''red''': Default '255'. Overrides the default red coloring of the entire objective, including the bullet.&lt;br /&gt;
** '''green''': Default '255'. Overrides the default green coloring of the entire objective, including the bullet.&lt;br /&gt;
** '''blue''': Default '192'. Overrides the default blue coloring of the entire objective, including the bullet.&lt;br /&gt;
** '''bonus''' (boolean): whether an early finish bonus is granted. If omitted, early finish bonus is not mentioned.&lt;br /&gt;
** '''carryover_percentage''': the amount of carryover gold. If omitted, the amount is not mentioned.&lt;br /&gt;
** '''[show_if]''': {{DevFeature1.13|11}} Gold carryover will not be shown if the specified condition isn't met. Conditional gold carryover is refreshed at '''[show_objectives]''' time only.&lt;br /&gt;
* {{anchor|objectives-note|'''[note]'''}}: describes a note, usually used for hints or additional information. This is an easier way of adding several notes than concatenating them together into a single string to use with the ''note='' key.&lt;br /&gt;
** '''bullet''': Default '• ' or whatever is set in the parent [objectives] block. Replaces the default bullet with whatever is provided for the note defined by the [note] block.&lt;br /&gt;
** '''red''': Default '255'. Overrides the default red coloring of the entire note, including the bullet.&lt;br /&gt;
** '''green''': Default '255'. Overrides the default green coloring of the entire note, including the bullet.&lt;br /&gt;
** '''blue''': Default '255'. Overrides the default blue coloring of the entire note, including the bullet.&lt;br /&gt;
** '''description''': the text of the note.&lt;br /&gt;
** '''[show_if]''': The note will not be shown if the specified condition isn't met. Conditional notes are refreshed at '''[show_objectives]''' time only.&lt;br /&gt;
&lt;br /&gt;
== [set_menu_item] ==&lt;br /&gt;
This tag is used to add a custom option in the right-click context menu which can then be used to trigger arbitrary WML commands. The menu items can be set and modified during any event, for example during &amp;quot;start&amp;quot; or &amp;quot;prestart&amp;quot; events. The user can also assign hotkeys to these WML commands unless specified otherwise. When the hotkey is pressed the event will be fired/filtered at the current mouse position.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' Due to limitations in portable devices where there are no scroll bars for context menus, there is a hard-coded limit of 7 custom WML menu items. If you really need to have more than 7 menu items, try combining some of them in a submenu. {{DevFeature1.13|0}} This limitation is being removed in a [http://forums.wesnoth.org/viewtopic.php?p=572554#p572554 future version] of Wesnoth.&lt;br /&gt;
&lt;br /&gt;
* '''id''': the unique id for this menu item. If a menu item with this id already exists, it allows you to set specific changes to that item. All menus will be sorted lexicographically by the id string. The ordering is underscores, digits, and finally letters.&lt;br /&gt;
* '''description''': the in-game text that will appear for this item in the menu.&lt;br /&gt;
* '''image''': the image to display next to this item, defaults to &amp;quot;buttons/WML-custom.png&amp;quot;&lt;br /&gt;
* '''needs_select''': if ''yes'' (default ''no''), then the latest select event (see [[EventWML]]) that triggered before this menu item was chosen will be transmitted over the network before this menu item action will be. This only has any effect in networked multiplayer, and is intended to allow more elaborate menu item behaviour there without causing out of sync errors. If you don't know what this means, just leave it. {{DevFeature1.13|6}} ''needs_select=yes'' is deprecated, consider using manual variable syncing with [sync_variable].&lt;br /&gt;
* '''synced''' {{DevFeature1.13|1}}: if ''no'' (default ''yes'') the command handler will only be run on the client that invoked the menu item; this means that changing the gamestate in a command handler of a menu item with ''synced=no'' will cause OOS&lt;br /&gt;
* '''use_hotkey''': if ''no'' (default ''yes''), then the user cannot assign hotkeys to this menu item. If ''only'', the menu item is only accessible via hotkeys, not via right-click context; you can use this in combination with [default_hotkey] if you want custom hotkeys in your campaign/mp. &lt;br /&gt;
* '''[show_if]''': If present, the menu item will only be available if the conditional statement (see [[ConditionalActionsWML#Condition_Tags|ConditionalActionsWML]]) within evaluates to true. When this is evaluated, the WML variables ''$x1'' and ''$y1'' will point to the location on which the context menu was invoked, so it's possible to for example only enable the option on empty hexes or on a particular unit.&lt;br /&gt;
* '''[filter_location]''': contains a [[StandardLocationFilter]] similar to the one found inside Single Unit Filters. The menu item will only be available on matching locations.&lt;br /&gt;
* '''[default_hotkey]''': contains a hotkey WML to specify what hotkey to assign to this, '''if the user has no hotkey assigned to this yet'''. (Unlike the rest of a menu item definition, modifying this tag has no effect on the game; it is only effective when initially defining a menu item.) Hotkey WML matches the format in the preferences file and contains the following keys:&lt;br /&gt;
** '''key''': a string that contains the key to assign to this.&lt;br /&gt;
** '''alt''', '''shift''', '''cmd'''(apple only), '''ctrl''':  boolean values.&lt;br /&gt;
** '''repeat_on_hold''' {{DevFeature1.13|12}}: if ''yes'' (default ''no''), holding the hotkey will repeat the action continuously, unless it blocks input with something like '''[message]'''. Due to a bug, versions older than 1.13.12 always repeat the action, with no way to disable it.&lt;br /&gt;
* '''[command]''': contains the WML actions to be executed when the menu item is selected. Again, the WML variables ''$x1'' and ''$y1'' will point to the location on which the context menu was invoked on.&lt;br /&gt;
** '''delayed_variable_substitution ''' (boolean yes|no, default: yes): If no, forces a variable substitution run onto the wml included in this [command] block. Use this, if you want variables which are to substitute to get the values they have at execution time of the event where this set_menu_item appears. Other than that, they get the values they have at invocation time of the menu item.&lt;br /&gt;
&lt;br /&gt;
== [clear_menu_item] ==&lt;br /&gt;
&lt;br /&gt;
Removes a menu item from the scenario.&lt;br /&gt;
Normally menu items are, including all their defining wml, automatically carried over between scenarios. This tag prevents this. (The behavior is comparable to set_variable/clear_variable).&lt;br /&gt;
* '''id''': (string): id of the menu item to clear. Can be a comma-separated list.&lt;br /&gt;
&lt;br /&gt;
== Other interface tags ==&lt;br /&gt;
&lt;br /&gt;
The following tags are also action tags:&lt;br /&gt;
&lt;br /&gt;
=== [change_theme] ===&lt;br /&gt;
&lt;br /&gt;
{{DevFeature1.13|8}}&lt;br /&gt;
&lt;br /&gt;
Change the current interface theme.&lt;br /&gt;
&lt;br /&gt;
* '''theme''': The ID of the new theme. Use &amp;lt;code&amp;gt;theme=&amp;lt;/code&amp;gt; (empty key) to switch back to the theme that the player has selected in Preferences. On &amp;lt;b&amp;gt;1.14.2&amp;lt;/b&amp;gt; and later it is also possible to omit the key entirely to achieve the same effect (on previous versions this will crash the Lua engine).&lt;br /&gt;
&lt;br /&gt;
=== [item] ===&lt;br /&gt;
Makes a graphical item appear on a certain hex. Note this only places the graphics for an item. It does not make the item do anything. Use a moveto event to make moving onto the item do something. &amp;lt;tt&amp;gt;''('''Hint:''' There are a number of predefined items that are used in various campaigns that you can make use of. You can find [http://www.wesnoth.org/macro-reference.xhtml#file:items.cfg a list of them] if you look into the items.cfg file in the wesnoth install directory (under /data/core/macros).)''&amp;lt;/tt&amp;gt;&lt;br /&gt;
* '''x''', '''y''': the location to place the item. (only for [event][item]: full [[StandardLocationFilter|SLF]] support)&lt;br /&gt;
* '''image''': the image (in ''images/'' as .png) to place on the hex. This image is aligned with the center of the hex (which is 72 pixels wide and 72 pixels tall). It is drawn underneath units. ''('''Hint:''' To position a small image somewhere other than the center, [[ImagePathFunctions#Blit_Function|BLIT]] the image onto &amp;lt;tt&amp;gt;misc/blank-hex.png&amp;lt;/tt&amp;gt; (a blank 72x72 image). The image is centered since {{DevFeature1.17|7}}, previously the images were aligned to the top-left; however this difference doesn't affect any image BLITted onto blank-hex.png, as that is the same size as a hex.)''&lt;br /&gt;
* '''halo''': an image to place centered on the hex. It is drawn on top of units. Use this instead of ''image'' if the image is bigger than the hex or if you want to animate an image ([https://github.com/wesnoth/wesnoth/issues/1219 #1219]). ''Example (where the integer after the colon is the duration of each frame or square bracket expansion as per [[AnimationWML]] is used): halo=scenery/fire1.png:100,scenery/fire2.png:100,scenery/fire3.png:100,scenery/fire4.png:100,scenery/fire5.png:100,scenery/fire6.png:100,scenery/fire7.png:100,scenery/fire8.png:100'' or equivalently (requires Wesnoth 1.11.2+): ''halo=scenery/fire[1~8].png:100''&lt;br /&gt;
* '''name''' an id that can be used to remove the item.&lt;br /&gt;
* '''team_name''': name of the team for which the item is to be displayed (hidden for others). For multiple teams just put all the names in one string, for example separated by commas. {{DevFeature1.15|0}} In 1.14 the '''[side]team_name''' attribute was expected to be a substring of this '''team_name'''. In 1.15 both are expected to be comma-separated lists of names and the item is visible if the lists intersect. ([https://github.com/wesnoth/wesnoth/pull/3533 #3533])&lt;br /&gt;
* '''visible_in_fog''': whether the item should be visible through fog or not. Default yes.&lt;br /&gt;
* '''submerge''': float, between 0 and 1: specifies how much of the image should be submerged. Gets multiplied with [[TerrainWML|[terrain]]]&amp;lt;nowiki/&amp;gt;submerge. Default 0.&lt;br /&gt;
* '''z_order''': float: defines the order the items get drawn in. Default 0.&lt;br /&gt;
* '''redraw''': (boolean yes|no, default: yes): If no, disables implicit calls to [[InterfaceActionsWML#.5Bredraw.5D|[redraw]]] when placing the items.&lt;br /&gt;
* '''[filter_team]''': {{DevFeature1.15|0}} A [[StandardSideFilter]]. Set '''team_name''' to the union of all '''[side]team_name''' attributes of all sides that match the SSF. ([https://github.com/wesnoth/wesnoth/pull/3533 #3533])&lt;br /&gt;
* {{DevFeature1.15|0}} If both '''team_name''' and '''[filter_team]''' are set, '''team_name''' is ignored.&lt;br /&gt;
&lt;br /&gt;
=== [remove_item] ===&lt;br /&gt;
Removes any graphical items on a given hex.&lt;br /&gt;
* [[StandardLocationFilter]]: the hexes to remove items from&lt;br /&gt;
* '''image''': if specified, only removes the given item if one of its 'image', 'halo' or 'name' attributes is exactly this value. (for 'halo' and 'image' this in particular means that the image name must include any [[ImagePathFunctions|image path functions]] appended to the original image name.)&lt;br /&gt;
&lt;br /&gt;
=== [print] ===&lt;br /&gt;
Displays a message across the screen. The message will disappear after a certain time, or when another [print] tag is encountered.&lt;br /&gt;
* '''text''': (translatable) the text to display. Can be an empty string to remove a previous message without showing a new one.&lt;br /&gt;
* '''size''': (default=12) the pointsize of the font to use&lt;br /&gt;
* '''duration''': the length of time to display the text for.&lt;br /&gt;
** (Before 1.15.4) This is measured in the number of 'frames', and the default is 50. A frame in Wesnoth is usually displayed for around 30ms.&lt;br /&gt;
** {{DevFeature1.15|4}} This is measured in milliseconds. Don't use the default value, because it's a mere 50ms.&lt;br /&gt;
** {{DevFeature1.15|14}} The default is 5000 milliseconds.&lt;br /&gt;
** {{DevFeature1.15|14}} The string '''unlimited''' displays the text until it's removed by another [print] tag.&lt;br /&gt;
* '''color''': (default '''0,0,0''') three comma-separated values giving the red, green and blue values (0-255).&lt;br /&gt;
* '''red''', '''green''', '''blue''': deprecated, use color=0,0,0 instead.&lt;br /&gt;
&lt;br /&gt;
=== [move_unit_fake] ===&lt;br /&gt;
Moves an image of a unit along a certain path on the map. The path does not need to be a continuous list of adjacent hexes, so for example only the start and end points can be given, in which case the straightest line between those points will be calculated and used.&lt;br /&gt;
* '''type''': the type of the unit whose image to use&lt;br /&gt;
* '''x''': a comma-separated list of x locations to move along&lt;br /&gt;
* '''y''': a comma-separated list of y locations to move along (x and y values are matched pairs)&lt;br /&gt;
* '''side''': the side of the fake unit, used for team-coloring the fake unit&lt;br /&gt;
* '''gender''': the gender of the fake unit. Example: gender=female&lt;br /&gt;
* '''variation''': the variation of the fake unit. Example: variation=undead&lt;br /&gt;
* '''image_mods''': [[ImagePathFunctions|image path functions]] sequence to be applied on the fake unit.&lt;br /&gt;
* '''force_scroll''':  Whether to scroll the map or not even when [[#.5Block_view.5D|[lock_view]]] is in effect or ''Follow Unit Actions'' is disabled in ''Advanced Preferences''. Defaults to ''yes'' starting with version '''1.11.6'''; the attribute did not exist in previous versions and this action behaved as if ''no'' was passed instead.&lt;br /&gt;
&lt;br /&gt;
=== [move_units_fake] ===&lt;br /&gt;
moves multiple images of units along paths on the map. These units are moved in lockstep.&lt;br /&gt;
* '''force_scroll''': {{DevFeature1.15|0}} Has the same meaning as in [move_unit_fake] but a different default.&lt;br /&gt;
* '''[fake_unit]''': A fake unit to move&lt;br /&gt;
** '''type''': the type of unit whose image to use&lt;br /&gt;
** '''x''': a comma-separated list of x locations to move along&lt;br /&gt;
** '''y''': a comma-separated list of y locations to move along (x and y values are matched pairs)&lt;br /&gt;
** '''side''': the side of the fake unit, used for team-coloring the fake unit&lt;br /&gt;
** '''skip_steps''': the number of steps to skip before this unit starts moving&lt;br /&gt;
&lt;br /&gt;
=== [hide_unit] ===&lt;br /&gt;
Temporarily prevents the engine from displaying the given unit. The unit does not become invisible, as it would be with the '''[hides]''' ability; it is still the same plain unit, but without an image. Useful in conjunction with '''[move_unit_fake]''': to move a leader unit into position on-screen. Until 1.8 each '''[hide_unit]''' tag only hides one unit.&lt;br /&gt;
* [[StandardUnitFilter]]: All matching units will be hidden&lt;br /&gt;
&lt;br /&gt;
=== [unhide_unit] ===&lt;br /&gt;
Stops the currently hidden units from being hidden.&lt;br /&gt;
* [[StandardUnitFilter]]: Only the matching units will be unhidden&lt;br /&gt;
&lt;br /&gt;
=== [lock_view] ===&lt;br /&gt;
Locks gamemap view scrolling for human players, so they cannot scroll the gamemap view until it is unlocked. WML or Lua actions such as '''[scroll_to]''' will continue to work normally, as they ignore this restriction; the locked/unlocked state is preserved when saving the current game.&lt;br /&gt;
&lt;br /&gt;
This feature is generally intended to be used in cutscenes to prevent the player scrolling away from scripted actions.&lt;br /&gt;
&lt;br /&gt;
{{DevFeature1.13|8}} This now also blocks the player from zooming the gamemap view. WML or Lua zoom will continue to work normally.&lt;br /&gt;
&lt;br /&gt;
=== [unlock_view] ===&lt;br /&gt;
Unlocks gamemap view scrolling for human players.&lt;br /&gt;
&lt;br /&gt;
=== [scroll] ===&lt;br /&gt;
Scroll a certain number of pixels in a given direction. Useful for earthquake/shaking effects.&lt;br /&gt;
* '''x''', '''y''': the number of pixels to scroll along the x and y axis&lt;br /&gt;
* '''side''': the side or sides for which this should happen. By default, the [scroll] happens for everyone.&lt;br /&gt;
* '''[filter_side]''': a [[StandardSideFilter]] to select the sides for which this should happen. By default, the [scroll] happens for everyone.&lt;br /&gt;
&lt;br /&gt;
=== [scroll_to] ===&lt;br /&gt;
Scroll to a given hex&lt;br /&gt;
* [[StandardLocationFilter]], do not use a [filter_location] sub-tag. If more than one location matches the filter, only the first matching location will be used.&lt;br /&gt;
* '''check_fogged''': whether to scroll even to locations covered in fog or shroud. Possible values ''yes'' (don't scroll to fog) and ''no'' (scroll even to fog), with ''no'' as the default.&lt;br /&gt;
* '''immediate''': whether to instantly warp to the target hex regardless of the scroll speed setting in Preferences (defaults to ''no'').&lt;br /&gt;
* '''highlight''': {{DevFeature1.13|5}} Whether to highlight the hex being scrolled to (defaults to ''no'').&lt;br /&gt;
* '''side''': the side or sides for which this should happen. By default, the [scroll_to] happens for everyone.&lt;br /&gt;
* '''[filter_side]''': a [[StandardSideFilter]] to select the sides for which this should happen. By default, the [scroll_to] happens for everyone.&lt;br /&gt;
&lt;br /&gt;
=== [scroll_to_unit] ===&lt;br /&gt;
Scroll to a given unit&lt;br /&gt;
* [[StandardUnitFilter]]; do not use a [filter] subtag.&lt;br /&gt;
* '''check_fogged''': whether to scroll even to locations covered in fog or shroud. Possible values ''yes'' (don't scroll to fog) and ''no'' (scroll even to fog), with ''no'' as the default.&lt;br /&gt;
* '''immediate''': whether to instantly warp to the target hex regardless of the scroll speed setting in Preferences (defaults to ''no'').&lt;br /&gt;
* '''highlight''': {{DevFeature1.13|5}} Whether to highlight the hex the unit is on (defaults to ''no'').&lt;br /&gt;
* '''for_side''': the side or sides for which this should happen. By default, the [scroll_to_unit] happens for everyone.&lt;br /&gt;
* '''[for_side]''': a [[StandardSideFilter]] to select the sides for which this should happen. By default, the [scroll_to_unit] happens for everyone.&lt;br /&gt;
&lt;br /&gt;
=== [select_unit] ===&lt;br /&gt;
Selects a given unit.&lt;br /&gt;
* [[StandardUnitFilter]]: The first unit found will be selected.&lt;br /&gt;
* '''fire_event''': whether a ''select'' event should be triggered or not (def. ''no''). (Note that select events aren't multiplayer save.)&lt;br /&gt;
* '''highlight''': whether the unit's current hex should be highlighted (def. ''yes'').&lt;br /&gt;
&lt;br /&gt;
'''Note:''' fire_event does not appear to work in 1.14 or 1.16.&lt;br /&gt;
&lt;br /&gt;
=== [sound]===&lt;br /&gt;
Plays a sound&lt;br /&gt;
* '''name''': the filename of the sound to play (in ''sounds/'' as .wav or .ogg). This can be a comma-separated list, from which one sound will be chosen randomly.&lt;br /&gt;
* '''repeat''': repeats the sound for a specified additional number of times (default=0)&lt;br /&gt;
&lt;br /&gt;
=== [sound_source] ===&lt;br /&gt;
Creates a sound source. &amp;quot;Sound sources&amp;quot; is a general name for a mechanism which makes possible for map elements to emit sounds according to some rules, where &amp;quot;map elements&amp;quot; can be specific locations or terrain types. For now, only sound sources tied to locations are supported.&lt;br /&gt;
* '''id''': a unique identification key of the sound source&lt;br /&gt;
* '''sounds''': a list of comma separated, randomly played sounds associated with the sound source&lt;br /&gt;
* '''delay''': a numerical value (in milliseconds) of the minimal delay between two playbacks of the source's sound if the source remains visible on the screen; if one scrolls out and back in, the source will be considered as ready to play&lt;br /&gt;
* '''chance''': a percentage (a value from 0 to 100) describing the chance of the source being activated every second after the delay has passed or when the source's location appears on the screen (note that it cannot play more than one file at the same time)&lt;br /&gt;
* '''check_fogged''': possible values ''yes'' and ''no'' - ''yes'' means the source will not play if its locations are fogged&lt;br /&gt;
* '''check_shrouded''': possible values ''yes'' and ''no'' - ''yes'' means the source will not play if its locations are shrouded&lt;br /&gt;
* '''x,y''': similar to x,y as found in a [[StandardLocationFilter]], these are the locations associated with the sound source&lt;br /&gt;
* '''fade_range''' (default = 14): distance in hexes that determines a &amp;quot;circular&amp;quot; area around the one specified by '''full_range''' where sound volume fades out linearly&lt;br /&gt;
* '''full_range''' (default = 3): distance in hexes that determines a &amp;quot;circular&amp;quot; area where source plays with full volume, relative to screen center&lt;br /&gt;
* '''loop''': number of times a sound sample should be looped if it stays visible. -1 means infinite (~65000)&lt;br /&gt;
&lt;br /&gt;
=== [story] ===&lt;br /&gt;
{{DevFeature1.13|8}}&lt;br /&gt;
&lt;br /&gt;
Shows the story screen.&lt;br /&gt;
* '''title''': Default title used if a part does not specify one — unlike the intro storyscreen, the scenario name is not used as a default title.&lt;br /&gt;
* '''[part]''', '''[if]''', '''[switch]''', '''[wml_message]''', '''[deprecated_message]''' : See [[IntroWML]].&lt;br /&gt;
&lt;br /&gt;
=== [remove_sound_source] ===&lt;br /&gt;
Removes a previously defined sound source.&lt;br /&gt;
* '''id''': the identification key of the sound source to remove&lt;br /&gt;
&lt;br /&gt;
=== [music] ===&lt;br /&gt;
Switches to playing different music&lt;br /&gt;
* '''name''': the filename of the music to play (in ''music/'' as .ogg)&lt;br /&gt;
* see [[MusicListWML]] for the correct syntax&lt;br /&gt;
&lt;br /&gt;
=== [volume] ===&lt;br /&gt;
Changes the game volume to a percent of the preferences volume for the game being played. Values can go from 0 to 100:  &lt;br /&gt;
* '''music''':  Changes the music volume.&lt;br /&gt;
* '''sound''':  Changes the sound volume.&lt;br /&gt;
&lt;br /&gt;
=== [color_adjust] ===&lt;br /&gt;
Adjust the color tint of terrain, by adjusting time-of-day coloring.&lt;br /&gt;
* '''red''', '''green''', '''blue''': values from -255 to 255, the amount to tint by for each color&lt;br /&gt;
&lt;br /&gt;
=== [screen_fade] ===&lt;br /&gt;
{{DevFeature1.17|6}}&lt;br /&gt;
&lt;br /&gt;
Overlay the game display with the given color, fading over the specified duration. This can be used for screen fade effects.&lt;br /&gt;
* '''red''', '''green''', '''blue''': values from 0 to 255, the final overlay color (defaults to 0,0,0)&lt;br /&gt;
* '''alpha''': value from 0 to 255, the strength of the effect. 0 means no effect and can be used to fade in. 255 means fully opaque and can be used to fully fade out to the given color. Intermediate values will end up with a partial overlay tint on the game screen.&lt;br /&gt;
* '''duration''': the length of time it will take to complete the fade, in milliseconds. If 0 the effect is immediate.&lt;br /&gt;
&lt;br /&gt;
=== [delay] ===&lt;br /&gt;
Pauses the game.&lt;br /&gt;
* '''time''': the time to pause in milliseconds&lt;br /&gt;
* '''accelerate ''' (boolean yes|no, default no): {{DevFeature1.13|0}} whether the delay is affected by acceleration. When [delay] is used to make an animation, this should be set to yes so that your animation matches the ones generated by the game.&lt;br /&gt;
&lt;br /&gt;
=== [redraw] ===&lt;br /&gt;
Redraws the screen (this normally isn't done during events, although some of the other interface actions cause the screen or parts of it to be redrawn).&lt;br /&gt;
* '''clear_shroud''' (boolean yes|no, default no): If yes, clears fog and shroud around existing units. Useful if you, for example, spawn friendly units in the middle of an event and want the shroud to update accordingly (otherwise units that spawn inside fog would remain invisible for the duration of the event, since the fog would not automatically get cleared around them).&lt;br /&gt;
* '''[[StandardSideFilter]]''': the sides for which to recalculate fog and shroud.&lt;br /&gt;
* '''side''': If used (forces clear_shroud=yes), clears fog and shroud for that side.&lt;br /&gt;
&lt;br /&gt;
=== [unit_overlay] ===&lt;br /&gt;
Sets an image that will be drawn over a particular unit, and follow it around&lt;br /&gt;
* [[StandardUnitFilter]]: All matching units will get the overlay (do not use [filter])&lt;br /&gt;
* '''image''': the image to place on the unit&lt;br /&gt;
* '''object_id''': object id to use, defaults to the '''image''' key with an &amp;quot;overlay_&amp;quot; prefix; this allows using [[DirectActionsWML#.5Bremove_object.5D|'''[remove_object]''']]&lt;br /&gt;
* '''duration''': object duration&lt;br /&gt;
&lt;br /&gt;
=== [remove_unit_overlay] ===&lt;br /&gt;
Removes a particular overlayed image from a unit&lt;br /&gt;
* [[StandardUnitFilter]]: The overlay will get removed from all matching units (do not use [filter])&lt;br /&gt;
* '''image''': the image to remove from the unit&lt;br /&gt;
* '''object_id''': object id to use&lt;br /&gt;
Using [[DirectActionsWML#.5Bremove_object.5D|'''[remove_object]''']] is also possible, see https://github.com/wesnoth/wesnoth/commit/26c2f941f2bcdd89528481e114c0375ad2a46271&lt;br /&gt;
&lt;br /&gt;
=== [animate_unit] ===&lt;br /&gt;
Uses an animation of a unit to animate it on screen (if the unit has the corresponding animation).&lt;br /&gt;
* '''flag''': The key to find the custom animation in the unit description (see the '''[extra_anim]''' description in [[AnimationWML]]). Standard animations can be triggered with the following keywords: ''leading recruited standing idling levelout levelin healing healed poisoned movement defend attack death victory pre_teleport post_teleport''&lt;br /&gt;
* '''[filter]''' with a [[StandardUnitFilter]] as argument, see [[FilterWML]]. By default, the unit at the event location will be animated. You can use this tag to choose any other unit to animate.&lt;br /&gt;
* '''[primary_attack]''': If this tag is not present, the filter for animation will be triggered with no attack. If it is here, all attacks from the unit will be filtered, and a matching one will be used to filter the animation. Takes a weapon filter as argument, see [[FilterWML]].&lt;br /&gt;
* '''[secondary_attack]''': Similar to '''[primary_attack]'''. May be needed to trigger a defense animation correctly, if there are more than one animations available for the defending unit.&lt;br /&gt;
* '''hits''': yes/no/hit/miss/kill: which according variation of a attack/defense animation shall be chosen (required)&lt;br /&gt;
* '''text''': a text to hover during the animation &lt;br /&gt;
* '''male_text''', '''female_text''': {{DevFeature1.13|2}} (translatable) gender-specific versions of the above&lt;br /&gt;
* '''red''': red value for the text color (0-255)&lt;br /&gt;
* '''green''': green value for the text color&lt;br /&gt;
* '''blue''': blue value for the text color&lt;br /&gt;
* '''with_bars''': yes/no: whether to display the status bars during the animation (e.g. the hitpoint bar)&lt;br /&gt;
* '''[animate]''': a sub block with the same syntax as '''[animate_unit]''' except that the '''[filter]''' block is mandatory to find the unit. This block will find and animate another unit simultaneously.&lt;br /&gt;
* '''[facing]''': a [[StandardLocationFilter]] specifying what hex the unit should be facing when animated&lt;br /&gt;
&lt;br /&gt;
=== [label] ===&lt;br /&gt;
Places a label on the map.&lt;br /&gt;
* '''x''', '''y''': the location of the label. {{DevFeature1.13|1}} (only for [event][label]: full [[StandardLocationFilter|SLF]] support)&lt;br /&gt;
* '''text''': what the label should say. If you put an empty string &amp;lt;code&amp;gt;&amp;quot;&amp;quot;&amp;lt;/code&amp;gt; as an argument, the label will be completely removed. Use this method if you want to remove a specific label from any location.&lt;br /&gt;
* '''team_name''': if specified, the label will only be visible to the given team.&lt;br /&gt;
* '''color''': color of the label. The format is r,g,b; r, g and b are numbers between 0 and 255. When you use Pango markup in the text, you cannot use this, but in that case you could colorize the text via Pango markup.&lt;br /&gt;
* '''visible_in_fog''': whether the label should be visible through fog or not. Default yes.&lt;br /&gt;
* '''visible_in_shroud''': whether the label should be visible through shroud or not. Default no.&lt;br /&gt;
* '''immutable''': whether this label is protected from being removed or changed by players. Default yes.&lt;br /&gt;
* '''category''': the Show/Hide Labels dialog allows showing/hiding all labels of a given category by toggling a checkbox.&lt;br /&gt;
* '''tooltip''': A tooltip visible when putting the mouse over the hex the label is on&lt;br /&gt;
* '''side''': the number of the side that placed the label. Can be 0 for labels placed by WML.&lt;br /&gt;
&lt;br /&gt;
=== [floating_text]===&lt;br /&gt;
Floats text (similar to the damage and healing numbers) on the given locations.&lt;br /&gt;
* [[StandardLocationFilter]]: the text will be floated on all matching locations simultaneously (do not use [filter] unless you intend to match one or more units).&lt;br /&gt;
* '''text''': the text to display.&lt;br /&gt;
&lt;br /&gt;
The default text color is &amp;lt;span style=&amp;quot;color: #6b8cff;&amp;quot;&amp;gt;'''#6b8cff'''&amp;lt;/span&amp;gt;. To change the color, use [[#Formatting|Pango markup]]. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Float some golden yellow text at 20,20.&lt;br /&gt;
[floating_text]&lt;br /&gt;
   x,y=20,20&lt;br /&gt;
   text=&amp;quot;&amp;lt;span color='#cccc33'&amp;gt;&amp;quot; + _ &amp;quot;Your text here&amp;quot; + &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
[/floating_text]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [deprecated_message] ===&lt;br /&gt;
Shows a deprecated message in the message area, this feature is only intended to be used to warn about deprecated macros in mainline. The message is not translatable.&lt;br /&gt;
* '''message''': the message to show.&lt;br /&gt;
* '''level''': {{DevFeature1.13|10}} The deprecation level, a number from 1 to 3.&lt;br /&gt;
* '''what''': {{DevFeature1.13|10}} The name of the thing being deprecated. Use this instead of '''message''' if possible; a stock message will be generated from it. Use '''message''' only if more information is required; it will be appended to the stock message. This should not be translatable&lt;br /&gt;
* '''version''': {{DevFeature1.13|10}} For deprecation levels 2 and 3, this indicates the version in which the feature could be removed. It does ''not'' indicate the version in which it became deprecated. &lt;br /&gt;
&lt;br /&gt;
The meanings of the deprecation levels are as follows:&lt;br /&gt;
&lt;br /&gt;
# Deprecated, but will only be removed if absolutely necessary. The '''version''' key is ignored.&lt;br /&gt;
# It will be removed no earlier than a specified version.&lt;br /&gt;
# It will be removed in the next stable version&lt;br /&gt;
# It has already been removed, leaving just a stub to inform users of how to update their code.&lt;br /&gt;
&lt;br /&gt;
Note that as of 1.13.11, deprecation messages show only in the log, not in the chat message area. The '''message''' can be translatable, but does not need to be.&lt;br /&gt;
&lt;br /&gt;
=== [wml_message] ===&lt;br /&gt;
Outputs a message to Wesnoth's console output. Intended for campaign designers to output silent text to the console, without annoying the player; then, that text might contain information useful for later bug-reporting. WML wrapper of [[LuaAPI/wesnoth#wesnoth.log]], see the link for more description.&lt;br /&gt;
* '''message''': the message to show.&lt;br /&gt;
* '''to_chat''': controls whether message is visible in chat, though logger=wml means message is visible anyways. Default ''no''.&lt;br /&gt;
* '''logger''': one of '''info''', '''debug''', '''warning''', '''error''', '''wml'''. Default ''info''.&lt;br /&gt;
&lt;br /&gt;
=== [test_condition] ===&lt;br /&gt;
&lt;br /&gt;
{{DevFeature1.13|2}}&lt;br /&gt;
&lt;br /&gt;
Evaluates the contained conditional tags. If they evaluate to the expected value, it prints out a message to the console explaining which part of the condition caused this result in a way similar to [wml_message]. This can be used if your conditional test is failing and you're not sure why.&lt;br /&gt;
&lt;br /&gt;
* '''result''': Whether you expect the conditions to fail or succeed. If no (the default), a message will be printed if the conditional tags fail. If yes, a message will instead be printed if the conditional tags pass.&lt;br /&gt;
* '''logger''': Same as for [wml_message]. Defaults to &amp;quot;warning&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== [open_help] ===&lt;br /&gt;
Opens the in-game help.&lt;br /&gt;
* '''topic''': the id of the topic to open&lt;br /&gt;
&lt;br /&gt;
Examples of ids:&lt;br /&gt;
* unit_Mage&lt;br /&gt;
* unit_Dark Adept&lt;br /&gt;
* weaponspecial_charge&lt;br /&gt;
* terrain_human_castle&lt;br /&gt;
&lt;br /&gt;
The engine will print the topic ids if run from the command line with the ''--log-debug=help'' option.&lt;br /&gt;
&lt;br /&gt;
=== [show_objectives] ===&lt;br /&gt;
refreshes the objectives defined by [objectives] and its [show_if] tags, and displays them. (It is also called whenever the user explicitly asks for the objectives; this matters only if the tag was overridden by a [[LuaWML#register_wml_action|Lua]] script.)&lt;br /&gt;
* '''side''': the side to show the objectives. If not set, all sides are used.&lt;br /&gt;
* '''[[StandardSideFilter]]''' tags and keys: Tag affects the matching sides instead of just all or the one given by the integer value of the side= key.&lt;br /&gt;
&lt;br /&gt;
=== [chat] ===&lt;br /&gt;
Displays a message in the chat area, not visible for observers. Alternative unconditionally visible for everyone: [[LuaWML:Display#wesnoth.message]]. {{DevFeature1.13|9}} can be visible for observers.&lt;br /&gt;
* '''speaker''': (default=&amp;quot;WML&amp;quot;) A string for the name of the sender of the message.&lt;br /&gt;
* '''message''': The message that should be displayed.&lt;br /&gt;
* '''observable''' (boolean yes|no, default yes): {{DevFeature1.13|9}} Whether the message is displayed for observers.&lt;br /&gt;
* '''[[StandardSideFilter]]''' tags and keys as argument; if the same client controls multiple sides that match, then the message will only be displayed once.&lt;br /&gt;
&lt;br /&gt;
=== [zoom] ===&lt;br /&gt;
&lt;br /&gt;
{{DevFeature1.13|8}}&lt;br /&gt;
&lt;br /&gt;
Changes the zoom level of the map.&lt;br /&gt;
&lt;br /&gt;
* '''factor''': The new zoom factor, measured as a multiple of the base zoom.&lt;br /&gt;
* '''relative''': If yes, zoom relative to current zoom level. Otherwise, set the absolute zoom level. Default no.&lt;br /&gt;
&lt;br /&gt;
== Useful Macros ==&lt;br /&gt;
There are some predefined macros that you find useful for interface actions. You can find a complete list along with a detailed explanation of how they work [http://www.wesnoth.org/macro-reference.xhtml here].&lt;br /&gt;
* '''{HIGHLIGHT_UNIT}''' Highlight a unit on the map. Use this to show important units&lt;br /&gt;
* '''{HIGHLIGHT_IMAGE}''' Places and highlights an image on the map. Use this to show important items or locations&lt;br /&gt;
* '''{SET_IMAGE}''' Places an image on the map which has no other function.&lt;br /&gt;
* '''{QUAKE &amp;lt;soundfile&amp;gt;}''' Creates a tremor-like screenshake and plays &amp;lt;soundfile&amp;gt;. For example, '''{QUAKE (rumble.ogg)}'''.&lt;br /&gt;
* '''{FLASH_WHITE}''' Flash the screen white momentarily. You can also replace WHITE with RED, BLUE or GREEN for a different colour.&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
* [[DirectActionsWML]]&lt;br /&gt;
* [[InternalActionsWML]]&lt;br /&gt;
* [[EventWML]]&lt;br /&gt;
* [[ReferenceWML]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category: WML Reference]]&lt;br /&gt;
[[Category: ActionsWML]]&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Template:DevDownload&amp;diff=74585</id>
		<title>Template:DevDownload</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Template:DevDownload&amp;diff=74585"/>
		<updated>2025-11-02T16:40:32Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
== Development (1.19 branch) ==&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
==== Windows (10 1903 and later) {{{4|}}} ====&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.17 | filename=wesnoth-1.19.17-win64.exe |&lt;br /&gt;
hash=3043cf6db1dcd17c341ee8af7d625a9d561cc06fbf091297a0aa6d3f413b21bb}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.16 | filename=wesnoth-1.19.16-win64.exe |&lt;br /&gt;
hash=4b52b3546c9c0d625058b60b018c967fdb793a04cf4700bc18388bb97f174907}}&lt;br /&gt;
&lt;br /&gt;
==== macOS (10.13 and later) {{{5|}}} ====&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.16 | filename=Wesnoth_1.19.16.dmg |&lt;br /&gt;
hash=730ddcf8b7f4d0cafa6bf924598528ff1e71e152d91dc3d8e9974e62a93bb8b8}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.15 | filename=Wesnoth_1.19.15.dmg |&lt;br /&gt;
hash=099a179a1b12f4b0babc9ca7fcfaa6027af794cbb8301cd0a06488049f56e6ec}}&lt;br /&gt;
&lt;br /&gt;
==== Source code ====&lt;br /&gt;
* [https://github.com/wesnoth/wesnoth/blob/master/INSTALL.md Compiling Wesnoth] - How to compile the source code&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.17 | filename=wesnoth-1.19.17.tar.bz2 |&lt;br /&gt;
hash=7a4f65b3bd845fc923a8f745591062061f5f72cedd4f81edb93e42b8e6b162ea}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.16 | filename=wesnoth-1.19.16.tar.bz2 |&lt;br /&gt;
hash=280c24868b19148278e3dd2604efecdf93b376f2652823453abafb55e94d0130}}&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Template:DevDownload&amp;diff=74522</id>
		<title>Template:DevDownload</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Template:DevDownload&amp;diff=74522"/>
		<updated>2025-09-25T21:56:23Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
== Development (1.19 branch) ==&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
==== Windows (10 1903 and later) {{{4|}}} ====&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.16 | filename=wesnoth-1.19.16-win64.exe |&lt;br /&gt;
hash=4b52b3546c9c0d625058b60b018c967fdb793a04cf4700bc18388bb97f174907}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.15 | filename=wesnoth-1.19.15-win64.exe |&lt;br /&gt;
hash=a17bd1fcdc7bebbf4b83cca838e1882bece27d7f092646b88661a0d47b5dcd5e}}&lt;br /&gt;
&lt;br /&gt;
==== macOS (10.13 and later) {{{5|}}} ====&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.16 | filename=Wesnoth_1.19.16.dmg |&lt;br /&gt;
hash=730ddcf8b7f4d0cafa6bf924598528ff1e71e152d91dc3d8e9974e62a93bb8b8}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.15 | filename=Wesnoth_1.19.15.dmg |&lt;br /&gt;
hash=099a179a1b12f4b0babc9ca7fcfaa6027af794cbb8301cd0a06488049f56e6ec}}&lt;br /&gt;
&lt;br /&gt;
==== Source code ====&lt;br /&gt;
* [https://github.com/wesnoth/wesnoth/blob/master/INSTALL.md Compiling Wesnoth] - How to compile the source code&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.16 | filename=wesnoth-1.19.16.tar.bz2 |&lt;br /&gt;
hash=280c24868b19148278e3dd2604efecdf93b376f2652823453abafb55e94d0130}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.15 | filename=wesnoth-1.19.15.tar.bz2 |&lt;br /&gt;
hash=22a2eedd40de70bc62e9e7e61d8277f6d7fcbef359efe28ed66821bcbd96378720ccd9831314322c}}&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Template:DevDownload&amp;diff=74504</id>
		<title>Template:DevDownload</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Template:DevDownload&amp;diff=74504"/>
		<updated>2025-08-25T21:43:53Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
== Development (1.19 branch) ==&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
==== Windows (10 1903 and later) {{{4|}}} ====&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.15 | filename=wesnoth-1.19.15-win64.exe |&lt;br /&gt;
hash=a17bd1fcdc7bebbf4b83cca838e1882bece27d7f092646b88661a0d47b5dcd5e}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.14 | filename=wesnoth-1.19.14-win64.exe |&lt;br /&gt;
hash=f4505fd37abc85f2f965169d871625cfc05a419ccaaf5e5290226134a4aab57a}}&lt;br /&gt;
&lt;br /&gt;
==== macOS (10.13 and later) {{{5|}}} ====&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.15 | filename=Wesnoth_1.19.15.dmg |&lt;br /&gt;
hash=099a179a1b12f4b0babc9ca7fcfaa6027af794cbb8301cd0a06488049f56e6ec}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.14 | filename=Wesnoth_1.19.14.dmg |&lt;br /&gt;
hash=addf7943fceeb05ea368460af6f7dd1e73353aedaf67cdbace034177acff4c0e}}&lt;br /&gt;
&lt;br /&gt;
==== Source code ====&lt;br /&gt;
* [https://github.com/wesnoth/wesnoth/blob/master/INSTALL.md Compiling Wesnoth] - How to compile the source code&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.15 | filename=wesnoth-1.19.15.tar.bz2 |&lt;br /&gt;
hash=22a2eedd40de70bc62e9e7e61d8277f6d7fcbef359efe28ed66821bcbd96378720ccd9831314322c}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.14 | filename=wesnoth-1.19.14.tar.bz2 |&lt;br /&gt;
hash=320b0c4b79ddbbc3a0e534f3a8c5f4a5ca7f8055145e3f7b20ccd9831314322c}}&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=WesnothTranslations&amp;diff=74456</id>
		<title>WesnothTranslations</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=WesnothTranslations&amp;diff=74456"/>
		<updated>2025-07-28T00:49:04Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==  Translations  ==&lt;br /&gt;
&lt;br /&gt;
Wesnoth is currently being translated into the following languages. These languages are active, with maintainer.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Translation !! Maintainer !! Contact&lt;br /&gt;
|-&lt;br /&gt;
| [[AncientGreekTranslation|Ancient Greek]] || Mejri Ziad (Hermestrismi)|| [mailto:beja.comuneATgmailDOTcom]&lt;br /&gt;
|-&lt;br /&gt;
| [[ArabicTranslation|Arabic]] || Mejri Ziad (Hermestrismi)|| [mailto:beja.comuneATgmailDOTcom]&lt;br /&gt;
|-&lt;br /&gt;
| [[BengaliTranslation|Bengali]] || Subhraman Sarkar (LumiousE) || lumious_e on Discord&lt;br /&gt;
|-&lt;br /&gt;
| [[BulgarianTranslation|Bulgarian]] || Ivan Petrov (TheWhiteKnight) || [mailto:vankata_petrovATabvDOTbg]&lt;br /&gt;
|-&lt;br /&gt;
| [[CatalanTranslation|Catalan]] || Miquel-Àngel Burgos i Fradeja || [mailto:miquel.angel.burgosATgmailDOTcom]&lt;br /&gt;
|-&lt;br /&gt;
| [[ChineseTranslation|Chinese]] || CloudiDust || [mailto:cloudidustATgmailDOTcom]&lt;br /&gt;
|-&lt;br /&gt;
| [[ChineseTaiwanTranslation|Chinese (Taiwan)]] || 楊綮銘 (Taiwan) || [mailto:steven2880ATgmailDOTcom]&lt;br /&gt;
|-&lt;br /&gt;
| [[CzechTranslation|Czech]] || Michal Žejdl || [mailto:lachimATemerDOTcz]&lt;br /&gt;
|-&lt;br /&gt;
| [[DutchTranslation|Dutch]] || Merijn de Vet || [mailto:merijndevetAThotmailDOTcom]&lt;br /&gt;
|-&lt;br /&gt;
| [[EnglishGBTranslation|English (GB)]] || Wedge009 || [mailto:wedge009ATwedge009DOTnet]&lt;br /&gt;
|-&lt;br /&gt;
| [[EnglishShawTranslation|English (Shaw)]] || Arc Riley || [mailto:ArcRileyATubuntuDOTcom]&lt;br /&gt;
|-&lt;br /&gt;
| [[Esperanto_translation|Esperanto]] || Mariano Street (mctpyt) || [mailto:mctpytATprotonDOTme]&lt;br /&gt;
|-&lt;br /&gt;
| [[FinnishTranslation|Finnish]] || Jaakko Saarikko (styxnix) || [mailto:jaakkoDOTsaarikkoATprotonmailDOTcom]&lt;br /&gt;
|-&lt;br /&gt;
| [[FrenchTranslation|French]] || demario || [mailto:wesnothfr-request@lists.tuxfamily.org?subject=subscribe mailing list]&lt;br /&gt;
|-&lt;br /&gt;
| [[GermanTranslation|German]] || Aaron Winter (Bitron) || &lt;br /&gt;
|-&lt;br /&gt;
| [[HungarianTranslation|Hungarian]] || Berda Jenő (bigbilly) || [mailto:big4billyATgmailDOTcom]&lt;br /&gt;
|-&lt;br /&gt;
| [[IndonesianTranslation|Indonesian]] || Irsyad Musthafa || [mailto:sevennightmareATtutanotaDOTde]&lt;br /&gt;
|-&lt;br /&gt;
| [[ItalianTranslation|Italian]] || Antonio Rosella || [mailto:arosellaATyahooDOTcom]&lt;br /&gt;
|-&lt;br /&gt;
| [[JapaneseTranslation|Japanese]] || Hironori Fujimoto (RatArmy) || [mailto:broadbarredfirefishATgmailDOTcom]&lt;br /&gt;
|-&lt;br /&gt;
| [[KoreanTranslation|Korean]] || mistzone || [mailto:drier22ATgmailDOTcom]&lt;br /&gt;
|-&lt;br /&gt;
| [[LatinTranslation|Latin]] || Daniel Faustmann || [mailto:donnerstag.freitag213@gmail.com]&lt;br /&gt;
|-&lt;br /&gt;
| [[NorwegianTranslation|Norwegian]] || Bloodaxe || [mailto:bloodaxenor@protonmail.com]&lt;br /&gt;
|-&lt;br /&gt;
| [[PolishTranslation|Polish]] || ForPeace || [https://forums.wesnoth.org/viewtopic.php?f=7&amp;amp;t=3796 forum thread]&lt;br /&gt;
|-&lt;br /&gt;
| [[PortugueseTranslation|Portuguese Brazilian]] || Andrei Machado || [mailto:andreisp.machadoATyahooDOTcom]&lt;br /&gt;
|-&lt;br /&gt;
| [[PortugueseContinentalTranslation|Portuguese (European)]] || trewe || [mailto:sjrs456ATyahooDOTfr]&lt;br /&gt;
|-&lt;br /&gt;
| [[RussianTranslation|Russian]] || Artem Khrapov || ([[User:kabachuha|kabachuha]]) [mailto:artemkhrapov2001ATyandexDOTru]&lt;br /&gt;
|-&lt;br /&gt;
| [[Scottish_Gaelic_Translation|Scottish Gaelic]] || GunChleoc || [mailto:fiosAIGforamnagaidhligDOTnet]&lt;br /&gt;
|-&lt;br /&gt;
| [[SlovakTranslation#Preklad|Slovak]] || Stanislav Hoferek || [mailto:shoferek@gmail.com]&lt;br /&gt;
|-&lt;br /&gt;
| [[SpanishTranslation|Spanish]] || Toranks || [mailto:davinciATtoranksDOTes]&lt;br /&gt;
|-&lt;br /&gt;
| [[SwedishTranslation|Swedish]] || Alex Alowersson (fluxbird) || [mailto:alexalowersonATgmailDOTcom]&lt;br /&gt;
|-&lt;br /&gt;
| [[TurkishTranslation|Turkish]] || Nilgün Belma Bugüner || [mailto:nilgunATbelgelerDOTorg]&lt;br /&gt;
|-&lt;br /&gt;
| [[UkrainianTranslation|Ukrainian]] || Oleksii Okhrimenko (lexa04) || Discord: amakri Email: [mailto:ohrimaleATgmailDOTcom]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Currenty unactive translations. If you wish to improve some of this languages, contact Ivanovic on Wesnoth Discord channel.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Translation !! Maintainer !! Contact&lt;br /&gt;
|-&lt;br /&gt;
| [[AfrikaansTranslation|Afrikaans]] || None || N/A&lt;br /&gt;
|-&lt;br /&gt;
| [[BasqueTranslation|Basque]] || None || N/A&lt;br /&gt;
|-&lt;br /&gt;
| [[BurmeseTranslation|Burmese]] || None || N/A&lt;br /&gt;
|-&lt;br /&gt;
| [[CroatianTranslation|Croatian]] || None || N/A&lt;br /&gt;
|-&lt;br /&gt;
| [[DanishTranslation|Danish]] || None || N/A&lt;br /&gt;
|-&lt;br /&gt;
| [[GalicianTranslation|Galician]] || None || N/A&lt;br /&gt;
|-&lt;br /&gt;
| [[GreekTranslation|Greek]] || None || N/A&lt;br /&gt;
|-&lt;br /&gt;
| [[HebrewTranslation|Hebrew]] || None || N/A&lt;br /&gt;
|-&lt;br /&gt;
| [[IcelandicTranslation|Icelandic]] || None || N/A&lt;br /&gt;
|-&lt;br /&gt;
| [[IrishTranslation|Irish]] || None || N/A&lt;br /&gt;
|-&lt;br /&gt;
| [[LatvianTranslation|Latvian]] || None || N/A&lt;br /&gt;
|-&lt;br /&gt;
| [[LithuanianTranslation|Lithuanian]] || None || N/A&lt;br /&gt;
|-&lt;br /&gt;
| [[MarathiTranslation|Marathi]] || None || N/A&lt;br /&gt;
|-&lt;br /&gt;
| [[MacedonianTranslation|Macedonian]] || None || N/A&lt;br /&gt;
|-&lt;br /&gt;
| [[OldEnglishTranslation|Old English]] || None || N/A&lt;br /&gt;
|-&lt;br /&gt;
| [[RACVTranslation|RACV]] || None || N/A&lt;br /&gt;
|-&lt;br /&gt;
| [[RomanianTranslation|Romanian]] || None || N/A&lt;br /&gt;
|-&lt;br /&gt;
| [[SerbianTranslation|Serbian]] || None || N/A&lt;br /&gt;
|-&lt;br /&gt;
| [[SlovenianTranslation|Slovenian]] || None || N/A&lt;br /&gt;
|-&lt;br /&gt;
| [[SpanishLatinAmericanTranslation|Spanish (Latin American)]] || None || N/A&lt;br /&gt;
|-&lt;br /&gt;
| [[ValencianTranslation|Valencian]] || None || N/A&lt;br /&gt;
|-&lt;br /&gt;
| [[VietnameseTranslation|Vietnamese]] || None || N/A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Mailing List ==&lt;br /&gt;
&lt;br /&gt;
There now is a mailing list dedicated to translation matters. It is mainly intended to be used for informing translation maintainers about important changes, to announce string freezes and other special things. Everyone is free to subscribe to this list.&lt;br /&gt;
&lt;br /&gt;
* [https://listengine.tuxfamily.org/wesnoth.org/i18n/ List info, how to subscribe, and archives from April 2022]&lt;br /&gt;
* [https://mailman.wesnoth.org/pipermail/i18n/ Old list archives (up until April 2022)]&lt;br /&gt;
&lt;br /&gt;
Please keep in mind that this list is not meant for discussing changes for one single translation but instead subjects which are relevant to all translations.&lt;br /&gt;
&lt;br /&gt;
==  See also  ==&lt;br /&gt;
&lt;br /&gt;
* [[WesnothTranslationsHowTo]]&lt;br /&gt;
* [[ImageLocalization]]&lt;br /&gt;
* [[GetText]]&lt;br /&gt;
* [http://gettext.wesnoth.org Translations statistics (stable)]&lt;br /&gt;
* [http://gettext.wesnoth.org/index.php?version=trunk&amp;amp;package=alloff Translations statistics (development)]&lt;br /&gt;
* [[GettextForTranslators#For_add-ons|Translating User Made Campaigns and add-ons]]&lt;br /&gt;
* [[SpellingMistakes]]&lt;br /&gt;
* [[CharactersStorys| Character descriptions for Translators (Spoiler Warning)]]&lt;br /&gt;
* [[Poetry of Wesnoth Translations]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Translations|*]]&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=WesnothTranslations&amp;diff=74455</id>
		<title>WesnothTranslations</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=WesnothTranslations&amp;diff=74455"/>
		<updated>2025-07-28T00:48:48Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==  Translations  ==&lt;br /&gt;
&lt;br /&gt;
Wesnoth is currently being translated into the following languages. These languages are active, with maintainer.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Translation !! Maintainer !! Contact&lt;br /&gt;
|-&lt;br /&gt;
| [[AncientGreekTranslation|Ancient Greek]] || Mejri Ziad (Hermestrismi)|| [mailto:beja.comuneATgmailDOTcom]&lt;br /&gt;
|-&lt;br /&gt;
| [[ArabicTranslation|Arabic]] || Mejri Ziad (Hermestrismi)|| [mailto:beja.comuneATgmailDOTcom]&lt;br /&gt;
|-&lt;br /&gt;
| [[BengaliTranslation|Bengali]] || Subhraman Sarkar (LumiousE) || lumious_e on Discord&lt;br /&gt;
|-&lt;br /&gt;
| [[BulgarianTranslation|Bulgarian]] || Ivan Petrov (TheWhiteKnight) || [mailto:vankata_petrovATabvDOTbg]&lt;br /&gt;
|-&lt;br /&gt;
| [[CatalanTranslation|Catalan]] || Miquel-Àngel Burgos i Fradeja || [mailto:miquel.angel.burgosATgmailDOTcom]&lt;br /&gt;
|-&lt;br /&gt;
| [[ChineseTranslation|Chinese]] || CloudiDust || [mailto:cloudidustATgmailDOTcom]&lt;br /&gt;
|-&lt;br /&gt;
| [[ChineseTaiwanTranslation|Chinese (Taiwan)]] || 楊綮銘 (Taiwan) || [mailto:steven2880ATgmailDOTcom]&lt;br /&gt;
|-&lt;br /&gt;
| [[CzechTranslation|Czech]] || Michal Žejdl || [mailto:lachimATemerDOTcz]&lt;br /&gt;
|-&lt;br /&gt;
| [[DutchTranslation|Dutch]] || Merijn de Vet || [mailto:merijndevetAThotmailDOTcom]&lt;br /&gt;
|-&lt;br /&gt;
| [[EnglishGBTranslation|English (GB)]] || Wedge009 || [mailto:wedge009ATwedge009DOTnet]&lt;br /&gt;
|-&lt;br /&gt;
| [[EnglishShawTranslation|English (Shaw)]] || Arc Riley || [mailto:ArcRileyATubuntuDOTcom]&lt;br /&gt;
|-&lt;br /&gt;
| [[Esperanto_translation|Esperanto]] || Mariano Street (mctpyt) || [mailto:mctpytATprotonDOTme]&lt;br /&gt;
|-&lt;br /&gt;
| [[FinnishTranslation|Finnish]] || Jaakko Saarikko (styxnix) || [mailto:jaakkoDOTsaarikkoATprotonmailDOTcom]&lt;br /&gt;
|-&lt;br /&gt;
| [[FrenchTranslation|French]] || demario || [mailto:wesnothfr-request@lists.tuxfamily.org?subject=subscribe mailing list]&lt;br /&gt;
|-&lt;br /&gt;
| [[GermanTranslation|German]] || Aaron Winter (Bitron) || &lt;br /&gt;
|-&lt;br /&gt;
| [[HungarianTranslation|Hungarian]] || Berda Jenő (bigbilly) || [mailto:big4billyATgmailDOTcom]&lt;br /&gt;
|-&lt;br /&gt;
| [[IndonesianTranslation|Indonesian]] || Irsyad Musthafa || [mailto:sevennightmareATtutanotaDOTde]&lt;br /&gt;
|-&lt;br /&gt;
| [[ItalianTranslation|Italian]] || Antonio Rosella || [mailto:arosellaATyahooDOTcom]&lt;br /&gt;
|-&lt;br /&gt;
| [[JapaneseTranslation|Japanese]] || Hironori Fujimoto (RatArmy) || [mailto:broadbarredfirefishATgmailDOTcom]&lt;br /&gt;
|-&lt;br /&gt;
| [[KoreanTranslation|Korean]] || mistzone || [mailto:drier22ATgmailDOTcom]&lt;br /&gt;
|-&lt;br /&gt;
| [[LatinTranslation|Latin]] || Daniel Faustmann || [mailto:donnerstag.freitag213@gmail.com]&lt;br /&gt;
|-&lt;br /&gt;
| [[NorwegianTranslation|Norwegian]] || Bloodaxe || [mailto:bloodaxenor@protonmail.com]&lt;br /&gt;
|-&lt;br /&gt;
| [[PolishTranslation|Polish]] || ForPeace || [https://forums.wesnoth.org/viewtopic.php?f=7&amp;amp;t=3796 forum thread]&lt;br /&gt;
|-&lt;br /&gt;
| [[PortugueseTranslation|Portuguese Brazilian]] || Andrei Machado || [mailto:andreisp.machadoATyahooDOTcom]&lt;br /&gt;
|-&lt;br /&gt;
| [[PortugueseContinentalTranslation|Portuguese (European)]] || trewe || [mailto:sjrs456ATyahooDOTfr]&lt;br /&gt;
|-&lt;br /&gt;
| [[RussianTranslation|Russian]] || Artem Khrapov || ([[User:kabachuha|kabachuha]]) [mailto:artemkhrapov2001ATyandexDOTru]&lt;br /&gt;
|-&lt;br /&gt;
| [[Scottish_Gaelic_Translation|Scottish Gaelic]] || GunChleoc || [mailto:fiosAIGforamnagaidhligDOTnet]&lt;br /&gt;
|-&lt;br /&gt;
| [[SlovakTranslation#Preklad|Slovak]] || Stanislav Hoferek || [mailto:shoferek@gmail.com]&lt;br /&gt;
|-&lt;br /&gt;
| [[SpanishTranslation|Spanish]] || Toranks || [mailto:davinciATtoranksDOTes]&lt;br /&gt;
|-&lt;br /&gt;
| [[SwedishTranslation|Swedish]] || Alex Alowersson (fluxbird) || [mailto:alexalowersonATgmailDOTcom]&lt;br /&gt;
|-&lt;br /&gt;
| [[TurkishTranslation|Turkish]] || Nilgün Belma Bugüner || [mailto:nilgunATbelgelerDOTorg]&lt;br /&gt;
|-&lt;br /&gt;
| [[UkrainianTranslation|Ukrainian]] || Oleksii Okhrimenko (lexa04) || Discord: amakri Email: [mailto:ohrimaleATgmailDOTcom]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Currenty unactive translations. If you wish to improve some of this languages, contact Ivanovic on Wesnoth Discord channel.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Translation !! Maintainer !! Contact&lt;br /&gt;
|-&lt;br /&gt;
| [[AfrikaansTranslation|Afrikaans]] || None || N/A&lt;br /&gt;
|-&lt;br /&gt;
| [[AncientGreekTranslation|Ancient Greek]] || None || N/A&lt;br /&gt;
|-&lt;br /&gt;
| [[BasqueTranslation|Basque]] || None || N/A&lt;br /&gt;
|-&lt;br /&gt;
| [[BurmeseTranslation|Burmese]] || None || N/A&lt;br /&gt;
|-&lt;br /&gt;
| [[CroatianTranslation|Croatian]] || None || N/A&lt;br /&gt;
|-&lt;br /&gt;
| [[DanishTranslation|Danish]] || None || N/A&lt;br /&gt;
|-&lt;br /&gt;
| [[GalicianTranslation|Galician]] || None || N/A&lt;br /&gt;
|-&lt;br /&gt;
| [[GreekTranslation|Greek]] || None || N/A&lt;br /&gt;
|-&lt;br /&gt;
| [[HebrewTranslation|Hebrew]] || None || N/A&lt;br /&gt;
|-&lt;br /&gt;
| [[IcelandicTranslation|Icelandic]] || None || N/A&lt;br /&gt;
|-&lt;br /&gt;
| [[IrishTranslation|Irish]] || None || N/A&lt;br /&gt;
|-&lt;br /&gt;
| [[LatvianTranslation|Latvian]] || None || N/A&lt;br /&gt;
|-&lt;br /&gt;
| [[LithuanianTranslation|Lithuanian]] || None || N/A&lt;br /&gt;
|-&lt;br /&gt;
| [[MarathiTranslation|Marathi]] || None || N/A&lt;br /&gt;
|-&lt;br /&gt;
| [[MacedonianTranslation|Macedonian]] || None || N/A&lt;br /&gt;
|-&lt;br /&gt;
| [[OldEnglishTranslation|Old English]] || None || N/A&lt;br /&gt;
|-&lt;br /&gt;
| [[RACVTranslation|RACV]] || None || N/A&lt;br /&gt;
|-&lt;br /&gt;
| [[RomanianTranslation|Romanian]] || None || N/A&lt;br /&gt;
|-&lt;br /&gt;
| [[SerbianTranslation|Serbian]] || None || N/A&lt;br /&gt;
|-&lt;br /&gt;
| [[SlovenianTranslation|Slovenian]] || None || N/A&lt;br /&gt;
|-&lt;br /&gt;
| [[SpanishLatinAmericanTranslation|Spanish (Latin American)]] || None || N/A&lt;br /&gt;
|-&lt;br /&gt;
| [[ValencianTranslation|Valencian]] || None || N/A&lt;br /&gt;
|-&lt;br /&gt;
| [[VietnameseTranslation|Vietnamese]] || None || N/A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Mailing List ==&lt;br /&gt;
&lt;br /&gt;
There now is a mailing list dedicated to translation matters. It is mainly intended to be used for informing translation maintainers about important changes, to announce string freezes and other special things. Everyone is free to subscribe to this list.&lt;br /&gt;
&lt;br /&gt;
* [https://listengine.tuxfamily.org/wesnoth.org/i18n/ List info, how to subscribe, and archives from April 2022]&lt;br /&gt;
* [https://mailman.wesnoth.org/pipermail/i18n/ Old list archives (up until April 2022)]&lt;br /&gt;
&lt;br /&gt;
Please keep in mind that this list is not meant for discussing changes for one single translation but instead subjects which are relevant to all translations.&lt;br /&gt;
&lt;br /&gt;
==  See also  ==&lt;br /&gt;
&lt;br /&gt;
* [[WesnothTranslationsHowTo]]&lt;br /&gt;
* [[ImageLocalization]]&lt;br /&gt;
* [[GetText]]&lt;br /&gt;
* [http://gettext.wesnoth.org Translations statistics (stable)]&lt;br /&gt;
* [http://gettext.wesnoth.org/index.php?version=trunk&amp;amp;package=alloff Translations statistics (development)]&lt;br /&gt;
* [[GettextForTranslators#For_add-ons|Translating User Made Campaigns and add-ons]]&lt;br /&gt;
* [[SpellingMistakes]]&lt;br /&gt;
* [[CharactersStorys| Character descriptions for Translators (Spoiler Warning)]]&lt;br /&gt;
* [[Poetry of Wesnoth Translations]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Translations|*]]&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Template:DevDownload&amp;diff=74454</id>
		<title>Template:DevDownload</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Template:DevDownload&amp;diff=74454"/>
		<updated>2025-07-27T02:10:16Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
== Development (1.19 branch) ==&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
==== Windows (10 1903 and later) {{{4|}}} ====&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.14 | filename=wesnoth-1.19.14-win64.exe |&lt;br /&gt;
hash=f4505fd37abc85f2f965169d871625cfc05a419ccaaf5e5290226134a4aab57a}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.13 | filename=wesnoth-1.19.13-win64.exe |&lt;br /&gt;
hash=7a096d9b0171b59b1fa6d400b0537ea11b5ffc6702dc821f09b9250486fba30a}}&lt;br /&gt;
&lt;br /&gt;
==== macOS (10.13 and later) {{{5|}}} ====&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.14 | filename=Wesnoth_1.19.14.dmg |&lt;br /&gt;
hash=addf7943fceeb05ea368460af6f7dd1e73353aedaf67cdbace034177acff4c0e}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.13 | filename=Wesnoth_1.19.13.dmg |&lt;br /&gt;
hash=6b2a854e96ed1ce0e06f58ba21a59d20e20ca259152c083fd330b8c0a681183f}}&lt;br /&gt;
&lt;br /&gt;
==== Source code ====&lt;br /&gt;
* [https://github.com/wesnoth/wesnoth/blob/master/INSTALL.md Compiling Wesnoth] - How to compile the source code&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.14 | filename=wesnoth-1.19.14.tar.bz2 |&lt;br /&gt;
hash=320b0c4b79ddbbc3a0e534f3a8c5f4a5ca7f8055145e3f7b20ccd9831314322c}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.13 | filename=wesnoth-1.19.13.tar.bz2 |&lt;br /&gt;
hash=1eea4bde4ccaf8afef6f502895bcde2bec42e8acec561c3944ac0703d8df4dde}}&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Template:DevDownload&amp;diff=74453</id>
		<title>Template:DevDownload</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Template:DevDownload&amp;diff=74453"/>
		<updated>2025-07-27T02:09:29Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
== Development (1.19 branch) ==&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
==== Windows (10 1903 and later) {{{4|}}} ====&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.14 | filename=wesnoth-1.19.14-win64.exe |&lt;br /&gt;
hash=f4505fd37abc85f2f965169d871625cfc05a419ccaaf5e5290226134a4aab57a}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.13 | filename=wesnoth-1.19.13-win64.exe |&lt;br /&gt;
hash=7a096d9b0171b59b1fa6d400b0537ea11b5ffc6702dc821f09b9250486fba30a}}&lt;br /&gt;
&lt;br /&gt;
==== macOS (10.13 and later) {{{5|}}} ====&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.14 | filename=Wesnoth_1.19.14.dmg |&lt;br /&gt;
hash=addf7943fceeb05ea368460af6f7dd1e73353aedaf67cdbace034177acff4c0e}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.13 | filename=Wesnoth_1.19.13.dmg |&lt;br /&gt;
hash=6b2a854e96ed1ce0e06f58ba21a59d20e20ca259152c083fd330b8c0a681183f}}&lt;br /&gt;
&lt;br /&gt;
==== Source code ====&lt;br /&gt;
* [https://github.com/wesnoth/wesnoth/blob/master/INSTALL.md Compiling Wesnoth] - How to compile the source code&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.14 | filename=wesnoth-1.19.14.tar.bz2 |&lt;br /&gt;
hash=320b0c4b79ddbbc3a0e534f3a8c5f4a5ca7f8055145e3f7b20ccd9831314322c}}&lt;br /&gt;
* [https://github.com/wesnoth/wesnoth/blob/master/INSTALL.md Compiling Wesnoth] - How to compile the source code&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.13 | filename=wesnoth-1.19.13.tar.bz2 |&lt;br /&gt;
hash=1eea4bde4ccaf8afef6f502895bcde2bec42e8acec561c3944ac0703d8df4dde}}&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Project&amp;diff=74452</id>
		<title>Project</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Project&amp;diff=74452"/>
		<updated>2025-07-26T18:07:42Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&amp;quot;tright&amp;quot;&amp;gt; __TOC__ &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;i&amp;gt;The Battle for Wesnoth&amp;lt;/i&amp;gt; is an [https://opensource.org/faq#osd open source] software project hosted on [https://github.com/wesnoth GitHub], created and maintained by &amp;lt;i&amp;gt;The Battle for Wesnoth Project&amp;lt;/i&amp;gt;, an [[Credits|international team of volunteers]] from diverse backgrounds. Conceived in 2003 by David White, &amp;lt;i&amp;gt;Wesnoth&amp;lt;/i&amp;gt; has caught the interest of a multitude of fans who have since contributed to different aspects of the game such as engine coding, content creation, art and music development, translation, packaging, testing, and community management.&lt;br /&gt;
&lt;br /&gt;
The Project is governed by the Project Manager and the Project Council as per the [https://www.wesnoth.org/constitution/ Project Constitution]. The current Project Manager [https://forums.wesnoth.org/viewtopic.php?t=55254 elected] by the development team for the Wesnoth 1.19.x development cycle is Pentarctagon. Past Project Managers include Charles Dang (vultraz), Iris Morelle (Irydacea), Nils Kneuper (Ivanovic) and Isaac Clerencia (isaac).&lt;br /&gt;
&lt;br /&gt;
The Wesnoth.org website, primary multiplayer server, and add-ons server facilities are managed by a few members of the project who staff the game's backend infrastructure.&lt;br /&gt;
&lt;br /&gt;
Funding for infrastructure and art and music commissions is provided by Software in the Public Interest, a US-based non-profit which manages revenue from donations made to Wesnoth through [https://liberapay.com/Wesnoth Liberapay] and [https://wesnoth.itch.io/battle-for-wesnoth itch.io]. While Software in the Public Interest financially supports the project, it does not have any involvement in its organization and direction. The current board of directors consists of Elvish_Hunter, Pentarctagon, and Soliton.&lt;br /&gt;
&lt;br /&gt;
== Content Creators ==&lt;br /&gt;
&lt;br /&gt;
Wesnoth's great replay value mainly stems from the great abundance of custom-made content developed by our talented community. It only takes a copy of the game, a text editor, creativity, and patience to create your own campaign, era, or multiplayer scenario!&lt;br /&gt;
&lt;br /&gt;
See [[Create]] for more information on the subject of user-made content development.&lt;br /&gt;
&lt;br /&gt;
== Artists ==&lt;br /&gt;
&lt;br /&gt;
There is plenty of room for improvement in areas such as animations and sound effects. User-made content creators are also always in need of new art, music, and sounds for their own projects!&lt;br /&gt;
&lt;br /&gt;
* [https://forums.wesnoth.org/viewforum.php?f=9 Mainline art contributions forum]   &amp;lt;small&amp;gt;''Attribution &amp;amp; copyright requirements for a contribution are outlined at [[ImageMetadata]]''&amp;lt;/small&amp;gt;&lt;br /&gt;
* [https://forums.wesnoth.org/viewforum.php?f=18 Mainline art development forum]&lt;br /&gt;
* [https://forums.wesnoth.org/viewforum.php?f=23 User-made art development forum]&lt;br /&gt;
* [https://forums.wesnoth.org/viewforum.php?f=14 Music contributions forum]&lt;br /&gt;
&lt;br /&gt;
== Developers ==&lt;br /&gt;
&lt;br /&gt;
The project is always eager to welcome new contributors able to help by fixing [https://bugs.wesnoth.org/ bugs], cleaning up and improving on existing code, or implementing new and exciting features!&lt;br /&gt;
&lt;br /&gt;
* [[WesnothRepository]] — cloning and using our Git repository&lt;br /&gt;
* [[CodingStandards]] and [[HackingWesnoth]] — information on our C++ style and coding conventions&lt;br /&gt;
* [[PatchSubmissionGuidelines]] — instructions for submitting your code contributions&lt;br /&gt;
* [[DeveloperGuide]] — additional information on commit messages, unit tests, etc.&lt;br /&gt;
* [https://devdocs.wesnoth.org/ Source code documentation] — generated from the game's source code using Doxygen and updated daily.&lt;br /&gt;
* [[ReferenceWML]] — information on the Wesnoth Markup Language (WML) and the game's Lua API&lt;br /&gt;
* [[DeveloperResources]] — additional development-related links&lt;br /&gt;
&lt;br /&gt;
== Translators ==&lt;br /&gt;
&lt;br /&gt;
In order to better reach its audience, Wesnoth needs people able to translate the game into other languages from across the globe. If you consider yourself able to help, join the translation team for your language -- or if none has been established already, follow the instructions to start your own!&lt;br /&gt;
&lt;br /&gt;
* [[WesnothTranslations]] — includes a list of translation maintainers and useful links for prospective translators&lt;br /&gt;
* [http://gettext.wesnoth.org Statistics]&lt;br /&gt;
&lt;br /&gt;
[[Category:Development]]&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Release_Steps&amp;diff=74442</id>
		<title>Release Steps</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Release_Steps&amp;diff=74442"/>
		<updated>2025-07-21T04:31:07Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Pre-release (stable only) ==&lt;br /&gt;
* Start the string freeze two weeks before the release.&lt;br /&gt;
* Do the pot update:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
scons pot-update update-po4a manual&lt;br /&gt;
git add -A&lt;br /&gt;
git commit -am &amp;quot;pot-update and regenerate doc files&amp;quot;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Email the translator's mailing list stating that the string freeze is starting.&lt;br /&gt;
&lt;br /&gt;
== Release (stable and master branches) ==&lt;br /&gt;
* Update [http://www.wesnoth.org/macro-reference.html macro-reference.html]:&lt;br /&gt;
&lt;br /&gt;
 cd data/tools/&lt;br /&gt;
 make macro-reference.html&lt;br /&gt;
* If stable&lt;br /&gt;
 scp macro-reference.html wesnoth@wesnoth.org:WWW/html/macro-reference.html&lt;br /&gt;
* If master&lt;br /&gt;
 scp macro-reference.html wesnoth@wesnoth.org:WWW/html/macro-reference-1.&amp;lt;version&amp;gt;.html&lt;br /&gt;
&lt;br /&gt;
* Regenerate the game credits and paste the contents to [[Credits]] on the wiki:&lt;br /&gt;
&lt;br /&gt;
 data/tools/about_cfg_to_wiki -w ./wesnoth &amp;gt; ./about.wiki&lt;br /&gt;
&lt;br /&gt;
* Check the '''changelog_entries''' folder for entries and update the changelog as necessary.&lt;br /&gt;
* Run the pot update (second time if this is a stable release).&lt;br /&gt;
* Do the pre-tag commit (check a previous commit as an example - this removes the &amp;quot;+dev&amp;quot; suffix everywhere).&lt;br /&gt;
* The the post-tag commit (check a previous commit as an example - this re-adds the &amp;quot;+dev&amp;quot; suffix everywhere).&lt;br /&gt;
* Tag the pre-tag commit with:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;git tag -a &amp;lt;version&amp;gt; -m &amp;quot;Wesnoth &amp;lt;version&amp;gt; (Alpha)&amp;quot; &amp;lt;commit hash&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
::- (Alpha)/(Beta) is only added for dev releases depending on where we are in the release cycle.&lt;br /&gt;
* Push the commits and the tag:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;git push&lt;br /&gt;
git push origin &amp;lt;version&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Ping the packagers on Discord that the release has been tagged:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;@packagers &amp;lt;version&amp;gt; has been tagged.&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Check that the new version is allowed on its respective multiplayer server.&lt;br /&gt;
* Update the header in Discord's #development channel.&lt;br /&gt;
* Upload music.zip and master.zip to SourceForge to the respective version's folder for use by Android&lt;br /&gt;
** master.zip contains the folders&lt;br /&gt;
*** data (data/core/music/ is removed)&lt;br /&gt;
*** fonts&lt;br /&gt;
*** images&lt;br /&gt;
*** sounds&lt;br /&gt;
*** translations&lt;br /&gt;
* Upload source code tarball to SourceForge and files.wesnoth.org (done by loonycyborg).&lt;br /&gt;
* Send an email to the packagers mailing list (done by loonycyborg).&lt;br /&gt;
* Upload the release to the various places Wesnoth is distributed (Steam, itch.io, SourceForge, macOS App Store, Flathub, F-Droid).&lt;br /&gt;
** Windows/Linux - handled by loonycyborg.&lt;br /&gt;
** macOS - handled by hrubymar.&lt;br /&gt;
** Android (F-Droid) - handled by LumiousE&lt;br /&gt;
* Post the forum announcements.&lt;br /&gt;
* Update the Downloads wiki page.&lt;br /&gt;
** url: https://wiki.wesnoth.org/Download&lt;br /&gt;
** dev template: https://wiki.wesnoth.org/Template:DevDownload#Development_.281.15_branch.29&lt;br /&gt;
** stable template: https://wiki.wesnoth.org/Template:StableDownload&lt;br /&gt;
* Add the News forum post.&lt;br /&gt;
* Post the Discord announcement.&lt;br /&gt;
** Make sure to publish it.&lt;br /&gt;
** Short link is: '''&amp;lt;nowiki&amp;gt;https://r.wesnoth.org/t#####&amp;lt;/nowiki&amp;gt;'''&lt;br /&gt;
* Post the itch.io devlog (copy of the Discord announcement).&lt;br /&gt;
* Update the wesnoth.org front page.&lt;br /&gt;
** See a previous version update commit to the '''wesmere''' repository.&lt;br /&gt;
** ssh into the website VM and execute the following shell commands (yes, it is specifically ''''make'''', not ''''make install''''!):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;sudo -iu wesnoth&lt;br /&gt;
cd ~/git/wesmere/static&lt;br /&gt;
git pull&lt;br /&gt;
make&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Generate the Steam announcement by running the following command in your local wesnoth repository root:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;python3 data/tools/steam-changelog changelog.md &amp;lt;version&amp;gt; &amp;gt; &amp;lt;version&amp;gt;.txt&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Post the Steam announcement.&lt;br /&gt;
* Log into Wesnoth's Steam page.&lt;br /&gt;
** Click &amp;quot;A Game Update&amp;quot;.&lt;br /&gt;
** Pick &amp;quot;Small Update&amp;quot;.&lt;br /&gt;
** Paste the output of of the above python command into the event description.&lt;br /&gt;
** Click &amp;quot;Link To Build&amp;quot; and select the appropriate branch.&lt;br /&gt;
** Edit the appropriate .xcf file from the [https://github.com/wesnoth/resources/tree/master/social-media-assets Resources repository] ('''wesnoth_event_header.xcf''' for stable releases, '''wesnoth_beta_header.xcf''' for development releases) and export it to PNG.&lt;br /&gt;
*** This requires the '''oldania''' font to be installed, which on Linux/Ubuntu-derivatives can be installed via the command:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;apt install fonts-adf-oldania&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Post the announcement to Fosstodon.&lt;br /&gt;
* Post the announcement to Reddit. (Elvish_Hunter)&lt;br /&gt;
** Add the &amp;quot;Development release&amp;quot;/&amp;quot;Stable release&amp;quot; flair.&lt;br /&gt;
** Don't paste the link in the post, directly post it as a link.&lt;br /&gt;
&lt;br /&gt;
== New Stable Series ==&lt;br /&gt;
=== Beta 1 ===&lt;br /&gt;
Write up the new Start page (ie: https://www.wesnoth.org/start/1.16/).&lt;br /&gt;
&lt;br /&gt;
=== Beta 2 ===&lt;br /&gt;
Make the new Start page available to Translators.&lt;br /&gt;
&lt;br /&gt;
=== RC1 ===&lt;br /&gt;
Before release, the new multiplayer server and add-ons server instances need to be setup. The server running the website status is owned by Iris - she needs to push updates to it.&lt;br /&gt;
* Multiplayer server&lt;br /&gt;
** Needs no changes since it goes to port 15000 and then that redirects based on version. The existing dev multiplayer server will be reused as the new stable instance.&lt;br /&gt;
** The Discord website status bot and the site status page (https://status.wesnoth.org/ - bin/valen.pl) need to be updated to rename the dev version to the stable version.&lt;br /&gt;
** A new stable multiplayer instance needs to be added to the alternate server.&lt;br /&gt;
&lt;br /&gt;
* Add-ons server - The port is the version number, for example 1.16 is 15016, 1.18 is 15018, etc.&lt;br /&gt;
** C++ update (currently default_campaignd_port in addon/validation.cpp)&lt;br /&gt;
** Python update (data/tools/wesnoth/campaignserver_client.py)&lt;br /&gt;
** Website update (bin/valen.pl) in the valen repository to add the new instance.&lt;br /&gt;
** The Discord website status bot and the site status page (https://status.wesnoth.org/ - bin/valen.pl) need to be updated to add the new version.&lt;br /&gt;
** Add a 1.18 cron job for ~wesnoth/bin/update_addons in the websites VM and remove the 1.17 cron job.&lt;br /&gt;
&lt;br /&gt;
* Flatpak&lt;br /&gt;
** &lt;br /&gt;
&lt;br /&gt;
* Add screenshots to https://wiki.wesnoth.org/Screenshots&lt;br /&gt;
&lt;br /&gt;
* Start page - soft link the folder from the repository to the folder that shows up on the actual website:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
cd /srv/www/html/start&lt;br /&gt;
ln -s /home/git/wesnoth/start/&amp;lt;version&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Update ci_main.yml to use the new branch instead of the master branch.&lt;br /&gt;
&lt;br /&gt;
[[Category:Release_Notes]]&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Release_Steps&amp;diff=74441</id>
		<title>Release Steps</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Release_Steps&amp;diff=74441"/>
		<updated>2025-07-21T03:04:52Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Pre-release (stable only) ==&lt;br /&gt;
* Start the string freeze two weeks before the release.&lt;br /&gt;
* Do the pot update:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
scons pot-update update-po4a manual&lt;br /&gt;
git add -A&lt;br /&gt;
git commit -am &amp;quot;pot-update and regenerate doc files&amp;quot;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Email the translator's mailing list stating that the string freeze is starting.&lt;br /&gt;
&lt;br /&gt;
== Release (stable and master branches) ==&lt;br /&gt;
* Update [http://www.wesnoth.org/macro-reference.html macro-reference.html]:&lt;br /&gt;
&lt;br /&gt;
 cd data/tools/&lt;br /&gt;
 make macro-reference.html&lt;br /&gt;
* If stable&lt;br /&gt;
 scp macro-reference.html wesnoth@wesnoth.org:WWW/html/macro-reference.html&lt;br /&gt;
* If master&lt;br /&gt;
 scp macro-reference.html wesnoth@wesnoth.org:WWW/html/macro-reference-1.&amp;lt;version&amp;gt;.html&lt;br /&gt;
&lt;br /&gt;
* Regenerate the game credits and paste the contents to [[Credits]] on the wiki:&lt;br /&gt;
&lt;br /&gt;
 data/tools/about_cfg_to_wiki -w ./wesnoth &amp;gt; ./about.wiki&lt;br /&gt;
&lt;br /&gt;
* Check the '''changelog_entries''' folder for entries and update the changelog as necessary.&lt;br /&gt;
* Run the pot update (second time if this is a stable release).&lt;br /&gt;
* Do the pre-tag commit (check a previous commit as an example - this removes the &amp;quot;+dev&amp;quot; suffix everywhere).&lt;br /&gt;
* The the post-tag commit (check a previous commit as an example - this re-adds the &amp;quot;+dev&amp;quot; suffix everywhere).&lt;br /&gt;
* Tag the pre-tag commit with:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;git tag -a &amp;lt;version&amp;gt; -m &amp;quot;Wesnoth &amp;lt;version&amp;gt; (Alpha)&amp;quot; &amp;lt;commit hash&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
::- (Alpha)/(Beta) is only added for dev releases depending on where we are in the release cycle.&lt;br /&gt;
* Push the commits and the tag:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;git push&lt;br /&gt;
git push origin &amp;lt;version&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Ping the packagers on Discord that the release has been tagged:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;@packagers &amp;lt;version&amp;gt; has been tagged.&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Check that the new version is allowed on its respective multiplayer server.&lt;br /&gt;
* Update the header in Discord's #development channel.&lt;br /&gt;
* Add items to the Release Notes page on this wiki for the release.&lt;br /&gt;
* Sync items on the Release Notes page to the changelog.&lt;br /&gt;
* Upload source code tarball to SourceForge and files.wesnoth.org (done by loonycyborg).&lt;br /&gt;
* Send an email to the packagers mailing list (done by loonycyborg).&lt;br /&gt;
* Upload the release to the various places Wesnoth is distributed (Steam, itch.io, SourceForge, macOS App Store, Flathub, F-Droid).&lt;br /&gt;
** Windows/Linux - handled by loonycyborg.&lt;br /&gt;
** macOS - handled by hrubymar.&lt;br /&gt;
** Android (F-Droid) - handled by LumiousE&lt;br /&gt;
* Post the forum announcements.&lt;br /&gt;
* Update the Downloads wiki page.&lt;br /&gt;
** url: https://wiki.wesnoth.org/Download&lt;br /&gt;
** dev template: https://wiki.wesnoth.org/Template:DevDownload#Development_.281.15_branch.29&lt;br /&gt;
** stable template: https://wiki.wesnoth.org/Template:StableDownload&lt;br /&gt;
* Add the News forum post.&lt;br /&gt;
* Post the Discord announcement.&lt;br /&gt;
** Make sure to publish it.&lt;br /&gt;
** Short link is: '''&amp;lt;nowiki&amp;gt;https://r.wesnoth.org/t#####&amp;lt;/nowiki&amp;gt;'''&lt;br /&gt;
* Post the itch.io devlog (copy of the Discord announcement).&lt;br /&gt;
* Update the wesnoth.org front page.&lt;br /&gt;
** See a previous version update commit to the '''wesmere''' repository.&lt;br /&gt;
** ssh into the website VM and execute the following shell commands (yes, it is specifically ''''make'''', not ''''make install''''!):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;sudo -iu wesnoth&lt;br /&gt;
cd ~/git/wesmere/static&lt;br /&gt;
git pull&lt;br /&gt;
make&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Generate the Steam announcement by running the following command in your local wesnoth repository root:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;python3 data/tools/steam-changelog changelog.md &amp;lt;version&amp;gt; &amp;gt; &amp;lt;version&amp;gt;.txt&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Post the Steam announcement.&lt;br /&gt;
* Log into Wesnoth's Steam page.&lt;br /&gt;
** Click &amp;quot;A Game Update&amp;quot;.&lt;br /&gt;
** Pick &amp;quot;Small Update&amp;quot;.&lt;br /&gt;
** Paste the output of of the above python command into the event description.&lt;br /&gt;
** Click &amp;quot;Link To Build&amp;quot; and select the appropriate branch.&lt;br /&gt;
** Edit the appropriate .xcf file from the [https://github.com/wesnoth/resources/tree/master/social-media-assets Resources repository] ('''wesnoth_event_header.xcf''' for stable releases, '''wesnoth_beta_header.xcf''' for development releases) and export it to PNG.&lt;br /&gt;
*** This requires the '''oldania''' font to be installed, which on Linux/Ubuntu-derivatives can be installed via the command:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;apt install fonts-adf-oldania&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Post the announcement to Fosstodon.&lt;br /&gt;
* Post the announcement to Reddit. (Elvish_Hunter)&lt;br /&gt;
** Add the &amp;quot;Development release&amp;quot;/&amp;quot;Stable release&amp;quot; flair.&lt;br /&gt;
** Don't paste the link in the post, directly post it as a link.&lt;br /&gt;
&lt;br /&gt;
== New Stable Series ==&lt;br /&gt;
=== Beta 1 ===&lt;br /&gt;
Write up the new Start page (ie: https://www.wesnoth.org/start/1.16/).&lt;br /&gt;
&lt;br /&gt;
=== Beta 2 ===&lt;br /&gt;
Make the new Start page available to Translators.&lt;br /&gt;
&lt;br /&gt;
=== RC1 ===&lt;br /&gt;
Before release, the new multiplayer server and add-ons server instances need to be setup. The server running the website status is owned by Iris - she needs to push updates to it.&lt;br /&gt;
* Multiplayer server&lt;br /&gt;
** Needs no changes since it goes to port 15000 and then that redirects based on version. The existing dev multiplayer server will be reused as the new stable instance.&lt;br /&gt;
** The Discord website status bot and the site status page (https://status.wesnoth.org/ - bin/valen.pl) need to be updated to rename the dev version to the stable version.&lt;br /&gt;
** A new stable multiplayer instance needs to be added to the alternate server.&lt;br /&gt;
&lt;br /&gt;
* Add-ons server - The port is the version number, for example 1.16 is 15016, 1.18 is 15018, etc.&lt;br /&gt;
** C++ update (currently default_campaignd_port in addon/validation.cpp)&lt;br /&gt;
** Python update (data/tools/wesnoth/campaignserver_client.py)&lt;br /&gt;
** Website update (bin/valen.pl) in the valen repository to add the new instance.&lt;br /&gt;
** The Discord website status bot and the site status page (https://status.wesnoth.org/ - bin/valen.pl) need to be updated to add the new version.&lt;br /&gt;
** Add a 1.18 cron job for ~wesnoth/bin/update_addons in the websites VM and remove the 1.17 cron job.&lt;br /&gt;
&lt;br /&gt;
* Flatpak&lt;br /&gt;
** &lt;br /&gt;
&lt;br /&gt;
* Add screenshots to https://wiki.wesnoth.org/Screenshots&lt;br /&gt;
&lt;br /&gt;
* Start page - soft link the folder from the repository to the folder that shows up on the actual website:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
cd /srv/www/html/start&lt;br /&gt;
ln -s /home/git/wesnoth/start/&amp;lt;version&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Update ci_main.yml to use the new branch instead of the master branch.&lt;br /&gt;
&lt;br /&gt;
[[Category:Release_Notes]]&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Release_Steps&amp;diff=74440</id>
		<title>Release Steps</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Release_Steps&amp;diff=74440"/>
		<updated>2025-07-21T02:51:54Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Pre-release (stable only) ==&lt;br /&gt;
* Start the string freeze two weeks before the release.&lt;br /&gt;
* Do the pot update:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
scons pot-update update-po4a manual&lt;br /&gt;
git add -A&lt;br /&gt;
git commit -am &amp;quot;pot-update and regenerate doc files&amp;quot;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Email the translator's mailing list stating that the string freeze is starting.&lt;br /&gt;
&lt;br /&gt;
== Release (stable and master branches) ==&lt;br /&gt;
* Update [http://www.wesnoth.org/macro-reference.html macro-reference.html]:&lt;br /&gt;
&lt;br /&gt;
 cd data/tools/&lt;br /&gt;
 make macro-reference.html&lt;br /&gt;
* If stable&lt;br /&gt;
 scp macro-reference.html wesnoth@wesnoth.org:WWW/html/macro-reference.html&lt;br /&gt;
* If master&lt;br /&gt;
 scp macro-reference.html wesnoth@wesnoth.org:WWW/html/macro-reference-1.&amp;lt;version&amp;gt;.html&lt;br /&gt;
&lt;br /&gt;
* Regenerate the game credits and paste the contents to [[Credits]] on the wiki:&lt;br /&gt;
&lt;br /&gt;
 data/tools/about_cfg_to_wiki -w ./wesnoth &amp;gt; ./about.wiki&lt;br /&gt;
&lt;br /&gt;
* Check the '''changelog_entries''' folder for entries and update the changelog as necessary.&lt;br /&gt;
* Run the pot update (second time if this is a stable release).&lt;br /&gt;
* Do the pre-tag commit (check a previous commit as an example - this removes the &amp;quot;+dev&amp;quot; suffix everywhere).&lt;br /&gt;
* The the post-tag commit (check a previous commit as an example - this re-adds the &amp;quot;+dev&amp;quot; suffix everywhere).&lt;br /&gt;
* Tag the pre-tag commit with:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;git tag -a &amp;lt;version&amp;gt; -m &amp;quot;Wesnoth &amp;lt;version&amp;gt; (Alpha)&amp;quot; &amp;lt;commit hash&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
::- (Alpha)/(Beta) is only added for dev releases depending on where we are in the release cycle.&lt;br /&gt;
* Push the commits and the tag:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;git push&lt;br /&gt;
git push origin &amp;lt;version&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Ping the packagers on Discord that the release has been tagged:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;@packagers &amp;lt;version&amp;gt; has been tagged.&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Check that the new version is allowed on its respective multiplayer server.&lt;br /&gt;
* Update the header in Discord's #development channel.&lt;br /&gt;
* Add items to the Release Notes page on this wiki for the release.&lt;br /&gt;
* Sync items on the Release Notes page to the changelog.&lt;br /&gt;
* Upload source code tarball to SourceForge and files.wesnoth.org (done by loonycyborg).&lt;br /&gt;
* Send an email to the packagers mailing list (done by loonycyborg).&lt;br /&gt;
* Upload the release to the various places Wesnoth is distributed (Steam, itch.io, SourceForge, macOS App Store, Flathub).&lt;br /&gt;
** Windows/Linux - handled by loonycyborg.&lt;br /&gt;
** macOS - handled by hrubymar.&lt;br /&gt;
** Android (F-Droid) - handled by LumiousE&lt;br /&gt;
* Post the forum announcements.&lt;br /&gt;
* Update the Downloads wiki page.&lt;br /&gt;
** url: https://wiki.wesnoth.org/Download&lt;br /&gt;
** dev template: https://wiki.wesnoth.org/Template:DevDownload#Development_.281.15_branch.29&lt;br /&gt;
** stable template: https://wiki.wesnoth.org/Template:StableDownload&lt;br /&gt;
* Add the News forum post.&lt;br /&gt;
* Post the Discord announcement.&lt;br /&gt;
** Make sure to publish it.&lt;br /&gt;
** Short link is: '''&amp;lt;nowiki&amp;gt;https://r.wesnoth.org/t#####&amp;lt;/nowiki&amp;gt;'''&lt;br /&gt;
* Post the itch.io devlog (copy of the Discord announcement).&lt;br /&gt;
* Update the wesnoth.org front page.&lt;br /&gt;
** See a previous version update commit to the '''wesmere''' repository.&lt;br /&gt;
** ssh into the website VM and execute the following shell commands (yes, it is specifically ''''make'''', not ''''make install''''!):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;sudo -iu wesnoth&lt;br /&gt;
cd ~/git/wesmere/static&lt;br /&gt;
git pull&lt;br /&gt;
make&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Generate the Steam announcement by running the following command in your local wesnoth repository root:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;python3 data/tools/steam-changelog changelog.md &amp;lt;version&amp;gt; &amp;gt; &amp;lt;version&amp;gt;.txt&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Post the Steam announcement.&lt;br /&gt;
* Log into Wesnoth's Steam page.&lt;br /&gt;
** Click &amp;quot;A Game Update&amp;quot;.&lt;br /&gt;
** Pick &amp;quot;Small Update&amp;quot;.&lt;br /&gt;
** Paste the output of of the above python command into the event description.&lt;br /&gt;
** Click &amp;quot;Link To Build&amp;quot; and select the appropriate branch.&lt;br /&gt;
** Edit the appropriate .xcf file from the [https://github.com/wesnoth/resources/tree/master/social-media-assets Resources repository] ('''wesnoth_event_header.xcf''' for stable releases, '''wesnoth_beta_header.xcf''' for development releases) and export it to PNG.&lt;br /&gt;
*** This requires the '''oldania''' font to be installed, which on Linux/Ubuntu-derivatives can be installed via the command:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;apt install fonts-adf-oldania&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Post the announcement to Fosstodon.&lt;br /&gt;
* Post the announcement to Reddit. (Elvish_Hunter)&lt;br /&gt;
** Add the &amp;quot;Development release&amp;quot;/&amp;quot;Stable release&amp;quot; flair.&lt;br /&gt;
** Don't paste the link in the post, directly post it as a link.&lt;br /&gt;
&lt;br /&gt;
== New Stable Series ==&lt;br /&gt;
=== Beta 1 ===&lt;br /&gt;
Write up the new Start page (ie: https://www.wesnoth.org/start/1.16/).&lt;br /&gt;
&lt;br /&gt;
=== Beta 2 ===&lt;br /&gt;
Make the new Start page available to Translators.&lt;br /&gt;
&lt;br /&gt;
=== RC1 ===&lt;br /&gt;
Before release, the new multiplayer server and add-ons server instances need to be setup. The server running the website status is owned by Iris - she needs to push updates to it.&lt;br /&gt;
* Multiplayer server&lt;br /&gt;
** Needs no changes since it goes to port 15000 and then that redirects based on version. The existing dev multiplayer server will be reused as the new stable instance.&lt;br /&gt;
** The Discord website status bot and the site status page (https://status.wesnoth.org/ - bin/valen.pl) need to be updated to rename the dev version to the stable version.&lt;br /&gt;
** A new stable multiplayer instance needs to be added to the alternate server.&lt;br /&gt;
&lt;br /&gt;
* Add-ons server - The port is the version number, for example 1.16 is 15016, 1.18 is 15018, etc.&lt;br /&gt;
** C++ update (currently default_campaignd_port in addon/validation.cpp)&lt;br /&gt;
** Python update (data/tools/wesnoth/campaignserver_client.py)&lt;br /&gt;
** Website update (bin/valen.pl) in the valen repository to add the new instance.&lt;br /&gt;
** The Discord website status bot and the site status page (https://status.wesnoth.org/ - bin/valen.pl) need to be updated to add the new version.&lt;br /&gt;
** Add a 1.18 cron job for ~wesnoth/bin/update_addons in the websites VM and remove the 1.17 cron job.&lt;br /&gt;
&lt;br /&gt;
* Flatpak&lt;br /&gt;
** &lt;br /&gt;
&lt;br /&gt;
* Add screenshots to https://wiki.wesnoth.org/Screenshots&lt;br /&gt;
&lt;br /&gt;
* Start page - soft link the folder from the repository to the folder that shows up on the actual website:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
cd /srv/www/html/start&lt;br /&gt;
ln -s /home/git/wesnoth/start/&amp;lt;version&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Update ci_main.yml to use the new branch instead of the master branch.&lt;br /&gt;
&lt;br /&gt;
[[Category:Release_Notes]]&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Template:DevDownload&amp;diff=74409</id>
		<title>Template:DevDownload</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Template:DevDownload&amp;diff=74409"/>
		<updated>2025-06-23T18:23:35Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
== Development (1.19 branch) ==&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
==== Windows (10 1903 and later) {{{4|}}} ====&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.13 | filename=wesnoth-1.19.13-win64.exe |&lt;br /&gt;
hash=7a096d9b0171b59b1fa6d400b0537ea11b5ffc6702dc821f09b9250486fba30a}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.12 | filename=wesnoth-1.19.12-win64.exe |&lt;br /&gt;
hash=97f88140d55598f876ea4e148358fad1187437bae488c1e5d63bcd2bbd6aeaed}}&lt;br /&gt;
&lt;br /&gt;
==== macOS (10.13 and later) {{{5|}}} ====&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.13 | filename=Wesnoth_1.19.13.dmg |&lt;br /&gt;
hash=6b2a854e96ed1ce0e06f58ba21a59d20e20ca259152c083fd330b8c0a681183f}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.12 | filename=Wesnoth_1.19.12.dmg |&lt;br /&gt;
hash=4361644e6ee6c9c2845080db2ebd025fa005fb601321dee98f261f345e9c7317}}&lt;br /&gt;
&lt;br /&gt;
==== Source code ====&lt;br /&gt;
* [https://github.com/wesnoth/wesnoth/blob/master/INSTALL.md Compiling Wesnoth] - How to compile the source code&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.13 | filename=wesnoth-1.19.13.tar.bz2 |&lt;br /&gt;
hash=1eea4bde4ccaf8afef6f502895bcde2bec42e8acec561c3944ac0703d8df4dde}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.12 | filename=wesnoth-1.19.12.tar.bz2 |&lt;br /&gt;
hash=9142678e9afd021cacb61ebef3959053040cf2c1b2a0f2996d7978329662c381}}&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Template:DevDownload&amp;diff=74303</id>
		<title>Template:DevDownload</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Template:DevDownload&amp;diff=74303"/>
		<updated>2025-06-02T16:47:48Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
== Development (1.19 branch) ==&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
==== Windows (10 1903 and later) {{{4|}}} ====&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.12 | filename=wesnoth-1.19.12-win64.exe |&lt;br /&gt;
hash=97f88140d55598f876ea4e148358fad1187437bae488c1e5d63bcd2bbd6aeaed}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.11 | filename=wesnoth-1.19.11-win64.exe |&lt;br /&gt;
hash=54e82026505108c48f9cebe8e17c7d2f6abd00ce9a9bf3bcd65bff77e927aae8}}&lt;br /&gt;
&lt;br /&gt;
==== macOS (10.13 and later) {{{5|}}} ====&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.12 | filename=Wesnoth_1.19.12.dmg |&lt;br /&gt;
hash=4361644e6ee6c9c2845080db2ebd025fa005fb601321dee98f261f345e9c7317}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.11 | filename=Wesnoth_1.19.11.dmg |&lt;br /&gt;
hash=8563f3e6de8e0979e95c91441f85b61a76260fffd15ccdd42224be3a50c2b653}}&lt;br /&gt;
&lt;br /&gt;
==== Source code ====&lt;br /&gt;
* [https://github.com/wesnoth/wesnoth/blob/master/INSTALL.md Compiling Wesnoth] - How to compile the source code&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.12 | filename=wesnoth-1.19.12.tar.bz2 |&lt;br /&gt;
hash=9142678e9afd021cacb61ebef3959053040cf2c1b2a0f2996d7978329662c381}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.11 | filename=wesnoth-1.19.11.tar.bz2 |&lt;br /&gt;
hash=8a2397059080020f9505d17fd0ab3121e39eb2288838b4f43a4adebb1b87b0bc}}&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Template:StableDownload&amp;diff=74302</id>
		<title>Template:StableDownload</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Template:StableDownload&amp;diff=74302"/>
		<updated>2025-06-02T16:46:53Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
== Stable (1.18 branch) ==&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
==== Windows (10 1903 and later, 64-bit only) {{{4|}}} ====&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth-1.18 |&lt;br /&gt;
version=1.18.5 | filename=wesnoth-1.18.5-win64.exe |&lt;br /&gt;
hash=915d9c0374221782fbfaecd3ac8d8833b470c6ed6c059e6086d5082a28edf80f}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth-1.18 |&lt;br /&gt;
version=1.18.4 | filename=wesnoth-1.18.4-win64.exe |&lt;br /&gt;
hash=d7211ba46831bcc456a33cdb66d6c05cf55866eb3314c0880b72b1c8df324ac2}}&lt;br /&gt;
&lt;br /&gt;
==== macOS (10.12 and later) {{{5|}}} ====&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth-1.18 |&lt;br /&gt;
version=1.18.5 | filename=Wesnoth_1.18.5.dmg |&lt;br /&gt;
hash=73e34ee58a7c81055bdf94f1b0646a524a992235682ce227fb8d3829af4061f1}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth-1.18 |&lt;br /&gt;
version=1.18.4 | filename=Wesnoth_1.18.4.dmg |&lt;br /&gt;
hash=a12904628042e42c2c1dd7292c54c72a199a591c3e13d823ac3236a421e1fbb8}}&lt;br /&gt;
&lt;br /&gt;
==== Source code ====&lt;br /&gt;
* [https://github.com/wesnoth/wesnoth/blob/master/INSTALL.md Compiling Wesnoth] - How to compile the source code&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth-1.18 |&lt;br /&gt;
version=1.18.5 | filename=wesnoth-1.18.5.tar.bz2 |&lt;br /&gt;
hash=e15db3caf446d91d389fc275f10c1a9e7ca3c6176c3b8ce94f5ee4a7a0c81bd6}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth-1.18 |&lt;br /&gt;
version=1.18.4 | filename=wesnoth-1.18.4.tar.bz2 |&lt;br /&gt;
hash=d7211ba46831bcc456a33cdb66d6c05cf55866eb3314c0880b72b1c8df324ac2}}&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Template:DevDownload&amp;diff=74285</id>
		<title>Template:DevDownload</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Template:DevDownload&amp;diff=74285"/>
		<updated>2025-05-05T18:58:27Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
== Development (1.19 branch) ==&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
==== Windows (10 1903 and later) {{{4|}}} ====&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.11 | filename=wesnoth-1.19.11-win64.exe |&lt;br /&gt;
hash=54e82026505108c48f9cebe8e17c7d2f6abd00ce9a9bf3bcd65bff77e927aae8}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.10 | filename=wesnoth-1.19.10-win64.exe |&lt;br /&gt;
hash=8ad9b6e55102d058ba54b3f45020b9b37ee401a0f6c6aa5df442e478a5b809c9}}&lt;br /&gt;
&lt;br /&gt;
==== macOS (10.13 and later) {{{5|}}} ====&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.11 | filename=Wesnoth_1.19.11.dmg |&lt;br /&gt;
hash=8563f3e6de8e0979e95c91441f85b61a76260fffd15ccdd42224be3a50c2b653}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.10 | filename=Wesnoth_1.19.10.dmg |&lt;br /&gt;
hash=8b73b69f908e9c894d3229abdf5f55e40ce6aabfca5cad90a8e9e6c050e1b377}}&lt;br /&gt;
&lt;br /&gt;
==== Source code ====&lt;br /&gt;
* [https://github.com/wesnoth/wesnoth/blob/master/INSTALL.md Compiling Wesnoth] - How to compile the source code&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.11 | filename=wesnoth-1.19.11.tar.bz2 |&lt;br /&gt;
hash=8a2397059080020f9505d17fd0ab3121e39eb2288838b4f43a4adebb1b87b0bc}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.10 | filename=wesnoth-1.19.10.tar.bz2 |&lt;br /&gt;
hash=c435d76d35bb336ad64ac80040c8b9e046571f80b51794f16a41b99b6b99e78f}}&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Template:DevDownload&amp;diff=74233</id>
		<title>Template:DevDownload</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Template:DevDownload&amp;diff=74233"/>
		<updated>2025-03-23T17:03:20Z</updated>

		<summary type="html">&lt;p&gt;Pentarctagon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
== Development (1.19 branch) ==&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
==== Windows (10 1903 and later) {{{4|}}} ====&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.10 | filename=wesnoth-1.19.10-win64.exe |&lt;br /&gt;
hash=8ad9b6e55102d058ba54b3f45020b9b37ee401a0f6c6aa5df442e478a5b809c9}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.9 | filename=wesnoth-1.19.9-win64.exe |&lt;br /&gt;
hash=ec5217a67846b18678d2585304e154c6e009f1b45c5a85d09459c629510f84e4}}&lt;br /&gt;
&lt;br /&gt;
==== macOS (10.13 and later) {{{5|}}} ====&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.10 | filename=Wesnoth_1.19.10.dmg |&lt;br /&gt;
hash=8b73b69f908e9c894d3229abdf5f55e40ce6aabfca5cad90a8e9e6c050e1b377}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.9 | filename=Wesnoth_1.19.9.dmg |&lt;br /&gt;
hash=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855}}&lt;br /&gt;
&lt;br /&gt;
==== Source code ====&lt;br /&gt;
* [https://github.com/wesnoth/wesnoth/blob/master/INSTALL.md Compiling Wesnoth] - How to compile the source code&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.10 | filename=wesnoth-1.19.10.tar.bz2 |&lt;br /&gt;
hash=c435d76d35bb336ad64ac80040c8b9e046571f80b51794f16a41b99b6b99e78f}}&lt;br /&gt;
* {{DownloadItem | label={{{1|Current Version}}} | group=wesnoth |&lt;br /&gt;
version=1.19.9 | filename=wesnoth-1.19.9.tar.bz2 |&lt;br /&gt;
hash=db0349490324ebd7a6f4484bbc9614dc6b046fff084e36682fcf13de9f2db3b8}}&lt;/div&gt;</summary>
		<author><name>Pentarctagon</name></author>
		
	</entry>
</feed>