From 0f1a25e7a9774a47ad8694337a59be0ec1bd2654 Mon Sep 17 00:00:00 2001 From: tommy Date: Sat, 9 May 2026 17:15:27 -0400 Subject: [PATCH] fix replay viewer obsolete textures on maps with doubled-materials pakfile (e.g. bhop_jaunt_2) --- src/replay-viewer/noclip/SourceEngine/Main.ts | 2 +- src/replay-viewer/noclip/SourceEngine/VMT.ts | 14 +++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/replay-viewer/noclip/SourceEngine/Main.ts b/src/replay-viewer/noclip/SourceEngine/Main.ts index b4b3130..1909d2f 100644 --- a/src/replay-viewer/noclip/SourceEngine/Main.ts +++ b/src/replay-viewer/noclip/SourceEngine/Main.ts @@ -176,7 +176,7 @@ export class SourceFileSystem { return null; } - private hasEntryAuthoritative(resolvedPath: string): boolean { + public hasEntryAuthoritative(resolvedPath: string): boolean { for (let i = 0; i < this.vpk.length; i++) { const entry = this.vpk[i].findEntry(resolvedPath); if (entry !== null) return true; diff --git a/src/replay-viewer/noclip/SourceEngine/VMT.ts b/src/replay-viewer/noclip/SourceEngine/VMT.ts index 1fb2315..c1acdb8 100644 --- a/src/replay-viewer/noclip/SourceEngine/VMT.ts +++ b/src/replay-viewer/noclip/SourceEngine/VMT.ts @@ -221,12 +221,16 @@ function stealPair(pairs: VKFPair[], name: string): VKFPair | null { export async function parseVMT(filesystem: SourceFileSystem, path: string, depth: number = 0): Promise { async function parsePath(path: string): Promise { path = filesystem.resolvePath(path, '.vmt'); - if (!filesystem.hasEntry(path)) { - // Amazingly, the material could be in materials/materials/, like is - // materials/materials/nature/2/blenddirttojunglegrass002b.vmt - // from cp_mossrock + // Amazingly, the material could be in materials/materials/, like is + // materials/materials/nature/2/blenddirttojunglegrass002b.vmt + // from cp_mossrock, or + // materials/materials/real_dev/dev_pink6.vmt + // from bhop_jaunt_2. Gate the retry on the authoritative mounts: an + // opportunistic loose mount (CSPakMount) claims every path, so a + // plain hasEntry() short-circuits the retry and the doubled-prefix + // pakfile entry never gets matched. + if (!filesystem.hasEntryAuthoritative(path) && filesystem.hasEntryAuthoritative(`materials/${path}`)) path = `materials/${path}`; - } if (!filesystem.hasEntry(path)) path = `materials/editor/obsolete.vmt`; // CSPakMount.hasEntry is optimistic, so 404s only surface at fetch