Compare commits

..

1 Commits

Author SHA1 Message Date
DrSmugleaf
42b414d3b7 Change state manager methods to return the new state 2022-08-15 00:51:41 +02:00
1723 changed files with 48441 additions and 106001 deletions

21
.github/CODEOWNERS vendored
View File

@@ -1,9 +1,20 @@
# Last match in file takes precedence.
# Ping for all PRs
* @PJB3005 @DrSmugleaf
* @Acruid @PJB3005 @Silvertorch5
# commands commands commands commands
**/Toolshed/** @moonheart08
*Command.cs @moonheart08
*Commands.cs @moonheart08
/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

View File

@@ -9,6 +9,14 @@ on:
concurrency: benchmarks
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
@@ -20,22 +28,8 @@ jobs:
host: centcomm.spacestation14.io
username: robust-benchmark-runner
key: ${{ secrets.CENTCOMM_ROBUST_BENCHMARK_RUNNER_KEY }}
command_timeout: 100000m
command_timeout: 100000m
script: |
mkdir benchmark_run_${{ github.sha }}
cd benchmark_run_${{ github.sha }}
git clone https://github.com/space-wizards/RobustToolbox.git repo_dir --recursive
cd repo_dir
git checkout ${{ github.sha }}
cd Robust.Benchmarks
dotnet restore
export ROBUST_BENCHMARKS_ENABLE_SQL=1
export ROBUST_BENCHMARKS_SQL_ADDRESS="${{ secrets.BENCHMARKS_WRITE_ADDRESS }}"
export ROBUST_BENCHMARKS_SQL_PORT="${{ secrets.BENCHMARKS_WRITE_PORT }}"
export ROBUST_BENCHMARKS_SQL_USER="${{ secrets.BENCHMARKS_WRITE_USER }}"
export ROBUST_BENCHMARKS_SQL_PASSWORD="${{ secrets.BENCHMARKS_WRITE_PASSWORD }}"
export ROBUST_BENCHMARKS_SQL_DATABASE="benchmarks"
export GITHUB_SHA="${{ github.sha }}"
dotnet run --filter '*' --configuration Release
cd ../../..
rm -rf benchmark_run_${{ github.sha }}
wget https://raw.githubusercontent.com/space-wizards/RobustToolbox/${{ github.sha }}/Tools/run_benchmarks.py
python3 run_benchmarks.py "${{ secrets.BENCHMARKS_WRITE_ADDRESS }}" "${{ secrets.BENCHMARKS_WRITE_PORT }}" "${{ secrets.BENCHMARKS_WRITE_USER }}" "${{ secrets.BENCHMARKS_WRITE_PASSWORD }}" "${{ github.sha }}"
rm run_benchmarks.py

View File

@@ -6,29 +6,29 @@ on:
jobs:
docfx:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3.6.0
steps:
- uses: actions/checkout@v2
with:
submodules: true
- name: Setup .NET Core
uses: actions/setup-dotnet@v3.2.0
uses: actions/setup-dotnet@v1
with:
dotnet-version: 7.0.x
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
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 }}
BUILD_DIR: Robust.Docfx/_robust-site
GH_PAT: ${{ secrets.GH_PAT }}

View File

@@ -15,19 +15,19 @@ jobs:
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3.6.0
- uses: actions/checkout@v2
with:
submodules: true
- name: Setup .NET Core
uses: actions/setup-dotnet@v3.2.0
uses: actions/setup-dotnet@v1
with:
dotnet-version: 7.0.x
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 -- NUnit.ConsoleOut=0

View File

@@ -35,14 +35,14 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v3.6.0
uses: actions/checkout@v2
with:
submodules: true
- name: Setup .NET Core
uses: actions/setup-dotnet@v3.2.0
uses: actions/setup-dotnet@v1
with:
dotnet-version: 7.0.x
dotnet-version: 6.0.100
- name: Build
run: dotnet build

View File

@@ -16,14 +16,14 @@ jobs:
$ver = [regex]::Match($env:GITHUB_REF, "refs/tags/v?(.+)").Groups[1].Value
echo ("::set-output name=version::{0}" -f $ver)
- uses: actions/checkout@v3.6.0
- uses: actions/checkout@v2
with:
submodules: true
- name: Setup .NET Core
uses: actions/setup-dotnet@v3.2.0
uses: actions/setup-dotnet@v1
with:
dotnet-version: 7.0.x
dotnet-version: 6.0.100
- name: Package client
run: Tools/package_client_build.py -p windows mac linux

View File

@@ -13,15 +13,15 @@ jobs:
steps:
- name: Check out content
uses: actions/checkout@v3.6.0
uses: actions/checkout@v2
with:
repository: space-wizards/space-station-14
submodules: recursive
- name: Setup .NET Core
uses: actions/setup-dotnet@v3.2.0
uses: actions/setup-dotnet@v1
with:
dotnet-version: 7.0.x
dotnet-version: 6.0.100
- name: Disable submodule autoupdate
run: touch BuildChecker/DISABLE_SUBMODULE_AUTOUPDATE
@@ -34,7 +34,7 @@ jobs:
- name: Install dependencies
run: dotnet restore
- name: Build
run: dotnet build --configuration Tools --no-restore
run: dotnet build --configuration Release --no-restore
- name: Content.Tests
run: dotnet test --no-build Content.Tests/Content.Tests.csproj -v n
- name: Content.IntegrationTests

View File

@@ -1,3 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\MSBuild\Robust.Engine.props" />
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
</Project>

View File

@@ -1,23 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<AssemblyName>SpaceWizards.Lidgren.Network</AssemblyName>
<TargetFramework>netcoreapp3.1</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
<DefaultItemExcludes>Lidgren.Network/**/*</DefaultItemExcludes>
<DefineConstants>$(DefineConstants);USE_RELEASE_STATISTICS</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<SkipRobustAnalyzer>true</SkipRobustAnalyzer>
</PropertyGroup>
<ItemGroup>
<Compile Include="Lidgren.Network\Lidgren.Network\**\*.cs">
<Link>%(RecursiveDir)%(Filename)%(Extension)</Link>
</Compile>
<Compile Remove="Lidgren.Network\Lidgren.Network\obj\**\*.cs" />
</ItemGroup>
<Import Project="../MSBuild/Robust.Properties.targets" />
</Project>

View File

@@ -1,5 +0,0 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="12.0">
<ItemGroup>
<ProjectReference Include="$(MSBuildThisFileDirectory)\..\Robust.Shared.CompNetworkGenerator\Robust.Shared.CompNetworkGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false"/>
</ItemGroup>
</Project>

View File

@@ -1,37 +0,0 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- Build configurations -->
<PropertyGroup>
<!-- Avoid SDK defining DEBUG/RELEASE/DEBUGOPT/TOOLS itself. -->
<DisableImplicitConfigurationDefines>true</DisableImplicitConfigurationDefines>
<!-- Project configurations -->
<Configurations>Debug;Release;Tools;DebugOpt</Configurations>
<Platforms>AnyCPU</Platforms>
</PropertyGroup>
<!-- Debug configuration: asserts, tools, no optimizations -->
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
<DebugSymbols Condition="'$(DebugSymbols)' == ''">true</DebugSymbols>
<Optimize Condition="'$(Optimize)' == ''">false</Optimize>
<RobustToolsBuild Condition="'$(RobustToolsBuild)' == ''">true</RobustToolsBuild>
<DefineConstants>DEBUG;$(DefineConstants)</DefineConstants>
</PropertyGroup>
<!-- DebugOpt configuration: asserts, tools, optimizations -->
<PropertyGroup Condition="'$(Configuration)' == 'DebugOpt'">
<DebugSymbols Condition="'$(DebugSymbols)' == ''">true</DebugSymbols>
<Optimize Condition="'$(Optimize)' == ''">true</Optimize>
<RobustToolsBuild Condition="'$(RobustToolsBuild)' == ''">true</RobustToolsBuild>
<DefineConstants>DEBUG;$(DefineConstants)</DefineConstants>
</PropertyGroup>
<!-- Tools configuration: no asserts, tools, optimizations -->
<PropertyGroup Condition="'$(Configuration)' == 'Tools'">
<DebugSymbols Condition="'$(DebugSymbols)' == ''">true</DebugSymbols>
<Optimize Condition="'$(Optimize)' == ''">true</Optimize>
<RobustToolsBuild Condition="'$(RobustToolsBuild)' == ''">true</RobustToolsBuild>
</PropertyGroup>
<!-- Release configuration: no asserts, no tools, optimizations -->
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<Optimize Condition="'$(Optimize)' == ''">true</Optimize>
<RobustToolsBuild Condition="'$(RobustToolsBuild)' == ''">false</RobustToolsBuild>
<DefineConstants>RELEASE;$(DefineConstants)</DefineConstants>
</PropertyGroup>
</Project>

View File

@@ -20,19 +20,10 @@
<PropertyGroup Condition="'$(FullRelease)' == 'True'">
<DefineConstants>$(DefineConstants);FULL_RELEASE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(FullRelease)' != 'True'">
<DefineConstants>$(DefineConstants);DEVELOPMENT</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release' Or '$(Configuration)' == 'Tools'">
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<DefineConstants>$(DefineConstants);EXCEPTION_TOLERANCE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(EnableClientScripting)' == 'True'">
<DefineConstants>$(DefineConstants);CLIENT_SCRIPTING</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(UseSystemSqlite)' == 'True'">
<DefineConstants>$(DefineConstants);USE_SYSTEM_SQLITE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(RobustToolsBuild)' == 'true'">
<DefineConstants>$(DefineConstants);TOOLS</DefineConstants>
</PropertyGroup>
</Project>

View File

@@ -1,4 +1,4 @@
<Project>
<!-- This file automatically reset by Tools/version.py -->
<Project>
<!-- This file automatically reset by Tools/version.py -->
<PropertyGroup><Version>0.40.3.0</Version></PropertyGroup>
</Project>

View File

@@ -1,8 +1,8 @@
<Project>
<!-- Engine-specific properties. Content should not use this file. -->
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<LangVersion>11</LangVersion>
<TargetFramework>net6.0</TargetFramework>
<LangVersion>10</LangVersion>
<Nullable>enable</Nullable>
<WarningsAsErrors>nullable</WarningsAsErrors>
</PropertyGroup>

View File

@@ -1,35 +0,0 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- MSBuild hurts and I can't find a foolproof way to detect platform. -->
<PropertyGroup>
<OS Condition="'$(OS)' == ''">Windows_NT</OS>
</PropertyGroup>
<Choose>
<When Condition="'$(OS)' != 'Unix'">
<PropertyGroup>
<ActualOS>Windows</ActualOS>
</PropertyGroup>
</When>
<!-- Folders that *probably* only exist on MacOS and not Linux. -->
<When Condition="Exists('/Volumes') And Exists('/System') And Exists('/Library')" >
<PropertyGroup>
<ActualOS>MacOS</ActualOS>
</PropertyGroup>
</When>
<When Condition="$([MSBuild]::IsOSPlatform('FreeBSD'))">
<PropertyGroup>
<ActualOS>FreeBSD</ActualOS>
</PropertyGroup>
</When>
<Otherwise>
<PropertyGroup>
<ActualOS>Linux</ActualOS>
</PropertyGroup>
</Otherwise>
</Choose>
<PropertyGroup>
<TargetOS Condition="'$(TargetOS)' == ''">$(ActualOS)</TargetOS>
<Python>python3</Python>
<Python Condition="'$(ActualOS)' == 'Windows'">py -3</Python>
<UseSystemSqlite Condition="'$(TargetOS)' == 'FreeBSD'">True</UseSystemSqlite>
</PropertyGroup>
</Project>

View File

@@ -1,31 +1,34 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- Properties for both engine and content. -->
<!-- Import this at the end of any project files in Robust and Content. -->
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
</PropertyGroup>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="12.0">
<Import Project="Robust.Custom.targets" Condition="Exists('Robust.Custom.targets')"/>
<!-- Configuration logic -->
<Import Project="Robust.Configurations.props" />
<!-- Some platform management logic -->
<Import Project="Robust.Platform.props" />
<!-- MSBuild hurts and I can't find a foolproof way to detect platform. -->
<PropertyGroup>
<EnableClientScripting>False</EnableClientScripting>
<!-- Client scripting is only enabled on tools builds for security and size reasons. -->
<EnableClientScripting Condition="'$(RobustToolsBuild)' == 'true'">True</EnableClientScripting>
<OS Condition="'$(OS)' == ''">Windows_NT</OS>
</PropertyGroup>
<Choose>
<When Condition="'$(OS)' != 'Unix'">
<PropertyGroup>
<ActualOS>Windows</ActualOS>
</PropertyGroup>
</When>
<!-- Folders that *probably* only exist on MacOS and not Linux. -->
<When Condition="Exists('/Volumes') And Exists('/System') And Exists('/Library')" >
<PropertyGroup>
<ActualOS>MacOS</ActualOS>
</PropertyGroup>
</When>
<Otherwise>
<PropertyGroup>
<ActualOS>Linux</ActualOS>
</PropertyGroup>
</Otherwise>
</Choose>
<PropertyGroup>
<TargetOS Condition="'$(TargetOS)' == ''">$(ActualOS)</TargetOS>
<Python>python3</Python>
<Python Condition="'$(ActualOS)' == 'Windows'">py -3</Python>
<TargetFramework>net6.0</TargetFramework>
<EnableClientScripting>True</EnableClientScripting>
<!-- Client scripting is disabled on full release builds for security and size reasons. -->
<EnableClientScripting Condition="'$(FullRelease)' == 'True'">False</EnableClientScripting>
</PropertyGroup>
<!-- built-in define constants -->
<Import Project="Robust.DefineConstants.targets" />
<!-- analyzer -->
<Import Project="Robust.Analyzers.targets" Condition="'$(SkipRobustAnalyzer)' != 'true'" />
<!-- serialization generator -->
<Import Project="Robust.Serialization.Generator.targets" />
</Project>

View File

@@ -1,5 +0,0 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="12.0">
<ItemGroup>
<ProjectReference Include="$(MSBuildThisFileDirectory)\..\Robust.Serialization.Generator\Robust.Serialization.Generator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false"/>
</ItemGroup>
</Project>

View File

@@ -2,7 +2,7 @@
<PropertyGroup>
<!-- Avoid MSBuild adding a None entry for XAML files because they'd show up TWICE in the project view. -->
<DefaultItemExcludes>**/*.xaml</DefaultItemExcludes>
<RobustUseExternalMSBuild>true</RobustUseExternalMSBuild>
<RobustUseExternalMSBuild>false</RobustUseExternalMSBuild>
<_RobustUseExternalMSBuild>$(RobustUseExternalMSBuild)</_RobustUseExternalMSBuild>
<_RobustUseExternalMSBuild Condition="'$(_RobustForceInternalMSBuild)' == 'true'">false</_RobustUseExternalMSBuild>
</PropertyGroup>
@@ -19,17 +19,10 @@
<ProjectReference Include="$(MSBuildThisFileDirectory)\..\Robust.Client.Injectors\Robust.Client.Injectors.csproj" ReferenceOutputAssembly="false"/>
</ItemGroup>
<!-- XamlIL does not make use of special Robust configurations like DebugOpt. Convert these down. -->
<PropertyGroup>
<RobustInjectorsConfiguration>$(Configuration)</RobustInjectorsConfiguration>
<RobustInjectorsConfiguration Condition="'$(Configuration)' == 'DebugOpt'">Debug</RobustInjectorsConfiguration>
<RobustInjectorsConfiguration Condition="'$(Configuration)' == 'Tools'">Release</RobustInjectorsConfiguration>
</PropertyGroup>
<UsingTask
Condition="'$(_RobustUseExternalMSBuild)' != 'true' And $(DesignTimeBuild) != true"
TaskName="CompileRobustXamlTask"
AssemblyFile="$(MSBuildThisFileDirectory)\..\Robust.Client.Injectors\bin\$(RobustInjectorsConfiguration)\netstandard2.0\Robust.Client.Injectors.dll"/>
AssemblyFile="$(MSBuildThisFileDirectory)\..\Robust.Client.Injectors\bin\$(Configuration)\netstandard2.0\Robust.Client.Injectors.dll"/>
<Target
Name="CompileRobustXaml"
Condition="Exists('@(IntermediateAssembly)')"

View File

@@ -25,7 +25,7 @@ namespace OpenToolkit.GraphicsLibraryFramework
}
string rName = null;
if (OperatingSystem.IsLinux() || OperatingSystem.IsFreeBSD()) rName = "libglfw.so.3";
if (OperatingSystem.IsLinux()) rName = "libglfw.so.3";
else if (OperatingSystem.IsMacOS()) rName = "libglfw.3.dylib";
if ((rName != null) && NativeLibrary.TryLoad(rName, assembly, path, out var handle))

View File

@@ -1,9 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\MSBuild\Robust.Properties.targets" />
<PropertyGroup>
<!-- Work around https://github.com/dotnet/project-system/issues/4314 -->
<TargetFramework>$(TargetFramework)</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<LangVersion>9.0</LangVersion>
<SkipRobustAnalyzer>true</SkipRobustAnalyzer>
<LangVersion>7.3</LangVersion>
</PropertyGroup>
<Import Project="..\MSBuild\Robust.Properties.targets" />
<Import Project="..\MSBuild\Robust.DefineConstants.targets" />
<ItemGroup>
<PackageReference Condition="'$(TargetFramework)' == 'net472'" Include="System.Memory" Version="4.5.3" />
</ItemGroup>
</Project>

View File

@@ -18,7 +18,7 @@ We are happy to accept contributions from anybody. Get in Discord or IRC if you
## Building
This repository is the **engine** part of SS14. It's the base engine all SS14 servers will be built on. As such, it does not start on its own: it needs the [content repo](https://github.com/space-wizards/space-station-14). Think of Robust Toolbox as BYOND in the context of Space Station 13.
This repository is the **engine** part of SS14. It's the base engine all SS14 servers will be built on. As such, it does not start on its own: it needs the [content repo](https://github.com/space-wizards/space-station-14). Think of Robust Toolbox as BYOND in the context of Spacestation 13.
## Legal Info

File diff suppressed because it is too large Load Diff

View File

@@ -1546,31 +1546,6 @@
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
- name: FastNoise
license: |
MIT License
Copyright(c) 2020 Jordan Peck (jordan.me2@gmail.com)
Copyright(c) 2020 Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
- name: OpenAL soft
license: |
GNU LIBRARY GENERAL PUBLIC LICENSE

View File

@@ -1,202 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -1,34 +0,0 @@
- type: entity
id: debugRotation
abstract: true
suffix: DEBUG
components:
- type: Sprite
netsync: false
visible: true
sprite: debugRotation.rsi
state: direction1
- type: entity
id: debugRotation1
parent: debugRotation
name: dbg_rotation1
components:
- type: Sprite
state: direction1
- type: entity
id: debugRotation4
parent: debugRotation
name: dbg_rotation4
components:
- type: Sprite
state: direction4
- type: entity
id: debugRotationTex
parent: debugRotation
name: dbg_rotationTex
components:
- type: Sprite
state: direction1

View File

@@ -1,44 +0,0 @@
- type: uiTheme
id: Default
path: /Textures/Interface/Default/
colors:
# Root
rootBackground: "#000000"
# Windows
windowBackground: "#111111"
windowBorder: "#444444"
windowHeader: "#001e3d"
windowCloseButton: "#FFFFFF"
windowCloseButtonHover: "#FF7F7F"
windowCloseButtonPressed: "#FF0000"
# Scrollbars
scrollBarDefault: "#80808059"
scrollBarHovered: "#8C8C8C59"
scrollBarGrabbed: "#8C8C8C59"
# Buttons
buttonBackground: "#171717"
buttonBackgroundHovered: "#272727"
buttonBackgroundPressed: "#173717"
buttonBorder: "#444444"
buttonBorderHovered: "#444444"
buttonBorderPressed: "#447044"
buttonBackgroundDisabled: "#333333"
buttonBorderDisabled: "#222222"
# LineEdit
lineEditUneditableText: "#444444"
lineEditPlaceholderText: "#7d7d7d"
lineEditBackground: "#000000"
lineEditBorder: "#444444"
# TabContainer
tabContainerBackground: "#000000"
tabContainerBorder: "#444444"
tabContainerActiveTabBackground: "#173717"
tabContainerActiveTabBorder: "#447044"
tabContainerInactiveTabBackground: "#171717"
tabContainerInactiveTabBorder: "#444444"

View File

@@ -1,63 +0,0 @@
# Used internally by the THE() function.
zzzz-the = { PROPER($ent) ->
*[false] the { $ent }
[true] { $ent }
}
# Used internally by the SUBJECT() function.
zzzz-subject-pronoun = { GENDER($ent) ->
[male] he
[female] she
[epicene] they
*[neuter] it
}
# Used internally by the OBJECT() function.
zzzz-object-pronoun = { GENDER($ent) ->
[male] him
[female] her
[epicene] them
*[neuter] it
}
# Used internally by the POSS-PRONOUN() function.
zzzz-possessive-pronoun = { GENDER($ent) ->
[male] his
[female] hers
[epicene] theirs
*[neuter] its
}
# Used internally by the POSS-ADJ() function.
zzzz-possessive-adjective = { GENDER($ent) ->
[male] his
[female] her
[epicene] their
*[neuter] its
}
# Used internally by the REFLEXIVE() function.
zzzz-reflexive-pronoun = { GENDER($ent) ->
[male] himself
[female] herself
[epicene] themselves
*[neuter] itself
}
# Used internally by the CONJUGATE-BE() function.
zzzz-conjugate-be = { GENDER($ent) ->
[epicene] are
*[other] is
}
# Used internally by the CONJUGATE-HAVE() function.
zzzz-conjugate-have = { GENDER($ent) ->
[epicene] have
*[other] has
}
# Used internally by the CONJUGATE-BASIC() function.
zzzz-conjugate-basic = { GENDER($ent) ->
[epicene] { $first }
*[other] { $second }
}

View File

@@ -1,16 +0,0 @@
# Loc strings for various entity state & client-side PVS related commands
cmd-reset-ent-help = Usage: resetent <Entity UID>
cmd-reset-ent-desc = Reset an entity to the most recently received server state. This will also reset entities that have been detached to null-space.
cmd-reset-all-ents-help = Usage: resetallents
cmd-reset-all-ents-desc = Resets all entities to the most recently received server state. This only impacts entities that have not been detached to null-space.
cmd-detach-ent-help = Usage: detachent <Entity UID>
cmd-detach-ent-desc = Detach an entity to null-space, as if it had left PVS range.
cmd-local-delete-help = Usage: localdelete <Entity UID>
cmd-local-delete-desc = Deletes an entity. Unlike the normal delete command, this is CLIENT-SIDE. Unless the entity is a client-side entity, this will likely cause errors.
cmd-full-state-reset-help = Usage: fullstatereset
cmd-full-state-reset-desc = Discards any entity state information and requests a full-state from the server.

View File

@@ -1,31 +1,22 @@
### Localization for engine console commands
## generic command errors
cmd-invalid-arg-number-error = Invalid number of arguments.
## generic
cmd-parse-failure-integer = {$arg} is not a valid integer.
cmd-parse-failure-float = {$arg} is not a valid float.
cmd-parse-failure-bool = {$arg} is not a valid bool.
cmd-parse-failure-uid = {$arg} is not a valid entity UID.
cmd-parse-failure-mapid = {$arg} is not a valid MapId.
cmd-parse-failure-entity-exist = UID {$arg} does not correspond to an existing entity.
cmd-error-file-not-found = Could not find file: {$file}.
cmd-error-dir-not-found = Could not find directory: {$dir}.
cmd-failure-no-attached-entity = There is no entity attached to this shell.
## 'help' command
cmd-oldhelp-desc = Display general help or help text for a specific command
cmd-oldhelp-help = Usage: help [command name]
cmd-help-desc = Display general help or help text for a specific command
cmd-help-help = Usage: help [command name]
When no command name is provided, displays general-purpose help text. If a command name is provided, displays help text for that command.
cmd-oldhelp-no-args = To display help for a specific command, write 'help <command>'. To list all available commands, write 'list'. To search for commands, use 'list <filter>'.
cmd-oldhelp-unknown = Unknown command: { $command }
cmd-oldhelp-top = { $command } - { $description }
cmd-oldhelp-invalid-args = Invalid amount of arguments.
cmd-oldhelp-arg-cmdname = [command name]
cmd-help-no-args = To display help for a specific command, write 'help <command>'. To list all available commands, write 'list'. To search for commands, use 'list <filter>'.
cmd-help-unknown = Unknown command: { $command }
cmd-help-top = { $command } - { $description }
cmd-help-invalid-args = Invalid amount of arguments.
cmd-help-arg-cmdname = [command name]
## 'cvar' command
cmd-cvar-desc = Gets or sets a CVar.
@@ -133,11 +124,6 @@ cmd-monitor-minus-all-hint = Hides all monitors
cmd-monitor-plus-all-hint = Shows all monitors
## 'setambientlight' command
cmd-set-ambient-light-desc = Allows you to set the ambient light for the specified map, in SRGB.
cmd-set-ambient-light-help = setambientlight [mapid] [r g b a]
cmd-set-ambient-light-parse = Unable to parse args as a byte values for a color.
## Mapping commands
cmd-savemap-desc = Serializes a map to disk. Will not save a post-init map unless forced.
@@ -161,403 +147,9 @@ cmd-hint-loadmap-y-position = [y-position]
cmd-hint-loadmap-rotation = [rotation]
cmd-hint-loadmap-uids = [float]
cmd-hint-savebp-id = <Grid EntityID>
## 'flushcookies' command
# Note: the flushcookies command is from Robust.Client.WebView, it's not in the main engine code.
cmd-flushcookies-desc = Flush CEF cookie storage to disk
cmd-flushcookies-help = This ensure cookies are properly saved to disk in the event of unclean shutdowns.
Note that the actual operation is asynchronous.
cmd-ldrsc-desc = Pre-caches a resource.
cmd-ldrsc-help = Usage: ldrsc <path> <type>
cmd-rldrsc-desc = Reloads a resource.
cmd-rldrsc-help = Usage: rldrsc <path> <type>
cmd-gridtc-desc = Gets the tile count of a grid.
cmd-gridtc-help = Usage: gridtc <gridId>
# Client-side commands
cmd-guidump-desc = Dump GUI tree to /guidump.txt in user data.
cmd-guidump-help = Usage: guidump
cmd-uitest-desc = Open a dummy UI testing window
cmd-uitest-help = Usage: uitest
## 'uitest2' command
cmd-uitest2-desc = Opens a UI control testing OS window
cmd-uitest2-help = Usage: uitest2 <tab>
cmd-uitest2-arg-tab = <tab>
cmd-uitest2-error-args = Expected at most one argument
cmd-uitest2-error-tab = Invalid tab: '{$value}'
cmd-uitest2-title = UITest2
cmd-setclipboard-desc = Sets the system clipboard
cmd-setclipboard-help = Usage: setclipboard <text>
cmd-getclipboard-desc = Gets the system clipboard
cmd-getclipboard-help = Usage: Getclipboard
cmd-togglelight-desc = Toggles light rendering.
cmd-togglelight-help = Usage: togglelight
cmd-togglefov-desc = Toggles fov for client.
cmd-togglefov-help = Usage: togglefov
cmd-togglehardfov-desc = Toggles hard fov for client. (for debugging space-station-14#2353)
cmd-togglehardfov-help = Usage: togglehardfov
cmd-toggleshadows-desc = Toggles shadow rendering.
cmd-toggleshadows-help = Usage: toggleshadows
cmd-togglelightbuf-desc = Toggles lighting rendering. This includes shadows but not FOV.
cmd-togglelightbuf-help = Usage: togglelightbuf
cmd-chunkinfo-desc = Gets info about a chunk under your mouse cursor.
cmd-chunkinfo-help = Usage: chunkinfo
cmd-rldshader-desc = Reloads all shaders.
cmd-rldshader-help = Usage: rldshader
cmd-cldbglyr-desc = Toggle fov and light debug layers.
cmd-cldbglyr-help= Usage: cldbglyr <layer>: Toggle <layer>
cldbglyr: Turn all Layers off
cmd-key-info-desc = Keys key info for a key.
cmd-key-info-help = Usage: keyinfo <Key>
## 'bind' command
cmd-bind-desc = Binds an input key combination to an input command.
cmd-bind-help = Usage: bind { cmd-bind-arg-key } { cmd-bind-arg-mode } { cmd-bind-arg-command }
Note that this DOES NOT automatically save bindings.
Use the 'svbind' command to save binding configuration.
cmd-bind-arg-key = <KeyName>
cmd-bind-arg-mode = <BindMode>
cmd-bind-arg-command = <InputCommand>
cmd-net-draw-interp-desc = Toggles the debug drawing of the network interpolation.
cmd-net-draw-interp-help = Usage: net_draw_interp
cmd-net-draw-interp-desc = Toggles the debug drawing of the network interpolation.
cmd-net-draw-interp-help = Usage: net_draw_interp
cmd-net-watch-ent-desc = Dumps all network updates for an EntityId to the console.
cmd-net-watch-ent-help = Usage: net_watchent <0|EntityUid>
cmd-net-refresh-desc = Requests a full server state.
cmd-net-refresh-help = Usage: net_refresh
cmd-net-entity-report-desc = Toggles the net entity report panel.
cmd-net-entity-report-help = Usage: net_entityreport
cmd-fill-desc = Fill up the console for debugging.
cmd-fill-help = Fills the console with some nonsense for debugging.
cmd-cls-desc = Clears the console.
cmd-cls-help = Clears the debug console of all messages.
cmd-sendgarbage-desc = Sends garbage to the server.
cmd-sendgarbage-help = The server will reply with 'no u'
cmd-loadgrid-desc = Loads a grid from a file into an existing map.
cmd-loadgrid-help = loadgrid <MapID> <Path> [x y] [rotation] [storeUids]
cmd-loc-desc = Prints the absolute location of the player's entity to console.
cmd-loc-help = loc
cmd-tpgrid-desc = Teleports a grid to a new location.
cmd-tpgrid-help = tpgrid <gridId> <X> <Y> [<MapId>]
cmd-rmgrid-desc = Removes a grid from a map. You cannot remove the default grid.
cmd-rmgrid-help = rmgrid <gridId>
cmd-mapinit-desc = Runs map init on a map.
cmd-mapinit-help = mapinit <mapID>
cmd-lsmap-desc = Lists maps.
cmd-lsmap-help = lsmap
cmd-lsgrid-desc = Lists grids.
cmd-lsgrid-help = lsgrid
cmd-addmap-desc = Adds a new empty map to the round. If the mapID already exists, this command does nothing.
cmd-addmap-help = addmap <mapID> [initialize]
cmd-rmmap-desc = Removes a map from the world. You cannot remove nullspace.
cmd-rmmap-help = rmmap <mapId>
cmd-savegrid-desc = Serializes a grid to disk.
cmd-savegrid-help = savegrid <gridID> <Path>
cmd-testbed-desc = Loads a physics testbed on the specified map.
cmd-testbed-help = testbed <mapid> <test>
cmd-saveconfig-desc = Saves the client configuration to the config file.
cmd-saveconfig-help = saveconfig
## 'flushcookies' command
# Note: the flushcookies command is from Robust.Client.WebView, it's not in the main engine code.
cmd-flushcookies-desc = Flush CEF cookie storage to disk
cmd-flushcookies-help = This ensure cookies are properly saved to disk in the event of unclean shutdowns.
Note that the actual operation is asynchronous.
## 'addcomp' command
cmd-addcomp-desc = Adds a component to an entity.
cmd-addcomp-help = addcomp <uid> <componentName>
cmd-addcompc-desc = Adds a component to an entity on the client.
cmd-addcompc-help = addcompc <uid> <componentName>
## 'rmcomp' command
cmd-rmcomp-desc = Removes a component from an entity.
cmd-rmcomp-help = rmcomp <uid> <componentName>
cmd-rmcompc-desc = Removes a component from an entity on the client.
cmd-rmcompc-help = rmcomp <uid> <componentName>
## 'addview' command
cmd-addview-desc = Allows you to subscribe to an entity's view for debugging purposes.
cmd-addview-help = addview <entityUid>
cmd-addviewc-desc = Allows you to subscribe to an entity's view for debugging purposes.
cmd-addviewc-help = addview <entityUid>
## 'removeview' command
cmd-removeview-desc = Allows you to unsubscribe to an entity's view for debugging purposes.
cmd-removeview-help = removeview <entityUid>
## 'loglevel' command
cmd-loglevel-desc = Changes the log level for a provided sawmill.
cmd-loglevel-help = Usage: loglevel <sawmill> <level>
sawmill: A label prefixing log messages. This is the one you're setting the level for.
level: The log level. Must match one of the values of the LogLevel enum.
cmd-testlog-desc = Writes a test log to a sawmill.
cmd-testlog-help = Usage: testlog <sawmill> <level> <message>
sawmill: A label prefixing the logged message.
level: The log level. Must match one of the values of the LogLevel enum.
message: The message to be logged. Wrap this in double quotes if you want to use spaces.
## 'vv' command
cmd-vv-desc = Opens View Variables.
cmd-vv-help = Usage: vv <entity ID|IoC interface name|SIoC interface name>
## 'showvelocities' command
cmd-showvelocities-desc = Displays your angular and linear velocities.
cmd-showvelocities-help = Usage: showvelocities
## 'setinputcontext' command
cmd-setinputcontext-desc = Sets the active input context.
cmd-setinputcontext-help = Usage: setinputcontext <context>
## 'forall' command
cmd-forall-desc = Runs a command over all entities with a given component.
cmd-forall-help = Usage: forall <bql query> do <command...>
## 'delete' command
cmd-delete-desc = Deletes the entity with the specified ID.
cmd-delete-help = delete <entity UID>
# System commands
cmd-showtime-desc = Shows the server time.
cmd-showtime-help = showtime
cmd-restart-desc = Gracefully restarts the server (not just the round).
cmd-restart-help = restart
cmd-shutdown-desc = Gracefully shuts down the server.
cmd-shutdown-help = shutdown
cmd-saveconfig-desc = Saves the server configuration to the config file.
cmd-saveconfig-help = saveconfig
cmd-netaudit-desc = Prints into about NetMsg security.
cmd-netaudit-help = netaudit
# Player commands
cmd-tp-desc = Teleports a player to any location in the round.
cmd-tp-help = tp <x> <y> [<mapID>]
cmd-tpto-desc = Teleports the current player or the specified players/entities to the location of the first player/entity.
cmd-tpto-help = tpto <username|uid> [username|uid]...
cmd-tpto-destination-hint = destination (uid or username)
cmd-tpto-victim-hint = entity to teleport (uid or username)
cmd-tpto-parse-error = Cant resolve entity or player: {$str}
cmd-listplayers-desc = Lists all players currently connected.
cmd-listplayers-help = listplayers
cmd-kick-desc = Kicks a connected player out of the server, disconnecting them.
cmd-kick-help = kick <PlayerIndex> [<Reason>]
# Spin command
cmd-spin-desc = Causes an entity to spin. Default entity is the attached player's parent.
cmd-spin-help = spin velocity [drag] [entityUid]
# Localization command
cmd-rldloc-desc = Reloads localization (client & server).
cmd-rldloc-help = Usage: rldloc
# Debug entity controls
cmd-spawn-desc = Spawns an entity with specific type.
cmd-spawn-help = spawn <prototype> OR spawn <prototype> <relative entity ID> OR spawn <prototype> <x> <y>
cmd-cspawn-desc = Spawns a client-side entity with specific type at your feet.
cmd-cspawn-help = cspawn <entity type>
cmd-scale-desc = Increases or decreases an entity's size naively.
cmd-scale-help = scale <entityUid> <float>
cmd-dumpentities-desc = Dump entity list.
cmd-dumpentities-help = Dumps entity list of UIDs and prototype.
cmd-getcomponentregistration-desc = Gets component registration information.
cmd-getcomponentregistration-help = Usage: getcomponentregistration <componentName>
cmd-showrays-desc = Toggles debug drawing of physics rays. An integer for <raylifetime> must be provided.
cmd-showrays-help = Usage: showrays <raylifetime>
cmd-disconnect-desc = Immediately disconnect from the server and go back to the main menu.
cmd-disconnect-help = Usage: disconnect
cmd-entfo-desc = Displays verbose diagnostics for an entity.
cmd-entfo-help = Usage: entfo <entityuid>
The entity UID can be prefixed with 'c' to convert it to a client entity UID.
cmd-fuck-desc = Throws an exception
cmd-fuck-help = Throws an exception
cmd-showpos-desc = Enables debug drawing over all entity positions in the game.
cmd-showpos-help = Usage: showpos
cmd-sggcell-desc = Lists entities on a snap grid cell.
cmd-sggcell-help = Usage: sggcell <gridID> <vector2i>\nThat vector2i param is in the form x<int>,y<int>.
cmd-overrideplayername-desc = Changes the name used when attempting to connect to the server.
cmd-overrideplayername-help = Usage: overrideplayername <name>
cmd-showanchored-desc = Shows anchored entities on a particular tile
cmd-showanchored-help = Usage: showanchored
cmd-dmetamem-desc = Dumps a type's members in a format suitable for the sandbox configuration file.
cmd-dmetamem-help = Usage: dmetamem <type>
cmd-dmetamem-desc = Displays chunk bounds for the purposes of rendering.
cmd-dmetamem-help = Usage: showchunkbb <type>
cmd-launchauth-desc = Load authentication tokens from launcher data to aid in testing of live servers.
cmd-launchauth-help = Usage: launchauth <account name>
cmd-lightbb-desc = Toggles whether to show light bounding boxes.
cmd-lightbb-help = Usage: lightbb
cmd-monitorinfo-desc = Monitors info
cmd-monitorinfo-help = Usage: monitorinfo <id>
cmd-setmonitor-desc = Set monitor
cmd-setmonitor-help = Usage: setmonitor <id>
cmd-physics-desc = Shows a debug physics overlay. The arg supplied specifies the overlay.
cmd-physics-help = Usage: physics <aabbs / com / contactnormals / contactpoints / distance / joints / shapeinfo / shapes>
cmd-hardquit-desc = Kills the game client instantly.
cmd-hardquit-help = Kills the game client instantly, leaving no traces. No telling the server goodbye.
cmd-quit-desc = Shuts down the game client gracefully.
cmd-quit-help = Properly shuts down the game client, notifying the connected server and such.
cmd-csi-desc = Opens a C# interactive console.
cmd-csi-help = Usage: csi
cmd-scsi-desc = Opens a C# interactive console on the server.
cmd-scsi-help = Usage: scsi
cmd-watch-desc = Opens a variable watch window.
cmd-watch-help = Usage: watch
cmd-showspritebb-desc = Toggle whether sprite bounds are shown
cmd-showspritebb-help = Usage: showspritebb
cmd-togglelookup-desc = Shows / hides entitylookup bounds via an overlay.
cmd-togglelookup-help = Usage: togglelookup
cmd-net_entityreport-desc = Toggles the net entity report panel.
cmd-net_entityreport-help = Usage: net_entityreport
cmd-net_refresh-desc = Requests a full server state.
cmd-net_refresh-help = Usage: net_refresh
cmd-net_graph-desc = Toggles the net statistics pannel.
cmd-net_graph-help = Usage: net_graph
cmd-net_watchent-desc = Dumps all network updates for an EntityId to the console.
cmd-net_watchent-help = Usage: net_watchent <0|EntityUid>
cmd-net_draw_interp-desc = Toggles the debug drawing of the network interpolation.
cmd-net_draw_interp-help = Usage: net_draw_interp <0|EntityUid>
cmd-vram-desc = Displays video memory usage statics by the game.
cmd-vram-help = Usage: vram
cmd-showislands-desc = Shows the current physics bodies involved in each physics island.
cmd-showislands-help = Usage: showislands
cmd-showgridnodes-desc = Shows the nodes for grid split purposes.
cmd-showgridnodes-help = Usage: showgridnodes
cmd-profsnap-desc = Make a profiling snapshot.
cmd-profsnap-help = Usage: profsnap
cmd-devwindow-desc = Dev Window
cmd-devwindow-help = Usage: devwindow
cmd-devwindow-desc = Open file
cmd-devwindow-help = Usage: testopenfile
cmd-scene-desc = Immediately changes the UI scene/state.
cmd-scene-help = Usage: scene <className>
cmd-szr_stats-desc = Report serializer statistics.
cmd-szr_stats-help = Usage: szr_stats
cmd-hwid-desc = Returns the current HWID (HardWare ID).
cmd-hwid-help = Usage: hwid
cmd-vvread-desc = Retrieve a path's value using VV (View Variables).
cmd-vvread-desc = Usage: vvread <path>
cmd-vvwrite-desc = Modify a path's value using VV (View Variables).
cmd-vvwrite-help = Usage: vvwrite <path>
cmd-vv-desc = Opens View Variables (VV).
cmd-vv-help = Usage: vv <path|entity ID|guihover>
cmd-vvinvoke-desc = Invoke/Call a path with arguments using VV.
cmd-vvinvoke-help = Usage: vvinvoke <path> [arguments...]
cmd-dump_dependency_injectors-desc = Dump IoCManager's dependency injector cache.
cmd-dump_dependency_injectors-help = Usage: dump_dependency_injectors
cmd-dump_dependency_injectors-total-count = Total count: { $total }
cmd-dump_netserializer_type_map-desc = Dump NetSerializer's type map and serializer hash.
cmd-dump_netserializer_type_map-help = Usage: dump_netserializer_type_map
cmd-hub_advertise_now-desc = Immediately advertise to the master hub server
cmd-hub_advertise_now-help = Usage: hub_advertise_now
cmd-echo-desc = Echo arguments back to the console
cmd-echo-help = Usage: echo "<message>"
## 'vfs_ls' command
cmd-vfs_ls-desc = List directory contents in the VFS.
cmd-vfs_ls-help = Usage: vfs_list <path>
Example:
vfs_list /Assemblies
cmd-vfs_ls-err-args = Need exactly 1 argument.
cmd-vfs_ls-hint-path = <path>
cmd-reloadtiletextures-desc = Reloads the tile texture atlas to allow hot reloading tile sprites
cmd-reloadtiletextures-help = Usage: reloadtiletextures

View File

@@ -3,7 +3,6 @@
entity-spawn-window-title = Entity Spawn Panel
entity-spawn-window-search-bar-placeholder = search
entity-spawn-window-clear-button = Clear
entity-spawn-window-replace-button-text = Replace
entity-spawn-window-erase-button-text = Erase Mode
entity-spawn-window-override-menu-tooltip = Override placement

View File

@@ -1,3 +0,0 @@
debug-builtin-connection-screen-invalid-username-with-reason = The given username is invalid: {$invalidreason}
debug-builtin-connection-screen-invalid-username = Invalid Username.
debug-builtin-connection-screen-failed-to-connect = Failed to connect: {$reason}

View File

@@ -1,5 +0,0 @@
discord-rpc-in-main-menu = In Main Menu
discord-rpc-in-main-menu-logo-text = I think coolsville SUCKS
discord-rpc-character = Username: {$username}
discord-rpc-on-server = On Server: {$servername}
discord-rpc-players = Players: {$players}/{$maxplayers}

View File

@@ -18,15 +18,6 @@ input-key-F12 = F12
input-key-F13 = F13
input-key-F14 = F14
input-key-F15 = F15
input-key-F16 = F16
input-key-F17 = F17
input-key-F18 = F18
input-key-F19 = F19
input-key-F20 = F20
input-key-F21 = F21
input-key-F22 = F22
input-key-F23 = F23
input-key-F24 = F24
input-key-Pause = Pause
input-key-Left = Left
input-key-Up = Up
@@ -34,22 +25,7 @@ input-key-Down = Down
input-key-Right = Right
input-key-Space = Space
input-key-Return = Return
input-key-NumpadEnter = Numpad Enter
input-key-NumpadNum0 = Numpad 0
input-key-NumpadNum1 = Numpad 1
input-key-NumpadNum2 = Numpad 2
input-key-NumpadNum3 = Numpad 3
input-key-NumpadNum4 = Numpad 4
input-key-NumpadNum5 = Numpad 5
input-key-NumpadNum6 = Numpad 6
input-key-NumpadNum7 = Numpad 7
input-key-NumpadNum8 = Numpad 8
input-key-NumpadNum9 = Numpad 9
input-key-NumpadAdd = Numpad Add
input-key-NumpadSubtract = Numpad Subtract
input-key-NumpadDivide = Numpad Divide
input-key-NumpadMultiply = Numpad Multiply
input-key-NumpadDecimal = Numpad Decimal
input-key-NumpadEnter = Num Enter
input-key-BackSpace = Backspace
input-key-Tab = Tab
input-key-PageUp = Page Up

View File

@@ -1 +1 @@
cmd-midipanic-desc = Turns off every note for every active MIDI renderer.
midi-panic-command-description = Turns off every note for every active MIDI renderer.

View File

@@ -1,59 +0,0 @@
# Playback Commands
cmd-replay-play-desc = Resume replay playback.
cmd-replay-play-help = replay_play
cmd-replay-pause-desc = Pause replay playback
cmd-replay-pause-help = replay_pause
cmd-replay-toggle-desc = Resume or pause replay playback.
cmd-replay-toggle-help = replay_toggle
cmd-replay-stop-desc = Stop and unload a replay.
cmd-replay-stop-help = replay_stop
cmd-replay-load-desc = Load and start a replay.
cmd-replay-load-help = replay_load <replay folder>
cmd-replay-load-hint = Replay folder
cmd-replay-skip-desc = Skip forwards or backwards in time.
cmd-replay-skip-help = replay_skip <tick or timespan>
cmd-replay-skip-hint = Ticks or timespan (HH:MM:SS).
cmd-replay-set-time-desc = Jump forwards or backwards to some specific time.
cmd-replay-set-time-help = replay_set <tick or time>
cmd-replay-set-time-hint = Tick or timespan (HH:MM:SS), starting from
cmd-replay-error-time = "{$time}" is not an integer or timespan.
cmd-replay-error-args = Wrong number of arguments.
cmd-replay-error-no-replay = Not currently playing a replay.
cmd-replay-error-already-loaded = A replay is already loaded.
cmd-replay-error-run-level = You cannot load a replay while connected to a server.
# Recording commands
cmd-replay-recording-start-desc = Starts a replay recording, optionally with some time limit.
cmd-replay-recording-start-help = Usage: replay_recording_start [name] [overwrite] [time limit]
cmd-replay-recording-start-success = Started recording a replay.
cmd-replay-recording-start-already-recording = Already recording a replay.
cmd-replay-recording-start-error = An error occurred while trying to start the recording.
cmd-replay-recording-start-hint-time = [time limit (minutes)]
cmd-replay-recording-start-hint-name = [name]
cmd-replay-recording-start-hint-overwrite = [overwrite (bool)]
cmd-replay-recording-stop-desc = Stops a replay recording.
cmd-replay-recording-stop-help = Usage: replay_recording_stop
cmd-replay-recording-stop-success = Stopped recording a replay.
cmd-replay-recording-stop-not-recording = Not currently recording a replay.
cmd-replay-recording-stats-desc = Displays information about the current replay recording.
cmd-replay-recording-stats-help = Usage: replay_recording_stats
cmd-replay-recording-stats-result = Duration: {$time} min, Ticks: {$ticks}, Size: {$size} MB, rate: {$rate} MB/min.
# Time Control UI
replay-time-box-scrubbing-label = Dynamic Scrubbing
replay-time-box-replay-time-label = Recording Time: {$current} / {$end} ({$percentage}%)
replay-time-box-server-time-label = Server Time: {$current} / {$end}
replay-time-box-index-label = Index: {$current} / {$total}
replay-time-box-tick-label = Tick: {$current} / {$total}

View File

@@ -1,423 +0,0 @@
command-description-tpto =
Teleport the given entities to some target entity.
command-description-player-list =
Returns a list of all player sessions.
command-description-player-self =
Returns the current player session.
command-description-player-imm =
Returns the session associated with the player given as argument.
command-description-player-entity =
Returns the entities of the input sessions.
command-description-self =
Returns the current attached entity.
command-description-physics-velocity =
Returns the velocity of the input entities.
command-description-physics-angular-velocity =
Returns the angular velocity of the input entities.
command-description-buildinfo =
Provides information about the build of the game.
command-description-cmd-list =
Returns a list of all commands, for this side.
command-description-explain =
Explains the given expression, providing command descriptions and signatures.
command-description-search =
Searches through the input for the provided value.
command-description-stopwatch =
Measures the execution time of the given expression.
command-description-types-consumers =
Provides all commands that can consume the given type.
command-description-types-tree =
Debug tool to return all types the command interpreter can downcast the input to.
command-description-types-gettype =
Returns the type of the input.
command-description-types-fullname =
Returns the full name of the input type according to CoreCLR.
command-description-as =
Casts the input to the given type.
Effectively a type hint if you know the type but the interpreter does not.
command-description-count =
Counts the amount of entries in it's input, returning an integer.
command-description-map =
Maps the input over the given block, with the provided expected return type.
This command may be modified to not need an explicit return type in the future.
command-description-select =
Selects N objects or N% of objects from the input.
One can additionally invert this command with not to make it select everything except N objects instead.
command-description-comp =
Returns the given component from the input entities, discarding entities without that component.
command-description-delete =
Deletes the input entities.
command-description-ent =
Returns the provided entity ID.
command-description-entities =
Returns all entities on the server.
command-description-paused =
Filters the input entities by whether or not they are paused.
This command can be inverted with not.
command-description-with =
Filters the input entities by whether or not they have the given component.
This command can be inverted with not.
command-description-fuck =
Throws an exception.
command-description-ecscomp-listty =
Lists every type of component registered.
command-description-cd =
Changes the session's current directory to the given relative or absolute path.
command-description-ls-here =
Lists the contents of the current directory.
command-description-ls-in =
Lists the contents of the given relative or absolute path.
command-description-methods-get =
Returns all methods associated with the input type.
command-description-methods-overrides =
Returns all methods overriden on the input type.
command-description-methods-overridesfrom =
Returns all methods overriden from the given type on the input type.
command-description-cmd-moo =
Asks the important questions.
command-description-cmd-descloc =
Returns the localization string for a command's description.
command-description-cmd-getshim =
Returns a command's execution shim.
command-description-help =
Provides a quick rundown of how to use toolshed.
command-description-ioc-registered =
Returns all the types registered with IoCManager on the current thread (usually the game thread)
command-description-ioc-get =
Gets an instance of an IoC registration.
command-description-loc-tryloc =
Tries to get a localization string, returning null if unable.
command-description-loc-loc =
Gets a localization string, returning the unlocalized string if unable.
command-description-physics-angular_velocity =
Returns the angular velocity of the given entities.
command-description-vars =
Provides a list of all variables set in this session.
command-description-any =
Returns true if there's any values in the input, otherwise false.
command-description-ArrowCommand =
Assigns the input to a variable.
command-description-isempty =
Returns true if the input is empty, otherwise false.
command-description-isnull =
Returns true if the input is null, otherwise false.
command-description-unique =
Filters the input sequence for uniqueness, removing duplicate values.
command-description-where =
Given some input sequence IEnumerable<T>, takes a block of signature T -> bool that decides if each input value should be included in the output sequence.
command-description-do =
Backwards compatibility with BQL, applies the given old commands over the input sequence.
command-description-named =
Filters the input entities by their name, with the regex ^selector$.
command-description-prototyped =
Filters the input entities by their prototype.
command-description-nearby =
Creates a new list of all entities nearby the inputs within the given range.
command-description-first =
Returns the first entry of the given enumerable.
command-description-splat =
"Splats" a block, value, or variable, creating N copies of it in a list.
command-description-val =
Casts the given value, block, or variable to the given type. This is mostly a workaround for current limitations of variables.
command-description-actor-controlled =
Filters entities by whether or not they're actively controlled.
command-description-actor-session =
Returns the sessions associated with the input entities.
command-description-physics-parent =
Returns the parent(s) of the input entities.
command-description-emplace =
Runs the given block over it's inputs, with the input value placed into the variable $value within the block.
Additionally breaks out $wx, $wy, $proto, $desc, $name, and $paused for entities.
Can also have breakout values for other types, consult the documentation for that type for further info.
command-description-AddCommand =
Performs numeric addition.
command-description-SubtractCommand =
Performs numeric subtraction.
command-description-MultiplyCommand =
Performs numeric multiplication.
command-description-DivideCommand =
Performs numeric division.
command-description-min =
Returns the minimum of two values.
command-description-max =
Returns the maximum of two values.
command-description-BitAndCommand =
Performs bitwise AND.
command-description-BitOrCommand =
Performs bitwise OR.
command-description-BitXorCommand =
Performs bitwise XOR.
command-description-neg =
Negates the input.
command-description-GreaterThanCommand =
Performs a greater-than comparison, x > y.
command-description-LessThanCommand =
Performs a less-than comparison, x < y.
command-description-GreaterThanOrEqualCommand =
Performs a greater-than-or-equal comparison, x >= y.
command-description-LessThanOrEqualCommand =
Performs a less-than-or-equal comparison, x <= y.
command-description-EqualCommand =
Performs an equality comparison, returning true if the inputs are equal.
command-description-NotEqualCommand =
Performs an equality comparison, returning true if the inputs are not equal.
command-description-append =
Appends a value to the input enumerable.
command-description-DefaultIfNullCommand =
Replaces the input with the type's default value if it is null, albeit only for value types (not objects).
command-description-OrValueCommand =
If the input is null, uses the provided alternate value.
command-description-DebugPrintCommand =
Prints the given value transparently, for debug prints in a command run.
command-description-i =
Integer constant.
command-description-f =
Float constant.
command-description-s =
String constant.
command-description-b =
Bool constant.
command-description-join =
Joins two sequences together into one sequence.
command-description-reduce =
Given a block to use as a reducer, turns a sequence into a single value.
The left hand side of the block is implied, and the right hand is stored in $value.
command-description-rep =
Repeats the input value N times to form a sequence.
command-description-take =
Takes N values from the input sequence
command-description-spawn-at =
Spawns an entity at the given coordinates.
command-description-spawn-on =
Spawns an entity on the given entity, at it's coordinates.
command-description-spawn-attached =
Spawns an entity attached to the given entity, at (0 0) relative to it.
command-description-mappos =
Returns an entity's coordinates relative to it's current map.
command-description-pos =
Returns an entity's coordinates.
command-description-tp-coords =
Teleports the target to the given coordinates.
command-description-tp-to =
Teleports the target to the given other entity.
command-description-tp-into =
Teleports the target "into" the given other entity, attaching it at (0 0) relative to it.
command-description-comp-get =
Gets the given component from the given entity.
command-description-comp-add =
Adds the given component to the given entity.
command-description-comp-ensure =
Ensures the given entity has the given component.
command-description-comp-has =
Check if the given entity has the given component.
command-description-AddVecCommand =
Adds a scalar (single value) to every element in the input.
command-description-SubVecCommand =
Subtracts a scalar (single value) from every element in the input.
command-description-MulVecCommand =
Multiplies a scalar (single value) by every element in the input.
command-description-DivVecCommand =
Divides every element in the input by a scalar (single value).
command-description-rng-to =
Returns a number from its input to its argument (i.e. n..m inclusive)
command-description-rng-from =
Returns a number to its input from its argument (i.e. m..n inclusive)
command-description-rng-prob =
Returns a boolean based on the input probability/chance (from 0 to 1)
command-description-sum =
Computes the sum of the input.
command-description-bin =
"Bins" the input, counting up how many times each unique element occurs.
command-description-extremes =
Returns the two extreme ends of a list, interwoven.
command-description-sortby =
Sorts the input least to greatest by the computed key.
command-description-sortmapby =
Sorts the input least to greatest by the computed key, replacing the value with it's computed key afterward.
command-description-sort =
Sorts the input least to greatest.
command-description-sortdownby =
Sorts the input greatest to least by the computed key.
command-description-sortmapdownby =
Sorts the input greatest to least by the computed key, replacing the value with it's computed key afterward.
command-description-sortdown =
Sorts the input greatest to least.
command-description-iota =
Returns a list of numbers 1 to N.
command-description-to =
Returns a list of numbers N to M.
command-description-curtick =
The current game tick.
command-description-curtime =
The current game time (a TimeSpan)
command-description-realtime =
The current realtime since startup (a TimeSpan)
command-description-servertime =
The current server game time, or zero if we are the server (a TimeSpan)
command-description-replace =
Replaces the input entities with the given prototype, preserving position and rotation (but nothing else)
command-description-allcomps =
Returns all components on the given entity.
command-description-entitysystemupdateorder-tick =
Lists the tick update order of entity systems.
command-description-entitysystemupdateorder-frame =
Lists the frame update order of entity systems.
command-description-more =
Prints the contents of $more, i.e. any extras that Toolshed didn't print from the last command.
command-description-ModulusCommand =
Computes the modulus of two values.
This is usually remainder, check C#'s documentation for the type.
command-description-ModVecCommand =
Performs the modulus operation over the input with the given constant right-hand value.
command-description-BitAndNotCommand =
Performs bitwise AND-NOT over the input.
command-description-BitOrNotCommand =
Performs bitwise OR-NOT over the input.
command-description-BitXnorCommand =
Performs bitwise XNOR over the input.
command-description-BitNotCommand =
Performs bitwise NOT on the input.
command-description-abs =
Computes the absolute value of the input (removing the sign)
command-description-average =
Computes the average (arithmetic mean) of the input.
command-description-bibytecount =
Returns the size of the input in bytes, given that the input implements IBinaryInteger.
This is NOT sizeof.
command-description-shortestbitlength =
Returns the minimum number of bits needed to represent the input value.
command-description-countleadzeros =
Counts the number of leading binary zeros in the input value.
command-description-counttrailingzeros =
Counts the number of trailing binary zeros in the input value.
command-description-fpi =
pi (3.14159...) as a float.
command-description-fe =
e (2.71828...) as a float.
command-description-ftau =
tau (6.28318...) as a float.
command-description-fepsilon =
The epsilon value for a float, exactly 1.4e-45.
command-description-dpi =
pi (3.14159...) as a double.
command-description-de =
e (2.71828...) as a double.
command-description-dtau =
tau (6.28318...) as a double.
command-description-depsilon =
The epsilon value for a double, exactly 4.9406564584124654E-324.
command-description-hpi =
pi (3.14...) as a half.
command-description-he =
e (2.71...) as a half.
command-description-htau =
tau (6.28...) as a half.
command-description-hepsilon =
The epsilon value for a half, exactly 5.9604645E-08.
command-description-floor =
Returns the floor of the input value (rounding toward zero).
command-description-ceil =
Returns the ceil of the input value (rounding away from zero).
command-description-round =
Rounds the input value.
command-description-trunc =
Truncates the input value.
command-description-round2frac =
Rounds the input value to the specified number of fractional digits.
command-description-exponentbytecount =
Returns the number of bytes required to store the exponent.
command-description-significandbytecount =
Returns the number of bytes required to store the significand.
command-description-significandbitcount =
Returns the exact bit length of the significand.
command-description-exponentshortestbitcount =
Returns the minimum number of bits to store the exponent.
command-description-stepnext =
Steps to the next float value, adding one to the significand with carry.
command-description-stepprev =
Steps to the previous float value, subtracting one from the significand with carry.
command-description-checkedto =
Converts from the input numeric type to the target, erroring if not possible.
command-description-saturateto =
Converts from the input numeric type to the target, saturating if the value is out of range.
For example, converting 382 to a byte would saturate to 255 (the maximum value of a byte).
command-description-truncto =
Converts from the input numeric type to the target, with truncation.
In the case of integers, this is a bit cast with sign extension.
command-description-iscanonical =
Returns whether the input is in canonical form.
command-description-iscomplex =
Returns whether the input is a complex number (by value, not by type)
command-description-iseven =
Returns whether the input is even.
Not a javascript package.
command-description-isodd =
Returns whether the input is odd.
command-description-isfinite =
Returns whether the input is finite.
command-description-isimaginary =
Returns whether the input is purely imaginary (no real part).
command-description-isinfinite =
Returns whether the input is infinite.
command-description-isinteger =
Returns whether the input is an integer (by value, not by type)
command-description-isnan =
Returns whether the input is Not a Number (NaN).
This is a special floating point value, so this is by value, not by type.
command-description-isnegative =
Returns whether the input is negative.
command-description-ispositive =
Returns whether the input is positive.
command-description-isreal =
Returns whether the input is purely real (no imaginary part).
command-description-issubnormal =
Returns whether the input is in sub-normal form.
command-description-iszero =
Returns whether the input is zero.
command-description-pow =
Computes the power of its lefthand to its righthand. x^y.
command-description-sqrt =
Computes the square root of its input.
command-description-cbrt =
Computes the cube root of its input.
command-description-root =
Computes the Nth root of its input.
command-description-hypot =
Computes the hypotenuse of a triangle with the given sides A and B.
command-description-sin =
Computes the sine of the input.
command-description-sinpi =
Computes the sine of the input multiplied by pi.
command-description-asin =
Computes the arcsine of the input.
command-description-asinpi =
Computes the arcsine of the input multiplied by pi.
command-description-cos =
Computes the cosine of the input.
command-description-cospi =
Computes the cosine of the input multiplied by pi.
command-description-acos =
Computes the arcosine of the input.
command-description-acospi =
Computes the arcosine of the input multiplied by pi.
command-description-tan =
Computes the tangent of the input.
command-description-tanpi =
Computes the tangent of the input multiplied by pi.
command-description-atan =
Computes the arctangent of the input.
command-description-atanpi =
Computes the arctangent of the input multiplied by pi.
command-description-iterate =
Iterates the given function over the input N times, returning a list of results.
Think of this like successively applying the function to a value, tracking all the intermediate values.
command-description-pick =
Picks a random value from the input.
command-description-tee =
Tees the input into the given block, ignoring the block's result.
This essentially lets you have a branch in your code to do multiple operations on one value.
command-description-cmd-info =
Returns a CommandSpec for the given command.
On it's own, this means it'll print the comamnd's help message.
command-description-comp-rm =
Removes the given component from the entity.

View File

@@ -1,7 +0,0 @@
uploadfolder-command-description = Uploads a folder from your UserData folder recursively to the server contentDB.
uploadfolder-command-help = uploadfolder [folder you want to upload in userdata/UploadFolder]
uploadfolder-command-wrong-args = Wrong number of arguments!
uploadfolder-command-folder-not-found = Folder {$folder} not found!
uploadfolder-command-resource-upload-disabled = Network Resource Uploading is currently disabled. check Server CVars.
uploadfolder-command-file-too-big = File {$filename} above the current size limit! It must be smaller than {$sizeLimit} MB. skipping.
uploadfolder-command-success = Uploaded {$fileCount} files

View File

@@ -1,63 +0,0 @@
# Used internally by the THE() function.
zzzz-the = { PROPER($ent) ->
*[false] a { $ent }
[true] { $ent }
}
# Used internally by the SUBJECT() function.
zzzz-subject-pronoun = { GENDER($ent) ->
[male] ele
[female] ela
[epicene] eles
*[neuter] ele
}
# Used internally by the OBJECT() function.
zzzz-object-pronoun = { GENDER($ent) ->
[male] ele
[female] ela
[epicene] eles
*[neuter] isso
}
# Used internally by the POSS-PRONOUN() function.
zzzz-possessive-pronoun = { GENDER($ent) ->
[male] dele
[female] dela
[epicene] deles
*[neuter] dele
}
# Used internally by the POSS-ADJ() function.
zzzz-possessive-adjective = { GENDER($ent) ->
[male] dele
[female] dela
[epicene] deles
*[neuter] dele
}
# Used internally by the REFLEXIVE() function.
zzzz-reflexive-pronoun = { GENDER($ent) ->
[male] ele mesmo
[female] ela mesmo
[epicene] eles mesmos
*[neuter] ele mesmo
}
# Used internally by the CONJUGATE-BE() function.
zzzz-conjugate-be = { GENDER($ent) ->
[epicene] é
*[other] é
}
# Used internally by the CONJUGATE-HAVE() function.
zzzz-conjugate-have = { GENDER($ent) ->
[epicene] tenho
*[other] tem
}
# Used internally by the CONJUGATE-BASIC() function.
zzzz-conjugate-basic = { GENDER($ent) ->
[epicene] { $first }
*[other] { $second }
}

View File

@@ -1,16 +0,0 @@
# Strings Loc para vários comandos relacionados ao estado da entidade e ao PVS do lado do cliente
cmd-reset-ent-help = Uso: resetent <Entity UID>
cmd-reset-ent-desc = Redefina uma entidade para o estado do servidor recebido mais recentemente. Isso também redefinirá as entidades que foram desanexadas para espaço nulo.
cmd-reset-all-ents-help = Uso: resetallents
cmd-reset-all-ents-desc = Redefine todas as entidades para o estado do servidor recebido mais recentemente. Isso afeta apenas as entidades que não foram desanexadas ao espaço nulo.
cmd-detach-ent-help = Uso: detachent <Entity UID>
cmd-detach-ent-desc = Desanexar uma entidade para espaço nulo, como se tivesse saído do intervalo PVS.
cmd-local-delete-help = Uso: localdelete <Entity UID>
cmd-local-delete-desc = Exclui uma entidade. Ao contrário do comando delete normal, este é CLIENT-SIDE. A menos que a entidade seja uma entidade do lado do cliente, isso provavelmente causará erros.
cmd-full-state-reset-help = Uso: fullstatereset
cmd-full-state-reset-desc = Descarta qualquer informação de estado da entidade e solicita um estado completo do servidor.

View File

@@ -1,161 +0,0 @@
### Localization for engine console commands
## generic
cmd-invalid-arg-number-error = Número inválido de argumentos.
cmd-parse-failure-integer = {$arg} não é um inteiro válido.
cmd-parse-failure-float = {$arg} não é um float válido.
cmd-parse-failure-bool = {$arg} não é um booleano válido.
cmd-parse-failure-uid = {$arg} não é um UID de entidade válido.
cmd-parse-failure-entity-exist = UID {$arg} não corresponde a uma entidade existente.
## 'help' command
cmd-help-desc = Exibir ajuda geral ou texto de ajuda para um comando específico
cmd-help-help = Uso: help [command name]
Quando nenhum nome de comando é fornecido, exibe o texto de ajuda geral. Se um nome de comando for fornecido, exibe o texto de ajuda para esse comando.
cmd-help-no-args = Para exibir a ajuda de um comando específico, escreva 'help <command>'. Para listar todos os comandos disponíveis, escreva 'list'. Para procurar comandos, use 'list <filter>'.
cmd-help-unknown = Comando desconhecido: { $command }
cmd-help-top = { $command } - { $description }
cmd-help-invalid-args = Quantidade de argumentos inválida.
cmd-help-arg-cmdname = [command name]
## 'cvar' command
cmd-cvar-desc = Obtém ou define um CVar.
cmd-cvar-help = Uso: cvar <name | ?> [value]
Se um valor for passado, o valor será analisado e armazenado como o novo valor do CVar.
Caso contrário, o valor atual do CVar é exibido.
Use 'cvar ?' para obter uma lista de todos os CVars registrados.
cmd-cvar-invalid-args = Deve fornecer exatamente um ou dois argumentos.
cmd-cvar-not-registered = CVar '{ $cvar }' não está registrado. Use 'cvar ?' para obter uma lista de todos os CVars registrados.
cmd-cvar-parse-error = O valor de entrada está no formato incorreto para o tipo { $type }
cmd-cvar-compl-list = Listar CVars disponíveis
cmd-cvar-arg-name = <name | ?>
cmd-cvar-value-hidden = <value hidden>
## 'list' command
cmd-list-desc = Lista os comandos disponíveis, com filtro de pesquisa opcional
cmd-list-help = Uso: list [filter]
Lista todos os comandos disponíveis. Se um argumento for fornecido, ele será usado para filtrar comandos por nome.
cmd-list-heading = NOME DESC{"\u000A"}-------------------------{"\u000A"}
cmd-list-arg-filter = [filter]
## '>' command, aka remote exec
cmd-remoteexec-desc = Executa comandos do lado do servidor
cmd-remoteexec-help = Uso: > <command> [arg] [arg] [arg...]
Executa um comando no servidor. Isso é necessário se um comando com o mesmo nome existir no cliente, pois a simples execução do comando executaria o comando do cliente primeiro.
## 'gc' command
cmd-gc-desc = Execute o GC (coletor de lixo)
cmd-gc-help = Uso: gc [generation]
Usa GC.Collect() para executar o Garbage Collector.
Se um argumento for fornecido, ele será analisado como um número de geração do GC e GC.Collect(int) será usado.
Use o comando 'gfc' para fazer um GC completo compactando LOH.
cmd-gc-failed-parse = Falha ao analisar o argumento.
cmd-gc-arg-generation = [generation]
## 'gcf' command
cmd-gcf-desc = Execute o GC, totalmente, compactando LOH e tudo.
cmd-gcf-help = Uso: gcf
Faz um GC.Collect(2, GCCollectionMode.Forced, true, true) completo enquanto também compacta LOH.
Isso provavelmente será bloqueado por centenas de milissegundos, esteja avisado.
## 'gc_mode' command
cmd-gc_mode-desc = Alterar/ler o modo de latência do GC
cmd-gc_mode-help = Uso: gc_mode [type]
Se nenhum argumento for fornecido, retornará o modo de latência do GC atual.
Se um argumento for passado, ele será analisado como GCLatencyMode e definido como o modo de latência do GC.
cmd-gc_mode-current = modo de latência atual do gc: { $prevMode }
cmd-gc_mode-possible = modos possíveis:
cmd-gc_mode-option = - { $mode }
cmd-gc_mode-unknown = modo de latência gc desconhecido: { $arg }
cmd-gc_mode-attempt = tentando alterar o modo de latência do gc: { $prevMode } -> { $mode }
cmd-gc_mode-result = modo de latência gc resultante: { $mode }
cmd-gc_mode-arg-type = [type]
## 'mem' command
cmd-mem-desc = Imprime informações de memória gerenciada
cmd-mem-help = Uso: mem
cmd-mem-report = Tamanho da pilha: { TOSTRING($heapSize, "N0") }
Total alocado: { TOSTRING($totalAllocated, "N0") }
## 'physics' command
cmd-physics-overlay = {$overlay} não é uma sobreposição reconhecida
## 'lsasm' command
cmd-lsasm-desc = Lista assemblies carregados por contexto de carregamento
cmd-lsasm-help = Uso: lsasm
## 'exec' command
cmd-exec-desc = Executa um arquivo de script dos dados de usuário graváveis do jogo
cmd-exec-help = Uso: exec <fileName>
Cada linha no arquivo é executada como um único comando, a menos que comece com um #
cmd-exec-arg-filename = <fileName>
## 'dump_net_comps' command
cmd-dump_net_comps-desc = Imprime a tabela de componentes em rede.
cmd-dump_net_comps-help = Uso: dump_net-comps
cmd-dump_net_comps-error-writeable = Registro ainda gravável, IDs de rede não foram gerados.
cmd-dump_net_comps-header = Registros de componentes em rede:
## 'dump_event_tables' command
cmd-dump_event_tables-desc = Imprime tabelas de eventos direcionados para uma entidade.
cmd-dump_event_tables-help = Uso: dump_event_tables <entityUid>
cmd-dump_event_tables-missing-arg-entity = Argumento de entidade ausente
cmd-dump_event_tables-error-entity = Entidade inválida
cmd-dump_event_tables-arg-entity = <entityUid>
## 'monitor' command
cmd-monitor-desc = Alterna um monitor de depuração no menu F3.
cmd-monitor-help = Uso: monitor <name>
Os monitores possíveis são: { $monitors }
Você também pode usar os valores especiais "-all" e "+all" para ocultar ou mostrar todos os monitores, respectivamente.
cmd-monitor-arg-monitor = <monitor>
cmd-monitor-invalid-name = Nome do monitor inválido
cmd-monitor-arg-count = Argumento do monitor ausente
cmd-monitor-minus-all-hint = Esconde todos os monitores
cmd-monitor-plus-all-hint = Mostra todos os monitores
## Mapping commands
cmd-savemap-desc = Serializa um mapa para o disco. Não salvará um mapa pós-inicialização a menos que seja forçado.
cmd-savemap-help = savemap <MapID> <Path> [force]
cmd-savemap-not-exist = O mapa de destino não existe.
cmd-savemap-init-warning = Tentativa de salvar um mapa pós-inicialização sem forçar o salvamento.
cmd-savemap-attempt = Tentando salvar o mapa {$mapId} em {$path}.
cmd-savemap-success = Mapa salvo com sucesso.
cmd-hint-savemap-id = <MapID>
cmd-hint-savemap-path = <Path>
cmd-hint-savemap-force = [bool]
cmd-loadmap-desc = Carrega um mapa do disco para o jogo.
cmd-loadmap-help = loadmap <MapID> <Path> [x] [y] [rotation] [consistentUids]
cmd-loadmap-nullspace = Você não pode carregar no mapa 0.
cmd-loadmap-exists = Mapa {$mapId} já existe.
cmd-loadmap-success = Mapa {$mapId} foi carregado em {$path}.
cmd-loadmap-error = Ocorreu um erro ao carregar o mapa de {$path}.
cmd-hint-loadmap-x-position = [x-position]
cmd-hint-loadmap-y-position = [y-position]
cmd-hint-loadmap-rotation = [rotation]
cmd-hint-loadmap-uids = [float]
cmd-hint-savebp-id = <Grid EntityID>
## 'flushcookies' command
# Note: the flushcookies command is from Robust.Client.WebView, it's not in the main engine code.
cmd-flushcookies-desc = Liberar o armazenamento de cookies CEF para o disco
cmd-flushcookies-help = Isso garante que os cookies sejam salvos corretamente no disco no caso de desligamentos impróprios.
Observe que a operação real é assíncrona.

View File

@@ -1,10 +0,0 @@
color-selector-sliders-red = R
color-selector-sliders-green = G
color-selector-sliders-blue = B
color-selector-sliders-hue = H
color-selector-sliders-saturation = S
color-selector-sliders-value = V
color-selector-sliders-alpha = A
color-selector-sliders-rgb = RGB
color-selector-sliders-hsv = HSV

View File

@@ -1,11 +0,0 @@
## EntitySpawnWindow
entity-spawn-window-title = Painel de Criação de Entidade
entity-spawn-window-search-bar-placeholder = pesquisar
entity-spawn-window-clear-button = Limpar
entity-spawn-window-erase-button-text = Modo Apagar
entity-spawn-window-override-menu-tooltip = Substituir posicionamento
## Console
console-line-edit-placeholder = Comando aqui

View File

@@ -1 +0,0 @@
defaultwindow-placeholder-title = Exemplo de título de janela aqui

View File

@@ -1,54 +0,0 @@
input-key-Escape = Escape
input-key-Control = Control
input-key-Shift = Shift
input-key-Alt = Alt
input-key-Menu = Menu
input-key-F1 = F1
input-key-F2 = F2
input-key-F3 = F3
input-key-F4 = F4
input-key-F5 = F5
input-key-F6 = F6
input-key-F7 = F7
input-key-F8 = F8
input-key-F9 = F9
input-key-F10 = F10
input-key-F11 = F11
input-key-F12 = F12
input-key-F13 = F13
input-key-F14 = F14
input-key-F15 = F15
input-key-Pause = Pause
input-key-Left = Left
input-key-Up = Up
input-key-Down = Down
input-key-Right = Right
input-key-Space = Space
input-key-Return = Return
input-key-NumpadEnter = Num Enter
input-key-BackSpace = Backspace
input-key-Tab = Tab
input-key-PageUp = Page Up
input-key-PageDown = Page Down
input-key-End = End
input-key-Home = Home
input-key-Insert = Insert
input-key-Delete = Delete
input-key-MouseLeft = Mouse Left
input-key-MouseRight = Mouse Right
input-key-MouseMiddle = Mouse Middle
input-key-MouseButton4 = Mouse 4
input-key-MouseButton5 = Mouse 5
input-key-MouseButton6 = Mouse 6
input-key-MouseButton7 = Mouse 7
input-key-MouseButton8 = Mouse 8
input-key-MouseButton9 = Mouse 9
input-key-LSystem-win = Left Win
input-key-RSystem-win = Right Win
input-key-LSystem-mac = Left Cmd
input-key-RSystem-mac = Right Cmd
input-key-LSystem-linux = Left Meta
input-key-RSystem-linux = Right Meta
input-key-unknown = <unknown key>

View File

@@ -1 +0,0 @@
cmd-midipanic-desc = Desliga cada nota para cada renderizador MIDI ativo.

View File

@@ -1 +0,0 @@
tab-container-not-tab-title-provided = Sem título

View File

@@ -1,11 +0,0 @@
## ViewVariablesInstanceEntity
view-variable-instance-entity-server-components-add-component-button-placeholder = Adicionar Componente
view-variable-instance-entity-client-variables-tab-title = Variávies do Cliente
view-variable-instance-entity-client-components-tab-title = Componentes do Cliente
view-variable-instance-entity-server-variables-tab-title = Variávies do Servidor
view-variable-instance-entity-server-components-tab-title = Componentes do Servidor
view-variable-instance-entity-client-components-search-bar-placeholder = Pesquisar
view-variable-instance-entity-server-components-search-bar-placeholder = Pesquisar
view-variable-instance-entity-add-window-server-components = Adicionar Componente [S]
view-variable-instance-entity-add-window-client-components = Adicionar Componente [C]

View File

@@ -5,7 +5,6 @@ preset raw;
#include "/Shaders/Internal/fov_shared.swsl"
const highp float g_MinVariance = 0.0;
uniform highp vec4 occludeColor;
void fragment()
{
@@ -20,5 +19,5 @@ void fragment()
discard;
}
COLOR = vec4(occludeColor.rgb, 1.0 - occlusion);
COLOR = vec4(0.0, 0.0, 0.0, 1.0 - occlusion);
}

View File

@@ -5,7 +5,6 @@ preset raw;
#include "/Shaders/Internal/fov_shared.swsl"
const highp float g_MinVariance = 0.0;
uniform highp vec4 occludeColor;
void fragment()
{
@@ -19,5 +18,5 @@ void fragment()
discard;
}
COLOR = vec4(occludeColor.rgb, 1.0);
COLOR = vec4(0.0, 0.0, 0.0, 1.0);
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 184 B

View File

Before

Width:  |  Height:  |  Size: 637 B

After

Width:  |  Height:  |  Size: 637 B

View File

@@ -1,7 +1,6 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Operations;
@@ -13,7 +12,6 @@ namespace Robust.Analyzers
public class AccessAnalyzer : DiagnosticAnalyzer
{
private const string AccessAttributeType = "Robust.Shared.Analyzers.AccessAttribute";
private const string RobustAutoGeneratedAttributeType = "Robust.Shared.Analyzers.RobustAutoGeneratedAttribute";
private const string PureAttributeType = "System.Diagnostics.Contracts.PureAttribute";
[SuppressMessage("ReSharper", "RS2008")]
@@ -75,20 +73,11 @@ namespace Robust.Analyzers
// Get the attributes
var friendAttribute = context.Compilation.GetTypeByMetadataName(AccessAttributeType);
var autoGenAttribute = context.Compilation.GetTypeByMetadataName(RobustAutoGeneratedAttributeType);
// Get the type that is containing this expression, or, the type where this is happening.
if (context.ContainingSymbol?.ContainingType is not {} accessingType)
return;
// Should we ignore the access attempt due to the accessing type being auto-generated?
if (accessingType.GetAttributes().FirstOrDefault(a =>
a.AttributeClass != null &&
a.AttributeClass.Equals(autoGenAttribute, SymbolEqualityComparer.Default)) is { } attr)
{
return;
}
// Determine which type of access is happening here... Read, write or execute?
var accessAttempt = DetermineAccess(context, targetAccess, operation);

View File

@@ -1,206 +0,0 @@
#nullable enable
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Operations;
using static Microsoft.CodeAnalysis.SymbolEqualityComparer;
namespace Robust.Analyzers;
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public sealed class ByRefEventAnalyzer : DiagnosticAnalyzer
{
private const string ByRefAttribute = "Robust.Shared.GameObjects.ByRefEventAttribute";
private static readonly DiagnosticDescriptor ByRefEventSubscribedByValueRule = new(
Diagnostics.IdByRefEventSubscribedByValue,
"By-ref event subscribed to by value",
"Tried to subscribe to a by-ref event '{0}' by value.",
"Usage",
DiagnosticSeverity.Error,
true,
"Make sure that methods subscribing to a ref event have the ref keyword for the event argument."
);
private static readonly DiagnosticDescriptor ByValueEventSubscribedByRefRule = new(
Diagnostics.IdValueEventRaisedByRef,
"Value event subscribed to by-ref",
"Tried to subscribe to a value event '{0}' by-ref.",
"Usage",
DiagnosticSeverity.Error,
true,
"Make sure that methods subscribing to value events do not have the ref keyword for the event argument."
);
private static readonly DiagnosticDescriptor ByRefEventRaisedByValueRule = new(
Diagnostics.IdByRefEventRaisedByValue,
"By-ref event raised by value",
"Tried to raise a by-ref event '{0}' by value.",
"Usage",
DiagnosticSeverity.Error,
true,
"Make sure to use the ref keyword when raising ref events."
);
private static readonly DiagnosticDescriptor ByValueEventRaisedByRefRule = new(
Diagnostics.IdValueEventRaisedByRef,
"Value event raised by-ref",
"Tried to raise a value event '{0}' by-ref.",
"Usage",
DiagnosticSeverity.Error,
true,
"Make sure to not use the ref keyword when raising value events."
);
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(
ByRefEventSubscribedByValueRule,
ByValueEventSubscribedByRefRule,
ByRefEventRaisedByValueRule,
ByValueEventRaisedByRefRule
);
public override void Initialize(AnalysisContext context)
{
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics);
context.EnableConcurrentExecution();
context.RegisterOperationAction(CheckEventSubscription, OperationKind.Invocation);
context.RegisterOperationAction(CheckEventRaise, OperationKind.Invocation);
}
private void CheckEventSubscription(OperationAnalysisContext context)
{
if (context.Operation is not IInvocationOperation operation)
return;
var subscribeMethods = context.Compilation
.GetTypeByMetadataName("Robust.Shared.GameObjects.EntitySystem")?
.GetMembers()
.Where(m => m.Name.Contains("SubscribeLocalEvent"))
.Cast<IMethodSymbol>();
if (subscribeMethods == null)
return;
if (!subscribeMethods.Any(m => m.Equals(operation.TargetMethod.OriginalDefinition, Default)))
return;
var typeArguments = operation.TargetMethod.TypeArguments;
if (typeArguments.Length < 1 || typeArguments.Length > 2)
return;
if (operation.Arguments.First().Value is not IDelegateCreationOperation delegateCreation)
return;
if (delegateCreation.Target is not IMethodReferenceOperation methodReference)
return;
var eventParameter = methodReference.Method.Parameters.LastOrDefault();
if (eventParameter == null)
return;
ITypeSymbol eventArgument;
switch (typeArguments.Length)
{
case 1:
eventArgument = typeArguments[0];
break;
case 2:
eventArgument = typeArguments[1];
break;
default:
return;
}
var byRefAttribute = context.Compilation.GetTypeByMetadataName(ByRefAttribute);
if (byRefAttribute == null)
return;
var isByRefEventType = eventArgument
.GetAttributes()
.Any(attribute => attribute.AttributeClass?.Equals(byRefAttribute, Default) ?? false);
var parameterIsRef = eventParameter.RefKind == RefKind.Ref;
if (isByRefEventType != parameterIsRef)
{
var descriptor = isByRefEventType ? ByRefEventSubscribedByValueRule : ByValueEventSubscribedByRefRule;
var diagnostic = Diagnostic.Create(descriptor, operation.Syntax.GetLocation(), eventArgument);
context.ReportDiagnostic(diagnostic);
}
}
private void CheckEventRaise(OperationAnalysisContext context)
{
if (context.Operation is not IInvocationOperation operation)
return;
var raiseMethods = context.Compilation
.GetTypeByMetadataName("Robust.Shared.GameObjects.EntitySystem")?
.GetMembers()
.Where(m => m.Name.Contains("RaiseLocalEvent") && m.Kind == SymbolKind.Method)
.Cast<IMethodSymbol>();
var busRaiseMethods = context.Compilation
.GetTypeByMetadataName("Robust.Shared.GameObjects.EntityEventBus")?
.GetMembers()
.Where(m => m.Name.Contains("RaiseLocalEvent") && m.Kind == SymbolKind.Method)
.Cast<IMethodSymbol>();
if (raiseMethods == null)
return;
if (busRaiseMethods != null)
raiseMethods = raiseMethods.Concat(busRaiseMethods);
if (!raiseMethods.Any(m => m.Equals(operation.TargetMethod.OriginalDefinition, Default)))
{
// If you try to do this normally by concatenating like busRaiseMethods above
// the analyzer does not run without any errors
// I don't know man
const string directedBusMethod = "Robust.Shared.GameObjects.IDirectedEventBus.RaiseLocalEvent";
if (!operation.TargetMethod.ToString().StartsWith(directedBusMethod))
return;
}
var arguments = operation.Arguments;
IArgumentOperation eventArgument;
switch (arguments.Length)
{
case 1:
eventArgument = arguments[0];
break;
case 2:
case 3:
eventArgument = arguments[1];
break;
default:
return;
}
var eventParameter = eventArgument.Parameter;
// TODO have a way to check generic type parameters
if (eventParameter == null ||
eventParameter.Type.SpecialType == SpecialType.System_Object ||
eventParameter.Type.TypeKind == TypeKind.TypeParameter)
{
return;
}
var byRefAttribute = context.Compilation.GetTypeByMetadataName(ByRefAttribute);
if (byRefAttribute == null)
return;
var isByRefEventType = eventParameter.Type
.GetAttributes()
.Any(attribute => attribute.AttributeClass?.Equals(byRefAttribute, Default) ?? false);
var parameterIsRef = eventParameter.RefKind == RefKind.Ref;
if (isByRefEventType != parameterIsRef)
{
var descriptor = isByRefEventType ? ByRefEventRaisedByValueRule : ByValueEventRaisedByRefRule;
var diagnostic = Diagnostic.Create(descriptor, eventArgument.Syntax.GetLocation(), eventParameter.Type);
context.ReportDiagnostic(diagnostic);
}
}
}

View File

@@ -1,293 +0,0 @@
#nullable enable
using System.Collections.Generic;
using System.Collections.Immutable;
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 DataDefinitionAnalyzer : DiagnosticAnalyzer
{
private const string DataDefinitionNamespace = "Robust.Shared.Serialization.Manager.Attributes.DataDefinitionAttribute";
private const string ImplicitDataDefinitionNamespace = "Robust.Shared.Serialization.Manager.Attributes.ImplicitDataDefinitionForInheritorsAttribute";
private const string DataFieldBaseNamespace = "Robust.Shared.Serialization.Manager.Attributes.DataFieldBaseAttribute";
private static readonly DiagnosticDescriptor DataDefinitionPartialRule = new(
Diagnostics.IdDataDefinitionPartial,
"Type must be partial",
"Type {0} is a DataDefinition but is not partial.",
"Usage",
DiagnosticSeverity.Error,
true,
"Make sure to mark any type that is a data definition as partial."
);
private static readonly DiagnosticDescriptor NestedDataDefinitionPartialRule = new(
Diagnostics.IdNestedDataDefinitionPartial,
"Type must be partial",
"Type {0} contains nested data definition {1} but is not partial.",
"Usage",
DiagnosticSeverity.Error,
true,
"Make sure to mark any type containing a nested data definition as partial."
);
private static readonly DiagnosticDescriptor DataFieldWritableRule = new(
Diagnostics.IdDataFieldWritable,
"Data field must not be readonly",
"Data field {0} in data definition {1} is readonly.",
"Usage",
DiagnosticSeverity.Error,
true,
"Make sure to remove the readonly modifier."
);
private static readonly DiagnosticDescriptor DataFieldPropertyWritableRule = new(
Diagnostics.IdDataFieldPropertyWritable,
"Data field property must have a setter",
"Data field property {0} in data definition {1} does not have a setter.",
"Usage",
DiagnosticSeverity.Error,
true,
"Make sure to add a setter."
);
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(
DataDefinitionPartialRule, NestedDataDefinitionPartialRule, DataFieldWritableRule, DataFieldPropertyWritableRule
);
public override void Initialize(AnalysisContext context)
{
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.None);
context.EnableConcurrentExecution();
context.RegisterSyntaxNodeAction(AnalyzeDataDefinition, SyntaxKind.ClassDeclaration);
context.RegisterSyntaxNodeAction(AnalyzeDataDefinition, SyntaxKind.StructDeclaration);
context.RegisterSyntaxNodeAction(AnalyzeDataDefinition, SyntaxKind.RecordDeclaration);
context.RegisterSyntaxNodeAction(AnalyzeDataDefinition, SyntaxKind.RecordStructDeclaration);
context.RegisterSyntaxNodeAction(AnalyzeDataDefinition, SyntaxKind.InterfaceDeclaration);
context.RegisterSyntaxNodeAction(AnalyzeDataField, SyntaxKind.FieldDeclaration);
context.RegisterSyntaxNodeAction(AnalyzeDataFieldProperty, SyntaxKind.PropertyDeclaration);
}
private void AnalyzeDataDefinition(SyntaxNodeAnalysisContext context)
{
if (context.Node is not TypeDeclarationSyntax declaration)
return;
var type = context.SemanticModel.GetDeclaredSymbol(declaration)!;
if (!IsDataDefinition(type))
return;
if (!IsPartial(declaration))
{
context.ReportDiagnostic(Diagnostic.Create(DataDefinitionPartialRule, declaration.Keyword.GetLocation(), type.Name));
}
var containingType = type.ContainingType;
while (containingType != null)
{
var containingTypeDeclaration = (TypeDeclarationSyntax) containingType.DeclaringSyntaxReferences[0].GetSyntax();
if (!IsPartial(containingTypeDeclaration))
{
context.ReportDiagnostic(Diagnostic.Create(NestedDataDefinitionPartialRule, containingTypeDeclaration.Keyword.GetLocation(), containingType.Name, type.Name));
}
containingType = containingType.ContainingType;
}
}
private void AnalyzeDataField(SyntaxNodeAnalysisContext context)
{
if (context.Node is not FieldDeclarationSyntax field)
return;
var typeDeclaration = field.FirstAncestorOrSelf<TypeDeclarationSyntax>();
if (typeDeclaration == null)
return;
var type = context.SemanticModel.GetDeclaredSymbol(typeDeclaration)!;
if (!IsDataDefinition(type))
return;
foreach (var variable in field.Declaration.Variables)
{
var fieldSymbol = context.SemanticModel.GetDeclaredSymbol(variable);
if (fieldSymbol == null)
continue;
if (IsReadOnlyDataField(type, fieldSymbol))
{
context.ReportDiagnostic(Diagnostic.Create(DataFieldWritableRule, context.Node.GetLocation(), fieldSymbol.Name, type.Name));
}
}
}
private void AnalyzeDataFieldProperty(SyntaxNodeAnalysisContext context)
{
if (context.Node is not PropertyDeclarationSyntax property)
return;
var typeDeclaration = property.FirstAncestorOrSelf<TypeDeclarationSyntax>();
if (typeDeclaration == null)
return;
var type = context.SemanticModel.GetDeclaredSymbol(typeDeclaration)!;
if (!IsDataDefinition(type) || type.IsRecord || type.IsValueType)
return;
var propertySymbol = context.SemanticModel.GetDeclaredSymbol(property);
if (propertySymbol == null)
return;
if (IsReadOnlyDataField(type, propertySymbol))
{
context.ReportDiagnostic(Diagnostic.Create(DataFieldPropertyWritableRule, context.Node.GetLocation(), propertySymbol.Name, type.Name));
}
}
private static bool IsReadOnlyDataField(ITypeSymbol type, ISymbol field)
{
if (!IsDataField(field, out _, out _))
return false;
return IsReadOnlyMember(type, field);
}
private static bool IsPartial(TypeDeclarationSyntax type)
{
return type.Modifiers.IndexOf(SyntaxKind.PartialKeyword) != -1;
}
private static bool IsDataDefinition(ITypeSymbol? type)
{
if (type == null)
return false;
return HasAttribute(type, DataDefinitionNamespace) ||
IsImplicitDataDefinition(type);
}
private static bool IsDataField(ISymbol member, out ITypeSymbol type, out AttributeData attribute)
{
// TODO data records and other attributes
if (member is IFieldSymbol field)
{
foreach (var attr in field.GetAttributes())
{
if (attr.AttributeClass != null && Inherits(attr.AttributeClass, DataFieldBaseNamespace))
{
type = field.Type;
attribute = attr;
return true;
}
}
}
else if (member is IPropertySymbol property)
{
foreach (var attr in property.GetAttributes())
{
if (attr.AttributeClass != null && Inherits(attr.AttributeClass, DataFieldBaseNamespace))
{
type = property.Type;
attribute = attr;
return true;
}
}
}
type = null!;
attribute = null!;
return false;
}
private static bool Inherits(ITypeSymbol type, string parent)
{
foreach (var baseType in GetBaseTypes(type))
{
if (baseType.ToDisplayString() == parent)
return true;
}
return false;
}
private static bool IsReadOnlyMember(ITypeSymbol type, ISymbol member)
{
if (member is IFieldSymbol field)
{
return field.IsReadOnly;
}
else if (member is IPropertySymbol property)
{
if (property.SetMethod == null)
return true;
if (property.SetMethod.IsInitOnly)
return type.IsReferenceType;
return false;
}
return false;
}
private static bool HasAttribute(ITypeSymbol type, string attributeName)
{
foreach (var attribute in type.GetAttributes())
{
if (attribute.AttributeClass?.ToDisplayString() == attributeName)
return true;
}
return false;
}
private static bool IsImplicitDataDefinition(ITypeSymbol type)
{
if (HasAttribute(type, ImplicitDataDefinitionNamespace))
return true;
foreach (var baseType in GetBaseTypes(type))
{
if (HasAttribute(baseType, ImplicitDataDefinitionNamespace))
return true;
}
foreach (var @interface in type.AllInterfaces)
{
if (IsImplicitDataDefinitionInterface(@interface))
return true;
}
return false;
}
private static bool IsImplicitDataDefinitionInterface(ITypeSymbol @interface)
{
if (HasAttribute(@interface, ImplicitDataDefinitionNamespace))
return true;
foreach (var subInterface in @interface.AllInterfaces)
{
if (HasAttribute(subInterface, ImplicitDataDefinitionNamespace))
return true;
}
return false;
}
private static IEnumerable<ITypeSymbol> GetBaseTypes(ITypeSymbol type)
{
var baseType = type.BaseType;
while (baseType != null)
{
yield return baseType;
baseType = baseType.BaseType;
}
}
}

View File

@@ -1,168 +0,0 @@
#nullable enable
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using static Microsoft.CodeAnalysis.CSharp.SyntaxKind;
using static Robust.Analyzers.Diagnostics;
namespace Robust.Analyzers;
[ExportCodeFixProvider(LanguageNames.CSharp)]
public sealed class DefinitionFixer : CodeFixProvider
{
public override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(
IdDataDefinitionPartial, IdNestedDataDefinitionPartial, IdDataFieldWritable, IdDataFieldPropertyWritable
);
public override Task RegisterCodeFixesAsync(CodeFixContext context)
{
foreach (var diagnostic in context.Diagnostics)
{
switch (diagnostic.Id)
{
case IdDataDefinitionPartial:
return RegisterPartialTypeFix(context, diagnostic);
case IdNestedDataDefinitionPartial:
return RegisterPartialTypeFix(context, diagnostic);
case IdDataFieldWritable:
return RegisterDataFieldFix(context, diagnostic);
case IdDataFieldPropertyWritable:
return RegisterDataFieldPropertyFix(context, diagnostic);
}
}
return Task.CompletedTask;
}
public override FixAllProvider GetFixAllProvider()
{
return WellKnownFixAllProviders.BatchFixer;
}
private static async Task RegisterPartialTypeFix(CodeFixContext context, Diagnostic diagnostic)
{
var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken);
var span = diagnostic.Location.SourceSpan;
var token = root?.FindToken(span.Start).Parent?.AncestorsAndSelf().OfType<TypeDeclarationSyntax>().First();
if (token == null)
return;
context.RegisterCodeFix(CodeAction.Create(
"Make type partial",
c => MakeDataDefinitionPartial(context.Document, token, c),
"Make type partial"
), diagnostic);
}
private static async Task<Document> MakeDataDefinitionPartial(Document document, TypeDeclarationSyntax declaration, CancellationToken cancellation)
{
var root = (CompilationUnitSyntax?) await document.GetSyntaxRootAsync(cancellation);
var token = SyntaxFactory.Token(PartialKeyword);
var newDeclaration = declaration.AddModifiers(token);
root = root!.ReplaceNode(declaration, newDeclaration);
return document.WithSyntaxRoot(root);
}
private static async Task RegisterDataFieldFix(CodeFixContext context, Diagnostic diagnostic)
{
var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken);
var span = diagnostic.Location.SourceSpan;
var field = root?.FindToken(span.Start).Parent?.AncestorsAndSelf().OfType<FieldDeclarationSyntax>().FirstOrDefault();
if (field == null)
return;
context.RegisterCodeFix(CodeAction.Create(
"Make data field writable",
c => MakeFieldWritable(context.Document, field, c),
"Make data field writable"
), diagnostic);
}
private static async Task RegisterDataFieldPropertyFix(CodeFixContext context, Diagnostic diagnostic)
{
var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken);
var span = diagnostic.Location.SourceSpan;
var property = root?.FindToken(span.Start).Parent?.AncestorsAndSelf().OfType<PropertyDeclarationSyntax>().FirstOrDefault();
if (property == null)
return;
context.RegisterCodeFix(CodeAction.Create(
"Make data field writable",
c => MakePropertyWritable(context.Document, property, c),
"Make data field writable"
), diagnostic);
}
private static async Task<Document> MakeFieldWritable(Document document, FieldDeclarationSyntax declaration, CancellationToken cancellation)
{
var root = (CompilationUnitSyntax?) await document.GetSyntaxRootAsync(cancellation);
var token = declaration.Modifiers.First(t => t.IsKind(ReadOnlyKeyword));
var newDeclaration = declaration.WithModifiers(declaration.Modifiers.Remove(token));
root = root!.ReplaceNode(declaration, newDeclaration);
return document.WithSyntaxRoot(root);
}
private static async Task<Document> MakePropertyWritable(Document document, PropertyDeclarationSyntax declaration, CancellationToken cancellation)
{
var root = (CompilationUnitSyntax?) await document.GetSyntaxRootAsync(cancellation);
var newDeclaration = declaration;
var privateSet = newDeclaration
.AccessorList?
.Accessors
.FirstOrDefault(s => s.IsKind(SetAccessorDeclaration) || s.IsKind(InitAccessorDeclaration));
if (newDeclaration.AccessorList != null && privateSet != null)
{
newDeclaration = newDeclaration.WithAccessorList(
newDeclaration.AccessorList.WithAccessors(
newDeclaration.AccessorList.Accessors.Remove(privateSet)
)
);
}
AccessorDeclarationSyntax setter;
if (declaration.Modifiers.Any(m => m.IsKind(PrivateKeyword)))
{
setter = SyntaxFactory.AccessorDeclaration(
SetAccessorDeclaration,
default,
default,
SyntaxFactory.Token(SetKeyword),
default,
default,
SyntaxFactory.Token(SemicolonToken)
);
}
else
{
setter = SyntaxFactory.AccessorDeclaration(
SetAccessorDeclaration,
default,
SyntaxFactory.TokenList(SyntaxFactory.Token(PrivateKeyword)),
SyntaxFactory.Token(SetKeyword),
default,
default,
SyntaxFactory.Token(SemicolonToken)
);
}
newDeclaration = newDeclaration.AddAccessorListAccessors(setter);
root = root!.ReplaceNode(declaration, newDeclaration);
return document.WithSyntaxRoot(root);
}
}

View File

@@ -9,22 +9,6 @@ public static class Diagnostics
public const string IdAccess = "RA0002";
public const string IdExplicitVirtual = "RA0003";
public const string IdTaskResult = "RA0004";
public const string IdUseGenericVariant = "RA0005";
public const string IdUseGenericVariantInvalidUsage = "RA0006";
public const string IdUseGenericVariantAttributeValueError = "RA0007";
public const string IdNotNullableFlagNotSet = "RA0008";
public const string IdInvalidNotNullableFlagValue = "RA0009";
public const string IdInvalidNotNullableFlagImplementation = "RA0010";
public const string IdInvalidNotNullableFlagType = "RA0011";
public const string IdNotNullableFlagValueType = "RA0012";
public const string IdByRefEventSubscribedByValue = "RA0013";
public const string IdValueEventSubscribedByRef = "RA0014";
public const string IdByRefEventRaisedByValue = "RA0015";
public const string IdValueEventRaisedByRef = "RA0016";
public const string IdDataDefinitionPartial = "RA0017";
public const string IdNestedDataDefinitionPartial = "RA0018";
public const string IdDataFieldWritable = "RA0019";
public const string IdDataFieldPropertyWritable = "RA0020";
public static SuppressionDescriptor MeansImplicitAssignment =>
new SuppressionDescriptor("RADC1000", "CS0649", "Marked as implicitly assigned.");

View File

@@ -1,171 +0,0 @@
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Operations;
namespace Robust.Analyzers;
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public sealed class NotNullableFlagAnalyzer : DiagnosticAnalyzer
{
private const string Attribute = "Robust.Shared.Analyzers.NotNullableFlagAttribute";
private static readonly DiagnosticDescriptor NotNullableNotSetRule = new (
Diagnostics.IdNotNullableFlagNotSet,
"Not Nullable Flag not set",
"Class type parameter {0} is not annotated as nullable and notNullableOverride is not set to true",
"Usage",
DiagnosticSeverity.Error,
true,
"Assign true to notNullableOverride or specify the type parameter as nullable.");
private static readonly DiagnosticDescriptor InvalidNotNullableValueRule = new (
Diagnostics.IdInvalidNotNullableFlagValue,
"Not Nullable Flag wrongfully set",
"Class type parameter {0} is annotated as nullable but notNullableOverride is set to true",
"Usage",
DiagnosticSeverity.Error,
true,
"Remove the true assignment to notNullableOverride or remove the nullable specifier of the type parameter.");
private static readonly DiagnosticDescriptor InvalidNotNullableImplementationRule = new (
Diagnostics.IdInvalidNotNullableFlagImplementation,
"Invalid NotNullable flag implementation.",
"NotNullable flag is either not typed as bool, or does not have a default value equaling false",
"Usage",
DiagnosticSeverity.Error,
true,
"Ensure that the notNullable flag is typed bool and has false set as a default value.");
private static readonly DiagnosticDescriptor InvalidNotNullableTypeRule = new (
Diagnostics.IdInvalidNotNullableFlagType,
"Failed to resolve type parameter",
"Failed to resolve type parameter \"{0}\".",
"Usage",
DiagnosticSeverity.Error,
true,
"Use nameof to avoid typos.");
private static readonly DiagnosticDescriptor NotNullableFlagValueTypeRule = new (
Diagnostics.IdNotNullableFlagValueType,
"NotNullable flag not supported for value types.",
"Value types as generic arguments are not supported for NotNullable flags",
"Usage",
DiagnosticSeverity.Error,
true,
"Nullable value types are distinct at runtime when inspected with reflection. Therefore they are not supported for NotNullable flags.");
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics =>
ImmutableArray.Create(
NotNullableNotSetRule,
InvalidNotNullableValueRule,
InvalidNotNullableImplementationRule,
InvalidNotNullableTypeRule,
NotNullableFlagValueTypeRule);
public override void Initialize(AnalysisContext context)
{
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics);
context.EnableConcurrentExecution();
context.RegisterOperationAction(CheckNotNullableFlag, OperationKind.Invocation);
}
private bool TryGetTypeArgument(IMethodSymbol methodSymbol, string typeParamName, out ITypeSymbol typeArgument)
{
for (var index = 0; index < methodSymbol.TypeParameters.Length; index++)
{
if (methodSymbol.TypeParameters[index].Name != typeParamName)
continue;
typeArgument = methodSymbol.TypeArguments[index];
return true;
}
typeArgument = null;
return false;
}
private void CheckNotNullableFlag(OperationAnalysisContext context)
{
if (context.Operation is not IInvocationOperation invocationOperation || !invocationOperation.TargetMethod.IsGenericMethod)
return;
var attribute = context.Compilation.GetTypeByMetadataName(Attribute);
var @bool = context.Compilation.GetSpecialType(SpecialType.System_Boolean);
foreach (var argument in invocationOperation.Arguments)
{
if(argument.Parameter == null) continue;
foreach (var attributeData in argument.Parameter.GetAttributes())
{
if (!SymbolEqualityComparer.Default.Equals(attributeData.AttributeClass, attribute))
continue;
if (!SymbolEqualityComparer.Default.Equals(argument.Parameter.Type, @bool) ||
!argument.Parameter.HasExplicitDefaultValue ||
argument.Parameter.ExplicitDefaultValue as bool? != false)
{
context.ReportDiagnostic(Diagnostic.Create(
InvalidNotNullableImplementationRule,
argument.Parameter.Locations[0]));
break;
}
if (!TryGetTypeArgument(invocationOperation.TargetMethod,
attributeData.ConstructorArguments[0].Value as string, out var typeArgument))
{
context.ReportDiagnostic(Diagnostic.Create(
InvalidNotNullableTypeRule,
argument.Parameter.Locations[0],
attributeData.ConstructorArguments[0].Value as string));
break;
}
//until i find a way to implement it sanely, generic calls are exempt from this attribute
if(typeArgument is ITypeParameterSymbol) break;
//dont ask me why, argument.ConstantValue just straight up doesnt work.
//i still kept it in here as a fallback, incase it ever starts working again lol -<paul
var constantValue = (argument.Value as ILiteralOperation)?.ConstantValue ?? argument.ConstantValue;
if (typeArgument.IsValueType)
{
if (argument.ArgumentKind != ArgumentKind.DefaultValue)
{
//todo diagnostic only use for struct types
context.ReportDiagnostic(Diagnostic.Create(
NotNullableFlagValueTypeRule,
argument.Syntax.GetLocation()));
}
break;
}
if (typeArgument.NullableAnnotation == NullableAnnotation.None ||
(argument.ArgumentKind != ArgumentKind.DefaultValue && !constantValue.HasValue))
break;
var flagValue = argument.ArgumentKind != ArgumentKind.DefaultValue ||
constantValue.Value as bool? == true;
var nullable = typeArgument.NullableAnnotation == NullableAnnotation.Annotated;
if (nullable && flagValue)
{
context.ReportDiagnostic(Diagnostic.Create(InvalidNotNullableValueRule,
argument.Syntax.GetLocation(),
typeArgument));
}
else if (!nullable && !flagValue)
{
context.ReportDiagnostic(Diagnostic.Create(NotNullableNotSetRule,
argument.Syntax.GetLocation(),
typeArgument));
}
break;
}
}
}
}

View File

@@ -1,238 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Operations;
namespace Robust.Analyzers;
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public sealed class PreferGenericVariantAnalyzer : DiagnosticAnalyzer
{
private const string AttributeType = "Robust.Shared.Analyzers.PreferGenericVariantAttribute";
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(
UseGenericVariantDescriptor, UseGenericVariantInvalidUsageDescriptor,
UseGenericVariantAttributeValueErrorDescriptor);
private static readonly DiagnosticDescriptor UseGenericVariantDescriptor = new(
Diagnostics.IdUseGenericVariant,
"Consider using the generic variant of this method",
"Consider using the generic variant of this method to avoid potential allocations",
"Usage",
DiagnosticSeverity.Warning,
true,
"Consider using the generic variant of this method to avoid potential allocations.");
private static readonly DiagnosticDescriptor UseGenericVariantInvalidUsageDescriptor = new(
Diagnostics.IdUseGenericVariantInvalidUsage,
"Invalid generic variant provided",
"Generic variant provided mismatches the amount of type parameters of non-generic variant",
"Usage",
DiagnosticSeverity.Error,
true,
"The non-generic variant should have at least as many type parameter at the beginning of the method as there are generic type parameters on the generic variant.");
private static readonly DiagnosticDescriptor UseGenericVariantAttributeValueErrorDescriptor = new(
Diagnostics.IdUseGenericVariantAttributeValueError,
"Failed resolving generic variant value",
"Failed resolving generic variant value: {0}",
"Usage",
DiagnosticSeverity.Error,
true,
"Consider using nameof to avoid any typos.");
public override void Initialize(AnalysisContext context)
{
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.ReportDiagnostics | GeneratedCodeAnalysisFlags.Analyze);
context.EnableConcurrentExecution();
context.RegisterOperationAction(CheckForGenericVariant, OperationKind.Invocation);
}
private void CheckForGenericVariant(OperationAnalysisContext obj)
{
if(obj.Operation is not IInvocationOperation invocationOperation) return;
var preferGenericAttribute = obj.Compilation.GetTypeByMetadataName(AttributeType);
string genericVariant = null;
AttributeData foundAttribute = null;
foreach (var attribute in invocationOperation.TargetMethod.GetAttributes())
{
if (!SymbolEqualityComparer.Default.Equals(attribute.AttributeClass, preferGenericAttribute))
continue;
genericVariant = attribute.ConstructorArguments[0].Value as string ?? invocationOperation.TargetMethod.Name;
foundAttribute = attribute;
break;
}
if(genericVariant == null) return;
var maxTypeParams = 0;
var typeTypeSymbol = obj.Compilation.GetTypeByMetadataName("System.Type");
foreach (var parameter in invocationOperation.TargetMethod.Parameters)
{
if(!SymbolEqualityComparer.Default.Equals(parameter.Type, typeTypeSymbol)) break;
maxTypeParams++;
}
if (maxTypeParams == 0)
{
obj.ReportDiagnostic(
Diagnostic.Create(UseGenericVariantInvalidUsageDescriptor,
foundAttribute.ApplicationSyntaxReference?.GetSyntax().GetLocation()));
return;
}
IMethodSymbol genericVariantMethod = null;
foreach (var member in invocationOperation.TargetMethod.ContainingType.GetMembers())
{
if (member is not IMethodSymbol methodSymbol
|| methodSymbol.Name != genericVariant
|| !methodSymbol.IsGenericMethod
|| methodSymbol.TypeParameters.Length > maxTypeParams
|| methodSymbol.Parameters.Length > invocationOperation.TargetMethod.Parameters.Length - methodSymbol.TypeParameters.Length
) continue;
var typeParamCount = methodSymbol.TypeParameters.Length;
var failedParamComparison = false;
var objType = obj.Compilation.GetSpecialType(SpecialType.System_Object);
for (int i = 0; i < methodSymbol.Parameters.Length; i++)
{
if (methodSymbol.Parameters[i].Type is ITypeParameterSymbol && SymbolEqualityComparer.Default.Equals(invocationOperation.TargetMethod.Parameters[i + typeParamCount].Type, objType))
continue;
if (!SymbolEqualityComparer.Default.Equals(methodSymbol.Parameters[i].Type,
invocationOperation.TargetMethod.Parameters[i + typeParamCount].Type))
{
failedParamComparison = true;
break;
}
}
if(failedParamComparison) continue;
genericVariantMethod = methodSymbol;
}
if (genericVariantMethod == null)
{
obj.ReportDiagnostic(Diagnostic.Create(
UseGenericVariantAttributeValueErrorDescriptor,
foundAttribute.ApplicationSyntaxReference?.GetSyntax().GetLocation(),
genericVariant));
return;
}
var typeOperands = new string[genericVariantMethod.TypeParameters.Length];
for (var i = 0; i < genericVariantMethod.TypeParameters.Length; i++)
{
switch (invocationOperation.Arguments[i].Value)
{
//todo figure out if ILocalReferenceOperation, IPropertyReferenceOperation or IFieldReferenceOperation is referencing static typeof assignments
case ITypeOfOperation typeOfOperation:
typeOperands[i] = typeOfOperation.TypeOperand.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
continue;
default:
return;
}
}
obj.ReportDiagnostic(Diagnostic.Create(
UseGenericVariantDescriptor,
invocationOperation.Syntax.GetLocation(),
ImmutableDictionary.CreateRange(new Dictionary<string, string>()
{
{"typeOperands", string.Join(",", typeOperands)}
})));
}
}
[ExportCodeFixProvider(LanguageNames.CSharp)]
public class PreferGenericVariantCodeFixProvider : CodeFixProvider
{
private static string Title(string method, string[] types) => $"Use {method}<{string.Join(",", types)}>.";
public override FixAllProvider GetFixAllProvider()
{
return WellKnownFixAllProviders.BatchFixer;
}
public override async Task RegisterCodeFixesAsync(CodeFixContext context)
{
var root = await context.Document.GetSyntaxRootAsync();
if(root == null) return;
foreach (var diagnostic in context.Diagnostics)
{
if (!diagnostic.Properties.TryGetValue("typeOperands", out var typeOperandsRaw)
|| typeOperandsRaw == null) continue;
var node = root.FindNode(diagnostic.Location.SourceSpan);
if (node is ArgumentSyntax argumentSyntax)
node = argumentSyntax.Expression;
if(node is not InvocationExpressionSyntax invocationExpression)
continue;
var typeOperands = typeOperandsRaw.Split(',');
context.RegisterCodeFix(
CodeAction.Create(
Title(invocationExpression.Expression.ToString(), typeOperands),
c => FixAsync(context.Document, invocationExpression, typeOperands, c),
Title(invocationExpression.Expression.ToString(), typeOperands)),
diagnostic);
}
}
private async Task<Document> FixAsync(
Document contextDocument,
InvocationExpressionSyntax invocationExpression,
string[] typeOperands,
CancellationToken cancellationToken)
{
var memberAccess = (MemberAccessExpressionSyntax)invocationExpression.Expression;
var root = (CompilationUnitSyntax) await contextDocument.GetSyntaxRootAsync(cancellationToken);
var arguments = new ArgumentSyntax[invocationExpression.ArgumentList.Arguments.Count - typeOperands.Length];
var types = new TypeSyntax[typeOperands.Length];
for (int i = 0; i < typeOperands.Length; i++)
{
types[i] = ((TypeOfExpressionSyntax)invocationExpression.ArgumentList.Arguments[i].Expression).Type;
}
Array.Copy(
invocationExpression.ArgumentList.Arguments.ToArray(),
typeOperands.Length,
arguments,
0,
arguments.Length);
memberAccess = memberAccess.WithName(SyntaxFactory.GenericName(memberAccess.Name.Identifier,
SyntaxFactory.TypeArgumentList(SyntaxFactory.SeparatedList(types))));
root = root!.ReplaceNode(invocationExpression,
invocationExpression.WithArgumentList(invocationExpression.ArgumentList.WithArguments(SyntaxFactory.SeparatedList(arguments)))
.WithExpression(memberAccess));
return contextDocument.WithSyntaxRoot(root);
}
public override ImmutableArray<string> FixableDiagnosticIds =>
ImmutableArray.Create(Diagnostics.IdUseGenericVariant);
}

View File

@@ -11,20 +11,10 @@
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.Common" Version="4.0.1" />
</ItemGroup>
<ItemGroup>
<!-- Needed for NotNullableFlagAnalyzer. -->
<Compile Include="..\Robust.Shared\Analyzers\NotNullableFlagAttribute.cs" />
</ItemGroup>
<ItemGroup>
<!-- Needed for FriendAnalyzer. -->
<Compile Include="..\Robust.Shared\Analyzers\AccessAttribute.cs" />
<Compile Include="..\Robust.Shared\Analyzers\AccessPermissions.cs" />
</ItemGroup>
<ItemGroup>
<!-- Needed for PreferGenericVariantAnalyzer. -->
<Compile Include="..\Robust.Shared\Analyzers\PreferGenericVariantAttribute.cs" />
</ItemGroup>
</Project>

View File

@@ -8,7 +8,7 @@ using Robust.UnitTesting.Server;
namespace Robust.Benchmarks.EntityManager;
[Virtual]
public partial class AddRemoveComponentBenchmark
public class AddRemoveComponentBenchmark
{
private ISimulation _simulation = default!;
private IEntityManager _entityManager = default!;
@@ -48,7 +48,7 @@ public partial class AddRemoveComponentBenchmark
}
[ComponentProtoName("A")]
public sealed partial class A : Component
public sealed class A : Component
{
}
}

View File

@@ -1,75 +0,0 @@
using BenchmarkDotNet.Attributes;
using JetBrains.Annotations;
using Robust.Shared.GameObjects;
using Robust.Shared.Map;
using Robust.UnitTesting.Server;
namespace Robust.Benchmarks.EntityManager;
public partial class ComponentIteratorBenchmark
{
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[] ComponentStructEnumerator()
{
var query = _entityManager.EntityQueryEnumerator<A>();
var i = 0;
while (query.MoveNext(out var comp))
{
Comps[i] = comp;
i++;
}
return Comps;
}
[Benchmark]
public A[] ComponentIEnumerable()
{
var i = 0;
foreach (var comp in _entityManager.EntityQuery<A>())
{
Comps[i] = comp;
i++;
}
return Comps;
}
[ComponentProtoName("A")]
public sealed partial class A : Component
{
}
}

View File

@@ -1,53 +0,0 @@
using BenchmarkDotNet.Attributes;
using Robust.Shared.Analyzers;
using static Robust.Benchmarks.EntityManager.ArchetypeComponentAccessBenchmark;
namespace Robust.Benchmarks.EntityManager;
[MemoryDiagnoser]
[Virtual]
public class ArrayAccessBenchmark
{
[Params(new[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9})]
public int[] Array = default!;
[Params(5)]
public int Element;
[Params(500)]
public int Handle;
public Archetype<int, int, int, int, int, int, int, int, int, int> Archetype = default!;
[GlobalSetup]
public void GlobalSetup()
{
Archetype = new Archetype<int, int, int, int, int, int, int, int, int, int>(1000);
}
[Benchmark]
public int? GetArrayElement()
{
return Consume();
}
[Benchmark]
public int? GetExisting()
{
return Consume(Element);
}
[Benchmark]
public int? GetArchetype()
{
return Consume(Archetype.GetComponentUnsafeHandle<int>(Handle));
}
private int? Consume(int? value = null)
{
if (value == null)
value = Array[5];
return value;
}
}

View File

@@ -1,3 +1,4 @@
using System;
using BenchmarkDotNet.Attributes;
using JetBrains.Annotations;
using Robust.Shared.Analyzers;
@@ -8,7 +9,7 @@ using Robust.UnitTesting.Server;
namespace Robust.Benchmarks.EntityManager;
[Virtual]
public partial class GetComponentBenchmark
public class GetComponentBenchmark
{
private ISimulation _simulation = default!;
private IEntityManager _entityManager = default!;
@@ -54,7 +55,7 @@ public partial class GetComponentBenchmark
}
[ComponentProtoName("A")]
public sealed partial class A : Component
public sealed class A : Component
{
}
}

View File

@@ -8,7 +8,7 @@ using Robust.UnitTesting.Server;
namespace Robust.Benchmarks.EntityManager;
[Virtual]
public partial class SpawnDeleteEntityBenchmark
public class SpawnDeleteEntityBenchmark
{
private ISimulation _simulation = default!;
private IEntityManager _entityManager = default!;
@@ -56,7 +56,7 @@ public partial class SpawnDeleteEntityBenchmark
}
[ComponentProtoName("A")]
public sealed partial class A : Component
public sealed class A : Component
{
}
}

View File

@@ -3,13 +3,11 @@ using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using BenchmarkDotNet.Exporters;
using BenchmarkDotNet.Loggers;
using BenchmarkDotNet.Mathematics;
using BenchmarkDotNet.Parameters;
using BenchmarkDotNet.Reports;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
@@ -22,11 +20,6 @@ namespace Robust.Benchmarks.Exporters;
public sealed class SQLExporter : IExporter
{
private static readonly JsonSerializerOptions JsonSerializerOptions = new JsonSerializerOptions
{
NumberHandling = JsonNumberHandling.AllowNamedFloatingPointLiterals
};
public static readonly IExporter Default = new SQLExporter();
private SQLExporter(){}
@@ -81,13 +74,13 @@ public sealed class SQLExporter : IExporter
{
ctx.Database.OpenConnection();
var con = (NpgsqlConnection) ctx.Database.GetDbConnection();
con.TypeMapper.AddTypeResolverFactory(new JsonOverrideTypeHandlerResolverFactory(JsonSerializerOptions));
con.TypeMapper.AddTypeResolverFactory(new JsonOverrideTypeHandlerResolverFactory(new JsonSerializerOptions
{
NumberHandling = JsonNumberHandling.AllowNamedFloatingPointLiterals
}));
ctx.Database.Migrate();
foreach (var run in BenchmarkRun.FromSummary(summary, gitHash))
{
ctx.BenchmarkRuns.Add(run);
}
ctx.BenchmarkRuns.Add(BenchmarkRun.FromSummary(summary, gitHash));
ctx.SaveChanges();
}
finally
@@ -138,7 +131,6 @@ class JsonOverrideTypeHandlerResolverFactory : TypeHandlerResolverFactory
=> null; // Let the built-in resolver do this
}
}
public sealed class DesignTimeContextFactoryPostgres : IDesignTimeDbContextFactory<BenchmarkContext>
{
public BenchmarkContext CreateDbContext(string[] args)
@@ -162,66 +154,42 @@ public class BenchmarkRun
public int Id { get; set; }
public string GitHash { get; set; } = string.Empty;
[Column(TypeName = "timestamptz")] public DateTime RunDate { get; set; }
[Column(TypeName = "timestamptz")]
public DateTime RunDate { get; set; }
public string Name { get; set; } = string.Empty;
public string? ParameterMapping { get; set; }
[Column(TypeName = "jsonb")]
public BenchmarkRunParameter[]? ParameterMappingJson { get; set; }
public BenchmarkRunReport[] Reports { get; set; } = Array.Empty<BenchmarkRunReport>();
[Column(TypeName = "jsonb")]
public Statistics Statistics { get; set; } = default!;
public static IEnumerable<BenchmarkRun> FromSummary(Summary summary, string gitHash)
public static BenchmarkRun FromSummary(Summary summary, string gitHash)
{
var runDate = DateTime.UtcNow;
foreach (var benchmarkReport in summary.Reports)
return new BenchmarkRun
{
var paramString = new StringBuilder();
var parametersItems = benchmarkReport.BenchmarkCase.Parameters.Items;
var runParameters = new BenchmarkRunParameter[parametersItems.Count];
for (var i = 0; i < parametersItems.Count; i++)
Reports = summary.Reports.Select(r => new BenchmarkRunReport
{
runParameters[i] = new BenchmarkRunParameter(parametersItems[i]);
paramString.Append(runParameters[i].ToString());
if (i < parametersItems.Count - 1) paramString.Append(',');
}
if (benchmarkReport.ResultStatistics == null)
{
Console.WriteLine($"err: No statistics available for {benchmarkReport.BenchmarkCase.Descriptor.DisplayInfo}!");
continue;
}
yield return new BenchmarkRun
{
Name = benchmarkReport.BenchmarkCase.Descriptor.DisplayInfo,
RunDate = runDate,
GitHash = gitHash,
ParameterMapping = runParameters.Length > 0 ? paramString.ToString() : null,
ParameterMappingJson = runParameters.Length > 0 ? runParameters : null,
Statistics = benchmarkReport.ResultStatistics
};
}
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 struct BenchmarkRunParameter
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!;
public BenchmarkRunParameter(ParameterInstance instance)
{
Name = instance.Name;
Value = instance.Value;
}
public override string ToString()
{
return $"{Name}={Value}";
}
}

View File

@@ -13,7 +13,7 @@ namespace Robust.Benchmarks.Migrations
{
[DbContext(typeof(BenchmarkContext))]
[Migration("20220510131430_fix-pk")]
partial class FixPK
partial class fixpk
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{

View File

@@ -6,7 +6,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
namespace Robust.Benchmarks.Migrations
{
public partial class FixPK : Migration
public partial class fixpk : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{

View File

@@ -1,62 +0,0 @@
// <auto-generated />
using System;
using BenchmarkDotNet.Mathematics;
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("20221009235705_db")]
partial class DB
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "6.0.4")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("Robust.Benchmarks.Exporters.BenchmarkRun", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("GitHash")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<string>("ParameterMapping")
.IsRequired()
.HasColumnType("text");
b.Property<DateTime>("RunDate")
.HasColumnType("timestamptz");
b.Property<Statistics>("Statistics")
.IsRequired()
.HasColumnType("jsonb");
b.HasKey("Id");
b.ToTable("BenchmarkRuns");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -1,36 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Robust.Benchmarks.Migrations
{
public partial class DB : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.RenameColumn(
name: "Reports",
table: "BenchmarkRuns",
newName: "Statistics");
migrationBuilder.AddColumn<string>(
name: "ParameterMapping",
table: "BenchmarkRuns",
type: "text",
nullable: false,
defaultValue: "");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "ParameterMapping",
table: "BenchmarkRuns");
migrationBuilder.RenameColumn(
name: "Statistics",
table: "BenchmarkRuns",
newName: "Reports");
}
}
}

View File

@@ -1,64 +0,0 @@
// <auto-generated />
using System;
using BenchmarkDotNet.Mathematics;
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("20221010144620_param_work")]
partial class ParamWork
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "6.0.4")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("Robust.Benchmarks.Exporters.BenchmarkRun", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("GitHash")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<string>("ParameterMapping")
.HasColumnType("text");
b.Property<BenchmarkRunParameter[]>("ParameterMappingJson")
.HasColumnType("jsonb");
b.Property<DateTime>("RunDate")
.HasColumnType("timestamptz");
b.Property<Statistics>("Statistics")
.IsRequired()
.HasColumnType("jsonb");
b.HasKey("Id");
b.ToTable("BenchmarkRuns");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -1,44 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
using Robust.Benchmarks.Exporters;
#nullable disable
namespace Robust.Benchmarks.Migrations
{
public partial class ParamWork : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "ParameterMapping",
table: "BenchmarkRuns",
type: "text",
nullable: true,
oldClrType: typeof(string),
oldType: "text");
migrationBuilder.AddColumn<BenchmarkRunParameter[]>(
name: "ParameterMappingJson",
table: "BenchmarkRuns",
type: "jsonb",
nullable: true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "ParameterMappingJson",
table: "BenchmarkRuns");
migrationBuilder.AlterColumn<string>(
name: "ParameterMapping",
table: "BenchmarkRuns",
type: "text",
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "text",
oldNullable: true);
}
}
}

View File

@@ -1,6 +1,5 @@
// <auto-generated />
using System;
using BenchmarkDotNet.Mathematics;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
@@ -18,7 +17,7 @@ namespace Robust.Benchmarks.Migrations
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "6.0.4")
.HasAnnotation("ProductVersion", "6.0.0")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
@@ -39,19 +38,13 @@ namespace Robust.Benchmarks.Migrations
.IsRequired()
.HasColumnType("text");
b.Property<string>("ParameterMapping")
.HasColumnType("text");
b.Property<BenchmarkRunParameter[]>("ParameterMappingJson")
b.Property<BenchmarkRunReport[]>("Reports")
.IsRequired()
.HasColumnType("jsonb");
b.Property<DateTime>("RunDate")
.HasColumnType("timestamptz");
b.Property<Statistics>("Statistics")
.IsRequired()
.HasColumnType("jsonb");
b.HasKey("Id");
b.ToTable("BenchmarkRuns");

View File

@@ -1,11 +0,0 @@
using System;
using BenchmarkDotNet.Mathematics;
using Robust.Benchmarks.Exporters;
namespace Robust.Benchmarks.Migrations;
public class BenchmarkRunReport
{
public BenchmarkRunParameter[] Parameters { get; set; } = Array.Empty<BenchmarkRunParameter>();
public Statistics Statistics { get; set; } = default!;
}

View File

@@ -1,32 +1,33 @@
using BenchmarkDotNet.Attributes;
using Robust.Shared.Analyzers;
namespace Robust.Benchmarks.NumericsHelpers;
[Virtual]
public class AddBenchmark
namespace Robust.Benchmarks.NumericsHelpers
{
[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!;
[GlobalSetup]
public void Setup()
[Virtual]
public class AddBenchmark
{
_inputA = new float[N];
_inputB = new float[N];
_output = new float[N];
}
[Params(32, 128)]
public int N { get; set; }
[Benchmark]
public void Bench()
{
Shared.Maths.NumericsHelpers.Add(_inputA, _inputB, _output);
[Params(1,2)]
public int T { get; set; }
private float[] _inputA = default!;
private float[] _inputB = default!;
private float[] _output = default!;
[GlobalSetup]
public void Setup()
{
_inputA = new float[N];
_inputB = new float[N];
_output = new float[N];
}
[Benchmark]
public void Bench()
{
Shared.Maths.NumericsHelpers.Add(_inputA, _inputB, _output);
}
}
}

View File

@@ -1,26 +0,0 @@
using BenchmarkDotNet.Attributes;
using Robust.Shared.Analyzers;
namespace Robust.Benchmarks.NumericsHelpers;
[Virtual]
[DisassemblyDiagnoser()]
public class HorizontalAddBenchmark
{
[Params(8, 32, 128)]
public int N { get; set; }
private float[] _inputA = default!;
[GlobalSetup]
public void Setup()
{
_inputA = new float[N];
}
[Benchmark]
public float Bench()
{
return Shared.Maths.NumericsHelpers.HorizontalAdd(_inputA);
}
}

View File

@@ -1,9 +1,8 @@
#if DEBUG
using BenchmarkDotNet.Configs;
#endif
using System;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Running;
using System;
using Robust.Benchmarks.Configs;
using Robust.Benchmarks.Exporters;
namespace Robust.Benchmarks
{

View File

@@ -1,25 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\MSBuild\Robust.Engine.props" />
<PropertyGroup>
<IsPackable>false</IsPackable>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<OutputPath>../bin/Benchmarks</OutputPath>
<OutputType>Exe</OutputType>
<NoWarn>RA0003</NoWarn>
</PropertyGroup>
<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.4" />
</ItemGroup>
<Import Project="..\MSBuild\Robust.Properties.targets" />
<Import Project="..\MSBuild\Robust.Properties.targets" />
<Import Project="..\MSBuild\Robust.Engine.props" />
<PropertyGroup>
<IsPackable>false</IsPackable>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<OutputPath>../bin/Benchmarks</OutputPath>
<OutputType>Exe</OutputType>
<NoWarn>RA0003</NoWarn>
</PropertyGroup>
<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.4" />
</ItemGroup>
<Import Project="..\MSBuild\Robust.Engine.targets" />
</Project>

View File

@@ -1,6 +1,5 @@
using System.Globalization;
using Robust.Shared.IoC;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager;
using Robust.Shared.Serialization.Markdown;
using Robust.Shared.Serialization.Markdown.Validation;
@@ -9,7 +8,7 @@ using Robust.Shared.Serialization.TypeSerializers.Interfaces;
namespace Robust.Benchmarks.Serialization
{
public sealed class BenchmarkIntSerializer : ITypeSerializer<int, ValueDataNode>, ITypeCopyCreator<int>
public sealed class BenchmarkIntSerializer : ITypeSerializer<int, ValueDataNode>
{
public ValidationNode Validate(ISerializationManager serializationManager, ValueDataNode node,
IDependencyCollection dependencies, ISerializationContext? context = null)
@@ -20,21 +19,19 @@ namespace Robust.Benchmarks.Serialization
}
public int Read(ISerializationManager serializationManager, ValueDataNode node,
IDependencyCollection dependencies, SerializationHookContext hookCtx, ISerializationContext? context = null,
ISerializationManager.InstantiationDelegate<int>? instanceProvider = null)
IDependencyCollection dependencies, bool skipHook, ISerializationContext? context = null, int _ = default)
{
return int.Parse(node.Value, CultureInfo.InvariantCulture);
}
public DataNode Write(ISerializationManager serializationManager, int value, IDependencyCollection dependencies,
bool alwaysWrite = false,
public DataNode Write(ISerializationManager serializationManager, int value, bool alwaysWrite = false,
ISerializationContext? context = null)
{
return new ValueDataNode(value.ToString(CultureInfo.InvariantCulture));
}
public int CreateCopy(ISerializationManager serializationManager, int source,
IDependencyCollection dependencies, SerializationHookContext hookCtx, ISerializationContext? context = null)
public int Copy(ISerializationManager serializationManager, int source, int target, bool skipHook,
ISerializationContext? context = null)
{
return source;
}

View File

@@ -3,6 +3,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;
using Robust.Shared.Serialization.Markdown.Sequence;
@@ -27,7 +28,7 @@ namespace Robust.Benchmarks.Serialization.Copy
var seedMapping = yamlStream.Documents[0].RootNode.ToDataNodeCast<SequenceDataNode>().Cast<MappingDataNode>(0);
Seed = SerializationManager.Read<SeedDataDefinition>(seedMapping, notNullableOverride: true);
Seed = SerializationManager.Read<SeedDataDefinition>(seedMapping);
}
private const string String = "ABC";
@@ -45,25 +46,25 @@ namespace Robust.Benchmarks.Serialization.Copy
[Benchmark]
public string? CreateCopyString()
{
return SerializationManager.CreateCopy(String, notNullableOverride: true);
return SerializationManager.Copy(String);
}
[Benchmark]
public int? CreateCopyInteger()
{
return SerializationManager.CreateCopy(Integer);
return SerializationManager.Copy(Integer);
}
[Benchmark]
public DataDefinitionWithString? CreateCopyDataDefinitionWithString()
{
return SerializationManager.CreateCopy(DataDefinitionWithString, notNullableOverride: true);
return SerializationManager.Copy(DataDefinitionWithString);
}
[Benchmark]
public SeedDataDefinition? CreateCopySeedDataDefinition()
{
return SerializationManager.CreateCopy(Seed, notNullableOverride: true);
return SerializationManager.Copy(Seed);
}
[Benchmark]
@@ -108,7 +109,9 @@ namespace Robust.Benchmarks.Serialization.Copy
copy.Potency = Seed.Potency;
copy.Ligneous = Seed.Ligneous;
copy.PlantRsi = new ResPath(Seed.PlantRsi.ToString());
copy.PlantRsi = Seed.PlantRsi == null
? null!
: new ResourcePath(Seed.PlantRsi.ToString(), Seed.PlantRsi.Separator);
copy.PlantIconState = Seed.PlantIconState;
copy.Bioluminescent = Seed.Bioluminescent;
copy.BioluminescentColor = Seed.BioluminescentColor;
@@ -121,21 +124,30 @@ namespace Robust.Benchmarks.Serialization.Copy
[BenchmarkCategory("flag")]
public object? CopyFlagZero()
{
return SerializationManager.CreateCopy<int, FlagSerializer<BenchmarkFlags>>((int) FlagZero);
return SerializationManager.CopyWithTypeSerializer(
typeof(FlagSerializer<BenchmarkFlags>),
(int) FlagZero,
(int) FlagZero);
}
[Benchmark]
[BenchmarkCategory("flag")]
public object? CopyFlagThirtyOne()
{
return SerializationManager.CreateCopy<int, FlagSerializer<BenchmarkFlags>>((int) FlagThirtyOne);
return SerializationManager.CopyWithTypeSerializer(
typeof(FlagSerializer<BenchmarkFlags>),
(int) FlagThirtyOne,
(int) FlagThirtyOne);
}
[Benchmark]
[BenchmarkCategory("customTypeSerializer")]
public object? CopyIntegerCustomSerializer()
{
return SerializationManager.CreateCopy<int, BenchmarkIntSerializer>(Integer);
return SerializationManager.CopyWithTypeSerializer(
typeof(BenchmarkIntSerializer),
Integer,
Integer);
}
}
}

View File

@@ -5,9 +5,9 @@ namespace Robust.Benchmarks.Serialization.Definitions
{
[DataDefinition]
[Virtual]
public partial class DataDefinitionWithString
public class DataDefinitionWithString
{
[DataField("string")]
public string StringField { get; set; } = default!;
public string StringField { get; init; } = default!;
}
}

View File

@@ -3,9 +3,9 @@
namespace Robust.Benchmarks.Serialization.Definitions
{
[DataDefinition]
public sealed partial class SealedDataDefinitionWithString
public sealed class SealedDataDefinitionWithString
{
[DataField("string")]
public string StringField { get; private set; } = default!;
public string StringField { get; init; } = default!;
}
}

View File

@@ -1,5 +1,4 @@
using System.Collections.Generic;
using Robust.Shared.GameObjects;
using Robust.Shared.Maths;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.Manager.Attributes;
@@ -11,7 +10,8 @@ namespace Robust.Benchmarks.Serialization.Definitions
/// Arbitrarily large data definition for benchmarks.
/// Taken from content.
/// </summary>
public sealed partial class SeedDataDefinition : Component
[Prototype("seed")]
public sealed class SeedDataDefinition : IPrototype
{
public const string Prototype = @"
- type: seed
@@ -87,7 +87,7 @@ namespace Robust.Benchmarks.Serialization.Definitions
#endregion
#region Cosmetics
[DataField("plantRsi", required: true)] public ResPath PlantRsi { get; set; } = default!;
[DataField("plantRsi", required: true)] public ResourcePath PlantRsi { get; set; } = default!;
[DataField("plantIconState")] public string PlantIconState { get; set; } = "produce";
[DataField("bioluminescent")] public bool Bioluminescent { get; set; }
[DataField("bioluminescentColor")] public Color BioluminescentColor { get; set; } = Color.White;
@@ -106,7 +106,7 @@ namespace Robust.Benchmarks.Serialization.Definitions
}
[DataDefinition]
public partial struct SeedChemQuantity
public struct SeedChemQuantity
{
[DataField("Min")]
public int Min;

View File

@@ -43,7 +43,7 @@ namespace Robust.Benchmarks.Serialization.Read
[Benchmark]
public string ReadString()
{
return SerializationManager.Read<string>(StringNode, notNullableOverride: true);
return SerializationManager.Read<string>(StringNode);
}
[Benchmark]
@@ -55,34 +55,43 @@ namespace Robust.Benchmarks.Serialization.Read
[Benchmark]
public DataDefinitionWithString ReadDataDefinitionWithString()
{
return SerializationManager.Read<DataDefinitionWithString>(StringDataDefNode, notNullableOverride: true);
return SerializationManager.Read<DataDefinitionWithString>(StringDataDefNode);
}
[Benchmark]
public SeedDataDefinition ReadSeedDataDefinition()
{
return SerializationManager.Read<SeedDataDefinition>(SeedNode, notNullableOverride: true);
return SerializationManager.Read<SeedDataDefinition>(SeedNode);
}
[Benchmark]
[BenchmarkCategory("flag")]
public object? ReadFlagZero()
{
return SerializationManager.Read<int, ValueDataNode, FlagSerializer<BenchmarkFlags>>(FlagZero);
return SerializationManager.ReadWithTypeSerializer(
typeof(int),
typeof(FlagSerializer<BenchmarkFlags>),
FlagZero);
}
[Benchmark]
[BenchmarkCategory("flag")]
public object? ReadThirtyOne()
{
return SerializationManager.Read<int, ValueDataNode, FlagSerializer<BenchmarkFlags>>(FlagThirtyOne);
return SerializationManager.ReadWithTypeSerializer(
typeof(int),
typeof(FlagSerializer<BenchmarkFlags>),
FlagThirtyOne);
}
[Benchmark]
[BenchmarkCategory("customTypeSerializer")]
public object? ReadIntegerCustomSerializer()
{
return SerializationManager.Read<int, ValueDataNode, BenchmarkIntSerializer>(IntNode);
return SerializationManager.ReadWithTypeSerializer(
typeof(int),
typeof(BenchmarkIntSerializer),
IntNode);
}
}
}

View File

@@ -46,84 +46,84 @@ namespace Robust.Benchmarks.Serialization
[BenchmarkCategory("read")]
public string[]? ReadEmptyString()
{
return SerializationManager.Read<string[]>(EmptyNode, notNullableOverride: true);
return SerializationManager.Read<string[]>(EmptyNode);
}
[Benchmark]
[BenchmarkCategory("read")]
public string[]? ReadOneString()
{
return SerializationManager.Read<string[]>(OneIntNode, notNullableOverride: true);
return SerializationManager.Read<string[]>(OneIntNode);
}
[Benchmark]
[BenchmarkCategory("read")]
public string[]? ReadTenStrings()
{
return SerializationManager.Read<string[]>(TenIntsNode, notNullableOverride: true);
return SerializationManager.Read<string[]>(TenIntsNode);
}
[Benchmark]
[BenchmarkCategory("read")]
public int[]? ReadEmptyInt()
{
return SerializationManager.Read<int[]>(EmptyNode, notNullableOverride: true);
return SerializationManager.Read<int[]>(EmptyNode);
}
[Benchmark]
[BenchmarkCategory("read")]
public int[]? ReadOneInt()
{
return SerializationManager.Read<int[]>(OneIntNode, notNullableOverride: true);
return SerializationManager.Read<int[]>(OneIntNode);
}
[Benchmark]
[BenchmarkCategory("read")]
public int[]? ReadTenInts()
{
return SerializationManager.Read<int[]>(TenIntsNode, notNullableOverride: true);
return SerializationManager.Read<int[]>(TenIntsNode);
}
[Benchmark]
[BenchmarkCategory("read")]
public DataDefinitionWithString[]? ReadEmptyStringDataDef()
{
return SerializationManager.Read<DataDefinitionWithString[]>(EmptyNode, notNullableOverride: true);
return SerializationManager.Read<DataDefinitionWithString[]>(EmptyNode);
}
[Benchmark]
[BenchmarkCategory("read")]
public DataDefinitionWithString[]? ReadOneStringDataDef()
{
return SerializationManager.Read<DataDefinitionWithString[]>(OneStringDefNode, notNullableOverride: true);
return SerializationManager.Read<DataDefinitionWithString[]>(OneStringDefNode);
}
[Benchmark]
[BenchmarkCategory("read")]
public DataDefinitionWithString[]? ReadTenStringDataDefs()
{
return SerializationManager.Read<DataDefinitionWithString[]>(TenStringDefsNode, notNullableOverride: true);
return SerializationManager.Read<DataDefinitionWithString[]>(TenStringDefsNode);
}
[Benchmark]
[BenchmarkCategory("read")]
public SealedDataDefinitionWithString[]? ReadEmptySealedStringDataDef()
{
return SerializationManager.Read<SealedDataDefinitionWithString[]>(EmptyNode, notNullableOverride: true);
return SerializationManager.Read<SealedDataDefinitionWithString[]>(EmptyNode);
}
[Benchmark]
[BenchmarkCategory("read")]
public SealedDataDefinitionWithString[]? ReadOneSealedStringDataDef()
{
return SerializationManager.Read<SealedDataDefinitionWithString[]>(OneStringDefNode, notNullableOverride: true);
return SerializationManager.Read<SealedDataDefinitionWithString[]>(OneStringDefNode);
}
[Benchmark]
[BenchmarkCategory("read")]
public SealedDataDefinitionWithString[]? ReadTenSealedStringDataDefs()
{
return SerializationManager.Read<SealedDataDefinitionWithString[]>(TenStringDefsNode, notNullableOverride: true);
return SerializationManager.Read<SealedDataDefinitionWithString[]>(TenStringDefsNode);
}
}
}

View File

@@ -12,9 +12,9 @@ namespace Robust.Benchmarks.Serialization
{
public SerializationBenchmark()
{
var deps = IoCManager.InitThread();
ServerIoC.RegisterIoC(deps);
deps.BuildGraph();
IoCManager.InitThread();
ServerIoC.RegisterIoC();
IoCManager.BuildGraph();
var assemblies = new[]
{
@@ -25,12 +25,12 @@ namespace Robust.Benchmarks.Serialization
foreach (var assembly in assemblies)
{
deps.Resolve<IConfigurationManagerInternal>().LoadCVarsFromAssembly(assembly);
IoCManager.Resolve<IConfigurationManagerInternal>().LoadCVarsFromAssembly(assembly);
}
deps.Resolve<IReflectionManager>().LoadAssemblies(assemblies);
IoCManager.Resolve<IReflectionManager>().LoadAssemblies(assemblies);
SerializationManager = deps.Resolve<ISerializationManager>();
SerializationManager = IoCManager.Resolve<ISerializationManager>();
}
protected ISerializationManager SerializationManager { get; }

View File

@@ -3,6 +3,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;
using Robust.Shared.Serialization.Markdown.Sequence;
@@ -27,7 +28,7 @@ namespace Robust.Benchmarks.Serialization.Write
var seedMapping = yamlStream.Documents[0].RootNode.ToDataNodeCast<SequenceDataNode>().Cast<MappingDataNode>(0);
Seed = SerializationManager.Read<SeedDataDefinition>(seedMapping, notNullableOverride: true);
Seed = SerializationManager.Read<SeedDataDefinition>(seedMapping);
}
private const string String = "ABC";
@@ -45,7 +46,7 @@ namespace Robust.Benchmarks.Serialization.Write
[Benchmark]
public DataNode WriteString()
{
return SerializationManager.WriteValue(String, notNullableOverride: true);
return SerializationManager.WriteValue(String);
}
[Benchmark]
@@ -57,13 +58,13 @@ namespace Robust.Benchmarks.Serialization.Write
[Benchmark]
public DataNode WriteDataDefinitionWithString()
{
return SerializationManager.WriteValue(DataDefinitionWithString, notNullableOverride: true);
return SerializationManager.WriteValue(DataDefinitionWithString);
}
[Benchmark]
public DataNode WriteSeedDataDefinition()
{
return SerializationManager.WriteValue(Seed, notNullableOverride: true);
return SerializationManager.WriteValue(Seed);
}
[Benchmark]
@@ -106,21 +107,30 @@ namespace Robust.Benchmarks.Serialization.Write
[BenchmarkCategory("flag")]
public DataNode WriteFlagZero()
{
return SerializationManager.WriteValue<int, FlagSerializer<BenchmarkFlags>>((int)FlagZero);
return SerializationManager.WriteWithTypeSerializer(
typeof(int),
typeof(FlagSerializer<BenchmarkFlags>),
FlagZero);
}
[Benchmark]
[BenchmarkCategory("flag")]
public DataNode WriteThirtyOne()
{
return SerializationManager.WriteValue<int, FlagSerializer<BenchmarkFlags>>((int)FlagThirtyOne);
return SerializationManager.WriteWithTypeSerializer(
typeof(int),
typeof(FlagSerializer<BenchmarkFlags>),
FlagThirtyOne);
}
[Benchmark]
[BenchmarkCategory("customTypeSerializer")]
public DataNode WriteIntegerCustomSerializer()
{
return SerializationManager.WriteValue<int, BenchmarkIntSerializer>(Integer);
return SerializationManager.WriteWithTypeSerializer(
typeof(int),
typeof(BenchmarkIntSerializer),
Integer);
}
}
}

View File

@@ -1,171 +0,0 @@
using System;
using System.Linq;
using System.Numerics;
using BenchmarkDotNet.Attributes;
using Robust.Server.Containers;
using Robust.Server.GameStates;
using Robust.Shared;
using Robust.Shared.Analyzers;
using Robust.Shared.Configuration;
using Robust.Shared.Containers;
using Robust.Shared.GameObjects;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.UnitTesting.Server;
namespace Robust.Benchmarks.Transform;
/// <summary>
/// This benchmark tests various transform/move related functions with an entity that has many children.
/// </summary>
[Virtual, MemoryDiagnoser]
public class RecursiveMoveBenchmark
{
private ISimulation _simulation = default!;
private IEntityManager _entMan = default!;
private SharedTransformSystem _transform = default!;
private ContainerSystem _container = default!;
private PvsSystem _pvs = default!;
private EntityCoordinates _mapCoords;
private EntityCoordinates _gridCoords;
private EntityUid _ent;
private EntityUid _child;
private TransformComponent _childXform = default!;
private EntityQuery<TransformComponent> _query;
[GlobalSetup]
public void GlobalSetup()
{
_simulation = RobustServerSimulation
.NewSimulation()
.InitializeInstance();
if (!_simulation.Resolve<IConfigurationManager>().GetCVar(CVars.NetPVS))
throw new InvalidOperationException("PVS must be enabled");
_entMan = _simulation.Resolve<IEntityManager>();
_transform = _entMan.System<SharedTransformSystem>();
_container = _entMan.System<ContainerSystem>();
_pvs = _entMan.System<PvsSystem>();
_query = _entMan.GetEntityQuery<TransformComponent>();
// Create map & grid
var mapMan = _simulation.Resolve<IMapManager>();
var mapSys = _entMan.System<SharedMapSystem>();
var mapId = mapMan.CreateMap();
var map = mapMan.GetMapEntityId(mapId);
var gridComp = mapMan.CreateGrid(mapId);
var grid = gridComp.Owner;
_gridCoords = new EntityCoordinates(grid, .5f, .5f);
_mapCoords = new EntityCoordinates(map, 100, 100);
mapSys.SetTile(grid, gridComp, Vector2i.Zero, new Tile(1));
// Next, we will spawn our test entity. This entity will have a complex transform/container hierarchy.
// This is intended to be representative of a typical SS14 player entity, with organs. clothing, and a full backpack.
_ent = _entMan.Spawn();
// Quick check that SetCoordinates actually changes the parent as expected
// I.e., ensure that grid-traversal code doesn't just dump the entity on the map.
_transform.SetCoordinates(_ent, _gridCoords);
if (_query.GetComponent(_ent).ParentUid != _gridCoords.EntityId)
throw new Exception("Grid traversal error.");
_transform.SetCoordinates(_ent, _mapCoords);
if (_query.GetComponent(_ent).ParentUid != _mapCoords.EntityId)
throw new Exception("Grid traversal error.");
// Add 5 direct children in slots to represent clothing.
for (var i = 0; i < 5; i++)
{
var id = $"inventory{i}";
_container.EnsureContainer<ContainerSlot>(_ent, id);
if (!_entMan.TrySpawnInContainer(null, _ent, id, out _))
throw new Exception($"Failed to setup entity");
}
// body parts
_container.EnsureContainer<Container>(_ent, "body");
for (var i = 0; i < 5; i++)
{
// Simple organ
if (!_entMan.TrySpawnInContainer(null, _ent, "body", out _))
throw new Exception($"Failed to setup entity");
// body part that has another body part / limb
if (!_entMan.TrySpawnInContainer(null, _ent, "body", out var limb))
throw new Exception($"Failed to setup entity");
_container.EnsureContainer<ContainerSlot>(limb.Value, "limb");
if (!_entMan.TrySpawnInContainer(null, limb.Value, "limb", out _))
throw new Exception($"Failed to setup entity");
}
// Backpack
_container.EnsureContainer<ContainerSlot>(_ent, "inventory-backpack");
if (!_entMan.TrySpawnInContainer(null, _ent, "inventory-backpack", out var backpack))
throw new Exception($"Failed to setup entity");
// Misc backpack contents.
var backpackStorage = _container.EnsureContainer<Container>(backpack.Value, "storage");
for (var i = 0; i < 10; i++)
{
if (!_entMan.TrySpawnInContainer(null, backpack.Value, "storage", out _))
throw new Exception($"Failed to setup entity");
}
// Emergency box inside of the backpack
var box = backpackStorage.ContainedEntities.First();
var boxContainer = _container.EnsureContainer<Container>(box, "storage");
for (var i = 0; i < 10; i++)
{
if (!_entMan.TrySpawnInContainer(null, box, "storage", out _))
throw new Exception($"Failed to setup entity");
}
// Deepest child.
_child = boxContainer.ContainedEntities.First();
_childXform = _query.GetComponent(_child);
_pvs.ProcessCollections();
}
/// <summary>
/// This implicitly measures move events, including PVS and entity lookups. Though given that most of the entities
/// are in containers, this will bias the entity lookup aspect.
/// </summary>
[Benchmark]
public void MoveEntity()
{
_transform.SetCoordinates(_ent, _gridCoords);
_transform.SetCoordinates(_ent, _mapCoords);
}
/// <summary>
/// Like <see cref="MoveEntity"/>, but also processes queued PVS chunk updates.
/// </summary>
[Benchmark]
public void MoveAndUpdateChunks()
{
_transform.SetCoordinates(_ent, _gridCoords);
_pvs.ProcessCollections();
_transform.SetCoordinates(_ent, _mapCoords);
_pvs.ProcessCollections();
}
[Benchmark]
public Vector2 GetWorldPos()
{
return _transform.GetWorldPosition(_childXform);
}
[Benchmark]
public EntityUid GetRootUid()
{
var xform = _childXform;
while (xform.ParentUid.IsValid())
{
xform = _query.GetComponent(xform.ParentUid);
}
return xform.ParentUid;
}
}

View File

@@ -1,71 +0,0 @@
using BenchmarkDotNet.Attributes;
using Robust.Shared.Analyzers;
namespace Robust.Benchmarks.TypeMatching;
[MemoryDiagnoser]
[Virtual]
public class TypeSwitchBenchmark
{
private readonly Matcher<Struct> _matcher = new();
[Benchmark]
public int BenchmarkInt()
{
return _matcher.TypeToInt<int>();
}
[Benchmark]
public int BenchmarkString()
{
return _matcher.TypeToInt<string>();
}
[Benchmark]
public int BenchmarkStruct()
{
return _matcher.TypeToInt<Struct>();
}
[Benchmark]
public int BenchmarkDouble()
{
return _matcher.TypeToInt<double>();
}
[Benchmark]
public int BenchmarkFloat()
{
return _matcher.TypeToInt<float>();
}
[Benchmark]
public int BenchmarkClass()
{
return _matcher.TypeToInt<Class>();
}
private class Matcher<T1>
{
public int TypeToInt<T>(T val = default!)
{
return val switch
{
int => 1,
string => 2,
double => 3,
T1 => 4,
Class => 5,
_ => 6
};
}
}
private struct Struct
{
}
private class Class
{
}
}

View File

@@ -1,36 +0,0 @@
using BenchmarkDotNet.Attributes;
using JetBrains.Annotations;
using Robust.Shared.Analyzers;
using Robust.Shared.Utility;
#pragma warning disable CS0612
namespace Robust.Benchmarks.Utility;
[Virtual]
public class ResourcePathBench
{
private string _path = default!;
[UsedImplicitly]
[Params(10, 100, 1000)]
public int N;
[GlobalSetup]
public void GlobalSetup()
{
_path = "/a/b/c/../test";
}
[Benchmark]
public ResPath CreateWithSeparatorResPath()
{
ResPath res = default;
for (var i = 0; i < N; i++)
{
res = new ResPath(_path);
}
return res;
}
}
#pragma warning restore CS0612

View File

@@ -25,7 +25,7 @@ namespace Robust.Build.Tasks
Single = ts.GetType("System.Single");
Int32 = ts.GetType("System.Int32");
(Vector2, Vector2ConstructorFull) = GetNumericTypeInfo("System.Numerics.Vector2", Single, 2);
(Vector2, Vector2ConstructorFull) = GetNumericTypeInfo("Robust.Shared.Maths.Vector2", Single, 2);
(Vector2i, Vector2iConstructorFull) = GetNumericTypeInfo("Robust.Shared.Maths.Vector2i", Int32, 2);
(Thickness, ThicknessConstructorFull) = GetNumericTypeInfo("Robust.Shared.Maths.Thickness", Single, 4);

View File

@@ -110,6 +110,25 @@ namespace Robust.Build.Tasks
var compiler =
new RobustXamlILCompiler(transformerconfig, emitConfig, true);
var loaderDispatcherDef = new TypeDefinition("CompiledRobustXaml", "!XamlLoader",
TypeAttributes.Class, asm.MainModule.TypeSystem.Object);
var loaderDispatcherMethod = new MethodDefinition("TryLoad",
MethodAttributes.Static | MethodAttributes.Public,
asm.MainModule.TypeSystem.Object)
{
Parameters = {new ParameterDefinition(asm.MainModule.TypeSystem.String)}
};
loaderDispatcherDef.Methods.Add(loaderDispatcherMethod);
asm.MainModule.Types.Add(loaderDispatcherDef);
var stringEquals = asm.MainModule.ImportReference(asm.MainModule.TypeSystem.String.Resolve().Methods.First(
m =>
m.IsStatic && m.Name == "Equals" && m.Parameters.Count == 2 &&
m.ReturnType.FullName == "System.Boolean"
&& m.Parameters[0].ParameterType.FullName == "System.String"
&& m.Parameters[1].ParameterType.FullName == "System.String"));
bool CompileGroup(IResourceGroup group)
{
var typeDef = new TypeDefinition("CompiledRobustXaml", "!" + group.Name, TypeAttributes.Class,
@@ -233,6 +252,31 @@ namespace Robust.Build.Tasks
$"No call to RobustXamlLoader.Load(this) call found anywhere in the type {classType.FullName} and type seems to have custom constructors.");
}
}
//add compiled build method
var compiledBuildMethod = typeSystem.GetTypeReference(builder).Resolve().Methods
.First(m => m.Name == buildName);
var parameterlessCtor = classTypeDefinition.GetConstructors()
.FirstOrDefault(c => c.IsPublic && !c.IsStatic && !c.HasParameters);
if (compiledBuildMethod != null && parameterlessCtor != null)
{
var i = loaderDispatcherMethod.Body.Instructions;
var nop = Instruction.Create(OpCodes.Nop);
i.Add(Instruction.Create(OpCodes.Ldarg_0));
i.Add(Instruction.Create(OpCodes.Ldstr, res.Uri));
i.Add(Instruction.Create(OpCodes.Call, stringEquals));
i.Add(Instruction.Create(OpCodes.Brfalse, nop));
if (parameterlessCtor != null)
i.Add(Instruction.Create(OpCodes.Newobj, parameterlessCtor));
else
{
i.Add(Instruction.Create(OpCodes.Call, compiledBuildMethod));
}
i.Add(Instruction.Create(OpCodes.Ret));
i.Add(nop);
}
}
catch (Exception e)
{
@@ -249,6 +293,8 @@ namespace Robust.Build.Tasks
return false;
}
loaderDispatcherMethod.Body.Instructions.Add(Instruction.Create(OpCodes.Ldnull));
loaderDispatcherMethod.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
return true;
}

View File

@@ -332,7 +332,7 @@ namespace {nameSpace}
"Usage",
DiagnosticSeverity.Error,
true),
candidateClass.GetLocation()));
Location.None));
}
}

View File

@@ -20,7 +20,7 @@ namespace Robust.Client.WebView.Cef
var mainArgs = new CefMainArgs(argv);
// This will block executing until the subprocess is shut down.
var code = CefRuntime.ExecuteProcess(mainArgs, new RobustCefApp(null), IntPtr.Zero);
var code = CefRuntime.ExecuteProcess(mainArgs, new RobustCefApp(), IntPtr.Zero);
if (code != 0)
{

View File

@@ -7,15 +7,9 @@ namespace Robust.Client.WebView.Cef
{
internal sealed class RobustCefApp : CefApp
{
private readonly ISawmill? _sawmill;
private readonly BrowserProcessHandler _browserProcessHandler = new();
private readonly RenderProcessHandler _renderProcessHandler = new();
public RobustCefApp(ISawmill? sawmill)
{
_sawmill = sawmill;
}
protected override CefBrowserProcessHandler GetBrowserProcessHandler()
{
return _browserProcessHandler;
@@ -45,7 +39,8 @@ namespace Robust.Client.WebView.Cef
commandLine.AppendSwitch("disable-threaded-scrolling", "1");
commandLine.AppendSwitch("disable-features", "TouchpadAndWheelScrollLatching,AsyncWheelEvents");
_sawmill?.Debug($"CEF command line: {commandLine}");
if(IoCManager.Instance != null)
Logger.Debug($"{commandLine}");
}
protected override void OnRegisterCustomSchemes(CefSchemeRegistrar registrar)

View File

@@ -27,7 +27,7 @@ namespace Robust.Client.WebView.Cef
var impl = new WebViewWindowImpl(this);
var lifeSpanHandler = new WindowLifeSpanHandler(impl);
var reqHandler = new RobustRequestHandler(_sawmill);
var reqHandler = new RobustRequestHandler(Logger.GetSawmill("root"));
var client = new WindowCefClient(lifeSpanHandler, reqHandler);
var settings = new CefBrowserSettings();

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