This changeset is motivated by a simple concept - get rid of the MiniYaml.Clone and MiniYamlNode.Clone methods to avoid deep copying yaml trees during merging. MiniYaml becoming immutable allows the merge function to reuse existing yaml trees rather than cloning them, saving on memory and improving merge performance. On initial loading the YAML for all maps is processed, so this provides a small reduction in initial loading time.
The rest of the changeset is dealing with the change in the exposed API surface. Some With* helper methods are introduced to allow creating new YAML from existing YAML. Areas of code that generated small amounts of YAML are able to transition directly to the immutable model without too much ceremony. Some use cases are far less ergonomic even with these helper methods and so a MiniYamlBuilder is introduced to retain mutable creation functionality. This allows those areas to continue to use the old mutable structures. The main users are the update rules and linting capabilities.
- Enforce SA1604 ElementDocumentationShouldHaveSummary.
- Enforce SA1629 DocumentationTextShouldEndWithAPeriod.
- Turn off some rules covered by IDExxxx rules.
- Remaining rules are treated as part of OpenRA style.
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.
Requires<T> means that trait of type T will be initialized first, and asserts that at least one exists. The new NotBefore<T> means that trait of type T will be initialized first, but allows no traits.
This allows traits to control initialization order for optional dependencies. They want to be initialized second so they can rely on the dependencies having been initialized. But if the dependencies are optional then to not throw if none are present.
We apply this to Locomotor which was previously using AddFrameEndTask to work around trait order initialization. This improves the user experience as the initialization is applied whilst the loading screen is still visible, rather than the game starting and creating jank by performing initialization on the first tick.
This helps improve the safety of code the uses reflection when methods may get renamed, and helps navigating code as the nameof will show up when searching for references to members.
Allows to pass the horizontal facing/yaw
and vertical angle/pitch of the carrier
projectile to warheads for further use.
Add ImpactPosition to WarheadArgs
InflictDamage doesn't pass the impact pos
directly, and the very point of WarheadArgs
is to avoid adding more and more arguments
to the warhead methods.
If a weapon was aiming at a target position rather
than an actor target, it would always check target types
of the terrain below, ignoring altitude (and therefore ignoring
"InvalidTargets: Air").