mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-15 03:30:53 +01:00
Compare commits
36 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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
123
RELEASE-NOTES.md
123
RELEASE-NOTES.md
@@ -54,6 +54,121 @@ END TEMPLATE-->
|
||||
*None yet*
|
||||
|
||||
|
||||
## 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 +182,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 +197,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 +213,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>
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -35,8 +35,6 @@ namespace Robust.Client
|
||||
throw new InvalidOperationException("Cannot start twice!");
|
||||
}
|
||||
|
||||
GlibcBug.Check();
|
||||
|
||||
_hasStarted = true;
|
||||
|
||||
if (CommandLineArgs.TryParse(args, out var parsed))
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -124,7 +124,14 @@ namespace Robust.Client.Input
|
||||
var path = new ResPath(KeybindsPath);
|
||||
if (_resourceMan.UserData.Exists(path))
|
||||
{
|
||||
LoadKeyFile(path, true);
|
||||
try
|
||||
{
|
||||
LoadKeyFile(path, true);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.ErrorS("input", "Failed to load user keybindings: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
if (_resourceMan.ContentFileExists(path))
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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++;
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -193,5 +193,6 @@ internal sealed partial class PvsSystem
|
||||
|
||||
session.PreviouslySent.Clear();
|
||||
session.LastSent = null;
|
||||
session.Entities.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,10 +47,19 @@ 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);
|
||||
@@ -197,7 +206,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 +243,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 +253,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 +265,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 +290,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 +309,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 +328,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 +379,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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -1408,4 +1408,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);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Robust.Shared.GameObjects;
|
||||
|
||||
@@ -11,25 +12,34 @@ namespace Robust.Shared.GameObjects;
|
||||
[PublicAPI]
|
||||
public sealed class PlayerBoundUserInterface
|
||||
{
|
||||
[ViewVariables]
|
||||
public float InteractionRange;
|
||||
|
||||
[ViewVariables]
|
||||
public float InteractionRangeSqrd => InteractionRange * InteractionRange;
|
||||
|
||||
[ViewVariables]
|
||||
public Enum UiKey { get; }
|
||||
[ViewVariables]
|
||||
public EntityUid Owner { get; }
|
||||
|
||||
internal readonly HashSet<ICommonSession> _subscribedSessions = new();
|
||||
[ViewVariables]
|
||||
internal BoundUIWrapMessage? LastStateMsg;
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public bool RequireInputValidation;
|
||||
|
||||
[ViewVariables]
|
||||
internal bool StateDirty;
|
||||
|
||||
[ViewVariables]
|
||||
internal readonly Dictionary<ICommonSession, BoundUIWrapMessage> PlayerStateOverrides =
|
||||
new();
|
||||
|
||||
/// <summary>
|
||||
/// All of the sessions currently subscribed to this UserInterface.
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
public IReadOnlySet<ICommonSession> SubscribedSessions => _subscribedSessions;
|
||||
|
||||
public PlayerBoundUserInterface(PrototypeData data, EntityUid owner)
|
||||
|
||||
@@ -1,19 +1,23 @@
|
||||
using System.Collections.Generic;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Robust.Shared.GameObjects
|
||||
{
|
||||
[RegisterComponent]
|
||||
public sealed partial class ActiveUserInterfaceComponent : Component
|
||||
{
|
||||
[ViewVariables]
|
||||
public HashSet<PlayerBoundUserInterface> Interfaces = new();
|
||||
}
|
||||
|
||||
[PublicAPI]
|
||||
public sealed class ServerBoundUserInterfaceMessage
|
||||
{
|
||||
[ViewVariables]
|
||||
public BoundUserInterfaceMessage Message { get; }
|
||||
[ViewVariables]
|
||||
public ICommonSession Session { get; }
|
||||
|
||||
public ServerBoundUserInterfaceMessage(BoundUserInterfaceMessage message, ICommonSession session)
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace Robust.Shared.GameObjects
|
||||
|
||||
/// <inheritdoc />
|
||||
[Virtual]
|
||||
public partial class EntityManager : IEntityManager
|
||||
public abstract partial class EntityManager : IEntityManager
|
||||
{
|
||||
#region Dependencies
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace Robust.Shared.GameObjects
|
||||
public IEntitySystemManager EntitySysManager => _entitySystemManager;
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual IEntityNetworkManager? EntityNetManager => null;
|
||||
public abstract IEntityNetworkManager EntityNetManager { get; }
|
||||
|
||||
protected readonly Queue<EntityUid> QueuedDeletions = new();
|
||||
protected readonly HashSet<EntityUid> QueuedDeletionsSet = new();
|
||||
|
||||
@@ -206,6 +206,32 @@ namespace Robust.Shared.GameObjects
|
||||
{
|
||||
System.SubscribeLocalEvent(handler, before, after);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Proxy to <see cref="M:Robust.Shared.GameObjects.EntitySystem.SubscribeLocalEvent``2(Robust.Shared.GameObjects.ComponentEventRefHandler{``0,``1},System.Type[],System.Type[])" />
|
||||
/// on the owning system.
|
||||
/// </summary>
|
||||
public void SubscribeLocalEvent<TComp, TEvent>(
|
||||
ComponentEventRefHandler<TComp, TEvent> handler,
|
||||
Type[]? before = null, Type[]? after = null)
|
||||
where TComp : IComponent
|
||||
where TEvent : EntityEventArgs
|
||||
{
|
||||
System.SubscribeLocalEvent(handler, before, after);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Proxy to <see cref="M:Robust.Shared.GameObjects.EntitySystem.SubscribeLocalEvent``2(Robust.Shared.GameObjects.EntityEventRefHandler{``0,``1},System.Type[],System.Type[])" />
|
||||
/// on the owning system.
|
||||
/// </summary>
|
||||
public void SubscribeLocalEvent<TComp, TEvent>(
|
||||
EntityEventRefHandler<TComp, TEvent> handler,
|
||||
Type[]? before = null, Type[]? after = null)
|
||||
where TComp : IComponent
|
||||
where TEvent : EntityEventArgs
|
||||
{
|
||||
System.SubscribeLocalEvent(handler, before, after);
|
||||
}
|
||||
}
|
||||
|
||||
private abstract class SubBase
|
||||
|
||||
@@ -16,10 +16,9 @@ namespace Robust.Shared.GameObjects
|
||||
/// The current lifetime stage of this component. You can use this to check
|
||||
/// if the component is initialized or being deleted.
|
||||
/// </summary>
|
||||
ComponentLifeStage LifeStage { get; [Obsolete("Do not use from content")] set; }
|
||||
ComponentLifeStage LifeStage { get; internal set; }
|
||||
|
||||
[Obsolete("Do not use from content")]
|
||||
bool Networked { get; set; }
|
||||
internal bool Networked { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether this component should be synchronized with clients when modified.
|
||||
@@ -68,22 +67,21 @@ namespace Robust.Shared.GameObjects
|
||||
/// <summary>
|
||||
/// Marks the component as dirty so that the network will re-sync it with clients.
|
||||
/// </summary>
|
||||
[Obsolete]
|
||||
void Dirty(IEntityManager? entManager = null);
|
||||
|
||||
/// <summary>
|
||||
/// This is the tick the component was created.
|
||||
/// </summary>
|
||||
GameTick CreationTick { get; set; }
|
||||
GameTick CreationTick { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// This is the last game tick Dirty() was called.
|
||||
/// </summary>
|
||||
GameTick LastModifiedTick { get; set; }
|
||||
GameTick LastModifiedTick { get; internal set; }
|
||||
|
||||
[Obsolete("Do not use from content")]
|
||||
void ClearTicks();
|
||||
internal void ClearTicks();
|
||||
|
||||
[Obsolete("Do not use from content")]
|
||||
void ClearCreationTick();
|
||||
internal void ClearCreationTick();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,7 +164,7 @@ namespace Robust.Shared.GameObjects
|
||||
/// <typeparam name="T">Component reference type to check for.</typeparam>
|
||||
/// <param name="uid">Entity UID to check.</param>
|
||||
/// <returns>True if the entity has the component type, otherwise false.</returns>
|
||||
bool HasComponent<T>(EntityUid? uid) where T : IComponent;
|
||||
bool HasComponent<T>([NotNullWhen(true)] EntityUid? uid) where T : IComponent;
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the entity has a component type.
|
||||
@@ -180,7 +180,7 @@ namespace Robust.Shared.GameObjects
|
||||
/// <param name="uid">Entity UID to check.</param>
|
||||
/// <param name="type">A trait or component type to check for.</param>
|
||||
/// <returns>True if the entity has the component type, otherwise false.</returns>
|
||||
bool HasComponent(EntityUid? uid, Type type);
|
||||
bool HasComponent([NotNullWhen(true)] EntityUid? uid, Type type);
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the entity has a component with a given network ID. This does not check
|
||||
@@ -198,7 +198,7 @@ namespace Robust.Shared.GameObjects
|
||||
/// <param name="uid">Entity UID to check.</param>
|
||||
/// <param name="netId">Network ID to check for.</param>
|
||||
/// <returns>True if the entity has a component with the given network ID, otherwise false.</returns>
|
||||
bool HasComponent(EntityUid? uid, ushort netId, MetaDataComponent? meta = null);
|
||||
bool HasComponent([NotNullWhen(true)] EntityUid? uid, ushort netId, MetaDataComponent? meta = null);
|
||||
|
||||
/// <summary>
|
||||
/// This method will always return a component for a certain entity, adding it if it's not there already.
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace Robust.Shared.GameObjects
|
||||
|
||||
IComponentFactory ComponentFactory { get; }
|
||||
IEntitySystemManager EntitySysManager { get; }
|
||||
IEntityNetworkManager? EntityNetManager { get; }
|
||||
IEntityNetworkManager EntityNetManager { get; }
|
||||
IEventBus EventBus { get; }
|
||||
|
||||
#region Entity Management
|
||||
|
||||
@@ -13,10 +13,10 @@ internal sealed class RobustMemoryManager
|
||||
// Let's be real this is a bandaid for pooling bullshit at an engine level and I don't know what
|
||||
// good memory management looks like for PVS or the RobustSerializer.
|
||||
|
||||
private static readonly RecyclableMemoryStreamManager MemStreamManager = new()
|
||||
private static readonly RecyclableMemoryStreamManager MemStreamManager = new(new RecyclableMemoryStreamManager.Options
|
||||
{
|
||||
ThrowExceptionOnToArray = true,
|
||||
};
|
||||
});
|
||||
|
||||
public RobustMemoryManager()
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,11 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Map.Components;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Physics.Collision.Shapes;
|
||||
using Robust.Shared.Physics.Dynamics;
|
||||
|
||||
namespace Robust.Shared.GameObjects;
|
||||
|
||||
@@ -10,6 +15,65 @@ public sealed partial class EntityLookupSystem
|
||||
* Local AABB / Box2Rotated queries for broadphase entities.
|
||||
*/
|
||||
|
||||
private void AddLocalEntitiesIntersecting(
|
||||
EntityUid lookupUid,
|
||||
HashSet<EntityUid> intersecting,
|
||||
Box2 localAABB,
|
||||
LookupFlags flags,
|
||||
BroadphaseComponent? lookup = null)
|
||||
{
|
||||
if (!_broadQuery.Resolve(lookupUid, ref lookup))
|
||||
return;
|
||||
|
||||
var lookupPoly = new PolygonShape();
|
||||
lookupPoly.SetAsBox(localAABB);
|
||||
var (lookupPos, lookupRot) = _transform.GetWorldPositionRotation(lookupUid);
|
||||
var lookupTransform = new Transform(lookupPos, lookupRot);
|
||||
|
||||
AddEntitiesIntersecting(lookupUid, intersecting, lookupPoly, lookupTransform, flags, lookup);
|
||||
}
|
||||
|
||||
private void AddLocalEntitiesIntersecting(
|
||||
EntityUid lookupUid,
|
||||
HashSet<EntityUid> intersecting,
|
||||
Box2Rotated localBounds,
|
||||
LookupFlags flags,
|
||||
BroadphaseComponent? lookup = null)
|
||||
{
|
||||
if (!_broadQuery.Resolve(lookupUid, ref lookup))
|
||||
return;
|
||||
|
||||
var shape = new PolygonShape();
|
||||
shape.Set(localBounds);
|
||||
|
||||
var transform = _physics.GetPhysicsTransform(lookupUid);
|
||||
AddEntitiesIntersecting(lookupUid, intersecting, shape, transform, flags);
|
||||
}
|
||||
|
||||
public bool AnyLocalEntitiesIntersecting(EntityUid lookupUid,
|
||||
Box2 localAABB,
|
||||
LookupFlags flags,
|
||||
EntityUid? ignored = null,
|
||||
BroadphaseComponent? lookup = null)
|
||||
{
|
||||
if (!_broadQuery.Resolve(lookupUid, ref lookup))
|
||||
return false;
|
||||
|
||||
var shape = new PolygonShape();
|
||||
shape.SetAsBox(localAABB);
|
||||
var transform = _physics.GetPhysicsTransform(lookupUid);
|
||||
return AnyEntitiesIntersecting(lookupUid, shape, transform, flags, ignored, lookup);
|
||||
}
|
||||
|
||||
public HashSet<EntityUid> GetLocalEntitiesIntersecting(EntityUid gridId, Vector2i gridIndices, float enlargement = TileEnlargementRadius, LookupFlags flags = DefaultFlags, MapGridComponent? gridComp = null)
|
||||
{
|
||||
// Technically this doesn't consider anything overlapping from outside the grid but is this an issue?
|
||||
var intersecting = new HashSet<EntityUid>();
|
||||
|
||||
GetLocalEntitiesIntersecting(gridId, gridIndices, intersecting, enlargement, flags, gridComp);
|
||||
return intersecting;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the entities intersecting the specified broadphase entity using a local AABB.
|
||||
/// </summary>
|
||||
@@ -25,8 +89,7 @@ public sealed partial class EntityLookupSystem
|
||||
|
||||
var localAABB = GetLocalBounds(localTile, tileSize);
|
||||
localAABB = localAABB.Enlarged(TileEnlargementRadius);
|
||||
AddLocalEntitiesIntersecting(gridUid, intersecting, localAABB, flags);
|
||||
AddContained(intersecting, flags);
|
||||
GetLocalEntitiesIntersecting(gridUid, localAABB, intersecting, flags);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -48,4 +111,40 @@ public sealed partial class EntityLookupSystem
|
||||
AddLocalEntitiesIntersecting(gridUid, intersecting, localBounds, flags);
|
||||
AddContained(intersecting, flags);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the entities intersecting any of the supplied tiles. Faster than doing each tile individually.
|
||||
/// </summary>
|
||||
public HashSet<EntityUid> GetLocalEntitiesIntersecting(EntityUid gridId, IEnumerable<Vector2i> gridIndices, LookupFlags flags = DefaultFlags)
|
||||
{
|
||||
var intersecting = new HashSet<EntityUid>();
|
||||
|
||||
// Technically this doesn't consider anything overlapping from outside the grid but is this an issue?
|
||||
if (!_gridQuery.TryGetComponent(gridId, out var mapGrid))
|
||||
return intersecting;
|
||||
|
||||
// TODO: You can probably decompose the indices into larger areas if you take in a hashset instead.
|
||||
foreach (var index in gridIndices)
|
||||
{
|
||||
GetLocalEntitiesIntersecting(gridId, index, intersecting, flags: flags, gridComp: mapGrid);
|
||||
}
|
||||
|
||||
return intersecting;
|
||||
}
|
||||
|
||||
public HashSet<EntityUid> GetLocalEntitiesIntersecting(BroadphaseComponent lookup, Box2 localAABB, LookupFlags flags = DefaultFlags)
|
||||
{
|
||||
var intersecting = new HashSet<EntityUid>();
|
||||
|
||||
AddLocalEntitiesIntersecting(lookup.Owner, intersecting, localAABB, flags, lookup);
|
||||
AddContained(intersecting, flags);
|
||||
|
||||
return intersecting;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public IEnumerable<EntityUid> GetLocalEntitiesIntersecting(TileRef tileRef, float enlargement = TileEnlargementRadius, LookupFlags flags = DefaultFlags)
|
||||
{
|
||||
return GetLocalEntitiesIntersecting(tileRef.GridUid, tileRef.GridIndices, enlargement, flags);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,6 +97,11 @@ public sealed partial class EntityLookupSystem : EntitySystem
|
||||
|
||||
public const float TileEnlargementRadius = -PhysicsConstants.PolygonRadius * 4f;
|
||||
|
||||
/// <summary>
|
||||
/// The minimum size an entity is assumed to be for point purposes.
|
||||
/// </summary>
|
||||
public const float LookupEpsilon = float.Epsilon * 10f;
|
||||
|
||||
/// <summary>
|
||||
/// Returns all non-grid entities. Consider using your own flags if you wish for a faster query.
|
||||
/// </summary>
|
||||
@@ -121,12 +126,11 @@ public sealed partial class EntityLookupSystem : EntitySystem
|
||||
SubscribeLocalEvent<MapChangedEvent>(OnMapChange);
|
||||
|
||||
_transform.OnGlobalMoveEvent += OnMove;
|
||||
EntityManager.EntityInitialized += OnEntityInit;
|
||||
|
||||
SubscribeLocalEvent<TransformComponent, PhysicsBodyTypeChangedEvent>(OnBodyTypeChange);
|
||||
SubscribeLocalEvent<PhysicsComponent, ComponentStartup>(OnBodyStartup);
|
||||
SubscribeLocalEvent<CollisionChangeEvent>(OnPhysicsUpdate);
|
||||
|
||||
EntityManager.EntityInitialized += OnEntityInit;
|
||||
}
|
||||
|
||||
private void OnBodyStartup(EntityUid uid, PhysicsComponent component, ComponentStartup args)
|
||||
@@ -354,8 +358,7 @@ public sealed partial class EntityLookupSystem : EntitySystem
|
||||
|
||||
private void AddPhysicsTree(EntityUid uid, EntityUid broadUid, BroadphaseComponent broadphase, TransformComponent xform, PhysicsComponent body, FixturesComponent fixtures)
|
||||
{
|
||||
var xformQuery = GetEntityQuery<TransformComponent>();
|
||||
var broadphaseXform = xformQuery.GetComponent(broadUid);
|
||||
var broadphaseXform = _xformQuery.GetComponent(broadUid);
|
||||
|
||||
if (broadphaseXform.MapID == MapId.Nullspace)
|
||||
return;
|
||||
@@ -363,7 +366,7 @@ public sealed partial class EntityLookupSystem : EntitySystem
|
||||
if (!_mapQuery.TryGetComponent(broadphaseXform.MapUid, out var physMap))
|
||||
throw new InvalidOperationException($"Physics Broadphase is missing physics map. {ToPrettyString(broadUid)}");
|
||||
|
||||
AddOrUpdatePhysicsTree(uid, broadUid, broadphase, broadphaseXform, physMap, xform, body, fixtures, xformQuery);
|
||||
AddOrUpdatePhysicsTree(uid, broadUid, broadphase, broadphaseXform, physMap, xform, body, fixtures);
|
||||
}
|
||||
|
||||
private void AddOrUpdatePhysicsTree(
|
||||
@@ -374,8 +377,7 @@ public sealed partial class EntityLookupSystem : EntitySystem
|
||||
PhysicsMapComponent physicsMap,
|
||||
TransformComponent xform,
|
||||
PhysicsComponent body,
|
||||
FixturesComponent manager,
|
||||
EntityQuery<TransformComponent> xformQuery)
|
||||
FixturesComponent manager)
|
||||
{
|
||||
DebugTools.Assert(!_container.IsEntityOrParentInContainer(body.Owner, null, xform));
|
||||
DebugTools.Assert(xform.Broadphase == null || xform.Broadphase == new BroadphaseData(broadphase.Owner, physicsMap.Owner, body.CanCollide, body.BodyType == BodyType.Static));
|
||||
@@ -385,7 +387,7 @@ public sealed partial class EntityLookupSystem : EntitySystem
|
||||
var tree = body.BodyType == BodyType.Static ? broadphase.StaticTree : broadphase.DynamicTree;
|
||||
|
||||
// TOOD optimize this. This function iterates UP through parents, while we are currently iterating down.
|
||||
var (worldPos, worldRot) = _transform.GetWorldPositionRotation(xform, xformQuery);
|
||||
var (worldPos, worldRot) = _transform.GetWorldPositionRotation(xform);
|
||||
var mapTransform = new Transform(worldPos, worldRot);
|
||||
|
||||
// TODO BROADPHASE PARENTING this just assumes local = world
|
||||
@@ -486,9 +488,6 @@ public sealed partial class EntityLookupSystem : EntitySystem
|
||||
return;
|
||||
|
||||
// We need to recursively update the cached data and remove children from the move buffer
|
||||
var xformQuery = GetEntityQuery<TransformComponent>();
|
||||
var fixturesQuery = GetEntityQuery<FixturesComponent>();
|
||||
|
||||
DebugTools.Assert(HasComp<MapGridComponent>(args.Sender));
|
||||
DebugTools.Assert(!newMap.IsValid() || HasComp<MapComponent>(newMap));
|
||||
DebugTools.Assert(!oldMap.IsValid() || HasComp<MapComponent>(oldMap));
|
||||
@@ -498,7 +497,7 @@ public sealed partial class EntityLookupSystem : EntitySystem
|
||||
|
||||
foreach (var child in args.Component._children)
|
||||
{
|
||||
RecursiveOnGridChangedMap(child, oldMap, newMap, oldBuffer, newBuffer, xformQuery, fixturesQuery);
|
||||
RecursiveOnGridChangedMap(child, oldMap, newMap, oldBuffer, newBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -507,17 +506,14 @@ public sealed partial class EntityLookupSystem : EntitySystem
|
||||
EntityUid oldMap,
|
||||
EntityUid newMap,
|
||||
Dictionary<FixtureProxy, Box2>? oldBuffer,
|
||||
Dictionary<FixtureProxy, Box2>? newBuffer,
|
||||
EntityQuery<TransformComponent> xformQuery,
|
||||
EntityQuery<FixturesComponent> fixturesQuery)
|
||||
Dictionary<FixtureProxy, Box2>? newBuffer)
|
||||
{
|
||||
if (!xformQuery.TryGetComponent(uid, out var xform))
|
||||
if (!_xformQuery.TryGetComponent(uid, out var xform))
|
||||
return;
|
||||
|
||||
|
||||
foreach (var child in xform._children)
|
||||
{
|
||||
RecursiveOnGridChangedMap(child, oldMap, newMap, oldBuffer, newBuffer, xformQuery, fixturesQuery);
|
||||
RecursiveOnGridChangedMap(child, oldMap, newMap, oldBuffer, newBuffer);
|
||||
}
|
||||
|
||||
if (xform.Broadphase == null || !xform.Broadphase.Value.CanCollide)
|
||||
@@ -526,7 +522,7 @@ public sealed partial class EntityLookupSystem : EntitySystem
|
||||
DebugTools.Assert(_netMan.IsClient || !xform.Broadphase.Value.PhysicsMap.IsValid() || xform.Broadphase.Value.PhysicsMap == oldMap);
|
||||
xform.Broadphase = xform.Broadphase.Value with { PhysicsMap = newMap };
|
||||
|
||||
if (!fixturesQuery.TryGetComponent(uid, out var fixtures))
|
||||
if (!_fixturesQuery.TryGetComponent(uid, out var fixtures))
|
||||
return;
|
||||
|
||||
if (oldBuffer != null)
|
||||
@@ -543,15 +539,17 @@ public sealed partial class EntityLookupSystem : EntitySystem
|
||||
|
||||
// TODO PERFORMANCE
|
||||
// track world position while recursively iterating down through children.
|
||||
var (worldPos, worldRot) = _transform.GetWorldPositionRotation(xform, xformQuery);
|
||||
var (worldPos, worldRot) = _transform.GetWorldPositionRotation(xform);
|
||||
var mapTransform = new Transform(worldPos, worldRot);
|
||||
|
||||
foreach (var fixture in fixtures.Fixtures.Values)
|
||||
{
|
||||
for (var i = 0; i < fixture.ProxyCount; i++)
|
||||
{
|
||||
var proxy = fixture.Proxies[i];
|
||||
newBuffer[proxy] = fixture.Shape.ComputeAABB(mapTransform, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateParent(EntityUid uid, TransformComponent xform, EntityUid oldParent)
|
||||
@@ -685,7 +683,7 @@ public sealed partial class EntityLookupSystem : EntitySystem
|
||||
}
|
||||
else
|
||||
{
|
||||
AddOrUpdatePhysicsTree(uid, broadUid, broadphase, broadphaseXform, physicsMap, xform, body, _fixturesQuery.GetComponent(uid), _xformQuery);
|
||||
AddOrUpdatePhysicsTree(uid, broadUid, broadphase, broadphaseXform, physicsMap, xform, body, _fixturesQuery.GetComponent(uid));
|
||||
}
|
||||
|
||||
if (xform.ChildCount == 0 || !recursive)
|
||||
|
||||
@@ -722,6 +722,21 @@ public abstract partial class SharedMapSystem
|
||||
return new GridTileEnumerator(uid, grid.Chunks.GetEnumerator(), grid.ChunkSize, ignoreEmpty);
|
||||
}
|
||||
|
||||
public void SetTile(Entity<MapGridComponent> grid, EntityCoordinates coordinates, Tile tile)
|
||||
{
|
||||
SetTile(grid.Owner, grid.Comp, coordinates, tile);
|
||||
}
|
||||
|
||||
public void SetTile(Entity<MapGridComponent> grid, Vector2i gridIndices, Tile tile)
|
||||
{
|
||||
SetTile(grid.Owner, grid.Comp, gridIndices, tile);
|
||||
}
|
||||
|
||||
public void SetTiles(Entity<MapGridComponent> grid, List<(Vector2i GridIndices, Tile Tile)> tiles)
|
||||
{
|
||||
SetTiles(grid.Owner, grid.Comp, tiles);
|
||||
}
|
||||
|
||||
public void SetTile(EntityUid uid, MapGridComponent grid, EntityCoordinates coords, Tile tile)
|
||||
{
|
||||
var localTile = CoordinatesToTile(uid, grid, coords);
|
||||
|
||||
@@ -23,15 +23,16 @@ public abstract partial class SharedTransformSystem
|
||||
TransformComponent xform,
|
||||
MapGridComponent oldGrid,
|
||||
MapGridComponent newGrid,
|
||||
Vector2i oldTilePos,
|
||||
Vector2i tilePos,
|
||||
EntityUid oldGridUid,
|
||||
EntityUid newGridUid,
|
||||
TransformComponent oldGridXform,
|
||||
TransformComponent newGridXform,
|
||||
EntityQuery<TransformComponent> xformQuery)
|
||||
Angle rotation)
|
||||
{
|
||||
// Bypass some of the expensive stuff in unanchoring / anchoring.
|
||||
_map.RemoveFromSnapGridCell(oldGridUid, oldGrid, tilePos, uid);
|
||||
_map.RemoveFromSnapGridCell(oldGridUid, oldGrid, oldTilePos, uid);
|
||||
_map.AddToSnapGridCell(newGridUid, newGrid, tilePos, uid);
|
||||
// TODO: Could do this re-parent way better.
|
||||
// Unfortunately we don't want any anchoring events to go out hence... this.
|
||||
@@ -40,21 +41,25 @@ public abstract partial class SharedTransformSystem
|
||||
newGridXform._children.Add(uid);
|
||||
xform._parent = newGridUid;
|
||||
xform._anchored = true;
|
||||
var oldPos = xform._localPosition;
|
||||
var oldRot = xform._localRotation;
|
||||
xform._localPosition = tilePos + newGrid.TileSizeHalfVector;
|
||||
xform._localRotation += rotation;
|
||||
|
||||
SetGridId(uid, xform, newGridUid, xformQuery);
|
||||
SetGridId(uid, xform, newGridUid, XformQuery);
|
||||
var reParent = new EntParentChangedMessage(uid, oldGridUid, xform.MapID, xform);
|
||||
RaiseLocalEvent(uid, ref reParent, true);
|
||||
var meta = MetaData(uid);
|
||||
var movEevee = new MoveEvent((uid, xform, meta),
|
||||
new EntityCoordinates(oldGridUid, xform._localPosition),
|
||||
new EntityCoordinates(oldGridUid, oldPos),
|
||||
new EntityCoordinates(newGridUid, xform._localPosition),
|
||||
xform.LocalRotation,
|
||||
oldRot,
|
||||
xform.LocalRotation,
|
||||
_gameTiming.ApplyingState);
|
||||
RaiseLocalEvent(uid, ref movEevee);
|
||||
InvokeGlobalMoveEvent(ref movEevee);
|
||||
|
||||
DebugTools.Assert(xformQuery.GetComponent(oldGridUid).MapID == xformQuery.GetComponent(newGridUid).MapID);
|
||||
DebugTools.Assert(XformQuery.GetComponent(oldGridUid).MapID == XformQuery.GetComponent(newGridUid).MapID);
|
||||
DebugTools.Assert(xform._anchored);
|
||||
|
||||
Dirty(uid, xform, meta);
|
||||
|
||||
@@ -91,7 +91,7 @@ namespace Robust.Shared.GameObjects
|
||||
|
||||
var aabb = _lookup.GetLocalBounds(tileIndices, grid.TileSize);
|
||||
|
||||
foreach (var entity in _lookup.GetEntitiesIntersecting(lookup, aabb, LookupFlags.Uncontained | LookupFlags.Approximate))
|
||||
foreach (var entity in _lookup.GetLocalEntitiesIntersecting(lookup, aabb, LookupFlags.Uncontained | LookupFlags.Approximate))
|
||||
{
|
||||
if (!XformQuery.TryGetComponent(entity, out var xform) || xform.ParentUid != gridId)
|
||||
continue;
|
||||
|
||||
@@ -156,6 +156,13 @@ public abstract class SharedUserInterfaceSystem : EntitySystem
|
||||
|
||||
OpenInterfaces.GetOrNew(session).Add(bui);
|
||||
RaiseLocalEvent(bui.Owner, new BoundUIOpenedEvent(bui.UiKey, bui.Owner, session));
|
||||
if (!bui._subscribedSessions.Contains(session))
|
||||
{
|
||||
// This can happen if Content closed a BUI from inside the event handler.
|
||||
// This will already have caused a redundant close event to be sent to the client, but whatever.
|
||||
// Just avoid doing the rest to avoid any state corruption shit.
|
||||
return false;
|
||||
}
|
||||
|
||||
RaiseNetworkEvent(new BoundUIWrapMessage(GetNetEntity(bui.Owner), new OpenBoundInterfaceMessage(), bui.UiKey), session.Channel);
|
||||
|
||||
|
||||
@@ -73,7 +73,9 @@ namespace Robust.Shared.Log
|
||||
|
||||
public void Log(LogLevel level, Exception? exception, string message, params object?[] args)
|
||||
{
|
||||
_sLogger.BindMessageTemplate(message, args, out var parsedTemplate, out var properties);
|
||||
if (!_sLogger.BindMessageTemplate(message, args, out var parsedTemplate, out var properties))
|
||||
return;
|
||||
|
||||
var msg = new LogEvent(DateTimeOffset.Now, level.ToSerilog(), exception, parsedTemplate, properties);
|
||||
LogInternal(Name, msg);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
@@ -42,7 +43,9 @@ namespace Robust.Shared.Map
|
||||
var gridSearchBox = Box2.UnitCentered.Scale(searchBoxSize).Translated(mapCoords.Position);
|
||||
|
||||
// find grids in search box
|
||||
var gridsInArea = mapManager.FindGridsIntersecting(mapCoords.MapId, gridSearchBox);
|
||||
var gridsInArea = new List<Entity<MapGridComponent>>();
|
||||
|
||||
mapManager.FindGridsIntersecting(mapCoords.MapId, gridSearchBox, ref gridsInArea);
|
||||
|
||||
// find closest grid intersecting our search box.
|
||||
gridUid = EntityUid.Invalid;
|
||||
@@ -57,7 +60,7 @@ namespace Robust.Shared.Map
|
||||
// TODO: Use CollisionManager to get nearest edge.
|
||||
|
||||
// figure out closest intersect
|
||||
var gridIntersect = gridSearchBox.Intersect(gridXform.WorldMatrix.TransformBox(grid.LocalAABB));
|
||||
var gridIntersect = gridSearchBox.Intersect(gridXform.WorldMatrix.TransformBox(grid.Comp.LocalAABB));
|
||||
var gridDist = (gridIntersect.Center - mapCoords.Position).LengthSquared();
|
||||
|
||||
if (gridDist >= distance)
|
||||
|
||||
@@ -6,6 +6,8 @@ using JetBrains.Annotations;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map.Components;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Physics.Collision.Shapes;
|
||||
|
||||
namespace Robust.Shared.Map
|
||||
{
|
||||
@@ -18,6 +20,9 @@ namespace Robust.Shared.Map
|
||||
/// </summary>
|
||||
public interface IMapManager
|
||||
{
|
||||
public const bool Approximate = false;
|
||||
public const bool IncludeMap = true;
|
||||
|
||||
[Obsolete("Use EntityQuery<MapGridComponent>")]
|
||||
IEnumerable<MapGridComponent> GetAllGrids();
|
||||
|
||||
@@ -102,82 +107,131 @@ namespace Robust.Shared.Map
|
||||
|
||||
IEnumerable<Entity<MapGridComponent>> GetAllGrids(MapId mapId);
|
||||
|
||||
#region MapId
|
||||
|
||||
public void FindGridsIntersecting(MapId mapId, IPhysShape shape, Transform transform,
|
||||
ref List<Entity<MapGridComponent>> grids, bool approx = Approximate, bool includeMap = IncludeMap);
|
||||
|
||||
public void FindGridsIntersecting(MapId mapId, PolygonShape shape, Transform transform, GridCallback callback,
|
||||
bool approx = Approximate, bool includeMap = IncludeMap);
|
||||
|
||||
public void FindGridsIntersecting(MapId mapId, Box2 worldAABB, GridCallback callback, bool approx = Approximate,
|
||||
bool includeMap = IncludeMap);
|
||||
|
||||
public void FindGridsIntersecting<TState>(MapId mapId, Box2 worldAABB, ref TState state,
|
||||
GridCallback<TState> callback, bool approx = Approximate, bool includeMap = IncludeMap);
|
||||
|
||||
public void FindGridsIntersecting(MapId mapId, Box2 worldAABB, ref List<Entity<MapGridComponent>> grids,
|
||||
bool approx = Approximate, bool includeMap = IncludeMap);
|
||||
|
||||
public void FindGridsIntersecting(MapId mapId, Box2Rotated worldBounds, GridCallback callback,
|
||||
bool approx = Approximate,
|
||||
bool includeMap = IncludeMap);
|
||||
|
||||
public void FindGridsIntersecting<TState>(MapId mapId, Box2Rotated worldBounds, ref TState state,
|
||||
GridCallback<TState> callback,
|
||||
bool approx = Approximate, bool includeMap = IncludeMap);
|
||||
|
||||
public void FindGridsIntersecting(MapId mapId, Box2Rotated worldBounds, ref List<Entity<MapGridComponent>> grids,
|
||||
bool approx = Approximate, bool includeMap = IncludeMap);
|
||||
|
||||
#endregion
|
||||
|
||||
#region MapEnt
|
||||
|
||||
public void FindGridsIntersecting(EntityUid mapEnt, PolygonShape shape, Transform transform, GridCallback callback,
|
||||
bool approx = Approximate, bool includeMap = IncludeMap);
|
||||
|
||||
public void FindGridsIntersecting<TState>(EntityUid mapEnt, IPhysShape shape, Transform transform,
|
||||
ref TState state, GridCallback<TState> callback, bool approx = Approximate, bool includeMap = IncludeMap);
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to find the map grid under the map location.
|
||||
/// Returns true if any grids overlap the specified shapes.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method will never return the map's default grid.
|
||||
/// </remarks>
|
||||
/// <param name="mapId">Map to search.</param>
|
||||
/// <param name="worldPos">Location on the map to check for a grid.</param>
|
||||
/// <param name="grid">Grid that was found, if any.</param>
|
||||
/// <returns>Returns true when a grid was found under the location.</returns>
|
||||
bool TryFindGridAt(MapId mapId, Vector2 worldPos, out EntityUid uid, [NotNullWhen(true)] out MapGridComponent? grid);
|
||||
public void FindGridsIntersecting(EntityUid mapEnt, List<IPhysShape> shapes, Transform transform,
|
||||
ref List<Entity<MapGridComponent>> entities, bool approx = Approximate, bool includeMap = IncludeMap);
|
||||
|
||||
public void FindGridsIntersecting(EntityUid mapEnt, IPhysShape shape, Transform transform,
|
||||
ref List<Entity<MapGridComponent>> grids, bool approx = Approximate, bool includeMap = IncludeMap);
|
||||
|
||||
public void FindGridsIntersecting(EntityUid mapEnt, Box2 worldAABB, GridCallback callback,
|
||||
bool approx = Approximate, bool includeMap = IncludeMap);
|
||||
|
||||
public void FindGridsIntersecting<TState>(EntityUid mapEnt, Box2 worldAABB, ref TState state,
|
||||
GridCallback<TState> callback, bool approx = Approximate, bool includeMap = IncludeMap);
|
||||
|
||||
public void FindGridsIntersecting(EntityUid mapEnt, Box2 worldAABB, ref List<Entity<MapGridComponent>> grids,
|
||||
bool approx = Approximate, bool includeMap = IncludeMap);
|
||||
|
||||
public void FindGridsIntersecting(EntityUid mapEnt, Box2Rotated worldBounds, GridCallback callback,
|
||||
bool approx = Approximate,
|
||||
bool includeMap = IncludeMap);
|
||||
|
||||
public void FindGridsIntersecting<TState>(EntityUid mapEnt, Box2Rotated worldBounds, ref TState state,
|
||||
GridCallback<TState> callback,
|
||||
bool approx = Approximate, bool includeMap = IncludeMap);
|
||||
|
||||
public void FindGridsIntersecting(EntityUid mapEnt, Box2Rotated worldBounds,
|
||||
ref List<Entity<MapGridComponent>> grids,
|
||||
bool approx = Approximate, bool includeMap = IncludeMap);
|
||||
|
||||
#endregion
|
||||
|
||||
#region TryFindGridAt
|
||||
|
||||
public bool TryFindGridAt(
|
||||
EntityUid mapEnt,
|
||||
Vector2 worldPos,
|
||||
out EntityUid uid,
|
||||
[NotNullWhen(true)] out MapGridComponent? grid);
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to find the map grid under the map location.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method will never return the map's default grid.
|
||||
/// </remarks>
|
||||
/// <param name="mapId">Map to search.</param>
|
||||
/// <param name="worldPos">Location on the map to check for a grid.</param>
|
||||
/// <param name="grid">Grid that was found, if any.</param>
|
||||
/// <returns>Returns true when a grid was found under the location.</returns>
|
||||
bool TryFindGridAt(EntityUid mapId, Vector2 worldPos, out EntityUid uid, [NotNullWhen(true)] out MapGridComponent? grid);
|
||||
public bool TryFindGridAt(MapId mapId, Vector2 worldPos, out EntityUid uid,
|
||||
[NotNullWhen(true)] out MapGridComponent? grid);
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to find the map grid under the map location.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method will never return the map's default grid.
|
||||
/// </remarks>
|
||||
/// <param name="mapId">Map to search.</param>
|
||||
/// <param name="worldPos">Location on the map to check for a grid.</param>
|
||||
/// <param name="grid">Grid that was found, if any.</param>
|
||||
/// <returns>Returns true when a grid was found under the location.</returns>
|
||||
bool TryFindGridAt(MapId mapId, Vector2 worldPos, EntityQuery<TransformComponent> query, out EntityUid uid, [NotNullWhen(true)] out MapGridComponent? grid);
|
||||
public bool TryFindGridAt(MapCoordinates mapCoordinates, out EntityUid uid,
|
||||
[NotNullWhen(true)] out MapGridComponent? grid);
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to find the map grid under the map location.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method will never return the map's default grid.
|
||||
/// </remarks>
|
||||
/// <param name="mapCoordinates">Location on the map to check for a grid.</param>
|
||||
/// <param name="grid">Grid that was found, if any.</param>
|
||||
/// <returns>Returns true when a grid was found under the location.</returns>
|
||||
bool TryFindGridAt(MapCoordinates mapCoordinates, out EntityUid uid, [NotNullWhen(true)] out MapGridComponent? grid);
|
||||
#endregion
|
||||
|
||||
void FindGridsIntersecting(MapId mapId, Box2 worldAABB, GridCallback callback, bool approx = false, bool includeMap = true);
|
||||
#region Obsolete
|
||||
|
||||
void FindGridsIntersecting<TState>(MapId mapId, Box2 worldAABB, ref TState state, GridCallback<TState> callback, bool approx = false, bool includeMap = true);
|
||||
[Obsolete]
|
||||
public bool TryFindGridAt(MapId mapId, Vector2 worldPos, EntityQuery<TransformComponent> query, out EntityUid uid, [NotNullWhen(true)] out MapGridComponent? grid)
|
||||
{
|
||||
return TryFindGridAt(mapId, worldPos, out uid, out grid);
|
||||
}
|
||||
|
||||
void FindGridsIntersecting(MapId mapId, Box2 worldAABB, ref List<Entity<MapGridComponent>> state, bool approx = false, bool includeMap = true);
|
||||
void FindGridsIntersecting(EntityUid map, Box2 worldAABB, ref List<Entity<MapGridComponent>> state, bool approx = false, bool includeMap = true);
|
||||
[Obsolete]
|
||||
public IEnumerable<MapGridComponent> FindGridsIntersecting(MapId mapId, Box2 worldAabb, bool approx = false, bool includeMap = true)
|
||||
{
|
||||
var grids = new List<Entity<MapGridComponent>>();
|
||||
FindGridsIntersecting(mapId, worldAabb, ref grids, approx, includeMap);
|
||||
|
||||
void FindGridsIntersecting(MapId mapId, Box2Rotated worldBounds, GridCallback callback, bool approx = false, bool includeMap = true);
|
||||
foreach (var grid in grids)
|
||||
{
|
||||
yield return grid.Comp;
|
||||
}
|
||||
}
|
||||
|
||||
void FindGridsIntersecting<TState>(MapId mapId, Box2Rotated worldBounds, ref TState state, GridCallback<TState> callback, bool approx = false, bool includeMap = true);
|
||||
[Obsolete]
|
||||
public IEnumerable<MapGridComponent> FindGridsIntersecting(MapId mapId, Box2Rotated worldArea, bool approx = false, bool includeMap = true)
|
||||
{
|
||||
var grids = new List<Entity<MapGridComponent>>();
|
||||
FindGridsIntersecting(mapId, worldArea, ref grids, approx, includeMap);
|
||||
|
||||
void FindGridsIntersecting(MapId mapId, Box2Rotated worldBounds, ref List<Entity<MapGridComponent>> state, bool approx = false, bool includeMap = true);
|
||||
foreach (var grid in grids)
|
||||
{
|
||||
yield return grid.Comp;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the grids intersecting this AABB.
|
||||
/// </summary>
|
||||
/// <param name="mapId">The relevant MapID</param>
|
||||
/// <param name="worldAabb">The AABB to intersect</param>
|
||||
/// <param name="approx">Set to false if you wish to accurately get the grid bounds per-tile.</param>
|
||||
/// <returns></returns>
|
||||
IEnumerable<MapGridComponent> FindGridsIntersecting(MapId mapId, Box2 worldAabb, bool approx = false, bool includeMap = true);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the grids intersecting this AABB.
|
||||
/// </summary>
|
||||
/// <param name="mapId">The relevant MapID</param>
|
||||
/// <param name="worldArea">The AABB to intersect</param>
|
||||
/// <param name="approx">Set to false if you wish to accurately get the grid bounds per-tile.</param>
|
||||
IEnumerable<MapGridComponent> FindGridsIntersecting(MapId mapId, Box2Rotated worldArea, bool approx = false, bool includeMap = true);
|
||||
#endregion
|
||||
|
||||
void DeleteGrid(EntityUid euid);
|
||||
|
||||
|
||||
@@ -4,228 +4,284 @@ using System.Diagnostics.CodeAnalysis;
|
||||
using System.Numerics;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map.Components;
|
||||
using Robust.Shared.Map.Enumerators;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Physics.Collision.Shapes;
|
||||
|
||||
namespace Robust.Shared.Map;
|
||||
|
||||
internal partial class MapManager
|
||||
{
|
||||
[Obsolete("Use the FindGridsIntersecting callback")]
|
||||
public IEnumerable<MapGridComponent> FindGridsIntersecting(MapId mapId, Box2Rotated bounds, bool approx = false, bool includeMap = true)
|
||||
{
|
||||
var aabb = bounds.CalcBoundingBox();
|
||||
// TODO: We can do slower GJK checks to check if 2 bounds actually intersect, but WYCI.
|
||||
return FindGridsIntersecting(mapId, aabb, includeMap, approx);
|
||||
}
|
||||
|
||||
public void FindGridsIntersecting(MapId mapId, Box2 worldAABB, GridCallback callback, bool approx = false, bool includeMap = true)
|
||||
{
|
||||
if (_mapEntities.TryGetValue(mapId, out var map))
|
||||
FindGridsIntersecting(map, worldAABB, callback, approx, includeMap);
|
||||
}
|
||||
|
||||
public void FindGridsIntersecting(EntityUid mapEnt, Box2 worldAABB, GridCallback callback, bool approx = false, bool includeMap = true)
|
||||
{
|
||||
if (!EntityManager.TryGetComponent<GridTreeComponent>(mapEnt, out var gridTree))
|
||||
return;
|
||||
|
||||
var state = (worldAABB, gridTree.Tree, callback, approx, this, _transformSystem);
|
||||
|
||||
gridTree.Tree.Query(ref state,
|
||||
static (ref (Box2 worldAABB,
|
||||
B2DynamicTree<(EntityUid Uid, MapGridComponent Grid)> gridTree,
|
||||
GridCallback callback,
|
||||
bool approx,
|
||||
MapManager mapManager,
|
||||
SharedTransformSystem xformSystem) tuple,
|
||||
DynamicTree.Proxy proxy) =>
|
||||
{
|
||||
var data = tuple.gridTree.GetUserData(proxy);
|
||||
|
||||
if (!tuple.approx && !tuple.mapManager.IsIntersecting(tuple.worldAABB, data.Uid, data.Grid))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return tuple.callback(data.Uid, data.Grid);
|
||||
}, worldAABB); ;
|
||||
|
||||
if (includeMap && EntityManager.TryGetComponent<MapGridComponent>(mapEnt, out var grid))
|
||||
{
|
||||
callback(mapEnt, grid);
|
||||
}
|
||||
}
|
||||
|
||||
public void FindGridsIntersecting<TState>(MapId mapId, Box2 worldAABB, ref TState state, GridCallback<TState> callback, bool approx = false, bool includeMap = true)
|
||||
{
|
||||
if (_mapEntities.TryGetValue(mapId, out var map))
|
||||
FindGridsIntersecting(map, worldAABB, ref state, callback, approx, includeMap);
|
||||
}
|
||||
|
||||
public void FindGridsIntersecting<TState>(EntityUid mapUid, Box2 worldAABB, ref TState state, GridCallback<TState> callback, bool approx = false, bool includeMap = true)
|
||||
{
|
||||
if (!EntityManager.TryGetComponent<GridTreeComponent>(mapUid, out var gridTree))
|
||||
return;
|
||||
|
||||
if (includeMap && EntityManager.TryGetComponent<MapGridComponent>(mapUid, out var grid))
|
||||
{
|
||||
callback(mapUid, grid, ref state);
|
||||
}
|
||||
|
||||
var state2 = (state, worldAABB, gridTree.Tree, callback, approx, this, _transformSystem);
|
||||
|
||||
gridTree.Tree.Query(ref state2, static (ref (
|
||||
TState state,
|
||||
Box2 worldAABB,
|
||||
B2DynamicTree<(EntityUid Uid, MapGridComponent Grid)> gridTree,
|
||||
GridCallback<TState> callback,
|
||||
bool approx,
|
||||
MapManager mapManager,
|
||||
SharedTransformSystem xformSystem) tuple,
|
||||
DynamicTree.Proxy proxy) =>
|
||||
{
|
||||
var data = tuple.gridTree.GetUserData(proxy);
|
||||
|
||||
if (!tuple.approx && !tuple.mapManager.IsIntersecting(tuple.worldAABB, data.Uid, data.Grid))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return tuple.callback(data.Uid, data.Grid, ref tuple.state);
|
||||
}, worldAABB);
|
||||
|
||||
state = state2.state;
|
||||
}
|
||||
|
||||
public void FindGridsIntersecting(MapId mapId, Box2 worldAABB, ref List<Entity<MapGridComponent>> state,
|
||||
bool approx = false, bool includeMap = true)
|
||||
{
|
||||
if (_mapEntities.TryGetValue(mapId, out var map))
|
||||
FindGridsIntersecting(map, worldAABB, ref state, approx, includeMap);
|
||||
}
|
||||
|
||||
public void FindGridsIntersecting(EntityUid map, Box2 worldAABB, ref List<Entity<MapGridComponent>> state,
|
||||
bool approx = false, bool includeMap = true)
|
||||
{
|
||||
FindGridsIntersecting(map, worldAABB, ref state, static (EntityUid uid, MapGridComponent grid,
|
||||
ref List<Entity<MapGridComponent>> list) =>
|
||||
{
|
||||
list.Add((uid, grid));
|
||||
return true;
|
||||
}, approx, includeMap);
|
||||
}
|
||||
|
||||
public void FindGridsIntersecting(EntityUid mapId, Box2Rotated worldBounds, GridCallback callback, bool approx = false,
|
||||
bool includeMap = true)
|
||||
{
|
||||
FindGridsIntersecting(mapId, worldBounds.CalcBoundingBox(), callback, approx, includeMap);
|
||||
}
|
||||
|
||||
public void FindGridsIntersecting(MapId mapId, Box2Rotated worldBounds, GridCallback callback, bool approx = false,
|
||||
bool includeMap = true)
|
||||
{
|
||||
FindGridsIntersecting(mapId, worldBounds.CalcBoundingBox(), callback, approx, includeMap);
|
||||
}
|
||||
|
||||
public void FindGridsIntersecting<TState>(EntityUid mapId, Box2Rotated worldBounds, ref TState state, GridCallback<TState> callback,
|
||||
bool approx = false, bool includeMap = true)
|
||||
{
|
||||
FindGridsIntersecting(mapId, worldBounds.CalcBoundingBox(), ref state, callback, approx, includeMap);
|
||||
}
|
||||
|
||||
public void FindGridsIntersecting<TState>(MapId mapId, Box2Rotated worldBounds, ref TState state, GridCallback<TState> callback,
|
||||
bool approx = false, bool includeMap = true)
|
||||
{
|
||||
FindGridsIntersecting(mapId, worldBounds.CalcBoundingBox(), ref state, callback, approx, includeMap);
|
||||
}
|
||||
|
||||
public void FindGridsIntersecting(MapId mapId, Box2Rotated worldBounds, ref List<Entity<MapGridComponent>> state,
|
||||
bool approx = false, bool includeMap = true)
|
||||
{
|
||||
if (_mapEntities.TryGetValue(mapId, out var map))
|
||||
FindGridsIntersecting(map, worldBounds, ref state, approx, includeMap);
|
||||
}
|
||||
|
||||
public void FindGridsIntersecting(EntityUid mapId, Box2Rotated worldBounds, ref List<Entity<MapGridComponent>> state,
|
||||
bool approx = false, bool includeMap = true)
|
||||
{
|
||||
FindGridsIntersecting(mapId, worldBounds, ref state, static (EntityUid uid, MapGridComponent grid,
|
||||
ref List<Entity<MapGridComponent>> list) =>
|
||||
{
|
||||
list.Add((uid, grid));
|
||||
return true;
|
||||
}, approx, includeMap);
|
||||
}
|
||||
|
||||
private bool IsIntersecting(
|
||||
Box2 aabb,
|
||||
EntityUid gridUid,
|
||||
MapGridComponent grid)
|
||||
ChunkEnumerator enumerator,
|
||||
IPhysShape shape,
|
||||
Transform shapeTransform,
|
||||
EntityUid gridUid)
|
||||
{
|
||||
var (worldPos, worldRot, matrix, invMatrix) = _transformSystem.GetWorldPositionRotationMatrixWithInv(gridUid);
|
||||
var overlap = matrix.TransformBox(grid.LocalAABB).Intersect(aabb);
|
||||
var localAABB = invMatrix.TransformBox(overlap);
|
||||
var gridTransform = _physics.GetPhysicsTransform(gridUid);
|
||||
|
||||
if (_physicsQuery.HasComponent(gridUid))
|
||||
while (enumerator.MoveNext(out var chunk))
|
||||
{
|
||||
var enumerator = _mapSystem.GetLocalMapChunks(gridUid, grid, localAABB);
|
||||
|
||||
var transform = new Transform(worldPos, worldRot);
|
||||
|
||||
while (enumerator.MoveNext(out var chunk))
|
||||
foreach (var fixture in chunk.Fixtures.Values)
|
||||
{
|
||||
foreach (var fixture in chunk.Fixtures.Values)
|
||||
for (var j = 0; j < fixture.Shape.ChildCount; j++)
|
||||
{
|
||||
for (var j = 0; j < fixture.Shape.ChildCount; j++)
|
||||
if (_manifolds.TestOverlap(shape, 0, fixture.Shape, j, shapeTransform, gridTransform))
|
||||
{
|
||||
// TODO: Should do shape intersects given this is supposed to be non-approx.
|
||||
if (!fixture.Shape.ComputeAABB(transform, j).Intersects(aabb)) continue;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return grid.ChunkCount == 0 && aabb.Contains(worldPos);
|
||||
}
|
||||
|
||||
[Obsolete("Use the FindGridsIntersecting callback")]
|
||||
public IEnumerable<MapGridComponent> FindGridsIntersecting(MapId mapId, Box2 worldAabb, bool approx = false, bool includeMap = true)
|
||||
{
|
||||
var grids = new List<MapGridComponent>();
|
||||
var state = grids;
|
||||
|
||||
FindGridsIntersecting(mapId, worldAabb, ref state,
|
||||
(EntityUid _, MapGridComponent grid, ref List<MapGridComponent> list) =>
|
||||
{
|
||||
list.Add(grid);
|
||||
return true;
|
||||
}, approx);
|
||||
|
||||
return grids;
|
||||
}
|
||||
|
||||
public bool TryFindGridAt(
|
||||
MapId mapId,
|
||||
Vector2 worldPos,
|
||||
EntityQuery<TransformComponent> xformQuery,
|
||||
out EntityUid uid,
|
||||
[NotNullWhen(true)] out MapGridComponent? grid)
|
||||
{
|
||||
if (_mapEntities.TryGetValue(mapId, out var map))
|
||||
return TryFindGridAt(map, worldPos, xformQuery, out uid, out grid);
|
||||
|
||||
uid = default;
|
||||
grid = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
#region MapId
|
||||
|
||||
public void FindGridsIntersecting(MapId mapId, IPhysShape shape, Transform transform,
|
||||
ref List<Entity<MapGridComponent>> grids, bool approx = IMapManager.Approximate, bool includeMap = IMapManager.IncludeMap)
|
||||
{
|
||||
if (_mapEntities.TryGetValue(mapId, out var mapEnt))
|
||||
FindGridsIntersecting(mapEnt, shape, transform, ref grids, approx, includeMap);
|
||||
}
|
||||
|
||||
public void FindGridsIntersecting(MapId mapId, PolygonShape shape, Transform transform, GridCallback callback, bool approx = IMapManager.Approximate, bool includeMap = IMapManager.IncludeMap)
|
||||
{
|
||||
if (_mapEntities.TryGetValue(mapId, out var mapEnt))
|
||||
FindGridsIntersecting(mapEnt, shape, transform, callback, includeMap, approx);
|
||||
}
|
||||
|
||||
public void FindGridsIntersecting(MapId mapId, Box2 worldAABB, GridCallback callback, bool approx = IMapManager.Approximate, bool includeMap = IMapManager.IncludeMap)
|
||||
{
|
||||
if (_mapEntities.TryGetValue(mapId, out var mapEnt))
|
||||
FindGridsIntersecting(mapEnt, worldAABB, callback, approx, includeMap);
|
||||
}
|
||||
|
||||
public void FindGridsIntersecting<TState>(MapId mapId, Box2 worldAABB, ref TState state, GridCallback<TState> callback, bool approx = IMapManager.Approximate, bool includeMap = IMapManager.IncludeMap)
|
||||
{
|
||||
if (_mapEntities.TryGetValue(mapId, out var map))
|
||||
FindGridsIntersecting(map, worldAABB, ref state, callback, approx, includeMap);
|
||||
}
|
||||
|
||||
public void FindGridsIntersecting(MapId mapId, Box2 worldAABB, ref List<Entity<MapGridComponent>> grids,
|
||||
bool approx = IMapManager.Approximate, bool includeMap = IMapManager.IncludeMap)
|
||||
{
|
||||
if (_mapEntities.TryGetValue(mapId, out var map))
|
||||
FindGridsIntersecting(map, worldAABB, ref grids, approx, includeMap);
|
||||
}
|
||||
|
||||
public void FindGridsIntersecting(MapId mapId, Box2Rotated worldBounds, GridCallback callback, bool approx = IMapManager.Approximate,
|
||||
bool includeMap = IMapManager.IncludeMap)
|
||||
{
|
||||
if (_mapEntities.TryGetValue(mapId, out var mapEnt))
|
||||
FindGridsIntersecting(mapEnt, worldBounds, callback, approx, includeMap);
|
||||
}
|
||||
|
||||
public void FindGridsIntersecting<TState>(MapId mapId, Box2Rotated worldBounds, ref TState state, GridCallback<TState> callback,
|
||||
bool approx = IMapManager.Approximate, bool includeMap = IMapManager.IncludeMap)
|
||||
{
|
||||
if (_mapEntities.TryGetValue(mapId, out var mapEnt))
|
||||
FindGridsIntersecting(mapEnt, worldBounds, ref state, callback, approx, includeMap);
|
||||
}
|
||||
|
||||
public void FindGridsIntersecting(MapId mapId, Box2Rotated worldBounds, ref List<Entity<MapGridComponent>> grids,
|
||||
bool approx = IMapManager.Approximate, bool includeMap = IMapManager.IncludeMap)
|
||||
{
|
||||
if (_mapEntities.TryGetValue(mapId, out var mapEnt))
|
||||
FindGridsIntersecting(mapEnt, worldBounds, ref grids, approx, includeMap);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region MapEnt
|
||||
|
||||
public void FindGridsIntersecting(EntityUid mapEnt, PolygonShape shape, Transform transform, GridCallback callback, bool approx = IMapManager.Approximate, bool includeMap = IMapManager.IncludeMap)
|
||||
{
|
||||
if (!_gridTreeQuery.TryGetComponent(mapEnt, out var gridTree))
|
||||
return;
|
||||
|
||||
if (includeMap && _gridQuery.TryGetComponent(mapEnt, out var mapGrid))
|
||||
{
|
||||
callback(mapEnt, mapGrid);
|
||||
}
|
||||
|
||||
var worldAABB = shape.ComputeAABB(transform, 0);
|
||||
|
||||
var gridState = new GridQueryState(
|
||||
callback,
|
||||
worldAABB,
|
||||
shape,
|
||||
transform,
|
||||
gridTree.Tree,
|
||||
_mapSystem,
|
||||
this,
|
||||
_transformSystem,
|
||||
approx);
|
||||
|
||||
|
||||
gridTree.Tree.Query(ref gridState, static (ref GridQueryState state, DynamicTree.Proxy proxy) =>
|
||||
{
|
||||
// Even for approximate we'll check if any chunks roughly overlap.
|
||||
var data = state.Tree.GetUserData(proxy);
|
||||
var gridInvMatrix = state.TransformSystem.GetInvWorldMatrix(data.Uid);
|
||||
var localAABB = gridInvMatrix.TransformBox(state.WorldAABB);
|
||||
|
||||
var overlappingChunks = state.MapSystem.GetLocalMapChunks(data.Uid, data.Grid, localAABB);
|
||||
|
||||
if (state.Approximate)
|
||||
{
|
||||
if (!overlappingChunks.MoveNext(out _))
|
||||
return true;
|
||||
}
|
||||
else if (!state.MapManager.IsIntersecting(overlappingChunks, state.Shape, state.Transform, data.Uid))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
state.Callback(data.Uid, data.Grid);
|
||||
|
||||
return true;
|
||||
}, worldAABB);
|
||||
}
|
||||
|
||||
public void FindGridsIntersecting<TState>(EntityUid mapEnt, IPhysShape shape, Transform transform,
|
||||
ref TState state, GridCallback<TState> callback, bool approx = IMapManager.Approximate, bool includeMap = IMapManager.IncludeMap)
|
||||
{
|
||||
if (!_gridTreeQuery.TryGetComponent(mapEnt, out var gridTree))
|
||||
return;
|
||||
|
||||
if (includeMap && _gridQuery.TryGetComponent(mapEnt, out var mapGrid))
|
||||
{
|
||||
callback(mapEnt, mapGrid, ref state);
|
||||
}
|
||||
|
||||
var worldAABB = shape.ComputeAABB(transform, 0);
|
||||
|
||||
var gridState = new GridQueryState<TState>(
|
||||
callback,
|
||||
state,
|
||||
worldAABB,
|
||||
shape,
|
||||
transform,
|
||||
gridTree.Tree,
|
||||
_mapSystem,
|
||||
this,
|
||||
_transformSystem,
|
||||
approx);
|
||||
|
||||
|
||||
gridTree.Tree.Query(ref gridState, static (ref GridQueryState<TState> state, DynamicTree.Proxy proxy) =>
|
||||
{
|
||||
// Even for approximate we'll check if any chunks roughly overlap.
|
||||
var data = state.Tree.GetUserData(proxy);
|
||||
var gridInvMatrix = state.TransformSystem.GetInvWorldMatrix(data.Uid);
|
||||
var localAABB = gridInvMatrix.TransformBox(state.WorldAABB);
|
||||
|
||||
var overlappingChunks = state.MapSystem.GetLocalMapChunks(data.Uid, data.Grid, localAABB);
|
||||
|
||||
if (state.Approximate)
|
||||
{
|
||||
if (!overlappingChunks.MoveNext(out _))
|
||||
return true;
|
||||
}
|
||||
else if (!state.MapManager.IsIntersecting(overlappingChunks, state.Shape, state.Transform, data.Uid))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var callbackState = state.State;
|
||||
var result = state.Callback(data.Uid, data.Grid, ref callbackState);
|
||||
state.State = callbackState;
|
||||
|
||||
return result;
|
||||
}, worldAABB);
|
||||
|
||||
// By-ref things
|
||||
state = gridState.State;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if any grids overlap the specified shapes.
|
||||
/// </summary>
|
||||
public void FindGridsIntersecting(EntityUid mapEnt, List<IPhysShape> shapes, Transform transform, ref List<Entity<MapGridComponent>> entities, bool approx = IMapManager.Approximate, bool includeMap = IMapManager.IncludeMap)
|
||||
{
|
||||
foreach (var shape in shapes)
|
||||
{
|
||||
FindGridsIntersecting(mapEnt, shape, transform, ref entities);
|
||||
}
|
||||
}
|
||||
|
||||
public void FindGridsIntersecting(EntityUid mapEnt, IPhysShape shape, Transform transform,
|
||||
ref List<Entity<MapGridComponent>> grids, bool approx = IMapManager.Approximate, bool includeMap = IMapManager.IncludeMap)
|
||||
{
|
||||
var state = grids;
|
||||
|
||||
FindGridsIntersecting(mapEnt, shape, transform, ref state,
|
||||
static (EntityUid uid, MapGridComponent grid, ref List<Entity<MapGridComponent>> list) =>
|
||||
{
|
||||
list.Add((uid, grid));
|
||||
return true;
|
||||
}, approx, includeMap);
|
||||
}
|
||||
|
||||
public void FindGridsIntersecting(EntityUid mapEnt, Box2 worldAABB, GridCallback callback, bool approx = IMapManager.Approximate, bool includeMap = IMapManager.IncludeMap)
|
||||
{
|
||||
var shape = new PolygonShape();
|
||||
shape.SetAsBox(worldAABB);
|
||||
FindGridsIntersecting(mapEnt, shape, Transform.Empty, callback, approx, includeMap);
|
||||
}
|
||||
|
||||
public void FindGridsIntersecting<TState>(EntityUid mapEnt, Box2 worldAABB, ref TState state, GridCallback<TState> callback, bool approx = IMapManager.Approximate, bool includeMap = IMapManager.IncludeMap)
|
||||
{
|
||||
var shape = new PolygonShape();
|
||||
shape.SetAsBox(worldAABB);
|
||||
FindGridsIntersecting(mapEnt, shape, Transform.Empty, ref state, callback, approx, includeMap);
|
||||
}
|
||||
|
||||
public void FindGridsIntersecting(EntityUid mapEnt, Box2 worldAABB, ref List<Entity<MapGridComponent>> grids,
|
||||
bool approx = IMapManager.Approximate, bool includeMap = IMapManager.IncludeMap)
|
||||
{
|
||||
var shape = new PolygonShape();
|
||||
shape.SetAsBox(worldAABB);
|
||||
FindGridsIntersecting(mapEnt, shape, Transform.Empty, ref grids, approx, includeMap);
|
||||
}
|
||||
|
||||
public void FindGridsIntersecting(EntityUid mapEnt, Box2Rotated worldBounds, GridCallback callback, bool approx = IMapManager.Approximate,
|
||||
bool includeMap = IMapManager.IncludeMap)
|
||||
{
|
||||
var shape = new PolygonShape();
|
||||
shape.Set(worldBounds);
|
||||
|
||||
FindGridsIntersecting(mapEnt, shape, Transform.Empty, callback, approx, includeMap);
|
||||
}
|
||||
|
||||
public void FindGridsIntersecting<TState>(EntityUid mapEnt, Box2Rotated worldBounds, ref TState state, GridCallback<TState> callback,
|
||||
bool approx = IMapManager.Approximate, bool includeMap = IMapManager.IncludeMap)
|
||||
{
|
||||
var shape = new PolygonShape();
|
||||
shape.Set(worldBounds);
|
||||
|
||||
FindGridsIntersecting(mapEnt, shape, Transform.Empty, ref state, callback, approx, includeMap);
|
||||
}
|
||||
|
||||
public void FindGridsIntersecting(EntityUid mapEnt, Box2Rotated worldBounds, ref List<Entity<MapGridComponent>> grids,
|
||||
bool approx = IMapManager.Approximate, bool includeMap = IMapManager.IncludeMap)
|
||||
{
|
||||
var shape = new PolygonShape();
|
||||
shape.Set(worldBounds);
|
||||
|
||||
FindGridsIntersecting(mapEnt, shape, Transform.Empty, ref grids, approx, includeMap);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region TryFindGridAt
|
||||
|
||||
public bool TryFindGridAt(
|
||||
EntityUid mapId,
|
||||
EntityUid mapEnt,
|
||||
Vector2 worldPos,
|
||||
EntityQuery<TransformComponent> xformQuery,
|
||||
out EntityUid uid,
|
||||
[NotNullWhen(true)] out MapGridComponent? grid)
|
||||
{
|
||||
@@ -238,7 +294,7 @@ internal partial class MapManager
|
||||
grid = null;
|
||||
var state = (uid, grid, worldPos, _mapSystem, _transformSystem);
|
||||
|
||||
FindGridsIntersecting(mapId, aabb, ref state, static (EntityUid iUid, MapGridComponent iGrid, ref (
|
||||
FindGridsIntersecting(mapEnt, aabb, ref state, static (EntityUid iUid, MapGridComponent iGrid, ref (
|
||||
EntityUid uid,
|
||||
MapGridComponent? grid,
|
||||
Vector2 worldPos,
|
||||
@@ -270,11 +326,11 @@ internal partial class MapManager
|
||||
tuple.uid = iUid;
|
||||
tuple.grid = iGrid;
|
||||
return false;
|
||||
}, approx: true);
|
||||
}, approx: true, includeMap: false);
|
||||
|
||||
if (state.grid == null && EntityManager.TryGetComponent<MapGridComponent>(mapId, out var mapGrid))
|
||||
if (state.grid == null && _gridQuery.TryGetComponent(mapEnt, out var mapGrid))
|
||||
{
|
||||
uid = mapId;
|
||||
uid = mapEnt;
|
||||
grid = mapGrid;
|
||||
return true;
|
||||
}
|
||||
@@ -284,21 +340,13 @@ internal partial class MapManager
|
||||
return grid != null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to find the map grid under the map location.
|
||||
/// </summary>
|
||||
public bool TryFindGridAt(EntityUid mapId, Vector2 worldPos, out EntityUid uid, [NotNullWhen(true)] out MapGridComponent? grid)
|
||||
{
|
||||
return TryFindGridAt(mapId, worldPos, _xformQuery, out uid, out grid);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to find the map grid under the map location.
|
||||
/// </summary>
|
||||
public bool TryFindGridAt(MapId mapId, Vector2 worldPos, out EntityUid uid, [NotNullWhen(true)] out MapGridComponent? grid)
|
||||
{
|
||||
if (_mapEntities.TryGetValue(mapId, out var map))
|
||||
return TryFindGridAt(map, worldPos, _xformQuery, out uid, out grid);
|
||||
return TryFindGridAt(map, worldPos, out uid, out grid);
|
||||
|
||||
uid = default;
|
||||
grid = null;
|
||||
@@ -312,4 +360,29 @@ internal partial class MapManager
|
||||
{
|
||||
return TryFindGridAt(mapCoordinates.MapId, mapCoordinates.Position, out uid, out grid);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private readonly record struct GridQueryState(
|
||||
GridCallback Callback,
|
||||
Box2 WorldAABB,
|
||||
IPhysShape Shape,
|
||||
Transform Transform,
|
||||
B2DynamicTree<(EntityUid Uid, MapGridComponent Grid)> Tree,
|
||||
SharedMapSystem MapSystem,
|
||||
MapManager MapManager,
|
||||
SharedTransformSystem TransformSystem,
|
||||
bool Approximate);
|
||||
|
||||
private record struct GridQueryState<TState>(
|
||||
GridCallback<TState> Callback,
|
||||
TState State,
|
||||
Box2 WorldAABB,
|
||||
IPhysShape Shape,
|
||||
Transform Transform,
|
||||
B2DynamicTree<(EntityUid Uid, MapGridComponent Grid)> Tree,
|
||||
SharedMapSystem MapSystem,
|
||||
MapManager MapManager,
|
||||
SharedTransformSystem TransformSystem,
|
||||
bool Approximate);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,10 @@ using Robust.Shared.IoC;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Map.Components;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Physics.Collision;
|
||||
using Robust.Shared.Physics.Components;
|
||||
using Robust.Shared.Physics.Systems;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
@@ -16,19 +19,29 @@ internal partial class MapManager : IMapManagerInternal, IEntityEventSubscriber
|
||||
{
|
||||
[field: Dependency] public IGameTiming GameTiming { get; } = default!;
|
||||
[field: Dependency] public IEntityManager EntityManager { get; } = default!;
|
||||
[Dependency] private readonly IManifoldManager _manifolds = default!;
|
||||
|
||||
[Dependency] private readonly IConsoleHost _conhost = default!;
|
||||
|
||||
private ISawmill _sawmill = default!;
|
||||
|
||||
private FixtureSystem _fixtureSystem = default!;
|
||||
private SharedMapSystem _mapSystem = default!;
|
||||
private SharedPhysicsSystem _physics = default!;
|
||||
private SharedTransformSystem _transformSystem = default!;
|
||||
|
||||
private EntityQuery<FixturesComponent> _fixturesQuery;
|
||||
private EntityQuery<GridTreeComponent> _gridTreeQuery;
|
||||
private EntityQuery<MapGridComponent> _gridQuery;
|
||||
private EntityQuery<PhysicsComponent> _physicsQuery;
|
||||
private EntityQuery<TransformComponent> _xformQuery;
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Initialize()
|
||||
{
|
||||
_fixturesQuery = EntityManager.GetEntityQuery<FixturesComponent>();
|
||||
_gridTreeQuery = EntityManager.GetEntityQuery<GridTreeComponent>();
|
||||
_gridQuery = EntityManager.GetEntityQuery<MapGridComponent>();
|
||||
_physicsQuery = EntityManager.GetEntityQuery<PhysicsComponent>();
|
||||
_xformQuery = EntityManager.GetEntityQuery<TransformComponent>();
|
||||
|
||||
@@ -45,6 +58,8 @@ internal partial class MapManager : IMapManagerInternal, IEntityEventSubscriber
|
||||
/// <inheritdoc />
|
||||
public void Startup()
|
||||
{
|
||||
_fixtureSystem = EntityManager.System<FixtureSystem>();
|
||||
_physics = EntityManager.System<SharedPhysicsSystem>();
|
||||
_transformSystem = EntityManager.System<SharedTransformSystem>();
|
||||
_mapSystem = EntityManager.System<SharedMapSystem>();
|
||||
|
||||
|
||||
@@ -4,14 +4,12 @@ using Robust.Shared.Serialization;
|
||||
|
||||
namespace Robust.Shared.Network.Messages;
|
||||
|
||||
#nullable disable
|
||||
|
||||
public sealed class MsgConCompletionResp : NetMessage
|
||||
{
|
||||
public override MsgGroups MsgGroup => MsgGroups.Command;
|
||||
|
||||
public int Seq { get; set; }
|
||||
public CompletionResult Result { get; set; }
|
||||
public CompletionResult Result { get; set; } = default!;
|
||||
|
||||
public override void ReadFromBuffer(NetIncomingMessage buffer, IRobustSerializer serializer)
|
||||
{
|
||||
|
||||
@@ -71,7 +71,7 @@ public sealed class DynamicTreeBroadPhase : IBroadPhase
|
||||
|
||||
public IEnumerable<FixtureProxy> QueryAabb(List<FixtureProxy> proxies, Box2 aabb, bool approx = false)
|
||||
{
|
||||
QueryAabb(ref proxies, (ref List<FixtureProxy> lst, in FixtureProxy i) =>
|
||||
QueryAabb(ref proxies, static (ref List<FixtureProxy> lst, in FixtureProxy i) =>
|
||||
{
|
||||
lst.Add(i);
|
||||
return true;
|
||||
@@ -89,7 +89,7 @@ public sealed class DynamicTreeBroadPhase : IBroadPhase
|
||||
{
|
||||
var tuple = (state, _tree, callback, point, approx, _extractAabb);
|
||||
_tree.Query(ref tuple,
|
||||
(ref (TState state, B2DynamicTree<FixtureProxy> tree, DynamicTree<FixtureProxy>.QueryCallbackDelegate<TState> callback, Vector2 point, bool approx, DynamicTree<FixtureProxy>.ExtractAabbDelegate extract) tuple,
|
||||
static (ref (TState state, B2DynamicTree<FixtureProxy> tree, DynamicTree<FixtureProxy>.QueryCallbackDelegate<TState> callback, Vector2 point, bool approx, DynamicTree<FixtureProxy>.ExtractAabbDelegate extract) tuple,
|
||||
DynamicTree.Proxy proxy) =>
|
||||
{
|
||||
var item = tuple.tree.GetUserData(proxy)!;
|
||||
@@ -112,7 +112,7 @@ public sealed class DynamicTreeBroadPhase : IBroadPhase
|
||||
{
|
||||
var list = new List<FixtureProxy>();
|
||||
|
||||
QueryPoint(ref list, (ref List<FixtureProxy> list, in FixtureProxy i) =>
|
||||
QueryPoint(ref list, static (ref List<FixtureProxy> list, in FixtureProxy i) =>
|
||||
{
|
||||
list.Add(i);
|
||||
return true;
|
||||
|
||||
@@ -188,6 +188,37 @@ namespace Robust.Shared.Physics.Collision.Shapes
|
||||
Set(Vertices.AsSpan(), VertexCount);
|
||||
}
|
||||
|
||||
public bool Set(Box2Rotated bounds)
|
||||
{
|
||||
Span<Vector2> vertices = stackalloc Vector2[]
|
||||
{
|
||||
bounds.BottomLeft,
|
||||
bounds.BottomRight,
|
||||
bounds.TopRight,
|
||||
bounds.TopLeft,
|
||||
};
|
||||
|
||||
return Set(vertices, 4);
|
||||
}
|
||||
|
||||
public void SetAsBox(Box2 box)
|
||||
{
|
||||
Array.Resize(ref Vertices, 4);
|
||||
Array.Resize(ref Normals, 4);
|
||||
|
||||
Vertices[0] = box.BottomLeft;
|
||||
Vertices[1] = box.BottomRight;
|
||||
Vertices[2] = box.TopRight;
|
||||
Vertices[3] = box.TopLeft;
|
||||
|
||||
Normals[0] = new Vector2(0.0f, -1.0f);
|
||||
Normals[1] = new Vector2(1.0f, 0.0f);
|
||||
Normals[2] = new Vector2(0.0f, 1.0f);
|
||||
Normals[3] = new Vector2(-1.0f, 0.0f);
|
||||
|
||||
Centroid = box.Center;
|
||||
}
|
||||
|
||||
public void SetAsBox(float halfWidth, float halfHeight)
|
||||
{
|
||||
Array.Resize(ref Vertices, 4);
|
||||
|
||||
@@ -222,7 +222,7 @@ namespace Robust.Shared.Physics
|
||||
{
|
||||
var list = new List<T>();
|
||||
|
||||
QueryAabb(ref list, (ref List<T> lst, in T i) =>
|
||||
QueryAabb(ref list, static (ref List<T> lst, in T i) =>
|
||||
{
|
||||
lst.Add(i);
|
||||
return true;
|
||||
|
||||
@@ -248,7 +248,7 @@ namespace Robust.Shared.Physics.Systems
|
||||
var computeProperties = false;
|
||||
|
||||
// Given a bunch of data isn't serialized need to sort of re-initialise it
|
||||
var newFixtures = new Dictionary<string, Fixture>(state.Fixtures.Count());
|
||||
var newFixtures = new Dictionary<string, Fixture>(state.Fixtures.Count);
|
||||
|
||||
foreach (var (id, fixture) in state.Fixtures)
|
||||
{
|
||||
|
||||
@@ -227,7 +227,7 @@ namespace Robust.Shared.Physics.Systems
|
||||
ref var buffer = ref tuple.pairBuffer;
|
||||
tuple.system.FindPairs(tuple.proxy, tuple.worldAABB, uid, buffer);
|
||||
return true;
|
||||
});
|
||||
}, approx: true, includeMap: false);
|
||||
|
||||
// Struct ref moment, I have no idea what's fastest.
|
||||
buffer = state.buffer;
|
||||
@@ -287,7 +287,7 @@ namespace Robust.Shared.Physics.Systems
|
||||
// TODO: Need to handle grids colliding with non-grid entities with the same layer
|
||||
// (nothing in SS14 does this yet).
|
||||
|
||||
var transform = _physicsSystem.GetPhysicsTransform(gridUid, xformQuery: _xformQuery);
|
||||
var transform = _physicsSystem.GetPhysicsTransform(gridUid);
|
||||
var state = (gridUid, grid, transform, worldMatrix, invWorldMatrix, _map, _physicsSystem, _transform, _physicsQuery, _xformQuery);
|
||||
|
||||
_mapManager.FindGridsIntersecting(mapId, aabb, ref state,
|
||||
@@ -311,7 +311,7 @@ namespace Robust.Shared.Physics.Systems
|
||||
|
||||
var (_, _, otherGridMatrix, otherGridInvMatrix) = tuple.xformSystem.GetWorldPositionRotationMatrixWithInv(collidingXform, tuple.xformQuery);
|
||||
var otherGridBounds = otherGridMatrix.TransformBox(component.LocalAABB);
|
||||
var otherTransform = tuple._physicsSystem.GetPhysicsTransform(uid, xformQuery: tuple.xformQuery);
|
||||
var otherTransform = tuple._physicsSystem.GetPhysicsTransform(uid);
|
||||
|
||||
// Get Grid2 AABB in grid1 ref
|
||||
var aabb1 = tuple.grid.LocalAABB.Intersect(tuple.invWorldMatrix.TransformBox(otherGridBounds));
|
||||
@@ -360,7 +360,7 @@ namespace Robust.Shared.Physics.Systems
|
||||
}
|
||||
|
||||
return true;
|
||||
}, includeMap: false);
|
||||
}, approx: true, includeMap: false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -628,7 +628,7 @@ public partial class SharedPhysicsSystem
|
||||
|
||||
#endregion
|
||||
|
||||
public Transform GetPhysicsTransform(EntityUid uid, TransformComponent? xform = null, EntityQuery<TransformComponent>? xformQuery = null)
|
||||
public Transform GetPhysicsTransform(EntityUid uid, TransformComponent? xform = null)
|
||||
{
|
||||
if (!_xformQuery.Resolve(uid, ref xform))
|
||||
return Physics.Transform.Empty;
|
||||
|
||||
@@ -436,8 +436,8 @@ public abstract partial class SharedPhysicsSystem
|
||||
// Special-case grid contacts.
|
||||
if ((contact.Flags & ContactFlags.Grid) != 0x0)
|
||||
{
|
||||
var gridABounds = fixtureA.Shape.ComputeAABB(GetPhysicsTransform(uidA, xformA, _xformQuery), 0);
|
||||
var gridBBounds = fixtureB.Shape.ComputeAABB(GetPhysicsTransform(uidB, xformB, _xformQuery), 0);
|
||||
var gridABounds = fixtureA.Shape.ComputeAABB(GetPhysicsTransform(uidA, xformA), 0);
|
||||
var gridBBounds = fixtureB.Shape.ComputeAABB(GetPhysicsTransform(uidB, xformB), 0);
|
||||
|
||||
if (!gridABounds.Intersects(gridBBounds))
|
||||
{
|
||||
|
||||
@@ -54,7 +54,6 @@ namespace Robust.Shared.Physics.Systems
|
||||
[Dependency] private readonly SharedBroadphaseSystem _broadphase = default!;
|
||||
[Dependency] private readonly SharedContainerSystem _containerSystem = default!;
|
||||
[Dependency] private readonly SharedDebugPhysicsSystem _debugPhysics = default!;
|
||||
[Dependency] private readonly SharedGridTraversalSystem _traversal = default!;
|
||||
[Dependency] private readonly SharedJointSystem _joints = default!;
|
||||
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||
[Dependency] private readonly CollisionWakeSystem _wakeSystem = default!;
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace Robust.Shared.Physics
|
||||
// TODO: Probably replace this internally with just the Vector2 and radians but I'd need to re-learn trig so yeah....
|
||||
public struct Transform
|
||||
{
|
||||
public static readonly Transform Empty = new Transform();
|
||||
public static readonly Transform Empty = new Transform(0f);
|
||||
|
||||
public Vector2 Position;
|
||||
public Quaternion2D Quaternion2D;
|
||||
|
||||
@@ -350,6 +350,30 @@ public interface IPrototypeManager
|
||||
/// Get the yaml data for a given prototype.
|
||||
/// </summary>
|
||||
IReadOnlyDictionary<string, MappingDataNode> GetPrototypeData(EntityPrototype prototype);
|
||||
|
||||
/// <summary>
|
||||
/// Forces all prototypes in the given file to be abstract.
|
||||
/// This makes them be read as abstract prototypes (mappings) instead of regular prototype instances.
|
||||
/// Calling this method will not retroactively abstract prototypes that have already been read.
|
||||
/// </summary>
|
||||
/// <param name="path">
|
||||
/// The file to force prototypes to be abstract in.
|
||||
/// This must start from the Resources-level directory, but not include Resources itself.
|
||||
/// For example: /Prototypes/Guidebook/antagonist.yml
|
||||
/// </param>
|
||||
void AbstractFile(ResPath path);
|
||||
|
||||
/// <summary>
|
||||
/// Forces all prototypes in files recursively within this directory to be abstract.
|
||||
/// This makes them be read as abstract prototypes (mappings) instead of regular prototype instances.
|
||||
/// Calling this method will not retroactively abstract prototypes that have already been read.
|
||||
/// </summary>
|
||||
/// <param name="path">
|
||||
/// The directory to force prototypes to be abstract in.
|
||||
/// This must start from the Resources-level directory, but not include Resources itself.
|
||||
/// For example: /Prototypes/Guidebook
|
||||
/// </param>
|
||||
void AbstractDirectory(ResPath path);
|
||||
}
|
||||
|
||||
internal interface IPrototypeManagerInternal : IPrototypeManager
|
||||
|
||||
@@ -14,6 +14,16 @@ namespace Robust.Shared.Prototypes;
|
||||
|
||||
public partial class PrototypeManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Which files to force all prototypes within to be abstract.
|
||||
/// </summary>
|
||||
private readonly List<ResPath> _abstractFiles = new();
|
||||
|
||||
/// <summary>
|
||||
/// Which directories to force all prototypes recursively within to be abstract.
|
||||
/// </summary>
|
||||
private readonly List<ResPath> _abstractDirectories = new();
|
||||
|
||||
public event Action<DataNodeDocument>? LoadedData;
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -35,6 +45,7 @@ public partial class PrototypeManager
|
||||
{
|
||||
try
|
||||
{
|
||||
var ignored = IsFileAbstract(file);
|
||||
using var reader = ReadFile(file, !overwrite);
|
||||
|
||||
if (reader == null)
|
||||
@@ -50,7 +61,12 @@ public partial class PrototypeManager
|
||||
{
|
||||
var data = ExtractMapping((MappingDataNode)mapping);
|
||||
if (data != null)
|
||||
{
|
||||
if (ignored)
|
||||
AbstractPrototype(data.Data);
|
||||
|
||||
extractedList.Add(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,6 +130,7 @@ public partial class PrototypeManager
|
||||
{
|
||||
try
|
||||
{
|
||||
var ignored = IsFileAbstract(file);
|
||||
using var reader = ReadFile(file, !overwrite);
|
||||
|
||||
if (reader == null)
|
||||
@@ -133,6 +150,9 @@ public partial class PrototypeManager
|
||||
if (extracted == null)
|
||||
continue;
|
||||
|
||||
if (ignored)
|
||||
AbstractPrototype(extracted.Data);
|
||||
|
||||
MergeMapping(extracted, overwrite, changed);
|
||||
}
|
||||
}
|
||||
@@ -282,6 +302,57 @@ public partial class PrototypeManager
|
||||
Freeze(modified);
|
||||
}
|
||||
|
||||
public void AbstractFile(ResPath path)
|
||||
{
|
||||
_abstractFiles.Add(path);
|
||||
}
|
||||
|
||||
public void AbstractDirectory(ResPath path)
|
||||
{
|
||||
_abstractDirectories.Add(path);
|
||||
}
|
||||
|
||||
private bool IsFileAbstract(ResPath file)
|
||||
{
|
||||
if (_abstractFiles.Count > 0)
|
||||
{
|
||||
foreach (var abstractFile in _abstractFiles)
|
||||
{
|
||||
if (file.TryRelativeTo(abstractFile, out _))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (_abstractDirectories.Count > 0)
|
||||
{
|
||||
foreach (var abstractDirectory in _abstractDirectories)
|
||||
{
|
||||
if (file.TryRelativeTo(abstractDirectory, out _))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void AbstractPrototype(MappingDataNode mapping)
|
||||
{
|
||||
if (mapping.TryGet(AbstractDataFieldAttribute.Name, out var abstractNode))
|
||||
{
|
||||
if (abstractNode is not ValueDataNode abstractValueNode)
|
||||
{
|
||||
mapping.Remove(abstractNode);
|
||||
mapping.Add("abstract", "true");
|
||||
return;
|
||||
}
|
||||
|
||||
abstractValueNode.Value = "true";
|
||||
return;
|
||||
}
|
||||
|
||||
mapping.Add("abstract", "true");
|
||||
}
|
||||
|
||||
// All these fields can be null in case the
|
||||
private sealed record ExtractedMappingData(
|
||||
Type Kind,
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Robust.Shared.Collections;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Toolshed.Commands.Generic;
|
||||
|
||||
namespace Robust.Shared.Random;
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using Robust.Shared.Collections;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Utility;
|
||||
@@ -47,7 +48,7 @@ namespace Robust.Shared.Random
|
||||
}
|
||||
}
|
||||
|
||||
throw new InvalidOperationException("This should be unreachable!");
|
||||
throw new UnreachableException("This should be unreachable!");
|
||||
}
|
||||
|
||||
public static T PickAndTake<T>(this IRobustRandom random, IList<T> list)
|
||||
@@ -58,6 +59,36 @@ namespace Robust.Shared.Random
|
||||
return element;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Picks a random element from a set and returns it.
|
||||
/// This is O(n) as it has to iterate the collection until the target index.
|
||||
/// </summary>
|
||||
public static T Pick<T>(this System.Random random, ICollection<T> collection)
|
||||
{
|
||||
var index = random.Next(collection.Count);
|
||||
var i = 0;
|
||||
foreach (var t in collection)
|
||||
{
|
||||
if (i++ == index)
|
||||
{
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
throw new UnreachableException("This should be unreachable!");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Picks a random from a collection then removes it and returns it.
|
||||
/// This is O(n) as it has to iterate the collection until the target index.
|
||||
/// </summary>
|
||||
public static T PickAndTake<T>(this System.Random random, ICollection<T> set)
|
||||
{
|
||||
var tile = Pick(random, set);
|
||||
set.Remove(tile);
|
||||
return tile;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate a random number from a normal (gaussian) distribution.
|
||||
/// </summary>
|
||||
|
||||
@@ -4,30 +4,30 @@
|
||||
<IsPackable>false</IsPackable>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<NoWarn>CA1416</NoWarn>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="JetBrains.Annotations" Version="2021.3.0" PrivateAssets="All" />
|
||||
<PackageReference Include="Microsoft.Extensions.ObjectPool" Version="6.0.2" />
|
||||
<PackageReference Include="Microsoft.ILVerification" Version="6.0.0" PrivateAssets="compile" />
|
||||
<PackageReference Include="Microsoft.IO.RecyclableMemoryStream" Version="2.3.2" />
|
||||
<PackageReference Include="Nett" Version="0.15.0" PrivateAssets="compile" />
|
||||
<PackageReference Include="VorbisPizza" Version="1.3.0" PrivateAssets="compile" />
|
||||
<PackageReference Include="Pidgin" Version="2.5.0" />
|
||||
<PackageReference Include="prometheus-net" Version="4.1.1" />
|
||||
<PackageReference Include="Robust.Shared.AuthLib" Version="0.1.2" />
|
||||
<PackageReference Include="Serilog" Version="2.10.0" />
|
||||
<PackageReference Include="YamlDotNet" Version="12.0.0" />
|
||||
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" PrivateAssets="compile" />
|
||||
<PackageReference Include="Linguini.Bundle" Version="0.1.3" />
|
||||
<PackageReference Include="SharpZstd.Interop" Version="1.5.2-beta2" PrivateAssets="compile" />
|
||||
<PackageReference Include="SpaceWizards.Sodium" Version="0.2.1" PrivateAssets="compile" />
|
||||
<PackageReference Include="SixLabors.ImageSharp" Version="2.1.3" />
|
||||
<PackageReference Include="TerraFX.Interop.Windows" Version="10.0.20348-rc2" PrivateAssets="compile" />
|
||||
<PackageReference Include="JetBrains.Annotations" PrivateAssets="All" />
|
||||
<PackageReference Include="Microsoft.Extensions.ObjectPool" />
|
||||
<PackageReference Include="Microsoft.ILVerification" PrivateAssets="compile" />
|
||||
<PackageReference Include="Microsoft.IO.RecyclableMemoryStream" />
|
||||
<PackageReference Include="Nett" PrivateAssets="compile" />
|
||||
<PackageReference Include="VorbisPizza" PrivateAssets="compile" />
|
||||
<PackageReference Include="Pidgin" />
|
||||
<PackageReference Include="prometheus-net" />
|
||||
<PackageReference Include="Robust.Shared.AuthLib" />
|
||||
<PackageReference Include="Serilog" />
|
||||
<PackageReference Include="YamlDotNet" />
|
||||
<PackageReference Include="Microsoft.Win32.Registry" PrivateAssets="compile" />
|
||||
<PackageReference Include="Linguini.Bundle" />
|
||||
<PackageReference Include="SharpZstd.Interop" PrivateAssets="compile" />
|
||||
<PackageReference Include="SpaceWizards.Sodium" PrivateAssets="compile" />
|
||||
<PackageReference Include="SixLabors.ImageSharp" />
|
||||
<PackageReference Include="TerraFX.Interop.Windows" PrivateAssets="compile" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Lidgren.Network\Lidgren.Network.csproj" />
|
||||
<ProjectReference Include="..\NetSerializer\NetSerializer\NetSerializer.csproj" />
|
||||
<ProjectReference Include="..\Robust.Physics\Robust.Physics.csproj" />
|
||||
<ProjectReference Include="..\Robust.Shared.Maths\Robust.Shared.Maths.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -100,6 +100,11 @@ namespace Robust.Shared.Serialization
|
||||
public byte[] GetSerializableTypesHash() => Convert.FromHexString(_serializer.GetSHA256());
|
||||
public string GetSerializableTypesHashString() => _serializer.GetSHA256();
|
||||
|
||||
internal void GetHashManifest(Stream stream, bool writeNewline=false)
|
||||
{
|
||||
_serializer.GetHashManifest(stream, writeNewline);
|
||||
}
|
||||
|
||||
public (byte[] Hash, byte[] Package) GetStringSerializerPackage() => MappedStringSerializer.GeneratePackage();
|
||||
|
||||
public Dictionary<Type, uint> GetTypeMap() => _serializer.GetTypeMap();
|
||||
|
||||
@@ -63,7 +63,7 @@ internal sealed unsafe class PrecisionSleepWindowsHighResolution : PrecisionSlee
|
||||
Windows.TIMER_ALL_ACCESS);
|
||||
|
||||
if (_timerHandle == HANDLE.NULL)
|
||||
Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
|
||||
Marshal.ThrowExceptionForHR(Windows.HRESULT_FROM_WIN32(Marshal.GetLastSystemError()));
|
||||
}
|
||||
|
||||
public override void Sleep(TimeSpan time)
|
||||
@@ -82,11 +82,11 @@ internal sealed unsafe class PrecisionSleepWindowsHighResolution : PrecisionSlee
|
||||
);
|
||||
|
||||
if (!success)
|
||||
Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
|
||||
Marshal.ThrowExceptionForHR(Windows.HRESULT_FROM_WIN32(Marshal.GetLastSystemError()));
|
||||
|
||||
var waitResult = Windows.WaitForSingleObject(_timerHandle, Windows.INFINITE);
|
||||
if (waitResult == WAIT.WAIT_FAILED)
|
||||
Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
|
||||
Marshal.ThrowExceptionForHR(Windows.HRESULT_FROM_WIN32(Marshal.GetLastSystemError()));
|
||||
|
||||
GC.KeepAlive(this);
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ internal static class FileHelper
|
||||
fixed (char* pPath = path)
|
||||
{
|
||||
file = Windows.CreateFileW(
|
||||
(ushort*)pPath,
|
||||
pPath,
|
||||
Windows.GENERIC_READ,
|
||||
FILE.FILE_SHARE_READ,
|
||||
null,
|
||||
@@ -61,7 +61,7 @@ internal static class FileHelper
|
||||
|
||||
if (file == HANDLE.INVALID_VALUE)
|
||||
{
|
||||
var lastError = Marshal.GetLastWin32Error();
|
||||
var lastError = Marshal.GetLastSystemError();
|
||||
if (lastError is ERROR.ERROR_FILE_NOT_FOUND or ERROR.ERROR_PATH_NOT_FOUND)
|
||||
{
|
||||
stream = null;
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using C = System.Console;
|
||||
|
||||
namespace Robust.Shared.Utility;
|
||||
|
||||
internal static unsafe class GlibcBug
|
||||
{
|
||||
/// <summary>
|
||||
/// Check for the glibc 2.35 DSO bug and log a warning if necessary.
|
||||
/// </summary>
|
||||
public static void Check()
|
||||
{
|
||||
if (!OperatingSystem.IsLinux())
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
var versionString = Marshal.PtrToStringUTF8((IntPtr) gnu_get_libc_version());
|
||||
var version = Version.Parse(versionString!);
|
||||
var badVersion = new Version(2, 35);
|
||||
var fixedVersion = new Version(2, 37);
|
||||
if (version >= badVersion && version < fixedVersion)
|
||||
{
|
||||
C.ForegroundColor = ConsoleColor.Yellow;
|
||||
C.WriteLine($"!!!WARNING!!!: glibc {badVersion} or higher detected (you have {version}).");
|
||||
C.WriteLine("If anything misbehaves (weird native crashes, library load failures), try setting GLIBC_TUNABLES=glibc.rtld.dynamic_sort=1 as environment variable.");
|
||||
C.WriteLine("This is a severe glibc bug introduced in glibc 2.35. See https://github.com/space-wizards/RobustToolbox/issues/2563 for details");
|
||||
C.WriteLine("We cannot detect if you are susceptible or whether you have correctly applied the fix. This warning cannot be removed.");
|
||||
C.ResetColor();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Couldn't figure out glibc version, whatever.
|
||||
// Hell maybe you're not even using glibc.
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport("libc.so.6")]
|
||||
private static extern byte* gnu_get_libc_version();
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user