-
Notifications
You must be signed in to change notification settings - Fork 1
Getting Started
- Download
FtDSharp.zipfrom the latest release - Extract the zip into your
From The Depths/Mods/folder (so thatplugin.jsonis atMods/FtDSharp/plugin.json) - Launch the game — the mod loads automatically
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.
- 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
voidwith no parameters - Restricted APIs (reflection, file I/O, network, etc.) are blocked — see Blocked APIs below
| 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.
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.
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.)
- You paste/type code into the Programmable Block and press "Save and Execute"
- 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
- When source code changes, the script recompiles on next save/execute;
[OnStart]runs again - On deactivation,
[OnStop]runs (if defined), then the instance is disposed - Compile errors appear in the block log with line numbers
For IntelliSense, autocompletion, and compile-time error checking:
- Install Visual Studio Code and the C# Dev Kit extension
- Install the .NET SDK 8.0+
- (Optional) Recommended extensions: Prettier, Code Spell Checker
- Open the
ScriptProject/folder inside the FtDSharp mod directory in VSCode - 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.
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(), ...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, ...)
- Weapons & Turrets: weapon control, tracking, typed weapon interfaces
- Missiles & Guidance: missile guidance, parts, visual effects
- AI & Targeting: mainframes, targets, aimpoints
- Drawing: 3D debug visualization
- Helpers: PIDs, WeaponController