Compare commits

...

15 Commits

Author SHA1 Message Date
Acruid
e0cdcd228e Fixed Timer Namespace in unit tests. 2021-02-18 20:35:34 -08:00
Acruid
fdb5e014b5 PauseManager moved to Shared (#1553)
* Moved IPauseManager from server to shared.

* Moved ITimerManager from Timers to Timing.

* Added missing IConsoleHost to server/client RegisterIoC. Tests work again.
2021-02-18 20:12:26 -08:00
DrSmugleaf
cefcad775b Make addcomp and rmcomp give better feedback and case insensitive (#1570)
* Make addcomp and rmcomp case insensitive

* Fix up names

* Make addcomp and rmcomp give better feedback

* Make addcomp and rmcomp less fail happy
2021-02-18 20:01:14 -08:00
Vera Aguilera Puerto
e40feac1f1 Adds VV autorefresh when right-clicking the refresh button. (#1558)
* Adds VV autorefresh when right-clicking the refresh button.

* cancel token on close

* button tooltip
2021-02-18 00:14:11 -08:00
DrSmugleaf
3ef4ac7452 Make component states dependant on the player getting them (#1569) 2021-02-17 23:48:17 -08:00
Pieter-Jan Briers
93bf1b09e7 Fix disconnecting while connecting causes you to be locked out of the server. 2021-02-17 23:22:11 +01:00
DrSmugleaf
a1e557e870 Add IPrototypeManager method to load a string (#1567) 2021-02-17 13:20:39 -08:00
Pieter-Jan Briers
864adb7445 Add DateTimeStyles to sandbox. 2021-02-17 11:52:36 +01:00
mirrorcult
9e3f3f0c1c vec2i serializer (#1563)
Co-authored-by: cyclowns <cyclowns@protonmail.ch>
2021-02-16 12:19:45 -08:00
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
56 changed files with 621 additions and 378 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

@@ -1,4 +1,4 @@
using System;
using System;
using Robust.Client.Audio.Midi;
using Robust.Client.Console;
using Robust.Client.Debugging;
@@ -17,6 +17,7 @@ using Robust.Client.UserInterface;
using Robust.Client.Utility;
using Robust.Client.ViewVariables;
using Robust.Shared;
using Robust.Shared.Console;
using Robust.Shared.ContentPack;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
@@ -59,6 +60,7 @@ namespace Robust.Client
IoCManager.Register<ILightManager, LightManager>();
IoCManager.Register<IDiscordRichPresence, DiscordRichPresence>();
IoCManager.Register<IClientConsoleHost, ClientConsoleHost>();
IoCManager.Register<IConsoleHost, ClientConsoleHost>();
IoCManager.Register<IFontManager, FontManager>();
IoCManager.Register<IFontManagerInternal, FontManager>();
IoCManager.Register<IMidiManager, MidiManager>();

View File

@@ -26,7 +26,6 @@ using Robust.Shared.Map;
using Robust.Shared.Network;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Timers;
using Robust.Shared.Timing;
using Robust.Shared.Utility;

View File

@@ -1,11 +0,0 @@
using Robust.Shared.GameObjects;
namespace Robust.Client.GameObjects
{
[RegisterComponent]
[ComponentReference(typeof(SharedIgnorePauseComponent))]
public sealed class IgnorePauseComponent : SharedIgnorePauseComponent
{
}
}

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

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using Robust.Client.GameObjects;
using Robust.Client.Input;
using Robust.Shared.GameStates;
@@ -352,7 +353,10 @@ namespace Robust.Client.GameStates
foreach (var component in _componentManager.GetNetComponents(createdEntity))
{
var state = component.GetComponentState();
Debug.Assert(_players.LocalPlayer != null, "_players.LocalPlayer != null");
var player = _players.LocalPlayer.Session;
var state = component.GetComponentState(player);
if (state.GetType() == typeof(ComponentState))
{

View File

@@ -5,7 +5,7 @@ using System.Diagnostics.Contracts;
using Robust.Client.Graphics;
using Robust.Shared.Input;
using Robust.Shared.Maths;
using Timer = Robust.Shared.Timers.Timer;
using Timer = Robust.Shared.Timing.Timer;
namespace Robust.Client.UserInterface.Controls
{

View File

@@ -1,21 +1,27 @@
using System.Collections.Generic;
using System.Collections.Generic;
using System.Threading;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.ViewVariables.Traits;
using Robust.Shared.Input;
using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables;
using Robust.Shared.Utility;
using Timer = Robust.Shared.Timing.Timer;
namespace Robust.Client.ViewVariables.Instances
{
internal class ViewVariablesInstanceObject : ViewVariablesInstance
{
private TabContainer _tabs = default!;
private Button _refreshButton = default!;
private int _tabCount;
private readonly List<ViewVariablesTrait> _traits = new();
private CancellationTokenSource _refreshCancelToken = new();
public ViewVariablesRemoteSession? Session { get; private set; }
public object? Object { get; private set; }
@@ -72,9 +78,10 @@ namespace Robust.Client.ViewVariables.Instances
name.SizeFlagsHorizontal = Control.SizeFlags.FillExpand;
headBox.AddChild(name);
var button = new Button {Text = "Refresh"};
button.OnPressed += _ => _refresh();
headBox.AddChild(button);
_refreshButton = new Button {Text = "Refresh", ToolTip = "RMB to toggle auto-refresh."};
_refreshButton.OnPressed += _ => _refresh();
_refreshButton.OnKeyBindDown += OnButtonKeybindDown;
headBox.AddChild(_refreshButton);
vBoxContainer.AddChild(headBox);
}
@@ -82,10 +89,32 @@ namespace Robust.Client.ViewVariables.Instances
vBoxContainer.AddChild(_tabs);
}
private void OnButtonKeybindDown(GUIBoundKeyEventArgs eventArgs)
{
if (eventArgs.Function == EngineKeyFunctions.UIRightClick)
{
_refreshButton.ToggleMode = !_refreshButton.ToggleMode;
_refreshButton.Pressed = !_refreshButton.Pressed;
_refreshCancelToken.Cancel();
if (!_refreshButton.Pressed) return;
_refreshCancelToken = new CancellationTokenSource();
Timer.SpawnRepeating(500, _refresh, _refreshCancelToken.Token);
} else if (eventArgs.Function == EngineKeyFunctions.UIClick)
{
_refreshButton.ToggleMode = false;
}
}
public override void Close()
{
base.Close();
_refreshCancelToken.Cancel();
if (Session != null && !Session.Closed)
{
ViewVariablesManager.CloseSession(Session);

View File

@@ -31,7 +31,6 @@ using Robust.Shared.Localization;
using Robust.Shared.Map;
using Robust.Shared.Network;
using Robust.Shared.Serialization;
using Robust.Shared.Timers;
using Serilog.Debugging;
using Serilog.Sinks.Loki;
using Stopwatch = Robust.Shared.Timing.Stopwatch;

View File

@@ -1,64 +0,0 @@
using JetBrains.Annotations;
using Robust.Shared.Console;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
namespace Robust.Server.Console.Commands
{
[UsedImplicitly]
internal sealed class AddCompCommand : IConsoleCommand
{
public string Command => "addcomp";
public string Description => "Adds a component to an entity";
public string Help => "addcomp <uid> <componentName>";
public void Execute(IConsoleShell shell, string argStr, string[] args)
{
if (args.Length != 2)
{
shell.WriteLine("Wrong number of arguments");
return;
}
var entityUid = EntityUid.Parse(args[0]);
var componentName = args[1];
var compManager = IoCManager.Resolve<IComponentManager>();
var compFactory = IoCManager.Resolve<IComponentFactory>();
var entityManager = IoCManager.Resolve<IEntityManager>();
var entity = entityManager.GetEntity(entityUid);
var component = (Component) compFactory.GetComponent(componentName);
component.Owner = entity;
compManager.AddComponent(entity, component);
}
}
[UsedImplicitly]
internal sealed class RemoveCompCommand : IConsoleCommand
{
public string Command => "rmcomp";
public string Description => "Removes a component from an entity.";
public string Help => "rmcomp <uid> <componentName>";
public void Execute(IConsoleShell shell, string argStr, string[] args)
{
if (args.Length != 2)
{
shell.WriteLine("Wrong number of arguments");
return;
}
var entityUid = EntityUid.Parse(args[0]);
var componentName = args[1];
var compManager = IoCManager.Resolve<IComponentManager>();
var compFactory = IoCManager.Resolve<IComponentFactory>();
var registration = compFactory.GetRegistration(componentName);
compManager.RemoveComponent(entityUid, registration.Type);
}
}
}

View File

@@ -0,0 +1,61 @@
using JetBrains.Annotations;
using Robust.Shared.Console;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
namespace Robust.Server.Console.Commands
{
[UsedImplicitly]
internal sealed class AddComponentCommand : IConsoleCommand
{
public string Command => "addcomp";
public string Description => "Adds a component to an entity";
public string Help => $"{Command} <uid> <componentName>";
public void Execute(IConsoleShell shell, string argStr, string[] args)
{
if (args.Length != 2)
{
shell.WriteLine($"Invalid amount of arguments.\n{Help}");
return;
}
if (!EntityUid.TryParse(args[0], out var uid))
{
shell.WriteLine($"{uid} is not a valid entity uid.");
return;
}
var entityManager = IoCManager.Resolve<IEntityManager>();
if (!entityManager.TryGetEntity(uid, out var entity))
{
shell.WriteLine($"No entity found with id {uid}.");
return;
}
var componentName = args[1];
var compManager = IoCManager.Resolve<IComponentManager>();
var compFactory = IoCManager.Resolve<IComponentFactory>();
if (!compFactory.TryGetRegistration(componentName, out var registration, true))
{
shell.WriteLine($"No component found with name {componentName}.");
return;
}
if (entity.HasComponent(registration.Type))
{
shell.WriteLine($"Entity {entity.Name} already has a {componentName} component.");
}
var component = (Component) compFactory.GetComponent(registration.Type);
component.Owner = entity;
compManager.AddComponent(entity, component);
shell.WriteLine($"Added {componentName} component to entity {entity.Name}.");
}
}
}

View File

@@ -1,15 +1,14 @@
using System.Globalization;
using System.Globalization;
using System.Linq;
using System.Text;
using Robust.Server.Maps;
using Robust.Server.Player;
using Robust.Server.Timing;
using Robust.Shared.Console;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Timing;
namespace Robust.Server.Console.Commands
{
@@ -237,81 +236,6 @@ namespace Robust.Server.Console.Commands
}
}
class PauseMapCommand : IConsoleCommand
{
public string Command => "pausemap";
public string Description => "Pauses a map, pausing all simulation processing on it.";
public string Help => "Usage: pausemap <map ID>";
public void Execute(IConsoleShell shell, string argStr, string[] args)
{
if (args.Length != 1)
{
shell.WriteLine(Loc.GetString("Need to supply a valid MapId"));
return;
}
var arg = args[0];
var mapId = new MapId(int.Parse(arg, CultureInfo.InvariantCulture));
var pauseManager = IoCManager.Resolve<IPauseManager>();
var mapManager = IoCManager.Resolve<IMapManager>();
if (!mapManager.MapExists(mapId))
{
shell.WriteLine("That map does not exist.");
return;
}
pauseManager.SetMapPaused(mapId, true);
}
}
class UnpauseMapCommand : IConsoleCommand
{
public string Command => "unpausemap";
public string Description => "unpauses a map, resuming all simulation processing on it.";
public string Help => "Usage: unpausemap <map ID>";
public void Execute(IConsoleShell shell, string argStr, string[] args)
{
if (args.Length != 1)
{
shell.WriteLine(Loc.GetString("Need to supply a valid MapId"));
return;
}
var arg = args[0];
var mapId = new MapId(int.Parse(arg, CultureInfo.InvariantCulture));
var pauseManager = IoCManager.Resolve<IPauseManager>();
var mapManager = IoCManager.Resolve<IMapManager>();
if (!mapManager.MapExists(mapId))
{
shell.WriteLine("That map does not exist.");
return;
}
pauseManager.SetMapPaused(mapId, false);
}
}
class QueryMapPausedCommand : IConsoleCommand
{
public string Command => "querymappaused";
public string Description => "Check whether a map is paused or not.";
public string Help => "Usage: querymappaused <map ID>";
public void Execute(IConsoleShell shell, string argStr, string[] args)
{
var arg = args[0];
var mapId = new MapId(int.Parse(arg, CultureInfo.InvariantCulture));
var pauseManager = IoCManager.Resolve<IPauseManager>();
var mapManager = IoCManager.Resolve<IMapManager>();
if (!mapManager.MapExists(mapId))
{
shell.WriteLine("That map does not exist.");
return;
}
shell.WriteLine(pauseManager.IsMapPaused(mapId).ToString());
}
}
class TpGridCommand : IConsoleCommand
{
public string Command => "tpgrid";

View File

@@ -0,0 +1,59 @@
using JetBrains.Annotations;
using Robust.Shared.Console;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
namespace Robust.Server.Console.Commands
{
[UsedImplicitly]
internal sealed class RemoveComponentCommand : IConsoleCommand
{
public string Command => "rmcomp";
public string Description => "Removes a component from an entity.";
public string Help => $"{Command} <uid> <componentName>";
public void Execute(IConsoleShell shell, string argStr, string[] args)
{
if (args.Length != 2)
{
shell.WriteLine($"Invalid amount of arguments.\n{Help}.");
return;
}
if (!EntityUid.TryParse(args[0], out var uid))
{
shell.WriteLine($"{uid} is not a valid entity uid.");
return;
}
var entityManager = IoCManager.Resolve<IEntityManager>();
if (!entityManager.TryGetEntity(uid, out var entity))
{
shell.WriteLine($"No entity found with id {uid}.");
return;
}
var componentName = args[1];
var compManager = IoCManager.Resolve<IComponentManager>();
var compFactory = IoCManager.Resolve<IComponentFactory>();
if (!compFactory.TryGetRegistration(componentName, out var registration, true))
{
shell.WriteLine($"No component found with name {componentName}.");
return;
}
if (!entity.HasComponent(registration.Type))
{
shell.WriteLine($"No {componentName} component found on entity {entity.Name}.");
return;
}
compManager.RemoveComponent(uid, registration.Type);
shell.WriteLine($"Removed {componentName} component from entity {entity.Name}.");
}
}
}

View File

@@ -3,6 +3,7 @@ using Robust.Shared.ViewVariables;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Robust.Shared.Players;
namespace Robust.Server.GameObjects
{
@@ -61,7 +62,7 @@ namespace Robust.Server.GameObjects
return false;
}
public override ComponentState GetComponentState()
public override ComponentState GetComponentState(ICommonSession player)
{
return new AppearanceComponentState(data);
}

View File

@@ -5,6 +5,7 @@ using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Players;
using Robust.Shared.Reflection;
using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables;
@@ -256,7 +257,7 @@ namespace Robust.Server.GameObjects
_entitiesWaitingResolve = null;
}
public override ComponentState GetComponentState()
public override ComponentState GetComponentState(ICommonSession player)
{
return new ContainerManagerComponentState(
_allContainers.ToDictionary(

View File

@@ -1,5 +1,6 @@
using Robust.Shared.GameObjects;
using Robust.Shared.Maths;
using Robust.Shared.Players;
using Robust.Shared.Serialization;
namespace Robust.Server.GameObjects
@@ -63,7 +64,7 @@ namespace Robust.Server.GameObjects
}
}
public override ComponentState GetComponentState()
public override ComponentState GetComponentState(ICommonSession player)
{
return new EyeComponentState(DrawFov, Zoom, Offset, Rotation);
}

View File

@@ -1,5 +1,6 @@
using Robust.Shared.GameObjects;
using Robust.Shared.Maths;
using Robust.Shared.Players;
using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables;
@@ -73,7 +74,7 @@ namespace Robust.Server.GameObjects
serializer.DataField(ref _offset, "offset", Vector2.Zero);
}
public override ComponentState GetComponentState()
public override ComponentState GetComponentState(ICommonSession player)
{
return new PointLightComponentState(Enabled, Color, Radius, Offset);
}

View File

@@ -4,6 +4,7 @@ using Robust.Shared.GameObjects;
using DrawDepthTag = Robust.Shared.GameObjects.DrawDepth;
using Robust.Shared.Log;
using Robust.Shared.Maths;
using Robust.Shared.Players;
using Robust.Shared.Serialization;
using Robust.Shared.Utility;
using Robust.Shared.ViewVariables;
@@ -441,7 +442,7 @@ namespace Robust.Server.GameObjects
Layers = layerData;
}
public override ComponentState GetComponentState()
public override ComponentState GetComponentState(ICommonSession player)
{
return new SpriteComponentState(Visible, DrawDepth, Scale, Rotation, Offset, Color, Directional,
BaseRSIPath, Layers, RenderOrder);

View File

@@ -10,7 +10,7 @@ namespace Robust.Server.GameObjects
/// <summary>
/// Gets all entity states that have been modified after and including the provided tick.
/// </summary>
List<EntityState>? GetEntityStates(GameTick fromTick);
List<EntityState>? GetEntityStates(GameTick fromTick, IPlayerSession player);
/// <summary>
/// Gets all entity states within an AABB that have been modified after and including the provided tick.

View File

@@ -4,7 +4,6 @@ using System.Linq;
using System.Threading;
using Prometheus;
using Robust.Server.Player;
using Robust.Server.Timing;
using Robust.Shared;
using Robust.Shared.Configuration;
using Robust.Shared.GameObjects;
@@ -13,6 +12,7 @@ using Robust.Shared.Maths;
using Robust.Shared.Prototypes;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
using static Robust.Shared.GameObjects.TransformComponent;
namespace Robust.Server.GameObjects
{
@@ -139,7 +139,7 @@ namespace Robust.Server.GameObjects
}
/// <inheritdoc />
public List<EntityState>? GetEntityStates(GameTick fromTick)
public List<EntityState>? GetEntityStates(GameTick fromTick, IPlayerSession player)
{
var stateEntities = new List<EntityState>();
foreach (var entity in AllEntities)
@@ -154,7 +154,7 @@ namespace Robust.Server.GameObjects
if (entity.LastModifiedTick <= fromTick)
continue;
stateEntities.Add(GetEntityState(ComponentManager, entity.Uid, fromTick));
stateEntities.Add(GetEntityState(ComponentManager, entity.Uid, fromTick, player));
}
// no point sending an empty collection
@@ -336,7 +336,7 @@ namespace Robust.Server.GameObjects
if (playerEnt == null)
{
// super-observer?
return GetEntityStates(fromTick);
return GetEntityStates(fromTick, player);
}
var playerUid = playerEnt.Uid;
@@ -390,7 +390,7 @@ namespace Robust.Server.GameObjects
}
}
var state = GetEntityState(ComponentManager, uid, fromTick);
var state = GetEntityState(ComponentManager, uid, fromTick, player);
if (checkedEnts.Add(uid))
{
@@ -404,14 +404,14 @@ namespace Robust.Server.GameObjects
{
// mover changed and can't be seen
var idx = Array.FindIndex(state.ComponentStates,
x => x is TransformComponent.TransformComponentState);
x => x is TransformComponentState);
if (idx != -1)
{
// mover changed positional data and can't be seen
var oldState =
(TransformComponent.TransformComponentState) state.ComponentStates[idx];
var newState = new TransformComponent.TransformComponentState(Vector2NaN,
(TransformComponentState) state.ComponentStates[idx];
var newState = new TransformComponentState(Vector2NaN,
oldState.Rotation, oldState.ParentID, oldState.NoLocalRotation);
state.ComponentStates[idx] = newState;
seenMovers.Remove(uid);
@@ -441,7 +441,7 @@ namespace Robust.Server.GameObjects
{
// mover can't be seen
var oldState =
(TransformComponent.TransformComponentState) entity.Transform.GetComponentState();
(TransformComponentState) entity.Transform.GetComponentState(player);
entityStates.Add(new EntityState(uid,
new ComponentChanged[]
{
@@ -449,7 +449,7 @@ namespace Robust.Server.GameObjects
},
new ComponentState[]
{
new TransformComponent.TransformComponentState(Vector2NaN, oldState.Rotation,
new TransformComponentState(Vector2NaN, oldState.Rotation,
oldState.ParentID, oldState.NoLocalRotation)
}));
@@ -517,7 +517,7 @@ namespace Robust.Server.GameObjects
}
// should this be lastSeen or fromTick?
var entityState = GetEntityState(ComponentManager, uid, lastSeen);
var entityState = GetEntityState(ComponentManager, uid, lastSeen, player);
checkedEnts.Add(uid);
@@ -577,7 +577,7 @@ namespace Robust.Server.GameObjects
continue;
}
var state = GetEntityState(ComponentManager, uid, fromTick);
var state = GetEntityState(ComponentManager, uid, fromTick, player);
if (state.ComponentStates == null)
{
@@ -591,7 +591,7 @@ namespace Robust.Server.GameObjects
seenMovers.Remove(uid);
ClearLastSeenTick(lSeen, uid);
var idx = Array.FindIndex(state.ComponentStates, x => x is TransformComponent.TransformComponentState);
var idx = Array.FindIndex(state.ComponentStates, x => x is TransformComponentState);
if (idx == -1)
{
@@ -599,9 +599,9 @@ namespace Robust.Server.GameObjects
continue;
}
var oldState = (TransformComponent.TransformComponentState) state.ComponentStates[idx];
var oldState = (TransformComponentState) state.ComponentStates[idx];
var newState =
new TransformComponent.TransformComponentState(Vector2NaN, oldState.Rotation, oldState.ParentID, oldState.NoLocalRotation);
new TransformComponentState(Vector2NaN, oldState.Rotation, oldState.ParentID, oldState.NoLocalRotation);
state.ComponentStates[idx] = newState;
@@ -630,7 +630,7 @@ namespace Robust.Server.GameObjects
}
var entity = GetEntity(uid);
var state = GetEntityState(ComponentManager, uid, fromTick);
var state = GetEntityState(ComponentManager, uid, fromTick, player);
if (state.ComponentStates == null || viewbox.Intersects(GetWorldAabbFromEntity(entity)))
{
@@ -643,7 +643,7 @@ namespace Robust.Server.GameObjects
entityStates.Add(state);
var idx = Array.FindIndex(state.ComponentStates,
x => x is TransformComponent.TransformComponentState);
x => x is TransformComponentState);
if (idx == -1)
{
@@ -651,9 +651,9 @@ namespace Robust.Server.GameObjects
continue;
}
var oldState = (TransformComponent.TransformComponentState) state.ComponentStates[idx];
var oldState = (TransformComponentState) state.ComponentStates[idx];
var newState =
new TransformComponent.TransformComponentState(Vector2NaN, oldState.Rotation,
new TransformComponentState(Vector2NaN, oldState.Rotation,
oldState.ParentID, oldState.NoLocalRotation);
state.ComponentStates[idx] = newState;
seenMovers.Remove(uid);
@@ -881,8 +881,9 @@ namespace Robust.Server.GameObjects
/// <param name="compMan">ComponentManager that contains the components for the entity.</param>
/// <param name="entityUid">Uid of the entity to generate the state from.</param>
/// <param name="fromTick">Only provide delta changes from this tick.</param>
/// <param name="player">The player to generate this state for.</param>
/// <returns>New entity State for the given entity.</returns>
private static EntityState GetEntityState(IComponentManager compMan, EntityUid entityUid, GameTick fromTick)
private static EntityState GetEntityState(IComponentManager compMan, EntityUid entityUid, GameTick fromTick, IPlayerSession player)
{
var compStates = new List<ComponentState>();
var changed = new List<ComponentChanged>();
@@ -899,7 +900,7 @@ namespace Robust.Server.GameObjects
// As such, we can avoid sending this data in this case since the client "already has it".
if (comp.NetSyncEnabled && comp.LastModifiedTick != GameTick.Zero && comp.LastModifiedTick >= fromTick)
compStates.Add(comp.GetComponentState());
compStates.Add(comp.GetComponentState(player));
if (comp.CreationTick != GameTick.Zero && comp.CreationTick >= fromTick && !comp.Deleted)
{

View File

@@ -135,7 +135,7 @@ namespace Robust.Server.GameStates
}
var entStates = lastAck == GameTick.Zero || !PvsEnabled
? _entityManager.GetEntityStates(lastAck)
? _entityManager.GetEntityStates(lastAck, session)
: _entityManager.UpdatePlayerSeenEntityStates(lastAck, session, _entityManager.MaxUpdateRange);
var playerStates = _playerManager.GetPlayerStates(lastAck);
var deletions = _entityManager.GetDeletedEntities(lastAck);

View File

@@ -12,9 +12,9 @@ using Robust.Shared.GameObjects;
using System.Globalization;
using System.Linq;
using Robust.Server.GameObjects;
using Robust.Server.Timing;
using Robust.Shared.ContentPack;
using Robust.Shared.Prototypes;
using Robust.Shared.Timing;
using YamlDotNet.Core;
namespace Robust.Server.Maps

View File

@@ -10,9 +10,9 @@ using Robust.Server.Prototypes;
using Robust.Server.Reflection;
using Robust.Server.Scripting;
using Robust.Server.ServerStatus;
using Robust.Server.Timing;
using Robust.Server.ViewVariables;
using Robust.Shared;
using Robust.Shared.Console;
using Robust.Shared.ContentPack;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
@@ -20,6 +20,7 @@ using Robust.Shared.Map;
using Robust.Shared.Network;
using Robust.Shared.Prototypes;
using Robust.Shared.Reflection;
using Robust.Shared.Timing;
namespace Robust.Server
{
@@ -37,11 +38,11 @@ namespace Robust.Server
IoCManager.Register<IComponentFactory, ServerComponentFactory>();
IoCManager.Register<IConGroupController, ConGroupController>();
IoCManager.Register<IServerConsoleHost, ServerConsoleHost>();
IoCManager.Register<IConsoleHost, ServerConsoleHost>();
IoCManager.Register<IEntityManager, ServerEntityManager>();
IoCManager.Register<IEntityNetworkManager, ServerEntityNetworkManager>();
IoCManager.Register<IServerEntityNetworkManager, ServerEntityNetworkManager>();
IoCManager.Register<IMapLoader, MapLoader>();
IoCManager.Register<IPauseManager, PauseManager>();
IoCManager.Register<IPlacementManager, PlacementManager>();
IoCManager.Register<IPlayerManager, PlayerManager>();
IoCManager.Register<IPrototypeManager, ServerPrototypeManager>();

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

@@ -1,98 +0,0 @@
using System;
using System.Collections.Generic;
using Robust.Server.GameObjects;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Map;
using Robust.Shared.ViewVariables;
namespace Robust.Server.Timing
{
internal sealed class PauseManager : IPauseManager, IPostInjectInit
{
[Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly IEntityManager _entityManager = default!;
[ViewVariables] private readonly HashSet<MapId> _pausedMaps = new();
[ViewVariables] private readonly HashSet<MapId> _unInitializedMaps = new();
public void SetMapPaused(MapId mapId, bool paused)
{
if (paused)
{
_pausedMaps.Add(mapId);
foreach (var entity in _entityManager.GetEntitiesInMap(mapId))
{
entity.Paused = true;
}
}
else
{
_pausedMaps.Remove(mapId);
foreach (var entity in _entityManager.GetEntitiesInMap(mapId))
{
entity.Paused = false;
}
}
}
public void DoMapInitialize(MapId mapId)
{
if (IsMapInitialized(mapId))
{
throw new ArgumentException("That map is already initialized.");
}
_unInitializedMaps.Remove(mapId);
foreach (var entity in _entityManager.GetEntitiesInMap(mapId))
{
entity.RunMapInit();
entity.Paused = false;
}
}
public void DoGridMapInitialize(IMapGrid grid) => DoGridMapInitialize(grid.Index);
public void DoGridMapInitialize(GridId gridId)
{
var mapId = _mapManager.GetGrid(gridId).ParentMapId;
foreach (var entity in _entityManager.GetEntitiesInMap(mapId))
{
if (entity.Transform.GridID != gridId)
continue;
entity.RunMapInit();
entity.Paused = false;
}
}
public void AddUninitializedMap(MapId mapId)
{
_unInitializedMaps.Add(mapId);
}
public bool IsMapPaused(MapId mapId) => _pausedMaps.Contains(mapId) || _unInitializedMaps.Contains(mapId);
public bool IsGridPaused(IMapGrid grid) => IsMapPaused(grid.ParentMapId);
public bool IsGridPaused(GridId gridId)
{
var grid = _mapManager.GetGrid(gridId);
return IsGridPaused(grid);
}
public bool IsMapInitialized(MapId mapId)
{
return !_unInitializedMaps.Contains(mapId);
}
public void PostInject()
{
_mapManager.MapDestroyed += (sender, args) =>
{
_pausedMaps.Remove(args.Map);
_unInitializedMaps.Add(args.Map);
};
}
}
}

View File

@@ -1,16 +0,0 @@
using System;
using JetBrains.Annotations;
using Robust.Shared.GameObjects;
namespace Robust.Server.Timing
{
public static class PauseManagerExt
{
[Pure]
[Obsolete("Use IEntity.Paused directly")]
public static bool IsEntityPaused(this IPauseManager manager, IEntity entity)
{
return entity.Paused;
}
}
}

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

@@ -330,6 +330,7 @@ Types:
System.Globalization:
CompareOptions: { }
CultureInfo: { All: True }
DateTimeStyles: { All: True } # Enum
TextInfo:
Methods:
- "bool get_IsRightToLeft()"

View File

@@ -202,8 +202,9 @@ namespace Robust.Shared.GameObjects
/// <inheritdoc />
public virtual void HandleNetworkMessage(ComponentMessage message, INetChannel netChannel, ICommonSession? session = null) { }
/// <param name="player"></param>
/// <inheritdoc />
public virtual ComponentState GetComponentState()
public virtual ComponentState GetComponentState(ICommonSession player)
{
if (NetID == null)
throw new InvalidOperationException($"Cannot make state for component without Net ID: {GetType()}");

View File

@@ -5,6 +5,7 @@ using Robust.Shared.IoC;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Physics;
using Robust.Shared.Players;
using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables;
@@ -132,8 +133,9 @@ namespace Robust.Shared.GameObjects
serializer.DataField(ref _mass, "mass", 1.0f);
}
/// <param name="player"></param>
/// <inheritdoc />
public override ComponentState GetComponentState()
public override ComponentState GetComponentState(ICommonSession player)
{
return new PhysicsComponentState(_canCollide, _status, _physShapes, _isHard, _mass, LinearVelocity, AngularVelocity, Anchored);
}

View File

@@ -1,5 +1,6 @@
using System;
using Robust.Shared.Localization.Macros;
using Robust.Shared.Players;
using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables;
@@ -33,7 +34,7 @@ namespace Robust.Shared.GameObjects
serializer.DataField(this, x => x.Proper, "proper", false);
}
public override ComponentState GetComponentState()
public override ComponentState GetComponentState(ICommonSession player)
{
return new GrammarComponentState(Proper);
}

View File

@@ -1,13 +1,13 @@
using Robust.Server.Timing;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Timing;
namespace Robust.Server.GameObjects
namespace Robust.Shared.GameObjects
{
[RegisterComponent]
[ComponentReference(typeof(SharedIgnorePauseComponent))]
public sealed class IgnorePauseComponent : SharedIgnorePauseComponent
public class IgnorePauseComponent : Component
{
public override string Name => "IgnorePause";
public override void OnAdd()
{
base.OnAdd();

View File

@@ -1,6 +1,7 @@
using System;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Players;
using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables;
@@ -73,7 +74,7 @@ namespace Robust.Shared.GameObjects
}
}
public override ComponentState GetComponentState()
public override ComponentState GetComponentState(ICommonSession player)
{
return new OccluderComponentState(Enabled, BoundingBox);
}

View File

@@ -1,5 +1,6 @@
using System;
using Robust.Shared.Map;
using Robust.Shared.Players;
using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables;
@@ -39,8 +40,9 @@ namespace Robust.Shared.GameObjects
_mapIndex = MapId.Nullspace;
}
/// <param name="player"></param>
/// <inheritdoc />
public override ComponentState GetComponentState()
public override ComponentState GetComponentState(ICommonSession player)
{
return new MapComponentState(_mapIndex);
}

View File

@@ -2,6 +2,7 @@
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Map;
using Robust.Shared.Players;
using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables;
@@ -61,8 +62,9 @@ namespace Robust.Shared.GameObjects
base.OnRemove();
}
/// <param name="player"></param>
/// <inheritdoc />
public override ComponentState GetComponentState()
public override ComponentState GetComponentState(ICommonSession player)
{
return new MapGridComponentState(_gridIndex, Grid.HasGravity);
}

View File

@@ -1,5 +1,6 @@
using System;
using Robust.Shared.IoC;
using Robust.Shared.Players;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables;
@@ -137,8 +138,9 @@ namespace Robust.Shared.GameObjects
}
}
/// <param name="player"></param>
/// <inheritdoc />
public override ComponentState GetComponentState()
public override ComponentState GetComponentState(ICommonSession player)
{
return new MetaDataComponentState(_entityName, _entityDescription, EntityPrototype?.ID);
}

View File

@@ -1,7 +0,0 @@
namespace Robust.Shared.GameObjects
{
public abstract class SharedIgnorePauseComponent : Component
{
public override string Name => "IgnorePause";
}
}

View File

@@ -4,7 +4,7 @@ using System.Threading;
using System.Threading.Tasks;
using Robust.Shared.Exceptions;
using Robust.Shared.IoC;
using Timer = Robust.Shared.Timers.Timer;
using Timer = Robust.Shared.Timing.Timer;
namespace Robust.Shared.GameObjects
{

View File

@@ -1,7 +1,7 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Timer = Robust.Shared.Timers.Timer;
using Timer = Robust.Shared.Timing.Timer;
namespace Robust.Shared.GameObjects
{

View File

@@ -6,6 +6,7 @@ using Robust.Shared.Containers;
using Robust.Shared.IoC;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Players;
using Robust.Shared.Serialization;
using Robust.Shared.Utility;
using Robust.Shared.ViewVariables;
@@ -698,8 +699,9 @@ namespace Robust.Shared.GameObjects
serializer.DataField(ref _noLocalRotation, "noRot", false);
}
/// <param name="player"></param>
/// <inheritdoc />
public override ComponentState GetComponentState()
public override ComponentState GetComponentState(ICommonSession player)
{
return new TransformComponentState(_localPosition, LocalRotation, _parent, _noLocalRotation);
}

View File

@@ -79,7 +79,7 @@ namespace Robust.Shared.GameObjects
get => _paused;
set
{
if (_paused == value || value && HasComponent<SharedIgnorePauseComponent>())
if (_paused == value || value && HasComponent<IgnorePauseComponent>())
return;
_paused = value;

View File

@@ -32,7 +32,7 @@ namespace Robust.Shared.GameObjects
/// Whether the Owner has been paused.
/// </summary>
bool Paused { get; }
/// <summary>
/// Whether the client should synchronize component additions and removals.
/// If this is false and the component gets added or removed server side, the client will not do the same.
@@ -125,8 +125,9 @@ namespace Robust.Shared.GameObjects
/// <summary>
/// Get the component's state for replicating on the client.
/// </summary>
/// <param name="player"></param>
/// <returns>ComponentState object</returns>
ComponentState GetComponentState();
ComponentState GetComponentState(ICommonSession player);
/// <summary>
/// Handles an incoming component state from the server.

View File

@@ -1,11 +1,9 @@
using Robust.Shared.GameObjects;
namespace Robust.Server.GameObjects
namespace Robust.Shared.GameObjects
{
/// <summary>
/// Defines a component that has "map initialization" behavior.
/// Basically irreversible behavior that moves the map from "map editor" to playable,
/// like spawning preset objects.
/// Defines a component that has "map initialization" behavior.
/// Basically irreversible behavior that moves the map from "map editor" to playable,
/// like spawning preset objects.
/// </summary>
public interface IMapInit
{

View File

@@ -179,9 +179,33 @@ 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);
}
}
if (connection.Status == NetConnectionStatus.Disconnecting ||
connection.Status == NetConnectionStatus.Disconnected)
{
Logger.InfoS("net",
"{ConnectionEndpoint} disconnected during handshake",
connection.RemoteEndPoint, userName, userId);
return;
}
var msg = peer.Peer.CreateMessage();
@@ -242,8 +266,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

@@ -56,6 +56,7 @@ namespace Robust.Shared.Prototypes
/// </summary>
void LoadDirectory(ResourcePath path);
void LoadFromStream(TextReader stream);
void LoadString(string str);
/// <summary>
/// Clear out all prototypes and reset to a blank slate.
/// </summary>
@@ -273,6 +274,11 @@ namespace Robust.Shared.Prototypes
LoadedData?.Invoke(yaml, "anonymous prototypes YAML stream");
}
public void LoadString(string str)
{
LoadFromStream(new StreamReader(str));
}
#endregion IPrototypeManager members
public void PostInject()

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;
@@ -38,6 +39,7 @@ namespace Robust.Shared.Serialization
{
{ typeof(Color), new ColorSerializer() },
{ typeof(Vector2), new Vector2Serializer() },
{ typeof(Vector2i), new Vector2iSerializer() },
{ typeof(Vector3), new Vector3Serializer() },
{ typeof(Vector4), new Vector4Serializer() },
{ typeof(Angle), new AngleSerializer() },
@@ -510,6 +512,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 +745,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 +905,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 +1068,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<,>);
@@ -1289,6 +1347,20 @@ namespace Robust.Shared.Serialization
}
}
class Vector2iSerializer : TypeSerializer
{
public override object NodeToType(Type type, YamlNode node, YamlObjectSerializer serializer)
{
return node.AsVector2i();
}
public override YamlNode TypeToNode(object obj, YamlObjectSerializer serializer)
{
var vec = (Vector2i)obj;
return new YamlScalarNode($"{vec.X.ToString(CultureInfo.InvariantCulture)},{vec.Y.ToString(CultureInfo.InvariantCulture)}");
}
}
class Vector3Serializer : TypeSerializer
{
public override object NodeToType(Type type, YamlNode node, YamlObjectSerializer serializer)

View File

@@ -13,7 +13,6 @@ using Robust.Shared.Physics;
using Robust.Shared.Random;
using Robust.Shared.Sandboxing;
using Robust.Shared.Serialization;
using Robust.Shared.Timers;
using Robust.Shared.Timing;
namespace Robust.Shared
@@ -35,6 +34,7 @@ namespace Robust.Shared
IoCManager.Register<ILogManager, LogManager>();
IoCManager.Register<IMapManager, MapManager>();
IoCManager.Register<IMapManagerInternal, MapManager>();
IoCManager.Register<IPauseManager, PauseManager>();
IoCManager.Register<IModLoader, ModLoader>();
IoCManager.Register<IModLoaderInternal, ModLoader>();
IoCManager.Register<INetManager, NetManager>();

View File

@@ -1,7 +1,7 @@
using JetBrains.Annotations;
using JetBrains.Annotations;
using Robust.Shared.Map;
namespace Robust.Server.Timing
namespace Robust.Shared.Timing
{
public interface IPauseManager
{
@@ -26,4 +26,4 @@ namespace Robust.Server.Timing
[Pure]
bool IsMapInitialized(MapId mapId);
}
}
}

View File

@@ -1,7 +1,6 @@
using System.Threading;
using Robust.Shared.Timing;
namespace Robust.Shared.Timers
namespace Robust.Shared.Timing
{
public interface ITimerManager
{

View File

@@ -0,0 +1,179 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using Robust.Shared.Console;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Map;
using Robust.Shared.ViewVariables;
namespace Robust.Shared.Timing
{
internal sealed class PauseManager : IPauseManager, IPostInjectInit
{
[Dependency] private readonly IConsoleHost _conhost = default!;
[Dependency] private readonly IEntityManager _entityManager = default!;
[Dependency] private readonly IMapManager _mapManager = default!;
[ViewVariables] private readonly HashSet<MapId> _pausedMaps = new();
[ViewVariables] private readonly HashSet<MapId> _unInitializedMaps = new();
public void SetMapPaused(MapId mapId, bool paused)
{
if (paused)
{
_pausedMaps.Add(mapId);
foreach (var entity in _entityManager.GetEntitiesInMap(mapId))
{
entity.Paused = true;
}
}
else
{
_pausedMaps.Remove(mapId);
foreach (var entity in _entityManager.GetEntitiesInMap(mapId))
{
entity.Paused = false;
}
}
}
public void DoMapInitialize(MapId mapId)
{
if (IsMapInitialized(mapId))
throw new ArgumentException("That map is already initialized.");
_unInitializedMaps.Remove(mapId);
foreach (var entity in _entityManager.GetEntitiesInMap(mapId))
{
entity.RunMapInit();
entity.Paused = false;
}
}
public void DoGridMapInitialize(IMapGrid grid)
{
DoGridMapInitialize(grid.Index);
}
public void DoGridMapInitialize(GridId gridId)
{
var mapId = _mapManager.GetGrid(gridId).ParentMapId;
foreach (var entity in _entityManager.GetEntitiesInMap(mapId))
{
if (entity.Transform.GridID != gridId)
continue;
entity.RunMapInit();
entity.Paused = false;
}
}
public void AddUninitializedMap(MapId mapId)
{
_unInitializedMaps.Add(mapId);
}
public bool IsMapPaused(MapId mapId)
{
return _pausedMaps.Contains(mapId) || _unInitializedMaps.Contains(mapId);
}
public bool IsGridPaused(IMapGrid grid)
{
return IsMapPaused(grid.ParentMapId);
}
public bool IsGridPaused(GridId gridId)
{
var grid = _mapManager.GetGrid(gridId);
return IsGridPaused(grid);
}
public bool IsMapInitialized(MapId mapId)
{
return !_unInitializedMaps.Contains(mapId);
}
/// <inheritdoc />
public void PostInject()
{
_mapManager.MapDestroyed += (_, args) =>
{
_pausedMaps.Remove(args.Map);
_unInitializedMaps.Add(args.Map);
};
if(_conhost.IsClient)
return;
_conhost.RegisterCommand("pausemap",
"Pauses a map, pausing all simulation processing on it.",
"pausemap <map ID>",
(shell, _, args) =>
{
if (args.Length != 1)
{
shell.WriteError("Need to supply a valid MapId");
return;
}
string? arg = args[0];
var mapId = new MapId(int.Parse(arg, CultureInfo.InvariantCulture));
if (!_mapManager.MapExists(mapId))
{
shell.WriteError("That map does not exist.");
return;
}
SetMapPaused(mapId, true);
});
_conhost.RegisterCommand("querymappaused",
"Check whether a map is paused or not.",
"querymappaused <map ID>",
(shell, _, args) =>
{
string? arg = args[0];
var mapId = new MapId(int.Parse(arg, CultureInfo.InvariantCulture));
if (!_mapManager.MapExists(mapId))
{
shell.WriteError("That map does not exist.");
return;
}
shell.WriteLine(IsMapPaused(mapId).ToString());
});
_conhost.RegisterCommand("unpausemap",
"unpauses a map, resuming all simulation processing on it.",
"Usage: unpausemap <map ID>",
(shell, _, args) =>
{
if (args.Length != 1)
{
shell.WriteLine(Loc.GetString("Need to supply a valid MapId"));
return;
}
string? arg = args[0];
var mapId = new MapId(int.Parse(arg, CultureInfo.InvariantCulture));
if (!_mapManager.MapExists(mapId))
{
shell.WriteLine("That map does not exist.");
return;
}
SetMapPaused(mapId, false);
});
}
}
}

View File

@@ -4,7 +4,7 @@ using System.Threading.Tasks;
using Robust.Shared.Exceptions;
using Robust.Shared.IoC;
namespace Robust.Shared.Timers
namespace Robust.Shared.Timing
{
public class Timer
{

View File

@@ -2,9 +2,8 @@
using System.Threading;
using Robust.Shared.Exceptions;
using Robust.Shared.IoC;
using Robust.Shared.Timing;
namespace Robust.Shared.Timers
namespace Robust.Shared.Timing
{
internal sealed class TimerManager : ITimerManager
{

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

View File

@@ -4,11 +4,10 @@ using NUnit.Framework;
using Robust.Shared.Asynchronous;
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Timers;
using Robust.Shared.Timing;
using Timer = Robust.Shared.Timers.Timer;
using Timer = Robust.Shared.Timing.Timer;
namespace Robust.UnitTesting.Shared.Timers
namespace Robust.UnitTesting.Shared.Timing
{
[TestFixture]
[TestOf(typeof(Timer))]