-
Notifications
You must be signed in to change notification settings - Fork 27
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
}
}