Various performance optimizations.

This commit is contained in:
Pieter-Jan Briers
2019-08-01 00:10:20 +02:00
parent fa10e1c330
commit 85a4375905
31 changed files with 197 additions and 133 deletions

View File

@@ -87,7 +87,6 @@ namespace Robust.Client
IoCManager.Register<IClydeInternal, ClydeHeadless>();
IoCManager.Register<IInputManager, InputManager>();
IoCManager.Register<IFileDialogManager, DummyFileDialogManager>();
IoCManager.Register<IFileDialogManagerInternal, DummyFileDialogManager>();
IoCManager.Register<IUriOpener, UriOpenerDummy>();
break;
case GameController.DisplayMode.Clyde:
@@ -96,7 +95,6 @@ namespace Robust.Client
IoCManager.Register<IClydeInternal, Clyde>();
IoCManager.Register<IInputManager, ClydeInputManager>();
IoCManager.Register<IFileDialogManager, FileDialogManager>();
IoCManager.Register<IFileDialogManagerInternal, FileDialogManager>();
#if LINUX
IoCManager.Register<IUriOpener, UriOpenerLinux>();
#elif MACOS
@@ -119,10 +117,13 @@ namespace Robust.Client
#if LINUX
IoCManager.Register<IClipboardManager, ClipboardManagerLinux>();
IoCManager.Register<IClipboardManagerInternal, ClipboardManagerLinux>();
#elif WINDOWS
IoCManager.Register<IClipboardManager, ClipboardManagerWindows>();
IoCManager.Register<IClipboardManagerInternal, ClipboardManagerWindows>();
#else
IoCManager.Register<IClipboardManager, ClipboardManagerUnsupported>();
IoCManager.Register<IClipboardManagerInternal, ClipboardManagerUnsupported>();
#endif
IoCManager.Register<ISignalHandler, ClientSignalHandler>();

View File

@@ -42,6 +42,7 @@ namespace Robust.Client
{
#pragma warning disable 649
[Dependency] private readonly IConfigurationManager _configurationManager;
[Dependency] private readonly IClipboardManagerInternal _clipboardManager;
[Dependency] private readonly IResourceCacheInternal _resourceCache;
[Dependency] private readonly IResourceManager _resourceManager;
[Dependency] private readonly IRobustSerializer _serializer;
@@ -68,7 +69,6 @@ namespace Robust.Client
[Dependency] private readonly ILocalizationManager _localizationManager;
[Dependency] private readonly IModLoader _modLoader;
[Dependency] private readonly ISignalHandler _signalHandler;
[Dependency] private readonly IFileDialogManagerInternal _fileDialogManager;
#pragma warning restore 649
public string ContentRootDir { get; set; } = "../../../";
@@ -122,6 +122,7 @@ namespace Robust.Client
_clyde.SetWindowTitle("Space Station 14");
_fontManager.Initialize();
_clipboardManager.Initialize();
//identical code for server in baseserver
if (!_modLoader.TryLoadAssembly<GameShared>(_resourceManager, $"Content.Shared"))
@@ -139,7 +140,6 @@ namespace Robust.Client
// Call Init in game assemblies.
_modLoader.BroadcastRunLevel(ModRunLevel.Init);
_fileDialogManager.Initialize();
_eyeManager.Initialize();
_serializer.Initialize();
_userInterfaceManager.Initialize();

View File

@@ -1,16 +1,17 @@
using System;
using System.Collections.Generic;
using System.IO;
using JetBrains.Annotations;
using SharpFont;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using SixLabors.Primitives;
using Robust.Client.Interfaces.Graphics;
using Robust.Shared.Interfaces.Configuration;
using Robust.Shared.IoC;
using Robust.Shared.Maths;
using Robust.Shared.Utility;
using SharpFont;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using SixLabors.Primitives;
namespace Robust.Client.Graphics
{
@@ -32,9 +33,9 @@ namespace Robust.Client.Graphics
_library = new Library();
}
public IFontFaceHandle Load(ReadOnlySpan<byte> data)
public IFontFaceHandle Load(Stream stream)
{
var face = new Face(_library, data.ToArray(), 0);
var face = new Face(_library, stream.CopyToArray(), 0);
var handle = new FontFaceHandle(face);
return handle;
}

View File

@@ -1,4 +1,4 @@
using System;
using System.IO;
using Robust.Client.Graphics;
namespace Robust.Client.Interfaces.Graphics
@@ -10,7 +10,7 @@ namespace Robust.Client.Interfaces.Graphics
internal interface IFontManagerInternal : IFontManager
{
IFontFaceHandle Load(ReadOnlySpan<byte> data);
IFontFaceHandle Load(Stream stream);
IFontInstanceHandle MakeInstance(IFontFaceHandle handle, int size);
void Initialize();
}

View File

@@ -8,4 +8,9 @@ namespace Robust.Client.Interfaces.UserInterface
string GetText();
void SetText(string text);
}
internal interface IClipboardManagerInternal : IClipboardManager
{
void Initialize();
}
}

View File

@@ -29,9 +29,4 @@ namespace Robust.Client.Interfaces.UserInterface
/// <returns>The path the user selected to open. Null if the user cancelled the action.</returns>
Task<string> OpenFolder();
}
internal interface IFileDialogManagerInternal : IFileDialogManager
{
void Initialize();
}
}

View File

@@ -1,20 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using SixLabors.Primitives;
using Robust.Client.Graphics;
using Robust.Client.Graphics.ClientEye;
using Robust.Client.Interfaces.Map;
using Robust.Client.Interfaces.ResourceManagement;
using Robust.Shared.GameObjects.Components.Renderable;
using Robust.Client.Utility;
using Robust.Shared.IoC;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Utility;
using Image = SixLabors.ImageSharp.Image;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
namespace Robust.Client.Map
{
@@ -72,10 +68,9 @@ namespace Robust.Client.Map
throw new NotImplementedException("Unable to use tiles with a dimension other than 32x32.");
}
var point = new Point(column * tileSize, row * tileSize);
var point = new Vector2i(column * tileSize, row * tileSize);
sheet.Mutate(x => x.DrawImage(image, point,
PixelColorBlendingMode.Overlay, 1));
image.Blit(new UIBox2i(0, 0, image.Width, image.Height), sheet, point);
_tileRegions.Add(def.TileId,
UIBox2.FromDimensions(

View File

@@ -1,9 +1,9 @@
using Robust.Client.Interfaces.ResourceManagement;
using System.IO;
using Robust.Shared.Utility;
using System.IO;
using Robust.Client.Graphics;
using Robust.Client.Interfaces.Graphics;
using Robust.Client.Interfaces.ResourceManagement;
using Robust.Shared.IoC;
using Robust.Shared.Utility;
namespace Robust.Client.ResourceManagement
{
@@ -18,7 +18,7 @@ namespace Robust.Client.ResourceManagement
throw new FileNotFoundException("Content file does not exist for font");
}
FontFaceHandle = IoCManager.Resolve<IFontManagerInternal>().Load(cache.ContentFileRead(path).ToArray());
FontFaceHandle = IoCManager.Resolve<IFontManagerInternal>().Load(cache.ContentFileRead(path));
}
public VectorFont MakeDefault()

View File

@@ -1,10 +1,10 @@
using Robust.Client.Graphics;
using System.IO;
using Robust.Client.Graphics;
using Robust.Client.Interfaces.Graphics;
using Robust.Client.Interfaces.ResourceManagement;
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Utility;
using System.IO;
using Robust.Client.Interfaces.Graphics;
using Robust.Shared.IoC;
using YamlDotNet.RepresentationModel;
namespace Robust.Client.ResourceManagement
@@ -16,7 +16,7 @@ namespace Robust.Client.ResourceManagement
public override void Load(IResourceCache cache, ResourcePath path)
{
if (!cache.ContentFileExists(path))
if (!cache.TryContentFileRead(path, out var stream))
{
throw new FileNotFoundException("Content file does not exist for texture");
}
@@ -26,7 +26,7 @@ namespace Robust.Client.ResourceManagement
var loadParameters = _tryLoadTextureParameters(cache, path) ?? TextureLoadParameters.Default;
_loadOpenGL(cache, path, loadParameters);
_loadOpenGL(cache, stream, path, loadParameters);
}
private static TextureLoadParameters? _tryLoadTextureParameters(IResourceCache cache, ResourcePath path)
@@ -52,11 +52,11 @@ namespace Robust.Client.ResourceManagement
return null;
}
private void _loadOpenGL(IResourceCache cache, ResourcePath path, TextureLoadParameters? parameters)
private void _loadOpenGL(IResourceCache cache, Stream stream, ResourcePath path, TextureLoadParameters? parameters)
{
var manager = IoCManager.Resolve<IClyde>();
Texture = manager.LoadTextureFromPNGStream(cache.ContentFileRead(path), path.ToString(), parameters);
Texture = manager.LoadTextureFromPNGStream(stream, path.ToString(), parameters);
}
public static implicit operator Texture(TextureResource res)

View File

@@ -1,14 +1,13 @@
using System;
using System.Diagnostics;
using System.Text;
using Robust.Client.Interfaces.UserInterface;
using Robust.Shared.Utility;
namespace Robust.Client.UserInterface
{
internal sealed class ClipboardManagerLinux : IClipboardManager
internal sealed class ClipboardManagerLinux : IClipboardManagerInternal
{
public bool Available { get; }
public bool Available { get; private set; }
public string NotAvailableReason =>
// ReSharper disable once StringLiteralTypo
@@ -58,7 +57,7 @@ namespace Robust.Client.UserInterface
process.WaitForExit();
}
public ClipboardManagerLinux()
public async void Initialize()
{
try
{
@@ -71,13 +70,14 @@ namespace Robust.Client.UserInterface
RedirectStandardError = true,
UseShellExecute = false
});
if (process == null)
{
Available = false;
return;
}
process.WaitForExit();
await process.WaitForExitAsync();
Available = process.ExitCode == 0;
}
catch (Exception)

View File

@@ -3,7 +3,7 @@ using Robust.Client.Interfaces.UserInterface;
namespace Robust.Client.UserInterface
{
internal sealed class ClipboardManagerUnsupported : IClipboardManager
internal sealed class ClipboardManagerUnsupported : IClipboardManagerInternal
{
public bool Available => false;
public string NotAvailableReason => "Sorry, the clipboard is not supported on your platform.";
@@ -17,5 +17,10 @@ namespace Robust.Client.UserInterface
{
throw new NotSupportedException();
}
public void Initialize()
{
// Nothing.
}
}
}

View File

@@ -8,7 +8,7 @@ using Robust.Shared.IoC;
namespace Robust.Client.UserInterface
{
// Yay Windows API!
sealed class ClipboardManagerWindows : IClipboardManager
sealed class ClipboardManagerWindows : IClipboardManagerInternal
{
[Dependency]
#pragma warning disable 649
@@ -166,6 +166,11 @@ namespace Robust.Client.UserInterface
}
}
public void Initialize()
{
// Nothing.
}
private const uint CF_UNICODETEXT = 13;
private const uint CF_TEXT = 1;
private const uint GMEM_MOVEABLE = 2;

View File

@@ -7,7 +7,6 @@ using Robust.Client.Graphics.Drawing;
using Robust.Client.Input;
using Robust.Client.Interfaces.Console;
using Robust.Client.UserInterface.Controls;
using Robust.Client.Utility;
using Robust.Shared.Interfaces.Resources;
using Robust.Shared.Maths;
using Robust.Shared.Utility;
@@ -219,7 +218,7 @@ namespace Robust.Client.UserInterface.CustomControls
}
}
private void _loadHistoryFromDisk()
private async void _loadHistoryFromDisk()
{
CommandHistory.Clear();
Stream stream;
@@ -237,7 +236,7 @@ namespace Robust.Client.UserInterface.CustomControls
{
using (var reader = new StreamReader(stream, EncodingHelpers.UTF8))
{
var data = JsonConvert.DeserializeObject<List<string>>(reader.ReadToEnd());
var data = JsonConvert.DeserializeObject<List<string>>(await reader.ReadToEndAsync());
CommandHistory.Clear();
CommandHistory.AddRange(data);
_historyPosition = CommandHistory.Count;

View File

@@ -6,7 +6,7 @@ namespace Robust.Client.UserInterface
/// <summary>
/// Treats ever file dialog operation as cancelled.
/// </summary>
internal sealed class DummyFileDialogManager : IFileDialogManagerInternal
internal sealed class DummyFileDialogManager : IFileDialogManager
{
public Task<string> OpenFile()
{
@@ -22,10 +22,5 @@ namespace Robust.Client.UserInterface
{
return Task.FromResult<string>(null);
}
public void Initialize()
{
// Nothing.
}
}
}

View File

@@ -16,7 +16,7 @@ namespace Robust.Client.UserInterface
[SuppressMessage("ReSharper", "IdentifierTypo")]
[SuppressMessage("ReSharper", "CommentTypo")]
[SuppressMessage("ReSharper", "StringLiteralTypo")]
internal sealed class FileDialogManager : IFileDialogManagerInternal
internal sealed class FileDialogManager : IFileDialogManager
{
// Uses nativefiledialog to open the file dialogs cross platform.
// On Linux, if the kdialog command is found, it will be used instead.
@@ -28,46 +28,40 @@ namespace Robust.Client.UserInterface
#if LINUX
private bool _kDialogAvailable;
private bool _checkedKDialogAvailable;
#endif
public Task<string> OpenFile()
public async Task<string> OpenFile()
{
#if LINUX
if (_kDialogAvailable)
if (await IsKDialogAvailable())
{
return OpenFileKDialog();
return await OpenFileKDialog();
}
#endif
return OpenFileNfd();
return await OpenFileNfd();
}
public Task<string> SaveFile()
public async Task<string> SaveFile()
{
#if LINUX
if (_kDialogAvailable)
if (await IsKDialogAvailable())
{
return SaveFileKDialog();
return await SaveFileKDialog();
}
#endif
return SaveFileNfd();
return await SaveFileNfd();
}
public Task<string> OpenFolder()
public async Task<string> OpenFolder()
{
#if LINUX
if (_kDialogAvailable)
if (await IsKDialogAvailable())
{
return OpenFolderKDialog();
return await OpenFolderKDialog();
}
#endif
return OpenFolderNfd();
}
public void Initialize()
{
#if LINUX
CheckKDialogSupport();
#endif
return await OpenFolderNfd();
}
private unsafe Task<string> OpenFileNfd()
@@ -150,7 +144,7 @@ namespace Robust.Client.UserInterface
}
#if LINUX
private void CheckKDialogSupport()
private async Task CheckKDialogSupport()
{
try
{
@@ -170,7 +164,7 @@ namespace Robust.Client.UserInterface
return;
}
process.WaitForExit();
await process.WaitForExitAsync();
_kDialogAvailable = process.ExitCode == 0;
if (_kDialogAvailable)
@@ -223,6 +217,17 @@ namespace Robust.Client.UserInterface
return (await process.StandardOutput.ReadLineAsync()).Trim();
}
private async Task<bool> IsKDialogAvailable()
{
if (!_checkedKDialogAvailable)
{
await CheckKDialogSupport();
_checkedKDialogAvailable = true;
}
return _kDialogAvailable;
}
#endif
[DllImport("swnfd.dll")]

View File

@@ -21,15 +21,15 @@ using FrameEventArgs = Robust.Client.FrameEventArgs;
namespace Robust.Lite
{
internal class LiteGameController : IGameController, IGameControllerInternal
internal class LiteGameController : IGameControllerInternal
{
private IGameLoop _mainLoop;
#pragma warning disable 649
[Dependency] private readonly IClipboardManagerInternal _clipboardManager;
[Dependency] private readonly IClydeInternal _clyde;
[Dependency] private readonly IConfigurationManager _configurationManager;
[Dependency] private readonly IEyeManager _eyeManager;
[Dependency] private readonly IFileDialogManagerInternal _fileDialogManager;
[Dependency] private readonly IFontManagerInternal _fontManager;
[Dependency] private readonly IGameTiming _gameTiming;
[Dependency] private readonly ILocalizationManager _localizationManager;
@@ -91,8 +91,7 @@ namespace Robust.Lite
}
_fontManager.Initialize();
_fileDialogManager.Initialize();
_clipboardManager.Initialize();
_eyeManager.Initialize();

View File

@@ -1,7 +1,6 @@
using Robust.Shared.Log;
using Robust.Shared.Utility;
using System.Collections.Generic;
using System.Collections.Generic;
using System.IO;
using Robust.Shared.Utility;
namespace Robust.Shared.ContentPack
{
@@ -31,7 +30,7 @@ namespace Robust.Shared.ContentPack
}
/// <inheritdoc />
public bool TryGetFile(ResourcePath relPath, out MemoryStream stream)
public bool TryGetFile(ResourcePath relPath, out Stream stream)
{
var path = GetPath(relPath);
if (!File.Exists(path))
@@ -40,8 +39,7 @@ namespace Robust.Shared.ContentPack
return false;
}
var bytes = File.ReadAllBytes(path);
stream = new MemoryStream(bytes, false);
stream = File.OpenRead(path);
return true;
}

View File

@@ -1,6 +1,6 @@
using Robust.Shared.Utility;
using System.Collections.Generic;
using System.Collections.Generic;
using System.IO;
using Robust.Shared.Utility;
namespace Robust.Shared.ContentPack
{
@@ -21,8 +21,9 @@ namespace Robust.Shared.ContentPack
/// Gets a file from the content root using the relative path.
/// </summary>
/// <param name="relPath">Relative path from the root directory.</param>
/// <param name="stream"></param>
/// <returns>A stream of the file loaded into memory.</returns>
bool TryGetFile(ResourcePath relPath, out MemoryStream stream);
bool TryGetFile(ResourcePath relPath, out Stream stream);
/// <summary>
/// Recursively finds all files in a directory and all sub directories.

View File

@@ -199,7 +199,7 @@ namespace Robust.Shared.ContentPack
try
{
// load the assembly into the process, and bootstrap the GameServer entry point.
LoadGameAssembly<T>(gameDll.ToArray(), gamePdb.ToArray());
LoadGameAssembly<T>(gameDll.CopyToArray(), gamePdb.CopyToArray());
return true;
}
catch (Exception e)
@@ -213,7 +213,7 @@ namespace Robust.Shared.ContentPack
try
{
// load the assembly into the process, and bootstrap the GameServer entry point.
LoadGameAssembly<T>(gameDll.ToArray());
LoadGameAssembly<T>(gameDll.CopyToArray());
return true;
}
catch (Exception e)

View File

@@ -35,7 +35,7 @@ namespace Robust.Shared.ContentPack
}
/// <inheritdoc />
public bool TryGetFile(ResourcePath relPath, out MemoryStream stream)
public bool TryGetFile(ResourcePath relPath, out Stream stream)
{
var entry = _zip.GetEntry(relPath.ToRootedPath().ToString());

View File

@@ -22,7 +22,7 @@ namespace Robust.Shared.ContentPack
// Nothing to do here I'm pretty sure.
}
public bool TryGetFile(ResourcePath relPath, out MemoryStream stream)
public bool TryGetFile(ResourcePath relPath, out Stream stream)
{
if (relPath == _resourcePath)
{

View File

@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using Robust.Shared.Configuration;
using Robust.Shared.Interfaces.Configuration;
using Robust.Shared.Interfaces.Resources;
using Robust.Shared.IoC;
@@ -107,13 +106,13 @@ namespace Robust.Shared.ContentPack
}
/// <inheritdoc />
public MemoryStream ContentFileRead(string path)
public Stream ContentFileRead(string path)
{
return ContentFileRead(new ResourcePath(path));
}
/// <inheritdoc />
public MemoryStream ContentFileRead(ResourcePath path)
public Stream ContentFileRead(ResourcePath path)
{
if (TryContentFileRead(path, out var fileStream))
{
@@ -123,13 +122,13 @@ namespace Robust.Shared.ContentPack
}
/// <inheritdoc />
public bool TryContentFileRead(string path, out MemoryStream fileStream)
public bool TryContentFileRead(string path, out Stream fileStream)
{
return TryContentFileRead(new ResourcePath(path), out fileStream);
}
/// <inheritdoc />
public bool TryContentFileRead(ResourcePath path, out MemoryStream fileStream)
public bool TryContentFileRead(ResourcePath path, out Stream fileStream)
{
if (path == null)
{

View File

@@ -50,7 +50,7 @@ namespace Robust.Shared.Interfaces.Resources
/// <exception cref="FileNotFoundException">Thrown if <paramref name="path"/> does not exist in the VFS.</exception>
/// <exception cref="ArgumentException">Thrown if <paramref name="path"/> is not rooted.</exception>
/// <exception cref="ArgumentNullException">Thrown if <paramref name="path"/> is null.</exception>
MemoryStream ContentFileRead(ResourcePath path);
Stream ContentFileRead(ResourcePath path);
/// <summary>
/// Read a file from the mounted content roots.
@@ -60,7 +60,7 @@ namespace Robust.Shared.Interfaces.Resources
/// <exception cref="FileNotFoundException">Thrown if <paramref name="path"/> does not exist in the VFS.</exception>
/// <exception cref="ArgumentException">Thrown if <paramref name="path"/> is not rooted.</exception>
/// <exception cref="ArgumentNullException">Thrown if <paramref name="path"/> is null.</exception>
MemoryStream ContentFileRead(string path);
Stream ContentFileRead(string path);
/// <summary>
/// Check if a file exists in any of the mounted content roots.
@@ -88,7 +88,7 @@ namespace Robust.Shared.Interfaces.Resources
/// <returns>True if the file could be loaded, false otherwise.</returns>
/// <exception cref="ArgumentException">Thrown if <paramref name="path"/> is not rooted.</exception>
/// <exception cref="ArgumentNullException">Thrown if <paramref name="path"/> is null.</exception>
bool TryContentFileRead(ResourcePath path, out MemoryStream fileStream);
bool TryContentFileRead(ResourcePath path, out Stream fileStream);
/// <summary>
/// Try to read a file from the mounted content roots.
@@ -98,7 +98,7 @@ namespace Robust.Shared.Interfaces.Resources
/// <returns>True if the file could be loaded, false otherwise.</returns>
/// <exception cref="ArgumentException">Thrown if <paramref name="path"/> is not rooted.</exception>
/// <exception cref="ArgumentNullException">Thrown if <paramref name="path"/> is null.</exception>
bool TryContentFileRead(string path, out MemoryStream fileStream);
bool TryContentFileRead(string path, out Stream fileStream);
/// <summary>
/// Recursively finds all files in a directory and all sub directories.

View File

@@ -162,9 +162,13 @@ namespace Robust.Shared.IoC
/// <inheritdoc />
public void InjectDependencies(object obj)
{
foreach (var field in obj.GetType().GetAllFields()
.Where(p => Attribute.GetCustomAttribute(p, typeof(DependencyAttribute)) != null))
foreach (var field in obj.GetType().GetAllFields())
{
if (Attribute.GetCustomAttribute(field, typeof(DependencyAttribute)) == null)
{
continue;
}
// Not using Resolve<T>() because we're literally building it right now.
if (!_services.ContainsKey(field.FieldType))
{

View File

@@ -50,7 +50,7 @@ namespace Robust.Shared.Map
/// <inheritdoc />
public MapIndices Indices => _gridIndices;
/// <inheritdoc />
public TileRef GetTileRef(ushort xIndex, ushort yIndex)
{
@@ -174,12 +174,11 @@ namespace Robust.Shared.Map
var list = offset == SnapGridOffset.Center ? cell.Center : cell.Edge;
if (list == null)
yield break;
foreach (var element in list)
{
yield return element;
return Array.Empty<SnapGridComponent>();
}
return list;
}
/// <inheritdoc />
@@ -276,7 +275,7 @@ namespace Robust.Shared.Map
newRight = cBounds.Right - 1;
tBounds = tBounds.Translated(new Vector2i(-1, 0));
}
cBounds = new Box2i(newLeft, cBounds.Bottom, newRight, cBounds.Top);
}
}
@@ -310,11 +309,11 @@ namespace Robust.Shared.Map
newTop = cBounds.Top - 1;
tBounds = tBounds.Translated(new Vector2i(0, -1));
}
cBounds = new Box2i(cBounds.Left, newBottom, cBounds.Right, newTop);
}
}
private static bool AnyTileOnX(in Tile[,] tiles, Vector2i extents, in Vector2i indices)
{
var y = indices.Y;
@@ -322,7 +321,7 @@ namespace Robust.Shared.Map
{
if(tiles[x, y].IsEmpty)
continue;
return false;
}
@@ -336,7 +335,7 @@ namespace Robust.Shared.Map
{
if(tiles[x, y].IsEmpty)
continue;
return false;
}

View File

@@ -1,5 +1,4 @@
using System;
using System.Linq;
using System.Collections.Generic;
using Robust.Shared.Interfaces.Map;

View File

@@ -264,7 +264,8 @@ namespace Robust.Shared.Prototypes
if (prototypeTypes.ContainsKey(attribute.Type))
{
throw new InvalidImplementationException(type, typeof(IPrototype), string.Format("Duplicate prototype type ID: {0}. Current: {1}", attribute.Type, prototypeTypes[attribute.Type]));
throw new InvalidImplementationException(type, typeof(IPrototype),
$"Duplicate prototype type ID: {attribute.Type}. Current: {prototypeTypes[attribute.Type]}");
}
prototypeTypes[attribute.Type] = type;

View File

@@ -1,8 +1,8 @@
using Robust.Shared.Interfaces.Reflection;
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Robust.Shared.Interfaces.Reflection;
using Robust.Shared.Log;
namespace Robust.Shared.Reflection
@@ -17,6 +17,7 @@ namespace Robust.Shared.Reflection
/// First prefix should probably be <code>""</code>.
/// </remarks>
protected abstract IEnumerable<string> TypePrefixes { get; }
private readonly List<Assembly> assemblies = new List<Assembly>();
public event EventHandler<ReflectionUpdateEventArgs> OnAssemblyAdded;
@@ -25,20 +26,16 @@ namespace Robust.Shared.Reflection
public IEnumerable<Type> GetAllChildren<T>(bool inclusive = false)
{
var typeLists = new List<Type[]>(Assemblies.Count);
try
{
// There's very little assemblies, so storing these temporarily is cheap.
// We need to do it ahead of time so that we can catch ReflectionTypeLoadException HERE,
// so whoever is using us doesn't have to handle them.
var TypeLists = new List<Type[]>(Assemblies.Count);
TypeLists.AddRange(Assemblies.Select(t => t.GetTypes()));
return TypeLists.SelectMany(t => t)
.Where(t => typeof(T).IsAssignableFrom(t)
&& !t.IsAbstract
&& ((Attribute.GetCustomAttribute(t, typeof(ReflectAttribute)) as ReflectAttribute)
?.Discoverable ?? ReflectAttribute.DEFAULT_DISCOVERABLE)
&& (inclusive || typeof(T) != t));
foreach (var assembly in Assemblies)
{
typeLists.Add(assembly.GetTypes());
}
}
catch (ReflectionTypeLoadException e)
{
@@ -47,11 +44,38 @@ namespace Robust.Shared.Reflection
{
Logger.Error(inner.ToString());
}
throw;
}
foreach (var t in typeLists)
{
foreach (var type in t)
{
if (!typeof(T).IsAssignableFrom(type) || type.IsAbstract)
{
continue;
}
var attribute = (ReflectAttribute) Attribute.GetCustomAttribute(type, typeof(ReflectAttribute));
if (!(attribute?.Discoverable ?? ReflectAttribute.DEFAULT_DISCOVERABLE))
{
continue;
}
if (typeof(T) == type && !inclusive)
{
continue;
}
yield return type;
}
}
}
public void LoadAssemblies(params Assembly[] args) => LoadAssemblies(args.AsEnumerable());
public void LoadAssemblies(IEnumerable<Assembly> assemblies)
{
this.assemblies.AddRange(assemblies);
@@ -86,6 +110,7 @@ namespace Robust.Shared.Reflection
{
return ret;
}
throw new ArgumentException("Unable to find type.");
}
@@ -143,7 +168,7 @@ namespace Robust.Shared.Reflection
continue;
}
@enum = (Enum)Enum.Parse(type, value);
@enum = (Enum) Enum.Parse(type, value);
return true;
}
}

View File

@@ -0,0 +1,24 @@
using System.IO;
namespace Robust.Shared.Utility
{
/// <summary>
/// Extension methods for working with streams.
/// </summary>
public static class StreamExt
{
/// <summary>
/// Copies any stream into a byte array.
/// </summary>
/// <param name="stream">The stream to copy.</param>
/// <returns>The byte array.</returns>
public static byte[] CopyToArray(this Stream stream)
{
using (var memStream = new MemoryStream())
{
stream.CopyTo(memStream);
return memStream.GetBuffer();
}
}
}
}

View File

@@ -36,7 +36,14 @@ namespace Robust.Shared.Utility
// We need to fetch the entire class hierarchy and SelectMany(),
// Because BindingFlags.FlattenHierarchy doesn't read privates,
// Even when you pass BindingFlags.NonPublic.
return GetClassHierarchy(t).SelectMany(p => p.GetFields(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public));
foreach (var p in GetClassHierarchy(t))
{
foreach (var field in p.GetFields(BindingFlags.NonPublic | BindingFlags.Instance |
BindingFlags.DeclaredOnly | BindingFlags.Public))
{
yield return field;
}
}
}
/// <summary>
@@ -44,7 +51,9 @@ namespace Robust.Shared.Utility
/// </summary>
public static IEnumerable<PropertyInfo> GetAllProperties(this Type t)
{
return GetClassHierarchy(t).SelectMany(p => p.GetProperties(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public));
return GetClassHierarchy(t).SelectMany(p =>
p.GetProperties(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly |
BindingFlags.Public));
}
public static IEnumerable<Type> GetClassHierarchy(this Type t)

View File

@@ -28,7 +28,7 @@ namespace Robust.UnitTesting.Shared.ContentPack
var resourceManager = IoCManager.Resolve<IResourceManagerInternal>();
using (var stream = resourceManager.ContentFileRead("/a/b/c.dat"))
{
Assert.That(stream.ToArray(), Is.EqualTo(Data));
Assert.That(stream.CopyToArray(), Is.EqualTo(Data));
}
}
}