d
This commit is contained in:
parent
c3a6f5ff37
commit
4c4e767ec6
73 changed files with 3502 additions and 741 deletions
|
|
@ -15,8 +15,8 @@ assert(functionSource('inventoryEntries').includes('personalEconomyMode()')&&fun
|
|||
assert(serverSource.includes(".add('POST','/api/player/purchase',handlePurchase)")&&serverSource.includes('assertPlayerCanAfford')&&!serverSource.includes("'/api/player/place-field'"),'Player purchase validation is missing or retired field-placement API remains');
|
||||
assert(realtimeSource.includes("message.type === 'reaction'")&&realtimeSource.includes('REACTION_MIN_INTERVAL_MS')&&!realtimeSource.includes('broadcastFieldEffect'),'Realtime reaction throttling is missing or field broadcasts remain');
|
||||
|
||||
const port=24000+Math.floor(Math.random()*8000),dataDir=fs.mkdtempSync(path.join(os.tmpdir(),'bend-field-complete-'));
|
||||
const child=spawn(process.execPath,[path.join(root,'server.js')],{env:{...process.env,PORT:String(port),HOST:'127.0.0.1',BEND_FIELD_DATA_DIR:dataDir},stdio:['ignore','pipe','pipe']});
|
||||
const port=24000+Math.floor(Math.random()*8000),dataDir=fs.mkdtempSync(path.join(os.tmpdir(),'link-field-complete-')),worldDir=path.join(dataDir,'world');
|
||||
const child=spawn(process.execPath,[path.join(root,'server.js')],{env:{...process.env,PORT:String(port),HOST:'127.0.0.1',LINK_FIELD_TEST_DATA_ROOT:dataDir},stdio:['ignore','pipe','pipe']});
|
||||
let stderr='',aliceWs=null,bobWs=null;child.stderr.on('data',chunk=>stderr+=chunk);
|
||||
const base=`http://127.0.0.1:${port}`,sleep=ms=>new Promise(resolve=>setTimeout(resolve,ms));
|
||||
async function request(url,options={}){const response=await fetch(base+url,options),body=await response.json();return{response,body}}
|
||||
|
|
@ -30,14 +30,14 @@ function solvedState(puzzle){return{paths:puzzle.solution.map(route=>({startGate
|
|||
const alice=(await request('/api/cloud/session',{method:'POST',headers:{'content-type':'application/json'},body:JSON.stringify({name:'Alice'})})).body;
|
||||
const bob=(await request('/api/cloud/session',{method:'POST',headers:{'content-type':'application/json'},body:JSON.stringify({name:'Bob'})})).body;
|
||||
const puzzle=starterPuzzle(),route=[[0,1],[0,0],[1,0],[2,0],[3,0],[4,0],[4,1],[3,1],[2,1],[1,1],[1,2],[0,2],[0,3],[0,4],[1,4],[1,3],[2,3],[2,4],[3,4],[4,4],[4,3],[3,3],[3,2],[4,2]];
|
||||
puzzle.g=[[0,1,'N'],[4,2,'S']];puzzle.n=[[0,0,10]];puzzle.valid=route.map(cell=>[...cell]);puzzle.obstacles=[[2,2]];puzzle.solution=[{startGate:0,endGate:1,cells:route.map(cell=>[...cell])}];puzzle.specialCells={crossings:[],warps:[],locks:[],internalGates:[]};puzzle.maxTurns=10;puzzle.totalTurns=10;
|
||||
puzzle.g=[[0,1,'N'],[4,2,'S']];puzzle.n=[[0,0,16]];puzzle.valid=route.map(cell=>[...cell]);puzzle.obstacles=[[2,2]];puzzle.solution=[{startGate:0,endGate:1,cells:route.map(cell=>[...cell])}];puzzle.specialCells={crossings:[],warps:[],locks:[],internalGates:[]};puzzle.maxTurns=16;puzzle.totalTurns=16;
|
||||
const b0=boardMeta('B0',0,15,puzzle);
|
||||
let pushed=await request('/api/cloud/push',{method:'POST',headers:auth(alice),body:JSON.stringify({baseRevision:0,global:{schema:31,appVersion:'47.70',generatorVersion:5,worldGeneration:'v47-field-reset-20260728-interaction-fix',nextId:1},metas:[b0],states:[{id:'B0',value:{paths:[],solved:false,rev:1,revAuthor:'alice'}}],deleted:[]})});assert.equal(pushed.response.status,200);
|
||||
let pushed=await request('/api/cloud/push',{method:'POST',headers:auth(alice),body:JSON.stringify({baseRevision:0,global:{schema:31,appVersion:'47.70',generatorVersion:5,worldGeneration:'linkfield-single-world-20260801',nextId:1},metas:[b0],states:[{id:'B0',value:{paths:[],solved:false,rev:1,revAuthor:'alice'}}],deleted:[]})});assert.equal(pushed.response.status,200);
|
||||
aliceWs=await connectRealtime(base,alice);bobWs=await connectRealtime(base,bob);aliceWs.send({type:'viewport',minX:-8,minY:-8,maxX:8,maxY:8});bobWs.send({type:'viewport',minX:-8,minY:-8,maxX:8,maxY:8});await aliceWs.waitFor('snapshot');await bobWs.waitFor('snapshot');
|
||||
aliceWs.send({type:'reaction',id:'reaction-one',emoji:'🎉',x:.4,y:.6});const reaction=await bobWs.waitFor(message=>message.type==='reaction'&&message.reaction?.id==='reaction-one');assert.equal(reaction.reaction.emoji,'🎉');assert.equal(reaction.reaction.playerName,'Alice');assert(reaction.reaction.expiresAt>reaction.reaction.createdAt);
|
||||
aliceWs.send({type:'reaction',id:'reaction-one',emoji:'🤩',style:'laser',x:.4,y:.6});const reaction=await bobWs.waitFor(message=>message.type==='reaction'&&message.reaction?.id==='reaction-one');assert.equal(reaction.reaction.emoji,'🤩');assert.equal(reaction.reaction.style,'laser');assert.equal(reaction.reaction.playerName,'Alice');assert(reaction.reaction.expiresAt>reaction.reaction.createdAt);
|
||||
aliceWs.send({type:'claim',requestId:'claim-b0',boardId:'B0'});assert.equal((await aliceWs.waitFor(message=>message.type==='claim-result'&&message.requestId==='claim-b0')).ok,true);
|
||||
pushed=await request('/api/cloud/push',{method:'POST',headers:auth(alice),body:JSON.stringify({baseRevision:1,global:{nextId:1},metas:[],states:[{id:'B0',value:solvedState(puzzle)}],deleted:[]})});assert.equal(pushed.response.status,200);let revision=pushed.body.revision;
|
||||
const alicePath=path.join(dataDir,`${alice.playerId}.json`),aliceRecord=JSON.parse(fs.readFileSync(alicePath,'utf8'));aliceRecord.earnedScore=250000;fs.writeFileSync(alicePath,JSON.stringify(aliceRecord));
|
||||
const alicePath=path.join(worldDir,`${alice.playerId}.json`),aliceRecord=JSON.parse(fs.readFileSync(alicePath,'utf8'));aliceRecord.earnedScore=250000;fs.writeFileSync(alicePath,JSON.stringify(aliceRecord));
|
||||
const [renamed,purchase]=await Promise.all([
|
||||
request('/api/cloud/profile',{method:'POST',headers:auth(alice),body:JSON.stringify({name:'Alice Concurrent'})}),
|
||||
request('/api/player/purchase',{method:'POST',headers:auth(alice),body:JSON.stringify({boardId:'B0',itemId:'score-lens'})})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue