Skip to content

textures

Source: mods/textures.

What it does

aowl.textures — high-res PBR texture replacement. The mod is safe-by-default: with no manifest, no bound hook, or no upload capability, it does nothing and the game uses stock textures. Every key here is declared in textures.nim's settings schema and editable from the F12 panel.

Settings

Defined in mods/textures/config.json. The values shown are the shipped defaults, not what is currently deployed.

enabled

  • Default: true

Master switch. False installs no hooks at all.

swapMode

  • Default: "off"

Crash-proofing escalation ladder. The first live test crashed the game at boot, so the mod ships in 'off'. off: install nothing (game boots, mod just reports). probe: install the VERIFIED LoadAsset hook and count firings only — proves the hook installs and fires without touching any asset. match: also name-match returned textures against the manifest (still no pixels). full: also upload the replacement texture. Move up ONE rung at a time and confirm the game still boots to the menu at each step. On build 1.1.0.1.46777 the hook is installed BY STATIC RVA and the name comes from a direct call at UnityEngine.Object::get_name (0x52AD4B0), because by-name resolution returns non-nil handles into unmapped memory; 'full' additionally needs il2cpp_array_new + LoadImage, which are still resolved by name, so it degrades to match-only and says so in the log. Check "nameSource" and "canUpload" in swapStats.

redirectMode

  • Default: "off"

UNKNOWN — this key carries no doc comment in config.json.

bundleRoot

  • Default: ""

Directory of replacement bundles from the pack pipeline. EMPTY = the redirect is OFF, whatever redirectMode says. Each file MUST be named EXACTLY like the bundle key: no extension is appended, stripped or normalised. Measured on 4.1.2 (fact #73), 214 of 292 in-scope keys carry NO .bundle extension, and appending one made them silently unfindable -- the first build had 214 of 278 dead with no error. Optionally drop an index.txt beside them (one key per line, verbatim; blank lines and # comments skipped) and the whole table is read once at arm time with zero filesystem I/O on the hook path; without it each distinct key costs one cached open() probe.

legacyNameSwap

  • Default: false

RETIRED AND OFF. swap.nim's name-keyed Texture2D substitution, kept only so the measurements that killed it stay reproducible. Nothing ever asks for a texture by name (the chain ends at LoadAllAssetsAsync -> Assets = op.allAssets, a bulk array); Texture2D.LoadImage returns false on a non-readable texture and RE-CREATES rather than mutating; and RGBA32 replacements are 4-8x the BC originals. It also detours the SAME RVA as the redirect, so the two are mutually exclusive and the redirect wins. swapMode is only consulted when this is true.

armDelayMs

  • Default: 15000

How long after the mod loads before hooks are installed. Deferred well past the boot bundle-load storm (where the crash was); the mod also waits until the IL2CPP runtime's metadata is queryable (a well-known Unity type resolves). This is drain-INDEPENDENT: on this build the host's per-frame drain binds no method, and the LoadAsset postfix does not need it (the game calls LoadAsset on the Unity thread, so the postfix runs there for free). 0 arms as soon as the runtime is ready.

hookAsync

  • Default: false

Also hook UnityEngine.AssetBundleRequest::get_asset (async loads). OFF: on build 1.1.0.1.46777 that method is a tail-jump virtual-dispatch thunk (48 8B 11 ... 48 FF E0), which is unsafe to postfix-detour. Leave off unless you have verified it on your build.

quality

  • Default: "2k"

off | 2k | 4k. 2K is the shipped tier. 4K needs the 4K ambientcg pack downloaded (only 2K is present today) and degrades to 2K when a 4K map is absent.

vramBudgetMB

  • Default: 1024

Hard cap on replacement-texture VRAM. A 2K RGBA32 texture with mips is ~22 MB, so 1024 MB is ~46 resident textures. The manifest is the candidate set; this is the resident cap. Raise it only if you have the headroom.

minConfidence

  • Default: 0.5

Runtime floor on name-match confidence, on top of the already-curated manifest. 0.5 matches the original plugin.

probeTargets

  • Default: ""

DIAGNOSTIC, DEFAULT OFF. The multi-target counting probe. Fact #55: eight count-only prefixes on UnityEngine.AssetBundle across a full Factory raid produced ONE call total, with the ab6 control correctly 0 -- so post-1.0 IL2CPP Tarkov does NOT load its assets through Unity's AssetBundle API. The table now also covers BSG's own layer: Diz.Resources.EasyAssets/EasyBundle (the DontDestroyOnLoad root literally named 'Easy Assets'), EFT.AssetsManager.AssetsManager/BundlesManager, EFT.EasyAssetsExtensions, EFT.AssetsManager.AssetBundleExtension::FixAssetName, and TextureCache::TryGet/Cache -- the only pair in the table whose NAME implies a Texture, which is the swap point. Value: a comma list of GROUPS (ab eb ea am bm ex tc abx bsg all) or TAGS (ab6 eb42 am100582 tc56889 ...). Rids are per-IMAGE and COLLIDE across these eight types, so a bare number resolves ONLY inside the ab group, preserving the meaning of the fact-#55 run. Start with 'bsg'. ab6 is the CONTROL and must read 0. Requires swapMode 'off': swap.nim postfixes ab6 and two detours on one function kill the first silently, so the probe refuses whole rather than run a contaminated measurement.

logMatches

  • Default: true

UNKNOWN — this key carries no doc comment in config.json.

albedoOnly

  • Default: true

Only albedo is COLOUR (fact #36). normal/roughness/ao/height/metalness are DATA and must not be gamma-decoded as sRGB. ImageConversion.LoadImage decodes into the texture the game already created and takes no colour-space argument, and the mod cannot establish offline what sRGB flag each destination texture was created with -- so non-albedo entries are matched, counted (refusedNonAlbedo in swapStats) and NOT swapped. Turn off only after verifying the colour space on your build.

catMetal

  • Default: true

UNKNOWN — this key carries no doc comment in config.json.

catWood

  • Default: true

UNKNOWN — this key carries no doc comment in config.json.

catConcrete

  • Default: true

UNKNOWN — this key carries no doc comment in config.json.

catBrick

  • Default: true

UNKNOWN — this key carries no doc comment in config.json.

catFabric

  • Default: true

UNKNOWN — this key carries no doc comment in config.json.

catGround

  • Default: false

UNKNOWN — this key carries no doc comment in config.json.

packRoot

  • Default: "<HOME>/Projects/TarkovTextures"

Absolute path to where the replacement images live. The committed manifest stores paths relative to the TarkovTextures root (e.g. ambientcg/Metal/.../Foo_2K-JPG_Color.jpg), so packRoot must point at that root — or at a self-contained pack assembled by build_pack.py --copy, whose manifest is pack-relative. Empty falls back to the mod's own data/pack. For deployment see README.md: run build_pack.py --copy <install>/mods/textures/data/pack and set packRoot to that (or leave empty to use the data/pack fallback).

aoughwl — self-hosted platform for things n stuff. Contact / Support on Discord for access to the private backends.