mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-15 03:30:53 +01:00
Compare commits
1 Commits
master
...
26-01-10-r
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
927f05fd3b |
@@ -59,7 +59,7 @@
|
||||
<PackageVersion Include="SixLabors.ImageSharp" Version="3.1.12" />
|
||||
<PackageVersion Include="SpaceWizards.HttpListener" Version="0.2.0" />
|
||||
<PackageVersion Include="SpaceWizards.NFluidsynth" Version="0.2.2" />
|
||||
<PackageVersion Include="SpaceWizards.Sdl" Version="1.1.1" />
|
||||
<PackageVersion Include="SpaceWizards.Sdl" Version="1.0.0" />
|
||||
<PackageVersion Include="SpaceWizards.SharpFont" Version="1.1.0" />
|
||||
<PackageVersion Include="SpaceWizards.Sodium" Version="0.3.0" />
|
||||
<PackageVersion Include="SpaceWizards.Fontconfig.Interop" Version="1.0.0" />
|
||||
|
||||
@@ -1,4 +1 @@
|
||||
<Project>
|
||||
|
||||
<!-- This file automatically reset by Tools/version.py -->
|
||||
|
||||
<Project>
|
||||
@@ -11,7 +11,7 @@
|
||||
<Target Name="_RTCheckForDirectReferences" BeforeTargets="BeforeResolveReferences"
|
||||
Condition="'$(AllowDirectRobustReferences)' != 'true'">
|
||||
<Error File="%(ProjectReference.DefiningProjectFullPath)"
|
||||
Text="Direct reference to %(Filename) is not allowed. Use RobustToolbox/Imports/*.props instead (e.g., Shared.props, Client.props, Server.props)"
|
||||
Text="Content may not reference %(Filename) directly"
|
||||
Condition="$([System.Text.RegularExpressions.Regex]::IsMatch('%(Identity)', 'RobustToolbox')) and !$([System.Text.RegularExpressions.Regex]::IsMatch('%(DefiningProjectFullPath)', '([Mm]icrosoft|RobustToolbox)'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
|
||||
5739
RELEASE-NOTES.md
5739
RELEASE-NOTES.md
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,8 @@
|
||||
#nullable enable
|
||||
using System.Collections.Immutable;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using Microsoft.CodeAnalysis.Diagnostics;
|
||||
using Microsoft.CodeAnalysis.Operations;
|
||||
using Robust.Roslyn.Shared;
|
||||
@@ -27,15 +29,16 @@ public sealed class ValidateMemberAnalyzer : DiagnosticAnalyzer
|
||||
{
|
||||
context.EnableConcurrentExecution();
|
||||
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics);
|
||||
context.RegisterOperationAction(AnalyzeOperation, OperationKind.Invocation);
|
||||
context.RegisterSyntaxNodeAction(AnalyzeExpression, SyntaxKind.InvocationExpression);
|
||||
}
|
||||
|
||||
private void AnalyzeOperation(OperationAnalysisContext context)
|
||||
private void AnalyzeExpression(SyntaxNodeAnalysisContext context)
|
||||
{
|
||||
if (context.Operation is not IInvocationOperation node)
|
||||
if (context.Node is not InvocationExpressionSyntax node)
|
||||
return;
|
||||
|
||||
var methodSymbol = node.TargetMethod;
|
||||
if (context.SemanticModel.GetSymbolInfo(node.Expression).Symbol is not IMethodSymbol methodSymbol)
|
||||
return;
|
||||
|
||||
// We need at least one type argument for context
|
||||
if (methodSymbol.TypeArguments.Length < 1)
|
||||
@@ -45,12 +48,16 @@ public sealed class ValidateMemberAnalyzer : DiagnosticAnalyzer
|
||||
if (methodSymbol.TypeArguments[0] is not INamedTypeSymbol targetType)
|
||||
return;
|
||||
|
||||
// Check each parameter of the method
|
||||
foreach (var op in node.Arguments)
|
||||
{
|
||||
if (op.Parameter is null)
|
||||
continue;
|
||||
// We defer building this set until we need it later, so we don't have to build it for every single method invocation!
|
||||
ImmutableHashSet<ISymbol>? members = null;
|
||||
|
||||
// Check each parameter of the method
|
||||
foreach (var parameterContext in node.ArgumentList.Arguments)
|
||||
{
|
||||
|
||||
// Get the symbol for this parameter
|
||||
if (context.SemanticModel.GetOperation(parameterContext) is not IArgumentOperation op || op.Parameter is null)
|
||||
continue;
|
||||
var parameterSymbol = op.Parameter.OriginalDefinition;
|
||||
|
||||
// Make sure the parameter has the ValidateMember attribute
|
||||
@@ -59,12 +66,15 @@ public sealed class ValidateMemberAnalyzer : DiagnosticAnalyzer
|
||||
|
||||
// Find the value passed for this parameter.
|
||||
// We use GetConstantValue to resolve compile-time values - i.e. the result of nameof()
|
||||
if (op.Value.ConstantValue is not { HasValue: true, Value: string fieldName})
|
||||
if (context.SemanticModel.GetConstantValue(parameterContext.Expression).Value is not string fieldName)
|
||||
continue;
|
||||
|
||||
// Get a set containing all the members of the target type and its ancestors
|
||||
members ??= targetType.GetBaseTypesAndThis().SelectMany(n => n.GetMembers()).ToImmutableHashSet(SymbolEqualityComparer.Default);
|
||||
|
||||
// Check each member of the target type to see if it matches our passed in value
|
||||
var found = false;
|
||||
foreach (var member in targetType.GetMembers())
|
||||
foreach (var member in members)
|
||||
{
|
||||
if (member.Name == fieldName)
|
||||
{
|
||||
@@ -74,14 +84,12 @@ public sealed class ValidateMemberAnalyzer : DiagnosticAnalyzer
|
||||
}
|
||||
// If we didn't find it, report the violation
|
||||
if (!found)
|
||||
{
|
||||
context.ReportDiagnostic(Diagnostic.Create(
|
||||
ValidateMemberDescriptor,
|
||||
op.Syntax.GetLocation(),
|
||||
parameterContext.GetLocation(),
|
||||
fieldName,
|
||||
targetType.Name
|
||||
));
|
||||
}
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,11 +16,7 @@
|
||||
<ProjectReference Include="..\Robust.UnitTesting\Robust.UnitTesting.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<!-- BenchmarkDotNet autogenerates files that attempt to reference BenchmarkDotNet through Robust.Benchmarks.
|
||||
By default the RT project privates these files, so we have to explicitly state that these files should be made available
|
||||
to the BenchmarkDotNet project so it can build the runner that executes the benchmark. -->
|
||||
<PackageReference Include="BenchmarkDotNet" PrivateAssets="none" />
|
||||
|
||||
<PackageReference Include="BenchmarkDotNet" />
|
||||
<PackageReference Include="JetBrains.Annotations" />
|
||||
<PackageReference Include="YamlDotNet" />
|
||||
<PackageReference Include="prometheus-net" />
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Numerics;
|
||||
using JetBrains.Annotations;
|
||||
using OpenTK.Audio.OpenAL;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Player;
|
||||
@@ -16,6 +17,7 @@ using Robust.Shared.Exceptions;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Map.Components;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Physics.Components;
|
||||
using Robust.Shared.Physics.Systems;
|
||||
@@ -180,16 +182,14 @@ public sealed partial class AudioSystem : SharedAudioSystem
|
||||
}
|
||||
|
||||
// If playback position changed then update it.
|
||||
var totalLen = GetAudioLengthImpl(entity.Comp.FileName).TotalSeconds;
|
||||
var position = CalculateAudioPosition(entity, (float) totalLen);
|
||||
|
||||
var position = (float) ((entity.Comp.PauseTime ?? Timing.CurTime) - entity.Comp.AudioStart).TotalSeconds;
|
||||
var currentPosition = entity.Comp.Source.PlaybackPosition;
|
||||
var diff = Math.Abs(position - currentPosition);
|
||||
|
||||
// Don't try to set the audio too far ahead.
|
||||
if (!string.IsNullOrEmpty(entity.Comp.FileName))
|
||||
{
|
||||
if (position > totalLen - _audioEndBuffer)
|
||||
if (position > GetAudioLengthImpl(entity.Comp.FileName).TotalSeconds - _audioEndBuffer)
|
||||
{
|
||||
entity.Comp.StopPlaying();
|
||||
return;
|
||||
@@ -251,7 +251,7 @@ public sealed partial class AudioSystem : SharedAudioSystem
|
||||
length ??= GetAudioLength(component.FileName);
|
||||
|
||||
// If audio came into range then start playback at the correct position.
|
||||
var offset = CalculateAudioPosition(entity, (float) length.Value.TotalSeconds);
|
||||
var offset = ((entity.Comp.PauseTime ?? Timing.CurTime) - component.AudioStart).TotalSeconds;
|
||||
|
||||
if (TryAudioLimit(component.FileName))
|
||||
{
|
||||
@@ -289,7 +289,7 @@ public sealed partial class AudioSystem : SharedAudioSystem
|
||||
|
||||
if (offset > 0)
|
||||
{
|
||||
component.PlaybackPosition = offset;
|
||||
component.PlaybackPosition = (float) offset;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -755,7 +755,10 @@ public sealed partial class AudioSystem : SharedAudioSystem
|
||||
var comp = entity.Comp;
|
||||
var source = comp.Source;
|
||||
|
||||
var offset = CalculateAudioPosition(entity, (float)stream.Length.TotalSeconds, audioP.PlayOffsetSeconds);
|
||||
// TODO clamp the offset inside of SetPlaybackPosition() itself.
|
||||
var offset = audioP.PlayOffsetSeconds;
|
||||
var maxOffset = Math.Max((float) stream.Length.TotalSeconds - 0.01f, 0f);
|
||||
offset = Math.Clamp(offset, 0f, maxOffset);
|
||||
source.PlaybackPosition = offset;
|
||||
|
||||
source.StartPlaying();
|
||||
|
||||
@@ -13,7 +13,6 @@ using Robust.Client.HWId;
|
||||
using Robust.Client.Input;
|
||||
using Robust.Client.Localization;
|
||||
using Robust.Client.Map;
|
||||
using Robust.Client.Network.Transfer;
|
||||
using Robust.Client.Placement;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Client.Profiling;
|
||||
@@ -42,7 +41,6 @@ using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Network.Transfer;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Prototypes;
|
||||
@@ -176,8 +174,6 @@ namespace Robust.Client
|
||||
deps.Register<IXamlProxyHelper, XamlProxyHelper>();
|
||||
deps.Register<MarkupTagManager>();
|
||||
deps.Register<IHWId, BasicHWId>();
|
||||
deps.Register<ITransferManager, ClientTransferManager>();
|
||||
deps.Register<ClientTransferTestManager>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
#if TOOLS
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Data.Sqlite;
|
||||
using Robust.Client.Utility;
|
||||
using Robust.Shared.Console;
|
||||
@@ -23,7 +20,15 @@ namespace Robust.Client.Console.Commands
|
||||
{
|
||||
var wantName = args.Length > 0 ? args[0] : null;
|
||||
|
||||
using var con = GetDb();
|
||||
var basePath = UserDataDir.GetRootUserDataDir(_gameController);
|
||||
var launcherDirName = Environment.GetEnvironmentVariable("SS14_LAUNCHER_APPDATA_NAME") ?? "launcher";
|
||||
var dbPath = Path.Combine(basePath, launcherDirName, "settings.db");
|
||||
|
||||
#if USE_SYSTEM_SQLITE
|
||||
SQLitePCL.raw.SetProvider(new SQLitePCL.SQLite3Provider_sqlite3());
|
||||
#endif
|
||||
using var con = new SqliteConnection($"Data Source={dbPath};Mode=ReadOnly");
|
||||
con.Open();
|
||||
using var cmd = con.CreateCommand();
|
||||
cmd.CommandText = "SELECT UserId, UserName, Token FROM Login WHERE Expires > datetime('NOW')";
|
||||
|
||||
@@ -52,51 +57,6 @@ namespace Robust.Client.Console.Commands
|
||||
|
||||
shell.WriteLine($"Logged into account {userName}");
|
||||
}
|
||||
|
||||
public override async ValueTask<CompletionResult> GetCompletionAsync(
|
||||
IConsoleShell shell,
|
||||
string[] args,
|
||||
string argStr,
|
||||
CancellationToken cancel)
|
||||
{
|
||||
if (args.Length != 1)
|
||||
return CompletionResult.Empty;
|
||||
|
||||
return await Task.Run(() =>
|
||||
{
|
||||
using var con = GetDb();
|
||||
|
||||
using var cmd = con.CreateCommand();
|
||||
cmd.CommandText = "SELECT UserName FROM Login WHERE Expires > datetime('NOW')";
|
||||
|
||||
var options = new List<CompletionOption>();
|
||||
|
||||
using var reader = cmd.ExecuteReader();
|
||||
while (reader.Read())
|
||||
{
|
||||
var name = reader.GetString(0);
|
||||
options.Add(new CompletionOption(name));
|
||||
}
|
||||
|
||||
return CompletionResult.FromOptions(options);
|
||||
},
|
||||
cancel);
|
||||
}
|
||||
|
||||
private SqliteConnection GetDb()
|
||||
{
|
||||
var basePath = UserDataDir.GetRootUserDataDir(_gameController);
|
||||
var launcherDirName = Environment.GetEnvironmentVariable("SS14_LAUNCHER_APPDATA_NAME") ?? "launcher";
|
||||
var dbPath = Path.Combine(basePath, launcherDirName, "settings.db");
|
||||
|
||||
#if USE_SYSTEM_SQLITE
|
||||
SQLitePCL.raw.SetProvider(new SQLitePCL.SQLite3Provider_sqlite3());
|
||||
#endif
|
||||
var con = new SqliteConnection($"Data Source={dbPath};Mode=ReadOnly");
|
||||
con.Open();
|
||||
|
||||
return con;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ using Robust.Client.GameObjects;
|
||||
using Robust.Client.GameStates;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Input;
|
||||
using Robust.Client.Network.Transfer;
|
||||
using Robust.Client.Placement;
|
||||
using Robust.Client.Replays.Loading;
|
||||
using Robust.Client.Replays.Playback;
|
||||
@@ -36,7 +35,6 @@ using Robust.Shared.Localization;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Network.Transfer;
|
||||
using Robust.Shared.Profiling;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Reflection;
|
||||
@@ -100,8 +98,6 @@ namespace Robust.Client
|
||||
[Dependency] private readonly ILocalizationManager _loc = default!;
|
||||
[Dependency] private readonly ISystemFontManagerInternal _systemFontManager = default!;
|
||||
[Dependency] private readonly LoadingScreenManager _loadscr = default!;
|
||||
[Dependency] private readonly ITransferManager _transfer = default!;
|
||||
[Dependency] private readonly ClientTransferTestManager _transferTest = default!;
|
||||
|
||||
private IWebViewManagerHook? _webViewHook;
|
||||
|
||||
@@ -205,14 +201,7 @@ namespace Robust.Client
|
||||
_logManager.GetSawmill("res"));
|
||||
|
||||
_loadscr.LoadingStep(_resourceCache.PreloadTextures, "Texture preload");
|
||||
_loadscr.LoadingStep(() =>
|
||||
{
|
||||
_networkManager.Initialize(false);
|
||||
_transfer.Initialize();
|
||||
_transferTest.Initialize();
|
||||
},
|
||||
_networkManager);
|
||||
|
||||
_loadscr.LoadingStep(() => { _networkManager.Initialize(false); }, _networkManager);
|
||||
_loadscr.LoadingStep(_configurationManager.SetupNetworking, _configurationManager);
|
||||
_loadscr.LoadingStep(_serializer.Initialize, _serializer);
|
||||
_loadscr.LoadingStep(_inputManager.Initialize, _inputManager);
|
||||
@@ -696,11 +685,6 @@ namespace Robust.Client
|
||||
_modLoader.BroadcastUpdate(ModUpdateLevel.FramePostEngine, frameEventArgs);
|
||||
}
|
||||
|
||||
using (_prof.Group("Transfer"))
|
||||
{
|
||||
_transfer.FrameUpdate();
|
||||
}
|
||||
|
||||
_audio.FlushALDisposeQueues();
|
||||
}
|
||||
|
||||
|
||||
@@ -1336,10 +1336,11 @@ namespace Robust.Client.GameObjects
|
||||
public Layer(Layer toClone, SpriteComponent parent) : this(parent)
|
||||
{
|
||||
if (toClone.Shader != null)
|
||||
{
|
||||
Shader = toClone.Shader.Mutable ? toClone.Shader.Duplicate() : toClone.Shader;
|
||||
|
||||
UnShaded = toClone.UnShaded;
|
||||
ShaderPrototype = toClone.ShaderPrototype;
|
||||
UnShaded = toClone.UnShaded;
|
||||
ShaderPrototype = toClone.ShaderPrototype;
|
||||
}
|
||||
Texture = toClone.Texture;
|
||||
RSI = toClone.RSI;
|
||||
State = toClone.State;
|
||||
|
||||
@@ -14,9 +14,9 @@ namespace Robust.Client.GameObjects
|
||||
private EntityQuery<AnimationPlayerComponent> _playerQuery;
|
||||
private EntityQuery<MetaDataComponent> _metaQuery;
|
||||
|
||||
#if DEBUG
|
||||
#pragma warning disable CS0414
|
||||
[Dependency] private readonly IComponentFactory _compFact = default!;
|
||||
#endif
|
||||
#pragma warning restore CS0414
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -154,9 +154,6 @@ namespace Robust.Client.GameObjects
|
||||
}
|
||||
|
||||
ent.Comp.PlayingAnimations.Add(key, playback);
|
||||
|
||||
var startedEvent = new AnimationStartedEvent(ent.Owner, ent.Comp, key);
|
||||
RaiseLocalEvent(ent.Owner, startedEvent, true);
|
||||
}
|
||||
|
||||
public bool HasRunningAnimation(EntityUid uid, string key)
|
||||
@@ -202,34 +199,6 @@ namespace Robust.Client.GameObjects
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raised whenever an animation started playing.
|
||||
/// </summary>
|
||||
public sealed class AnimationStartedEvent : EntityEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// The entity associated with the event.
|
||||
/// </summary>
|
||||
public EntityUid Uid { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// The animation player component associated with the entity this event was raised on.
|
||||
/// </summary>
|
||||
public AnimationPlayerComponent AnimationPlayer { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// The key associated with the animation that was started.
|
||||
/// </summary>
|
||||
public string Key { get; init; } = string.Empty;
|
||||
|
||||
internal AnimationStartedEvent(EntityUid uid, AnimationPlayerComponent animationPlayer, string key)
|
||||
{
|
||||
Uid = uid;
|
||||
AnimationPlayer = animationPlayer;
|
||||
Key = key;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raised whenever an animation stops, either due to running its course or being stopped manually.
|
||||
/// </summary>
|
||||
|
||||
@@ -493,9 +493,6 @@ namespace Robust.Client.Graphics.Clyde
|
||||
{
|
||||
if (viewport.Eye == null || viewport.Eye.Position.MapId == MapId.Nullspace)
|
||||
{
|
||||
if (viewport.ClearWhenMissingEye)
|
||||
RenderInRenderTarget(viewport.RenderTarget, () => { }, viewport.ClearColor);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -138,7 +138,6 @@ namespace Robust.Client.Graphics.Clyde
|
||||
public Vector2i Size { get; set; }
|
||||
public event Action<ClearCachedViewportResourcesEvent>? ClearCachedResources;
|
||||
public Color? ClearColor { get; set; } = Color.Black;
|
||||
public bool ClearWhenMissingEye { get; set; }
|
||||
public Vector2 RenderScale { get; set; } = Vector2.One;
|
||||
public bool AutomaticRender { get; set; }
|
||||
public long Id { get; }
|
||||
|
||||
@@ -601,11 +601,6 @@ namespace Robust.Client.Graphics.Clyde
|
||||
_clyde._windowing!.TextInputStop(Reg);
|
||||
}
|
||||
|
||||
public void SetWindowProgress(WindowProgressState state, float value)
|
||||
{
|
||||
_clyde._windowing!.WindowSetProgress(Reg, state, value);
|
||||
}
|
||||
|
||||
public nint? WindowsHWnd => _clyde._windowing!.WindowGetWin32Window(Reg);
|
||||
}
|
||||
|
||||
|
||||
@@ -91,8 +91,6 @@ namespace Robust.Client.Graphics.Clyde
|
||||
private bool _earlyGLInit;
|
||||
private bool _threadWindowApi;
|
||||
|
||||
public bool IsInitialized { get; private set; }
|
||||
|
||||
public Clyde()
|
||||
{
|
||||
_currentBoundRenderTarget = default!;
|
||||
@@ -185,8 +183,6 @@ namespace Robust.Client.Graphics.Clyde
|
||||
if (!InitMainWindowAndRenderer())
|
||||
return false;
|
||||
|
||||
IsInitialized = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,6 @@ namespace Robust.Client.Graphics.Clyde
|
||||
internal sealed class ClydeHeadless : IClydeInternal
|
||||
{
|
||||
// Would it make sense to report a fake resolution like 720p here so code doesn't break? idk.
|
||||
public bool IsInitialized { get; private set; }
|
||||
public IClydeWindow MainWindow { get; }
|
||||
public Vector2i ScreenSize => (1280, 720);
|
||||
public IEnumerable<IClydeWindow> AllWindows => _windows;
|
||||
@@ -173,7 +172,6 @@ namespace Robust.Client.Graphics.Clyde
|
||||
|
||||
public bool InitializePostWindowing()
|
||||
{
|
||||
IsInitialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -526,7 +524,6 @@ namespace Robust.Client.Graphics.Clyde
|
||||
public Vector2i Size { get; }
|
||||
public event Action<ClearCachedViewportResourcesEvent>? ClearCachedResources;
|
||||
public Color? ClearColor { get; set; } = Color.Black;
|
||||
public bool ClearWhenMissingEye { get; set; }
|
||||
public Vector2 RenderScale { get; set; }
|
||||
public bool AutomaticRender { get; set; }
|
||||
|
||||
@@ -585,11 +582,6 @@ namespace Robust.Client.Graphics.Clyde
|
||||
public event Action<WindowDestroyedEventArgs>? Destroyed;
|
||||
public event Action<WindowResizedEventArgs>? Resized { add { } remove { } }
|
||||
|
||||
public void SetWindowProgress(WindowProgressState state, float value)
|
||||
{
|
||||
// Nop.
|
||||
}
|
||||
|
||||
public void TextInputSetRect(UIBox2i rect, int cursor)
|
||||
{
|
||||
// Nop.
|
||||
|
||||
@@ -42,7 +42,6 @@ namespace Robust.Client.Graphics.Clyde
|
||||
void WindowSetSize(WindowReg window, Vector2i size);
|
||||
void WindowSetVisible(WindowReg window, bool visible);
|
||||
void WindowRequestAttention(WindowReg window);
|
||||
void WindowSetProgress(WindowReg reg, WindowProgressState state, float value);
|
||||
void WindowSwapBuffers(WindowReg window);
|
||||
uint? WindowGetX11Id(WindowReg window);
|
||||
nint? WindowGetX11Display(WindowReg window);
|
||||
|
||||
@@ -38,7 +38,7 @@ internal partial class Clyde
|
||||
|
||||
fixed (Rgba32* pixPtr = img.GetPixelSpan())
|
||||
{
|
||||
var surface = (nint) SDL.SDL_CreateSurfaceFrom(
|
||||
var surface = SDL.SDL_CreateSurfaceFrom(
|
||||
img.Width,
|
||||
img.Height,
|
||||
SDL.SDL_PixelFormat.SDL_PIXELFORMAT_ABGR8888,
|
||||
|
||||
@@ -21,7 +21,6 @@ internal partial class Clyde
|
||||
private sealed partial class Sdl3WindowingImpl
|
||||
{
|
||||
private int _nextWindowId = 1;
|
||||
private bool _progressUnavailable;
|
||||
|
||||
public (WindowReg?, string? error) WindowCreate(
|
||||
GLContextSpec? spec,
|
||||
@@ -439,8 +438,7 @@ internal partial class Clyde
|
||||
|
||||
private static void WinThreadWinSetSize(CmdWinSetSize cmd)
|
||||
{
|
||||
var density = SDL.SDL_GetWindowPixelDensity(cmd.Window);
|
||||
SDL.SDL_SetWindowSize(cmd.Window, (int)(cmd.W / density), (int)(cmd.H / density));
|
||||
SDL.SDL_SetWindowSize(cmd.Window, cmd.W, cmd.H);
|
||||
}
|
||||
|
||||
private static void WinThreadWinSetVisible(CmdWinSetVisible cmd)
|
||||
@@ -463,42 +461,6 @@ internal partial class Clyde
|
||||
_sawmill.Error("Failed to flash window: {error}", SDL.SDL_GetError());
|
||||
}
|
||||
|
||||
public void WindowSetProgress(WindowReg window, WindowProgressState state, float value)
|
||||
{
|
||||
SendCmd(new CmdWinSetProgress
|
||||
{
|
||||
Window = WinPtr(window),
|
||||
State = (SDL.SDL_ProgressState)state,
|
||||
Value = value
|
||||
});
|
||||
}
|
||||
|
||||
private void WinThreadWinSetProgress(CmdWinSetProgress cmd)
|
||||
{
|
||||
if (_progressUnavailable)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
var res = SDL.SDL_SetWindowProgressState(cmd.Window, cmd.State);
|
||||
if (!res)
|
||||
{
|
||||
_sawmill.Error("Failed to set window progress state: {error}", SDL.SDL_GetError());
|
||||
return;
|
||||
}
|
||||
|
||||
res = SDL.SDL_SetWindowProgressValue(cmd.Window, cmd.Value);
|
||||
if (!res)
|
||||
_sawmill.Error("Failed to set window progress value: {error}", SDL.SDL_GetError());
|
||||
}
|
||||
catch (EntryPointNotFoundException)
|
||||
{
|
||||
// Allowing it to fail means I don't have to update the launcher immediately :)
|
||||
_progressUnavailable = true;
|
||||
_sawmill.Debug("SDL3 progress APIs unavailable");
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe void WindowSwapBuffers(WindowReg window)
|
||||
{
|
||||
var reg = (Sdl3WindowReg)window;
|
||||
|
||||
@@ -75,7 +75,7 @@ internal partial class Clyde
|
||||
IntPtr surface;
|
||||
fixed (byte* ptr = copied)
|
||||
{
|
||||
surface = (nint) SDL.SDL_CreateSurfaceFrom(
|
||||
surface = SDL.SDL_CreateSurfaceFrom(
|
||||
img.Width,
|
||||
img.Height,
|
||||
SDL.SDL_PixelFormat.SDL_PIXELFORMAT_ABGR8888,
|
||||
|
||||
@@ -93,10 +93,6 @@ internal partial class Clyde
|
||||
WinThreadWinRequestAttention(cmd);
|
||||
break;
|
||||
|
||||
case CmdWinSetProgress cmd:
|
||||
WinThreadWinSetProgress(cmd);
|
||||
break;
|
||||
|
||||
case CmdWinSetSize cmd:
|
||||
WinThreadWinSetSize(cmd);
|
||||
break;
|
||||
@@ -265,13 +261,6 @@ internal partial class Clyde
|
||||
public nint Window;
|
||||
}
|
||||
|
||||
private sealed class CmdWinSetProgress : CmdBase
|
||||
{
|
||||
public nint Window;
|
||||
public SDL.SDL_ProgressState State;
|
||||
public float Value;
|
||||
}
|
||||
|
||||
private sealed class CmdWinSetSize : CmdBase
|
||||
{
|
||||
public nint Window;
|
||||
|
||||
@@ -18,8 +18,6 @@ namespace Robust.Client.Graphics
|
||||
[NotContentImplementable]
|
||||
public interface IClyde
|
||||
{
|
||||
internal bool IsInitialized { get; }
|
||||
|
||||
IClydeWindow MainWindow { get; }
|
||||
IRenderTarget MainWindowRenderTarget => MainWindow.RenderTarget;
|
||||
|
||||
|
||||
@@ -43,11 +43,6 @@ namespace Robust.Client.Graphics
|
||||
/// </summary>
|
||||
Color? ClearColor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// On frames where Eye is null or in nullspace, whether the viewport may clear.
|
||||
/// </summary>
|
||||
bool ClearWhenMissingEye { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// This is, effectively, a multiplier to the eye's zoom.
|
||||
/// </summary>
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
using System.Numerics;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
using SDL3;
|
||||
|
||||
namespace Robust.Client.Graphics
|
||||
{
|
||||
@@ -44,8 +43,6 @@ namespace Robust.Client.Graphics
|
||||
/// </summary>
|
||||
event Action<WindowResizedEventArgs> Resized;
|
||||
|
||||
internal void SetWindowProgress(WindowProgressState state, float value);
|
||||
|
||||
/// <summary>
|
||||
/// Set the active text input area in window pixel coordinates.
|
||||
/// </summary>
|
||||
@@ -71,15 +68,6 @@ namespace Robust.Client.Graphics
|
||||
void TextInputStop();
|
||||
}
|
||||
|
||||
internal enum WindowProgressState : byte
|
||||
{
|
||||
None = SDL.SDL_ProgressState.SDL_PROGRESS_STATE_NONE,
|
||||
Indeterminate = SDL.SDL_ProgressState.SDL_PROGRESS_STATE_INDETERMINATE,
|
||||
Normal = SDL.SDL_ProgressState.SDL_PROGRESS_STATE_NORMAL,
|
||||
Paused = SDL.SDL_ProgressState.SDL_PROGRESS_STATE_PAUSED,
|
||||
Error = SDL.SDL_ProgressState.SDL_PROGRESS_STATE_ERROR
|
||||
}
|
||||
|
||||
[NotContentImplementable]
|
||||
internal interface IClydeWindowInternal : IClydeWindow
|
||||
{
|
||||
|
||||
@@ -118,13 +118,6 @@ internal sealed class LoadingScreenManager : ILoadingScreenManager
|
||||
|
||||
_currentSectionName = sectionName;
|
||||
|
||||
if (_clyde.IsInitialized)
|
||||
{
|
||||
_clyde.MainWindow.SetWindowProgress(
|
||||
WindowProgressState.Normal,
|
||||
_currentSection / (float)_numberOfLoadingSections);
|
||||
}
|
||||
|
||||
if (!dontRender)
|
||||
{
|
||||
// This ensures that if the screen was resized or something the new size is properly updated to clyde.
|
||||
@@ -183,8 +176,6 @@ internal sealed class LoadingScreenManager : ILoadingScreenManager
|
||||
if (_currentSection != _numberOfLoadingSections)
|
||||
_sawmill.Error($"The number of seen loading sections isn't equal to the total number of loading sections! Seen: {_currentSection}, Total: {_numberOfLoadingSections}");
|
||||
|
||||
_clyde.MainWindow.SetWindowProgress(WindowProgressState.None, 1);
|
||||
|
||||
_finished = true;
|
||||
}
|
||||
|
||||
|
||||
13
Robust.Client/ModuleInit.cs
Normal file
13
Robust.Client/ModuleInit.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
using Robust.Shared.Interop.RobustNative;
|
||||
|
||||
namespace Robust.Client;
|
||||
|
||||
internal static class ModuleInit
|
||||
{
|
||||
[ModuleInitializer]
|
||||
public static void Initialize()
|
||||
{
|
||||
RobustNativeDll.IsClientProcess = true;
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
using System;
|
||||
using System.Net.WebSockets;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Network.Transfer;
|
||||
|
||||
namespace Robust.Client.Network.Transfer;
|
||||
|
||||
internal sealed class ClientTransferImplWebSocket : TransferImplWebSocket
|
||||
{
|
||||
private readonly (string EndpointUrl, byte[] Key) _info;
|
||||
private readonly bool _slow;
|
||||
|
||||
public ClientTransferImplWebSocket(
|
||||
(string EndpointUrl, byte[] Key) info,
|
||||
ISawmill sawmill,
|
||||
BaseTransferManager parent,
|
||||
INetChannel channel,
|
||||
bool slow)
|
||||
: base(sawmill, parent, channel)
|
||||
{
|
||||
_info = info;
|
||||
_slow = slow;
|
||||
}
|
||||
|
||||
public override async Task ClientInit(CancellationToken cancel)
|
||||
{
|
||||
var clientWs = new ClientWebSocket();
|
||||
clientWs.Options.SetRequestHeader(KeyHeaderName, Convert.ToBase64String(_info.Key));
|
||||
clientWs.Options.SetRequestHeader(UserIdHeaderName, Channel.UserId.ToString());
|
||||
|
||||
if (_slow)
|
||||
await Task.Delay(2000, cancel);
|
||||
|
||||
await clientWs.ConnectAsync(new Uri(_info.EndpointUrl), cancel);
|
||||
|
||||
WebSocket = clientWs;
|
||||
|
||||
ReadThread();
|
||||
}
|
||||
|
||||
public override Task ServerInit()
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Robust.Shared;
|
||||
using Robust.Shared.Asynchronous;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Network.Messages.Transfer;
|
||||
using Robust.Shared.Network.Transfer;
|
||||
|
||||
namespace Robust.Client.Network.Transfer;
|
||||
|
||||
internal sealed class ClientTransferManager : BaseTransferManager, ITransferManager
|
||||
{
|
||||
private readonly IClientNetManager _netManager;
|
||||
private readonly IConfigurationManager _cfg;
|
||||
private BaseTransferImpl? _transferImpl;
|
||||
|
||||
public event Action? ClientHandshakeComplete;
|
||||
|
||||
internal ClientTransferManager(
|
||||
IClientNetManager netManager,
|
||||
ILogManager logManager,
|
||||
ITaskManager taskManager,
|
||||
IConfigurationManager cfg)
|
||||
: base(logManager, NetMessageAccept.Client, taskManager)
|
||||
{
|
||||
_netManager = netManager;
|
||||
_cfg = cfg;
|
||||
}
|
||||
|
||||
public Stream StartTransfer(INetChannel channel, TransferStartInfo startInfo)
|
||||
{
|
||||
if (_transferImpl == null)
|
||||
throw new InvalidOperationException("Not connected yet!");
|
||||
|
||||
if (channel != _netManager.ServerChannel)
|
||||
throw new InvalidOperationException("Invalid channel!");
|
||||
|
||||
return _transferImpl.StartTransfer(startInfo);
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
_netManager.RegisterNetMessage<MsgTransferInit>(RxTransferInit, NetMessageAccept.Client | NetMessageAccept.Handshake);
|
||||
_netManager.RegisterNetMessage<MsgTransferAckInit>();
|
||||
_netManager.RegisterNetMessage<MsgTransferData>(RxTransferData, NetMessageAccept.Client | NetMessageAccept.Handshake);
|
||||
}
|
||||
|
||||
private async void RxTransferInit(MsgTransferInit message)
|
||||
{
|
||||
BaseTransferImpl impl;
|
||||
if (message.HttpInfo is { } httpInfo)
|
||||
{
|
||||
impl = new ClientTransferImplWebSocket(
|
||||
httpInfo,
|
||||
Sawmill,
|
||||
this,
|
||||
message.MsgChannel,
|
||||
_cfg.GetCVar(CVars.TransferArtificialDelay));
|
||||
}
|
||||
else
|
||||
{
|
||||
impl = new TransferImplLidgren(Sawmill, message.MsgChannel, this, _netManager);
|
||||
}
|
||||
|
||||
_transferImpl = impl;
|
||||
await _transferImpl.ClientInit(default);
|
||||
|
||||
ClientHandshakeComplete?.Invoke();
|
||||
}
|
||||
|
||||
private void RxTransferData(MsgTransferData message)
|
||||
{
|
||||
if (_transferImpl is not TransferImplLidgren lidgren)
|
||||
{
|
||||
message.MsgChannel.Disconnect("Not lidgren");
|
||||
return;
|
||||
}
|
||||
|
||||
lidgren.ReceiveData(message);
|
||||
}
|
||||
|
||||
public Task ServerHandshake(INetChannel channel)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Network.Transfer;
|
||||
|
||||
namespace Robust.Client.Network.Transfer;
|
||||
|
||||
internal sealed class ClientTransferTestManager(ITransferManager manager, ILogManager logManager)
|
||||
: TransferTestManager(manager, logManager)
|
||||
{
|
||||
protected override bool PermissionCheck(INetChannel channel)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -13,9 +13,9 @@ namespace Robust.Client.Prototypes
|
||||
public sealed class ClientPrototypeManager : PrototypeManager
|
||||
{
|
||||
[Dependency] private readonly INetManager _netManager = default!;
|
||||
#if TOOLS
|
||||
#pragma warning disable CS0414
|
||||
[Dependency] private readonly IClientGameTiming _timing = default!;
|
||||
#endif
|
||||
#pragma warning restore CS0414
|
||||
[Dependency] private readonly IGameControllerInternal _controller = default!;
|
||||
[Dependency] private readonly IReloadManager _reload = default!;
|
||||
|
||||
|
||||
@@ -279,7 +279,10 @@ public sealed partial class ReplayLoadManager
|
||||
var path = resUpload.RelativePath.Clean().ToRelativePath();
|
||||
if (uploadedFiles.Add(path) && !_netResMan.FileExists(path))
|
||||
{
|
||||
_netResMan.StoreFile(path, resUpload.Data);
|
||||
_netMan.DispatchLocalNetMessage(new NetworkResourceUploadMessage
|
||||
{
|
||||
RelativePath = path, Data = resUpload.Data
|
||||
});
|
||||
message.Messages.RemoveSwap(i);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ public sealed partial class ReplayLoadManager : IReplayLoadManager
|
||||
[Dependency] private readonly IBaseClient _client = default!;
|
||||
[Dependency] private readonly EntityManager _entMan = default!;
|
||||
[Dependency] private readonly IClientGameTiming _timing = default!;
|
||||
[Dependency] private readonly IClientNetManager _netMan = default!;
|
||||
[Dependency] private readonly IComponentFactory _factory = default!;
|
||||
[Dependency] private readonly IPrototypeManager _protoMan = default!;
|
||||
[Dependency] private readonly ILocalizationManager _locMan = default!;
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
<ProjectReference Include="..\Lidgren.Network\Lidgren.Network.csproj" />
|
||||
<ProjectReference Include="..\NetSerializer\NetSerializer\NetSerializer.csproj" />
|
||||
<ProjectReference Include="..\Robust.LoaderApi\Robust.LoaderApi\Robust.LoaderApi.csproj" />
|
||||
<ProjectReference Include="..\Robust.Shared.Interop.RobustNative\Robust.Shared.Interop.RobustNative.csproj" />
|
||||
<ProjectReference Include="..\Robust.Shared.Maths\Robust.Shared.Maths.csproj" />
|
||||
<ProjectReference Include="..\Robust.Shared\Robust.Shared.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -4,6 +4,7 @@ using Robust.Shared;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Upload;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
@@ -13,7 +14,7 @@ public sealed class UploadFileCommand : IConsoleCommand
|
||||
{
|
||||
[Dependency] private readonly IConfigurationManager _cfgManager = default!;
|
||||
[Dependency] private readonly IFileDialogManager _dialog = default!;
|
||||
[Dependency] private readonly NetworkResourceManager _netRes = default!;
|
||||
[Dependency] private readonly INetManager _netManager = default!;
|
||||
|
||||
public string Command => "uploadfile";
|
||||
public string Description => "Uploads a resource to the server.";
|
||||
@@ -54,6 +55,12 @@ public sealed class UploadFileCommand : IConsoleCommand
|
||||
|
||||
var data = file.CopyToArray();
|
||||
|
||||
_netRes.UploadResources([(path, data)]);
|
||||
var msg = new NetworkResourceUploadMessage
|
||||
{
|
||||
RelativePath = path,
|
||||
Data = data
|
||||
};
|
||||
|
||||
_netManager.ClientSendMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.IO;
|
||||
using Robust.Shared;
|
||||
using Robust.Shared.Configuration;
|
||||
@@ -6,6 +6,7 @@ using Robust.Shared.Console;
|
||||
using Robust.Shared.ContentPack;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Upload;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
@@ -13,9 +14,9 @@ namespace Robust.Client.Upload.Commands;
|
||||
|
||||
public sealed class UploadFolderCommand : IConsoleCommand
|
||||
{
|
||||
[Dependency] private readonly IResourceManager _resourceManager = default!;
|
||||
[Dependency] private readonly IConfigurationManager _configManager = default!;
|
||||
[Dependency] private readonly NetworkResourceManager _netRes = default!;
|
||||
[Dependency] private IResourceManager _resourceManager = default!;
|
||||
[Dependency] private IConfigurationManager _configManager = default!;
|
||||
[Dependency] private INetManager _netMan = default!;
|
||||
|
||||
public string Command => "uploadfolder";
|
||||
public string Description => Loc.GetString("uploadfolder-command-description");
|
||||
@@ -49,7 +50,6 @@ public sealed class UploadFolderCommand : IConsoleCommand
|
||||
}
|
||||
|
||||
//Grab all files in specified folder and upload them
|
||||
var files = new List<(ResPath Relative, byte[] Data)>();
|
||||
foreach (var filepath in _resourceManager.UserData.Find($"{folderPath.ToRelativePath()}/").files )
|
||||
{
|
||||
await using var filestream = _resourceManager.UserData.Open(filepath, FileMode.Open);
|
||||
@@ -63,14 +63,17 @@ public sealed class UploadFolderCommand : IConsoleCommand
|
||||
|
||||
var data = filestream.CopyToArray();
|
||||
|
||||
files.Add((filepath.RelativeTo(BaseUploadFolderPath), data));
|
||||
var msg = new NetworkResourceUploadMessage
|
||||
{
|
||||
RelativePath = filepath.RelativeTo(BaseUploadFolderPath),
|
||||
Data = data
|
||||
};
|
||||
|
||||
_netMan.ClientSendMessage(msg);
|
||||
fileCount++;
|
||||
}
|
||||
}
|
||||
|
||||
_netRes.UploadResources(files);
|
||||
|
||||
shell.WriteLine( Loc.GetString("uploadfolder-command-success",("fileCount",fileCount)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
using System;
|
||||
using System.Buffers.Binary;
|
||||
using System.Collections.Generic;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Network.Transfer;
|
||||
using Robust.Shared.Upload;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Robust.Client.Upload;
|
||||
|
||||
@@ -13,44 +7,10 @@ public sealed class NetworkResourceManager : SharedNetworkResourceManager
|
||||
{
|
||||
[Dependency] private readonly IBaseClient _client = default!;
|
||||
|
||||
internal override void Initialize()
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_client.RunLevelChanged += OnLevelChanged;
|
||||
|
||||
TransferManager.RegisterTransferMessage(TransferKeyNetworkUpload);
|
||||
TransferManager.RegisterTransferMessage(TransferKeyNetworkDownload, ReceiveDownload);
|
||||
|
||||
NetManager.RegisterNetMessage<NetworkResourceAckMessage>();
|
||||
}
|
||||
|
||||
private async void ReceiveDownload(TransferReceivedEvent transfer)
|
||||
{
|
||||
Sawmill.Debug("Receiving file download transfer!");
|
||||
|
||||
await using var stream = transfer.DataStream;
|
||||
|
||||
try
|
||||
{
|
||||
var ackKeyBytes = new byte[4];
|
||||
await stream.ReadExactlyAsync(ackKeyBytes);
|
||||
var ackKey = BinaryPrimitives.ReadInt32LittleEndian(ackKeyBytes);
|
||||
|
||||
await IngestFileStream(stream);
|
||||
|
||||
if (ackKey != 0)
|
||||
{
|
||||
NetManager.ClientSendMessage(new NetworkResourceAckMessage
|
||||
{
|
||||
Key = ackKey
|
||||
});
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Sawmill.Error($"Error while downloading transfer resources: {e}");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnLevelChanged(object? sender, RunLevelChangedEventArgs e)
|
||||
@@ -67,20 +27,4 @@ public sealed class NetworkResourceManager : SharedNetworkResourceManager
|
||||
{
|
||||
ContentRoot.Clear();
|
||||
}
|
||||
|
||||
internal async void UploadResources(List<(ResPath Relative, byte[] Data)> files)
|
||||
{
|
||||
var clientNet = (IClientNetManager)NetManager;
|
||||
if (clientNet.ServerChannel is not { } channel)
|
||||
throw new InvalidOperationException("Not connected to server!");
|
||||
|
||||
await using var transfer = TransferManager.StartTransfer(
|
||||
channel,
|
||||
new TransferStartInfo
|
||||
{
|
||||
MessageKey = TransferKeyNetworkUpload,
|
||||
});
|
||||
|
||||
await WriteFileStream(transfer, files);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ namespace Robust.Client.UserInterface
|
||||
{
|
||||
private Dictionary<string, AnimationPlayback>? _playingAnimations;
|
||||
|
||||
public Action<string>? AnimationStarted;
|
||||
public Action<string>? AnimationCompleted;
|
||||
|
||||
/// <summary>
|
||||
@@ -28,7 +27,6 @@ namespace Robust.Client.UserInterface
|
||||
|
||||
_playingAnimations ??= new Dictionary<string, AnimationPlayback>();
|
||||
_playingAnimations.Add(key, playback);
|
||||
AnimationStarted?.Invoke(key);
|
||||
}
|
||||
|
||||
public bool HasRunningAnimation(string key)
|
||||
|
||||
@@ -2,7 +2,6 @@ using System;
|
||||
using System.Numerics;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Shared.Animations;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.ViewVariables;
|
||||
@@ -356,7 +355,6 @@ namespace Robust.Client.UserInterface
|
||||
/// </remarks>
|
||||
/// <seealso cref="MinWidth"/>
|
||||
/// <seealso cref="MinHeight"/>
|
||||
[Animatable]
|
||||
public Vector2 MinSize
|
||||
{
|
||||
get => new(_minWidth, _minHeight);
|
||||
@@ -380,7 +378,6 @@ namespace Robust.Client.UserInterface
|
||||
/// </remarks>
|
||||
/// <seealso cref="SetWidth"/>
|
||||
/// <seealso cref="SetHeight"/>
|
||||
[Animatable]
|
||||
public Vector2 SetSize
|
||||
{
|
||||
get => new(_setWidth, _setHeight);
|
||||
@@ -437,7 +434,6 @@ namespace Robust.Client.UserInterface
|
||||
/// Width component of <see cref="SetSize"/>.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[Animatable]
|
||||
public float SetWidth
|
||||
{
|
||||
get => _setWidth;
|
||||
@@ -453,7 +449,6 @@ namespace Robust.Client.UserInterface
|
||||
/// Height component of <see cref="SetSize"/>.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[Animatable]
|
||||
public float SetHeight
|
||||
{
|
||||
get => _setHeight;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
@@ -44,7 +44,6 @@ namespace Robust.Client.UserInterface.Controls
|
||||
/// Thrown if <see cref="TextMemory"/> was set directly and there is no backing string instance to fetch.
|
||||
/// </exception>
|
||||
[ViewVariables]
|
||||
[Animatable]
|
||||
public string? Text
|
||||
{
|
||||
get => _text ?? (_textMemory.Length > 0 ? throw new InvalidOperationException("Label uses TextMemory, cannot fetch string text.") : null);
|
||||
|
||||
@@ -144,7 +144,7 @@ namespace Robust.Client.UserInterface.Controls
|
||||
SetPositionFirst();
|
||||
|
||||
// Resize the window by our UIScale
|
||||
ClydeWindow.Size = new((int)(parameters.Width * UIScale), (int)(parameters.Height * UIScale));
|
||||
ClydeWindow.Size = new((int)(ClydeWindow.Size.X * UIScale), (int)(ClydeWindow.Size.Y * UIScale));
|
||||
return ClydeWindow;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,10 +22,8 @@ namespace Robust.Client.UserInterface.Controls
|
||||
|
||||
private int _currentTab;
|
||||
private bool _tabsVisible = true;
|
||||
|
||||
// the laid out tabs
|
||||
private List<TabBox> _tabBoxes = new();
|
||||
private float _enclosingTabHeight;
|
||||
// The right-most coordinate of each tab header
|
||||
private List<float> _tabRight = new();
|
||||
|
||||
public int CurrentTab
|
||||
{
|
||||
@@ -148,66 +146,41 @@ namespace Robust.Client.UserInterface.Controls
|
||||
base.Draw(handle);
|
||||
|
||||
// First, draw panel.
|
||||
var headerSize = _enclosingTabHeight;
|
||||
var headerSize = _getHeaderSize();
|
||||
var panel = _getPanel();
|
||||
var panelBox = new UIBox2(0, headerSize, PixelWidth, PixelHeight);
|
||||
|
||||
panel?.Draw(handle, panelBox, UIScale);
|
||||
|
||||
var font = _getFont();
|
||||
var boxActive = _getTabBoxActive();
|
||||
var boxInactive = _getTabBoxInactive();
|
||||
var fontColorActive = _getTabFontColorActive();
|
||||
var fontColorInactive = _getTabFontColorInactive();
|
||||
|
||||
// Then draw the tabs
|
||||
foreach (var tabBox in _tabBoxes)
|
||||
{
|
||||
if (tabBox.Box is { } styleBox)
|
||||
{
|
||||
styleBox.Draw(handle, tabBox.Bounding, UIScale);
|
||||
}
|
||||
var headerOffset = 0f;
|
||||
|
||||
var baseLine = new Vector2(0, font.GetAscent(UIScale)) + tabBox.Content.TopLeft;
|
||||
foreach (var rune in tabBox.Title.EnumerateRunes())
|
||||
{
|
||||
if (!font.TryGetCharMetrics(rune, UIScale, out var metrics))
|
||||
continue;
|
||||
|
||||
font.DrawChar(handle, rune, baseLine, UIScale, tabBox.Index == _currentTab ? fontColorActive : fontColorInactive);
|
||||
baseLine += new Vector2(metrics.Advance, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private readonly record struct TabBox(UIBox2 Bounding, UIBox2 Content, StyleBox? Box, string Title, int Index);
|
||||
|
||||
private void CalculateTabBoxes(Vector2 availableSize)
|
||||
{
|
||||
availableSize *= UIScale;
|
||||
var tabLeft = 0f;
|
||||
var tabTop = 0f;
|
||||
var tabHeight = 0f;
|
||||
|
||||
var font = _getFont();
|
||||
var boxActive = _getTabBoxActive();
|
||||
var boxInactive = _getTabBoxInactive();
|
||||
|
||||
_tabBoxes.Clear();
|
||||
|
||||
if (!_tabsVisible)
|
||||
return;
|
||||
_tabRight.Clear();
|
||||
|
||||
// Then, draw the tabs.
|
||||
for (var i = 0; i < ChildCount; i++)
|
||||
{
|
||||
if (!GetTabVisible(i))
|
||||
{
|
||||
_tabRight.Add(headerOffset);
|
||||
continue;
|
||||
}
|
||||
|
||||
var title = GetActualTabTitle(i);
|
||||
|
||||
var titleLength = 0;
|
||||
// Get string length.
|
||||
foreach (var rune in title.EnumerateRunes())
|
||||
{
|
||||
if (!font.TryGetCharMetrics(rune, UIScale, out var metrics))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
titleLength += metrics.Advance;
|
||||
}
|
||||
@@ -215,57 +188,50 @@ namespace Robust.Client.UserInterface.Controls
|
||||
var active = _currentTab == i;
|
||||
var box = active ? boxActive : boxInactive;
|
||||
|
||||
var topLeft = new Vector2(tabLeft, tabTop);
|
||||
var size = new Vector2(titleLength, font.GetHeight(UIScale));
|
||||
|
||||
if (box != null)
|
||||
{
|
||||
size = box.GetEnvelopBox(topLeft, size, UIScale).Size;
|
||||
}
|
||||
|
||||
if (tabLeft + size.X > availableSize.X)
|
||||
{
|
||||
tabLeft = 0;
|
||||
tabTop += tabHeight;
|
||||
tabHeight = 0;
|
||||
}
|
||||
|
||||
topLeft = new(tabLeft, tabTop);
|
||||
size = new(titleLength, font.GetHeight(UIScale));
|
||||
|
||||
UIBox2 boundingBox;
|
||||
UIBox2 contentBox;
|
||||
var topLeft = new Vector2(headerOffset, 0);
|
||||
var size = new Vector2(titleLength, font.GetHeight(UIScale));
|
||||
float boxAdvance;
|
||||
|
||||
if (box != null)
|
||||
{
|
||||
boundingBox = box.GetEnvelopBox(topLeft, size, UIScale);
|
||||
contentBox = box.GetContentBox(boundingBox, UIScale);
|
||||
var drawBox = box.GetEnvelopBox(topLeft, size, UIScale);
|
||||
boxAdvance = drawBox.Width;
|
||||
box.Draw(handle, drawBox, UIScale);
|
||||
contentBox = box.GetContentBox(drawBox, UIScale);
|
||||
}
|
||||
else
|
||||
{
|
||||
boxAdvance = size.X;
|
||||
contentBox = UIBox2.FromDimensions(topLeft, size);
|
||||
boundingBox = contentBox;
|
||||
}
|
||||
|
||||
tabLeft += boundingBox.Size.X;
|
||||
tabHeight = Math.Max(tabHeight, boundingBox.Size.Y);
|
||||
_tabBoxes.Add(new(boundingBox, contentBox, box, title, i));
|
||||
}
|
||||
var baseLine = new Vector2(0, font.GetAscent(UIScale)) + contentBox.TopLeft;
|
||||
|
||||
if (Math.Abs(_enclosingTabHeight - (tabTop + tabHeight)) >= 0.1)
|
||||
{
|
||||
InvalidateArrange();
|
||||
foreach (var rune in title.EnumerateRunes())
|
||||
{
|
||||
if (!font.TryGetCharMetrics(rune, UIScale, out var metrics))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
font.DrawChar(handle, rune, baseLine, UIScale, active ? fontColorActive : fontColorInactive);
|
||||
baseLine += new Vector2(metrics.Advance, 0);
|
||||
}
|
||||
|
||||
headerOffset += boxAdvance;
|
||||
// Remember the right-most point of this tab, for testing clicked areas
|
||||
_tabRight.Add(headerOffset);
|
||||
}
|
||||
_enclosingTabHeight = tabTop + tabHeight;
|
||||
}
|
||||
|
||||
protected override Vector2 MeasureOverride(Vector2 availableSize)
|
||||
{
|
||||
CalculateTabBoxes(availableSize);
|
||||
var headerSize = Vector2.Zero;
|
||||
|
||||
if (TabsVisible)
|
||||
{
|
||||
headerSize = new Vector2(0, _enclosingTabHeight / UIScale);
|
||||
headerSize = new Vector2(0, _getHeaderSize() / UIScale);
|
||||
}
|
||||
|
||||
var panel = _getPanel();
|
||||
@@ -288,13 +254,12 @@ namespace Robust.Client.UserInterface.Controls
|
||||
|
||||
protected override Vector2 ArrangeOverride(Vector2 finalSize)
|
||||
{
|
||||
CalculateTabBoxes(finalSize);
|
||||
if (ChildCount == 0 || _currentTab >= ChildCount)
|
||||
{
|
||||
return finalSize;
|
||||
}
|
||||
|
||||
var headerSize = (int)_enclosingTabHeight;
|
||||
var headerSize = _getHeaderSize();
|
||||
var panel = _getPanel();
|
||||
var contentBox = new UIBox2i(0, headerSize, (int) (finalSize.X * UIScale), (int) (finalSize.Y * UIScale));
|
||||
if (panel != null)
|
||||
@@ -318,23 +283,50 @@ namespace Robust.Client.UserInterface.Controls
|
||||
}
|
||||
|
||||
// Outside of header size, ignore.
|
||||
if (args.RelativePixelPosition.Y < 0 || args.RelativePixelPosition.Y > _enclosingTabHeight)
|
||||
if (args.RelativePixelPosition.Y < 0 || args.RelativePixelPosition.Y > _getHeaderSize())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
args.Handle();
|
||||
|
||||
foreach (var box in _tabBoxes)
|
||||
var relX = args.RelativePixelPosition.X;
|
||||
float tabLeft = 0;
|
||||
for (var i = 0; i < ChildCount; i++)
|
||||
{
|
||||
if (box.Bounding.Contains(args.RelativePixelPosition))
|
||||
if (relX > tabLeft && relX <= _tabRight[i])
|
||||
{
|
||||
CurrentTab = box.Index;
|
||||
CurrentTab = i;
|
||||
return;
|
||||
}
|
||||
|
||||
// Next tab starts here
|
||||
tabLeft = _tabRight[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the size of the header, in real pixels
|
||||
[System.Diagnostics.Contracts.Pure]
|
||||
private int _getHeaderSize()
|
||||
{
|
||||
var headerSize = 0;
|
||||
|
||||
if (TabsVisible)
|
||||
{
|
||||
var active = _getTabBoxActive();
|
||||
var inactive = _getTabBoxInactive();
|
||||
var font = _getFont();
|
||||
|
||||
var activeSize = (active?.MinimumSize ?? Vector2.Zero) * UIScale;
|
||||
var inactiveSize = (inactive?.MinimumSize ?? Vector2.Zero) * UIScale;
|
||||
|
||||
headerSize = (int) MathF.Max(activeSize.Y, inactiveSize.Y);
|
||||
headerSize += font.GetHeight(UIScale);
|
||||
}
|
||||
|
||||
return headerSize;
|
||||
}
|
||||
|
||||
[System.Diagnostics.Contracts.Pure]
|
||||
private StyleBox? _getTabBoxActive()
|
||||
{
|
||||
|
||||
@@ -14,6 +14,15 @@ namespace Robust.Client.Utility
|
||||
{
|
||||
NativeLibrary.SetDllImportResolver(typeof(ClientDllMap).Assembly, (name, assembly, path) =>
|
||||
{
|
||||
if (name == "swnfd.dll")
|
||||
{
|
||||
#if LINUX || FREEBSD
|
||||
return NativeLibrary.Load("libswnfd.so", assembly, path);
|
||||
#elif MACOS
|
||||
return NativeLibrary.Load("libswnfd.dylib", assembly, path);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (name == "libEGL.dll")
|
||||
{
|
||||
#if LINUX || FREEBSD
|
||||
|
||||
@@ -20,9 +20,9 @@ internal sealed class ReloadManager : IReloadManager
|
||||
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
||||
[Dependency] private readonly ILogManager _logMan = default!;
|
||||
[Dependency] private readonly IResourceManagerInternal _res = default!;
|
||||
#if TOOLS
|
||||
#pragma warning disable CS0414
|
||||
[Dependency] private readonly ITaskManager _tasks = default!;
|
||||
#endif
|
||||
#pragma warning restore CS0414
|
||||
|
||||
private readonly TimeSpan _reloadDelay = TimeSpan.FromMilliseconds(10);
|
||||
private CancellationTokenSource _reloadToken = new();
|
||||
|
||||
@@ -56,7 +56,7 @@ internal sealed class ViewVariableControlFactory : IViewVariableControlFactory
|
||||
RegisterForType<TimeSpan>(_ => new VVPropEditorTimeSpan());
|
||||
|
||||
RegisterWithCondition(
|
||||
type => type != typeof(ViewVariablesBlobMembers.ServerValueTypeToken),
|
||||
type => type != typeof(ViewVariablesBlobMembers.ServerValueTypeToken) && !type.IsValueType,
|
||||
_ => new VVPropEditorReference()
|
||||
);
|
||||
RegisterWithCondition(
|
||||
|
||||
@@ -9,13 +9,11 @@ using Robust.Server.Debugging;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Server.GameStates;
|
||||
using Robust.Server.Localization;
|
||||
using Robust.Server.Network.Transfer;
|
||||
using Robust.Server.Physics;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Server.Prototypes;
|
||||
using Robust.Server.Reflection;
|
||||
using Robust.Server.Replays;
|
||||
using Robust.Server.ServerStatus;
|
||||
using Robust.Shared;
|
||||
using Robust.Shared.Asynchronous;
|
||||
using Robust.Shared.Configuration;
|
||||
@@ -30,7 +28,6 @@ using Robust.Shared.Log;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Map.Components;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Network.Transfer;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Physics.Collision;
|
||||
using Robust.Shared.Physics.Components;
|
||||
@@ -201,9 +198,6 @@ namespace Robust.UnitTesting.Server
|
||||
container.Register<HttpClientHolder>();
|
||||
container.Register<IHttpClientHolder, HttpClientHolder>();
|
||||
container.Register<IHWId, DummyHWId>();
|
||||
container.Register<IServerNetManager, NetManager>();
|
||||
container.Register<IStatusHost, StatusHost>();
|
||||
container.Register<ITransferManager, ServerTransferManager>();
|
||||
|
||||
var realReflection = new ServerReflectionManager();
|
||||
realReflection.LoadAssemblies(new List<Assembly>(2)
|
||||
@@ -268,6 +262,7 @@ namespace Robust.UnitTesting.Server
|
||||
|
||||
// I just wanted to load pvs system
|
||||
container.Register<IServerEntityManager, ServerEntityManager>();
|
||||
container.Register<IServerNetManager, NetManager>();
|
||||
// god help you if you actually need to test pvs functions
|
||||
container.RegisterInstance<IPlayerManager>(new Mock<IPlayerManager>().Object);
|
||||
container.RegisterInstance<ISharedPlayerManager>(new Mock<ISharedPlayerManager>().Object);
|
||||
|
||||
@@ -9,7 +9,6 @@ using Robust.Server.DataMetrics;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Server.GameStates;
|
||||
using Robust.Server.Log;
|
||||
using Robust.Server.Network.Transfer;
|
||||
using Robust.Server.Placement;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Server.Scripting;
|
||||
@@ -30,7 +29,6 @@ using Robust.Shared.Localization;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Network.Transfer;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Profiling;
|
||||
using Robust.Shared.Prototypes;
|
||||
@@ -109,8 +107,6 @@ namespace Robust.Server
|
||||
[Dependency] private readonly UploadedContentManager _uploadedContMan = default!;
|
||||
[Dependency] private readonly NetworkResourceManager _netResMan = default!;
|
||||
[Dependency] private readonly IReflectionManager _refMan = default!;
|
||||
[Dependency] private readonly ITransferManager _transfer = default!;
|
||||
[Dependency] private readonly ServerTransferTestManager _transferTest = default!;
|
||||
|
||||
private readonly Stopwatch _uptimeStopwatch = new();
|
||||
|
||||
@@ -279,7 +275,6 @@ namespace Robust.Server
|
||||
|
||||
// Load metrics really early so that we can profile startup times in the future maybe.
|
||||
_metricsManager.Initialize();
|
||||
_prof.Initialize();
|
||||
|
||||
try
|
||||
{
|
||||
@@ -298,9 +293,6 @@ namespace Robust.Server
|
||||
return true;
|
||||
}
|
||||
|
||||
_transfer.Initialize();
|
||||
_transferTest.Initialize();
|
||||
|
||||
var dataDir = Options.LoadConfigAndUserData
|
||||
? _commandLineArgs?.DataDir ?? PathHelpers.ExecutableRelativeFile("data")
|
||||
: null;
|
||||
@@ -781,8 +773,6 @@ namespace Robust.Server
|
||||
|
||||
_modLoader.BroadcastUpdate(ModUpdateLevel.FramePostEngine, frameEventArgs);
|
||||
|
||||
_transfer.FrameUpdate();
|
||||
|
||||
_metricsManager.FrameUpdate();
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ using Robust.Shared.IoC;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Network.Messages;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Profiling;
|
||||
using Robust.Shared.Toolshed;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
@@ -23,7 +22,6 @@ namespace Robust.Server.Console
|
||||
[Dependency] private readonly IPlayerManager _players = default!;
|
||||
[Dependency] private readonly ISystemConsoleManager _systemConsole = default!;
|
||||
[Dependency] private readonly ToolshedManager _toolshed = default!;
|
||||
[Dependency] private readonly ProfManager _prof = default!;
|
||||
|
||||
public ServerConsoleHost() : base(isServer: true) {}
|
||||
|
||||
@@ -110,8 +108,7 @@ namespace Robust.Server.Console
|
||||
if (args.Count == 0)
|
||||
return;
|
||||
|
||||
var cmdName = args[0];
|
||||
using var _ = _prof.Group(cmdName);
|
||||
string? cmdName = args[0];
|
||||
|
||||
if (RegisteredCommands.TryGetValue(cmdName, out var conCmd)) // command registered
|
||||
{
|
||||
|
||||
13
Robust.Server/ModuleInit.cs
Normal file
13
Robust.Server/ModuleInit.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
using Robust.Shared.Interop.RobustNative;
|
||||
|
||||
namespace Robust.Server;
|
||||
|
||||
internal static class ModuleInit
|
||||
{
|
||||
[ModuleInitializer]
|
||||
public static void Initialize()
|
||||
{
|
||||
RobustNativeDll.IsServerProcess = true;
|
||||
}
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Security.Cryptography;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Robust.Server.ServerStatus;
|
||||
using Robust.Shared;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Network.Messages.Transfer;
|
||||
using Robust.Shared.Network.Transfer;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Robust.Server.Network.Transfer;
|
||||
|
||||
internal sealed class ServerTransferImplWebSocket : TransferImplWebSocket
|
||||
{
|
||||
private readonly IConfigurationManager _cfg;
|
||||
private readonly INetManager _netManager;
|
||||
private readonly SemaphoreSlim _apiLock = new(1, 1);
|
||||
private readonly TaskCompletionSource _connectTcs = new();
|
||||
|
||||
// To authenticate the client doing the HTTP request,
|
||||
// we ask that they provide a key we gave them via Lidgren traffic.
|
||||
public byte[]? Key;
|
||||
|
||||
public ServerTransferImplWebSocket(
|
||||
ISawmill sawmill,
|
||||
BaseTransferManager parent,
|
||||
IConfigurationManager cfg,
|
||||
INetManager netManager,
|
||||
INetChannel channel)
|
||||
: base(sawmill, parent, channel)
|
||||
{
|
||||
_cfg = cfg;
|
||||
_netManager = netManager;
|
||||
}
|
||||
|
||||
public override Task ServerInit()
|
||||
{
|
||||
Key = RandomNumberGenerator.GetBytes(RandomKeyBytes);
|
||||
|
||||
var uriBuilder = new UriBuilder(string.Concat(
|
||||
_cfg.GetCVar(CVars.TransferHttpEndpoint).TrimEnd("/"),
|
||||
ServerTransferManager.TransferApiUrl));
|
||||
|
||||
uriBuilder.Scheme = uriBuilder.Scheme switch
|
||||
{
|
||||
"http" => "ws",
|
||||
"https" => "wss",
|
||||
_ => throw new InvalidOperationException($"Invalid API endpoint scheme: {uriBuilder.Scheme}")
|
||||
};
|
||||
|
||||
var url = uriBuilder.ToString();
|
||||
|
||||
Sawmill.Verbose($"Transfer API URL is '{url}'");
|
||||
|
||||
var initMsg = new MsgTransferInit();
|
||||
initMsg.HttpInfo = (url, Key);
|
||||
|
||||
_netManager.ServerSendMessage(initMsg, Channel);
|
||||
|
||||
return _connectTcs.Task;
|
||||
}
|
||||
|
||||
public override Task ClientInit(CancellationToken cancel)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public async Task HandleApiRequest(NetUserId userId, IStatusHandlerContext context)
|
||||
{
|
||||
using var _ = await _apiLock.WaitGuardAsync();
|
||||
|
||||
if (Key == null)
|
||||
{
|
||||
Sawmill.Warning($"HTTP request failed: UserID '{userId}' tried to connect twice");
|
||||
await context.RespondErrorAsync(HttpStatusCode.BadRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!context.RequestHeaders.TryGetValue(KeyHeaderName, out var keyValue) || keyValue is not [{ } keyValueStr])
|
||||
{
|
||||
await context.RespondErrorAsync(HttpStatusCode.BadRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
var buf = new byte[RandomKeyBytes];
|
||||
|
||||
if (!Convert.TryFromBase64String(keyValueStr, buf, out var written) || written != RandomKeyBytes)
|
||||
{
|
||||
Sawmill.Verbose("HTTP request failed: key is not valid base64 or wrong length");
|
||||
await context.RespondErrorAsync(HttpStatusCode.BadRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!CryptographicOperations.FixedTimeEquals(buf, Key))
|
||||
{
|
||||
Sawmill.Warning("HTTP request failed: key is wrong");
|
||||
await context.RespondErrorAsync(HttpStatusCode.Unauthorized);
|
||||
return;
|
||||
}
|
||||
|
||||
Sawmill.Debug("Client connect to transfer WS channel: {UserId}", userId);
|
||||
|
||||
WebSocket = await context.AcceptWebSocketAsync();
|
||||
|
||||
// We've connected.
|
||||
// Clear key so this can't be reconnected to.
|
||||
Key = null;
|
||||
|
||||
_connectTcs.TrySetResult();
|
||||
|
||||
ReadThread();
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
_connectTcs.TrySetCanceled();
|
||||
}
|
||||
}
|
||||
@@ -1,171 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using Robust.Server.ServerStatus;
|
||||
using Robust.Shared;
|
||||
using Robust.Shared.Asynchronous;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Network.Messages.Transfer;
|
||||
using Robust.Shared.Network.Transfer;
|
||||
|
||||
namespace Robust.Server.Network.Transfer;
|
||||
|
||||
internal sealed class ServerTransferManager : BaseTransferManager, ITransferManager
|
||||
{
|
||||
internal const string TransferApiUrl = "/rt_transfer_init";
|
||||
|
||||
private readonly IConfigurationManager _cfg;
|
||||
private readonly IStatusHost _statusHost;
|
||||
private readonly IServerNetManager _netManager;
|
||||
|
||||
private readonly Dictionary<NetUserId, Player> _onlinePlayers = new();
|
||||
|
||||
internal ServerTransferManager(IConfigurationManager cfg, IStatusHost statusHost, IServerNetManager netManager, ILogManager logManager, ITaskManager taskManager)
|
||||
: base(logManager, NetMessageAccept.Server, taskManager)
|
||||
{
|
||||
_cfg = cfg;
|
||||
_statusHost = statusHost;
|
||||
_netManager = netManager;
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
_netManager.RegisterNetMessage<MsgTransferInit>();
|
||||
_netManager.RegisterNetMessage<MsgTransferData>(RxTransferData, NetMessageAccept.Server | NetMessageAccept.Handshake);
|
||||
_netManager.RegisterNetMessage<MsgTransferAckInit>(RxTransferAckInit, NetMessageAccept.Server | NetMessageAccept.Handshake);
|
||||
|
||||
_statusHost.AddHandler(HandleRequest);
|
||||
|
||||
_netManager.Disconnect += NetManagerOnDisconnect;
|
||||
}
|
||||
|
||||
private void RxTransferData(MsgTransferData message)
|
||||
{
|
||||
if (!_onlinePlayers.TryGetValue(message.MsgChannel.UserId, out var player)
|
||||
|| player.Impl is not TransferImplLidgren lidgren)
|
||||
{
|
||||
message.MsgChannel.Disconnect("Not lidgren");
|
||||
return;
|
||||
}
|
||||
|
||||
lidgren.ReceiveData(message);
|
||||
}
|
||||
|
||||
private void RxTransferAckInit(MsgTransferAckInit message)
|
||||
{
|
||||
if (!_onlinePlayers.TryGetValue(message.MsgChannel.UserId, out var player)
|
||||
|| player.Impl is not TransferImplLidgren lidgren)
|
||||
{
|
||||
message.MsgChannel.Disconnect("Not lidgren");
|
||||
return;
|
||||
}
|
||||
|
||||
lidgren.ReceiveInitAck();
|
||||
}
|
||||
|
||||
public Stream StartTransfer(INetChannel channel, TransferStartInfo startInfo)
|
||||
{
|
||||
if (!_onlinePlayers.TryGetValue(channel.UserId, out var player))
|
||||
throw new InvalidOperationException("Player is not connected yet!");
|
||||
|
||||
return player.Impl.StartTransfer(startInfo);
|
||||
}
|
||||
|
||||
private async Task<bool> HandleRequest(IStatusHandlerContext context)
|
||||
{
|
||||
if (context.Url.AbsolutePath != TransferApiUrl)
|
||||
return false;
|
||||
|
||||
if (!context.IsWebSocketRequest)
|
||||
{
|
||||
Sawmill.Verbose("HTTP request failed: not a websocket request");
|
||||
await context.RespondErrorAsync(HttpStatusCode.BadRequest);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!context.RequestHeaders.TryGetValue(TransferImplWebSocket.UserIdHeaderName, out var userIdValue)
|
||||
|| userIdValue.Count != 1)
|
||||
{
|
||||
Sawmill.Verbose("HTTP request failed: missing RT-UserId");
|
||||
await context.RespondErrorAsync(HttpStatusCode.BadRequest);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!Guid.TryParse(userIdValue[0], out var userId))
|
||||
{
|
||||
Sawmill.Verbose($"HTTP request failed: UserID '{userId}' invalid");
|
||||
await context.RespondErrorAsync(HttpStatusCode.BadRequest);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!_onlinePlayers.TryGetValue(new NetUserId(userId), out var player))
|
||||
{
|
||||
Sawmill.Warning($"HTTP request failed: UserID '{userId}' not online");
|
||||
await context.RespondErrorAsync(HttpStatusCode.BadRequest);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (player.Impl is not ServerTransferImplWebSocket serverWs)
|
||||
{
|
||||
Sawmill.Warning($"HTTP request failed: UserID '{userId}' is not using websocket transfer");
|
||||
await context.RespondErrorAsync(HttpStatusCode.Unauthorized);
|
||||
return true;
|
||||
}
|
||||
|
||||
await serverWs.HandleApiRequest(new NetUserId(userId), context);
|
||||
return true;
|
||||
}
|
||||
|
||||
public async Task ServerHandshake(INetChannel channel)
|
||||
{
|
||||
if (_onlinePlayers.ContainsKey(channel.UserId))
|
||||
throw new InvalidOperationException("We already have data for this user??");
|
||||
|
||||
var transferHttpEnabled = _cfg.GetCVar(CVars.TransferHttp);
|
||||
|
||||
BaseTransferImpl impl;
|
||||
if (transferHttpEnabled)
|
||||
{
|
||||
impl = new ServerTransferImplWebSocket(Sawmill, this, _cfg, _netManager, channel);
|
||||
}
|
||||
else
|
||||
{
|
||||
impl = new TransferImplLidgren(Sawmill, channel, this, _netManager);
|
||||
}
|
||||
|
||||
impl.MaxChannelCount = _cfg.GetCVar(CVars.TransferStreamLimit);
|
||||
|
||||
var datum = new Player
|
||||
{
|
||||
Impl = impl,
|
||||
};
|
||||
|
||||
_onlinePlayers.Add(channel.UserId, datum);
|
||||
|
||||
await impl.ServerInit();
|
||||
}
|
||||
|
||||
public event Action ClientHandshakeComplete
|
||||
{
|
||||
add { }
|
||||
remove { }
|
||||
}
|
||||
|
||||
private void NetManagerOnDisconnect(object? sender, NetDisconnectedArgs e)
|
||||
{
|
||||
if (!_onlinePlayers.Remove(e.Channel.UserId, out var player))
|
||||
return;
|
||||
|
||||
Sawmill.Debug("Cleaning up connection for channel {Player} that disconnected", e.Channel);
|
||||
player.Impl.Dispose();
|
||||
}
|
||||
|
||||
private sealed class Player
|
||||
{
|
||||
public required BaseTransferImpl Impl;
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
using Robust.Server.Console;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Network.Transfer;
|
||||
|
||||
namespace Robust.Server.Network.Transfer;
|
||||
|
||||
internal sealed class ServerTransferTestManager(
|
||||
ITransferManager manager,
|
||||
ILogManager logManager,
|
||||
IConGroupController controller,
|
||||
IPlayerManager playerManager)
|
||||
: TransferTestManager(manager, logManager)
|
||||
{
|
||||
protected override bool PermissionCheck(INetChannel channel)
|
||||
{
|
||||
if (!playerManager.TryGetSessionByChannel(channel, out var session))
|
||||
return false;
|
||||
|
||||
return controller.CanCommand(session, TransferTestCommand.CommandKey);
|
||||
}
|
||||
}
|
||||
@@ -217,10 +217,6 @@ namespace Robust.Server.Placement
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes any existing entity.
|
||||
/// </summary>
|
||||
/// <param name="msg"></param>
|
||||
private void HandleEntRemoveReq(MsgPlacement msg)
|
||||
{
|
||||
//TODO: Some form of admin check
|
||||
@@ -229,61 +225,26 @@ namespace Robust.Server.Placement
|
||||
if (!_entityManager.EntityExists(entity))
|
||||
return;
|
||||
|
||||
var placementEraseEvent = new PlacementEntityEvent(entity,
|
||||
_entityManager.GetComponent<TransformComponent>(entity).Coordinates,
|
||||
PlacementEventAction.Erase,
|
||||
msg.MsgChannel.UserId);
|
||||
|
||||
var placementEraseEvent = new PlacementEntityEvent(entity, _entityManager.GetComponent<TransformComponent>(entity).Coordinates, PlacementEventAction.Erase, msg.MsgChannel.UserId);
|
||||
_entityManager.EventBus.RaiseEvent(EventSource.Local, placementEraseEvent);
|
||||
_entityManager.DeleteEntity(entity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes almost any existing entity within a selection box.
|
||||
/// </summary>
|
||||
/// <param name="msg"></param>
|
||||
private void HandleRectRemoveReq(MsgPlacement msg)
|
||||
{
|
||||
var start = _entityManager.GetCoordinates(msg.NetCoordinates);
|
||||
var rectSize = msg.RectSize;
|
||||
|
||||
foreach (var entity in _lookup.GetEntitiesIntersecting(_xformSystem.GetMapId(start), new Box2(start.Position, start.Position + rectSize)))
|
||||
EntityCoordinates start = _entityManager.GetCoordinates(msg.NetCoordinates);
|
||||
Vector2 rectSize = msg.RectSize;
|
||||
foreach (var entity in _lookup.GetEntitiesIntersecting(_xformSystem.GetMapId(start),
|
||||
new Box2(start.Position, start.Position + rectSize)))
|
||||
{
|
||||
if (_entityManager.Deleted(entity)
|
||||
|| _entityManager.HasComponent<MapGridComponent>(entity)
|
||||
|| _entityManager.HasComponent<ActorComponent>(entity))
|
||||
continue;
|
||||
|
||||
var xform = _entityManager.GetComponent<TransformComponent>(entity);
|
||||
var parent = xform.ParentUid;
|
||||
var isChildOfActor = false;
|
||||
|
||||
while (parent.IsValid())
|
||||
if (_entityManager.Deleted(entity) ||
|
||||
_entityManager.HasComponent<MapGridComponent>(entity) ||
|
||||
_entityManager.HasComponent<ActorComponent>(entity))
|
||||
{
|
||||
if (_entityManager.HasComponent<ActorComponent>(parent))
|
||||
{
|
||||
isChildOfActor = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (_entityManager.TryGetComponent<TransformComponent>(parent, out var parentXform))
|
||||
{
|
||||
parent = parentXform.ParentUid;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isChildOfActor)
|
||||
continue;
|
||||
|
||||
var placementEraseEvent = new PlacementEntityEvent(entity,
|
||||
_entityManager.GetComponent<TransformComponent>(entity).Coordinates,
|
||||
PlacementEventAction.Erase,
|
||||
msg.MsgChannel.UserId);
|
||||
|
||||
var placementEraseEvent = new PlacementEntityEvent(entity, _entityManager.GetComponent<TransformComponent>(entity).Coordinates, PlacementEventAction.Erase, msg.MsgChannel.UserId);
|
||||
_entityManager.EventBus.RaiseEvent(EventSource.Local, placementEraseEvent);
|
||||
_entityManager.DeleteEntity(entity);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Robust.Shared.Input;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Player;
|
||||
|
||||
namespace Robust.Server.Player;
|
||||
@@ -11,6 +10,4 @@ namespace Robust.Server.Player;
|
||||
public interface IPlayerManager : ISharedPlayerManager
|
||||
{
|
||||
BoundKeyMap KeyMap { get; }
|
||||
|
||||
internal void MarkPlayerResourcesSent(INetChannel channel);
|
||||
}
|
||||
|
||||
@@ -120,34 +120,13 @@ namespace Robust.Server.Player
|
||||
private void HandlePlayerListReq(MsgPlayerListReq message)
|
||||
{
|
||||
var channel = message.MsgChannel;
|
||||
var session = (CommonSession) GetSessionByChannel(channel);
|
||||
session.InitialPlayerListReqDone = true;
|
||||
|
||||
if (!session.InitialResourcesDone)
|
||||
return;
|
||||
|
||||
SendPlayerList(channel, session);
|
||||
}
|
||||
|
||||
public void MarkPlayerResourcesSent(INetChannel channel)
|
||||
{
|
||||
var session = (CommonSession) GetSessionByChannel(channel);
|
||||
session.InitialResourcesDone = true;
|
||||
|
||||
if (!session.InitialPlayerListReqDone)
|
||||
return;
|
||||
|
||||
SendPlayerList(channel, session);
|
||||
}
|
||||
|
||||
private void SendPlayerList(INetChannel channel, CommonSession session)
|
||||
{
|
||||
var players = Sessions;
|
||||
var netMsg = new MsgPlayerList();
|
||||
|
||||
// client session is complete, set their status accordingly.
|
||||
// This is done before the packet is built, so that the client
|
||||
// can see themselves Connected.
|
||||
var session = GetSessionByChannel(channel);
|
||||
session.ConnectedTime = DateTime.UtcNow;
|
||||
SetStatus(session, SessionStatus.Connected);
|
||||
|
||||
|
||||
@@ -13,10 +13,10 @@ namespace Robust.Server.Prototypes
|
||||
{
|
||||
public sealed class ServerPrototypeManager : PrototypeManager
|
||||
{
|
||||
#if TOOLS
|
||||
#pragma warning disable CS0414
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
[Dependency] private readonly IConGroupController _conGroups = default!;
|
||||
#endif
|
||||
#pragma warning restore CS0414
|
||||
[Dependency] private readonly INetManager _netManager = default!;
|
||||
[Dependency] private readonly IBaseServerInternal _server = default!;
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Lidgren.Network\Lidgren.Network.csproj" />
|
||||
<ProjectReference Include="..\NetSerializer\NetSerializer\NetSerializer.csproj" />
|
||||
<ProjectReference Include="..\Robust.Shared.Interop.RobustNative\Robust.Shared.Interop.RobustNative.csproj" />
|
||||
<ProjectReference Include="..\Robust.Shared.Maths\Robust.Shared.Maths.csproj" />
|
||||
<ProjectReference Include="..\Robust.Shared.Scripting\Robust.Shared.Scripting.csproj" />
|
||||
<ProjectReference Include="..\Robust.Shared\Robust.Shared.csproj" />
|
||||
|
||||
@@ -5,7 +5,6 @@ using Robust.Server.DataMetrics;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Server.GameStates;
|
||||
using Robust.Server.Localization;
|
||||
using Robust.Server.Network.Transfer;
|
||||
using Robust.Server.Placement;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Server.Prototypes;
|
||||
@@ -26,7 +25,6 @@ using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Network.Transfer;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Reflection;
|
||||
@@ -104,8 +102,6 @@ namespace Robust.Server
|
||||
deps.Register<IHWId, DummyHWId>();
|
||||
deps.Register<ILocalizationManager, ServerLocalizationManager>();
|
||||
deps.Register<ILocalizationManagerInternal, ServerLocalizationManager>();
|
||||
deps.Register<ITransferManager, ServerTransferManager>();
|
||||
deps.Register<ServerTransferTestManager>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.WebSockets;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
|
||||
@@ -26,8 +25,6 @@ namespace Robust.Server.ServerStatus
|
||||
IDictionary<string, string> ResponseHeaders { get; }
|
||||
bool KeepAlive { get; set; }
|
||||
|
||||
bool IsWebSocketRequest { get; }
|
||||
|
||||
Task<T?> RequestBodyJsonAsync<T>();
|
||||
|
||||
Task RespondNoContentAsync();
|
||||
@@ -57,7 +54,5 @@ namespace Robust.Server.ServerStatus
|
||||
Task RespondJsonAsync(object jsonData, HttpStatusCode code = HttpStatusCode.OK);
|
||||
|
||||
Task<Stream> RespondStreamAsync(HttpStatusCode code = HttpStatusCode.OK);
|
||||
|
||||
Task<WebSocket> AcceptWebSocketAsync();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Mime;
|
||||
using System.Net.WebSockets;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using System.Text.Json.Serialization;
|
||||
@@ -243,7 +242,6 @@ namespace Robust.Server.ServerStatus
|
||||
public Uri Url => _context.Request.Url!;
|
||||
public bool IsGetLike => RequestMethod == HttpMethod.Head || RequestMethod == HttpMethod.Get;
|
||||
public IReadOnlyDictionary<string, StringValues> RequestHeaders { get; }
|
||||
public bool IsWebSocketRequest => _context.Request.IsWebSocketRequest;
|
||||
|
||||
public bool KeepAlive
|
||||
{
|
||||
@@ -355,12 +353,6 @@ namespace Robust.Server.ServerStatus
|
||||
return Task.FromResult(_context.Response.OutputStream);
|
||||
}
|
||||
|
||||
public async Task<WebSocket> AcceptWebSocketAsync()
|
||||
{
|
||||
var context = await _context.AcceptWebSocketAsync(null);
|
||||
return context.WebSocket;
|
||||
}
|
||||
|
||||
private void RespondShared()
|
||||
{
|
||||
foreach (var (header, value) in _responseHeaders)
|
||||
|
||||
@@ -1,153 +1,77 @@
|
||||
using System;
|
||||
using System.Buffers.Binary;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using Robust.Server.Console;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Network.Transfer;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Upload;
|
||||
using Robust.Shared.Utility;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Robust.Server.Upload;
|
||||
|
||||
public sealed class NetworkResourcesUploadedEvent
|
||||
{
|
||||
public ICommonSession Session { get; }
|
||||
public ImmutableArray<(ResPath Relative, byte[] Data)> Files { get; }
|
||||
|
||||
internal NetworkResourcesUploadedEvent(ICommonSession session, ImmutableArray<(ResPath, byte[])> files)
|
||||
{
|
||||
Session = session;
|
||||
Files = files;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class NetworkResourceManager : SharedNetworkResourceManager
|
||||
{
|
||||
internal const int AckInitial = 1;
|
||||
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
[Dependency] private readonly IServerNetManager _serverNetManager = default!;
|
||||
[Dependency] private readonly IConfigurationManager _cfgManager = default!;
|
||||
[Dependency] private readonly IConGroupController _controller = default!;
|
||||
|
||||
[Obsolete("Use ResourcesUploaded instead")]
|
||||
public event Action<ICommonSession, NetworkResourceUploadMessage>? OnResourceUploaded;
|
||||
public event Action<NetworkResourcesUploadedEvent>? ResourcesUploaded;
|
||||
|
||||
[ViewVariables] public bool Enabled { get; private set; } = true;
|
||||
[ViewVariables] public float SizeLimit { get; private set; }
|
||||
|
||||
internal event Action<INetChannel, int>? AckReceived;
|
||||
|
||||
internal override void Initialize()
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
TransferManager.RegisterTransferMessage(TransferKeyNetworkDownload);
|
||||
TransferManager.RegisterTransferMessage(TransferKeyNetworkUpload, ReceiveUpload);
|
||||
|
||||
_cfgManager.OnValueChanged(CVars.ResourceUploadingEnabled, value => Enabled = value, true);
|
||||
_cfgManager.OnValueChanged(CVars.ResourceUploadingLimitMb, value => SizeLimit = value, true);
|
||||
|
||||
_serverNetManager.RegisterNetMessage<NetworkResourceAckMessage>(RxAck);
|
||||
}
|
||||
|
||||
private void RxAck(NetworkResourceAckMessage message)
|
||||
{
|
||||
AckReceived?.Invoke(message.MsgChannel, message.Key);
|
||||
}
|
||||
|
||||
private async void ReceiveUpload(TransferReceivedEvent transfer)
|
||||
/// <summary>
|
||||
/// Callback for when a client attempts to upload a resource.
|
||||
/// </summary>
|
||||
/// <param name="msg"></param>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
protected override void ResourceUploadMsg(NetworkResourceUploadMessage msg)
|
||||
{
|
||||
// Do not allow uploading any new resources if it has been disabled.
|
||||
// Note: Any resources uploaded before being disabled will still be kept and sent.
|
||||
if (!Enabled)
|
||||
{
|
||||
transfer.Channel.Disconnect("Resource upload not enabled.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_playerManager.TryGetSessionByChannel(transfer.Channel, out var session))
|
||||
{
|
||||
transfer.Channel.Disconnect("Not in-game");
|
||||
if (!_playerManager.TryGetSessionByChannel(msg.MsgChannel, out var session))
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_controller.CanCommand(session, "uploadfile"))
|
||||
{
|
||||
transfer.Channel.Disconnect("Not authorized");
|
||||
return;
|
||||
}
|
||||
|
||||
Sawmill.Verbose("Ingesting file uploads from {Session}", session);
|
||||
// Ensure the data is under the current size limit, if it's currently enabled.
|
||||
if (SizeLimit > 0f && msg.Data.Length * BytesToMegabytes > SizeLimit)
|
||||
return;
|
||||
|
||||
List<(ResPath Relative, byte[] Data)> ingested;
|
||||
await using (var stream = transfer.DataStream)
|
||||
{
|
||||
ingested = await IngestFileStream(stream);
|
||||
}
|
||||
|
||||
Sawmill.Verbose("Ingesting file uploads complete, distributing...");
|
||||
base.ResourceUploadMsg(msg);
|
||||
|
||||
// Now we broadcast the message!
|
||||
foreach (var channel in _serverNetManager.Channels)
|
||||
{
|
||||
SendToPlayer(channel, ingested);
|
||||
channel.SendMessage(msg);
|
||||
}
|
||||
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
if (OnResourceUploaded != null)
|
||||
OnResourceUploaded?.Invoke(session, msg);
|
||||
}
|
||||
|
||||
internal void SendToNewUser(INetChannel channel)
|
||||
{
|
||||
foreach (var (path, data) in ContentRoot.GetAllFiles())
|
||||
{
|
||||
foreach (var (relative, data) in ingested)
|
||||
{
|
||||
OnResourceUploaded?.Invoke(session, new NetworkResourceUploadMessage
|
||||
{
|
||||
MsgChannel = session.Channel,
|
||||
Data = data,
|
||||
RelativePath = relative
|
||||
});
|
||||
}
|
||||
var msg = new NetworkResourceUploadMessage();
|
||||
msg.RelativePath = path;
|
||||
msg.Data = data;
|
||||
channel.SendMessage(msg);
|
||||
}
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
|
||||
ResourcesUploaded?.Invoke(new NetworkResourcesUploadedEvent(session, [..ingested]));
|
||||
}
|
||||
|
||||
protected override void ValidateUpload(uint size)
|
||||
{
|
||||
if (SizeLimit > 0f && size * BytesToMegabytes > SizeLimit)
|
||||
throw new Exception("File upload too large!");
|
||||
}
|
||||
|
||||
internal bool SendToNewUser(INetChannel channel)
|
||||
{
|
||||
var allFiles = ContentRoot.GetAllFiles().ToList();
|
||||
if (allFiles.Count == 0)
|
||||
return false;
|
||||
|
||||
SendToPlayer(channel, allFiles, AckInitial);
|
||||
return true;
|
||||
}
|
||||
|
||||
private async void SendToPlayer(INetChannel channel, List<(ResPath Relative, byte[] Data)> files, int ack = 0)
|
||||
{
|
||||
await using var stream = TransferManager.StartTransfer(channel,
|
||||
new TransferStartInfo
|
||||
{
|
||||
MessageKey = TransferKeyNetworkDownload
|
||||
});
|
||||
|
||||
var ackBytes = new byte[4];
|
||||
BinaryPrimitives.WriteInt32LittleEndian(ackBytes, ack);
|
||||
await stream.WriteAsync(ackBytes);
|
||||
|
||||
await WriteFileStream(stream, files);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Network;
|
||||
|
||||
namespace Robust.Server.Upload;
|
||||
@@ -10,36 +9,20 @@ namespace Robust.Server.Upload;
|
||||
internal sealed class UploadedContentManager
|
||||
{
|
||||
[Dependency] private readonly IServerNetManager _netManager = default!;
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
[Dependency] private readonly GamePrototypeLoadManager _prototypeLoadManager = default!;
|
||||
[Dependency] private readonly NetworkResourceManager _networkResourceManager = default!;
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
_netManager.Connected += NetManagerOnConnected;
|
||||
_networkResourceManager.AckReceived += OnAckReceived;
|
||||
}
|
||||
|
||||
private void OnAckReceived(INetChannel channel, int ack)
|
||||
{
|
||||
if (ack != NetworkResourceManager.AckInitial)
|
||||
return;
|
||||
|
||||
ResourcesReady(channel);
|
||||
}
|
||||
|
||||
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.
|
||||
var sentAny = _networkResourceManager.SendToNewUser(e.Channel);
|
||||
if (!sentAny)
|
||||
ResourcesReady(e.Channel);
|
||||
}
|
||||
|
||||
private void ResourcesReady(INetChannel channel)
|
||||
{
|
||||
_prototypeLoadManager.SendToNewUser(channel);
|
||||
_playerManager.MarkPlayerResourcesSent(channel);
|
||||
// Note: both net messages sent here are on the same group and are therefore ordered.
|
||||
_networkResourceManager.SendToNewUser(e.Channel);
|
||||
_prototypeLoadManager.SendToNewUser(e.Channel);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,5 @@ namespace Robust.Server.ViewVariables
|
||||
object Object { get; }
|
||||
uint SessionId { get; }
|
||||
Type ObjectType { get; }
|
||||
Action<object>? ObjectChangeDelegate { get; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Robust.Server.Console;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
@@ -137,7 +138,6 @@ namespace Robust.Server.ViewVariables
|
||||
}
|
||||
|
||||
object theObject;
|
||||
Action<object>? objectChangeDelegate = null;
|
||||
|
||||
switch (message.Selector)
|
||||
{
|
||||
@@ -200,14 +200,13 @@ namespace Robust.Server.ViewVariables
|
||||
return;
|
||||
}
|
||||
|
||||
if (value == null)
|
||||
if (value == null || value.GetType().IsValueType)
|
||||
{
|
||||
Deny(ViewVariablesResponseCode.NoObject);
|
||||
return;
|
||||
}
|
||||
|
||||
theObject = value;
|
||||
objectChangeDelegate = obj => relSession.Modify(sessionRelativeSelector.PropertyIndex, obj);
|
||||
break;
|
||||
}
|
||||
case ViewVariablesIoCSelector ioCSelector:
|
||||
@@ -251,7 +250,7 @@ namespace Robust.Server.ViewVariables
|
||||
}
|
||||
|
||||
var sessionId = _nextSessionId++;
|
||||
var session = new ViewVariablesSession(message.MsgChannel.UserId, theObject, objectChangeDelegate, sessionId, this,
|
||||
var session = new ViewVariablesSession(message.MsgChannel.UserId, theObject, sessionId, this,
|
||||
_robustSerializer, _entityManager, Sawmill);
|
||||
|
||||
_sessions.Add(sessionId, session);
|
||||
|
||||
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Prototypes;
|
||||
@@ -197,8 +198,6 @@ namespace Robust.Server.ViewVariables.Traits
|
||||
try
|
||||
{
|
||||
field.SetValue(Session.Object, value);
|
||||
Session.ObjectChangeDelegate?.Invoke(Session.Object);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
|
||||
@@ -22,7 +22,6 @@ namespace Robust.Server.ViewVariables
|
||||
public object Object { get; }
|
||||
public uint SessionId { get; }
|
||||
public Type ObjectType { get; }
|
||||
public Action<object>? ObjectChangeDelegate { get; }
|
||||
|
||||
/// <param name="playerUser">The session ID of the player who opened this session.</param>
|
||||
/// <param name="o">The object we represent.</param>
|
||||
@@ -30,14 +29,13 @@ namespace Robust.Server.ViewVariables
|
||||
/// The session ID for this session. This is what the server and client use to talk about this session.
|
||||
/// </param>
|
||||
/// <param name="host">The view variables host owning this session.</param>
|
||||
public ViewVariablesSession(NetUserId playerUser, object o, Action<object>? objectChangeDelegate, uint sessionId, IServerViewVariablesInternal host,
|
||||
public ViewVariablesSession(NetUserId playerUser, object o, uint sessionId, IServerViewVariablesInternal host,
|
||||
IRobustSerializer robustSerializer, IEntityManager entMan, ISawmill logger)
|
||||
{
|
||||
PlayerUser = playerUser;
|
||||
Object = o;
|
||||
SessionId = sessionId;
|
||||
ObjectType = o.GetType();
|
||||
ObjectChangeDelegate = objectChangeDelegate;
|
||||
Host = host;
|
||||
RobustSerializer = robustSerializer;
|
||||
EntityManager = entMan;
|
||||
|
||||
@@ -2,14 +2,9 @@ using System;
|
||||
using System.IO;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Robust.Server;
|
||||
using Robust.Server.Configuration;
|
||||
using Robust.Server.Network.Transfer;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Server.Reflection;
|
||||
using Robust.Server.Serialization;
|
||||
using Robust.Server.ServerStatus;
|
||||
using Robust.Shared.Asynchronous;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.ContentPack;
|
||||
using Robust.Shared.GameObjects;
|
||||
@@ -18,7 +13,6 @@ using Robust.Shared.Log;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Map.Components;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Network.Transfer;
|
||||
using Robust.Shared.Profiling;
|
||||
using Robust.Shared.Reflection;
|
||||
using Robust.Shared.Replays;
|
||||
@@ -49,7 +43,6 @@ namespace Robust.UnitTesting.Shared.GameObjects
|
||||
container.Register<IAuthManager, AuthManager>();
|
||||
container.Register<IGameTiming, GameTiming>();
|
||||
container.Register<ProfManager, ProfManager>();
|
||||
container.RegisterInstance<ITransferManager>(Mock.Of<ITransferManager>());
|
||||
container.Register<HttpClientHolder>();
|
||||
container.RegisterInstance<IReplayRecordingManager>(new Mock<IReplayRecordingManager>().Object);
|
||||
container.BuildGraph();
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Robust.Server.Configuration;
|
||||
@@ -85,6 +88,7 @@ namespace Robust.UnitTesting.Shared.GameObjects
|
||||
deps.Register<IDynamicTypeFactoryInternal, DynamicTypeFactory>();
|
||||
deps.RegisterInstance<IModLoader>(new Mock<IModLoader>().Object);
|
||||
deps.Register<IEntitySystemManager, EntitySystemManager>();
|
||||
deps.RegisterInstance<IEntityManager>(new Mock<IEntityManager>().Object);
|
||||
// WHEN WILL THE SUFFERING END
|
||||
deps.RegisterInstance<IReplayRecordingManager>(new Mock<IReplayRecordingManager>().Object);
|
||||
|
||||
@@ -100,15 +104,6 @@ namespace Robust.UnitTesting.Shared.GameObjects
|
||||
|
||||
deps.RegisterInstance<IReflectionManager>(reflectionMock.Object);
|
||||
|
||||
// Never
|
||||
var componentFactoryMock = new Mock<IComponentFactory>();
|
||||
componentFactoryMock.Setup(p => p.AllRegisteredTypes).Returns(Enumerable.Empty<Type>());
|
||||
deps.RegisterInstance<IComponentFactory>(componentFactoryMock.Object);
|
||||
|
||||
var entityManagerMock = new Mock<IEntityManager>();
|
||||
entityManagerMock.Setup(p => p.ComponentFactory).Returns(componentFactoryMock.Object);
|
||||
deps.RegisterInstance<IEntityManager>(entityManagerMock.Object);
|
||||
|
||||
deps.BuildGraph();
|
||||
|
||||
IoCManager.InitThread(deps, true);
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using Robust.Shared.Analyzers;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.IoC.Exceptions;
|
||||
using Robust.Shared.Physics.Components;
|
||||
|
||||
namespace Robust.UnitTesting.Shared.GameObjects
|
||||
{
|
||||
@@ -38,14 +39,6 @@ namespace Robust.UnitTesting.Shared.GameObjects
|
||||
[Dependency] public readonly ESystemDepA ESystemDepA = default!;
|
||||
}
|
||||
|
||||
internal sealed class ESystemDepAll : EntitySystem
|
||||
{
|
||||
[Dependency] public readonly ESystemDepA ESystemDepA = default!;
|
||||
[Dependency] public readonly IConfigurationManager Config = default!;
|
||||
[Dependency] public readonly EntityQuery<TransformComponent> TransformQuery = default!;
|
||||
[Dependency] public readonly EntityQuery<PhysicsComponent> PhysicsQuery = default!;
|
||||
}
|
||||
|
||||
/*
|
||||
ESystemBase (Abstract)
|
||||
- ESystemA
|
||||
@@ -65,7 +58,6 @@ namespace Robust.UnitTesting.Shared.GameObjects
|
||||
syssy.LoadExtraSystemType<ESystemC>();
|
||||
syssy.LoadExtraSystemType<ESystemDepA>();
|
||||
syssy.LoadExtraSystemType<ESystemDepB>();
|
||||
syssy.LoadExtraSystemType<ESystemDepAll>();
|
||||
syssy.Initialize(false);
|
||||
}
|
||||
|
||||
@@ -111,16 +103,5 @@ namespace Robust.UnitTesting.Shared.GameObjects
|
||||
Assert.That(sysB.ESystemDepA, Is.EqualTo(sysA));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DependencyInjectionTest()
|
||||
{
|
||||
var esm = IoCManager.Resolve<IEntitySystemManager>();
|
||||
var sys = esm.GetEntitySystem<ESystemDepAll>();
|
||||
|
||||
Assert.That(sys.ESystemDepA, Is.Not.Null);
|
||||
Assert.That(sys.Config, Is.Not.Null);
|
||||
Assert.That(sys.TransformQuery, Is.Not.Default);
|
||||
Assert.That(sys.PhysicsQuery, Is.Not.Default);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,203 +0,0 @@
|
||||
using JetBrains.Annotations;
|
||||
using NUnit.Framework;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.UnitTesting.Shared;
|
||||
|
||||
namespace Robust.Shared.IntegrationTests.Serialization;
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
[UsedImplicitly(Reason = "Needed so RobustSerializer is guaranteed to pick up on the unsafe types.")]
|
||||
internal sealed class MakeTheseSerializable
|
||||
{
|
||||
public UnsafeFloat Single;
|
||||
public UnsafeDouble Double;
|
||||
public UnsafeHalf Half;
|
||||
public Half SafeHalf;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests the serialization behavior of float types when <see cref="IRobustSerializer"/> is *not* set to do anything special.
|
||||
/// Tests both primitives and Robust's "Unsafe" variants.
|
||||
/// </summary>
|
||||
[TestFixture, TestOf(typeof(RobustSerializer)), TestOf(typeof(NetUnsafeFloatSerializer))]
|
||||
internal sealed class NetSerializerDefaultFloatTest : OurRobustUnitTest
|
||||
{
|
||||
private IRobustSerializer _serializer = null!;
|
||||
|
||||
[OneTimeSetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_serializer = IoCManager.Resolve<IRobustSerializer>();
|
||||
_serializer.Initialize();
|
||||
}
|
||||
|
||||
internal static readonly TestCaseData[] PassThroughFloatTests =
|
||||
[
|
||||
new TestCaseData(0.0).Returns(0.0),
|
||||
new TestCaseData(1.0).Returns(1.0),
|
||||
new TestCaseData(double.NaN).Returns(double.NaN),
|
||||
new TestCaseData(double.PositiveInfinity).Returns(double.PositiveInfinity),
|
||||
];
|
||||
|
||||
[TestCaseSource(nameof(PassThroughFloatTests))]
|
||||
public double TestSingle(double input)
|
||||
{
|
||||
var ms = new MemoryStream();
|
||||
_serializer.Serialize(ms, (float)input);
|
||||
|
||||
ms.Position = 0;
|
||||
|
||||
return _serializer.Deserialize<float>(ms);
|
||||
}
|
||||
|
||||
[TestCaseSource(nameof(PassThroughFloatTests))]
|
||||
public double TestUnsafeSingle(double input)
|
||||
{
|
||||
var ms = new MemoryStream();
|
||||
_serializer.Serialize(ms, (UnsafeFloat)input);
|
||||
|
||||
ms.Position = 0;
|
||||
|
||||
return _serializer.Deserialize<UnsafeFloat>(ms);
|
||||
}
|
||||
|
||||
[TestCaseSource(nameof(PassThroughFloatTests))]
|
||||
public double TestDouble(double input)
|
||||
{
|
||||
var ms = new MemoryStream();
|
||||
_serializer.Serialize(ms, input);
|
||||
|
||||
ms.Position = 0;
|
||||
|
||||
return _serializer.Deserialize<double>(ms);
|
||||
}
|
||||
|
||||
[TestCaseSource(nameof(PassThroughFloatTests))]
|
||||
public double TestUnsafeDouble(double input)
|
||||
{
|
||||
var ms = new MemoryStream();
|
||||
_serializer.Serialize(ms, (UnsafeDouble)input);
|
||||
|
||||
ms.Position = 0;
|
||||
|
||||
return _serializer.Deserialize<UnsafeDouble>(ms);
|
||||
}
|
||||
|
||||
[TestCaseSource(nameof(PassThroughFloatTests))]
|
||||
public double TestHalf(double input)
|
||||
{
|
||||
var ms = new MemoryStream();
|
||||
_serializer.Serialize(ms, (Half)input);
|
||||
|
||||
ms.Position = 0;
|
||||
|
||||
return (double)_serializer.Deserialize<Half>(ms);
|
||||
}
|
||||
|
||||
[TestCaseSource(nameof(PassThroughFloatTests))]
|
||||
public double TestUnsafeHalf(double input)
|
||||
{
|
||||
var ms = new MemoryStream();
|
||||
_serializer.Serialize(ms, (UnsafeHalf)(Half)input);
|
||||
|
||||
ms.Position = 0;
|
||||
|
||||
return (double)(Half)_serializer.Deserialize<UnsafeHalf>(ms);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests the serialization behavior of float types when <see cref="IRobustSerializer"/> is set to remove NaNs on read.
|
||||
/// Tests both primitives and Robust's "Unsafe" variants.
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
[TestOf(typeof(RobustSerializer)), TestOf(typeof(NetUnsafeFloatSerializer)), TestOf(typeof(NetSafeFloatSerializer))]
|
||||
internal sealed class NetSerializerSafeFloatTest : OurRobustUnitTest
|
||||
{
|
||||
private IRobustSerializer _serializer = default!;
|
||||
|
||||
[OneTimeSetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_serializer = IoCManager.Resolve<IRobustSerializer>();
|
||||
_serializer.FloatFlags = SerializerFloatFlags.RemoveReadNan;
|
||||
_serializer.Initialize();
|
||||
}
|
||||
|
||||
internal static readonly TestCaseData[] SafeFloatTests =
|
||||
[
|
||||
new TestCaseData(0.0).Returns(0.0),
|
||||
new TestCaseData(1.0).Returns(1.0),
|
||||
new TestCaseData(double.NaN).Returns(0.0),
|
||||
new TestCaseData(double.PositiveInfinity).Returns(double.PositiveInfinity),
|
||||
];
|
||||
|
||||
[TestCaseSource(nameof(SafeFloatTests))]
|
||||
public double TestSingle(double input)
|
||||
{
|
||||
var ms = new MemoryStream();
|
||||
_serializer.Serialize(ms, (float)input);
|
||||
|
||||
ms.Position = 0;
|
||||
|
||||
return _serializer.Deserialize<float>(ms);
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(NetSerializerDefaultFloatTest), nameof(NetSerializerDefaultFloatTest.PassThroughFloatTests))]
|
||||
public double TestUnsafeSingle(double input)
|
||||
{
|
||||
var ms = new MemoryStream();
|
||||
_serializer.Serialize(ms, (UnsafeFloat)input);
|
||||
|
||||
ms.Position = 0;
|
||||
|
||||
return _serializer.Deserialize<UnsafeFloat>(ms);
|
||||
}
|
||||
|
||||
[TestCaseSource(nameof(SafeFloatTests))]
|
||||
public double TestDouble(double input)
|
||||
{
|
||||
var ms = new MemoryStream();
|
||||
_serializer.Serialize(ms, input);
|
||||
|
||||
ms.Position = 0;
|
||||
|
||||
return _serializer.Deserialize<double>(ms);
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(NetSerializerDefaultFloatTest), nameof(NetSerializerDefaultFloatTest.PassThroughFloatTests))]
|
||||
public double TestUnsafeDouble(double input)
|
||||
{
|
||||
var ms = new MemoryStream();
|
||||
_serializer.Serialize(ms, (UnsafeDouble)input);
|
||||
|
||||
ms.Position = 0;
|
||||
|
||||
return _serializer.Deserialize<UnsafeDouble>(ms);
|
||||
}
|
||||
|
||||
|
||||
[TestCaseSource(nameof(SafeFloatTests))]
|
||||
public double TestHalf(double input)
|
||||
{
|
||||
var ms = new MemoryStream();
|
||||
_serializer.Serialize(ms, (Half)input);
|
||||
|
||||
ms.Position = 0;
|
||||
|
||||
return (double)_serializer.Deserialize<Half>(ms);
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(NetSerializerDefaultFloatTest), nameof(NetSerializerDefaultFloatTest.PassThroughFloatTests))]
|
||||
public double TestUnsafeHalf(double input)
|
||||
{
|
||||
var ms = new MemoryStream();
|
||||
_serializer.Serialize(ms, (UnsafeHalf)(Half)input);
|
||||
|
||||
ms.Position = 0;
|
||||
|
||||
return (double)(Half)_serializer.Deserialize<UnsafeHalf>(ms);
|
||||
}
|
||||
}
|
||||
5
Robust.Shared.Interop.RobustNative/AssemblyInfo.cs
Normal file
5
Robust.Shared.Interop.RobustNative/AssemblyInfo.cs
Normal file
@@ -0,0 +1,5 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("Robust.Shared")]
|
||||
[assembly: InternalsVisibleTo("Robust.Client")]
|
||||
[assembly: InternalsVisibleTo("Robust.Server")]
|
||||
2
Robust.Shared.Interop.RobustNative/GlobalUsings.cs
Normal file
2
Robust.Shared.Interop.RobustNative/GlobalUsings.cs
Normal file
@@ -0,0 +1,2 @@
|
||||
global using System.Runtime.InteropServices;
|
||||
global using Robust.Shared.Interop.RobustNative.Ogg;
|
||||
@@ -1,9 +1,9 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
// ReSharper disable IdentifierTypo
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
namespace Robust.Shared.Native;
|
||||
namespace Robust.Shared.Interop.RobustNative;
|
||||
|
||||
internal static class Libc
|
||||
internal static partial class Libc
|
||||
{
|
||||
public const int RTLD_LAZY = 0x00001;
|
||||
public const int RTLD_NOW = 0x00002;
|
||||
@@ -14,6 +14,6 @@ internal static class Libc
|
||||
public const int RTLD_LOCAL = 0;
|
||||
public const int RTLD_NODELETE = 0x01000;
|
||||
|
||||
[DllImport("libdl.so.2")]
|
||||
public static extern IntPtr dlopen([MarshalAs(UnmanagedType.LPUTF8Str)] string name, int flags);
|
||||
[LibraryImport("dl", StringMarshalling = StringMarshalling.Utf8)]
|
||||
public static partial IntPtr dlopen(string name, int flags);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Robust.Shared.Interop.RobustNative.Ogg;
|
||||
|
||||
/// <summary>Defines the annotation found in a native declaration.</summary>
|
||||
[AttributeUsage(AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = true, Inherited = false)]
|
||||
[Conditional("DEBUG")]
|
||||
internal sealed partial class NativeAnnotationAttribute : Attribute
|
||||
{
|
||||
private readonly string _annotation;
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="NativeAnnotationAttribute" /> class.</summary>
|
||||
/// <param name="annotation">The annotation that was used in the native declaration.</param>
|
||||
public NativeAnnotationAttribute(string annotation)
|
||||
{
|
||||
_annotation = annotation;
|
||||
}
|
||||
|
||||
/// <summary>Gets the annotation that was used in the native declaration.</summary>
|
||||
public string Annotation => _annotation;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Robust.Shared.Interop.RobustNative.Ogg;
|
||||
|
||||
/// <summary>Defines the type of a member as it was used in the native signature.</summary>
|
||||
[AttributeUsage(AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = false, Inherited = true)]
|
||||
[Conditional("DEBUG")]
|
||||
internal sealed partial class NativeTypeNameAttribute : Attribute
|
||||
{
|
||||
private readonly string _name;
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="NativeTypeNameAttribute" /> class.</summary>
|
||||
/// <param name="name">The name of the type that was used in the native signature.</param>
|
||||
public NativeTypeNameAttribute(string name)
|
||||
{
|
||||
_name = name;
|
||||
}
|
||||
|
||||
/// <summary>Gets the name of the type that was used in the native signature.</summary>
|
||||
public string Name => _name;
|
||||
}
|
||||
237
Robust.Shared.Interop.RobustNative/Ogg/Gen/Ogg.cs
Normal file
237
Robust.Shared.Interop.RobustNative/Ogg/Gen/Ogg.cs
Normal file
@@ -0,0 +1,237 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Robust.Shared.Interop.RobustNative.Ogg;
|
||||
|
||||
internal static unsafe partial class Ogg
|
||||
{
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern void oggpack_writeinit(oggpack_buffer* b);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int oggpack_writecheck(oggpack_buffer* b);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern void oggpack_writetrunc(oggpack_buffer* b, [NativeTypeName("long")] CLong bits);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern void oggpack_writealign(oggpack_buffer* b);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern void oggpack_writecopy(oggpack_buffer* b, void* source, [NativeTypeName("long")] CLong bits);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern void oggpack_reset(oggpack_buffer* b);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern void oggpack_writeclear(oggpack_buffer* b);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern void oggpack_readinit(oggpack_buffer* b, [NativeTypeName("unsigned char *")] byte* buf, int bytes);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern void oggpack_write(oggpack_buffer* b, [NativeTypeName("unsigned long")] CULong value, int bits);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
[return: NativeTypeName("long")]
|
||||
public static extern CLong oggpack_look(oggpack_buffer* b, int bits);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
[return: NativeTypeName("long")]
|
||||
public static extern CLong oggpack_look1(oggpack_buffer* b);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern void oggpack_adv(oggpack_buffer* b, int bits);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern void oggpack_adv1(oggpack_buffer* b);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
[return: NativeTypeName("long")]
|
||||
public static extern CLong oggpack_read(oggpack_buffer* b, int bits);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
[return: NativeTypeName("long")]
|
||||
public static extern CLong oggpack_read1(oggpack_buffer* b);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
[return: NativeTypeName("long")]
|
||||
public static extern CLong oggpack_bytes(oggpack_buffer* b);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
[return: NativeTypeName("long")]
|
||||
public static extern CLong oggpack_bits(oggpack_buffer* b);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
[return: NativeTypeName("unsigned char *")]
|
||||
public static extern byte* oggpack_get_buffer(oggpack_buffer* b);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern void oggpackB_writeinit(oggpack_buffer* b);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int oggpackB_writecheck(oggpack_buffer* b);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern void oggpackB_writetrunc(oggpack_buffer* b, [NativeTypeName("long")] CLong bits);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern void oggpackB_writealign(oggpack_buffer* b);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern void oggpackB_writecopy(oggpack_buffer* b, void* source, [NativeTypeName("long")] CLong bits);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern void oggpackB_reset(oggpack_buffer* b);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern void oggpackB_writeclear(oggpack_buffer* b);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern void oggpackB_readinit(oggpack_buffer* b, [NativeTypeName("unsigned char *")] byte* buf, int bytes);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern void oggpackB_write(oggpack_buffer* b, [NativeTypeName("unsigned long")] CULong value, int bits);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
[return: NativeTypeName("long")]
|
||||
public static extern CLong oggpackB_look(oggpack_buffer* b, int bits);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
[return: NativeTypeName("long")]
|
||||
public static extern CLong oggpackB_look1(oggpack_buffer* b);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern void oggpackB_adv(oggpack_buffer* b, int bits);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern void oggpackB_adv1(oggpack_buffer* b);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
[return: NativeTypeName("long")]
|
||||
public static extern CLong oggpackB_read(oggpack_buffer* b, int bits);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
[return: NativeTypeName("long")]
|
||||
public static extern CLong oggpackB_read1(oggpack_buffer* b);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
[return: NativeTypeName("long")]
|
||||
public static extern CLong oggpackB_bytes(oggpack_buffer* b);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
[return: NativeTypeName("long")]
|
||||
public static extern CLong oggpackB_bits(oggpack_buffer* b);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
[return: NativeTypeName("unsigned char *")]
|
||||
public static extern byte* oggpackB_get_buffer(oggpack_buffer* b);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int ogg_stream_packetin(ogg_stream_state* os, ogg_packet* op);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int ogg_stream_iovecin(ogg_stream_state* os, ogg_iovec_t* iov, int count, [NativeTypeName("long")] CLong e_o_s, [NativeTypeName("ogg_int64_t")] CLong granulepos);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int ogg_stream_pageout(ogg_stream_state* os, ogg_page* og);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int ogg_stream_pageout_fill(ogg_stream_state* os, ogg_page* og, int nfill);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int ogg_stream_flush(ogg_stream_state* os, ogg_page* og);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int ogg_stream_flush_fill(ogg_stream_state* os, ogg_page* og, int nfill);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int ogg_sync_init(ogg_sync_state* oy);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int ogg_sync_clear(ogg_sync_state* oy);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int ogg_sync_reset(ogg_sync_state* oy);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int ogg_sync_destroy(ogg_sync_state* oy);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int ogg_sync_check(ogg_sync_state* oy);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
[return: NativeTypeName("char *")]
|
||||
public static extern sbyte* ogg_sync_buffer(ogg_sync_state* oy, [NativeTypeName("long")] CLong size);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int ogg_sync_wrote(ogg_sync_state* oy, [NativeTypeName("long")] CLong bytes);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
[return: NativeTypeName("long")]
|
||||
public static extern CLong ogg_sync_pageseek(ogg_sync_state* oy, ogg_page* og);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int ogg_sync_pageout(ogg_sync_state* oy, ogg_page* og);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int ogg_stream_pagein(ogg_stream_state* os, ogg_page* og);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int ogg_stream_packetout(ogg_stream_state* os, ogg_packet* op);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int ogg_stream_packetpeek(ogg_stream_state* os, ogg_packet* op);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int ogg_stream_init(ogg_stream_state* os, int serialno);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int ogg_stream_clear(ogg_stream_state* os);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int ogg_stream_reset(ogg_stream_state* os);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int ogg_stream_reset_serialno(ogg_stream_state* os, int serialno);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int ogg_stream_destroy(ogg_stream_state* os);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int ogg_stream_check(ogg_stream_state* os);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int ogg_stream_eos(ogg_stream_state* os);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern void ogg_page_checksum_set(ogg_page* og);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int ogg_page_version([NativeTypeName("const ogg_page *")] ogg_page* og);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int ogg_page_continued([NativeTypeName("const ogg_page *")] ogg_page* og);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int ogg_page_bos([NativeTypeName("const ogg_page *")] ogg_page* og);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int ogg_page_eos([NativeTypeName("const ogg_page *")] ogg_page* og);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
[return: NativeTypeName("ogg_int64_t")]
|
||||
public static extern CLong ogg_page_granulepos([NativeTypeName("const ogg_page *")] ogg_page* og);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int ogg_page_serialno([NativeTypeName("const ogg_page *")] ogg_page* og);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
[return: NativeTypeName("long")]
|
||||
public static extern CLong ogg_page_pageno([NativeTypeName("const ogg_page *")] ogg_page* og);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int ogg_page_packets([NativeTypeName("const ogg_page *")] ogg_page* og);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern void ogg_packet_clear(ogg_packet* op);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Robust.Shared.Interop.RobustNative.Ogg;
|
||||
|
||||
internal unsafe partial struct ogg_iovec_t
|
||||
{
|
||||
public void* iov_base;
|
||||
|
||||
[NativeTypeName("size_t")]
|
||||
public nuint iov_len;
|
||||
}
|
||||
22
Robust.Shared.Interop.RobustNative/Ogg/Gen/ogg_packet.cs
Normal file
22
Robust.Shared.Interop.RobustNative/Ogg/Gen/ogg_packet.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
namespace Robust.Shared.Interop.RobustNative.Ogg;
|
||||
|
||||
internal unsafe partial struct ogg_packet
|
||||
{
|
||||
[NativeTypeName("unsigned char *")]
|
||||
public byte* packet;
|
||||
|
||||
[NativeTypeName("long")]
|
||||
public CLong bytes;
|
||||
|
||||
[NativeTypeName("long")]
|
||||
public CLong b_o_s;
|
||||
|
||||
[NativeTypeName("long")]
|
||||
public CLong e_o_s;
|
||||
|
||||
[NativeTypeName("ogg_int64_t")]
|
||||
public CLong granulepos;
|
||||
|
||||
[NativeTypeName("ogg_int64_t")]
|
||||
public CLong packetno;
|
||||
}
|
||||
16
Robust.Shared.Interop.RobustNative/Ogg/Gen/ogg_page.cs
Normal file
16
Robust.Shared.Interop.RobustNative/Ogg/Gen/ogg_page.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
namespace Robust.Shared.Interop.RobustNative.Ogg;
|
||||
|
||||
internal unsafe partial struct ogg_page
|
||||
{
|
||||
[NativeTypeName("unsigned char *")]
|
||||
public byte* header;
|
||||
|
||||
[NativeTypeName("long")]
|
||||
public CLong header_len;
|
||||
|
||||
[NativeTypeName("unsigned char *")]
|
||||
public byte* body;
|
||||
|
||||
[NativeTypeName("long")]
|
||||
public CLong body_len;
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
namespace Robust.Shared.Interop.RobustNative.Ogg;
|
||||
|
||||
internal unsafe partial struct ogg_stream_state
|
||||
{
|
||||
[NativeTypeName("unsigned char *")]
|
||||
public byte* body_data;
|
||||
|
||||
[NativeTypeName("long")]
|
||||
public CLong body_storage;
|
||||
|
||||
[NativeTypeName("long")]
|
||||
public CLong body_fill;
|
||||
|
||||
[NativeTypeName("long")]
|
||||
public CLong body_returned;
|
||||
|
||||
public int* lacing_vals;
|
||||
|
||||
[NativeTypeName("ogg_int64_t *")]
|
||||
public CLong* granule_vals;
|
||||
|
||||
[NativeTypeName("long")]
|
||||
public CLong lacing_storage;
|
||||
|
||||
[NativeTypeName("long")]
|
||||
public CLong lacing_fill;
|
||||
|
||||
[NativeTypeName("long")]
|
||||
public CLong lacing_packet;
|
||||
|
||||
[NativeTypeName("long")]
|
||||
public CLong lacing_returned;
|
||||
|
||||
[NativeTypeName("unsigned char[282]")]
|
||||
public fixed byte header[282];
|
||||
|
||||
public int header_fill;
|
||||
|
||||
public int e_o_s;
|
||||
|
||||
public int b_o_s;
|
||||
|
||||
[NativeTypeName("long")]
|
||||
public CLong serialno;
|
||||
|
||||
[NativeTypeName("long")]
|
||||
public CLong pageno;
|
||||
|
||||
[NativeTypeName("ogg_int64_t")]
|
||||
public CLong packetno;
|
||||
|
||||
[NativeTypeName("ogg_int64_t")]
|
||||
public CLong granulepos;
|
||||
}
|
||||
19
Robust.Shared.Interop.RobustNative/Ogg/Gen/ogg_sync_state.cs
Normal file
19
Robust.Shared.Interop.RobustNative/Ogg/Gen/ogg_sync_state.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
namespace Robust.Shared.Interop.RobustNative.Ogg;
|
||||
|
||||
internal unsafe partial struct ogg_sync_state
|
||||
{
|
||||
[NativeTypeName("unsigned char *")]
|
||||
public byte* data;
|
||||
|
||||
public int storage;
|
||||
|
||||
public int fill;
|
||||
|
||||
public int returned;
|
||||
|
||||
public int unsynced;
|
||||
|
||||
public int headerbytes;
|
||||
|
||||
public int bodybytes;
|
||||
}
|
||||
18
Robust.Shared.Interop.RobustNative/Ogg/Gen/oggpack_buffer.cs
Normal file
18
Robust.Shared.Interop.RobustNative/Ogg/Gen/oggpack_buffer.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
namespace Robust.Shared.Interop.RobustNative.Ogg;
|
||||
|
||||
internal unsafe partial struct oggpack_buffer
|
||||
{
|
||||
[NativeTypeName("long")]
|
||||
public CLong endbyte;
|
||||
|
||||
public int endbit;
|
||||
|
||||
[NativeTypeName("unsigned char *")]
|
||||
public byte* buffer;
|
||||
|
||||
[NativeTypeName("unsigned char *")]
|
||||
public byte* ptr;
|
||||
|
||||
[NativeTypeName("long")]
|
||||
public CLong storage;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Robust.Shared.Interop.RobustNative.Opus;
|
||||
|
||||
/// <summary>Defines the annotation found in a native declaration.</summary>
|
||||
[AttributeUsage(AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = true, Inherited = false)]
|
||||
[Conditional("DEBUG")]
|
||||
internal sealed partial class NativeAnnotationAttribute : Attribute
|
||||
{
|
||||
private readonly string _annotation;
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="NativeAnnotationAttribute" /> class.</summary>
|
||||
/// <param name="annotation">The annotation that was used in the native declaration.</param>
|
||||
public NativeAnnotationAttribute(string annotation)
|
||||
{
|
||||
_annotation = annotation;
|
||||
}
|
||||
|
||||
/// <summary>Gets the annotation that was used in the native declaration.</summary>
|
||||
public string Annotation => _annotation;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Robust.Shared.Interop.RobustNative.Opus;
|
||||
|
||||
/// <summary>Defines the type of a member as it was used in the native signature.</summary>
|
||||
[AttributeUsage(AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = false, Inherited = true)]
|
||||
[Conditional("DEBUG")]
|
||||
internal sealed partial class NativeTypeNameAttribute : Attribute
|
||||
{
|
||||
private readonly string _name;
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="NativeTypeNameAttribute" /> class.</summary>
|
||||
/// <param name="name">The name of the type that was used in the native signature.</param>
|
||||
public NativeTypeNameAttribute(string name)
|
||||
{
|
||||
_name = name;
|
||||
}
|
||||
|
||||
/// <summary>Gets the name of the type that was used in the native signature.</summary>
|
||||
public string Name => _name;
|
||||
}
|
||||
161
Robust.Shared.Interop.RobustNative/Opus/Gen/Opus.cs
Normal file
161
Robust.Shared.Interop.RobustNative/Opus/Gen/Opus.cs
Normal file
@@ -0,0 +1,161 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Robust.Shared.Interop.RobustNative.Opus;
|
||||
|
||||
internal static unsafe partial class Opus
|
||||
{
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
[return: NativeTypeName("const char *")]
|
||||
public static extern sbyte* opus_strerror(int error);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
[return: NativeTypeName("const char *")]
|
||||
public static extern sbyte* opus_get_version_string();
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int opus_encoder_get_size(int channels);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern OpusEncoder* opus_encoder_create([NativeTypeName("opus_int32")] int Fs, int channels, int application, int* error);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int opus_encoder_init(OpusEncoder* st, [NativeTypeName("opus_int32")] int Fs, int channels, int application);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
[return: NativeTypeName("opus_int32")]
|
||||
public static extern int opus_encode(OpusEncoder* st, [NativeTypeName("const opus_int16 *")] short* pcm, int frame_size, [NativeTypeName("unsigned char *")] byte* data, [NativeTypeName("opus_int32")] int max_data_bytes);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
[return: NativeTypeName("opus_int32")]
|
||||
public static extern int opus_encode_float(OpusEncoder* st, [NativeTypeName("const float *")] float* pcm, int frame_size, [NativeTypeName("unsigned char *")] byte* data, [NativeTypeName("opus_int32")] int max_data_bytes);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern void opus_encoder_destroy(OpusEncoder* st);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int opus_encoder_ctl(OpusEncoder* st, int request, __arglist);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int opus_decoder_get_size(int channels);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern OpusDecoder* opus_decoder_create([NativeTypeName("opus_int32")] int Fs, int channels, int* error);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int opus_decoder_init(OpusDecoder* st, [NativeTypeName("opus_int32")] int Fs, int channels);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int opus_decode(OpusDecoder* st, [NativeTypeName("const unsigned char *")] byte* data, [NativeTypeName("opus_int32")] int len, [NativeTypeName("opus_int16 *")] short* pcm, int frame_size, int decode_fec);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int opus_decode_float(OpusDecoder* st, [NativeTypeName("const unsigned char *")] byte* data, [NativeTypeName("opus_int32")] int len, float* pcm, int frame_size, int decode_fec);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int opus_decoder_ctl(OpusDecoder* st, int request, __arglist);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern void opus_decoder_destroy(OpusDecoder* st);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int opus_dred_decoder_get_size();
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern OpusDREDDecoder* opus_dred_decoder_create(int* error);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int opus_dred_decoder_init(OpusDREDDecoder* dec);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern void opus_dred_decoder_destroy(OpusDREDDecoder* dec);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int opus_dred_decoder_ctl(OpusDREDDecoder* dred_dec, int request, __arglist);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int opus_dred_get_size();
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern OpusDRED* opus_dred_alloc(int* error);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern void opus_dred_free(OpusDRED* dec);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int opus_dred_parse(OpusDREDDecoder* dred_dec, OpusDRED* dred, [NativeTypeName("const unsigned char *")] byte* data, [NativeTypeName("opus_int32")] int len, [NativeTypeName("opus_int32")] int max_dred_samples, [NativeTypeName("opus_int32")] int sampling_rate, int* dred_end, int defer_processing);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int opus_dred_process(OpusDREDDecoder* dred_dec, [NativeTypeName("const OpusDRED *")] OpusDRED* src, OpusDRED* dst);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int opus_decoder_dred_decode(OpusDecoder* st, [NativeTypeName("const OpusDRED *")] OpusDRED* dred, [NativeTypeName("opus_int32")] int dred_offset, [NativeTypeName("opus_int16 *")] short* pcm, [NativeTypeName("opus_int32")] int frame_size);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int opus_decoder_dred_decode_float(OpusDecoder* st, [NativeTypeName("const OpusDRED *")] OpusDRED* dred, [NativeTypeName("opus_int32")] int dred_offset, float* pcm, [NativeTypeName("opus_int32")] int frame_size);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int opus_packet_parse([NativeTypeName("const unsigned char *")] byte* data, [NativeTypeName("opus_int32")] int len, [NativeTypeName("unsigned char *")] byte* out_toc, [NativeTypeName("const unsigned char *[48]")] byte** frames, [NativeTypeName("opus_int16[48]")] short* size, int* payload_offset);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int opus_packet_get_bandwidth([NativeTypeName("const unsigned char *")] byte* data);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int opus_packet_get_samples_per_frame([NativeTypeName("const unsigned char *")] byte* data, [NativeTypeName("opus_int32")] int Fs);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int opus_packet_get_nb_channels([NativeTypeName("const unsigned char *")] byte* data);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int opus_packet_get_nb_frames([NativeTypeName("const unsigned char[]")] byte* packet, [NativeTypeName("opus_int32")] int len);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int opus_packet_get_nb_samples([NativeTypeName("const unsigned char[]")] byte* packet, [NativeTypeName("opus_int32")] int len, [NativeTypeName("opus_int32")] int Fs);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int opus_packet_has_lbrr([NativeTypeName("const unsigned char[]")] byte* packet, [NativeTypeName("opus_int32")] int len);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int opus_decoder_get_nb_samples([NativeTypeName("const OpusDecoder *")] OpusDecoder* dec, [NativeTypeName("const unsigned char[]")] byte* packet, [NativeTypeName("opus_int32")] int len);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern void opus_pcm_soft_clip(float* pcm, int frame_size, int channels, float* softclip_mem);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int opus_repacketizer_get_size();
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern OpusRepacketizer* opus_repacketizer_init(OpusRepacketizer* rp);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern OpusRepacketizer* opus_repacketizer_create();
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern void opus_repacketizer_destroy(OpusRepacketizer* rp);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int opus_repacketizer_cat(OpusRepacketizer* rp, [NativeTypeName("const unsigned char *")] byte* data, [NativeTypeName("opus_int32")] int len);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
[return: NativeTypeName("opus_int32")]
|
||||
public static extern int opus_repacketizer_out_range(OpusRepacketizer* rp, int begin, int end, [NativeTypeName("unsigned char *")] byte* data, [NativeTypeName("opus_int32")] int maxlen);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int opus_repacketizer_get_nb_frames(OpusRepacketizer* rp);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
[return: NativeTypeName("opus_int32")]
|
||||
public static extern int opus_repacketizer_out(OpusRepacketizer* rp, [NativeTypeName("unsigned char *")] byte* data, [NativeTypeName("opus_int32")] int maxlen);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int opus_packet_pad([NativeTypeName("unsigned char *")] byte* data, [NativeTypeName("opus_int32")] int len, [NativeTypeName("opus_int32")] int new_len);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
[return: NativeTypeName("opus_int32")]
|
||||
public static extern int opus_packet_unpad([NativeTypeName("unsigned char *")] byte* data, [NativeTypeName("opus_int32")] int len);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int opus_multistream_packet_pad([NativeTypeName("unsigned char *")] byte* data, [NativeTypeName("opus_int32")] int len, [NativeTypeName("opus_int32")] int new_len, int nb_streams);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
[return: NativeTypeName("opus_int32")]
|
||||
public static extern int opus_multistream_packet_unpad([NativeTypeName("unsigned char *")] byte* data, [NativeTypeName("opus_int32")] int len, int nb_streams);
|
||||
}
|
||||
5
Robust.Shared.Interop.RobustNative/Opus/Gen/OpusDRED.cs
Normal file
5
Robust.Shared.Interop.RobustNative/Opus/Gen/OpusDRED.cs
Normal file
@@ -0,0 +1,5 @@
|
||||
namespace Robust.Shared.Interop.RobustNative.Opus;
|
||||
|
||||
internal partial struct OpusDRED
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
namespace Robust.Shared.Interop.RobustNative.Opus;
|
||||
|
||||
internal partial struct OpusDREDDecoder
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
namespace Robust.Shared.Interop.RobustNative.Opus;
|
||||
|
||||
internal partial struct OpusDecoder
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
namespace Robust.Shared.Interop.RobustNative.Opus;
|
||||
|
||||
internal partial struct OpusEncoder
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
namespace Robust.Shared.Interop.RobustNative.Opus;
|
||||
|
||||
internal partial struct OpusRepacketizer
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="..\MSBuild\Robust.Engine.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="JetBrains.Annotations" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="..\MSBuild\Robust.Properties.targets" />
|
||||
</Project>
|
||||
95
Robust.Shared.Interop.RobustNative/RobustNativeDll.cs
Normal file
95
Robust.Shared.Interop.RobustNative/RobustNativeDll.cs
Normal file
@@ -0,0 +1,95 @@
|
||||
namespace Robust.Shared.Interop.RobustNative;
|
||||
|
||||
internal static class RobustNativeDll
|
||||
{
|
||||
private const string DllName = "robust-native";
|
||||
|
||||
private static readonly Lock LoadLock = new();
|
||||
|
||||
public static bool IsClientProcess;
|
||||
public static bool IsServerProcess;
|
||||
|
||||
private static nint _robustNativeHandle;
|
||||
private static Exception? _loadFailed;
|
||||
|
||||
static RobustNativeDll()
|
||||
{
|
||||
NativeLibrary.SetDllImportResolver(typeof(RobustNativeDll).Assembly,
|
||||
(name, _, _) =>
|
||||
{
|
||||
if (name == DllName)
|
||||
return LoadRobustNative();
|
||||
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
|
||||
public static nint LoadRobustNative()
|
||||
{
|
||||
using var _ = LoadLock.EnterScope();
|
||||
|
||||
if (_robustNativeHandle != 0)
|
||||
return _robustNativeHandle;
|
||||
|
||||
if (_loadFailed != null)
|
||||
throw _loadFailed;
|
||||
|
||||
try
|
||||
{
|
||||
_robustNativeHandle = LoadCore();
|
||||
return _robustNativeHandle;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_loadFailed = e;
|
||||
throw _loadFailed;
|
||||
}
|
||||
}
|
||||
|
||||
private static nint LoadCore()
|
||||
{
|
||||
var dllName = GetDllName();
|
||||
#if WINDOWS
|
||||
return NativeLibrary.Load(dllName, typeof(RobustNativeDll).Assembly, DllImportSearchPath.SafeDirectories);
|
||||
#elif UNIX
|
||||
#if MACOS
|
||||
dllName = $"lib{dllName}.dylib";
|
||||
#else
|
||||
dllName = $"lib{dllName}.so";
|
||||
#endif
|
||||
// On Unix platforms we *need* to load the native lib with RTLD_DEEPBIND | RTLD_LOCAL
|
||||
// To avoid issues with symbol collisions.
|
||||
var searchDirectories = (string?)AppContext.GetData("NATIVE_DLL_SEARCH_DIRECTORIES");
|
||||
|
||||
foreach (var dir in searchDirectories?.Split(':') ?? Array.Empty<string>()) {
|
||||
var libraryPath = Path.Combine(dir, dllName);
|
||||
|
||||
var attempt = Libc.dlopen(libraryPath, Libc.RTLD_LAZY | Libc.RTLD_DEEPBIND | Libc.RTLD_LOCAL);
|
||||
if (attempt != 0)
|
||||
return attempt;
|
||||
}
|
||||
|
||||
throw new DllNotFoundException($"Unable to locatee {dllName}");
|
||||
#endif
|
||||
}
|
||||
|
||||
private static string GetDllName()
|
||||
{
|
||||
#if DEVELOPMENT
|
||||
// Always load universal on dev builds to avoid issues with test processes.
|
||||
return "robust_native_universal";
|
||||
#else
|
||||
if (IsClientProcess && IsServerProcess)
|
||||
return "robust_native_universal";
|
||||
|
||||
if (IsClientProcess)
|
||||
return "robust_native_client";
|
||||
|
||||
if (IsServerProcess)
|
||||
return "robust_native_server";
|
||||
|
||||
throw new InvalidOperationException("Is neither server or client process???");
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Robust.Shared.Interop.RobustNative.Vorbis;
|
||||
|
||||
/// <summary>Defines the annotation found in a native declaration.</summary>
|
||||
[AttributeUsage(AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = true, Inherited = false)]
|
||||
[Conditional("DEBUG")]
|
||||
internal sealed partial class NativeAnnotationAttribute : Attribute
|
||||
{
|
||||
private readonly string _annotation;
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="NativeAnnotationAttribute" /> class.</summary>
|
||||
/// <param name="annotation">The annotation that was used in the native declaration.</param>
|
||||
public NativeAnnotationAttribute(string annotation)
|
||||
{
|
||||
_annotation = annotation;
|
||||
}
|
||||
|
||||
/// <summary>Gets the annotation that was used in the native declaration.</summary>
|
||||
public string Annotation => _annotation;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Robust.Shared.Interop.RobustNative.Vorbis;
|
||||
|
||||
/// <summary>Defines the type of a member as it was used in the native signature.</summary>
|
||||
[AttributeUsage(AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = false, Inherited = true)]
|
||||
[Conditional("DEBUG")]
|
||||
internal sealed partial class NativeTypeNameAttribute : Attribute
|
||||
{
|
||||
private readonly string _name;
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="NativeTypeNameAttribute" /> class.</summary>
|
||||
/// <param name="name">The name of the type that was used in the native signature.</param>
|
||||
public NativeTypeNameAttribute(string name)
|
||||
{
|
||||
_name = name;
|
||||
}
|
||||
|
||||
/// <summary>Gets the name of the type that was used in the native signature.</summary>
|
||||
public string Name => _name;
|
||||
}
|
||||
117
Robust.Shared.Interop.RobustNative/Vorbis/Gen/Vorbis.cs
Normal file
117
Robust.Shared.Interop.RobustNative/Vorbis/Gen/Vorbis.cs
Normal file
@@ -0,0 +1,117 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Robust.Shared.Interop.RobustNative.Vorbis;
|
||||
|
||||
internal static unsafe partial class Vorbis
|
||||
{
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern void vorbis_info_init(vorbis_info* vi);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern void vorbis_info_clear(vorbis_info* vi);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int vorbis_info_blocksize(vorbis_info* vi, int zo);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern void vorbis_comment_init(vorbis_comment* vc);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern void vorbis_comment_add(vorbis_comment* vc, [NativeTypeName("const char *")] sbyte* comment);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern void vorbis_comment_add_tag(vorbis_comment* vc, [NativeTypeName("const char *")] sbyte* tag, [NativeTypeName("const char *")] sbyte* contents);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
[return: NativeTypeName("char *")]
|
||||
public static extern sbyte* vorbis_comment_query(vorbis_comment* vc, [NativeTypeName("const char *")] sbyte* tag, int count);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int vorbis_comment_query_count(vorbis_comment* vc, [NativeTypeName("const char *")] sbyte* tag);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern void vorbis_comment_clear(vorbis_comment* vc);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int vorbis_block_init(vorbis_dsp_state* v, vorbis_block* vb);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int vorbis_block_clear(vorbis_block* vb);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern void vorbis_dsp_clear(vorbis_dsp_state* v);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern double vorbis_granule_time(vorbis_dsp_state* v, [NativeTypeName("ogg_int64_t")] CLong granulepos);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
[return: NativeTypeName("const char *")]
|
||||
public static extern sbyte* vorbis_version_string();
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int vorbis_analysis_init(vorbis_dsp_state* v, vorbis_info* vi);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int vorbis_commentheader_out(vorbis_comment* vc, ogg_packet* op);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int vorbis_analysis_headerout(vorbis_dsp_state* v, vorbis_comment* vc, ogg_packet* op, ogg_packet* op_comm, ogg_packet* op_code);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern float** vorbis_analysis_buffer(vorbis_dsp_state* v, int vals);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int vorbis_analysis_wrote(vorbis_dsp_state* v, int vals);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int vorbis_analysis_blockout(vorbis_dsp_state* v, vorbis_block* vb);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int vorbis_analysis(vorbis_block* vb, ogg_packet* op);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int vorbis_bitrate_addblock(vorbis_block* vb);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int vorbis_bitrate_flushpacket(vorbis_dsp_state* vd, ogg_packet* op);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int vorbis_synthesis_idheader(ogg_packet* op);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int vorbis_synthesis_headerin(vorbis_info* vi, vorbis_comment* vc, ogg_packet* op);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int vorbis_synthesis_init(vorbis_dsp_state* v, vorbis_info* vi);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int vorbis_synthesis_restart(vorbis_dsp_state* v);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int vorbis_synthesis(vorbis_block* vb, ogg_packet* op);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int vorbis_synthesis_trackonly(vorbis_block* vb, ogg_packet* op);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int vorbis_synthesis_blockin(vorbis_dsp_state* v, vorbis_block* vb);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int vorbis_synthesis_pcmout(vorbis_dsp_state* v, float*** pcm);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int vorbis_synthesis_lapout(vorbis_dsp_state* v, float*** pcm);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int vorbis_synthesis_read(vorbis_dsp_state* v, int samples);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
[return: NativeTypeName("long")]
|
||||
public static extern CLong vorbis_packet_blocksize(vorbis_info* vi, ogg_packet* op);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int vorbis_synthesis_halfrate(vorbis_info* v, int flag);
|
||||
|
||||
[DllImport("robust-native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
public static extern int vorbis_synthesis_halfrate_p(vorbis_info* v);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Robust.Shared.Interop.RobustNative.Vorbis;
|
||||
|
||||
internal unsafe partial struct alloc_chain
|
||||
{
|
||||
public void* ptr;
|
||||
|
||||
[NativeTypeName("struct alloc_chain *")]
|
||||
public alloc_chain* next;
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
namespace Robust.Shared.Interop.RobustNative.Vorbis;
|
||||
|
||||
internal unsafe partial struct vorbis_block
|
||||
{
|
||||
public float** pcm;
|
||||
|
||||
public oggpack_buffer opb;
|
||||
|
||||
[NativeTypeName("long")]
|
||||
public CLong lW;
|
||||
|
||||
[NativeTypeName("long")]
|
||||
public CLong W;
|
||||
|
||||
[NativeTypeName("long")]
|
||||
public CLong nW;
|
||||
|
||||
public int pcmend;
|
||||
|
||||
public int mode;
|
||||
|
||||
public int eofflag;
|
||||
|
||||
[NativeTypeName("ogg_int64_t")]
|
||||
public CLong granulepos;
|
||||
|
||||
[NativeTypeName("ogg_int64_t")]
|
||||
public CLong sequence;
|
||||
|
||||
public vorbis_dsp_state* vd;
|
||||
|
||||
public void* localstore;
|
||||
|
||||
[NativeTypeName("long")]
|
||||
public CLong localtop;
|
||||
|
||||
[NativeTypeName("long")]
|
||||
public CLong localalloc;
|
||||
|
||||
[NativeTypeName("long")]
|
||||
public CLong totaluse;
|
||||
|
||||
[NativeTypeName("struct alloc_chain *")]
|
||||
public alloc_chain* reap;
|
||||
|
||||
[NativeTypeName("long")]
|
||||
public CLong glue_bits;
|
||||
|
||||
[NativeTypeName("long")]
|
||||
public CLong time_bits;
|
||||
|
||||
[NativeTypeName("long")]
|
||||
public CLong floor_bits;
|
||||
|
||||
[NativeTypeName("long")]
|
||||
public CLong res_bits;
|
||||
|
||||
public void* @internal;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace Robust.Shared.Interop.RobustNative.Vorbis;
|
||||
|
||||
internal unsafe partial struct vorbis_comment
|
||||
{
|
||||
[NativeTypeName("char **")]
|
||||
public sbyte** user_comments;
|
||||
|
||||
public int* comment_lengths;
|
||||
|
||||
public int comments;
|
||||
|
||||
[NativeTypeName("char *")]
|
||||
public sbyte* vendor;
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
namespace Robust.Shared.Interop.RobustNative.Vorbis;
|
||||
|
||||
internal unsafe partial struct vorbis_dsp_state
|
||||
{
|
||||
public int analysisp;
|
||||
|
||||
public vorbis_info* vi;
|
||||
|
||||
public float** pcm;
|
||||
|
||||
public float** pcmret;
|
||||
|
||||
public int pcm_storage;
|
||||
|
||||
public int pcm_current;
|
||||
|
||||
public int pcm_returned;
|
||||
|
||||
public int preextrapolate;
|
||||
|
||||
public int eofflag;
|
||||
|
||||
[NativeTypeName("long")]
|
||||
public CLong lW;
|
||||
|
||||
[NativeTypeName("long")]
|
||||
public CLong W;
|
||||
|
||||
[NativeTypeName("long")]
|
||||
public CLong nW;
|
||||
|
||||
[NativeTypeName("long")]
|
||||
public CLong centerW;
|
||||
|
||||
[NativeTypeName("ogg_int64_t")]
|
||||
public CLong granulepos;
|
||||
|
||||
[NativeTypeName("ogg_int64_t")]
|
||||
public CLong sequence;
|
||||
|
||||
[NativeTypeName("ogg_int64_t")]
|
||||
public CLong glue_bits;
|
||||
|
||||
[NativeTypeName("ogg_int64_t")]
|
||||
public CLong time_bits;
|
||||
|
||||
[NativeTypeName("ogg_int64_t")]
|
||||
public CLong floor_bits;
|
||||
|
||||
[NativeTypeName("ogg_int64_t")]
|
||||
public CLong res_bits;
|
||||
|
||||
public void* backend_state;
|
||||
}
|
||||
25
Robust.Shared.Interop.RobustNative/Vorbis/Gen/vorbis_info.cs
Normal file
25
Robust.Shared.Interop.RobustNative/Vorbis/Gen/vorbis_info.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
namespace Robust.Shared.Interop.RobustNative.Vorbis;
|
||||
|
||||
internal unsafe partial struct vorbis_info
|
||||
{
|
||||
public int version;
|
||||
|
||||
public int channels;
|
||||
|
||||
[NativeTypeName("long")]
|
||||
public CLong rate;
|
||||
|
||||
[NativeTypeName("long")]
|
||||
public CLong bitrate_upper;
|
||||
|
||||
[NativeTypeName("long")]
|
||||
public CLong bitrate_nominal;
|
||||
|
||||
[NativeTypeName("long")]
|
||||
public CLong bitrate_lower;
|
||||
|
||||
[NativeTypeName("long")]
|
||||
public CLong bitrate_window;
|
||||
|
||||
public void* codec_setup;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user