|
|
@@ -37,8 +37,8 @@ private void InitializeInteractions()
|
|
|
|
|
|
// Event handling. Add your subscriptions here! Just make sure they're all handled by EnqueueEvent.
|
|
|
SubscribeLocalEvent<ConstructionComponent, InteractUsingEvent>(EnqueueEvent,
|
|
|
- new []{typeof(AnchorableSystem), typeof(PryingSystem), typeof(WeldableSystem)},
|
|
|
- new []{typeof(EncryptionKeySystem)});
|
|
|
+ new[] { typeof(AnchorableSystem), typeof(PryingSystem), typeof(WeldableSystem) },
|
|
|
+ new[] { typeof(EncryptionKeySystem) });
|
|
|
SubscribeLocalEvent<ConstructionComponent, OnTemperatureChangeEvent>(EnqueueEvent);
|
|
|
SubscribeLocalEvent<ConstructionComponent, PartAssemblyPartInsertedEvent>(EnqueueEvent);
|
|
|
}
|
|
|
@@ -56,13 +56,13 @@ private HandleResult HandleEvent(EntityUid uid, object ev, bool validation, Cons
|
|
|
return HandleResult.False;
|
|
|
|
|
|
// If the state machine is in an invalid state (not on a valid node) we can't do anything, ever.
|
|
|
- if (GetCurrentNode(uid, construction) is not {} node)
|
|
|
+ if (GetCurrentNode(uid, construction) is not { } node)
|
|
|
{
|
|
|
return HandleResult.False;
|
|
|
}
|
|
|
|
|
|
// If we're currently in an edge, we'll let the edge handle or validate the interaction.
|
|
|
- if (GetCurrentEdge(uid, construction) is {} edge)
|
|
|
+ if (GetCurrentEdge(uid, construction) is { } edge)
|
|
|
{
|
|
|
var result = HandleEdge(uid, ev, edge, validation, construction);
|
|
|
|
|
|
@@ -258,166 +258,166 @@ private HandleResult HandleInteraction(EntityUid uid, object ev, ConstructionGra
|
|
|
// Note: Please use braces for your new case, it's convenient.
|
|
|
|
|
|
case EntityInsertConstructionGraphStep insertStep:
|
|
|
- {
|
|
|
- // EntityInsert steps only work with InteractUsing!
|
|
|
- if (ev is not InteractUsingEvent interactUsing)
|
|
|
- break;
|
|
|
-
|
|
|
- // TODO: Sanity checks.
|
|
|
+ {
|
|
|
+ // EntityInsert steps only work with InteractUsing!
|
|
|
+ if (ev is not InteractUsingEvent interactUsing)
|
|
|
+ break;
|
|
|
|
|
|
- user = interactUsing.User;
|
|
|
+ // TODO: Sanity checks.
|
|
|
|
|
|
- var insert = interactUsing.Used;
|
|
|
+ user = interactUsing.User;
|
|
|
|
|
|
- // Since many things inherit this step, we delegate the "is this entity valid?" logic to them.
|
|
|
- // While this is very OOP and I find it icky, I must admit that it simplifies the code here a lot.
|
|
|
- if(!insertStep.EntityValid(insert, EntityManager, _factory))
|
|
|
- return HandleResult.False;
|
|
|
+ var insert = interactUsing.Used;
|
|
|
|
|
|
- // If we're only testing whether this step would be handled by the given event, then we're done.
|
|
|
- if (validation)
|
|
|
- return HandleResult.Validated;
|
|
|
+ // Since many things inherit this step, we delegate the "is this entity valid?" logic to them.
|
|
|
+ // While this is very OOP and I find it icky, I must admit that it simplifies the code here a lot.
|
|
|
+ if (!insertStep.EntityValid(insert, EntityManager, _factory))
|
|
|
+ return HandleResult.False;
|
|
|
|
|
|
- // If we still haven't completed this step's DoAfter...
|
|
|
- if (doAfterState == DoAfterState.None && insertStep.DoAfter > 0)
|
|
|
- {
|
|
|
- var doAfterEv = new ConstructionInteractDoAfterEvent(EntityManager, interactUsing);
|
|
|
+ // If we're only testing whether this step would be handled by the given event, then we're done.
|
|
|
+ if (validation)
|
|
|
+ return HandleResult.Validated;
|
|
|
|
|
|
- var doAfterEventArgs = new DoAfterArgs(EntityManager, interactUsing.User, step.DoAfter, doAfterEv, uid, uid, interactUsing.Used)
|
|
|
+ // If we still haven't completed this step's DoAfter...
|
|
|
+ if (doAfterState == DoAfterState.None && insertStep.DoAfter > 0)
|
|
|
{
|
|
|
- BreakOnDamage = false,
|
|
|
- BreakOnMove = true,
|
|
|
- NeedHand = true,
|
|
|
- };
|
|
|
+ var doAfterEv = new ConstructionInteractDoAfterEvent(EntityManager, interactUsing);
|
|
|
|
|
|
- var started = _doAfterSystem.TryStartDoAfter(doAfterEventArgs);
|
|
|
+ var doAfterEventArgs = new DoAfterArgs(EntityManager, interactUsing.User, step.DoAfter, doAfterEv, uid, uid, interactUsing.Used)
|
|
|
+ {
|
|
|
+ BreakOnDamage = false,
|
|
|
+ BreakOnMove = true,
|
|
|
+ NeedHand = true,
|
|
|
+ };
|
|
|
|
|
|
- if (!started)
|
|
|
- return HandleResult.False;
|
|
|
+ var started = _doAfterSystem.TryStartDoAfter(doAfterEventArgs);
|
|
|
+
|
|
|
+ if (!started)
|
|
|
+ return HandleResult.False;
|
|
|
|
|
|
#if DEBUG
|
|
|
- // Verify that the resulting DoAfter event will be handled by the current construction state.
|
|
|
- // if it can't what is even the point of raising this DoAfter?
|
|
|
- doAfterEv.DoAfter = new(default, doAfterEventArgs, default);
|
|
|
- var result = HandleInteraction(uid, doAfterEv, step, validation: true, out _, construction);
|
|
|
- DebugTools.Assert(result == HandleResult.Validated);
|
|
|
+ // Verify that the resulting DoAfter event will be handled by the current construction state.
|
|
|
+ // if it can't what is even the point of raising this DoAfter?
|
|
|
+ doAfterEv.DoAfter = new(default, doAfterEventArgs, default);
|
|
|
+ var result = HandleInteraction(uid, doAfterEv, step, validation: true, out _, construction);
|
|
|
+ DebugTools.Assert(result == HandleResult.Validated);
|
|
|
#endif
|
|
|
- return HandleResult.DoAfter;
|
|
|
- }
|
|
|
+ return HandleResult.DoAfter;
|
|
|
+ }
|
|
|
|
|
|
- // Material steps, which use stacks, are handled specially. Instead of inserting the whole item,
|
|
|
- // we split the stack in two and insert the split stack.
|
|
|
- if (insertStep is MaterialConstructionGraphStep materialInsertStep)
|
|
|
- {
|
|
|
- if (_stackSystem.Split(insert, materialInsertStep.Amount, Transform(interactUsing.User).Coordinates) is not {} stack)
|
|
|
- return HandleResult.False;
|
|
|
+ // Material steps, which use stacks, are handled specially. Instead of inserting the whole item,
|
|
|
+ // we split the stack in two and insert the split stack.
|
|
|
+ if (insertStep is MaterialConstructionGraphStep materialInsertStep)
|
|
|
+ {
|
|
|
+ if (_stackSystem.Split(insert, materialInsertStep.Amount, Transform(interactUsing.User).Coordinates) is not { } stack)
|
|
|
+ return HandleResult.False;
|
|
|
|
|
|
- insert = stack;
|
|
|
- }
|
|
|
+ insert = stack;
|
|
|
+ }
|
|
|
|
|
|
- // Container-storage handling.
|
|
|
- if (!string.IsNullOrEmpty(insertStep.Store))
|
|
|
- {
|
|
|
- // In the case we want to store this item in a container on the entity...
|
|
|
- var store = insertStep.Store;
|
|
|
+ // Container-storage handling.
|
|
|
+ if (!string.IsNullOrEmpty(insertStep.Store))
|
|
|
+ {
|
|
|
+ // In the case we want to store this item in a container on the entity...
|
|
|
+ var store = insertStep.Store;
|
|
|
|
|
|
- // Add this container to the collection of "construction-owned" containers.
|
|
|
- // Containers in that set will be transferred to new entities in the case of a prototype change.
|
|
|
- construction.Containers.Add(store);
|
|
|
+ // Add this container to the collection of "construction-owned" containers.
|
|
|
+ // Containers in that set will be transferred to new entities in the case of a prototype change.
|
|
|
+ construction.Containers.Add(store);
|
|
|
|
|
|
- // The container doesn't necessarily need to exist, so we ensure it.
|
|
|
- _container.Insert(insert, _container.EnsureContainer<Container>(uid, store));
|
|
|
+ // The container doesn't necessarily need to exist, so we ensure it.
|
|
|
+ _container.Insert(insert, _container.EnsureContainer<Container>(uid, store));
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // If we don't store the item in a container on the entity, we just delete it right away.
|
|
|
+ Del(insert);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Step has been handled correctly, so we signal this.
|
|
|
+ return HandleResult.True;
|
|
|
}
|
|
|
- else
|
|
|
+
|
|
|
+ case ToolConstructionGraphStep toolInsertStep:
|
|
|
{
|
|
|
- // If we don't store the item in a container on the entity, we just delete it right away.
|
|
|
- Del(insert);
|
|
|
- }
|
|
|
+ if (ev is not InteractUsingEvent interactUsing)
|
|
|
+ break;
|
|
|
|
|
|
- // Step has been handled correctly, so we signal this.
|
|
|
- return HandleResult.True;
|
|
|
- }
|
|
|
+ // TODO: Sanity checks.
|
|
|
|
|
|
- case ToolConstructionGraphStep toolInsertStep:
|
|
|
- {
|
|
|
- if (ev is not InteractUsingEvent interactUsing)
|
|
|
- break;
|
|
|
+ user = interactUsing.User;
|
|
|
|
|
|
- // TODO: Sanity checks.
|
|
|
+ // If we're validating whether this event handles the step...
|
|
|
+ if (validation)
|
|
|
+ {
|
|
|
+ // Then we only really need to check whether the tool entity has that quality or not.
|
|
|
+ return _toolSystem.HasQuality(interactUsing.Used, toolInsertStep.Tool)
|
|
|
+ ? HandleResult.Validated
|
|
|
+ : HandleResult.False;
|
|
|
+ }
|
|
|
|
|
|
- user = interactUsing.User;
|
|
|
+ // If we're handling an event after its DoAfter finished...
|
|
|
+ if (doAfterState == DoAfterState.Completed)
|
|
|
+ return HandleResult.True;
|
|
|
+
|
|
|
+ var result = _toolSystem.UseTool(
|
|
|
+ interactUsing.Used,
|
|
|
+ interactUsing.User,
|
|
|
+ uid,
|
|
|
+ TimeSpan.FromSeconds(toolInsertStep.DoAfter),
|
|
|
+ new[] { toolInsertStep.Tool },
|
|
|
+ new ConstructionInteractDoAfterEvent(EntityManager, interactUsing),
|
|
|
+ out var doAfter,
|
|
|
+ toolInsertStep.Fuel);
|
|
|
+
|
|
|
+ return result && doAfter != null ? HandleResult.DoAfter : HandleResult.False;
|
|
|
+ }
|
|
|
|
|
|
- // If we're validating whether this event handles the step...
|
|
|
- if (validation)
|
|
|
+ case TemperatureConstructionGraphStep temperatureChangeStep:
|
|
|
{
|
|
|
- // Then we only really need to check whether the tool entity has that quality or not.
|
|
|
- return _toolSystem.HasQuality(interactUsing.Used, toolInsertStep.Tool)
|
|
|
- ? HandleResult.Validated
|
|
|
- : HandleResult.False;
|
|
|
- }
|
|
|
+ if (ev is not OnTemperatureChangeEvent)
|
|
|
+ break;
|
|
|
|
|
|
- // If we're handling an event after its DoAfter finished...
|
|
|
- if (doAfterState == DoAfterState.Completed)
|
|
|
- return HandleResult.True;
|
|
|
-
|
|
|
- var result = _toolSystem.UseTool(
|
|
|
- interactUsing.Used,
|
|
|
- interactUsing.User,
|
|
|
- uid,
|
|
|
- TimeSpan.FromSeconds(toolInsertStep.DoAfter),
|
|
|
- new [] { toolInsertStep.Tool },
|
|
|
- new ConstructionInteractDoAfterEvent(EntityManager, interactUsing),
|
|
|
- out var doAfter,
|
|
|
- toolInsertStep.Fuel);
|
|
|
-
|
|
|
- return result && doAfter != null ? HandleResult.DoAfter : HandleResult.False;
|
|
|
- }
|
|
|
+ // Some things, like microwaves, might need to block the temperature construction step from kicking in, or override it entirely.
|
|
|
+ var tempEvent = new OnConstructionTemperatureEvent();
|
|
|
+ RaiseLocalEvent(uid, tempEvent, true);
|
|
|
|
|
|
- case TemperatureConstructionGraphStep temperatureChangeStep:
|
|
|
- {
|
|
|
- if (ev is not OnTemperatureChangeEvent)
|
|
|
- break;
|
|
|
+ if (tempEvent.Result is not null)
|
|
|
+ return tempEvent.Result.Value;
|
|
|
|
|
|
- // Some things, like microwaves, might need to block the temperature construction step from kicking in, or override it entirely.
|
|
|
- var tempEvent = new OnConstructionTemperatureEvent();
|
|
|
- RaiseLocalEvent(uid, tempEvent, true);
|
|
|
+ // prefer using InternalTemperature since that's more accurate for cooking.
|
|
|
+ float temp;
|
|
|
+ if (TryComp<InternalTemperatureComponent>(uid, out var internalTemp))
|
|
|
+ {
|
|
|
+ temp = internalTemp.Temperature;
|
|
|
+ }
|
|
|
+ else if (TryComp<TemperatureComponent>(uid, out var tempComp))
|
|
|
+ {
|
|
|
+ temp = tempComp.CurrentTemperature;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ return HandleResult.False;
|
|
|
+ }
|
|
|
|
|
|
- if (tempEvent.Result is not null)
|
|
|
- return tempEvent.Result.Value;
|
|
|
+ if ((!temperatureChangeStep.MinTemperature.HasValue || temp >= temperatureChangeStep.MinTemperature.Value) &&
|
|
|
+ (!temperatureChangeStep.MaxTemperature.HasValue || temp <= temperatureChangeStep.MaxTemperature.Value))
|
|
|
+ {
|
|
|
+ return HandleResult.True;
|
|
|
+ }
|
|
|
|
|
|
- // prefer using InternalTemperature since that's more accurate for cooking.
|
|
|
- float temp;
|
|
|
- if (TryComp<InternalTemperatureComponent>(uid, out var internalTemp))
|
|
|
- {
|
|
|
- temp = internalTemp.Temperature;
|
|
|
- }
|
|
|
- else if (TryComp<TemperatureComponent>(uid, out var tempComp))
|
|
|
- {
|
|
|
- temp = tempComp.CurrentTemperature;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
return HandleResult.False;
|
|
|
}
|
|
|
|
|
|
- if ((!temperatureChangeStep.MinTemperature.HasValue || temp >= temperatureChangeStep.MinTemperature.Value) &&
|
|
|
- (!temperatureChangeStep.MaxTemperature.HasValue || temp <= temperatureChangeStep.MaxTemperature.Value))
|
|
|
- {
|
|
|
- return HandleResult.True;
|
|
|
- }
|
|
|
-
|
|
|
- return HandleResult.False;
|
|
|
- }
|
|
|
-
|
|
|
case PartAssemblyConstructionGraphStep partAssemblyStep:
|
|
|
- {
|
|
|
- if (ev is not PartAssemblyPartInsertedEvent)
|
|
|
- break;
|
|
|
+ {
|
|
|
+ if (ev is not PartAssemblyPartInsertedEvent)
|
|
|
+ break;
|
|
|
|
|
|
- if (partAssemblyStep.Condition(uid, EntityManager))
|
|
|
- return HandleResult.True;
|
|
|
- return HandleResult.False;
|
|
|
- }
|
|
|
+ if (partAssemblyStep.Condition(uid, EntityManager))
|
|
|
+ return HandleResult.True;
|
|
|
+ return HandleResult.False;
|
|
|
+ }
|
|
|
|
|
|
#endregion
|
|
|
// --- CONSTRUCTION STEP EVENT HANDLING FINISH ---
|