← Knowledge base
README
readmev1updated 5h ago
7 Days to Die Modding Knowledgebase
Shared knowledgebase for 7DTD mod development. Used by multiple projects (7nes, 7builder, PixelPaste).
Modding Fundamentals
- Mod Structure — Folder layout, ModInfo.xml, DLL loading, modlet system
- XML Patching (XPath) — How to patch vanilla XML configs; sounds system
- Harmony Patching — Harmony prefix/postfix patterns, common targets, reflection
- 7DTD 3.0.0 API Changes — Breaking 2.x→3.0.0 changes: XUi folder split (
Config/XUi/→Config/XUi_InGame/or mod UI silently doesn't load →Window unknown!),Config/Localization.txt→Config/Localization.csv(old name silently ignored → raw keys in tooltips),<ruleset>wrapper removed fromxui.xml,WorldclrIdxparam removal (GetTileEntity/SetBlockRPCnow takeBlockValueRef),ChunkClusters→ChunkCache,RefreshBindings()arg drop,GUIWindowManager.Openoverloads; recompile to surface the C# breaks as compile errors - Localization — Adding translated text keys
- Persistent Mod Config (versioned JSON) — Store user settings under
%AppData%/7DaysToDie/so they survive redeploys; theFillMissing+ per-axisUpgradeXxx()/version-pair migration pattern (evolve schema without wiping tunes); split a shared field into per-variant profiles via a legacy-nullable field +Clone(); per-drone/per-item profiles keyed offItemClass.Name - Crafting Skill Unlock Screen (progression display_entry) — How the Skills → crafting-skill "Unlocks" list is built;
display_entrysimple vs custom forms, theitem=overridesname_keylabel trap, gating a mod recipe behind a skill level, and the CSV comma-quoting gotcha - Blocks — Custom block classes, XPath patches, block properties
- Structural Integrity & Falling Blocks — Stability channel internals (0–15), the
World.AddFallingBlockchoke point, and the two-layer recipe (stability-15 stamp + Harmony prefix) for keeping runtime-moved blocks from collapsing - Moving Blocks at Runtime (SetBlocksRPC) — Relocating world blocks in batches (capture → TE detach →
SetBlocksRPC→ TE reattach) and rendering aBlockValueas a smooth-gliding proxy GameObject viaItemClassBlock.CreateMesh(elevators, moving platforms); rotation/paint baked from the real BlockValue,ToItemValue()strips rotation, layer 16,Origin.position - Elevator Mod - Floor Anchor Model — How the Elevator mod anchors floors/car to
BoundsMin(CurrentOffset= physical truth); the bounds-re-edit trap that silently re-anchored floor 1 at the parked car (fixed 2026-07-10: re-edits keep the ground Y, only reposition the car), and moving the ground floor as a pure relabel (BoundsMin.y += d; CurrentOffset -= d) - Moving Platforms & Riding Entities — Making a runtime-moved collider carry players/zombies/vehicles without blocking their movement: full layer table + collision-matrix facts (13 “Items” touches NO character controller; 16 “TerrainCollision” is ground to everyone), why every fixed-step approach (MovePosition/FixedUpdate, the dormant UFPS
m_Platformcode) stair-steps the camera and looks shaky, the butter-smooth per-render-frame recipe (state-preservingvp_FPControllershift for the local player, suspension physics for driven vehicles), and the filtered vertical-delta carry for KCC entities (InteractiveRigidbodyHandling=false) and parked (voxel-AABB) vehicles - Composite Doors (TEFeatureDoor) — Driving modern vanilla doors from code (
TileEntityComposite+TEFeatureDoor.SetOpen), the two-door-features-per-block gotcha, built-inAutoCloseTimelimits, and subclassingBlockCompositeTileEntityto add radial commands - Locks & Lockpicking (TEFeatureLockable) — 3.0.x lock anatomy (
TEFeatureLockable/TEFeatureLockPickable, legacyTileEntitySecure*gone), where door/storage activation is actually gated, theAllowBlockActivationCommandaggregation contract, and the four read-through Harmony patches for a global lock bypass (zPhone Master Key);ReadOnlySpanpatch param +IsLockedinlining gotchas - Workstations — Workstation blocks, modules, tool slots, XUi window groups
- Items — Custom item definitions, icons (ItemIconAtlas), dynamic item generation
- Power Sources — Custom power generators, TileEntityPowerSource, fuel management, power system C# internals
- Entities — Custom entity classes (NPCs, zombies, animals), AI tasks, drops
- Vehicles — Custom vehicles (drivable mounts, hover bikes),
vehicles.xmlschema, mount/dismount pipeline, seat poses, camera switch, scripted-locomotion gotchas - Networking - Connecting and Chat — ConnectionManager, sending chat via NetPackageChat, JSON escape gotcha in 7debug's /api/command
- Asset Bundles — Loading custom models, particles, sounds from .unity3d bundles
- Assetto Corsa Import (kn5, FSB5, engine audio) — kn5 binary format, FSB5 PCM16 bank extraction, wheel-node-derived orientation/mirroring, the cracked VPEngine SoundRange fade formula for rpm-slice engine audio, and the AssettoCar converter utility
- Runtime Procedural VFX — Runtime LineRenderer/particle effects with no bundle; the
HideAndDontSavetexture/material gotcha, procedural lightning, world→scene space - Runtime Explosions (ExplosionData) —
GameManager.ExplosionServercode-driven blasts; the 3.0.0 silent-no-op gotcha (ExplosionDatareads nestedClasses["Explosion"]keys, not flatExplosion.*) and theExplosionServerclrIdxparam removal - Homing Missiles (lock-on + scripted flight) — GTA-style vehicle homing rockets with no XML/bundle: scripted MonoBehaviour flight (capped turn-rate homing,
Voxel.Raycastcollision, proximity fuse, arm delay), vanillarocketPrefab+m136_fire/m136_rocket_lpasset reuse (.wavloadable viaDataLoader.LoadAsset<AudioClip>), camera-cone lock-on with sticky hold + LOS-from-vehicle (camera rays clip the own E_Vehicle collider), IMGUI detection box, and synthesized beep/tone lock audio; seeOppressor/src/OppressorRockets.cs - Player Feedback Sounds — Stock UI "denied" buzzers (e.g.
missingitemtorepair) and how to play them viaAudio.Manager.PlayInsidePlayerHead - Runtime WAV Loading (AudioClip from disk) — Ship a loose
.wavinResources/and decode it into anAudioClipat runtime (RIFF chunk-walk + PCM→float +AudioClip.Create/SetData) with no asset-bundle rebuild; seeFPV/src/FPVWavLoader.cs - Synthesized Drone Rotor Audio — Procedural racing-quad sound: RPM→pitch model (Unity
AudioSource.pitchclamps at ±3), fundamental-dominant harmonics to avoid rasp, two-pole-filtered prop-wash noise, and an ffmpeg+numpy workflow for tuning a synth against a real recording; seeFPV/src/FPVDroneAudio.cs - Remote Camera World Loading (Drone FPV) — Loading + rendering the world around a camera far from the player body (FPV drone / spectator). Three independent player-centric systems: a ChunkObserver loads voxels/collision (easy — matches vanilla's own player observer), but entity render-fade (
World.SetEntitiesVisibleNearToLocalPlayer→EntityAlive.VisiblityCheckfades models past 90 m from the player camera → real-but-invisible zombies) and Distant-POI DynamicMesh imposters (marble no-collision husks; the hide rule!IsChunkInGameonly fires near the player) each need their own drone-aware nudge - Secondary Camera Feeds (RenderTexture + IMGUI) — Extra in-world cameras (drone feed, pilot PiP): RenderTexture +
GUI.DrawTexturepattern, clone the main camera'sPostProcessLayeror the feed renders dark/flat (privatem_Resourcesvia reflection), PiP of the still-rendering main view by mirroringCamera.mainpose in LateUpdate, per-camera layer hiding viacullingMask - Camera View Switching (First/Third Person) —
SetFirstPersonView/SetCameraAttachedToPlayerinternals;playerCamera.transformIScameraTransform; the cross-mod bug where a temporary view switch leaves the camera + held-item transforms parked and breaks other mods' laser/aim (cone beam, targets own head), and the multi-frame re-assert fix - Escape Menu Pause & World-Save Stall — ESC menu
OnOpen→Pause(true)→ single-playerSaveWorld→RegionFileManager.WaitSaveDone()spins the main thread flushing dirty chunks (1–2s freeze after a roaming ChunkObserver); the log tell (Saving N of chunks took Xms), why close-after-open can't fix it, and the Harmony-freeHudEnabledStates.FullHidegate (defer HUD restore until ESC releases) - Paint & Textures — Block paint texture IDs and the paint system
- Time & Weather Control — Freeze/set the clock (
GameStats TimeOfDayIncPerSec, 0 = frozen, default24000/(DayNightLength*60)re-derived every world start),WeatherManager.force*fields + off sentinels (-1f/ temp-100f,BaseTemperature=70°F), why both need a re-apply enforcer after world load, and blocking player status effects via anEntityBuffs.AddBuffprefix - Reading HID Joysticks (hid.dll) — read RC transmitters/joysticks via setupapi + hid.dll (legacy Input Manager can't); full 8-axis recipe, plus why winmm is a dead end (only 6 slots — HID Ry and Dial are invisible to it)
- Betaflight Rates Math — Faithful Betaflight rateprofile formulas (RC Rate/super rate/expo, throttle MID/EXPO + limit, TPA) for sim flight models; the pre-expo
|stick|superfactor gotcha, max-vel formula, cached-texture IMGUI curve previews, and the FPV csprojGameDirbuild flag - Chunk Observers & Chunk Loading —
AddChunkObserverAPI for loading/displaying terrain around a non-player viewpoint (camera drone); viewDim caps, SP vs MP-client gating, why the whole pipeline is observer-driven (no camera/player gating), the fast-mover trailing-bubble problem (lead the observer), and the vanillachunkobserverconsole command +Time:log line decoding - Unity Sweep Casts & Resting Contact — PhysX box/sphere sweeps report already-overlapping colliders as
distance = 0hits withpoint = (0,0,0),normal = -direction; custom flight physics that bounces/rests on any hit freezes an object resting in ground contact (can't take off even straight up). Fix: skipdistance <= 0hits in movement sweeps + park grounded craft on a small virtual floor - Procedural Texture Fills & Main-Thread Stalls — a 1M-texel minimap fill measured ~4.5–5s on the main thread at spawn regardless of write path (NativeArray vs managed+
SetPixels32— the write path was NOT the cost); never run big texture composition on the main thread — worker-thread render + coalesced jobs +SetPixels32upload pattern. Includes the frame-gap + GC-delta + Harmony-stopwatch stall-probe recipe for attributing silent main-thread freezes - Voxel Light & Scene Brightness —
World.GetLightBrightnessis static sky exposure, not current brightness (1.0 outdoors at midnight, ~0 under a bridge at noon); correct recipe =max(Chunk.GetLight(BLOCK)/15, SkyManager.GetSunIntensity()); SkyManager statics reference - Map Fog & Reveal — Map fog-of-war = which chunks are in the per-player
ChunkObserver.mapDatabase(no hide flag), written only byEntityPlayer.Updatein a 9×9 area around the player.visitmap fulldoes NOT reveal fog (it pregens chunks + caches colors for the world-tile renderer). Correct reveal =MapVisitorto load every chunk + explicitmapDatabase.Add(c.X, c.Z, c.GetMapColors()). Mod console commands auto-register via reflection (no Harmony), butConsoleCmdAbstractoverrides must bepublic(CS0507 gotcha). A fully-populated fog DB freezes spawn ~9s:MapChunkDatabaseByRegion.Loadholdsm_regionsLockthe whole load and the main thread blocks on it first frame after spawn — fix by bulk-decompress + per-region locking (UncoverMapDbLoadPatch) - Runtime Texture Tinting (entity repaint) — Live-recolor an entity's albedo textures from a color picker without hitches: soft double-gated color masks (hard thresholds + JPEG noise = speckle), shade-normalized tint with highlight rolloff (no flat neon clipping), precompute + 256-entry LUT +
GetPixelData+ one-texture-per-frame apply; see OppressorEntityOppressor.cs - World-Space Block UI (look-at buttons) — Re-dress a model-entity block with code-built world-space buttons/labels (hide vanilla renderers, rig on the model transform), the pooled-model-transform lifecycle trap (chunk unload sends the model to GameObjectPool with your rig still attached; renderer hides get stomped on redisplay — re-assert per frame, compare
bed.transformto your anchor), and interact with sub-regions of one block: crosshair-ray → face-plane math inGetActivationText/OnBlockActivated, the wall-panel local frame + mirror trap (viewer right = −X, TextMesh yaw-180), depth-tested TextMesh via Sprites/Default + font atlas, renderQueue layering - Selection Boxes (SelectionBoxManager) — Draw colored world-space wireframe boxes from mod code (bounds editors, zone previews): categories,
AddBox/SetPositionAndSize, captions, show-through-walls, the world-reload invalidation gotcha; plus a DIY dashed-wireframe + fitted per-face TextMesh recipe for when the built-in giant caption text won't do (Unity 2022LegacyRuntime.ttffont note included) - Map System (XUiC_MapArea) — How the M map renders (2048px ring-buffer texture, 1px=1block,
_MainMapPosAndScaleshader globals, FOW = alpha from the per-player map DB); why zoom-out is clamped at 6.15 and the overview-texture technique to zoom out to the whole world (see Uncover mod); Harmony DLL location + publicized-assembly notes
XUi (UI System)
- XUi - Window System — XML window definitions, elements, colors, styles, controls
- XUi - Controllers (C#) — C# XUiController subclasses, bindings, events
- HUD Safe Zones — Top DAY/TIME strip + bottom message/toolbelt strip must not be overlapped by IMGUI or non-HUD-hiding windows
- HUD Compass, DayTime Label & Moving HUD Windows —
XUiC_CompassWindow.ShowCompasspublic static hides the compass strip (label auto-relocates via{showtimenocompass}); day/time/temp binding internals + gates; moving vanilla HUD windows at runtime viaXUiView.Positionwith resolve-capture-enforce self-healing (xui.GetChildById, re-resolve onUiTransform == null) - IMGUI Tracker Stack — Right-side stacked status cards for tracked entities (HP bar + status text + fade in/out). Also covers interactive IMGUI tool overlays (alignment / tuning sliders): always include a typeable text field next to step buttons, expose
static IsOpenso other input listeners can short-circuit (Event.current.Use()doesn't blockInput.GetMouseButtonDown). - zPhone External Apps — External app manifests, JSON page controls, action bridge registration, and held-item tuning patterns.
- Embedded Edge Capture (zPhone WebSurface) — Hidden
msedge --app+ WGC capture + CDP input pipeline; Edge chrome height is not constant (injected infobars like the "browser data" banner shift the page and break fixed-offset click mapping — measurewindow.innerHeightvia the bridge instead), plus user-data-dir/job-object/throttling gotchas. - Native Radial Menu (XUiC_Radial) — Drive the vanilla radial wheel from a mod via
xui.RadialWindow(no XML); hold-key-to-select comes free; custom gear/icon sprites; the 2026-06-29ExplosionServer/clrIdxAPI change.
Prefab & Binary Formats
- TTS File Format — TerraTerrain Storage binary format (voxel grid)
- NIM File Format — Name Index Map binary format (block ID → name)
- Pregen World Format —
Data/Worlds/folder layout;main.ttwheader gotcha - Extracting FMOD Bank Audio (FSB5) & Custom Vehicle Sounds — Carving PCM16 WAVs out of FMOD Studio .bank files (Assetto Corsa soundsets) and wiring them as a vehicle's engine/horn sounds via sounds.xml + bundle clips
- Extracting WEM Audio (Wwise) — Pulling playable WAVs out of Helldivers 2
.patch_0/.streamWwise archives with vgmstream (sourcing mod sound assets) - Block Data Structures — Key data structures for prefab import
- Block Definition Resolution — How block IDs resolve to definitions
- Prefab Import Pipeline — Full flow from prefab selection to placed voxels
Coordinate & Rotation Systems
- Coordinate System — Prefab grid, transforms, TTS iteration order
- Entity Positions — Live runtime world coordinates, origin reposition, sanity ranges, JSON serialization gotchas
- Rotation System — 24 discrete block orientations
- Rotation Types — Per-block rotation constraints
- Multi-Block Rotation — How rotation affects multi-cell blocks
- X-Mirror Rotation — Rotation correction for mirrored prefabs
Quick Reference
| Topic | Key File (vanilla) |
|---|---|
| All window/HUD definitions | Data/Config/XUi/windows.xml |
| Reusable UI component templates | Data/Config/XUi/controls.xml |
| Named color tokens & styles | Data/Config/XUi/styles.xml |
| XUi ruleset / window group registration | Data/Config/XUi/xui.xml |
| Block definitions | Data/Config/blocks.xml |
| Entity class definitions | Data/Config/entityclasses.xml |
| Item definitions | Data/Config/items.xml |
| Item modifier definitions | Data/Config/item_modifiers.xml |
| Quality/item background colors | Data/Config/qualityinfo.xml |
| UI display info (item stats shown in UI) | Data/Config/ui_display.xml |
| Buff/effect definitions | Data/Config/buffs.xml |
| Recipe definitions | Data/Config/recipes.xml |
| Sound definitions | Data/Config/sounds.xml |
| Loot table definitions | Data/Config/loot.xml |
| Loading screen tips | Data/Config/loadingscreen.xml |
Tooling Notes
- ModForge UI Conventions — Compact modal sizing and typography conventions for the ModForge desktop app.
- ModForge Managed Agent Docs — How modman maintains the sentinel blocks in each mod's CLAUDE.md/AGENTS.md; refreshed only when a mod is opened, never via bulk sweep.
- Mod Runtime Memory Attribution — Why OS monitors can show 7DTD process RAM but cannot split one Unity heap by mod; practical ModForge options for approximate per-mod telemetry.
- Renaming a Mod (modman) — Full rename checklist (contents, git mv, gh repo rename + SSH-remote gotcha, stale DLLs, old
Mods/copy); why the folder itself can't be renamed while a modman Claude session is open (session cwd handles) and what to do instead. - Verifying Tauri UIs Headlessly (CDP + IPC mock) — Drive a Tauri 2 + vite frontend in headless Chrome with
__TAURI_INTERNALS__mocked from real backend payload dumps; trusted CDP clicks, screenshots, and event simulation without popping windows on an in-use desktop. - Unity DDS Import Quirks (AC kn5 textures) — DDS layouts AC cars ship that Unity's importer rejects (RGBA masks, A8L8, truncated mips, non-multiple-of-4 BC1/BC3 sizes) and how AssettoCarBuilder repairs each; why odd-sized BC textures must be CPU-decoded, not header-padded (UV stretch).
- ModForge Deploy & Drift Tracking — How the kind counters gate the game-shutdown preflight; robocopy 1224 on memory-mapped DLLs when the game is running; the Stop-hook git-PATH failure that misclassifies code changes as assets; reproducing a deploy outside modman.