Elimate most IInteractUsing (#7481)

This commit is contained in:
Rane
2022-04-15 17:20:20 -04:00
committed by GitHub
parent 569085ab5c
commit 70a26bf0c2
13 changed files with 431 additions and 485 deletions

View File

@@ -1,5 +1,13 @@
using Content.Server.AME.Components;
using System.Linq;
using Content.Server.AME.Components;
using Content.Server.Power.Components;
using Content.Server.Hands.Components;
using Content.Server.Popups;
using Content.Server.Tools;
using Content.Shared.Interaction;
using Robust.Shared.Map;
using Robust.Shared.Player;
using Robust.Shared.Audio;
using JetBrains.Annotations;
namespace Content.Server.AME
@@ -7,6 +15,9 @@ namespace Content.Server.AME
[UsedImplicitly]
public sealed class AntimatterEngineSystem : EntitySystem
{
[Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
[Dependency] private readonly ToolSystem _toolSystem = default!;
private float _accumulatedFrameTime;
private const float UpdateCooldown = 10f;
@@ -15,6 +26,8 @@ namespace Content.Server.AME
{
base.Initialize();
SubscribeLocalEvent<AMEControllerComponent, PowerChangedEvent>(OnAMEPowerChange);
SubscribeLocalEvent<AMEControllerComponent, InteractUsingEvent>(OnInteractUsing);
SubscribeLocalEvent<AMEPartComponent, InteractUsingEvent>(OnPartInteractUsing);
}
public override void Update(float frameTime)
@@ -37,5 +50,61 @@ namespace Content.Server.AME
{
component.UpdateUserInterface();
}
private void OnInteractUsing(EntityUid uid, AMEControllerComponent component, InteractUsingEvent args)
{
if (!TryComp(args.User, out HandsComponent? hands))
{
_popupSystem.PopupEntity(Loc.GetString("ame-controller-component-interact-using-no-hands-text"), uid, Filter.Entities(args.User));
return;
}
if (HasComp<AMEFuelContainerComponent?>(args.Used))
{
if (component.HasJar)
{
_popupSystem.PopupEntity(Loc.GetString("ame-controller-component-interact-using-already-has-jar"), uid, Filter.Entities(args.User));
}
else
{
component.JarSlot.Insert(args.Used);
_popupSystem.PopupEntity(Loc.GetString("ame-controller-component-interact-using-success"), uid, Filter.Entities(args.User));
component.UpdateUserInterface();
}
}
else
{
_popupSystem.PopupEntity(Loc.GetString("ame-controller-component-interact-using-fail"), uid, Filter.Entities(args.User));
}
}
private void OnPartInteractUsing(EntityUid uid, AMEPartComponent component, InteractUsingEvent args)
{
if (!HasComp<HandsComponent>(args.User))
{
_popupSystem.PopupEntity(Loc.GetString("ame-part-component-interact-using-no-hands"), uid, Filter.Entities(args.User));
return;
}
if (!_toolSystem.HasQuality(args.Used, component.QualityNeeded))
return;
if (!_mapManager.TryGetGrid(args.ClickLocation.GetGridId(EntityManager), out var mapGrid))
return; // No AME in space.
var snapPos = mapGrid.TileIndicesFor(args.ClickLocation);
if (mapGrid.GetAnchoredEntities(snapPos).Any(sc => HasComp<AMEShieldComponent>(sc)))
{
_popupSystem.PopupEntity(Loc.GetString("ame-part-component-shielding-already-present"), uid, Filter.Entities(args.User));
return;
}
var ent = EntityManager.SpawnEntity("AMEShielding", mapGrid.GridTileToLocal(snapPos));
SoundSystem.Play(Filter.Pvs(uid), component.UnwrapSound.GetSound(), uid);
EntityManager.QueueDeleteEntity(uid);
}
}
}

View File

@@ -1,16 +1,9 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using Content.Server.Hands.Components;
using Content.Server.NodeContainer;
using Content.Server.Power.Components;
using Content.Server.UserInterface;
using Content.Shared.ActionBlocker;
using Content.Shared.AME;
using Content.Shared.Hands.EntitySystems;
using Content.Shared.Interaction;
using Content.Shared.Item;
using Content.Shared.Popups;
using Content.Shared.Sound;
using Robust.Server.GameObjects;
using Robust.Shared.Audio;
@@ -20,8 +13,7 @@ using Robust.Shared.Player;
namespace Content.Server.AME.Components
{
[RegisterComponent]
[ComponentReference(typeof(IInteractUsing))]
public sealed class AMEControllerComponent : SharedAMEControllerComponent, IInteractUsing
public sealed class AMEControllerComponent : SharedAMEControllerComponent
{
[Dependency] private readonly IEntityManager _entities = default!;
[Dependency] private readonly IEntitySystemManager _sysMan = default!;
@@ -41,8 +33,8 @@ namespace Content.Server.AME.Components
[ViewVariables]
private int _stability = 100;
private ContainerSlot _jarSlot = default!;
[ViewVariables] private bool HasJar => _jarSlot.ContainedEntity != null;
public ContainerSlot JarSlot = default!;
[ViewVariables] public bool HasJar => JarSlot.ContainedEntity != null;
protected override void Initialize()
{
@@ -59,7 +51,7 @@ namespace Content.Server.AME.Components
_injecting = false;
InjectionAmount = 2;
_jarSlot = ContainerHelpers.EnsureContainer<ContainerSlot>(Owner, $"{Name}-fuelJarContainer");
JarSlot = ContainerHelpers.EnsureContainer<ContainerSlot>(Owner, $"{Name}-fuelJarContainer");
}
internal void OnUpdate(float frameTime)
@@ -76,7 +68,7 @@ namespace Content.Server.AME.Components
return;
}
if (_jarSlot.ContainedEntity is not {Valid: true} jar)
if (JarSlot.ContainedEntity is not {Valid: true} jar)
return;
_entities.TryGetComponent<AMEFuelContainerComponent?>(jar, out var fuelJar);
@@ -105,7 +97,7 @@ namespace Content.Server.AME.Components
private AMEControllerBoundUserInterfaceState GetUserInterfaceState()
{
if (_jarSlot.ContainedEntity is not {Valid: true} jar)
if (JarSlot.ContainedEntity is not {Valid: true} jar)
{
return new AMEControllerBoundUserInterfaceState(Powered, IsMasterController(), false, HasJar, 0, InjectionAmount, GetCoreCount());
}
@@ -187,10 +179,10 @@ namespace Content.Server.AME.Components
if (!HasJar || _injecting)
return;
if (_jarSlot.ContainedEntity is not {Valid: true} jar)
if (JarSlot.ContainedEntity is not {Valid: true} jar)
return;
_jarSlot.Remove(jar);
JarSlot.Remove(jar);
UpdateUserInterface();
_sysMan.GetEntitySystem<SharedHandsSystem>().PickupOrDrop(user, jar);
@@ -277,43 +269,6 @@ namespace Content.Server.AME.Components
{
SoundSystem.Play(Filter.Pvs(Owner), _injectSound.GetSound(), Owner, AudioParams.Default.WithVolume(overloading ? 10f : 0f));
}
async Task<bool> IInteractUsing.InteractUsing(InteractUsingEventArgs args)
{
if (!_entities.TryGetComponent(args.User, out HandsComponent? hands))
{
Owner.PopupMessage(args.User, Loc.GetString("ame-controller-component-interact-using-no-hands-text"));
return true;
}
if (hands.ActiveHandEntity == null)
{
Owner.PopupMessage(args.User, Loc.GetString("ame-controller-component-interact-using-nothing-in-hands-text"));
return false;
}
var activeHandEntity = hands.ActiveHandEntity;
if (_entities.HasComponent<AMEFuelContainerComponent?>(activeHandEntity))
{
if (HasJar)
{
Owner.PopupMessage(args.User, Loc.GetString("ame-controller-component-interact-using-already-has-jar"));
}
else
{
_jarSlot.Insert(activeHandEntity.Value);
Owner.PopupMessage(args.User, Loc.GetString("ame-controller-component-interact-using-success"));
UpdateUserInterface();
}
}
else
{
Owner.PopupMessage(args.User, Loc.GetString("ame-controller-component-interact-using-fail"));
}
return true;
}
}
}

View File

@@ -1,64 +1,16 @@
using System.Linq;
using System.Threading.Tasks;
using Content.Server.Hands.Components;
using Content.Server.Tools;
using Content.Shared.Interaction;
using Content.Shared.Popups;
using Content.Shared.Sound;
using Robust.Server.GameObjects;
using Robust.Shared.Audio;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Map;
using Robust.Shared.Player;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Server.AME.Components
{
[RegisterComponent]
[ComponentReference(typeof(IInteractUsing))]
public sealed class AMEPartComponent : Component, IInteractUsing
public sealed class AMEPartComponent : Component
{
[Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly IServerEntityManager _serverEntityManager = default!;
[DataField("unwrapSound")]
private SoundSpecifier _unwrapSound = new SoundPathSpecifier("/Audio/Effects/unwrap.ogg");
public SoundSpecifier UnwrapSound = new SoundPathSpecifier("/Audio/Effects/unwrap.ogg");
[DataField("qualityNeeded", customTypeSerializer:typeof(PrototypeIdSerializer<EntityPrototype>))]
private string _qualityNeeded = "Pulsing";
async Task<bool> IInteractUsing.InteractUsing(InteractUsingEventArgs args)
{
if (!_serverEntityManager.HasComponent<HandsComponent>(args.User))
{
Owner.PopupMessage(args.User, Loc.GetString("ame-part-component-interact-using-no-hands"));
return false;
}
if (!EntitySystem.Get<ToolSystem>().HasQuality(args.Using, _qualityNeeded))
return false;
if (!_mapManager.TryGetGrid(args.ClickLocation.GetGridId(_serverEntityManager), out var mapGrid))
return false; // No AME in space.
var snapPos = mapGrid.TileIndicesFor(args.ClickLocation);
if (mapGrid.GetAnchoredEntities(snapPos).Any(sc => _serverEntityManager.HasComponent<AMEShieldComponent>(sc)))
{
Owner.PopupMessage(args.User, Loc.GetString("ame-part-component-shielding-already-present"));
return true;
}
var ent = _serverEntityManager.SpawnEntity("AMEShielding", mapGrid.GridTileToLocal(snapPos));
SoundSystem.Play(Filter.Pvs(Owner), _unwrapSound.GetSound(), Owner);
_serverEntityManager.QueueDeleteEntity(Owner);
return true;
}
public string QualityNeeded = "Pulsing";
}
}

View File

@@ -1,23 +1,13 @@
using System.Threading.Tasks;
using Content.Server.Atmos;
using Content.Server.Atmos.EntitySystems;
using Content.Server.Botany.Systems;
using Content.Server.Chemistry.EntitySystems;
using Content.Server.Fluids.Components;
using Content.Server.Hands.Components;
using Content.Server.Kitchen.Components;
using Content.Server.Popups;
using Content.Shared.Audio;
using Content.Shared.Botany;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.FixedPoint;
using Content.Shared.Interaction;
using Content.Shared.Popups;
using Content.Shared.Random.Helpers;
using Content.Shared.Tag;
using Robust.Shared.Audio;
using Robust.Shared.Player;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using Robust.Shared.Timing;
@@ -26,7 +16,7 @@ namespace Content.Server.Botany.Components
{
[RegisterComponent]
#pragma warning disable 618
public sealed class PlantHolderComponent : Component, IInteractUsing, IInteractHand, IActivate
public sealed class PlantHolderComponent : Component, IInteractHand, IActivate
#pragma warning restore 618
{
public const float HydroponicsSpeedMultiplier = 1f;
@@ -43,7 +33,7 @@ namespace Content.Server.Botany.Components
private readonly TimeSpan _cycleDelay = TimeSpan.FromSeconds(15f);
[ViewVariables] private TimeSpan _lastCycle = TimeSpan.Zero;
[ViewVariables] public TimeSpan LastCycle = TimeSpan.Zero;
[ViewVariables(VVAccess.ReadWrite)] private bool _updateSpriteAfterUpdate;
@@ -127,14 +117,14 @@ namespace Content.Server.Botany.Components
if (ForceUpdate)
ForceUpdate = false;
else if (curTime < (_lastCycle + _cycleDelay))
else if (curTime < (LastCycle + _cycleDelay))
{
if (_updateSpriteAfterUpdate)
UpdateSprite();
return;
}
_lastCycle = curTime;
LastCycle = curTime;
// todo ecs.
var botanySystem = EntitySystem.Get<BotanySystem>();
@@ -389,7 +379,7 @@ namespace Content.Server.Botany.Components
UpdateSprite();
}
private void CheckLevelSanity()
public void CheckLevelSanity()
{
if (Seed != null)
Health = MathHelper.Clamp(Health, 0, Seed.Endurance);
@@ -634,196 +624,13 @@ namespace Content.Server.Botany.Components
Seed = Seed.Diverge(modified);
}
private void ForceUpdateByExternalCause()
public void ForceUpdateByExternalCause()
{
SkipAging++; // We're forcing an update cycle, so one age hasn't passed.
ForceUpdate = true;
Update();
}
async Task<bool> IInteractUsing.InteractUsing(InteractUsingEventArgs eventArgs)
{
var user = eventArgs.User;
var usingItem = eventArgs.Using;
if ((!_entMan.EntityExists(usingItem) ? EntityLifeStage.Deleted : _entMan.GetComponent<MetaDataComponent>(usingItem).EntityLifeStage) >= EntityLifeStage.Deleted)
return false;
var botanySystem = EntitySystem.Get<BotanySystem>();
if (_entMan.TryGetComponent(usingItem, out SeedComponent? seeds))
{
if (Seed == null)
{
var protoMan = IoCManager.Resolve<IPrototypeManager>();
if (!protoMan.TryIndex<SeedPrototype>(seeds.SeedName, out var seed))
return false;
user.PopupMessageCursor(Loc.GetString("plant-holder-component-plant-success-message",
("seedName", seed.SeedName),
("seedNoun", seed.SeedNoun)));
Seed = seed;
Dead = false;
Age = 1;
Health = Seed.Endurance;
_lastCycle = _gameTiming.CurTime;
_entMan.QueueDeleteEntity(usingItem);
CheckLevelSanity();
UpdateSprite();
return true;
}
user.PopupMessageCursor(Loc.GetString("plant-holder-component-already-seeded-message",
("name", _entMan.GetComponent<MetaDataComponent>(Owner).EntityName)));
return false;
}
var tagSystem = EntitySystem.Get<TagSystem>();
if (tagSystem.HasTag(usingItem, "Hoe"))
{
if (WeedLevel > 0)
{
user.PopupMessageCursor(Loc.GetString("plant-holder-component-remove-weeds-message",
("name", _entMan.GetComponent<MetaDataComponent>(Owner).EntityName)));
user.PopupMessageOtherClients(Loc.GetString("plant-holder-component-remove-weeds-others-message",
("otherName", _entMan.GetComponent<MetaDataComponent>(user).EntityName)));
WeedLevel = 0;
UpdateSprite();
}
else
{
user.PopupMessageCursor(Loc.GetString("plant-holder-component-no-weeds-message"));
}
return true;
}
if (tagSystem.HasTag(usingItem, "Shovel"))
{
if (Seed != null)
{
user.PopupMessageCursor(Loc.GetString("plant-holder-component-remove-plant-message",
("name", _entMan.GetComponent<MetaDataComponent>(Owner).EntityName)));
user.PopupMessageOtherClients(Loc.GetString("plant-holder-component-remove-plant-others-message",
("name", _entMan.GetComponent<MetaDataComponent>(user).EntityName)));
RemovePlant();
}
else
{
user.PopupMessageCursor(Loc.GetString("plant-holder-component-no-plant-message"));
}
return true;
}
var solutionSystem = EntitySystem.Get<SolutionContainerSystem>();
if (solutionSystem.TryGetDrainableSolution(usingItem, out var solution)
&& solutionSystem.TryGetSolution(Owner, SoilSolutionName, out var targetSolution) && _entMan.TryGetComponent(usingItem, out SprayComponent? spray))
{
var amount = FixedPoint2.New(1);
var targetEntity = Owner;
var solutionEntity = usingItem;
SoundSystem.Play(Filter.Pvs(usingItem), spray.SpraySound.GetSound(), usingItem,
AudioHelpers.WithVariation(0.125f));
var split = solutionSystem.Drain(solutionEntity, solution, amount);
if (split.TotalVolume == 0)
{
user.PopupMessageCursor(Loc.GetString("plant-holder-component-empty-message",
("owner", usingItem)));
return true;
}
user.PopupMessageCursor(Loc.GetString("plant-holder-component-spray-message",
("owner", Owner),
("amount", split.TotalVolume)));
solutionSystem.TryAddSolution(targetEntity, targetSolution, split);
ForceUpdateByExternalCause();
return true;
}
if (tagSystem.HasTag(usingItem, "PlantSampleTaker"))
{
if (Seed == null)
{
user.PopupMessageCursor(Loc.GetString("plant-holder-component-nothing-to-sample-message"));
return false;
}
if (Sampled)
{
user.PopupMessageCursor(Loc.GetString("plant-holder-component-already-sampled-message"));
return false;
}
if (Dead)
{
user.PopupMessageCursor(Loc.GetString("plant-holder-component-dead-plant-message"));
return false;
}
var seed = botanySystem.SpawnSeedPacket(Seed, _entMan.GetComponent<TransformComponent>(user).Coordinates);
seed.RandomOffset(0.25f);
user.PopupMessageCursor(Loc.GetString("plant-holder-component-take-sample-message",
("seedName", Seed.DisplayName)));
Health -= (_random.Next(3, 5) * 10);
if (_random.Prob(0.3f))
Sampled = true;
// Just in case.
CheckLevelSanity();
ForceUpdateByExternalCause();
return true;
}
if (_entMan.HasComponent<SharpComponent>(usingItem))
{
return DoHarvest(user);
}
if (_entMan.TryGetComponent<ProduceComponent?>(usingItem, out var produce))
{
user.PopupMessageCursor(Loc.GetString("plant-holder-component-compost-message",
("owner", Owner),
("usingItem", usingItem)));
user.PopupMessageOtherClients(Loc.GetString("plant-holder-component-compost-others-message",
("user", user),
("usingItem", usingItem),
("owner", Owner)));
if (solutionSystem.TryGetSolution(usingItem, produce.SolutionName, out var solution2))
{
// This deliberately discards overfill.
solutionSystem.TryAddSolution(usingItem, solution2,
solutionSystem.SplitSolution(usingItem, solution2, solution2.TotalVolume));
ForceUpdateByExternalCause();
}
_entMan.QueueDeleteEntity(usingItem);
return true;
}
return false;
}
bool IInteractHand.InteractHand(InteractHandEventArgs eventArgs)
{
// DoHarvest does the sanity checks.

View File

@@ -1,14 +1,37 @@
using Content.Server.Botany.Components;
using Content.Server.Popups;
using Content.Server.Chemistry.EntitySystems;
using Content.Server.Fluids.Components;
using Content.Server.Kitchen.Components;
using Content.Shared.Interaction;
using Content.Shared.Examine;
using Content.Shared.Tag;
using Content.Shared.FixedPoint;
using Content.Shared.Audio;
using Content.Shared.Random.Helpers;
using Robust.Shared.Prototypes;
using Robust.Shared.Player;
using Robust.Shared.Timing;
using Robust.Shared.Audio;
using Robust.Shared.Random;
namespace Content.Server.Botany.Systems
{
public sealed class PlantHolderSystem : EntitySystem
{
[Dependency] private readonly BotanySystem _botanySystem = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly TagSystem _tagSystem = default!;
[Dependency] private readonly SolutionContainerSystem _solutionSystem = default!;
[Dependency] private readonly IRobustRandom _random = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<PlantHolderComponent, ExaminedEvent>(OnExamine);
SubscribeLocalEvent<PlantHolderComponent, InteractUsingEvent>(OnInteractUsing);
}
private void OnExamine(EntityUid uid, PlantHolderComponent component, ExaminedEvent args)
@@ -68,5 +91,170 @@ namespace Content.Server.Botany.Systems
args.PushMarkup(Loc.GetString("plant-holder-component-gas-missing-warning"));
}
}
private void OnInteractUsing(EntityUid uid, PlantHolderComponent component, InteractUsingEvent args)
{
if (TryComp(args.Used, out SeedComponent? seeds))
{
if (component.Seed == null)
{
if (!_prototypeManager.TryIndex<SeedPrototype>(seeds.SeedName, out var seed))
return;
_popupSystem.PopupCursor(Loc.GetString("plant-holder-component-plant-success-message",
("seedName", seed.SeedName),
("seedNoun", seed.SeedNoun)), Filter.Entities(args.User));
component.Seed = seed;
component.Dead = false;
component.Age = 1;
component.Health = component.Seed.Endurance;
component.LastCycle = _gameTiming.CurTime;
EntityManager.QueueDeleteEntity(args.Used);
component.CheckLevelSanity();
component.UpdateSprite();
return;
}
_popupSystem.PopupCursor(Loc.GetString("plant-holder-component-already-seeded-message",
("name", Comp<MetaDataComponent>(uid).EntityName)), Filter.Entities(args.User));
return;
}
if (_tagSystem.HasTag(args.Used, "Hoe"))
{
if (component.WeedLevel > 0)
{
_popupSystem.PopupCursor(Loc.GetString("plant-holder-component-remove-weeds-message",
("name", Comp<MetaDataComponent>(uid).EntityName)), Filter.Entities(args.User));
_popupSystem.PopupEntity(Loc.GetString("plant-holder-component-remove-weeds-others-message",
("otherName", Comp<MetaDataComponent>(args.User).EntityName)), uid, Filter.Pvs(args.User).RemoveWhereAttachedEntity(puid => puid == args.User));
component.WeedLevel = 0;
component.UpdateSprite();
}
else
{
_popupSystem.PopupCursor(Loc.GetString("plant-holder-component-no-weeds-message"), Filter.Entities(args.User));
}
return;
}
if (_tagSystem.HasTag(args.Used, "Shovel"))
{
if (component.Seed != null)
{
_popupSystem.PopupCursor(Loc.GetString("plant-holder-component-remove-plant-message",
("name", Comp<MetaDataComponent>(uid).EntityName)), Filter.Entities(args.User));
_popupSystem.PopupEntity(Loc.GetString("plant-holder-component-remove-plant-others-message",
("otherName", Comp<MetaDataComponent>(args.User).EntityName)), uid, Filter.Pvs(args.User).RemoveWhereAttachedEntity(puid => puid == args.User));
component.RemovePlant();
}
else
{
_popupSystem.PopupCursor(Loc.GetString("plant-holder-component-no-plant-message",
("name", Comp<MetaDataComponent>(uid).EntityName)), Filter.Entities(args.User));
}
return;
}
if (_solutionSystem.TryGetDrainableSolution(args.Used, out var solution)
&& _solutionSystem.TryGetSolution(uid, component.SoilSolutionName, out var targetSolution) && TryComp(args.Used, out SprayComponent? spray))
{
var amount = FixedPoint2.New(1);
var targetEntity = uid;
var solutionEntity = args.Used;
SoundSystem.Play(Filter.Pvs(args.Used), spray.SpraySound.GetSound(), args.Used,
AudioHelpers.WithVariation(0.125f));
var split =_solutionSystem.Drain(solutionEntity, solution, amount);
if (split.TotalVolume == 0)
{
_popupSystem.PopupCursor(Loc.GetString("plant-holder-component-no-plant-message",
("owner", args.Used)), Filter.Entities(args.User));
return;
}
_popupSystem.PopupCursor(Loc.GetString("plant-holder-component-spray-message",
("owner", uid),
("amount", split.TotalVolume)), Filter.Entities(args.User));
_solutionSystem.TryAddSolution(targetEntity, targetSolution, split);
component.ForceUpdateByExternalCause();
return;
}
if (_tagSystem.HasTag(args.Used, "PlantSampleTaker"))
{
if (component.Seed == null)
{
_popupSystem.PopupCursor(Loc.GetString("plant-holder-component-nothing-to-sample-message"), Filter.Entities(args.User));
return;
}
if (component.Sampled)
{
_popupSystem.PopupCursor(Loc.GetString("plant-holder-component-already-sampled-message"), Filter.Entities(args.User));
return;
}
if (component.Dead)
{
_popupSystem.PopupCursor(Loc.GetString("plant-holder-component-dead-plant-message"), Filter.Entities(args.User));
return;
}
var seed = _botanySystem.SpawnSeedPacket(component.Seed, Transform(args.User).Coordinates);
seed.RandomOffset(0.25f);
_popupSystem.PopupCursor(Loc.GetString("plant-holder-component-take-sample-message",
("seedName", component.Seed.DisplayName)), Filter.Entities(args.User));
component.Health -= (_random.Next(3, 5) * 10);
if (_random.Prob(0.3f))
component.Sampled = true;
// Just in case.
component.CheckLevelSanity();
component.ForceUpdateByExternalCause();
return;
}
if (HasComp<SharpComponent>(args.Used))
component.DoHarvest(args.User);
if (TryComp<ProduceComponent?>(args.Used, out var produce))
{
_popupSystem.PopupCursor(Loc.GetString("plant-holder-component-compost-message",
("owner", uid),
("args.Used", args.Used)), Filter.Entities(args.User));
_popupSystem.PopupEntity(Loc.GetString("plant-holder-component-compost-others-message",
("user", args.User),
("args.Used", args.Used),
("owner", uid)), uid, Filter.Pvs(args.User).RemoveWhereAttachedEntity(puid => puid == args.User));
if (_solutionSystem.TryGetSolution(args.Used, produce.SolutionName, out var solution2))
{
// This deliberately discards overfill.
_solutionSystem.TryAddSolution(args.Used, solution2,
_solutionSystem.SplitSolution(args.Used, solution2, solution2.TotalVolume));
component.ForceUpdateByExternalCause();
}
EntityManager.QueueDeleteEntity(args.Used);
}
}
}
}

View File

@@ -1,13 +1,4 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Content.Server.Stack;
using Content.Server.Tools;
using Content.Shared.Interaction;
using Content.Shared.Tools;
using Content.Shared.Tools.Components;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Server.Construction.Components
@@ -17,61 +8,20 @@ namespace Content.Server.Construction.Components
/// For example, glass shard can be refined to glass sheet.
/// </summary>
[RegisterComponent]
public sealed class WelderRefinableComponent : Component, IInteractUsing
public sealed class WelderRefinableComponent : Component
{
[Dependency] private readonly IEntityManager _entMan = default!;
[DataField("refineResult")]
private HashSet<string>? _refineResult = new() { };
public HashSet<string>? RefineResult = new() { };
[DataField("refineTime")]
private float _refineTime = 2f;
public float RefineTime = 2f;
[DataField("refineFuel")]
private float _refineFuel = 0f;
public float RefineFuel = 0f;
[DataField("qualityNeeded", customTypeSerializer:typeof(PrototypeIdSerializer<ToolQualityPrototype>))]
private string _qualityNeeded = "Welding";
public string QualityNeeded = "Welding";
private bool _beingWelded;
async Task<bool> IInteractUsing.InteractUsing(InteractUsingEventArgs eventArgs)
{
// check if object is welder
if (!_entMan.TryGetComponent(eventArgs.Using, out ToolComponent? tool))
return false;
// check if someone is already welding object
if (_beingWelded)
return false;
_beingWelded = true;
var toolSystem = EntitySystem.Get<ToolSystem>();
if (!await toolSystem.UseTool(eventArgs.Using, eventArgs.User, Owner, _refineFuel, _refineTime, _qualityNeeded))
{
// failed to veld - abort refine
_beingWelded = false;
return false;
}
// get last owner coordinates and delete it
var resultPosition = _entMan.GetComponent<TransformComponent>(Owner).Coordinates;
_entMan.DeleteEntity(Owner);
// spawn each result after refine
foreach (var result in _refineResult!)
{
var droppedEnt = _entMan.SpawnEntity(result, resultPosition);
// TODO: If something has a stack... Just use a prototype with a single thing in the stack.
// This is not a good way to do it.
if (_entMan.TryGetComponent<StackComponent?>(droppedEnt, out var stack))
EntitySystem.Get<StackSystem>().SetCount(droppedEnt,1, stack);
}
return true;
}
public bool BeingWelded;
}
}

View File

@@ -0,0 +1,54 @@
using Content.Server.Construction.Components;
using Content.Server.Tools;
using Content.Server.Stack;
using Content.Shared.Interaction;
using Content.Shared.Tools.Components;
namespace Content.Server.Construction
{
public sealed class RefiningSystem : EntitySystem
{
[Dependency] private readonly ToolSystem _toolSystem = default!;
[Dependency] private readonly StackSystem _stackSystem = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<WelderRefinableComponent, InteractUsingEvent>(OnInteractUsing);
}
private async void OnInteractUsing(EntityUid uid, WelderRefinableComponent component, InteractUsingEvent args)
{
// check if object is welder
if (!TryComp(args.Used, out ToolComponent? tool))
return;
// check if someone is already welding object
if (component.BeingWelded)
return;
component.BeingWelded = true;
if (!await _toolSystem.UseTool(args.Used, args.User, uid, component.RefineFuel, component.RefineTime, component.QualityNeeded))
{
// failed to veld - abort refine
component.BeingWelded = false;
return;
}
// get last owner coordinates and delete it
var resultPosition = Transform(uid).Coordinates;
EntityManager.DeleteEntity(uid);
// spawn each result after refine
foreach (var result in component.RefineResult!)
{
var droppedEnt = EntityManager.SpawnEntity(result, resultPosition);
// TODO: If something has a stack... Just use a prototype with a single thing in the stack.
// This is not a good way to do it.
if (TryComp<StackComponent?>(droppedEnt, out var stack))
_stackSystem.SetCount(droppedEnt,1, stack);
}
}
}
}

View File

@@ -1,10 +1,8 @@
using System.Linq;
using System.Threading.Tasks;
using Content.Server.Act;
using Content.Server.Chat.Managers;
using Content.Server.Chemistry.Components.SolutionManager;
using Content.Server.Chemistry.EntitySystems;
using Content.Server.Hands.Components;
using Content.Server.Popups;
using Content.Server.Power.Components;
using Content.Server.Temperature.Components;
@@ -14,8 +12,6 @@ using Content.Shared.Acts;
using Content.Shared.Body.Components;
using Content.Shared.Body.Part;
using Content.Shared.FixedPoint;
using Content.Shared.Interaction;
using Content.Shared.Item;
using Content.Shared.Kitchen;
using Content.Shared.Kitchen.Components;
using Content.Shared.Popups;
@@ -30,7 +26,7 @@ using Robust.Shared.Player;
namespace Content.Server.Kitchen.Components
{
[RegisterComponent]
public sealed class MicrowaveComponent : SharedMicrowaveComponent, IInteractUsing, ISuicideAct, IBreakAct
public sealed class MicrowaveComponent : SharedMicrowaveComponent, ISuicideAct, IBreakAct
{
[Dependency] private readonly IEntityManager _entities = default!;
@@ -56,7 +52,7 @@ namespace Content.Server.Kitchen.Components
#endregion YAMLSERIALIZE
[ViewVariables] private bool _busy = false;
private bool _broken;
public bool Broken;
/// <summary>
/// This is a fixed offset of 5.
@@ -71,9 +67,9 @@ namespace Content.Server.Kitchen.Components
[DataField("temperatureUpperThreshold")]
public float TemperatureUpperThreshold = 373.15f;
private bool Powered => !_entities.TryGetComponent(Owner, out ApcPowerReceiverComponent? receiver) || receiver.Powered;
public bool Powered => !_entities.TryGetComponent(Owner, out ApcPowerReceiverComponent? receiver) || receiver.Powered;
private bool HasContents => _storage.ContainedEntities.Count > 0;
private bool HasContents => Storage.ContainedEntities.Count > 0;
public bool UIDirty = true;
private bool _lostPower;
@@ -84,7 +80,7 @@ namespace Content.Server.Kitchen.Components
UIDirty = true;
}
private Container _storage = default!;
public Container Storage = default!;
[ViewVariables] private BoundUserInterface? UserInterface => Owner.GetUIOrNull(MicrowaveUiKey.Key);
@@ -94,7 +90,7 @@ namespace Content.Server.Kitchen.Components
_currentCookTimerTime = _cookTimeDefault;
_storage = ContainerHelpers.EnsureContainer<Container>(Owner, "microwave_entity_container",
Storage = ContainerHelpers.EnsureContainer<Container>(Owner, "microwave_entity_container",
out _);
if (UserInterface != null)
@@ -159,7 +155,7 @@ namespace Content.Server.Kitchen.Components
UIDirty = true;
}
if (_busy && _broken)
if (_busy && Broken)
{
SetAppearance(MicrowaveVisualState.Broken);
//we broke while we were cooking/busy!
@@ -173,7 +169,7 @@ namespace Content.Server.Kitchen.Components
{
UserInterface?.SetState(new MicrowaveUpdateUserInterfaceState
(
_storage.ContainedEntities.Select(item => item).ToArray(),
Storage.ContainedEntities.Select(item => item).ToArray(),
_busy,
_currentCookTimeButtonIndex,
_currentCookTimerTime
@@ -185,7 +181,7 @@ namespace Content.Server.Kitchen.Components
private void SetAppearance(MicrowaveVisualState state)
{
var finalState = state;
if (_broken)
if (Broken)
{
finalState = MicrowaveVisualState.Broken;
}
@@ -198,42 +194,9 @@ namespace Content.Server.Kitchen.Components
public void OnBreak(BreakageEventArgs eventArgs)
{
_broken = true;
Broken = true;
SetAppearance(MicrowaveVisualState.Broken);
}
async Task<bool> IInteractUsing.InteractUsing(InteractUsingEventArgs eventArgs)
{
if (!Powered)
{
Owner.PopupMessage(eventArgs.User, Loc.GetString("microwave-component-interact-using-no-power"));
return false;
}
if (_broken)
{
Owner.PopupMessage(eventArgs.User, Loc.GetString("microwave-component-interact-using-broken"));
return false;
}
if (_entities.GetComponent<HandsComponent>(eventArgs.User).ActiveHandEntity is not {Valid: true} itemEntity)
{
eventArgs.User.PopupMessage(Loc.GetString("microwave-component-interact-using-no-active-hand"));
return false;
}
if (!_entities.TryGetComponent(itemEntity, typeof(SharedItemComponent), out var food))
{
Owner.PopupMessage(eventArgs.User, "microwave-component-interact-using-transfer-fail");
return false;
}
var ent = food.Owner; //Get the entity of the ItemComponent.
_storage.Insert(ent);
UIDirty = true;
return true;
}
// ReSharper disable once InconsistentNaming
// ReSharper disable once IdentifierTypo
private void Wzhzhzh()
@@ -247,7 +210,7 @@ namespace Content.Server.Kitchen.Components
// Convert storage into Dictionary of ingredients
var solidsDict = new Dictionary<string, int>();
var reagentDict = new Dictionary<string, FixedPoint2>();
foreach (var item in _storage.ContainedEntities)
foreach (var item in Storage.ContainedEntities)
{
// special behavior when being microwaved ;)
var ev = new BeingMicrowavedEvent(Owner);
@@ -262,7 +225,7 @@ namespace Content.Server.Kitchen.Components
|| tagSys.HasTag(item, "Metal"))
{
// destroy microwave
_broken = true;
Broken = true;
SetAppearance(MicrowaveVisualState.Broken);
SoundSystem.Play(Filter.Pvs(Owner), ItemBreakSound.GetSound(), Owner);
return;
@@ -355,7 +318,7 @@ namespace Content.Server.Kitchen.Components
public void AddTemperature(float time)
{
var solutionContainerSystem = EntitySystem.Get<SolutionContainerSystem>();
foreach (var entity in _storage.ContainedEntities)
foreach (var entity in Storage.ContainedEntities)
{
if (_entities.TryGetComponent(entity, out TemperatureComponent? temp))
{
@@ -377,9 +340,9 @@ namespace Content.Server.Kitchen.Components
private void EjectSolids()
{
for (var i = _storage.ContainedEntities.Count - 1; i >= 0; i--)
for (var i = Storage.ContainedEntities.Count - 1; i >= 0; i--)
{
_storage.Remove(_storage.ContainedEntities.ElementAt(i));
Storage.Remove(Storage.ContainedEntities.ElementAt(i));
}
}
@@ -387,7 +350,7 @@ namespace Content.Server.Kitchen.Components
{
if (_entities.EntityExists(entityId))
{
_storage.Remove(entityId);
Storage.Remove(entityId);
}
}
@@ -397,7 +360,7 @@ namespace Content.Server.Kitchen.Components
var solutionContainerSystem = EntitySystem.Get<SolutionContainerSystem>();
// this is spaghetti ngl
foreach (var item in _storage.ContainedEntities)
foreach (var item in Storage.ContainedEntities)
{
if (!_entities.TryGetComponent<SolutionContainerManagerComponent>(item, out var solMan))
continue;
@@ -435,7 +398,7 @@ namespace Content.Server.Kitchen.Components
{
for (var i = 0; i < recipeSolid.Value; i++)
{
foreach (var item in _storage.ContainedEntities)
foreach (var item in Storage.ContainedEntities)
{
var metaData = _entities.GetComponent<MetaDataComponent>(item);
if (metaData.EntityPrototype == null)
@@ -445,7 +408,7 @@ namespace Content.Server.Kitchen.Components
if (metaData.EntityPrototype.ID == recipeSolid.Key)
{
_storage.Remove(item);
Storage.Remove(item);
_entities.DeleteEntity(item);
break;
}
@@ -512,7 +475,7 @@ namespace Content.Server.Kitchen.Components
continue;
}
_storage.Insert(droppedPart.Owner);
Storage.Insert(droppedPart.Owner);
headCount++;
}
}

View File

@@ -1,6 +1,9 @@
using Content.Server.Chemistry.EntitySystems;
using Content.Server.Kitchen.Components;
using Content.Server.UserInterface;
using Content.Server.Popups;
using Content.Shared.Interaction;
using Content.Shared.Item;
using Robust.Shared.Player;
using JetBrains.Annotations;
namespace Content.Server.Kitchen.EntitySystems
@@ -8,11 +11,13 @@ namespace Content.Server.Kitchen.EntitySystems
[UsedImplicitly]
internal sealed class MicrowaveSystem : EntitySystem
{
[Dependency] private readonly PopupSystem _popupSystem = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<MicrowaveComponent, SolutionChangedEvent>(OnSolutionChange);
SubscribeLocalEvent<MicrowaveComponent, InteractUsingEvent>(OnInteractUsing);
}
private void OnSolutionChange(EntityUid uid, MicrowaveComponent component, SolutionChangedEvent args)
@@ -28,5 +33,29 @@ namespace Content.Server.Kitchen.EntitySystems
comp.OnUpdate();
}
}
private void OnInteractUsing(EntityUid uid, MicrowaveComponent component, InteractUsingEvent args)
{
if (!component.Powered)
{
_popupSystem.PopupEntity(Loc.GetString("microwave-component-interact-using-no-power"), uid, Filter.Entities(args.User));
return;
}
if (component.Broken)
{
_popupSystem.PopupEntity(Loc.GetString("microwave-component-interact-using-broken"), uid, Filter.Entities(args.User));
return;
}
if (!HasComp<SharedItemComponent>(args.Used))
{
_popupSystem.PopupEntity(Loc.GetString("microwave-component-interact-using-transfer-fail"), uid, Filter.Entities(args.User));
return;
}
component.Storage.Insert(args.Used);
component.DirtyUi();
}
}
}

View File

@@ -1,17 +1,13 @@
using System;
using System.Collections.Generic;
using Content.Server.Tools;
using Content.Server.VendingMachines;
using Content.Shared.ActionBlocker;
using Content.Shared.Interaction;
using Content.Shared.Examine;
using Content.Shared.Tools.Components;
using Content.Shared.GameTicking;
using Robust.Server.GameObjects;
using Robust.Shared.Audio;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Player;
using Robust.Shared.Random;
using Robust.Shared.ViewVariables;
using static Content.Shared.Wires.SharedWiresComponent;
namespace Content.Server.WireHacking
@@ -33,6 +29,7 @@ namespace Content.Server.WireHacking
SubscribeLocalEvent<WiresComponent, ComponentStartup>(OnWiresStartup);
SubscribeLocalEvent<WiresComponent, MapInitEvent>(OnWiresMapInit);
SubscribeLocalEvent<WiresComponent, ExaminedEvent>(OnWiresExamine);
SubscribeLocalEvent<WiresComponent, InteractUsingEvent>(OnInteractUsing);
// Hacking DoAfters
SubscribeLocalEvent<WiresComponent, WiresComponent.WiresCutEvent>(OnWiresCut);
@@ -109,6 +106,39 @@ namespace Content.Server.WireHacking
: "wires-component-on-examine-panel-closed"));
}
private async void OnInteractUsing(EntityUid uid, WiresComponent component, InteractUsingEvent args)
{
if (!TryComp<ToolComponent?>(args.Used, out var tool))
return;
// opens the wires ui if using a tool with cutting or multitool quality on it
if (component.IsPanelOpen &&
(tool.Qualities.Contains(component.CuttingQuality) ||
tool.Qualities.Contains(component.PulsingQuality)))
{
if (TryComp(args.User, out ActorComponent? actor))
{
component.OpenInterface(actor.PlayerSession);
return;
}
}
// screws the panel open if the tool can do so
else if (await _tools.UseTool(tool.Owner, args.User, uid,
0f, WireHackingSystem.ScrewTime, component.ScrewingQuality, toolComponent:tool))
{
component.InvertPanel();
if (component.IsPanelOpen)
{
SoundSystem.Play(Filter.Pvs(uid), component.ScrewdriverOpenSound.GetSound(), uid);
}
else
{
SoundSystem.Play(Filter.Pvs(uid), component.ScrewdriverCloseSound.GetSound(), uid);
}
}
}
private void OnWiresStartup(EntityUid uid, WiresComponent component, ComponentStartup args)
{
WireLayout? layout = null;

View File

@@ -1,15 +1,10 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Threading.Tasks;
using Content.Server.DoAfter;
using Content.Server.Hands.Components;
using Content.Server.Tools;
using Content.Server.UserInterface;
using Content.Server.VendingMachines;
using Content.Shared.Interaction;
using Content.Shared.Interaction.Helpers;
using Content.Shared.Popups;
using Content.Shared.Sound;
using Content.Shared.Tools;
@@ -17,24 +12,16 @@ using Content.Shared.Tools.Components;
using Content.Shared.Wires;
using Robust.Server.GameObjects;
using Robust.Server.Player;
using Robust.Shared.Audio;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Player;
using Robust.Shared.Random;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
using Robust.Shared.ViewVariables;
namespace Content.Server.WireHacking
{
[RegisterComponent]
public sealed class WiresComponent : SharedWiresComponent, IInteractUsing
public sealed class WiresComponent : SharedWiresComponent
{
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly IEntityManager _entities = default!;
private bool _isPanelOpen;
[DataField("cuttingTime")] public float CuttingTime = 1f;
@@ -169,10 +156,10 @@ namespace Content.Server.WireHacking
[DataField("pulseSound")] public SoundSpecifier PulseSound = new SoundPathSpecifier("/Audio/Effects/multitool_pulse.ogg");
[DataField("screwdriverOpenSound")]
private SoundSpecifier _screwdriverOpenSound = new SoundPathSpecifier("/Audio/Machines/screwdriveropen.ogg");
public SoundSpecifier ScrewdriverOpenSound = new SoundPathSpecifier("/Audio/Machines/screwdriveropen.ogg");
[DataField("screwdriverCloseSound")]
private SoundSpecifier _screwdriverCloseSound = new SoundPathSpecifier("/Audio/Machines/screwdriverclose.ogg");
public SoundSpecifier ScrewdriverCloseSound = new SoundPathSpecifier("/Audio/Machines/screwdriverclose.ogg");
[ViewVariables] private BoundUserInterface? UserInterface => Owner.GetUIOrNull(WiresUiKey.Key);
@@ -500,47 +487,6 @@ namespace Content.Server.WireHacking
WireSeed));
}
async Task<bool> IInteractUsing.InteractUsing(InteractUsingEventArgs eventArgs)
{
if (!_entities.TryGetComponent<ToolComponent?>(eventArgs.Using, out var tool))
{
return false;
}
var toolSystem = EntitySystem.Get<ToolSystem>();
// opens the wires ui if using a tool with cutting or multitool quality on it
if (IsPanelOpen &&
(tool.Qualities.Contains(CuttingQuality) ||
tool.Qualities.Contains(PulsingQuality)))
{
if (_entities.TryGetComponent(eventArgs.User, out ActorComponent? actor))
{
OpenInterface(actor.PlayerSession);
return true;
}
}
// screws the panel open if the tool can do so
else if (await toolSystem.UseTool(tool.Owner, eventArgs.User, Owner,
0f, WireHackingSystem.ScrewTime, ScrewingQuality, toolComponent:tool))
{
IsPanelOpen = !IsPanelOpen;
if (IsPanelOpen)
{
SoundSystem.Play(Filter.Pvs(Owner), _screwdriverOpenSound.GetSound(), Owner);
}
else
{
SoundSystem.Play(Filter.Pvs(Owner), _screwdriverCloseSound.GetSound(), Owner);
}
return true;
}
return false;
}
public void SetStatus(object statusIdentifier, object status)
{
if (_statuses.TryGetValue(statusIdentifier, out var storedMessage))
@@ -554,5 +500,10 @@ namespace Content.Server.WireHacking
_statuses[statusIdentifier] = status;
UpdateUserInterface();
}
/// Just opens/closes the panel state in the right namespace
public void InvertPanel()
{
IsPanelOpen = !IsPanelOpen;
}
}
}

View File

@@ -1,6 +1,5 @@
ame-controller-component-interact-no-hands-text = You have no hands.
ame-controller-component-interact-using-no-hands-text = You have no hands.
ame-controller-component-interact-using-nothing-in-hands-text = You have nothing in your hand!
ame-controller-component-interact-using-already-has-jar = The controller already has a jar loaded.
ame-controller-component-interact-using-success = You insert the jar into the fuel slot.
ame-controller-component-interact-using-fail = You can't put that in the controller...
@@ -20,4 +19,4 @@ ame-window-core-count-label = Core count:
ame-window-toggle-injection-button = Toggle Injection
ame-window-eject-button = Eject
ame-window-increase-fuel-button = Increase
ame-window-decrease-fuel-button = Decrease
ame-window-decrease-fuel-button = Decrease

View File

@@ -2,7 +2,6 @@
microwave-component-interact-using-no-power = It has no power!
microwave-component-interact-using-broken = It's broken!
microwave-component-interact-using-no-active-hand = You have no active hand!
microwave-component-interact-using-container-full = Container is full
microwave-component-interact-using-transfer-success = Transferred {$amount}u
microwave-component-interact-using-transfer-fail = That won't work!