mirror of
https://github.com/exogen/t2-mapper.git
synced 2026-07-11 14:34:51 +00:00
1 line
No EOL
5.5 KiB
JavaScript
1 line
No EOL
5.5 KiB
JavaScript
import{t as e}from"./logger-B058WGzf.js";import{M as t,v as n}from"./streamHelpers-CYLk-lCT.js";var r=e(`demoTimelineScanner`),i=500,a=new Set([`msglegitkill`,`msgheadshotkill`,`msgteamkill`,`msgselfkill`,`msgexplosionkill`,`msgvehiclekill`,`msgvehiclecrash`,`msgvehiclespawnkill`,`msgturretkill`,`msgcturretkill`,`msgturretselfkill`,`msgoobkill`,`msgcampkill`,`msgrogueminekill`,`msglavakill`,`msglightningkill`]),o=new Set([`msgselfkill`,`msgturretselfkill`,`msgvehiclecrash`,`msgvehiclespawnkill`,`msgoobkill`,`msglavakill`,`msglightningkill`,`msgcampkill`]),s={msgoobkill:`Out of bounds`,msglavakill:`Killed by lava`,msglightningkill:`Struck by lightning`,msgcampkill:`Nexus camping`,msgturretselfkill:`Killed by own turret`,msgvehiclecrash:`Vehicle crash`,msgvehiclespawnkill:`Crushed by vehicle`},c={turret:`base turret`,"plasma turret":`plasma turret`,"aa turret":`AA turret`,"elf turret":`ELF turret`,"mortar turret":`mortar turret`,"missile turret":`missile turret`,"clamp turret":`indoor deployable turret`,"spike turret":`outdoor deployable turret`,"sentry turret":`sentry turret`,"shrike blaster":`Shrike`,"belly turret":`Havoc belly turret`,"bomber bomb":`bomber`,"tank chaingun":`tank chaingun`,"tank mortar":`tank mortar`,"mpb missile":`MPB missile`,forcefield:`force field`,impact:`vehicle impact`,crash:`vehicle crash`,explosion:`explosion`},l={ground:`Cratered`,mine:`Killed by own mine`,satchelcharge:`Killed by own satchel`,grenade:`Killed by own grenade`,mortar:`Killed by own mortar`,disc:`Killed by own disc`,plasma:`Killed by own plasma`,blaster:`Killed by own blaster`,missile:`Killed by own missile`,explosion:`Killed by explosion`};function u(e,t){if(e.length>=2&&e.charCodeAt(0)===1){let n=parseInt(e.slice(1),10);if(Number.isFinite(n))return t.get(n)??e}return e}function d(e,t,r){let i=u(e,r);for(let e=0;e<t.length;e++){let a=`%${e+1}`;i.includes(a)&&(i=i.replaceAll(a,n(u(t[e],r))))}return i=i.replace(/%\d+/g,``),n(i)}async function f(e,f,p,m){let h=new t(new Uint8Array(e)),{initialBlock:g}=await h.load(),_=new Map;for(let[e,t]of g.taggedStrings)_.set(e,t);let v=h.getRegistry(),y=f?n(f).trim().toLowerCase():null,b=null,x=null;for(let e=0;e<g.demoValues.length;e++){if(g.demoValues[e]!==`readplayerinfo`)continue;let t=g.demoValues[e+1];if(t?.startsWith(`1 `)){let e=t.split(` `),n=parseInt(e[1],10);Number.isFinite(n)&&(b=n);break}}if(b!=null){let e=g.demoValues,t=parseInt(e[1]===`<BLANK>`?`0`:e[1]??`0`,10)||0;for(let n=0;n<t;n++){let t=(e[2+n]??``).split(` `);if(parseInt(t[2],10)===b){let e=parseInt(t[4],10);isNaN(e)||(x=e);break}}}let S=[],C=0,w=!1,T=null,E=0,D=h.blockCount;for(;!m?.aborted;){let e;try{e=h.nextBlock()}catch(e){r.warn(`Stopping scan at block %d due to read error: %o`,E,e);break}if(!e)break;if(E++,e.type===2){C++;continue}if(e.type!==0||!e.parsed)continue;let t=e.parsed;if(!t.events)continue;let f=32/1e3*C;for(let e of t.events)try{if(!e.parsedData)continue;let t=e.parsedData.type;if(t===`NetStringEvent`){let t=e.parsedData,n=t.id,r=t.value;r!=null&&_.set(n,r);continue}let r=v.getEventParser(e.classId)?.name;if(t!==`RemoteCommandEvent`&&r!==`RemoteCommandEvent`)continue;let i=e.parsedData;if(u(i.funcName,_)!==`ServerMessage`)continue;let p=i.args;if(!p||p.length<2)continue;let m=u(p[0],_).toLowerCase();if(m===`msgclientjointeam`&&b!=null&&p.length>=6&&parseInt(u(p[4],_),10)===b){let e=parseInt(u(p[5],_),10);isNaN(e)||(x=e)}if(m===`msgmissiondropinfo`&&p.length>=3){let e=n(u(p[2],_)).trim();e&&(T=e)}if(m===`msgloadinfo`&&p.length>=4){let e=n(u(p[3],_)).trim();e&&(T=e)}if(m===`msgmissionstart`&&!w){w=!0;let e=T?` (${T})`:``;S.push({timeSec:f,type:`match-start`,description:`Match started${e}`});continue}if(m===`msggameover`){let e=T?` (${T})`:``;S.push({timeSec:f,type:`match-end`,description:`Match ended${e}`}),w=!1;continue}if(m===`msgctfflagtaken`&&p.length>=3){let e=n(u(p[2],_)).trim();if(y&&e.toLowerCase()===y){let e=p.length>=4?n(u(p[3],_)).trim():void 0;S.push({timeSec:f,type:`flag-grab`,description:`You took the ${e??`enemy`} flag`,teamAffinity:`friendly`,flagTeamName:e||void 0})}continue}if(m===`msgctfflagreturned`&&p.length>=3){let e=n(u(p[2],_)).trim();y&&e.toLowerCase()===y&&S.push({timeSec:f,type:`flag-return`,description:`You returned your flag`,teamAffinity:`friendly`});continue}if(m===`msgctfflagcapped`&&p.length>=2){let e=d(p[1],p.slice(2),_),t=p.length>=3?n(u(p[2],_)).trim():void 0,r=p.length>=4?n(u(p[3],_)).trim():void 0,i=`neutral`;if(x!=null&&x>0&&p.length>=6){let e=parseInt(u(p[5],_),10);e===x?i=`friendly`:isNaN(e)||(i=`enemy`)}S.push({timeSec:f,type:`flag-cap`,description:e||`Flag captured`,teamAffinity:i,capturer:t,flagTeamName:r||void 0});continue}if(a.has(m)&&p.length>=6){let e=n(u(p[5],_)).trim(),t=n(u(p[2],_)).trim(),r=p.length>=10?n(u(p[9],_)).trim():void 0;if(y){let n=e.toLowerCase(),i=t.toLowerCase(),a=o.has(m);if(!a&&n===y&&i!==y){let n=d(p[1],p.slice(2),_);S.push({timeSec:f,type:`kill`,description:n||`${e} got a kill`,killer:e,victim:t,weapon:r||void 0})}if(i===y)if(a){let e=s[m],t=m===`msgselfkill`&&r?l[r.toLowerCase()]:void 0;S.push({timeSec:f,type:`death`,description:e??t??`Died`,weapon:r||void 0})}else if(n!==y&&e)S.push({timeSec:f,type:`death`,description:`Killed by ${e}`,killer:e,victim:t,weapon:r||void 0});else{let e=r?.toLowerCase();S.push({timeSec:f,type:`death`,description:r?`Killed by ${c[e]??r}`:`Died`,weapon:r||void 0})}}}}catch(e){r.warn(`Skipping malformed event in block %d: %o`,E,e)}E%i===0&&(D&&p&&p(Math.min(E/D,1)),await new Promise(e=>setTimeout(e,0)))}return r.info(`Scanned %d blocks, found %d events`,E,S.length),S}export{f as scanDemoTimeline}; |