/** * 修补 Cesium.js:在 uniform 类型 switch-case 中添加 SAMPLER_3D (35679) 支持。 * * SuperMap 定制的 Cesium.js 在 PostProcessStage 的 uniform setter 创建逻辑中 * 缺少对 SAMPLER_3D 分支的处理,导致 sampler3D 类型的 uniform 绑定失败。 * * 本脚本通过分析 obfuscated 代码中的 SAMPLER constants 定义,找到对应的 * WebGL 常量值,并在 switch-case 中插入缺失的 SAMPLER_3D 分支。 */ const fs = require('fs'); const path = require('path'); const filePath = path.join(__dirname, 'public/Cesium/Cesium.js'); let content = fs.readFileSync(filePath, 'utf8'); // Step 1: Find SAMPLER_3D constant definition // Looking for: 'SAMPLER_3D':0x8b5f const sampler3DConstIdx = content.indexOf("'SAMPLER_3D'"); if (sampler3DConstIdx < 0) { console.error('SAMPLER_3D constant not found in Cesium.js'); process.exit(1); } console.log('SAMPLER_3D constant found at byte', sampler3DConstIdx); // Step 2: Find SAMPLER_2D constant definition to find its numeric value const sampler2DConstIdx = content.indexOf("'SAMPLER_2D'"); if (sampler2DConstIdx < 0) { console.error('SAMPLER_2D constant not found'); process.exit(1); } console.log('SAMPLER_2D constant found at byte', sampler2DConstIdx); // Step 3: Find the switch-case that handles uniform types // Looking for the pattern: case ... SAMPLER_2D ... case ... SAMPLER_CUBE // These are used in the uniform setter creation function // Search for SAMPLER_CUBE in the context of a switch case const switchPattern = /case\s+[^;]*?SAMPLER_2D[^;]*?case\s+[^;]*?SAMPLER_CUBE/g; let match; let found = false; while ((match = switchPattern.exec(content)) !== null) { const fullMatch = match[0]; console.log('\nFound SAMPLER_2D..SAMPLER_CUBE sequence at byte', match.index); console.log('Match:', fullMatch.substring(0, 200)); // Check if SAMPLER_3D is already present between them if (fullMatch.includes('SAMPLER_3D')) { console.log('SAMPLER_3D already present - no patch needed!'); found = true; continue; } // Find the pattern between SAMPLER_2D and SAMPLER_CUBE const s2Idx = fullMatch.indexOf('SAMPLER_2D'); const scIdx = fullMatch.indexOf('SAMPLER_CUBE'); const between = fullMatch.substring(s2Idx + 'SAMPLER_2D'.length, scIdx); console.log('Between SAMPLER_2D and SAMPLER_CUBE:', between.substring(0, 100)); // Get the property access pattern: e.g., `_0x2cbe(0x...)` or `this.SAMPLER_2D` // We need to find how SAMPLER_2D's value is obtained const s2Access = fullMatch.substring(0, s2Idx).trim(); const s2AccessClean = s2Access.replace(/^case\s+/, '').trim(); console.log('SAMPLER_2D access pattern:', s2AccessClean.substring(0, 80)); // The SAMPLER_2D access is via a property on an object // The SAMPLER_3D should use the SAME object but with SAMPLER_3D // e.g. if SAMPLER_2D is accessed as `_0x4b6e38.SAMPLER_2D` // then SAMPLER_3D should be `_0x4b6e38.SAMPLER_3D` const objMatch = s2AccessClean.match(/^([\w.]+)\.SAMPLER_2D$/); if (!objMatch) { console.log('Cannot parse access pattern, trying alternative...'); // Could also be an array access like _0x...['SAMPLER_2D'] continue; } const obj = objMatch[1]; const sampler3DAccess = obj + ".SAMPLER_3D"; const insertStr = "case " + sampler3DAccess + ":"; console.log('Will insert:', insertStr); // Insert SAMPLER_3D case after SAMPLER_2D case const insertPos = match.index + s2Idx + 'SAMPLER_2D'.length + between.length; const insertion = "case " + sampler3DAccess + ":"; content = content.substring(0, insertPos) + insertion + content.substring(insertPos); console.log('Inserted at byte', insertPos); found = true; break; } if (!found) { console.log('\nCould not find the switch-case pattern. Trying alternative approach...'); // Alternative: Search for "SAMPLER_2D:SAMPLER_CUBE" or similar sequences // The obfuscated code might have these constant strings next to each other const altPattern = /SAMPLER_2D['"`:;,.\]]+SAMPLER_CUBE/g; while ((match = altPattern.exec(content)) !== null) { console.log('Alt pattern found at byte', match.index, ':', match[0].substring(0, 100)); } } // Save the patched file fs.writeFileSync(filePath, content, 'utf8'); console.log('\nPatch complete');