s&box Engine Documentation

repository·master·Indexed 27 days ago

https://github.com/facepunch/sbox-public

A modern game engine built on Valve's Source 2 and .NET technology. This documentation covers the s&box editor, including the Model Context Protocol (MCP) server for AI agent integration, the Sandbox.CodeUpgrader system for Roslyn-based analyzers and fixers, and InteropGen for generating C++↔C# bindings.

Tokens
29K
Snippets
21
Records
161
Agent score
91%

What's inside s&box

  1. Overview of MCP Tools in s&box

    master

    The s&box editor runs a Model Context Protocol server that allows AI agents (like Claude Code) to read and interact with your open project.

    • Endpoint: http://127.0.0.1:7269/mcp
    • Availability: Enabled by default (Editor → Preferences → MCP Server).
    • Discovery: Tools are discovered via EditorTypeLibrary. They appear and disappear automatically as code compiles (hotloading).
    • Mechanism: Tools are implemented as static methods. There is no manual registration required.
  2. Overview of InteropGen

    master

    InteropGen is a tool used to generate C++↔C# bindings for the s&box engine. It processes .def files (a Domain Specific Language describing classes and structs crossing the native/managed boundary) to produce three types of output:

    • Managed files (cs directive): Typed C# wrappers, [UnmanagedCallersOnly] exports, and the NativeInterop bootstrap.
    • Native headers (hpp directive): Declarations of managed classes that the native side can call.
    • Native source files (cpp directive): Exported thunks, import function pointers, and the igen_* initializer.

    Note: Generated output is not committed to version control. The build process regenerates these files, only overwriting those whose content has changed.

  3. Understand the .def file format

    master

    A .def file is used for interop generation and is parsed line by line.

    Syntax Rules:

    • Comments: Lines starting with // are ignored.
    • Blank Lines: Skipped.
    • Directives: The first word is the keyword, followed by its argument (e.g., ident "engine"). Arguments can be wrapped in double quotes.
    • Type Declarations: Uses keywords like native class ... or managed struct ....
    • Attributes: Applied to the next declaration (e.g., [nogc], [Handle:...]).
    • Flexibility: Keywords do not need to start the line; for example, #include "foo.h" is valid to maintain C++ syntax highlighting compatibility.
  4. Use Rope Spring Constraints for Particle Ropes

    master

    The C_OP_RopeSpringConstraint is intended for creating rope-like systems using a static particle count (recommended length of 5 to 32 particles).

    Configuration

    • Minimum/Maximum Segment Length % (m_flMinDistance / m_flMaxDistance): The allowed range for the distance between any two particles, expressed as a percentage of the spacing they had upon creation.
    • Scale Factor for Spring Correction (m_flAdjustmentScale): Controls how aggressively the system maintains segment lengths. Higher values make springs stiffer but can cause instability. Increasing the system's Maximum Time Step can help compensate for instability.
    • Slack (m_flRestLength): The amount of slack in the system relative to its starting position. Larger numbers result in a looser rope; smaller numbers result in a tighter rope.
  5. Inherit and skip definitions in .def files

    master

    When multiple .def files cover overlapping native code, use inherit and skipall to manage the dependency chain.

    Inherit

    Use inherit "filename.def" to build on an existing binding set. The inherited types are parsed so they can be used as parameter/return types, but they are not re-emitted. This prevents duplicate wrappers in the export tables.

    Skipall

    Use skipall "filename.def" for deep dependency chains. This is a stronger form of inheritance that skips the emission of everything in the named def, including classes (native and managed), structs, and its .h includes.

    Example of inheritance pattern:

    ident "tools"
    inherit "engine.def"
    include "common/*"
  6. Use Custom Classes and Structs as Parameters

    master

    You can use plain data types as parameters (or nested within arrays/lists). The schema is generated from the public settable properties.

    • Property Naming: Properties are advertised in camelCase (e.g., Position becomes position).
    • Required Fields: Use the C# required keyword to make a property mandatory in the JSON schema.
    • Descriptions: Use XML summaries (addons) or [Description] (engine) to describe properties.
    • Attributes: [JsonPropertyName] and [JsonIgnore] are respected.

    Note: Engine/framework types (like Vector3) use custom converters (e.g., comma strings) and do not expose their internal properties to the schema.

    /// <summary>
    /// One waypoint on a patrol route.
    /// </summary>
    public class Waypoint
    {
    	/// <summary>Where to stand, as 'x,y,z'.</summary>
    	public required Vector3 Position { get; set; }
    
    	/// <summary>Seconds to wait before moving on.</summary>
    	public float Wait { get; set; }
    }
    
    [McpTool( "set_patrol" )]
    public static object SetPatrol( string id, Waypoint[] waypoints ) { ... }
  7. Verify InteropGen refactors via snapshot-diffing

    master

    Because generated files are not committed to Git, you must verify refactors by hashing the output before and after your changes. If the hashes match, the refactor is pure.

    1. Run the generator before the change.
    2. Hash all generated files (e.g., engine/Sandbox.*/Interop.*.cs and src/**/interop.*).
    3. Apply changes.
    4. Run the generator again.
    5. Hash the files again and compare to the first snapshot.
  8. Handle Errors in MCP Tools

    master

    When a tool fails, throw an exception. The exception's message is sent directly to the agent as an error result.

    Guideline: Write error messages specifically for the AI agent. Tell it what went wrong and suggest what it should do next (e.g., which tool to call instead).

    throw new Exception( $"No car named '{name}'. Find cars with find_cars." );
  9. Use the Tile Editor Tool

    master

    The Tile Editor Tool (Command.HammerEditorSession.ToolTileEditor) allows you to edit a tile grid. Use the following modes and commands to manipulate tiles and objects:

    Modes:

    • ModeSelect: Select and modify both tiles and objects.
    • ModeEditObjects: Place individual props, trees, and plants.
    • ModeBrushHeight: Raise or lower ground height.
    • ModeBrushTrees: Place trees over an area.
    • ModeBrushPath: Draw paths and create ramps.
    • ModeBrushPlants: Place plants over an area.
    • ModeBrushWater: Draw water over an area.
    • ModeUnhideTiles: Enter mode to un-hide previously hidden tiles.
    • ModeEnableDisableTiles: Enable or disable tiles.

    Tile Manipulation Commands:

    • ToggleTileSelection: Toggle selecting tiles.
    • ToggleObjectSelection: Toggle selecting objects.
    • FreezeTile: Create an editable copy of the selected tile.
    • HideTile: Hide the selected tile.
    • CollapseTiles: Convert selected tiles into objects for direct editing.
    • AssignNextTileSet / AssignPreviousTileSet / AssignCurrentTileSet: Switch or assign tile sets to the selected item.
    • ShowGridProperties: Open properties for the tile grid to select active tile sets.

    Variation Commands:

    • NextVariation / PreviousVariation / RandomVariation: Pick different variations of the selected item.
    Command.HammerEditorSession.ToolTileEditor
  10. Configure Operator Fade Group

    master

    The Operator Fade Group allows you to hand-tune when an operator influences an effect. These properties are standard and work on all operators, though binary operators that cannot logically scale (like setting control point positions) will simply switch on and off using these fades.

    Key Behaviors:

    • Timing: Fade times are relative to the emitter lifespan, not the individual particle.
    • Oscillation: If an oscillation time is set, fade in and fade out times become $0.0$ to $1.0$ relative to that oscillation cycle.
    • Advanced Use: This is considered an advanced tool and should be used as a last resort if operator-specific control mechanisms are unsuitable.