diff --git a/Content.Client/Construction/ConstructionMenuPresenter.cs b/Content.Client/Construction/ConstructionMenuPresenter.cs index fdd7aede4c..09f9fde8fb 100644 --- a/Content.Client/Construction/ConstructionMenuPresenter.cs +++ b/Content.Client/Construction/ConstructionMenuPresenter.cs @@ -6,7 +6,6 @@ using Content.Client.GameObjects.EntitySystems; using Content.Client.UserInterface; using Content.Client.Utility; using Content.Shared.Construction; -using Content.Shared.GameObjects.Components; using Content.Shared.GameObjects.Components.Interactable; using Robust.Client.Graphics; using Robust.Client.Placement; @@ -18,7 +17,6 @@ using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Localization; using Robust.Shared.Prototypes; -using Robust.Shared.Utility; namespace Content.Client.Construction { @@ -224,15 +222,21 @@ namespace Content.Client.Construction var startNode = graph.Nodes[prototype.StartNode]; var targetNode = graph.Nodes[prototype.TargetNode]; - var path = graph.Path(startNode.Name, targetNode.Name); + if (!graph.TryPath(startNode.Name, targetNode.Name, out var path)) + { + return; + } var current = startNode; - var stepNumber = 1; foreach (var node in path) { - var edge = current.GetEdge(node.Name); + if (!current.TryGetEdge(node.Name, out var edge)) + { + continue; + } + var firstNode = current == startNode; if (firstNode) diff --git a/Content.Client/GameObjects/Components/Atmos/GasAnalyzerMenu.cs b/Content.Client/GameObjects/Components/Atmos/GasAnalyzerMenu.cs index 89e7767e2e..059520cc39 100644 --- a/Content.Client/GameObjects/Components/Atmos/GasAnalyzerMenu.cs +++ b/Content.Client/GameObjects/Components/Atmos/GasAnalyzerMenu.cs @@ -165,7 +165,7 @@ namespace Content.Client.GameObjects.Components.Atmos TemperatureHelpers.KelvinToCelsius(state.Temperature)) }); // Return here cause all that stuff down there is gas stuff (so we don't get the seperators) - if (state.Gases.Length == 0) + if (state.Gases == null || state.Gases.Length == 0) { return; } diff --git a/Content.Client/GameObjects/Components/Construction/ConstructionGhostComponent.cs b/Content.Client/GameObjects/Components/Construction/ConstructionGhostComponent.cs index 0505bac60e..10bd810bfb 100644 --- a/Content.Client/GameObjects/Components/Construction/ConstructionGhostComponent.cs +++ b/Content.Client/GameObjects/Components/Construction/ConstructionGhostComponent.cs @@ -27,8 +27,13 @@ namespace Content.Client.GameObjects.Components.Construction if (!_prototypeManager.TryIndex(Prototype.Graph, out ConstructionGraphPrototype? graph)) return; var startNode = graph.Nodes[Prototype.StartNode]; - var path = graph.Path(Prototype.StartNode, Prototype.TargetNode); - var edge = startNode.GetEdge(path[0].Name); + + if (!graph.TryPath(Prototype.StartNode, Prototype.TargetNode, out var path) || + !startNode.TryGetEdge(path[0].Name, out var edge)) + { + return; + } + edge.Steps[0].DoExamine(message, inDetailsRange); } } diff --git a/Content.Client/GameObjects/EntitySystems/DragDropSystem.cs b/Content.Client/GameObjects/EntitySystems/DragDropSystem.cs index f82fefa31d..a707367645 100644 --- a/Content.Client/GameObjects/EntitySystems/DragDropSystem.cs +++ b/Content.Client/GameObjects/EntitySystems/DragDropSystem.cs @@ -20,6 +20,7 @@ using Robust.Shared.Localization; using Robust.Shared.Log; using Robust.Shared.Maths; using Robust.Shared.Prototypes; +using Robust.Shared.Utility; using DrawDepth = Content.Shared.GameObjects.DrawDepth; namespace Content.Client.GameObjects.EntitySystems @@ -217,8 +218,11 @@ namespace Content.Client.GameObjects.EntitySystems { return false; } + + DebugTools.AssertNotNull(_dragger); + // still in range of the thing we are dragging? - if (!_interactionSystem.InRangeUnobstructed(_dragger, _dragDropHelper.Dragged)) + if (!_interactionSystem.InRangeUnobstructed(_dragger!, _dragDropHelper.Dragged)) { return false; } diff --git a/Content.Server/AI/Operators/Inventory/CloseStorageOperator.cs b/Content.Server/AI/Operators/Inventory/CloseStorageOperator.cs index 44ca81d991..8de3086357 100644 --- a/Content.Server/AI/Operators/Inventory/CloseStorageOperator.cs +++ b/Content.Server/AI/Operators/Inventory/CloseStorageOperator.cs @@ -66,7 +66,7 @@ namespace Content.Server.AI.Operators.Inventory if (storageComponent.Open) { - var activateArgs = new ActivateEventArgs {User = _owner, Target = _target}; + var activateArgs = new ActivateEventArgs(_owner, _target); storageComponent.Activate(activateArgs); } diff --git a/Content.Server/AI/Operators/Inventory/OpenStorageOperator.cs b/Content.Server/AI/Operators/Inventory/OpenStorageOperator.cs index e13c463fc8..d1823631d9 100644 --- a/Content.Server/AI/Operators/Inventory/OpenStorageOperator.cs +++ b/Content.Server/AI/Operators/Inventory/OpenStorageOperator.cs @@ -43,7 +43,7 @@ namespace Content.Server.AI.Operators.Inventory if (!storageComponent.Open) { - var activateArgs = new ActivateEventArgs {User = _owner, Target = _target}; + var activateArgs = new ActivateEventArgs(_owner, _target); storageComponent.Activate(activateArgs); } diff --git a/Content.Server/GameObjects/Components/Atmos/GasAnalyzerComponent.cs b/Content.Server/GameObjects/Components/Atmos/GasAnalyzerComponent.cs index baf42d1418..6f57f06001 100644 --- a/Content.Server/GameObjects/Components/Atmos/GasAnalyzerComponent.cs +++ b/Content.Server/GameObjects/Components/Atmos/GasAnalyzerComponent.cs @@ -239,7 +239,7 @@ namespace Content.Server.GameObjects.Components.Atmos var activeHandEntity = handsComponent.GetActiveHand?.Owner; if (activeHandEntity == null || !activeHandEntity.TryGetComponent(out GasAnalyzerComponent? gasAnalyzer)) { - serverMsg.Session.AttachedEntity.PopupMessage(Loc.GetString("You need a Gas Analyzer in your hand!")); + serverMsg.Session.AttachedEntity?.PopupMessage(Loc.GetString("You need a Gas Analyzer in your hand!")); return; } diff --git a/Content.Server/GameObjects/Components/Body/MechanismComponent.cs b/Content.Server/GameObjects/Components/Body/MechanismComponent.cs index c89b4b7d55..1fe339b346 100644 --- a/Content.Server/GameObjects/Components/Body/MechanismComponent.cs +++ b/Content.Server/GameObjects/Components/Body/MechanismComponent.cs @@ -88,7 +88,7 @@ namespace Content.Server.GameObjects.Components.Body } else // If surgery cannot be performed, show message saying so. { - eventArgs.Target.PopupMessage(eventArgs.User, + eventArgs.Target?.PopupMessage(eventArgs.User, Loc.GetString("You see no way to install the {0}.", Owner.Name)); } } diff --git a/Content.Server/GameObjects/Components/Body/Part/BodyPartComponent.cs b/Content.Server/GameObjects/Components/Body/Part/BodyPartComponent.cs index 95e231581d..35ca191558 100644 --- a/Content.Server/GameObjects/Components/Body/Part/BodyPartComponent.cs +++ b/Content.Server/GameObjects/Components/Body/Part/BodyPartComponent.cs @@ -155,7 +155,7 @@ namespace Content.Server.GameObjects.Components.Body.Part } else // If surgery cannot be performed, show message saying so. { - eventArgs.Target.PopupMessage(eventArgs.User, + eventArgs.Target?.PopupMessage(eventArgs.User, Loc.GetString("You see no way to install {0:theName}.", Owner)); } } diff --git a/Content.Server/GameObjects/Components/Body/Surgery/SurgeryToolComponent.cs b/Content.Server/GameObjects/Components/Body/Surgery/SurgeryToolComponent.cs index 1adcce5967..be21308370 100644 --- a/Content.Server/GameObjects/Components/Body/Surgery/SurgeryToolComponent.cs +++ b/Content.Server/GameObjects/Components/Body/Surgery/SurgeryToolComponent.cs @@ -16,8 +16,6 @@ using Robust.Server.Player; using Robust.Shared.GameObjects; using Robust.Shared.Localization; using Robust.Shared.Log; -using Robust.Shared.Prototypes; -using Robust.Shared.Serialization; using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.ViewVariables; @@ -246,7 +244,9 @@ namespace Content.Server.GameObjects.Components.Body.Surgery private void HandleReceiveMechanism(int key) { // TODO: sanity checks to see whether user is in range, user is still able-bodied, target is still the same, etc etc - if (!_optionsCache.TryGetValue(key, out var targetObject) || + if (BodyCache == null || + !_optionsCache.TryGetValue(key, out var targetObject) || + targetObject is not MechanismComponent target || PerformerCache == null || !PerformerCache.TryGetComponent(out IActorComponent? actor)) { @@ -254,20 +254,22 @@ namespace Content.Server.GameObjects.Components.Body.Surgery return; } - var target = targetObject as MechanismComponent; - CloseSurgeryUI(actor.playerSession); _callbackCache?.Invoke(target, BodyCache, this, PerformerCache); } private void NotUsefulPopup() { + if (PerformerCache == null) return; + BodyCache?.Owner.PopupMessage(PerformerCache, Loc.GetString("You see no useful way to use {0:theName}.", Owner)); } private void NotUsefulAnymorePopup() { + if (PerformerCache == null) return; + BodyCache?.Owner.PopupMessage(PerformerCache, Loc.GetString("You see no useful way to use {0:theName} anymore.", Owner)); } diff --git a/Content.Server/GameObjects/Components/Buckle/BuckleComponent.cs b/Content.Server/GameObjects/Components/Buckle/BuckleComponent.cs index 2f9333317e..ce04fe1676 100644 --- a/Content.Server/GameObjects/Components/Buckle/BuckleComponent.cs +++ b/Content.Server/GameObjects/Components/Buckle/BuckleComponent.cs @@ -13,7 +13,6 @@ using Content.Shared.GameObjects.Components.Strap; using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.GameObjects.Verbs; using Content.Shared.Interfaces; -using Content.Shared.Interfaces.GameObjects.Components; using Content.Shared.Utility; using Robust.Server.GameObjects; using Robust.Shared.Containers; @@ -237,7 +236,7 @@ namespace Content.Server.GameObjects.Components.Buckle public override bool TryBuckle(IEntity? user, IEntity to) { - if (!CanBuckle(user, to, out var strap)) + if (user == null || !CanBuckle(user, to, out var strap)) { return false; } @@ -410,7 +409,7 @@ namespace Content.Server.GameObjects.Components.Buckle return new BuckleComponentState(Buckled, drawDepth, LastEntityBuckledTo, DontCollide); } - + public void Update() { if (!DontCollide || Physics == null) diff --git a/Content.Server/GameObjects/Components/Instruments/InstrumentComponent.cs b/Content.Server/GameObjects/Components/Instruments/InstrumentComponent.cs index db4ee06d6c..13a3f9245e 100644 --- a/Content.Server/GameObjects/Components/Instruments/InstrumentComponent.cs +++ b/Content.Server/GameObjects/Components/Instruments/InstrumentComponent.cs @@ -15,8 +15,6 @@ using Robust.Shared.GameObjects; using Robust.Shared.Localization; using Robust.Shared.Network; using Robust.Shared.Players; -using Robust.Shared.Prototypes; -using Robust.Shared.Serialization; using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.ViewVariables; @@ -201,11 +199,11 @@ namespace Content.Server.GameObjects.Components.Instruments { if (_laggedBatches == (int) (maxMidiLaggedBatches * (1 / 3d) + 1)) { - Owner.PopupMessage(InstrumentPlayer.AttachedEntity, + InstrumentPlayer.AttachedEntity?.PopupMessage( Loc.GetString("Your fingers are beginning to a cramp a little!")); } else if (_laggedBatches == (int) (maxMidiLaggedBatches * (2 / 3d) + 1)) { - Owner.PopupMessage(InstrumentPlayer.AttachedEntity, + InstrumentPlayer.AttachedEntity?.PopupMessage( Loc.GetString("Your fingers are seriously cramping up!")); } } @@ -360,11 +358,11 @@ namespace Content.Server.GameObjects.Components.Instruments stun.Stun(1); Clean(); } + + Owner.PopupMessage(mob, "Your fingers cramp up from playing!"); } InstrumentPlayer = null; - - Owner.PopupMessage(mob, "Your fingers cramp up from playing!"); } _timer += delta; diff --git a/Content.Server/GameObjects/Components/Interactable/WelderComponent.cs b/Content.Server/GameObjects/Components/Interactable/WelderComponent.cs index 556e857917..33f1b0ce47 100644 --- a/Content.Server/GameObjects/Components/Interactable/WelderComponent.cs +++ b/Content.Server/GameObjects/Components/Interactable/WelderComponent.cs @@ -21,8 +21,6 @@ using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Localization; using Robust.Shared.Players; -using Robust.Shared.Prototypes; -using Robust.Shared.Serialization; using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.Utility; using Robust.Shared.ViewVariables; @@ -139,20 +137,24 @@ namespace Content.Server.GameObjects.Components.Interactable { if (!WelderLit) { - if(!silent) Owner.PopupMessage(user, Loc.GetString("The welder is turned off!")); + if (!silent && user != null) + Owner.PopupMessage(user, Loc.GetString("The welder is turned off!")); + return false; } if (!CanWeld(value)) { - if(!silent) Owner.PopupMessage(user, Loc.GetString("The welder does not have enough fuel for that!")); + if (!silent && user != null) + Owner.PopupMessage(user, Loc.GetString("The welder does not have enough fuel for that!")); + return false; } if (_solutionComponent == null) return false; - bool succeeded = _solutionComponent.TryRemoveReagent("chem.WeldingFuel", ReagentUnit.New(value)); + var succeeded = _solutionComponent.TryRemoveReagent("chem.WeldingFuel", ReagentUnit.New(value)); if (succeeded && !silent) { @@ -192,7 +194,7 @@ namespace Content.Server.GameObjects.Components.Interactable return true; } - if (!CanLitWelder()) + if (!CanLitWelder() && user != null) { Owner.PopupMessage(user, Loc.GetString("The welder has no fuel left!")); return false; diff --git a/Content.Server/GameObjects/Components/Items/Storage/ServerStorageComponent.cs b/Content.Server/GameObjects/Components/Items/Storage/ServerStorageComponent.cs index 18345093fb..fb9d230212 100644 --- a/Content.Server/GameObjects/Components/Items/Storage/ServerStorageComponent.cs +++ b/Content.Server/GameObjects/Components/Items/Storage/ServerStorageComponent.cs @@ -23,8 +23,6 @@ using Robust.Shared.Log; using Robust.Shared.Map; using Robust.Shared.Network; using Robust.Shared.Players; -using Robust.Shared.Prototypes; -using Robust.Shared.Serialization; using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.ViewVariables; @@ -481,7 +479,7 @@ namespace Content.Server.GameObjects.Components.Items.Storage void IActivate.Activate(ActivateEventArgs eventArgs) { - ((IUse) this).UseEntity(new UseEntityEventArgs { User = eventArgs.User }); + ((IUse) this).UseEntity(new UseEntityEventArgs(eventArgs.User)); } /// diff --git a/Content.Server/GameObjects/Components/Morgue/MorgueTrayComponent.cs b/Content.Server/GameObjects/Components/Morgue/MorgueTrayComponent.cs index cb37297c3c..b4057a278d 100644 --- a/Content.Server/GameObjects/Components/Morgue/MorgueTrayComponent.cs +++ b/Content.Server/GameObjects/Components/Morgue/MorgueTrayComponent.cs @@ -15,13 +15,9 @@ namespace Content.Server.GameObjects.Components.Morgue void IActivate.Activate(ActivateEventArgs eventArgs) { - if(Morgue != null && !Morgue.Deleted && Morgue.TryGetComponent(out var comp)) + if (Morgue != null && !Morgue.Deleted && Morgue.TryGetComponent(out var comp)) { - comp.Activate(new ActivateEventArgs() - { - User = eventArgs.User, - Target = Morgue - }); + comp.Activate(new ActivateEventArgs(eventArgs.User, Morgue)); } } } diff --git a/Content.Server/GameObjects/EntitySystems/Click/InteractionSystem.cs b/Content.Server/GameObjects/EntitySystems/Click/InteractionSystem.cs index dc5d5d804e..d855a610ed 100644 --- a/Content.Server/GameObjects/EntitySystems/Click/InteractionSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/Click/InteractionSystem.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Content.Server.GameObjects.Components.Items.Storage; @@ -26,7 +25,6 @@ using Robust.Shared.IoC; using Robust.Shared.Log; using Robust.Shared.Map; using Robust.Shared.Maths; -using Robust.Shared.Physics; using Robust.Shared.Players; namespace Content.Server.GameObjects.EntitySystems.Click @@ -143,7 +141,7 @@ namespace Content.Server.GameObjects.EntitySystems.Click } // all activates should only fire when in range / unbostructed - var activateEventArgs = new ActivateEventArgs { User = user, Target = used }; + var activateEventArgs = new ActivateEventArgs(user, used); if (activateEventArgs.InRangeUnobstructed(ignoreInsideBlocker: true, popup: true)) { activateComp.Activate(activateEventArgs); @@ -432,10 +430,7 @@ namespace Content.Server.GameObjects.EntitySystems.Click return; var attackBys = attacked.GetAllComponents().OrderByDescending(x => x.Priority); - var attackByEventArgs = new InteractUsingEventArgs - { - User = user, ClickLocation = clickLocation, Using = weapon, Target = attacked - }; + var attackByEventArgs = new InteractUsingEventArgs(user, clickLocation, weapon, attacked); // all AttackBys should only happen when in range / unobstructed, so no range check is needed if (attackByEventArgs.InRangeUnobstructed(ignoreInsideBlocker: true, popup: true)) @@ -474,7 +469,7 @@ namespace Content.Server.GameObjects.EntitySystems.Click if (message.Handled) return; - var attackHandEventArgs = new InteractHandEventArgs { User = user, Target = attacked }; + var attackHandEventArgs = new InteractHandEventArgs(user, attacked); // all attackHands should only fire when in range / unobstructed if (attackHandEventArgs.InRangeUnobstructed(ignoreInsideBlocker: true, popup: true)) @@ -534,7 +529,7 @@ namespace Content.Server.GameObjects.EntitySystems.Click // Try to use item on any components which have the interface foreach (var use in uses) { - if (use.UseEntity(new UseEntityEventArgs { User = user })) + if (use.UseEntity(new UseEntityEventArgs(user))) { // If a Use returns a status completion we finish our attack return; @@ -753,10 +748,7 @@ namespace Content.Server.GameObjects.EntitySystems.Click return; var rangedAttackBys = attacked.GetAllComponents().ToList(); - var rangedAttackByEventArgs = new RangedInteractEventArgs - { - User = user, Using = weapon, ClickLocation = clickLocation - }; + var rangedAttackByEventArgs = new RangedInteractEventArgs(user, weapon, clickLocation); // See if we have a ranged attack interaction foreach (var t in rangedAttackBys) diff --git a/Content.Server/GameObjects/EntitySystems/ConstructionSystem.cs b/Content.Server/GameObjects/EntitySystems/ConstructionSystem.cs index e1244cbbe8..261ddf8e86 100644 --- a/Content.Server/GameObjects/EntitySystems/ConstructionSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/ConstructionSystem.cs @@ -352,11 +352,18 @@ namespace Content.Server.GameObjects.EntitySystems return; } + var user = args.SenderSession.AttachedEntity; + + if (user == null) + { + Logger.Error($"Client sent {nameof(TryStartStructureConstructionMessage)} with no attached entity!"); + return; + } + var startNode = constructionGraph.Nodes[constructionPrototype.StartNode]; var targetNode = constructionGraph.Nodes[constructionPrototype.TargetNode]; var pathFind = constructionGraph.Path(startNode.Name, targetNode.Name); - var user = args.SenderSession.AttachedEntity; if (_beingBuilt.TryGetValue(args.SenderSession, out var set)) { diff --git a/Content.Server/GameObjects/EntitySystems/PointingSystem.cs b/Content.Server/GameObjects/EntitySystems/PointingSystem.cs index 96cda4f1f8..4fc87a1e26 100644 --- a/Content.Server/GameObjects/EntitySystems/PointingSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/PointingSystem.cs @@ -69,7 +69,7 @@ namespace Content.Server.GameObjects.EntitySystems ? viewerPointedAtMessage : viewerMessage; - source.PopupMessage(viewer.AttachedEntity, message); + source.PopupMessage(viewerEntity, message); } } diff --git a/Content.Shared/Construction/ConstructionGraphNode.cs b/Content.Shared/Construction/ConstructionGraphNode.cs index 9c86d7b3a2..181eb53b81 100644 --- a/Content.Shared/Construction/ConstructionGraphNode.cs +++ b/Content.Shared/Construction/ConstructionGraphNode.cs @@ -1,6 +1,6 @@ using System; using System.Collections.Generic; -using Robust.Shared.Prototypes; +using System.Diagnostics.CodeAnalysis; using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.ViewVariables; @@ -12,12 +12,13 @@ namespace Content.Shared.Construction { [DataField("actions", serverOnly: true)] private List _actions = new(); + [DataField("edges")] private List _edges = new(); [ViewVariables] - [DataField("node")] - public string Name { get; private set; } + [DataField("node", required: true)] + public string Name { get; private set; } = default!; [ViewVariables] public IReadOnlyList Edges => _edges; @@ -27,9 +28,9 @@ namespace Content.Shared.Construction [ViewVariables] [DataField("entity")] - public string Entity { get; private set; } + public string? Entity { get; private set; } - public ConstructionGraphEdge GetEdge(string target) + public ConstructionGraphEdge? GetEdge(string target) { foreach (var edge in _edges) { @@ -39,5 +40,10 @@ namespace Content.Shared.Construction return null; } + + public bool TryGetEdge(string target, [NotNullWhen(true)] out ConstructionGraphEdge? edge) + { + return (edge = GetEdge(target)) != null; + } } } diff --git a/Content.Shared/Construction/ConstructionGraphPrototype.cs b/Content.Shared/Construction/ConstructionGraphPrototype.cs index 2323f7ac70..aa60b3bb29 100644 --- a/Content.Shared/Construction/ConstructionGraphPrototype.cs +++ b/Content.Shared/Construction/ConstructionGraphPrototype.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.IO; using Robust.Shared.Prototypes; using Robust.Shared.Serialization; @@ -12,8 +13,8 @@ namespace Content.Shared.Construction public class ConstructionGraphPrototype : IPrototype, ISerializationHooks { private readonly Dictionary _nodes = new(); - private readonly Dictionary, ConstructionGraphNode[]> _paths = new(); - private readonly Dictionary> _pathfinding = new(); + private readonly Dictionary, ConstructionGraphNode[]?> _paths = new(); + private readonly Dictionary> _pathfinding = new(); [ViewVariables] [field: DataField("id", required: true)] @@ -21,7 +22,7 @@ namespace Content.Shared.Construction [ViewVariables] [field: DataField("start")] - public string Start { get; } + public string? Start { get; } [DataField("graph", priority: 0)] private List _graph = new(); @@ -35,20 +36,30 @@ namespace Content.Shared.Construction foreach (var graphNode in _graph) { + if (string.IsNullOrEmpty(graphNode.Name)) + { + throw new InvalidDataException($"Name of graph node is null in construction graph {ID}!"); + } + _nodes[graphNode.Name] = graphNode; } - if(string.IsNullOrEmpty(Start) || !_nodes.ContainsKey(Start)) + if (string.IsNullOrEmpty(Start) || !_nodes.ContainsKey(Start)) throw new InvalidDataException($"Starting node for construction graph {ID} is null, empty or invalid!"); } - public ConstructionGraphEdge Edge(string startNode, string nextNode) + public ConstructionGraphEdge? Edge(string startNode, string nextNode) { var start = _nodes[startNode]; return start.GetEdge(nextNode); } - public ConstructionGraphNode[] Path(string startNode, string finishNode) + public bool TryPath(string startNode, string finishNode, [NotNullWhen(true)] out ConstructionGraphNode[]? path) + { + return (path = Path(startNode, finishNode)) != null; + } + + public ConstructionGraphNode[]? Path(string startNode, string finishNode) { var tuple = new ValueTuple(startNode, finishNode); @@ -57,7 +68,7 @@ namespace Content.Shared.Construction // Get graph given the current start. - Dictionary pathfindingForStart; + Dictionary pathfindingForStart; if (_pathfinding.ContainsKey(startNode)) { pathfindingForStart = _pathfinding[startNode]; @@ -76,8 +87,6 @@ namespace Content.Shared.Construction var path = new List(); while (current != start) { - path.Add(current); - // No path. if (current == null || !pathfindingForStart.ContainsKey(current)) { @@ -86,6 +95,8 @@ namespace Content.Shared.Construction return null; } + path.Add(current); + current = pathfindingForStart[current]; } @@ -97,13 +108,13 @@ namespace Content.Shared.Construction /// Uses breadth first search for pathfinding. /// /// - private Dictionary PathsForStart(string start) + private Dictionary PathsForStart(string start) { // TODO: Make this use A* or something, although it's not that important. var startNode = _nodes[start]; var frontier = new Queue(); - var cameFrom = new Dictionary(); + var cameFrom = new Dictionary(); frontier.Enqueue(startNode); cameFrom[startNode] = null; diff --git a/Content.Shared/Content.Shared.csproj b/Content.Shared/Content.Shared.csproj index 61e07381d0..c1492422ce 100644 --- a/Content.Shared/Content.Shared.csproj +++ b/Content.Shared/Content.Shared.csproj @@ -10,6 +10,7 @@ Release;Debug AnyCPU nullable + enable diff --git a/Content.Shared/GameObjects/Components/Inventory/SharedInventoryComponent.cs b/Content.Shared/GameObjects/Components/Inventory/SharedInventoryComponent.cs index e41b25f150..ca65aa7080 100644 --- a/Content.Shared/GameObjects/Components/Inventory/SharedInventoryComponent.cs +++ b/Content.Shared/GameObjects/Components/Inventory/SharedInventoryComponent.cs @@ -1,11 +1,9 @@ using System; using System.Collections.Generic; using Content.Shared.GameObjects.Components.Movement; -using Content.Shared.GameObjects.EntitySystems.EffectBlocker; using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Reflection; -using Robust.Shared.Prototypes; using Robust.Shared.Serialization; using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.Utility; @@ -16,16 +14,14 @@ namespace Content.Shared.GameObjects.Components.Inventory { public abstract class SharedInventoryComponent : Component, IMoveSpeedModifier { - // ReSharper disable UnassignedReadonlyField - [Dependency] protected readonly IReflectionManager ReflectionManager; - [Dependency] protected readonly IDynamicTypeFactory DynamicTypeFactory; - // ReSharper restore UnassignedReadonlyField + [Dependency] protected readonly IReflectionManager ReflectionManager = default!; + [Dependency] protected readonly IDynamicTypeFactory DynamicTypeFactory = default!; public sealed override string Name => "Inventory"; public sealed override uint? NetID => ContentNetIDs.STORAGE; [ViewVariables] - protected Inventory InventoryInstance { get; private set; } + protected Inventory InventoryInstance { get; private set; } = default!; [ViewVariables] [DataField("Template")] @@ -42,7 +38,7 @@ namespace Content.Shared.GameObjects.Components.Inventory { var type = ReflectionManager.LooseGetType(_templateName); DebugTools.Assert(type != null); - InventoryInstance = DynamicTypeFactory.CreateInstance(type); + InventoryInstance = DynamicTypeFactory.CreateInstance(type!); } /// true if the item is equipped to an equip slot (NOT inside an equipped container diff --git a/Content.Shared/GameObjects/Components/Materials/MaterialComponent.cs b/Content.Shared/GameObjects/Components/Materials/MaterialComponent.cs index e6dda66c49..c3a9fd5cba 100644 --- a/Content.Shared/GameObjects/Components/Materials/MaterialComponent.cs +++ b/Content.Shared/GameObjects/Components/Materials/MaterialComponent.cs @@ -40,13 +40,13 @@ namespace Content.Shared.GameObjects.Components.Materials [DataDefinition] public class MaterialDataEntry : ISerializationHooks { - public object Key; + public object Key = default!; - [DataField("key")] - public string StringKey; + [DataField("key", required: true)] + public string StringKey = default!; - [DataField("mat")] - public string Value; + [DataField("mat", required: true)] + public string Value = default!; void ISerializationHooks.AfterDeserialization() { diff --git a/Content.Shared/GameObjects/Components/SharedGasAnalyzerComponent.cs b/Content.Shared/GameObjects/Components/SharedGasAnalyzerComponent.cs index 4c98bed0cd..d7fa7f294e 100644 --- a/Content.Shared/GameObjects/Components/SharedGasAnalyzerComponent.cs +++ b/Content.Shared/GameObjects/Components/SharedGasAnalyzerComponent.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using Robust.Shared.GameObjects; using Robust.Shared.Localization; using Robust.Shared.Serialization; @@ -22,10 +21,10 @@ namespace Content.Shared.GameObjects.Components { public float Pressure; public float Temperature; - public GasEntry[] Gases; - public string Error = string.Empty; + public GasEntry[]? Gases; + public string? Error; - public GasAnalyzerBoundUserInterfaceState(float pressure, float temperature, GasEntry[] gases, string error = null) + public GasAnalyzerBoundUserInterfaceState(float pressure, float temperature, GasEntry[]? gases, string? error = null) { Pressure = pressure; Temperature = temperature; diff --git a/Content.Shared/GameObjects/Components/SharedStackComponent.cs b/Content.Shared/GameObjects/Components/SharedStackComponent.cs index 9671765e9d..74d3155007 100644 --- a/Content.Shared/GameObjects/Components/SharedStackComponent.cs +++ b/Content.Shared/GameObjects/Components/SharedStackComponent.cs @@ -76,7 +76,7 @@ namespace Content.Shared.GameObjects.Components return new StackComponentState(Count, MaxCount); } - public override void HandleComponentState(ComponentState curState, ComponentState nextState) + public override void HandleComponentState(ComponentState? curState, ComponentState? nextState) { if (curState is not StackComponentState cast) { diff --git a/Content.Shared/GameObjects/EntitySystems/SharedInteractionSystem.cs b/Content.Shared/GameObjects/EntitySystems/SharedInteractionSystem.cs index 6773cb51b3..7c3ea58a9c 100644 --- a/Content.Shared/GameObjects/EntitySystems/SharedInteractionSystem.cs +++ b/Content.Shared/GameObjects/EntitySystems/SharedInteractionSystem.cs @@ -4,10 +4,8 @@ using Content.Shared.Interfaces.GameObjects.Components; using Content.Shared.Physics; using JetBrains.Annotations; using Robust.Shared.GameObjects; -using Robust.Shared.IoC; using Robust.Shared.Localization; using Robust.Shared.Map; -using Robust.Shared.Maths; using Robust.Shared.Physics; using Robust.Shared.Physics.Broadphase; @@ -40,7 +38,7 @@ namespace Content.Shared.GameObjects.EntitySystems MapCoordinates origin, MapCoordinates other, int collisionMask = (int) CollisionGroup.Impassable, - Ignored predicate = null) + Ignored? predicate = null) { var dir = other.Position - origin.Position; @@ -69,7 +67,7 @@ namespace Content.Shared.GameObjects.EntitySystems MapCoordinates origin, MapCoordinates other, int collisionMask = (int) CollisionGroup.Impassable, - IEntity ignoredEnt = null) + IEntity? ignoredEnt = null) { var predicate = ignoredEnt == null ? null @@ -111,7 +109,7 @@ namespace Content.Shared.GameObjects.EntitySystems MapCoordinates other, float range = InteractionRange, CollisionGroup collisionMask = CollisionGroup.Impassable, - Ignored predicate = null, + Ignored? predicate = null, bool ignoreInsideBlocker = false) { if (!origin.InRange(other, range)) return false; @@ -132,7 +130,7 @@ namespace Content.Shared.GameObjects.EntitySystems foreach (var result in rayResults) { - if (!result.HitEntity.TryGetComponent(out IPhysBody p)) + if (!result.HitEntity.TryGetComponent(out IPhysBody? p)) { continue; } @@ -186,7 +184,7 @@ namespace Content.Shared.GameObjects.EntitySystems IEntity other, float range = InteractionRange, CollisionGroup collisionMask = CollisionGroup.Impassable, - Ignored predicate = null, + Ignored? predicate = null, bool ignoreInsideBlocker = false, bool popup = false) { @@ -242,7 +240,7 @@ namespace Content.Shared.GameObjects.EntitySystems IComponent other, float range = InteractionRange, CollisionGroup collisionMask = CollisionGroup.Impassable, - Ignored predicate = null, + Ignored? predicate = null, bool ignoreInsideBlocker = false, bool popup = false) { @@ -298,7 +296,7 @@ namespace Content.Shared.GameObjects.EntitySystems EntityCoordinates other, float range = InteractionRange, CollisionGroup collisionMask = CollisionGroup.Impassable, - Ignored predicate = null, + Ignored? predicate = null, bool ignoreInsideBlocker = false, bool popup = false) { @@ -354,7 +352,7 @@ namespace Content.Shared.GameObjects.EntitySystems MapCoordinates other, float range = InteractionRange, CollisionGroup collisionMask = CollisionGroup.Impassable, - Ignored predicate = null, + Ignored? predicate = null, bool ignoreInsideBlocker = false, bool popup = false) { @@ -408,7 +406,7 @@ namespace Content.Shared.GameObjects.EntitySystems ITargetedInteractEventArgs args, float range = InteractionRange, CollisionGroup collisionMask = CollisionGroup.Impassable, - Ignored predicate = null, + Ignored? predicate = null, bool ignoreInsideBlocker = false, bool popup = false) { @@ -453,7 +451,7 @@ namespace Content.Shared.GameObjects.EntitySystems DragDropEventArgs args, float range = InteractionRange, CollisionGroup collisionMask = CollisionGroup.Impassable, - Ignored predicate = null, + Ignored? predicate = null, bool ignoreInsideBlocker = false, bool popup = false) { @@ -521,7 +519,7 @@ namespace Content.Shared.GameObjects.EntitySystems AfterInteractEventArgs args, float range = InteractionRange, CollisionGroup collisionMask = CollisionGroup.Impassable, - Ignored predicate = null, + Ignored? predicate = null, bool ignoreInsideBlocker = false, bool popup = false) { diff --git a/Content.Shared/Interfaces/GameObjects/Components/Interaction/IActivate.cs b/Content.Shared/Interfaces/GameObjects/Components/Interaction/IActivate.cs index d52681b4c4..4b76747e35 100644 --- a/Content.Shared/Interfaces/GameObjects/Components/Interaction/IActivate.cs +++ b/Content.Shared/Interfaces/GameObjects/Components/Interaction/IActivate.cs @@ -23,8 +23,14 @@ namespace Content.Shared.Interfaces.GameObjects.Components public class ActivateEventArgs : EventArgs, ITargetedInteractEventArgs { - public IEntity User { get; set; } - public IEntity Target { get; set; } + public ActivateEventArgs(IEntity user, IEntity target) + { + User = user; + Target = target; + } + + public IEntity User { get; } + public IEntity Target { get; } } /// diff --git a/Content.Shared/Interfaces/GameObjects/Components/Interaction/IInteractHand.cs b/Content.Shared/Interfaces/GameObjects/Components/Interaction/IInteractHand.cs index f617ecf509..51de4b1da4 100644 --- a/Content.Shared/Interfaces/GameObjects/Components/Interaction/IInteractHand.cs +++ b/Content.Shared/Interfaces/GameObjects/Components/Interaction/IInteractHand.cs @@ -20,8 +20,14 @@ namespace Content.Shared.Interfaces.GameObjects.Components public class InteractHandEventArgs : EventArgs, ITargetedInteractEventArgs { - public IEntity User { get; set; } - public IEntity Target { get; set; } + public InteractHandEventArgs(IEntity user, IEntity target) + { + User = user; + Target = target; + } + + public IEntity User { get; } + public IEntity Target { get; } } diff --git a/Content.Shared/Interfaces/GameObjects/Components/Interaction/IInteractUsing.cs b/Content.Shared/Interfaces/GameObjects/Components/Interaction/IInteractUsing.cs index dec7cf2c94..9b19336466 100644 --- a/Content.Shared/Interfaces/GameObjects/Components/Interaction/IInteractUsing.cs +++ b/Content.Shared/Interfaces/GameObjects/Components/Interaction/IInteractUsing.cs @@ -29,10 +29,18 @@ namespace Content.Shared.Interfaces.GameObjects.Components public class InteractUsingEventArgs : EventArgs, ITargetedInteractEventArgs { - public IEntity User { get; set; } - public EntityCoordinates ClickLocation { get; set; } - public IEntity Using { get; set; } - public IEntity Target { get; set; } + public InteractUsingEventArgs(IEntity user, EntityCoordinates clickLocation, IEntity @using, IEntity target) + { + User = user; + ClickLocation = clickLocation; + Using = @using; + Target = target; + } + + public IEntity User { get; } + public EntityCoordinates ClickLocation { get; } + public IEntity Using { get; } + public IEntity Target { get; } } /// diff --git a/Content.Shared/Interfaces/GameObjects/Components/Interaction/IRangedInteract.cs b/Content.Shared/Interfaces/GameObjects/Components/Interaction/IRangedInteract.cs index e22aae8cbc..c0a94f8702 100644 --- a/Content.Shared/Interfaces/GameObjects/Components/Interaction/IRangedInteract.cs +++ b/Content.Shared/Interfaces/GameObjects/Components/Interaction/IRangedInteract.cs @@ -23,9 +23,16 @@ namespace Content.Shared.Interfaces.GameObjects.Components [PublicAPI] public class RangedInteractEventArgs : EventArgs { - public IEntity User { get; set; } - public IEntity Using { get; set; } - public EntityCoordinates ClickLocation { get; set; } + public RangedInteractEventArgs(IEntity user, IEntity @using, EntityCoordinates clickLocation) + { + User = user; + Using = @using; + ClickLocation = clickLocation; + } + + public IEntity User { get; } + public IEntity Using { get; } + public EntityCoordinates ClickLocation { get; } } /// diff --git a/Content.Shared/Interfaces/GameObjects/Components/Interaction/IUse.cs b/Content.Shared/Interfaces/GameObjects/Components/Interaction/IUse.cs index d42f0098c0..8dc45ade88 100644 --- a/Content.Shared/Interfaces/GameObjects/Components/Interaction/IUse.cs +++ b/Content.Shared/Interfaces/GameObjects/Components/Interaction/IUse.cs @@ -21,7 +21,12 @@ namespace Content.Shared.Interfaces.GameObjects.Components public class UseEntityEventArgs : EventArgs { - public IEntity User { get; set; } + public UseEntityEventArgs(IEntity user) + { + User = user; + } + + public IEntity User { get; } } ///