diff --git a/Content.Shared/Mech/EntitySystems/SharedMechSystem.cs b/Content.Shared/Mech/EntitySystems/SharedMechSystem.cs deleted file mode 100644 index 2ec48085c47..00000000000 --- a/Content.Shared/Mech/EntitySystems/SharedMechSystem.cs +++ /dev/null @@ -1,478 +0,0 @@ -using System.Linq; -using Content.Shared.Access.Components; -using Content.Shared.ActionBlocker; -using Content.Shared.Actions; -using Content.Shared.Destructible; -using Content.Shared.DoAfter; -using Content.Shared.DragDrop; -using Content.Shared.FixedPoint; -using Content.Shared.Interaction; -using Content.Shared.Interaction.Components; -using Content.Shared.Interaction.Events; -using Content.Shared.Mech.Components; -using Content.Shared.Mech.Equipment.Components; -using Content.Shared.Movement.Components; -using Content.Shared.Movement.Systems; -using Content.Shared.Popups; -using Content.Shared.Weapons.Melee; -using Content.Shared.Whitelist; -using Robust.Shared.Containers; -using Robust.Shared.Network; -using Robust.Shared.Serialization; -using Robust.Shared.Timing; - -namespace Content.Shared.Mech.EntitySystems; - -/// -/// Handles all of the interactions, UI handling, and items shennanigans for -/// -public abstract class SharedMechSystem : EntitySystem -{ - [Dependency] private readonly IGameTiming _timing = default!; - [Dependency] private readonly INetManager _net = default!; - [Dependency] private readonly ActionBlockerSystem _actionBlocker = default!; - [Dependency] private readonly SharedActionsSystem _actions = default!; - [Dependency] private readonly SharedAppearanceSystem _appearance = default!; - [Dependency] private readonly SharedContainerSystem _container = default!; - [Dependency] private readonly SharedInteractionSystem _interaction = default!; - [Dependency] private readonly SharedMoverController _mover = default!; - [Dependency] private readonly SharedPopupSystem _popup = default!; - [Dependency] private readonly SharedDoAfterSystem _doAfter = default!; - [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; - - /// - public override void Initialize() - { - SubscribeLocalEvent(OnToggleEquipmentAction); - SubscribeLocalEvent(OnEjectPilotEvent); - SubscribeLocalEvent(RelayInteractionEvent); - SubscribeLocalEvent(OnStartup); - SubscribeLocalEvent(OnDestruction); - SubscribeLocalEvent(OnGetAdditionalAccess); - SubscribeLocalEvent(OnDragDrop); - SubscribeLocalEvent(OnCanDragDrop); - - SubscribeLocalEvent(OnGetMeleeWeapon); - SubscribeLocalEvent(OnCanAttackFromContainer); - SubscribeLocalEvent(OnAttackAttempt); - } - - private void OnToggleEquipmentAction(EntityUid uid, MechComponent component, MechToggleEquipmentEvent args) - { - if (args.Handled) - return; - args.Handled = true; - CycleEquipment(uid); - } - - private void OnEjectPilotEvent(EntityUid uid, MechComponent component, MechEjectPilotEvent args) - { - if (args.Handled) - return; - args.Handled = true; - TryEject(uid, component); - } - - private void RelayInteractionEvent(EntityUid uid, MechComponent component, UserActivateInWorldEvent args) - { - var pilot = component.PilotSlot.ContainedEntity; - if (pilot == null) - return; - - // TODO why is this being blocked? - if (!_timing.IsFirstTimePredicted) - return; - - if (component.CurrentSelectedEquipment != null) - { - RaiseLocalEvent(component.CurrentSelectedEquipment.Value, args); - } - } - - private void OnStartup(EntityUid uid, MechComponent component, ComponentStartup args) - { - component.PilotSlot = _container.EnsureContainer(uid, component.PilotSlotId); - component.EquipmentContainer = _container.EnsureContainer(uid, component.EquipmentContainerId); - component.BatterySlot = _container.EnsureContainer(uid, component.BatterySlotId); - UpdateAppearance(uid, component); - } - - private void OnDestruction(EntityUid uid, MechComponent component, DestructionEventArgs args) - { - BreakMech(uid, component); - } - - private void OnGetAdditionalAccess(EntityUid uid, MechComponent component, ref GetAdditionalAccessEvent args) - { - var pilot = component.PilotSlot.ContainedEntity; - if (pilot == null) - return; - - args.Entities.Add(pilot.Value); - } - - private void SetupUser(EntityUid mech, EntityUid pilot, MechComponent? component = null) - { - if (!Resolve(mech, ref component)) - return; - - var rider = EnsureComp(pilot); - - // Warning: this bypasses most normal interaction blocking components on the user, like drone laws and the like. - var irelay = EnsureComp(pilot); - - _mover.SetRelay(pilot, mech); - _interaction.SetRelay(pilot, mech, irelay); - rider.Mech = mech; - Dirty(pilot, rider); - - if (_net.IsClient) - return; - - _actions.AddAction(pilot, ref component.MechCycleActionEntity, component.MechCycleAction, mech); - _actions.AddAction(pilot, ref component.MechUiActionEntity, component.MechUiAction, mech); - _actions.AddAction(pilot, ref component.MechEjectActionEntity, component.MechEjectAction, mech); - } - - private void RemoveUser(EntityUid mech, EntityUid pilot) - { - if (!RemComp(pilot)) - return; - RemComp(pilot); - RemComp(pilot); - - _actions.RemoveProvidedActions(pilot, mech); - } - - /// - /// Destroys the mech, removing the user and ejecting all installed equipment. - /// - /// - /// - public virtual void BreakMech(EntityUid uid, MechComponent? component = null) - { - if (!Resolve(uid, ref component)) - return; - - TryEject(uid, component); - var equipment = new List(component.EquipmentContainer.ContainedEntities); - foreach (var ent in equipment) - { - RemoveEquipment(uid, ent, component, forced: true); - } - - component.Broken = true; - UpdateAppearance(uid, component); - } - - /// - /// Cycles through the currently selected equipment. - /// - /// - /// - public void CycleEquipment(EntityUid uid, MechComponent? component = null) - { - if (!Resolve(uid, ref component)) - return; - - var allEquipment = component.EquipmentContainer.ContainedEntities.ToList(); - - var equipmentIndex = -1; - if (component.CurrentSelectedEquipment != null) - { - bool StartIndex(EntityUid u) => u == component.CurrentSelectedEquipment; - equipmentIndex = allEquipment.FindIndex(StartIndex); - } - - equipmentIndex++; - component.CurrentSelectedEquipment = equipmentIndex >= allEquipment.Count - ? null - : allEquipment[equipmentIndex]; - - var popupString = component.CurrentSelectedEquipment != null - ? Loc.GetString("mech-equipment-select-popup", ("item", component.CurrentSelectedEquipment)) - : Loc.GetString("mech-equipment-select-none-popup"); - - if (_net.IsServer) - _popup.PopupEntity(popupString, uid); - - Dirty(uid, component); - } - - /// - /// Inserts an equipment item into the mech. - /// - /// - /// - /// - /// - public void InsertEquipment(EntityUid uid, EntityUid toInsert, MechComponent? component = null, - MechEquipmentComponent? equipmentComponent = null) - { - if (!Resolve(uid, ref component)) - return; - - if (!Resolve(toInsert, ref equipmentComponent)) - return; - - if (component.EquipmentContainer.ContainedEntities.Count >= component.MaxEquipmentAmount) - return; - - if (_whitelistSystem.IsWhitelistFail(component.EquipmentWhitelist, toInsert)) - return; - - equipmentComponent.EquipmentOwner = uid; - _container.Insert(toInsert, component.EquipmentContainer); - var ev = new MechEquipmentInsertedEvent(uid); - RaiseLocalEvent(toInsert, ref ev); - UpdateUserInterface(uid, component); - } - - /// - /// Removes an equipment item from a mech. - /// - /// - /// - /// - /// - /// Whether or not the removal can be cancelled - public void RemoveEquipment(EntityUid uid, EntityUid toRemove, MechComponent? component = null, - MechEquipmentComponent? equipmentComponent = null, bool forced = false) - { - if (!Resolve(uid, ref component)) - return; - - if (!Resolve(toRemove, ref equipmentComponent)) - return; - - if (!forced) - { - var attemptev = new AttemptRemoveMechEquipmentEvent(); - RaiseLocalEvent(toRemove, ref attemptev); - if (attemptev.Cancelled) - return; - } - - var ev = new MechEquipmentRemovedEvent(uid); - RaiseLocalEvent(toRemove, ref ev); - - if (component.CurrentSelectedEquipment == toRemove) - CycleEquipment(uid, component); - - equipmentComponent.EquipmentOwner = null; - _container.Remove(toRemove, component.EquipmentContainer); - UpdateUserInterface(uid, component); - } - - /// - /// Attempts to change the amount of energy in the mech. - /// - /// The mech itself - /// The change in energy - /// - /// If the energy was successfully changed. - public virtual bool TryChangeEnergy(EntityUid uid, FixedPoint2 delta, MechComponent? component = null) - { - if (!Resolve(uid, ref component)) - return false; - - if (component.Energy + delta < 0) - return false; - - component.Energy = FixedPoint2.Clamp(component.Energy + delta, 0, component.MaxEnergy); - Dirty(uid, component); - UpdateUserInterface(uid, component); - return true; - } - - /// - /// Sets the integrity of the mech. - /// - /// The mech itself - /// The value the integrity will be set at - /// - public void SetIntegrity(EntityUid uid, FixedPoint2 value, MechComponent? component = null) - { - if (!Resolve(uid, ref component)) - return; - - component.Integrity = FixedPoint2.Clamp(value, 0, component.MaxIntegrity); - - if (component.Integrity <= 0) - { - BreakMech(uid, component); - } - else if (component.Broken) - { - component.Broken = false; - UpdateAppearance(uid, component); - } - - Dirty(uid, component); - UpdateUserInterface(uid, component); - } - - /// - /// Checks if the pilot is present - /// - /// - /// Whether or not the pilot is present - public bool IsEmpty(MechComponent component) - { - return component.PilotSlot.ContainedEntity == null; - } - - /// - /// Checks if an entity can be inserted into the mech. - /// - /// - /// - /// - /// - public bool CanInsert(EntityUid uid, EntityUid toInsert, MechComponent? component = null) - { - if (!Resolve(uid, ref component)) - return false; - - return IsEmpty(component) && _actionBlocker.CanMove(toInsert); - } - - /// - /// Updates the user interface - /// - /// - /// This is defined here so that UI updates can be accessed from shared. - /// - public virtual void UpdateUserInterface(EntityUid uid, MechComponent? component = null) - { - } - - /// - /// Attempts to insert a pilot into the mech. - /// - /// - /// - /// - /// Whether or not the entity was inserted - public bool TryInsert(EntityUid uid, EntityUid? toInsert, MechComponent? component = null) - { - if (!Resolve(uid, ref component)) - return false; - - if (toInsert == null || component.PilotSlot.ContainedEntity == toInsert) - return false; - - if (!CanInsert(uid, toInsert.Value, component)) - return false; - - SetupUser(uid, toInsert.Value); - _container.Insert(toInsert.Value, component.PilotSlot); - UpdateAppearance(uid, component); - return true; - } - - /// - /// Attempts to eject the current pilot from the mech - /// - /// - /// - /// Whether or not the pilot was ejected. - public bool TryEject(EntityUid uid, MechComponent? component = null) - { - if (!Resolve(uid, ref component)) - return false; - - if (component.PilotSlot.ContainedEntity == null) - return false; - - var pilot = component.PilotSlot.ContainedEntity.Value; - - RemoveUser(uid, pilot); - _container.RemoveEntity(uid, pilot); - UpdateAppearance(uid, component); - return true; - } - - private void OnGetMeleeWeapon(EntityUid uid, MechPilotComponent component, GetMeleeWeaponEvent args) - { - if (args.Handled) - return; - - if (!TryComp(component.Mech, out var mech)) - return; - - var weapon = mech.CurrentSelectedEquipment ?? component.Mech; - args.Weapon = weapon; - args.Handled = true; - } - - private void OnCanAttackFromContainer(EntityUid uid, MechPilotComponent component, CanAttackFromContainerEvent args) - { - args.CanAttack = true; - } - - private void OnAttackAttempt(EntityUid uid, MechPilotComponent component, AttackAttemptEvent args) - { - if (args.Target == component.Mech) - args.Cancel(); - } - - private void UpdateAppearance(EntityUid uid, MechComponent? component = null, - AppearanceComponent? appearance = null) - { - if (!Resolve(uid, ref component, ref appearance, false)) - return; - - _appearance.SetData(uid, MechVisuals.Open, IsEmpty(component), appearance); - _appearance.SetData(uid, MechVisuals.Broken, component.Broken, appearance); - } - - private void OnDragDrop(EntityUid uid, MechComponent component, ref DragDropTargetEvent args) - { - if (args.Handled) - return; - - args.Handled = true; - - var doAfterEventArgs = new DoAfterArgs(EntityManager, args.Dragged, component.EntryDelay, new MechEntryEvent(), uid, target: uid) - { - BreakOnMove = true, - }; - - _doAfter.TryStartDoAfter(doAfterEventArgs); - } - - private void OnCanDragDrop(EntityUid uid, MechComponent component, ref CanDropTargetEvent args) - { - args.Handled = true; - - args.CanDrop |= !component.Broken && CanInsert(uid, args.Dragged, component); - } - -} - -/// -/// Event raised when the battery is successfully removed from the mech, -/// on both success and failure -/// -[Serializable, NetSerializable] -public sealed partial class RemoveBatteryEvent : SimpleDoAfterEvent -{ -} - -/// -/// Event raised when a person removes someone from a mech, -/// on both success and failure -/// -[Serializable, NetSerializable] -public sealed partial class MechExitEvent : SimpleDoAfterEvent -{ -} - -/// -/// Event raised when a person enters a mech, on both success and failure -/// -[Serializable, NetSerializable] -public sealed partial class MechEntryEvent : SimpleDoAfterEvent -{ -}