diff --git a/Content.Client/Hands/HandsGui.xaml.cs b/Content.Client/Hands/HandsGui.xaml.cs index e468c1bc7d..71fc1b6cf8 100644 --- a/Content.Client/Hands/HandsGui.xaml.cs +++ b/Content.Client/Hands/HandsGui.xaml.cs @@ -86,7 +86,7 @@ namespace Content.Client.Hands private void UpdateGui() { HandsContainer.DisposeAllChildren(); - + var entManager = IoCManager.Resolve(); foreach (var hand in _hands) { var newButton = MakeHandButton(hand.HandLocation); @@ -97,17 +97,17 @@ namespace Content.Client.Hands newButton.OnPressed += args => OnHandPressed(args, handName); newButton.OnStoragePressed += _ => OnStoragePressed(handName); - _itemSlotManager.SetItemSlot(newButton, hand.HeldItem); + _itemSlotManager.SetItemSlot(newButton, hand.HeldItem ?? EntityUid.Invalid); // Show blocked overlay if hand is blocked. newButton.Blocked.Visible = - hand.HeldItem != null && IoCManager.Resolve().HasComponent(hand.HeldItem); + hand.HeldItem != null && entManager.HasComponent(hand.HeldItem.Value); } if (TryGetActiveHand(out var activeHand)) { activeHand.HandButton.SetActiveHand(true); - StatusPanel.Update(activeHand.HeldItem); + StatusPanel.Update(activeHand.HeldItem ?? EntityUid.Invalid); } } @@ -119,7 +119,7 @@ namespace Content.Client.Hands } else if (TryGetHand(handName, out var hand)) { - _itemSlotManager.OnButtonPressed(args, hand.HeldItem); + _itemSlotManager.OnButtonPressed(args, hand.HeldItem ?? EntityUid.Invalid); } } @@ -156,7 +156,7 @@ namespace Content.Client.Hands foreach (var hand in _hands) { - _itemSlotManager.UpdateCooldown(hand.HandButton, hand.HeldItem); + _itemSlotManager.UpdateCooldown(hand.HandButton, hand.HeldItem ?? EntityUid.Invalid); } } @@ -250,7 +250,7 @@ namespace Content.Client.Hands /// The item being held in this hand. /// [ViewVariables] - public EntityUid HeldItem { get; } + public EntityUid? HeldItem { get; } /// /// The button in the gui associated with this hand. Assumed to be set by gui shortly after being received from the client HandsComponent. @@ -258,7 +258,7 @@ namespace Content.Client.Hands [ViewVariables] public HandButton HandButton { get; set; } = default!; - public GuiHand(string name, HandLocation handLocation, EntityUid heldItem) + public GuiHand(string name, HandLocation handLocation, EntityUid? heldItem) { Name = name; HandLocation = handLocation; diff --git a/Content.Client/Hands/ShowHandItemOverlay.cs b/Content.Client/Hands/ShowHandItemOverlay.cs index 1c73cbc0a8..b6a6abcc07 100644 --- a/Content.Client/Hands/ShowHandItemOverlay.cs +++ b/Content.Client/Hands/ShowHandItemOverlay.cs @@ -1,4 +1,4 @@ -using Content.Shared.CCVar; +using Content.Shared.CCVar; using Robust.Client.GameObjects; using Robust.Client.Graphics; using Robust.Client.Input; @@ -46,7 +46,7 @@ namespace Content.Client.Hands var sys = EntitySystem.Get(); var handEntity = sys.GetActiveHandEntity(); - if (handEntity == default || !_cfg.GetCVar(CCVars.HudHeldItemShow) || !IoCManager.Resolve().HasComponent(handEntity)) + if (handEntity == null || !_cfg.GetCVar(CCVars.HudHeldItemShow) || !IoCManager.Resolve().HasComponent(handEntity)) return; var screen = args.ScreenHandle; @@ -56,7 +56,7 @@ namespace Content.Client.Hands screen.RenderInRenderTarget(_renderBackbuffer, () => { - screen.DrawEntity(handEntity, halfSize, new Vector2(1f, 1f) * uiScale, Direction.South); + screen.DrawEntity(handEntity.Value, halfSize, new Vector2(1f, 1f) * uiScale, Direction.South); }, Color.Transparent); var offset = _cfg.GetCVar(CCVars.HudHeldItemOffset); diff --git a/Content.Client/Hands/Systems/HandsSystem.cs b/Content.Client/Hands/Systems/HandsSystem.cs index 79456eea9a..ddfb3eb6dc 100644 --- a/Content.Client/Hands/Systems/HandsSystem.cs +++ b/Content.Client/Hands/Systems/HandsSystem.cs @@ -77,10 +77,10 @@ namespace Content.Client.Hands return new HandsGuiState(states, hands.ActiveHand); } - public EntityUid GetActiveHandEntity() + public EntityUid? GetActiveHandEntity() { if (GetPlayerHandsComponent() is not { ActiveHand: { } active } hands) - return default; + return null; return hands.GetHand(active).HeldEntity; } @@ -106,7 +106,7 @@ namespace Content.Client.Hands var pressedEntity = pressedHand.HeldEntity; var activeEntity = activeHand.HeldEntity; - if (pressedHand == activeHand && activeEntity != default) + if (pressedHand == activeHand && activeEntity != null) { // use item in hand // it will always be attack_self() in my heart. @@ -114,14 +114,14 @@ namespace Content.Client.Hands return; } - if (pressedHand != activeHand && pressedEntity == default) + if (pressedHand != activeHand && pressedEntity == null) { // change active hand RaiseNetworkEvent(new RequestSetHandEvent(handName)); return; } - if (pressedHand != activeHand && pressedEntity != default && activeEntity != default) + if (pressedHand != activeHand && pressedEntity != null && activeEntity != null) { // use active item on held item RaiseNetworkEvent(new ClientInteractUsingInHandMsg(pressedHand.Name)); diff --git a/Content.Server/Access/Systems/IdCardSystem.cs b/Content.Server/Access/Systems/IdCardSystem.cs index 364a53d7ec..9bdb08ddb4 100644 --- a/Content.Server/Access/Systems/IdCardSystem.cs +++ b/Content.Server/Access/Systems/IdCardSystem.cs @@ -92,7 +92,7 @@ namespace Content.Server.Access.Systems // check held item? if (EntityManager.TryGetComponent(uid, out SharedHandsComponent? hands) && hands.TryGetActiveHeldEntity(out var heldItem) && - TryGetIdCard(heldItem, out idCard)) + TryGetIdCard(heldItem.Value, out idCard)) { return true; } diff --git a/Content.Server/Hands/Systems/HandVirtualItemSystem.cs b/Content.Server/Hands/Systems/HandVirtualItemSystem.cs index 8a56d897f5..448bc23776 100644 --- a/Content.Server/Hands/Systems/HandVirtualItemSystem.cs +++ b/Content.Server/Hands/Systems/HandVirtualItemSystem.cs @@ -1,4 +1,4 @@ -using Content.Server.Hands.Components; +using Content.Server.Hands.Components; using Content.Shared.Hands; using Content.Shared.Hands.Components; using Content.Shared.Interaction; @@ -27,7 +27,7 @@ namespace Content.Server.Hands.Systems foreach (var handName in hands.ActivePriorityEnumerable()) { var hand = hands.GetHand(handName); - if (!hand.IsEmpty) + if (hand.HeldEntity != null) continue; var pos = EntityManager.GetComponent(hands.Owner).Coordinates; @@ -87,13 +87,11 @@ namespace Content.Server.Hands.Systems foreach (var handName in hands.ActivePriorityEnumerable()) { var hand = hands.GetHand(handName); - if (hand.IsEmpty) + + if (!(hand.HeldEntity is { } heldEntity)) continue; - if (hand.HeldEntity == default) - continue; - - if (EntityManager.TryGetComponent(hand.HeldEntity, out var virt) + if (EntityManager.TryGetComponent(heldEntity, out var virt) && virt.BlockingEntity == matching) { Delete(virt, user); diff --git a/Content.Server/Hands/Systems/HandsSystem.cs b/Content.Server/Hands/Systems/HandsSystem.cs index b1a6d164d5..a067e19747 100644 --- a/Content.Server/Hands/Systems/HandsSystem.cs +++ b/Content.Server/Hands/Systems/HandsSystem.cs @@ -68,7 +68,7 @@ namespace Content.Server.Hands.Systems return; // Cancel pull if all hands full. - if (component.Hands.All(hand => !hand.IsEmpty)) + if (component.Hands.All(hand => hand.HeldEntity != null)) args.Cancelled = true; } @@ -92,12 +92,12 @@ namespace Content.Server.Hands.Systems // and clear it. foreach (var hand in component.Hands) { - if (hand.HeldEntity == default + if (hand.HeldEntity == null || !EntityManager.TryGetComponent(hand.HeldEntity, out HandVirtualItemComponent? virtualItem) || virtualItem.BlockingEntity != args.Pulled.Owner) continue; - EntityManager.DeleteEntity(hand.HeldEntity); + EntityManager.DeleteEntity(hand.HeldEntity.Value); break; } } @@ -234,16 +234,16 @@ namespace Content.Server.Hands.Systems !_actionBlockerSystem.CanThrow(player)) return false; - if (EntityManager.TryGetComponent(throwEnt, out StackComponent? stack) && stack.Count > 1 && stack.ThrowIndividually) + if (EntityManager.TryGetComponent(throwEnt.Value, out StackComponent? stack) && stack.Count > 1 && stack.ThrowIndividually) { - var splitStack = _stackSystem.Split(throwEnt, 1, EntityManager.GetComponent(player).Coordinates, stack); + var splitStack = _stackSystem.Split(throwEnt.Value, 1, EntityManager.GetComponent(player).Coordinates, stack); if (splitStack is not {Valid: true}) return false; throwEnt = splitStack.Value; } - else if (!hands.Drop(throwEnt)) + else if (!hands.Drop(throwEnt.Value)) return false; var direction = coords.ToMapPos(EntityManager) - EntityManager.GetComponent(player).WorldPosition; @@ -253,7 +253,7 @@ namespace Content.Server.Hands.Systems direction = direction.Normalized * Math.Min(direction.Length, hands.ThrowRange); var throwStrength = hands.ThrowForceMultiplier; - throwEnt.TryThrow(direction, throwStrength, player); + throwEnt.Value.TryThrow(direction, throwStrength, player); return true; } diff --git a/Content.Server/Power/EntitySystems/CableMultitoolSystem.cs b/Content.Server/Power/EntitySystems/CableMultitoolSystem.cs index bbcc87d782..998268e24a 100644 --- a/Content.Server/Power/EntitySystems/CableMultitoolSystem.cs +++ b/Content.Server/Power/EntitySystems/CableMultitoolSystem.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using Content.Server.NodeContainer; @@ -48,7 +48,7 @@ namespace Content.Server.Power.EntitySystems var held = hand.HeldEntity; // Pulsing is hardcoded here because I don't think it needs to be more complex than that right now. // Update if I'm wrong. - if ((held != null) && _toolSystem.HasQuality(held, "Pulsing")) + if (held != null && _toolSystem.HasQuality(held.Value, "Pulsing")) { args.PushMarkup(GenerateCableMarkup(uid)); // args.PushFancyUpdatingPowerGraphs(uid); diff --git a/Content.Shared/Access/Systems/AccessReaderSystem.cs b/Content.Shared/Access/Systems/AccessReaderSystem.cs index f604030b69..c4c47a6da2 100644 --- a/Content.Shared/Access/Systems/AccessReaderSystem.cs +++ b/Content.Shared/Access/Systems/AccessReaderSystem.cs @@ -71,7 +71,7 @@ namespace Content.Shared.Access.Systems if (EntityManager.TryGetComponent(uid, out SharedHandsComponent? hands)) { if (hands.TryGetActiveHeldEntity(out var heldItem) && - FindAccessTagsItem(heldItem, out tags)) + FindAccessTagsItem(heldItem.Value, out tags)) { return tags; } diff --git a/Content.Shared/Containers/ItemSlot/ItemSlotsSystem.cs b/Content.Shared/Containers/ItemSlot/ItemSlotsSystem.cs index d93ba287df..7935ba7d3d 100644 --- a/Content.Shared/Containers/ItemSlot/ItemSlotsSystem.cs +++ b/Content.Shared/Containers/ItemSlot/ItemSlotsSystem.cs @@ -285,15 +285,16 @@ namespace Content.Shared.Containers.ItemSlots if (!hands.TryGetActiveHeldEntity(out var item)) return false; + var heldItem = item.Value; - if (!CanInsert(uid, item, slot)) + if (!CanInsert(uid, item.Value, slot)) return false; // hands.Drop(item) checks CanDrop action blocker - if (!_actionBlockerSystem.CanInteract(user) && hands.Drop(item)) + if (!_actionBlockerSystem.CanInteract(user) && hands.Drop(heldItem)) return false; - Insert(uid, slot, item, user); + Insert(uid, slot, heldItem, user); return true; } #endregion diff --git a/Content.Shared/Hands/Components/SharedHandsComponent.cs b/Content.Shared/Hands/Components/SharedHandsComponent.cs index 52c2d1c08a..d2f39e50bf 100644 --- a/Content.Shared/Hands/Components/SharedHandsComponent.cs +++ b/Content.Shared/Hands/Components/SharedHandsComponent.cs @@ -217,23 +217,23 @@ namespace Content.Shared.Hands.Components if (!TryGetActiveHand(out var hand)) return false; - return hand.HeldEntity != default; + return hand.HeldEntity != null; } - public bool TryGetHeldEntity(string handName, out EntityUid heldEntity) + public bool TryGetHeldEntity(string handName,[NotNullWhen(true)] out EntityUid? heldEntity) { - heldEntity = default; + heldEntity = null; if (!TryGetHand(handName, out var hand)) return false; heldEntity = hand.HeldEntity; - return heldEntity != default; + return hand.HeldEntity != null; } - public bool TryGetActiveHeldEntity(out EntityUid heldEntity) + public bool TryGetActiveHeldEntity([NotNullWhen(true)] out EntityUid? heldEntity) { - heldEntity = GetActiveHand()?.HeldEntity ?? default; + heldEntity = GetActiveHand()?.HeldEntity; return heldEntity != null; } @@ -251,8 +251,8 @@ namespace Content.Shared.Hands.Components { foreach (var hand in Hands) { - if (hand.HeldEntity != default) - yield return hand.HeldEntity; + if (hand.HeldEntity.HasValue) + yield return hand.HeldEntity.Value; } } @@ -265,7 +265,7 @@ namespace Content.Shared.Hands.Components int acc = 0; foreach (var hand in Hands) { - if (hand.HeldEntity == default) + if (hand.HeldEntity == null) acc += 1; } @@ -418,16 +418,8 @@ namespace Content.Shared.Hands.Components if (hand.HeldEntity == null) return false; - var heldEntity = hand.HeldEntity; - var handContainer = hand.Container; - if (handContainer == null) - return false; - - if (!handContainer.CanRemove(heldEntity)) - return false; - - return true; + return hand.Container?.CanRemove(hand.HeldEntity.Value) ?? false; } /// @@ -446,11 +438,9 @@ namespace Content.Shared.Hands.Components /// private void RemoveHeldEntityFromHand(Hand hand) { - if (hand.HeldEntity == null) + if (hand.HeldEntity is not { } heldEntity) return; - var heldEntity = hand.HeldEntity; - var handContainer = hand.Container; if (handContainer == null) return; @@ -474,11 +464,9 @@ namespace Content.Shared.Hands.Components /// public void DropHeldEntity(Hand hand, EntityCoordinates targetDropLocation) { - if (hand.IsEmpty) + if (hand.HeldEntity is not { } heldEntity) return; - var heldEntity = hand.HeldEntity; - RemoveHeldEntityFromHand(hand); EntitySystem.Get().DroppedInteraction(Owner, heldEntity); @@ -537,11 +525,9 @@ namespace Content.Shared.Hands.Components private bool CanPutHeldEntityIntoContainer(Hand hand, IContainer targetContainer, bool checkActionBlocker) { - if (hand.HeldEntity == null) + if (hand.HeldEntity is not { } heldEntity) return false; - var heldEntity = hand.HeldEntity; - if (checkActionBlocker && !PlayerCanDrop()) return false; @@ -556,11 +542,9 @@ namespace Content.Shared.Hands.Components /// private void PutHeldEntityIntoContainer(Hand hand, IContainer targetContainer) { - if (hand.HeldEntity == null) + if (hand.HeldEntity is not { } heldEntity) return; - var heldEntity = hand.HeldEntity; - RemoveHeldEntityFromHand(hand); if (!targetContainer.Insert(heldEntity)) @@ -718,7 +702,7 @@ namespace Content.Shared.Hands.Components return; await EntitySystem.Get() - .InteractUsing(Owner, activeHeldEntity, heldEntity, EntityCoordinates.Invalid); + .InteractUsing(Owner, activeHeldEntity.Value, heldEntity.Value, EntityCoordinates.Invalid); } public void ActivateItem(bool altInteract = false) @@ -727,7 +711,7 @@ namespace Content.Shared.Hands.Components return; EntitySystem.Get() - .TryUseInteraction(Owner, heldEntity, altInteract); + .TryUseInteraction(Owner, heldEntity.Value, altInteract); } public void ActivateHeldEntity(string handName) @@ -750,14 +734,14 @@ namespace Content.Shared.Hands.Components if (!TryGetHeldEntity(handName, out var heldEntity)) return false; - if (!CanInsertEntityIntoHand(activeHand, heldEntity) || !CanRemoveHeldEntityFromHand(hand)) + if (!CanInsertEntityIntoHand(activeHand, heldEntity.Value) || !CanRemoveHeldEntityFromHand(hand)) return false; if (checkActionBlocker && (!PlayerCanDrop() || !PlayerCanPickup())) return false; RemoveHeldEntityFromHand(hand); - PutEntityIntoHand(activeHand, heldEntity); + PutEntityIntoHand(activeHand, heldEntity.Value); return true; } @@ -766,13 +750,13 @@ namespace Content.Shared.Hands.Components private void DeselectActiveHeldEntity() { if (TryGetActiveHeldEntity(out var entity)) - EntitySystem.Get().HandDeselectedInteraction(Owner, entity); + EntitySystem.Get().HandDeselectedInteraction(Owner, entity.Value); } private void SelectActiveHeldEntity() { if (TryGetActiveHeldEntity(out var entity)) - EntitySystem.Get().HandSelectedInteraction(Owner, entity); + EntitySystem.Get().HandSelectedInteraction(Owner, entity.Value); } private void HandCountChanged() @@ -905,11 +889,9 @@ namespace Content.Shared.Hands.Components [ViewVariables] public IContainer? Container { get; set; } - // TODO: Make this a nullable EntityUid... [ViewVariables] - public EntityUid HeldEntity => Container?.ContainedEntities.FirstOrDefault() ?? EntityUid.Invalid; + public EntityUid? HeldEntity => Container?.ContainedEntities?.Count > 0 ? Container.ContainedEntities[0] : null; - public bool IsEmpty => HeldEntity == default; public Hand(string name, HandLocation location, IContainer? container = null) { diff --git a/Content.Shared/Interaction/SharedInteractionSystem.cs b/Content.Shared/Interaction/SharedInteractionSystem.cs index 540133acc9..92d1f836b6 100644 --- a/Content.Shared/Interaction/SharedInteractionSystem.cs +++ b/Content.Shared/Interaction/SharedInteractionSystem.cs @@ -139,18 +139,15 @@ namespace Content.Shared.Interaction if (!TryComp(user, out SharedHandsComponent? hands)) return; - // TODO remove invalid/default uid and use nullable. - hands.TryGetActiveHeldEntity(out var heldEntity); - EntityUid? held = heldEntity.Valid ? heldEntity : null; // TODO: Replace with body interaction range when we get something like arm length or telekinesis or something. var inRangeUnobstructed = user.InRangeUnobstructed(coordinates, ignoreInsideBlocker: true); if (target == null || !inRangeUnobstructed) { - if (held == null) + if (!hands.TryGetActiveHeldEntity(out var heldEntity)) return; - if (!await InteractUsingRanged(user, held.Value, target, coordinates, inRangeUnobstructed) && + if (!await InteractUsingRanged(user, heldEntity.Value, target, coordinates, inRangeUnobstructed) && !inRangeUnobstructed) { var message = Loc.GetString("interaction-system-user-interaction-cannot-reach"); @@ -165,13 +162,17 @@ namespace Content.Shared.Interaction if (altInteract) // Perform alternative interactions, using context menu verbs. AltInteract(user, target.Value); - else if (held != null && held != target) - // We are performing a standard interaction with an item, and the target isn't the same as the item - // currently in our hand. We will use the item in our hand on the nearby object via InteractUsing - await InteractUsing(user, held.Value, target.Value, coordinates); - else if (held == null) + + if (!hands.TryGetActiveHeldEntity(out var heldEntity)) + { // Since our hand is empty we will use InteractHand/Activate InteractHand(user, target.Value); + } + else if (heldEntity != target) + { + await InteractUsing(user, heldEntity.Value, target.Value, coordinates); + } + } }