Compare commits

..
122 Commits
Author SHA1 Message Date
Tyler TrahanandPeter Nelson 14ec60f248 Update: Update changelog and bump release version for 15.3 2026-04-04 16:16:04 +01:00
Peter NelsonandPeter Nelson c1ebd8b19c Update: Backport language changes 2026-04-03 22:25:50 +01:00
metablasterandPeter Nelson 31ed643942 Fix: [Script] IsBuildableRectangle for a 0x0 tile should return false (#15357) 2026-04-03 22:25:50 +01:00
Jonathan G RennisonandPeter Nelson d9e977c823 Fix: MaxReliability order condition value not being clamped to <= 100 2026-04-03 22:25:50 +01:00
Peter NelsonandPeter Nelson 65193cb050 Fix: force sprites in main menu image-text buttons to same square dimensions
Fixes appearance with original basesets
2026-04-03 22:25:50 +01:00
Peter NelsonandPeter Nelson f3c94f08b7 Fix: size toolbar buttons relative to largest toolbar icon instead of hardcoded value
This improves appearance with basesets that use a different sprite size for toolbar icons.
2026-04-03 22:25:50 +01:00
Peter NelsonandPeter Nelson 2937d4550b Codechange: call AdjustPaddingForZoom on window creation
Reduces duplication in SetMinimalSize / SetMinimalTextLines
2026-04-03 22:25:50 +01:00
Loïc GuillouxandPeter Nelson c668ed2406 Fix 4b7a324: compilation with DEBUG_DUMP_COMMANDS (#15343) 2026-04-03 22:25:50 +01:00
Loïc GuillouxandPeter Nelson f8e0a8a4eb Fix 98ac75e: non deterministic handling of train crashes (#15338) 2026-04-03 22:25:50 +01:00
Jonathan G RennisonandPeter Nelson 79bf008514 Fix #15310: Incorrect map tile indices used for aircraft outside the map
When crashing aircraft or finding hangars
2026-04-03 22:25:50 +01:00
Jonathan G RennisonandPeter Nelson b9a35ef4b4 Fix: Incorrect scroll bar capacity for train details window total cargo tab 2026-04-03 22:25:50 +01:00
Peter NelsonandPeter Nelson c91185ebd9 Doc: bump release version to 15.2 2026-02-18 18:52:10 +00:00
Peter NelsonandPeter Nelson 1d53bd037a Doc: update changelog for 15.2 2026-02-18 18:52:10 +00:00
Peter NelsonandPeter Nelson bfdbff5c6c Update: Backport language changes 2026-02-18 11:15:19 +00:00
SamuXarickandPeter Nelson cbc4b5a274 Fix 434163aa: Crashed zeppelin not blocking runway (#15281)
Turns out the block flag was in Reset mode instead of Set.
Move the Set block logic earlier to make it repeatedly set for as long as the zeppeliner exists.
2026-02-18 11:15:19 +00:00
Peter NelsonandPeter Nelson 613aba0667 Fix #15269: crash when building drive-through stop on unowned one-way road (#15270)
Allow over-building drive-through roadstops on unowned one-way roads.
2026-02-18 11:15:19 +00:00
Peter NelsonandPeter Nelson 735b3958c2 Update: Backport language changes 2026-02-12 19:58:33 +00:00
Owen RudgeandPeter Nelson fc6d0d078c Codechange: [CI] Upload to the Windows Store automatically.
Microsoft expects a .msixbundle these days, which is effectively identical to .appxbundle, but needs a newer version of Windows 10, so bump our minimum version requirement too.
2026-02-12 19:58:33 +00:00
ronvidandPeter Nelson ecb5152c01 Fix #15105: Czech townname generation causing crashes. (#15231) 2026-02-12 19:58:33 +00:00
Peter NelsonandPeter Nelson bc03ff3fa0 Fix #15247: crash when handling invalid sprite in OpenGL cursor sprite system (#15248) 2026-02-12 19:58:33 +00:00
Loïc GuillouxandPeter Nelson fb981a130f Fix #15225: [CMake] Detect mismatch between tag and internal version (#15226) 2026-02-12 19:58:33 +00:00
Peter NelsonandPeter Nelson 28b88f5002 Fix b4ac5e2231: don't compare clear density with ClearGround (#15217) 2026-02-12 19:58:33 +00:00
Peter NelsonandPeter Nelson d8b7ee2483 Fix bd57aee3a9: Town supplied history incorrectly clamped to uint16_t (#15183) 2026-02-12 19:58:33 +00:00
Peter NelsonandPeter Nelson ebec0b37a1 Fix #15085: don't perform GUI scale changes before video driver is fully initialised (#15175) 2026-02-12 19:58:33 +00:00
RubidiumandPeter Nelson ba874b69e6 Fix #15166: foundations missing adjacent to NewGRF objects without foundation 2026-02-12 19:58:33 +00:00
Jonathan G RennisonandPeter Nelson 4b90a8276d Fix: Articulated road vehicle following with immediately sequential u-turns (#15170) 2026-02-12 19:58:33 +00:00
Charles PigottandPeter Nelson 70c142c013 Add: [Fluidsynth] Read settings from config files if available 2026-02-12 17:01:52 +00:00
Peter NelsonandPeter Nelson 8c0c3256a5 Fix 39f30692fe: Badge filter toggles no longer worked. 2026-02-12 17:01:52 +00:00
Peter NelsonandGitHub 119d71ae95 Update: Changelog for 15.1 (#15164) 2026-01-24 20:26:56 +00:00
Peter NelsonandPeter Nelson 8fb4721457 Update: Backport language changes 2026-01-24 19:32:36 +00:00
175a0c4d83 Fix #15088: When building a new train, the refit button state may be incorrect. (#15162)
Invalidate vehicle view window when the vehicle chain is changed.

Co-authored-by: Abigail <abigailthomsonhicks@gmail.com>
2026-01-24 19:32:36 +00:00
Loïc GuillouxandPeter Nelson 903325e4c8 Fix #15160: Use savegame landscape to display company names in SaveLoad window (#15161) 2026-01-24 19:32:36 +00:00
Peter NelsonandPeter Nelson 3f7934604c Fix #15116: install fallback cargo translation table for old cargo sets (#15150)
Old combined cargo/industry sets may set up cargo types with labels and expect them to be usable without a translation table.

Install a fallback table if the NewGRF does not install one to give them a better chance of working.
2026-01-24 19:32:36 +00:00
Peter NelsonandPeter Nelson 5d7fddf52c Fix: Allow infinite water to be selected when loading heightmap (#15146) 2026-01-24 19:32:36 +00:00
Loïc GuillouxandPeter Nelson cae58f37b4 Fix #15153, beb213f9: Wrong tile used to get bridge reservation overlay (#15154) 2026-01-24 19:32:36 +00:00
4adacf7640 Fix 568b70e: Fjordia SlCompanyLiveries::Load crash (#15148)
Co-authored-by: qirlib <qirlib@gmail.com>
2026-01-24 19:32:36 +00:00
Peter NelsonandGitHub 62649f4a83 Update: Changelog for 15.1 (#15128) 2026-01-22 18:46:01 +00:00
Peter NelsonandPeter Nelson c57db6ecdd Update: Backport language changes 2026-01-22 18:34:49 +00:00
Peter NelsonandPeter Nelson 4fd478295b Fix 595b696d61: Tile suitability test for farm field no longer handled snow tiles. (#15134) 2026-01-22 18:34:49 +00:00
Peter NelsonandPeter Nelson 3d8826bd16 Fix #15131, 3cf9b15959: Trees no longer spread on partially snowy tiles. (#15133) 2026-01-22 18:34:49 +00:00
Peter NelsonandPeter Nelson 175334b587 Update: Backport language changes 2026-01-18 19:30:43 +00:00
Richard WheelerandPeter Nelson 2ec7382f5c Fix: Change tooltips to match change from checkboxes to switches (#15123) 2026-01-18 19:30:43 +00:00
AbigailandPeter Nelson eec49bc795 Fix #15069: World generation map edges GUI starts in an invalid state (#15082) 2026-01-18 19:30:43 +00:00
Peter NelsonandPeter Nelson e52b3e161f Update: Backport language changes 2026-01-17 10:30:36 +00:00
Peter NelsonandPeter Nelson fb56c25d2c Fix: [Script] Potential out of bounds array/string slice indexes. 2026-01-17 10:30:36 +00:00
Peter NelsonandPeter Nelson a80c9325b2 Fix: [Script] Potential out of bounds indexed string access. 2026-01-17 10:30:36 +00:00
Peter NelsonandPeter Nelson 632b038933 Fix: [Script] Check if array sort function modified array.
Do not allow a script to add or remove elements.
2026-01-17 10:30:36 +00:00
Loïc GuillouxandPeter Nelson 6cab2e1ff8 Codefix 701cb2e: Incorrect initialisation of treat_first_red_two_way_signal_as_eol (#15109) 2026-01-17 10:30:36 +00:00
Cyprian KlimaszewskiandPeter Nelson 08503470cb Codefix: Remove unnecessary client side checks for setting an unbunch order (#15107) 2026-01-17 10:30:36 +00:00
Owen RudgeandPeter Nelson fe2c7c130f Fix: [CI] Use the latest version of GOGGalaxyPipelineBuilder to upload releases to GOG 2026-01-17 10:30:36 +00:00
Peter NelsonandPeter Nelson 0d3960148e Fix #15079: Incorrect dates shown on town cargo history graph. (#15080) 2026-01-17 10:30:36 +00:00
Peter NelsonandPeter Nelson 3c683c8303 Fix #15067: Mark NewGRF settings as modified after moving by drag & drop. (#15068) 2026-01-17 10:30:36 +00:00
Cyprian KlimaszewskiandPeter Nelson 69ef22674a Fix 0b99a0b: Incorrect error message for aqueducts reaching northern map borders (#14974) 2026-01-17 10:30:36 +00:00
Tyler TrahanandPeter Nelson d859130613 Fix: Standardize wording of GRF/NewGRF (#15059) 2026-01-17 10:30:36 +00:00
Charles PigottandPeter Nelson 89cdc726c8 Fix: [Fluidsynth] Don't try to load the default soundfont if it's not set or doesn't exist 2026-01-17 10:30:36 +00:00
Peter NelsonandPeter Nelson 1185f74588 Fix #15046: Crash on loading game due to invalid group parents. (#15049)
A bug when deleting groups could leave the group hierarchy in an invalid state.
2026-01-17 10:30:36 +00:00
Jonathan G RennisonandPeter Nelson ec0232ce11 Fix: disable_elrails handling with engines that use both RAIL and ELRL (#15045) 2026-01-17 10:30:36 +00:00
Peter NelsonandPeter Nelson a39c836fd1 Fix #15039: Name and version can disappear from content list. (#15040)
If the small font is set larger than the normal font, both name and version text disappeared.

Take account of the height of the small font when setting the resize height.
2026-01-17 10:30:36 +00:00
Tyler TrahanandPeter Nelson a5c36fa01b Fix #15026: Remove incorrect info from base sounds tooltip (#15029) 2026-01-17 10:30:36 +00:00
Loïc GuillouxandPeter Nelson a64ffbc5ca Fix: [Script] Improve reporting of invalid GetAPIVersion return (#15015) 2026-01-17 10:30:36 +00:00
SamuXarickandLoïc Guilloux 753f7e769a Fix: [Script] Retarget iterators on list swap (#14805)
Fix script list sorter to correctly retarget iterator when swapping lists.
Each sorter implementation now updates its internal iterator to remain valid after attaching to a new list, avoiding undefined behaviour.
2026-01-12 18:50:51 +01:00
RubidiumandLoïc Guilloux 6f735d73ab Codechange: [Script] Simplify constructors and add constness 2026-01-12 18:50:51 +01:00
RubidiumandLoïc Guilloux e21632ec24 Codechange: [Script] Move identical code from sub class to super class 2026-01-12 18:50:51 +01:00
Loïc Guilloux 252547ff8b Codechange: [Script] Reuse memory when changing values of ScriptList items (#14966) 2026-01-12 18:50:51 +01:00
Loïc Guilloux 64e01c7c8b Codechange: [Script] Replace map of sets with set of pairs for per value storage (#14930) 2026-01-12 18:50:51 +01:00
Tyler TrahanandGitHub 30cc053596 Update: Changelog for 15.0 (#15005) 2026-01-01 17:05:18 +00:00
Charles Pigott 4f794f0cb5 Update: Backport language changes 2026-01-01 17:03:56 +00:00
Peter NelsonandCharles Pigott 2b8b882fc3 Fix #14982: Can't place buoys under bridges. (#15007)
Bridges can be built over buoys but not the other way around.
2026-01-01 17:03:56 +00:00
Jonathan G RennisonandCharles Pigott 347295c319 Fix b4ac5e22: Incorrect TileIndex used in TownCanBePlacedHere (#15002) 2026-01-01 17:03:56 +00:00
Charles Pigott b2d9036fdb Fix: Small ufos would loop over vehicles in depots forever (#15008)
* Codechange: Rename variables to be more meaningful

* Fix: Small ufos would loop over vehicles in depots forever
2026-01-01 17:03:56 +00:00
Charles Pigott 98131fdff3 Fix #15004: Crash when dropdown is open when end game screen appears (#15006) 2026-01-01 17:03:56 +00:00
Tyler TrahanandCharles Pigott 07032d1af3 Fix #14992, 046b0c6: Respect non-stop order setting when adding waypoint orders (#14993) 2026-01-01 17:03:56 +00:00
Tyler TrahanandCharles Pigott 7f2e4257a3 Fix: Use correct 'minutes per year' setting for old savegames (#14995) 2026-01-01 17:03:56 +00:00
Loïc GuillouxandCharles Pigott bd9e7898a4 Fix: potential division by 0 when drawing a line (#14994) 2026-01-01 17:03:56 +00:00
Michael LutzandGitHub 20477ff541 Codechange: Disable asserts for release (#14883) 2025-12-31 22:31:24 +00:00
Tyler TrahanandGitHub 530546b8ca Update: Changelog for 15.0-RC4 (#14970) 2025-12-26 13:01:20 -05:00
Peter NelsonandPeter Nelson d79edfd974 Update: Backport language changes 2025-12-26 16:41:11 +00:00
Peter NelsonandPeter Nelson ddd4afd8ec Fix: Update language files for changes to English strings. 2025-12-26 16:41:11 +00:00
Peter NelsonandPeter Nelson 6e48325661 Fix f34c45c36d: Incorrect colour in cargo list in fund industry window. 2025-12-26 16:41:11 +00:00
Peter NelsonandPeter Nelson 2f2d6a419f Fix 8a8ebabb9d: Don't draw bridge deck rail sprites for default bridges. (#14985)
Bridge deck sprites for default rail/road types should only be drawn for custom bridges.
2025-12-26 16:41:11 +00:00
Jonathan G RennisonandPeter Nelson 7e30849c1e Fix b956af63: Incorrect TileIndex used in FindNearestGoodCoastalTownSpot (#14988) 2025-12-26 16:41:11 +00:00
Jonathan G RennisonandPeter Nelson 09240d8c22 Fix #12465: Click/tooltip alignment of industry chain cargo lines (#14963) 2025-12-26 16:41:11 +00:00
Peter NelsonandPeter Nelson 4b5b20a167 Fix 2d7d085e8e: "(Invalid parameter)" in error message when trying to remove another player's object. (#14981)
Formatted error string was thrown away.
2025-12-26 16:41:11 +00:00
Peter NelsonandPeter Nelson ac3ce09dd2 Fix #14978: Don't clear water tiles after removing buoys. (#14980)
Buoys have no owner and can be cleared by anyone, but the underlying tile (e.g. canal) should not be cleared if has a different owner.
2025-12-26 16:41:11 +00:00
Peter NelsonandPeter Nelson 448f322bd6 Fix: Update language files for changes to English strings. 2025-12-26 16:41:11 +00:00
Peter NelsonandPeter Nelson 7348c89fb3 Fix f34c45c36d: Incorrect string colour in industry directory. 2025-12-26 16:41:11 +00:00
Peter NelsonandPeter Nelson 81cb7fcd53 Fix #14973: Incorrect colour for some composed strings. 2025-12-26 16:41:11 +00:00
Peter NelsonandPeter Nelson 0755317f4d Fix c213218b66: Don't highlight selected dropdown item if it has a click result.
This is used by toggles and buttons within the dropdown item, and using those should not cause the row to look selected.
2025-12-26 16:41:11 +00:00
Peter NelsonandPeter Nelson f4dd4e455d Update: Backport language changes 2025-12-24 19:22:11 +00:00
Tyler TrahanandPeter Nelson 95ec0d2244 Fix #14938: Don't allow cacti to die off (#14956) 2025-12-24 19:22:11 +00:00
RubidiumandPeter Nelson 5434715724 Codefix: add missing tracing debug messages for Coordinator/Stun/Turn 2025-12-24 19:22:11 +00:00
Cyprian KlimaszewskiandPeter Nelson ecd95d332c Fix cb1c240: Client list is not invalidated after company take over. (#14955) 2025-12-24 19:22:11 +00:00
Jonathan G RennisonandPeter Nelson 5854536b89 Fix #14951: Init and save/load TimerGameEconomy::days_since_last_month (#14962) 2025-12-24 19:22:11 +00:00
Loïc GuillouxandPeter Nelson 0858148c94 Fix #14958, e96f35c: Don't use not yet initialised member (#14959) 2025-12-24 19:22:11 +00:00
glx22andPeter Nelson 92ef1697ec Fix #14949, 0717746: Add the new callbacks to the callback table 2025-12-24 19:22:11 +00:00
glx22andPeter Nelson a7961b41cb Codechange: Check command callbacks registration even in single player 2025-12-24 19:22:11 +00:00
Peter NelsonandPeter Nelson e7ba18bfd9 Fix #14945: Hang when deleting implicit orders during vehicle loading. (#14946) 2025-12-24 19:22:11 +00:00
Tyler TrahanandGitHub 6338c487b8 Update: Changelog for 15.0-RC3 (#14940) 2025-12-20 14:10:15 -05:00
Peter NelsonandPeter Nelson 4c0a91aac2 Update: Backport language changes 2025-12-20 19:07:50 +00:00
Peter NelsonandPeter Nelson d04225a2fb Change: Automatically push/pop colours when formatting a sub-string. (#14006)
Reverts 226a44bf86.

This universally prevents the sub-string from changing colours in the outer string.
2025-12-20 19:07:50 +00:00
Peter NelsonandPeter Nelson 65902d4abe Fix #14932: Increase internal badge index size to avoid overflowing BadgeIDs. (#14933) 2025-12-20 19:07:50 +00:00
mmtunligitandPeter Nelson 27fbcb3cc5 Fix a41738e: Picker item recolour depends on gamemode (#14929) 2025-12-20 19:07:50 +00:00
Peter NelsonandPeter Nelson 8c6531f297 Fix #14921: Crash during station autorefit if station doesn't accept current cargo type. (#14924)
Add convenience helpers to correctly retrieve goods entry cargo available/totals.

Avoids having to check if cargo data is available before accessing it, which was missing for autorefit.
2025-12-20 19:07:50 +00:00
Peter NelsonandPeter Nelson 88a52b60f8 Fix #14917: Crash when opening house picker with no houses available. (#14920) 2025-12-20 19:07:50 +00:00
Peter NelsonandPeter Nelson aa4b5ca747 Fix #14916: Duration of error message window could be too short. (#14919)
The timer for automatically closing the error message was started when creating the window, instead of when first displaying the window.
2025-12-20 19:07:50 +00:00
Peter NelsonandPeter Nelson 5ce9c6cadd Fix #14915: Crash due to divide-by-zero of industry probabilities. (#14918) 2025-12-20 19:07:50 +00:00
Loïc GuillouxandPeter Nelson 2027912e8f Fix ff08a22: script configs were cleared by AIPL and GSDT chunks from intro game (#14910) 2025-12-20 19:07:50 +00:00
RubidiumandPeter Nelson dd835262ed Codefix: possible null pointer dereference 2025-12-20 19:07:50 +00:00
Rubidiumandrubidium42 24364c3fbc Doc: not much is going to change in the 15.0 script APIs 2025-12-14 17:57:36 +01:00
Peter NelsonandPeter Nelson ca42564da8 Update: Changelog for 15.0-RC2 2025-12-13 18:13:31 +00:00
Peter NelsonandPeter Nelson 9062d25456 Update: Backport language changes 2025-12-13 11:54:27 +00:00
RubidiumandPeter Nelson 4213c62edd Fix #14677: desync due to using newgame time settings to validate savegame time settings 2025-12-13 11:54:27 +00:00
Peter NelsonandPeter Nelson a97587b3fe Revert: "Change: Support side-by-side fallback FontCaches instead of hierarchical. (#13303)"
This reverts commit 1829f7926d.
2025-12-13 11:54:27 +00:00
Peter NelsonandPeter Nelson 8ac9762a84 Revert: "Add: Automatically load fonts for missing glyphs. (#14856)"
This reverts commit c1d37d8699.
2025-12-13 11:54:27 +00:00
Peter NelsonandPeter Nelson 4ad85e0fe6 Fix: Graph label allocated size could be too small. (#14901)
Set initial size based on what could be displayed, instead of what is displayed right now.
2025-12-13 11:54:27 +00:00
Loïc GuillouxandPeter Nelson ab1ae7ec1a Codechange: [CI] setup-vcpkg action is now in OpenTTD/actions (#14897) 2025-12-13 11:54:27 +00:00
Peter NelsonandPeter Nelson 84c3ac6852 Fix #14891, a8650c6b06: Minimum sprite zoomlevel could break in some cases. (#14894)
Caused by sprite control flags not being reset when scanning available sprites.
2025-12-13 11:54:27 +00:00
Peter NelsonandPeter Nelson a6994a9550 Fix #14889: [FluidSynth] Don't try to load a soundfont that doesn't exist. 2025-12-13 11:54:27 +00:00
Peter NelsonandPeter Nelson f22f9d8b18 Codechange: Auto-reformat fluidsynth.cpp. 2025-12-13 11:54:27 +00:00
Peter NelsonandPeter Nelson 4b701e053f Update: Backport language changes 2025-12-08 18:06:36 +00:00
Loïc GuillouxandPeter Nelson b575769a7f Fix: [CI] Install NSIS for windows releases (#14885) 2025-12-08 18:06:36 +00:00
Rubidiumandrubidium42 04f1a114dd Change #14155: Erato's the winner of the title game competition 2025-12-07 22:40:14 +01:00
1208 changed files with 50895 additions and 65188 deletions
-85
View File
@@ -1,85 +0,0 @@
"""
Script to scan the OpenTTD source-tree for doxygen @file annotations.
Checks whether they exist, are recognised by doxygen and match coding style.
"""
import os
import sys
END_OF_SENTENCE = [".", "!", "?"]
SOURCE_FILE_EXTENSION = ["cpp", "c", "hpp", "h", "mm", "m", "cc"]
TEMPLATE_FILE_EXTENSION = ["preamble", "in"]
REPO_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
EXCLUDED_FILES = [
os.path.join(REPO_DIR, "src", "script", "api", "squirrel_export.sq.hpp.in"),
os.path.join(REPO_DIR, "src", "script", "api", "script_includes.hpp.in"),
]
def read_files_list_from_file(file_path):
with open(file_path, "r") as f:
while line := f.readline():
yield line[:-1]
def list_files_walk(start_path="."):
for root, dirs, files in os.walk(start_path):
for file in files:
yield os.path.join(root, file)
def check_descriptions(files):
errors = []
for path in files:
if os.path.abspath(path) in EXCLUDED_FILES:
continue
if path.find("3rdparty") != -1 or path.find("lang") != -1:
continue
if not os.path.isfile(path):
continue
name = path[path.rfind("/") + 1 :]
while True:
extension = name[name.rfind('.') + 1 :]
if extension not in TEMPLATE_FILE_EXTENSION:
break
name = name[0 : -len(extension) - 1]
if extension not in SOURCE_FILE_EXTENSION:
continue
with open(path, "r") as f:
content = f.read()
ann = content.find(f"@file {name} ")
reason = f'Should be of the form "/** @file {name} Brief description of the file here. */"'
if ann == -1:
if content.find("@file") == -1:
errors.append(f'File "{path}" does not provide description. {reason}')
continue
else:
end = content.find("\n", ann)
start = content.rfind("\n", 0, ann) + 1
if content[start : ann] == "/** " and content[end - 3 : end] == " */" and content[end - 4] in END_OF_SENTENCE:
continue
elif content[start : ann] == " * ":
if content[start - 4 : start - 1] == "/**" and content[end - 1] in END_OF_SENTENCE and content[end + 1 : end + 4] != " */":
continue
reason = f"Should be of the form:\n/**\n * @file {name} Brief description of the file here.\n * Detailed description of the file here.\n */"
errors.append(f'Description of file "{path}" does not match coding style. {reason}')
return errors
def main():
if len(sys.argv) == 1:
files = list_files_walk(os.path.join(REPO_DIR, "src"))
else:
files = read_files_list_from_file(sys.argv[1])
errors = check_descriptions(files)
if errors:
print("\n".join(errors))
sys.exit(1)
print("OK")
if __name__ == "__main__":
main()
-26
View File
@@ -1,26 +0,0 @@
name: Install Doxygen
runs:
using: composite
steps:
- name: Install Doxygen
run: |
echo "::group::Downloading"
# Download currently (at the time of creation this action) latest version of Doxygen
# because version in ubuntu repository (1.9.8) is outdated and buggy.
wget -O doxygen.tar.gz "https://github.com/doxygen/doxygen/releases/download/Release_1_17_0/doxygen-1.17.0.linux.bin.tar.gz"
echo "::endgroup::"
echo "::group::Unpacking"
tar -xzf doxygen.tar.gz
rm doxygen.tar.gz
echo "::endgroup::"
echo "::group::Installing"
cd doxygen*
sudo make install
echo "::endgroup::"
cd ..
rm -r doxygen*
shell: bash
-28
View File
@@ -1,28 +0,0 @@
""" Script that sorts warnings generated by doxygen to maintain consistent order. """
import sys
def read_by_line(file_path):
with open(file_path, "r") as f:
while line := f.readline():
yield line[:-1]
def main():
if len(sys.argv) != 3:
print("Wrong number of arguments provided, expected two.")
print("Usage: python3 sort_doxygen_warnings.py [input_file] [output_file]")
sys.exit(1)
warnings = []
for line in read_by_line(sys.argv[1]):
if "warning:" in line or "error:" in line:
warnings.append(line)
continue
# Doxygen warnings can span multiple lines, keep these lines together.
warnings[-1] = f"{warnings[-1]}\n{line}"
warnings = sorted(set(warnings))
with open(sys.argv[2], "w") as out:
out.write("\n".join(warnings))
out.write("\n")
print("Doxygen warnings sorted successfully.")
if __name__ == "__main__":
main()
+1 -1
View File
@@ -105,4 +105,4 @@ jobs:
steps:
- name: Check annotations
uses: OpenTTD/actions/annotation-check@v7
uses: OpenTTD/actions/annotation-check@v6
+11 -4
View File
@@ -14,23 +14,30 @@ jobs:
container:
# If you change this version, change the numbers in the cache step,
# .github/workflows/preview-build.yml (2x) and os/emscripten/Dockerfile too.
image: emscripten/emsdk:6.0.1
image: emscripten/emsdk:3.1.57
steps:
- name: Checkout
uses: actions/checkout@v7
uses: actions/checkout@v6
- name: Fix dubious ownership
run: |
git config --global --add safe.directory ${GITHUB_WORKSPACE}
- name: Update to modern GCC
run: |
apt-get update
apt-get install -y gcc-12 g++-12
update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-12 100
update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-12 100
- name: Setup cache
uses: actions/cache@v6
uses: actions/cache@v4
with:
# If you change this version, change the numbers in the image configuration step,
# .github/workflows/preview-build.yml (2x) and os/emscripten/Dockerfile too.
path: /emsdk/upstream/emscripten/cache
key: 6.0.1-${{ runner.os }}
key: 3.1.57-${{ runner.os }}
- name: Add liblzma support
run: |
+3 -4
View File
@@ -23,18 +23,18 @@ jobs:
linux:
name: CI
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
env:
CC: ${{ inputs.compiler }}
CXX: ${{ inputs.cxxcompiler }}
steps:
- name: Checkout
uses: actions/checkout@v7
uses: actions/checkout@v6
- name: Setup vcpkg
id: vcpkg
uses: OpenTTD/actions/setup-vcpkg@v7
uses: OpenTTD/actions/setup-vcpkg@v6
- name: Install dependencies
run: |
@@ -54,7 +54,6 @@ jobs:
libogg-dev \
libopus-dev \
libopusfile-dev \
libsoxr-dev \
${{ inputs.libraries }} \
zlib1g-dev \
# EOF
+2 -2
View File
@@ -32,11 +32,11 @@ jobs:
xcode-version: latest-stable
- name: Checkout
uses: actions/checkout@v7
uses: actions/checkout@v6
- name: Setup vcpkg
id: vcpkg
uses: OpenTTD/actions/setup-vcpkg@v7
uses: OpenTTD/actions/setup-vcpkg@v6
- name: Install OpenGFX
run: |
+10 -12
View File
@@ -21,7 +21,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v7
uses: actions/checkout@v6
- name: Setup MSYS2
uses: msys2/setup-msys2@v2
@@ -31,17 +31,15 @@ jobs:
install: >-
git
make
pacboy: >-
cmake:p
gcc:p
lzo2:p
libpng:p
lld:p
ninja:p
libogg:p
opus:p
opusfile:p
libsoxr:p
mingw-w64-${{ inputs.arch }}-cmake
mingw-w64-${{ inputs.arch }}-gcc
mingw-w64-${{ inputs.arch }}-lzo2
mingw-w64-${{ inputs.arch }}-libpng
mingw-w64-${{ inputs.arch }}-lld
mingw-w64-${{ inputs.arch }}-ninja
mingw-w64-${{ inputs.arch }}-libogg
mingw-w64-${{ inputs.arch }}-opus
mingw-w64-${{ inputs.arch }}-opusfile
- name: Install OpenGFX
shell: bash
+4 -2
View File
@@ -31,8 +31,10 @@ jobs:
fail-fast: false
matrix:
include:
- msystem: UCRT64
- msystem: MINGW64
arch: x86_64
- msystem: MINGW32
arch: i686
name: MinGW (${{ matrix.arch }})
@@ -55,4 +57,4 @@ jobs:
steps:
- name: Check annotations
uses: OpenTTD/actions/annotation-check@v7
uses: OpenTTD/actions/annotation-check@v6
+2 -2
View File
@@ -18,11 +18,11 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v7
uses: actions/checkout@v6
- name: Setup vcpkg
id: vcpkg
uses: OpenTTD/actions/setup-vcpkg@v7
uses: OpenTTD/actions/setup-vcpkg@v6
- name: Install OpenGFX
shell: bash
+5 -6
View File
@@ -25,11 +25,11 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v7
uses: actions/checkout@v6
- name: Setup vcpkg
id: vcpkg
uses: OpenTTD/actions/setup-vcpkg@v7
uses: OpenTTD/actions/setup-vcpkg@v6
- name: Install dependencies
run: |
@@ -49,7 +49,6 @@ jobs:
libopus-dev \
libopusfile-dev \
libsdl2-dev \
libsoxr-dev \
zlib1g-dev \
# EOF
@@ -76,7 +75,7 @@ jobs:
echo "::endgroup::"
- name: Initialize CodeQL
uses: github/codeql-action/init@v4.37.9
uses: github/codeql-action/init@v4
with:
languages: cpp
config-file: ./.github/codeql/codeql-config.yml
@@ -92,7 +91,7 @@ jobs:
echo "::endgroup::"
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v4.37.9
uses: github/codeql-action/analyze@v4
with:
category: /language:cpp
upload: False
@@ -110,6 +109,6 @@ jobs:
output: sarif-results/cpp.sarif
- name: Upload results
uses: github/codeql-action/upload-sarif@v4.37.9
uses: github/codeql-action/upload-sarif@v4
with:
sarif_file: sarif-results/cpp.sarif
+2 -2
View File
@@ -14,12 +14,12 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v7
uses: actions/checkout@v6
with:
fetch-depth: 4
- name: Get pull-request commits
uses: OpenTTD/actions/checkout-pull-request@v7
uses: OpenTTD/actions/checkout-pull-request@v6
- name: Check commits
uses: OpenTTD/OpenTTD-git-hooks@main
-88
View File
@@ -1,88 +0,0 @@
name: Docs checker
on:
pull_request:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
jobs:
docs-checker:
name: New doxygen warnings checker
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v7
with:
fetch-depth: 4
- name: Get pull-request commits
uses: OpenTTD/actions/checkout-pull-request@v7
- name: Install Doxygen
uses: ./.github/install-doxygen
- name: Build docs for PR
run: |
mkdir build
echo "::group::CMake"
cmake -S . -B build -DOPTION_DOCS_ONLY=ON -DOPTION_LINE_IN_DOXYGEN_WARNINGS=OFF -DOPTION_DOXYGEN_GS_WARN_FILE="Warnings.GS" -DOPTION_DOXYGEN_AI_WARN_FILE="Warnings.AI" -DOPTION_DOXYGEN_WARN_FILE="Warnings.source"
echo "::endgroup::"
echo "::group::Build Source"
cmake --build build --target docs_source
python3 .github/sort_doxygen_warnings.py build/Warnings.source doxygen_warnings.PR
echo "::endgroup::"
echo "::group::Build AI"
cmake --build build --target docs_ai
python3 .github/sort_doxygen_warnings.py build/Warnings.AI doxygen_AI_warnings.PR
echo "::endgroup::"
echo "::group::Build GS"
cmake --build build --target docs_game
python3 .github/sort_doxygen_warnings.py build/Warnings.GS doxygen_GS_warnings.PR
echo "::endgroup::"
rm -r build
- name: Build docs for base branch
run: |
git checkout HEAD^
mkdir build
echo "::group::CMake"
cmake -S . -B build -DOPTION_DOCS_ONLY=ON -DOPTION_LINE_IN_DOXYGEN_WARNINGS=OFF -DOPTION_DOXYGEN_GS_WARN_FILE="Warnings.GS" -DOPTION_DOXYGEN_AI_WARN_FILE="Warnings.AI" -DOPTION_DOXYGEN_WARN_FILE="Warnings.source"
echo "::endgroup::"
echo "::group::Build Source"
cmake --build build --target docs_source
python3 .github/sort_doxygen_warnings.py build/Warnings.source doxygen_warnings.base
echo "::endgroup::"
echo "::group::Build AI"
cmake --build build --target docs_ai
python3 .github/sort_doxygen_warnings.py build/Warnings.AI doxygen_AI_warnings.base
echo "::endgroup::"
echo "::group::Build GS"
cmake --build build --target docs_game
python3 .github/sort_doxygen_warnings.py build/Warnings.GS doxygen_GS_warnings.base
echo "::endgroup::"
rm -r build
- name: Compare doxygen warnings and errors
run: |
unset FAIL
diff doxygen_warnings.base doxygen_warnings.PR | grep '^>' && FAIL=1
diff doxygen_AI_warnings.base doxygen_AI_warnings.PR | grep '^>' && FAIL=1
diff doxygen_GS_warnings.base doxygen_GS_warnings.PR | grep '^>' && FAIL=1
if [ $FAIL ]; then
exit 1;
fi
-29
View File
@@ -1,29 +0,0 @@
name: File descriptions
on:
pull_request:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
jobs:
file-descriptions:
name: File descriptions
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v7
with:
fetch-depth: 4
- name: Get pull-request commits
uses: OpenTTD/actions/checkout-pull-request@v7
- name: Check descriptions of source files
run: |
git diff-tree --no-commit-id --name-only -r HEAD HEAD^ > modified_files.txt
cat modified_files.txt
set -ex
python3 .github/file-descriptions.py modified_files.txt
+33 -13
View File
@@ -2,20 +2,31 @@ name: Preview build
on:
workflow_call:
secrets:
PREVIEW_CLOUDFLARE_API_TOKEN:
description: API token to upload a preview to Cloudflare Pages
required: true
PREVIEW_CLOUDFLARE_ACCOUNT_ID:
description: Account ID to upload a preview to Cloudflare Pages
required: true
jobs:
preview:
name: Build preview
environment:
name: preview
url: https://preview.openttd.org/pr${{ github.event.pull_request.number }}/
runs-on: ubuntu-latest
container:
# If you change this version, change the numbers in the cache step,
# .github/workflows/ci-emscripten.yml (2x) and os/emscripten/Dockerfile too.
image: emscripten/emsdk:6.0.1
image: emscripten/emsdk:3.1.57
steps:
- name: Checkout
uses: actions/checkout@v7
uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.sha }}
@@ -24,13 +35,20 @@ jobs:
git config --global --add safe.directory ${GITHUB_WORKSPACE}
git checkout -b pr${{ github.event.pull_request.number }}
- name: Update to modern GCC
run: |
apt-get update
apt-get install -y gcc-12 g++-12
update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-12 100
update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-12 100
- name: Setup cache
uses: actions/cache@v6
uses: actions/cache@v4
with:
path: /emsdk/upstream/emscripten/cache
# If you change this version, change the numbers in the image configuration step,
# .github/workflows/ci-emscripten.yml (2x) and os/emscripten/Dockerfile too.
key: 6.0.1-${{ runner.os }}
key: 3.1.57-${{ runner.os }}
- name: Add liblzma support
run: |
@@ -79,14 +97,16 @@ jobs:
cp build/openttd.js public/
cp build/openttd.wasm public/
mkdir pr
echo ${{ github.event.pull_request.number }} > ./pr/number
# Ensure we use the latest version of npm; the one we get with current
# emscripten doesn't allow running "npx wrangler" as root.
# Current emscripten can't install npm>=10.0.0 because node is too old.
npm install -g npm@9
- name: Upload artifacts
uses: actions/upload-artifact@v7
- name: Publish preview
uses: cloudflare/pages-action@v1
with:
name: pr${{ github.event.pull_request.number }}
path: |
public
pr
retention-days: 1
apiToken: ${{ secrets.PREVIEW_CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.PREVIEW_CLOUDFLARE_ACCOUNT_ID }}
projectName: ${{ vars.PREVIEW_CLOUDFLARE_PROJECT_NAME }}
directory: public
branch: pr${{ github.event.pull_request.number }}
-59
View File
@@ -1,59 +0,0 @@
name: Preview publish
on:
workflow_run:
workflows:
- Preview
types:
- completed
jobs:
preview:
name: Publish preview
runs-on: ubuntu-latest
if: >
github.event.workflow_run.event == 'pull_request' &&
github.event.workflow_run.conclusion == 'success'
steps:
- name: Create deployment
id: deployment
run: |
curl -L \
-X POST \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
-H "X-GitHub-Api-Version: 2026-03-10" \
https://api.github.com/repos/${{ github.repository }}/deployments \
-d '{"ref":"${{ github.event.workflow_run.head_sha }}","environment":"preview","required_contexts":[]}' \
| jq --raw-output0 '"url=\(.statuses_url)"' >> $GITHUB_OUTPUT
- name: Download artifacts
uses: actions/download-artifact@v8
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
run-id: ${{github.event.workflow_run.id }}
- name: Get PR number
id: pr
run: |
echo "number=$(cat pr/number)" >> $GITHUB_OUTPUT
- name: Publish preview
uses: cloudflare/wrangler-action@v4
with:
apiToken: ${{ secrets.PREVIEW_CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.PREVIEW_CLOUDFLARE_ACCOUNT_ID }}
command: pages deploy public --project-name=${{ vars.PREVIEW_CLOUDFLARE_PROJECT_NAME }} --branch pr${{ steps.pr.outputs.number }}
- name: Update deployment
if: always()
run: |
curl -L \
-X POST \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
-H "X-GitHub-Api-Version: 2026-03-10" \
${{ steps.deployment.outputs.url }} \
-d '{"state":"${{ job.status }}","log_url":"${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}","environment_url":"https://preview.openttd.org/pr${{ steps.pr.outputs.number }}/","auto_inactive":false}'
+1 -1
View File
@@ -1,7 +1,7 @@
name: Preview
on:
pull_request:
pull_request_target:
types:
- labeled
- synchronize
+15 -4
View File
@@ -15,7 +15,7 @@ jobs:
steps:
- name: Download source
uses: actions/download-artifact@v8
uses: actions/download-artifact@v6
with:
name: internal-source
@@ -23,8 +23,19 @@ jobs:
run: |
tar -xf source.tar.gz --strip-components=1
- name: Install Doxygen
uses: ./.github/install-doxygen
- name: Install dependencies
run: |
echo "::group::Update apt"
sudo apt-get update
echo "::endgroup::"
echo "::group::Install dependencies"
sudo apt-get install -y --no-install-recommends \
doxygen \
# EOF
echo "::endgroup::"
env:
DEBIAN_FRONTEND: noninteractive
- name: Build
run: |
@@ -67,7 +78,7 @@ jobs:
echo "::endgroup::"
- name: Store bundles
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@v5
with:
name: openttd-docs
path: build/bundles/*.tar.xz
+4 -7
View File
@@ -21,7 +21,7 @@ jobs:
steps:
- name: Download source
uses: actions/download-artifact@v8
uses: actions/download-artifact@v6
with:
name: internal-source
@@ -40,11 +40,9 @@ jobs:
echo "::group::Install system dependencies"
# perl-IPC-Cmd, wget, and zip are needed to run vcpkg.
# autoconf-archive is needed to build ICU.
# perl-Time-Piece is needed to build OpenSSL.
yum install -y \
autoconf-archive \
perl-IPC-Cmd \
perl-Time-Piece \
wget \
zip \
# EOF
@@ -83,7 +81,6 @@ jobs:
yum install -y \
alsa-lib-devel \
pulseaudio-libs-devel \
pipewire-devel \
# EOF
echo "::endgroup::"
@@ -114,7 +111,7 @@ jobs:
- name: Setup vcpkg
id: vcpkg
uses: OpenTTD/actions/setup-vcpkg@v7
uses: OpenTTD/actions/setup-vcpkg@v6
with:
vcpkg-location: /vcpkg
mono-install-command: 'yum install -y mono-complete'
@@ -160,14 +157,14 @@ jobs:
echo "::endgroup::"
- name: Store bundles
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@v5
with:
name: openttd-linux-generic
path: build/bundles
retention-days: 5
- name: Store symbols
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@v5
with:
name: symbols-linux-generic
path: build/symbols
+5 -5
View File
@@ -23,7 +23,7 @@ jobs:
xcode-version: latest-stable
- name: Download source
uses: actions/download-artifact@v8
uses: actions/download-artifact@v6
with:
name: internal-source
@@ -39,7 +39,7 @@ jobs:
- name: Setup vcpkg
id: vcpkg
uses: OpenTTD/actions/setup-vcpkg@v7
uses: OpenTTD/actions/setup-vcpkg@v6
- name: Install dependencies
env:
@@ -77,7 +77,7 @@ jobs:
echo "::endgroup::"
- name: Import code signing certificates
uses: Apple-Actions/import-codesign-certs@v7
uses: Apple-Actions/import-codesign-certs@v5
with:
# The certificates in a PKCS12 file encoded as a base64 string
p12-file-base64: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_P12_BASE64 }}
@@ -203,14 +203,14 @@ jobs:
mv _CPack_Packages/*/Bundle/openttd-*.zip bundles/
- name: Store bundles
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@v5
with:
name: openttd-macos-universal
path: build-x64/bundles
retention-days: 5
- name: Store symbols
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@v5
with:
name: symbols-macos-universal
path: build-x64/symbols
+5 -5
View File
@@ -30,14 +30,14 @@ jobs:
steps:
- name: Checkout (Release)
if: github.event_name == 'release'
uses: actions/checkout@v7
uses: actions/checkout@v6
with:
# We generate a changelog; for this we need the full git log.
fetch-depth: 0
- name: Checkout (Manual)
if: github.event_name == 'workflow_dispatch'
uses: actions/checkout@v7
uses: actions/checkout@v6
with:
ref: ${{ github.event.inputs.ref }}
# We generate a changelog; for this we need the full git log.
@@ -45,7 +45,7 @@ jobs:
- name: Checkout (Trigger)
if: github.event_name == 'repository_dispatch'
uses: actions/checkout@v7
uses: actions/checkout@v6
with:
ref: ${{ github.event.client_payload.ref }}
# We generate a changelog; for this we need the full git log.
@@ -202,14 +202,14 @@ jobs:
echo "::endgroup::"
- name: Store bundles
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@v5
with:
name: openttd-source
path: build/bundles/*
retention-days: 5
- name: Store source (for other jobs)
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@v5
with:
name: internal-source
path: source.tar.gz
+5 -5
View File
@@ -15,7 +15,7 @@ jobs:
steps:
- name: Download source
uses: actions/download-artifact@v8
uses: actions/download-artifact@v6
with:
name: internal-source
@@ -25,17 +25,17 @@ jobs:
tar -xf source.tar.gz --strip-components=1
- name: Download x86 build
uses: actions/download-artifact@v8
uses: actions/download-artifact@v6
with:
name: openttd-windows-x86
- name: Download x64 build
uses: actions/download-artifact@v8
uses: actions/download-artifact@v6
with:
name: openttd-windows-x64
- name: Download arm64 build
uses: actions/download-artifact@v8
uses: actions/download-artifact@v6
with:
name: openttd-windows-arm64
@@ -185,7 +185,7 @@ jobs:
move output\OpenTTD.msixbundle bundles\internal\openttd-${{ inputs.version }}-windows-store.msixbundle
- name: Store bundles
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@v5
with:
name: openttd-windows-store
path: builds/bundles
+4 -4
View File
@@ -30,7 +30,7 @@ jobs:
steps:
- name: Download source
uses: actions/download-artifact@v8
uses: actions/download-artifact@v6
with:
name: internal-source
@@ -47,7 +47,7 @@ jobs:
- name: Setup vcpkg
id: vcpkg
uses: OpenTTD/actions/setup-vcpkg@v7
uses: OpenTTD/actions/setup-vcpkg@v6
- name: Install dependencies
shell: bash
@@ -193,14 +193,14 @@ jobs:
AZURE_CODESIGN_PROFILE_NAME: ${{ secrets.AZURE_CODESIGN_PROFILE_NAME }}
- name: Store bundles
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@v5
with:
name: openttd-windows-${{ matrix.arch }}
path: build/bundles
retention-days: 5
- name: Store symbols
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@v5
with:
name: symbols-windows-${{ matrix.arch }}
path: build/symbols
@@ -14,7 +14,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v7
uses: actions/checkout@v6
- name: Check for finding script functions that require company/deity mode enforcement/checks
run: |
+1 -1
View File
@@ -14,7 +14,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v7
uses: actions/checkout@v6
- name: Check for unused strings
run: |
+5 -5
View File
@@ -21,7 +21,7 @@ jobs:
steps:
- name: Download all bundles
uses: actions/download-artifact@v8
uses: actions/download-artifact@v6
- name: Calculate checksums
run: |
@@ -70,14 +70,14 @@ jobs:
done
- name: Store bundles
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@v5
with:
name: cdn-bundles
path: bundles/*
retention-days: 5
- name: Store breakpad symbols
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@v5
with:
name: cdn-symbols
path: symbols/*
@@ -88,7 +88,7 @@ jobs:
- prepare
name: Publish bundles
uses: OpenTTD/actions/.github/workflows/rw-cdn-upload.yml@v7
uses: OpenTTD/actions/.github/workflows/rw-cdn-upload.yml@v6
secrets:
CDN_SIGNING_KEY: ${{ secrets.CDN_SIGNING_KEY }}
DEPLOYMENT_APP_ID: ${{ secrets.DEPLOYMENT_APP_ID }}
@@ -103,7 +103,7 @@ jobs:
- prepare
name: Publish symbols
uses: OpenTTD/actions/.github/workflows/rw-symbols-upload.yml@v7
uses: OpenTTD/actions/.github/workflows/rw-symbols-upload.yml@v6
secrets:
SYMBOLS_SIGNING_KEY: ${{ secrets.SYMBOLS_SIGNING_KEY }}
with:
+5 -5
View File
@@ -15,31 +15,31 @@ jobs:
steps:
- name: Download source
uses: actions/download-artifact@v8
uses: actions/download-artifact@v6
with:
name: internal-source
path: internal-source
- name: Download bundle (Windows x86)
uses: actions/download-artifact@v8
uses: actions/download-artifact@v6
with:
name: openttd-windows-x86
path: openttd-windows-x86
- name: Download bundle (Windows x64)
uses: actions/download-artifact@v8
uses: actions/download-artifact@v6
with:
name: openttd-windows-x64
path: openttd-windows-x64
- name: Download bundle (MacOS)
uses: actions/download-artifact@v8
uses: actions/download-artifact@v6
with:
name: openttd-macos-universal
path: openttd-macos-universal
- name: Download bundle (Linux)
uses: actions/download-artifact@v8
uses: actions/download-artifact@v6
with:
name: openttd-linux-generic
path: openttd-linux-generic
+5 -5
View File
@@ -18,31 +18,31 @@ jobs:
steps:
- name: Download source
uses: actions/download-artifact@v8
uses: actions/download-artifact@v6
with:
name: internal-source
path: internal-source
- name: Download bundle (Windows x86)
uses: actions/download-artifact@v8
uses: actions/download-artifact@v6
with:
name: openttd-windows-x86
path: openttd-windows-x86
- name: Download bundle (Windows x64)
uses: actions/download-artifact@v8
uses: actions/download-artifact@v6
with:
name: openttd-windows-x64
path: openttd-windows-x64
- name: Download bundle (MacOS)
uses: actions/download-artifact@v8
uses: actions/download-artifact@v6
with:
name: openttd-macos-universal
path: openttd-macos-universal
- name: Download bundle (Linux)
uses: actions/download-artifact@v8
uses: actions/download-artifact@v6
with:
name: openttd-linux-generic
path: openttd-linux-generic
+2 -2
View File
@@ -18,13 +18,13 @@ jobs:
steps:
- name: Download bundle (Windows Store)
uses: actions/download-artifact@v8
uses: actions/download-artifact@v6
with:
name: openttd-windows-store
path: openttd-windows-store
- name: Configure Microsoft Store CLI
uses: microsoft/microsoft-store-apppublisher@v1.4
uses: microsoft/microsoft-store-apppublisher@v1.1
- name: Reconfigure store credentials
run: msstore reconfigure `
+5 -11
View File
@@ -5,7 +5,7 @@ if(NOT BINARY_NAME)
endif()
project(${BINARY_NAME}
VERSION 16.0
VERSION 15.3
LANGUAGES CXX
)
@@ -75,10 +75,6 @@ add_custom_target(find_version
-DREV_MAJOR=${PROJECT_VERSION_MAJOR}
-DREV_MINOR=${PROJECT_VERSION_MINOR}
-DWINDOWS=${WIN32}
-DDOXYGEN_WARN_FORMAT_LINE=${DOXYGEN_WARN_FORMAT_LINE}
-DDOXYGEN_WARN_FILE=${DOXYGEN_WARN_FILE}
-DDOXYGEN_GS_WARN_FILE=${DOXYGEN_GS_WARN_FILE}
-DDOXYGEN_AI_WARN_FILE=${DOXYGEN_AI_WARN_FILE}
-P "${CMAKE_SOURCE_DIR}/cmake/scripts/FindVersion.cmake"
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
BYPRODUCTS ${GENERATED_SOURCE_FILES}
@@ -156,7 +152,6 @@ if(NOT OPTION_DEDICATED)
endif()
endif()
find_package(OpusFile)
find_package(Soxr)
endif()
if(APPLE)
enable_language(OBJCXX)
@@ -190,7 +185,7 @@ if(UNIX AND NOT APPLE AND NOT OPTION_DEDICATED)
if(NOT SDL2_FOUND AND NOT ALLEGRO_FOUND)
message(FATAL_ERROR "SDL2 or Allegro is required for this platform")
endif()
if(HARFBUZZ_FOUND AND NOT ICU_I18N_FOUND)
if(HARFBUZZ_FOUND AND NOT ICU_i18n_FOUND)
message(WARNING "HarfBuzz depends on ICU i18n to function; HarfBuzz will be disabled")
endif()
if(NOT HARFBUZZ_FOUND)
@@ -328,10 +323,9 @@ if(NOT OPTION_DEDICATED)
link_package(FREETYPE TARGET Freetype::Freetype)
link_package(Fontconfig TARGET Fontconfig::Fontconfig)
link_package(Harfbuzz TARGET harfbuzz::harfbuzz)
link_package(ICU_I18N TARGET ICU::i18n)
link_package(ICU_UC TARGET ICU::uc)
link_package(ICU_i18n)
link_package(ICU_uc)
link_package(OpusFile TARGET OpusFile::opusfile)
link_package(Soxr TARGET Soxr::soxr)
if(SDL2_FOUND AND OPENGL_FOUND AND UNIX)
# SDL2 dynamically loads OpenGL if needed, so do not link to OpenGL when
@@ -372,7 +366,7 @@ if(EMSCRIPTEN)
add_definitions(-s DISABLE_EXCEPTION_CATCHING=0)
# Export functions to Javascript.
target_link_libraries(WASM::WASM INTERFACE "-s EXPORTED_FUNCTIONS='[\"_main\", \"_em_openttd_add_server\"]' -s EXPORTED_RUNTIME_METHODS='[\"cwrap\", \"HEAPU8\"]'")
target_link_libraries(WASM::WASM INTERFACE "-s EXPORTED_FUNCTIONS='[\"_main\", \"_em_openttd_add_server\"]' -s EXPORTED_RUNTIME_METHODS='[\"cwrap\"]'")
# Preload all the files we generate during build.
# As we do not compile with FreeType / FontConfig, we also have no way to
-1
View File
@@ -12,7 +12,6 @@ What is simple to some might appear very complicated to others. Documentation he
* Use Foo() instead of Foo(void).
* Prefer using "const" for reference and compound parameters when appropriate.
* If a member function can be a const function, make it so.
* Order of qualifiers is `static inline` / `static constexpr`, don't use `inline` with `constexpr`.
```c++
void ThisIsAFunction()
{
+15 -19
View File
@@ -45,9 +45,7 @@ PYTHON_DOCSTRING = YES
INHERIT_DOCS = YES
SEPARATE_MEMBER_PAGES = NO
TAB_SIZE = 2
ALIASES = important="@attention" # @important is available in newer versions of doxygen.
ALIASES += split_group{1}="@}^^@{^^@ingroup \1^^" \
split_group{3;}="^^@defgroup \1_\2 \3^^@ingroup \1^^@{^^@}^^@}^^@{^^@ingroup \1_\2^^"
ALIASES =
OPTIMIZE_OUTPUT_FOR_C = YES
OPTIMIZE_OUTPUT_JAVA = NO
OPTIMIZE_FOR_FORTRAN = NO
@@ -61,7 +59,7 @@ BUILTIN_STL_SUPPORT = NO
CPP_CLI_SUPPORT = NO
SIP_SUPPORT = NO
IDL_PROPERTY_SUPPORT = YES
DISTRIBUTE_GROUP_DOC = YES
DISTRIBUTE_GROUP_DOC = NO
GROUP_NESTED_COMPOUNDS = NO
SUBGROUPING = YES
INLINE_GROUPED_CLASSES = NO
@@ -120,12 +118,11 @@ WARNINGS = YES
WARN_IF_UNDOCUMENTED = YES
WARN_IF_DOC_ERROR = YES
WARN_IF_INCOMPLETE_DOC = YES
WARN_NO_PARAMDOC = YES
WARN_IF_UNDOC_ENUM_VAL = YES
WARN_NO_PARAMDOC = NO
WARN_AS_ERROR = NO
WARN_FORMAT = "$file:$${DOXYGEN_WARN_FORMAT_LINE}: $text"
WARN_LINE_FORMAT = "at line $${DOXYGEN_WARN_FORMAT_LINE} of file $file"
WARN_LOGFILE = ${DOXYGEN_WARN_FILE}
WARN_FORMAT = "$file:$line: $text"
WARN_LINE_FORMAT = "at line $line of file $file"
WARN_LOGFILE =
#---------------------------------------------------------------------------
# Configuration options related to the input files
#---------------------------------------------------------------------------
@@ -137,15 +134,12 @@ FILE_PATTERNS = *.c \
*.cpp \
*.c++ \
*.h \
*.hpp \
*.mm \
*.m
*.hpp
RECURSIVE = YES
EXCLUDE =
EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS = */3rdparty \
*/script/api \
*/tests
*/script/api
EXCLUDE_SYMBOLS =
EXAMPLE_PATH =
EXAMPLE_PATTERNS = *
@@ -191,6 +185,7 @@ HTML_EXTRA_FILES =
HTML_COLORSTYLE_HUE = 220
HTML_COLORSTYLE_SAT = 100
HTML_COLORSTYLE_GAMMA = 80
HTML_TIMESTAMP = NO
HTML_DYNAMIC_MENUS = YES
HTML_DYNAMIC_SECTIONS = NO
HTML_INDEX_NUM_ENTRIES = 100
@@ -226,6 +221,7 @@ EXT_LINKS_IN_WINDOW = NO
OBFUSCATE_EMAILS = YES
HTML_FORMULA_FORMAT = png
FORMULA_FONTSIZE = 10
FORMULA_TRANSPARENT = YES
FORMULA_MACROFILE =
USE_MATHJAX = NO
MATHJAX_VERSION = MathJax_2
@@ -260,6 +256,7 @@ USE_PDFLATEX = NO
LATEX_BATCHMODE = NO
LATEX_HIDE_INDICES = NO
LATEX_BIB_STYLE = plain
LATEX_TIMESTAMP = NO
LATEX_EMOJI_DIRECTORY =
#---------------------------------------------------------------------------
# Configuration options related to the RTF output
@@ -320,14 +317,10 @@ PREDEFINED = WITH_ZLIB \
WITH_HARFBUZZ \
WITH_ICU_I18N \
UNICODE \
DOXYGEN_API \
_UNICODE \
_GNU_SOURCE \
CDECL= \
CALLBACK= \
APIENTRY= \
FINAL=
EXPAND_AS_DEFINED = DEFINE_POOL_METHOD
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration options related to external references
@@ -344,6 +337,8 @@ DIA_PATH =
HIDE_UNDOC_RELATIONS = YES
HAVE_DOT = NO
DOT_NUM_THREADS = 0
DOT_FONTNAME = Helvetica
DOT_FONTSIZE = 10
DOT_FONTPATH =
CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES
@@ -371,6 +366,7 @@ PLANTUML_CFG_FILE =
PLANTUML_INCLUDE_PATH =
DOT_GRAPH_MAX_NODES = 50
MAX_DOT_GRAPH_DEPTH = 1000
DOT_TRANSPARENT = NO
DOT_MULTI_TARGETS = NO
GENERATE_LEGEND = YES
DOT_CLEANUP = YES
-1
View File
@@ -15,7 +15,6 @@ set(AI_COMPAT_SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/compat_12.nut
${CMAKE_CURRENT_SOURCE_DIR}/compat_13.nut
${CMAKE_CURRENT_SOURCE_DIR}/compat_14.nut
${CMAKE_CURRENT_SOURCE_DIR}/compat_15.nut
)
foreach(AI_COMPAT_SOURCE_FILE IN LISTS AI_COMPAT_SOURCE_FILES)
-8
View File
@@ -1,8 +0,0 @@
/*
* This file is part of OpenTTD.
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
*/
/* This file contains code to downgrade the API from 16 to 15. */
-1
View File
@@ -12,7 +12,6 @@ set(GS_COMPAT_SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/compat_12.nut
${CMAKE_CURRENT_SOURCE_DIR}/compat_13.nut
${CMAKE_CURRENT_SOURCE_DIR}/compat_14.nut
${CMAKE_CURRENT_SOURCE_DIR}/compat_15.nut
)
foreach(GS_COMPAT_SOURCE_FILE IN LISTS GS_COMPAT_SOURCE_FILES)
-140
View File
@@ -1,140 +0,0 @@
/*
* This file is part of OpenTTD.
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
*/
/* This file contains code to downgrade the API from 16 to 15. */
/*
* These window/widget related enumerations have never been stable, but breaking anything using them
* is a really big ask when restructuring code. If in the future things are removed from the underlying
* enumerations, feel free to remove them from this compatibility script.
*/
GSWindow.WN_GAME_OPTIONS_AI <- GSWindow.GameOptionsWindowNumber.AI;
GSWindow.WN_GAME_OPTIONS_GS <- GSWindow.GameOptionsWindowNumber.GS;
GSWindow.WN_GAME_OPTIONS_ABOUT <- GSWindow.GameOptionsWindowNumber.About;
GSWindow.WN_GAME_OPTIONS_NEWGRF_STATE <- GSWindow.GameOptionsWindowNumber.NewGRFState;
GSWindow.WN_GAME_OPTIONS_GAME_OPTIONS <- GSWindow.GameOptionsWindowNumber.GameOptions;
GSWindow.WN_GAME_OPTIONS_GAME_SETTINGS <- GSWindow.GameOptionsWindowNumber.GameOptions;
GSWindow.WN_QUERY_STRING <- GSWindow.QueryStringWindowNumber.Default;
GSWindow.WN_QUERY_STRING_SIGN <- GSWindow.QueryStringWindowNumber.Sign;
GSWindow.WN_CONFIRM_POPUP_QUERY <- GSWindow.ConfirmPopupQueryWindowNumber.Default;
GSWindow.WN_CONFIRM_POPUP_QUERY_BOOTSTRAP <- GSWindow.ConfirmPopupQueryWindowNumber.Bootstrap;
GSWindow.WN_NETWORK_WINDOW_GAME <- GSWindow.NetworkWindowNumber.Game;
GSWindow.WN_NETWORK_WINDOW_CONTENT_LIST <- GSWindow.NetworkWindowNumber.ContentList;
GSWindow.WN_NETWORK_WINDOW_START <- GSWindow.NetworkWindowNumber.StartServer;
GSWindow.WN_NETWORK_STATUS_WINDOW_JOIN <- GSWindow.NetworkStatusWindowNumber.Join;
GSWindow.WN_NETWORK_STATUS_WINDOW_CONTENT_DOWNLOAD <- GSWindow.NetworkStatusWindowNumber.ContentDownload;
GSWindow.WC_NONE <- GSWindow.WindowClass.None;
GSWindow.WC_MAIN_WINDOW <- GSWindow.WindowClass.MainWindow;
GSWindow.WC_MAIN_TOOLBAR <- GSWindow.WindowClass.MainToolbar;
GSWindow.WC_STATUS_BAR <- GSWindow.WindowClass.Statusbar;
GSWindow.WC_BUILD_TOOLBAR <- GSWindow.WindowClass.BuildToolbar;
GSWindow.WC_SCEN_BUILD_TOOLBAR <- GSWindow.WindowClass.ScenarioBuildToolbar;
GSWindow.WC_BUILD_TREES <- GSWindow.WindowClass.BuildTrees;
GSWindow.WC_TRANSPARENCY_TOOLBAR <- GSWindow.WindowClass.TransparencyToolbar;
GSWindow.WC_BUILD_SIGNAL <- GSWindow.WindowClass.BuildSignal;
GSWindow.WC_SMALLMAP <- GSWindow.WindowClass.SmallMap;
GSWindow.WC_ERRMSG <- GSWindow.WindowClass.ErrorMessage;
GSWindow.WC_TOOLTIPS <- GSWindow.WindowClass.ToolTips;
GSWindow.WC_QUERY_STRING <- GSWindow.WindowClass.QueryString;
GSWindow.WC_CONFIRM_POPUP_QUERY <- GSWindow.WindowClass.ConfirmPopupQuery;
GSWindow.WC_GOAL_QUESTION <- GSWindow.WindowClass.GoalQuestion;
GSWindow.WC_SAVELOAD <- GSWindow.WindowClass.SaveLoad;
GSWindow.WC_LAND_INFO <- GSWindow.WindowClass.LandInfo;
GSWindow.WC_DROPDOWN_MENU <- GSWindow.WindowClass.DropdownMenu;
GSWindow.WC_OSK <- GSWindow.WindowClass.OnScreenKeyboard;
GSWindow.WC_SET_DATE <- GSWindow.WindowClass.SetDate;
GSWindow.WC_SCRIPT_SETTINGS <- GSWindow.WindowClass.ScriptSettings;
GSWindow.WC_GRF_PARAMETERS <- GSWindow.WindowClass.NewGRFParameters;
GSWindow.WC_TEXTFILE <- GSWindow.WindowClass.Textfile;
GSWindow.WC_TOWN_AUTHORITY <- GSWindow.WindowClass.TownAuthority;
GSWindow.WC_VEHICLE_DETAILS <- GSWindow.WindowClass.VehicleDetails;
GSWindow.WC_VEHICLE_REFIT <- GSWindow.WindowClass.VehicleRefit;
GSWindow.WC_VEHICLE_ORDERS <- GSWindow.WindowClass.VehicleOrders;
GSWindow.WC_REPLACE_VEHICLE <- GSWindow.WindowClass.ReplaceVehicle;
GSWindow.WC_VEHICLE_TIMETABLE <- GSWindow.WindowClass.VehicleTimetable;
GSWindow.WC_COMPANY_COLOUR <- GSWindow.WindowClass.CompanyLivery;
GSWindow.WC_COMPANY_MANAGER_FACE <- GSWindow.WindowClass.CompanyManagerFace;
GSWindow.WC_SELECT_STATION <- GSWindow.WindowClass.JoinStation;
GSWindow.WC_NEWS_WINDOW <- GSWindow.WindowClass.News;
GSWindow.WC_TOWN_DIRECTORY <- GSWindow.WindowClass.TownDirectory;
GSWindow.WC_SUBSIDIES_LIST <- GSWindow.WindowClass.SubsidyList;
GSWindow.WC_INDUSTRY_DIRECTORY <- GSWindow.WindowClass.IndustryDirectory;
GSWindow.WC_MESSAGE_HISTORY <- GSWindow.WindowClass.MessageHistory;
GSWindow.WC_SIGN_LIST <- GSWindow.WindowClass.SignList;
GSWindow.WC_SCRIPT_LIST <- GSWindow.WindowClass.ScriptList;
GSWindow.WC_GOALS_LIST <- GSWindow.WindowClass.GoalList;
GSWindow.WC_STORY_BOOK <- GSWindow.WindowClass.StoryBook;
GSWindow.WC_STATION_LIST <- GSWindow.WindowClass.StationList;
GSWindow.WC_TRAINS_LIST <- GSWindow.WindowClass.TrainList;
GSWindow.WC_ROADVEH_LIST <- GSWindow.WindowClass.RoadVehicleList;
GSWindow.WC_SHIPS_LIST <- GSWindow.WindowClass.ShipList;
GSWindow.WC_AIRCRAFT_LIST <- GSWindow.WindowClass.AircraftList;
GSWindow.WC_TOWN_VIEW <- GSWindow.WindowClass.TownView;
GSWindow.WC_VEHICLE_VIEW <- GSWindow.WindowClass.VehicleView;
GSWindow.WC_STATION_VIEW <- GSWindow.WindowClass.StationView;
GSWindow.WC_VEHICLE_DEPOT <- GSWindow.WindowClass.VehicleDepot;
GSWindow.WC_WAYPOINT_VIEW <- GSWindow.WindowClass.WaypointView;
GSWindow.WC_INDUSTRY_VIEW <- GSWindow.WindowClass.IndustryView;
GSWindow.WC_COMPANY <- GSWindow.WindowClass.Company;
GSWindow.WC_BUILD_OBJECT <- GSWindow.WindowClass.BuildObject;
GSWindow.WC_BUILD_HOUSE <- GSWindow.WindowClass.BuildHouse;
GSWindow.WC_BUILD_VEHICLE <- GSWindow.WindowClass.BuildVehicle;
GSWindow.WC_BUILD_BRIDGE <- GSWindow.WindowClass.BuildBridge;
GSWindow.WC_BUILD_STATION <- GSWindow.WindowClass.BuildStation;
GSWindow.WC_BUS_STATION <- GSWindow.WindowClass.BuildBusStation;
GSWindow.WC_TRUCK_STATION <- GSWindow.WindowClass.BuildTruckStation;
GSWindow.WC_BUILD_DEPOT <- GSWindow.WindowClass.BuildDepot;
GSWindow.WC_BUILD_WAYPOINT <- GSWindow.WindowClass.BuildWaypoint;
GSWindow.WC_FOUND_TOWN <- GSWindow.WindowClass.FoundTown;
GSWindow.WC_BUILD_INDUSTRY <- GSWindow.WindowClass.BuildIndustry;
GSWindow.WC_SELECT_GAME <- GSWindow.WindowClass.SelectGame;
GSWindow.WC_SCEN_LAND_GEN <- GSWindow.WindowClass.ScenarioGenerateLandscape;
GSWindow.WC_GENERATE_LANDSCAPE <- GSWindow.WindowClass.GenerateLandscape;
GSWindow.WC_MODAL_PROGRESS <- GSWindow.WindowClass.ModalProgress;
GSWindow.WC_NETWORK_WINDOW <- GSWindow.WindowClass.Network;
GSWindow.WC_CLIENT_LIST <- GSWindow.WindowClass.NetworkClientList;
GSWindow.WC_NETWORK_STATUS_WINDOW <- GSWindow.WindowClass.NetworkStatus;
GSWindow.WC_NETWORK_ASK_RELAY <- GSWindow.WindowClass.NetworkAskRelay;
GSWindow.WC_NETWORK_ASK_SURVEY <- GSWindow.WindowClass.NetworkAskSurvey;
GSWindow.WC_SEND_NETWORK_MSG <- GSWindow.WindowClass.NetworkChat;
GSWindow.WC_INDUSTRY_CARGOES <- GSWindow.WindowClass.IndustryCargoes;
GSWindow.WC_GRAPH_LEGEND <- GSWindow.WindowClass.GraphLegend;
GSWindow.WC_FINANCES <- GSWindow.WindowClass.Finances;
GSWindow.WC_INCOME_GRAPH <- GSWindow.WindowClass.IncomeGraph;
GSWindow.WC_OPERATING_PROFIT <- GSWindow.WindowClass.OperatingProfitGraph;
GSWindow.WC_DELIVERED_CARGO <- GSWindow.WindowClass.DeliveredCargoGraph;
GSWindow.WC_PERFORMANCE_HISTORY <- GSWindow.WindowClass.PerformanceGraph;
GSWindow.WC_COMPANY_VALUE <- GSWindow.WindowClass.CompanyValueGraph;
GSWindow.WC_COMPANY_LEAGUE <- GSWindow.WindowClass.CompanyLeague;
GSWindow.WC_PAYMENT_RATES <- GSWindow.WindowClass.CargoPaymentRatesGraph;
GSWindow.WC_PERFORMANCE_DETAIL <- GSWindow.WindowClass.PerformanceDetail;
GSWindow.WC_INDUSTRY_PRODUCTION <- GSWindow.WindowClass.IndustryProductionGraph;
GSWindow.WC_TOWN_CARGO_GRAPH <- GSWindow.WindowClass.TownCargoGraph;
GSWindow.WC_COMPANY_INFRASTRUCTURE <- GSWindow.WindowClass.CompanyInfrastructure;
GSWindow.WC_BUY_COMPANY <- GSWindow.WindowClass.BuyCompany;
GSWindow.WC_ENGINE_PREVIEW <- GSWindow.WindowClass.EnginePreview;
GSWindow.WC_MUSIC_WINDOW <- GSWindow.WindowClass.Music;
GSWindow.WC_MUSIC_TRACK_SELECTION <- GSWindow.WindowClass.MusicTrackSelection;
GSWindow.WC_GAME_OPTIONS <- GSWindow.WindowClass.GameOptions;
GSWindow.WC_CUSTOM_CURRENCY <- GSWindow.WindowClass.CustomCurrenty;
GSWindow.WC_CHEATS <- GSWindow.WindowClass.Cheat;
GSWindow.WC_EXTRA_VIEWPORT <- GSWindow.WindowClass.ExtraViewport;
GSWindow.WC_CONSOLE <- GSWindow.WindowClass.Console;
GSWindow.WC_BOOTSTRAP <- GSWindow.WindowClass.Bootstrap;
GSWindow.WC_HIGHSCORE <- GSWindow.WindowClass.Highscore;
GSWindow.WC_ENDSCREEN <- GSWindow.WindowClass.Endscreen;
GSWindow.WC_SCRIPT_DEBUG <- GSWindow.WindowClass.ScriptDebug;
GSWindow.WC_NEWGRF_INSPECT <- GSWindow.WindowClass.NewGRFInspect;
GSWindow.WC_SPRITE_ALIGNER <- GSWindow.WindowClass.SpriteAligner;
GSWindow.WC_LINKGRAPH_LEGEND <- GSWindow.WindowClass.LinkGraphLegend;
GSWindow.WC_SAVE_PRESET <- GSWindow.WindowClass.SavePreset;
GSWindow.WC_FRAMERATE_DISPLAY <- GSWindow.WindowClass.FramerateDisplay;
GSWindow.WC_FRAMETIME_GRAPH <- GSWindow.WindowClass.FrametimeGraph;
GSWindow.WC_SCREENSHOT <- GSWindow.WindowClass.Screenshot;
GSWindow.WC_HELPWIN <- GSWindow.WindowClass.Help;
GSWindow.WC_INVALID <- GSWindow.WindowClass.Invalid;
-116
View File
@@ -1,119 +1,3 @@
## 16.x
### 16.0-beta2 (2026-07-12)
- Feature: Allow bridges over depots (#15836)
- Feature: Increase maximum number of vehicles per type to 10,000 (#15810)
- Feature: Add and remove whole classes to picker collections (#15808)
- Feature: Station list can be filtered by name (#15772)
- Change: Use "bridge ... too low" message for bridgeable objects (#15838)
- Fix: Use meaningful tooltips for graph range toggle buttons (#15842)
- Fix #15826: Exclude allow any/all options for AI companies (#15834)
- Fix #7992: Fix for catenary road and tram catenary sprites not being drawn on bridges (#15811)
- Fix #15784: Crash due to incorrect road build toolbar when switching road tram types (#15789)
- Fix: [NewGRF] Make 'signals on traffic side' consistent with explicit settings (#15661)
- Fix: [Win32] Explicitly initialize COM in Win32 video driver (#15553)
### 16.0-beta1 (2026-06-25)
- Feature: Add default road and tram selection (#15585)
- Feature: Trains with an engine on the rear can drive backwards when reversing (#15379)
- Feature: Add worldgen setting for average height of terrain (#14989)
- Feature: Add text filter to dropdown lists (#14842)
- Feature: User-defined collections of saved items in the picker window (#14813)
- Feature: Configurable sign text colors in scenario editor (#14743)
- Feature: Allow placing an area of 1x1 houses in scenario editor (#14708)
- Feature: Scale cargo payment aging rate (#14635)
- Feature: Support automatic detection of data from Atari's Transport Tycoon Deluxe re-release (#15483)
- Add: [NewGRF] Implement custom waypoint layouts by callback 24 (#15616)
- Add: List 'Place object' in landscaping dropdown (#15609)
- Add: Setting to disable aircraft range limit (#15433)
- Add: Show maximum reliability in vehicle info (#15401)
- Add: Lower the Send To Depot button when a vehicle is on its way to one (#15397)
- Add: Setting to disallow train magic flip, and reverse at reduced speed (#15391)
- Add: [NewGRF] Variable for when a train is driving backwards (#15379)
- Add: [NewGRF] Flag to allow unpowered wagon to lead train when backing up (#15379)
- Add: [NewGRF] Station flag to divide cargo by area instead of perimeter (#15253)
- Add: Company allow-list can be set to allow anyone (#15204)
- Add: Record history of cargo delivered to towns (#15184)
- Add: Show additional vehicle details based on sort criteria (#15158)
- Add: Setting to control minimum distance between towns (#14893)
- Change: Selecting Rail/Roadtype updates build toolbar instead of closing and reopening (#15589)
- Change: Default setting to review orders excludes stopped vehicles (#15565)
- Change: Most used rail type takes ownership into account (#15489)
- Change: Test font for eligibility before adding as fallback (#15412)
- Change: Clarify max age shown in vehicle info window (#15403)
- Change: Show "Delete All" in order window delete button when applicable (#15370)
- Change: Make continuation error messages consistent (#15328)
- Change: Distinguish between 'Flat land required' and 'Land sloped in wrong direction' for building depots (#15327)
- Change: Allow subsidies with CargoDist (#15189)
- Change: Removing river tiles reduces local authority rating (#15180)
- Change: Protect rivers from removal when terraforming (#15176)
- Change: [Script] Reformat callstack output (#15171)
- Change: Apply slightly more padding to image-text buttons (#15077)
- Change: [NewGRF] Display rail and road type speed limit text in yellow (#15076)
- Change: Make smallmap show infinite water, if enabled (#15041)
- Change: Add support for next/previous/first/last rail/road/tram type hotkeys (#15028)
- Change: Allow rocks on desert tiles (#14979)
- Change: [Script] Include Array/PriorityQueye/ScriptList contents in script memory allocation total (#14954)
- Change: [Script] Various ScriptList methods are now suspendable (#14943, #14762)
- Change: Improve generation of coasts at map edges (#14868)
- Change: Show only selected badge in badge filter dropdown buttons (#14855)
- Change: River springs must be surrounded by hills (#14845)
- Change: Vehicles loading at stations don't lose reliability (#14841)
- Change: Generate lighthouses along coasts and near towns (#14828)
- Change: Transmitter object only spawns after original base year (#14786)
- Change: Share one window for engine preview pop ups (#14703)
- Fix: [NewGRF] Town name language incorrectly decoded (#15691)
- Fix #15606: Undefined behaviour may cause buttons to be invisible (#15686)
- Fix #14975: Show correct tile for tunnel error message (#15660)
- Fix: [NewGRF] Incorrect language IDs passed to TranslateTTDPatchCodes (#15655)
- Fix: Scenario editor random industry generation (#15626)
- Fix: [NewGRF] Ignore blocked waypoint tiles (#15620)
- Fix: [NewGRF] Pylons and no-wires flags were ignored for waypoint tiles (#15619)
- Fix: Dedicated server signal handling for SIGTERM/SIGINT/SIGQUIT (#15607)
- Fix: [NewGRF] Potential out-of-bounds read when performing GRM (#15600)
- Fix: Badge offsets not ignored when determining width (#15588)
- Fix: Account for NewGRF's global train width when drawing dual-head engines (#15587)
- Fix: Station list facility buttons do not produce click sound (#15569)
- Fix #15495: Fix incorrectly built default waypoints (#15562)
- Fix #15495: Unable to build bridge over default waypoints (#15562)
- Fix #15235: Make GameScripts obey town road construction setting (#15559)
- Fix: Crash when loading crash save with no viewport coordinates (#15550)
- Fix #15520: Fix viewport snap back on stop following vehicle (#15520) (#15531)
- Fix: Buttons for choosing engine in preview window show for single engine (#15514)
- Fix #15511: Vehicle passed to commands must be a company buildable type (#15512)
- Fix #15497: [Script] ScriptController::Break not pausing in TestMode (#15498)
- Fix: Coordinate transformation for JSON town placement when anticlockwise (#15490)
- Fix: NewGRF debug handler for towns in wrong place since badges (#15467)
- Fix: Object id overrides were not reset between games (#15465)
- Fix: Debug saveload errors were clobbered (#15452)
- Fix: Refresh client list when client renames (#15439)
- Fix #15428: [Fluidsynth] Treat configured synth.gain as maximum instead of hardcoded value (#15429)
- Fix: Refresh string width cache for all loaded fonts (#15427)
- Fix: Typo in Hungarian town name suffix ("kak" -> "lak") (#15421)
- Fix: [NewGRF] Variable 0x69 has not been added for waypoints (#15396)
- Fix: Dropdown text filter could interfere with hotkeys after closing (#15395)
- Fix: Rejecting or accepting engine preview incorrectly closed preview window (#15378)
- Fix #15318: Nonsensical error message when trying to send aircraft to hangar with no usable airports (#15334)
- Fix #15234: Null pointer dereference opening sign edit window when sign 0 does not exist (#15236)
- Fix: [GS] Docs are missing or do not match the code (#15230)
- Fix: Off by one and redundant logic in snowy road checks (#15214)
- Fix #15137: Roads built on steep slopes at the minimum snow level height have inconsistent snowiness (#15190)
- Fix: Station view window fold/unfold not refreshing scrollbar (#15187)
- Fix: Use consistent description for invalid orders (#15177)
- Fix: [Script] Give GetPrimary/SecondaryLiveryColour preconditions (#15169)
- Fix: Cocoa video driver did not register (#15145)
- Fix: MacOS version detection was broken (#15145)
- Fix #13600: Make terraform click+draggable in scenario editor (#15135)
- Fix: [Script] Map some error strings to existing errors (#15113)
- Fix: Allow to build buoys at (0x0) (#14983)
- Fix #14610: Do not treat aircraft with only depot orders as having valid orders (#14961)
- Fix #12937: Allow the computer to go to sleep while the game is paused (#14948)
- Fix: Company query popups do not update in multiplayer (#14947)
- Fix #14892: Potential crash when logging fonts for survey (#14896)
- Fix #14827: Store random trigger information per-tile (#14830)
## 15.x
### 15.3 (2026-04-04)
+27
View File
@@ -56,6 +56,11 @@ macro(compile_flags)
# This flag disables the broken optimisation to work around the bug
add_compile_options(/d2ssa-rse-)
endif()
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
add_compile_options(
-Wno-multichar
)
endif()
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
add_compile_options(
-W
@@ -73,6 +78,9 @@ macro(compile_flags)
-Wnon-virtual-dtor
-Wsuggest-override
# We use 'ABCD' multichar for SaveLoad chunks identifiers
-Wno-multichar
# Prevent optimisation supposing enums are in a range specified by the standard
# For details, see http://gcc.gnu.org/PR43680 and PR#5246.
-fno-strict-enums
@@ -92,6 +100,9 @@ macro(compile_flags)
endif()
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
include(CheckCXXCompilerFlag)
check_cxx_compiler_flag("-flifetime-dse=1" LIFETIME_DSE_FOUND)
add_compile_options(
# GCC 4.2+ automatically assumes that signed overflows do
# not occur in signed arithmetics, whereas we are not
@@ -99,6 +110,10 @@ macro(compile_flags)
# about its own optimized code in some places.
"-fno-strict-overflow"
# -flifetime-dse=2 (default since GCC 6) doesn't play
# well with our custom pool item allocator
"$<$<BOOL:${LIFETIME_DSE_FOUND}>:-flifetime-dse=1>"
# We have a fight between clang wanting std::move() and gcc not wanting it
# and of course they both warn when the other compiler is happy
"-Wno-redundant-move"
@@ -118,6 +133,18 @@ macro(compile_flags)
endif()
endif()
endif()
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
add_compile_options(
-Wall
# warning #873: function ... ::operator new ... has no corresponding operator delete ...
-wd873
# warning #1292: unknown attribute "fallthrough"
-wd1292
# warning #1899: multicharacter character literal (potential portability problem)
-wd1899
# warning #2160: anonymous union qualifier is ignored
-wd2160
)
else()
message(FATAL_ERROR "No warning flags are set for this compiler yet; please consider creating a Pull Request to add support for this compiler.")
endif()
+2 -6
View File
@@ -5,12 +5,12 @@
#
# create_regression(file1 ...)
#
macro(create_regression SCRIPT_FOLDER)
macro(create_regression)
set(REGRESSION_SOURCE_FILES ${ARGN})
foreach(REGRESSION_SOURCE_FILE IN LISTS REGRESSION_SOURCE_FILES)
string(REPLACE "${CMAKE_SOURCE_DIR}/regression/" "" REGRESSION_SOURCE_FILE_NAME "${REGRESSION_SOURCE_FILE}")
string(CONCAT REGRESSION_BINARY_FILE "${CMAKE_BINARY_DIR}/${SCRIPT_FOLDER}/" "${REGRESSION_SOURCE_FILE_NAME}")
string(CONCAT REGRESSION_BINARY_FILE "${CMAKE_BINARY_DIR}/ai/" "${REGRESSION_SOURCE_FILE_NAME}")
add_custom_command(OUTPUT ${REGRESSION_BINARY_FILE}
COMMAND ${CMAKE_COMMAND} -E copy
@@ -38,7 +38,6 @@ macro(create_regression SCRIPT_FOLDER)
-DOPENTTD_EXECUTABLE=$<TARGET_FILE:openttd>
-DEDITBIN_EXECUTABLE=${EDITBIN_EXECUTABLE}
-DREGRESSION_TEST=${REGRESSION_TEST_NAME}
-DSCRIPT_FOLDER=${SCRIPT_FOLDER}
-P "${CMAKE_SOURCE_DIR}/cmake/scripts/Regression.cmake"
DEPENDS openttd regression_${REGRESSION_TEST_NAME}_files
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
@@ -51,12 +50,9 @@ macro(create_regression SCRIPT_FOLDER)
-DOPENTTD_EXECUTABLE=$<TARGET_FILE:openttd>
-DEDITBIN_EXECUTABLE=${EDITBIN_EXECUTABLE}
-DREGRESSION_TEST=${REGRESSION_TEST_NAME}
-DSCRIPT_FOLDER=${SCRIPT_FOLDER}
-P "${CMAKE_SOURCE_DIR}/cmake/scripts/Regression.cmake"
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
set_property(TEST regression_${REGRESSION_TEST_NAME} PROPERTY RUN_SERIAL TRUE)
add_dependencies(regression regression_${REGRESSION_TEST_NAME})
endmacro()
+69
View File
@@ -0,0 +1,69 @@
# CMake provides a FindICU module since version 3.7.
# But it doesn't use pkgconfig, doesn't set expected variables,
# And it returns incomplete dependencies if only some modules are searched.
#[=======================================================================[.rst:
FindICU
-------
Finds components of the ICU library.
Accepted components are: uc, i18n, le, lx, io, data
Result Variables
^^^^^^^^^^^^^^^^
This will define the following variables:
``ICU_FOUND``
True if components of ICU library are found.
``ICU_VERSION``
The version of the ICU library which was found.
``ICU_<c>_FOUND``
True if the system has the <c> component of ICU library.
``ICU_<c>_INCLUDE_DIRS``
Include directories needed to use the <c> component of ICU library.
``ICU_<c>_LIBRARIES``
Libraries needed to link to the <c> component of ICU library.
#]=======================================================================]
find_package(PkgConfig QUIET)
set(ICU_KNOWN_COMPONENTS "uc" "i18n" "le" "lx" "io" "data")
foreach(MOD_NAME IN LISTS ICU_FIND_COMPONENTS)
if(NOT MOD_NAME IN_LIST ICU_KNOWN_COMPONENTS)
message(FATAL_ERROR "Unknown ICU component: ${MOD_NAME}")
endif()
pkg_check_modules(PC_ICU_${MOD_NAME} QUIET icu-${MOD_NAME})
# Check the libraries returned by pkg-config really exist.
unset(PC_LIBRARIES)
foreach(LIBRARY IN LISTS PC_ICU_${MOD_NAME}_LIBRARIES)
unset(PC_LIBRARY CACHE)
find_library(PC_LIBRARY NAMES ${LIBRARY})
if(NOT PC_LIBRARY)
unset(PC_ICU_${MOD_NAME}_FOUND)
endif()
list(APPEND PC_LIBRARIES ${PC_LIBRARY})
endforeach()
unset(PC_LIBRARY CACHE)
if(${PC_ICU_${MOD_NAME}_FOUND})
set(ICU_COMPONENT_FOUND TRUE)
set(ICU_${MOD_NAME}_FOUND TRUE)
set(ICU_${MOD_NAME}_LIBRARIES ${PC_LIBRARIES})
set(ICU_${MOD_NAME}_INCLUDE_DIRS ${PC_ICU_${MOD_NAME}_INCLUDE_DIRS})
set(ICU_VERSION ${PC_ICU_${MOD_NAME}_VERSION})
endif()
endforeach()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(ICU
FOUND_VAR ICU_FOUND
REQUIRED_VARS ICU_COMPONENT_FOUND
VERSION_VAR ICU_VERSION
HANDLE_COMPONENTS
)
-41
View File
@@ -1,41 +0,0 @@
include(FindPackageHandleStandardArgs)
find_library(Soxr_LIBRARY
NAMES soxr
)
include(FixVcpkgLibrary)
FixVcpkgLibrary(Soxr)
set(Soxr_COMPILE_OPTIONS "" CACHE STRING "Extra compile options of soxr")
set(Soxr_LINK_LIBRARIES "" CACHE STRING "Extra link libraries of soxr")
set(Soxr_LINK_FLAGS "" CACHE STRING "Extra link flags of soxr")
find_path(Soxr_INCLUDE_PATH
NAMES soxr.h
)
find_package_handle_standard_args(Soxr
REQUIRED_VARS Soxr_LIBRARY Soxr_INCLUDE_PATH
)
if(Soxr_FOUND)
if(NOT TARGET Soxr::soxr)
add_library(Soxr::soxr UNKNOWN IMPORTED)
set_target_properties(Soxr::soxr PROPERTIES
IMPORTED_LOCATION "${Soxr_LIBRARY}"
INTERFACE_INCLUDE_DIRECTORIES "${Soxr_INCLUDE_PATH}"
INTERFACE_COMPILE_OPTIONS "${Soxr_COMPILE_OPTIONS}"
INTERFACE_LINK_LIBRARIES "${Soxr_LINK_LIBRARIES}"
INTERFACE_LINK_FLAGS "${Soxr_LINK_FLAGS}"
)
FixVcpkgTarget(Soxr Soxr::soxr)
# Prevent undefined references in UCRT64 MinGW environment
if(MINGW AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set_property(TARGET Soxr::soxr APPEND PROPERTY INTERFACE_LINK_LIBRARIES gomp)
endif()
endif()
endif()
+31 -50
View File
@@ -190,63 +190,44 @@ elseif(UNIX)
set(CPACK_GENERATOR "TXZ")
set(PLATFORM "unknown")
else()
if(EXISTS "/etc/os-release")
file(STRINGS "/etc/os-release" OS_RELEASE_LIKE_CONTENTS REGEX "^ID_LIKE=")
if (OS_RELEASE_LIKE_CONTENTS)
string(REGEX MATCH "ID_LIKE=\\\"?([^\\\"]+)" _ ${OS_RELEASE_LIKE_CONTENTS})
string(REGEX MATCHALL "([^ ]+)" DISTRO_LIKE_IDS ${CMAKE_MATCH_1})
endif()
if (DISTRO_LIKE_IDS)
set(DISTRO_IDS ${DISTRO_LIKE_IDS})
else()
file(STRINGS "/etc/os-release" OS_RELEASE_CONTENTS REGEX "^ID=")
string(REGEX MATCH "ID=(.*)" _ ${OS_RELEASE_CONTENTS})
set(DISTRO_IDS ${CMAKE_MATCH_1})
endif()
if("arch" IN_LIST DISTRO_IDS)
set(PLATFORM "arch")
set(CPACK_GENERATOR "TXZ")
elseif("fedora" IN_LIST DISTRO_IDS OR "rhel" IN_LIST DISTRO_IDS)
set(PLATFORM "fedora")
set(CPACK_GENERATOR "RPM")
include(PackageRPM)
elseif("debian" IN_LIST DISTRO_IDS OR "ubuntu" IN_LIST DISTRO_IDS OR "linuxmint" IN_LIST DISTRO_IDS)
file(STRINGS "/etc/os-release" OS_RELEASE_CODENAME REGEX "^VERSION_CODENAME=")
string(REGEX MATCH "VERSION_CODENAME=(.*)" _ ${OS_RELEASE_CODENAME})
set(RELEASE_CODENAME ${CMAKE_MATCH_1})
string(TOLOWER "${DISTRO_ID}-${RELEASE_CODENAME}" PLATFORM)
find_program(LSB_RELEASE_EXEC lsb_release)
execute_process(COMMAND ${LSB_RELEASE_EXEC} -is
OUTPUT_VARIABLE LSB_RELEASE_ID
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if(LSB_RELEASE_ID)
if(LSB_RELEASE_ID STREQUAL "Ubuntu" OR LSB_RELEASE_ID STREQUAL "Debian" OR LSB_RELEASE_ID STREQUAL "Linuxmint")
execute_process(COMMAND ${LSB_RELEASE_EXEC} -cs
OUTPUT_VARIABLE LSB_RELEASE_CODENAME
OUTPUT_STRIP_TRAILING_WHITESPACE
)
string(TOLOWER "${LSB_RELEASE_ID}-${LSB_RELEASE_CODENAME}" PLATFORM)
set(CPACK_GENERATOR "DEB")
include(PackageDeb)
elseif(LSB_RELEASE_ID STREQUAL "Fedora")
set(PLATFORM "fedora")
set(CPACK_GENERATOR "RPM")
include(PackageRPM)
else()
set(UNSUPPORTED_PLATFORM_NAME "LSB-based Linux distribution '${LSB_RELEASE_ID}'")
endif()
elseif(EXISTS "/etc/os-release")
file(STRINGS "/etc/os-release" OS_RELEASE_CONTENTS REGEX "^ID=")
string(REGEX MATCH "ID=(.*)" _ ${OS_RELEASE_CONTENTS})
set(DISTRO_ID ${CMAKE_MATCH_1})
if(DISTRO_ID STREQUAL "arch")
set(PLATFORM "arch")
set(CPACK_GENERATOR "TXZ")
elseif(DISTRO_ID STREQUAL "fedora" OR DISTRO_ID STREQUAL "rhel")
set(PLATFORM "fedora")
set(CPACK_GENERATOR "RPM")
include(PackageRPM)
else()
set(UNSUPPORTED_PLATFORM_NAME "Linux distribution '${DISTRO_ID}' from /etc/os-release")
endif()
else()
find_program(LSB_RELEASE_EXEC lsb_release)
execute_process(COMMAND ${LSB_RELEASE_EXEC} -is
OUTPUT_VARIABLE LSB_RELEASE_ID
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if(LSB_RELEASE_ID)
if(LSB_RELEASE_ID STREQUAL "Ubuntu" OR LSB_RELEASE_ID STREQUAL "Debian" OR LSB_RELEASE_ID STREQUAL "Linuxmint")
execute_process(COMMAND ${LSB_RELEASE_EXEC} -cs
OUTPUT_VARIABLE LSB_RELEASE_CODENAME
OUTPUT_STRIP_TRAILING_WHITESPACE
)
string(TOLOWER "${LSB_RELEASE_ID}-${LSB_RELEASE_CODENAME}" PLATFORM)
set(CPACK_GENERATOR "DEB")
include(PackageDeb)
elseif(LSB_RELEASE_ID STREQUAL "Fedora")
set(PLATFORM "fedora")
set(CPACK_GENERATOR "RPM")
include(PackageRPM)
else()
set(UNSUPPORTED_PLATFORM_NAME "LSB-based Linux distribution '${LSB_RELEASE_ID}'")
endif()
else()
set(UNSUPPORTED_PLATFORM_NAME "Linux distribution")
endif()
set(UNSUPPORTED_PLATFORM_NAME "Linux distribution")
endif()
if(NOT PLATFORM)
+1 -21
View File
@@ -56,37 +56,17 @@ function(set_options)
option(OPTION_DEDICATED "Build dedicated server only (no GUI)" OFF)
option(OPTION_INSTALL_FHS "Install with Filesystem Hierarchy Standard folders" ${DEFAULT_OPTION_INSTALL_FHS})
option(OPTION_USE_ASSERTS "Use assertions; leave enabled for nightlies, betas, and RCs" ON)
option(OPTION_USE_ASSERTS "Use assertions; leave enabled for nightlies, betas, and RCs" OFF)
option(OPTION_USE_NSIS "Use NSIS to create windows installer; enable only for stable releases" OFF)
option(OPTION_TOOLS_ONLY "Build only tools target" OFF)
option(OPTION_DOCS_ONLY "Build only docs target" OFF)
option(OPTION_ALLOW_INVALID_SIGNATURE "Allow loading of content with invalid signatures" OFF)
option(OPTION_LINE_IN_DOXYGEN_WARNINGS "Print line number in doxygen warnings" ON)
if (OPTION_DOCS_ONLY)
set(OPTION_TOOLS_ONLY ON PARENT_SCOPE)
endif()
if (OPTION_LINE_IN_DOXYGEN_WARNINGS)
set(DOXYGEN_WARN_FORMAT_LINE "line" PARENT_SCOPE)
endif()
option(OPTION_SURVEY_KEY "Survey-key to use for the opt-in survey (empty if you have none)" "")
option(OPTION_DOXYGEN_WARN_FILE "File to write doxygen warnings into (if empty warnings are written to standard error)" "")
option(OPTION_DOXYGEN_GS_WARN_FILE "File to write doxygen warnings from game script docs into (if empty warnings are written to standard error)" "")
option(OPTION_DOXYGEN_AI_WARN_FILE "File to write doxygen warnings from AI docs into (if empty warnings are written to standard error)" "")
if(OPTION_DOXYGEN_WARN_FILE)
set(DOXYGEN_WARN_FILE ${CMAKE_BINARY_DIR}/${OPTION_DOXYGEN_WARN_FILE} PARENT_SCOPE)
endif()
if(OPTION_DOXYGEN_GS_WARN_FILE)
set(DOXYGEN_GS_WARN_FILE ${CMAKE_BINARY_DIR}/${OPTION_DOXYGEN_GS_WARN_FILE} PARENT_SCOPE)
endif()
if(OPTION_DOXYGEN_AI_WARN_FILE)
set(DOXYGEN_AI_WARN_FILE ${CMAKE_BINARY_DIR}/${OPTION_DOXYGEN_AI_WARN_FILE} PARENT_SCOPE)
endif()
endfunction()
# Show the values of the generic options.
+13 -23
View File
@@ -25,13 +25,6 @@ endif()
file(STRINGS ${GENERATE_SOURCE_FILE} ENUM_LINES REGEX "@enum")
function(remove_invalid_links VARIABLE)
string(REGEX REPLACE "#([A-Za-z0-9_]*Widgets)" "@hash \\1" VARIABLE "${VARIABLE}")
string(REPLACE "#" "" VARIABLE "${VARIABLE}")
string(REPLACE "@hash " "#" VARIABLE "${VARIABLE}")
set(NO_INVALID_LINKS ${VARIABLE} PARENT_SCOPE)
endfunction()
foreach(ENUM IN LISTS ENUM_LINES)
string(REGEX REPLACE "^( )// @enum ([^ ]+) ([^ ]+)@([^ ]+)@" "\\4" PLACE_HOLDER "${ENUM}")
set(ADD_INDENT "${CMAKE_MATCH_1}")
@@ -56,17 +49,14 @@ foreach(ENUM IN LISTS ENUM_LINES)
# Remember possible doxygen comment before enum declaration
if((NOT ACTIVE) AND "${LINE}" MATCHES "/\\*\\*")
remove_invalid_links("${LINE}")
set(COMMENT "${ADD_INDENT}${NO_INVALID_LINKS}")
set(COMMENT "${ADD_INDENT}${LINE}")
set(ACTIVE_COMMENT 1)
elseif(ACTIVE_COMMENT EQUAL 1)
remove_invalid_links("${LINE}")
string(APPEND COMMENT "\n${ADD_INDENT}${NO_INVALID_LINKS}")
string(APPEND COMMENT "\n${ADD_INDENT}${LINE}")
endif()
# Check for enum match
if("${LINE}" MATCHES "^ *enum *(class)? *(${ENUM_PATTERN})( *: *[^ ]*)? *\{")
set(ENUM_NAME "${CMAKE_MATCH_2}")
if("${LINE}" MATCHES "^ *enum *${ENUM_PATTERN}( *: *[^ ]*)? *\{")
# REGEX REPLACE does a REGEX MATCHALL and fails if an empty string is matched
string(REGEX MATCH "[^ ]*" RESULT "${LINE}")
string(REPLACE "${RESULT}" "" RM_INDENT "${LINE}")
@@ -110,23 +100,23 @@ foreach(ENUM IN LISTS ENUM_LINES)
endforeach()
if(CMAKE_MATCH_3)
# CMAKE_MATCH_3 contains inline comment.
remove_invalid_links("${CMAKE_MATCH_3}")
string(APPEND ${PLACE_HOLDER} "\n${ADD_INDENT}${CMAKE_MATCH_1}${CMAKE_MATCH_2}${SPACES} = to_underlying(::${ENUM_NAME}::${CMAKE_MATCH_2}),${SPACES}${NO_INVALID_LINKS}")
string(APPEND ${PLACE_HOLDER} "\n${ADD_INDENT}${CMAKE_MATCH_1}${CMAKE_MATCH_2}${SPACES} = ::${CMAKE_MATCH_2},${SPACES}${CMAKE_MATCH_3}")
else()
string(APPEND ${PLACE_HOLDER} "\n${ADD_INDENT}${CMAKE_MATCH_1}${CMAKE_MATCH_2}${SPACES} = to_underlying(::${ENUM_NAME}::${CMAKE_MATCH_2}),")
string(APPEND ${PLACE_HOLDER} "\n${ADD_INDENT}${CMAKE_MATCH_1}${CMAKE_MATCH_2}${SPACES} = ::${CMAKE_MATCH_2},")
endif()
elseif("${LINE}" STREQUAL "")
string(APPEND ${PLACE_HOLDER} "\n")
elseif("${LINE}" MATCHES "^ *\};")
string(APPEND ${PLACE_HOLDER} "\n${ADD_INDENT}${LINE}\n")
unset(ACTIVE)
else()
# Line is not an enum member, so it might be a comment.
remove_invalid_links("${LINE}")
string(APPEND ${PLACE_HOLDER} "\n${ADD_INDENT}${NO_INVALID_LINKS}")
string(APPEND ${PLACE_HOLDER} "\n${ADD_INDENT}${LINE}")
endif()
endif()
if("${LINE}" MATCHES "^ *\};")
if(ACTIVE)
string(APPEND ${PLACE_HOLDER} "\n")
endif()
unset(ACTIVE)
endif()
endforeach()
endforeach()
endforeach()
+4 -7
View File
@@ -7,14 +7,11 @@ cmake_minimum_required(VERSION 3.17)
if(NOT REGRESSION_TEST)
message(FATAL_ERROR "Script needs REGRESSION_TEST defined (tip: use -DREGRESSION_TEST=..)")
endif()
if(NOT SCRIPT_FOLDER)
message(FATAL_ERROR "Script needs SCRIPT_FOLDER defined (tip: use -DSCRIPT_FOLDER=..)")
endif()
if(NOT OPENTTD_EXECUTABLE)
message(FATAL_ERROR "Script needs OPENTTD_EXECUTABLE defined (tip: use -DOPENTTD_EXECUTABLE=..)")
endif()
if(NOT EXISTS ${SCRIPT_FOLDER}/${REGRESSION_TEST}/test.sav)
if(NOT EXISTS ai/${REGRESSION_TEST}/test.sav)
message(FATAL_ERROR "Regression test ${REGRESSION_TEST} does not exist (tip: check regression folder for the correct spelling)")
endif()
@@ -38,7 +35,7 @@ endif()
execute_process(COMMAND ${OPENTTD_EXECUTABLE}
-x
-c regression/regression.cfg
-g ${SCRIPT_FOLDER}/${REGRESSION_TEST}/test.sav
-g ai/${REGRESSION_TEST}/test.sav
-snull
-mnull
-vnull:ticks=30000
@@ -80,7 +77,7 @@ string(REGEX REPLACE "\\\[script:[0-9]\\\]" "" REGRESSION_RESULT "${REGRESSION_R
# Convert the output to a format that is expected (and more readable) by result.txt
string(REPLACE "dbg: " "ERROR: " REGRESSION_RESULT "${REGRESSION_RESULT}")
string(REGEX REPLACE "ERROR: \\\[18?\\\] " "" REGRESSION_RESULT "${REGRESSION_RESULT}")
string(REPLACE "ERROR: [1] " "" REGRESSION_RESULT "${REGRESSION_RESULT}")
string(REPLACE "[P] " "" REGRESSION_RESULT "${REGRESSION_RESULT}")
string(REPLACE "[S] " "" REGRESSION_RESULT "${REGRESSION_RESULT}")
string(REGEX REPLACE "dbg: ([^\n]*)\n?" "" REGRESSION_RESULT "${REGRESSION_RESULT}")
@@ -91,7 +88,7 @@ string(REGEX REPLACE "ERROR: [12]([^\n]*)\n?" "" REGRESSION_RESULT "${REGRESSI
string(REGEX REPLACE "ERROR: The first([^\n]*)\n?" "" REGRESSION_RESULT "${REGRESSION_RESULT}")
# Read the expected result
file(READ ${SCRIPT_FOLDER}/${REGRESSION_TEST}/result.txt REGRESSION_EXPECTED)
file(READ ai/${REGRESSION_TEST}/result.txt REGRESSION_EXPECTED)
# Convert the string to a list
string(REPLACE "\n" ";" REGRESSION_RESULT "${REGRESSION_RESULT}")
+129 -61
View File
@@ -215,10 +215,6 @@ foreach(LINE IN LISTS SOURCE_LINES)
continue()
endif()
if("${LINE}" MATCHES "^([\t ]*)\\* @suspendable.*$")
set(SUSPENDABLE TRUE)
endif()
# Ignore the comments
if("${LINE}" MATCHES "^#")
continue()
@@ -262,7 +258,7 @@ foreach(LINE IN LISTS SOURCE_LINES)
endif()
# We need to make specialized conversions for enums
if("${LINE}" MATCHES "^(\t*)enum *(class)? *([^ ]*)")
if("${LINE}" MATCHES "^(\t*)enum ([^ ]*)")
math(EXPR CLS_LEVEL "${CLS_LEVEL} + 1")
# Check if we want to publish this enum
@@ -280,10 +276,7 @@ foreach(LINE IN LISTS SOURCE_LINES)
endif()
set(IN_ENUM TRUE)
if(CMAKE_MATCH_2 STREQUAL "class")
set(IN_SCOPED_ENUM TRUE)
endif()
list(APPEND ENUMS "${CLS}::${CMAKE_MATCH_3}")
list(APPEND ENUMS "${CLS}::${CMAKE_MATCH_2}")
continue()
endif()
@@ -292,7 +285,6 @@ foreach(LINE IN LISTS SOURCE_LINES)
math(EXPR CLS_LEVEL "${CLS_LEVEL} - 1")
if(CLS_LEVEL)
unset(IN_ENUM)
unset(IN_SCOPED_ENUM)
continue()
endif()
@@ -369,86 +361,168 @@ foreach(LINE IN LISTS SOURCE_LINES)
string(APPEND SQUIRREL_EXPORT "\n")
# Enum values
macro(add_scoped_enum_end_if_needed)
if(CURRENT_ENUM_NAME)
unset(CURRENT_ENUM_NAME)
string(APPEND SQUIRREL_EXPORT "\n\tSQ${API_CLS}.AddScopedEnumEnd(engine);\n")
endif()
endmacro()
set(CURRENT_ENUM_NAME 0)
set(MLEN 0)
foreach(ENUM_VALUE IN LISTS ENUM_VALUES)
if(ENUM_VALUE MATCHES "::")
string(REGEX REPLACE ".*:" "" ENUM_VALUE_NAME "${ENUM_VALUE}")
string(REGEX MATCH "::(.*)::" ENUM_NAME "${ENUM_VALUE}")
set(ENUM_NAME ${CMAKE_MATCH_1})
if(CURRENT_ENUM_NAME STREQUAL ENUM_NAME)
else()
add_scoped_enum_end_if_needed()
string(APPEND SQUIRREL_EXPORT "\n\tSQ${API_CLS}.AddScopedEnumBegin(engine, \"${ENUM_NAME}\");")
set(CURRENT_ENUM_NAME ${ENUM_NAME})
endif()
string(APPEND SQUIRREL_EXPORT "\n\tSQ${API_CLS}.DefSQConst(engine, to_underlying(${ENUM_VALUE}), \"${ENUM_VALUE_NAME}\");")
continue()
string(LENGTH "${ENUM_VALUE}" LEN)
if(MLEN LESS LEN)
set(MLEN ${LEN})
endif()
add_scoped_enum_end_if_needed()
string(APPEND SQUIRREL_EXPORT "\n\tSQ${API_CLS}.DefSQConst(engine, ${CLS}::${ENUM_VALUE}, \"${ENUM_VALUE}\");")
endforeach()
add_scoped_enum_end_if_needed()
foreach(ENUM_VALUE IN LISTS ENUM_VALUES)
string(LENGTH "${ENUM_VALUE}" LEN)
math(EXPR LEN "${MLEN} - ${LEN}")
unset(SPACES)
foreach(i RANGE ${LEN})
string(APPEND SPACES " ")
endforeach()
string(APPEND SQUIRREL_EXPORT "\n\tSQ${API_CLS}.DefSQConst(engine, ${CLS}::${ENUM_VALUE},${SPACES}\"${ENUM_VALUE}\");")
endforeach()
if(MLEN)
string(APPEND SQUIRREL_EXPORT "\n")
endif()
# Const values
set(MLEN 0)
foreach(CONST_VALUE IN LISTS CONST_VALUES)
string(APPEND SQUIRREL_EXPORT "\n\tSQ${API_CLS}.DefSQConst(engine, ${CLS}::${CONST_VALUE}, \"${CONST_VALUE}\");")
string(LENGTH "${CONST_VALUE}" LEN)
if(MLEN LESS LEN)
set(MLEN ${LEN})
endif()
endforeach()
foreach(CONST_VALUE IN LISTS CONST_VALUES)
string(LENGTH "${CONST_VALUE}" LEN)
math(EXPR LEN "${MLEN} - ${LEN}")
unset(SPACES)
foreach(i RANGE ${LEN})
string(APPEND SPACES " ")
endforeach()
string(APPEND SQUIRREL_EXPORT "\n\tSQ${API_CLS}.DefSQConst(engine, ${CLS}::${CONST_VALUE},${SPACES}\"${CONST_VALUE}\");")
endforeach()
if(MLEN)
string(APPEND SQUIRREL_EXPORT "\n")
endif()
# Mapping of OTTD strings to errors
set(MLEN 0)
foreach(ENUM_STRING_TO_ERROR IN LISTS ENUM_STRING_TO_ERRORS)
string(REPLACE ":" ";" ENUM_STRING_TO_ERROR "${ENUM_STRING_TO_ERROR}")
list(GET ENUM_STRING_TO_ERROR 0 ENUM_STRING)
string(LENGTH "${ENUM_STRING}" LEN)
if(MLEN LESS LEN)
set(MLEN ${LEN})
endif()
endforeach()
foreach(ENUM_STRING_TO_ERROR IN LISTS ENUM_STRING_TO_ERRORS)
string(REPLACE ":" ";" ENUM_STRING_TO_ERROR "${ENUM_STRING_TO_ERROR}")
list(GET ENUM_STRING_TO_ERROR 0 ENUM_STRING)
list(GET ENUM_STRING_TO_ERROR 1 ENUM_ERROR)
string(APPEND SQUIRREL_EXPORT "\n\tScriptError::RegisterErrorMap(${ENUM_STRING}, ${CLS}::${ENUM_ERROR});")
string(LENGTH "${ENUM_STRING}" LEN)
math(EXPR LEN "${MLEN} - ${LEN}")
unset(SPACES)
foreach(i RANGE ${LEN})
string(APPEND SPACES " ")
endforeach()
string(APPEND SQUIRREL_EXPORT "\n\tScriptError::RegisterErrorMap(${ENUM_STRING},${SPACES}${CLS}::${ENUM_ERROR});")
endforeach()
if(MLEN)
string(APPEND SQUIRREL_EXPORT "\n")
endif()
# Mapping of errors to human 'readable' strings.
set(MLEN 0)
foreach(ENUM_ERROR_TO_STRING IN LISTS ENUM_ERROR_TO_STRINGS)
string(LENGTH "${ENUM_ERROR_TO_STRING}" LEN)
string(APPEND SQUIRREL_EXPORT "\n\tScriptError::RegisterErrorMapString(${CLS}::${ENUM_ERROR_TO_STRING}, \"${ENUM_ERROR_TO_STRING}\");")
if(MLEN LESS LEN)
set(MLEN ${LEN})
endif()
endforeach()
foreach(ENUM_ERROR_TO_STRING IN LISTS ENUM_ERROR_TO_STRINGS)
string(LENGTH "${ENUM_ERROR_TO_STRING}" LEN)
math(EXPR LEN "${MLEN} - ${LEN}")
unset(SPACES)
foreach(i RANGE ${LEN})
string(APPEND SPACES " ")
endforeach()
string(APPEND SQUIRREL_EXPORT "\n\tScriptError::RegisterErrorMapString(${CLS}::${ENUM_ERROR_TO_STRING},${SPACES}\"${ENUM_ERROR_TO_STRING}\");")
endforeach()
if(MLEN)
string(APPEND SQUIRREL_EXPORT "\n")
endif()
# Static methods
set(MLEN 0)
foreach(STATIC_METHOD IN LISTS STATIC_METHODS)
string(REPLACE ":" ";" STATIC_METHOD "${STATIC_METHOD}")
list(GET STATIC_METHOD 0 FUNCNAME)
string(LENGTH "${FUNCNAME}" LEN)
if(MLEN LESS LEN)
set(MLEN ${LEN})
endif()
endforeach()
foreach(STATIC_METHOD IN LISTS STATIC_METHODS)
string(REPLACE ":" ";" STATIC_METHOD "${STATIC_METHOD}")
list(GET STATIC_METHOD 0 FUNCNAME)
list(GET STATIC_METHOD 1 TYPES)
list(GET STATIC_METHOD 2 SUSPENDABLE)
if(SUSPENDABLE)
set(SUSPENDABLE ", true")
endif()
string(LENGTH "${FUNCNAME}" LEN)
math(EXPR LEN "${MLEN} - ${LEN}")
if("${TYPES}" STREQUAL "v")
string(APPEND SQUIRREL_EXPORT "\n\tSQ${API_CLS}.DefSQAdvancedStaticMethod(engine, &${CLS}::${FUNCNAME}, \"${FUNCNAME}\"${SUSPENDABLE});")
if(LEN GREATER 8)
math(EXPR LEN "${LEN} - 8")
else()
set(LEN 0)
endif()
endif()
unset(SPACES)
foreach(i RANGE ${LEN})
string(APPEND SPACES " ")
endforeach()
if("${TYPES}" STREQUAL "v")
string(APPEND SQUIRREL_EXPORT "\n\tSQ${API_CLS}.DefSQAdvancedStaticMethod(engine, &${CLS}::${FUNCNAME},${SPACES}\"${FUNCNAME}\");")
else()
string(APPEND SQUIRREL_EXPORT "\n\tSQ${API_CLS}.DefSQStaticMethod(engine, &${CLS}::${FUNCNAME}, \"${FUNCNAME}\", \"${TYPES}\"${SUSPENDABLE});")
string(APPEND SQUIRREL_EXPORT "\n\tSQ${API_CLS}.DefSQStaticMethod(engine, &${CLS}::${FUNCNAME},${SPACES}\"${FUNCNAME}\",${SPACES}\"${TYPES}\");")
endif()
endforeach()
if(MLEN)
string(APPEND SQUIRREL_EXPORT "\n")
endif()
# Non-static methods
set(MLEN 0)
foreach(METHOD IN LISTS METHODS)
string(REPLACE ":" ";" METHOD "${METHOD}")
list(GET METHOD 0 FUNCNAME)
string(LENGTH "${FUNCNAME}" LEN)
if(MLEN LESS LEN)
set(MLEN ${LEN})
endif()
endforeach()
foreach(METHOD IN LISTS METHODS)
string(REPLACE ":" ";" METHOD "${METHOD}")
list(GET METHOD 0 FUNCNAME)
list(GET METHOD 1 TYPES)
list(GET METHOD 2 SUSPENDABLE)
if(SUSPENDABLE)
set(SUSPENDABLE ", true")
endif()
string(LENGTH "${FUNCNAME}" LEN)
math(EXPR LEN "${MLEN} - ${LEN}")
if("${TYPES}" STREQUAL "v")
string(APPEND SQUIRREL_EXPORT "\n\tSQ${API_CLS}.DefSQAdvancedMethod(engine, &${CLS}::${FUNCNAME}, \"${FUNCNAME}\"${SUSPENDABLE});")
if(LEN GREATER 8)
math(EXPR LEN "${LEN} - 8")
else()
set(LEN 0)
endif()
endif()
unset(SPACES)
foreach(i RANGE ${LEN})
string(APPEND SPACES " ")
endforeach()
if("${TYPES}" STREQUAL "v")
string(APPEND SQUIRREL_EXPORT "\n\tSQ${API_CLS}.DefSQAdvancedMethod(engine, &${CLS}::${FUNCNAME},${SPACES}\"${FUNCNAME}\");")
else()
string(APPEND SQUIRREL_EXPORT "\n\tSQ${API_CLS}.DefSQMethod(engine, &${CLS}::${FUNCNAME}, \"${FUNCNAME}\", \"${TYPES}\"${SUSPENDABLE});")
string(APPEND SQUIRREL_EXPORT "\n\tSQ${API_CLS}.DefSQMethod(engine, &${CLS}::${FUNCNAME},${SPACES}\"${FUNCNAME}\",${SPACES}\"${TYPES}\");")
endif()
endforeach()
if(MLEN)
string(APPEND SQUIRREL_EXPORT "\n")
endif()
string(APPEND SQUIRREL_EXPORT "\n")
string(APPEND SQUIRREL_EXPORT "\n\tSQ${API_CLS}.PostRegister(engine);")
string(APPEND SQUIRREL_EXPORT "\n}")
@@ -468,16 +542,11 @@ foreach(LINE IN LISTS SOURCE_LINES)
# Add enums
if(IN_ENUM)
string(REGEX MATCH "([^,\t ]+)" ENUM_VALUE "${LINE}")
list(APPEND ENUM_VALUES "${ENUM_VALUE}")
# Check if this a special error enum
list(GET ENUMS -1 ENUM)
string(REGEX MATCH "([^,\t ]+)" ENUM_VALUE "${LINE}")
if(IN_SCOPED_ENUM)
list(APPEND ENUM_VALUES "${ENUM}::${ENUM_VALUE}")
else()
list(APPEND ENUM_VALUES "${ENUM_VALUE}")
endif()
if("${ENUM}" MATCHES ".*::ErrorMessages")
# syntax:
# enum ErrorMessages {
@@ -603,11 +672,10 @@ foreach(LINE IN LISTS SOURCE_LINES)
set(CLS_TYPES "${TYPES}")
elseif("${FUNCNAME}" MATCHES "^_" AND NOT "${TYPES}" STREQUAL "v")
elseif(IS_STATIC)
list(APPEND STATIC_METHODS "${FUNCNAME}:${TYPES}:${SUSPENDABLE}")
list(APPEND STATIC_METHODS "${FUNCNAME}:${TYPES}")
else()
list(APPEND METHODS "${FUNCNAME}:${TYPES}:${SUSPENDABLE}")
list(APPEND METHODS "${FUNCNAME}:${TYPES}")
endif()
unset(SUSPENDABLE)
continue()
endif()
endforeach()
+66 -66
View File
@@ -38,7 +38,7 @@ Last updated: 2024-03-26
packets are dropped in favour of a new packet.
This though will be reflected in the protocol version as announced in the
`PacketAdminType::ServerProtocol` in section 2.0).
`ADMIN_PACKET_SERVER_PROTOCOL` in section 2.0).
A reference implementation in Java for a client connecting to the admin interface
can be found at: [http://dev.openttdcoop.org/projects/joan](http://dev.openttdcoop.org/projects/joan)
@@ -49,18 +49,18 @@ Last updated: 2024-03-26
Create a TCP connection to the server on port 3977. The application is
expected to authenticate within 10 seconds.
To authenticate send either an `PacketAdminType::AdminJoin` or an
`PacketAdminType::AdminJoinSecure` packet.
To authenticate send either an `ADMIN_PACKET_ADMIN_JOIN` or an
`ADMIN_PACKET_ADMIN_JOIN_SECURE` packet.
The `PacketAdminType::AdminJoin` packet sends the password without any
The `ADMIN_PACKET_ADMIN_JOIN` packet sends the password without any
encryption or safeguards over the connection, and as such has been disabled
by default.
The `PacketAdminType::AdminJoinSecure` packet initiates a key exchange
The `ADMIN_PACKET_ADMIN_JOIN_SECURE` packet initiates a key exchange
authentication schema which tells te server which methods the client
supports and the server makes a choice. The server will then send an
`PacketAdminType::ServerAuthenticationRequest` packet to which the client has to respond
with an `PacketAdminType::AdminAuthenticationResponse` packet.
`ADMIN_PACKET_SERVER_AUTH_REQUEST` packet to which the client has to respond
with an `ADMIN_PACKET_ADMIN_AUTH_RESPONSE` packet.
The current choices for secure authentication are authorized keys, where
the client has a private key and the server a list of authorized public
@@ -69,41 +69,41 @@ Last updated: 2024-03-26
The server falls back to password authentication when the client's key is
not in the list of authorized keys.
When authentication has succeeded for either of the `AdminJoin` schemas, the
server will reply with `PacketAdminType::ServerProtocol` followed directly
by `PacketAdminType::ServerWelcome`.
When authentication has succeeded for either of the `JOIN` schemas, the
server will reply with `ADMIN_PACKET_SERVER_PROTOCOL` followed directly
by `ADMIN_PACKET_SERVER_WELCOME`.
`PacketAdminType::ServerProtocol` contains details about the protocol version.
`ADMIN_PACKET_SERVER_PROTOCOL` contains details about the protocol version.
It is the job of your application to check this number and decide whether
it will remain connected or not.
Furthermore, this packet holds details on every `AdminUpdateType` and the
supported `AdminFrequencyTypes` (bitwise representation).
`PacketAdminType::ServerWelcome` contains details on the server and the map,
`ADMIN_PACKET_SERVER_WELCOME` contains details on the server and the map,
e.g. if the server is dedicated, its NetworkLanguage, size of the Map, etc.
Once you have received `PacketAdminType::ServerWelcome` you are connected and
Once you have received `ADMIN_PACKET_SERVER_WELCOME` you are connected and
authorized to do your thing.
The server will not provide any game related updates unless you ask for them.
There are four packets the server will none the less send, if applicable:
- PacketAdminType::ServerError
- PacketAdminType::ServerWelcome
- PacketAdminType::ServerNewGame
- PacketAdminType::ServerShutdown
- ADMIN_PACKET_SERVER_ERROR
- ADMIN_PACKET_SERVER_WELCOME
- ADMIN_PACKET_SERVER_NEWGAME
- ADMIN_PACKET_SERVER_SHUTDOWN
However, `PacketAdminType::ServerWelcome` only after a `PacketAdminType::ServerNewGame`
However, `ADMIN_PACKET_SERVER_WELCOME` only after a `ADMIN_PACKET_SERVER_NEWGAME`
## 3.0) Asking for updates
Asking for updates is done with `PacketAdminType::AdminUpdateFrequency`.
Asking for updates is done with `ADMIN_PACKET_ADMIN_UPDATE_FREQUENCY`.
With this packet you define which update you wish to receive at which
frequency.
Note: not every update type supports every frequency. If in doubt, you can
verify against the data received in `PacketAdminType::ServerProtocol`.
verify against the data received in `ADMIN_PACKET_SERVER_PROTOCOL`.
Please note the potential gotcha in the "Certain packet information" section below
when using the `ADMIN_UPDATE_FREQUENCY` packet.
@@ -114,61 +114,61 @@ Last updated: 2024-03-26
Additional debug information can be found with a debug level of `net=3`.
`AdminUpdateType::Date` results in the server sending:
`ADMIN_UPDATE_DATE` results in the server sending:
- PacketAdminType::ServerDate
- ADMIN_PACKET_SERVER_DATE
`AdminUpdateType::ClientInfo` results in the server sending:
`ADMIN_UPDATE_CLIENT_INFO` results in the server sending:
- PacketAdminType::ServerClientJoin
- PacketAdminType::ServerClientInfo
- PacketAdminType::ServerClientUpdate
- PacketAdminType::ServerClientQuit
- PacketAdminType::ServerClientError
- ADMIN_PACKET_SERVER_CLIENT_JOIN
- ADMIN_PACKET_SERVER_CLIENT_INFO
- ADMIN_PACKET_SERVER_CLIENT_UPDATE
- ADMIN_PACKET_SERVER_CLIENT_QUIT
- ADMIN_PACKET_SERVER_CLIENT_ERROR
`AdminUpdateType::CompanyInfo` results in the server sending:
`ADMIN_UPDATE_COMPANY_INFO` results in the server sending:
- PacketAdminType::ServerCompanyNew
- PacketAdminType::ServerCompanyInfo
- PacketAdminType::ServerCompanyUpdate
- PacketAdminType::ServerCompanyRemove
- ADMIN_PACKET_SERVER_COMPANY_NEW
- ADMIN_PACKET_SERVER_COMPANY_INFO
- ADMIN_PACKET_SERVER_COMPANY_UPDATE
- ADMIN_PACKET_SERVER_COMPANY_REMOVE
`AdminUpdateType::CompanyEconomy` results in the server sending:
`ADMIN_UPDATE_COMPANY_ECONOMY` results in the server sending:
- PacketAdminType::ServerCompanyEconomy
- ADMIN_PACKET_SERVER_COMPANY_ECONOMY
`AdminUpdateType::CompanyStats` results in the server sending:
`ADMIN_UPDATE_COMPANY_STATS` results in the server sending:
- PacketAdminType::ServerCompanyStatistics
- ADMIN_PACKET_SERVER_COMPANY_STATS
`AdminUpdateType::Chat` results in the server sending:
`ADMIN_UPDATE_CHAT` results in the server sending:
- PacketAdminType::ServerChat
- ADMIN_PACKET_SERVER_CHAT
`AdminUpdateType::Console` results in the server sending:
`ADMIN_UPDATE_CONSOLE` results in the server sending:
- PacketAdminType::ServerConsole
- ADMIN_PACKET_SERVER_CONSOLE
`AdminUpdateType::CmdLogging` results in the server sending:
`ADMIN_UPDATE_CMD_LOGGING` results in the server sending:
- PacketAdminType::ServerCommandLogging
- ADMIN_PACKET_SERVER_CMD_LOGGING
## 3.1) Polling manually
Certain `AdminUpdateTypes` can also be polled:
- AdminUpdateType::Date
- AdminUpdateType::ClientInfo
- AdminUpdateType::CompanyInfo
- AdminUpdateType::CompanyEconomy
- AdminUpdateType::CompanyStats
- AdminUpdateType::CmdNames
- ADMIN_UPDATE_DATE
- ADMIN_UPDATE_CLIENT_INFO
- ADMIN_UPDATE_COMPANY_INFO
- ADMIN_UPDATE_COMPANY_ECONOMY
- ADMIN_UPDATE_COMPANY_STATS
- ADMIN_UPDATE_CMD_NAMES
Please note the potential gotcha in the "Certain packet information" section below
when using the `ADMIN_POLL` packet.
`AdminUpdateType::ClientInfo` and `AdminUpdateType::CompanyInfo` accept an additional
`ADMIN_UPDATE_CLIENT_INFO` and `ADMIN_UPDATE_COMPANY_INFO` accept an additional
parameter. This parameter is used to specify a certain client or company.
Setting this parameter to `UINT32_MAX (0xFFFFFFFF)` will tell the server you
want to receive updates for all clients or companies.
@@ -181,16 +181,16 @@ Last updated: 2024-03-26
## 4.0) Sending rcon commands
Rcon runs separate from the `AdminUpdateType::Console` `AdminUpdateType`. Requesting
Rcon runs separate from the `ADMIN_UPDATE_CONSOLE` `AdminUpdateType`. Requesting
the execution of a remote console command is done with the packet
`PacketAdminType::AdminRemoteConsoleCommand`.
`ADMIN_PACKET_ADMIN_RCON`.
Note: No additional authentication is required for rcon commands.
The server will reply with one or more `PacketAdminType::ServerRemoteConsoleCommand` packets.
Finally an `PacketAdminType::AdminRemoteConsoleCommandEnd` packet will be sent. Applications
The server will reply with one or more `ADMIN_PACKET_SERVER_RCON` packets.
Finally an `ADMIN_PACKET_ADMIN_RCON_END` packet will be sent. Applications
will not receive the answer twice if they have asked for the `AdminUpdateType`
`AdminUpdateType::Console`, as the result is not printed on the servers console
`ADMIN_UPDATE_CONSOLE`, as the result is not printed on the servers console
(just like clients rcon commands).
Furthermore, sending a `say` command (or any similar command) will not
@@ -199,7 +199,7 @@ Last updated: 2024-03-26
was not sent from the admin network.
Note that when content is queried or updated via rcon, the processing
happens asynchronously. But the `PacketAdminType::AdminRemoteConsoleCommandEnd` packet is sent
happens asynchronously. But the `ADMIN_PACKET_ADMIN_RCON_END` packet is sent
already right after the content is requested as there's no immediate output.
Thus other packages and the output of content rcon command may be sent at
an arbitrary later time, mixing into the output of other console activity,
@@ -208,7 +208,7 @@ Last updated: 2024-03-26
## 5.0) Sending chat
Sending a `PacketAdminType::AdminChat` results in chat originating from the server.
Sending a `ADMIN_PACKET_ADMIN_CHAT` results in chat originating from the server.
Currently four types of chat are supported:
@@ -223,7 +223,7 @@ Last updated: 2024-03-26
## 5.1) Receiving chat
Register `AdminUpdateType::Chat` at `AdminUpdateFrequency::Automatic` to receive chat.
Register `ADMIN_UPDATE_CHAT` at `AdminUpdateFrequency::Automatic` to receive chat.
The application will be able to receive all chat the server can see.
The configuration option `network.server_admin_chat` specifies whether
@@ -233,12 +233,12 @@ Last updated: 2024-03-26
## 6.0) Disconnecting
It is a kind thing to say good bye before leaving. Do this by sending the
`PacketAdminType::AdminQuit` packet.
`ADMIN_PACKET_ADMIN_QUIT` packet.
## 7.0) Certain packet information
`PacketAdminType::AdminUpdateFrequency` and `PacketAdminType::AdminPoll`
`ADMIN_PACKET_ADMIN_UPDATE_FREQUENCY` and `ADMIN_PACKET_ADMIN_POLL`
Potential gotcha: the AdminUpdateType integer type used is a
uint16 for `UPDATE_FREQUENCY`, and a uint8 for `POLL`.
@@ -246,21 +246,21 @@ Last updated: 2024-03-26
It is safe to cast between the two when sending
(i.e cast from a uint8 to a uint16).
All `PacketAdminType::Server*` packets have an enum value greater 100.
All `ADMIN_PACKET_SERVER_*` packets have an enum value greater 100.
`PacketAdminType::ServerWelcome`
`ADMIN_PACKET_SERVER_WELCOME`
Either directly follows `PacketAdminType::ServerProtocol` or is sent
Either directly follows `ADMIN_PACKET_SERVER_PROTOCOL` or is sent
after a new game has been started or a map loaded, i.e. also
after PacketAdminType::ServerNewGame.
after ADMIN_PACKET_SERVER_NEWGAME.
`PacketAdminType::ServerClientJoin` and `PacketAdminType::ServerCompanyNew`
`ADMIN_PACKET_SERVER_CLIENT_JOIN` and `ADMIN_PACKET_SERVER_COMPANY_NEW`
These packets directly follow their respective INFO packets. If you receive
a CLIENT_JOIN / COMPANY_NEW packet without having received the INFO packet
it may be a good idea to POLL for the specific ID.
`PacketAdminType::ServerCommandNames` and `PacketAdminType::ServerCommandLogging`
`ADMIN_PACKET_SERVER_CMD_NAMES` and `ADMIN_PACKET_SERVER_CMD_LOGGING`
Data provided with these packets is not stable and will not be
treated as such. Do not rely on IDs or names to be constant
-11
View File
@@ -38,17 +38,6 @@ your operating system:
It includes the OpenTTD files (grf+lng) and it will work as long as they
are not touched
7. The Atari Transport Tycoon Deluxe directory, if installed (path may vary)
This refers to the `CD` folder within the Transport Tycoon Deluxe
installation folder (2026 Atari re-release). OpenTTD detects the presence
of this folder based upon the contents of the `installpath.ini` file located
in:
- Windows: `%APPDATA%\Atari\Transport Tycoon Deluxe`
- macOS: `~/Library/Application Support/Atari/Transport Tycoon Deluxe`
- Linux: `$XDG_DATA_HOME/Atari/Transport Tycoon Deluxe`
This is used only for the loading of base sets (graphics, sound, music).
Different types of data or extensions go into different subdirectories of the
chosen main OpenTTD directory:
+95 -99
View File
@@ -16,7 +16,7 @@
<a href="landscape_grid.html">Landscape grid</a> page.
</p>
<p>Nine attributes (counting &quot;<span style="font-weight: bold;">type</span>&quot; and
&quot;<span style="font-weight: bold;">height</span>&quot;) hold the information about a tile.<br>
&quot;<span style="font-weight: bold;">height</span>&quot;) hold the information about a tile.<BR>
These attributes are referred to as
&quot;<span style="font-weight: bold;">type</span>",
&quot;<span style="font-weight: bold;">height</span>",
@@ -50,7 +50,6 @@
<tr><td><tt>0A</tt></td><td>Objects</td></tr>
</table>
</li>
<li>
Bits 3..2:
<table border="1" style="width: 30em;">
<tr bgcolor="#CCCCCC"><td colspan="2">Presence and direction of bridge above.</td></tr>
@@ -58,7 +57,6 @@
<tr><td><tt>01</tt></td><td>Axis X (North-East)</td></tr>
<tr><td><tt>02</tt></td><td>Axis Y (South-West)</td></tr>
</table>
</li>
<li>
<a name="tropic_zone"></a>
Bits 1..0:
@@ -71,14 +69,13 @@
In any other climate these 2 bits are theoretically free of use, however using them does not seem useful.
</li>
</ul>
</li>
<li><span style="font-weight: bold;">m1</span>
<ul>
<li>
<a name="WaterClass"></a>
Bits 6..5:
<table border="1" style="width: 30em;">
<tr bgcolor="#CCCCCC"><td colspan="2">The type of water that is on a tile.</td></tr>
<tr bgcolor="#CCCCCC"><td colspan="2">The type of water that is on a tile.
<tr><td style="width: 5em;"><tt>00</tt></td><td align=left>Sea</td></tr>
<tr><td><tt>01</tt></td><td align=left>Canal</td></tr>
<tr><td><tt>02</tt></td><td align=left>River</td></tr>
@@ -90,7 +87,7 @@
<a name="OwnershipInfo"></a>
Bits 4..0:
<table border="1" style="width: 30em;">
<tr bgcolor="#CCCCCC"><td colspan="2">The owner of a tile can be either companies (human or AI) or "Game entities".</td></tr>
<tr bgcolor="#CCCCCC"><td colspan="2">The owner of a tile can be either companies (human or AI) or "Game entities".
<tr><td style="width: 5em;"><tt>00..0E</tt></td><td align=left>Normal companies</td></tr>
<tr><td><tt>0F</tt></td><td align=left>a town owns the tile</td></tr>
<tr><td><tt>10</tt></td><td align=left>nobody owns the tile</td></tr>
@@ -155,8 +152,8 @@
<li>m4 bits 7..5: type of hedge on the SW border of the tile (1 through 6, or 0=none)</li>
<li>m4 bits 4..2: same as 7..5, but for the SE border</li>
<li>m5 bits 7..5: update counter, incremented on every periodic processing for tile types,
other than <tt>03</tt>, <tt>07</tt>, <tt>0B</tt>, <tt>10</tt> and above.<br>
on wraparound, the tile is updated (for fields, the type of fields in m3 is increased, for other types the tile type in m5 is increased).<br>
other than <tt>03</tt>, <tt>07</tt>, <tt>0B</tt>, <tt>10</tt> and above.<BR>
on wraparound, the tile is updated (for fields, the type of fields in m3 is increased, for other types the tile type in m5 is increased).<BR>
For snow and desert, these bits are not used, tile is updated on every periodic processing.</li>
<li>m5 bits 4..2: tile type:
<table>
@@ -393,7 +390,7 @@
</tr>
</table>
</li>
<li>m5 bit 6 set = with signals:<br>
<li>m5 bit 6 set = with signals:<BR>
There are at most 4 signals on a tile. The signals 0..3 belong to the directions:
<table>
<tr>
@@ -565,7 +562,7 @@
<td>
<ul>
<li>m2: Index into the array of towns (owning town for town roads; closest town otherwise, INVALID_TOWN if there is no town or we are creating a town)</li>
<li>m3 bits 7..4: <a href="#OwnershipInfo">owner</a> of road type 1 (tram); OWNER_NONE (<tt>10</tt>) is stored as OWNER_TOWN (<tt>0F</tt>)</li>
<li>m3 bits 7..4: <a href="#OwnershipInfo">owner</a> of road type 1 (tram); OWNER_NONE (<tt>10</tt>) is stored as OWNER_TOWN (<tt>0F</tt>)
<li>m4 bits 5..0: <a href="#RoadType">Roadtype</a></li>
<li>m7 bit 5 set = on snow or desert</li>
<li>m8 bits 11..6: <a href="#TramType">Tramtype</a></li>
@@ -724,9 +721,8 @@
</ul>
</li>
</ul>
</li>
<li>m3 bit 6 : free</li>
<li>m3 bit 5 : The house is protected by the player from the town upgrading it</li>
<li>m3 bit 5 : The house is protected from the town upgrading it</li>
<li>m3 bits 4..0 : triggers activated <a href="#newhouses">(newhouses)</a></li>
<li>m4 : free</li>
<li>m5 : see m3 bit 7</li>
@@ -1054,96 +1050,97 @@
<td>
<ul>
<li>m1 bit 7: Ship docking tile status</li>
<li>m1 bits 6..5 : Water class (sea, canal or river)</li>
<li>m1 bits 6..5 : Water class (sea, canal or river)
<li>m1 bits 4..0: <a href="#OwnershipInfo">owner</a> (for sea, rivers, and coasts normally <tt>11</tt>)</li>
<li>m2: Depot index (for depots only)</li>
<li>m3 bit 0: Non-flooding state</li>
<li>m4: Random data for canal or river tiles</li>
<li>m5 bits 7..4: Water tile type:
<table>
<tr>
<td><tt>0</tt>&nbsp; </td>
<td>water, canal or river</td>
</tr>
<tr>
<td><tt>1</tt>&nbsp; </td>
<td>coast or riverbank</td>
</tr>
<tr>
<td nowrap valign=top><tt>2</tt>&nbsp; </td>
<td>canal lock<br>
<ul>
<li>m5 bits 3..2: Lock part
<table>
<tr>
<td><tt>0</tt>&nbsp; </td>
<td>Middle part</td>
</tr>
<tr>
<td><tt>1</tt>&nbsp; </td>
<td>Lower part</td>
</tr>
<tr>
<td><tt>2</tt>&nbsp; </td>
<td>Upper part</td>
</tr>
</table>
</li>
<li>m5 bits 1..0: Lock direction
<table>
<tr>
<td><tt>0</tt>&nbsp; </td>
<td>NE raised</td>
</tr>
<tr>
<td><tt>1</tt>&nbsp; </td>
<td>SE raised</td>
</tr>
<tr>
<td><tt>2</tt>&nbsp; </td>
<td>SW raised</td>
</tr>
<tr>
<td><tt>3</tt>&nbsp; </td>
<td>NW raised</td>
</tr>
</table>
</li>
</ul>
</td>
</tr>
<tr>
<td nowrap valign=top><tt>3</tt>&nbsp; </td>
<td>depot<br>
<ul>
<li>m5 bit 1: Depot axis
<table>
<tr>
<td><tt>0</tt>&nbsp; </td>
<td>X direction (NE-SW)</td>
</tr>
<tr>
<td><tt>1</tt>&nbsp; </td>
<td>Y direction (NW-SE)</td>
</tr>
</table>
</li>
<li>m5 bit 0: Depot part
<table>
<tr>
<td><tt>0</tt>&nbsp; </td>
<td>North part</td>
</tr>
<tr>
<td><tt>1</tt>&nbsp; </td>
<td>South part</td>
</tr>
</table>
</li>
</ul>
</td>
</tr>
</table>
<tr>
<td><tt>0</tt>&nbsp; </td>
<td>water, canal or river</td>
</tr>
<tr>
<td><tt>1</tt>&nbsp; </td>
<td>coast or riverbank</td>
</tr>
<tr>
<td nowrap valign=top><tt>2</tt>&nbsp; </td>
<td>canal lock<br>
<ul>
<li>m5 bits 3..2: Lock part
<table>
<tr>
<td><tt>0</tt>&nbsp; </td>
<td>Middle part</td>
</tr>
<tr>
<td><tt>1</tt>&nbsp; </td>
<td>Lower part</td>
</tr>
<tr>
<td><tt>2</tt>&nbsp; </td>
<td>Upper part</td>
</tr>
</table>
</li>
<li>m5 bits 1..0: Lock direction
<table>
<tr>
<td><tt>0</tt>&nbsp; </td>
<td>NE raised</td>
</tr>
<tr>
<td><tt>1</tt>&nbsp; </td>
<td>SE raised</td>
</tr>
<tr>
<td><tt>2</tt>&nbsp; </td>
<td>SW raised</td>
</tr>
<tr>
<td><tt>3</tt>&nbsp; </td>
<td>NW raised</td>
</tr>
</table>
</li>
</ul>
</td>
</tr>
<tr>
<td nowrap valign=top><tt>3</tt>&nbsp; </td>
<td>depot<br>
<ul>
<li>m5 bit 1: Depot axis
<table>
<tr>
<td><tt>0</tt>&nbsp; </td>
<td>X direction (NE-SW)</td>
</tr>
<tr>
<td><tt>1</tt>&nbsp; </td>
<td>Y direction (NW-SE)</td>
</tr>
</table>
</li>
<li>m5 bit 0: Depot part
<table>
<tr>
<td><tt>0</tt>&nbsp; </td>
<td>North part</td>
</tr>
<tr>
<td><tt>1</tt>&nbsp; </td>
<td>South part</td>
</tr>
</table>
</li>
</ul>
</td>
</tr>
</table>
</li>
</li>
</ul>
</td>
@@ -1170,7 +1167,7 @@
<ul>
<li>m1 bit 7: clear = under construction
<ul>
<li>m1 bits 6..5 : Water class (sea, canal, river or land)</li>
<li>m1 bits 6..5 : Water class (sea, canal, river or land)
<li>m1 bits 3..2: construction counter, for buildings under construction incremented on every periodic tile processing</li>
<li>m1 bits 1..0: stage of construction (<tt>3</tt> = completed), incremented when the construction counter wraps around<br>
the meaning is different for some animated tiles which are never under construction (types <tt>01</tt>, <tt>1E</tt>..<tt>20</tt>, <tt>30</tt>, <tt>58</tt>; see above)</li>
@@ -1326,8 +1323,7 @@
<td nowrap valign=top><tt>58</tt>&nbsp; </td>
<td align=left>wheel tower when animated; animation state in m7 bits 5..0; m7 bit 6 set = sound already generated</td>
</tr>
</table>
</td>
</table></td>
</tr>
<tr>
+4 -4
View File
@@ -92,7 +92,7 @@ the array so you can quickly see what is used and what is not.
<tr>
<td class="caption">farmland</td>
<td class="bits"><span class="pool" title="Industry index on pool">XXXX XXXX XXXX XXXX</span></td>
<td class="bits"><span class="used" title="Type of hedge on NE border">XXX</span> <span class="used" title="Snow presence">X</span><span class="used" title="Field production stage">XXXX</span></td>
<td class="bits"><span class="used" title="Type of hedge on NE border">XXX</span> <span class="used" title="Field production stage">XXXXX</span></td>
</tr>
<tr>
<td rowspan=3>1</td>
@@ -156,7 +156,7 @@ the array so you can quickly see what is used and what is not.
<td class="caption">finished house</td>
<td class="bits" rowspan=2><span class="used" title="House random bits">XXXX XXXX</span></td>
<td class="bits" rowspan=2><span class="pool" title="Town index on pool">XXXX XXXX XXXX XXXX</span></td>
<td class="bits"><span class="used" title="House is complete/in construction (see m5)">1</span><span class="free">O</span><span class="used" title="The house is protected by the player from the town upgrading it.">X</span><span class="usable" title="Activated triggers (bits 2..4 don't have a meaning)">X XX</span><span class="used" title="Activated triggers (bits 2..4 don't have a meaning)">XX</span></td>
<td class="bits"><span class="used" title="House is complete/in construction (see m5)">1</span><span class="free">O</span><span class="used" title="The house is protected from the town upgrading it.">X</span><span class="usable" title="Activated triggers (bits 2..4 don't have a meaning)">X XX</span><span class="used" title="Activated triggers (bits 2..4 don't have a meaning)">XX</span></td>
<td class="bits" rowspan=2><span class="free">OOOO OOOO</span></td>
<td class="bits"><span class="used" title="Age in years, clamped at 255">XXXX XXXX</span></td>
<td class="bits" rowspan=2><span class="abuse" title="Newhouses activated: periodic processing time remaining; if not, lift position for houses 04 and 05">XXXX XX</span><span class="used" title="Animated tile state">XX</span></td>
@@ -165,14 +165,14 @@ the array so you can quickly see what is used and what is not.
</tr>
<tr>
<td class="caption">house under construction</td>
<td class="bits"><span class="used" title="House is complete/in construction (see m5)">O</span><span class="free">O</span><span class="used" title="The house is protected by the player from the town upgrading it.">X</span><span class="usable" title="Activated triggers (bits 2..4 don't have a meaning)">X XX</span><span class="used" title="Activated triggers (bits 2..4 don't have a meaning)">XX</span></td>
<td class="bits"><span class="used" title="House is complete/in construction (see m5)">O</span><span class="used" title="House type (m4 + m3[6])">X</span><span class="used" title="The house is protected from the town upgrading it.">X</span><span class="usable" title="Activated triggers (bits 2..4 don't have a meaning)">X XX</span><span class="used" title="Activated triggers (bits 2..4 don't have a meaning)">XX</span></td>
<td class="bits"><span class="free">OOO</span><span class="used" title="Construction stage">X X</span><span class="used" title="Construction counter">XXX</span></td>
</tr>
<tr>
<td>4</td>
<td class="caption">trees</td>
<td class="bits"><span class="free">O</span><span class="used" title="Water class">XX</span><span class="usable" title="Owner (always OWNER_NONE)">1 OOOO</span></td>
<td class="bits"><span class="free">OOOO OOO</span><span class="used" title="Tree ground">XXX</span> <span class="used" title="Tree density">XX</span> <span class="free">OOOO</span></td>
<td class="bits"><span class="free">OOOO OOO</span><span class="used" title="Tree ground">XXX</span> <span class="used" title="Tree density">XX</span> <span class="used" title="Tree counter">XXXX</span></td>
<td class="bits"><span class="usable" title="Tree type unused bits">XX</span><span class="used" title="Tree type">XX XXXX</span></td>
<td class="bits"><span class="free">OOOO OOOO</span></td>
<td class="bits"><span class="used" title="Number of trees on tile (+1)">XX</span><span class="free">OO O</span><span class="used" title="Tree growth">XXX</span></td>
+16 -16
View File
@@ -69,19 +69,19 @@ An example of a valid tag is `PLYR` when looking at it via ASCII, which contains
`[4..4]` - Next follows a byte where the lower 4 bits contain the type.
The possible valid types are:
- `0` - `ChunkType::Riff` - This chunk is a binary blob.
- `1` - `ChunkType::Array` - This chunk is a list of items.
- `2` - `ChunkType::SparseArray` - This chunk is a list of items.
- `3` - `ChunkType::Table` - This chunk is self-describing list of items.
- `4` - `ChunkType::SparseTable` - This chunk is self-describing list of items.
- `0` - `CH_RIFF` - This chunk is a binary blob.
- `1` - `CH_ARRAY` - This chunk is a list of items.
- `2` - `CH_SPARSE_ARRAY` - This chunk is a list of items.
- `3` - `CH_TABLE` - This chunk is self-describing list of items.
- `4` - `CH_SPARSE_TABLE` - This chunk is self-describing list of items.
Now per type the format is (slightly) different.
### ChunkType::Riff
### CH_RIFF
(since savegame version 295, this chunk type is only used for MAP-chunks, containing bit-information about each tile on the map)
A `ChunkType::Riff` starts with an `uint24` which together with the upper-bits of the type defines the length of the chunk.
A `CH_RIFF` starts with an `uint24` which together with the upper-bits of the type defines the length of the chunk.
In pseudo-code:
```
@@ -94,11 +94,11 @@ if type == 0
The next `length` bytes are part of the chunk.
What those bytes mean depends on the tag of the chunk; further details per chunk can be found in the source-code.
### ChunkType::Array / ChunkType::SparseArray
### CH_ARRAY / CH_SPARSE_ARRAY
(this chunk type is deprecated since savegame version 295 and is no longer in use)
`[0..G1]` - A `ChunkType::Array` / `ChunkType::SparseArray` starts with a `gamma`, indicating the size of the next item plus one.
`[0..G1]` - A `CH_ARRAY` / `CH_SPARSE_ARRAY` starts with a `gamma`, indicating the size of the next item plus one.
If this size value is zero, it indicates the end of the list.
This indicates the full length of the next item minus one.
In psuedo-code:
@@ -111,21 +111,21 @@ loop
read <size> bytes
```
`[]` - For `ChunkType::Array` there is an implicit index.
`[]` - For `CH_ARRAY` there is an implicit index.
The loop starts at zero, and every iteration adds one to the index.
For entries in the game that were not allocated, the `size` will be zero.
`[G1+1..G2]` - For `ChunkType::SparseArray` there is an explicit index.
`[G1+1..G2]` - For `CH_SPARSE_ARRAY` there is an explicit index.
The `gamma` following the size indicates the index.
The content of the item is a binary blob, and similar to `ChunkType::Riff`, it depends on the tag of the chunk what it means.
The content of the item is a binary blob, and similar to `CH_RIFF`, it depends on the tag of the chunk what it means.
Please check the source-code for further details.
### ChunkType::Table / ChunkType::SparseTable
### CH_TABLE / CH_SPARSE_TABLE
(this chunk type only exists since savegame version 295)
Both `ChunkType::Table` and `ChunkType::SparseTable` are very similar to `ChunkType::Array` / `ChunkType::SparseArray` respectively.
Both `CH_TABLE` and `CH_SPARSE_TABLE` are very similar to `CH_ARRAY` / `CH_SPARSE_ARRAY` respectively.
The only change is that the chunk starts with a header.
This header describes the chunk in details; with the header you know the meaning of each byte in the binary blob that follows.
@@ -168,7 +168,7 @@ struct | substruct3
The headers will be, in order: `table`, `substruct1`, `substruct3`, `substruct2`, each ending with a `type` is zero field.
After reading all the fields of all the headers, there is a list of records.
To read this, see `ChunkType::Array` / `ChunkType::SparseArray` for details.
To read this, see `CH_ARRAY` / `CH_SPARSE_ARRAY` for details.
As each `type` has a well defined length, you can read the records even without knowing anything about the chunk-tag yourself.
@@ -187,7 +187,7 @@ The prefix is strongly advised to avoid conflicts with future-settings in an unp
## Scripts custom data format
Script chunks (`AIPL` and `GSDT`) use `ChunkType::Table` chunk type.
Script chunks (`AIPL` and `GSDT`) use `CH_TABLE` chunk type.
At the end of each record there's an `uint8` to indicate if there's custom data (1) or not (0).
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
b198439be549299b877e97ca3b58aef1
c56aad31380c077d619e124bd87c8270
-3
View File
@@ -51,9 +51,6 @@ if(GRFCODEC_FOUND)
${CMAKE_CURRENT_SOURCE_DIR}/overlay_snowy_rocks_2.png
${CMAKE_CURRENT_SOURCE_DIR}/overlay_snowy_rocks_3.png
${CMAKE_CURRENT_SOURCE_DIR}/overlay_snowy_rocks_4.png
${CMAKE_CURRENT_SOURCE_DIR}/overlay_coastal_rocks.png
${CMAKE_CURRENT_SOURCE_DIR}/overlay_toyland_rocks.png
${CMAKE_CURRENT_SOURCE_DIR}/overlay_toyland_coastal_rocks.png
${CMAKE_CURRENT_SOURCE_DIR}/roadstops.png
${CMAKE_CURRENT_SOURCE_DIR}/road_waypoints.png
${CMAKE_CURRENT_SOURCE_DIR}/signals.png
Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

+1 -70
View File
@@ -4,8 +4,7 @@
// See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
//
-1 * 0 0C "Overlay rocks"
-1 * 0 07 83 01 \7= 03 73
-1 * 3 05 1A 72
-1 * 3 05 1A 5F
// Plain overlay rocks (unused...)
-1 sprites/overlay_rocks.png 8bpp 1 1 64 31 -31 0 normal
@@ -111,71 +110,3 @@
-1 sprites/overlay_snowy_rocks_4.png 8bpp 1281 1 64 15 -31 0 normal
-1 sprites/overlay_snowy_rocks_4.png 8bpp 1361 1 64 31 -31 -8 normal
-1 sprites/overlay_snowy_rocks_4.png 8bpp 1441 1 64 31 -31 -8 normal
// Coastal rocks
-1 sprites/overlay_coastal_rocks.png 8bpp 1 1 64 31 -31 0 normal
-1 sprites/overlay_coastal_rocks.png 8bpp 81 1 64 31 -31 0 normal
-1 sprites/overlay_coastal_rocks.png 8bpp 161 1 64 23 -31 0 normal
-1 sprites/overlay_coastal_rocks.png 8bpp 241 1 64 23 -31 0 normal
-1 sprites/overlay_coastal_rocks.png 8bpp 321 1 64 31 -31 0 normal
-1 sprites/overlay_coastal_rocks.png 8bpp 401 1 64 31 -31 0 normal
-1 sprites/overlay_coastal_rocks.png 8bpp 481 1 64 23 -31 0 normal
-1 sprites/overlay_coastal_rocks.png 8bpp 561 1 64 23 -31 0 normal
-1 sprites/overlay_coastal_rocks.png 8bpp 641 1 64 39 -31 -8 normal
-1 sprites/overlay_coastal_rocks.png 8bpp 721 1 64 39 -31 -8 normal
-1 sprites/overlay_coastal_rocks.png 8bpp 801 1 64 31 -31 -8 normal
-1 sprites/overlay_coastal_rocks.png 8bpp 881 1 64 31 -31 -8 normal
-1 sprites/overlay_coastal_rocks.png 8bpp 961 1 64 39 -31 -8 normal
-1 sprites/overlay_coastal_rocks.png 8bpp 1041 1 64 39 -31 -8 normal
-1 sprites/overlay_coastal_rocks.png 8bpp 1121 1 64 31 -31 -8 normal
-1 sprites/overlay_coastal_rocks.png 8bpp 1201 1 64 47 -31 -16 normal
-1 sprites/overlay_coastal_rocks.png 8bpp 1281 1 64 15 -31 0 normal
-1 sprites/overlay_coastal_rocks.png 8bpp 1361 1 64 31 -31 -8 normal
-1 sprites/overlay_coastal_rocks.png 8bpp 1441 1 64 31 -31 -8 normal
-1 * 6 07 83 01 \7! 03 28
-1 * 3 05 1A 13
// Toyland rocks
-1 sprites/overlay_toyland_rocks.png 8bpp 1 1 64 31 -31 0 normal
-1 sprites/overlay_toyland_rocks.png 8bpp 81 1 64 31 -31 0 normal
-1 sprites/overlay_toyland_rocks.png 8bpp 161 1 64 23 -31 0 normal
-1 sprites/overlay_toyland_rocks.png 8bpp 241 1 64 23 -31 0 normal
-1 sprites/overlay_toyland_rocks.png 8bpp 321 1 64 31 -31 0 normal
-1 sprites/overlay_toyland_rocks.png 8bpp 401 1 64 31 -31 0 normal
-1 sprites/overlay_toyland_rocks.png 8bpp 481 1 64 23 -31 0 normal
-1 sprites/overlay_toyland_rocks.png 8bpp 561 1 64 23 -31 0 normal
-1 sprites/overlay_toyland_rocks.png 8bpp 641 1 64 39 -31 -8 normal
-1 sprites/overlay_toyland_rocks.png 8bpp 721 1 64 39 -31 -8 normal
-1 sprites/overlay_toyland_rocks.png 8bpp 801 1 64 31 -31 -8 normal
-1 sprites/overlay_toyland_rocks.png 8bpp 881 1 64 31 -31 -8 normal
-1 sprites/overlay_toyland_rocks.png 8bpp 961 1 64 39 -31 -8 normal
-1 sprites/overlay_toyland_rocks.png 8bpp 1041 1 64 39 -31 -8 normal
-1 sprites/overlay_toyland_rocks.png 8bpp 1121 1 64 31 -31 -8 normal
-1 sprites/overlay_toyland_rocks.png 8bpp 1201 1 64 47 -31 -16 normal
-1 sprites/overlay_toyland_rocks.png 8bpp 1281 1 64 15 -31 0 normal
-1 sprites/overlay_toyland_rocks.png 8bpp 1361 1 64 31 -31 -8 normal
-1 sprites/overlay_toyland_rocks.png 8bpp 1441 1 64 31 -31 -8 normal
-1 * 3 05 9A 13 5F
// Toyland coastal rocks
-1 sprites/overlay_toyland_coastal_rocks.png 8bpp 1 1 64 31 -31 0 normal
-1 sprites/overlay_toyland_coastal_rocks.png 8bpp 81 1 64 31 -31 0 normal
-1 sprites/overlay_toyland_coastal_rocks.png 8bpp 161 1 64 23 -31 0 normal
-1 sprites/overlay_toyland_coastal_rocks.png 8bpp 241 1 64 23 -31 0 normal
-1 sprites/overlay_toyland_coastal_rocks.png 8bpp 321 1 64 31 -31 0 normal
-1 sprites/overlay_toyland_coastal_rocks.png 8bpp 401 1 64 31 -31 0 normal
-1 sprites/overlay_toyland_coastal_rocks.png 8bpp 481 1 64 23 -31 0 normal
-1 sprites/overlay_toyland_coastal_rocks.png 8bpp 561 1 64 23 -31 0 normal
-1 sprites/overlay_toyland_coastal_rocks.png 8bpp 641 1 64 39 -31 -8 normal
-1 sprites/overlay_toyland_coastal_rocks.png 8bpp 721 1 64 39 -31 -8 normal
-1 sprites/overlay_toyland_coastal_rocks.png 8bpp 801 1 64 31 -31 -8 normal
-1 sprites/overlay_toyland_coastal_rocks.png 8bpp 881 1 64 31 -31 -8 normal
-1 sprites/overlay_toyland_coastal_rocks.png 8bpp 961 1 64 39 -31 -8 normal
-1 sprites/overlay_toyland_coastal_rocks.png 8bpp 1041 1 64 39 -31 -8 normal
-1 sprites/overlay_toyland_coastal_rocks.png 8bpp 1121 1 64 31 -31 -8 normal
-1 sprites/overlay_toyland_coastal_rocks.png 8bpp 1201 1 64 47 -31 -16 normal
-1 sprites/overlay_toyland_coastal_rocks.png 8bpp 1281 1 64 15 -31 0 normal
-1 sprites/overlay_toyland_coastal_rocks.png 8bpp 1361 1 64 31 -31 -8 normal
-1 sprites/overlay_toyland_coastal_rocks.png 8bpp 1441 1 64 31 -31 -8 normal
Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.
+4 -1
View File
@@ -1,8 +1,11 @@
# If you change this version, change the numbers in .github/workflows/ci-emscripten.yml (2x)
# and .github/workflows/preview-build.yml (2x) too.
FROM emscripten/emsdk:6.0.1
FROM emscripten/emsdk:3.1.57
RUN apt-get update \
&& apt-get install -y gcc-12 g++-12 \
&& update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-12 100 \
&& update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-12 100 \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
-2
View File
@@ -22,5 +22,3 @@
add_subdirectory(regression)
add_subdirectory(stationlist)
add_subdirectory(gs)
add_subdirectory(gs_compat)
-8
View File
@@ -1,8 +0,0 @@
include(CreateRegression)
create_regression("game"
${CMAKE_CURRENT_SOURCE_DIR}/info.nut
${CMAKE_CURRENT_SOURCE_DIR}/main.nut
${CMAKE_CURRENT_SOURCE_DIR}/require.nut
${CMAKE_CURRENT_SOURCE_DIR}/result.txt
${CMAKE_CURRENT_SOURCE_DIR}/test.sav
)
-14
View File
@@ -1,14 +0,0 @@
class Regression extends GSInfo {
function GetAuthor() { return "OpenTTD GS Developers Team"; }
function GetName() { return "Regression"; }
function GetShortName() { return "REGR"; }
function GetDescription() { return "This runs regression-tests on some commands. On the same map the result should always be the same."; }
function GetVersion() { return 1; }
function GetAPIVersion() { return "16"; }
function GetDate() { return "2026-05-19"; }
function CreateInstance() { return "Regression"; }
function UseAsRandomAI() { return false; }
}
RegisterGS(Regression());
-83
View File
@@ -1,83 +0,0 @@
class Regression extends GSController {
function Start();
};
function Regression::TestInit()
{
print("");
print("--TestInit--");
print(" Ops: " + this.GetOpsTillSuspend());
print(" TickTest: " + this.GetTick());
this.Sleep(1);
print(" TickTest: " + this.GetTick());
print(" Ops: " + this.GetOpsTillSuspend());
print(" SetCommandDelay: " + GSController.SetCommandDelay(1));
print(" IsValid(vehicle.plane_speed): " + GSGameSettings.IsValid("vehicle.plane_speed"));
print(" vehicle.plane_speed: " + GSGameSettings.GetValue("vehicle.plane_speed"));
require("require.nut");
print(" TestEnum.value1: " + ::TestEnum.value1);
print(" test_constant: " + ::test_constant);
print(" TestEnum.value2: " + TestEnum.value2);
print(" test_constant: " + test_constant);
print(" min(6, 3): " + min(6, 3));
print(" min(3, 6): " + min(3, 6));
print(" max(6, 3): " + max(6, 3));
print(" max(3, 6): " + max(3, 6));
}
function Regression::Company()
{
print("");
print("--Company--");
/* Test GSXXXMode() in scopes */
{
local test = GSTestMode();
print(" SetName(): " + GSCompany.SetName("Regression"));
print(" SetName(): " + GSCompany.SetName("Regression"));
{
local exec = GSExecMode();
print(" SetName(): " + GSCompany.SetName("Regression"));
print(" SetName(): " + GSCompany.SetName("Regression"));
print(" GetLastErrorString(): " + GSError.GetLastErrorString());
}
}
print(" GetName(): " + GSCompany.GetName(GSCompany.COMPANY_SELF));
print(" GetPresidentName(): " + GSCompany.GetPresidentName(GSCompany.COMPANY_SELF));
print(" SetPresidentName(): " + GSCompany.SetPresidentName("Regression GS"));
print(" GetPresidentName(): " + GSCompany.GetPresidentName(GSCompany.COMPANY_SELF));
print("");
print("--CompanyMode--");
local company = GSCompanyMode(GSCompany.COMPANY_FIRST);
{
local test = GSTestMode();
print(" SetName(): " + GSCompany.SetName("Regression"));
print(" SetName(): " + GSCompany.SetName("Regression"));
{
local exec = GSExecMode();
print(" SetName(): " + GSCompany.SetName("Regression"));
print(" SetName(): " + GSCompany.SetName("Regression"));
print(" GetLastErrorString(): " + GSError.GetLastErrorString());
}
}
print(" GetName(): " + GSCompany.GetName(GSCompany.COMPANY_SELF));
print(" GetPresidentName(): " + GSCompany.GetPresidentName(GSCompany.COMPANY_SELF));
print(" SetPresidentName(): " + GSCompany.SetPresidentName("Regression GS"));
print(" GetPresidentName(): " + GSCompany.GetPresidentName(GSCompany.COMPANY_SELF));
}
function Regression::Start()
{
this.TestInit();
this.Company();
print("");
print("Done...");
print("");
}
-9
View File
@@ -1,9 +0,0 @@
print(" Required this file");
const test_constant = 1;
enum TestEnum {
value0,
value1,
value2
};
-44
View File
@@ -1,44 +0,0 @@
--TestInit--
Ops: 9988
TickTest: 1
TickTest: 2
Ops: 9990
SetCommandDelay: (null : 0x00000000)
IsValid(vehicle.plane_speed): true
vehicle.plane_speed: 4
Required this file
TestEnum.value1: 1
test_constant: 1
TestEnum.value2: 2
test_constant: 1
min(6, 3): 3
min(3, 6): 3
max(6, 3): 6
max(3, 6): 6
--Company--
SetName(): false
SetName(): false
SetName(): false
SetName(): false
GetLastErrorString(): ERR_PRECONDITION_INVALID_COMPANY
GetName(): (null : 0x00000000)
GetPresidentName(): (null : 0x00000000)
SetPresidentName(): false
GetPresidentName(): (null : 0x00000000)
--CompanyMode--
SetName(): true
SetName(): true
SetName(): true
SetName(): false
GetLastErrorString(): ERR_NAME_IS_NOT_UNIQUE
GetName(): Regression
GetPresidentName(): S. G. Bloggs
SetPresidentName(): true
GetPresidentName(): Regression GS
Done...
ERROR: The script died unexpectedly.
Binary file not shown.
-7
View File
@@ -1,7 +0,0 @@
include(CreateRegression)
create_regression("game"
${CMAKE_CURRENT_SOURCE_DIR}/info.nut
${CMAKE_CURRENT_SOURCE_DIR}/main.nut
${CMAKE_CURRENT_SOURCE_DIR}/result.txt
${CMAKE_CURRENT_SOURCE_DIR}/test.sav
)
-13
View File
@@ -1,13 +0,0 @@
class CompatRegression extends GSInfo {
function GetAuthor() { return "OpenTTD GS Developers Team"; }
function GetName() { return "Compat Regression"; }
function GetShortName() { return "REGC"; }
function GetDescription() { return "This runs regression on the compat scripts."; }
function GetVersion() { return 1; }
function GetAPIVersion() { return "1.2"; }
function GetDate() { return "2026-05-19"; }
function CreateInstance() { return "CompatRegression"; }
function UseAsRandomAI() { return false; }
}
RegisterGS(CompatRegression());
-6
View File
@@ -1,6 +0,0 @@
class CompatRegression extends GSController {
function Start()
{
print("Done...");
}
};
-2
View File
@@ -1,2 +0,0 @@
Done...
ERROR: The script died unexpectedly.
Binary file not shown.
+1 -1
View File
@@ -1,5 +1,5 @@
include(CreateRegression)
create_regression("ai"
create_regression(
${CMAKE_CURRENT_SOURCE_DIR}/info.nut
${CMAKE_CURRENT_SOURCE_DIR}/main.nut
${CMAKE_CURRENT_SOURCE_DIR}/require.nut
+1 -1
View File
@@ -4,7 +4,7 @@ class Regression extends AIInfo {
function GetShortName() { return "REGR"; }
function GetDescription() { return "This runs regression-tests on some commands. On the same map the result should always be the same."; }
function GetVersion() { return 1; }
function GetAPIVersion() { return "16"; }
function GetAPIVersion() { return "15"; }
function GetDate() { return "2007-03-18"; }
function CreateInstance() { return "Regression"; }
function UseAsRandomAI() { return false; }
+13 -325
View File
@@ -227,7 +227,7 @@ function Regression::Airport()
print(" GetAirportNumHelipads(" + i + "): " + AIAirport.GetAirportNumHelipads(i));
}
local accounting = AIAccounting();
print(" GetBankBalance(): " + AICompany.GetBankBalance(AICompany.COMPANY_SELF));
print(" GetPrice(): " + AIAirport.GetPrice(0));
print(" BuildAirport(): " + AIAirport.BuildAirport(32116, 0, AIStation.STATION_JOIN_ADJACENT));
print(" IsHangarTile(): " + AIAirport.IsHangarTile(32116));
@@ -237,13 +237,12 @@ function Regression::Airport()
print(" IsHangarTile(): " + AIAirport.IsHangarTile(32119));
print(" IsAirportTile(): " + AIAirport.IsAirportTile(32119));
print(" GetAirportType(): " + AIAirport.GetAirportType(32119));
print(" GetCosts(): " + accounting.GetCosts());
print(" GetBankBalance(): " + AICompany.GetBankBalance(AICompany.COMPANY_SELF));
accounting.ResetCosts();
print(" RemoveAirport(): " + AIAirport.RemoveAirport(32118));
print(" IsHangarTile(): " + AIAirport.IsHangarTile(32119));
print(" IsAirportTile(): " + AIAirport.IsAirportTile(32119));
print(" GetCosts(): " + accounting.GetCosts());
print(" GetBankBalance(): " + AICompany.GetBankBalance(AICompany.COMPANY_SELF));
print(" BuildAirport(): " + AIAirport.BuildAirport(32116, 0, AIStation.STATION_JOIN_ADJACENT));
}
@@ -843,7 +842,6 @@ function Regression::List()
}
list[4000] = 50;
list[4006] = 12;
list[4012] = true;
print(" foreach():");
foreach (idx, val in list) {
@@ -851,7 +849,6 @@ function Regression::List()
}
print(" []:");
print(" 4000 => " + list[4000]);
print(" 4012 => " + list[4012]);
print(" clone:");
local list3 = clone list;
@@ -868,25 +865,25 @@ function Regression::List()
}
local it = list.Begin();
print(" " + it + " => " + list.GetValue(it) + " (" + list.IsEnd() + ")");
print(" " + it + " => " + list.GetValue(it) + " (" + !list.IsEnd() + ")");
list.Sort(list.SORT_BY_VALUE, list.SORT_ASCENDING);
it = list.Next();
print(" " + it + " => " + list.GetValue(it) + " (" + list.IsEnd() + ")");
print(" " + it + " => " + list.GetValue(it) + " (" + !list.IsEnd() + ")");
it = list.Begin();
print(" " + it + " => " + list.GetValue(it) + " (" + list.IsEnd() + ")");
print(" " + it + " => " + list.GetValue(it) + " (" + !list.IsEnd() + ")");
list.SetValue(it + 1, -5);
it = list.Next();
print(" " + it + " => " + list.GetValue(it) + " (" + list.IsEnd() + ")");
print(" " + it + " => " + list.GetValue(it) + " (" + !list.IsEnd() + ")");
list.RemoveValue(list.GetValue(it) + 1);
it = list.Next();
print(" " + it + " => " + list.GetValue(it) + " (" + list.IsEnd() + ")");
print(" " + it + " => " + list.GetValue(it) + " (" + !list.IsEnd() + ")");
list.RemoveAboveValue(list.GetValue(it));
it = list.Next();
print(" " + it + " => " + list.GetValue(it) + " (" + list.IsEnd() + ")");
print(" " + it + " => " + list.GetValue(it) + " (" + !list.IsEnd() + ")");
while (!list.IsEnd()) {
it = list.Next();
@@ -898,232 +895,6 @@ function Regression::List()
print(" " + idx + " => " + val);
}
list.RemoveItem(0);
local list4 = clone list;
foreach (sorter_type in [ AIList.SORT_BY_VALUE, AIList.SORT_BY_ITEM ]) {
foreach (sorter_direction in [ AIList.SORT_DESCENDING, AIList.SORT_ASCENDING ]) {
local type = sorter_type == AIList.SORT_BY_VALUE ? "Value" : "Item";
local direction = sorter_direction == AIList.SORT_DESCENDING ? "Descending" : "Ascending";
local sorter = " (" + type + " " + direction + ")";
list = clone list4;
list.Sort(sorter_type, sorter_direction);
print("");
print(" ListDump:" + sorter);
foreach (idx, val in list) {
print(" " + idx + " => " + val);
}
it = list.Begin();
print(" Begin(): " + it + " => " + list.GetValue(it) + " (" + list.IsEnd() + ")");
it = list.Next();
print(" Next(): " + it + " => " + list.GetValue(it) + " (" + list.IsEnd() + ")");
it = list.Next();
print(" Next(): " + it + " => " + list.GetValue(it) + " (" + list.IsEnd() + ")");
it = list.Next();
print(" Next(): " + it + " => " + list.GetValue(it) + " (" + list.IsEnd() + ")");
it = list.Next();
print(" Next(): " + it + " => " + list.GetValue(it) + " (" + list.IsEnd() + ")");
print(" foreach (idx, val in list) {print}:" + sorter);
foreach (idx, val in list) {
print(" " + idx + " => " + val + " (" + list.IsEnd() + ")");
}
print(" Post loop: (" + list.IsEnd() + ")");
it = list.Next();
print(" Post loop Next: " + it + " => " + list.GetValue(it) + " (" + list.IsEnd() + ")");
it = list.Next();
print(" Post loop Next: " + it + " => " + list.GetValue(it) + " (" + list.IsEnd() + ")");
print(" for (Begin / !IsEnd / Next) {print}:" + sorter);
for (it = list.Begin(); !list.IsEnd(); it = list.Next()) {
print(" " + it + " => " + list.GetValue(it) + " (" + list.IsEnd() + ")");
}
print(" Post loop: " + it + " => " + list.GetValue(it) + " (" + list.IsEnd() + ")");
it = list.Next();
print(" Post loop Next: " + it + " => " + list.GetValue(it) + " (" + list.IsEnd() + ")");
it = list.Next();
print(" Post loop Next: " + it + " => " + list.GetValue(it) + " (" + list.IsEnd() + ")");
print(" Begin / while (!IsEnd) {print / Next}:" + sorter);
it = list.Begin();
while (!list.IsEnd()) {
print(" " + it + " => " + list.GetValue(it) + " (" + list.IsEnd() + ")");
it = list.Next();
}
print(" Post loop: " + it + " => " + list.GetValue(it) + " (" + list.IsEnd() + ")");
it = list.Next();
print(" Post loop Next: " + it + " => " + list.GetValue(it) + " (" + list.IsEnd() + ")");
it = list.Next();
print(" Post loop Next: " + it + " => " + list.GetValue(it) + " (" + list.IsEnd() + ")");
print(" Begin / do {{print / Next} while (!IsEnd)}:" + sorter);
it = list.Begin();
do {
print(" " + it + " => " + list.GetValue(it) + " (" + list.IsEnd() + ")");
it = list.Next();
} while (!list.IsEnd());
print(" Post loop: " + it + " => " + list.GetValue(it) + " (" + list.IsEnd() + ")");
it = list.Next();
print(" Post loop Next: " + it + " => " + list.GetValue(it) + " (" + list.IsEnd() + ")");
it = list.Next();
print(" Post loop Next: " + it + " => " + list.GetValue(it) + " (" + list.IsEnd() + ")");
print(" GetValue / SetValue:" + sorter);
for (it = list.Begin(); !list.IsEnd(); it = list.Next()) {
local old_val = list.GetValue(it);
local old_isend = list.IsEnd();
local res = list.SetValue(it, old_val);
local val = list.GetValue(it);
local isend = list.IsEnd();
local new_val_to_set = old_val * 1111;
local new_res = list.SetValue(it, new_val_to_set);
local new_val = list.GetValue(it);
local new_isend = list.IsEnd();
print(" " + it + " => " + old_val + " (" + old_isend + ")");
print(" => SetValue(" + it + ", " + old_val + ") ? " + res + " => " + val + " (" + isend + ")");
print(" => SetValue(" + it + ", " + new_val_to_set + ") ? " + new_res + " => " + new_val + " (" + new_isend + ")");
}
print(" Post loop: " + it + " => " + list.GetValue(it) + " (" + list.IsEnd() + ")");
it = list.Next();
print(" Post loop Next: " + it + " => " + list.GetValue(it) + " (" + list.IsEnd() + ")");
it = list.Next();
print(" Post loop Next: " + it + " => " + list.GetValue(it) + " (" + list.IsEnd() + ")");
list.Clear();
list.AddList(list4);
print(" GetValue / AddItem:" + sorter);
for (it = list.Begin(); !list.IsEnd(); it = list.Next()) {
local old_val = list.GetValue(it);
local old_isend = list.IsEnd();
list.AddItem(it, old_val);
local val = list.GetValue(it);
local isend = list.IsEnd();
local new_val_to_set = old_val * 1111;
list.AddItem(it, new_val_to_set);
local new_val = list.GetValue(it);
local new_isend = list.IsEnd();
print(" " + it + " => " + old_val + " (" + old_isend + ")");
print(" => AddItem(" + it + ", " + old_val + ") => " + val + " (" + isend + ")");
print(" => AddItem(" + it + ", " + new_val_to_set + ") => " + new_val + " (" + new_isend + ")");
}
print(" Post loop: " + it + " => " + list.GetValue(it) + " (" + list.IsEnd() + ")");
it = list.Next();
print(" Post loop Next: " + it + " => " + list.GetValue(it) + " (" + list.IsEnd() + ")");
it = list.Next();
print(" Post loop Next: " + it + " => " + list.GetValue(it) + " (" + list.IsEnd() + ")");
list.Clear();
list.AddList(list4);
print(" RemoveItem / HasItem / AddItem:" + sorter);
for (it = list.Begin(); !list.IsEnd(); it = list.Next()) {
local val = list.GetValue(it);
print(" " + it + " => " + val + " / " + list.HasItem(it) + " (" + list.IsEnd() + ")");
list.RemoveItem(it);
print(" => RemoveItem(" + it + ") => " + list.GetValue(it) + " / " + list.HasItem(it) + " (" + list.IsEnd() + ")");
if (list.IsEnd()) {
list.AddItem(it, val);
print(" => AddItem(" + it + ", " + val + ") => " + list.GetValue(it) + " / " + list.HasItem(it) + " (" + list.IsEnd() + ")");
}
}
print(" Post loop: " + it + " => " + list.GetValue(it) + " (" + list.IsEnd() + ")");
it = list.Next();
print(" Post loop Next: " + it + " => " + list.GetValue(it) + " (" + list.IsEnd() + ")");
it = list.Next();
print(" Post loop Next: " + it + " => " + list.GetValue(it) + " (" + list.IsEnd() + ")");
}
}
list.Clear(),
list.AddList(list4);
local list1 = list;
local list2 = list3;
foreach (sorter_type_1 in [ AIList.SORT_BY_VALUE, AIList.SORT_BY_ITEM ]) {
foreach (sorter_direction_1 in [ AIList.SORT_DESCENDING, AIList.SORT_ASCENDING ]) {
local type_1 = sorter_type_1 == AIList.SORT_BY_VALUE ? "Value" : "Item";
local direction_1 = sorter_direction_1 == AIList.SORT_DESCENDING ? "Descending" : "Ascending";
local sorter_1 = " (" + type_1 + " " + direction_1 + ")";
foreach (sorter_type_2 in [ AIList.SORT_BY_VALUE, AIList.SORT_BY_ITEM ]) {
foreach (sorter_direction_2 in [ AIList.SORT_DESCENDING, AIList.SORT_ASCENDING ]) {
local type_2 = sorter_type_2 == AIList.SORT_BY_VALUE ? "Value" : "Item";
local direction_2 = sorter_direction_2 == AIList.SORT_DESCENDING ? "Descending" : "Ascending";
local sorter_2 = " (" + type_2 + " " + direction_2 + ")";
local sorter = sorter_1 + sorter_2;
list1.Clear(),
list1.AddList(list4);
list1.Sort(sorter_type_1, sorter_direction_1);
list2.Sort(sorter_type_2, sorter_direction_2);
print("");
print(" SwapList:" + sorter);
print(" DumpList 1:" + sorter_1);
foreach (idx, val in list1) {
print(" " + idx + " => " + val);
}
print(" DumpList 2:" + sorter_2);
foreach (idx, val in list2) {
print(" " + idx + " => " + val);
}
local it1 = list1.Begin();
print(" List 1 Begin: " + it1 + " => " + list1.GetValue(it1) + " (" + list1.IsEnd() + ")");
local it2 = list2.Begin();
print(" List 2 Begin: " + it2 + " => " + list2.GetValue(it2) + " (" + list2.IsEnd() + ")");
it2 = list2.Next();
print(" List 2 Next: " + it2 + " => " + list2.GetValue(it2) + " (" + list2.IsEnd() + ")");
print(" => Swap list 1 with list 2 " + list1.SwapList(list2));
it1 = list1.Next();
print(" List 1 Next: " + it1 + " => " + list1.GetValue(it1) + " (" + list1.IsEnd() + ")");
it2 = list2.Next();
print(" List 2 Next: " + it2 + " => " + list2.GetValue(it2) + " (" + list2.IsEnd() + ")");
it2 = list2.Next();
print(" List 2 Next: " + it2 + " => " + list2.GetValue(it2) + " (" + list2.IsEnd() + ")");
print(" => Swap list 1 with list 2 " + list1.SwapList(list2));
it1 = list1.Next();
print(" List 1 Next: " + it1 + " => " + list1.GetValue(it1) + " (" + list1.IsEnd() + ")");
it2 = list2.Next();
print(" List 2 Next: " + it2 + " >= " + list2.GetValue(it2) + " (" + list2.IsEnd() + ")");
it2 = list2.Next();
print(" List 2 Next: " + it2 + " >= " + list2.GetValue(it2) + " (" + list2.IsEnd() + ")");
}
}
}
}
list.Clear();
print(" IsEmpty(): " + list.IsEmpty());
list2 = AIList();
for (local i = -10; i < 10; i++) {
list2.AddItem(i, -i * i / 2);
}
list.SwapList(list2);
print(" Negative ListDump:");
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
print(" " + i + " => " + list.GetValue(i));
}
print(" KeepBelowValue(-12):");
list.KeepBelowValue(-12);
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
print(" " + i + " => " + list.GetValue(i));
}
print(" KeepAboveValue(-40):");
list.KeepAboveValue(-40);
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
print(" " + i + " => " + list.GetValue(i));
}
print(" KeepValue(-24):");
list.KeepValue(-24);
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
print(" " + i + " => " + list.GetValue(i));
}
}
function Regression::Map()
@@ -1168,7 +939,7 @@ function Regression::Marine()
print(" IsLockTile(): " + AIMarine.IsLockTile(32116));
print(" IsCanalTile(): " + AIMarine.IsCanalTile(32116));
local accounting = AIAccounting();
print(" GetBankBalance(): " + AICompany.GetBankBalance(AICompany.COMPANY_SELF));
print(" BuildWaterDepot(): " + AIMarine.BuildWaterDepot(28479, 28478));
print(" BuildDock(): " + AIMarine.BuildDock(29253, AIStation.STATION_JOIN_ADJACENT));
print(" BuildBuoy(): " + AIMarine.BuildBuoy(28481));
@@ -1181,7 +952,7 @@ function Regression::Marine()
print(" IsBuoyTile(): " + AIMarine.IsBuoyTile(28481));
print(" IsLockTile(): " + AIMarine.IsLockTile(28487));
print(" IsCanalTile(): " + AIMarine.IsCanalTile(32127));
print(" GetCosts(): " + accounting.GetCosts());
print(" GetBankBalance(): " + AICompany.GetBankBalance(AICompany.COMPANY_SELF));
local list = AIWaypointList(AIWaypoint.WAYPOINT_BUOY);
print("");
@@ -1197,7 +968,6 @@ function Regression::Marine()
}
print("");
accounting.ResetCosts();
print(" RemoveWaterDepot(): " + AIMarine.RemoveWaterDepot(28479));
print(" RemoveDock(): " + AIMarine.RemoveDock(29253));
print(" RemoveBuoy(): " + AIMarine.RemoveBuoy(28481));
@@ -1208,7 +978,7 @@ function Regression::Marine()
print(" IsBuoyTile(): " + AIMarine.IsBuoyTile(28481));
print(" IsLockTile(): " + AIMarine.IsLockTile(28487));
print(" IsCanalTile(): " + AIMarine.IsCanalTile(32127));
print(" GetCosts(): " + accounting.GetCosts());
print(" GetBankBalance(): " + AICompany.GetBankBalance(AICompany.COMPANY_SELF));
print(" BuildWaterDepot(): " + AIMarine.BuildWaterDepot(28479, 28480));
print(" BuildDock(): " + AIMarine.BuildDock(29253, AIStation.STATION_JOIN_ADJACENT));
@@ -1222,7 +992,6 @@ function Regression::Order()
print("");
print("--Order--");
print(" GetOrderCount(): " + AIOrder.GetOrderCount(12));
print(" GetOrderCount(): " + AIOrder.GetOrderCount(9999));
print(" GetOrderDestination(): " + AIOrder.GetOrderDestination(12, 1));
print(" AreOrderFlagsValid(): " + AIOrder.AreOrderFlagsValid(33416, AIOrder.OF_TRANSFER));
print(" AreOrderFlagsValid(): " + AIOrder.AreOrderFlagsValid(33416, AIOrder.OF_TRANSFER | AIOrder.OF_UNLOAD));
@@ -1399,9 +1168,6 @@ function Regression::Rail()
print(" Depot");
print(" IsRailTile(): " + AIRail.IsRailTile(33411));
print(" BuildRailDepot(): " + AIRail.BuildRailDepot(0, 1));
print(" RemoveRailDepot(): " + AIRail.RemoveRailDepot(33411));
print(" BuildRailDepot(): " + AIRail.BuildRailDepot(33411, 33412));
print(" RemoveRailDepot(): " + AIRail.RemoveRailDepot(33411));
print(" BuildRailDepot(): " + AIRail.BuildRailDepot(33411, 33411));
print(" BuildRailDepot(): " + AIRail.BuildRailDepot(33411, 33410));
print(" BuildRailDepot(): " + AIRail.BuildRailDepot(33411, 33414));
@@ -2111,14 +1877,11 @@ function Regression::Vehicle()
print(" GetWagonAge(): " + AIVehicle.GetWagonAge(17, 2));
print(" GetWagonEngineType(): " + AIVehicle.GetWagonEngineType(17 3));
print(" GetWagonAge(): " + AIVehicle.GetWagonAge(17, 3));
print(" GetVehicleType(): " + AIVehicle.GetVehicleType(14));
print(" GetLength(): " + AIVehicle.GetLength(14));
print(" --Refit--");
print(" GetBuildWithRefitCapacity(): " + AIVehicle.GetBuildWithRefitCapacity(28479, 211, 255));
print(" GetBuildWithRefitCapacity(): " + AIVehicle.GetBuildWithRefitCapacity(28479, 211, 0));
print(" GetBuildWithRefitCapacity(): " + AIVehicle.GetBuildWithRefitCapacity(28479, 211, 9));
print(" GetBuildWithRefitCapacity(): " + AIVehicle.GetBuildWithRefitCapacity(28481, 211, 0));
print(" BuildVehicleWithRefit(): " + AIVehicle.BuildVehicleWithRefit(28479, 211, 9));
print(" GetCapacity(): " + AIVehicle.GetCapacity(20, 9));
print(" GetCapacity(): " + AIVehicle.GetCapacity(20, 5));
@@ -2309,81 +2072,6 @@ function Regression::PriorityQueue()
print(" Count(): " + queue.Count());
}
function Regression::Terraforming()
{
local accounting = AIAccounting();
print("");
print("--Terraforming--");
print(" DemolishTile(): " + AITile.DemolishTile(4033));
print(" DemolishTile(): " + AITile.DemolishTile(60766));
print(" GetCosts(): " + accounting.GetCosts());
accounting.ResetCosts();
print(" LowerTile(): " + AITile.LowerTile(8205, AITile.SLOPE_ENW));
print(" RaiseTile(): " + AITile.RaiseTile(8205, AITile.SLOPE_ENW));
print(" GetCosts(): " + accounting.GetCosts());
accounting.ResetCosts();
print(" LowerTile(): " + AITile.LowerTile(8205, AITile.SLOPE_ENW));
print(" GetCosts(): " + accounting.GetCosts());
accounting.ResetCosts();
print(" LowerTile(): " + AITile.LowerTile(4113, AITile.SLOPE_SW));
print(" RaiseTile(): " + AITile.RaiseTile(5902, AITile.SLOPE_NE));
print(" GetCosts(): " + accounting.GetCosts());
accounting.ResetCosts();
print(" RaiseTile(): " + AITile.RaiseTile(7958, AITile.SLOPE_SE));
print(" LowerTile(): " + AITile.LowerTile(7958, AITile.SLOPE_NE));
print(" LowerTile(): " + AITile.LowerTile(7958, AITile.SLOPE_SE));
print(" RaiseTile(): " + AITile.RaiseTile(7958, AITile.SLOPE_SE));
print(" LowerTile(): " + AITile.LowerTile(7958, AITile.SLOPE_EW));
print(" GetCosts(): " + accounting.GetCosts());
accounting.ResetCosts();
print(" LowerTile(): " + AITile.LowerTile(33924, AITile.SLOPE_ELEVATED));
print(" LowerTile(): " + AITile.LowerTile(33923, AITile.SLOPE_ELEVATED));
print(" RaiseTile(): " + AITile.RaiseTile(34193, AITile.SLOPE_ELEVATED));
print(" LowerTile(): " + AITile.LowerTile(34193, AITile.SLOPE_ELEVATED));
print(" LowerTile(): " + AITile.LowerTile(34192, AITile.SLOPE_NE));
print(" RaiseTile(): " + AITile.RaiseTile(34193, AITile.SLOPE_ELEVATED));
print(" LowerTile(): " + AITile.LowerTile(34192, AITile.SLOPE_NE));
print(" GetCosts(): " + accounting.GetCosts());
accounting.ResetCosts();
print(" RaiseTile(): " + AITile.RaiseTile(5687, AITile.SLOPE_N));
print(" LowerTile(): " + AITile.LowerTile(5687, AITile.SLOPE_SE));
print(" GetCosts(): " + accounting.GetCosts());
accounting.ResetCosts();
print(" RaiseTile(): " + AITile.RaiseTile(23596, AITile.SLOPE_NE));
print(" LowerTile(): " + AITile.LowerTile(23596, AITile.SLOPE_NE));
print(" GetCosts(): " + accounting.GetCosts());
accounting.ResetCosts();
print(" RaiseTile(): " + AITile.RaiseTile(28536, AITile.SLOPE_E));
print(" RaiseTile(): " + AITile.RaiseTile(28536, AITile.SLOPE_E));
print(" GetCosts(): " + accounting.GetCosts());
accounting.ResetCosts();
print(" LevelTiles(): " + AITile.LevelTiles(28536, 29053));
print(" LevelTiles(): " + AITile.LevelTiles(28536, 29053));
print(" GetCosts(): " + accounting.GetCosts());
accounting.ResetCosts();
print(" LevelTiles(): " + AITile.LevelTiles(22348, 24405));
print(" LevelTiles(): " + AITile.LevelTiles(27717, 29772));
print(" GetCosts(): " + accounting.GetCosts());
accounting.ResetCosts();
print(" LowerTile(): " + AITile.LowerTile(61534, AITile.SLOPE_W));
print(" RaiseTile(): " + AITile.RaiseTile(61534, AITile.SLOPE_NE));
print(" RaiseTile(): " + AITile.RaiseTile(61534, AITile.SLOPE_N));
print(" LowerTile(): " + AITile.LowerTile(61534, AITile.SLOPE_W));
print(" GetCosts(): " + accounting.GetCosts());
accounting.ResetCosts();
print(" RaiseTile(): " + AITile.RaiseTile(61534, AITile.SLOPE_N));
print(" LowerTile(): " + AITile.LowerTile(61533, AITile.SLOPE_E));
print(" LowerTile(): " + AITile.LowerTile(61534, AITile.SLOPE_E));
print(" GetCosts(): " + accounting.GetCosts());
accounting.ResetCosts();
print(" RaiseTile(): " + AITile.RaiseTile(4033, AITile.SLOPE_S));
print(" LowerTile(): " + AITile.LowerTile(4033, AITile.SLOPE_S));
print(" LowerTile(): " + AITile.LowerTile(4033, AITile.SLOPE_E));
print(" RaiseTile(): " + AITile.RaiseTile(4033, AITile.SLOPE_E));
print(" RaiseTile(): " + AITile.RaiseTile(4033, AITile.SLOPE_NWS));
print(" GetCosts(): " + accounting.GetCosts());
}
function Regression::Start()
{
this.TestInit();
@@ -2482,7 +2170,6 @@ function Regression::Start()
this.Math();
this.PriorityQueue();
this.Terraforming();
/* Check Valuate() is actually limited, MUST BE THE LAST TEST. */
print("--Valuate() with excessive CPU usage--")
@@ -2496,3 +2183,4 @@ function Regression::Start()
}
list.Valuate(Infinite);
}
+25 -848
View File
@@ -573,10 +573,8 @@
4001 => 8002
4002 => 8004
4006 => 12
4012 => 1
[]:
4000 => 50
4012 => 1
clone:
Clone ListDump:
1005 => 1005
@@ -584,779 +582,21 @@
4001 => 8002
4002 => 8004
4006 => 12
4012 => 1
IsEmpty(): true
0 => 5 (false)
0 => 5 (true)
ERROR: Next() is invalid as Begin() is never called
ERROR: IsEnd() is invalid as Begin() is never called
0 => 5 (true)
0 => 5 (false)
2 => 6 (false)
3 => 6 (false)
0 => 5 (true)
2 => 6 (true)
3 => 6 (true)
0 => 5 (false)
Clone ListDump:
1005 => 1005
4000 => 50
4001 => 8002
4002 => 8004
4006 => 12
4012 => 1
ListDump: (Value Descending)
3 => 6
2 => 6
1 => -5
Begin(): 3 => 6 (false)
Next(): 2 => 6 (false)
Next(): 1 => -5 (false)
Next(): 0 => 0 (true)
Next(): 0 => 0 (true)
foreach (idx, val in list) {print}: (Value Descending)
3 => 6 (false)
2 => 6 (false)
1 => -5 (false)
Post loop: (true)
Post loop Next: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
for (Begin / !IsEnd / Next) {print}: (Value Descending)
3 => 6 (false)
2 => 6 (false)
1 => -5 (false)
Post loop: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
Begin / while (!IsEnd) {print / Next}: (Value Descending)
3 => 6 (false)
2 => 6 (false)
1 => -5 (false)
Post loop: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
Begin / do {{print / Next} while (!IsEnd)}: (Value Descending)
3 => 6 (false)
2 => 6 (false)
1 => -5 (false)
Post loop: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
GetValue / SetValue: (Value Descending)
3 => 6 (false)
=> SetValue(3, 6) ? true => 6 (false)
=> SetValue(3, 6666) ? true => 6666 (false)
2 => 6 (false)
=> SetValue(2, 6) ? true => 6 (false)
=> SetValue(2, 6666) ? true => 6666 (false)
1 => -5 (false)
=> SetValue(1, -5) ? true => -5 (false)
=> SetValue(1, -5555) ? true => -5555 (false)
Post loop: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
GetValue / AddItem: (Value Descending)
3 => 6 (false)
=> AddItem(3, 6) => 6 (false)
=> AddItem(3, 6666) => 6 (false)
2 => 6 (false)
=> AddItem(2, 6) => 6 (false)
=> AddItem(2, 6666) => 6 (false)
1 => -5 (false)
=> AddItem(1, -5) => -5 (false)
=> AddItem(1, -5555) => -5 (false)
Post loop: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
RemoveItem / HasItem / AddItem: (Value Descending)
3 => 6 / true (false)
=> RemoveItem(3) => 0 / false (false)
2 => 6 / true (false)
=> RemoveItem(2) => 0 / false (false)
1 => -5 / true (false)
=> RemoveItem(1) => 0 / false (true)
=> AddItem(1, -5) => -5 / true (false)
Post loop: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
ListDump: (Value Ascending)
1 => -5
2 => 6
3 => 6
Begin(): 1 => -5 (false)
Next(): 2 => 6 (false)
Next(): 3 => 6 (false)
Next(): 0 => 0 (true)
Next(): 0 => 0 (true)
foreach (idx, val in list) {print}: (Value Ascending)
1 => -5 (false)
2 => 6 (false)
3 => 6 (false)
Post loop: (true)
Post loop Next: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
for (Begin / !IsEnd / Next) {print}: (Value Ascending)
1 => -5 (false)
2 => 6 (false)
3 => 6 (false)
Post loop: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
Begin / while (!IsEnd) {print / Next}: (Value Ascending)
1 => -5 (false)
2 => 6 (false)
3 => 6 (false)
Post loop: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
Begin / do {{print / Next} while (!IsEnd)}: (Value Ascending)
1 => -5 (false)
2 => 6 (false)
3 => 6 (false)
Post loop: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
GetValue / SetValue: (Value Ascending)
1 => -5 (false)
=> SetValue(1, -5) ? true => -5 (false)
=> SetValue(1, -5555) ? true => -5555 (false)
2 => 6 (false)
=> SetValue(2, 6) ? true => 6 (false)
=> SetValue(2, 6666) ? true => 6666 (false)
3 => 6 (false)
=> SetValue(3, 6) ? true => 6 (false)
=> SetValue(3, 6666) ? true => 6666 (false)
2 => 6666 (false)
=> SetValue(2, 6666) ? true => 6666 (false)
=> SetValue(2, 7405926) ? true => 7405926 (false)
3 => 6666 (false)
=> SetValue(3, 6666) ? true => 6666 (false)
=> SetValue(3, 7405926) ? true => 7405926 (false)
2 => 7405926 (false)
=> SetValue(2, 7405926) ? true => 7405926 (false)
=> SetValue(2, 8227983786) ? true => 8227983786 (false)
3 => 7405926 (false)
=> SetValue(3, 7405926) ? true => 7405926 (false)
=> SetValue(3, 8227983786) ? true => 8227983786 (false)
2 => 8227983786 (false)
=> SetValue(2, 8227983786) ? true => 8227983786 (false)
=> SetValue(2, 9141289986246) ? true => 9141289986246 (false)
3 => 8227983786 (false)
=> SetValue(3, 8227983786) ? true => 8227983786 (false)
=> SetValue(3, 9141289986246) ? true => 9141289986246 (false)
2 => 9141289986246 (false)
=> SetValue(2, 9141289986246) ? true => 9141289986246 (false)
=> SetValue(2, 10155973174719306) ? true => 10155973174719306 (false)
3 => 9141289986246 (false)
=> SetValue(3, 9141289986246) ? true => 9141289986246 (false)
=> SetValue(3, 10155973174719306) ? true => 10155973174719306 (false)
2 => 10155973174719306 (false)
=> SetValue(2, 10155973174719306) ? true => 10155973174719306 (false)
=> SetValue(2, -7163457876596402650) ? true => -7163457876596402650 (false)
3 => 10155973174719306 (false)
=> SetValue(3, 10155973174719306) ? true => 10155973174719306 (false)
=> SetValue(3, -7163457876596402650) ? true => -7163457876596402650 (false)
Post loop: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
GetValue / AddItem: (Value Ascending)
1 => -5 (false)
=> AddItem(1, -5) => -5 (false)
=> AddItem(1, -5555) => -5 (false)
2 => 6 (false)
=> AddItem(2, 6) => 6 (false)
=> AddItem(2, 6666) => 6 (false)
3 => 6 (false)
=> AddItem(3, 6) => 6 (false)
=> AddItem(3, 6666) => 6 (false)
Post loop: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
RemoveItem / HasItem / AddItem: (Value Ascending)
1 => -5 / true (false)
=> RemoveItem(1) => 0 / false (false)
2 => 6 / true (false)
=> RemoveItem(2) => 0 / false (false)
3 => 6 / true (false)
=> RemoveItem(3) => 0 / false (true)
=> AddItem(3, 6) => 6 / true (false)
Post loop: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
ListDump: (Item Descending)
3 => 6
2 => 6
1 => -5
Begin(): 3 => 6 (false)
Next(): 2 => 6 (false)
Next(): 1 => -5 (false)
Next(): 0 => 0 (true)
Next(): 0 => 0 (true)
foreach (idx, val in list) {print}: (Item Descending)
3 => 6 (false)
2 => 6 (false)
1 => -5 (false)
Post loop: (true)
Post loop Next: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
for (Begin / !IsEnd / Next) {print}: (Item Descending)
3 => 6 (false)
2 => 6 (false)
1 => -5 (false)
Post loop: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
Begin / while (!IsEnd) {print / Next}: (Item Descending)
3 => 6 (false)
2 => 6 (false)
1 => -5 (false)
Post loop: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
Begin / do {{print / Next} while (!IsEnd)}: (Item Descending)
3 => 6 (false)
2 => 6 (false)
1 => -5 (false)
Post loop: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
GetValue / SetValue: (Item Descending)
3 => 6 (false)
=> SetValue(3, 6) ? true => 6 (false)
=> SetValue(3, 6666) ? true => 6666 (false)
2 => 6 (false)
=> SetValue(2, 6) ? true => 6 (false)
=> SetValue(2, 6666) ? true => 6666 (false)
1 => -5 (false)
=> SetValue(1, -5) ? true => -5 (false)
=> SetValue(1, -5555) ? true => -5555 (false)
Post loop: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
GetValue / AddItem: (Item Descending)
3 => 6 (false)
=> AddItem(3, 6) => 6 (false)
=> AddItem(3, 6666) => 6 (false)
2 => 6 (false)
=> AddItem(2, 6) => 6 (false)
=> AddItem(2, 6666) => 6 (false)
1 => -5 (false)
=> AddItem(1, -5) => -5 (false)
=> AddItem(1, -5555) => -5 (false)
Post loop: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
RemoveItem / HasItem / AddItem: (Item Descending)
3 => 6 / true (false)
=> RemoveItem(3) => 0 / false (false)
2 => 6 / true (false)
=> RemoveItem(2) => 0 / false (false)
1 => -5 / true (false)
=> RemoveItem(1) => 0 / false (true)
=> AddItem(1, -5) => -5 / true (false)
Post loop: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
ListDump: (Item Ascending)
1 => -5
2 => 6
3 => 6
Begin(): 1 => -5 (false)
Next(): 2 => 6 (false)
Next(): 3 => 6 (false)
Next(): 0 => 0 (true)
Next(): 0 => 0 (true)
foreach (idx, val in list) {print}: (Item Ascending)
1 => -5 (false)
2 => 6 (false)
3 => 6 (false)
Post loop: (true)
Post loop Next: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
for (Begin / !IsEnd / Next) {print}: (Item Ascending)
1 => -5 (false)
2 => 6 (false)
3 => 6 (false)
Post loop: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
Begin / while (!IsEnd) {print / Next}: (Item Ascending)
1 => -5 (false)
2 => 6 (false)
3 => 6 (false)
Post loop: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
Begin / do {{print / Next} while (!IsEnd)}: (Item Ascending)
1 => -5 (false)
2 => 6 (false)
3 => 6 (false)
Post loop: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
GetValue / SetValue: (Item Ascending)
1 => -5 (false)
=> SetValue(1, -5) ? true => -5 (false)
=> SetValue(1, -5555) ? true => -5555 (false)
2 => 6 (false)
=> SetValue(2, 6) ? true => 6 (false)
=> SetValue(2, 6666) ? true => 6666 (false)
3 => 6 (false)
=> SetValue(3, 6) ? true => 6 (false)
=> SetValue(3, 6666) ? true => 6666 (false)
Post loop: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
GetValue / AddItem: (Item Ascending)
1 => -5 (false)
=> AddItem(1, -5) => -5 (false)
=> AddItem(1, -5555) => -5 (false)
2 => 6 (false)
=> AddItem(2, 6) => 6 (false)
=> AddItem(2, 6666) => 6 (false)
3 => 6 (false)
=> AddItem(3, 6) => 6 (false)
=> AddItem(3, 6666) => 6 (false)
Post loop: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
RemoveItem / HasItem / AddItem: (Item Ascending)
1 => -5 / true (false)
=> RemoveItem(1) => 0 / false (false)
2 => 6 / true (false)
=> RemoveItem(2) => 0 / false (false)
3 => 6 / true (false)
=> RemoveItem(3) => 0 / false (true)
=> AddItem(3, 6) => 6 / true (false)
Post loop: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
Post loop Next: 0 => 0 (true)
SwapList: (Value Descending) (Value Descending)
DumpList 1: (Value Descending)
3 => 6
2 => 6
1 => -5
DumpList 2: (Value Descending)
4002 => 8004
4001 => 8002
1005 => 1005
4000 => 50
4006 => 12
4012 => 1
List 1 Begin: 3 => 6 (false)
List 2 Begin: 4002 => 8004 (false)
List 2 Next: 4001 => 8002 (false)
=> Swap list 1 with list 2 (null : 0x00000000)
List 1 Next: 1005 => 1005 (false)
List 2 Next: 2 => 6 (false)
List 2 Next: 1 => -5 (false)
=> Swap list 1 with list 2 (null : 0x00000000)
List 1 Next: 0 => 0 (true)
List 2 Next: 4000 >= 50 (false)
List 2 Next: 4006 >= 12 (false)
SwapList: (Value Descending) (Value Ascending)
DumpList 1: (Value Descending)
3 => 6
2 => 6
1 => -5
DumpList 2: (Value Ascending)
4012 => 1
4006 => 12
4000 => 50
1005 => 1005
4001 => 8002
4002 => 8004
List 1 Begin: 3 => 6 (false)
List 2 Begin: 4012 => 1 (false)
List 2 Next: 4006 => 12 (false)
=> Swap list 1 with list 2 (null : 0x00000000)
List 1 Next: 4000 => 50 (false)
List 2 Next: 2 => 6 (false)
List 2 Next: 1 => -5 (false)
=> Swap list 1 with list 2 (null : 0x00000000)
List 1 Next: 0 => 0 (true)
List 2 Next: 1005 >= 1005 (false)
List 2 Next: 4001 >= 8002 (false)
SwapList: (Value Descending) (Item Descending)
DumpList 1: (Value Descending)
3 => 6
2 => 6
1 => -5
DumpList 2: (Item Descending)
4012 => 1
4006 => 12
4002 => 8004
4001 => 8002
4000 => 50
1005 => 1005
List 1 Begin: 3 => 6 (false)
List 2 Begin: 4012 => 1 (false)
List 2 Next: 4006 => 12 (false)
=> Swap list 1 with list 2 (null : 0x00000000)
List 1 Next: 4002 => 8004 (false)
List 2 Next: 2 => 6 (false)
List 2 Next: 1 => -5 (false)
=> Swap list 1 with list 2 (null : 0x00000000)
List 1 Next: 0 => 0 (true)
List 2 Next: 4001 >= 8002 (false)
List 2 Next: 4000 >= 50 (false)
SwapList: (Value Descending) (Item Ascending)
DumpList 1: (Value Descending)
3 => 6
2 => 6
1 => -5
DumpList 2: (Item Ascending)
1005 => 1005
4000 => 50
4001 => 8002
4002 => 8004
4006 => 12
4012 => 1
List 1 Begin: 3 => 6 (false)
List 2 Begin: 1005 => 1005 (false)
List 2 Next: 4000 => 50 (false)
=> Swap list 1 with list 2 (null : 0x00000000)
List 1 Next: 4001 => 8002 (false)
List 2 Next: 2 => 6 (false)
List 2 Next: 1 => -5 (false)
=> Swap list 1 with list 2 (null : 0x00000000)
List 1 Next: 0 => 0 (true)
List 2 Next: 4002 >= 8004 (false)
List 2 Next: 4006 >= 12 (false)
SwapList: (Value Ascending) (Value Descending)
DumpList 1: (Value Ascending)
1 => -5
2 => 6
3 => 6
DumpList 2: (Value Descending)
4002 => 8004
4001 => 8002
1005 => 1005
4000 => 50
4006 => 12
4012 => 1
List 1 Begin: 1 => -5 (false)
List 2 Begin: 4002 => 8004 (false)
List 2 Next: 4001 => 8002 (false)
=> Swap list 1 with list 2 (null : 0x00000000)
List 1 Next: 1005 => 1005 (false)
List 2 Next: 2 => 6 (false)
List 2 Next: 3 => 6 (false)
=> Swap list 1 with list 2 (null : 0x00000000)
List 1 Next: 0 => 0 (true)
List 2 Next: 4000 >= 50 (false)
List 2 Next: 4006 >= 12 (false)
SwapList: (Value Ascending) (Value Ascending)
DumpList 1: (Value Ascending)
1 => -5
2 => 6
3 => 6
DumpList 2: (Value Ascending)
4012 => 1
4006 => 12
4000 => 50
1005 => 1005
4001 => 8002
4002 => 8004
List 1 Begin: 1 => -5 (false)
List 2 Begin: 4012 => 1 (false)
List 2 Next: 4006 => 12 (false)
=> Swap list 1 with list 2 (null : 0x00000000)
List 1 Next: 4000 => 50 (false)
List 2 Next: 2 => 6 (false)
List 2 Next: 3 => 6 (false)
=> Swap list 1 with list 2 (null : 0x00000000)
List 1 Next: 0 => 0 (true)
List 2 Next: 1005 >= 1005 (false)
List 2 Next: 4001 >= 8002 (false)
SwapList: (Value Ascending) (Item Descending)
DumpList 1: (Value Ascending)
1 => -5
2 => 6
3 => 6
DumpList 2: (Item Descending)
4012 => 1
4006 => 12
4002 => 8004
4001 => 8002
4000 => 50
1005 => 1005
List 1 Begin: 1 => -5 (false)
List 2 Begin: 4012 => 1 (false)
List 2 Next: 4006 => 12 (false)
=> Swap list 1 with list 2 (null : 0x00000000)
List 1 Next: 4002 => 8004 (false)
List 2 Next: 2 => 6 (false)
List 2 Next: 3 => 6 (false)
=> Swap list 1 with list 2 (null : 0x00000000)
List 1 Next: 0 => 0 (true)
List 2 Next: 4001 >= 8002 (false)
List 2 Next: 4000 >= 50 (false)
SwapList: (Value Ascending) (Item Ascending)
DumpList 1: (Value Ascending)
1 => -5
2 => 6
3 => 6
DumpList 2: (Item Ascending)
1005 => 1005
4000 => 50
4001 => 8002
4002 => 8004
4006 => 12
4012 => 1
List 1 Begin: 1 => -5 (false)
List 2 Begin: 1005 => 1005 (false)
List 2 Next: 4000 => 50 (false)
=> Swap list 1 with list 2 (null : 0x00000000)
List 1 Next: 4001 => 8002 (false)
List 2 Next: 2 => 6 (false)
List 2 Next: 3 => 6 (false)
=> Swap list 1 with list 2 (null : 0x00000000)
List 1 Next: 0 => 0 (true)
List 2 Next: 4002 >= 8004 (false)
List 2 Next: 4006 >= 12 (false)
SwapList: (Item Descending) (Value Descending)
DumpList 1: (Item Descending)
3 => 6
2 => 6
1 => -5
DumpList 2: (Value Descending)
4002 => 8004
4001 => 8002
1005 => 1005
4000 => 50
4006 => 12
4012 => 1
List 1 Begin: 3 => 6 (false)
List 2 Begin: 4002 => 8004 (false)
List 2 Next: 4001 => 8002 (false)
=> Swap list 1 with list 2 (null : 0x00000000)
List 1 Next: 1005 => 1005 (false)
List 2 Next: 2 => 6 (false)
List 2 Next: 1 => -5 (false)
=> Swap list 1 with list 2 (null : 0x00000000)
List 1 Next: 0 => 0 (true)
List 2 Next: 4000 >= 50 (false)
List 2 Next: 4006 >= 12 (false)
SwapList: (Item Descending) (Value Ascending)
DumpList 1: (Item Descending)
3 => 6
2 => 6
1 => -5
DumpList 2: (Value Ascending)
4012 => 1
4006 => 12
4000 => 50
1005 => 1005
4001 => 8002
4002 => 8004
List 1 Begin: 3 => 6 (false)
List 2 Begin: 4012 => 1 (false)
List 2 Next: 4006 => 12 (false)
=> Swap list 1 with list 2 (null : 0x00000000)
List 1 Next: 4000 => 50 (false)
List 2 Next: 2 => 6 (false)
List 2 Next: 1 => -5 (false)
=> Swap list 1 with list 2 (null : 0x00000000)
List 1 Next: 0 => 0 (true)
List 2 Next: 1005 >= 1005 (false)
List 2 Next: 4001 >= 8002 (false)
SwapList: (Item Descending) (Item Descending)
DumpList 1: (Item Descending)
3 => 6
2 => 6
1 => -5
DumpList 2: (Item Descending)
4012 => 1
4006 => 12
4002 => 8004
4001 => 8002
4000 => 50
1005 => 1005
List 1 Begin: 3 => 6 (false)
List 2 Begin: 4012 => 1 (false)
List 2 Next: 4006 => 12 (false)
=> Swap list 1 with list 2 (null : 0x00000000)
List 1 Next: 4002 => 8004 (false)
List 2 Next: 2 => 6 (false)
List 2 Next: 1 => -5 (false)
=> Swap list 1 with list 2 (null : 0x00000000)
List 1 Next: 0 => 0 (true)
List 2 Next: 4001 >= 8002 (false)
List 2 Next: 4000 >= 50 (false)
SwapList: (Item Descending) (Item Ascending)
DumpList 1: (Item Descending)
3 => 6
2 => 6
1 => -5
DumpList 2: (Item Ascending)
1005 => 1005
4000 => 50
4001 => 8002
4002 => 8004
4006 => 12
4012 => 1
List 1 Begin: 3 => 6 (false)
List 2 Begin: 1005 => 1005 (false)
List 2 Next: 4000 => 50 (false)
=> Swap list 1 with list 2 (null : 0x00000000)
List 1 Next: 4001 => 8002 (false)
List 2 Next: 2 => 6 (false)
List 2 Next: 1 => -5 (false)
=> Swap list 1 with list 2 (null : 0x00000000)
List 1 Next: 0 => 0 (true)
List 2 Next: 4002 >= 8004 (false)
List 2 Next: 4006 >= 12 (false)
SwapList: (Item Ascending) (Value Descending)
DumpList 1: (Item Ascending)
1 => -5
2 => 6
3 => 6
DumpList 2: (Value Descending)
4002 => 8004
4001 => 8002
1005 => 1005
4000 => 50
4006 => 12
4012 => 1
List 1 Begin: 1 => -5 (false)
List 2 Begin: 4002 => 8004 (false)
List 2 Next: 4001 => 8002 (false)
=> Swap list 1 with list 2 (null : 0x00000000)
List 1 Next: 1005 => 1005 (false)
List 2 Next: 2 => 6 (false)
List 2 Next: 3 => 6 (false)
=> Swap list 1 with list 2 (null : 0x00000000)
List 1 Next: 0 => 0 (true)
List 2 Next: 4000 >= 50 (false)
List 2 Next: 4006 >= 12 (false)
SwapList: (Item Ascending) (Value Ascending)
DumpList 1: (Item Ascending)
1 => -5
2 => 6
3 => 6
DumpList 2: (Value Ascending)
4012 => 1
4006 => 12
4000 => 50
1005 => 1005
4001 => 8002
4002 => 8004
List 1 Begin: 1 => -5 (false)
List 2 Begin: 4012 => 1 (false)
List 2 Next: 4006 => 12 (false)
=> Swap list 1 with list 2 (null : 0x00000000)
List 1 Next: 4000 => 50 (false)
List 2 Next: 2 => 6 (false)
List 2 Next: 3 => 6 (false)
=> Swap list 1 with list 2 (null : 0x00000000)
List 1 Next: 0 => 0 (true)
List 2 Next: 1005 >= 1005 (false)
List 2 Next: 4001 >= 8002 (false)
SwapList: (Item Ascending) (Item Descending)
DumpList 1: (Item Ascending)
1 => -5
2 => 6
3 => 6
DumpList 2: (Item Descending)
4012 => 1
4006 => 12
4002 => 8004
4001 => 8002
4000 => 50
1005 => 1005
List 1 Begin: 1 => -5 (false)
List 2 Begin: 4012 => 1 (false)
List 2 Next: 4006 => 12 (false)
=> Swap list 1 with list 2 (null : 0x00000000)
List 1 Next: 4002 => 8004 (false)
List 2 Next: 2 => 6 (false)
List 2 Next: 3 => 6 (false)
=> Swap list 1 with list 2 (null : 0x00000000)
List 1 Next: 0 => 0 (true)
List 2 Next: 4001 >= 8002 (false)
List 2 Next: 4000 >= 50 (false)
SwapList: (Item Ascending) (Item Ascending)
DumpList 1: (Item Ascending)
1 => -5
2 => 6
3 => 6
DumpList 2: (Item Ascending)
1005 => 1005
4000 => 50
4001 => 8002
4002 => 8004
4006 => 12
4012 => 1
List 1 Begin: 1 => -5 (false)
List 2 Begin: 1005 => 1005 (false)
List 2 Next: 4000 => 50 (false)
=> Swap list 1 with list 2 (null : 0x00000000)
List 1 Next: 4001 => 8002 (false)
List 2 Next: 2 => 6 (false)
List 2 Next: 3 => 6 (false)
=> Swap list 1 with list 2 (null : 0x00000000)
List 1 Next: 0 => 0 (true)
List 2 Next: 4002 >= 8004 (false)
List 2 Next: 4006 >= 12 (false)
IsEmpty(): true
Negative ListDump:
1 => 0
0 => 0
-1 => 0
2 => -2
-2 => -2
3 => -4
-3 => -4
4 => -8
-4 => -8
5 => -12
-5 => -12
6 => -18
-6 => -18
7 => -24
-7 => -24
8 => -32
-8 => -32
9 => -40
-9 => -40
-10 => -50
KeepBelowValue(-12):
6 => -18
-6 => -18
7 => -24
-7 => -24
8 => -32
-8 => -32
9 => -40
-9 => -40
-10 => -50
KeepAboveValue(-40):
6 => -18
-6 => -18
7 => -24
-7 => -24
8 => -32
-8 => -32
KeepValue(-24):
7 => -24
-7 => -24
--Company--
SetName(): true
@@ -1643,6 +883,7 @@ ERROR: IsEnd() is invalid as Begin() is never called
GetAirportHeight(9): -1
GetAirportCoverageRadius(9): -1
GetAirportNumHelipads(9): -1
GetBankBalance(): 1999999790
GetPrice(): 5400
BuildAirport(): true
IsHangarTile(): false
@@ -1652,11 +893,11 @@ ERROR: IsEnd() is invalid as Begin() is never called
IsHangarTile(): true
IsAirportTile(): true
GetAirportType(): 0
GetCosts(): 9900
GetBankBalance(): 1999989890
RemoveAirport(): true
IsHangarTile(): false
IsAirportTile(): false
GetCosts(): 264
GetBankBalance(): 1999989626
BuildAirport(): true
--Bridge--
@@ -8412,6 +7653,7 @@ ERROR: IsEnd() is invalid as Begin() is never called
IsBuoyTile(): false
IsLockTile(): false
IsCanalTile(): false
GetBankBalance(): 1999979304
BuildWaterDepot(): true
BuildDock(): true
BuildBuoy(): true
@@ -8424,7 +7666,7 @@ ERROR: IsEnd() is invalid as Begin() is never called
IsBuoyTile(): true
IsLockTile(): true
IsCanalTile(): true
GetCosts(): 14624
GetBankBalance(): 1999964680
--AIWaypointList(BUOY)--
Count(): 1
@@ -8443,7 +7685,7 @@ ERROR: IsEnd() is invalid as Begin() is never called
IsBuoyTile(): false
IsLockTile(): false
IsCanalTile(): false
GetCosts(): 5395
GetBankBalance(): 1999959285
BuildWaterDepot(): true
BuildDock(): true
BuildBuoy(): true
@@ -8554,9 +7796,6 @@ ERROR: IsEnd() is invalid as Begin() is never called
Depot
IsRailTile(): false
BuildRailDepot(): false
RemoveRailDepot(): false
BuildRailDepot(): true
RemoveRailDepot(): true
BuildRailDepot(): false
BuildRailDepot(): true
BuildRailDepot(): true
@@ -10539,9 +9778,9 @@ ERROR: IsEnd() is invalid as Begin() is never called
GetLocation(): 33417
GetEngineType(): 153
GetUnitNumber(): 1
GetAge(): 0
GetAge(): 1
GetMaxAge(): 5490
GetAgeLeft(): 5490
GetAgeLeft(): 5489
GetCurrentSpeed(): 7
GetRunningCost(): 421
GetProfitThisYear(): 0
@@ -10554,7 +9793,7 @@ ERROR: IsEnd() is invalid as Begin() is never called
IsInDepot(): false
GetNumWagons(): 1
GetWagonEngineType(): 153
GetWagonAge(): 0
GetWagonAge(): 1
GetLength(): 8
GetOwner(): 1
BuildVehicle(): 14
@@ -10586,13 +9825,10 @@ ERROR: IsEnd() is invalid as Begin() is never called
GetWagonAge(): 0
GetWagonEngineType(): 65535
GetWagonAge(): -1
GetVehicleType(): 3
GetLength(): -1
--Refit--
GetBuildWithRefitCapacity(): -1
GetBuildWithRefitCapacity(): 0
GetBuildWithRefitCapacity(): 160
GetBuildWithRefitCapacity(): -1
BuildVehicleWithRefit(): 20
GetCapacity(): 160
GetCapacity(): 0
@@ -10632,11 +9868,11 @@ ERROR: IsEnd() is invalid as Begin() is never called
14 => 1
12 => 1
Age ListDump:
14 => 1
13 => 1
12 => 1
17 => 0
16 => 0
14 => 0
13 => 0
MaxAge ListDump:
16 => 10980
14 => 10980
@@ -10645,9 +9881,9 @@ ERROR: IsEnd() is invalid as Begin() is never called
12 => 5490
AgeLeft ListDump:
16 => 10980
14 => 10979
14 => 10980
17 => 7320
13 => 5489
13 => 5490
12 => 5489
CurrentSpeed ListDump:
12 => 27
@@ -10666,7 +9902,7 @@ ERROR: IsEnd() is invalid as Begin() is never called
16 => 0
14 => 0
13 => 0
12 => -1
12 => 0
ProfitLastYear ListDump:
17 => 0
16 => 0
@@ -10706,7 +9942,6 @@ ERROR: IsEnd() is invalid as Begin() is never called
--Order--
GetOrderCount(): 0
GetOrderCount(): -1
GetOrderDestination(): -1
AreOrderFlagsValid(): true
AreOrderFlagsValid(): false
@@ -10877,73 +10112,15 @@ ERROR: IsEnd() is invalid as Begin() is never called
Clear(): (null : 0x00000000)
IsEmpty(): true
Count(): 0
--Terraforming--
DemolishTile(): true
DemolishTile(): true
GetCosts(): 120
LowerTile(): false
RaiseTile(): true
GetCosts(): 60561
LowerTile(): true
GetCosts(): 561
LowerTile(): true
RaiseTile(): true
GetCosts(): 30958
RaiseTile(): false
LowerTile(): false
LowerTile(): true
RaiseTile(): true
LowerTile(): true
GetCosts(): 2478
LowerTile(): false
LowerTile(): true
RaiseTile(): false
LowerTile(): true
LowerTile(): false
RaiseTile(): true
LowerTile(): true
GetCosts(): 5551
RaiseTile(): true
LowerTile(): true
GetCosts(): 16055
RaiseTile(): false
LowerTile(): true
GetCosts(): 2076
RaiseTile(): true
RaiseTile(): true
GetCosts(): 10222
LevelTiles(): true
LevelTiles(): false
GetCosts(): 9628
LevelTiles(): true
LevelTiles(): true
GetCosts(): 286079
LowerTile(): false
RaiseTile(): true
RaiseTile(): false
LowerTile(): true
GetCosts(): 6099
RaiseTile(): true
LowerTile(): true
LowerTile(): false
GetCosts(): 1167
RaiseTile(): false
LowerTile(): true
LowerTile(): false
RaiseTile(): false
RaiseTile(): true
GetCosts(): 38996
--Valuate() with excessive CPU usage--
constructor failed with: excessive CPU usage in list filter function
Your script made an error: excessive CPU usage in valuator function
CALLSTACK WITH LOCALS
*FUNCTION [Valuate()] Valuate line [5]
[args] ARRAY
[this] INSTANCE
*FUNCTION [Start()] regression/main.nut line [2497]
[Infinite] CLOSURE
[list] INSTANCE
[this] INSTANCE
CALLSTACK
*FUNCTION [Start()] regression/main.nut line [2184]
LOCALS
[Infinite] CLOSURE
[list] INSTANCE
[this] INSTANCE
ERROR: The script died unexpectedly.
+1 -1
View File
@@ -1,5 +1,5 @@
include(CreateRegression)
create_regression("ai"
create_regression(
${CMAKE_CURRENT_SOURCE_DIR}/info.nut
${CMAKE_CURRENT_SOURCE_DIR}/main.nut
${CMAKE_CURRENT_SOURCE_DIR}/result.txt
+1 -1
View File
@@ -4,7 +4,7 @@ class StationList extends AIInfo {
function GetShortName() { return "REGS"; }
function GetDescription() { return "This runs stationlist-tests on some commands. On the same map the result should always be the same."; }
function GetVersion() { return 1; }
function GetAPIVersion() { return "16"; }
function GetAPIVersion() { return "15"; }
function GetDate() { return "2007-03-18"; }
function CreateInstance() { return "StationList"; }
function UseAsRandomAI() { return false; }
+1 -1
View File
@@ -3,5 +3,5 @@ add_subdirectory(tests)
add_files(
scriptrun.cpp
scriptrun.h
CONDITION ICU_I18N_FOUND
CONDITION ICU_i18n_FOUND
)
+1 -1
View File
@@ -152,7 +152,7 @@ UBool ScriptRun::next()
// if it's an open character, push it onto the stack.
// if it's a close character, find the matching open on the
// stack, and use that script code. Any non-matching open
// characters above it on the stack will be popped.
// characters above it on the stack will be poped.
if (pairIndex >= 0) {
if ((pairIndex & 1) == 0) {
parenStack[++parenSP].pairIndex = pairIndex;
+1 -1
View File
@@ -1,4 +1,4 @@
add_test_files(
test_srtest.cpp
CONDITION ICU_I18N_FOUND
CONDITION ICU_i18n_FOUND
)
+24 -18
View File
@@ -19,7 +19,7 @@ void sqstd_printcallstack(HSQUIRRELVM v)
SQInteger level=1; //1 is to skip this function that is level 0
SQInteger seq=0;
pf(v,"\n");
pf(v,"CALLSTACK WITH LOCALS\n");
pf(v,"CALLSTACK\n");
while(SQ_SUCCEEDED(sq_stackinfos(v,level,&si)))
{
std::string_view fn="unknown";
@@ -35,6 +35,13 @@ void sqstd_printcallstack(HSQUIRRELVM v)
src = (p == std::string_view::npos) ? si.source : si.source.substr(p + 4);
}
pf(v,fmt::format("*FUNCTION [{}()] {} line [{}]\n",fn,src,si.line));
level++;
}
level=0;
pf(v,"\n");
pf(v,"LOCALS\n");
for(level=0;level<10;level++){
seq=0;
std::optional<std::string_view> opt;
while ((opt = sq_getlocal(v,level,seq)).has_value()) {
@@ -43,65 +50,64 @@ void sqstd_printcallstack(HSQUIRRELVM v)
switch(sq_gettype(v,-1))
{
case OT_NULL:
pf(v,fmt::format(" [{}] NULL\n",name));
pf(v,fmt::format("[{}] NULL\n",name));
break;
case OT_INTEGER:
sq_getinteger(v,-1,&i);
pf(v,fmt::format(" [{}] {}\n",name,i));
pf(v,fmt::format("[{}] {}\n",name,i));
break;
case OT_FLOAT:
sq_getfloat(v,-1,&f);
pf(v,fmt::format(" [{}] {:14g}\n",name,f));
pf(v,fmt::format("[{}] {:14g}\n",name,f));
break;
case OT_USERPOINTER:
pf(v,fmt::format(" [{}] USERPOINTER\n",name));
pf(v,fmt::format("[{}] USERPOINTER\n",name));
break;
case OT_STRING: {
std::string_view view;
sq_getstring(v,-1,view);
pf(v,fmt::format(" [{}] \"{}\"\n",name,view));
pf(v,fmt::format("[{}] \"{}\"\n",name,view));
break;
}
case OT_TABLE:
pf(v,fmt::format(" [{}] TABLE\n",name));
pf(v,fmt::format("[{}] TABLE\n",name));
break;
case OT_ARRAY:
pf(v,fmt::format(" [{}] ARRAY\n",name));
pf(v,fmt::format("[{}] ARRAY\n",name));
break;
case OT_CLOSURE:
pf(v,fmt::format(" [{}] CLOSURE\n",name));
pf(v,fmt::format("[{}] CLOSURE\n",name));
break;
case OT_NATIVECLOSURE:
pf(v,fmt::format(" [{}] NATIVECLOSURE\n",name));
pf(v,fmt::format("[{}] NATIVECLOSURE\n",name));
break;
case OT_GENERATOR:
pf(v,fmt::format(" [{}] GENERATOR\n",name));
pf(v,fmt::format("[{}] GENERATOR\n",name));
break;
case OT_USERDATA:
pf(v,fmt::format(" [{}] USERDATA\n",name));
pf(v,fmt::format("[{}] USERDATA\n",name));
break;
case OT_THREAD:
pf(v,fmt::format(" [{}] THREAD\n",name));
pf(v,fmt::format("[{}] THREAD\n",name));
break;
case OT_CLASS:
pf(v,fmt::format(" [{}] CLASS\n",name));
pf(v,fmt::format("[{}] CLASS\n",name));
break;
case OT_INSTANCE:
pf(v,fmt::format(" [{}] INSTANCE\n",name));
pf(v,fmt::format("[{}] INSTANCE\n",name));
break;
case OT_WEAKREF:
pf(v,fmt::format(" [{}] WEAKREF\n",name));
pf(v,fmt::format("[{}] WEAKREF\n",name));
break;
case OT_BOOL:{
sq_getbool(v,-1,&b);
pf(v,fmt::format(" [{}] {}\n",name,b?"true":"false"));
pf(v,fmt::format("[{}] {}\n",name,b?"true":"false"));
}
break;
default: assert(0); break;
}
sq_pop(v,1);
}
level++;
}
}
}
+3 -3
View File
@@ -472,7 +472,7 @@ SQRESULT sq_setroottable(HSQUIRRELVM v)
v->Pop();
return SQ_OK;
}
return sq_throwerror(v, "invalid type");
return sq_throwerror(v, "ivalid type");
}
SQRESULT sq_setconsttable(HSQUIRRELVM v)
@@ -483,7 +483,7 @@ SQRESULT sq_setconsttable(HSQUIRRELVM v)
v->Pop();
return SQ_OK;
}
return sq_throwerror(v, "invalid type, expected table");
return sq_throwerror(v, "ivalid type, expected table");
}
void sq_setforeignptr(HSQUIRRELVM v,SQUserPointer p)
@@ -796,7 +796,7 @@ SQRESULT sq_setdelegate(HSQUIRRELVM v,SQInteger idx)
switch(type) {
case OT_TABLE:
if(type(mt) == OT_TABLE) {
if(!_table(self)->SetDelegate(_table(mt))) return sq_throwerror(v, "delegate cycle");
if(!_table(self)->SetDelegate(_table(mt))) return sq_throwerror(v, "delagate cycle");
v->Pop();}
else if(type(mt)==OT_NULL) {
_table(self)->SetDelegate(nullptr); v->Pop(); }
+1 -1
View File
@@ -554,7 +554,7 @@ bool _hsort_sift_down(HSQUIRRELVM v,SQArray *arr, SQInteger root, SQInteger bott
if (ret < 0) {
if (root == maxChild) {
v->Raise_Error("inconsistent compare function");
return false; // We'd be swapping ourself. The compare function is incorrect
return false; // We'd be swapping ourselve. The compare function is incorrect
}
_Swap(arr->_values[root],arr->_values[maxChild]);
root = maxChild;
+1 -1
View File
@@ -245,7 +245,7 @@ bool SafeWrite(HSQUIRRELVM v,SQWRITEFUNC write,SQUserPointer up,SQUserPointer de
bool SafeRead(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,SQUserPointer dest,SQInteger size)
{
if(size && read(up,dest,size) != size) {
v->Raise_Error("io error, read function failure, the origin stream could be corrupted/truncated");
v->Raise_Error("io error, read function failure, the origin stream could be corrupted/trucated");
return false;
}
return true;
+2 -2
View File
@@ -193,7 +193,7 @@ SQSharedState::~SQSharedState()
t = nx;
}
}
// assert(_gc_chain==nullptr); //just to prove a theory
// assert(_gc_chain==nullptr); //just to proove a theory
while(_gc_chain){
_gc_chain->_uiRef--;
_gc_chain->Release();
@@ -227,7 +227,7 @@ SQInteger SQSharedState::GetMetaMethodIdxByName(const SQObjectPtr &name)
* This is done internally by a vector onto which the to be freed instances are pushed. When
* this is called when not already processing, this method will actually call the FinalFree
* function which might cause more elements to end up in the queue which this method then
* picks up continuing until it has processed all instances in that queue.
* picks up continueing until it has processed all instances in that queue.
* @param collectable The collectable to (eventually) free.
*/
void SQSharedState::DelayFinalFree(SQCollectable *collectable)
+1 -1
View File
@@ -424,7 +424,7 @@ bool SQVM::Return(SQInteger _arg0, SQInteger _arg1, SQObjectPtr &retval)
else retval = _null_;
}
else {
if(target != -1) { //-1 is when a class constructor ret value has to be ignored
if(target != -1) { //-1 is when a class contructor ret value has to be ignored
if (_arg0 != MAX_FUNC_STACKSIZE)
STK(target) = _stack._vals[oldstackbase+_arg1];
else
+2 -14
View File
@@ -37,7 +37,7 @@ add_files(
add_files(
gfx_layout_icu.cpp
gfx_layout_icu.h
CONDITION ICU_I18N_FOUND AND HARFBUZZ_FOUND
CONDITION ICU_i18n_FOUND AND HARFBUZZ_FOUND
)
add_files(
@@ -50,11 +50,6 @@ add_files(
CONDITION OpusFile_FOUND
)
add_files(
soundresampler_soxr.cpp
CONDITION Soxr_FOUND
)
add_files(
aircraft.h
aircraft_cmd.cpp
@@ -138,13 +133,11 @@ add_files(
crashlog.cpp
crashlog.h
currency.cpp
currency_func.h
currency_type.h
currency.h
date_gui.cpp
date_gui.h
debug.cpp
debug.h
debug_type.h
dedicated.cpp
depot.cpp
depot_base.h
@@ -216,7 +209,6 @@ add_files(
goal_base.h
goal_cmd.h
goal_gui.cpp
goal_gui.h
goal_type.h
graph_gui.cpp
graph_gui.h
@@ -342,7 +334,6 @@ add_files(
newgrf_town.h
newgrf_townname.cpp
newgrf_townname.h
newgrf_type.h
news_cmd.h
news_func.h
news_gui.cpp
@@ -406,8 +397,6 @@ add_files(
roadveh_cmd.h
roadveh_gui.cpp
safeguards.h
screensaver.cpp
screensaver.h
screenshot_bmp.cpp
screenshot_gui.cpp
screenshot_gui.h
@@ -459,7 +448,6 @@ add_files(
soundloader_type.h
soundloader_raw.cpp
soundloader_wav.cpp
soundresampler_type.h
source_type.h
sprite.cpp
sprite.h
+8 -14
View File
@@ -10,7 +10,7 @@
#ifndef AI_HPP
#define AI_HPP
#include "../script/api/script_event.hpp"
#include "../script/api/script_event_types.hpp"
#include "ai_scanner.hpp"
/**
@@ -37,7 +37,6 @@ public:
/**
* Get the current AI tick.
* @return The tick number.
*/
static uint GetTick();
@@ -98,35 +97,30 @@ public:
/**
* Queue a new event for an AI.
* @param company The company to receive the event.
* @param event The event.
*/
static void NewEvent(CompanyID company, ScriptEvent *event);
/**
* Broadcast a new event to all active AIs.
* @param event The event to broadcast.
* @param skip_company The optional company not to send the event to.
*/
static void BroadcastNewEvent(ScriptEvent *event, CompanyID skip_company = CompanyID::Invalid());
/**
* Save data from an AI to a savegame.
* @param company To company to save.
*/
static void Save(CompanyID company);
/** @copydoc ScriptScanner::GetConsoleList */
/** Wrapper function for AIScanner::GetAIConsoleList */
static void GetConsoleList(std::back_insert_iterator<std::string> &output_iterator, bool newest_only);
/** @copydoc ScriptScanner::GetConsoleList */
static void GetConsoleLibraryList(std::back_insert_iterator<std::string> &output_iterator, bool newest_only);
/** @copydoc ScriptScanner::GetInfoList */
/** Wrapper function for AIScanner::GetAIConsoleLibraryList */
static void GetConsoleLibraryList(std::back_insert_iterator<std::string> &output_iterator);
/** Wrapper function for AIScanner::GetAIInfoList */
static const ScriptInfoList *GetInfoList();
/** @copydoc ScriptScanner::GetUniqueInfoList */
/** Wrapper function for AIScanner::GetUniqueAIInfoList */
static const ScriptInfoList *GetUniqueInfoList();
/** @copydoc ScriptConfig::FindInfo */
/** Wrapper function for AIScanner::FindInfo */
static class AIInfo *FindInfo(const std::string &name, int version, bool force_exact_match);
/** @copydoc ScriptInstance::FindLibrary */
/** Wrapper function for AIScanner::FindLibrary */
static class AILibrary *FindLibrary(const std::string &library, int version);
/**
+3 -3
View File
@@ -21,14 +21,14 @@
{
assert(company < MAX_COMPANIES);
if (source == ScriptSettingSource::Default && _game_mode == GameMode::Menu) source = ScriptSettingSource::ForceNewGame;
if (source == SSS_DEFAULT && _game_mode == GM_MENU) source = SSS_FORCE_NEWGAME;
if (source == ScriptSettingSource::Default) {
if (source == SSS_DEFAULT) {
Company *c = Company::GetIfValid(company);
if (c != nullptr && c->ai_config != nullptr) return c->ai_config.get();
}
auto &config = (source == ScriptSettingSource::ForceNewGame) ? _settings_newgame.script_config.ai[company] : _settings_game.script_config.ai[company];
auto &config = (source == SSS_FORCE_NEWGAME) ? _settings_newgame.script_config.ai[company] : _settings_game.script_config.ai[company];
if (config == nullptr) config = std::make_unique<AIConfig>();
return config.get();
+2 -11
View File
@@ -13,30 +13,21 @@
#include "../script/script_config.hpp"
#include "../company_type.h"
/** AI instantion of script configuration. */
class AIConfig : public ScriptConfig {
public:
/**
* Get the AI configuration of specific company.
* @param company The company to get the configuration for.
* @param source The context, i.e. current / new game mode.
* @return The configuration.
* Get the config of a company.
*/
static AIConfig *GetConfig(CompanyID company, ScriptSettingSource source = ScriptSettingSource::Default);
static AIConfig *GetConfig(CompanyID company, ScriptSettingSource source = SSS_DEFAULT);
AIConfig() :
ScriptConfig()
{}
/**
* Copy constructor.
* @param config The configuration to copy.
*/
AIConfig(const AIConfig &config) :
ScriptConfig(config)
{}
/** @copydoc ScriptConfig::GetInfo. */
class AIInfo *GetInfo() const;
/**
+40 -48
View File
@@ -40,12 +40,12 @@
/* Clients shouldn't start AIs */
if (_networking && !_network_server) return;
AutoRestoreBackup cur_company(_current_company, company);
Backup<CompanyID> cur_company(_current_company, company);
Company *c = Company::Get(company);
AIConfig *config = c->ai_config.get();
if (config == nullptr) {
c->ai_config = std::make_unique<AIConfig>(*AIConfig::GetConfig(company, AIConfig::ScriptSettingSource::ForceCurrentGame));
c->ai_config = std::make_unique<AIConfig>(*AIConfig::GetConfig(company, AIConfig::SSS_FORCE_GAME));
config = c->ai_config.get();
}
@@ -65,18 +65,10 @@
c->ai_instance->LoadOnStack(config->GetToLoadData());
config->SetToLoadData(nullptr);
InvalidateWindowClassesData(WindowClass::ScriptDebug, -1);
return;
}
cur_company.Restore();
/**
* Get the \c PerformanceElement for the AI of the given company.
* @param company The company to get the PerformanceElement for.
* @return The \c PerformanceElement.
*/
static constexpr PerformanceElement GetAIPerformanceElement(CompanyID company)
{
return static_cast<PerformanceElement>(PerformanceElement::AI0 + company);
InvalidateWindowClassesData(WC_SCRIPT_DEBUG, -1);
return;
}
/* static */ void AI::GameLoop()
@@ -89,10 +81,11 @@ static constexpr PerformanceElement GetAIPerformanceElement(CompanyID company)
assert(_settings_game.difficulty.competitor_speed <= 4);
if ((AI::frame_counter & ((1 << (4 - _settings_game.difficulty.competitor_speed)) - 1)) != 0) return;
Backup<CompanyID> cur_company(_current_company);
for (const Company *c : Company::Iterate()) {
if (c->is_ai) {
PerformanceMeasurer framerate(GetAIPerformanceElement(c->index));
AutoRestoreBackup cur_company(_current_company, c->index);
PerformanceMeasurer framerate((PerformanceElement)(PFE_AI0 + c->index));
cur_company.Change(c->index);
c->ai_instance->GameLoop();
/* Occasionally collect garbage; every 255 ticks do one company.
* Effectively collecting garbage once every two months per AI. */
@@ -100,9 +93,10 @@ static constexpr PerformanceElement GetAIPerformanceElement(CompanyID company)
c->ai_instance->CollectGarbage();
}
} else {
PerformanceMeasurer::SetInactive(GetAIPerformanceElement(c->index));
PerformanceMeasurer::SetInactive((PerformanceElement)(PFE_AI0 + c->index));
}
}
cur_company.Restore();
}
/* static */ uint AI::GetTick()
@@ -113,16 +107,18 @@ static constexpr PerformanceElement GetAIPerformanceElement(CompanyID company)
/* static */ void AI::Stop(CompanyID company)
{
if (_networking && !_network_server) return;
PerformanceMeasurer::SetInactive(GetAIPerformanceElement(company));
PerformanceMeasurer::SetInactive((PerformanceElement)(PFE_AI0 + company));
AutoRestoreBackup cur_company(_current_company, company);
Backup<CompanyID> cur_company(_current_company, company);
Company *c = Company::Get(company);
c->ai_instance.reset();
c->ai_info = nullptr;
c->ai_config.reset();
InvalidateWindowClassesData(WindowClass::ScriptDebug, -1);
cur_company.Restore();
InvalidateWindowClassesData(WC_SCRIPT_DEBUG, -1);
}
/* static */ void AI::Pause(CompanyID company)
@@ -132,20 +128,28 @@ static constexpr PerformanceElement GetAIPerformanceElement(CompanyID company)
* for the server owner to unpause the script again. */
if (_network_dedicated) return;
AutoRestoreBackup cur_company(_current_company, company);
Backup<CompanyID> cur_company(_current_company, company);
Company::Get(company)->ai_instance->Pause();
cur_company.Restore();
}
/* static */ void AI::Unpause(CompanyID company)
{
AutoRestoreBackup cur_company(_current_company, company);
Backup<CompanyID> cur_company(_current_company, company);
Company::Get(company)->ai_instance->Unpause();
cur_company.Restore();
}
/* static */ bool AI::IsPaused(CompanyID company)
{
AutoRestoreBackup cur_company(_current_company, company);
return Company::Get(company)->ai_instance->IsPaused();
Backup<CompanyID> cur_company(_current_company, company);
bool paused = Company::Get(company)->ai_instance->IsPaused();
cur_company.Restore();
return paused;
}
/* static */ void AI::KillAll()
@@ -199,14 +203,14 @@ static constexpr PerformanceElement GetAIPerformanceElement(CompanyID company)
for (CompanyID c = CompanyID::Begin(); c < MAX_COMPANIES; ++c) {
if (_settings_game.script_config.ai[c] != nullptr && _settings_game.script_config.ai[c]->HasScript()) {
if (!_settings_game.script_config.ai[c]->ResetInfo(true)) {
Debug(Facility::Script, Severity::Critical, "After a reload, the AI by the name '{}' was no longer found, and removed from the list.", _settings_game.script_config.ai[c]->GetName());
Debug(script, 0, "After a reload, the AI by the name '{}' was no longer found, and removed from the list.", _settings_game.script_config.ai[c]->GetName());
_settings_game.script_config.ai[c]->Change(std::nullopt);
}
}
if (_settings_newgame.script_config.ai[c] != nullptr && _settings_newgame.script_config.ai[c]->HasScript()) {
if (!_settings_newgame.script_config.ai[c]->ResetInfo(false)) {
Debug(Facility::Script, Severity::Critical, "After a reload, the AI by the name '{}' was no longer found, and removed from the list.", _settings_newgame.script_config.ai[c]->GetName());
Debug(script, 0, "After a reload, the AI by the name '{}' was no longer found, and removed from the list.", _settings_newgame.script_config.ai[c]->GetName());
_settings_newgame.script_config.ai[c]->Change(std::nullopt);
}
}
@@ -243,8 +247,9 @@ static constexpr PerformanceElement GetAIPerformanceElement(CompanyID company)
}
/* Queue the event */
AutoRestoreBackup cur_company(_current_company, company);
Backup<CompanyID> cur_company(_current_company, company);
Company::Get(_current_company)->ai_instance->InsertEvent(event);
cur_company.Restore();
}
/* static */ void AI::BroadcastNewEvent(ScriptEvent *event, CompanyID skip_company)
@@ -270,8 +275,9 @@ static constexpr PerformanceElement GetAIPerformanceElement(CompanyID company)
/* When doing emergency saving, an AI can be not fully initialised. */
if (c->ai_instance != nullptr) {
AutoRestoreBackup cur_company(_current_company, company);
Backup<CompanyID> cur_company(_current_company, company);
c->ai_instance->Save();
cur_company.Restore();
return;
}
}
@@ -284,9 +290,9 @@ static constexpr PerformanceElement GetAIPerformanceElement(CompanyID company)
AI::scanner_info->GetConsoleList(output_iterator, newest_only);
}
/* static */ void AI::GetConsoleLibraryList(std::back_insert_iterator<std::string> &output_iterator, bool newest_only)
/* static */ void AI::GetConsoleLibraryList(std::back_insert_iterator<std::string> &output_iterator)
{
AI::scanner_library->GetConsoleList(output_iterator, newest_only);
AI::scanner_library->GetConsoleList(output_iterator, true);
}
/* static */ const ScriptInfoList *AI::GetInfoList()
@@ -317,46 +323,32 @@ static constexpr PerformanceElement GetAIPerformanceElement(CompanyID company)
AI::scanner_library->RescanDir();
ResetConfig();
InvalidateWindowData(WindowClass::ScriptList, 0, 1);
SetWindowClassesDirty(WindowClass::ScriptDebug);
InvalidateWindowClassesData(WindowClass::ScriptSettings);
InvalidateWindowData(WC_SCRIPT_LIST, 0, 1);
SetWindowClassesDirty(WC_SCRIPT_DEBUG);
InvalidateWindowClassesData(WC_SCRIPT_SETTINGS);
}
/**
* Check whether we have an AI with the exact characteristics as ci.
* Check whether we have an AI (library) with the exact characteristics as ci.
* @param ci the characteristics to search on (shortname and md5sum)
* @param md5sum whether to check the MD5 checksum
* @return true iff we have an AI matching.
* @return true iff we have an AI (library) matching.
*/
/* static */ bool AI::HasAI(const ContentInfo &ci, bool md5sum)
{
return AI::scanner_info->HasScript(ci, md5sum);
}
/**
* Check whether we have an AI library with the exact characteristics as ci.
* @param ci the characteristics to search on (shortname and md5sum)
* @param md5sum whether to check the MD5 checksum
* @return true iff we have an AI library matching.
*/
/* static */ bool AI::HasAILibrary(const ContentInfo &ci, bool md5sum)
{
return AI::scanner_library->HasScript(ci, md5sum);
}
/**
* Get the scanner info for AIs.
* @return The AI scanner info.
*/
/* static */ AIScannerInfo *AI::GetScannerInfo()
{
return AI::scanner_info.get();
}
/**
* Get the scanner info for AI libraries.
* @return The AI library scanner info.
*/
/* static */ AIScannerLibrary *AI::GetScannerLibrary()
{
return AI::scanner_library.get();
+42 -46
View File
@@ -5,7 +5,7 @@
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
*/
/** @file ai_gui.cpp %Window for configuring the AIs. */
/** @file ai_gui.cpp %Window for configuring the AIs */
#include "../stdafx.h"
#include "../error.h"
@@ -22,8 +22,6 @@
#include "ai_info.hpp"
#include "../script/script_gui.h"
#include "../widgets/ai_widget.h"
#include "table/strings.h"
#include "../safeguards.h"
@@ -32,51 +30,51 @@
/** Widgets for the configure AI window. */
static constexpr std::initializer_list<NWidgetPart> _nested_ai_config_widgets = {
NWidget(NWID_HORIZONTAL),
NWidget(WWT_CLOSEBOX, Colours::Mauve),
NWidget(WWT_CAPTION, Colours::Mauve), SetStringTip(STR_AI_CONFIG_CAPTION_AI, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
NWidget(WWT_CLOSEBOX, COLOUR_MAUVE),
NWidget(WWT_CAPTION, COLOUR_MAUVE), SetStringTip(STR_AI_CONFIG_CAPTION_AI, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
EndContainer(),
NWidget(WWT_PANEL, Colours::Mauve, WID_AIC_BACKGROUND),
NWidget(WWT_PANEL, COLOUR_MAUVE, WID_AIC_BACKGROUND),
NWidget(NWID_VERTICAL), SetPIP(0, WidgetDimensions::unscaled.vsep_wide, 0), SetPadding(WidgetDimensions::unscaled.sparse),
NWidget(NWID_VERTICAL), SetPIP(0, WidgetDimensions::unscaled.vsep_sparse, 0),
NWidget(NWID_HORIZONTAL), SetPIP(0, WidgetDimensions::unscaled.hsep_wide, 0),
NWidget(NWID_HORIZONTAL, NWidContainerFlag::EqualSize),
NWidget(WWT_PUSHARROWBTN, Colours::Yellow, WID_AIC_DECREASE_NUMBER), SetArrowWidgetTypeTip(ArrowWidgetType::Decrease),
NWidget(WWT_PUSHARROWBTN, Colours::Yellow, WID_AIC_INCREASE_NUMBER), SetArrowWidgetTypeTip(ArrowWidgetType::Increase),
NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_AIC_DECREASE_NUMBER), SetArrowWidgetTypeTip(AWV_DECREASE),
NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_AIC_INCREASE_NUMBER), SetArrowWidgetTypeTip(AWV_INCREASE),
EndContainer(),
NWidget(WWT_TEXT, Colours::Invalid, WID_AIC_NUMBER), SetFill(1, 0),
NWidget(WWT_TEXT, INVALID_COLOUR, WID_AIC_NUMBER), SetFill(1, 0),
EndContainer(),
NWidget(NWID_HORIZONTAL), SetPIP(0, WidgetDimensions::unscaled.hsep_wide, 0),
NWidget(NWID_HORIZONTAL, NWidContainerFlag::EqualSize),
NWidget(WWT_PUSHARROWBTN, Colours::Yellow, WID_AIC_DECREASE_INTERVAL), SetArrowWidgetTypeTip(ArrowWidgetType::Decrease),
NWidget(WWT_PUSHARROWBTN, Colours::Yellow, WID_AIC_INCREASE_INTERVAL), SetArrowWidgetTypeTip(ArrowWidgetType::Increase),
NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_AIC_DECREASE_INTERVAL), SetArrowWidgetTypeTip(AWV_DECREASE),
NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_AIC_INCREASE_INTERVAL), SetArrowWidgetTypeTip(AWV_INCREASE),
EndContainer(),
NWidget(WWT_TEXT, Colours::Invalid, WID_AIC_INTERVAL), SetFill(1, 0),
NWidget(WWT_TEXT, INVALID_COLOUR, WID_AIC_INTERVAL), SetFill(1, 0),
EndContainer(),
NWidget(NWID_HORIZONTAL, NWidContainerFlag::EqualSize),
NWidget(WWT_PUSHTXTBTN, Colours::Yellow, WID_AIC_MOVE_UP), SetResize(1, 0), SetFill(1, 0), SetStringTip(STR_AI_CONFIG_MOVE_UP, STR_AI_CONFIG_MOVE_UP_TOOLTIP),
NWidget(WWT_PUSHTXTBTN, Colours::Yellow, WID_AIC_MOVE_DOWN), SetResize(1, 0), SetFill(1, 0), SetStringTip(STR_AI_CONFIG_MOVE_DOWN, STR_AI_CONFIG_MOVE_DOWN_TOOLTIP),
NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_AIC_MOVE_UP), SetResize(1, 0), SetFill(1, 0), SetStringTip(STR_AI_CONFIG_MOVE_UP, STR_AI_CONFIG_MOVE_UP_TOOLTIP),
NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_AIC_MOVE_DOWN), SetResize(1, 0), SetFill(1, 0), SetStringTip(STR_AI_CONFIG_MOVE_DOWN, STR_AI_CONFIG_MOVE_DOWN_TOOLTIP),
EndContainer(),
EndContainer(),
NWidget(WWT_FRAME, Colours::Mauve), SetStringTip(STR_AI_CONFIG_AI), SetPIP(0, WidgetDimensions::unscaled.vsep_sparse, 0),
NWidget(WWT_FRAME, COLOUR_MAUVE), SetStringTip(STR_AI_CONFIG_AI), SetPIP(0, WidgetDimensions::unscaled.vsep_sparse, 0),
NWidget(NWID_HORIZONTAL),
NWidget(WWT_MATRIX, Colours::Mauve, WID_AIC_LIST), SetMinimalSize(288, 112), SetFill(1, 0), SetMatrixDataTip(1, 8, STR_AI_CONFIG_AILIST_TOOLTIP), SetScrollbar(WID_AIC_SCROLLBAR),
NWidget(NWID_VSCROLLBAR, Colours::Mauve, WID_AIC_SCROLLBAR),
NWidget(WWT_MATRIX, COLOUR_MAUVE, WID_AIC_LIST), SetMinimalSize(288, 112), SetFill(1, 0), SetMatrixDataTip(1, 8, STR_AI_CONFIG_AILIST_TOOLTIP), SetScrollbar(WID_AIC_SCROLLBAR),
NWidget(NWID_VSCROLLBAR, COLOUR_MAUVE, WID_AIC_SCROLLBAR),
EndContainer(),
NWidget(WWT_PUSHTXTBTN, Colours::Yellow, WID_AIC_CONFIGURE), SetFill(1, 0), SetStringTip(STR_AI_CONFIG_CONFIGURE, STR_AI_CONFIG_CONFIGURE_TOOLTIP),
NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_AIC_CONFIGURE), SetFill(1, 0), SetStringTip(STR_AI_CONFIG_CONFIGURE, STR_AI_CONFIG_CONFIGURE_TOOLTIP),
EndContainer(),
NWidget(NWID_HORIZONTAL), SetPIP(0, WidgetDimensions::unscaled.hsep_wide, 0),
NWidget(NWID_VERTICAL, NWidContainerFlag::EqualSize),
NWidget(WWT_PUSHTXTBTN, Colours::Yellow, WID_AIC_CHANGE), SetFill(1, 1), SetStringTip(STR_AI_CONFIG_CHANGE_AI, STR_AI_CONFIG_CHANGE_TOOLTIP),
NWidget(WWT_PUSHTXTBTN, Colours::Yellow, WID_AIC_CONTENT_DOWNLOAD), SetFill(1, 1), SetStringTip(STR_INTRO_ONLINE_CONTENT, STR_INTRO_TOOLTIP_ONLINE_CONTENT),
NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_AIC_CHANGE), SetFill(1, 1), SetStringTip(STR_AI_CONFIG_CHANGE_AI, STR_AI_CONFIG_CHANGE_TOOLTIP),
NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_AIC_CONTENT_DOWNLOAD), SetFill(1, 1), SetStringTip(STR_INTRO_ONLINE_CONTENT, STR_INTRO_TOOLTIP_ONLINE_CONTENT),
EndContainer(),
NWidget(NWID_VERTICAL, NWidContainerFlag::EqualSize),
NWidget(NWID_HORIZONTAL, NWidContainerFlag::EqualSize),
NWidget(WWT_PUSHTXTBTN, Colours::Yellow, WID_AIC_OPEN_URL), SetResize(1, 0), SetFill(1, 0), SetStringTip(STR_CONTENT_OPEN_URL, STR_CONTENT_OPEN_URL_TOOLTIP),
NWidget(WWT_PUSHTXTBTN, Colours::Yellow, WID_AIC_TEXTFILE + TextfileType::Readme), SetFill(1, 1), SetResize(1, 0), SetStringTip(STR_TEXTFILE_VIEW_README, STR_TEXTFILE_VIEW_README_TOOLTIP),
NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_AIC_OPEN_URL), SetResize(1, 0), SetFill(1, 0), SetStringTip(STR_CONTENT_OPEN_URL, STR_CONTENT_OPEN_URL_TOOLTIP),
NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_AIC_TEXTFILE + TFT_README), SetFill(1, 1), SetResize(1, 0), SetStringTip(STR_TEXTFILE_VIEW_README, STR_TEXTFILE_VIEW_README_TOOLTIP),
EndContainer(),
NWidget(NWID_HORIZONTAL, NWidContainerFlag::EqualSize),
NWidget(WWT_PUSHTXTBTN, Colours::Yellow, WID_AIC_TEXTFILE + TextfileType::Changelog), SetFill(1, 1), SetResize(1, 0), SetStringTip(STR_TEXTFILE_VIEW_CHANGELOG, STR_TEXTFILE_VIEW_CHANGELOG_TOOLTIP),
NWidget(WWT_PUSHTXTBTN, Colours::Yellow, WID_AIC_TEXTFILE + TextfileType::License), SetFill(1, 1), SetResize(1, 0), SetStringTip(STR_TEXTFILE_VIEW_LICENCE, STR_TEXTFILE_VIEW_LICENCE_TOOLTIP),
NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_AIC_TEXTFILE + TFT_CHANGELOG), SetFill(1, 1), SetResize(1, 0), SetStringTip(STR_TEXTFILE_VIEW_CHANGELOG, STR_TEXTFILE_VIEW_CHANGELOG_TOOLTIP),
NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_AIC_TEXTFILE + TFT_LICENSE), SetFill(1, 1), SetResize(1, 0), SetStringTip(STR_TEXTFILE_VIEW_LICENCE, STR_TEXTFILE_VIEW_LICENCE_TOOLTIP),
EndContainer(),
EndContainer(),
EndContainer(),
@@ -86,8 +84,8 @@ static constexpr std::initializer_list<NWidgetPart> _nested_ai_config_widgets =
/** Window definition for the configure AI window. */
static WindowDesc _ai_config_desc(
WindowPosition::Center, {}, 0, 0,
WindowClass::GameOptions, WindowClass::None,
WDP_CENTER, {}, 0, 0,
WC_GAME_OPTIONS, WC_NONE,
{},
_nested_ai_config_widgets
);
@@ -102,7 +100,7 @@ struct AIConfigWindow : public Window {
AIConfigWindow() : Window(_ai_config_desc)
{
this->InitNested(GameOptionsWindowNumber::AI); // Initializes 'this->line_height' as a side effect.
this->InitNested(WN_GAME_OPTIONS_AI); // Initializes 'this->line_height' as a side effect.
this->vscroll = this->GetScrollbar(WID_AIC_SCROLLBAR);
this->selected_slot = CompanyID::Invalid();
NWidgetCore *nwi = this->GetWidget<NWidgetCore>(WID_AIC_LIST);
@@ -113,8 +111,8 @@ struct AIConfigWindow : public Window {
void Close([[maybe_unused]] int data = 0) override
{
CloseWindowByClass(WindowClass::ScriptList);
CloseWindowByClass(WindowClass::ScriptSettings);
CloseWindowByClass(WC_SCRIPT_LIST);
CloseWindowByClass(WC_SCRIPT_SETTINGS);
this->Window::Close();
}
@@ -143,7 +141,7 @@ struct AIConfigWindow : public Window {
break;
case WID_AIC_LIST:
this->line_height = GetCharacterHeight(FontSize::Normal) + padding.height;
this->line_height = GetCharacterHeight(FS_NORMAL) + padding.height;
fill.height = resize.height = this->line_height;
size.height = 8 * this->line_height;
break;
@@ -157,7 +155,7 @@ struct AIConfigWindow : public Window {
*/
static bool IsEditable(CompanyID slot)
{
if (_game_mode != GameMode::Normal) {
if (_game_mode != GM_NORMAL) {
return slot > 0 && slot < MAX_COMPANIES;
}
return slot < MAX_COMPANIES && !Company::IsValidID(slot);
@@ -170,7 +168,7 @@ struct AIConfigWindow : public Window {
*/
std::string GetSlotText(CompanyID cid) const
{
if ((_game_mode != GameMode::Normal && cid == 0) || (_game_mode == GameMode::Normal && Company::IsValidHumanID(cid))) return GetString(STR_AI_CONFIG_HUMAN_PLAYER);
if ((_game_mode != GM_NORMAL && cid == 0) || (_game_mode == GM_NORMAL && Company::IsValidHumanID(cid))) return GetString(STR_AI_CONFIG_HUMAN_PLAYER);
if (const AIInfo *info = AIConfig::GetConfig(cid)->GetInfo(); info != nullptr) return info->GetName();
return GetString(STR_AI_CONFIG_RANDOM_AI);
}
@@ -183,10 +181,10 @@ struct AIConfigWindow : public Window {
*/
TextColour GetSlotColour(CompanyID cid, CompanyID max_slot) const
{
if (this->selected_slot == cid) return TextColour::White;
if (IsEditable(cid)) return cid < max_slot ? TextColour::Orange : TextColour::Silver;
if (Company::IsValidAiID(cid)) return TextColour::Green;
return TextColour::Silver;
if (this->selected_slot == cid) return TC_WHITE;
if (IsEditable(cid)) return cid < max_slot ? TC_ORANGE : TC_SILVER;
if (Company::IsValidAiID(cid)) return TC_GREEN;
return TC_SILVER;
}
void DrawWidget(const Rect &r, WidgetID widget) const override
@@ -195,7 +193,7 @@ struct AIConfigWindow : public Window {
case WID_AIC_LIST: {
Rect tr = r.Shrink(WidgetDimensions::scaled.matrix);
int max_slot = GetGameSettings().difficulty.max_no_competitors;
if (_game_mode == GameMode::Normal) {
if (_game_mode == GM_NORMAL) {
for (const Company *c : Company::Iterate()) {
if (c->is_ai) max_slot--;
}
@@ -217,7 +215,7 @@ struct AIConfigWindow : public Window {
void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
{
if (widget >= WID_AIC_TEXTFILE && widget < WID_AIC_TEXTFILE + TextfileType::ContentEnd) {
if (widget >= WID_AIC_TEXTFILE && widget < WID_AIC_TEXTFILE + TFT_CONTENT_END) {
if (this->selected_slot == CompanyID::Invalid() || AIConfig::GetConfig(this->selected_slot) == nullptr) return;
ShowScriptTextfileWindow(this, static_cast<TextfileType>(widget - WID_AIC_TEXTFILE), this->selected_slot);
@@ -260,8 +258,7 @@ struct AIConfigWindow : public Window {
case WID_AIC_MOVE_UP:
if (IsEditable(this->selected_slot) && IsEditable(static_cast<CompanyID>(this->selected_slot - 1))) {
auto it = std::next(std::begin(GetGameSettings().script_config.ai), this->selected_slot.base());
std::swap(*it, *std::prev(it));
std::swap(GetGameSettings().script_config.ai[this->selected_slot], GetGameSettings().script_config.ai[this->selected_slot - 1]);
this->selected_slot = static_cast<CompanyID>(this->selected_slot - 1);
this->vscroll->ScrollTowards(this->selected_slot.base());
this->InvalidateData();
@@ -270,8 +267,7 @@ struct AIConfigWindow : public Window {
case WID_AIC_MOVE_DOWN:
if (IsEditable(this->selected_slot) && IsEditable(static_cast<CompanyID>(this->selected_slot + 1))) {
auto it = std::next(std::begin(GetGameSettings().script_config.ai), this->selected_slot.base());
std::swap(*it, *std::next(it));
std::swap(GetGameSettings().script_config.ai[this->selected_slot], GetGameSettings().script_config.ai[this->selected_slot + 1]);
++this->selected_slot;
this->vscroll->ScrollTowards(this->selected_slot.base());
this->InvalidateData();
@@ -295,9 +291,9 @@ struct AIConfigWindow : public Window {
case WID_AIC_CONTENT_DOWNLOAD:
if (!_network_available) {
ShowErrorMessage(GetEncodedString(STR_NETWORK_ERROR_NOTAVAILABLE), {}, WarningLevel::Error);
ShowErrorMessage(GetEncodedString(STR_NETWORK_ERROR_NOTAVAILABLE), {}, WL_ERROR);
} else {
ShowNetworkContentListWindow(nullptr, ContentType::Ai);
ShowNetworkContentListWindow(nullptr, CONTENT_TYPE_AI);
}
break;
}
@@ -328,7 +324,7 @@ struct AIConfigWindow : public Window {
this->SetWidgetDisabledState(WID_AIC_MOVE_DOWN, !IsEditable(this->selected_slot) || !IsEditable(static_cast<CompanyID>(this->selected_slot + 1)));
this->SetWidgetDisabledState(WID_AIC_OPEN_URL, this->selected_slot == CompanyID::Invalid() || config->GetInfo() == nullptr || config->GetInfo()->GetURL().empty());
for (TextfileType tft : EnumRange(TextfileType::ContentBegin, TextfileType::ContentEnd)) {
for (TextfileType tft = TFT_CONTENT_BEGIN; tft < TFT_CONTENT_END; tft++) {
this->SetWidgetDisabledState(WID_AIC_TEXTFILE + tft, this->selected_slot == CompanyID::Invalid() || !config->GetTextfile(tft, this->selected_slot).has_value());
}
}
@@ -337,7 +333,7 @@ struct AIConfigWindow : public Window {
/** Open the AI config window. */
void ShowAIConfigWindow()
{
CloseWindowByClass(WindowClass::GameOptions);
CloseWindowByClass(WC_GAME_OPTIONS);
new AIConfigWindow();
}
+1 -1
View File
@@ -5,7 +5,7 @@
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
*/
/** @file ai_gui.hpp %Window for configuring the AIs. */
/** @file ai_gui.hpp %Window for configuring the AIs */
#ifndef AI_GUI_HPP
#define AI_GUI_HPP
+1 -2
View File
@@ -5,7 +5,7 @@
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
*/
/** @file ai_info.cpp Implementation of AIInfo and AILibrary. */
/** @file ai_info.cpp Implementation of AIInfo and AILibrary */
#include "../stdafx.h"
@@ -21,7 +21,6 @@
/**
* Check if the API version provided by the AI is supported.
* @param api_version The API version as provided by the AI.
* @return \c true if the given version is supported by this version of OpenTTD.
*/
static bool CheckAPIVersion(const std::string &api_version)
{
+2 -15
View File
@@ -15,47 +15,38 @@
/** All static information from an AI like name, version, etc. */
class AIInfo : public ScriptInfo {
public:
/** All valid AI API versions, in order. */
static constexpr std::string_view ApiVersions[]{ "0.7", "1.0", "1.1", "1.2", "1.3", "1.4", "1.5", "1.6", "1.7", "1.8", "1.9", "1.10", "1.11", "12", "13", "14", "15", "16" };
/* All valid AI API versions, in order. */
static constexpr std::string_view ApiVersions[]{ "0.7", "1.0", "1.1", "1.2", "1.3", "1.4", "1.5", "1.6", "1.7", "1.8", "1.9", "1.10", "1.11", "12", "13", "14", "15" };
AIInfo();
/**
* Register the functions of this class.
* @param engine The engine to register to.
*/
static void RegisterAPI(Squirrel &engine);
/**
* Create an AI, using this AIInfo as start-template.
* @param vm The virtual machine to push the instance to.
* @return The number of stack places occupied.
*/
static SQInteger Constructor(HSQUIRRELVM vm);
/**
* Create a dummy-AI.
* @param vm The virtual machine to push the instance to.
* @return The number of stack places occupied.
*/
static SQInteger DummyConstructor(HSQUIRRELVM vm);
/**
* Check if we can start this AI.
* @param version The version to check.
* @return \c true if this script can load the data from that version.
*/
bool CanLoadFromVersion(int version) const;
/**
* Use this AI as a random AI.
* @return \c true when it can be used as random AI, \c false when the user must specifically request it.
*/
bool UseAsRandomAI() const { return this->use_as_random; }
/**
* Get the API version this AI is written for.
* @return The API version.
*/
const std::string &GetAPIVersion() const { return this->api_version; }
@@ -72,20 +63,16 @@ public:
/**
* Register the functions of this class.
* @param engine The engine to register to.
*/
static void RegisterAPI(Squirrel &engine);
/**
* Create an AI, using this AIInfo as start-template.
* @param vm The virtual machine to push the instance to.
* @return The number of stack places occupied.
*/
static SQInteger Constructor(HSQUIRRELVM vm);
/**
* Get the category this library is in.
* @return The category.
*/
const std::string &GetCategory() const { return this->category; }
+4 -4
View File
@@ -55,7 +55,7 @@ void AIInstance::RegisterAPI()
/* Register all classes */
SQAI_RegisterAll(*this->engine);
if (!this->LoadCompatibilityScripts(Subdirectory::Ai, AIInfo::ApiVersions)) this->Died();
if (!this->LoadCompatibilityScripts(AI_DIR, AIInfo::ApiVersions)) this->Died();
}
void AIInstance::Died()
@@ -63,16 +63,16 @@ void AIInstance::Died()
ScriptInstance::Died();
/* Intro is not supposed to use AI, but it may have 'dummy' AI which instant dies. */
if (_game_mode == GameMode::Menu) return;
if (_game_mode == GM_MENU) return;
/* Don't show errors while loading savegame. They will be shown at end of loading anyway. */
if (_switch_mode != SwitchMode::None) return;
if (_switch_mode != SM_NONE) return;
ShowScriptDebugWindow(_current_company);
const AIInfo *info = AIConfig::GetConfig(_current_company)->GetInfo();
if (info != nullptr) {
ShowErrorMessage(GetEncodedString(STR_ERROR_AI_PLEASE_REPORT_CRASH), {}, WarningLevel::Warning);
ShowErrorMessage(GetEncodedString(STR_ERROR_AI_PLEASE_REPORT_CRASH), {}, WL_WARNING);
if (!info->GetURL().empty()) {
ScriptLog::Info("Please report the error to the following URL:");
+4 -4
View File
@@ -5,7 +5,7 @@
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
*/
/** @file ai_scanner.cpp Allows scanning AI scripts. */
/** @file ai_scanner.cpp allows scanning AI scripts */
#include "../stdafx.h"
#include <ranges>
@@ -53,8 +53,8 @@ void AIScannerInfo::RegisterAPI(class Squirrel &engine)
AIInfo *AIScannerInfo::SelectRandomAI() const
{
if (_game_mode == GameMode::Menu) {
Debug(Facility::Script, Severity::Critical, "The intro game should not use AI, loading 'dummy' AI.");
if (_game_mode == GM_MENU) {
Debug(script, 0, "The intro game should not use AI, loading 'dummy' AI.");
return this->info_dummy.get();
}
@@ -63,7 +63,7 @@ AIInfo *AIScannerInfo::SelectRandomAI() const
uint num_random_ais = std::ranges::distance(random_ais);
if (num_random_ais == 0) {
Debug(Facility::Script, Severity::Critical, "No suitable AI found, loading 'dummy' AI.");
Debug(script, 0, "No suitable AI found, loading 'dummy' AI.");
return this->info_dummy.get();
}
+4 -7
View File
@@ -5,18 +5,17 @@
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
*/
/** @file ai_scanner.hpp Declarations of the class for AI scanner. */
/** @file ai_scanner.hpp declarations of the class for AI scanner */
#ifndef AI_SCANNER_HPP
#define AI_SCANNER_HPP
#include "../script/script_scanner.hpp"
/** AI instantiation of a ScriptScanner. */
class AIScannerInfo : public ScriptScanner {
public:
AIScannerInfo();
~AIScannerInfo() override;
~AIScannerInfo();
void Initialize() override;
@@ -37,14 +36,13 @@ public:
/**
* Set the Dummy AI.
* @param info The new dummy AI.
*/
void SetDummyAI(std::unique_ptr<class AIInfo> &&info);
protected:
std::string GetScriptName(ScriptInfo &info) override;
std::string_view GetFileName() const override { return PATHSEP "info.nut"; }
Subdirectory GetDirectory() const override { return Subdirectory::Ai; }
Subdirectory GetDirectory() const override { return AI_DIR; }
std::string_view GetScannerName() const override { return "AIs"; }
void RegisterAPI(class Squirrel &engine) override;
@@ -52,7 +50,6 @@ private:
std::unique_ptr<AIInfo> info_dummy; ///< The dummy AI.
};
/** AI instantiation of a ScriptScanner for libraries. */
class AIScannerLibrary : public ScriptScanner {
public:
void Initialize() override;
@@ -68,7 +65,7 @@ public:
protected:
std::string GetScriptName(ScriptInfo &info) override;
std::string_view GetFileName() const override { return PATHSEP "library.nut"; }
Subdirectory GetDirectory() const override { return Subdirectory::AiLibrary; }
Subdirectory GetDirectory() const override { return AI_LIBRARY_DIR; }
std::string_view GetScannerName() const override { return "AI Libraries"; }
void RegisterAPI(class Squirrel &engine) override;
};
+12 -14
View File
@@ -33,21 +33,18 @@ enum AircraftSubType : uint8_t {
};
/** Flags for air vehicles; shared with disaster vehicles. */
enum class VehicleAirFlag : uint8_t {
DestinationTooFar = 0, ///< Next destination is too far away.
enum AirVehicleFlags : uint8_t {
VAF_DEST_TOO_FAR = 0, ///< Next destination is too far away.
/* The next two flags are to prevent stair climbing of the aircraft. The idea is that the aircraft
* will ascend or descend multiple flight levels at a time instead of following the contours of the
* landscape at a fixed altitude. This only has effect when there are more than 15 height levels. */
InMaximumHeightCorrection = 1, ///< The vehicle is currently lowering its altitude because it hit the upper bound.
InMinimumHeightCorrection = 2, ///< The vehicle is currently raising its altitude because it hit the lower bound.
VAF_IN_MAX_HEIGHT_CORRECTION = 1, ///< The vehicle is currently lowering its altitude because it hit the upper bound.
VAF_IN_MIN_HEIGHT_CORRECTION = 2, ///< The vehicle is currently raising its altitude because it hit the lower bound.
HelicopterDirectDescent = 3, ///< The helicopter is descending directly at its destination (helipad or in front of hangar)
VAF_HELI_DIRECT_DESCENT = 3, ///< The helicopter is descending directly at its destination (helipad or in front of hangar)
};
/** Bitset of \c VehicleAirFlag elements. */
using VehicleAirFlags = EnumBitSet<VehicleAirFlag, uint8_t>;
static const int ROTOR_Z_OFFSET = 5; ///< Z Offset between helicopter- and rotorsprite.
void HandleAircraftEnterHangar(Aircraft *v);
@@ -72,26 +69,27 @@ struct AircraftCache {
/**
* Aircraft, helicopters, rotors and their shadows belong to this class.
*/
struct Aircraft final : public SpecializedVehicle<Aircraft, VehicleType::Aircraft> {
struct Aircraft final : public SpecializedVehicle<Aircraft, VEH_AIRCRAFT> {
uint16_t crashed_counter = 0; ///< Timer for handling crash animations.
uint8_t pos = 0; ///< Next desired position of the aircraft.
uint8_t previous_pos = 0; ///< Previous desired position of the aircraft.
StationID targetairport = StationID::Invalid(); ///< Airport to go to next.
uint8_t state = 0; ///< State of the airport. @see AirportMovementStates
Direction last_direction = Direction::Invalid;
Direction last_direction = INVALID_DIR;
uint8_t number_consecutive_turns = 0; ///< Protection to prevent the aircraft of making a lot of turns in order to reach a specific point.
uint8_t turn_counter = 0; ///< Ticks between each turn to prevent > 45 degree turns.
VehicleAirFlags flags{}; ///< Aircraft flags. @see VehicleAirFlags
uint8_t flags = 0; ///< Aircraft flags. @see AirVehicleFlags
AircraftCache acache{};
Aircraft(VehicleID index) : SpecializedVehicleBase(index) {}
/** We don't want GCC to zero our struct! It already is zeroed and has an index! */
Aircraft() : SpecializedVehicleBase() {}
/** We want to 'destruct' the right class. */
~Aircraft() override { this->PreDestructor(); }
virtual ~Aircraft() { this->PreDestructor(); }
void MarkDirty() override;
void UpdateDeltaXY() override;
ExpensesType GetExpenseType(bool income) const override { return income ? ExpensesType::AircraftRevenue : ExpensesType::AircraftRun; }
ExpensesType GetExpenseType(bool income) const override { return income ? EXPENSES_AIRCRAFT_REVENUE : EXPENSES_AIRCRAFT_RUN; }
bool IsPrimaryVehicle() const override { return this->IsNormalAircraft(); }
void GetImage(Direction direction, EngineImageType image_type, VehicleSpriteSeq *result) const override;
int GetDisplaySpeed() const override { return this->cur_speed; }

Some files were not shown because too many files have changed in this diff Show More