mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-15 03:30:53 +01:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b67d24efee | ||
|
|
d992e47f30 | ||
|
|
dadd7b4cc3 | ||
|
|
baef2bc7f8 | ||
|
|
e0b1a7d64a | ||
|
|
aea5f83002 | ||
|
|
7df2d1f430 | ||
|
|
d216c3a1f6 | ||
|
|
986ec3ef06 | ||
|
|
60cec9cb84 |
@@ -4,4 +4,8 @@ entity-spawn-window-title = Entity Spawn Panel
|
||||
entity-spawn-window-search-bar-placeholder = search
|
||||
entity-spawn-window-clear-button = Clear
|
||||
entity-spawn-window-erase-button-text = Erase Mode
|
||||
entity-spawn-window-override-menu-tooltip = Override placement
|
||||
entity-spawn-window-override-menu-tooltip = Override placement
|
||||
|
||||
## Console
|
||||
|
||||
console-line-edit-placeholder = Command Here
|
||||
|
||||
@@ -46,13 +46,15 @@ namespace Robust.Client
|
||||
IoCManager.Register<IClientMapManager, ClientMapManager>();
|
||||
IoCManager.Register<IEntityManager, ClientEntityManager>();
|
||||
IoCManager.Register<IEntityLookup, EntityLookup>();
|
||||
IoCManager.Register<IReflectionManager, ClientReflectionManager>();
|
||||
IoCManager.Register<IConsoleHost, ClientConsoleHost>();
|
||||
IoCManager.Register<IClientConsoleHost, ClientConsoleHost>();
|
||||
IoCManager.Register<IComponentFactory, ClientComponentFactory>();
|
||||
IoCManager.Register<ITileDefinitionManager, ClydeTileDefinitionManager>();
|
||||
IoCManager.Register<IClydeTileDefinitionManager, ClydeTileDefinitionManager>();
|
||||
IoCManager.Register<GameController, GameController>();
|
||||
IoCManager.Register<IGameController, GameController>();
|
||||
IoCManager.Register<IGameControllerInternal, GameController>();
|
||||
IoCManager.Register<IReflectionManager, ClientReflectionManager>();
|
||||
IoCManager.Register<IResourceManager, ResourceCache>();
|
||||
IoCManager.Register<IResourceManagerInternal, ResourceCache>();
|
||||
IoCManager.Register<IResourceCache, ResourceCache>();
|
||||
@@ -72,8 +74,6 @@ namespace Robust.Client
|
||||
IoCManager.Register<IDebugDrawingManager, DebugDrawingManager>();
|
||||
IoCManager.Register<ILightManager, LightManager>();
|
||||
IoCManager.Register<IDiscordRichPresence, DiscordRichPresence>();
|
||||
IoCManager.Register<IClientConsoleHost, ClientConsoleHost>();
|
||||
IoCManager.Register<IConsoleHost, ClientConsoleHost>();
|
||||
IoCManager.Register<IMidiManager, MidiManager>();
|
||||
IoCManager.Register<IAuthManager, AuthManager>();
|
||||
switch (mode)
|
||||
|
||||
@@ -49,7 +49,11 @@ namespace Robust.Client.Console
|
||||
NetManager.RegisterNetMessage<MsgConCmdAck>(HandleConCmdAck);
|
||||
NetManager.RegisterNetMessage<MsgConCmd>(ProcessCommand);
|
||||
|
||||
Reset();
|
||||
_requestedCommands = false;
|
||||
NetManager.Connected += OnNetworkConnected;
|
||||
|
||||
LoadConsoleCommands();
|
||||
SendServerCommandRequest();
|
||||
LogManager.RootSawmill.AddHandler(new DebugConsoleLogHandler(this));
|
||||
}
|
||||
|
||||
@@ -61,17 +65,6 @@ namespace Robust.Client.Console
|
||||
ExecuteCommand(null, text);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Reset()
|
||||
{
|
||||
AvailableCommands.Clear();
|
||||
_requestedCommands = false;
|
||||
NetManager.Connected += OnNetworkConnected;
|
||||
|
||||
LoadConsoleCommands();
|
||||
SendServerCommandRequest();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public event EventHandler<AddStringArgs>? AddString;
|
||||
|
||||
@@ -97,7 +90,7 @@ namespace Robust.Client.Console
|
||||
return;
|
||||
|
||||
// echo the command locally
|
||||
WriteError(null, "> " + command);
|
||||
WriteLine(null, "> " + command);
|
||||
|
||||
//Commands are processed locally and then sent to the server to be processed there again.
|
||||
var args = new List<string>();
|
||||
@@ -142,6 +135,9 @@ namespace Robust.Client.Console
|
||||
private void OutputText(string text, bool local, bool error)
|
||||
{
|
||||
AddString?.Invoke(this, new AddStringArgs(text, local, error));
|
||||
|
||||
var level = error ? LogLevel.Warning : LogLevel.Info;
|
||||
Logger.LogS(level, "CON", text);
|
||||
}
|
||||
|
||||
private void OnNetworkConnected(object? sender, NetChannelArgs netChannelArgs)
|
||||
|
||||
@@ -77,7 +77,7 @@ namespace Robust.Client.Console.Commands
|
||||
message.Append($"net ID: {registration.NetID}");
|
||||
}
|
||||
|
||||
message.Append($", NSE: {registration.NetworkSynchronizeExistence}, references:");
|
||||
message.Append($", References:");
|
||||
|
||||
shell.WriteLine(message.ToString());
|
||||
|
||||
|
||||
@@ -11,11 +11,6 @@ namespace Robust.Client.Console
|
||||
/// </summary>
|
||||
void Initialize();
|
||||
|
||||
/// <summary>
|
||||
/// Resets the console to a post-initialized state.
|
||||
/// </summary>
|
||||
void Reset();
|
||||
|
||||
event EventHandler<AddStringArgs> AddString;
|
||||
event EventHandler<AddFormattedMessageArgs> AddFormatted;
|
||||
|
||||
|
||||
@@ -177,8 +177,9 @@ namespace Robust.Client.Debugging
|
||||
foreach (var fixture in physBody.Fixtures)
|
||||
{
|
||||
var shape = fixture.Shape;
|
||||
var sleepPercent = physBody.Awake ? physBody.SleepTime / sleepThreshold : 1.0f;
|
||||
var sleepPercent = physBody.Awake ? 0.0f : 1.0f;
|
||||
shape.DebugDraw(drawing, transform.WorldMatrix, in viewport, sleepPercent);
|
||||
drawing.SetTransform(in Matrix3.Identity);
|
||||
}
|
||||
|
||||
foreach (var joint in physBody.Joints)
|
||||
@@ -187,6 +188,7 @@ namespace Robust.Client.Debugging
|
||||
drawnJoints.Add(joint);
|
||||
|
||||
joint.DebugDraw(drawing, in viewport);
|
||||
drawing.SetTransform(in Matrix3.Identity);
|
||||
}
|
||||
|
||||
if (worldBox.Contains(mouseWorldPos))
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Reflection;
|
||||
|
||||
namespace Robust.Client.GameObjects
|
||||
{
|
||||
public class ClientComponentFactory : ComponentFactory
|
||||
internal class ClientComponentFactory : ComponentFactory
|
||||
{
|
||||
public ClientComponentFactory()
|
||||
public ClientComponentFactory(IDynamicTypeFactoryInternal typeFactory, IReflectionManager reflectionManager, IConsoleHost conHost)
|
||||
: base(typeFactory, reflectionManager, conHost)
|
||||
{
|
||||
// Required for the engine to work
|
||||
RegisterIgnore("KeyBindingInput");
|
||||
|
||||
@@ -109,13 +109,15 @@ namespace Robust.Client.GameObjects
|
||||
[Obsolete("Component Messages are deprecated, use Entity Events instead.")]
|
||||
public void SendComponentNetworkMessage(INetChannel? channel, IEntity entity, IComponent component, ComponentMessage message)
|
||||
{
|
||||
if (!component.NetID.HasValue)
|
||||
var netId = ComponentFactory.GetRegistration(component.GetType()).NetID;
|
||||
|
||||
if (!netId.HasValue)
|
||||
throw new ArgumentException($"Component {component.Name} does not have a NetID.", nameof(component));
|
||||
|
||||
var msg = _networkManager.CreateNetMessage<MsgEntity>();
|
||||
msg.Type = EntityMessageType.ComponentMessage;
|
||||
msg.EntityUid = entity.Uid;
|
||||
msg.NetId = component.NetID.Value;
|
||||
msg.NetId = netId.Value;
|
||||
msg.ComponentMessage = message;
|
||||
msg.SourceTick = _gameTiming.CurTick;
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ using Robust.Client.ResourceManagement;
|
||||
using Robust.Shared.Animations;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Map;
|
||||
@@ -17,12 +18,12 @@ namespace Robust.Client.GameObjects
|
||||
{
|
||||
[RegisterComponent]
|
||||
[ComponentReference(typeof(IPointLightComponent))]
|
||||
[NetworkedComponent()]
|
||||
public class PointLightComponent : Component, IPointLightComponent, ISerializationHooks
|
||||
{
|
||||
[Dependency] private readonly IResourceCache _resourceCache = default!;
|
||||
|
||||
public override string Name => "PointLight";
|
||||
public override uint? NetID => NetIDs.POINT_LIGHT;
|
||||
|
||||
internal bool TreeUpdateQueued { get; set; }
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Input;
|
||||
using Robust.Client.Map;
|
||||
@@ -25,6 +26,7 @@ using Robust.Shared.Utility;
|
||||
namespace Robust.Client.GameStates
|
||||
{
|
||||
/// <inheritdoc />
|
||||
[UsedImplicitly]
|
||||
public class ClientGameStateManager : IClientGameStateManager
|
||||
{
|
||||
private GameStateProcessor _processor = default!;
|
||||
@@ -36,6 +38,8 @@ namespace Robust.Client.GameStates
|
||||
_pendingSystemMessages
|
||||
= new();
|
||||
|
||||
private uint _metaCompNetId;
|
||||
|
||||
[Dependency] private readonly IComponentFactory _compFactory = default!;
|
||||
[Dependency] private readonly IClientEntityManagerInternal _entities = default!;
|
||||
[Dependency] private readonly IEntityLookup _lookup = default!;
|
||||
@@ -99,6 +103,12 @@ namespace Robust.Client.GameStates
|
||||
Predicting = _config.GetCVar(CVars.NetPredict);
|
||||
PredictTickBias = _config.GetCVar(CVars.NetPredictTickBias);
|
||||
PredictLagBias = _config.GetCVar(CVars.NetPredictLagBias);
|
||||
|
||||
var metaId = _compFactory.GetRegistration(typeof(MetaDataComponent)).NetID;
|
||||
if (!metaId.HasValue)
|
||||
throw new InvalidOperationException("MetaDataComponent does not have a NetId.");
|
||||
|
||||
_metaCompNetId = metaId.Value;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -343,11 +353,11 @@ namespace Robust.Client.GameStates
|
||||
}
|
||||
|
||||
// TODO: handle component deletions/creations.
|
||||
foreach (var comp in _componentManager.GetNetComponents(entity.Uid))
|
||||
foreach (var (netId, comp) in _componentManager.GetNetComponents(entity.Uid))
|
||||
{
|
||||
DebugTools.AssertNotNull(comp.NetID);
|
||||
DebugTools.AssertNotNull(netId);
|
||||
|
||||
if (comp.LastModifiedTick < curTick || !last.TryGetValue(comp.NetID!.Value, out var compState))
|
||||
if (comp.LastModifiedTick < curTick || !last.TryGetValue(netId, out var compState))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -368,24 +378,22 @@ namespace Robust.Client.GameStates
|
||||
// so that we can later roll back to it (if necessary).
|
||||
var outputData = new Dictionary<EntityUid, Dictionary<uint, ComponentState>>();
|
||||
|
||||
Debug.Assert(_players.LocalPlayer != null, "_players.LocalPlayer != null");
|
||||
var player = _players.LocalPlayer.Session;
|
||||
|
||||
foreach (var createdEntity in createdEntities)
|
||||
{
|
||||
var compData = new Dictionary<uint, ComponentState>();
|
||||
outputData.Add(createdEntity, compData);
|
||||
|
||||
foreach (var component in _componentManager.GetNetComponents(createdEntity))
|
||||
foreach (var (netId, component) in _componentManager.GetNetComponents(createdEntity))
|
||||
{
|
||||
Debug.Assert(_players.LocalPlayer != null, "_players.LocalPlayer != null");
|
||||
|
||||
var player = _players.LocalPlayer.Session;
|
||||
var state = component.GetComponentState(player);
|
||||
|
||||
if (state.GetType() == typeof(ComponentState))
|
||||
{
|
||||
if(state.GetType() == typeof(ComponentState))
|
||||
continue;
|
||||
}
|
||||
|
||||
compData.Add(state.NetID, state);
|
||||
compData.Add(netId, state);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -432,8 +440,7 @@ namespace Robust.Client.GameStates
|
||||
}
|
||||
else //Unknown entities
|
||||
{
|
||||
var metaState = (MetaDataComponentState?) es.ComponentStates
|
||||
?.FirstOrDefault(c => c.NetID == NetIDs.META_DATA);
|
||||
var metaState = (MetaDataComponentState?) es.ComponentChanges?.FirstOrDefault(c => c.NetID == _metaCompNetId).State;
|
||||
if (metaState == null)
|
||||
{
|
||||
throw new InvalidOperationException($"Server sent new entity state for {es.Uid} without metadata component!");
|
||||
@@ -543,7 +550,7 @@ namespace Robust.Client.GameStates
|
||||
private void HandleEntityState(IComponentManager compMan, IEntity entity, EntityEventBus bus, EntityState? curState,
|
||||
EntityState? nextState)
|
||||
{
|
||||
var compStateWork = new Dictionary<uint, (ComponentState? curState, ComponentState? nextState)>();
|
||||
var compStateWork = new Dictionary<ushort, (ComponentState? curState, ComponentState? nextState)>();
|
||||
var entityUid = entity.Uid;
|
||||
|
||||
if (curState?.ComponentChanges != null)
|
||||
@@ -559,42 +566,46 @@ namespace Robust.Client.GameStates
|
||||
}
|
||||
else
|
||||
{
|
||||
//Right now we just assume every state from an unseen entity is added
|
||||
|
||||
if (compMan.HasComponent(entityUid, compChange.NetID))
|
||||
continue;
|
||||
|
||||
var newComp = (Component) _compFactory.GetComponent(compChange.ComponentName!);
|
||||
var newComp = (Component) _compFactory.GetComponent(compChange.NetID);
|
||||
newComp.Owner = entity;
|
||||
compMan.AddComponent(entity, newComp, true);
|
||||
|
||||
compStateWork[compChange.NetID] = (compChange.State, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (curState?.ComponentStates != null)
|
||||
if (curState?.ComponentChanges != null)
|
||||
{
|
||||
foreach (var compState in curState.ComponentStates)
|
||||
foreach (var compChange in curState.ComponentChanges)
|
||||
{
|
||||
compStateWork[compState.NetID] = (compState, null);
|
||||
compStateWork[compChange.NetID] = (compChange.State, null);
|
||||
}
|
||||
}
|
||||
|
||||
if (nextState?.ComponentStates != null)
|
||||
if (nextState?.ComponentChanges != null)
|
||||
{
|
||||
foreach (var compState in nextState.ComponentStates)
|
||||
foreach (var compState in nextState.ComponentChanges)
|
||||
{
|
||||
if (compStateWork.TryGetValue(compState.NetID, out var state))
|
||||
{
|
||||
compStateWork[compState.NetID] = (state.curState, compState);
|
||||
compStateWork[compState.NetID] = (state.curState, compState.State);
|
||||
}
|
||||
else
|
||||
{
|
||||
compStateWork[compState.NetID] = (null, compState);
|
||||
compStateWork[compState.NetID] = (null, compState.State);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var (netId, (cur, next)) in compStateWork)
|
||||
{
|
||||
if (compMan.TryGetComponent(entityUid, netId, out var component))
|
||||
if (compMan.TryGetComponent(entityUid, (ushort) netId, out var component))
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using Robust.Shared.GameObjects;
|
||||
@@ -195,14 +195,10 @@ namespace Robust.Client.GameStates
|
||||
{
|
||||
compData.Remove(change.NetID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (entityState.ComponentStates != null)
|
||||
{
|
||||
foreach (var compState in entityState.ComponentStates)
|
||||
{
|
||||
compData[compState.NetID] = compState;
|
||||
else if (change.State is not null)
|
||||
{
|
||||
compData[change.NetID] = change.State;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ namespace Robust.Client.GameStates
|
||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||
[Dependency] private readonly IClientNetManager _netManager = default!;
|
||||
[Dependency] private readonly IClientGameStateManager _gameStateManager = default!;
|
||||
[Dependency] private readonly IComponentFactory _componentFactory = default!;
|
||||
|
||||
private const int HistorySize = 60 * 3; // number of ticks to keep in history.
|
||||
private const int TargetPayloadBps = 56000 / 8; // Target Payload size in Bytes per second. A mind-numbing fifty-six thousand bits per second, who would ever need more?
|
||||
@@ -90,17 +91,14 @@ namespace Robust.Client.GameStates
|
||||
sb.Append($"\n Changes:");
|
||||
foreach (var compChange in entState.ComponentChanges)
|
||||
{
|
||||
var del = compChange.Deleted ? 'D' : 'C';
|
||||
sb.Append($"\n [{del}]{compChange.NetID}:{compChange.ComponentName}");
|
||||
}
|
||||
}
|
||||
var registration = _componentFactory.GetRegistration(compChange.NetID);
|
||||
var create = compChange.Created ? 'C' : '\0';
|
||||
var mod = !(compChange.Created || compChange.Created) ? 'M' : '\0';
|
||||
var del = compChange.Deleted ? 'D' : '\0';
|
||||
sb.Append($"\n [{create}{mod}{del}]{compChange.NetID}:{registration.Name}");
|
||||
|
||||
if (entState.ComponentStates is not null)
|
||||
{
|
||||
sb.Append($"\n States:");
|
||||
foreach (var compState in entState.ComponentStates)
|
||||
{
|
||||
sb.Append($"\n {compState.NetID}:{compState.GetType().Name}");
|
||||
if(compChange.State is not null)
|
||||
sb.Append($"\n STATE:{compChange.State.GetType().Name}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,12 +32,12 @@ namespace Robust.Client.Map
|
||||
//get shared euid of map comp entity
|
||||
foreach (var entityState in entityStates!)
|
||||
{
|
||||
if(entityState.ComponentStates is null)
|
||||
if(entityState.ComponentChanges is null)
|
||||
continue;
|
||||
|
||||
foreach (var compState in entityState.ComponentStates)
|
||||
foreach (var compChange in entityState.ComponentChanges)
|
||||
{
|
||||
if (compState is not MapComponentState mapCompState || mapCompState.MapId != mapId)
|
||||
if (compChange.State is not MapComponentState mapCompState || mapCompState.MapId != mapId)
|
||||
continue;
|
||||
|
||||
mapEuid = entityState.Uid;
|
||||
@@ -67,12 +67,12 @@ namespace Robust.Client.Map
|
||||
//get shared euid of map comp entity
|
||||
foreach (var entityState in entityStates!)
|
||||
{
|
||||
if(entityState.ComponentStates is null)
|
||||
if (entityState.ComponentChanges is null)
|
||||
continue;
|
||||
|
||||
foreach (var compState in entityState.ComponentStates)
|
||||
foreach (var compState in entityState.ComponentChanges)
|
||||
{
|
||||
if (compState is not MapGridComponentState gridCompState || gridCompState.GridIndex != gridId)
|
||||
if (compState.State is not MapGridComponentState gridCompState || gridCompState.GridIndex != gridId)
|
||||
continue;
|
||||
|
||||
gridEuid = entityState.Uid;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.ResourceManagement;
|
||||
@@ -17,7 +18,7 @@ namespace Robust.Client.Map
|
||||
[Dependency] private readonly IResourceCache _resourceCache = default!;
|
||||
|
||||
private Texture? _tileTextureAtlas;
|
||||
|
||||
|
||||
public Texture TileTextureAtlas => _tileTextureAtlas ?? Texture.Transparent;
|
||||
|
||||
private readonly Dictionary<ushort, Box2> _tileRegions = new();
|
||||
@@ -61,7 +62,7 @@ namespace Robust.Client.Map
|
||||
var row = i / dimensionX;
|
||||
|
||||
Image<Rgba32> image;
|
||||
using (var stream = _resourceCache.ContentFileRead($"/Textures/Constructible/Tiles/{def.SpriteName}.png"))
|
||||
using (var stream = _resourceCache.ContentFileRead(Path.Join(def.Path, $"{def.SpriteName}.png")))
|
||||
{
|
||||
image = Image.Load<Rgba32>(stream);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace Robust.Client.UserInterface.Controls
|
||||
{
|
||||
public Label Label { get; }
|
||||
|
||||
public Button() : base()
|
||||
public Button()
|
||||
{
|
||||
AddStyleClass(StyleClassButton);
|
||||
Label = new Label
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace Robust.Client.UserInterface.Controls
|
||||
public Label Label { get; }
|
||||
public TextureRect TextureRect { get; }
|
||||
|
||||
public CheckBox() : base()
|
||||
public CheckBox()
|
||||
{
|
||||
ToggleMode = true;
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace Robust.Client.UserInterface.Controls
|
||||
public const string StylePseudoClassHover = "hover";
|
||||
public const string StylePseudoClassDisabled = "disabled";
|
||||
|
||||
public ContainerButton() : base()
|
||||
public ContainerButton()
|
||||
{
|
||||
DrawModeChanged();
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace Robust.Client.UserInterface.Controls
|
||||
|
||||
public event EventHandler<ValueChangedEventArgs>? ValueChanged;
|
||||
|
||||
public SpinBox() : base()
|
||||
public SpinBox()
|
||||
{
|
||||
MouseFilter = MouseFilterMode.Pass;
|
||||
|
||||
|
||||
@@ -33,6 +33,9 @@ namespace Robust.Client.ViewVariables
|
||||
var valArg = args[0];
|
||||
if (valArg.StartsWith("SI"))
|
||||
{
|
||||
if (valArg.StartsWith("SIoC"))
|
||||
valArg = valArg.Substring(4);
|
||||
|
||||
// Server-side IoC selector.
|
||||
var selector = new ViewVariablesIoCSelector(valArg.Substring(1));
|
||||
vvm.OpenVV(selector);
|
||||
@@ -41,6 +44,9 @@ namespace Robust.Client.ViewVariables
|
||||
|
||||
if (valArg.StartsWith("I"))
|
||||
{
|
||||
if (valArg.StartsWith("IoC"))
|
||||
valArg = valArg.Substring(3);
|
||||
|
||||
// Client-side IoC selector.
|
||||
var reflection = IoCManager.Resolve<IReflectionManager>();
|
||||
if (!reflection.TryLooseGetType(valArg, out var type))
|
||||
|
||||
@@ -349,6 +349,16 @@ namespace Robust.Server
|
||||
_entityManager.Startup();
|
||||
IoCManager.Resolve<IEntityLookup>().Startup();
|
||||
_stateManager.Initialize();
|
||||
|
||||
// sometime after content init
|
||||
{
|
||||
var reg = _entityManager.ComponentFactory.GetRegistration<TransformComponent>();
|
||||
if (!reg.NetID.HasValue)
|
||||
throw new InvalidOperationException("TransformComponent does not have a NetId.");
|
||||
|
||||
_stateManager.SetTransformNetId(reg.NetID.Value);
|
||||
}
|
||||
|
||||
_scriptHost.Initialize();
|
||||
|
||||
_modLoader.BroadcastRunLevel(ModRunLevel.PostInit);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Players;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Players;
|
||||
@@ -10,6 +11,7 @@ namespace Robust.Server.GameObjects
|
||||
{
|
||||
[RegisterComponent]
|
||||
[ComponentReference(typeof(IPointLightComponent))]
|
||||
[NetworkedComponent()]
|
||||
public class PointLightComponent : Component, IPointLightComponent
|
||||
{
|
||||
[DataField("color")]
|
||||
@@ -22,7 +24,6 @@ namespace Robust.Server.GameObjects
|
||||
private Vector2 _offset = Vector2.Zero;
|
||||
|
||||
public override string Name => "PointLight";
|
||||
public override uint? NetID => NetIDs.POINT_LIGHT;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public Color Color
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Reflection;
|
||||
|
||||
namespace Robust.Server.GameObjects
|
||||
{
|
||||
public class ServerComponentFactory : ComponentFactory
|
||||
internal class ServerComponentFactory : ComponentFactory
|
||||
{
|
||||
public ServerComponentFactory()
|
||||
public ServerComponentFactory(IDynamicTypeFactoryInternal typeFactory, IReflectionManager reflectionManager, IConsoleHost conHost)
|
||||
: base(typeFactory, reflectionManager, conHost)
|
||||
{
|
||||
RegisterIgnore("Input");
|
||||
RegisterIgnore("AnimationPlayer");
|
||||
|
||||
@@ -75,7 +75,7 @@ namespace Robust.Server.GameObjects
|
||||
// As such, we can reset the modified ticks to Zero,
|
||||
// which indicates "not different from client's own deserialization".
|
||||
// So the initial data for the component or even the creation doesn't have to be sent over the wire.
|
||||
foreach (var component in ComponentManager.GetNetComponents(entity.Uid))
|
||||
foreach (var (netId, component) in ComponentManager.GetNetComponents(entity.Uid))
|
||||
{
|
||||
// Make sure to ONLY get components that are defined in the prototype.
|
||||
// Others could be instantiated directly by AddComponent (e.g. ContainerManager).
|
||||
@@ -143,13 +143,15 @@ namespace Robust.Server.GameObjects
|
||||
if (_networkManager.IsClient)
|
||||
return;
|
||||
|
||||
if (!component.NetID.HasValue)
|
||||
var netId = ComponentFactory.GetRegistration(component.GetType()).NetID;
|
||||
|
||||
if (!netId.HasValue)
|
||||
throw new ArgumentException($"Component {component.Name} does not have a NetID.", nameof(component));
|
||||
|
||||
var msg = _networkManager.CreateNetMessage<MsgEntity>();
|
||||
msg.Type = EntityMessageType.ComponentMessage;
|
||||
msg.EntityUid = entity.Uid;
|
||||
msg.NetId = component.NetID.Value;
|
||||
msg.NetId = netId.Value;
|
||||
msg.ComponentMessage = message;
|
||||
msg.SourceTick = _gameTiming.CurTick;
|
||||
|
||||
|
||||
@@ -39,6 +39,8 @@ namespace Robust.Server.GameStates
|
||||
private readonly ObjectPool<HashSet<EntityUid>> _viewerEntsPool
|
||||
= new DefaultObjectPool<HashSet<EntityUid>>(new DefaultPooledObjectPolicy<HashSet<EntityUid>>(), MaxVisPoolSize);
|
||||
|
||||
private ushort _transformNetId = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Is view culling enabled, or will we send the whole map?
|
||||
/// </summary>
|
||||
@@ -58,6 +60,11 @@ namespace Robust.Server.GameStates
|
||||
_lookup = lookup;
|
||||
}
|
||||
|
||||
public void SetTransformNetId(ushort value)
|
||||
{
|
||||
_transformNetId = value;
|
||||
}
|
||||
|
||||
// Not thread safe
|
||||
public void EntityDeleted(EntityUid e)
|
||||
{
|
||||
@@ -204,17 +211,14 @@ namespace Robust.Server.GameStates
|
||||
var oldState = (TransformComponent.TransformComponentState) xform.GetComponentState(session);
|
||||
|
||||
entityStates.Add(new EntityState(entityUid,
|
||||
new ComponentChanged[]
|
||||
new[]
|
||||
{
|
||||
new(false, NetIDs.TRANSFORM, "Transform")
|
||||
},
|
||||
new ComponentState[]
|
||||
{
|
||||
new TransformComponent.TransformComponentState(Vector2NaN,
|
||||
oldState.Rotation,
|
||||
oldState.ParentID,
|
||||
oldState.NoLocalRotation,
|
||||
oldState.Anchored)
|
||||
ComponentChange.Changed(_transformNetId,
|
||||
new TransformComponent.TransformComponentState(Vector2NaN,
|
||||
oldState.Rotation,
|
||||
oldState.ParentID,
|
||||
oldState.NoLocalRotation,
|
||||
oldState.Anchored)),
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
@@ -17,5 +17,6 @@ namespace Robust.Server.GameStates
|
||||
|
||||
bool PvsEnabled { get; set; }
|
||||
float PvsRange { get; set; }
|
||||
void SetTransformNetId(ushort netId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Server.Map;
|
||||
using Robust.Server.Player;
|
||||
@@ -21,6 +22,7 @@ using Robust.Shared.Utility;
|
||||
namespace Robust.Server.GameStates
|
||||
{
|
||||
/// <inheritdoc cref="IServerGameStateManager"/>
|
||||
[UsedImplicitly]
|
||||
public class ServerGameStateManager : IServerGameStateManager, IPostInjectInit
|
||||
{
|
||||
// Mapping of net UID of clients -> last known acked state.
|
||||
@@ -53,6 +55,11 @@ namespace Robust.Server.GameStates
|
||||
set => _configurationManager.SetCVar(CVars.NetMaxUpdateRange, value);
|
||||
}
|
||||
|
||||
public void SetTransformNetId(ushort netId)
|
||||
{
|
||||
_entityView.SetTransformNetId(netId);
|
||||
}
|
||||
|
||||
public void PostInject()
|
||||
{
|
||||
_logger = Logger.GetSawmill("PVS");
|
||||
@@ -249,38 +256,44 @@ namespace Robust.Server.GameStates
|
||||
/// <returns>New entity State for the given entity.</returns>
|
||||
internal static EntityState GetEntityState(IComponentManager compMan, ICommonSession player, EntityUid entityUid, GameTick fromTick)
|
||||
{
|
||||
var compStates = new List<ComponentState>();
|
||||
var changed = new List<ComponentChanged>();
|
||||
var changed = new List<ComponentChange>();
|
||||
|
||||
foreach (var comp in compMan.GetNetComponents(entityUid))
|
||||
foreach (var (netId, component) in compMan.GetNetComponents(entityUid))
|
||||
{
|
||||
DebugTools.Assert(comp.Initialized);
|
||||
DebugTools.Assert(component.Initialized);
|
||||
|
||||
// NOTE: When LastModifiedTick or CreationTick are 0 it means that the relevant data is
|
||||
// "not different from entity creation".
|
||||
// i.e. when the client spawns the entity and loads the entity prototype,
|
||||
// the data it deserializes from the prototype SHOULD be equal
|
||||
// to what the component state / ComponentChanged would send.
|
||||
// to what the component state / ComponentChange would send.
|
||||
// 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(player));
|
||||
DebugTools.Assert(component.LastModifiedTick >= component.CreationTick);
|
||||
|
||||
if (comp.CreationTick != GameTick.Zero && comp.CreationTick >= fromTick && !comp.Deleted)
|
||||
if (component.CreationTick != GameTick.Zero && component.CreationTick >= fromTick && !component.Deleted)
|
||||
{
|
||||
ComponentState? state = null;
|
||||
if (component.NetSyncEnabled && component.LastModifiedTick != GameTick.Zero && component.LastModifiedTick >= fromTick)
|
||||
state = component.GetComponentState(player);
|
||||
|
||||
// Can't be null since it's returned by GetNetComponents
|
||||
// ReSharper disable once PossibleInvalidOperationException
|
||||
changed.Add(ComponentChanged.Added(comp.NetID!.Value, comp.Name));
|
||||
changed.Add(ComponentChange.Added(netId, state));
|
||||
}
|
||||
else if (comp.Deleted && comp.LastModifiedTick >= fromTick)
|
||||
else if (component.NetSyncEnabled && component.LastModifiedTick != GameTick.Zero && component.LastModifiedTick >= fromTick)
|
||||
{
|
||||
changed.Add(ComponentChange.Changed(netId, component.GetComponentState(player)));
|
||||
}
|
||||
else if (component.Deleted && component.LastModifiedTick >= fromTick)
|
||||
{
|
||||
// Can't be null since it's returned by GetNetComponents
|
||||
// ReSharper disable once PossibleInvalidOperationException
|
||||
changed.Add(ComponentChanged.Removed(comp.NetID!.Value));
|
||||
changed.Add(ComponentChange.Removed(netId));
|
||||
}
|
||||
}
|
||||
|
||||
return new EntityState(entityUid, changed.ToArray(), compStates.ToArray());
|
||||
return new EntityState(entityUid, changed.ToArray());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -409,7 +409,7 @@ namespace Robust.Server.Maps
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (var component in _componentManager.GetNetComponents(entity.Uid))
|
||||
foreach (var (netId, component) in _componentManager.GetNetComponents(entity.Uid))
|
||||
{
|
||||
var castComp = (Component) component;
|
||||
|
||||
|
||||
@@ -39,10 +39,11 @@ namespace Robust.Server
|
||||
IoCManager.Register<IBaseServerInternal, BaseServer>();
|
||||
IoCManager.Register<BaseServer, BaseServer>();
|
||||
IoCManager.Register<IGameTiming, GameTiming>();
|
||||
IoCManager.Register<IReflectionManager, ServerReflectionManager>();
|
||||
IoCManager.Register<IConsoleHost, ServerConsoleHost>();
|
||||
IoCManager.Register<IServerConsoleHost, ServerConsoleHost>();
|
||||
IoCManager.Register<IComponentFactory, ServerComponentFactory>();
|
||||
IoCManager.Register<IConGroupController, ConGroupController>();
|
||||
IoCManager.Register<IServerConsoleHost, ServerConsoleHost>();
|
||||
IoCManager.Register<IConsoleHost, ServerConsoleHost>();
|
||||
IoCManager.Register<IMapManager, ServerMapManager>();
|
||||
IoCManager.Register<IMapManagerInternal, ServerMapManager>();
|
||||
IoCManager.Register<IServerMapManager, ServerMapManager>();
|
||||
@@ -55,7 +56,6 @@ namespace Robust.Server
|
||||
IoCManager.Register<IPlayerManager, PlayerManager>();
|
||||
IoCManager.Register<ISharedPlayerManager, PlayerManager>();
|
||||
IoCManager.Register<IPrototypeManager, ServerPrototypeManager>();
|
||||
IoCManager.Register<IReflectionManager, ServerReflectionManager>();
|
||||
IoCManager.Register<IResourceManager, ResourceManager>();
|
||||
IoCManager.Register<IResourceManagerInternal, ResourceManager>();
|
||||
IoCManager.Register<IServerEntityManager, ServerEntityManager>();
|
||||
|
||||
@@ -149,6 +149,26 @@ namespace Robust.Shared.Maths
|
||||
return new Box2(X0, Y0, X1, Y1);
|
||||
}
|
||||
|
||||
public bool Contains(Vector2 worldPoint)
|
||||
{
|
||||
// Get the worldpoint in our frame of reference so we can do a faster AABB check.
|
||||
var localPoint = GetLocalPoint(worldPoint);
|
||||
return Box.Contains(localPoint);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert a point in world-space coordinates to our local coordinates.
|
||||
/// </summary>
|
||||
private Vector2 GetLocalPoint(Vector2 point)
|
||||
{
|
||||
// Could make this more efficient but works for now I guess...
|
||||
var boxCenter = Box.Center;
|
||||
|
||||
var result = point - boxCenter;
|
||||
result = Origin + Rotation.RotateVec(result - Origin);
|
||||
return result + boxCenter;
|
||||
}
|
||||
|
||||
#region Equality
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Players;
|
||||
using Robust.Shared.Serialization;
|
||||
@@ -17,6 +18,7 @@ namespace Robust.Shared.Containers
|
||||
/// Holds data about a set of entity containers on this entity.
|
||||
/// </summary>
|
||||
[ComponentReference(typeof(IContainerManager))]
|
||||
[NetworkedComponent()]
|
||||
public class ContainerManagerComponent : Component, IContainerManager
|
||||
{
|
||||
[Dependency] private readonly IRobustSerializer _serializer = default!;
|
||||
@@ -29,9 +31,6 @@ namespace Robust.Shared.Containers
|
||||
/// <inheritdoc />
|
||||
public sealed override string Name => "ContainerContainer";
|
||||
|
||||
/// <inheritdoc />
|
||||
public sealed override uint? NetID => NetIDs.CONTAINER_MANAGER;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnRemove()
|
||||
{
|
||||
@@ -281,7 +280,7 @@ namespace Robust.Shared.Containers
|
||||
{
|
||||
public List<ContainerData> ContainerSet;
|
||||
|
||||
public ContainerManagerComponentState(List<ContainerData> containers) : base(NetIDs.CONTAINER_MANAGER)
|
||||
public ContainerManagerComponentState(List<ContainerData> containers)
|
||||
{
|
||||
ContainerSet = containers;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Players;
|
||||
using Robust.Shared.Reflection;
|
||||
@@ -18,14 +19,6 @@ namespace Robust.Shared.GameObjects
|
||||
[ViewVariables]
|
||||
public abstract string Name { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
[ViewVariables]
|
||||
public virtual uint? NetID => null;
|
||||
|
||||
/// <inheritdoc />
|
||||
[ViewVariables]
|
||||
public virtual bool NetworkSynchronizeExistence => false;
|
||||
|
||||
/// <inheritdoc />
|
||||
[ViewVariables]
|
||||
[DataField("netsync")]
|
||||
@@ -249,14 +242,16 @@ namespace Robust.Shared.GameObjects
|
||||
[Obsolete("Component Messages are deprecated, use Entity Events instead.")]
|
||||
public virtual void HandleNetworkMessage(ComponentMessage message, INetChannel netChannel, ICommonSession? session = null) { }
|
||||
|
||||
private static readonly ComponentState DefaultComponentState = new();
|
||||
|
||||
/// <param name="player"></param>
|
||||
/// <inheritdoc />
|
||||
public virtual ComponentState GetComponentState(ICommonSession player)
|
||||
{
|
||||
if (NetID == null)
|
||||
throw new InvalidOperationException($"Cannot make state for component without Net ID: {GetType()}");
|
||||
if (!(Attribute.GetCustomAttribute(GetType(), typeof(NetworkedComponentAttribute)) is NetworkedComponentAttribute))
|
||||
throw new InvalidOperationException($"Calling base {nameof(GetComponentState)} without being networked.");
|
||||
|
||||
return new ComponentState(NetID.Value);
|
||||
return DefaultComponentState;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -3,31 +3,33 @@ using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Reflection;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Robust.Shared.GameObjects
|
||||
{
|
||||
public class ComponentFactory : IComponentFactory
|
||||
internal class ComponentFactory : IComponentFactory
|
||||
{
|
||||
[Dependency] private readonly IDynamicTypeFactoryInternal _typeFactory = default!;
|
||||
[Dependency] private readonly IReflectionManager _reflectionManager = default!;
|
||||
private readonly IDynamicTypeFactoryInternal _typeFactory;
|
||||
private readonly IReflectionManager _reflectionManager;
|
||||
|
||||
private class ComponentRegistration : IComponentRegistration
|
||||
{
|
||||
public string Name { get; }
|
||||
public uint? NetID { get; }
|
||||
public bool NetworkSynchronizeExistence { get; }
|
||||
public ushort? NetID { get; set; }
|
||||
public Type Type { get; }
|
||||
internal readonly List<Type> References = new();
|
||||
IReadOnlyList<Type> IComponentRegistration.References => References;
|
||||
|
||||
public ComponentRegistration(string name, Type type, uint? netID, bool networkSynchronizeExistence)
|
||||
public ComponentRegistration(string name, Type type)
|
||||
{
|
||||
Name = name;
|
||||
NetID = netID;
|
||||
NetworkSynchronizeExistence = networkSynchronizeExistence;
|
||||
NetID = null;
|
||||
Type = type;
|
||||
References.Add(type);
|
||||
}
|
||||
@@ -52,7 +54,7 @@ namespace Robust.Shared.GameObjects
|
||||
/// <summary>
|
||||
/// Mapping of network ID to type.
|
||||
/// </summary>
|
||||
private readonly Dictionary<uint, ComponentRegistration> netIDs = new();
|
||||
private List<IComponentRegistration>? _networkedComponents;
|
||||
|
||||
/// <summary>
|
||||
/// Mapping of concrete component types to their registration.
|
||||
@@ -76,8 +78,34 @@ namespace Robust.Shared.GameObjects
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<Type> AllRegisteredTypes => types.Keys;
|
||||
|
||||
/// <inheritdoc />
|
||||
public IReadOnlyList<IComponentRegistration>? NetworkedComponents => _networkedComponents;
|
||||
|
||||
private IEnumerable<ComponentRegistration> AllRegistrations => types.Values;
|
||||
|
||||
public ComponentFactory(IDynamicTypeFactoryInternal typeFactory, IReflectionManager reflectionManager, IConsoleHost conHost)
|
||||
{
|
||||
_typeFactory = typeFactory;
|
||||
_reflectionManager = reflectionManager;
|
||||
|
||||
conHost.RegisterCommand("dump_net_comps", "Prints the table of networked components.", "dump_net_comps", (shell, argStr, args) =>
|
||||
{
|
||||
if (_networkedComponents is null)
|
||||
{
|
||||
shell.WriteError("Registration still writeable, network ids have not been generated.");
|
||||
return;
|
||||
}
|
||||
|
||||
shell.WriteLine("Networked Component Registrations:");
|
||||
|
||||
for (int netId = 0; netId < _networkedComponents.Count; netId++)
|
||||
{
|
||||
var registration = _networkedComponents[netId];
|
||||
shell.WriteLine($" [{netId,4}] {registration.Name,-16} {registration.Type.Name}");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
[Obsolete("Use RegisterClass and Attributes instead of the Register/RegisterReference combo")]
|
||||
public void Register<T>(bool overwrite = false) where T : IComponent, new()
|
||||
{
|
||||
@@ -86,6 +114,9 @@ namespace Robust.Shared.GameObjects
|
||||
|
||||
private void Register(Type type, bool overwrite = false)
|
||||
{
|
||||
if (_networkedComponents is not null)
|
||||
throw new ComponentRegistrationLockException();
|
||||
|
||||
if (types.ContainsKey(type))
|
||||
{
|
||||
throw new InvalidOperationException($"Type is already registered: {type}");
|
||||
@@ -97,8 +128,6 @@ namespace Robust.Shared.GameObjects
|
||||
|
||||
var name = dummy.Name;
|
||||
var lowerCaseName = name.ToLowerInvariant();
|
||||
var netID = dummy.NetID;
|
||||
var netSyncExist = dummy.NetworkSynchronizeExistence;
|
||||
|
||||
if (IgnoredComponentNames.Contains(name))
|
||||
{
|
||||
@@ -128,24 +157,11 @@ namespace Robust.Shared.GameObjects
|
||||
}
|
||||
}
|
||||
|
||||
if (netID != null && netIDs.ContainsKey(netID.Value))
|
||||
{
|
||||
if (!overwrite)
|
||||
{
|
||||
throw new InvalidOperationException($"{name} has duplicate network ID {netID}, previous: {netIDs[netID.Value]}");
|
||||
}
|
||||
|
||||
RemoveComponent(netIDs[netID.Value].Name);
|
||||
}
|
||||
|
||||
var registration = new ComponentRegistration(name, type, netID, netSyncExist);
|
||||
var registration = new ComponentRegistration(name, type);
|
||||
names[name] = registration;
|
||||
_lowerCaseNames[lowerCaseName] = name;
|
||||
types[type] = registration;
|
||||
if (netID != null)
|
||||
{
|
||||
netIDs[netID.Value] = registration;
|
||||
}
|
||||
|
||||
ComponentAdded?.Invoke(registration);
|
||||
}
|
||||
|
||||
@@ -157,6 +173,9 @@ namespace Robust.Shared.GameObjects
|
||||
|
||||
private void RegisterReference(Type target, Type @interface)
|
||||
{
|
||||
if (_networkedComponents is not null)
|
||||
throw new ComponentRegistrationLockException();
|
||||
|
||||
if (!types.ContainsKey(target))
|
||||
{
|
||||
throw new InvalidOperationException($"Unregistered type: {target}");
|
||||
@@ -194,15 +213,14 @@ namespace Robust.Shared.GameObjects
|
||||
|
||||
private void RemoveComponent(string name)
|
||||
{
|
||||
if (_networkedComponents is not null)
|
||||
throw new ComponentRegistrationLockException();
|
||||
|
||||
var registration = names[name];
|
||||
|
||||
names.Remove(registration.Name);
|
||||
_lowerCaseNames.Remove(registration.Name.ToLowerInvariant());
|
||||
types.Remove(registration.Type);
|
||||
if (registration.NetID != null)
|
||||
{
|
||||
netIDs.Remove(registration.NetID.Value);
|
||||
}
|
||||
}
|
||||
|
||||
public ComponentAvailability GetComponentAvailability(string componentName, bool ignoreCase = false)
|
||||
@@ -253,7 +271,7 @@ namespace Robust.Shared.GameObjects
|
||||
return _typeFactory.CreateInstanceUnchecked<IComponent>(GetRegistration(componentName).Type);
|
||||
}
|
||||
|
||||
public IComponent GetComponent(uint netId)
|
||||
public IComponent GetComponent(ushort netId)
|
||||
{
|
||||
return _typeFactory.CreateInstanceUnchecked<IComponent>(GetRegistration(netId).Type);
|
||||
}
|
||||
@@ -275,11 +293,14 @@ namespace Robust.Shared.GameObjects
|
||||
}
|
||||
}
|
||||
|
||||
public IComponentRegistration GetRegistration(uint netID)
|
||||
public IComponentRegistration GetRegistration(ushort netID)
|
||||
{
|
||||
if (_networkedComponents is null)
|
||||
throw new ComponentRegistrationLockException();
|
||||
|
||||
try
|
||||
{
|
||||
return netIDs[netID];
|
||||
return _networkedComponents[netID];
|
||||
}
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
@@ -343,9 +364,9 @@ namespace Robust.Shared.GameObjects
|
||||
return TryGetRegistration(typeof(T), out registration);
|
||||
}
|
||||
|
||||
public bool TryGetRegistration(uint netID, [NotNullWhen(true)] out IComponentRegistration? registration)
|
||||
public bool TryGetRegistration(ushort netID, [NotNullWhen(true)] out IComponentRegistration? registration)
|
||||
{
|
||||
if (netIDs.TryGetValue(netID, out var tempRegistration))
|
||||
if (_networkedComponents is not null && _networkedComponents.TryGetValue(netID, out var tempRegistration))
|
||||
{
|
||||
registration = tempRegistration;
|
||||
return true;
|
||||
@@ -406,15 +427,36 @@ namespace Robust.Shared.GameObjects
|
||||
return AllRegistrations.SelectMany(r => r.References).Distinct();
|
||||
}
|
||||
|
||||
public IEnumerable<uint> GetAllNetIds()
|
||||
/// <inheritdoc />
|
||||
public void GenerateNetIds()
|
||||
{
|
||||
foreach (var registration in AllRegistrations)
|
||||
// assumptions:
|
||||
// component names are guaranteed to be unique
|
||||
// component names are 1:1 with component concrete types
|
||||
|
||||
// a subset of component names are networked
|
||||
var networkedRegs = new List<IComponentRegistration>(names.Count);
|
||||
|
||||
foreach (var kvRegistration in names)
|
||||
{
|
||||
if (registration.NetID != null)
|
||||
var registration = kvRegistration.Value;
|
||||
if (Attribute.GetCustomAttribute(registration.Type, typeof(NetworkedComponentAttribute)) is NetworkedComponentAttribute)
|
||||
{
|
||||
yield return registration.NetID.Value;
|
||||
networkedRegs.Add(registration);
|
||||
}
|
||||
}
|
||||
|
||||
// The sorting implementation is unstable, but there are no duplicate names, so that isn't a problem.
|
||||
// Ordinal comparison is used so that the resulting order is always identical on every computer.
|
||||
networkedRegs.Sort((a, b) => string.Compare(a.Name, b.Name, StringComparison.Ordinal));
|
||||
|
||||
for (ushort i = 0; i < networkedRegs.Count; i++)
|
||||
{
|
||||
var registration = (ComponentRegistration) networkedRegs[i];
|
||||
registration.NetID = i;
|
||||
}
|
||||
|
||||
_networkedComponents = networkedRegs;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -434,4 +476,6 @@ namespace Robust.Shared.GameObjects
|
||||
SerializationInfo info,
|
||||
StreamingContext context) : base(info, context) { }
|
||||
}
|
||||
|
||||
public class ComponentRegistrationLockException : Exception { }
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Internal.TypeSystem;
|
||||
using Robust.Shared.Exceptions;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Serialization;
|
||||
@@ -28,7 +30,7 @@ namespace Robust.Shared.GameObjects
|
||||
private const int EntityCapacity = 1024;
|
||||
private const int NetComponentCapacity = 8;
|
||||
|
||||
private readonly Dictionary<EntityUid, Dictionary<uint, Component>> _netComponents
|
||||
private readonly Dictionary<EntityUid, Dictionary<ushort, Component>> _netComponents
|
||||
= new(EntityCapacity);
|
||||
|
||||
private readonly Dictionary<Type, Dictionary<EntityUid, Component>> _entTraitDict
|
||||
@@ -144,14 +146,14 @@ namespace Robust.Shared.GameObjects
|
||||
}
|
||||
|
||||
// add the component to the netId grid
|
||||
if (component.NetID != null)
|
||||
if (reg.NetID != null)
|
||||
{
|
||||
// the main comp grid keeps this in sync
|
||||
var netId = component.NetID.Value;
|
||||
var netId = reg.NetID.Value;
|
||||
|
||||
if (!_netComponents.TryGetValue(uid, out var netSet))
|
||||
{
|
||||
netSet = new Dictionary<uint, Component>(NetComponentCapacity);
|
||||
netSet = new Dictionary<ushort, Component>(NetComponentCapacity);
|
||||
_netComponents.Add(uid, netSet);
|
||||
}
|
||||
netSet.Add(netId, component);
|
||||
@@ -191,7 +193,7 @@ namespace Robust.Shared.GameObjects
|
||||
|
||||
/// <inheritdoc />
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void RemoveComponent(EntityUid uid, uint netId)
|
||||
public void RemoveComponent(EntityUid uid, ushort netId)
|
||||
{
|
||||
RemoveComponentDeferred((Component)GetComponent(uid, netId), uid, false);
|
||||
}
|
||||
@@ -335,13 +337,13 @@ namespace Robust.Shared.GameObjects
|
||||
}
|
||||
|
||||
// ReSharper disable once InvertIf
|
||||
if (component.NetID != null)
|
||||
if (reg.NetID != null)
|
||||
{
|
||||
var netSet = _netComponents[entityUid];
|
||||
if (netSet.Count == 1)
|
||||
_netComponents.Remove(entityUid);
|
||||
else
|
||||
netSet.Remove(component.NetID.Value);
|
||||
netSet.Remove(reg.NetID.Value);
|
||||
|
||||
component.Owner.Dirty();
|
||||
}
|
||||
@@ -367,7 +369,7 @@ namespace Robust.Shared.GameObjects
|
||||
|
||||
/// <inheritdoc />
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool HasComponent(EntityUid uid, uint netId)
|
||||
public bool HasComponent(EntityUid uid, ushort netId)
|
||||
{
|
||||
return _netComponents.TryGetValue(uid, out var netSet)
|
||||
&& netSet.ContainsKey(netId);
|
||||
@@ -397,7 +399,7 @@ namespace Robust.Shared.GameObjects
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IComponent GetComponent(EntityUid uid, uint netId)
|
||||
public IComponent GetComponent(EntityUid uid, ushort netId)
|
||||
{
|
||||
return _netComponents[uid][netId];
|
||||
}
|
||||
@@ -436,7 +438,7 @@ namespace Robust.Shared.GameObjects
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool TryGetComponent(EntityUid uid, uint netId, [MaybeNullWhen(false)] out IComponent component)
|
||||
public bool TryGetComponent(EntityUid uid, ushort netId, [MaybeNullWhen(false)] out IComponent component)
|
||||
{
|
||||
if (_netComponents.TryGetValue(uid, out var netSet)
|
||||
&& netSet.TryGetValue(netId, out var comp))
|
||||
@@ -474,9 +476,9 @@ namespace Robust.Shared.GameObjects
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<IComponent> GetNetComponents(EntityUid uid)
|
||||
public NetComponentEnumerable GetNetComponents(EntityUid uid)
|
||||
{
|
||||
return _netComponents[uid].Values;
|
||||
return new NetComponentEnumerable(_netComponents[uid]);
|
||||
}
|
||||
|
||||
#region Join Functions
|
||||
@@ -597,4 +599,30 @@ namespace Robust.Shared.GameObjects
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public readonly struct NetComponentEnumerable
|
||||
{
|
||||
private readonly Dictionary<ushort, Component> _dictionary;
|
||||
|
||||
public NetComponentEnumerable(Dictionary<ushort, Component> dictionary) => _dictionary = dictionary;
|
||||
public NetComponentEnumerator GetEnumerator() => new(_dictionary);
|
||||
}
|
||||
|
||||
public struct NetComponentEnumerator
|
||||
{
|
||||
// DO NOT MAKE THIS READONLY
|
||||
private Dictionary<ushort, Component>.Enumerator _dictEnum;
|
||||
|
||||
public NetComponentEnumerator(Dictionary<ushort, Component> dictionary) => _dictEnum = dictionary.GetEnumerator();
|
||||
public bool MoveNext() => _dictEnum.MoveNext();
|
||||
public (ushort netId, IComponent component) Current
|
||||
{
|
||||
get
|
||||
{
|
||||
var val = _dictEnum.Current;
|
||||
return (val.Key, val.Value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,10 @@
|
||||
using Robust.Shared.Serialization;
|
||||
using System;
|
||||
using Robust.Shared.Analyzers;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Robust.Shared.GameObjects
|
||||
{
|
||||
[RequiresSerializable]
|
||||
[Serializable, NetSerializable]
|
||||
public class ComponentState
|
||||
{
|
||||
public uint NetID { get; }
|
||||
|
||||
public ComponentState(uint netID)
|
||||
{
|
||||
NetID = netID;
|
||||
}
|
||||
}
|
||||
public class ComponentState { }
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Robust.Shared.GameObjects
|
||||
@@ -11,10 +12,10 @@ namespace Robust.Shared.GameObjects
|
||||
/// The data works using a simple key/value system. It is recommended to use enum keys to prevent errors.
|
||||
/// Visualization works client side with overrides of the <c>AppearanceVisualizer</c> class.
|
||||
/// </summary>
|
||||
[NetworkedComponent()]
|
||||
public abstract class SharedAppearanceComponent : Component
|
||||
{
|
||||
public override string Name => "Appearance";
|
||||
public override uint? NetID => NetIDs.APPEARANCE;
|
||||
|
||||
public abstract void SetData(string key, object value);
|
||||
public abstract void SetData(Enum key, object value);
|
||||
@@ -30,7 +31,7 @@ namespace Robust.Shared.GameObjects
|
||||
{
|
||||
public readonly Dictionary<object, object> Data;
|
||||
|
||||
public AppearanceComponentState(Dictionary<object, object> data) : base(NetIDs.APPEARANCE)
|
||||
public AppearanceComponentState(Dictionary<object, object> data)
|
||||
{
|
||||
Data = data;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace Robust.Shared.GameObjects
|
||||
{
|
||||
public Box2? LocalBounds { get; }
|
||||
|
||||
public ClickableComponentState(Box2? localBounds) : base(NetIDs.CLICKABLE)
|
||||
public ClickableComponentState(Box2? localBounds)
|
||||
{
|
||||
LocalBounds = localBounds;
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Map;
|
||||
@@ -44,6 +45,7 @@ using Robust.Shared.ViewVariables;
|
||||
namespace Robust.Shared.GameObjects
|
||||
{
|
||||
[ComponentReference(typeof(IPhysBody))]
|
||||
[NetworkedComponent()]
|
||||
public sealed class PhysicsComponent : Component, IPhysBody, ISerializationHooks
|
||||
{
|
||||
[DataField("status", readOnly: true)]
|
||||
@@ -52,9 +54,6 @@ namespace Robust.Shared.GameObjects
|
||||
/// <inheritdoc />
|
||||
public override string Name => "Physics";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override uint? NetID => NetIDs.PHYSICS;
|
||||
|
||||
/// <summary>
|
||||
/// Has this body been added to an island previously in this tick.
|
||||
/// </summary>
|
||||
@@ -834,6 +833,32 @@ namespace Robust.Shared.GameObjects
|
||||
[DataField("angularDamping")]
|
||||
private float _angularDamping = 0.02f;
|
||||
|
||||
/// <summary>
|
||||
/// Get the linear and angular velocities at the same time.
|
||||
/// </summary>
|
||||
public (Vector2 Linear, float Angular) MapVelocities
|
||||
{
|
||||
get
|
||||
{
|
||||
var linearVelocity = _linVelocity;
|
||||
var angularVelocity = _angVelocity;
|
||||
var parent = Owner.Transform.Parent?.Owner;
|
||||
|
||||
while (parent != null)
|
||||
{
|
||||
if (parent.TryGetComponent(out PhysicsComponent? body))
|
||||
{
|
||||
linearVelocity += body.LinearVelocity;
|
||||
angularVelocity += body.AngularVelocity;
|
||||
}
|
||||
|
||||
parent = parent.Transform.Parent?.Owner;
|
||||
}
|
||||
|
||||
return (linearVelocity, angularVelocity);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Current linear velocity of the entity in meters per second.
|
||||
/// </summary>
|
||||
@@ -862,6 +887,33 @@ namespace Robust.Shared.GameObjects
|
||||
|
||||
private Vector2 _linVelocity;
|
||||
|
||||
/// <summary>
|
||||
/// Get the body's LinearVelocity in map terms.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Consider using <see cref="MapVelocities"/> if you need linear and angular at the same time.
|
||||
/// </remarks>
|
||||
public Vector2 MapLinearVelocity
|
||||
{
|
||||
get
|
||||
{
|
||||
var velocity = _linVelocity;
|
||||
var parent = Owner.Transform.Parent?.Owner;
|
||||
|
||||
while (parent != null)
|
||||
{
|
||||
if (parent.TryGetComponent(out PhysicsComponent? body))
|
||||
{
|
||||
velocity += body.LinearVelocity;
|
||||
}
|
||||
|
||||
parent = parent.Transform.Parent?.Owner;
|
||||
}
|
||||
|
||||
return velocity;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Current angular velocity of the entity in radians per sec.
|
||||
/// </summary>
|
||||
@@ -890,6 +942,33 @@ namespace Robust.Shared.GameObjects
|
||||
|
||||
private float _angVelocity;
|
||||
|
||||
/// <summary>
|
||||
/// Get the body's AngularVelocity in map terms.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Consider using <see cref="MapVelocities"/> if you need linear and angular at the same time.
|
||||
/// </remarks>
|
||||
public float MapAngularVelocity
|
||||
{
|
||||
get
|
||||
{
|
||||
var velocity = _angVelocity;
|
||||
var parent = Owner.Transform.Parent?.Owner;
|
||||
|
||||
while (parent != null)
|
||||
{
|
||||
if (parent.TryGetComponent(out PhysicsComponent? body))
|
||||
{
|
||||
velocity += body.AngularVelocity;
|
||||
}
|
||||
|
||||
parent = parent.Transform.Parent?.Owner;
|
||||
}
|
||||
|
||||
return velocity;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Current momentum of the entity in kilogram meters per second
|
||||
/// </summary>
|
||||
|
||||
@@ -44,7 +44,6 @@ namespace Robust.Shared.GameObjects
|
||||
Vector2 linearVelocity,
|
||||
float angularVelocity,
|
||||
BodyType bodyType)
|
||||
: base(NetIDs.PHYSICS)
|
||||
{
|
||||
CanCollide = canCollide;
|
||||
SleepingAllowed = sleepingAllowed;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Players;
|
||||
using Robust.Shared.Serialization;
|
||||
@@ -11,10 +12,10 @@ namespace Robust.Shared.GameObjects
|
||||
/// <summary>
|
||||
/// An optimisation component for stuff that should be set as collidable when it's awake and non-collidable when asleep.
|
||||
/// </summary>
|
||||
[NetworkedComponent()]
|
||||
public sealed class CollisionWakeComponent : Component
|
||||
{
|
||||
public override string Name => "CollisionWake";
|
||||
public override uint? NetID => NetIDs.COLLISION_WAKE;
|
||||
|
||||
[DataField("enabled")]
|
||||
private bool _enabled = true;
|
||||
@@ -64,7 +65,7 @@ namespace Robust.Shared.GameObjects
|
||||
{
|
||||
public bool Enabled { get; }
|
||||
|
||||
public CollisionWakeState(bool enabled) : base(NetIDs.COLLISION_WAKE)
|
||||
public CollisionWakeState(bool enabled)
|
||||
{
|
||||
Enabled = enabled;
|
||||
}
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
using System;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Robust.Shared.GameObjects
|
||||
{
|
||||
[NetworkedComponent()]
|
||||
public class SharedEyeComponent : Component
|
||||
{
|
||||
public override string Name => "Eye";
|
||||
public override uint? NetID => NetIDs.EYE;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public virtual bool DrawFov { get; set; }
|
||||
@@ -39,7 +40,7 @@ namespace Robust.Shared.GameObjects
|
||||
public Angle Rotation { get; }
|
||||
public uint VisibilityMask { get; }
|
||||
|
||||
public EyeComponentState(bool drawFov, Vector2 zoom, Vector2 offset, Angle rotation, uint visibilityMask) : base(NetIDs.EYE)
|
||||
public EyeComponentState(bool drawFov, Vector2 zoom, Vector2 offset, Angle rotation, uint visibilityMask)
|
||||
{
|
||||
DrawFov = drawFov;
|
||||
Zoom = zoom;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Prototypes;
|
||||
@@ -9,10 +10,10 @@ using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Robust.Shared.GameObjects
|
||||
{
|
||||
[NetworkedComponent()]
|
||||
public class OccluderComponent : Component
|
||||
{
|
||||
public sealed override string Name => "Occluder";
|
||||
public sealed override uint? NetID => NetIDs.OCCLUDER;
|
||||
|
||||
[DataField("enabled")]
|
||||
private bool _enabled = true;
|
||||
@@ -94,7 +95,7 @@ namespace Robust.Shared.GameObjects
|
||||
public bool Enabled { get; }
|
||||
public Box2 BoundingBox { get; }
|
||||
|
||||
public OccluderComponentState(bool enabled, Box2 boundingBox) : base(NetIDs.OCCLUDER)
|
||||
public OccluderComponentState(bool enabled, Box2 boundingBox)
|
||||
{
|
||||
Enabled = enabled;
|
||||
BoundingBox = boundingBox;
|
||||
|
||||
@@ -14,7 +14,6 @@ namespace Robust.Shared.GameObjects
|
||||
public readonly Vector2 Offset;
|
||||
|
||||
public PointLightComponentState(bool enabled, Color color, float radius, Vector2 offset)
|
||||
: base(NetIDs.POINT_LIGHT)
|
||||
{
|
||||
Enabled = enabled;
|
||||
Color = color;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
@@ -10,10 +11,10 @@ namespace Robust.Shared.GameObjects.Components.Localization
|
||||
/// Overrides grammar attributes specified in prototypes or localization files.
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
[NetworkedComponent()]
|
||||
public class GrammarComponent : Component
|
||||
{
|
||||
public override string Name => "Grammar";
|
||||
public override uint? NetID => NetIDs.GRAMMAR;
|
||||
|
||||
[ViewVariables]
|
||||
[DataField("attributes")]
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Players;
|
||||
using Robust.Shared.Serialization;
|
||||
@@ -18,6 +19,7 @@ namespace Robust.Shared.GameObjects
|
||||
|
||||
/// <inheritdoc cref="IMapComponent"/>
|
||||
[ComponentReference(typeof(IMapComponent))]
|
||||
[NetworkedComponent()]
|
||||
public class MapComponent : Component, IMapComponent
|
||||
{
|
||||
[ViewVariables(VVAccess.ReadOnly)]
|
||||
@@ -27,9 +29,6 @@ namespace Robust.Shared.GameObjects
|
||||
/// <inheritdoc />
|
||||
public override string Name => "Map";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override uint? NetID => NetIDs.MAP_MAP;
|
||||
|
||||
/// <inheritdoc />
|
||||
public MapId WorldMap
|
||||
{
|
||||
@@ -73,7 +72,6 @@ namespace Robust.Shared.GameObjects
|
||||
public MapId MapId { get; }
|
||||
|
||||
public MapComponentState(MapId mapId)
|
||||
: base(NetIDs.MAP_MAP)
|
||||
{
|
||||
MapId = mapId;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
@@ -25,6 +26,7 @@ namespace Robust.Shared.GameObjects
|
||||
|
||||
/// <inheritdoc cref="IMapGridComponent"/>
|
||||
[ComponentReference(typeof(IMapGridComponent))]
|
||||
[NetworkedComponent()]
|
||||
internal class MapGridComponent : Component, IMapGridComponent
|
||||
{
|
||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||
@@ -36,9 +38,6 @@ namespace Robust.Shared.GameObjects
|
||||
/// <inheritdoc />
|
||||
public override string Name => "MapGrid";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override uint? NetID => NetIDs.MAP_GRID;
|
||||
|
||||
/// <inheritdoc />
|
||||
public GridId GridIndex
|
||||
{
|
||||
@@ -145,7 +144,6 @@ namespace Robust.Shared.GameObjects
|
||||
/// </summary>
|
||||
/// <param name="gridIndex">Index of the grid this component is linked to.</param>
|
||||
public MapGridComponentState(GridId gridIndex)
|
||||
: base(NetIDs.MAP_GRID)
|
||||
{
|
||||
GridIndex = gridIndex;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Players;
|
||||
using Robust.Shared.Prototypes;
|
||||
@@ -35,7 +36,6 @@ namespace Robust.Shared.GameObjects
|
||||
/// <param name="description">The in-game description of this entity.</param>
|
||||
/// <param name="prototypeId">The prototype this entity was created from, if any.</param>
|
||||
public MetaDataComponentState(string? name, string? description, string? prototypeId)
|
||||
: base(NetIDs.META_DATA)
|
||||
{
|
||||
Name = name;
|
||||
Description = description;
|
||||
@@ -66,6 +66,7 @@ namespace Robust.Shared.GameObjects
|
||||
|
||||
/// <inheritdoc cref="IMetaDataComponent"/>
|
||||
[ComponentReference(typeof(IMetaDataComponent))]
|
||||
[NetworkedComponent()]
|
||||
internal class MetaDataComponent : Component, IMetaDataComponent
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _prototypes = default!;
|
||||
@@ -79,9 +80,6 @@ namespace Robust.Shared.GameObjects
|
||||
/// <inheritdoc />
|
||||
public override string Name => "MetaData";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override uint? NetID => NetIDs.META_DATA;
|
||||
|
||||
/// <inheritdoc />
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public string EntityName
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
namespace Robust.Shared.GameObjects
|
||||
{
|
||||
public static class NetIDs
|
||||
{
|
||||
public const uint MAP_MAP = 1;
|
||||
public const uint MAP_GRID = 2;
|
||||
public const uint META_DATA = 4;
|
||||
public const uint TRANSFORM = 5;
|
||||
public const uint SPRITE = 8;
|
||||
public const uint POINT_LIGHT = 10;
|
||||
public const uint PHYSICS = 12;
|
||||
public const uint CLICKABLE = 14;
|
||||
public const uint APPEARANCE = 22;
|
||||
public const uint USERINTERFACE = 24;
|
||||
public const uint CONTAINER_MANAGER = 25;
|
||||
public const uint OCCLUDER = 26;
|
||||
public const uint EYE = 28;
|
||||
public const uint GRAMMAR = 29;
|
||||
public const uint COLLISION_WAKE = 30;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
@@ -7,10 +8,10 @@ using Robust.Shared.Utility;
|
||||
|
||||
namespace Robust.Shared.GameObjects
|
||||
{
|
||||
[NetworkedComponent()]
|
||||
public abstract class SharedSpriteComponent : Component
|
||||
{
|
||||
public override string Name => "Sprite";
|
||||
public override uint? NetID => NetIDs.SPRITE;
|
||||
|
||||
public abstract bool Visible { get; set; }
|
||||
|
||||
@@ -42,7 +43,6 @@ namespace Robust.Shared.GameObjects
|
||||
string? baseRsiPath,
|
||||
List<PrototypeLayerData> layers,
|
||||
uint renderOrder)
|
||||
: base(NetIDs.SPRITE)
|
||||
{
|
||||
Visible = visible;
|
||||
DrawDepth = drawDepth;
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using Robust.Shared.Animations;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
@@ -16,6 +17,7 @@ using Robust.Shared.ViewVariables;
|
||||
namespace Robust.Shared.GameObjects
|
||||
{
|
||||
[ComponentReference(typeof(ITransformComponent))]
|
||||
[NetworkedComponent()]
|
||||
internal class TransformComponent : Component, ITransformComponent, IComponentDebug
|
||||
{
|
||||
[DataField("parent")]
|
||||
@@ -54,9 +56,6 @@ namespace Robust.Shared.GameObjects
|
||||
/// <inheritdoc />
|
||||
public override string Name => "Transform";
|
||||
|
||||
/// <inheritdoc />
|
||||
public sealed override uint? NetID => NetIDs.TRANSFORM;
|
||||
|
||||
/// <inheritdoc />
|
||||
[ViewVariables]
|
||||
public MapId MapID { get; private set; }
|
||||
@@ -896,7 +895,6 @@ namespace Robust.Shared.GameObjects
|
||||
/// <param name="parentId">Current parent transform of this entity.</param>
|
||||
/// <param name="noLocalRotation"></param>
|
||||
public TransformComponentState(Vector2 localPosition, Angle rotation, EntityUid parentId, bool noLocalRotation, bool anchored)
|
||||
: base(NetIDs.TRANSFORM)
|
||||
{
|
||||
LocalPosition = localPosition;
|
||||
Rotation = rotation;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Reflection;
|
||||
using Robust.Shared.Serialization;
|
||||
@@ -6,10 +7,10 @@ using Robust.Shared.Serialization.Manager.Attributes;
|
||||
|
||||
namespace Robust.Shared.GameObjects
|
||||
{
|
||||
[NetworkedComponent()]
|
||||
public abstract class SharedUserInterfaceComponent : Component
|
||||
{
|
||||
public sealed override string Name => "UserInterface";
|
||||
public sealed override uint? NetID => NetIDs.USERINTERFACE;
|
||||
|
||||
[DataDefinition]
|
||||
public sealed class PrototypeData : ISerializationHooks
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace Robust.Shared.GameObjects
|
||||
|
||||
[IoC.Dependency] protected readonly IPrototypeManager PrototypeManager = default!;
|
||||
[IoC.Dependency] protected readonly IEntitySystemManager EntitySystemManager = default!;
|
||||
[IoC.Dependency] private readonly IComponentFactory ComponentFactory = default!;
|
||||
[IoC.Dependency] protected readonly IComponentFactory ComponentFactory = default!;
|
||||
[IoC.Dependency] private readonly IComponentManager _componentManager = default!;
|
||||
[IoC.Dependency] private readonly IMapManager _mapManager = default!;
|
||||
[IoC.Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||
@@ -32,6 +32,8 @@ namespace Robust.Shared.GameObjects
|
||||
/// <inheritdoc />
|
||||
public GameTick CurrentTick => _gameTiming.CurTick;
|
||||
|
||||
IComponentFactory IEntityManager.ComponentFactory => ComponentFactory;
|
||||
|
||||
/// <inheritdoc />
|
||||
public IComponentManager ComponentManager => _componentManager;
|
||||
|
||||
@@ -479,7 +481,7 @@ namespace Robust.Shared.GameObjects
|
||||
var uid = netMsg.EntityUid;
|
||||
if (compMsg.Directed)
|
||||
{
|
||||
if (_componentManager.TryGetComponent(uid, netMsg.NetId, out var component))
|
||||
if (_componentManager.TryGetComponent(uid, (ushort) netMsg.NetId, out var component))
|
||||
component.HandleNetworkMessage(compMsg, compChannel, session);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -7,61 +7,71 @@ namespace Robust.Shared.GameObjects
|
||||
public sealed class EntityState
|
||||
{
|
||||
public EntityUid Uid { get; }
|
||||
public ComponentChanged[]? ComponentChanges { get; }
|
||||
public ComponentState[]? ComponentStates { get; }
|
||||
|
||||
public bool Empty => ComponentChanges is null && ComponentStates is null;
|
||||
public ComponentChange[]? ComponentChanges { get; }
|
||||
|
||||
public EntityState(EntityUid uid, ComponentChanged[]? changedComponents, ComponentState[]? componentStates)
|
||||
public bool Empty => ComponentChanges is null;
|
||||
|
||||
public EntityState(EntityUid uid, ComponentChange[]? changedComponents)
|
||||
{
|
||||
Uid = uid;
|
||||
|
||||
// empty lists are 5 bytes each
|
||||
ComponentChanges = changedComponents == null || changedComponents.Length == 0 ? null : changedComponents;
|
||||
ComponentStates = componentStates == null || componentStates.Length == 0 ? null : componentStates;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public readonly struct ComponentChanged
|
||||
public readonly struct ComponentChange
|
||||
{
|
||||
// 15ish bytes to create a component (strings are big), 5 bytes to remove one
|
||||
|
||||
/// <summary>
|
||||
/// Was the component added or removed from the entity.
|
||||
/// Was the component removed from the entity.
|
||||
/// </summary>
|
||||
public readonly bool Deleted;
|
||||
|
||||
/// <summary>
|
||||
/// The Network ID of the component to remove.
|
||||
/// Was the component added to the entity.
|
||||
/// </summary>
|
||||
public readonly uint NetID;
|
||||
public readonly bool Created;
|
||||
|
||||
/// <summary>
|
||||
/// The prototype name of the component to add.
|
||||
/// State data for the created/modified component, if any.
|
||||
/// </summary>
|
||||
public readonly string? ComponentName;
|
||||
public readonly ComponentState? State;
|
||||
|
||||
public ComponentChanged(bool deleted, uint netId, string? componentName)
|
||||
/// <summary>
|
||||
/// The Network ID of the component to remove.
|
||||
/// </summary>
|
||||
public readonly ushort NetID;
|
||||
|
||||
public ComponentChange(ushort netId, bool created, bool deleted, ComponentState? state)
|
||||
{
|
||||
Deleted = deleted;
|
||||
State = state;
|
||||
NetID = netId;
|
||||
ComponentName = componentName;
|
||||
Created = created;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{(Deleted ? "D" : "C")} {NetID} {ComponentName}";
|
||||
return $"{(Deleted ? "D" : "C")} {NetID} {State?.GetType().Name}";
|
||||
}
|
||||
|
||||
public static ComponentChanged Added(uint netId, string componentName)
|
||||
public static ComponentChange Added(ushort netId, ComponentState? state)
|
||||
{
|
||||
return new(false, netId, componentName);
|
||||
return new(netId, true, false, state);
|
||||
}
|
||||
|
||||
public static ComponentChanged Removed(uint netId)
|
||||
public static ComponentChange Changed(ushort netId, ComponentState state)
|
||||
{
|
||||
return new(true, netId, null);
|
||||
return new(netId, false, false, state);
|
||||
}
|
||||
|
||||
public static ComponentChange Removed(ushort netId)
|
||||
{
|
||||
return new(netId, false, true, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Players;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Robust.Shared.GameObjects
|
||||
@@ -13,16 +13,6 @@ namespace Robust.Shared.GameObjects
|
||||
/// </remarks>
|
||||
public interface IComponent
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the network ID for the component.
|
||||
/// The network ID is used to determine which component will receive the component state
|
||||
/// on the other side of the network.
|
||||
/// If this is <c>null</c>, the component is not replicated across the network.
|
||||
/// </summary>
|
||||
/// <seealso cref="NetworkSynchronizeExistence" />
|
||||
/// <seealso cref="IComponentRegistration.NetID" />
|
||||
uint? NetID { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Name that this component is represented with in prototypes.
|
||||
/// </summary>
|
||||
@@ -40,21 +30,11 @@ namespace Robust.Shared.GameObjects
|
||||
/// </summary>
|
||||
ComponentLifeStage LifeStage { 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.
|
||||
/// If this is true and the server adds or removes the component, the client will do as such too.
|
||||
/// This flag has no effect if <see cref="NetID" /> is <c>null</c>.
|
||||
/// This is disabled by default, usually the client builds their instance from a prototype.
|
||||
/// </summary>
|
||||
/// <seealso cref="IComponentRegistration.NetworkSynchronizeExistence" />
|
||||
bool NetworkSynchronizeExistence { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether this component should be synchronized with clients when modified.
|
||||
/// If this is true, the server will synchronize all client instances with the data in this instance.
|
||||
/// If this is false, clients can modify the data in their instances without being overwritten by the server.
|
||||
/// This flag has no effect if <see cref="NetID" /> is <c>null</c>.
|
||||
/// This flag has no effect if <see cref="NetworkedComponentAttribute" /> is not defined on the component.
|
||||
/// This is enabled by default.
|
||||
/// </summary>
|
||||
bool NetSyncEnabled { get; }
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Robust.Shared.GameObjects
|
||||
@@ -58,6 +59,16 @@ namespace Robust.Shared.GameObjects
|
||||
/// </summary>
|
||||
IEnumerable<Type> AllRegisteredTypes { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The subset of all registered components that are networked, so that they can be
|
||||
/// referenced between the client and the server.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This will be null if the network Ids have not been generated yet.
|
||||
/// </remarks>
|
||||
/// <seealso cref="GenerateNetIds"/>
|
||||
IReadOnlyList<IComponentRegistration>? NetworkedComponents { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Get whether a component is available right now.
|
||||
/// </summary>
|
||||
@@ -142,7 +153,7 @@ namespace Robust.Shared.GameObjects
|
||||
/// <exception cref="UnknownComponentException">
|
||||
/// Thrown if no component exists with the given id <see cref="netId"/>.
|
||||
/// </exception>
|
||||
IComponent GetComponent(uint netId);
|
||||
IComponent GetComponent(ushort netId);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the registration belonging to a component, throwing an exception if it does not exist.
|
||||
@@ -181,7 +192,7 @@ namespace Robust.Shared.GameObjects
|
||||
/// <exception cref="UnknownComponentException">
|
||||
/// Thrown if no component with id <see cref="netID"/> exists.
|
||||
/// </exception>
|
||||
IComponentRegistration GetRegistration(uint netID);
|
||||
IComponentRegistration GetRegistration(ushort netID);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the registration of a component, throwing an exception if
|
||||
@@ -225,7 +236,7 @@ namespace Robust.Shared.GameObjects
|
||||
/// <param name="netID">The network ID corresponding to the component.</param>
|
||||
/// <param name="registration">The registration if found, null otherwise.</param>
|
||||
/// <returns>true it found, false otherwise.</returns>
|
||||
bool TryGetRegistration(uint netID, [NotNullWhen(true)] out IComponentRegistration? registration);
|
||||
bool TryGetRegistration(ushort netID, [NotNullWhen(true)] out IComponentRegistration? registration);
|
||||
|
||||
/// <summary>
|
||||
/// Tries to get the registration of a component.
|
||||
@@ -241,8 +252,7 @@ namespace Robust.Shared.GameObjects
|
||||
void DoAutoRegistrations();
|
||||
|
||||
IEnumerable<Type> GetAllRefTypes();
|
||||
|
||||
IEnumerable<uint> GetAllNetIds();
|
||||
void GenerateNetIds();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -263,18 +273,8 @@ namespace Robust.Shared.GameObjects
|
||||
/// ID used to reference the component type across the network.
|
||||
/// If null, no network synchronization will be available for this component.
|
||||
/// </summary>
|
||||
/// <seealso cref="IComponent.NetID" />
|
||||
uint? NetID { get; }
|
||||
|
||||
/// <summary>
|
||||
/// True if the addition and removal of the component will be synchronized to clients.
|
||||
/// This means that if the server adds or removes the component outside of prototype-based creation,
|
||||
/// the client will update accordingly.
|
||||
/// If false the client will ignore missing components even when the net ID checks out and could be instantiated.
|
||||
/// and the client won't delete the component if no state was sent for it.
|
||||
/// </summary>
|
||||
/// <seealso cref="IComponent.NetworkSynchronizeExistence" />
|
||||
bool NetworkSynchronizeExistence { get; }
|
||||
/// <seealso cref="NetworkedComponentAttribute" />
|
||||
ushort? NetID { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The type that will be instantiated if this component is created.
|
||||
|
||||
@@ -72,7 +72,7 @@ namespace Robust.Shared.GameObjects
|
||||
/// </summary>
|
||||
/// <param name="uid">Entity UID to modify.</param>
|
||||
/// <param name="netID">Network ID of the component to remove.</param>
|
||||
void RemoveComponent(EntityUid uid, uint netID);
|
||||
void RemoveComponent(EntityUid uid, ushort netID);
|
||||
|
||||
/// <summary>
|
||||
/// Removes the specified component.
|
||||
@@ -118,7 +118,7 @@ namespace Robust.Shared.GameObjects
|
||||
/// <param name="uid">Entity UID to check.</param>
|
||||
/// <param name="netId">Network ID to check for.</param>
|
||||
/// <returns>True if the entity has a component with the given network ID, otherwise false.</returns>
|
||||
bool HasComponent(EntityUid uid, uint netId);
|
||||
bool HasComponent(EntityUid uid, ushort netId);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the component of a specific type.
|
||||
@@ -143,7 +143,7 @@ namespace Robust.Shared.GameObjects
|
||||
/// <param name="uid">Entity UID to look on.</param>
|
||||
/// <param name="netId">Network ID of the component to retrieve.</param>
|
||||
/// <returns>The component with the specified network id.</returns>
|
||||
IComponent GetComponent(EntityUid uid, uint netId);
|
||||
IComponent GetComponent(EntityUid uid, ushort netId);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the component of a specific type.
|
||||
@@ -171,7 +171,7 @@ namespace Robust.Shared.GameObjects
|
||||
/// <param name="netId">Component Network ID to check for.</param>
|
||||
/// <param name="component">Component with the specified network id.</param>
|
||||
/// <returns>If the component existed in the entity.</returns>
|
||||
bool TryGetComponent(EntityUid uid, uint netId, [NotNullWhen(true)] out IComponent? component);
|
||||
bool TryGetComponent(EntityUid uid, ushort netId, [NotNullWhen(true)] out IComponent? component);
|
||||
|
||||
/// <summary>
|
||||
/// Returns ALL component type instances on an entity. A single component instance
|
||||
@@ -195,7 +195,7 @@ namespace Robust.Shared.GameObjects
|
||||
/// </summary>
|
||||
/// <param name="uid">Entity UID to look on.</param>
|
||||
/// <returns>All components that have a network ID.</returns>
|
||||
IEnumerable<IComponent> GetNetComponents(EntityUid uid);
|
||||
NetComponentEnumerable GetNetComponents(EntityUid uid);
|
||||
|
||||
/// <summary>
|
||||
/// Returns ALL component instances of a specified type.
|
||||
|
||||
@@ -24,6 +24,7 @@ namespace Robust.Shared.GameObjects
|
||||
/// </summary>
|
||||
void FrameUpdate(float frameTime);
|
||||
|
||||
IComponentFactory ComponentFactory { get; }
|
||||
IComponentManager ComponentManager { get; }
|
||||
IEntitySystemManager EntitySysManager { get; }
|
||||
IEntityNetworkManager? EntityNetManager { get; }
|
||||
|
||||
@@ -104,15 +104,47 @@ namespace Robust.Shared.GameObjects
|
||||
SubscribeLocalEvent<PhysicsWakeMessage>(HandleWakeMessage);
|
||||
SubscribeLocalEvent<PhysicsSleepMessage>(HandleSleepMessage);
|
||||
SubscribeLocalEvent<EntMapIdChangedMessage>(HandleMapChange);
|
||||
|
||||
SubscribeLocalEvent<EntInsertedIntoContainerMessage>(HandleContainerInserted);
|
||||
SubscribeLocalEvent<EntRemovedFromContainerMessage>(HandleContainerRemoved);
|
||||
SubscribeLocalEvent<EntParentChangedMessage>(HandleParentChange);
|
||||
|
||||
BuildControllers();
|
||||
Logger.DebugS("physics", $"Found {_controllers.Count} physics controllers.");
|
||||
|
||||
IoCManager.Resolve<IIslandManager>().Initialize();
|
||||
}
|
||||
|
||||
private void HandleParentChange(EntParentChangedMessage args)
|
||||
{
|
||||
var entity = args.Entity;
|
||||
|
||||
if (!entity.Initialized ||
|
||||
!entity.TryGetComponent(out PhysicsComponent? body) ||
|
||||
entity.IsInContainer()) return;
|
||||
|
||||
var oldParent = args.OldParent;
|
||||
var linearVelocityDiff = Vector2.Zero;
|
||||
var angularVelocityDiff = 0f;
|
||||
|
||||
if (oldParent != null && oldParent.TryGetComponent(out PhysicsComponent? oldBody))
|
||||
{
|
||||
var (linear, angular) = oldBody.MapVelocities;
|
||||
|
||||
linearVelocityDiff += linear;
|
||||
angularVelocityDiff += angular;
|
||||
}
|
||||
|
||||
if (entity.Transform.Parent!.Owner.TryGetComponent(out PhysicsComponent? newBody))
|
||||
{
|
||||
var (linear, angular) = newBody.MapVelocities;
|
||||
|
||||
linearVelocityDiff -= linear;
|
||||
angularVelocityDiff -= angular;
|
||||
}
|
||||
|
||||
body.LinearVelocity += linearVelocityDiff;
|
||||
body.AngularVelocity += angularVelocityDiff;
|
||||
}
|
||||
|
||||
private void BuildControllers()
|
||||
{
|
||||
|
||||
10
Robust.Shared/GameStates/NetworkedComponentAttribute.cs
Normal file
10
Robust.Shared/GameStates/NetworkedComponentAttribute.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
using System;
|
||||
|
||||
namespace Robust.Shared.GameStates
|
||||
{
|
||||
/// <summary>
|
||||
/// This attribute marks a component as networked, so that it is replicated to clients.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class NetworkedComponentAttribute : Attribute { }
|
||||
}
|
||||
@@ -25,6 +25,11 @@
|
||||
/// </summary>
|
||||
string SpriteName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Path to the folder where the tile sprite is contained.
|
||||
/// </summary>
|
||||
string Path { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Physics objects that are interacting on this tile are slowed down by this float.
|
||||
/// </summary>
|
||||
|
||||
@@ -116,23 +116,6 @@ namespace Robust.Shared.Network
|
||||
/// </summary>
|
||||
event EventHandler<NetDisconnectedArgs> Disconnect;
|
||||
|
||||
#region StringTable
|
||||
|
||||
/// <summary>
|
||||
/// Registers a NetMessage to be sent or received.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type to register.</typeparam>
|
||||
/// <param name="name">String ID of the message.</param>
|
||||
/// <param name="rxCallback">Callback function to process the received message.</param>
|
||||
/// <param name="accept">
|
||||
/// The side of the network this message is accepted on.
|
||||
/// If we are not on the side specified, the receive callback will not be registered even if provided.
|
||||
/// </param>
|
||||
[Obsolete("Use the method without a name argument instead")]
|
||||
void RegisterNetMessage<T>(string name, ProcessMessage<T>? rxCallback = null,
|
||||
NetMessageAccept accept = NetMessageAccept.Both)
|
||||
where T : NetMessage;
|
||||
|
||||
/// <summary>
|
||||
/// Registers a NetMessage to be sent or received.
|
||||
/// </summary>
|
||||
@@ -156,8 +139,5 @@ namespace Robust.Shared.Network
|
||||
/// <typeparam name="T">Type of NetMessage to send.</typeparam>
|
||||
/// <returns>Instance of the NetMessage.</returns>
|
||||
T CreateNetMessage<T>() where T : NetMessage;
|
||||
|
||||
#endregion StringTable
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
using Lidgren.Network;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Robust.Shared.Network.Messages
|
||||
{
|
||||
public class MsgPlayerListReq : NetMessage
|
||||
|
||||
@@ -902,10 +902,11 @@ namespace Robust.Shared.Network
|
||||
#region NetMessages
|
||||
|
||||
/// <inheritdoc />
|
||||
public void RegisterNetMessage<T>(string name, ProcessMessage<T>? rxCallback = null,
|
||||
public void RegisterNetMessage<T>(ProcessMessage<T>? rxCallback = null,
|
||||
NetMessageAccept accept = NetMessageAccept.Both)
|
||||
where T : NetMessage
|
||||
where T : NetMessage, new()
|
||||
{
|
||||
var name = new T().MsgName;
|
||||
var id = _strings.AddString(name);
|
||||
|
||||
_messages.Add(name, typeof(T));
|
||||
@@ -928,14 +929,6 @@ namespace Robust.Shared.Network
|
||||
CacheBlankFunction(typeof(T));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void RegisterNetMessage<T>(ProcessMessage<T>? rxCallback = null,
|
||||
NetMessageAccept accept = NetMessageAccept.Both)
|
||||
where T : NetMessage, new()
|
||||
{
|
||||
RegisterNetMessage(new T().MsgName, rxCallback, accept);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public T CreateNetMessage<T>()
|
||||
where T : NetMessage
|
||||
|
||||
@@ -66,18 +66,6 @@ namespace Robust.Shared.Network
|
||||
/// </summary>
|
||||
public int MsgSize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Constructs an instance of the NetMessage.
|
||||
/// </summary>
|
||||
/// <param name="name">String identifier of the message type.</param>
|
||||
/// <param name="group">The group this message type belongs to.</param>
|
||||
[Obsolete("Use NetMessageAttribute and no constructor instead")]
|
||||
protected NetMessage(string name, MsgGroups group)
|
||||
{
|
||||
MsgName = name;
|
||||
MsgGroup = group;
|
||||
}
|
||||
|
||||
protected NetMessage()
|
||||
{
|
||||
MsgName = GetType().Name;
|
||||
|
||||
@@ -151,7 +151,6 @@ namespace Robust.Shared.Physics.Collision.Shapes
|
||||
m.R1C2 = modelMatrix.R1C2;
|
||||
handle.SetTransform(m);
|
||||
handle.DrawLine(Vertex1, Vertex2, handle.CalcWakeColor(handle.RectFillColor, sleepPercent));
|
||||
handle.SetTransform(in Matrix3.Identity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +82,6 @@ namespace Robust.Shared.Physics.Collision.Shapes
|
||||
|
||||
handle.SetTransform(m);
|
||||
handle.DrawRect(LocalBounds, handle.CalcWakeColor(handle.RectFillColor, sleepPercent));
|
||||
handle.SetTransform(in Matrix3.Identity);
|
||||
}
|
||||
|
||||
// TODO
|
||||
|
||||
@@ -78,7 +78,6 @@ namespace Robust.Shared.Physics.Collision.Shapes
|
||||
{
|
||||
handle.SetTransform(in modelMatrix);
|
||||
handle.DrawCircle(Vector2.Zero, _radius, handle.CalcWakeColor(handle.RectFillColor, sleepPercent));
|
||||
handle.SetTransform(in Matrix3.Identity);
|
||||
}
|
||||
|
||||
public bool Equals(IPhysShape? other)
|
||||
|
||||
@@ -70,7 +70,6 @@ namespace Robust.Shared.Physics.Collision.Shapes
|
||||
handle.DrawRect(localBox, handle.CalcWakeColor(handle.GridFillColor, sleepPercent));
|
||||
}
|
||||
}
|
||||
handle.SetTransform(in Matrix3.Identity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -60,7 +60,6 @@ namespace Robust.Shared.Physics.Collision.Shapes
|
||||
var rotationMatrix = Matrix3.CreateRotation(Math.PI);
|
||||
handle.SetTransform(rotationMatrix * modelMatrix);
|
||||
handle.DrawRect(Rectangle, handle.CalcWakeColor(handle.RectFillColor, sleepPercent));
|
||||
handle.SetTransform(in Matrix3.Identity);
|
||||
}
|
||||
|
||||
[field: NonSerialized]
|
||||
|
||||
@@ -188,7 +188,6 @@ namespace Robust.Shared.Physics.Collision.Shapes
|
||||
{
|
||||
handle.SetTransform(modelMatrix);
|
||||
handle.DrawPolygonShape(_vertices.ToArray(), handle.CalcWakeColor(handle.RectFillColor, sleepPercent));
|
||||
handle.SetTransform(in Matrix3.Identity);
|
||||
}
|
||||
|
||||
public static explicit operator PolygonShape(PhysShapeAabb aabb)
|
||||
|
||||
@@ -12,10 +12,16 @@ namespace Robust.Shared.Serialization.Manager.Result
|
||||
|
||||
public abstract void CallAfterDeserializationHook();
|
||||
|
||||
public static DeserializationResult Value<T>(T value) where T : notnull
|
||||
public static DeserializationResult Value<T>(T value)
|
||||
{
|
||||
var type = typeof(DeserializedValue<>).MakeGenericType(value.GetType());
|
||||
return (DeserializationResult) Activator.CreateInstance(type, value)!;
|
||||
return Value(typeof(T), value);
|
||||
}
|
||||
|
||||
public static DeserializationResult Value(Type type, object? value)
|
||||
{
|
||||
var genericType = typeof(DeserializedValue<>).MakeGenericType(type);
|
||||
return (DeserializationResult) Activator.CreateInstance(genericType, value)!;
|
||||
|
||||
}
|
||||
|
||||
public T Cast<T>() where T : DeserializationResult
|
||||
|
||||
@@ -115,6 +115,8 @@ namespace Robust.Shared.Serialization.Manager
|
||||
_copyByRefRegistrations.Add(type);
|
||||
}
|
||||
|
||||
_copyByRefRegistrations.Add(typeof(Type));
|
||||
|
||||
_initialized = true;
|
||||
_initializing = false;
|
||||
}
|
||||
@@ -299,6 +301,11 @@ namespace Robust.Shared.Serialization.Manager
|
||||
|
||||
public DeserializationResult Read(Type type, DataNode node, ISerializationContext? context = null, bool skipHook = false)
|
||||
{
|
||||
if (type.IsNullable() && node is ValueDataNode {Value: "null"})
|
||||
{
|
||||
return DeserializationResult.Value(type, null);
|
||||
}
|
||||
|
||||
var underlyingType = type.EnsureNotNullableType();
|
||||
|
||||
if (underlyingType.IsArray)
|
||||
|
||||
@@ -214,9 +214,9 @@ namespace Robust.Shared.Serialization
|
||||
/// <seealso cref="OnClientCompleteHandshake"/>
|
||||
private void NetworkInitialize()
|
||||
{
|
||||
_net.RegisterNetMessage<MsgMapStrServerHandshake>(nameof(MsgMapStrServerHandshake), HandleServerHandshake, NetMessageAccept.Client);
|
||||
_net.RegisterNetMessage<MsgMapStrClientHandshake>(nameof(MsgMapStrClientHandshake), HandleClientHandshake, NetMessageAccept.Server);
|
||||
_net.RegisterNetMessage<MsgMapStrStrings>(nameof(MsgMapStrStrings), HandleStringsMessage, NetMessageAccept.Client);
|
||||
_net.RegisterNetMessage<MsgMapStrServerHandshake>(HandleServerHandshake, NetMessageAccept.Client);
|
||||
_net.RegisterNetMessage<MsgMapStrClientHandshake>(HandleClientHandshake, NetMessageAccept.Server);
|
||||
_net.RegisterNetMessage<MsgMapStrStrings>(HandleStringsMessage, NetMessageAccept.Client);
|
||||
|
||||
_net.Disconnect += NetOnDisconnect;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Reflection;
|
||||
using Robust.Shared.Serialization.Manager;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.Serialization.Manager.Result;
|
||||
using Robust.Shared.Serialization.Markdown;
|
||||
using Robust.Shared.Serialization.Markdown.Validation;
|
||||
using Robust.Shared.Serialization.Markdown.Value;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Interfaces;
|
||||
|
||||
namespace Robust.Shared.Serialization.TypeSerializers.Implementations
|
||||
{
|
||||
[TypeSerializer]
|
||||
public class TypeSerializer : ITypeSerializer<Type, ValueDataNode>
|
||||
{
|
||||
private static readonly Dictionary<string, Type> _shortcuts = new ()
|
||||
{
|
||||
{"bool", typeof(bool)}
|
||||
};
|
||||
|
||||
public ValidationNode Validate(ISerializationManager serializationManager, ValueDataNode node,
|
||||
IDependencyCollection dependencies, ISerializationContext? context = null)
|
||||
{
|
||||
if (_shortcuts.ContainsKey(node.Value)) return new ValidatedValueNode(node);
|
||||
|
||||
return dependencies.Resolve<IReflectionManager>().GetType(node.Value) == null
|
||||
? new ErrorNode(node, $"Type '{node.Value}' not found.")
|
||||
: new ValidatedValueNode(node);
|
||||
}
|
||||
|
||||
public DeserializationResult Read(ISerializationManager serializationManager, ValueDataNode node,
|
||||
IDependencyCollection dependencies, bool skipHook, ISerializationContext? context = null)
|
||||
{
|
||||
if(_shortcuts.TryGetValue(node.Value, out var shortcutType)) return DeserializationResult.Value(shortcutType);
|
||||
|
||||
var type = dependencies.Resolve<IReflectionManager>().GetType(node.Value);
|
||||
if (type == null) throw new InvalidMappingException($"Type '{node.Value}' not found.");
|
||||
return DeserializationResult.Value(type);
|
||||
}
|
||||
|
||||
public DataNode Write(ISerializationManager serializationManager, Type value, bool alwaysWrite = false,
|
||||
ISerializationContext? context = null)
|
||||
{
|
||||
return new ValueDataNode(value.FullName ?? value.Name);
|
||||
}
|
||||
|
||||
public Type Copy(ISerializationManager serializationManager, Type source, Type target, bool skipHook,
|
||||
ISerializationContext? context = null)
|
||||
{
|
||||
return source;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace Robust.Shared.Utility
|
||||
{
|
||||
@@ -37,6 +38,18 @@ namespace Robust.Shared.Utility
|
||||
return dict;
|
||||
}
|
||||
|
||||
public static bool TryGetValue<T>(this IList<T> list, int index, out T value)
|
||||
{
|
||||
if (list.Count > index)
|
||||
{
|
||||
value = list[index];
|
||||
return true;
|
||||
}
|
||||
|
||||
value = default!;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove an item from the list, replacing it with the one at the very end of the list.
|
||||
/// This means that the order will not be preserved, but it should be an O(1) operation.
|
||||
|
||||
@@ -272,9 +272,9 @@ namespace Robust.UnitTesting
|
||||
public event EventHandler<NetChannelArgs>? Connected;
|
||||
public event EventHandler<NetDisconnectedArgs>? Disconnect;
|
||||
|
||||
public void RegisterNetMessage<T>(string name, ProcessMessage<T>? rxCallback = null,
|
||||
NetMessageAccept accept = NetMessageAccept.Both) where T : NetMessage
|
||||
public void RegisterNetMessage<T>(ProcessMessage<T>? rxCallback = null, NetMessageAccept accept = NetMessageAccept.Both) where T : NetMessage, new()
|
||||
{
|
||||
var name = new T().MsgName;
|
||||
var thisSide = IsServer ? NetMessageAccept.Server : NetMessageAccept.Client;
|
||||
|
||||
_registeredMessages.Add(typeof(T));
|
||||
@@ -282,11 +282,6 @@ namespace Robust.UnitTesting
|
||||
_callbacks.Add(typeof(T), msg => rxCallback((T) msg));
|
||||
}
|
||||
|
||||
public void RegisterNetMessage<T>(ProcessMessage<T>? rxCallback = null, NetMessageAccept accept = NetMessageAccept.Both) where T : NetMessage, new()
|
||||
{
|
||||
RegisterNetMessage(new T().MsgName, rxCallback, accept);
|
||||
}
|
||||
|
||||
public T CreateNetMessage<T>() where T : NetMessage
|
||||
{
|
||||
var type = typeof(T);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
@@ -267,7 +267,6 @@ namespace Robust.UnitTesting.Server.GameObjects.Components
|
||||
var containerMan = entity.GetComponent<IContainerManager>();
|
||||
var state = (ContainerManagerComponent.ContainerManagerComponentState)containerMan.GetComponentState(new Mock<ICommonSession>().Object);
|
||||
|
||||
Assert.That(state.NetID, Is.EqualTo(containerMan.NetID));
|
||||
Assert.That(state.ContainerSet.Count, Is.EqualTo(1));
|
||||
Assert.That(state.ContainerSet[0].Id, Is.EqualTo("dummy"));
|
||||
Assert.That(state.ContainerSet[0].OccludesLight, Is.True);
|
||||
|
||||
@@ -62,6 +62,8 @@ namespace Robust.UnitTesting.Server.GameObjects.Components
|
||||
[OneTimeSetUp]
|
||||
public void Setup()
|
||||
{
|
||||
IoCManager.Resolve<IComponentFactory>().GenerateNetIds();
|
||||
|
||||
EntityManager = IoCManager.Resolve<IServerEntityManagerInternal>();
|
||||
MapManager = IoCManager.Resolve<IMapManager>();
|
||||
MapManager.CreateMap();
|
||||
|
||||
@@ -41,6 +41,7 @@ namespace Robust.UnitTesting.Server.GameObjects
|
||||
_componentFactory.RegisterClass<ThrowsInAddComponent>();
|
||||
_componentFactory.RegisterClass<ThrowsInInitializeComponent>();
|
||||
_componentFactory.RegisterClass<ThrowsInStartupComponent>();
|
||||
_componentFactory.GenerateNetIds();
|
||||
|
||||
EntityManager = IoCManager.Resolve<IServerEntityManager>();
|
||||
MapManager = IoCManager.Resolve<IMapManager>();
|
||||
|
||||
@@ -84,6 +84,7 @@ entities:
|
||||
{
|
||||
var compFactory = IoCManager.Resolve<IComponentFactory>();
|
||||
compFactory.RegisterClass<MapDeserializeTestComponent>();
|
||||
compFactory.GenerateNetIds();
|
||||
IoCManager.Resolve<ISerializationManager>().Initialize();
|
||||
|
||||
var resourceManager = IoCManager.Resolve<IResourceManagerInternal>();
|
||||
|
||||
@@ -10,6 +10,7 @@ using Robust.Server.Reflection;
|
||||
using Robust.Shared;
|
||||
using Robust.Shared.Asynchronous;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.ContentPack;
|
||||
using Robust.Shared.Exceptions;
|
||||
using Robust.Shared.GameObjects;
|
||||
@@ -190,6 +191,7 @@ namespace Robust.UnitTesting.Server
|
||||
container.RegisterInstance<IGameTiming>(new Mock<IGameTiming>().Object); // TODO: get timing working similar to RobustIntegrationTest
|
||||
|
||||
//Tier 2: Simulation
|
||||
container.RegisterInstance<IConsoleHost>(new Mock<IConsoleHost>().Object); //Console is technically a frontend, we want to run headless
|
||||
container.Register<IEntityManager, EntityManager>();
|
||||
container.Register<IMapManager, MapManager>();
|
||||
container.Register<IEntityLookup, EntityLookup>();
|
||||
@@ -226,6 +228,8 @@ namespace Robust.UnitTesting.Server
|
||||
|
||||
_regDelegate?.Invoke(compFactory);
|
||||
|
||||
compFactory.GenerateNetIds();
|
||||
|
||||
var entityMan = container.Resolve<IEntityManager>();
|
||||
entityMan.Initialize();
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.IO;
|
||||
using NUnit.Framework;
|
||||
using Robust.Shared.ContentPack;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
@@ -61,6 +62,9 @@ namespace Robust.UnitTesting.Shared.ContentPack
|
||||
[OneTimeSetUp]
|
||||
public void Setup()
|
||||
{
|
||||
var componentFactory = IoCManager.Resolve<IComponentFactory>();
|
||||
componentFactory.GenerateNetIds();
|
||||
|
||||
var stream = new MemoryStream(Data);
|
||||
var resourceManager = IoCManager.Resolve<IResourceManagerInternal>();
|
||||
resourceManager.MountStreamAt(stream, new ResourcePath("/a/b/c.dat"));
|
||||
|
||||
@@ -164,6 +164,7 @@ namespace Robust.UnitTesting.Shared.GameObjects
|
||||
componentFactory.RegisterClass<TestFiveComponent>();
|
||||
componentFactory.RegisterClass<TestSixComponent>();
|
||||
componentFactory.RegisterClass<TestSevenComponent>();
|
||||
componentFactory.GenerateNetIds();
|
||||
|
||||
IoCManager.Resolve<ISerializationManager>().Initialize();
|
||||
var prototypeManager = IoCManager.Resolve<IPrototypeManager>();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.UnitTesting.Server;
|
||||
@@ -10,7 +11,6 @@ namespace Robust.UnitTesting.Shared.GameObjects
|
||||
[TestFixture, Parallelizable ,TestOf(typeof(ComponentManager))]
|
||||
public class ComponentManager_Tests
|
||||
{
|
||||
private const uint CompNetId = 3;
|
||||
private static readonly EntityCoordinates DefaultCoords = new(new EntityUid(1), Vector2.Zero);
|
||||
|
||||
[Test]
|
||||
@@ -98,13 +98,17 @@ namespace Robust.UnitTesting.Shared.GameObjects
|
||||
{
|
||||
// Arrange
|
||||
var sim = SimulationFactory();
|
||||
|
||||
var factory = sim.Resolve<IComponentFactory>();
|
||||
var netId = factory.GetRegistration<DummyComponent>().NetID!;
|
||||
|
||||
var entMan = sim.Resolve<IEntityManager>();
|
||||
var manager = sim.Resolve<IComponentManager>();
|
||||
var entity = entMan.SpawnEntity(null, DefaultCoords);
|
||||
entity.AddComponent<DummyComponent>();
|
||||
|
||||
// Act
|
||||
var result = manager.HasComponent(entity.Uid, CompNetId);
|
||||
var result = manager.HasComponent(entity.Uid, netId.Value);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.True);
|
||||
@@ -115,13 +119,17 @@ namespace Robust.UnitTesting.Shared.GameObjects
|
||||
{
|
||||
// Arrange
|
||||
var sim = SimulationFactory();
|
||||
|
||||
var factory = sim.Resolve<IComponentFactory>();
|
||||
var netId = factory.GetRegistration<DummyComponent>().NetID!;
|
||||
|
||||
var entMan = sim.Resolve<IEntityManager>();
|
||||
var manager = sim.Resolve<IComponentManager>();
|
||||
var entity = entMan.SpawnEntity(null, DefaultCoords);
|
||||
var component = entity.AddComponent<DummyComponent>();
|
||||
|
||||
// Act
|
||||
var result = manager.GetComponent(entity.Uid, CompNetId);
|
||||
var result = manager.GetComponent(entity.Uid, netId.Value);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo(component));
|
||||
@@ -150,13 +158,17 @@ namespace Robust.UnitTesting.Shared.GameObjects
|
||||
{
|
||||
// Arrange
|
||||
var sim = SimulationFactory();
|
||||
|
||||
var factory = sim.Resolve<IComponentFactory>();
|
||||
var netId = factory.GetRegistration<DummyComponent>().NetID!;
|
||||
|
||||
var entMan = sim.Resolve<IEntityManager>();
|
||||
var manager = sim.Resolve<IComponentManager>();
|
||||
var entity = entMan.SpawnEntity(null, DefaultCoords);
|
||||
var component = entity.AddComponent<DummyComponent>();
|
||||
|
||||
// Act
|
||||
var result = manager.TryGetComponent(entity.Uid, CompNetId, out var comp);
|
||||
var result = manager.TryGetComponent(entity.Uid, netId.Value, out var comp);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.True);
|
||||
@@ -186,13 +198,17 @@ namespace Robust.UnitTesting.Shared.GameObjects
|
||||
{
|
||||
// Arrange
|
||||
var sim = SimulationFactory();
|
||||
|
||||
var factory = sim.Resolve<IComponentFactory>();
|
||||
var netId = factory.GetRegistration<DummyComponent>().NetID!;
|
||||
|
||||
var entMan = sim.Resolve<IEntityManager>();
|
||||
var manager = sim.Resolve<IComponentManager>();
|
||||
var entity = entMan.SpawnEntity(null, DefaultCoords);
|
||||
var component = entity.AddComponent<DummyComponent>();
|
||||
|
||||
// Act
|
||||
manager.RemoveComponent(entity.Uid, CompNetId);
|
||||
manager.RemoveComponent(entity.Uid, netId.Value);
|
||||
manager.CullRemovedComponents();
|
||||
|
||||
// Assert
|
||||
@@ -269,10 +285,10 @@ namespace Robust.UnitTesting.Shared.GameObjects
|
||||
return sim;
|
||||
}
|
||||
|
||||
[NetworkedComponent()]
|
||||
private class DummyComponent : Component, ICompType1, ICompType2
|
||||
{
|
||||
public override string Name => "Dummy";
|
||||
public override uint? NetID => CompNetId;
|
||||
}
|
||||
|
||||
private interface ICompType1 { }
|
||||
|
||||
@@ -60,11 +60,7 @@ namespace Robust.UnitTesting.Shared.GameObjects
|
||||
new EntityUid(512),
|
||||
new []
|
||||
{
|
||||
new ComponentChanged(false, NetIDs.MAP_GRID, nameof(MapGridComponent)),
|
||||
},
|
||||
new []
|
||||
{
|
||||
new MapGridComponentState(new GridId(0)),
|
||||
new ComponentChange(0, true, false, new MapGridComponentState(new GridId(0)))
|
||||
});
|
||||
|
||||
serializer.Serialize(stream, payload);
|
||||
|
||||
@@ -19,7 +19,6 @@ namespace Robust.UnitTesting.Shared.GameObjects.Systems
|
||||
|
||||
private class Subscriber : IEntityEventSubscriber { }
|
||||
|
||||
|
||||
private const string Prototypes = @"
|
||||
- type: entity
|
||||
name: anchoredEnt
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using NUnit.Framework;
|
||||
@@ -21,7 +21,9 @@ namespace Robust.UnitTesting.Shared.Localization
|
||||
public void Setup()
|
||||
{
|
||||
IoCManager.Resolve<ISerializationManager>().Initialize();
|
||||
IoCManager.Resolve<IComponentFactory>().RegisterClass<GrammarComponent>();
|
||||
var componentFactory = IoCManager.Resolve<IComponentFactory>();
|
||||
componentFactory.RegisterClass<GrammarComponent>();
|
||||
componentFactory.GenerateNetIds();
|
||||
|
||||
var res = IoCManager.Resolve<IResourceManagerInternal>();
|
||||
res.MountString("/Locale/en-US/a.ftl", FluentCode);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.IO;
|
||||
using System.IO;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Robust.Server.GameObjects;
|
||||
@@ -44,6 +44,9 @@ namespace Robust.UnitTesting.Shared.Map
|
||||
var prototypeManager = IoCManager.Resolve<IPrototypeManager>();
|
||||
prototypeManager.LoadFromStream(new StringReader(PROTOTYPES));
|
||||
prototypeManager.Resync();
|
||||
|
||||
var factory = IoCManager.Resolve<IComponentFactory>();
|
||||
factory.GenerateNetIds();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -28,6 +28,12 @@ namespace Robust.UnitTesting.Shared.Map
|
||||
IoCManager.RegisterInstance<IEntitySystemManager>(mock.Object, true);
|
||||
}
|
||||
|
||||
[OneTimeSetUp]
|
||||
public void Setup()
|
||||
{
|
||||
IoCManager.Resolve<IComponentFactory>().GenerateNetIds();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetTileRefCoords()
|
||||
{
|
||||
|
||||
@@ -77,5 +77,37 @@ namespace Robust.UnitTesting.Shared.Maths
|
||||
var rotated = new Box2Rotated(baseBox, rotation, origin);
|
||||
Assert.That(rotated.CalcBoundingBoxSse(), Is.Approximately(expected));
|
||||
}
|
||||
|
||||
// Offset it just to make sure the rotation is also gucci.
|
||||
private static readonly Vector2 Offset = new Vector2(10.0f, 10.0f);
|
||||
|
||||
private static Box2Rotated IntersectionBox = new(Box2.UnitCentered.Translated(Offset), Angle.FromDegrees(45));
|
||||
|
||||
private static IEnumerable<Vector2> InboundPoints => new Vector2[]
|
||||
{
|
||||
Offset,
|
||||
Offset - new Vector2(-0.5f, 0.0f),
|
||||
Offset + new Vector2(0.1f, 0.1f),
|
||||
};
|
||||
|
||||
[Test]
|
||||
public void TestPointIntersect([ValueSource(nameof(InboundPoints))] Vector2 point)
|
||||
{
|
||||
Assert.That(IntersectionBox.Contains(point), $"Rotated box doesn't contain {point}");
|
||||
}
|
||||
|
||||
private static IEnumerable<Vector2> OutboundPoints => new Vector2[]
|
||||
{
|
||||
Offset + new Vector2(-0.48f, -0.48f),
|
||||
Offset + new Vector2(-0.48f, 0.48f),
|
||||
Offset + new Vector2(0.48f, 0.48f),
|
||||
Offset + new Vector2(0.48f, -0.48f),
|
||||
};
|
||||
|
||||
[Test]
|
||||
public void TestPointNoIntersect([ValueSource(nameof(OutboundPoints))] Vector2 point)
|
||||
{
|
||||
Assert.That(!IntersectionBox.Contains(point), $"Rotated box contains {point}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
62
Robust.UnitTesting/Shared/Physics/MapVelocity_Test.cs
Normal file
62
Robust.UnitTesting/Shared/Physics/MapVelocity_Test.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
using System.Threading.Tasks;
|
||||
using NUnit.Framework;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Physics;
|
||||
|
||||
namespace Robust.UnitTesting.Shared.Physics
|
||||
{
|
||||
public class MapVelocity_Test : RobustIntegrationTest
|
||||
{
|
||||
private const string DummyEntity = "Dummy";
|
||||
|
||||
private static readonly string Prototypes = $@"
|
||||
- type: entity
|
||||
name: {DummyEntity}
|
||||
id: {DummyEntity}
|
||||
components:
|
||||
- type: Physics
|
||||
bodyType: Dynamic
|
||||
";
|
||||
|
||||
[Test]
|
||||
public async Task Test()
|
||||
{
|
||||
var server = StartServer(new ServerIntegrationOptions {ExtraPrototypes = Prototypes});
|
||||
|
||||
await server.WaitIdleAsync();
|
||||
var compManager = server.ResolveDependency<IComponentManager>();
|
||||
var entityManager = server.ResolveDependency<IEntityManager>();
|
||||
var mapManager = server.ResolveDependency<IMapManager>();
|
||||
|
||||
await server.WaitAssertion(() =>
|
||||
{
|
||||
var mapId = mapManager.CreateMap();
|
||||
var grid = mapManager.CreateGrid(mapId);
|
||||
|
||||
Assert.That(compManager.TryGetComponent<PhysicsComponent>(grid.GridEntityId, out var gridPhysics));
|
||||
|
||||
// TODO: Once grid rotations are a stable thing try it with angular velocity too.
|
||||
// Check that grid even moving first
|
||||
gridPhysics.BodyType = BodyType.Dynamic;
|
||||
gridPhysics.LinearVelocity = Vector2.One;
|
||||
Assert.That(gridPhysics.LinearVelocity, Is.EqualTo(Vector2.One));
|
||||
|
||||
// Check that map velocity is correct for entity
|
||||
var dummy = entityManager.SpawnEntity(DummyEntity, new EntityCoordinates(grid.GridEntityId, Vector2.Zero));
|
||||
Assert.That(compManager.TryGetComponent<PhysicsComponent>(dummy.Uid, out var body));
|
||||
Assert.That(body.LinearVelocity, Is.EqualTo(Vector2.Zero));
|
||||
|
||||
Assert.That(body.MapLinearVelocity, Is.EqualTo(Vector2.One));
|
||||
|
||||
// Check that the newly parented entity's velocity is correct
|
||||
// it should retain its previous velocity despite new parent
|
||||
var grid2 = mapManager.CreateGrid(mapId);
|
||||
dummy.Transform.AttachParent(entityManager.GetEntity(grid2.GridEntityId));
|
||||
|
||||
Assert.That(body.MapLinearVelocity, Is.EqualTo(Vector2.One));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
@@ -42,6 +42,7 @@ namespace Robust.UnitTesting.Shared.Prototypes
|
||||
_components = IoCManager.Resolve<IComponentFactory>();
|
||||
_components.RegisterClass<HotReloadTestComponentOne>();
|
||||
_components.RegisterClass<HotReloadTestComponentTwo>();
|
||||
_components.GenerateNetIds();
|
||||
|
||||
IoCManager.Resolve<ISerializationManager>().Initialize();
|
||||
_prototypes = (PrototypeManager) IoCManager.Resolve<IPrototypeManager>();
|
||||
|
||||
@@ -51,6 +51,7 @@ namespace Robust.UnitTesting.Shared.Serialization
|
||||
componentFactory.RegisterClass<BaseComponent>();
|
||||
componentFactory.RegisterClass<InheritorComponent>();
|
||||
componentFactory.RegisterClass<FinalComponent>();
|
||||
componentFactory.GenerateNetIds();
|
||||
|
||||
var serializationManager = IoCManager.Resolve<ISerializationManager>();
|
||||
serializationManager.Initialize();
|
||||
|
||||
Reference in New Issue
Block a user