Skip to content
John Snail edited this page Aug 2, 2020 · 5 revisions

Mod.Call

This page goes over how to interface Subworld Library within your own mod without adding a strong dependency, achieved via "Mod.Call". Doing so requires a more careful approach, since you have to consider two cases: Subworld Library is enabled, or disabled. See the following tModLoader guide for an introduction on "Mod.Call". Also see the ModCallExampleMod, which contains current API usage and examples. If you wish to use/test it yourself, you can clone this repository, then symlink it to your Mod Sources folder, instructions here (based on ExampleMod).

Why no strong dependency?

  • Your mod's core isn't built around subworlds
  • You want to detach your mod from this one, in case incompatibilities start arising which will stop your entire mod from loading
  • Opt-in subworlds

You'll have to signal to your players that this feature exists via other means (description, homepage, ingame), because it won't be marked as a dependency in the Mods menu.

Available Mod.Call commands

If something goes wrong, null is returned. For "Register", only the parameters up until List<GenPass> tasks are required.

Command Parameters Returns
"Register" Mod mod string name int width int height List<GenPass> tasks Action load = null Action unload = null ModWorld modWorld = null bool saveSubworld = false bool disablePlayerSaving = false bool saveModData = false bool noWorldUpdate = true UserInterface loadingUI = null Func<UIState> loadingUIState = null Func<UIState> votingUI = null ushort votingDuration = 1800 Action onVotedFor = null string id
"Enter" string id true
"Exit" true
"Current" string id, null if not in a subworld
"IsActive" string id true if in that subworld, false if not
"AnyActive" Mod mod true if in a subworld from that mod, false if not
"DrawMenu" bool (optional) SLWorld.drawMenu
"DrawUnderworldBackground" bool (optional) SLWorld.drawUnderworldBackground

Examples

To register subworlds, you will have to do so in your MyMod.cs file in the PostSetupContent hook. You first check if Subworld Library is loaded, then call "Register" with the arguments you want.

To interface with some of the methods here, you would do the same procedure. in WeakRefExampleMod, we simplify that by checking for Subworld Library only once during PostSetupContent, and reuse that in all other calls.

Register

Minimal "Register" example. You'll see a bigger one in the ModCallExampleMod.

public static string mySubworldID = string.Empty; //An empty string will not cause any problems in Enter, IsActive etc. calls

public override void Unload()
{
    mySubworldID = string.Empty;
}

public override void PostSetupContent()
{
    Mod subworldLibrary = ModLoader.GetMod("SubworldLibrary");
    if (subworldLibrary != null)
    {
        object result = subworldLibrary.Call(
            "Register",
            /*Mod mod*/ ModContent.GetInstance<MyMod>(),
            /*string name*/ "MySubworld",
            /*int width*/ 600,
            /*int height*/ 400,
            /*List<GenPass> tasks*/ MySubworldGenPassList() //Defined below
            );

        if (result != null && result is string id)
        {
            mySubworldID = id;
        }
    }
}

//Example for some GenPasses you might want to use. You can use Main.maxTilesX/Y here, they'll be the width and height you specified earlier
public static List<GenPass> MySubworldGenPassList()
{
    List<GenPass> list = new List<GenPass>
    {
        //First pass
        new PassLegacy("Adjusting",
        delegate (GenerationProgress progress)
        {
            progress.Message = "Adjusting world levels"; //Sets the text above the worldgen progress bar
            Main.worldSurface = Main.maxTilesY - 42; //Hides the underground layer just out of bounds
            Main.rockLayer = Main.maxTilesY; //Hides the cavern layer way out of bounds
        },
        1f),
        //Second pass
        new PassLegacy("GeneratingDirt",
        delegate (GenerationProgress progress)
        {
            progress.Message = "Generating a place to stand on";

            //Create three tiles for the player to stand on when he spawns
            for (int i = -1; i < 2; i++)
            {
                WorldGen.PlaceTile(Main.spawnTileX - i,  Main.spawnTileY + 2, TileID.Dirt, true, true);
            }
        },
        1f)
        //Add more passes here
    };
    return list;
}

Enter

This will work as a helper method, you can apply the same syntax to the other ones.

public static bool? Enter(string id)
{
    Mod subworldLibrary = ModLoader.GetMod("SubworldLibrary");
    if (subworldLibrary != null)
    {
        return subworldLibrary.Call("Enter", id) as bool?;
    }
    return null;
}

Usage example:

bool result = Enter(mySubworldID) ?? false;
if (!result) Main.NewText("Something went wrong, not entering " + mySubworldID);
Clone this wiki locally