// Exercise the real GSC identity adapter under a small VM shim; native policy tests are separate. import assert from 'node:assert/strict'; import {readFileSync} from 'node:fs'; import vm from 'node:vm'; for (const game of ['t5','t6']) { const source=readFileSync(new URL(`../${game}/scripts/tws_${game}_moderation.gsc`,import.meta.url),'utf8'); assert.equal((source.match(/level waittill\("connected"/g)??[]).length,0,'must use the shared connection dispatcher'); assert(source.includes('register_connect_handler(::moderation_connected)')); assert(!source.includes('executeCommand'),'all effects belong to the native synchronous adapter'); const start=source.indexOf('moderation_observe(player)\n{'); const end=source.indexOf('\nmoderation_loop()',start); let body=source.slice(start,end).replace('moderation_observe(player)','function observe(player)'); body=body.replace(' guid =',' var guid =').replace(' name =',' var name ='); body=body.replace('player getGuid()','getGuid(player)').replaceAll('typeof(', 'kind(').replace('player moderationObserve(guid, name)', 'record(player,guid,name)'); const calls=[]; const c=vm.createContext({isDefined:v=>v!==null&&v!==undefined,kind:v=>typeof v==='number'?(Number.isInteger(v)?'int':'float'):typeof v, getGuid:p=>p.identity,record:(...args)=>calls.push(args)}); vm.runInContext(body,c); const player=identity=>({identity,guid:identity,name:'same name'}); c.observe(player('18446744073709551615')); assert.equal(calls.at(-1)[1],'18446744073709551615'); c.observe(player(2741626)); assert.equal(calls.at(-1)[1],'2741626'); c.observe(player('0000123')); assert.equal(calls.at(-1)[1],'0000123'); const count=calls.length; for(const value of [undefined,null,1.5,{},[]])c.observe(player(value)); assert.equal(calls.length,count); c.observe(undefined); assert.equal(calls.length,count); c.observe({...player('abc'),name:undefined}); assert.equal(calls.at(-1)[2],'Unknown player'); let loop=source.slice(source.indexOf('moderation_loop()\n{')) .replace('moderation_loop()', 'function* loop()').replaceAll(/wait ([0-9.]+);/g, 'yield $1;') .replace('players = getPlayers();', 'var players = getPlayers();').replace('for (i = 0;', 'for (var i = 0;').replace('players.size', 'players.length'); let enabled=true, configured=false, stopped=0, pumped=0, observed=0; const level={moderation_ready:false}; const runtime=vm.createContext({level,GetDvar:key=>key==='tws_moderation_enabled'?(enabled?'1':'0'):'configured',GetDvarInt:()=>1, moderationConfigure:()=>configured,moderationStop:()=>++stopped,moderationPump:()=>++pumped,getPlayers:()=>[{guid:'123'}],moderation_observe:()=>++observed}); vm.runInContext(loop,runtime); const poll=runtime.loop(); assert.equal(poll.next().value,3); assert.equal(level.moderation_ready,false); configured=true; assert.equal(poll.next().value,0.5); assert.equal(level.moderation_ready,true); assert.equal(pumped,1); assert.equal(observed,1); enabled=false; assert.equal(poll.next().value,3); assert.equal(level.moderation_ready,false); assert.equal(stopped,1); enabled=true; assert.equal(poll.next().value,0.5); assert.equal(pumped,2); console.log(`PASS ${game}: actual moderation identity, retry/disable/resume loop and shared dispatcher integration`); }