Compare commits

...

6 Commits

Author SHA1 Message Date
DrSmugleaf
a40c4a435c Fix file not found exceptions when starting up the game with a debugger (#1562)
* Fix exceptions when starting up the game

* Remove try catches
2021-02-16 20:05:22 +01:00
DrSmugleaf
17182dd0e8 Engine PR for enabling nullability in Content.Client (#1565) 2021-02-16 20:05:06 +01:00
DrSmugleaf
d8b50044a2 Add (de)serialization for immutable lists (#1549) 2021-02-16 20:04:28 +01:00
Pieter-Jan Briers
4dc396e73d Fixes warning in TypePropertySerialization_Test.cs 2021-02-16 09:20:06 +01:00
Pieter-Jan Briers
6ae0b0e892 Fix [GenerateTypedNameReferences] with sealed types.
Fixes #1546
2021-02-16 09:19:57 +01:00
Pieter-Jan Briers
7162ca3456 Probably fix the bug where people get locked out of the server due to duplicate connction attempts. 2021-02-16 09:02:14 +01:00
9 changed files with 163 additions and 28 deletions

View File

@@ -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;

View File

@@ -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

View File

@@ -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)
{

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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<,>);

View File

@@ -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);
}
}

View File

@@ -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);