Files
jakub fda19a5200 Complete roadblocks in background and fix session regressions
Continue safe roadblock placement after admission and prison unlock, build posts incrementally, and clean up incomplete transactions. Add bounded stuck-patrol dismount recovery, defer deployment initialization during terrain takeover, reset deferred site search timing on first player arrival, and fix atlas page serialization and terrain resource lookup.

Validation: 30 native Everon posts with 120 living guards after unlock; seven affected regression suites pass; two final restart smoke rounds complete with 21 assertions and no script/runtime failures. Existing dependency asset errors remain.
2026-10-14 19:48:29 +02:00

98 lines
5.7 KiB
Python

"""Run shipped sheet geometry; no engine or multiplayer claims."""
import re
from policy_harness import ROOT, body, run
source = ROOT/'addons/core/Scripts/Game/ERR/30_Map/ERRM_SharedMapPages.c'
def adapt(signature):
text = body(source, signature)
for a,b in [('out float zoom','float& zoom'),('out int columns','int& columns'),('out int rows','int& rows'),('SCR_MapConstants.MAX_PIX_PER_METER','20.f'),('Math.Min','minf'),('Math.Max','maxf'),('Math.Ceil','ceilf'),('Math.Clamp','clampf'),('static const int','static constexpr int')]:
text=text.replace(a,b)
return re.sub(r"out (int|vector) (\w+)", r"\1& \2", text)
run(r'''
#include <array>
#include <algorithm>
#include <cassert>
#include <cmath>
using vector=std::array<float,3>;
vector Vector(float x,float y,float z){return {x,y,z};}
float minf(float a,float b){return std::min(a,b);}
float maxf(float a,float b){return std::max(a,b);}
float clampf(float a,float b,float c){return std::clamp(a,b,c);}
'''+'constexpr int COVER=16777215, OVERVIEW=16777214, REGION=16777216;\n'+adapt('static bool Layout(')+adapt('static vector Centre(')+''.join(adapt(sig) for sig in ['static bool IsRegion(', 'static int RegionColumns(', 'static int RegionRows(', 'static int RegionCount(', 'static int LastNumber(', 'static void RegionCells(', 'static int ParentRegion(', 'static float Boundary(', 'static void RegionBounds('])+adapt('static int Number(')+adapt('static int State(')+r'''
void check(vector size, vector offset){
float zoom;int cols,rows;
assert(Layout(size,.5f,zoom,cols,rows));
assert(cols>=1&&rows>=1&&cols*rows<=400);
assert(Number(COVER,cols,rows)==0&&Number(OVERVIEW,cols,rows)==1);
assert(State(0,cols,rows)==COVER&&State(1,cols,rows)==OVERVIEW);
assert(State(-1,cols,rows)==-1&&State(LastNumber(cols,rows)+1,cols,rows)==-1);
for(int n=2;n<=LastNumber(cols,rows);n++) assert(Number(State(n,cols,rows),cols,rows)==n);
assert(LastNumber(cols,rows)<1000);
for(int region=0;region<RegionCount(cols,rows);region++) {
int l,t,r,b; RegionCells(REGION+region,cols,rows,l,t,r,b);
assert(l>=0&&t>=0&&r<=cols&&b<=rows&&r>l&&b>t&&r-l<=3&&b-t<=3);
vector low,high; RegionBounds(REGION+region,cols,rows,size,zoom,low,high);
assert(low[0]>=0&&low[2]>=0&&high[0]<=1&&high[2]<=1&&high[0]>low[0]&&high[2]>low[2]);
for(int y=t;y<b;y++) for(int x=l;x<r;x++) assert(ParentRegion(x+y*4096,cols,rows)==REGION+region);
if(region%RegionColumns(cols)>0) {
vector prevLow,prevHigh;RegionBounds(REGION+region-1,cols,rows,size,zoom,prevLow,prevHigh);
assert(std::abs(prevHigh[0]-low[0])<.00001f);
}
}
float w=744/zoom,h=1024/zoom;
for(int row=0;row<rows;row++) for(int col=0;col<cols;col++) {
auto p=Centre(offset,size,zoom,cols,rows,col,row);
assert(p[0]-w/2>=offset[0]-.01f&&p[0]+w/2<=offset[0]+size[0]+.01f);
assert(p[2]-h/2>=offset[2]-.01f&&p[2]+h/2<=offset[2]+size[2]+.01f);
if(col) {
auto prev=Centre(offset,size,zoom,cols,rows,col-1,row);
assert(p[0]>prev[0]&&p[0]-prev[0]<=w*.91f);
}
if(row) {
auto prev=Centre(offset,size,zoom,cols,rows,col,row-1);
assert(p[2]<prev[2]&&prev[2]-p[2]<=h*.91f);
}
}
auto nw=Centre(offset,size,zoom,cols,rows,0,0);
auto se=Centre(offset,size,zoom,cols,rows,cols-1,rows-1);
// Every border is covered up to the explicit two-pixel rounding margin.
assert(nw[0]-w/2-offset[0]<=4.01f/zoom);
assert(offset[2]+size[2]-nw[2]-h/2<=4.01f/zoom);
assert(offset[0]+size[0]-se[0]-w/2<=4.01f/zoom);
assert(se[2]-h/2-offset[2]<=4.01f/zoom);
}
int main(){
for(auto size:{vector{15360,0,15360},vector{12800,0,12800},vector{1024,0,512},vector{32768,0,8192},vector{8192,0,32768},vector{300,0,300},vector{100000,0,100000},vector{100000,0,500}})
for(auto offset:{vector{0,0,0},vector{-1234,0,4321}}) check(size,offset);
float zoom;int cols,rows;
assert(Layout({15360,0,15360},.5f,zoom,cols,rows)&&cols==12&&rows==9&&zoom==.5f);
assert(Layout({12800,0,12800},.5f,zoom,cols,rows)&&cols==10&&rows==7);
assert(!Layout({1000000,0,100},.5f,zoom,cols,rows));
assert(!Layout({0,0,10},.5f,zoom,cols,rows));
assert(!Layout({100,0,100},0,zoom,cols,rows));
}
''')
print('PASS: shipped sheet geometry covers square, rectangular and small terrains with overlap and shifted origins; regional grids cover all detail pages with round-trip numbering; Chernarus has 12 x 9 fixed detail sheets')
component=ROOT/'addons/core/Scripts/Game/ERR/30_Map/ERRM_SharedMapComponent.c'
wire='\n'.join(body(component,sig) for sig in ('override bool RplSave(', 'override bool RplLoad('))
wire=wire.replace('override ', '').replace('ScriptBitWriter writer', 'ScriptBitWriter& writer').replace('ScriptBitReader reader','ScriptBitReader& reader').replace('super.','Native::')
run(r'''
#include <cassert>
#include <cstdint>
#include <vector>
struct ScriptBitWriter{std::vector<int32_t> data;void WriteInt(int value){data.push_back(value);}};
struct ScriptBitReader{std::vector<int32_t> data;bool ReadInt(int& value){if(data.empty())return false;value=data[0];data.erase(data.begin());return true;}};
struct Native{int saves=0,loads=0;bool RplSave(ScriptBitWriter&){saves++;return true;}bool RplLoad(ScriptBitReader&){loads++;return true;}};
struct Map:Native{int m_ESMPage=-1,m_ESMLastSelectedPage=-1;
'''+wire+r'''
};
int main(){
for(int page:{0,4097,16777214,16777215,16777216,16777227,16777615}){
Map source,target;source.m_ESMPage=page;ScriptBitWriter writer;assert(source.RplSave(writer)&&source.saves==1);
ScriptBitReader reader{writer.data};assert(target.RplLoad(reader)&&target.loads==1&&target.m_ESMPage==page&&target.m_ESMLastSelectedPage==page);
}
Map missing;ScriptBitReader empty;assert(!missing.RplLoad(empty)&&missing.loads==0&&missing.m_ESMLastSelectedPage==-1);
}
''')
print('PASS: actual map replication round-trips cover, overview, detail and regional pages, including the failing server value 16777227; truncated reads fail')