-
Notifications
You must be signed in to change notification settings - Fork 24
Home
Welcome to the Subworld Library wiki!
Simply open your mod's build.txt, and add modReferences = SubworldLibrary
.
It is highly recommended that you also download SubworldLibrary.dll and SubworldLibrary.xml. These let you reference Subworld Library and view its documentation in your IDE.
Visual Studio: right-click on Dependencies
in your project, click on Add Project Reference...
, then Browse...
, select the dll, and click OK
. The xml will be detected automatically if it's in the same location as the dll.
Classes that derive from Subworld
are automatically registered as subworlds. Below is a list of fields and methods that can be overridden.
Width | The subworld's width. |
Height | The subworld's height. |
Tasks | The subworld's generation tasks. |
ShouldSave | Whether the subworld should save or not. Default: false |
NoPlayerSaving | Reverts changes to players when they leave the subworld. Default: false |
NormalUpdates | Completely disables vanilla world updating in the subworld. Do not enable unless you are replicating a standard world! Default: false |
OnEnter() | Called when entering a subworld. Before this is called, noReturn and hideUnderworld are reset. |
OnLoad() | Called after the subworld generates or loads from file. |
OnExit() | Called when exiting a subworld. After this is called, noReturn and hideUnderworld are reset. |
OnUnload() | Called while leaving the subworld, before a different world generates or loads from file. |
DrawMenu() | Called by DrawSetup to draw the subworld's loading menu. Defaults to text on a black background.
Main.spriteBatch.DrawString(FontAssets.DeathText.Value, Main.statusText, new Vector2(Main.screenWidth, Main.screenHeight) / 2 - FontAssets.DeathText.Value.MeasureString(Main.statusText) / 2, Color.White); |
DrawSetup() | Corrects zoom and clears the screen, then calls DrawMenu and draws the cursor.
PlayerInput.SetZoom_Unscaled();
Main.instance.GraphicsDevice.Clear(Color.Black);
Main.spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.LinearClamp, DepthStencilState.None, Main.Rasterizer, null, Main.UIScaleMatrix);
DrawMenu(gameTime);
Main.DrawCursor(Main.DrawThickCursor());
Main.spriteBatch.End(); |
GetLight() | Controls how a tile in the subworld is lit. Return true to disable vanilla behaviour. Default: false
// Gives water a blue glow.
if (tile.LiquidType == LiquidID.Water && tile.LiquidAmount > 0)
{
color.Z = tile.LiquidAmount / 255f; // The result of integer division is rounded down, so one of the numbers must be a float
}
return false; |
Typically, a subworld's name is seen in Multiplayer, and is set with the following localization key: SubworldName.[subworld class]
(e.g. SubworldName.ExampleSubworld
)
To enter a subworld, call SubworldSystem.Enter<T>()
, where T
is the subworld's class.
To exit a subworld, call SubworldSystem.Exit()
.
To enter another mod's subworld:
If the mod is a dependency, call SubworldSystem.Enter<T>()
.
If the mod is not a dependency, call SubworldSystem.Enter(string)
, where string
is the mod's ID, followed by /
, followed by the subworld's ID (e.g. "ExampleMod/ExampleSubworld"
).
Current | The current subworld. |
IsActive(string) | Returns true if the current subworld's ID matches the specified ID. |
IsActive<T>() | Where T is the subworld's class. Returns true if the specified subworld is active. |
AnyActive(Mod) | Returns true if the current subworld is from the specified mod. |
AnyActive<T>() | Where T is the mod's class. Returns true if the current subworld is from the specified mod. |
noReturn | Hides the Return button. Its value is reset before OnEnter is called, and after OnExit is called.
public override void OnEnter()
{
SubworldSystem.noReturn = true;
} |
hideUnderworld | Hides the Underworld background. Its value is reset before OnEnter is called, and after OnExit is called.
public override void OnEnter()
{
SubworldSystem.hideUnderworld = false;
} |
public class ExampleSubworld : Subworld
{
public override int Width => 1000;
public override int Height => 1000;
public override bool ShouldSave => false;
public override bool NoPlayerSaving => true;
public override List<GenPass> Tasks => new List<GenPass>()
{
new ExampleGenPass()
};
// Sets the time to the middle of the day whenever the subworld loads
public override void OnLoad()
{
Main.dayTime = true;
Main.time = 27000;
}
}
public class ExampleGenPass : GenPass
{
//TODO: remove this once tML changes generation passes
public ExampleGenPass() : base("Terrain", 1) { }
protected override void ApplyPass(GenerationProgress progress, GameConfiguration configuration)
{
progress.Message = "Generating terrain"; // Sets the text displayed for this pass
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
for (int i = 0; i < Main.maxTilesX; i++)
{
for (int j = 0; j < Main.maxTilesY; j++)
{
progress.Set((j + i * Main.maxTilesY) / (float)(Main.maxTilesX * Main.maxTilesY)); // Controls the progress bar, should only be set between 0f and 1f
Tile tile = Main.tile[i, j];
tile.HasTile = true;
tile.TileType = TileID.Dirt;
}
}
}
}
This example shows how to update mechanisms, tile entities and liquid in subworlds that don't update normally.
public class UpdateSubworldSystem : ModSystem
{
public override void PreUpdateWorld()
{
if (SubworldSystem.IsActive<ExampleSubworld>())
{
// Update mechanisms
Wiring.UpdateMech();
// Update tile entities
TileEntity.UpdateStart();
foreach (TileEntity te in TileEntity.ByID.Values)
{
te.Update();
}
TileEntity.UpdateEnd();
// Update liquid
if (++Liquid.skipCount > 1)
{
Liquid.UpdateLiquid();
Liquid.skipCount = 0;
}
}
}
}
By default, subworlds inherit the seed of the main world. This behaviour can be overridden by calling Main.ActiveWorldFileData.SetSeed
in the subworld's first GenPass.
public override List<GenPass> Tasks => new List<GenPass>()
{
new SeedGenPass(),
new ExampleGenPass()
// other passes
};
public class SeedGenPass : GenPass
{
//TODO: remove this once tML changes generation passes
public SeedGenPass() : base("Set Seed", 0.01f) { }
protected override void ApplyPass(GenerationProgress progress, GameConfiguration configuration)
{
progress.Message = "Setting subworld seed"; // Sets the text displayed for this pass
Main.ActiveWorldFileData.SetSeedToRandom(); // Randomizes the subworld seed
//Main.ActiveWorldFileData.SetSeed(100.ToString()); // Sets the subworld seed to 100
// You can do other things in this pass as long as they don't make RNG calls! Having specific passes is cleaner though.
}
}
public class StandardWorldGenPass : GenPass
{
//TODO: remove this once tML changes generation passes
public StandardWorldGenPass() : base("Standard World", 100) { }
protected override void ApplyPass(GenerationProgress progress, GameConfiguration configuration)
{
GenerationProgress cache = WorldGenerator.CurrentGenerationProgress; // Cache generation progress...
WorldGen.GenerateWorld(Main.ActiveWorldFileData.Seed);
WorldGenerator.CurrentGenerationProgress = cache; // ...because GenerateWorld sets it to null when it ends, and it must be set back
}
}