Mod Loading Steps - tModLoader/tModLoader GitHub Wiki
The following page lists the order in which tModLoader loads mods and their content.
This page may become outdated if tModLoader updates. As such, every section of this page will contain a link to the file(s) the information came from.
Additionally, this page is not comprehensive. Your best resource for a specific load-time issue is looking around in tModLoader's source yourself, specifically ModContent::Load()
.
tl;dr
The most important load order steps.
- Call
Mod
subclass constructor. - Load mod configs (if content autoloading enabled).
- Load mod content (if content autoloading enabled). This also calls
ILoadable::Load()
on all autoloaded content. - Load gores, music, backgrounds, clouds (if respective autoloading enabled).
- Call
Mod::Load()
, thenModSystem::OnModLoad()
. - Call
ModType::SetupContent()
(and by extension,ModType::SetStaticDefaults())
. - Initialize
ContentSamples
. - Call
Mod::PostSetupContent()
, thenModSystem::PostSetupContent()
. - Set up the bestiary.
- Set up NPC and item drop tables.
- Set up recipes groups.
- Add recipes.
- Call
ModSystem::PostAddRecipes()
. - Call
ModSystem::PostSetupRecipes()
.
Mod Load Order
Sources:
Terraria.ModLoader.Core.ModOrganizer::SelectAndSortMods()
Terraria.ModLoader.Core.BuildProperties::ReadBuildFile()
See also:
When tModLoader loads mods, it sorts them by internal name, and then resorts them such that the following conditions are satisfied for each mod MOD:
- MOD will load before any mod included in the
sortBefore
field of MOD'sbuild.txt
. - MOD will load after any mod included in the
sortAfter
field of MOD'sbuild.txt
. - MOD will load after any mod included in the
modReferences
orweakReferences
fields of MOD'sbuild.txt
as long as those mods aren't included insortBefore
.
Before these conditions are fulfilled, mods are sorted by internal name. Do NOT rely on the initial name-based sorting: Mods may be moved around arbitrarily to fulfill the conditions above. If you need your mod to load before/after another mod, use sortBefore
/sortAfter
.
For an example, take the following build.txt
snippet for the mod MOD:
modReferences = ModA
weakReferences = ModB
sortBefore = ModB, ModC
sortAfter = ModD
- MOD will load before
ModC
because it's included insortBefore
. - MOD will load before
ModB
because it's included insortBefore
, even thoughModB
is also inweakReferences
. - MOD will load after
ModA
because it's included inmodReferences
and not insortBefore
. - MOD will load after
ModD
because it's included insortAfter
.
As a special exception, tModLoader's internal ModLoaderMod
(which handles unloaded content, among other things) is always loaded first, and is inserted into the mod load order after mods are instantiated.
Content Load Order
After mods are sorted, all mods are loaded.
Several steps happen atomically using Terraria.ModLoader.ModContent::LoadModContent()
: All substeps are performed for one mod before moving onto the next mod. Steps that occur like this will be marked as such.
Loadable Types
Sources:
Several sections below mention "loadable" types. A type is considered loadable if it passes the following checks:
- If the type has the
ExtendsFromMod
attribute, it is considered not loadable if any of the mods listed in said attribute are not loaded. - If the type extends from a type that is not loadable, then it is also considered not loadable.
- If a type is nested inside of a type that is not loadable, or if it is constructed from a generic type definition that is not loadable, then it is also considered not loadable.
- If a type implements any interfaces that are not loadable, then it is also considered not loadable.
- Passing all these checks, the type is considered loadable.
1. Instantiation
Sources:
Terraria.ModLoader.Core.AssemblyManager::InstantiateMods()
Terraria.ModLoader.Core.AssemblyManager::Instantiate()
Terraria.ModLoader.Core.AssemblyManager::VerifyMod()
The first step is instantiation, wherein all enabled mods' assemblies are loaded into memory. This step happens atomically.
In order:
- The mod is verified: The mod's assembly name must match its internal name, the mod must have at least one loadable type whose namespace begins with the internal name, and the mod must have at most one loadable subclass of
Terraria.ModLoader.Mod
. - An instance of the mod's
Mod
subclass (or ofMod
if no subclass exists) is created. - The following fields on
Mod
are filled:File
;Code
;Logger
;Side
;DisplayName
;TModLoaderVersion
;TranslationForMods
.
This step is where your Mod
subclass's constructor is called, and is a good spot to assign any field on Mod
that isn't autofilled in substep 3 (e.g. PreJITFilter
, ContentAutoLoadingEnabled
, etc.).
2. Content Loading and JITting
The next step is content loading, wherein all of a mod's content and systems load. This is also the step in which the mod's assembly is JITted. These two steps happen at the same time: JITting begins before the first mod begins loading, and must finish before moving onto pre-setup.
Content Loading
Sources:
This step happens atomically.
In order:
Mod::loading
is set totrue
, allowing content to be added to the mod.- The mod autoloads all loadable subclasses of
Terraria.ModLoader.Config::ModConfig
(ordered by internal name) that returntrue
inModConfig::Autoload()
. - The mod prepares to load assets by calling
Mod::CreateDefaultContentSource()
. - The mod attempts to autoload all content:
- The mod loads all localization files and registers all found localization keys.
- All localization keys starting with
Mods.MODNAME.GameTips.
are added to the game tips list. Mod::ModSourceBestiaryInfoElement
is auto-assigned.- If
Mod::ContentAutoloadingEnabled
istrue
: Load all autoloadable content by callingMod::AddContent()
on a new instance of the content's type.- This is where
ILoadable::IsLoadingEnabled()
andLoad()
are called! - By extension, this is where
ModType::ValidateType()
,InitTemplateInstance()
,Load()
, andRegister()
are called (in that order).
- This is where
- If not on a dedicated server: Load all asset-only gores, music, backgrounds, and clouds if
Mod::GoreAutoloadingEnabled
,MusicAutoLoadingEnabled
,BackgroundAutoloadingEnabled
, andCloudAutoloadingEnabled
(respectively) aretrue
.
Mod::Load()
is called.ModSystem::OnModLoad()
is called for every knownModSystem
in the mod. If you try to add a newModSystem
during this step, tModLoader won't callOnModLoad()
on it!Mod::loading
is set tofalse
. At this point, no more content can be added to a mod.
Autoloadable Content
Sources:
A type is autoloadable if:
- The type is loadable.
- The type implements the
ILoadable
interface (ModType
does this, so any subclasses also do it). - The type is not abstract.
- The type contains no unbound generic parameters (e.g.
public class MyItem<T> : ModItem
is not autoloadable). - The type has a parameterless constructor (even if it's private).
- The type either doesn't have the
Autoload
attribute, or the attribute allows loading.
JITting
Sources:
See also:
JITting occurs on a set of methods from all of a mod's loadable types. Specifically, a method is JITted if all of the following conditions are true:
- The method's containing type is loadable.
- The method's containing type passes the mod's
PreJITFilter
. - If the method's containing type is nested or generic, the parent type / generic type definition also must pass the mod's
PreJITFilter
. - The method must not be abstract, must not contain generic parameters, and must be declared on the type it is being JITted on (i.e. don't JIT a non-overridden virtual method on a subclass).
By default, a type or method passed a mod's PreJITFilter
if all MemberJit
attributes on that type/method return true
in MemberJitAttribute::ShouldJIT()
, or if the type/emthod has no MemberJit
attributes. tModLoader provides the following subclasses of MemberJITAttribute
for use:
NoJITAttribute
: Member is never JITted.JITWhenModsEnabledAttribute
: Member is only JITted if the specified mods are also enabled.
Be aware that you can make your own subclasses of PreJITFilter
and MemberJITAttribute
if you need more control.
3. Before Setup
Sources:
Some steps are taken between loading content and setting it up. Namely:
- All content arrays are resized. This includes all ID sets.
- If the player was using a modded resource set, it is restored here.
4. Setup Content
Sources:
The next step is setup. This is an incredibly simple step: ModType::SetupContent()
is called for every loaded ModType
in the mod. In most cases, the ModType
subclass will call ModType::SetStaticDefaults()
here, alongside some extra work specific to each ModType
. Check out each ModType
if you need to see what specific extra work it does.
This step happens atomically.
5. Extra Setup
Some extra work done after SetupContent()
is called, but before PostSetupContent()
. In order:
ContentSamples
is re-initialized. After this step, it will now contain all modded data, as well as any changes made to vanilla content inSetDefaults()
.ContentSamples
loads NPC instances first, then projectiles, then items, then NPC bestiary rarity stars.
- Some tile merging data is setup (see
Terraria.Main::SetupAllBlockMerge()
andModTile::PostSetupTileMerge()
). - Mount-based buff data is setup (see
Terraria.Main::Initialize_BuffDataFromMountData()
).
6. Post Setup Content
The final step performed on all mods is post setup content. This is the step often used for cross-mod compatibility. This step happens atomically.
In order:
Mod::PostSetupContent()
is called.ModSystem::PostSetupContent()
is called for every knownModSystem
in the mod.- All requested mod assets (
ModContent::Request<T>()
) are loaded (seeMod::TransferAllAssets()
).
7. Final Setup
Sources:
Terraria.ModLoader.ModContent::SetupBestiary()
Terraria.ModLoader.ModContent::SetupRecipes()
Terraria.ModLoader.RecipeLoader::AddRecipes()
Many things happen after PostSetupContent()
is called, including (in order):
- Many
ModType
s have a "final setup" phase that is called here. This includes caching localized text, setting up globals, setting up hooks added by mods, etc. ModSystem::ModifyGameTipVisibility()
is called.- The bestiary is set up. This is where
NPCLoader::SetBestiary()
is called. - Item drop rules are set up. This is where
NPCLoader::ModifyGlobalLoot()
,NPCLoader::ModifyNPCLoot()
, andItemLoader::ModifyItemLoot()
are called. - Recipes are set up. This is the "Adding recipes…" step in loading, and is where the following methods are called (in order):
Mod::AddRecipeGroups()
,ModSystem::AddRecipeGroups()
,Mod::AddRecipes()
,ModSystem::AddRecipes()
,ModItem::AddRecipes()
,GlobalItem::AddRecipes()
,Mod::PostAddRecipes()
,ModSystem::PostAddRecipes()
,ModSystem::PostSetupRecipes()
. - If the player was using a modded menu or boss bar style, it is restored.
The few steps above are only highlights; please see the end of ModContent::Load()
for the full list.
Final Notes
Once again, this guide may become outdated as tModLoader updates; the best way to check load order is to read through ModContent::Load()
yourself (preferably in an environment that lets you jump to method definitions).