Assets pipeline
How does X4 go from an XML file on disk to a 3D ship flying in space? The assets pipeline is the chain of file types that wire definitions together β macro XML defines properties, component XML defines geometry, index files map names to file paths, the engine loads on-demand. This overview maps the chain.
For the macro-level details see Macro (data layer).
The pipeline
Section titled βThe pipelineββββββββββββββββββββββββββββββββββββββββββββββ Index files (index/) ββ - macros.xml: name β file path mapping ββ - components.xml: same for components βββββββββββββββββββ¬ββββββββββββββββββββββββββ β engine resolves at loadβββββββββββββββββββββββββββββββββββββββββββββ Macro file (.xml) ββ - <macro name="X" class="Y"> ββ - <component ref="..."/> ββ - <properties>...</properties> βββββββββββββββββββ¬ββββββββββββββββββββββββββ β referencesβββββββββββββββββββββββββββββββββββββββββββββ Component file (.xml) ββ - 3D mesh / collision data refs ββ - connection points ββ - sub-component slots βββββββββββββββββββ¬ββββββββββββββββββββββββββ β referencesβββββββββββββββββββββββββββββββββββββββββββββ Mesh / texture / animation data ββ - Binary asset files βββββββββββββββββββββββββββββββββββββββββββββThe index layer
Section titled βThe index layerβThe index/ directory has two files:
| File | Maps |
|---|---|
index/macros.xml | Macro name β file path |
index/components.xml | Component name β file path |
These are giant lookup tables. Vanilla index/macros.xml has thousands of entries:
<entry name="ship_arg_l_destroyer_01_a_macro" value="assets/units/size_l/macros/ship_arg_l_destroyer_01_a_macro"/>
<entry name="station_arg_shy_1_macro" value="assets/structures/argon/macros/station_arg_shy_1_macro"/>When MD calls <create_object macro="macro.ship_arg_l_destroyer_01_a_macro">, the engine:
- Looks up
ship_arg_l_destroyer_01_a_macroinindex/macros.xml - Finds the file path
- Loads the macro XML
- Resolves the macroβs
<component ref="...">againstindex/components.xml - Loads the component XML
- Instantiates the runtime object
Critical: if index/macros.xml doesnβt have an entry, the engine canβt find the macro. Adding a new macro file isnβt enough β you must also add its index entry.
The macro layer
Section titled βThe macro layerβA macro file defines a runtime template β properties, class, default loadout. See Macro (data layer) for the schema.
Key relationship: a macro references its component:
<macro name="ship_arg_l_destroyer_01_a_macro" class="ship_l"> <component ref="ship_arg_l_destroyer_01_a"/> <properties>...</properties></macro>The <component ref="..."> is the link from βdesignβ (macro) to βthing in the worldβ (component).
The component layer
Section titled βThe component layerβA component file defines the physical structure β meshes, collision, connections to sub-components:
<component name="ship_arg_l_destroyer_01_a"> <source geometry="..." collision="..."/> <connections> <connection name="con_weapon_01" type="weapon"> ... </connection> <connection name="con_engine_01" type="engine"> ... </connection> </connections></component>Components are about geometry + connection topology. Properties (hull, speed, cargo) live on macros, not components.
Sub-components and connections
Section titled βSub-components and connectionsβComponents have connection points that map to sub-components:
ship_arg_l_destroyer_01_a (main component)βββ con_weapon_01 β weapon component (e.g. turret_01_a)βββ con_weapon_02 β weapon componentβββ con_engine_01 β engine componentβββ con_shield_01 β shield generator componentβββ con_dock_01 β dockingbay componentEach connection has a type tag (weapon, engine, shield). Sub-components must have a compatible connection on their end. The engine matches them at instantiation time.
Macros for sub-components
Section titled βMacros for sub-componentsβSub-components also have macros β turret_arg_l_beam_01_mk2_macro references the turret component. This is how the loadout system works: a loadout assigns specific turret/engine/shield macros to specific connection slots:
ship_arg_l_destroyer_01_a runtime instanceβββ slot con_weapon_01: turret_arg_l_beam_01_mk2_macroβββ slot con_engine_01: engine_arg_l_advance_01_mk1_macroβββ slot con_shield_01: shield_arg_l_standard_01_mk2_macroThis is the loadout system. Different loadouts = same ship with different equipment. See Loadout for runtime details.
File system layout
Section titled βFile system layoutβVanilla organises assets by category:
assets/βββ units/ β shipsβ βββ size_xs/macros/β βββ size_s/macros/β βββ size_m/macros/β βββ size_l/macros/β βββ size_xl/macros/βββ structures/ β stations + modulesβ βββ argon/macros/β βββ paranid/macros/β βββ teladi/macros/β βββ modules/macros/β βββ ...βββ equipment/ β turrets, engines, shieldsβ βββ turrets/macros/β βββ engines/macros/β βββ shields/macros/β βββ ...βββ fx/ β effectsβ βββ macros/βββ ...Files in each macros/ subdirectory are macros; component files live adjacent (often in components/ subdirectories).
The βmacro_macroβ convention
Section titled βThe βmacro_macroβ conventionβVanilla uses _macro suffix on macro names: ship_X_macro, module_Y_macro. Engine treats this as convention β macro.ship_X_macro is the lookup. Donβt omit the suffix.
The corresponding component drops the suffix: ship_X is the component name for macro ship_X_macro. So macro β component is _macro removal.
Catalog file (catalog.xml)
Section titled βCatalog file (catalog.xml)βEach asset directory typically has a catalog.xml that summarises its contents. This is for engine discovery / mod compatibility β listing which macros / components are present, sometimes their classes.
Modders extending an asset directory usually donβt touch catalog.xml β the index files (index/macros.xml) are what the engine actually uses for lookups.
Why this matters for modders
Section titled βWhy this matters for moddersβAdding a new ship
Section titled βAdding a new shipβTo add a new ship ship_mlog_my_destroyer:
- Create component file
ship_mlog_my_destroyer.xmlin anassets/.../components/directory - Create macro file
ship_mlog_my_destroyer_macro.xmlreferencing the component - Add entries to
index/macros.xml(macro path) andindex/components.xml(component path) - (Optional) Create loadout files for default equipment
- (Optional) Reference from god.xml for initial seeding
Without step 3, the engine canβt find your files.
Index conflicts
Section titled βIndex conflictsβTwo mods adding the same macro name overwrite each otherβs index entries. Use mlog_ prefix or other namespace convention to avoid collisions.
Component reuse
Section titled βComponent reuseβA new ship doesnβt always need a new component. If youβre re-skinning, you can:
- Reuse an existing component
- Create a new macro with different properties
- Point the macroβs
<component ref>at the existing component
This is how vanilla creates β_aβ, β_bβ, β_cβ variants of the same ship.
DLC-aware paths
Section titled βDLC-aware pathsβDLC content lives under separate paths (extensions/ego_dlc_terran/assets/...). Index files in extensions add to the same global namespace. Modders donβt need to worry about this directly β the engine merges all extensionsβ indices.
Modified macros affect all instances
Section titled βModified macros affect all instancesβEditing a macro file in a mod changes ALL future and existing instances of that macro. For per-instance changes, use MD <set_value> on the runtime object.
Cross-references
Section titled βCross-referencesβ- Macro (data layer) β macro file schema
- Loadout β runtime equipment from macros
- Ship β runtime instance of ship macro
- Module β runtime instance of module macro
Related architectural overviews
Section titled βRelated architectural overviewsβ- Galaxy seeding β references macros for initial spawns
- Construction sequence β applies macros to build modules