Include the current addon, terrain integrations, tools, regression tests and recorded development evidence.
34 lines
2.6 KiB
Diff
34 lines
2.6 KiB
Diff
--- a/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryMineTransfer.c
|
|
+++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryMineTransfer.c
|
|
@@ -221,6 +221,9 @@
|
|
bool accepted = m_Source.TryMoveItemToStorage(m_Mine, m_Storage, -1, m_Callback);
|
|
if (!accepted && m_Acknowledgement != 1) return Fail("native mine move refused; exact identity remains spent");
|
|
}
|
|
+ // Native callbacks may synchronously stop this leaf or revoke its authority.
|
|
+ if (m_State != ERR_InfantryAmmoTransferState.PENDING) return m_State;
|
|
+ if (!Context()) return Fail("original mine carrier or truck authority changed during native submission");
|
|
if (m_Acknowledgement < 0) return Fail("native mine move failed; unproved custody remains quarantined");
|
|
if (m_Acknowledgement == 1 && PhysicalProof())
|
|
{
|
|
--- a/tests/test_infantry_mine_transfer.py
|
|
+++ b/tests/test_infantry_mine_transfer.py
|
|
@@ -101,6 +101,18 @@
|
|
void Move(){source.items.clear();destination.items.Insert(&incoming);from.attached=nullptr;to.attached=&incoming;inItem.slot=&to;}
|
|
};
|
|
int main(){
|
|
+ // Inline native completion cannot resurrect a cancelled transfer or bypass
|
|
+ // original authority, in either zero replacement or one-mine top-up mode.
|
|
+ for(int empty=0;empty<2;empty++)for(int loss=0;loss<5;loss++){
|
|
+ Fixture f;if(empty){f.destination.items.clear();}auto t=f.Job(empty);
|
|
+ f.source.effect=[&]{if(loss==0)t.Stop();if(loss==1)f.mode.active=false;if(loss==2)f.roster.valid=false;if(loss==3)ERR_ConvoyRules::captured=true;if(loss==4){if(empty)f.mode.hq.designated=false;else f.destination.items.clear();}f.Move();f.source.last->OnComplete();};
|
|
+ assert(t.Tick(0)==FAILED&&t.Submitted()&&!t.Unresolved()&&f.source.calls==1);
|
|
+ assert(t.Tick(1)==FAILED&&f.source.calls==1&&f.spent.Count()==1&&!f.reservation.ReleaseUnsubmitted());}
|
|
+ // A synchronous success callback without moved custody remains quarantined
|
|
+ // after cancellation; late proof settles it without resuming or refunding.
|
|
+ {Fixture f;auto t=f.Job();f.source.effect=[&]{t.Stop();f.source.last->OnComplete();};
|
|
+ assert(t.Tick(0)==FAILED&&t.Unresolved()&&f.source.calls==1);f.Move();
|
|
+ assert(!t.Unresolved()&&t.Tick(1)==FAILED&&f.source.calls==1&&f.spent.Count()==1&&!f.reservation.ReleaseUnsubmitted());}
|
|
// Authoritative designation plus an inspected empty inventory permits exactly one finite replacement.
|
|
{Fixture f;f.destination.items.clear();auto t=f.Job(true);assert(t.Tick(0)==PENDING&&t.Submitted());f.Move();f.source.last->OnComplete();assert(t.Tick(1)==SUCCEEDED&&f.destination.items.Count()==1&&f.source.calls==1);}
|
|
for(int k=0;k<7;k++){Fixture f;f.destination.items.clear();
|