### C# Server Startup and Management Source: https://context7.com/space-wizards/robusttoolbox/llms.txt Example C# code for starting and managing a RobustToolbox server. Includes server initialization, command-line argument parsing, and handling player status changes. Relies on Robust.Server and Robust.Shared namespaces. ```csharp using Robust.Server; using Robust.Shared.ContentPack; using Robust.Shared.IoC; // Server startup code public static class Program { public static void Main(string[] args) { // Create server instance var server = new BaseServer(); // Parse command line options var options = new ServerOptions(); options.LoadFromArgs(args); // Initialize server if (!server.Start(options)) { Log.Fatal("Failed to start server"); return; } // Main server loop server.MainLoop(); // Cleanup server.Shutdown("Server shutting down"); } } // Custom server implementation public sealed class MyGameServer { [Dependency] private readonly IBaseServer _baseServer = default!; [Dependency] private readonly IPlayerManager _playerManager = default!; public void Initialize() { IoCManager.InjectDependencies(this); _playerManager.PlayerStatusChanged += OnPlayerStatusChanged; } private void OnPlayerStatusChanged(object? sender, SessionStatusEventArgs args) { var session = args.Session; switch (args.NewStatus) { case SessionStatus.Connected: Log.Info($"Player {session.Name} connected"); break; case SessionStatus.InGame: Log.Info($"Player {session.Name} joined game"); SpawnPlayerEntity(session); break; case SessionStatus.Disconnected: Log.Info($"Player {session.Name} disconnected"); break; } } private void SpawnPlayerEntity(ICommonSession session) { var entityManager = IoCManager.Resolve(); var spawn = GetSpawnPoint(); var entity = entityManager.SpawnEntity("PlayerMob", spawn); session.AttachToEntity(entity); } } ``` -------------------------------- ### Get Server Info Source: https://github.com/space-wizards/robusttoolbox/wiki/ss14:---and-ss14s:---URI-handling Fetches information about the game server, including the UDP connect address. ```APIDOC ## GET /info ### Description This endpoint retrieves information about the game server, including its connection details. ### Method GET ### Endpoint `/{path}/info` Where `{path}` is the path specified in the ss14:// or ss14s:// URI. ### Parameters #### Query Parameters None ### Request Example GET https://builds.spacestation14.io/ss14_server/info ### Response #### Success Response (200) - **connect_address** (string | null) - The UDP address to connect to, in the format `udp://host:port`. If null, the main URI's host and default port (1212) should be used. - Other server information fields may be present. #### Response Example ```json { "connect_address": "udp://server.spacestation14.io:1212", "version": "0.1", "current_players": 10, "max_players": 64 } ``` #### Response Example (null connect_address) ```json { "connect_address": null, "version": "0.1", "current_players": 5, "max_players": 32 } ``` ``` -------------------------------- ### C# Field Injection with Dependency Attribute Source: https://github.com/space-wizards/robusttoolbox/wiki/IoC-(Inversion-of-Control) Demonstrates dependency injection into a C# class field using the [Dependency] attribute. It showcases injecting an ILogger and implementing IPostInjectInit for post-injection logic. Note the warning about potential race conditions and incorrect logger initialization in the example. ```csharp public class MyDependency : IMyDependency, IPostInjectInit { [Dependency] private readonly ILogger logger; // Gets called when logger becomes available. public void PostInject() { logger.info("MyDependency being created!"); // IMPORTANT: Don't actually do this specific thing with a logger. It gets the point across but is broken. // Because logger won't have been initialized properly yet, it has no output file. // As such, this message will go to the console, but will not be logged to any files. This is a bug. } public void Foo() { // This is fine of course, provided `Foo()` gets called after `BaseServer` had its way setting things up. logger.info("Hi!"); Console.WriteLine("Hello World!"); } } ``` -------------------------------- ### GET /status Source: https://github.com/space-wizards/robusttoolbox/blob/master/docs/Server Status.md Fetches the current status information of the SS14 server. This endpoint returns a JSON object containing details about the server's state, such as the server name and player count. ```APIDOC ## GET /status ### Description Fetches the current status information of the SS14 server. This endpoint returns a JSON object containing details about the server's state, such as the server name and player count. ### Method GET ### Endpoint /status ### Parameters #### Query Parameters None #### Request Body None ### Request Example (No request body for GET requests) ### Response #### Success Response (200) - **name** (string) - The name of the server. - **players** (integer) - The current number of players connected to the server. - (Other fields may be present depending on content implementation) #### Response Example ```json { "name": "Robust Toolbox Server", "players": 50 } ``` #### Error Response (e.g., 404 Not Found, 500 Internal Server Error) (Specific error responses depend on server configuration and potential issues during status retrieval.) ``` -------------------------------- ### C# Event Bus and Component Events in RobustToolbox Source: https://context7.com/space-wizards/robusttoolbox/llms.txt Demonstrates how to define and use component events and broadcast events in C#. Component events require the [ComponentEvent] attribute and are entity/component-specific, while broadcast events are global. Events can be raised locally or globally and subscribed to within EntitySystems. The example also shows how to use the ByRefEvent attribute for performance-critical events. ```csharp using Robust.Shared.GameObjects; // Component event: MUST use [ComponentEvent] attribute (v268.0.0+) // These events are raised via RaiseLocalEvent(entityUid, event) and target specific entities/components // IMPORTANT: Failing to add this attribute will cause runtime errors [ComponentEvent] public record struct HealthChangedEvent(float OldHealth, float NewHealth); [ComponentEvent] public record struct InventoryChangedEvent(EntityUid Item, bool Added); // Broadcast event: no attribute needed // These events are raised via RaiseLocalEvent(event) and broadcast to all subscribers public record struct RoundStartEvent(); public record struct ServerAnnouncementEvent(string Message); // Using events in a system public sealed class HealthSystem : EntitySystem { public override void Initialize() { base.Initialize(); // Subscribe to component-specific event SubscribeLocalEvent(OnHealthChanged); // Subscribe to broadcast event SubscribeLocalEvent(OnRoundStart); } private void OnHealthChanged(EntityUid uid, HealthComponent component, HealthChangedEvent args) { // Handle health change for specific entity Log.Info($"Entity {uid} health changed from {args.OldHealth} to {args.NewHealth}"); if (args.NewHealth <= 0) { // Raise another event RaiseLocalEvent(uid, new DeathEvent()); } } private void OnRoundStart(RoundStartEvent args) { // Handle round start globally var query = EntityQueryEnumerator(); while (query.MoveNext(out var uid, out var health)) { health.Health = health.MaxHealth; // Reset all health } } // Raise events public void DamageEntity(EntityUid target, float damage) { if (!TryComp(target, out var health)) return; var oldHealth = health.Health; health.Health -= damage; // Raise component event RaiseLocalEvent(target, new HealthChangedEvent(oldHealth, health.Health)); } public void StartRound() { // Raise broadcast event RaiseLocalEvent(new RoundStartEvent()); } } // Event with ByRefEventAttribute for performance (pass by reference) [ByRefEvent] [ComponentEvent] public record struct DamageAttemptEvent(float Damage, bool Cancelled = false); public sealed class ArmorSystem : EntitySystem { public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnDamageAttempt); } private void OnDamageAttempt(EntityUid uid, ArmorComponent component, ref DamageAttemptEvent args) { // Reduce damage based on armor args.Damage *= (1.0f - component.DamageReduction); // Can modify the event since it's passed by reference if (component.Invulnerable) { args.Cancelled = true; } } } ``` -------------------------------- ### C# Runtime Prototype Access and Entity Spawning in RobustToolbox Source: https://context7.com/space-wizards/robusttoolbox/llms.txt Demonstrates accessing and manipulating entity prototypes at runtime using C#. It shows how to use the IPrototypeManager to index specific prototypes, enumerate prototypes of a certain type, and check for prototype existence. The code also illustrates spawning entities from their respective prototypes using the EntityManager. ```csharp using Robust.Shared.Prototypes; using Robust.Shared.IoC; // Access prototypes at runtime [Dependency] private readonly IPrototypeManager _prototypeManager = default!; // Get a specific prototype var weaponProto = _prototypeManager.Index("WeaponPistol"); var name = weaponProto.Name; // Enumerate all prototypes of a type foreach (var proto in _prototypeManager.EnumeratePrototypes()) { if (proto.TryGetComponent(out var gun)) { // Process all gun prototypes Log.Info($"Gun {proto.ID}: damage={gun.Damage}, range={gun.Range}"); } } // Check if prototype exists if (_prototypeManager.HasIndex("WeaponPistol")) { // Spawn entity from prototype var entity = _entityManager.SpawnEntity("WeaponPistol", coordinates); } ``` -------------------------------- ### RobustToolbox: C# Dependency Injection with IoC Container Source: https://context7.com/space-wizards/robusttoolbox/llms.txt This snippet illustrates dependency injection using RobustToolbox's IoC container in C#. It shows how to define interfaces, implement services with injected dependencies, register these services, and resolve them within entity systems or manually. Key dependencies include Robust.Shared.IoC and Robust.Shared.GameObjects. The input is a request for a service, and the output is the resolved service instance with its dependencies automatically injected. ```csharp using Robust.Shared.IoC; using Robust.Shared.GameObjects; // Define an interface and implementation public interface ICustomService { void DoSomething(); } public sealed class CustomService : ICustomService { [Dependency] private readonly IEntityManager _entityManager = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!; public void DoSomething() { // Service implementation with resolved dependencies } } // Register service at startup (in IoC registration) IoCManager.Register(); // Use in entity systems public sealed class MySystem : EntitySystem { [Dependency] private readonly ICustomService _customService = default!; [Dependency] private readonly IEntityManager _entityManager = default!; [Dependency] private readonly IGameTiming _timing = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly IMapManager _mapManager = default!; public override void Initialize() { base.Initialize(); // All dependencies are automatically resolved before Initialize() is called _customService.DoSomething(); } } // Manual dependency resolution var service = IoCManager.Resolve(); service.DoSomething(); // Build object with dependencies var obj = IoCManager.Resolve().CreateInstance(); ``` -------------------------------- ### Registering a Dependency with IoCManager in C# Source: https://github.com/space-wizards/robusttoolbox/wiki/IoC-(Inversion-of-Control) Demonstrates how to register a new dependency by mapping an interface to its concrete implementation using the IoCManager. This process typically involves defining an interface and a class that implements it, then calling the Register method. This is usually done at the application's startup. ```csharp // SS14.Server/Example/MyDependency.cs namespace SS14.Server.Example { public class MyDependency : IMyDependency { public void Foo() { Console.WriteLine("Hello World!"); } } } // SS14.Server/Interfaces/Example/IMyDependency.cs namespace SS14.Server.Interfaces.Example { public interface IMyDependency { /// /// Writes a message to the console. /// void Foo(); } } // SS14.Server/Program.cs AND SS14.UnitTesting/SS14UnitTest.cs, inside RegisterIoC() IoCManager.Register(); ``` -------------------------------- ### C# Map and Grid Management in RobustToolbox Source: https://context7.com/space-wizards/robusttoolbox/llms.txt Demonstrates creating new maps and grids, setting tiles, placing entities on the grid, and retrieving an entity's grid position. This C# code utilizes Robust.Shared.Map and Robust.Shared.Maths namespaces. It requires an active RobustToolbox environment with necessary dependencies like IMapManager and SharedMapSystem. ```csharp using Robust.Shared.Map; using Robust.Shared.Map.Components; using Robust.Shared.Maths; public sealed class MapExampleSystem : EntitySystem { [Dependency] private readonly IMapManager _mapManager = default!; [Dependency] private readonly SharedMapSystem _mapSystem = default!; public (EntityUid mapUid, EntityUid gridUid) CreateNewMap() { // Create a new map var mapId = _mapManager.CreateMap(); var mapUid = _mapManager.GetMapEntityId(mapId); // Create a grid on the map var gridUid = _mapManager.CreateGridEntity(mapId); if (!TryComp(gridUid, out var grid)) return (mapUid, gridUid); // Set tiles on the grid var tiles = new List<(Vector2i pos, Tile tile)>(); for (int x = -10; x < 10; x++) { for (int y = -10; y < 10; y++) { tiles.Add((new Vector2i(x, y), new Tile(1))); // Tile type 1 } } _mapSystem.SetTiles(gridUid, grid, tiles); return (mapUid, gridUid); } public void PlaceEntityOnGrid(EntityUid gridUid, EntityUid entity, Vector2i gridPos) { if (!TryComp(gridUid, out var grid)) return; var worldPos = _mapSystem.GridTileToWorldPos(gridUid, grid, gridPos); var coords = new EntityCoordinates(gridUid, worldPos); Transform(entity).Coordinates = coords; } public Vector2i? GetGridPosition(EntityUid entity) { var xform = Transform(entity); if (!_mapManager.TryFindGridAt(xform.MapPosition, out var gridUid, out var grid)) return null; return _mapSystem.WorldToTile(gridUid, grid, xform.WorldPosition); } } ``` -------------------------------- ### Entity-Component-System Core Management in C# Source: https://context7.com/space-wizards/robusttoolbox/llms.txt Demonstrates core Entity-Component-System (ECS) operations using RobustToolbox's IEntityManager in C#. This includes creating, querying, and deleting entities, as well as accessing and modifying components, and listening for entity-related events. It relies on the Robust.Shared library for ECS functionality. ```csharp using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Map; // Get the entity manager via dependency injection [Dependency] private readonly IEntityManager _entityManager = default!; // Create an entity from a prototype at specific coordinates var coordinates = new EntityCoordinates(mapEntity, new Vector2(10, 5)); var entity = _entityManager.SpawnEntity("MyEntityPrototype", coordinates); // Get a component from an entity if (_entityManager.TryGetComponent(entity, out var transform)) { var position = transform.WorldPosition; var rotation = transform.WorldRotation; } // Query all entities with specific components var query = _entityManager.EntityQueryEnumerator(); while (query.MoveNext(out var uid, out var physics, out var transform)) { // Process entities with both PhysicsComponent and TransformComponent var velocity = physics.LinearVelocity; var position = transform.WorldPosition; } // Delete an entity _entityManager.DeleteEntity(entity); // Listen for entity events _entityManager.EntityAdded += OnEntityAdded; void OnEntityAdded(Entity entity) { // Handle new entity creation } ``` -------------------------------- ### Server Configuration (TOML) Source: https://context7.com/space-wizards/robusttoolbox/llms.txt Configuration file for the RobustToolbox server, defining logging, networking, game, hub, and authentication settings. These parameters control server behavior, network operations, and game-specific options. ```toml [log] path = "logs" format = "log_%(date)s-%(time)s.txt" level = 1 [net] tickrate = 30 port = 1212 bindto = "::,0.0.0.0" max_connections = 256 [game] hostname = "My Game Server" [hub] advertise = false tags = "roleplay,english" [auth] mode = 1 # 0 = Optional, 1 = Required, 2 = Disabled allowlocal = true ``` -------------------------------- ### C# Client Rendering System Source: https://context7.com/space-wizards/robusttoolbox/llms.txt C# code for the client-side rendering system in RobustToolbox, utilizing the Clyde rendering engine. It covers loading textures, creating render targets, and custom per-frame rendering. Requires Robust.Client.Graphics and Robust.Shared namespaces. ```csharp using Robust.Client.Graphics; using Robust.Client.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Maths; public sealed class ClientRenderingSystem : EntitySystem { [Dependency] private readonly IClyde _clyde = default!; [Dependency] private readonly IEyeManager _eyeManager = default!; private IRenderTexture? _renderTarget; private Texture? _customTexture; public override void Initialize() { base.Initialize(); // Load a texture _customTexture = _clyde.LoadTextureFromImage(myImage); // Create render target _renderTarget = _clyde.CreateRenderTarget( new Vector2i(1024, 768), new RenderTargetFormatParameters(RenderTargetColorFormat.Rgba8Srgb), name: "MyRenderTarget" ); } public override void FrameUpdate(float frameTime) { base.FrameUpdate(frameTime); // Custom rendering each frame var worldHandle = _clyde.RenderWindow.DrawingHandleWorld; // Draw using world coordinates foreach (var entity in GetEntitiesToRender()) { if (!TryComp(entity, out var xform)) continue; var worldPos = xform.WorldPosition; var rotation = xform.WorldRotation; worldHandle.DrawTexture(_customTexture, worldPos, rotation); } } } // Sprite component for entity rendering public sealed class MySpriteSystem : EntitySystem { public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnSpriteStartup); } private void OnSpriteStartup(EntityUid uid, SpriteComponent component, ComponentStartup args) { // Configure sprite rendering component.LayerMapReserveBlank("base"); component.LayerSetSprite("base", new SpriteSpecifier.Rsi( new ResPath("Objects/items.rsi"), "item_sprite" )); component.LayerSetVisible("base", true); } } ``` -------------------------------- ### Entity System Implementation in C# Source: https://context7.com/space-wizards/robusttoolbox/llms.txt Implements a custom entity system for handling component events and updates. It subscribes to component and global events, processes damage, and updates components on a per-tick basis. Requires Robust.Shared.GameObjects, Robust.Shared.IoC, and Robust.Shared.Timing namespaces. ```csharp using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Timing; public sealed class MyCustomSystem : EntitySystem { [Dependency] private readonly IGameTiming _timing = default!; public override void Initialize() { base.Initialize(); // Subscribe to component events SubscribeLocalEvent(OnComponentStartup); SubscribeLocalEvent(OnDamage); // Subscribe to broadcast events (not component-specific) SubscribeLocalEvent(OnGlobalEvent); } private void OnComponentStartup(EntityUid uid, MyComponent component, ComponentStartup args) { // Initialize component when entity starts up component.InitializedTime = _timing.CurTime; } private void OnDamage(EntityUid uid, MyComponent component, DamageEvent args) { // Handle damage event component.Health -= args.Damage; if (component.Health <= 0) { EntityManager.DeleteEntity(uid); } } private void OnGlobalEvent(EntityUid uid, MyComponent component, GlobalGameEvent args) { // Handle global events } public override void Update(float frameTime) { base.Update(frameTime); // Update all entities with MyComponent each tick var query = EntityQueryEnumerator(); while (query.MoveNext(out var uid, out var myComp, out var xform)) { myComp.Timer += frameTime; if (myComp.Timer > 1.0f) { // Do something every second myComp.Timer = 0; } } } } // Component-specific event (raised via RaiseLocalEvent targeting entity) // REQUIRED: Must be annotated with [ComponentEvent] attribute (v268.0.0+) [ComponentEvent] public record struct DamageEvent(float Damage); // Broadcast event (raised via RaiseLocalEvent without entity target) // No attribute needed for broadcast events public record struct GlobalGameEvent(string Message); // In some other system: // Raise event targeted at specific entity/component // RaiseLocalEvent(targetEntity, new DamageEvent(10f)); // Raise event as broadcast to all subscribers // var globalEvent = new GlobalGameEvent("Server restart in 5 minutes"); // RaiseLocalEvent(globalEvent); ``` -------------------------------- ### Handle Physics Collisions in C# with RobustToolbox Source: https://context7.com/space-wizards/robusttoolbox/llms.txt This C# snippet demonstrates how to handle collision events (StartCollideEvent and EndCollideEvent) using the RobustToolbox's physics system. It includes logic for applying damage based on collision force and notes important details about event buffering in specific versions of the engine. Dependencies include Robust.Shared.Physics and Robust.Shared.Maths. ```csharp using Robust.Shared.Physics; using Robust.Shared.Physics.Components; using Robust.Shared.Physics.Events; using Robust.Shared.Maths; public sealed class PhysicsExampleSystem : EntitySystem { [Dependency] private readonly SharedPhysicsSystem _physics = default!; public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnCollision); SubscribeLocalEvent(OnCollisionEnd); } private void OnCollision(EntityUid uid, PhysicsComponent component, ref StartCollideEvent args) { var otherEntity = args.OtherEntity; var ourEntity = args.OurEntity; // Handle collision logic // IMPORTANT: Collision events are buffered until end of physics substeps (v268.0.0+) // This means events may arrive slightly delayed from when the actual collision occurred // Multiple collisions in a single frame will be batched and processed together if (HasComp(otherEntity)) { // Apply damage based on collision force var impulse = args.OurFixture.Body.LinearVelocity.Length(); ApplyCollisionDamage(otherEntity, impulse); } } private void OnCollisionEnd(EntityUid uid, PhysicsComponent component, ref EndCollideEvent args) { // Handle separation // IMPORTANT: EndCollide events are double-buffered (v268.0.0+) // New EndCollide events raised during processing are dispatched on the next tick // This prevents infinite event loops but means separation handling is slightly delayed } public void ApplyForce(EntityUid entity, Vector2 force) { if (!TryComp(entity, out var physics)) return; _physics.ApplyLinearImpulse(entity, force, body: physics); } public void SetVelocity(EntityUid entity, Vector2 velocity) { if (!TryComp(entity, out var physics)) return; _physics.SetLinearVelocity(entity, velocity, body: physics); } public EntityUid CreatePhysicsEntity(EntityCoordinates coords) { var entity = EntityManager.SpawnEntity(null, coords); // Add physics component var physics = EntityManager.AddComponent(entity); physics.BodyType = BodyType.Dynamic; // Add fixture (collision shape) var fixture = new Fixture( physics, new PhysShapeCircle(0.5f) ); fixture.CollisionLayer = (int)CollisionGroup.MobLayer; fixture.CollisionMask = (int)(CollisionGroup.WallLayer | CollisionGroup.MobLayer); _physics.AddFixture(entity, fixture, body: physics); return entity; } } ``` -------------------------------- ### Adding a Child Control to a Parent Control - C# Source: https://github.com/space-wizards/robusttoolbox/wiki/UI-System-Tutorial Demonstrates how to add a child Control to a parent Control using the AddChild method in C#. It also verifies the parent-child relationship. ```csharp var parent = new Control("parent"); var child = new Control("child"); parent.AddChild(child); DebugTools.Assert(child.Parent == parent); ``` -------------------------------- ### RobustToolbox: C# Network Message Handling for Client-Server Communication Source: https://context7.com/space-wizards/robusttoolbox/llms.txt This snippet demonstrates how to define, register, and handle custom network messages in RobustToolbox using C#. It covers both server-side message registration and handling, as well as client-side message sending. Dependencies include Robust.Shared.Network, Robust.Shared.Serialization, and Lidgren.Network. The input is a custom NetMessage, and the output is server-side processing or client-side message transmission. ```csharp using Robust.Shared.Network; using Robust.Shared.Serialization; using Lidgren.Network; // Define a network message [Serializable, NetSerializable] public sealed class RequestItemMessage : NetMessage { public override MsgGroups MsgGroup => MsgGroups.EntityEvent; public EntityUid ItemEntity; public EntityUid TargetEntity; } // Server-side: Register and handle messages public sealed class ServerInventorySystem : EntitySystem { [Dependency] private readonly INetManager _netManager = default!; public override void Initialize() { base.Initialize(); // Subscribe to network message _netManager.RegisterNetMessage(HandleItemRequest); } private void HandleItemRequest(RequestItemMessage message) { var channel = message.MsgChannel; var player = channel.ConnectedPlayer; // Validate request server-side if (!ValidateItemRequest(player, message.ItemEntity, message.TargetEntity)) { return; } // Perform server-authoritative action TransferItem(message.ItemEntity, message.TargetEntity); // State automatically syncs to clients via component replication } // Send message to specific client public void SendUpdateToPlayer(INetChannel channel, EntityUid entity) { var msg = new EntityStateMessage { Entity = entity }; _netManager.ServerSendMessage(msg, channel); } // Broadcast to all clients public void BroadcastEvent(EntityUid entity) { var msg = new GlobalEventMessage { Entity = entity }; _netManager.ServerSendToAll(msg); } } // Client-side: Send messages to server public sealed class ClientInventorySystem : EntitySystem { [Dependency] private readonly INetManager _netManager = default!; public void RequestPickupItem(EntityUid item, EntityUid target) { var msg = new RequestItemMessage { ItemEntity = item, TargetEntity = target }; _netManager.ClientSendMessage(msg); } } ``` -------------------------------- ### IconComponent Prototype Configuration (YAML) Source: https://github.com/space-wizards/robusttoolbox/wiki/Sprite-&-Icon-documentation Defines the structure for an IconComponent in a prototype, specifying texture, sprite, and state for entity icons. Texture is for direct image files, while sprite and state are for RSI archives. Texture and sprite/state are mutually exclusive. ```yaml - type: icon texture: "" sprite: "" state: "" ``` -------------------------------- ### Add Default Font Prototype Requirement (YAML) Source: https://github.com/space-wizards/robusttoolbox/blob/master/RELEASE-NOTES.md This YAML snippet demonstrates the required 'Default' font prototype configuration. It specifies the font type, its ID as 'Default', and the path to the font file. This is a breaking change introduced in version 0.88.0.0. ```yaml - type: font id: Default path: /Fonts/NotoSans/NotoSans-Regular.ttf ``` -------------------------------- ### Implement Client-Side Component State Handling - C# Source: https://github.com/space-wizards/robusttoolbox/wiki/Entity-and-Component-netcode This C# code shows the client-side implementation for handling replicated component states. It defines the expected `StateType` and overrides `HandleComponentState` to cast the incoming state and update the client's component data accordingly. This is essential for visual and functional synchronization. ```csharp // CLIENT SIDE CODE. public override Type StateType => typeof(DooHickyComponentState); public override void HandleComponentState(ComponentState state) { // Note: although the state is passed in as ComponentState, // It will always be the same type as StateType, you can safely cast it. var dooHickyState = (DooHickyComponentState)state; DoTheStuff = dooHickyState.DoTheStuff; } ``` -------------------------------- ### YAML Prototype Definitions for Entities in RobustToolbox Source: https://context7.com/space-wizards/robusttoolbox/llms.txt Defines entity prototypes using YAML, supporting inheritance and data-driven design. Prototypes are defined in YAML files and can inherit from abstract or concrete prototypes, allowing for modular and reusable definitions of game entities and their components. This system facilitates a data-driven approach to game content creation. ```yaml # entities.yml - Define entity prototypes - type: entity id: BaseWeapon abstract: true components: - type: Sprite sprite: Objects/Weapons/weapons.rsi - type: Item size: 10 - type: Physics mass: 2 - type: entity id: WeaponPistol parent: BaseWeapon name: pistol description: A standard pistol. components: - type: Sprite state: pistol - type: Gun fireRate: 2.0 damage: 15 range: 20 - type: Item size: 8 - type: entity id: WeaponRifle parent: BaseWeapon name: rifle description: A military rifle. components: - type: Sprite state: rifle - type: Gun fireRate: 4.0 damage: 25 range: 50 ``` -------------------------------- ### Component Definition and Networking in C# Source: https://context7.com/space-wizards/robusttoolbox/llms.txt Defines data components with automatic network synchronization using RobustToolbox attributes. Supports modern automatic state generation with field-level deltas and a legacy approach for custom synchronization logic. Requires Robust.Shared.GameObjects, Robust.Shared.Serialization, and Robust.Shared.GameStates namespaces. ```csharp using Robust.Shared.GameObjects; using Robust.Shared.Serialization; using Robust.Shared.GameStates; // Modern approach: AutoGenerateComponentState with field-level deltas [RegisterComponent] [NetworkedComponent] [AutoGenerateComponentState(true, fieldDeltas: true)] // Automatic field-level delta states public sealed partial class MyComponent : Component { // Automatically serialized and networked fields [DataField, AutoNetworkedField] public float Health = 100f; [DataField, AutoNetworkedField] public float MaxHealth = 100f; [DataField, AutoNetworkedField] public float Armor = 0f; // Non-serialized runtime state [ViewVariables] public float Timer; [ViewVariables] public TimeSpan InitializedTime; } // Legacy approach: Manual component state (still supported for custom sync logic) [RegisterComponent] [NetworkedComponent] public sealed partial class LegacyComponent : Component { [DataField("health")] public float Health = 100f; [DataField("maxHealth")] public float MaxHealth = 100f; // Component state for explicit network synchronization public override ComponentState GetComponentState() { return new LegacyComponentState { Health = Health, MaxHealth = MaxHealth }; } public override void HandleComponentState(ComponentState? curState, ComponentState? nextState) { if (curState is not LegacyComponentState state) return; Health = state.Health; MaxHealth = state.MaxHealth; } } [Serializable, NetSerializable] public sealed class LegacyComponentState : ComponentState { public float Health; public float MaxHealth; } ``` -------------------------------- ### Implement Server-Side Component State Retrieval - C# Source: https://github.com/space-wizards/robusttoolbox/wiki/Entity-and-Component-netcode This C# code snippet demonstrates how a server-side component overrides the `GetComponentState()` method to return an instance of its corresponding `ComponentState`. This ensures that the current state of the component is packaged and sent to the client for replication. ```csharp // SERVER SIDE CODE. public override ComponentState GetComponentState() { return new DooHickyComponentState(DoTheStuff); } ``` -------------------------------- ### Define Server-Side Component for Replication - C# Source: https://github.com/space-wizards/robusttoolbox/wiki/Entity-and-Component-netcode This C# code defines a server-side component, `DooHickyComponent`, which includes essential properties like Name and NetID. It is marked as server-side and prepares for replication by defining a NetID. This component will have its state synchronized with the client. ```csharp // NOTE: This specific snippet is server-side code. For this tutorial we'll assume the components are basically copies of each other. // Though when client or server-specific code is used it is marked. using SS14.Shared.GameObjects; using SS14.Shared.GameObjects.Components; namespace SS14.Server.GameObjects { public class DooHickyComponent : Component { // Name, needed by all components. public override string Name => "DooHicky"; // Net ID, required to sync across the network. // IMPORTANT: the type is uint?, NOT uint. The question mark means it's nullable. public override uint? NetID => NetIDs.DOO_HICKY; // The variable that we will be replicating. public bool DoTheStuff { get; set; } } } ```