Last active
October 29, 2022 21:50
-
-
Save Disquse/014882c6463a66af7e184d79136aeaed to your computer and use it in GitHub Desktop.
Fix typo
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const fs = require("fs"); | |
const path = require("path"); | |
// !!! PUT *unpacked* .#pm files in this folder. | |
const targetPath = `${__dirname}\\Files`; | |
// !!! Path to RAGE-StringsDatabase repo. | |
const stringsPath = `${__dirname}\\RAGE-StringsDatabase`; | |
async function* getFiles(dir, target = "") { | |
const entries = await fs.promises.readdir(dir, { withFileTypes: true }); | |
for (const dirent of entries) { | |
const res = path.resolve(dir, dirent.name); | |
if (dirent.isDirectory()) { | |
yield* getFiles(res); | |
} else { | |
if (!res.endsWith(target)) { | |
continue; | |
} | |
yield res; | |
} | |
} | |
} | |
function getJoaat(key) { | |
const length = key.length; | |
let hash, i; | |
for (hash = i = 0; i < length; i++){ | |
hash += key.charCodeAt(i); | |
hash += (hash << 10); | |
hash ^= (hash >>> 6); | |
} | |
hash += (hash << 3); | |
hash ^= (hash >>> 11); | |
hash += (hash << 15); | |
return hash >>> 0; | |
} | |
const hashToName = new Map(); | |
(async () => { | |
for await (const filePath of getFiles(targetPath, ".full")) { | |
const fileName = filePath.split("\\").pop().replace(".ypm.full", ""); | |
if (!fileName.startsWith("0x")) { | |
continue; | |
} | |
const fileHash = parseInt(fileName, 16); | |
const fileContent = fs.readFileSync(filePath, { encoding: "binary" }); | |
const nameOffsetBytes = []; | |
for (let i = 0x3B; i >= 0x38; i--) { | |
nameOffsetBytes.push(fileContent[i].charCodeAt(0)); | |
} | |
const nameOffset = (nameOffsetBytes[3] | nameOffsetBytes[2] << 8 | nameOffsetBytes[1] << 16 | nameOffsetBytes[0] << 24) - 0x50000000; | |
const fileNameBytes = []; | |
let charOffset = 0; | |
while (true) { | |
const charCursor = nameOffset + charOffset; | |
const charCode = fileContent[charCursor].charCodeAt(0); | |
if (!charCode) { | |
break; | |
} | |
fileNameBytes.push(fileContent[charCursor]); | |
charOffset++; | |
} | |
const assetName = fileNameBytes.join("").trim(); | |
if (getJoaat(assetName) !== fileHash) { | |
console.warn("joaat missmatch for " + fileName); | |
continue; | |
} | |
if (!assetName) { | |
console.warn("invalid name of " + fileName); | |
continue; | |
} | |
hashToName.set(fileHash, assetName); | |
} | |
const addedFiles = {}; | |
for await (const filePath of getFiles(stringsPath, ".hashes")) { | |
const hashesList = fs.readFileSync(filePath, { encoding: "utf8" }).split("\n"); | |
for (const hashLine of hashesList) { | |
const actualHash = parseInt(hashLine.trim(), 16); | |
if (hashToName.has(actualHash)) { | |
if (!addedFiles[filePath]) { | |
addedFiles[filePath] = []; | |
} | |
addedFiles[filePath].push(hashToName.get(actualHash)); | |
} | |
} | |
} | |
for (const addedFile in addedFiles) { | |
const addedStrings = addedFiles[addedFile]; | |
const textPath = addedFile.replace(".hashes", ".txt"); | |
const fileContent = fs.readFileSync(textPath, { encoding: "utf8" }).split("\n").filter(line => line.trim()); | |
for (const addedString of addedStrings) { | |
if (fileContent.includes(addedString)) { | |
continue; | |
} | |
if (addedString) { | |
fileContent.push(addedString); | |
} | |
} | |
fs.writeFileSync(textPath, fileContent.sort().join("\n") + "\n"); | |
} | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment