Commit Graph

1577 Commits

Author SHA1 Message Date
Gustas
ec01f63317 Add missing dispose calls 2025-03-29 13:58:24 +00:00
JovialFeline
2030c17a8b Add Lua documentation details 2025-02-08 14:02:27 +02:00
RoosterDragon
bf7f81b7fe Improve some String.Split calls. 2024-11-15 22:28:18 +02:00
RoosterDragon
332ab244a7 Fix CA1862 2024-11-15 22:28:18 +02:00
Paul Chote
67254e0b39 Rename Fluent *GetString methods to GetMessage. 2024-11-03 16:52:47 +02:00
RoosterDragon
bb17cfa179 Expose mod.yaml content to localisation.
Mod metadata, load screens and mod content is all now sourced from ftl files, allowing these items to be translated.

Translations are now initialized as part of ModData creation, as currently they are made available too late for the usage we need here.

The "modcontent" mod learns a new parameter for "Content.TranslationFile" - this allows a mod to provide the path of a translation file to the mod which it can load. This allows mods such as ra, cnc, d2k, ts to own the translations for their ModContent, yet still make them accessible to the modcontent mod.

CheckFluentReference learns to validate all these new fields to ensure translations have been set.
2024-10-07 12:38:40 +03:00
Paul Chote
d6285affec Remove FluentBundle.Arguments helper method. 2024-10-04 15:11:27 +03:00
Paul Chote
b29b685058 Rename Fluent-related code to be more precise. 2024-10-04 15:11:27 +03:00
Gustas
c050b211eb Rename Explodes to FireWarheadsOnDeath 2024-09-19 17:53:43 +02:00
RoosterDragon
87aa7c11c5 Provide buffer size in ShpRemasteredSprite.
As the expected size is quite small here, providing an explicit buffer size helps as otherwise default buffers for 1024 characters are allocated by the StreamReader which must be cleaned up by the GC afterwards. These smaller buffers still need cleanup but waste less memory.
2024-09-18 12:32:44 +03:00
JovialFeline
bdce0570bd Remove IRON offset from RA1 map imports 2024-08-29 21:26:35 +03:00
Matthias Mailänder
04d45e1f54 Revert "TS: EMP Cannon should only be able to fire via the support power. Fix…"
This reverts commit cd5eb89ebc.
2024-08-05 12:29:01 +03:00
RoosterDragon
b313f47660 Implement Stream.Read(Span<byte>) overloads.
The default Stream implementation of this method has to rent an array so it can call the overload that accepts an array, and then copy the output over. This is because the array overload is required and the span overload was only added more recently.

We can avoid the overhead of this by implementing the span overload and working with the destination span directly. Do so for all classes we have that derive from Stream, and redirect their array overload to the span overload for code reuse.
2024-08-04 10:40:43 +01:00
RoosterDragon
ab28e6a75a Improve Lua type documentation and bindings.
The ExtractEmmyLuaAPI utility command, invoked with `--emmy-lua-api`, produces a documentation file that is used by the [OpenRA Lua Language Extension](https://marketplace.visualstudio.com/items?itemName=openra.vscode-openra-lua) to provide documentation and type information is VSCode and VSCode compatible editors when editing the Lua scripts.

We improve the documentation and types produced by this utility in a few ways:
- Require descriptions to be provided for all items.
- Fix the type definitions of the base engine types (cpos, wpos, wangle, wdist, wvec, cvec) to match with the actual bindings on the C# side. Add some extra bindings for these types to increase their utility.
- Introduce ScriptEmmyTypeOverrideAttribute to allow the C# side of the bindings to provide a more specific type. The utility command now requires this to be used to avoid accidentally exporting poor type information.
- Fix a handful of scripts where the new type information revealed warnings.

The ability to ScriptEmmyTypeOverrideAttribute allows parameters and return types to provide a more specific type compared to the previous, weak, type definition. For example LuaValue mapped to `any`, LuaTable mapped to `table`, and LuaFunction mapped to `function`. These types are all non-specific. `any` can be anything, `table` is a table without known types for its keys or values, `function` is a function with an unknown signature.

Now, we can provide specific types. , e.g. instead of `table`, ReinforcementsGlobal.ReinforceWithTransport is able to specify `{ [1]: actor, [2]: actor[] }` - a table with keys 1 and 2, whose values are an actor, and a table of actors respectively. The callback functions in MapGlobal now have signatures, e.g. instead of `function` we have `fun(a: actor):boolean`. In UtilsGlobal, we also make use of generic types. These work in a similar fashion to generics in C#. These methods operate on collections, we can introduce a generic parameter named `T` for the type of the items in those collections. Now the return type and callback parameters can also use that generic type. This means the return type or callback functions operate on the same type as whatever type is in the collection you pass in. e.g. Utils.Do accepts a collection typed as `T[]` with a callback function invoked on each item typed as `fun(item: T)`. If you pass in actors, the callback operates on an actor. If you pass in strings, the callback operates on a string, etc.

Overall, these changes should result in an improved user experience for those editing OpenRA Lua scripts in a compatible IDE.
2024-08-03 19:12:51 +03:00
Matthias Mailänder
14ef6b5774 Fix formatting rule warnings. 2024-08-03 13:27:18 +03:00
RoosterDragon
88fb83bc57 Remove caching of CurrentAdjacentCells in Cargo
In 05ed9d9a73 we stopped caching the values with ToArray to resolve a desync. But even caching the enumerable can lead to a desync, so remove the caching entirely.

----

Let's explain how the code that cached values via ToArray could desync.

Usually, the cell given by `self.Location` matches with the cell given by `self.GetTargetablePositions()`. However if the unit is moving and close to the boundary between two cells, it is possible for the targetable position to be an adjacent cell instead.

Combined with the fact hovering over the unit will evaluate `CurrentAdjacentCells` only for the local player and not everybody, the following sequence becomes possible to induce a desync:
- As the APC is moving into the last cell before unloading, the local player hovers over it. `self.Location` is the last cell, but `self.GetTargetablePositions()` gives the *previous* cell (as the unit is close to the boundary between the cells)
- The local player then caches `CurrentAdjacentCells`. The cache key of `self.Location` is the final cell, but the values are calculated for `self.GetTargetablePositions()` of an *adjacent* cell.
- When the order to unload is resolved, the cache key of `CurrentAdjacentCells` is already `self.Location` and so `CurrentAdjacentCells` is *not* updated.
- The units unload into cells based on the *adjacent* cell.

Then, for other players in the game:
- The hover does nothing for these players.
- When the order is resolved, `CurrentAdjacentCells` is out of date and is re-evaluated.
- `self.Location` and `self.GetTargetablePositions()` are both the last cell, because the unit has finished moving.
- So the cache is updated with a key of `self.Location` and values from the *same* cell.
- The units unload into cells based on the *current* cell.

As the units unload into different cells, a desync occurs. Ultimately the cause here is that cache key is insufficient - `self.Location` can have the same value but the output can differ. The function isn't a pure function so memoizing the result via `ToArray()` isn't sound.

Reverting it to cache the enumerable, which is then lazily re-evaluated reduces the scope of possible desyncs but is NOT a full solve. The cached enumerable caches the result of `Actor.GetTargetablePositions()` which isn't a fully lazy sequence. A different result is returned depending on `EnabledTargetablePositions.Any()`. Therefore, if the traits were to enable/disable inbetween, then we can still end up with different results. Memoizing the enumerable isn't sound either!

Currently our only trait is `HitShape` which is enabled based on conditions. A condition that enables/disables it based on movement would be one way to trigger this scenario. Let's say you have a unit where you toggle between two hit shapes when it is moving and when it stops moving. That would allow you to replicate the above scenario once again.

Instead of trying to come up with a sound caching mechanism in the face of a series of complex inputs, we just give up on trying to cache this information at all.
2024-08-01 22:58:15 +02:00
Gustas
7b9a173f5a Trim empty space around edges of Shp(TD) frames.
Co-Authored-By: Paul Chote <pchote@users.noreply.github.com>
2024-07-30 13:27:16 +02:00
RoosterDragon
0649f3dc32 RCS0056 - roslynator_max_line_length = 160 2024-07-29 21:56:36 +02:00
RoosterDragon
9d5d2ab493 RCS0056 - roslynator_max_line_length = 180 2024-07-29 21:56:36 +02:00
RoosterDragon
2ed0656d1b Introduce MoveCooldownHelper to prevent lag spikes from failed pathfinding
Several activities that queue child Move activities can get into a bad scenario where the actor is pathfinding and then gets stuck because the destination is unreachable. When the Move activity then completes, then parent activity sees it has yet to reach the destination and tries to move again. However, the actor is still blocked in the same spot as before and thus the movment finishes immediately. This causes a performance death spiral where the actor attempts to pathfind every tick. The pathfinding attempt can also be very expensive if it must exhaustively check the whole map to determine no route is possible.

In order to prevent blocked actors from running into this scenario, we introduce MoveCooldownHelper. In its default setup it allows the parent activity to bail out if the actor was blocked during a pathfinding attempt. This means the activity will be dropped rather than trying to move endlessly. It also has an option to allow retrying if pathfinding was blocked, but applies a cooldown to avoid the performance penalty. For activities such as Enter, this means the actors will still try and enter their target if it is unreachable, but will only attempt once a second now rather than every tick.

MoveAdjacentTo will now cancel if it fails to reach the destination. This fixes MoveOntoAndTurn to skip the Turn if the move didn't reach the intended destination. Any other derived classes will similarly benefit from skipping follow-up actions.
2024-07-01 15:56:11 +03:00
RoosterDragon
cf0e73e75e Improve performance of copy-paste in map editor.
- EditorActorLayer now tracks previews on map with a SpatiallyPartitioned instead of a Dictionary. This allows the copy-paste logic to call an efficient PreviewsInCellRegion method, instead of asking for previews cell-by-cell.
- EditorActorPreview subscribes to the CellEntryChanged methods on the map. Previously the preview was refreshed regardless of which cell changed. Now the preview only regenerates if the preview's footprint has been affected.
2024-06-16 13:35:13 +03:00
Gustas
64b2bd4735 Update to HTTPS 2024-06-03 10:25:06 +02:00
Gustas
f337450348 Link no longer exists 2024-06-03 10:25:06 +02:00
Gustas
a20f5981e2 Fix TSVeinRenderer not having tooltip translated 2024-06-02 16:54:40 +02:00
Gustas
5fc36bd45f Make player stance colours universally respected 2024-05-04 16:31:35 +02:00
Gustas
34262fb33c Make PlayerRelationShipColor static 2024-05-04 16:31:35 +02:00
Matthias Mailänder
97c61e0068 Extract strings from resource renderer. 2024-04-30 11:27:46 +03:00
JovialFeline
6c9e33b76c Fix subcells imported from Gen1 maps 2024-04-30 11:12:04 +03:00
RoosterDragon
a4bb58007f Trim memory usage of IReadOnlyPackage implementations.
These implementations are often backed by a Dictionary, and tend to live a long time after being loaded. Ensure TrimExcess is called on the backing dictionaries to reduce the long term memory usage. In some cases, we can also preallocate the dictionary size for efficiency.
2024-04-06 10:47:19 +03:00
JovialFeline
8f985118cd Fix RA+CnC map import of BARB/FENC 2024-03-29 11:32:29 +02:00
RoosterDragon
00a23e6c11 Fetch actors directly in DropPodsPower.
Use direct dictionary lookups, rather than iterating the entire actors dictionary.
2024-03-09 21:33:42 +02:00
RoosterDragon
5f97e2de5a Make Color use uint for ARGB.
This is a more natural representation than int that allows removal of casts in many places that require uint. Additionally, we can change the internal representation from long to uint, making the Color struct smaller. Since arrays of colors are common, this can save on memory.
2024-03-09 21:10:02 +02:00
atlimit8
a054d2115d remove unused RenderSprite trait fields 2024-02-16 09:36:44 +02:00
Gustas
6026d088c8 Use HashSets instead of .Distinct
And don't cast to array / list where unnecessary
2024-01-30 22:06:58 -06:00
Thomas Christlieb
f979e6da0f Don't allow to unspy a spy by clicking on itself 2024-01-20 00:44:46 +01:00
Paul Chote
6c56ea4c55 Introduce Renderer.WorldBufferSnapshot(). 2023-12-15 13:37:05 +02:00
RoosterDragon
e6914f707a Introduce FirstOrDefault extensions method for Array.Find and List.Find.
This allows the LINQ spelling to be used, but benefits from the performance improvement of the specific methods for these classes that provide the same result.
2023-11-19 19:28:57 +02:00
RoosterDragon
acca837142 Fix RCS1246 2023-11-19 19:28:57 +02:00
RoosterDragon
330ca92045 Fix RCS1077 2023-11-19 19:28:57 +02:00
Paul Chote
3b67e425ed Add FilenamePattern support to sequences. 2023-11-16 15:06:10 +02:00
RoosterDragon
c8efc5fdd7 Fix CA1854 2023-11-16 09:29:17 +02:00
RoosterDragon
360f24f609 Fix IDE0055
This rule no longer appears to be buggy, so enforce it. Some of the automated fixes are adjusted in order to improve the result. #pragma directives have no option to control indentation, so remove them where possible.
2023-11-16 08:45:10 +02:00
Jakub Vesely
91802e6f10 ImportGen2Map: Fix imports of malformed maps.
Fixes #21126
2023-11-15 19:20:45 +02:00
RoosterDragon
3ae617c55b Fix CA2208 2023-11-15 19:13:17 +02:00
RoosterDragon
b97d1a4c6c Fix IDE0090 2023-11-15 19:13:17 +02:00
RoosterDragon
eb287d9b8d Fix RCS1089 2023-11-10 10:38:41 +02:00
RoosterDragon
4dd787be13 Fix RCS1061 2023-11-10 10:38:41 +02:00
RoosterDragon
5d91b678bb Use spans to improve performance in StreamExts.
Also avoid ReadBytes calls that allocate a buffer by either updating the stream position (if not interested in the bytes), by reusing an input buffer (if interested in the bytes), or using a stackalloc buffer to avoid the allocation (for small reads).
2023-11-10 10:25:39 +02:00
abcdefg30
d9f5588a1f Fix warnings about NREs in WithEmbeddedTurretSpriteBody 2023-10-30 23:37:52 +02:00
RoosterDragon
d2ecd0c777 Fix RCS1216 2023-10-30 23:31:33 +02:00