Compare commits

...
764 Commits
Author SHA1 Message Date
Peter NelsonandGitHub 24a4a1652b Update: Changelog for 15.0-beta3 (#14407) 2025-08-31 14:49:25 -04:00
Peter NelsonandGitHub a23970af32 Fix f30f808b50: Bridge over bridge head could be built one level too low. (#14564) 2025-08-31 19:15:49 +01:00
Peter NelsonandGitHub febf8b0d57 Fix #14561: Vehicle effects missing for vehicle on bridge. (#14563) 2025-08-31 18:27:46 +01:00
Loïc GuillouxandGitHub 4b9afbe35b Codefix: [Script] Mention ScriptError::ERR_STATION_TOO_SPREAD_OUT in API doc (#14562) 2025-08-31 15:18:51 +00:00
Loïc GuillouxandGitHub 80666a0d51 Add: [Script] ScriptError::ERR_BRIDGE_TOO_LOW (#14560) 2025-08-31 14:04:02 +00:00
Rubidiumandrubidium42 7c0f69a8fe Codefix: typos in comments and strings 2025-08-31 10:30:37 +02:00
Rubidiumandrubidium42 4fb749886a Codefix: typos in variable/constant/function names 2025-08-31 10:30:37 +02:00
Rubidiumandrubidium42 da8422a656 Codefix: typos in string names 2025-08-31 10:30:37 +02:00
translators 37b72f9dcf Update: Translations from eints
galician: 21 changes by pvillaverde
french: 9 changes by ottdfevr
2025-08-31 04:38:04 +00:00
Loïc GuillouxandGitHub fac55d0278 Fix #14506, aac3a5b6: Restore prefilling of _stations_nearby_list (#14551) 2025-08-30 21:11:09 +02:00
Peter NelsonandGitHub b867939f37 Fix #14553: Parameter configuration of pre-action 14 NewGRFs did not work. (#14554) 2025-08-30 19:47:37 +01:00
translators 011fca6e21 Update: Translations from eints
danish: 59 changes by bscargo
2025-08-30 04:37:31 +00:00
Jonathan G Rennisonandrubidium42 32d93e1c67 Cleanup: Misspellings of "dropdown" in order_gui.cpp 2025-08-29 21:40:35 +02:00
translators 5c285f3e0c Update: Translations from eints
italian: 12 changes by da-cal
maori (new zealand): 85 changes by Kyle-McDangersword
2025-08-29 04:38:53 +00:00
Richard Wheeler 72fc2032e6 Change: Update OpenTTD TTF fonts to v0.8
Add new private range special symbols for recent OpenTTD updates: town and city icons for sans (supporting #14504), left arrow for small and sans (supporting #14174). Add Hebrew alphabet to small and serif fonts, for first (beta) support for Hebrew. Fix new shekel glyph height in all fonts. Fix i ogonek right bearing and umlaut alignment in sans font. Fixes #14179
2025-08-28 22:50:15 +01:00
Richard Wheeler c6c72404e1 Change: Set endgame background to match original graphics borders 2025-08-28 21:22:31 +01:00
KuhnovicandGitHub 10e81af663 Codechange: Deduplicate YAPF estimate calculation. (#14527) 2025-08-28 21:09:00 +02:00
Peter NelsonandGitHub e6323e6760 Fix: File/directory titles not updated if language is changed. (#14542) 2025-08-28 17:42:00 +01:00
Peter NelsonandGitHub 2978cfa5c9 Fix fbd71a9d72: Missing space after old file type identifier. (#14541) 2025-08-27 18:06:49 +01:00
translators 41ecb25238 Update: Translations from eints
maori (new zealand): 2 changes by translators
2025-08-27 04:39:11 +00:00
Kyle McDangerswordandrubidium42 2907dff157 Add #14536: Maori (New Zealand) language 2025-08-26 20:52:25 +02:00
Peter NelsonandGitHub 68af94cf3e Fix 7344dfe651: Hang when clicking on a link in a text file. (#14539)
When text is not wrapped, a line's `wrapped_width` is 0, causing the Layouter to get stuck in an infinite loop.
2025-08-26 18:28:16 +01:00
Loïc GuillouxandGitHub 995f30bff0 Codefix bd1a3fe0: Incorrect handling of squirrel stack (#14538) 2025-08-26 16:00:01 +02:00
translators d3d25a39a0 Update: Translations from eints
norwegian (bokmal): 5 changes by eriksorngard
2025-08-26 04:40:50 +00:00
Jonathan G RennisonandGitHub c4912c94e4 Fix: Incorrect use of GetDescription in town/industry load handler (#14526)
GetLoadDescription should be used instead such that skipping incoming
table fields works as expected
2025-08-25 15:16:04 +01:00
Peter NelsonandGitHub 6eb5c166dc Fix: Account for both text and icon size in station waiting cargo display. (#14535) 2025-08-25 15:15:10 +01:00
translators 5996aa4a57 Update: Translations from eints
chinese (traditional): 4 changes by KogentaSan
english (us): 5 changes by 2TallTyler
chinese (simplified): 5 changes by WenSimEHRP
2025-08-25 04:42:04 +00:00
glx22andLoïc Guilloux 6d495d1fb9 Codechange: [Actions] Use NuGet for vcpkg binary caching 2025-08-24 21:38:16 +02:00
glx22andLoïc Guilloux 0f2d1dc39c Codechange: [Actions] Setup vcpkg via a composite action 2025-08-24 21:38:16 +02:00
Cornelius DiekmannandGitHub c9fc7c0caa Doc: Symbol consistency in landscape_grid.html (#14531)
The table in landscape_grid.html uses both the letter `O` as well as the digit `0` (zero) to denote bits.
The digit `0` represents actual values, while the letter `O` is a placeholder for free bits.
2025-08-24 12:46:10 +00:00
Jonathan G RennisonandGitHub 294006b1c8 Fix: Incorrect Company::freegroups handling on company merger (#14534) 2025-08-24 12:26:34 +00:00
Jonathan G RennisonandGitHub 98ffd3cdb1 Fix: Off-by-one when drawing diagonal lines (#14523) 2025-08-24 13:24:17 +01:00
translators 98090fe948 Update: Translations from eints
swedish: 5 changes by robert-i
korean: 5 changes by telk5093
hungarian: 9 changes by vargaviktor
catalan: 5 changes by J0anJosep
2025-08-24 04:42:03 +00:00
translators 0d736d7555 Update: Translations from eints
greek: 7 changes by gh658804
finnish: 6 changes by hpiirai
dutch: 9 changes by Afoklala
2025-08-23 04:39:05 +00:00
Peter NelsonandGitHub 54f328beeb Codechange: Remove output pointer from GetTileArea(). (#14530)
This simplifies things and removes undocumented type `ETileArea`
2025-08-22 21:27:31 +01:00
translators 2aaf0c0211 Update: Translations from eints
english (au): 5 changes by krysclarke
chinese (traditional): 5 changes by KogentaSan
russian: 5 changes by Ln-Wolf
finnish: 8 changes by hpiirai
portuguese: 7 changes by jcteotonio
portuguese (brazilian): 6 changes by pasantoro
polish: 5 changes by pAter-exe
2025-08-22 04:40:24 +00:00
translators b3beff9781 Update: Translations from eints
swedish: 2 changes by joeax910
chinese (traditional): 2 changes by KogentaSan
english (us): 4 changes by 2TallTyler
chinese (simplified): 2 changes by WenSimEHRP
finnish: 2 changes by hpiirai
2025-08-21 04:40:46 +00:00
Peter NelsonandPeter Nelson 7a47f7b834 Change: Tweak tubular bridges to remove baked-in pillars. 2025-08-20 21:40:41 +01:00
9a294ab2ed Feature: Allow stations and roadstops under bridges.
Bridges above stations will have pillars excluded if they conflict with the station layout.

Partly based on the system implemented in JGRPP.

Co-authored-by: <su@angel-island.zone>
2025-08-20 21:40:41 +01:00
Peter NelsonandPeter Nelson 6d6e64b1f0 Add: [NewGRF] Bridge pillar exclusion information for stations and roadstops.
NewGRF stations and roadstops can now specify bridge pillar and minimum height information for their tiles.
2025-08-20 21:40:41 +01:00
Peter NelsonandPeter Nelson f30f808b50 Codechange: Implement tile proc handler to test for building bridge over tile. 2025-08-20 21:40:41 +01:00
translators 77503776b6 Update: Translations from eints
english (au): 2 changes by krysclarke
norwegian (bokmal): 7 changes by eriksorngard
chinese (traditional): 2 changes by KogentaSan
korean: 7 changes by telk5093
russian: 2 changes by Ln-Wolf
catalan: 24 changes by J0anJosep
portuguese (brazilian): 2 changes by pasantoro
polish: 2 changes by pAter-exe
2025-08-20 04:40:05 +00:00
Peter NelsonandGitHub 1cb0cbcb6c Codechange: Standardise how AllocateSpecToStation/RoadStop are called. (#14525)
Replace use of negative value with std::optional and update doxygen.
2025-08-19 18:52:36 +01:00
translators 5eeede82c5 Update: Translations from eints
swedish: 4 changes by robert-i
english (us): 2 changes by 2TallTyler
greek: 2 changes by gh658804
2025-08-19 04:39:40 +00:00
Peter NelsonandPeter Nelson 3a5eaf367a Feature: Option to disable activate-on-release behaviour of toolbar dropdown buttons. 2025-08-18 19:48:22 +01:00
Peter NelsonandPeter Nelson ea9bee2a3e Fix: Close dropdown menu when user clicks on a differenet window.
This did not happen if the clicked window is flagged as unfocusable (i.e. the main toolbar.)
2025-08-18 19:48:22 +01:00
translators 1850ad1aa2 Update: Translations from eints
chinese (traditional): 2 changes by KogentaSan
russian: 2 changes by Ln-Wolf
2025-08-18 04:46:26 +00:00
Jonathan G RennisonandPeter Nelson add40a2de2 Fix #10222: Off by one drawing even-width horizontal/vertical lines 2025-08-17 20:41:49 +01:00
Jonathan G RennisonandPeter Nelson 80f72d3722 Fix: Off-by-one in Blitter::DrawLineGeneric 2025-08-17 20:41:22 +01:00
Loïc GuillouxandGitHub 2d60b9d7b9 Codefix: [macos] variable length array warnings with clang-17 (#14521) 2025-08-17 19:47:31 +02:00
translators 88923a3f18 Update: Translations from eints
english (au): 2 changes by krysclarke
chinese (simplified): 4 changes by WenSimEHRP
finnish: 2 changes by hpiirai
french: 52 changes by glx22
portuguese: 2 changes by jcteotonio
portuguese (brazilian): 2 changes by pasantoro
polish: 2 changes by pAter-exe
2025-08-17 04:45:07 +00:00
translators 94ba9b1454 Update: Translations from eints
hungarian: 2 changes by vargaviktor
finnish: 2 changes by hpiirai
dutch: 3 changes by Afoklala
2025-08-16 04:41:07 +00:00
dPandGitHub 628a23a990 Fix: [Script] Invalid title on GSGoal.Question windows (#14519) 2025-08-16 00:55:09 +02:00
Peter NelsonandPeter Nelson 0a1c0b8b48 Change: Hide bridge pillars if obstructed by tile below.
Tiles can now control if pillars are drawn on a bridge above it. There is no visible change with default bridges.
2025-08-15 23:20:18 +01:00
Peter NelsonandPeter Nelson 48b42492bc Add: [NewGRF] Add extra information to bridges about pillars.
Bridges can now include information about pillars and blocked edges for each bridge piece.

This data is set for default bridges, and NewGRFs can provide their own pillar information.
2025-08-15 23:20:18 +01:00
85af200788 Add: Identify cities on the main viewport by appending an icon to their names (#14504)
Co-authored-by: Peter Nelson <peter1138@openttd.org>
2025-08-15 16:49:25 -04:00
Tyler TrahanandGitHub 3d806d6a65 Fix: 'Map edges' GUI buttons shouldn't initialize with water on northeast edge (#14514) 2025-08-14 08:25:16 -04:00
Peter NelsonandGitHub 980121cdf5 Codefix: Don't store palette for track detail in temporary global variable. (#14516)
Pass palette via parameters instead.
2025-08-14 12:28:36 +01:00
translators 1399efd72a Update: Translations from eints
portuguese: 2 changes by jcteotonio
2025-08-14 04:44:10 +00:00
Peter NelsonandGitHub 376b2f42c9 Fix 0878f71051: Incorrect station layout for even platform counts. (#14515) 2025-08-13 23:18:26 +01:00
Peter NelsonandGitHub 0878f71051 Codechange: Add RailStationTileLayout iterator. (#14510)
This allows iterating a predefined or calculated rail station layout without allocating extra memory and copying.
2025-08-13 17:23:19 +01:00
translators 5b5bdd346d Update: Translations from eints
english (au): 2 changes by krysclarke
chinese (traditional): 2 changes by KogentaSan
english (us): 4 changes by 2TallTyler
chinese (simplified): 2 changes by WenSimEHRP
greek: 2 changes by gh658804
portuguese (brazilian): 2 changes by pasantoro
polish: 2 changes by pAter-exe
2025-08-13 04:43:07 +00:00
Peter NelsonandGitHub f898acae3e Codechange: Remove line break before opening brace of Yapf classes. (#14513) 2025-08-12 21:08:41 +01:00
translators f1a33d50a7 Update: Translations from eints
english (au): 1 change by krysclarke
chinese (simplified): 1 change by WenSimEHRP
2025-08-12 04:42:13 +00:00
Peter NelsonandGitHub b4ebb26c55 Codechange: Remove SpriteGroupType from SpriteGroup. (#14511) 2025-08-11 23:14:44 +01:00
Tyler TrahanandGitHub f596498a28 Fix #14486: Make cargo graph All/None tooltips less specific (#14509) 2025-08-11 16:08:05 -04:00
Peter NelsonandGitHub 1af721a6f0 Add: [Badges] Vehicle variable to query badges of current rail or road types. (#14312) 2025-08-11 19:08:48 +01:00
Peter NelsonandGitHub cd61682ebf Codefix: Don't unnecessarily extract string from bridge CommandCost result. (#14507) 2025-08-10 22:01:03 +01:00
Tyler TrahanandGitHub 78f7060994 Fix: Standardize "rail waypoint" strings (#14505) 2025-08-10 10:56:33 -04:00
translators 3587db6a23 Update: Translations from eints
swedish: 1 change by robert-i
english (us): 1 change by 2TallTyler
portuguese: 1 change by jcteotonio
2025-08-10 04:46:46 +00:00
translators 850bf1c715 Update: Translations from eints
dutch: 6 changes by Afoklala
2025-08-09 04:42:25 +00:00
Peter NelsonandGitHub 4a4613e630 Change: Reduce visual height of default rail waypoints. (#14503)
Added 20 years ago, these were perhaps out of proportion with default rail stations.
2025-08-08 17:53:46 +01:00
froschandrubidium42 66b775016a Fix: Original graphics' tycoon-of-the-century sprite assumes a black background. 2025-08-08 18:15:24 +02:00
KuhnovicandGitHub 40457fc0dd Change: Separate ships travelling in opposite direction (#14493) 2025-08-08 09:52:01 +02:00
translators c8a07fe90b Update: Translations from eints
chinese (traditional): 36 changes by KogentaSan
2025-08-08 04:47:48 +00:00
merni-nsandrubidium42 e1b404089c Fix #13307: Return non-zero value when there is a mistake in command-line arguments
Specifically, when the savegame passed to -q cannot be read or when non-existent/invalid options are passed
2025-08-07 23:28:57 +02:00
Peter NelsonandPeter Nelson e1a50abcbb Codechange: Move fallback font detection to FontCacheFactory.
Provides a standard interface instead of relying on defines.
2025-08-07 19:38:00 +01:00
Peter NelsonandPeter Nelson 140f2b291a Codechange: Use ProviderManager interface to register FontCache factories.
This removes use of #ifdefs to select the appropriate loader, and also replaces FontCache self-registration.
2025-08-07 19:38:00 +01:00
Peter NelsonandGitHub ed1262cab9 Codefix: Move provider instances to static members. (#14501)
Avoids misnaming in global scope.
2025-08-07 09:21:44 +01:00
translators 2b6cb8a2d2 Update: Translations from eints
english (au): 1 change by krysclarke
norwegian (bokmal): 1 change by eriksorngard
chinese (traditional): 2 changes by KogentaSan
greek: 1 change by gh658804
hungarian: 1 change by vargaviktor
german: 190 changes by Wuzzy2
russian: 1 change by Ln-Wolf
finnish: 1 change by hpiirai
portuguese (brazilian): 1 change by pasantoro
polish: 3 changes by pAter-exe
2025-08-07 04:48:50 +00:00
Peter NelsonandGitHub 1ccbd735d8 Codechange: Extract function to draw custom rail station foundations. (#14492) 2025-08-06 23:46:53 +01:00
translators 73a69fd171 Update: Translations from eints
swedish: 55 changes by robert-i
norwegian (bokmal): 8 changes by eriksorngard
spanish (mexican): 1 change by absay
chinese (simplified): 1 change by WenSimEHRP
2025-08-06 04:47:48 +00:00
Mizuki NguyenandGitHub 45929c1672 Add: Currency: Vietnamese Dong (#14474) 2025-08-05 20:16:12 +01:00
Peter NelsonandGitHub cb12a59eed Fix #14495: Dangling references in Industry Production graph window. (#14496) 2025-08-05 20:14:55 +01:00
Peter NelsonandGitHub 439723b718 Codechange: Use handler structs for NewGRF action map sprite groups. (#14489)
Reduces code duplication for mapping sprite groups across GRF features.
2025-08-05 20:14:30 +01:00
Peter NelsonandGitHub b0f247df23 Fix #14498: Crash when cloning aircraft with no orders. (#14499) 2025-08-05 20:08:23 +01:00
Tyler TrahanandGitHub 8c58fb1efd Fix: Missing button beeps (#14470) 2025-08-05 13:57:45 -04:00
translators dea40880a4 Update: Translations from eints
english (us): 5 changes by 2TallTyler
portuguese: 2 changes by jcteotonio
polish: 1 change by pAter-exe
2025-08-05 04:48:13 +00:00
translators d545cec9a2 Update: Translations from eints
english (au): 5 changes by krysclarke
chinese (traditional): 7 changes by KogentaSan
chinese (simplified): 11 changes by WenSimEHRP
korean: 5 changes by telk5093
greek: 7 changes by gh658804
hungarian: 5 changes by vargaviktor
russian: 7 changes by Ln-Wolf
finnish: 5 changes by hpiirai
portuguese: 5 changes by jcteotonio
portuguese (brazilian): 5 changes by pasantoro
polish: 6 changes by pAter-exe
2025-08-04 04:50:00 +00:00
Peter NelsonandGitHub 5b1c6772da Fix 557fb0bd78, bd57aee3a9: Remove separate x-axis label for industry/town production graph. (#14497)
This is no longer necessary (and is wrong) as it's now part of the horizontal scale selector.
2025-08-03 20:04:17 +01:00
Peter NelsonandGitHub 5ee186e850 Codefix: Possible use of uninitialised variable. (#14494)
Realistically this can't happen but gcc 12.2 warns.
2025-08-03 10:48:26 +00:00
translators 61c1f2a35b Update: Translations from eints
polish: 6 changes by pAter-exe
2025-08-03 04:48:21 +00:00
Peter NelsonandGitHub bd57aee3a9 Add: Town cargo history graphs. (#14461) 2025-08-02 23:19:43 +01:00
kojonek2andrubidium42 aac3a5b683 Fix #12900: Join station window will be shown for stations with existing stations in tile gaps 2025-08-02 20:37:02 +02:00
translators 8f9d4150bc Update: Translations from eints
norwegian (bokmal): 11 changes by eriksorngard
english (us): 6 changes by 2TallTyler
korean: 6 changes by telk5093
dutch: 6 changes by Afoklala
2025-08-02 04:46:00 +00:00
translators 4d03b4b618 Update: Translations from eints
portuguese: 1 change by jcteotonio
2025-08-01 04:49:17 +00:00
Loïc GuillouxandGitHub 2a0e0b4b68 Fix #14490, 0455627d: Incorrect detection of final order when drawing timetable (#14491) 2025-08-01 03:39:02 +02:00
Ian EarleandGitHub ec7c8dd095 Codefix: Updating doxygen file documentation string for group_sl.cpp (#14488) 2025-07-31 12:39:22 -04:00
Tyler TrahanandGitHub 48e3aa1027 Fix #14415: Update survey option text when changing setting (#14487) 2025-07-31 06:03:51 -04:00
translators 22bcb8bd46 Update: Translations from eints
english (au): 6 changes by krysclarke
chinese (traditional): 8 changes by KogentaSan
spanish (mexican): 6 changes by absay
greek: 6 changes by gh658804
hungarian: 6 changes by vargaviktor
russian: 6 changes by Ln-Wolf
finnish: 6 changes by hpiirai
portuguese: 6 changes by jcteotonio
portuguese (brazilian): 6 changes by pasantoro
2025-07-31 04:47:22 +00:00
translators fe95782047 Update: Translations from eints 2025-07-30 04:47:35 +00:00
Peter NelsonandPeter Nelson 557fb0bd78 Change: Add support for different horizontal graph scales. 2025-07-30 01:13:05 +01:00
Peter NelsonandPeter Nelson d09dfd843c Codechange: Extend industry cargo history to 24 years.
Monthly data is stored for the current 24 months.
Quarterly data is stored for a further 2-6 years.
Yearly data is stored for a further 6-24 years.
2025-07-30 01:13:05 +01:00
translators 8675d7b498 Update: Translations from eints
chinese (simplified): 5 changes by WenSimEHRP
2025-07-29 04:48:22 +00:00
translators 7c8759552a Update: Translations from eints
japanese: 40 changes by akaregi
hungarian: 6 changes by nemesbala
2025-07-28 04:48:20 +00:00
Peter NelsonandGitHub 614a01907a Codechange: Make functions for click and confirm beeps. (#14484)
Avoids repetition.
2025-07-27 21:54:32 +01:00
Peter NelsonandGitHub f51067f9f5 Codechange: Give all bridge sprite tables descriptive names. (#14483)
Finish off the work started 17 years ago...
2025-07-27 20:14:37 +01:00
Peter NelsonandGitHub 009b7cbc57 Fix #14480: Music player playlist buttons are clickable but non-operational in intro menu. (#14482)
In the intro menu the music is hardcoded to be the introduction track. Therefore, prevent these buttons being clickable.
2025-07-27 16:03:47 +01:00
translators 79524af5fc Update: Translations from eints
spanish (mexican): 6 changes by absay
galician: 6 changes by pvillaverde
dutch: 6 changes by Afoklala
polish: 3 changes by pAter-exe
2025-07-27 04:48:17 +00:00
translators d764d59f5a Update: Translations from eints
chinese (traditional): 7 changes by KogentaSan
welsh: 62 changes by Ansbaradigeidfran
2025-07-26 04:46:16 +00:00
Peter NelsonandGitHub 13759e9f23 Fix: Display GRFID in correct hex format. (#14478) 2025-07-25 08:41:48 +01:00
translators 3e06c69e26 Update: Translations from eints
portuguese: 1 change by jcteotonio
polish: 6 changes by pAter-exe
2025-07-25 04:47:26 +00:00
translators 7eb042feac Update: Translations from eints
english (us): 5 changes by 2TallTyler
2025-07-24 04:46:38 +00:00
Peter NelsonandPeter Nelson 10eeba86a6 Codechange: Simplify/breakout logic for selecting bridge table sprites.
Move various base offsets to separate functions where they can be reused and documented.

No longer rely on coincidences to select the correct data between bridges and aqueducts.
2025-07-23 20:31:15 +01:00
Peter NelsonandPeter Nelson d99dad9e9e Codechange: Pass bridge pillar palette/sprite by reference. 2025-07-23 20:31:15 +01:00
translators ae917cb8c6 Update: Translations from eints
vietnamese: 134 changes by MagicalDrizzle
2025-07-23 04:48:20 +00:00
translators 6d95cea73a Update: Translations from eints
english (au): 5 changes by krysclarke
korean: 6 changes by telk5093
greek: 5 changes by gh658804
russian: 5 changes by Ln-Wolf
finnish: 5 changes by hpiirai
portuguese: 5 changes by jcteotonio
portuguese (brazilian): 5 changes by pasantoro
2025-07-22 04:46:31 +00:00
Peter NelsonandGitHub 921d83c324 Codechange: Unify structures with sprite sub-tile bounds and simplify bounding boxes. (#14424)
Lots of different structs contain variations on sub-tile bounds with different naming. Unify into a single struct that can be inherited and passed directly to AddSortableSpriteToDraw.

At the same time, offsets now work more logically: sub-tile bounds now specify the bounding box, and an offset can be applied to the sprite.
2025-07-22 00:02:00 +01:00
Peter NelsonandGitHub c69fc76395 Codefix: Rail type bridge offset is not a SpriteID. (#14471) 2025-07-21 20:00:04 +00:00
translators 1d21edde8d Update: Translations from eints
english (us): 1 change by 2TallTyler
2025-07-21 04:47:54 +00:00
Peter NelsonandGitHub b82ffa3542 Codechange: Decouple glyph map from SpriteFontCache instances. (#14449)
This makes the map independent from the SpriteFontCache instances.
2025-07-20 22:58:43 +01:00
Peter NelsonandGitHub 8e2df7809b Codechange: Add distinct type to hold pixel drawing colour. (#14457)
This is used for individual pixels as well as line drawing.
2025-07-20 22:57:55 +01:00
Jonathan G Rennisonandrubidium42 821784004d Fix: [Linkgraph] Incorrect NodeID to StationID conversion for EraseFlows 2025-07-20 16:07:11 +02:00
Jonathan G Rennisonandrubidium42 f0447d59d4 Codechange: Use StationID as StationIDStack Titem type 2025-07-20 16:06:03 +02:00
Jonathan G Rennisonandrubidium42 cbdd358ae8 Codechange: Allow SmallStack Titem type to be non-structural 2025-07-20 16:06:03 +02:00
Peter NelsonandGitHub 2cdd50f40e Fix 03f5f7145f: Wrong colour used when string POP_COLOURs back to initial colour. (#14468)
Fixing ellipsis colour broke the PUSH_COLOUR/POP_COLOUR system, reverting to the last used colour instead of the initial colour.
2025-07-20 14:30:18 +01:00
Peter NelsonandPeter Nelson 56942a15c7 Add: Industry accepted and waiting history graphs.
Records amount of cargo accepted, and a rolling average of the waiting amount.

Average waiting samples the waiting amount once per day for each industry, spread out over an economy day.
2025-07-20 14:03:54 +01:00
Peter NelsonandPeter Nelson 5eeda026a4 Codechange: Allow unused graph ranges to be masked. 2025-07-20 14:03:54 +01:00
Peter NelsonandGitHub edc5b8ea1f Fix #14464: Invalid string parameter in scenario editor when unable to build industry. (#14465)
Resolved by removing the Build Industry command callback. This was used to display an error message in the scenario editor, however an error is already automatically displayed.
2025-07-20 14:03:29 +01:00
Peter NelsonandGitHub a8650c6b06 Codechange: Make SpriteCacheCtrlFlags an enum bit set. (#14462)
Due to header dependencies, this requires types to split from the spritecache header.
2025-07-19 23:49:15 +01:00
Peter NelsonandGitHub 7bb4940ebd Codechange: Use unique_ptr for all pointers in script instance. (#14339)
Removes manual memory management with new/delete.
2025-07-19 09:29:30 +01:00
translators b8e56cd05d Update: Translations from eints
chinese (traditional): 3 changes by KogentaSan
chinese (simplified): 1 change by ahyangyi
2025-07-19 04:43:14 +00:00
Peter NelsonandGitHub df5237e721 Fix: Vehicle liveries did not update when switching company. (#14456)
Vehicle liveries must be refreshed if "Show vehicle-type specific liveries" is set to "Own company".
2025-07-18 23:43:07 +00:00
Peter NelsonandGitHub 03f5f7145f Fix f6e78a480d: Truncation ellipsis always drawn in initial colour. (#14451)
Truncation ellipsis is now a layouted line, so we can no longer rely on implicitly using the last set colour.
2025-07-18 18:24:19 +01:00
Peter NelsonandGitHub 0dc40877fd Codechange: Initialise/reset font cache with FontSizes bitset. (#14448)
Instead of choosing either "Normal/Small/Large" or "Monospace", use an EnumBitSet to allow any combination.
2025-07-18 18:23:28 +01:00
Jonathan G RennisonandGitHub 03672ed8eb Fix: EngineImageType mismatch between sizing and drawing in preview window (#14455) 2025-07-18 07:02:46 -04:00
Loïc GuillouxandGitHub 1b01a0636c Fix #14362, 4b677e8256: Don't crash old scripts doing silly instantiation (#14394) 2025-07-17 13:30:33 +02:00
nikolasandGitHub bccbd64037 Fix: GL error typo (#14376) 2025-07-17 07:18:35 +01:00
Ivan PravdinandGitHub 434163aa31 Fix #14277: Aircraft can land when Zeppeliner in the runway (#14317) 2025-07-17 07:26:57 +02:00
translators 55605ae8f2 Update: Translations from eints
english (au): 1 change by krysclarke
catalan: 1 change by J0anJosep
portuguese: 8 changes by jcteotonio
2025-07-17 04:45:55 +00:00
Jonathan G RennisonandGitHub 7f792e9c5f Codefix: Spelling error in name of GetGRFStringTextStackParameters (#14447) 2025-07-16 09:21:25 -04:00
translators 6b6caa6fa8 Update: Translations from eints
chinese (traditional): 1 change by KogentaSan
greek: 1 change by gh658804
hungarian: 1 change by vargaviktor
russian: 1 change by Ln-Wolf
finnish: 1 change by hpiirai
catalan: 49 changes by J0anJosep
portuguese: 2 changes by jcteotonio
portuguese (brazilian): 1 change by pasantoro
polish: 1 change by pAter-exe
2025-07-16 04:46:46 +00:00
Peter NelsonandGitHub 67e56391c7 Fix #8167: No error sub-message when trying to clear protected buildings. (#14444) 2025-07-14 23:23:15 +01:00
Peter NelsonandGitHub e015e3ecc3 Codefix 3fde611012: AirportMovingDataFlag should be enum class (#14435)
`AirportMovingDataFlag` was changed to use `enum class` naming style, but wasn't actually changed to be `enum class`.
2025-07-14 23:22:51 +01:00
Henry Wilsonandrubidium42 8330957a4d Codechange: Remove manual memory management from IcuStringIterator 2025-07-14 23:55:24 +02:00
Peter NelsonandPeter Nelson 9ce2aca949 Codechange: Get/pass ScriptStorage by reference instead of pointer. 2025-07-14 19:19:29 +01:00
Peter NelsonandPeter Nelson 55098a2f2e Codechange: Get/pass engine by reference instead of pointer. 2025-07-14 19:19:29 +01:00
Peter NelsonandPeter Nelson 7ff0c67f77 Codechange: Get/pass script controller by reference instead of pointer. 2025-07-14 19:19:29 +01:00
Peter NelsonandGitHub b2de1ff66f Fix #14433: Broken road stop drawing due to incorrect modes conversion. (#14434)
The mask was treated as a single RoadStopDrawMode instead of a RoadStopDrawModes bitset.
2025-07-14 17:25:53 +01:00
Loïc GuillouxandGitHub fc924161ab Fix 0455627d: Don't draw timetable panel if no orders (#14441) 2025-07-14 14:18:54 +00:00
Peter NelsonandGitHub 61a299bc99 Codechange: Use SpriteID as GlyphID for SpriteFontCache. (#14439)
This reduces the amount of lookups in the character map as rendering a cached layout no longer needs to do so.
2025-07-14 13:28:10 +01:00
Peter NelsonandGitHub 7546c1acab Codefix f220ed179d: GetUnicodeGlyph takes a unicode character. (#14438)
Previous change erroneously changed type to GlyphID, based on naming. It should actually be char32_t.
2025-07-14 08:01:42 +00:00
Peter NelsonandGitHub a6143eea21 Codechange: Include more relevant headers for script_storage. (#14437) 2025-07-14 07:49:50 +01:00
Peter NelsonandPeter Nelson 1d38cbafcb Codechange: Use unique_ptr for ScriptInfo instances.
Replaces raw pointers, slightly.
2025-07-14 00:10:14 +01:00
Peter NelsonandPeter Nelson 992d58d799 Codechange: Pass ScriptInfo by reference to IsSameScript. 2025-07-14 00:10:14 +01:00
Peter NelsonandPeter Nelson 8f34b7a821 Codechange: Keep Squirrel engine in unique_ptr. 2025-07-14 00:10:14 +01:00
Peter NelsonandGitHub bf6d0c4934 Codechange: Don't pre-fill font metrics when loading fonts. (#14436)
Each font cache implementation sets its own metrics based on the loaded font, so there is no need to pre-fill with (unscaled, invalid) default metrics.
2025-07-13 23:38:31 +01:00
Michael LutzandGitHub 3c4fb21a5e Fix: [Win32] Link failure with newer Windows SDK version due to WinRT changes. (#14432) 2025-07-13 22:34:32 +01:00
translators baced00e9f Update: Translations from eints
spanish (mexican): 1 change by absay
english (us): 1 change by 2TallTyler
galician: 10 changes by pvillaverde
dutch: 1 change by Afoklala
portuguese: 10 changes by jcteotonio
2025-07-13 04:45:12 +00:00
translators aaf5d39b15 Update: Translations from eints
english (au): 1 change by krysclarke
chinese (traditional): 1 change by KogentaSan
chinese (simplified): 1 change by WenSimEHRP
korean: 1 change by telk5093
greek: 1 change by gh658804
russian: 1 change by Ln-Wolf
finnish: 1 change by hpiirai
portuguese: 1 change by azulcosta
portuguese (brazilian): 1 change by pasantoro
polish: 1 change by pAter-exe
2025-07-11 04:45:38 +00:00
Richard WheelerandGitHub 7db135099a Fix: Scale graph gridlines and axes with GUI scale (#12131) 2025-07-10 00:05:48 +01:00
Peter NelsonandPeter Nelson 290144c5c9 Fix #14396: Industry production graph showed zero instead of N/A.
Record the number of valid history records per industry so that the graph avoids showing values which are not present as zero.
2025-07-09 23:02:58 +01:00
Peter NelsonandPeter Nelson 9b55ad5b8d Codechange: Generic type and container for history statistics. 2025-07-09 23:02:58 +01:00
Peter NelsonandGitHub f6e78a480d Change: Make truncation ellipsis translatable. (#14417) 2025-07-09 22:55:43 +01:00
Tyler TrahanandGitHub 259830777c Fix #14375: When loading config, validate timekeeping mode and minutes per year (#14405) 2025-07-09 16:04:38 -04:00
Tyler TrahanandGitHub 753905ae2d Fix #14377: Make house picker window remember house protection state when closed (#14406) 2025-07-09 14:18:19 +00:00
Peter NelsonandGitHub d2ee2add28 Codechange: Remove ZOOM_LVL_GUI macro. (#14423) 2025-07-09 11:05:06 +01:00
translators 8de32c4509 Update: Translations from eints
portuguese: 7 changes by jcteotonio
2025-07-09 04:45:29 +00:00
Peter NelsonandGitHub 77b572619a Codechange: Make use of ZoomLevels range iteration. (#14422) 2025-07-08 14:00:12 +01:00
Peter NelsonandGitHub b21c8a3450 Codechange: Simplify test for bridges above bridge ramps. (#14421) 2025-07-08 13:55:36 +01:00
translators 6d86c760c6 Update: Translations from eints
hungarian: 9 changes by vargaviktor
2025-07-08 04:43:02 +00:00
translators d44e693b25 Update: Translations from eints
norwegian (bokmal): 17 changes by eriksorngard
spanish (mexican): 6 changes by absay
english (us): 21 changes by 2TallTyler
2025-07-07 04:45:34 +00:00
translators b0ea6c0974 Update: Translations from eints
chinese (traditional): 6 changes by KogentaSan
chinese (simplified): 6 changes by WenSimEHRP
2025-07-06 04:44:01 +00:00
Peter NelsonandGitHub 84e9e106c1 Codefix: SpriteFontCache was never deleted. (#14414) 2025-07-05 13:22:45 +01:00
translators ebd984d894 Update: Translations from eints
english (au): 3 changes by krysclarke
korean: 6 changes by telk5093
greek: 3 changes by gh658804
russian: 3 changes by Ln-Wolf
dutch: 6 changes by Afoklala
portuguese: 4 changes by jcteotonio
portuguese (brazilian): 3 changes by pasantoro
2025-07-05 04:43:09 +00:00
translators f23845805a Update: Translations from eints
english (au): 6 changes by krysclarke
greek: 7 changes by gh658804
russian: 6 changes by Ln-Wolf
finnish: 25 changes by hpiirai
portuguese: 19 changes by jcteotonio
portuguese (brazilian): 6 changes by pasantoro
polish: 6 changes by pAter-exe
2025-07-04 04:42:38 +00:00
Loïc GuillouxandGitHub 655291facb Fix #14385: [Strgen] Don't count parameters more than one time (#14413) 2025-07-04 01:10:50 +02:00
Peter NelsonandGitHub 16b0371c1b Codechange: Remove owner from CargoPayment. (#14411)
Owner can instead be looked up from the CargoPayment's vehicle.

This reduces the size of each CargoPayment slightly.
2025-07-03 23:11:12 +01:00
Heikki Piirainenandrubidium42 febba930b0 Fix: Inconsistent capitalization in game settings 2025-07-03 17:11:51 +02:00
translators bf07751ee7 Update: Translations from eints
spanish (mexican): 12 changes by absay
portuguese: 1 change by jcteotonio
2025-07-03 04:44:02 +00:00
Tyler TrahanandGitHub e578668a93 Fix #14360: Don't reuse strings for Low/Medium/High setting values (#14409) 2025-07-02 06:09:39 -04:00
translators 226b098c55 Update: Translations from eints
portuguese: 17 changes by jcteotonio
2025-07-02 04:42:46 +00:00
Peter NelsonandGitHub 0391eec189 Change: Improve sprite ellipsis appearance. (#14404)
Make spacing more consistent with periods.
2025-07-01 17:34:26 +01:00
translators b84b641ed9 Update: Translations from eints
hungarian: 7 changes by vargaviktor
2025-07-01 04:45:31 +00:00
Peter NelsonandGitHub 4fe6adb2dd Fix c2d4098afa: Crash when accessing unconfigurable badge feature. (#14403)
Some features support badges but do not have a way to configure them. Accessing these features could crash the game.
2025-06-30 21:45:08 +01:00
Peter NelsonandGitHub 36d7e09369 Fix: Include sort button width in content list header minimal size. (#14402) 2025-06-30 20:40:26 +01:00
Peter NelsonandGitHub 42a9d27fd9 Fix: Don't draw truncation ellipsis if it's too wide. (#14401) 2025-06-30 20:40:04 +01:00
Peter NelsonandGitHub 80d2194511 Fix: Don't include ellipsis width in RTL truncation offset. (#14400)
This caused the right-most glyphs to be truncated.
2025-06-30 10:03:24 +01:00
translators 7c33a67e7b Update: Translations from eints
galician: 30 changes by pvillaverde
danish: 6 changes by bscargo
2025-06-30 04:44:29 +00:00
translators 9bcf1cf29b Update: Translations from eints
korean: 8 changes by telk5093
polish: 3 changes by pAter-exe
2025-06-29 04:45:43 +00:00
Peter NelsonandGitHub 4b6d409ee8 Codefix: Out-of-range cargo type passed to a string affected remaining parameters. (#14398)
When the string codes CARGO_TINY, CARGO_SHORT or CARGO_LONG encountered an out-of-range string, they did not read the extra amount parameter. This leads to later parameters being used in the wrong place.

Change the order of operation so that all parameters for these string codes are always read, even if the cargo type is not valid.
2025-06-28 21:50:36 +01:00
translators a37ad181ff Update: Translations from eints
dutch: 12 changes by Afoklala
polish: 12 changes by pAter-exe
2025-06-28 04:42:40 +00:00
Peter NelsonandGitHub 20ed5be905 Codechange: Use FontSizeToName() instead of switch block. (#14395) 2025-06-27 20:38:39 +00:00
translators f41ad372a3 Update: Translations from eints
chinese (traditional): 1 change by KogentaSan
2025-06-27 04:42:22 +00:00
Peter NelsonandPeter Nelson bd2430dc94 Codechange: Use FlatSet to avoid trying to add variant parents multiple times. 2025-06-26 08:33:34 +01:00
Peter NelsonandPeter Nelson 1ddc03b916 Codechange: Give FlatSet insert() a return value.
This now returns an iterator, and whether an insert was performed.

Allows the caller to know if the item was already in the FlatSet without explicitly checking first.
2025-06-26 08:33:34 +01:00
translators 1ff12b6e74 Update: Translations from eints
english (au): 8 changes by krysclarke
chinese (traditional): 23 changes by KogentaSan
chinese (simplified): 12 changes by WenSimEHRP
greek: 8 changes by gh658804
russian: 6 changes by Ln-Wolf
finnish: 8 changes by hpiirai
portuguese: 9 changes by jcteotonio
portuguese (brazilian): 8 changes by pasantoro
2025-06-26 04:43:34 +00:00
Peter NelsonandGitHub d5ebd20110 Fix 319caef58f: Buildings with non-zero subtile offsets broken in house picker. (#14390)
Partially reverts 319caef58f. Conversion of subtile position was originally correct.
2025-06-25 17:33:15 +00:00
translators b3c96a7785 Update: Translations from eints
english (au): 4 changes by krysclarke
norwegian (bokmal): 4 changes by eriksorngard
chinese (traditional): 4 changes by KogentaSan
korean: 4 changes by telk5093
greek: 4 changes by gh658804
hungarian: 4 changes by vargaviktor
russian: 4 changes by Ln-Wolf
finnish: 4 changes by hpiirai
portuguese: 4 changes by jcteotonio
portuguese (brazilian): 4 changes by pasantoro
2025-06-25 04:42:43 +00:00
Peter NelsonandGitHub 8f01ae675e Revert 0853c1979b: Button to toggle showing advanced signal types (#9617) (#14219) 2025-06-24 20:18:08 +02:00
Peter NelsonandGitHub a46a3a97f3 Change: New company face definition system and UI. (#14319)
Bits used by company faces are now defined by a variable system instead of being hardcoded, allowing future expansion.

The four face types covering gender and skin colour are now separate face styles with their own definitions.
2025-06-24 07:59:49 +01:00
translators ebc74c8905 Update: Translations from eints 2025-06-24 04:43:09 +00:00
Jonathan G RennisonandPeter Nelson e436b32468 Codechange: Remove now unused sprite cache memory error strings 2025-06-23 21:22:37 +01:00
Peter NelsonandPeter Nelson 7744f49a9e Change: Simplify sprite cache memory management
* Remove custom allocator
* Use std::unique_ptr for sprite data
* Perform LRU cache eviction in a single pass
2025-06-23 21:22:37 +01:00
Peter NelsonandGitHub 1d67094863 Add: Buttons to change picker preview image height. (#14373)
Adjusted height is remembered per picker type, but not saved.
2025-06-23 08:24:49 +01:00
Peter NelsonandGitHub 8901f9adca Fix #14361: Removing a badge filter did not clear it. (#14379) 2025-06-23 08:24:03 +01:00
translators c15568be5f Update: Translations from eints
ukrainian: 20 changes by StepanIvasyn
latvian: 13 changes by lexuslatvia
2025-06-22 04:43:50 +00:00
Patric StoutandGitHub 3571f77d46 Codechange: typo in GoG's workflow (#14386) 2025-06-21 09:25:39 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
1b2a3b0cb1 Upgrade: Bump Apple-Actions/import-codesign-certs in the actions group (#13945)
Bumps the actions group with 1 update: [Apple-Actions/import-codesign-certs](https://github.com/apple-actions/import-codesign-certs).

Updates `Apple-Actions/import-codesign-certs` from 3 to 5
- [Release notes](https://github.com/apple-actions/import-codesign-certs/releases)
- [Commits](https://github.com/apple-actions/import-codesign-certs/compare/v3...v5)

---
updated-dependencies:
- dependency-name: Apple-Actions/import-codesign-certs
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-21 09:18:32 +00:00
Peter NelsonandGitHub 5766ba51d7 Codefix: Clean up incorrect indentation for multi-line comments. (#14383) 2025-06-20 19:01:44 +01:00
translators a927925996 Update: Translations from eints
portuguese: 13 changes by jcteotonio
2025-06-20 04:42:53 +00:00
translators de6e420917 Update: Translations from eints
ukrainian: 11 changes by StepanIvasyn
portuguese: 18 changes by jcteotonio
2025-06-19 04:43:06 +00:00
Adam ZmudaandGitHub 9238f508eb Fix #14081: Check if removed item is a savegame (#14371) 2025-06-18 10:05:18 +02:00
translators 7aa4e7fc58 Update: Translations from eints
ukrainian: 12 changes by StepanIvasyn
portuguese: 8 changes by jcteotonio
2025-06-18 04:43:22 +00:00
Peter NelsonandGitHub c882ad5142 Fix: Allow object picker to resize if there are no classes. (#14372) 2025-06-17 19:04:34 +01:00
Peter NelsonandGitHub e4cf6ca0ba Fix: Mis-sized widgets due to missing widget fill. (#14370)
In most places where we calculate and set widget resize step we neglect
to set widget fill step to match. Initial widget sizing uses fill step
instead of resize step, which means the initial size may not be a
multiple of the resize step as intended. In particular this will cause
WWT_MATRIX to be misrendered.

Whether or not this matters depends on the widget type being resized and
the window layout, however for consistency always set fill step to the
same as resize step when calculating.
2025-06-17 17:40:11 +01:00
Peter NelsonandPeter Nelson 4144865c73 Change: Tweak layout of music player widgets.
This removes some magic numbers and gets rid of spacers.
2025-06-17 08:54:08 +01:00
Peter NelsonandPeter Nelson 7ec78e94db Fix: Don't include height of blank text in frame and inset widgets. 2025-06-17 08:54:08 +01:00
translators dd826ea49c Update: Translations from eints
spanish: 13 changes by Unely
portuguese: 30 changes by jcteotonio
2025-06-17 04:41:57 +00:00
Peter NelsonandGitHub 009b68caeb Codechange: Use toolbar minimal sizing with intro menu buttons. (#14368)
The intro menu buttons use toolbar icons, so use SetToolbarMinimalSize() on them for consistency.
2025-06-17 01:12:39 +01:00
Colin CaineandGitHub 5f8e04457e Codechange: Use default OnHotkey handler for focusing editboxes (#14358) 2025-06-16 22:25:54 +02:00
56bc391763 Codechange: Remove manual memory management of AIScannerInfo::info_dummy (#14338)
Co-authored-by: Henry Wilson <henry@henryandlizzy.uk>
2025-06-16 10:30:22 +01:00
translators ea410cfe85 Update: Translations from eints
chinese (traditional): 4 changes by KogentaSan
chinese (simplified): 69 changes by WenSimEHRP
ukrainian: 57 changes by StepanIvasyn
portuguese: 35 changes by jcteotonio
2025-06-16 04:43:21 +00:00
c71515e790 Codechange: Remove manual memory management from CountArticulatedParts (#14336)
Co-authored-by: Henry Wilson <henry@henryandlizzy.uk>
2025-06-15 21:38:00 +01:00
Peter NelsonandGitHub cdd555edd5 Codechange: Use vector with unique_ptr instead of linked-list for base set lists. (#14332) 2025-06-15 21:32:29 +01:00
Michael LutzandGitHub e163aab892 Fix: Train path reservations on different railtypes could join leading to train crashes. (#14366)
This could happen if the compatibility between the railtypes was not symmetric. If for
example a reservation of a first train ended at a railtype transition with an already present
reservation on the other side, a reversing train could end up crashing with the first train.
2025-06-15 22:09:04 +02:00
translators 98b488f366 Update: Translations from eints
chinese (traditional): 3 changes by KogentaSan
chinese (simplified): 108 changes by WenSimEHRP
ukrainian: 21 changes by StepanIvasyn
dutch: 9 changes by Afoklala
portuguese: 177 changes by jcteotonio
2025-06-15 04:42:32 +00:00
Loïc GuillouxandGitHub d0b56022d8 Fix #14362, 4b677e8256: Class with non static methods may have a default constructor (#14363) 2025-06-14 23:39:22 +02:00
Peter NelsonandGitHub 1cd0391926 Fix #14356, ff7eb996e6: Incorrect sprite group chosen for stations and road stops. (#14359) 2025-06-14 13:38:45 +01:00
glx22andLoïc Guilloux 8e3acbfa84 Codechange: Deduplicate DefSQClass::DefSQ[Static]Method() 2025-06-14 12:41:39 +02:00
glx22andLoïc Guilloux 90e21bc713 Codechange: Remove useless SQConstruct parameters 2025-06-14 12:41:39 +02:00
glx22andLoïc Guilloux 4b677e8256 Codechange: Don't export default constructors 2025-06-14 12:41:39 +02:00
glx22andLoïc Guilloux ccffbb4142 Codechange: Remove manual param count for constructors too 2025-06-14 12:41:39 +02:00
glx22andLoïc Guilloux 6d601e2eb1 Codechange: Use more descriptive variable names 2025-06-14 12:41:39 +02:00
translators a1786fa1f4 Update: Translations from eints
norwegian (bokmal): 13 changes by eriksorngard
ukrainian: 28 changes by StepanIvasyn
portuguese: 16 changes by jcteotonio
polish: 1 change by pAter-exe
2025-06-13 04:42:21 +00:00
Jonathan G RennisonandPeter Nelson d3e4e07daa Codechange: Remove ReferenceThroughBaseContainer 2025-06-12 18:50:49 +01:00
Jonathan G RennisonandPeter Nelson 63f1c2aa3a Codechange: Use TypedIndexContainer for typed index containers
Instead of ReferenceThroughBaseContainer
2025-06-12 18:50:49 +01:00
Jonathan G RennisonandPeter Nelson d0e49a297f Codechange: Add TypedIndexContainer adapter type
This is equivalent in functionality to ReferenceThroughBaseContainer,
except only for the correct index type, instead of any type matching
ConvertibleThroughBase.
The also serves to unambiguously document the index type at the
point of definition of the container.
2025-06-12 18:50:49 +01:00
Peter NelsonandGitHub 401ebed03a Add: Show and sort online content version in list. (#14355) 2025-06-12 18:27:16 +01:00
translators b012d9e3dc Update: Translations from eints
danish: 18 changes by bscargo
portuguese: 23 changes by jcteotonio
2025-06-12 04:42:39 +00:00
Peter NelsonandGitHub 28cc0079f2 Codechange: Create ScriptAllocator with make_unique instead of new. (#14340) 2025-06-11 23:28:08 +01:00
Peter NelsonandGitHub b2d69ae606 Codechange: Use AutoRelease to simplify cleanup after FontConfig calls. (#14354) 2025-06-11 21:24:31 +01:00
Peter NelsonandGitHub 9c16603da6 Codechange: Add AutoRelease helper to use function as unique_ptr deleter. (#14353)
This allows passing the function as a template parameter instead of requiring a custom deleter functor.
2025-06-11 20:13:49 +01:00
translators f8776b0a6f Update: Translations from eints
hungarian: 9 changes by vargaviktor
finnish: 13 changes by hpiirai
ukrainian: 1 change by imlystyi
tamil: 2 changes by merni-ns
lithuanian: 1 change by khamper
spanish: 22 changes by Unely
portuguese: 46 changes by jcteotonio
2025-06-11 04:42:30 +00:00
Peter NelsonandGitHub f2318c35db Fix 0455627d16: Order backups were no longer created when selling vehicles. (#14352) 2025-06-10 18:03:05 +01:00
Peter NelsonandGitHub c702e05517 Codechange: Replace C-casts for FontConfig with helper functions. (#14349)
Add `ToFcString()` and `FromFcString()` to remove C-style casts and make reinterpret_casts safer and clearer.
2025-06-10 17:11:22 +01:00
Peter NelsonandGitHub 8f5ac84a3d Fix 20738865f0: Remove colour codes from Game Options strings. (#14348)
When merging the game options and settings windows, colour codes were removed from strings. This change didn't get propagated to all translations.
2025-06-10 17:10:57 +01:00
translators 8c90be8c9f Update: Translations from eints
english (au): 9 changes by krysclarke
spanish (mexican): 10 changes by absay
english (us): 9 changes by 2TallTyler
korean: 13 changes by telk5093
lithuanian: 3 changes by khamper
portuguese: 13 changes by jcteotonio
polish: 9 changes by pAter-exe
2025-06-10 04:42:12 +00:00
Peter NelsonandGitHub 4f18c18735 Fix: Remove U+200C characters from Lithuanian translation. (#14347)
This character prevents OpenTTD Sans being used.
2025-06-09 11:53:31 +00:00
translators 3908df5fbe Update: Translations from eints
chinese (traditional): 9 changes by KogentaSan
greek: 9 changes by gh658804
russian: 9 changes by Ln-Wolf
portuguese (brazilian): 9 changes by pasantoro
2025-06-09 04:43:26 +00:00
SamuXarickandGitHub ac8b236885 Fix: [Script] Make ScriptOrder functions aware of road waypoints (#13419) 2025-06-08 16:49:36 -04:00
SamuXarickandGitHub 484f18f987 Codechange: Code style changes to AI/GS GUI files (#13665) 2025-06-08 16:48:36 -04:00
SamuXarickandGitHub 893a75f2c0 Codechange: Iterate with VehiclesOnTile when attaching a just bought wagon to a locomotive (#14284) 2025-06-08 16:45:58 -04:00
Peter NelsonandGitHub de660cba02 Change: Consistent toolbar sizes with dedicated NWidgetParts. (#14344)
Add SetToolbarSpacerMinimalSize() and SetToolbarMinimalSize() NWidgetParts and use to make toolbar button sizes consistent.
2025-06-08 18:13:47 +00:00
Peter NelsonandGitHub 7c9c2aec49 Codechange: Use vehicle tile hash to search for free wagons. (#14343)
Avoids iterating the vehicle pool.
2025-06-08 19:07:43 +01:00
translators 4b18622c4e Update: Translations from eints
chinese (traditional): 4 changes by KogentaSan
english (us): 4 changes by 2TallTyler
french: 4 changes by ottdfevr
2025-06-08 04:43:18 +00:00
Peter NelsonandPeter Nelson 2f725d1e85 Add: Hover on graph legend to highlight line. 2025-06-07 15:50:25 +01:00
Peter NelsonandPeter Nelson 10841ea3fd Codechange: Add constant for common blink interval. 2025-06-07 15:50:25 +01:00
Peter NelsonandGitHub ecafbf884e Add: Allow separate expansion of town buildings and roads in scenario editor. (#14341) 2025-06-07 13:56:43 +00:00
translators 6b5cde463a Update: Translations from eints
english (au): 4 changes by krysclarke
spanish (mexican): 3 changes by absay
greek: 4 changes by gh658804
hungarian: 4 changes by vargaviktor
russian: 5 changes by Ln-Wolf
dutch: 4 changes by Afoklala
portuguese (brazilian): 4 changes by pasantoro
polish: 4 changes by pAter-exe
2025-06-07 04:40:06 +00:00
Loïc GuillouxandGitHub 9339b8270c Fix: Wrong error message about script Save() returned value (#14334) 2025-06-06 19:01:50 +02:00
Peter NelsonandGitHub a6de925ba6 Fix #14333, 20d83677eb: Incorrect change from index to range iteration. (#14335) 2025-06-06 16:57:26 +00:00
glx22andLoïc Guilloux 938acbe6ef Add: [Script] Cloning ScriptList 2025-06-05 22:37:33 +02:00
glx22andLoïc Guilloux 7200e7f509 Add: [Script] Framework for cloning selected ScriptObject 2025-06-05 22:37:33 +02:00
Jonathan G RennisonandGitHub 7dcc932d44 Fix: Drag drop line position when dragging NewGRF from file to active panel (#14316) 2025-06-05 14:09:51 -04:00
Peter NelsonandPeter Nelson 48764b0fed Add: Badge dropdown filters to picker window. 2025-06-05 17:55:24 +01:00
Peter NelsonandPeter Nelson 7b60e5ccad Add: Badge dropdown filters to build vehicle window. 2025-06-05 17:55:24 +01:00
Peter NelsonandPeter Nelson 25f1c97bea Change: Add badge dropdown filters and configuration. 2025-06-05 17:55:24 +01:00
Peter NelsonandPeter Nelson 308ce39747 Codechange: Add DropDownUnselectable component.
This component makes a drop down item unselectable, as it says on the tin.
2025-06-05 17:55:24 +01:00
Peter NelsonandPeter Nelson 82f5af7ecd Codechange: Allow all widget types to have a WidgetID index. 2025-06-05 17:55:24 +01:00
glx22andLoïc Guilloux 31fbb17c5b Codechange: Replace ScriptObject::[SG]etAllowDoCommand with ScriptObject::DisableDoCommandScope 2025-06-05 01:39:40 +02:00
glx22andLoïc Guilloux 4beb23af30 Codechange: TicToc can now accumulate and output every tick 2025-06-04 23:59:06 +02:00
glx22andLoïc Guilloux fca75fd06a Codechange: Use brace counting to detect end of class in squirrel-exporter 2025-06-04 19:48:27 +02:00
glx22andLoïc Guilloux 6482e16564 Codechange: Deduplicate namespace opening in squirrel-exporter 2025-06-04 19:48:27 +02:00
glx22andLoïc Guilloux e0d8158957 Codechange: Don't use literal tabs in squirrel-exporter 2025-06-04 19:48:27 +02:00
Owen Rudge b0dbe631b3 Codechange: [CI] Azure Code Signing has been rebranded 'Trusted Signing' 2025-06-04 09:16:18 +01:00
Peter NelsonandGitHub 2e78c24ba3 Codefix: Use bitset .None() or .Any() instead of comparing against an empty bitset. (#14327) 2025-06-04 07:31:44 +01:00
translators 8f10f9fb5a Update: Translations from eints
finnish: 1 change by hpiirai
2025-06-04 04:43:00 +00:00
Peter NelsonandGitHub 5bf31a431e Fix 4c8f1b0f81: Hidden-by-facility station signs were not ignored when handling clicks. (#14326) 2025-06-03 20:53:53 +00:00
Loïc GuillouxandGitHub 9e8fc8da48 Fix: [Script] SQOpsLimiter had no effect for native valuator/filter (#14322) 2025-06-03 14:05:29 +02:00
Peter NelsonandPeter Nelson ea0b3983a5 Codechange: Deduplicate common parts of graph windows with cargo legends.
This unifies handling on the cargo selected to avoid having to rewrite it for every cargo graph window.
2025-06-02 17:40:39 +01:00
Peter NelsonandPeter Nelson 43d57a6b7e Codefix 5c45738613: Rename CompanyGraphWindow to BaseCompanyGraphWindow.
This makes it clearer that it isn't a final graph window.
2025-06-02 17:40:39 +01:00
translators 6d0dd90e20 Update: Translations from eints
korean: 2 changes by telk5093
portuguese: 2 changes by jcteotonio
2025-06-02 04:43:26 +00:00
Peter NelsonandGitHub b7b2b57805 Fix bd1a3fe0b7: Crash if loading compatibility scripts fails. (#14318) 2025-05-31 19:59:23 +01:00
Peter NelsonandGitHub 4ab48f34f5 Fix 5664b1e2f6: Upgrade button in NewGRF window no longer worked. (#14315) 2025-05-31 08:20:55 +00:00
translators 621c031307 Update: Translations from eints
dutch: 4 changes by Afoklala
2025-05-31 04:39:26 +00:00
Loïc GuillouxandGitHub 2cd3c8db86 Codechange: [Script] Don't report multiple errors on valuator/filter failure (#14303) 2025-05-30 14:38:41 +02:00
translators 10c159a79f Update: Translations from eints
norwegian (bokmal): 4 changes by eriksorngard
korean: 4 changes by telk5093
2025-05-29 04:47:48 +00:00
Peter NelsonandPeter Nelson c233e5ee2c Codechange: Tweak layouts of graph windows to reduce spacers. 2025-05-28 18:40:33 +01:00
Peter NelsonandPeter Nelson 5c45738613 Codechange: Improve inheritance of graph windows.
BaseGraphWindow contains parts that are only relevant to company-series data -- these are moved to a separate class.
2025-05-28 18:40:33 +01:00
translators 3aca5d62a8 Update: Translations from eints
spanish (mexican): 4 changes by absay
chinese (simplified): 4 changes by WenSimEHRP
hungarian: 5 changes by vargaviktor
french: 27 changes by glx22
polish: 4 changes by pAter-exe
2025-05-28 04:47:09 +00:00
Peter NelsonandGitHub 7c9393e822 Codechange: Remove terminator from airport tile lists. (#14306) 2025-05-27 20:23:59 +01:00
translators 808af15975 Update: Translations from eints
english (au): 4 changes by krysclarke
chinese (traditional): 5 changes by KogentaSan
english (us): 5 changes by 2TallTyler
greek: 4 changes by gh658804
russian: 4 changes by Ln-Wolf
finnish: 4 changes by hpiirai
latvian: 6 changes by lexuslatvia
portuguese: 4 changes by jcteotonio
portuguese (brazilian): 4 changes by pasantoro
2025-05-27 04:48:27 +00:00
Peter NelsonandGitHub e2d066e5d3 Codefix: Effect vehicles don't use v->tile, so shouldn't be in the vehicle tile hash. (#14302) 2025-05-26 21:45:46 +01:00
translators e23a591a1e Update: Translations from eints
galician: 10 changes by pvillaverde
turkish: 20 changes by BeratSJ
latvian: 2 changes by lexuslatvia
2025-05-26 04:49:25 +00:00
Peter NelsonandGitHub b042e7a439 Codefix: Prefer static inline const keyword order. (#14301) 2025-05-25 20:32:56 +01:00
Peter NelsonandPeter Nelson 948ceb3b17 Add: Button to configure badges in build picker window. 2025-05-25 09:13:05 +01:00
Peter NelsonandPeter Nelson f28dc3cca4 Add: Button to configure badges in build vehicle window. 2025-05-25 09:13:05 +01:00
Peter NelsonandPeter Nelson c2d4098afa Add: Configuration of NewGRF badges. 2025-05-25 09:13:05 +01:00
Peter NelsonandPeter Nelson daef052329 Add: Generic "configure list/view" vertical ellipsis icon. 2025-05-25 09:13:05 +01:00
Peter NelsonandPeter Nelson 29970fb496 Codechange: Add DropDownToggle component. 2025-05-25 09:13:05 +01:00
Peter NelsonandPeter Nelson 6e90b828c6 Codechange: Add CentreTo Rect method. 2025-05-25 09:13:05 +01:00
Peter NelsonandPeter Nelson c213218b66 Codechange: Pass click state to Dropdown Draw() function.
This allows drawing to change depending on last click position.
2025-05-25 09:13:05 +01:00
Peter NelsonandPeter Nelson 984d864c72 Codechange: Add OnClick handler for dropdown items.
This allows each dropdown item to indicate if something different should happen depending on where in the item was clicked.
2025-05-25 09:13:05 +01:00
Peter NelsonandPeter Nelson 04e07dff84 Codechange: Add Up/Down buttons, to fit in with the settings-button style. 2025-05-25 09:13:05 +01:00
translators b82e32c360 Update: Translations from eints
norwegian (bokmal): 1 change by eriksorngard
spanish (mexican): 1 change by absay
chinese (simplified): 1 change by WenSimEHRP
korean: 1 change by telk5093
danish: 68 changes by bscargo
2025-05-25 04:48:20 +00:00
Loïc GuillouxandGitHub 5e765a2787 Codechange: [CMake] Use ".sq.hpp" instead of ".hpp.sq" for API exports (#14297) 2025-05-24 22:38:37 +02:00
KuhnovicandGitHub 34c0b09764 Codechange: Removed T prefix from water region related types. (#14290) 2025-05-24 18:12:16 +02:00
Loïc GuillouxandGitHub fea120a710 Fix #14295, 0455627d16: v->cur_implicit_order_index is never INVALID_VEH_ORDER_ID (#14296) 2025-05-24 13:53:51 +00:00
translators c366e6a48e Update: Translations from eints
chinese (simplified): 1 change by WenSimEHRP
dutch: 1 change by Afoklala
2025-05-24 04:44:57 +00:00
Peter NelsonandGitHub b42abfbefc Fix 0455627d16: Incorrect script order position mapping. (#14294) 2025-05-23 19:55:22 +01:00
KuhnovicandGitHub 180ec6505b Codechange: Use strong types for water regions. (#14289) 2025-05-23 20:54:42 +02:00
Peter NelsonandGitHub 0455627d16 Codechange: Move ownership of Orders to OrderList. (#13948)
Removes the orders pool, and orders are now stored directly in each OrderList.

Iterating orders now no longer needs to traverse a linked-list, all orders in an OrderList are sequential.
2025-05-23 10:36:28 +01:00
Peter NelsonandPeter Nelson 7344dfe651 Change: Reflow Textfile window content incrementally.
This avoids a stall when reflowing a long text file with some truetype fonts.
2025-05-23 07:42:10 +01:00
Peter NelsonandPeter Nelson 46b745a06a Codechange: Use a helper method to test if text file window is wrapped. 2025-05-23 07:42:10 +01:00
Peter NelsonandPeter Nelson 940071a5f2 Codechange: Add alternating iterator to take elements from middle of range. 2025-05-23 07:42:10 +01:00
Peter NelsonandPeter Nelson 780c26237f Codechange: Add OnScrollbarScroll window event, called when a scrollbar position changes. 2025-05-23 07:42:10 +01:00
translators 321f7e8683 Update: Translations from eints
swedish: 3 changes by joeax910
2025-05-23 04:45:57 +00:00
Peter NelsonandGitHub 1064309ecf Change: Don't measure group name widths in company livery window. (#14291)
Measuring the name width did not also take account of indentation levels so didn't prevent cropping, and the window can be resized anyway.

This avoids a potential bottleneck due to layouting group names if there are a lot of groups present.
2025-05-22 22:57:50 +01:00
SamuXarickandGitHub 5fef32bde7 Change: [Script] Move GSStation::GetOwner to GSBaseStation::GetOwner (#13406)
* Add: [Script] GSBaseStation::GetOwner

Added method for Game Scripts to retrieve the owner of a basestation.

* Cleanup: [Script] Remove ScriptStation::GetOwner

Due to class inheritance, GSStation::GetOwner and GSWaypoint::GetOwner can both reach GetOwner defined at GSBaseStation.
2025-05-22 13:47:04 +02:00
translators 467f832c2f Update: Translations from eints
english (au): 1 change by krysclarke
chinese (traditional): 10 changes by KogentaSan
greek: 1 change by gh658804
russian: 1 change by Ln-Wolf
finnish: 1 change by hpiirai
latvian: 1 change by lexuslatvia
portuguese: 1 change by jcteotonio
portuguese (brazilian): 1 change by pasantoro
polish: 10 changes by pAter-exe
2025-05-22 04:47:11 +00:00
Peter NelsonandGitHub 5fe6578f64 Codechange: Improve performance of exclusive preview engine test. (#14270)
Check group statistics to test if a company has built an exclusive preview engine.

This improves performance by avoiding iterating the vehicle pool.
2025-05-21 21:19:38 +01:00
Peter NelsonandPeter Nelson 9f190aa534 Codechange: Use group's children list to improve performance of group UI. 2025-05-21 19:50:07 +01:00
Peter NelsonandPeter Nelson 000a79c093 Codechange: Improve performance of evaluating group hierarchy.
Store a list of child groups in each group, to avoid having to iterate the group pool to find its children.
2025-05-21 19:50:07 +01:00
SamuXarickandGitHub 8f3f25de4b Codefix: Missing 'this->' in VehiclesNearTileXY::Iterator::Iterator (#14288) 2025-05-21 20:28:47 +02:00
Peter NelsonandGitHub 1d8db2223f Fix #14234, 5aa4ad5135: Crash due to unexpected NUL char in string. (#14235)
Gracefully handle an unexpected NUL character in non-debug builds.
2025-05-21 18:47:04 +01:00
translators 82876c25e0 Update: Translations from eints 2025-05-21 04:46:46 +00:00
Peter NelsonandGitHub a2addf0fe7 Fix: Clear rail vehicle flipped flag if reverse probability callback returns false. (#14281)
This now distinguishes between not-flipped and callback not implemented.
2025-05-20 23:03:55 +01:00
Peter NelsonandGitHub acf594a7b7 Fix #14271, 7fd0e6c27d: Crash due to incorrect parameter index in string. (#14272) 2025-05-20 23:03:27 +01:00
Loïc GuillouxandGitHub 4b1b2a4310 Change: [Script] Don't allow scripts to instantiate ScriptEvent (#14276) 2025-05-20 15:37:05 +02:00
froschandfrosch 2926179d02 Fix: Restore the behaviour when entering numbers in query windows: clamp integers out of range to the maximum valid value. 2025-05-20 12:57:30 +02:00
froschandfrosch c1389c77b2 Codechange: ParseInteger optionally clamps out-of-range values, instead of treating them as invalid. 2025-05-20 12:57:30 +02:00
translators ecadf1b322 Update: Translations from eints
hungarian: 4 changes by meskobalazs
2025-05-20 04:46:13 +00:00
Peter NelsonandGitHub ce83f583bc Codechange: Use EnumBitSet for VehicleRailFlags. (#14280) 2025-05-19 18:56:45 +01:00
Peter NelsonandGitHub 77d6f6c69f Codechange: Make ContentType::State an enum class. (#14279) 2025-05-19 17:11:28 +01:00
SamuXarickandGitHub ad3a34e9ef Add: [Script] ScriptVehicleList_Waypoint (#13456)
Creates a list of vehicles that have orders to a given waypoint.
2025-05-19 14:48:17 +02:00
Loïc GuillouxandGitHub 1b0fd0e6fd Fix b2c57123: [Script] Conversion from ScriptEvent to ScriptEventCompanyTown subclasses (#14274) 2025-05-18 15:40:47 +02:00
translators 9bbc525e53 Update: Translations from eints
catalan: 17 changes by J0anJosep
2025-05-18 04:50:09 +00:00
Peter NelsonandGitHub 940a7127f8 Fix f8bdc1e612: Empty first parameter of EncodedString was skipped. (#14273)
This would place the remaining parameters one position too early.
2025-05-17 22:55:48 +00:00
translators 617169c1c9 Update: Translations from eints
norwegian (bokmal): 2 changes by eriksorngard
english (us): 9 changes by 2TallTyler
romanian: 3 changes by The-Bober
dutch: 2 changes by Afoklala
2025-05-17 04:44:32 +00:00
translators 521d0465d9 Update: Translations from eints
korean: 2 changes by telk5093
hungarian: 26 changes by meskobalazs
2025-05-16 04:47:27 +00:00
translators 6c84dd1f32 Update: Translations from eints
persian: 371 changes by realsepehrz
romanian: 49 changes by The-Bober
portuguese: 2 changes by azulcosta
2025-05-15 04:46:38 +00:00
Peter NelsonandPeter Nelson c8a336f760 Codechange: Move GetNthSetBit() to BaseBitSet.
This now returns the correct type, or std::nullopt instead of -1.
2025-05-14 07:22:12 +01:00
Peter NelsonandPeter Nelson c50ee282f9 Codechange: EnumBitSet bits can be iterated directly. 2025-05-14 07:22:12 +01:00
Peter NelsonandPeter Nelson 66c16a1d1f Codechange: Add Count() method to BaseBitSet. 2025-05-14 07:22:12 +01:00
translators ecc3438519 Update: Translations from eints
polish: 2 changes by pAter-exe
2025-05-14 04:46:05 +00:00
Loïc GuillouxandGitHub c16d5f3a8d Change: [Script] ScriptVehicleList_Station accepts an optional VehicleType parameter (#14260) 2025-05-13 16:41:23 +02:00
Peter NelsonandPeter Nelson 87fa1e41d5 Codechange: Use std::byte for sound buffers. 2025-05-13 14:51:17 +01:00
Peter NelsonandPeter Nelson 5585363407 Codechange: Use std::byte for glyph sprite buffer. 2025-05-13 14:51:17 +01:00
translators c718858999 Update: Translations from eints
english (au): 2 changes by krysclarke
chinese (traditional): 2 changes by KogentaSan
spanish (mexican): 2 changes by absay
chinese (simplified): 11 changes by WenSimEHRP
greek: 2 changes by gh658804
hungarian: 2 changes by vargaviktor
persian: 17 changes by realsepehrz
russian: 2 changes by lexuslatvia
finnish: 4 changes by hpiirai
latvian: 2 changes by lexuslatvia
portuguese (brazilian): 2 changes by pasantoro
2025-05-13 04:47:36 +00:00
Peter NelsonandGitHub 156f98ba06 Fix #14256, dfd9fbf873: Company finance windows not updated when paused. (#14258)
Refresh company finance windows via a WindowTimer instead of in game loop.

As the invalidation affects multiple windows this is a global timer instead of window-specific.
2025-05-13 01:23:27 +01:00
Peter NelsonandGitHub bc778545b3 Fix 0829604b4f: Dragging of selected order was still not possible. (#14259)
Check click_count condition earlier so that drag and drop is activated.
2025-05-13 01:22:58 +01:00
Peter NelsonandGitHub 431e57d087 Fix 0ce30d05c8: Replacing a dropdown list could reposition it partially off-screen. (#14261) 2025-05-13 01:22:45 +01:00
Peter NelsonandGitHub d37d4c18b5 Change: Remove Apply button from NewGRF config window when unneeded. (#14254)
When configuring NewGRFs outside of a game, the changes are always applied when the window is closed, even if the Apply button is not used.

The Apply button only needs appear during a game when changes are not automatically applied.
2025-05-13 01:22:23 +01:00
Jonathan G Rennisonandrubidium42 d107b7c8c0 Fix 3cf9b159: Incorrect tile colour in smallmap for snowy MP_CLEAR tiles in vegetation mode
See: #13659
2025-05-12 19:04:43 +02:00
Peter NelsonandGitHub d9247fa1a0 Change: Remove extra close buttons from some windows. (#14124)
All windows have an X button to close it, so remove the redundant close buttons.
2025-05-12 14:54:44 +01:00
froschandGitHub a62081d79e Fix #14251: Out-of-bounds writes via TextRefStack. (#14255) 2025-05-12 13:59:33 +02:00
Peter NelsonandGitHub 0aacd7acb3 Codechange: Use GrfSpecFeature type instead of uint8_t. (#14253) 2025-05-12 08:44:39 +01:00
translators 2516c435b7 Update: Translations from eints
swedish: 9 changes by joeax910
2025-05-12 04:47:40 +00:00
Rubidiumandrubidium42 568b70e556 Codechange: replace memmove with std::move(_backwards) 2025-05-11 21:51:57 +02:00
Rubidiumandrubidium42 3cd040ffe9 Codechange: unify moving of pixels in the blitters 2025-05-11 21:51:57 +02:00
Peter NelsonandGitHub b38527ca05 Change: Move OpenTTD version to intro viewport. (#14233)
This stops the length of the game version from affecting the main menu.
2025-05-11 20:01:22 +01:00
Rubidiumandrubidium42 03116ea878 Codechange: remove now unused cpp_sizeof 2025-05-11 13:48:23 +02:00
Rubidiumandrubidium42 02d8ae018c Codechange: simplify getting the value of a NewGRF property 2025-05-11 13:48:23 +02:00
Rubidiumandrubidium42 f2b48bad79 Codechange: remove last (hidden) users of memset 2025-05-11 06:07:01 +02:00
froschandGitHub c037722cb5 Fix 51a7edd: NewGRF debug sprite picker was broken. (#14246) 2025-05-10 20:27:43 +02:00
Rubidiumandrubidium42 a48a5f0cc6 Codechange: replace memcpy with std::copy_n 2025-05-10 16:50:58 +02:00
Loïc GuillouxandGitHub a45f23686d Fix #14241, 6e10584: Invalid string parameters in subsidies list window (#14243) 2025-05-09 18:08:17 +02:00
Rubidiumandrubidium42 f8aceb6c37 Codechange: use value initialisation over memset 2025-05-09 17:20:41 +02:00
Rubidiumandrubidium42 7981fcb297 Codechange: use std::fill_n over memset 2025-05-09 17:20:41 +02:00
Rubidiumandrubidium42 92bd78dd25 Codechange: use std::ranges::fill over memset 2025-05-09 17:20:41 +02:00
Rubidiumandrubidium42 96873dee63 Codechange: use std::array.fill over memset 2025-05-09 17:20:41 +02:00
froschandGitHub 228f9ca941 Fix #13854: 40bpp-anim blitter recolouring failed for 32bpp pixels without mask channel. (#14242) 2025-05-09 17:16:29 +02:00
froschandfrosch a277cb2b4c Change: [NewGRF] Increase the textstack for all callbacks to 16 registers. 2025-05-09 12:39:11 +02:00
froschandfrosch c6fa5022cb Add: [NewGRF] All callbacks returning D0xx strings, have now the option to return any string id via register 0x100. 2025-05-09 12:39:11 +02:00
froschandfrosch 84bc78fd8f Add: [NewGRF] Special value 0x7FFE for VarAction2 results specifying 'return calculated result'. 2025-05-09 12:38:58 +02:00
froschandfrosch 9d32087236 Add: [NewGRF] Special value 0x7FFF for Action2 references specifying explicit 'callback/sprite-resolving failed'. 2025-05-09 12:38:58 +02:00
translators b1cdf5024f Update: Translations from eints
spanish (mexican): 7 changes by absay
2025-05-09 04:46:47 +00:00
Peter NelsonandGitHub ae1f469aac Fix #14234, 16b4e73: Skip PLURAL data if parameter is invalid. (#14236) 2025-05-08 09:06:56 +01:00
glx22andLoïc Guilloux 1d18b4a80b Codechange: remove core/mem_func.hpp 2025-05-08 09:33:18 +02:00
glx22andLoïc Guilloux aba5e1258e Codechange: use assignment over MemCpyT 2025-05-08 09:33:18 +02:00
glx22andLoïc Guilloux 6356311fbc Codechange: use std::copy_n over MemCpyT 2025-05-08 09:33:18 +02:00
glx22andLoïc Guilloux a013f81120 Codechange: use std::array's fill over memset 2025-05-08 09:33:18 +02:00
glx22andLoïc Guilloux 82244779eb Codechange: use C++ initialisation over MemSetT 2025-05-08 09:33:18 +02:00
translators 6680169251 Update: Translations from eints 2025-05-08 04:46:44 +00:00
Peter NelsonandPeter Nelson 2feba80fd7 Codechange: Codestyle fixes for elrail code. 2025-05-07 20:34:33 +01:00
Peter NelsonandPeter Nelson 4a8dd494ee Codechange: Don't abbreviate TileLocationGroup type name. 2025-05-07 20:34:33 +01:00
froschandfrosch d00196cd65 Change: Rearrange buttons in the intro screen, remove unnecessary ones. 2025-05-07 18:41:48 +02:00
froschandfrosch 4111ce2698 Add: WWT_IMGTEXTBTN, WWT_PUSHIMGTEXTBTN 2025-05-07 18:41:48 +02:00
Peter NelsonandPeter Nelson a7019b859c Codechange: Use DiagDirections when checking for flat buildable tiles. 2025-05-07 17:31:29 +01:00
Peter NelsonandPeter Nelson aa9e5b38cd Codechange: Use DiagDirections when drawing level crossings. 2025-05-07 17:31:29 +01:00
Peter NelsonandPeter Nelson 1ac9f24f38 Codechange: Use (Diag)Directions when drawing catenary. 2025-05-07 17:31:29 +01:00
Peter NelsonandPeter Nelson 87544eff0c Codechange: Use DiagDirections to collect rail fence data. 2025-05-07 17:31:29 +01:00
Peter NelsonandPeter Nelson 1cbc4da054 Codechange: Use Directions for water flooding data. 2025-05-07 17:31:29 +01:00
Peter NelsonandPeter Nelson 968bb8961e Codechange: Add Directions and DiagDirections EnumBitSets. 2025-05-07 17:31:29 +01:00
Peter NelsonandPeter Nelson e0dbbbb032 Codechange: Add Reset() and missing &=/|= operators for BaseBitSet. 2025-05-07 17:31:29 +01:00
Peter NelsonandGitHub c4d033967b Codechange: Remove some unnecessary includes from network files. (#14226) 2025-05-07 16:46:14 +01:00
froschandfrosch 22fedca77e Codechange: Integrate ResolverObject::ResetState() into DoResolve(), no need to call it manually. 2025-05-06 22:24:41 +02:00
froschandfrosch f8c928ed98 Codechange: Make temporary storage a member of ResolverObject. 2025-05-06 22:24:41 +02:00
froschandfrosch eb9bbb2456 Codechange: Remove direct access to temporary storage from TextRefStack. 2025-05-06 22:24:41 +02:00
froschandfrosch 6faa667644 Codechange: Remove global GetRegister(), instead return 100+ registers directly from GetXxxCallback(). 2025-05-06 22:24:41 +02:00
froschandfrosch f59cf73b88 Codechange: Access temporary storage through ResolverObject during sprite layout preprocessing. 2025-05-06 22:24:41 +02:00
froschandfrosch 85be7a4d92 Codechange: Access temporary storage through ResolverObject during Resolve. 2025-05-06 22:24:41 +02:00
froschandfrosch 99d7a775ad Codechange: Make GetRegister return a signed integer, matching the underlying TemporaryStorageArray. 2025-05-06 22:24:41 +02:00
froschandfrosch 74030a63e6 Codechange: Move SpriteLayoutProcessor's operations closer to the ResolverObject. 2025-05-06 22:24:41 +02:00
Rubidiumandrubidium42 0ffdc86a2c Codechange: use std::ranges::equal over memcmp 2025-05-06 21:29:21 +02:00
Rubidiumandrubidium42 89deb3876f Codechange: use fstream to compare file equality 2025-05-06 21:29:21 +02:00
froschandGitHub cd7ac64f9d Codefix: Fix compilation with DEBUG_DUMP_COMMANDS. (#14228) 2025-05-06 21:11:30 +02:00
froschandfrosch 592cc49b62 Codechange: Turn _grow_town_result into a local variable in GrowTownAtRoad. 2025-05-06 20:58:17 +02:00
froschandfrosch 5af877d12d Codechange: Do not assign _grow_town_result in GrowTownInTile, instead return the new value. 2025-05-06 20:58:17 +02:00
froschandfrosch 22af391064 Codechange: Move _grow_town_result out of GrowTownWithExtraHouse, GrowTownWithRoad, GrowTownWithBridge and GrowTownWithTunnel. 2025-05-06 20:58:17 +02:00
Rubidiumandrubidium42 d70aeb72a7 Codechange: C++ initialise LanguageHeaderPack 2025-05-06 20:03:35 +02:00
Rubidiumandrubidium42 8f1e94c546 Codechange: use C++ initialisation over MemSetT 2025-05-06 20:03:35 +02:00
Rubidiumandrubidium42 cc51b29234 Codechange: use std::fill_n/copy_n over MemSetT/MemCpyT 2025-05-06 20:03:35 +02:00
Rubidiumandrubidium42 0d922c9d62 Codechange: use std::array's fill over memset 2025-05-06 20:03:35 +02:00
Rubidiumandrubidium42 4c1cd4fe4c Codefix: remove unused mem_func includes 2025-05-06 20:03:35 +02:00
Peter NelsonandPeter Nelson 9735fbbaa1 Codechange: Use LRUCache for layouted LineCache.
This avoids needing to manually manage the size of the cache.
2025-05-06 18:09:00 +01:00
Peter NelsonandPeter Nelson 8c4f8af66e Codechange: Move std::unique_ptr out of LRUCache implementation.
This is an implementation detail of how OpenGLSprites are stored.
2025-05-06 18:09:00 +01:00
froschandfrosch 8bbfbd0347 Codechange: Move spritelayout preprocessing to a separate class, which owns the heap allocations involved. 2025-05-06 18:30:42 +02:00
froschandfrosch d9c43e7fda Codechange: Make TileLayoutSpriteGroup::ProcessRegisters return a DrawTileSpriteSpan on the stack, instead of a reference to a global. 2025-05-06 18:30:42 +02:00
froschandfrosch 51a7edd941 Codechange: Remove _input_events_this_tick. 2025-05-06 18:29:41 +02:00
froschandfrosch 42f9312f71 Codechange: Make station variable cache a member of StationScopeResolver. 2025-05-06 18:29:41 +02:00
froschandfrosch b20b6da937 Codechange: The compiler ensures static variables are initialised only once, no need to track that manually. 2025-05-06 18:29:41 +02:00
froschandfrosch 75a775e59d Codechange: Make GetCurrentLocale return a std::string instead of a reference to a static buffer.
For win32 this is even a fix, because the static buffer was only updated once. Later calls discarded the determined locale.
2025-05-06 18:29:41 +02:00
froschandfrosch 0d5b3ebd7f Codechange: Declare all IntervalTimers const, which can be const. 2025-05-06 18:29:41 +02:00
froschandfrosch 61cec33be2 Codechange: Add 'const' to static variables, which are only initialised once. 2025-05-06 18:29:41 +02:00
froschandfrosch 1900125c98 Codechange: Use string_view for FileExists. 2025-05-06 18:29:41 +02:00
Peter NelsonandGitHub d571491405 Codechange: Replace std::bitset<CONTENT_TYPE_END> with ContentTypes. (#14223)
#14214 added `ContentTypes` as en `EnumBitSet`, but some std::bitset existed already; they are now `ContentTypes` too.
2025-05-06 17:20:01 +01:00
translators eca826b0a4 Update: Translations from eints
korean: 7 changes by telk5093
hungarian: 3 changes by vargaviktor
latvian: 3 changes by lexuslatvia
polish: 6 changes by pAter-exe
2025-05-06 04:46:37 +00:00
froschandGitHub 13349254ea Fix #14216, d030d17: RealSpriteGroups referencing CallbackResultSpriteGroups were always treated as callback-failure. (#14218) 2025-05-05 16:13:41 +02:00
Peter NelsonandPeter Nelson e23de03a99 Codechange: Use FlatSet for sprite picker list. 2025-05-05 14:00:38 +01:00
Peter NelsonandPeter Nelson b06273f716 Codechange: Use FlatSet when searching tiles around stations. 2025-05-05 14:00:38 +01:00
Peter NelsonandPeter Nelson 7679b0bc46 Codechange: Use FlatSet when filtering and drawing badge names. 2025-05-05 14:00:38 +01:00
Peter NelsonandPeter Nelson 5fd7344a6d Codechange: Use FlatSet when creating rivers. 2025-05-05 14:00:38 +01:00
Peter NelsonandPeter Nelson 7c834921b2 Codechange: Use FlatSet for per-industry type industry lists. 2025-05-05 14:00:38 +01:00
Peter NelsonandPeter Nelson 6070f8d4f3 Codechange: Add FlatSet implementation.
This is a flat set implemented using a sorted vector for storage.
2025-05-05 14:00:38 +01:00
Peter NelsonandGitHub 2355d67e11 Codechange: Use EnumBitSet instead of Vector to record received content types. (#14214) 2025-05-05 08:55:34 +01:00
translators a46b885640 Update: Translations from eints
english (au): 1 change by krysclarke
russian: 2 changes by Ln-Wolf
2025-05-05 04:47:18 +00:00
Peter NelsonandGitHub d7563096c6 Doc: Tweak documentation for consistency. (#14211)
* Remove/add line breaks so spacing is the same.
* Fix ToC links.
2025-05-04 20:16:29 +01:00
Peter NelsonandPeter Nelson ac76212b80 Fix: Closing the Game Options window closes all textfile windows.
Record the parent window that opens a textfile window so only child windows are closed instead of all.
2025-05-04 19:36:46 +01:00
Peter NelsonandPeter Nelson dabf2ede67 Change: Add methods to close child windows with a specific window number. 2025-05-04 19:36:46 +01:00
Rubidiumandrubidium42 0724b3cda8 Codechange: replace SQChar with char 2025-05-04 16:59:06 +02:00
Rubidiumandrubidium42 1f411f8a16 Codechange: use string_view for squirrel parameter checks 2025-05-04 16:59:06 +02:00
Rubidiumandrubidium42 588b0de3de Codechange: hide SQString internals behind std::string_view/std::span 2025-05-04 16:59:06 +02:00
Rubidiumandrubidium42 635ca3739f Codechange: use std::string_view in squirrel lexer 2025-05-04 16:59:06 +02:00
Rubidiumandrubidium42 4255a94779 Codechange: use std::span over char* for writing the buffers 2025-05-04 15:32:52 +02:00
Rubidiumandrubidium42 6817f52d9b Codechange: move definition of getcwd for Windows to where it is used 2025-05-04 15:32:52 +02:00
Rubidiumandrubidium42 6189bbc45a Codechange: return std::string_view for convert_from_fs 2025-05-04 15:32:52 +02:00
Rubidiumandrubidium42 6caa08098c Codechange: remove char* StringConsumer 2025-05-04 15:32:52 +02:00
Peter NelsonandGitHub 3e608b5fe4 Fix: Zoom-scroll extra viewports only if the mouse cursor is over the viewport. (#14209) 2025-05-04 14:16:05 +01:00
Rubidiumandrubidium42 afc1e76575 Codefix: StartNewThread uses char* after returning 2025-05-04 14:05:15 +02:00
Rubidiumandrubidium42 8f74c08ea6 Codechange: put SQRegFunctions into initializer_list and use ranged for loops 2025-05-04 14:05:05 +02:00
Rubidiumandrubidium42 f4fc8f6b38 Codechange: replace Error with simple throw 2025-05-04 14:05:05 +02:00
Rubidiumandrubidium42 9d8a612bfb Codechange: remove unused function 2025-05-04 10:43:56 +02:00
Rubidiumandrubidium42 5e3c7c4146 Codechange: char* -> char * 2025-05-04 10:43:56 +02:00
Rubidiumandrubidium42 3f2b39e3f8 Codechange: replace char* where out-of-date 2025-05-04 10:43:56 +02:00
Rubidiumandrubidium42 d697280493 Codechange: remove now obsolete char* tests
The function is std::string_view and there are std::string_view tests as well.
2025-05-04 10:43:56 +02:00
Rubidiumandrubidium42 d01bebbd18 Codefix 26a4da9b01: MinGW compilation failure 2025-05-04 09:07:02 +02:00
translators 7d7a6bd32c Update: Translations from eints
norwegian (bokmal): 3 changes by eriksorngard
2025-05-04 04:46:05 +00:00
froschandfrosch 8571af9833 Codechange: Turn ZoomLevel into enum class. 2025-05-03 23:21:09 +02:00
froschandfrosch c0d4ab69d0 Codechange: Add a container to index data by zoom level. 2025-05-03 23:21:09 +02:00
froschandfrosch 7055ea0aee Codechange: Define sequential operators for ZoomLevel. 2025-05-03 23:21:09 +02:00
froschandfrosch bbfda39ac3 Codechange: Add ZoomLevels bit set. 2025-05-03 23:21:09 +02:00
froschandfrosch 48d09af039 Codechange: Simplify weird range check. 2025-05-03 23:21:09 +02:00
Rubidiumandrubidium42 d464961c41 Codechange: use std::string_view for SQ stack and function info 2025-05-03 23:02:09 +02:00
Rubidiumandrubidium42 0bc773215e Codechange: use std::optional<std::string_view> to make the intent of function clearer 2025-05-03 23:02:09 +02:00
Rubidiumandrubidium42 ead3b96883 Codechange: use std::string_view to create SQString 2025-05-03 23:02:09 +02:00
Rubidiumandrubidium42 fca99967a7 Codechange: make sq_scratchpad use std::span<char> 2025-05-03 23:02:09 +02:00
Rubidiumandrubidium42 b4d9682f21 Codechange: use std::string_view for sq_throwerror 2025-05-03 23:02:09 +02:00
Rubidiumandrubidium42 ec79ceb2be Codechange: use std::string_view for sq_pushstring 2025-05-03 23:02:09 +02:00
Rubidiumandrubidium42 3020e615a9 Codechange: use std::string_view for squirrel compilation 2025-05-03 23:02:09 +02:00
Rubidiumandrubidium42 26a4da9b01 Codechange: replace last strncmp uses 2025-05-03 21:51:01 +02:00
Peter NelsonandGitHub 31754a0afd Fix: Changing monospace font didn't refresh the monospace width cache. (#14185) 2025-05-03 18:34:45 +01:00
Peter NelsonandGitHub 7596f98e2d Codechange: Cache layouted text for the last used width. (#14177) 2025-05-03 18:33:47 +01:00
Peter NelsonandGitHub bd1a3fe0b7 Change: Remove the limit of 20 parameters to a Script Text string. (#14193) 2025-05-03 18:33:29 +01:00
froschandfrosch 518a34c286 Codechange: Use std::byte for generic buffers. 2025-05-03 18:43:20 +02:00
froschandfrosch 02082a0211 Codechange: Deduplicate array lookup. 2025-05-03 18:43:20 +02:00
froschandfrosch bb767608de Codechange: Pass SpriteType as direct parameter to SpriteEncoder::Encoder. 2025-05-03 18:43:20 +02:00
froschandGitHub c3aa3f140c Codechange: Use more std::string_view. (#14197) 2025-05-03 18:40:37 +02:00
froschandGitHub 74a275f37b Add: [NewGRF] Add purchase list Action3 CID for houses, industries, industry tiles, airports and airport tiles. (#14121) 2025-05-03 17:50:20 +02:00
froschandGitHub 9ac9798d7f Codechange: Remove usages of stoi and stol. (#14196) 2025-05-03 17:46:30 +02:00
Rubidiumandrubidium42 b6afd8d2b6 Codechange: remove some completely unused squirrel files 2025-05-03 17:14:10 +02:00
Rubidiumandrubidium42 85f1110569 Codechange: rewrite ini file parsing with the StringConsumer 2025-05-03 17:13:33 +02:00
Rubidiumandrubidium42 6a9f694158 Codechange: remove StrEmpty 2025-05-03 15:58:14 +02:00
Rubidiumandrubidium42 d037dbb42a Codechange: use std::string_view for locales 2025-05-03 15:58:14 +02:00
Rubidiumandrubidium42 96fd291693 Codechange: introduce GetEnv that returns optional based on std::getenv 2025-05-03 15:58:14 +02:00
Rubidiumandrubidium42 04a6a55e94 Codechange: replace StripTrailingWhitespace with StrTrimView 2025-05-03 15:57:53 +02:00
Rubidiumandrubidium42 1f39d469ff Codechange: pass the characters to trim to StrTrimView 2025-05-03 15:57:53 +02:00
Rubidiumandrubidium42 e2db8277b8 Codefix: implement StrTrimInPlace without assigning a borrowed view of itself 2025-05-03 15:57:53 +02:00
Rubidiumandrubidium42 4109b6848b Codechange: replace manual trim and std::from_chars with ParseInteger 2025-05-03 15:57:53 +02:00
Rubidiumandrubidium42 414f6a3067 Codechange: add support for parsing octal numbers 2025-05-03 15:57:53 +02:00
Rubidiumandrubidium42 c79abc6da6 Codechange: reduce dependence on C-style strings in OpenGL 2025-05-03 14:24:49 +02:00
Rubidiumandrubidium42 278aee2c19 Codechange: use std::string_view for sq_getstring 2025-05-03 14:24:28 +02:00
translators f4f05dea33 Update: Translations from eints
chinese (traditional): 1 change by KogentaSan
chinese (simplified): 1 change by WenSimEHRP
greek: 1 change by gh658804
russian: 1 change by Ln-Wolf
finnish: 1 change by hpiirai
dutch: 8 changes by Afoklala
portuguese: 3 changes by jcteotonio
portuguese (brazilian): 1 change by pasantoro
polish: 1 change by pAter-exe
2025-05-03 04:45:31 +00:00
Peter NelsonandGitHub 8b14faaa40 Codechange: Add version of DrawStringMultiLine that performs clipping test. (#14189)
Normally DrawStringMultiLine does not perform any clipping, as the return value may be needed if it the text is not drawn.

In some specific cases the height is already known, so it is possible to test for clipping, which can cut down on layouting time for text which won't be visible.
2025-05-02 22:59:55 +01:00
Iris-PersephoneandGitHub 2f020abe74 Add: "Many random towns" button in scenario editor now prompts for the number of towns, with defaults based on new game settings (#14158) 2025-05-02 22:54:21 +01:00
Peter NelsonandGitHub 3eba97f67c Codechange: Scrollbar Count no longer needs to be clamped to uint16_t. (#14184) 2025-05-02 22:21:05 +01:00
Peter NelsonandGitHub f7db4938ce Fix #14098: Use 64-bit type for MIDI realtime information. (#14144) 2025-05-02 22:20:44 +01:00
Rubidiumandrubidium42 c420ba349d Codechange: use std::string_view over char* 2025-05-02 23:12:43 +02:00
Rubidiumandrubidium42 f2a32c6d13 Codechange: use std::byte instead of char for calculating arbitrary byte offsets 2025-05-02 23:12:43 +02:00
Peter NelsonandGitHub 932dca927b Fix: Crash/Undefined behaviour in station view window. (#14183)
No column limit was applied when drawing waiting cargo, which could cause out-of-bounds array access.
2025-05-02 08:02:35 +01:00
translators e0a9c7d818 Update: Translations from eints
english (au): 2 changes by krysclarke
chinese (traditional): 3 changes by KogentaSan
chinese (simplified): 6 changes by WenSimEHRP
greek: 2 changes by gh658804
russian: 2 changes by Ln-Wolf
finnish: 3 changes by hpiirai
portuguese (brazilian): 2 changes by pasantoro
polish: 2 changes by pAter-exe
2025-05-02 04:45:34 +00:00
Peter NelsonandGitHub ae9646eb0a Change: Use same padding as NewGRF parameters for AI/GS parameters lists. (#14118) 2025-05-01 22:36:53 +01:00
Rubidiumandrubidium42 5ca686261e Codechange: use std::string_view for the string setting defaults 2025-05-01 23:24:43 +02:00
Rubidiumandrubidium42 5c7b04a0c2 Codechange: use std::string_view for 'x-of-many' settings 2025-05-01 23:24:43 +02:00
Rubidiumandrubidium42 7805c1c189 Codechange: use std::string_view for ini_key 2025-05-01 23:24:43 +02:00
Peter NelsonandGitHub d958d50985 Fix: Small order list arrow was wrong direction for RTL text. (#14174)
Add sprite for small left arrow and use for small order list when using an RTL language.
2025-05-01 22:08:24 +01:00
Loïc GuillouxandGitHub 41b113840a Fix: [Script] Access to enum/consts defined outside of main.nut (#14176) 2025-05-01 18:16:32 +02:00
Loïc GuillouxandGitHub 1f212e6f2a Fix: Handle \t when loading GS strings from savegame (#14180) 2025-05-01 16:48:02 +02:00
Loïc GuillouxandGitHub 6f4994329c Fix bf8a241f: Handle \t in trailing whitespaces (#14178) 2025-05-01 12:32:00 +02:00
translators a30f251d05 Update: Translations from eints
hungarian: 99 changes by meskobalazs
russian: 8 changes by Ln-Wolf
finnish: 24 changes by hpiirai
latvian: 70 changes by lexuslatvia
2025-05-01 04:47:22 +00:00
Rubidiumandrubidium42 fbe80f31fe Codechange: replace char* in GetOptData with std::string_view 2025-04-30 23:49:06 +02:00
Rubidiumandrubidium42 c1a287ad17 Codechange: make some saveload functions work natively with std::string_view 2025-04-30 23:49:06 +02:00
Rubidiumandrubidium42 855377191e Codechange: replace some more char*s with std::string_view 2025-04-30 23:49:06 +02:00
froschandGitHub a80c11a6e8 Fix 66733e2a: Textbuf was broken, and did not insert any input. (#14173) 2025-04-30 19:31:52 +00:00
Peter NelsonandGitHub 7dd3bed10f Fix #14170, 7fd0e6c27d: Missing spaces for timetabled order strings. (#14172) 2025-04-30 19:54:54 +01:00
froschandfrosch 316279f4b4 Codechange: Use more std::string_view. 2025-04-30 19:33:56 +02:00
froschandfrosch 9cf36dac39 Codechange: Use data() instead of c_str(), if no NUL termination is needed. 2025-04-30 19:33:56 +02:00
froschandfrosch 9e90d4ed79 Codefix: Do not assign nullptr to std::string_view. 2025-04-30 19:33:56 +02:00
froschandfrosch 36ce1f890a Codechange: Remove c_str, if std::string_view is already accepted. 2025-04-30 19:33:56 +02:00
froschandfrosch b564fbb5e6 Codechange: Use StringConsumer to parse hotkeys. 2025-04-30 19:33:56 +02:00
froschandfrosch 66733e2a50 Codechange: Use std::string_view in IME input handling. 2025-04-30 19:33:56 +02:00
froschandfrosch 6db13df3b5 Add: [BaseSet] Allow basesets to set minor and patch versions in obg/obs/obm files. 2025-04-30 15:23:27 +02:00
froschandfrosch d30fee4a99 Codechange: Improve debug/error messages when reading baseset metadata. 2025-04-30 15:23:27 +02:00
Rubidiumandrubidium42 708e6a512d Codechange: replace char* with C++ style strings 2025-04-30 12:05:04 +02:00
Peter NelsonandGitHub 356b0159c7 Fix 261e09a549: Compilation failure with Fluidsynth enabled. (#14167) 2025-04-30 07:27:57 +01:00
translators 7bec2029fa Update: Translations from eints
english (au): 4 changes by krysclarke
norwegian (bokmal): 5 changes by eriksorngard
chinese (traditional): 4 changes by KogentaSan
greek: 8 changes by gh658804
russian: 4 changes by Ln-Wolf
finnish: 4 changes by hpiirai
portuguese: 4 changes by jcteotonio
portuguese (brazilian): 4 changes by pasantoro
polish: 4 changes by pAter-exe
2025-04-30 04:46:51 +00:00
Peter NelsonandGitHub 0abebfce1c Codechange: Use result of .find() instead of looking up multiple times. (#14154) 2025-04-29 23:52:46 +01:00
Peter NelsonandGitHub aa9e8b422c Fix #14166, dfd9fbf873: Loan was no longer invalidated when refreshing finance window. (#14168)
In most cases the company loan does not change, but it should be updated in case it does.
2025-04-29 23:52:11 +01:00
Rubidiumandrubidium42 f4ad614285 Codechange: use std::string_view for FS2OTTD and OTTD2FS 2025-04-29 22:33:32 +02:00
Rubidiumandrubidium42 ef71ce0a9d Codechange: return std::string_view for Textbuf::GetText() 2025-04-29 22:15:49 +02:00
Rubidiumandrubidium42 261e09a549 Codechange: remove char* from base driver code 2025-04-29 21:09:18 +02:00
froschandfrosch d030d17bd6 Codechange: Do not use a mutable global to return calculated VarAction2 results. 2025-04-29 20:35:46 +02:00
froschandfrosch e90b68d504 Codechange: Pass SpriteGroup as reference to ResolveReal. 2025-04-29 20:35:46 +02:00
froschandfrosch 7c946d97da Codefix: Build with OPTION_DEDICATED=OFF and CMAKE_DISABLE_PRECOMPILE_HEADERS=ON. 2025-04-29 20:26:23 +02:00
froschandfrosch afe3dfb3a4 Codechange: Use format instead of to_string. 2025-04-29 20:26:23 +02:00
froschandfrosch fda93b6f35 Codechange: Add format_append as short-hand to format_to + back_inserter. 2025-04-29 20:26:23 +02:00
froschandfrosch 98481ecc01 Codechange: Replace strtol, strtoll, stroul and strtoull with ParseInteger. 2025-04-29 20:14:56 +02:00
froschandfrosch cdafc50c94 Codechange: Replace atoi and atoll with ParseInteger. 2025-04-29 20:14:56 +02:00
froschandfrosch 3973199879 Change: ParseInteger now checks for trailing junk chars. 2025-04-29 20:14:56 +02:00
froschandfrosch 79b2202f2e Codechange: Use StringConsumer for parsing more strings. 2025-04-29 20:14:56 +02:00
froschandfrosch e7d758c82a Codechange: Replace sscanf with StringConsumer. 2025-04-29 20:14:56 +02:00
froschandfrosch 8027e31f47 Codechange: Remove virtual functions SpriteGroup::GetResult and GetNumResults. They are only implemented in and called via ResultSpriteGroup. 2025-04-29 10:35:10 +02:00
froschandfrosch 010b944173 Codechange: Move SpriteGroup cast from callers into Resolve. 2025-04-29 10:35:10 +02:00
Rubidiumandrubidium42 af25eecc15 Codechange: use const for std::string_view where appropriate 2025-04-29 10:15:18 +02:00
Rubidiumandrubidium42 78250c3bba Codechange: remove const char* overloads when there are std::string_view and std::string& overloads 2025-04-29 10:14:53 +02:00
Peter NelsonandPeter Nelson a5578166bb Codechange: Pass Script Info by reference. 2025-04-28 23:08:20 +01:00
Peter NelsonandPeter Nelson 341cdbc16b Codechange: Pass Script engine by reference. 2025-04-28 23:08:20 +01:00
Peter NelsonandPeter Nelson 72ca962b84 Codechange: Pass ScriptInstance by reference. 2025-04-28 23:08:20 +01:00
Peter NelsonandGitHub 13fcc0900e Change: Use enum/bitset to track which script configuration items are defined. (#14150)
Removes magic numbers, and simplifies compatibility. It is no longer necessary to provide values which won't be used.
2025-04-28 23:07:57 +01:00
Rubidiumandrubidium42 b20b56d5fc Codechange: store revision information in C++ style strings 2025-04-28 23:48:32 +02:00
Rubidiumandrubidium42 8b1c1cc33d Codechange: provide 'sv' (string_view) literals globally 2025-04-28 23:39:33 +02:00
Rubidiumandrubidium42 be53bd320d Codechange: replace char* from settingsgen 2025-04-28 23:27:46 +02:00
froschandfrosch 47b5ca6115 Fix: [NewGRF] Computed VarAction2 callback results were not always properly masked to 15 bit results. 2025-04-28 23:25:31 +02:00
froschandfrosch d90f6f01cc Codechange: CALLBACK_FAILED is an internal constant, do not use it as numeric value in VA2 computations. 2025-04-28 23:25:31 +02:00
froschandGitHub 30b1eb6e5f Fix: [NewGRF] The result of Action123 evaluation affected rerandomisation in a weird corner case. (#14139)
Rerandomisation does not care about the Resolve result.
But we skipped it, in case of 'invalid SpriteGroup reference'.
2025-04-28 23:24:42 +02:00
froschandfrosch b281c5616e Change: [NewGRF] If Action123 does not resolve in a valid SpriteSet, prefer drawing the default sprite instead of an invalid sprite. 2025-04-28 22:20:54 +02:00
froschandfrosch 7b08170ac8 Codechange: Replace a magic value with a maybe less magical constant. 2025-04-28 22:20:54 +02:00
Rubidiumandrubidium42 360670626b Codechange: replace char* with std::string_view 2025-04-28 21:31:12 +02:00
Rubidiumandrubidium42 9107c3f6c6 Codechange: add std::string_view variant of FileHandle::Open 2025-04-28 21:31:12 +02:00
Peter NelsonandGitHub 2c4897c2cd Codechange: Use EnumBitSet for HouseZones. (#14137) 2025-04-28 20:27:43 +01:00
froschandfrosch f5a9eae8b1 Fix: [NewGRF] AI station construction callback did not work for stations with ID >= 0x100. 2025-04-28 20:50:13 +02:00
froschandfrosch e2084bbdcd Codechange: Replace out parameters with result tuples. 2025-04-28 20:50:13 +02:00
froschandfrosch 0c6426cb2d Fix: Out-of-bounds read, if NewGRF stations provided no spritesets. 2025-04-28 20:49:20 +02:00
froschandfrosch 0f1ef96ca1 Codechange: Road stops do not use RealSpriteGroup, ResolveReal is never called. 2025-04-28 20:49:20 +02:00
Rubidiumandrubidium42 9116f96e2e Codechange: replace char * with std::string_view 2025-04-28 17:53:18 +02:00
Rubidiumandrubidium42 c6ea0ce961 Codechange: use std::span for transferring data in network code 2025-04-28 17:53:18 +02:00
froschandfrosch b7e7f08f78 Codechange: Simplify usage of GRFFileProps by adding some common helper methods. 2025-04-28 13:44:46 +02:00
froschandfrosch 46494c6d44 Codechange: Rename GRFFileProps to SubstituteGRFFileProps. 2025-04-28 13:44:46 +02:00
Richard WheelerandGitHub 298e02d593 Fix: List Ctrl+Click behaviour for vehicle details tooltip (#14127)
Also change mention of "road vehicle" to "vehicle", in line with vehicle order, refit, reverse, etc. tooltips. Fixes #14128
2025-04-28 07:00:18 +01:00
translators 68ba2735ea Update: Translations from eints
swedish: 109 changes by Brickblock1
spanish (mexican): 1 change by absay
english (us): 1 change by 2TallTyler
2025-04-28 04:46:30 +00:00
Rubidiumandrubidium42 794ba1f5da Fix 29ceaf0a8: checking std::optional against nullptr caused crash 2025-04-27 21:10:12 +02:00
Rubidiumandrubidium42 49ef3eee13 Codechange: replace char* with std::string_view 2025-04-27 20:08:02 +02:00
froschandfrosch e1859df1c0 Codechange: Use enums as keys for the spritegroups in FixedGRFFileProps. 2025-04-27 19:50:51 +02:00
froschandfrosch 05504ec463 Codechange: Use SingleGRFFileProps, if the feature has no spritegroup keys. 2025-04-27 19:50:51 +02:00
froschandfrosch 41a20e512d Codechange: Use proper enum type to index sprite groups in VariableGRFFileProps. 2025-04-27 19:50:51 +02:00
froschandfrosch 893aa0fb91 Codechange: Add an explicit enum member for the default spritegroup of badges. 2025-04-27 19:50:51 +02:00
Rubidiumandrubidium42 29ceaf0a84 Codechange: use std::string_view over const char * 2025-04-27 18:04:04 +02:00
Rubidiumandrubidium42 c7056866a3 Codechange: remove manual param count; in all cases strlen(params) == nparams 2025-04-27 17:57:53 +02:00
Rubidiumandrubidium42 781187b8a6 Codechange: replace C-style strings with std::string_view related to strings functions 2025-04-27 17:57:42 +02:00
Rubidiumandrubidium42 4e3e3d5be6 Codechange: introduce transparent hash lookup for strings 2025-04-27 17:57:42 +02:00
Peter NelsonandGitHub 7bbf380931 Fix #14125, 828e808444: NewGRF sounds were not loaded. (#14130)
NewGRF Action 11 should be handled in both INIT and ACTIVATION stages for sounds to be loaded.

Additionally the Action 0 feature test failed due to offsets involved.
2025-04-27 15:20:38 +00:00
Rubidiumandrubidium42 b9667ec3d1 Codechange: use std::string_view for scripts 2025-04-27 17:00:25 +02:00
translators 864fe29028 Update: Translations from eints
english (au): 1 change by krysclarke
chinese (traditional): 1 change by KogentaSan
galician: 66 changes by pvillaverde
chinese (simplified): 1 change by WenSimEHRP
korean: 72 changes by telk5093
greek: 1 change by gh658804
russian: 1 change by Ln-Wolf
finnish: 1 change by hpiirai
portuguese: 1 change by jcteotonio
portuguese (brazilian): 1 change by pasantoro
polish: 1 change by pAter-exe
2025-04-27 04:44:13 +00:00
Peter NelsonandGitHub 5a7893b730 Fix #14104, 67a0fcc: Don't base timetable timing decisions on client settings. (#14105)
Client settings different between clients so the resultant timings may be different.

Partially reverts 67a0fcc.
2025-04-26 22:39:01 +01:00
Peter NelsonandGitHub b87ce9c845 Change: Draw info headers as shade of window colour instead of pixel colour. (#14123)
Use the normal or lightest colour gradient to pick a suitable colour, instead of an arbitrary pixel colour.

(Except for the NewGRF window's info panel, this happens to be the same colour.)
2025-04-26 22:38:24 +01:00
froschandGitHub 55fad9c78a Add: Limit height of settings description, and add scrollbar. (#14102) 2025-04-26 22:34:18 +02:00
froschandGitHub d85f6dccc5 Fix 5575379: Crash with default airports. (#14120) 2025-04-26 22:29:01 +02:00
froschandGitHub f62f728187 Codechange: Move usage of ResolverObjects to newgrf_xxx.cpp (#14116) 2025-04-26 20:53:50 +02:00
froschandfrosch be39a05327 Fix: Road vehicle blocking and train collissions used slightly inconsistent distance thresholds. 2025-04-26 19:32:59 +02:00
froschandfrosch 3a70d1e2f7 Codechange: Pass the max-distance as parameter to VehiclesNearTileXY. 2025-04-26 19:32:59 +02:00
froschandfrosch 2df1233f1f Codechange: Clamp the search area to valid values for the hash bucket selection.
The bucket selection uses a truncating division instead of a flooring division, so it does not work for negative positions.
Anyhow, there are no negative tile coordinates, so just clamp the search area.
2025-04-26 19:32:59 +02:00
froschandfrosch 0f76ba122c Codefix: VehiclesNearTileXY yielded all vehicles with matching hashes, even if they are far away. 2025-04-26 19:32:59 +02:00
froschandfrosch c14e4a6db1 Codefix: Rect::Contains did not consider the bottom/right edges as inside. 2025-04-26 19:32:59 +02:00
Rubidiumandrubidium42 3235ec4cf8 Codefix: checking unsigned int >= 0 is pointless, check before subtraction 2025-04-26 18:31:36 +02:00
froschandfrosch ce2155ab27 Codechange: Remove unused FindVehicleOnPosXY/HasVehicleOnPosXY. 2025-04-26 16:54:56 +02:00
froschandfrosch 98ac75e74f Codechange: Replace FindVehicleOnPosXY/HasVehicleOnPosXY with VehiclesNearTileXY/HasVehicleNearTileXY. 2025-04-26 16:54:56 +02:00
froschandfrosch 9f1c04c0e1 Codechange: Add VehiclesNearTileXY and HasVehicleNearTileXY to iterate over/check for ground vehicles near a tile coordinate. 2025-04-26 16:54:56 +02:00
froschandfrosch ac3ed9f3ad Codechange: Deduplicate and simplify tile hash arithmetic. 2025-04-26 16:54:56 +02:00
Rubidiumandrubidium42 b4d4d730a5 Codechange: use std::string_view for town name generation 2025-04-26 16:30:30 +02:00
Rubidiumandrubidium42 30f381acee Codechange: use std::string_view for NetworkAddress 2025-04-26 16:30:16 +02:00
Rubidiumandrubidium42 e1db09a41f Codechange: use std::string_view for NewsTypeData 2025-04-26 16:30:16 +02:00
Rubidiumandrubidium42 42f0aa24f6 Codechange: use std::string_view for connection/URI strings 2025-04-26 16:30:16 +02:00
Rubidiumandrubidium42 a5812a45f8 Codechange: use std::string view for URI and std::move for data 2025-04-26 16:30:16 +02:00
Rubidiumandrubidium42 d1a7d30572 Codechange: use std::string_view for some settings functions 2025-04-26 16:30:16 +02:00
Rubidiumandrubidium42 4476ce804d Codechange: use std::string_view for GetNextParameterString 2025-04-26 16:30:16 +02:00
froschandGitHub 398524e49a Add: [NewGRF] Provide random bits in var10 of house callback 1C 'construction stage changed'. (#14095) 2025-04-26 15:58:44 +02:00
froschandGitHub 55753795bf Fix: [NewGRF] Cargo-types for airport-tile animation-triggers were not properly translated. (#14092) 2025-04-26 15:58:30 +02:00
froschandGitHub 1ea1dbd19e Add: [NewGRF] Station/roadstop animation-triggers 'tile loop' (bit 7) and 'path reservation' (bit 8). (#14080) 2025-04-26 14:44:55 +02:00
froschandGitHub d3ae6bc9a8 Fix: [NewGRF] For animation-triggers which do not supply a cargo-type in var18, the var18 bits should remain empty. (#14091) 2025-04-26 14:44:07 +02:00
froschandGitHub 0d9074769d Change: [NewGRF] Animation-trigger 'construction stage changed' of houses and industries now also triggers at construction start. (#14089) 2025-04-26 14:42:49 +02:00
Rubidiumandrubidium42 365eed533d Codechange: use std::string_view for console commands 2025-04-26 14:15:10 +02:00
Rubidiumandrubidium42 f04cf54939 Codechange: make IConsoleCmdExec use C++ strings internally 2025-04-26 14:15:10 +02:00
Loïc GuillouxandGitHub 28d0e6dfc0 Change: [Script] Reject scripts using negative version (#14096) 2025-04-26 14:02:36 +02:00
Peter NelsonandGitHub 4a5db57f7b Fix #14107: Mark the company value in the company view window dirty when it changes. (#14112) 2025-04-26 11:56:11 +00:00
Peter NelsonandGitHub dfd9fbf873 Codechange: Defer refreshing company finance windows. (#14111)
During each game tick every cargo payment will issue an Invalidate of the status bar and company finance window. While this doesn't paint the window yet, it does need to search for open windows, and then mark a area of dirty blocks, which is done for every Invalidate.

Instead, set a bit in a CompanyMask, and test these bits once after the game tick is complete.

This reduces the amount of dirtying, and allows more specific widgets to be dirtied instead of the whole window.
2025-04-26 10:50:51 +00:00
Peter NelsonandGitHub a1f086e60c Fix #14107: Invalidate all shared vehicle windows when changing group. (#14110)
Previously only windows of the first vehicle were invalidated.
2025-04-26 10:49:41 +00:00
translators bb1d561369 Update: Translations from eints
chinese (traditional): 9 changes by KogentaSan
english (us): 66 changes by 2TallTyler
greek: 65 changes by gh658804
russian: 77 changes by Ln-Wolf
dutch: 66 changes by Afoklala
portuguese: 65 changes by jcteotonio
polish: 68 changes by pAter-exe
2025-04-26 04:44:12 +00:00
Rubidiumandrubidium42 08ce16018b Codechange: make start-ai console command parsing work with std::string_view 2025-04-25 19:04:22 +02:00
Rubidiumandrubidium42 ccbf7f4a46 Codechange: validate the given seed 2025-04-25 19:04:22 +02:00
Rubidiumandrubidium42 86039a5b69 Codechange: make SetDebugString use C++-style strings and function types 2025-04-25 19:04:22 +02:00
Rubidiumandrubidium42 498a0f1c1b Codechange: use C++ strings over C-strings 2025-04-25 19:04:22 +02:00
froschandGitHub 4a09860c53 Fix: Focus settings filter box (only) when the tab becomes active. (#14100) 2025-04-25 12:04:26 +02:00
froschandGitHub f554d799d7 Change: [NewGRF] Provide shared random bits in multi-tile animation-triggers of airport tiles and objects, just like for other features. (#14090) 2025-04-25 10:01:01 +02:00
Peter NelsonandGitHub 8b927220c7 Change: Move Game Options toggles to before label, add Off/On text. (#14097) 2025-04-25 07:49:33 +01:00
translators e61762a805 Update: Translations from eints
english (au): 65 changes by krysclarke
norwegian (bokmal): 67 changes by eriksorngard
chinese (traditional): 67 changes by KogentaSan
spanish (mexican): 66 changes by absay
chinese (simplified): 91 changes by WenSimEHRP
finnish: 65 changes by hpiirai
french: 61 changes by ottdfevr
portuguese (brazilian): 65 changes by pasantoro
2025-04-25 04:46:37 +00:00
Peter NelsonandGitHub 87b5b0ffa3 Fix 2b80812922: Map size column in server list may be too wide. (#14094)
Incorrect change from SetDParamMaxValue to GetParamMaxValue.
2025-04-24 21:05:31 +01:00
Rubidiumandrubidium42 2087bca87d Codechange: replace atoi with ParseInteger in console commands 2025-04-24 18:10:01 +02:00
Rubidiumandrubidium42 ddc0d6ead3 Codechange: use string comparision for ConExec's second parameter 2025-04-24 18:10:01 +02:00
Richard WheelerandGitHub a01d47b333 Doc: Correct baseset obg file MD5 and url documentation (#14086) 2025-04-24 12:24:32 +01:00
froschandfrosch 880a947eb3 Fix: [NewGRF] Randomisation-trigger 'path reservation' did not work for waypoints. 2025-04-24 09:19:43 +02:00
froschandfrosch bc0eaf9ac4 Codechange: Allow passing waypoints to Trigger(Station|RoadStop)Randomisation. 2025-04-24 09:19:43 +02:00
Peter NelsonandGitHub c0cd7cafe4 Change: Remove minimum width from advanced settings panel of Game Options window. (#14088)
Previous minimum width of 400 was fairly arbitrary and isn't necessary when
the minimum size is suitably constrained by other widgets in the window.

This allows the window to be narrower for CJK languages.
2025-04-23 23:39:35 +00:00
Peter NelsonandGitHub 7846f0f4ee Fix a4dc7249ee: Changing language or interface scale could hang. (#14087)
A bit of hysteresis caused by OnResize calling ReInit calling OnResize calling ReInit calling OnResize calling ReInit ...
2025-04-24 00:29:54 +01:00
Peter NelsonandPeter Nelson 78d3eaf3e2 Change: Slider widget can now be colourful. 2025-04-23 19:07:52 +01:00
Peter NelsonandPeter Nelson 20738865f0 Change: Use standard mauve/yellow scheme for game options window.
This is the colour scheme used by AI/GS settings, NewGRF settings and (previously) advanced settings.
2025-04-23 19:07:52 +01:00
Peter NelsonandPeter Nelson 17e7dafa2a Change: Add alternate_colour widget data for boolean button.
Allows boolean button to have different background and button colours.
2025-04-23 19:07:52 +01:00
Peter NelsonandPeter Nelson 7953a97cbb Change: Adjust section names in Graphics options tab.
"Interface size" and "Graphics" section names do not make much sense any more.
2025-04-23 19:07:52 +01:00
Peter NelsonandPeter Nelson 77da79a052 Codechange: Remove unnecessary SetMinimalSize from Game Options window. 2025-04-23 19:07:52 +01:00
Peter NelsonandPeter Nelson a4dc7249ee Change: Merge Game Options and Game Settings together.
Game Settings is now an additional 'Advanced' tab in the Game Options window.
2025-04-23 19:07:52 +01:00
froschandGitHub 6f056283f2 Fix: [NewGRF] For roadstop multi-tile-animation-triggers, the upper 16 bits were not the same for all tiles. (#14084) 2025-04-23 19:26:09 +02:00
Loïc GuillouxandGitHub f8bdc1e612 Fix f5ffd47: Don't skip separator while reading a record (#14083) 2025-04-23 17:30:51 +02:00
Peter NelsonandGitHub 6d5aee0545 Codechange: Restructure RoadStop Entries to reduce pointers. (#14069)
A RoadStop must own both west and east `Entry`s, but they are allocated separately.

Combine this allocation into one instead.
2025-04-23 08:29:34 +01:00
Peter NelsonandGitHub 41ed5f9822 Fix c7d6934816: Town view caption lost "(City)" flag. (#14082) 2025-04-23 08:14:08 +01:00
translators d9dc6cb5e4 Update: Translations from eints
english (au): 1 change by krysclarke
chinese (traditional): 7 changes by KogentaSan
chinese (simplified): 201 changes by WenSimEHRP
greek: 1 change by gh658804
hungarian: 9 changes by meskobalazs
russian: 1 change by Ln-Wolf
finnish: 1 change by hpiirai
latvian: 1 change by lexuslatvia
portuguese: 1 change by azulcosta
portuguese (brazilian): 1 change by pasantoro
polish: 1 change by pAter-exe
2025-04-23 04:46:38 +00:00
Peter NelsonandGitHub d028c7f9e2 Codefix: Incorrect type for OnDropdownSelect widget parameter. (#14074) 2025-04-22 22:44:25 +01:00
Rubidiumandrubidium42 4149384ebc Codechange: simplify and move GetArgumentInteger 2025-04-22 23:16:15 +02:00
froschandfrosch 2bee313642 Codechange: Replace FindVehicleOnPos with 'for' loop. 2025-04-22 22:12:59 +02:00
froschandfrosch 06c399b79e Codechange: Replace HasVehicleOnPos and callbacks with HasVehicleOnTile and lambda-predicates. 2025-04-22 22:12:59 +02:00
froschandfrosch dacd77b2bd Codechange: Use FindVehicleOnPos instead of HasVehicleOnPos, if there is no stop condition. 2025-04-22 22:12:59 +02:00
froschandfrosch fca3103d8c Codechange: Add iterator for vehicles on a tile. 2025-04-22 22:12:59 +02:00
Rubidiumandrubidium42 917ef03e97 Codechange: use std::string_view in IConsole settings API 2025-04-22 19:52:37 +02:00
Rubidiumandrubidium42 b279bc37e7 Codechange: use std::string_view to set string settings 2025-04-22 19:52:37 +02:00
Rubidiumandrubidium42 fdb8defa64 Codechange: use std::string_view to parse setting values 2025-04-22 19:52:37 +02:00
Peter NelsonandGitHub 12118b201c Change: Enhance visibility of disabled bool button. (#14071)
Apply masked fill to background as well.
2025-04-22 17:37:30 +01:00
translators 415ac07a08 Update: Translations from eints
chinese (simplified): 32 changes by WenSimEHRP
hungarian: 38 changes by meskobalazs
2025-04-22 04:46:01 +00:00
Peter NelsonandGitHub 3aa82d5e63 Codechange: Use EnumBitSet for RoadStopStatusFlags. (#14068) 2025-04-21 20:16:23 +01:00
Peter NelsonandGitHub 81edd1123a Change: Use scaled instead of fixed dimensions for framerate graphs. (#14039) 2025-04-21 20:15:57 +01:00
froschandGitHub d7ddea4032 Codechange: Turn AnimationTrigger enums into enum classes. (#14067) 2025-04-21 20:53:31 +02:00
froschandGitHub 61a0a520f6 Codechange: Unify random trigger enums and turn them into enum classes. (#14066) 2025-04-21 20:03:34 +02:00
froschandfrosch f399b8eb29 Codechange: Unify naming of NewGRF animation callbacks. 2025-04-21 19:06:13 +02:00
froschandfrosch 264abfafe6 Codechange: Rename storage of random triggers to include the term 'random'. 2025-04-21 19:06:13 +02:00
froschandfrosch 39220a5feb Codechange: Unify naming of NewGRF random trigger functions. 2025-04-21 19:06:13 +02:00
froschandfrosch 368d131fb7 Codechange: Use 'construction stage' consistently, instead of 'construction state'. 2025-04-21 19:06:13 +02:00
froschandGitHub 98445088b1 Codechange: Move VehicleEnteredDepotThisTick call to a more suitable position. (#14065) 2025-04-21 17:52:03 +02:00
Peter NelsonandGitHub 7d03cee512 Change: Include dragged train in depot tile length display. (#14060)
In the depot, when dragging a train over another train, the tile length displayed now includes the length of the dragged train.

As the parts are not moved yet, length changes due to callbacks are not taken into account.
2025-04-21 16:37:10 +01:00
froschandGitHub 2a62eea005 Codefix: Comment style. (#14064) 2025-04-21 17:25:09 +02:00
Peter NelsonandPeter Nelson 5b2754fdee Change: Use standard boolean toggle buttons for game options toggles. 2025-04-21 16:23:11 +01:00
Peter NelsonandPeter Nelson d89753b88d Codechange: Add dedicated widget for boolean toggle buttons. 2025-04-21 16:23:11 +01:00
Peter NelsonandPeter Nelson e3d2d68bd4 Change: Draw boolean toggle as a slider widget.
This improves usability as the slider position indicates the state instead of a red/green colour change.
2025-04-21 16:23:11 +01:00
Rubidiumandrubidium42 e3858e81dc Codechange: use std::string_view over const std::string& for finding files 2025-04-21 17:20:00 +02:00
froschandGitHub 354ad43edb Codechange: Remove unnecessary string constructions. (#14063) 2025-04-21 16:46:31 +02:00
Peter NelsonandGitHub e1fdc10227 Fix e114ed357d: Incorrect test of object flags allowed HQ to be removed. (#14062) 2025-04-21 15:45:29 +01:00
Loïc GuillouxandGitHub 305c892b3a Change: "setting" console command now shows default value (#14061) 2025-04-21 16:00:37 +02:00
Peter NelsonandGitHub 788845f731 Change: Allow Double-Ctrl+Click on default size box to clear saved size. (#14055) 2025-04-21 14:16:29 +01:00
Peter NelsonandGitHub 0cf7048a67 Change: Don't select content when toggling its download status. (#14059)
This improves usability when toggling content sorted by status, as the list position no longer jumps to the now (de)selected item, making it easier to (de)select multiple items.
2025-04-21 13:20:52 +01:00
Peter NelsonandGitHub 9ff2b4991f Change: Add scrollbar to infrastructure window. (#14056)
Company infrastructure window will no longer overflow the screen when lots of rail and road types are present.

To further declutter the list, we now only show a value when the count for that item is non-zero.
2025-04-21 08:46:09 +01:00
translators 5502618ac3 Update: Translations from eints
romanian: 1 change by ALEX11BR
2025-04-21 04:45:21 +00:00
Peter NelsonandGitHub e9a92b8795 Fix: Odd drawing and crash if scrollbar is not tall enough. (#14052)
Under certain conditions the scrollbar "tab" could be too large for the scrollbar, and cause issues.

Caused by an off-by-one in height calculation.
2025-04-20 23:23:52 +01:00
froschandGitHub 0efbb3a7a7 Doc: PR template referenced non-existing label. (#14050) 2025-04-20 23:02:33 +02:00
689f55a0ea Fix #14044: Negative string parameters from GS were rendered as zero. (#14049)
String parameters are always stored as uint64_t. Negative values are sign-extended to int64_t and then casted to uint64_t.
The same applies to encoded strings. But ScriptText encoded them as int64_t.

Co-authored-by: rubidium42 <rubidium42@users.noreply.github.com>
2025-04-20 23:01:49 +02:00
Rubidiumandrubidium42 4e14f0ac3f Codechange: pass network tokens as std::string_view or with move semantics where appropriate 2025-04-20 22:43:24 +02:00
Rubidiumandrubidium42 c13956a58a Codechange: use std::string_view for connection strings 2025-04-20 22:43:24 +02:00
Rubidiumandrubidium42 31433882a4 Codechange: use std::string_view for passing NetworkError strings 2025-04-20 22:43:24 +02:00
froschandGitHub 8aa2f6b8a6 Codefix: StringConsumer integer parsing failed for the most negative value, which has no positive equivalent. (#14048) 2025-04-20 22:20:53 +02:00
Peter NelsonandGitHub fc45bb5a2b Codechange: Replace bitstuffed VehicleEnterTileStatus. (#14027)
VehicleEnterTileStatus was an bitset-style enum, but bitstuffed with a StationID. However the StationID part was only used by trains, and only in two locations.

Instead, return just the enum bitset. The two places which require the StationID just call GetStationIndex() directly.
2025-04-20 21:10:02 +01:00
froschandfrosch cb113cfed0 Codefix: Add missing header includes. 2025-04-20 22:06:18 +02:00
froschandfrosch 461b73e21b Codefix: stdafx.h and safeguards.h should be the first and last include in every source file, and not appear in any header file. 2025-04-20 22:06:18 +02:00
froschandfrosch 54de376c55 Codechange: Make the squirrel-exporter skip ctor lists. 2025-04-20 21:07:12 +02:00
froschandfrosch 6256b55671 Codechange: Make the squirrel-exporter skip function bodies. 2025-04-20 21:07:12 +02:00
Rubidiumandrubidium42 26de3404a4 Codechange: use std::string_view for sending chat messages 2025-04-20 13:31:41 +02:00
Rubidiumandrubidium42 bb259b8e77 Codechange: use std::string_view for sending a remote console command (result) 2025-04-20 13:31:41 +02:00
Rubidiumandrubidium42 d99edf2bbc Codechange: use std::string_view for kicking/banning 2025-04-20 13:31:41 +02:00
Rubidiumandrubidium42 a0246bc8a7 Codechange: use std::string_view over std::string for NetworkTextMessage 2025-04-20 13:31:41 +02:00
Rubidiumandrubidium42 a0e4dab771 Codechange: use std::string_view for NetworkAddress::IsInNetmask of std::string 2025-04-20 13:31:41 +02:00
froschandfrosch ff2da0fc73 Codechange: Remove CircularTileSearch. 2025-04-20 12:50:45 +02:00
froschandfrosch b956af631e Codechange: Replace CircularTileSearch with SpiralTileSequence. 2025-04-20 12:50:45 +02:00
froschandfrosch 0dada5a750 Codechange: Add SpiralTileSequence to iterate over a tile area the same ways as CircularTileSearch. 2025-04-20 12:50:45 +02:00
froschandfrosch b9bd7b2cfe Codechange: Confusion of 'radius' and 'diameter' in variable names and comments. 2025-04-20 12:50:45 +02:00
Peter NelsonandGitHub e43e4327a7 Fix: Incorrect string display for autoreplace wagon removal status. (#14038) 2025-04-20 10:44:37 +01:00
translators ee81313254 Update: Translations from eints
welsh: 1 change by Ansbaradigeidfran
vietnamese: 2 changes by KhoiCanDev
2025-04-20 04:43:37 +00:00
Peter NelsonandGitHub 2b92d76e9d Fix e49150f9ca: House picker crashes if selection is not available. (#14030)
This occurs because the extra invalidation in OnInit() also happens on construction, and too early.

Solution is to validate all instead of just position when invalidating in OnInit().
2025-04-19 15:04:18 +01:00
translators d248f45d67 Update: Translations from eints
vietnamese: 7 changes by KhoiCanDev
2025-04-19 04:44:03 +00:00
froschandfrosch 43ea6c9b88 Codechange: Turn AyStar into an actual class with virtual methods instead of function pointers. 2025-04-19 00:24:15 +02:00
froschandfrosch 97ead8e241 Codechange: Remove unused options from AyStar. 2025-04-19 00:24:15 +02:00
froschandfrosch 53899c3c21 Codechange: Replace vehicle viewport hash macros with functions. 2025-04-18 23:41:37 +02:00
froschandfrosch cde350dc01 Codechange: Replace macros GENERAL_SPRITE_COLOUR and COMPANY_SPRITE_COLOUR with functions GetColourPalette and GetCompanyPalette. 2025-04-18 23:41:37 +02:00
froschandfrosch c2c5dae760 Codechange: Turn GREY_SCALE macro into constexpr function. 2025-04-18 23:41:37 +02:00
froschandfrosch 8f335a84cf Codechange: Turn GetCustom(Vehicle|Rotor)(Sprite|Icon) macros into functions. 2025-04-18 23:41:37 +02:00
froschandfrosch 8f8e997575 Codechange: Replace local macro with lambda. 2025-04-18 23:41:37 +02:00
froschandfrosch 68016031cf Codechange: Turn macros GetCompanyHQSize and IncreaseCompanyHQSize into functions. 2025-04-18 23:41:37 +02:00
froschandfrosch 0eb6964311 Codechange: Change ScreenshotCallback into a std::function, so there is no need for void* user data. 2025-04-18 22:43:41 +02:00
froschandfrosch c09e825e0b Codechange: Change SetDateCallback into a std::function, so there is no need for void* user data. 2025-04-18 22:43:41 +02:00
froschandfrosch 0d4588688f Codechange: Manage script event queue using smart pointers. 2025-04-18 19:47:28 +02:00
froschandfrosch b9f4ef3d78 Codechange: Move ScriptStorage constructor into source file, so private members can have partially incomplete types. 2025-04-18 19:47:28 +02:00
froschandGitHub af14809697 Codechange: Add filename and line number to errors/warnings of the squirrel-exporters. (#14031) 2025-04-18 19:43:32 +02:00
froschandGitHub 50252cb5df Codechange: Ini(Load|Save)WindowSettings expect a WindowDesc*, no void*. (#14029) 2025-04-18 18:44:58 +02:00
Peter NelsonandGitHub 394adb654e Codechange: Move GUI parts of badges to a separate file. (#14023) 2025-04-18 17:20:31 +01:00
Peter NelsonandGitHub 67d6089f39 Change: Don't replace stripped control codes with '?' for scripts. (#14028) 2025-04-18 17:20:08 +01:00
froschandfrosch 45917dbaa3 Codechange: Remove unused macro strncasecmp. 2025-04-18 17:16:48 +02:00
froschandfrosch 84e175ce63 Codechange: Determine array length using 'std::size' instead of using a separate constant. 2025-04-18 17:16:48 +02:00
froschandfrosch 7cbf4f5560 Codechange: Expand the single usage of the macro CLRBITS. 2025-04-18 17:16:48 +02:00
froschandfrosch d97936e77a Codechange: Replace ALIGN macro with C++11 alignas specifier. 2025-04-18 17:16:48 +02:00
froschandfrosch f82e172610 Codechange: Expand and remove DEF_CONSOLE_CMD and DEF_CONSOLE_HOOK macros. 2025-04-18 17:16:48 +02:00
froschandfrosch 42deccc4f5 Codechange: Merge (IsOn|Toggle)(Snow|Desert) into (IsOn|Toggle)SnowOrDesert. 2025-04-18 16:33:26 +02:00
froschandfrosch 252376ce3e Codechange: Rename DrawRoadAsSnowDesert to DrawRoadAsSnowOrDesert to be consistent with other functions. 2025-04-18 16:33:26 +02:00
froschandGitHub 26db4ccf09 Codechange: Turn bit-stuffed FiosType enum into a struct. (#14019) 2025-04-18 15:20:55 +02:00
froschandGitHub b862d4937f Codechange: Turn custom vehicle spritenums into enum, and use them consistently. (#14022) 2025-04-18 15:19:28 +02:00
Peter NelsonandGitHub 2c59838acb Codechange: (re)set multiple bitset flags in one call. (#14017) 2025-04-18 14:07:57 +01:00
froschandGitHub 31e716449d Codechange: Change StationNameInformation to not use macros. (#14020) 2025-04-18 15:06:46 +02:00
froschandGitHub 5aed046d11 Fix: [NewGRF] Strange things happened, when using the synchronised tile loop animation trigger for houses. (#14011) 2025-04-17 12:15:49 +02:00
translators 421f202539 Update: Translations from eints
luxembourgish: 103 changes by phreeze83
latvian: 1 change by lexuslatvia
2025-04-17 04:45:26 +00:00
Peter NelsonandGitHub 1f83ea41fc Fix: [NewGRF] PrepareLayout worked on a copy of the data resulting in bad sprite layouts. (#14013) 2025-04-16 21:27:36 +00:00
Peter NelsonandPeter Nelson 378ea52ac6 Codechange: Use EnumBitSet for CzechChooseFlags. 2025-04-16 19:44:28 +01:00
Peter NelsonandPeter Nelson ea0817390f Codechange: Use EnumBitSet for CzechAllowFlags. 2025-04-16 19:44:28 +01:00
Peter NelsonandGitHub 6ea10edef8 Codechange: Use std::unique_ptrs for handling station cargo display. (#14009)
Replaces manual management of raw pointers.
2025-04-16 19:43:45 +01:00
Peter NelsonandPeter Nelson a281ac4674 Codefix: Information for NewGRF specs remained duplicated after loading.
After loading airports+tiles, industries+tiles, houses and objects, their specs are copied from the NewGRF's loading storage to the final global storage.

Instead, move the specs to the their new storage, and clear the NewGRF's storage once done. (Stations and RoadStops are different, and the NewGRF's storage is the final storage location.)
2025-04-16 19:43:07 +01:00
Peter NelsonandPeter Nelson f9ab492e64 Codechange: Pass HouseSpec by reference to IsHouseSpecValid(). 2025-04-16 19:43:07 +01:00
translators b57f3262ec Update: Translations from eints
spanish: 101 changes by MontyMontana
2025-04-16 04:44:48 +00:00
Peter NelsonandGitHub fa0814e257 Codefix: Codestyle consistency fixes. (#14008) 2025-04-15 20:57:13 +00:00
froschandfrosch 03ed59a004 Codechange: Turn AnimationStatus into an enum class. 2025-04-15 20:42:44 +02:00
froschandfrosch 47f0f4dd9e Fix: [NewGRF] Animation speed properties of houses and stations had wrong default. 2025-04-15 20:42:44 +02:00
froschandGitHub 301b209b87 Fix: [NewGRF] Roadstop animation/randomisation was not triggered on vehicle arrival. (#14003) 2025-04-15 14:53:29 +02:00
translators 5fad689782 Update: Translations from eints
norwegian (bokmal): 1 change by eriksorngard
2025-04-15 04:44:48 +00:00
Peter NelsonandGitHub 5008568dfc Codechange: Rename CenterBounds to CentreBounds and move to geometry header. (#14002) 2025-04-14 23:55:40 +01:00
Michael LutzandGitHub fc20ce301a Doc: Missing changelog entry for 15.0-beta2. (#14001) 2025-04-14 18:50:02 +00:00
froschandfrosch d2c9828b4c Codechange: Move IsUtf8Part to only file using it. 2025-04-14 18:56:23 +02:00
froschandfrosch 588fedb5db Codechange: Remove unused Utf8Consume, Utf8Decode, Utf8EncodedCharLen. 2025-04-14 18:56:23 +02:00
froschandfrosch bf8a241f69 Codechange: Parse translation files using StringConsumer. 2025-04-14 18:10:14 +02:00
froschandfrosch b27fd83ff1 Codechange: Parse translation strings using StringConsumer. 2025-04-14 18:10:14 +02:00
froschandfrosch b81a35ea89 Codechange: Use StringConsumer and Builder in StrMakeValid and StrValid. 2025-04-14 18:07:23 +02:00
froschandfrosch dc21fae18e Codechange: Add InPlaceReplacement to couple StringConsumer and Builder on the same buffer. 2025-04-14 18:07:23 +02:00
froschandfrosch f5ffd4789b Codechange: Use StringConsumer in FormatString. 2025-04-14 16:57:41 +02:00
froschandfrosch 15a17d832f Codechange: Use StringConsumer in HandleNewGRFStringControlCodes. 2025-04-14 16:57:41 +02:00
froschandfrosch 98efd3c96e Codefix #13872: Use StringConsumer in TranslateTTDPatchCodes. 2025-04-14 16:57:41 +02:00
John TaylorandGitHub 069edc1a4b Fix #13954: Plotting graphs with limited data to the right. (#13956) 2025-04-14 16:57:07 +02:00
translators 3dacf46870 Update: Translations from eints
vietnamese: 7 changes by KhoiCanDev
2025-04-14 04:44:46 +00:00
Peter NelsonandGitHub d48bc18721 Codechange: Rename badge_class to class_index and badge_classes to gui_classes internally. (#13995)
These names are already used in some places, so this brings a bit of consistency.
2025-04-13 21:06:09 +01:00
froschandfrosch 131b7c7122 Codechange: Replace Utf8Decode usages with StringConsumer. 2025-04-13 21:59:10 +02:00
froschandfrosch 9bcd3feb17 Codechange: Make SQFile a buffered reader, based on StringConsumer. 2025-04-13 21:59:10 +02:00
froschandfrosch 3964d053b5 Codechange: Replace BufState with StringConsumer. 2025-04-13 21:59:10 +02:00
froschandfrosch 96eee0e8e4 Codechange: Base ByteReader on StringConsumer. 2025-04-13 21:59:10 +02:00
froschandfrosch 800d6e339d Codechange: Add StringConsumer. 2025-04-13 21:59:10 +02:00
Peter NelsonandGitHub 4721a1f93e Fix: Don't display badges if the class has no name. (#13994)
Unnamed badges are intended to be for internal-use, not for player information.

Additionally if there is no name to the class, then is causes problems when user configuration comes.
2025-04-13 18:00:41 +01:00
900 changed files with 37546 additions and 26722 deletions
-1
View File
@@ -50,7 +50,6 @@ Describe here
Some things are not automated, and forgotten often. This list is a reminder for the reviewers.
* The bug fix is important enough to be backported? (label: 'backport requested')
* This PR touches english.txt or translations? Check the [guidelines](https://github.com/OpenTTD/OpenTTD/blob/master/docs/eints.md)
* This PR affects the save game format? (label 'savegame upgrade')
* This PR affects the GS/AI API? (label 'needs review: Script API')
* ai_changelog.hpp, game_changelog.hpp need updating.
* The compatibility wrappers (compat_*.nut) need updating.
+50
View File
@@ -0,0 +1,50 @@
name: 'Setup vcpkg'
description: 'Installs vcpkg and initialises binary caching via NuGet'
inputs:
vcpkg-location:
description: 'Where to install vcpkg'
required: true
mono-install-command:
description: 'Command to run to install mono'
required: false
runs:
using: "composite"
steps:
- name: Install vcpkg
shell: bash
run: |
git clone https://github.com/microsoft/vcpkg "${{ inputs.vcpkg-location }}"
cd "${{ inputs.vcpkg-location }}"
./bootstrap-vcpkg.$(if [ "${{ runner.os }}" = "Windows" ]; then echo "bat"; else echo "sh"; fi) -disableMetrics
- name: Install mono
if: inputs.mono-install-command
shell: bash
run: |
${{ inputs.mono-install-command }}
echo "MONO=mono" >> "$GITHUB_ENV"
- name: Setup NuGet Credentials
shell: bash
env:
FEED_URL: 'https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json'
run: |
cd "${{ inputs.vcpkg-location }}"
${{ env.MONO }} $(./vcpkg fetch nuget | tail -n 1) \
sources add \
-source "${{ env.FEED_URL }}" \
-storepasswordincleartext \
-name "GitHub" \
-username "${{ github.repository_owner }}" \
-password "${{ github.token }}"
${{ env.MONO }} $(./vcpkg fetch nuget | tail -n 1) \
setapikey "${{ github.token }}" \
-source "${{ env.FEED_URL }}"
- name: Setup vcpkg caching
uses: actions/github-script@v7
with:
script: |
core.exportVariable('VCPKG_BINARY_SOURCES', 'clear;nuget,GitHub,readwrite')
+1 -1
View File
@@ -158,7 +158,7 @@ def scan_source_files(path, strings_found):
# Most files we can just open, but some use magic, that requires the
# G++ preprocessor before we can make sense out of it.
if new_path == "src/table/cargo_const.h":
p = subprocess.run(["g++", "-E", new_path], stdout=subprocess.PIPE)
p = subprocess.run(["g++", "-E", "-DCHECK_UNUSED_STRINGS", new_path], stdout=subprocess.PIPE)
output = p.stdout.decode()
else:
with open(new_path) as fp:
+4 -11
View File
@@ -32,18 +32,11 @@ jobs:
- name: Checkout
uses: actions/checkout@v4
- name: Setup vcpkg caching
uses: actions/github-script@v7
- name: Setup vcpkg
uses: ./.github/actions/setup-vcpkg
with:
script: |
core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || '');
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
core.exportVariable('VCPKG_BINARY_SOURCES', 'clear;x-gha,readwrite')
- name: Install vcpkg
run: |
git clone https://github.com/microsoft/vcpkg ${{ runner.temp }}/vcpkg
${{ runner.temp }}/vcpkg/bootstrap-vcpkg.sh -disableMetrics
vcpkg-location: ${{ runner.temp }}/vcpkg
mono-install-command: 'sudo apt-get install -y --no-install-recommends mono-complete'
- name: Install dependencies
run: |
+4 -11
View File
@@ -34,18 +34,11 @@ jobs:
- name: Checkout
uses: actions/checkout@v4
- name: Setup vcpkg caching
uses: actions/github-script@v7
- name: Setup vcpkg
uses: ./.github/actions/setup-vcpkg
with:
script: |
core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || '');
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
core.exportVariable('VCPKG_BINARY_SOURCES', 'clear;x-gha,readwrite')
- name: Install vcpkg
run: |
git clone https://github.com/microsoft/vcpkg ${{ runner.temp }}/vcpkg
${{ runner.temp }}/vcpkg/bootstrap-vcpkg.sh -disableMetrics
vcpkg-location: ${{ runner.temp }}/vcpkg
mono-install-command: 'brew install mono'
- name: Install OpenGFX
run: |
+3 -11
View File
@@ -20,18 +20,10 @@ jobs:
- name: Checkout
uses: actions/checkout@v4
- name: Setup vcpkg caching
uses: actions/github-script@v7
- name: Setup vcpkg
uses: ./.github/actions/setup-vcpkg
with:
script: |
core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || '');
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
core.exportVariable('VCPKG_BINARY_SOURCES', 'clear;x-gha,readwrite')
- name: Install vcpkg
run: |
git clone https://github.com/microsoft/vcpkg ${{ runner.temp }}\vcpkg
${{ runner.temp }}\vcpkg\bootstrap-vcpkg.bat -disableMetrics
vcpkg-location: ${{ runner.temp }}/vcpkg
- name: Install OpenGFX
shell: bash
+4 -11
View File
@@ -26,18 +26,11 @@ jobs:
- name: Checkout
uses: actions/checkout@v4
- name: Setup vcpkg caching
uses: actions/github-script@v7
- name: Setup vcpkg
uses: ./.github/actions/setup-vcpkg
with:
script: |
core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || '');
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
core.exportVariable('VCPKG_BINARY_SOURCES', 'clear;x-gha,readwrite')
- name: Install vcpkg
run: |
git clone https://github.com/microsoft/vcpkg ${{ runner.temp }}/vcpkg
${{ runner.temp }}/vcpkg/bootstrap-vcpkg.sh -disableMetrics
vcpkg-location: ${{ runner.temp }}/vcpkg
mono-install-command: 'sudo apt-get install -y --no-install-recommends mono-complete'
- name: Install dependencies
run: |
+6 -18
View File
@@ -35,14 +35,6 @@ jobs:
- name: Enable Rust cache
uses: Swatinem/rust-cache@v2
- name: Setup vcpkg caching
uses: actions/github-script@v7
with:
script: |
core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || '');
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
core.exportVariable('VCPKG_BINARY_SOURCES', 'clear;x-gha,readwrite')
- name: Install dependencies
run: |
echo "::group::Install system dependencies"
@@ -113,20 +105,16 @@ jobs:
# EOF
echo "::endgroup::"
# We use vcpkg for our dependencies, to get more up-to-date version.
echo "::group::Install vcpkg and dependencies"
git clone https://github.com/microsoft/vcpkg /vcpkg
(
cd /vcpkg
./bootstrap-vcpkg.sh -disableMetrics
)
echo "::group::Install breakpad dependencies"
cargo install --locked dump_syms
echo "::endgroup::"
- name: Setup vcpkg
uses: ./.github/actions/setup-vcpkg
with:
vcpkg-location: /vcpkg
mono-install-command: 'yum install -y mono-complete'
- name: Install GCC problem matcher
uses: ammaraskar/gcc-problem-matcher@master
+5 -12
View File
@@ -37,18 +37,11 @@ jobs:
- name: Enable Rust cache
uses: Swatinem/rust-cache@v2
- name: Setup vcpkg caching
uses: actions/github-script@v7
- name: Setup vcpkg
uses: ./.github/actions/setup-vcpkg
with:
script: |
core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || '');
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
core.exportVariable('VCPKG_BINARY_SOURCES', 'clear;x-gha,readwrite')
- name: Install vcpkg
run: |
git clone https://github.com/microsoft/vcpkg ${{ runner.temp }}/vcpkg
${{ runner.temp }}/vcpkg/bootstrap-vcpkg.sh -disableMetrics
vcpkg-location: ${{ runner.temp }}/vcpkg
mono-install-command: 'brew install mono'
- name: Install dependencies
env:
@@ -86,7 +79,7 @@ jobs:
echo "::endgroup::"
- name: Import code signing certificates
uses: Apple-Actions/import-codesign-certs@v3
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 }}
+3 -11
View File
@@ -45,18 +45,10 @@ jobs:
- name: Enable Rust cache
uses: Swatinem/rust-cache@v2
- name: Setup vcpkg caching
uses: actions/github-script@v7
- name: Setup vcpkg
uses: ./.github/actions/setup-vcpkg
with:
script: |
core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || '');
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
core.exportVariable('VCPKG_BINARY_SOURCES', 'clear;x-gha,readwrite')
- name: Install vcpkg
run: |
git clone https://github.com/microsoft/vcpkg ${{ runner.temp }}\vcpkg
${{ runner.temp }}\vcpkg\bootstrap-vcpkg.bat -disableMetrics
vcpkg-location: ${{ runner.temp }}/vcpkg
- name: Install dependencies
shell: bash
+1 -1
View File
@@ -77,7 +77,7 @@ jobs:
curl -L https://cdn.openttd.org/openmsx-releases/0.4.2/openmsx-0.4.2-all.zip -o openmsx-all.zip
echo "::endgroup::"
echo "::group::Unpack OpenGFX"
echo "::group::Unpack OpenMSX"
unzip openmsx-all.zip
tar xf openmsx-*.tar
echo "::endgroup::"
+2 -14
View File
@@ -37,12 +37,10 @@ Both 'stable' and 'nightly' versions are available for download:
OpenTTD is also available for free on [Steam](https://store.steampowered.com/app/1536610/OpenTTD/), [GOG.com](https://www.gog.com/game/openttd), and the [Microsoft Store](https://www.microsoft.com/p/openttd-official/9ncjg5rvrr1c). On some platforms OpenTTD will be available via your OS package manager or a similar service.
## 1.2) OpenTTD gameplay manual
OpenTTD has a [community-maintained wiki](https://wiki.openttd.org/), including a gameplay manual and tips.
## 1.3) Supported platforms
OpenTTD has been ported to several platforms and operating systems.
@@ -56,6 +54,7 @@ The currently supported platforms are:
Other platforms may also work (in particular various BSD systems), but we don't actively test or maintain these.
### 1.3.1) Legacy support
Platforms, languages and compilers change.
We'll keep support going on old platforms as long as someone is interested in supporting them, except where it means the project can't move forward to keep up with language and compiler features.
@@ -72,7 +71,6 @@ For some platforms these will be downloaded during the installation process if r
For some platforms, you will need to refer to [the installation guide](https://wiki.openttd.org/en/Manual/Installation).
### 1.4.1) Free graphics and sound files
The free data files, split into OpenGFX for graphics, OpenSFX for sounds and
@@ -85,7 +83,6 @@ OpenMSX for music can be found at:
Please follow the readme of these packages about the installation procedure.
The Windows installer can optionally download and install these packages.
### 1.4.2) Original Transport Tycoon Deluxe graphics and sound files
If you want to play with the original Transport Tycoon Deluxe data files you have to copy the data files from the CD-ROM into the baseset/ directory.
@@ -100,7 +97,6 @@ You need to copy the following files:
- trgir.grf or TRGI.GRF
- trgtr.grf or TRGT.GRF
### 1.4.3) Original Transport Tycoon Deluxe music
If you want the Transport Tycoon Deluxe music, copy the appropriate files from the original game into the baseset folder.
@@ -108,7 +104,6 @@ If you want the Transport Tycoon Deluxe music, copy the appropriate files from t
- TTD for DOS: The GM.CAT file
- Transport Tycoon Original: The GM.CAT file, but rename it to GM-TTO.CAT
## 1.5) Add-on content / mods
OpenTTD features multiple types of add-on content, which modify gameplay in different ways.
@@ -117,7 +112,6 @@ Most types of add-on content can be downloaded within OpenTTD via the 'Check Onl
Add-on content can also be installed manually, but that's more complicated; the [OpenTTD wiki](https://wiki.openttd.org/) may offer help with that, or the [OpenTTD directory structure guide](./docs/directory_structure.md).
### 1.5.1) Social Integration
OpenTTD has the ability to load plugins to integrate with Social Platforms like Steam, Discord, etc.
@@ -126,7 +120,6 @@ To enable such integration, the plugin for the specific platform has to be downl
See [OpenTTD's website](https://www.openttd.org), under Downloads, for what plugins are available.
### 1.6) OpenTTD directories
OpenTTD uses its own directory structure to store game data, add-on content etc.
@@ -137,7 +130,6 @@ For more information, see the [directory structure guide](./docs/directory_struc
If you want to compile OpenTTD from source, instructions can be found in [COMPILING.md](./COMPILING.md).
## 2.0) Contact and Community
'Official' channels
@@ -160,12 +152,10 @@ You can play OpenTTD with others, either cooperatively or competitively.
See the [multiplayer documentation](./docs/multiplayer.md) for more details.
### 2.2) Contributing to OpenTTD
We welcome contributors to OpenTTD. More information for contributors can be found in [CONTRIBUTING.md](./CONTRIBUTING.md)
### 2.3) Reporting bugs
Good bug reports are very helpful. We have a [guide to reporting bugs](./CONTRIBUTING.md#bug-reports) to help with this.
@@ -173,12 +163,10 @@ Good bug reports are very helpful. We have a [guide to reporting bugs](./CONTRI
Desyncs in multiplayer are complex to debug and report (some software development skils are required).
Instructions can be found in [debugging and reporting desyncs](./docs/debugging_desyncs.md).
### 2.4) Translating
OpenTTD is translated into many languages. Translations are added and updated via the [online translation tool](https://translator.openttd.org).
## 3.0) Licensing
OpenTTD is licensed under the GNU General Public License version 2.0.
@@ -215,6 +203,6 @@ See `src/3rdparty/openttd_social_integration_api/LICENSE` for the complete licen
The atomic datatype support detection in `cmake/3rdparty/llvm/CheckAtomic.cmake` is licensed under the Apache 2.0 license.
See `cmake/3rdparty/llvm/LICENSE.txt` for the complete license text.
## 4.0 Credits
## 4.0) Credits
See [CREDITS.md](./CREDITS.md)
+8
View File
@@ -36,3 +36,11 @@ AITown.FoundTown <- function(tile, size, city, layout, name) { return AITown.Fou
AIVehicle.SetNameCompat14 <- AIVehicle.SetName;
AIVehicle.SetName <- function(id, name) { return AIVehicle.SetNameCompat14(id, AICompat14.Text(name)); }
AIObject.constructorCompat14 <- AIObject.constructor;
foreach(name, object in CompatScriptRootTable) {
if (type(object) != "class") continue;
if (!object.rawin("constructor")) continue;
if (object.constructor != AIObject.constructorCompat14) continue;
object.constructor <- function() : (name) { AILog.Error("'" + name + "' is not instantiable"); }
}
+11
View File
@@ -9,6 +9,9 @@
GSBridge.GetBridgeID <- GSBridge.GetBridgeType;
/* Emulate old GSText parameter padding behaviour */
GSText.SCRIPT_TEXT_MAX_PARAMETERS <- 20;
class GSCompat14 {
function Text(text)
{
@@ -78,3 +81,11 @@ GSTown.FoundTown <- function(tile, size, city, layout, name) { return GSTown.Fou
GSVehicle.SetNameCompat14 <- GSVehicle.SetName;
GSVehicle.SetName <- function(id, name) { return GSVehicle.SetNameCompat14(id, GSCompat14.Text(name)); }
GSObject.constructorCompat14 <- GSObject.constructor;
foreach(name, object in CompatScriptRootTable) {
if (type(object) != "class") continue;
if (!object.rawin("constructor")) continue;
if (object.constructor != GSObject.constructorCompat14) continue;
object.constructor <- function() : (name) { GSLog.Error("'" + name + "' is not instantiable"); }
}
+149
View File
@@ -1,5 +1,153 @@
## 15.x
### 15.0-beta3 (2025-08-31)
- Feature: Identify cities in the main viewport by appending an icon to their names (#14504)
- Feature: Allow stations and roadstops under bridges (#14477)
- Feature: Separate ships travelling in opposite direction (#14493)
- Feature: Town and Industry cargo history graphs (#14321, #14461)
- Feature: New company face definition system and UI (#14319)
- Feature: Rework intro screen menu (#14220, #14233)
- Feature: Scrollbar for infrastructure window (#14056)
- Feature: Double-Ctrl+Click on default size box to clear saved size (#14055)
- Feature: Configure badges in build vehicle and picker windows (#13993, #14021)
- Feature: Player configuration of badge display (#13993, #14021)
- Feature: Merge Game Options and Game Settings together (#13242, #14088)
- Feature: Option to disable activate-on-release behaviour of toolbar dropdown buttons (#10938)
- Add: Maori (New Zealand) language (#14540)
- Add: Vietnamese Dong currency (#14474)
- Add: Buttons to change picker preview image height (#14373)
- Add: Show and sort online content version in list (#14355)
- Add: Allow separate expansion of town buildings and roads in scenario editor (#14341)
- Add: Hover on graph legend to highlight line (#14314)
- Add: [Script] Ability to clone ScriptList objects (#14305)
- Add: [NewGRF] All callbacks returning D0xx strings, have now the option to return any string id via register 0x100 (#14224)
- Add: [BaseSet] Allow basesets to set minor and patch versions in obg/obs/obm files (#14169)
- Add: "Many random towns" button in scenario editor now prompts for the number of towns, with defaults based on new game settings (#14158)
- Add: [NewGRF] Special value 0x7FFE for VarAction2 results specifying 'return calculated result' (#14149)
- Add: [NewGRF] Special value 0x7FFF for Action2 references specifying explicit 'callback/sprite-resolving failed' (#14149)
- Add: [NewGRF] Add purchase list Action3 CID for houses, industries, industry tiles, airports and airport tiles (#14121)
- Add: [NewGRF] Provide random bits in var10 of house callback 1C 'construction stage changed' (#14095)
- Add: [NewGRF] Station/roadstop animation-triggers 'tile loop' (bit 7) and 'path reservation' (bit 8) (#14080)
- Add: [Script] ScriptVehicleList_Waypoint (#13456)
- Change: Update OpenTTD TTF fonts to v0.8 (#14546)
- Change: Hide bridge pillars if obstructed by tile below (#14517)
- Change: Reduce visual height of default rail waypoints (#14503)
- Change: Improve sprite ellipsis appearance (#14404)
- Change: [Script] Don't allow scripts to instantiate ScriptEvent (#14276)
- Change: [Script] ScriptVehicleList_Station accepts an optional VehicleType parameter (#14260)
- Change: Remove Apply button from NewGRF config window when unneeded (#14254)
- Change: [NewGRF] Increase the textstack for all callbacks to 16 registers (#14224)
- Change: Remove button to toggle showing advanced signal types (#14219)
- Change: [Script] Remove the limit of 20 parameters to a Text string (#14193)
- Change: [NewGRF] If Action123 does not resolve in a valid SpriteSet, prefer drawing the default sprite instead of an invalid sprite (#14143)
- Change: Remove extra close buttons from some windows (#14124)
- Change: Limit height of settings description, and add scrollbar (#14102)
- Change: [NewGRF] Provide shared random bits in multi-tile animation-triggers of airport tiles and objects, just like for other features (#14090)
- Change: [NewGRF] Animation-trigger 'construction stage changed' of houses and industries now also triggers at construction start (#14089)
- Change: "setting" console command now shows default value (#14061)
- Change: Include dragged train in depot tile length display (#14060)
- Change: Don't select content when toggling its download status (#14059)
- Change: Draw boolean settings toggles as a slider widget (#14051, #14071)
- Change: Don't replace stripped control codes with '?' for scripts (#14028)
- Change: [Script] Move GSStation::GetOwner to GSBaseStation::GetOwner (#13406)
- Fix #14561: Vehicle effects were missing for vehicle on bridge (#14563)
- Fix #14553: Parameter configuration of pre-action 14 NewGRFs did not work (#14554)
- Fix: File/directory titles not updated if language is changed (#14542)
- Fix: Missing space after old file type identifier (#14541)
- Fix: Account for both text and icon size in station waiting cargo display (#14535)
- Fix: Crash when buying out company with groups (#14534)
- Fix #10222: Off by one drawing lines of certain widths (#14520, #14522, #14523)
- Fix: [Script] Invalid title on GSGoal.Question windows (#14519)
- Fix: 'Map edges' GUI buttons shouldn't initialize with water on northeast edge (#14514)
- Fix #14415: Update survey option text when changing setting (#14487)
- Fix #14480: Music player playlist buttons are clickable but non-operational in intro menu (#14482)
- Fix: Missing button beeps (#14470)
- Fix #14464: Invalid string parameter in scenario editor when unable to build industry (#14465)
- Fix: [Linkgraph] Use correct station ID when erasing flows (#14459)
- Fix: Vehicle liveries did not update when switching company (#14456)
- Fix: Engine preview window could have the wrong size (#14455)
- Fix #8167: No error sub-message when trying to clear protected buildings (#14444)
- Fix #14433: [NewGRF] Road tile for drive-through stops was not drawn (#14434)
- Fix: [Win32] Build failure with newer Windows SDK version due to WinRT changes (#14432)
- Fix #14396: Industry production graph showed zero when data was unavailable (#14416)
- Fix #14385: Crash in industry view due to incorrect string parameter calculations (#14413)
- Fix #14360: Stop reusing strings for Low/Medium/High setting values to improve translations (#14409)
- Fix #14377: Make house picker window remember house protection state when closed (#14406)
- Fix #14375: When loading config, validate timekeeping mode and minutes per year (#14405)
- Fix: Include sort button width in content list header minimal size (#14402)
- Fix: Don't draw truncation ellipsis if it's too wide (#14401)
- Fix: Don't include ellipsis width in RTL truncation offset (#14400)
- Fix: Buildings with non-zero subtile offsets broken in house picker (#14390)
- Fix #12900: Could not use join station with new non-square stations (#14378)
- Fix: Allow object picker to resize if there are no classes (#14372)
- Fix #14081: Only allow "rm" & "del" console commands to remove savegames (#14371)
- Fix: Train path reservations on different railtypes could join leading to train crashes (#14366)
- Fix #14356: Incorrect sprite group chosen for stations and road stops (#14359)
- Fix: Wrong error message about script Save() returned value (#14334)
- Fix: Hidden-by-facility station signs were not ignored when handling clicks (#14326)
- Fix: [Script] SQOpsLimiter had no effect for native valuator/filter (#14322)
- Fix: Crash if loading compatibility scripts fails (#14318)
- Fix #14277: Aircraft could land when a zeppelin was on the runway (#14317)
- Fix: Drag drop line position when dragging NewGRF from file to active panel (#14316)
- Fix: Upgrade button in NewGRF window no longer worked (#14315)
- Fix: [NewGRF] Clear rail vehicle flipped flag if reverse probability callback returns false (#14281)
- Fix: [Script] Conversion from ScriptEvent to ScriptEventCompanyTown subclasses (#14274)
- Fix: Empty first parameter of EncodedString was skipped (#14273)
- Fix #14271: Crash due to incorrect parameter index in string (#14272)
- Fix: Restore the behaviour when entering numbers in query windows: clamp integers out of range to the maximum valid value (#14268)
- Fix: Replacing a dropdown list could reposition it partially off-screen (#14261)
- Fix: Click+Dragging of selected order was not possible (#14259)
- Fix #14256: Company finance windows not updated when paused (#14258)
- Fix: Incorrect tile colour in smallmap for snowy clear tiles in vegetation mode (#14257)
- Fix #14241: Invalid string parameters in subsidies list window (#14243)
- Fix #13854: 40bpp-anim blitter recolouring failed for 32bpp pixels without mask channel (#14242)
- Fix #14234: Crash due to broken invalid string parameter handling (#14235, #14236)
- Fix: Closing the Game Options window closes all textfile windows (#14210)
- Fix: Zoom-scroll extra viewports only if the mouse cursor is over the viewport (#14209)
- Fix: Changing monospace font didn't refresh the monospace width cache, causing wrapping issues (#14185)
- Fix: Crash/Undefined behaviour in station view window (#14183)
- Fix: Handle tab characters when loading GS strings from savegame (#14180)
- Fix: [Script] Access to enum/consts defined outside of main.nut (#14176)
- Fix: Small order list arrow was wrong direction for RTL text (#14174)
- Fix #14170: Missing spaces for timetabled order strings (#14172)
- Fix #14166: Loan was no longer invalidated when refreshing finance window (#14168)
- Fix #14098: Ability to play MIDI tracks over 7 minutes long (#14144)
- Fix: [NewGRF] AI station construction callback did not work for stations with ID >= 0x100 (#14142)
- Fix: Out-of-bounds read, if NewGRF stations provided no spritesets (#14140)
- Fix: [NewGRF] The result of Action123 evaluation affected rerandomisation in a weird corner case (#14139)
- Fix: [NewGRF] Computed VarAction2 callback results were not always properly masked to 15 bit results (#14138)
- Fix #14125: NewGRF sounds were not loaded (#14130)
- Fix: List Ctrl+Click behaviour for vehicle details tooltip (#14127)
- Fix: Road vehicle blocking and train collisions used slightly inconsistent distance thresholds (#14114)
- Fix #14107: Mark the company value in the company view window dirty when it changes (#14112)
- Fix #14107: Invalidate all shared vehicle windows when changing group (#14110)
- Fix #14104: Don't base timetable timing decisions on client settings (#14105)
- Fix: Focus settings filter box (only) when the tab becomes active (#14100)
- Fix: [Script] Reject scripts using negative version (#14096)
- Fix: Map size column in server list could be too wide (#14094)
- Fix: [NewGRF] Cargo-types for airport-tile animation-triggers were not properly translated (#14092)
- Fix: [NewGRF] For animation-triggers which do not supply a cargo-type in var18, the var18 bits should remain empty (#14091)
- Fix: Changing language or interface scale could hang (#14087)
- Fix: [NewGRF] For roadstop multi-tile-animation-triggers, the upper 16 bits were not the same for all tiles (#14084)
- Fix: Town view caption lost "(City)" flag (#14082)
- Fix: [NewGRF] Randomisation-trigger 'path reservation' did not work for waypoints (#14076)
- Fix: Incorrect test of object flags allowed HQ to be removed (#14062)
- Fix: Odd drawing and crash if scrollbar is not tall enough (#14052)
- Fix: Incorrect string display for autoreplace wagon removal status (#14038)
- Fix: House picker crashes if selection is not available (#14030)
- Fix: [NewGRF] PrepareLayout worked on a copy of the data resulting in bad sprite layouts (#14013)
- Fix: [NewGRF] Strange things happened, when using the synchronised tile loop animation trigger for houses (#14011)
- Fix: [NewGRF] Animation speed properties of houses and stations had wrong default (#14005)
- Fix: [NewGRF] Roadstop animation/randomisation was not triggered on vehicle arrival (#14003)
- Fix: Don't display badges if the class has no name (#13994)
- Fix #13954: Plotting graphs with limited data to the right (#13956)
- Fix #13307: Return non-zero value when there is a mistake in command-line arguments (#13547)
- Fix: [Script] Make ScriptOrder functions aware of road waypoints (#13419)
- Fix: Scale graph gridlines and axes with GUI scale (#12131)
- Fix: Original graphics' tycoon-of-the-century sprite assumes a black background (#11679, #14545)
### 15.0-beta2 (2025-04-13)
- Feature: Snow-covered rocks are now visible (#13627)
@@ -20,6 +168,7 @@
- Add: Ukrainian Hryvnia currency (#12877)
- Add: Convert 32bpp-only sprites to 8bpp when needed (#11602)
- Change: [Script] Start GS (but don't run it) when generating world in scenario editor (#13961)
- Change: [Script] Add vehicle owner to crash event (#13878)
- Change: Make tree placement at world generation look more organic (#13515)
- Change: [MacOS] Put the icon in a rounded rectangle (#13446)
- Change: [Script] GetWaypointID to return the StationID of any waypoint (#13407)
+99 -99
View File
@@ -17,41 +17,48 @@ if(NOT APILC)
endif()
macro(dump_fileheader)
get_filename_component(SCRIPT_API_FILE_NAME "${SCRIPT_API_FILE}" NAME)
string(APPEND SQUIRREL_EXPORT "\n#include \"../${SCRIPT_API_FILE_NAME}\"")
get_filename_component(SCRIPT_API_FILE_NAME "${SCRIPT_API_FILE}" NAME_WE)
string(APPEND SQUIRREL_EXPORT "\n#include \"../${SCRIPT_API_FILE_NAME}.hpp\"")
if(NOT "${APIUC}" STREQUAL "Template")
string(REPLACE "script_" "template_" SCRIPT_API_FILE_NAME "${SCRIPT_API_FILE_NAME}")
string(APPEND SQUIRREL_EXPORT "\n#include \"../template/${SCRIPT_API_FILE_NAME}.sq\"")
string(APPEND SQUIRREL_EXPORT "\n#include \"../template/${SCRIPT_API_FILE_NAME}.sq.hpp\"")
endif()
endmacro()
macro(open_namespace)
if(NOT NAMESPACE_OPENED)
string(APPEND SQUIRREL_EXPORT "\nnamespace SQConvert {")
set(NAMESPACE_OPENED TRUE)
endif()
endmacro()
macro(dump_class_templates NAME)
string(REGEX REPLACE "^Script" "" REALNAME ${NAME})
string(APPEND SQUIRREL_EXPORT "\n template <> struct Param<${NAME} *> { static inline ${NAME} *Get(HSQUIRRELVM vm, int index) { return static_cast<${NAME} *>(Squirrel::GetRealInstance(vm, index, \"${REALNAME}\")); } };")
string(APPEND SQUIRREL_EXPORT "\n template <> struct Param<${NAME} &> { static inline ${NAME} &Get(HSQUIRRELVM vm, int index) { return *static_cast<${NAME} *>(Squirrel::GetRealInstance(vm, index, \"${REALNAME}\")); } };")
string(APPEND SQUIRREL_EXPORT "\n template <> struct Param<const ${NAME} *> { static inline const ${NAME} *Get(HSQUIRRELVM vm, int index) { return static_cast<${NAME} *>(Squirrel::GetRealInstance(vm, index, \"${REALNAME}\")); } };")
string(APPEND SQUIRREL_EXPORT "\n template <> struct Param<const ${NAME} &> { static inline const ${NAME} &Get(HSQUIRRELVM vm, int index) { return *static_cast<${NAME} *>(Squirrel::GetRealInstance(vm, index, \"${REALNAME}\")); } };")
string(APPEND SQUIRREL_EXPORT "\n\ttemplate <> struct Param<${NAME} *> { static inline ${NAME} *Get(HSQUIRRELVM vm, int index) { return static_cast<${NAME} *>(Squirrel::GetRealInstance(vm, index, \"${REALNAME}\")); } };")
string(APPEND SQUIRREL_EXPORT "\n\ttemplate <> struct Param<${NAME} &> { static inline ${NAME} &Get(HSQUIRRELVM vm, int index) { return *static_cast<${NAME} *>(Squirrel::GetRealInstance(vm, index, \"${REALNAME}\")); } };")
string(APPEND SQUIRREL_EXPORT "\n\ttemplate <> struct Param<const ${NAME} *> { static inline const ${NAME} *Get(HSQUIRRELVM vm, int index) { return static_cast<${NAME} *>(Squirrel::GetRealInstance(vm, index, \"${REALNAME}\")); } };")
string(APPEND SQUIRREL_EXPORT "\n\ttemplate <> struct Param<const ${NAME} &> { static inline const ${NAME} &Get(HSQUIRRELVM vm, int index) { return *static_cast<${NAME} *>(Squirrel::GetRealInstance(vm, index, \"${REALNAME}\")); } };")
if("${NAME}" STREQUAL "ScriptEvent")
string(APPEND SQUIRREL_EXPORT "\n template <> struct Return<${NAME} *> { static inline int Set(HSQUIRRELVM vm, ${NAME} *res) { if (res == nullptr) { sq_pushnull(vm); return 1; } Squirrel::CreateClassInstanceVM(vm, \"${REALNAME}\", res, nullptr, DefSQDestructorCallback<${NAME}>, true); return 1; } };")
string(APPEND SQUIRREL_EXPORT "\n\ttemplate <> struct Return<${NAME} *> { static inline int Set(HSQUIRRELVM vm, ${NAME} *res) { if (res == nullptr) { sq_pushnull(vm); return 1; } Squirrel::CreateClassInstanceVM(vm, \"${REALNAME}\", res, nullptr, DefSQDestructorCallback<${NAME}>, true); return 1; } };")
elseif("${NAME}" STREQUAL "ScriptText")
string(APPEND SQUIRREL_EXPORT "\n")
string(APPEND SQUIRREL_EXPORT "\n template <> struct Param<Text *> {")
string(APPEND SQUIRREL_EXPORT "\n static inline Text *Get(HSQUIRRELVM vm, int index) {")
string(APPEND SQUIRREL_EXPORT "\n if (sq_gettype(vm, index) == OT_INSTANCE) {")
string(APPEND SQUIRREL_EXPORT "\n return Param<ScriptText *>::Get(vm, index);")
string(APPEND SQUIRREL_EXPORT "\n }")
string(APPEND SQUIRREL_EXPORT "\n if (sq_gettype(vm, index) == OT_STRING) {")
string(APPEND SQUIRREL_EXPORT "\n return new RawText(Param<const std::string &>::Get(vm, index));")
string(APPEND SQUIRREL_EXPORT "\n }")
string(APPEND SQUIRREL_EXPORT "\n if (sq_gettype(vm, index) == OT_NULL) {")
string(APPEND SQUIRREL_EXPORT "\n return nullptr;")
string(APPEND SQUIRREL_EXPORT "\n }")
string(APPEND SQUIRREL_EXPORT "\n throw sq_throwerror(vm, fmt::format(\"parameter {} has an invalid type ; expected: 'Text'\", index - 1));")
string(APPEND SQUIRREL_EXPORT "\n }")
string(APPEND SQUIRREL_EXPORT "\n };")
string(APPEND SQUIRREL_EXPORT "\n\ttemplate <> struct Param<Text *> {")
string(APPEND SQUIRREL_EXPORT "\n\t\tstatic inline Text *Get(HSQUIRRELVM vm, int index) {")
string(APPEND SQUIRREL_EXPORT "\n\t\t\tif (sq_gettype(vm, index) == OT_INSTANCE) {")
string(APPEND SQUIRREL_EXPORT "\n\t\t\t\treturn Param<ScriptText *>::Get(vm, index);")
string(APPEND SQUIRREL_EXPORT "\n\t\t\t}")
string(APPEND SQUIRREL_EXPORT "\n\t\t\tif (sq_gettype(vm, index) == OT_STRING) {")
string(APPEND SQUIRREL_EXPORT "\n\t\t\t\treturn new RawText(Param<const std::string &>::Get(vm, index));")
string(APPEND SQUIRREL_EXPORT "\n\t\t\t}")
string(APPEND SQUIRREL_EXPORT "\n\t\t\tif (sq_gettype(vm, index) == OT_NULL) {")
string(APPEND SQUIRREL_EXPORT "\n\t\t\t\treturn nullptr;")
string(APPEND SQUIRREL_EXPORT "\n\t\t\t}")
string(APPEND SQUIRREL_EXPORT "\n\t\t\tthrow sq_throwerror(vm, fmt::format(\"parameter {} has an invalid type ; expected: 'Text'\", index - 1));")
string(APPEND SQUIRREL_EXPORT "\n\t\t}")
string(APPEND SQUIRREL_EXPORT "\n\t};")
else()
string(APPEND SQUIRREL_EXPORT "\n template <> struct Return<${NAME} *> { static inline int Set(HSQUIRRELVM vm, ${NAME} *res) { if (res == nullptr) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, \"${REALNAME}\", res, nullptr, DefSQDestructorCallback<${NAME}>, true); return 1; } };")
string(APPEND SQUIRREL_EXPORT "\n\ttemplate <> struct Return<${NAME} *> { static inline int Set(HSQUIRRELVM vm, ${NAME} *res) { if (res == nullptr) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, \"${REALNAME}\", res, nullptr, DefSQDestructorCallback<${NAME}>, true); return 1; } };")
endif()
endmacro()
@@ -66,7 +73,6 @@ macro(reset_reader)
unset(STATIC_METHODS)
unset(CLS)
unset(START_SQUIRREL_DEFINE_ON_NEXT_LINE)
set(CLS_LEVEL 0)
unset(CLS_IN_API)
endmacro()
@@ -75,6 +81,9 @@ reset_reader()
file(STRINGS "${SCRIPT_API_FILE}" SOURCE_LINES)
set(NUM_LINE 0)
set(CLS_LEVEL 0)
set(BRACE_LEVEL 0)
macro(doxygen_check)
if(NOT "${DOXYGEN_SKIP}" STREQUAL "")
message(FATAL_ERROR "${SCRIPT_API_FILE}:${NUM_LINE}: a DOXYGEN_API block was not properly closed")
@@ -110,7 +119,7 @@ foreach(LINE IN LISTS SOURCE_LINES)
continue()
endif()
if("${LINE}" MATCHES "^([ ]*)\\* @api (.*)$")
if("${LINE}" MATCHES "^([\t ]*)\\* @api (.*)$")
set(LINE ${CMAKE_MATCH_2})
# By default, classes are not selected
if(NOT CLS_LEVEL)
@@ -148,22 +157,28 @@ foreach(LINE IN LISTS SOURCE_LINES)
continue()
endif()
# Count braces to skip function bodies
string(REGEX REPLACE "[^{]" "" OPENING_BRACES "${LINE}")
string(LENGTH "${OPENING_BRACES}" OPENING_BRACES)
string(REGEX REPLACE "[^}]" "" CLOSING_BRACES "${LINE}")
string(LENGTH "${CLOSING_BRACES}" CLOSING_BRACES)
math(EXPR BRACE_LEVEL "${BRACE_LEVEL} + ${OPENING_BRACES} - ${CLOSING_BRACES}")
# Ignore forward declarations of classes
if("${LINE}" MATCHES "^( *)class(.*);")
if("${LINE}" MATCHES "^(\t*)class(.*);")
continue()
endif()
# We only want to have public functions exported for now
if("${LINE}" MATCHES "^( *)class (.*) (: public|: protected|: private|:) ([^ ]*)")
if("${LINE}" MATCHES "^(\t*)class (.*) (: public|: protected|: private|:) ([^ ]*)")
if(NOT CLS_LEVEL)
if(NOT DEFINED API_SELECTED)
message(WARNING "Class '${CMAKE_MATCH_2}' has no @api. It won't be published to any API.")
message(WARNING "${SCRIPT_API_FILE}:${NUM_LINE}: Class '${CMAKE_MATCH_2}' has no @api. It won't be published to any API.")
set(API_SELECTED FALSE)
endif()
unset(IS_PUBLIC)
unset(CLS_PARAM_0)
set(CLS_PARAM_1 1)
set(CLS_PARAM_2 "x")
unset(CLS_PARAMS)
set(CLS_TYPES "x")
set(CLS_IN_API ${API_SELECTED})
unset(API_SELECTED)
set(CLS "${CMAKE_MATCH_2}")
@@ -181,19 +196,19 @@ foreach(LINE IN LISTS SOURCE_LINES)
math(EXPR CLS_LEVEL "${CLS_LEVEL} + 1")
continue()
endif()
if("${LINE}" MATCHES "^( *)public")
if("${LINE}" MATCHES "^(\t*)public")
if(CLS_LEVEL EQUAL 1)
set(IS_PUBLIC TRUE)
endif()
continue()
endif()
if("${LINE}" MATCHES "^( *)protected")
if("${LINE}" MATCHES "^(\t*)protected")
if(CLS_LEVEL EQUAL 1)
unset(IS_PUBLIC)
endif()
continue()
endif()
if("${LINE}" MATCHES "^( *)private")
if("${LINE}" MATCHES "^(\t*)private")
if(CLS_LEVEL EQUAL 1)
unset(IS_PUBLIC)
endif()
@@ -221,7 +236,7 @@ foreach(LINE IN LISTS SOURCE_LINES)
endif()
# We need to make specialized conversions for structs
if("${LINE}" MATCHES "^( *)struct ([^ ]*)")
if("${LINE}" MATCHES "^(\t*)struct ([^ ]*)")
math(EXPR CLS_LEVEL "${CLS_LEVEL} + 1")
# Check if we want to publish this struct
@@ -243,7 +258,7 @@ foreach(LINE IN LISTS SOURCE_LINES)
endif()
# We need to make specialized conversions for enums
if("${LINE}" MATCHES "^( *)enum ([^ ]*)")
if("${LINE}" MATCHES "^(\t*)enum ([^ ]*)")
math(EXPR CLS_LEVEL "${CLS_LEVEL} + 1")
# Check if we want to publish this enum
@@ -266,7 +281,7 @@ foreach(LINE IN LISTS SOURCE_LINES)
endif()
# Maybe the end of the class, if so we can start with the Squirrel export pretty soon
if("${LINE}" MATCHES "};")
if(BRACE_LEVEL LESS CLS_LEVEL)
math(EXPR CLS_LEVEL "${CLS_LEVEL} - 1")
if(CLS_LEVEL)
unset(IN_ENUM)
@@ -280,7 +295,7 @@ foreach(LINE IN LISTS SOURCE_LINES)
endif()
# Empty/white lines. When we may do the Squirrel export, do that export.
if("${LINE}" MATCHES "^([ ]*)$")
if("${LINE}" MATCHES "^([ \t]*)$")
if(NOT START_SQUIRREL_DEFINE_ON_NEXT_LINE)
continue()
endif()
@@ -304,33 +319,17 @@ foreach(LINE IN LISTS SOURCE_LINES)
string(APPEND SQUIRREL_EXPORT "\n")
if("${APIUC}" STREQUAL "Template")
# First check whether we have enums to print
if(DEFINED ENUMS)
if(NOT NAMESPACE_OPENED)
string(APPEND SQUIRREL_EXPORT "\nnamespace SQConvert {")
set(NAMESPACE_OPENED TRUE)
endif()
endif()
# Then check whether we have structs/classes to print
if(DEFINED STRUCTS)
if(NOT NAMESPACE_OPENED)
string(APPEND SQUIRREL_EXPORT "\nnamespace SQConvert {")
set(NAMESPACE_OPENED TRUE)
endif()
string(APPEND SQUIRREL_EXPORT "\n /* Allow inner classes/structs to be used as Squirrel parameters */")
open_namespace()
string(APPEND SQUIRREL_EXPORT "\n\t/* Allow inner classes/structs to be used as Squirrel parameters */")
foreach(STRUCT IN LISTS STRUCTS)
dump_class_templates(${STRUCT})
endforeach()
endif()
if(NOT NAMESPACE_OPENED)
string(APPEND SQUIRREL_EXPORT "\nnamespace SQConvert {")
set(NAMESPACE_OPENED TRUE)
else()
string(APPEND SQUIRREL_EXPORT "\n")
endif()
string(APPEND SQUIRREL_EXPORT "\n /* Allow ${CLS} to be used as Squirrel parameter */")
open_namespace()
string(APPEND SQUIRREL_EXPORT "\n\t/* Allow ${CLS} to be used as Squirrel parameter */")
dump_class_templates(${CLS})
string(APPEND SQUIRREL_EXPORT "\n} // namespace SQConvert")
@@ -340,23 +339,23 @@ foreach(LINE IN LISTS SOURCE_LINES)
endif()
string(APPEND SQUIRREL_EXPORT "\n")
string(APPEND SQUIRREL_EXPORT "\ntemplate <> SQInteger PushClassName<${CLS}, ScriptType::${APIUC}>(HSQUIRRELVM vm) { sq_pushstring(vm, \"${API_CLS}\", -1); return 1; }")
string(APPEND SQUIRREL_EXPORT "\ntemplate <> SQInteger PushClassName<${CLS}, ScriptType::${APIUC}>(HSQUIRRELVM vm) { sq_pushstring(vm, \"${API_CLS}\"); return 1; }")
string(APPEND SQUIRREL_EXPORT "\n")
# Then do the registration functions of the class.
string(APPEND SQUIRREL_EXPORT "\nvoid SQ${API_CLS}_Register(Squirrel *engine)")
string(APPEND SQUIRREL_EXPORT "\nvoid SQ${API_CLS}_Register(Squirrel &engine)")
string(APPEND SQUIRREL_EXPORT "\n{")
string(APPEND SQUIRREL_EXPORT "\n DefSQClass<${CLS}, ScriptType::${APIUC}> SQ${API_CLS}(\"${API_CLS}\");")
string(APPEND SQUIRREL_EXPORT "\n\tDefSQClass<${CLS}, ScriptType::${APIUC}> SQ${API_CLS}(\"${API_CLS}\");")
if("${SUPER_CLS}" STREQUAL "Text")
string(APPEND SQUIRREL_EXPORT "\n SQ${API_CLS}.PreRegister(engine);")
string(APPEND SQUIRREL_EXPORT "\n\tSQ${API_CLS}.PreRegister(engine);")
else()
string(APPEND SQUIRREL_EXPORT "\n SQ${API_CLS}.PreRegister(engine, \"${API_SUPER_CLS}\");")
string(APPEND SQUIRREL_EXPORT "\n\tSQ${API_CLS}.PreRegister(engine, \"${API_SUPER_CLS}\");")
endif()
if(NOT "${SUPER_CLS}" MATCHES "^ScriptEvent")
if("${CLS_PARAM_2}" STREQUAL "v")
string(APPEND SQUIRREL_EXPORT "\n SQ${API_CLS}.AddSQAdvancedConstructor(engine);")
if((DEFINED CLS_PARAMS OR DEFINED METHODS) AND NOT "${SUPER_CLS}" MATCHES "^ScriptEvent" AND NOT "${CLS}" STREQUAL "ScriptEvent")
if("${CLS_TYPES}" STREQUAL "v")
string(APPEND SQUIRREL_EXPORT "\n\tSQ${API_CLS}.AddSQAdvancedConstructor(engine);")
else()
string(APPEND SQUIRREL_EXPORT "\n SQ${API_CLS}.AddConstructor<void (${CLS}::*)(${CLS_PARAM_0}), ${CLS_PARAM_1}>(engine, \"${CLS_PARAM_2}\");")
string(APPEND SQUIRREL_EXPORT "\n\tSQ${API_CLS}.AddConstructor<void (${CLS}::*)(${CLS_PARAMS})>(engine, \"${CLS_TYPES}\");")
endif()
endif()
string(APPEND SQUIRREL_EXPORT "\n")
@@ -376,7 +375,7 @@ foreach(LINE IN LISTS SOURCE_LINES)
foreach(i RANGE ${LEN})
string(APPEND SPACES " ")
endforeach()
string(APPEND SQUIRREL_EXPORT "\n SQ${API_CLS}.DefSQConst(engine, ${CLS}::${ENUM_VALUE},${SPACES}\"${ENUM_VALUE}\");")
string(APPEND SQUIRREL_EXPORT "\n\tSQ${API_CLS}.DefSQConst(engine, ${CLS}::${ENUM_VALUE},${SPACES}\"${ENUM_VALUE}\");")
endforeach()
if(MLEN)
string(APPEND SQUIRREL_EXPORT "\n")
@@ -397,7 +396,7 @@ foreach(LINE IN LISTS SOURCE_LINES)
foreach(i RANGE ${LEN})
string(APPEND SPACES " ")
endforeach()
string(APPEND SQUIRREL_EXPORT "\n SQ${API_CLS}.DefSQConst(engine, ${CLS}::${CONST_VALUE},${SPACES}\"${CONST_VALUE}\");")
string(APPEND SQUIRREL_EXPORT "\n\tSQ${API_CLS}.DefSQConst(engine, ${CLS}::${CONST_VALUE},${SPACES}\"${CONST_VALUE}\");")
endforeach()
if(MLEN)
string(APPEND SQUIRREL_EXPORT "\n")
@@ -423,7 +422,7 @@ foreach(LINE IN LISTS SOURCE_LINES)
foreach(i RANGE ${LEN})
string(APPEND SPACES " ")
endforeach()
string(APPEND SQUIRREL_EXPORT "\n ScriptError::RegisterErrorMap(${ENUM_STRING},${SPACES}${CLS}::${ENUM_ERROR});")
string(APPEND SQUIRREL_EXPORT "\n\tScriptError::RegisterErrorMap(${ENUM_STRING},${SPACES}${CLS}::${ENUM_ERROR});")
endforeach()
if(MLEN)
string(APPEND SQUIRREL_EXPORT "\n")
@@ -444,7 +443,7 @@ foreach(LINE IN LISTS SOURCE_LINES)
foreach(i RANGE ${LEN})
string(APPEND SPACES " ")
endforeach()
string(APPEND SQUIRREL_EXPORT "\n ScriptError::RegisterErrorMapString(${CLS}::${ENUM_ERROR_TO_STRING},${SPACES}\"${ENUM_ERROR_TO_STRING}\");")
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")
@@ -463,8 +462,7 @@ foreach(LINE IN LISTS SOURCE_LINES)
foreach(STATIC_METHOD IN LISTS STATIC_METHODS)
string(REPLACE ":" ";" STATIC_METHOD "${STATIC_METHOD}")
list(GET STATIC_METHOD 0 FUNCNAME)
list(GET STATIC_METHOD 1 ARGC)
list(GET STATIC_METHOD 2 TYPES)
list(GET STATIC_METHOD 1 TYPES)
string(LENGTH "${FUNCNAME}" LEN)
math(EXPR LEN "${MLEN} - ${LEN}")
if("${TYPES}" STREQUAL "v")
@@ -479,9 +477,9 @@ foreach(LINE IN LISTS SOURCE_LINES)
string(APPEND SPACES " ")
endforeach()
if("${TYPES}" STREQUAL "v")
string(APPEND SQUIRREL_EXPORT "\n SQ${API_CLS}.DefSQAdvancedStaticMethod(engine, &${CLS}::${FUNCNAME},${SPACES}\"${FUNCNAME}\");")
string(APPEND SQUIRREL_EXPORT "\n\tSQ${API_CLS}.DefSQAdvancedStaticMethod(engine, &${CLS}::${FUNCNAME},${SPACES}\"${FUNCNAME}\");")
else()
string(APPEND SQUIRREL_EXPORT "\n SQ${API_CLS}.DefSQStaticMethod(engine, &${CLS}::${FUNCNAME},${SPACES}\"${FUNCNAME}\",${SPACES}${ARGC}, \"${TYPES}\");")
string(APPEND SQUIRREL_EXPORT "\n\tSQ${API_CLS}.DefSQStaticMethod(engine, &${CLS}::${FUNCNAME},${SPACES}\"${FUNCNAME}\",${SPACES}\"${TYPES}\");")
endif()
endforeach()
if(MLEN)
@@ -501,8 +499,7 @@ foreach(LINE IN LISTS SOURCE_LINES)
foreach(METHOD IN LISTS METHODS)
string(REPLACE ":" ";" METHOD "${METHOD}")
list(GET METHOD 0 FUNCNAME)
list(GET METHOD 1 ARGC)
list(GET METHOD 2 TYPES)
list(GET METHOD 1 TYPES)
string(LENGTH "${FUNCNAME}" LEN)
math(EXPR LEN "${MLEN} - ${LEN}")
if("${TYPES}" STREQUAL "v")
@@ -517,16 +514,16 @@ foreach(LINE IN LISTS SOURCE_LINES)
string(APPEND SPACES " ")
endforeach()
if("${TYPES}" STREQUAL "v")
string(APPEND SQUIRREL_EXPORT "\n SQ${API_CLS}.DefSQAdvancedMethod(engine, &${CLS}::${FUNCNAME},${SPACES}\"${FUNCNAME}\");")
string(APPEND SQUIRREL_EXPORT "\n\tSQ${API_CLS}.DefSQAdvancedMethod(engine, &${CLS}::${FUNCNAME},${SPACES}\"${FUNCNAME}\");")
else()
string(APPEND SQUIRREL_EXPORT "\n SQ${API_CLS}.DefSQMethod(engine, &${CLS}::${FUNCNAME},${SPACES}\"${FUNCNAME}\",${SPACES}${ARGC}, \"${TYPES}\");")
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 SQ${API_CLS}.PostRegister(engine);")
string(APPEND SQUIRREL_EXPORT "\n\tSQ${API_CLS}.PostRegister(engine);")
string(APPEND SQUIRREL_EXPORT "\n}")
reset_reader()
@@ -539,9 +536,13 @@ foreach(LINE IN LISTS SOURCE_LINES)
continue()
endif()
if(NOT BRACE_LEVEL EQUAL CLS_LEVEL)
continue()
endif()
# Add enums
if(IN_ENUM)
string(REGEX MATCH "([^, ]+)" ENUM_VALUE "${LINE}")
string(REGEX MATCH "([^,\t ]+)" ENUM_VALUE "${LINE}")
list(APPEND ENUM_VALUES "${ENUM_VALUE}")
# Check if this a special error enum
@@ -549,12 +550,12 @@ foreach(LINE IN LISTS SOURCE_LINES)
if("${ENUM}" MATCHES ".*::ErrorMessages")
# syntax:
# enum ErrorMessages {
# ERR_SOME_ERROR, // [STR_ITEM1, STR_ITEM2, ...]
#\tERR_SOME_ERROR,\t// [STR_ITEM1, STR_ITEM2, ...]
# }
# Set the mappings
if("${LINE}" MATCHES "\\[(.*)\\]")
string(REGEX REPLACE "[ ]" "" MAPPINGS "${CMAKE_MATCH_1}")
string(REGEX REPLACE "[ \t]" "" MAPPINGS "${CMAKE_MATCH_1}")
string(REPLACE "," ";" MAPPINGS "${MAPPINGS}")
foreach(MAPPING IN LISTS MAPPINGS)
@@ -568,11 +569,11 @@ foreach(LINE IN LISTS SOURCE_LINES)
endif()
# Add a const (non-enum) value
if("${LINE}" MATCHES "^[ ]*static const [^ ]+ ([^ ]+) = -?\\(?[^ ]*\\)?[^ ]+;")
if("${LINE}" MATCHES "^[ \t]*static const [^ ]+ ([^ ]+) = -?\\(?[^ ]*\\)?[^ ]+;")
list(APPEND CONST_VALUES "${CMAKE_MATCH_1}")
continue()
endif()
if("${LINE}" MATCHES "^[ ]*static constexpr [^ ]+ ([^ ]+) = -?\\(?[^ ]*\\)?[^ ]+;")
if("${LINE}" MATCHES "^[ \t]*static constexpr [^ ]+ ([^ ]+) = -?\\(?[^ ]*\\)?[^ ]+;")
list(APPEND CONST_VALUES "${CMAKE_MATCH_1}")
continue()
endif()
@@ -584,41 +585,43 @@ foreach(LINE IN LISTS SOURCE_LINES)
endif()
if("${LINE}" MATCHES "~")
if(DEFINED API_SELECTED)
message(WARNING "Destructor for '${CLS}' has @api. Tag ignored.")
message(WARNING "${SCRIPT_API_FILE}:${NUM_LINE}: Destructor for '${CLS}' has @api. Tag ignored.")
unset(API_SELECTED)
endif()
continue()
endif()
unset(IS_STATIC)
if("${LINE}" MATCHES "static")
if("${LINE}" MATCHES "static ")
set(IS_STATIC TRUE)
endif()
string(REGEX REPLACE "(virtual|static|const)[ ]+" "" LINE "${LINE}")
string(REGEX REPLACE "(virtual|static|const)[ \t]+" "" LINE "${LINE}")
string(REGEX REPLACE "{.*" "" LINE "${LINE}")
set(PARAM_S "${LINE}")
string(REGEX REPLACE "\\*" "" LINE "${LINE}")
string(REGEX REPLACE "\\(.*" "" LINE "${LINE}")
string(REGEX REPLACE ".*\\(" "" PARAM_S "${PARAM_S}")
# Parameters start at first "(". Further "(" will appear in ctor lists.
string(REGEX MATCH "\\(.*" PARAM_S "${PARAM_S}")
string(REGEX REPLACE "\\).*" "" PARAM_S "${PARAM_S}")
string(REGEX REPLACE "^\\(" "" PARAM_S "${PARAM_S}")
string(REGEX MATCH "([^ ]+)( ([^ ]+))?" RESULT "${LINE}")
string(REGEX MATCH "([^ \t]+)( ([^ ]+))?" RESULT "${LINE}")
set(FUNCTYPE "${CMAKE_MATCH_1}")
set(FUNCNAME "${CMAKE_MATCH_3}")
if("${FUNCTYPE}" STREQUAL "${CLS}" AND NOT FUNCNAME)
if(DEFINED API_SELECTED)
message(WARNING "Constructor for '${CLS}' has @api. Tag ignored.")
message(WARNING "${SCRIPT_API_FILE}:${NUM_LINE}: Constructor for '${CLS}' has @api. Tag ignored.")
unset(API_SELECTED)
endif()
set(CLS_PARAM_0 "${PARAM_S}")
set(CLS_PARAMS "${PARAM_S}")
if(NOT PARAM_S)
continue()
endif()
elseif(NOT FUNCNAME)
continue()
endif()
endif()
string(REPLACE "," ";" PARAMS "${PARAM_S}")
if(IS_STATIC)
@@ -627,9 +630,7 @@ foreach(LINE IN LISTS SOURCE_LINES)
set(TYPES "x")
endif()
set(LEN 1)
foreach(PARAM IN LISTS PARAMS)
math(EXPR LEN "${LEN} + 1")
string(STRIP "${PARAM}" PARAM)
if("${PARAM}" MATCHES "\\*|&")
if("${PARAM}" MATCHES "^char")
@@ -668,13 +669,12 @@ foreach(LINE IN LISTS SOURCE_LINES)
unset(API_SELECTED)
if("${FUNCTYPE}" STREQUAL "${CLS}" AND NOT FUNCNAME)
set(CLS_PARAM_1 ${LEN})
set(CLS_PARAM_2 "${TYPES}")
set(CLS_TYPES "${TYPES}")
elseif("${FUNCNAME}" MATCHES "^_" AND NOT "${TYPES}" STREQUAL "v")
elseif(IS_STATIC)
list(APPEND STATIC_METHODS "${FUNCNAME}:${LEN}:${TYPES}")
list(APPEND STATIC_METHODS "${FUNCNAME}:${TYPES}")
else()
list(APPEND METHODS "${FUNCNAME}:${LEN}:${TYPES}")
list(APPEND METHODS "${FUNCNAME}:${TYPES}")
endif()
continue()
endif()
+2 -2
View File
@@ -19,7 +19,7 @@ endif()
file(READ "${API_FILES}" SCRIPT_API_BINARY_FILES)
foreach(FILE IN LISTS SCRIPT_API_BINARY_FILES)
file(STRINGS "${FILE}" LINES REGEX "^void SQ${APIUC}.*_Register\\(Squirrel \\*engine\\)$")
file(STRINGS "${FILE}" LINES REGEX "^void SQ${APIUC}.*_Register\\(Squirrel &engine\\)$")
if(LINES)
string(REGEX REPLACE ".*api/${APILC}/(.*)" "#include \"\\1\"" FILE "${FILE}")
list(APPEND SQUIRREL_INCLUDES "${FILE}")
@@ -28,7 +28,7 @@ foreach(FILE IN LISTS SCRIPT_API_BINARY_FILES)
continue()
endif()
string(REGEX REPLACE "^.*void " " " LINE "${LINE}")
string(REGEX REPLACE "Squirrel \\*" "" LINE "${LINE}")
string(REGEX REPLACE "Squirrel &" "" LINE "${LINE}")
list(APPEND SQUIRREL_REGISTER "${LINE}")
endforeach()
endif()
+1 -1
View File
@@ -246,7 +246,7 @@ the array so you can quickly see what is used and what is not.
<td class="bits" rowspan=4><span class="free">OOOO OOOO OOOO OOOO</span></td>
<td class="bits" rowspan=5><span class="free">OOOO OOO</span><span class="used" title="Non-flooding state">X</span></td>
<td class="bits"><span class="free">OOOO OOOO</span></td>
<td class="bits"><span class="used" title="Water tile type: coast, clear, lock, depot">0000</span> <span class="free">OOO0</span></td>
<td class="bits"><span class="used" title="Water tile type: coast, clear, lock, depot">0000</span> <span class="free">OOOO</span></td>
<td class="bits" rowspan=5><span class="free">OOOO OOOO</span></td>
<td class="bits" rowspan=5><span class="free">OOOO OOOO</span></td>
<td class="bits" rowspan=5><span class="free">OOOO OOOO OOOO OOOO</span></td>
+7 -2
View File
@@ -16,8 +16,11 @@
; - `openttd -I <name>` starts OpenTTD with the given set (case sensitive)
; - adding `graphicsset = <name>` to the misc section of openttd.cfg makes
; OpenTTD start with that graphics set by default
; - there is a command line tool for all platforms called md5sum that can
; create the MD5 checksum you need.
; - `grfid -m` can give the GRF file MD5 checksums that you need
; - The `--md5` output option for `nmlc` can also give the MD5 if you are
; encoding from an nml source
; - Simple file MD5 checksums, eg. using `md5sum` are not correct for grf
; container versions other than 1
; - all files specified in this file are search relatively to the path where
; this file is found, i.e. if the graphics files are in a subdir you have
; to add that subdir to the names in this file to! It will NOT search for
@@ -44,6 +47,8 @@ description.en_US = howdie
palette = DOS
; preferred blitter, optional; either 8bpp (default) or 32bpp.
blitter = 8bpp
; url, optional
url = https://github.com/my/baseset
; The files section lists the files that replace sprites.
; The file names are case sensitive.
+3 -3
View File
@@ -2,8 +2,8 @@
## Table of contents
- 1.0) About
- 2.0) Known bugs
- 1.0) [About](#10-about)
- 2.0) [Known bugs](#20-known-bugs)
## 1.0) About
@@ -12,7 +12,7 @@ that are the same as these. If you do, do not act surprised, because
we WILL flame you!
The current list of known bugs that we intend to fix can be found in our
bug tracking system at https://github.com/OpenTTD/OpenTTD/issues
bug tracking system at [https://github.com/OpenTTD/OpenTTD/issues](https://github.com/OpenTTD/OpenTTD/issues)
Also check the closed bugs when searching for your bug in this system as we
might have fixed the bug in the mean time.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
019dba4830a64ee4345d3d647633e1da
eb8390a0569e66ec417c64ad254f9d05
+12 -2
View File
@@ -671,9 +671,9 @@
// U+2026: Horizontal Ellipsis
-1 * 18 12 04 00 01 26 20 01 01 26 20 02 01 26 20 03 01 26 20
-1 sprites/chars.png 8bpp 560 370 11 12 0 -1 normal
-1 sprites/chars.png 8bpp 560 370 9 12 0 -1 normal
-1 sprites/chars.png 8bpp 560 390 5 7 0 0 normal
-1 sprites/chars.png 8bpp 560 400 15 21 0 -2 normal
-1 sprites/chars.png 8bpp 560 400 14 21 0 -2 normal
-1 sprites/mono.png 8bpp 265 270 7 13 0 0 normal
// U+2039: Single Left-Pointing Angle Quotation Mark
@@ -840,3 +840,13 @@
-1 sprites/chars.png 8bpp 630 400 6 21 0 -2 normal
-1 sprites/mono.png 8bpp 325 270 7 13 0 0 normal
-1 sprites/mono.png 8bpp 340 270 7 13 0 0 normal
// U+E29D: Small left arrow
-1 * 6 12 01 01 01 9D E2
-1 sprites/chars.png 8bpp 10 430 5 5 0 1 normal
// U+E29B: Town
// U+E29C: City
-1 * 6 12 01 00 02 9B E2
-1 sprites/chars.png 8bpp 20 430 10 10 0 0 normal
-1 sprites/chars.png 8bpp 40 430 10 10 0 0 normal
Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

+2 -1
View File
@@ -4,7 +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 <http://www.gnu.org/licenses/>.
//
-1 * 0 0C "OpenTTD GUI graphics"
-1 * 3 05 15 \b 191 // OPENTTD_SPRITE_COUNT
-1 * 3 05 15 \b 192 // OPENTTD_SPRITE_COUNT
-1 sprites/openttdgui.png 8bpp 66 8 64 31 -31 7 normal
-1 sprites/openttdgui.png 8bpp 146 8 64 31 -31 7 normal
-1 sprites/openttdgui.png 8bpp 226 8 64 31 -31 7 normal
@@ -196,3 +196,4 @@
-1 sprites/openttdgui.png 8bpp 567 440 12 10 0 0 normal
-1 sprites/openttdgui.png 8bpp 581 440 10 10 0 0 normal
-1 sprites/openttdgui.png 8bpp 593 440 10 10 0 0 normal
-1 sprites/openttdgui.png 8bpp 605 440 8 10 0 0 normal
Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 76 KiB

+2 -2
View File
@@ -24,7 +24,7 @@ if (!$Env:AZURE_CODESIGN_ENDPOINT -or !$Env:AZURE_CODESIGN_ACCOUNT_NAME -or !$En
exit
}
Install-Module -Name AzureCodeSigning -Scope CurrentUser -RequiredVersion 0.3.0 -Force -Repository PSGallery
Install-Module -Name TrustedSigning -Scope CurrentUser -RequiredVersion 0.5.3 -Force -Repository PSGallery
$params = @{}
@@ -37,4 +37,4 @@ $params["FileDigest"] = "SHA256"
$params["TimestampRfc3161"] = "http://timestamp.acs.microsoft.com"
$params["TimestampDigest"] = "SHA256"
Invoke-AzureCodeSigning @params
Invoke-TrustedSigning @params
+98 -3
View File
@@ -17,6 +17,10 @@ function Regression::TestInit()
print(" IsValid(vehicle.plane_speed): " + AIGameSettings.IsValid("vehicle.plane_speed"));
print(" vehicle.plane_speed: " + AIGameSettings.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));
@@ -824,6 +828,13 @@ function Regression::List()
print(" []:");
print(" 4000 => " + list[4000]);
print(" clone:");
local list3 = clone list;
print(" Clone ListDump:");
foreach (idx, val in list3) {
print(" " + idx + " => " + val);
}
list.Clear();
print(" IsEmpty(): " + list.IsEmpty());
@@ -856,6 +867,12 @@ function Regression::List()
it = list.Next();
print(" " + it + " => " + list.GetValue(it));
}
print(" Clone ListDump:");
foreach (idx, val in list3) {
print(" " + idx + " => " + val);
}
}
function Regression::Map()
@@ -1017,6 +1034,28 @@ function Regression::Order()
foreach (idx, val in list) {
print(" " + idx + " => " + val);
}
list = AIVehicleList_Station(3, AIVehicle.VT_ROAD);
print(" Count(): " + list.Count());
list.Valuate(AIVehicle.GetLocation);
print(" Location ListDump:");
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
print(" " + i + " => " + list.GetValue(i));
}
print(" foreach():");
foreach (idx, val in list) {
print(" " + idx + " => " + val);
}
list = AIVehicleList_Station(3, AIVehicle.VT_RAIL);
print(" Count(): " + list.Count());
list.Valuate(AIVehicle.GetLocation);
print(" Location ListDump:");
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
print(" " + i + " => " + list.GetValue(i));
}
print(" foreach():");
foreach (idx, val in list) {
print(" " + idx + " => " + val);
}
}
function Regression::RailTypeList()
@@ -1675,13 +1714,22 @@ function Regression::TownList()
}
print(" HasStatue(): " + AITown.HasStatue(list.Begin()));
print(" GetRoadReworkDuration(): " + AITown.GetRoadReworkDuration(list.Begin()));
print(" GetExclusiveRightsCompany(): " + AITown.GetExclusiveRightsCompany(list.Begin()));
print(" GetExclusiveRightsDuration(): " + AITown.GetExclusiveRightsDuration(list.Begin()));
print(" IsActionAvailable(BUILD_STATUE): " + AITown.IsActionAvailable(list.Begin(), AITown.TOWN_ACTION_BUILD_STATUE));
print(" PerformTownAction(BUILD_STATUE): " + AITown.PerformTownAction(list.Begin(), AITown.TOWN_ACTION_BUILD_STATUE));
print(" IsActionAvailable(BUILD_STATUE): " + AITown.IsActionAvailable(list.Begin(), AITown.TOWN_ACTION_BUILD_STATUE));
print(" HasStatue(): " + AITown.HasStatue(list.Begin()));
print(" GetRoadReworkDuration(): " + AITown.GetRoadReworkDuration(list.Begin()));
print(" IsActionAvailable(ROAD_REBUILD): " + AITown.IsActionAvailable(list.Begin(), AITown.TOWN_ACTION_ROAD_REBUILD));
print(" PerformTownAction(ROAD_REBUILD): " + AITown.PerformTownAction(list.Begin(), AITown.TOWN_ACTION_ROAD_REBUILD));
print(" IsActionAvailable(ROAD_REBUILD): " + AITown.IsActionAvailable(list.Begin(), AITown.TOWN_ACTION_ROAD_REBUILD));
print(" GetRoadReworkDuration(): " + AITown.GetRoadReworkDuration(list.Begin()));
print(" GetExclusiveRightsCompany(): " + AITown.GetExclusiveRightsCompany(list.Begin()));
print(" GetExclusiveRightsDuration(): " + AITown.GetExclusiveRightsDuration(list.Begin()));
print(" IsActionAvailable(BUY_RIGHTS): " + AITown.IsActionAvailable(list.Begin(), AITown.TOWN_ACTION_BUY_RIGHTS));
print(" PerformTownAction(BUY_RIGHTS): " + AITown.PerformTownAction(list.Begin(), AITown.TOWN_ACTION_BUY_RIGHTS));
print(" IsActionAvailable(BUY_RIGHTS): " + AITown.IsActionAvailable(list.Begin(), AITown.TOWN_ACTION_BUY_RIGHTS));
print(" GetExclusiveRightsCompany(): " + AITown.GetExclusiveRightsCompany(list.Begin()));
print(" GetExclusiveRightsDuration(): " + AITown.GetExclusiveRightsDuration(list.Begin()));
}
function Regression::Tunnel()
@@ -1975,6 +2023,33 @@ function Regression::Math()
print(" 13725 > -2147483648: " + ( 13725 > -2147483648));
}
function Regression::PriorityQueue()
{
print("");
print("--PriorityQueue--");
local queue = AIPriorityQueue();
print(" IsEmpty(): " + queue.IsEmpty());
print(" Count(): " + queue.Count());
print(" --Insert--")
for (local i = 0; i < 10; i++) {
print(" Insert(" + i + ", " + i + "): " + queue.Insert(i, i));
}
print(" Exists(5): " + queue.Exists(5));
print(" Insert(5, 5): "+ queue.Insert(5, 5));
print(" IsEmpty(): " + queue.IsEmpty());
print(" Count(): " + queue.Count());
local item = queue.Peek();
print(" Peek(): " + item);
print(" Count(): " + queue.Count());
local item2 = queue.Pop();
print(" Pop(): " + item2);
print(" Count(): " + queue.Count());
print(" " + item + " == " + item2 + " : " + (item == item2));
print(" Clear(): " + queue.Clear());
print(" IsEmpty(): " + queue.IsEmpty());
print(" Count(): " + queue.Count());
}
function Regression::Start()
{
this.TestInit();
@@ -2049,6 +2124,20 @@ function Regression::Start()
print(" PresidentName: " + c.GetNewName());
} break;
case AIEvent.ET_EXCLUSIVE_TRANSPORT_RIGHTS: {
local c = AIEventExclusiveTransportRights.Convert(e);
print(" EventName: ExclusiveTransportRights");
print(" CompanyID: " + c.GetCompanyID());
print(" TownID: " + c.GetTownID());
} break;
case AIEvent.ET_ROAD_RECONSTRUCTION: {
local c = AIEventRoadReconstruction.Convert(e);
print(" EventName: RoadReconstruction");
print(" CompanyID: " + c.GetCompanyID());
print(" TownID: " + c.GetTownID());
} break;
default:
print(" Unknown Event");
break;
@@ -2057,12 +2146,18 @@ function Regression::Start()
print(" IsEventWaiting: false");
this.Math();
this.PriorityQueue();
/* Check Valuate() is actually limited, MUST BE THE LAST TEST. */
print("--Valuate() with excessive CPU usage--")
local list = AIList();
list.AddItem(0, 0);
local Infinite = function(id) { while(true); }
try {
list = AIIndustryList(Infinite);
} catch (e) {
print("constructor failed with: " + e);
}
list.Valuate(Infinite);
}
+7
View File
@@ -1,2 +1,9 @@
print(" Required this file");
const test_constant = 1;
enum TestEnum {
value0,
value1,
value2
};
+77 -16
View File
@@ -8,6 +8,10 @@
IsValid(vehicle.plane_speed): true
vehicle.plane_speed: 2
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
@@ -81,7 +85,7 @@
20
30
40
Ops: 8673
Ops: 8649
--Std--
abs(-21): 21
@@ -571,6 +575,13 @@
4006 => 12
[]:
4000 => 50
clone:
Clone ListDump:
1005 => 1005
4000 => 50
4001 => 8002
4002 => 8004
4006 => 12
IsEmpty(): true
0 => 5 (true)
ERROR: Next() is invalid as Begin() is never called
@@ -580,6 +591,12 @@ ERROR: IsEnd() is invalid as Begin() is never called
2 => 6 (true)
3 => 6 (true)
9 => 0 (false)
Clone ListDump:
1005 => 1005
4000 => 50
4001 => 8002
4002 => 8004
4006 => 12
--Company--
SetName(): true
@@ -9423,13 +9440,22 @@ ERROR: IsEnd() is invalid as Begin() is never called
23 => 652
25 => 563
HasStatue(): false
GetRoadReworkDuration(): 0
GetExclusiveRightsCompany(): -1
GetExclusiveRightsDuration(): 0
IsActionAvailable(BUILD_STATUE): true
PerformTownAction(BUILD_STATUE): true
IsActionAvailable(BUILD_STATUE): false
HasStatue(): true
GetRoadReworkDuration(): 0
IsActionAvailable(ROAD_REBUILD): true
PerformTownAction(ROAD_REBUILD): true
IsActionAvailable(ROAD_REBUILD): true
GetRoadReworkDuration(): 6
GetExclusiveRightsCompany(): -1
GetExclusiveRightsDuration(): 0
IsActionAvailable(BUY_RIGHTS): true
PerformTownAction(BUY_RIGHTS): true
IsActionAvailable(BUY_RIGHTS): false
GetExclusiveRightsCompany(): 1
GetExclusiveRightsDuration(): 12
--Tunnel--
IsTunnelTile(): false
@@ -9694,6 +9720,14 @@ ERROR: IsEnd() is invalid as Begin() is never called
GetStopLocation(): 1
--VehicleList_Station--
Count(): 1
Location ListDump:
20 => 23596
foreach():
20 => 23596
Count(): 0
Location ListDump:
foreach():
Count(): 1
Location ListDump:
20 => 23596
@@ -9726,6 +9760,16 @@ ERROR: IsEnd() is invalid as Begin() is never called
EventName: CompanyRenamed
CompanyID: 1
CompanyName: Little Frutford Transport
GetNextEvent: instance
GetEventType: 28
EventName: RoadReconstruction
CompanyID: 1
TownID: 12
GetNextEvent: instance
GetEventType: 27
EventName: ExclusiveTransportRights
CompanyID: 1
TownID: 12
IsEventWaiting: false
--Math--
@@ -9760,21 +9804,38 @@ ERROR: IsEnd() is invalid as Begin() is never called
-1 > 2147483647: false
-2147483648 > 2147483647: false
13725 > -2147483648: true
--PriorityQueue--
IsEmpty(): true
Count(): 0
--Insert--
Insert(0, 0): true
Insert(1, 1): true
Insert(2, 2): true
Insert(3, 3): true
Insert(4, 4): true
Insert(5, 5): true
Insert(6, 6): true
Insert(7, 7): true
Insert(8, 8): true
Insert(9, 9): true
Exists(5): true
Insert(5, 5): true
IsEmpty(): false
Count(): 11
Peek(): 0
Count(): 11
Pop(): 0
Count(): 10
0 == 0 : true
Clear(): (null : 0x00000000)
IsEmpty(): true
Count(): 0
--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
*FUNCTION [unknown()] regression/main.nut line [2065]
*FUNCTION [Valuate()] NATIVE line [-1]
*FUNCTION [Start()] regression/main.nut line [2066]
[id] 0
[this] TABLE
[Infinite] CLOSURE
[list] INSTANCE
[this] INSTANCE
Your script made an error: excessive CPU usage in valuator function
*FUNCTION [Start()] regression/main.nut line [2066]
*FUNCTION [Start()] regression/main.nut line [2161]
[Infinite] CLOSURE
[list] INSTANCE
+1
View File
@@ -19,6 +19,7 @@
#include <unicode/utypes.h>
#include <unicode/uobject.h>
#include <unicode/uscript.h>
#include <array>
U_NAMESPACE_BEGIN
+2 -2
View File
@@ -281,7 +281,7 @@ void Md5::Append(const void *data, const size_t nbytes)
if (offset) {
size_t copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
memcpy(this->buf + offset, p, copy);
std::copy_n(p, copy, this->buf + offset);
if (offset + copy < 64) return;
@@ -294,7 +294,7 @@ void Md5::Append(const void *data, const size_t nbytes)
for (; left >= 64; p += 64, left -= 64) this->Process(p);
/* Process a final partial block. */
if (left) memcpy(this->buf, p, left);
if (left) std::copy_n(p, left, this->buf);
}
void Md5::Finish(MD5Hash &digest)
-1
View File
@@ -1,6 +1,5 @@
add_files(
sqstdaux.h
sqstdmath.h
sqstdstring.h
squirrel.h
)
-23
View File
@@ -1,23 +0,0 @@
/* see copyright notice in squirrel.h */
#ifndef _SQSTD_STRING_H_
#define _SQSTD_STRING_H_
typedef unsigned int SQRexBool;
typedef struct SQRex SQRex;
typedef struct {
const SQChar *begin;
SQInteger len;
} SQRexMatch;
SQRex *sqstd_rex_compile(const SQChar *pattern,const SQChar **error);
void sqstd_rex_free(SQRex *exp);
SQBool sqstd_rex_match(SQRex* exp,const SQChar* text);
SQBool sqstd_rex_search(SQRex* exp,const SQChar* text, const SQChar** out_begin, const SQChar** out_end);
SQBool sqstd_rex_searchrange(SQRex* exp,const SQChar* text_begin,const SQChar* text_end,const SQChar** out_begin, const SQChar** out_end);
SQInteger sqstd_rex_getsubexpcount(SQRex* exp);
SQBool sqstd_rex_getsubexp(SQRex* exp, SQInteger n, SQRexMatch *subexp);
SQRESULT sqstd_register_stringlib(HSQUIRRELVM v);
#endif /*_SQSTD_STRING_H_*/
+21 -24
View File
@@ -68,7 +68,6 @@ struct SQClass;
struct SQInstance;
struct SQDelegable;
typedef char SQChar;
#define MAX_CHAR 0xFFFF
#define SQUIRREL_VERSION "Squirrel 2.2.5 stable - With custom OpenTTD modifications"
@@ -164,17 +163,17 @@ typedef struct tagSQObject
}SQObject;
typedef struct tagSQStackInfos{
const SQChar* funcname;
const SQChar* source;
SQInteger line;
std::string_view funcname;
std::string_view source;
SQInteger line = -1;
}SQStackInfos;
typedef struct SQVM* HSQUIRRELVM;
typedef SQObject HSQOBJECT;
typedef SQInteger (*SQFUNCTION)(HSQUIRRELVM);
typedef SQInteger (*SQRELEASEHOOK)(SQUserPointer,SQInteger size);
typedef void (*SQCOMPILERERROR)(HSQUIRRELVM,const SQChar * /*desc*/,const SQChar * /*source*/,SQInteger /*line*/,SQInteger /*column*/);
typedef void (*SQPRINTFUNCTION)(HSQUIRRELVM,const std::string &);
typedef void (*SQCOMPILERERROR)(HSQUIRRELVM,std::string_view /*desc*/,std::string_view /*source*/,SQInteger /*line*/,SQInteger /*column*/);
typedef void (*SQPRINTFUNCTION)(HSQUIRRELVM,std::string_view);
typedef SQInteger (*SQWRITEFUNC)(SQUserPointer,SQUserPointer,SQInteger);
typedef SQInteger (*SQREADFUNC)(SQUserPointer,SQUserPointer,SQInteger);
@@ -182,16 +181,16 @@ typedef SQInteger (*SQREADFUNC)(SQUserPointer,SQUserPointer,SQInteger);
typedef char32_t (*SQLEXREADFUNC)(SQUserPointer);
typedef struct tagSQRegFunction{
const SQChar *name;
std::string_view name;
SQFUNCTION f;
SQInteger nparamscheck;
const SQChar *typemask;
std::optional<std::string_view> typemask;
}SQRegFunction;
typedef struct tagSQFunctionInfo {
SQUserPointer funcid;
const SQChar *name;
const SQChar *source;
std::string_view name;
std::string_view source;
}SQFunctionInfo;
@@ -213,8 +212,8 @@ SQInteger sq_getvmstate(HSQUIRRELVM v);
void sq_decreaseops(HSQUIRRELVM v, int amount);
/*compiler*/
SQRESULT sq_compile(HSQUIRRELVM v,SQLEXREADFUNC read,SQUserPointer p,const SQChar *sourcename,SQBool raiseerror);
SQRESULT sq_compilebuffer(HSQUIRRELVM v,const SQChar *s,SQInteger size,const SQChar *sourcename,SQBool raiseerror);
SQRESULT sq_compile(HSQUIRRELVM v,SQLEXREADFUNC read,SQUserPointer p,std::string_view sourcename,SQBool raiseerror);
SQRESULT sq_compilebuffer(HSQUIRRELVM v,std::string_view buffer,std::string_view sourcename,SQBool raiseerror);
void sq_enabledebuginfo(HSQUIRRELVM v, SQBool enable);
void sq_notifyallexceptions(HSQUIRRELVM v, SQBool enable);
void sq_setcompilererrorhandler(HSQUIRRELVM v,SQCOMPILERERROR f);
@@ -235,10 +234,9 @@ SQUserPointer sq_newuserdata(HSQUIRRELVM v,SQUnsignedInteger size);
void sq_newtable(HSQUIRRELVM v);
void sq_newarray(HSQUIRRELVM v,SQInteger size);
void sq_newclosure(HSQUIRRELVM v,SQFUNCTION func,SQUnsignedInteger nfreevars);
SQRESULT sq_setparamscheck(HSQUIRRELVM v,SQInteger nparamscheck,const SQChar *typemask);
SQRESULT sq_setparamscheck(HSQUIRRELVM v,SQInteger nparamscheck,std::optional<std::string_view> typemask);
SQRESULT sq_bindenv(HSQUIRRELVM v,SQInteger idx);
void sq_pushstring(HSQUIRRELVM v,const SQChar *s,SQInteger len);
inline void sq_pushstring(HSQUIRRELVM v, const std::string &str, SQInteger len = -1) { sq_pushstring(v, str.data(), len == -1 ? str.size() : len); }
void sq_pushstring(HSQUIRRELVM v, std::string_view str);
void sq_pushfloat(HSQUIRRELVM v,SQFloat f);
void sq_pushinteger(HSQUIRRELVM v,SQInteger n);
void sq_pushbool(HSQUIRRELVM v,SQBool b);
@@ -250,7 +248,7 @@ SQRESULT sq_getbase(HSQUIRRELVM v,SQInteger idx);
SQBool sq_instanceof(HSQUIRRELVM v);
void sq_tostring(HSQUIRRELVM v,SQInteger idx);
void sq_tobool(HSQUIRRELVM v, SQInteger idx, SQBool *b);
SQRESULT sq_getstring(HSQUIRRELVM v,SQInteger idx,const SQChar **c);
SQRESULT sq_getstring(HSQUIRRELVM v,SQInteger idx,std::string_view &str);
SQRESULT sq_getinteger(HSQUIRRELVM v,SQInteger idx,SQInteger *i);
SQRESULT sq_getfloat(HSQUIRRELVM v,SQInteger idx,SQFloat *f);
SQRESULT sq_getbool(HSQUIRRELVM v,SQInteger idx,SQBool *b);
@@ -260,10 +258,10 @@ SQRESULT sq_getuserdata(HSQUIRRELVM v,SQInteger idx,SQUserPointer *p,SQUserPoint
SQRESULT sq_settypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer typetag);
SQRESULT sq_gettypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer *typetag);
void sq_setreleasehook(HSQUIRRELVM v,SQInteger idx,SQRELEASEHOOK hook);
SQChar *sq_getscratchpad(HSQUIRRELVM v,SQInteger minsize);
std::span<char> sq_getscratchpad(HSQUIRRELVM v,SQInteger minsize);
SQRESULT sq_getfunctioninfo(HSQUIRRELVM v,SQInteger idx,SQFunctionInfo *fi);
SQRESULT sq_getclosureinfo(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger *nparams,SQUnsignedInteger *nfreevars);
SQRESULT sq_setnativeclosurename(HSQUIRRELVM v,SQInteger idx,const SQChar *name);
SQRESULT sq_setnativeclosurename(HSQUIRRELVM v,SQInteger idx,std::string_view name);
SQRESULT sq_setinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer p);
SQRESULT sq_getinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer *p,SQUserPointer typetag);
SQRESULT sq_setclassudsize(HSQUIRRELVM v, SQInteger idx, SQInteger udsize);
@@ -305,10 +303,9 @@ SQRESULT sq_clear(HSQUIRRELVM v,SQInteger idx);
/*calls*/
SQRESULT sq_call(HSQUIRRELVM v,SQInteger params,SQBool retval,SQBool raiseerror, int suspend = -1);
SQRESULT sq_resume(HSQUIRRELVM v,SQBool retval,SQBool raiseerror);
const SQChar *sq_getlocal(HSQUIRRELVM v,SQUnsignedInteger level,SQUnsignedInteger idx);
const SQChar *sq_getfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval);
SQRESULT sq_throwerror(HSQUIRRELVM v,const SQChar *err, SQInteger len = -1);
inline SQRESULT sq_throwerror(HSQUIRRELVM v, const std::string_view err) { return sq_throwerror(v, err.data(), err.size()); }
std::optional<std::string_view> sq_getlocal(HSQUIRRELVM v,SQUnsignedInteger level,SQUnsignedInteger idx);
std::optional<std::string_view> sq_getfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval);
SQRESULT sq_throwerror(HSQUIRRELVM v,std::string_view err);
void sq_reseterror(HSQUIRRELVM v);
void sq_getlasterror(HSQUIRRELVM v);
@@ -318,7 +315,7 @@ void sq_pushobject(HSQUIRRELVM v,HSQOBJECT obj);
void sq_addref(HSQUIRRELVM v,HSQOBJECT *po);
SQBool sq_release(HSQUIRRELVM v,HSQOBJECT *po);
void sq_resetobject(HSQOBJECT *po);
const SQChar *sq_objtostring(HSQOBJECT *o);
std::optional<std::string_view> sq_objtostring(HSQOBJECT *o);
SQBool sq_objtobool(HSQOBJECT *o);
SQInteger sq_objtointeger(HSQOBJECT *o);
SQFloat sq_objtofloat(HSQOBJECT *o);
@@ -363,7 +360,7 @@ void sq_setdebughook(HSQUIRRELVM v);
/* Limit the total number of ops that can be consumed by an operation */
struct SQOpsLimiter {
SQOpsLimiter(HSQUIRRELVM v, SQInteger ops, const char *label);
SQOpsLimiter(HSQUIRRELVM v, SQInteger ops, std::string_view label);
~SQOpsLimiter();
private:
HSQUIRRELVM _v;
+19 -22
View File
@@ -16,28 +16,22 @@ void sqstd_printcallstack(HSQUIRRELVM v)
SQInteger i;
SQBool b;
SQFloat f;
const SQChar *s;
SQInteger level=1; //1 is to skip this function that is level 0
const SQChar *name=nullptr;
SQInteger seq=0;
pf(v,"\nCALLSTACK\n");
while(SQ_SUCCEEDED(sq_stackinfos(v,level,&si)))
{
const SQChar *fn="unknown";
const SQChar *src="unknown";
if(si.funcname)fn=si.funcname;
if(si.source) {
std::string_view fn="unknown";
std::string_view src="unknown";
if(!si.funcname.empty())fn=si.funcname;
if(!si.source.empty()) {
/* We don't want to bother users with absolute paths to all AI files.
* Since the path only reaches NoAI code in a formatted string we have
* to strip it here. Let's hope nobody installs openttd in a subdirectory
* of a directory named /ai/. */
src = strstr(si.source, "\\ai\\");
if (!src) src = strstr(si.source, "/ai/");
if (src) {
src += 4;
} else {
src = si.source;
}
auto p = si.source.find("\\ai\\");
if (p == std::string_view::npos) p = si.source.find("/ai/");
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++;
@@ -47,8 +41,9 @@ void sqstd_printcallstack(HSQUIRRELVM v)
for(level=0;level<10;level++){
seq=0;
while((name = sq_getlocal(v,level,seq)))
{
std::optional<std::string_view> opt;
while ((opt = sq_getlocal(v,level,seq)).has_value()) {
std::string_view name = *opt;
seq++;
switch(sq_gettype(v,-1))
{
@@ -66,10 +61,12 @@ void sqstd_printcallstack(HSQUIRRELVM v)
case OT_USERPOINTER:
pf(v,fmt::format("[{}] USERPOINTER\n",name));
break;
case OT_STRING:
sq_getstring(v,-1,&s);
pf(v,fmt::format("[{}] \"{}\"\n",name,s));
case OT_STRING: {
std::string_view view;
sq_getstring(v,-1,view);
pf(v,fmt::format("[{}] \"{}\"\n",name,view));
break;
}
case OT_TABLE:
pf(v,fmt::format("[{}] TABLE\n",name));
break;
@@ -117,10 +114,10 @@ static SQInteger _sqstd_aux_printerror(HSQUIRRELVM v)
{
SQPRINTFUNCTION pf = sq_getprintfunc(v);
if(pf) {
const SQChar *sErr = nullptr;
std::string_view error;
if(sq_gettop(v)>=1) {
if(SQ_SUCCEEDED(sq_getstring(v,2,&sErr))) {
pf(v,fmt::format("\nAN ERROR HAS OCCURRED [{}]\n",sErr));
if(SQ_SUCCEEDED(sq_getstring(v,2,error))) {
pf(v,fmt::format("\nAN ERROR HAS OCCURRED [{}]\n",error));
}
else{
pf(v,"\nAN ERROR HAS OCCURRED [unknown]\n");
@@ -131,7 +128,7 @@ static SQInteger _sqstd_aux_printerror(HSQUIRRELVM v)
return 0;
}
void _sqstd_compiler_error(HSQUIRRELVM v,const SQChar *sErr,const SQChar *sSource,SQInteger line,SQInteger column)
void _sqstd_compiler_error(HSQUIRRELVM v,std::string_view sErr,std::string_view sSource,SQInteger line,SQInteger column)
{
SQPRINTFUNCTION pf = sq_getprintfunc(v);
if(pf) {
+9 -12
View File
@@ -67,7 +67,7 @@ SINGLE_ARG_FUNC(ceil, 1)
SINGLE_ARG_FUNC(exp, 100)
#define _DECL_FUNC(name,nparams,tycheck) {#name,math_##name,nparams,tycheck}
static SQRegFunction mathlib_funcs[] = {
static const std::initializer_list<SQRegFunction> mathlib_funcs = {
_DECL_FUNC(sqrt,2,".n"),
_DECL_FUNC(sin,2,".n"),
_DECL_FUNC(cos,2,".n"),
@@ -84,11 +84,10 @@ static SQRegFunction mathlib_funcs[] = {
_DECL_FUNC(exp,2,".n"),
#ifdef EXPORT_DEFAULT_SQUIRREL_FUNCTIONS
_DECL_FUNC(srand,2,".n"),
_DECL_FUNC(rand,1,nullptr),
_DECL_FUNC(rand,1,std::nullopt),
#endif /* EXPORT_DEFAULT_SQUIRREL_FUNCTIONS */
_DECL_FUNC(fabs,2,".n"),
_DECL_FUNC(abs,2,".n"),
{nullptr,nullptr,0,nullptr},
};
#ifndef M_PI
@@ -97,21 +96,19 @@ static SQRegFunction mathlib_funcs[] = {
SQRESULT sqstd_register_mathlib(HSQUIRRELVM v)
{
SQInteger i=0;
while(mathlib_funcs[i].name!=nullptr) {
sq_pushstring(v,mathlib_funcs[i].name,-1);
sq_newclosure(v,mathlib_funcs[i].f,0);
sq_setparamscheck(v,mathlib_funcs[i].nparamscheck,mathlib_funcs[i].typemask);
sq_setnativeclosurename(v,-1,mathlib_funcs[i].name);
for(auto &func : mathlib_funcs) {
sq_pushstring(v,func.name);
sq_newclosure(v,func.f,0);
sq_setparamscheck(v,func.nparamscheck,func.typemask);
sq_setnativeclosurename(v,-1,func.name);
sq_createslot(v,-3);
i++;
}
#ifdef EXPORT_DEFAULT_SQUIRREL_FUNCTIONS
sq_pushstring(v,"RAND_MAX",-1);
sq_pushstring(v,"RAND_MAX");
sq_pushinteger(v,RAND_MAX);
sq_createslot(v,-3);
#endif /* EXPORT_DEFAULT_SQUIRREL_FUNCTIONS */
sq_pushstring(v,"PI",-1);
sq_pushstring(v,"PI");
sq_pushfloat(v,(SQFloat)M_PI);
sq_createslot(v,-3);
return SQ_OK;
-632
View File
@@ -1,632 +0,0 @@
/* see copyright notice in squirrel.h */
#include <squirrel.h>
#include <exception>
#include "sqstdstring.h"
#ifdef _UNICODE
#define scisprint iswprint
#else
#define scisprint isprint
#endif
#ifdef _DEBUG
static const SQChar *g_nnames[] =
{
"NONE","OP_GREEDY", "OP_OR",
"OP_EXPR","OP_NOCAPEXPR","OP_DOT", "OP_CLASS",
"OP_CCLASS","OP_NCLASS","OP_RANGE","OP_CHAR",
"OP_EOL","OP_BOL","OP_WB"
};
#endif
#define OP_GREEDY (MAX_CHAR+1) // * + ? {n}
#define OP_OR (MAX_CHAR+2)
#define OP_EXPR (MAX_CHAR+3) //parentesis ()
#define OP_NOCAPEXPR (MAX_CHAR+4) //parentesis (?:)
#define OP_DOT (MAX_CHAR+5)
#define OP_CLASS (MAX_CHAR+6)
#define OP_CCLASS (MAX_CHAR+7)
#define OP_NCLASS (MAX_CHAR+8) //negates class the [^
#define OP_RANGE (MAX_CHAR+9)
#define OP_CHAR (MAX_CHAR+10)
#define OP_EOL (MAX_CHAR+11)
#define OP_BOL (MAX_CHAR+12)
#define OP_WB (MAX_CHAR+13)
#define SQREX_SYMBOL_ANY_CHAR ('.')
#define SQREX_SYMBOL_GREEDY_ONE_OR_MORE ('+')
#define SQREX_SYMBOL_GREEDY_ZERO_OR_MORE ('*')
#define SQREX_SYMBOL_GREEDY_ZERO_OR_ONE ('?')
#define SQREX_SYMBOL_BRANCH ('|')
#define SQREX_SYMBOL_END_OF_STRING ('$')
#define SQREX_SYMBOL_BEGINNING_OF_STRING ('^')
#define SQREX_SYMBOL_ESCAPE_CHAR ('\\')
typedef int SQRexNodeType;
typedef struct tagSQRexNode{
SQRexNodeType type;
SQInteger left;
SQInteger right;
SQInteger next;
}SQRexNode;
struct SQRex{
const SQChar *_eol;
const SQChar *_bol;
const SQChar *_p;
SQInteger _first;
SQInteger _op;
SQRexNode *_nodes;
SQInteger _nallocated;
SQInteger _nsize;
SQInteger _nsubexpr;
SQRexMatch *_matches;
SQInteger _currsubexp;
const SQChar **_error;
};
static SQInteger sqstd_rex_list(SQRex *exp);
static SQInteger sqstd_rex_newnode(SQRex *exp, SQRexNodeType type)
{
SQRexNode n;
n.type = type;
n.next = n.right = n.left = -1;
if(type == OP_EXPR)
n.right = exp->_nsubexpr++;
if(exp->_nallocated < (exp->_nsize + 1)) {
SQInteger oldsize = exp->_nallocated;
exp->_nallocated *= 2;
exp->_nodes = (SQRexNode *)sq_realloc(exp->_nodes, oldsize * sizeof(SQRexNode) ,exp->_nallocated * sizeof(SQRexNode));
}
exp->_nodes[exp->_nsize++] = n;
SQInteger newid = exp->_nsize - 1;
return (SQInteger)newid;
}
static void sqstd_rex_error(SQRex *exp,const SQChar *error)
{
if(exp->_error) *exp->_error = error;
throw std::exception();
}
static void sqstd_rex_expect(SQRex *exp, SQChar n){
if((*exp->_p) != n)
sqstd_rex_error(exp, "expected paren");
exp->_p++;
}
static SQChar sqstd_rex_escapechar(SQRex *exp)
{
if(*exp->_p == SQREX_SYMBOL_ESCAPE_CHAR){
exp->_p++;
switch(*exp->_p) {
case 'v': exp->_p++; return '\v';
case 'n': exp->_p++; return '\n';
case 't': exp->_p++; return '\t';
case 'r': exp->_p++; return '\r';
case 'f': exp->_p++; return '\f';
default: return (*exp->_p++);
}
} else if(!scisprint(*exp->_p)) sqstd_rex_error(exp,"letter expected");
return (*exp->_p++);
}
static SQInteger sqstd_rex_charclass(SQRex *exp,SQInteger classid)
{
SQInteger n = sqstd_rex_newnode(exp,OP_CCLASS);
exp->_nodes[n].left = classid;
return n;
}
static SQInteger sqstd_rex_charnode(SQRex *exp,SQBool isclass)
{
SQChar t;
if(*exp->_p == SQREX_SYMBOL_ESCAPE_CHAR) {
exp->_p++;
switch(*exp->_p) {
case 'n': exp->_p++; return sqstd_rex_newnode(exp,'\n');
case 't': exp->_p++; return sqstd_rex_newnode(exp,'\t');
case 'r': exp->_p++; return sqstd_rex_newnode(exp,'\r');
case 'f': exp->_p++; return sqstd_rex_newnode(exp,'\f');
case 'v': exp->_p++; return sqstd_rex_newnode(exp,'\v');
case 'a': case 'A': case 'w': case 'W': case 's': case 'S':
case 'd': case 'D': case 'x': case 'X': case 'c': case 'C':
case 'p': case 'P': case 'l': case 'u':
{
t = *exp->_p; exp->_p++;
return sqstd_rex_charclass(exp,t);
}
case 'b':
case 'B':
if(!isclass) {
SQInteger node = sqstd_rex_newnode(exp,OP_WB);
exp->_nodes[node].left = *exp->_p;
exp->_p++;
return node;
} //else default
default:
t = *exp->_p; exp->_p++;
return sqstd_rex_newnode(exp,t);
}
}
else if(!scisprint(*exp->_p)) {
sqstd_rex_error(exp,"letter expected");
}
t = *exp->_p; exp->_p++;
return sqstd_rex_newnode(exp,t);
}
static SQInteger sqstd_rex_class(SQRex *exp)
{
SQInteger ret = -1;
SQInteger first = -1,chain;
if(*exp->_p == SQREX_SYMBOL_BEGINNING_OF_STRING){
ret = sqstd_rex_newnode(exp,OP_NCLASS);
exp->_p++;
}else ret = sqstd_rex_newnode(exp,OP_CLASS);
if(*exp->_p == ']') sqstd_rex_error(exp,"empty class");
chain = ret;
while(*exp->_p != ']' && exp->_p != exp->_eol) {
if(*exp->_p == '-' && first != -1){
SQInteger r;
if(*exp->_p++ == ']') sqstd_rex_error(exp,"unfinished range");
r = sqstd_rex_newnode(exp,OP_RANGE);
if(exp->_nodes[first].type>*exp->_p) sqstd_rex_error(exp,"invalid range");
if(exp->_nodes[first].type == OP_CCLASS) sqstd_rex_error(exp,"cannot use character classes in ranges");
exp->_nodes[r].left = exp->_nodes[first].type;
SQInteger t = sqstd_rex_escapechar(exp);
exp->_nodes[r].right = t;
exp->_nodes[chain].next = r;
chain = r;
first = -1;
}
else{
if(first!=-1){
SQInteger c = first;
exp->_nodes[chain].next = c;
chain = c;
first = sqstd_rex_charnode(exp,SQTrue);
}
else{
first = sqstd_rex_charnode(exp,SQTrue);
}
}
}
if(first!=-1){
SQInteger c = first;
exp->_nodes[chain].next = c;
chain = c;
first = -1;
}
/* hack? */
exp->_nodes[ret].left = exp->_nodes[ret].next;
exp->_nodes[ret].next = -1;
return ret;
}
static SQInteger sqstd_rex_parsenumber(SQRex *exp)
{
SQInteger ret = *exp->_p-'0';
SQInteger positions = 10;
exp->_p++;
while(isdigit(*exp->_p)) {
ret = ret*10+(*exp->_p++-'0');
if(positions==1000000000) sqstd_rex_error(exp,"overflow in numeric constant");
positions *= 10;
};
return ret;
}
static SQInteger sqstd_rex_element(SQRex *exp)
{
SQInteger ret = -1;
switch(*exp->_p)
{
case '(': {
SQInteger expr;
exp->_p++;
if(*exp->_p =='?') {
exp->_p++;
sqstd_rex_expect(exp,':');
expr = sqstd_rex_newnode(exp,OP_NOCAPEXPR);
}
else
expr = sqstd_rex_newnode(exp,OP_EXPR);
SQInteger newn = sqstd_rex_list(exp);
exp->_nodes[expr].left = newn;
ret = expr;
sqstd_rex_expect(exp,')');
}
break;
case '[':
exp->_p++;
ret = sqstd_rex_class(exp);
sqstd_rex_expect(exp,']');
break;
case SQREX_SYMBOL_END_OF_STRING: exp->_p++; ret = sqstd_rex_newnode(exp,OP_EOL);break;
case SQREX_SYMBOL_ANY_CHAR: exp->_p++; ret = sqstd_rex_newnode(exp,OP_DOT);break;
default:
ret = sqstd_rex_charnode(exp,SQFalse);
break;
}
SQInteger op;
SQBool isgreedy = SQFalse;
unsigned short p0 = 0, p1 = 0;
switch(*exp->_p){
case SQREX_SYMBOL_GREEDY_ZERO_OR_MORE: p0 = 0; p1 = 0xFFFF; exp->_p++; isgreedy = SQTrue; break;
case SQREX_SYMBOL_GREEDY_ONE_OR_MORE: p0 = 1; p1 = 0xFFFF; exp->_p++; isgreedy = SQTrue; break;
case SQREX_SYMBOL_GREEDY_ZERO_OR_ONE: p0 = 0; p1 = 1; exp->_p++; isgreedy = SQTrue; break;
case '{':
exp->_p++;
if(!isdigit(*exp->_p)) sqstd_rex_error(exp,"number expected");
p0 = (unsigned short)sqstd_rex_parsenumber(exp);
/*******************************/
switch(*exp->_p) {
case '}':
p1 = p0; exp->_p++;
break;
case ',':
exp->_p++;
p1 = 0xFFFF;
if(isdigit(*exp->_p)){
p1 = (unsigned short)sqstd_rex_parsenumber(exp);
}
sqstd_rex_expect(exp,'}');
break;
default:
sqstd_rex_error(exp,", or } expected");
}
/*******************************/
isgreedy = SQTrue;
break;
}
if(isgreedy) {
SQInteger nnode = sqstd_rex_newnode(exp,OP_GREEDY);
op = OP_GREEDY;
exp->_nodes[nnode].left = ret;
exp->_nodes[nnode].right = ((p0)<<16)|p1;
ret = nnode;
}
if((*exp->_p != SQREX_SYMBOL_BRANCH) && (*exp->_p != ')') && (*exp->_p != SQREX_SYMBOL_GREEDY_ZERO_OR_MORE) && (*exp->_p != SQREX_SYMBOL_GREEDY_ONE_OR_MORE) && (*exp->_p != '\0')) {
SQInteger nnode = sqstd_rex_element(exp);
exp->_nodes[ret].next = nnode;
}
return ret;
}
static SQInteger sqstd_rex_list(SQRex *exp)
{
SQInteger ret=-1,e;
if(*exp->_p == SQREX_SYMBOL_BEGINNING_OF_STRING) {
exp->_p++;
ret = sqstd_rex_newnode(exp,OP_BOL);
}
e = sqstd_rex_element(exp);
if(ret != -1) {
exp->_nodes[ret].next = e;
}
else ret = e;
if(*exp->_p == SQREX_SYMBOL_BRANCH) {
SQInteger temp,tright;
exp->_p++;
temp = sqstd_rex_newnode(exp,OP_OR);
exp->_nodes[temp].left = ret;
tright = sqstd_rex_list(exp);
exp->_nodes[temp].right = tright;
ret = temp;
}
return ret;
}
static SQBool sqstd_rex_matchcclass(SQInteger cclass,SQChar c)
{
switch(cclass) {
case 'a': return isalpha(c)?SQTrue:SQFalse;
case 'A': return !isalpha(c)?SQTrue:SQFalse;
case 'w': return (isalnum(c) || c == '_')?SQTrue:SQFalse;
case 'W': return (!isalnum(c) && c != '_')?SQTrue:SQFalse;
case 's': return isspace(c)?SQTrue:SQFalse;
case 'S': return !isspace(c)?SQTrue:SQFalse;
case 'd': return isdigit(c)?SQTrue:SQFalse;
case 'D': return !isdigit(c)?SQTrue:SQFalse;
case 'x': return isxdigit(c)?SQTrue:SQFalse;
case 'X': return !isxdigit(c)?SQTrue:SQFalse;
case 'c': return iscntrl(c)?SQTrue:SQFalse;
case 'C': return !iscntrl(c)?SQTrue:SQFalse;
case 'p': return ispunct(c)?SQTrue:SQFalse;
case 'P': return !ispunct(c)?SQTrue:SQFalse;
case 'l': return islower(c)?SQTrue:SQFalse;
case 'u': return isupper(c)?SQTrue:SQFalse;
}
return SQFalse; /*cannot happen*/
}
static SQBool sqstd_rex_matchclass(SQRex* exp,SQRexNode *node,SQInteger c)
{
do {
switch(node->type) {
case OP_RANGE:
if(c >= node->left && c <= node->right) return SQTrue;
break;
case OP_CCLASS:
if(sqstd_rex_matchcclass(node->left,c)) return SQTrue;
break;
default:
if(c == node->type)return SQTrue;
}
} while((node->next != -1) && (node = &exp->_nodes[node->next]));
return SQFalse;
}
static const SQChar *sqstd_rex_matchnode(SQRex* exp,SQRexNode *node,const SQChar *str,SQRexNode *next)
{
SQRexNodeType type = node->type;
switch(type) {
case OP_GREEDY: {
//SQRexNode *greedystop = (node->next != -1) ? &exp->_nodes[node->next] : nullptr;
SQRexNode *greedystop = nullptr;
SQInteger p0 = (node->right >> 16)&0x0000FFFF, p1 = node->right&0x0000FFFF, nmaches = 0;
const SQChar *s=str, *good = str;
if(node->next != -1) {
greedystop = &exp->_nodes[node->next];
}
else {
greedystop = next;
}
while((nmaches == 0xFFFF || nmaches < p1)) {
const SQChar *stop;
if(!(s = sqstd_rex_matchnode(exp,&exp->_nodes[node->left],s,greedystop)))
break;
nmaches++;
good=s;
if(greedystop) {
//checks that 0 matches satisfy the expression(if so skips)
//if not would always stop(for instance if is a '?')
if(greedystop->type != OP_GREEDY ||
(greedystop->type == OP_GREEDY && ((greedystop->right >> 16)&0x0000FFFF) != 0))
{
SQRexNode *gnext = nullptr;
if(greedystop->next != -1) {
gnext = &exp->_nodes[greedystop->next];
}else if(next && next->next != -1){
gnext = &exp->_nodes[next->next];
}
stop = sqstd_rex_matchnode(exp,greedystop,s,gnext);
if(stop) {
//if satisfied stop it
if(p0 == p1 && p0 == nmaches) break;
else if(nmaches >= p0 && p1 == 0xFFFF) break;
else if(nmaches >= p0 && nmaches <= p1) break;
}
}
}
if(s >= exp->_eol)
break;
}
if(p0 == p1 && p0 == nmaches) return good;
else if(nmaches >= p0 && p1 == 0xFFFF) return good;
else if(nmaches >= p0 && nmaches <= p1) return good;
return nullptr;
}
case OP_OR: {
const SQChar *asd = str;
SQRexNode *temp=&exp->_nodes[node->left];
while( (asd = sqstd_rex_matchnode(exp,temp,asd,nullptr)) ) {
if(temp->next != -1)
temp = &exp->_nodes[temp->next];
else
return asd;
}
asd = str;
temp = &exp->_nodes[node->right];
while( (asd = sqstd_rex_matchnode(exp,temp,asd,nullptr)) ) {
if(temp->next != -1)
temp = &exp->_nodes[temp->next];
else
return asd;
}
return nullptr;
break;
}
case OP_EXPR:
case OP_NOCAPEXPR:{
SQRexNode *n = &exp->_nodes[node->left];
const SQChar *cur = str;
SQInteger capture = -1;
if(node->type != OP_NOCAPEXPR && node->right == exp->_currsubexp) {
capture = exp->_currsubexp;
exp->_matches[capture].begin = cur;
exp->_currsubexp++;
}
do {
SQRexNode *subnext = nullptr;
if(n->next != -1) {
subnext = &exp->_nodes[n->next];
}else {
subnext = next;
}
if(!(cur = sqstd_rex_matchnode(exp,n,cur,subnext))) {
if(capture != -1){
exp->_matches[capture].begin = 0;
exp->_matches[capture].len = 0;
}
return nullptr;
}
} while((n->next != -1) && (n = &exp->_nodes[n->next]));
if(capture != -1)
exp->_matches[capture].len = cur - exp->_matches[capture].begin;
return cur;
}
case OP_WB:
if((str == exp->_bol && !isspace(*str))
|| (str == exp->_eol && !isspace(*(str-1)))
|| (!isspace(*str) && isspace(*(str+1)))
|| (isspace(*str) && !isspace(*(str+1))) ) {
return (node->left == 'b')?str:nullptr;
}
return (node->left == 'b')?nullptr:str;
case OP_BOL:
if(str == exp->_bol) return str;
return nullptr;
case OP_EOL:
if(str == exp->_eol) return str;
return nullptr;
case OP_DOT:{
*str++;
}
return str;
case OP_NCLASS:
case OP_CLASS:
if(sqstd_rex_matchclass(exp,&exp->_nodes[node->left],*str)?(type == OP_CLASS?SQTrue:SQFalse):(type == OP_NCLASS?SQTrue:SQFalse)) {
*str++;
return str;
}
return nullptr;
case OP_CCLASS:
if(sqstd_rex_matchcclass(node->left,*str)) {
*str++;
return str;
}
return nullptr;
default: /* char */
if(*str != (SQChar)node->type) return nullptr;
*str++;
return str;
}
return nullptr;
}
/* public api */
SQRex *sqstd_rex_compile(const SQChar *pattern,const SQChar **error)
{
SQRex *exp = (SQRex *)sq_malloc(sizeof(SQRex));
exp->_eol = exp->_bol = nullptr;
exp->_p = pattern;
exp->_nallocated = (SQInteger)strlen(pattern) * sizeof(SQChar);
exp->_nodes = (SQRexNode *)sq_malloc(exp->_nallocated * sizeof(SQRexNode));
exp->_nsize = 0;
exp->_matches = 0;
exp->_nsubexpr = 0;
exp->_first = sqstd_rex_newnode(exp,OP_EXPR);
exp->_error = error;
try {
SQInteger res = sqstd_rex_list(exp);
exp->_nodes[exp->_first].left = res;
if(*exp->_p!='\0')
sqstd_rex_error(exp,"unexpected character");
#ifdef _DEBUG
{
SQInteger nsize,i;
SQRexNode *t;
nsize = exp->_nsize;
t = &exp->_nodes[0];
printf("\n");
/* XXX -- The (int) casts are needed to silent warnings on 64bit systems (SQInteger is 64bit, %d assumes 32bit, (int) is 32bit) */
for(i = 0;i < nsize; i++) {
if(exp->_nodes[i].type>MAX_CHAR)
printf("[%02d] %10s ",(int)i,g_nnames[exp->_nodes[i].type-MAX_CHAR]);
else
printf("[%02d] %10c ",(int)i,exp->_nodes[i].type);
printf("left %02d right %02d next %02d\n",(int)exp->_nodes[i].left,(int)exp->_nodes[i].right,(int)exp->_nodes[i].next);
}
printf("\n");
}
#endif
exp->_matches = (SQRexMatch *) sq_malloc(exp->_nsubexpr * sizeof(SQRexMatch));
memset(exp->_matches,0,exp->_nsubexpr * sizeof(SQRexMatch));
}
catch (...) {
sqstd_rex_free(exp);
return nullptr;
}
return exp;
}
void sqstd_rex_free(SQRex *exp)
{
if(exp) {
if(exp->_nodes) sq_free(exp->_nodes,exp->_nallocated * sizeof(SQRexNode));
if(exp->_matches) sq_free(exp->_matches,exp->_nsubexpr * sizeof(SQRexMatch));
sq_free(exp,sizeof(SQRex));
}
}
SQBool sqstd_rex_match(SQRex* exp,const SQChar* text)
{
const SQChar* res = nullptr;
exp->_bol = text;
exp->_eol = text + strlen(text);
exp->_currsubexp = 0;
res = sqstd_rex_matchnode(exp,exp->_nodes,text,nullptr);
if(res == nullptr || res != exp->_eol)
return SQFalse;
return SQTrue;
}
SQBool sqstd_rex_searchrange(SQRex* exp,const SQChar* text_begin,const SQChar* text_end,const SQChar** out_begin, const SQChar** out_end)
{
const SQChar *cur = nullptr;
SQInteger node = exp->_first;
if(text_begin >= text_end) return SQFalse;
exp->_bol = text_begin;
exp->_eol = text_end;
do {
cur = text_begin;
while(node != -1) {
exp->_currsubexp = 0;
cur = sqstd_rex_matchnode(exp,&exp->_nodes[node],cur,nullptr);
if(!cur)
break;
node = exp->_nodes[node].next;
}
*text_begin++;
} while(cur == nullptr && text_begin != text_end);
if(cur == nullptr)
return SQFalse;
--text_begin;
if(out_begin) *out_begin = text_begin;
if(out_end) *out_end = cur;
return SQTrue;
}
SQBool sqstd_rex_search(SQRex* exp,const SQChar* text, const SQChar** out_begin, const SQChar** out_end)
{
return sqstd_rex_searchrange(exp,text,text + strlen(text),out_begin,out_end);
}
SQInteger sqstd_rex_getsubexpcount(SQRex* exp)
{
return exp->_nsubexpr;
}
SQBool sqstd_rex_getsubexp(SQRex* exp, SQInteger n, SQRexMatch *subexp)
{
if( n<0 || n >= exp->_nsubexpr) return SQFalse;
*subexp = exp->_matches[n];
return SQTrue;
}
-270
View File
@@ -1,270 +0,0 @@
/* see copyright notice in squirrel.h */
#include <squirrel.h>
#include <sqstdstring.h>
#define scstrchr strchr
#define scatoi atoi
#define scstrtok strtok
#define MAX_FORMAT_LEN 20
#define MAX_WFORMAT_LEN 3
#define ADDITIONAL_FORMAT_SPACE (100*sizeof(SQChar))
static SQInteger validate_format(HSQUIRRELVM v, SQChar *fmt, const SQChar *src, SQInteger n,SQInteger &width)
{
SQChar swidth[MAX_WFORMAT_LEN];
SQInteger wc = 0;
SQInteger start = n;
fmt[0] = '%';
while (scstrchr("-+ #0", src[n])) n++;
while (isdigit(src[n])) {
swidth[wc] = src[n];
n++;
wc++;
if(wc>=MAX_WFORMAT_LEN)
return sq_throwerror(v,"width format too long");
}
swidth[wc] = '\0';
if(wc > 0) {
width = atoi(swidth);
}
else
width = 0;
if (src[n] == '.') {
n++;
wc = 0;
while (isdigit(src[n])) {
swidth[wc] = src[n];
n++;
wc++;
if(wc>=MAX_WFORMAT_LEN)
return sq_throwerror(v,"precision format too long");
}
swidth[wc] = '\0';
if(wc > 0) {
width += atoi(swidth);
}
}
if (n-start > MAX_FORMAT_LEN )
return sq_throwerror(v,"format too long");
memcpy(&fmt[1],&src[start],((n-start)+1)*sizeof(SQChar));
fmt[(n-start)+2] = '\0';
return n;
}
static void __strip_l(const SQChar *str,const SQChar **start)
{
const SQChar *t = str;
while(((*t) != '\0') && isspace(*t)){ t++; }
*start = t;
}
static void __strip_r(const SQChar *str,SQInteger len,const SQChar **end)
{
if(len == 0) {
*end = str;
return;
}
const SQChar *t = &str[len-1];
while(t != str && isspace(*t)) { t--; }
*end = t+1;
}
static SQInteger _string_strip(HSQUIRRELVM v)
{
const SQChar *str,*start,*end;
sq_getstring(v,2,&str);
SQInteger len = sq_getsize(v,2);
__strip_l(str,&start);
__strip_r(str,len,&end);
sq_pushstring(v,start,end - start);
return 1;
}
static SQInteger _string_lstrip(HSQUIRRELVM v)
{
const SQChar *str,*start;
sq_getstring(v,2,&str);
__strip_l(str,&start);
sq_pushstring(v,start,-1);
return 1;
}
static SQInteger _string_rstrip(HSQUIRRELVM v)
{
const SQChar *str,*end;
sq_getstring(v,2,&str);
SQInteger len = sq_getsize(v,2);
__strip_r(str,len,&end);
sq_pushstring(v,str,end - str);
return 1;
}
static SQInteger _string_split(HSQUIRRELVM v)
{
const SQChar *str,*seps;
SQChar *stemp,*tok;
sq_getstring(v,2,&str);
sq_getstring(v,3,&seps);
if(sq_getsize(v,3) == 0) return sq_throwerror(v,"empty separators string");
SQInteger memsize = (sq_getsize(v,2)+1)*sizeof(SQChar);
stemp = sq_getscratchpad(v,memsize);
memcpy(stemp,str,memsize);
tok = scstrtok(stemp,seps);
sq_newarray(v,0);
while( tok != nullptr ) {
sq_pushstring(v,tok,-1);
sq_arrayappend(v,-2);
tok = scstrtok( nullptr, seps );
}
return 1;
}
#define SETUP_REX(v) \
SQRex *self = nullptr; \
sq_getinstanceup(v,1,(SQUserPointer *)&self,0);
static SQInteger _rexobj_releasehook(SQUserPointer p, SQInteger size)
{
SQRex *self = ((SQRex *)p);
sqstd_rex_free(self);
return 1;
}
static SQInteger _regexp_match(HSQUIRRELVM v)
{
SETUP_REX(v);
const SQChar *str;
sq_getstring(v,2,&str);
if(sqstd_rex_match(self,str) == SQTrue)
{
sq_pushbool(v,SQTrue);
return 1;
}
sq_pushbool(v,SQFalse);
return 1;
}
static void _addrexmatch(HSQUIRRELVM v,const SQChar *str,const SQChar *begin,const SQChar *end)
{
sq_newtable(v);
sq_pushstring(v,"begin",-1);
sq_pushinteger(v,begin - str);
sq_rawset(v,-3);
sq_pushstring(v,"end",-1);
sq_pushinteger(v,end - str);
sq_rawset(v,-3);
}
static SQInteger _regexp_search(HSQUIRRELVM v)
{
SETUP_REX(v);
const SQChar *str,*begin,*end;
SQInteger start = 0;
sq_getstring(v,2,&str);
if(sq_gettop(v) > 2) sq_getinteger(v,3,&start);
if(sqstd_rex_search(self,str+start,&begin,&end) == SQTrue) {
_addrexmatch(v,str,begin,end);
return 1;
}
return 0;
}
static SQInteger _regexp_capture(HSQUIRRELVM v)
{
SETUP_REX(v);
const SQChar *str,*begin,*end;
SQInteger start = 0;
sq_getstring(v,2,&str);
if(sq_gettop(v) > 2) sq_getinteger(v,3,&start);
if(sqstd_rex_search(self,str+start,&begin,&end) == SQTrue) {
SQInteger n = sqstd_rex_getsubexpcount(self);
SQRexMatch match;
sq_newarray(v,0);
for(SQInteger i = 0;i < n; i++) {
sqstd_rex_getsubexp(self,i,&match);
if(match.len > 0)
_addrexmatch(v,str,match.begin,match.begin+match.len);
else
_addrexmatch(v,str,str,str); //empty match
sq_arrayappend(v,-2);
}
return 1;
}
return 0;
}
static SQInteger _regexp_subexpcount(HSQUIRRELVM v)
{
SETUP_REX(v);
sq_pushinteger(v,sqstd_rex_getsubexpcount(self));
return 1;
}
static SQInteger _regexp_constructor(HSQUIRRELVM v)
{
const SQChar *error,*pattern;
sq_getstring(v,2,&pattern);
SQRex *rex = sqstd_rex_compile(pattern,&error);
if(!rex) return sq_throwerror(v,error);
sq_setinstanceup(v,1,rex);
sq_setreleasehook(v,1,_rexobj_releasehook);
return 0;
}
static SQInteger _regexp__typeof(HSQUIRRELVM v)
{
sq_pushstring(v,"regexp",-1);
return 1;
}
#define _DECL_REX_FUNC(name,nparams,pmask) {#name,_regexp_##name,nparams,pmask}
static SQRegFunction rexobj_funcs[]={
_DECL_REX_FUNC(constructor,2,".s"),
_DECL_REX_FUNC(search,-2,"xsn"),
_DECL_REX_FUNC(match,2,"xs"),
_DECL_REX_FUNC(capture,-2,"xsn"),
_DECL_REX_FUNC(subexpcount,1,"x"),
_DECL_REX_FUNC(_typeof,1,"x"),
{0,0,0,0}
};
#define _DECL_FUNC(name,nparams,pmask) {#name,_string_##name,nparams,pmask}
static SQRegFunction stringlib_funcs[]={
_DECL_FUNC(format,-2,".s"),
_DECL_FUNC(strip,2,".s"),
_DECL_FUNC(lstrip,2,".s"),
_DECL_FUNC(rstrip,2,".s"),
_DECL_FUNC(split,3,".ss"),
{0,0,0,0}
};
SQInteger sqstd_register_stringlib(HSQUIRRELVM v)
{
sq_pushstring(v,"regexp",-1);
sq_newclass(v,SQFalse);
SQInteger i = 0;
while(rexobj_funcs[i].name != 0) {
SQRegFunction &f = rexobj_funcs[i];
sq_pushstring(v,f.name,-1);
sq_newclosure(v,f.f,0);
sq_setparamscheck(v,f.nparamscheck,f.typemask);
sq_setnativeclosurename(v,-1,f.name);
sq_createslot(v,-3);
i++;
}
sq_createslot(v,-3);
i = 0;
while(stringlib_funcs[i].name!=0)
{
sq_pushstring(v,stringlib_funcs[i].name,-1);
sq_newclosure(v,stringlib_funcs[i].f,0);
sq_setparamscheck(v,stringlib_funcs[i].nparamscheck,stringlib_funcs[i].typemask);
sq_setnativeclosurename(v,-1,stringlib_funcs[i].name);
sq_createslot(v,-3);
i++;
}
return 1;
}
+32 -58
View File
@@ -18,6 +18,7 @@
#include "sqfuncstate.h"
#include "sqclass.h"
#include "../../../core/string_consumer.hpp"
#include "../../../string_func.h"
#include "../../../safeguards.h"
@@ -131,7 +132,7 @@ void sq_close(HSQUIRRELVM v)
sq_delete(ss, SQSharedState);
}
SQRESULT sq_compile(HSQUIRRELVM v,SQLEXREADFUNC read,SQUserPointer p,const SQChar *sourcename,SQBool raiseerror)
SQRESULT sq_compile(HSQUIRRELVM v,SQLEXREADFUNC read,SQUserPointer p,std::string_view sourcename,SQBool raiseerror)
{
SQObjectPtr o;
if(Compile(v, read, p, sourcename, o, raiseerror != 0, _ss(v)->_debuginfo)) {
@@ -172,12 +173,12 @@ SQBool sq_release(HSQUIRRELVM v,HSQOBJECT *po)
#endif
}
const SQChar *sq_objtostring(HSQOBJECT *o)
std::optional<std::string_view> sq_objtostring(HSQOBJECT *o)
{
if(sq_type(*o) == OT_STRING) {
return _stringval(*o);
}
return nullptr;
return std::nullopt;
}
SQInteger sq_objtointeger(HSQOBJECT *o)
@@ -209,11 +210,9 @@ void sq_pushnull(HSQUIRRELVM v)
v->Push(_null_);
}
void sq_pushstring(HSQUIRRELVM v,const SQChar *s,SQInteger len)
void sq_pushstring(HSQUIRRELVM v,std::string_view s)
{
if(s)
v->Push(SQObjectPtr(SQString::Create(_ss(v), s, len)));
else v->Push(_null_);
v->Push(SQObjectPtr(SQString::Create(_ss(v), s)));
}
void sq_pushinteger(HSQUIRRELVM v,SQInteger n)
@@ -375,7 +374,7 @@ SQRESULT sq_getclosureinfo(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger *nparam
return sq_throwerror(v,"the object is not a closure");
}
SQRESULT sq_setnativeclosurename(HSQUIRRELVM v,SQInteger idx,const SQChar *name)
SQRESULT sq_setnativeclosurename(HSQUIRRELVM v,SQInteger idx,std::string_view name)
{
SQObject o = stack_get(v, idx);
if(sq_isnativeclosure(o)) {
@@ -386,16 +385,16 @@ SQRESULT sq_setnativeclosurename(HSQUIRRELVM v,SQInteger idx,const SQChar *name)
return sq_throwerror(v,"the object is not a nativeclosure");
}
SQRESULT sq_setparamscheck(HSQUIRRELVM v,SQInteger nparamscheck,const SQChar *typemask)
SQRESULT sq_setparamscheck(HSQUIRRELVM v,SQInteger nparamscheck,std::optional<std::string_view> typemask)
{
SQObject o = stack_get(v, -1);
if(!sq_isnativeclosure(o))
return sq_throwerror(v, "native closure expected");
SQNativeClosure *nc = _nativeclosure(o);
nc->_nparamscheck = nparamscheck;
if(typemask) {
if(typemask.has_value()) {
SQIntVec res;
if(!CompileTypemask(res, typemask))
if(!CompileTypemask(res, *typemask))
return sq_throwerror(v, "invalid typemask");
nc->_typecheck.copy(res);
}
@@ -552,11 +551,11 @@ SQRESULT sq_getbool(HSQUIRRELVM v,SQInteger idx,SQBool *b)
return SQ_ERROR;
}
SQRESULT sq_getstring(HSQUIRRELVM v,SQInteger idx,const SQChar **c)
SQRESULT sq_getstring(HSQUIRRELVM v,SQInteger idx,std::string_view &str)
{
SQObjectPtr *o = nullptr;
_GETSAFE_OBJ(v, idx, OT_STRING,o);
*c = _stringval(*o);
str = _stringval(*o);
return SQ_OK;
}
@@ -584,7 +583,7 @@ SQInteger sq_getsize(HSQUIRRELVM v, SQInteger idx)
SQObjectPtr &o = stack_get(v, idx);
SQObjectType type = type(o);
switch(type) {
case OT_STRING: return _string(o)->_len;
case OT_STRING: return _string(o)->View().size();
case OT_TABLE: return _table(o)->CountUsed();
case OT_ARRAY: return _array(o)->Size();
case OT_USERDATA: return _userdata(o)->_size;
@@ -896,7 +895,7 @@ SQRESULT sq_getstackobj(HSQUIRRELVM v,SQInteger idx,HSQOBJECT *po)
return SQ_OK;
}
const SQChar *sq_getlocal(HSQUIRRELVM v,SQUnsignedInteger level,SQUnsignedInteger idx)
std::optional<std::string_view> sq_getlocal(HSQUIRRELVM v,SQUnsignedInteger level,SQUnsignedInteger idx)
{
SQUnsignedInteger cstksize=v->_callsstacksize;
SQUnsignedInteger lvl=(cstksize-level)-1;
@@ -908,7 +907,7 @@ const SQChar *sq_getlocal(HSQUIRRELVM v,SQUnsignedInteger level,SQUnsignedIntege
}
SQVM::CallInfo &ci=v->_callsstack[lvl];
if(type(ci._closure)!=OT_CLOSURE)
return nullptr;
return std::nullopt;
SQClosure *c=_closure(ci._closure);
SQFunctionProto *func=_funcproto(c->_function);
if(func->_noutervalues > (SQInteger)idx) {
@@ -918,7 +917,7 @@ const SQChar *sq_getlocal(HSQUIRRELVM v,SQUnsignedInteger level,SQUnsignedIntege
idx -= func->_noutervalues;
return func->GetLocal(v,stackbase,idx,(SQInteger)(ci._ip-func->_instructions)-1);
}
return nullptr;
return std::nullopt;
}
void sq_pushobject(HSQUIRRELVM v,HSQOBJECT obj)
@@ -931,9 +930,9 @@ void sq_resetobject(HSQOBJECT *po)
po->_unVal.pUserPointer=nullptr;po->_type=OT_NULL;
}
SQRESULT sq_throwerror(HSQUIRRELVM v,const SQChar *err, SQInteger len)
SQRESULT sq_throwerror(HSQUIRRELVM v,std::string_view error)
{
v->_lasterror=SQString::Create(_ss(v),err, len);
v->_lasterror=SQString::Create(_ss(v),error);
return -1;
}
@@ -978,6 +977,10 @@ SQRESULT sq_call(HSQUIRRELVM v,SQInteger params,SQBool retval,SQBool raiseerror,
if(!v->_suspended) {
v->Pop(params);//pop closure and args
}
if (!v->_can_suspend && v->IsOpsTillSuspendError()) {
v->Raise_Error(fmt::format("excessive CPU usage in {}", v->_ops_till_suspend_error_label));
return SQ_ERROR;
}
if(retval){
v->Push(res); return SQ_OK;
}
@@ -1075,7 +1078,7 @@ SQRESULT sq_readclosure(HSQUIRRELVM v,SQREADFUNC r,SQUserPointer up)
return SQ_OK;
}
SQChar *sq_getscratchpad(HSQUIRRELVM v,SQInteger minsize)
std::span<char> sq_getscratchpad(HSQUIRRELVM v,SQInteger minsize)
{
return _ss(v)->GetScratchPad(minsize);
}
@@ -1089,19 +1092,18 @@ SQInteger sq_collectgarbage(HSQUIRRELVM v)
#endif
}
const SQChar *sq_getfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval)
std::optional<std::string_view> sq_getfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval)
{
SQObjectPtr &self = stack_get(v,idx);
const SQChar *name = nullptr;
if(type(self) == OT_CLOSURE) {
if(_closure(self)->_outervalues.size()>nval) {
v->Push(_closure(self)->_outervalues[nval]);
SQFunctionProto *fp = _funcproto(_closure(self)->_function);
SQOuterVar &ov = fp->_outervalues[nval];
name = _stringval(ov._name);
return _stringval(ov._name);
}
}
return name;
return std::nullopt;
}
SQRESULT sq_setfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval)
@@ -1253,44 +1255,16 @@ SQRESULT sq_next(HSQUIRRELVM v,SQInteger idx)
return SQ_ERROR;
}
struct BufState{
const SQChar *buf;
SQInteger ptr;
SQInteger size;
};
char32_t buf_lexfeed(SQUserPointer file)
{
/* Convert an UTF-8 character into a char32_t */
BufState *buf = (BufState *)file;
const char *p = &buf->buf[buf->ptr];
if (buf->size < buf->ptr + 1) return 0;
/* Read the first character, and get the length based on UTF-8 specs. If invalid, bail out. */
uint len = Utf8EncodedCharLen(*p);
if (len == 0) {
buf->ptr++;
return -1;
}
/* Read the remaining bits. */
if (buf->size < buf->ptr + len) return 0;
buf->ptr += len;
/* Convert the character, and when definitely invalid, bail out as well. */
char32_t c;
if (Utf8Decode(&c, p) != len) return -1;
return c;
StringConsumer &consumer = *reinterpret_cast<StringConsumer *>(file);
return consumer.AnyBytesLeft() ? consumer.ReadUtf8(-1) : 0;
}
SQRESULT sq_compilebuffer(HSQUIRRELVM v,const SQChar *s,SQInteger size,const SQChar *sourcename,SQBool raiseerror) {
BufState buf;
buf.buf = s;
buf.size = size;
buf.ptr = 0;
return sq_compile(v, buf_lexfeed, &buf, sourcename, raiseerror);
SQRESULT sq_compilebuffer(HSQUIRRELVM v,std::string_view buffer,std::string_view sourcename,SQBool raiseerror) {
StringConsumer consumer{buffer};
return sq_compile(v, buf_lexfeed, &consumer, sourcename, raiseerror);
}
void sq_move(HSQUIRRELVM dest,HSQUIRRELVM src,SQInteger idx)
@@ -1323,7 +1297,7 @@ void sq_free(void *p,SQUnsignedInteger size)
SQ_FREE(p,size);
}
SQOpsLimiter::SQOpsLimiter(HSQUIRRELVM v, SQInteger ops, const char *label) : _v(v)
SQOpsLimiter::SQOpsLimiter(HSQUIRRELVM v, SQInteger ops, std::string_view label) : _v(v)
{
this->_ops = v->_ops_till_suspend_error_threshold;
if (this->_ops == INT64_MIN) {
+99 -110
View File
@@ -5,6 +5,7 @@
#include "../../../stdafx.h"
#include "../../fmt/format.h"
#include "../../../core/string_consumer.hpp"
#include "sqpcheader.h"
#include "sqvm.h"
#include "sqstring.h"
@@ -17,19 +18,20 @@
#include "../../../safeguards.h"
bool str2num(const SQChar *s,SQObjectPtr &res)
bool str2num(std::string_view s,SQObjectPtr &res)
{
SQChar *end;
if(strstr(s,".")){
SQFloat r = SQFloat(strtod(s,&end));
if(s == end) return false;
if(s.find('.') != std::string_view::npos){
char *end;
std::string str{s};
SQFloat r = SQFloat(strtod(str.c_str(),&end));
if(str.c_str() == end) return false;
res = r;
return true;
}
else{
SQInteger r = SQInteger(strtol(s,&end,10));
if(s == end) return false;
res = r;
auto val = ParseInteger<int64_t>(s);
if (!val.has_value()) return false;
res = *val;
return true;
}
}
@@ -101,29 +103,29 @@ static SQInteger base_getstackinfos(HSQUIRRELVM v)
SQInteger level;
SQStackInfos si;
SQInteger seq = 0;
const SQChar *name = nullptr;
sq_getinteger(v, -1, &level);
if (SQ_SUCCEEDED(sq_stackinfos(v, level, &si)))
{
const SQChar *fn = "unknown";
const SQChar *src = "unknown";
std::string_view fn = "unknown";
std::string_view src = "unknown";
if(si.funcname)fn = si.funcname;
if(si.source)src = si.source;
sq_newtable(v);
sq_pushstring(v, "func", -1);
sq_pushstring(v, fn, -1);
sq_pushstring(v, "func");
sq_pushstring(v, fn);
sq_createslot(v, -3);
sq_pushstring(v, "src", -1);
sq_pushstring(v, src, -1);
sq_pushstring(v, "src");
sq_pushstring(v, src);
sq_createslot(v, -3);
sq_pushstring(v, "line", -1);
sq_pushstring(v, "line");
sq_pushinteger(v, si.line);
sq_createslot(v, -3);
sq_pushstring(v, "locals", -1);
sq_pushstring(v, "locals");
sq_newtable(v);
seq=0;
while ((name = sq_getlocal(v, level, seq))) {
sq_pushstring(v, name, -1);
std::optional<std::string_view> name;
while ((name = sq_getlocal(v, level, seq)).has_value()) {
sq_pushstring(v, *name);
sq_push(v, -2);
sq_createslot(v, -4);
sq_pop(v, 1);
@@ -169,9 +171,9 @@ static SQInteger get_slice_params(HSQUIRRELVM v,SQInteger &sidx,SQInteger &eidx,
static SQInteger base_print(HSQUIRRELVM v)
{
const SQChar *str;
std::string_view str;
sq_tostring(v,2);
sq_getstring(v,-1,&str);
sq_getstring(v,-1,str);
if(_ss(v)->_printfunc) _ss(v)->_printfunc(v,str);
return 0;
}
@@ -180,14 +182,14 @@ static SQInteger base_print(HSQUIRRELVM v)
static SQInteger base_compilestring(HSQUIRRELVM v)
{
SQInteger nargs=sq_gettop(v);
const SQChar *src=nullptr,*name="unnamedbuffer";
std::string_view src, name="unnamedbuffer";
SQInteger size;
sq_getstring(v,2,&src);
sq_getstring(v,2,src);
size=sq_getsize(v,2);
if(nargs>2){
sq_getstring(v,3,&name);
sq_getstring(v,3,name);
}
if(SQ_SUCCEEDED(sq_compilebuffer(v,src,size,name,SQFalse)))
if(SQ_SUCCEEDED(sq_compilebuffer(v,src.substr(0, size),name,SQFalse)))
return 1;
else
return SQ_ERROR;
@@ -232,62 +234,59 @@ static SQInteger base_array(HSQUIRRELVM v)
static SQInteger base_type(HSQUIRRELVM v)
{
SQObjectPtr &o = stack_get(v,2);
v->Push(SQString::Create(_ss(v),GetTypeName(o),-1));
v->Push(SQString::Create(_ss(v),GetTypeName(o)));
return 1;
}
static SQRegFunction base_funcs[]={
static const std::initializer_list<SQRegFunction> base_funcs={
//generic
#ifdef EXPORT_DEFAULT_SQUIRREL_FUNCTIONS
{"seterrorhandler",base_seterrorhandler,2, nullptr},
{"setdebughook",base_setdebughook,2, nullptr},
{"enabledebuginfo",base_enabledebuginfo,2, nullptr},
{"seterrorhandler",base_seterrorhandler,2, std::nullopt},
{"setdebughook",base_setdebughook,2, std::nullopt},
{"enabledebuginfo",base_enabledebuginfo,2, std::nullopt},
{"getstackinfos",base_getstackinfos,2, ".n"},
{"getroottable",base_getroottable,1, nullptr},
{"setroottable",base_setroottable,2, nullptr},
{"getconsttable",base_getconsttable,1, nullptr},
{"setconsttable",base_setconsttable,2, nullptr},
{"getroottable",base_getroottable,1, std::nullopt},
{"setroottable",base_setroottable,2, std::nullopt},
{"getconsttable",base_getconsttable,1, std::nullopt},
{"setconsttable",base_setconsttable,2, std::nullopt},
#endif
{"assert",base_assert,2, nullptr},
{"print",base_print,2, nullptr},
{"assert",base_assert,2, std::nullopt},
{"print",base_print,2, std::nullopt},
#ifdef EXPORT_DEFAULT_SQUIRREL_FUNCTIONS
{"compilestring",base_compilestring,-2, ".ss"},
{"newthread",base_newthread,2, ".c"},
{"suspend",base_suspend,-1, nullptr},
{"suspend",base_suspend,-1, std::nullopt},
#endif
{"array",base_array,-2, ".n"},
{"type",base_type,2, nullptr},
{"type",base_type,2, std::nullopt},
#ifdef EXPORT_DEFAULT_SQUIRREL_FUNCTIONS
{"dummy",base_dummy,0,nullptr},
{"dummy",base_dummy,0,std::nullopt},
#ifndef NO_GARBAGE_COLLECTOR
{"collectgarbage",base_collectgarbage,1, "t"},
#endif
#endif
{nullptr,nullptr,0,nullptr}
};
void sq_base_register(HSQUIRRELVM v)
{
SQInteger i=0;
sq_pushroottable(v);
while(base_funcs[i].name!=nullptr) {
sq_pushstring(v,base_funcs[i].name,-1);
sq_newclosure(v,base_funcs[i].f,0);
sq_setnativeclosurename(v,-1,base_funcs[i].name);
sq_setparamscheck(v,base_funcs[i].nparamscheck,base_funcs[i].typemask);
for(auto &func : base_funcs) {
sq_pushstring(v,func.name);
sq_newclosure(v,func.f,0);
sq_setnativeclosurename(v,-1,func.name);
sq_setparamscheck(v,func.nparamscheck,func.typemask);
sq_createslot(v,-3);
i++;
}
sq_pushstring(v,"_version_",-1);
sq_pushstring(v,SQUIRREL_VERSION,-1);
sq_pushstring(v,"_version_");
sq_pushstring(v,SQUIRREL_VERSION);
sq_createslot(v,-3);
sq_pushstring(v,"_charsize_",-1);
sq_pushinteger(v,sizeof(SQChar));
sq_pushstring(v,"_charsize_");
sq_pushinteger(v,sizeof(char));
sq_createslot(v,-3);
sq_pushstring(v,"_intsize_",-1);
sq_pushstring(v,"_intsize_");
sq_pushinteger(v,sizeof(SQInteger));
sq_createslot(v,-3);
sq_pushstring(v,"_floatsize_",-1);
sq_pushstring(v,"_floatsize_");
sq_pushinteger(v,sizeof(SQFloat));
sq_createslot(v,-3);
sq_pop(v,1);
@@ -370,8 +369,8 @@ static SQInteger obj_clear(HSQUIRRELVM v)
static SQInteger number_delegate_tochar(HSQUIRRELVM v)
{
SQObject &o=stack_get(v,1);
SQChar c = (SQChar)tointeger(o);
v->Push(SQString::Create(_ss(v),(const SQChar *)&c,1));
char c = static_cast<char>(tointeger(o));
v->Push(SQString::Create(_ss(v),std::string_view(&c, 1)));
return 1;
}
@@ -409,16 +408,15 @@ static SQInteger table_rawget(HSQUIRRELVM v)
}
SQRegFunction SQSharedState::_table_default_delegate_funcz[]={
/* static */ const std::initializer_list<SQRegFunction> SQSharedState::_table_default_delegate_funcz={
{"len",default_delegate_len,1, "t"},
{"rawget",table_rawget,2, "t"},
{"rawset",table_rawset,3, "t"},
{"rawdelete",table_rawdelete,2, "t"},
{"rawin",container_rawexists,2, "t"},
{"weakref",obj_delegate_weakref,1, nullptr },
{"weakref",obj_delegate_weakref,1, std::nullopt },
{"tostring",default_delegate_tostring,1, "."},
{"clear",obj_clear,1, "."},
{nullptr,nullptr,0,nullptr}
};
//ARRAY DEFAULT DELEGATE///////////////////////////////////////
@@ -611,7 +609,7 @@ static SQInteger array_slice(HSQUIRRELVM v)
}
SQRegFunction SQSharedState::_array_default_delegate_funcz[]={
/* static */ const std::initializer_list<SQRegFunction> SQSharedState::_array_default_delegate_funcz={
{"len",default_delegate_len,1, "a"},
{"append",array_append,2, "a"},
{"extend",array_extend,2, "aa"},
@@ -624,10 +622,9 @@ SQRegFunction SQSharedState::_array_default_delegate_funcz[]={
{"reverse",array_reverse,1, "a"},
{"sort",array_sort,-1, "ac"},
{"slice",array_slice,-1, "ann"},
{"weakref",obj_delegate_weakref,1, nullptr },
{"weakref",obj_delegate_weakref,1, std::nullopt },
{"tostring",default_delegate_tostring,1, "."},
{"clear",obj_clear,1, "."},
{nullptr,nullptr,0,nullptr}
};
//STRING DEFAULT DELEGATE//////////////////////////
@@ -636,25 +633,25 @@ static SQInteger string_slice(HSQUIRRELVM v)
SQInteger sidx,eidx;
SQObjectPtr o;
if(SQ_FAILED(get_slice_params(v,sidx,eidx,o)))return -1;
SQInteger slen = _string(o)->_len;
SQInteger slen = _string(o)->View().size();
if(sidx < 0)sidx = slen + sidx;
if(eidx < 0)eidx = slen + eidx;
if(eidx < sidx) return sq_throwerror(v,"wrong indexes");
if(eidx > slen) return sq_throwerror(v,"slice out of range");
v->Push(SQString::Create(_ss(v),&_stringval(o)[sidx],eidx-sidx));
v->Push(SQString::Create(_ss(v),_stringval(o).substr(sidx,eidx-sidx)));
return 1;
}
static SQInteger string_find(HSQUIRRELVM v)
{
SQInteger top,start_idx=0;
const SQChar *str,*substr,*ret;
if(((top=sq_gettop(v))>1) && SQ_SUCCEEDED(sq_getstring(v,1,&str)) && SQ_SUCCEEDED(sq_getstring(v,2,&substr))){
std::string_view str,substr;
if(((top=sq_gettop(v))>1) && SQ_SUCCEEDED(sq_getstring(v,1,str)) && SQ_SUCCEEDED(sq_getstring(v,2,substr))){
if(top>2)sq_getinteger(v,3,&start_idx);
if((sq_getsize(v,1)>start_idx) && (start_idx>=0)){
ret=strstr(&str[start_idx],substr);
if(ret){
sq_pushinteger(v,(SQInteger)(ret-str));
auto ret = str.find(substr, start_idx);
if(ret != std::string_view::npos){
sq_pushinteger(v,static_cast<SQInteger>(ret));
return 1;
}
}
@@ -666,11 +663,11 @@ static SQInteger string_find(HSQUIRRELVM v)
#define STRING_TOFUNCZ(func) static SQInteger string_##func(HSQUIRRELVM v) \
{ \
SQObject str=stack_get(v,1); \
SQInteger len=_string(str)->_len; \
const SQChar *sThis=_stringval(str); \
SQChar *sNew=(_ss(v)->GetScratchPad(len)); \
for(SQInteger i=0;i<len;i++) sNew[i]=func(sThis[i]); \
v->Push(SQString::Create(_ss(v),sNew,len)); \
std::string_view sThis=_stringval(str); \
size_t len=sThis.size(); \
std::span<char> sNew=(_ss(v)->GetScratchPad(len)); \
for(size_t i=0;i<len;i++) sNew[i]=func(sThis[i]); \
v->Push(SQString::Create(_ss(v),std::string_view(sNew.data(), len))); \
return 1; \
}
@@ -678,7 +675,7 @@ static SQInteger string_find(HSQUIRRELVM v)
STRING_TOFUNCZ(tolower)
STRING_TOFUNCZ(toupper)
SQRegFunction SQSharedState::_string_default_delegate_funcz[]={
/* static */ const std::initializer_list<SQRegFunction> SQSharedState::_string_default_delegate_funcz={
{"len",default_delegate_len,1, "s"},
{"tointeger",default_delegate_tointeger,1, "s"},
{"tofloat",default_delegate_tofloat,1, "s"},
@@ -687,18 +684,16 @@ SQRegFunction SQSharedState::_string_default_delegate_funcz[]={
{"find",string_find,-2, "s s n "},
{"tolower",string_tolower,1, "s"},
{"toupper",string_toupper,1, "s"},
{"weakref",obj_delegate_weakref,1, nullptr },
{nullptr,nullptr,0,nullptr}
{"weakref",obj_delegate_weakref,1, std::nullopt },
};
//INTEGER DEFAULT DELEGATE//////////////////////////
SQRegFunction SQSharedState::_number_default_delegate_funcz[]={
/* static */ const std::initializer_list<SQRegFunction> SQSharedState::_number_default_delegate_funcz={
{"tointeger",default_delegate_tointeger,1, "n|b"},
{"tofloat",default_delegate_tofloat,1, "n|b"},
{"tostring",default_delegate_tostring,1, "."},
{"tochar",number_delegate_tochar,1, "n|b"},
{"weakref",obj_delegate_weakref,1, nullptr },
{nullptr,nullptr,0,nullptr}
{"weakref",obj_delegate_weakref,1, std::nullopt },
};
//CLOSURE DEFAULT DELEGATE//////////////////////////
@@ -749,19 +744,19 @@ static SQInteger closure_getinfos(HSQUIRRELVM v) {
_array(params)->Set((SQInteger)n,f->_parameters[n]);
}
if(f->_varparams) {
_array(params)->Set(nparams-1,SQString::Create(_ss(v),"...",-1));
_array(params)->Set(nparams-1,SQString::Create(_ss(v),"..."));
}
res->NewSlot(SQString::Create(_ss(v),"native",-1),false);
res->NewSlot(SQString::Create(_ss(v),"name",-1),f->_name);
res->NewSlot(SQString::Create(_ss(v),"src",-1),f->_sourcename);
res->NewSlot(SQString::Create(_ss(v),"parameters",-1),params);
res->NewSlot(SQString::Create(_ss(v),"varargs",-1),f->_varparams);
res->NewSlot(SQString::Create(_ss(v),"native"),false);
res->NewSlot(SQString::Create(_ss(v),"name"),f->_name);
res->NewSlot(SQString::Create(_ss(v),"src"),f->_sourcename);
res->NewSlot(SQString::Create(_ss(v),"parameters"),params);
res->NewSlot(SQString::Create(_ss(v),"varargs"),f->_varparams);
}
else { //OT_NATIVECLOSURE
SQNativeClosure *nc = _nativeclosure(o);
res->NewSlot(SQString::Create(_ss(v),"native",-1),true);
res->NewSlot(SQString::Create(_ss(v),"name",-1),nc->_name);
res->NewSlot(SQString::Create(_ss(v),"paramscheck",-1),nc->_nparamscheck);
res->NewSlot(SQString::Create(_ss(v),"native"),true);
res->NewSlot(SQString::Create(_ss(v),"name"),nc->_name);
res->NewSlot(SQString::Create(_ss(v),"paramscheck"),nc->_nparamscheck);
SQObjectPtr typecheck;
if(!nc->_typecheck.empty()) {
typecheck =
@@ -770,23 +765,22 @@ static SQInteger closure_getinfos(HSQUIRRELVM v) {
_array(typecheck)->Set((SQInteger)n,nc->_typecheck[n]);
}
}
res->NewSlot(SQString::Create(_ss(v),"typecheck",-1),typecheck);
res->NewSlot(SQString::Create(_ss(v),"typecheck"),typecheck);
}
v->Push(res);
return 1;
}
SQRegFunction SQSharedState::_closure_default_delegate_funcz[]={
/* static */ const std::initializer_list<SQRegFunction> SQSharedState::_closure_default_delegate_funcz={
{"call",closure_call,-1, "c"},
{"pcall",closure_pcall,-1, "c"},
{"acall",closure_acall,2, "ca"},
{"pacall",closure_pacall,2, "ca"},
{"weakref",obj_delegate_weakref,1, nullptr },
{"weakref",obj_delegate_weakref,1, std::nullopt },
{"tostring",default_delegate_tostring,1, "."},
{"bindenv",closure_bindenv,2, "c x|y|t"},
{"getinfos",closure_getinfos,1, "c"},
{nullptr,nullptr,0,nullptr}
};
//GENERATOR DEFAULT DELEGATE
@@ -801,11 +795,10 @@ static SQInteger generator_getstatus(HSQUIRRELVM v)
return 1;
}
SQRegFunction SQSharedState::_generator_default_delegate_funcz[]={
/* static */ const std::initializer_list<SQRegFunction> SQSharedState::_generator_default_delegate_funcz={
{"getstatus",generator_getstatus,1, "g"},
{"weakref",obj_delegate_weakref,1, nullptr },
{"weakref",obj_delegate_weakref,1, std::nullopt },
{"tostring",default_delegate_tostring,1, "."},
{nullptr,nullptr,0,nullptr}
};
//THREAD DEFAULT DELEGATE
@@ -871,13 +864,13 @@ static SQInteger thread_getstatus(HSQUIRRELVM v)
SQObjectPtr &o = stack_get(v,1);
switch(sq_getvmstate(_thread(o))) {
case SQ_VMSTATE_IDLE:
sq_pushstring(v,"idle",-1);
sq_pushstring(v,"idle");
break;
case SQ_VMSTATE_RUNNING:
sq_pushstring(v,"running",-1);
sq_pushstring(v,"running");
break;
case SQ_VMSTATE_SUSPENDED:
sq_pushstring(v,"suspended",-1);
sq_pushstring(v,"suspended");
break;
default:
return sq_throwerror(v,"internal VM error");
@@ -885,13 +878,12 @@ static SQInteger thread_getstatus(HSQUIRRELVM v)
return 1;
}
SQRegFunction SQSharedState::_thread_default_delegate_funcz[] = {
/* static */ const std::initializer_list<SQRegFunction> SQSharedState::_thread_default_delegate_funcz = {
{"call", thread_call, -1, "v"},
{"wakeup", thread_wakeup, -1, "v"},
{"getstatus", thread_getstatus, 1, "v"},
{"weakref",obj_delegate_weakref,1, nullptr },
{"weakref",obj_delegate_weakref,1, std::nullopt },
{"tostring",default_delegate_tostring,1, "."},
{nullptr,nullptr,0,nullptr},
};
static SQInteger class_getattributes(HSQUIRRELVM v)
@@ -915,14 +907,13 @@ static SQInteger class_instance(HSQUIRRELVM v)
return SQ_ERROR;
}
SQRegFunction SQSharedState::_class_default_delegate_funcz[] = {
/* static */ const std::initializer_list<SQRegFunction> SQSharedState::_class_default_delegate_funcz = {
{"getattributes", class_getattributes, 2, "y."},
{"setattributes", class_setattributes, 3, "y.."},
{"rawin",container_rawexists,2, "y"},
{"weakref",obj_delegate_weakref,1, nullptr },
{"weakref",obj_delegate_weakref,1, std::nullopt },
{"tostring",default_delegate_tostring,1, "."},
{"instance",class_instance,1, "y"},
{nullptr,nullptr,0,nullptr}
};
static SQInteger instance_getclass(HSQUIRRELVM v)
@@ -932,12 +923,11 @@ static SQInteger instance_getclass(HSQUIRRELVM v)
return SQ_ERROR;
}
SQRegFunction SQSharedState::_instance_default_delegate_funcz[] = {
/* static */ const std::initializer_list<SQRegFunction> SQSharedState::_instance_default_delegate_funcz = {
{"getclass", instance_getclass, 1, "x"},
{"rawin",container_rawexists,2, "x"},
{"weakref",obj_delegate_weakref,1, nullptr },
{"weakref",obj_delegate_weakref,1, std::nullopt },
{"tostring",default_delegate_tostring,1, "."},
{nullptr,nullptr,0,nullptr}
};
static SQInteger weakref_ref(HSQUIRRELVM v)
@@ -947,11 +937,10 @@ static SQInteger weakref_ref(HSQUIRRELVM v)
return 1;
}
SQRegFunction SQSharedState::_weakref_default_delegate_funcz[] = {
/* static */ const std::initializer_list<SQRegFunction> SQSharedState::_weakref_default_delegate_funcz = {
{"ref",weakref_ref,1, "r"},
{"weakref",obj_delegate_weakref,1, nullptr },
{"weakref",obj_delegate_weakref,1, std::nullopt },
{"tostring",default_delegate_tostring,1, "."},
{nullptr,nullptr,0,nullptr}
};
+34 -38
View File
@@ -57,16 +57,12 @@ typedef sqvector<ExpState> ExpStateVec;
class SQCompiler
{
public:
SQCompiler(SQVM *v, SQLEXREADFUNC rg, SQUserPointer up, const SQChar* sourcename, bool raiseerror, bool lineinfo) : _token(0), _fs(nullptr), _lex(_ss(v), rg, up), _debugline(0), _debugop(0)
SQCompiler(SQVM *v, SQLEXREADFUNC rg, SQUserPointer up, std::string_view sourcename, bool raiseerror, bool lineinfo) : _token(0), _fs(nullptr), _lex(_ss(v), rg, up), _debugline(0), _debugop(0)
{
_vm=v;
_sourcename = SQString::Create(_ss(v), sourcename);
_lineinfo = lineinfo;_raiseerror = raiseerror;
}
[[noreturn]] void Error(const std::string &msg)
{
throw CompileException(msg);
}
void Lex(){ _token = _lex.Lex();}
void PushExpState(){ _expstates.push_back(ExpState()); }
bool IsDerefToken(SQInteger tok)
@@ -92,7 +88,7 @@ public:
//do nothing
}
else {
const SQChar *etypename;
std::string_view etypename;
if(tok > 255) {
switch(tok)
{
@@ -109,21 +105,21 @@ public:
etypename = "FLOAT";
break;
default:
etypename = _lex.Tok2Str(tok);
etypename = _lex.Tok2Str(tok).value_or("<unknown>");
}
Error(fmt::format("expected '{}'", etypename));
throw CompileException(fmt::format("expected '{}'", etypename));
}
Error(fmt::format("expected '{:c}'", tok));
throw CompileException(fmt::format("expected '{:c}'", tok));
}
}
SQObjectPtr ret;
switch(tok)
{
case TK_IDENTIFIER:
ret = _fs->CreateString(_lex._svalue);
ret = _fs->CreateString(_lex.View());
break;
case TK_STRING_LITERAL:
ret = _fs->CreateString(_lex._svalue,_lex._longstr.size()-1);
ret = _fs->CreateString(_lex.View());
break;
case TK_INTEGER:
ret = SQObjectPtr(_lex._nvalue);
@@ -140,7 +136,7 @@ public:
{
if(_token == ';') { Lex(); return; }
if(!IsEndOfStatement()) {
Error("end of statement expected (; or lf)");
throw CompileException("end of statement expected (; or lf)");
}
}
void MoveIfCurrentTargetIsLocal() {
@@ -233,7 +229,7 @@ public:
}
break;}
case TK_BREAK:
if(_fs->_breaktargets.size() <= 0)Error("'break' has to be in a loop block");
if(_fs->_breaktargets.size() <= 0)throw CompileException("'break' has to be in a loop block");
if(_fs->_breaktargets.top() > 0){
_fs->AddInstruction(_OP_POPTRAP, _fs->_breaktargets.top(), 0);
}
@@ -243,7 +239,7 @@ public:
Lex();
break;
case TK_CONTINUE:
if(_fs->_continuetargets.size() <= 0)Error("'continue' has to be in a loop block");
if(_fs->_continuetargets.size() <= 0)throw CompileException("'continue' has to be in a loop block");
if(_fs->_continuetargets.top() > 0) {
_fs->AddInstruction(_OP_POPTRAP, _fs->_continuetargets.top(), 0);
}
@@ -356,19 +352,19 @@ public:
SQInteger op = _token;
SQInteger ds = _exst._deref;
bool freevar = _exst._freevar;
if(ds == DEREF_NO_DEREF) Error("can't assign expression");
if(ds == DEREF_NO_DEREF) throw CompileException("can't assign expression");
Lex(); Expression();
switch(op){
case TK_NEWSLOT:
if(freevar) Error("free variables cannot be modified");
if(freevar) throw CompileException("free variables cannot be modified");
if(ds == DEREF_FIELD)
EmitDerefOp(_OP_NEWSLOT);
else //if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local
Error("can't 'create' a local slot");
throw CompileException("can't 'create' a local slot");
break;
case '=': //ASSIGN
if(freevar) Error("free variables cannot be modified");
if(freevar) throw CompileException("free variables cannot be modified");
if(ds == DEREF_FIELD)
EmitDerefOp(_OP_SET);
else {//if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local
@@ -533,7 +529,7 @@ public:
if(_token == TK_PARENT) {
Lex();
if(!NeedGet())
Error("parent cannot be set");
throw CompileException("parent cannot be set");
SQInteger src = _fs->PopTarget();
_fs->AddInstruction(_OP_GETPARENT, _fs->PushTarget(), src);
}
@@ -546,7 +542,7 @@ public:
}
break;
case '[':
if(_lex._prevtoken == '\n') Error("cannot brake deref/or comma needed after [exp]=exp slot declaration");
if(_lex._prevtoken == '\n') throw CompileException("cannot brake deref/or comma needed after [exp]=exp slot declaration");
Lex(); Expression(); Expect(']');
pos = -1;
if(NeedGet()) Emit2ArgsOP(_OP_GET);
@@ -598,7 +594,7 @@ public:
switch(_token)
{
case TK_STRING_LITERAL: {
_fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(_fs->CreateString(_lex._svalue,_lex._longstr.size()-1)));
_fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(_fs->CreateString(_lex.View())));
Lex();
}
break;
@@ -618,7 +614,7 @@ public:
SQObject id;
SQObject constant;
switch(_token) {
case TK_IDENTIFIER: id = _fs->CreateString(_lex._svalue); break;
case TK_IDENTIFIER: id = _fs->CreateString(_lex.View()); break;
case TK_THIS: id = _fs->CreateString("this"); break;
case TK_CONSTRUCTOR: id = _fs->CreateString("constructor"); break;
}
@@ -638,7 +634,7 @@ public:
Expect('.'); constid = Expect(TK_IDENTIFIER);
if(!_table(constant)->Get(constid,constval)) {
constval.Null();
Error(fmt::format("invalid constant [{}.{}]", _stringval(id),_stringval(constid)));
throw CompileException(fmt::format("invalid constant [{}.{}]", _stringval(id),_stringval(constid)));
}
}
else {
@@ -742,7 +738,7 @@ public:
case TK_DELEGATE : DelegateExpr(); break;
case '(': Lex(); CommaExpr(); Expect(')');
break;
default: Error("expression expected");
default: throw CompileException("expression expected");
}
return -1;
}
@@ -771,7 +767,7 @@ public:
nargs++;
if(_token == ','){
Lex();
if(_token == ')') Error("expression expected, found ')'");
if(_token == ')') throw CompileException("expression expected, found ')'");
}
}
Lex();
@@ -1082,13 +1078,13 @@ public:
_exst._funcarg = false;
PrefixedExpr();
es = PopExpState();
if(es._deref == DEREF_NO_DEREF) Error("invalid class name");
if(es._deref == DEREF_NO_DEREF) throw CompileException("invalid class name");
if(es._deref == DEREF_FIELD) {
ClassExp();
EmitDerefOp(_OP_NEWSLOT);
_fs->PopTarget();
}
else Error("cannot create a class in a local with the syntax(class <local>)");
else throw CompileException("cannot create a class in a local with the syntax(class <local>)");
}
SQObject ExpectScalar()
{
@@ -1103,7 +1099,7 @@ public:
val._unVal.fFloat = _lex._fvalue;
break;
case TK_STRING_LITERAL:
val = _fs->CreateString(_lex._svalue,_lex._longstr.size()-1);
val = _fs->CreateString(_lex.View());
break;
case '-':
Lex();
@@ -1118,12 +1114,12 @@ public:
val._unVal.fFloat = -_lex._fvalue;
break;
default:
Error("scalar expected : integer,float");
throw CompileException("scalar expected : integer,float");
val._type = OT_NULL; // Silent compile-warning
}
break;
default:
Error("scalar expected : integer,float or string");
throw CompileException("scalar expected : integer,float or string");
val._type = OT_NULL; // Silent compile-warning
}
Lex();
@@ -1226,9 +1222,9 @@ public:
_exst._funcarg = false;
PrefixedExpr();
es = PopExpState();
if(es._deref == DEREF_NO_DEREF) Error("can't delete an expression");
if(es._deref == DEREF_NO_DEREF) throw CompileException("can't delete an expression");
if(es._deref == DEREF_FIELD) Emit2ArgsOP(_OP_DELETE);
else Error("cannot delete a local");
else throw CompileException("cannot delete a local");
}
void PrefixIncDec(SQInteger token)
{
@@ -1255,10 +1251,10 @@ public:
SQInteger defparams = 0;
while(_token!=')') {
if(_token == TK_VARPARAMS) {
if(defparams > 0) Error("function with default parameters cannot have variable number of parameters");
if(defparams > 0) throw CompileException("function with default parameters cannot have variable number of parameters");
funcstate->_varparams = true;
Lex();
if(_token != ')') Error("expected ')'");
if(_token != ')') throw CompileException("expected ')'");
break;
}
else {
@@ -1271,10 +1267,10 @@ public:
defparams++;
}
else {
if(defparams > 0) Error("expected '='");
if(defparams > 0) throw CompileException("expected '='");
}
if(_token == ',') Lex();
else if(_token != ')') Error("expected ')' or ','");
else if(_token != ')') throw CompileException("expected ')' or ','");
}
}
Expect(')');
@@ -1289,7 +1285,7 @@ public:
//outers are treated as implicit local variables
funcstate->AddOuterValue(paramname);
if(_token == ',') Lex();
else if(_token != ')') Error("expected ')' or ','");
else if(_token != ')') throw CompileException("expected ')' or ','");
}
Lex();
}
@@ -1346,7 +1342,7 @@ private:
SQVM *_vm;
};
bool Compile(SQVM *vm,SQLEXREADFUNC rg, SQUserPointer up, const SQChar *sourcename, SQObjectPtr &out, bool raiseerror, bool lineinfo)
bool Compile(SQVM *vm,SQLEXREADFUNC rg, SQUserPointer up, std::string_view sourcename, SQObjectPtr &out, bool raiseerror, bool lineinfo)
{
SQCompiler p(vm, rg, up, sourcename, raiseerror, lineinfo);
return p.Compile(out);
+1 -1
View File
@@ -73,5 +73,5 @@ struct SQVM;
using CompileException = std::runtime_error;
bool Compile(SQVM *vm, SQLEXREADFUNC rg, SQUserPointer up, const SQChar *sourcename, SQObjectPtr &out, bool raiseerror, bool lineinfo);
bool Compile(SQVM *vm, SQLEXREADFUNC rg, SQUserPointer up, std::string_view sourcename, SQObjectPtr &out, bool raiseerror, bool lineinfo);
#endif //_SQCOMPILER_H_
+4 -4
View File
@@ -37,7 +37,7 @@ SQRESULT sq_stackinfos(HSQUIRRELVM v, SQInteger level, SQStackInfos *si)
{
SQInteger cssize = v->_callsstacksize;
if (cssize > level) {
memset(si, 0, sizeof(SQStackInfos));
*si = {};
SQVM::CallInfo &ci = v->_callsstack[cssize-level-1];
switch (type(ci._closure)) {
case OT_CLOSURE:{
@@ -101,15 +101,15 @@ void SQVM::Raise_CompareError(const SQObject &o1, const SQObject &o2)
void SQVM::Raise_ParamTypeError(SQInteger nparam,SQInteger typemask,SQInteger type)
{
SQObjectPtr exptypes = SQString::Create(_ss(this), "", -1);
SQObjectPtr exptypes = SQString::Create(_ss(this), "");
SQInteger found = 0;
for(SQInteger i=0; i<16; i++)
{
SQInteger mask = 0x00000001LL << i;
if(typemask & (mask)) {
if(found>0) StringCat(exptypes,SQString::Create(_ss(this), "|", -1), exptypes);
if(found>0) StringCat(exptypes,SQString::Create(_ss(this), "|"), exptypes);
found ++;
StringCat(exptypes,SQString::Create(_ss(this), IdType2Name((SQObjectType)mask), -1), exptypes);
StringCat(exptypes,SQString::Create(_ss(this), IdType2Name((SQObjectType)mask)), exptypes);
}
}
Raise_Error(fmt::format("parameter {} has an invalid type '{}' ; expected: '{}'", nparam, IdType2Name((SQObjectType)type), _stringval(exptypes)));
+1 -1
View File
@@ -114,7 +114,7 @@ public:
this->~SQFunctionProto();
sq_vm_free(this,size);
}
const SQChar* GetLocal(SQVM *v,SQUnsignedInteger stackbase,SQUnsignedInteger nseq,SQUnsignedInteger nop);
std::optional<std::string_view> GetLocal(SQVM *v,SQUnsignedInteger stackbase,SQUnsignedInteger nseq,SQUnsignedInteger nop);
SQInteger GetLine(SQInstruction *curr);
bool Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write);
static bool Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret);
+5 -10
View File
@@ -110,11 +110,6 @@ SQFuncState::SQFuncState(SQSharedState *ss,SQFuncState *parent)
}
void SQFuncState::Error(const SQChar *err)
{
throw CompileException(err);
}
#ifdef _DEBUG_DUMP
void SQFuncState::Dump(SQFunctionProto *func)
{
@@ -234,7 +229,7 @@ SQInteger SQFuncState::GetConstant(const SQObject &cons)
_nliterals++;
if(_nliterals > MAX_LITERALS) {
val.Null();
Error("internal compiler error: too many literals");
throw CompileException("internal compiler error: too many literals");
}
}
return _integer(val);
@@ -264,7 +259,7 @@ SQInteger SQFuncState::AllocStackPos()
SQInteger npos=_vlocals.size();
_vlocals.push_back(SQLocalVarInfo());
if(_vlocals.size()>((SQUnsignedInteger)_stacksize)) {
if(_stacksize>MAX_FUNC_STACKSIZE) Error("internal compiler error: too many locals");
if(_stacksize>MAX_FUNC_STACKSIZE) throw CompileException("internal compiler error: too many locals");
_stacksize=_vlocals.size();
}
return npos;
@@ -499,9 +494,9 @@ void SQFuncState::AddInstruction(SQInstruction &i)
_instructions.push_back(i);
}
SQObject SQFuncState::CreateString(const SQChar *s,SQInteger len)
SQObject SQFuncState::CreateString(std::string_view s)
{
SQObjectPtr ns(SQString::Create(_sharedstate,s,len));
SQObjectPtr ns(SQString::Create(_sharedstate,s));
_table(_strings)->NewSlot(ns,(SQInteger)1);
return std::move(ns);
}
@@ -539,7 +534,7 @@ SQFunctionProto *SQFuncState::BuildProto()
for(SQUnsignedInteger no = 0; no < _lineinfos.size(); no++) f->_lineinfos[no] = _lineinfos[no];
for(SQUnsignedInteger no = 0; no < _defaultparams.size(); no++) f->_defaultparams[no] = _defaultparams[no];
memcpy(f->_instructions,&_instructions[0],(size_t)_instructions.size()*sizeof(SQInstruction));
std::copy_n(&_instructions[0], _instructions.size(), f->_instructions);
f->_varparams = _varparams;
+1 -2
View File
@@ -11,7 +11,6 @@ struct SQFuncState
#ifdef _DEBUG_DUMP
void Dump(SQFunctionProto *func);
#endif
[[noreturn]] void Error(const SQChar *err);
SQFuncState *PushChildState(SQSharedState *ss);
void PopChildState();
void AddInstruction(SQOpcode _op,SQInteger arg0=0,SQInteger arg1=0,SQInteger arg2=0,SQInteger arg3=0){SQInstruction i(_op,arg0,arg1,arg2,arg3);AddInstruction(i);}
@@ -43,7 +42,7 @@ struct SQFuncState
SQInteger TopTarget();
SQInteger GetUpTarget(SQInteger n);
bool IsLocal(SQUnsignedInteger stkpos);
SQObject CreateString(const SQChar *s,SQInteger len = -1);
SQObject CreateString(std::string_view s);
SQObject CreateTable();
bool IsConstant(const SQObject &name,SQObject &e);
SQInteger _returnexp;
+36 -77
View File
@@ -12,6 +12,7 @@
#include "sqlexer.h"
#include "../../../core/utf8.hpp"
#include "../../../core/string_consumer.hpp"
#include "../../../safeguards.h"
@@ -84,22 +85,16 @@ SQLexer::SQLexer(SQSharedState *ss, SQLEXREADFUNC rg, SQUserPointer up)
_prevtoken = -1;
_curtoken = -1;
_svalue = nullptr;
_nvalue = 0;
_fvalue = 0;
Next();
}
[[noreturn]] void SQLexer::Error(const SQChar *err)
{
throw CompileException(err);
}
void SQLexer::Next()
{
char32_t t = _readf(_up);
if(t > MAX_CHAR) Error("Invalid character");
if(t > MAX_CHAR) throw CompileException("Invalid character");
if(t != 0) {
_currdata = t;
return;
@@ -107,7 +102,7 @@ void SQLexer::Next()
_currdata = SQUIRREL_EOB;
}
const SQChar *SQLexer::Tok2Str(SQInteger tok)
std::optional<std::string_view> SQLexer::Tok2Str(SQInteger tok)
{
SQObjectPtr itr, key, val;
SQInteger nitr;
@@ -116,7 +111,7 @@ const SQChar *SQLexer::Tok2Str(SQInteger tok)
if(((SQInteger)_integer(val)) == tok)
return _stringval(key);
}
return nullptr;
return std::nullopt;
}
void SQLexer::LexBlockComment()
@@ -126,7 +121,7 @@ void SQLexer::LexBlockComment()
switch(CUR_CHAR) {
case '*': { NEXT(); if(CUR_CHAR == '/') { done = true; NEXT(); }}; continue;
case '\n': _currentline++; NEXT(); continue;
case SQUIRREL_EOB: Error("missing \"*/\" in comment");
case SQUIRREL_EOB: throw CompileException("missing \"*/\" in comment");
default: NEXT();
}
}
@@ -195,11 +190,11 @@ SQInteger SQLexer::Lex()
SQInteger stype;
NEXT();
if(CUR_CHAR != '"')
Error("string expected");
throw CompileException("string expected");
if((stype=ReadString('"',true))!=-1) {
RETURN_TOKEN(stype);
}
Error("error parsing the string");
throw CompileException("error parsing the string");
}
case '"':
case '\'': {
@@ -207,7 +202,7 @@ SQInteger SQLexer::Lex()
if((stype=ReadString(CUR_CHAR,false))!=-1){
RETURN_TOKEN(stype);
}
Error("error parsing the string");
throw CompileException("error parsing the string");
}
case '{': case '}': case '(': case ')': case '[': case ']':
case ';': case ',': case '?': case '^': case '~':
@@ -217,7 +212,7 @@ SQInteger SQLexer::Lex()
NEXT();
if (CUR_CHAR != '.'){ RETURN_TOKEN('.') }
NEXT();
if (CUR_CHAR != '.'){ Error("invalid token '..'"); }
if (CUR_CHAR != '.'){ throw CompileException("invalid token '..'"); }
NEXT();
RETURN_TOKEN(TK_VARPARAMS);
case '&':
@@ -263,7 +258,7 @@ SQInteger SQLexer::Lex()
}
else {
SQInteger c = CUR_CHAR;
if (iscntrl((int)c)) Error("unexpected character(control)");
if (iscntrl((int)c)) throw CompileException("unexpected character(control)");
NEXT();
RETURN_TOKEN(c);
}
@@ -274,7 +269,7 @@ SQInteger SQLexer::Lex()
return 0;
}
SQInteger SQLexer::GetIDType(SQChar *s)
SQInteger SQLexer::GetIDType(std::string_view s)
{
SQObjectPtr t;
if(_keywords->Get(SQString::Create(_sharedstate, s), t)) {
@@ -293,10 +288,10 @@ SQInteger SQLexer::ReadString(char32_t ndelim,bool verbatim)
while(CUR_CHAR != ndelim) {
switch(CUR_CHAR) {
case SQUIRREL_EOB:
Error("unfinished string");
throw CompileException("unfinished string");
return -1;
case '\n':
if(!verbatim) Error("newline in a constant");
if(!verbatim) throw CompileException("newline in a constant");
APPEND_CHAR(CUR_CHAR); NEXT();
_currentline++;
break;
@@ -308,18 +303,18 @@ SQInteger SQLexer::ReadString(char32_t ndelim,bool verbatim)
NEXT();
switch(CUR_CHAR) {
case 'x': NEXT(); {
if(!isxdigit(CUR_CHAR)) Error("hexadecimal number expected");
if(!isxdigit(CUR_CHAR)) throw CompileException("hexadecimal number expected");
const SQInteger maxdigits = 4;
SQChar temp[maxdigits+1];
SQInteger n = 0;
char temp[maxdigits];
size_t n = 0;
while(isxdigit(CUR_CHAR) && n < maxdigits) {
temp[n] = CUR_CHAR;
n++;
NEXT();
}
temp[n] = 0;
SQChar *sTemp;
APPEND_CHAR((SQChar)strtoul(temp,&sTemp,16));
auto val = ParseInteger(std::string_view{temp, n}, 16);
if (!val.has_value()) throw CompileException("hexadecimal number expected");
APPEND_CHAR(static_cast<char>(*val));
}
break;
case 't': APPEND_CHAR('\t'); NEXT(); break;
@@ -334,7 +329,7 @@ SQInteger SQLexer::ReadString(char32_t ndelim,bool verbatim)
case '"': APPEND_CHAR('"'); NEXT(); break;
case '\'': APPEND_CHAR('\''); NEXT(); break;
default:
Error("unrecognised escaper char");
throw CompileException("unrecognised escaper char");
break;
}
}
@@ -353,49 +348,16 @@ SQInteger SQLexer::ReadString(char32_t ndelim,bool verbatim)
break;
}
}
TERMINATE_BUFFER();
SQInteger len = _longstr.size()-1;
if(ndelim == '\'') {
if(len == 0) Error("empty constant");
if(len > 1) Error("constant too long");
if(_longstr.empty()) throw CompileException("empty constant");
if(_longstr.size() > 1) throw CompileException("constant too long");
_nvalue = _longstr[0];
return TK_INTEGER;
}
_svalue = &_longstr[0];
return TK_STRING_LITERAL;
}
void LexHexadecimal(const SQChar *s,SQUnsignedInteger *res)
{
*res = 0;
while(*s != 0)
{
if(isdigit(*s)) *res = (*res)*16+((*s++)-'0');
else if(isxdigit(*s)) *res = (*res)*16+(toupper(*s++)-'A'+10);
else { assert(0); }
}
}
void LexInteger(const SQChar *s,SQUnsignedInteger *res)
{
*res = 0;
while(*s != 0)
{
*res = (*res)*10+((*s++)-'0');
}
}
SQInteger scisodigit(SQChar c) { return c >= '0' && c <= '7'; }
void LexOctal(const SQChar *s,SQUnsignedInteger *res)
{
*res = 0;
while(*s != 0)
{
if(scisodigit(*s)) *res = (*res)*8+((*s++)-'0');
else { assert(0); }
}
}
SQInteger scisodigit(char c) { return c >= '0' && c <= '7'; }
SQInteger isexponent(SQInteger c) { return c == 'e' || c=='E'; }
@@ -409,7 +371,6 @@ SQInteger SQLexer::ReadNumber()
#define TSCIENTIFIC 4
#define TOCTAL 5
SQInteger type = TINT, firstchar = CUR_CHAR;
SQChar *sTemp;
INIT_TEMP_STRING();
NEXT();
if(firstchar == '0' && (toupper(CUR_CHAR) == 'X' || scisodigit(CUR_CHAR)) ) {
@@ -419,7 +380,7 @@ SQInteger SQLexer::ReadNumber()
APPEND_CHAR(CUR_CHAR);
NEXT();
}
if(isdigit(CUR_CHAR)) Error("invalid octal number");
if(isdigit(CUR_CHAR)) throw CompileException("invalid octal number");
}
else {
NEXT();
@@ -428,7 +389,7 @@ SQInteger SQLexer::ReadNumber()
APPEND_CHAR(CUR_CHAR);
NEXT();
}
if(_longstr.size() > MAX_HEX_DIGITS) Error("too many digits for an Hex number");
if(_longstr.size() > MAX_HEX_DIGITS) throw CompileException("too many digits for an Hex number");
}
}
else {
@@ -436,7 +397,7 @@ SQInteger SQLexer::ReadNumber()
while (CUR_CHAR == '.' || isdigit(CUR_CHAR) || isexponent(CUR_CHAR)) {
if(CUR_CHAR == '.' || isexponent(CUR_CHAR)) type = TFLOAT;
if(isexponent(CUR_CHAR)) {
if(type != TFLOAT) Error("invalid numeric format");
if(type != TFLOAT) throw CompileException("invalid numeric format");
type = TSCIENTIFIC;
APPEND_CHAR(CUR_CHAR);
NEXT();
@@ -444,27 +405,29 @@ SQInteger SQLexer::ReadNumber()
APPEND_CHAR(CUR_CHAR);
NEXT();
}
if(!isdigit(CUR_CHAR)) Error("exponent expected");
if(!isdigit(CUR_CHAR)) throw CompileException("exponent expected");
}
APPEND_CHAR(CUR_CHAR);
NEXT();
}
}
TERMINATE_BUFFER();
switch(type) {
case TSCIENTIFIC:
case TFLOAT:
_fvalue = (SQFloat)strtod(&_longstr[0],&sTemp);
case TFLOAT: {
std::string str{View()};
char *sTemp;
_fvalue = (SQFloat)strtod(str.c_str(),&sTemp);
return TK_FLOAT;
}
case TINT:
LexInteger(&_longstr[0],(SQUnsignedInteger *)&_nvalue);
_nvalue = ParseInteger<SQUnsignedInteger>(View(), 10).value_or(0);
return TK_INTEGER;
case THEX:
LexHexadecimal(&_longstr[0],(SQUnsignedInteger *)&_nvalue);
_nvalue = ParseInteger<SQUnsignedInteger>(View(), 16).value_or(0);
return TK_INTEGER;
case TOCTAL:
LexOctal(&_longstr[0],(SQUnsignedInteger *)&_nvalue);
_nvalue = ParseInteger<SQUnsignedInteger>(View(), 8).value_or(0);
return TK_INTEGER;
}
return 0;
@@ -478,10 +441,6 @@ SQInteger SQLexer::ReadID()
APPEND_CHAR(CUR_CHAR);
NEXT();
} while(isalnum(CUR_CHAR) || CUR_CHAR == '_');
TERMINATE_BUFFER();
res = GetIDType(&_longstr[0]);
if(res == TK_IDENTIFIER || res == TK_CONSTRUCTOR) {
_svalue = &_longstr[0];
}
res = GetIDType(View());
return res;
}
+5 -6
View File
@@ -6,11 +6,10 @@ struct SQLexer
{
~SQLexer();
SQLexer(SQSharedState *ss,SQLEXREADFUNC rg,SQUserPointer up);
[[noreturn]] void Error(const SQChar *err);
SQInteger Lex();
const SQChar *Tok2Str(SQInteger tok);
std::optional<std::string_view> Tok2Str(SQInteger tok);
private:
SQInteger GetIDType(SQChar *s);
SQInteger GetIDType(std::string_view s);
SQInteger ReadString(char32_t ndelim,bool verbatim);
SQInteger ReadNumber();
void LexBlockComment();
@@ -20,21 +19,21 @@ private:
SQTable *_keywords;
void INIT_TEMP_STRING() { _longstr.resize(0); }
void APPEND_CHAR(char32_t c);
void TERMINATE_BUFFER() { _longstr.push_back('\0'); }
public:
SQInteger _prevtoken;
SQInteger _currentline;
SQInteger _lasttokenline;
SQInteger _currentcolumn;
const SQChar *_svalue;
SQInteger _nvalue;
SQFloat _fvalue;
SQLEXREADFUNC _readf;
SQUserPointer _up;
char32_t _currdata;
SQSharedState *_sharedstate;
sqvector<SQChar> _longstr;
sqvector<char> _longstr;
std::string_view View() const { return std::string_view(_longstr._vals, _longstr.size()); }
};
#endif
+22 -22
View File
@@ -18,7 +18,7 @@
#include "../../../safeguards.h"
const SQChar *IdType2Name(SQObjectType type)
std::string_view IdType2Name(SQObjectType type)
{
switch(_RAW_TYPE(type))
{
@@ -42,25 +42,25 @@ const SQChar *IdType2Name(SQObjectType type)
case _RT_INSTANCE: return "instance";
case _RT_WEAKREF: return "weakref";
default:
return nullptr;
NOT_REACHED();
}
}
const SQChar *GetTypeName(const SQObjectPtr &obj1)
std::string_view GetTypeName(const SQObjectPtr &obj1)
{
return IdType2Name(type(obj1));
}
SQString *SQString::Create(SQSharedState *ss,const SQChar *s,SQInteger len)
SQString *SQString::Create(SQSharedState *ss,std::string_view s)
{
SQString *str=ADD_STRING(ss,s,len);
SQString *str=ss->_stringtable->Add(s);
str->_sharedstate=ss;
return str;
}
void SQString::Release()
{
REMOVE_STRING(_sharedstate,this);
_sharedstate->_stringtable->Remove(this);
}
SQInteger SQString::Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval)
@@ -202,24 +202,21 @@ void SQArray::Extend(const SQArray *a){
Append(a->_values[i]);
}
const SQChar* SQFunctionProto::GetLocal(SQVM *vm,SQUnsignedInteger stackbase,SQUnsignedInteger nseq,SQUnsignedInteger nop)
std::optional<std::string_view> SQFunctionProto::GetLocal(SQVM *vm,SQUnsignedInteger stackbase,SQUnsignedInteger nseq,SQUnsignedInteger nop)
{
SQUnsignedInteger nvars=_nlocalvarinfos;
const SQChar *res=nullptr;
if(nvars>=nseq){
for(SQUnsignedInteger i=0;i<nvars;i++){
if(_localvarinfos[i]._start_op<=nop && _localvarinfos[i]._end_op>=nop)
{
if(_localvarinfos[i]._start_op<=nop && _localvarinfos[i]._end_op>=nop) {
if(nseq==0){
vm->Push(vm->_stack[stackbase+_localvarinfos[i]._pos]);
res=_stringval(_localvarinfos[i]._name);
break;
return _stringval(_localvarinfos[i]._name);
}
nseq--;
}
}
}
return res;
return std::nullopt;
}
SQInteger SQFunctionProto::GetLine(SQInstruction *curr)
@@ -273,10 +270,13 @@ bool WriteObject(HSQUIRRELVM v,SQUserPointer up,SQWRITEFUNC write,SQObjectPtr &o
{
_CHECK_IO(SafeWrite(v,write,up,&type(o),sizeof(SQObjectType)));
switch(type(o)){
case OT_STRING:
_CHECK_IO(SafeWrite(v,write,up,&_string(o)->_len,sizeof(SQInteger)));
_CHECK_IO(SafeWrite(v,write,up,_stringval(o),_string(o)->_len));
case OT_STRING: {
auto str = _string(o)->Span();
SQInteger len = str.size();
_CHECK_IO(SafeWrite(v,write,up,&len,sizeof(len)));
_CHECK_IO(SafeWrite(v,write,up,str.data(),len));
break;
}
case OT_INTEGER:
_CHECK_IO(SafeWrite(v,write,up,&_integer(o),sizeof(SQInteger)));break;
case OT_FLOAT:
@@ -297,11 +297,11 @@ bool ReadObject(HSQUIRRELVM v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &o)
switch(t){
case OT_STRING:{
SQInteger len;
_CHECK_IO(SafeRead(v,read,up,&len,sizeof(SQInteger)));
_CHECK_IO(SafeRead(v,read,up,_ss(v)->GetScratchPad(len),len));
o=SQString::Create(_ss(v),_ss(v)->GetScratchPad(-1),len);
}
_CHECK_IO(SafeRead(v,read,up,&len,sizeof(len)));
_CHECK_IO(SafeRead(v,read,up,_ss(v)->GetScratchPad(len).data(),len));
o=SQString::Create(_ss(v),std::string_view(_ss(v)->GetScratchPad(-1).data(),len));
break;
}
case OT_INTEGER:{
SQInteger i;
_CHECK_IO(SafeRead(v,read,up,&i,sizeof(SQInteger))); o = i; break;
@@ -323,7 +323,7 @@ bool ReadObject(HSQUIRRELVM v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &o)
bool SQClosure::Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write)
{
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_HEAD));
_CHECK_IO(WriteTag(v,write,up,sizeof(SQChar)));
_CHECK_IO(WriteTag(v,write,up,sizeof(char)));
_CHECK_IO(_funcproto(_function)->Save(v,up,write));
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_TAIL));
return true;
@@ -332,7 +332,7 @@ bool SQClosure::Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write)
bool SQClosure::Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret)
{
_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_HEAD));
_CHECK_IO(CheckTag(v,read,up,sizeof(SQChar)));
_CHECK_IO(CheckTag(v,read,up,sizeof(char)));
SQObjectPtr func;
_CHECK_IO(SQFunctionProto::Load(v,up,read,func));
_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_TAIL));
+4 -4
View File
@@ -138,7 +138,7 @@ struct SQObjectPtr;
#define _refcounted(obj) ((obj)._unVal.pRefCounted)
#define _rawval(obj) ((obj)._unVal.raw)
#define _stringval(obj) (obj)._unVal.pString->_val
#define _stringval(obj) (obj)._unVal.pString->View()
#define _userdataval(obj) (obj)._unVal.pUserData->_val
#define tofloat(num) ((type(num)==OT_INTEGER)?(SQFloat)_integer(num):_float(num))
@@ -357,7 +357,7 @@ struct SQObjectPtr : public SQObject
return *this;
}
private:
SQObjectPtr(const SQChar *){} //safety
SQObjectPtr(const char *) = delete; //safety
};
inline void _Swap(SQObject &a,SQObject &b)
@@ -449,8 +449,8 @@ struct SQDelegable : public CHAINABLE_OBJ {
SQUnsignedInteger TranslateIndex(const SQObjectPtr &idx);
typedef sqvector<SQObjectPtr> SQObjectPtrVec;
typedef sqvector<SQInteger> SQIntVec;
const SQChar *GetTypeName(const SQObjectPtr &obj1);
const SQChar *IdType2Name(SQObjectType type);
std::string_view GetTypeName(const SQObjectPtr &obj1);
std::string_view IdType2Name(SQObjectType type);
+1 -1
View File
@@ -87,7 +87,7 @@ enum SQOpcode
};
struct SQInstructionDesc {
const SQChar *name;
std::string_view name;
};
struct SQInstruction
+40 -52
View File
@@ -14,6 +14,7 @@
#include "sqarray.h"
#include "squserdata.h"
#include "sqclass.h"
#include "../../../core/string_consumer.hpp"
#include "../../../safeguards.h"
@@ -32,14 +33,12 @@ SQObjectPtr _minusone_((SQInteger)-1);
_table(_metamethodsmap)->NewSlot(_metamethods->back(),(SQInteger)(_metamethods->size()-1)); \
}
bool CompileTypemask(SQIntVec &res,const SQChar *typemask)
bool CompileTypemask(SQIntVec &res,std::string_view typemask)
{
SQInteger i = 0;
SQInteger mask = 0;
while(typemask[i] != 0) {
switch(typemask[i]){
StringConsumer consumer{typemask};
while (consumer.AnyBytesLeft()) {
switch(consumer.ReadChar()){
case 'o': mask |= _RT_NULL; break;
case 'i': mask |= _RT_INTEGER; break;
case 'f': mask |= _RT_FLOAT; break;
@@ -56,37 +55,32 @@ bool CompileTypemask(SQIntVec &res,const SQChar *typemask)
case 'x': mask |= _RT_INSTANCE; break;
case 'y': mask |= _RT_CLASS; break;
case 'r': mask |= _RT_WEAKREF; break;
case '.': mask = -1; res.push_back(mask); i++; mask = 0; continue;
case ' ': i++; continue; //ignores spaces
case '.': mask = -1; res.push_back(mask); mask = 0; continue;
case ' ': continue; //ignores spaces
default:
return false;
}
i++;
if(typemask[i] == '|') {
i++;
if(typemask[i] == 0)
return false;
if(consumer.ReadCharIf('|')) {
if(!consumer.AnyBytesLeft()) return false;
continue;
}
res.push_back(mask);
mask = 0;
}
return true;
}
SQTable *CreateDefaultDelegate(SQSharedState *ss,SQRegFunction *funcz)
SQTable *CreateDefaultDelegate(SQSharedState *ss,const std::initializer_list<SQRegFunction> &funcz)
{
SQInteger i=0;
SQTable *t=SQTable::Create(ss,0);
while(funcz[i].name!=nullptr){
SQNativeClosure *nc = SQNativeClosure::Create(ss,funcz[i].f);
nc->_nparamscheck = funcz[i].nparamscheck;
nc->_name = SQString::Create(ss,funcz[i].name);
if(funcz[i].typemask && !CompileTypemask(nc->_typecheck,funcz[i].typemask))
for (auto &func : funcz) {
SQNativeClosure *nc = SQNativeClosure::Create(ss,func.f);
nc->_nparamscheck = func.nparamscheck;
nc->_name = SQString::Create(ss,func.name);
if(func.typemask.has_value() && !CompileTypemask(nc->_typecheck,*func.typemask))
return nullptr;
t->NewSlot(SQString::Create(ss,funcz[i].name),nc);
i++;
t->NewSlot(SQString::Create(ss,func.name),nc);
}
return t;
}
@@ -97,8 +91,6 @@ SQSharedState::SQSharedState()
_printfunc = nullptr;
_debuginfo = false;
_notifyallexceptions = false;
_scratchpad=nullptr;
_scratchpadsize=0;
_collectable_free_processing = false;
#ifndef NO_GARBAGE_COLLECTOR
_gc_chain=nullptr;
@@ -212,7 +204,6 @@ SQSharedState::~SQSharedState()
sq_delete(_systemstrings,SQObjectPtrVec);
sq_delete(_metamethods,SQObjectPtrVec);
sq_delete(_stringtable,SQStringTable);
if(_scratchpad)SQ_FREE(_scratchpad,_scratchpadsize);
}
@@ -357,19 +348,16 @@ void SQCollectable::RemoveFromChain(SQCollectable **chain,SQCollectable *c)
}
#endif
SQChar* SQSharedState::GetScratchPad(SQInteger size)
std::span<char> SQSharedState::GetScratchPad(SQInteger size)
{
SQInteger newsize;
if(size>0) {
if(_scratchpadsize < size) {
if(_scratchpad.size() < static_cast<size_t>(size)) {
newsize = size + (size>>1);
_scratchpad = (SQChar *)SQ_REALLOC(_scratchpad,_scratchpadsize,newsize);
_scratchpadsize = newsize;
}else if(_scratchpadsize >= (size<<5)) {
newsize = _scratchpadsize >> 1;
_scratchpad = (SQChar *)SQ_REALLOC(_scratchpad,_scratchpadsize,newsize);
_scratchpadsize = newsize;
_scratchpad.resize(newsize);
}else if(_scratchpad.size() >= static_cast<size_t>(size<<5)) {
newsize = _scratchpad.size() >> 1;
_scratchpad.resize(newsize);
}
}
return _scratchpad;
@@ -550,36 +538,36 @@ void SQStringTable::AllocNodes(SQInteger size)
{
_numofslots = size;
_strings = (SQString**)SQ_MALLOC(sizeof(SQString*)*_numofslots);
memset(_strings,0,sizeof(SQString*)*(size_t)_numofslots);
std::fill_n(_strings, _numofslots, nullptr);
}
SQString *SQStringTable::Add(const SQChar *news,SQInteger len)
static const std::hash<std::string_view> string_table_hash{};
SQString *SQStringTable::Add(std::string_view new_string)
{
if(len<0)
len = (SQInteger)strlen(news);
SQHash h = ::_hashstr(news,(size_t)len)&(_numofslots-1);
size_t len = new_string.size();
auto slot = string_table_hash(new_string) & (_numofslots-1);
SQString *s;
for (s = _strings[h]; s; s = s->_next){
if(s->_len == len && (!memcmp(news,s->_val,(size_t)len)))
return s; //found
for (s = _strings[slot]; s; s = s->_next){
if(s->View() == new_string) return s; //found
}
SQString *t=(SQString *)SQ_MALLOC(len+sizeof(SQString));
new (t) SQString(news, len);
t->_next = _strings[h];
_strings[h] = t;
new (t) SQString(new_string);
t->_next = _strings[slot];
_strings[slot] = t;
_slotused++;
if (_slotused > _numofslots) /* too crowded? */
Resize(_numofslots*2);
return t;
}
SQString::SQString(const SQChar *news, SQInteger len)
SQString::SQString(std::string_view new_string)
{
memcpy(_val,news,(size_t)len);
_val[len] = '\0';
_len = len;
_hash = ::_hashstr(news,(size_t)len);
std::ranges::copy(new_string, _val);
_val[new_string.size()] = '\0';
_len = new_string.size();
_hash = string_table_hash(new_string);
_next = nullptr;
_sharedstate = nullptr;
}
@@ -615,7 +603,7 @@ void SQStringTable::Remove(SQString *bs)
else
_strings[h] = s->_next;
_slotused--;
SQInteger slen = s->_len;
size_t slen = s->View().size();
s->~SQString();
SQ_FREE(s,sizeof(SQString) + slen);
return;
+14 -18
View File
@@ -13,7 +13,7 @@ struct SQStringTable
{
SQStringTable();
~SQStringTable();
SQString *Add(const SQChar *,SQInteger len);
SQString *Add(std::string_view str);
void Remove(SQString *);
private:
void Resize(SQInteger size);
@@ -49,9 +49,6 @@ private:
RefNode **_buckets;
};
#define ADD_STRING(ss,str,len) ss->_stringtable->Add(str,len)
#define REMOVE_STRING(ss,bstr) ss->_stringtable->Remove(bstr)
struct SQObjectPtr;
struct SQSharedState
@@ -59,7 +56,7 @@ struct SQSharedState
SQSharedState();
~SQSharedState();
public:
SQChar* GetScratchPad(SQInteger size);
std::span<char> GetScratchPad(SQInteger size);
SQInteger GetMetaMethodIdxByName(const SQObjectPtr &name);
void DelayFinalFree(SQCollectable *collectable);
#ifndef NO_GARBAGE_COLLECTOR
@@ -84,33 +81,32 @@ public:
#endif
SQObjectPtr _root_vm;
SQObjectPtr _table_default_delegate;
static SQRegFunction _table_default_delegate_funcz[];
static const std::initializer_list<SQRegFunction> _table_default_delegate_funcz;
SQObjectPtr _array_default_delegate;
static SQRegFunction _array_default_delegate_funcz[];
static const std::initializer_list<SQRegFunction> _array_default_delegate_funcz;
SQObjectPtr _string_default_delegate;
static SQRegFunction _string_default_delegate_funcz[];
static const std::initializer_list<SQRegFunction> _string_default_delegate_funcz;
SQObjectPtr _number_default_delegate;
static SQRegFunction _number_default_delegate_funcz[];
static const std::initializer_list<SQRegFunction> _number_default_delegate_funcz;
SQObjectPtr _generator_default_delegate;
static SQRegFunction _generator_default_delegate_funcz[];
static const std::initializer_list<SQRegFunction> _generator_default_delegate_funcz;
SQObjectPtr _closure_default_delegate;
static SQRegFunction _closure_default_delegate_funcz[];
static const std::initializer_list<SQRegFunction> _closure_default_delegate_funcz;
SQObjectPtr _thread_default_delegate;
static SQRegFunction _thread_default_delegate_funcz[];
static const std::initializer_list<SQRegFunction> _thread_default_delegate_funcz;
SQObjectPtr _class_default_delegate;
static SQRegFunction _class_default_delegate_funcz[];
static const std::initializer_list<SQRegFunction> _class_default_delegate_funcz;
SQObjectPtr _instance_default_delegate;
static SQRegFunction _instance_default_delegate_funcz[];
static const std::initializer_list<SQRegFunction> _instance_default_delegate_funcz;
SQObjectPtr _weakref_default_delegate;
static SQRegFunction _weakref_default_delegate_funcz[];
static const std::initializer_list<SQRegFunction> _weakref_default_delegate_funcz;
SQCOMPILERERROR _compilererrorhandler;
SQPRINTFUNCTION _printfunc;
bool _debuginfo;
bool _notifyallexceptions;
private:
SQChar *_scratchpad;
SQInteger _scratchpadsize;
std::vector<char> _scratchpad;
};
#define _sp(s) (_sharedstate->GetScratchPad(s))
@@ -133,6 +129,6 @@ extern SQObjectPtr _false_;
extern SQObjectPtr _one_;
extern SQObjectPtr _minusone_;
bool CompileTypemask(SQIntVec &res,const SQChar *typemask);
bool CompileTypemask(SQIntVec &res,std::string_view typemask);
#endif //_SQSTATE_H_
+8 -14
View File
@@ -2,29 +2,23 @@
#ifndef _SQSTRING_H_
#define _SQSTRING_H_
inline SQHash _hashstr (const SQChar *s, size_t l)
{
SQHash h = (SQHash)l; /* seed */
size_t step = (l>>5)|1; /* if string is too long, don't hash all its chars */
for (; l>=step; l-=step)
h = h ^ ((h<<5)+(h>>2)+(unsigned short)*(s++));
return h;
}
struct SQString : public SQRefCounted
{
SQString(const SQChar *news, SQInteger len);
SQString(std::string_view str);
~SQString(){}
public:
static SQString *Create(SQSharedState *ss, const SQChar *, SQInteger len = -1 );
static SQString *Create(SQSharedState *ss, const std::string &str) { return Create(ss, str.data(), str.size()); }
static SQString *Create(SQSharedState *ss, std::string_view str);
SQInteger Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval);
void Release() override;
SQSharedState *_sharedstate;
SQString *_next; //chain for the string table
std::size_t _hash;
std::string_view View() const { return std::string_view(this->_val, this->_len); }
std::span<char> Span() { return std::span<char>(this->_val, this->_len); }
private:
SQInteger _len;
SQHash _hash;
SQChar _val[1];
char _val[1];
};
+1 -1
View File
@@ -31,7 +31,7 @@ struct SQUserData : SQDelegable
SQInteger _size;
SQRELEASEHOOK _hook;
SQUserPointer _typetag;
SQChar _val[1];
char _val[1];
};
#endif //_SQUSERDATA_H_
+1 -1
View File
@@ -93,7 +93,7 @@ public:
{
_vals[idx].~T();
if(idx < (_size - 1)) {
memmove(static_cast<void *>(&_vals[idx]), &_vals[idx+1], sizeof(T) * (_size - (size_t)idx - 1));
std::move(&_vals[idx + 1], &_vals[_size], &_vals[idx]);
}
_size--;
}
+8 -11
View File
@@ -117,7 +117,6 @@ SQVM::SQVM(SQSharedState *ss)
_in_stackoverflow = false;
_ops_till_suspend = 0;
_ops_till_suspend_error_threshold = INT64_MIN;
_ops_till_suspend_error_label = nullptr;
_callsstack = nullptr;
_callsstacksize = 0;
_alloccallsstacksize = 0;
@@ -198,7 +197,7 @@ bool SQVM::ObjCmp(const SQObjectPtr &o1,const SQObjectPtr &o2,SQInteger &result)
SQObjectPtr res;
switch(type(o1)){
case OT_STRING:
_RET_SUCCEED(strcmp(_stringval(o1),_stringval(o2)));
_RET_SUCCEED(_stringval(o1).compare(_stringval(o2)));
case OT_INTEGER:
/* FS#3954: wrong integer comparison */
_RET_SUCCEED((_integer(o1)<_integer(o2))?-1:(_integer(o1)==_integer(o2))?0:1);
@@ -302,11 +301,7 @@ bool SQVM::StringCat(const SQObjectPtr &str,const SQObjectPtr &obj,SQObjectPtr &
SQObjectPtr a, b;
ToString(str, a);
ToString(obj, b);
SQInteger l = _string(a)->_len , ol = _string(b)->_len;
SQChar *s = _sp(l + ol + 1);
memcpy(s, _stringval(a), (size_t)l);
memcpy(s + l, _stringval(b), (size_t)ol);
dest = SQString::Create(_ss(this), _spval, l + ol);
dest = SQString::Create(_ss(this), fmt::format("{}{}", _stringval(a), _stringval(b)));
return true;
}
@@ -1253,7 +1248,8 @@ bool SQVM::Get(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest,
if(fetchroot) {
if(_rawval(STK(0)) == _rawval(self) &&
type(STK(0)) == type(self)) {
return _table(_roottable)->Get(key,dest);
if (_table(_roottable)->Get(key,dest)) return true;
return _table(_ss(this)->_consts)->Get(key,dest);
}
}
return false;
@@ -1288,9 +1284,10 @@ bool SQVM::FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPt
case OT_STRING:
if(sq_isnumeric(key)){
SQInteger n=tointeger(key);
if(abs((int)n)<_string(self)->_len){
if(n<0)n=_string(self)->_len-n;
dest=SQInteger(_stringval(self)[n]);
std::string_view str = _stringval(self);
if(std::abs(n) < static_cast<SQInteger>(str.size())){
if(n<0)n=str.size()+n;
dest=SQInteger(str[n]);
return true;
}
return false;
+1 -1
View File
@@ -169,7 +169,7 @@ public:
SQBool _can_suspend;
SQInteger _ops_till_suspend;
SQInteger _ops_till_suspend_error_threshold;
const char *_ops_till_suspend_error_label;
std::string_view _ops_till_suspend_error_label;
SQBool _in_stackoverflow;
bool ShouldSuspend()
+7 -1
View File
@@ -91,6 +91,7 @@ add_files(
bridge_gui.cpp
bridge_map.cpp
bridge_map.h
bridge_type.h
build_vehicle_gui.cpp
cachecheck.cpp
cargo_type.h
@@ -187,7 +188,6 @@ add_files(
fios_gui.cpp
fontcache.cpp
fontcache.h
fontdetection.h
framerate_gui.cpp
framerate_type.h
gamelog.cpp
@@ -279,6 +279,10 @@ add_files(
newgrf_animation_type.h
newgrf_badge.cpp
newgrf_badge.h
newgrf_badge_config.cpp
newgrf_badge_config.h
newgrf_badge_gui.cpp
newgrf_badge_gui.h
newgrf_badge_type.h
newgrf_callbacks.h
newgrf_canal.cpp
@@ -450,6 +454,7 @@ add_files(
spritecache.cpp
spritecache.h
spritecache_internal.h
spritecache_type.h
station.cpp
station_base.h
station_cmd.cpp
@@ -458,6 +463,7 @@ add_files(
station_gui.cpp
station_gui.h
station_kdtree.h
station_layout_type.h
station_map.h
station_type.h
statusbar_gui.cpp
+12 -12
View File
@@ -84,7 +84,7 @@ static constexpr NWidgetPart _nested_ai_config_widgets[] = {
/** Window definition for the configure AI window. */
static WindowDesc _ai_config_desc(
WDP_CENTER, nullptr, 0, 0,
WDP_CENTER, {}, 0, 0,
WC_GAME_OPTIONS, WC_NONE,
{},
_nested_ai_config_widgets
@@ -142,7 +142,7 @@ struct AIConfigWindow : public Window {
case WID_AIC_LIST:
this->line_height = GetCharacterHeight(FS_NORMAL) + padding.height;
resize.height = this->line_height;
fill.height = resize.height = this->line_height;
size.height = 8 * this->line_height;
break;
}
@@ -218,7 +218,7 @@ struct AIConfigWindow : public Window {
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((TextfileType)(widget - WID_AIC_TEXTFILE), this->selected_slot);
ShowScriptTextfileWindow(this, static_cast<TextfileType>(widget - WID_AIC_TEXTFILE), this->selected_slot);
return;
}
@@ -250,23 +250,23 @@ struct AIConfigWindow : public Window {
}
case WID_AIC_LIST: { // Select a slot
this->selected_slot = (CompanyID)this->vscroll->GetScrolledRowFromWidget(pt.y, this, widget);
this->selected_slot = static_cast<CompanyID>(this->vscroll->GetScrolledRowFromWidget(pt.y, this, widget));
this->InvalidateData();
if (click_count > 1 && IsEditable(this->selected_slot)) ShowScriptListWindow((CompanyID)this->selected_slot, _ctrl_pressed);
if (click_count > 1 && IsEditable(this->selected_slot)) ShowScriptListWindow(this->selected_slot, _ctrl_pressed);
break;
}
case WID_AIC_MOVE_UP:
if (IsEditable(this->selected_slot) && IsEditable((CompanyID)(this->selected_slot - 1))) {
if (IsEditable(this->selected_slot) && IsEditable(static_cast<CompanyID>(this->selected_slot - 1))) {
std::swap(GetGameSettings().script_config.ai[this->selected_slot], GetGameSettings().script_config.ai[this->selected_slot - 1]);
this->selected_slot = CompanyID(this->selected_slot - 1);
this->selected_slot = static_cast<CompanyID>(this->selected_slot - 1);
this->vscroll->ScrollTowards(this->selected_slot.base());
this->InvalidateData();
}
break;
case WID_AIC_MOVE_DOWN:
if (IsEditable(this->selected_slot) && IsEditable((CompanyID)(this->selected_slot + 1))) {
if (IsEditable(this->selected_slot) && IsEditable(static_cast<CompanyID>(this->selected_slot + 1))) {
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());
@@ -282,11 +282,11 @@ struct AIConfigWindow : public Window {
}
case WID_AIC_CHANGE: // choose other AI
if (IsEditable(this->selected_slot)) ShowScriptListWindow((CompanyID)this->selected_slot, _ctrl_pressed);
if (IsEditable(this->selected_slot)) ShowScriptListWindow(this->selected_slot, _ctrl_pressed);
break;
case WID_AIC_CONFIGURE: // change the settings for an AI
ShowScriptSettingsWindow((CompanyID)this->selected_slot);
ShowScriptSettingsWindow(this->selected_slot);
break;
case WID_AIC_CONTENT_DOWNLOAD:
@@ -320,8 +320,8 @@ struct AIConfigWindow : public Window {
this->SetWidgetDisabledState(WID_AIC_INCREASE_INTERVAL, GetGameSettings().difficulty.competitors_interval == MAX_COMPETITORS_INTERVAL);
this->SetWidgetDisabledState(WID_AIC_CHANGE, !IsEditable(this->selected_slot));
this->SetWidgetDisabledState(WID_AIC_CONFIGURE, this->selected_slot == CompanyID::Invalid() || config->GetConfigList()->empty());
this->SetWidgetDisabledState(WID_AIC_MOVE_UP, !IsEditable(this->selected_slot) || !IsEditable((CompanyID)(this->selected_slot - 1)));
this->SetWidgetDisabledState(WID_AIC_MOVE_DOWN, !IsEditable(this->selected_slot) || !IsEditable((CompanyID)(this->selected_slot + 1)));
this->SetWidgetDisabledState(WID_AIC_MOVE_UP, !IsEditable(this->selected_slot) || !IsEditable(static_cast<CompanyID>(this->selected_slot - 1)));
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 = TFT_CONTENT_BEGIN; tft < TFT_CONTENT_END; tft++) {
+18 -18
View File
@@ -27,14 +27,14 @@ static bool CheckAPIVersion(const std::string &api_version)
return std::ranges::find(AIInfo::ApiVersions, api_version) != std::end(AIInfo::ApiVersions);
}
template <> SQInteger PushClassName<AIInfo, ScriptType::AI>(HSQUIRRELVM vm) { sq_pushstring(vm, "AIInfo", -1); return 1; }
template <> SQInteger PushClassName<AIInfo, ScriptType::AI>(HSQUIRRELVM vm) { sq_pushstring(vm, "AIInfo"); return 1; }
/* static */ void AIInfo::RegisterAPI(Squirrel *engine)
/* static */ void AIInfo::RegisterAPI(Squirrel &engine)
{
/* Create the AIInfo class, and add the RegisterAI function */
DefSQClass<AIInfo, ScriptType::AI> SQAIInfo("AIInfo");
SQAIInfo.PreRegister(engine);
SQAIInfo.AddConstructor<void (AIInfo::*)(), 1>(engine, "x");
SQAIInfo.AddConstructor<void (AIInfo::*)()>(engine, "x");
SQAIInfo.DefSQAdvancedMethod(engine, &AIInfo::AddSetting, "AddSetting");
SQAIInfo.DefSQAdvancedMethod(engine, &AIInfo::AddLabels, "AddLabels");
SQAIInfo.DefSQConst(engine, ScriptConfigFlags{}.base(), "CONFIG_NONE");
@@ -50,8 +50,8 @@ template <> SQInteger PushClassName<AIInfo, ScriptType::AI>(HSQUIRRELVM vm) { sq
SQAIInfo.DefSQConst(engine, ScriptConfigFlags{ScriptConfigFlag::InGame}.base(), "AICONFIG_INGAME");
SQAIInfo.PostRegister(engine);
engine->AddMethod("RegisterAI", &AIInfo::Constructor, 2, "tx");
engine->AddMethod("RegisterDummyAI", &AIInfo::DummyConstructor, 2, "tx");
engine.AddMethod("RegisterAI", &AIInfo::Constructor, "tx");
engine.AddMethod("RegisterDummyAI", &AIInfo::DummyConstructor, "tx");
}
/* static */ SQInteger AIInfo::Constructor(HSQUIRRELVM vm)
@@ -61,11 +61,12 @@ template <> SQInteger PushClassName<AIInfo, ScriptType::AI>(HSQUIRRELVM vm) { sq
if (SQ_FAILED(sq_getinstanceup(vm, 2, &instance, nullptr)) || instance == nullptr) return sq_throwerror(vm, "Pass an instance of a child class of AIInfo to RegisterAI");
AIInfo *info = (AIInfo *)instance;
SQInteger res = ScriptInfo::Constructor(vm, info);
SQInteger res = ScriptInfo::Constructor(vm, *info);
if (res != 0) return res;
if (info->engine->MethodExists(info->SQ_instance, "MinVersionToLoad")) {
if (!info->engine->CallIntegerMethod(info->SQ_instance, "MinVersionToLoad", &info->min_loadable_version, MAX_GET_OPS)) return SQ_ERROR;
if (info->min_loadable_version < 0) return SQ_ERROR;
} else {
info->min_loadable_version = info->GetVersion();
}
@@ -89,7 +90,7 @@ template <> SQInteger PushClassName<AIInfo, ScriptType::AI>(HSQUIRRELVM vm) { sq
/* Remove the link to the real instance, else it might get deleted by RegisterAI() */
sq_setinstanceup(vm, 2, nullptr);
/* Register the AI to the base system */
info->GetScanner()->RegisterScript(info);
info->GetScanner()->RegisterScript(std::unique_ptr<AIInfo>{info});
return 0;
}
@@ -101,13 +102,13 @@ template <> SQInteger PushClassName<AIInfo, ScriptType::AI>(HSQUIRRELVM vm) { sq
AIInfo *info = (AIInfo *)instance;
info->api_version = *std::rbegin(AIInfo::ApiVersions);
SQInteger res = ScriptInfo::Constructor(vm, info);
SQInteger res = ScriptInfo::Constructor(vm, *info);
if (res != 0) return res;
/* Remove the link to the real instance, else it might get deleted by RegisterAI() */
sq_setinstanceup(vm, 2, nullptr);
/* Register the AI to the base system */
static_cast<AIScannerInfo *>(info->GetScanner())->SetDummyAI(info);
static_cast<AIScannerInfo *>(info->GetScanner())->SetDummyAI(std::unique_ptr<AIInfo>(info));
return 0;
}
@@ -124,33 +125,32 @@ bool AIInfo::CanLoadFromVersion(int version) const
}
/* static */ void AILibrary::RegisterAPI(Squirrel *engine)
/* static */ void AILibrary::RegisterAPI(Squirrel &engine)
{
/* Create the AILibrary class, and add the RegisterLibrary function */
engine->AddClassBegin("AILibrary");
engine->AddClassEnd();
engine->AddMethod("RegisterLibrary", &AILibrary::Constructor, 2, "tx");
engine.AddClassBegin("AILibrary");
engine.AddClassEnd();
engine.AddMethod("RegisterLibrary", &AILibrary::Constructor, "tx");
}
/* static */ SQInteger AILibrary::Constructor(HSQUIRRELVM vm)
{
/* Create a new library */
AILibrary *library = new AILibrary();
auto library = std::make_unique<AILibrary>();
SQInteger res = ScriptInfo::Constructor(vm, library);
SQInteger res = ScriptInfo::Constructor(vm, *library);
if (res != 0) {
delete library;
return res;
}
/* Cache the category */
if (!library->CheckMethod("GetCategory") || !library->engine->CallStringMethod(library->SQ_instance, "GetCategory", &library->category, MAX_GET_OPS)) {
delete library;
return SQ_ERROR;
}
/* Register the Library to the base system */
library->GetScanner()->RegisterScript(library);
ScriptScanner *scanner = library->GetScanner();
scanner->RegisterScript(std::move(library));
return 0;
}
+2 -2
View File
@@ -23,7 +23,7 @@ public:
/**
* Register the functions of this class.
*/
static void RegisterAPI(Squirrel *engine);
static void RegisterAPI(Squirrel &engine);
/**
* Create an AI, using this AIInfo as start-template.
@@ -64,7 +64,7 @@ public:
/**
* Register the functions of this class.
*/
static void RegisterAPI(Squirrel *engine);
static void RegisterAPI(Squirrel &engine);
/**
* Create an AI, using this AIInfo as start-template.
+4 -4
View File
@@ -27,7 +27,7 @@
#include "table/strings.h"
/* Manually include the Text glue. */
#include "../script/api/template/template_text.hpp.sq"
#include "../script/api/template/template_text.sq.hpp"
/* Convert all AI related classes to Squirrel data. */
#include "../script/api/ai/ai_includes.hpp"
@@ -43,7 +43,7 @@ void AIInstance::Initialize(AIInfo *info)
this->api_version = info->GetAPIVersion();
/* Register the AIController (including the "import" command) */
SQAIController_Register(this->engine);
SQAIController_Register(*this->engine);
ScriptInstance::Initialize(info->GetMainScript(), info->GetInstanceName(), _current_company);
}
@@ -53,7 +53,7 @@ void AIInstance::RegisterAPI()
ScriptInstance::RegisterAPI();
/* Register all classes */
SQAI_RegisterAll(this->engine);
SQAI_RegisterAll(*this->engine);
if (!this->LoadCompatibilityScripts(AI_DIR, AIInfo::ApiVersions)) this->Died();
}
@@ -83,7 +83,7 @@ void AIInstance::Died()
void AIInstance::LoadDummyScript()
{
ScriptAllocatorScope alloc_scope(this->engine);
ScriptAllocatorScope alloc_scope(this->engine.get());
Script_CreateDummy(this->engine->GetVM(), STR_ERROR_AI_NO_AI_FOUND, "AI");
}
+14 -22
View File
@@ -22,39 +22,31 @@
#include "../safeguards.h"
AIScannerInfo::AIScannerInfo() :
ScriptScanner(),
info_dummy(nullptr)
{
}
AIScannerInfo::AIScannerInfo() = default;
AIScannerInfo::~AIScannerInfo() = default;
void AIScannerInfo::Initialize()
{
ScriptScanner::Initialize("AIScanner");
ScriptAllocatorScope alloc_scope(this->engine);
ScriptAllocatorScope alloc_scope(this->engine.get());
/* Create the dummy AI */
this->main_script = "%_dummy";
Script_CreateDummyInfo(this->engine->GetVM(), "AI", "ai");
}
void AIScannerInfo::SetDummyAI(class AIInfo *info)
void AIScannerInfo::SetDummyAI(std::unique_ptr<class AIInfo> &&info)
{
this->info_dummy = info;
this->info_dummy = std::move(info);
}
AIScannerInfo::~AIScannerInfo()
std::string AIScannerInfo::GetScriptName(ScriptInfo &info)
{
delete this->info_dummy;
return info.GetName();
}
std::string AIScannerInfo::GetScriptName(ScriptInfo *info)
{
return info->GetName();
}
void AIScannerInfo::RegisterAPI(class Squirrel *engine)
void AIScannerInfo::RegisterAPI(class Squirrel &engine)
{
AIInfo::RegisterAPI(engine);
}
@@ -63,7 +55,7 @@ AIInfo *AIScannerInfo::SelectRandomAI() const
{
if (_game_mode == GM_MENU) {
Debug(script, 0, "The intro game should not use AI, loading 'dummy' AI.");
return this->info_dummy;
return this->info_dummy.get();
}
/* Filter for AIs suitable as Random AI. */
@@ -72,7 +64,7 @@ AIInfo *AIScannerInfo::SelectRandomAI() const
uint num_random_ais = std::ranges::distance(random_ais);
if (num_random_ais == 0) {
Debug(script, 0, "No suitable AI found, loading 'dummy' AI.");
return this->info_dummy;
return this->info_dummy.get();
}
/* Pick a random AI */
@@ -125,13 +117,13 @@ void AIScannerLibrary::Initialize()
ScriptScanner::Initialize("AIScanner");
}
std::string AIScannerLibrary::GetScriptName(ScriptInfo *info)
std::string AIScannerLibrary::GetScriptName(ScriptInfo &info)
{
AILibrary *library = static_cast<AILibrary *>(info);
return fmt::format("{}.{}", library->GetCategory(), library->GetInstanceName());
AILibrary &library = static_cast<AILibrary &>(info);
return fmt::format("{}.{}", library.GetCategory(), library.GetInstanceName());
}
void AIScannerLibrary::RegisterAPI(class Squirrel *engine)
void AIScannerLibrary::RegisterAPI(class Squirrel &engine)
{
AILibrary::RegisterAPI(engine);
}
+10 -10
View File
@@ -37,17 +37,17 @@ public:
/**
* Set the Dummy AI.
*/
void SetDummyAI(class AIInfo *info);
void SetDummyAI(std::unique_ptr<class AIInfo> &&info);
protected:
std::string GetScriptName(ScriptInfo *info) override;
const char *GetFileName() const override { return PATHSEP "info.nut"; }
std::string GetScriptName(ScriptInfo &info) override;
std::string_view GetFileName() const override { return PATHSEP "info.nut"; }
Subdirectory GetDirectory() const override { return AI_DIR; }
const char *GetScannerName() const override { return "AIs"; }
void RegisterAPI(class Squirrel *engine) override;
std::string_view GetScannerName() const override { return "AIs"; }
void RegisterAPI(class Squirrel &engine) override;
private:
AIInfo *info_dummy; ///< The dummy AI.
std::unique_ptr<AIInfo> info_dummy; ///< The dummy AI.
};
class AIScannerLibrary : public ScriptScanner {
@@ -63,11 +63,11 @@ public:
class AILibrary *FindLibrary(const std::string &library, int version);
protected:
std::string GetScriptName(ScriptInfo *info) override;
const char *GetFileName() const override { return PATHSEP "library.nut"; }
std::string GetScriptName(ScriptInfo &info) override;
std::string_view GetFileName() const override { return PATHSEP "library.nut"; }
Subdirectory GetDirectory() const override { return AI_LIBRARY_DIR; }
const char *GetScannerName() const override { return "AI Libraries"; }
void RegisterAPI(class Squirrel *engine) override;
std::string_view GetScannerName() const override { return "AI Libraries"; }
void RegisterAPI(class Squirrel &engine) override;
};
#endif /* AI_SCANNER_HPP */
+27 -16
View File
@@ -48,10 +48,7 @@
void Aircraft::UpdateDeltaXY()
{
this->x_offs = -1;
this->y_offs = -1;
this->x_extent = 2;
this->y_extent = 2;
this->bounds = {{-1, -1, 0}, {2, 2, 0}, {}};
switch (this->subtype) {
default: NOT_REACHED();
@@ -64,21 +61,21 @@ void Aircraft::UpdateDeltaXY()
case LANDING:
case HELILANDING:
case FLYING:
this->x_extent = 24;
this->y_extent = 24;
/* Bounds are not centred on the aircraft. */
this->bounds.extent.x = 24;
this->bounds.extent.y = 24;
break;
}
this->z_extent = 5;
this->bounds.extent.z = 5;
break;
case AIR_SHADOW:
this->z_extent = 1;
this->x_offs = 0;
this->y_offs = 0;
this->bounds.extent.z = 1;
this->bounds.origin = {};
break;
case AIR_ROTOR:
this->z_extent = 1;
this->bounds.extent.z = 1;
break;
}
}
@@ -175,7 +172,7 @@ void Aircraft::GetImage(Direction direction, EngineImageType image_type, Vehicle
{
uint8_t spritenum = this->spritenum;
if (is_custom_sprite(spritenum)) {
if (IsCustomVehicleSpriteNum(spritenum)) {
GetCustomVehicleSprite(this, direction, image_type, result);
if (result->IsValid()) return;
@@ -191,7 +188,7 @@ void GetRotorImage(const Aircraft *v, EngineImageType image_type, VehicleSpriteS
assert(v->subtype == AIR_HELICOPTER);
const Aircraft *w = v->Next()->Next();
if (is_custom_sprite(v->spritenum)) {
if (IsCustomVehicleSpriteNum(v->spritenum)) {
GetCustomRotorSprite(v, image_type, result);
if (result->IsValid()) return;
}
@@ -205,7 +202,7 @@ static void GetAircraftIcon(EngineID engine, EngineImageType image_type, Vehicle
const Engine *e = Engine::Get(engine);
uint8_t spritenum = e->u.air.image_index;
if (is_custom_sprite(spritenum)) {
if (IsCustomVehicleSpriteNum(spritenum)) {
GetCustomVehicleIcon(engine, DIR_W, image_type, result);
if (result->IsValid()) return;
@@ -1125,6 +1122,15 @@ static bool AircraftController(Aircraft *v)
}
if (amd.flags.Test(AirportMovingDataFlag::Land)) {
if (st->airport.blocks.Test(AirportBlock::Zeppeliner)) {
/* Zeppeliner blocked the runway, abort landing */
v->state = FLYING;
UpdateAircraftCache(v);
SetAircraftPosition(v, gp.x, gp.y, GetAircraftFlightLevel(v));
v->pos = v->previous_pos;
continue;
}
if (st->airport.tile == INVALID_TILE) {
/* Airport has been removed, abort the landing procedure */
v->state = FLYING;
@@ -1430,7 +1436,7 @@ static void AircraftLandAirplane(Aircraft *v)
v->UpdateDeltaXY();
AirportTileAnimationTrigger(st, vt, AAT_STATION_AIRPLANE_LAND);
TriggerAirportTileAnimation(st, vt, AirportAnimationTrigger::AirplaneTouchdown);
if (!PlayVehicleSound(v, VSE_TOUCHDOWN)) {
SndPlayVehicleFx(SND_17_SKID_PLANE, v);
@@ -1668,7 +1674,7 @@ static void AircraftEventHandler_Flying(Aircraft *v, const AirportFTAClass *apc)
if (current->heading == landingtype) {
/* save speed before, since if AirportHasBlock is false, it resets them to 0
* we don't want that for plane in air
* hack for speed thingie */
* hack for speed thingy */
uint16_t tcur_speed = v->cur_speed;
uint16_t tsubspeed = v->subspeed;
if (!AirportHasBlock(v, current, apc)) {
@@ -1782,6 +1788,11 @@ static void AirportClearBlock(const Aircraft *v, const AirportFTAClass *apc)
if (apc->layout[v->previous_pos].blocks != apc->layout[v->pos].blocks) {
Station *st = Station::Get(v->targetairport);
if (st->airport.blocks.Test(AirportBlock::Zeppeliner) &&
apc->layout[v->previous_pos].blocks == AirportBlock::RunwayIn) {
return;
}
st->airport.blocks.Reset(apc->layout[v->previous_pos].blocks);
}
}
+1 -1
View File
@@ -82,7 +82,7 @@ void DrawAircraftImage(const Vehicle *v, const Rect &r, VehicleID selection, Eng
int x_offs = UnScaleGUI(rect.left);
int x = rtl ? r.right - width - x_offs : r.left - x_offs;
/* This magic -1 offset is related to the sprite_y_offsets in build_vehicle_gui.cpp */
int y = ScaleSpriteTrad(-1) + CenterBounds(r.top, r.bottom, 0);
int y = ScaleSpriteTrad(-1) + CentreBounds(r.top, r.bottom, 0);
bool helicopter = v->subtype == AIR_HELICOPTER;
int heli_offs = 0;
+2 -1
View File
@@ -44,7 +44,7 @@ enum AirportTypes : uint8_t {
};
/** Flags for airport movement data. */
enum AirportMovingDataFlag : uint8_t {
enum class AirportMovingDataFlag : uint8_t {
NoSpeedClamp, ///< No speed restrictions.
Takeoff, ///< Takeoff movement.
SlowTurn, ///< Turn slowly (mostly used in the air).
@@ -127,6 +127,7 @@ enum class AirportBlock : uint8_t {
/* end of new blocks */
Nothing = 30,
Zeppeliner = 62, ///< Block for the zeppeliner disaster vehicle.
AirportClosed = 63, ///< Dummy block for indicating a closed airport.
};
using AirportBlocks = EnumBitSet<AirportBlock, uint64_t>;
+9 -9
View File
@@ -21,7 +21,7 @@
#include "company_base.h"
#include "station_type.h"
#include "newgrf_airport.h"
#include "newgrf_badge.h"
#include "newgrf_badge_gui.h"
#include "newgrf_callbacks.h"
#include "dropdown_type.h"
#include "dropdown_func.h"
@@ -204,9 +204,9 @@ static constexpr NWidgetPart _nested_air_toolbar_widgets[] = {
NWidget(WWT_STICKYBOX, COLOUR_DARK_GREEN),
EndContainer(),
NWidget(NWID_HORIZONTAL),
NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_AT_AIRPORT), SetFill(0, 1), SetMinimalSize(42, 22), SetSpriteTip(SPR_IMG_AIRPORT, STR_TOOLBAR_AIRCRAFT_BUILD_AIRPORT_TOOLTIP),
NWidget(WWT_PANEL, COLOUR_DARK_GREEN), SetMinimalSize(4, 22), SetFill(1, 1), EndContainer(),
NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_AT_DEMOLISH), SetFill(0, 1), SetMinimalSize(22, 22), SetSpriteTip(SPR_IMG_DYNAMITE, STR_TOOLTIP_DEMOLISH_BUILDINGS_ETC),
NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_AT_AIRPORT), SetFill(0, 1), SetToolbarMinimalSize(2), SetSpriteTip(SPR_IMG_AIRPORT, STR_TOOLBAR_AIRCRAFT_BUILD_AIRPORT_TOOLTIP),
NWidget(WWT_PANEL, COLOUR_DARK_GREEN), SetToolbarSpacerMinimalSize(), SetFill(1, 1), EndContainer(),
NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_AT_DEMOLISH), SetFill(0, 1), SetToolbarMinimalSize(1), SetSpriteTip(SPR_IMG_DYNAMITE, STR_TOOLTIP_DEMOLISH_BUILDINGS_ETC),
EndContainer(),
};
@@ -401,7 +401,7 @@ public:
case WID_AP_AIRPORT_SPRITE:
if (this->preview_sprite != 0) {
Dimension d = GetSpriteSize(this->preview_sprite);
DrawSprite(this->preview_sprite, COMPANY_SPRITE_COLOUR(_local_company), CenterBounds(r.left, r.right, d.width), CenterBounds(r.top, r.bottom, d.height));
DrawSprite(this->preview_sprite, GetCompanyPalette(_local_company), CentreBounds(r.left, r.right, d.width), CentreBounds(r.top, r.bottom, d.height));
}
break;
@@ -509,7 +509,7 @@ public:
this->SetWidgetLoweredState(WID_AP_BTN_DONTHILIGHT, !_settings_client.gui.station_show_coverage);
this->SetWidgetLoweredState(WID_AP_BTN_DOHILIGHT, _settings_client.gui.station_show_coverage);
this->SetDirty();
if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
SndClickBeep();
this->UpdateSelectSize();
SetViewportCatchmentStation(nullptr, true);
break;
@@ -561,7 +561,7 @@ public:
this->SelectOtherAirport(-1);
}
void OnDropdownSelect(WidgetID widget, int index) override
void OnDropdownSelect(WidgetID widget, int index, int) override
{
if (widget == WID_AP_CLASS_DROPDOWN) {
_selected_airport_class = (AirportClassID)index;
@@ -575,7 +575,7 @@ public:
CheckRedrawStationCoverage(this);
}
IntervalTimer<TimerGameCalendar> yearly_interval = {{TimerGameCalendar::YEAR, TimerGameCalendar::Priority::NONE}, [this](auto) {
const IntervalTimer<TimerGameCalendar> yearly_interval = {{TimerGameCalendar::YEAR, TimerGameCalendar::Priority::NONE}, [this](auto) {
this->InvalidateData();
}};
};
@@ -618,7 +618,7 @@ static constexpr NWidgetPart _nested_build_airport_widgets[] = {
};
static WindowDesc _build_airport_desc(
WDP_AUTO, nullptr, 0, 0,
WDP_AUTO, {}, 0, 0,
WC_BUILD_STATION, WC_BUILD_TOOLBAR,
WindowDefaultFlag::Construction,
_nested_build_airport_widgets
+7 -6
View File
@@ -80,20 +80,18 @@ uint CountArticulatedParts(EngineID engine_type, bool purchase_window)
* either, so it doesn't matter how many articulated parts there are. */
if (!Vehicle::CanAllocateItem()) return 0;
Vehicle *v = nullptr;
std::unique_ptr<Vehicle> v;
if (!purchase_window) {
v = new Vehicle();
v = std::make_unique<Vehicle>();
v->engine_type = engine_type;
v->owner = _current_company;
}
uint i;
for (i = 1; i < MAX_ARTICULATED_PARTS; i++) {
if (GetNextArticulatedPart(i, engine_type, v) == EngineID::Invalid()) break;
if (GetNextArticulatedPart(i, engine_type, v.get()) == EngineID::Invalid()) break;
}
delete v;
return i - 1;
}
@@ -432,7 +430,10 @@ void AddArticulatedParts(Vehicle *first)
if (flip_image) v->spritenum++;
if (v->type == VEH_TRAIN && TestVehicleBuildProbability(v, v->engine_type, BuildProbabilityType::Reversed)) SetBit(Train::From(v)->flags, VRF_REVERSE_DIRECTION);
if (v->type == VEH_TRAIN) {
auto prob = TestVehicleBuildProbability(v, v->engine_type, BuildProbabilityType::Reversed);
if (prob.has_value()) Train::From(v)->flags.Set(VehicleRailFlag::Flipped, prob.value());
}
v->UpdatePosition();
}
}
+6 -3
View File
@@ -17,9 +17,12 @@
#include "safeguards.h"
/**
* @return true, if the textbuf was updated.
*/
bool AutoCompletion::AutoComplete()
{
// We are pressing TAB for the first time after reset.
/* We are pressing TAB for the first time after reset. */
if (this->suggestions.empty()) {
this->InitSuggestions(this->textbuf->GetText());
if (this->suggestions.empty()) {
@@ -29,11 +32,11 @@ bool AutoCompletion::AutoComplete()
return true;
}
// We are pressing TAB again on the same text.
/* We are pressing TAB again on the same text. */
if (this->current_suggestion_index + 1 < this->suggestions.size()) {
this->ApplySuggestion(prefix, this->suggestions[++this->current_suggestion_index]);
} else {
// We are out of options, restore original text.
/* We are out of options, restore original text. */
this->textbuf->Assign(initial_buf);
this->Reset();
}
-1
View File
@@ -32,7 +32,6 @@ public:
}
virtual ~AutoCompletion() = default;
// Returns true the textbuf was updated.
bool AutoComplete();
void Reset();
+11 -8
View File
@@ -185,9 +185,9 @@ static bool VerifyAutoreplaceRefitForOrders(const Vehicle *v, EngineID engine_ty
CargoTypes union_refit_mask_b = GetUnionOfArticulatedRefitMasks(engine_type, false);
const Vehicle *u = (v->type == VEH_TRAIN) ? v->First() : v;
for (const Order *o : u->Orders()) {
if (!o->IsRefit() || o->IsAutoRefit()) continue;
CargoType cargo_type = o->GetRefitCargo();
for (const Order &o : u->Orders()) {
if (!o.IsRefit() || o.IsAutoRefit()) continue;
CargoType cargo_type = o.GetRefitCargo();
if (!HasBit(union_refit_mask_a, cargo_type)) continue;
if (!HasBit(union_refit_mask_b, cargo_type)) return false;
@@ -206,13 +206,12 @@ static int GetIncompatibleRefitOrderIdForAutoreplace(const Vehicle *v, EngineID
{
CargoTypes union_refit_mask = GetUnionOfArticulatedRefitMasks(engine_type, false);
const Order *o;
const Vehicle *u = (v->type == VEH_TRAIN) ? v->First() : v;
const OrderList *orders = u->orders;
if (orders == nullptr) return -1;
for (VehicleOrderID i = 0; i < orders->GetNumOrders(); i++) {
o = orders->GetOrderAt(i);
const Order *o = orders->GetOrderAt(i);
if (!o->IsRefit()) continue;
if (!HasBit(union_refit_mask, o->GetRefitCargo())) return i;
}
@@ -373,8 +372,12 @@ static CommandCost BuildReplacementVehicle(Vehicle *old_veh, Vehicle **new_vehic
}
/* Try to reverse the vehicle, but do not care if it fails as the new type might not be reversible */
if (new_veh->type == VEH_TRAIN && HasBit(Train::From(old_veh)->flags, VRF_REVERSE_DIRECTION)) {
Command<CMD_REVERSE_TRAIN_DIRECTION>::Do(DoCommandFlag::Execute, new_veh->index, true);
if (new_veh->type == VEH_TRAIN && Train::From(old_veh)->flags.Test(VehicleRailFlag::Flipped)) {
/* Only copy the reverse state if neither old or new vehicle implements reverse-on-build probability callback. */
if (!TestVehicleBuildProbability(old_veh, old_veh->engine_type, BuildProbabilityType::Reversed).has_value() &&
!TestVehicleBuildProbability(new_veh, new_veh->engine_type, BuildProbabilityType::Reversed).has_value()) {
Command<CMD_REVERSE_TRAIN_DIRECTION>::Do(DoCommandFlag::Execute, new_veh->index, true);
}
}
return cost;
@@ -432,7 +435,7 @@ static CommandCost CopyHeadSpecificThings(Vehicle *old_head, Vehicle *new_head,
/* Last do those things which do never fail (resp. we do not care about), but which are not undo-able */
if (cost.Succeeded() && old_head != new_head && flags.Test(DoCommandFlag::Execute)) {
/* Copy other things which cannot be copied by a command and which shall not stay resetted from the build vehicle command */
/* Copy other things which cannot be copied by a command and which shall not stay reset from the build vehicle command */
new_head->CopyVehicleConfigAndStatistics(old_head);
GroupStatistics::AddProfitLastYear(new_head);
+10 -11
View File
@@ -122,7 +122,7 @@ class ReplaceVehicleWindow : public Window {
*/
void GenerateReplaceVehList(bool draw_left)
{
std::vector<EngineID> variants;
FlatSet<EngineID> variants;
EngineID selected_engine = EngineID::Invalid();
VehicleType type = this->window_number;
uint8_t side = draw_left ? 0 : 1;
@@ -161,8 +161,7 @@ class ReplaceVehicleWindow : public Window {
if (side == 1) {
EngineID parent = e->info.variant_id;
while (parent != EngineID::Invalid()) {
variants.push_back(parent);
while (parent != EngineID::Invalid() && variants.insert(parent).second) {
parent = Engine::Get(parent)->info.variant_id;
}
}
@@ -311,7 +310,7 @@ public:
case WID_RV_LEFT_MATRIX:
case WID_RV_RIGHT_MATRIX:
resize.height = GetEngineListHeight(this->window_number);
fill.height = resize.height = GetEngineListHeight(this->window_number);
size.height = (this->window_number <= VEH_ROAD ? 8 : 4) * resize.height;
break;
@@ -406,11 +405,11 @@ public:
case WID_RV_TRAIN_WAGONREMOVE_TOGGLE:
if (const Group *g = Group::GetIfValid(this->sel_group); g != nullptr) {
bool remove_wagon = g->flags.Test(GroupFlag::ReplaceWagonRemoval);
return GetString(STR_GROUP_NAME, sel_group, remove_wagon ? STR_CONFIG_SETTING_ON : STR_CONFIG_SETTING_OFF);
return GetString(STR_REPLACE_REMOVE_WAGON, STR_GROUP_NAME, sel_group, remove_wagon ? STR_CONFIG_SETTING_ON : STR_CONFIG_SETTING_OFF);
} else {
const Company *c = Company::Get(_local_company);
bool remove_wagon = c->settings.renew_keep_length;
return GetString(STR_GROUP_DEFAULT_TRAINS + this->window_number, std::monostate{}, remove_wagon ? STR_CONFIG_SETTING_ON : STR_CONFIG_SETTING_OFF);
return GetString(STR_REPLACE_REMOVE_WAGON, STR_GROUP_DEFAULT_TRAINS + this->window_number, std::monostate{}, remove_wagon ? STR_CONFIG_SETTING_ON : STR_CONFIG_SETTING_OFF);
}
break;
@@ -552,7 +551,7 @@ public:
if (g != nullptr) {
Command<CMD_SET_GROUP_FLAG>::Post(this->sel_group, GroupFlag::ReplaceWagonRemoval, !g->flags.Test(GroupFlag::ReplaceWagonRemoval), _ctrl_pressed);
} else {
// toggle renew_keep_length
/* toggle renew_keep_length */
Command<CMD_CHANGE_COMPANY_SETTING>::Post("company.renew_keep_length", Company::Get(_local_company)->settings.renew_keep_length ? 0 : 1);
}
break;
@@ -563,8 +562,8 @@ public:
this->HandleButtonClick(WID_RV_START_REPLACE);
ReplaceClick_StartReplace(false);
} else {
bool replacment_when_old = EngineHasReplacementWhenOldForCompany(Company::Get(_local_company), this->sel_engine[0], this->sel_group);
ShowDropDownMenu(this, _start_replace_dropdown, replacment_when_old ? 1 : 0, WID_RV_START_REPLACE, !this->replace_engines ? 1 << 1 : 0, 0);
bool replacement_when_old = EngineHasReplacementWhenOldForCompany(Company::Get(_local_company), this->sel_engine[0], this->sel_group);
ShowDropDownMenu(this, _start_replace_dropdown, replacement_when_old ? 1 : 0, WID_RV_START_REPLACE, !this->replace_engines ? 1 << 1 : 0, 0);
}
break;
}
@@ -623,7 +622,7 @@ public:
}
}
void OnDropdownSelect(WidgetID widget, int index) override
void OnDropdownSelect(WidgetID widget, int index, int) override
{
switch (widget) {
case WID_RV_SORT_DROPDOWN:
@@ -744,7 +743,7 @@ static constexpr NWidgetPart _nested_replace_rail_vehicle_widgets[] = {
NWidget(WWT_PANEL, COLOUR_GREY, WID_RV_LEFT_DETAILS), SetMinimalSize(240, 122), SetResize(1, 0), EndContainer(),
NWidget(NWID_VERTICAL),
NWidget(WWT_PANEL, COLOUR_GREY, WID_RV_RIGHT_DETAILS), SetMinimalSize(240, 122), SetResize(1, 0), EndContainer(),
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_RV_TRAIN_WAGONREMOVE_TOGGLE), SetMinimalSize(138, 12), SetStringTip(STR_REPLACE_REMOVE_WAGON, STR_REPLACE_REMOVE_WAGON_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_RV_TRAIN_WAGONREMOVE_TOGGLE), SetMinimalSize(138, 12), SetToolTip(STR_REPLACE_REMOVE_WAGON_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
EndContainer(),
EndContainer(),
NWidget(NWID_HORIZONTAL),
+25 -19
View File
@@ -16,8 +16,9 @@
#include "3rdparty/md5/md5.h"
#include <unordered_map>
/* Forward declare these; can't do 'struct X' in functions as older GCCs barf on that */
struct IniFile;
struct IniGroup;
struct IniItem;
struct ContentInfo;
/** Structure holding filename and MD5 information about a single file */
@@ -47,7 +48,7 @@ template <class T> struct BaseSetTraits;
*/
template <class T>
struct BaseSet {
typedef std::unordered_map<std::string, std::string> TranslatedStrings;
typedef std::unordered_map<std::string, std::string, StringHash, std::equal_to<>> TranslatedStrings;
/** Number of files in this set */
static constexpr size_t NUM_FILES = BaseSetTraits<T>::num_files;
@@ -62,21 +63,13 @@ struct BaseSet {
std::string url; ///< URL for information about the base set
TranslatedStrings description; ///< Description of the base set
uint32_t shortname = 0; ///< Four letter short variant of the name
uint32_t version = 0; ///< The version of this base set
std::vector<uint32_t> version; ///< The version of this base set
bool fallback = false; ///< This set is a fallback set, i.e. it should be used only as last resort
std::array<MD5File, BaseSet<T>::NUM_FILES> files{}; ///< All files part of this set
uint found_files = 0; ///< Number of the files that could be found
uint valid_files = 0; ///< Number of the files that could be found and are valid
T *next = nullptr; ///< The next base set in this list
/** Free everything we allocated */
~BaseSet()
{
delete this->next;
}
/**
* Get the number of missing files.
* @return the number
@@ -96,6 +89,9 @@ struct BaseSet {
return BaseSet<T>::NUM_FILES - this->valid_files;
}
void LogError(std::string_view full_filename, std::string_view detail, int level = 0) const;
const IniItem *GetMandatoryItem(std::string_view full_filename, const IniGroup &group, std::string_view name) const;
bool FillSetDetails(const IniFile &ini, const std::string &path, const std::string &full_filename, bool allow_empty_filename = true);
void CopyCompatibleConfig([[maybe_unused]] const T &src) {}
@@ -107,7 +103,7 @@ struct BaseSet {
* @param isocode the isocode to search for
* @return the description
*/
const std::string &GetDescription(const std::string &isocode) const
const std::string &GetDescription(std::string_view isocode) const
{
if (!isocode.empty()) {
/* First the full ISO code */
@@ -166,9 +162,9 @@ struct BaseSet {
template <class Tbase_set>
class BaseMedia : FileScanner {
protected:
static inline Tbase_set *available_sets = nullptr; ///< All available sets
static inline Tbase_set *duplicate_sets = nullptr; ///< All sets that aren't available, but needed for not downloading base sets when a newer version than the one on BaNaNaS is loaded.
static inline const Tbase_set *used_set = nullptr; ///< The currently used set
static inline std::vector<std::unique_ptr<Tbase_set>> available_sets; ///< All available sets
static inline std::vector<std::unique_ptr<Tbase_set>> duplicate_sets; ///< All sets that aren't available, but needed for not downloading base sets when a newer version than the one on BaNaNaS is loaded.
static inline const Tbase_set *used_set; ///< The currently used set
bool AddFile(const std::string &filename, size_t basepath_length, const std::string &tar_filename) override;
@@ -176,7 +172,13 @@ protected:
* Get the extension that is used to identify this set.
* @return the extension
*/
static const char *GetExtension();
static std::string_view GetExtension();
/**
* Return the duplicate sets.
* @return The duplicate sets.
*/
static std::span<const std::unique_ptr<Tbase_set>> GetDuplicateSets() { return BaseMedia<Tbase_set>::duplicate_sets; }
public:
/**
* Determine the graphics pack that has to be used.
@@ -194,7 +196,11 @@ public:
return num + fs.Scan(GetExtension(), BASESET_DIR, Tbase_set::SEARCH_IN_TARS);
}
static Tbase_set *GetAvailableSets();
/**
* Return the available sets.
* @return The available sets.
*/
static std::span<const std::unique_ptr<Tbase_set>> GetAvailableSets() { return BaseMedia<Tbase_set>::available_sets; }
static bool SetSet(const Tbase_set *set);
static bool SetSetByName(const std::string &name);
@@ -219,9 +225,9 @@ public:
* @param ci The content info to compare it to.
* @param md5sum Should the MD5 checksum be tested as well?
* @param s The list with sets.
* @return The filename of the first file of the base set, or \c nullptr if there is no match.
* @return The filename of the first file of the base set, or \c std::nullopt if there is no match.
*/
template <class Tbase_set>
const char *TryGetBaseSetFile(const ContentInfo &ci, bool md5sum, const Tbase_set *s);
std::optional<std::string_view> TryGetBaseSetFile(const ContentInfo &ci, bool md5sum, std::span<const std::unique_ptr<Tbase_set>> sets);
#endif /* BASE_MEDIA_BASE_H */
+112 -119
View File
@@ -14,20 +14,39 @@
#include "ini_type.h"
#include "string_func.h"
#include "error_func.h"
#include "core/string_consumer.hpp"
#include "3rdparty/fmt/ranges.h"
extern void CheckExternalFiles();
/**
* Try to read a single piece of metadata and return false if it doesn't exist.
* Log error from reading basesets.
* @param full_filename the full filename of the loaded file
* @param detail detail log message
* @param level debug level
*/
template <class T>
void BaseSet<T>::LogError(std::string_view full_filename, std::string_view detail, int level) const
{
Debug(misc, level, "Loading base {}set details failed: {}", BaseSet<T>::SET_TYPE, full_filename);
Debug(misc, level, " {}", detail);
}
/**
* Try to read a single piece of metadata and return nullptr if it doesn't exist.
* Log error, if the data is missing.
* @param full_filename the full filename of the loaded file (for error reporting purposes)
* @param group ini group to read from
* @param name the name of the item to fetch.
*/
#define fetch_metadata(name) \
item = metadata->GetItem(name); \
if (item == nullptr || !item->value.has_value() || item->value->empty()) { \
Debug(grf, 0, "Base {}set detail loading: {} field missing.", BaseSet::SET_TYPE, name); \
Debug(grf, 0, " Is {} readable for the user running OpenTTD?", full_filename); \
return false; \
}
template <class T>
const IniItem *BaseSet<T>::GetMandatoryItem(std::string_view full_filename, const IniGroup &group, std::string_view name) const
{
auto *item = group.GetItem(name);
if (item != nullptr && item->value.has_value() && !item->value->empty()) return item;
this->LogError(full_filename, fmt::format("{}.{} field missing.", group.name, name));
return nullptr;
}
/**
* Read the set information from a loaded ini.
@@ -42,16 +61,17 @@ bool BaseSet<T>::FillSetDetails(const IniFile &ini, const std::string &path, con
{
const IniGroup *metadata = ini.GetGroup("metadata");
if (metadata == nullptr) {
Debug(grf, 0, "Base {}set detail loading: metadata missing.", BaseSet<T>::SET_TYPE);
Debug(grf, 0, " Is {} readable for the user running OpenTTD?", full_filename);
this->LogError(full_filename, "Is the file readable for the user running OpenTTD?");
return false;
}
const IniItem *item;
fetch_metadata("name");
item = this->GetMandatoryItem(full_filename, *metadata, "name");
if (item == nullptr) return false;
this->name = *item->value;
fetch_metadata("description");
item = this->GetMandatoryItem(full_filename, *metadata, "description");
if (item == nullptr) return false;
this->description[std::string{}] = *item->value;
item = metadata->GetItem("url");
@@ -64,13 +84,24 @@ bool BaseSet<T>::FillSetDetails(const IniFile &ini, const std::string &path, con
this->description[titem.name.substr(12)] = titem.value.value_or("");
}
fetch_metadata("shortname");
item = this->GetMandatoryItem(full_filename, *metadata, "shortname");
if (item == nullptr) return false;
for (uint i = 0; (*item->value)[i] != '\0' && i < 4; i++) {
this->shortname |= ((uint8_t)(*item->value)[i]) << (i * 8);
}
fetch_metadata("version");
this->version = atoi(item->value->c_str());
item = this->GetMandatoryItem(full_filename, *metadata, "version");
if (item == nullptr) return false;
for (StringConsumer consumer{*item->value};;) {
auto value = consumer.TryReadIntegerBase<uint32_t>(10);
bool valid = value.has_value();
if (valid) this->version.push_back(*value);
if (valid && !consumer.AnyBytesLeft()) break;
if (!valid || !consumer.ReadIf(".")) {
this->LogError(full_filename, fmt::format("metadata.version field is invalid: {}", *item->value));
return false;
}
}
item = metadata->GetItem("fallback");
this->fallback = (item != nullptr && item->value && *item->value != "0" && *item->value != "false");
@@ -80,13 +111,18 @@ bool BaseSet<T>::FillSetDetails(const IniFile &ini, const std::string &path, con
const IniGroup *md5s = ini.GetGroup("md5s");
const IniGroup *origin = ini.GetGroup("origin");
auto file_names = BaseSet<T>::GetFilenames();
bool original_set =
std::byteswap(this->shortname) == 'TTDD' || // TTD DOS graphics, TTD DOS music
std::byteswap(this->shortname) == 'TTDW' || // TTD WIN graphics, TTD WIN music
std::byteswap(this->shortname) == 'TTDO' || // TTD sound
std::byteswap(this->shortname) == 'TTOD'; // TTO music
for (uint i = 0; i < BaseSet<T>::NUM_FILES; i++) {
MD5File *file = &this->files[i];
/* Find the filename first. */
item = files != nullptr ? files->GetItem(file_names[i]) : nullptr;
if (item == nullptr || (!item->value.has_value() && !allow_empty_filename)) {
Debug(grf, 0, "No {} file for: {} (in {})", BaseSet<T>::SET_TYPE, file_names[i], full_filename);
this->LogError(full_filename, fmt::format("files.{} field missing", file_names[i]));
return false;
}
@@ -104,34 +140,19 @@ bool BaseSet<T>::FillSetDetails(const IniFile &ini, const std::string &path, con
/* Then find the MD5 checksum */
item = md5s != nullptr ? md5s->GetItem(filename) : nullptr;
if (item == nullptr || !item->value.has_value()) {
Debug(grf, 0, "No MD5 checksum specified for: {} (in {})", filename, full_filename);
this->LogError(full_filename, fmt::format("md5s.{} field missing", filename));
return false;
}
const char *c = item->value->c_str();
for (size_t i = 0; i < file->hash.size() * 2; i++, c++) {
uint j;
if ('0' <= *c && *c <= '9') {
j = *c - '0';
} else if ('a' <= *c && *c <= 'f') {
j = *c - 'a' + 10;
} else if ('A' <= *c && *c <= 'F') {
j = *c - 'A' + 10;
} else {
Debug(grf, 0, "Malformed MD5 checksum specified for: {} (in {})", filename, full_filename);
return false;
}
if (i % 2 == 0) {
file->hash[i / 2] = j << 4;
} else {
file->hash[i / 2] |= j;
}
if (!ConvertHexToBytes(*item->value, file->hash)) {
this->LogError(full_filename, fmt::format("md5s.{} is malformed: {}", filename, *item->value));
return false;
}
/* Then find the warning message when the file's missing */
item = origin != nullptr ? origin->GetItem(filename) : nullptr;
if (item == nullptr) item = origin != nullptr ? origin->GetItem("default") : nullptr;
if (item == nullptr || !item->value.has_value()) {
Debug(grf, 1, "No origin warning message specified for: {}", filename);
this->LogError(full_filename, fmt::format("origin.{} field missing", filename), 1);
file->missing_warning.clear();
} else {
file->missing_warning = item->value.value();
@@ -148,12 +169,14 @@ bool BaseSet<T>::FillSetDetails(const IniFile &ini, const std::string &path, con
break;
case MD5File::CR_MISMATCH:
Debug(grf, 1, "MD5 checksum mismatch for: {} (in {})", filename, full_filename);
/* This is normal for original sample.cat, which either matches with orig_dos or orig_win. */
this->LogError(full_filename, fmt::format("MD5 checksum mismatch for: {}", filename), original_set ? 1 : 0);
this->found_files++;
break;
case MD5File::CR_NO_FILE:
Debug(grf, 1, "The file {} specified in {} is missing", filename, full_filename);
/* Missing files is normal for the original basesets. Use lower debug level */
this->LogError(full_filename, fmt::format("File is missing: {}", filename), original_set ? 1 : 0);
break;
}
}
@@ -164,10 +187,9 @@ bool BaseSet<T>::FillSetDetails(const IniFile &ini, const std::string &path, con
template <class Tbase_set>
bool BaseMedia<Tbase_set>::AddFile(const std::string &filename, size_t basepath_length, const std::string &)
{
bool ret = false;
Debug(grf, 1, "Checking {} for base {} set", filename, BaseSet<Tbase_set>::SET_TYPE);
Debug(misc, 1, "Checking {} for base {} set", filename, BaseSet<Tbase_set>::SET_TYPE);
Tbase_set *set = new Tbase_set();
auto set = std::make_unique<Tbase_set>();
IniFile ini{};
std::string path{ filename, basepath_length };
ini.LoadFromDisk(path, BASESET_DIR);
@@ -179,60 +201,44 @@ bool BaseMedia<Tbase_set>::AddFile(const std::string &filename, size_t basepath_
path.clear();
}
if (set->FillSetDetails(ini, path, filename)) {
Tbase_set *duplicate = nullptr;
for (Tbase_set *c = BaseMedia<Tbase_set>::available_sets; c != nullptr; c = c->next) {
if (c->name == set->name || c->shortname == set->shortname) {
duplicate = c;
break;
}
if (!set->FillSetDetails(ini, path, filename)) return false;
auto existing = std::ranges::find_if(BaseMedia<Tbase_set>::available_sets, [&set](const auto &c) { return c->name == set->name || c->shortname == set->shortname; });
if (existing != std::end(BaseMedia<Tbase_set>::available_sets)) {
/* The more complete set takes precedence over the version number. */
if (((*existing)->valid_files == set->valid_files && (*existing)->version >= set->version) ||
(*existing)->valid_files > set->valid_files) {
Debug(misc, 1, "Not adding {} ({}) as base {} set (duplicate, {})", set->name, fmt::join(set->version, "."),
BaseSet<Tbase_set>::SET_TYPE,
(*existing)->valid_files > set->valid_files ? "fewer valid files" : "lower version");
duplicate_sets.push_back(std::move(set));
return false;
}
if (duplicate != nullptr) {
/* The more complete set takes precedence over the version number. */
if ((duplicate->valid_files == set->valid_files && duplicate->version >= set->version) ||
duplicate->valid_files > set->valid_files) {
Debug(grf, 1, "Not adding {} ({}) as base {} set (duplicate, {})", set->name, set->version,
BaseSet<Tbase_set>::SET_TYPE,
duplicate->valid_files > set->valid_files ? "less valid files" : "lower version");
set->next = BaseMedia<Tbase_set>::duplicate_sets;
BaseMedia<Tbase_set>::duplicate_sets = set;
} else {
Tbase_set **prev = &BaseMedia<Tbase_set>::available_sets;
while (*prev != duplicate) prev = &(*prev)->next;
*prev = set;
set->next = duplicate->next;
/* If the duplicate set is currently used (due to rescanning this can happen)
* update the currently used set to the new one. This will 'lie' about the
* version number until a new game is started which isn't a big problem */
if (BaseMedia<Tbase_set>::used_set == existing->get()) BaseMedia<Tbase_set>::used_set = set.get();
/* Keep baseset configuration, if compatible */
set->CopyCompatibleConfig(*duplicate);
/* Keep baseset configuration, if compatible */
set->CopyCompatibleConfig(**existing);
/* If the duplicate set is currently used (due to rescanning this can happen)
* update the currently used set to the new one. This will 'lie' about the
* version number until a new game is started which isn't a big problem */
if (BaseMedia<Tbase_set>::used_set == duplicate) BaseMedia<Tbase_set>::used_set = set;
Debug(misc, 1, "Removing {} ({}) as base {} set (duplicate, {})", (*existing)->name, fmt::join((*existing)->version, "."), BaseSet<Tbase_set>::SET_TYPE,
(*existing)->valid_files < set->valid_files ? "fewer valid files" : "lower version");
Debug(grf, 1, "Removing {} ({}) as base {} set (duplicate, {})", duplicate->name, duplicate->version,
BaseSet<Tbase_set>::SET_TYPE,
duplicate->valid_files < set->valid_files ? "less valid files" : "lower version");
duplicate->next = BaseMedia<Tbase_set>::duplicate_sets;
BaseMedia<Tbase_set>::duplicate_sets = duplicate;
ret = true;
}
} else {
Tbase_set **last = &BaseMedia<Tbase_set>::available_sets;
while (*last != nullptr) last = &(*last)->next;
/* Existing set is worse, move it to duplicates and replace with the current set. */
duplicate_sets.push_back(std::move(*existing));
*last = set;
ret = true;
}
if (ret) {
Debug(grf, 1, "Adding {} ({}) as base {} set", set->name, set->version, BaseSet<Tbase_set>::SET_TYPE);
}
Debug(misc, 1, "Adding {} ({}) as base {} set", set->name, fmt::join(set->version, "."), BaseSet<Tbase_set>::SET_TYPE);
*existing = std::move(set);
} else {
delete set;
Debug(grf, 1, "Adding {} ({}) as base {} set", set->name, set->version, BaseSet<Tbase_set>::SET_TYPE);
available_sets.push_back(std::move(set));
}
return ret;
return true;
}
/**
@@ -264,9 +270,9 @@ template <class Tbase_set>
return SetSet(nullptr);
}
for (const Tbase_set *s = BaseMedia<Tbase_set>::available_sets; s != nullptr; s = s->next) {
for (const auto &s : BaseMedia<Tbase_set>::available_sets) {
if (name == s->name) {
return SetSet(s);
return SetSet(s.get());
}
}
return false;
@@ -284,9 +290,9 @@ template <class Tbase_set>
return SetSet(nullptr);
}
for (const Tbase_set *s = BaseMedia<Tbase_set>::available_sets; s != nullptr; s = s->next) {
for (const auto &s : BaseMedia<Tbase_set>::available_sets) {
if (shortname == s->shortname) {
return SetSet(s);
return SetSet(s.get());
}
}
return false;
@@ -300,7 +306,7 @@ template <class Tbase_set>
/* static */ void BaseMedia<Tbase_set>::GetSetsList(std::back_insert_iterator<std::string> &output_iterator)
{
fmt::format_to(output_iterator, "List of {} sets:\n", BaseSet<Tbase_set>::SET_TYPE);
for (const Tbase_set *s = BaseMedia<Tbase_set>::available_sets; s != nullptr; s = s->next) {
for (const auto &s : BaseMedia<Tbase_set>::available_sets) {
fmt::format_to(output_iterator, "{:>18}: {}", s->name, s->GetDescription({}));
int invalid = s->GetNumInvalid();
if (invalid != 0) {
@@ -319,28 +325,28 @@ template <class Tbase_set>
#include "network/core/tcp_content_type.h"
template <class Tbase_set> const char *TryGetBaseSetFile(const ContentInfo &ci, bool md5sum, const Tbase_set *s)
template <class Tbase_set> std::optional<std::string_view> TryGetBaseSetFile(const ContentInfo &ci, bool md5sum, std::span<const std::unique_ptr<Tbase_set>> sets)
{
for (; s != nullptr; s = s->next) {
for (const auto &s : sets) {
if (s->GetNumMissing() != 0) continue;
if (s->shortname != ci.unique_id) continue;
if (!md5sum) return s->files[0].filename.c_str();
if (!md5sum) return s->files[0].filename;
MD5Hash md5;
for (const auto &file : s->files) {
md5 ^= file.hash;
}
if (md5 == ci.md5sum) return s->files[0].filename.c_str();
if (md5 == ci.md5sum) return s->files[0].filename;
}
return nullptr;
return std::nullopt;
}
template <class Tbase_set>
/* static */ bool BaseMedia<Tbase_set>::HasSet(const ContentInfo &ci, bool md5sum)
{
return (TryGetBaseSetFile(ci, md5sum, BaseMedia<Tbase_set>::available_sets) != nullptr) ||
(TryGetBaseSetFile(ci, md5sum, BaseMedia<Tbase_set>::duplicate_sets) != nullptr);
return TryGetBaseSetFile(ci, md5sum, BaseMedia<Tbase_set>::GetAvailableSets()).has_value() ||
TryGetBaseSetFile(ci, md5sum, BaseMedia<Tbase_set>::GetDuplicateSets()).has_value();
}
/**
@@ -350,12 +356,9 @@ template <class Tbase_set>
template <class Tbase_set>
/* static */ int BaseMedia<Tbase_set>::GetNumSets()
{
int n = 0;
for (const Tbase_set *s = BaseMedia<Tbase_set>::available_sets; s != nullptr; s = s->next) {
if (s != BaseMedia<Tbase_set>::used_set && s->GetNumMissing() != 0) continue;
n++;
}
return n;
return std::ranges::count_if(BaseMedia<Tbase_set>::GetAvailableSets(), [](const auto &set) {
return set.get() == BaseMedia<Tbase_set>::used_set || set->GetNumMissing() == 0;
});
}
/**
@@ -366,8 +369,8 @@ template <class Tbase_set>
/* static */ int BaseMedia<Tbase_set>::GetIndexOfUsedSet()
{
int n = 0;
for (const Tbase_set *s = BaseMedia<Tbase_set>::available_sets; s != nullptr; s = s->next) {
if (s == BaseMedia<Tbase_set>::used_set) return n;
for (const auto &s : BaseMedia<Tbase_set>::available_sets) {
if (s.get() == BaseMedia<Tbase_set>::used_set) return n;
if (s->GetNumMissing() != 0) continue;
n++;
}
@@ -381,9 +384,9 @@ template <class Tbase_set>
template <class Tbase_set>
/* static */ const Tbase_set *BaseMedia<Tbase_set>::GetSet(int index)
{
for (const Tbase_set *s = BaseMedia<Tbase_set>::available_sets; s != nullptr; s = s->next) {
if (s != BaseMedia<Tbase_set>::used_set && s->GetNumMissing() != 0) continue;
if (index == 0) return s;
for (const auto &s : BaseMedia<Tbase_set>::available_sets) {
if (s.get() != BaseMedia<Tbase_set>::used_set && s->GetNumMissing() != 0) continue;
if (index == 0) return s.get();
index--;
}
FatalError("Base{}::GetSet(): index {} out of range", BaseSet<Tbase_set>::SET_TYPE, index);
@@ -398,13 +401,3 @@ template <class Tbase_set>
{
return BaseMedia<Tbase_set>::used_set;
}
/**
* Return the available sets.
* @return The available sets.
*/
template <class Tbase_set>
/* static */ Tbase_set *BaseMedia<Tbase_set>::GetAvailableSets()
{
return BaseMedia<Tbase_set>::available_sets;
}
+6 -7
View File
@@ -74,9 +74,9 @@ struct BaseStation : StationPool::PoolItem<&_station_pool> {
TimerGameCalendar::Date build_date{}; ///< Date of construction
uint16_t random_bits = 0; ///< Random bits assigned to this station
uint8_t waiting_triggers = 0; ///< Waiting triggers (NewGRF) for this station
uint8_t cached_anim_triggers = 0; ///< NOSAVE: Combined animation trigger bitmask, used to determine if trigger processing should happen.
uint8_t cached_roadstop_anim_triggers = 0; ///< NOSAVE: Combined animation trigger bitmask for road stops, used to determine if trigger processing should happen.
StationRandomTriggers waiting_random_triggers; ///< Waiting triggers (NewGRF), shared by all station parts/tiles, road stops, ... essentially useless and broken by design.
StationAnimationTriggers cached_anim_triggers; ///< NOSAVE: Combined animation trigger bitmask, used to determine if trigger processing should happen.
StationAnimationTriggers cached_roadstop_anim_triggers; ///< NOSAVE: Combined animation trigger bitmask for road stops, used to determine if trigger processing should happen.
CargoTypes cached_cargo_triggers{}; ///< NOSAVE: Combined cargo trigger bitmask
CargoTypes cached_roadstop_cargo_triggers{}; ///< NOSAVE: Combined cargo trigger bitmask for road stops
@@ -130,11 +130,10 @@ struct BaseStation : StationPool::PoolItem<&_station_pool> {
/**
* Get the tile area for a given station type.
* @param ta tile area to fill.
* @param type the type of the area
* @return The tile area.
*/
virtual void GetTileArea(TileArea *ta, StationType type) const = 0;
virtual TileArea GetTileArea(StationType type) const = 0;
/**
* Obtain the length of a platform
@@ -244,7 +243,7 @@ struct SpecializedStation : public BaseStation {
/**
* Gets station with given index
* @return pointer to station with given index casted to T *
* @return pointer to station with given index cast to T *
*/
static inline T *Get(auto index)
{
+17 -27
View File
@@ -25,8 +25,8 @@ inline void Blitter_32bppAnim::Draw(const Blitter::BlitterParams *bp, ZoomLevel
{
const SpriteData *src = (const SpriteData *)bp->sprite;
const Colour *src_px = (const Colour *)(src->data + src->offset[zoom][0]);
const uint16_t *src_n = (const uint16_t *)(src->data + src->offset[zoom][1]);
const Colour *src_px = reinterpret_cast<const Colour *>(src->data + src->offset[0][zoom]);
const uint16_t *src_n = reinterpret_cast<const uint16_t *>(src->data + src->offset[1][zoom]);
for (uint i = bp->skip_top; i != 0; i--) {
src_px = (const Colour *)((const uint8_t *)src_px + *(const uint32_t *)src_px);
@@ -321,19 +321,19 @@ void Blitter_32bppAnim::DrawColourMappingRect(void *dst, int width, int height,
Debug(misc, 0, "32bpp blitter doesn't know how to draw this colour table ('{}')", pal);
}
void Blitter_32bppAnim::SetPixel(void *video, int x, int y, uint8_t colour)
void Blitter_32bppAnim::SetPixel(void *video, int x, int y, PixelColour colour)
{
*((Colour *)video + x + y * _screen.pitch) = LookupColourInPalette(colour);
*((Colour *)video + x + y * _screen.pitch) = LookupColourInPalette(colour.p);
/* Set the colour in the anim-buffer too, if we are rendering to the screen */
if (_screen_disable_anim) return;
this->anim_buf[this->ScreenToAnimOffset((uint32_t *)video) + x + y * this->anim_buf_pitch] = colour | (DEFAULT_BRIGHTNESS << 8);
this->anim_buf[this->ScreenToAnimOffset((uint32_t *)video) + x + y * this->anim_buf_pitch] = colour.p | (DEFAULT_BRIGHTNESS << 8);
}
void Blitter_32bppAnim::DrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, uint8_t colour, int width, int dash)
void Blitter_32bppAnim::DrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, PixelColour colour, int width, int dash)
{
const Colour c = LookupColourInPalette(colour);
const Colour c = LookupColourInPalette(colour.p);
if (_screen_disable_anim) {
this->DrawLineGeneric(x, y, x2, y2, screen_width, screen_height, width, dash, [&](int x, int y) {
@@ -341,7 +341,7 @@ void Blitter_32bppAnim::DrawLine(void *video, int x, int y, int x2, int y2, int
});
} else {
uint16_t * const offset_anim_buf = this->anim_buf + this->ScreenToAnimOffset((uint32_t *)video);
const uint16_t anim_colour = colour | (DEFAULT_BRIGHTNESS << 8);
const uint16_t anim_colour = colour.p | (DEFAULT_BRIGHTNESS << 8);
this->DrawLineGeneric(x, y, x2, y2, screen_width, screen_height, width, dash, [&](int x, int y) {
*((Colour *)video + x + y * _screen.pitch) = c;
offset_anim_buf[x + y * this->anim_buf_pitch] = anim_colour;
@@ -349,7 +349,7 @@ void Blitter_32bppAnim::DrawLine(void *video, int x, int y, int x2, int y2, int
}
}
void Blitter_32bppAnim::DrawRect(void *video, int width, int height, uint8_t colour)
void Blitter_32bppAnim::DrawRect(void *video, int width, int height, PixelColour colour)
{
if (_screen_disable_anim) {
/* This means our output is not to the screen, so we can't be doing any animation stuff, so use our parent DrawRect() */
@@ -357,7 +357,7 @@ void Blitter_32bppAnim::DrawRect(void *video, int width, int height, uint8_t col
return;
}
Colour colour32 = LookupColourInPalette(colour);
Colour colour32 = LookupColourInPalette(colour.p);
uint16_t *anim_line = this->ScreenToAnimOffset((uint32_t *)video) + this->anim_buf;
do {
@@ -367,7 +367,7 @@ void Blitter_32bppAnim::DrawRect(void *video, int width, int height, uint8_t col
for (int i = width; i > 0; i--) {
*dst = colour32;
/* Set the colour in the anim-buffer too */
*anim = colour | (DEFAULT_BRIGHTNESS << 8);
*anim = colour.p | (DEFAULT_BRIGHTNESS << 8);
dst++;
anim++;
}
@@ -389,11 +389,11 @@ void Blitter_32bppAnim::CopyFromBuffer(void *video, const void *src, int width,
Colour *dst_pal = dst;
uint16_t *anim_pal = anim_line;
memcpy(static_cast<void *>(dst), usrc, width * sizeof(uint32_t));
std::copy_n(usrc, width, reinterpret_cast<uint32_t *>(dst));
usrc += width;
dst += _screen.pitch;
/* Copy back the anim-buffer */
memcpy(anim_line, usrc, width * sizeof(uint16_t));
std::copy_n(reinterpret_cast<const uint16_t *>(usrc), width, anim_line);
usrc = (const uint32_t *)&((const uint16_t *)usrc)[width];
anim_line += this->anim_buf_pitch;
@@ -428,11 +428,11 @@ void Blitter_32bppAnim::CopyToBuffer(const void *video, void *dst, int width, in
const uint16_t *anim_line = this->ScreenToAnimOffset((const uint32_t *)video) + this->anim_buf;
for (; height > 0; height--) {
memcpy(udst, src, width * sizeof(uint32_t));
std::copy_n(src, width, udst);
src += _screen.pitch;
udst += width;
/* Copy the anim-buffer */
memcpy(udst, anim_line, width * sizeof(uint16_t));
std::copy_n(anim_line, width, reinterpret_cast<uint16_t *>(udst));
udst = (uint32_t *)&((uint16_t *)udst)[width];
anim_line += this->anim_buf_pitch;
}
@@ -458,11 +458,7 @@ void Blitter_32bppAnim::ScrollBuffer(void *video, int &left, int &top, int &widt
uint tw = width + (scroll_x >= 0 ? -scroll_x : scroll_x);
uint th = height - scroll_y;
for (; th > 0; th--) {
memcpy(dst, src, tw * sizeof(uint16_t));
src -= this->anim_buf_pitch;
dst -= this->anim_buf_pitch;
}
Blitter::MovePixels(src, dst, tw, th, -this->anim_buf_pitch);
} else {
/* Calculate pointers */
dst = this->anim_buf + left + top * this->anim_buf_pitch;
@@ -475,15 +471,9 @@ void Blitter_32bppAnim::ScrollBuffer(void *video, int &left, int &top, int &widt
src -= scroll_x;
}
/* the y-displacement may be 0 therefore we have to use memmove,
* because source and destination may overlap */
uint tw = width + (scroll_x >= 0 ? -scroll_x : scroll_x);
uint th = height + scroll_y;
for (; th > 0; th--) {
memmove(dst, src, tw * sizeof(uint16_t));
src += this->anim_buf_pitch;
dst += this->anim_buf_pitch;
}
Blitter::MovePixels(src, dst, tw, th, this->anim_buf_pitch);
}
Blitter_32bppBase::ScrollBuffer(video, left, top, width, height, scroll_x, scroll_y);
+3 -3
View File
@@ -34,9 +34,9 @@ public:
void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom) override;
void DrawColourMappingRect(void *dst, int width, int height, PaletteID pal) override;
void SetPixel(void *video, int x, int y, uint8_t colour) override;
void DrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, uint8_t colour, int width, int dash) override;
void DrawRect(void *video, int width, int height, uint8_t colour) override;
void SetPixel(void *video, int x, int y, PixelColour colour) override;
void DrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, PixelColour colour, int width, int dash) override;
void DrawRect(void *video, int width, int height, PixelColour colour) override;
void CopyFromBuffer(void *video, const void *src, int width, int height) override;
void CopyToBuffer(const void *video, void *dst, int width, int height) override;
void ScrollBuffer(void *video, int &left, int &top, int &width, int &height, int scroll_x, int scroll_y) override;
+1 -1
View File
@@ -190,8 +190,8 @@ bmno_full_transparency:
const uint m1 = (uint8_t) (mvX2 >> 16);
const uint r1 = remap[m1];
if (mvX2 & 0x00FF00FF) {
/* Written so the compiler uses CMOV. */
#define CMOV_REMAP(m_colour, m_colour_init, m_src, m_m) \
/* Written so the compiler uses CMOV. */ \
Colour m_colour = m_colour_init; \
{ \
const Colour srcm = (Colour) (m_src); \
+4 -2
View File
@@ -39,8 +39,10 @@ public:
template <BlitterMode mode, Blitter_32bppSSE_Base::ReadMode read_mode, Blitter_32bppSSE_Base::BlockType bt_last, bool translucent, bool animated>
void Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom);
void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom) override;
Sprite *Encode(const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator) override {
return Blitter_32bppSSE_Base::Encode(sprite, allocator);
Sprite *Encode(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator) override
{
return Blitter_32bppSSE_Base::Encode(sprite_type, sprite, allocator);
}
std::string_view GetName() override { return "32bpp-sse4-anim"; }
using Blitter_32bppSSE2_Anim::LookupColourInPalette;
+11 -21
View File
@@ -18,22 +18,22 @@ void *Blitter_32bppBase::MoveTo(void *video, int x, int y)
return (uint32_t *)video + x + y * _screen.pitch;
}
void Blitter_32bppBase::SetPixel(void *video, int x, int y, uint8_t colour)
void Blitter_32bppBase::SetPixel(void *video, int x, int y, PixelColour colour)
{
*((Colour *)video + x + y * _screen.pitch) = LookupColourInPalette(colour);
*((Colour *)video + x + y * _screen.pitch) = LookupColourInPalette(colour.p);
}
void Blitter_32bppBase::DrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, uint8_t colour, int width, int dash)
void Blitter_32bppBase::DrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, PixelColour colour, int width, int dash)
{
const Colour c = LookupColourInPalette(colour);
const Colour c = LookupColourInPalette(colour.p);
this->DrawLineGeneric(x, y, x2, y2, screen_width, screen_height, width, dash, [=](int x, int y) {
*((Colour *)video + x + y * _screen.pitch) = c;
});
}
void Blitter_32bppBase::DrawRect(void *video, int width, int height, uint8_t colour)
void Blitter_32bppBase::DrawRect(void *video, int width, int height, PixelColour colour)
{
Colour colour32 = LookupColourInPalette(colour);
Colour colour32 = LookupColourInPalette(colour.p);
do {
Colour *dst = (Colour *)video;
@@ -51,7 +51,7 @@ void Blitter_32bppBase::CopyFromBuffer(void *video, const void *src, int width,
const uint32_t *usrc = (const uint32_t *)src;
for (; height > 0; height--) {
memcpy(dst, usrc, width * sizeof(uint32_t));
std::copy_n(usrc, width, dst);
usrc += width;
dst += _screen.pitch;
}
@@ -63,7 +63,7 @@ void Blitter_32bppBase::CopyToBuffer(const void *video, void *dst, int width, in
const uint32_t *src = (const uint32_t *)video;
for (; height > 0; height--) {
memcpy(udst, src, width * sizeof(uint32_t));
std::copy_n(src, width, udst);
src += _screen.pitch;
udst += width;
}
@@ -75,7 +75,7 @@ void Blitter_32bppBase::CopyImageToBuffer(const void *video, void *dst, int widt
const uint32_t *src = (const uint32_t *)video;
for (; height > 0; height--) {
memcpy(udst, src, width * sizeof(uint32_t));
std::copy_n(src, width, udst);
src += _screen.pitch;
udst += dst_pitch;
}
@@ -106,11 +106,7 @@ void Blitter_32bppBase::ScrollBuffer(void *video, int &left, int &top, int &widt
width += scroll_x;
}
for (int h = height; h > 0; h--) {
memcpy(dst, src, width * sizeof(uint32_t));
src -= _screen.pitch;
dst -= _screen.pitch;
}
Blitter::MovePixels(src, dst, width, height, -_screen.pitch);
} else {
/* Calculate pointers */
dst = (uint32_t *)video + left + top * _screen.pitch;
@@ -130,13 +126,7 @@ void Blitter_32bppBase::ScrollBuffer(void *video, int &left, int &top, int &widt
width += scroll_x;
}
/* the y-displacement may be 0 therefore we have to use memmove,
* because source and destination may overlap */
for (int h = height; h > 0; h--) {
memmove(dst, src, width * sizeof(uint32_t));
src += _screen.pitch;
dst += _screen.pitch;
}
Blitter::MovePixels(src, dst, width, height, _screen.pitch);
}
}
+3 -3
View File
@@ -19,9 +19,9 @@ class Blitter_32bppBase : public Blitter {
public:
uint8_t GetScreenDepth() override { return 32; }
void *MoveTo(void *video, int x, int y) override;
void SetPixel(void *video, int x, int y, uint8_t colour) override;
void DrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, uint8_t colour, int width, int dash) override;
void DrawRect(void *video, int width, int height, uint8_t colour) override;
void SetPixel(void *video, int x, int y, PixelColour colour) override;
void DrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, PixelColour colour, int width, int dash) override;
void DrawRect(void *video, int width, int height, PixelColour colour) override;
void CopyFromBuffer(void *video, const void *src, int width, int height) override;
void CopyToBuffer(const void *video, void *dst, int width, int height) override;
void CopyImageToBuffer(const void *video, void *dst, int width, int height, int dst_pitch) override;
+30 -26
View File
@@ -32,11 +32,11 @@ inline void Blitter_32bppOptimized::Draw(const Blitter::BlitterParams *bp, ZoomL
/* src_px : each line begins with uint32_t n = 'number of bytes in this line',
* then n times is the Colour struct for this line */
const Colour *src_px = (const Colour *)(src->data + src->offset[zoom][0]);
const Colour *src_px = reinterpret_cast<const Colour *>(src->data + src->offset[0][zoom]);
/* src_n : each line begins with uint32_t n = 'number of bytes in this line',
* then interleaved stream of 'm' and 'n' channels. 'm' is remap,
* 'n' is number of bytes with the same alpha channel class */
const uint16_t *src_n = (const uint16_t *)(src->data + src->offset[zoom][1]);
const uint16_t *src_n = reinterpret_cast<const uint16_t *>(src->data + src->offset[1][zoom]);
/* skip upper lines in src_px and src_n */
for (uint i = bp->skip_top; i != 0; i--) {
@@ -285,12 +285,13 @@ void Blitter_32bppOptimized::Draw(Blitter::BlitterParams *bp, BlitterMode mode,
this->Draw<false>(bp, mode, zoom);
}
template <bool Tpal_to_rgb> Sprite *Blitter_32bppOptimized::EncodeInternal(const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator)
template <bool Tpal_to_rgb>
Sprite *Blitter_32bppOptimized::EncodeInternal(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator)
{
/* streams of pixels (a, r, g, b channels)
*
* stored in separated stream so data are always aligned on 4B boundary */
std::array<std::unique_ptr<Colour[]>, ZOOM_LVL_END> dst_px_orig;
SpriteCollMap<std::unique_ptr<Colour[]>> dst_px_orig;
/* interleaved stream of 'm' channel and 'n' channel
* 'n' is number of following pixels with the same alpha channel class
@@ -298,21 +299,21 @@ template <bool Tpal_to_rgb> Sprite *Blitter_32bppOptimized::EncodeInternal(const
*
* it has to be stored in one stream so fewer registers are used -
* x86 has problems with register allocation even with this solution */
std::array<std::unique_ptr<uint16_t[]>, ZOOM_LVL_END> dst_n_orig;
SpriteCollMap<std::unique_ptr<uint16_t[]>> dst_n_orig;
/* lengths of streams */
uint32_t lengths[ZOOM_LVL_END][2];
SpriteCollMap<uint32_t> lengths[2];
ZoomLevel zoom_min;
ZoomLevel zoom_max;
if (sprite[ZOOM_LVL_MIN].type == SpriteType::Font) {
zoom_min = ZOOM_LVL_MIN;
zoom_max = ZOOM_LVL_MIN;
if (sprite_type == SpriteType::Font) {
zoom_min = ZoomLevel::Min;
zoom_max = ZoomLevel::Min;
} else {
zoom_min = _settings_client.gui.zoom_min;
zoom_max = _settings_client.gui.zoom_max;
if (zoom_max == zoom_min) zoom_max = ZOOM_LVL_MAX;
if (zoom_max == zoom_min) zoom_max = ZoomLevel::Max;
}
for (ZoomLevel z = zoom_min; z <= zoom_max; z++) {
@@ -405,40 +406,43 @@ template <bool Tpal_to_rgb> Sprite *Blitter_32bppOptimized::EncodeInternal(const
dst_n_ln = (uint32_t *)dst_n;
}
lengths[z][0] = reinterpret_cast<uint8_t *>(dst_px_ln) - reinterpret_cast<uint8_t *>(dst_px_orig[z].get()); // all are aligned to 4B boundary
lengths[z][1] = reinterpret_cast<uint8_t *>(dst_n_ln) - reinterpret_cast<uint8_t *>(dst_n_orig[z].get());
lengths[0][z] = reinterpret_cast<uint8_t *>(dst_px_ln) - reinterpret_cast<uint8_t *>(dst_px_orig[z].get()); // all are aligned to 4B boundary
lengths[1][z] = reinterpret_cast<uint8_t *>(dst_n_ln) - reinterpret_cast<uint8_t *>(dst_n_orig[z].get());
}
uint len = 0; // total length of data
for (ZoomLevel z = zoom_min; z <= zoom_max; z++) {
len += lengths[z][0] + lengths[z][1];
len += lengths[0][z] + lengths[1][z];
}
Sprite *dest_sprite = allocator.Allocate<Sprite>(sizeof(*dest_sprite) + sizeof(SpriteData) + len);
dest_sprite->height = sprite[ZOOM_LVL_MIN].height;
dest_sprite->width = sprite[ZOOM_LVL_MIN].width;
dest_sprite->x_offs = sprite[ZOOM_LVL_MIN].x_offs;
dest_sprite->y_offs = sprite[ZOOM_LVL_MIN].y_offs;
const auto &root_sprite = sprite.Root();
dest_sprite->height = root_sprite.height;
dest_sprite->width = root_sprite.width;
dest_sprite->x_offs = root_sprite.x_offs;
dest_sprite->y_offs = root_sprite.y_offs;
SpriteData *dst = (SpriteData *)dest_sprite->data;
memset(dst, 0, sizeof(*dst));
uint32_t offset = 0;
for (ZoomLevel z = zoom_min; z <= zoom_max; z++) {
dst->offset[z][0] = z == zoom_min ? 0 : lengths[z - 1][1] + dst->offset[z - 1][1];
dst->offset[z][1] = lengths[z][0] + dst->offset[z][0];
dst->offset[0][z] = offset;
offset += lengths[0][z];
dst->offset[1][z] = offset;
offset += lengths[1][z];
memcpy(dst->data + dst->offset[z][0], dst_px_orig[z].get(), lengths[z][0]);
memcpy(dst->data + dst->offset[z][1], dst_n_orig[z].get(), lengths[z][1]);
std::copy_n(reinterpret_cast<uint8_t *>(dst_px_orig[z].get()), lengths[0][z], dst->data + dst->offset[0][z]);
std::copy_n(reinterpret_cast<uint8_t *>(dst_n_orig[z].get()), lengths[1][z], dst->data + dst->offset[1][z]);
}
return dest_sprite;
}
template Sprite *Blitter_32bppOptimized::EncodeInternal<true>(const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator);
template Sprite *Blitter_32bppOptimized::EncodeInternal<false>(const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator);
template Sprite *Blitter_32bppOptimized::EncodeInternal<true>(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator);
template Sprite *Blitter_32bppOptimized::EncodeInternal<false>(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator);
Sprite *Blitter_32bppOptimized::Encode(const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator)
Sprite *Blitter_32bppOptimized::Encode(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator)
{
return this->EncodeInternal<true>(sprite, allocator);
return this->EncodeInternal<true>(sprite_type, sprite, allocator);
}
+3 -3
View File
@@ -17,12 +17,12 @@ class Blitter_32bppOptimized : public Blitter_32bppSimple {
public:
/** Data stored about a (single) sprite. */
struct SpriteData {
uint32_t offset[ZOOM_LVL_END][2]; ///< Offsets (from .data) to streams for different zoom levels, and the normal and remap image information.
SpriteCollMap<uint32_t> offset[2]; ///< Offsets (from .data) to streams for different zoom levels, and the normal and remap image information.
uint8_t data[]; ///< Data, all zoomlevels.
};
void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom) override;
Sprite *Encode(const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator) override;
Sprite *Encode(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator) override;
std::string_view GetName() override { return "32bpp-optimized"; }
@@ -30,7 +30,7 @@ public:
protected:
template <bool Tpal_to_rgb> void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom);
template <bool Tpal_to_rgb> Sprite *EncodeInternal(const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator);
template <bool Tpal_to_rgb> Sprite *EncodeInternal(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator);
};
/** Factory for the optimised 32 bpp blitter (without palette animation). */
+10 -9
View File
@@ -115,20 +115,21 @@ void Blitter_32bppSimple::DrawColourMappingRect(void *dst, int width, int height
Debug(misc, 0, "32bpp blitter doesn't know how to draw this colour table ('{}')", pal);
}
Sprite *Blitter_32bppSimple::Encode(const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator)
Sprite *Blitter_32bppSimple::Encode(SpriteType, const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator)
{
const auto &root_sprite = sprite.Root();
Blitter_32bppSimple::Pixel *dst;
Sprite *dest_sprite = allocator.Allocate<Sprite>(sizeof(*dest_sprite) + static_cast<size_t>(sprite[ZOOM_LVL_MIN].height) * static_cast<size_t>(sprite[ZOOM_LVL_MIN].width) * sizeof(*dst));
Sprite *dest_sprite = allocator.Allocate<Sprite>(sizeof(*dest_sprite) + static_cast<size_t>(root_sprite.height) * static_cast<size_t>(root_sprite.width) * sizeof(*dst));
dest_sprite->height = sprite[ZOOM_LVL_MIN].height;
dest_sprite->width = sprite[ZOOM_LVL_MIN].width;
dest_sprite->x_offs = sprite[ZOOM_LVL_MIN].x_offs;
dest_sprite->y_offs = sprite[ZOOM_LVL_MIN].y_offs;
dest_sprite->height = root_sprite.height;
dest_sprite->width = root_sprite.width;
dest_sprite->x_offs = root_sprite.x_offs;
dest_sprite->y_offs = root_sprite.y_offs;
dst = (Blitter_32bppSimple::Pixel *)dest_sprite->data;
SpriteLoader::CommonPixel *src = (SpriteLoader::CommonPixel *)sprite[ZOOM_LVL_MIN].data;
dst = reinterpret_cast<Blitter_32bppSimple::Pixel *>(dest_sprite->data);
SpriteLoader::CommonPixel *src = reinterpret_cast<SpriteLoader::CommonPixel *>(root_sprite.data);
for (int i = 0; i < sprite[ZOOM_LVL_MIN].height * sprite[ZOOM_LVL_MIN].width; i++) {
for (int i = 0; i < root_sprite.height * root_sprite.width; i++) {
if (src->m == 0) {
dst[i].r = src->r;
dst[i].g = src->g;
+1 -1
View File
@@ -26,7 +26,7 @@ class Blitter_32bppSimple : public Blitter_32bppBase {
public:
void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom) override;
void DrawColourMappingRect(void *dst, int width, int height, PaletteID pal) override;
Sprite *Encode(const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator) override;
Sprite *Encode(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator) override;
std::string_view GetName() override { return "32bpp-simple"; }
};
+22 -19
View File
@@ -20,18 +20,18 @@
/** Instantiation of the SSE2 32bpp blitter factory. */
static FBlitter_32bppSSE2 iFBlitter_32bppSSE2;
Sprite *Blitter_32bppSSE_Base::Encode(const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator)
Sprite *Blitter_32bppSSE_Base::Encode(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator)
{
/* First uint32_t of a line = the number of transparent pixels from the left.
* Second uint32_t of a line = the number of transparent pixels from the right.
* Then all RGBA then all MV.
*/
ZoomLevel zoom_min = ZOOM_LVL_MIN;
ZoomLevel zoom_max = ZOOM_LVL_MIN;
if (sprite[ZOOM_LVL_MIN].type != SpriteType::Font) {
ZoomLevel zoom_min = ZoomLevel::Min;
ZoomLevel zoom_max = ZoomLevel::Min;
if (sprite_type != SpriteType::Font) {
zoom_min = _settings_client.gui.zoom_min;
zoom_max = _settings_client.gui.zoom_max;
if (zoom_max == zoom_min) zoom_max = ZOOM_LVL_MAX;
if (zoom_max == zoom_min) zoom_max = ZoomLevel::Max;
}
/* Calculate sizes and allocate. */
@@ -39,23 +39,25 @@ Sprite *Blitter_32bppSSE_Base::Encode(const SpriteLoader::SpriteCollection &spri
uint all_sprites_size = 0;
for (ZoomLevel z = zoom_min; z <= zoom_max; z++) {
const SpriteLoader::Sprite *src_sprite = &sprite[z];
sd.infos[z].sprite_width = src_sprite->width;
sd.infos[z].sprite_offset = all_sprites_size;
sd.infos[z].sprite_line_size = sizeof(Colour) * src_sprite->width + sizeof(uint32_t) * META_LENGTH;
auto &info = sd.infos[z];
info.sprite_width = src_sprite->width;
info.sprite_offset = all_sprites_size;
info.sprite_line_size = sizeof(Colour) * src_sprite->width + sizeof(uint32_t) * META_LENGTH;
const uint rgba_size = sd.infos[z].sprite_line_size * src_sprite->height;
sd.infos[z].mv_offset = all_sprites_size + rgba_size;
const uint rgba_size = info.sprite_line_size * src_sprite->height;
info.mv_offset = all_sprites_size + rgba_size;
const uint mv_size = sizeof(MapValue) * src_sprite->width * src_sprite->height;
all_sprites_size += rgba_size + mv_size;
}
Sprite *dst_sprite = allocator.Allocate<Sprite>(sizeof(Sprite) + sizeof(SpriteData) + all_sprites_size);
dst_sprite->height = sprite[ZOOM_LVL_MIN].height;
dst_sprite->width = sprite[ZOOM_LVL_MIN].width;
dst_sprite->x_offs = sprite[ZOOM_LVL_MIN].x_offs;
dst_sprite->y_offs = sprite[ZOOM_LVL_MIN].y_offs;
memcpy(dst_sprite->data, &sd, sizeof(SpriteData));
const auto &root_sprite = sprite.Root();
dst_sprite->height = root_sprite.height;
dst_sprite->width = root_sprite.width;
dst_sprite->x_offs = root_sprite.x_offs;
dst_sprite->y_offs = root_sprite.y_offs;
std::copy_n(reinterpret_cast<std::byte *>(&sd), sizeof(SpriteData), dst_sprite->data);
/* Copy colours and determine flags. */
bool has_remap = false;
@@ -64,8 +66,9 @@ Sprite *Blitter_32bppSSE_Base::Encode(const SpriteLoader::SpriteCollection &spri
for (ZoomLevel z = zoom_min; z <= zoom_max; z++) {
const SpriteLoader::Sprite *src_sprite = &sprite[z];
const SpriteLoader::CommonPixel *src = (const SpriteLoader::CommonPixel *) src_sprite->data;
Colour *dst_rgba_line = (Colour *) &dst_sprite->data[sizeof(SpriteData) + sd.infos[z].sprite_offset];
MapValue *dst_mv = (MapValue *) &dst_sprite->data[sizeof(SpriteData) + sd.infos[z].mv_offset];
const auto &info = sd.infos[z];
Colour *dst_rgba_line = reinterpret_cast<Colour *>(&dst_sprite->data[sizeof(SpriteData) + info.sprite_offset]);
MapValue *dst_mv = reinterpret_cast<MapValue *>(&dst_sprite->data[sizeof(SpriteData) + info.mv_offset]);
for (uint y = src_sprite->height; y != 0; y--) {
Colour *dst_rgba = dst_rgba_line + META_LENGTH;
for (uint x = src_sprite->width; x != 0; x--) {
@@ -113,7 +116,7 @@ Sprite *Blitter_32bppSSE_Base::Encode(const SpriteLoader::SpriteCollection &spri
(*dst_rgba_line).data = nb_pix_transp;
Colour *nb_right = dst_rgba_line + 1;
dst_rgba_line = (Colour*) ((uint8_t*) dst_rgba_line + sd.infos[z].sprite_line_size);
dst_rgba_line = reinterpret_cast<Colour *>(reinterpret_cast<std::byte *>(dst_rgba_line) + info.sprite_line_size);
/* Count the number of transparent pixels from the right. */
dst_rgba = dst_rgba_line - 1;
@@ -132,7 +135,7 @@ Sprite *Blitter_32bppSSE_Base::Encode(const SpriteLoader::SpriteCollection &spri
if (has_translucency) sd.flags.Set(SpriteFlag::Translucent);
if (!has_remap) sd.flags.Set(SpriteFlag::NoRemap);
if (!has_anim) sd.flags.Set(SpriteFlag::NoAnim);
memcpy(dst_sprite->data, &sd, sizeof(SpriteData));
std::copy_n(reinterpret_cast<std::byte *>(&sd), sizeof(SpriteData), dst_sprite->data);
return dst_sprite;
}
+5 -4
View File
@@ -73,11 +73,11 @@ public:
};
struct SpriteData {
SpriteFlags flags{};
std::array<SpriteInfo, ZOOM_LVL_END> infos{};
SpriteCollMap<SpriteInfo> infos{};
uint8_t data[]; ///< Data, all zoomlevels.
};
Sprite *Encode(const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator);
Sprite *Encode(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator);
};
/** The SSE2 32 bpp blitter (without palette animation). */
@@ -87,8 +87,9 @@ public:
template <BlitterMode mode, Blitter_32bppSSE_Base::ReadMode read_mode, Blitter_32bppSSE_Base::BlockType bt_last, bool translucent>
void Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom);
Sprite *Encode(const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator) override {
return Blitter_32bppSSE_Base::Encode(sprite, allocator);
Sprite *Encode(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator) override
{
return Blitter_32bppSSE_Base::Encode(sprite_type, sprite, allocator);
}
std::string_view GetName() override { return "32bpp-sse2"; }
+1 -1
View File
@@ -309,8 +309,8 @@ inline void Blitter_32bppSSE4::Draw(const Blitter::BlitterParams *bp, ZoomLevel
/* Remap colours. */
if (mvX2 & 0x00FF00FF) {
/* Written so the compiler uses CMOV. */
#define CMOV_REMAP(m_colour, m_colour_init, m_src, m_m) \
/* Written so the compiler uses CMOV. */ \
Colour m_colour = m_colour_init; \
{ \
const Colour srcm = (Colour) (m_src); \
+2 -10
View File
@@ -28,18 +28,10 @@
#endif
#define META_LENGTH 2 ///< Number of uint32_t inserted before each line of pixels in a sprite.
#define MARGIN_NORMAL_THRESHOLD (zoom == ZOOM_LVL_OUT_8X ? 8 : 4) ///< Minimum width to use margins with BlitterMode::Normal.
#define MARGIN_NORMAL_THRESHOLD (zoom == ZoomLevel::Out8x ? 8 : 4) ///< Minimum width to use margins with BlitterMode::Normal.
#define MARGIN_REMAP_THRESHOLD 4 ///< Minimum width to use margins with BlitterMode::ColourRemap.
#undef ALIGN
#ifdef _MSC_VER
#define ALIGN(n) __declspec(align(n))
#else
#define ALIGN(n) __attribute__ ((aligned (n)))
#endif
typedef union ALIGN(16) um128i {
typedef union alignas(16) um128i {
__m128i m128i;
uint8_t m128i_u8[16];
uint16_t m128i_u16[8];
+22 -29
View File
@@ -27,7 +27,7 @@ static FBlitter_40bppAnim iFBlitter_40bppAnim;
static const Colour _black_colour(0, 0, 0);
void Blitter_40bppAnim::SetPixel(void *video, int x, int y, uint8_t colour)
void Blitter_40bppAnim::SetPixel(void *video, int x, int y, PixelColour colour)
{
if (_screen_disable_anim) {
Blitter_32bppOptimized::SetPixel(video, x, y, colour);
@@ -35,11 +35,11 @@ void Blitter_40bppAnim::SetPixel(void *video, int x, int y, uint8_t colour)
size_t y_offset = static_cast<size_t>(y) * _screen.pitch;
*((Colour *)video + x + y_offset) = _black_colour;
VideoDriver::GetInstance()->GetAnimBuffer()[((uint32_t *)video - (uint32_t *)_screen.dst_ptr) + x + y_offset] = colour;
VideoDriver::GetInstance()->GetAnimBuffer()[((uint32_t *)video - (uint32_t *)_screen.dst_ptr) + x + y_offset] = colour.p;
}
}
void Blitter_40bppAnim::DrawRect(void *video, int width, int height, uint8_t colour)
void Blitter_40bppAnim::DrawRect(void *video, int width, int height, PixelColour colour)
{
if (_screen_disable_anim) {
/* This means our output is not to the screen, so we can't be doing any animation stuff, so use our parent DrawRect() */
@@ -56,7 +56,7 @@ void Blitter_40bppAnim::DrawRect(void *video, int width, int height, uint8_t col
for (int i = width; i > 0; i--) {
*dst = _black_colour;
*anim = colour;
*anim = colour.p;
dst++;
anim++;
}
@@ -65,7 +65,7 @@ void Blitter_40bppAnim::DrawRect(void *video, int width, int height, uint8_t col
} while (--height);
}
void Blitter_40bppAnim::DrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, uint8_t colour, int width, int dash)
void Blitter_40bppAnim::DrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, PixelColour colour, int width, int dash)
{
if (_screen_disable_anim) {
/* This means our output is not to the screen, so we can't be doing any animation stuff, so use our parent DrawRect() */
@@ -78,7 +78,7 @@ void Blitter_40bppAnim::DrawLine(void *video, int x, int y, int x2, int y2, int
this->DrawLineGeneric(x, y, x2, y2, screen_width, screen_height, width, dash, [=](int x, int y) {
*((Colour *)video + x + y * _screen.pitch) = _black_colour;
*(anim + x + y * _screen.pitch) = colour;
*(anim + x + y * _screen.pitch) = colour.p;
});
}
@@ -96,11 +96,11 @@ inline void Blitter_40bppAnim::Draw(const Blitter::BlitterParams *bp, ZoomLevel
/* src_px : each line begins with uint32_t n = 'number of bytes in this line',
* then n times is the Colour struct for this line */
const Colour *src_px = (const Colour *)(src->data + src->offset[zoom][0]);
const Colour *src_px = reinterpret_cast<const Colour *>(src->data + src->offset[0][zoom]);
/* src_n : each line begins with uint32_t n = 'number of bytes in this line',
* then interleaved stream of 'm' and 'n' channels. 'm' is remap,
* 'n' is number of bytes with the same alpha channel class */
const uint16_t *src_n = (const uint16_t *)(src->data + src->offset[zoom][1]);
const uint16_t *src_n = reinterpret_cast<const uint16_t *>(src->data + src->offset[1][zoom]);
/* skip upper lines in src_px and src_n */
for (uint i = bp->skip_top; i != 0; i--) {
@@ -377,8 +377,11 @@ void Blitter_40bppAnim::DrawColourMappingRect(void *dst, int width, int height,
const uint8_t *remap = GetNonSprite(pal, SpriteType::Recolour) + 1;
do {
for (int i = 0; i != width; i++) {
if (*anim == 0) *udst = MakeGrey(*udst);
*anim = remap[*anim];
if (*anim == 0) {
*udst = MakeGrey(*udst);
} else {
*anim = remap[*anim];
}
udst++;
anim++;
}
@@ -389,7 +392,7 @@ void Blitter_40bppAnim::DrawColourMappingRect(void *dst, int width, int height,
const uint8_t *remap = GetNonSprite(pal, SpriteType::Recolour) + 1;
do {
for (int i = 0; i != width; i++) {
*anim = remap[*anim];
if (*anim != 0) *anim = remap[*anim];
anim++;
}
anim = anim - width + _screen.pitch;
@@ -397,9 +400,9 @@ void Blitter_40bppAnim::DrawColourMappingRect(void *dst, int width, int height,
}
}
Sprite *Blitter_40bppAnim::Encode(const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator)
Sprite *Blitter_40bppAnim::Encode(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator)
{
return this->EncodeInternal<false>(sprite, allocator);
return this->EncodeInternal<false>(sprite_type, sprite, allocator);
}
@@ -415,11 +418,11 @@ void Blitter_40bppAnim::CopyFromBuffer(void *video, const void *src, int width,
uint8_t *anim_line = ((uint32_t *)video - (uint32_t *)_screen.dst_ptr) + anim_buf;
for (; height > 0; height--) {
memcpy(dst, usrc, width * sizeof(uint32_t));
std::copy_n(usrc, width, dst);
usrc += width;
dst += _screen.pitch;
/* Copy back the anim-buffer */
memcpy(anim_line, usrc, width * sizeof(uint8_t));
std::copy_n(reinterpret_cast<const uint8_t *>(usrc), width, anim_line);
usrc = (const uint32_t *)((const uint8_t *)usrc + width);
anim_line += _screen.pitch;
}
@@ -437,11 +440,11 @@ void Blitter_40bppAnim::CopyToBuffer(const void *video, void *dst, int width, in
const uint8_t *anim_line = ((const uint32_t *)video - (uint32_t *)_screen.dst_ptr) + anim_buf;
for (; height > 0; height--) {
memcpy(udst, src, width * sizeof(uint32_t));
std::copy_n(src, width, udst);
src += _screen.pitch;
udst += width;
/* Copy the anim-buffer */
memcpy(udst, anim_line, width * sizeof(uint8_t));
std::copy_n(anim_line, width, reinterpret_cast<uint8_t *>(udst));
udst = (uint32_t *)((uint8_t *)udst + width);
anim_line += _screen.pitch;
}
@@ -490,11 +493,7 @@ void Blitter_40bppAnim::ScrollBuffer(void *video, int &left, int &top, int &widt
uint tw = width + (scroll_x >= 0 ? -scroll_x : scroll_x);
uint th = height - scroll_y;
for (; th > 0; th--) {
memcpy(dst, src, tw * sizeof(uint8_t));
src -= _screen.pitch;
dst -= _screen.pitch;
}
Blitter::MovePixels(src, dst, tw, th, -_screen.pitch);
} else {
/* Calculate pointers */
dst = anim_buf + left + top * _screen.pitch;
@@ -507,15 +506,9 @@ void Blitter_40bppAnim::ScrollBuffer(void *video, int &left, int &top, int &widt
src -= scroll_x;
}
/* the y-displacement may be 0 therefore we have to use memmove,
* because source and destination may overlap */
uint tw = width + (scroll_x >= 0 ? -scroll_x : scroll_x);
uint th = height + scroll_y;
for (; th > 0; th--) {
memmove(dst, src, tw * sizeof(uint8_t));
src += _screen.pitch;
dst += _screen.pitch;
}
Blitter::MovePixels(src, dst, tw, th, _screen.pitch);
}
Blitter_32bppBase::ScrollBuffer(video, left, top, width, height, scroll_x, scroll_y);
+4 -4
View File
@@ -18,16 +18,16 @@
class Blitter_40bppAnim : public Blitter_32bppOptimized {
public:
void SetPixel(void *video, int x, int y, uint8_t colour) override;
void DrawRect(void *video, int width, int height, uint8_t colour) override;
void DrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, uint8_t colour, int width, int dash) override;
void SetPixel(void *video, int x, int y, PixelColour colour) override;
void DrawRect(void *video, int width, int height, PixelColour colour) override;
void DrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, PixelColour colour, int width, int dash) override;
void CopyFromBuffer(void *video, const void *src, int width, int height) override;
void CopyToBuffer(const void *video, void *dst, int width, int height) override;
void CopyImageToBuffer(const void *video, void *dst, int width, int height, int dst_pitch) override;
void ScrollBuffer(void *video, int &left, int &top, int &width, int &height, int scroll_x, int scroll_y) override;
void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom) override;
void DrawColourMappingRect(void *dst, int width, int height, PaletteID pal) override;
Sprite *Encode(const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator) override;
Sprite *Encode(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator) override;
size_t BufferSize(uint width, uint height) override;
Blitter::PaletteAnimation UsePaletteAnimation() override;
bool NeedsAnimationBuffer() override;

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