Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added Third-Party/GFXFzip.exe
Binary file not shown.
11 changes: 6 additions & 5 deletions docs/Folder Structure.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,15 @@ The content folder contains chunk folders, which contain files (and folders, the
| `contract.json` | A contract that will be added to the contracts ORES |
| `JSON.patch.json` | An RFC6902 JSON patch that will be applied to the hash the file specifies |
| `material.json` | An RPKG tool material JSON that will replace/add the targeted material |
| `clng.json` | A HMLanguages CLNG JSON that will replace/add the targeted file |
| `ditl.json` | A HMLanguages DITL JSON that will replace/add the targeted file |
| `dlge.json` | A HMLanguages DLGE JSON that will replace/add the targeted file |
| `locr.json` | A HMLanguages LOCR JSON that will replace/add the targeted file |
| `rtlv.json` | A HMLanguages RTLV JSON that will replace/add the targeted file |
| `clng.json` | A HMLanguages CLNG JSON that will replace/add the targeted file |
| `ditl.json` | A HMLanguages DITL JSON that will replace/add the targeted file |
| `dlge.json` | A HMLanguages DLGE JSON that will replace/add the targeted file |
| `locr.json` | A HMLanguages LOCR JSON that will replace/add the targeted file |
| `rtlv.json` | A HMLanguages RTLV JSON that will replace/add the targeted file |
| `texture.tga` | A TGA to rebuild into a game texture (TEXT only or TEXT and TEXD) |
| `sfx.wem` | A Wwise sound effect to patch a WWEV file with |
| `delta` | A VCDiff delta file to patch the specified file with |
| `gfxf.zip` | A GFXF zip file that will replace/add the targeted file |

The names of special files do not matter - it is their extensions that do, **except for texture.tga, sfx.wem and delta files**. Raw files, which any non-special file is, are placed directly into the built RPKG and so must be named like usual.

Expand Down
3 changes: 3 additions & 0 deletions docs/Special File Types.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,3 +159,6 @@ The framework will automatically extract the WWEV and copy the wem to it, then r
Patches a given file with a VCDiff delta using xdelta3. Named in the format `hash~filetype.delta`. For example, to patch `004A314BA75429D7.GFXF`, the file should be named `004A314BA75429D7~GFXF.delta`.

The framework will automatically extract the file and patch it, then place it in the staging folder. You may want to include a meta file for the hash as well, or the RPKG tool will assume the default metadata.

## gfxf.zip
A GFXF zip file obtained from Anthony Fuller's GFXFzip tool. Will be converted to a GFXF file and placed in the staging folder (overriding any existing game file).
47 changes: 46 additions & 1 deletion src/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -620,7 +620,12 @@ export default async function deploy(
"texture.tga",
"sfx.wem",
"delta",
"locr.json"
"clng.json",
"ditl.json",
"dlge.json",
"locr.json",
"rtlv.json",
"gfxf.zip"
].includes(content.type)
? sentryContentTransaction.startChild({
op: "stageContentFile",
Expand Down Expand Up @@ -1631,6 +1636,46 @@ export default async function deploy(
)
break
}
case "gfxf.zip": {
await logger.debug(`Converting Scaleform GFx package ${contentIdentifier}`)

if (
invalidatedData.some((a) => a.filePath === contentIdentifier) || // must redeploy, invalid cache
!(await copyFromCache(instruction.cacheFolder, path.join(`chunk${content.chunk}`, await xxhash3(contentIdentifier)), path.join(process.cwd(), "temp", `chunk${content.chunk}`))) // cache is not available
) {
fs.ensureDirSync(path.join(process.cwd(), "temp", `chunk${content.chunk}`))

let contentFilePath
if (content.source === "disk") {
contentFilePath = content.path
} else {
fs.ensureDirSync(path.join(process.cwd(), "virtual"))
fs.writeFileSync(path.join(process.cwd(), "virtual", content.type), Buffer.from(await content.content.arrayBuffer()))
contentFilePath = path.join(process.cwd(), "virtual", content.type)
}

execCommand(
`"Third-Party\\GFXFzip" rebuild H3 "${contentFilePath}" "${path.join(
process.cwd(),
"temp",
`chunk${content.chunk}`
)}" --folder`
)

fs.removeSync(path.join(process.cwd(), "virtual"))

await copyToCache(instruction.cacheFolder, path.join(process.cwd(), "temp", `chunk${content.chunk}`), path.join(`chunk${content.chunk}`, await xxhash3(contentIdentifier)))
}

fs.ensureDirSync(path.join(process.cwd(), "staging", `chunk${content.chunk}`))

// Copy generated files (have to copy the entire folder as we do not know what the final hash is)
fs.copySync(
path.join(process.cwd(), "temp", `chunk${content.chunk}`),
path.join(process.cwd(), "staging", `chunk${content.chunk}`)
)
break
}
default: // Copy the file to the staging directory; we don't cache these for obvious reasons
if (
(content.source === "disk" ? path.basename(content.path).split(".").slice(1).join(".") : content.extraInformation.fileType!).length === 4 ||
Expand Down
9 changes: 9 additions & 0 deletions src/discover.ts
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,15 @@ export default async function discover(): Promise<{ [x: string]: { hash: string;

affected.push(normaliseToHash(entityContent.hash))
break
case "gfxf.zip": // Depends on nothing, edits the GFXF file
// Now this is a tricky one, we don't exactly know which GFXF
// will be affected. Forcing the user to use the hash of the file for
// the name defeats the purpose of this file type. Which was to allow for
// end users to easily make changes to this file, so having an easily identifiable
// or descriptive name makes this better.

// Right now, we don't do anything to the affected or dependencies arrays.
break
default: // Replaces a file with a raw file
if (
path.basename(contentFilePath).split(".").slice(1).join(".").length === 4 ||
Expand Down