-
Notifications
You must be signed in to change notification settings - Fork 614
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Separate crate machine from market system #2681
base: master
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
using Content.Server.Power.Components; | ||
using Content.Shared._NF.CrateMachine; | ||
using Content.Shared._NF.CrateMachine.Interfaces; | ||
using AppearanceSystem = Robust.Server.GameObjects.AppearanceSystem; | ||
using CrateMachineComponent = Content.Shared._NF.CrateMachine.Components.CrateMachineComponent; | ||
|
||
namespace Content.Server._NF.CrateMachine; | ||
|
||
/// <summary> | ||
/// Handles starting the opening animation. | ||
/// Updates the time remaining on the component. | ||
/// Notifies <see cref="ICrateMachineDelegate"/>. | ||
/// </summary> | ||
public sealed partial class CrateMachineSystem: SharedCrateMachineSystem | ||
{ | ||
[Dependency] private readonly AppearanceSystem _appearanceSystem = default!; | ||
|
||
/// <summary> | ||
/// Keep track of time in this function, in order to process the animation. | ||
/// </summary> | ||
/// <param name="frameTime">The current frame time</param> | ||
public override void Update(float frameTime) | ||
{ | ||
base.Update(frameTime); | ||
|
||
var query = EntityQueryEnumerator<CrateMachineComponent, ApcPowerReceiverComponent>(); | ||
while (query.MoveNext(out var uid, out var crateMachine, out var receiver)) | ||
{ | ||
if (!receiver.Powered) | ||
continue; | ||
|
||
ProcessOpeningAnimation(uid, frameTime, crateMachine); | ||
ProcessClosingAnimation(uid, frameTime, crateMachine); | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Updates the time remaining for the opening animation, calls the delegate when the animation finishes, and updates the visual state. | ||
/// </summary> | ||
/// <param name="uid">The Uid of the crate machine</param> | ||
/// <param name="frameTime">The current frame time</param> | ||
/// <param name="comp">The crate machine component</param> | ||
private void ProcessOpeningAnimation(EntityUid uid, float frameTime, CrateMachineComponent comp) | ||
{ | ||
if (comp.OpeningTimeRemaining <= 0) | ||
return; | ||
|
||
comp.OpeningTimeRemaining -= frameTime; | ||
|
||
// Automatically start closing after it finishes open animation. | ||
if (comp.OpeningTimeRemaining <= 0) | ||
{ | ||
comp.DidTakeCrate = false; | ||
comp.Delegate?.OnCrateMachineOpened(uid, comp); | ||
} | ||
|
||
// Update at the end so the closing animation can start automatically. | ||
UpdateVisualState(uid, comp); | ||
} | ||
|
||
/// <summary> | ||
/// Updates the time remaining for the closing animation, calls the delegate when the animation finishes, and updates the visual state. | ||
/// </summary> | ||
/// <param name="uid">The Uid of the crate machine</param> | ||
/// <param name="frameTime">The current frame time</param> | ||
/// <param name="comp">The crate machine component</param> | ||
private void ProcessClosingAnimation(EntityUid uid, float frameTime, CrateMachineComponent comp) | ||
{ | ||
if (!comp.DidTakeCrate && !IsOccupied(uid, comp, true)) | ||
{ | ||
comp.DidTakeCrate = true; | ||
comp.ClosingTimeRemaining = comp.ClosingTime; | ||
comp.Delegate?.OnCrateTaken(uid, comp); | ||
} | ||
|
||
if (comp.ClosingTimeRemaining <= 0) | ||
{ | ||
comp.Delegate?.OnCrateMachineClosed(uid, comp); | ||
} | ||
|
||
comp.ClosingTimeRemaining -= frameTime; | ||
UpdateVisualState(uid, comp); | ||
} | ||
|
||
/// <summary> | ||
/// Updates the visual state of the crate machine by setting the visual state using the appearance system. | ||
/// </summary> | ||
/// <param name="uid">The Uid of the crate machine</param> | ||
/// <param name="component">The crate machine component</param> | ||
private void UpdateVisualState(EntityUid uid, CrateMachineComponent? component = null) | ||
{ | ||
if (!Resolve(uid, ref component)) | ||
return; | ||
|
||
if (component.OpeningTimeRemaining > 0) | ||
_appearanceSystem.SetData(uid, CrateMachineComponent.CrateMachineVisuals.VisualState, CrateMachineComponent.CrateMachineVisualState.Opening); | ||
else if (component.ClosingTimeRemaining > 0) | ||
_appearanceSystem.SetData(uid, CrateMachineComponent.CrateMachineVisuals.VisualState, CrateMachineComponent.CrateMachineVisualState.Closing); | ||
else if (!component.DidTakeCrate) | ||
_appearanceSystem.SetData(uid, CrateMachineComponent.CrateMachineVisuals.VisualState, CrateMachineComponent.CrateMachineVisualState.Open); | ||
else | ||
_appearanceSystem.SetData(uid, CrateMachineComponent.CrateMachineVisuals.VisualState, CrateMachineComponent.CrateMachineVisualState.Closed); | ||
} | ||
|
||
/// <summary> | ||
/// Starts the opening animation of the crate machine and calls the delegate when the animation finishes. | ||
/// </summary> | ||
/// <param name="crateMachineUid">The Uid of the crate machine</param> | ||
/// <param name="component">The crate machine component</param> | ||
/// <param name="delegate">The delegate to call when the animation finishes</param> | ||
public void OpenFor(EntityUid crateMachineUid, CrateMachineComponent component, ICrateMachineDelegate @delegate) | ||
{ | ||
component.Delegate = @delegate; | ||
component.OpeningTimeRemaining = component.OpeningTime; | ||
UpdateVisualState(crateMachineUid, component); | ||
} | ||
GreaseMonk marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,122 @@ | ||||||||||||||||||||||||||||||||
using System.Diagnostics.CodeAnalysis; | ||||||||||||||||||||||||||||||||
using System.Linq; | ||||||||||||||||||||||||||||||||
using Content.Server.Storage.EntitySystems; | ||||||||||||||||||||||||||||||||
using Content.Shared._NF.CrateMachine.Components; | ||||||||||||||||||||||||||||||||
using Content.Shared._NF.CrateMachine.Interfaces; | ||||||||||||||||||||||||||||||||
using Content.Shared.Maps; | ||||||||||||||||||||||||||||||||
using Robust.Shared.Map; | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
namespace Content.Server._NF.CrateMachine; | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
/// <summary> | ||||||||||||||||||||||||||||||||
/// The crate machine system can be used to make a crate machine open and spawn crates. | ||||||||||||||||||||||||||||||||
/// When calling <see cref="OpenFor"/>, the machine will open the door and give a callback to the given | ||||||||||||||||||||||||||||||||
/// <see cref="ICrateMachineDelegate"/> when it is done opening. | ||||||||||||||||||||||||||||||||
/// </summary> | ||||||||||||||||||||||||||||||||
public sealed partial class CrateMachineSystem | ||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Extend the shared version, add the needed import above? |
||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||
[Dependency] private readonly IEntityManager _entityManager = default!; | ||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Shouldn't need this - why isn't this extending SharedCrateMachineSystem? EntitySystem should already has a reference in EntityManager. |
||||||||||||||||||||||||||||||||
[Dependency] private readonly IMapManager _mapManager = default!; | ||||||||||||||||||||||||||||||||
[Dependency] private readonly EntityLookupSystem _lookup = default!; | ||||||||||||||||||||||||||||||||
[Dependency] private readonly EntityStorageSystem _storage = default!; | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
/// <summary> | ||||||||||||||||||||||||||||||||
/// Checks if there is a crate on the crate machine. | ||||||||||||||||||||||||||||||||
/// </summary> | ||||||||||||||||||||||||||||||||
/// <param name="crateMachineUid">The Uid of the crate machine</param> | ||||||||||||||||||||||||||||||||
/// <param name="component">The crate machine component</param> | ||||||||||||||||||||||||||||||||
/// <param name="ignoreAnimation">Ignores animation checks</param> | ||||||||||||||||||||||||||||||||
/// <returns>False if not occupied, true if it is.</returns> | ||||||||||||||||||||||||||||||||
public bool IsOccupied(EntityUid crateMachineUid, CrateMachineComponent component, bool ignoreAnimation = false) | ||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||
if (!_entityManager.TryGetComponent<TransformComponent>(crateMachineUid, out var crateMachineTransform)) | ||||||||||||||||||||||||||||||||
return true; | ||||||||||||||||||||||||||||||||
var tileRef = crateMachineTransform.Coordinates.GetTileRef(EntityManager, _mapManager); | ||||||||||||||||||||||||||||||||
if (tileRef == null) | ||||||||||||||||||||||||||||||||
return true; | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
if (!ignoreAnimation && (component.OpeningTimeRemaining > 0 || component.ClosingTimeRemaining > 0f)) | ||||||||||||||||||||||||||||||||
return true; | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
// Finally check if there is a crate intersecting the crate machine. | ||||||||||||||||||||||||||||||||
return _lookup.GetLocalEntitiesIntersecting(tileRef.Value, flags: LookupFlags.All | LookupFlags.Approximate) | ||||||||||||||||||||||||||||||||
.Any(entity => _entityManager.GetComponent<MetaDataComponent>(entity).EntityPrototype?.ID == | ||||||||||||||||||||||||||||||||
component.CratePrototype); | ||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
/// <summary> | ||||||||||||||||||||||||||||||||
/// Calculates distance between two EntityCoordinates on the same grid. | ||||||||||||||||||||||||||||||||
/// Used to check for cargo pallets around the console instead of on the grid. | ||||||||||||||||||||||||||||||||
/// </summary> | ||||||||||||||||||||||||||||||||
/// <param name="point1">the first point</param> | ||||||||||||||||||||||||||||||||
/// <param name="point2">the second point</param> | ||||||||||||||||||||||||||||||||
/// <returns></returns> | ||||||||||||||||||||||||||||||||
private static double CalculateDistance(EntityCoordinates point1, EntityCoordinates point2) | ||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||
var xDifference = point2.X - point1.X; | ||||||||||||||||||||||||||||||||
var yDifference = point2.Y - point1.Y; | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
return Math.Sqrt(xDifference * xDifference + yDifference * yDifference); | ||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
Comment on lines
+45
to
+59
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Just use Vector2.Distance. |
||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
/// <summary> | ||||||||||||||||||||||||||||||||
/// Find the nearest unoccupied crate machine, that is anchored. | ||||||||||||||||||||||||||||||||
/// </summary> | ||||||||||||||||||||||||||||||||
/// <param name="from">The Uid of the entity to find the nearest crate machine from</param> | ||||||||||||||||||||||||||||||||
/// <param name="maxDistance">The maximum distance to search for a crate machine</param> | ||||||||||||||||||||||||||||||||
/// <param name="machineUid">The Uid of the nearest unoccupied crate machine, or null if none found</param> | ||||||||||||||||||||||||||||||||
public bool FindNearestUnoccupied(EntityUid from, int maxDistance, [NotNullWhen(true)] out EntityUid? machineUid) | ||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||
machineUid = null; | ||||||||||||||||||||||||||||||||
if (maxDistance < 0) | ||||||||||||||||||||||||||||||||
return false; | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
var crateMachineQuery = AllEntityQuery<CrateMachineComponent, TransformComponent>(); | ||||||||||||||||||||||||||||||||
var consoleGridUid = Transform(from).GridUid!.Value; | ||||||||||||||||||||||||||||||||
while (crateMachineQuery.MoveNext(out var crateMachineUid, out var comp, out var compXform)) | ||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||
// Skip crate machines that aren't mounted on a grid. | ||||||||||||||||||||||||||||||||
if (Transform(crateMachineUid).GridUid == null) | ||||||||||||||||||||||||||||||||
continue; | ||||||||||||||||||||||||||||||||
// Skip crate machines that are not on the same grid. | ||||||||||||||||||||||||||||||||
if (Transform(crateMachineUid).GridUid!.Value != consoleGridUid) | ||||||||||||||||||||||||||||||||
continue; | ||||||||||||||||||||||||||||||||
var currentDistance = CalculateDistance(compXform.Coordinates, Transform(from).Coordinates); | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
var isTooFarAway = currentDistance > maxDistance; | ||||||||||||||||||||||||||||||||
Comment on lines
+83
to
+85
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Vector2 has a convenient function for this, and TransformSystem does too. I believe the snippet above should work - I also wrong a version using TransformSystem, which is even better since it'll handle weird parenting better - no false positives. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems odd to assign some conditions to variables when they're only used in an if statement but eh. |
||||||||||||||||||||||||||||||||
var isBusy = IsOccupied(crateMachineUid, comp); | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
if (!compXform.Anchored || isTooFarAway || isBusy) | ||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||
continue; | ||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
machineUid = crateMachineUid; | ||||||||||||||||||||||||||||||||
return true; | ||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
return false; | ||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
/// <summary> | ||||||||||||||||||||||||||||||||
/// Convenience function that simply spawns a crate and returns the uid. | ||||||||||||||||||||||||||||||||
/// </summary> | ||||||||||||||||||||||||||||||||
/// <param name="uid">The Uid of the crate machine</param> | ||||||||||||||||||||||||||||||||
/// <param name="component">The crate machine component</param> | ||||||||||||||||||||||||||||||||
/// <returns>The Uid of the spawned crate</returns> | ||||||||||||||||||||||||||||||||
public EntityUid SpawnCrate(EntityUid uid, CrateMachineComponent component) | ||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||
return Spawn(component.CratePrototype, Transform(uid).Coordinates); | ||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
/// <summary> | ||||||||||||||||||||||||||||||||
/// Convenience function that simply inserts a entity into the container entity and relieve the caller of | ||||||||||||||||||||||||||||||||
/// using the storage system reference. | ||||||||||||||||||||||||||||||||
/// </summary> | ||||||||||||||||||||||||||||||||
/// <param name="uid">The Uid of the crate machine</param> | ||||||||||||||||||||||||||||||||
/// <param name="container">The Uid of the container</param> | ||||||||||||||||||||||||||||||||
public void InsertIntoCrate(EntityUid uid, EntityUid container) | ||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||
_storage.Insert(uid, container); | ||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
per https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/partial-classes-and-methods:
All the parts must use the partial keyword