[WIP] [Tweak] Ограничение раздатчиков реагентов и прочих жидкостей. (#498)
* Reapply "Add limited-reagent dispensers (#23907)" This reverts commit531becd592. # Conflicts: # Content.Client/Chemistry/UI/ReagentDispenserWindow.xaml.cs # Content.Server/Chemistry/EntitySystems/ReagentDispenserSystem.cs # Content.Shared/Chemistry/SharedReagentDispenser.cs # Content.Shared/Containers/ItemSlot/ItemSlotsComponent.cs # Resources/Prototypes/Catalog/ReagentDispensers/beverage.yml # Resources/Prototypes/Entities/Objects/Specific/chemical-containers.yml # Resources/Prototypes/Entities/Structures/Dispensers/chem.yml * Reapply "Fix comp.Owner (#24206)" This reverts commit2d2405ff93. * Reapply "Use old reagent dispenser beaker slot ID (#24209)" This reverts commit388424e2f3. * Add a container display to dispenser UI (#25391) * Implemented contents display for dispenser UI * Update Content.Client/Chemistry/UI/ReagentDispenserWindow.xaml.cs Co-authored-by: Nemanja <98561806+EmoGarbage404@users.noreply.github.com> * Resolve the netent into a euid first --------- Co-authored-by: Nemanja <98561806+EmoGarbage404@users.noreply.github.com> * Add prediction to hand labeler labels (#25869) Added prediction to labels * scoopable ash and foam, solution transfer prediction (#25832) * move SolutionTransfer to shared and predict as much as possible * fully move OpenableSystem to shared now that SolutionTransfer is * fix imports for everything * doc for solution transfer system * trolling * add scoopable system * make ash and foam scoopable * untroll * untroll real * make clickable it work * troll * the scooping room --------- Co-authored-by: deltanedas <@deltanedas:kde.org> Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com> # Conflicts: # Resources/Prototypes/Entities/Effects/chemistry_effects.yml * Reagent dispenser UI (#27831) * reagent dispenser: fancy window * reagent dispenser: dispense button grid * reagent dispenser: rearrange containers & info * reagent dispenser: remove `reagent-dispenser-window-container-label` * reagent dispenser: add `Scrollcontainer` on right side * reagent dispenser: get rid of pointless actions * reagent dispenser: cleanup actions and `inventory` field on bound ui state * reagent dispenser: cool reagent cards & finishing touches * reagent dispenser: final cleanup and formatting * reagent dispenser: `ButtonGrid` and `ReagentDispenserSetDispenseAmountMessage` refactor * reagent dispenser: cleanup code & address minor concerns * reagent dispenser: text in reagent cards no longer clips * reagent dispenser: oh wait i forgot to change this and thats why the builds keep failing probably * reagent dispenser mayybe this * reagent dispenser: remove `using FastAccessors;` # Conflicts: # Content.Client/Chemistry/UI/ReagentDispenserWindow.xaml.cs * Reagent dispenser UI (Again) (#27958) * reagent dispenser: fancy window * reagent dispenser: dispense button grid * reagent dispenser: rearrange containers & info * reagent dispenser: remove `reagent-dispenser-window-container-label` * reagent dispenser: add `Scrollcontainer` on right side * reagent dispenser: get rid of pointless actions * reagent dispenser: cleanup actions and `inventory` field on bound ui state * reagent dispenser: cool reagent cards & finishing touches * reagent dispenser: final cleanup and formatting * reagent dispenser: `ButtonGrid` and `ReagentDispenserSetDispenseAmountMessage` refactor * reagent dispenser: cleanup code & address minor concerns * reagent dispenser: text in reagent cards no longer clips * reagent dispenser: oh wait i forgot to change this and thats why the builds keep failing probably * reagent dispenser mayybe this * reagent dispenser: remove `using FastAccessors;` * delete unused classes * disable reagent button when container is empty * Make things a bit bigger * remove obsolete text color override * пару фиксов поверх * переводики хихиххи * еще переводы * feat: химические картриджи --------- Co-authored-by: Tayrtahn <tayrtahn@gmail.com> Co-authored-by: Nemanja <98561806+EmoGarbage404@users.noreply.github.com> Co-authored-by: deltanedas <39013340+deltanedas@users.noreply.github.com> Co-authored-by: Brandon Li <48413902+aspiringLich@users.noreply.github.com>
This commit is contained in:
@@ -1,26 +1,20 @@
|
||||
using Content.Server.Administration.Logs;
|
||||
using Content.Server.Chemistry.Components;
|
||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using Content.Server.DeviceLinking.Systems;
|
||||
using Content.Server.Nutrition.Components;
|
||||
using Content.Shared.Chemistry;
|
||||
using Content.Shared.Chemistry.Dispenser;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Shared.Containers.ItemSlots;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.DeviceLinking;
|
||||
using Content.Shared.DeviceLinking.Events;
|
||||
using Content.Shared.Emag.Components;
|
||||
using Content.Shared.Emag.Systems;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Nutrition.EntitySystems;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Server.Audio;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.Prototypes;
|
||||
using System.Linq;
|
||||
using Content.Server.Administration.Logs;
|
||||
using Content.Shared.Chemistry.Components.SolutionManager;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.Labels.Components;
|
||||
|
||||
namespace Content.Server.Chemistry.EntitySystems
|
||||
{
|
||||
@@ -33,13 +27,13 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
{
|
||||
[Dependency] private readonly AudioSystem _audioSystem = default!;
|
||||
[Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!;
|
||||
[Dependency] private readonly SolutionTransferSystem _solutionTransferSystem = default!;
|
||||
[Dependency] private readonly ItemSlotsSystem _itemSlotsSystem = default!;
|
||||
[Dependency] private readonly UserInterfaceSystem _userInterfaceSystem = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly DeviceLinkSystem _signalSystem = default!; // WD
|
||||
[Dependency] private readonly ChemMasterSystem _chemMasterSystem = default!; // WD
|
||||
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
|
||||
|
||||
[Dependency] private readonly OpenableSystem _openable = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
@@ -50,108 +44,13 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
SubscribeLocalEvent<ReagentDispenserComponent, EntRemovedFromContainerMessage>(SubscribeUpdateUiState);
|
||||
SubscribeLocalEvent<ReagentDispenserComponent, BoundUIOpenedEvent>(SubscribeUpdateUiState);
|
||||
|
||||
// WD START
|
||||
SubscribeLocalEvent<ReagentDispenserComponent, ComponentInit>(OnInit);
|
||||
SubscribeLocalEvent<ReagentDispenserComponent, MapInitEvent>(OnMapInit);
|
||||
SubscribeLocalEvent<ReagentDispenserComponent, NewLinkEvent>(OnNewLink);
|
||||
SubscribeLocalEvent<ReagentDispenserComponent, PortDisconnectedEvent>(OnPortDisconnected);
|
||||
SubscribeLocalEvent<ReagentDispenserComponent, AnchorStateChangedEvent>(OnAnchorChanged);
|
||||
// WD END
|
||||
|
||||
SubscribeLocalEvent<ReagentDispenserComponent, GotEmaggedEvent>(OnEmagged);
|
||||
|
||||
SubscribeLocalEvent<ReagentDispenserComponent, ReagentDispenserSetDispenseAmountMessage>(OnSetDispenseAmountMessage);
|
||||
SubscribeLocalEvent<ReagentDispenserComponent, ReagentDispenserDispenseReagentMessage>(OnDispenseReagentMessage);
|
||||
SubscribeLocalEvent<ReagentDispenserComponent, ReagentDispenserClearContainerSolutionMessage>(OnClearContainerSolutionMessage);
|
||||
|
||||
SubscribeLocalEvent<ReagentDispenserComponent, MapInitEvent>(OnMapInit, before: new []{typeof(ItemSlotsSystem)});
|
||||
}
|
||||
|
||||
// WD START
|
||||
private void OnInit(EntityUid uid, ReagentDispenserComponent component, ComponentInit args)
|
||||
{
|
||||
_signalSystem.EnsureSourcePorts(uid, ReagentDispenserComponent.ChemMasterPort);
|
||||
}
|
||||
|
||||
private void OnMapInit(EntityUid uid, ReagentDispenserComponent component, MapInitEvent args)
|
||||
{
|
||||
if (!TryComp<DeviceLinkSourceComponent>(uid, out var receiver))
|
||||
return;
|
||||
|
||||
foreach (var port in receiver.Outputs.Values.SelectMany(ports => ports))
|
||||
{
|
||||
if (!TryComp<ChemMasterComponent>(port, out var master))
|
||||
continue;
|
||||
|
||||
UpdateConnection(uid, port, component, master);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnNewLink(EntityUid uid, ReagentDispenserComponent component, NewLinkEvent args)
|
||||
{
|
||||
if (TryComp<ChemMasterComponent>(args.Sink, out var master) && args.SourcePort == ReagentDispenserComponent.ChemMasterPort)
|
||||
UpdateConnection(uid, args.Sink, component, master);
|
||||
}
|
||||
|
||||
private void OnPortDisconnected(EntityUid uid, ReagentDispenserComponent component, PortDisconnectedEvent args)
|
||||
{
|
||||
if (args.Port != ReagentDispenserComponent.ChemMasterPort)
|
||||
return;
|
||||
|
||||
component.ChemMaster = null;
|
||||
component.ChemMasterInRange = false;
|
||||
}
|
||||
|
||||
private void OnAnchorChanged(EntityUid uid, ReagentDispenserComponent component, ref AnchorStateChangedEvent args)
|
||||
{
|
||||
if (args.Anchored)
|
||||
RecheckConnections(uid, component);
|
||||
}
|
||||
|
||||
public void UpdateConnection(
|
||||
EntityUid dispenser,
|
||||
EntityUid chemMaster,
|
||||
ReagentDispenserComponent? dispenserComp = null,
|
||||
ChemMasterComponent? chemMasterComp = null)
|
||||
{
|
||||
if (!Resolve(dispenser, ref dispenserComp) || !Resolve(chemMaster, ref chemMasterComp))
|
||||
return;
|
||||
|
||||
if (dispenserComp.ChemMaster.HasValue && dispenserComp.ChemMaster.Value != chemMaster &&
|
||||
TryComp(dispenserComp.ChemMaster, out ChemMasterComponent? oldMaster))
|
||||
{
|
||||
oldMaster.ConnectedDispenser = null;
|
||||
}
|
||||
|
||||
if (chemMasterComp.ConnectedDispenser.HasValue && chemMasterComp.ConnectedDispenser.Value != dispenser &&
|
||||
TryComp(dispenserComp.ChemMaster, out ReagentDispenserComponent? oldDispenser))
|
||||
{
|
||||
oldDispenser.ChemMaster = null;
|
||||
oldDispenser.ChemMasterInRange = false;
|
||||
}
|
||||
|
||||
dispenserComp.ChemMaster = chemMaster;
|
||||
chemMasterComp.ConnectedDispenser = dispenser;
|
||||
|
||||
RecheckConnections(dispenser, dispenserComp);
|
||||
}
|
||||
|
||||
private void RecheckConnections(EntityUid dispenser, ReagentDispenserComponent? component = null)
|
||||
{
|
||||
if (!Resolve(dispenser, ref component))
|
||||
return;
|
||||
|
||||
if (component.ChemMaster == null)
|
||||
{
|
||||
component.ChemMasterInRange = false;
|
||||
return;
|
||||
}
|
||||
|
||||
Transform(component.ChemMaster.Value).Coordinates
|
||||
.TryDistance(EntityManager, Transform(dispenser).Coordinates, out var distance);
|
||||
component.ChemMasterInRange = distance <= 1.5f;
|
||||
}
|
||||
// WD END
|
||||
|
||||
private void SubscribeUpdateUiState<T>(Entity<ReagentDispenserComponent> ent, ref T ev)
|
||||
{
|
||||
UpdateUiState(ent);
|
||||
@@ -184,35 +83,39 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
return null;
|
||||
}
|
||||
|
||||
private List<ReagentId> GetInventory(Entity<ReagentDispenserComponent> ent)
|
||||
private List<ReagentInventoryItem> GetInventory(Entity<ReagentDispenserComponent> reagentDispenser)
|
||||
{
|
||||
var reagentDispenser = ent.Comp;
|
||||
var inventory = new List<ReagentId>();
|
||||
var inventory = new List<ReagentInventoryItem>();
|
||||
|
||||
if (reagentDispenser.PackPrototypeId is not null
|
||||
&& _prototypeManager.TryIndex(reagentDispenser.PackPrototypeId, out ReagentDispenserInventoryPrototype? packPrototype))
|
||||
for (var i = 0; i < reagentDispenser.Comp.NumSlots; i++)
|
||||
{
|
||||
inventory.AddRange(packPrototype.Inventory.Select(x => new ReagentId(x, null)));
|
||||
}
|
||||
var storageSlotId = ReagentDispenserComponent.BaseStorageSlotId + i;
|
||||
var storedContainer = _itemSlotsSystem.GetItemOrNull(reagentDispenser.Owner, storageSlotId);
|
||||
|
||||
if (HasComp<EmaggedComponent>(ent)
|
||||
&& reagentDispenser.EmagPackPrototypeId is not null
|
||||
&& _prototypeManager.TryIndex(reagentDispenser.EmagPackPrototypeId, out ReagentDispenserInventoryPrototype? emagPackPrototype))
|
||||
{
|
||||
inventory.AddRange(emagPackPrototype.Inventory.Select(x => new ReagentId(x, null)));
|
||||
// Set label from manually-applied label, or metadata if unavailable
|
||||
string reagentLabel;
|
||||
if (TryComp<LabelComponent>(storedContainer, out var label) && !string.IsNullOrEmpty(label.CurrentLabel))
|
||||
reagentLabel = label.CurrentLabel;
|
||||
else if (storedContainer != null)
|
||||
reagentLabel = Name(storedContainer.Value);
|
||||
else
|
||||
continue;
|
||||
|
||||
// Get volume remaining and color of solution
|
||||
FixedPoint2 quantity = 0f;
|
||||
var reagentColor = Color.White;
|
||||
if (storedContainer != null && _solutionContainerSystem.TryGetDrainableSolution(storedContainer.Value, out _, out var sol))
|
||||
{
|
||||
quantity = sol.Volume;
|
||||
reagentColor = sol.GetColor(_prototypeManager);
|
||||
}
|
||||
|
||||
inventory.Add(new ReagentInventoryItem(storageSlotId, reagentLabel, quantity, reagentColor));
|
||||
}
|
||||
|
||||
return inventory;
|
||||
}
|
||||
|
||||
private void OnEmagged(Entity<ReagentDispenserComponent> reagentDispenser, ref GotEmaggedEvent args)
|
||||
{
|
||||
// adding component manually to have correct state
|
||||
EntityManager.AddComponent<EmaggedComponent>(reagentDispenser);
|
||||
UpdateUiState(reagentDispenser);
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void OnSetDispenseAmountMessage(Entity<ReagentDispenserComponent> reagentDispenser, ref ReagentDispenserSetDispenseAmountMessage message)
|
||||
{
|
||||
reagentDispenser.Comp.DispenseAmount = message.ReagentDispenserDispenseAmount;
|
||||
@@ -223,33 +126,23 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
private void OnDispenseReagentMessage(Entity<ReagentDispenserComponent> reagentDispenser, ref ReagentDispenserDispenseReagentMessage message)
|
||||
{
|
||||
// Ensure that the reagent is something this reagent dispenser can dispense.
|
||||
if (!GetInventory(reagentDispenser).Contains(message.ReagentId))
|
||||
var storedContainer = _itemSlotsSystem.GetItemOrNull(reagentDispenser, message.SlotId);
|
||||
if (storedContainer == null)
|
||||
return;
|
||||
|
||||
var outputContainer = _itemSlotsSystem.GetItemOrNull(reagentDispenser, SharedReagentDispenser.OutputSlotName);
|
||||
if (outputContainer is not { Valid: true } || !_solutionContainerSystem.TryGetFitsInDispenser(outputContainer.Value, out var solution, out _))
|
||||
{
|
||||
// WD EDIT START
|
||||
var chemMasterUid = reagentDispenser.Comp.ChemMaster;
|
||||
if (!reagentDispenser.Comp.ChemMasterInRange ||
|
||||
!TryComp(chemMasterUid, out ChemMasterComponent? chemMaster) ||
|
||||
!TryComp(chemMasterUid, out SolutionContainerManagerComponent? solutionContainer) ||
|
||||
!_solutionContainerSystem.TryGetSolution((chemMasterUid.Value, solutionContainer),
|
||||
SharedChemMaster.BufferSolutionName, out var bufferSolution))
|
||||
return;
|
||||
|
||||
bufferSolution.Value.Comp.Solution.AddReagent(message.ReagentId, FixedPoint2.New((int)reagentDispenser.Comp.DispenseAmount));
|
||||
_chemMasterSystem.UpdateUiState((chemMasterUid.Value, chemMaster));
|
||||
ClickSound(reagentDispenser);
|
||||
|
||||
return;
|
||||
} // WD EDIT END
|
||||
|
||||
if (_solutionContainerSystem.TryAddReagent(solution.Value, message.ReagentId, (int) reagentDispenser.Comp.DispenseAmount, out var dispensedAmount)
|
||||
&& message.Session.AttachedEntity is not null)
|
||||
if (_solutionContainerSystem.TryGetDrainableSolution(storedContainer.Value, out var src, out _) &&
|
||||
_solutionContainerSystem.TryGetRefillableSolution(outputContainer.Value, out var dst, out _))
|
||||
{
|
||||
_adminLogger.Add(LogType.ChemicalReaction, LogImpact.Medium,
|
||||
$"{ToPrettyString(message.Session.AttachedEntity.Value):player} dispensed {dispensedAmount}u of {message.ReagentId} into {ToPrettyString(outputContainer.Value):entity}");
|
||||
// force open container, if applicable, to avoid confusing people on why it doesn't dispense
|
||||
_openable.SetOpen(storedContainer.Value, true);
|
||||
_solutionTransferSystem.Transfer(reagentDispenser,
|
||||
storedContainer.Value, src.Value,
|
||||
outputContainer.Value, dst.Value,
|
||||
(int)reagentDispenser.Comp.DispenseAmount);
|
||||
}
|
||||
|
||||
UpdateUiState(reagentDispenser);
|
||||
@@ -271,5 +164,41 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
{
|
||||
_audioSystem.PlayPvs(reagentDispenser.Comp.ClickSound, reagentDispenser, AudioParams.Default.WithVolume(-2f));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Automatically generate storage slots for all NumSlots, and fill them with their initial chemicals.
|
||||
/// The actual spawning of entities happens in ItemSlotsSystem's MapInit.
|
||||
/// </summary>
|
||||
private void OnMapInit(EntityUid uid, ReagentDispenserComponent component, MapInitEvent args)
|
||||
{
|
||||
// Get list of pre-loaded containers
|
||||
List<string> preLoad = new List<string>();
|
||||
if (component.PackPrototypeId is not null
|
||||
&& _prototypeManager.TryIndex(component.PackPrototypeId, out ReagentDispenserInventoryPrototype? packPrototype))
|
||||
{
|
||||
preLoad.AddRange(packPrototype.Inventory);
|
||||
}
|
||||
|
||||
// Populate storage slots with base storage slot whitelist
|
||||
for (var i = 0; i < component.NumSlots; i++)
|
||||
{
|
||||
var storageSlotId = ReagentDispenserComponent.BaseStorageSlotId + i;
|
||||
ItemSlot storageComponent = new();
|
||||
storageComponent.Whitelist = component.StorageWhitelist;
|
||||
storageComponent.Swap = false;
|
||||
storageComponent.EjectOnBreak = true;
|
||||
|
||||
// Check corresponding index in pre-loaded container (if exists) and set starting item
|
||||
if (i < preLoad.Count)
|
||||
storageComponent.StartingItem = preLoad[i];
|
||||
|
||||
component.StorageSlotIds.Add(storageSlotId);
|
||||
component.StorageSlots.Add(storageComponent);
|
||||
component.StorageSlots[i].Name = "Storage Slot " + (i+1);
|
||||
_itemSlotsSystem.AddItemSlot(uid, component.StorageSlotIds[i], component.StorageSlots[i]);
|
||||
}
|
||||
|
||||
_itemSlotsSystem.AddItemSlot(uid, SharedReagentDispenser.OutputSlotName, component.BeakerSlot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user