Local Material Silo (#36492)
* Material Silo * fix board, fix copyright * a bit of review.... for the vibe.... * a tiny bit of review * 4 spaced * sloths no good very tiny nitpick * fix ui flickers * oops * slightly lower range * Sloth Review --------- Co-authored-by: ScarKy0 <scarky0@onet.eu>
This commit is contained in:
168
Content.Shared/Materials/OreSilo/SharedOreSiloSystem.cs
Normal file
168
Content.Shared/Materials/OreSilo/SharedOreSiloSystem.cs
Normal file
@@ -0,0 +1,168 @@
|
||||
using Content.Shared.Power.EntitySystems;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Shared.Materials.OreSilo;
|
||||
|
||||
public abstract class SharedOreSiloSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SharedMaterialStorageSystem _materialStorage = default!;
|
||||
[Dependency] private readonly SharedPowerReceiverSystem _powerReceiver = default!;
|
||||
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||
|
||||
private EntityQuery<OreSiloClientComponent> _clientQuery;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<OreSiloComponent, ToggleOreSiloClientMessage>(OnToggleOreSiloClient);
|
||||
SubscribeLocalEvent<OreSiloComponent, ComponentShutdown>(OnSiloShutdown);
|
||||
Subs.BuiEvents<OreSiloComponent>(OreSiloUiKey.Key,
|
||||
subs =>
|
||||
{
|
||||
subs.Event<BoundUIOpenedEvent>(OnBoundUIOpened);
|
||||
});
|
||||
|
||||
|
||||
SubscribeLocalEvent<OreSiloClientComponent, GetStoredMaterialsEvent>(OnGetStoredMaterials);
|
||||
SubscribeLocalEvent<OreSiloClientComponent, ConsumeStoredMaterialsEvent>(OnConsumeStoredMaterials);
|
||||
SubscribeLocalEvent<OreSiloClientComponent, ComponentShutdown>(OnClientShutdown);
|
||||
|
||||
_clientQuery = GetEntityQuery<OreSiloClientComponent>();
|
||||
}
|
||||
|
||||
private void OnToggleOreSiloClient(Entity<OreSiloComponent> ent, ref ToggleOreSiloClientMessage args)
|
||||
{
|
||||
var client = GetEntity(args.Client);
|
||||
|
||||
if (!_clientQuery.TryComp(client, out var clientComp))
|
||||
return;
|
||||
|
||||
if (ent.Comp.Clients.Contains(client)) // remove client
|
||||
{
|
||||
clientComp.Silo = null;
|
||||
Dirty(client, clientComp);
|
||||
ent.Comp.Clients.Remove(client);
|
||||
Dirty(ent);
|
||||
|
||||
UpdateOreSiloUi(ent);
|
||||
}
|
||||
else // add client
|
||||
{
|
||||
if (!CanTransmitMaterials((ent, ent), client))
|
||||
return;
|
||||
|
||||
var clientMats = _materialStorage.GetStoredMaterials(client, true);
|
||||
var inverseMats = new Dictionary<string, int>();
|
||||
foreach (var (mat, amount) in clientMats)
|
||||
{
|
||||
inverseMats.Add(mat, -amount);
|
||||
}
|
||||
_materialStorage.TryChangeMaterialAmount(client, inverseMats, localOnly: true);
|
||||
_materialStorage.TryChangeMaterialAmount(ent.Owner, clientMats);
|
||||
|
||||
ent.Comp.Clients.Add(client);
|
||||
Dirty(ent);
|
||||
clientComp.Silo = ent;
|
||||
Dirty(client, clientComp);
|
||||
|
||||
UpdateOreSiloUi(ent);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnBoundUIOpened(Entity<OreSiloComponent> ent, ref BoundUIOpenedEvent args)
|
||||
{
|
||||
UpdateOreSiloUi(ent);
|
||||
}
|
||||
|
||||
private void OnSiloShutdown(Entity<OreSiloComponent> ent, ref ComponentShutdown args)
|
||||
{
|
||||
foreach (var client in ent.Comp.Clients)
|
||||
{
|
||||
if (!_clientQuery.TryComp(client, out var comp))
|
||||
continue;
|
||||
|
||||
comp.Silo = null;
|
||||
Dirty(client, comp);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void UpdateOreSiloUi(Entity<OreSiloComponent> ent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void OnGetStoredMaterials(Entity<OreSiloClientComponent> ent, ref GetStoredMaterialsEvent args)
|
||||
{
|
||||
if (args.LocalOnly)
|
||||
return;
|
||||
|
||||
if (ent.Comp.Silo is not { } silo)
|
||||
return;
|
||||
|
||||
if (!CanTransmitMaterials(silo, ent))
|
||||
return;
|
||||
|
||||
var materials = _materialStorage.GetStoredMaterials(silo);
|
||||
|
||||
foreach (var (mat, amount) in materials)
|
||||
{
|
||||
// Don't supply materials that they don't usually have access to.
|
||||
if (!_materialStorage.IsMaterialWhitelisted((args.Entity, args.Entity), mat))
|
||||
continue;
|
||||
|
||||
var existing = args.Materials.GetOrNew(mat);
|
||||
args.Materials[mat] = existing + amount;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnConsumeStoredMaterials(Entity<OreSiloClientComponent> ent, ref ConsumeStoredMaterialsEvent args)
|
||||
{
|
||||
if (args.LocalOnly)
|
||||
return;
|
||||
|
||||
if (ent.Comp.Silo is not { } silo || !TryComp<MaterialStorageComponent>(silo, out var materialStorage))
|
||||
return;
|
||||
|
||||
if (!CanTransmitMaterials(silo, ent))
|
||||
return;
|
||||
|
||||
foreach (var (mat, amount) in args.Materials)
|
||||
{
|
||||
if (!_materialStorage.TryChangeMaterialAmount(silo, mat, amount, materialStorage))
|
||||
continue;
|
||||
args.Materials[mat] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnClientShutdown(Entity<OreSiloClientComponent> ent, ref ComponentShutdown args)
|
||||
{
|
||||
if (!TryComp<OreSiloComponent>(ent.Comp.Silo, out var silo))
|
||||
return;
|
||||
|
||||
silo.Clients.Remove(ent);
|
||||
Dirty(ent.Comp.Silo.Value, silo);
|
||||
UpdateOreSiloUi((ent.Comp.Silo.Value, silo));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a given client fulfills the criteria to link/receive materials from an ore silo.
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public bool CanTransmitMaterials(Entity<OreSiloComponent?> silo, EntityUid client)
|
||||
{
|
||||
if (!Resolve(silo, ref silo.Comp))
|
||||
return false;
|
||||
|
||||
if (!_powerReceiver.IsPowered(silo.Owner))
|
||||
return false;
|
||||
|
||||
if (_transform.GetGrid(client) != _transform.GetGrid(silo.Owner))
|
||||
return false;
|
||||
|
||||
if (!_transform.InRange(silo.Owner, client, silo.Comp.Range))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user