Skip to content

Garry's Mod

Platform ID com.facepunch.gmod

DigitalHeaven.Mods.GarrysMod Source lets you wear a DigitalHeaven avatar as a native Source playermodel in Garry’s Mod, and every player on the server sees it. Unlike every other mod here, nothing renders at runtime: the avatar is exported to a real .mdl with the game’s own studiomdl, packed into a .gma, and mounted like a Workshop addon.

FeatureStatus
Avatar replacement (native playermodel, all animations)Yes
Avatar picker with 3D preview (C menu)Yes
Managing exports: every avatar listed, several exported at once, exports removedYes
Export settings: proportions, fit, spring bonesYes
Spring bones, as Source jigglebonesYes
Spring collidersNo
First-person viewmodel hands from the avatarYes
Avatars as Friendly and Hostile NPCsYes
Avatars as ragdolls, in a DigitalHeaven spawn menu tabYes
Eye look and blinking, on players and NPCsYes
Other players see your avatar (server relay)Yes
Seeing avatars without the native moduleYes
Late joiners receive current avatarsYes
Exporting on WindowsYes
Exporting on Linux (x86-64 branch; studiomdl under Proton’s Wine)Not yet in game
Exporting on macOSNo
OverlayNo

The addon has two halves, and only the first needs the native module:

  1. Exporting (your machine: Windows on either branch, or Linux on the x86-64 branch). The module (gmcl_digitalheaven_win64.dll, _win32.dll or _linux64.dll) reads your DigitalHeaven workspace (dh-config.jsonc, then DH_WORKSPACE, then ~/Documents/DigitalHeaven), fits the avatar to Valve’s player skeleton, compiles it with Garry’s Mod’s own studiomdl.exe (under Proton’s Wine on Linux, see Source export), and packs garrysmod/data/digitalheaven/avatars/<hash>.gma. The work runs in a helper process, so the game never stalls. The model path is named by the export’s content hash (models/digitalheaven/<hash>.mdl), because Source can’t replace a model that is already loaded.
  2. Syncing (every machine, pure Lua). The server pulls the .gma from you, checks it, mounts it and sets your model. Every other client pulls it from the server, checks it the same way and mounts it. Players without the module, on any OS, still see everyone’s avatar.

The server only accepts a .gma that holds exactly one avatar: models/digitalheaven/<hash> (and its optional _arms hands and _npc NPC model) with the extensions .mdl, .vvd, .phy, .ani and .vtx (.dx90, .dx80, .sw), and .vmt/.vtf files directly in materials/models/digitalheaven/<hash>/. It refuses anything else, including any Lua, a file whose checksum doesn’t match, or a .gma over the size cap. Clients run the same check before they mount.

  1. From Platforms/DigitalHeaven.Mods.GarrysMod/addon, run:
    Terminal window
    powershell -NoProfile -ExecutionPolicy Bypass -File tools\install.ps1
  2. For exporting, build and install the native module and helper: native/build.ps1 then native/install.ps1 (see native/README.md)
  3. Start Garry’s Mod. A first install needs a restart if the game was running; after that, Lua changes apply live

The script installs a legacy folder addon at garrysmod/addons/digitalheaven/ and targets H:\SteamLibrary\steamapps\common\GarrysMod\garrysmod unless you pass -GarrysModDir. It is idempotent: a rerun with nothing changed writes nothing. It records what it installed in install-manifest.json and only ever removes those files. -Uninstall removes them and the empty folders; it never touches garrysmod/data/digitalheaven/, where your exported and received avatars live.

The Linux module needs Garry’s Mod’s x86-64 beta branch: .NET’s NativeAOT has no 32-bit Linux target. native/build-linux.sh builds the module and helper on Linux (on Windows, native/build.ps1 runs it in WSL), and native/install-linux.sh installs the addon, the module and the helper together, on this machine or on another over ssh (--ssh deck@host). Linux installs ship no model compiler, so exporting also needs DH_STUDIOMDL set to a Windows studiomdl.exe with its DLLs, and Proton or Wine; see Source export. Set it in the game’s launch options, for example DH_STUDIOMDL=/path/to/bin/win64/studiomdl.exe %command%.

On a Linux with glibc 2.34 or newer, the x86-64 branch’s own main menu shows Menu failed to load. Its bundled Chromium (80) kills its page renderer with SIGSYS when glibc starts a thread through clone3 (Facepunch issue #5439). The DigitalHeaven window is Derma, not HTML, so it is unaffected: open the console (~), run map gm_construct, and hold C.

The export itself has run end to end on a Steam Machine (SteamOS): the Linux module and helper exported mltn Mayu, mltn Taidum and the stick figure through a stand-in lua_shared.so. The module has not yet been loaded by the game itself, which waits on the x86-64 branch.

Hold C and click the DigitalHeaven icon on the desktop. The window has two tabs: Avatar, to choose what you wear, and Manage, for your exports (see Managing Exports).

  • The window is stock Derma. The spawn menu’s arrangement: blue DForm category bars over a light DCategoryList, the skin’s combo boxes, checkboxes and fonts. Only the avatar picker carries a faint blue tint. Rows show the avatar’s thumbnail when its pallet has one (the module copies it to data/digitalheaven/thumbs/; pallets carry no avatar thumbnails yet), else, for every exported avatar, GMod’s own spawn icon of its export’s model, else the stock user icon. The spawn icon is rendered once per model path, and the path is the export’s content hash, so it changes only when the avatar is exported again, never on a selection. Each shows its barcode in the DigitalHeaven style, split by Core in the module (barcodeParts): the pallet prefix and extension dimmed, the name normal.
  • The picker shows only what you wear. Click it to open the list (click it again, click outside or press Esc to close it): None first, then your workspace’s avatars. Each row has a 48 px thumbnail with a badge on its corner, recreations of the stock silk icons (editable SVGs in Assets/Icons/gmod/badges/): a check (exported and current), a warning sign (out of date), an hourglass (exporting) or a red exclamation (failed; the row’s tooltip says why); a not-exported avatar has no badge and a dimmed thumbnail. The worn avatar’s row is highlighted, and the closed picker uses the same layout. The list is fetched when it opens and is gone when it closes, so a screenshot of the window shows nothing else.
  • Picking starts the export. Seven steps: read the avatar, fit it to Valve’s skeleton, compile the model, compile the hands, compile the NPC, pack, done. The count comes from the export’s events, never assumed. You keep wearing your current avatar until it finishes, then every player switches at once. A new pick replaces an earlier pick still exporting. Exports run one at a time, so a pick made while the Manage tab’s exports run waits behind them (the Avatar tab says Queued (N)).
  • The preview shows the model in game now, and during an export still the old one, dimmed. Drag to turn it, scroll to zoom.
  • The window has no explanatory text. Only labels and states. The status line is empty at rest and speaks only when something runs or needs a hand: Exporting (Cancel), Exporting 2 of 5: name for several (Cancel all), Export failed (Retry, Copy details, with the export’s own message above), Uploading N%, Server refused: … (Retry), Module not installed, Module not ready, No hands / Hands failed, No NPC. Copy details puts the error code, the message, the workspace and the export log on the clipboard.
  • Auto reload. With the Auto reload toggle on (the default), the list is asked for every 5 seconds while you wear an avatar, and when it reports that the worn avatar’s pallet was rebuilt (out of date), the avatar re-exports once and every player switches to the new export. With it off, you keep the export you wear until you pick the avatar again.
  • None puts your Garry’s Mod playermodel back at once.

Your avatar is remembered in data/digitalheaven/worn.json and put back on when you join a server, as long as its .gma is still there.

The Manage tab lists every avatar in your workspace, always, whether exported or not. It’s where you see at a glance what is exported, export several avatars at once, and clear exports away.

  • Each row has a checkbox, the avatar’s spawn icon (dimmed when it isn’t exported), its name over its barcode, its state with the same badges as the picker (Exported, Out of date, Not exported, Export failed), and, for an avatar with an export on disk, when it was exported and its .gma size. The avatar you wear is bold and marked Current.
  • Filters above the list: All, Exported, Out of date, Not exported, and Failed while anything failed, each with its count. Select opens a menu that checks exactly the rows the filter shows that match: All, Needs export (out of date and not exported together), Out of date, Not exported and None. A choice replaces what was checked, and a queued row is never checked. A click anywhere on a row checks or unchecks it.
  • Export exports the checked avatars in list order, one at a time. Each row shows Step N of 7 with a bar while it runs, and Queued (N) until its turn. The tab reads Manage 2/5 while a queue runs, and the status line Exporting 2 of 5: name with Cancel all. Exporting here leaves what you wear alone; the switch is ManageExportWears in sh_config.lua (off), which, when on, wears the last avatar of the batch once it is done.
  • Remove export deletes every .gma the checked avatars exported. The avatar you wear, and one queued or exporting, can’t be removed. A .gma the game has mounted stays locked until GMod restarts: the row reads Not exported at once, the note says how many are in use, removed when GMod restarts, and the file is deleted when the module next starts. An avatar exported this session is usually one of them, since its spawn icon is drawn from the mounted model the first time; once GMod has cached the icon, the picture is shown without mounting.
  • Older exports on the right counts the .gma files nothing needs any more (earlier versions of your avatars, avatars gone from the workspace) and Remove deletes them. Avatars received from other players, what you wear, and what the server holds are never counted.
  • The log (collapsed at rest) shows the running export’s output, or the last one’s, in the console’s font. It opens by itself when a queue starts.

The list is asked for every time the tab is shown.

The window’s settings are the top layer of four: built-in default, the workspace’s dh-config.jsonc, the avatar’s own pallet, then yours. Each is a client convar, and an empty one forces nothing.

SettingConvarValues (default first)What it does
Proportionsdigitalheaven_proportionsown, hl2Avatar’s own keeps the avatar’s limb lengths above the hip; Half-Life 2 stretches it to a stock player’s
Fitdigitalheaven_fithips, eyesHips: the hips land at a stock player’s hip height (the scale is capped at 1.3×). Eyes: the eyes sit at a stock player’s eye height, and every client lowers the pelvis by the avatar’s hip ratio and plants the lower foot on the ground
Spring bonesdigitalheaven_springbones1, 0Source jigglebones from the avatar’s own spring-bone settings (dh.springBone). Sent to the exporter as the force field springBones
Handsdigitalheaven_hands1, 0First-person viewmodel hands made from the avatar (see Hands below). Sent as force.hands
NPCsdigitalheaven_npcs1, 0The NPC model the avatar’s Friendly and Hostile NPCs use (see NPCs and ragdolls below). Sent as force.npcs
Third persondigitalheaven_thirdperson0, 1An over-the-shoulder camera to see yourself; a view toggle under the preview, not an export setting
Progress HUDdigitalheaven_progress_hud1, 0The progress box on the HUD while the window is closed; a view toggle under the preview
Auto reloaddigitalheaven_auto_reload1, 0Re-export and wear the worn avatar again when its pallet is rebuilt; a toggle under the preview
Blink speeddigitalheaven_blink_speed1.25 (0.25 to 4)How fast the lids close, hold and open in a DigitalHeaven blink, as a multiple of the avatar’s own timing (its dh.eyes blink, else DigitalHeaven’s defaults). Garry’s Mod’s alone; needs the native module
Eyesdigitalheaven_eyes1, 0DigitalHeaven’s own eye look and blinking on every DigitalHeaven avatar this client sees (needs the native module; see Eyes below). Off hands the lids back to Source’s blink

A change takes effect by itself. Three quarters of a second after the last change, the worn avatar re-exports with the new settings (the usual Exporting state, the old model still worn), then every player switches. A change during an export restarts it with the new settings. With nothing worn or exported, the export settings are disabled; Third person always works.

The window keeps the two kinds apart. Proportions, Fit, Spring bones, Hands and NPCs sit in the Export section, since they change the avatar build. Third person, Progress HUD and Auto reload are toggles, buttons in the bar under the preview.

The progress HUD. While an export or an upload runs and the window is closed, a small box at the bottom center, clear of the health and ammo panels, shows the avatar’s name, a thin bar and N/7 with the current step’s name under it in small, dim text (exporting), or a percent (uploading). It ends on Ready: name, which fades after a moment, or a short red error (Export failed, Server refused: …), which fades after a few seconds; a cancel ends it silently. It scales with the screen height, and it hides with the HUD (cl_drawhud 0, the camera, anything vetoing HUDShouldDraw).

The camera is a plain CalcView hook returning a view with drawviewer, plus ShouldDrawLocalPlayer and PreDrawViewModel hooks. Another addon’s CalcView hook that returns a view of its own while its feature is active wins over it. digitalheaven_debug_view prints the convar, whether the hooks are registered, what the camera’s hook last actually answered, and every other CalcView and ShouldDrawLocalPlayer hook.

ConvarDefaultWhat it does
digitalheaven_allow1Let players wear DigitalHeaven avatars on this server
digitalheaven_max_mb64The largest avatar .gma the server accepts, in MB
digitalheaven_max_shared16How many avatars nobody wears the server holds for spawning (it keeps each .gma in memory to serve it); 0 allows only worn avatars

Each export also makes the avatar’s first-person viewmodel hands, models/digitalheaven/<hash>_arms.mdl, packed into the same .gma with the playermodel’s materials. The whitelist accepts that second model stem, and still requires only the playermodel, since older exports and Hands off carry none.

  • The server applies them. A PlayerSetHandsModel hook gives the wearer’s gmod_hands the avatar’s hands (skin 0, bodygroups "0") and returns true, so the gamemode’s player_manager lookup, which would pick citizen hands for a worn avatar, is skipped. When the .gma has no hands it returns nothing, and the gamemode’s own hands apply. SetupHands runs after every wear and after taking an avatar off.
  • Nothing new travels. The hands are inside the .gma everyone already mounts, and their path follows from the hash. gmod_hands only transmits with its owner’s viewmodel, so only the wearer (or someone spectating them in first person) draws them.
  • A hands failure never blocks the body. The export still succeeds; the body is worn, and the status line reads No hands (the avatar had no hand mesh) or Hands failed.

Each export also makes an NPC model, models/digitalheaven/<hash>_npc.mdl: the playermodel on a stock citizen’s animations, in the same .gma (see Source export). Every avatar the server holds is then a Friendly and a Hostile NPC, and every exported avatar is a ragdoll.

  • Two NPCs, both citizens. Friendly is npc_citizen with citizentype 4 (a unique citizen, which keeps its model) in the rebels’ squad. Hostile is the same with the Hostile keyvalue in the combine’s squad, as Garry’s Mod’s own hostile-rebel entry is, so it fights you with a citizen’s animations. Both get a player’s 100 health and a stock rebel’s weapons, and the NPC tab’s weapon override applies.
  • The DigitalHeaven tab. A top-level spawn menu tab, shaped like the stock Weapons and NPCs tabs. The tree lists collections first (Avatars: every avatar), then one node per pallet, named by the barcode’s bundle prefix. A node shows Ragdolls, Friendly NPCs and Hostile NPCs, each avatar as GMod’s own spawn icon of its model; the tooltip names it. It lists your workspace’s exported avatars (the list is fetched when the spawn menu opens), plus other players’ avatars the server holds, which appear under Avatars only.
  • The NPC tab also has a DigitalHeaven category, with the same entries under Friendly and Hostile. When entries come or go while that category is open, it is rebuilt by the stock code, so each icon lands under its own header, as after a restart. The stock live refresh appends a new icon under whichever header is last.
  • Registered from the mounted .gma. An avatar’s NPCs are registered in a realm once its .gma is mounted there and carries <hash>_npc.mdl, checked with file.Exists(path, "GAME"). util.IsValidModel can’t answer this on a client, because it says no for any model the server hasn’t precached, and the server precaches your own export only once you wear or share it. An export without the NPC model claims nothing, so an older export of the same avatar keeps its NPCs. The console says why when a mounted export gets no NPCs ([DigitalHeaven] no NPCs for <name> (<hash>): ...), once per export.
  • Each avatar is listed once, as its current export. Records carry the avatar’s barcode, so on every client a newer export of the same avatar replaces the older one in the NPC tab and in the DigitalHeaven tab. Your own current export always wins over another player’s export of the same avatar. The server keeps every NPC entry, since its list is never shown and a client may still spawn one, but holds only the newest shared export of each avatar. The old .gma files stay on disk: a mounted one is locked until the map changes, received ones are pruned at a later startup, and your own exports are the module’s.
  • Spawning shares first. An avatar the server doesn’t hold yet (you exported it but don’t wear it) is uploaded the way a worn one is, checked and mounted, and its NPCs are registered on the server and sent to every client, late joiners included. Then the stock gmod_spawnnpc or gm_spawn runs, so sandbox limits, undo and cleanup apply as usual.
  • NPCs off (or an older export) has no NPC model: the avatar spawns as a ragdoll only, and the status line reads No NPC when the model failed to compile.

An avatar’s eyes follow its own dh.eyes, on players and NPCs alike:

  • With the native module, once a frame, every DigitalHeaven player and NPC within 1500 units of your view goes to DigitalHeaven’s eye brain (the same one the engine and the Unity mods run) in one call. It turns the avatar’s eye bones and sets its blink and lid shapes, and switches Source’s own blink off for it. Its blinks run at digitalheaven_blink_speed times the avatar’s own timing, slightly faster by default. The lid weights are written again before every view draws (water, mirrors and render targets included), since an entity’s flex weights slip back toward the server’s with each draw pass. Other players and NPCs around are the faces it looks at, including who is looking back and who is talking. With four avatars and six heads around, the whole frame’s work took about 0.25 ms (the brain’s own part, a few microseconds an avatar).
  • An NPC’s own look steers it: the server sends each DigitalHeaven NPC’s enemy, or the player, NPC or object its own look logic picked, and while one is set the eyes follow it instead of choosing.
  • Without the module, the avatar still blinks: its blink shapes are Source flexes on the blink controller Source drives for every player and NPC (every 1.5 to 4.5 seconds). The eyes stay at rest.
  • An avatar whose dh.eyes turns blinking off never blinks, with or without the module, and one that turns looking off keeps its eyes at rest.

How the export carries all of this is on the Source page.

GMod frames any model with an eyes attachment like a stock human head: 60 units back at a 10° field of view. An avatar’s head can be twice that size, with its eyes low in it. So the addon frames DigitalHeaven playermodels and NPC models itself, through SpawniconGenFunctions:

  • Same angle as stock. The camera takes the stock angle from the export’s eyes attachment.
  • Aimed at the whole head. The aim is the middle of the head’s hitbox.
  • Distance fitted to the head. The camera backs off in proportion to the hitbox’s longest side, with a little room so the ears stay in.

Icons are cached per model path, and an export’s path is its content hash, so a new export always renders a fresh icon.

  • Transfers pull, never push. The side that wants a file (the server for an upload, a client for a download) asks for it 48 KB at a time with two chunks in flight, so no net channel ever floods. The server serves each player at most 60 chunks a second.
  • Listen servers and single-player share one data/ folder between the server and the host, so the host’s own export is never uploaded, and the host’s client mounts other players’ uploads straight from disk.
  • Late joiners get every current avatar when they finish loading.
  • Changing avatars is never refused. One player’s changes are at least 2 seconds apart, so nobody can make everyone download avatar after avatar; a change sooner waits and applies when the 2 seconds are up (only the latest one). The host of a listen server, and single-player, skip the wait.
  • A Lua reload mid-game (autorefresh, a reinstall) keeps what you wear. The client reads it back from your actual model, named by worn.json or by the server’s record, and the preview always shows the model you have in game. A reloaded server asks every client what it wears again.
  • Enhanced PlayerModel Selector replaces Player:SetModel with an enforcer that refuses changes after spawn. The addon calls the Entity method it wraps, and sets the model again on every respawn.
  • Cleanup. A player’s record goes when they leave. A mounted .gma stays locked for the rest of the session, so received files are deleted at the next startup once they are 14 days unused, or past 1 GB in total. Your own exports belong to the module and are never deleted by the addon.

With the native module absent, the window reports Module not installed and nothing can export; there is no addon-side stand-in for it. The Lua test suite (bun tools/lua.ts test) exercises the full window, export and sync flow against a stub module table that lives only under addon/tests/support/, never shipped.

digitalheaven_capture (with developer 1) stands two stock references and every DigitalHeaven avatar of the session in a row, poses them through bind, idle, run, crouch, crouch-walk and a jiggle run, and has Garry’s Mod render each into data/digitalheaven/capture/, with the bone heights in report.txt.

digitalheaven_capture_ui (with developer 1) opens the window on its own and photographs it with render.Capture from PostRenderVGUI in eight states (the Avatar tab at rest, list open, exporting, error and nothing worn; the Manage tab at rest, with rows checked, and with a staged queue) into data/digitalheaven/capture/ui/, with the rendered height of every dropdown, its row and its menu items in layout.txt. The states are staged for the moment of the picture and put back afterwards; nothing is exported or sent.

  • Exporting needs Windows, or Linux on the x86-64 branch (with a Windows studiomdl under Wine; not yet run inside the game on Linux). macOS can’t export. Seeing avatars works everywhere.
  • Models stay loaded until the map changes. Each rebuild is a new model path, so a long session with many rebuilds keeps the old ones in memory.

The addon lives at Platforms/DigitalHeaven.Mods.GarrysMod/addon/digitalheaven/ (Workshop layout: addon.json, lua/, materials/). The native module and its helper process live beside it in native/.

FileRealmWhat it holds
lua/autorun/digitalheaven.luabothThe load order
sh_config.luabothEvery tuning number, the net message names, the server convars
sh_gma.luabothThe .gma reader and writer, and the avatar whitelist
sh_transfer.luabothThe chunked pull transfer and the avatar record on the wire
sh_cache.luabothReceived files on disk, and their cleanup
sv_sync.luaserverRecords, uploads, mounting, SetModel, serving downloads
cl_state.luaclientThe backend (the native module), the export in flight, what you wear
cl_settings.luaclientThe settings convars and rows, the debounced re-export trigger
cl_view.luaclientThe third-person camera and digitalheaven_debug_view
cl_fit.luaclientThe Eyes fit’s pelvis scale and foot plant
cl_eyes.luaclientThe eyes: every DigitalHeaven avatar near the view through the module’s eye brain, once a frame
sv_eyes.luaserverEach DigitalHeaven NPC’s view target, sent to clients when it changes
cl_sync.luaclientServing your upload, downloading and mounting everyone else’s
cl_hud.luaclientThe progress HUD and its state machine
cl_picker.lua, cl_window.luaclientThe picker and the window
cl_manage.lua, cl_manage_panel.luaclientThe Manage tab: its model (filters, selection, the queue, older exports), then its Derma
cl_capture.luaclientdigitalheaven_capture

The window builds its content from DH.Pages: the Avatar and Manage tabs of a DPropertySheet sharing the status line. A page may give a title (the Manage tab’s Manage 2/5) and an OnShown (its list request). State.jobs is the export queue in the helper’s order; State.job is always its head, the export running.

The tools run Garry’s Mod’s own lua_shared.dll (LuaJIT) from the install through bun’s FFI:

Terminal window
cd Platforms/DigitalHeaven.Mods.GarrysMod/addon
bun tools/lua.ts check # every addon file compiles
bun tools/lua.ts test # tests/*.lua against a fake server, clients and network
cd tools && bun install && bun globals.ts # every global read is a known GMod name

The tests load the addon’s real files into separate server and client environments connected by a fake network: an export through a stub digitalheaven table (tests/support/native_stub.lua, never shipped), the upload, a download, a late joiner, settings changes re-exporting by themselves, Eyes reaching another client, a failure, a cancel, a .gma carrying Lua being refused, None, a disconnect, the listen-server shortcut, the viewmodel hands, the NPC registrations and a share on first spawn (with the spawn tab’s collections and pallet nodes), the own list’s NPCs while a client’s util.IsValidModel says no (the fake answers as GMod does, false for a model the server hasn’t precached) and a mass export turning ready over several lists into an open stock NPC tab, a rebuilt pallet (auto reload on and off, the newer export replacing the older in every menu and among the shares, the picker’s spawn icons), the wear cooldown and the host’s exemption, the progress HUD, the third-person camera, and the Manage tab’s model (every avatar with its export’s hash, size and time, the filters, the Select menu’s choices, a queue that runs one at a time and leaves what you wear alone, a pick joining it, removing exports, one held by the game waiting for the next start, the older exports without received ones, and the ManageExportWears switch).

protocol_test.lua replays events recorded from real exports (mltn Taidum with fit=eyes, mltn Mayu with hands off, and a barcode no pallet has) through a stand-in module table, so the addon is checked against the protocol the helper actually speaks: barcodeParts, the steps (seven, with Compile the hands), the fit numbers, done.hands, and a failure. Everything it checks is read from the recording. After a protocol change, rebuild the helper (dotnet build native/DigitalHeaven.Mods.GarrysMod.Export) and record them again with DH_WORKSPACE=<workspace> DH_GMOD_STUDIOMDL=<studiomdl.exe> bun tools/record-protocol.ts (the game folder is taken from beside studiomdl, or DH_GMOD_GAME); machine paths become placeholders.