class ERR_MortarCourierCallback : ScriptedInventoryOperationCallback { ERR_MortarCourierTransfer Transfer; protected override void OnComplete() { if (Transfer) Transfer.Acknowledge(true); } protected override void OnFailed() { if (Transfer) Transfer.Acknowledge(false); } } // One exact native move belonging to one courier trip. Never retries ambiguous work. class ERR_MortarCourierTransfer { protected ERR_MortarLogistics m_Service; protected IEntity m_Shell; protected IEntity m_From; protected IEntity m_To; protected InventoryStorageManagerComponent m_Source; protected InventoryStorageManagerComponent m_Destination; protected BaseInventoryStorageComponent m_Storage; protected ref ERR_MortarCourierCallback m_Callback; protected int m_Trip; protected int m_Acknowledgement; protected float m_Deadline; protected bool m_Accepted; protected bool m_Invalidated; protected bool m_Resolved; void ERR_MortarCourierTransfer(ERR_MortarLogistics service, int trip, IEntity shell, IEntity from, IEntity to, BaseInventoryStorageComponent storage, float now) { m_Service = service; m_Trip = trip; m_Shell = shell; m_From = from; m_To = to; m_Storage = storage; m_Deadline = now + 8000; m_Source = InventoryStorageManagerComponent.Cast(from.FindComponent(InventoryStorageManagerComponent)); m_Destination = InventoryStorageManagerComponent.Cast(to.FindComponent(InventoryStorageManagerComponent)); } static bool Proven(bool complete, bool source, bool destination, bool exact) { return complete && !source && destination && exact; } protected bool Contains(InventoryStorageManagerComponent inventory) { if (!inventory || !m_Shell) return false; array items = {}; ERR_Inventory.Items(inventory, items); return items.Contains(m_Shell); } void Acknowledge(bool success) { if (m_Acknowledgement != 0) return; if (success) m_Acknowledgement = 1; else m_Acknowledgement = -1; } bool Begin(float now) { if (m_Callback || !Replication.IsServer() || !m_Service.TransferAllowed(m_Trip, m_Shell, m_From, m_To, now) || !Contains(m_Source) || Contains(m_Destination)) return false; m_Callback = new ERR_MortarCourierCallback(); m_Callback.Transfer = this; m_Accepted = m_Source.TryMoveItemToStorage(m_Shell, m_Storage, -1, m_Callback); if (!m_Accepted) { Acknowledge(false); m_Resolved = true; } return m_Accepted; } void Invalidate() { m_Invalidated = true; } bool Unresolved() { return m_Accepted && !m_Resolved; } IEntity Shell() { return m_Shell; } int Poll(float now) { // A deleted exact entity cannot complete later; close as a permanent loss. if (!m_Shell) { m_Resolved = true; m_Invalidated = true; return -1; } bool exact; InventoryItemComponent item; if (m_Shell) item = InventoryItemComponent.Cast(m_Shell.FindComponent(InventoryItemComponent)); if (item && item.GetParentSlot()) exact = item.GetParentSlot().GetStorage() == m_Storage; bool proven = Proven(m_Acknowledgement == 1, Contains(m_Source), Contains(m_Destination), exact); if (proven || m_Acknowledgement < 0) m_Resolved = true; if (m_Invalidated || now >= m_Deadline || !m_Service.TransferAllowed(m_Trip, m_Shell, m_From, m_To, now)) { m_Invalidated = true; return -1; } if (proven) return 1; if (m_Acknowledgement < 0 || !m_Accepted) return -1; return 0; } }