mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-15 03:30:53 +01:00
Compare commits
69 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
15eded3da8 | ||
|
|
b4165e8661 | ||
|
|
ad339b5bfd | ||
|
|
e1197af8ce | ||
|
|
102cadf3a6 | ||
|
|
e7723b61bc | ||
|
|
a9d17337a3 | ||
|
|
74622bac83 | ||
|
|
a3047b1687 | ||
|
|
3a55118143 | ||
|
|
3c5fbc648a | ||
|
|
f9c39bce0b | ||
|
|
0e8c803c0f | ||
|
|
6bb7b88c69 | ||
|
|
9e0fc7017c | ||
|
|
76317b7ab3 | ||
|
|
d5f4d4bf2f | ||
|
|
156d1a6b14 | ||
|
|
3fa456fd44 | ||
|
|
bf9bb46154 | ||
|
|
fb3da0b53c | ||
|
|
5c635c09b4 | ||
|
|
fad539212d | ||
|
|
7275302639 | ||
|
|
5057ff97a3 | ||
|
|
754d5a1fbb | ||
|
|
7cee5b67a7 | ||
|
|
21729e7e48 | ||
|
|
394d1e6cc2 | ||
|
|
f73d7f7285 | ||
|
|
e505cfffd8 | ||
|
|
d0fe3591ef | ||
|
|
1868f32457 | ||
|
|
ca82767b07 | ||
|
|
76024330a7 | ||
|
|
21e8107eb1 | ||
|
|
bcaa97a79b | ||
|
|
19727f6a25 | ||
|
|
2102b96323 | ||
|
|
59b3ffda4f | ||
|
|
aae929966c | ||
|
|
0cf842cacc | ||
|
|
96885c5b53 | ||
|
|
d45ce7742e | ||
|
|
50e27fd204 | ||
|
|
af98933173 | ||
|
|
e357dada65 | ||
|
|
19c48862e2 | ||
|
|
448ce94b35 | ||
|
|
3681b7f0d5 | ||
|
|
7b3c883653 | ||
|
|
c81004ddb4 | ||
|
|
f844011348 | ||
|
|
0094040d68 | ||
|
|
dfb5369664 | ||
|
|
2462c906b3 | ||
|
|
8cbc05840f | ||
|
|
510846321d | ||
|
|
ac60567583 | ||
|
|
7592997f4e | ||
|
|
c68b3dccb7 | ||
|
|
da2a2ce4ff | ||
|
|
538418ea93 | ||
|
|
2bf284bce8 | ||
|
|
b51cb06d53 | ||
|
|
bab6c29fbe | ||
|
|
9502c86a65 | ||
|
|
359811f71e | ||
|
|
9de5840017 |
@@ -10,5 +10,8 @@ charset = utf-8
|
||||
[*.{csproj,xml,yml,dll.config,targets,props}]
|
||||
indent_size = 2
|
||||
|
||||
[nuget.config]
|
||||
indent_size = 2
|
||||
|
||||
[*.gdsl]
|
||||
indent_style = tab
|
||||
|
||||
61
Directory.Packages.props
Normal file
61
Directory.Packages.props
Normal file
@@ -0,0 +1,61 @@
|
||||
<Project>
|
||||
<ItemGroup>
|
||||
<PackageVersion Include="BenchmarkDotNet" Version="0.13.12" />
|
||||
<PackageVersion Include="DiscordRichPresence" Version="1.2.1.24" />
|
||||
<PackageVersion Include="ILReader.Core" Version="1.0.0.4" />
|
||||
<PackageVersion Include="JetBrains.Annotations" Version="2023.3.0" />
|
||||
<PackageVersion Include="JetBrains.Profiler.Api" Version="1.4.0" />
|
||||
<PackageVersion Include="Linguini.Bundle" Version="0.1.3" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzer.Testing" Version="1.1.1"/>
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp.Analyzer.Testing.NUnit" Version="1.1.1"/>
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.8.0" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp.Features" Version="4.8.0" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="4.8.0" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.8.0" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.Common" Version="4.8.0" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.Workspaces.Common" Version="4.8.0" />
|
||||
<PackageVersion Include="Microsoft.CodeCoverage" Version="17.8.0" />
|
||||
<PackageVersion Include="Microsoft.Data.Sqlite.Core" Version="8.0.0" />
|
||||
<PackageVersion Include="Microsoft.DotNet.RemoteExecutor" Version="8.0.0-beta.24059.4" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging" Version="8.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.ObjectPool" Version="8.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Primitives" Version="8.0.0" />
|
||||
<PackageVersion Include="Microsoft.ILVerification" Version="8.0.0" />
|
||||
<PackageVersion Include="Microsoft.IO.RecyclableMemoryStream" Version="3.0.0" />
|
||||
<PackageVersion Include="Microsoft.NET.ILLink.Tasks" Version="8.0.0" />
|
||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
|
||||
<PackageVersion Include="Microsoft.Win32.Registry" Version="5.0.0" />
|
||||
<PackageVersion Include="Moq" Version="4.20.70" />
|
||||
<PackageVersion Include="NUnit" Version="4.0.1" />
|
||||
<PackageVersion Include="NUnit.Analyzers" Version="3.10.0" />
|
||||
<PackageVersion Include="NUnit3TestAdapter" Version="4.5.0" />
|
||||
<PackageVersion Include="Nett" Version="0.15.0" />
|
||||
<PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="6.0.4" />
|
||||
<PackageVersion Include="OpenTK.OpenAL" Version="4.7.7" />
|
||||
<PackageVersion Include="OpenToolkit.Graphics" Version="4.0.0-pre9.1" />
|
||||
<PackageVersion Include="Pidgin" Version="3.2.2" />
|
||||
<PackageVersion Include="Robust.Natives" Version="0.1.1" />
|
||||
<PackageVersion Include="Robust.Natives.Cef" Version="120.1.9" />
|
||||
<PackageVersion Include="Robust.Shared.AuthLib" Version="0.1.2" />
|
||||
<PackageVersion Include="SQLitePCLRaw.bundle_e_sqlite3" Version="2.1.7" />
|
||||
<PackageVersion Include="SQLitePCLRaw.provider.sqlite3" Version="2.1.7" />
|
||||
<PackageVersion Include="Serilog" Version="3.1.1" />
|
||||
<PackageVersion Include="Serilog.Sinks.Loki" Version="4.0.0-beta3" />
|
||||
<PackageVersion Include="SharpZstd.Interop" Version="1.5.2-beta2" />
|
||||
<PackageVersion Include="SixLabors.ImageSharp" Version="3.1.2" />
|
||||
<PackageVersion Include="SpaceWizards.HttpListener" Version="0.1.0" />
|
||||
<PackageVersion Include="SpaceWizards.NFluidsynth" Version="0.1.1" />
|
||||
<PackageVersion Include="SpaceWizards.SharpFont" Version="1.0.2" />
|
||||
<PackageVersion Include="SpaceWizards.Sodium" Version="0.2.1" />
|
||||
<PackageVersion Include="System.Numerics.Vectors" Version="4.5.0" />
|
||||
<PackageVersion Include="TerraFX.Interop.Windows" Version="10.0.22621.5" />
|
||||
<PackageVersion Include="TerraFX.Interop.Xlib" Version="6.4.0" />
|
||||
<PackageVersion Include="VorbisPizza" Version="1.3.0" />
|
||||
<PackageVersion Include="YamlDotNet" Version="13.7.1" />
|
||||
<PackageVersion Include="prometheus-net" Version="8.2.1" />
|
||||
<PackageVersion Include="prometheus-net.DotNetRuntime" Version="4.4.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,9 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
// So I wanted to mess with NetIncomingMessage and NetOutgoingMessage from tests.
|
||||
// Now.. the instructors are internal...
|
||||
// Unless...
|
||||
// I mean we have this project here from the weird way we're compiling Lidgren.
|
||||
// I could just put this in here... it wouldn't touch the main Lidgren repo at all...
|
||||
[assembly: InternalsVisibleTo("Robust.UnitTesting")]
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="CursedHorrorsBeyondOurWildestImagination.cs" />
|
||||
|
||||
<Compile Include="Lidgren.Network\Lidgren.Network\**\*.cs">
|
||||
<Link>%(RecursiveDir)%(Filename)%(Extension)</Link>
|
||||
</Compile>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<Project>
|
||||
|
||||
<!-- This file automatically reset by Tools/version.py -->
|
||||
<!-- This file automatically reset by Tools/version.py -->
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="Robust.Custom.targets" Condition="Exists('Robust.Custom.targets')"/>
|
||||
@@ -27,5 +28,5 @@
|
||||
<Import Project="Robust.Analyzers.targets" Condition="'$(SkipRobustAnalyzer)' != 'true'" />
|
||||
|
||||
<!-- serialization generator -->
|
||||
<Import Project="Robust.Serialization.Generator.targets" />
|
||||
<Import Project="Robust.Serialization.Generator.targets" Condition="'$(SkipRobustAnalyzer)' != 'true'" />
|
||||
</Project>
|
||||
|
||||
Submodule NetSerializer updated: 7224829e87...7f51deaeca
197
RELEASE-NOTES.md
197
RELEASE-NOTES.md
@@ -54,6 +54,195 @@ END TEMPLATE-->
|
||||
*None yet*
|
||||
|
||||
|
||||
## 210.0.2
|
||||
|
||||
|
||||
## 210.0.1
|
||||
|
||||
### Bugfixes
|
||||
|
||||
* Revert changes to `TextureButton` that broke style property handling.
|
||||
|
||||
|
||||
## 210.0.0
|
||||
|
||||
### New features
|
||||
|
||||
* Controls can now hook before, after, and during rendering of their children.
|
||||
* IRenderHandle is now a public API, with the caveat that it's properties and methods are unstable.
|
||||
* ButtonGroup now exposes what buttons it contains, alongside which is currently pressed.
|
||||
* OptionButton has additional styleclasses, and has a hook for modifying it's internal buttons.
|
||||
* PanelContainer.GetStyleBox() is now protected rather than private.
|
||||
* TextureButton now uses a TextureRect instead of custom drawing code.
|
||||
* TextureRect has additional style properties exposed.
|
||||
* A new property, TextureSizeTarget, was added, which allows specifying a size in virtual pixels that the control should attempt to draw at.
|
||||
* Stretch mode is now a style property.
|
||||
* Scale is now a style property.
|
||||
* Avalonia.Metadata.XmlnsDefinitionAttribute is now permitted by the sandbox.
|
||||
* Add MaxDimension property to Box2 to return the higher of the Width or Height.
|
||||
* Add GetLocalPosition to convert ScreenCoordinates to coordinates relative to the control. Ignores window.
|
||||
* Add GlobalRect and GlobalPixelRect for controls to get their UIBox2i in screen terms.
|
||||
* Add dotted line drawing to DrawingHandleScreen.
|
||||
* You can use `Subs.CVar()` from an entity systems to subscribe to CVar changes. This is more convenient than `IConfigurationManager.OnValueChanged` as it automatically unsubscribes on system shutdown.
|
||||
* There is now a built-in type serializer for `DateTime`, so you can put `DateTime`s in your data fields.
|
||||
* `System.Text.Unicode.UnicodeRange` and `UnicodeRanges` are now available in the sandbox.
|
||||
|
||||
### Bugfixes
|
||||
|
||||
* UI drawing now properly accounts for a control's draw routine potentially mangling the current matrix.
|
||||
* UI roots now properly update when the global stylesheet is changed. They previously only did so if they had a dedicated stylesheet (which is the one case where they would be unaffected by a global sheet update.
|
||||
|
||||
|
||||
## 209.0.1
|
||||
|
||||
### Bugfixes
|
||||
|
||||
* Fix missed import from 209.0.0.
|
||||
|
||||
|
||||
## 209.0.0
|
||||
|
||||
### Breaking changes
|
||||
|
||||
* `replay.max_compressed_size` and `replay.max_uncompressed_size` CVars are now `long`.
|
||||
* Remove obsolete CoordinatesExtension for ToEntityCoordinates from GridUid / Vector2i.
|
||||
|
||||
### New features
|
||||
|
||||
* Add GetEntitiesOnMap / GetChildEntities to EntityLookupSystem to return components on the specified map and components with the specified parent respectively.
|
||||
* Add MaxDimension property to Box2 to return the higher of the Width or Height.
|
||||
* Add GetLocalPosition to convert ScreenCoordinates to coordinates relative to the control. Ignores window.
|
||||
* Add GlobalRect and GlobalPixelRect for controls to get their UIBox2i in screen terms.
|
||||
* Add dotted line drawing to DrawingHandleScreen.
|
||||
* `IConfigurationManager.LoadDefaultsFromTomlStream` properly does type conversions. This fixes scenarios like loading of `long` CVars.
|
||||
* Add helper methods for TileRef / Vector2i to SharedMapSystem for ToCenterCoordinates (tile center EntityCoordinates) and ToCoordinates (tile origin to EntityCoordinates).
|
||||
* Copy some of the coordinates extensions to SharedTransformSystem.
|
||||
|
||||
### Bugfixes
|
||||
|
||||
* Fixed integer overflows in replay max size calculation.
|
||||
* Explicitly capped `replay.replay_tick_batchSize` internally to avoid high values causing allocation failures.
|
||||
|
||||
### Other
|
||||
|
||||
* Important MIDI performance improvements.
|
||||
|
||||
|
||||
## 208.0.0
|
||||
|
||||
### Breaking changes
|
||||
|
||||
* Metadata flags are no longer serialized as they get rebuilt on entity startup.
|
||||
|
||||
### Bugfixes
|
||||
|
||||
* Log failing to load user keybinds and handle the exception.
|
||||
|
||||
|
||||
## 207.1.0
|
||||
|
||||
### New features
|
||||
|
||||
* Add the ability to merge grids via GridFixtureSystem.
|
||||
|
||||
|
||||
## 207.0.0
|
||||
|
||||
### Breaking changes
|
||||
|
||||
* Update EntityLookup internally so non-approximate queries use the GJK solver and are much more accurate. This also means the approximate flag matters much more if you don't need narrowphase checks.
|
||||
* Add shape versions of queries for both EntityLookup and MapManager.
|
||||
|
||||
### Bugfixes
|
||||
|
||||
* Fix PVS full state updates not clearing session entities and causing exceptions.
|
||||
|
||||
### Other
|
||||
|
||||
* Integration tests now run `NetMessage`s through serialization rather than passing the objects between client and server. This causes tests that missed `[NetSerializer]` attributes on any objects that need them to fail.
|
||||
|
||||
### Internal
|
||||
|
||||
* Remove a lot of duplicate code internally from EntityLookup and MapManager.
|
||||
|
||||
|
||||
## 206.0.0
|
||||
|
||||
### Breaking changes
|
||||
|
||||
* tpto will teleport you to physics-center instead of transform center instead.
|
||||
* Rename local EntityLookup methods to reflect they take local AABBs and not world AABBs.
|
||||
|
||||
### New features
|
||||
|
||||
* Add some additional EntityLookup methods for local queries.
|
||||
* Add support to PrototypeManager for parsing specific files / directories as abstract.
|
||||
|
||||
### Bugfixes
|
||||
|
||||
* Fix tpto short-circuiting if one of the listed entities isn't found.
|
||||
* Fix tpto not allowing grids as targets.
|
||||
|
||||
### Other
|
||||
|
||||
* Reduce MIDI source update rate from 10hz to 4hz.
|
||||
|
||||
### Internal
|
||||
|
||||
* Remove some duplicate internal code in EntityLookupSystem.
|
||||
* Skip serialization sourcegen in GLFW and Lidgren.
|
||||
|
||||
|
||||
## 205.0.0
|
||||
|
||||
### Breaking changes
|
||||
|
||||
* The unused `Robust.Physics` project has been deleted.
|
||||
* The project now uses [Central Package Management](https://learn.microsoft.com/en-us/nuget/consume-packages/central-package-management).
|
||||
* (Almost) all the NuGet packages have been updated. This causes many problems. I am so sorry.
|
||||
* Cleaned up some unused packages as well.
|
||||
|
||||
|
||||
## 204.1.0
|
||||
|
||||
### New features
|
||||
|
||||
* New `EntitySystem` subscription helper for working with Bound User Interface events. You can find them by doing `Subs.BuiEvents<>()` in a system.
|
||||
* The `EntityManager.Subscriptions` type (for building helper extension methods) now uses
|
||||
|
||||
### Bugfixes
|
||||
|
||||
* Avoid loading assemblies from content `/Assemblies` if Robust ships its own copy. This avoid duplicate or weird mismatching version issues.
|
||||
|
||||
### Other
|
||||
|
||||
* Removed glibc version check warning.
|
||||
|
||||
|
||||
## 204.0.0
|
||||
|
||||
### Breaking changes
|
||||
|
||||
* Make EntityManager abstract and make IEntityManager.EntityNetManager not nullable.
|
||||
* Make VVAccess.ReadWrite default for all Datafields instead of VVAccess.ReadOnly
|
||||
|
||||
### New features
|
||||
|
||||
* `TextEdit.OnTextChanged`
|
||||
* Add Pick and PickAndTake versions for System.Random for ICollections.
|
||||
|
||||
### Bugfixes
|
||||
|
||||
* Fix `IClipboardManager.GetText()` returning null in some cases.
|
||||
* Fix possible NRE in server-side console command completion code.
|
||||
* Fix possible NRE on DebugConsole logs.
|
||||
* Fix exception when VVing non-networked components.
|
||||
|
||||
### Other
|
||||
|
||||
* Remove "Do not use from content" from IComponent.
|
||||
|
||||
|
||||
## 203.0.0
|
||||
|
||||
### Breaking changes
|
||||
@@ -67,8 +256,8 @@ END TEMPLATE-->
|
||||
### New features
|
||||
|
||||
* `RobustUnitTest` now has a `ExtraComponents` field for automatically registering additional components.
|
||||
* `IComponentFactory.RegisterIgnore()` now accepts more than one string.
|
||||
* Added `IComponentFactory.RegisterTypes` for simultaneously registering multiple components.
|
||||
* `IComponentFactory.RegisterIgnore()` now accepts more than one string.
|
||||
* Added `IComponentFactory.RegisterTypes` for simultaneously registering multiple components.
|
||||
|
||||
### Bugfixes
|
||||
|
||||
@@ -82,7 +271,7 @@ END TEMPLATE-->
|
||||
* Reverted some map/grid initialisation changes that might've been causing broadphase/physics errors.
|
||||
* Fixed PVS sometimes sending entities without first sending their children.
|
||||
* Fixed a container state handling bug caused by containers not removing expected entities when shutting down.
|
||||
* Fixed a `EnsureEntity<T>` state handling bug caused by improper handling of entity deletions.
|
||||
* Fixed a `EnsureEntity<T>` state handling bug caused by improper handling of entity deletions.
|
||||
* Fixed a bad NetSyncEnabled debug assert.
|
||||
|
||||
|
||||
@@ -98,7 +287,7 @@ END TEMPLATE-->
|
||||
### Breaking changes
|
||||
|
||||
* Various entity manager methods now have a new `where T : IComponent` constraint.
|
||||
* The `IComponentFactory.ComponentAdded` event has been renamed to `ComponentsAdded` and now provides an array of component registrations.
|
||||
* The `IComponentFactory.ComponentAdded` event has been renamed to `ComponentsAdded` and now provides an array of component registrations.
|
||||
* `IComponentFactory.RegisterIgnore()` no longer supports overwriting existing registrations, components should get ignored before they are registered.
|
||||
|
||||
### New features
|
||||
|
||||
8
Resources/Locale/en-US/physics/grid_merging.ftl
Normal file
8
Resources/Locale/en-US/physics/grid_merging.ftl
Normal file
@@ -0,0 +1,8 @@
|
||||
cmd-merge_grids-desc = Combines 2 grids into 1 grid
|
||||
cmd-merge_grids-help = merge_grids <gridUid1> <gridUid2> <offsetX> <offsetY> [angle]
|
||||
|
||||
cmd-merge_grids-hintA = Grid A
|
||||
cmd-merge_grids-hintB = Grid B
|
||||
cmd-merge_grids-xOffset = X offset
|
||||
cmd-merge_grids-yOffset = Y offset
|
||||
cmd-merge_grids-angle = [Angle]
|
||||
@@ -1,23 +1,26 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="..\MSBuild\Robust.Properties.targets" />
|
||||
<Import Project="..\MSBuild\Robust.Engine.props" />
|
||||
|
||||
<Import Project="..\MSBuild\Robust.Properties.targets"/>
|
||||
<Import Project="..\MSBuild\Robust.Engine.props"/>
|
||||
|
||||
<PropertyGroup>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.Analyzer.Testing" Version="1.1.1"/>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.0.1"/>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Analyzer.Testing.NUnit" Version="1.1.1"/>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.0.1"/>
|
||||
<PackageReference Include="NUnit" Version="3.13.2"/>
|
||||
<PackageReference Include="NUnit.ConsoleRunner" Version="3.15.0"/>
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1"/>
|
||||
<PackageReference Include="NUnit.Analyzers" Version="3.3.0"/>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.2.0" />
|
||||
<PackageVersion Update="NUnit" Version="3.14.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.Analyzer.Testing"/>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp"/>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Analyzer.Testing.NUnit"/>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces"/>
|
||||
<PackageReference Include="NUnit"/>
|
||||
<PackageReference Include="NUnit3TestAdapter"/>
|
||||
<PackageReference Include="NUnit.Analyzers"/>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Robust.Analyzers\Robust.Analyzers.csproj"/>
|
||||
</ItemGroup>
|
||||
|
||||
@@ -3,19 +3,20 @@
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<LangVersion>10</LangVersion>
|
||||
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.0.1" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.3" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.Common" Version="4.0.1" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.Common" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- Needed for NotNullableFlagAnalyzer. -->
|
||||
<Compile Include="..\Robust.Shared\Analyzers\NotNullableFlagAttribute.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<!-- Needed for FriendAnalyzer. -->
|
||||
<Compile Include="..\Robust.Shared\Analyzers\AccessAttribute.cs" />
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using BenchmarkDotNet.Analysers;
|
||||
using BenchmarkDotNet.Columns;
|
||||
using BenchmarkDotNet.Configs;
|
||||
using BenchmarkDotNet.Diagnosers;
|
||||
using BenchmarkDotNet.EventProcessors;
|
||||
using BenchmarkDotNet.Exporters;
|
||||
using BenchmarkDotNet.Filters;
|
||||
using BenchmarkDotNet.Jobs;
|
||||
using BenchmarkDotNet.Loggers;
|
||||
using BenchmarkDotNet.Order;
|
||||
using BenchmarkDotNet.Reports;
|
||||
using BenchmarkDotNet.Running;
|
||||
using BenchmarkDotNet.Validators;
|
||||
using Robust.Benchmarks.Exporters;
|
||||
|
||||
@@ -44,10 +47,16 @@ public sealed class DefaultSQLConfig : IConfig
|
||||
|
||||
public IEnumerable<BenchmarkLogicalGroupRule> GetLogicalGroupRules() => DefaultConfig.Instance.GetLogicalGroupRules();
|
||||
|
||||
public IEnumerable<EventProcessor> GetEventProcessors() => DefaultConfig.Instance.GetEventProcessors();
|
||||
|
||||
public IEnumerable<IColumnHidingRule> GetColumnHidingRules() => DefaultConfig.Instance.GetColumnHidingRules();
|
||||
public IOrderer Orderer => DefaultConfig.Instance.Orderer!;
|
||||
public ICategoryDiscoverer? CategoryDiscoverer => DefaultConfig.Instance.CategoryDiscoverer;
|
||||
public SummaryStyle SummaryStyle => DefaultConfig.Instance.SummaryStyle;
|
||||
public ConfigUnionRule UnionRule => DefaultConfig.Instance.UnionRule;
|
||||
public string ArtifactsPath => DefaultConfig.Instance.ArtifactsPath;
|
||||
public CultureInfo CultureInfo => DefaultConfig.Instance.CultureInfo!;
|
||||
public ConfigOptions Options => DefaultConfig.Instance.Options;
|
||||
public TimeSpan BuildTimeout => DefaultConfig.Instance.BuildTimeout;
|
||||
public IReadOnlyList<Conclusion> ConfigAnalysisConclusion => DefaultConfig.Instance.ConfigAnalysisConclusion;
|
||||
}
|
||||
|
||||
@@ -13,12 +13,12 @@
|
||||
<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">
|
||||
<PackageReference Include="BenchmarkDotNet" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="6.0.4" />
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="..\MSBuild\Robust.Properties.targets" />
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Build.Framework" Version="17.0.0" />
|
||||
<PackageReference Include="Mono.Cecil" Version="0.11.3" />
|
||||
<PackageReference Include="Microsoft.Build.Framework" Version="17.8.3" />
|
||||
<PackageReference Include="Mono.Cecil" Version="0.11.5" />
|
||||
<PackageReference Include="Pidgin" Version="2.5.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -2,11 +2,12 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.0.1" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.3" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" PrivateAssets="all" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="JetBrains.Annotations" Version="2020.3.0" />
|
||||
<PackageReference Include="Robust.Natives.Cef" Version="120.1.9" />
|
||||
<PackageReference Include="JetBrains.Annotations" />
|
||||
<PackageReference Include="Robust.Natives.Cef" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -39,7 +39,7 @@ public sealed class AudioOverlay : Overlay
|
||||
|
||||
protected internal override void Draw(in OverlayDrawArgs args)
|
||||
{
|
||||
var localPlayer = _playerManager.LocalPlayer?.ControlledEntity;
|
||||
var localPlayer = _playerManager.LocalEntity;
|
||||
|
||||
if (args.ViewportControl == null || localPlayer == null)
|
||||
return;
|
||||
|
||||
@@ -106,8 +106,8 @@ public sealed partial class AudioSystem : SharedAudioSystem
|
||||
SubscribeNetworkEvent<PlayAudioEntityMessage>(OnEntityAudio);
|
||||
SubscribeNetworkEvent<PlayAudioPositionalMessage>(OnEntityCoordinates);
|
||||
|
||||
CfgManager.OnValueChanged(CVars.AudioAttenuation, OnAudioAttenuation, true);
|
||||
CfgManager.OnValueChanged(CVars.AudioRaycastLength, OnRaycastLengthChanged, true);
|
||||
Subs.CVar(CfgManager, CVars.AudioAttenuation, OnAudioAttenuation, true);
|
||||
Subs.CVar(CfgManager, CVars.AudioRaycastLength, OnRaycastLengthChanged, true);
|
||||
}
|
||||
|
||||
private void OnAudioState(EntityUid uid, AudioComponent component, ref AfterAutoHandleStateEvent args)
|
||||
@@ -133,13 +133,6 @@ public sealed partial class AudioSystem : SharedAudioSystem
|
||||
_audio.SetMasterGain(value);
|
||||
}
|
||||
|
||||
public override void Shutdown()
|
||||
{
|
||||
CfgManager.UnsubValueChanged(CVars.AudioAttenuation, OnAudioAttenuation);
|
||||
CfgManager.UnsubValueChanged(CVars.AudioRaycastLength, OnRaycastLengthChanged);
|
||||
base.Shutdown();
|
||||
}
|
||||
|
||||
private void OnAudioPaused(EntityUid uid, AudioComponent component, ref EntityPausedEvent args)
|
||||
{
|
||||
component.Pause();
|
||||
|
||||
@@ -72,7 +72,7 @@ internal sealed partial class MidiManager : IMidiManager
|
||||
|
||||
// To avoid lock contention until some kind of MIDI refactor.
|
||||
private TimeSpan _nextUpdate;
|
||||
private TimeSpan _updateFrequency = TimeSpan.FromSeconds(0.1f);
|
||||
private TimeSpan _updateFrequency = TimeSpan.FromSeconds(0.25f);
|
||||
|
||||
private SemaphoreSlim _updateSemaphore = new(1);
|
||||
|
||||
@@ -192,7 +192,12 @@ internal sealed partial class MidiManager : IMidiManager
|
||||
_settings["synth.midi-bank-select"].StringValue = "gm";
|
||||
//_settings["synth.verbose"].IntValue = 1; // Useful for debugging.
|
||||
|
||||
_parallel.AddAndInvokeParallelCountChanged(UpdateParallelCount);
|
||||
var midiParallel = _cfgMan.GetCVar(CVars.MidiParallelism);
|
||||
_settings["synth.polyphony"].IntValue = Math.Clamp(1024 + (int)(Math.Log2(midiParallel) * 2048), 1, 65535);
|
||||
_settings["synth.cpu-cores"].IntValue = Math.Clamp(midiParallel, 1, 256);
|
||||
|
||||
_midiSawmill.Debug($"Synth Cores: {_settings["synth.cpu-cores"].IntValue}");
|
||||
_midiSawmill.Debug($"Synth Polyphony: {_settings["synth.polyphony"].IntValue}");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -201,7 +206,10 @@ internal sealed partial class MidiManager : IMidiManager
|
||||
return;
|
||||
}
|
||||
|
||||
_midiThread = new Thread(ThreadUpdate);
|
||||
_midiThread = new Thread(ThreadUpdate)
|
||||
{
|
||||
Name = "RobustToolbox MIDI Thread"
|
||||
};
|
||||
_midiThread.Start();
|
||||
|
||||
_updateJob = new MidiUpdateJob()
|
||||
@@ -219,18 +227,6 @@ internal sealed partial class MidiManager : IMidiManager
|
||||
FluidsynthInitialized = true;
|
||||
}
|
||||
|
||||
private void UpdateParallelCount()
|
||||
{
|
||||
if (_settings == null)
|
||||
return;
|
||||
|
||||
_settings["synth.polyphony"].IntValue = Math.Clamp(1024 + (int)(Math.Log2(_parallel.ParallelProcessCount) * 2048), 1, 65535);
|
||||
_settings["synth.cpu-cores"].IntValue = Math.Clamp(_parallel.ParallelProcessCount, 1, 256);
|
||||
|
||||
_midiSawmill.Debug($"Synth Cores: {_settings["synth.cpu-cores"].IntValue}");
|
||||
_midiSawmill.Debug($"Synth Polyphony: {_settings["synth.polyphony"].IntValue}");
|
||||
}
|
||||
|
||||
private void LoggerDelegate(NFluidsynth.Logger.LogLevel level, string message, IntPtr data)
|
||||
{
|
||||
var rLevel = level switch
|
||||
|
||||
@@ -38,6 +38,7 @@ internal sealed class MidiRenderer : IMidiRenderer
|
||||
private readonly Synth _synth;
|
||||
private readonly Sequencer _sequencer;
|
||||
private NFluidsynth.Player? _player;
|
||||
private int _playerTotalTicks;
|
||||
private MidiDriver? _driver;
|
||||
private byte _midiProgram = 1;
|
||||
private byte _midiBank = 1;
|
||||
@@ -144,7 +145,21 @@ internal sealed class MidiRenderer : IMidiRenderer
|
||||
public bool DisableProgramChangeEvent { get; set; } = true;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public int PlayerTotalTick => _player?.GetTotalTicks ?? 0;
|
||||
public int PlayerTotalTick
|
||||
{
|
||||
get
|
||||
{
|
||||
// GetTotalTicks is really expensive (has to iterate the entire file, not cached).
|
||||
// Slight problem with caching it ourselves: the value only becomes available when the player loads the MIDI file.
|
||||
// And that only happens after playback really starts, with the timer and synth and all that stuff.
|
||||
// So we cache it "as soon as it's available", i.e. not 0.
|
||||
// We don't care about playlists and such, so it shouldn't change anymore after.
|
||||
if (_playerTotalTicks != 0)
|
||||
return _playerTotalTicks;
|
||||
|
||||
return _playerTotalTicks = _player?.GetTotalTicks ?? 0;
|
||||
}
|
||||
}
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public int PlayerTick
|
||||
@@ -339,6 +354,7 @@ internal sealed class MidiRenderer : IMidiRenderer
|
||||
return false;
|
||||
}
|
||||
|
||||
_playerTotalTicks = 0;
|
||||
_player?.Dispose();
|
||||
_player = new NFluidsynth.Player(_synth);
|
||||
_player.SetPlaybackCallback(MidiPlayerEventHandler);
|
||||
@@ -377,6 +393,7 @@ internal sealed class MidiRenderer : IMidiRenderer
|
||||
_player?.Join();
|
||||
_player?.Dispose();
|
||||
_player = null;
|
||||
_playerTotalTicks = 0;
|
||||
}
|
||||
|
||||
StopAllNotes();
|
||||
|
||||
@@ -229,7 +229,7 @@ namespace Robust.Client
|
||||
|
||||
// Don't invoke PlayerLeaveServer if PlayerJoinedServer & GameStartedSetup hasn't been called yet.
|
||||
if (RunLevel > ClientRunLevel.Connecting)
|
||||
PlayerLeaveServer?.Invoke(this, new PlayerEventArgs(_playMan.LocalPlayer?.Session));
|
||||
PlayerLeaveServer?.Invoke(this, new PlayerEventArgs(_playMan.LocalSession));
|
||||
|
||||
LastDisconnectReason = args.Reason;
|
||||
GameStoppedReset();
|
||||
|
||||
@@ -188,7 +188,7 @@ namespace Robust.Client.Console
|
||||
}
|
||||
|
||||
args.RemoveAt(0);
|
||||
var shell = new ConsoleShell(this, session ?? _player.LocalPlayer?.Session, session == null);
|
||||
var shell = new ConsoleShell(this, session ?? _player.LocalSession, session == null);
|
||||
var cmdArgs = args.ToArray();
|
||||
|
||||
AnyCommandExecuted?.Invoke(shell, commandName, command, cmdArgs);
|
||||
@@ -200,8 +200,7 @@ namespace Robust.Client.Console
|
||||
// When not connected to a server, you can run all local commands.
|
||||
// When connected to a server, you can only run commands according to the con group controller.
|
||||
|
||||
return _player.LocalPlayer == null
|
||||
|| _player.LocalPlayer.Session.Status <= SessionStatus.Connecting
|
||||
return _player.LocalSession is not { Status: > SessionStatus.Connecting }
|
||||
|| _conGroup.CanCommand(cmdName);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,8 +16,7 @@ namespace Robust.Client.Console.Commands
|
||||
|
||||
public override void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var controlled = _playerManager.LocalPlayer?.ControlledEntity ?? EntityUid.Invalid;
|
||||
if (controlled == EntityUid.Invalid)
|
||||
if (_playerManager.LocalEntity is not { } controlled)
|
||||
{
|
||||
shell.WriteLine("You don't have an attached entity.");
|
||||
return;
|
||||
|
||||
@@ -420,7 +420,7 @@ namespace Robust.Client.Debugging
|
||||
if (mapPos.MapId != args.MapId)
|
||||
return;
|
||||
|
||||
var player = _playerManager.LocalPlayer?.ControlledEntity;
|
||||
var player = _playerManager.LocalEntity;
|
||||
|
||||
if (!_entityManager.TryGetComponent<TransformComponent>(player, out var playerXform) ||
|
||||
playerXform.MapID != args.MapId)
|
||||
|
||||
@@ -35,8 +35,6 @@ namespace Robust.Client
|
||||
throw new InvalidOperationException("Cannot start twice!");
|
||||
}
|
||||
|
||||
GlibcBug.Check();
|
||||
|
||||
_hasStarted = true;
|
||||
|
||||
if (CommandLineArgs.TryParse(args, out var parsed))
|
||||
|
||||
@@ -42,6 +42,8 @@ public sealed partial class ClientEntityManager
|
||||
var pending = PendingNetEntityStates.GetOrNew(nEntity);
|
||||
pending.Add((typeof(T), callerEntity));
|
||||
|
||||
|
||||
|
||||
return entity.Item1;
|
||||
}
|
||||
|
||||
|
||||
@@ -221,7 +221,7 @@ namespace Robust.Client.GameObjects
|
||||
public void DispatchReceivedNetworkMsg(EntityEventArgs msg)
|
||||
{
|
||||
var sessionType = typeof(EntitySessionMessage<>).MakeGenericType(msg.GetType());
|
||||
var sessionMsg = Activator.CreateInstance(sessionType, new EntitySessionEventArgs(_playerManager.LocalPlayer!.Session), msg)!;
|
||||
var sessionMsg = Activator.CreateInstance(sessionType, new EntitySessionEventArgs(_playerManager.LocalSession!), msg)!;
|
||||
ReceivedSystemMessage?.Invoke(this, msg);
|
||||
ReceivedSystemMessage?.Invoke(this, sessionMsg);
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ internal sealed class ClientOccluderSystem : OccluderSystem
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<OccluderComponent, AnchorStateChangedEvent>(OnAnchorChanged);
|
||||
SubscribeLocalEvent<OccluderComponent, ReAnchorEvent>(OnReAnchor);
|
||||
SubscribeLocalEvent<OccluderComponent, ComponentShutdown>(OnShutdown);
|
||||
}
|
||||
|
||||
@@ -90,11 +89,6 @@ internal sealed class ClientOccluderSystem : OccluderSystem
|
||||
AnchorStateChanged(uid, comp, args.Transform);
|
||||
}
|
||||
|
||||
private void OnReAnchor(EntityUid uid, OccluderComponent comp, ref ReAnchorEvent args)
|
||||
{
|
||||
AnchorStateChanged(uid, comp, args.Xform);
|
||||
}
|
||||
|
||||
private void QueueOccludedDirectionUpdate(EntityUid sender, OccluderComponent occluder, TransformComponent? xform = null)
|
||||
{
|
||||
if (!Resolve(sender, ref xform))
|
||||
@@ -174,8 +168,9 @@ internal sealed class ClientOccluderSystem : OccluderSystem
|
||||
|
||||
var tile = grid.TileIndicesFor(xform.Coordinates);
|
||||
|
||||
DebugTools.Assert(occluder.LastPosition == null
|
||||
|| occluder.LastPosition.Value.Grid == xform.GridUid && occluder.LastPosition.Value.Tile == tile);
|
||||
// TODO: Sub to parent changes instead or something.
|
||||
// DebugTools.Assert(occluder.LastPosition == null
|
||||
// || occluder.LastPosition.Value.Grid == xform.GridUid && occluder.LastPosition.Value.Tile == tile);
|
||||
occluder.LastPosition = (xform.GridUid.Value, tile);
|
||||
|
||||
// dir starts at the relative effective south direction;
|
||||
|
||||
@@ -105,12 +105,10 @@ namespace Robust.Client.GameObjects
|
||||
/// <param name="inputCmd">Input command to handle as predicted.</param>
|
||||
public void PredictInputCommand(IFullInputCmdMessage inputCmd)
|
||||
{
|
||||
DebugTools.AssertNotNull(_playerManager.LocalPlayer);
|
||||
|
||||
var keyFunc = _inputManager.NetworkBindMap.KeyFunctionName(inputCmd.InputFunctionId);
|
||||
|
||||
Predicted = true;
|
||||
var session = _playerManager.LocalPlayer!.Session;
|
||||
var session = _playerManager.LocalSession;
|
||||
foreach (var handler in BindRegistry.GetHandlers(keyFunc))
|
||||
{
|
||||
if (handler.HandleCmdMessage(EntityManager, session, inputCmd))
|
||||
@@ -145,27 +143,22 @@ namespace Robust.Client.GameObjects
|
||||
|
||||
private void GenerateInputCommand(IConsoleShell shell, string argstr, string[] args)
|
||||
{
|
||||
var localPlayer = _playerManager.LocalPlayer;
|
||||
if(localPlayer is null)
|
||||
return;
|
||||
|
||||
var pent = localPlayer.ControlledEntity;
|
||||
if(pent is null)
|
||||
if (_playerManager.LocalEntity is not { } pent)
|
||||
return;
|
||||
|
||||
BoundKeyFunction keyFunction = new BoundKeyFunction(args[0]);
|
||||
BoundKeyState state = args[1] == "u" ? BoundKeyState.Up: BoundKeyState.Down;
|
||||
|
||||
var pxform = Transform(pent.Value);
|
||||
var pxform = Transform(pent);
|
||||
var wPos = pxform.WorldPosition + new Vector2(float.Parse(args[2]), float.Parse(args[3]));
|
||||
var coords = EntityCoordinates.FromMap(EntityManager, pent.Value, new MapCoordinates(wPos, pxform.MapID));
|
||||
var coords = EntityCoordinates.FromMap(EntityManager, pent, new MapCoordinates(wPos, pxform.MapID));
|
||||
|
||||
var funcId = _inputManager.NetworkBindMap.KeyFunctionID(keyFunction);
|
||||
|
||||
var message = new FullInputCmdMessage(_timing.CurTick, _timing.TickFraction, funcId, state,
|
||||
GetNetCoordinates(coords), new ScreenCoordinates(0, 0, default), NetEntity.Invalid);
|
||||
|
||||
HandleInputCommand(localPlayer.Session, keyFunction, message);
|
||||
HandleInputCommand(_playerManager.LocalSession, keyFunction, message);
|
||||
}
|
||||
|
||||
private void OnAttachedEntityChanged(LocalPlayerAttachedEvent message)
|
||||
@@ -208,11 +201,8 @@ namespace Robust.Client.GameObjects
|
||||
/// </summary>
|
||||
public void SetEntityContextActive()
|
||||
{
|
||||
var controlled = _playerManager.LocalPlayer?.ControlledEntity ?? EntityUid.Invalid;
|
||||
if (controlled == EntityUid.Invalid)
|
||||
{
|
||||
if (_playerManager.LocalEntity is not { } controlled)
|
||||
return;
|
||||
}
|
||||
|
||||
SetEntityContextActive(_inputManager, controlled);
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace Robust.Client.GameObjects
|
||||
SubscribeLocalEvent<SpriteComponent, SpriteUpdateInertEvent>(QueueUpdateInert);
|
||||
SubscribeLocalEvent<SpriteComponent, ComponentInit>(OnInit);
|
||||
|
||||
_cfg.OnValueChanged(CVars.RenderSpriteDirectionBias, OnBiasChanged, true);
|
||||
Subs.CVar(_cfg, CVars.RenderSpriteDirectionBias, OnBiasChanged, true);
|
||||
_sawmill = _logManager.GetSawmill("sprite");
|
||||
}
|
||||
|
||||
@@ -72,12 +72,6 @@ namespace Robust.Client.GameObjects
|
||||
QueueUpdateInert(uid, component);
|
||||
}
|
||||
|
||||
public override void Shutdown()
|
||||
{
|
||||
base.Shutdown();
|
||||
_cfg.UnsubValueChanged(CVars.RenderSpriteDirectionBias, OnBiasChanged);
|
||||
}
|
||||
|
||||
private void OnBiasChanged(double value)
|
||||
{
|
||||
SpriteComponent.DirectionBias = value;
|
||||
|
||||
@@ -29,10 +29,7 @@ namespace Robust.Client.GameObjects
|
||||
|
||||
var uiKey = ev.UiKey;
|
||||
var message = ev.Message;
|
||||
// This should probably not happen at this point, but better make extra sure!
|
||||
if (_playerManager.LocalPlayer != null)
|
||||
message.Session = _playerManager.LocalPlayer.Session;
|
||||
|
||||
message.Session = _playerManager.LocalSession!;
|
||||
message.Entity = GetNetEntity(uid);
|
||||
message.UiKey = uiKey;
|
||||
|
||||
@@ -75,8 +72,7 @@ namespace Robust.Client.GameObjects
|
||||
boundInterface.Open();
|
||||
uiComp.OpenInterfaces[uiKey] = boundInterface;
|
||||
|
||||
var playerSession = _playerManager.LocalPlayer?.Session;
|
||||
if (playerSession != null)
|
||||
if (_playerManager.LocalSession is { } playerSession)
|
||||
{
|
||||
uiComp.Interfaces[uiKey]._subscribedSessions.Add(playerSession);
|
||||
RaiseLocalEvent(uid, new BoundUIOpenedEvent(uiKey, uid, playerSession), true);
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace Robust.Client.GameObjects
|
||||
return;
|
||||
}
|
||||
|
||||
var player = _playerManager.LocalPlayer?.ControlledEntity;
|
||||
var player = _playerManager.LocalEntity;
|
||||
|
||||
if (player == null || !EntityManager.TryGetComponent(player.Value, out PhysicsComponent? body))
|
||||
{
|
||||
|
||||
@@ -232,9 +232,9 @@ namespace Robust.Client.GameStates
|
||||
return default;
|
||||
}
|
||||
|
||||
DebugTools.AssertNotNull(_players.LocalPlayer);
|
||||
DebugTools.Assert(_players.LocalSession != null);
|
||||
|
||||
var evArgs = new EntitySessionEventArgs(_players.LocalPlayer!.Session);
|
||||
var evArgs = new EntitySessionEventArgs(_players.LocalSession);
|
||||
_pendingSystemMessages.Enqueue((_nextInputCmdSeq, _timing.CurTick, message,
|
||||
new EntitySessionMessage<T>(evArgs, message)));
|
||||
|
||||
|
||||
@@ -313,7 +313,7 @@ namespace Robust.Client.GameStates
|
||||
|
||||
if (args.Length == 0)
|
||||
{
|
||||
entity = _playerManager.LocalPlayer?.ControlledEntity ?? EntityUid.Invalid;
|
||||
entity = _playerManager.LocalEntity ?? EntityUid.Invalid;
|
||||
}
|
||||
else if (!NetEntity.TryParse(args[0], out var netEntity) || !_entManager.TryGetEntity(netEntity, out entity))
|
||||
{
|
||||
|
||||
@@ -28,6 +28,8 @@ namespace Robust.Client.Graphics.Clyde
|
||||
private int _verticesPerChunk(MapChunk chunk) => chunk.ChunkSize * chunk.ChunkSize * 4;
|
||||
private int _indicesPerChunk(MapChunk chunk) => chunk.ChunkSize * chunk.ChunkSize * GetQuadBatchIndexCount();
|
||||
|
||||
private List<Entity<MapGridComponent>> _grids = new();
|
||||
|
||||
private void _drawGrids(Viewport viewport, Box2 worldAABB, Box2Rotated worldBounds, IEye eye)
|
||||
{
|
||||
var mapId = eye.Position.MapId;
|
||||
@@ -37,14 +39,15 @@ namespace Robust.Client.Graphics.Clyde
|
||||
mapId = MapId.Nullspace;
|
||||
}
|
||||
|
||||
var grids = new List<Entity<MapGridComponent>>();
|
||||
_mapManager.FindGridsIntersecting(mapId, worldBounds, ref grids);
|
||||
_grids.Clear();
|
||||
_mapManager.FindGridsIntersecting(mapId, worldBounds, ref _grids);
|
||||
|
||||
var requiresFlush = true;
|
||||
GLShaderProgram gridProgram = default!;
|
||||
var gridOverlays = GetOverlaysForSpace(OverlaySpace.WorldSpaceGrids);
|
||||
var mapSystem = _entityManager.System<SharedMapSystem>();
|
||||
|
||||
foreach (var mapGrid in grids)
|
||||
foreach (var mapGrid in _grids)
|
||||
{
|
||||
if (!_mapChunkData.TryGetValue(mapGrid, out var data))
|
||||
{
|
||||
@@ -65,7 +68,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
|
||||
var transform = _entityManager.GetComponent<TransformComponent>(mapGrid);
|
||||
gridProgram.SetUniform(UniIModelMatrix, transform.WorldMatrix);
|
||||
var enumerator = mapGrid.Comp.GetMapChunks(worldBounds);
|
||||
var enumerator = mapSystem.GetMapChunks(mapGrid.Owner, mapGrid.Comp, worldBounds);
|
||||
|
||||
while (enumerator.MoveNext(out var chunk))
|
||||
{
|
||||
|
||||
@@ -224,8 +224,8 @@ namespace Robust.Client.Graphics.Clyde
|
||||
fixed (char* pCaption = "RobustToolbox: Failed to create window")
|
||||
{
|
||||
Windows.MessageBoxW(HWND.NULL,
|
||||
(ushort*) pText,
|
||||
(ushort*) pCaption,
|
||||
pText,
|
||||
pCaption,
|
||||
MB.MB_OK | MB.MB_ICONERROR);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -413,7 +413,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
DXGI_ADAPTER_DESC1 desc;
|
||||
ThrowIfFailed("GetDesc1", _adapter->GetDesc1(&desc));
|
||||
|
||||
var descName = new ReadOnlySpan<char>(desc.Description, 128).TrimEnd('\0');
|
||||
var descName = ((ReadOnlySpan<char>)desc.Description).TrimEnd('\0');
|
||||
|
||||
Logger.DebugS("clyde.ogl.angle", "Successfully created D3D11 device!");
|
||||
Logger.DebugS("clyde.ogl.angle", $"D3D11 Device Adapter: {descName.ToString()}");
|
||||
@@ -493,7 +493,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
DXGI_ADAPTER_DESC1 desc;
|
||||
ThrowIfFailed("GetDesc1", adapter->GetDesc1(&desc));
|
||||
|
||||
var descName = new ReadOnlySpan<char>(desc.Description, 128);
|
||||
var descName = ((ReadOnlySpan<char>)desc.Description);
|
||||
|
||||
if (descName.StartsWith(name))
|
||||
return adapter;
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
adapter->Release();
|
||||
ThrowIfFailed("GetDesc", adapter3->GetDesc2(&desc));
|
||||
|
||||
var descString = new ReadOnlySpan<char>(desc.Description, 128).TrimEnd('\0');
|
||||
var descString = ((ReadOnlySpan<char>)desc.Description).TrimEnd('\0');
|
||||
shell.WriteLine(descString.ToString());
|
||||
|
||||
DXGI_QUERY_VIDEO_MEMORY_INFO memInfo;
|
||||
|
||||
@@ -654,7 +654,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
|
||||
private static void WinThreadGetClipboard(CmdGetClipboard cmd)
|
||||
{
|
||||
var clipboard = GLFW.GetClipboardString((Window*) cmd.Window);
|
||||
var clipboard = GLFW.GetClipboardString((Window*) cmd.Window) ?? "";
|
||||
// Don't have to care about synchronization I don't think so just fire this immediately.
|
||||
cmd.Tcs.TrySetResult(clipboard);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Shared.Collections;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Graphics;
|
||||
using Robust.Shared.Maths;
|
||||
@@ -14,6 +15,79 @@ namespace Robust.Client.Graphics
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simialr to DrawLine but has dashes interspersed.
|
||||
/// </summary>
|
||||
/// <param name="offset">Offset from the start of the line.</param>
|
||||
/// <param name="dashSize">How long a dash is.</param>
|
||||
/// <param name="gapSize">How long the gap between dashes is.</param>
|
||||
public void DrawDottedLine(Vector2 from, Vector2 to, Color color, float offset = 0f, float dashSize = 8f, float gapSize = 2f)
|
||||
{
|
||||
var lineVector = to - from;
|
||||
|
||||
// No drawing for you.
|
||||
if (lineVector.LengthSquared() < 10f * float.Epsilon)
|
||||
return;
|
||||
|
||||
var lineAndGap = gapSize + dashSize;
|
||||
var lines = new ValueList<Vector2>();
|
||||
|
||||
// Minimum distance.
|
||||
if (lineVector.Length() < lineAndGap)
|
||||
{
|
||||
lines.Add(from);
|
||||
lines.Add(to);
|
||||
}
|
||||
else
|
||||
{
|
||||
var maxLength = lineVector.Length();
|
||||
var normalizedLine = lineVector.Normalized();
|
||||
var dashVector = normalizedLine * dashSize;
|
||||
var gapVector = normalizedLine * gapSize;
|
||||
|
||||
var position = from;
|
||||
offset %= (dashSize + gapSize);
|
||||
var length = offset;
|
||||
var dashLength = dashSize;
|
||||
|
||||
// If offset is less than gap size then start with a gap
|
||||
// otherwise start with a partial line
|
||||
if (offset > 0f)
|
||||
{
|
||||
if (offset < gapSize)
|
||||
{
|
||||
position += normalizedLine * offset;
|
||||
length += offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
dashLength = (offset - gapSize);
|
||||
}
|
||||
}
|
||||
|
||||
while (length < maxLength)
|
||||
{
|
||||
lines.Add(position);
|
||||
|
||||
position += normalizedLine * dashLength;
|
||||
var lengthFromStart = (position - from).Length();
|
||||
|
||||
// if over length then cap the thing.
|
||||
if (lengthFromStart > maxLength)
|
||||
{
|
||||
position = to;
|
||||
}
|
||||
|
||||
lines.Add(position);
|
||||
dashLength = dashVector.Length();
|
||||
position += gapVector;
|
||||
length = (position - from).Length();
|
||||
}
|
||||
}
|
||||
|
||||
DrawPrimitives(DrawPrimitiveTopology.LineList, lines.Span, color);
|
||||
}
|
||||
|
||||
public abstract void DrawRect(UIBox2 rect, Color color, bool filled = true);
|
||||
|
||||
public abstract void DrawTextureRectRegion(Texture texture, UIBox2 rect, UIBox2? subRegion = null, Color? modulate = null);
|
||||
|
||||
@@ -6,7 +6,10 @@ using Robust.Shared.Maths;
|
||||
|
||||
namespace Robust.Client.Graphics
|
||||
{
|
||||
internal interface IRenderHandle
|
||||
/// <remarks>
|
||||
/// Unstable API. Likely to break hard during renderer rewrite if you rely on it.
|
||||
/// </remarks>
|
||||
public interface IRenderHandle
|
||||
{
|
||||
DrawingHandleScreen DrawingHandleScreen { get; }
|
||||
DrawingHandleWorld DrawingHandleWorld { get; }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using Robust.Client.ResourceManagement;
|
||||
@@ -69,7 +69,7 @@ namespace Robust.Client.Graphics
|
||||
ShaderBlendMode? blend = null;
|
||||
if (_rawBlendMode != null)
|
||||
{
|
||||
if (!Enum.TryParse<ShaderBlendMode>(_rawBlendMode.ToUpper(), out var parsed))
|
||||
if (!Enum.TryParse<ShaderBlendMode>(_rawBlendMode, true, out var parsed))
|
||||
Logger.Error($"invalid mode: {_rawBlendMode}");
|
||||
else
|
||||
blend = parsed;
|
||||
|
||||
@@ -124,12 +124,19 @@ namespace Robust.Client.Input
|
||||
var path = new ResPath(KeybindsPath);
|
||||
if (_resourceMan.UserData.Exists(path))
|
||||
{
|
||||
LoadKeyFile(path, true);
|
||||
try
|
||||
{
|
||||
LoadKeyFile(path, false, true);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.ErrorS("input", "Failed to load user keybindings: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
if (_resourceMan.ContentFileExists(path))
|
||||
{
|
||||
LoadKeyFile(path, false);
|
||||
LoadKeyFile(path, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -489,7 +496,13 @@ namespace Robust.Client.Input
|
||||
return true;
|
||||
}
|
||||
|
||||
private void LoadKeyFile(ResPath file, bool userData)
|
||||
/// <summary>
|
||||
/// Loads a keybind file, configuring keybinds.
|
||||
/// </summary>
|
||||
/// <param name="file">File to load from the content package</param>
|
||||
/// <param name="defaultRegistration">Whether or not this is a "default" keybind set. If it is, then it won't override the current configuration, only the defaults.</param>
|
||||
/// <param name="userData">Whether or not to load from the user data directory instead of the content package.</param>
|
||||
public void LoadKeyFile(ResPath file, bool defaultRegistration, bool userData = false)
|
||||
{
|
||||
TextReader reader;
|
||||
if (userData)
|
||||
@@ -519,7 +532,7 @@ namespace Robust.Client.Input
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!userData)
|
||||
if (defaultRegistration)
|
||||
{
|
||||
_defaultRegistrations.Add(reg);
|
||||
|
||||
@@ -531,11 +544,11 @@ namespace Robust.Client.Input
|
||||
}
|
||||
}
|
||||
|
||||
RegisterBinding(reg, markModified: userData);
|
||||
RegisterBinding(reg, markModified: defaultRegistration);
|
||||
}
|
||||
}
|
||||
|
||||
if (userData && mapping.TryGet("leaveEmpty", out var node))
|
||||
if (!defaultRegistration && mapping.TryGet("leaveEmpty", out var node))
|
||||
{
|
||||
var leaveEmpty = _serialization.Read<BoundKeyFunction[]>(node, notNullableOverride: true);
|
||||
|
||||
|
||||
@@ -37,7 +37,9 @@ public sealed class TileEdgeOverlay : GridOverlay
|
||||
var tileDimensions = new Vector2(tileSize, tileSize);
|
||||
var (_, _, worldMatrix, invMatrix) = xformSystem.GetWorldPositionRotationMatrixWithInv(Grid.Owner);
|
||||
args.WorldHandle.SetTransform(worldMatrix);
|
||||
var localAABB = invMatrix.TransformBox(args.WorldBounds);
|
||||
var bounds = args.WorldBounds;
|
||||
bounds = new Box2Rotated(bounds.Box.Enlarged(1), bounds.Rotation, bounds.Origin);
|
||||
var localAABB = invMatrix.TransformBox(bounds);
|
||||
|
||||
var enumerator = mapSystem.GetLocalTilesEnumerator(Grid.Owner, Grid, localAABB, false);
|
||||
|
||||
|
||||
@@ -207,8 +207,8 @@ public sealed partial class PhysicsSystem
|
||||
var contact = contacts[i];
|
||||
var uidA = contact.EntityA;
|
||||
var uidB = contact.EntityB;
|
||||
var bodyATransform = GetPhysicsTransform(uidA, xformQuery.GetComponent(uidA), xformQuery);
|
||||
var bodyBTransform = GetPhysicsTransform(uidB, xformQuery.GetComponent(uidB), xformQuery);
|
||||
var bodyATransform = GetPhysicsTransform(uidA, xformQuery.GetComponent(uidA));
|
||||
var bodyBTransform = GetPhysicsTransform(uidB, xformQuery.GetComponent(uidB));
|
||||
contact.UpdateIsTouching(bodyATransform, bodyBTransform);
|
||||
}
|
||||
|
||||
|
||||
@@ -495,7 +495,7 @@ namespace Robust.Client.Placement
|
||||
{
|
||||
// Try to get current map.
|
||||
var map = MapId.Nullspace;
|
||||
if (EntityManager.TryGetComponent(PlayerManager.LocalPlayer?.ControlledEntity, out TransformComponent? xform))
|
||||
if (EntityManager.TryGetComponent(PlayerManager.LocalEntity, out TransformComponent? xform))
|
||||
{
|
||||
map = xform.MapID;
|
||||
}
|
||||
@@ -512,7 +512,7 @@ namespace Robust.Client.Placement
|
||||
|
||||
private bool CurrentEraserMouseCoordinates(out EntityCoordinates coordinates)
|
||||
{
|
||||
var ent = PlayerManager.LocalPlayer?.ControlledEntity ?? EntityUid.Invalid;
|
||||
var ent = PlayerManager.LocalEntity ?? EntityUid.Invalid;
|
||||
if (ent == EntityUid.Invalid)
|
||||
{
|
||||
coordinates = new EntityCoordinates();
|
||||
@@ -640,7 +640,7 @@ namespace Robust.Client.Placement
|
||||
|
||||
if (CurrentPermission is not {Range: > 0} ||
|
||||
!CurrentMode.RangeRequired ||
|
||||
PlayerManager.LocalPlayer?.ControlledEntity is not {Valid: true} controlled)
|
||||
PlayerManager.LocalEntity is not {Valid: true} controlled)
|
||||
return;
|
||||
|
||||
var worldPos = EntityManager.GetComponent<TransformComponent>(controlled).WorldPosition;
|
||||
|
||||
@@ -216,7 +216,7 @@ namespace Robust.Client.Placement
|
||||
{
|
||||
if (!RangeRequired)
|
||||
return true;
|
||||
var controlled = pManager.PlayerManager.LocalPlayer?.ControlledEntity ?? EntityUid.Invalid;
|
||||
var controlled = pManager.PlayerManager.LocalEntity ?? EntityUid.Invalid;
|
||||
if (controlled == EntityUid.Invalid)
|
||||
{
|
||||
return false;
|
||||
|
||||
@@ -10,14 +10,13 @@ namespace Robust.Client.Player
|
||||
|
||||
public override Filter FromEntities(Filter filter, params EntityUid[] entities)
|
||||
{
|
||||
if (_playerManager.LocalPlayer is not { } localPlayer
|
||||
|| localPlayer.Session.AttachedEntity is not {Valid: true} attachedUid)
|
||||
if (_playerManager.LocalEntity is not {Valid: true} attachedUid)
|
||||
return filter;
|
||||
|
||||
foreach (var uid in entities)
|
||||
{
|
||||
if (uid == attachedUid)
|
||||
filter.AddPlayer(localPlayer.Session);
|
||||
filter.AddPlayer(_playerManager.LocalSession!);
|
||||
}
|
||||
|
||||
return filter;
|
||||
|
||||
@@ -36,12 +36,12 @@ internal sealed class ReplayRecordingManager : SharedReplayRecordingManager
|
||||
|
||||
private void OnRecordingStarted(MappingDataNode metadata, List<object> messages)
|
||||
{
|
||||
if (_player.LocalPlayer == null)
|
||||
if (_player.LocalSession == null)
|
||||
return;
|
||||
|
||||
// Add information about the user doing the recording. This is used to set the default replay observer position
|
||||
// when playing back the replay.
|
||||
var guid = _player.LocalPlayer.UserId.UserId.ToString();
|
||||
var guid = _player.LocalUser.ToString();
|
||||
metadata[ReplayConstants.MetaKeyRecordedBy] = new ValueDataNode(guid);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,33 +5,33 @@
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<NoWarn>NU1701</NoWarn>
|
||||
<NoWarn>NU1701;CA1416</NoWarn>
|
||||
<OutputPath>../bin/Client</OutputPath>
|
||||
<RobustILLink>true</RobustILLink>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="DiscordRichPresence" Version="1.0.175" PrivateAssets="compile" />
|
||||
<PackageReference Include="JetBrains.Annotations" Version="2021.3.0" PrivateAssets="All" />
|
||||
<PackageReference Include="Microsoft.Data.Sqlite.Core" Version="6.0.9" PrivateAssets="compile" />
|
||||
<PackageReference Include="SQLitePCLRaw.provider.sqlite3" Version="2.1.2" Condition="'$(UseSystemSqlite)' == 'True'" PrivateAssets="compile" />
|
||||
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="2.1.2" Condition="'$(UseSystemSqlite)' != 'True'" PrivateAssets="compile" />
|
||||
<PackageReference Include="SpaceWizards.NFluidsynth" Version="0.1.1" PrivateAssets="compile" />
|
||||
<PackageReference Include="SixLabors.ImageSharp" Version="2.1.3" />
|
||||
<PackageReference Include="OpenToolkit.Graphics" Version="4.0.0-pre9.1" PrivateAssets="compile" />
|
||||
<PackageReference Include="OpenTK.OpenAL" Version="4.7.5" PrivateAssets="compile" />
|
||||
<PackageReference Include="SpaceWizards.SharpFont" Version="1.0.1" PrivateAssets="compile" />
|
||||
<PackageReference Include="Robust.Natives" Version="0.1.1" />
|
||||
<PackageReference Include="System.Numerics.Vectors" Version="4.4.0" />
|
||||
<PackageReference Include="TerraFX.Interop.Windows" Version="10.0.20348-rc2" PrivateAssets="compile" />
|
||||
<PackageReference Condition="'$(FullRelease)' != 'True'" Include="JetBrains.Profiler.Api" Version="1.2.0" PrivateAssets="compile" />
|
||||
<PackageReference Include="SpaceWizards.Sodium" Version="0.2.1" PrivateAssets="compile" />
|
||||
<PackageReference Include="Microsoft.NET.ILLink.Tasks" Version="8.0.0" />
|
||||
<PackageReference Include="TerraFX.Interop.Xlib" Version="6.4.0" />
|
||||
<PackageReference Include="DiscordRichPresence" PrivateAssets="compile" />
|
||||
<PackageReference Include="JetBrains.Annotations" PrivateAssets="All" />
|
||||
<PackageReference Include="Microsoft.Data.Sqlite.Core" PrivateAssets="compile" />
|
||||
<PackageReference Include="SQLitePCLRaw.provider.sqlite3" Condition="'$(UseSystemSqlite)' == 'True'" PrivateAssets="compile" />
|
||||
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Condition="'$(UseSystemSqlite)' != 'True'" PrivateAssets="compile" />
|
||||
<PackageReference Include="SpaceWizards.NFluidsynth" PrivateAssets="compile" />
|
||||
<PackageReference Include="SixLabors.ImageSharp" />
|
||||
<PackageReference Include="OpenToolkit.Graphics" PrivateAssets="compile" />
|
||||
<PackageReference Include="OpenTK.OpenAL" PrivateAssets="compile" />
|
||||
<PackageReference Include="SpaceWizards.SharpFont" PrivateAssets="compile" />
|
||||
<PackageReference Include="Robust.Natives" />
|
||||
<PackageReference Include="System.Numerics.Vectors" />
|
||||
<PackageReference Include="TerraFX.Interop.Windows" PrivateAssets="compile" />
|
||||
<PackageReference Condition="'$(FullRelease)' != 'True'" Include="JetBrains.Profiler.Api" PrivateAssets="compile" />
|
||||
<PackageReference Include="SpaceWizards.Sodium" PrivateAssets="compile" />
|
||||
<PackageReference Include="Microsoft.NET.ILLink.Tasks" />
|
||||
<PackageReference Include="TerraFX.Interop.Xlib" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(EnableClientScripting)' == 'True'">
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Features" Version="4.0.1" PrivateAssets="compile" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="4.0.1" PrivateAssets="compile" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.0.1" PrivateAssets="compile" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Features" PrivateAssets="compile" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" PrivateAssets="compile" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" PrivateAssets="compile" />
|
||||
|
||||
<ProjectReference Include="..\Robust.Shared.Scripting\Robust.Shared.Scripting.csproj" />
|
||||
</ItemGroup>
|
||||
@@ -40,7 +40,6 @@
|
||||
<ProjectReference Include="..\Lidgren.Network\Lidgren.Network.csproj" />
|
||||
<ProjectReference Include="..\OpenToolkit.GraphicsLibraryFramework\OpenToolkit.GraphicsLibraryFramework.csproj" />
|
||||
<ProjectReference Include="..\Robust.LoaderApi\Robust.LoaderApi\Robust.LoaderApi.csproj" />
|
||||
<ProjectReference Include="..\Robust.Physics\Robust.Physics.csproj" />
|
||||
<ProjectReference Include="..\Robust.Shared.Maths\Robust.Shared.Maths.csproj" />
|
||||
<ProjectReference Include="..\Robust.Shared\Robust.Shared.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -11,15 +11,17 @@ namespace Robust.Client.Upload.Commands;
|
||||
|
||||
public sealed class UploadFileCommand : IConsoleCommand
|
||||
{
|
||||
[Dependency] private readonly IConfigurationManager _cfgManager = default!;
|
||||
[Dependency] private readonly IFileDialogManager _dialog = default!;
|
||||
[Dependency] private readonly INetManager _netManager = default!;
|
||||
|
||||
public string Command => "uploadfile";
|
||||
public string Description => "Uploads a resource to the server.";
|
||||
public string Help => $"{Command} [relative path for the resource]";
|
||||
|
||||
public async void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var cfgMan = IoCManager.Resolve<IConfigurationManager>();
|
||||
|
||||
if (!cfgMan.GetCVar(CVars.ResourceUploadingEnabled))
|
||||
if (!_cfgManager.GetCVar(CVars.ResourceUploadingEnabled))
|
||||
{
|
||||
shell.WriteError("Network Resource Uploading is currently disabled by the server.");
|
||||
return;
|
||||
@@ -33,10 +35,8 @@ public sealed class UploadFileCommand : IConsoleCommand
|
||||
|
||||
var path = new ResPath(args[0]).ToRelativePath();
|
||||
|
||||
var dialog = IoCManager.Resolve<IFileDialogManager>();
|
||||
|
||||
var filters = new FileDialogFilters(new FileDialogFilters.Group(path.Extension));
|
||||
await using var file = await dialog.OpenFile(filters);
|
||||
await using var file = await _dialog.OpenFile(filters);
|
||||
|
||||
if (file == null)
|
||||
{
|
||||
@@ -44,7 +44,7 @@ public sealed class UploadFileCommand : IConsoleCommand
|
||||
return;
|
||||
}
|
||||
|
||||
var sizeLimit = cfgMan.GetCVar(CVars.ResourceUploadingLimitMb);
|
||||
var sizeLimit = _cfgManager.GetCVar(CVars.ResourceUploadingLimitMb);
|
||||
|
||||
if (sizeLimit > 0f && file.Length * SharedNetworkResourceManager.BytesToMegabytes > sizeLimit)
|
||||
{
|
||||
@@ -54,12 +54,12 @@ public sealed class UploadFileCommand : IConsoleCommand
|
||||
|
||||
var data = file.CopyToArray();
|
||||
|
||||
var netManager = IoCManager.Resolve<INetManager>();
|
||||
var msg = netManager.CreateNetMessage<NetworkResourceUploadMessage>();
|
||||
var msg = new NetworkResourceUploadMessage
|
||||
{
|
||||
RelativePath = path,
|
||||
Data = data
|
||||
};
|
||||
|
||||
msg.RelativePath = path;
|
||||
msg.Data = data;
|
||||
|
||||
netManager.ClientSendMessage(msg);
|
||||
_netManager.ClientSendMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using Robust.Shared;
|
||||
using Robust.Shared.Configuration;
|
||||
@@ -13,21 +14,20 @@ namespace Robust.Client.Upload.Commands;
|
||||
|
||||
public sealed class UploadFolderCommand : IConsoleCommand
|
||||
{
|
||||
[Dependency] private IResourceManager _resourceManager = default!;
|
||||
[Dependency] private IConfigurationManager _configManager = default!;
|
||||
[Dependency] private INetManager _netMan = default!;
|
||||
|
||||
public string Command => "uploadfolder";
|
||||
public string Description => Loc.GetString("uploadfolder-command-description");
|
||||
public string Help => Loc.GetString("uploadfolder-command-help");
|
||||
|
||||
private static readonly ResPath BaseUploadFolderPath = new("/UploadFolder");
|
||||
|
||||
[Dependency] private IResourceManager _resourceManager = default!;
|
||||
[Dependency] private IConfigurationManager _configManager = default!;
|
||||
[Dependency] private INetManager _netMan = default!;
|
||||
|
||||
public async void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var fileCount = 0;
|
||||
|
||||
|
||||
if (!_configManager.GetCVar(CVars.ResourceUploadingEnabled))
|
||||
{
|
||||
shell.WriteError( Loc.GetString("uploadfolder-command-resource-upload-disabled"));
|
||||
@@ -52,8 +52,7 @@ public sealed class UploadFolderCommand : IConsoleCommand
|
||||
//Grab all files in specified folder and upload them
|
||||
foreach (var filepath in _resourceManager.UserData.Find($"{folderPath.ToRelativePath()}/").files )
|
||||
{
|
||||
|
||||
await using var filestream = _resourceManager.UserData.Open(filepath,FileMode.Open);
|
||||
await using var filestream = _resourceManager.UserData.Open(filepath, FileMode.Open);
|
||||
{
|
||||
var sizeLimit = _configManager.GetCVar(CVars.ResourceUploadingLimitMb);
|
||||
if (sizeLimit > 0f && filestream.Length * SharedNetworkResourceManager.BytesToMegabytes > sizeLimit)
|
||||
@@ -64,9 +63,11 @@ public sealed class UploadFolderCommand : IConsoleCommand
|
||||
|
||||
var data = filestream.CopyToArray();
|
||||
|
||||
var msg = _netMan.CreateNetMessage<NetworkResourceUploadMessage>();
|
||||
msg.RelativePath = filepath.RelativeTo(BaseUploadFolderPath);
|
||||
msg.Data = data;
|
||||
var msg = new NetworkResourceUploadMessage
|
||||
{
|
||||
RelativePath = filepath.RelativeTo(BaseUploadFolderPath),
|
||||
Data = data
|
||||
};
|
||||
|
||||
_netMan.ClientSendMessage(msg);
|
||||
fileCount++;
|
||||
|
||||
@@ -226,6 +226,10 @@ namespace Robust.Client.UserInterface
|
||||
/// <seealso cref="Rect"/>
|
||||
public UIBox2i PixelRect => UIBox2i.FromDimensions(PixelPosition, PixelSize);
|
||||
|
||||
public UIBox2 GlobalRect => UIBox2.FromDimensions(GlobalPosition, _size);
|
||||
|
||||
public UIBox2i GlobalPixelRect => UIBox2i.FromDimensions(GlobalPixelPosition, PixelSize);
|
||||
|
||||
/// <summary>
|
||||
/// Horizontal alignment mode.
|
||||
/// This determines how the control should be laid out horizontally
|
||||
@@ -464,6 +468,14 @@ namespace Robust.Client.UserInterface
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the screen coordinates position relative to the control.
|
||||
/// </summary>
|
||||
public Vector2 GetLocalPosition(ScreenCoordinates coordinates)
|
||||
{
|
||||
return coordinates.Position - GlobalPixelPosition;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Notify the layout system that this control's <see cref="Measure"/> result may have changed
|
||||
/// and must be recalculated.
|
||||
|
||||
@@ -545,6 +545,36 @@ namespace Robust.Client.UserInterface
|
||||
Draw(renderHandle.DrawingHandleScreen);
|
||||
}
|
||||
|
||||
protected internal virtual void PreRenderChildren(ref ControlRenderArguments args)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected internal virtual void PostRenderChildren(ref ControlRenderArguments args)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected internal virtual void RenderChildOverride(ref ControlRenderArguments args, int childIndex, Vector2i position)
|
||||
{
|
||||
RenderControl(ref args, childIndex, position);
|
||||
}
|
||||
|
||||
public ref struct ControlRenderArguments
|
||||
{
|
||||
public IRenderHandle Handle;
|
||||
public ref int Total;
|
||||
public Vector2i Position;
|
||||
public Color Modulate;
|
||||
public UIBox2i? ScissorBox;
|
||||
public ref Matrix3 CoordinateTransform;
|
||||
}
|
||||
|
||||
protected void RenderControl(ref ControlRenderArguments args, int childIndex, Vector2i position)
|
||||
{
|
||||
UserInterfaceManagerInternal.RenderControl(args.Handle, ref args.Total, GetChild(childIndex), position, args.Modulate, args.ScissorBox, args.CoordinateTransform);
|
||||
}
|
||||
|
||||
public void UpdateDraw()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Robust.Client.Audio;
|
||||
using Robust.Client.ResourceManagement;
|
||||
using Robust.Shared.ContentPack;
|
||||
@@ -37,8 +38,10 @@ namespace Robust.Client.UserInterface.Controls
|
||||
get => _group;
|
||||
set
|
||||
{
|
||||
if (value?.InternalButtons.Contains(this) ?? false)
|
||||
return; // No work to do.
|
||||
// Remove from old group.
|
||||
_group?.Buttons.Remove(this);
|
||||
_group?.InternalButtons.Remove(this);
|
||||
|
||||
_group = value;
|
||||
|
||||
@@ -47,11 +50,12 @@ namespace Robust.Client.UserInterface.Controls
|
||||
return;
|
||||
}
|
||||
|
||||
value.Buttons.Add(this);
|
||||
value.InternalButtons.Add(this);
|
||||
ToggleMode = true;
|
||||
|
||||
// Set us to pressed if we're the first button.
|
||||
Pressed = value.Buttons.Count == 0;
|
||||
// Set us to pressed if we're the first button. Doesn't go through the setter to avoid setting off our own error check.
|
||||
_pressed = value.InternalButtons.Count == 1;
|
||||
DrawModeChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -326,7 +330,7 @@ namespace Robust.Client.UserInterface.Controls
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var button in _group.Buttons)
|
||||
foreach (var button in _group.InternalButtons)
|
||||
{
|
||||
if (button != this && button.Pressed)
|
||||
{
|
||||
@@ -440,6 +444,9 @@ namespace Robust.Client.UserInterface.Controls
|
||||
/// </remarks>
|
||||
public sealed class ButtonGroup
|
||||
{
|
||||
internal readonly List<BaseButton> Buttons = new();
|
||||
internal readonly List<BaseButton> InternalButtons = new();
|
||||
public IReadOnlyList<BaseButton> Buttons => InternalButtons;
|
||||
|
||||
public BaseButton? Pressed => InternalButtons.FirstOrDefault(x => x.Pressed);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.Contracts;
|
||||
@@ -9,6 +9,9 @@ using Robust.Shared.Input;
|
||||
using Robust.Shared.Maths;
|
||||
using Timer = Robust.Shared.Timing.Timer;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a scrollable list of items in a user interface.
|
||||
/// </summary>
|
||||
namespace Robust.Client.UserInterface.Controls
|
||||
{
|
||||
[Virtual]
|
||||
@@ -29,6 +32,10 @@ namespace Robust.Client.UserInterface.Controls
|
||||
public const string StylePropertySelectedItemBackground = "selected-item-background";
|
||||
public const string StylePropertyDisabledItemBackground = "disabled-item-background";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the ItemSeparation of individual list items
|
||||
/// </summary>
|
||||
public int ItemSeparation { get; set; } = 0; // Default value is 0px
|
||||
public int Count => _itemList.Count;
|
||||
public bool IsReadOnly => false;
|
||||
|
||||
@@ -68,8 +75,10 @@ namespace Robust.Client.UserInterface.Controls
|
||||
itemHeight += ActualItemBackground.MinimumSize.Y * UIScale;
|
||||
|
||||
_totalContentHeight += (int)Math.Ceiling(itemHeight);
|
||||
_totalContentHeight += ItemSeparation;
|
||||
}
|
||||
|
||||
//Remove unneeded ItemSeparation on last item.
|
||||
_totalContentHeight -= ItemSeparation;
|
||||
_scrollBar.MaxValue = Math.Max(_scrollBar.Page, _totalContentHeight);
|
||||
_updateScrollbarVisibility();
|
||||
}
|
||||
@@ -390,6 +399,9 @@ namespace Robust.Client.UserInterface.Controls
|
||||
}
|
||||
|
||||
offset += itemHeight;
|
||||
|
||||
// Add a ItemSeparation at the bottom of each item.
|
||||
offset += ItemSeparation;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -399,7 +411,7 @@ namespace Robust.Client.UserInterface.Controls
|
||||
|
||||
var color = ActualFontColor;
|
||||
var offsetY = (int) (box.Height - font.GetHeight(UIScale)) / 2;
|
||||
var baseLine = new Vector2i(0, offsetY + font.GetAscent(UIScale)) + box.TopLeft;
|
||||
var baseLine = new Vector2i(5, offsetY + font.GetAscent(UIScale)) + box.TopLeft;
|
||||
|
||||
foreach (var rune in text.EnumerateRunes())
|
||||
{
|
||||
|
||||
@@ -12,6 +12,7 @@ namespace Robust.Client.UserInterface.Controls
|
||||
public class OptionButton : ContainerButton
|
||||
{
|
||||
public const string StyleClassOptionButton = "optionButton";
|
||||
public const string StyleClassPopup = "optionButtonPopup";
|
||||
public const string StyleClassOptionTriangle = "optionTriangle";
|
||||
public readonly ScrollContainer OptionsScroll;
|
||||
|
||||
@@ -74,7 +75,8 @@ namespace Robust.Client.UserInterface.Controls
|
||||
|
||||
_popup = new Popup()
|
||||
{
|
||||
Children = { OptionsScroll }
|
||||
Children = { new PanelContainer(), OptionsScroll },
|
||||
StyleClasses = { StyleClassPopup }
|
||||
};
|
||||
_popup.OnPopupHide += OnPopupHide;
|
||||
|
||||
@@ -99,6 +101,11 @@ namespace Robust.Client.UserInterface.Controls
|
||||
AddItem(label, id);
|
||||
}
|
||||
|
||||
public virtual void ButtonOverride(Button button)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void AddItem(string label, int? id = null)
|
||||
{
|
||||
if (id == null)
|
||||
@@ -132,6 +139,8 @@ namespace Robust.Client.UserInterface.Controls
|
||||
{
|
||||
Select(0);
|
||||
}
|
||||
|
||||
ButtonOverride(button);
|
||||
}
|
||||
|
||||
private void TogglePopup(bool show)
|
||||
@@ -139,6 +148,8 @@ namespace Robust.Client.UserInterface.Controls
|
||||
if (show)
|
||||
{
|
||||
var globalPos = GlobalPosition;
|
||||
globalPos.Y += Size.Y + 1; // Place it below us, with a safety margin.
|
||||
globalPos.Y -= Margin.SumVertical;
|
||||
OptionsScroll.Measure(Window?.Size ?? Vector2Helpers.Infinity);
|
||||
var (minX, minY) = OptionsScroll.DesiredSize;
|
||||
var box = UIBox2.FromDimensions(globalPos, new Vector2(Math.Max(minX, Width), minY));
|
||||
|
||||
@@ -15,13 +15,13 @@ namespace Robust.Client.UserInterface.Controls
|
||||
{
|
||||
base.Draw(handle);
|
||||
|
||||
var style = _getStyleBox();
|
||||
var style = GetStyleBox();
|
||||
style?.Draw(handle, PixelSizeBox, UIScale);
|
||||
}
|
||||
|
||||
protected override Vector2 MeasureOverride(Vector2 availableSize)
|
||||
{
|
||||
var styleSize = _getStyleBox()?.MinimumSize ?? Vector2.Zero;
|
||||
var styleSize = GetStyleBox()?.MinimumSize ?? Vector2.Zero;
|
||||
var measureSize = Vector2.Max(availableSize - styleSize, Vector2.Zero);
|
||||
var childSize = Vector2.Zero;
|
||||
foreach (var child in Children)
|
||||
@@ -36,7 +36,7 @@ namespace Robust.Client.UserInterface.Controls
|
||||
protected override Vector2 ArrangeOverride(Vector2 finalSize)
|
||||
{
|
||||
var ourSize = UIBox2.FromDimensions(Vector2.Zero, finalSize);
|
||||
var contentBox = _getStyleBox()?.GetContentBox(ourSize, 1) ?? ourSize;
|
||||
var contentBox = GetStyleBox()?.GetContentBox(ourSize, 1) ?? ourSize;
|
||||
|
||||
foreach (var child in Children)
|
||||
{
|
||||
@@ -47,7 +47,7 @@ namespace Robust.Client.UserInterface.Controls
|
||||
}
|
||||
|
||||
[System.Diagnostics.Contracts.Pure]
|
||||
private StyleBox? _getStyleBox()
|
||||
protected StyleBox? GetStyleBox()
|
||||
{
|
||||
if (PanelOverride != null)
|
||||
{
|
||||
|
||||
@@ -90,6 +90,8 @@ public sealed class TextEdit : Control
|
||||
internal bool DebugOverlay;
|
||||
private Vector2? _lastDebugMousePos;
|
||||
|
||||
public event Action<TextEditEventArgs>? OnTextChanged;
|
||||
|
||||
public TextEdit()
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
@@ -315,7 +317,7 @@ public sealed class TextEdit : Control
|
||||
if (changed)
|
||||
{
|
||||
_selectionStart = _cursorPosition;
|
||||
// OnTextChanged?.Invoke(new LineEditEventArgs(this, _text));
|
||||
OnTextChanged?.Invoke(new TextEditEventArgs(this, _textRope));
|
||||
// _updatePseudoClass();
|
||||
// OnBackspace?.Invoke(new LineEditBackspaceEventArgs(oldText, _text, cursor, selectStart));
|
||||
}
|
||||
@@ -349,7 +351,7 @@ public sealed class TextEdit : Control
|
||||
if (changed)
|
||||
{
|
||||
_selectionStart = _cursorPosition;
|
||||
// OnTextChanged?.Invoke(new LineEditEventArgs(this, _text));
|
||||
OnTextChanged?.Invoke(new TextEditEventArgs(this, _textRope));
|
||||
// _updatePseudoClass();
|
||||
}
|
||||
|
||||
@@ -382,7 +384,10 @@ public sealed class TextEdit : Control
|
||||
}
|
||||
|
||||
if (changed)
|
||||
{
|
||||
_selectionStart = _cursorPosition;
|
||||
OnTextChanged?.Invoke(new TextEditEventArgs(this, _textRope));
|
||||
}
|
||||
|
||||
InvalidateHorizontalCursorPos();
|
||||
args.Handle();
|
||||
@@ -411,7 +416,10 @@ public sealed class TextEdit : Control
|
||||
}
|
||||
|
||||
if (changed)
|
||||
{
|
||||
_selectionStart = _cursorPosition;
|
||||
OnTextChanged?.Invoke(new TextEditEventArgs(this, _textRope));
|
||||
}
|
||||
|
||||
InvalidateHorizontalCursorPos();
|
||||
args.Handle();
|
||||
@@ -748,6 +756,7 @@ public sealed class TextEdit : Control
|
||||
|
||||
var startPos = _cursorPosition;
|
||||
TextRope = Rope.Insert(TextRope, startPos.Index, ev.Text);
|
||||
OnTextChanged?.Invoke(new TextEditEventArgs(this, _textRope));
|
||||
|
||||
_selectionStart = _cursorPosition = new CursorPos(startPos.Index + startChars, LineBreakBias.Top);
|
||||
_imeData = (startPos, ev.Text.Length);
|
||||
@@ -844,6 +853,7 @@ public sealed class TextEdit : Control
|
||||
var upper = SelectionUpper.Index;
|
||||
|
||||
TextRope = Rope.ReplaceSubstring(TextRope, lower, upper - lower, text);
|
||||
OnTextChanged?.Invoke(new TextEditEventArgs(this, _textRope));
|
||||
|
||||
_selectionStart = _cursorPosition = new CursorPos(lower + text.Length, LineBreakBias.Top);
|
||||
// OnTextChanged?.Invoke(new LineEditEventArgs(this, _text));
|
||||
@@ -1441,6 +1451,12 @@ public sealed class TextEdit : Control
|
||||
AbortIme(delete: false);
|
||||
}
|
||||
|
||||
public sealed class TextEditEventArgs(TextEdit control, Rope.Node textRope) : EventArgs
|
||||
{
|
||||
public TextEdit Control { get; } = control;
|
||||
public Rope.Node TextRope { get; } = textRope;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specifies which line the cursor is positioned at when on a word-wrapping break.
|
||||
/// </summary>
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace Robust.Client.UserInterface.CustomControls
|
||||
// And also if Update() stops firing due to an exception loop the console will still work.
|
||||
// (At least from the main thread, which is what's throwing the exceptions..)
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class DebugConsole : Control, IDebugConsoleView, IPostInjectInit
|
||||
public sealed partial class DebugConsole : Control, IDebugConsoleView
|
||||
{
|
||||
[Dependency] private readonly IClientConsoleHost _consoleHost = default!;
|
||||
[Dependency] private readonly IResourceManager _resourceManager = default!;
|
||||
@@ -49,7 +49,7 @@ namespace Robust.Client.UserInterface.CustomControls
|
||||
private static readonly ResPath HistoryPath = new("/debug_console_history.json");
|
||||
|
||||
private readonly ConcurrentQueue<FormattedMessage> _messageQueue = new();
|
||||
private ISawmill _logger = default!;
|
||||
private readonly ISawmill _logger;
|
||||
|
||||
public DebugConsole()
|
||||
{
|
||||
@@ -57,6 +57,8 @@ namespace Robust.Client.UserInterface.CustomControls
|
||||
|
||||
IoCManager.InjectDependencies(this);
|
||||
|
||||
_logger = _logMan.GetSawmill("dbgconsole");
|
||||
|
||||
InitCompletions();
|
||||
|
||||
CommandBar.OnTextChanged += OnCommandChanged;
|
||||
@@ -282,10 +284,5 @@ namespace Robust.Client.UserInterface.CustomControls
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void IPostInjectInit.PostInject()
|
||||
{
|
||||
_logger = _logMan.GetSawmill("dbgconsole");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,6 +61,9 @@ namespace Robust.Client.UserInterface
|
||||
Vector2? CalcRelativeMousePositionFor(Control control, ScreenCoordinates mousePos);
|
||||
|
||||
Color GetMainClearColor();
|
||||
|
||||
void RenderControl(IRenderHandle renderHandle, ref int total, Control control, Vector2i position, Color modulate,
|
||||
UIBox2i? scissorBox, Matrix3 coordinateTransform);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -132,9 +132,10 @@ internal sealed partial class UserInterfaceManager
|
||||
try
|
||||
{
|
||||
var total = 0;
|
||||
_render(renderHandle, ref total, root, Vector2i.Zero, Color.White, null);
|
||||
var drawingHandle = renderHandle.DrawingHandleScreen;
|
||||
drawingHandle.SetTransform(Vector2.Zero, Angle.Zero, Vector2.One);
|
||||
drawingHandle.SetTransform(Matrix3.Identity);
|
||||
RenderControl(renderHandle, ref total, root, Vector2i.Zero, Color.White, null, Matrix3.Identity);
|
||||
drawingHandle.SetTransform(Matrix3.Identity);
|
||||
OnPostDrawUIRoot?.Invoke(new PostDrawUIRootEventArgs(root, drawingHandle));
|
||||
|
||||
_prof.WriteValue("Controls rendered", ProfData.Int32(total));
|
||||
|
||||
@@ -75,7 +75,7 @@ namespace Robust.Client.UserInterface
|
||||
|
||||
foreach (var root in _roots)
|
||||
{
|
||||
if (root.Stylesheet != null)
|
||||
if (root.Stylesheet == null)
|
||||
{
|
||||
root.StylesheetUpdateRecursive();
|
||||
}
|
||||
@@ -329,8 +329,8 @@ namespace Robust.Client.UserInterface
|
||||
}
|
||||
}
|
||||
|
||||
private void _render(IRenderHandle renderHandle, ref int total, Control control, Vector2i position, Color modulate,
|
||||
UIBox2i? scissorBox)
|
||||
public void RenderControl(IRenderHandle renderHandle, ref int total, Control control, Vector2i position, Color modulate,
|
||||
UIBox2i? scissorBox, Matrix3 coordinateTransform)
|
||||
{
|
||||
if (!control.Visible)
|
||||
{
|
||||
@@ -377,7 +377,10 @@ namespace Robust.Client.UserInterface
|
||||
total += 1;
|
||||
|
||||
var handle = renderHandle.DrawingHandleScreen;
|
||||
handle.SetTransform(position, Angle.Zero, Vector2.One);
|
||||
var oldXform = handle.GetTransform();
|
||||
var xform = oldXform;
|
||||
xform.Multiply(Matrix3.CreateTransform(position, Angle.Zero, Vector2.One));
|
||||
handle.SetTransform(xform);
|
||||
modulate *= control.Modulate;
|
||||
|
||||
if (_rendering || control.AlwaysRender)
|
||||
@@ -389,16 +392,32 @@ namespace Robust.Client.UserInterface
|
||||
handle.Modulate = oldMod;
|
||||
handle.UseShader(null);
|
||||
}
|
||||
handle.SetTransform(oldXform);
|
||||
var args = new Control.ControlRenderArguments()
|
||||
{
|
||||
Handle = renderHandle,
|
||||
Total = ref total,
|
||||
Modulate = modulate,
|
||||
ScissorBox = scissorRegion,
|
||||
CoordinateTransform = ref coordinateTransform
|
||||
};
|
||||
|
||||
control.PreRenderChildren(ref args);
|
||||
|
||||
foreach (var child in control.Children)
|
||||
{
|
||||
_render(renderHandle, ref total, child, position + child.PixelPosition, modulate, scissorRegion);
|
||||
var pos = position + (Vector2i) coordinateTransform.Transform(child.PixelPosition);
|
||||
control.RenderChildOverride(ref args, child.GetPositionInParent(), pos);
|
||||
}
|
||||
|
||||
control.PostRenderChildren(ref args);
|
||||
|
||||
if (clip)
|
||||
{
|
||||
renderHandle.SetScissor(scissorBox);
|
||||
}
|
||||
|
||||
handle.SetTransform(oldXform);
|
||||
}
|
||||
|
||||
public Color GetMainClearColor() => RootControl.ActualBgColor;
|
||||
|
||||
@@ -4,6 +4,7 @@ using Robust.Shared.Resources;
|
||||
using Robust.Shared.Utility;
|
||||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.Formats.Png;
|
||||
using SixLabors.ImageSharp.Formats.Png.Chunks;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
|
||||
namespace Robust.Packaging.AssetProcessing.Passes;
|
||||
@@ -168,7 +169,7 @@ internal sealed class AssetPassPackRsis : AssetPass
|
||||
}
|
||||
|
||||
var ms = new MemoryStream();
|
||||
sheet.Metadata.GetPngMetadata().TextData.Add(new PngTextData("Description", metaJson, null, null));
|
||||
sheet.Metadata.GetPngMetadata().TextData.Add(new PngTextData("Description", metaJson, "", ""));
|
||||
sheet.SaveAsPng(ms);
|
||||
|
||||
sheet.Dispose();
|
||||
|
||||
@@ -10,9 +10,5 @@
|
||||
<ProjectReference Include="..\Robust.Shared\Robust.Shared.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="NVorbis" Version="0.10.5" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="..\MSBuild\Robust.Properties.targets" />
|
||||
</Project>
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="..\MSBuild\Robust.Engine.props" />
|
||||
<PropertyGroup>
|
||||
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DefineConstants>TRACE;RELEASE</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Robust.Shared.Maths\Robust.Shared.Maths.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="..\MSBuild\Robust.Properties.targets" />
|
||||
</Project>
|
||||
@@ -4,12 +4,13 @@
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<LangVersion>11</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.Common" Version="4.4.0" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.4.0" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.Common" Version="4.4.0" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.Common" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.Common" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -259,6 +259,9 @@ namespace Robust.Server.Console
|
||||
}
|
||||
|
||||
done:
|
||||
|
||||
result ??= CompletionResult.Empty;
|
||||
|
||||
var msg = new MsgConCompletionResp
|
||||
{
|
||||
Result = result,
|
||||
|
||||
@@ -19,13 +19,15 @@ internal sealed partial class MetricsManager
|
||||
{
|
||||
private readonly ISawmill _sawmill;
|
||||
private readonly HttpListener _listener;
|
||||
private readonly CollectorRegistry _registry;
|
||||
|
||||
public ManagedHttpListenerMetricsServer(ISawmill sawmill, string host, int port, string url = "metrics/",
|
||||
CollectorRegistry? registry = null) : base(registry)
|
||||
CollectorRegistry? registry = null)
|
||||
{
|
||||
_sawmill = sawmill;
|
||||
_listener = new HttpListener();
|
||||
_listener.Prefixes.Add($"http://{host}:{port}/{url}");
|
||||
_registry = registry ?? Metrics.DefaultRegistry;
|
||||
}
|
||||
|
||||
protected override Task StartServer(CancellationToken cancel)
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace Robust.Server.GameObjects
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<MapGridComponent, EmptyGridEvent>(HandleGridEmpty);
|
||||
|
||||
_cfg.OnValueChanged(CVars.GameDeleteEmptyGrids, SetGridDeletion, true);
|
||||
Subs.CVar(_cfg, CVars.GameDeleteEmptyGrids, SetGridDeletion, true);
|
||||
}
|
||||
|
||||
protected override void OnMapAdd(EntityUid uid, MapComponent component, ComponentAdd args)
|
||||
@@ -64,13 +64,6 @@ namespace Robust.Server.GameObjects
|
||||
return !(grid.GetAllTiles().Any());
|
||||
}
|
||||
|
||||
public override void Shutdown()
|
||||
{
|
||||
base.Shutdown();
|
||||
|
||||
_cfg.UnsubValueChanged(CVars.GameDeleteEmptyGrids, SetGridDeletion);
|
||||
}
|
||||
|
||||
private void HandleGridEmpty(EntityUid uid, MapGridComponent component, EmptyGridEvent args)
|
||||
{
|
||||
if (!_deleteEmptyGrids || TerminatingOrDeleted(uid) || HasComp<MapComponent>(uid))
|
||||
|
||||
@@ -20,7 +20,8 @@ namespace Robust.Server.GameObjects
|
||||
{
|
||||
base.Initialize();
|
||||
LoadMetricCVar();
|
||||
_configurationManager.OnValueChanged(CVars.MetricsEnabled, _ => LoadMetricCVar());
|
||||
|
||||
Subs.CVar(_configurationManager, CVars.MetricsEnabled, _ => LoadMetricCVar());
|
||||
}
|
||||
|
||||
private void LoadMetricCVar()
|
||||
|
||||
@@ -193,5 +193,6 @@ internal sealed partial class PvsSystem
|
||||
|
||||
session.PreviouslySent.Clear();
|
||||
session.LastSent = null;
|
||||
session.Entities.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,11 +126,12 @@ internal sealed partial class PvsSystem : EntitySystem
|
||||
_playerManager.PlayerStatusChanged += OnPlayerStatusChanged;
|
||||
_transform.OnGlobalMoveEvent += OnEntityMove;
|
||||
|
||||
_configManager.OnValueChanged(CVars.NetPVS, SetPvs, true);
|
||||
_configManager.OnValueChanged(CVars.NetMaxUpdateRange, OnViewsizeChanged, true);
|
||||
_configManager.OnValueChanged(CVars.NetLowLodRange, OnLodChanged, true);
|
||||
_configManager.OnValueChanged(CVars.NetForceAckThreshold, OnForceAckChanged, true);
|
||||
_configManager.OnValueChanged(CVars.NetPvsAsync, OnAsyncChanged, true);
|
||||
Subs.CVar(_configManager, CVars.NetPVS, SetPvs, true);
|
||||
Subs.CVar(_configManager, CVars.NetMaxUpdateRange, OnViewsizeChanged, true);
|
||||
Subs.CVar(_configManager, CVars.NetLowLodRange, OnLodChanged, true);
|
||||
Subs.CVar(_configManager, CVars.NetForceAckThreshold, OnForceAckChanged, true);
|
||||
Subs.CVar(_configManager, CVars.NetPvsAsync, OnAsyncChanged, true);
|
||||
Subs.CVar(_configManager, CVars.NetPvsCompressLevel, ResetParallelism, true);
|
||||
|
||||
_serverGameStateManager.ClientAck += OnClientAck;
|
||||
_serverGameStateManager.ClientRequestFull += OnClientRequestFull;
|
||||
@@ -138,7 +139,6 @@ internal sealed partial class PvsSystem : EntitySystem
|
||||
InitializeDirty();
|
||||
|
||||
_parallelMgr.ParallelCountChanged += ResetParallelism;
|
||||
_configManager.OnValueChanged(CVars.NetPvsCompressLevel, ResetParallelism, true);
|
||||
}
|
||||
|
||||
public override void Shutdown()
|
||||
@@ -148,10 +148,6 @@ internal sealed partial class PvsSystem : EntitySystem
|
||||
_playerManager.PlayerStatusChanged -= OnPlayerStatusChanged;
|
||||
_transform.OnGlobalMoveEvent -= OnEntityMove;
|
||||
|
||||
_configManager.UnsubValueChanged(CVars.NetPVS, SetPvs);
|
||||
_configManager.UnsubValueChanged(CVars.NetMaxUpdateRange, OnViewsizeChanged);
|
||||
_configManager.UnsubValueChanged(CVars.NetForceAckThreshold, OnForceAckChanged);
|
||||
_configManager.UnsubValueChanged(CVars.NetPvsCompressLevel, ResetParallelism);
|
||||
_parallelMgr.ParallelCountChanged -= ResetParallelism;
|
||||
|
||||
_serverGameStateManager.ClientAck -= OnClientAck;
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace Robust.Server.Log
|
||||
|
||||
if (valid)
|
||||
{
|
||||
message.AddOrUpdateProperty(sawmillProperty);
|
||||
message.AddOrUpdateProperty(sawmillProperty!);
|
||||
}
|
||||
|
||||
_sLogger.Write(message);
|
||||
|
||||
138
Robust.Server/Physics/GridFixtureSystem.Merging.cs
Normal file
138
Robust.Server/Physics/GridFixtureSystem.Merging.cs
Normal file
@@ -0,0 +1,138 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Map.Components;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Robust.Server.Physics;
|
||||
|
||||
public sealed partial class GridFixtureSystem
|
||||
{
|
||||
/*
|
||||
* Something to keep in mind is that they rotate around the origin of a tile (e.g. 0,0), so a rotation of -90 degrees
|
||||
* moves the origin to 0, -1.
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Merges GridB into GridA.
|
||||
/// </summary>
|
||||
/// <param name="offset">Origin of GridB relative to GridA</param>
|
||||
/// <param name="rotation">Rotation to apply to GridB when being merged.
|
||||
/// Note that the rotation is applied before the offset so the offset itself will be rotated.</param>
|
||||
public void Merge(
|
||||
EntityUid gridAUid,
|
||||
EntityUid gridBUid,
|
||||
Vector2i offset,
|
||||
Angle rotation,
|
||||
MapGridComponent? gridA = null,
|
||||
MapGridComponent? gridB = null,
|
||||
TransformComponent? xformA = null,
|
||||
TransformComponent? xformB = null)
|
||||
{
|
||||
var matrix = Matrix3.CreateTransform(offset, rotation);
|
||||
Merge(gridAUid, gridBUid, matrix, gridA, gridB, xformA, xformB);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Merges GridB into GridA.
|
||||
/// </summary>
|
||||
/// <param name="offset">Origin of GridB relative to GridA</param>
|
||||
/// <param name="matrix">Matrix to apply to gridB when being merged.
|
||||
/// Note that rotation is applied first and then offset so the offset itself will be rotated.</param>
|
||||
public void Merge(
|
||||
EntityUid gridAUid,
|
||||
EntityUid gridBUid,
|
||||
Matrix3 matrix,
|
||||
MapGridComponent? gridA = null,
|
||||
MapGridComponent? gridB = null,
|
||||
TransformComponent? xformA = null,
|
||||
TransformComponent? xformB = null)
|
||||
{
|
||||
if (!Resolve(gridAUid, ref gridA, ref xformA))
|
||||
return;
|
||||
|
||||
if (!Resolve(gridBUid, ref gridB, ref xformB))
|
||||
return;
|
||||
|
||||
var sw = new Stopwatch();
|
||||
var tiles = new List<(Vector2i Indices, Tile Tile)>();
|
||||
var enumerator = _maps.GetAllTilesEnumerator(gridBUid, gridB);
|
||||
|
||||
while (enumerator.MoveNext(out var tileRef))
|
||||
{
|
||||
var offsetTile = matrix.Transform(new Vector2(tileRef.Value.GridIndices.X, tileRef.Value.GridIndices.Y) + gridA.TileSizeHalfVector);
|
||||
tiles.Add((offsetTile.Floored(), tileRef.Value.Tile));
|
||||
}
|
||||
|
||||
_maps.SetTiles(gridAUid, gridA, tiles);
|
||||
|
||||
enumerator = _maps.GetAllTilesEnumerator(gridBUid, gridB);
|
||||
var rotationDiff = matrix.Rotation();
|
||||
|
||||
while (enumerator.MoveNext(out var tileRef))
|
||||
{
|
||||
var chunkOrigin = SharedMapSystem.GetChunkIndices(tileRef.Value.GridIndices, gridB.ChunkSize);
|
||||
|
||||
if (!_maps.TryGetChunk(gridBUid, gridB, chunkOrigin, out var chunk))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var chunkLocalTile = SharedMapSystem.GetChunkRelative(tileRef.Value.GridIndices, gridB.ChunkSize);
|
||||
var snapgrid = chunk.GetSnapGrid((ushort) chunkLocalTile.X, (ushort) chunkLocalTile.Y);
|
||||
|
||||
if (snapgrid == null || snapgrid.Count == 0)
|
||||
continue;
|
||||
|
||||
var offsetTile = matrix.Transform(new Vector2(tileRef.Value.GridIndices.X, tileRef.Value.GridIndices.Y) + gridA.TileSizeHalfVector);
|
||||
var tileIndex = offsetTile.Floored();
|
||||
|
||||
for (var j = snapgrid.Count - 1; j >= 0; j--)
|
||||
{
|
||||
var ent = snapgrid[j];
|
||||
var xform = _xformQuery.GetComponent(ent);
|
||||
_xformSystem.ReAnchor(ent, xform,
|
||||
gridB, gridA,
|
||||
tileRef.Value.GridIndices, tileIndex,
|
||||
gridBUid, gridAUid,
|
||||
xformB, xformA,
|
||||
rotationDiff);
|
||||
|
||||
DebugTools.Assert(xform.ParentUid == gridAUid);
|
||||
}
|
||||
|
||||
DebugTools.Assert(snapgrid.Count == 0);
|
||||
}
|
||||
|
||||
enumerator = _maps.GetAllTilesEnumerator(gridBUid, gridB);
|
||||
|
||||
while (enumerator.MoveNext(out var tileRef))
|
||||
{
|
||||
var bounds = _lookup.GetLocalBounds(tileRef.Value.GridIndices, gridB.TileSize);
|
||||
|
||||
_entSet.Clear();
|
||||
_lookup.GetLocalEntitiesIntersecting(gridBUid, bounds, _entSet, LookupFlags.All | ~LookupFlags.Contained | LookupFlags.Approximate);
|
||||
|
||||
foreach (var ent in _entSet)
|
||||
{
|
||||
// Consider centre of entity position maybe?
|
||||
var entXform = _xformQuery.GetComponent(ent);
|
||||
|
||||
if (entXform.ParentUid != gridBUid ||
|
||||
!bounds.Contains(entXform.LocalPosition)) continue;
|
||||
|
||||
var newPos = matrix.Transform(entXform.LocalPosition);
|
||||
|
||||
_xformSystem.SetCoordinates(ent, entXform, new EntityCoordinates(gridAUid, newPos), entXform.LocalRotation + rotationDiff, oldParent: xformB, newParent: xformA);
|
||||
}
|
||||
}
|
||||
|
||||
DebugTools.Assert(xformB.ChildCount == 0);
|
||||
Del(gridBUid);
|
||||
|
||||
Log.Debug($"Merged grids in {sw.Elapsed.TotalMilliseconds}ms");
|
||||
}
|
||||
}
|
||||
@@ -23,16 +23,16 @@ namespace Robust.Server.Physics
|
||||
/// <summary>
|
||||
/// Handles generating fixtures for MapGrids.
|
||||
/// </summary>
|
||||
public sealed class GridFixtureSystem : SharedGridFixtureSystem
|
||||
public sealed partial class GridFixtureSystem : SharedGridFixtureSystem
|
||||
{
|
||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
||||
[Dependency] private readonly IConGroupController _conGroup = default!;
|
||||
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
||||
[Dependency] private readonly SharedMapSystem _maps = default!;
|
||||
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
|
||||
[Dependency] private readonly SharedTransformSystem _xformSystem = default!;
|
||||
|
||||
private ISawmill _logger = default!;
|
||||
private readonly Dictionary<EntityUid, Dictionary<Vector2i, ChunkNodeGroup>> _nodes = new();
|
||||
|
||||
/// <summary>
|
||||
@@ -47,15 +47,24 @@ namespace Robust.Server.Physics
|
||||
|
||||
internal bool SplitAllowed = true;
|
||||
|
||||
private HashSet<EntityUid> _entSet = new();
|
||||
|
||||
private EntityQuery<MapGridComponent> _gridQuery;
|
||||
private EntityQuery<PhysicsComponent> _bodyQuery;
|
||||
private EntityQuery<TransformComponent> _xformQuery;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
_logger = Logger.GetSawmill("gsplit");
|
||||
|
||||
_gridQuery = GetEntityQuery<MapGridComponent>();
|
||||
_bodyQuery = GetEntityQuery<PhysicsComponent>();
|
||||
_xformQuery = GetEntityQuery<TransformComponent>();
|
||||
SubscribeLocalEvent<GridRemovalEvent>(OnGridRemoval);
|
||||
SubscribeNetworkEvent<RequestGridNodesMessage>(OnDebugRequest);
|
||||
SubscribeNetworkEvent<StopGridNodesMessage>(OnDebugStopRequest);
|
||||
|
||||
_cfg.OnValueChanged(CVars.GridSplitting, SetSplitAllowed, true);
|
||||
Subs.CVar(_cfg, CVars.GridSplitting, SetSplitAllowed, true);
|
||||
}
|
||||
|
||||
private void SetSplitAllowed(bool value) => SplitAllowed = value;
|
||||
@@ -64,7 +73,6 @@ namespace Robust.Server.Physics
|
||||
{
|
||||
base.Shutdown();
|
||||
_subscribedSessions.Clear();
|
||||
_cfg.UnsubValueChanged(CVars.GridSplitting, SetSplitAllowed);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -197,7 +205,7 @@ namespace Robust.Server.Physics
|
||||
}
|
||||
|
||||
_isSplitting = true;
|
||||
_logger.Debug($"Started split check for {ToPrettyString(uid)}");
|
||||
Log.Debug($"Started split check for {ToPrettyString(uid)}");
|
||||
var splitFrontier = new Queue<ChunkSplitNode>(4);
|
||||
var grids = new List<HashSet<ChunkSplitNode>>(1);
|
||||
|
||||
@@ -234,7 +242,7 @@ namespace Robust.Server.Physics
|
||||
// Split time
|
||||
if (grids.Count > 1)
|
||||
{
|
||||
_logger.Info($"Splitting {ToPrettyString(uid)} into {grids.Count} grids.");
|
||||
Log.Info($"Splitting {ToPrettyString(uid)} into {grids.Count} grids.");
|
||||
var sw = new Stopwatch();
|
||||
sw.Start();
|
||||
|
||||
@@ -244,13 +252,10 @@ namespace Robust.Server.Physics
|
||||
x.Sum(o => o.Indices.Count)
|
||||
.CompareTo(y.Sum(o => o.Indices.Count)));
|
||||
|
||||
var xformQuery = GetEntityQuery<TransformComponent>();
|
||||
var bodyQuery = GetEntityQuery<PhysicsComponent>();
|
||||
var gridQuery = GetEntityQuery<MapGridComponent>();
|
||||
var oldGridXform = xformQuery.GetComponent(oldGridUid);
|
||||
var (gridPos, gridRot) = _xformSystem.GetWorldPositionRotation(oldGridXform, xformQuery);
|
||||
var mapBody = bodyQuery.GetComponent(oldGridUid);
|
||||
var oldGridComp = gridQuery.GetComponent(oldGridUid);
|
||||
var oldGridXform = _xformQuery.GetComponent(oldGridUid);
|
||||
var (gridPos, gridRot) = _xformSystem.GetWorldPositionRotation(oldGridXform);
|
||||
var mapBody = _bodyQuery.GetComponent(oldGridUid);
|
||||
var oldGridComp = _gridQuery.GetComponent(oldGridUid);
|
||||
var newGrids = new EntityUid[grids.Count - 1];
|
||||
var mapId = oldGridXform.MapID;
|
||||
|
||||
@@ -259,17 +264,17 @@ namespace Robust.Server.Physics
|
||||
var group = grids[i];
|
||||
var newGrid = _mapManager.CreateGridEntity(mapId);
|
||||
var newGridUid = newGrid.Owner;
|
||||
var newGridXform = xformQuery.GetComponent(newGridUid);
|
||||
var newGridXform = _xformQuery.GetComponent(newGridUid);
|
||||
newGrids[i] = newGridUid;
|
||||
|
||||
// Keep same origin / velocity etc; this makes updating a lot faster and easier.
|
||||
_xformSystem.SetWorldPosition(newGridXform, gridPos);
|
||||
_xformSystem.SetWorldPositionRotation(newGridXform, gridPos, gridRot);
|
||||
var splitBody = bodyQuery.GetComponent(newGridUid);
|
||||
_xformSystem.SetWorldPositionRotation(newGridUid, gridPos, gridRot, newGridXform);
|
||||
var splitBody = _bodyQuery.GetComponent(newGridUid);
|
||||
_physics.SetLinearVelocity(newGridUid, mapBody.LinearVelocity, body: splitBody);
|
||||
_physics.SetAngularVelocity(newGridUid, mapBody.AngularVelocity, body: splitBody);
|
||||
|
||||
var gridComp = gridQuery.GetComponent(newGridUid);
|
||||
var gridComp = _gridQuery.GetComponent(newGridUid);
|
||||
var tileData = new List<(Vector2i GridIndices, Tile Tile)>(group.Sum(o => o.Indices.Count));
|
||||
|
||||
// Gather all tiles up front and set once to minimise fixture change events
|
||||
@@ -284,7 +289,7 @@ namespace Robust.Server.Physics
|
||||
}
|
||||
}
|
||||
|
||||
newGrid.Comp.SetTiles(tileData);
|
||||
_maps.SetTiles(newGrid.Owner, newGrid.Comp, tileData);
|
||||
DebugTools.Assert(_mapManager.IsGrid(newGridUid), "A split grid had no tiles?");
|
||||
|
||||
// Set tiles on new grid + update anchored entities
|
||||
@@ -303,8 +308,13 @@ namespace Robust.Server.Physics
|
||||
for (var j = snapgrid.Count - 1; j >= 0; j--)
|
||||
{
|
||||
var ent = snapgrid[j];
|
||||
var xform = xformQuery.GetComponent(ent);
|
||||
_xformSystem.ReAnchor(ent, xform, oldGridComp, gridComp, tilePos, oldGridUid, newGridUid, oldGridXform, newGridXform, xformQuery);
|
||||
var xform = _xformQuery.GetComponent(ent);
|
||||
_xformSystem.ReAnchor(ent, xform,
|
||||
oldGridComp, gridComp,
|
||||
tilePos, tilePos,
|
||||
oldGridUid, newGridUid,
|
||||
oldGridXform, newGridXform,
|
||||
Angle.Zero);
|
||||
DebugTools.Assert(xform.Anchored);
|
||||
}
|
||||
}
|
||||
@@ -317,15 +327,18 @@ namespace Robust.Server.Physics
|
||||
var tilePos = offset + tile;
|
||||
var bounds = _lookup.GetLocalBounds(tilePos, oldGrid.TileSize);
|
||||
|
||||
foreach (var ent in _lookup.GetEntitiesIntersecting(oldGridUid, tilePos, 0f, LookupFlags.Dynamic | LookupFlags.Sundries))
|
||||
_entSet.Clear();
|
||||
_lookup.GetLocalEntitiesIntersecting(oldGridUid, tilePos, _entSet, 0f, LookupFlags.All | ~LookupFlags.Uncontained | LookupFlags.Approximate);
|
||||
|
||||
foreach (var ent in _entSet)
|
||||
{
|
||||
// Consider centre of entity position maybe?
|
||||
var entXform = xformQuery.GetComponent(ent);
|
||||
var entXform = _xformQuery.GetComponent(ent);
|
||||
|
||||
if (entXform.ParentUid != oldGridUid ||
|
||||
!bounds.Contains(entXform.LocalPosition)) continue;
|
||||
|
||||
_xformSystem.SetParent(ent, entXform, newGridUid, xformQuery, newGridXform);
|
||||
_xformSystem.SetParent(ent, entXform, newGridUid, _xformQuery, newGridXform);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -365,10 +378,10 @@ namespace Robust.Server.Physics
|
||||
var ev = new GridSplitEvent(newGrids, oldGridUid);
|
||||
RaiseLocalEvent(uid, ref ev, true);
|
||||
|
||||
_logger.Debug($"Split {grids.Count} grids in {sw.Elapsed}");
|
||||
Log.Debug($"Split {grids.Count} grids in {sw.Elapsed}");
|
||||
}
|
||||
|
||||
_logger.Debug($"Stopped split check for {ToPrettyString(uid)}");
|
||||
Log.Debug($"Stopped split check for {ToPrettyString(uid)}");
|
||||
_isSplitting = false;
|
||||
SendNodeDebug(oldGridUid);
|
||||
}
|
||||
|
||||
69
Robust.Server/Physics/MergeGridsCommand.cs
Normal file
69
Robust.Server/Physics/MergeGridsCommand.cs
Normal file
@@ -0,0 +1,69 @@
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Map.Components;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Toolshed;
|
||||
|
||||
namespace Robust.Server.Physics;
|
||||
|
||||
public sealed class MergeGridsCommand : LocalizedCommands
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entManager = default!;
|
||||
|
||||
public override string Command => "merge_grids";
|
||||
|
||||
public override void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (args.Length < 4)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!NetEntity.TryParse(args[0], out var gridANet) ||
|
||||
!NetEntity.TryParse(args[1], out var gridBNet))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var gridAUid = _entManager.GetEntity(gridANet);
|
||||
var gridBUid = _entManager.GetEntity(gridBNet);
|
||||
|
||||
if (!_entManager.TryGetComponent<MapGridComponent>(gridAUid, out var gridA) ||
|
||||
!_entManager.TryGetComponent<MapGridComponent>(gridBUid, out var gridB))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!int.TryParse(args[2], out var x) ||
|
||||
!int.TryParse(args[3], out var y))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Angle rotation = Angle.Zero;
|
||||
|
||||
if (args.Length >= 5 && int.TryParse(args[4], out var rotationInt))
|
||||
{
|
||||
rotation = Angle.FromDegrees(rotationInt);
|
||||
}
|
||||
|
||||
var offset = new Vector2i(x, y);
|
||||
var fixtureSystem = _entManager.System<GridFixtureSystem>();
|
||||
fixtureSystem.Merge(gridAUid, gridBUid, offset, rotation, gridA: gridA, gridB: gridB);
|
||||
}
|
||||
|
||||
public override CompletionResult GetCompletion(IConsoleShell shell, string[] args)
|
||||
{
|
||||
return args.Length switch
|
||||
{
|
||||
1 => CompletionResult.FromHintOptions(CompletionHelper.Components<MapGridComponent>(args[0], _entManager), Loc.GetString("cmd-merge_grids-hintA")),
|
||||
2 => CompletionResult.FromHintOptions(CompletionHelper.Components<MapGridComponent>(args[1], _entManager), Loc.GetString("cmd-merge_grids-hintB")),
|
||||
3 => CompletionResult.FromHint(Loc.GetString("cmd-merge_grids-xOffset")),
|
||||
4 => CompletionResult.FromHint(Loc.GetString("cmd-merge_grids-yOffset")),
|
||||
5 => CompletionResult.FromHint(Loc.GetString("cmd-merge_grids-angle")),
|
||||
_ => CompletionResult.Empty
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -32,8 +32,6 @@ namespace Robust.Server
|
||||
throw new InvalidOperationException("Cannot start twice!");
|
||||
}
|
||||
|
||||
GlibcBug.Check();
|
||||
|
||||
_hasStarted = true;
|
||||
|
||||
if (!CommandLineArgs.TryParse(args, out var parsed))
|
||||
|
||||
@@ -10,27 +10,30 @@
|
||||
<!-- Try to fix sporadic errors against Robust.Packaging, apparently?? -->
|
||||
<ValidateExecutableReferencesMatchSelfContained>false</ValidateExecutableReferencesMatchSelfContained>
|
||||
<RobustILLink>true</RobustILLink>
|
||||
<NoWarn>CA1416</NoWarn>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="JetBrains.Annotations" Version="2021.3.0" PrivateAssets="All" />
|
||||
<PackageReference Include="SpaceWizards.HttpListener" Version="0.1.0" PrivateAssets="compile" />
|
||||
<PackageReference Include="Microsoft.Data.Sqlite.Core" Version="6.0.9" />
|
||||
<PackageReference Include="SQLitePCLRaw.provider.sqlite3" Version="2.1.4" Condition="'$(UseSystemSqlite)' == 'True'" /> <!-- Cannot be private since Content.Server/Database/ServerDbManager.cs depends on SQLitePCL.raw -->
|
||||
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="2.1.4" Condition="'$(UseSystemSqlite)' != 'True'" PrivateAssets="compile" />
|
||||
<PackageReference Include="prometheus-net" Version="4.1.1" />
|
||||
<PackageReference Include="Serilog.Sinks.Loki" Version="4.0.0-beta3" PrivateAssets="compile" />
|
||||
<PackageReference Include="Microsoft.Extensions.Primitives" Version="6.0.0" />
|
||||
<PackageReference Include="prometheus-net.DotNetRuntime" Version="4.2.2" />
|
||||
<PackageReference Include="TerraFX.Interop.Windows" Version="10.0.20348-rc2" PrivateAssets="compile" />
|
||||
<PackageReference Include="Microsoft.Extensions.ObjectPool" Version="6.0.2" PrivateAssets="compile" />
|
||||
<PackageReference Include="SpaceWizards.Sodium" Version="0.2.1" PrivateAssets="compile" />
|
||||
<PackageReference Include="SharpZstd.Interop" Version="1.5.2-beta2" PrivateAssets="compile" />
|
||||
<PackageReference Condition="'$(FullRelease)' != 'True'" Include="JetBrains.Profiler.Api" Version="1.2.0" />
|
||||
<PackageReference Include="Microsoft.NET.ILLink.Tasks" Version="8.0.0" />
|
||||
<PackageReference Include="JetBrains.Annotations" PrivateAssets="All" />
|
||||
<PackageReference Include="SpaceWizards.HttpListener" PrivateAssets="compile" />
|
||||
<PackageReference Include="Microsoft.Data.Sqlite.Core" />
|
||||
<PackageReference Include="SQLitePCLRaw.provider.sqlite3" Condition="'$(UseSystemSqlite)' == 'True'" /> <!-- Cannot be private since Content.Server/Database/ServerDbManager.cs depends on SQLitePCL.raw -->
|
||||
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Condition="'$(UseSystemSqlite)' != 'True'" PrivateAssets="compile" />
|
||||
<PackageReference Include="prometheus-net" />
|
||||
<PackageReference Include="Serilog.Sinks.Loki" PrivateAssets="compile" />
|
||||
<PackageReference Include="Microsoft.Extensions.Primitives" />
|
||||
<!-- Needed to pull-up the dependency from prometheus-net -->
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
|
||||
<PackageReference Include="prometheus-net.DotNetRuntime" />
|
||||
<PackageReference Include="TerraFX.Interop.Windows" PrivateAssets="compile" />
|
||||
<PackageReference Include="Microsoft.Extensions.ObjectPool" PrivateAssets="compile" />
|
||||
<PackageReference Include="SpaceWizards.Sodium" PrivateAssets="compile" />
|
||||
<PackageReference Include="SharpZstd.Interop" PrivateAssets="compile" />
|
||||
<PackageReference Condition="'$(FullRelease)' != 'True'" Include="JetBrains.Profiler.Api" />
|
||||
<PackageReference Include="Microsoft.NET.ILLink.Tasks" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Lidgren.Network\Lidgren.Network.csproj" />
|
||||
<ProjectReference Include="..\Robust.Physics\Robust.Physics.csproj" />
|
||||
<ProjectReference Include="..\Robust.Shared.Maths\Robust.Shared.Maths.csproj" />
|
||||
<ProjectReference Include="..\Robust.Shared.Scripting\Robust.Shared.Scripting.csproj" />
|
||||
<ProjectReference Include="..\Robust.Shared\Robust.Shared.csproj" />
|
||||
|
||||
@@ -297,25 +297,20 @@ namespace Robust.Server.Scripting
|
||||
|
||||
var results = await (CompletionService
|
||||
.GetService(document)?
|
||||
.GetCompletionsAsync(document, message.Cursor) ?? Task.FromResult<CompletionList?>(null));
|
||||
.GetCompletionsAsync(document, message.Cursor) ?? Task.FromResult(CompletionList.Empty));
|
||||
|
||||
if (results is not null)
|
||||
{
|
||||
var ires = ImmutableArray.CreateBuilder<LiteResult>();
|
||||
foreach (var r in results.Items)
|
||||
ires.Add(new LiteResult(
|
||||
displayText: r.DisplayText,
|
||||
displayTextPrefix: r.DisplayTextPrefix,
|
||||
displayTextSuffix: r.DisplayTextSuffix,
|
||||
inlineDescription: r.InlineDescription,
|
||||
tags: r.Tags,
|
||||
properties: r.Properties
|
||||
));
|
||||
var ires = ImmutableArray.CreateBuilder<LiteResult>();
|
||||
foreach (var r in results.ItemsList)
|
||||
ires.Add(new LiteResult(
|
||||
displayText: r.DisplayText,
|
||||
displayTextPrefix: r.DisplayTextPrefix,
|
||||
displayTextSuffix: r.DisplayTextSuffix,
|
||||
inlineDescription: r.InlineDescription,
|
||||
tags: r.Tags,
|
||||
properties: r.Properties
|
||||
));
|
||||
|
||||
replyMessage.Results = ires.ToImmutable();
|
||||
}
|
||||
else
|
||||
replyMessage.Results = ImmutableArray<LiteResult>.Empty;
|
||||
replyMessage.Results = ires.ToImmutable();
|
||||
|
||||
_netManager.ServerSendMessage(replyMessage, message.MsgChannel);
|
||||
}
|
||||
|
||||
@@ -308,7 +308,7 @@ namespace Robust.Server.ServerStatus
|
||||
private static bool RequestWantsZStd(IStatusHandlerContext context)
|
||||
{
|
||||
// Yeah this isn't a good parser for Accept-Encoding but who cares.
|
||||
return context.RequestHeaders.TryGetValue("Accept-Encoding", out var ac) && ac.Count > 0 && ac[0].Contains("zstd");
|
||||
return context.RequestHeaders.TryGetValue("Accept-Encoding", out var ac) && ac.Count > 0 && ac[0]?.Contains("zstd") == true;
|
||||
}
|
||||
|
||||
// Only call this if the download URL is not available!
|
||||
|
||||
@@ -97,7 +97,7 @@ namespace Robust.Server.ViewVariables
|
||||
|
||||
// Auto-dirty component. Only works when modifying a field that is directly on a component,
|
||||
// Does not work for nested objects.
|
||||
if (Object is Component comp)
|
||||
if (Object is Component { NetSyncEnabled: true } comp)
|
||||
EntityManager.Dirty(comp.Owner, comp);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,10 +3,11 @@
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<LangVersion>9</LangVersion>
|
||||
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.4.0" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.3" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" PrivateAssets="all" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
@@ -258,7 +259,24 @@ namespace Robust.Shared.Maths
|
||||
/// <param name="degrees">The angle in degrees.</param>
|
||||
public static Angle FromDegrees(double degrees)
|
||||
{
|
||||
return new(MathHelper.DegreesToRadians(degrees));
|
||||
// Avoid rounding issues with common use cases.
|
||||
switch (degrees)
|
||||
{
|
||||
case -270:
|
||||
return new Angle(Math.PI * -1.5);
|
||||
case 90:
|
||||
return new Angle(Math.PI / 2);
|
||||
case -180:
|
||||
return new Angle(-Math.PI);
|
||||
case 180:
|
||||
return new Angle(Math.PI);
|
||||
case 270.0:
|
||||
return new Angle(Math.PI * 1.5);
|
||||
case -90:
|
||||
return new Angle(Math.PI / -2);
|
||||
default:
|
||||
return new(MathHelper.DegreesToRadians(degrees));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -75,6 +75,15 @@ namespace Robust.Shared.Maths
|
||||
get => new(Width, Height);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the highest of width or height.
|
||||
/// </summary>
|
||||
public readonly float MaxDimension
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => MathF.Max(Height, Width);
|
||||
}
|
||||
|
||||
public readonly Vector2 Center
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
@@ -177,13 +186,13 @@ namespace Robust.Shared.Maths
|
||||
[Pure]
|
||||
public readonly Box2 Intersect(in Box2 other)
|
||||
{
|
||||
var ourLeftBottom = new System.Numerics.Vector2(Left, Bottom);
|
||||
var ourRightTop = new System.Numerics.Vector2(Right, Top);
|
||||
var otherLeftBottom = new System.Numerics.Vector2(other.Left, other.Bottom);
|
||||
var otherRightTop = new System.Numerics.Vector2(other.Right, other.Top);
|
||||
var ourLeftBottom = new Vector2(Left, Bottom);
|
||||
var ourRightTop = new Vector2(Right, Top);
|
||||
var otherLeftBottom = new Vector2(other.Left, other.Bottom);
|
||||
var otherRightTop = new Vector2(other.Right, other.Top);
|
||||
|
||||
var max = System.Numerics.Vector2.Max(ourLeftBottom, otherLeftBottom);
|
||||
var min = System.Numerics.Vector2.Min(ourRightTop, otherRightTop);
|
||||
var max = Vector2.Max(ourLeftBottom, otherLeftBottom);
|
||||
var min = Vector2.Min(ourRightTop, otherRightTop);
|
||||
|
||||
if (max.X <= min.X && max.Y <= min.Y)
|
||||
return new Box2(max.X, max.Y, min.X, min.Y);
|
||||
@@ -210,13 +219,13 @@ namespace Robust.Shared.Maths
|
||||
[Pure]
|
||||
public readonly Box2 Union(in Box2 other)
|
||||
{
|
||||
var ourLeftBottom = new System.Numerics.Vector2(Left, Bottom);
|
||||
var otherLeftBottom = new System.Numerics.Vector2(other.Left, other.Bottom);
|
||||
var ourRightTop = new System.Numerics.Vector2(Right, Top);
|
||||
var otherRightTop = new System.Numerics.Vector2(other.Right, other.Top);
|
||||
var ourLeftBottom = new Vector2(Left, Bottom);
|
||||
var otherLeftBottom = new Vector2(other.Left, other.Bottom);
|
||||
var ourRightTop = new Vector2(Right, Top);
|
||||
var otherRightTop = new Vector2(other.Right, other.Top);
|
||||
|
||||
var leftBottom = System.Numerics.Vector2.Min(ourLeftBottom, otherLeftBottom);
|
||||
var rightTop = System.Numerics.Vector2.Max(ourRightTop, otherRightTop);
|
||||
var leftBottom = Vector2.Min(ourLeftBottom, otherLeftBottom);
|
||||
var rightTop = Vector2.Max(ourRightTop, otherRightTop);
|
||||
|
||||
if (leftBottom.X <= rightTop.X && leftBottom.Y <= rightTop.Y)
|
||||
return new Box2(leftBottom.X, leftBottom.Y, rightTop.X, rightTop.Y);
|
||||
@@ -396,11 +405,11 @@ namespace Robust.Shared.Maths
|
||||
[Pure]
|
||||
public static Box2 Union(in Vector2 a, in Vector2 b)
|
||||
{
|
||||
var vecA = new System.Numerics.Vector2(a.X, a.Y);
|
||||
var vecB = new System.Numerics.Vector2(b.X, b.Y);
|
||||
var vecA = new Vector2(a.X, a.Y);
|
||||
var vecB = new Vector2(b.X, b.Y);
|
||||
|
||||
var min = System.Numerics.Vector2.Min(vecA, vecB);
|
||||
var max = System.Numerics.Vector2.Max(vecA, vecB);
|
||||
var min = Vector2.Min(vecA, vecB);
|
||||
var max = Vector2.Max(vecA, vecB);
|
||||
|
||||
return new Box2(min.X, min.Y, max.X, max.Y);
|
||||
}
|
||||
@@ -412,12 +421,12 @@ namespace Robust.Shared.Maths
|
||||
[Pure]
|
||||
public readonly Box2 ExtendToContain(Vector2 vec)
|
||||
{
|
||||
var leftBottom = new System.Numerics.Vector2(Left, Bottom);
|
||||
var rightTop = new System.Numerics.Vector2(Right, Top);
|
||||
var vector = new System.Numerics.Vector2(vec.X, vec.Y);
|
||||
var leftBottom = new Vector2(Left, Bottom);
|
||||
var rightTop = new Vector2(Right, Top);
|
||||
var vector = new Vector2(vec.X, vec.Y);
|
||||
|
||||
var min = System.Numerics.Vector2.Min(vector, leftBottom);
|
||||
var max = System.Numerics.Vector2.Max(vector, rightTop);
|
||||
var min = Vector2.Min(vector, leftBottom);
|
||||
var max = Vector2.Max(vector, rightTop);
|
||||
|
||||
return new Box2(min.X, min.Y, max.X, max.Y);
|
||||
}
|
||||
|
||||
@@ -1,13 +1,229 @@
|
||||
using System;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace Robust.Shared.Maths;
|
||||
|
||||
// Reference: https://easings.net/
|
||||
|
||||
internal static class Easings
|
||||
/// <summary>
|
||||
/// A static class for computing easings for animations.
|
||||
/// The parameter "p" is the absolute progress of the animation between 0 and 1.
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public static class Easings
|
||||
{
|
||||
#region Trig
|
||||
|
||||
public static float InSine(float p)
|
||||
{
|
||||
return 1.0f - MathF.Cos(p * MathF.PI / 2.0f);
|
||||
}
|
||||
|
||||
public static float OutSine(float p)
|
||||
{
|
||||
return MathF.Sin(p * MathF.PI / 2);
|
||||
}
|
||||
|
||||
public static float InOutSine(float p)
|
||||
{
|
||||
return -(MathF.Cos(MathF.PI * p) - 1.0f) / 2.0f;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Polynomial
|
||||
|
||||
public static float InQuad(float p)
|
||||
{
|
||||
return p * p;
|
||||
}
|
||||
|
||||
public static float OutQuad(float p)
|
||||
{
|
||||
return 1 - (1 - p) * (1 - p);
|
||||
}
|
||||
|
||||
public static float InOutQuad(float p)
|
||||
{
|
||||
return p < 0.5 ? 2 * p * p : 1 - MathF.Pow(-2 * p + 2, 2) / 2;
|
||||
}
|
||||
|
||||
public static float InCubic(float p)
|
||||
{
|
||||
return p * p * p;
|
||||
}
|
||||
|
||||
public static float OutCubic(float p)
|
||||
{
|
||||
return 1 - MathF.Pow(1 - p, 3);
|
||||
}
|
||||
|
||||
public static float InOutCubic(float p)
|
||||
{
|
||||
return p < 0.5 ? 4 * p * p * p : 1 - MathF.Pow(-2 * p + 2, 3) / 2;
|
||||
}
|
||||
|
||||
public static float InQuart(float p)
|
||||
{
|
||||
return p * p * p * p;
|
||||
}
|
||||
|
||||
public static float OutQuart(float p)
|
||||
{
|
||||
return 1 - MathF.Pow(1 - p, 4);
|
||||
}
|
||||
|
||||
public static float InOutQuart(float p)
|
||||
{
|
||||
return p < 0.5 ? 8 * p * p * p * p : 1 - MathF.Pow(-2 * p + 2, 4) / 2;
|
||||
}
|
||||
|
||||
public static float InQuint(float p)
|
||||
{
|
||||
return p * p * p * p * p;
|
||||
}
|
||||
|
||||
public static float OutQuint(float p)
|
||||
{
|
||||
return 1 - MathF.Pow(1 - p, 5);
|
||||
}
|
||||
|
||||
public static float InOutQuint(float p)
|
||||
{
|
||||
return p < 0.5f ? (16 * p * p * p * p * p) : 1 - MathF.Pow(-2 * p + 2, 5) / 2;
|
||||
return p < 0.5f ? 16 * p * p * p * p * p : 1 - MathF.Pow(-2 * p + 2, 5) / 2;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Other
|
||||
|
||||
public static float InExpo(float p)
|
||||
{
|
||||
return p == 0 ? 0 : MathF.Pow(2, 10 * p - 10);
|
||||
}
|
||||
|
||||
public static float OutExpo(float p)
|
||||
{
|
||||
return Math.Abs(p - 1) < 0.0001f ? 1 : 1 - MathF.Pow(2, -10 * p);
|
||||
}
|
||||
|
||||
public static float InOutExpo(float p)
|
||||
{
|
||||
return p == 0.0f
|
||||
? 0
|
||||
: Math.Abs(p - 1) < 0.0001f
|
||||
? 1
|
||||
: p < 0.5f
|
||||
? MathF.Pow(2, 20 * p - 10) / 2
|
||||
: (2 - MathF.Pow(2, -20 * p + 10)) / 2;
|
||||
}
|
||||
|
||||
public static float InCirc(float p)
|
||||
{
|
||||
return 1 - MathF.Sqrt(1 - MathF.Pow(p, 2));
|
||||
}
|
||||
|
||||
public static float OutCirc(float p)
|
||||
{
|
||||
return MathF.Sqrt(1 - MathF.Pow(p - 1, 2));
|
||||
}
|
||||
|
||||
public static float InOutCirc(float p)
|
||||
{
|
||||
return p < 0.5
|
||||
? (1 - MathF.Sqrt(1 - MathF.Pow(2 * p, 2))) / 2
|
||||
: (MathF.Sqrt(1 - MathF.Pow(-2 * p + 2, 2)) + 1) / 2;
|
||||
}
|
||||
|
||||
public static float InBack(float p)
|
||||
{
|
||||
var c1 = 1.70158f;
|
||||
var c3 = c1 + 1;
|
||||
|
||||
return c3 * p * p * p - c1 * p * p;
|
||||
}
|
||||
|
||||
public static float OutBack(float p)
|
||||
{
|
||||
const float c1 = 1.70158f;
|
||||
const float c3 = c1 + 1;
|
||||
|
||||
return 1 + c3 * MathF.Pow(p - 1, 3) + c1 * MathF.Pow(p - 1, 2);
|
||||
}
|
||||
|
||||
public static float InOutBack(float p)
|
||||
{
|
||||
const float c1 = 1.70158f;
|
||||
const float c2 = c1 * 1.525f;
|
||||
|
||||
return p < 0.5
|
||||
? MathF.Pow(2 * p, 2) * ((c2 + 1) * 2 * p - c2) / 2
|
||||
: (MathF.Pow(2 * p - 2, 2) * ((c2 + 1) * (p * 2 - 2) + c2) + 2) / 2;
|
||||
}
|
||||
|
||||
/// <remarks>
|
||||
/// elastic in, not "inelastic"
|
||||
/// </remarks>
|
||||
public static float InElastic(float p)
|
||||
{
|
||||
const float c4 = 2 * MathF.PI / 3;
|
||||
|
||||
return p == 0
|
||||
? 0
|
||||
: Math.Abs(p - 1) < 0.0001f
|
||||
? 1
|
||||
: -MathF.Pow(2, 10 * p - 10) * MathF.Sin((p * 10 - 10.75f) * c4);
|
||||
}
|
||||
|
||||
public static float OutElastic(float p)
|
||||
{
|
||||
const float c4 = 2.0f * MathF.PI / 3.0f;
|
||||
|
||||
return p == 0
|
||||
? 0
|
||||
: Math.Abs(p - 1) < 0.0001f
|
||||
? 1
|
||||
: MathF.Pow(2, -10 * p) * MathF.Sin((p * 10.0f - 0.75f) * c4) + 1.0f;
|
||||
}
|
||||
|
||||
public static float InOutElastic(float p)
|
||||
{
|
||||
const float c5 = 2.0f * MathF.PI / 4.5f;
|
||||
|
||||
return p == 0
|
||||
? 0
|
||||
: Math.Abs(p - 1) < 0.0001f
|
||||
? 1
|
||||
: p < 0.5
|
||||
? -(MathF.Pow(2, 20 * p - 10) * MathF.Sin((20.0f * p - 11.125f) * c5)) / 2.0f
|
||||
: MathF.Pow(2, -20.0f * p + 10.0f) * MathF.Sin((20.0f * p - 11.125f) * c5) / 2.0f + 1.0f;
|
||||
}
|
||||
|
||||
public static float InBounce(float p)
|
||||
{
|
||||
return 1 - OutBounce(1 - p);
|
||||
}
|
||||
|
||||
public static float OutBounce(float p)
|
||||
{
|
||||
const float n1 = 7.5625f;
|
||||
const float d1 = 2.75f;
|
||||
|
||||
if (p < 1 / d1) return n1 * p * p;
|
||||
|
||||
if (p < 2 / d1) return n1 * (p -= 1.5f / d1) * p + 0.75f;
|
||||
|
||||
if (p < 2.5 / d1) return n1 * (p -= 2.25f / d1) * p + 0.9375f;
|
||||
|
||||
return n1 * (p -= 2.625f / d1) * p + 0.984375f;
|
||||
}
|
||||
|
||||
public static float InOutBounce(float p)
|
||||
{
|
||||
return p < 0.5
|
||||
? (1 - OutBounce(1 - 2 * p)) / 2
|
||||
: (1 + OutBounce(2 * p - 1)) / 2;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="JetBrains.Annotations" Version="2021.3.0" PrivateAssets="All" />
|
||||
<PackageReference Include="JetBrains.Annotations" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="..\MSBuild\Robust.Properties.targets" />
|
||||
|
||||
@@ -109,6 +109,11 @@ namespace Robust.Shared.Maths
|
||||
}
|
||||
}
|
||||
|
||||
public Vector2i Rotate(Angle angle)
|
||||
{
|
||||
return (Vector2i) angle.RotateVec(this);
|
||||
}
|
||||
|
||||
public static Vector2i operator -(Vector2i a, Vector2i b)
|
||||
{
|
||||
return new(a.X - b.X, a.Y - b.Y);
|
||||
|
||||
@@ -7,11 +7,11 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ILReader.Core" Version="1.0.0.4" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Features" Version="4.0.1" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="4.0.1" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.0.1" />
|
||||
<PackageReference Include="JetBrains.Annotations" Version="2021.3.0" PrivateAssets="All" />
|
||||
<PackageReference Include="ILReader.Core" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Features" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" />
|
||||
<PackageReference Include="JetBrains.Annotations" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -50,17 +50,11 @@ public abstract partial class SharedAudioSystem : EntitySystem
|
||||
base.Initialize();
|
||||
InitializeEffect();
|
||||
ZOffset = CfgManager.GetCVar(CVars.AudioZOffset);
|
||||
CfgManager.OnValueChanged(CVars.AudioZOffset, SetZOffset);
|
||||
Subs.CVar(CfgManager, CVars.AudioZOffset, SetZOffset);
|
||||
SubscribeLocalEvent<AudioComponent, ComponentGetStateAttemptEvent>(OnAudioGetStateAttempt);
|
||||
SubscribeLocalEvent<AudioComponent, EntityUnpausedEvent>(OnAudioUnpaused);
|
||||
}
|
||||
|
||||
public override void Shutdown()
|
||||
{
|
||||
base.Shutdown();
|
||||
CfgManager.UnsubValueChanged(CVars.AudioZOffset, SetZOffset);
|
||||
}
|
||||
|
||||
protected void SetZOffset(float value)
|
||||
{
|
||||
ZOffset = value;
|
||||
|
||||
@@ -1239,7 +1239,7 @@ namespace Robust.Shared
|
||||
/// Enable Discord rich presence integration.
|
||||
/// </summary>
|
||||
public static readonly CVarDef<bool> DiscordEnabled =
|
||||
CVarDef.Create("discord.enabled", true, CVar.CLIENTONLY);
|
||||
CVarDef.Create("discord.enabled", true, CVar.CLIENTONLY | CVar.ARCHIVE);
|
||||
|
||||
public static readonly CVarDef<string> DiscordRichPresenceMainIconId =
|
||||
CVarDef.Create("discord.rich_main_icon_id", "devstation", CVar.SERVER | CVar.REPLICATED);
|
||||
@@ -1323,6 +1323,16 @@ namespace Robust.Shared
|
||||
public static readonly CVarDef<float> MidiVolume =
|
||||
CVarDef.Create("midi.volume", 0.50f, CVar.CLIENTONLY | CVar.ARCHIVE);
|
||||
|
||||
/// <summary>
|
||||
/// Controls amount of CPU cores and (by extension) polyphony for Fluidsynth.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// You probably don't want to set this to be multithreaded, the way Fluidsynth's multithreading works is
|
||||
/// probably worse-than-nothing for Robust's usage.
|
||||
/// </remarks>
|
||||
public static readonly CVarDef<int> MidiParallelism =
|
||||
CVarDef.Create("midi.parallelism", 1, CVar.CLIENTONLY | CVar.ARCHIVE);
|
||||
|
||||
/*
|
||||
* HUB
|
||||
* CVars related to public master server hub
|
||||
@@ -1487,14 +1497,14 @@ namespace Robust.Shared
|
||||
/// <summary>
|
||||
/// Maximum compressed size of a replay recording (in kilobytes) before recording automatically stops.
|
||||
/// </summary>
|
||||
public static readonly CVarDef<int> ReplayMaxCompressedSize = CVarDef.Create("replay.max_compressed_size",
|
||||
1024 * 256, CVar.ARCHIVE);
|
||||
public static readonly CVarDef<long> ReplayMaxCompressedSize = CVarDef.Create("replay.max_compressed_size",
|
||||
1024L * 256, CVar.ARCHIVE);
|
||||
|
||||
/// <summary>
|
||||
/// Maximum uncompressed size of a replay recording (in kilobytes) before recording automatically stops.
|
||||
/// </summary>
|
||||
public static readonly CVarDef<int> ReplayMaxUncompressedSize = CVarDef.Create("replay.max_uncompressed_size",
|
||||
1024 * 1024, CVar.ARCHIVE);
|
||||
public static readonly CVarDef<long> ReplayMaxUncompressedSize = CVarDef.Create("replay.max_uncompressed_size",
|
||||
1024L * 1024, CVar.ARCHIVE);
|
||||
|
||||
/// <summary>
|
||||
/// Uncompressed size of individual files created by the replay (in kilobytes), where each file contains data
|
||||
|
||||
@@ -113,10 +113,46 @@ namespace Robust.Shared.Configuration
|
||||
{
|
||||
var loaded = new HashSet<string>();
|
||||
|
||||
foreach (var (cvar, value) in ParseCVarValuesFromToml(stream))
|
||||
var callbackEvents = new ValueList<ValueChangedInvoke>();
|
||||
|
||||
// Ensure callbacks are raised OUTSIDE the write lock.
|
||||
using (Lock.WriteGuard())
|
||||
{
|
||||
loaded.Add(cvar);
|
||||
OverrideDefault(cvar, value);
|
||||
foreach (var (cVarName, value) in ParseCVarValuesFromToml(stream))
|
||||
{
|
||||
if (!_configVars.TryGetValue(cVarName, out var cVar) || !cVar.Registered)
|
||||
{
|
||||
_sawmill.Error($"Trying to set unregistered variable '{cVarName}'");
|
||||
continue;
|
||||
}
|
||||
|
||||
var convertedValue = value;
|
||||
if (!cVar.DefaultValue.GetType().IsEnum && cVar.DefaultValue.GetType() != value.GetType())
|
||||
{
|
||||
try
|
||||
{
|
||||
convertedValue = ConvertToCVarType(value, cVar.DefaultValue.GetType());
|
||||
}
|
||||
catch
|
||||
{
|
||||
_sawmill.Error($"Override TOML parsed cvar does not match registered cvar type. Name: {cVarName}. Code Type: {cVar.DefaultValue.GetType()}. Toml type: {value.GetType()}");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
cVar.DefaultValue = value;
|
||||
|
||||
if (cVar.OverrideValue == null && cVar.Value == null)
|
||||
{
|
||||
if (SetupInvokeValueChanged(cVar, convertedValue) is { } invoke)
|
||||
callbackEvents.Add(invoke);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var callback in callbackEvents)
|
||||
{
|
||||
InvokeValueChanged(callback);
|
||||
}
|
||||
|
||||
return loaded;
|
||||
@@ -303,8 +339,7 @@ namespace Robust.Shared.Configuration
|
||||
{
|
||||
try
|
||||
{
|
||||
// try convert thing like int to float.
|
||||
cVar.Value = Convert.ChangeType(cVar.Value, type);
|
||||
cVar.Value = ConvertToCVarType(cVar.Value, type);
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -711,6 +746,26 @@ namespace Robust.Shared.Configuration
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try to convert a compatible value to the actual registration type of a CVar.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// When CVars are parsed from TOML, their in-code type is not known.
|
||||
/// This function does the necessary conversions from e.g. int to long.
|
||||
/// </remarks>
|
||||
/// <param name="value">
|
||||
/// The value to convert.
|
||||
/// This must be a simple type like strings or integers.
|
||||
/// </param>
|
||||
/// <param name="cVar">
|
||||
/// The registration type of the CVar.
|
||||
/// </param>
|
||||
/// <returns></returns>
|
||||
private static object ConvertToCVarType(object value, Type cVar)
|
||||
{
|
||||
return Convert.ChangeType(value, cVar);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Holds the data for a single configuration variable.
|
||||
/// </summary>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
@@ -9,6 +10,7 @@ using Robust.Shared.Localization;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Map.Components;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Physics.Components;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
@@ -84,11 +86,18 @@ public sealed class TeleportToCommand : LocalizedCommands
|
||||
|
||||
var target = args[0];
|
||||
|
||||
if (!TryGetTransformFromUidOrUsername(target, shell, out _, out var targetTransform))
|
||||
if (!TryGetTransformFromUidOrUsername(target, shell, out var targetUid, out _))
|
||||
return;
|
||||
|
||||
var transformSystem = _entities.System<SharedTransformSystem>();
|
||||
var targetCoords = targetTransform.Coordinates;
|
||||
var targetCoords = new EntityCoordinates(targetUid.Value, Vector2.Zero);
|
||||
|
||||
if (_entities.TryGetComponent(targetUid, out PhysicsComponent? targetPhysics))
|
||||
{
|
||||
targetCoords = targetCoords.Offset(targetPhysics.LocalCenter);
|
||||
}
|
||||
|
||||
var victims = new List<(EntityUid Entity, TransformComponent Transform)>();
|
||||
|
||||
if (args.Length == 1)
|
||||
{
|
||||
@@ -100,8 +109,7 @@ public sealed class TeleportToCommand : LocalizedCommands
|
||||
return;
|
||||
}
|
||||
|
||||
transformSystem.SetCoordinates(ent.Value, targetCoords);
|
||||
playerTransform.AttachToGridOrMap();
|
||||
victims.Add((ent.Value, playerTransform));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -111,12 +119,17 @@ public sealed class TeleportToCommand : LocalizedCommands
|
||||
continue;
|
||||
|
||||
if (!TryGetTransformFromUidOrUsername(victim, shell, out var uid, out var victimTransform))
|
||||
return;
|
||||
continue;
|
||||
|
||||
transformSystem.SetCoordinates(uid.Value, targetCoords);
|
||||
victimTransform.AttachToGridOrMap();
|
||||
victims.Add((uid.Value, victimTransform));
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var victim in victims)
|
||||
{
|
||||
transformSystem.SetCoordinates(victim.Entity, targetCoords);
|
||||
transformSystem.AttachToGridOrMap(victim.Entity, victim.Transform);
|
||||
}
|
||||
}
|
||||
|
||||
private bool TryGetTransformFromUidOrUsername(
|
||||
@@ -128,8 +141,7 @@ public sealed class TeleportToCommand : LocalizedCommands
|
||||
if (NetEntity.TryParse(str, out var uidNet)
|
||||
&& _entities.TryGetEntity(uidNet, out var uid)
|
||||
&& _entities.TryGetComponent(uid, out transform)
|
||||
&& !_entities.HasComponent<MapComponent>(uid)
|
||||
&& !_entities.HasComponent<MapGridComponent>(uid))
|
||||
&& !_entities.HasComponent<MapComponent>(uid))
|
||||
{
|
||||
victimUid = uid;
|
||||
return true;
|
||||
|
||||
@@ -25,6 +25,7 @@ namespace Robust.Shared.Containers
|
||||
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||
[Dependency] private readonly SharedJointSystem _joint = default!;
|
||||
|
||||
private EntityQuery<ContainerManagerComponent> _managerQuery;
|
||||
private EntityQuery<MapGridComponent> _gridQuery;
|
||||
private EntityQuery<MapComponent> _mapQuery;
|
||||
protected EntityQuery<MetaDataComponent> MetaQuery;
|
||||
@@ -42,6 +43,7 @@ namespace Robust.Shared.Containers
|
||||
SubscribeLocalEvent<ContainerManagerComponent, ComponentGetState>(OnContainerGetState);
|
||||
SubscribeLocalEvent<ContainerManagerComponent, ComponentRemove>(OnContainerManagerRemove);
|
||||
|
||||
_managerQuery = GetEntityQuery<ContainerManagerComponent>();
|
||||
_gridQuery = GetEntityQuery<MapGridComponent>();
|
||||
_mapQuery = GetEntityQuery<MapComponent>();
|
||||
MetaQuery = GetEntityQuery<MetaDataComponent>();
|
||||
@@ -437,8 +439,7 @@ namespace Robust.Shared.Containers
|
||||
/// </summary>
|
||||
public bool TryGetOuterContainer(EntityUid uid, TransformComponent xform, [NotNullWhen(true)] out BaseContainer? container)
|
||||
{
|
||||
var xformQuery = GetEntityQuery<TransformComponent>();
|
||||
return TryGetOuterContainer(uid, xform, out container, xformQuery);
|
||||
return TryGetOuterContainer(uid, xform, out container, TransformQuery);
|
||||
}
|
||||
|
||||
public bool TryGetOuterContainer(EntityUid uid, TransformComponent xform,
|
||||
@@ -449,15 +450,13 @@ namespace Robust.Shared.Containers
|
||||
if (!uid.IsValid())
|
||||
return false;
|
||||
|
||||
var conQuery = GetEntityQuery<ContainerManagerComponent>();
|
||||
var metaQuery = GetEntityQuery<MetaDataComponent>();
|
||||
var child = uid;
|
||||
var parent = xform.ParentUid;
|
||||
|
||||
while (parent.IsValid())
|
||||
{
|
||||
if (((metaQuery.GetComponent(child).Flags & MetaDataFlags.InContainer) == MetaDataFlags.InContainer) &&
|
||||
conQuery.TryGetComponent(parent, out var conManager) &&
|
||||
if (((MetaQuery.GetComponent(child).Flags & MetaDataFlags.InContainer) == MetaDataFlags.InContainer) &&
|
||||
_managerQuery.TryGetComponent(parent, out var conManager) &&
|
||||
TryGetContainingContainer(parent, child, out var parentContainer, conManager))
|
||||
{
|
||||
container = parentContainer;
|
||||
|
||||
@@ -913,9 +913,14 @@ namespace Robust.Shared.ContentPack
|
||||
return null;
|
||||
}
|
||||
|
||||
public PEReader? Resolve(string simpleName)
|
||||
public PEReader? ResolveAssembly(AssemblyName assemblyName)
|
||||
{
|
||||
return _dictionary.GetOrAdd(simpleName, ResolveCore);
|
||||
return _dictionary.GetOrAdd(assemblyName.Name!, ResolveCore);
|
||||
}
|
||||
|
||||
public PEReader? ResolveModule(AssemblyName referencingAssembly, string fileName)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
||||
@@ -325,19 +325,23 @@ namespace Robust.Shared.ContentPack
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
Sawmill.Debug("ResolvingAssembly {0}", name);
|
||||
Sawmill.Verbose("ResolvingAssembly {0}", name);
|
||||
|
||||
// Try main modules.
|
||||
foreach (var mod in Mods)
|
||||
{
|
||||
if (mod.GameAssembly.FullName == name.FullName)
|
||||
{
|
||||
Sawmill.Verbose($"Found assembly in modloader ALC: {mod.GameAssembly}");
|
||||
return mod.GameAssembly;
|
||||
}
|
||||
}
|
||||
|
||||
if (TryLoadExtra(name) is { } asm)
|
||||
{
|
||||
Sawmill.Verbose($"Found assembly through extra loader: {asm}");
|
||||
return asm;
|
||||
}
|
||||
|
||||
// Do not allow sideloading when sandboxing is enabled.
|
||||
// Side loaded assemblies would not be checked for sandboxing currently, so we can't have that.
|
||||
@@ -347,18 +351,42 @@ namespace Robust.Shared.ContentPack
|
||||
{
|
||||
if (assembly.FullName == name.FullName)
|
||||
{
|
||||
Sawmill.Verbose($"Found assembly in existing side modules: {assembly}");
|
||||
return assembly;
|
||||
}
|
||||
}
|
||||
|
||||
// Try to resolve assemblies in the default AssemblyLoadContext.
|
||||
// If we don't do this manually, the sideloading code below could load assemblies from content,
|
||||
// even if Robust provides its own versions.
|
||||
// This can lead to:
|
||||
// * Multiple copies of the same assembly being loaded.
|
||||
// * Mismatching versions of dependencies being loaded.
|
||||
// * e.g. Microsoft.Extensions.Primitives 6.0 with Microsoft.Extensions.DependencyInjection 7.0
|
||||
//
|
||||
// Now, to be clear, this is 100% an error in packaging. But it's also one that's really easy to make.
|
||||
//
|
||||
try
|
||||
{
|
||||
var defaultAssembly = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(name.Name!));
|
||||
Sawmill.Verbose($"Found assembly through default ALC (early): {defaultAssembly}");
|
||||
return defaultAssembly;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Assume assembly not loadable from Robust's directory, proceed with loading from content.
|
||||
}
|
||||
|
||||
if (_res.TryContentFileRead($"/Assemblies/{name.Name}.dll", out var dll))
|
||||
{
|
||||
var assembly = _loadContext.LoadFromStream(dll);
|
||||
_sideModules.Add(assembly);
|
||||
Sawmill.Verbose($"Found assembly in NEW side module: {assembly}");
|
||||
return assembly;
|
||||
}
|
||||
}
|
||||
|
||||
Sawmill.Verbose("Did not find assembly directly. Should fall back to default ALC.");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -381,7 +409,7 @@ namespace Robust.Shared.ContentPack
|
||||
// Otherwise it would load the assemblies a second time which is an amazing way to have everything break.
|
||||
if (_useLoadContext)
|
||||
{
|
||||
Sawmill.Debug($"RESOLVING DEFAULT: {name}");
|
||||
Sawmill.Verbose($"RESOLVING DEFAULT: {name}");
|
||||
foreach (var module in LoadedModules)
|
||||
{
|
||||
if (module.GetName().Name == name.Name)
|
||||
|
||||
@@ -73,6 +73,9 @@ WhitelistedNamespaces:
|
||||
# * The API is not *relevant* to content. e.g. System.Type.IsAnsiClass.
|
||||
# * I am lazy these API lists are huge dude.
|
||||
Types:
|
||||
Avalonia.Metadata:
|
||||
XmlnsDefinitionAttribute:
|
||||
All: True
|
||||
NetSerializer:
|
||||
NetListAsArray`1:
|
||||
Fields:
|
||||
@@ -626,6 +629,7 @@ Types:
|
||||
- "System.Text.Encoding get_UTF7()"
|
||||
- "System.Text.Encoding get_UTF8()"
|
||||
- "System.Text.Encoding get_UTF32()"
|
||||
- "System.Text.Encoding GetEncoding(string)"
|
||||
NormalizationForm: { } # Enum
|
||||
Rune: { All: True }
|
||||
StringBuilder:
|
||||
@@ -716,6 +720,9 @@ Types:
|
||||
ChunkEnumerator: { All: True }
|
||||
AppendInterpolatedStringHandler: { All: True }
|
||||
StringRuneEnumerator: { All: True }
|
||||
System.Text.Unicode:
|
||||
UnicodeRange: { All: True }
|
||||
UnicodeRanges: { All: True }
|
||||
System.Threading.Tasks:
|
||||
Task: { All: True }
|
||||
Task`1: { All: True }
|
||||
@@ -1408,4 +1415,7 @@ Types:
|
||||
# should be fine to do All: True, but this has some methods to read filestreams. So just in case this ever adds an extension method that directly opens a file:
|
||||
Methods:
|
||||
- "!!0 ParseOrThrow<>(Pidgin.Parser`2<char, !!0>, string, System.Func`3<char, Pidgin.SourcePos, Pidgin.SourcePos>)"
|
||||
- "!!0 ParseOrThrow<>(Pidgin.Parser`2<char, !!0>, string, Pidgin.Configuration.IConfiguration`1<char>)"
|
||||
SourcePos: { }
|
||||
Pidgin.Configuration:
|
||||
IConfiguration`1: { All: True }
|
||||
|
||||
@@ -16,8 +16,13 @@ namespace Robust.Shared.GameObjects
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
private bool _netSync { get; set; } = true;
|
||||
|
||||
[Obsolete("Do not use from content")]
|
||||
public bool Networked { get; set; } = true;
|
||||
internal bool Networked { get; set; } = true;
|
||||
|
||||
bool IComponent.Networked
|
||||
{
|
||||
get => Networked;
|
||||
set => Networked = value;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool NetSyncEnabled
|
||||
@@ -31,9 +36,14 @@ namespace Robust.Shared.GameObjects
|
||||
[Obsolete("Update your API to allow accessing Owner through other means")]
|
||||
public EntityUid Owner { get; set; } = EntityUid.Invalid;
|
||||
|
||||
/// <inheritdoc />
|
||||
[ViewVariables]
|
||||
public ComponentLifeStage LifeStage { get; [Obsolete("Do not use from content")] set; } = ComponentLifeStage.PreAdd;
|
||||
public ComponentLifeStage LifeStage { get; internal set; } = ComponentLifeStage.PreAdd;
|
||||
|
||||
ComponentLifeStage IComponent.LifeStage
|
||||
{
|
||||
get => LifeStage;
|
||||
set => LifeStage = value;
|
||||
}
|
||||
|
||||
public virtual bool SendOnlyToOwner => false;
|
||||
|
||||
@@ -51,13 +61,29 @@ namespace Robust.Shared.GameObjects
|
||||
[ViewVariables]
|
||||
public bool Deleted => LifeStage >= ComponentLifeStage.Removing;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// This is the tick the component was created.
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
public GameTick CreationTick { get; [Obsolete("Do not use from content")] set; }
|
||||
public GameTick CreationTick { get; internal set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
GameTick IComponent.CreationTick
|
||||
{
|
||||
get => CreationTick;
|
||||
set => CreationTick = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Marks the component as dirty so that the network will re-sync it with clients.
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
public GameTick LastModifiedTick { get; [Obsolete("Do not use from content")] set; }
|
||||
public GameTick LastModifiedTick { get; internal set; }
|
||||
|
||||
GameTick IComponent.LastModifiedTick
|
||||
{
|
||||
get => LastModifiedTick;
|
||||
set => LastModifiedTick = value;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[Obsolete]
|
||||
@@ -69,15 +95,23 @@ namespace Robust.Shared.GameObjects
|
||||
|
||||
// these two methods clear the LastModifiedTick/CreationTick to mark it as "not different from prototype load".
|
||||
// This is used as optimization in the game state system to avoid sending redundant component data.
|
||||
[Obsolete("Do not use from content")]
|
||||
public virtual void ClearTicks()
|
||||
void IComponent.ClearTicks()
|
||||
{
|
||||
ClearTicks();
|
||||
}
|
||||
|
||||
private protected virtual void ClearTicks()
|
||||
{
|
||||
LastModifiedTick = GameTick.Zero;
|
||||
ClearCreationTick();
|
||||
}
|
||||
|
||||
[Obsolete("Do not use from content")]
|
||||
public void ClearCreationTick()
|
||||
void IComponent.ClearCreationTick()
|
||||
{
|
||||
ClearCreationTick();
|
||||
}
|
||||
|
||||
private protected void ClearCreationTick()
|
||||
{
|
||||
CreationTick = GameTick.Zero;
|
||||
}
|
||||
|
||||
@@ -149,7 +149,6 @@ namespace Robust.Shared.GameObjects
|
||||
[ViewVariables]
|
||||
public EntityLifeStage EntityLifeStage { get; internal set; }
|
||||
|
||||
[DataField("flags")]
|
||||
public MetaDataFlags Flags
|
||||
{
|
||||
get => _flags;
|
||||
@@ -192,8 +191,7 @@ namespace Robust.Shared.GameObjects
|
||||
[ViewVariables]
|
||||
internal PvsChunkLocation? LastPvsLocation;
|
||||
|
||||
[Obsolete("Do not use from content")]
|
||||
public override void ClearTicks()
|
||||
private protected override void ClearTicks()
|
||||
{
|
||||
// Do not clear modified ticks.
|
||||
// MetaDataComponent is used in the game state system to carry initial data like prototype ID.
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
namespace Robust.Shared.GameObjects;
|
||||
|
||||
/// <summary>
|
||||
/// Helper extension methods for working with Bound User Interface events.
|
||||
/// </summary>
|
||||
/// <seealso cref="BoundUserInterfaceMessage"/>
|
||||
public static class BoundUserInterfaceRegisterExt
|
||||
{
|
||||
/// <summary>
|
||||
/// Delegate that subscribes to actual BUI events.
|
||||
/// Used as a lambda via <see cref="BoundUserInterfaceRegisterExt.BuiEvents{TComp}"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="TComp">The type of component that will receive the events.</typeparam>
|
||||
public delegate void BuiEventSubscriber<TComp>(Subscriber<TComp> subscriber) where TComp : IComponent;
|
||||
|
||||
/// <summary>
|
||||
/// Extension method to subscribe to one or more Bound User Interface events via a system,
|
||||
/// sharing the same UI key and owning component.
|
||||
/// </summary>
|
||||
/// <param name="subs">
|
||||
/// The entity system subscriptions.
|
||||
/// Call this with <see cref="EntitySystem.Subscriptions"/>.
|
||||
/// </param>
|
||||
/// <param name="uiKey">
|
||||
/// The UI key to filter these subscriptions. The handler will only receive events targeted for this UI key.
|
||||
/// </param>
|
||||
/// <param name="subscriber">The delegate that will subscribe to the actual events.</param>
|
||||
/// <typeparam name="TComp">The type of component that will receive the events.</typeparam>
|
||||
/// <seealso cref="Subscriber{TComp}"/>
|
||||
public static void BuiEvents<TComp>(
|
||||
this EntitySystem.Subscriptions subs,
|
||||
object uiKey,
|
||||
BuiEventSubscriber<TComp> subscriber)
|
||||
where TComp : IComponent
|
||||
{
|
||||
subscriber(new Subscriber<TComp>(subs, uiKey));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper class to register Bound User Interface subscriptions against.
|
||||
/// Created by <see cref="BoundUserInterfaceRegisterExt.BuiEvents{TComp}"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="TComp">The type of component that will receive the events.</typeparam>
|
||||
public sealed class Subscriber<TComp> where TComp : IComponent
|
||||
{
|
||||
private readonly EntitySystem.Subscriptions _subs;
|
||||
private readonly object _uiKey;
|
||||
|
||||
internal Subscriber(EntitySystem.Subscriptions subs, object uiKey)
|
||||
{
|
||||
_subs = subs;
|
||||
_uiKey = uiKey;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subscribe to a local event. This is effectively equivalent to <see cref="M:Robust.Shared.GameObjects.EntitySystem.SubscribeLocalEvent``2(Robust.Shared.GameObjects.ComponentEventHandler{``0,``1},System.Type[],System.Type[])"/>,
|
||||
/// but reduces repetition and automatically filters for the appropriate UI key.
|
||||
/// </summary>
|
||||
/// <param name="handler">The handler that will get executed whenever the appropriate event is raised.</param>
|
||||
/// <typeparam name="TEvent">The type of event to handle with this subscription.</typeparam>
|
||||
/// <seealso cref="M:Robust.Shared.GameObjects.EntitySystem.SubscribeLocalEvent``2(Robust.Shared.GameObjects.ComponentEventHandler{``0,``1},System.Type[],System.Type[])"/>
|
||||
public void Event<TEvent>(ComponentEventHandler<TComp, TEvent> handler)
|
||||
where TEvent : BaseBoundUserInterfaceEvent
|
||||
{
|
||||
_subs.SubscribeLocalEvent<TComp, TEvent>((uid, component, args) =>
|
||||
{
|
||||
if (!_uiKey.Equals(args.UiKey))
|
||||
return;
|
||||
|
||||
handler(uid, component, args);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subscribe to a local event. This is effectively equivalent to <see cref="M:Robust.Shared.GameObjects.EntitySystem.SubscribeLocalEvent``2(Robust.Shared.GameObjects.ComponentEventHandler{``0,``1},System.Type[],System.Type[])"/>,
|
||||
/// but reduces repetition and automatically filters for the appropriate UI key.
|
||||
/// </summary>
|
||||
/// <param name="handler">The handler that will get executed whenever the appropriate event is raised.</param>
|
||||
/// <typeparam name="TEvent">The type of event to handle with this subscription.</typeparam>
|
||||
/// <seealso cref="M:Robust.Shared.GameObjects.EntitySystem.SubscribeLocalEvent``2(Robust.Shared.GameObjects.ComponentEventHandler{``0,``1},System.Type[],System.Type[])"/>
|
||||
public void Event<TEvent>(EntityEventRefHandler<TComp, TEvent> handler)
|
||||
where TEvent : BaseBoundUserInterfaceEvent
|
||||
{
|
||||
_subs.SubscribeLocalEvent((Entity<TComp> ent, ref TEvent args) =>
|
||||
{
|
||||
if (!_uiKey.Equals(args.UiKey))
|
||||
return;
|
||||
|
||||
handler(ent, ref args);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user