Skip to content

Getting Started

trk20 edited this page May 31, 2026 · 9 revisions

Getting Started

Installation

  1. Download FtDSharp.zip from the latest release
  2. Extract the zip into your From The Depths/Mods/ folder (so that plugin.json is at Mods/FtDSharp/plugin.json)
  3. Launch the game — the mod loads automatically

Your First Script

Place a Programmable Block on your construct. The default template compiles and runs immediately:

public class MyScript
{
    // Note: you can also have a constructor if you need to initialize readonly fields - constructors run before [OnStart]
    [OnStart]
    public void Initialize() // runs once when the script starts
    {
        Log("FtDSharp script template running.");
        Log($"I am {Game.MainConstruct.Name} at {Game.MainConstruct.Position}");
    }

    [OnPhysicsTick]
    public void Update()
    {
        // Your logic here
    }
}

You can write scripts in the in-game editor for quick tests, or use an external IDE with full IntelliSense (recommended). See Editor Setup below.

Script Requirements

  • Your script must include a public class with at least one entry-point method marked with [OnPhysicsTick], [OnStart], or [OnStop]
  • Entry-point methods must be public instance methods returning void with no parameters
  • Restricted APIs (reflection, file I/O, network, etc.) are blocked — see Blocked APIs below

Entry Points

Attribute When it runs
[OnStart] Once when the script first activates (after compile/instantiate)
[OnPhysicsTick] Every physics tick (~40 Hz at 1x speed)
[OnStop] When the script is deactivated or the block is destroyed

Multiple entry points on the same class are allowed. A class can omit [OnPhysicsTick] if it only needs [OnStart], but at least one attributed method is required.

Implicit Global Usings

The compiler injects these automatically — no using lines required in-game:

global using System;
global using System.Collections.Generic;
global using System.Linq;
global using UnityEngine;
global using FtDSharp;
global using static FtDSharp.Logging;

That means Log(), LogWarning(), and LogError() work out of the box. Other APIs use their class prefix (Game.MainConstruct, Weapons.All, etc.) unless you add optional using static imports in your IDE project.

Blocked APIs

For security, the following are blocked at compile time:

  • System.IO — file system access
  • System.Reflection — reflection
  • System.Net — network access
  • dynamic — dynamic dispatch
  • Meta-compilation (Microsoft.CodeAnalysis, expression compile, etc.)

Script Lifecycle

  1. You paste/type code into the Programmable Block and press "Save and Execute"
  2. FtDSharp compiles it via Roslyn; on success:
    • Finds your public class with attributed entry points
    • Creates an instance
    • Calls [OnStart] methods (if any)
    • Calls [OnPhysicsTick] every tick
  3. When source code changes, the script recompiles on next save/execute; [OnStart] runs again
  4. On deactivation, [OnStop] runs (if defined), then the instance is disposed
  5. Compile errors appear in the block log with line numbers

Editor Setup (VSCode)

For IntelliSense, autocompletion, and compile-time error checking:

  1. Install Visual Studio Code and the C# Dev Kit extension
  2. Install the .NET SDK 8.0+
  3. (Optional) Recommended extensions: Prettier, Code Spell Checker
  4. Open the ScriptProject/ folder inside the FtDSharp mod directory in VSCode
  5. Write your script in the IDE, then copy into the in-game Programmable Block

The template project references FtDSharp.API.dll and UnityEngine.CoreModule.dll for IntelliSense. It does not include the implicit global usings from the in-game compiler aside from using static FtDSharp.Logging;, so you can add using static FtDSharp.Game;, using static FtDSharp.AI;, etc. in scripts if you want the same shorthand.

Most other editors should have similar support for .NET and C# development.

Static Classes

FtDSharp exposes game data through static classes:

Static Class Purpose
Game MainConstruct, GameTime, RealTime, delta times, TicksSinceStart
AI Mainframes, HighestPriorityMainframe
Weapons All, Turrets, typed accessors, CreateController
Guidance Missiles — active script-controllable missiles in flight
Friendly All, AllExcludingSelf, Fleets, MyFleet
Warnings IncomingProjectiles, IncomingMissiles, IncomingShells
Drawing Arrow, Line, Point, Cross, Sphere, Circle, Gimbal, Clear
Blocks Auto-generated typed accessors for 200+ block types
Logging Log, LogWarning, LogError, ClearLogs (included by default)

Optional using static imports for shorter syntax in IDE scripts:

using static FtDSharp.Game;     // MainConstruct, GameTime, ...
using static FtDSharp.Drawing;  // Arrow(), Line(), ...

Type Hierarchy (Condensed)

ITargetable (Position, Velocity, Acceleration)
├── IConstruct (UniqueId, Name, BlockCount, Stability)
│   ├── ITarget (enemy — PositionError, firepower breakdown)
│   └── IFriendlyConstruct (Rotation, Forward, Yaw/Pitch/Roll, Fleet)
│       └── IMainConstruct (your construct — Propulsion, Weapons, Turrets, Missiles)

IBlock (UniqueId, Position, CustomName, Parent, IsOnRoot, Health, SubobjectDepth)
├── IWeapon (WeaponType, AimDirection, ProjectileSpeed, Track/Fire/AimAt)
│   ├── ITurret (Weapons, Azimuth, Elevation, aggregate status)
│   ├── IApsWeapon, ICramWeapon, ILaserWeapon, IMissileController, ...
│   └── ISimpleWeapon
└── 200+ auto-generated block interfaces (IAIMainframe, ISoundEmitter, ...)

Next Steps

Clone this wiki locally