Technical Details - The Logistics Network
How the logistics network works:
All Pawns (Towers are Pawns as well as Enemies) have a ResourceContainer, which contains things references to PawnResources, which contain things like Energy/Ammunition/Health/Armor/etc. Health and Armor are treated just like any other resource in this context.
Towers can request resources via the ResourceRequester component.
The RequestResources method raises a mutable ResourceRequestEvent.
public struct ResourceRequestEvent : IEvent { public IResourceRequester Requester; public ResourceTypes Type; public int AmountRequested; public List<(ResourceProvider provider, int amount)> PendingProviders; public ResourceRequestEvent(IResourceRequester requester, ResourceTypes resourceType, int amountRequested) { Requester = requester; Type = resourceType; AmountRequested = amountRequested; PendingProviders = new List<(ResourceProvider provider, int amount)>(); } }
ResourceProviders listen for this event and pledge resource to the event by adding themselves to a list of pending providers in the eventData itself.
Because the message bus is synchronous, all providers are immediately ready in the list of pending providers. The request is then queued by the ResourceDispatcher. The Dispatcher contains two ResourceDictionaries dictionaries, AwaitingPaths and ReadyForSorting containing resource request events in various states. Both have IResourceRequester keys with ResourceEntry values. When a request is queued it's added to the AwaitingPaths dictionary
public class ResourceEntry { public List<ResourceProvider> providers; public List<Path> paths; public int amount; }
Later, in Update, the dispatcher loops through each resource provider in AwaitingPaths that has pledged resources and ensures a path is possible from the requester to the provider. It then queues the path via Pathfinding Project Pro's asynchronous path construction usage. The path construction has a callback, OnPathCalculated. When these paths are calculated, the callback updates the AwaitingPaths dictionary and adds the path to the entry's list of paths.
Later, again in Update, the dispatcher checks on these. If the number of paths is equal to the number of providers, it's no longer awaiting paths and moved to ReadyForSorting. The dispatcher then calculates the total distance from provider to requester and sorts these entries based on this distance. The Dispatcher then loops through each provider and decrements the resource request event's Amount field until the request is fulfilled. Each iteration of this loop increments an IncomingAmount field on containers to ensure they know resources are coming and not to request more.
// Loop through each entry in distances, dispatching packets and decrementing amount; breaking when none left for (int i = 0; i < distances.Count; i++) { var distanceEntry = distances[i]; var targetContainer = key.Container; // If amount is zero, this request is complete; add it to the list for removal if (distanceEntry.amount <= 0) { keysToRemove.Add(key); break; } // If target container is full, this request is considered complete; add it to the list for removal if (targetContainer.IncomingAmount + targetContainer.CurrentAmount >= targetContainer.Capacity) { keysToRemove.Add(key); break; } // Ensure only the amount needed is sent and only up to the amount the provider has int amountNeeded = math.min(distanceEntry.amount, key.Container.Capacity - key.Container.IncomingAmount - key.Container.CurrentAmount); int amountToDispatch = math.min(distanceEntry.provider.Container.CurrentAmount, amountNeeded); if (amountToDispatch == 0) continue; // Finally, choose a provider and tell it to dispatch a packet distanceEntry.provider.DispatchPacket(key.Container, distanceEntry.provider.Container.Type, amountToDispatch); // Set the incoming amount of the requesting container so it doesn't request any more resources key.Container.IncomingAmount += amountToDispatch; // Decrement remaining amount for next loop iteration distanceEntry.amount -= amountToDispatch; }
There's nothing left to do so a packet is then ordered to be dispatched by the ResourceProvider. The packet is provided the path and at the end the container gets its requested resources.
Get Hex TD
Hex TD
Roguelite tower defense game
Status | In development |
Author | JonBrant |
More posts
- 0.6 - Wave Rework22 days ago
- 0.5 - Aggressive Enemies36 days ago
- 0.43 - Boss abilities!39 days ago
- 0.42 - Juicy info41 days ago
Leave a comment
Log in with itch.io to leave a comment.