A web-based custom picture pack creator for 7 Days to Die V2.6. Upload your art, drop it into vanilla painting / poster / canvas / frame slots across 69 swap targets, download a ready-to-install modlet. Every painting in every POI ~ plus snack posters, movie posters, picture frames, hidden-safe disguises ~ now wears your art. No Unity, no asset bundles, no prefab hacks. A Harmony runtime swap does the heavy lifting at world load.
- Pick a category ~ tabbed builder with a live
X/Y filledbadge per category and a sticky download bar always within reach. - Upload an image per slot you want to override. Skipped slots stay vanilla.
- Crop ~ aspect-locked crop matched per slot kind (3:4 portraits, 1:1 abstracts, atlas-tile aspects for movie posters / canvases / picture frames).
- Frame style ~ portraits + picture frames each take a wood/metal preset (dark wood, light wood, gold gilt, silver, matte black, ornate gold). Portraits paint the preset into a UV strip wrapping the 3D frame mesh; picture frames apply it as a multiply-blend tint over the wood-frame zone of the atlas.
- Title each slot ~ shows up as
Print: <your title>in the creative menu, searchable under "print" or any keyword. - Download ~ a complete modlet zip with the shared
KitsunePrints.dll, composed textures (per-slot for portraits/abstracts/decor; per-shared-atlas for movie posters / canvases / picture frames), generatedblocks.xml(with optional inlineCanPickuppatches for ~100 vanilla decor blocks) /recipes.xml/Localization.txt, ItemIcons, and apicture_pack.jsonmap. Drop into<7DTD>/Mods/, restart, done.
The full pack state (slot titles, frame choices, pack info) auto-saves to your browser's localStorage so you don't lose work on reload. Images are session-only ~ re-upload them when you come back.
| Category | Slots | What they cover |
|---|---|---|
| Portraits | 6 | 1Γ1 backer paintings (Ben, Lorien, Derek, Noah, Duke, Ken) ~ 3:4 portrait + wood frame strip |
| Abstracts | 4 | Each drives both 2Γ2 and 3Γ2 painting blocks per design (8 vanilla blocks total) |
| Movie Posters | 4 | Tiles of the shared posterMovie 1024Γ1024 atlas. Theater variants ride along ~ replacing one re-skins both blocks. |
| Misc Decor | 5 | Calendar, Pistol/Rifle Blueprints, Target Posters 1+2 |
| Snack Posters | 17 | The full snackPosters_d atlas wall ~ Thick Nick's, Goblin-O's, Bretzels, Eye Candy, Skull Crushers, Nachios Beef + Ranch, Health Bar (wide), Hackers, Prime, Atom, Nerd Tats, Ramen, Jail Breakers, Fort Bites, Oops + Oops Classic |
| Picture Frames | 23 | Per-letter slots across 8 shared atlases (pictureFramed, pictureFramed2..8). Hidden-safe variants re-skin automatically since they extend their non-safe twin. |
| Canvases | 10 | Per-letter slots across 2 shared atlases (pictureCanvas1, pictureCanvas2) |
Every pack ships with <property name="CanPickup" value="true"/> patches that turn vanilla decor blocks into press-E-pickup items. No tool, no recipe ~ walk up, press E, place from inventory. Two opt-in tiers (separate checkboxes on the Pack Info tab):
- Picture core (~83 blocks, default on) ~ all 7 slot categories: paintings, snack posters, movie posters + theaters, canvases, picture frames.
- Extended decor (~224 blocks, default on) ~ flags, road signs, OPEN/CLOSED, gun store + shop signs (unlit variants), bathroom signs, wall clocks, mirrors, bulletin boards, planters, ad signs, gas signs.
Trader signage and lit/electrical signs are deliberately excluded from the extended set ~ traders stay nice, and lit signs would risk the same electrical-init NREs that hidden safes triggered. Hidden-safe disguises are also excluded (they're loot-container TileEntities; CanPickup conflicts with their init).
The pickup patches are inlined into Config/blocks.xml (the canonical filename 7DTD's XmlPatcher reliably loads) ~ a custom pickup.xml was tried in v0.5.x and silently dropped by the loader, so v0.8.2 moved them.
The included KitsunePrints.dll is a single Harmony patch on World.LoadWorld postfix. At runtime it:
- Reads
Config/picture_pack.jsonfor avanilla_material β texture_filenamemap (or falls back to bundled defaults). - Walks
Resources.FindObjectsOfTypeAll<Material>()to find each vanilla material by name. - Replaces
_MainTex(and_BaseMapfor URP) with the user's image, resets UV scale/offset to(1,1)/(0,0)so atlas-tile materials display the full swapped image instead of a tiny crop.
The discovery and swap calls go through IMaterialFinder + IMaterialSwap adapter interfaces, so future game versions (URP/HDRP migration in v3.0/v4.0, Addressables behavior changes, shader property renames) can be handled by swapping in a different implementation without touching the sweep loop. See docs/migration-plan.md for the full v3.x β v4.x risk assessment.
This is shared infrastructure across every pack ~ per-pack only the textures + JSON config + ModInfo + generated XMLs vary. The same DLL works for every pack created by the tool.
Some categories (movie posters, picture frames, canvases) sample tiles from a shared atlas in vanilla ~ multiple block prefabs all use one atlas, each with its own mesh-UV-defined sub-region. For these, the composer:
- Loads the vanilla atlas as a base layer (preserves regions sampled by mesh UVs we don't write to)
- For picture-frame atlases: multiply-blends the chosen frame tint over the top 55% wood-frame zone (wood grain preserved, just recolored)
- Pastes each filled slot's user image into its tile rectangle (rects derived empirically from each prefab's LOD0 mesh UVs ~ see
scripts/read_picture_frame_uvs.pyandscripts/read_movie_poster_uvs.py)
Result: one composite texture file per shared material, with each prefab automatically rendering the right sub-region thanks to vanilla's mesh UVs.
If you'd rather skip the web tool, grab KitsunePrints-DIY-Kit.zip from GitHub Releases ~ Python script + DLL + frame textures + 11 vanilla atlases (~46 MB unzipped) + example config. pip install Pillow, edit a JSON, drop your images, run python make_pack.py example_pack/, get a modlet out. The DIY kit ships every category the web tool ships ~ same 69 slots, same atlas-tile compositing, same press-E pickup.
- 7 Days to Die V2.6 (vanilla material naming, atlas layout, and prefab mesh UVs are version-specific; see migration plan for v3.x/v4.x outlook)
- EAC must be disabled (any DLL-shipping mod requires this)
- No third-party mod dependencies ~ the Harmony patch is self-contained
- Vite + React 19 + TypeScript
- Tailwind CSS v4
- JSZip + react-easy-crop (client-side composition + zip generation, no server-side image processing)
- vitest (43 unit tests gating CI)
- Express (serves the static build + small build-counter API)
- Pillow (Python, DIY-kit-side image composition)
- Harmony / C# (DLL patch ~ source in the KitsunePrints mod repo)
- UnityPy (one-off vanilla atlas + mesh UV extraction; see
scripts/extract_vanilla_refs.py)
src/
pages/ # IntroPage, BuilderPage (tabbed grid + sticky download bar), TermsPage
components/ # SlotCard, FramePresetPicker, CropDialog, PackMetaForm, DownloadButton
utils/
buildModlet.ts # zip orchestration, XML rendering, pickup patch inlining (35 unit tests cover the helpers)
buildModlet.test.ts
composer.ts # composePortrait / composeAbstract / composeAtlas / composeIcon
pickupBlocks.ts # PICKUP_BLOCKS (~83 picture core) + EXTENDED_DECOR_PICKUP_BLOCKS (~224)
persistence.ts # localStorage save/load for slot config + pack meta
types/
slots.ts # SLOTS list + ATLAS_SOURCES + FRAME_PRESETS + isDefaultPackMeta
slots.test.ts
public/
reference/ # KitsunePrints.dll (bundled into every downloaded pack)
frames/ # 6 frame texture presets, 256Γ1024 each
vanilla/ # extracted vanilla reference thumbnails + atlas base layers used by the composer
screenshots/ # in-POI hero + tool screenshots
social-print.png # OG / Twitter card
discord.png # Kitsune Den Discord callout banner
docs/
migration-plan.md # Β§3.4 KitsunePrints addendum to the Kitsune-Den migration handbook
scripts/
make_pack.py # standalone CLI builder (DIY kit's main script)
build_diy_kit.py # packages script + DLL + frames + 11 vanilla atlases into the downloadable zip
extract_vanilla_refs.py # one-off UnityPy extraction of reference thumbs + atlas base layers
read_picture_frame_uvs.py # one-off mesh UV reader for picture frame tile rects
read_movie_poster_uvs.py # one-off mesh UV reader for movie poster tile rects
example_pack/ # example config for the DIY kit
kitsuneprints.service # systemd user unit for the VPS
.github/workflows/
deploy.yml # CI gates on `npm run test`, then auto-deploys to prints.kitsuneden.net
npm install
npm run dev # http://localhost:5173
npm run test # vitest run (35 tests)
npm run build # tsc -b && vite build β dist/
node server.cjs # serve the build on http://localhost:9003DIY kit changes:
python scripts/build_diy_kit.py # rebuild public/KitsunePrints-DIY-Kit.zipDLL changes (different repo, Kitsune-Den/KitsunePrints):
cd KitsunePrints/Harmony && dotnet build -c Release
cp ../KitsunePrints.dll <web-tool-repo>/public/reference/KitsunePrints.dllPushes to main run unit tests, then auto-deploy via GitHub Actions to the DreamHost VPS at prints.kitsuneden.net. See scripts/kitsuneprints.service and .github/workflows/deploy.yml for the systemd + workflow setup.
Required GitHub secrets: VPS_HOST, VPS_USER, VPS_SSH_KEY.
Your images never leave your browser. Composition, icon generation, zip packaging ~ all client-side canvas + JSZip. The only server-side ping is an anonymous fire-and-forget POST /api/built after a successful download, logging only a timestamp and slot count. Slot titles, frame choices, and pack metadata also live in your browser's localStorage and never go anywhere else. See Terms & Privacy.
Architecture is now ready for almost any vanilla wall-art expansion ~ adding a new category to the web tool is mostly: identify the vanilla material(s), add an entry to SLOTS in src/types/slots.ts, and run extract_vanilla_refs.py for reference thumbs. Categories under consideration:
- πͺ§ Trader signage ~ traderBobSign, traderJoelSign, etc., plus the storeSigns01/02_d atlases (Shotgun Messiah, Crackabook, Mo Power, etc.)
- πͺͺ Street + yard signs ~ where they make sense (most are functional, less interesting to re-skin)
- π¨ Cat / dog / sparky standalone posters ~ slot scaffolding identified, materials need a deeper prefab walk
- πͺ Wallpaper / floor tiles ~ bigger lift; same Harmony pattern works in principle
- π§ Slot pre-tour ~ visual gallery on the front page showing every replaceable slot before visitors hit the builder
Tracked issues: #1 (place vanilla paintings in survival) ~ shipped via press-E pickup; #2 (custom inventory icons for picked-up vanilla blocks) ~ closed in v0.8.5; #3 (extended decor pickup ~ flags, signs, etc.) ~ shipped in v0.9.0.
If a specific block or sign you'd love to skin isn't in the slot list, open an issue with its name and we'll see if it's swap-friendly.
- KitsuneDen ~ home server hub
- KitsunePaint ~ custom paint pack creator
- KitsunePrints ~ custom picture pack creator (you are here)
- Join the Discord ~ get support, share builds, suggest new slots
Built by Ada Β· Powered by the Skulk