mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-15 11:40:52 +01:00
Compare commits
375 Commits
v0.8.21
...
reactjs-su
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
de8c2c14bb | ||
|
|
baebfff321 | ||
|
|
24191404aa | ||
|
|
990842f5c2 | ||
|
|
2c2bd3f330 | ||
|
|
1ae14c4bfa | ||
|
|
61a1701dc9 | ||
|
|
c6ea11346e | ||
|
|
ad7c871e28 | ||
|
|
c77b3f8022 | ||
|
|
b263f4a1df | ||
|
|
1a11d41bba | ||
|
|
14d0a77644 | ||
|
|
b75045ce1a | ||
|
|
1d8a8e15ef | ||
|
|
28a087c267 | ||
|
|
8dc849b6bb | ||
|
|
7e56f46f35 | ||
|
|
4453a23069 | ||
|
|
57be0bc845 | ||
|
|
430910ff36 | ||
|
|
4c95807e2d | ||
|
|
92fd04552d | ||
|
|
9c7e244821 | ||
|
|
41f64b5c3c | ||
|
|
4003003580 | ||
|
|
f49341b53c | ||
|
|
61d9d9a832 | ||
|
|
c0b7dd053f | ||
|
|
f642e10acc | ||
|
|
2fb64480db | ||
|
|
075b5ec203 | ||
|
|
21f2fe6b1b | ||
|
|
89080ef7c7 | ||
|
|
f5d36dc9ca | ||
|
|
ef87610b36 | ||
|
|
c89f1e4d31 | ||
|
|
c4805d89e0 | ||
|
|
659ffb028a | ||
|
|
a14c956ccc | ||
|
|
facb3914a4 | ||
|
|
aab8f7876b | ||
|
|
1f199ea71c | ||
|
|
00b557b77a | ||
|
|
eac536cffe | ||
|
|
bf75c6f247 | ||
|
|
1518c79291 | ||
|
|
aae2f72d1a | ||
|
|
273aa3d6ea | ||
|
|
756c4510eb | ||
|
|
cd50e89aec | ||
|
|
25b648b929 | ||
|
|
1dbbb08250 | ||
|
|
5432f7311e | ||
|
|
e662802b4c | ||
|
|
bae2c390bb | ||
|
|
7976926eaf | ||
|
|
4aee730753 | ||
|
|
e87c342aa2 | ||
|
|
d335d74d8f | ||
|
|
bc68b0e3ec | ||
|
|
b1eadbc58f | ||
|
|
2d3165a16f | ||
|
|
d99d25de37 | ||
|
|
be035ab002 | ||
|
|
12c8883eea | ||
|
|
758c7c1869 | ||
|
|
72ab1f5a1a | ||
|
|
6b9c1369c0 | ||
|
|
fd1f1dc64a | ||
|
|
e211368bc4 | ||
|
|
39307f916d | ||
|
|
7378cc50a1 | ||
|
|
867b9ad932 | ||
|
|
03064255f6 | ||
|
|
c9ccd0b873 | ||
|
|
650eceea7e | ||
|
|
452ad5a6e5 | ||
|
|
7c292c75d4 | ||
|
|
cab4113697 | ||
|
|
f1a5de79b5 | ||
|
|
191e80c175 | ||
|
|
241bce56c8 | ||
|
|
b105639b31 | ||
|
|
419e63ecd5 | ||
|
|
46e632bf9d | ||
|
|
a8871f4ff4 | ||
|
|
65f28c023d | ||
|
|
e506f6aba2 | ||
|
|
93ae74b5a7 | ||
|
|
7b25fa98ee | ||
|
|
e320b7abb4 | ||
|
|
6b9b56ca83 | ||
|
|
4d19790b3d | ||
|
|
2027863d4c | ||
|
|
4a4444a1ee | ||
|
|
f10316d384 | ||
|
|
778be40c86 | ||
|
|
2046323c71 | ||
|
|
71bb5cd58e | ||
|
|
71c6e437fa | ||
|
|
26e1474179 | ||
|
|
89a7459fda | ||
|
|
a61adf5631 | ||
|
|
97db1712f3 | ||
|
|
ea7012d114 | ||
|
|
d3eaea5697 | ||
|
|
4ca3fbe4bf | ||
|
|
81fea7595a | ||
|
|
2e0806cc1f | ||
|
|
5325650e92 | ||
|
|
31764d3c2d | ||
|
|
9df5152610 | ||
|
|
c6cd780ab5 | ||
|
|
023f845c48 | ||
|
|
5e977da9bc | ||
|
|
fa1de04df7 | ||
|
|
33251222cd | ||
|
|
70c1e8680f | ||
|
|
0d214769e6 | ||
|
|
495bbe891a | ||
|
|
5f68f569c3 | ||
|
|
52c883cb1f | ||
|
|
4b20bae597 | ||
|
|
64ff046ceb | ||
|
|
5f2566a97d | ||
|
|
c3735d1d5e | ||
|
|
749e547773 | ||
|
|
af8a010f43 | ||
|
|
a8a29e814f | ||
|
|
c3cb5406f6 | ||
|
|
73f26d93ca | ||
|
|
5e86a99060 | ||
|
|
ce9070b966 | ||
|
|
aa5bcefaf2 | ||
|
|
2df267fc28 | ||
|
|
306fcce337 | ||
|
|
3683b66ef8 | ||
|
|
08a52fb892 | ||
|
|
fd3c54b373 | ||
|
|
adee05b009 | ||
|
|
a66d40eb19 | ||
|
|
d065a96e01 | ||
|
|
ef7709aa78 | ||
|
|
305b330075 | ||
|
|
bec4297ce1 | ||
|
|
18b21b3d60 | ||
|
|
9b263417b9 | ||
|
|
13da0a7925 | ||
|
|
bb28db2412 | ||
|
|
489d150ae0 | ||
|
|
077dbaf933 | ||
|
|
26f83ac7a2 | ||
|
|
822009b429 | ||
|
|
e07a4e516c | ||
|
|
9ec38b5538 | ||
|
|
97da770978 | ||
|
|
3acbc8235d | ||
|
|
a32359d5d4 | ||
|
|
78fd39aee2 | ||
|
|
fca5c14c67 | ||
|
|
f60e3a14ef | ||
|
|
503a7032f9 | ||
|
|
918bbd3f01 | ||
|
|
a1441d5051 | ||
|
|
58d6189c40 | ||
|
|
58defed1d2 | ||
|
|
27a94384d0 | ||
|
|
4b8f5815db | ||
|
|
d830eef435 | ||
|
|
e7c4bf7341 | ||
|
|
162e646404 | ||
|
|
93049fcacf | ||
|
|
5b90db4beb | ||
|
|
7692ff736b | ||
|
|
f25ad8ece9 | ||
|
|
1aaf3b9250 | ||
|
|
11f6cff6df | ||
|
|
c2ea57c95a | ||
|
|
f61ae5da6b | ||
|
|
8ae9a5f2da | ||
|
|
3f7e89e006 | ||
|
|
cee4e4d62e | ||
|
|
14a3783760 | ||
|
|
b4607f7b1f | ||
|
|
5a28c16cae | ||
|
|
9e8bf861ea | ||
|
|
b540f04a7a | ||
|
|
bcaa7001ad | ||
|
|
3f0fba7b4e | ||
|
|
d7d7a53045 | ||
|
|
40daba9adf | ||
|
|
5665f8eb1c | ||
|
|
8f0d562f3e | ||
|
|
f3950e940e | ||
|
|
3fdca65cc9 | ||
|
|
4cfb9210d0 | ||
|
|
23d0b8a555 | ||
|
|
452b03d5a6 | ||
|
|
c8f2dab381 | ||
|
|
7409df07f8 | ||
|
|
973406b91d | ||
|
|
2e646fe2b6 | ||
|
|
6b902d22d4 | ||
|
|
83e6d52e58 | ||
|
|
025fdcd0b3 | ||
|
|
fe3ace92bd | ||
|
|
317070f167 | ||
|
|
3524363ad4 | ||
|
|
90287dbb09 | ||
|
|
9a2f35f2d3 | ||
|
|
3f10dbe770 | ||
|
|
8fcba93ada | ||
|
|
35366b5bc1 | ||
|
|
d8bf31ecc4 | ||
|
|
de4d255841 | ||
|
|
ec768c563f | ||
|
|
2114d2bc67 | ||
|
|
43478d0e45 | ||
|
|
561699b26e | ||
|
|
460923e54d | ||
|
|
c299104f0c | ||
|
|
224bebeeb5 | ||
|
|
52c8e8ecdf | ||
|
|
ac636b2703 | ||
|
|
a892f9ac99 | ||
|
|
2ebee8f40c | ||
|
|
43741dc5fc | ||
|
|
da9467b678 | ||
|
|
8f24a7b4fc | ||
|
|
ff48959e97 | ||
|
|
09e648d086 | ||
|
|
1d1db2e109 | ||
|
|
6a902286cd | ||
|
|
933724e4ee | ||
|
|
53034e6f05 | ||
|
|
681f77a796 | ||
|
|
6a31c5649c | ||
|
|
7bd90578dc | ||
|
|
2a7f1cbf48 | ||
|
|
c076be95a6 | ||
|
|
7b732dd68a | ||
|
|
3e34b1414e | ||
|
|
8456cd90d1 | ||
|
|
c4e63cfdc7 | ||
|
|
d716e1ff62 | ||
|
|
8e9acc9191 | ||
|
|
773a068b7d | ||
|
|
b37bfff155 | ||
|
|
a14cce222b | ||
|
|
c077e09436 | ||
|
|
213955566b | ||
|
|
b98cd3e6e1 | ||
|
|
987c8e8229 | ||
|
|
fcbb97ec55 | ||
|
|
c1ac7aebdb | ||
|
|
e4b0d1a03c | ||
|
|
f13f9dc5cd | ||
|
|
1f6170c000 | ||
|
|
53c7ec8ddc | ||
|
|
e438e53d36 | ||
|
|
792608f0d0 | ||
|
|
7b5678fd0f | ||
|
|
88c328a636 | ||
|
|
f9573530a8 | ||
|
|
c1df7dcca7 | ||
|
|
f141a0033e | ||
|
|
227d047584 | ||
|
|
73b73cd9da | ||
|
|
66be082bdb | ||
|
|
ac43cf0de1 | ||
|
|
fb41601d9f | ||
|
|
f35dda3fb3 | ||
|
|
7ee14f6f4f | ||
|
|
97920b42ee | ||
|
|
8ace0ec254 | ||
|
|
a3606f1098 | ||
|
|
616d379902 | ||
|
|
a27f475715 | ||
|
|
6ee76e8f46 | ||
|
|
891c30c9be | ||
|
|
9757a4c3b6 | ||
|
|
5be2f610cd | ||
|
|
35324e0853 | ||
|
|
ac753cdb93 | ||
|
|
3edd39f0eb | ||
|
|
8f790c28be | ||
|
|
c253afaf8e | ||
|
|
a6ac1dced0 | ||
|
|
d1e0f2cd94 | ||
|
|
af861d289a | ||
|
|
753f3f8c0f | ||
|
|
5c2a5741ee | ||
|
|
26941a2013 | ||
|
|
fad4c20da2 | ||
|
|
2b79ef301d | ||
|
|
014491e674 | ||
|
|
2e70cd4f2e | ||
|
|
689e1baa12 | ||
|
|
c34e84378a | ||
|
|
9a44becc73 | ||
|
|
d324d9fcf3 | ||
|
|
74cd48401c | ||
|
|
43081c57e7 | ||
|
|
b80a51d03f | ||
|
|
e90d5e4977 | ||
|
|
979034906a | ||
|
|
9e4fd2905b | ||
|
|
914c269411 | ||
|
|
2cacc4cd49 | ||
|
|
3024094584 | ||
|
|
4c66451324 | ||
|
|
7e7d808c90 | ||
|
|
0538e89948 | ||
|
|
6376f7c35d | ||
|
|
37721f2327 | ||
|
|
b0d2404644 | ||
|
|
5f76cb4819 | ||
|
|
427a54fc67 | ||
|
|
1cd1fb905d | ||
|
|
33333f87d2 | ||
|
|
4e5b8ec1e2 | ||
|
|
007feb76b7 | ||
|
|
d34dcb81fb | ||
|
|
8abb366903 | ||
|
|
3e7ba7ca28 | ||
|
|
14d52a9da9 | ||
|
|
847f8d1fee | ||
|
|
0c8d7adf37 | ||
|
|
d68d803709 | ||
|
|
13ef514d3e | ||
|
|
e20cd248a0 | ||
|
|
b8a3bda31d | ||
|
|
001493d984 | ||
|
|
013a3e3e8c | ||
|
|
4c2d984835 | ||
|
|
21bb0f15e0 | ||
|
|
8d5162ef8d | ||
|
|
257913ac0e | ||
|
|
c90dfccbf4 | ||
|
|
9c7dc8876f | ||
|
|
fc8cbdf01f | ||
|
|
5af4bfa912 | ||
|
|
0c5a47ff9d | ||
|
|
b4b4a3864f | ||
|
|
dca8561881 | ||
|
|
ee58b5299d | ||
|
|
7868b12279 | ||
|
|
42e91e8c4d | ||
|
|
28c9326305 | ||
|
|
40b8772980 | ||
|
|
b6a548629a | ||
|
|
291a37924d | ||
|
|
0b5eccd60a | ||
|
|
866a324922 | ||
|
|
baf48a8dc1 | ||
|
|
a85b2dd43c | ||
|
|
43059b3985 | ||
|
|
4d6183d6af | ||
|
|
79f87f03ce | ||
|
|
01ede29fc4 | ||
|
|
fb54d0df1c | ||
|
|
5b65495fbc | ||
|
|
cec3a8c1c2 | ||
|
|
8bd0b459b9 | ||
|
|
7da50516f9 | ||
|
|
6cbb2135b8 | ||
|
|
66dbc05022 | ||
|
|
18cc385c70 | ||
|
|
384f672eec | ||
|
|
f49a29cfb3 | ||
|
|
e8b70877cf | ||
|
|
9b084ea6a9 | ||
|
|
51f2fc4259 | ||
|
|
bb27482e9f |
19
.github/CODEOWNERS
vendored
19
.github/CODEOWNERS
vendored
@@ -1,7 +1,20 @@
|
||||
# Last match in file takes precedence.
|
||||
|
||||
# Ping for all PRs
|
||||
* @Acruid @PJB3005 @Silvertorch5
|
||||
|
||||
/Robust.*/Audio/Midi/ @Zumorica
|
||||
|
||||
/Robust.Client.NameGenerator @PaulRitter
|
||||
/Robust.Client.Injectors @PaulRitter
|
||||
/Robust.Generators @PaulRitter
|
||||
/Robust.Analyzers @PaulRitter
|
||||
/Robust.*/GameStates @PaulRitter
|
||||
/Robust.Shared/Analyzers @PaulRitter
|
||||
/Robust.*/Serialization @PaulRitter @DrSmugleaf
|
||||
/Robust.*/Prototypes @PaulRitter
|
||||
/Robust.Shared/GameObjects/ComponentDependencies @PaulRitter
|
||||
/Robust.*/Containers @PaulRitter
|
||||
|
||||
# Be they Fluent translations or Freemarker templates, I know them both!
|
||||
*.ftl @RemieRichards
|
||||
|
||||
# Ping for all PRs
|
||||
* @Acruid @PJB3005 @Silvertorch5
|
||||
33
.github/workflows/benchmarks.yml
vendored
Normal file
33
.github/workflows/benchmarks.yml
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
name: Benchmarks
|
||||
#on:
|
||||
# push
|
||||
#schedule:
|
||||
# - cron: '0 5 * * *'
|
||||
#push:
|
||||
# tags:
|
||||
# - 'v*'
|
||||
|
||||
env:
|
||||
ROBUST_BENCHMARKS_ENABLE_SQL: 1
|
||||
ROBUST_BENCHMARKS_SQL_ADDRESS: ${{ secrets.BENCHMARKS_WRITE_ADDRESS }}
|
||||
ROBUST_BENCHMARKS_SQL_PORT: ${{ secrets.BENCHMARKS_WRITE_PORT }}
|
||||
ROBUST_BENCHMARKS_SQL_USER: ${{ secrets.BENCHMARKS_WRITE_USER }}
|
||||
ROBUST_BENCHMARKS_SQL_PASSWORD: ${{ secrets.BENCHMARKS_WRITE_PASSWORD }}
|
||||
ROBUST_BENCHMARKS_SQL_DATABASE: benchmarks
|
||||
|
||||
jobs:
|
||||
benchmark:
|
||||
name: Run Benchmarks
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup .NET Core
|
||||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: 6.0.x
|
||||
- name: Install dependencies
|
||||
run: dotnet restore
|
||||
- name: Run benchmark
|
||||
run: cd Robust.Benchmarks && sudo dotnet run --filter '*' --configuration Release
|
||||
34
.github/workflows/build-docfx.yml
vendored
Normal file
34
.github/workflows/build-docfx.yml
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
name: Build & Publish DocFX
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 0 * * 0"
|
||||
jobs:
|
||||
docfx:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Setup .NET Core
|
||||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: 6.0.x
|
||||
|
||||
- name: Install dependencies
|
||||
run: dotnet restore
|
||||
|
||||
- name: Build Project
|
||||
run: dotnet build --no-restore /p:WarningsAsErrors=nullable
|
||||
|
||||
- name: Build DocFX
|
||||
uses: nikeee/docfx-action@v1.0.0
|
||||
with:
|
||||
args: Robust.Docfx/docfx.json
|
||||
|
||||
- name: Publish Docfx Documentation on GitHub Pages
|
||||
uses: maxheld83/ghpages@master
|
||||
env:
|
||||
BUILD_DIR: Robust.Docfx/_robust-site
|
||||
GH_PAT: ${{ secrets.GH_PAT }}
|
||||
4
.github/workflows/build-test.yml
vendored
4
.github/workflows/build-test.yml
vendored
@@ -22,10 +22,12 @@ jobs:
|
||||
- name: Setup .NET Core
|
||||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: 6.0.100
|
||||
dotnet-version: 6.0.x
|
||||
- name: Install dependencies
|
||||
run: dotnet restore
|
||||
- name: Build
|
||||
run: dotnet build --no-restore /p:WarningsAsErrors=nullable
|
||||
- name: Test Engine
|
||||
run: dotnet test --no-build Robust.UnitTesting/Robust.UnitTesting.csproj -v n
|
||||
|
||||
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -76,3 +76,5 @@ MSBuild/Robust.Custom.targets
|
||||
|
||||
|
||||
release/
|
||||
Robust.Docfx/*-site
|
||||
Robust.Docfx/api
|
||||
|
||||
Submodule Lidgren.Network/Lidgren.Network updated: 1dd5c1f333...b723fc532e
@@ -1,4 +1,4 @@
|
||||
<Project>
|
||||
<!-- This file automatically reset by Tools/version.py -->
|
||||
<PropertyGroup><Version>0.8.21</Version></PropertyGroup>
|
||||
<PropertyGroup><Version>0.8.86</Version></PropertyGroup>
|
||||
</Project>
|
||||
|
||||
Submodule ManagedHttpListener updated: f2aa590fec...ae0539e66f
BIN
Resources/Textures/noTile.png
Normal file
BIN
Resources/Textures/noTile.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 535 B |
@@ -1,10 +1,14 @@
|
||||
using Microsoft.CodeAnalysis;
|
||||
|
||||
namespace Robust.Generators
|
||||
namespace Robust.Analyzers;
|
||||
|
||||
public static class Diagnostics
|
||||
{
|
||||
public static class Diagnostics
|
||||
{
|
||||
public static SuppressionDescriptor MeansImplicitAssignment =>
|
||||
new SuppressionDescriptor("RADC1000", "CS0649", "Marked as implicitly assigned.");
|
||||
}
|
||||
public const string IdExplicitInterface = "RA0000";
|
||||
public const string IdSerializable = "RA0001";
|
||||
public const string IdFriend = "RA0002";
|
||||
public const string IdExplicitVirtual = "RA0003";
|
||||
|
||||
public static SuppressionDescriptor MeansImplicitAssignment =>
|
||||
new SuppressionDescriptor("RADC1000", "CS0649", "Marked as implicitly assigned.");
|
||||
}
|
||||
|
||||
@@ -24,14 +24,14 @@ namespace Robust.Analyzers
|
||||
SyntaxKind.OverrideKeyword
|
||||
};
|
||||
|
||||
public const string DiagnosticId = "RA0000";
|
||||
|
||||
private const string Title = "No explicit interface specified";
|
||||
private const string MessageFormat = "No explicit interface specified";
|
||||
private const string Description = "Make sure to specify the interface in your method-declaration.";
|
||||
private const string Category = "Usage";
|
||||
|
||||
[SuppressMessage("ReSharper", "RS2008")] private static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor(DiagnosticId, Title, MessageFormat, Category, DiagnosticSeverity.Warning, isEnabledByDefault: true, description: Description);
|
||||
[SuppressMessage("ReSharper", "RS2008")] private static readonly DiagnosticDescriptor Rule = new(
|
||||
Diagnostics.IdExplicitInterface,
|
||||
"No explicit interface specified",
|
||||
"No explicit interface specified",
|
||||
"Usage",
|
||||
DiagnosticSeverity.Warning,
|
||||
isEnabledByDefault: true,
|
||||
description: "Make sure to specify the interface in your method-declaration.");
|
||||
|
||||
private const string RequiresExplicitImplementationAttributeMetadataName =
|
||||
"Robust.Shared.Analyzers.RequiresExplicitImplementationAttribute";
|
||||
|
||||
176
Robust.Analyzers/ExplicitVirtualAnalyzer.cs
Normal file
176
Robust.Analyzers/ExplicitVirtualAnalyzer.cs
Normal file
@@ -0,0 +1,176 @@
|
||||
using System.Collections.Immutable;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using Microsoft.CodeAnalysis.Diagnostics;
|
||||
|
||||
namespace Robust.Analyzers;
|
||||
|
||||
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
||||
public sealed class ExplicitVirtualAnalyzer : DiagnosticAnalyzer
|
||||
{
|
||||
internal const string Attribute = "Robust.Shared.Analyzers.VirtualAttribute";
|
||||
|
||||
[SuppressMessage("ReSharper", "RS2008")]
|
||||
private static readonly DiagnosticDescriptor Rule = new(
|
||||
Diagnostics.IdExplicitVirtual,
|
||||
"Class must be explicitly marked as [Virtual], abstract, static or sealed",
|
||||
"Class must be explicitly marked as [Virtual], abstract, static or sealed",
|
||||
"Usage",
|
||||
DiagnosticSeverity.Warning,
|
||||
isEnabledByDefault: true,
|
||||
description: "Class must be explicitly marked as [Virtual], abstract, static or sealed.");
|
||||
|
||||
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(Rule);
|
||||
|
||||
public override void Initialize(AnalysisContext context)
|
||||
{
|
||||
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
|
||||
context.EnableConcurrentExecution();
|
||||
context.RegisterSyntaxNodeAction(AnalyzeNode, SyntaxKind.ClassDeclaration);
|
||||
}
|
||||
|
||||
private static bool HasAttribute(INamedTypeSymbol namedTypeSymbol, INamedTypeSymbol attrSymbol)
|
||||
{
|
||||
return namedTypeSymbol.GetAttributes()
|
||||
.Any(a => SymbolEqualityComparer.Default.Equals(a.AttributeClass, attrSymbol));
|
||||
}
|
||||
|
||||
private static void AnalyzeNode(SyntaxNodeAnalysisContext context)
|
||||
{
|
||||
var attrSymbol = context.Compilation.GetTypeByMetadataName(Attribute);
|
||||
var classDecl = (ClassDeclarationSyntax)context.Node;
|
||||
var classSymbol = context.SemanticModel.GetDeclaredSymbol(classDecl);
|
||||
if (classSymbol == null)
|
||||
return;
|
||||
|
||||
if (classSymbol.IsSealed || classSymbol.IsAbstract || classSymbol.IsStatic)
|
||||
return;
|
||||
|
||||
if (HasAttribute(classSymbol, attrSymbol))
|
||||
return;
|
||||
|
||||
var diag = Diagnostic.Create(Rule, classDecl.Keyword.GetLocation());
|
||||
context.ReportDiagnostic(diag);
|
||||
}
|
||||
}
|
||||
|
||||
// Doesn't work as I'd hoped: Roslyn doesn't provide an API for global usings and I can't get batch changes to work.
|
||||
/*
|
||||
[ExportCodeFixProvider(LanguageNames.CSharp)]
|
||||
public sealed class ExplicitVirtualCodeFixProvider : CodeFixProvider
|
||||
{
|
||||
private const string TitleSealed = "Annotate class as sealed.";
|
||||
private const string TitleVirtual = "Annotate class as [Virtual].";
|
||||
private const string TitleAbstract = "Annotate class as abstract.";
|
||||
private const string TitleStatic = "Annotate class as static.";
|
||||
|
||||
public override async Task RegisterCodeFixesAsync(CodeFixContext context)
|
||||
{
|
||||
var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken);
|
||||
|
||||
foreach (var diagnostic in context.Diagnostics)
|
||||
{
|
||||
var span = diagnostic.Location.SourceSpan;
|
||||
var classDecl = root.FindToken(span.Start).Parent.AncestorsAndSelf().OfType<ClassDeclarationSyntax>()
|
||||
.First();
|
||||
|
||||
context.RegisterCodeFix(
|
||||
CodeAction.Create(
|
||||
TitleVirtual,
|
||||
c => FixVirtualAsync(context.Document, classDecl, c),
|
||||
TitleVirtual),
|
||||
diagnostic);
|
||||
|
||||
context.RegisterCodeFix(
|
||||
CodeAction.Create(
|
||||
TitleStatic,
|
||||
c => FixStaticAsync(context.Document, classDecl, c),
|
||||
TitleStatic),
|
||||
diagnostic);
|
||||
|
||||
context.RegisterCodeFix(
|
||||
CodeAction.Create(
|
||||
TitleSealed,
|
||||
c => FixSealedAsync(context.Document, classDecl, c),
|
||||
TitleSealed),
|
||||
diagnostic);
|
||||
|
||||
context.RegisterCodeFix(
|
||||
CodeAction.Create(
|
||||
TitleAbstract,
|
||||
c => FixAbstractAsync(context.Document, classDecl, c),
|
||||
TitleAbstract),
|
||||
diagnostic);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<Document> FixVirtualAsync(
|
||||
Document document,
|
||||
ClassDeclarationSyntax classDecl,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var ns = "Robust.Shared.Analyzers";
|
||||
var attrib = SyntaxFactory.Attribute(SyntaxFactory.ParseName("Virtual"));
|
||||
|
||||
var newClassDecl = classDecl.AddAttributeLists(
|
||||
SyntaxFactory.AttributeList(SyntaxFactory.SeparatedList(new[] { attrib })));
|
||||
|
||||
var root = (CompilationUnitSyntax)await document.GetSyntaxRootAsync(cancellationToken);
|
||||
root = root.ReplaceNode(classDecl, newClassDecl);
|
||||
|
||||
var options = await document.GetOptionsAsync(cancellationToken);
|
||||
|
||||
if (root.Usings.All(u => u.Name.ToString() != ns))
|
||||
{
|
||||
root = root.AddUsings(SyntaxFactory.UsingDirective(SyntaxFactory.ParseName(ns)));
|
||||
}
|
||||
|
||||
return document.WithSyntaxRoot(root);
|
||||
}
|
||||
|
||||
private async Task<Document> FixStaticAsync(
|
||||
Document document,
|
||||
ClassDeclarationSyntax classDecl,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var newClassDecl = classDecl.AddModifiers(SyntaxFactory.Token(SyntaxKind.StaticKeyword));
|
||||
|
||||
var root = (CompilationUnitSyntax)await document.GetSyntaxRootAsync(cancellationToken);
|
||||
root = root.ReplaceNode(classDecl, newClassDecl);
|
||||
|
||||
return document.WithSyntaxRoot(root);
|
||||
}
|
||||
|
||||
private async Task<Document> FixAbstractAsync(
|
||||
Document document,
|
||||
ClassDeclarationSyntax classDecl,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var newClassDecl = classDecl.AddModifiers(SyntaxFactory.Token(SyntaxKind.AbstractKeyword));
|
||||
|
||||
var root = (CompilationUnitSyntax)await document.GetSyntaxRootAsync(cancellationToken);
|
||||
root = root.ReplaceNode(classDecl, newClassDecl);
|
||||
|
||||
return document.WithSyntaxRoot(root);
|
||||
}
|
||||
|
||||
private async Task<Document> FixSealedAsync(
|
||||
Document document,
|
||||
ClassDeclarationSyntax classDecl,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var newClassDecl = classDecl.AddModifiers(SyntaxFactory.Token(SyntaxKind.SealedKeyword));
|
||||
|
||||
var root = (CompilationUnitSyntax)await document.GetSyntaxRootAsync(cancellationToken);
|
||||
root = root.ReplaceNode(classDecl, newClassDecl);
|
||||
|
||||
return document.WithSyntaxRoot(root);
|
||||
}
|
||||
|
||||
public override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer;
|
||||
public override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(Diagnostics.IdExplicitVirtual);
|
||||
}
|
||||
*/
|
||||
@@ -14,15 +14,15 @@ namespace Robust.Analyzers
|
||||
{
|
||||
const string FriendAttribute = "Robust.Shared.Analyzers.FriendAttribute";
|
||||
|
||||
public const string DiagnosticId = "RA0002";
|
||||
|
||||
private const string Title = "Tried to access friend-only member";
|
||||
private const string MessageFormat = "Tried to access member \"{0}\" in class \"{1}\" which can only be accessed by friend classes";
|
||||
private const string Description = "Make sure to specify the accessing class in the friends attribute.";
|
||||
private const string Category = "Usage";
|
||||
|
||||
[SuppressMessage("ReSharper", "RS2008")]
|
||||
private static readonly DiagnosticDescriptor Rule = new (DiagnosticId, Title, MessageFormat, Category, DiagnosticSeverity.Error, true, Description);
|
||||
private static readonly DiagnosticDescriptor Rule = new (
|
||||
Diagnostics.IdFriend,
|
||||
"Tried to access friend-only member",
|
||||
"Tried to access member \"{0}\" in class \"{1}\" which can only be accessed by friend classes",
|
||||
"Usage",
|
||||
DiagnosticSeverity.Error,
|
||||
true,
|
||||
"Make sure to specify the accessing class in the friends attribute.");
|
||||
|
||||
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(Rule);
|
||||
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.Diagnostics;
|
||||
using Robust.Generators;
|
||||
|
||||
namespace Robust.Analyzers
|
||||
{
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<LangVersion>9</LangVersion>
|
||||
<LangVersion>10</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.8.0" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.2" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.Common" Version="3.8.0" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.0.1" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.3" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.Common" Version="4.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -17,19 +17,21 @@ namespace Robust.Analyzers
|
||||
public class SerializableAnalyzer : DiagnosticAnalyzer
|
||||
{
|
||||
// Metadata of the analyzer
|
||||
public const string DiagnosticId = "RA0001";
|
||||
|
||||
// You could use LocalizedString but it's a little more complicated for this sample
|
||||
private const string Title = "Class not marked as (Net)Serializable";
|
||||
private const string MessageFormat = "Class not marked as (Net)Serializable";
|
||||
private const string Description = "The class should be marked as (Net)Serializable.";
|
||||
private const string Category = "Usage";
|
||||
|
||||
private const string RequiresSerializableAttributeMetadataName = "Robust.Shared.Analyzers.RequiresSerializableAttribute";
|
||||
private const string SerializableAttributeMetadataName = "System.SerializableAttribute";
|
||||
private const string NetSerializableAttributeMetadataName = "Robust.Shared.Serialization.NetSerializableAttribute";
|
||||
|
||||
[SuppressMessage("ReSharper", "RS2008")] private static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor(DiagnosticId, Title, MessageFormat, Category, DiagnosticSeverity.Warning, isEnabledByDefault: true, description: Description);
|
||||
[SuppressMessage("ReSharper", "RS2008")] private static readonly DiagnosticDescriptor Rule = new(
|
||||
Diagnostics.IdSerializable,
|
||||
"Class not marked as (Net)Serializable",
|
||||
"Class not marked as (Net)Serializable",
|
||||
"Usage",
|
||||
DiagnosticSeverity.Warning,
|
||||
isEnabledByDefault: true,
|
||||
description: "The class should be marked as (Net)Serializable.");
|
||||
|
||||
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(Rule);
|
||||
|
||||
@@ -139,7 +141,8 @@ namespace Robust.Analyzers
|
||||
return document.WithSyntaxRoot(root);
|
||||
}
|
||||
|
||||
public sealed override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(SerializableAnalyzer.DiagnosticId);
|
||||
public sealed override ImmutableArray<string> FixableDiagnosticIds
|
||||
=> ImmutableArray.Create(Diagnostics.IdSerializable);
|
||||
|
||||
public override FixAllProvider GetFixAllProvider()
|
||||
{
|
||||
|
||||
53
Robust.Benchmarks/Configs/DefaultSQLConfig.cs
Normal file
53
Robust.Benchmarks/Configs/DefaultSQLConfig.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using BenchmarkDotNet.Analysers;
|
||||
using BenchmarkDotNet.Columns;
|
||||
using BenchmarkDotNet.Configs;
|
||||
using BenchmarkDotNet.Diagnosers;
|
||||
using BenchmarkDotNet.Exporters;
|
||||
using BenchmarkDotNet.Filters;
|
||||
using BenchmarkDotNet.Jobs;
|
||||
using BenchmarkDotNet.Loggers;
|
||||
using BenchmarkDotNet.Order;
|
||||
using BenchmarkDotNet.Reports;
|
||||
using BenchmarkDotNet.Validators;
|
||||
using Robust.Benchmarks.Exporters;
|
||||
|
||||
namespace Robust.Benchmarks.Configs;
|
||||
|
||||
public sealed class DefaultSQLConfig : IConfig
|
||||
{
|
||||
public static readonly IConfig Instance = new DefaultSQLConfig();
|
||||
|
||||
private DefaultSQLConfig(){}
|
||||
|
||||
public IEnumerable<IExporter> GetExporters()
|
||||
{
|
||||
yield return SQLExporter.Default;
|
||||
}
|
||||
|
||||
public IEnumerable<IColumnProvider> GetColumnProviders() => DefaultConfig.Instance.GetColumnProviders();
|
||||
|
||||
public IEnumerable<ILogger> GetLoggers() => DefaultConfig.Instance.GetLoggers();
|
||||
|
||||
public IEnumerable<IDiagnoser> GetDiagnosers() => DefaultConfig.Instance.GetDiagnosers();
|
||||
|
||||
public IEnumerable<IAnalyser> GetAnalysers() => DefaultConfig.Instance.GetAnalysers();
|
||||
|
||||
public IEnumerable<Job> GetJobs() => DefaultConfig.Instance.GetJobs();
|
||||
|
||||
public IEnumerable<IValidator> GetValidators() => DefaultConfig.Instance.GetValidators();
|
||||
|
||||
public IEnumerable<HardwareCounter> GetHardwareCounters() => DefaultConfig.Instance.GetHardwareCounters();
|
||||
|
||||
public IEnumerable<IFilter> GetFilters() => DefaultConfig.Instance.GetFilters();
|
||||
|
||||
public IEnumerable<BenchmarkLogicalGroupRule> GetLogicalGroupRules() => DefaultConfig.Instance.GetLogicalGroupRules();
|
||||
|
||||
public IOrderer Orderer => DefaultConfig.Instance.Orderer!;
|
||||
public SummaryStyle SummaryStyle => DefaultConfig.Instance.SummaryStyle;
|
||||
public ConfigUnionRule UnionRule => DefaultConfig.Instance.UnionRule;
|
||||
public string ArtifactsPath => DefaultConfig.Instance.ArtifactsPath;
|
||||
public CultureInfo CultureInfo => DefaultConfig.Instance.CultureInfo!;
|
||||
public ConfigOptions Options => DefaultConfig.Instance.Options;
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Analyzers;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.UnitTesting.Server;
|
||||
|
||||
namespace Robust.Benchmarks.EntityManager;
|
||||
|
||||
[Virtual]
|
||||
public class AddRemoveComponentBenchmark
|
||||
{
|
||||
private ISimulation _simulation = default!;
|
||||
private IEntityManager _entityManager = default!;
|
||||
|
||||
[UsedImplicitly]
|
||||
[Params(1, 10, 100, 1000)]
|
||||
public int N;
|
||||
|
||||
[GlobalSetup]
|
||||
public void GlobalSetup()
|
||||
{
|
||||
_simulation = RobustServerSimulation
|
||||
.NewSimulation()
|
||||
.RegisterComponents(f => f.RegisterClass<A>())
|
||||
.InitializeInstance();
|
||||
|
||||
_entityManager = _simulation.Resolve<IEntityManager>();
|
||||
|
||||
var coords = new MapCoordinates(0, 0, new MapId(1));
|
||||
_simulation.AddMap(coords.MapId);
|
||||
|
||||
for (var i = 0; i < N; i++)
|
||||
{
|
||||
_entityManager.SpawnEntity(null, coords);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void AddRemoveComponent()
|
||||
{
|
||||
for (var i = 2; i <= N+1; i++)
|
||||
{
|
||||
var uid = new EntityUid(i);
|
||||
_entityManager.AddComponent<A>(uid);
|
||||
_entityManager.RemoveComponent<A>(uid);
|
||||
}
|
||||
}
|
||||
|
||||
[ComponentProtoName("A")]
|
||||
public sealed class A : Component
|
||||
{
|
||||
}
|
||||
}
|
||||
61
Robust.Benchmarks/EntityManager/GetComponentBenchmark.cs
Normal file
61
Robust.Benchmarks/EntityManager/GetComponentBenchmark.cs
Normal file
@@ -0,0 +1,61 @@
|
||||
using System;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Analyzers;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.UnitTesting.Server;
|
||||
|
||||
namespace Robust.Benchmarks.EntityManager;
|
||||
|
||||
[Virtual]
|
||||
public class GetComponentBenchmark
|
||||
{
|
||||
private ISimulation _simulation = default!;
|
||||
private IEntityManager _entityManager = default!;
|
||||
|
||||
[UsedImplicitly]
|
||||
[Params(1, 10, 100, 1000)]
|
||||
public int N;
|
||||
|
||||
public A[] Comps = default!;
|
||||
|
||||
[GlobalSetup]
|
||||
public void GlobalSetup()
|
||||
{
|
||||
_simulation = RobustServerSimulation
|
||||
.NewSimulation()
|
||||
.RegisterComponents(f => f.RegisterClass<A>())
|
||||
.InitializeInstance();
|
||||
|
||||
_entityManager = _simulation.Resolve<IEntityManager>();
|
||||
|
||||
Comps = new A[N+2];
|
||||
|
||||
var coords = new MapCoordinates(0, 0, new MapId(1));
|
||||
_simulation.AddMap(coords.MapId);
|
||||
|
||||
for (var i = 0; i < N; i++)
|
||||
{
|
||||
var uid = _entityManager.SpawnEntity(null, coords);
|
||||
_entityManager.AddComponent<A>(uid);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public A[] GetComponent()
|
||||
{
|
||||
for (var i = 2; i <= N+1; i++)
|
||||
{
|
||||
Comps[i] = _entityManager.GetComponent<A>(new EntityUid(i));
|
||||
}
|
||||
|
||||
// Return something so the JIT doesn't optimize out all the GetComponent calls.
|
||||
return Comps;
|
||||
}
|
||||
|
||||
[ComponentProtoName("A")]
|
||||
public sealed class A : Component
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Analyzers;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.UnitTesting.Server;
|
||||
|
||||
namespace Robust.Benchmarks.EntityManager;
|
||||
|
||||
[Virtual]
|
||||
public class SpawnDeleteEntityBenchmark
|
||||
{
|
||||
private ISimulation _simulation = default!;
|
||||
private IEntityManager _entityManager = default!;
|
||||
|
||||
private MapCoordinates _mapCoords = MapCoordinates.Nullspace;
|
||||
private EntityCoordinates _entCoords = EntityCoordinates.Invalid;
|
||||
|
||||
[UsedImplicitly]
|
||||
[Params(1, 10, 100, 1000)]
|
||||
public int N;
|
||||
|
||||
[GlobalSetup]
|
||||
public void GlobalSetup()
|
||||
{
|
||||
_simulation = RobustServerSimulation
|
||||
.NewSimulation()
|
||||
.RegisterComponents(f => f.RegisterClass<A>())
|
||||
.InitializeInstance();
|
||||
|
||||
_entityManager = _simulation.Resolve<IEntityManager>();
|
||||
|
||||
_mapCoords = new MapCoordinates(0, 0, new MapId(1));
|
||||
var uid = _simulation.AddMap(_mapCoords.MapId);
|
||||
_entCoords = new EntityCoordinates(uid, 0, 0);
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = true)]
|
||||
public void SpawnDeleteEntityMapCoords()
|
||||
{
|
||||
for (var i = 0; i < N; i++)
|
||||
{
|
||||
var uid = _entityManager.SpawnEntity(null, _mapCoords);
|
||||
_entityManager.DeleteEntity(uid);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void SpawnDeleteEntityEntCoords()
|
||||
{
|
||||
for (var i = 0; i < N; i++)
|
||||
{
|
||||
var uid = _entityManager.SpawnEntity(null, _entCoords);
|
||||
_entityManager.DeleteEntity(uid);
|
||||
}
|
||||
}
|
||||
|
||||
[ComponentProtoName("A")]
|
||||
public sealed class A : Component
|
||||
{
|
||||
}
|
||||
}
|
||||
143
Robust.Benchmarks/Exporters/SQLExporter.cs
Normal file
143
Robust.Benchmarks/Exporters/SQLExporter.cs
Normal file
@@ -0,0 +1,143 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using BenchmarkDotNet.Exporters;
|
||||
using BenchmarkDotNet.Loggers;
|
||||
using BenchmarkDotNet.Mathematics;
|
||||
using BenchmarkDotNet.Reports;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Design;
|
||||
using Npgsql;
|
||||
|
||||
namespace Robust.Benchmarks.Exporters;
|
||||
|
||||
public sealed class SQLExporter : IExporter
|
||||
{
|
||||
public static readonly IExporter Default = new SQLExporter();
|
||||
|
||||
private SQLExporter(){}
|
||||
|
||||
public void ExportToLog(Summary summary, ILogger logger)
|
||||
{
|
||||
Export(summary, logger);
|
||||
}
|
||||
|
||||
public IEnumerable<string> ExportToFiles(Summary summary, ILogger consoleLogger)
|
||||
{
|
||||
Export(summary, consoleLogger);
|
||||
return Array.Empty<string>();
|
||||
}
|
||||
|
||||
private bool TryGetEnvironmentVariable(string name, ILogger logger, [NotNullWhen(true)] out string? value)
|
||||
{
|
||||
value = Environment.GetEnvironmentVariable(name);
|
||||
if (value == null)
|
||||
logger.WriteError($"ROBUST_BENCHMARKS_ENABLE_SQL is set, but {name} is missing.");
|
||||
return value != null;
|
||||
}
|
||||
|
||||
private void Export(Summary summary, ILogger logger)
|
||||
{
|
||||
if (!TryGetEnvironmentVariable("ROBUST_BENCHMARKS_SQL_ADDRESS", logger, out var address) ||
|
||||
!TryGetEnvironmentVariable("ROBUST_BENCHMARKS_SQL_PORT", logger, out var rawPort) ||
|
||||
!TryGetEnvironmentVariable("ROBUST_BENCHMARKS_SQL_USER", logger, out var user) ||
|
||||
!TryGetEnvironmentVariable("ROBUST_BENCHMARKS_SQL_PASSWORD", logger, out var password) ||
|
||||
!TryGetEnvironmentVariable("ROBUST_BENCHMARKS_SQL_DATABASE", logger, out var db) ||
|
||||
!TryGetEnvironmentVariable("GITHUB_SHA", logger, out var gitHash))
|
||||
return;
|
||||
|
||||
if (!int.TryParse(rawPort, out var port))
|
||||
{
|
||||
logger.WriteError("Failed parsing ROBUST_BENCHMARKS_SQL_PORT to int.");
|
||||
return;
|
||||
}
|
||||
|
||||
var builder = new DbContextOptionsBuilder<BenchmarkContext>();
|
||||
var connectionString = new NpgsqlConnectionStringBuilder
|
||||
{
|
||||
Host = address,
|
||||
Port = port,
|
||||
Database = db,
|
||||
Username = user,
|
||||
Password = password
|
||||
}.ConnectionString;
|
||||
builder.UseNpgsql(connectionString);
|
||||
using var ctx = new BenchmarkContext(builder.Options);
|
||||
try
|
||||
{
|
||||
ctx.Database.Migrate();
|
||||
ctx.BenchmarkRuns.Add(BenchmarkRun.FromSummary(summary, gitHash));
|
||||
ctx.SaveChanges();
|
||||
}
|
||||
finally
|
||||
{
|
||||
ctx.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public string Name => "sql";
|
||||
}
|
||||
|
||||
public sealed class DesignTimeContextFactoryPostgres : IDesignTimeDbContextFactory<BenchmarkContext>
|
||||
{
|
||||
public BenchmarkContext CreateDbContext(string[] args)
|
||||
{
|
||||
var optionsBuilder = new DbContextOptionsBuilder<BenchmarkContext>();
|
||||
optionsBuilder.UseNpgsql("Server=localhost");
|
||||
return new BenchmarkContext(optionsBuilder.Options);
|
||||
}
|
||||
}
|
||||
|
||||
public class BenchmarkContext : DbContext
|
||||
{
|
||||
public DbSet<BenchmarkRun> BenchmarkRuns { get; set; } = default!;
|
||||
|
||||
public BenchmarkContext() { }
|
||||
public BenchmarkContext(DbContextOptions<BenchmarkContext> options) : base(options) { }
|
||||
}
|
||||
|
||||
public class BenchmarkRun
|
||||
{
|
||||
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
public ulong Id { get; set; }
|
||||
public string GitHash { get; set; } = string.Empty;
|
||||
[Column(TypeName = "timestamptz")]
|
||||
public DateTime RunDate { get; set; }
|
||||
public string Name { get; set; } = string.Empty;
|
||||
[Column(TypeName = "jsonb")]
|
||||
public BenchmarkRunReport[] Reports { get; set; } = Array.Empty<BenchmarkRunReport>();
|
||||
|
||||
public static BenchmarkRun FromSummary(Summary summary, string gitHash)
|
||||
{
|
||||
return new BenchmarkRun
|
||||
{
|
||||
Reports = summary.Reports.Select(r => new BenchmarkRunReport
|
||||
{
|
||||
Parameters = r.BenchmarkCase.Parameters.Items.Select(p => new BenchmarkRunParameter
|
||||
{
|
||||
Name = p.Name,
|
||||
Value = p.Value
|
||||
}).ToArray(),
|
||||
Statistics = r.ResultStatistics
|
||||
}).ToArray(),
|
||||
Name = summary.BenchmarksCases.First().FolderInfo,
|
||||
RunDate = DateTime.UtcNow,
|
||||
GitHash = gitHash
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public class BenchmarkRunReport
|
||||
{
|
||||
public BenchmarkRunParameter[] Parameters { get; set; } = Array.Empty<BenchmarkRunParameter>();
|
||||
public Statistics Statistics { get; set; } = default!;
|
||||
}
|
||||
|
||||
public class BenchmarkRunParameter
|
||||
{
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public object Value { get; set; } = default!;
|
||||
}
|
||||
55
Robust.Benchmarks/Migrations/20220328231938_InitialCreate.Designer.cs
generated
Normal file
55
Robust.Benchmarks/Migrations/20220328231938_InitialCreate.Designer.cs
generated
Normal file
@@ -0,0 +1,55 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using Robust.Benchmarks.Exporters;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Robust.Benchmarks.Migrations
|
||||
{
|
||||
[DbContext(typeof(BenchmarkContext))]
|
||||
[Migration("20220328231938_InitialCreate")]
|
||||
partial class InitialCreate
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "6.0.0")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Robust.Benchmarks.Exporters.BenchmarkRun", b =>
|
||||
{
|
||||
b.Property<decimal>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("numeric(20,0)");
|
||||
|
||||
b.Property<string>("GitHash")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<BenchmarkRunReport[]>("Reports")
|
||||
.IsRequired()
|
||||
.HasColumnType("jsonb");
|
||||
|
||||
b.Property<DateTime>("RunDate")
|
||||
.HasColumnType("Date");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("BenchmarkRuns");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
35
Robust.Benchmarks/Migrations/20220328231938_InitialCreate.cs
Normal file
35
Robust.Benchmarks/Migrations/20220328231938_InitialCreate.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Robust.Benchmarks.Exporters;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Robust.Benchmarks.Migrations
|
||||
{
|
||||
public partial class InitialCreate : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "BenchmarkRuns",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<decimal>(type: "numeric(20,0)", nullable: false),
|
||||
GitHash = table.Column<string>(type: "text", nullable: false),
|
||||
RunDate = table.Column<DateTime>(type: "Date", nullable: false),
|
||||
Name = table.Column<string>(type: "text", nullable: false),
|
||||
Reports = table.Column<BenchmarkRunReport[]>(type: "jsonb", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_BenchmarkRuns", x => x.Id);
|
||||
});
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "BenchmarkRuns");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using Robust.Benchmarks.Exporters;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Robust.Benchmarks.Migrations
|
||||
{
|
||||
[DbContext(typeof(BenchmarkContext))]
|
||||
partial class BenchmarkContextModelSnapshot : ModelSnapshot
|
||||
{
|
||||
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "6.0.0")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Robust.Benchmarks.Exporters.BenchmarkRun", b =>
|
||||
{
|
||||
b.Property<decimal>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("numeric(20,0)");
|
||||
|
||||
b.Property<string>("GitHash")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<BenchmarkRunReport[]>("Reports")
|
||||
.IsRequired()
|
||||
.HasColumnType("jsonb");
|
||||
|
||||
b.Property<DateTime>("RunDate")
|
||||
.HasColumnType("Date");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("BenchmarkRuns");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,17 @@
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Robust.Shared.Analyzers;
|
||||
|
||||
namespace Robust.Benchmarks.NumericsHelpers
|
||||
{
|
||||
[Virtual]
|
||||
public class AddBenchmark
|
||||
{
|
||||
[Params(32, 128)]
|
||||
public int N { get; set; }
|
||||
|
||||
[Params(1,2)]
|
||||
public int T { get; set; }
|
||||
|
||||
private float[] _inputA = default!;
|
||||
private float[] _inputB = default!;
|
||||
private float[] _output = default!;
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
using BenchmarkDotNet.Configs;
|
||||
using BenchmarkDotNet.Running;
|
||||
using System;
|
||||
using Robust.Benchmarks.Configs;
|
||||
using Robust.Benchmarks.Exporters;
|
||||
|
||||
namespace Robust.Benchmarks
|
||||
{
|
||||
internal class Program
|
||||
internal static class Program
|
||||
{
|
||||
// --allCategories=ctg1,ctg2
|
||||
// --anyCategories=ctg1,ctg2
|
||||
@@ -16,7 +18,8 @@ namespace Robust.Benchmarks
|
||||
Console.WriteLine("THE DEBUG BUILD IS ONLY GOOD FOR FIXING A CRASHING BENCHMARK\n");
|
||||
BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args, new DebugInProcessConfig());
|
||||
#else
|
||||
BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args);
|
||||
var config = Environment.GetEnvironmentVariable("ROBUST_BENCHMARKS_ENABLE_SQL") != null ? DefaultSQLConfig.Instance : null;
|
||||
BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args, config);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,9 +10,15 @@
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Robust.Server\Robust.Server.csproj" />
|
||||
<ProjectReference Include="..\Robust.Shared\Robust.Shared.csproj" />
|
||||
<ProjectReference Include="..\Robust.UnitTesting\Robust.UnitTesting.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BenchmarkDotNet" Version="0.12.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.0">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="6.0.0-rc.2" />
|
||||
</ItemGroup>
|
||||
<Import Project="..\MSBuild\Robust.Engine.targets" />
|
||||
</Project>
|
||||
|
||||
@@ -9,7 +9,7 @@ using Robust.Shared.Serialization.TypeSerializers.Interfaces;
|
||||
|
||||
namespace Robust.Benchmarks.Serialization
|
||||
{
|
||||
public class BenchmarkIntSerializer : ITypeSerializer<int, ValueDataNode>
|
||||
public sealed class BenchmarkIntSerializer : ITypeSerializer<int, ValueDataNode>
|
||||
{
|
||||
public ValidationNode Validate(ISerializationManager serializationManager, ValueDataNode node,
|
||||
IDependencyCollection dependencies, ISerializationContext? context = null)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Linq;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Robust.Benchmarks.Serialization.Definitions;
|
||||
using Robust.Shared.Analyzers;
|
||||
using Robust.Shared.Serialization.Manager;
|
||||
using Robust.Shared.Serialization.Markdown;
|
||||
using Robust.Shared.Serialization.Markdown.Mapping;
|
||||
@@ -13,6 +14,7 @@ using YamlDotNet.RepresentationModel;
|
||||
namespace Robust.Benchmarks.Serialization.Copy
|
||||
{
|
||||
[MemoryDiagnoser]
|
||||
[Virtual]
|
||||
public class SerializationCopyBenchmark : SerializationBenchmark
|
||||
{
|
||||
public SerializationCopyBenchmark()
|
||||
|
||||
@@ -3,7 +3,7 @@ using Robust.Shared.Serialization;
|
||||
|
||||
namespace Robust.Benchmarks.Serialization.Definitions
|
||||
{
|
||||
public class BenchmarkFlags
|
||||
public sealed class BenchmarkFlags
|
||||
{
|
||||
public const int Zero = 1 << 0;
|
||||
public const int ThirtyOne = 1 << 31;
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.Analyzers;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
|
||||
namespace Robust.Benchmarks.Serialization.Definitions
|
||||
{
|
||||
[DataDefinition]
|
||||
[Virtual]
|
||||
public class DataDefinitionWithString
|
||||
{
|
||||
[DataField("string")]
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace Robust.Benchmarks.Serialization.Definitions
|
||||
/// Taken from content.
|
||||
/// </summary>
|
||||
[Prototype("seed")]
|
||||
public class SeedDataDefinition : IPrototype
|
||||
public sealed class SeedDataDefinition : IPrototype
|
||||
{
|
||||
public const string Prototype = @"
|
||||
- type: seed
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Robust.Shared.Analyzers;
|
||||
using Robust.Shared.Serialization.Manager;
|
||||
|
||||
namespace Robust.Benchmarks.Serialization.Initialize
|
||||
{
|
||||
[MemoryDiagnoser]
|
||||
[Virtual]
|
||||
public class SerializationInitializeBenchmark : SerializationBenchmark
|
||||
{
|
||||
[IterationCleanup]
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.IO;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Robust.Benchmarks.Serialization.Definitions;
|
||||
using Robust.Shared.Analyzers;
|
||||
using Robust.Shared.Serialization.Manager.Result;
|
||||
using Robust.Shared.Serialization.Markdown;
|
||||
using Robust.Shared.Serialization.Markdown.Mapping;
|
||||
@@ -12,6 +13,7 @@ using YamlDotNet.RepresentationModel;
|
||||
namespace Robust.Benchmarks.Serialization.Read
|
||||
{
|
||||
[MemoryDiagnoser]
|
||||
[Virtual]
|
||||
public class SerializationReadBenchmark : SerializationBenchmark
|
||||
{
|
||||
public SerializationReadBenchmark()
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Robust.Benchmarks.Serialization.Definitions;
|
||||
using Robust.Shared.Analyzers;
|
||||
using Robust.Shared.Serialization.Markdown.Mapping;
|
||||
using Robust.Shared.Serialization.Markdown.Sequence;
|
||||
using Robust.Shared.Serialization.Markdown.Value;
|
||||
@@ -7,6 +8,7 @@ using Robust.Shared.Serialization.Markdown.Value;
|
||||
namespace Robust.Benchmarks.Serialization
|
||||
{
|
||||
[MemoryDiagnoser]
|
||||
[Virtual]
|
||||
public class SerializationArrayBenchmark : SerializationBenchmark
|
||||
{
|
||||
public SerializationArrayBenchmark()
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.IO;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Robust.Benchmarks.Serialization.Definitions;
|
||||
using Robust.Shared.Analyzers;
|
||||
using Robust.Shared.Serialization.Manager;
|
||||
using Robust.Shared.Serialization.Markdown;
|
||||
using Robust.Shared.Serialization.Markdown.Mapping;
|
||||
@@ -13,6 +14,7 @@ using YamlDotNet.RepresentationModel;
|
||||
namespace Robust.Benchmarks.Serialization.Write
|
||||
{
|
||||
[MemoryDiagnoser]
|
||||
[Virtual]
|
||||
public class SerializationWriteBenchmark : SerializationBenchmark
|
||||
{
|
||||
public SerializationWriteBenchmark()
|
||||
|
||||
11
Robust.Benchmarks/add-migration.ps1
Normal file
11
Robust.Benchmarks/add-migration.ps1
Normal file
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/env pwsh
|
||||
|
||||
param([String]$name)
|
||||
|
||||
if ($name -eq "")
|
||||
{
|
||||
Write-Error "must specify migration name"
|
||||
exit
|
||||
}
|
||||
|
||||
dotnet ef migrations add --context BenchmarkContext -o Migrations $name
|
||||
8
Robust.Benchmarks/add-migration.sh
Normal file
8
Robust.Benchmarks/add-migration.sh
Normal file
@@ -0,0 +1,8 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
if [ -z "$1" ] ; then
|
||||
echo "Must specify migration name"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
dotnet ef migrations add --context BenchmarkContext -o Migrations "$1"
|
||||
@@ -6,7 +6,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Build.Framework" Version="16.8.0" />
|
||||
<PackageReference Include="Microsoft.Build.Framework" Version="17.0.0" />
|
||||
<PackageReference Include="Mono.Cecil" Version="0.11.3" />
|
||||
<PackageReference Include="Pidgin" Version="2.5.0" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.8.0" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.2" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.0.1" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.3" PrivateAssets="all" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -3,7 +3,7 @@ using Robust.Shared.Animations;
|
||||
|
||||
namespace Robust.Client.Animations
|
||||
{
|
||||
public class AnimationTrackControlProperty : AnimationTrackProperty
|
||||
public sealed class AnimationTrackControlProperty : AnimationTrackProperty
|
||||
{
|
||||
public string? Property { get; set; }
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace Robust.Client.Audio.Midi
|
||||
void Shutdown();
|
||||
}
|
||||
|
||||
internal class MidiManager : IMidiManager
|
||||
internal sealed class MidiManager : IMidiManager
|
||||
{
|
||||
[Dependency] private readonly IEyeManager _eyeManager = default!;
|
||||
[Dependency] private readonly IResourceManagerInternal _resourceManager = default!;
|
||||
@@ -392,7 +392,7 @@ namespace Robust.Client.Audio.Midi
|
||||
/// <summary>
|
||||
/// This class is used to load soundfonts.
|
||||
/// </summary>
|
||||
private class ResourceLoaderCallbacks : SoundFontLoaderCallbacks
|
||||
private sealed class ResourceLoaderCallbacks : SoundFontLoaderCallbacks
|
||||
{
|
||||
private readonly Dictionary<int, Stream> _openStreams = new();
|
||||
private int _nextStreamId = 1;
|
||||
|
||||
@@ -180,7 +180,7 @@ namespace Robust.Client.Audio.Midi
|
||||
internal void InternalDispose();
|
||||
}
|
||||
|
||||
internal class MidiRenderer : IMidiRenderer
|
||||
internal sealed class MidiRenderer : IMidiRenderer
|
||||
{
|
||||
[Dependency] private readonly IClydeAudio _clydeAudio = default!;
|
||||
[Dependency] private readonly ITaskManager _taskManager = default!;
|
||||
@@ -619,6 +619,7 @@ namespace Robust.Client.Audio.Midi
|
||||
var seqEv = (SequencerEvent) midiEvent;
|
||||
seqEv.Dest = _debugEvents ? _debugRegister : _synthRegister;
|
||||
_sequencer.SendAt(seqEv, time, absolute);
|
||||
seqEv.Dispose();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
||||
@@ -20,13 +20,12 @@ using Robust.Shared.Utility;
|
||||
namespace Robust.Client
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public class BaseClient : IBaseClient
|
||||
public sealed class BaseClient : IBaseClient
|
||||
{
|
||||
[Dependency] private readonly IClientNetManager _net = default!;
|
||||
[Dependency] private readonly IPlayerManager _playMan = default!;
|
||||
[Dependency] private readonly INetConfigurationManager _configManager = default!;
|
||||
[Dependency] private readonly IClientEntityManager _entityManager = default!;
|
||||
[Dependency] private readonly IEntityLookup _entityLookup = default!;
|
||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||
[Dependency] private readonly IDiscordRichPresence _discord = default!;
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
@@ -213,7 +212,6 @@ namespace Robust.Client
|
||||
{
|
||||
_entityManager.Startup();
|
||||
_mapManager.Startup();
|
||||
_entityLookup.Startup();
|
||||
|
||||
_timing.ResetSimTime();
|
||||
_timing.Paused = false;
|
||||
@@ -224,7 +222,6 @@ namespace Robust.Client
|
||||
IoCManager.Resolve<INetConfigurationManager>().FlushMessages();
|
||||
_gameStates.Reset();
|
||||
_playMan.Shutdown();
|
||||
_entityLookup.Shutdown();
|
||||
_entityManager.Shutdown();
|
||||
_mapManager.Shutdown();
|
||||
_discord.ClearPresence();
|
||||
@@ -291,7 +288,7 @@ namespace Robust.Client
|
||||
/// <summary>
|
||||
/// Event arguments for when something changed with the player.
|
||||
/// </summary>
|
||||
public class PlayerEventArgs : EventArgs
|
||||
public sealed class PlayerEventArgs : EventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// The session that triggered the event.
|
||||
@@ -310,7 +307,7 @@ namespace Robust.Client
|
||||
/// <summary>
|
||||
/// Event arguments for when the RunLevel has changed in the BaseClient.
|
||||
/// </summary>
|
||||
public class RunLevelChangedEventArgs : EventArgs
|
||||
public sealed class RunLevelChangedEventArgs : EventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// RunLevel that the BaseClient switched from.
|
||||
@@ -335,7 +332,7 @@ namespace Robust.Client
|
||||
/// <summary>
|
||||
/// Info about the server and player that is sent to the client while connecting.
|
||||
/// </summary>
|
||||
public class ServerInfo
|
||||
public sealed class ServerInfo
|
||||
{
|
||||
public ServerInfo(string serverName)
|
||||
{
|
||||
|
||||
@@ -43,11 +43,10 @@ namespace Robust.Client
|
||||
IoCManager.Register<IGameTiming, ClientGameTiming>();
|
||||
IoCManager.Register<IClientGameTiming, ClientGameTiming>();
|
||||
IoCManager.Register<IPrototypeManager, ClientPrototypeManager>();
|
||||
IoCManager.Register<IMapManager, ClientMapManager>();
|
||||
IoCManager.Register<IMapManagerInternal, ClientMapManager>();
|
||||
IoCManager.Register<IClientMapManager, ClientMapManager>();
|
||||
IoCManager.Register<IMapManager, NetworkedMapManager>();
|
||||
IoCManager.Register<IMapManagerInternal, NetworkedMapManager>();
|
||||
IoCManager.Register<INetworkedMapManager, NetworkedMapManager>();
|
||||
IoCManager.Register<IEntityManager, ClientEntityManager>();
|
||||
IoCManager.Register<IEntityLookup, EntityLookup>();
|
||||
IoCManager.Register<IReflectionManager, ClientReflectionManager>();
|
||||
IoCManager.Register<IConsoleHost, ClientConsoleHost>();
|
||||
IoCManager.Register<IClientConsoleHost, ClientConsoleHost>();
|
||||
@@ -72,7 +71,6 @@ namespace Robust.Client
|
||||
IoCManager.Register<IStateManager, StateManager>();
|
||||
IoCManager.Register<IUserInterfaceManager, UserInterfaceManager>();
|
||||
IoCManager.Register<IUserInterfaceManagerInternal, UserInterfaceManager>();
|
||||
IoCManager.Register<IDebugDrawing, DebugDrawing>();
|
||||
IoCManager.Register<ILightManager, LightManager>();
|
||||
IoCManager.Register<IDiscordRichPresence, DiscordRichPresence>();
|
||||
IoCManager.Register<IMidiManager, MidiManager>();
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Robust.Client.Console
|
||||
{
|
||||
public class ClientConGroupController : IClientConGroupController
|
||||
public sealed class ClientConGroupController : IClientConGroupController
|
||||
{
|
||||
private IClientConGroupImplementation? _implementation;
|
||||
public event Action? ConGroupUpdated;
|
||||
|
||||
@@ -14,7 +14,7 @@ using Robust.Shared.Utility;
|
||||
|
||||
namespace Robust.Client.Console
|
||||
{
|
||||
public class AddStringArgs : EventArgs
|
||||
public sealed class AddStringArgs : EventArgs
|
||||
{
|
||||
public string Text { get; }
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace Robust.Client.Console
|
||||
}
|
||||
}
|
||||
|
||||
public class AddFormattedMessageArgs : EventArgs
|
||||
public sealed class AddFormattedMessageArgs : EventArgs
|
||||
{
|
||||
public readonly FormattedMessage Message;
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace Robust.Client.Console
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IClientConsoleHost" />
|
||||
internal class ClientConsoleHost : ConsoleHost, IClientConsoleHost
|
||||
internal sealed class ClientConsoleHost : ConsoleHost, IClientConsoleHost
|
||||
{
|
||||
[Dependency] private readonly IClientConGroupController _conGroup = default!;
|
||||
|
||||
@@ -109,13 +109,13 @@ namespace Robust.Client.Console
|
||||
if (AvailableCommands.ContainsKey(commandName))
|
||||
{
|
||||
var playerManager = IoCManager.Resolve<IPlayerManager>();
|
||||
|
||||
#if !DEBUG
|
||||
if (!_conGroup.CanCommand(commandName) && playerManager.LocalPlayer?.Session.Status > SessionStatus.Connecting)
|
||||
{
|
||||
WriteError(null, $"Insufficient perms for command: {commandName}");
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
var command1 = AvailableCommands[commandName];
|
||||
args.RemoveAt(0);
|
||||
var shell = new ConsoleShell(this, null);
|
||||
@@ -209,7 +209,7 @@ namespace Robust.Client.Console
|
||||
/// These dummies are made purely so list and help can list server-side commands.
|
||||
/// </summary>
|
||||
[Reflect(false)]
|
||||
internal class ServerDummyCommand : IConsoleCommand
|
||||
internal sealed class ServerDummyCommand : IConsoleCommand
|
||||
{
|
||||
internal ServerDummyCommand(string command, string help, string description)
|
||||
{
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace Robust.Client.Console.Commands
|
||||
}
|
||||
|
||||
[UsedImplicitly]
|
||||
public class SaveConfig : IConsoleCommand
|
||||
public sealed class SaveConfig : IConsoleCommand
|
||||
{
|
||||
public string Command => "saveconfig";
|
||||
public string Description => "Saves the client configuration to the config file";
|
||||
|
||||
@@ -6,7 +6,7 @@ using Robust.Shared.Console;
|
||||
|
||||
namespace Robust.Client.Console.Commands
|
||||
{
|
||||
class ClearCommand : IConsoleCommand
|
||||
sealed class ClearCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "cls";
|
||||
public string Help => "Clears the debug console of all messages.";
|
||||
@@ -18,7 +18,7 @@ namespace Robust.Client.Console.Commands
|
||||
}
|
||||
}
|
||||
|
||||
class FillCommand : IConsoleCommand
|
||||
sealed class FillCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "fill";
|
||||
public string Help => "Fills the console with some nonsense for debugging.";
|
||||
|
||||
@@ -30,7 +30,7 @@ using static Robust.Client.UserInterface.Controls.BoxContainer;
|
||||
|
||||
namespace Robust.Client.Console.Commands
|
||||
{
|
||||
internal class DumpEntitiesCommand : IConsoleCommand
|
||||
internal sealed class DumpEntitiesCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "dumpentities";
|
||||
public string Help => "Dump entity list";
|
||||
@@ -47,7 +47,7 @@ namespace Robust.Client.Console.Commands
|
||||
}
|
||||
}
|
||||
|
||||
internal class GetComponentRegistrationCommand : IConsoleCommand
|
||||
internal sealed class GetComponentRegistrationCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "getcomponentregistration";
|
||||
public string Help => "Usage: getcomponentregistration <componentName>";
|
||||
@@ -93,7 +93,7 @@ namespace Robust.Client.Console.Commands
|
||||
}
|
||||
}
|
||||
|
||||
internal class ToggleMonitorCommand : IConsoleCommand
|
||||
internal sealed class ToggleMonitorCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "monitor";
|
||||
|
||||
@@ -148,7 +148,7 @@ namespace Robust.Client.Console.Commands
|
||||
}
|
||||
}
|
||||
|
||||
internal class ExceptionCommand : IConsoleCommand
|
||||
internal sealed class ExceptionCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "fuck";
|
||||
public string Help => "Throws an exception";
|
||||
@@ -160,7 +160,7 @@ namespace Robust.Client.Console.Commands
|
||||
}
|
||||
}
|
||||
|
||||
internal class ShowPositionsCommand : IConsoleCommand
|
||||
internal sealed class ShowPositionsCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "showpos";
|
||||
public string Help => "";
|
||||
@@ -168,12 +168,12 @@ namespace Robust.Client.Console.Commands
|
||||
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var mgr = IoCManager.Resolve<IDebugDrawing>();
|
||||
var mgr = EntitySystem.Get<DebugDrawingSystem>();
|
||||
mgr.DebugPositions = !mgr.DebugPositions;
|
||||
}
|
||||
}
|
||||
|
||||
internal class ShowRayCommand : IConsoleCommand
|
||||
internal sealed class ShowRayCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "showrays";
|
||||
public string Help => "Usage: showrays <raylifetime>";
|
||||
@@ -200,7 +200,7 @@ namespace Robust.Client.Console.Commands
|
||||
}
|
||||
}
|
||||
|
||||
internal class DisconnectCommand : IConsoleCommand
|
||||
internal sealed class DisconnectCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "disconnect";
|
||||
public string Help => "";
|
||||
@@ -212,7 +212,7 @@ namespace Robust.Client.Console.Commands
|
||||
}
|
||||
}
|
||||
|
||||
internal class EntityInfoCommand : IConsoleCommand
|
||||
internal sealed class EntityInfoCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "entfo";
|
||||
|
||||
@@ -264,7 +264,7 @@ namespace Robust.Client.Console.Commands
|
||||
}
|
||||
}
|
||||
|
||||
internal class SnapGridGetCell : IConsoleCommand
|
||||
internal sealed class SnapGridGetCell : IConsoleCommand
|
||||
{
|
||||
public string Command => "sggcell";
|
||||
public string Help => "sggcell <gridID> <vector2i>\nThat vector2i param is in the form x<int>,y<int>.";
|
||||
@@ -313,7 +313,7 @@ namespace Robust.Client.Console.Commands
|
||||
}
|
||||
}
|
||||
|
||||
internal class SetPlayerName : IConsoleCommand
|
||||
internal sealed class SetPlayerName : IConsoleCommand
|
||||
{
|
||||
public string Command => "overrideplayername";
|
||||
public string Description => "Changes the name used when attempting to connect to the server.";
|
||||
@@ -333,7 +333,7 @@ namespace Robust.Client.Console.Commands
|
||||
}
|
||||
}
|
||||
|
||||
internal class LoadResource : IConsoleCommand
|
||||
internal sealed class LoadResource : IConsoleCommand
|
||||
{
|
||||
public string Command => "ldrsc";
|
||||
public string Description => "Pre-caches a resource.";
|
||||
@@ -370,7 +370,7 @@ namespace Robust.Client.Console.Commands
|
||||
}
|
||||
}
|
||||
|
||||
internal class ReloadResource : IConsoleCommand
|
||||
internal sealed class ReloadResource : IConsoleCommand
|
||||
{
|
||||
public string Command => "rldrsc";
|
||||
public string Description => "Reloads a resource.";
|
||||
@@ -404,7 +404,7 @@ namespace Robust.Client.Console.Commands
|
||||
}
|
||||
}
|
||||
|
||||
internal class GridTileCount : IConsoleCommand
|
||||
internal sealed class GridTileCount : IConsoleCommand
|
||||
{
|
||||
public string Command => "gridtc";
|
||||
public string Description => "Gets the tile count of a grid";
|
||||
@@ -438,7 +438,7 @@ namespace Robust.Client.Console.Commands
|
||||
}
|
||||
}
|
||||
|
||||
internal class GuiDumpCommand : IConsoleCommand
|
||||
internal sealed class GuiDumpCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "guidump";
|
||||
public string Description => "Dump GUI tree to /guidump.txt in user data.";
|
||||
@@ -512,7 +512,7 @@ namespace Robust.Client.Console.Commands
|
||||
}
|
||||
}
|
||||
|
||||
internal class UITestCommand : IConsoleCommand
|
||||
internal sealed class UITestCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "uitest";
|
||||
public string Description => "Open a dummy UI testing window";
|
||||
@@ -644,7 +644,7 @@ namespace Robust.Client.Console.Commands
|
||||
}
|
||||
}
|
||||
|
||||
internal class SetClipboardCommand : IConsoleCommand
|
||||
internal sealed class SetClipboardCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "setclipboard";
|
||||
public string Description => "Sets the system clipboard";
|
||||
@@ -657,7 +657,7 @@ namespace Robust.Client.Console.Commands
|
||||
}
|
||||
}
|
||||
|
||||
internal class GetClipboardCommand : IConsoleCommand
|
||||
internal sealed class GetClipboardCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "getclipboard";
|
||||
public string Description => "Gets the system clipboard";
|
||||
@@ -670,7 +670,7 @@ namespace Robust.Client.Console.Commands
|
||||
}
|
||||
}
|
||||
|
||||
internal class ToggleLight : IConsoleCommand
|
||||
internal sealed class ToggleLight : IConsoleCommand
|
||||
{
|
||||
public string Command => "togglelight";
|
||||
public string Description => "Toggles light rendering.";
|
||||
@@ -684,7 +684,7 @@ namespace Robust.Client.Console.Commands
|
||||
}
|
||||
}
|
||||
|
||||
internal class ToggleFOV : IConsoleCommand
|
||||
internal sealed class ToggleFOV : IConsoleCommand
|
||||
{
|
||||
public string Command => "togglefov";
|
||||
public string Description => "Toggles fov for client.";
|
||||
@@ -698,7 +698,7 @@ namespace Robust.Client.Console.Commands
|
||||
}
|
||||
}
|
||||
|
||||
internal class ToggleHardFOV : IConsoleCommand
|
||||
internal sealed class ToggleHardFOV : IConsoleCommand
|
||||
{
|
||||
public string Command => "togglehardfov";
|
||||
public string Description => "Toggles hard fov for client (for debugging space-station-14#2353).";
|
||||
@@ -712,7 +712,7 @@ namespace Robust.Client.Console.Commands
|
||||
}
|
||||
}
|
||||
|
||||
internal class ToggleShadows : IConsoleCommand
|
||||
internal sealed class ToggleShadows : IConsoleCommand
|
||||
{
|
||||
public string Command => "toggleshadows";
|
||||
public string Description => "Toggles shadow rendering.";
|
||||
@@ -725,7 +725,7 @@ namespace Robust.Client.Console.Commands
|
||||
mgr.DrawShadows = !mgr.DrawShadows;
|
||||
}
|
||||
}
|
||||
internal class ToggleLightBuf : IConsoleCommand
|
||||
internal sealed class ToggleLightBuf : IConsoleCommand
|
||||
{
|
||||
public string Command => "togglelightbuf";
|
||||
public string Description => "Toggles lighting rendering. This includes shadows but not FOV.";
|
||||
@@ -739,7 +739,7 @@ namespace Robust.Client.Console.Commands
|
||||
}
|
||||
}
|
||||
|
||||
internal class GcCommand : IConsoleCommand
|
||||
internal sealed class GcCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "gc";
|
||||
public string Description => "Run the GC.";
|
||||
@@ -761,7 +761,7 @@ namespace Robust.Client.Console.Commands
|
||||
}
|
||||
}
|
||||
|
||||
internal class GcFullCommand : IConsoleCommand
|
||||
internal sealed class GcFullCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "gcf";
|
||||
public string Description => "Run the GC, fully, compacting LOH and everything.";
|
||||
@@ -774,7 +774,7 @@ namespace Robust.Client.Console.Commands
|
||||
}
|
||||
}
|
||||
|
||||
internal class GcModeCommand : IConsoleCommand
|
||||
internal sealed class GcModeCommand : IConsoleCommand
|
||||
{
|
||||
|
||||
public string Command => "gc_mode";
|
||||
@@ -816,7 +816,7 @@ namespace Robust.Client.Console.Commands
|
||||
|
||||
}
|
||||
|
||||
internal class SerializeStatsCommand : IConsoleCommand
|
||||
internal sealed class SerializeStatsCommand : IConsoleCommand
|
||||
{
|
||||
|
||||
public string Command => "szr_stats";
|
||||
@@ -836,7 +836,7 @@ namespace Robust.Client.Console.Commands
|
||||
|
||||
}
|
||||
|
||||
internal class ChunkInfoCommand : IConsoleCommand
|
||||
internal sealed class ChunkInfoCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "chunkinfo";
|
||||
public string Description => "Gets info about a chunk under your mouse cursor.";
|
||||
@@ -861,11 +861,11 @@ namespace Robust.Client.Console.Commands
|
||||
var chunkIndex = grid.LocalToChunkIndices(grid.MapToGrid(mousePos));
|
||||
var chunk = internalGrid.GetChunk(chunkIndex);
|
||||
|
||||
shell.WriteLine($"worldBounds: {chunk.CalcWorldAABB()} localBounds: {chunk.CalcLocalBounds()}");
|
||||
shell.WriteLine($"worldBounds: {internalGrid.CalcWorldAABB(chunk)} localBounds: {chunk.CachedBounds}");
|
||||
}
|
||||
}
|
||||
|
||||
internal class ReloadShadersCommand : IConsoleCommand
|
||||
internal sealed class ReloadShadersCommand : IConsoleCommand
|
||||
{
|
||||
|
||||
public string Command => "rldshader";
|
||||
@@ -1036,7 +1036,7 @@ namespace Robust.Client.Console.Commands
|
||||
|
||||
}
|
||||
|
||||
internal class ClydeDebugLayerCommand : IConsoleCommand
|
||||
internal sealed class ClydeDebugLayerCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "cldbglyr";
|
||||
public string Description => "Toggle fov and light debug layers";
|
||||
@@ -1061,7 +1061,7 @@ namespace Robust.Client.Console.Commands
|
||||
}
|
||||
}
|
||||
|
||||
internal class GetKeyInfoCommand : IConsoleCommand
|
||||
internal sealed class GetKeyInfoCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "keyinfo";
|
||||
public string Description => "Keys key info for a key";
|
||||
|
||||
@@ -4,7 +4,7 @@ using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Robust.Client.Console.Commands
|
||||
{
|
||||
public class GridChunkBBCommand : IConsoleCommand
|
||||
public sealed class GridChunkBBCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "showchunkbb";
|
||||
public string Description => "Displays chunk bounds for the purposes of rendering";
|
||||
|
||||
@@ -5,7 +5,7 @@ using Robust.Shared.Network;
|
||||
|
||||
namespace Robust.Client.Console.Commands
|
||||
{
|
||||
class HelpCommand : IConsoleCommand
|
||||
sealed class HelpCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "help";
|
||||
public string Help => "When no arguments are provided, displays a generic help text. When an argument is passed, display the help text for the command with that name.";
|
||||
@@ -44,7 +44,7 @@ namespace Robust.Client.Console.Commands
|
||||
}
|
||||
}
|
||||
|
||||
class ListCommand : IConsoleCommand
|
||||
sealed class ListCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "list";
|
||||
public string Help => "Usage: list [filter]\n" +
|
||||
|
||||
@@ -4,7 +4,7 @@ using Robust.Shared.Console;
|
||||
|
||||
namespace Robust.Client.Console.Commands
|
||||
{
|
||||
class LogSetLevelCommand : IConsoleCommand
|
||||
sealed class LogSetLevelCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "loglevel";
|
||||
public string Description => "Changes the log level for a provided sawmill.";
|
||||
@@ -40,7 +40,7 @@ namespace Robust.Client.Console.Commands
|
||||
}
|
||||
}
|
||||
|
||||
class TestLog : IConsoleCommand
|
||||
sealed class TestLog : IConsoleCommand
|
||||
{
|
||||
public string Command => "testlog";
|
||||
public string Description => "Writes a test log to a sawmill.";
|
||||
|
||||
@@ -4,7 +4,7 @@ using Robust.Shared.IoC;
|
||||
|
||||
namespace Robust.Client.Console.Commands
|
||||
{
|
||||
class HardQuitCommand : IConsoleCommand
|
||||
sealed class HardQuitCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "hardquit";
|
||||
public string Description => "Kills the game client instantly.";
|
||||
@@ -16,7 +16,7 @@ namespace Robust.Client.Console.Commands
|
||||
}
|
||||
}
|
||||
|
||||
class QuitCommand : IConsoleCommand
|
||||
sealed class QuitCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "quit";
|
||||
public string Description => "Shuts down the game client gracefully.";
|
||||
|
||||
@@ -6,7 +6,7 @@ using Robust.Shared.IoC;
|
||||
namespace Robust.Client.Console.Commands
|
||||
{
|
||||
[UsedImplicitly]
|
||||
public class SetInputContextCommand : IConsoleCommand
|
||||
public sealed class SetInputContextCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "setinputcontext";
|
||||
public string Description => "Sets the active input context.";
|
||||
|
||||
@@ -4,7 +4,7 @@ using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Robust.Client.Console.Commands
|
||||
{
|
||||
public class VelocitiesCommand : IConsoleCommand
|
||||
public sealed class VelocitiesCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "showvelocities";
|
||||
public string Description => "Displays your angular and linear velocities";
|
||||
|
||||
@@ -11,7 +11,7 @@ using static Robust.Shared.Network.Messages.MsgScriptCompletionResponse;
|
||||
|
||||
namespace Robust.Client.Console
|
||||
{
|
||||
public class Completions : DefaultWindow
|
||||
public sealed class Completions : DefaultWindow
|
||||
{
|
||||
private HistoryLineEdit _textBar;
|
||||
private ScrollContainer _suggestPanel = new()
|
||||
@@ -75,7 +75,7 @@ namespace Robust.Client.Console
|
||||
}
|
||||
|
||||
// Label and ghetto button.
|
||||
public class Entry : RichTextLabel
|
||||
public sealed class Entry : RichTextLabel
|
||||
{
|
||||
public readonly LiteResult Result;
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ using Robust.Shared.Network.Messages;
|
||||
|
||||
namespace Robust.Client.Console
|
||||
{
|
||||
public partial class ScriptClient : IScriptClient
|
||||
public sealed partial class ScriptClient : IScriptClient
|
||||
{
|
||||
[Dependency] private readonly IClientConGroupController _conGroupController = default!;
|
||||
[Dependency] private readonly IClientNetManager _netManager = default!;
|
||||
|
||||
@@ -15,7 +15,7 @@ using static Robust.Client.UserInterface.Controls.BoxContainer;
|
||||
|
||||
namespace Robust.Client.Console
|
||||
{
|
||||
public class WatchWindow : DefaultWindow
|
||||
public sealed class WatchWindow : DefaultWindow
|
||||
{
|
||||
private readonly IReflectionManager _reflectionManager;
|
||||
|
||||
|
||||
@@ -6,17 +6,21 @@ using Robust.Shared.Maths;
|
||||
|
||||
namespace Robust.Client.Debugging
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public class DebugDrawing : IDebugDrawing
|
||||
/// <summary>
|
||||
/// A collection of visual debug overlays for the client game.
|
||||
/// </summary>
|
||||
public sealed class DebugDrawingSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IOverlayManager _overlayManager = default!;
|
||||
[Dependency] private readonly IEyeManager _eyeManager = default!;
|
||||
[Dependency] private readonly IEntityLookup _lookup = default!;
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
||||
|
||||
private bool _debugPositions;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Toggles the visual overlay of the local origin for each entity on screen.
|
||||
/// </summary>
|
||||
public bool DebugPositions
|
||||
{
|
||||
get => _debugPositions;
|
||||
@@ -42,13 +46,13 @@ namespace Robust.Client.Debugging
|
||||
|
||||
private sealed class EntityPositionOverlay : Overlay
|
||||
{
|
||||
private readonly IEntityLookup _lookup;
|
||||
private readonly EntityLookupSystem _lookup;
|
||||
private readonly IEyeManager _eyeManager;
|
||||
private readonly IEntityManager _entityManager;
|
||||
|
||||
public override OverlaySpace Space => OverlaySpace.WorldSpace;
|
||||
|
||||
public EntityPositionOverlay(IEntityLookup lookup, IEyeManager eyeManager, IEntityManager entityManager)
|
||||
public EntityPositionOverlay(EntityLookupSystem lookup, IEyeManager eyeManager, IEntityManager entityManager)
|
||||
{
|
||||
_lookup = lookup;
|
||||
_eyeManager = eyeManager;
|
||||
@@ -61,13 +65,11 @@ namespace Robust.Client.Debugging
|
||||
|
||||
var worldHandle = (DrawingHandleWorld) args.DrawingHandle;
|
||||
var viewport = _eyeManager.GetWorldViewport();
|
||||
var xformQuery = _entityManager.GetEntityQuery<TransformComponent>();
|
||||
|
||||
foreach (var entity in _lookup.GetEntitiesIntersecting(_eyeManager.CurrentMap, viewport))
|
||||
{
|
||||
var transform = _entityManager.GetComponent<TransformComponent>(entity);
|
||||
|
||||
var center = transform.WorldPosition;
|
||||
var worldRotation = transform.WorldRotation;
|
||||
var (center, worldRotation) = xformQuery.GetComponent(entity).GetWorldPositionRotation();
|
||||
|
||||
var xLine = worldRotation.RotateVec(Vector2.UnitX);
|
||||
var yLine = worldRotation.RotateVec(Vector2.UnitY);
|
||||
@@ -207,10 +207,10 @@ namespace Robust.Client.Debugging
|
||||
|
||||
const float AlphaModifier = 0.2f;
|
||||
|
||||
foreach (var fixture in physBody.Fixtures)
|
||||
foreach (var fixture in _entityManager.GetComponent<FixturesComponent>(physBody.Owner).Fixtures.Values)
|
||||
{
|
||||
// Invalid shape - Box2D doesn't check for IsSensor
|
||||
if (physBody.BodyType == BodyType.Dynamic && fixture.Mass == 0f)
|
||||
// Invalid shape - Box2D doesn't check for IsSensor but we will for sanity.
|
||||
if (physBody.BodyType == BodyType.Dynamic && fixture.Mass == 0f && fixture.Hard)
|
||||
{
|
||||
DrawShape(worldHandle, fixture, xform, Color.Red.WithAlpha(AlphaModifier));
|
||||
}
|
||||
@@ -274,7 +274,7 @@ namespace Robust.Client.Debugging
|
||||
const float AlphaModifier = 0.2f;
|
||||
Box2? aabb = null;
|
||||
|
||||
foreach (var fixture in physBody.Fixtures)
|
||||
foreach (var fixture in _entityManager.GetComponent<FixturesComponent>(physBody.Owner).Fixtures.Values)
|
||||
{
|
||||
for (var i = 0; i < fixture.Shape.ChildCount; i++)
|
||||
{
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
namespace Robust.Client.Debugging
|
||||
{
|
||||
/// <summary>
|
||||
/// A collection of visual debug overlays for the client game.
|
||||
/// </summary>
|
||||
public interface IDebugDrawing
|
||||
{
|
||||
/// <summary>
|
||||
/// Toggles the visual overlay of the local origin for each entity on screen.
|
||||
/// </summary>
|
||||
bool DebugPositions { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ namespace Robust.Client
|
||||
{
|
||||
internal partial class GameController
|
||||
{
|
||||
internal class LoaderEntryPoint : ILoaderEntryPoint
|
||||
internal sealed class LoaderEntryPoint : ILoaderEntryPoint
|
||||
{
|
||||
public void Main(IMainArgs args)
|
||||
{
|
||||
|
||||
@@ -50,7 +50,6 @@ namespace Robust.Client
|
||||
[Dependency] private readonly IClientConsoleHost _console = default!;
|
||||
[Dependency] private readonly ITimerManager _timerManager = default!;
|
||||
[Dependency] private readonly IClientEntityManager _entityManager = default!;
|
||||
[Dependency] private readonly IEntityLookup _lookup = default!;
|
||||
[Dependency] private readonly IPlacementManager _placementManager = default!;
|
||||
[Dependency] private readonly IClientGameStateManager _gameStateManager = default!;
|
||||
[Dependency] private readonly IOverlayManagerInternal _overlayManager = default!;
|
||||
@@ -134,8 +133,8 @@ namespace Robust.Client
|
||||
_prototypeManager.Initialize();
|
||||
_prototypeManager.LoadDirectory(Options.PrototypeDirectory);
|
||||
_prototypeManager.Resync();
|
||||
_mapManager.Initialize();
|
||||
_entityManager.Initialize();
|
||||
_mapManager.Initialize();
|
||||
_gameStateManager.Initialize();
|
||||
_placementManager.Initialize();
|
||||
_viewVariablesManager.Initialize();
|
||||
@@ -339,6 +338,14 @@ namespace Robust.Client
|
||||
|
||||
if (_loaderArgs != null)
|
||||
{
|
||||
if (_loaderArgs.ApiMounts is { } mounts)
|
||||
{
|
||||
foreach (var (api, prefix) in mounts)
|
||||
{
|
||||
_resourceCache.MountLoaderApi(api, "", new ResourcePath(prefix));
|
||||
}
|
||||
}
|
||||
|
||||
_stringSerializer.EnableCaching = false;
|
||||
_resourceCache.MountLoaderApi(_loaderArgs.FileApi, "Resources/");
|
||||
_modLoader.VerifierExtraLoadHandler = VerifierExtraLoadHandler;
|
||||
@@ -447,6 +454,7 @@ namespace Robust.Client
|
||||
private void Tick(FrameEventArgs frameEventArgs)
|
||||
{
|
||||
_modLoader.BroadcastUpdate(ModUpdateLevel.PreEngine, frameEventArgs);
|
||||
_console.CommandBufferExecute();
|
||||
_timerManager.UpdateTimers(frameEventArgs);
|
||||
_taskManager.ProcessPendingTasks();
|
||||
|
||||
@@ -459,8 +467,9 @@ namespace Robust.Client
|
||||
// In singleplayer, however, we're in full control instead.
|
||||
else if (_client.RunLevel == ClientRunLevel.SinglePlayerGame)
|
||||
{
|
||||
// The last real tick is the current tick! This way we won't be in "prediction" mode.
|
||||
_gameTiming.LastRealTick = _gameTiming.CurTick;
|
||||
_entityManager.TickUpdate(frameEventArgs.DeltaSeconds, noPredictions: false);
|
||||
_lookup.Update();
|
||||
}
|
||||
|
||||
_modLoader.BroadcastUpdate(ModUpdateLevel.PostEngine, frameEventArgs);
|
||||
@@ -500,7 +509,7 @@ namespace Robust.Client
|
||||
logManager.GetSawmill("discord").Level = LogLevel.Warning;
|
||||
logManager.GetSawmill("net.predict").Level = LogLevel.Info;
|
||||
logManager.GetSawmill("szr").Level = LogLevel.Info;
|
||||
logManager.GetSawmill("loc").Level = LogLevel.Error;
|
||||
logManager.GetSawmill("loc").Level = LogLevel.Warning;
|
||||
|
||||
#if DEBUG_ONLY_FCE_INFO
|
||||
#if DEBUG_ONLY_FCE_LOG
|
||||
@@ -565,7 +574,6 @@ namespace Robust.Client
|
||||
|
||||
_networkManager.Shutdown("Client shutting down");
|
||||
_midiManager.Shutdown();
|
||||
IoCManager.Resolve<IEntityLookup>().Shutdown();
|
||||
_entityManager.Shutdown();
|
||||
_clyde.Shutdown();
|
||||
_clydeAudio.Shutdown();
|
||||
|
||||
@@ -3,7 +3,7 @@ using Robust.Shared.Utility;
|
||||
|
||||
namespace Robust.Client
|
||||
{
|
||||
public class GameControllerOptions
|
||||
public sealed class GameControllerOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Whether content sandboxing will be enabled & enforced.
|
||||
|
||||
@@ -6,7 +6,7 @@ using Robust.Shared.Reflection;
|
||||
|
||||
namespace Robust.Client.GameObjects
|
||||
{
|
||||
internal class ClientComponentFactory : ComponentFactory
|
||||
internal sealed class ClientComponentFactory : ComponentFactory
|
||||
{
|
||||
public ClientComponentFactory(IDynamicTypeFactoryInternal typeFactory, IReflectionManager reflectionManager, IConsoleHost conHost)
|
||||
: base(typeFactory, reflectionManager, conHost)
|
||||
@@ -29,13 +29,9 @@ namespace Robust.Client.GameObjects
|
||||
RegisterClass<EyeComponent>();
|
||||
RegisterClass<AnimationPlayerComponent>();
|
||||
RegisterClass<TimerComponent>();
|
||||
|
||||
#if DEBUG
|
||||
RegisterClass<DebugExceptionOnAddComponent>();
|
||||
RegisterClass<DebugExceptionInitializeComponent>();
|
||||
RegisterClass<DebugExceptionStartupComponent>();
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ namespace Robust.Client.GameObjects
|
||||
public override void Initialize()
|
||||
{
|
||||
SetupNetworking();
|
||||
ReceivedComponentMessage += (_, compMsg) => DispatchComponentMessage(compMsg);
|
||||
ReceivedSystemMessage += (_, systemMsg) => EventBus.RaiseEvent(EventSource.Network, systemMsg);
|
||||
|
||||
base.Initialize();
|
||||
@@ -52,9 +51,6 @@ namespace Robust.Client.GameObjects
|
||||
|
||||
public override IEntityNetworkManager EntityNetManager => this;
|
||||
|
||||
/// <inheritdoc />
|
||||
public event EventHandler<NetworkComponentMessage>? ReceivedComponentMessage;
|
||||
|
||||
/// <inheritdoc />
|
||||
public event EventHandler<object>? ReceivedSystemMessage;
|
||||
|
||||
@@ -105,25 +101,6 @@ namespace Robust.Client.GameObjects
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[Obsolete("Component Messages are deprecated, use Entity Events instead.")]
|
||||
public void SendComponentNetworkMessage(INetChannel? channel, EntityUid entity, IComponent component, ComponentMessage message)
|
||||
{
|
||||
var netId = ComponentFactory.GetRegistration(component.GetType()).NetID;
|
||||
|
||||
if (!netId.HasValue)
|
||||
throw new ArgumentException($"Component {component.Name} does not have a NetID.", nameof(component));
|
||||
|
||||
var msg = _networkManager.CreateNetMessage<MsgEntity>();
|
||||
msg.Type = EntityMessageType.ComponentMessage;
|
||||
msg.EntityUid = entity;
|
||||
msg.NetId = netId.Value;
|
||||
msg.ComponentMessage = message;
|
||||
msg.SourceTick = _gameTiming.CurTick;
|
||||
|
||||
_networkManager.ClientSendMessage(msg);
|
||||
}
|
||||
|
||||
private void HandleEntityNetworkMessage(MsgEntity message)
|
||||
{
|
||||
if (message.SourceTick <= _gameStateManager.CurServerTick)
|
||||
@@ -142,10 +119,6 @@ namespace Robust.Client.GameObjects
|
||||
{
|
||||
switch (message.Type)
|
||||
{
|
||||
case EntityMessageType.ComponentMessage:
|
||||
ReceivedComponentMessage?.Invoke(this, new NetworkComponentMessage(message));
|
||||
return;
|
||||
|
||||
case EntityMessageType.SystemMessage:
|
||||
var msg = message.SystemMessage;
|
||||
var sessionType = typeof(EntitySessionMessage<>).MakeGenericType(msg.GetType());
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Runtime.Serialization;
|
||||
namespace Robust.Client.GameObjects
|
||||
{
|
||||
[Serializable]
|
||||
[Virtual]
|
||||
public class ComponentStateApplyException : Exception
|
||||
{
|
||||
public ComponentStateApplyException()
|
||||
|
||||
@@ -13,8 +13,6 @@ namespace Robust.Client.GameObjects
|
||||
{
|
||||
// TODO: Give this component a friend someday. Way too much content shit to change atm ._.
|
||||
|
||||
public override string Name => "AnimationPlayer";
|
||||
|
||||
public int PlayingAnimationCount => PlayingAnimations.Count;
|
||||
|
||||
internal readonly Dictionary<string, AnimationPlayback> PlayingAnimations
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Robust.Shared.GameObjects;
|
||||
using System;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
|
||||
namespace Robust.Client.GameObjects;
|
||||
@@ -14,6 +15,7 @@ public abstract class AppearanceVisualizer
|
||||
/// Initializes an entity to be managed by this appearance controller.
|
||||
/// DO NOT assume this is your only entity. Visualizers are shared.
|
||||
/// </summary>
|
||||
[Obsolete("Subscribe to your component being initialised instead.")]
|
||||
public virtual void InitializeEntity(EntityUid entity)
|
||||
{
|
||||
}
|
||||
@@ -23,6 +25,7 @@ public abstract class AppearanceVisualizer
|
||||
/// Update its visuals here.
|
||||
/// </summary>
|
||||
/// <param name="component">The appearance component of the entity that might need updating.</param>
|
||||
[Obsolete("Subscribe to AppearanceChangeEvent instead.")]
|
||||
public virtual void OnChangeData(AppearanceComponent component)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using Robust.Shared.Analyzers;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.ViewVariables;
|
||||
@@ -9,39 +10,10 @@ namespace Robust.Client.GameObjects;
|
||||
/// This is the client instance of <see cref="AppearanceComponent"/>.
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
[ComponentReference(typeof(AppearanceComponent))]
|
||||
[ComponentReference(typeof(AppearanceComponent)), Friend(typeof(AppearanceSystem))]
|
||||
public sealed class ClientAppearanceComponent : AppearanceComponent
|
||||
{
|
||||
[ViewVariables]
|
||||
private bool _appearanceDirty;
|
||||
|
||||
[ViewVariables]
|
||||
[DataField("visuals")]
|
||||
internal List<AppearanceVisualizer> Visualizers = new();
|
||||
|
||||
protected override void MarkDirty()
|
||||
{
|
||||
if (_appearanceDirty)
|
||||
return;
|
||||
|
||||
EntitySystem.Get<AppearanceSystem>().EnqueueUpdate(this);
|
||||
_appearanceDirty = true;
|
||||
}
|
||||
|
||||
protected override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
foreach (var visual in Visualizers)
|
||||
{
|
||||
visual.InitializeEntity(Owner);
|
||||
}
|
||||
|
||||
MarkDirty();
|
||||
}
|
||||
|
||||
internal void UnmarkDirty()
|
||||
{
|
||||
_appearanceDirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,14 +9,11 @@ using Robust.Shared.ViewVariables;
|
||||
namespace Robust.Client.GameObjects
|
||||
{
|
||||
[ComponentReference(typeof(SharedEyeComponent))]
|
||||
public class EyeComponent : SharedEyeComponent
|
||||
public sealed class EyeComponent : SharedEyeComponent
|
||||
{
|
||||
[Dependency] private readonly IEyeManager _eyeManager = default!;
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Name => "Eye";
|
||||
|
||||
[ViewVariables]
|
||||
private Eye? _eye = default!;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.ResourceManagement;
|
||||
using Robust.Client.Utility;
|
||||
using Robust.Shared.GameObjects;
|
||||
@@ -12,9 +12,8 @@ using Robust.Shared.Utility;
|
||||
namespace Robust.Client.GameObjects
|
||||
{
|
||||
[RegisterComponent]
|
||||
public class IconComponent : Component, ISerializationHooks
|
||||
public sealed class IconComponent : Component, ISerializationHooks
|
||||
{
|
||||
public override string Name => "Icon";
|
||||
public IDirectionalTextureProvider? Icon { get; private set; }
|
||||
|
||||
[DataField("sprite")]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Input;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.ViewVariables;
|
||||
@@ -8,11 +8,8 @@ namespace Robust.Client.GameObjects
|
||||
/// <summary>
|
||||
/// Defines data fields used in the <see cref="InputSystem"/>.
|
||||
/// </summary>
|
||||
public class InputComponent : Component
|
||||
public sealed class InputComponent : Component
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Name => "Input";
|
||||
|
||||
/// <summary>
|
||||
/// The context that will be made active for a client that attaches to this entity.
|
||||
/// </summary>
|
||||
|
||||
@@ -8,7 +8,7 @@ using Robust.Shared.ViewVariables;
|
||||
namespace Robust.Client.GameObjects
|
||||
{
|
||||
[ComponentReference(typeof(OccluderComponent))]
|
||||
internal sealed class ClientOccluderComponent : OccluderComponent
|
||||
public sealed class ClientOccluderComponent : OccluderComponent
|
||||
{
|
||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
@@ -40,13 +40,14 @@ namespace Robust.Client.GameObjects
|
||||
|
||||
public void AnchorStateChanged()
|
||||
{
|
||||
SendDirty();
|
||||
var xform = _entityManager.GetComponent<TransformComponent>(Owner);
|
||||
SendDirty(xform);
|
||||
|
||||
if(!_entityManager.GetComponent<TransformComponent>(Owner).Anchored)
|
||||
if(!xform.Anchored)
|
||||
return;
|
||||
|
||||
var grid = _mapManager.GetGrid(_entityManager.GetComponent<TransformComponent>(Owner).GridID);
|
||||
_lastPosition = (_entityManager.GetComponent<TransformComponent>(Owner).GridID, grid.TileIndicesFor(_entityManager.GetComponent<TransformComponent>(Owner).Coordinates));
|
||||
var grid = _mapManager.GetGrid(xform.GridID);
|
||||
_lastPosition = (xform.GridID, grid.TileIndicesFor(xform.Coordinates));
|
||||
}
|
||||
|
||||
protected override void Shutdown()
|
||||
@@ -56,9 +57,10 @@ namespace Robust.Client.GameObjects
|
||||
SendDirty();
|
||||
}
|
||||
|
||||
private void SendDirty()
|
||||
private void SendDirty(TransformComponent? xform = null)
|
||||
{
|
||||
if (_entityManager.GetComponent<TransformComponent>(Owner).Anchored)
|
||||
xform ??= _entityManager.GetComponent<TransformComponent>(Owner);
|
||||
if (xform.Anchored)
|
||||
{
|
||||
_entityManager.EventBus.RaiseEvent(EventSource.Local,
|
||||
new OccluderDirtyEvent(Owner, _lastPosition));
|
||||
@@ -69,13 +71,29 @@ namespace Robust.Client.GameObjects
|
||||
{
|
||||
Occluding = OccluderDir.None;
|
||||
|
||||
if (Deleted || !_entityManager.GetComponent<TransformComponent>(Owner).Anchored)
|
||||
if (Deleted)
|
||||
return;
|
||||
|
||||
// Content may want to override the default behavior for occlusion.
|
||||
var xform = _entityManager.GetComponent<TransformComponent>(Owner);
|
||||
var ev = new OccluderDirectionsEvent
|
||||
{
|
||||
Component = xform,
|
||||
};
|
||||
|
||||
_entityManager.EventBus.RaiseLocalEvent(Owner, ref ev);
|
||||
|
||||
if (ev.Handled)
|
||||
{
|
||||
Occluding = ev.Directions;
|
||||
return;
|
||||
}
|
||||
|
||||
var grid = _mapManager.GetGrid(_entityManager.GetComponent<TransformComponent>(Owner).GridID);
|
||||
var position = _entityManager.GetComponent<TransformComponent>(Owner).Coordinates;
|
||||
if (!xform.Anchored)
|
||||
return;
|
||||
|
||||
var grid = _mapManager.GetGrid(xform.GridID);
|
||||
var position = xform.Coordinates;
|
||||
void CheckDir(Direction dir, OccluderDir oclDir)
|
||||
{
|
||||
foreach (var neighbor in grid.GetInDir(position, dir))
|
||||
@@ -88,7 +106,7 @@ namespace Robust.Client.GameObjects
|
||||
}
|
||||
}
|
||||
|
||||
var angle = _entityManager.GetComponent<TransformComponent>(Owner).LocalRotation;
|
||||
var angle = xform.LocalRotation;
|
||||
var dirRolling = angle.GetCardinalDir();
|
||||
// dirRolling starts at effective south
|
||||
|
||||
@@ -103,15 +121,28 @@ namespace Robust.Client.GameObjects
|
||||
|
||||
CheckDir(dirRolling, OccluderDir.East);
|
||||
}
|
||||
}
|
||||
|
||||
[Flags]
|
||||
internal enum OccluderDir : byte
|
||||
{
|
||||
None = 0,
|
||||
North = 1,
|
||||
East = 1 << 1,
|
||||
South = 1 << 2,
|
||||
West = 1 << 3,
|
||||
}
|
||||
[Flags]
|
||||
public enum OccluderDir : byte
|
||||
{
|
||||
None = 0,
|
||||
North = 1,
|
||||
East = 1 << 1,
|
||||
South = 1 << 2,
|
||||
West = 1 << 3,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raised by occluders when trying to get occlusion directions.
|
||||
/// </summary>
|
||||
[ByRefEvent]
|
||||
public struct OccluderDirectionsEvent
|
||||
{
|
||||
public bool Handled = false;
|
||||
public OccluderDir Directions = OccluderDir.None;
|
||||
public TransformComponent Component = default!;
|
||||
|
||||
public OccluderDirectionsEvent() {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace Robust.Client.GameObjects
|
||||
{
|
||||
[RegisterComponent]
|
||||
[ComponentReference(typeof(SharedPointLightComponent))]
|
||||
public class PointLightComponent : SharedPointLightComponent, ISerializationHooks
|
||||
public sealed class PointLightComponent : SharedPointLightComponent, ISerializationHooks
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
|
||||
@@ -96,26 +96,6 @@ namespace Robust.Client.GameObjects
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public Texture? Mask { get; set; }
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[Animatable]
|
||||
public float Energy
|
||||
{
|
||||
get => _energy;
|
||||
set => _energy = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Soft shadow strength multiplier.
|
||||
/// Has no effect if soft shadows are not enabled.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[Animatable]
|
||||
public float Softness
|
||||
{
|
||||
get => _softness;
|
||||
set => _softness = value;
|
||||
}
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public bool VisibleNested
|
||||
{
|
||||
@@ -134,10 +114,7 @@ namespace Robust.Client.GameObjects
|
||||
[DataField("autoRot")]
|
||||
private bool _maskAutoRotate;
|
||||
private Angle _rotation;
|
||||
[DataField("energy")]
|
||||
private float _energy = 1f;
|
||||
[DataField("softness")]
|
||||
private float _softness = 1f;
|
||||
|
||||
[DataField("mask")]
|
||||
internal string? _maskPath;
|
||||
|
||||
@@ -162,7 +139,7 @@ namespace Robust.Client.GameObjects
|
||||
internal RenderingTreeComponent? RenderTree { get; set; }
|
||||
}
|
||||
|
||||
public class PointLightRadiusChangedEvent : EntityEventArgs
|
||||
public sealed class PointLightRadiusChangedEvent : EntityEventArgs
|
||||
{
|
||||
public PointLightComponent PointLightComponent { get; }
|
||||
|
||||
|
||||
@@ -25,6 +25,8 @@ namespace Robust.Client.GameObjects
|
||||
[Animatable]
|
||||
Vector2 Scale { get; set; }
|
||||
|
||||
Box2 Bounds { get; }
|
||||
|
||||
/// <summary>
|
||||
/// A rotation applied to all layers.
|
||||
/// </summary>
|
||||
@@ -119,7 +121,8 @@ namespace Robust.Client.GameObjects
|
||||
/// This is useful to allow layer map configs to be defined in prototypes,
|
||||
/// while still allowing code to create configs if they're absent.
|
||||
/// </remarks>
|
||||
void LayerMapReserveBlank(object key);
|
||||
/// <returns>Index of the new layer.</returns>
|
||||
int LayerMapReserveBlank(object key);
|
||||
|
||||
/// <summary>
|
||||
/// Adds a layer without texture (thus falling back to the error texture).
|
||||
@@ -145,8 +148,8 @@ namespace Robust.Client.GameObjects
|
||||
void RemoveLayer(int layer);
|
||||
void RemoveLayer(object layerKey);
|
||||
|
||||
void LayerSetShader(int layer, ShaderInstance shader);
|
||||
void LayerSetShader(object layerKey, ShaderInstance shader);
|
||||
void LayerSetShader(int layer, ShaderInstance shader, string? prototype = null);
|
||||
void LayerSetShader(object layerKey, ShaderInstance shader, string? prototype = null);
|
||||
void LayerSetShader(int layer, string shaderName);
|
||||
void LayerSetShader(object layerKey, string shaderName);
|
||||
|
||||
@@ -217,8 +220,8 @@ namespace Robust.Client.GameObjects
|
||||
int GetLayerDirectionCount(ISpriteLayer layer);
|
||||
|
||||
/// <summary>
|
||||
/// Calculate sprite bounding box in world-space coordinates.
|
||||
/// Calculate the rotated sprite bounding box in world-space coordinates.
|
||||
/// </summary>
|
||||
Box2 CalculateBoundingBox(Vector2 worldPos);
|
||||
Box2Rotated CalculateRotatedBoundingBox(Vector2 worldPosition, Angle worldRotation, IEye? eye = null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,8 +25,6 @@ namespace Robust.Client.GameObjects
|
||||
|
||||
RSI.State.Direction EffectiveDirection(Angle worldRotation);
|
||||
|
||||
Vector2 LocalToLayer(Vector2 localPos);
|
||||
|
||||
/// <summary>
|
||||
/// Layer size in pixels.
|
||||
/// Don't account layer scale or sprite world transform.
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace Robust.Client.GameObjects
|
||||
private bool _enabled;
|
||||
}
|
||||
|
||||
public class SpriteBoundsOverlay : Overlay
|
||||
public sealed class SpriteBoundsOverlay : Overlay
|
||||
{
|
||||
public override OverlaySpace Space => OverlaySpace.WorldSpace;
|
||||
|
||||
@@ -84,10 +84,16 @@ namespace Robust.Client.GameObjects
|
||||
|
||||
foreach (var sprite in comp.SpriteTree.QueryAabb(localAABB))
|
||||
{
|
||||
var worldPos = _entityManager.GetComponent<TransformComponent>(sprite.Owner).WorldPosition;
|
||||
var bounds = sprite.CalculateBoundingBox(worldPos);
|
||||
var (worldPos, worldRot) = _entityManager.GetComponent<TransformComponent>(sprite.Owner).GetWorldPositionRotation();
|
||||
var bounds = sprite.CalculateRotatedBoundingBox(worldPos, worldRot);
|
||||
|
||||
// Get scaled down bounds used to indicate the "south" of a sprite.
|
||||
var localBound = bounds.Box;
|
||||
var smallLocal = localBound.Scale(0.2f).Translated(-new Vector2(0f, localBound.Extents.Y));
|
||||
var southIndicator = new Box2Rotated(smallLocal, bounds.Rotation, bounds.Origin);
|
||||
|
||||
handle.DrawRect(bounds, Color.Red.WithAlpha(0.2f));
|
||||
handle.DrawRect(bounds.Scale(0.2f).Translated(-new Vector2(0f, bounds.Extents.Y)), Color.Blue.WithAlpha(0.5f));
|
||||
handle.DrawRect(southIndicator, Color.Blue.WithAlpha(0.5f));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -6,8 +6,6 @@ namespace Robust.Client.GameObjects
|
||||
[RegisterComponent]
|
||||
public sealed class RenderingTreeComponent : Component
|
||||
{
|
||||
public override string Name => "RenderingTree";
|
||||
|
||||
internal DynamicTree<SpriteComponent> SpriteTree { get; set; } = default!;
|
||||
internal DynamicTree<PointLightComponent> LightTree { get; set; } = default!;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ using Robust.Shared.ViewVariables;
|
||||
namespace Robust.Client.GameObjects
|
||||
{
|
||||
[ComponentReference(typeof(SharedUserInterfaceComponent))]
|
||||
public class ClientUserInterfaceComponent : SharedUserInterfaceComponent, ISerializationHooks
|
||||
public sealed class ClientUserInterfaceComponent : SharedUserInterfaceComponent, ISerializationHooks
|
||||
{
|
||||
[Dependency] private readonly IReflectionManager _reflectionManager = default!;
|
||||
[Dependency] private readonly IDynamicTypeFactory _dynamicTypeFactory = default!;
|
||||
|
||||
@@ -62,6 +62,12 @@ namespace Robust.Client.GameObjects
|
||||
Play(component, animation, key);
|
||||
}
|
||||
|
||||
public void Play(EntityUid uid, AnimationPlayerComponent? component, Animation animation, string key)
|
||||
{
|
||||
component ??= EntityManager.EnsureComponent<AnimationPlayerComponent>(uid);
|
||||
Play(component, animation, key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start playing an animation.
|
||||
/// </summary>
|
||||
@@ -79,6 +85,14 @@ namespace Robust.Client.GameObjects
|
||||
component.PlayingAnimations.ContainsKey(key);
|
||||
}
|
||||
|
||||
public bool HasRunningAnimation(EntityUid uid, AnimationPlayerComponent? component, string key)
|
||||
{
|
||||
if (component == null)
|
||||
TryComp(uid, out component);
|
||||
|
||||
return component != null && component.PlayingAnimations.ContainsKey(key);
|
||||
}
|
||||
|
||||
public bool HasRunningAnimation(AnimationPlayerComponent component, string key)
|
||||
{
|
||||
return component.PlayingAnimations.ContainsKey(key);
|
||||
@@ -88,6 +102,18 @@ namespace Robust.Client.GameObjects
|
||||
{
|
||||
component.PlayingAnimations.Remove(key);
|
||||
}
|
||||
|
||||
public void Stop(EntityUid uid, string key)
|
||||
{
|
||||
if (!TryComp<AnimationPlayerComponent>(uid, out var player)) return;
|
||||
player.PlayingAnimations.Remove(key);
|
||||
}
|
||||
|
||||
public void Stop(EntityUid uid, AnimationPlayerComponent? component, string key)
|
||||
{
|
||||
if (!Resolve(uid, ref component, false)) return;
|
||||
component.PlayingAnimations.Remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class AnimationCompletedEvent : EntityEventArgs
|
||||
|
||||
@@ -1,17 +1,95 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Robust.Client.GameObjects
|
||||
{
|
||||
[UsedImplicitly]
|
||||
internal sealed class AppearanceSystem : EntitySystem
|
||||
public sealed class AppearanceSystem : SharedAppearanceSystem
|
||||
{
|
||||
private readonly Queue<ClientAppearanceComponent> _queuedUpdates = new();
|
||||
|
||||
public void EnqueueUpdate(ClientAppearanceComponent component)
|
||||
public override void Initialize()
|
||||
{
|
||||
_queuedUpdates.Enqueue(component);
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<ClientAppearanceComponent, ComponentInit>(OnAppearanceInit);
|
||||
SubscribeLocalEvent<ClientAppearanceComponent, ComponentHandleState>(OnAppearanceHandleState);
|
||||
}
|
||||
|
||||
private void OnAppearanceInit(EntityUid uid, ClientAppearanceComponent component, ComponentInit args)
|
||||
{
|
||||
foreach (var visual in component.Visualizers)
|
||||
{
|
||||
visual.InitializeEntity(uid);
|
||||
}
|
||||
|
||||
MarkDirty(component);
|
||||
}
|
||||
|
||||
private void OnAppearanceHandleState(EntityUid uid, ClientAppearanceComponent component, ref ComponentHandleState args)
|
||||
{
|
||||
if (args.Current is not AppearanceComponentState actualState)
|
||||
return;
|
||||
|
||||
var stateDiff = component.AppearanceData.Count != actualState.Data.Count;
|
||||
|
||||
if (!stateDiff)
|
||||
{
|
||||
foreach (var (key, value) in component.AppearanceData)
|
||||
{
|
||||
if (!actualState.Data.TryGetValue(key, out var stateValue) ||
|
||||
!value.Equals(stateValue))
|
||||
{
|
||||
stateDiff = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!stateDiff) return;
|
||||
|
||||
component.AppearanceData = CloneAppearanceData(actualState.Data);
|
||||
MarkDirty(component);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Take in an appearance data dictionary and attempt to clone it.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// As some appearance data values are not simple value-type objects, this is not just a shallow clone.
|
||||
/// </remarks>
|
||||
private Dictionary<object, object> CloneAppearanceData(Dictionary<object, object> data)
|
||||
{
|
||||
Dictionary<object, object> newDict = new(data.Count);
|
||||
|
||||
foreach (var (key, value) in data)
|
||||
{
|
||||
if (value.GetType().IsValueType)
|
||||
newDict[key] = value;
|
||||
else if (value is ICloneable cloneable)
|
||||
newDict[key] = cloneable.Clone();
|
||||
else
|
||||
throw new NotSupportedException("Invalid object in appearance data dictionary. Appearance data must be cloneable");
|
||||
}
|
||||
|
||||
return newDict;
|
||||
}
|
||||
|
||||
public override void MarkDirty(AppearanceComponent component)
|
||||
{
|
||||
if (component.AppearanceDirty)
|
||||
return;
|
||||
|
||||
_queuedUpdates.Enqueue((ClientAppearanceComponent) component);
|
||||
component.AppearanceDirty = true;
|
||||
}
|
||||
|
||||
internal void UnmarkDirty(ClientAppearanceComponent component)
|
||||
{
|
||||
component.AppearanceDirty = false;
|
||||
}
|
||||
|
||||
public override void FrameUpdate(float frameTime)
|
||||
@@ -19,10 +97,10 @@ namespace Robust.Client.GameObjects
|
||||
while (_queuedUpdates.TryDequeue(out var appearance))
|
||||
{
|
||||
if (appearance.Deleted)
|
||||
return;
|
||||
continue;
|
||||
|
||||
OnChangeData(appearance.Owner, appearance);
|
||||
appearance.UnmarkDirty();
|
||||
UnmarkDirty(appearance);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,10 +108,30 @@ namespace Robust.Client.GameObjects
|
||||
{
|
||||
if (!Resolve(uid, ref appearanceComponent, false)) return;
|
||||
|
||||
var ev = new AppearanceChangeEvent
|
||||
{
|
||||
Component = appearanceComponent,
|
||||
AppearanceData = appearanceComponent.AppearanceData,
|
||||
};
|
||||
|
||||
// Give it AppearanceData so we can still keep the friend attribute on the component.
|
||||
EntityManager.EventBus.RaiseLocalEvent(uid, ref ev);
|
||||
|
||||
// Eventually visualizers would be nuked and we'd just make them components instead.
|
||||
foreach (var visualizer in appearanceComponent.Visualizers)
|
||||
{
|
||||
visualizer.OnChangeData(appearanceComponent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raised whenever the appearance data for an entity changes.
|
||||
/// </summary>
|
||||
[ByRefEvent]
|
||||
public struct AppearanceChangeEvent
|
||||
{
|
||||
public AppearanceComponent Component;
|
||||
public IReadOnlyDictionary<object, object> AppearanceData;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ using Robust.Shared.Utility;
|
||||
namespace Robust.Client.GameObjects
|
||||
{
|
||||
[UsedImplicitly]
|
||||
public class AudioSystem : SharedAudioSystem, IAudioSystem
|
||||
public sealed class AudioSystem : SharedAudioSystem, IAudioSystem
|
||||
{
|
||||
[Dependency] private readonly IResourceCache _resourceCache = default!;
|
||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||
@@ -253,9 +253,15 @@ namespace Robust.Client.GameObjects
|
||||
/// </summary>
|
||||
/// <param name="stream">The audio stream to play.</param>
|
||||
/// <param name="audioParams"></param>
|
||||
private IPlayingAudioStream Play(AudioStream stream, AudioParams? audioParams = null)
|
||||
private IPlayingAudioStream? Play(AudioStream stream, AudioParams? audioParams = null)
|
||||
{
|
||||
var source = _clyde.CreateAudioSource(stream);
|
||||
|
||||
if (source == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
ApplyAudioParams(audioParams, source);
|
||||
|
||||
source.SetGlobal();
|
||||
@@ -303,6 +309,12 @@ namespace Robust.Client.GameObjects
|
||||
AudioParams? audioParams = null)
|
||||
{
|
||||
var source = _clyde.CreateAudioSource(stream);
|
||||
|
||||
if (source == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!source.SetPosition(EntityManager.GetComponent<TransformComponent>(entity).WorldPosition))
|
||||
{
|
||||
return Play(stream, fallbackCoordinates, fallbackCoordinates, audioParams);
|
||||
@@ -356,6 +368,12 @@ namespace Robust.Client.GameObjects
|
||||
EntityCoordinates fallbackCoordinates, AudioParams? audioParams = null)
|
||||
{
|
||||
var source = _clyde.CreateAudioSource(stream);
|
||||
|
||||
if (source == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!source.SetPosition(fallbackCoordinates.Position))
|
||||
{
|
||||
source.Dispose();
|
||||
@@ -402,7 +420,7 @@ namespace Robust.Client.GameObjects
|
||||
source.IsLooping = audioParams.Value.Loop;
|
||||
}
|
||||
|
||||
private class PlayingStream : IPlayingAudioStream
|
||||
private sealed class PlayingStream : IPlayingAudioStream
|
||||
{
|
||||
public uint? NetIdentifier;
|
||||
public IClydeAudioSource Source = default!;
|
||||
|
||||
@@ -72,10 +72,13 @@ namespace Robust.Client.GameObjects
|
||||
var sender = ev.Sender;
|
||||
if (EntityManager.EntityExists(sender) &&
|
||||
EntityManager.TryGetComponent(sender, out ClientOccluderComponent? iconSmooth)
|
||||
&& iconSmooth.Running)
|
||||
&& iconSmooth.Initialized)
|
||||
{
|
||||
var grid1 = _mapManager.GetGrid(EntityManager.GetComponent<TransformComponent>(sender).GridID);
|
||||
var coords = EntityManager.GetComponent<TransformComponent>(sender).Coordinates;
|
||||
var xform = EntityManager.GetComponent<TransformComponent>(sender);
|
||||
if (!_mapManager.TryGetGrid(xform.GridID, out var grid1))
|
||||
return;
|
||||
|
||||
var coords = xform.Coordinates;
|
||||
|
||||
_dirtyEntities.Enqueue(sender);
|
||||
AddValidEntities(grid1.GetInDir(coords, Direction.North));
|
||||
@@ -85,7 +88,7 @@ namespace Robust.Client.GameObjects
|
||||
}
|
||||
|
||||
// Entity is no longer valid, update around the last position it was at.
|
||||
if (ev.LastPosition.HasValue && _mapManager.TryGetGrid(ev.LastPosition.Value.grid, out var grid))
|
||||
else if (ev.LastPosition.HasValue && _mapManager.TryGetGrid(ev.LastPosition.Value.grid, out var grid))
|
||||
{
|
||||
var pos = ev.LastPosition.Value.pos;
|
||||
|
||||
|
||||
@@ -5,12 +5,14 @@ using Robust.Shared.Containers;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Serialization;
|
||||
using static Robust.Shared.Containers.ContainerManagerComponent;
|
||||
|
||||
namespace Robust.Client.GameObjects
|
||||
{
|
||||
public class ContainerSystem : SharedContainerSystem
|
||||
public sealed class ContainerSystem : SharedContainerSystem
|
||||
{
|
||||
[Dependency] private readonly IRobustSerializer _serializer = default!;
|
||||
[Dependency] private readonly IDynamicTypeFactoryInternal _dynFactory = default!;
|
||||
@@ -59,7 +61,7 @@ namespace Robust.Client.GameObjects
|
||||
{
|
||||
if (!cast.ContainerSet.Any(data => data.Id == id))
|
||||
{
|
||||
container.EmptyContainer(true);
|
||||
container.EmptyContainer(true, entMan: EntityManager);
|
||||
container.Shutdown();
|
||||
toDelete ??= new List<string>();
|
||||
toDelete.Add(id);
|
||||
@@ -131,12 +133,51 @@ namespace Robust.Client.GameObjects
|
||||
continue;
|
||||
}
|
||||
|
||||
// If an entity is currently in the shadow realm, it means we probably left PVS and are now getting
|
||||
// back into range. We do not want to directly insert this entity, as IF the container and entity
|
||||
// transform states did not get sent simultaneously, the entity's transform will be modified by the
|
||||
// insert operation. This means it will then be reset to the shadow realm, causing it to be ejected
|
||||
// from the container. It would then subsequently be parented to the container without ever being
|
||||
// re-inserted, leading to the client seeing what should be hidden entities attached to
|
||||
// containers/players.
|
||||
if (Transform(entity).MapID == MapId.Nullspace)
|
||||
{
|
||||
AddExpectedEntity(entity, container);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!container.ContainedEntities.Contains(entity))
|
||||
container.Insert(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void HandleParentChanged(ref EntParentChangedMessage message)
|
||||
{
|
||||
base.HandleParentChanged(ref message);
|
||||
|
||||
// If an entity warped in from null-space (i.e., re-entered PVS) and got attached to a container, do the same checks as for newly initialized entities.
|
||||
if (message.OldParent != null && message.OldParent.Value.IsValid())
|
||||
return;
|
||||
|
||||
if (!ExpectedEntities.TryGetValue(message.Entity, out var container))
|
||||
return;
|
||||
|
||||
if (Transform(message.Entity).ParentUid != container.Owner)
|
||||
{
|
||||
// This container is expecting an entity... but it got parented to some other entity???
|
||||
// Ah well, the sever should send a new container state that updates expected entities so just ignore it for now.
|
||||
return;
|
||||
}
|
||||
|
||||
RemoveExpectedEntity(message.Entity);
|
||||
|
||||
if (container.Deleted)
|
||||
return;
|
||||
|
||||
container.Insert(message.Entity);
|
||||
}
|
||||
|
||||
private IContainer ContainerFactory(ContainerManagerComponent component, string containerType, string id)
|
||||
{
|
||||
var type = _serializer.FindSerializedType(typeof(IContainer), containerType);
|
||||
@@ -169,68 +210,101 @@ namespace Robust.Client.GameObjects
|
||||
public override void FrameUpdate(float frameTime)
|
||||
{
|
||||
base.FrameUpdate(frameTime);
|
||||
var pointQuery = EntityManager.GetEntityQuery<PointLightComponent>();
|
||||
var spriteQuery = EntityManager.GetEntityQuery<SpriteComponent>();
|
||||
var xformQuery = EntityManager.GetEntityQuery<TransformComponent>();
|
||||
|
||||
foreach (var toUpdate in _updateQueue)
|
||||
{
|
||||
if (EntityManager.Deleted(toUpdate))
|
||||
{
|
||||
if (Deleted(toUpdate))
|
||||
continue;
|
||||
}
|
||||
|
||||
UpdateEntityRecursively(toUpdate);
|
||||
UpdateEntityRecursively(toUpdate, xformQuery, pointQuery, spriteQuery);
|
||||
}
|
||||
|
||||
_updateQueue.Clear();
|
||||
}
|
||||
|
||||
private void UpdateEntityRecursively(EntityUid entity)
|
||||
private void UpdateEntityRecursively(
|
||||
EntityUid entity,
|
||||
EntityQuery<TransformComponent> xformQuery,
|
||||
EntityQuery<PointLightComponent> pointQuery,
|
||||
EntityQuery<SpriteComponent> spriteQuery)
|
||||
{
|
||||
// TODO: Since we are recursing down,
|
||||
// we could cache ShowContents data here to speed it up for children.
|
||||
// Am lazy though.
|
||||
UpdateEntity(entity);
|
||||
// Recursively go up parents and containers to see whether both sprites and lights need to be occluded
|
||||
// Could maybe optimise this more by checking nearest parent that has sprite / light and whether it's container
|
||||
// occluded but this probably isn't a big perf issue.
|
||||
var xform = xformQuery.GetComponent(entity);
|
||||
var parent = xform.ParentUid;
|
||||
var child = entity;
|
||||
var spriteOccluded = false;
|
||||
var lightOccluded = false;
|
||||
|
||||
foreach (var child in EntityManager.GetComponent<TransformComponent>(entity).Children)
|
||||
while (parent.IsValid() && !spriteOccluded && !lightOccluded)
|
||||
{
|
||||
UpdateEntityRecursively(child.Owner);
|
||||
var parentXform = xformQuery.GetComponent(parent);
|
||||
if (TryComp<ContainerManagerComponent>(parent, out var manager) && manager.TryGetContainer(child, out var container))
|
||||
{
|
||||
spriteOccluded = spriteOccluded || !container.ShowContents;
|
||||
lightOccluded = lightOccluded || container.OccludesLight;
|
||||
}
|
||||
|
||||
child = parent;
|
||||
parent = parentXform.ParentUid;
|
||||
}
|
||||
|
||||
// Alright so
|
||||
// This is the CBT bit.
|
||||
// The issue is we need to go through the children and re-check whether they are or are not contained.
|
||||
// if they are contained then the occlusion values may need updating for all those children
|
||||
UpdateEntity(entity, xform, xformQuery, pointQuery, spriteQuery, spriteOccluded, lightOccluded);
|
||||
}
|
||||
|
||||
private void UpdateEntity(EntityUid entity)
|
||||
private void UpdateEntity(
|
||||
EntityUid entity,
|
||||
TransformComponent xform,
|
||||
EntityQuery<TransformComponent> xformQuery,
|
||||
EntityQuery<PointLightComponent> pointQuery,
|
||||
EntityQuery<SpriteComponent> spriteQuery,
|
||||
bool spriteOccluded,
|
||||
bool lightOccluded)
|
||||
{
|
||||
if (EntityManager.TryGetComponent(entity, out SpriteComponent? sprite))
|
||||
if (spriteQuery.TryGetComponent(entity, out var sprite))
|
||||
{
|
||||
sprite.ContainerOccluded = false;
|
||||
|
||||
// We have to recursively scan for containers upwards in case of nested containers.
|
||||
var tempParent = entity;
|
||||
while (tempParent.TryGetContainer(out var container))
|
||||
{
|
||||
if (!container.ShowContents)
|
||||
{
|
||||
sprite.ContainerOccluded = true;
|
||||
break;
|
||||
}
|
||||
|
||||
tempParent = container.Owner;
|
||||
}
|
||||
sprite.ContainerOccluded = spriteOccluded;
|
||||
}
|
||||
|
||||
if (EntityManager.TryGetComponent(entity, out PointLightComponent? light))
|
||||
if (pointQuery.TryGetComponent(entity, out var light))
|
||||
{
|
||||
light.ContainerOccluded = false;
|
||||
light.ContainerOccluded = lightOccluded;
|
||||
}
|
||||
|
||||
// We have to recursively scan for containers upwards in case of nested containers.
|
||||
var tempParent = entity;
|
||||
while (tempParent.TryGetContainer(out var container))
|
||||
var childEnumerator = xform.ChildEnumerator;
|
||||
|
||||
// Try to avoid TryComp if we already know stuff is occluded.
|
||||
if ((!spriteOccluded || !lightOccluded) && TryComp<ContainerManagerComponent>(entity, out var manager))
|
||||
{
|
||||
while (childEnumerator.MoveNext(out var child))
|
||||
{
|
||||
if (container.OccludesLight)
|
||||
// Thank god it's by value and not by ref.
|
||||
var childSpriteOccluded = spriteOccluded;
|
||||
var childLightOccluded = lightOccluded;
|
||||
|
||||
// We already know either sprite or light is not occluding so need to check container.
|
||||
if (manager.TryGetContainer(child.Value, out var container))
|
||||
{
|
||||
light.ContainerOccluded = true;
|
||||
break;
|
||||
childSpriteOccluded = childSpriteOccluded || !container.ShowContents;
|
||||
childLightOccluded = childLightOccluded || container.OccludesLight;
|
||||
}
|
||||
|
||||
tempParent = container.Owner;
|
||||
UpdateEntity(child.Value, xformQuery.GetComponent(child.Value), xformQuery, pointQuery, spriteQuery, childSpriteOccluded, childLightOccluded);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (childEnumerator.MoveNext(out var child))
|
||||
{
|
||||
UpdateEntity(child.Value, xformQuery.GetComponent(child.Value), xformQuery, pointQuery, spriteQuery, spriteOccluded, lightOccluded);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,133 +0,0 @@
|
||||
#if DEBUG
|
||||
using System;
|
||||
using System.Text;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Input;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
|
||||
namespace Robust.Client.GameObjects
|
||||
{
|
||||
internal sealed class DebugGridTileLookupSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IEyeManager _eyeManager = default!;
|
||||
[Dependency] private readonly IInputManager _inputManager = default!;
|
||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||
|
||||
public bool Enabled
|
||||
{
|
||||
get => _enabled;
|
||||
set
|
||||
{
|
||||
if (_enabled == value) return;
|
||||
_enabled = value;
|
||||
|
||||
if (_enabled)
|
||||
{
|
||||
_label.Visible = true;
|
||||
LastTile = default;
|
||||
}
|
||||
else
|
||||
{
|
||||
_label.Text = null;
|
||||
_label.Visible = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool _enabled;
|
||||
|
||||
private (GridId Grid, Vector2i Indices) LastTile;
|
||||
|
||||
// Label and shit that follows cursor
|
||||
private Label _label = new()
|
||||
{
|
||||
Visible = false,
|
||||
};
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeNetworkEvent<SendGridTileLookupMessage>(HandleSentEntities);
|
||||
IoCManager.Resolve<IUserInterfaceManager>().StateRoot.AddChild(_label);
|
||||
}
|
||||
|
||||
public override void Shutdown()
|
||||
{
|
||||
base.Shutdown();
|
||||
IoCManager.Resolve<IUserInterfaceManager>().StateRoot.RemoveChild(_label);
|
||||
}
|
||||
|
||||
private void RequestEntities(GridId gridId, Vector2i indices)
|
||||
{
|
||||
if (gridId == GridId.Invalid) return;
|
||||
RaiseNetworkEvent(new RequestGridTileLookupMessage(gridId, indices));
|
||||
}
|
||||
|
||||
private void HandleSentEntities(SendGridTileLookupMessage message)
|
||||
{
|
||||
if (!Enabled) return;
|
||||
var text = new StringBuilder();
|
||||
text.AppendLine($"GridId: {LastTile.Grid}, Tile: {LastTile.Indices}");
|
||||
|
||||
for (var i = 0; i < message.Entities.Count; i++)
|
||||
{
|
||||
var entity = message.Entities[i];
|
||||
|
||||
if (!EntityManager.EntityExists(entity)) continue;
|
||||
|
||||
text.AppendLine((string) EntityManager.ToPrettyString(entity));
|
||||
}
|
||||
|
||||
_label.Text = text.ToString();
|
||||
}
|
||||
|
||||
public override void FrameUpdate(float frameTime)
|
||||
{
|
||||
base.FrameUpdate(frameTime);
|
||||
if (!Enabled) return;
|
||||
|
||||
var mousePos = _inputManager.MouseScreenPosition;
|
||||
var worldPos = _eyeManager.ScreenToMap(mousePos);
|
||||
|
||||
GridId gridId;
|
||||
Vector2i tile;
|
||||
|
||||
if (_mapManager.TryFindGridAt(worldPos, out var grid))
|
||||
{
|
||||
gridId = grid.Index;
|
||||
tile = grid.WorldToTile(worldPos.Position);
|
||||
}
|
||||
else
|
||||
{
|
||||
gridId = GridId.Invalid;
|
||||
tile = new Vector2i((int) MathF.Floor(worldPos.Position.X), (int) MathF.Floor(worldPos.Position.Y));
|
||||
}
|
||||
|
||||
LayoutContainer.SetPosition(_label, mousePos.Position);
|
||||
|
||||
if ((gridId, tile).Equals(LastTile)) return;
|
||||
|
||||
_label.Text = null;
|
||||
LastTile = (gridId, tile);
|
||||
RequestEntities(gridId, tile);
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class RequestTileEntities : IConsoleCommand
|
||||
{
|
||||
public string Command => "tilelookup";
|
||||
public string Description => "Used for debugging GridTileLookupSystem";
|
||||
public string Help => $"{Command}";
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
EntitySystem.Get<DebugGridTileLookupSystem>().Enabled ^= true;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -25,7 +25,7 @@ namespace Robust.Client.GameObjects
|
||||
if (_enabled)
|
||||
{
|
||||
_lightOverlay = new DebugLightOverlay(
|
||||
IoCManager.Resolve<IEntityLookup>(),
|
||||
EntitySystem.Get<EntityLookupSystem>(),
|
||||
IoCManager.Resolve<IEyeManager>(),
|
||||
IoCManager.Resolve<IMapManager>(),
|
||||
Get<RenderingTreeSystem>());
|
||||
@@ -44,7 +44,7 @@ namespace Robust.Client.GameObjects
|
||||
|
||||
private sealed class DebugLightOverlay : Overlay
|
||||
{
|
||||
private IEntityLookup _lookup;
|
||||
private EntityLookupSystem _lookup;
|
||||
private IEyeManager _eyeManager;
|
||||
private IMapManager _mapManager;
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace Robust.Client.GameObjects
|
||||
|
||||
public override OverlaySpace Space => OverlaySpace.WorldSpace;
|
||||
|
||||
public DebugLightOverlay(IEntityLookup lookup, IEyeManager eyeManager, IMapManager mapManager, RenderingTreeSystem tree)
|
||||
public DebugLightOverlay(EntityLookupSystem lookup, IEyeManager eyeManager, IMapManager mapManager, RenderingTreeSystem tree)
|
||||
{
|
||||
_lookup = lookup;
|
||||
_eyeManager = eyeManager;
|
||||
@@ -72,7 +72,7 @@ namespace Robust.Client.GameObjects
|
||||
{
|
||||
foreach (var light in tree.LightTree)
|
||||
{
|
||||
var aabb = _lookup.GetWorldAabbFromEntity(light.Owner);
|
||||
var aabb = _lookup.GetWorldAABB(light.Owner);
|
||||
if (!aabb.Intersects(worldBounds)) continue;
|
||||
|
||||
args.WorldHandle.DrawRect(aabb, Color.Green.WithAlpha(0.1f));
|
||||
|
||||
@@ -15,7 +15,7 @@ using Robust.Shared.Enums;
|
||||
|
||||
namespace Robust.Client.GameObjects
|
||||
{
|
||||
public class EffectSystem : EntitySystem
|
||||
public sealed class EffectSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IGameTiming gameTiming = default!;
|
||||
[Dependency] private readonly IResourceCache resourceCache = default!;
|
||||
@@ -94,7 +94,7 @@ namespace Robust.Client.GameObjects
|
||||
}
|
||||
}
|
||||
|
||||
private class Effect
|
||||
private sealed class Effect
|
||||
{
|
||||
/// <summary>
|
||||
/// Effect Sprite
|
||||
@@ -323,7 +323,7 @@ namespace Robust.Client.GameObjects
|
||||
{
|
||||
private readonly IPlayerManager _playerManager;
|
||||
|
||||
public override OverlaySpace Space => OverlaySpace.WorldSpace;
|
||||
public override OverlaySpace Space => OverlaySpace.WorldSpaceBelowFOV;
|
||||
|
||||
private readonly ShaderInstance _unshadedShader;
|
||||
private readonly EffectSystem _owner;
|
||||
@@ -342,7 +342,6 @@ namespace Robust.Client.GameObjects
|
||||
var map = _owner.eyeManager.CurrentMap;
|
||||
|
||||
var worldHandle = args.WorldHandle;
|
||||
ShaderInstance? currentShader = null;
|
||||
|
||||
if (_playerManager.LocalPlayer?.ControlledEntity is not {} playerEnt)
|
||||
return;
|
||||
@@ -362,13 +361,8 @@ namespace Robust.Client.GameObjects
|
||||
continue;
|
||||
}
|
||||
|
||||
var newShader = effect.Shaded ? null : _unshadedShader;
|
||||
|
||||
if (newShader != currentShader)
|
||||
{
|
||||
worldHandle.UseShader(newShader);
|
||||
currentShader = newShader;
|
||||
}
|
||||
if (!effect.Shaded)
|
||||
worldHandle.UseShader(_unshadedShader);
|
||||
|
||||
// TODO: Should be doing matrix transformations
|
||||
var effectSprite = effect.EffectSprite;
|
||||
@@ -377,6 +371,9 @@ namespace Robust.Client.GameObjects
|
||||
(attachedXform?.Coordinates ?? effect.Coordinates)
|
||||
.Offset(effect.AttachedOffset);
|
||||
|
||||
// If we've never seen the entity before then can't resolve coordinates.
|
||||
if (!coordinates.IsValid(_entityManager)) continue;
|
||||
|
||||
// ???
|
||||
var rotation = attachedXform?.WorldRotation ?? _entityManager.GetComponent<TransformComponent>(coordinates.EntityId).WorldRotation;
|
||||
|
||||
@@ -386,6 +383,9 @@ namespace Robust.Client.GameObjects
|
||||
var rotatedBox = new Box2Rotated(effectArea, effect.Rotation + rotation, effectOrigin);
|
||||
|
||||
worldHandle.DrawTextureRect(effectSprite, rotatedBox, ToColor(effect.Color));
|
||||
|
||||
if (!effect.Shaded)
|
||||
worldHandle.UseShader(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace Robust.Client.GameObjects
|
||||
/// Updates the position of every Eye every frame, so that the camera follows the player around.
|
||||
/// </summary>
|
||||
[UsedImplicitly]
|
||||
public class EyeUpdateSystem : EntitySystem
|
||||
public sealed class EyeUpdateSystem : EntitySystem
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void Initialize()
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using System;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.GameObjects;
|
||||
@@ -11,8 +10,12 @@ using Robust.Shared.Utility;
|
||||
|
||||
namespace Robust.Client.GameObjects
|
||||
{
|
||||
public class GridChunkBoundsDebugSystem : EntitySystem
|
||||
public sealed class GridChunkBoundsDebugSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IEyeManager _eyeManager = default!;
|
||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||
[Dependency] private readonly IOverlayManager _overlayManager = default!;
|
||||
|
||||
private GridChunkBoundsOverlay? _overlay;
|
||||
|
||||
public bool Enabled
|
||||
@@ -29,14 +32,14 @@ namespace Robust.Client.GameObjects
|
||||
DebugTools.Assert(_overlay == null);
|
||||
_overlay = new GridChunkBoundsOverlay(
|
||||
EntityManager,
|
||||
IoCManager.Resolve<IEyeManager>(),
|
||||
IoCManager.Resolve<IMapManager>());
|
||||
_eyeManager,
|
||||
_mapManager);
|
||||
|
||||
IoCManager.Resolve<IOverlayManager>().AddOverlay(_overlay);
|
||||
_overlayManager.AddOverlay(_overlay);
|
||||
}
|
||||
else
|
||||
{
|
||||
IoCManager.Resolve<IOverlayManager>().RemoveOverlay(_overlay!);
|
||||
_overlayManager.RemoveOverlay(_overlay!);
|
||||
_overlay = null;
|
||||
}
|
||||
}
|
||||
@@ -63,7 +66,7 @@ namespace Robust.Client.GameObjects
|
||||
protected internal override void Draw(in OverlayDrawArgs args)
|
||||
{
|
||||
var currentMap = _eyeManager.CurrentMap;
|
||||
var viewport = _eyeManager.GetWorldViewport();
|
||||
var viewport = args.WorldBounds;
|
||||
var worldHandle = args.WorldHandle;
|
||||
|
||||
foreach (var grid in _mapManager.FindGridsIntersecting(currentMap, viewport))
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Robust.Client.GameObjects;
|
||||
|
||||
internal class GridRenderingSystem : EntitySystem
|
||||
{
|
||||
private readonly IClydeInternal _clyde;
|
||||
|
||||
public GridRenderingSystem(IClydeInternal clyde)
|
||||
{
|
||||
_clyde = clyde;
|
||||
}
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
_clyde.RegisterGridEcsEvents();
|
||||
}
|
||||
}
|
||||
@@ -4,11 +4,15 @@ using Robust.Client.Input;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Shared;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Input;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Players;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Robust.Client.GameObjects
|
||||
@@ -16,11 +20,13 @@ namespace Robust.Client.GameObjects
|
||||
/// <summary>
|
||||
/// Client-side processing of all input commands through the simulation.
|
||||
/// </summary>
|
||||
public class InputSystem : SharedInputSystem
|
||||
public sealed class InputSystem : SharedInputSystem
|
||||
{
|
||||
[Dependency] private readonly IInputManager _inputManager = default!;
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
[Dependency] private readonly IClientGameStateManager _stateManager = default!;
|
||||
[Dependency] private readonly IConsoleHost _conHost = default!;
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
|
||||
private readonly IPlayerCommandStates _cmdStates = new PlayerCommandStates();
|
||||
|
||||
@@ -108,6 +114,43 @@ namespace Robust.Client.GameObjects
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<PlayerAttachSysMessage>(OnAttachedEntityChanged);
|
||||
|
||||
_conHost.RegisterCommand("incmd",
|
||||
"Inserts an input command into the simulation",
|
||||
"incmd <KeyFunction> <d|u KeyState> <wxPos> <wyPos>",
|
||||
GenerateInputCommand);
|
||||
}
|
||||
|
||||
public override void Shutdown()
|
||||
{
|
||||
base.Shutdown();
|
||||
|
||||
_conHost.UnregisterCommand("incmd");
|
||||
}
|
||||
|
||||
private void GenerateInputCommand(IConsoleShell shell, string argstr, string[] args)
|
||||
{
|
||||
var localPlayer = _playerManager.LocalPlayer;
|
||||
if(localPlayer is null)
|
||||
return;
|
||||
|
||||
var pent = localPlayer.ControlledEntity;
|
||||
if(pent is null)
|
||||
return;
|
||||
|
||||
BoundKeyFunction keyFunction = new BoundKeyFunction(args[0]);
|
||||
BoundKeyState state = args[1] == "u" ? BoundKeyState.Up: BoundKeyState.Down;
|
||||
|
||||
var pxform = Transform(pent.Value);
|
||||
var wPos = pxform.WorldPosition + new Vector2(float.Parse(args[2]), float.Parse(args[3]));
|
||||
var coords = EntityCoordinates.FromMap(EntityManager, pent.Value, new MapCoordinates(wPos, pxform.MapID));
|
||||
|
||||
var funcId = _inputManager.NetworkBindMap.KeyFunctionID(keyFunction);
|
||||
|
||||
var message = new FullInputCmdMessage(_timing.CurTick, _timing.TickFraction, funcId, state,
|
||||
coords, new ScreenCoordinates(0, 0, default), EntityUid.Invalid);
|
||||
|
||||
HandleInputCommand(localPlayer.Session, keyFunction, message);
|
||||
}
|
||||
|
||||
private void OnAttachedEntityChanged(PlayerAttachSysMessage message)
|
||||
@@ -163,7 +206,7 @@ namespace Robust.Client.GameObjects
|
||||
/// <summary>
|
||||
/// Entity system message that is raised when the player changes attached entities.
|
||||
/// </summary>
|
||||
public class PlayerAttachSysMessage : EntityEventArgs
|
||||
public sealed class PlayerAttachSysMessage : EntityEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// New entity the player is attached to.
|
||||
@@ -180,7 +223,7 @@ namespace Robust.Client.GameObjects
|
||||
}
|
||||
}
|
||||
|
||||
public class PlayerAttachedEvent : EntityEventArgs
|
||||
public sealed class PlayerAttachedEvent : EntityEventArgs
|
||||
{
|
||||
public PlayerAttachedEvent(EntityUid entity)
|
||||
{
|
||||
@@ -190,7 +233,7 @@ namespace Robust.Client.GameObjects
|
||||
public EntityUid Entity { get; }
|
||||
}
|
||||
|
||||
public class PlayerDetachedEvent : EntityEventArgs
|
||||
public sealed class PlayerDetachedEvent : EntityEventArgs
|
||||
{
|
||||
public PlayerDetachedEvent(EntityUid entity)
|
||||
{
|
||||
|
||||
@@ -4,7 +4,7 @@ using Robust.Shared.IoC;
|
||||
|
||||
namespace Robust.Client.GameObjects
|
||||
{
|
||||
public class MidiSystem : EntitySystem
|
||||
public sealed class MidiSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IMidiManager _midiManager = default!;
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ namespace Robust.Client.GameObjects
|
||||
public sealed class PointLightSystem : SharedPointLightSystem
|
||||
{
|
||||
[Dependency] private readonly IResourceCache _resourceCache = default!;
|
||||
[Dependency] private readonly RenderingTreeSystem _renderingTreeSystem = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -19,16 +20,14 @@ namespace Robust.Client.GameObjects
|
||||
private void HandleInit(EntityUid uid, PointLightComponent component, ComponentInit args)
|
||||
{
|
||||
UpdateMask(component);
|
||||
RaiseLocalEvent(uid, new PointLightUpdateEvent());
|
||||
}
|
||||
|
||||
private void HandleRemove(EntityUid uid, PointLightComponent component, ComponentRemove args)
|
||||
{
|
||||
var map = EntityManager.GetComponent<TransformComponent>(uid).MapID;
|
||||
// TODO: Just make this update the tree directly and not allocate
|
||||
if (map != MapId.Nullspace)
|
||||
if (Transform(uid).MapID != MapId.Nullspace)
|
||||
{
|
||||
EntityManager.EventBus.RaiseEvent(EventSource.Local,
|
||||
new RenderTreeRemoveLightEvent(component, map));
|
||||
_renderingTreeSystem.ClearLight(component);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -70,21 +70,19 @@ namespace Robust.Client.GameObjects
|
||||
UpdatesAfter.Add(typeof(TransformSystem));
|
||||
UpdatesAfter.Add(typeof(PhysicsSystem));
|
||||
|
||||
_mapManager.MapCreated += MapManagerOnMapCreated;
|
||||
_mapManager.OnGridCreated += MapManagerOnGridCreated;
|
||||
SubscribeLocalEvent<MapChangedEvent>(MapManagerOnMapCreated);
|
||||
|
||||
SubscribeLocalEvent<GridInitializeEvent>(MapManagerOnGridCreated);
|
||||
|
||||
// Due to how recursion works, this must be done.
|
||||
SubscribeLocalEvent<MoveEvent>(AnythingMoved);
|
||||
|
||||
SubscribeLocalEvent<SpriteComponent, EntMapIdChangedMessage>(SpriteMapChanged);
|
||||
SubscribeLocalEvent<SpriteComponent, EntParentChangedMessage>(SpriteParentChanged);
|
||||
SubscribeLocalEvent<SpriteComponent, ComponentRemove>(RemoveSprite);
|
||||
SubscribeLocalEvent<SpriteComponent, SpriteUpdateEvent>(HandleSpriteUpdate);
|
||||
|
||||
SubscribeLocalEvent<PointLightComponent, EntMapIdChangedMessage>(LightMapChanged);
|
||||
SubscribeLocalEvent<PointLightComponent, EntParentChangedMessage>(LightParentChanged);
|
||||
SubscribeLocalEvent<PointLightComponent, PointLightRadiusChangedEvent>(PointLightRadiusChanged);
|
||||
SubscribeLocalEvent<PointLightComponent, RenderTreeRemoveLightEvent>(RemoveLight);
|
||||
SubscribeLocalEvent<PointLightComponent, PointLightUpdateEvent>(HandleLightUpdate);
|
||||
|
||||
SubscribeLocalEvent<RenderingTreeComponent, ComponentInit>(OnTreeInit);
|
||||
@@ -114,10 +112,18 @@ namespace Robust.Client.GameObjects
|
||||
|
||||
private void AnythingMoved(ref MoveEvent args)
|
||||
{
|
||||
AnythingMovedSubHandler(args.Sender);
|
||||
var pointQuery = EntityManager.GetEntityQuery<PointLightComponent>();
|
||||
var spriteQuery = EntityManager.GetEntityQuery<SpriteComponent>();
|
||||
var xformQuery = EntityManager.GetEntityQuery<TransformComponent>();
|
||||
|
||||
AnythingMovedSubHandler(args.Sender, xformQuery, pointQuery, spriteQuery);
|
||||
}
|
||||
|
||||
private void AnythingMovedSubHandler(EntityUid uid, TransformComponent? xform = null)
|
||||
private void AnythingMovedSubHandler(
|
||||
EntityUid uid,
|
||||
EntityQuery<TransformComponent> xformQuery,
|
||||
EntityQuery<PointLightComponent> pointQuery,
|
||||
EntityQuery<SpriteComponent> spriteQuery)
|
||||
{
|
||||
// To avoid doing redundant updates (and we don't need to update a grid's children ever)
|
||||
if (!_checkedChildren.Add(uid) || EntityManager.HasComponent<RenderingTreeComponent>(uid)) return;
|
||||
@@ -126,17 +132,19 @@ namespace Robust.Client.GameObjects
|
||||
// WHATEVER YOU DO, DON'T REPLACE THIS WITH SPAMMING EVENTS UNLESS YOU HAVE A GUARANTEE IT WON'T LAG THE GC.
|
||||
// (Struct-based events ok though)
|
||||
// Ironically this was lagging the GC lolz
|
||||
if (EntityManager.TryGetComponent(uid, out SpriteComponent? sprite))
|
||||
if (spriteQuery.TryGetComponent(uid, out var sprite))
|
||||
QueueSpriteUpdate(sprite);
|
||||
|
||||
if (EntityManager.TryGetComponent(uid, out PointLightComponent? light))
|
||||
if (pointQuery.TryGetComponent(uid, out var light))
|
||||
QueueLightUpdate(light);
|
||||
|
||||
if (!Resolve(uid, ref xform)) return;
|
||||
if (!xformQuery.TryGetComponent(uid, out var xform)) return;
|
||||
|
||||
foreach (var child in xform.ChildEntities)
|
||||
var childEnumerator = xform.ChildEnumerator;
|
||||
|
||||
while (childEnumerator.MoveNext(out var child))
|
||||
{
|
||||
AnythingMovedSubHandler(child);
|
||||
AnythingMovedSubHandler(child.Value, xformQuery, pointQuery, spriteQuery);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,10 +154,6 @@ namespace Robust.Client.GameObjects
|
||||
// Otherwise these will still have their past MapId and that's all we need..
|
||||
|
||||
#region SpriteHandlers
|
||||
private void SpriteMapChanged(EntityUid uid, SpriteComponent component, EntMapIdChangedMessage args)
|
||||
{
|
||||
QueueSpriteUpdate(component);
|
||||
}
|
||||
|
||||
private void SpriteParentChanged(EntityUid uid, SpriteComponent component, ref EntParentChangedMessage args)
|
||||
{
|
||||
@@ -179,10 +183,6 @@ namespace Robust.Client.GameObjects
|
||||
#endregion
|
||||
|
||||
#region LightHandlers
|
||||
private void LightMapChanged(EntityUid uid, PointLightComponent component, EntMapIdChangedMessage args)
|
||||
{
|
||||
QueueLightUpdate(component);
|
||||
}
|
||||
|
||||
private void LightParentChanged(EntityUid uid, PointLightComponent component, ref EntParentChangedMessage args)
|
||||
{
|
||||
@@ -194,12 +194,7 @@ namespace Robust.Client.GameObjects
|
||||
QueueLightUpdate(component);
|
||||
}
|
||||
|
||||
private void RemoveLight(EntityUid uid, PointLightComponent component, RenderTreeRemoveLightEvent args)
|
||||
{
|
||||
ClearLight(component);
|
||||
}
|
||||
|
||||
private void ClearLight(PointLightComponent component)
|
||||
public void ClearLight(PointLightComponent component)
|
||||
{
|
||||
if (component.RenderTree == null) return;
|
||||
|
||||
@@ -216,13 +211,6 @@ namespace Robust.Client.GameObjects
|
||||
}
|
||||
#endregion
|
||||
|
||||
public override void Shutdown()
|
||||
{
|
||||
base.Shutdown();
|
||||
_mapManager.MapCreated -= MapManagerOnMapCreated;
|
||||
_mapManager.OnGridCreated -= MapManagerOnGridCreated;
|
||||
}
|
||||
|
||||
private void OnTreeRemove(EntityUid uid, RenderingTreeComponent component, ComponentRemove args)
|
||||
{
|
||||
foreach (var sprite in component.SpriteTree)
|
||||
@@ -239,9 +227,9 @@ namespace Robust.Client.GameObjects
|
||||
component.LightTree.Clear();
|
||||
}
|
||||
|
||||
private void MapManagerOnMapCreated(object? sender, MapEventArgs e)
|
||||
private void MapManagerOnMapCreated(MapChangedEvent e)
|
||||
{
|
||||
if (e.Map == MapId.Nullspace)
|
||||
if (e.Destroyed || e.Map == MapId.Nullspace)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -249,28 +237,26 @@ namespace Robust.Client.GameObjects
|
||||
EntityManager.EnsureComponent<RenderingTreeComponent>(_mapManager.GetMapEntityId(e.Map));
|
||||
}
|
||||
|
||||
private void MapManagerOnGridCreated(MapId mapId, GridId gridId)
|
||||
private void MapManagerOnGridCreated(GridInitializeEvent ev)
|
||||
{
|
||||
EntityManager.EnsureComponent<RenderingTreeComponent>(_mapManager.GetGrid(gridId).GridEntityId);
|
||||
EntityManager.EnsureComponent<RenderingTreeComponent>(_mapManager.GetGrid(ev.GridId).GridEntityId);
|
||||
}
|
||||
|
||||
// TODO: Pass in TransformComponent directly: mainly interested in getting this shit working atm.
|
||||
private RenderingTreeComponent? GetRenderTree(EntityUid entity)
|
||||
private RenderingTreeComponent? GetRenderTree(EntityUid entity, EntityQuery<TransformComponent> xforms)
|
||||
{
|
||||
var lookups = EntityManager.GetEntityQuery<RenderingTreeComponent>();
|
||||
|
||||
if (!EntityManager.EntityExists(entity) ||
|
||||
!EntityManager.TryGetComponent(entity, out TransformComponent? xform) ||
|
||||
!xforms.TryGetComponent(entity, out var xform) ||
|
||||
xform.MapID == MapId.Nullspace ||
|
||||
EntityManager.HasComponent<RenderingTreeComponent>(entity)) return null;
|
||||
lookups.HasComponent(entity)) return null;
|
||||
|
||||
var parent = xform.ParentUid;
|
||||
|
||||
while (true)
|
||||
while (parent.IsValid())
|
||||
{
|
||||
if (!parent.IsValid())
|
||||
break;
|
||||
|
||||
if (EntityManager.TryGetComponent(parent, out RenderingTreeComponent? comp)) return comp;
|
||||
parent = EntityManager.GetComponent<TransformComponent>(parent).ParentUid;
|
||||
if (lookups.TryGetComponent(parent, out var comp)) return comp;
|
||||
parent = xforms.GetComponent(parent).ParentUid;
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -285,6 +271,8 @@ namespace Robust.Client.GameObjects
|
||||
{
|
||||
_checkedChildren.Clear();
|
||||
|
||||
var xforms = EntityManager.GetEntityQuery<TransformComponent>();
|
||||
|
||||
foreach (var sprite in _spriteQueue)
|
||||
{
|
||||
sprite.TreeUpdateQueued = false;
|
||||
@@ -295,9 +283,9 @@ namespace Robust.Client.GameObjects
|
||||
}
|
||||
|
||||
var oldMapTree = sprite.RenderTree;
|
||||
var newMapTree = GetRenderTree(sprite.Owner);
|
||||
var newMapTree = GetRenderTree(sprite.Owner, xforms);
|
||||
// TODO: Temp PVS guard
|
||||
var xform = EntityManager.GetComponent<TransformComponent>(sprite.Owner);
|
||||
var xform = xforms.GetComponent(sprite.Owner);
|
||||
var (worldPos, worldRot) = xform.GetWorldPositionRotation();
|
||||
|
||||
if (float.IsNaN(worldPos.X) || float.IsNaN(worldPos.Y))
|
||||
@@ -306,7 +294,7 @@ namespace Robust.Client.GameObjects
|
||||
continue;
|
||||
}
|
||||
|
||||
var aabb = SpriteAabbFunc(sprite, worldPos, worldRot);
|
||||
var aabb = SpriteAabbFunc(sprite, worldPos, worldRot, xforms);
|
||||
|
||||
// If we're on a new map then clear the old one.
|
||||
if (oldMapTree != newMapTree)
|
||||
@@ -333,9 +321,9 @@ namespace Robust.Client.GameObjects
|
||||
}
|
||||
|
||||
var oldMapTree = light.RenderTree;
|
||||
var newMapTree = GetRenderTree(light.Owner);
|
||||
var newMapTree = GetRenderTree(light.Owner, xforms);
|
||||
// TODO: Temp PVS guard
|
||||
var worldPos = EntityManager.GetComponent<TransformComponent>(light.Owner).WorldPosition;
|
||||
var worldPos = xforms.GetComponent(light.Owner).WorldPosition;
|
||||
|
||||
if (float.IsNaN(worldPos.X) || float.IsNaN(worldPos.Y))
|
||||
{
|
||||
@@ -350,7 +338,7 @@ namespace Robust.Client.GameObjects
|
||||
Logger.WarningS(LoggerSawmill, $"Light radius for {light.Owner} set above max radius of {MaxLightRadius}. This may lead to pop-in.");
|
||||
}
|
||||
|
||||
var aabb = LightAabbFunc(light, worldPos);
|
||||
var aabb = LightAabbFunc(light, worldPos, xforms);
|
||||
|
||||
// If we're on a new map then clear the old one.
|
||||
if (oldMapTree != newMapTree)
|
||||
@@ -372,82 +360,41 @@ namespace Robust.Client.GameObjects
|
||||
|
||||
private Box2 SpriteAabbFunc(in SpriteComponent value)
|
||||
{
|
||||
var xform = EntityManager.GetComponent<TransformComponent>(value.Owner);
|
||||
var xforms = EntityManager.GetEntityQuery<TransformComponent>();
|
||||
var xform = xforms.GetComponent(value.Owner);
|
||||
var (worldPos, worldRot) = xform.GetWorldPositionRotation();
|
||||
var bounds = new Box2Rotated(value.CalculateBoundingBox(worldPos), worldRot, worldPos);
|
||||
var tree = GetRenderTree(value.Owner);
|
||||
|
||||
if (tree == null)
|
||||
{
|
||||
return bounds.CalcBoundingBox();
|
||||
}
|
||||
else
|
||||
{
|
||||
return EntityManager.GetComponent<TransformComponent>(tree.Owner).InvWorldMatrix.TransformBox(bounds);
|
||||
}
|
||||
return SpriteAabbFunc(value, worldPos, worldRot, xforms);
|
||||
}
|
||||
|
||||
private Box2 LightAabbFunc(in PointLightComponent value)
|
||||
{
|
||||
var worldPos = EntityManager.GetComponent<TransformComponent>(value.Owner).WorldPosition;
|
||||
var tree = GetRenderTree(value.Owner);
|
||||
var xforms = EntityManager.GetEntityQuery<TransformComponent>();
|
||||
|
||||
var worldPos = xforms.GetComponent(value.Owner).WorldPosition;
|
||||
var tree = GetRenderTree(value.Owner, xforms);
|
||||
var boxSize = value.Radius * 2;
|
||||
|
||||
Vector2 localPos;
|
||||
if (tree == null)
|
||||
{
|
||||
localPos = worldPos;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Need a way to just cache this InvWorldMatrix
|
||||
localPos = EntityManager.GetComponent<TransformComponent>(tree.Owner).InvWorldMatrix.Transform(worldPos);
|
||||
}
|
||||
var localPos = tree == null ? worldPos : xforms.GetComponent(tree.Owner).InvWorldMatrix.Transform(worldPos);
|
||||
return Box2.CenteredAround(localPos, (boxSize, boxSize));
|
||||
}
|
||||
|
||||
private Box2 SpriteAabbFunc(SpriteComponent value, Vector2 worldPos, Angle worldRot)
|
||||
private Box2 SpriteAabbFunc(SpriteComponent value, Vector2 worldPos, Angle worldRot, EntityQuery<TransformComponent> xforms)
|
||||
{
|
||||
var bounds = new Box2Rotated(value.CalculateBoundingBox(worldPos), worldRot, worldPos);
|
||||
var tree = GetRenderTree(value.Owner);
|
||||
var bounds = value.CalculateRotatedBoundingBox(worldPos, worldRot);
|
||||
var tree = GetRenderTree(value.Owner, xforms);
|
||||
|
||||
if (tree == null)
|
||||
{
|
||||
return bounds.CalcBoundingBox();
|
||||
}
|
||||
else
|
||||
{
|
||||
return EntityManager.GetComponent<TransformComponent>(tree.Owner).InvWorldMatrix.TransformBox(bounds);
|
||||
}
|
||||
return tree == null ? bounds.CalcBoundingBox() : xforms.GetComponent(tree.Owner).InvWorldMatrix.TransformBox(bounds);
|
||||
}
|
||||
|
||||
private Box2 LightAabbFunc(PointLightComponent value, Vector2 worldPos)
|
||||
private Box2 LightAabbFunc(PointLightComponent value, Vector2 worldPos, EntityQuery<TransformComponent> xforms)
|
||||
{
|
||||
// Lights are circles so don't need entity's rotation
|
||||
var tree = GetRenderTree(value.Owner);
|
||||
var tree = GetRenderTree(value.Owner, xforms);
|
||||
var boxSize = value.Radius * 2;
|
||||
|
||||
Vector2 localPos;
|
||||
if (tree == null)
|
||||
{
|
||||
localPos = worldPos;
|
||||
} else
|
||||
{
|
||||
localPos = EntityManager.GetComponent<TransformComponent>(tree.Owner).InvWorldMatrix.Transform(worldPos);
|
||||
}
|
||||
var localPos = tree == null ? worldPos : xforms.GetComponent(tree.Owner).InvWorldMatrix.Transform(worldPos);
|
||||
return Box2.CenteredAround(localPos, (boxSize, boxSize));
|
||||
}
|
||||
}
|
||||
|
||||
internal class RenderTreeRemoveLightEvent : EntityEventArgs
|
||||
{
|
||||
public RenderTreeRemoveLightEvent(PointLightComponent light, MapId map)
|
||||
{
|
||||
Light = light;
|
||||
Map = map;
|
||||
}
|
||||
|
||||
public PointLightComponent Light { get; }
|
||||
public MapId Map { get; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
using System;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.ResourceManagement;
|
||||
using Robust.Client.Utility;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Robust.Client.GameObjects;
|
||||
|
||||
public sealed partial class SpriteSystem
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _proto = default!;
|
||||
[Dependency] private readonly IResourceCache _resourceCache = default!;
|
||||
|
||||
[Pure]
|
||||
public Texture Frame0(SpriteSpecifier specifier)
|
||||
{
|
||||
return RsiStateLike(specifier).Default;
|
||||
}
|
||||
|
||||
[Pure]
|
||||
public IRsiStateLike RsiStateLike(SpriteSpecifier specifier)
|
||||
{
|
||||
switch (specifier)
|
||||
{
|
||||
case SpriteSpecifier.Texture tex:
|
||||
return tex.GetTexture(_resourceCache);
|
||||
|
||||
case SpriteSpecifier.Rsi rsi:
|
||||
return GetState(rsi);
|
||||
|
||||
case SpriteSpecifier.EntityPrototype prototypeIcon:
|
||||
if (!_proto.TryIndex<EntityPrototype>(prototypeIcon.EntityPrototypeId, out var prototype))
|
||||
{
|
||||
Logger.Error("Failed to load PrototypeIcon {0}", prototypeIcon.EntityPrototypeId);
|
||||
return SpriteComponent.GetFallbackState(_resourceCache);
|
||||
}
|
||||
|
||||
return SpriteComponent.GetPrototypeIcon(prototype, _resourceCache);
|
||||
|
||||
default:
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
|
||||
[Pure]
|
||||
public IRsiStateLike GetPrototypeIcon(EntityPrototype prototype, IResourceCache resourceCache)
|
||||
{
|
||||
var icon = IconComponent.GetPrototypeIcon(prototype, _resourceCache);
|
||||
if (icon != null) return icon;
|
||||
|
||||
if (!prototype.Components.ContainsKey("Sprite"))
|
||||
{
|
||||
return SpriteComponent.GetFallbackState(resourceCache);
|
||||
}
|
||||
|
||||
var dummy = Spawn(prototype.ID, MapCoordinates.Nullspace);
|
||||
var spriteComponent = EnsureComp<SpriteComponent>(dummy);
|
||||
var result = spriteComponent.Icon ?? SpriteComponent.GetFallbackState(resourceCache);
|
||||
Del(dummy);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
[Pure]
|
||||
public RSI.State GetState(SpriteSpecifier.Rsi rsiSpecifier)
|
||||
{
|
||||
if (_resourceCache.TryGetResource<RSIResource>(
|
||||
SharedSpriteComponent.TextureRoot / rsiSpecifier.RsiPath,
|
||||
out var theRsi) &&
|
||||
theRsi.RSI.TryGetState(rsiSpecifier.RsiState, out var state))
|
||||
{
|
||||
return state;
|
||||
}
|
||||
|
||||
Logger.Error("Failed to load RSI {0}", rsiSpecifier.RsiPath);
|
||||
return SpriteComponent.GetFallbackState(_resourceCache);
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ namespace Robust.Client.GameObjects
|
||||
/// Updates the layer animation for every visible sprite.
|
||||
/// </summary>
|
||||
[UsedImplicitly]
|
||||
public class SpriteSystem : EntitySystem
|
||||
public sealed partial class SpriteSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IEyeManager _eyeManager = default!;
|
||||
[Dependency] private readonly RenderingTreeSystem _treeSystem = default!;
|
||||
@@ -53,9 +53,11 @@ namespace Robust.Client.GameObjects
|
||||
return;
|
||||
}
|
||||
|
||||
var xforms = EntityManager.GetEntityQuery<TransformComponent>();
|
||||
|
||||
foreach (var comp in _treeSystem.GetRenderTrees(currentMap, pvsBounds))
|
||||
{
|
||||
var bounds = EntityManager.GetComponent<TransformComponent>(comp.Owner).InvWorldMatrix.TransformBox(pvsBounds);
|
||||
var bounds = xforms.GetComponent(comp.Owner).InvWorldMatrix.TransformBox(pvsBounds);
|
||||
|
||||
comp.SpriteTree.QueryAabb(ref frameTime, (ref float state, in SpriteComponent value) =>
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@ using Robust.Shared.Maths;
|
||||
|
||||
namespace Robust.Client.GameObjects
|
||||
{
|
||||
public class VelocityDebugSystem : EntitySystem
|
||||
public sealed class VelocityDebugSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IEyeManager _eyeManager = default!;
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user