├── .dockerignore ├── .github ├── CODEOWNERS ├── dependabot.yml └── workflows │ ├── test.yml │ └── validate.yml ├── .gitignore ├── LICENSE ├── README.md ├── build.cjs ├── demo └── index.html ├── dev.Dockerfile ├── dist ├── uasset-reader.js └── uasset-reader.min.js ├── docker-bake.hcl ├── eslint.config.js ├── jsdoc.conf.json ├── package-lock.json ├── package.json ├── src └── js │ ├── _namespace_.js │ ├── enums │ └── enums.js │ └── main.js └── tests ├── datacases.json ├── main.test.js └── uassets └── ue50 ├── BP_Actor_Simple.json ├── BP_Actor_Simple.uasset └── BP_Actor_Simple.utxt /.dockerignore: -------------------------------------------------------------------------------- 1 | /coverage 2 | /node_modules 3 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @rancoud -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "npm" 4 | directory: "/" 5 | schedule: 6 | interval: "daily" 7 | time: "08:00" 8 | timezone: "Europe/Paris" 9 | - package-ecosystem: "github-actions" 10 | directory: "/" 11 | schedule: 12 | interval: "daily" 13 | time: "08:00" 14 | timezone: "Europe/Paris" 15 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: test 2 | 3 | permissions: 4 | contents: read 5 | 6 | concurrency: 7 | group: ${{ github.workflow }}-${{ github.ref }} 8 | cancel-in-progress: true 9 | 10 | on: 11 | push: 12 | branches: 13 | - 'main' 14 | pull_request: 15 | 16 | jobs: 17 | test: 18 | runs-on: ubuntu-latest 19 | steps: 20 | - 21 | name: Checkout 22 | uses: actions/checkout@v4 23 | - 24 | name: Test 25 | uses: docker/bake-action@v6 26 | with: 27 | source: . 28 | targets: test 29 | - 30 | name: Upload coverage 31 | uses: codecov/codecov-action@v5 32 | with: 33 | files: ./coverage/lcov.info 34 | token: ${{ secrets.CODECOV_TOKEN }} 35 | -------------------------------------------------------------------------------- /.github/workflows/validate.yml: -------------------------------------------------------------------------------- 1 | name: validate 2 | 3 | permissions: 4 | contents: read 5 | 6 | concurrency: 7 | group: ${{ github.workflow }}-${{ github.ref }} 8 | cancel-in-progress: true 9 | 10 | on: 11 | push: 12 | branches: 13 | - 'main' 14 | pull_request: 15 | 16 | jobs: 17 | prepare: 18 | runs-on: ubuntu-latest 19 | outputs: 20 | targets: ${{ steps.targets.outputs.matrix }} 21 | steps: 22 | - 23 | name: Checkout 24 | uses: actions/checkout@v4 25 | - 26 | name: Targets matrix 27 | id: targets 28 | run: | 29 | echo "matrix=$(docker buildx bake validate --print | jq -cr '.group.validate.targets')" >> $GITHUB_OUTPUT 30 | 31 | validate: 32 | runs-on: ubuntu-latest 33 | needs: 34 | - prepare 35 | strategy: 36 | fail-fast: false 37 | matrix: 38 | target: ${{ fromJson(needs.prepare.outputs.targets) }} 39 | steps: 40 | - 41 | name: Checkout 42 | uses: actions/checkout@v4 43 | - 44 | name: Validate 45 | uses: docker/bake-action@v6 46 | with: 47 | source: . 48 | targets: ${{ matrix.target }} 49 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # IntelliJ 2 | .idea 3 | *.iml 4 | 5 | # Node modules 6 | node_modules 7 | 8 | # System files 9 | .DS_Store 10 | 11 | # Jest 12 | coverage 13 | 14 | # JSDoc 15 | jsdoc 16 | 17 | # eslint 18 | eslint_out.html -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 blueprintUE 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Uasset Reader JS 2 | Read and extract informations of `.uasset` files from Unreal Engine in javascript. 3 | [Here a Live Demo.](https://blueprintue.com/tools/uasset-reader.html) 4 | 5 | ## How to use 6 | First you need to import `uasset-reader.min.js` in your page. 7 | ```js 8 | const file = document.getElementById("file-input").files[0]; 9 | const buffer = await file.arrayBuffer(); 10 | const bytes = new Uint8Array(buffer); 11 | new window.blueprintUE.uasset.ReaderUasset().analyze(bytes); 12 | ``` 13 | 14 | ### Main Methods 15 | #### analyze([bytes: Uint8Array]): Uasset 16 | This method read each byte to extract data from current `.uasset` file. 17 | 18 | ## How to Dev 19 | `npm test` or `docker buildx bake test` to test and coverage 20 | `npm run build` or `docker buildx bake build` to create dist js file minified 21 | `npm run jsdoc` or `docker buildx bake jsdoc` to generate documentation 22 | `npm run eslint` or `docker buildx bake lint` to run eslint 23 | `npm run eslint:fix` to run eslint and fix files 24 | -------------------------------------------------------------------------------- /build.cjs: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const path = require("path"); 3 | const babel = require("@babel/core"); 4 | 5 | // region JS 6 | 7 | function generateJS() { 8 | // list of JS files to concat 9 | const inputJSFiles = [ 10 | path.join(__dirname, 'src/js/_namespace_.js'), 11 | path.join(__dirname, 'src/js/enums/enums.js'), 12 | path.join(__dirname, 'src/js/main.js') 13 | ]; 14 | 15 | // output JS file 16 | const outputJSFilename = "dist/uasset-reader.js"; 17 | 18 | let outputJSFileContent = concatJSFiles(inputJSFiles); 19 | outputJSFileContent = removeLines(outputJSFileContent); 20 | outputJSFileContent = removeDebug(outputJSFileContent); 21 | outputJSFileContent = addHeaderAndLicense(outputJSFileContent); 22 | saveFile(outputJSFilename, outputJSFileContent); 23 | } 24 | 25 | function concatJSFiles(files) { 26 | let outputFileContent = ["(function () {"]; 27 | outputFileContent.push('"use strict";' + "\n"); 28 | 29 | for(let idxFiles = 0, maxFiles = files.length; idxFiles < maxFiles; ++idxFiles) { 30 | outputFileContent.push(fs.readFileSync(files[idxFiles]).toString("utf8")); 31 | } 32 | 33 | outputFileContent.push("})();"); 34 | 35 | return outputFileContent.join("\n"); 36 | } 37 | 38 | function removeLines(content) { 39 | const lines = content.split(/\r\n|\r|\n/g); 40 | let idxLines = 0; 41 | let maxLines = lines.length; 42 | let newLines = []; 43 | 44 | for (; idxLines < maxLines; ++idxLines) { 45 | if (lines[idxLines].match("BUILD REMOVE LINE")) { 46 | continue; 47 | } 48 | 49 | newLines.push(lines[idxLines]); 50 | } 51 | 52 | return newLines.join("\n"); 53 | } 54 | 55 | function removeDebug(content) { 56 | function getNode(node) { 57 | if (node.isMemberExpression()) { 58 | const object = node.get("object"); 59 | if (object.isIdentifier() && node.has("property")) { 60 | return node.get("property"); 61 | } 62 | } 63 | 64 | return node; 65 | } 66 | 67 | function isConsole(nodePath) { 68 | const callee = nodePath.get("callee"); 69 | 70 | if (!callee.isMemberExpression()) { 71 | return; 72 | } 73 | 74 | return getNode(callee.get("object")).isIdentifier({name: "console"}) && callee.has("property"); 75 | } 76 | 77 | function isAlert(nodePath) { 78 | return getNode(nodePath.get("callee")).isIdentifier({name: "alert"}); 79 | } 80 | 81 | return babel.transformSync(content, { 82 | retainLines: true, 83 | plugins:[{ 84 | visitor: { 85 | DebuggerStatement(nodePath) { 86 | nodePath.remove(); 87 | }, 88 | CallExpression(nodePath) { 89 | if (isConsole(nodePath) || isAlert(nodePath)) { 90 | nodePath.remove(); 91 | } 92 | } 93 | }, 94 | }] 95 | }).code; 96 | } 97 | 98 | generateJS(); 99 | 100 | // endregion 101 | 102 | function addHeaderAndLicense(content) { 103 | const license = fs.readFileSync("./LICENSE", "utf8"); 104 | const pkg = require("./package.json"); 105 | 106 | let header = pkg.name + " (v" + pkg.version + ")\n" + pkg.homepage + "\n\n" + license; 107 | 108 | const lines = header.split("\n"); 109 | for (let idx = 0, max = lines.length; idx < max; ++idx) { 110 | if (idx + 1 !== max) { 111 | lines[idx] = " * " + lines[idx]; 112 | } else { 113 | lines[idx] = " */" + lines[idx]; 114 | } 115 | } 116 | 117 | return "/**\n" + lines.join("\n") + "\n" + content; 118 | } 119 | 120 | function saveFile(filename, content) { 121 | fs.writeFileSync(filename, content); 122 | } 123 | -------------------------------------------------------------------------------- /demo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Read .uasset dev file from Unreal Engine 5 in javascript 6 | 197 | 198 | 199 |

.uasset reader dev file from Unreal Engine 5

200 |
201 |

Drop your .uasset dev file from Unreal Engine 5 here or click on the input file below.

202 | 203 |
204 | 205 | 206 | 207 | 208 | 209 |
210 |

Legend

211 |
212 |
00 uint16
213 |
00 int16
214 |
00 uint32
215 |
00 int32
216 |
00 int64
217 |
00 uint64
218 |
00 fguidSlot
219 |
00 fguidString
220 |
00 fstring
221 |
00 data
222 |
223 |
224 | 225 | 237 | 238 | 239 | 545 | 546 | -------------------------------------------------------------------------------- /dev.Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax=docker/dockerfile:1 2 | 3 | FROM node:alpine AS base 4 | RUN apk add --no-cache cpio findutils git 5 | WORKDIR /src 6 | 7 | FROM base AS deps 8 | RUN --mount=type=bind,target=.,rw \ 9 | --mount=type=cache,target=/src/node_modules \ 10 | npm install && mkdir /vendor && cp package-lock.json /vendor 11 | 12 | FROM scratch AS vendor-update 13 | COPY --from=deps /vendor / 14 | 15 | FROM deps AS vendor-validate 16 | RUN --mount=type=bind,target=.,rw <&2 'ERROR: Vendor result differs. Please vendor your package with "docker buildx bake vendor-update"' 22 | git status --porcelain -- package-lock.json 23 | exit 1 24 | fi 25 | EOT 26 | 27 | FROM deps AS build 28 | RUN --mount=type=bind,target=.,rw \ 29 | --mount=type=cache,target=/src/node_modules \ 30 | npm run build && mkdir /out && cp -Rf dist /out/ 31 | 32 | FROM scratch AS build-update 33 | COPY --from=build /out / 34 | 35 | FROM build AS build-validate 36 | RUN --mount=type=bind,target=.,rw <&2 'ERROR: Build result differs. Please build first with "docker buildx bake build"' 42 | git status --porcelain -- dist 43 | exit 1 44 | fi 45 | EOT 46 | 47 | FROM deps AS format 48 | RUN --mount=type=bind,target=.,rw \ 49 | --mount=type=cache,target=/src/node_modules \ 50 | npm run eslint:fix \ 51 | && mkdir /out && find . -name '*.js' -not -path './node_modules/*' | cpio -pdm /out 52 | 53 | FROM scratch AS format-update 54 | COPY --from=format /out / 55 | 56 | FROM deps AS lint 57 | RUN --mount=type=bind,target=.,rw \ 58 | --mount=type=cache,target=/src/node_modules \ 59 | npm run eslint 60 | 61 | FROM deps AS test 62 | RUN --mount=type=bind,target=.,rw \ 63 | --mount=type=cache,target=/src/node_modules \ 64 | npm test && cp -r ./coverage /tmp 65 | 66 | FROM scratch AS test-coverage 67 | COPY --from=test /tmp/coverage / 68 | 69 | FROM deps AS jsdoc 70 | RUN --mount=type=bind,target=.,rw \ 71 | --mount=type=cache,target=/src/node_modules \ 72 | npm run jsdoc && cp -r ./jsdoc /tmp 73 | 74 | FROM scratch AS jsdoc-update 75 | COPY --from=jsdoc /tmp/jsdoc / 76 | -------------------------------------------------------------------------------- /dist/uasset-reader.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * uasset-reader-js (v1.1.2) 3 | * https://github.com/blueprintue/uasset-reader-js 4 | * 5 | * MIT License 6 | * 7 | * Copyright (c) 2023 blueprintUE 8 | * 9 | * Permission is hereby granted, free of charge, to any person obtaining a copy 10 | * of this software and associated documentation files (the "Software"), to deal 11 | * in the Software without restriction, including without limitation the rights 12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | * copies of the Software, and to permit persons to whom the Software is 14 | * furnished to do so, subject to the following conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be included in all 17 | * copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | * SOFTWARE. 26 | */ 27 | !function(){"use strict";function e(){this.currentIdx=0,this.bytes=[],this.uasset={hexView:[],header:{},names:[],gatherableTextData:[],imports:{},exports:[],depends:{},softPackageReferences:{},searchableNames:{},thumbnails:{Index:[],Thumbnails:[]},assetRegistryData:{},preloadDependency:{},bulkDataStart:{}}}void 0===window.blueprintUE&&(window.blueprintUE={}),void 0===window.blueprintUE.uasset&&(window.blueprintUE.uasset={}),e.prototype.uint16=function(e){var t=this.readCountBytes(2),t=new DataView(new Uint8Array(t).buffer).getUint16(0,this.useLittleEndian);return this.addHexView(e,"uint16",t,this.currentIdx-2,this.currentIdx-1),t},e.prototype.int32=function(e){var t=this.readCountBytes(4),t=new DataView(new Uint8Array(t).buffer).getInt32(0,this.useLittleEndian);return this.addHexView(e,"int32",t,this.currentIdx-4,this.currentIdx-1),t},e.prototype.uint32=function(e){var t=this.readCountBytes(4),t=new DataView(new Uint8Array(t).buffer).getUint32(0,this.useLittleEndian);return this.addHexView(e,"uint32",t,this.currentIdx-4,this.currentIdx-1),t},e.prototype.int64=function(e){var t=this.readCountBytes(8),t=new DataView(new Uint8Array(t).buffer).getBigInt64(0,this.useLittleEndian);return this.addHexView(e,"int64",t,this.currentIdx-8,this.currentIdx-1),t},e.prototype.uint64=function(e){var t=this.readCountBytes(8),t=new DataView(new Uint8Array(t).buffer).getBigUint64(0,this.useLittleEndian);return this.addHexView(e,"uint64",t,this.currentIdx-8,this.currentIdx-1),t},e.prototype.fguidSlot=function(e){for(var t,s="",a="",i="",r="",n=3,h=this.readCountBytes(16);0<=n;--n)s+=h[n].toString(16).padStart(2,"0"),a+=h[n+4].toString(16).padStart(2,"0"),i+=h[n+8].toString(16).padStart(2,"0"),r+=h[n+12].toString(16).padStart(2,"0");return t=(s+a+i+r).toUpperCase(),this.addHexView(e,"fguidSlot",t,this.currentIdx-16,this.currentIdx-1),t},e.prototype.fguidString=function(e){for(var t,s="",a=0,i=this.readCountBytes(16);a<16;++a)s+=i[a].toString(16).padStart(2,"0");return t=s.toUpperCase(),this.addHexView(e,"fguidString",t,this.currentIdx-16,this.currentIdx-1),t},e.prototype.fstring=function(e){var t,s,a,i,r,n,h="",o=0,u=[],d=this.int32(e+" (fstring length)");if(0===d)return"";if(n=this.currentIdx,0>"], "int32Hint": true}], 65 | "no-caller": "error", 66 | "no-case-declarations": "error", 67 | "no-class-assign": "error", 68 | "no-compare-neg-zero": "error", 69 | "no-cond-assign": ["error", "always"], 70 | "no-console": "error", 71 | "no-const-assign": "error", 72 | "no-constant-binary-expression": "error", 73 | "no-constant-condition": ["error", {"checkLoops": "all"}], 74 | "no-constructor-return": "error", 75 | "no-continue": "off", 76 | "no-control-regex": "error", 77 | "no-debugger": "error", 78 | "no-delete-var": "error", 79 | "no-div-regex": "error", 80 | "no-dupe-args": "error", 81 | "no-dupe-class-members": "error", 82 | "no-dupe-else-if": "error", 83 | "no-dupe-keys": "error", 84 | "no-duplicate-case": "error", 85 | "no-duplicate-imports": "error", 86 | "no-else-return": "error", 87 | "no-empty": "error", 88 | "no-empty-character-class": "error", 89 | "no-empty-function": "error", 90 | "no-empty-pattern": "error", 91 | "no-empty-static-block": "error", 92 | "no-eq-null": "error", 93 | "no-eval": "error", 94 | "no-ex-assign": "error", 95 | "no-extend-native": "error", 96 | "no-extra-bind": "error", 97 | "no-extra-boolean-cast": ["error", {"enforceForLogicalOperands": true}], 98 | "no-extra-label": "error", 99 | "no-fallthrough": "error", 100 | "no-func-assign": "error", 101 | "no-global-assign": "error", 102 | "no-implicit-coercion": "error", 103 | "no-implicit-globals": "off", 104 | "no-implied-eval": "error", 105 | "no-import-assign": "error", 106 | "no-inline-comments": ["error", {"ignorePattern": "BUILD REMOVE LINE"}], 107 | "no-inner-declarations": ["error", "functions", {"blockScopedFunctions": "disallow"}], 108 | "no-invalid-regexp": "error", 109 | "no-invalid-this": "error", 110 | "no-irregular-whitespace": "error", 111 | "no-iterator": "error", 112 | "no-label-var": "error", 113 | "no-labels": "error", 114 | "no-lone-blocks": "error", 115 | "no-lonely-if": "error", 116 | "no-loop-func": "error", 117 | "no-loss-of-precision": "error", 118 | "no-magic-numbers": ["error", {"ignore": [0, 1, -1, 2, 4, 8, 12, 16], "ignoreArrayIndexes": true, "ignoreDefaultValues": true}], 119 | "no-misleading-character-class": "error", 120 | "no-multi-assign": "error", 121 | "no-multi-str": "error", 122 | "no-negated-condition": "error", 123 | "no-nested-ternary": "error", 124 | "no-new": "error", 125 | "no-new-func": "error", 126 | "no-new-native-nonconstructor": "error", 127 | "no-new-wrappers": "error", 128 | "no-nonoctal-decimal-escape": "error", 129 | "no-obj-calls": "error", 130 | "no-object-constructor": "error", 131 | "no-octal": "error", 132 | "no-octal-escape": "error", 133 | "no-param-reassign": "error", 134 | "no-plusplus": ["error", {"allowForLoopAfterthoughts": true}], 135 | "no-promise-executor-return": "error", 136 | "no-proto": "error", 137 | "no-prototype-builtins": "error", 138 | "no-redeclare": "error", 139 | "no-regex-spaces": "error", 140 | "no-restricted-exports": "error", 141 | "no-restricted-globals": "error", 142 | "no-restricted-imports": "error", 143 | "no-restricted-properties": "error", 144 | "no-restricted-syntax": "error", 145 | "no-return-assign": "error", 146 | "no-script-url": "error", 147 | "no-self-assign": "error", 148 | "no-self-compare": "error", 149 | "no-sequences": "error", 150 | "no-setter-return": "error", 151 | "no-shadow": "error", 152 | "no-shadow-restricted-names": "error", 153 | "no-sparse-arrays": "error", 154 | "no-template-curly-in-string": "error", 155 | "no-ternary": "error", 156 | "no-this-before-super": "error", 157 | "no-throw-literal": "error", 158 | "no-undef": "error", 159 | "no-undef-init": "error", 160 | "no-undefined": "off", 161 | "no-underscore-dangle": "error", 162 | "no-unexpected-multiline": "error", 163 | "no-unmodified-loop-condition": "error", 164 | "no-unneeded-ternary": "error", 165 | "no-unreachable": "error", 166 | "no-unreachable-loop": "error", 167 | "no-unsafe-finally": "error", 168 | "no-unsafe-negation": "error", 169 | "no-unsafe-optional-chaining": "error", 170 | "no-unused-expressions": "error", 171 | "no-unused-labels": "error", 172 | "no-unused-private-class-members": "error", 173 | "no-unused-vars": "error", 174 | "no-use-before-define": ["error", {"functions": false, "classes": true, "variables": true}], 175 | "no-useless-assignment": "error", 176 | "no-useless-backreference": "error", 177 | "no-useless-call": "error", 178 | "no-useless-catch": "error", 179 | "no-useless-computed-key": "error", 180 | "no-useless-concat": "error", 181 | "no-useless-constructor": "error", 182 | "no-useless-escape": "error", 183 | "no-useless-rename": "error", 184 | "no-useless-return": "error", 185 | "no-var": "off", 186 | "no-void": "error", 187 | "no-warning-comments": "error", 188 | "no-with": "error", 189 | "object-shorthand": ["error", "never"], 190 | "one-var": ["error", "never"], 191 | "operator-assignment": ["error", "never"], 192 | "prefer-arrow-callback": "off", 193 | "prefer-const": "off", 194 | "prefer-destructuring": "off", 195 | "prefer-exponentiation-operator": "off", 196 | "prefer-named-capture-group": "off", 197 | "prefer-numeric-literals": "error", 198 | "prefer-object-has-own": "off", 199 | "prefer-object-spread": "off", 200 | "prefer-promise-reject-errors": "off", 201 | "prefer-regex-literals": "error", 202 | "prefer-rest-params": "off", 203 | "prefer-spread": "off", 204 | "prefer-template": "off", 205 | "radix": ["error", "always"], 206 | "require-atomic-updates": "error", 207 | "require-await": "error", 208 | "require-unicode-regexp": "off", 209 | "require-yield": "error", 210 | "sort-imports": "error", 211 | "sort-keys": ["off"], 212 | "sort-vars": ["off"], 213 | "strict": "off", 214 | "symbol-description": "off", 215 | "unicode-bom": ["error", "never"], 216 | "use-isnan": "error", 217 | "valid-typeof": "error", 218 | "vars-on-top": "error", 219 | "yoda": "error", 220 | // eslint-stylistic:all 221 | "stylistic/array-bracket-newline": ["error", "consistent"], 222 | "stylistic/array-bracket-spacing": ["error", "never"], 223 | "stylistic/array-element-newline": ["error", "consistent"], 224 | "stylistic/arrow-parens": ["error", "always"], 225 | "stylistic/arrow-spacing": ["error", {"before": true, "after": true}], 226 | "stylistic/block-spacing": ["error", "always"], 227 | "stylistic/brace-style": ["error", "1tbs", {"allowSingleLine": false}], 228 | "stylistic/comma-dangle": ["error", "never"], 229 | "stylistic/comma-spacing": ["error", {"before": false, "after": true}], 230 | "stylistic/comma-style": ["error", "last"], 231 | "stylistic/computed-property-spacing": ["error", "never"], 232 | "stylistic/dot-location": ["error", "object"], 233 | "stylistic/eol-last": ["error", "always"], 234 | "stylistic/function-call-argument-newline": ["error", "consistent"], 235 | "stylistic/function-call-spacing": ["error", "never"], 236 | "stylistic/function-paren-newline": ["error", "consistent"], 237 | "stylistic/generator-star-spacing": ["error", 238 | { 239 | "before": false, 240 | "after": true, 241 | "anonymous": {"before": false, "after": true}, 242 | "method": {"before": true, "after": false} 243 | } 244 | ], 245 | "stylistic/implicit-arrow-linebreak": ["error", "beside"], 246 | "stylistic/indent": ["error", 4], 247 | "stylistic/indent-binary-ops": ["error", 4], 248 | "stylistic/key-spacing": ["error", 249 | { 250 | "beforeColon": false, 251 | "afterColon": true, 252 | "mode": "minimum", 253 | align: { 254 | "beforeColon": false, 255 | "afterColon": true, 256 | "on": "colon", 257 | "mode": "minimum" 258 | } 259 | } 260 | ], 261 | "stylistic/keyword-spacing": ["error", {"before": true, "after": true}], 262 | "stylistic/line-comment-position": ["error", {"position": "above", "ignorePattern": "BUILD REMOVE LINE"}], 263 | "stylistic/linebreak-style": ["error", "unix"], 264 | "stylistic/lines-around-comment": ["error", 265 | { 266 | "beforeBlockComment": true, 267 | "afterBlockComment": false, 268 | "beforeLineComment": true, 269 | "afterLineComment": false, 270 | "allowBlockStart": true, 271 | "allowBlockEnd": false, 272 | "allowClassStart": true, 273 | "allowClassEnd": false, 274 | "allowObjectStart": true, 275 | "allowObjectEnd": false, 276 | "allowArrayStart": true, 277 | "allowArrayEnd": false, 278 | "ignorePattern": "region|endregion|type" 279 | } 280 | ], 281 | "stylistic/lines-between-class-members": ["error", "always"], 282 | "stylistic/max-len": ["error", 283 | { 284 | "code": 180, 285 | "comments": 180, 286 | "ignorePattern": "global", 287 | "ignoreRegExpLiterals": true, 288 | "ignoreStrings": true, 289 | "ignoreTemplateLiterals": true, 290 | "ignoreTrailingComments": true, 291 | "ignoreUrls": true 292 | } 293 | ], 294 | "stylistic/max-statements-per-line": ["error", {"max": 1}], 295 | "stylistic/member-delimiter-style": ["error", 296 | { 297 | "multiline": { 298 | "delimiter": "comma", 299 | "requireLast": false 300 | }, 301 | "singleline": { 302 | "delimiter": "comma", 303 | "requireLast": false 304 | }, 305 | } 306 | ], 307 | "stylistic/multiline-comment-style": ["error", "starred-block"], 308 | "stylistic/multiline-ternary": ["error", "always-multiline"], 309 | "stylistic/new-parens": ["error", "always"], 310 | "stylistic/newline-per-chained-call": ["error", {"ignoreChainWithDepth": 5}], 311 | "stylistic/no-confusing-arrow": ["error", {"allowParens": false, "onlyOneSimpleParam": false}], 312 | "stylistic/no-extra-parens": "off", 313 | "stylistic/no-extra-semi": "error", 314 | "stylistic/no-floating-decimal": "error", 315 | "stylistic/no-mixed-operators": ["error", {"allowSamePrecedence": false}], 316 | "stylistic/no-mixed-spaces-and-tabs": "error", 317 | "stylistic/no-multi-spaces": ["error", {"ignoreEOLComments": false, "exceptions": {"Property": true}}], 318 | "stylistic/no-multiple-empty-lines": ["error", {"max": 1, "maxBOF": 0, "maxEOF": 1}], 319 | "stylistic/no-tabs": ["error", {"allowIndentationTabs": false}], 320 | "stylistic/no-trailing-spaces": ["error", {"ignoreComments": false, "skipBlankLines": false}], 321 | "stylistic/no-whitespace-before-property": "error", 322 | "stylistic/nonblock-statement-body-position": ["error", "below"], 323 | "stylistic/object-curly-newline": ["error", {"consistent": true}], 324 | "stylistic/object-curly-spacing": ["error", "never"], 325 | "stylistic/object-property-newline": ["error", {"allowAllPropertiesOnSameLine": true}], 326 | "stylistic/one-var-declaration-per-line": ["error", "always"], 327 | "stylistic/operator-linebreak": ["error", "after"], 328 | "stylistic/padded-blocks": ["error", "never"], 329 | "stylistic/padding-line-between-statements": ["error"], 330 | "stylistic/quote-props": ["error", "consistent-as-needed", {"keywords": true, "numbers": true}], 331 | "stylistic/quotes": ["error", "double"], 332 | "stylistic/rest-spread-spacing": ["error", "never"], 333 | "stylistic/semi": ["error", "always"], 334 | "stylistic/semi-spacing": ["error", {"before": false, "after": true}], 335 | "stylistic/semi-style": ["error", "last"], 336 | "stylistic/space-before-blocks": ["error"], 337 | "stylistic/space-before-function-paren": ["error", "never"], 338 | "stylistic/space-in-parens": ["error", "never"], 339 | "stylistic/space-infix-ops": ["error", {"int32Hint": false}], 340 | "stylistic/space-unary-ops": ["error"], 341 | "stylistic/spaced-comment": ["error", "always"], 342 | "stylistic/switch-colon-spacing": ["error", {"after": true, "before": false}], 343 | "stylistic/template-curly-spacing": ["error", "never"], 344 | "stylistic/template-tag-spacing": ["error", "never"], 345 | "stylistic/wrap-iife": ["error", "outside"], 346 | "stylistic/wrap-regex": "error", 347 | "stylistic/yield-star-spacing": ["error", {"before": false, "after": true}], 348 | // jsdoc:all 349 | "jsdoc/check-access": "error", 350 | "jsdoc/check-alignment": "error", 351 | "jsdoc/check-examples": "off", 352 | "jsdoc/check-indentation": "off", 353 | "jsdoc/check-line-alignment": ["error", "always", {"tags": ["param", "property"]}], 354 | "jsdoc/check-param-names": ["error", {"enableFixer": true, "checkDestructured": true, "useDefaultObjectProperties": true, "disableExtraPropertyReporting": true}], 355 | "jsdoc/check-property-names": ["error", {"enableFixer": true}], 356 | "jsdoc/check-syntax": "error", 357 | "jsdoc/check-tag-names": "error", 358 | "jsdoc/check-types": "error", 359 | "jsdoc/check-values": ["error"], 360 | "jsdoc/empty-tags": "error", 361 | "jsdoc/implements-on-classes": "error", 362 | "jsdoc/imports-as-dependencies": "error", 363 | "jsdoc/match-description": "error", 364 | "jsdoc/match-name": "off", 365 | "jsdoc/multiline-blocks": "error", 366 | "jsdoc/no-bad-blocks": "error", 367 | "jsdoc/no-blank-block-descriptions": "error", 368 | "jsdoc/no-blank-blocks": "error", 369 | "jsdoc/no-defaults": "error", 370 | "jsdoc/no-missing-syntax": "off", 371 | "jsdoc/no-multi-asterisks": "error", 372 | "jsdoc/no-restricted-syntax": "off", 373 | "jsdoc/no-types": "off", 374 | "jsdoc/no-undefined-types": "error", 375 | "jsdoc/require-asterisk-prefix": ["error", "always"], 376 | "jsdoc/require-description": "error", 377 | "jsdoc/require-description-complete-sentence": "off", 378 | "jsdoc/require-example": "off", 379 | "jsdoc/require-file-overview": "off", 380 | "jsdoc/require-hyphen-before-param-description": ["error", "always"], 381 | "jsdoc/require-jsdoc": "error", 382 | "jsdoc/require-param": "error", 383 | "jsdoc/require-param-description": "error", 384 | "jsdoc/require-param-name": "error", 385 | "jsdoc/require-param-type": "error", 386 | "jsdoc/require-property": "error", 387 | "jsdoc/require-property-description": "error", 388 | "jsdoc/require-property-name": "error", 389 | "jsdoc/require-property-type": "error", 390 | "jsdoc/require-returns": "error", 391 | "jsdoc/require-returns-check": "error", 392 | "jsdoc/require-returns-description": "off", 393 | "jsdoc/require-returns-type": "error", 394 | "jsdoc/require-throws": "error", 395 | "jsdoc/require-yields": "error", 396 | "jsdoc/require-yields-check": "error", 397 | "jsdoc/sort-tags": ["error", {"tagSequence": [ 398 | {tags: [ 399 | // Brief descriptions 400 | "summary", 401 | "typeSummary", 402 | 403 | // Module/file-level 404 | "module", 405 | "exports", 406 | "file", 407 | "fileoverview", 408 | "overview", 409 | "import", 410 | 411 | // Identifying (name, type) 412 | "typedef", 413 | "interface", 414 | "record", 415 | "template", 416 | "name", 417 | "kind", 418 | "type", 419 | "alias", 420 | "external", 421 | "host", 422 | "callback", 423 | "func", 424 | "function", 425 | "method", 426 | "class", 427 | "constructor", 428 | 429 | // Relationships 430 | "modifies", 431 | "mixes", 432 | "mixin", 433 | "mixinClass", 434 | "mixinFunction", 435 | "namespace", 436 | "borrows", 437 | "constructs", 438 | "lends", 439 | "implements", 440 | "requires", 441 | 442 | // Long descriptions 443 | "desc", 444 | "description", 445 | "classdesc", 446 | "tutorial", 447 | "copyright", 448 | "license", 449 | 450 | // Simple annotations 451 | "const", 452 | "constant", 453 | "final", 454 | "global", 455 | "readonly", 456 | "abstract", 457 | "virtual", 458 | "var", 459 | "member", 460 | "memberof", 461 | "memberof!", 462 | "inner", 463 | "instance", 464 | "inheritdoc", 465 | "inheritDoc", 466 | "override", 467 | "hideconstructor", 468 | 469 | // Core function/object info 470 | "param", 471 | "arg", 472 | "argument", 473 | "prop", 474 | "property", 475 | "return", 476 | "returns", 477 | 478 | // Important behavior details 479 | "async", 480 | "generator", 481 | "default", 482 | "defaultvalue", 483 | "enum", 484 | "augments", 485 | "extends", 486 | "throws", 487 | "exception", 488 | "yield", 489 | "yields", 490 | "event", 491 | "fires", 492 | "emits", 493 | "listens", 494 | "this", 495 | 496 | // Access 497 | "static", 498 | "private", 499 | "protected", 500 | "public", 501 | "access", 502 | "package", 503 | 504 | "-other", 505 | 506 | // Supplementary descriptions 507 | "see", 508 | "example", 509 | 510 | // METADATA 511 | 512 | // Other Closure (undocumented) metadata 513 | "closurePrimitive", 514 | "customElement", 515 | "expose", 516 | "hidden", 517 | "idGenerator", 518 | "meaning", 519 | "ngInject", 520 | "owner", 521 | "wizaction", 522 | 523 | // Other Closure (documented) metadata 524 | "define", 525 | "dict", 526 | "export", 527 | "externs", 528 | "implicitCast", 529 | "noalias", 530 | "nocollapse", 531 | "nocompile", 532 | "noinline", 533 | "nosideeffects", 534 | "polymer", 535 | "polymerBehavior", 536 | "preserve", 537 | "struct", 538 | "suppress", 539 | "unrestricted", 540 | 541 | // @homer0/prettier-plugin-jsdoc metadata 542 | "category", 543 | 544 | // Non-Closure metadata 545 | "ignore", 546 | "author", 547 | "version", 548 | "variation", 549 | "since", 550 | "deprecated", 551 | "todo", 552 | ]} 553 | ]}], 554 | "jsdoc/tag-lines": ["error", "any", {"startLines": 1}], 555 | "jsdoc/text-escaping": "off", 556 | "jsdoc/valid-types": "off" 557 | }, 558 | }, 559 | { 560 | files: ["tests/*.js"], 561 | languageOptions: { 562 | ecmaVersion: "latest", 563 | globals: { 564 | ...globals.browser, 565 | ...globals.jest, 566 | ...globals.es2015, 567 | ...globals.node, 568 | Promise: "off", 569 | }, 570 | }, 571 | plugins: { 572 | jest: jest, 573 | stylistic: stylistic, 574 | }, 575 | rules: { 576 | // eslint:recommended 577 | "constructor-super": "error", 578 | "for-direction": "error", 579 | "getter-return": "error", 580 | "no-async-promise-executor": "error", 581 | "no-case-declarations": "error", 582 | "no-class-assign": "error", 583 | "no-compare-neg-zero": "error", 584 | "no-cond-assign": "error", 585 | "no-const-assign": "error", 586 | "no-constant-binary-expression": "error", 587 | "no-constant-condition": "error", 588 | "no-control-regex": "error", 589 | "no-debugger": "error", 590 | "no-delete-var": "error", 591 | "no-dupe-args": "error", 592 | "no-dupe-class-members": "error", 593 | "no-dupe-else-if": "error", 594 | "no-dupe-keys": "error", 595 | "no-duplicate-case": "error", 596 | "no-empty": "error", 597 | "no-empty-character-class": "error", 598 | "no-empty-pattern": "error", 599 | "no-empty-static-block": "error", 600 | "no-ex-assign": "error", 601 | "no-extra-boolean-cast": "error", 602 | "no-fallthrough": "error", 603 | "no-func-assign": "error", 604 | "no-global-assign": "error", 605 | "no-import-assign": "error", 606 | "no-invalid-regexp": "error", 607 | "no-irregular-whitespace": "error", 608 | "no-loss-of-precision": "error", 609 | "no-misleading-character-class": "error", 610 | "no-new-native-nonconstructor": "error", 611 | "no-nonoctal-decimal-escape": "error", 612 | "no-obj-calls": "error", 613 | "no-octal": "error", 614 | "no-prototype-builtins": "error", 615 | "no-redeclare": "error", 616 | "no-regex-spaces": "error", 617 | "no-self-assign": "error", 618 | "no-setter-return": "error", 619 | "no-shadow-restricted-names": "error", 620 | "no-sparse-arrays": "error", 621 | "no-this-before-super": "error", 622 | "no-undef": "error", 623 | "no-unexpected-multiline": "error", 624 | "no-unreachable": "error", 625 | "no-unsafe-finally": "error", 626 | "no-unsafe-negation": "error", 627 | "no-unsafe-optional-chaining": "error", 628 | "no-unused-labels": "error", 629 | "no-unused-private-class-members": "error", 630 | "no-unused-vars": "error", 631 | "no-useless-backreference": "error", 632 | "no-useless-catch": "error", 633 | "no-useless-escape": "error", 634 | "no-with": "error", 635 | "require-yield": "error", 636 | "use-isnan": "error", 637 | "valid-typeof": "error", 638 | // eslint-stylistic:recommended 639 | "stylistic/array-bracket-spacing": ["error", "never"], 640 | "stylistic/arrow-parens": ["error", "always"], 641 | "stylistic/arrow-spacing": ["error", {"before": true, "after": true}], 642 | "stylistic/block-spacing": ["error", "always"], 643 | "stylistic/brace-style": ["error", "1tbs", {"allowSingleLine": true}], 644 | "stylistic/comma-dangle": ["error", "never"], 645 | "stylistic/comma-spacing": ["error", {"before": false, "after": true}], 646 | "stylistic/comma-style": ["error", "last"], 647 | "stylistic/computed-property-spacing": ["error", "never"], 648 | "stylistic/dot-location": ["error", "object"], 649 | "stylistic/eol-last": ["error", "always"], 650 | "stylistic/indent": ["error", 4], 651 | "stylistic/indent-binary-ops": ["error", 4], 652 | "stylistic/key-spacing": ["error", 653 | { 654 | "beforeColon": false, 655 | "afterColon": true, 656 | "mode": "minimum", 657 | align: { 658 | "beforeColon": false, 659 | "afterColon": true, 660 | "on": "colon", 661 | "mode": "minimum" 662 | } 663 | } 664 | ], 665 | "stylistic/keyword-spacing": ["error", {"before": true, "after": true}], 666 | "stylistic/lines-between-class-members": ["error", "always"], 667 | "stylistic/max-statements-per-line": ["error", {"max": 1}], 668 | "stylistic/member-delimiter-style": ["error", 669 | { 670 | "multiline": { 671 | "delimiter": "comma", 672 | "requireLast": false 673 | }, 674 | "singleline": { 675 | "delimiter": "comma", 676 | "requireLast": false 677 | }, 678 | } 679 | ], 680 | "stylistic/multiline-ternary": ["error", "always-multiline"], 681 | "stylistic/new-parens": ["error", "always"], 682 | "stylistic/no-extra-parens": "off", 683 | "stylistic/no-floating-decimal": "error", 684 | "stylistic/no-mixed-operators": ["error", {"allowSamePrecedence": false}], 685 | "stylistic/no-mixed-spaces-and-tabs": "error", 686 | "stylistic/no-multi-spaces": ["error", {"ignoreEOLComments": false, "exceptions": {"Property": true}}], 687 | "stylistic/no-multiple-empty-lines": ["error", {"max": 1, "maxBOF": 0, "maxEOF": 1}], 688 | "stylistic/no-tabs": ["error", {"allowIndentationTabs": false}], 689 | "stylistic/no-trailing-spaces": ["error", {"ignoreComments": false, "skipBlankLines": false}], 690 | "stylistic/no-whitespace-before-property": "error", 691 | "stylistic/object-curly-spacing": ["error", "never"], 692 | "stylistic/operator-linebreak": ["error", "after"], 693 | "stylistic/padded-blocks": ["error", "never"], 694 | "stylistic/quote-props": ["error", "consistent-as-needed", {"keywords": true, "numbers": true}], 695 | "stylistic/quotes": ["error", "double", {"allowTemplateLiterals": true}], 696 | "stylistic/rest-spread-spacing": ["error", "never"], 697 | "stylistic/semi": ["error", "always"], 698 | "stylistic/semi-spacing": ["error", {"before": false, "after": true}], 699 | "stylistic/space-before-blocks": ["error"], 700 | "stylistic/space-before-function-paren": ["error", "never"], 701 | "stylistic/space-in-parens": ["error", "never"], 702 | "stylistic/space-infix-ops": ["error", {"int32Hint": false}], 703 | "stylistic/space-unary-ops": ["error"], 704 | "stylistic/spaced-comment": ["error", "always"], 705 | "stylistic/template-curly-spacing": ["error", "never"], 706 | "stylistic/template-tag-spacing": ["error", "never"], 707 | "stylistic/wrap-iife": ["error", "outside"], 708 | "stylistic/yield-star-spacing": ["error", {"before": false, "after": true}], 709 | // jest:recommended 710 | "jest/expect-expect": "warn", 711 | "jest/no-alias-methods": "error", 712 | "jest/no-commented-out-tests": "warn", 713 | "jest/no-conditional-expect": "error", 714 | "jest/no-deprecated-functions": "error", 715 | "jest/no-disabled-tests": "warn", 716 | "jest/no-done-callback": "error", 717 | "jest/no-export": "error", 718 | "jest/no-focused-tests": "error", 719 | "jest/no-identical-title": "error", 720 | "jest/no-interpolation-in-snapshots": "error", 721 | "jest/no-jasmine-globals": "error", 722 | "jest/no-mocks-import": "error", 723 | "jest/no-standalone-expect": "error", 724 | "jest/no-test-prefixes": "error", 725 | "jest/valid-describe-callback": "error", 726 | "jest/valid-expect": "error", 727 | "jest/valid-expect-in-promise": "error", 728 | "jest/valid-title": "error" 729 | }, 730 | } 731 | ]; 732 | -------------------------------------------------------------------------------- /jsdoc.conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "opts": { 3 | "encoding": "utf8", 4 | "destination": "./jsdoc/", 5 | "pedantic": true, 6 | "private": true, 7 | "recurse": true 8 | }, 9 | "plugins": [], 10 | "recurseDepth": 5, 11 | "source": { 12 | "include": [ 13 | "./src/js" 14 | ], 15 | "includePattern": ".js$", 16 | "excludePattern": "", 17 | "exclude": [ 18 | "node_modules", 19 | "dist", 20 | "demo", 21 | "tests", 22 | "coverage" 23 | ] 24 | }, 25 | "sourceType": "module", 26 | "tags": { 27 | "allowUnknownTags": false, 28 | "dictionaries": ["jsdoc","closure"] 29 | }, 30 | "templates": { 31 | "cleverLinks": true, 32 | "monospaceLinks": true, 33 | "default": { 34 | "outputSourceFiles": false 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "uasset-reader-js", 3 | "version": "1.1.2", 4 | "description": "Read .uasset files from Unreal Engine in javascript", 5 | "scripts": { 6 | "test": "jest --coverage --coverageDirectory=./coverage -- tests/main.test.js", 7 | "build": "node build.cjs && uglifyjs dist/uasset-reader.js --mangle --webkit --compress \"drop_console=true,module=false,passes=5\" --comments \"/MIT License/\" -o dist/uasset-reader.min.js && jest", 8 | "jsdoc": "jsdoc -c jsdoc.conf.json", 9 | "eslint": "eslint --max-warnings=0 src/**/*.js tests/*.js", 10 | "eslint:fix": "eslint --fix src/**/*.js tests/*.js" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "git+https://github.com/blueprintue/uasset-reader-js.git" 15 | }, 16 | "author": "Sébastien Rancoud ", 17 | "license": "MIT", 18 | "bugs": { 19 | "url": "https://github.com/blueprintue/uasset-reader-js/issues" 20 | }, 21 | "homepage": "https://github.com/blueprintue/uasset-reader-js", 22 | "devDependencies": { 23 | "@babel/core": "^7.27.4", 24 | "@stylistic/eslint-plugin": "^4.4.1", 25 | "@types/jest": "^29.5.14", 26 | "eslint": "^9.28.0", 27 | "eslint-plugin-jest": "^28.13.0", 28 | "eslint-plugin-jsdoc": "^50.7.1", 29 | "globals": "^16.2.0", 30 | "jest": "^29.7.0", 31 | "jest-environment-jsdom": "^29.7.0", 32 | "jsdoc": "^4.0.4", 33 | "uglify-js": "^3.19.3" 34 | }, 35 | "type": "module", 36 | "engines": { 37 | "npm": ">=10.7.0", 38 | "node": ">=22.1.0" 39 | }, 40 | "jest": { 41 | "testEnvironment": "jsdom" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/js/_namespace_.js: -------------------------------------------------------------------------------- 1 | /* istanbul ignore else */ 2 | if (window.blueprintUE === undefined) { 3 | /** 4 | * This namespace is attached to `window`.
5 | * It's the main namespace leading to another namespace called `render`. 6 | * 7 | * @namespace 8 | */ 9 | window.blueprintUE = {}; 10 | } 11 | /* istanbul ignore else */ 12 | if (window.blueprintUE.uasset === undefined) { 13 | /** 14 | * This namespace is attached to `window.blueprintUE`.
15 | * It will only expose the `Main` class.
16 | * 17 | * @namespace 18 | */ 19 | window.blueprintUE.uasset = {}; 20 | } 21 | 22 | /** 23 | * Uasset structure. 24 | * 25 | * @typedef Uasset 26 | * @property {HexView[]} hexView - list of bytes read with position and type in file 27 | * @property {object} header - header file 28 | * @property {Name[]} names - to fill 29 | * @property {GatherableTextData[]} gatherableTextData - to fill 30 | * @property {object} imports - to fill 31 | * @property {object} exports - to fill 32 | * @property {object} depends - to fill 33 | * @property {object} softPackageReferences - to fill 34 | * @property {object} searchableNames - to fill 35 | * @property {Thumbnails} thumbnails - to fill 36 | * @property {object} assetRegistryData - to fill 37 | * @property {object} preloadDependency - to fill 38 | * @property {object} bulkDataStart - to fill 39 | */ 40 | 41 | /** 42 | * HexView structure. 43 | * 44 | * @typedef HexView 45 | * @property {string} key - name of what we read 46 | * @property {string} type - type name of what we read (int16, int32, etc...) 47 | * @property {string} value - value read 48 | * @property {number} start - start position in the file 49 | * @property {number} stop - stop position in the file 50 | */ 51 | 52 | /** 53 | * Name structure. 54 | * 55 | * @typedef Name 56 | * @property {string} Name - value 57 | * @property {number} NonCasePreservingHash - hash of value with case non preserved (upper) 58 | * @property {number} CasePreservingHash - hash of value with case preserved 59 | */ 60 | 61 | // region GatherableTextData 62 | /** 63 | * GatherableTextData Structure. 64 | * 65 | * @typedef GatherableTextData 66 | * @property {string} NamespaceName - to fill 67 | * @property {SourceData} SourceData - to fill 68 | * @property {SourceSiteContexts[]} SourceSiteContexts - to fill 69 | */ 70 | 71 | /** 72 | * SourceData Structure. 73 | * 74 | * @typedef SourceData 75 | * @property {string} SourceString - to fill 76 | * @property {GatherableTextDataMetadata} SourceStringMetaData - to fill 77 | */ 78 | 79 | /** 80 | * SourceSiteContexts Structure. 81 | * 82 | * @typedef SourceSiteContexts 83 | * @property {string} KeyName - to fill 84 | * @property {string} SiteDescription - to fill 85 | * @property {number} IsEditorOnly - to fill 86 | * @property {number} IsOptional - to fill 87 | * @property {GatherableTextDataMetadata} InfoMetaData - to fill 88 | * @property {GatherableTextDataMetadata} KeyMetaData - to fill 89 | */ 90 | 91 | /** 92 | * GatherableTextDataMetadata Structure. 93 | * 94 | * @typedef GatherableTextDataMetadata 95 | * @property {number} ValueCount - to fill 96 | * @property {any[]} Values - to fill 97 | */ 98 | // endregion 99 | 100 | // region Thumbnails 101 | /** 102 | * Thumbnails Structure. 103 | * 104 | * @typedef Thumbnails 105 | * @property {ThumbnailsIndex[]} Index - index 106 | * @property {ThumbnailsThumbnails[]} Thumbnails - thumbnails 107 | */ 108 | 109 | /** 110 | * Thumbnails Index Structure 111 | * 112 | * @typedef ThumbnailsIndex 113 | * @property {string} AssetClassName - class name 114 | * @property {string} ObjectPathWithoutPackageName - path 115 | * @property {number} FileOffset - position in file 116 | */ 117 | 118 | /** 119 | * Thumbnails Thumbnails Structure 120 | * 121 | * @typedef ThumbnailsThumbnails 122 | * @property {number} ImageWidth - width 123 | * @property {number} ImageHeight - height 124 | * @property {string} ImageFormat - format (PNG or JPEG) 125 | * @property {number} ImageSizeData - how many bytes used in file 126 | * @property {number[]} ImageData - raw data 127 | */ 128 | // endregion 129 | -------------------------------------------------------------------------------- /src/js/main.js: -------------------------------------------------------------------------------- 1 | /* global DataView, EPackageFileTag, EUnrealEngineObjectUE4Version, EUnrealEngineObjectUE5Version, GatherableTextData, SourceSiteContexts, Uasset, Uint8Array */ 2 | /** 3 | * Main public entry point. 4 | * 5 | * @class ReaderUasset 6 | */ 7 | function ReaderUasset() { 8 | this.currentIdx = 0; 9 | this.bytes = []; 10 | 11 | /** @type {Uasset} */ 12 | this.uasset = { 13 | hexView : [], 14 | header : {}, 15 | names : [], 16 | gatherableTextData : [], 17 | imports : {}, 18 | exports : [], 19 | depends : {}, 20 | softPackageReferences: {}, 21 | searchableNames : {}, 22 | thumbnails : {Index: [], Thumbnails: []}, 23 | assetRegistryData : {}, 24 | preloadDependency : {}, 25 | bulkDataStart : {} 26 | }; 27 | } 28 | 29 | // region helpers 30 | /** 31 | * Read 2 bytes, save in hex view and return value as uint16 en littleEndian. 32 | * 33 | * @function ReaderUasset#uint16 34 | * @param {string} key - name of what we read 35 | * @returns {number} 36 | * @private 37 | */ 38 | ReaderUasset.prototype.uint16 = function uint16(key) { 39 | /** @type {number} */ 40 | var val; 41 | /** @type {number[]} */ 42 | var bytes = this.readCountBytes(2); 43 | 44 | val = new DataView(new Uint8Array(bytes).buffer).getUint16(0, this.useLittleEndian); 45 | 46 | this.addHexView(key, "uint16", val, this.currentIdx - 2, this.currentIdx - 1); 47 | 48 | return val; 49 | }; 50 | 51 | /** 52 | * Read 4 bytes, save in hex view and return value as int32 en littleEndian. 53 | * 54 | * @function ReaderUasset#int32 55 | * @param {string} key - name of what we read 56 | * @returns {number} 57 | * @private 58 | */ 59 | ReaderUasset.prototype.int32 = function int32(key) { 60 | /** @type {number} */ 61 | var val; 62 | /** @type {number[]} */ 63 | var bytes = this.readCountBytes(4); 64 | 65 | val = new DataView(new Uint8Array(bytes).buffer).getInt32(0, this.useLittleEndian); 66 | 67 | this.addHexView(key, "int32", val, this.currentIdx - 4, this.currentIdx - 1); 68 | 69 | return val; 70 | }; 71 | 72 | /** 73 | * Read 4 bytes, save in hex view and return value as uint32 en littleEndian. 74 | * 75 | * @function ReaderUasset#uint32 76 | * @param {string} key - name of what we read 77 | * @returns {number} 78 | * @private 79 | */ 80 | ReaderUasset.prototype.uint32 = function uint32(key) { 81 | /** @type {number} */ 82 | var val; 83 | /** @type {number[]} */ 84 | var bytes = this.readCountBytes(4); 85 | 86 | val = new DataView(new Uint8Array(bytes).buffer).getUint32(0, this.useLittleEndian); 87 | 88 | this.addHexView(key, "uint32", val, this.currentIdx - 4, this.currentIdx - 1); 89 | 90 | return val; 91 | }; 92 | 93 | /** 94 | * Read 8 bytes, save in hex view and return value as int64 en littleEndian. 95 | * 96 | * @function ReaderUasset#int64 97 | * @param {string} key - name of what we read 98 | * @returns {number} 99 | * @private 100 | */ 101 | ReaderUasset.prototype.int64 = function int64(key) { 102 | /** @type {bigint} */ 103 | var val; 104 | /** @type {number[]} */ 105 | var bytes = this.readCountBytes(8); 106 | 107 | val = new DataView(new Uint8Array(bytes).buffer).getBigInt64(0, this.useLittleEndian); 108 | 109 | this.addHexView(key, "int64", val, this.currentIdx - 8, this.currentIdx - 1); 110 | 111 | return val; 112 | }; 113 | 114 | /** 115 | * Read 8 bytes, save in hex view and return value as uint64 en littleEndian. 116 | * 117 | * @function ReaderUasset#uint64 118 | * @param {string} key - name of what we read 119 | * @returns {number} 120 | * @private 121 | */ 122 | ReaderUasset.prototype.uint64 = function uint64(key) { 123 | /** @type {bigint} */ 124 | var val; 125 | /** @type {number[]} */ 126 | var bytes = this.readCountBytes(8); 127 | 128 | val = new DataView(new Uint8Array(bytes).buffer).getBigUint64(0, this.useLittleEndian); 129 | 130 | this.addHexView(key, "uint64", val, this.currentIdx - 8, this.currentIdx - 1); 131 | 132 | return val; 133 | }; 134 | 135 | /** 136 | * Read 16 bytes, save in hex view and return value as string. 137 | * 138 | * @function ReaderUasset#fguidSlot 139 | * @param {string} key - name of what we read 140 | * @returns {string} 141 | * @private 142 | */ 143 | ReaderUasset.prototype.fguidSlot = function fguidSlot(key) { 144 | /** @type {string} */ 145 | var val; 146 | /** @type {string} */ 147 | var str1 = ""; 148 | /** @type {string} */ 149 | var str2 = ""; 150 | /** @type {string} */ 151 | var str3 = ""; 152 | /** @type {string} */ 153 | var str4 = ""; 154 | /** @type {number} */ 155 | var idx = 3; 156 | /** @type {number[]} */ 157 | var bytes = this.readCountBytes(16); 158 | 159 | for (; idx >= 0; --idx) { 160 | str1 = str1 + bytes[idx].toString(16).padStart(2, "0"); 161 | str2 = str2 + bytes[idx + 4].toString(16).padStart(2, "0"); 162 | str3 = str3 + bytes[idx + 8].toString(16).padStart(2, "0"); 163 | str4 = str4 + bytes[idx + 12].toString(16).padStart(2, "0"); 164 | } 165 | 166 | val = (str1 + str2 + str3 + str4).toUpperCase(); 167 | 168 | this.addHexView(key, "fguidSlot", val, this.currentIdx - 16, this.currentIdx - 1); 169 | 170 | return val; 171 | }; 172 | 173 | /** 174 | * Read 16 bytes, save in hex view and return value as string. 175 | * 176 | * @function ReaderUasset#fguidString 177 | * @param {string} key - name of what we read 178 | * @returns {string} 179 | * @private 180 | */ 181 | ReaderUasset.prototype.fguidString = function fguidString(key) { 182 | /** @type {string} */ 183 | var val; 184 | /** @type {string} */ 185 | var str = ""; 186 | /** @type {number} */ 187 | var idx = 0; 188 | /** @type {number[]} */ 189 | var bytes = this.readCountBytes(16); 190 | 191 | for (; idx < 16; ++idx) { 192 | str = str + bytes[idx].toString(16).padStart(2, "0"); 193 | } 194 | 195 | val = str.toUpperCase(); 196 | 197 | this.addHexView(key, "fguidString", val, this.currentIdx - 16, this.currentIdx - 1); 198 | 199 | return val; 200 | }; 201 | 202 | /** 203 | * Read 16 bytes, save in hex view and return value as string. 204 | * 205 | * @function ReaderUasset#fstring 206 | * @param {string} key - name of what we read 207 | * @returns {string} 208 | * @private 209 | */ 210 | ReaderUasset.prototype.fstring = function fstring(key) { 211 | /** @type {string} */ 212 | var val; 213 | /** @type {number[]} */ 214 | var bytes; 215 | /** @type {string} */ 216 | var str = ""; 217 | /** @type {number} */ 218 | var counter = 0; 219 | /** @type {number[]} */ 220 | var output = []; 221 | /** @type {string} */ 222 | var value; 223 | /** @type {string} */ 224 | var extra; 225 | /** @type {number} */ 226 | var idx; 227 | /** @type {number} */ 228 | var startPosition; 229 | 230 | var length = this.int32(key + " (fstring length)"); 231 | if (length === 0) { 232 | return ""; 233 | } 234 | 235 | startPosition = this.currentIdx; 236 | 237 | if (length > 0) { 238 | bytes = this.readCountBytes(length); 239 | for (idx = 0; idx < bytes.length - 1; ++idx) { 240 | str = str + String.fromCharCode(bytes[idx]); 241 | } 242 | 243 | val = str; 244 | 245 | this.addHexView(key, "fstring", val, startPosition, this.currentIdx - 1); 246 | 247 | return str; 248 | } 249 | 250 | /* eslint-disable */ 251 | length = length * -1 * 2; 252 | bytes = this.readCountBytes(length); 253 | while (counter < bytes.length) { 254 | value = String.fromCharCode(bytes[counter++]); 255 | if (value >= 0xD800 && value <= 0xDBFF && counter < bytes.length) { 256 | extra = String.fromCharCode(bytes[counter++]); 257 | if ((extra & 0xFC00) === 0xDC00) { 258 | output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000); 259 | } else { 260 | output.push(value); 261 | counter--; 262 | } 263 | } else { 264 | output.push(value); 265 | } 266 | } 267 | /* eslint-enable */ 268 | 269 | val = output.join(""); 270 | 271 | this.addHexView(key, "fstring", val, startPosition, this.currentIdx - 1); 272 | 273 | return val; 274 | }; 275 | 276 | /** 277 | * Read n bytes. 278 | * 279 | * @function ReaderUasset#readCountBytes 280 | * @param {number} count - number of bytes to read. 281 | * @returns {number[]} 282 | * @private 283 | */ 284 | ReaderUasset.prototype.readCountBytes = function readCountBytes(count) { 285 | var bytes = []; 286 | var idx = 0; 287 | 288 | for (; idx < count; ++idx) { 289 | bytes.push(this.bytes[this.currentIdx]); 290 | this.currentIdx = this.currentIdx + 1; 291 | } 292 | 293 | return bytes; 294 | }; 295 | 296 | /** 297 | * Add informations in HexView struct. 298 | * 299 | * @function ReaderUasset#addHexView 300 | * @param {string} key - name of what we read 301 | * @param {string} type - type name of what we read (int16, int32, etc...) 302 | * @param {string} value - value read 303 | * @param {number} startPosition - start position in the file 304 | * @param {number} stopPosition - stop position in the file 305 | * @returns {undefined} 306 | * @private 307 | */ 308 | ReaderUasset.prototype.addHexView = function addHexView(key, type, value, startPosition, stopPosition) { /* eslint-disable-line max-params */ 309 | if (this.saveHexView === false) { 310 | return; 311 | } 312 | 313 | this.uasset.hexView.push({ 314 | key : key, 315 | type : type, 316 | value: value, 317 | start: startPosition, 318 | stop : stopPosition 319 | }); 320 | }; 321 | 322 | /** 323 | * Resolve FName. 324 | * 325 | * @function ReaderUasset#resolveFName 326 | * @param {number} idx - name of what we read 327 | * @returns {string} 328 | * @private 329 | */ 330 | ReaderUasset.prototype.resolveFName = function resolveFName(idx) { 331 | if (this.uasset.names[idx]) { 332 | return this.uasset.names[idx].Name; 333 | } 334 | 335 | return ""; 336 | }; 337 | // endregion 338 | 339 | /** 340 | * Read Header. 341 | * 342 | * @function ReaderUasset#readHeader 343 | * @returns {(Error|undefined)} 344 | * @private 345 | * @see https://github.com/EpicGames/UnrealEngine/blob/5.0/Engine/Source/Runtime/CoreUObject/Private/UObject/PackageFileSummary.cpp#L48 346 | */ 347 | /* eslint-disable-next-line max-lines-per-function,max-statements,complexity */ 348 | ReaderUasset.prototype.readHeader = function readHeader() { 349 | /** @type {number} */ 350 | var idx; 351 | /** @type {number} */ 352 | var count; 353 | 354 | // Check file is uasset 355 | this.uasset.header.EPackageFileTag = this.uint32("EPackageFileTag"); 356 | if (this.uasset.header.EPackageFileTag === EPackageFileTag.PACKAGE_FILE_TAG_SWAPPED) { 357 | // The package has been stored in a separate endianness 358 | this.useLittleEndian = false; 359 | } 360 | 361 | if (this.uasset.header.EPackageFileTag !== EPackageFileTag.PACKAGE_FILE_TAG && 362 | this.uasset.header.EPackageFileTag !== EPackageFileTag.PACKAGE_FILE_TAG_SWAPPED) { 363 | return new Error("invalid uasset"); 364 | } 365 | 366 | /** 367 | * Check file is not UE3 368 | * 369 | * The package file version number when this package was saved. 370 | * 371 | * Lower 16 bits stores the UE3 engine version 372 | * Upper 16 bits stores the UE licensee version 373 | * For newer packages this is -7:
374 | * -2 indicates presence of enum-based custom versions
375 | * -3 indicates guid-based custom versions
376 | * -4 indicates removal of the UE3 version. Packages saved with this ID cannot be loaded in older engine versions
377 | * -5 indicates the replacement of writing out the "UE3 version" so older versions of engine can gracefully fail to open newer packages
378 | * -6 indicates optimizations to how custom versions are being serialized
379 | * -7 indicates the texture allocation info has been removed from the summary
380 | * -8 indicates that the UE5 version has been added to the summary 381 | */ 382 | this.uasset.header.LegacyFileVersion = this.int32("LegacyFileVersion"); 383 | /* eslint-disable-next-line no-magic-numbers */ 384 | if (this.uasset.header.LegacyFileVersion !== -6 && this.uasset.header.LegacyFileVersion !== -7 && this.uasset.header.LegacyFileVersion !== -8) { 385 | return new Error("unsupported version"); 386 | } 387 | 388 | /** 389 | * Next bytes is for UE3 390 | * No need to check because it will always be different of -4 391 | */ 392 | this.uasset.header.LegacyUE3Version = this.int32("LegacyUE3Version"); 393 | 394 | // Check file is valid UE4 395 | this.uasset.header.FileVersionUE4 = this.int32("FileVersionUE4"); 396 | 397 | // Check valid UE5 398 | /* eslint-disable-next-line no-magic-numbers */ 399 | if (this.uasset.header.LegacyFileVersion <= -8) { 400 | this.uasset.header.FileVersionUE5 = this.int32("FileVersionUE5"); 401 | } 402 | 403 | this.uasset.header.FileVersionLicenseeUE4 = this.int32("FileVersionLicenseeUE4"); 404 | if (this.uasset.header.FileVersionUE4 === 0 && this.uasset.header.FileVersionLicenseeUE4 === 0 && this.uasset.header.FileVersionUE5 === 0) { 405 | return new Error("asset unversioned"); 406 | } 407 | 408 | count = this.int32("CustomVersions Count"); 409 | this.uasset.header.CustomVersions = []; 410 | for (idx = 0; idx < count; ++idx) { 411 | this.uasset.header.CustomVersions.push({ 412 | key : this.fguidSlot("CustomVersions #" + idx + ": key"), 413 | version: this.int32("CustomVersions #" + idx + ": version") 414 | }); 415 | } 416 | 417 | this.uasset.header.TotalHeaderSize = this.int32("TotalHeaderSize"); 418 | 419 | this.uasset.header.FolderName = this.fstring("FolderName"); 420 | 421 | this.uasset.header.PackageFlags = this.uint32("PackageFlags"); 422 | 423 | this.uasset.header.NameCount = this.int32("NameCount"); 424 | this.uasset.header.NameOffset = this.int32("NameOffset"); 425 | 426 | if (this.uasset.header.FileVersionUE5 >= EUnrealEngineObjectUE5Version.VER_UE5_ADD_SOFTOBJECTPATH_LIST.value) { 427 | this.uasset.header.SoftObjectPathsCount = this.uint32("SoftObjectPathsCount"); 428 | this.uasset.header.SoftObjectPathsOffset = this.uint32("SoftObjectPathsOffset"); 429 | } 430 | 431 | if (this.uasset.header.FileVersionUE4 >= EUnrealEngineObjectUE4Version.VER_UE4_ADDED_PACKAGE_SUMMARY_LOCALIZATION_ID.value) { 432 | this.uasset.header.LocalizationId = this.fstring("LocalizationId"); 433 | } 434 | 435 | if (this.uasset.header.FileVersionUE4 >= EUnrealEngineObjectUE4Version.VER_UE4_SERIALIZE_TEXT_IN_PACKAGES.value) { 436 | this.uasset.header.GatherableTextDataCount = this.int32("GatherableTextDataCount"); 437 | this.uasset.header.GatherableTextDataOffset = this.int32("GatherableTextDataOffset"); 438 | } 439 | 440 | this.uasset.header.ExportCount = this.int32("ExportCount"); 441 | this.uasset.header.ExportOffset = this.int32("ExportOffset"); 442 | 443 | this.uasset.header.ImportCount = this.int32("ImportCount"); 444 | this.uasset.header.ImportOffset = this.int32("ImportOffset"); 445 | 446 | this.uasset.header.DependsOffset = this.int32("DependsOffset"); 447 | 448 | if (this.uasset.header.FileVersionUE4 < EUnrealEngineObjectUE4Version.VER_UE4_OLDEST_LOADABLE_PACKAGE.value) { 449 | return new Error("asset too old"); 450 | } 451 | 452 | if (this.uasset.header.FileVersionUE4 >= EUnrealEngineObjectUE4Version.VER_UE4_ADD_STRING_ASSET_REFERENCES_MAP.value) { 453 | this.uasset.header.SoftPackageReferencesCount = this.int32("SoftPackageReferencesCount"); 454 | this.uasset.header.SoftPackageReferencesOffset = this.int32("SoftPackageReferencesOffset"); 455 | } 456 | 457 | if (this.uasset.header.FileVersionUE4 >= EUnrealEngineObjectUE4Version.VER_UE4_ADDED_SEARCHABLE_NAMES.value) { 458 | this.uasset.header.SearchableNamesOffset = this.int32("SearchableNamesOffset"); 459 | } 460 | 461 | this.uasset.header.ThumbnailTableOffset = this.int32("ThumbnailTableOffset"); 462 | 463 | this.uasset.header.Guid = this.fguidString("Guid"); 464 | 465 | if (this.uasset.header.FileVersionUE4 >= EUnrealEngineObjectUE4Version.VER_UE4_ADDED_PACKAGE_OWNER.value) { 466 | this.uasset.header.PersistentGuid = this.fguidString("PersistentGuid"); 467 | } 468 | 469 | // eslint-disable-next-line stylistic/max-len 470 | if (this.uasset.header.FileVersionUE4 >= EUnrealEngineObjectUE4Version.VER_UE4_ADDED_PACKAGE_OWNER.value && this.uasset.header.FileVersionUE4 < EUnrealEngineObjectUE4Version.VER_UE4_NON_OUTER_PACKAGE_IMPORT.value) { 471 | this.uasset.header.OwnerPersistentGuid = this.fguidString("OwnerPersistentGuid"); 472 | } 473 | 474 | count = this.int32("Generations Count"); 475 | this.uasset.header.Generations = []; 476 | for (idx = 0; idx < count; ++idx) { 477 | this.uasset.header.Generations.push({ 478 | exportCount: this.int32("Generations #" + idx + ": export count"), 479 | nameCount : this.int32("Generations #" + idx + ": name count)") 480 | }); 481 | } 482 | 483 | if (this.uasset.header.FileVersionUE4 >= EUnrealEngineObjectUE4Version.VER_UE4_ENGINE_VERSION_OBJECT.value) { 484 | this.uasset.header.SavedByEngineVersion = String(this.uint16("SavedByEngineVersion Major")); 485 | this.uasset.header.SavedByEngineVersion = this.uasset.header.SavedByEngineVersion + "." + this.uint16("SavedByEngineVersion Minor"); 486 | this.uasset.header.SavedByEngineVersion = this.uasset.header.SavedByEngineVersion + "." + this.uint16("SavedByEngineVersion Patch"); 487 | this.uasset.header.SavedByEngineVersion = this.uasset.header.SavedByEngineVersion + "-" + this.uint32("SavedByEngineVersion Changelist"); 488 | this.uasset.header.SavedByEngineVersion = this.uasset.header.SavedByEngineVersion + "+" + this.fstring("SavedByEngineVersion Branch"); 489 | } else { 490 | this.uasset.header.EngineChangelist = this.int32("EngineChangelist"); 491 | } 492 | 493 | if (this.uasset.header.FileVersionUE4 >= EUnrealEngineObjectUE4Version.VER_UE4_PACKAGE_SUMMARY_HAS_COMPATIBLE_ENGINE_VERSION.value) { 494 | this.uasset.header.CompatibleWithEngineVersion = String(this.uint16("CompatibleWithEngineVersion Major")); 495 | this.uasset.header.CompatibleWithEngineVersion = this.uasset.header.CompatibleWithEngineVersion + "." + this.uint16("CompatibleWithEngineVersion Minor"); 496 | this.uasset.header.CompatibleWithEngineVersion = this.uasset.header.CompatibleWithEngineVersion + "." + this.uint16("CompatibleWithEngineVersion Patch"); 497 | this.uasset.header.CompatibleWithEngineVersion = this.uasset.header.CompatibleWithEngineVersion + "-" + this.uint32("CompatibleWithEngineVersion Changelist"); 498 | this.uasset.header.CompatibleWithEngineVersion = this.uasset.header.CompatibleWithEngineVersion + "+" + this.fstring("CompatibleWithEngineVersion Branch"); 499 | } else { 500 | this.uasset.header.CompatibleWithEngineVersion = this.uasset.header.SavedByEngineVersion; 501 | } 502 | 503 | this.uasset.header.CompressionFlags = this.uint32("CompressionFlags"); 504 | 505 | count = this.int32("CompressedChunks Count"); 506 | if (count > 0) { 507 | return new Error("asset compressed"); 508 | } 509 | 510 | this.uasset.header.PackageSource = this.uint32("PackageSource"); 511 | 512 | count = this.uint32("AdditionalPackagesToCook Count"); 513 | this.uasset.header.AdditionalPackagesToCook = []; 514 | if (count > 0) { 515 | return new Error("AdditionalPackagesToCook has items"); 516 | } 517 | 518 | /* eslint-disable-next-line no-magic-numbers */ 519 | if (this.uasset.header.LegacyFileVersion > -7) { 520 | this.uasset.header.NumTextureAllocations = this.int32("NumTextureAllocations"); 521 | } 522 | 523 | this.uasset.header.AssetRegistryDataOffset = this.int32("AssetRegistryDataOffset"); 524 | this.uasset.header.BulkDataStartOffset = this.int64("BulkDataStartOffset"); 525 | 526 | if (this.uasset.header.FileVersionUE4 >= EUnrealEngineObjectUE4Version.VER_UE4_WORLD_LEVEL_INFO.value) { 527 | this.uasset.header.WorldTileInfoDataOffset = this.int32("WorldTileInfoDataOffset"); 528 | } 529 | 530 | if (this.uasset.header.FileVersionUE4 >= EUnrealEngineObjectUE4Version.VER_UE4_CHANGED_CHUNKID_TO_BE_AN_ARRAY_OF_CHUNKIDS.value) { 531 | count = this.int32("ChunkIDs Count"); 532 | this.uasset.header.ChunkIDs = []; 533 | if (count > 0) { 534 | return new Error("ChunkIDs has items"); 535 | } 536 | } else if (this.uasset.header.FileVersionUE4 >= EUnrealEngineObjectUE4Version.VER_UE4_ADDED_CHUNKID_TO_ASSETDATA_AND_UPACKAGE.value) { 537 | this.uasset.header.ChunkID = this.int32("ChunkID"); 538 | } 539 | 540 | if (this.uasset.header.FileVersionUE4 >= EUnrealEngineObjectUE4Version.VER_UE4_PRELOAD_DEPENDENCIES_IN_COOKED_EXPORTS.value) { 541 | this.uasset.header.PreloadDependencyCount = this.int32("PreloadDependencyCount"); 542 | this.uasset.header.PreloadDependencyOffset = this.int32("PreloadDependencyOffset"); 543 | } else { 544 | this.uasset.header.PreloadDependencyCount = -1; 545 | this.uasset.header.PreloadDependencyOffset = 0; 546 | } 547 | 548 | if (this.uasset.header.FileVersionUE5 >= EUnrealEngineObjectUE5Version.VER_UE5_NAMES_REFERENCED_FROM_EXPORT_DATA.value) { 549 | this.uasset.header.NamesReferencedFromExportDataCount = this.int32("NamesReferencedFromExportDataCount"); 550 | } 551 | 552 | if (this.uasset.header.FileVersionUE5 >= EUnrealEngineObjectUE5Version.VER_UE5_PAYLOAD_TOC.value) { 553 | this.uasset.header.PayloadTocOffset = this.int64("PayloadTocOffset"); 554 | } else { 555 | this.uasset.header.PayloadTocOffset = -1; 556 | } 557 | 558 | if (this.uasset.header.FileVersionUE5 >= EUnrealEngineObjectUE5Version.VER_UE5_DATA_RESOURCES.value) { 559 | this.uasset.header.DataResourceOffset = this.int32("DataResourceOffset"); 560 | } 561 | 562 | return undefined; 563 | }; 564 | 565 | /** 566 | * Read Names. 567 | * 568 | * @function ReaderUasset#readNames 569 | * @returns {undefined} 570 | * @private 571 | * @see https://github.com/EpicGames/UnrealEngine/blob/5.0/Engine/Source/Runtime/Core/Private/UObject/UnrealNames.cpp#L2736 572 | */ 573 | ReaderUasset.prototype.readNames = function readNames() { 574 | var idx = 0; 575 | var count = this.uasset.header.NameCount; 576 | this.currentIdx = this.uasset.header.NameOffset; 577 | 578 | /** 579 | * Hashes: These are not used anymore but recalculated on save to maintain serialization format 580 | * GetRawNonCasePreservingHash -> return FCrc::Strihash_DEPRECATED(Source) & 0xFFFF; 581 | * GetRawCasePreservingHash -> return FCrc::StrCrc32(Source) & 0xFFFF; 582 | */ 583 | 584 | for (; idx < count; ++idx) { 585 | this.uasset.names.push({ 586 | Name : this.fstring("Name #" + (idx + 1) + ": string"), 587 | NonCasePreservingHash: this.uint16("Name #" + (idx + 1) + ": NonCasePreservingHash"), 588 | CasePreservingHash : this.uint16("Name #" + (idx + 1) + ": CasePreservingHash") 589 | }); 590 | } 591 | }; 592 | 593 | /** 594 | * Read Gatherable Text Data. 595 | * 596 | * @function ReaderUasset#readGatherableTextData 597 | * @returns {Error|undefined} 598 | * @private 599 | * @see https://github.com/EpicGames/UnrealEngine/blob/5.0/Engine/Source/Runtime/Core/Private/Internationalization/GatherableTextData.cpp 600 | */ 601 | ReaderUasset.prototype.readGatherableTextData = function readGatherableTextData() { 602 | /** @type {GatherableTextData} */ 603 | var gatherableTextData; 604 | /** @type {SourceSiteContexts} */ 605 | var sourceSiteContexts; 606 | /** @type {number} */ 607 | var countSourceSiteContexts; 608 | /** @type {number} */ 609 | var idxSourceSiteContexts; 610 | /** @type {number} */ 611 | var idx = 0; 612 | /** @type {number} */ 613 | var count = this.uasset.header.GatherableTextDataCount; 614 | 615 | this.currentIdx = this.uasset.header.GatherableTextDataOffset; 616 | 617 | this.uasset.gatherableTextData = []; 618 | for (; idx < count; ++idx) { 619 | gatherableTextData = {}; 620 | 621 | gatherableTextData.NamespaceName = this.fstring("GatherableTextData #" + (idx + 1) + ": NamespaceName"); 622 | 623 | gatherableTextData.SourceData = { 624 | SourceString : this.fstring("GatherableTextData #" + (idx + 1) + ": SourceData.SourceString"), 625 | SourceStringMetaData: { 626 | ValueCount: this.int32("GatherableTextData #" + (idx + 1) + ": SourceData.CountSourceStringMetaData"), 627 | Values : [] 628 | } 629 | }; 630 | 631 | if (gatherableTextData.SourceData.SourceStringMetaData.ValueCount > 0) { 632 | return new Error("unsupported SourceStringMetaData from readGatherableTextData"); 633 | } 634 | 635 | gatherableTextData.SourceSiteContexts = []; 636 | countSourceSiteContexts = this.int32("GatherableTextData #" + (idx + 1) + ": CountSourceSiteContexts"); 637 | for (idxSourceSiteContexts = 0; idxSourceSiteContexts < countSourceSiteContexts; ++idxSourceSiteContexts) { 638 | sourceSiteContexts = {}; 639 | sourceSiteContexts.KeyName = this.fstring("GatherableTextData #" + (idx + 1) + " - SourceSiteContexts #" + (idxSourceSiteContexts + 1) + ": KeyName"); 640 | sourceSiteContexts.SiteDescription = this.fstring("GatherableTextData #" + (idx + 1) + " - SourceSiteContexts #" + (idxSourceSiteContexts + 1) + ": SiteDescription"); 641 | sourceSiteContexts.IsEditorOnly = this.uint32("GatherableTextData #" + (idx + 1) + " - SourceSiteContexts #" + (idxSourceSiteContexts + 1) + ": IsEditorOnly"); 642 | sourceSiteContexts.IsOptional = this.uint32("GatherableTextData #" + (idx + 1) + " - SourceSiteContexts #" + (idxSourceSiteContexts + 1) + ": IsOptional"); 643 | 644 | sourceSiteContexts.InfoMetaData = { 645 | ValueCount: this.int32("GatherableTextData #" + (idx + 1) + " - SourceSiteContexts #" + (idxSourceSiteContexts + 1) + ": CountInfoMetaData"), 646 | Values : [] 647 | }; 648 | 649 | if (sourceSiteContexts.InfoMetaData.ValueCount > 0) { 650 | return new Error("unsupported SourceSiteContexts.InfoMetaData from readGatherableTextData"); 651 | } 652 | 653 | sourceSiteContexts.KeyMetaData = { 654 | ValueCount: this.int32("GatherableTextData #" + (idx + 1) + " - SourceSiteContexts #" + (idxSourceSiteContexts + 1) + ": CountKeyMetaData"), 655 | Values : [] 656 | }; 657 | 658 | if (sourceSiteContexts.KeyMetaData.ValueCount > 0) { 659 | return new Error("unsupported SourceSiteContexts.KeyMetaData from readGatherableTextData"); 660 | } 661 | 662 | gatherableTextData.SourceSiteContexts.push(sourceSiteContexts); 663 | } 664 | 665 | this.uasset.gatherableTextData.push(gatherableTextData); 666 | } 667 | 668 | return undefined; 669 | }; 670 | 671 | /** 672 | * Read Imports. 673 | * 674 | * @function ReaderUasset#readImports 675 | * @returns {undefined} 676 | * @private 677 | * @see https://github.com/EpicGames/UnrealEngine/blob/5.0/Engine/Source/Runtime/CoreUObject/Private/UObject/ObjectResource.cpp#L302 678 | */ 679 | ReaderUasset.prototype.readImports = function readImports() { 680 | var idx = 0; 681 | /** @type {number} */ 682 | var classPackage; 683 | /** @type {number} */ 684 | var className; 685 | /** @type {number} */ 686 | var outerIndex; 687 | /** @type {number} */ 688 | var objectName; 689 | /** @type {number} */ 690 | var packageName = 0; 691 | /** @type {number} */ 692 | var bImportOptional = 0; 693 | /** @type {number} */ 694 | var count = this.uasset.header.ImportCount; 695 | 696 | this.currentIdx = this.uasset.header.ImportOffset; 697 | 698 | this.uasset.imports.Imports = []; 699 | for (; idx < count; ++idx) { 700 | classPackage = this.uint64("Import #" + (idx + 1) + ": classPackage"); 701 | className = this.uint64("Import #" + (idx + 1) + ": className"); 702 | outerIndex = this.int32("Import #" + (idx + 1) + ": outerIndex"); 703 | objectName = this.uint64("Import #" + (idx + 1) + ": objectName"); 704 | 705 | if (this.uasset.header.FileVersionUE4 >= EUnrealEngineObjectUE4Version.VER_UE4_NON_OUTER_PACKAGE_IMPORT.value) { 706 | packageName = this.uint64("Import #" + (idx + 1) + ": packageName"); 707 | } 708 | 709 | if (this.uasset.header.FileVersionUE5 >= EUnrealEngineObjectUE5Version.VER_UE5_OPTIONAL_RESOURCES.value) { 710 | bImportOptional = this.int32("Import #" + (idx + 1) + ": importOptional"); 711 | } 712 | 713 | this.uasset.imports.Imports.push({ 714 | classPackage : this.resolveFName(classPackage), 715 | className : this.resolveFName(className), 716 | outerIndex : outerIndex, 717 | objectName : this.resolveFName(objectName), 718 | packageName : this.resolveFName(packageName), 719 | bImportOptional: bImportOptional 720 | }); 721 | } 722 | }; 723 | 724 | /** 725 | * Read Exports. 726 | * 727 | * @function ReaderUasset#readExports 728 | * @returns {undefined} 729 | * @private 730 | * @see https://github.com/EpicGames/UnrealEngine/blob/5.0/Engine/Source/Runtime/CoreUObject/Private/UObject/ObjectResource.cpp#L113 731 | * @todo Data are HERE, need to find how to read that 732 | */ 733 | /* eslint-disable-next-line max-statements */ 734 | ReaderUasset.prototype.readExports = function readExports() { 735 | /** @type {number} */ 736 | var idx = 0; 737 | /** @type {number} */ 738 | var count; 739 | /** @type {number} */ 740 | var nodeNameRef; 741 | /** @type {number} */ 742 | var classIndex; 743 | /** @type {number} */ 744 | var superIndex; 745 | /** @type {number} */ 746 | var templateIndex = 0; 747 | /** @type {number} */ 748 | var outerIndex; 749 | /** @type {number} */ 750 | var objectName; 751 | /** @type {number} */ 752 | var objectFlags; 753 | /** @type {number} */ 754 | var serialSize; 755 | /** @type {number} */ 756 | var serialOffset; 757 | /** @type {number} */ 758 | var bForcedExport; 759 | /** @type {number} */ 760 | var bNotForClient; 761 | /** @type {number} */ 762 | var bNotForServer; 763 | /** @type {string} */ 764 | var packageGuid; 765 | /** @type {number} */ 766 | var packageFlags; 767 | /** @type {number} */ 768 | var bNotAlwaysLoadedForEditorGame = 0; 769 | /** @type {number} */ 770 | var bIsAsset = 0; 771 | /** @type {number} */ 772 | var bGeneratePublicHash = 0; 773 | /** @type {number} */ 774 | var firstExportDependency = 0; 775 | /** @type {number} */ 776 | var serializationBeforeSerializationDependencies = 0; 777 | /** @type {number} */ 778 | var createBeforeSerializationDependencies = 0; 779 | /** @type {number} */ 780 | var serializationBeforeCreateDependencies = 0; 781 | /** @type {number} */ 782 | var createBeforeCreateDependencies = 0; 783 | 784 | this.currentIdx = this.uasset.header.ExportOffset; 785 | 786 | count = this.uasset.header.ExportCount; 787 | this.uasset.exports = []; 788 | for (; idx < count; ++idx) { 789 | classIndex = this.int32("Export #" + (idx + 1) + ": classIndex"); 790 | superIndex = this.int32("Export #" + (idx + 1) + ": superIndex"); 791 | 792 | if (this.uasset.header.FileVersionUE4 >= EUnrealEngineObjectUE4Version.VER_UE4_TEMPLATEINDEX_IN_COOKED_EXPORTS.value) { 793 | templateIndex = this.int32("Export #" + (idx + 1) + ": templateIndex"); 794 | } 795 | 796 | outerIndex = this.int32("Export #" + (idx + 1) + ": outerIndex"); 797 | objectName = this.uint64("Export #" + (idx + 1) + ": objectName"); 798 | objectFlags = this.uint32("Export #" + (idx + 1) + ": objectFlags"); 799 | serialSize = this.int64("Export #" + (idx + 1) + ": serialSize"); 800 | serialOffset = this.int64("Export #" + (idx + 1) + ": serialOffset"); 801 | bForcedExport = this.int32("Export #" + (idx + 1) + ": bForcedExport"); 802 | bNotForClient = this.int32("Export #" + (idx + 1) + ": bNotForClient"); 803 | bNotForServer = this.int32("Export #" + (idx + 1) + ": bNotForServer"); 804 | packageGuid = this.fguidString("Export #" + (idx + 1) + ": packageGuid"); 805 | packageFlags = this.uint32("Export #" + (idx + 1) + ": packageFlags"); 806 | 807 | if (this.uasset.header.FileVersionUE4 >= EUnrealEngineObjectUE4Version.VER_UE4_LOAD_FOR_EDITOR_GAME.value) { 808 | bNotAlwaysLoadedForEditorGame = this.int32("Export #" + (idx + 1) + ": bNotAlwaysLoadedForEditorGame"); 809 | } 810 | 811 | if (this.uasset.header.FileVersionUE4 >= EUnrealEngineObjectUE4Version.VER_UE4_COOKED_ASSETS_IN_EDITOR_SUPPORT.value) { 812 | bIsAsset = this.int32("Export #" + (idx + 1) + ": bIsAsset"); 813 | } 814 | 815 | if (this.uasset.header.FileVersionUE5 >= EUnrealEngineObjectUE5Version.VER_UE5_OPTIONAL_RESOURCES.value) { 816 | bGeneratePublicHash = this.int32("Export #" + (idx + 1) + ": bGeneratePublicHash"); 817 | } 818 | 819 | if (this.uasset.header.FileVersionUE4 >= EUnrealEngineObjectUE4Version.VER_UE4_PRELOAD_DEPENDENCIES_IN_COOKED_EXPORTS.value) { 820 | firstExportDependency = this.int32("Export #" + (idx + 1) + ": firstExportDependency"); 821 | serializationBeforeSerializationDependencies = this.int32("Export #" + (idx + 1) + ": serializationBeforeSerializationDependencies"); 822 | createBeforeSerializationDependencies = this.int32("Export #" + (idx + 1) + ": createBeforeSerializationDependencies"); 823 | serializationBeforeCreateDependencies = this.int32("Export #" + (idx + 1) + ": serializationBeforeCreateDependencies"); 824 | createBeforeCreateDependencies = this.int32("Export #" + (idx + 1) + ": createBeforeCreateDependencies"); 825 | } 826 | 827 | this.uasset.exports.push({ 828 | classIndex : classIndex, 829 | superIndex : superIndex, 830 | templateIndex : templateIndex, 831 | outerIndex : outerIndex, 832 | objectName : this.resolveFName(objectName), 833 | objectFlags : objectFlags, 834 | serialSize : serialSize, 835 | serialOffset : serialOffset, 836 | bForcedExport : bForcedExport, 837 | bNotForClient : bNotForClient, 838 | bNotForServer : bNotForServer, 839 | packageGuid : packageGuid, 840 | packageFlags : packageFlags, 841 | bNotAlwaysLoadedForEditorGame : bNotAlwaysLoadedForEditorGame, 842 | bIsAsset : bIsAsset, 843 | bGeneratePublicHash : bGeneratePublicHash, 844 | firstExportDependency : firstExportDependency, 845 | serializationBeforeSerializationDependencies: serializationBeforeSerializationDependencies, 846 | createBeforeSerializationDependencies : createBeforeSerializationDependencies, 847 | serializationBeforeCreateDependencies : serializationBeforeCreateDependencies, 848 | createBeforeCreateDependencies : createBeforeCreateDependencies, 849 | data : [] 850 | }); 851 | } 852 | 853 | for (idx = 0; idx < count; ++idx) { 854 | if (this.uasset.exports[idx].serialSize <= 0) { 855 | continue; 856 | } 857 | 858 | this.currentIdx = Number(this.uasset.exports[idx].serialOffset); 859 | 860 | // Data are HERE, need to find how to read that 861 | 862 | nodeNameRef = this.uint64("Exports #" + (idx + 1) + ": data"); 863 | this.uasset.exports[idx].data.push(this.resolveFName(nodeNameRef)); 864 | this.uasset.exports[idx].data.push(this.uint32("flags")); 865 | } 866 | }; 867 | 868 | /** 869 | * Read Depends. 870 | * 871 | * @function ReaderUasset#readDepends 872 | * @returns {undefined} 873 | * @private 874 | */ 875 | ReaderUasset.prototype.readDepends = function readDepends() { 876 | /** @type {number} */ 877 | var idx = 0; 878 | /** @type {number} */ 879 | var count; 880 | 881 | this.currentIdx = this.uasset.header.DependsOffset; 882 | 883 | count = this.int32("Depends Count"); 884 | this.uasset.depends.Depends = []; 885 | for (; idx < count; ++idx) { 886 | this.uasset.depends.Depends.push({ 887 | FPackageIndex: this.int32("Depend #" + (idx + 1) + ": FPackageIndex") 888 | }); 889 | } 890 | }; 891 | 892 | /** 893 | * Read Soft Package References. 894 | * 895 | * @function ReaderUasset#readSoftPackageReferences 896 | * @returns {undefined} 897 | * @private 898 | */ 899 | ReaderUasset.prototype.readSoftPackageReferences = function readSoftPackageReferences() { 900 | /** @type {number} */ 901 | var nameIndex; 902 | /** @type {number} */ 903 | var idx = 0; 904 | /** @type {number} */ 905 | var count; 906 | 907 | this.currentIdx = this.uasset.header.SoftPackageReferencesOffset; 908 | 909 | count = this.uasset.header.SoftPackageReferencesCount; 910 | this.uasset.softPackageReferences = []; 911 | for (; idx < count; ++idx) { 912 | nameIndex = this.uint64("SoftPackageReferences #" + (idx + 1) + ": SoftPackageReferences"); 913 | this.uasset.softPackageReferences.push({ 914 | assetPathName: this.resolveFName(nameIndex) 915 | }); 916 | } 917 | }; 918 | 919 | /** 920 | * Read Searchable Names. 921 | * 922 | * @function ReaderUasset#readSearchableNames 923 | * @returns {undefined} 924 | * @private 925 | */ 926 | ReaderUasset.prototype.readSearchableNames = function readSearchableNames() { 927 | this.currentIdx = this.uasset.header.SearchableNamesOffset; 928 | 929 | this.int32("CountSearchableNames"); 930 | this.uasset.searchableNames = []; 931 | }; 932 | 933 | /** 934 | * Read Thumbnails. 935 | * 936 | * @function ReaderUasset#readThumbnails 937 | * @returns {undefined} 938 | * @private 939 | * @see https://github.com/EpicGames/UnrealEngine/blob/5.0/Engine/Source/Runtime/Core/Private/Misc/ObjectThumbnail.cpp#L42 940 | */ 941 | ReaderUasset.prototype.readThumbnails = function readThumbnails() { 942 | /** @type {number} */ 943 | var pos; 944 | /** @type {number} */ 945 | var idx = 0; 946 | /** @type {number} */ 947 | var count; 948 | /** @type {number} */ 949 | var imageWidth; 950 | /** @type {number} */ 951 | var imageHeight; 952 | /** @type {string} */ 953 | var imageFormat; 954 | /** @type {number} */ 955 | var imageSizeData; 956 | /** @type {number[]} */ 957 | var imageData; 958 | 959 | this.currentIdx = this.uasset.header.ThumbnailTableOffset; 960 | 961 | count = this.int32("Thumbnails Count"); 962 | this.uasset.thumbnails.Index = []; 963 | this.uasset.thumbnails.Thumbnails = []; 964 | for (; idx < count; ++idx) { 965 | this.uasset.thumbnails.Index.push({ 966 | AssetClassName : this.fstring("Thumbnails #" + (idx + 1) + ": assetClassName"), 967 | ObjectPathWithoutPackageName: this.fstring("Thumbnails #" + (idx + 1) + ": objectPathWithoutPackageName"), 968 | FileOffset : this.int32("Thumbnails #" + (idx + 1) + ": fileOffset") 969 | }); 970 | } 971 | 972 | for (idx = 0; idx < count; ++idx) { 973 | this.currentIdx = this.uasset.thumbnails.Index[idx].FileOffset; 974 | 975 | imageWidth = this.int32("Thumbnails #" + (idx + 1) + ": imageWidth"); 976 | imageHeight = this.int32("Thumbnails #" + (idx + 1) + ": imageHeight"); 977 | imageFormat = "PNG"; 978 | 979 | if (imageHeight < 0) { 980 | imageFormat = "JPEG"; 981 | imageHeight = imageHeight * -1; 982 | } 983 | 984 | imageData = []; 985 | imageSizeData = this.int32("Thumbnails #" + (idx + 1) + ": imageSizeData"); 986 | if (imageSizeData > 0) { 987 | pos = this.currentIdx; 988 | imageData = this.readCountBytes(imageSizeData); 989 | this.addHexView("Thumbnails #" + (idx + 1) + ": imageData", "data", imageData.join(""), pos, this.currentIdx - 1); 990 | } 991 | 992 | this.uasset.thumbnails.Thumbnails.push({ 993 | ImageWidth : imageWidth, 994 | ImageHeight : imageHeight, 995 | ImageFormat : imageFormat, 996 | ImageSizeData: imageSizeData, 997 | ImageData : imageData 998 | }); 999 | } 1000 | }; 1001 | 1002 | /** 1003 | * Read Asset Registry Data. 1004 | * 1005 | * @function ReaderUasset#readAssetRegistryData 1006 | * @returns {undefined} 1007 | * @private 1008 | */ 1009 | ReaderUasset.prototype.readAssetRegistryData = function readAssetRegistryData() { 1010 | /** @type {number} */ 1011 | var idx; 1012 | /** @type {number} */ 1013 | var count; 1014 | /** @type {number} */ 1015 | var idxTag; 1016 | /** @type {number} */ 1017 | var countTag; 1018 | /** @type {number} */ 1019 | var nextOffset = this.uasset.header.TotalHeaderSize; 1020 | 1021 | this.currentIdx = this.uasset.header.AssetRegistryDataOffset; 1022 | 1023 | if (this.uasset.header.WorldTileInfoDataOffset > 0) { 1024 | nextOffset = this.uasset.header.WorldTileInfoDataOffset; 1025 | } 1026 | 1027 | this.uasset.assetRegistryData.size = nextOffset - this.uasset.header.AssetRegistryDataOffset; 1028 | 1029 | this.uasset.assetRegistryData.DependencyDataOffset = this.int64("DependencyDataOffset"); 1030 | 1031 | this.uasset.assetRegistryData.data = []; 1032 | count = this.int32("AssetRegistryData Count"); 1033 | for (idx = 0; idx < count; ++idx) { 1034 | this.uasset.assetRegistryData.data.push({ 1035 | ObjectPath : this.fstring("ObjectPath"), 1036 | ObjectClassName: this.fstring("ObjectClassName"), 1037 | Tags : [] 1038 | }); 1039 | 1040 | countTag = this.int32("AssetRegistryData Tag Count"); 1041 | for (idxTag = 0; idxTag < countTag; ++idxTag) { 1042 | this.uasset.assetRegistryData.data[idx].Tags.push({ 1043 | Key : this.fstring("key"), 1044 | Value: this.fstring("value") 1045 | }); 1046 | } 1047 | } 1048 | }; 1049 | 1050 | /** 1051 | * Read Preload Dependency. 1052 | * 1053 | * @function ReaderUasset#readPreloadDependency 1054 | * @returns {undefined} 1055 | * @private 1056 | */ 1057 | ReaderUasset.prototype.readPreloadDependency = function readPreloadDependency() { 1058 | this.currentIdx = this.uasset.header.PreloadDependencyOffset; 1059 | }; 1060 | 1061 | /** 1062 | * Read Bulk Data Start. 1063 | * 1064 | * @function ReaderUasset#readBulkDataStart 1065 | * @returns {undefined} 1066 | * @private 1067 | */ 1068 | ReaderUasset.prototype.readBulkDataStart = function readBulkDataStart() { 1069 | this.currentIdx = Number(this.uasset.header.BulkDataStartOffset); 1070 | }; 1071 | 1072 | /** 1073 | * Analyze Uasset. 1074 | * 1075 | * @function ReaderUasset#analyze 1076 | * @param {Uint8Array} bytes - bytes read from file 1077 | * @param {boolean} saveHexView - if true save all informations to debug 1078 | * @returns {(Error|Uasset)} 1079 | * @public 1080 | */ 1081 | ReaderUasset.prototype.analyze = function analyze(bytes, saveHexView) { 1082 | /** @type {(Error|undefined)} */ 1083 | var err; 1084 | 1085 | this.currentIdx = 0; 1086 | this.bytes = bytes; 1087 | this.saveHexView = saveHexView || false; 1088 | this.useLittleEndian = true; 1089 | 1090 | err = this.readHeader(); 1091 | if (err !== undefined) { 1092 | return err; 1093 | } 1094 | 1095 | this.readNames(); 1096 | 1097 | err = this.readGatherableTextData(); 1098 | if (err !== undefined) { 1099 | return err; 1100 | } 1101 | 1102 | this.readImports(); 1103 | this.readExports(); 1104 | this.readDepends(); 1105 | this.readSoftPackageReferences(); 1106 | this.readSearchableNames(); 1107 | this.readThumbnails(); 1108 | this.readAssetRegistryData(); 1109 | this.readPreloadDependency(); 1110 | this.readBulkDataStart(); 1111 | 1112 | this.uasset.hexView.sort(function sortHexView(left, right) { 1113 | return left.start - right.start; 1114 | }); 1115 | 1116 | return this.uasset; 1117 | }; 1118 | 1119 | // Freeze prototype for security issue about prototype pollution. 1120 | Object.freeze(ReaderUasset.prototype); 1121 | Object.freeze(ReaderUasset); 1122 | 1123 | window.blueprintUE.uasset.ReaderUasset = ReaderUasset; 1124 | -------------------------------------------------------------------------------- /tests/datacases.json: -------------------------------------------------------------------------------- 1 | { 2 | "simple": { 3 | "ue50": [ 4 | { 5 | "name": "BP_Actor_Simple", 6 | "input": "uassets/ue50/BP_Actor_Simple.uasset", 7 | "expected": "uassets/ue50/BP_Actor_Simple.json" 8 | } 9 | ] 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/main.test.js: -------------------------------------------------------------------------------- 1 | require("../src/js/_namespace_"); 2 | require("../src/js/enums/enums"); 3 | require("../src/js/main"); 4 | const fs = require("fs"); 5 | const path = require("path"); 6 | const datacases = require("./datacases.json"); 7 | 8 | function parseBigIntPayload(key, value) { 9 | if (["PayloadTocOffset", "BulkDataStartOffset"].indexOf(key) !== -1) { 10 | value = value.replace("n", ""); 11 | value = BigInt(value); 12 | } 13 | 14 | return value; 15 | } 16 | 17 | describe("main", function() { 18 | // region constructor 19 | it("should be defined", () => { 20 | expect(window.blueprintUE.uasset.ReaderUasset).toBeDefined(); 21 | }); 22 | // endregion 23 | 24 | describe("datacases", function() { 25 | describe("simple", function() { 26 | describe("UE 5.0", function() { 27 | /* eslint-disable-next-line no-unused-vars */ 28 | it.each(datacases.simple.ue50)(`$name`, ({name, input, expected}) => { 29 | const bytesInput = new Uint8Array(fs.readFileSync(path.resolve(__dirname, input))); 30 | const bytesOutput = JSON.parse(fs.readFileSync(path.resolve(__dirname, expected)).toString(), parseBigIntPayload); 31 | 32 | const uasset = new window.blueprintUE.uasset.ReaderUasset().analyze(bytesInput, false); 33 | 34 | expect(uasset.header).toStrictEqual(bytesOutput.header); 35 | expect(uasset.names).toStrictEqual(bytesOutput.names); 36 | expect(uasset.gatherableTextData).toStrictEqual(bytesOutput.gatherableTextData); 37 | }); 38 | }); 39 | }); 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /tests/uassets/ue50/BP_Actor_Simple.json: -------------------------------------------------------------------------------- 1 | { 2 | "header": { 3 | "AdditionalPackagesToCook": [], 4 | "AssetRegistryDataOffset": 5620, 5 | "BulkDataStartOffset": "20574n", 6 | "ChunkIDs": [], 7 | "CompatibleWithEngineVersion": "5.0.0-19505902+++UE5+Release-5.0", 8 | "CompressionFlags": 0, 9 | "CustomVersions": [ 10 | { 11 | "key": "29E575DDE0A346279D10D276232CDCEA", 12 | "version": 17 13 | }, 14 | { 15 | "key": "375EC13C06E448FBB50084F0262A717E", 16 | "version": 4 17 | }, 18 | { 19 | "key": "59DA5D5212324948B878597870B8E98B", 20 | "version": 8 21 | }, 22 | { 23 | "key": "601D1886AC644F84AA16D3DE0DEAC7D6", 24 | "version": 59 25 | }, 26 | { 27 | "key": "697DD581E64F41ABAA4A51ECBEB7B628", 28 | "version": 59 29 | }, 30 | { 31 | "key": "9C54D522A8264FBE9421074661B482D0", 32 | "version": 44 33 | }, 34 | { 35 | "key": "B0D832E41F894F0DACCF7EB736FD4AA2", 36 | "version": 10 37 | }, 38 | { 39 | "key": "CFFC743F43B04480939114DF171D2073", 40 | "version": 37 41 | }, 42 | { 43 | "key": "D89B5E4224BD4D468412ACA8DF641779", 44 | "version": 36 45 | }, 46 | { 47 | "key": "E4B068EDF49442E9A231DA0B2E46BB41", 48 | "version": 40 49 | } 50 | ], 51 | "DependsOffset": 5352, 52 | "EPackageFileTag": 2653586369, 53 | "ExportCount": 14, 54 | "ExportOffset": 3840, 55 | "FileVersionLicenseeUE4": 0, 56 | "FileVersionUE4": 522, 57 | "FileVersionUE5": 1004, 58 | "FolderName": "None", 59 | "GatherableTextDataCount": 1, 60 | "GatherableTextDataOffset": 2969, 61 | "Generations": [ 62 | { 63 | "exportCount": 14, 64 | "nameCount": 107 65 | } 66 | ], 67 | "Guid":"06318DB10D38BC46A951670107952FF5", 68 | "ImportCount": 18, 69 | "ImportOffset": 3120, 70 | "LegacyFileVersion": -8, 71 | "LegacyUE3Version": 864, 72 | "LocalizationId": "50B4947A4816F182AF72CC889D9D0EB8", 73 | "NameCount": 107, 74 | "NameOffset": 498, 75 | "NamesReferencedFromExportDataCount": 81, 76 | "PackageFlags": 262144, 77 | "PackageSource": 81731590, 78 | "PayloadTocOffset": "-1n", 79 | "PersistentGuid": "496FAA46B66D61499D3C93D6872762C1", 80 | "PreloadDependencyCount": -1, 81 | "PreloadDependencyOffset": 14650, 82 | "SavedByEngineVersion": "5.0.3-20979098+++UE5+Release-5.0", 83 | "SearchableNamesOffset": 5496, 84 | "SoftPackageReferencesCount": 1, 85 | "SoftPackageReferencesOffset": 5488, 86 | "ThumbnailTableOffset": 5524, 87 | "TotalHeaderSize": 14650, 88 | "WorldTileInfoDataOffset": 0 89 | }, 90 | "names": [ 91 | { 92 | "Name": "/Game/BP_Actor_Simple.BP_Actor_Simple", 93 | "NonCasePreservingHash": 29338, 94 | "CasePreservingHash": 60561 95 | }, 96 | { 97 | "Name": "/Game/BP_Actor_Simple.BP_Actor_Simple_C", 98 | "NonCasePreservingHash": 12397, 99 | "CasePreservingHash": 33577 100 | }, 101 | { 102 | "Name": "AllNodes", 103 | "NonCasePreservingHash": 5631, 104 | "CasePreservingHash": 17127 105 | }, 106 | { 107 | "Name": "ArrayProperty", 108 | "NonCasePreservingHash": 45129, 109 | "CasePreservingHash": 27107 110 | }, 111 | { 112 | "Name": "bAllowDeletion", 113 | "NonCasePreservingHash": 61951, 114 | "CasePreservingHash": 60174 115 | }, 116 | { 117 | "Name": "bCommentBubblePinned", 118 | "NonCasePreservingHash": 11889, 119 | "CasePreservingHash": 19493 120 | }, 121 | { 122 | "Name": "bCommentBubbleVisible", 123 | "NonCasePreservingHash": 9297, 124 | "CasePreservingHash": 15420 125 | }, 126 | { 127 | "Name": "bLegacyNeedToPurgeSkelRefs", 128 | "NonCasePreservingHash": 44431, 129 | "CasePreservingHash": 15196 130 | }, 131 | { 132 | "Name": "BlueprintGuid", 133 | "NonCasePreservingHash": 1999, 134 | "CasePreservingHash": 21786 135 | }, 136 | { 137 | "Name": "BlueprintInternalUseOnly", 138 | "NonCasePreservingHash": 57478, 139 | "CasePreservingHash": 20896 140 | }, 141 | { 142 | "Name": "BlueprintSystemVersion", 143 | "NonCasePreservingHash": 29825, 144 | "CasePreservingHash": 11017 145 | }, 146 | { 147 | "Name": "BlueprintType", 148 | "NonCasePreservingHash": 4364, 149 | "CasePreservingHash": 57234 150 | }, 151 | { 152 | "Name": "BoolProperty", 153 | "NonCasePreservingHash": 1040, 154 | "CasePreservingHash": 35504 155 | }, 156 | { 157 | "Name": "bOverrideFunction", 158 | "NonCasePreservingHash": 62992, 159 | "CasePreservingHash": 23440 160 | }, 161 | { 162 | "Name": "bVisualizeComponent", 163 | "NonCasePreservingHash": 34731, 164 | "CasePreservingHash": 55862 165 | }, 166 | { 167 | "Name": "Category", 168 | "NonCasePreservingHash": 32503, 169 | "CasePreservingHash": 50580 170 | }, 171 | { 172 | "Name": "CategoryName", 173 | "NonCasePreservingHash": 13966, 174 | "CasePreservingHash": 3160 175 | }, 176 | { 177 | "Name": "Comment", 178 | "NonCasePreservingHash": 6602, 179 | "CasePreservingHash": 40892 180 | }, 181 | { 182 | "Name": "ComponentClass", 183 | "NonCasePreservingHash": 65073, 184 | "CasePreservingHash": 22006 185 | }, 186 | { 187 | "Name": "ComponentTemplate", 188 | "NonCasePreservingHash": 43732, 189 | "CasePreservingHash": 49698 190 | }, 191 | { 192 | "Name": "DefaultGraphNode", 193 | "NonCasePreservingHash": 58036, 194 | "CasePreservingHash": 30438 195 | }, 196 | { 197 | "Name": "DefaultSceneRoot", 198 | "NonCasePreservingHash": 36028, 199 | "CasePreservingHash": 1438 200 | }, 201 | { 202 | "Name": "DefaultSceneRootNode", 203 | "NonCasePreservingHash": 20538, 204 | "CasePreservingHash": 58813 205 | }, 206 | { 207 | "Name": "delegate", 208 | "NonCasePreservingHash": 64503, 209 | "CasePreservingHash": 36762 210 | }, 211 | { 212 | "Name": "DeltaSeconds", 213 | "NonCasePreservingHash": 21698, 214 | "CasePreservingHash": 891 215 | }, 216 | { 217 | "Name": "DisplayName", 218 | "NonCasePreservingHash": 38266, 219 | "CasePreservingHash": 17126 220 | }, 221 | { 222 | "Name": "EditedDocumentInfo", 223 | "NonCasePreservingHash": 24507, 224 | "CasePreservingHash": 64272 225 | }, 226 | { 227 | "Name": "EditedObjectPath", 228 | "NonCasePreservingHash": 16846, 229 | "CasePreservingHash": 32927 230 | }, 231 | { 232 | "Name": "EnabledState", 233 | "NonCasePreservingHash": 9665, 234 | "CasePreservingHash": 56654 235 | }, 236 | { 237 | "Name": "Engine", 238 | "NonCasePreservingHash": 439, 239 | "CasePreservingHash": 58948 240 | }, 241 | { 242 | "Name": "ENodeEnabledState", 243 | "NonCasePreservingHash": 16518, 244 | "CasePreservingHash": 62427 245 | }, 246 | { 247 | "Name": "ENodeEnabledState::Disabled", 248 | "NonCasePreservingHash": 43953, 249 | "CasePreservingHash": 54526 250 | }, 251 | { 252 | "Name": "EnumProperty", 253 | "NonCasePreservingHash": 55121, 254 | "CasePreservingHash": 16541 255 | }, 256 | { 257 | "Name": "EventReference", 258 | "NonCasePreservingHash": 41639, 259 | "CasePreservingHash": 44001 260 | }, 261 | { 262 | "Name": "exec", 263 | "NonCasePreservingHash": 60028, 264 | "CasePreservingHash": 6908 265 | }, 266 | { 267 | "Name": "float", 268 | "NonCasePreservingHash": 30996, 269 | "CasePreservingHash": 52381 270 | }, 271 | { 272 | "Name": "FloatProperty", 273 | "NonCasePreservingHash": 43003, 274 | "CasePreservingHash": 64990 275 | }, 276 | { 277 | "Name": "FunctionGraphs", 278 | "NonCasePreservingHash": 10564, 279 | "CasePreservingHash": 15656 280 | }, 281 | { 282 | "Name": "FunctionReference", 283 | "NonCasePreservingHash": 23205, 284 | "CasePreservingHash": 5628 285 | }, 286 | { 287 | "Name": "GeneratedClass", 288 | "NonCasePreservingHash": 2182, 289 | "CasePreservingHash": 21592 290 | }, 291 | { 292 | "Name": "GraphGuid", 293 | "NonCasePreservingHash": 33442, 294 | "CasePreservingHash": 30411 295 | }, 296 | { 297 | "Name": "Guid", 298 | "NonCasePreservingHash": 20547, 299 | "CasePreservingHash": 26874 300 | }, 301 | { 302 | "Name": "InternalVariableName", 303 | "NonCasePreservingHash": 65341, 304 | "CasePreservingHash": 64778 305 | }, 306 | { 307 | "Name": "IntProperty", 308 | "NonCasePreservingHash": 54181, 309 | "CasePreservingHash": 18998 310 | }, 311 | { 312 | "Name": "LastEditedDocuments", 313 | "NonCasePreservingHash": 7692, 314 | "CasePreservingHash": 53250 315 | }, 316 | { 317 | "Name": "MemberName", 318 | "NonCasePreservingHash": 8076, 319 | "CasePreservingHash": 46771 320 | }, 321 | { 322 | "Name": "MemberParent", 323 | "NonCasePreservingHash": 59774, 324 | "CasePreservingHash": 15485 325 | }, 326 | { 327 | "Name": "MemberReference", 328 | "NonCasePreservingHash": 46718, 329 | "CasePreservingHash": 16313 330 | }, 331 | { 332 | "Name": "ModuleRelativePath", 333 | "NonCasePreservingHash": 8816, 334 | "CasePreservingHash": 24971 335 | }, 336 | { 337 | "Name": "NameProperty", 338 | "NonCasePreservingHash": 62082, 339 | "CasePreservingHash": 18952 340 | }, 341 | { 342 | "Name": "NodeComment", 343 | "NonCasePreservingHash": 9312, 344 | "CasePreservingHash": 62303 345 | }, 346 | { 347 | "Name": "NodeGuid", 348 | "NonCasePreservingHash": 44241, 349 | "CasePreservingHash": 43780 350 | }, 351 | { 352 | "Name": "NodePosY", 353 | "NonCasePreservingHash": 18034, 354 | "CasePreservingHash": 26093 355 | }, 356 | { 357 | "Name": "Nodes", 358 | "NonCasePreservingHash": 65209, 359 | "CasePreservingHash": 27803 360 | }, 361 | { 362 | "Name": "None", 363 | "NonCasePreservingHash": 1012, 364 | "CasePreservingHash": 3525 365 | }, 366 | { 367 | "Name": "object", 368 | "NonCasePreservingHash": 19301, 369 | "CasePreservingHash": 65431 370 | }, 371 | { 372 | "Name": "ObjectProperty", 373 | "NonCasePreservingHash": 56129, 374 | "CasePreservingHash": 60083 375 | }, 376 | { 377 | "Name": "OtherActor", 378 | "NonCasePreservingHash": 60607, 379 | "CasePreservingHash": 64347 380 | }, 381 | { 382 | "Name": "OutputDelegate", 383 | "NonCasePreservingHash": 27916, 384 | "CasePreservingHash": 19858 385 | }, 386 | { 387 | "Name": "PackageLocalizationNamespace", 388 | "NonCasePreservingHash": 29714, 389 | "CasePreservingHash": 34937 390 | }, 391 | { 392 | "Name": "ParentClass", 393 | "NonCasePreservingHash": 56600, 394 | "CasePreservingHash": 23461 395 | }, 396 | { 397 | "Name": "real", 398 | "NonCasePreservingHash": 51542, 399 | "CasePreservingHash": 11945 400 | }, 401 | { 402 | "Name": "ReceiveActorBeginOverlap", 403 | "NonCasePreservingHash": 62953, 404 | "CasePreservingHash": 47985 405 | }, 406 | { 407 | "Name": "ReceiveBeginPlay", 408 | "NonCasePreservingHash": 32129, 409 | "CasePreservingHash": 51810 410 | }, 411 | { 412 | "Name": "ReceiveTick", 413 | "NonCasePreservingHash": 20811, 414 | "CasePreservingHash": 52988 415 | }, 416 | { 417 | "Name": "RootNodes", 418 | "NonCasePreservingHash": 3095, 419 | "CasePreservingHash": 22343 420 | }, 421 | { 422 | "Name": "SavedViewOffset", 423 | "NonCasePreservingHash": 51324, 424 | "CasePreservingHash": 17644 425 | }, 426 | { 427 | "Name": "SavedZoomAmount", 428 | "NonCasePreservingHash": 5727, 429 | "CasePreservingHash": 51597 430 | }, 431 | { 432 | "Name": "Schema", 433 | "NonCasePreservingHash": 48127, 434 | "CasePreservingHash": 30603 435 | }, 436 | { 437 | "Name": "SimpleConstructionScript", 438 | "NonCasePreservingHash": 11028, 439 | "CasePreservingHash": 8274 440 | }, 441 | { 442 | "Name": "SoftObjectPath", 443 | "NonCasePreservingHash": 41343, 444 | "CasePreservingHash": 41435 445 | }, 446 | { 447 | "Name": "StrProperty", 448 | "NonCasePreservingHash": 49467, 449 | "CasePreservingHash": 9330 450 | }, 451 | { 452 | "Name": "StructProperty", 453 | "NonCasePreservingHash": 48, 454 | "CasePreservingHash": 64668 455 | }, 456 | { 457 | "Name": "TextProperty", 458 | "NonCasePreservingHash": 15044, 459 | "CasePreservingHash": 46964 460 | }, 461 | { 462 | "Name": "then", 463 | "NonCasePreservingHash": 45441, 464 | "CasePreservingHash": 32978 465 | }, 466 | { 467 | "Name": "ThumbnailInfo", 468 | "NonCasePreservingHash": 19634, 469 | "CasePreservingHash": 45875 470 | }, 471 | { 472 | "Name": "ToolTip", 473 | "NonCasePreservingHash": 60085, 474 | "CasePreservingHash": 48647 475 | }, 476 | { 477 | "Name": "UbergraphPages", 478 | "NonCasePreservingHash": 8986, 479 | "CasePreservingHash": 13218 480 | }, 481 | { 482 | "Name": "UserConstructionScript", 483 | "NonCasePreservingHash": 45901, 484 | "CasePreservingHash": 96 485 | }, 486 | { 487 | "Name": "VariableGuid", 488 | "NonCasePreservingHash": 38571, 489 | "CasePreservingHash": 55934 490 | }, 491 | { 492 | "Name": "Vector2D", 493 | "NonCasePreservingHash": 12373, 494 | "CasePreservingHash": 2412 495 | }, 496 | { 497 | "Name": "/Game/BP_Actor_Simple", 498 | "NonCasePreservingHash": 45200, 499 | "CasePreservingHash": 1766 500 | }, 501 | { 502 | "Name": "/Script/BlueprintGraph", 503 | "NonCasePreservingHash": 56297, 504 | "CasePreservingHash": 17532 505 | }, 506 | { 507 | "Name": "/Script/CoreUObject", 508 | "NonCasePreservingHash": 18936, 509 | "CasePreservingHash": 15917 510 | }, 511 | { 512 | "Name": "/Script/Engine", 513 | "NonCasePreservingHash": 16518, 514 | "CasePreservingHash": 18821 515 | }, 516 | { 517 | "Name": "/Script/UnrealEd", 518 | "NonCasePreservingHash": 1068, 519 | "CasePreservingHash": 2199 520 | }, 521 | { 522 | "Name": "Actor", 523 | "NonCasePreservingHash": 53037, 524 | "CasePreservingHash": 22819 525 | }, 526 | { 527 | "Name": "Blueprint", 528 | "NonCasePreservingHash": 14612, 529 | "CasePreservingHash": 3379 530 | }, 531 | { 532 | "Name": "BlueprintGeneratedClass", 533 | "NonCasePreservingHash": 39721, 534 | "CasePreservingHash": 11632 535 | }, 536 | { 537 | "Name": "BP_Actor_Simple", 538 | "NonCasePreservingHash": 50246, 539 | "CasePreservingHash": 61200 540 | }, 541 | { 542 | "Name": "BP_Actor_Simple_C", 543 | "NonCasePreservingHash": 49498, 544 | "CasePreservingHash": 25989 545 | }, 546 | { 547 | "Name": "Class", 548 | "NonCasePreservingHash": 30580, 549 | "CasePreservingHash": 37240 550 | }, 551 | { 552 | "Name": "Default__Actor", 553 | "NonCasePreservingHash": 52377, 554 | "CasePreservingHash": 37723 555 | }, 556 | { 557 | "Name": "Default__BP_Actor_Simple_C", 558 | "NonCasePreservingHash": 55410, 559 | "CasePreservingHash": 35552 560 | }, 561 | { 562 | "Name": "DefaultSceneRoot_GEN_VARIABLE", 563 | "NonCasePreservingHash": 32430, 564 | "CasePreservingHash": 18564 565 | }, 566 | { 567 | "Name": "EdGraph", 568 | "NonCasePreservingHash": 28420, 569 | "CasePreservingHash": 23988 570 | }, 571 | { 572 | "Name": "EdGraphSchema_K2", 573 | "NonCasePreservingHash": 49592, 574 | "CasePreservingHash": 3480 575 | }, 576 | { 577 | "Name": "EventGraph", 578 | "NonCasePreservingHash": 42333, 579 | "CasePreservingHash": 23809 580 | }, 581 | { 582 | "Name": "K2Node_Event", 583 | "NonCasePreservingHash": 34163, 584 | "CasePreservingHash": 7002 585 | }, 586 | { 587 | "Name": "K2Node_FunctionEntry", 588 | "NonCasePreservingHash": 54171, 589 | "CasePreservingHash": 10757 590 | }, 591 | { 592 | "Name": "MetaData", 593 | "NonCasePreservingHash": 32996, 594 | "CasePreservingHash": 37812 595 | }, 596 | { 597 | "Name": "Object", 598 | "NonCasePreservingHash": 19301, 599 | "CasePreservingHash": 493 600 | }, 601 | { 602 | "Name": "Package", 603 | "NonCasePreservingHash": 18291, 604 | "CasePreservingHash": 5512 605 | }, 606 | { 607 | "Name": "PackageMetaData", 608 | "NonCasePreservingHash": 11421, 609 | "CasePreservingHash": 26020 610 | }, 611 | { 612 | "Name": "SceneComponent", 613 | "NonCasePreservingHash": 6216, 614 | "CasePreservingHash": 24420 615 | }, 616 | { 617 | "Name": "SceneThumbnailInfo", 618 | "NonCasePreservingHash": 59682, 619 | "CasePreservingHash": 46086 620 | }, 621 | { 622 | "Name": "SCS_Node", 623 | "NonCasePreservingHash": 54065, 624 | "CasePreservingHash": 50642 625 | } 626 | ], 627 | "gatherableTextData":[ 628 | { 629 | "NamespaceName": "SCS", 630 | "SourceData": { 631 | "SourceString": "Default", 632 | "SourceStringMetaData": { 633 | "ValueCount": 0, 634 | "Values": [] 635 | } 636 | }, 637 | "SourceSiteContexts": [ 638 | { 639 | "KeyName": "Default", 640 | "SiteDescription": "/Game/BP_Actor_Simple.BP_Actor_Simple_C:SimpleConstructionScript_0.SCS_Node_0.CategoryName", 641 | "IsEditorOnly": 1, 642 | "IsOptional": 0, 643 | "InfoMetaData": { 644 | "ValueCount": 0, 645 | "Values": [] 646 | }, 647 | "KeyMetaData": { 648 | "ValueCount": 0, 649 | "Values": [] 650 | } 651 | } 652 | ] 653 | } 654 | ] 655 | } -------------------------------------------------------------------------------- /tests/uassets/ue50/BP_Actor_Simple.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blueprintue/uasset-reader-js/0e1dc14e10dcdf9b77cd0242e0f0298374406cec/tests/uassets/ue50/BP_Actor_Simple.uasset -------------------------------------------------------------------------------- /tests/uassets/ue50/BP_Actor_Simple.utxt: -------------------------------------------------------------------------------- 1 | { 2 | "GatherableTextData": [ 3 | { 4 | "NamespaceName": "SCS", 5 | "SourceData": { 6 | "SourceString": "Default", 7 | "SourceStringMetaData": { 8 | "ValueCount": 0, 9 | "Values": [] 10 | } 11 | }, 12 | "SourceSiteContexts": [ 13 | { 14 | "KeyName": "Default", 15 | "SiteDescription": "/Game/BP_Actor_Simple.BP_Actor_Simple_C:SimpleConstructionScript_0.SCS_Node_0.CategoryName", 16 | "IsEditorOnly": true, 17 | "IsOptional": false, 18 | "InfoMetaData": { 19 | "ValueCount": 0, 20 | "Values": [] 21 | }, 22 | "KeyMetaData": { 23 | "ValueCount": 0, 24 | "Values": [] 25 | } 26 | } 27 | ] 28 | } 29 | ], 30 | "Thumbnails": { 31 | "Thumbnails": [ 32 | { 33 | "ImageWidth": 0, 34 | "ImageHeight": 0, 35 | "CompressedImageData": "Base64:" 36 | }, 37 | { 38 | "ImageWidth": 0, 39 | "ImageHeight": 0, 40 | "CompressedImageData": "Base64:" 41 | } 42 | ], 43 | "Index": [ 44 | { 45 | "ObjectClassName": "Blueprint", 46 | "ObjectPathWithoutPackageName": "BP_Actor_Simple", 47 | "FileOffset": 0 48 | }, 49 | { 50 | "ObjectClassName": "BlueprintGeneratedClass", 51 | "ObjectPathWithoutPackageName": "BP_Actor_Simple_C", 52 | "FileOffset": 0 53 | } 54 | ] 55 | }, 56 | "Exports": { 57 | "BP_Actor_Simple": { 58 | "__Class": "Class /Script/Engine.Blueprint", 59 | "__ObjectFlags": 11, 60 | "__bNotForClient": true, 61 | "__bNotForServer": true, 62 | "__bIsAsset": true, 63 | "__Value": { 64 | "BaseClassAutoGen": { 65 | "Data": { 66 | "Digest": "10372b3ba5db31ccfc7b581c21f43b10037f0083", 67 | "Base64": [ 68 | "AAAAAAEAAAAEAAAAAAAAAAAAAAAAAgAAAAMAAAAEAAAAAAAAAAACAAAABAAAAAEAAAAEAAAAAAAAAAABAAAABQAAAAYAAAAIAAAAAAAAAAEAAAAAAQAAAAIA", 69 | "AAAHAAAABgAAAAgAAAAAAAAAAQAAAAABAAAAAwAAAAgAAAAGAAAAjgEAAAAAAAAJAAAAAAMAAAAIAAAACQAAAGUBAAAAAAAACgAAAAAAAAAAAAAAAAAAAAAA", 70 | "AAAACwAAAAkAAAAEAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANAAAACQAAABAAAAAAAAAADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", 71 | "AAAAAAAAAA8AAAAQAAAABAAAAAAAAAAAAACAvxEAAAALAAAACQAAAAQAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAA0AAAAJAAAAEAAAAAAAAAAO", 72 | "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwAAABAAAAAEAAAAAAAAAAAAAIC/EQAAAAsAAAAJAAAABAAAAAAAAAAMAAAAAAAAAAAAAAAA", 73 | "AAAAAAAAAAACAAAADQAAAAkAAAAQAAAAAAAAAA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPAAAAEAAAAAQAAAAAAAAAAAAAgL8RAAAA", 74 | "EgAAAAEAAAAEAAAAAAAAAAAEAAAAEwAAAAEAAAAEAAAAAAAAAAAFAAAAFAAAABUAAAAAAAAAAAAAAAAAFgAAAAkAAAAQAAAAAAAAABcAAAAAAAAAAAAAAAAA", 75 | "AAAAAAAAAA/J7U/Ev9RHmOOY0CDtAukRAAAAAAAAAA==" 76 | ] 77 | }, 78 | "Objects": [ 79 | "Object:/Script/CoreUObject.Class /Script/Engine.Actor", 80 | "Object:/Script/Engine.SimpleConstructionScript /Game/BP_Actor_Simple.BP_Actor_Simple_C:SimpleConstructionScript_0", 81 | "Object:/Script/Engine.EdGraph /Game/BP_Actor_Simple.BP_Actor_Simple:EventGraph", 82 | "Object:/Script/Engine.EdGraph /Game/BP_Actor_Simple.BP_Actor_Simple:UserConstructionScript", 83 | "Object:/Script/UnrealEd.SceneThumbnailInfo /Game/BP_Actor_Simple.BP_Actor_Simple:SceneThumbnailInfo_0", 84 | "Object:/Script/Engine.BlueprintGeneratedClass /Game/BP_Actor_Simple.BP_Actor_Simple_C" 85 | ], 86 | "Names": [ 87 | "ParentClass", 88 | "ObjectProperty", 89 | "BlueprintSystemVersion", 90 | "IntProperty", 91 | "SimpleConstructionScript", 92 | "UbergraphPages", 93 | "ArrayProperty", 94 | "FunctionGraphs", 95 | "LastEditedDocuments", 96 | "StructProperty", 97 | "EditedDocumentInfo", 98 | "EditedObjectPath", 99 | "SoftObjectPath", 100 | "SavedViewOffset", 101 | "Vector2D", 102 | "SavedZoomAmount", 103 | "FloatProperty", 104 | "None", 105 | "ThumbnailInfo", 106 | "GeneratedClass", 107 | "bLegacyNeedToPurgeSkelRefs", 108 | "BoolProperty", 109 | "BlueprintGuid", 110 | "Guid" 111 | ], 112 | "SoftObjectPaths": [ 113 | "Object:/Game/BP_Actor_Simple.BP_Actor_Simple_C:SimpleConstructionScript_0", 114 | "Object:/Game/BP_Actor_Simple.BP_Actor_Simple:UserConstructionScript", 115 | "Object:/Game/BP_Actor_Simple.BP_Actor_Simple:EventGraph" 116 | ] 117 | } 118 | } 119 | }, 120 | "BP_Actor_Simple_C": { 121 | "__Class": "Class /Script/Engine.BlueprintGeneratedClass", 122 | "__SuperStruct": "Class /Script/Engine.Actor", 123 | "__ObjectFlags": 9, 124 | "__bIsAsset": true, 125 | "__Value": { 126 | "Data": { 127 | "Digest": "7c90b254dc8ce36d9252e841b03533c9882d3412", 128 | "Base64": [ 129 | "AAAAAAEAAAAEAAAAAAAAAAAAAAAAAgAAAAAAAAABAAAAAAAAAAEAAAABAAAAAwAAAAEAIAABAAAAAQAAAAQAAAAIAAAARGVmYXVsdAABAAAACAAAAAQACAAE", 130 | "AAAAAAACAAAAAAIAAAAAAAAAAAAAAAAAAAAECIQAAwAAAAUAAAAEAAAAAAAAAAAAAAACAAAAAAAAAAUAAAA=" 131 | ] 132 | }, 133 | "Objects": [ 134 | "Object:/Script/Engine.SimpleConstructionScript /Game/BP_Actor_Simple.BP_Actor_Simple_C:SimpleConstructionScript_0", 135 | "Object:/Script/CoreUObject.Class /Script/Engine.Actor", 136 | "Object:/Script/CoreUObject.Class /Script/Engine.SceneComponent", 137 | "Object:/Script/CoreUObject.Class /Script/CoreUObject.Object", 138 | "Object:/Script/Engine.Blueprint /Game/BP_Actor_Simple.BP_Actor_Simple", 139 | "Object:/Game/BP_Actor_Simple.BP_Actor_Simple_C /Game/BP_Actor_Simple.Default__BP_Actor_Simple_C" 140 | ], 141 | "Names": [ 142 | "SimpleConstructionScript", 143 | "ObjectProperty", 144 | "None", 145 | "DefaultSceneRoot", 146 | "Category", 147 | "Engine" 148 | ] 149 | } 150 | }, 151 | "Default__BP_Actor_Simple_C": { 152 | "__Class": "BlueprintGeneratedClass /Game/BP_Actor_Simple.BP_Actor_Simple_C", 153 | "__ObjectFlags": 49, 154 | "__Value": { 155 | "Data": "Base64:AAAAAAAAAAA=", 156 | "Objects": [ 157 | null 158 | ], 159 | "Names": [ 160 | "None" 161 | ] 162 | } 163 | }, 164 | "BP_Actor_Simple:EventGraph": { 165 | "__Class": "Class /Script/Engine.EdGraph", 166 | "__Outer": "Blueprint /Game/BP_Actor_Simple.BP_Actor_Simple", 167 | "__ObjectFlags": 8, 168 | "__Value": { 169 | "Properties": { 170 | "Schema": { 171 | "__Type": "ObjectProperty", 172 | "__Value": "Object:/Script/CoreUObject.Class /Script/BlueprintGraph.EdGraphSchema_K2" 173 | }, 174 | "Nodes": { 175 | "__Type": "ArrayProperty", 176 | "__InnerType": "ObjectProperty", 177 | "__Value": [ 178 | "Object:/Script/BlueprintGraph.K2Node_Event /Game/BP_Actor_Simple.BP_Actor_Simple:EventGraph.K2Node_Event_0", 179 | "Object:/Script/BlueprintGraph.K2Node_Event /Game/BP_Actor_Simple.BP_Actor_Simple:EventGraph.K2Node_Event_1", 180 | "Object:/Script/BlueprintGraph.K2Node_Event /Game/BP_Actor_Simple.BP_Actor_Simple:EventGraph.K2Node_Event_2" 181 | ] 182 | }, 183 | "bAllowDeletion": { 184 | "__Type": "BoolProperty", 185 | "__Value": 0 186 | }, 187 | "GraphGuid": { 188 | "__Type": "StructProperty", 189 | "__StructName": "Guid", 190 | "__Value": "80D7644A4C053D71DC2DD3957E802C71" 191 | } 192 | } 193 | } 194 | }, 195 | "BP_Actor_Simple:UserConstructionScript": { 196 | "__Class": "Class /Script/Engine.EdGraph", 197 | "__Outer": "Blueprint /Game/BP_Actor_Simple.BP_Actor_Simple", 198 | "__ObjectFlags": 8, 199 | "__Value": { 200 | "Properties": { 201 | "Schema": { 202 | "__Type": "ObjectProperty", 203 | "__Value": "Object:/Script/CoreUObject.Class /Script/BlueprintGraph.EdGraphSchema_K2" 204 | }, 205 | "Nodes": { 206 | "__Type": "ArrayProperty", 207 | "__InnerType": "ObjectProperty", 208 | "__Value": [ 209 | "Object:/Script/BlueprintGraph.K2Node_FunctionEntry /Game/BP_Actor_Simple.BP_Actor_Simple:UserConstructionScript.K2Node_FunctionEntry_0" 210 | ] 211 | }, 212 | "bAllowDeletion": { 213 | "__Type": "BoolProperty", 214 | "__Value": 0 215 | }, 216 | "GraphGuid": { 217 | "__Type": "StructProperty", 218 | "__StructName": "Guid", 219 | "__Value": "62BB7F164F284D40007185972DF6D63F" 220 | } 221 | } 222 | } 223 | }, 224 | "BP_Actor_Simple:EventGraph.K2Node_Event_0": { 225 | "__Class": "Class /Script/BlueprintGraph.K2Node_Event", 226 | "__Outer": "EdGraph /Game/BP_Actor_Simple.BP_Actor_Simple:EventGraph", 227 | "__ObjectFlags": 8, 228 | "__Value": { 229 | "BaseClassAutoGen": { 230 | "Data": { 231 | "Digest": "3010a4471c0269a54720aaae696bc4e0f0ae324a", 232 | "Base64": [ 233 | "AAAAAAEAAAAuAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAEAAAABAAAAAAAAAAAAAAAAAUAAAAGAAAABAAAAAAAAAAABwAAAAgAAAAJAAAACgAA", 234 | "AAAAAAAAAAAAAQALAAAADAAAAAQAAAAAAAAADQAAAAAOAAAADwAAAAoAAAAAAAAAAAAAAAEAEAAAAAoAAAAAAAAAAAAAAAEAEQAAABIAAABYAAAAAAAAAABU", 235 | "AAAAVGhpcyBub2RlIGlzIGRpc2FibGVkIGFuZCB3aWxsIG5vdCBiZSBjYWxsZWQuCkRyYWcgb2ZmIHBpbnMgdG8gYnVpbGQgZnVuY3Rpb25hbGl0eS4AEwAA", 236 | "AAEAAAAQAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAErEMMhye4dDkwlWjvBkyBsIAAAAAAAAAAIAAAAAAAAAAQAAAOt2CaTCkRFIk6vV5P/B4rQBAAAA", 237 | "63YJpMKREUiTq9Xk/8HitBUAAAAAAAAA/wAAAAD/////AAAAAAEWAAAACAAAAAIAAAAAAAAAAAAAAAAAAAAABwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", 238 | "AAAAAAAAAAAAAAAAAAIAAAAAAAAA/wAAAAAAAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAB5FgZWkOSFDtXa0O68Lx/gBAAAA", 239 | "HkWBlaQ5IUO1drQ7rwvH+BcAAAAAAAAA/wAAAAD/////AAAAAAEYAAAACAAAAAIAAAAAAAAAAAAAAAACAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", 240 | "AAAAAAAAAAAAAAAAAAIAAAAAAAAA/wAAAAAAAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" 241 | ] 242 | }, 243 | "Objects": [ 244 | "Object:/Script/CoreUObject.Class /Script/Engine.Actor", 245 | "Object:/Script/BlueprintGraph.K2Node_Event /Game/BP_Actor_Simple.BP_Actor_Simple:EventGraph.K2Node_Event_0", 246 | null 247 | ], 248 | "Names": [ 249 | "EventReference", 250 | "StructProperty", 251 | "MemberReference", 252 | "MemberParent", 253 | "ObjectProperty", 254 | "MemberName", 255 | "NameProperty", 256 | "ReceiveBeginPlay", 257 | "None", 258 | "bOverrideFunction", 259 | "BoolProperty", 260 | "EnabledState", 261 | "EnumProperty", 262 | "ENodeEnabledState", 263 | "ENodeEnabledState::Disabled", 264 | "bCommentBubblePinned", 265 | "bCommentBubbleVisible", 266 | "NodeComment", 267 | "StrProperty", 268 | "NodeGuid", 269 | "Guid", 270 | "OutputDelegate", 271 | "delegate", 272 | "then", 273 | "exec" 274 | ] 275 | } 276 | } 277 | }, 278 | "BP_Actor_Simple:EventGraph.K2Node_Event_1": { 279 | "__Class": "Class /Script/BlueprintGraph.K2Node_Event", 280 | "__Outer": "EdGraph /Game/BP_Actor_Simple.BP_Actor_Simple:EventGraph", 281 | "__ObjectFlags": 8, 282 | "__Value": { 283 | "BaseClassAutoGen": { 284 | "Data": { 285 | "Digest": "e3b3b9cc96a99308ee01d552146996c4337522bf", 286 | "Base64": [ 287 | "AAAAAAEAAAAuAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAEAAAABAAAAAAAAAAAAAAAAAUAAAAGAAAABAAAAAAAAAAABwAAAAgAAAAJAAAACgAA", 288 | "AAAAAAAAAAAAAQALAAAADAAAAAQAAAAAAAAAANAAAAANAAAADgAAAAQAAAAAAAAADwAAAAAQAAAAEQAAAAoAAAAAAAAAAAAAAAEAEgAAAAoAAAAAAAAAAAAA", 289 | "AAEAEwAAABQAAABYAAAAAAAAAABUAAAAVGhpcyBub2RlIGlzIGRpc2FibGVkIGFuZCB3aWxsIG5vdCBiZSBjYWxsZWQuCkRyYWcgb2ZmIHBpbnMgdG8gYnVp", 290 | "bGQgZnVuY3Rpb25hbGl0eS4AFQAAAAEAAAAQAAAAAAAAABYAAAAAAAAAAAAAAAAAAAAAAAAAAFrQJUwFeA5Ou5uMIryPUq0IAAAAAAAAAAMAAAAAAAAAAQAA", 291 | "ABCQu7JBkuxGu4hOZYadL6MBAAAAEJC7skGS7Ea7iE5lhp0voxcAAAAAAAAA/wAAAAD/////AAAAAAEYAAAACAAAAAIAAAAAAAAAAAAAAAAAAAAABwAAAAAA", 292 | "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAA/wAAAAAAAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA", 293 | "ACQpWe2xfPRDmqFkTo897woBAAAAJClZ7bF89EOaoWROjz3vChkAAAAAAAAA/wAAAAD/////AAAAAAEaAAAACAAAAAIAAAAAAAAAAAAAAAACAAAACAAAAAAA", 294 | "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAA/wAAAAAAAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA", 295 | "AFDKR5O36itDhQXpXBnWB3MBAAAAUMpHk7fqK0OFBelcGdYHcxsAAAAAAAAA/wAAAAD/////IwAAAE90aGVyIEFjdG9yCkFjdG9yIE9iamVjdCBSZWZlcmVu", 296 | "Y2UAARwAAAAIAAAAAAAAAAAAAAAAAAAAAAIAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAD/AAAAAAAAAAAAAAAA", 297 | "AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=" 298 | ] 299 | }, 300 | "Objects": [ 301 | "Object:/Script/CoreUObject.Class /Script/Engine.Actor", 302 | "Object:/Script/BlueprintGraph.K2Node_Event /Game/BP_Actor_Simple.BP_Actor_Simple:EventGraph.K2Node_Event_1", 303 | null 304 | ], 305 | "Names": [ 306 | "EventReference", 307 | "StructProperty", 308 | "MemberReference", 309 | "MemberParent", 310 | "ObjectProperty", 311 | "MemberName", 312 | "NameProperty", 313 | "ReceiveActorBeginOverlap", 314 | "None", 315 | "bOverrideFunction", 316 | "BoolProperty", 317 | "NodePosY", 318 | "IntProperty", 319 | "EnabledState", 320 | "EnumProperty", 321 | "ENodeEnabledState", 322 | "ENodeEnabledState::Disabled", 323 | "bCommentBubblePinned", 324 | "bCommentBubbleVisible", 325 | "NodeComment", 326 | "StrProperty", 327 | "NodeGuid", 328 | "Guid", 329 | "OutputDelegate", 330 | "delegate", 331 | "then", 332 | "exec", 333 | "OtherActor", 334 | "object" 335 | ] 336 | } 337 | } 338 | }, 339 | "BP_Actor_Simple:EventGraph.K2Node_Event_2": { 340 | "__Class": "Class /Script/BlueprintGraph.K2Node_Event", 341 | "__Outer": "EdGraph /Game/BP_Actor_Simple.BP_Actor_Simple:EventGraph", 342 | "__ObjectFlags": 8, 343 | "__Value": { 344 | "BaseClassAutoGen": { 345 | "Data": { 346 | "Digest": "98daf35e4938c7a8412e6067ffab274146e7924e", 347 | "Base64": [ 348 | "AAAAAAEAAAAuAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAEAAAABAAAAAAAAAAAAAAAAAUAAAAGAAAABAAAAAAAAAAABwAAAAgAAAAJAAAACgAA", 349 | "AAAAAAAAAAAAAQALAAAADAAAAAQAAAAAAAAAAKABAAANAAAADgAAAAQAAAAAAAAADwAAAAAQAAAAEQAAAAoAAAAAAAAAAAAAAAEAEgAAAAoAAAAAAAAAAAAA", 350 | "AAEAEwAAABQAAABYAAAAAAAAAABUAAAAVGhpcyBub2RlIGlzIGRpc2FibGVkIGFuZCB3aWxsIG5vdCBiZSBjYWxsZWQuCkRyYWcgb2ZmIHBpbnMgdG8gYnVp", 351 | "bGQgZnVuY3Rpb25hbGl0eS4AFQAAAAEAAAAQAAAAAAAAABYAAAAAAAAAAAAAAAAAAAAAAAAAAE5UY/6qyqNMrmjiWuqwZQYIAAAAAAAAAAMAAAAAAAAAAQAA", 352 | "AJqvoqoJhsRDm8XX4xLF6IcBAAAAmq+iqgmGxEObxdfjEsXohxcAAAAAAAAA/wAAAAD/////AAAAAAEYAAAACAAAAAIAAAAAAAAAAAAAAAAAAAAABwAAAAAA", 353 | "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAA/wAAAAAAAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA", 354 | "AMxc37R4qyFEn2iBanIz59ABAAAAzFzftHirIUSfaIFqcjPn0BkAAAAAAAAA/wAAAAD/////AAAAAAEaAAAACAAAAAIAAAAAAAAAAAAAAAACAAAACAAAAAAA", 355 | "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAA/wAAAAAAAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA", 356 | "AGY5Q/lkzOBChxv07QHqyxUBAAAAZjlD+WTM4EKHG/TtAerLFRsAAAAAAAAA/wAAAAD/////JwAAAERlbHRhIFNlY29uZHMKRmxvYXQgKHNpbmdsZS1wcmVj", 357 | "aXNpb24pAAEcAAAAHQAAAAIAAAAAAAAAAAAAAAACAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAMC4wAAQAAAAwLjAAAgAAAAAAAAD/", 358 | "AAAAAAAAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=" 359 | ] 360 | }, 361 | "Objects": [ 362 | "Object:/Script/CoreUObject.Class /Script/Engine.Actor", 363 | "Object:/Script/BlueprintGraph.K2Node_Event /Game/BP_Actor_Simple.BP_Actor_Simple:EventGraph.K2Node_Event_2", 364 | null 365 | ], 366 | "Names": [ 367 | "EventReference", 368 | "StructProperty", 369 | "MemberReference", 370 | "MemberParent", 371 | "ObjectProperty", 372 | "MemberName", 373 | "NameProperty", 374 | "ReceiveTick", 375 | "None", 376 | "bOverrideFunction", 377 | "BoolProperty", 378 | "NodePosY", 379 | "IntProperty", 380 | "EnabledState", 381 | "EnumProperty", 382 | "ENodeEnabledState", 383 | "ENodeEnabledState::Disabled", 384 | "bCommentBubblePinned", 385 | "bCommentBubbleVisible", 386 | "NodeComment", 387 | "StrProperty", 388 | "NodeGuid", 389 | "Guid", 390 | "OutputDelegate", 391 | "delegate", 392 | "then", 393 | "exec", 394 | "DeltaSeconds", 395 | "real", 396 | "float" 397 | ] 398 | } 399 | } 400 | }, 401 | "BP_Actor_Simple:UserConstructionScript.K2Node_FunctionEntry_0": { 402 | "__Class": "Class /Script/BlueprintGraph.K2Node_FunctionEntry", 403 | "__Outer": "EdGraph /Game/BP_Actor_Simple.BP_Actor_Simple:UserConstructionScript", 404 | "__ObjectFlags": 8, 405 | "__Value": { 406 | "BaseClassAutoGen": { 407 | "Data": { 408 | "Digest": "da857612cee7916519bd235beb4b8d02da47ae57", 409 | "Base64": [ 410 | "AAAAAAEAAAAuAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAEAAAABAAAAAAAAAAAAAAAAAUAAAAGAAAABAAAAAAAAAAABwAAAAgAAAAJAAAAAQAA", 411 | "ABAAAAAAAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAcDt3wFpStUekfzhJGpRyHAgAAAAAAAAAAQAAAAAAAAABAAAA81AWZG2BT0Wh6ad7uJPjaQEAAADzUBZk", 412 | "bYFPRaHpp3u4k+NpCwAAAAAAAAD/AAAAAP////8AAAAAAQwAAAAIAAAAAgAAAAAAAAAAAAAAAAIAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", 413 | "AAAAAAAAAAAAAgAAAAAAAAD/AAAAAAAAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=" 414 | ] 415 | }, 416 | "Objects": [ 417 | "Object:/Script/CoreUObject.Class /Script/Engine.Actor", 418 | "Object:/Script/BlueprintGraph.K2Node_FunctionEntry /Game/BP_Actor_Simple.BP_Actor_Simple:UserConstructionScript.K2Node_FunctionEntry_0", 419 | null 420 | ], 421 | "Names": [ 422 | "FunctionReference", 423 | "StructProperty", 424 | "MemberReference", 425 | "MemberParent", 426 | "ObjectProperty", 427 | "MemberName", 428 | "NameProperty", 429 | "UserConstructionScript", 430 | "None", 431 | "NodeGuid", 432 | "Guid", 433 | "then", 434 | "exec" 435 | ] 436 | } 437 | } 438 | }, 439 | "PackageMetaData": { 440 | "__Class": "Class /Script/CoreUObject.MetaData", 441 | "__ObjectFlags": 2, 442 | "__bNotForClient": true, 443 | "__bNotForServer": true, 444 | "__Value": { 445 | "Properties": {}, 446 | "ObjectMetaDataMap": [ 447 | [ 448 | "Object:/Script/BlueprintGraph.K2Node_FunctionEntry /Game/BP_Actor_Simple.BP_Actor_Simple:UserConstructionScript.K2Node_FunctionEntry_0", 449 | [ 450 | [ 451 | "DefaultGraphNode", 452 | "true" 453 | ] 454 | ] 455 | ], 456 | [ 457 | null, 458 | [ 459 | [ 460 | "BlueprintInternalUseOnly", 461 | "true" 462 | ], 463 | [ 464 | "Comment", 465 | "/**\n\t * Construction script, the place to spawn components and do other setup.\n\t * @note Name used in CreateBlueprint function\n\t */" 466 | ], 467 | [ 468 | "DisplayName", 469 | "Construction Script" 470 | ], 471 | [ 472 | "ModuleRelativePath", 473 | "Classes/GameFramework/Actor.h" 474 | ], 475 | [ 476 | "ToolTip", 477 | "Construction script, the place to spawn components and do other setup.\n@note Name used in CreateBlueprint function" 478 | ] 479 | ] 480 | ], 481 | [ 482 | null, 483 | [ 484 | [ 485 | "BlueprintType", 486 | "true" 487 | ] 488 | ] 489 | ], 490 | [ 491 | "Object:/Script/Engine.BlueprintGeneratedClass /Game/BP_Actor_Simple.BP_Actor_Simple_C", 492 | [ 493 | [ 494 | "BlueprintType", 495 | "true" 496 | ] 497 | ] 498 | ], 499 | [ 500 | "Object:/Script/BlueprintGraph.K2Node_Event /Game/BP_Actor_Simple.BP_Actor_Simple:EventGraph.K2Node_Event_0", 501 | [ 502 | [ 503 | "DefaultGraphNode", 504 | "true" 505 | ] 506 | ] 507 | ], 508 | [ 509 | "Object:/Script/BlueprintGraph.K2Node_Event /Game/BP_Actor_Simple.BP_Actor_Simple:EventGraph.K2Node_Event_1", 510 | [ 511 | [ 512 | "DefaultGraphNode", 513 | "true" 514 | ] 515 | ] 516 | ], 517 | [ 518 | "Object:/Script/BlueprintGraph.K2Node_Event /Game/BP_Actor_Simple.BP_Actor_Simple:EventGraph.K2Node_Event_2", 519 | [ 520 | [ 521 | "DefaultGraphNode", 522 | "true" 523 | ] 524 | ] 525 | ] 526 | ], 527 | "RootMetaDataMap": [ 528 | [ 529 | "PackageLocalizationNamespace", 530 | "50B4947A4816F182AF72CC889D9D0EB8" 531 | ] 532 | ] 533 | } 534 | }, 535 | "BP_Actor_Simple_C:DefaultSceneRoot_GEN_VARIABLE": { 536 | "__Class": "Class /Script/Engine.SceneComponent", 537 | "__Outer": "BlueprintGeneratedClass /Game/BP_Actor_Simple.BP_Actor_Simple_C", 538 | "__ObjectFlags": 41, 539 | "__Value": { 540 | "BaseClassAutoGen": { 541 | "Data": "Base64:AAAAAAEAAAAAAAAAAAAAAAEAAgAAAAAAAAA=", 542 | "Names": [ 543 | "bVisualizeComponent", 544 | "BoolProperty", 545 | "None" 546 | ] 547 | } 548 | } 549 | }, 550 | "BP_Actor_Simple:SceneThumbnailInfo_0": { 551 | "__Class": "Class /Script/UnrealEd.SceneThumbnailInfo", 552 | "__Outer": "Blueprint /Game/BP_Actor_Simple.BP_Actor_Simple", 553 | "__ObjectFlags": 8, 554 | "__Value": { 555 | "BaseClassAutoGen": { 556 | "Data": "Base64:AAAAAAAAAAA=", 557 | "Names": [ 558 | "None" 559 | ] 560 | } 561 | } 562 | }, 563 | "BP_Actor_Simple_C:SimpleConstructionScript_0.SCS_Node_0": { 564 | "__Class": "Class /Script/Engine.SCS_Node", 565 | "__Outer": "SimpleConstructionScript /Game/BP_Actor_Simple.BP_Actor_Simple_C:SimpleConstructionScript_0", 566 | "__ObjectFlags": 8, 567 | "__Value": { 568 | "BaseClassAutoGen": { 569 | "Data": { 570 | "Digest": "09e3221fe1e01809393718552a21d9282757908c", 571 | "Base64": [ 572 | "AAAAAAEAAAAEAAAAAAAAAAAAAAAAAgAAAAEAAAAEAAAAAAAAAAABAAAAAwAAAAQAAAAlAAAAAAAAAAAIAAAAAAQAAABTQ1MACAAAAERlZmF1bHQACAAAAERl", 573 | "ZmF1bHQABQAAAAYAAAAQAAAAAAAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAOFU8+m//pdCrS+eS124x/wIAAAACQAAAAQAAAAAAAAAAAoAAAALAAAAAAAAAA==" 574 | ] 575 | }, 576 | "Objects": [ 577 | "Object:/Script/CoreUObject.Class /Script/Engine.SceneComponent", 578 | "Object:/Script/Engine.SceneComponent /Game/BP_Actor_Simple.BP_Actor_Simple_C:DefaultSceneRoot_GEN_VARIABLE" 579 | ], 580 | "Names": [ 581 | "ComponentClass", 582 | "ObjectProperty", 583 | "ComponentTemplate", 584 | "CategoryName", 585 | "TextProperty", 586 | "VariableGuid", 587 | "StructProperty", 588 | "Guid", 589 | "InternalVariableName", 590 | "NameProperty", 591 | "DefaultSceneRoot", 592 | "None" 593 | ] 594 | } 595 | } 596 | }, 597 | "BP_Actor_Simple_C:SimpleConstructionScript_0": { 598 | "__Class": "Class /Script/Engine.SimpleConstructionScript", 599 | "__Outer": "BlueprintGeneratedClass /Game/BP_Actor_Simple.BP_Actor_Simple_C", 600 | "__ObjectFlags": 8, 601 | "__Value": { 602 | "BaseClassAutoGen": { 603 | "Data": "Base64:AAAAAAEAAAAIAAAAAAAAAAIAAAAAAQAAAAAAAAADAAAAAQAAAAgAAAAAAAAAAgAAAAABAAAAAAAAAAQAAAACAAAABAAAAAAAAAAAAAAAAAUAAAAAAAAA", 604 | "Objects": [ 605 | "Object:/Script/Engine.SCS_Node /Game/BP_Actor_Simple.BP_Actor_Simple_C:SimpleConstructionScript_0.SCS_Node_0" 606 | ], 607 | "Names": [ 608 | "RootNodes", 609 | "ArrayProperty", 610 | "ObjectProperty", 611 | "AllNodes", 612 | "DefaultSceneRootNode", 613 | "None" 614 | ] 615 | } 616 | } 617 | } 618 | }, 619 | "Summary": { 620 | "Tag": -1641380927, 621 | "LegacyFileVersion": -8, 622 | "LegacyUE3Version": 864, 623 | "FileVersionUE4": 522, 624 | "FileVersionUE5": 1004, 625 | "FileVersionLicenseeUE4": 0, 626 | "CustomVersions": [ 627 | { 628 | "Key": "29E575DDE0A346279D10D276232CDCEA", 629 | "Version": 17 630 | }, 631 | { 632 | "Key": "375EC13C06E448FBB50084F0262A717E", 633 | "Version": 4 634 | }, 635 | { 636 | "Key": "59DA5D5212324948B878597870B8E98B", 637 | "Version": 8 638 | }, 639 | { 640 | "Key": "601D1886AC644F84AA16D3DE0DEAC7D6", 641 | "Version": 59 642 | }, 643 | { 644 | "Key": "697DD581E64F41ABAA4A51ECBEB7B628", 645 | "Version": 59 646 | }, 647 | { 648 | "Key": "9C54D522A8264FBE9421074661B482D0", 649 | "Version": 44 650 | }, 651 | { 652 | "Key": "B0D832E41F894F0DACCF7EB736FD4AA2", 653 | "Version": 10 654 | }, 655 | { 656 | "Key": "CFFC743F43B04480939114DF171D2073", 657 | "Version": 37 658 | }, 659 | { 660 | "Key": "D89B5E4224BD4D468412ACA8DF641779", 661 | "Version": 36 662 | }, 663 | { 664 | "Key": "E4B068EDF49442E9A231DA0B2E46BB41", 665 | "Version": 40 666 | } 667 | ], 668 | "TotalHeaderSize": 0, 669 | "FolderName": "None", 670 | "PackageFlags": 1024, 671 | "NameCount": 107, 672 | "NameOffset": 0, 673 | "LocalizationId": "50B4947A4816F182AF72CC889D9D0EB8", 674 | "GatherableTextDataCount": 1, 675 | "GatherableTextDataOffset": 0, 676 | "ExportCount": 14, 677 | "ExportOffset": 0, 678 | "ImportCount": 18, 679 | "ImportOffset": 0, 680 | "DependsOffset": 0, 681 | "SoftPackageReferencesCount": 0, 682 | "SoftPackageReferencesOffset": 0, 683 | "SearchableNamesOffset": 0, 684 | "ThumbnailTableOffset": 0, 685 | "Guid": "A4C929A946BF2ED15058CBB53ECABC7B", 686 | "PersistentGuid": "46AA6F4949616DB6D6933C9DC1622787", 687 | "GenerationCount": 1, 688 | "Generations": [ 689 | { 690 | "ExportCount": 14, 691 | "NameCount": 107 692 | } 693 | ], 694 | "SavedByEngineVersion": "5.0.3-20979098+++UE5+Release-5.0", 695 | "CompatibleWithEngineVersion": "5.0.0-19505902+++UE5+Release-5.0", 696 | "CompressionFlags": 0, 697 | "CompressedChunks": [], 698 | "PackageSource": 81731590, 699 | "AdditionalPackagesToCook": [], 700 | "AssetRegistryDataOffset": 0, 701 | "BulkDataStartOffset": 0, 702 | "WorldTileInfoDataOffset": 0, 703 | "ChunkIDs": [], 704 | "PreloadDependencyCount": 0, 705 | "PreloadDependencyOffset": 0, 706 | "NamesReferencedFromExportDataCount": 81, 707 | "PayloadTocOffset": -1 708 | } 709 | } --------------------------------------------------------------------------------