MODFORGEWORLD
← 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.txtConfig/Localization.csv (old name silently ignored → raw keys in tooltips), <ruleset> wrapper removed from xui.xml, World clrIdx param removal (GetTileEntity/SetBlockRPC now take BlockValueRef), ChunkClustersChunkCache, RefreshBindings() arg drop, GUIWindowManager.Open overloads; 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; the FillMissing + per-axis UpgradeXxx()/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 off ItemClass.Name
  • Crafting Skill Unlock Screen (progression display_entry) — How the Skills → crafting-skill "Unlocks" list is built; display_entry simple vs custom forms, the item= overrides name_key label 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.AddFallingBlock choke 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 a BlockValue as a smooth-gliding proxy GameObject via ItemClassBlock.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_Platform code) stair-steps the camera and looks shaky, the butter-smooth per-render-frame recipe (state-preserving vp_FPController shift 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-in AutoCloseTime limits, and subclassing BlockCompositeTileEntity to add radial commands
  • Locks & Lockpicking (TEFeatureLockable) — 3.0.x lock anatomy (TEFeatureLockable/TEFeatureLockPickable, legacy TileEntitySecure* gone), where door/storage activation is actually gated, the AllowBlockActivationCommand aggregation contract, and the four read-through Harmony patches for a global lock bypass (zPhone Master Key); ReadOnlySpan patch param + IsLocked inlining 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.xml schema, 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 HideAndDontSave texture/material gotcha, procedural lightning, world→scene space
  • Runtime Explosions (ExplosionData)GameManager.ExplosionServer code-driven blasts; the 3.0.0 silent-no-op gotcha (ExplosionData reads nested Classes["Explosion"] keys, not flat Explosion.*) and the ExplosionServer clrIdx param removal
  • Homing Missiles (lock-on + scripted flight) — GTA-style vehicle homing rockets with no XML/bundle: scripted MonoBehaviour flight (capped turn-rate homing, Voxel.Raycast collision, proximity fuse, arm delay), vanilla rocketPrefab + m136_fire/m136_rocket_lp asset reuse (.wav loadable via DataLoader.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; see Oppressor/src/OppressorRockets.cs
  • Player Feedback Sounds — Stock UI "denied" buzzers (e.g. missingitemtorepair) and how to play them via Audio.Manager.PlayInsidePlayerHead
  • Runtime WAV Loading (AudioClip from disk) — Ship a loose .wav in Resources/ and decode it into an AudioClip at runtime (RIFF chunk-walk + PCM→float + AudioClip.Create/SetData) with no asset-bundle rebuild; see FPV/src/FPVWavLoader.cs
  • Synthesized Drone Rotor Audio — Procedural racing-quad sound: RPM→pitch model (Unity AudioSource.pitch clamps 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; see FPV/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.SetEntitiesVisibleNearToLocalPlayerEntityAlive.VisiblityCheck fades models past 90 m from the player camera → real-but-invisible zombies) and Distant-POI DynamicMesh imposters (marble no-collision husks; the hide rule !IsChunkInGame only 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.DrawTexture pattern, clone the main camera's PostProcessLayer or the feed renders dark/flat (private m_Resources via reflection), PiP of the still-rendering main view by mirroring Camera.main pose in LateUpdate, per-camera layer hiding via cullingMask
  • Camera View Switching (First/Third Person)SetFirstPersonView/SetCameraAttachedToPlayer internals; playerCamera.transform IS cameraTransform; 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 OnOpenPause(true) → single-player SaveWorldRegionFileManager.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-free HudEnabledStates.FullHide gate (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, default 24000/(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 an EntityBuffs.AddBuff prefix
  • 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 csproj GameDir build flag
  • Chunk Observers & Chunk LoadingAddChunkObserver API 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 vanilla chunkobserver console command + Time: log line decoding
  • Unity Sweep Casts & Resting ContactPhysX box/sphere sweeps report already-overlapping colliders as distance = 0 hits with point = (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: skip distance <= 0 hits 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 + SetPixels32 upload pattern. Includes the frame-gap + GC-delta + Harmony-stopwatch stall-probe recipe for attributing silent main-thread freezes
  • Voxel Light & Scene BrightnessWorld.GetLightBrightness is 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 by EntityPlayer.Update in a 9×9 area around the player. visitmap full does NOT reveal fog (it pregens chunks + caches colors for the world-tile renderer). Correct reveal = MapVisitor to load every chunk + explicit mapDatabase.Add(c.X, c.Z, c.GetMapColors()). Mod console commands auto-register via reflection (no Harmony), but ConsoleCmdAbstract overrides must be public (CS0507 gotcha). A fully-populated fog DB freezes spawn ~9s: MapChunkDatabaseByRegion.Load holds m_regionsLock the whole load and the main thread blocks on it first frame after spawn — fix by bulk-decompress + per-region locking (Uncover MapDbLoadPatch)
  • 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 Oppressor EntityOppressor.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.transform to your anchor), and interact with sub-regions of one block: crosshair-ray → face-plane math in GetActivationText/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 2022 LegacyRuntime.ttf font note included)
  • Map System (XUiC_MapArea) — How the M map renders (2048px ring-buffer texture, 1px=1block, _MainMapPosAndScale shader 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 WindowsXUiC_CompassWindow.ShowCompass public static hides the compass strip (label auto-relocates via {showtimenocompass}); day/time/temp binding internals + gates; moving vanilla HUD windows at runtime via XUiView.Position with resolve-capture-enforce self-healing (xui.GetChildById, re-resolve on UiTransform == 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 IsOpen so other input listeners can short-circuit (Event.current.Use() doesn't block Input.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 — measure window.innerHeight via 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-29 ExplosionServer/clrIdx API change.

Prefab & Binary Formats

Coordinate & Rotation Systems

Quick Reference

TopicKey File (vanilla)
All window/HUD definitionsData/Config/XUi/windows.xml
Reusable UI component templatesData/Config/XUi/controls.xml
Named color tokens & stylesData/Config/XUi/styles.xml
XUi ruleset / window group registrationData/Config/XUi/xui.xml
Block definitionsData/Config/blocks.xml
Entity class definitionsData/Config/entityclasses.xml
Item definitionsData/Config/items.xml
Item modifier definitionsData/Config/item_modifiers.xml
Quality/item background colorsData/Config/qualityinfo.xml
UI display info (item stats shown in UI)Data/Config/ui_display.xml
Buff/effect definitionsData/Config/buffs.xml
Recipe definitionsData/Config/recipes.xml
Sound definitionsData/Config/sounds.xml
Loot table definitionsData/Config/loot.xml
Loading screen tipsData/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.