Built and signed on GitHub ActionsBuilt and signed on GitHub Actions
Built and signed on GitHub Actions
latest
NeKzor/sdpWorks with
•JSR Score70%•This package works with Cloudflare Workers, Node.js, Deno, Bun, Browsers




Downloads4/wk
•Publisheda year ago (0.10.1)
Simple Source Engine demo parser. 🔧
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976// Copyright (c) 2023-2024, NeKz // SPDX-License-Identifier: MIT import type { SourceDemoBuffer } from '../buffer.ts'; import type { SourceDemo } from '../demo.ts'; import type { QAngle } from './QAngle.ts'; import type { Vector } from './Vector.ts'; export class UserMessage { type: number; constructor(type: number) { this.type = type; } getType(): number { return this.type; } getName(): string { return this.constructor.name; } read(_buf: SourceDemoBuffer, _demo: SourceDemo) { throw new Error(`read() for ${this.constructor.name} not implemented!`); } write(_buf: SourceDemoBuffer, _demo: SourceDemo) { throw new Error(`write() for ${this.constructor.name} not implemented!`); } as<T extends UserMessage>(): T { return this as unknown as T; } } export class Geiger extends UserMessage { geigerRange?: number; override read(buf: SourceDemoBuffer) { this.geigerRange = buf.readUint8(); } override write(buf: SourceDemoBuffer) { buf.writeUint8(this.geigerRange!); } } export class Train extends UserMessage { pos?: number; override read(buf: SourceDemoBuffer) { this.pos = buf.readUint8(); } override write(buf: SourceDemoBuffer) { buf.writeUint8(this.pos!); } } export class HudText extends UserMessage { text?: string; override read(buf: SourceDemoBuffer) { this.text = buf.readASCIIString(); } override write(buf: SourceDemoBuffer) { buf.writeASCIIString(this.text!); } } export class SayText extends UserMessage { client?: number; text?: string; wantsToChat?: number; override read(buf: SourceDemoBuffer) { this.client = buf.readUint8(); this.text = buf.readASCIIString(); this.wantsToChat = buf.readUint8(); } override write(buf: SourceDemoBuffer) { buf.writeUint8(this.client!); buf.writeASCIIString(this.text!); buf.writeUint8(this.wantsToChat!); } } export class SayText2 extends UserMessage { client?: number; text?: string; wantsToChat?: number; messageText?: string; messages?: [string, string, string, string]; override read(buf: SourceDemoBuffer) { this.client = buf.readUint8(); this.text = buf.readASCIIString(); this.wantsToChat = buf.readUint8(); this.messageText = buf.readASCIIString(); this.messages = [ buf.readASCIIString(), buf.readASCIIString(), buf.readASCIIString(), buf.readASCIIString(), ]; } override write(buf: SourceDemoBuffer) { buf.writeUint8(this.client!); buf.writeASCIIString(this.text!); buf.writeUint8(this.wantsToChat!); buf.writeASCIIString(this.messageText!); for (const message of this.messages!.values()) { buf.writeASCIIString(message); } } } export enum HudPrint { Notify = 1, Console = 2, Talk = 3, Center = 4, } export class TextMsg extends UserMessage { msgDest?: HudPrint; output?: [string, string, string, string, string]; override read(buf: SourceDemoBuffer) { this.msgDest = buf.readUint8(); this.output = ['', '', '', '', '']; for (let i = 0; i < 5; ++i) { this.output[i] = buf.readASCIIString(); } } override write(buf: SourceDemoBuffer) { buf.writeUint8(this.msgDest!); for (const str of this.output!.values() ?? []) { buf.writeASCIIString(str); } } } export interface HudTextParms { x: number; y: number; effect: number; r1: number; g1: number; b1: number; a1: number; r2: number; g2: number; b2: number; a2: number; fadeinTime: number; fadeoutTime: number; holdTime: number; fxTime: number; channel: number; } export class HudMsg extends UserMessage { textParms?: HudTextParms; message?: string; override read(buf: SourceDemoBuffer) { this.textParms = { channel: buf.readUint8(), x: buf.readFloat32(), y: buf.readFloat32(), r1: buf.readUint8(), g1: buf.readUint8(), b1: buf.readUint8(), a1: buf.readUint8(), r2: buf.readUint8(), g2: buf.readUint8(), b2: buf.readUint8(), a2: buf.readUint8(), effect: buf.readFloat32(), fadeinTime: buf.readFloat32(), fadeoutTime: buf.readFloat32(), holdTime: buf.readFloat32(), fxTime: buf.readFloat32(), }; this.message = buf.readASCIIString(); } override write(buf: SourceDemoBuffer) { buf.writeUint8(this.textParms!.channel); buf.writeFloat32(this.textParms!.x); buf.writeFloat32(this.textParms!.y); buf.writeUint8(this.textParms!.r1); buf.writeUint8(this.textParms!.g1); buf.writeUint8(this.textParms!.b1); buf.writeUint8(this.textParms!.a1); buf.writeUint8(this.textParms!.r2); buf.writeUint8(this.textParms!.g2); buf.writeUint8(this.textParms!.b2); buf.writeUint8(this.textParms!.a2); buf.writeFloat32(this.textParms!.effect); buf.writeFloat32(this.textParms!.fadeinTime); buf.writeFloat32(this.textParms!.fadeoutTime); buf.writeFloat32(this.textParms!.holdTime); buf.writeFloat32(this.textParms!.fxTime); buf.writeASCIIString(this.message!); } } export class ResetHUD extends UserMessage { reset?: number; override read(buf: SourceDemoBuffer) { this.reset = buf.readUint8(); } override write(buf: SourceDemoBuffer) { buf.writeUint8(this.reset!); } } export class GameTitle extends UserMessage { override read(_buf: SourceDemoBuffer) {} override write(_buf: SourceDemoBuffer) {} } export class ItemPickup extends UserMessage { name?: string; override read(buf: SourceDemoBuffer) { this.name = buf.readASCIIString(); } override write(buf: SourceDemoBuffer) { buf.writeASCIIString(this.name!); } } // NOTE: Unused export class ShowMenu extends UserMessage { override read(_buf: SourceDemoBuffer) {} override write(_buf: SourceDemoBuffer) {} } export enum ShakeCommand { Start = 0, Stop = 1, Amplitude = 2, Frequency = 3, StartRumbleOnly = 4, StartNoRumble = 5, } export class Shake extends UserMessage { command?: ShakeCommand; amplitude?: number; frequency?: number; duration?: number; override read(buf: SourceDemoBuffer) { this.command = buf.readUint8(); this.amplitude = buf.readFloat32(); this.frequency = buf.readFloat32(); this.duration = buf.readFloat32(); } override write(buf: SourceDemoBuffer) { buf.writeUint8(this.command!); buf.writeFloat32(this.amplitude!); buf.writeFloat32(this.frequency!); buf.writeFloat32(this.duration!); } } export class Tilt extends UserMessage { command?: number; easeInOut?: number; angle?: QAngle; duration?: number; time?: number; override read(buf: SourceDemoBuffer) { this.command = buf.readUint8(); this.easeInOut = buf.readUint8(); this.angle = buf.readQAngle(); this.duration = buf.readFloat32(); this.time = buf.readFloat32(); } override write(buf: SourceDemoBuffer) { buf.writeUint8(this.command!); buf.writeUint8(this.easeInOut!); buf.writeQAngle(this.angle!); buf.writeFloat32(this.duration!); buf.writeFloat32(this.time!); } } export class Fade extends UserMessage { duration?: number; holdTime?: number; fadeFlags?: number; fade?: { r: number; g: number; b: number; a: number }; override read(buf: SourceDemoBuffer) { this.duration = buf.readUint16(); this.holdTime = buf.readUint16(); this.fadeFlags = buf.readUint16(); this.fade = { r: buf.readUint8(), g: buf.readUint8(), b: buf.readUint8(), a: buf.readUint8(), }; } override write(buf: SourceDemoBuffer) { buf.writeUint16(this.duration!); buf.writeUint16(this.holdTime!); buf.writeUint16(this.fadeFlags!); buf.writeUint8(this.fade!.r); buf.writeUint8(this.fade!.g); buf.writeUint8(this.fade!.b); buf.writeUint8(this.fade!.a); } } export class VGUIMenu extends UserMessage { name?: string; show?: number; size?: number; keyValues?: { key: string; value: string }[]; override read(buf: SourceDemoBuffer) { this.name = buf.readASCIIString(); this.show = buf.readUint8(); this.size = buf.readUint8(); this.keyValues = []; for (let i = 0; i < this.size; ++i) { this.keyValues.push({ key: buf.readASCIIString(), value: buf.readASCIIString(), }); } } override write(buf: SourceDemoBuffer) { buf.writeASCIIString(this.name!); buf.writeUint8(this.show!); buf.writeUint8(this.size!); this.keyValues!.forEach(({ key, value }) => { buf.writeASCIIString(key); buf.writeASCIIString(value); }); } } export class Rumble extends UserMessage { index?: number; data?: number; flags?: number; override read(buf: SourceDemoBuffer) { this.index = buf.readUint8(); this.data = buf.readUint8(); this.flags = buf.readUint8(); } override write(buf: SourceDemoBuffer) { buf.writeUint8(this.index!); buf.writeUint8(this.data!); buf.writeUint8(this.flags!); } } export class Battery extends UserMessage { battery?: number; override read(buf: SourceDemoBuffer) { this.battery = buf.readUint16(); } override write(buf: SourceDemoBuffer) { buf.writeUint16(this.battery!); } } // NOTE: Unused export class Damage extends UserMessage { override read(_buf: SourceDemoBuffer) {} override write(_buf: SourceDemoBuffer) {} } export class VoiceMask extends UserMessage { audiblePlayers?: [number, number]; serverBannedPlayers?: [number, number]; serverModEnabled?: number; override read(buf: SourceDemoBuffer) { const VOICE_MAX_PLAYERS_DW = 2; this.audiblePlayers = [0, 0]; this.serverBannedPlayers = [0, 0]; for (let index = 0; index < VOICE_MAX_PLAYERS_DW; ++index) { this.audiblePlayers[index] = buf.readUint32(); this.serverBannedPlayers[index] = buf.readUint32(); } this.serverModEnabled = buf.readUint8(); } override write(buf: SourceDemoBuffer) { const VOICE_MAX_PLAYERS_DW = 2; for (let index = 0; index < VOICE_MAX_PLAYERS_DW; ++index) { buf.writeUint32(this.audiblePlayers![index]!); buf.writeUint32(this.serverBannedPlayers![index]!); } buf.writeUint8(this.serverModEnabled!); } } export class RequestState extends UserMessage { override read(_buf: SourceDemoBuffer) {} override write(_buf: SourceDemoBuffer) {} } export class CloseCaption extends UserMessage { hash?: number; duration?: number; fromPlayer?: boolean; override read(buf: SourceDemoBuffer) { this.hash = buf.readUint32(); this.duration = buf.readBits(15, false); this.fromPlayer = buf.readBoolean(); } override write(buf: SourceDemoBuffer) { buf.writeUint32(this.hash!); buf.writeBits(this.duration!, 15); buf.writeBoolean(this.fromPlayer!); } } export class CloseCaptionDirect extends UserMessage { hash?: number; duration?: number; fromPlayer?: boolean; override read(buf: SourceDemoBuffer) { this.hash = buf.readUint32(); this.duration = buf.readBits(15, false); this.fromPlayer = buf.readBoolean(); } override write(buf: SourceDemoBuffer) { buf.writeUint32(this.hash!); buf.writeBits(this.duration!, 15); buf.writeBoolean(this.fromPlayer!); } } export class HintText extends UserMessage { hintString?: string; override read(buf: SourceDemoBuffer) { this.hintString = buf.readASCIIString(); } override write(buf: SourceDemoBuffer) { buf.writeASCIIString(this.hintString!); } } export class KeyHintText extends UserMessage { messages?: 1; message?: string; override read(buf: SourceDemoBuffer) { this.messages = buf.readUint8() as 1; this.message = buf.readASCIIString(); } override write(buf: SourceDemoBuffer) { buf.writeUint8(this.messages!); buf.writeASCIIString(this.message!); } } // NOTE: Unused export class SquadMemberDied extends UserMessage { override read(_buf: SourceDemoBuffer) {} override write(_buf: SourceDemoBuffer) {} } // NOTE: Unused export class AmmoDenied extends UserMessage { ammo?: number; override read(_buf: SourceDemoBuffer) { // this.ammo = buf.readUint16(); } override write(_buf: SourceDemoBuffer) { // buf.writeUint16(this.ammo); } } export enum CreditsType { Logo = 1, Intro = 2, Outro = 3, } export class CreditsMsg extends UserMessage { creditsType?: CreditsType; override read(buf: SourceDemoBuffer) { this.creditsType = buf.readUint8(); } override write(buf: SourceDemoBuffer) { buf.writeUint8(this.creditsType!); } } export class LogoTimeMsg extends UserMessage { time?: number; override read(buf: SourceDemoBuffer) { this.time = buf.readFloat32(); } override write(buf: SourceDemoBuffer) { buf.writeFloat32(this.time!); } } // NOTE: Unused export class AchievementEvent extends UserMessage { achievementId?: number; override read(_buf: SourceDemoBuffer) { // this.achievementId = buf.readUint16(); } override write(_buf: SourceDemoBuffer) { // buf.writeUint16(this.achievementId); } } export class UpdateJalopyRadar extends UserMessage { override read(_buf: SourceDemoBuffer) {} override write(_buf: SourceDemoBuffer) {} } export class CurrentTimescale extends UserMessage { override read(_buf: SourceDemoBuffer) {} override write(_buf: SourceDemoBuffer) {} } export enum GameTimescaleInterpolators { Linear = 0, Accel = 1, DeAccel = 2, EaseInOut = 3, } export class DesiredTimescale extends UserMessage { desiredTimescale?: number; durationRealTimeSeconds?: number; interpolationType?: GameTimescaleInterpolators; startBlendTime?: number; override read(buf: SourceDemoBuffer) { this.desiredTimescale = buf.readFloat32(); this.durationRealTimeSeconds = buf.readFloat32(); this.interpolationType = buf.readUint8(); this.startBlendTime = buf.readFloat32(); } override write(buf: SourceDemoBuffer) { buf.writeFloat32(this.desiredTimescale!); buf.writeFloat32(this.durationRealTimeSeconds!); buf.writeUint8(this.interpolationType!); buf.writeFloat32(this.startBlendTime!); } } export enum PortalCreditsType { Logo = 1, Intro = 2, Outro = 3, OutroPortal = 4, } export class CreditsPortalMsg extends UserMessage { creditsType?: PortalCreditsType; override read(buf: SourceDemoBuffer) { this.creditsType = buf.readUint8(); } override write(buf: SourceDemoBuffer) { buf.writeUint8(this.creditsType!); } } // NOTE: Unused export class InventoryFlash extends UserMessage { override read(_buf: SourceDemoBuffer) {} override write(_buf: SourceDemoBuffer) {} } // NOTE: Unused export class IndicatorFlash extends UserMessage { override read(_buf: SourceDemoBuffer) {} override write(_buf: SourceDemoBuffer) {} } // NOTE: Unused export class ControlHelperAnimate extends UserMessage { override read(_buf: SourceDemoBuffer) {} override write(_buf: SourceDemoBuffer) {} } // NOTE: Unused export class TakePhoto extends UserMessage { override read(_buf: SourceDemoBuffer) {} override write(_buf: SourceDemoBuffer) {} } // NOTE: Unused export class Flash extends UserMessage { override read(_buf: SourceDemoBuffer) {} override write(_buf: SourceDemoBuffer) {} } export class HudPingIndicator extends UserMessage { position?: Vector; override read(buf: SourceDemoBuffer) { this.position = buf.readVector(); } override write(buf: SourceDemoBuffer) { buf.writeVector(this.position!); } } // NOTE: Unused export class OpenRadialMenu extends UserMessage { override read(_buf: SourceDemoBuffer) {} override write(_buf: SourceDemoBuffer) {} } // TODO export class AddLocator extends UserMessage { playerIndex?: number; entityHandle?: number; displayTime?: number; position?: Vector; normal?: Vector; iconName?: string; override read(_buf: SourceDemoBuffer) { // this.playerIndex = buf.readUint16(); // this.entityHandle = buf.readUint32(); // this.displayTime = buf.readFloat32(); // this.position = buf.readVectorCoord(); // this.normal = buf.readVector(); // this.iconName = buf.readASCIIString(); } override write(_buf: SourceDemoBuffer) { // buf.writeUint16(this.playerIndex!); // buf.writeUint32(this.entityHandle!); // buf.writeFloat32(this.displayTime!); // buf.writeVectorCoord(this.position!); // buf.writeVector(this.normal!); // buf.writeASCIIString(this.iconName!); } } export class MPMapCompleted extends UserMessage { branch?: number; level?: number; override read(buf: SourceDemoBuffer) { this.branch = buf.readUint8(); this.level = buf.readUint8(); } override write(buf: SourceDemoBuffer) { buf.writeUint8(this.branch!); buf.writeUint8(this.level!); } } export class MPMapIncomplete extends UserMessage { branch?: number; level?: number; override read(buf: SourceDemoBuffer) { this.branch = buf.readUint8(); this.level = buf.readUint8(); } override write(buf: SourceDemoBuffer) { buf.writeUint8(this.branch!); buf.writeUint8(this.level!); } } // TODO export class MPMapCompletedData extends UserMessage { levelCompletions?: boolean[][][]; override read(_buf: SourceDemoBuffer) { // const MAX_PORTAL2_COOP_BRANCHES = 6; // const MAX_PORTAL2_COOP_LEVELS_PER_BRANCH = 16; // const numBits = 2 * MAX_PORTAL2_COOP_BRANCHES * MAX_PORTAL2_COOP_LEVELS_PER_BRANCH; // const buffer = buf.readArrayBuffer(numBits / 8); // let current = 0; // let mask = 0x01; // this.levelCompletions = []; // for (let player = 0; player < 2; ++player) { // this.levelCompletions[player] = []; // for (let branch = 0; branch < MAX_PORTAL2_COOP_BRANCHES; ++branch) { // this.levelCompletions[player]![branch] = []; // for (let level = 0; level < MAX_PORTAL2_COOP_LEVELS_PER_BRANCH; ++level) { // if ((buffer.at(current)! & mask) !== 0) { // this.levelCompletions![player]![branch]![level] = true; // } // mask <<= 1; // if (mask > 0x100) { // ++current; // mask = 0x01; // } // } // } // } } override write(_buf: SourceDemoBuffer) { // const MAX_PORTAL2_COOP_BRANCHES = 6; // const MAX_PORTAL2_COOP_LEVELS_PER_BRANCH = 16; // const numBits = 2 * MAX_PORTAL2_COOP_BRANCHES * MAX_PORTAL2_COOP_LEVELS_PER_BRANCH; // const buffer = new Uint8Array(8 + numBits / 8); // let current = 0; // let mask = 0x01; // this.levelCompletions = []; // for (let player = 0; player < 2; ++player) { // this.levelCompletions[player] = []; // for (let branch = 0; branch < MAX_PORTAL2_COOP_BRANCHES; ++branch) { // this.levelCompletions[player]![branch] = []; // for (let level = 0; level < MAX_PORTAL2_COOP_LEVELS_PER_BRANCH; ++level) { // const completed = this.levelCompletions![player]![branch]![level]; // buffer.set(new Uint8Array([completed ? mask : 0x00]), current); // mask <<= 1; // if (mask > 0x100) { // ++current; // mask = 0x01; // } // } // } // } // buf.writeArrayBuffer(buffer, buffer.byteLength); } } export class MPTauntEarned extends UserMessage { taunt?: string; awardSilently?: boolean; override read(buf: SourceDemoBuffer) { this.taunt = buf.readASCIIString(); this.awardSilently = buf.readBoolean(); } override write(buf: SourceDemoBuffer) { buf.writeASCIIString(this.taunt!); buf.writeBoolean(this.awardSilently!); } } export class MPTauntUnlocked extends UserMessage { taunt?: string; override read(buf: SourceDemoBuffer) { this.taunt = buf.readASCIIString(); } override write(buf: SourceDemoBuffer) { buf.writeASCIIString(this.taunt!); } } export class MPTauntLocked extends UserMessage { taunt?: string; override read(buf: SourceDemoBuffer) { this.taunt = buf.readASCIIString(); } override write(buf: SourceDemoBuffer) { buf.writeASCIIString(this.taunt!); } } export class MPAllTauntsLocked extends UserMessage { override read(_buf: SourceDemoBuffer) {} override write(_buf: SourceDemoBuffer) {} } export enum PortalFizzleType { Success = 0, CantFit = 1, OverlappedLinked = 2, BadVolume = 3, BadSurface = 4, Killed = 5, Cleanser = 6, Close = 7, NearBlue = 8, NearRed = 9, None = 10, } // TODO: vector coord is incorrect :> export class PortalFX_Surface extends UserMessage { entIndex?: number; playerEntIndex?: number; team?: number; portalNum?: number; effect?: PortalFizzleType; vecOrigin?: Vector; angles?: QAngle; override read(_buf: SourceDemoBuffer) { // this.entIndex = buf.readInt16(); // this.playerEntIndex = buf.readInt16(); // this.team = buf.readInt8(); // this.portalNum = buf.readInt8(); // this.effect = buf.readInt8(); // this.vecOrigin = buf.readVectorCoord(); // this.angles = buf.readAngles(); } override write(_buf: SourceDemoBuffer) { // buf.writeInt16(this.entIndex!); // buf.writeInt16(this.playerEntIndex!); // buf.writeInt8(this.team!); // buf.writeInt8(this.portalNum!); // buf.writeInt8(this.effect!); // buf.writeVectorCoord(this.vecOrigin!); // buf.writeAngles(this.angles!); } } // TODO export class PaintWorld extends UserMessage { unk1?: number; unk2?: number; unk3?: number; unk4?: number; unk5?: number; override read(_buf: SourceDemoBuffer) { // this.unk1 = buf.readUint8(); // this.unk2 = buf.readUint32(); // this.unk3 = buf.readFloat32(); // this.unk4 = buf.readFloat32(); // this.unk5 = buf.readUint8(); } override write(_buf: SourceDemoBuffer) { // buf.writeUint8(this.unk1!); // buf.writeUint32(this.unk2!); // buf.writeFloat32(this.unk3!); // buf.writeFloat32(this.unk4!); // buf.writeUint8(this.unk5!); } } // TODO export class PaintEntity extends UserMessage { unk1?: number; unk2?: number; unk3?: number; unk4?: number; unk5?: number; override read(_buf: SourceDemoBuffer) { // this.unk1 = buf.readUint32(); // this.unk2 = buf.readUint8(); // this.unk3 = buf.readFloat32(); // this.unk4 = buf.readFloat32(); // this.unk5 = buf.readFloat32(); } override write(_buf: SourceDemoBuffer) { // buf.writeUint32(this.unk1!); // buf.writeUint8(this.unk2!); // buf.writeFloat32(this.unk3!); // buf.writeFloat32(this.unk4!); // buf.writeFloat32(this.unk5!); } } // TODO export class ChangePaintColor extends UserMessage { unk1?: number; unk2?: number; override read(_buf: SourceDemoBuffer) { // this.unk1 = buf.readUint32(); // this.unk2 = buf.readUint8(); } override write(_buf: SourceDemoBuffer) { // buf.writeUint32(this.unk1!); // buf.writeUint8(this.unk2!); } } // NOTE: Unused export class PaintBombExplode extends UserMessage { override read(_buf: SourceDemoBuffer) {} override write(_buf: SourceDemoBuffer) {} } export class RemoveAllPaint extends UserMessage { override read(_buf: SourceDemoBuffer) {} override write(_buf: SourceDemoBuffer) {} } // NOTE: Unused export class PaintAllSurfaces extends UserMessage { override read(_buf: SourceDemoBuffer) {} override write(_buf: SourceDemoBuffer) {} } export class RemovePaint extends UserMessage { override read(_buf: SourceDemoBuffer) {} override write(_buf: SourceDemoBuffer) {} } // NOTE: Unused export class StartSurvey extends UserMessage { handle?: number; override read(buf: SourceDemoBuffer) { this.handle = buf.readUint32(); } override write(buf: SourceDemoBuffer) { buf.writeUint32(this.handle!); } } // TODO export class ApplyHitBoxDamageEffect extends UserMessage { entityHandle?: number; effectIndex?: number; hits?: number; override read(_buf: SourceDemoBuffer) { // this.entityHandle = buf.readUint32(); // this.effectIndex = buf.readUint8(); // this.hits = buf.readUint8(); } override write(_buf: SourceDemoBuffer) { // buf.writeUint32(this.entityHandle!); // buf.writeUint8(this.effectIndex!); // buf.writeUint8(this.hits!); } } export class SetMixLayerTriggerFactor extends UserMessage { layer?: string; group?: string; factor?: number; override read(buf: SourceDemoBuffer) { this.layer = buf.readASCIIString(); this.group = buf.readASCIIString(); this.factor = buf.readFloat32(); } override write(buf: SourceDemoBuffer) { buf.writeASCIIString(this.layer!); buf.writeASCIIString(this.group!); buf.writeFloat32(this.factor!); } } export class TransitionFade extends UserMessage { fade?: number; override read(buf: SourceDemoBuffer) { this.fade = buf.readFloat32(); } override write(buf: SourceDemoBuffer) { buf.writeFloat32(this.fade!); } } export class ScoreboardTempUpdate extends UserMessage { portalScore?: number; timeScore?: number; override read(buf: SourceDemoBuffer) { this.portalScore = buf.readUint32(); this.timeScore = buf.readUint32(); } override write(buf: SourceDemoBuffer) { buf.writeUint32(this.portalScore!); buf.writeUint32(this.timeScore!); } } export class ChallengeModeCheatSession extends UserMessage { override read(_buf: SourceDemoBuffer) {} override write(_buf: SourceDemoBuffer) {} } export class ChallengeModeCloseAllUI extends UserMessage { override read(_buf: SourceDemoBuffer) {} override write(_buf: SourceDemoBuffer) {} } export const UserMessages = { Portal2Engine: [ Geiger, // 0 Train, // 1 HudText, // 2 SayText, // 3 SayText2, // 4 TextMsg, // 5 HudMsg, // 6 ResetHUD, // 7 GameTitle, // 8 ItemPickup, // 9 ShowMenu, // 10 Shake, // 11 Tilt, // 12 Fade, // 13 VGUIMenu, // 14 Rumble, // 15 Battery, // 16 Damage, // 17 VoiceMask, // 18 RequestState, // 19 CloseCaption, // 20 CloseCaptionDirect, // 21 HintText, // 22 KeyHintText, // 23 SquadMemberDied, // 24 AmmoDenied, // 25 CreditsMsg, // 26 LogoTimeMsg, // 27 AchievementEvent, // 28 UpdateJalopyRadar, // 29 CurrentTimescale, // 30 DesiredTimescale, // 31 CreditsPortalMsg, // 32 InventoryFlash, // 33 IndicatorFlash, // 34 ControlHelperAnimate, // 35 TakePhoto, // 36 Flash, // 37 HudPingIndicator, // 38 OpenRadialMenu, // 39 AddLocator, // 40 MPMapCompleted, // 41 MPMapIncomplete, // 42 MPMapCompletedData, // 43 MPTauntEarned, // 44 MPTauntUnlocked, // 45 MPTauntLocked, // 46 MPAllTauntsLocked, // 47 PortalFX_Surface, // 48 PaintWorld, // 49 PaintEntity, // 50 ChangePaintColor, // 51 PaintBombExplode, // 52 RemoveAllPaint, // 53 PaintAllSurfaces, // 54 RemovePaint, // 55 StartSurvey, // 56 ApplyHitBoxDamageEffect, // 57 SetMixLayerTriggerFactor, // 58 TransitionFade, // 59 ScoreboardTempUpdate, // 60 ChallengeModeCheatSession, // 61 ChallengeModeCloseAllUI, // 62 // not registered: // VoiceSubtitle { client: i8, menu: i8, item: i8 } // StatsCrawlMsg {} // creditsMsg {} // MPVSGameOver { unk: i8 } // MPVSRoundEnd { unk: i8 } // MPVSGameStart { unk: i8 } ], };