mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-15 03:30:53 +01:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a40c4a435c | ||
|
|
17182dd0e8 | ||
|
|
d8b50044a2 | ||
|
|
4dc396e73d | ||
|
|
6ae0b0e892 | ||
|
|
7162ca3456 |
@@ -111,9 +111,10 @@ namespace Robust.Client.AutoGenerated
|
||||
compiler.Transform(parsed);
|
||||
var initialRoot = (XamlAstObjectNode) parsed.Root;
|
||||
var names = NameVisitor.GetNames(initialRoot);
|
||||
var fieldAccess = classSymbol.IsSealed ? "private" : "protected";
|
||||
//var names = NameVisitor.GetNames((XamlAstObjectNode)XDocumentXamlParser.Parse(xamlFile).Root);
|
||||
var namedControls = names.Select(info => " " +
|
||||
$"protected global::{info.type} {info.name} => " +
|
||||
$"{fieldAccess} global::{info.type} {info.name} => " +
|
||||
$"this.FindControl<global::{info.type}>(\"{info.name}\");");
|
||||
return $@"// <auto-generated />
|
||||
using Robust.Client.UserInterface;
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace Robust.Client.GameObjects
|
||||
/// <param name="message">Arguments for this event.</param>
|
||||
/// <param name="replay">if true, current cmd state will not be checked or updated - use this for "replaying" an
|
||||
/// old input that was saved or buffered until further processing could be done</param>
|
||||
public bool HandleInputCommand(ICommonSession session, BoundKeyFunction function, FullInputCmdMessage message, bool replay = false)
|
||||
public bool HandleInputCommand(ICommonSession? session, BoundKeyFunction function, FullInputCmdMessage message, bool replay = false)
|
||||
{
|
||||
#if DEBUG
|
||||
|
||||
|
||||
@@ -152,21 +152,21 @@ namespace Robust.Server.ServerStatus
|
||||
|
||||
private void RegisterCVars()
|
||||
{
|
||||
try
|
||||
var path = PathHelpers.ExecutableRelativeFile("build.json");
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
var buildInfo = File.ReadAllText(PathHelpers.ExecutableRelativeFile("build.json"));
|
||||
var info = JsonConvert.DeserializeObject<BuildInfo>(buildInfo);
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't replace cvars with contents of build.json if overriden by --cvar or such.
|
||||
SetCVarIfUnmodified(CVars.BuildEngineVersion, info.EngineVersion);
|
||||
SetCVarIfUnmodified(CVars.BuildForkId, info.ForkId);
|
||||
SetCVarIfUnmodified(CVars.BuildVersion, info.Version);
|
||||
SetCVarIfUnmodified(CVars.BuildDownloadUrl, info.Download ?? "");
|
||||
SetCVarIfUnmodified(CVars.BuildHash, info.Hash ?? "");
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
}
|
||||
var buildInfo = File.ReadAllText(path);
|
||||
var info = JsonConvert.DeserializeObject<BuildInfo>(buildInfo);
|
||||
|
||||
// Don't replace cvars with contents of build.json if overriden by --cvar or such.
|
||||
SetCVarIfUnmodified(CVars.BuildEngineVersion, info.EngineVersion);
|
||||
SetCVarIfUnmodified(CVars.BuildForkId, info.ForkId);
|
||||
SetCVarIfUnmodified(CVars.BuildVersion, info.Version);
|
||||
SetCVarIfUnmodified(CVars.BuildDownloadUrl, info.Download ?? "");
|
||||
SetCVarIfUnmodified(CVars.BuildHash, info.Hash ?? "");
|
||||
|
||||
void SetCVarIfUnmodified(CVarDef<string> cvar, string val)
|
||||
{
|
||||
|
||||
@@ -767,14 +767,14 @@ namespace Robust.Shared.ContentPack
|
||||
var dllName = $"{simpleName}.dll";
|
||||
foreach (var diskLoadPath in _diskLoadPaths)
|
||||
{
|
||||
try
|
||||
{
|
||||
var path = Path.Combine(diskLoadPath, dllName);
|
||||
return new PEReader(File.OpenRead(path));
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
var path = Path.Combine(diskLoadPath, dllName);
|
||||
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
return new PEReader(File.OpenRead(path));
|
||||
}
|
||||
|
||||
var extraStream = _parent.ExtraRobustLoader?.Invoke(dllName);
|
||||
|
||||
@@ -179,9 +179,23 @@ namespace Robust.Shared.Network
|
||||
// Well they're in. Kick a connected client with the same GUID if we have to.
|
||||
if (_assignedUserIds.TryGetValue(userId, out var existing))
|
||||
{
|
||||
existing.Disconnect("Another connection has been made with your account.");
|
||||
// Have to wait until they're properly off the server to avoid any collisions.
|
||||
await AwaitDisconnectAsync(existing);
|
||||
if (_awaitingDisconnectToConnect.Contains(userId))
|
||||
{
|
||||
connection.Disconnect("Stop trying to connect multiple times at once.");
|
||||
return;
|
||||
}
|
||||
|
||||
_awaitingDisconnectToConnect.Add(userId);
|
||||
try
|
||||
{
|
||||
existing.Disconnect("Another connection has been made with your account.");
|
||||
// Have to wait until they're properly off the server to avoid any collisions.
|
||||
await AwaitDisconnectAsync(existing);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_awaitingDisconnectToConnect.Remove(userId);
|
||||
}
|
||||
}
|
||||
|
||||
var msg = peer.Peer.CreateMessage();
|
||||
@@ -242,8 +256,12 @@ namespace Robust.Shared.Network
|
||||
|
||||
private Task AwaitDisconnectAsync(NetConnection connection)
|
||||
{
|
||||
var tcs = new TaskCompletionSource<object?>();
|
||||
_awaitingDisconnect.Add(connection, tcs);
|
||||
if (!_awaitingDisconnect.TryGetValue(connection, out var tcs))
|
||||
{
|
||||
tcs = new TaskCompletionSource<object?>();
|
||||
_awaitingDisconnect.Add(connection, tcs);
|
||||
}
|
||||
|
||||
return tcs.Task;
|
||||
}
|
||||
|
||||
|
||||
@@ -135,6 +135,8 @@ namespace Robust.Shared.Network
|
||||
private readonly Dictionary<NetConnection, TaskCompletionSource<object?>> _awaitingDisconnect
|
||||
= new();
|
||||
|
||||
private readonly HashSet<NetUserId> _awaitingDisconnectToConnect = new HashSet<NetUserId>();
|
||||
|
||||
/// <inheritdoc />
|
||||
public int Port => _config.GetCVar(CVars.NetPort);
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Globalization;
|
||||
@@ -510,6 +511,24 @@ namespace Robust.Shared.Serialization
|
||||
return newList;
|
||||
}
|
||||
|
||||
if (TryGenericImmutableListType(type, out var immutableListType))
|
||||
{
|
||||
var listNode = (YamlSequenceNode) node;
|
||||
var elems = listNode.Children;
|
||||
|
||||
var newList = Array.CreateInstance(immutableListType, elems.Count);
|
||||
|
||||
for (var i = 0; i < elems.Count; i++)
|
||||
{
|
||||
newList.SetValue(NodeToType(immutableListType, elems[i]), i);
|
||||
}
|
||||
|
||||
var list = typeof(ImmutableList);
|
||||
var add = list.GetMethod("CreateRange")!.MakeGenericMethod(immutableListType);
|
||||
|
||||
return add.Invoke(null, new object?[] {newList})!;
|
||||
}
|
||||
|
||||
// Dictionary<K,V>/IReadOnlyDictionary<K,V>
|
||||
if (TryGenericReadDictType(type, out var keyType, out var valType, out var dictType))
|
||||
{
|
||||
@@ -725,6 +744,28 @@ namespace Robust.Shared.Serialization
|
||||
return node;
|
||||
}
|
||||
|
||||
if (TryGenericImmutableListType(type, out var immutableListType))
|
||||
{
|
||||
var node = new YamlSequenceNode {Tag = TagSkipTag};
|
||||
|
||||
foreach (var entry in (IEnumerable) obj)
|
||||
{
|
||||
if (entry == null)
|
||||
{
|
||||
throw new ArgumentException("Cannot serialize null value inside list.");
|
||||
}
|
||||
|
||||
var entryNode = TypeToNode(entry);
|
||||
|
||||
// write the concrete type tag
|
||||
AssignTag<object?>(immutableListType, entry, null, entryNode);
|
||||
|
||||
node.Add(entryNode);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
// Dictionary<K,V>
|
||||
if (TryGenericDictType(type, out var keyType, out var valType)
|
||||
|| TryGenericReadOnlyDictType(type, out keyType, out valType))
|
||||
@@ -863,7 +904,8 @@ namespace Robust.Shared.Serialization
|
||||
return true;
|
||||
}
|
||||
|
||||
if (TryGenericListType(type!, out _))
|
||||
if (TryGenericListType(type!, out _) ||
|
||||
TryGenericImmutableListType(type!, out _))
|
||||
{
|
||||
var listA = (IList) a;
|
||||
var listB = (IList) b!;
|
||||
@@ -1025,6 +1067,21 @@ namespace Robust.Shared.Serialization
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool TryGenericImmutableListType(Type type, [NotNullWhen(true)] out Type? listType)
|
||||
{
|
||||
var isImmutableList = type.GetTypeInfo().IsGenericType &&
|
||||
type.GetGenericTypeDefinition() == typeof(ImmutableList<>);
|
||||
|
||||
if (isImmutableList)
|
||||
{
|
||||
listType = type.GetGenericArguments()[0];
|
||||
return true;
|
||||
}
|
||||
|
||||
listType = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool TryGenericReadOnlyDictType(Type type, [NotNullWhen(true)] out Type? keyType, [NotNullWhen(true)] out Type? valType)
|
||||
{
|
||||
var isDict = type.GetTypeInfo().IsGenericType && type.GetGenericTypeDefinition() == typeof(IReadOnlyDictionary<,>);
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using NUnit.Framework;
|
||||
using Robust.Shared.Serialization;
|
||||
using YamlDotNet.RepresentationModel;
|
||||
using static Robust.UnitTesting.Shared.Serialization.YamlObjectSerializerTests.YamlObjectSerializer_Test;
|
||||
// ReSharper disable AccessToStaticMemberViaDerivedType
|
||||
|
||||
namespace Robust.UnitTesting.Shared.Serialization.YamlObjectSerializerTests
|
||||
{
|
||||
[Parallelizable(ParallelScope.All | ParallelScope.Fixtures)]
|
||||
[TestFixture]
|
||||
[TestOf(typeof(YamlObjectSerializer))]
|
||||
public class ImmutableListSerializationTest
|
||||
{
|
||||
[Test]
|
||||
public void SerializeListTest()
|
||||
{
|
||||
// Arrange
|
||||
var data = _serializableList;
|
||||
var mapping = new YamlMappingNode();
|
||||
var serializer = YamlObjectSerializer.NewWriter(mapping);
|
||||
|
||||
// Act
|
||||
serializer.DataField(ref data, "datalist", ImmutableList<int>.Empty);
|
||||
|
||||
// Assert
|
||||
var result = NodeToYamlText(mapping);
|
||||
Assert.That(result, Is.EqualTo(_serializedListYaml));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DeserializeListTest()
|
||||
{
|
||||
// Arrange
|
||||
ImmutableList<int> data = null!;
|
||||
var rootNode = YamlTextToNode(_serializedListYaml);
|
||||
var serializer = YamlObjectSerializer.NewReader(rootNode);
|
||||
|
||||
// Act
|
||||
serializer.DataField(ref data, "datalist", ImmutableList<int>.Empty);
|
||||
|
||||
// Assert
|
||||
Assert.That(data, Is.Not.Null);
|
||||
Assert.That(data.Count, Is.EqualTo(_serializableList.Count));
|
||||
|
||||
for (var i = 0; i < _serializableList.Count; i++)
|
||||
{
|
||||
Assert.That(data[i], Is.EqualTo(_serializableList[i]));
|
||||
}
|
||||
}
|
||||
|
||||
private readonly string _serializedListYaml = "datalist:\n- 1\n- 2\n- 3\n...\n";
|
||||
private readonly ImmutableList<int> _serializableList = ImmutableList.Create<int>(1, 2, 3);
|
||||
}
|
||||
}
|
||||
@@ -77,7 +77,7 @@ namespace Robust.UnitTesting.Shared.Serialization.YamlObjectSerializerTests
|
||||
|
||||
public int TestPropertyTwo { get; set; }
|
||||
|
||||
public void ExposeData(ObjectSerializer serializer)
|
||||
void IExposeData.ExposeData(ObjectSerializer serializer)
|
||||
{
|
||||
serializer.DataField(this, x => TestPropertyOne, "testPropertyOne", null);
|
||||
serializer.DataField(this, x => TestPropertyTwo, "testPropertyTwo", 0);
|
||||
|
||||
Reference in New Issue
Block a user