/unreal.js

A pak reader for games like VALORANT & Fortnite written in pure JavaScript

Primary LanguageTypeScriptMIT LicenseMIT

UPDATE: I (Sprayxe) am no longer maintaining this project. I simply lost motivation to work on it due to several reasons. If you want to keep maintaining the project send me a DM via discord! Thanks to all the people who helped me in this project and thanks to all the people who used or are still using this library. Cya!

LICENCE TYPESCRIPT JAVASCRIPT NODEJS DISCORD0
NPM

LOGO_0

unreal.js

A pak reader for games like VALORANT & Fortnite written in Node.JS

Notice

This library is in VERY early development so it might be unstable. Please also keep in mind that JavaScript is not really made for this kind of stuff so the usage of this library is experimental. We still try fixing most issues though so report if you experience any!\

Features

  • Easy2use file provider for fast interaction with pak/asset files
  • Supports loading of UE4 pak files
  • Supports loading of UE4 asset files (.uasset, .umap, .uexp, .ubulk)
  • Supports loading of .locres files
  • Supports loading of AssetRegistry.bin
  • Supports exporting of UE4 textures as image
  • Supports exporting of UE4 sounds files

Prerequisites

  • Node.JS/NPM installed
  • Experience with JavaScript or TypeScript
  • Python, Visual C++ Build Tools (node-gyp dependencies)

Installation

npm i unreal.js
This library has optional dependencies like canvas and dxt-js which are used in ue4 texture conversion. If you don't want to install these dependencies, use: npm i unreal.js --no-optional.

Documentation

Here

Usage

Basics: FileProvider

The file provider is basically the heart of the library and from there you control basically all features.

IMPORTANT: When using the library with Fortnite V14.40 and above, you need oo9core_8_win64.dll present in your working directory (you can download it using Oodle.downloadDLL()). You will also need a .usmap mappings file corresponding to your fortnite version.
You will also experience longer mounting times than e.g VALORANT.

  • Usage with Fortnite

    // Create new instance
    const usmap = new UsmapTypeMappingsProvider(readFileSync("USMAPPATH"))
    const provider = new FileProvider("GAMEPATH", VERSION, usmap)
    provider.mappingsProvider.reload() // Loads .usmap
    // Setting this to '0' will skip reading directory index
    // Means it will not populate .utoc file entries, so <FIoStoreReader>.getFiles() will be empty
    // Leaving it to default value will slightly increase pak mounting time
    provider.ioStoreTocReadOptions = 0
    // 'start' the provider
    await provider.initialize()
    // submit aes key to decrypt paks
    await provider.submitKey(FGuid.mainGuid, "KEY")

    Replace:

    • USMAPPATH: Path to your .usmap file (doesn't need to be in working dir)
    • VERSION: Version you want to use (e.g Ue4Version.GAME_UE4_26, pass null for latest)
    • GAMEPATH: Path to fortnite's paks
    • KEY: An aes key corresponding to your version
  • Usage with VALORANT

     // Create new instance 
     const provider = new FileProvider("GAMEPATH", Ue4Version.GAME_VALORANT)
     // 'start' the provider
     await provider.initialize()
     // submit aes key to decrypt paks
     await provider.submitKey(FGuid.mainGuid, "0x4BE71AF2459CF83899EC9DC2CB60E22AC4B3047E0211034BBABE9D174C069DD6")

    Replace:

    • GAMEPATH: Path to valorant's paks

Basics: Loading an asset

  • Loading whole file

     const pkg = provider.loadGameFile("PATH") // loads the file
     console.log(pkg.toJson()) // turns file into json format

    Replace:

    • PATH: Path to the file you want to load
  • Loading specific object from file

    const obj = provider.loadObject("PATH", "OBJECTNAME") // loads the object
    console.log(pkg.toJson()) // turns object into json format

    Replace:

    • PATH: Path to the file you want to load
    • OBJECTNAME: Name of the object to load
      You can leave this parameter out if you provide the object name as file extension

Basics: Exporting sounds

  • Exporting a sound wave

    // this will find an export which matches the class 'USoundWave'
    const sound = pkg.getExportOfType(USoundWave)
    // use 'pkg.getExportOfTypeOrNull(USoundWave)' if you check for undefined/null manually
    const wave = SoundWave.convert(sound) // converts USoundWave to a usable file
    // write it to a file
    writeFileSync(`MySoundFile.${wave.format}`, wave.data)
  • Exporting wwise audio (VALORANT)

    // this will find an export which matches the class 'UAkMediaAssetData'
    const mediaData = pkg.getExportOfType(UAkMediaAssetData)
    const wwise = WwiseAudio.convert(mediaData) // Converts it to a .wem file
    // write it to a file
    writeFileSync(`MySoundFile.${wwise.format}`, wwise.data)

    IMPORTANT: .wem are not playable by windows, you have to convert it to a .wav file first!
    Unreal.JS is able to do that with vgmstream. Download the zip file from here, create a folder called 'vgm' in your working directory and extract all files into it. Then do:

    // this will find an export which matches the class 'UAkMediaAssetData'
    const mediaData = pkg.getExportOfType(UAkMediaAssetData)
    const wwise = WwiseAudio.convert(mediaData) // Converts it to a .wem file
    // converts and exports it as playable .wav file
    wwise.export() // you can pass an output path (must include whole path with filename and extension)

Basics: Exporting textures

  // this will find an export which matches the class 'UTexture2D'
  const tex = pkg.getExportOfType(UTexture2D)
  // use 'pkg.getExportOfTypeOrNull(UTexture2D)' if you check for undefined/null manually
  const image = Image.convert(tex) // converts texture to image (import Image class from unreal.js)
  // writes it it a file
  writeFileSync("image.png", image)

Basics: Loading locres

  • Loading by file path

    const locres = provider.loadLocres("PATH") // loads the locres file
    console.log(locres.toJson()) // turns locres into json format 

    Replace:

    • PATH: Path to the .locres file
  • Loading by enum

    const locres = provider.loadLocres(FnLanguage.DE) // loads using enum
    console.log(locres.toJson()) // turns locres into json format 

Advanced: Loading a pak file manually

const reader = new PakFileReader("PATH", GAME) // Create a new instance
reader.aesKey = "KEY" // Set an aes key (can be left out if pak is not encrypted)
reader.readIndex() // Read the index
reader.extract(reader.files.first()) // Gets the first file and extracts it as Buffer

Replace:

  • PATH: Path to the pak file
  • GAME: Game version you are using (e.g Ue4Version.GAME_UE4_26)
    You can leave it out if you want to use the latest version
  • KEY: Aes key used for decrypting the pak
    WARNING Using a wrong aes key will throw an exception! You can use reader.testAesKey("KEY") to test if it works (returns a boolean)

Advanced: Loading a package manually

// load a pak package (e.g valorant)
const pkg = new PakPackage(UASSETBUFFER, UEXPBUFFER, UBULKBUFFER, NAME, PROVIDER, GAME)
// load an io package (mostly used in fortnite)
const pkg2 = new IoPackage(UASSETBUFFER, PACKAGEID, STOREENTRY, GLOBALPACKAGESTORE, PROVIDER, GAME)

Replace:

  • UASSETBUFFER: Buffer of the .uasset file
  • UEXPBUFFER: Buffer of the .uexp file
  • UBULKBUFFER: Buffer of the .ubulk file (pass null if it doesn't exist)
  • NAME: Name of the package
  • PROVIDER: Instance of a fileprovider (optional in PakPackage)
  • GAME: Version of the game you are using (e.g Ue4Version.GAME_VALORANT, optional in both)
  • PACKAGEID: The id of the io package
  • STOREENTRY: Instance of the io package's FPackageStoreEntry
  • GLOBALPACKAGESTORE: The file provider's FPackageStore object

Support, Feedback, Contact

  • Discord: MarcelWRLD#4682
  • Twitter: Sprayxe_

Inspiration

LOGO_1