-
Notifications
You must be signed in to change notification settings - Fork 6
en Basic VaultLoaden
VaultLoadenAttribute is an automatic resource loading attribute designed for Terraria ModLoader mod developers. By adding this attribute to static fields, properties, or classes, resources such as textures and sounds can be automatically assigned without manual loading, simplifying resource management.
- Automatically loads textures, sounds, effects, and other resources for static fields or properties
- Supports class-level tags for batch management of all resource members in a class
- Supports intelligent path completion, namespace replacement, and class path replacement
- Supports cross-mod resource referencing
- Supports arrays and lists for batch loading
- Supports custom loaders to extend new resource types
- Resource type can be auto-inferred or manually specified
| Resource Type | Member Type | AssetMode Value | Notes |
|---|---|---|---|
| Sound | SoundStyle |
AssetMode.Sound |
|
| Texture (lazy) | Asset<Texture2D> |
AssetMode.Texture |
Recommended, loads on demand |
| Texture (immediate) | Texture2D |
AssetMode.TextureValue |
Loads into memory immediately |
| Shader (lazy) | Asset<Effect> |
AssetMode.Effects |
|
| Shader (immediate) | Effect |
AssetMode.EffectValue |
|
| Armor Shader | ArmorShaderData |
AssetMode.ArmorShader |
|
| Misc Shader | MiscShaderData |
AssetMode.MiscShader |
All of the above types support batch loading via arrays T[] or IList<T>. The system automatically loads by numeric suffix (e.g., _0, _1, _2...).
| Resource Type | Member Type | AssetMode Value |
|---|---|---|
| Sound Array | SoundStyle[] |
AssetMode.SoundArray |
| Texture Array | Asset<Texture2D>[] |
AssetMode.TextureArray |
| Shader Array | Asset<Effect>[] |
AssetMode.EffectArray |
Apply the [VaultLoaden] attribute to a field or property, optionally specifying the path and asset type.
[VaultLoaden("Assets/Sounds/MySound", AssetMode.Sound)]
public static SoundStyle MySoundEffect;If the path ends with /, the field name will be automatically appended as the resource file name:
[VaultLoaden("Assets/Textures/UI/", AssetMode.Texture)]
public static Asset<Texture2D> ButtonBackground;
// Actual path: Assets/Textures/UI/ButtonBackgroundYou can use the {@namespace} placeholder in the path to automatically replace with the namespace path:
namespace MyMod.Content.UI {
[VaultLoaden("{@namespace}/Panels/", AssetMode.Texture)]
public static Asset<Texture2D> MainPanel;
}
// Actual path: MyMod/Content/UI/Panels/MainPanelYou can use the {@classPath} placeholder in the path, which will be replaced with the full tag path of the class where the member resides:
namespace MyMod.Content.Items {
public class MyWeapon {
[VaultLoaden("{@classPath}/Icon")]
public static Asset<Texture2D> WeaponIcon;
}
}
// Actual path: MyMod/Content/Items/MyWeapon/IconIf the class itself is also marked with [VaultLoaden], then {@classPath} will use the class tag's Path value:
namespace MyMod.Content.Items {
[VaultLoaden("Assets/Weapons/")]
public class MyWeapon {
[VaultLoaden("{@classPath}Icon")]
public static Asset<Texture2D> WeaponIcon;
}
}
// Actual path: Assets/Weapons/IconIf AssetMode is not specified, the type will be inferred from the field type:
[VaultLoaden("Assets/Sounds/MenuOpen")]
public static SoundStyle MenuOpenSound;
// Automatically inferred as AssetMode.Sound[VaultLoaden("Assets/Effects/Glow/")]
public static Asset<Effect> GlowEffect;
// Auto-completes field name, final path: Assets/Effects/Glow/GlowEffect[VaultLoaden("Assets/Effects/Glow/GlowEffect", AssetMode.ArmorShader, "CustomPass")]
public static ArmorShaderData CustomShader;
// Uses effect pass name "CustomPass"If effectPassname is omitted, it defaults to {EffectName}Pass.
To load a resource from another mod, prefix the path with @ModName/:
[VaultLoaden("@ExampleMod/Assets/Textures/ExtraBar", AssetMode.Texture)]
public static Asset<Texture2D> ExtraBarTex;
// Loads resource from mod named ExampleModMarking [VaultLoaden] on a class provides default loading rules for all untagged static members in the class, and recursively applies to nested classes.
// Automatically load all resource members in the class
[VaultLoaden("Assets/Image/")]
public class AssetClass2
{
public static Asset<Texture2D> Image1; // Loads "Assets/Image/Image1"
public static Asset<Texture2D> Image2; // Loads "Assets/Image/Image2"
public static Asset<Texture2D> Image3; // Loads "Assets/Image/Image3"
}
// It's optional to end the path with '/', the system will auto-complete
[VaultLoaden("Assets/Image")]
public class AssetClass3
{
public static Asset<Texture2D> Image1; // Loads "Assets/Image/Image1"
public static Asset<Texture2D> Image2; // Loads "Assets/Image/Image2"
// Class-level and member-level tags do not conflict;
// class management will skip members that have their own tag
[VaultLoaden("@OtherMod/Textures/")]
public static Asset<Texture2D> MyFaceImage; // Loads "OtherMod/Textures/MyFaceImage"
}Only applicable to class-level tags. When enabled, member names are split by underscore _ into subdirectory paths:
[VaultLoaden("Assets/UI/", AssetMode.None, "", 0, 0, true)]
public class UIAssets
{
public static Asset<Texture2D> Button_Primary_Hover;
// Member name "Button_Primary_Hover" is split by underscore
// Final path: Assets/UI/Button/Primary/Hover
public static Asset<Texture2D> Panel_Main_Background;
// Final path: Assets/UI/Panel/Main/Background
}When AssetMode is specified on a class-level tag, only members matching that type will be processed:
[VaultLoaden("Assets/Textures/", AssetMode.Texture)]
public class TextureAssets
{
public static Asset<Texture2D> Icon; // ✅ Will be loaded
public static SoundStyle ClickSound; // ❌ Type mismatch, skipped
}Supports loading resources as arrays or IList<T>. The system loads by numeric suffix _0, _1, _2... in order.
// Method 1: Pre-initialize array length, system auto-infers count
[VaultLoaden("Assets/Textures/Frames/Walk")]
public static Asset<Texture2D>[] WalkFrames = new Asset<Texture2D>[8];
// Loads: Walk_0, Walk_1, Walk_2 ... Walk_7
// Method 2: Specify count via arrayCount parameter
[VaultLoaden("Assets/Textures/Frames/Run", AssetMode.None, "", 0, 6)]
public static Asset<Texture2D>[] RunFrames;
// Loads: Run_0, Run_1 ... Run_5
// Method 3: Specify start index
[VaultLoaden("Assets/Textures/Frames/Attack", 1, 4)]
public static Asset<Texture2D>[] AttackFrames;
// Loads: Attack_1, Attack_2, Attack_3, Attack_4If the built-in resource types are not enough, you can extend the system by inheriting VaultLoadenHandle to support new loading types.
public class MyCustomLoader : VaultLoadenHandle
{
// The target type this loader handles
public override Type TargetType => typeof(MyCustomResource);
// Priority (higher value = higher priority, default is 0)
public override int Priority => 0;
// Core loading method
public override object HandleLoad(MemberInfo member, VaultLoadenAttribute attribute) {
// Load and return your custom resource based on attribute.Path
return LoadMyResource(attribute.Path);
}
// Cleanup logic on unload
public override void HandleUnload(MemberInfo member, object currentValue) {
// Clean up resources
}
}The system automatically scans and registers all classes that inherit from VaultLoadenHandle — no manual registration required.
VaultLoadenAttribute provides multiple constructor overloads. The complete parameter list is as follows:
| Parameter | Type | Default | Description |
|---|---|---|---|
path |
string |
(required) | Resource path, supports placeholders and cross-mod prefix |
assetMode |
AssetMode |
None |
Resource type, None means auto-infer |
effectPassname |
string |
"" |
Shader pass name, empty for auto-generated |
startIndex |
int |
0 |
Start index for collection resources |
arrayCount |
int |
0 |
Number of collection elements, 0 means infer from initialized collection |
pathConcatenation |
bool |
false |
Class-level tag only, splits member name by underscore to extend path |
- Only supports static fields or properties
- Properties must have a setter (public or non-public), i.e., must be writable
- When loading collections without specifying
arrayCount, the collection must be pre-initialized to determine length - Non-resource types (e.g.,
string,int) are not supported unless a corresponding custom loader exists
| Error Message | Cause |
|---|---|
| Cannot determine asset mode for ... | Resource type cannot be inferred. Specify AssetMode manually. |
| Property ... has no setter. | Property lacks a setter and cannot be assigned. |
| Member ... couldn't find Mod "xxx" | Specified mod name does not exist or is misspelled. |
| Attribute path on member ... is empty or invalid | Path is empty or formatted incorrectly. |
| After the Effect is loaded, there is an error message saying "Pass or Filters.Scene" | Incorrect EffectPassname or the Effect file does not contain that pass. |
public class AssetClass1
{
// Auto-inferred as Sound
[VaultLoaden("Assets/Sounds/Click")]
public static SoundStyle ClickSound;
// Auto-inferred as Texture (field name used: ButtonBackground)
[VaultLoaden("Assets/Textures/")]
public static Asset<Texture2D> ButtonBackground;
// Namespace replacement example
[VaultLoaden("{@namespace}/Icons/Warning", AssetMode.Texture)]
public static Asset<Texture2D> WarningIcon;
// Load effect and specify pass name
[VaultLoaden("Effects/Beam", AssetMode.Effects, "GlowPass")]
public static Asset<Effect> BeamEffect;
// Load ArmorShaderData
[VaultLoaden("Effects/Armor/ColdShader", AssetMode.ArmorShader)]
public static ArmorShaderData ColdArmorShader;
// Load resource from another mod
[VaultLoaden("@OtherMod/Textures/Cursor", AssetMode.Texture)]
public static Asset<Texture2D> OtherCursor;
// Texture array loading
[VaultLoaden("Assets/Textures/Anim/Frame", 0, 5)]
public static Asset<Texture2D>[] AnimFrames;
// Loads: Frame_0, Frame_1, Frame_2, Frame_3, Frame_4
}
// InnoVault's own resource class is a good example of class-level tags
[VaultLoaden("Assets/")]
public class VaultAsset : IVaultLoader
{
public static Asset<Texture2D> placeholder; // Assets/placeholder
public static Asset<Texture2D> placeholder2; // Assets/placeholder2
public static Asset<Texture2D> placeholder3; // Assets/placeholder3
public static Asset<Texture2D> Light; // Assets/Light
public static Asset<Texture2D> GearWheel; // Assets/GearWheel
}