Add interaction tests (#15251)

This commit is contained in:
Leon Friedrich
2023-04-15 07:41:25 +12:00
committed by GitHub
parent ffe946729f
commit 489660a6bb
36 changed files with 2354 additions and 32 deletions

View File

@@ -13,6 +13,7 @@ namespace Content.Server.Construction.Completions
{
[DataField("container")] public string Container { get; private set; } = string.Empty;
// TODO use or generalize ConstructionSystem.ChangeEntity();
public void PerformAction(EntityUid uid, EntityUid? userUid, IEntityManager entityManager)
{
if (!entityManager.TryGetComponent(uid, out ContainerManagerComponent? containerManager))
@@ -62,8 +63,12 @@ namespace Content.Server.Construction.Completions
// We only add this container. If some construction needs to take other containers into account, fix this.
entityManager.EntitySysManager.GetEntitySystem<ConstructionSystem>().AddContainer(computer, Container);
var entChangeEv = new ConstructionChangeEntityEvent(computer, uid);
entityManager.EventBus.RaiseLocalEvent(uid, entChangeEv);
entityManager.EventBus.RaiseLocalEvent(computer, entChangeEv, broadcast: true);
// Delete the original entity.
entityManager.DeleteEntity(uid);
entityManager.QueueDeleteEntity(uid);
}
}
}

View File

@@ -12,6 +12,7 @@ namespace Content.Server.Construction.Completions
[DataDefinition]
public sealed class BuildMachine : IGraphAction
{
// TODO use or generalize ConstructionSystem.ChangeEntity();
public void PerformAction(EntityUid uid, EntityUid? userUid, IEntityManager entityManager)
{
if (!entityManager.TryGetComponent(uid, out ContainerManagerComponent? containerManager))
@@ -102,7 +103,10 @@ namespace Content.Server.Construction.Completions
constructionSystem.RefreshParts(machineComp);
}
entityManager.DeleteEntity(uid);
var entChangeEv = new ConstructionChangeEntityEvent(machine, uid);
entityManager.EventBus.RaiseLocalEvent(uid, entChangeEv);
entityManager.EventBus.RaiseLocalEvent(machine, entChangeEv, broadcast: true);
entityManager.QueueDeleteEntity(uid);
}
}
}

View File

@@ -23,6 +23,7 @@ public sealed class BuildMech : IGraphAction
[DataField("container")]
public string Container = "battery-container";
// TODO use or generalize ConstructionSystem.ChangeEntity();
public void PerformAction(EntityUid uid, EntityUid? userUid, IEntityManager entityManager)
{
if (!entityManager.TryGetComponent(uid, out ContainerManagerComponent? containerManager))
@@ -64,8 +65,10 @@ public sealed class BuildMech : IGraphAction
mechComp.BatterySlot.Insert(cell);
}
// Delete the original entity.
entityManager.DeleteEntity(uid);
var entChangeEv = new ConstructionChangeEntityEvent(mech, uid);
entityManager.EventBus.RaiseLocalEvent(uid, entChangeEv);
entityManager.EventBus.RaiseLocalEvent(mech, entChangeEv, broadcast: true);
entityManager.QueueDeleteEntity(uid);
}
}

View File

@@ -352,6 +352,10 @@ namespace Content.Server.Construction
}
}
var entChangeEv = new ConstructionChangeEntityEvent(newUid, uid);
RaiseLocalEvent(uid, entChangeEv);
RaiseLocalEvent(newUid, entChangeEv, broadcast: true);
QueueDel(uid);
return newUid;
@@ -384,4 +388,20 @@ namespace Content.Server.Construction
return ChangeNode(uid, userUid, nodeId, performActions, construction);
}
}
/// <summary>
/// This event gets raised when an entity changes prototype / uid during construction. The event is raised
/// directed both at the old and new entity.
/// </summary>
public sealed class ConstructionChangeEntityEvent : EntityEventArgs
{
public readonly EntityUid New;
public readonly EntityUid Old;
public ConstructionChangeEntityEvent(EntityUid newUid, EntityUid oldUid)
{
New = newUid;
Old = oldUid;
}
}
}

View File

@@ -169,6 +169,8 @@ namespace Content.Server.Construction
if (!materialStep.EntityValid(entity, out var stack))
continue;
// TODO allow taking from several stacks.
// Also update crafting steps to check if it works.
var splitStack = _stackSystem.Split(entity, materialStep.Amount, user.ToCoordinates(0, 0), stack);
if (splitStack == null)
@@ -288,43 +290,49 @@ namespace Content.Server.Construction
return newEntity;
}
// LEGACY CODE. See warning at the top of the file!
private async void HandleStartItemConstruction(TryStartItemConstructionMessage ev, EntitySessionEventArgs args)
{
if (!_prototypeManager.TryIndex(ev.PrototypeName, out ConstructionPrototype? constructionPrototype))
if (args.SenderSession.AttachedEntity is {Valid: true} user)
await TryStartItemConstruction(ev.PrototypeName, user);
}
// LEGACY CODE. See warning at the top of the file!
public async Task<bool> TryStartItemConstruction(string prototype, EntityUid user)
{
if (!_prototypeManager.TryIndex(prototype, out ConstructionPrototype? constructionPrototype))
{
_sawmill.Error($"Tried to start construction of invalid recipe '{ev.PrototypeName}'!");
return;
_sawmill.Error($"Tried to start construction of invalid recipe '{prototype}'!");
return false;
}
if (!_prototypeManager.TryIndex(constructionPrototype.Graph,
out ConstructionGraphPrototype? constructionGraph))
{
_sawmill.Error(
$"Invalid construction graph '{constructionPrototype.Graph}' in recipe '{ev.PrototypeName}'!");
return;
$"Invalid construction graph '{constructionPrototype.Graph}' in recipe '{prototype}'!");
return false;
}
var startNode = constructionGraph.Nodes[constructionPrototype.StartNode];
var targetNode = constructionGraph.Nodes[constructionPrototype.TargetNode];
var pathFind = constructionGraph.Path(startNode.Name, targetNode.Name);
if (args.SenderSession.AttachedEntity is not {Valid: true} user || !_actionBlocker.CanInteract(user, null))
return;
if (!_actionBlocker.CanInteract(user, null))
return false;
if (!HasComp<HandsComponent>(user))
return;
return false;
foreach (var condition in constructionPrototype.Conditions)
{
if (!condition.Condition(user, user.ToCoordinates(0, 0), Direction.South))
return;
return false;
}
if (pathFind == null)
{
throw new InvalidDataException(
$"Can't find path from starting node to target node in construction! Recipe: {ev.PrototypeName}");
$"Can't find path from starting node to target node in construction! Recipe: {prototype}");
}
var edge = startNode.GetEdge(pathFind[0].Name);
@@ -332,7 +340,7 @@ namespace Content.Server.Construction
if (edge == null)
{
throw new InvalidDataException(
$"Can't find edge from starting node to the next node in pathfinding! Recipe: {ev.PrototypeName}");
$"Can't find edge from starting node to the next node in pathfinding! Recipe: {prototype}");
}
// No support for conditions here!
@@ -347,11 +355,12 @@ namespace Content.Server.Construction
}
if (await Construct(user, "item_construction", constructionGraph, edge, targetNode) is not { Valid: true } item)
return;
return false;
// Just in case this is a stack, attempt to merge it. If it isn't a stack, this will just normally pick up
// or drop the item as normal.
_stackSystem.TryMergeToHands(item, user);
return true;
}
// LEGACY CODE. See warning at the top of the file!
@@ -490,7 +499,7 @@ namespace Content.Server.Construction
xform.LocalRotation = constructionPrototype.CanRotate ? ev.Angle : Angle.Zero;
xform.Anchored = wasAnchored;
RaiseNetworkEvent(new AckStructureConstructionMessage(ev.Ack));
RaiseNetworkEvent(new AckStructureConstructionMessage(ev.Ack, structure));
_adminLogger.Add(LogType.Construction, LogImpact.Low, $"{ToPrettyString(user):player} has turned a {ev.PrototypeName} construction ghost into {ToPrettyString(structure)} at {Transform(structure).Coordinates}");
Cleanup();
}

View File

@@ -59,6 +59,14 @@ public sealed partial class ConstructionSystem
args.Verbs.Add(verb);
}
public List<MachinePartComponent> GetAllParts(EntityUid uid, MachineComponent? component = null)
{
if (!Resolve(uid, ref component))
return new List<MachinePartComponent>();
return GetAllParts(component);
}
public List<MachinePartComponent> GetAllParts(MachineComponent component)
{
var parts = new List<MachinePartComponent>();