#nullable enable
using System.Collections.Generic;
using System.Linq;
using Content.Shared.Stacks;
using Robust.Shared.GameObjects;
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
using static Robust.UnitTesting.RobustIntegrationTest;
namespace Content.IntegrationTests.Tests.Interaction;
public abstract partial class InteractionTest
{
///
/// Data structure for representing a collection of s.
///
protected sealed class EntitySpecifierCollection
{
public Dictionary Entities = new();
///
/// If true, a check has been performed to see if the prototypes correspond to entity prototypes with a stack
/// component, in which case the specifier was converted into a stack-specifier
///
public bool Converted;
public EntitySpecifierCollection()
{
Converted = true;
}
public EntitySpecifierCollection(IEnumerable ents)
{
Converted = true;
foreach (var ent in ents)
{
Add(ent);
}
}
public static implicit operator EntitySpecifierCollection(string prototype)
{
var result = new EntitySpecifierCollection();
result.Add(prototype, 1);
return result;
}
public static implicit operator EntitySpecifierCollection((string, int) tuple)
{
var result = new EntitySpecifierCollection();
result.Add(tuple.Item1, tuple.Item2);
return result;
}
public void Remove(EntitySpecifier spec)
{
Add(new EntitySpecifier(spec.Prototype, -spec.Quantity, spec.Converted));
}
public void Add(EntitySpecifier spec)
{
Add(spec.Prototype, spec.Quantity, spec.Converted);
}
public void Add(string id, int quantity, bool converted = false)
{
Converted &= converted;
if (!Entities.TryGetValue(id, out var existing))
{
if (quantity != 0)
Entities.Add(id, quantity);
return;
}
var newQuantity = quantity + existing;
if (newQuantity == 0)
Entities.Remove(id);
else
Entities[id] = newQuantity;
}
public void Add(EntitySpecifierCollection collection)
{
var converted = Converted && collection.Converted;
foreach (var (id, quantity) in collection.Entities)
{
Add(id, quantity);
}
Converted = converted;
}
public void Remove(EntitySpecifierCollection collection)
{
var converted = Converted && collection.Converted;
foreach (var (id, quantity) in collection.Entities)
{
Add(id, -quantity);
}
Converted = converted;
}
public EntitySpecifierCollection Clone()
{
return new EntitySpecifierCollection()
{
Entities = Entities.ShallowClone(),
Converted = Converted
};
}
///
/// Convert applicable entity prototypes into stack prototypes.
///
public async Task ConvertToStacks(IPrototypeManager protoMan, IComponentFactory factory, ServerIntegrationInstance server)
{
if (Converted)
return;
HashSet toRemove = new();
List<(string, int)> toAdd = new();
foreach (var (id, quantity) in Entities)
{
if (protoMan.HasIndex(id))
continue;
if (!protoMan.TryIndex(id, out var entProto))
{
Assert.Fail($"Unknown prototype: {id}");
continue;
}
StackComponent? stack = null;
await server.WaitPost(() =>
{
entProto.TryGetComponent(factory.GetComponentName(), out stack);
});
if (stack == null)
continue;
toRemove.Add(id);
toAdd.Add((stack.StackTypeId, quantity));
}
foreach (var id in toRemove)
{
Entities.Remove(id);
}
foreach (var (id, quantity) in toAdd)
{
Add(id, quantity);
}
Converted = true;
}
}
protected EntitySpecifierCollection ToEntityCollection(IEnumerable entities)
{
var collection = new EntitySpecifierCollection(entities
.Select(ToEntitySpecifier)
.OfType());
Assert.That(collection.Converted);
return collection;
}
}