mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-15 11:40:52 +01:00
Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
950ceb235a | ||
|
|
38ab4b729e | ||
|
|
634ba59316 | ||
|
|
01b60240d5 | ||
|
|
fc1cca4f48 | ||
|
|
3657b0a424 | ||
|
|
c3d8080a8e | ||
|
|
8e50924607 | ||
|
|
7fdd5c9d1c | ||
|
|
7fbcfeaa8f | ||
|
|
b82bc258db | ||
|
|
7ad2925f2c | ||
|
|
4091ad4837 | ||
|
|
35881d7a6a | ||
|
|
2d28ac35d8 | ||
|
|
8b5ad938d5 | ||
|
|
723f936a33 | ||
|
|
2636879860 | ||
|
|
dad1da507c | ||
|
|
145c190800 | ||
|
|
b7cc0ec629 | ||
|
|
ad329a6b58 | ||
|
|
4deba4b866 | ||
|
|
4c31083186 | ||
|
|
d31e7ccb55 |
@@ -55,7 +55,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.3" />
|
||||
<PackageVersion Include="SixLabors.ImageSharp" Version="3.1.5" />
|
||||
<PackageVersion Include="SpaceWizards.HttpListener" Version="0.1.1" />
|
||||
<PackageVersion Include="SpaceWizards.NFluidsynth" Version="0.1.1" />
|
||||
<PackageVersion Include="SpaceWizards.SharpFont" Version="1.0.2" />
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<Project>
|
||||
|
||||
<!-- This file automatically reset by Tools/version.py -->
|
||||
<!-- This file automatically reset by Tools/version.py -->
|
||||
|
||||
|
||||
@@ -54,6 +54,33 @@ END TEMPLATE-->
|
||||
*None yet*
|
||||
|
||||
|
||||
## 228.0.2
|
||||
|
||||
|
||||
## 228.0.1
|
||||
|
||||
|
||||
## 228.0.0
|
||||
|
||||
### Breaking changes
|
||||
|
||||
* The `Color` struct's equality methods now check for exact equality. Use `MathHelper.CloseToPercent(Color, Color)` for the previous functionality.
|
||||
* Added a toolshed.nearby_limit cvar to limit the maximum range of the nearby command. Defaults to 200.
|
||||
|
||||
### New features
|
||||
|
||||
* Added command usage with types to Toolshed command help.
|
||||
* Add Text property to RichTextLabel.
|
||||
* Whitelist System.Net.IPEndPoint.
|
||||
* Add event for mass & angular inertia changes.
|
||||
* Add SpriteSystem.IsVisible for layers.
|
||||
* Add TryQueueDeleteEntity that checks if the entity is already deleted / queuedeleted first.
|
||||
|
||||
### Bugfixes
|
||||
|
||||
* Clients connecting to a server now always load prototype uploads after resource uploads, fixing ordering bugs that could cause various errors.
|
||||
|
||||
|
||||
## 227.0.0
|
||||
|
||||
### Breaking changes
|
||||
|
||||
91
Robust.Analyzers.Tests/DataDefinitionAnalyzerTest.cs
Normal file
91
Robust.Analyzers.Tests/DataDefinitionAnalyzerTest.cs
Normal file
@@ -0,0 +1,91 @@
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.CodeAnalysis.CSharp.Testing;
|
||||
using Microsoft.CodeAnalysis.Testing;
|
||||
using Microsoft.CodeAnalysis.Testing.Verifiers;
|
||||
using NUnit.Framework;
|
||||
using VerifyCS =
|
||||
Microsoft.CodeAnalysis.CSharp.Testing.NUnit.AnalyzerVerifier<Robust.Analyzers.DataDefinitionAnalyzer>;
|
||||
|
||||
namespace Robust.Analyzers.Tests;
|
||||
|
||||
[Parallelizable(ParallelScope.All | ParallelScope.Fixtures)]
|
||||
[TestFixture]
|
||||
public sealed class DataDefinitionAnalyzerTest
|
||||
{
|
||||
private static Task Verifier(string code, params DiagnosticResult[] expected)
|
||||
{
|
||||
var test = new CSharpAnalyzerTest<DataDefinitionAnalyzer, NUnitVerifier>()
|
||||
{
|
||||
TestState =
|
||||
{
|
||||
Sources = { code }
|
||||
},
|
||||
};
|
||||
|
||||
// ExpectedDiagnostics cannot be set, so we need to AddRange here...
|
||||
test.TestState.ExpectedDiagnostics.AddRange(expected);
|
||||
|
||||
return test.RunAsync();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Test()
|
||||
{
|
||||
const string code = """
|
||||
using System;
|
||||
using Robust.Shared.ViewVariables;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
|
||||
namespace Robust.Shared.ViewVariables
|
||||
{
|
||||
public sealed class ViewVariablesAttribute : Attribute
|
||||
{
|
||||
public readonly VVAccess Access = VVAccess.ReadOnly;
|
||||
|
||||
public ViewVariablesAttribute() { }
|
||||
|
||||
public ViewVariablesAttribute(VVAccess access)
|
||||
{
|
||||
Access = access;
|
||||
}
|
||||
}
|
||||
public enum VVAccess : byte
|
||||
{
|
||||
ReadOnly = 0,
|
||||
ReadWrite = 1,
|
||||
}
|
||||
}
|
||||
|
||||
namespace Robust.Shared.Serialization.Manager.Attributes
|
||||
{
|
||||
public class DataFieldBaseAttribute : Attribute;
|
||||
public class DataFieldAttribute : DataFieldBaseAttribute;
|
||||
public sealed class DataDefinitionAttribute : Attribute;
|
||||
}
|
||||
|
||||
[DataDefinition]
|
||||
public sealed partial class Foo
|
||||
{
|
||||
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
||||
public int Bad;
|
||||
|
||||
[DataField]
|
||||
public int Good;
|
||||
|
||||
[DataField, ViewVariables]
|
||||
public int Good2;
|
||||
|
||||
[DataField, ViewVariables(VVAccess.ReadOnly)]
|
||||
public int Good3;
|
||||
|
||||
[ViewVariables]
|
||||
public int Good4;
|
||||
}
|
||||
""";
|
||||
|
||||
await Verifier(code,
|
||||
// /0/Test0.cs(35,5): info RA0028: Data field Bad in data definition Foo has ViewVariables attribute with ReadWrite access, which is redundant
|
||||
VerifyCS.Diagnostic(DataDefinitionAnalyzer.DataFieldNoVVReadWriteRule).WithSpan(35, 5, 36, 20).WithArguments("Bad", "Foo")
|
||||
);
|
||||
}
|
||||
}
|
||||
71
Robust.Analyzers.Tests/PreferNonGenericVariantForTest.cs
Normal file
71
Robust.Analyzers.Tests/PreferNonGenericVariantForTest.cs
Normal file
@@ -0,0 +1,71 @@
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.CodeAnalysis.CSharp.Testing;
|
||||
using Microsoft.CodeAnalysis.Testing;
|
||||
using Microsoft.CodeAnalysis.Testing.Verifiers;
|
||||
using NUnit.Framework;
|
||||
using VerifyCS =
|
||||
Microsoft.CodeAnalysis.CSharp.Testing.NUnit.AnalyzerVerifier<Robust.Analyzers.PreferNonGenericVariantForAnalyzer>;
|
||||
|
||||
namespace Robust.Analyzers.Tests;
|
||||
|
||||
[Parallelizable(ParallelScope.All | ParallelScope.Fixtures)]
|
||||
[TestFixture]
|
||||
public sealed class PreferNonGenericVariantForTest
|
||||
{
|
||||
private static Task Verifier(string code, params DiagnosticResult[] expected)
|
||||
{
|
||||
var test = new CSharpAnalyzerTest<PreferNonGenericVariantForAnalyzer, NUnitVerifier>()
|
||||
{
|
||||
TestState =
|
||||
{
|
||||
Sources = { code },
|
||||
},
|
||||
};
|
||||
|
||||
TestHelper.AddEmbeddedSources(
|
||||
test.TestState,
|
||||
"Robust.Shared.Analyzers.PreferNonGenericVariantForAttribute.cs"
|
||||
);
|
||||
|
||||
// ExpectedDiagnostics cannot be set, so we need to AddRange here...
|
||||
test.TestState.ExpectedDiagnostics.AddRange(expected);
|
||||
|
||||
return test.RunAsync();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Test()
|
||||
{
|
||||
const string code = """
|
||||
using Robust.Shared.Analyzers;
|
||||
|
||||
public class Bar { };
|
||||
public class Baz { };
|
||||
public class Okay { };
|
||||
|
||||
public static class Foo
|
||||
{
|
||||
[PreferNonGenericVariantFor(typeof(Bar), typeof(Baz))]
|
||||
public static void DoFoo<T>() { }
|
||||
}
|
||||
|
||||
public class Test
|
||||
{
|
||||
public void DoBad()
|
||||
{
|
||||
Foo.DoFoo<Bar>();
|
||||
}
|
||||
|
||||
public void DoGood()
|
||||
{
|
||||
Foo.DoFoo<Okay>();
|
||||
}
|
||||
}
|
||||
""";
|
||||
|
||||
await Verifier(code,
|
||||
// /0/Test0.cs(17,9): warning RA0029: Use the non-generic variant of this method for type Bar
|
||||
VerifyCS.Diagnostic().WithSpan(17, 9, 17, 25).WithArguments("Bar")
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@
|
||||
<EmbeddedResource Include="..\Robust.Shared\Analyzers\AccessAttribute.cs" LogicalName="Robust.Shared.Analyzers.AccessAttribute.cs" LinkBase="Implementations" />
|
||||
<EmbeddedResource Include="..\Robust.Shared\Analyzers\AccessPermissions.cs" LogicalName="Robust.Shared.Analyzers.AccessPermissions.cs" LinkBase="Implementations" />
|
||||
<EmbeddedResource Include="..\Robust.Shared\Analyzers\MustCallBaseAttribute.cs" LogicalName="Robust.Shared.IoC.MustCallBaseAttribute.cs" LinkBase="Implementations" />
|
||||
<EmbeddedResource Include="..\Robust.Shared\Analyzers\PreferNonGenericVariantForAttribute.cs" LogicalName="Robust.Shared.Analyzers.PreferNonGenericVariantForAttribute.cs" LinkBase="Implementations" />
|
||||
<EmbeddedResource Include="..\Robust.Shared\IoC\DependencyAttribute.cs" LogicalName="Robust.Shared.IoC.DependencyAttribute.cs" LinkBase="Implementations" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using Microsoft.CodeAnalysis.Diagnostics;
|
||||
using Robust.Roslyn.Shared;
|
||||
using Robust.Shared.Serialization.Manager.Definition;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Robust.Analyzers;
|
||||
|
||||
@@ -16,6 +17,7 @@ public sealed class DataDefinitionAnalyzer : DiagnosticAnalyzer
|
||||
private const string DataDefinitionNamespace = "Robust.Shared.Serialization.Manager.Attributes.DataDefinitionAttribute";
|
||||
private const string ImplicitDataDefinitionNamespace = "Robust.Shared.Serialization.Manager.Attributes.ImplicitDataDefinitionForInheritorsAttribute";
|
||||
private const string DataFieldBaseNamespace = "Robust.Shared.Serialization.Manager.Attributes.DataFieldBaseAttribute";
|
||||
private const string ViewVariablesNamespace = "Robust.Shared.ViewVariables.ViewVariablesAttribute";
|
||||
|
||||
private static readonly DiagnosticDescriptor DataDefinitionPartialRule = new(
|
||||
Diagnostics.IdDataDefinitionPartial,
|
||||
@@ -66,9 +68,20 @@ public sealed class DataDefinitionAnalyzer : DiagnosticAnalyzer
|
||||
true,
|
||||
"Make sure to remove the tag string from the data field attribute."
|
||||
);
|
||||
|
||||
public static readonly DiagnosticDescriptor DataFieldNoVVReadWriteRule = new(
|
||||
Diagnostics.IdDataFieldNoVVReadWrite,
|
||||
"Data field has VV ReadWrite",
|
||||
"Data field {0} in data definition {1} has ViewVariables attribute with ReadWrite access, which is redundant",
|
||||
"Usage",
|
||||
DiagnosticSeverity.Info,
|
||||
true,
|
||||
"Make sure to remove the ViewVariables attribute."
|
||||
);
|
||||
|
||||
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(
|
||||
DataDefinitionPartialRule, NestedDataDefinitionPartialRule, DataFieldWritableRule, DataFieldPropertyWritableRule,
|
||||
DataFieldRedundantTagRule
|
||||
DataFieldRedundantTagRule, DataFieldNoVVReadWriteRule
|
||||
);
|
||||
|
||||
public override void Initialize(AnalysisContext context)
|
||||
@@ -141,6 +154,11 @@ public sealed class DataDefinitionAnalyzer : DiagnosticAnalyzer
|
||||
{
|
||||
context.ReportDiagnostic(Diagnostic.Create(DataFieldRedundantTagRule, context.Node.GetLocation(), fieldSymbol.Name, type.Name));
|
||||
}
|
||||
|
||||
if (HasVVReadWrite(fieldSymbol))
|
||||
{
|
||||
context.ReportDiagnostic(Diagnostic.Create(DataFieldNoVVReadWriteRule, context.Node.GetLocation(), fieldSymbol.Name, type.Name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,6 +188,11 @@ public sealed class DataDefinitionAnalyzer : DiagnosticAnalyzer
|
||||
{
|
||||
context.ReportDiagnostic(Diagnostic.Create(DataFieldRedundantTagRule, context.Node.GetLocation(), propertySymbol.Name, type.Name));
|
||||
}
|
||||
|
||||
if (HasVVReadWrite(propertySymbol))
|
||||
{
|
||||
context.ReportDiagnostic(Diagnostic.Create(DataFieldNoVVReadWriteRule, context.Node.GetLocation(), propertySymbol.Name, type.Name));
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsReadOnlyDataField(ITypeSymbol type, ISymbol field)
|
||||
@@ -292,6 +315,34 @@ public sealed class DataDefinitionAnalyzer : DiagnosticAnalyzer
|
||||
return explicitName == automaticName;
|
||||
}
|
||||
|
||||
private static bool HasVVReadWrite(ISymbol symbol)
|
||||
{
|
||||
if (!IsDataField(symbol, out _, out _))
|
||||
return false;
|
||||
|
||||
// Make sure it has ViewVariablesAttribute
|
||||
AttributeData? viewVariablesAttribute = null;
|
||||
foreach (var attr in symbol.GetAttributes())
|
||||
{
|
||||
if (attr.AttributeClass?.ToDisplayString() == ViewVariablesNamespace)
|
||||
{
|
||||
viewVariablesAttribute = attr;
|
||||
}
|
||||
}
|
||||
if (viewVariablesAttribute == null)
|
||||
return false;
|
||||
|
||||
// Default is ReadOnly, which is fine
|
||||
if (viewVariablesAttribute.ConstructorArguments.Length == 0)
|
||||
return false;
|
||||
|
||||
var accessArgument = viewVariablesAttribute.ConstructorArguments[0];
|
||||
if (accessArgument.Value is not byte accessByte)
|
||||
return false;
|
||||
|
||||
return (VVAccess)accessByte == VVAccess.ReadWrite;
|
||||
}
|
||||
|
||||
private static bool IsImplicitDataDefinition(ITypeSymbol type)
|
||||
{
|
||||
if (HasAttribute(type, ImplicitDataDefinitionNamespace))
|
||||
|
||||
@@ -15,9 +15,11 @@ public sealed class DefinitionFixer : CodeFixProvider
|
||||
{
|
||||
private const string DataFieldAttributeName = "DataField";
|
||||
|
||||
private const string ViewVariablesAttributeName = "ViewVariables";
|
||||
|
||||
public override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(
|
||||
IdDataDefinitionPartial, IdNestedDataDefinitionPartial, IdDataFieldWritable, IdDataFieldPropertyWritable,
|
||||
IdDataFieldRedundantTag
|
||||
IdDataFieldRedundantTag, IdDataFieldNoVVReadWrite
|
||||
);
|
||||
|
||||
public override Task RegisterCodeFixesAsync(CodeFixContext context)
|
||||
@@ -36,6 +38,8 @@ public sealed class DefinitionFixer : CodeFixProvider
|
||||
return RegisterDataFieldPropertyFix(context, diagnostic);
|
||||
case IdDataFieldRedundantTag:
|
||||
return RegisterRedundantTagFix(context, diagnostic);
|
||||
case IdDataFieldNoVVReadWrite:
|
||||
return RegisterVVReadWriteFix(context, diagnostic);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,6 +140,48 @@ public sealed class DefinitionFixer : CodeFixProvider
|
||||
return document.WithSyntaxRoot(root);
|
||||
}
|
||||
|
||||
private static async Task RegisterVVReadWriteFix(CodeFixContext context, Diagnostic diagnostic)
|
||||
{
|
||||
var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken);
|
||||
var span = diagnostic.Location.SourceSpan;
|
||||
var token = root?.FindToken(span.Start).Parent?.AncestorsAndSelf().OfType<MemberDeclarationSyntax>().First();
|
||||
|
||||
if (token == null)
|
||||
return;
|
||||
|
||||
context.RegisterCodeFix(CodeAction.Create(
|
||||
"Remove ViewVariables attribute",
|
||||
c => RemoveVVAttribute(context.Document, token, c),
|
||||
"Remove ViewVariables attribute"
|
||||
), diagnostic);
|
||||
}
|
||||
|
||||
private static async Task<Document> RemoveVVAttribute(Document document, MemberDeclarationSyntax syntax, CancellationToken cancellation)
|
||||
{
|
||||
var root = (CompilationUnitSyntax?) await document.GetSyntaxRootAsync(cancellation);
|
||||
|
||||
var newLists = new SyntaxList<AttributeListSyntax>();
|
||||
foreach (var attributeList in syntax.AttributeLists)
|
||||
{
|
||||
var attributes = new SeparatedSyntaxList<AttributeSyntax>();
|
||||
foreach (var attribute in attributeList.Attributes)
|
||||
{
|
||||
if (attribute.Name.ToString() != ViewVariablesAttributeName)
|
||||
{
|
||||
attributes = attributes.Add(attribute);
|
||||
}
|
||||
}
|
||||
// Don't add empty lists []
|
||||
if (attributes.Count > 0)
|
||||
newLists = newLists.Add(attributeList.WithAttributes(attributes));
|
||||
}
|
||||
var newSyntax = syntax.WithAttributeLists(newLists);
|
||||
|
||||
root = root!.ReplaceNode(syntax, newSyntax);
|
||||
|
||||
return document.WithSyntaxRoot(root);
|
||||
}
|
||||
|
||||
private static async Task RegisterDataFieldFix(CodeFixContext context, Diagnostic diagnostic)
|
||||
{
|
||||
var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken);
|
||||
|
||||
65
Robust.Analyzers/PreferNonGenericVariantForAnalyzer.cs
Normal file
65
Robust.Analyzers/PreferNonGenericVariantForAnalyzer.cs
Normal file
@@ -0,0 +1,65 @@
|
||||
using System.Collections.Immutable;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.Diagnostics;
|
||||
using Microsoft.CodeAnalysis.Operations;
|
||||
using Robust.Roslyn.Shared;
|
||||
|
||||
namespace Robust.Analyzers;
|
||||
|
||||
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
||||
public sealed class PreferNonGenericVariantForAnalyzer : DiagnosticAnalyzer
|
||||
{
|
||||
private const string AttributeType = "Robust.Shared.Analyzers.PreferNonGenericVariantForAttribute";
|
||||
|
||||
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(
|
||||
UseNonGenericVariantDescriptor
|
||||
);
|
||||
|
||||
private static readonly DiagnosticDescriptor UseNonGenericVariantDescriptor = new(
|
||||
Diagnostics.IdUseNonGenericVariant,
|
||||
"Consider using the non-generic variant of this method",
|
||||
"Use the non-generic variant of this method for type {0}",
|
||||
"Usage",
|
||||
DiagnosticSeverity.Warning,
|
||||
true,
|
||||
"Use the generic variant of this method.");
|
||||
|
||||
public override void Initialize(AnalysisContext context)
|
||||
{
|
||||
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.ReportDiagnostics | GeneratedCodeAnalysisFlags.Analyze);
|
||||
context.EnableConcurrentExecution();
|
||||
context.RegisterOperationAction(CheckForNonGenericVariant, OperationKind.Invocation);
|
||||
}
|
||||
|
||||
private void CheckForNonGenericVariant(OperationAnalysisContext obj)
|
||||
{
|
||||
if (obj.Operation is not IInvocationOperation invocationOperation) return;
|
||||
|
||||
var preferNonGenericAttribute = obj.Compilation.GetTypeByMetadataName(AttributeType);
|
||||
|
||||
HashSet<ITypeSymbol> forTypes = [];
|
||||
foreach (var attribute in invocationOperation.TargetMethod.GetAttributes())
|
||||
{
|
||||
if (!SymbolEqualityComparer.Default.Equals(attribute.AttributeClass, preferNonGenericAttribute))
|
||||
continue;
|
||||
|
||||
foreach (var type in attribute.ConstructorArguments[0].Values)
|
||||
forTypes.Add((ITypeSymbol)type.Value);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (forTypes == null)
|
||||
return;
|
||||
|
||||
foreach (var typeArg in invocationOperation.TargetMethod.TypeArguments)
|
||||
{
|
||||
if (forTypes.Contains(typeArg))
|
||||
{
|
||||
obj.ReportDiagnostic(
|
||||
Diagnostic.Create(UseNonGenericVariantDescriptor,
|
||||
invocationOperation.Syntax.GetLocation(), typeArg.Name));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,9 +16,16 @@
|
||||
<Compile Include="..\Robust.Shared\Analyzers\PreferGenericVariantAttribute.cs" LinkBase="Implementations" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- Needed for PreferNonGenericVariantAnalyzer. -->
|
||||
<Compile Include="..\Robust.Shared\Analyzers\PreferNonGenericVariantForAttribute.cs" LinkBase="Implementations" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- Needed for DataDefinitionAnalyzer. -->
|
||||
<Compile Include="..\Robust.Shared\Serialization\Manager\Definition\DataDefinitionUtility.cs" LinkBase="Implementations" />
|
||||
<Compile Include="..\Robust.Shared\ViewVariables\ViewVariablesAttribute.cs" LinkBase="Implementations" />
|
||||
<Compile Include="..\Robust.Shared\Serialization\NetSerializableAttribute.cs" LinkBase="Implementations" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="../Robust.Roslyn.Shared/Robust.Roslyn.Shared.props" />
|
||||
|
||||
@@ -302,7 +302,7 @@ internal partial class AudioManager
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
IBufferedAudioSource? IAudioInternal.CreateBufferedAudioSource(int buffers, bool floatAudio=false)
|
||||
IBufferedAudioSource? IAudioInternal.CreateBufferedAudioSource(int buffers, bool floatAudio)
|
||||
{
|
||||
var source = AL.GenSource();
|
||||
|
||||
|
||||
@@ -143,12 +143,11 @@ internal sealed partial class AudioManager : IAudioInternal
|
||||
/// <summary>
|
||||
/// Like _checkAlError but allows custom data to be passed in as relevant.
|
||||
/// </summary>
|
||||
internal void LogALError(string message, [CallerMemberName] string callerMember = "", [CallerLineNumber] int callerLineNumber = -1)
|
||||
internal void LogALError(ALErrorInterpolatedStringHandler message, [CallerMemberName] string callerMember = "", [CallerLineNumber] int callerLineNumber = -1)
|
||||
{
|
||||
var error = AL.GetError();
|
||||
if (error != ALError.NoError)
|
||||
if (message.Error != ALError.NoError)
|
||||
{
|
||||
OpenALSawmill.Error("[{0}:{1}] AL error: {2}, {3}. Stacktrace is {4}", callerMember, callerLineNumber, error, message, Environment.StackTrace);
|
||||
OpenALSawmill.Error("[{0}:{1}] AL error: {2}, {3}. Stacktrace is {4}", callerMember, callerLineNumber, message.Error, message.ToStringAndClear(), Environment.StackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,4 +169,32 @@ internal sealed partial class AudioManager : IAudioInternal
|
||||
BufferHandle = bufferHandle;
|
||||
}
|
||||
}
|
||||
|
||||
[InterpolatedStringHandler]
|
||||
internal ref struct ALErrorInterpolatedStringHandler
|
||||
{
|
||||
private DefaultInterpolatedStringHandler _handler;
|
||||
public ALError Error;
|
||||
|
||||
public ALErrorInterpolatedStringHandler(int literalLength, int formattedCount, out bool shouldAppend)
|
||||
{
|
||||
Error = AL.GetError();
|
||||
if (Error == ALError.NoError)
|
||||
{
|
||||
shouldAppend = false;
|
||||
_handler = default;
|
||||
}
|
||||
else
|
||||
{
|
||||
shouldAppend = true;
|
||||
_handler = new DefaultInterpolatedStringHandler(literalLength, formattedCount);
|
||||
}
|
||||
}
|
||||
|
||||
public string ToStringAndClear() => _handler.ToStringAndClear();
|
||||
public override string ToString() => _handler.ToString();
|
||||
public void AppendLiteral(string value) => _handler.AppendLiteral(value);
|
||||
public void AppendFormatted<T>(T value) => _handler.AppendFormatted(value);
|
||||
public void AppendFormatted<T>(T value, string? format) => _handler.AppendFormatted(value, format);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ public sealed class AudioOverlay : Overlay
|
||||
|
||||
var screenHandle = args.ScreenHandle;
|
||||
var output = new StringBuilder();
|
||||
var listenerPos = _entManager.GetComponent<TransformComponent>(localPlayer.Value).MapPosition;
|
||||
var listenerPos = _transform.GetMapCoordinates(_entManager.GetComponent<TransformComponent>(localPlayer.Value));
|
||||
|
||||
if (listenerPos.MapId != args.MapId)
|
||||
return;
|
||||
|
||||
@@ -1,24 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Numerics;
|
||||
using OpenTK.Audio.OpenAL;
|
||||
using OpenTK.Audio.OpenAL.Extensions.Creative.EFX;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Shared.Audio.Sources;
|
||||
using Robust.Shared.Maths;
|
||||
|
||||
namespace Robust.Client.Audio.Sources;
|
||||
|
||||
internal sealed class BufferedAudioSource : BaseAudioSource, IBufferedAudioSource
|
||||
{
|
||||
private int? SourceHandle = null;
|
||||
private int[] BufferHandles;
|
||||
private Dictionary<int, int> BufferMap = new();
|
||||
private readonly AudioManager _master;
|
||||
private bool _mono = true;
|
||||
private bool _float = false;
|
||||
private int FilterHandle;
|
||||
|
||||
public int SampleRate { get; set; } = 44100;
|
||||
|
||||
@@ -43,7 +37,7 @@ internal sealed class BufferedAudioSource : BaseAudioSource, IBufferedAudioSourc
|
||||
get
|
||||
{
|
||||
_checkDisposed();
|
||||
var state = AL.GetSourceState(SourceHandle!.Value);
|
||||
var state = AL.GetSourceState(SourceHandle);
|
||||
_master._checkAlError();
|
||||
return state == ALSourceState.Playing;
|
||||
}
|
||||
@@ -53,7 +47,7 @@ internal sealed class BufferedAudioSource : BaseAudioSource, IBufferedAudioSourc
|
||||
{
|
||||
_checkDisposed();
|
||||
// IDK why this stackallocs but gonna leave it for now.
|
||||
AL.SourcePlay(stackalloc int[] {SourceHandle!.Value});
|
||||
AL.SourcePlay(stackalloc int[] {SourceHandle});
|
||||
_master._checkAlError();
|
||||
}
|
||||
else
|
||||
@@ -61,7 +55,7 @@ internal sealed class BufferedAudioSource : BaseAudioSource, IBufferedAudioSourc
|
||||
if (_isDisposed())
|
||||
return;
|
||||
|
||||
AL.SourceStop(SourceHandle!.Value);
|
||||
AL.SourceStop(SourceHandle);
|
||||
_master._checkAlError();
|
||||
}
|
||||
}
|
||||
@@ -74,13 +68,13 @@ internal sealed class BufferedAudioSource : BaseAudioSource, IBufferedAudioSourc
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (SourceHandle == null)
|
||||
if (SourceHandle == -1)
|
||||
return;
|
||||
|
||||
if (!_master.IsMainThread())
|
||||
{
|
||||
// We can't run this code inside another thread so tell Clyde to clear it up later.
|
||||
_master.DeleteBufferedSourceOnMainThread(SourceHandle.Value, FilterHandle);
|
||||
_master.DeleteBufferedSourceOnMainThread(SourceHandle, FilterHandle);
|
||||
|
||||
foreach (var handle in BufferHandles)
|
||||
{
|
||||
@@ -92,21 +86,21 @@ internal sealed class BufferedAudioSource : BaseAudioSource, IBufferedAudioSourc
|
||||
if (FilterHandle != 0)
|
||||
EFX.DeleteFilter(FilterHandle);
|
||||
|
||||
AL.DeleteSource(SourceHandle.Value);
|
||||
AL.DeleteSource(SourceHandle);
|
||||
AL.DeleteBuffers(BufferHandles);
|
||||
_master.RemoveBufferedAudioSource(SourceHandle.Value);
|
||||
_master.RemoveBufferedAudioSource(SourceHandle);
|
||||
_master._checkAlError();
|
||||
}
|
||||
|
||||
FilterHandle = 0;
|
||||
SourceHandle = null;
|
||||
SourceHandle = -1;
|
||||
}
|
||||
|
||||
public int GetNumberOfBuffersProcessed()
|
||||
{
|
||||
_checkDisposed();
|
||||
// ReSharper disable once PossibleInvalidOperationException
|
||||
AL.GetSource(SourceHandle!.Value, ALGetSourcei.BuffersProcessed, out var buffersProcessed);
|
||||
AL.GetSource(SourceHandle, ALGetSourcei.BuffersProcessed, out var buffersProcessed);
|
||||
return buffersProcessed;
|
||||
}
|
||||
|
||||
@@ -116,7 +110,7 @@ internal sealed class BufferedAudioSource : BaseAudioSource, IBufferedAudioSourc
|
||||
var entries = Math.Min(Math.Min(handles.Length, BufferHandles.Length), GetNumberOfBuffersProcessed());
|
||||
fixed (int* ptr = handles)
|
||||
{
|
||||
AL.SourceUnqueueBuffers(SourceHandle!.Value, entries, ptr);
|
||||
AL.SourceUnqueueBuffers(SourceHandle, entries, ptr);
|
||||
}
|
||||
|
||||
for (var i = 0; i < entries; i++)
|
||||
@@ -183,7 +177,7 @@ internal sealed class BufferedAudioSource : BaseAudioSource, IBufferedAudioSourc
|
||||
fixed (int* ptr = realHandles)
|
||||
// ReSharper disable once PossibleInvalidOperationException
|
||||
{
|
||||
AL.SourceQueueBuffers(SourceHandle!.Value, handles.Length, ptr);
|
||||
AL.SourceQueueBuffers(SourceHandle, handles.Length, ptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -291,9 +291,9 @@ namespace Robust.Client.Console.Commands
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class SnapGridGetCell : LocalizedCommands
|
||||
internal sealed class SnapGridGetCell : LocalizedEntityCommands
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entManager = default!;
|
||||
[Dependency] private readonly SharedMapSystem _map = default!;
|
||||
|
||||
public override string Command => "sggcell";
|
||||
|
||||
@@ -319,9 +319,10 @@ namespace Robust.Client.Console.Commands
|
||||
return;
|
||||
}
|
||||
|
||||
if (_entManager.TryGetComponent<MapGridComponent>(_entManager.GetEntity(gridNet), out var grid))
|
||||
var gridEnt = EntityManager.GetEntity(gridNet);
|
||||
if (EntityManager.TryGetComponent<MapGridComponent>(gridEnt, out var grid))
|
||||
{
|
||||
foreach (var entity in grid.GetAnchoredEntities(new Vector2i(
|
||||
foreach (var entity in _map.GetAnchoredEntities(gridEnt, grid, new Vector2i(
|
||||
int.Parse(indices.Split(',')[0], CultureInfo.InvariantCulture),
|
||||
int.Parse(indices.Split(',')[1], CultureInfo.InvariantCulture))))
|
||||
{
|
||||
@@ -425,9 +426,9 @@ namespace Robust.Client.Console.Commands
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class GridTileCount : LocalizedCommands
|
||||
internal sealed class GridTileCount : LocalizedEntityCommands
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entManager = default!;
|
||||
[Dependency] private readonly SharedMapSystem _map = default!;
|
||||
|
||||
public override string Command => "gridtc";
|
||||
|
||||
@@ -440,15 +441,15 @@ namespace Robust.Client.Console.Commands
|
||||
}
|
||||
|
||||
if (!NetEntity.TryParse(args[0], out var gridUidNet) ||
|
||||
!_entManager.TryGetEntity(gridUidNet, out var gridUid))
|
||||
!EntityManager.TryGetEntity(gridUidNet, out var gridUid))
|
||||
{
|
||||
shell.WriteLine($"{args[0]} is not a valid entity UID.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (_entManager.TryGetComponent<MapGridComponent>(gridUid, out var grid))
|
||||
if (EntityManager.TryGetComponent<MapGridComponent>(gridUid, out var grid))
|
||||
{
|
||||
shell.WriteLine(grid.GetAllTiles().Count().ToString());
|
||||
shell.WriteLine(_map.GetAllTiles(gridUid.Value, grid).Count().ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -680,12 +681,12 @@ namespace Robust.Client.Console.Commands
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class ChunkInfoCommand : LocalizedCommands
|
||||
internal sealed class ChunkInfoCommand : LocalizedEntityCommands
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entManager = default!;
|
||||
[Dependency] private readonly IMapManager _map = default!;
|
||||
[Dependency] private readonly IEyeManager _eye = default!;
|
||||
[Dependency] private readonly IInputManager _input = default!;
|
||||
[Dependency] private readonly SharedMapSystem _mapSystem = default!;
|
||||
|
||||
public override string Command => "chunkinfo";
|
||||
|
||||
@@ -699,8 +700,8 @@ namespace Robust.Client.Console.Commands
|
||||
return;
|
||||
}
|
||||
|
||||
var mapSystem = _entManager.System<SharedMapSystem>();
|
||||
var chunkIndex = mapSystem.LocalToChunkIndices(gridUid, grid, grid.MapToGrid(mousePos));
|
||||
var mapSystem = EntityManager.System<SharedMapSystem>();
|
||||
var chunkIndex = mapSystem.LocalToChunkIndices(gridUid, grid, _mapSystem.MapToGrid(gridUid, mousePos));
|
||||
var chunk = mapSystem.GetOrAddChunk(gridUid, grid, chunkIndex);
|
||||
|
||||
shell.WriteLine($"worldBounds: {mapSystem.CalcWorldAABB(gridUid, grid, chunk)} localBounds: {chunk.CachedBounds}");
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace Robust.Client.Console.Commands
|
||||
|
||||
public override void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var type = Type.GetType(args[0]);
|
||||
var type = GetType(args[0]);
|
||||
|
||||
if (type == null)
|
||||
{
|
||||
@@ -25,6 +25,17 @@ namespace Robust.Client.Console.Commands
|
||||
shell.WriteLine(sig);
|
||||
}
|
||||
}
|
||||
|
||||
private Type? GetType(string name)
|
||||
{
|
||||
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
|
||||
{
|
||||
if (assembly.GetType(name) is { } type)
|
||||
return type;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
|
||||
namespace Robust.Client.Console.Commands
|
||||
{
|
||||
public sealed class GridChunkBBCommand : LocalizedCommands
|
||||
public sealed class GridChunkBBCommand : LocalizedEntityCommands
|
||||
{
|
||||
[Dependency] private readonly GridChunkBoundsDebugSystem _system = default!;
|
||||
|
||||
public override string Command => "showchunkbb";
|
||||
|
||||
public override void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
EntitySystem.Get<GridChunkBoundsDebugSystem>().Enabled ^= true;
|
||||
_system.Enabled ^= true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,7 +204,7 @@ Suspendisse hendrerit blandit urna ut laoreet. Suspendisse ac elit at erat males
|
||||
private Control TabRichText()
|
||||
{
|
||||
var label = new RichTextLabel();
|
||||
label.SetMessage(FormattedMessage.FromMarkup(Lipsum));
|
||||
label.SetMessage(FormattedMessage.FromMarkupOrThrow(Lipsum));
|
||||
|
||||
TabContainer.SetTabTitle(label, "RichText");
|
||||
return label;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Numerics;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.GameObjects;
|
||||
@@ -14,6 +15,8 @@ namespace Robust.Client.Debugging
|
||||
{
|
||||
[Dependency] private readonly IOverlayManager _overlayManager = default!;
|
||||
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
||||
[Dependency] private readonly TransformSystem _transform = default!;
|
||||
|
||||
|
||||
private bool _debugPositions;
|
||||
private bool _debugRotations;
|
||||
@@ -35,7 +38,7 @@ namespace Robust.Client.Debugging
|
||||
|
||||
if (value && !_overlayManager.HasOverlay<EntityPositionOverlay>())
|
||||
{
|
||||
_overlayManager.AddOverlay(new EntityPositionOverlay(_lookup, EntityManager));
|
||||
_overlayManager.AddOverlay(new EntityPositionOverlay(_lookup, EntityManager, _transform));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -74,13 +77,15 @@ namespace Robust.Client.Debugging
|
||||
{
|
||||
private readonly EntityLookupSystem _lookup;
|
||||
private readonly IEntityManager _entityManager;
|
||||
private readonly SharedTransformSystem _transform;
|
||||
|
||||
public override OverlaySpace Space => OverlaySpace.WorldSpace;
|
||||
|
||||
public EntityPositionOverlay(EntityLookupSystem lookup, IEntityManager entityManager)
|
||||
public EntityPositionOverlay(EntityLookupSystem lookup, IEntityManager entityManager, SharedTransformSystem transform)
|
||||
{
|
||||
_lookup = lookup;
|
||||
_entityManager = entityManager;
|
||||
_transform = transform;
|
||||
}
|
||||
|
||||
protected internal override void Draw(in OverlayDrawArgs args)
|
||||
@@ -88,11 +93,10 @@ namespace Robust.Client.Debugging
|
||||
const float stubLength = 0.25f;
|
||||
|
||||
var worldHandle = (DrawingHandleWorld) args.DrawingHandle;
|
||||
var xformQuery = _entityManager.GetEntityQuery<TransformComponent>();
|
||||
|
||||
foreach (var entity in _lookup.GetEntitiesIntersecting(args.MapId, args.WorldBounds))
|
||||
{
|
||||
var (center, worldRotation) = xformQuery.GetComponent(entity).GetWorldPositionRotation();
|
||||
var (center, worldRotation) = _transform.GetWorldPositionRotation(entity);
|
||||
|
||||
var xLine = worldRotation.RotateVec(Vector2.UnitX);
|
||||
var yLine = worldRotation.RotateVec(Vector2.UnitY);
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Input;
|
||||
using Robust.Client.Player;
|
||||
@@ -78,6 +79,14 @@ namespace Robust.Client.Debugging
|
||||
internal int PointCount;
|
||||
|
||||
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
|
||||
[Dependency] private readonly EntityLookupSystem _entityLookup = default!;
|
||||
[Dependency] private readonly TransformSystem _transform = default!;
|
||||
[Dependency] private readonly IOverlayManager _overlay = default!;
|
||||
[Dependency] private readonly IEyeManager _eye = default!;
|
||||
[Dependency] private readonly IInputManager _input = default!;
|
||||
[Dependency] private readonly IMapManager _map = default!;
|
||||
[Dependency] private readonly IPlayerManager _player = default!;
|
||||
[Dependency] private readonly IResourceCache _resourceCache = default!;
|
||||
|
||||
internal ContactPoint[] Points = new ContactPoint[MaxContactPoints];
|
||||
|
||||
@@ -89,20 +98,21 @@ namespace Robust.Client.Debugging
|
||||
if (value == _flags) return;
|
||||
|
||||
if (_flags == PhysicsDebugFlags.None)
|
||||
IoCManager.Resolve<IOverlayManager>().AddOverlay(
|
||||
_overlay.AddOverlay(
|
||||
new PhysicsDebugOverlay(
|
||||
EntityManager,
|
||||
IoCManager.Resolve<IEyeManager>(),
|
||||
IoCManager.Resolve<IInputManager>(),
|
||||
IoCManager.Resolve<IMapManager>(),
|
||||
IoCManager.Resolve<IPlayerManager>(),
|
||||
IoCManager.Resolve<IResourceCache>(),
|
||||
_eye,
|
||||
_input,
|
||||
_map,
|
||||
_player,
|
||||
_resourceCache,
|
||||
this,
|
||||
Get<EntityLookupSystem>(),
|
||||
Get<SharedPhysicsSystem>()));
|
||||
_entityLookup,
|
||||
_physics,
|
||||
_transform));
|
||||
|
||||
if (value == PhysicsDebugFlags.None)
|
||||
IoCManager.Resolve<IOverlayManager>().RemoveOverlay(typeof(PhysicsDebugOverlay));
|
||||
_overlay.RemoveOverlay(typeof(PhysicsDebugOverlay));
|
||||
|
||||
_flags = value;
|
||||
}
|
||||
@@ -198,6 +208,7 @@ namespace Robust.Client.Debugging
|
||||
private readonly DebugPhysicsSystem _debugPhysicsSystem;
|
||||
private readonly EntityLookupSystem _lookup;
|
||||
private readonly SharedPhysicsSystem _physicsSystem;
|
||||
private readonly SharedTransformSystem _transformSystem;
|
||||
|
||||
public override OverlaySpace Space => OverlaySpace.WorldSpace | OverlaySpace.ScreenSpace;
|
||||
|
||||
@@ -208,7 +219,7 @@ namespace Robust.Client.Debugging
|
||||
private HashSet<Joint> _drawnJoints = new();
|
||||
private List<Entity<MapGridComponent>> _grids = new();
|
||||
|
||||
public PhysicsDebugOverlay(IEntityManager entityManager, IEyeManager eyeManager, IInputManager inputManager, IMapManager mapManager, IPlayerManager playerManager, IResourceCache cache, DebugPhysicsSystem system, EntityLookupSystem lookup, SharedPhysicsSystem physicsSystem)
|
||||
public PhysicsDebugOverlay(IEntityManager entityManager, IEyeManager eyeManager, IInputManager inputManager, IMapManager mapManager, IPlayerManager playerManager, IResourceCache cache, DebugPhysicsSystem system, EntityLookupSystem lookup, SharedPhysicsSystem physicsSystem, SharedTransformSystem transformSystem)
|
||||
{
|
||||
_entityManager = entityManager;
|
||||
_eyeManager = eyeManager;
|
||||
@@ -218,6 +229,7 @@ namespace Robust.Client.Debugging
|
||||
_debugPhysicsSystem = system;
|
||||
_lookup = lookup;
|
||||
_physicsSystem = physicsSystem;
|
||||
_transformSystem = transformSystem;
|
||||
_font = new VectorFont(cache.GetResource<FontResource>("/EngineFonts/NotoSans/NotoSans-Regular.ttf"), 10);
|
||||
}
|
||||
|
||||
@@ -327,7 +339,7 @@ namespace Robust.Client.Debugging
|
||||
{
|
||||
if (jointComponent.JointCount == 0 ||
|
||||
!_entityManager.TryGetComponent(uid, out TransformComponent? xf1) ||
|
||||
!viewAABB.Contains(xf1.WorldPosition)) continue;
|
||||
!viewAABB.Contains(_transformSystem.GetWorldPosition(xf1))) continue;
|
||||
|
||||
foreach (var (_, joint) in jointComponent.Joints)
|
||||
{
|
||||
@@ -517,8 +529,8 @@ namespace Robust.Client.Debugging
|
||||
if (!_entityManager.TryGetComponent(joint.BodyAUid, out TransformComponent? xform1) ||
|
||||
!_entityManager.TryGetComponent(joint.BodyBUid, out TransformComponent? xform2)) return;
|
||||
|
||||
var matrix1 = xform1.WorldMatrix;
|
||||
var matrix2 = xform2.WorldMatrix;
|
||||
var matrix1 = _transformSystem.GetWorldMatrix(xform1);
|
||||
var matrix2 = _transformSystem.GetWorldMatrix(xform2);
|
||||
|
||||
var xf1 = new Vector2(matrix1.M31, matrix1.M32);
|
||||
var xf2 = new Vector2(matrix2.M31, matrix2.M32);
|
||||
@@ -526,8 +538,8 @@ namespace Robust.Client.Debugging
|
||||
var p1 = Vector2.Transform(joint.LocalAnchorA, matrix1);
|
||||
var p2 = Vector2.Transform(joint.LocalAnchorB, matrix2);
|
||||
|
||||
var xfa = new Transform(xf1, xform1.WorldRotation);
|
||||
var xfb = new Transform(xf2, xform2.WorldRotation);
|
||||
var xfa = new Transform(xf1, _transformSystem.GetWorldRotation(xform1));
|
||||
var xfb = new Transform(xf2, _transformSystem.GetWorldRotation(xform2));
|
||||
|
||||
switch (joint)
|
||||
{
|
||||
|
||||
@@ -48,16 +48,6 @@ namespace Robust.Client.GameObjects
|
||||
return base.CreateEntity(prototypeName, out metadata);
|
||||
}
|
||||
|
||||
void IClientEntityManagerInternal.InitializeEntity(EntityUid entity, MetaDataComponent? meta)
|
||||
{
|
||||
base.InitializeEntity(entity, meta);
|
||||
}
|
||||
|
||||
void IClientEntityManagerInternal.StartEntity(EntityUid entity)
|
||||
{
|
||||
base.StartEntity(entity);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void DirtyEntity(EntityUid uid, MetaDataComponent? meta = null)
|
||||
{
|
||||
|
||||
@@ -18,6 +18,8 @@ namespace Robust.Client.GameObjects
|
||||
[Dependency] private readonly IEyeManager _eyeManager = default!;
|
||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||
[Dependency] private readonly IOverlayManager _overlayManager = default!;
|
||||
[Dependency] private readonly TransformSystem _transform = default!;
|
||||
[Dependency] private readonly SharedMapSystem _map = default!;
|
||||
|
||||
private GridChunkBoundsOverlay? _overlay;
|
||||
|
||||
@@ -36,7 +38,9 @@ namespace Robust.Client.GameObjects
|
||||
_overlay = new GridChunkBoundsOverlay(
|
||||
EntityManager,
|
||||
_eyeManager,
|
||||
_mapManager);
|
||||
_mapManager,
|
||||
_transform,
|
||||
_map);
|
||||
|
||||
_overlayManager.AddOverlay(_overlay);
|
||||
}
|
||||
@@ -56,16 +60,20 @@ namespace Robust.Client.GameObjects
|
||||
private readonly IEntityManager _entityManager;
|
||||
private readonly IEyeManager _eyeManager;
|
||||
private readonly IMapManager _mapManager;
|
||||
private readonly SharedTransformSystem _transformSystem;
|
||||
private readonly SharedMapSystem _mapSystem;
|
||||
|
||||
public override OverlaySpace Space => OverlaySpace.WorldSpace;
|
||||
|
||||
private List<Entity<MapGridComponent>> _grids = new();
|
||||
|
||||
public GridChunkBoundsOverlay(IEntityManager entManager, IEyeManager eyeManager, IMapManager mapManager)
|
||||
public GridChunkBoundsOverlay(IEntityManager entManager, IEyeManager eyeManager, IMapManager mapManager, SharedTransformSystem transformSystem, SharedMapSystem mapSystem)
|
||||
{
|
||||
_entityManager = entManager;
|
||||
_eyeManager = eyeManager;
|
||||
_mapManager = mapManager;
|
||||
_transformSystem = transformSystem;
|
||||
_mapSystem = mapSystem;
|
||||
}
|
||||
|
||||
protected internal override void Draw(in OverlayDrawArgs args)
|
||||
@@ -78,11 +86,11 @@ namespace Robust.Client.GameObjects
|
||||
_mapManager.FindGridsIntersecting(currentMap, viewport, ref _grids);
|
||||
foreach (var grid in _grids)
|
||||
{
|
||||
var worldMatrix = _entityManager.GetComponent<TransformComponent>(grid).WorldMatrix;
|
||||
var worldMatrix = _transformSystem.GetWorldMatrix(grid);
|
||||
worldHandle.SetTransform(worldMatrix);
|
||||
var transform = new Transform(Vector2.Zero, Angle.Zero);
|
||||
|
||||
var chunkEnumerator = grid.Comp.GetMapChunks(viewport);
|
||||
var chunkEnumerator = _mapSystem.GetMapChunks(grid.Owner, grid.Comp, viewport);
|
||||
|
||||
while (chunkEnumerator.MoveNext(out var chunk))
|
||||
{
|
||||
|
||||
@@ -196,7 +196,7 @@ namespace Robust.Client.GameObjects
|
||||
wOffset = new Vector2(wX, wY);
|
||||
}
|
||||
|
||||
var coords = EntityCoordinates.FromMap(pent, _transform.GetMapCoordinates(pent).Offset(wOffset), _transform, EntityManager);
|
||||
var coords = _transform.ToCoordinates(pent, _transform.GetMapCoordinates(pent).Offset(wOffset));
|
||||
var funcId = _inputManager.NetworkBindMap.KeyFunctionID(keyFunction);
|
||||
|
||||
var message = new ClientFullInputCmdMessage(_timing.CurTick,
|
||||
|
||||
@@ -66,6 +66,11 @@ namespace Robust.Client.GameObjects
|
||||
_sawmill = _logManager.GetSawmill("sprite");
|
||||
}
|
||||
|
||||
public bool IsVisible(Layer layer)
|
||||
{
|
||||
return layer.Visible && layer.CopyToShaderParameters == null;
|
||||
}
|
||||
|
||||
private void OnInit(EntityUid uid, SpriteComponent component, ComponentInit args)
|
||||
{
|
||||
// I'm not 100% this is needed, but I CBF with this ATM. Somebody kill server sprite component please.
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Robust.Client.GameObjects
|
||||
{
|
||||
[Dependency] private readonly IEyeManager _eyeManager = default!;
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
[Dependency] private readonly TransformSystem _transform = default!;
|
||||
|
||||
internal bool Enabled { get; set; }
|
||||
|
||||
@@ -43,7 +44,7 @@ namespace Robust.Client.GameObjects
|
||||
return;
|
||||
}
|
||||
|
||||
var screenPos = _eyeManager.WorldToScreen(EntityManager.GetComponent<TransformComponent>(player.Value).WorldPosition);
|
||||
var screenPos = _eyeManager.WorldToScreen(_transform.GetWorldPosition(Transform(player.Value)));
|
||||
LayoutContainer.SetPosition(_label, screenPos + new Vector2(0, 50));
|
||||
_label.Visible = true;
|
||||
|
||||
|
||||
@@ -7,9 +7,5 @@ namespace Robust.Client.GameObjects
|
||||
// These methods are used by the Game State Manager.
|
||||
|
||||
EntityUid CreateEntity(string? prototypeName, out MetaDataComponent metadata);
|
||||
|
||||
void InitializeEntity(EntityUid entity, MetaDataComponent? meta = null);
|
||||
|
||||
void StartEntity(EntityUid entity);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,13 +34,13 @@ namespace Robust.Client.Placement.Modes
|
||||
{
|
||||
var from = ScreenToWorld(new Vector2(a, 0));
|
||||
var to = ScreenToWorld(new Vector2(a, viewportSize.Y));
|
||||
args.WorldHandle.DrawLine(from, to, new Color(0, 0, 1f));
|
||||
args.WorldHandle.DrawLine(from, to, new Color(0, 0, 0.3f));
|
||||
}
|
||||
for (var a = gridstart.Y; a < viewportSize.Y; a += SnapSize * EyeManager.PixelsPerMeter)
|
||||
{
|
||||
var from = ScreenToWorld(new Vector2(0, a));
|
||||
var to = ScreenToWorld(new Vector2(viewportSize.X, a));
|
||||
args.WorldHandle.DrawLine(from, to, new Color(0, 0, 1f));
|
||||
args.WorldHandle.DrawLine(from, to, new Color(0, 0, 0.3f));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -327,8 +327,7 @@ public sealed class EntitySpawningUIController : UIController
|
||||
if (_window == null || _window.Disposed)
|
||||
return;
|
||||
|
||||
var textures = SpriteComponent.GetPrototypeTextures(prototype, _resources).Select(o => o.Default).ToList();
|
||||
var button = _window.InsertEntityButton(prototype, insertFirst, index, textures);
|
||||
var button = _window.InsertEntityButton(prototype, insertFirst, index);
|
||||
|
||||
button.ActualButton.OnToggled += OnEntityButtonToggled;
|
||||
}
|
||||
|
||||
@@ -33,10 +33,7 @@ public class EntityPrototypeView : SpriteView
|
||||
|
||||
_currentPrototype = entProto;
|
||||
SetEntity(null);
|
||||
if (_ourEntity != null)
|
||||
{
|
||||
EntMan.DeleteEntity(_ourEntity);
|
||||
}
|
||||
EntMan.DeleteEntity(_ourEntity);
|
||||
|
||||
if (_currentPrototype != null)
|
||||
{
|
||||
@@ -57,8 +54,6 @@ public class EntityPrototypeView : SpriteView
|
||||
protected override void ExitedTree()
|
||||
{
|
||||
base.ExitedTree();
|
||||
|
||||
if (!EntMan.Deleted(_ourEntity))
|
||||
EntMan.QueueDeleteEntity(_ourEntity);
|
||||
EntMan.TryQueueDeleteEntity(_ourEntity);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using Robust.Client.Graphics;
|
||||
@@ -14,6 +14,7 @@ namespace Robust.Client.UserInterface.Controls
|
||||
public const string StyleClassOptionButton = "optionButton";
|
||||
public const string StyleClassPopup = "optionButtonPopup";
|
||||
public const string StyleClassOptionTriangle = "optionTriangle";
|
||||
public const string StyleClassOptionsBackground = "optionButtonBackground";
|
||||
public readonly ScrollContainer OptionsScroll;
|
||||
|
||||
private readonly List<ButtonData> _buttonData = new();
|
||||
@@ -75,7 +76,12 @@ namespace Robust.Client.UserInterface.Controls
|
||||
|
||||
_popup = new Popup()
|
||||
{
|
||||
Children = { new PanelContainer(), OptionsScroll },
|
||||
Children = {
|
||||
new PanelContainer {
|
||||
StyleClasses = { StyleClassOptionsBackground }
|
||||
},
|
||||
OptionsScroll
|
||||
},
|
||||
StyleClasses = { StyleClassPopup }
|
||||
};
|
||||
_popup.OnPopupHide += OnPopupHide;
|
||||
|
||||
@@ -38,6 +38,18 @@ namespace Robust.Client.UserInterface.Controls
|
||||
}
|
||||
}
|
||||
|
||||
public string? Text
|
||||
{
|
||||
get => _message?.ToMarkup();
|
||||
set
|
||||
{
|
||||
if (value == null)
|
||||
_message?.Clear();
|
||||
else
|
||||
_message?.AddMarkupPermissive(value);
|
||||
}
|
||||
}
|
||||
|
||||
public RichTextLabel()
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
|
||||
@@ -12,7 +12,7 @@ public sealed class EntitySpawnButton : Control
|
||||
public EntityPrototype Prototype { get; set; } = default!;
|
||||
public Button ActualButton { get; private set; }
|
||||
public Label EntityLabel { get; private set; }
|
||||
public LayeredTextureRect EntityTextureRects { get; private set; }
|
||||
public EntityPrototypeView EntityTextureRects {get; private set; }
|
||||
public int Index { get; set; }
|
||||
|
||||
public EntitySpawnButton()
|
||||
@@ -27,13 +27,12 @@ public sealed class EntitySpawnButton : Control
|
||||
Orientation = BoxContainer.LayoutOrientation.Horizontal,
|
||||
Children =
|
||||
{
|
||||
(EntityTextureRects = new LayeredTextureRect
|
||||
(EntityTextureRects = new EntityPrototypeView
|
||||
{
|
||||
MinSize = new Vector2(32, 32),
|
||||
HorizontalAlignment = HAlignment.Center,
|
||||
VerticalAlignment = VAlignment.Center,
|
||||
Stretch = TextureRect.StretchMode.KeepAspectCentered,
|
||||
CanShrink = true
|
||||
Stretch = SpriteView.StretchMode.Fill
|
||||
}),
|
||||
(EntityLabel = new Label
|
||||
{
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace Robust.Client.UserInterface.CustomControls
|
||||
}
|
||||
|
||||
// Create a spawn button and insert it into the start or end of the list.
|
||||
public EntitySpawnButton InsertEntityButton(EntityPrototype prototype, bool insertFirst, int index, List<Texture> textures)
|
||||
public EntitySpawnButton InsertEntityButton(EntityPrototype prototype, bool insertFirst, int index)
|
||||
{
|
||||
var button = new EntitySpawnButton
|
||||
{
|
||||
@@ -67,7 +67,7 @@ namespace Robust.Client.UserInterface.CustomControls
|
||||
}
|
||||
|
||||
var rect = button.EntityTextureRects;
|
||||
rect.Textures = textures;
|
||||
rect.SetPrototype(prototype.ID);
|
||||
|
||||
PrototypeList.AddChild(button);
|
||||
if (insertFirst)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Shared.Utility;
|
||||
@@ -7,41 +8,135 @@ namespace Robust.Client.ViewVariables.Editors
|
||||
{
|
||||
sealed class VVPropEditorEnum : VVPropEditor
|
||||
{
|
||||
private readonly Dictionary<int, int> _idToValue = new();
|
||||
private readonly Dictionary<int, int> _valueToId = new();
|
||||
|
||||
private readonly Dictionary<int, Button> _buttons = new();
|
||||
|
||||
private int _invalidOptionId;
|
||||
|
||||
private int _value;
|
||||
private bool _flagEnum;
|
||||
|
||||
protected override Control MakeUI(object? value)
|
||||
{
|
||||
DebugTools.Assert(value!.GetType().IsEnum);
|
||||
var enumType = value.GetType();
|
||||
var enumList = Enum.GetValues(enumType);
|
||||
var enumNames = Enum.GetNames(enumType);
|
||||
var underlyingType = Enum.GetUnderlyingType(enumType);
|
||||
|
||||
var convertedValue = Convert.ToInt32(value);
|
||||
|
||||
var hBoxContainer = new BoxContainer
|
||||
{
|
||||
Orientation = BoxContainer.LayoutOrientation.Horizontal,
|
||||
};
|
||||
|
||||
var optionButton = new OptionButton();
|
||||
bool hasValue = false;
|
||||
hBoxContainer.AddChild(optionButton);
|
||||
|
||||
var hasValue = false;
|
||||
var selectedId = 0;
|
||||
var i = 0;
|
||||
foreach (var val in enumList)
|
||||
{
|
||||
var label = val?.ToString();
|
||||
if (label == null)
|
||||
continue;
|
||||
optionButton.AddItem(label, Convert.ToInt32(val));
|
||||
hasValue |= Convert.ToInt32(val) == Convert.ToInt32(value);
|
||||
var label = enumNames[i];
|
||||
var entry = Convert.ToInt32(val);
|
||||
_idToValue.Add(i, entry);
|
||||
_valueToId.TryAdd(entry, i);
|
||||
optionButton.AddItem(label, i);
|
||||
if (entry == convertedValue)
|
||||
{
|
||||
hasValue = true;
|
||||
selectedId = i;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
|
||||
// TODO properly support enum flags
|
||||
if (!hasValue)
|
||||
optionButton.AddItem(value.ToString() ?? string.Empty, Convert.ToInt32(value));
|
||||
var isFlags = enumType.GetCustomAttributes(typeof(FlagsAttribute), false).Length > 0;
|
||||
|
||||
optionButton.SelectId(Convert.ToInt32(value));
|
||||
// Handle unnamed enum values.
|
||||
if (!hasValue || isFlags)
|
||||
{
|
||||
_invalidOptionId = i;
|
||||
_idToValue.Add(_invalidOptionId, convertedValue);
|
||||
optionButton.AddItem(string.Empty, _invalidOptionId);
|
||||
if (!hasValue)
|
||||
selectedId = _invalidOptionId;
|
||||
}
|
||||
|
||||
optionButton.SelectId(selectedId);
|
||||
optionButton.Disabled = ReadOnly;
|
||||
|
||||
// Flags
|
||||
if (isFlags)
|
||||
{
|
||||
_flagEnum = true;
|
||||
var flags = 0;
|
||||
foreach (var val in enumList)
|
||||
{
|
||||
var entry = Convert.ToInt32(val);
|
||||
if ((entry & flags) != 0 || entry == 0)
|
||||
continue;
|
||||
|
||||
flags |= entry;
|
||||
var button = new Button
|
||||
{
|
||||
Text = enumNames[_valueToId[entry]],
|
||||
};
|
||||
_buttons.Add(entry, button);
|
||||
hBoxContainer.AddChild(button);
|
||||
button.ToggleMode = true;
|
||||
if (!ReadOnly)
|
||||
{
|
||||
button.OnToggled += args =>
|
||||
{
|
||||
if (args.Pressed)
|
||||
SelectButtons(_value | entry);
|
||||
else
|
||||
SelectButtons(_value & ~entry);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!ReadOnly)
|
||||
{
|
||||
var underlyingType = Enum.GetUnderlyingType(value.GetType());
|
||||
optionButton.OnItemSelected += e =>
|
||||
{
|
||||
optionButton.SelectId(e.Id);
|
||||
ValueChanged(Convert.ChangeType(e.Id, underlyingType));
|
||||
if (e.Id == _invalidOptionId)
|
||||
{
|
||||
optionButton.SelectId(_invalidOptionId);
|
||||
return;
|
||||
}
|
||||
|
||||
SelectButtons(_idToValue[e.Id]);
|
||||
};
|
||||
}
|
||||
|
||||
return optionButton;
|
||||
SelectButtons(convertedValue, false);
|
||||
|
||||
return hBoxContainer;
|
||||
|
||||
void SelectButtons(int flags, bool changeValue = true)
|
||||
{
|
||||
_value = flags;
|
||||
if (_flagEnum)
|
||||
{
|
||||
foreach (var (buttonFlags, button) in _buttons)
|
||||
{
|
||||
button.Pressed = (buttonFlags & flags) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_valueToId.TryGetValue(flags, out var id)
|
||||
|| !optionButton.TrySelectId(id))
|
||||
optionButton.SelectId(_invalidOptionId);
|
||||
|
||||
if (changeValue)
|
||||
ValueChanged(Convert.ChangeType(flags, underlyingType));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ namespace Robust.Client.ViewVariables.Editors
|
||||
{
|
||||
var protoMan = IoCManager.Resolve<IPrototypeManager>();
|
||||
|
||||
if (!protoMan.TryGetVariantFrom(typeof(T), out var variant)) return;
|
||||
if (!protoMan.TryGetKindFrom(typeof(T), out var variant)) return;
|
||||
|
||||
var list = new List<string>();
|
||||
|
||||
|
||||
@@ -32,6 +32,8 @@ public static class Diagnostics
|
||||
public const string IdUncachedRegex = "RA0026";
|
||||
public const string IdDataFieldRedundantTag = "RA0027";
|
||||
public const string IdMustCallBase = "RA0028";
|
||||
public const string IdDataFieldNoVVReadWrite = "RA0029";
|
||||
public const string IdUseNonGenericVariant = "RA0030";
|
||||
|
||||
public static SuppressionDescriptor MeansImplicitAssignment =>
|
||||
new SuppressionDescriptor("RADC1000", "CS0649", "Marked as implicitly assigned.");
|
||||
|
||||
@@ -3,6 +3,10 @@ using Robust.Shared.Serialization.Manager.Attributes;
|
||||
|
||||
namespace Robust.Server.GameObjects
|
||||
{
|
||||
/// <summary>
|
||||
/// Controls PVS visibility of entities. THIS COMPONENT CONTROLS WHETHER ENTITIES ARE NETWORKED TO PLAYERS
|
||||
/// AND SHOULD NOT BE USED AS THE SOLE WAY TO HIDE AN ENTITY FROM A PLAYER.
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
[Access(typeof(VisibilitySystem))]
|
||||
public sealed partial class VisibilityComponent : Component
|
||||
|
||||
@@ -93,8 +93,10 @@ namespace Robust.Server
|
||||
deps.Register<IServerNetConfigurationManager, ServerNetConfigurationManager>();
|
||||
deps.Register<INetConfigurationManagerInternal, ServerNetConfigurationManager>();
|
||||
deps.Register<IGamePrototypeLoadManager, GamePrototypeLoadManager>();
|
||||
deps.Register<GamePrototypeLoadManager>();
|
||||
deps.Register<NetworkResourceManager>();
|
||||
deps.Register<IHttpClientHolder, HttpClientHolder>();
|
||||
deps.Register<UploadedContentManager>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,8 +24,6 @@ public sealed class GamePrototypeLoadManager : SharedPrototypeLoadManager
|
||||
base.Initialize();
|
||||
|
||||
_sawmill = _logManager.GetSawmill("adminbus");
|
||||
|
||||
_netManager.Connected += NetManagerOnConnected;
|
||||
}
|
||||
|
||||
public override void SendGamePrototype(string prototype)
|
||||
@@ -50,7 +48,7 @@ public sealed class GamePrototypeLoadManager : SharedPrototypeLoadManager
|
||||
}
|
||||
}
|
||||
|
||||
private void NetManagerOnConnected(object? sender, NetChannelArgs e)
|
||||
internal void SendToNewUser(INetChannel channel)
|
||||
{
|
||||
// Just dump all the prototypes on connect, before them missing could be an issue.
|
||||
foreach (var prototype in LoadedPrototypes)
|
||||
@@ -59,7 +57,7 @@ public sealed class GamePrototypeLoadManager : SharedPrototypeLoadManager
|
||||
{
|
||||
PrototypeData = prototype
|
||||
};
|
||||
e.Channel.SendMessage(msg);
|
||||
channel.SendMessage(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ public sealed class NetworkResourceManager : SharedNetworkResourceManager
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_serverNetManager.Connected += ServerNetManagerOnConnected;
|
||||
_cfgManager.OnValueChanged(CVars.ResourceUploadingEnabled, value => Enabled = value, true);
|
||||
_cfgManager.OnValueChanged(CVars.ResourceUploadingLimitMb, value => SizeLimit = value, true);
|
||||
}
|
||||
@@ -65,14 +64,14 @@ public sealed class NetworkResourceManager : SharedNetworkResourceManager
|
||||
OnResourceUploaded?.Invoke(session, msg);
|
||||
}
|
||||
|
||||
private void ServerNetManagerOnConnected(object? sender, NetChannelArgs e)
|
||||
internal void SendToNewUser(INetChannel channel)
|
||||
{
|
||||
foreach (var (path, data) in ContentRoot.GetAllFiles())
|
||||
{
|
||||
var msg = new NetworkResourceUploadMessage();
|
||||
msg.RelativePath = path;
|
||||
msg.Data = data;
|
||||
e.Channel.SendMessage(msg);
|
||||
channel.SendMessage(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
28
Robust.Server/Upload/UploadedContentManager.cs
Normal file
28
Robust.Server/Upload/UploadedContentManager.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Network;
|
||||
|
||||
namespace Robust.Server.Upload;
|
||||
|
||||
/// <summary>
|
||||
/// Responsible for sending uploaded content to clients when they connect.
|
||||
/// </summary>
|
||||
internal sealed class UploadedContentManager
|
||||
{
|
||||
[Dependency] private readonly IServerNetManager _netManager = default!;
|
||||
[Dependency] private readonly GamePrototypeLoadManager _prototypeLoadManager = default!;
|
||||
[Dependency] private readonly NetworkResourceManager _networkResourceManager = default!;
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
_netManager.Connected += NetManagerOnConnected;
|
||||
}
|
||||
|
||||
private void NetManagerOnConnected(object? sender, NetChannelArgs e)
|
||||
{
|
||||
// This just shells out to the other managers, ensuring they are ordered properly.
|
||||
// Resources must be done before prototypes.
|
||||
// Note: both net messages sent here are on the same group and are therefore ordered.
|
||||
_networkResourceManager.SendToNewUser(e.Channel);
|
||||
_prototypeLoadManager.SendToNewUser(e.Channel);
|
||||
}
|
||||
}
|
||||
@@ -997,12 +997,7 @@ namespace Robust.Shared.Maths
|
||||
/// <param name="other">The Color structure to compare to.</param>
|
||||
/// <returns>True if both Color structures contain the same components; false otherwise.</returns>
|
||||
public readonly bool Equals(Color other)
|
||||
{
|
||||
// TODO COLOR why is this approximate
|
||||
// This method literally doesn't do what its docstring says it does.
|
||||
// If people wanted approximate equality, they can check that manually.
|
||||
return MathHelper.CloseToPercent(this, other);
|
||||
}
|
||||
=> RGBA == other.RGBA;
|
||||
|
||||
[PublicAPI]
|
||||
public enum BlendFactor : byte
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
|
||||
#if ROBUST_ANALYZERS_IMPL
|
||||
namespace Robust.Shared.Analyzers.Implementation;
|
||||
#else
|
||||
namespace Robust.Shared.Analyzers;
|
||||
#endif
|
||||
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
public sealed class PreferNonGenericVariantForAttribute : Attribute
|
||||
{
|
||||
public readonly Type[] ForTypes;
|
||||
|
||||
public PreferNonGenericVariantForAttribute(params Type[] forTypes)
|
||||
{
|
||||
ForTypes = forTypes;
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,8 @@ namespace Robust.Shared.CPUJob.JobQueues
|
||||
/// <typeparam name="T">The type of result this job generates</typeparam>
|
||||
public abstract class Job<T> : IJob
|
||||
{
|
||||
private readonly ISawmill _sawmill = Logger.GetSawmill("job");
|
||||
|
||||
public JobStatus Status { get; private set; } = JobStatus.Pending;
|
||||
|
||||
/// <summary>
|
||||
@@ -184,7 +186,7 @@ namespace Robust.Shared.CPUJob.JobQueues
|
||||
{
|
||||
// TODO: Should this be exposed differently?
|
||||
// I feel that people might forget to check whether the job failed.
|
||||
Logger.ErrorS("job", "Job failed on exception:\n{0}", e);
|
||||
_sawmill.Error("Job failed on exception:\n{0}", e);
|
||||
Exception = e;
|
||||
_taskTcs.TrySetException(e);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using Lidgren.Network;
|
||||
using Robust.Shared.Audio;
|
||||
@@ -1759,5 +1758,16 @@ namespace Robust.Shared
|
||||
/// </summary>
|
||||
public static readonly CVarDef<bool> LaunchContentBundle =
|
||||
CVarDef.Create("launch.content_bundle", false, CVar.CLIENTONLY);
|
||||
|
||||
/*
|
||||
* TOOLSHED
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// The max range that can be passed to the nearby toolshed command.
|
||||
/// Any higher value will cause an exception.
|
||||
/// </summary>
|
||||
public static readonly CVarDef<int> ToolshedNearbyLimit =
|
||||
CVarDef.Create("toolshed.nearby_limit", 200, CVar.SERVER | CVar.REPLICATED);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ public abstract class ComponentTreeSystem<TTreeComp, TComp> : EntitySystem
|
||||
[Dependency] private readonly RecursiveMoveSystem _recursiveMoveSys = default!;
|
||||
[Dependency] protected readonly SharedTransformSystem XformSystem = default!;
|
||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||
[Dependency] private readonly SharedMapSystem _mapSystem = default!;
|
||||
|
||||
private readonly Queue<ComponentTreeEntry<TComp>> _updateQueue = new();
|
||||
private readonly HashSet<EntityUid> _updated = new();
|
||||
@@ -288,11 +289,9 @@ public abstract class ComponentTreeSystem<TTreeComp, TComp> : EntitySystem
|
||||
return true;
|
||||
}, includeMap: false);
|
||||
|
||||
var mapUid = _mapManager.GetMapEntityId(mapId);
|
||||
|
||||
if (TryComp(mapUid, out TTreeComp? mapTreeComp))
|
||||
if (_mapSystem.TryGetMap(mapId, out var mapUid) && TryComp(mapUid, out TTreeComp? mapTreeComp))
|
||||
{
|
||||
state.trees.Add((mapUid, mapTreeComp));
|
||||
state.trees.Add((mapUid.Value, mapTreeComp));
|
||||
}
|
||||
|
||||
return state.trees;
|
||||
|
||||
@@ -8,10 +8,9 @@ using Robust.Shared.Map.Components;
|
||||
|
||||
namespace Robust.Shared.Console.Commands;
|
||||
|
||||
sealed class AddMapCommand : LocalizedCommands
|
||||
sealed class AddMapCommand : LocalizedEntityCommands
|
||||
{
|
||||
[Dependency] private readonly IMapManagerInternal _map = default!;
|
||||
[Dependency] private readonly IEntityManager _entMan = default!;
|
||||
[Dependency] private readonly SharedMapSystem _mapSystem = default!;
|
||||
|
||||
public override string Command => "addmap";
|
||||
public override bool RequireServerOrSingleplayer => true;
|
||||
@@ -23,10 +22,10 @@ sealed class AddMapCommand : LocalizedCommands
|
||||
|
||||
var mapId = new MapId(int.Parse(args[0]));
|
||||
|
||||
if (!_map.MapExists(mapId))
|
||||
if (!_mapSystem.MapExists(mapId))
|
||||
{
|
||||
var init = args.Length < 2 || !bool.Parse(args[1]);
|
||||
_entMan.System<SharedMapSystem>().CreateMap(mapId, runMapInit: init);
|
||||
EntityManager.System<SharedMapSystem>().CreateMap(mapId, runMapInit: init);
|
||||
|
||||
shell.WriteLine($"Map with ID {mapId} created.");
|
||||
return;
|
||||
@@ -64,11 +63,8 @@ sealed class RemoveMapCommand : LocalizedCommands
|
||||
}
|
||||
}
|
||||
|
||||
sealed class RemoveGridCommand : LocalizedCommands
|
||||
sealed class RemoveGridCommand : LocalizedEntityCommands
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entManager = default!;
|
||||
[Dependency] private readonly IMapManager _map = default!;
|
||||
|
||||
public override string Command => "rmgrid";
|
||||
public override bool RequireServerOrSingleplayer => true;
|
||||
|
||||
@@ -82,20 +78,20 @@ sealed class RemoveGridCommand : LocalizedCommands
|
||||
|
||||
var gridIdNet = NetEntity.Parse(args[0]);
|
||||
|
||||
if (!_entManager.TryGetEntity(gridIdNet, out var gridId) || !_entManager.HasComponent<MapGridComponent>(gridId))
|
||||
if (!EntityManager.TryGetEntity(gridIdNet, out var gridId) || !EntityManager.HasComponent<MapGridComponent>(gridId))
|
||||
{
|
||||
shell.WriteError($"Grid {gridId} does not exist.");
|
||||
return;
|
||||
}
|
||||
|
||||
_map.DeleteGrid(gridId.Value);
|
||||
EntityManager.DeleteEntity(gridId);
|
||||
shell.WriteLine($"Grid {gridId} was removed.");
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class RunMapInitCommand : LocalizedCommands
|
||||
internal sealed class RunMapInitCommand : LocalizedEntityCommands
|
||||
{
|
||||
[Dependency] private readonly IMapManager _map = default!;
|
||||
[Dependency] private readonly SharedMapSystem _mapSystem = default!;
|
||||
|
||||
public override string Command => "mapinit";
|
||||
public override bool RequireServerOrSingleplayer => true;
|
||||
@@ -111,26 +107,27 @@ internal sealed class RunMapInitCommand : LocalizedCommands
|
||||
var arg = args[0];
|
||||
var mapId = new MapId(int.Parse(arg, CultureInfo.InvariantCulture));
|
||||
|
||||
if (!_map.MapExists(mapId))
|
||||
if (!_mapSystem.MapExists(mapId))
|
||||
{
|
||||
shell.WriteError("Map does not exist!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (_map.IsMapInitialized(mapId))
|
||||
if (_mapSystem.IsInitialized(mapId))
|
||||
{
|
||||
shell.WriteError("Map is already initialized!");
|
||||
return;
|
||||
}
|
||||
|
||||
_map.DoMapInitialize(mapId);
|
||||
_mapSystem.InitializeMap(mapId);
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class ListMapsCommand : LocalizedCommands
|
||||
internal sealed class ListMapsCommand : LocalizedEntityCommands
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entManager = default!;
|
||||
[Dependency] private readonly IMapManager _map = default!;
|
||||
[Dependency] private readonly SharedMapSystem _mapSystem = default!;
|
||||
|
||||
public override string Command => "lsmap";
|
||||
|
||||
@@ -143,13 +140,15 @@ internal sealed class ListMapsCommand : LocalizedCommands
|
||||
|
||||
foreach (var mapId in _map.GetAllMapIds().OrderBy(id => id.Value))
|
||||
{
|
||||
var mapUid = _map.GetMapEntityId(mapId);
|
||||
if (!_mapSystem.TryGetMap(mapId, out var mapUid))
|
||||
continue;
|
||||
|
||||
msg.AppendFormat("{0}: {1}, init: {2}, paused: {3}, nent: {4}, grids: {5}\n",
|
||||
mapId, _entManager.GetComponent<MetaDataComponent>(mapUid).EntityName,
|
||||
_map.IsMapInitialized(mapId),
|
||||
_map.IsMapPaused(mapId),
|
||||
_entManager.GetNetEntity(_map.GetMapEntityId(mapId)),
|
||||
mapId,
|
||||
_entManager.GetComponent<MetaDataComponent>(mapUid.Value).EntityName,
|
||||
_mapSystem.IsInitialized(mapUid),
|
||||
_mapSystem.IsPaused(mapId),
|
||||
_entManager.GetNetEntity(mapUid),
|
||||
string.Join(",", _map.GetAllGrids(mapId).Select(grid => grid.Owner)));
|
||||
}
|
||||
|
||||
@@ -157,9 +156,10 @@ internal sealed class ListMapsCommand : LocalizedCommands
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class ListGridsCommand : LocalizedCommands
|
||||
internal sealed class ListGridsCommand : LocalizedEntityCommands
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _ent = default!;
|
||||
[Dependency]
|
||||
private readonly SharedTransformSystem _transformSystem = default!;
|
||||
|
||||
public override string Command => "lsgrid";
|
||||
|
||||
@@ -169,15 +169,14 @@ internal sealed class ListGridsCommand : LocalizedCommands
|
||||
public override void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var msg = new StringBuilder();
|
||||
var xformSystem = _ent.System<SharedTransformSystem>();
|
||||
var xformQuery = _ent.GetEntityQuery<TransformComponent>();
|
||||
var grids = _ent.AllComponentsList<MapGridComponent>();
|
||||
var xformQuery = EntityManager.GetEntityQuery<TransformComponent>();
|
||||
var grids = EntityManager.AllComponentsList<MapGridComponent>();
|
||||
grids.Sort((x, y) => x.Uid.CompareTo(y.Uid));
|
||||
|
||||
foreach (var (uid, grid) in grids)
|
||||
foreach (var (uid, _) in grids)
|
||||
{
|
||||
var xform = xformQuery.GetComponent(uid);
|
||||
var worldPos = xformSystem.GetWorldPosition(xform);
|
||||
var worldPos = _transformSystem.GetWorldPosition(xform);
|
||||
|
||||
msg.AppendFormat("{0}: map: {1}, ent: {2}, pos: {3:0.0},{4:0.0} \n",
|
||||
uid, xform.MapID, uid, worldPos.X, worldPos.Y);
|
||||
|
||||
@@ -61,7 +61,7 @@ internal sealed class TeleportCommand : LocalizedEntityCommands
|
||||
else
|
||||
{
|
||||
var mapEnt = _map.GetMapEntityIdOrThrow(mapId);
|
||||
_transform.SetWorldPosition(transform, position);
|
||||
_transform.SetWorldPosition((entity, transform), position);
|
||||
_transform.SetParent(entity, transform, mapEnt);
|
||||
}
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace Robust.Shared.Console
|
||||
|
||||
void WriteMarkup(string markup)
|
||||
{
|
||||
WriteLine(FormattedMessage.FromMarkup(markup));
|
||||
WriteLine(FormattedMessage.FromMarkupPermissive(markup));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -659,7 +659,9 @@ namespace Robust.Shared.Containers
|
||||
if (!transform.Comp.ParentUid.IsValid()
|
||||
|| !TryGetContainingContainer(transform.Comp.ParentUid, out var container)
|
||||
|| !TryInsertIntoContainer(transform, container))
|
||||
transform.Comp.AttachToGridOrMap();
|
||||
{
|
||||
_transform.AttachToGridOrMap(transform, transform.Comp);
|
||||
}
|
||||
}
|
||||
|
||||
private bool TryInsertIntoContainer(Entity<TransformComponent> transform, BaseContainer container)
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace Robust.Shared.ContentPack
|
||||
String("short").ThenReturn(PrimitiveTypeCode.Int16);
|
||||
|
||||
private static readonly Parser<char, PrimitiveTypeCode> UInt16TypeParser =
|
||||
String("ushort").ThenReturn(PrimitiveTypeCode.UInt32);
|
||||
String("ushort").ThenReturn(PrimitiveTypeCode.UInt16);
|
||||
|
||||
private static readonly Parser<char, PrimitiveTypeCode> Int32TypeParser =
|
||||
String("int").ThenReturn(PrimitiveTypeCode.Int32);
|
||||
|
||||
@@ -84,12 +84,146 @@ Types:
|
||||
- "bool get_HasContents()"
|
||||
Lidgren.Network:
|
||||
NetBuffer:
|
||||
All: True
|
||||
Methods:
|
||||
- "byte[] get_Data()"
|
||||
- "void set_Data(byte[])"
|
||||
- "int get_LengthBytes()"
|
||||
- "void set_LengthBytes(int)"
|
||||
- "int get_LengthBits()"
|
||||
- "void set_LengthBits(int)"
|
||||
- "long get_Position()"
|
||||
- "void set_Position(long)"
|
||||
- "int get_PositionInBytes()"
|
||||
- "byte[] PeekDataBuffer()"
|
||||
- "bool PeekBoolean()"
|
||||
- "byte PeekByte()"
|
||||
- "sbyte PeekSByte()"
|
||||
- "byte PeekByte(int)"
|
||||
- "System.Span`1<byte> PeekBytes(System.Span`1<byte>)"
|
||||
- "byte[] PeekBytes(int)"
|
||||
- "void PeekBytes(byte[], int, int)"
|
||||
- "short PeekInt16()"
|
||||
- "ushort PeekUInt16()"
|
||||
- "int PeekInt32()"
|
||||
- "int PeekInt32(int)"
|
||||
- "uint PeekUInt32()"
|
||||
- "uint PeekUInt32(int)"
|
||||
- "ulong PeekUInt64()"
|
||||
- "long PeekInt64()"
|
||||
- "ulong PeekUInt64(int)"
|
||||
- "long PeekInt64(int)"
|
||||
- "float PeekFloat()"
|
||||
- "System.Half PeekHalf()"
|
||||
- "float PeekSingle()"
|
||||
- "double PeekDouble()"
|
||||
- "string PeekString()"
|
||||
- "int PeekStringSize()"
|
||||
- "bool ReadBoolean()"
|
||||
- "byte ReadByte()"
|
||||
- "bool ReadByte(ref byte)"
|
||||
- "sbyte ReadSByte()"
|
||||
- "byte ReadByte(int)"
|
||||
- "System.Span`1<byte> ReadBytes(System.Span`1<byte>)"
|
||||
- "byte[] ReadBytes(int)"
|
||||
- "bool ReadBytes(int, ref byte[])"
|
||||
- "bool TryReadBytes(System.Span`1<byte>)"
|
||||
- "void ReadBytes(byte[], int, int)"
|
||||
- "void ReadBits(System.Span`1<byte>, int)"
|
||||
- "void ReadBits(byte[], int, int)"
|
||||
- "short ReadInt16()"
|
||||
- "ushort ReadUInt16()"
|
||||
- "int ReadInt32()"
|
||||
- "bool ReadInt32(ref int)"
|
||||
- "int ReadInt32(int)"
|
||||
- "uint ReadUInt32()"
|
||||
- "bool ReadUInt32(ref uint)"
|
||||
- "uint ReadUInt32(int)"
|
||||
- "ulong ReadUInt64()"
|
||||
- "long ReadInt64()"
|
||||
- "ulong ReadUInt64(int)"
|
||||
- "long ReadInt64(int)"
|
||||
- "float ReadFloat()"
|
||||
- "System.Half ReadHalf()"
|
||||
- "float ReadSingle()"
|
||||
- "bool ReadSingle(ref float)"
|
||||
- "double ReadDouble()"
|
||||
- "uint ReadVariableUInt32()"
|
||||
- "bool ReadVariableUInt32(ref uint)"
|
||||
- "int ReadVariableInt32()"
|
||||
- "long ReadVariableInt64()"
|
||||
- "ulong ReadVariableUInt64()"
|
||||
- "float ReadSignedSingle(int)"
|
||||
- "float ReadUnitSingle(int)"
|
||||
- "float ReadRangedSingle(float, float, int)"
|
||||
- "int ReadRangedInteger(int, int)"
|
||||
- "long ReadRangedInteger(long, long)"
|
||||
- "string ReadString()"
|
||||
- "bool ReadString(ref string)"
|
||||
- "double ReadTime(Lidgren.Network.NetConnection, bool)"
|
||||
- "System.Net.IPEndPoint ReadIPEndPoint()"
|
||||
- "void SkipPadBits()"
|
||||
- "void ReadPadBits()"
|
||||
- "void SkipPadBits(int)"
|
||||
- "void EnsureBufferSize(int)"
|
||||
- "void Write(bool)"
|
||||
- "void Write(byte)"
|
||||
- "void WriteAt(int, byte)"
|
||||
- "void Write(sbyte)"
|
||||
- "void Write(byte, int)"
|
||||
- "void Write(byte[])"
|
||||
- "void Write(System.ReadOnlySpan`1<byte>)"
|
||||
- "void Write(byte[], int, int)"
|
||||
- "void Write(ushort)"
|
||||
- "void WriteAt(int, ushort)"
|
||||
- "void Write(ushort, int)"
|
||||
- "void Write(short)"
|
||||
- "void WriteAt(int, short)"
|
||||
- "void Write(int)"
|
||||
- "void WriteAt(int, int)"
|
||||
- "void Write(uint)"
|
||||
- "void WriteAt(int, uint)"
|
||||
- "void Write(uint, int)"
|
||||
- "void Write(int, int)"
|
||||
- "void Write(ulong)"
|
||||
- "void WriteAt(int, ulong)"
|
||||
- "void Write(ulong, int)"
|
||||
- "void Write(long)"
|
||||
- "void Write(long, int)"
|
||||
- "void Write(System.Half)"
|
||||
- "void Write(float)"
|
||||
- "void Write(double)"
|
||||
- "int WriteVariableUInt32(uint)"
|
||||
- "int WriteVariableInt32(int)"
|
||||
- "int WriteVariableInt64(long)"
|
||||
- "int WriteVariableUInt64(ulong)"
|
||||
- "void WriteSignedSingle(float, int)"
|
||||
- "void WriteUnitSingle(float, int)"
|
||||
- "void WriteRangedSingle(float, float, float, int)"
|
||||
- "int WriteRangedInteger(int, int, int)"
|
||||
- "int WriteRangedInteger(long, long, long)"
|
||||
- "void Write(string)"
|
||||
- "void Write(System.Net.IPEndPoint)"
|
||||
- "void WriteTime(bool)"
|
||||
- "void WriteTime(double, bool)"
|
||||
- "void WritePadBits()"
|
||||
- "void WritePadBits(int)"
|
||||
- "void Write(Lidgren.Network.NetBuffer)"
|
||||
- "void Zero(int)"
|
||||
- "void .ctor()"
|
||||
NetDeliveryMethod: { }
|
||||
NetIncomingMessage:
|
||||
All: True
|
||||
Methods:
|
||||
- "Lidgren.Network.NetIncomingMessageType get_MessageType()"
|
||||
- "Lidgren.Network.NetDeliveryMethod get_DeliveryMethod()"
|
||||
- "int get_SequenceChannel()"
|
||||
- "System.Net.IPEndPoint get_SenderEndPoint()"
|
||||
- "Lidgren.Network.NetConnection get_SenderConnection()"
|
||||
- "double get_ReceiveTime()"
|
||||
- "double ReadTime(bool)"
|
||||
- "string ToString()"
|
||||
NetOutgoingMessage:
|
||||
All: True
|
||||
Methods:
|
||||
- "string ToString()"
|
||||
Nett:
|
||||
CommentLocation: { } # Enum
|
||||
Toml:
|
||||
@@ -438,6 +572,7 @@ Types:
|
||||
System.Net:
|
||||
DnsEndPoint: { }
|
||||
IPAddress: { All: True }
|
||||
IPEndPoint: { All: True }
|
||||
HttpStatusCode: { } # Enum
|
||||
System.Net.Sockets:
|
||||
AddressFamily: { }
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Robust.Shared.ContentPack
|
||||
@@ -135,11 +136,37 @@ namespace Robust.Shared.ContentPack
|
||||
path = path.Directory;
|
||||
|
||||
var fullPath = GetFullPath(path);
|
||||
Process.Start(new ProcessStartInfo
|
||||
if (OperatingSystem.IsWindows())
|
||||
{
|
||||
UseShellExecute = true,
|
||||
FileName = fullPath,
|
||||
});
|
||||
Process.Start(new ProcessStartInfo
|
||||
{
|
||||
FileName = $"{Environment.GetEnvironmentVariable("SystemRoot")}\\explorer.exe",
|
||||
Arguments = ".",
|
||||
WorkingDirectory = fullPath,
|
||||
});
|
||||
}
|
||||
else if (OperatingSystem.IsMacOS())
|
||||
{
|
||||
Process.Start(new ProcessStartInfo
|
||||
{
|
||||
FileName = "open",
|
||||
Arguments = ".",
|
||||
WorkingDirectory = fullPath,
|
||||
});
|
||||
}
|
||||
else if (OperatingSystem.IsLinux() || OperatingSystem.IsFreeBSD())
|
||||
{
|
||||
Process.Start(new ProcessStartInfo
|
||||
{
|
||||
FileName = "xdg-open",
|
||||
Arguments = ".",
|
||||
WorkingDirectory = fullPath,
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotSupportedException("Opening OS windows not supported on this OS");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -660,21 +660,25 @@ namespace Robust.Shared.GameObjects
|
||||
/// Raised when the Anchor state of the transform is changed.
|
||||
/// </summary>
|
||||
[ByRefEvent]
|
||||
public readonly struct AnchorStateChangedEvent
|
||||
public readonly struct AnchorStateChangedEvent(
|
||||
EntityUid entity,
|
||||
TransformComponent transform,
|
||||
bool detaching = false)
|
||||
{
|
||||
public readonly TransformComponent Transform;
|
||||
public EntityUid Entity => Transform.Owner;
|
||||
public readonly TransformComponent Transform = transform;
|
||||
public EntityUid Entity { get; } = entity;
|
||||
public bool Anchored => Transform.Anchored;
|
||||
|
||||
/// <summary>
|
||||
/// If true, the entity is being detached to null-space
|
||||
/// </summary>
|
||||
public readonly bool Detaching;
|
||||
public readonly bool Detaching = detaching;
|
||||
|
||||
[Obsolete("Use constructor that takes in EntityUid")]
|
||||
public AnchorStateChangedEvent(TransformComponent transform, bool detaching = false)
|
||||
: this(transform.Owner, transform, detaching)
|
||||
{
|
||||
Detaching = detaching;
|
||||
Transform = transform;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -468,6 +468,21 @@ namespace Robust.Shared.GameObjects
|
||||
ent.Comp4.LastModifiedTick = CurrentTick;
|
||||
}
|
||||
|
||||
public bool TryQueueDeleteEntity(EntityUid? uid)
|
||||
{
|
||||
if (uid == null)
|
||||
return false;
|
||||
|
||||
if (Deleted(uid.Value))
|
||||
return false;
|
||||
|
||||
if (!QueuedDeletionsSet.Add(uid.Value))
|
||||
return false;
|
||||
|
||||
QueueDeleteEntity(uid);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shuts-down and removes given Entity. This is also broadcast to all clients.
|
||||
/// </summary>
|
||||
|
||||
@@ -439,6 +439,7 @@ public partial class EntitySystem
|
||||
|
||||
/// <inheritdoc cref="IEntityManager.TryGetComponent<T>(EntityUid, out T)"/>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
[PreferNonGenericVariantFor(typeof(TransformComponent), typeof(MetaDataComponent))]
|
||||
protected bool TryComp<T>(EntityUid uid, [NotNullWhen(true)] out T? comp) where T : IComponent
|
||||
{
|
||||
return EntityManager.TryGetComponent(uid, out comp);
|
||||
@@ -705,6 +706,13 @@ public partial class EntitySystem
|
||||
EntityManager.QueueDeleteEntity(uid);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IEntityManager.TryQueueDeleteEntity(EntityUid?)" />
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
protected bool TryQueueDel(EntityUid? uid)
|
||||
{
|
||||
return EntityManager.TryQueueDeleteEntity(uid);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Entity Spawning
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace Robust.Shared.GameObjects
|
||||
[Reflect(false), PublicAPI]
|
||||
public abstract partial class EntitySystem : IEntitySystem, IPostInjectInit
|
||||
{
|
||||
[Dependency] protected readonly EntityManager EntityManager;
|
||||
[Dependency] protected readonly EntityManager EntityManager = default!;
|
||||
[Dependency] protected readonly ILogManager LogManager = default!;
|
||||
[Dependency] private readonly ISharedPlayerManager _playerMan = default!;
|
||||
[Dependency] private readonly IReplayRecordingManager _replayMan = default!;
|
||||
@@ -65,11 +65,8 @@ namespace Robust.Shared.GameObjects
|
||||
IEnumerable<Type> IEntitySystem.UpdatesAfter => UpdatesAfter;
|
||||
IEnumerable<Type> IEntitySystem.UpdatesBefore => UpdatesBefore;
|
||||
|
||||
protected EntitySystem() : this(default!) { }
|
||||
|
||||
protected EntitySystem(IEntityManager entityManager)
|
||||
protected EntitySystem()
|
||||
{
|
||||
EntityManager = (EntityManager)entityManager;
|
||||
Subs = new Subscriptions(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -153,6 +153,11 @@ namespace Robust.Shared.GameObjects
|
||||
where T3 : IComponent
|
||||
where T4 : IComponent;
|
||||
|
||||
/// <summary>
|
||||
/// Tries to QueueDeleteEntity if the entity is not already deleted.
|
||||
/// </summary>
|
||||
public bool TryQueueDeleteEntity(EntityUid? uid);
|
||||
|
||||
public void QueueDeleteEntity(EntityUid? uid);
|
||||
|
||||
public bool IsQueuedForDeletion(EntityUid uid);
|
||||
|
||||
@@ -90,7 +90,7 @@ public abstract partial class SharedTransformSystem
|
||||
|
||||
if (!wasAnchored && xform.Running)
|
||||
{
|
||||
var ev = new AnchorStateChangedEvent(xform);
|
||||
var ev = new AnchorStateChangedEvent(uid, xform);
|
||||
RaiseLocalEvent(uid, ref ev, true);
|
||||
}
|
||||
|
||||
@@ -150,7 +150,7 @@ public abstract partial class SharedTransformSystem
|
||||
if (!xform.Running)
|
||||
return;
|
||||
|
||||
var ev = new AnchorStateChangedEvent(xform);
|
||||
var ev = new AnchorStateChangedEvent(uid, xform);
|
||||
RaiseLocalEvent(uid, ref ev, true);
|
||||
}
|
||||
|
||||
@@ -249,19 +249,20 @@ public abstract partial class SharedTransformSystem
|
||||
if (!component._anchored)
|
||||
return;
|
||||
|
||||
MapGridComponent? grid;
|
||||
Entity<MapGridComponent>? grid = null;
|
||||
|
||||
// First try find grid via parent:
|
||||
if (component.GridUid == component.ParentUid && TryComp(component.ParentUid, out MapGridComponent? gridComp))
|
||||
{
|
||||
grid = gridComp;
|
||||
grid = (component.ParentUid, gridComp);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Entity may not be directly parented to the grid (e.g., spawned using some relative entity coordinates)
|
||||
// in that case, we attempt to attach to a grid.
|
||||
var pos = new MapCoordinates(GetWorldPosition(component), component.MapID);
|
||||
_mapManager.TryFindGridAt(pos, out _, out grid);
|
||||
if (_mapManager.TryFindGridAt(pos, out var gridUid, out gridComp))
|
||||
grid = (gridUid, gridComp);
|
||||
}
|
||||
|
||||
if (grid == null)
|
||||
@@ -270,7 +271,7 @@ public abstract partial class SharedTransformSystem
|
||||
return;
|
||||
}
|
||||
|
||||
if (!AnchorEntity(uid, component, grid))
|
||||
if (!AnchorEntity((uid, component), grid))
|
||||
component._anchored = false;
|
||||
}
|
||||
|
||||
@@ -308,7 +309,7 @@ public abstract partial class SharedTransformSystem
|
||||
if (xform.Anchored)
|
||||
{
|
||||
DebugTools.Assert(xform.ParentUid == xform.GridUid && xform.ParentUid.IsValid());
|
||||
var anchorEv = new AnchorStateChangedEvent(xform);
|
||||
var anchorEv = new AnchorStateChangedEvent(uid, xform);
|
||||
RaiseLocalEvent(uid, ref anchorEv, true);
|
||||
}
|
||||
|
||||
@@ -746,7 +747,7 @@ public abstract partial class SharedTransformSystem
|
||||
|
||||
if (oldAnchored != newState.Anchored && xform.Initialized)
|
||||
{
|
||||
var ev = new AnchorStateChangedEvent(xform);
|
||||
var ev = new AnchorStateChangedEvent(uid, xform);
|
||||
RaiseLocalEvent(uid, ref ev, true);
|
||||
}
|
||||
|
||||
@@ -934,7 +935,7 @@ public abstract partial class SharedTransformSystem
|
||||
// Entity was not actually in the transform hierarchy. This is probably a sign that something is wrong, or that the function is being misused.
|
||||
Log.Warning($"Target entity ({ToPrettyString(relative)}) not in transform hierarchy while calling {nameof(GetRelativePositionRotation)}.");
|
||||
var relXform = query.GetComponent(relative);
|
||||
pos = Vector2.Transform(pos, relXform.InvWorldMatrix);
|
||||
pos = Vector2.Transform(pos, GetInvWorldMatrix(relXform));
|
||||
rot = rot - GetWorldRotation(relXform, query);
|
||||
break;
|
||||
}
|
||||
@@ -976,10 +977,11 @@ public abstract partial class SharedTransformSystem
|
||||
public void SetWorldPosition(EntityUid uid, Vector2 worldPos)
|
||||
{
|
||||
var xform = XformQuery.GetComponent(uid);
|
||||
SetWorldPosition(xform, worldPos);
|
||||
SetWorldPosition((uid, xform), worldPos);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
[Obsolete("Use overload that takes Entity<T> instead")]
|
||||
public void SetWorldPosition(TransformComponent component, Vector2 worldPos)
|
||||
{
|
||||
SetWorldPosition((component.Owner, component), worldPos);
|
||||
@@ -1313,10 +1315,9 @@ public abstract partial class SharedTransformSystem
|
||||
{
|
||||
newParent = gridUid;
|
||||
}
|
||||
else if (_mapManager.GetMapEntityId(xform.MapID) is { Valid: true } mapEnt
|
||||
&& !TerminatingOrDeleted(mapEnt))
|
||||
else if (_map.TryGetMap(xform.MapID, out var mapEnt) && !TerminatingOrDeleted(mapEnt))
|
||||
{
|
||||
newParent = mapEnt;
|
||||
newParent = mapEnt.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1446,7 +1447,7 @@ public abstract partial class SharedTransformSystem
|
||||
var tileIndices = _map.TileIndicesFor(xform.GridUid.Value, grid, xform.Coordinates);
|
||||
_map.RemoveFromSnapGridCell(xform.GridUid.Value, grid, tileIndices, uid);
|
||||
xform._anchored = false;
|
||||
var anchorStateChangedEvent = new AnchorStateChangedEvent(xform, true);
|
||||
var anchorStateChangedEvent = new AnchorStateChangedEvent(uid, xform, true);
|
||||
RaiseLocalEvent(uid, ref anchorStateChangedEvent, true);
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,8 @@ namespace Robust.Shared.Map
|
||||
{
|
||||
IoCManager.Resolve(ref entityManager, ref mapManager);
|
||||
|
||||
var gridId = coords.GetGridUid(entityManager);
|
||||
var xform = entityManager.System<SharedTransformSystem>();
|
||||
var gridId = xform.GetGrid(coords);
|
||||
var mapSystem = entityManager.System<SharedMapSystem>();
|
||||
|
||||
if (entityManager.TryGetComponent<MapGridComponent>(gridId, out var mapGrid))
|
||||
@@ -20,8 +21,7 @@ namespace Robust.Shared.Map
|
||||
return mapSystem.GridTileToLocal(gridId.Value, mapGrid, mapSystem.CoordinatesToTile(gridId.Value, mapGrid, coords));
|
||||
}
|
||||
|
||||
var transformSystem = entityManager.System<SharedTransformSystem>();
|
||||
var mapCoords = coords.ToMap(entityManager, transformSystem);
|
||||
var mapCoords = xform.ToMapCoordinates(coords);
|
||||
|
||||
if (mapManager.TryFindGridAt(mapCoords, out var gridUid, out mapGrid))
|
||||
{
|
||||
@@ -49,7 +49,8 @@ namespace Robust.Shared.Map
|
||||
// TODO: Use CollisionManager to get nearest edge.
|
||||
|
||||
// figure out closest intersect
|
||||
var gridIntersect = gridSearchBox.Intersect(gridXform.WorldMatrix.TransformBox(grid.Comp.LocalAABB));
|
||||
var worldMatrix = xform.GetWorldMatrix(gridXform);
|
||||
var gridIntersect = gridSearchBox.Intersect(worldMatrix.TransformBox(grid.Comp.LocalAABB));
|
||||
var gridDist = (gridIntersect.Center - mapCoords.Position).LengthSquared();
|
||||
|
||||
if (gridDist >= distance)
|
||||
|
||||
@@ -143,14 +143,14 @@ namespace Robust.Shared.Map
|
||||
return new Vector2i();
|
||||
|
||||
var mapSystem = entityManager.System<SharedMapSystem>();
|
||||
var gridIdOpt = GetGridUid(entityManager);
|
||||
var gridIdOpt = transformSystem.GetGrid(this);
|
||||
if (gridIdOpt is { } gridId && gridId.IsValid())
|
||||
{
|
||||
var grid = entityManager.GetComponent<MapGridComponent>(gridId);
|
||||
return mapSystem.GetTileRef(gridId, grid, this).GridIndices;
|
||||
}
|
||||
|
||||
var vec = ToMapPos(entityManager, transformSystem);
|
||||
var vec = transformSystem.ToMapCoordinates(this);
|
||||
|
||||
return new Vector2i((int)MathF.Floor(vec.X), (int)MathF.Floor(vec.Y));
|
||||
}
|
||||
@@ -334,8 +334,8 @@ namespace Robust.Shared.Map
|
||||
return true;
|
||||
}
|
||||
|
||||
var mapCoordinates = ToMap(entityManager, transformSystem);
|
||||
var otherMapCoordinates = otherCoordinates.ToMap(entityManager, transformSystem);
|
||||
var mapCoordinates = transformSystem.ToMapCoordinates(this);
|
||||
var otherMapCoordinates = transformSystem.ToMapCoordinates(otherCoordinates);
|
||||
|
||||
if (mapCoordinates.MapId != otherMapCoordinates.MapId)
|
||||
return false;
|
||||
|
||||
@@ -115,7 +115,7 @@ internal static class HappyEyeballsHttp
|
||||
await socket.ConnectAsync(new IPEndPoint(address, port), cancel).ConfigureAwait(false);
|
||||
return socket;
|
||||
}
|
||||
catch (Exception e)
|
||||
catch (Exception)
|
||||
{
|
||||
// Log.Verbose(e, "Happy Eyeballs to {Address} [{Index}] failed", address, index);
|
||||
socket.Dispose();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Buffers.Binary;
|
||||
using System.Threading;
|
||||
using Lidgren.Network;
|
||||
using SpaceWizards.Sodium;
|
||||
@@ -60,11 +60,10 @@ internal sealed class NetEncryption
|
||||
ciphertext = message.Data = new byte[encryptedSize];
|
||||
}
|
||||
|
||||
// TODO: this is probably broken for big-endian machines.
|
||||
Span<byte> nonceData = stackalloc byte[CryptoAeadXChaCha20Poly1305Ietf.NoncePublicBytes];
|
||||
nonceData.Fill(0);
|
||||
MemoryMarshal.Write(nonceData, ref nonce);
|
||||
MemoryMarshal.Write(ciphertext, ref nonce);
|
||||
BinaryPrimitives.WriteUInt64LittleEndian(nonceData, nonce);
|
||||
BinaryPrimitives.WriteUInt64LittleEndian(ciphertext, nonce);
|
||||
|
||||
CryptoAeadXChaCha20Poly1305Ietf.Encrypt(
|
||||
// ciphertext
|
||||
@@ -93,10 +92,9 @@ internal sealed class NetEncryption
|
||||
var buffer = ArrayPool<byte>.Shared.Rent(cipherText.Length);
|
||||
cipherText.CopyTo(buffer);
|
||||
|
||||
// TODO: this is probably broken for big-endian machines.
|
||||
Span<byte> nonceData = stackalloc byte[CryptoAeadXChaCha20Poly1305Ietf.NoncePublicBytes];
|
||||
nonceData.Fill(0);
|
||||
MemoryMarshal.Write(nonceData, ref nonce);
|
||||
BinaryPrimitives.WriteUInt64LittleEndian(nonceData, nonce);
|
||||
|
||||
var result = CryptoAeadXChaCha20Poly1305Ietf.Decrypt(
|
||||
// plaintext
|
||||
|
||||
@@ -17,8 +17,8 @@ namespace Robust.Shared.Physics.Controllers;
|
||||
|
||||
public sealed class Gravity2DController : VirtualController
|
||||
{
|
||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
|
||||
[Dependency] private readonly SharedMapSystem _mapSystem = default!;
|
||||
|
||||
private ISawmill _sawmill = default!;
|
||||
|
||||
@@ -72,7 +72,7 @@ public sealed class Gravity2DController : VirtualController
|
||||
|
||||
public void SetGravity(MapId mapId, Vector2 value)
|
||||
{
|
||||
var mapUid = _mapManager.GetMapEntityId(mapId);
|
||||
var mapUid = _mapSystem.GetMap(mapId);
|
||||
var gravity = EnsureComp<Gravity2DComponent>(mapUid);
|
||||
|
||||
if (gravity.Gravity.Equals(value))
|
||||
|
||||
28
Robust.Shared/Physics/Events/MassChangedEvent.cs
Normal file
28
Robust.Shared/Physics/Events/MassChangedEvent.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Physics.Components;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Robust.Shared.Physics.Events;
|
||||
|
||||
/// <summary>
|
||||
/// By-ref directed event raised when the mass or angular inertia or center of mass of a physics body changes.
|
||||
/// </summary>
|
||||
/// <param name="Entity">The physics body that changed.</param>
|
||||
/// <param name="OldMass">The old mass of the physics body.</param>
|
||||
/// <param name="OldInertia">The old angular inertia of the physics body.</param>
|
||||
/// <param name="OldCenter">The old (local) center of mass of the physics body.</param>
|
||||
[ByRefEvent]
|
||||
public readonly record struct MassDataChangedEvent(
|
||||
Entity<PhysicsComponent, FixturesComponent> Entity,
|
||||
float OldMass,
|
||||
float OldInertia,
|
||||
Vector2 OldCenter
|
||||
)
|
||||
{
|
||||
public float NewMass => Entity.Comp1._mass;
|
||||
public float NewInertia => Entity.Comp1._inertia;
|
||||
public Vector2 NewCenter => Entity.Comp1._localCenter;
|
||||
public bool MassChanged => NewMass != OldMass;
|
||||
public bool InertiaChanged => NewInertia != OldInertia;
|
||||
public bool CenterChanged => NewCenter != OldCenter;
|
||||
}
|
||||
@@ -53,7 +53,7 @@ public partial class SharedPhysicsSystem
|
||||
{
|
||||
if (component.BodyType != BodyType.Static)
|
||||
{
|
||||
SetAwake(uid, component, true);
|
||||
SetAwake((uid, component), true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,6 +256,9 @@ public partial class SharedPhysicsSystem
|
||||
if (!_fixturesQuery.Resolve(uid, ref manager))
|
||||
return;
|
||||
|
||||
var oldMass = body._mass;
|
||||
var oldInertia = body._inertia;
|
||||
|
||||
body._mass = 0.0f;
|
||||
body._invMass = 0.0f;
|
||||
body._inertia = 0.0f;
|
||||
@@ -314,6 +317,12 @@ public partial class SharedPhysicsSystem
|
||||
// Update center of mass velocity.
|
||||
body.LinearVelocity += Vector2Helpers.Cross(body.AngularVelocity, localCenter - oldCenter);
|
||||
Dirty(uid, body);
|
||||
|
||||
if (body._mass == oldMass && body._inertia == oldInertia && oldCenter == localCenter)
|
||||
return;
|
||||
|
||||
var ev = new MassDataChangedEvent((uid, body, manager), oldMass, oldInertia, oldCenter);
|
||||
RaiseLocalEvent(uid, ref ev);
|
||||
}
|
||||
|
||||
public bool SetAngularVelocity(EntityUid uid, float value, bool dirty = true, FixturesComponent? manager = null, PhysicsComponent? body = null)
|
||||
@@ -482,14 +491,14 @@ public partial class SharedPhysicsSystem
|
||||
|
||||
if (body.BodyType == BodyType.Static)
|
||||
{
|
||||
SetAwake(uid, body, false);
|
||||
SetAwake((uid, body), false);
|
||||
body.LinearVelocity = Vector2.Zero;
|
||||
body.AngularVelocity = 0.0f;
|
||||
}
|
||||
// Even if it's dynamic if it can't collide then don't force it awake.
|
||||
else if (body.CanCollide)
|
||||
{
|
||||
SetAwake(uid, body, true);
|
||||
SetAwake((uid, body), true);
|
||||
}
|
||||
|
||||
body.Force = Vector2.Zero;
|
||||
@@ -562,7 +571,7 @@ public partial class SharedPhysicsSystem
|
||||
body.CanCollide = value;
|
||||
|
||||
if (!value)
|
||||
SetAwake(uid, body, false);
|
||||
SetAwake((uid, body), false);
|
||||
|
||||
if (body.Initialized)
|
||||
{
|
||||
@@ -646,7 +655,7 @@ public partial class SharedPhysicsSystem
|
||||
return;
|
||||
|
||||
if (!value)
|
||||
SetAwake(uid, body, true);
|
||||
SetAwake((uid, body), true);
|
||||
|
||||
body.SleepingAllowed = value;
|
||||
|
||||
|
||||
@@ -690,7 +690,7 @@ public abstract partial class SharedPhysicsSystem
|
||||
/// </summary>
|
||||
/// <param name="island"></param>
|
||||
/// <returns></returns>
|
||||
private bool InternalParallel(IslandData island)
|
||||
private static bool InternalParallel(IslandData island)
|
||||
{
|
||||
// Should lone island most times as well.
|
||||
return island.Bodies.Count > 128 || island.Contacts.Count > 128 || island.Joints.Count > 128;
|
||||
|
||||
@@ -45,13 +45,15 @@ namespace Robust.Shared.Player
|
||||
{
|
||||
IoCManager.Resolve(ref entityManager, ref playerMan, ref cfgMan);
|
||||
var transform = entityManager.GetComponent<TransformComponent>(origin);
|
||||
return AddPlayersByPvs(transform.MapPosition, rangeMultiplier, entityManager, playerMan, cfgMan);
|
||||
var transformSystem = entityManager.System<SharedTransformSystem>();
|
||||
return AddPlayersByPvs(transformSystem.GetMapCoordinates(transform), rangeMultiplier, entityManager, playerMan, cfgMan);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds all players inside an entity's PVS.
|
||||
/// The current PVS range will be multiplied by <see cref="rangeMultiplier"/>.
|
||||
/// </summary>
|
||||
[Obsolete("Use overload that takes in managers")]
|
||||
public Filter AddPlayersByPvs(TransformComponent origin, float rangeMultiplier = 2f)
|
||||
{
|
||||
return AddPlayersByPvs(origin.MapPosition, rangeMultiplier);
|
||||
@@ -64,7 +66,8 @@ namespace Robust.Shared.Player
|
||||
public Filter AddPlayersByPvs(EntityCoordinates origin, float rangeMultiplier = 2f, IEntityManager? entityMan = null, ISharedPlayerManager? playerMan = null)
|
||||
{
|
||||
IoCManager.Resolve(ref entityMan, ref playerMan);
|
||||
return AddPlayersByPvs(origin.ToMap(entityMan, entityMan.System<SharedTransformSystem>()), rangeMultiplier, entityMan, playerMan);
|
||||
var system = entityMan.System<SharedTransformSystem>();
|
||||
return AddPlayersByPvs(system.ToMapCoordinates(origin), rangeMultiplier, entityMan, playerMan);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -168,12 +171,13 @@ namespace Robust.Shared.Player
|
||||
{
|
||||
IoCManager.Resolve(ref playerMan, ref entMan);
|
||||
var xformQuery = entMan.GetEntityQuery<TransformComponent>();
|
||||
var xformSystem = entMan.System<SharedTransformSystem>();
|
||||
|
||||
return AddWhere(session =>
|
||||
session.AttachedEntity != null &&
|
||||
xformQuery.TryGetComponent(session.AttachedEntity.Value, out var xform) &&
|
||||
xform.MapID == position.MapId &&
|
||||
(xform.WorldPosition - position.Position).Length() < range, playerMan);
|
||||
(xformSystem.GetWorldPosition(xform) - position.Position).Length() < range, playerMan);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -211,7 +215,7 @@ namespace Robust.Shared.Player
|
||||
/// <summary>
|
||||
/// Removes players from the filter.
|
||||
/// </summary>
|
||||
public Filter RemovePlayers(params ICommonSession[] players) => RemovePlayers(players);
|
||||
public Filter RemovePlayers(params ICommonSession[] players) => RemovePlayers((IEnumerable<ICommonSession>) players);
|
||||
|
||||
/// <summary>
|
||||
/// Removes a single player from the filter, specified by the entity to which they are attached.
|
||||
@@ -232,7 +236,7 @@ namespace Robust.Shared.Player
|
||||
/// <summary>
|
||||
/// Removes players from the filter, specified by the entities to which they are attached.
|
||||
/// </summary>
|
||||
public Filter RemovePlayersByAttachedEntity(params EntityUid[] uids) => RemovePlayersByAttachedEntity(uids);
|
||||
public Filter RemovePlayersByAttachedEntity(params EntityUid[] uids) => RemovePlayersByAttachedEntity((IEnumerable<EntityUid>) uids);
|
||||
|
||||
/// <summary>
|
||||
/// Removes all players from the filter that match a predicate.
|
||||
@@ -260,12 +264,13 @@ namespace Robust.Shared.Player
|
||||
{
|
||||
IoCManager.Resolve(ref entMan);
|
||||
var xformQuery = entMan.GetEntityQuery<TransformComponent>();
|
||||
var xformSystem = entMan.System<SharedTransformSystem>();
|
||||
|
||||
return RemoveWhere(session =>
|
||||
session.AttachedEntity != null &&
|
||||
xformQuery.TryGetComponent(session.AttachedEntity.Value, out var xform) &&
|
||||
xform.MapID == position.MapId &&
|
||||
(xform.WorldPosition - position.Position).Length() < range);
|
||||
(xformSystem.GetWorldPosition(xform) - position.Position).Length() < range);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -370,6 +375,7 @@ namespace Robust.Shared.Player
|
||||
/// <summary>
|
||||
/// A filter with every player whose PVS overlaps this point.
|
||||
/// </summary>
|
||||
[Obsolete("Use overload that takes in managers")]
|
||||
public static Filter Pvs(TransformComponent origin, float rangeMultiplier = 2f)
|
||||
{
|
||||
return Empty().AddPlayersByPvs(origin, rangeMultiplier);
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Robust.Shared.Serialization.TypeSerializers.Implementations
|
||||
ISerializationContext? context = null,
|
||||
ISerializationManager.InstantiationDelegate<FormattedMessage>? instanceProvider = null)
|
||||
{
|
||||
return FormattedMessage.FromMarkup(node.Value);
|
||||
return FormattedMessage.FromMarkupOrThrow(node.Value);
|
||||
}
|
||||
|
||||
public ValidationNode Validate(ISerializationManager serializationManager, ValueDataNode node,
|
||||
|
||||
@@ -1,20 +1,30 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
|
||||
namespace Robust.Shared.Toolshed.Commands.Entities;
|
||||
|
||||
[ToolshedCommand]
|
||||
internal sealed class NearbyCommand : ToolshedCommand
|
||||
{
|
||||
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
||||
|
||||
private EntityLookupSystem? _lookup;
|
||||
|
||||
[CommandImplementation]
|
||||
public IEnumerable<EntityUid> Nearby(
|
||||
[CommandInvocationContext] IInvocationContext ctx,
|
||||
[PipedArgument] IEnumerable<EntityUid> input,
|
||||
[CommandArgument] float range
|
||||
)
|
||||
{
|
||||
var limit = _cfg.GetCVar(CVars.ToolshedNearbyLimit);
|
||||
if (range > limit)
|
||||
throw new ArgumentException($"Tried to query too many entities with nearby ({range})! Limit: {limit}. Change the {CVars.ToolshedNearbyLimit.Name} cvar to increase this at your own risk.");
|
||||
|
||||
_lookup ??= GetSys<EntityLookupSystem>();
|
||||
return input.SelectMany(x => _lookup.GetEntitiesInRange(x, range)).Distinct();
|
||||
}
|
||||
|
||||
@@ -16,12 +16,15 @@ internal sealed class BuildInfoCommand : ToolshedCommand
|
||||
public void BuildInfo([CommandInvocationContext] IInvocationContext ctx)
|
||||
{
|
||||
var game = _cfg.GetCVar(CVars.BuildForkId);
|
||||
ctx.WriteLine(FormattedMessage.FromMarkup($"[color={Gold}]Game:[/color] {game}"));
|
||||
var buildCommit = _cfg.GetCVar(CVars.BuildHash);
|
||||
ctx.WriteLine(FormattedMessage.FromMarkup($"[color={Gold}]Build commit:[/color] {buildCommit}"));
|
||||
var buildManifest = _cfg.GetCVar(CVars.BuildManifestHash);
|
||||
ctx.WriteLine(FormattedMessage.FromMarkup($"[color={Gold}]Manifest hash:[/color] {buildManifest}"));
|
||||
var engine = _cfg.GetCVar(CVars.BuildEngineVersion);
|
||||
ctx.WriteLine(FormattedMessage.FromMarkup($"[color={Gold}]Engine ver:[/color] {engine}"));
|
||||
|
||||
ctx.WriteLine(FormattedMessage.FromMarkupOrThrow($"""
|
||||
[color={Gold}]Game:[/color] {game}
|
||||
[color={Gold}]Build commit:[/color] {buildCommit}
|
||||
[color={Gold}]Manifest hash:[/color] {buildManifest}
|
||||
[color={Gold}]Engine ver:[/color] {engine}
|
||||
"""));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ public sealed class NotForServerConsoleError : IConError
|
||||
{
|
||||
public FormattedMessage DescribeInner()
|
||||
{
|
||||
return FormattedMessage.FromMarkup(
|
||||
return FormattedMessage.FromMarkupOrThrow(
|
||||
"You must be logged in with a client to use this, the server console isn't workable.");
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ public record SessionHasNoEntityError(ICommonSession Session) : IConError
|
||||
{
|
||||
public FormattedMessage DescribeInner()
|
||||
{
|
||||
return FormattedMessage.FromMarkup($"The user {Session.Name} has no attached entity.");
|
||||
return FormattedMessage.FromMarkupOrThrow($"The user {Session.Name} has no attached entity.");
|
||||
}
|
||||
|
||||
public string? Expression { get; set; }
|
||||
|
||||
@@ -82,7 +82,7 @@ public interface IInvocationContext
|
||||
/// </remarks>
|
||||
public void WriteMarkup(string markup)
|
||||
{
|
||||
WriteLine(FormattedMessage.FromMarkup(markup));
|
||||
WriteLine(FormattedMessage.FromMarkupPermissive(markup));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -352,7 +352,7 @@ public record OutOfInputError : IConError
|
||||
{
|
||||
public FormattedMessage DescribeInner()
|
||||
{
|
||||
return FormattedMessage.FromMarkup("Ran out of input data when data was expected.");
|
||||
return FormattedMessage.FromMarkupOrThrow("Ran out of input data when data was expected.");
|
||||
}
|
||||
|
||||
public string? Expression { get; set; }
|
||||
|
||||
@@ -103,7 +103,7 @@ public record BadVarTypeError(Type Got, Type Expected, string VarName) : IConErr
|
||||
{
|
||||
public FormattedMessage DescribeInner()
|
||||
{
|
||||
return FormattedMessage.FromMarkup(
|
||||
return FormattedMessage.FromMarkupOrThrow(
|
||||
$"Got unexpected type {Got.PrettyName()} in {VarName}, expected {Expected.PrettyName()}");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Linq;
|
||||
using Robust.Shared.Localization;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Robust.Shared.Toolshed;
|
||||
|
||||
@@ -31,10 +32,37 @@ public abstract partial class ToolshedCommand
|
||||
/// </summary>
|
||||
public string GetHelp(string? subCommand)
|
||||
{
|
||||
if (subCommand is null)
|
||||
return $"{Name}: {Description(null)}";
|
||||
else
|
||||
return $"{Name}:{subCommand}: {Description(subCommand)}";
|
||||
// Description
|
||||
var description = subCommand is null
|
||||
? $"{Name}: {Description(null)}"
|
||||
: $"{Name}:{subCommand}: {Description(subCommand)}";
|
||||
|
||||
// Usage
|
||||
var usage = new StringBuilder();
|
||||
usage.AppendLine();
|
||||
usage.Append(Loc.GetString("command-description-usage"));
|
||||
foreach (var (pipedType, parameters) in _readonlyParameters[subCommand ?? ""])
|
||||
{
|
||||
usage.Append(Environment.NewLine + " ");
|
||||
|
||||
// Piped type
|
||||
if (pipedType != null)
|
||||
{
|
||||
usage.Append(Loc.GetString("command-description-usage-pipedtype",
|
||||
("typeName", GetFriendlyName(pipedType))));
|
||||
}
|
||||
|
||||
// Name
|
||||
usage.Append(Name);
|
||||
|
||||
// Parameters
|
||||
foreach (var param in parameters)
|
||||
{
|
||||
usage.Append($" <{GetFriendlyName(param)}>");
|
||||
}
|
||||
}
|
||||
|
||||
return description + usage;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -42,4 +70,27 @@ public abstract partial class ToolshedCommand
|
||||
{
|
||||
return GetHelp(null);
|
||||
}
|
||||
|
||||
public static string GetFriendlyName(Type type)
|
||||
{
|
||||
string friendlyName = type.Name;
|
||||
if (type.IsGenericType)
|
||||
{
|
||||
int iBacktick = friendlyName.IndexOf('`');
|
||||
if (iBacktick > 0)
|
||||
{
|
||||
friendlyName = friendlyName.Remove(iBacktick);
|
||||
}
|
||||
friendlyName += "<";
|
||||
Type[] typeParameters = type.GetGenericArguments();
|
||||
for (int i = 0; i < typeParameters.Length; ++i)
|
||||
{
|
||||
string typeParamName = GetFriendlyName(typeParameters[i]);
|
||||
friendlyName += (i == 0 ? typeParamName : "," + typeParamName);
|
||||
}
|
||||
friendlyName += ">";
|
||||
}
|
||||
|
||||
return friendlyName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ using Robust.Shared.Reflection;
|
||||
using Robust.Shared.Toolshed.Errors;
|
||||
using Robust.Shared.Toolshed.Syntax;
|
||||
using Robust.Shared.Toolshed.TypeParsers;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Robust.Shared.Toolshed;
|
||||
|
||||
@@ -74,6 +75,12 @@ public abstract partial class ToolshedCommand
|
||||
/// </summary>
|
||||
public IEnumerable<string> Subcommands => _implementors.Keys.Where(x => x != "");
|
||||
|
||||
/// <summary>
|
||||
/// List of parameters for this command and all sub commands. Used for command help usage.
|
||||
/// Dictionary(subCommand, List(pipedType, List(parameterType)))
|
||||
/// </summary>
|
||||
private readonly Dictionary<string, List<(Type?, List<Type>)>> _readonlyParameters;
|
||||
|
||||
protected ToolshedCommand()
|
||||
{
|
||||
var name = GetType().GetCustomAttribute<ToolshedCommandAttribute>()!.Name;
|
||||
@@ -103,9 +110,12 @@ public abstract partial class ToolshedCommand
|
||||
var impls = GetGenericImplementations();
|
||||
Dictionary<(string, Type?), SortedDictionary<string, Type>> parameters = new();
|
||||
|
||||
_readonlyParameters = new();
|
||||
|
||||
foreach (var impl in impls)
|
||||
{
|
||||
var myParams = new SortedDictionary<string, Type>();
|
||||
var orderedParams = new List<Type>();
|
||||
string? subCmd = null;
|
||||
if (impl.GetCustomAttribute<CommandImplementationAttribute>() is {SubCommand: { } x})
|
||||
{
|
||||
@@ -123,7 +133,10 @@ public abstract partial class ToolshedCommand
|
||||
foreach (var param in impl.GetParameters())
|
||||
{
|
||||
if (param.GetCustomAttribute<CommandArgumentAttribute>() is not null)
|
||||
myParams.TryAdd(param.Name!, param.ParameterType);
|
||||
{
|
||||
if (myParams.TryAdd(param.Name!, param.ParameterType))
|
||||
orderedParams.Add(param.ParameterType);
|
||||
}
|
||||
|
||||
if (param.GetCustomAttribute<PipedArgumentAttribute>() is not null)
|
||||
{
|
||||
@@ -135,7 +148,11 @@ public abstract partial class ToolshedCommand
|
||||
|
||||
var key = (subCmd ?? "", pipedType);
|
||||
if (parameters.TryAdd(key, myParams))
|
||||
{
|
||||
var readParam = _readonlyParameters.GetOrNew(subCmd ?? "");
|
||||
readParam.Add((pipedType, orderedParams));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!parameters[key].SequenceEqual(myParams))
|
||||
throw new NotImplementedException("All command implementations of a given subcommand with the same pipe type must share the same argument types");
|
||||
|
||||
@@ -93,7 +93,7 @@ public record struct StringMustStartWithQuote : IConError
|
||||
{
|
||||
public FormattedMessage DescribeInner()
|
||||
{
|
||||
return FormattedMessage.FromMarkup("A string must start with a quote.");
|
||||
return FormattedMessage.FromMarkupOrThrow("A string must start with a quote.");
|
||||
}
|
||||
|
||||
public string? Expression { get; set; }
|
||||
|
||||
@@ -8,8 +8,7 @@ namespace Robust.Shared.Upload;
|
||||
|
||||
public sealed class NetworkResourceUploadMessage : NetMessage
|
||||
{
|
||||
public override NetDeliveryMethod DeliveryMethod => NetDeliveryMethod.ReliableUnordered;
|
||||
public override MsgGroups MsgGroup => MsgGroups.Command;
|
||||
public override MsgGroups MsgGroup => MsgGroups.String;
|
||||
|
||||
public byte[] Data { get; set; } = Array.Empty<byte>();
|
||||
public ResPath RelativePath { get; set; } = ResPath.Self;
|
||||
|
||||
@@ -271,30 +271,34 @@ public sealed class ZStdDecompressStream : Stream
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* inputPtr = _buffer)
|
||||
fixed (byte* outputPtr = buffer.Span)
|
||||
{
|
||||
ZSTD_outBuffer outputBuf = default;
|
||||
outputBuf.dst = outputPtr;
|
||||
outputBuf.pos = 0;
|
||||
outputBuf.size = (nuint)buffer.Length;
|
||||
ZSTD_inBuffer inputBuf = default;
|
||||
inputBuf.src = inputPtr;
|
||||
inputBuf.pos = (nuint)_bufferPos;
|
||||
inputBuf.size = (nuint)_bufferSize;
|
||||
var ret = DecompressChunk(this, buffer.Span);
|
||||
if (ret > 0)
|
||||
return (int)ret;
|
||||
|
||||
var ret = ZSTD_decompressStream(_ctx, &outputBuf, &inputBuf);
|
||||
|
||||
_bufferPos = (int)inputBuf.pos;
|
||||
ZStdException.ThrowIfError(ret);
|
||||
|
||||
if (outputBuf.pos > 0)
|
||||
return (int)outputBuf.pos;
|
||||
}
|
||||
}
|
||||
} while (true);
|
||||
|
||||
static unsafe nuint DecompressChunk(ZStdDecompressStream stream, Span<byte> buffer)
|
||||
{
|
||||
fixed (byte* inputPtr = stream._buffer)
|
||||
fixed (byte* outputPtr = buffer)
|
||||
{
|
||||
ZSTD_outBuffer outputBuf = default;
|
||||
outputBuf.dst = outputPtr;
|
||||
outputBuf.pos = 0;
|
||||
outputBuf.size = (nuint)buffer.Length;
|
||||
ZSTD_inBuffer inputBuf = default;
|
||||
inputBuf.src = inputPtr;
|
||||
inputBuf.pos = (nuint)stream._bufferPos;
|
||||
inputBuf.size = (nuint)stream._bufferSize;
|
||||
|
||||
var ret = ZSTD_decompressStream(stream._ctx, &outputBuf, &inputBuf);
|
||||
|
||||
stream._bufferPos = (int)inputBuf.pos;
|
||||
ZStdException.ThrowIfError(ret);
|
||||
|
||||
return outputBuf.pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
|
||||
@@ -14,7 +14,7 @@ internal abstract partial class ViewVariablesManager
|
||||
if (_typeHandlers.TryGetValue(typeof(T), out var h))
|
||||
return (ViewVariablesTypeHandler<T>)h;
|
||||
|
||||
var handler = new ViewVariablesTypeHandler<T>();
|
||||
var handler = new ViewVariablesTypeHandler<T>(Sawmill);
|
||||
_typeHandlers.Add(typeof(T), handler);
|
||||
return handler;
|
||||
}
|
||||
|
||||
@@ -31,9 +31,11 @@ public sealed class ViewVariablesTypeHandler<T> : ViewVariablesTypeHandler
|
||||
{
|
||||
private readonly List<TypeHandlerData> _handlers = new();
|
||||
private readonly Dictionary<string, PathHandler> _paths = new();
|
||||
private readonly ISawmill _sawmill;
|
||||
|
||||
internal ViewVariablesTypeHandler()
|
||||
internal ViewVariablesTypeHandler(ISawmill sawmill)
|
||||
{
|
||||
_sawmill = sawmill;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -210,7 +212,9 @@ public sealed class ViewVariablesTypeHandler<T> : ViewVariablesTypeHandler
|
||||
}
|
||||
catch (NullReferenceException e)
|
||||
{
|
||||
Logger.ErrorS(nameof(ViewVariablesManager), e,
|
||||
_sawmill.Log(
|
||||
LogLevel.Error,
|
||||
e,
|
||||
$"NRE caught in setter for path \"{path}\" for type \"{typeof(T).Name}\"...");
|
||||
}
|
||||
});
|
||||
|
||||
@@ -8,6 +8,7 @@ using Robust.Server.Debugging;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Server.GameStates;
|
||||
using Robust.Server.Physics;
|
||||
using Robust.Shared.ComponentTrees;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.ContentPack;
|
||||
@@ -26,6 +27,7 @@ using Robust.Shared.Threading;
|
||||
using Robust.Shared.Utility;
|
||||
using InputSystem = Robust.Server.GameObjects.InputSystem;
|
||||
using MapSystem = Robust.Server.GameObjects.MapSystem;
|
||||
using PointLightComponent = Robust.Client.GameObjects.PointLightComponent;
|
||||
|
||||
namespace Robust.UnitTesting
|
||||
{
|
||||
@@ -126,8 +128,8 @@ namespace Robust.UnitTesting
|
||||
if (Project == UnitTestProject.Client)
|
||||
{
|
||||
systems.LoadExtraSystemType<ClientMetaDataSystem>();
|
||||
systems.LoadExtraSystemType<Robust.Server.Containers.ContainerSystem>();
|
||||
systems.LoadExtraSystemType<Robust.Server.GameObjects.TransformSystem>();
|
||||
systems.LoadExtraSystemType<ContainerSystem>();
|
||||
systems.LoadExtraSystemType<Robust.Client.GameObjects.TransformSystem>();
|
||||
systems.LoadExtraSystemType<Robust.Client.Physics.BroadPhaseSystem>();
|
||||
systems.LoadExtraSystemType<Robust.Client.Physics.JointSystem>();
|
||||
systems.LoadExtraSystemType<Robust.Client.Physics.PhysicsSystem>();
|
||||
@@ -135,6 +137,12 @@ namespace Robust.UnitTesting
|
||||
systems.LoadExtraSystemType<PrototypeReloadSystem>();
|
||||
systems.LoadExtraSystemType<Robust.Client.Debugging.DebugPhysicsSystem>();
|
||||
systems.LoadExtraSystemType<Robust.Client.GameObjects.MapSystem>();
|
||||
systems.LoadExtraSystemType<Robust.Client.GameObjects.PointLightSystem>();
|
||||
systems.LoadExtraSystemType<LightTreeSystem>();
|
||||
systems.LoadExtraSystemType<RecursiveMoveSystem>();
|
||||
systems.LoadExtraSystemType<SpriteSystem>();
|
||||
systems.LoadExtraSystemType<SpriteTreeSystem>();
|
||||
systems.LoadExtraSystemType<GridChunkBoundsDebugSystem>();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -171,6 +179,11 @@ namespace Robust.UnitTesting
|
||||
compFactory.RegisterClass<MapSaveTileMapComponent>();
|
||||
compFactory.RegisterClass<MapSaveIdComponent>();
|
||||
}
|
||||
else
|
||||
{
|
||||
compFactory.RegisterClass<PointLightComponent>();
|
||||
compFactory.RegisterClass<SpriteComponent>();
|
||||
}
|
||||
|
||||
deps.Resolve<IParallelManagerInternal>().Initialize();
|
||||
|
||||
|
||||
@@ -344,7 +344,7 @@ namespace Robust.UnitTesting.Shared.Maths
|
||||
var controlColor = new Color(rf, gf, bf, af);
|
||||
var color = Color.FromSrgb(Color.ToSrgb(controlColor));
|
||||
|
||||
Assert.That(color, Is.EqualTo(controlColor));
|
||||
Assert.That(MathHelper.CloseToPercent(color, controlColor));
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -355,7 +355,7 @@ namespace Robust.UnitTesting.Shared.Maths
|
||||
var controlColor = new Color(rf, gf, bf, af);
|
||||
var color = Color.FromHsl(Color.ToHsl(controlColor));
|
||||
|
||||
Assert.That(color, Is.EqualTo(controlColor));
|
||||
Assert.That(MathHelper.CloseToPercent(color, controlColor));
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -366,7 +366,7 @@ namespace Robust.UnitTesting.Shared.Maths
|
||||
var controlColor = new Color(rf, gf, bf, af);
|
||||
var color = Color.FromHsv(Color.ToHsv(controlColor));
|
||||
|
||||
Assert.That(color, Is.EqualTo(controlColor));
|
||||
Assert.That(MathHelper.CloseToPercent(color, controlColor));
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -393,7 +393,7 @@ namespace Robust.UnitTesting.Shared.Maths
|
||||
var controlColor = new Color(rf, gf, bf, af);
|
||||
var color = Color.FromYcbcr(Color.ToYcbcr(controlColor));
|
||||
|
||||
Assert.That(color, Is.EqualTo(controlColor));
|
||||
Assert.That(MathHelper.CloseToPercent(color, controlColor));
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -404,7 +404,7 @@ namespace Robust.UnitTesting.Shared.Maths
|
||||
var controlColor = new Color(rf, gf, bf, af);
|
||||
var color = Color.FromHcy(Color.ToHcy(controlColor));
|
||||
|
||||
Assert.That(color, Is.EqualTo(controlColor));
|
||||
Assert.That(MathHelper.CloseToPercent(color, controlColor));
|
||||
}
|
||||
|
||||
static IEnumerable<float> InterpolationValues => new float[]
|
||||
@@ -430,7 +430,7 @@ namespace Robust.UnitTesting.Shared.Maths
|
||||
var interColor = Color.InterpolateBetween(color1, color2, interpolation);
|
||||
var inverseInterColor = Color.InterpolateBetween(color2, color1, 1 - interpolation);
|
||||
|
||||
Assert.That(interColor, Is.EqualTo(inverseInterColor));
|
||||
Assert.That(MathHelper.CloseToPercent(interColor, inverseInterColor));
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
Reference in New Issue
Block a user