Capture current mission, AI, map and administration development
Include the current addon, terrain integrations, tools, regression tests and recorded development evidence.
This commit is contained in:
@@ -128,3 +128,76 @@ int main(){
|
||||
}
|
||||
''')
|
||||
print('PASS: actual admission attempt budget bounds blocked/missing prerequisites; preparation, spent life and async pending remain protected')
|
||||
|
||||
|
||||
# Execute actual queue/retry methods as well: identities can outlive controller
|
||||
# connections. The queue adapter is deterministic; no engine scheduler is claimed.
|
||||
retry_methods = '\n'.join(body(source, signature) for signature in (
|
||||
'protected void RetryLater(', 'protected void RetrySpawn('))
|
||||
retry_methods = retry_methods.replace('protected ', '')
|
||||
retry_methods = retry_methods.replace('SCR_PlayerController.Cast(', 'Controller::Cast(')
|
||||
retry_methods = retry_methods.replace('SCR_PlayerController ', 'Controller* ')
|
||||
retry_methods = retry_methods.replace('GetGame().', 'GetGame()->')
|
||||
retry_methods = retry_methods.replace('GetPlayerManager().', 'GetPlayerManager()->')
|
||||
retry_methods = retry_methods.replace('GetCallqueue().', 'GetCallqueue()->')
|
||||
retry_methods = retry_methods.replace('CallLater(RetrySpawn,', 'CallLater(this, &Logic::RetrySpawn,')
|
||||
run(r"""
|
||||
#include <cassert>
|
||||
#include <map>
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
using UUID = int;
|
||||
struct Controller {static Controller* Cast(Controller* c){return c;}};
|
||||
struct Values {
|
||||
std::map<int,int> values;
|
||||
bool Contains(int id){return values.count(id);}
|
||||
bool Find(int id,int& value){if(!Contains(id))return false;value=values[id];return true;}
|
||||
int Get(int id){return Contains(id)?values[id]:0;}
|
||||
void Set(int id,int value){values[id]=value;}
|
||||
void Remove(int id){values.erase(id);}
|
||||
};
|
||||
struct Queue {
|
||||
std::vector<std::function<void()>> callbacks;
|
||||
template<class Owner,class Method,class... Args>
|
||||
void CallLater(Owner* owner,Method method,int delay,bool repeat,Args... args){
|
||||
assert(delay==1000&&!repeat);
|
||||
callbacks.push_back([=](){(owner->*method)(args...);});
|
||||
}
|
||||
};
|
||||
struct Manager {Controller* current=nullptr;Controller* GetPlayerController(int){return current;}};
|
||||
struct Game {Manager manager;Queue queue;Manager* GetPlayerManager(){return &manager;}Queue* GetCallqueue(){return &queue;}} game;
|
||||
Game* GetGame(){return &game;}
|
||||
struct Logic {
|
||||
Values m_Identities,m_Attempts,m_Retries;int spawns=0;
|
||||
void DoSpawn_S(int id){spawns++;m_Attempts.Set(id,m_Attempts.Get(id)+1);RetryLater(id);}
|
||||
""" + retry_methods + r"""
|
||||
};
|
||||
int main(){
|
||||
Controller original,replacement;Logic logic;
|
||||
logic.m_Identities.Set(7,100);logic.m_Attempts.Set(7,0);game.manager.current=&original;
|
||||
logic.RetryLater(7);assert(game.queue.callbacks.size()==1);
|
||||
logic.RetryLater(7);assert(game.queue.callbacks.size()==1); // duplicate still suppressed
|
||||
// Actual disconnect removes the old retry. The same account can bind that ID
|
||||
// again and enqueue a retry for its new controller before the old one fires.
|
||||
logic.m_Retries.Remove(7);game.manager.current=&replacement;
|
||||
logic.RetryLater(7);assert(game.queue.callbacks.size()==2);
|
||||
auto stale=game.queue.callbacks[0];auto current=game.queue.callbacks[1];
|
||||
stale();
|
||||
assert(logic.spawns==0&&logic.m_Attempts.Get(7)==0&&logic.m_Retries.Get(7)==100);
|
||||
current();
|
||||
assert(logic.spawns==1&&logic.m_Attempts.Get(7)==1&&game.queue.callbacks.size()==3);
|
||||
// Further stale invocations cannot drain the newly scheduled retry chain.
|
||||
for(int i=0;i<50;i++)stale();
|
||||
assert(logic.spawns==1&&logic.m_Attempts.Get(7)==1&&game.queue.callbacks.size()==3);
|
||||
auto next=game.queue.callbacks[2];next();
|
||||
assert(logic.spawns==2&&logic.m_Attempts.Get(7)==2);
|
||||
// Existing identity and cancellation guards remain effective.
|
||||
logic.m_Identities.Set(7,101);current();assert(logic.spawns==2);
|
||||
logic.m_Identities.Set(7,100);logic.m_Retries.Remove(7);current();assert(logic.spawns==2);
|
||||
// No current controller means no queued work or stranded retry entry.
|
||||
game.manager.current=nullptr;auto before=game.queue.callbacks.size();
|
||||
logic.RetryLater(7);assert(game.queue.callbacks.size()==before&&!logic.m_Retries.Contains(7));
|
||||
logic.RetrySpawn(7,100,nullptr);assert(logic.spawns==2);
|
||||
}
|
||||
""")
|
||||
print('PASS: delayed admission retry retains controller ownership across same-account recycled connection IDs')
|
||||
|
||||
Reference in New Issue
Block a user