Compare commits

...

334 Commits

Author SHA1 Message Date
penev92
54675d6f2b Fixed packaging for Windows missing assembly info
Apparently building/publishing/packaging for Windows on Linux using .NET 6 sets some of the assembly / Portable Executable information for the generated DLL, but nothing for the generated EXE (which isn't the case when building on Windows).
2023-04-14 19:40:08 +03:00
penev92
2101e74470 Added product version to assembly info 2023-04-14 18:42:33 +03:00
penev92
73ccc83971 Added project information in Directory.Build.props 2023-04-14 18:42:29 +03:00
Ivaylo Draganov
96d023de87 Don't change cursor when mousing over label widgets
Labels don't handle input so the cursor should not change over them.
2023-04-12 12:09:50 +03:00
Gustas
3ca2bb1d23 Fix IDE0074, SA1316 and followup CS8141 2023-04-09 10:26:04 +01:00
RoosterDragon
595717fff0 Enable Code Quality Rules
Enforces a variety of CAxxxx rules that do not have existing violations.

For the benefit of dotnet_code_quality.CA2241.try_determine_additional_string_formatting_methods_automatically = true, rename parameters of methods that forward to string.Format so format issues will get detected automatically.
2023-04-08 23:15:40 +02:00
Gustas
d838d08570 Add IColorPickerManagerInfo interface 2023-04-08 18:05:20 +03:00
darkademic
265f915442 Resurrected old colour picker. 2023-04-08 18:05:20 +03:00
RoosterDragon
dcac966d49 Don't enable IDE0063, IDE0078. 2023-04-08 16:51:51 +03:00
RoosterDragon
4110c199fb Enable IDE0150, CA1845 2023-04-08 16:51:51 +03:00
RoosterDragon
14c0d011ea Fix SA1414 2023-04-08 16:51:51 +03:00
RoosterDragon
a167f9680f Fix SA1316 2023-04-08 16:51:51 +03:00
RoosterDragon
062dc2bd40 Fix SA1141 2023-04-08 16:51:51 +03:00
RoosterDragon
1ce9acd442 Fix IDE0110 2023-04-08 16:51:51 +03:00
RoosterDragon
8a285f9b19 Fix IDE0090 2023-04-08 16:51:51 +03:00
RoosterDragon
164abfdae1 Fix IDE0083 2023-04-08 16:51:51 +03:00
RoosterDragon
bd2b3d9793 Fix IDE0074 2023-04-08 16:51:51 +03:00
RoosterDragon
cbd0583289 Fix IDE0062 2023-04-08 16:51:51 +03:00
RoosterDragon
023d80b94d Fix IDE0057 2023-04-08 16:51:51 +03:00
RoosterDragon
5254348819 Fix IDE0056 2023-04-08 16:51:51 +03:00
RoosterDragon
4ec5a4b34a Fix reversed path searches from inaccessible locations.
The Harvester trait and MoveAdjacentTo activity called the pathfinder but had a single source and multiple targets. The pathfinder interface only allows for the opposite: multiple sources and a single target. To work around this they would swap the inputs. This works in most cases but not all cases. One aspect of asymmetry is that an actor may move out of an inaccessible source cell, but not onto an inaccessible target cell.

Searches that involved an inaccessible source cell and that applied this swapping method would therefore fail to return a path, when a valid path was possible. Although a rare case, once good way to reproduce is to use a production building that spawns actors on inaccessible cells around it, such as the RA naval yard. A move order uses the pathfinder correctly and the unit will move out. Using a force attack causes the unit to use the broken "swapped" mechanism in MoveAdjacentTo and it will be stuck.

This asymmetry has been longstanding but the pathfinding infrastructure only sporadically accounted for it. It is now documented and applied consistently. Create a new overload on the pathfinder trait that allows a single source and multiple targets, so callers have an overload that does what they need and won't be tempted to swap the positions and run into this issue.

Internally, this requires us to teach Locomotor to ignore the self actor when performing movement cost checks for these "in reverse" searches so the unit doesn't consider the cell blocked by itself.
2023-04-07 16:38:37 +01:00
Gustas
e4ba9733fe Add sequences linting to ingame lobby 2023-04-07 16:23:30 +01:00
IceReaper
a332fba702 IDFiles should be optional. 2023-04-05 21:13:11 +02:00
RoosterDragon
83561d639d Update LangVersion to C# 9.
mono was the bottleneck restricting our ability to use a newer C# version. mono 6.12 is currently available. Although poorly documented on their website, this supports C# 9. https://www.mono-project.com/docs/about-mono/versioning/#mono-source-versioning indicates mono 6.12 uses Roslyn 3.9.0. https://github.com/dotnet/roslyn/blob/main/docs/wiki/NuGet-packages.md#versioning indicates Roslyn 3.9.0 supports C# 9.

This unlocks C# 8 and C# 9 features previously unavailable to us.
- https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-version-history#c-version-80
- https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-version-history#c-version-9

A newer version of StyleCop is required to avoid rules tripping up on the new syntax. Currently only prerelease versions are available but their use is encouraged https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3420#issuecomment-994899135

Fix style rule violations on existing rules where the newer language version makes some existing casts redundant or allows use of the null coalescing assignment operator.
2023-04-05 15:27:41 +03:00
RoosterDragon
9dd4f938da Cache reflection calls when running utility lints and commands.
Reduces runtime of --check-yaml command to 70% of original.
2023-04-05 00:25:32 +02:00
Gustas
1a2aafa17c Fix backwards movement not canceling when BackwardDuration times out 2023-04-04 20:25:04 +02:00
Gustas
a4e80e1153 Fix backwards movement not working correctly when turning in an arc 2023-04-04 20:25:04 +02:00
dnqbob
a261abbc3f Using support power uncloak TS superweapon 2023-04-04 18:26:11 +03:00
dnqbob
27f780c5d1 Using support power can uncloak actor 2023-04-04 18:26:11 +03:00
IceReaper
11ab4a7935 Support dos paths in registry. 2023-04-04 16:20:05 +02:00
IceReaper
4dd532f60e Implemented MP3 detection. 2023-04-03 20:05:52 +02:00
IceReaper
138715b509 Added Zip support to installer source actions. 2023-04-03 17:57:16 +02:00
IceReaper
d97df78f4f Steam and Gog resolvers now take IDFiles into account. 2023-04-03 17:57:16 +02:00
IceReaper
56c0680685 Fixed a typo. 2023-04-03 17:57:16 +02:00
RoosterDragon
95f675becd Improve performance of ActorInfo.TraitsInConstructOrder.
Avoid redundant enumerations of the more and unresolved enumerables. This gives an approx 3x speedup for this function.
2023-04-03 17:29:08 +03:00
ThomasChr
a5ef6801c9 fix two crashes in hotkey menu, trying to select not visible widgets 2023-03-31 16:52:54 +03:00
abcdefg30
75a47aabb5 Don't always display the overwrite dialogue
When a save was selected but the filename text was changed,
we don't overwrite the existing save, so we don't need a dialogue
2023-03-31 16:32:09 +03:00
abcdefg30
73f29005bd Allow saving games by pressing enter 2023-03-31 16:32:09 +03:00
abcdefg30
f1d439a07f Make the save game title field take focus 2023-03-31 16:32:09 +03:00
penev92
9ce4ef0bff Updated ExtractEmmyLuaAPI command to fix issues
Issues:
 - The generated API file caused a ton of diagnostics warnings.
 - Perhaps due to EmmyLua moving forward since this was created, we were missing out on some features.

Changes:
 - Disabled diagnostics about missing return values for functions.
 - Added add operator definitions because by default CPos+CVec would be assumed to return a number and assignments would cause warnings about type mismatches.
 - Added explicit @enum annotations. This also fixed warnings in the generated API file about missing types.
 - Changed default type of properties from an empty table to nil. This fixed warnings in the generated API file about type mismatch.
 - Renamed local variable "required" -> "requiredTraits" for readability.
 - Disabled duplicate function/property  name warnings
 - Updated trait docs URL.
2023-03-31 11:46:28 +02:00
Thomas Christlieb
9e081763ad fix stance icon not updating when selecting units 2023-03-28 22:09:07 +03:00
Matthias Mailänder
378f66a1ff Resolve Lua language server diagnosed problems. 2023-03-28 11:45:15 +02:00
Matthias Mailänder
3d0efa1cbe Add EmmyLua notation to resolve the type. 2023-03-28 11:45:15 +02:00
Matthias Mailänder
cae07bb408 Remove uninitialized variable. 2023-03-28 11:45:15 +02:00
Matthias Mailänder
c94c1f8a6c Remove missing actors. 2023-03-28 11:45:15 +02:00
Matthias Mailänder
0847cd33bd Fix typos in mission scripts. 2023-03-28 11:45:15 +02:00
RoosterDragon
dc40442118 Fix doc comment on CanKickClient. 2023-03-27 20:55:44 +02:00
Gustas
2959a2c137 Fix warnings in LobbyCommand.cs 2023-03-27 20:15:17 +02:00
Gustas
bf00577d33 Allow kicking dead players 2023-03-27 20:15:17 +02:00
Gustas
c4bd9fb7aa Add quit button to connection lost panel 2023-03-27 20:02:54 +02:00
Gustas
482f2fc335 Fix inconsistent abort naming 2023-03-27 20:02:54 +02:00
Gustas
925e042455 Add Interactable lint test
Since # 19174 bounds are calculated from WDist instead of pixels. This causes many of the older maps to crash games, And this lint test makes it easier for map makers to detect these issues.

As calculating the bounds requires MapGrid, we need to write a separate lint test for Interactable instead of defaulting to RulesetLoaded checks.
2023-03-27 19:55:19 +02:00
Gustas
c525c48d25 Make sure submarines don't smoke underwater 2023-03-26 20:24:30 -05:00
Gustas
f90dba2c6b Add ^Submarine and make submarines inherit it 2023-03-26 20:24:30 -05:00
Gustas
e28f45f785 Use interpolated facings for submarines 2023-03-26 20:24:30 -05:00
Mustafa Alperen Seki
87eca8f2c0 Fix colors of paratroopers in the missions. 2023-03-26 17:49:02 -05:00
Mustafa Alperen Seki
960f829221 Move Soviets palette index definition to campaign-palettes.yaml. 2023-03-26 17:49:02 -05:00
RoosterDragon
8a4303cc94 Rework PriorityQueue for performance.
- Providing the comparer as a type argument that is a struct allows the calls to be devirtualised, leading to approx a 3x performance improvement.
- Use a single backing array, rather than a list of arrays.
2023-03-25 18:50:09 +01:00
penev92
7a4ac01348 Changed SequenceReferenceAttributes to use nameof 2023-03-24 18:51:36 +01:00
penev92
6dda4fa9f7 Fixed BuildableTerrainOverlay ignoring scale 2023-03-24 18:51:36 +01:00
Matthias Mailänder
af2b32e7ba Add particle smoke effects. 2023-03-23 12:15:16 +02:00
michaeldgg2
069b7c5500 RepairableBuilding: play/display notification when repair process is aborted. 2023-03-23 10:28:12 +01:00
michaeldgg2
ae1983faba ProductionQueue: make PauseProduction, CancelProduction virtual, CancelProductionInner protected 2023-03-20 12:17:55 +02:00
RoosterDragon
bcfa0c9ae9 Review StyleCop rules.
- Enforce SA1604 ElementDocumentationShouldHaveSummary.
- Enforce SA1629 DocumentationTextShouldEndWithAPeriod.
- Turn off some rules covered by IDExxxx rules.
- Remaining rules are treated as part of OpenRA style.
2023-03-18 12:46:10 +02:00
RoosterDragon
88ba974ea5 Reformat editorconfig
- Group style rules with their associated options in a way that matches the documentation. This makes it easier to pair rules and their options.
- Remove OpenRA.ruleset and move all rules into .editorconfig file.
- Centralise IDE0005 workaround in Directory.Build.props file.
2023-03-17 22:31:10 +01:00
RoosterDragon
721c03d9af Enforce additional style rules. 2023-03-17 22:31:10 +01:00
Gustas
384435f8eb Remove annoying autocomplete suffix 2023-03-16 21:07:21 +01:00
penev92
e808549637 Removed a redundant cast - IDE0004 2023-03-14 17:43:32 +01:00
penev92
bde13a8572 Fixed a bad merge 2023-03-14 17:43:32 +01:00
RoosterDragon
98c4eaca83 Fix IDE0032 2023-03-14 13:41:25 +02:00
michaeldgg2
e64c0a35c5 ProductionPaletteWidget: offset and align for queued count is now customizable 2023-03-12 15:10:26 +01:00
penev92
6bedc4697b Fix modcontent.chrome-3x.png
After it was changed to a version without padding.
2023-03-12 13:24:39 +02:00
Gustas
2dbefaf375 Cache font 2023-03-12 10:53:45 +01:00
Gustas
2050d55b21 Add player's name to super weapon timers 2023-03-12 10:53:45 +01:00
penev92
d61178de41 Added tooltips to ContentPackages 2023-03-11 21:43:18 +01:00
penev92
9cb2d19654 Added checkbox tick artwork to modcontent's chrome 2023-03-11 21:43:18 +01:00
penev92
8a59982420 Made Advanced installation offer optional packages
Previously all detected content would be installed. Now the user can choose whether they want to install the optional packages like music and videos.
2023-03-11 21:43:18 +01:00
penev92
c5aee7b2cf Added Title and Identifier as fields of ModPackage 2023-03-11 21:43:18 +01:00
penev92
d0285b058b Grouped installer SourceActions by ContentPackage
ContentPackages are defined in mod.yaml and list Installers that support them, but then the Installers and their SourceActions knew nothing about ContentPackages.
Also added BeforeInstall and AfterInstall sections for SourceActions in the Installers.
2023-03-11 21:43:18 +01:00
abcdefg30
64e84554d3 Fix empty mission objectives getting translated 2023-03-11 21:07:02 +01:00
Gustas
8a18c2e4b6 Add a CanDeploy check to Transform at FrameEndTask 2023-03-11 21:00:51 +01:00
abcdefg30
43bb9e4302 Fix the map.yaml formatting of some new D2k maps 2023-03-11 20:56:32 +01:00
abcdefg30
cb8921dc22 Fix the sequence filename update rule node placement 2023-03-11 20:56:32 +01:00
abcdefg30
64933ed04b Fix sequence inheritance defined in yaml
Nodes need to be placed after "Inherits" nodes so that they take
precedence over the inherited nodes.
2023-03-11 20:56:32 +01:00
abcdefg30
040fbf9694 Make Wanders and AttackWander queue activities instead of resolving orders 2023-03-11 20:47:34 +01:00
Wylli
4500d964b3 Update AUTHORS
Update AUTHORS
2023-03-10 20:35:56 +01:00
IceReaper
fceab4f388 Allow mods to override production widgets text colors. 2023-03-10 20:31:15 +01:00
Guillermoqnk
b3d468aca1 Fix return fire logic ignoring AutoAttack priotities
Added brand new feature

Unnecessary assignmet removed
2023-03-10 20:18:10 +02:00
Paul Chote
3b0b15abb9 Reduce duplication and allocations around CalculateFrameIndices. 2023-03-10 20:11:33 +02:00
Paul Chote
f0cf728825 Dispose SequenceSet when we're done with it.
Utility rules that do something on a map and exit
are left without explicit disposing, as they will
be cleaned up immediately anyway.
2023-03-10 20:11:33 +02:00
Paul Chote
c35ab081ff Rewrite sequence loading logic.
Multiple layers of Lazy<T>ness are replaced with
an explicit two-part loading scheme.

Sequences are parsed immediately, without the need
for the sprite assets, and tell the SpriteCache
which frames they need. Use-cases that want the
actual sprites can then tell the SpriteCache to
load the frames and the sequences to resolve the
sprites.
2023-03-10 20:11:33 +02:00
Paul Chote
1f3403717b Fix negative sequence lengths. 2023-03-10 20:11:33 +02:00
Paul Chote
a6f3db0a45 Allow all sprites to use interpolated facings. 2023-03-10 20:11:33 +02:00
Paul Chote
b051211842 Remove internal state from ISpriteSequence API. 2023-03-10 20:11:33 +02:00
Paul Chote
279869b4c5 Fix --dump-sequence-sheets utility command.
Also formats output filenames to specify
indexed sprite channels.
2023-03-10 20:11:33 +02:00
Paul Chote
b69adb518a Remove asset browser dependency on sequences. 2023-03-10 20:11:33 +02:00
Paul Chote
b7cdcf419f Add ILintSequencesPass. 2023-03-10 20:11:33 +02:00
Paul Chote
7cd4272350 Access sequences from Map. 2023-03-10 20:11:33 +02:00
Paul Chote
992ba1a9a2 Remove HasEmbeddedPalette from sequences. 2023-03-10 20:11:33 +02:00
Gustas
dab3ca0025 Add support for dark player colors 2023-03-10 15:43:24 +02:00
RoosterDragon
939f715e3c Fix IDE0053 2023-03-07 13:18:13 +02:00
Matthias Mailänder
37afd6094e Rename GiveMcvCrateAction to GiveBaseBuilderCrateAction. 2023-03-07 12:53:31 +02:00
RoosterDragon
c916a00624 Remove workaround for old versions of mono. 2023-03-07 12:51:06 +02:00
Matthias Mailänder
f6e5bee334 Move JumpJet traits to the C&C library. 2023-03-07 12:24:05 +02:00
Matthias Mailänder
63b9f18d05 Also document the launch parameters. 2023-03-05 12:15:32 +02:00
Matthias Mailänder
7b9dafcd19 Code cleanup. 2023-03-05 12:15:32 +02:00
RoosterDragon
53e9f44972 Spelling fixes 2023-03-02 20:11:54 +02:00
RoosterDragon
52fd564eac Fix some whitespace formatting issues: stray tabs or spaces.
Wrap some long lines on affected code.
2023-03-02 20:02:45 +02:00
Matthias Mailänder
edaf11cb89 Update thirdparty dependencies. 2023-03-01 23:52:59 +01:00
RoosterDragon
ad122c8e32 When running a server, don't load minimap previews into memory. 2023-03-02 00:13:46 +02:00
RoosterDragon
8ee6957e6a Fix IDE0048 2023-03-01 21:56:28 +02:00
abcdefg30
65e28d5562 Retire the release-20200202 update path 2023-03-01 20:02:01 +01:00
Gustas
422a228cea Fix PlayerColorRemap expecting colors in linear space
PlayerColorRemap expected colors in linear space yet we provided them in gamma. We fix this by instead expecting gamma space colors and then converting them into linear space ourselves.
2023-02-28 23:26:37 +02:00
RoosterDragon
0b01b73111 Fix IDE0060 2023-02-28 21:21:40 +02:00
RoosterDragon
555aac3f64 Fix IDE0042 2023-02-28 21:21:40 +02:00
RoosterDragon
5b70d344cc Fix IDE0038 2023-02-28 21:21:40 +02:00
RoosterDragon
71ce515d6d Fix IDE0004 2023-02-28 21:21:40 +02:00
Eonfge
a4f9ceaf09 Add PrefersNonDefaultGPU flag to Desktop Entry
This means that the application will automatically start with the dedicated GPU of laptops, instead of the iGPU. Based on the Linux's FreeDesktop spec: https://specifications.freedesktop.org/desktop-entry-spec/latest/ar01s06.html
2023-02-27 10:42:07 +01:00
RoosterDragon
d4135d608e Fix IDE0039 2023-02-27 10:09:11 +01:00
Gustas
4b3f7034b2 Silence rule "Use span-based 'string.Concat'" 2023-02-27 08:36:47 +02:00
Gustas
e64c77fdde Use pattern matching to avoid is check followed by a cast (with variable) 2023-02-27 08:36:47 +02:00
Gustas
8d0fe52dd8 Remove unnecessary parentheses 2023-02-27 08:36:47 +02:00
Gustas
157d1b32dc Use null propagation 2023-02-27 08:36:47 +02:00
Gustas
b06cbd7a95 Add missing punctuation to editorconfig 2023-02-27 08:36:47 +02:00
Gustas
2cccae96fe Change click InterruptType to Overlap 2023-02-25 14:46:53 +02:00
Orb370
e758678140 update TD map pool 2023 2023-02-24 22:01:15 +01:00
RoosterDragon
6c96405ab2 Fix CS1573 2023-02-24 22:00:25 +02:00
RoosterDragon
63aa34cb35 Fix CS1570 2023-02-24 22:00:25 +02:00
RoosterDragon
5a2a448c32 Fix IDE0250 2023-02-24 22:00:25 +02:00
RoosterDragon
5e52d067c8 Fix IDE0180 2023-02-24 22:00:25 +02:00
RoosterDragon
bf960b6eae Fix IDE0120 2023-02-24 22:00:25 +02:00
RoosterDragon
ede5412526 Fix IDE0100 2023-02-24 22:00:25 +02:00
RoosterDragon
78c41b84a1 Fix IDE0082 2023-02-24 22:00:25 +02:00
RoosterDragon
99c289e063 Fix IDE0075 2023-02-24 22:00:25 +02:00
RoosterDragon
3402031399 Fix IDE0071 2023-02-24 22:00:25 +02:00
RoosterDragon
837c70f857 Fix IDE0061 2023-02-24 22:00:25 +02:00
RoosterDragon
4f6095c3d4 Fix IDE0054 2023-02-24 22:00:25 +02:00
RoosterDragon
2d4119e88d Fix IDE0051 2023-02-24 22:00:25 +02:00
RoosterDragon
4991f2f892 Fix IDE0041 2023-02-24 22:00:25 +02:00
RoosterDragon
10def52ad9 Fix IDE0033 2023-02-24 22:00:25 +02:00
RoosterDragon
99c1a4448b Fix IDE0030 2023-02-24 22:00:25 +02:00
RoosterDragon
8223161959 Fix IDE0029 2023-02-24 22:00:25 +02:00
RoosterDragon
67ba3e55de Fix IDE0020 2023-02-24 22:00:25 +02:00
RoosterDragon
6d7c73d498 Fix IDE0019 2023-02-24 22:00:25 +02:00
RoosterDragon
80bb828fe5 Fix IDE0018 2023-02-24 22:00:25 +02:00
RoosterDragon
b0dca05e50 Fix IDE0002 2023-02-24 22:00:25 +02:00
RoosterDragon
8b4500146f Fix IDE0001 2023-02-24 22:00:25 +02:00
Matthias Mailänder
ee35cbc0d0 Let bot Deviators prioritize vehicles. 2023-02-22 23:09:08 +01:00
Matthias Mailänder
0b6f335c9f Reference trait name in description. 2023-02-22 23:09:08 +01:00
Matthias Mailänder
40e8061797 Removed unused water terrain type from Dune 2000. 2023-02-22 23:09:08 +01:00
penev92
bb8e6ab03c Fix sprites with no frames crashing AssetBrowser 2023-02-22 11:25:17 +02:00
penev92
807bd4d06a Make AssetBrowser not case sensitive to file types 2023-02-22 11:25:17 +02:00
penev92
e1a7fb1cc8 Fixed displayed audio length in the AssetBrowser 2023-02-20 13:07:32 +01:00
Matthias Mailänder
5032b2b872 Extract translation strings. 2023-02-19 23:46:41 +01:00
abcdefg30
640e9d68b7 Fix not all ammo pools getting rearmed during RearmTick 2023-02-19 15:11:05 +02:00
Gustas
049d0283f9 Remove TiberianSunRefinery
Also add IDockClientBody interface,
move WithDockingOverlay cnc -> common,
remove HarvesterDockSequence implementing classes
2023-02-18 16:35:15 +01:00
Andre Mohren
3f0c3a8b9c Allow mods to control how looped sounds are used. 2023-02-18 16:18:20 +01:00
Gustas
68fddf818c Polish encyclopedia descriptions 2023-02-18 16:18:01 +01:00
Gustas
6997c442c6 Add MacOS Utility executable 2023-02-18 17:14:22 +02:00
Gustas
78677fd8ab Fix replays continuing after desync 2023-02-18 15:53:17 +01:00
Gustas
20a16ad5f8 Move force pausing to EndGame method 2023-02-18 15:53:17 +01:00
penev92
19613ed833 Minor D2k encyclopedia UI polish
- Make the text area taller so all the current text fits without a scroll.
- Limit label width so text doesn't press against the scrollbar.
2023-02-18 15:39:19 +01:00
penev92
63bc73d9d2 Change the way the output directory is set during packaging 2023-02-18 15:18:35 +02:00
penev92
5c7b8955dc Added video player background for D2k 2023-02-18 14:10:24 +01:00
penev92
2c51e791ad Added VideoPlayerWidget.LoadAndPlayAsync method
Previous commits removed the async loading of videos, which can be a problem for videos played in the radar widget mid-game because it can cause a lag spike. This loads the video on a separate thread and runs it on the main thread whenever it is loaded, not blocking the main thread meanwhile and allowing the game to continue while the video loads.
Also add back cancelling of already playing video and add a check to not try to run onComplete if it is null.
2023-02-18 14:10:24 +01:00
penev92
c3fcbf77ed Rename some VideoPlayerWidget methods for clarity 2023-02-18 14:10:24 +01:00
penev92
6321432d97 Fix crash caused by VideoPlayerWidget.DrawOverlay
Somehow this would divide by 0 on the next line, not crashing but resulting in an integer overflow on `overlayHeight`, which would crash when trying to render.
2023-02-18 14:10:24 +01:00
penev92
4135079290 Unify MediaGlobal/Scripting.Media PlayFMV* methods
- Improve consistency
- Remove dead code
- Removed AsyncAction!
- Delegate.BeginInvoke is unsupported since .NET Core and throws an "Operation is not supported on this platform." exception.
2023-02-18 14:10:24 +01:00
penev92
287428b487 Did a slight refactor pass on MediaGlobal
- Unified onPlayComplete callback handling to avoid code duplication.
- Fixed code style issues.
2023-02-18 14:10:24 +01:00
Paul Chote
af23888b95 Remove dependency on VCRUNTIME140.dll. 2023-02-18 14:30:56 +02:00
abcdefg30
4a554431ff Remove redundant jumps and other style nits from the update rules 2023-02-18 00:41:07 +02:00
Paul Chote
947f53a991 Disable max order length check for local servers. 2023-02-14 10:15:21 +02:00
abcdefg30
835537fcc2 Adjust the encyclopedia descriptions of combat tanks 2023-02-14 10:09:11 +02:00
abcdefg30
08ba35763c Adjust the encyclopedia descriptions of light armored units 2023-02-14 10:09:11 +02:00
oldnaari
14ad4e168e Update DownloadPackageLogic.cs, to log missing files in package 2023-02-05 20:19:49 +02:00
penev92
a614375982 Fixed Makefile check of MacOS architecture 2023-02-05 00:19:05 +01:00
abcdefg30
e4bb13ea07 Throw an ArgumentException when trying to translate null keys 2023-02-03 08:31:28 +02:00
abcdefg30
84add8a03d Fix an NRE in ConnectionLogic 2023-02-03 08:31:28 +02:00
Gustas
f5aa2f153a Use Refinery reference in HarvesterDockSequence 2023-01-31 23:49:10 +01:00
Gustas
f56b0ea0d0 Moved HarvesterDockSequence notifications to the base class
And fix a minor oversight in VoxelHarvesterDockSequence.cs
2023-01-31 23:49:10 +01:00
Azarus
77b06ac9f7 Add an option to check if an actor can be captured via Lua 2023-01-30 13:46:29 +02:00
Gustas
3f2007cd2c Optimise TakeCover to have clear states 2023-01-28 20:18:48 +01:00
michaeldgg2
6f87c565ac AddFactionSuffixLogic: add suffix to ProductionTabsWidget.Decorations 2023-01-27 12:30:38 +02:00
michaeldgg2
949b993a4a ProductionTabsWidget: center left/right arrow image on left/right button background 2023-01-27 12:30:38 +02:00
michaeldgg2
ca7e7c2304 ProductionTabsWidget: allow specifying different panels for left/right scroll button and tab buttons. 2023-01-27 12:30:38 +02:00
michaeldgg2
38e52c062e ProductionTabsWidget: allow customizing left/right arrow buttons.
This moves initialization of Initialize getters for left/right arrow image from constructor Initialize method making it possible to override fields Decorations, DecorationScrollLeft and DecorationScrollRight after widget creation.
2023-01-27 12:30:38 +02:00
Paul Chote
8be3ac863b Only update changed files when saving maps. 2023-01-27 07:43:25 +01:00
Dean Simmons
e1b78c4821 Only return file paths when returning zip contents 2023-01-26 19:25:58 +02:00
penev92
c1da198f5d Fixed RA parabomb/paradrop support power tooltips
The AFLD's AirstrikePower@parabombs' description wasn't updated to the latest balance patch (3 Badgers -> 1 Badger)
2023-01-26 09:32:34 +01:00
penev92
474de014f8 Move RenameEngineerRepair to its proper folder 2023-01-25 12:00:57 +01:00
Matthias Mailänder
c3752d1c18 Remove engineer repairing completely. 2023-01-24 23:26:14 +01:00
Matthias Mailänder
f67b6f6cad Give EngineerRepair(able) more generic names 2023-01-24 23:26:14 +01:00
Matthias Mailänder
9b2e291a46 Extract translation strings. 2023-01-23 20:51:45 +01:00
Matthias Mailänder
867efcc6e8 Add Media.DisplayMessageToPlayer 2023-01-23 20:51:45 +01:00
Matthias Mailänder
847bbf5710 Use out parameter modifier code style. 2023-01-23 20:51:45 +01:00
Matthias Mailänder
f013a003a0 Don't translate enemy objectives. 2023-01-23 20:51:45 +01:00
Matthias Mailänder
7cdc8c4ec5 Add a quick save button to the map editor. 2023-01-23 14:13:19 +02:00
Paul Chote
3dd1fd6b00 Add support for Flatpak Steam installs. 2023-01-22 22:39:36 +01:00
Paul Chote
e13a7aed90 Manual yaml cleanup. 2023-01-22 22:10:48 +02:00
Paul Chote
5b8f148c50 Simplify tileset-specific sequence definitions.
All magic behaviour for constructing sprite filenames
has been removed in favour of an explicit Filename
(and TilesetFilenames for tileset-specific sequences)
property.
2023-01-22 22:10:48 +02:00
Paul Chote
04c3cd6ec5 Reimplement sequence Defaults parsing:
The previous MiniYaml.Merge implementation interacted
poorly with yaml inheritance, making it complicated
(or impossible) to override certain keys from Defaults.

The new implementation is simpler: If a key is defined
it will be used. If it isn't, the default (if defined)
will be used. Defaults can be masked by making sure
the same key is defined (even with an empty value)
in the sequence.

This also fixes naming within the sequence code to
distinguish between images (a group of sequences),
sequences (defining a specific sprite/animation),
and filenames for a specific sprite/animation.
2023-01-22 22:10:48 +02:00
Paul Chote
05c83a9dbb Fix ExtractSpriteSequenceDocsCommand crash on non-generic static fields. 2023-01-22 22:10:48 +02:00
abcdefg30
3ef0b3be95 Add the expected parameter(s) to the ExtractFilesCommand description 2023-01-22 18:31:32 +00:00
Gustas
84e7eb144b Move RearmTick to Rearmable 2023-01-20 11:43:12 +02:00
Gustas
75d65b3d20 Remove redundant INotifyRearm 2023-01-20 10:43:18 +02:00
Gustas
12af8506f8 Fix Rearmable using the wrong interface 2023-01-20 10:43:18 +02:00
Gustas
0d24f2c08b Merge INotifyBeingResupplied into INotifyDockClient 2023-01-20 10:43:18 +02:00
Gustas
dca07d240c Add INotifyDockHost and INotifyDockClient interfaces
Rename INotifyDocking to INotifyDockHost and extract INotifyDockClient from INotifyHarvesterAction
2023-01-20 10:43:18 +02:00
N.N
ba011ffc5f Fix deviator GrantExternalCondition Warhead
Warhead now applies only to enemy and neutral units.
2023-01-18 23:41:18 +01:00
RoosterDragon
faf12f93a4 Fix Locomotor cache coherency for disabled or paused mobile actors.
The cache in Locomotor that is populated via the UpdateCellBlocking method disagreed with the non-cached logic of IsBlockedBy when dealing with Mobile actors. The cache determined an actor to be moving if it was both movable and had horizontal movement types. IsBlockedBy determined an actor to be moving if it had horizontal movement types, but did not check if it was movable. This difference in checks could allow a mobile trait that was disabled or paused and which had horizontal movement to be treated differently be the two methods. UpdateCellBlocking would consider it not moving due to the disabled/paused trait. IsBlockedBy would consider it moving as it didn't care about the disabled/paused state of the trait.

Now, we unify the two methods to consider a mobile trait that is disabled/paused as not moving. This prevents HierarchicalPathFinder from crashing on the inconsistent state, i.e. when asked to path search through a cell of a mobile unit which has disabled or paused movement, but which has horizontal movement types from prior movement.
2023-01-17 18:58:22 +01:00
Andre Mohren
1dc44c4047 Looped sounds can now be unlooped to avoid cut-offs. 2023-01-14 13:56:20 +01:00
David Wilson
9cd3981b94 Fix to ensure Windows uninstaller removes reg entries from the 64 bit registry 2023-01-14 13:47:37 +01:00
Moath Altarawneh
44be6cea94 Update Program.cs
a small change to line 174 to use an easier way to format the string 👍
2023-01-14 13:02:28 +02:00
abcdefg30
5bf7fe852c Remove the copyright year numbers 2023-01-11 11:58:54 +02:00
penev92
5f80e93aee Added ITilesetSpecificPaletteInfo for linting 2023-01-10 16:36:36 +00:00
Gustas
80b92fb667 Fixed UnhardcodeBaseBuilderBotModule update rule
Update rules should should not read `modData.DefaultRules`
2023-01-10 18:02:24 +02:00
Gustas
29d21545a6 Fixed UnhardcodeSquadManager update rule
Update rules should should not read `modData.DefaultRules`
2023-01-10 18:02:24 +02:00
Gustas
326f8115a0 Exclude Plugs from TS protection types 2023-01-10 18:02:24 +02:00
Paul Chote
129db98a2f Add BeforeUpdate* methods for update rules.
These make it possible to write more advanced update
rules that query state across multiple actors, or
based on resolved state.
2023-01-10 18:02:24 +02:00
penev92
15fe2d5594 Added an update rule for adding ControlGroups 2023-01-10 00:15:00 +01:00
penev92
e3e012a9ed Added an update rule for DomainIndex removal
Also for adding the new HPF-related PathFinderOverlay and HierarchicalPathFinderOverlay that were added at the same time.
2023-01-10 00:15:00 +01:00
Ivaylo Draganov
04648a66e6 Clarify the wording and explain the meaning of some labels in settings 2023-01-09 21:47:11 +02:00
abcdefg30
edd0068d88 Remove an unuseful comment from mods/ra/installer/origin.yaml 2023-01-09 19:27:50 +01:00
Matthias Mailänder
79d786708b Fix URL button blocking the party button. 2023-01-08 23:07:19 +01:00
Matthias Mailänder
921da2f19e Bump DiscordRichPresence library. 2023-01-08 23:07:19 +01:00
Andre Mohren
0b94a0639e Implemented WestwoodCompression for AUD files. 2023-01-08 12:40:57 +00:00
Gustas
fb93281beb Fixed a spelling error in Discovery ant mission 2023-01-07 17:02:12 +01:00
Gustas
b75976b6d8 Remove bogus bridge tiles from temperate tileset 2023-01-07 17:02:12 +01:00
Matthias Mailänder
b0aea7b810 Bump checkout action. 2023-01-04 21:54:55 +00:00
Matthias Mailänder
f65c3a09db Bump setup .NET action. 2023-01-04 21:54:55 +00:00
abcdefg30
d4d6d5b7c0 Remove custom network frame counting from ReplayConnection 2023-01-04 09:33:55 +00:00
Matthias Mailänder
56ff98a2a3 Throw specific cursor sequence errors
instead of dividing by zero because length is 0.
2023-01-03 13:25:50 +01:00
Paul Chote
6d438a9d61 Allow mods to customise the default rendering scale. 2022-12-31 17:11:03 +01:00
Gustas
e21f94f36a Guarantee 1 riflemen on sell in mods
And engineer on RA and D2K construction yards
2022-12-31 16:51:26 +01:00
Gustas
34543e2952 Add an option to guarantee actors on sell 2022-12-31 16:51:26 +01:00
Unrud
b1ffe0edd5 Don't use parameter expansion for paths
It fails when the script is started with `bash package-all.sh`.
2022-12-31 16:20:55 +01:00
Matthias Mailänder
19ecddcd86 Enforce use of 'var' instead of explicit type. 2022-12-28 23:02:04 +01:00
abcdefg30
982c97dc6c Specify targetable offsets for the repair pad in Dune 2000 2022-12-28 17:11:31 +02:00
Paul Chote
27c602fc30 Downgrade OpenAL-soft to 1.10.1.
1.12.2 introduces noticeable behaviour changes
to source positioning and cash ticks. This also
fixes missing sound backends on Linux.
2022-12-28 00:19:32 +01:00
Matthias Mailänder
943751547e Don't hardcode enemy aircraft ignorance. 2022-12-25 22:24:57 +01:00
Matthias Mailänder
24ed5f7a1a Add linting to AI squad manager types. 2022-12-25 22:24:57 +01:00
abcdefg30
0d654d5e53 Change into the correct directory before trying to push
Each workflow step starts back in the default directory,
so we need to checkout the repository folder again
2022-12-24 16:02:46 +01:00
abcdefg30
ffa015dc21 Let the documentation workflow fetch the required git branch 2022-12-24 16:02:46 +01:00
Paul Chote
a6eb00f326 Fix pseudo-fullscreen window size on macs with a notch. 2022-12-24 12:10:26 +01:00
abcdefg30
5a12f44a25 Fix map actors not being spawned with the correct owner 2022-12-24 11:20:35 +02:00
Matthias Mailänder
5ffb564376 Fix invalid actors not spawning in-game. 2022-12-23 18:33:55 +01:00
Matthias Mailänder
6bcf2f718c In map editor replace invalid actor owners with neutral. 2022-12-23 18:33:55 +01:00
Paul Chote
7c2be4ce3c Implement state prediction for lobby ready checkbox. 2022-12-23 16:33:21 +02:00
Paul Chote
25935bbe99 Implement state prediction for debug menu checkboxes. 2022-12-23 16:33:21 +02:00
Paul Chote
2ba52f1b94 Implement state prediction for lobby checkboxes. 2022-12-23 16:33:21 +02:00
Paul Chote
e2e541a251 Package macOS releases as a universal binary.
* Minimum macOS version is raised to 10.11.
* App bundles ship 3 versions of the runtime and engine binaries,
  and a fat launcher that selects the appropriate runtime/apphost.
* Mono is used for macOS 10.11 - 10.14, or if OPENRA_PREFER_MONO
  environment variable has been set.
2022-12-23 12:54:06 +02:00
Paul Chote
363a0e1d1e Update native deps to include macOS and Linux arm64 binaries. 2022-12-23 12:54:06 +02:00
Paul Chote
80945cd08a Report CPU arch in logs and sysinfo. 2022-12-23 12:54:06 +02:00
Paul Chote
a17e1671f0 Fix MiniYaml source locations being lost when merging. 2022-12-23 10:44:54 +02:00
Gustas
b619dd14c5 Remove sniper 2022-12-21 21:56:24 -06:00
Gustas
55cf40ec52 Added carryalls to spectator Economy statistics 2022-12-21 21:06:38 +01:00
Gustas
f3e44094a1 Fix contrail using the wrong colors 2022-12-21 19:35:52 +02:00
N.N
43094742fb Change tile 9 to Rough TerrainType 2022-12-21 19:31:15 +02:00
abcdefg30
70549fce14 Run the CI workflow on PRs targeting prep 2022-12-21 13:28:14 +02:00
Paul Chote
360a5b293d Bubble unhandled double-click events to OnClick. 2022-12-20 23:01:41 +01:00
RoosterDragon
f4965915ee Fix PathFinderOverlay crash when deselecting actor moving along waypoints.
Set an actor moving along several waypoints whilst the /path-debug command is active, then deselect the actor. Each waypoint will add more information to the debugging overlay until it crashes with "Maximum two records permitted." This resolves the crash by no longer adding new debugging information once the actor is deselected.
2022-12-20 13:23:32 +13:00
RoosterDragon
39e48d9e8d HPF is aware of map projection changes.
An event is added to Map to indicate when the cell projection is changed. This is important as this can mean Map.Contains(CPos) could now return different results for the cell. The HierarchicalPathFinder is made aware of these changes so it can rebuild any out-of-date information. This fixes prevent a crash if a cell that was previously outside the map changes height and becomes inside the map. The local path search will explore the cell as it is inside the map - but if the HPF was unaware if had been updated, it will still consider the cell to be outside the map and unreachable, resulting in a crash.
2022-12-20 09:47:24 +13:00
RoosterDragon
d8ebb96077 HPF handles searches from unreachable source cells into cut off areas.
If a path search is performed by the HierarchicalPathFinder when the source cell is unreachable location, a path is still allowed and starts from one of the cells adjacent to the location. If moving into one of these cells results in the actor moving into an isolated area that cannot reach the target this would previously crash as no abstract path could be found. Now we handle such locations by giving them a unreachable cost so the path search will not attempt to explore them.

Imagine a map split into two by a one tile wide line of impassable cliffs. If an actor is on top of these cliffs it is allowed to path because it can "jump off" the cliff and move into the cell immediately either side of it. However it is important which side it chooses to jump into, as one it has moved off the cliff it loses access to the other side. The previous error came about because the path might try and search on the side that couldn't reach the target location. Now we avoid that being considered.
2022-12-20 09:47:24 +13:00
Paul Chote
11e5d19f32 Prioritise primary buildings in CycleBasesHotkeyLogic. 2022-12-19 11:55:45 +02:00
Alex
82d0546d16 build: harden workflow permissions
Signed-off-by: Alex <aleksandrosansan@gmail.com>
2022-12-19 22:40:19 +13:00
Ivaylo Draganov
a0f17b15ec Refactor translation files
- Add prefixes to all message keys to provide context
- Use messages with attributes for some UI elements (dropdowns, dialogs, checkboxes, menus)
- Rename some class fields for consistency with translation keys
2022-12-19 22:04:54 +13:00
Matthias Mailänder
46caa2d889 Make RenderShroud/JammerCircle conditional. 2022-12-19 20:03:40 +13:00
Gustas
475468ccc7 Fix Devil's Tongue attacking while submerged 2022-12-19 19:25:59 +13:00
Gustas
f3dc168dbd Don't cancel guard cursor when holding shift 2022-12-18 15:39:12 +01:00
Matthias Mailänder
4ffd81bd41 Fix documentation deployment. 2022-12-18 12:57:08 +13:00
abcdefg30
0f149f1143 Fix the actor edit panel not always getting closed properly 2022-12-18 12:24:36 +13:00
Ivaylo Draganov
8513de0b47 Fix error in PlayerResources trait documentation
This was missed in #19295
2022-12-16 12:14:54 +02:00
Ivaylo Draganov
614603089e Define and measure duration for text notifications in milliseconds
During a game notification duration should be the same regardless of
game speed. Switch to using wall-clock time defined in milliseconds 
instead of game ticks. Also use the opportunity to rename the field 
to "Duration" because "RemoveTime" is not so clear.
2022-12-15 23:28:46 +01:00
Ivaylo Draganov
e280e0f31c Use an overload that already passes the second argument as true 2022-12-15 23:28:46 +01:00
Gustas
c739447598 Fix map editor sliders stealing focus 2022-12-14 23:53:28 +01:00
Ivaylo Draganov
e60f7bb125 Remove unused common chrome yaml file 2022-12-12 23:51:46 +01:00
Ivaylo Draganov
18e36b96db Add HPF overlay controls to observer chrome 2022-12-12 23:51:46 +01:00
Gustas
2b57b6be1d Don't cancel attack move cursor when holding shift 2022-12-12 23:20:45 +01:00
dnqbob
45d4a2c7e2 Fix syncreport crash caused by getting LocalClient index from ReplayConnection 2022-12-11 23:32:59 +02:00
Gustas
6fccd6be84 Fix attack move lines not showing up for undeploy on force move units
DeployForGrantedCondition is wrapped around the Move activity, so the AttackMoveActivity thinks that DeployForGrantedCondition is the Move activity.

All it means is that we need to forward the target line request to the Move activity
2022-12-11 22:06:47 +01:00
Smittytron
767ac1c4e2 Remove MustDestroy from longbows in Soviet 11 2022-12-10 16:16:00 +02:00
Smittytron
b14caf004d Fix Siberian Conflict 3 win trigger 2022-12-10 16:16:00 +02:00
N.N
d72d25c369 Update D2k map pool 2022-12-07 23:39:35 +01:00
Matthias Mailänder
640e52d4b4 Report missing translation keys only once. 2022-12-07 18:40:26 +02:00
Matthias Mailänder
9ba51c6b51 Manually add game speeds to the linter. 2022-12-07 18:40:26 +02:00
Matthias Mailänder
8297fcff30 Expose lobby options to localisation. 2022-12-07 18:40:26 +02:00
Matthias Mailänder
aefa49a831 Add support for translating trait rules. 2022-12-07 18:40:26 +02:00
Matthias Mailänder
e251377f7c Add support for translation attributes. 2022-12-07 18:40:26 +02:00
Matthias Mailänder
760a1245c5 Mark non-moddable translation strings as constant. 2022-12-07 18:40:26 +02:00
Matthias Mailänder
4f016f149f Install libfuse2 in Ubuntu 22.04 2022-12-06 09:46:48 +02:00
abcdefg30
c14b585433 Remove a stray $ from infront of the version string when writing logs 2022-12-03 23:49:15 +02:00
Matthias Mailänder
2d78dae01a Execute self-contained binaries with runtime as backfall 2022-12-02 23:03:40 +01:00
Gustas
b0036a2d3e Add cell reference HPF crash messages 2022-12-02 17:46:46 +01:00
Matthias Mailänder
3091504c7e Unify file extensions. 2022-12-01 19:52:56 +02:00
Matthias Mailänder
bd678659a2 Update Ubuntu 2022-12-01 19:52:56 +02:00
Paul Chote
06edc3dff1 Remove redundant order copies. 2022-11-27 22:58:23 +01:00
Paul Chote
c2208ce8fe Always serialize orders. 2022-11-27 22:58:23 +01:00
Paul Chote
1add57e5ad Fix frame number not being included in pre-serialized order packets. 2022-11-27 22:58:23 +01:00
Matthias Mailänder
435c999abf Update notarisation to XCode 13 tooling. 2022-11-27 20:31:10 +01:00
Paul Chote
c82b8244e8 Fix display bounds when running on macbooks with a notch. 2022-11-26 20:43:57 +01:00
dnqbob
8703cfc4f4 Incease NumSyncReports to 7 2022-11-25 23:57:39 +01:00
dnqbob
63411f9938 Add Player is host infomation for a better debug of desync related with AI 2022-11-25 23:57:39 +01:00
dnqbob
60f35f779d SyncReport filename contains index of local client 2022-11-25 23:57:39 +01:00
dnqbob
1a2ef49100 SyncReport: Output the frames recorded for better debug. 2022-11-25 23:57:39 +01:00
dnqbob
6fbdc2c221 HarvesterBotModule should not command harvesters that cannot be ordered 2022-11-24 23:09:22 +01:00
Matthias Mailänder
14b5504ea7 Show the host in the download failed error message. 2022-11-23 23:35:53 +01:00
Matthias Mailänder
6f4f0c4e8f Fix unknown host not getting translated. 2022-11-23 23:35:53 +01:00
dnqbob
ac92162825 Weapon checks valid frozen actor 2022-11-22 21:49:12 +01:00
dnqbob
a25558b550 Weapon doesn't check warheads in IsValidAgainst 2022-11-22 21:49:12 +01:00
dnqbob
e8d9e2dfa9 Make weapon can target attacker itself an option. 2022-11-22 21:49:12 +01:00
Vapre
aa878c9dc8 ExceptionHandler, fix npe. 2022-11-22 12:35:28 +01:00
abcdefg30
7aa50d412c Remove the unused MONO_TAG variable from the MacOS buildpackage script 2022-11-20 22:08:38 +01:00
Matthias Mailänder
69949f9d53 Revert "Scripts: Check exit status of background process"
This reverts commit 3f106bef72.
2022-11-20 20:36:29 +02:00
Andre Mohren
0c8ae195ae Removed offset and length utility commands, obsolete now. 2022-11-19 12:27:13 +01:00
Andre Mohren
e6682d2108 Added C&C Remastered installer support (Origin and Steam) 2022-11-19 12:27:13 +01:00
IceReaper
9fa6c47dc5 Added GoG and Steam SourceResolver. 2022-11-19 12:27:13 +01:00
Andre Mohren
f5b169ab54 Added ExtractMixSourceAction. 2022-11-19 12:27:13 +01:00
IceReaper
09b32f7f98 Fixed the blast decompression. Fixes #13689 2022-11-19 12:27:13 +01:00
Matthias Mailänder
621c85059e Extract Tiberian Dawn campaign translations. 2022-11-17 22:28:07 +02:00
Matthias Mailänder
b62cf7ee9a Add translation arguments to the Lua API. 2022-11-17 22:28:07 +02:00
Matthias Mailänder
5d118e2634 Inline variables. 2022-11-17 22:28:07 +02:00
Matthias Mailänder
807e9b5496 Don't crash Lua when the translation attempt fails. 2022-11-17 22:28:07 +02:00
IceReaper
0c47a0a710 Bugfix: mod.yaml was listing downloads as source too! 2022-11-17 21:19:57 +01:00
IceReaper
35eb246080 Replaced hardcoded SourceType with custom defined ISourceResolver. 2022-11-17 21:19:57 +01:00
IceReaper
7188f88ba1 Replaced hardcoded source actions by user defined ISourceAction. 2022-11-17 21:19:57 +01:00
IceReaper
fcc8f53b59 Installer downloads now using specified IPackageLoader. 2022-11-17 21:19:57 +01:00
Gustas
a9da6bb2d8 Introduce MinDistance to AreaBeam projectile 2022-11-17 20:48:37 +01:00
Gustas
f7286b525c Move AbortOnResupply from AttackAircraft to AttackFollow 2022-11-17 20:42:47 +01:00
Julius Vitkauskas
4517734fbe Dispose DependencyContextJsonReader after using 2022-11-17 20:36:13 +02:00
ThomasChr
bd882c98c7 fix Issue #20373 - Aircraft hanging midair 2022-11-17 20:27:14 +02:00
Thomas Christlieb
ed9880f801 fix misclicks through sidebar 2022-11-16 23:20:50 +01:00
IceReaper
8ae5383698 Made installer asset resolving case insensitive. 2022-11-17 00:16:59 +02:00
IceReaper
98e7058486 ZipFile is now determined by a zip header, not the file extensions, as it may be a temp file. 2022-11-17 00:16:59 +02:00
IceReaper
0aced08204 Support for InstallShield CAB version <= 5. 2022-11-17 00:16:59 +02:00
1962 changed files with 29772 additions and 33028 deletions

View File

@@ -8,24 +8,444 @@ end_of_line = LF
insert_final_newline = true
trim_trailing_whitespace = true
; 4-column tab indentation
[*.yaml]
indent_style = tab
indent_size = 4
; 4-column tab indentation and .NET coding conventions
[*.cs]
indent_style = tab
indent_size = 4
dotnet_separate_import_directive_groups = false
dotnet_sort_system_directives_first = true
#### Code Style Rules
#### https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/
csharp_style_var_elsewhere = true:suggestion
csharp_style_var_for_built_in_types = true:suggestion
csharp_style_var_when_type_is_apparent = true:suggestion
# Severity Levels: https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/configuration-options#severity-level
# Below we enable specific rules by setting severity to warning.
# Rules are disabled by setting severity to silent (to still allow use in IDE) or none (to prevent all use).
# Rules are listed below with any options available.
# Options are commented out if they match the defaults.
csharp_prefer_braces = when_multiline:suggestion
csharp_using_directive_placement = outside_namespace:suggestion
csharp_new_line_before_open_brace = all
csharp_space_around_binary_operators = before_and_after
### Language Rules
### https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/language-rules
## Naming styles:
## this and Me preferences
# IDE0003/IDE0009 Remove 'this' or 'Me' qualification/Add 'this' or 'Me' qualification
#dotnet_style_qualification_for_field = false
#dotnet_style_qualification_for_property = false
#dotnet_style_qualification_for_method = false
#dotnet_style_qualification_for_event = false
dotnet_diagnostic.IDE0003.severity = warning
dotnet_diagnostic.IDE0009.severity = warning
## Use languages keywords for types
# IDE0049 Use language keywords instead of framework type names for type references
#dotnet_style_predefined_type_for_locals_parameters_members = true
#dotnet_style_predefined_type_for_member_access = true
dotnet_diagnostic.IDE0049.severity = warning
## Modifier preferences
# IDE0036 Order modifiers
#csharp_preferred_modifier_order = public, private, protected, internal, file, static, extern, new, virtual, abstract, sealed, override, readonly, unsafe, required, volatile, async
dotnet_diagnostic.IDE0036.severity = warning
# IDE0040 Add accessibility modifiers
dotnet_style_require_accessibility_modifiers = omit_if_default
dotnet_diagnostic.IDE0040.severity = warning
# IDE0044 Add readonly modifier
#dotnet_style_readonly_field = true
dotnet_diagnostic.IDE0044.severity = warning
# IDE0062 Make local function static
#csharp_prefer_static_local_function = true
dotnet_diagnostic.IDE0062.severity = warning
# IDE0064 Make struct fields writable
# No options
dotnet_diagnostic.IDE0064.severity = warning
## Parentheses preferences
# IDE0047/IDE0048 Remove unnecessary parentheses/Add parentheses for clarity
dotnet_style_parentheses_in_arithmetic_binary_operators = never_if_unnecessary
dotnet_style_parentheses_in_relational_binary_operators = never_if_unnecessary
#dotnet_style_parentheses_in_other_binary_operators = always_for_clarity
#dotnet_style_parentheses_in_other_operators = never_if_unnecessary
dotnet_diagnostic.IDE0047.severity = warning
dotnet_diagnostic.IDE0048.severity = warning
## Expression-level preferences
# IDE0010 Add missing cases to switch statement
# No options
dotnet_diagnostic.IDE0010.severity = silent
# IDE0017 Use object initializers
#dotnet_style_object_initializer = true
dotnet_diagnostic.IDE0017.severity = warning
# IDE0018 Inline variable declaration
#csharp_style_inlined_variable_declaration = true
dotnet_diagnostic.IDE0018.severity = warning
# IDE0028 Use collection initializers
#dotnet_style_collection_initializer = true
dotnet_diagnostic.IDE0028.severity = warning
# IDE0032 Use auto-implemented property
#dotnet_style_prefer_auto_properties = true
dotnet_diagnostic.IDE0032.severity = warning
# IDE0033 Use explicitly provided tuple name
#dotnet_style_explicit_tuple_names = true
dotnet_diagnostic.IDE0033.severity = warning
# IDE0034 Simplify 'default' expression
#csharp_prefer_simple_default_expression = true
dotnet_diagnostic.IDE0034.severity = warning
# IDE0037 Use inferred member name
#dotnet_style_prefer_inferred_tuple_names = true
#dotnet_style_prefer_inferred_anonymous_type_member_names = true
dotnet_diagnostic.IDE0037.severity = silent
# IDE0039 Use local function instead of lambda
#csharp_style_prefer_local_over_anonymous_function = true
dotnet_diagnostic.IDE0039.severity = warning
# IDE0042 Deconstruct variable declaration
#csharp_style_deconstructed_variable_declaration = true
dotnet_diagnostic.IDE0042.severity = warning
# IDE0045 Use conditional expression for assignment
#dotnet_style_prefer_conditional_expression_over_assignment = true
dotnet_diagnostic.IDE0045.severity = silent
# IDE0046 Use conditional expression for return
#dotnet_style_prefer_conditional_expression_over_return = true
dotnet_diagnostic.IDE0046.severity = silent
# IDE0050 Convert anonymous type to tuple
# No options
dotnet_diagnostic.IDE0050.severity = silent
# IDE0054/IDE0074 Use compound assignment/Use coalesce compound assignment
#dotnet_style_prefer_compound_assignment = true
dotnet_diagnostic.IDE0054.severity = warning
dotnet_diagnostic.IDE0074.severity = warning
# IDE0056 Use index operator
#csharp_style_prefer_index_operator = true
dotnet_diagnostic.IDE0056.severity = warning
# IDE0057 Use range operator
#csharp_style_prefer_range_operator = true
dotnet_diagnostic.IDE0057.severity = warning
# IDE0070 Use 'System.HashCode.Combine'
# No options
dotnet_diagnostic.IDE0070.severity = warning
# IDE0071 Simplify interpolation
#dotnet_style_prefer_simplified_interpolation = true
dotnet_diagnostic.IDE0071.severity = warning
# IDE0072 Add missing cases to switch expression
# No options
dotnet_diagnostic.IDE0072.severity = silent
# IDE0075 Simplify conditional expression
#dotnet_style_prefer_simplified_boolean_expressions = true
dotnet_diagnostic.IDE0075.severity = warning
# IDE0082 Convert 'typeof' to 'nameof'
# No options
dotnet_diagnostic.IDE0082.severity = warning
# IDE0090 Simplify 'new' expression
#csharp_style_implicit_object_creation_when_type_is_apparent = true
dotnet_diagnostic.IDE0090.severity = warning
# IDE0180 Use tuple to swap values
#csharp_style_prefer_tuple_swap = true
dotnet_diagnostic.IDE0180.severity = warning
## Namespace declaration preferences
# IDE0160/IDE0161 Use block-scoped namespace/Use file-scoped namespace
#csharp_style_namespace_declarations = block_scoped
dotnet_diagnostic.IDE0160.severity = warning
dotnet_diagnostic.IDE0161.severity = warning
## Null-checking preferences
# IDE0016 Use throw expression
#csharp_style_throw_expression = true
dotnet_diagnostic.IDE0016.severity = silent
# IDE0029/IDE0030/IDE0270 Use coalesce expression (non-nullable types)/Use coalesce expression (nullable types)/Use coalesce expression (if null)
#dotnet_style_coalesce_expression = true
dotnet_diagnostic.IDE0029.severity = warning
dotnet_diagnostic.IDE0030.severity = warning
dotnet_diagnostic.IDE0270.severity = silent
# IDE0031 Use null propagation
#dotnet_style_null_propagation = true
dotnet_diagnostic.IDE0031.severity = warning
# IDE0041 Use 'is null' check
#dotnet_style_prefer_is_null_check_over_reference_equality_method = true
dotnet_diagnostic.IDE0041.severity = warning
# IDE0150 Prefer 'null' check over type check
#csharp_style_prefer_null_check_over_type_check = true
dotnet_diagnostic.IDE0150.severity = warning
# IDE1005 Use conditional delegate call
csharp_style_conditional_delegate_call = true # true is the default, but the rule is not triggered if this is not specified.
dotnet_diagnostic.IDE1005.severity = warning
## var preferences
# IDE0007/IDE0008 Use 'var' instead of explicit type/Use explicit type instead of 'var'
csharp_style_var_for_built_in_types = true
csharp_style_var_when_type_is_apparent = true
csharp_style_var_elsewhere = true
dotnet_diagnostic.IDE0007.severity = warning
dotnet_diagnostic.IDE0008.severity = warning
## Expression-bodied-members
# IDE0021 Use expression body for constructors
#csharp_style_expression_bodied_constructors = false
dotnet_diagnostic.IDE0021.severity = silent
# IDE0022 Use expression body for methods
#csharp_style_expression_bodied_methods = false
dotnet_diagnostic.IDE0022.severity = silent
# IDE0023/IDE0024 Use expression body for conversion operators/Use expression body for operators
#csharp_style_expression_bodied_operators = false
dotnet_diagnostic.IDE0023.severity = silent
dotnet_diagnostic.IDE0024.severity = silent
# IDE0025 Use expression body for properties
#csharp_style_expression_bodied_properties = true
dotnet_diagnostic.IDE0025.severity = silent
# IDE0026 Use expression body for indexers
#csharp_style_expression_bodied_indexers = true
dotnet_diagnostic.IDE0026.severity = silent
# IDE0027 Use expression body for accessors
#csharp_style_expression_bodied_accessors = true
dotnet_diagnostic.IDE0027.severity = warning
# IDE0053 Use expression body for lambdas
# This rule is buggy and not enforced for builds. ':warning' will at least enforce it in the IDE.
csharp_style_expression_bodied_lambdas = when_on_single_line:warning
dotnet_diagnostic.IDE0053.severity = warning
# IDE0061 Use expression body for local functions
csharp_style_expression_bodied_local_functions = when_on_single_line
dotnet_diagnostic.IDE0061.severity = warning
## Pattern matching preferences
# IDE0019 Use pattern matching to avoid 'as' followed by a 'null' check
#csharp_style_pattern_matching_over_as_with_null_check = true
dotnet_diagnostic.IDE0019.severity = warning
# IDE0020/IDE0038 Use pattern matching to avoid 'is' check followed by a cast (with variable)/Use pattern matching to avoid 'is' check followed by a cast (without variable)
#csharp_style_pattern_matching_over_is_with_cast_check = true
dotnet_diagnostic.IDE0020.severity = warning
dotnet_diagnostic.IDE0038.severity = warning
# IDE0066 Use switch expression
#csharp_style_prefer_switch_expression = true
dotnet_diagnostic.IDE0066.severity = silent
# IDE0078 Use pattern matching
#csharp_style_prefer_pattern_matching = true
dotnet_diagnostic.IDE0078.severity = silent
# IDE0083 Use pattern matching ('not' operator)
#csharp_style_prefer_not_pattern = true
dotnet_diagnostic.IDE0083.severity = warning
# IDE0170 Simplify property pattern
#csharp_style_prefer_extended_property_pattern = true
dotnet_diagnostic.IDE0170.severity = silent # Requires C# 10
## Code block preferences
# IDE0011 Add braces
#csharp_prefer_braces = true
# No options match the style used in OpenRA.
dotnet_diagnostic.IDE0011.severity = none
# IDE0063 Use simple 'using' statement
#csharp_prefer_simple_using_statement = true
dotnet_diagnostic.IDE0063.severity = silent
## 'using' directive preferences
# IDE0065 'using' directive placement
#csharp_using_directive_placement = outside_namespace
dotnet_diagnostic.IDE0065.severity = silent
## File header preferences
# IDE0073 Require file header
#file_header_template = unset
# This rule does not allow us to enforce our desired header, as it prefixes the header lines with // comments, meaning we can't apply a region.
dotnet_diagnostic.IDE0073.severity = none
## Namespace naming preferences
# IDE0130 Namespace does not match folder structure
#dotnet_style_namespace_match_folder = true
# This rule doesn't appear to work (never reports violations)
dotnet_diagnostic.IDE0130.severity = none
### Unnecessary Code Rules
### https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/unnecessary-code-rules
# IDE0001 Simplify name
# No options
dotnet_diagnostic.IDE0001.severity = warning
# IDE0002 Simplify member access
# No options
dotnet_diagnostic.IDE0002.severity = warning
# IDE0004 Remove unnecessary cast
# No options
dotnet_diagnostic.IDE0004.severity = warning
# IDE0005 Remove unnecessary import
# No options
# IDE0005 is only enabled in the IDE by default. https://github.com/dotnet/roslyn/issues/41640
# To enable it for builds outside the IDE the 'GenerateDocumentationFile' property must be enabled on the build.
# GenerateDocumentationFile generates additional warnings about XML docs, so disable any we don't care about.
dotnet_diagnostic.CS1591.severity = none # Missing XML comment for publicly visible type or member
dotnet_diagnostic.IDE0005.severity = warning
# IDE0035 Remove unreachable code
# No options
# Duplicates compiler warning CS0162
dotnet_diagnostic.IDE0035.severity = none
# IDE0051 Remove unused private member
# No options
dotnet_diagnostic.IDE0051.severity = warning
# IDE0052 Remove unread private member
# No options
dotnet_diagnostic.IDE0052.severity = warning
# IDE0058 Remove unnecessary expression value
#csharp_style_unused_value_expression_statement_preference = discard_variable
dotnet_diagnostic.IDE0058.severity = silent
# IDE0059 Remove unnecessary value assignment
#csharp_style_unused_value_assignment_preference = discard_variable
dotnet_diagnostic.IDE0059.severity = warning
# IDE0060 Remove unused parameter
dotnet_code_quality_unused_parameters = non_public
dotnet_diagnostic.IDE0060.severity = warning
# IDE0079 Remove unnecessary suppression
#dotnet_remove_unnecessary_suppression_exclusions = none
dotnet_diagnostic.IDE0079.severity = warning
# IDE0080 Remove unnecessary suppression operator
# No options
dotnet_diagnostic.IDE0080.severity = warning
# IDE0100 Remove unnecessary equality operator
# No options
dotnet_diagnostic.IDE0100.severity = warning
# IDE0110 Remove unnecessary discard
# No options
dotnet_diagnostic.IDE0110.severity = warning
### Miscellaneous Rules
### https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/miscellaneous-rules
# IDE0076 Remove invalid global 'SuppressMessageAttribute'
# No options
dotnet_diagnostic.IDE0076.severity = warning
# IDE0077 Avoid legacy format target in global 'SuppressMessageAttribute'
# No options
dotnet_diagnostic.IDE0077.severity = warning
### Formatting Rules (IDE0055)
### https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0055
# We may eventually wish to enforce this rule, however some existing formatting conflicts with the rule despite being reasonable.
# Additionally, the rule is buggy and likes to report spuriously after invoking Format Document in the IDE.
dotnet_diagnostic.IDE0055.severity = none
#dotnet_sort_system_directives_first = true
#dotnet_separate_import_directive_groups = false
#dotnet_style_namespace_match_folder = true
#csharp_new_line_before_open_brace = all
#csharp_new_line_before_else = true
#csharp_new_line_before_catch = true
#csharp_new_line_before_finally = true
#csharp_new_line_before_members_in_object_initializers = true
#csharp_new_line_before_members_in_anonymous_types = true
#csharp_new_line_between_query_expression_clauses = true
#csharp_indent_case_contents = true
#csharp_indent_switch_labels = true
#csharp_indent_labels = one_less_than_current
#csharp_indent_block_contents = true
#csharp_indent_braces = false
#csharp_indent_case_contents_when_block = true
#csharp_space_after_cast = false
#csharp_space_after_keywords_in_control_flow_statements = true
#csharp_space_between_parentheses =
#csharp_space_before_colon_in_inheritance_clause = true
#csharp_space_after_colon_in_inheritance_clause = true
#csharp_space_around_binary_operators = before_and_after
#csharp_space_between_method_declaration_parameter_list_parentheses = false
#csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
#csharp_space_between_method_declaration_name_and_open_parenthesis = false
#csharp_space_between_method_call_parameter_list_parentheses = false
#csharp_space_between_method_call_empty_parameter_list_parentheses = false
#csharp_space_between_method_call_name_and_opening_parenthesis = false
#csharp_space_after_comma = true
#csharp_space_before_comma = false
#csharp_space_after_dot = false
#csharp_space_before_dot = false
#csharp_space_after_semicolon_in_for_statement = true
#csharp_space_before_semicolon_in_for_statement = false
#csharp_space_around_declaration_statements = false
#csharp_space_before_open_square_brackets = false
#csharp_space_between_empty_square_brackets = false
#csharp_space_between_square_brackets = false
#csharp_preserve_single_line_statements = true
#csharp_preserve_single_line_blocks = true
### Naming Rules (IDE1006)
### https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/naming-rules
dotnet_diagnostic.IDE1006.severity = warning
## Naming styles
dotnet_naming_style.camel_case.capitalization = camel_case
@@ -34,7 +454,7 @@ dotnet_naming_style.pascal_case.capitalization = pascal_case
dotnet_naming_style.i_prefix_pascal_case.capitalization = pascal_case
dotnet_naming_style.i_prefix_pascal_case.required_prefix = I
## Symbol specifications:
## Naming Symbols
dotnet_naming_symbols.const_locals.applicable_kinds = local
dotnet_naming_symbols.const_locals.applicable_accessibilities = *
@@ -64,7 +484,7 @@ dotnet_naming_symbols.parameters_and_locals.applicable_accessibilities = *
dotnet_naming_symbols.most_symbols.applicable_kinds = namespace, class, struct, enum, field, property, method, local_function, event, delegate, type_parameter
dotnet_naming_symbols.most_symbols.applicable_accessibilities = *
## Naming rules:
## Naming Rules
dotnet_naming_rule.const_locals_should_be_pascal_case.symbols = const_locals
dotnet_naming_rule.const_locals_should_be_pascal_case.style = pascal_case
@@ -98,86 +518,309 @@ dotnet_naming_rule.most_symbols_should_be_pascal_case.symbols = most_symbols
dotnet_naming_rule.most_symbols_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.most_symbols_should_be_pascal_case.severity = warning
## Formatting:
# Also handled by StyleCopAnalyzers - SA1024: ColonsMustBeSpacedCorrectly.
csharp_space_after_colon_in_inheritance_clause = true
### StyleCop.Analyzers
### https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/DOCUMENTATION.md
# Also handled by StyleCopAnalyzers - SA1024: ColonsMustBeSpacedCorrectly.
csharp_space_before_colon_in_inheritance_clause = true
# Below we enable rule categories by setting severity to warning.
# We'll only list rules to disable.
# Individual rules we wish to disable are typically set to none severity.
# Also handled by StyleCopAnalyzers - SA1000: KeywordsMustBeSpacedCorrectly.
csharp_space_after_keywords_in_control_flow_statements = true
# Covers SAxxxx and SXxxxx rules
dotnet_analyzer_diagnostic.category-StyleCop.CSharp.DocumentationRules.severity = warning
dotnet_analyzer_diagnostic.category-StyleCop.CSharp.LayoutRules.severity = warning
dotnet_analyzer_diagnostic.category-StyleCop.CSharp.MaintainabilityRules.severity = warning
dotnet_analyzer_diagnostic.category-StyleCop.CSharp.NamingRules.severity = warning
dotnet_analyzer_diagnostic.category-StyleCop.CSharp.OrderingRules.severity = warning
dotnet_analyzer_diagnostic.category-StyleCop.CSharp.ReadabilityRules.severity = warning
dotnet_analyzer_diagnostic.category-StyleCop.CSharp.SpacingRules.severity = warning
dotnet_analyzer_diagnostic.category-StyleCop.CSharp.SpecialRules.severity = warning
# Leave code block on single line.
csharp_preserve_single_line_blocks = true
# Rules that are covered by IDE0001 Simplify name
dotnet_diagnostic.SA1125.severity = none # UseShorthandForNullableTypes
# Leave statements and member declarations on the same line.
csharp_preserve_single_line_statements = true
# Rules that are covered by IDE0047 Remove unnecessary parentheses
dotnet_diagnostic.SA1119.severity = none # StatementMustNotUseUnnecessaryParenthesis
# IDE0049, IDE-only counterpart of StyleCopAnalyzers - SA1121: UseBuiltInTypeAlias.
dotnet_style_predefined_type_for_member_access = true
# Rules that are covered by IDE0055 Formatting Rules
dotnet_diagnostic.SA1027.severity = none # UseTabsCorrectly
# IDE0049, IDE-only counterpart of StyleCopAnalyzers - SA1121: UseBuiltInTypeAlias.
dotnet_style_predefined_type_for_locals_parameters_members = true
# Rules that are covered by IDE1006 Naming Rules
dotnet_diagnostic.SA1300.severity = none # ElementMustBeginWithUpperCaseLetter
dotnet_diagnostic.SA1302.severity = none # InterfaceNamesMustBeginWithI
dotnet_diagnostic.SA1303.severity = none # ConstFieldNamesMustBeginWithUpperCaseLetter
dotnet_diagnostic.SA1304.severity = none # NonPrivateReadonlyFieldsMustBeginWithUpperCaseLetter
dotnet_diagnostic.SA1306.severity = none # FieldNamesMustBeginWithLowerCaseLetter
dotnet_diagnostic.SA1307.severity = none # AccessibleFieldsMustBeginWithUpperCaseLetter
dotnet_diagnostic.SA1311.severity = none # StaticReadonlyFieldsMustBeginWithUpperCaseLetter
dotnet_diagnostic.SA1312.severity = none # VariableNamesMustBeginWithLowerCaseLetter
dotnet_diagnostic.SA1313.severity = none # ParameterNamesMustBeginWithLowerCaseLetter
## Others:
# Rules that conflict with OpenRA project style conventions
dotnet_diagnostic.SA1101.severity = none # PrefixLocalCallsWithThis
dotnet_diagnostic.SA1107.severity = none # CodeMustNotContainMultipleStatementsOnOneLine
dotnet_diagnostic.SA1116.severity = none # SplitParametersMustStartOnLineAfterDeclaration
dotnet_diagnostic.SA1117.severity = none # ParametersMustBeOnSameLineOrSeparateLines
dotnet_diagnostic.SA1118.severity = none # ParameterMustNotSpanMultipleLines
dotnet_diagnostic.SA1122.severity = none # UseStringEmptyForEmptyStrings
dotnet_diagnostic.SA1124.severity = none # DoNotUseRegions
dotnet_diagnostic.SA1127.severity = none # GenericTypeConstraintsMustBeOnOwnLine
dotnet_diagnostic.SA1132.severity = none # DoNotCombineFields
dotnet_diagnostic.SA1135.severity = none # UsingDirectivesMustBeQualified
dotnet_diagnostic.SA1136.severity = none # EnumValuesShouldBeOnSeparateLines
dotnet_diagnostic.SA1200.severity = none # UsingDirectivesMustBePlacedCorrectly
dotnet_diagnostic.SA1201.severity = none # ElementsMustAppearInTheCorrectOrder
dotnet_diagnostic.SA1202.severity = none # ElementsMustBeOrderedByAccess
dotnet_diagnostic.SA1204.severity = none # StaticElementsMustAppearBeforeInstanceElements
dotnet_diagnostic.SA1214.severity = none # ReadonlyElementsMustAppearBeforeNonReadonlyElements
dotnet_diagnostic.SX1309.severity = none # FieldNamesMustBeginWithUnderscore
dotnet_diagnostic.SX1309S.severity = none # StaticFieldNamesMustBeginWithUnderscore
dotnet_diagnostic.SA1314.severity = none # TypeParameterNamesMustBeginWithT
dotnet_diagnostic.SA1400.severity = none # AccessModifierMustBeDeclared
dotnet_diagnostic.SA1401.severity = none # FieldsMustBePrivate
dotnet_diagnostic.SA1402.severity = none # FileMayOnlyContainASingleType
dotnet_diagnostic.SA1407.severity = none # ArithmeticExpressionsMustDeclarePrecedence
dotnet_diagnostic.SA1413.severity = none # UseTrailingCommasInMultiLineInitializers
dotnet_diagnostic.SA1501.severity = none # StatementMustNotBeOnSingleLine
dotnet_diagnostic.SA1502.severity = none # ElementMustNotBeOnSingleLine
dotnet_diagnostic.SA1503.severity = none # BracesMustNotBeOmitted
dotnet_diagnostic.SA1516.severity = none # ElementsMustBeSeparatedByBlankLine
dotnet_diagnostic.SA1519.severity = none # BracesMustNotBeOmittedFromMultiLineChildStatement
dotnet_diagnostic.SA1520.severity = none # UseBracesConsistently
dotnet_diagnostic.SA1600.severity = none # ElementsMustBeDocumented
dotnet_diagnostic.SA1601.severity = none # PartialElementsMustBeDocumented
dotnet_diagnostic.SA1602.severity = none # EnumerationItemsMustBeDocumented
dotnet_diagnostic.SA1611.severity = none # ElementParametersShouldBeDocumented
dotnet_diagnostic.SA1615.severity = none # ElementReturnValueShouldBeDocumented
dotnet_diagnostic.SA1618.severity = none # GenericTypeParametersShouldBeDocumented
dotnet_diagnostic.SA1623.severity = none # PropertySummaryDocumentationShouldMatchAccessors
dotnet_diagnostic.SA1633.severity = none # FileMustHaveHeader
dotnet_diagnostic.SA1642.severity = none # ConstructorSummaryDocumentationShouldBeginWithStandardText
dotnet_diagnostic.SA1649.severity = none # FileNameMustMatchTypeName
# Show an IDE warning when default access modifiers are explicitly specified.
dotnet_style_require_accessibility_modifiers = omit_if_default:warning
#### Code Quality Rules
#### https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/
# Don't prefer braces (for one liners).
dotnet_diagnostic.IDE0011.severity = silent
# Below we enable specific rules by setting severity to warning.
# Rules are listed below with any options available.
# Options are commented out if they match the defaults.
# Object initialization can be simplified / Use object initializer.
dotnet_diagnostic.IDE0017.severity = warning
# Rule options that apply over multiple rules are set here.
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/code-quality-rule-options
dotnet_code_quality.api_surface = all
# Collection initialization can be simplified
dotnet_diagnostic.IDE0028.severity = warning
### Design Rules
### https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/design-warnings
# Simplify 'default' expression
dotnet_diagnostic.IDE0034.severity = warning
# Provide ObsoleteAttribute message.
dotnet_diagnostic.CA1041.severity = warning
# Modifiers are not ordered.
dotnet_diagnostic.IDE0036.severity = warning
# Do not declare protected members in sealed types.
dotnet_diagnostic.CA1047.severity = warning
# Raise a warning on build when default access modifiers are explicitly specified.
dotnet_diagnostic.IDE0040.severity = warning
# Declare types in namespaces.
dotnet_diagnostic.CA1050.severity = warning
# Make field readonly.
dotnet_diagnostic.IDE0044.severity = warning
# Do not hide base class methods.
dotnet_diagnostic.CA1061.severity = warning
# Unused private member.
dotnet_diagnostic.IDE0052.severity = warning
# Override 'Equals' when implementing 'IEquatable'.
dotnet_diagnostic.CA1067.severity = warning
# Unnecessary value assignment.
dotnet_diagnostic.IDE0059.severity = warning
# 'CancellationToken' parameters must come last.
dotnet_diagnostic.CA1068.severity = warning
# Unused parameter.
dotnet_diagnostic.IDE0060.severity = warning
# Do not declare event fields as virtual.
dotnet_diagnostic.CA1070.severity = warning
# Naming rule violation.
dotnet_diagnostic.IDE1006.severity = warning
### Documentation Rules
### https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/documentation-warnings
# Avoid unnecessary zero-length array allocations.
# Avoid using 'cref' tags with a prefix.
dotnet_diagnostic.CA1200.severity = warning
### Globalization Rules
### https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/globalization-warnings
### Portability and Interoperability Rules
### https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/interoperability-warnings
# Do not use 'OutAttribute' on string parameters for P/Invokes.
dotnet_diagnostic.CA1417.severity = warning
### Maintainability Rules
### https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/maintainability-warnings
# Use 'nameof' in place of string.
dotnet_diagnostic.CA1507.severity = warning
### Naming Rules
### https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/naming-warnings
# Do not prefix enum values with type name.
dotnet_code_quality.CA1712.enum_values_prefix_trigger = AnyEnumValue
dotnet_diagnostic.CA1712.severity = warning
# Flags enums should have plural names.
dotnet_diagnostic.CA1714.severity = warning
# Only 'FlagsAttribute' enums should have plural names.
dotnet_diagnostic.CA1717.severity = warning
### Performance Rules
### https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/performance-warnings
# Remove empty finalizers.
dotnet_diagnostic.CA1821.severity = warning
# Avoid unused private fields.
dotnet_diagnostic.CA1823.severity = warning
# Avoid zero-length array allocations.
dotnet_diagnostic.CA1825.severity = warning
# Do not use Enumerable methods on indexable collections. Instead use the collection directly.
# Use property instead of Linq Enumerable method.
#dotnet_code_quality.CA1826.exclude_ordefault_methods = false
dotnet_diagnostic.CA1826.severity = warning
# Count() is used where Any() could be used instead to improve performance.
# Do not use Count/LongCount when Any can be used.
dotnet_diagnostic.CA1827.severity = warning
# Do not use CountAsync/LongCountAsync when AnyAsync can be used.
dotnet_diagnostic.CA1828.severity = warning
# Use Length/Count property instead of Enumerable.Count method.
dotnet_diagnostic.CA1829.severity = warning
# Prefer strongly-typed Append and Insert method overloads on StringBuilder.
dotnet_diagnostic.CA1830.severity = warning
# Use AsSpan instead of Range-based indexers for string when appropriate.
dotnet_diagnostic.CA1831.severity = warning
# Use AsSpan or AsMemory instead of Range-based indexers for getting ReadOnlySpan or ReadOnlyMemory portion of an array.
dotnet_diagnostic.CA1832.severity = warning
# Use AsSpan or AsMemory instead of Range-based indexers for getting Span or Memory portion of an array.
dotnet_diagnostic.CA1833.severity = warning
# Prefer the memory-based overloads of ReadAsync/WriteAsync methods in stream-based classes.
dotnet_diagnostic.CA1835.severity = warning
# Prefer IsEmpty over Count when available.
dotnet_diagnostic.CA1836.severity = warning
# Use Environment.ProcessId instead of Process.GetCurrentProcess().Id.
dotnet_diagnostic.CA1837.severity = warning
# Avoid StringBuilder parameters for P/Invokes.
dotnet_diagnostic.CA1838.severity = warning
# Use Environment.CurrentManagedThreadId instead of Thread.CurrentThread.ManagedThreadId.
dotnet_diagnostic.CA1840.severity = warning
# Do not use 'WhenAll' with a single task.
dotnet_diagnostic.CA1842.severity = warning
# Do not use 'WaitAll' with a single task.
dotnet_diagnostic.CA1843.severity = warning
# Provide memory-based overrides of async methods when subclassing 'Stream'.
dotnet_diagnostic.CA1844.severity = warning
# Use span-based 'string.Concat'.
dotnet_diagnostic.CA1845.severity = warning
# Use string.Contains(char) instead of string.Contains(string) with single characters.
dotnet_diagnostic.CA1847.severity = warning
; 4-column tab indentation
[*.yaml]
indent_style = tab
indent_size = 4
# Unnecessary call to 'Dictionary.ContainsKey(key)'.
dotnet_diagnostic.CA1853.severity = warning
# Use Span<T>.Clear() instead of Span<T>.Fill().
dotnet_diagnostic.CA1855.severity = warning
# Use StartsWith instead of IndexOf.
dotnet_diagnostic.CA1858.severity = warning
# Avoid using 'Enumerable.Any()' extension method.
dotnet_diagnostic.CA1860.severity = warning
### Reliability Rules
### https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/reliability-warnings
# Do not assign property within its setter.
dotnet_diagnostic.CA2011.severity = warning
# Use ValueTasks correctly.
dotnet_diagnostic.CA2012.severity = warning
# Do not use ReferenceEquals with value types.
dotnet_diagnostic.CA2013.severity = warning
# Do not use stackalloc in loops.
dotnet_diagnostic.CA2014.severity = warning
# Forward the CancellationToken parameter to methods that take one.
dotnet_diagnostic.CA2016.severity = warning
# The 'count' argument to Buffer.BlockCopy should specify the number of bytes to copy.
dotnet_diagnostic.CA2018.severity = warning
### Security Rules
### https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/security-warnings
# Do Not Use Broken Cryptographic Algorithms.
dotnet_diagnostic.CA5351.severity = warning
### Usage Rules
### https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/usage-warnings
# Rethrow to preserve stack details.
dotnet_diagnostic.CA2200.severity = warning
# Initialize value type static fields inline.
dotnet_diagnostic.CA2207.severity = warning
# Override GetHashCode on overriding Equals.
dotnet_diagnostic.CA2218.severity = warning
# Overload operator equals on overriding ValueType.Equals.
dotnet_diagnostic.CA2231.severity = warning
# Provide correct arguments to formatting methods.
#dotnet_code_quality.CA2241.additional_string_formatting_methods =
dotnet_code_quality.CA2241.try_determine_additional_string_formatting_methods_automatically = true
dotnet_diagnostic.CA2241.severity = warning
# Test for NaN correctly.
dotnet_diagnostic.CA2242.severity = warning
# Attribute string literals should parse correctly.
dotnet_diagnostic.CA2243.severity = warning
# Do not duplicate indexed element initializations.
dotnet_diagnostic.CA2244.severity = warning
# Do not assign a property to itself.
dotnet_diagnostic.CA2245.severity = warning
# Argument passed to TaskCompletionSource constructor should be TaskCreationOptions enum instead of TaskContinuationOptions enum.
dotnet_diagnostic.CA2247.severity = warning
# Provide correct enum argument to Enum.HasFlag.
dotnet_diagnostic.CA2248.severity = warning
# Use ThrowIfCancellationRequested.
dotnet_diagnostic.CA2250.severity = warning
# Ensure ThreadStatic is only used with static fields.
dotnet_diagnostic.CA2259.severity = warning
### Roslynator
### https://github.com/JosefPihrt/Roslynator/tree/main/docs/analyzers
# Below we enable specific rules by setting severity to warning.
# Use 'Count' property instead of 'Any' method.
dotnet_diagnostic.RCS1080.severity = warning

View File

@@ -3,19 +3,22 @@ name: Continuous Integration
on:
push:
pull_request:
branches: [ bleed ]
branches: [ bleed, 'prep-*' ]
permissions:
contents: read # to fetch code (actions/checkout)
jobs:
linux:
name: Linux (.NET 6.0)
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
steps:
- name: Clone Repository
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Install .NET 6.0
uses: actions/setup-dotnet@v1
uses: actions/setup-dotnet@v3
with:
dotnet-version: '6.0.x'
@@ -31,11 +34,11 @@ jobs:
linux-mono:
name: Linux (mono)
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
steps:
- name: Clone Repository
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Check Code
run: |
@@ -53,10 +56,10 @@ jobs:
steps:
- name: Clone Repository
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Install .NET 6.0
uses: actions/setup-dotnet@v1
uses: actions/setup-dotnet@v3
with:
dotnet-version: '6.0.x'

View File

@@ -8,19 +8,22 @@ on:
required: true
default: 'release-xxxxxxxx'
permissions:
contents: read # to fetch code (actions/checkout)
jobs:
wiki:
name: Update Wiki
if: github.repository == 'openra/openra'
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
steps:
- name: Clone Repository
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
ref: ${{ github.event.inputs.tag }}
- name: Install .NET 6
uses: actions/setup-dotnet@v1
uses: actions/setup-dotnet@v3
with:
dotnet-version: '6.0.x'
@@ -29,7 +32,7 @@ jobs:
make all
- name: Clone Wiki
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
repository: openra/openra.wiki
token: ${{ secrets.DOCS_TOKEN }}
@@ -63,15 +66,15 @@ jobs:
docs:
name: Update docs.openra.net
if: github.repository == 'openra/openra'
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
steps:
- name: Clone Repository
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
ref: ${{ github.event.inputs.tag }}
- name: Install .NET 6
uses: actions/setup-dotnet@v1
uses: actions/setup-dotnet@v3
with:
dotnet-version: '6.0.x'
@@ -79,19 +82,29 @@ jobs:
run: |
make all
- name: Clone docs.openra.net
uses: actions/checkout@v2
- name: Clone docs.openra.net (Playtest)
if: startsWith(github.event.inputs.tag, 'playtest-')
uses: actions/checkout@v3
with:
repository: openra/docs
token: ${{ secrets.DOCS_TOKEN }}
path: docs
ref: playtest
- name: Clone docs.openra.net (Release)
if: startsWith(github.event.inputs.tag, 'release-')
uses: actions/checkout@v3
with:
repository: openra/docs
token: ${{ secrets.DOCS_TOKEN }}
path: docs
ref: release
- name: Update docs.openra.net (Playtest)
if: startsWith(github.event.inputs.tag, 'playtest-')
env:
GIT_TAG: ${{ github.event.inputs.tag }}
run: |
git checkout playtest
./utility.sh all --docs "${GIT_TAG}" | python3 ./packaging/format-docs.py > "docs/api/traits.md"
./utility.sh all --weapon-docs "${GIT_TAG}" | python3 ./packaging/format-docs.py > "docs/api/weapons.md"
./utility.sh all --sprite-sequence-docs "${GIT_TAG}" | python3 ./packaging/format-docs.py > "docs/api/sprite-sequences.md"
@@ -102,7 +115,6 @@ jobs:
env:
GIT_TAG: ${{ github.event.inputs.tag }}
run: |
git checkout release
./utility.sh all --docs "${GIT_TAG}" | python3 ./packaging/format-docs.py > "docs/api/traits.md"
./utility.sh all --weapon-docs "${GIT_TAG}" | python3 ./packaging/format-docs.py > "docs/api/weapons.md"
./utility.sh all --sprite-sequence-docs "${GIT_TAG}" | python3 ./packaging/format-docs.py > "docs/api/sprite-sequences.md"
@@ -115,15 +127,17 @@ jobs:
cd docs
git config --local user.email "actions@github.com"
git config --local user.name "GitHub Actions"
git add *.md
git add api/*.md
git commit -m "Update auto-generated documentation for ${GIT_TAG}"
- name: Push docs.openra.net (Release)
if: startsWith(github.event.inputs.tag, 'release-')
run: |
cd docs
git push origin release
- name: Push docs.openra.net (Playtest)
if: startsWith(github.event.inputs.tag, 'playtest-')
run: |
cd docs
git push origin playtest

View File

@@ -8,10 +8,11 @@ on:
required: true
default: 'release-xxxxxxxx'
permissions: {}
jobs:
itch:
name: Deploy to itch.io
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
if: github.repository == 'openra/openra'
steps:
- name: Download Packages

View File

@@ -7,13 +7,16 @@ on:
- 'playtest-*'
- 'devtest-*'
permissions:
contents: write # for release creation (svenstaro/upload-release-action)
jobs:
source:
name: Source Tarball
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
steps:
- name: Clone Repository
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Prepare Environment
run: echo "GIT_TAG=${GITHUB_REF#refs/tags/}" >> ${GITHUB_ENV}
@@ -34,13 +37,13 @@ jobs:
linux:
name: Linux AppImages
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
steps:
- name: Clone Repository
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Install .NET 6.0
uses: actions/setup-dotnet@v1
uses: actions/setup-dotnet@v3
with:
dotnet-version: '6.0.x'
@@ -50,6 +53,7 @@ jobs:
- name: Package AppImages
run: |
mkdir -p build/linux
sudo apt install libfuse2
./packaging/linux/buildpackage.sh "${GIT_TAG}" "${PWD}/build/linux"
- name: Upload Packages
@@ -62,21 +66,21 @@ jobs:
file: build/linux/*
macos:
name: macOS Disk Images
name: macOS Disk Image
runs-on: macos-11
steps:
- name: Clone Repository
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Install .NET 6.0
uses: actions/setup-dotnet@v1
uses: actions/setup-dotnet@v3
with:
dotnet-version: '6.0.x'
- name: Prepare Environment
run: echo "GIT_TAG=${GITHUB_REF#refs/tags/}" >> ${GITHUB_ENV}
- name: Package Disk Images
- name: Package Disk Image
env:
MACOS_DEVELOPER_IDENTITY: ${{ secrets.MACOS_DEVELOPER_IDENTITY }}
MACOS_DEVELOPER_CERTIFICATE_BASE64: ${{ secrets.MACOS_DEVELOPER_CERTIFICATE_BASE64 }}
@@ -87,7 +91,7 @@ jobs:
mkdir -p build/macos
./packaging/macos/buildpackage.sh "${GIT_TAG}" "${PWD}/build/macos"
- name: Upload Packages
- name: Upload Package
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
@@ -98,13 +102,13 @@ jobs:
windows:
name: Windows Installers
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
steps:
- name: Clone Repository
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Install .NET 6.0
uses: actions/setup-dotnet@v1
uses: actions/setup-dotnet@v3
with:
dotnet-version: '6.0.x'

View File

@@ -74,6 +74,7 @@ Also thanks to:
* Glenn Martin Jensen (Baxxster)
* Gordon Martin (Happy0)
* Guido Lipke (LipkeGu)
* Guillermo Cuenca (Wylli)
* Hervé Matysiak (Herve-M)
* Huw Pascoe
* Ian T. Jacobsen (Smilex)

View File

@@ -5,15 +5,16 @@
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Optimize>true</Optimize>
<LangVersion>7.3</LangVersion>
<LangVersion>9</LangVersion>
<DebugSymbols>true</DebugSymbols>
<EngineRootPath Condition="'$(EngineRootPath)' == ''">..</EngineRootPath>
<OutputPath>$(EngineRootPath)/bin</OutputPath>
<PlatformTarget>AnyCPU</PlatformTarget>
<ExternalConsole>false</ExternalConsole>
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
<CodeAnalysisRuleSet>$(EngineRootPath)/OpenRA.ruleset</CodeAnalysisRuleSet>
<Nullable>disable</Nullable>
<Product>OpenRA</Product>
<Copyright>Copyright (c) The OpenRA Developers and Contributors</Copyright>
</PropertyGroup>
<PropertyGroup>
@@ -30,6 +31,12 @@
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
<DefineConstants>DEBUG;TRACE</DefineConstants>
<Optimize>false</Optimize>
<!-- Enable only for Debug builds to improve compile-time performance for Release builds -->
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<!-- Enabling GenerateDocumentationFile is required for IDE0005 (Remove unnecessary import)
rule to run in command line builds. https://github.com/dotnet/roslyn/issues/41640
Enable only for Debug builds to improve compile-time performance for Release builds -->
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
<ItemGroup>
@@ -46,7 +53,6 @@
<!-- StyleCop -->
<ItemGroup>
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.2" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="All" />
</ItemGroup>
</Project>

View File

@@ -17,7 +17,7 @@ Run the game with `launch-game.cmd`. It can be handed arguments that specify the
Linux
=====
.NET 6 or Mono (version 6.4 or later) is required to compile OpenRA. We recommend using .NET 6 when possible, as Mono is poorly packaged by most Linux distributions (e.g. missing the required `msbuild` toolchain), and has been deprecated as a standalone project.
.NET 6 or Mono (version 6.12 or later) is required to compile OpenRA. We recommend using .NET 6 when possible, as Mono is poorly packaged by most Linux distributions (e.g. missing the required `msbuild` toolchain), and has been deprecated as a standalone project.
The [.NET 6 download page](https://dotnet.microsoft.com/download/dotnet/6.0) provides repositories for various package managers and binary releases for several architectures. If you prefer to use Mono, we suggest adding the [upstream repository](https://www.mono-project.com/download/stable/#download-lin) for your distro to obtain the latest version and the `msbuild` toolchain.
@@ -78,6 +78,6 @@ Type `sudo make install` for system-wide installation. Run `sudo make install-li
macOS
=====
[.NET 6](https://dotnet.microsoft.com/download/dotnet/6.0) or [Mono](https://www.mono-project.com/download/stable/#download-mac) (version 6.4 or later) is required to compile OpenRA. We recommend using .NET 6 unless you are running a very old version of macOS (10.9 through 10.14).
[.NET 6](https://dotnet.microsoft.com/download/dotnet/6.0) or [Mono](https://www.mono-project.com/download/stable/#download-mac) (version 6.12 or later) is required to compile OpenRA. We recommend using .NET 6 unless you are running a very old version of macOS (10.9 through 10.14).
To compile OpenRA, run `make` from the command line (or `make RUNTIME=mono` if using Mono). Run with `./launch-game.sh`.

View File

@@ -3,7 +3,7 @@
# to compile, run:
# make
#
# to compile using Mono (version 6.4 or greater) instead of .NET 6, run:
# to compile using Mono (version 6.12 or greater) instead of .NET 6, run:
# make RUNTIME=mono
#
# to compile using system libraries for native dependencies, run:
@@ -58,6 +58,8 @@ RM_RF = $(RM) -rf
RUNTIME ?= net6
CONFIGURATION ?= Release
DOTNET_RID = $(shell ${DOTNET} --info | grep RID: | cut -w -f3)
ARCH_X64 = $(shell echo ${DOTNET_RID} | grep x64)
# Only for use in target version:
VERSION := $(shell git name-rev --name-only --tags --no-undefined HEAD 2>/dev/null || (c=$$(git rev-parse --short HEAD 2>/dev/null) && echo git-$$c))
@@ -67,22 +69,30 @@ ifndef TARGETPLATFORM
UNAME_S := $(shell uname -s)
UNAME_M := $(shell uname -m)
ifeq ($(UNAME_S),Darwin)
ifeq ($(ARCH_X64),)
TARGETPLATFORM = osx-arm64
else
TARGETPLATFORM = osx-x64
endif
else
ifeq ($(UNAME_M),x86_64)
TARGETPLATFORM = linux-x64
else
ifeq ($(UNAME_M),aarch64)
TARGETPLATFORM = linux-arm64
else
TARGETPLATFORM = unix-generic
endif
endif
endif
endif
##################### DEVELOPMENT BUILDS AND TESTS #####################
#
all:
@echo "Compiling in ${CONFIGURATION} mode..."
ifeq ($(RUNTIME), mono)
@command -v $(firstword $(MSBUILD)) >/dev/null || (echo "OpenRA requires the '$(MSBUILD)' tool provided by Mono >= 6.4."; exit 1)
@command -v $(firstword $(MSBUILD)) >/dev/null || (echo "OpenRA requires the '$(MSBUILD)' tool provided by Mono >= 6.12."; exit 1)
@$(MSBUILD) -t:Build -restore -p:Configuration=${CONFIGURATION} -p:TargetPlatform=$(TARGETPLATFORM)
else
@$(DOTNET) build -c ${CONFIGURATION} -nologo -p:TargetPlatform=$(TARGETPLATFORM)
@@ -102,11 +112,10 @@ check:
@echo
@echo "Compiling in Debug mode..."
ifeq ($(RUNTIME), mono)
# Enabling EnforceCodeStyleInBuild and GenerateDocumentationFile as a workaround for some code style rules (in particular IDE0005) being bugged and not reporting warnings/errors otherwise.
@$(MSBUILD) -t:build -restore -p:Configuration=Debug -warnaserror -p:TargetPlatform=$(TARGETPLATFORM) -p:EnforceCodeStyleInBuild=true -p:GenerateDocumentationFile=true
@$(MSBUILD) -t:clean\;build -restore -p:Configuration=Debug -warnaserror -p:TargetPlatform=$(TARGETPLATFORM)
else
# Enabling EnforceCodeStyleInBuild and GenerateDocumentationFile as a workaround for some code style rules (in particular IDE0005) being bugged and not reporting warnings/errors otherwise.
@$(DOTNET) build -c Debug -nologo -warnaserror -p:TargetPlatform=$(TARGETPLATFORM) -p:EnforceCodeStyleInBuild=true -p:GenerateDocumentationFile=true
@$(DOTNET) clean -c Debug --nologo --verbosity minimal
@$(DOTNET) build -c Debug -nologo -warnaserror -p:TargetPlatform=$(TARGETPLATFORM)
endif
ifeq ($(TARGETPLATFORM), unix-generic)
@./configure-system-libraries.sh
@@ -164,7 +173,7 @@ help:
@echo 'to compile, run:'
@echo ' make'
@echo
@echo 'to compile using Mono (version 6.4 or greater) instead of .NET 6, run:'
@echo 'to compile using Mono (version 6.12 or greater) instead of .NET 6, run:'
@echo ' make RUNTIME=mono'
@echo
@echo 'to compile using system libraries for native dependencies, run:'

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -84,21 +84,21 @@ namespace OpenRA
class ConditionState
{
/// <summary>Delegates that have registered to be notified when this condition changes.</summary>
public readonly List<VariableObserverNotifier> Notifiers = new List<VariableObserverNotifier>();
public readonly List<VariableObserverNotifier> Notifiers = new();
/// <summary>Unique integers identifying granted instances of the condition.</summary>
public readonly HashSet<int> Tokens = new HashSet<int>();
public readonly HashSet<int> Tokens = new();
}
readonly Dictionary<string, ConditionState> conditionStates = new Dictionary<string, ConditionState>();
readonly Dictionary<string, ConditionState> conditionStates = new();
/// <summary>Each granted condition receives a unique token that is used when revoking.</summary>
readonly Dictionary<int, string> conditionTokens = new Dictionary<int, string>();
readonly Dictionary<int, string> conditionTokens = new();
int nextConditionToken = 1;
/// <summary>Cache of condition -> enabled state for quick evaluation of token counter conditions.</summary>
readonly Dictionary<string, int> conditionCache = new Dictionary<string, int>();
readonly Dictionary<string, int> conditionCache = new();
/// <summary>Read-only version of conditionCache that is passed to IConditionConsumers.</summary>
readonly IReadOnlyDictionary<string, int> readOnlyConditionCache;
@@ -587,7 +587,7 @@ namespace OpenRA
return InvalidConditionToken;
}
/// <summary>Returns whether the specified token is valid for RevokeCondition</summary>
/// <summary>Returns whether the specified token is valid for RevokeCondition.</summary>
public bool TokenValid(int token)
{
return conditionTokens.ContainsKey(token);
@@ -600,8 +600,7 @@ namespace OpenRA
Lazy<ScriptActorInterface> luaInterface;
public void OnScriptBind(ScriptContext context)
{
if (luaInterface == null)
luaInterface = Exts.Lazy(() => new ScriptActorInterface(context, this));
luaInterface ??= Exts.Lazy(() => new ScriptActorInterface(context, this));
}
public LuaValue this[LuaRuntime runtime, LuaValue keyValue]

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -41,7 +41,7 @@ namespace OpenRA
Bits = (x & 0xFFF) << 20 | (y & 0xFFF) << 8 | layer;
}
public static readonly CPos Zero = new CPos(0, 0, 0);
public static readonly CPos Zero = new(0, 0, 0);
public static explicit operator CPos(int2 a) { return new CPos(a.X, a.Y); }
@@ -56,7 +56,7 @@ namespace OpenRA
public override int GetHashCode() { return Bits.GetHashCode(); }
public bool Equals(CPos other) { return Bits == other.Bits; }
public override bool Equals(object obj) { return obj is CPos && Equals((CPos)obj); }
public override bool Equals(object obj) { return obj is CPos cell && Equals(cell); }
public override string ToString()
{

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -22,7 +22,7 @@ namespace OpenRA
public readonly int X, Y;
public CVec(int x, int y) { X = x; Y = y; }
public static readonly CVec Zero = new CVec(0, 0);
public static readonly CVec Zero = new(0, 0);
public static CVec operator +(CVec a, CVec b) { return new CVec(a.X + b.X, a.Y + b.Y); }
public static CVec operator -(CVec a, CVec b) { return new CVec(a.X - b.X, a.Y - b.Y); }
@@ -55,7 +55,7 @@ namespace OpenRA
public override int GetHashCode() { return X.GetHashCode() ^ Y.GetHashCode(); }
public bool Equals(CVec other) { return other == this; }
public override bool Equals(object obj) { return obj is CVec && Equals((CVec)obj); }
public override bool Equals(object obj) { return obj is CVec vec && Equals(vec); }
public override string ToString() { return X + "," + Y; }

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of

View File

@@ -1,39 +0,0 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version. For more
* information, see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using OpenRA.Graphics;
namespace OpenRA.Effects
{
public class AsyncAction : IEffect
{
readonly Action a;
readonly IAsyncResult ar;
public AsyncAction(IAsyncResult ar, Action a)
{
this.a = a;
this.ar = ar;
}
public void Tick(World world)
{
if (ar.IsCompleted)
{
world.AddFrameEndTask(w => { w.Remove(this); a(); });
}
}
public IEnumerable<IRenderable> Render(WorldRenderer r) { yield break; }
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -41,7 +41,7 @@ namespace OpenRA
public class ExternalMods : IReadOnlyDictionary<string, ExternalMod>
{
readonly Dictionary<string, ExternalMod> mods = new Dictionary<string, ExternalMod>();
readonly Dictionary<string, ExternalMod> mods = new();
readonly SheetBuilder sheetBuilder;
Sheet CreateSheet()
@@ -181,10 +181,12 @@ namespace OpenRA
/// <summary>
/// Removes invalid mod registrations:
/// * LaunchPath no longer exists
/// * LaunchPath and mod id matches the active mod, but the version is different
/// * Filename doesn't match internal key
/// * Fails to parse as a mod registration
/// <list type="bullet">
/// <item>LaunchPath no longer exists.</item>
/// <item>LaunchPath and mod id matches the active mod, but the version is different.</item>
/// <item>Filename doesn't match internal key.</item>
/// <item>Fails to parse as a mod registration.</item>
/// </list>
/// </summary>
internal void ClearInvalidRegistrations(ModRegistration registration)
{

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -27,9 +27,9 @@ namespace OpenRA
return string.Compare(str.ToUpperInvariant(), str, false) == 0;
}
public static string F(this string fmt, params object[] args)
public static string F(this string format, params object[] args)
{
return string.Format(fmt, args);
return string.Format(format, args);
}
public static T WithDefault<T>(T def, Func<T> f)
@@ -45,21 +45,16 @@ namespace OpenRA
return a.GetTypes().Select(t => t.Namespace).Distinct().Where(n => n != null);
}
public static bool HasAttribute<T>(this MemberInfo mi)
public static bool HasAttribute<TAttribute>(this MemberInfo mi)
where TAttribute : Attribute
{
return Attribute.IsDefined(mi, typeof(T));
return Attribute.IsDefined(mi, typeof(TAttribute));
}
public static T[] GetCustomAttributes<T>(this MemberInfo mi, bool inherit)
where T : class
public static TAttribute[] GetCustomAttributes<TAttribute>(this MemberInfo mi, bool inherit)
where TAttribute : Attribute
{
return (T[])mi.GetCustomAttributes(typeof(T), inherit);
}
public static T[] GetCustomAttributes<T>(this ParameterInfo mi)
where T : class
{
return (T[])mi.GetCustomAttributes(typeof(T), true);
return (TAttribute[])mi.GetCustomAttributes(typeof(TAttribute), inherit);
}
public static T Clamp<T>(this T val, T min, T max) where T : IComparable<T>
@@ -149,7 +144,7 @@ namespace OpenRA
static T Random<T>(IEnumerable<T> ts, MersenneTwister r, bool throws)
{
var xs = ts as ICollection<T>;
xs = xs ?? ts.ToList();
xs ??= ts.ToList();
if (xs.Count == 0)
{
if (throws)
@@ -396,8 +391,8 @@ namespace OpenRA
string debugName, Func<TKey, string> logKey = null, Func<TElement, string> logValue = null)
{
// Fall back on ToString() if null functions are provided:
logKey = logKey ?? (s => s.ToString());
logValue = logValue ?? (s => s.ToString());
logKey ??= s => s.ToString();
logValue ??= s => s.ToString();
// Try to build a dictionary and log all duplicates found (if any):
var dupKeys = new Dictionary<TKey, List<string>>();
@@ -515,7 +510,7 @@ namespace OpenRA
public static bool IsTraitEnabled<T>(this T trait)
{
return !(trait is IDisabledTrait disabledTrait) || !disabledTrait.IsTraitDisabled;
return trait is not IDisabledTrait disabledTrait || !disabledTrait.IsTraitDisabled;
}
public static T FirstEnabledTraitOrDefault<T>(this IEnumerable<T> ts)
@@ -595,8 +590,8 @@ namespace OpenRA
return true;
}
Current = span.Slice(0, index);
str = span.Slice(index + 1);
Current = span[..index];
str = span[(index + 1)..];
return true;
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -56,24 +56,20 @@ namespace OpenRA
}
public static Func<string, Type, string, object> InvalidValueAction = (s, t, f) =>
{
throw new YamlException($"FieldLoader: Cannot parse `{s}` into `{f}.{t}` ");
};
public static Action<string, Type> UnknownFieldAction = (s, f) =>
{
throw new NotImplementedException($"FieldLoader: Missing field `{s}` on `{f.Name}`");
};
static readonly ConcurrentCache<Type, FieldLoadInfo[]> TypeLoadInfo =
new ConcurrentCache<Type, FieldLoadInfo[]>(BuildTypeLoadInfo);
new(BuildTypeLoadInfo);
static readonly ConcurrentCache<string, BooleanExpression> BooleanExpressionCache =
new ConcurrentCache<string, BooleanExpression>(expression => new BooleanExpression(expression));
new(expression => new BooleanExpression(expression));
static readonly ConcurrentCache<string, IntegerExpression> IntegerExpressionCache =
new ConcurrentCache<string, IntegerExpression>(expression => new IntegerExpression(expression));
new(expression => new IntegerExpression(expression));
static readonly Dictionary<Type, Func<string, Type, string, MemberInfo, object>> TypeParsers =
new Dictionary<Type, Func<string, Type, string, MemberInfo, object>>()
new()
{
{ typeof(int), ParseInt },
{ typeof(ushort), ParseUShort },
@@ -107,7 +103,7 @@ namespace OpenRA
};
static readonly Dictionary<Type, Func<string, Type, string, MiniYaml, MemberInfo, object>> GenericTypeParsers =
new Dictionary<Type, Func<string, Type, string, MiniYaml, MemberInfo, object>>()
new()
{
{ typeof(HashSet<>), ParseHashSetOrList },
{ typeof(List<>), ParseHashSetOrList },
@@ -159,7 +155,7 @@ namespace OpenRA
static object ParseColor(string fieldName, Type fieldType, string value, MemberInfo field)
{
if (value != null && Color.TryParse(value, out var color))
return color;
return color;
return InvalidValueAction(value, fieldType, fieldName);
}
@@ -539,8 +535,7 @@ namespace OpenRA
{
object val;
if (md == null)
md = my.ToDictionary();
md ??= my.ToDictionary();
if (fli.Loader != null)
{
if (!fli.Attribute.Required || md.ContainsKey(fli.YamlName))
@@ -754,7 +749,7 @@ namespace OpenRA
[AttributeUsage(AttributeTargets.Field)]
public class SerializeAttribute : Attribute
{
public static readonly SerializeAttribute Default = new SerializeAttribute(true);
public static readonly SerializeAttribute Default = new(true);
public bool IsDefault => this == Default;

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -31,7 +31,7 @@ namespace OpenRA.FileFormats
public Color[] Palette { get; }
public byte[] Data { get; }
public SpriteFrameType Type { get; }
public Dictionary<string, string> EmbeddedData = new Dictionary<string, string>();
public Dictionary<string, string> EmbeddedData = new();
public int PixelStride => Type == SpriteFrameType.Indexed8 ? 1 : Type == SpriteFrameType.Rgb24 ? 3 : 4;

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -29,16 +29,16 @@ namespace OpenRA.FileSystem
public class FileSystem : IReadOnlyFileSystem
{
public IEnumerable<IReadOnlyPackage> MountedPackages => mountedPackages.Keys;
readonly Dictionary<IReadOnlyPackage, int> mountedPackages = new Dictionary<IReadOnlyPackage, int>();
readonly Dictionary<string, IReadOnlyPackage> explicitMounts = new Dictionary<string, IReadOnlyPackage>();
readonly Dictionary<IReadOnlyPackage, int> mountedPackages = new();
readonly Dictionary<string, IReadOnlyPackage> explicitMounts = new();
readonly string modID;
// Mod packages that should not be disposed
readonly List<IReadOnlyPackage> modPackages = new List<IReadOnlyPackage>();
readonly List<IReadOnlyPackage> modPackages = new();
readonly IReadOnlyDictionary<string, Manifest> installedMods;
readonly IPackageLoader[] packageLoaders;
Cache<string, List<IReadOnlyPackage>> fileIndex = new Cache<string, List<IReadOnlyPackage>>(_ => new List<IReadOnlyPackage>());
Cache<string, List<IReadOnlyPackage>> fileIndex = new(_ => new List<IReadOnlyPackage>());
public FileSystem(string modID, IReadOnlyDictionary<string, Manifest> installedMods, IPackageLoader[] packageLoaders)
{
@@ -85,14 +85,14 @@ namespace OpenRA.FileSystem
{
var optional = name.StartsWith("~", StringComparison.Ordinal);
if (optional)
name = name.Substring(1);
name = name[1..];
try
{
IReadOnlyPackage package;
if (name.StartsWith("$", StringComparison.Ordinal))
{
name = name.Substring(1);
name = name[1..];
if (!installedMods.TryGetValue(name, out var mod))
throw new InvalidOperationException($"Could not load mod '{name}'. Available mods: {installedMods.Keys.JoinWith(", ")}");
@@ -211,9 +211,9 @@ namespace OpenRA.FileSystem
public bool TryGetPackageContaining(string path, out IReadOnlyPackage package, out string filename)
{
var explicitSplit = path.IndexOf('|');
if (explicitSplit > 0 && explicitMounts.TryGetValue(path.Substring(0, explicitSplit), out package))
if (explicitSplit > 0 && explicitMounts.TryGetValue(path[..explicitSplit], out package))
{
filename = path.Substring(explicitSplit + 1);
filename = path[(explicitSplit + 1)..];
return true;
}
@@ -228,9 +228,9 @@ namespace OpenRA.FileSystem
var explicitSplit = filename.IndexOf('|');
if (explicitSplit > 0)
{
if (explicitMounts.TryGetValue(filename.Substring(0, explicitSplit), out var explicitPackage))
if (explicitMounts.TryGetValue(filename[..explicitSplit], out var explicitPackage))
{
s = explicitPackage.GetStream(filename.Substring(explicitSplit + 1));
s = explicitPackage.GetStream(filename[(explicitSplit + 1)..]);
if (s != null)
return true;
}
@@ -263,15 +263,15 @@ namespace OpenRA.FileSystem
{
var explicitSplit = filename.IndexOf('|');
if (explicitSplit > 0)
if (explicitMounts.TryGetValue(filename.Substring(0, explicitSplit), out var explicitPackage))
if (explicitPackage.Contains(filename.Substring(explicitSplit + 1)))
if (explicitMounts.TryGetValue(filename[..explicitSplit], out var explicitPackage))
if (explicitPackage.Contains(filename[(explicitSplit + 1)..]))
return true;
return fileIndex.ContainsKey(filename);
}
/// <summary>
/// Returns true if the given filename references an external mod via an explicit mount
/// Returns true if the given filename references an external mod via an explicit mount.
/// </summary>
public bool IsExternalModFile(string filename)
{
@@ -279,7 +279,7 @@ namespace OpenRA.FileSystem
if (explicitSplit < 0)
return false;
if (!explicitMounts.TryGetValue(filename.Substring(0, explicitSplit), out var explicitPackage))
if (!explicitMounts.TryGetValue(filename[..explicitSplit], out var explicitPackage))
return false;
if (installedMods[modID].Package == explicitPackage)
@@ -297,8 +297,8 @@ namespace OpenRA.FileSystem
var explicitSplit = path.IndexOf('|');
if (explicitSplit > 0 && !path.StartsWith("^"))
{
var parent = path.Substring(0, explicitSplit);
var filename = path.Substring(explicitSplit + 1);
var parent = path[..explicitSplit];
var filename = path[(explicitSplit + 1)..];
var parentPath = manifest.Packages.FirstOrDefault(kv => kv.Value == parent).Key;
if (parentPath == null)
@@ -306,10 +306,10 @@ namespace OpenRA.FileSystem
if (parentPath.StartsWith("$", StringComparison.Ordinal))
{
if (!installedMods.TryGetValue(parentPath.Substring(1), out var mod))
if (!installedMods.TryGetValue(parentPath[1..], out var mod))
return null;
if (!(mod.Package is Folder))
if (mod.Package is not Folder)
return null;
path = Path.Combine(mod.Package.Name, filename);
@@ -322,6 +322,28 @@ namespace OpenRA.FileSystem
return File.Exists(resolvedPath) ? resolvedPath : null;
}
public static string ResolveCaseInsensitivePath(string path)
{
var resolved = Path.GetPathRoot(path);
if (resolved == null)
return null;
foreach (var name in path[resolved.Length..].Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar))
{
// Filter out paths of the form /foo/bar/./baz
if (name == ".")
continue;
resolved = Directory.GetFileSystemEntries(resolved).FirstOrDefault(e => e.Equals(Path.Combine(resolved, name), StringComparison.InvariantCultureIgnoreCase));
if (resolved == null)
return null;
}
return resolved;
}
public string GetPrefix(IReadOnlyPackage package)
{
return explicitMounts.ContainsValue(package) ? explicitMounts.First(f => f.Value == package).Key : null;

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -18,24 +18,22 @@ namespace OpenRA.FileSystem
{
public sealed class Folder : IReadWritePackage
{
readonly string path;
public string Name { get; }
public Folder(string path)
{
this.path = path;
Name = path;
if (!Directory.Exists(path))
Directory.CreateDirectory(path);
}
public string Name => path;
public IEnumerable<string> Contents
{
get
{
// Order may vary on different file systems and it matters for hashing.
return Directory.GetFiles(path, "*", SearchOption.TopDirectoryOnly)
.Concat(Directory.GetDirectories(path))
return Directory.GetFiles(Name, "*", SearchOption.TopDirectoryOnly)
.Concat(Directory.GetDirectories(Name))
.Select(Path.GetFileName)
.OrderBy(f => f);
}
@@ -43,14 +41,14 @@ namespace OpenRA.FileSystem
public Stream GetStream(string filename)
{
try { return File.OpenRead(Path.Combine(path, filename)); }
try { return File.OpenRead(Path.Combine(Name, filename)); }
catch { return null; }
}
public bool Contains(string filename)
{
var combined = Path.Combine(path, filename);
return combined.StartsWith(path, StringComparison.Ordinal) && File.Exists(combined);
var combined = Path.Combine(Name, filename);
return combined.StartsWith(Name, StringComparison.Ordinal) && File.Exists(combined);
}
public IReadOnlyPackage OpenPackage(string filename, FileSystem context)
@@ -82,7 +80,7 @@ namespace OpenRA.FileSystem
// in FileSystem.OpenPackage. Their internal name therefore contains the
// full parent path too. We need to be careful to not add a second path
// prefix to these hacked packages.
var filePath = filename.StartsWith(path) ? filename : Path.Combine(path, filename);
var filePath = filename.StartsWith(Name) ? filename : Path.Combine(Name, filename);
Directory.CreateDirectory(Path.GetDirectoryName(filePath));
using (var s = File.Create(filePath))
@@ -96,7 +94,7 @@ namespace OpenRA.FileSystem
// in FileSystem.OpenPackage. Their internal name therefore contains the
// full parent path too. We need to be careful to not add a second path
// prefix to these hacked packages.
var filePath = filename.StartsWith(path) ? filename : Path.Combine(path, filename);
var filePath = filename.StartsWith(Name) ? filename : Path.Combine(Name, filename);
if (Directory.Exists(filePath))
Directory.Delete(filePath, true);
else if (File.Exists(filePath))

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -19,7 +19,7 @@ namespace OpenRA.FileSystem
{
public class ZipFileLoader : IPackageLoader
{
static readonly string[] Extensions = { ".zip", ".oramap" };
static readonly uint ZipSignature = 0x04034b50;
class ReadOnlyZipFile : IReadOnlyPackage
{
@@ -55,7 +55,8 @@ namespace OpenRA.FileSystem
get
{
foreach (ZipEntry entry in pkg)
yield return entry.Name;
if (entry.IsFile)
yield return entry.Name;
}
}
@@ -94,7 +95,7 @@ namespace OpenRA.FileSystem
sealed class ReadWriteZipFile : ReadOnlyZipFile, IReadWritePackage
{
readonly MemoryStream pkgStream = new MemoryStream();
readonly MemoryStream pkgStream = new();
public ReadWriteZipFile(string filename, bool create = false)
{
@@ -141,23 +142,22 @@ namespace OpenRA.FileSystem
sealed class ZipFolder : IReadOnlyPackage
{
public string Name => path;
public string Name { get; }
public ReadOnlyZipFile Parent { get; }
readonly string path;
public ZipFolder(ReadOnlyZipFile parent, string path)
{
if (path.EndsWith("/", StringComparison.Ordinal))
path = path.Substring(0, path.Length - 1);
path = path[..^1];
Name = path;
Parent = parent;
this.path = path;
}
public Stream GetStream(string filename)
{
// Zip files use '/' as a path separator
return Parent.GetStream(path + '/' + filename);
return Parent.GetStream(Name + '/' + filename);
}
public IEnumerable<string> Contents
@@ -166,9 +166,9 @@ namespace OpenRA.FileSystem
{
foreach (var entry in Parent.Contents)
{
if (entry.StartsWith(path, StringComparison.Ordinal) && entry != path)
if (entry.StartsWith(Name, StringComparison.Ordinal) && entry != Name)
{
var filename = entry.Substring(path.Length + 1);
var filename = entry[(Name.Length + 1)..];
var dirLevels = filename.Split('/').Count(c => !string.IsNullOrEmpty(c));
if (dirLevels == 1)
yield return filename;
@@ -179,12 +179,12 @@ namespace OpenRA.FileSystem
public bool Contains(string filename)
{
return Parent.Contains(path + '/' + filename);
return Parent.Contains(Name + '/' + filename);
}
public IReadOnlyPackage OpenPackage(string filename, FileSystem context)
{
return Parent.OpenPackage(path + '/' + filename, context);
return Parent.OpenPackage(Name + '/' + filename, context);
}
public void Dispose() { /* nothing to do */ }
@@ -206,7 +206,10 @@ namespace OpenRA.FileSystem
public bool TryParsePackage(Stream s, string filename, FileSystem context, out IReadOnlyPackage package)
{
if (!Extensions.Any(e => filename.EndsWith(e, StringComparison.InvariantCultureIgnoreCase)))
var readSignature = s.ReadUInt32();
s.Position -= 4;
if (readSignature != ZipSignature)
{
package = null;
return false;
@@ -218,10 +221,13 @@ namespace OpenRA.FileSystem
public static bool TryParseReadWritePackage(string filename, out IReadWritePackage package)
{
if (!Extensions.Any(e => filename.EndsWith(e, StringComparison.InvariantCultureIgnoreCase)))
using (var s = File.OpenRead(filename))
{
package = null;
return false;
if (s.ReadUInt32() != ZipSignature)
{
package = null;
return false;
}
}
package = new ReadWriteZipFile(filename);

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -29,6 +29,9 @@ namespace OpenRA
{
public static class Game
{
[TranslationReference("filename")]
const string SavedScreenshot = "notification-saved-screenshot";
public const int TimestepJankThreshold = 250; // Don't catch up for delays larger than 250ms
public static InstalledMods Mods { get; private set; }
@@ -45,7 +48,7 @@ namespace OpenRA
internal static OrderManager OrderManager;
static Server.Server server;
public static MersenneTwister CosmeticRandom = new MersenneTwister(); // not synced
public static MersenneTwister CosmeticRandom = new(); // not synced
public static Renderer Renderer;
public static Sound Sound;
@@ -62,7 +65,7 @@ namespace OpenRA
{
var newConnection = new NetworkConnection(endpoint);
if (recordReplay)
newConnection.StartRecording(() => { return TimestampedFilename(); });
newConnection.StartRecording(() => TimestampedFilename());
var om = new OrderManager(newConnection);
JoinInner(om);
@@ -184,13 +187,8 @@ namespace OpenRA
Cursor.SetCursor(null);
BeforeGameStart();
Map map;
using (new PerfTimer("PrepareMap"))
map = ModData.PrepareMap(mapUID);
using (new PerfTimer("NewWorld"))
OrderManager.World = new World(ModData, map, OrderManager, type);
OrderManager.World = new World(mapUID, ModData, OrderManager, type);
OrderManager.World.GameOver += FinishBenchmark;
@@ -267,15 +265,14 @@ namespace OpenRA
{
OrderManager om = null;
Action lobbyReady = null;
lobbyReady = () =>
void LobbyReady()
{
LobbyInfoChanged -= lobbyReady;
LobbyInfoChanged -= LobbyReady;
foreach (var o in setupOrders)
om.IssueOrder(o);
};
}
LobbyInfoChanged += lobbyReady;
LobbyInfoChanged += LobbyReady;
om = JoinServer(CreateLocalServer(mapUID), "");
}
@@ -318,7 +315,7 @@ namespace OpenRA
if (!string.IsNullOrEmpty(supportDirArg))
Platform.OverrideSupportDir(supportDirArg);
Console.WriteLine($"Platform is {Platform.CurrentPlatform}");
Console.WriteLine($"Platform is {Platform.CurrentPlatform} ({Platform.CurrentArchitecture})");
// Load the engine version as early as possible so it can be written to exception logs
try
@@ -419,7 +416,7 @@ namespace OpenRA
// Sanitize input from platform-specific launchers
// Process.Start requires paths to not be quoted, even if they contain spaces
if (launchPath != null && launchPath.First() == '"' && launchPath.Last() == '"')
launchPath = launchPath.Substring(1, launchPath.Length - 2);
launchPath = launchPath[1..^1];
// Metadata registration requires an explicit launch path
if (launchPath != null)
@@ -566,14 +563,11 @@ namespace OpenRA
// Note: These delayed actions should only be used by widgets or disposing objects
// - things that depend on a particular world should be queuing them on the world actor.
static volatile ActionQueue delayedActions = new ActionQueue();
static volatile ActionQueue delayedActions = new();
public static void RunAfterTick(Action a) { delayedActions.Add(a, RunTime); }
public static void RunAfterDelay(int delayMilliseconds, Action a) { delayedActions.Add(a, RunTime + delayMilliseconds); }
[TranslationReference("filename")]
static readonly string SavedScreenshot = "saved-screenshot";
static void TakeScreenshotInner()
{
using (new PerfTimer("Renderer.SaveScreenshot"))
@@ -619,10 +613,7 @@ namespace OpenRA
if (orderManager.TryTick())
{
Sync.RunUnsynced(world, () =>
{
world.OrderGenerator.Tick(world);
});
Sync.RunUnsynced(world, () => world.OrderGenerator.Tick(world));
world.Tick();

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -36,7 +36,7 @@ namespace OpenRA
public TimeSpan Duration => EndTimeUtc > StartTimeUtc ? EndTimeUtc - StartTimeUtc : TimeSpan.Zero;
public IList<Player> Players { get; }
public HashSet<int> DisabledSpawnPoints = new HashSet<int>();
public HashSet<int> DisabledSpawnPoints = new();
public MapPreview MapPreview => Game.ModData.MapCache[MapUid];
public IEnumerable<Player> HumanPlayers { get { return Players.Where(p => p.IsHuman); } }
public bool IsSinglePlayer => HumanPlayers.Count() == 1;

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -32,7 +32,7 @@ namespace OpenRA
/// You can remove inherited traits by adding a - in front of them as in -TraitName: to inherit everything, but this trait.
/// </summary>
public readonly string Name;
readonly TypeDictionary traits = new TypeDictionary();
readonly TypeDictionary traits = new();
List<TraitInfo> constructOrderCache = null;
public ActorInfo(ObjectCreator creator, string name, MiniYaml node)
@@ -115,27 +115,34 @@ namespace OpenRA
}).ToList();
var resolved = source.Where(s => s.Dependencies.Count == 0 && s.OptionalDependencies.Count == 0).ToList();
var unresolved = source.Except(resolved);
var unresolved = source.ToHashSet();
unresolved.ExceptWith(resolved);
var testResolve = new Func<Type, Type, bool>((a, b) => a == b || a.IsAssignableFrom(b));
static bool AreResolvable(Type a, Type b) => a.IsAssignableFrom(b);
// This query detects which unresolved traits can be immediately resolved as all their direct dependencies are met.
var more = unresolved.Where(u =>
u.Dependencies.All(d => // To be resolvable, all dependencies must be satisfied according to the following conditions:
resolved.Exists(r => testResolve(d, r.Type)) && // There must exist a resolved trait that meets the dependency.
!unresolved.Any(u1 => testResolve(d, u1.Type))) && // All matching traits that meet this dependency must be resolved first.
resolved.Exists(r => AreResolvable(d, r.Type)) && // There must exist a resolved trait that meets the dependency.
!unresolved.Any(u1 => AreResolvable(d, u1.Type))) && // All matching traits that meet this dependency must be resolved first.
u.OptionalDependencies.All(d => // To be resolvable, all optional dependencies must be satisfied according to the following condition:
!unresolved.Any(u1 => testResolve(d, u1.Type)))); // All matching traits that meet this optional dependencies must be resolved first.
!unresolved.Any(u1 => AreResolvable(d, u1.Type)))); // All matching traits that meet this optional dependencies must be resolved first.
// Continue resolving traits as long as possible.
// Each time we resolve some traits, this means dependencies for other traits may then be possible to satisfy in the next pass.
while (more.Any())
resolved.AddRange(more);
var readyToResolve = more.ToList();
while (readyToResolve.Count != 0)
{
resolved.AddRange(readyToResolve);
unresolved.ExceptWith(readyToResolve);
readyToResolve.Clear();
readyToResolve.AddRange(more);
}
if (unresolved.Any())
if (unresolved.Count != 0)
{
var exceptionString = "ActorInfo(\"" + Name + "\") failed to initialize because of the following:\r\n";
var missing = unresolved.SelectMany(u => u.Dependencies.Where(d => !source.Any(s => testResolve(d, s.Type)))).Distinct();
var missing = unresolved.SelectMany(u => u.Dependencies.Where(d => !source.Any(s => AreResolvable(d, s.Type)))).Distinct();
exceptionString += "Missing:\r\n";
foreach (var m in missing)

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -15,7 +15,6 @@ using System.Linq;
using System.Threading.Tasks;
using OpenRA.FileSystem;
using OpenRA.GameRules;
using OpenRA.Graphics;
using OpenRA.Traits;
namespace OpenRA
@@ -28,7 +27,6 @@ namespace OpenRA
public readonly IReadOnlyDictionary<string, SoundInfo> Notifications;
public readonly IReadOnlyDictionary<string, MusicInfo> Music;
public readonly ITerrainInfo TerrainInfo;
public readonly SequenceProvider Sequences;
public readonly IReadOnlyDictionary<string, MiniYamlNode> ModelSequences;
public Ruleset(
@@ -38,7 +36,6 @@ namespace OpenRA
IReadOnlyDictionary<string, SoundInfo> notifications,
IReadOnlyDictionary<string, MusicInfo> music,
ITerrainInfo terrainInfo,
SequenceProvider sequences,
IReadOnlyDictionary<string, MiniYamlNode> modelSequences)
{
Actors = new ActorInfoDictionary(actors);
@@ -47,7 +44,6 @@ namespace OpenRA
Notifications = notifications;
Music = music;
TerrainInfo = terrainInfo;
Sequences = sequences;
ModelSequences = modelSequences;
foreach (var a in Actors.Values)
@@ -124,7 +120,7 @@ namespace OpenRA
var fs = modData.DefaultFileSystem;
Ruleset ruleset = null;
Action f = () =>
void LoadRuleset()
{
var actors = MergeOrDefault("Manifest,Rules", fs, m.Rules, null, null,
k => new ActorInfo(modData.ObjectCreator, k.Key.ToLowerInvariant(), k.Value),
@@ -145,15 +141,15 @@ namespace OpenRA
var modelSequences = MergeOrDefault("Manifest,ModelSequences", fs, m.ModelSequences, null, null,
k => k);
// The default ruleset does not include a preferred tileset or sequence set
ruleset = new Ruleset(actors, weapons, voices, notifications, music, null, null, modelSequences);
};
// The default ruleset does not include a preferred tileset
ruleset = new Ruleset(actors, weapons, voices, notifications, music, null, modelSequences);
}
if (modData.IsOnMainThread)
{
modData.HandleLoadingProgress();
var loader = new Task(f);
var loader = new Task(LoadRuleset);
loader.Start();
// Animate the loadscreen while we wait
@@ -161,7 +157,7 @@ namespace OpenRA
modData.HandleLoadingProgress();
}
else
f();
LoadRuleset();
return ruleset;
}
@@ -170,20 +166,19 @@ namespace OpenRA
{
var dr = modData.DefaultRules;
var terrainInfo = modData.DefaultTerrainInfo[tileSet];
var sequences = modData.DefaultSequences[tileSet];
return new Ruleset(dr.Actors, dr.Weapons, dr.Voices, dr.Notifications, dr.Music, terrainInfo, sequences, dr.ModelSequences);
return new Ruleset(dr.Actors, dr.Weapons, dr.Voices, dr.Notifications, dr.Music, terrainInfo, dr.ModelSequences);
}
public static Ruleset Load(ModData modData, IReadOnlyFileSystem fileSystem, string tileSet,
MiniYaml mapRules, MiniYaml mapWeapons, MiniYaml mapVoices, MiniYaml mapNotifications,
MiniYaml mapMusic, MiniYaml mapSequences, MiniYaml mapModelSequences)
MiniYaml mapMusic, MiniYaml mapModelSequences)
{
var m = modData.Manifest;
var dr = modData.DefaultRules;
Ruleset ruleset = null;
Action f = () =>
void LoadRuleset()
{
var actors = MergeOrDefault("Rules", fileSystem, m.Rules, mapRules, dr.Actors,
k => new ActorInfo(modData.ObjectCreator, k.Key.ToLowerInvariant(), k.Value),
@@ -204,23 +199,19 @@ namespace OpenRA
// TODO: Add support for merging custom terrain modifications
var terrainInfo = modData.DefaultTerrainInfo[tileSet];
// TODO: Top-level dictionary should be moved into the Ruleset instead of in its own object
var sequences = mapSequences == null ? modData.DefaultSequences[tileSet] :
new SequenceProvider(fileSystem, modData, tileSet, mapSequences);
var modelSequences = dr.ModelSequences;
if (mapModelSequences != null)
modelSequences = MergeOrDefault("ModelSequences", fileSystem, m.ModelSequences, mapModelSequences, dr.ModelSequences,
k => k);
ruleset = new Ruleset(actors, weapons, voices, notifications, music, terrainInfo, sequences, modelSequences);
};
ruleset = new Ruleset(actors, weapons, voices, notifications, music, terrainInfo, modelSequences);
}
if (modData.IsOnMainThread)
{
modData.HandleLoadingProgress();
var loader = new Task(f);
var loader = new Task(LoadRuleset);
loader.Start();
// Animate the loadscreen while we wait
@@ -228,7 +219,7 @@ namespace OpenRA
modData.HandleLoadingProgress();
}
else
f();
LoadRuleset();
return ruleset;
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -17,14 +17,14 @@ namespace OpenRA.GameRules
{
public class SoundInfo
{
public readonly Dictionary<string, string[]> Variants = new Dictionary<string, string[]>();
public readonly Dictionary<string, string[]> Prefixes = new Dictionary<string, string[]>();
public readonly Dictionary<string, string[]> Voices = new Dictionary<string, string[]>();
public readonly Dictionary<string, string[]> Notifications = new Dictionary<string, string[]>();
public readonly Dictionary<string, string[]> Variants = new();
public readonly Dictionary<string, string[]> Prefixes = new();
public readonly Dictionary<string, string[]> Voices = new();
public readonly Dictionary<string, string[]> Notifications = new();
public readonly string DefaultVariant = ".aud";
public readonly string DefaultPrefix = "";
public readonly HashSet<string> DisableVariants = new HashSet<string>();
public readonly HashSet<string> DisablePrefixes = new HashSet<string>();
public readonly HashSet<string> DisableVariants = new();
public readonly HashSet<string> DisablePrefixes = new();
public readonly Lazy<Dictionary<string, SoundPool>> VoicePools;
public readonly Lazy<Dictionary<string, SoundPool>> NotificationsPools;
@@ -69,7 +69,7 @@ namespace OpenRA.GameRules
public readonly float VolumeModifier;
public readonly InterruptType Type;
readonly string[] clips;
readonly List<string> liveclips = new List<string>();
readonly List<string> liveclips = new();
public SoundPool(float volumeModifier, InterruptType interruptType, params string[] clips)
{

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -99,17 +99,20 @@ namespace OpenRA.GameRules
[Desc("Number of shots in a single ammo magazine.")]
public readonly int Burst = 1;
[Desc("Can this weapon target the attacker itself?")]
public readonly bool CanTargetSelf = false;
[Desc("What types of targets are affected.")]
public readonly BitSet<TargetableType> ValidTargets = new BitSet<TargetableType>("Ground", "Water");
public readonly BitSet<TargetableType> ValidTargets = new("Ground", "Water");
[Desc("What types of targets are unaffected.", "Overrules ValidTargets.")]
public readonly BitSet<TargetableType> InvalidTargets;
static readonly BitSet<TargetableType> TargetTypeAir = new BitSet<TargetableType>("Air");
static readonly BitSet<TargetableType> TargetTypeAir = new("Air");
[Desc("If weapon is not directly targeting an actor and targeted position is above this altitude,",
"the weapon will ignore terrain target types and only check TargetTypeAir for validity.")]
public readonly WDist AirThreshold = new WDist(128);
public readonly WDist AirThreshold = new(128);
[Desc("Delay in ticks between firing shots from the same ammo magazine. If one entry, it will be used for all bursts.",
"If multiple entries, their number needs to match Burst - 1.")]
@@ -125,10 +128,10 @@ namespace OpenRA.GameRules
public readonly IProjectileInfo Projectile;
[FieldLoader.LoadUsing(nameof(LoadWarheads))]
public readonly List<IWarhead> Warheads = new List<IWarhead>();
public readonly List<IWarhead> Warheads = new();
/// <summary>
/// This constructor is used solely for documentation generation!
/// This constructor is used solely for documentation generation.
/// </summary>
public WeaponInfo() { }
@@ -206,29 +209,24 @@ namespace OpenRA.GameRules
/// <summary>Checks if the weapon is valid against (can target) the actor.</summary>
public bool IsValidAgainst(Actor victim, Actor firedBy)
{
var targetTypes = victim.GetEnabledTargetTypes();
if (!IsValidTarget(targetTypes))
if (!CanTargetSelf && victim == firedBy)
return false;
// PERF: Avoid LINQ.
foreach (var warhead in Warheads)
if (warhead.IsValidAgainst(victim, firedBy))
return true;
var targetTypes = victim.GetEnabledTargetTypes();
return false;
return IsValidTarget(targetTypes);
}
/// <summary>Checks if the weapon is valid against (can target) the frozen actor.</summary>
public bool IsValidAgainst(FrozenActor victim, Actor firedBy)
{
if (!IsValidTarget(victim.TargetTypes))
if (!victim.IsValid)
return false;
if (!Warheads.Any(w => w.IsValidAgainst(victim, firedBy)))
if (!CanTargetSelf && victim.Actor == firedBy)
return false;
return true;
return IsValidTarget(victim.TargetTypes);
}
/// <summary>Applies all the weapon's warheads to the target.</summary>

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -16,6 +16,7 @@ namespace OpenRA
{
public class GameSpeed
{
[TranslationReference]
[FieldLoader.Require]
public readonly string Name;

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -22,7 +22,7 @@ namespace OpenRA.Graphics
public string Name { get; private set; }
public bool IsDecoration { get; set; }
readonly SequenceProvider sequenceProvider;
readonly SequenceSet sequences;
readonly Func<WAngle> facingFunc;
readonly Func<bool> paused;
@@ -43,7 +43,7 @@ namespace OpenRA.Graphics
public Animation(World world, string name, Func<WAngle> facingFunc, Func<bool> paused)
{
sequenceProvider = world.Map.Rules.Sequences;
sequences = world.Map.Sequences;
Name = name.ToLowerInvariant();
this.facingFunc = facingFunc;
this.paused = paused;
@@ -61,9 +61,9 @@ namespace OpenRA.Graphics
var imageRenderable = new SpriteRenderable(image, pos, offset, CurrentSequence.ZOffset + zOffset, palette, CurrentSequence.Scale, alpha, float3.Ones, tintModifiers, IsDecoration,
rotation);
if (CurrentSequence.ShadowStart >= 0)
var shadow = CurrentSequence.GetShadow(CurrentFrame, facingFunc());
if (shadow != null)
{
var shadow = CurrentSequence.GetShadow(CurrentFrame, facingFunc());
var shadowRenderable = new SpriteRenderable(shadow, pos, offset, CurrentSequence.ShadowZOffset + zOffset, palette, CurrentSequence.Scale, 1f, float3.Ones, tintModifiers,
true, rotation);
return new IRenderable[] { shadowRenderable, imageRenderable };
@@ -80,9 +80,9 @@ namespace OpenRA.Graphics
var alpha = CurrentSequence.GetAlpha(CurrentFrame);
var imageRenderable = new UISpriteRenderable(Image, WPos.Zero + offset, imagePos, CurrentSequence.ZOffset + zOffset, palette, scale, alpha, rotation);
if (CurrentSequence.ShadowStart >= 0)
var shadow = CurrentSequence.GetShadow(CurrentFrame, facingFunc());
if (shadow != null)
{
var shadow = CurrentSequence.GetShadow(CurrentFrame, facingFunc());
var shadowPos = pos - new int2((int)(scale * shadow.Size.X / 2), (int)(scale * shadow.Size.Y / 2));
var shadowRenderable = new UISpriteRenderable(shadow, WPos.Zero + offset, shadowPos, CurrentSequence.ShadowZOffset + zOffset, palette, scale, 1f, rotation);
return new IRenderable[] { shadowRenderable, imageRenderable };
@@ -236,11 +236,11 @@ namespace OpenRA.Graphics
}
}
public bool HasSequence(string seq) { return sequenceProvider.HasSequence(Name, seq); }
public bool HasSequence(string seq) { return sequences.HasSequence(Name, seq); }
public ISpriteSequence GetSequence(string sequenceName)
{
return sequenceProvider.GetSequence(Name, sequenceName);
return sequences.GetSequence(Name, sequenceName);
}
public string GetRandomExistingSequence(string[] sequences, MersenneTwister random)

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -49,7 +49,7 @@ namespace OpenRA.Graphics
public readonly int[] PanelRegion = null;
public readonly PanelSides PanelSides = PanelSides.All;
public readonly Dictionary<string, Rectangle> Regions = new Dictionary<string, Rectangle>();
public readonly Dictionary<string, Rectangle> Regions = new();
}
public static IReadOnlyDictionary<string, Collection> Collections => collections;
@@ -100,9 +100,7 @@ namespace OpenRA.Graphics
static void LoadCollection(string name, MiniYaml yaml)
{
if (Game.ModData.LoadScreen != null)
Game.ModData.LoadScreen.Display();
Game.ModData.LoadScreen?.Display();
collections.Add(name, FieldLoader.Load<Collection>(yaml));
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -28,7 +28,7 @@ namespace OpenRA.Graphics
public IHardwareCursor[] Cursors;
}
readonly Dictionary<string, Cursor> cursors = new Dictionary<string, Cursor>();
readonly Dictionary<string, Cursor> cursors = new();
readonly SheetBuilder sheetBuilder;
readonly GraphicSettings graphicSettings;
@@ -111,8 +111,7 @@ namespace OpenRA.Graphics
var template = kv.Value;
for (var i = 0; i < template.Sprites.Length; i++)
{
if (template.Cursors[i] != null)
template.Cursors[i].Dispose();
template.Cursors[i]?.Dispose();
// Calculate the padding to position the frame within sequenceBounds
var paddingTL = -(template.Bounds.Location - template.Sprites[i].Offset.XY.ToInt2());

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -31,7 +31,8 @@ namespace OpenRA.Graphics
Palette = palette;
Name = name;
Frames = cache[cursorSrc].Skip(Start).ToArray();
var cursorSprites = cache[cursorSrc];
Frames = cursorSprites.Skip(Start).ToArray();
if ((d.ContainsKey("Length") && d["Length"].Value == "*") || (d.ContainsKey("End") && d["End"].Value == "*"))
Length = Frames.Length;
@@ -44,6 +45,12 @@ namespace OpenRA.Graphics
Frames = Frames.Take(Length).ToArray();
if (Start > cursorSprites.Length)
throw new YamlException($"Cursor {name}: {nameof(Start)} is greater than the length of the sprite sequence.");
if (Length > cursorSprites.Length)
throw new YamlException($"Cursor {name}: {nameof(Length)} is greater than the length of the sprite sequence.");
if (d.ContainsKey("X"))
{
Exts.TryParseIntegerInvariant(d["X"].Value, out var x);

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -21,9 +21,9 @@ namespace OpenRA.Graphics
public ITexture ColorShifts { get; }
public int Height { get; private set; }
readonly Dictionary<string, ImmutablePalette> palettes = new Dictionary<string, ImmutablePalette>();
readonly Dictionary<string, MutablePalette> mutablePalettes = new Dictionary<string, MutablePalette>();
readonly Dictionary<string, int> indices = new Dictionary<string, int>();
readonly Dictionary<string, ImmutablePalette> palettes = new();
readonly Dictionary<string, MutablePalette> mutablePalettes = new();
readonly Dictionary<string, int> indices = new();
byte[] buffer = Array.Empty<byte>();
float[] colorShiftBuffer = Array.Empty<float>();
@@ -70,7 +70,7 @@ namespace OpenRA.Graphics
{
Height = Exts.NextPowerOf2(index + 1);
Array.Resize(ref buffer, Height * Palette.Size * 4);
Array.Resize(ref colorShiftBuffer, Height * 4);
Array.Resize(ref colorShiftBuffer, Height * 8);
}
if (allowModifiers)
@@ -90,19 +90,20 @@ namespace OpenRA.Graphics
CopyBufferToTexture();
}
public void SetColorShift(string name, float hueOffset, float satOffset, float minHue, float maxHue)
public void SetColorShift(string name, float hueOffset, float satOffset, float valueMultiplier, float minHue, float maxHue)
{
var index = GetPaletteIndex(name);
colorShiftBuffer[4 * index + 0] = hueOffset;
colorShiftBuffer[4 * index + 1] = satOffset;
colorShiftBuffer[4 * index + 2] = minHue;
colorShiftBuffer[4 * index + 3] = maxHue;
colorShiftBuffer[8 * index + 0] = minHue;
colorShiftBuffer[8 * index + 1] = maxHue;
colorShiftBuffer[8 * index + 4] = hueOffset;
colorShiftBuffer[8 * index + 5] = satOffset;
colorShiftBuffer[8 * index + 6] = valueMultiplier;
}
public bool HasColorShift(string name)
{
var index = GetPaletteIndex(name);
return colorShiftBuffer[4 * index + 2] != 0 || colorShiftBuffer[4 * index + 3] != 0;
return colorShiftBuffer[8 * index] != 0 || colorShiftBuffer[8 * index + 1] != 0;
}
public void Initialize()
@@ -125,7 +126,7 @@ namespace OpenRA.Graphics
void CopyBufferToTexture()
{
Texture.SetData(buffer, Palette.Size, Height);
ColorShifts.SetFloatData(colorShiftBuffer, 1, Height);
ColorShifts.SetFloatData(colorShiftBuffer, 2, Height);
}
public void ApplyModifiers(IEnumerable<IPaletteModifier> paletteMods)

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -26,7 +26,7 @@ namespace OpenRA.Graphics
float[] Bounds(uint frame);
ModelRenderData RenderData(uint section);
/// <summary>Returns the smallest rectangle that covers all rotations of all frames in a model</summary>
/// <summary>Returns the smallest rectangle that covers all rotations of all frames in a model.</summary>
Rectangle AggregateBounds { get; }
}
@@ -84,7 +84,6 @@ namespace OpenRA.Graphics
}
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "IDE0060:Remove unused parameter", Justification = "Load game API")]
public PlaceholderModelSequenceLoader(ModData modData) { }
public IModelCache CacheModels(IReadOnlyFileSystem fileSystem, ModData modData, IReadOnlyDictionary<string, MiniYamlNode> modelDefinitions)

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -37,7 +37,7 @@ namespace OpenRA.Graphics
// Static constants
static readonly float[] ShadowDiffuse = new float[] { 0, 0, 0 };
static readonly float[] ShadowAmbient = new float[] { 1, 1, 1 };
static readonly float2 SpritePadding = new float2(2, 2);
static readonly float2 SpritePadding = new(2, 2);
static readonly float[] ZeroVector = new float[] { 0, 0, 0, 1 };
static readonly float[] ZVector = new float[] { 0, 0, 1, 1 };
static readonly float[] FlipMtx = Util.ScaleMatrix(1, -1, 1);
@@ -47,9 +47,9 @@ namespace OpenRA.Graphics
readonly Renderer renderer;
readonly IShader shader;
readonly Dictionary<Sheet, IFrameBuffer> mappedBuffers = new Dictionary<Sheet, IFrameBuffer>();
readonly Stack<KeyValuePair<Sheet, IFrameBuffer>> unmappedBuffers = new Stack<KeyValuePair<Sheet, IFrameBuffer>>();
readonly List<(Sheet Sheet, Action Func)> doRender = new List<(Sheet, Action)>();
readonly Dictionary<Sheet, IFrameBuffer> mappedBuffers = new();
readonly Stack<KeyValuePair<Sheet, IFrameBuffer>> unmappedBuffers = new();
readonly List<(Sheet Sheet, Action Func)> doRender = new();
SheetBuilder sheetBuilderForFrame;
bool isInFrame;
@@ -167,8 +167,7 @@ namespace OpenRA.Graphics
CalculateSpriteGeometry(tl, br, 1, out var spriteSize, out var spriteOffset);
CalculateSpriteGeometry(stl, sbr, 2, out var shadowSpriteSize, out var shadowSpriteOffset);
if (sheetBuilderForFrame == null)
sheetBuilderForFrame = new SheetBuilder(SheetType.BGRA, AllocateSheet);
sheetBuilderForFrame ??= new SheetBuilder(SheetType.BGRA, AllocateSheet);
var sprite = sheetBuilderForFrame.Allocate(spriteSize, 0, spriteOffset);
var shadowSprite = sheetBuilderForFrame.Allocate(shadowSpriteSize, 0, shadowSpriteOffset);

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -108,7 +108,7 @@ namespace OpenRA.Graphics
public ImmutablePalette(IPalette p)
{
for (int i = 0; i < Palette.Size; i++)
for (var i = 0; i < Palette.Size; i++)
colors[i] = p[i];
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -20,12 +20,14 @@ namespace OpenRA.Graphics
readonly int[] remapIndices;
readonly float hue;
readonly float saturation;
readonly float value;
public PlayerColorRemap(int[] remapIndices, float hue, float saturation)
public PlayerColorRemap(int[] remapIndices, Color color)
{
this.remapIndices = remapIndices;
this.hue = hue;
this.saturation = saturation;
var (r, g, b) = color.ToLinear();
(hue, saturation, value) = Color.RgbToHsv(r, g, b);
}
public Color GetRemappedColor(Color original, int index)
@@ -42,7 +44,7 @@ namespace OpenRA.Graphics
var value = Math.Max(Math.Max(r, g), b);
// Construct the new RGB color
(r, g, b) = Color.HsvToRgb(hue, saturation, value);
(r, g, b) = Color.HsvToRgb(hue, saturation, value * this.value);
// Convert linear back to SRGB and pre-multiply by the alpha
return Color.FromLinear(original.A, r, g, b);

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -18,7 +18,7 @@ namespace OpenRA.Graphics
{
public class RgbaColorRenderer
{
static readonly float3 Offset = new float3(0.5f, 0.5f, 0f);
static readonly float3 Offset = new(0.5f, 0.5f, 0f);
readonly SpriteRenderer parent;
readonly Vertex[] vertices = new Vertex[6];
@@ -78,7 +78,7 @@ namespace OpenRA.Graphics
/// <summary>
/// Calculate the 2D intersection of two lines.
/// Will behave badly if the lines are parallel.
/// Z position is the average of a and b (ignores actual intersection point if it exists)
/// Z position is the average of a and b (ignores actual intersection point if it exists).
/// </summary>
float3 IntersectionOf(in float3 a, in float3 da, in float3 b, in float3 db)
{
@@ -138,7 +138,7 @@ namespace OpenRA.Graphics
// Segment is part of closed loop
if (closed)
{
var prev = points[points.Length - 1];
var prev = points[^1];
var prevDir = (start - prev) / (start - prev).XY.Length;
var prevCorner = width / 2 * new float3(-prevDir.Y, prevDir.X, prevDir.Z);
ca = IntersectionOf(start - prevCorner, prevDir, start - corner, dir);

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of

View File

@@ -1,152 +0,0 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version. For more
* information, see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using OpenRA.FileSystem;
using OpenRA.Primitives;
namespace OpenRA.Graphics
{
using Sequences = IReadOnlyDictionary<string, Lazy<IReadOnlyDictionary<string, ISpriteSequence>>>;
using UnitSequences = Lazy<IReadOnlyDictionary<string, ISpriteSequence>>;
public interface ISpriteSequence
{
string Name { get; }
int Start { get; }
int Length { get; }
int Stride { get; }
int Facings { get; }
int InterpolatedFacings { get; }
int Tick { get; }
int ZOffset { get; }
int ShadowStart { get; }
int ShadowZOffset { get; }
int[] Frames { get; }
Rectangle Bounds { get; }
bool IgnoreWorldTint { get; }
float Scale { get; }
Sprite GetSprite(int frame);
Sprite GetSprite(int frame, WAngle facing);
(Sprite, WAngle) GetSpriteWithRotation(int frame, WAngle facing);
Sprite GetShadow(int frame, WAngle facing);
float GetAlpha(int frame);
}
public interface ISpriteSequenceLoader
{
IReadOnlyDictionary<string, ISpriteSequence> ParseSequences(ModData modData, string tileSet, SpriteCache cache, MiniYamlNode node);
}
public class SequenceProvider : IDisposable
{
readonly ModData modData;
readonly string tileSet;
readonly Lazy<Sequences> sequences;
readonly Lazy<SpriteCache> spriteCache;
public SpriteCache SpriteCache => spriteCache.Value;
readonly Dictionary<string, UnitSequences> sequenceCache = new Dictionary<string, UnitSequences>();
public SequenceProvider(IReadOnlyFileSystem fileSystem, ModData modData, string tileSet, MiniYaml additionalSequences)
{
this.modData = modData;
this.tileSet = tileSet;
sequences = Exts.Lazy(() =>
{
using (new Support.PerfTimer("LoadSequences"))
return Load(fileSystem, additionalSequences);
});
spriteCache = Exts.Lazy(() => new SpriteCache(fileSystem, modData.SpriteLoaders));
}
public ISpriteSequence GetSequence(string unitName, string sequenceName)
{
if (!sequences.Value.TryGetValue(unitName, out var unitSeq))
throw new InvalidOperationException($"Unit `{unitName}` does not have any sequences defined.");
if (!unitSeq.Value.TryGetValue(sequenceName, out var seq))
throw new InvalidOperationException($"Unit `{unitName}` does not have a sequence named `{sequenceName}`");
return seq;
}
public IEnumerable<string> Images => sequences.Value.Keys;
public bool HasSequence(string unitName)
{
return sequences.Value.ContainsKey(unitName);
}
public bool HasSequence(string unitName, string sequenceName)
{
if (!sequences.Value.TryGetValue(unitName, out var unitSeq))
throw new InvalidOperationException($"Unit `{unitName}` does not have any sequences defined.");
return unitSeq.Value.ContainsKey(sequenceName);
}
public IEnumerable<string> Sequences(string unitName)
{
if (!sequences.Value.TryGetValue(unitName, out var unitSeq))
throw new InvalidOperationException($"Unit `{unitName}` does not have any sequences defined.");
return unitSeq.Value.Keys;
}
Sequences Load(IReadOnlyFileSystem fileSystem, MiniYaml additionalSequences)
{
var nodes = MiniYaml.Load(fileSystem, modData.Manifest.Sequences, additionalSequences);
var items = new Dictionary<string, UnitSequences>();
foreach (var node in nodes)
{
// Nodes starting with ^ are inheritable but never loaded directly
if (node.Key.StartsWith(ActorInfo.AbstractActorPrefix, StringComparison.Ordinal))
continue;
var key = node.Value.ToLines(node.Key).JoinWith("|");
if (sequenceCache.TryGetValue(key, out var t))
items.Add(node.Key, t);
else
{
t = Exts.Lazy(() => modData.SpriteSequenceLoader.ParseSequences(modData, tileSet, SpriteCache, node));
sequenceCache.Add(key, t);
items.Add(node.Key, t);
}
}
return items;
}
public void Preload()
{
foreach (var sb in SpriteCache.SheetBuilders.Values)
sb.Current.CreateBuffer();
foreach (var unitSeq in sequences.Value.Values)
foreach (var seq in unitSeq.Value.Values) { }
foreach (var sb in SpriteCache.SheetBuilders.Values)
sb.Current.ReleaseBuffer();
}
public void Dispose()
{
if (spriteCache.IsValueCreated)
foreach (var sb in SpriteCache.SheetBuilders.Values)
sb.Dispose();
}
}
}

View File

@@ -0,0 +1,119 @@
#region Copyright & License Information
/*
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version. For more
* information, see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using OpenRA.FileSystem;
using OpenRA.Primitives;
namespace OpenRA.Graphics
{
public interface ISpriteSequence
{
string Name { get; }
int Length { get; }
int Facings { get; }
int Tick { get; }
int ZOffset { get; }
int ShadowZOffset { get; }
Rectangle Bounds { get; }
bool IgnoreWorldTint { get; }
float Scale { get; }
void ResolveSprites(SpriteCache cache);
Sprite GetSprite(int frame);
Sprite GetSprite(int frame, WAngle facing);
(Sprite Sprite, WAngle Rotation) GetSpriteWithRotation(int frame, WAngle facing);
Sprite GetShadow(int frame, WAngle facing);
float GetAlpha(int frame);
}
public interface ISpriteSequenceLoader
{
int BgraSheetSize { get; }
int IndexedSheetSize { get; }
IReadOnlyDictionary<string, ISpriteSequence> ParseSequences(ModData modData, string tileSet, SpriteCache cache, MiniYamlNode node);
}
public sealed class SequenceSet : IDisposable
{
readonly ModData modData;
readonly string tileSet;
readonly IReadOnlyDictionary<string, IReadOnlyDictionary<string, ISpriteSequence>> images;
public SpriteCache SpriteCache { get; }
public SequenceSet(IReadOnlyFileSystem fileSystem, ModData modData, string tileSet, MiniYaml additionalSequences)
{
this.modData = modData;
this.tileSet = tileSet;
SpriteCache = new SpriteCache(fileSystem, modData.SpriteLoaders, modData.SpriteSequenceLoader.BgraSheetSize, modData.SpriteSequenceLoader.IndexedSheetSize);
using (new Support.PerfTimer("LoadSequences"))
images = Load(fileSystem, additionalSequences);
}
public ISpriteSequence GetSequence(string image, string sequence)
{
if (!images.TryGetValue(image, out var sequences))
throw new InvalidOperationException($"Image `{image}` does not have any sequences defined.");
if (!sequences.TryGetValue(sequence, out var seq))
throw new InvalidOperationException($"Image `{image}` does not have a sequence named `{sequence}`.");
return seq;
}
public IEnumerable<string> Images => images.Keys;
public bool HasSequence(string image, string sequence)
{
if (!images.TryGetValue(image, out var sequences))
throw new InvalidOperationException($"Image `{image}` does not have any sequences defined.");
return sequences.ContainsKey(sequence);
}
public IEnumerable<string> Sequences(string image)
{
if (!images.TryGetValue(image, out var sequences))
throw new InvalidOperationException($"Image `{image}` does not have any sequences defined.");
return sequences.Keys;
}
IReadOnlyDictionary<string, IReadOnlyDictionary<string, ISpriteSequence>> Load(IReadOnlyFileSystem fileSystem, MiniYaml additionalSequences)
{
var nodes = MiniYaml.Load(fileSystem, modData.Manifest.Sequences, additionalSequences);
var images = new Dictionary<string, IReadOnlyDictionary<string, ISpriteSequence>>();
foreach (var node in nodes)
{
// Nodes starting with ^ are inheritable but never loaded directly
if (node.Key.StartsWith(ActorInfo.AbstractActorPrefix, StringComparison.Ordinal))
continue;
images[node.Key] = modData.SpriteSequenceLoader.ParseSequences(modData, tileSet, SpriteCache, node);
}
return images;
}
public void LoadSprites()
{
SpriteCache.LoadReservations(modData);
foreach (var sequences in images.Values)
foreach (var sequence in sequences)
sequence.Value.ResolveSprites(SpriteCache);
}
public void Dispose()
{
SpriteCache.Dispose();
}
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -34,15 +34,16 @@ namespace OpenRA.Graphics
public sealed class SheetBuilder : IDisposable
{
public readonly SheetType Type;
readonly List<Sheet> sheets = new List<Sheet>();
readonly List<Sheet> sheets = new();
readonly Func<Sheet> allocateSheet;
readonly int margin;
Sheet current;
TextureChannel channel;
int rowHeight = 0;
int2 p;
public Sheet Current { get; private set; }
public TextureChannel CurrentChannel { get; private set; }
public IEnumerable<Sheet> AllSheets => sheets;
public static Sheet AllocateSheet(SheetType type, int sheetSize)
{
return new Sheet(type, new Size(sheetSize, sheetSize));
@@ -73,10 +74,10 @@ namespace OpenRA.Graphics
public SheetBuilder(SheetType t, Func<Sheet> allocateSheet, int margin = 1)
{
channel = t == SheetType.Indexed ? TextureChannel.Red : TextureChannel.RGBA;
CurrentChannel = t == SheetType.Indexed ? TextureChannel.Red : TextureChannel.RGBA;
Type = t;
current = allocateSheet();
sheets.Add(current);
Current = allocateSheet();
sheets.Add(Current);
this.allocateSheet = allocateSheet;
this.margin = margin;
}
@@ -87,19 +88,19 @@ namespace OpenRA.Graphics
{
// Don't bother allocating empty sprites
if (size.Width == 0 || size.Height == 0)
return new Sprite(current, Rectangle.Empty, 0, spriteOffset, channel, BlendMode.Alpha);
return new Sprite(Current, Rectangle.Empty, 0, spriteOffset, CurrentChannel, BlendMode.Alpha);
var rect = Allocate(size, zRamp, spriteOffset);
Util.FastCopyIntoChannel(rect, src, type);
current.CommitBufferedData();
Current.CommitBufferedData();
return rect;
}
public Sprite Add(Png src, float scale = 1f)
{
var rect = Allocate(new Size(src.Width, src.Height), scale);
var rect = Allocate(new Size(src.Width, src.Height), scale);
Util.FastCopyIntoSprite(rect, src);
current.CommitBufferedData();
Current.CommitBufferedData();
return rect;
}
@@ -115,7 +116,7 @@ namespace OpenRA.Graphics
public Sprite Allocate(Size imageSize, float scale = 1f) { return Allocate(imageSize, 0, float3.Zero, scale); }
public Sprite Allocate(Size imageSize, float zRamp, in float3 spriteOffset, float scale = 1f)
{
if (imageSize.Width + p.X + margin > current.Size.Width)
if (imageSize.Width + p.X + margin > Current.Size.Width)
{
p = new int2(0, p.Y + rowHeight + margin);
rowHeight = imageSize.Height;
@@ -124,33 +125,29 @@ namespace OpenRA.Graphics
if (imageSize.Height > rowHeight)
rowHeight = imageSize.Height;
if (p.Y + imageSize.Height + margin > current.Size.Height)
if (p.Y + imageSize.Height + margin > Current.Size.Height)
{
var next = NextChannel(channel);
var next = NextChannel(CurrentChannel);
if (next == null)
{
current.ReleaseBuffer();
current = allocateSheet();
sheets.Add(current);
channel = Type == SheetType.Indexed ? TextureChannel.Red : TextureChannel.RGBA;
Current.ReleaseBuffer();
Current = allocateSheet();
sheets.Add(Current);
CurrentChannel = Type == SheetType.Indexed ? TextureChannel.Red : TextureChannel.RGBA;
}
else
channel = next.Value;
CurrentChannel = next.Value;
rowHeight = imageSize.Height;
p = int2.Zero;
}
var rect = new Sprite(current, new Rectangle(p.X + margin, p.Y + margin, imageSize.Width, imageSize.Height), zRamp, spriteOffset, channel, BlendMode.Alpha, scale);
var rect = new Sprite(Current, new Rectangle(p.X + margin, p.Y + margin, imageSize.Width, imageSize.Height), zRamp, spriteOffset, CurrentChannel, BlendMode.Alpha, scale);
p += new int2(imageSize.Width + margin, 0);
return rect;
}
public Sheet Current => current;
public TextureChannel CurrentChannel => channel;
public IEnumerable<Sheet> AllSheets => sheets;
public void Dispose()
{
foreach (var sheet in sheets)

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of

View File

@@ -0,0 +1,174 @@
#region Copyright & License Information
/*
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version. For more
* information, see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using OpenRA.FileSystem;
using OpenRA.Primitives;
namespace OpenRA.Graphics
{
public class SpriteCache : IDisposable
{
public readonly Dictionary<SheetType, SheetBuilder> SheetBuilders;
readonly ISpriteLoader[] loaders;
readonly IReadOnlyFileSystem fileSystem;
readonly Dictionary<int, (int[] Frames, MiniYamlNode.SourceLocation Location)> spriteReservations = new();
readonly Dictionary<int, (int[] Frames, MiniYamlNode.SourceLocation Location)> frameReservations = new();
readonly Dictionary<string, List<int>> reservationsByFilename = new();
readonly Dictionary<int, ISpriteFrame[]> resolvedFrames = new();
readonly Dictionary<int, Sprite[]> resolvedSprites = new();
readonly Dictionary<int, (string Filename, MiniYamlNode.SourceLocation Location)> missingFiles = new();
int nextReservationToken = 1;
public SpriteCache(IReadOnlyFileSystem fileSystem, ISpriteLoader[] loaders, int bgraSheetSize, int indexedSheetSize, int bgraSheetMargin = 1, int indexedSheetMargin = 1)
{
SheetBuilders = new Dictionary<SheetType, SheetBuilder>
{
{ SheetType.Indexed, new SheetBuilder(SheetType.Indexed, indexedSheetSize, indexedSheetMargin) },
{ SheetType.BGRA, new SheetBuilder(SheetType.BGRA, bgraSheetSize, bgraSheetMargin) }
};
this.fileSystem = fileSystem;
this.loaders = loaders;
}
public int ReserveSprites(string filename, IEnumerable<int> frames, MiniYamlNode.SourceLocation location)
{
var token = nextReservationToken++;
spriteReservations[token] = (frames?.ToArray(), location);
reservationsByFilename.GetOrAdd(filename, _ => new List<int>()).Add(token);
return token;
}
public int ReserveFrames(string filename, IEnumerable<int> frames, MiniYamlNode.SourceLocation location)
{
var token = nextReservationToken++;
frameReservations[token] = (frames?.ToArray(), location);
reservationsByFilename.GetOrAdd(filename, _ => new List<int>()).Add(token);
return token;
}
static ISpriteFrame[] GetFrames(IReadOnlyFileSystem fileSystem, string filename, ISpriteLoader[] loaders, out TypeDictionary metadata)
{
metadata = null;
if (!fileSystem.TryOpen(filename, out var stream))
return null;
using (stream)
{
foreach (var loader in loaders)
if (loader.TryParseSprite(stream, filename, out var frames, out metadata))
return frames;
return null;
}
}
public void LoadReservations(ModData modData)
{
foreach (var sb in SheetBuilders.Values)
sb.Current.CreateBuffer();
var spriteCache = new Dictionary<int, Sprite>();
foreach (var (filename, tokens) in reservationsByFilename)
{
modData.LoadScreen?.Display();
var loadedFrames = GetFrames(fileSystem, filename, loaders, out _);
foreach (var token in tokens)
{
if (frameReservations.TryGetValue(token, out var r))
{
if (loadedFrames != null)
{
if (r.Frames != null)
{
var resolved = new ISpriteFrame[loadedFrames.Length];
foreach (var i in r.Frames)
resolved[i] = loadedFrames[i];
resolvedFrames[token] = resolved;
}
else
resolvedFrames[token] = loadedFrames;
}
else
{
resolvedFrames[token] = null;
missingFiles[token] = (filename, r.Location);
}
}
if (spriteReservations.TryGetValue(token, out r))
{
if (loadedFrames != null)
{
var resolved = new Sprite[loadedFrames.Length];
var frames = r.Frames ?? Enumerable.Range(0, loadedFrames.Length);
foreach (var i in frames)
resolved[i] = spriteCache.GetOrAdd(i,
f => SheetBuilders[SheetBuilder.FrameTypeToSheetType(loadedFrames[f].Type)].Add(loadedFrames[f]));
resolvedSprites[token] = resolved;
}
else
{
resolvedSprites[token] = null;
missingFiles[token] = (filename, r.Location);
}
}
}
spriteCache.Clear();
}
spriteReservations.Clear();
frameReservations.Clear();
reservationsByFilename.Clear();
foreach (var sb in SheetBuilders.Values)
sb.Current.ReleaseBuffer();
}
public Sprite[] ResolveSprites(int token)
{
var resolved = resolvedSprites[token];
resolvedSprites.Remove(token);
if (missingFiles.TryGetValue(token, out var r))
throw new FileNotFoundException($"{r.Location}: {r.Filename} not found", r.Filename);
return resolved;
}
public ISpriteFrame[] ResolveFrames(int token)
{
var resolved = resolvedFrames[token];
resolvedFrames.Remove(token);
if (missingFiles.TryGetValue(token, out var r))
throw new FileNotFoundException($"{r.Location}: {r.Filename} not found", r.Filename);
return resolved;
}
public IEnumerable<(string Filename, MiniYamlNode.SourceLocation Location)> MissingFiles => missingFiles.Values.ToHashSet();
public void Dispose()
{
foreach (var sb in SheetBuilders.Values)
sb.Dispose();
}
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -9,10 +9,7 @@
*/
#endregion
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using OpenRA.FileSystem;
using OpenRA.Primitives;
@@ -21,7 +18,7 @@ namespace OpenRA.Graphics
/// <summary>
/// Describes the format of the pixel data in a ISpriteFrame.
/// Note that the channel order is defined for little-endian bytes, so BGRA corresponds
/// to a 32bit ARGB value, such as that returned by Color.ToArgb()!
/// to a 32bit ARGB value, such as that returned by Color.ToArgb().
/// </summary>
public enum SpriteFrameType
{
@@ -67,94 +64,6 @@ namespace OpenRA.Graphics
bool DisableExportPadding { get; }
}
public class SpriteCache
{
public readonly Cache<SheetType, SheetBuilder> SheetBuilders;
readonly ISpriteLoader[] loaders;
readonly IReadOnlyFileSystem fileSystem;
readonly Dictionary<string, List<Sprite[]>> sprites = new Dictionary<string, List<Sprite[]>>();
readonly Dictionary<string, ISpriteFrame[]> unloadedFrames = new Dictionary<string, ISpriteFrame[]>();
readonly Dictionary<string, TypeDictionary> metadata = new Dictionary<string, TypeDictionary>();
public SpriteCache(IReadOnlyFileSystem fileSystem, ISpriteLoader[] loaders)
{
SheetBuilders = new Cache<SheetType, SheetBuilder>(t => new SheetBuilder(t));
this.fileSystem = fileSystem;
this.loaders = loaders;
}
/// <summary>
/// Returns the first set of sprites with the given filename.
/// If getUsedFrames is defined then the indices returned by the function call
/// are guaranteed to be loaded. The value of other indices in the returned
/// array are undefined and should never be accessed.
/// </summary>
public Sprite[] this[string filename, Func<int, IEnumerable<int>> getUsedFrames = null]
{
get
{
var allSprites = sprites.GetOrAdd(filename);
var sprite = allSprites.FirstOrDefault();
if (!unloadedFrames.TryGetValue(filename, out var unloaded))
unloaded = null;
// This is the first time that the file has been requested
// Load all of the frames into the unused buffer and initialize
// the loaded cache (initially empty)
if (sprite == null)
{
unloaded = FrameLoader.GetFrames(fileSystem, filename, loaders, out var fileMetadata);
unloadedFrames[filename] = unloaded;
metadata[filename] = fileMetadata;
sprite = new Sprite[unloaded.Length];
allSprites.Add(sprite);
}
// HACK: The sequence code relies on side-effects from getUsedFrames
var indices = getUsedFrames != null ? getUsedFrames(sprite.Length) :
Enumerable.Range(0, sprite.Length);
// Load any unused frames into the SheetBuilder
if (unloaded != null)
{
foreach (var i in indices)
{
if (unloaded[i] != null)
{
sprite[i] = SheetBuilders[SheetBuilder.FrameTypeToSheetType(unloaded[i].Type)].Add(unloaded[i]);
unloaded[i] = null;
}
}
// All frames have been loaded
if (unloaded.All(f => f == null))
unloadedFrames.Remove(filename);
}
return sprite;
}
}
/// <summary>
/// Returns a TypeDictionary containing any metadata defined by the frame
/// or null if the frame does not define metadata.
/// </summary>
public TypeDictionary FrameMetadata(string filename)
{
if (!metadata.TryGetValue(filename, out var fileMetadata))
{
FrameLoader.GetFrames(fileSystem, filename, loaders, out fileMetadata);
metadata[filename] = fileMetadata;
}
return fileMetadata;
}
}
public class FrameCache
{
readonly Cache<string, ISpriteFrame[]> frames;

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -21,102 +21,95 @@ namespace OpenRA.Graphics
readonly Sprite sprite;
readonly WPos pos;
readonly WVec offset;
readonly int zOffset;
readonly PaletteReference palette;
readonly float scale;
readonly WAngle rotation = WAngle.Zero;
readonly float3 tint;
readonly TintModifiers tintModifiers;
readonly float alpha;
readonly bool isDecoration;
public SpriteRenderable(Sprite sprite, WPos pos, WVec offset, int zOffset, PaletteReference palette, float scale, float alpha,
float3 tint, TintModifiers tintModifiers, bool isDecoration, WAngle rotation)
{
this.sprite = sprite;
this.pos = pos;
this.offset = offset;
this.zOffset = zOffset;
this.palette = palette;
Offset = offset;
ZOffset = zOffset;
Palette = palette;
this.scale = scale;
this.rotation = rotation;
this.tint = tint;
this.isDecoration = isDecoration;
this.tintModifiers = tintModifiers;
this.alpha = alpha;
Tint = tint;
IsDecoration = isDecoration;
TintModifiers = tintModifiers;
Alpha = alpha;
// PERF: Remove useless palette assignments for RGBA sprites
// HACK: This is working around the fact that palettes are defined on traits rather than sequences
// and can be removed once this has been fixed
if (sprite.Channel == TextureChannel.RGBA && !(palette?.HasColorShift ?? false))
this.palette = null;
Palette = null;
}
public SpriteRenderable(Sprite sprite, WPos pos, WVec offset, int zOffset, PaletteReference palette, float scale, float alpha,
float3 tint, TintModifiers tintModifiers, bool isDecoration)
: this(sprite, pos, offset, zOffset, palette, scale, alpha, tint, tintModifiers, isDecoration, WAngle.Zero) { }
public WPos Pos => pos + offset;
public WVec Offset => offset;
public PaletteReference Palette => palette;
public int ZOffset => zOffset;
public bool IsDecoration => isDecoration;
public WPos Pos => pos + Offset;
public WVec Offset { get; }
public PaletteReference Palette { get; }
public int ZOffset { get; }
public bool IsDecoration { get; }
public float Alpha => alpha;
public float3 Tint => tint;
public TintModifiers TintModifiers => tintModifiers;
public float Alpha { get; }
public float3 Tint { get; }
public TintModifiers TintModifiers { get; }
public IPalettedRenderable WithPalette(PaletteReference newPalette)
{
return new SpriteRenderable(sprite, pos, offset, zOffset, newPalette, scale, alpha, tint, tintModifiers, isDecoration, rotation);
return new SpriteRenderable(sprite, pos, Offset, ZOffset, newPalette, scale, Alpha, Tint, TintModifiers, IsDecoration, rotation);
}
public IRenderable WithZOffset(int newOffset)
{
return new SpriteRenderable(sprite, pos, offset, newOffset, palette, scale, alpha, tint, tintModifiers, isDecoration, rotation);
return new SpriteRenderable(sprite, pos, Offset, newOffset, Palette, scale, Alpha, Tint, TintModifiers, IsDecoration, rotation);
}
public IRenderable OffsetBy(in WVec vec)
{
return new SpriteRenderable(sprite, pos + vec, offset, zOffset, palette, scale, alpha, tint, tintModifiers, isDecoration, rotation);
return new SpriteRenderable(sprite, pos + vec, Offset, ZOffset, Palette, scale, Alpha, Tint, TintModifiers, IsDecoration, rotation);
}
public IRenderable AsDecoration()
{
return new SpriteRenderable(sprite, pos, offset, zOffset, palette, scale, alpha, tint, tintModifiers, true, rotation);
return new SpriteRenderable(sprite, pos, Offset, ZOffset, Palette, scale, Alpha, Tint, TintModifiers, true, rotation);
}
public IModifyableRenderable WithAlpha(float newAlpha)
{
return new SpriteRenderable(sprite, pos, offset, zOffset, palette, scale, newAlpha, tint, tintModifiers, isDecoration, rotation);
return new SpriteRenderable(sprite, pos, Offset, ZOffset, Palette, scale, newAlpha, Tint, TintModifiers, IsDecoration, rotation);
}
public IModifyableRenderable WithTint(in float3 newTint, TintModifiers newTintModifiers)
{
return new SpriteRenderable(sprite, pos, offset, zOffset, palette, scale, alpha, newTint, newTintModifiers, isDecoration, rotation);
return new SpriteRenderable(sprite, pos, Offset, ZOffset, Palette, scale, Alpha, newTint, newTintModifiers, IsDecoration, rotation);
}
float3 ScreenPosition(WorldRenderer wr)
{
var s = 0.5f * scale * sprite.Size;
return wr.Screen3DPxPosition(pos) + wr.ScreenPxOffset(offset) - new float3((int)s.X, (int)s.Y, s.Z);
return wr.Screen3DPxPosition(pos) + wr.ScreenPxOffset(Offset) - new float3((int)s.X, (int)s.Y, s.Z);
}
public IFinalizedRenderable PrepareRender(WorldRenderer wr) { return this; }
public void Render(WorldRenderer wr)
{
var wsr = Game.Renderer.WorldSpriteRenderer;
var t = alpha * tint;
if (wr.TerrainLighting != null && (tintModifiers & TintModifiers.IgnoreWorldTint) == 0)
var t = Alpha * Tint;
if (wr.TerrainLighting != null && (TintModifiers & TintModifiers.IgnoreWorldTint) == 0)
t *= wr.TerrainLighting.TintAt(pos);
// Shader interprets negative alpha as a flag to use the tint colour directly instead of multiplying the sprite colour
var a = alpha;
if ((tintModifiers & TintModifiers.ReplaceColor) != 0)
var a = Alpha;
if ((TintModifiers & TintModifiers.ReplaceColor) != 0)
a *= -1;
wsr.DrawSprite(sprite, palette, ScreenPosition(wr), scale, t, a, rotation.RendererRadians());
wsr.DrawSprite(sprite, Palette, ScreenPosition(wr), scale, t, a, rotation.RendererRadians());
}
public void RenderDebugGeometry(WorldRenderer wr)

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -27,7 +27,7 @@ namespace OpenRA.Graphics
readonly IVertexBuffer<Vertex> vertexBuffer;
readonly Vertex[] vertices;
readonly bool[] ignoreTint;
readonly HashSet<int> dirtyRows = new HashSet<int>();
readonly HashSet<int> dirtyRows = new();
readonly int rowStride;
readonly bool restrictToBounds;

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -16,10 +16,7 @@ namespace OpenRA.Graphics
public class UISpriteRenderable : IRenderable, IPalettedRenderable, IFinalizedRenderable
{
readonly Sprite sprite;
readonly WPos effectiveWorldPos;
readonly int2 screenPos;
readonly int zOffset;
readonly PaletteReference palette;
readonly float scale;
readonly float alpha;
readonly float rotation = 0f;
@@ -27,10 +24,10 @@ namespace OpenRA.Graphics
public UISpriteRenderable(Sprite sprite, WPos effectiveWorldPos, int2 screenPos, int zOffset, PaletteReference palette, float scale = 1f, float alpha = 1f, float rotation = 0f)
{
this.sprite = sprite;
this.effectiveWorldPos = effectiveWorldPos;
Pos = effectiveWorldPos;
this.screenPos = screenPos;
this.zOffset = zOffset;
this.palette = palette;
ZOffset = zOffset;
Palette = palette;
this.scale = scale;
this.alpha = alpha;
this.rotation = rotation;
@@ -39,18 +36,18 @@ namespace OpenRA.Graphics
// HACK: This is working around the fact that palettes are defined on traits rather than sequences
// and can be removed once this has been fixed
if (sprite.Channel == TextureChannel.RGBA && !(palette?.HasColorShift ?? false))
this.palette = null;
Palette = null;
}
// Does not exist in the world, so a world positions don't make sense
public WPos Pos => effectiveWorldPos;
public WPos Pos { get; }
public WVec Offset => WVec.Zero;
public bool IsDecoration => true;
public PaletteReference Palette => palette;
public int ZOffset => zOffset;
public PaletteReference Palette { get; }
public int ZOffset { get; }
public IPalettedRenderable WithPalette(PaletteReference newPalette) { return new UISpriteRenderable(sprite, effectiveWorldPos, screenPos, zOffset, newPalette, scale, alpha, rotation); }
public IPalettedRenderable WithPalette(PaletteReference newPalette) { return new UISpriteRenderable(sprite, Pos, screenPos, ZOffset, newPalette, scale, alpha, rotation); }
public IRenderable WithZOffset(int newOffset) { return this; }
public IRenderable OffsetBy(in WVec vec) { return this; }
public IRenderable AsDecoration() { return this; }
@@ -58,7 +55,7 @@ namespace OpenRA.Graphics
public IFinalizedRenderable PrepareRender(WorldRenderer wr) { return this; }
public void Render(WorldRenderer wr)
{
Game.Renderer.SpriteRenderer.DrawSprite(sprite, palette, screenPos, scale, float3.Ones, alpha, rotation);
Game.Renderer.SpriteRenderer.DrawSprite(sprite, Palette, screenPos, scale, float3.Ones, alpha, rotation);
}
public void RenderDebugGeometry(WorldRenderer wr)

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -224,10 +224,10 @@ namespace OpenRA.Graphics
}
/// <summary>Rotates a quad about its center in the x-y plane.</summary>
/// <param name="tl">The top left vertex of the quad</param>
/// <param name="size">A float3 containing the X, Y, and Z lengths of the quad</param>
/// <param name="rotation">The number of radians to rotate by</param>
/// <returns>An array of four vertices representing the rotated quad (top-left, top-right, bottom-right, bottom-left)</returns>
/// <param name="tl">The top left vertex of the quad.</param>
/// <param name="size">A float3 containing the X, Y, and Z lengths of the quad.</param>
/// <param name="rotation">The number of radians to rotate by.</param>
/// <returns>An array of four vertices representing the rotated quad (top-left, top-right, bottom-right, bottom-left).</returns>
public static float3[] RotateQuad(float3 tl, float3 size, float rotation)
{
var center = tl + 0.5f * size;
@@ -258,15 +258,15 @@ namespace OpenRA.Graphics
/// <summary>
/// Returns the bounds of an object. Used for determining which objects need to be rendered on screen, and which do not.
/// </summary>
/// <param name="offset">The top left vertex of the object</param>
/// <param name="size">A float 3 containing the X, Y, and Z lengths of the object</param>
/// <param name="rotation">The angle to rotate the object by (use 0f if there is no rotation)</param>
/// <param name="offset">The top left vertex of the object.</param>
/// <param name="size">A float 3 containing the X, Y, and Z lengths of the object.</param>
/// <param name="rotation">The angle to rotate the object by (use 0f if there is no rotation).</param>
public static Rectangle BoundingRectangle(float3 offset, float3 size, float rotation)
{
if (rotation == 0f)
return new Rectangle((int)offset.X, (int)offset.Y, (int)size.X, (int)size.Y);
var rotatedQuad = Util.RotateQuad(offset, size, rotation);
var rotatedQuad = RotateQuad(offset, size, rotation);
var minX = rotatedQuad[0].X;
var maxX = rotatedQuad[0].X;
var minY = rotatedQuad[0].Y;

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -53,7 +53,7 @@ namespace OpenRA.Graphics
public WPos CenterPosition => worldRenderer.ProjectedPosition(CenterLocation);
public Rectangle Rectangle => new Rectangle(TopLeft, new Size(viewportSize.X, viewportSize.Y));
public Rectangle Rectangle => new(TopLeft, new Size(viewportSize.X, viewportSize.Y));
public int2 TopLeft => CenterLocation - viewportSize / 2;
public int2 BottomRight => CenterLocation + viewportSize / 2;
int2 viewportSize;
@@ -66,9 +66,6 @@ namespace OpenRA.Graphics
WorldViewport lastViewportDistance;
float zoom = 1f;
float minZoom = 1f;
float maxZoom = 2f;
bool unlockMinZoom;
float unlockedMinZoomScale;
float unlockedMinZoom = 1f;
@@ -86,12 +83,13 @@ namespace OpenRA.Graphics
}
}
public float MinZoom => minZoom;
public float MinZoom { get; private set; } = 1f;
public float MaxZoom { get; private set; } = 2f;
public void AdjustZoom(float dz)
{
// Exponential ensures that equal positive and negative steps have the same effect
Zoom = (zoom * (float)Math.Exp(dz)).Clamp(unlockMinZoom ? unlockedMinZoom : minZoom, maxZoom);
Zoom = (zoom * (float)Math.Exp(dz)).Clamp(unlockMinZoom ? unlockedMinZoom : MinZoom, MaxZoom);
}
public void AdjustZoom(float dz, int2 center)
@@ -105,10 +103,10 @@ namespace OpenRA.Graphics
public void ToggleZoom()
{
// Unlocked zooms always reset to the default zoom
if (zoom < minZoom)
Zoom = minZoom;
if (zoom < MinZoom)
Zoom = MinZoom;
else
Zoom = zoom > minZoom ? minZoom : maxZoom;
Zoom = zoom > MinZoom ? MinZoom : MaxZoom;
}
public void UnlockMinimumZoom(float scale)
@@ -121,23 +119,6 @@ namespace OpenRA.Graphics
public static long LastMoveRunTime = 0;
public static int2 LastMousePos;
float ClosestTo(float[] collection, float target)
{
var closestValue = collection.First();
var subtractResult = Math.Abs(closestValue - target);
foreach (var element in collection)
{
if (Math.Abs(element - target) < subtractResult)
{
subtractResult = Math.Abs(element - target);
closestValue = element;
}
}
return closestValue;
}
public ScrollDirection GetBlockedDirections()
{
var ret = ScrollDirection.None;
@@ -227,14 +208,14 @@ namespace OpenRA.Graphics
var vd = graphicSettings.ViewportDistance;
if (viewportSizes.AllowNativeZoom && vd == WorldViewport.Native)
minZoom = 1;
MinZoom = viewportSizes.DefaultScale;
else
{
var range = viewportSizes.GetSizeRange(vd);
minZoom = CalculateMinimumZoom(range.X, range.Y);
MinZoom = CalculateMinimumZoom(range.X, range.Y) * viewportSizes.DefaultScale;
}
maxZoom = Math.Min(minZoom * viewportSizes.MaxZoomScale, Game.Renderer.NativeResolution.Height * 1f / viewportSizes.MaxZoomWindowHeight);
MaxZoom = Math.Min(MinZoom * viewportSizes.MaxZoomScale, Game.Renderer.NativeResolution.Height * viewportSizes.DefaultScale / viewportSizes.MaxZoomWindowHeight);
if (unlockMinZoom)
{
@@ -242,19 +223,19 @@ namespace OpenRA.Graphics
// TODO: Allow zooming out until the full map is visible
// We need to improve our viewport scroll handling to center the map as we zoom out
// before this will work well enough to enable
unlockedMinZoom = minZoom * unlockedMinZoomScale;
unlockedMinZoom = MinZoom * unlockedMinZoomScale;
}
if (resetCurrentZoom)
Zoom = minZoom;
Zoom = MinZoom;
else
Zoom = Zoom.Clamp(minZoom, maxZoom);
Zoom = Zoom.Clamp(MinZoom, MaxZoom);
var maxSize = (1f / (unlockMinZoom ? unlockedMinZoom : minZoom) * new float2(Game.Renderer.NativeResolution));
var maxSize = 1f / (unlockMinZoom ? unlockedMinZoom : MinZoom) * new float2(Game.Renderer.NativeResolution);
Game.Renderer.SetMaximumViewportSize(new Size((int)maxSize.X, (int)maxSize.Y));
foreach (var t in worldRenderer.World.WorldActor.TraitsImplementing<INotifyViewportZoomExtentsChanged>())
t.ViewportZoomExtentsChanged(minZoom, maxZoom);
t.ViewportZoomExtentsChanged(MinZoom, MaxZoom);
}
public CPos ViewToWorld(int2 view)
@@ -297,7 +278,7 @@ namespace OpenRA.Graphics
return worldRenderer.World.Map.CellContaining(worldRenderer.ProjectedPosition(ViewToWorldPx(view)));
}
/// <summary> Returns an unfiltered list of all cells that could potentially contain the mouse cursor</summary>
/// <summary>Returns an unfiltered list of all cells that could potentially contain the mouse cursor.</summary>
IEnumerable<MPos> CandidateMouseoverCells(int2 world)
{
var map = worldRenderer.World.Map;
@@ -313,8 +294,8 @@ namespace OpenRA.Graphics
}
public int2 ViewToWorldPx(int2 view) { return (graphicSettings.UIScale / Zoom * view.ToFloat2()).ToInt2() + TopLeft; }
public int2 WorldToViewPx(int2 world) { return ((Zoom / graphicSettings.UIScale) * (world - TopLeft).ToFloat2()).ToInt2(); }
public int2 WorldToViewPx(in float3 world) { return ((Zoom / graphicSettings.UIScale) * (world - TopLeft).XY).ToInt2(); }
public int2 WorldToViewPx(int2 world) { return (Zoom / graphicSettings.UIScale * (world - TopLeft).ToFloat2()).ToInt2(); }
public int2 WorldToViewPx(in float3 world) { return (Zoom / graphicSettings.UIScale * (world - TopLeft).XY).ToInt2(); }
public void Center(IEnumerable<Actor> actors)
{

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -31,19 +31,19 @@ namespace OpenRA.Graphics
public event Action PaletteInvalidated = null;
readonly HashSet<Actor> onScreenActors = new HashSet<Actor>();
readonly HardwarePalette palette = new HardwarePalette();
readonly Dictionary<string, PaletteReference> palettes = new Dictionary<string, PaletteReference>();
readonly HashSet<Actor> onScreenActors = new();
readonly HardwarePalette palette = new();
readonly Dictionary<string, PaletteReference> palettes = new();
readonly IRenderTerrain terrainRenderer;
readonly Lazy<DebugVisualizations> debugVis;
readonly Func<string, PaletteReference> createPaletteReference;
readonly bool enableDepthBuffer;
readonly List<IFinalizedRenderable> preparedRenderables = new List<IFinalizedRenderable>();
readonly List<IFinalizedRenderable> preparedOverlayRenderables = new List<IFinalizedRenderable>();
readonly List<IFinalizedRenderable> preparedAnnotationRenderables = new List<IFinalizedRenderable>();
readonly List<IFinalizedRenderable> preparedRenderables = new();
readonly List<IFinalizedRenderable> preparedOverlayRenderables = new();
readonly List<IFinalizedRenderable> preparedAnnotationRenderables = new();
readonly List<IRenderable> renderablesBuffer = new List<IRenderable>();
readonly List<IRenderable> renderablesBuffer = new();
internal WorldRenderer(ModData modData, World world)
{
@@ -113,9 +113,9 @@ namespace OpenRA.Graphics
palettes[name].Palette = pal;
}
public void SetPaletteColorShift(string name, float hueOffset, float satOffset, float minHue, float maxHue)
public void SetPaletteColorShift(string name, float hueOffset, float satOffset, float valueModifier, float minHue, float maxHue)
{
palette.SetColorShift(name, hueOffset, satOffset, minHue, maxHue);
palette.SetColorShift(name, hueOffset, satOffset, valueModifier, minHue, maxHue);
}
// PERF: Avoid LINQ.
@@ -177,7 +177,7 @@ namespace OpenRA.Graphics
foreach (var e in World.Effects)
{
if (!(e is IEffectAboveShroud ea))
if (e is not IEffectAboveShroud ea)
continue;
foreach (var renderable in ea.RenderAboveShroud(this))
@@ -218,7 +218,7 @@ namespace OpenRA.Graphics
foreach (var e in World.Effects)
{
if (!(e is IEffectAnnotation ea))
if (e is not IEffectAnnotation ea)
continue;
foreach (var renderAnnotation in ea.RenderAnnotation(this))

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -19,8 +19,8 @@ namespace OpenRA
public readonly string Name;
public readonly Hotkey Default = Hotkey.Invalid;
public readonly string Description = "";
public readonly HashSet<string> Types = new HashSet<string>();
public readonly HashSet<string> Contexts = new HashSet<string>();
public readonly HashSet<string> Types = new();
public readonly HashSet<string> Contexts = new();
public readonly bool Readonly = false;
public bool HasDuplicates { get; internal set; }

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -18,8 +18,8 @@ namespace OpenRA
public sealed class HotkeyManager
{
readonly Dictionary<string, Hotkey> settings;
readonly Dictionary<string, HotkeyDefinition> definitions = new Dictionary<string, HotkeyDefinition>();
readonly Dictionary<string, Hotkey> keys = new Dictionary<string, Hotkey>();
readonly Dictionary<string, HotkeyDefinition> definitions = new();
readonly Dictionary<string, Hotkey> keys = new();
public HotkeyManager(IReadOnlyFileSystem fileSystem, Dictionary<string, Hotkey> settings, Manifest manifest)
{
@@ -102,7 +102,7 @@ namespace OpenRA
return null;
}
public HotkeyReference this[string name] => new HotkeyReference(GetHotkeyReference(name));
public HotkeyReference this[string name] => new(GetHotkeyReference(name));
public IEnumerable<HotkeyDefinition> Definitions => definitions.Values;
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -9,12 +9,41 @@
*/
#endregion
using System;
using System.Reflection;
using OpenRA.Primitives;
using OpenRA.Traits;
namespace OpenRA
{
public class Utility
{
static readonly ConcurrentCache<Type, FieldInfo[]> TypeFields =
new(type => type.GetFields());
static readonly ConcurrentCache<(MemberInfo Member, Type AttributeType), bool> MemberHasAttribute =
new(x => Attribute.IsDefined(x.Member, x.AttributeType));
static readonly ConcurrentCache<(MemberInfo Member, Type AttributeType, bool Inherit), object[]> MemberCustomAttributes =
new(x => x.Member.GetCustomAttributes(x.AttributeType, x.Inherit));
public static FieldInfo[] GetFields(Type type)
{
return TypeFields[type];
}
public static bool HasAttribute<TAttribute>(MemberInfo member)
where TAttribute : Attribute
{
return MemberHasAttribute[(member, typeof(TAttribute))];
}
public static TAttribute[] GetCustomAttributes<TAttribute>(MemberInfo member, bool inherit)
where TAttribute : Attribute
{
return (TAttribute[])MemberCustomAttributes[(member, typeof(TAttribute), inherit)];
}
public readonly ModData ModData;
public readonly InstalledMods Mods;

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -15,7 +15,7 @@ namespace OpenRA
{
public readonly struct Hotkey : IEquatable<Hotkey>
{
public static Hotkey Invalid = new Hotkey(Keycode.UNKNOWN, Modifiers.None);
public static Hotkey Invalid = new(Keycode.UNKNOWN, Modifiers.None);
public bool IsValid()
{
return Key != Keycode.UNKNOWN;
@@ -42,7 +42,7 @@ namespace OpenRA
var mods = Modifiers.None;
if (parts.Length >= 2)
{
var modString = s.Substring(s.IndexOf(' '));
var modString = s[s.IndexOf(' ')..];
if (!Enum<Modifiers>.TryParse(modString, true, out mods))
return false;
}
@@ -84,7 +84,7 @@ namespace OpenRA
return obj is Hotkey o && (Hotkey?)o == this;
}
public override string ToString() { return $"{Key} {Modifiers.ToString("F")}"; }
public override string ToString() { return $"{Key} {Modifiers:F}"; }
public string DisplayString()
{

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -14,7 +14,7 @@ using System;
namespace OpenRA
{
/// <summary>
/// A reference to either a named hotkey (defined in the game settings) or a statically assigned hotkey
/// A reference to either a named hotkey (defined in the game settings) or a statically assigned hotkey.
/// </summary>
public class HotkeyReference
{

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -256,7 +256,7 @@ namespace OpenRA
public static class KeycodeExts
{
static readonly Dictionary<Keycode, string> KeyNames = new Dictionary<Keycode, string>
static readonly Dictionary<Keycode, string> KeyNames = new()
{
{ Keycode.UNKNOWN, "Undefined" },
{ Keycode.RETURN, "Return" },

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -19,7 +19,7 @@ namespace OpenRA
public readonly int U, V;
public MPos(int u, int v) { U = u; V = v; }
public static readonly MPos Zero = new MPos(0, 0);
public static readonly MPos Zero = new(0, 0);
public static bool operator ==(MPos me, MPos other) { return me.U == other.U && me.V == other.V; }
public static bool operator !=(MPos me, MPos other) { return !(me == other); }
@@ -27,7 +27,7 @@ namespace OpenRA
public override int GetHashCode() { return U.GetHashCode() ^ V.GetHashCode(); }
public bool Equals(MPos other) { return other == this; }
public override bool Equals(object obj) { return obj is MPos && Equals((MPos)obj); }
public override bool Equals(object obj) { return obj is MPos uv && Equals(uv); }
public MPos Clamp(Rectangle r)
{
@@ -64,14 +64,14 @@ namespace OpenRA
}
/// <summary>
/// Projected map position
/// Projected map position.
/// </summary>
public readonly struct PPos : IEquatable<PPos>
{
public readonly int U, V;
public PPos(int u, int v) { U = u; V = v; }
public static readonly PPos Zero = new PPos(0, 0);
public static readonly PPos Zero = new(0, 0);
public static bool operator ==(PPos me, PPos other) { return me.U == other.U && me.V == other.V; }
public static bool operator !=(PPos me, PPos other) { return !(me == other); }
@@ -88,7 +88,7 @@ namespace OpenRA
public override int GetHashCode() { return U.GetHashCode() ^ V.GetHashCode(); }
public bool Equals(PPos other) { return other == this; }
public override bool Equals(object obj) { return obj is PPos && Equals((PPos)obj); }
public override bool Equals(object obj) { return obj is PPos puv && Equals(puv); }
public override string ToString() { return U + "," + V; }
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -64,7 +64,7 @@ namespace OpenRA
public bool Hidden;
}
/// <summary> Describes what is to be loaded in order to run a mod. </summary>
/// <summary>Describes what is to be loaded in order to run a mod.</summary>
public class Manifest : IDisposable
{
public readonly string Id;
@@ -95,7 +95,7 @@ namespace OpenRA
"RequiresMods", "PackageFormats"
};
readonly TypeDictionary modules = new TypeDictionary();
readonly TypeDictionary modules = new();
readonly Dictionary<string, MiniYaml> yaml;
bool customDataLoaded;

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -54,7 +54,7 @@ namespace OpenRA
// Traits tagged with an instance name prefer inits with the same name.
// If a more specific init is not available, fall back to an unnamed init.
// If duplicate inits are defined, take the last to match standard yaml override expectations
if (info != null && !string.IsNullOrEmpty(info.InstanceName))
if (!string.IsNullOrEmpty(info?.InstanceName))
return inits.LastOrDefault(i => i.InstanceName == info.InstanceName) ??
inits.LastOrDefault(i => string.IsNullOrEmpty(i.InstanceName));
@@ -159,9 +159,9 @@ namespace OpenRA
public virtual void Initialize(T value)
{
var field = typeof(ValueActorInit<T>).GetField(nameof(value), BindingFlags.NonPublic | BindingFlags.Instance);
if (field != null)
field.SetValue(this, value);
typeof(ValueActorInit<T>)
.GetField(nameof(value), BindingFlags.NonPublic | BindingFlags.Instance)
?.SetValue(this, value);
}
public override MiniYaml Save()
@@ -246,16 +246,16 @@ namespace OpenRA
public void Initialize(MiniYaml yaml)
{
var field = typeof(OwnerInit).GetField(nameof(InternalName), BindingFlags.Public | BindingFlags.Instance);
if (field != null)
field.SetValue(this, yaml.Value);
typeof(OwnerInit)
.GetField(nameof(InternalName), BindingFlags.Public | BindingFlags.Instance)
?.SetValue(this, yaml.Value);
}
public void Initialize(Player player)
{
var field = typeof(OwnerInit).GetField(nameof(value), BindingFlags.NonPublic | BindingFlags.Instance);
if (field != null)
field.SetValue(this, player);
typeof(OwnerInit)
.GetField(nameof(value), BindingFlags.NonPublic | BindingFlags.Instance)
?.SetValue(this, player);
}
public override MiniYaml Save()

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -87,14 +87,14 @@ namespace OpenRA
var ret = new MiniYaml(Type);
foreach (var o in initDict.Value)
{
if (!(o is ActorInit init) || o is ISuppressInitExport)
if (o is not ActorInit init || o is ISuppressInitExport)
continue;
if (initFilter != null && !initFilter(init))
continue;
var initTypeName = init.GetType().Name;
var initName = initTypeName.Substring(0, initTypeName.Length - 4);
var initName = initTypeName[..^4];
if (!string.IsNullOrEmpty(init.InstanceName))
initName += ActorInfo.TraitInstanceSeparator + init.InstanceName;

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -72,7 +72,7 @@ namespace OpenRA
return uv.V * Size.Width + uv.U;
}
/// <summary>Gets or sets the <see cref="CellLayer"/> using cell coordinates</summary>
/// <summary>Gets or sets the <see cref="CellLayer"/> using cell coordinates.</summary>
public T this[CPos cell]
{
get => Entries[Index(cell)];
@@ -85,7 +85,7 @@ namespace OpenRA
}
}
/// <summary>Gets or sets the layer contents using raw map coordinates (not CPos!)</summary>
/// <summary>Gets or sets the layer contents using raw map coordinates (not CPos!).</summary>
public T this[MPos uv]
{
get => Entries[Index(uv)];

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -43,13 +43,13 @@ namespace OpenRA
Array.Copy(anotherLayer.Entries, Entries, Entries.Length);
}
/// <summary>Clears the layer contents with their default value</summary>
/// <summary>Clears the layer contents with their default value.</summary>
public virtual void Clear()
{
Array.Clear(Entries, 0, Entries.Length);
}
/// <summary>Clears the layer contents with a known value</summary>
/// <summary>Clears the layer contents with a known value.</summary>
public virtual void Clear(T clearValue)
{
Array.Fill(Entries, clearValue);

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -102,7 +102,7 @@ namespace OpenRA
return uv.U >= mapTopLeft.U && uv.U <= mapBottomRight.U && uv.V >= mapTopLeft.V && uv.V <= mapBottomRight.V;
}
public MapCoordsRegion MapCoords => new MapCoordsRegion(mapTopLeft, mapBottomRight);
public MapCoordsRegion MapCoords => new(mapTopLeft, mapBottomRight);
public CellRegionEnumerator GetEnumerator()
{
@@ -126,15 +126,12 @@ namespace OpenRA
// Current position, in map coordinates
int u, v;
// Current position, in cell coordinates
CPos current;
public CellRegionEnumerator(CellRegion region)
: this()
{
r = region;
Reset();
current = new MPos(u, v).ToCPos(r.gridType);
Current = new MPos(u, v).ToCPos(r.gridType);
}
public bool MoveNext()
@@ -152,7 +149,8 @@ namespace OpenRA
return false;
}
current = new MPos(u, v).ToCPos(r.gridType);
// Current position, in cell coordinates
Current = new MPos(u, v).ToCPos(r.gridType);
return true;
}
@@ -163,7 +161,7 @@ namespace OpenRA
v = r.mapTopLeft.V;
}
public CPos Current => current;
public CPos Current { get; private set; }
object IEnumerator.Current => Current;
public void Dispose() { }
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -149,13 +149,13 @@ namespace OpenRA
}
}
public class Map : IReadOnlyFileSystem
public class Map : IReadOnlyFileSystem, IDisposable
{
public const int SupportedMapFormat = 11;
public const int CurrentMapFormat = 12;
const short InvalidCachedTerrainIndex = -1;
/// <summary>Defines the order of the fields in map.yaml</summary>
/// <summary>Defines the order of the fields in map.yaml.</summary>
static readonly MapField[] YamlFields =
{
new MapField("MapFormat"),
@@ -198,8 +198,8 @@ namespace OpenRA
public int2 MapSize { get; private set; }
// Player and actor yaml. Public for access by the map importers and lint checks.
public List<MiniYamlNode> PlayerDefinitions = new List<MiniYamlNode>();
public List<MiniYamlNode> ActorDefinitions = new List<MiniYamlNode>();
public List<MiniYamlNode> PlayerDefinitions = new();
public List<MiniYamlNode> ActorDefinitions = new();
// Custom map yaml. Public for access by the map importers and lint checks
public readonly MiniYaml RuleDefinitions;
@@ -210,7 +210,7 @@ namespace OpenRA
public readonly MiniYaml MusicDefinitions;
public readonly MiniYaml NotificationDefinitions;
public readonly Dictionary<CPos, TerrainTile> ReplacedInvalidTerrainTiles = new Dictionary<CPos, TerrainTile>();
public readonly Dictionary<CPos, TerrainTile> ReplacedInvalidTerrainTiles = new();
// Generated data
public readonly MapGrid Grid;
@@ -218,6 +218,8 @@ namespace OpenRA
public string Uid { get; private set; }
public Ruleset Rules { get; private set; }
public SequenceSet Sequences { get; private set; }
public bool InvalidCustomRules { get; private set; }
public Exception InvalidCustomRulesException { get; private set; }
@@ -243,6 +245,8 @@ namespace OpenRA
public CellRegion AllCells { get; private set; }
public List<CPos> AllEdgeCells { get; private set; }
public event Action<CPos> CellProjectionChanged;
// Internal data
readonly ModData modData;
CellLayer<short> cachedTerrainIndexes;
@@ -336,11 +340,12 @@ namespace OpenRA
Height = new CellLayer<byte>(Grid.Type, size);
Ramp = new CellLayer<byte>(Grid.Type, size);
Tiles.Clear(terrainInfo.DefaultTerrainTile);
if (Grid.MaximumTerrainHeight > 0)
{
Height.CellEntryChanged += UpdateProjection;
Tiles.CellEntryChanged += UpdateProjection;
Tiles.CellEntryChanged += UpdateRamp;
Tiles.CellEntryChanged += UpdateProjection;
Height.CellEntryChanged += UpdateProjection;
}
PostInit();
@@ -387,7 +392,7 @@ namespace OpenRA
// TODO: Remember to remove this when rewriting tile variants / PickAny
if (index == byte.MaxValue)
index = (byte)(i % 4 + (j % 4) * 4);
index = (byte)(i % 4 + j % 4 * 4);
Tiles[new MPos(i, j)] = new TerrainTile(tile, index);
}
@@ -434,7 +439,7 @@ namespace OpenRA
try
{
Rules = Ruleset.Load(modData, this, Tileset, RuleDefinitions, WeaponDefinitions,
VoiceDefinitions, NotificationDefinitions, MusicDefinitions, SequenceDefinitions, ModelSequenceDefinitions);
VoiceDefinitions, NotificationDefinitions, MusicDefinitions, ModelSequenceDefinitions);
}
catch (Exception e)
{
@@ -444,8 +449,7 @@ namespace OpenRA
Rules = Ruleset.LoadDefaultsForTileSet(modData, Tileset);
}
Rules.Sequences.Preload();
Sequences = new SequenceSet(this, modData, Tileset, SequenceDefinitions);
Translation = new Translation(Game.Settings.Player.Language, Translations, this);
var tl = new MPos(0, 0).ToCPos(this);
@@ -477,17 +481,17 @@ namespace OpenRA
AllEdgeCells = UpdateEdgeCells();
// Invalidate the entry for a cell if anything could cause the terrain index to change.
Action<CPos> invalidateTerrainIndex = c =>
void InvalidateTerrainIndex(CPos c)
{
if (cachedTerrainIndexes != null)
cachedTerrainIndexes[c] = InvalidCachedTerrainIndex;
};
}
// Even though the cache is lazily initialized, we must attach these event handlers on init.
// This ensures our handler to invalidate the cache runs first,
// so other listeners to these same events will get correct data when calling GetTerrainIndex.
CustomTerrain.CellEntryChanged += invalidateTerrainIndex;
Tiles.CellEntryChanged += invalidateTerrainIndex;
CustomTerrain.CellEntryChanged += InvalidateTerrainIndex;
Tiles.CellEntryChanged += InvalidateTerrainIndex;
}
void UpdateRamp(CPos cell)
@@ -530,6 +534,7 @@ namespace OpenRA
var inverse = inverseCellProjection[uv];
inverse.Clear();
inverse.Add(uv);
CellProjectionChanged?.Invoke(cell);
return;
}
@@ -567,6 +572,8 @@ namespace OpenRA
projectedHeight[temp] = height;
}
}
CellProjectionChanged?.Invoke(cell);
}
byte ProjectedCellHeightInner(PPos puv)
@@ -642,12 +649,21 @@ namespace OpenRA
toPackage.Update(file, Package.GetStream(file).ReadAllBytes());
if (!LockPreview)
toPackage.Update("map.png", SavePreview());
{
var previewData = SavePreview();
if (Package != toPackage || !Enumerable.SequenceEqual(previewData, Package.GetStream("map.png").ReadAllBytes()))
toPackage.Update("map.png", previewData);
}
// Update the package with the new map data
var s = root.WriteToString();
toPackage.Update("map.yaml", Encoding.UTF8.GetBytes(s));
toPackage.Update("map.bin", SaveBinaryData());
var textData = Encoding.UTF8.GetBytes(root.WriteToString());
if (Package != toPackage || !Enumerable.SequenceEqual(textData, Package.GetStream("map.yaml").ReadAllBytes()))
toPackage.Update("map.yaml", textData);
var binaryData = SaveBinaryData();
if (Package != toPackage || !Enumerable.SequenceEqual(binaryData, Package.GetStream("map.bin").ReadAllBytes()))
toPackage.Update("map.bin", binaryData);
Package = toPackage;
// Update UID to match the newly saved data
@@ -733,7 +749,7 @@ namespace OpenRA
public byte[] SavePreview()
{
var actorTypes = Rules.Actors.Values.Where(a => a.HasTraitInfo<IMapPreviewSignatureInfo>());
var actors = ActorDefinitions.Where(a => actorTypes.Where(ai => ai.Name == a.Value.Value).Any());
var actors = ActorDefinitions.Where(a => actorTypes.Any(ai => ai.Name == a.Value.Value));
var positions = new List<(MPos Position, Color Color)>();
foreach (var actor in actors)
{
@@ -977,11 +993,11 @@ namespace OpenRA
}
/// <summary>
/// The size of the map Height step in world units
/// The size of the map Height step in world units.
/// </summary>
/// RectangularIsometric defines 1024 units along the diagonal axis,
/// giving a half-tile height step of sqrt(2) * 512
public WDist CellHeightStep => new WDist(Grid.Type == MapGridType.RectangularIsometric ? 724 : 512);
public WDist CellHeightStep => new(Grid.Type == MapGridType.RectangularIsometric ? 724 : 512);
public CPos CellContaining(WPos pos)
{
@@ -1233,8 +1249,8 @@ namespace OpenRA
if (allProjected.Length > 0)
{
var puv = allProjected.First();
var horizontalBound = ((puv.U - Bounds.Left) < Bounds.Width / 2) ? Bounds.Left : Bounds.Right;
var verticalBound = ((puv.V - Bounds.Top) < Bounds.Height / 2) ? Bounds.Top : Bounds.Bottom;
var horizontalBound = (puv.U - Bounds.Left < Bounds.Width / 2) ? Bounds.Left : Bounds.Right;
var verticalBound = (puv.V - Bounds.Top < Bounds.Height / 2) ? Bounds.Top : Bounds.Bottom;
var du = Math.Abs(horizontalBound - puv.U);
var dv = Math.Abs(verticalBound - puv.V);
@@ -1401,5 +1417,10 @@ namespace OpenRA
return modData.Translation.GetString(key, args);
}
public void Dispose()
{
Sequences.Dispose();
}
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -25,32 +25,33 @@ namespace OpenRA
{
public sealed class MapCache : IEnumerable<MapPreview>, IDisposable
{
public static readonly MapPreview UnknownMap = new MapPreview(null, null, MapGridType.Rectangular, null);
public static readonly MapPreview UnknownMap = new(null, null, MapGridType.Rectangular, null);
public IReadOnlyDictionary<IReadOnlyPackage, MapClassification> MapLocations => mapLocations;
readonly Dictionary<IReadOnlyPackage, MapClassification> mapLocations = new Dictionary<IReadOnlyPackage, MapClassification>();
readonly Dictionary<IReadOnlyPackage, MapClassification> mapLocations = new();
public bool LoadPreviewImages = true;
readonly Cache<string, MapPreview> previews;
readonly ModData modData;
readonly SheetBuilder sheetBuilder;
Thread previewLoaderThread;
bool previewLoaderThreadShutDown = true;
readonly object syncRoot = new object();
readonly Queue<MapPreview> generateMinimap = new Queue<MapPreview>();
readonly object syncRoot = new();
readonly Queue<MapPreview> generateMinimap = new();
public Dictionary<string, string> StringPool { get; } = new Dictionary<string, string>();
readonly List<MapDirectoryTracker> mapDirectoryTrackers = new List<MapDirectoryTracker>();
readonly List<MapDirectoryTracker> mapDirectoryTrackers = new();
/// <summary>
/// The most recenly modified or loaded map at runtime
/// The most recently modified or loaded map at runtime.
/// </summary>
public string LastModifiedMap { get; private set; } = null;
readonly Dictionary<string, string> mapUpdates = new Dictionary<string, string>();
readonly Dictionary<string, string> mapUpdates = new();
string lastLoadedLastModifiedMap;
/// <summary>
/// If LastModifiedMap was picked already, returns a null
/// If LastModifiedMap was picked already, returns a null.
/// </summary>
public string PickLastModifiedMap(MapVisibility visibility)
{
@@ -98,7 +99,7 @@ namespace OpenRA
IReadOnlyPackage package;
var optional = name.StartsWith("~", StringComparison.Ordinal);
if (optional)
name = name.Substring(1);
name = name[1..];
try
{
@@ -137,7 +138,7 @@ namespace OpenRA
IReadOnlyPackage mapPackage = null;
try
{
using (new Support.PerfTimer(map))
using (new PerfTimer(map))
{
mapPackage = package.OpenPackage(map, modData.ModFiles);
if (mapPackage != null)
@@ -182,7 +183,7 @@ namespace OpenRA
var name = kv.Key;
var optional = name.StartsWith("~", StringComparison.Ordinal);
if (optional)
name = name.Substring(1);
name = name[1..];
// Don't try to open the map directory in the support directory if it doesn't exist
var resolved = Platform.ResolvePath(name);
@@ -194,7 +195,7 @@ namespace OpenRA
}
}
public IEnumerable<(IReadWritePackage package, string map)> EnumerateMapDirPackagesAndNames(MapClassification classification = MapClassification.System)
public IEnumerable<(IReadWritePackage Package, string Map)> EnumerateMapDirPackagesAndNames(MapClassification classification = MapClassification.System)
{
var mapDirPackages = EnumerateMapDirPackages(classification);
@@ -213,12 +214,6 @@ namespace OpenRA
yield return mapPackage;
}
public IEnumerable<Map> EnumerateMapsWithoutCaching(MapClassification classification = MapClassification.System)
{
foreach (var mapPackage in EnumerateMapPackagesWithoutCaching(classification))
yield return new Map(modData, mapPackage);
}
public void QueryRemoteMapDetails(string repositoryUrl, IEnumerable<string> uids, Action<MapPreview> mapDetailsReceived = null, Action<MapPreview> mapQueryFailed = null)
{
var queryUids = uids.Distinct()

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -19,7 +19,6 @@ namespace OpenRA
public struct MapCoordsEnumerator : IEnumerator<MPos>
{
readonly MapCoordsRegion r;
MPos current;
public MapCoordsEnumerator(MapCoordsRegion region)
: this()
@@ -30,41 +29,38 @@ namespace OpenRA
public bool MoveNext()
{
var u = current.U + 1;
var v = current.V;
var u = Current.U + 1;
var v = Current.V;
// Check for column overflow
if (u > r.bottomRight.U)
if (u > r.BottomRight.U)
{
v += 1;
u = r.topLeft.U;
u = r.TopLeft.U;
// Check for row overflow
if (v > r.bottomRight.V)
if (v > r.BottomRight.V)
return false;
}
current = new MPos(u, v);
Current = new MPos(u, v);
return true;
}
public void Reset()
{
current = new MPos(r.topLeft.U - 1, r.topLeft.V);
Current = new MPos(r.TopLeft.U - 1, r.TopLeft.V);
}
public MPos Current => current;
public MPos Current { get; private set; }
object IEnumerator.Current => Current;
public void Dispose() { }
}
readonly MPos topLeft;
readonly MPos bottomRight;
public MapCoordsRegion(MPos mapTopLeft, MPos mapBottomRight)
{
topLeft = mapTopLeft;
bottomRight = mapBottomRight;
TopLeft = mapTopLeft;
BottomRight = mapBottomRight;
}
public override string ToString()
@@ -87,7 +83,7 @@ namespace OpenRA
return GetEnumerator();
}
public MPos TopLeft => topLeft;
public MPos BottomRight => bottomRight;
public MPos TopLeft { get; }
public MPos BottomRight { get; }
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -25,7 +25,7 @@ namespace OpenRA
readonly MapClassification classification;
enum MapAction { Add, Delete, Update }
readonly Dictionary<string, MapAction> mapActionQueue = new Dictionary<string, MapAction>();
readonly Dictionary<string, MapAction> mapActionQueue = new();
bool dirty = false;

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
@@ -29,7 +29,10 @@ namespace OpenRA
public readonly WVec[][] Polygons;
public readonly WRot Orientation;
public CellRamp(MapGridType type, WRot orientation, RampCornerHeight tl = RampCornerHeight.Low, RampCornerHeight tr = RampCornerHeight.Low, RampCornerHeight br = RampCornerHeight.Low, RampCornerHeight bl = RampCornerHeight.Low, RampSplit split = RampSplit.Flat)
public CellRamp(MapGridType type, WRot orientation,
RampCornerHeight tl = RampCornerHeight.Low, RampCornerHeight tr = RampCornerHeight.Low,
RampCornerHeight br = RampCornerHeight.Low, RampCornerHeight bl = RampCornerHeight.Low,
RampSplit split = RampSplit.Flat)
{
Orientation = orientation;
if (type == MapGridType.RectangularIsometric)
@@ -103,7 +106,7 @@ namespace OpenRA
public class MapGrid : IGlobalModData
{
public readonly MapGridType Type = MapGridType.Rectangular;
public readonly Size TileSize = new Size(24, 24);
public readonly Size TileSize = new(24, 24);
public readonly byte MaximumTerrainHeight = 0;
public readonly SubCell DefaultSubCell = (SubCell)byte.MaxValue;

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of

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