Add interaction tests (#15251)
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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>();
|
||||
|
||||
Reference in New Issue
Block a user