### Installing Specific Godot Version with GodotEnv (Shell) Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/docs/setup.mdx This command uses the `godotenv` tool to automatically download and install a specific version of Godot (e.g., 4.0.1) onto the system. GodotEnv handles the extraction, installation, and symlinking, simplifying the process of managing multiple Godot versions. This command requires GodotEnv to be previously installed. ```Shell godotenv godot install 4.0.1 ``` -------------------------------- ### Installing Chickensoft Godot Project Templates Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/docs/setup.mdx These shell commands use the `dotnet new install` command to add Chickensoft's custom project templates (`GodotGame` and `GodotPackage`) to the local `dotnet` tool, enabling quick creation of new C# Godot projects. ```sh dotnet new install Chickensoft.GodotGame dotnet new install Chickensoft.GodotPackage ``` -------------------------------- ### Creating a New Godot Game Project (Shell) Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/docs/setup.mdx This snippet demonstrates how to initialize a new Godot game project using the `chickengame` dotnet template. It creates a new directory with the specified name and author, then navigates into it and restores project dependencies. This setup includes debug configurations, testing, and CI/CD integration. ```Shell dotnet new chickengame --name "MyGameName" --param:author "My Name" cd MyGameName dotnet restore ``` -------------------------------- ### Installing GodotEnv CLI Tool (.NET CLI) Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/docs/setup.mdx This command installs the `Chickensoft.GodotEnv` command-line tool globally using the .NET SDK's tool management system. GodotEnv is used to manage Godot versions and asset library addons. This requires the .NET SDK to be properly installed and configured in the system's PATH. ```Shell dotnet tool install --global Chickensoft.GodotEnv ``` -------------------------------- ### Installing .NET 8 SDK using Winget on Windows Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/docs/setup.mdx This command utilizes the Winget package manager within PowerShell to install the .NET 8 SDK on Windows. It requires administrator privileges to execute. The command `winget upgrade` can be used to update an existing .NET SDK installation. ```PowerShell winget install dotnet-sdk-8 ``` -------------------------------- ### Creating a Reusable Godot Nuget Package (Shell) Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/docs/setup.mdx This snippet outlines the steps to create a new reusable Nuget package for Godot using the `chickenpackage` dotnet template. It first installs the template, then generates a new project with the specified name and author. Finally, it builds the Godot solutions headlessly and compiles the .NET project, setting up for continuous integration and debugging. ```Shell dotnet new --install Chickensoft.GodotPackage dotnet new chickenpackage --name "MyPackageName" --param:author "My Name" cd MyPackageName /path/to/godot4 --headless --build-solutions --quit dotnet build ``` -------------------------------- ### Using and Binding to a LogicBlock in C# Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/docs/logic_blocks/quick_start.mdx This snippet illustrates how to interact with a `LogicBlock` instance. It shows how to start the logic block, add inputs, access the current state, and use the binding system to monitor outputs, inputs, state changes, and exceptions. It emphasizes preferring output monitoring over state changes for more flexible code. ```csharp // Start the logic block to force the initial state to be active. // // This is optional: you can also start a logic block by just adding an // input to it or reading its state. logic.Start(); // Add an input to turn our light switch on. logic.Input(new LightSwitch.Input.Toggle()); // The logic block's value represents the current state. var state = logic.Value; // PoweredOn // Bindings allow you to observe the logic block easily. using var binding = logic.Bind(); // Monitor an output: binding.Handle((in LightSwitch.Output.StatusChanged output) => Console.WriteLine( $"Status changed to {(output.IsOn ? "on" : "off")}" ) ); // Can also use bindings to monitor inputs, state changes, and exceptions. // // In general, prefer monitoring outputs over state changes for more // flexible code. // Monitor an input: binding.Watch((in LightSwitch.Input.Toggle input) => Console.WriteLine("Toggled!") ); // Monitor a specific type of state: binding.When((LightSwitch.State.PoweredOn _) => Console.WriteLine("Powered on!") ); // Monitor all exceptions: binding.Catch((Exception e) => Console.WriteLine(e.Message)); // Monitor specific types of exceptions: binding.Catch((InvalidOperationException e) => Console.WriteLine(e.Message) ); ``` -------------------------------- ### Recommended VSCode Settings for C# Development and Terminal Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/docs/setup.mdx This set of VSCode configurations enhances the C# development workflow by suppressing hidden diagnostics, enabling bracket pair guides, and automating code actions (like import organization and fixes) on save. It also configures Windows terminal profiles to default to Git Bash. ```javascript "csharp.suppressHiddenDiagnostics": false, // Draw a line between selected brackets so you can see blocks of code easier. "editor.guides.bracketPairs": "active", "[csharp]": { "editor.codeActionsOnSave": { "source.addMissingImports": "explicit", "source.fixAll": "explicit", "source.organizeImports": "explicit" }, "editor.formatOnPaste": true, "editor.formatOnSave": true, "editor.formatOnType": true }, // To make bash the default terminal on Windows, add these: "terminal.integrated.defaultProfile.windows": "Git Bash", "terminal.integrated.profiles.windows": { "Command Prompt": { "icon": "terminal-cmd", "path": [ "${env:windir}\\Sysnative\\cmd.exe", "${env:windir}\\System32\\cmd.exe" ] }, "Git Bash": { "icon": "terminal", "source": "Git Bash" }, "PowerShell": { "icon": "terminal-powershell", "source": "PowerShell" } } ``` -------------------------------- ### Implementing Two-Phase Initialization in Godot C# Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/blog/game-architecture.mdx This C# snippet demonstrates the two-phase initialization pattern within a Godot `Control` script, `InGameUI`. The `Setup()` method is used for creating internal dependencies like `InGameUILogic`, while `OnResolved()` handles binding to state machine outputs and starting the logic. This separation ensures dependencies are fully resolved before being used, facilitating dependency injection and unit testing by allowing mock values to be injected. ```csharp [Meta(typeof(IAutoNode))] public partial class InGameUI : Control, IInGameUI { public override void _Notification(int what) => this.Notify(what); #region Dependencies [Dependency] public IAppRepo AppRepo => DependOn(); #endregion Dependencies #region Nodes [Node] public ILabel CoinsLabel { get; set; } = default!; #endregion Nodes #region State public IInGameUILogic InGameUILogic { get; set; } = default!; public InGameUILogic.IBinding InGameUIBinding { get; set; } = default!; #endregion State public void Setup() { InGameUILogic = new InGameUILogic(this, AppRepo); } public void OnResolved() { InGameUIBinding = InGameUILogic.Bind(); InGameUIBinding .Handle( (output) => SetCoinsLabel( output.NumCoinsCollected, output.NumCoinsAtStart ) ); InGameUILogic.Start(); } ``` -------------------------------- ### Fixing C# Semantic Highlighting in VSCode Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/docs/setup.mdx These VSCode `editor.tokenColorCustomizations` settings adjust the foreground colors for C# documentation comments across different themes (Dark, Light, and others) to improve readability and correct funky semantic highlighting issues. ```javascript "editor.tokenColorCustomizations": { "[*Dark*]": { // Themes that include the word "Dark" in them. "textMateRules": [ { "scope": "comment.documentation", "settings": { "foreground": "#608B4E" } }, { "scope": "comment.documentation.attribute", "settings": { "foreground": "#C8C8C8" } }, { "scope": "comment.documentation.cdata", "settings": { "foreground": "#E9D585" } }, { "scope": "comment.documentation.delimiter", "settings": { "foreground": "#808080" } }, { "scope": "comment.documentation.name", "settings": { "foreground": "#569CD6" } } ] }, "[*Light*]": { // Themes that include the word "Light" in them. "textMateRules": [ { "scope": "comment.documentation", "settings": { "foreground": "#008000" } }, { "scope": "comment.documentation.attribute", "settings": { "foreground": "#282828" } }, { "scope": "comment.documentation.cdata", "settings": { "foreground": "#808080" } }, { "scope": "comment.documentation.delimiter", "settings": { "foreground": "#808080" } }, { "scope": "comment.documentation.name", "settings": { "foreground": "#808080" } } ] }, "[*]": { // Themes that don't include the word "Dark" or "Light" in them. // These are some bold colors that show up well against most dark and // light themes. // // Change them to something that goes well with your preferred theme :) "textMateRules": [ { "scope": "comment.documentation", "settings": { "foreground": "#0091ff" } }, { "scope": "comment.documentation.attribute", "settings": { "foreground": "#8480ff" } }, { "scope": "comment.documentation.cdata", "settings": { "foreground": "#0091ff" } }, { "scope": "comment.documentation.delimiter", "settings": { "foreground": "#aa00ff" } }, { "scope": "comment.documentation.name", "settings": { "foreground": "#ef0074" } } ] } } ``` -------------------------------- ### Configuring .NET SDK Environment Variables for Windows (Git Bash) Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/docs/setup.mdx This snippet configures the .NET SDK environment variables for Windows users utilizing Git Bash. It sets the DOTNET_ROOT path, disables telemetry, and enables roll-forward to prerelease versions. Users should add this to their `~/.bashrc` file. Note that the provided snippet is incomplete and may require additional PATH configurations. ```sh # .NET SDK Configuration export DOTNET_ROOT="C:\\Program Files\\dotnet" export DOTNET_CLI_TELEMETRY_OPTOUT=1 # Disable analytics export DOTNET_ROLL_FORWARD_TO_PRERELEASE=1 ``` -------------------------------- ### Configuring .NET SDK Environment Variables for Linux (Bash) Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/docs/setup.mdx This snippet configures the .NET SDK environment variables for Linux users utilizing Bash. It sets the DOTNET_ROOT path, disables telemetry, enables roll-forward to prerelease versions, and adds necessary .NET SDK directories to the system's PATH. It also includes an alias `nugetclean` to clear NuGet local caches, useful for resolving `dotnet restore` errors. Users should add this to their `~/.bashrc` file. ```sh # .NET SDK Configuration export DOTNET_ROOT="/usr/share/dotnet" export DOTNET_CLI_TELEMETRY_OPTOUT=1 # Disable analytics export DOTNET_ROLL_FORWARD_TO_PRERELEASE=1 # Add the .NET SDK to the system paths so we can use the `dotnet` tool. export PATH="$DOTNET_ROOT:$PATH" export PATH="$DOTNET_ROOT/sdk:$PATH" export PATH="$HOME/.dotnet/tools:$PATH" # Run this if you ever run into errors while doing a `dotnet restore` alias nugetclean="dotnet nuget locals --clear all" ``` -------------------------------- ### Configuring .NET SDK Paths and Nuget Cache Alias (Bash) Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/docs/setup.mdx These commands add the .NET SDK directories to the system's PATH environment variable, enabling the `dotnet` tool to be used from any terminal. It also defines an alias `nugetclean` to clear all local NuGet caches, useful for resolving `dotnet restore` errors. Users should verify if these paths are already set and adjust `DOTNET_ROOT` as needed. ```Bash export PATH="$DOTNET_ROOT:$PATH" export PATH="$DOTNET_ROOT\sdk:$PATH" export PATH="$HOME\.dotnet\tools:$PATH" alias nugetclean="dotnet nuget locals --clear all" ``` -------------------------------- ### Configuring OmniSharp and C# Extension in VSCode Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/docs/setup.mdx These settings enable OmniSharp and prioritize the C# extension for improved project compatibility and C# development experience within VSCode. They ensure proper C# language server functionality. ```javascript "dotnetAcquisitionExtension.enableTelemetry": false, // Increases project compatibility with the C# extension. "dotnet.preferCSharpExtension": true, ``` -------------------------------- ### Creating a LightSwitch LogicBlock in C# Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/docs/logic_blocks/quick_start.mdx This snippet defines a `LightSwitch` logic block by extending `LogicBlock`. It demonstrates how to define initial states, inputs (using a nested `Input` class), outputs (using a nested `Output` class), and state transitions (e.g., `PoweredOn` and `PoweredOff` states handling `Input.Toggle`). It highlights the use of `[Meta]` and `[LogicBlock]` attributes for introspection and diagram generation. ```csharp using Chickensoft.Introspection; [Meta, LogicBlock(typeof(State), Diagram = true)] public partial class LightSwitch : LogicBlock { // Define your initial state here. public override Transition GetInitialState() => To(); // By convention, inputs are defined in a static nested class called Input. public static class Input { public readonly record struct Toggle; } // By convention, outputs are defined in a static nested class called Output. public static class Output { public readonly record struct StatusChanged(bool IsOn); } // To reduce unnecessary heap allocations, inputs and outputs should be // readonly record structs. // By convention, the base state type is nested inside the logic block. This // helps the logic block diagram generator know where to search for state // types. public abstract record State : StateLogic { // Substates are sometimes nested inside their parent states to help // organize the code. // On state. public record PoweredOn : State, IGet { public PoweredOn() { // Announce that we are now on. this.OnEnter(() => Output(new Output.StatusChanged(IsOn: true))); } public Transition On(in Input.Toggle input) => To(); } // Off state. public record PoweredOff : State, IGet { public PoweredOff() { // Announce that we are now off. this.OnEnter(() => Output(new Output.StatusChanged(IsOn: false))); } public Transition On(in Input.Toggle input) => To(); } } } ``` -------------------------------- ### Configuring .NET SDK Environment Variables for macOS (Zsh) Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/docs/setup.mdx This snippet configures the .NET SDK environment variables for macOS users utilizing Zsh. It sets the DOTNET_ROOT path, disables telemetry, enables roll-forward to prerelease versions, and adds necessary .NET SDK directories to the system's PATH. It also includes an alias `nugetclean` to clear NuGet local caches, useful for resolving `dotnet restore` errors. Users should add this to their `~/.zshrc` file. ```sh # .NET SDK Configuration export DOTNET_ROOT="/usr/local/share/dotnet" export DOTNET_CLI_TELEMETRY_OPTOUT=1 # Disable analytics export DOTNET_ROLL_FORWARD_TO_PRERELEASE=1 # Add the .NET SDK to the system paths so we can use the `dotnet` tool. export PATH="$DOTNET_ROOT:$PATH" export PATH="$DOTNET_ROOT/sdk:$PATH" export PATH="$HOME/.dotnet/tools:$PATH" # Run this if you ever run into errors while doing a `dotnet restore` alias nugetclean="dotnet nuget locals --clear all" ``` -------------------------------- ### Starting LogicBlock and Observing Initial State Entry (C#) Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/docs/logic_blocks/basics/states.mdx This C# snippet demonstrates initiating a LogicBlock instance by calling `logic.Start()`. It shows the expected console output, illustrating that when the initial state `Standing` (which inherits from `Inactive`) is entered, the `OnEnter` callbacks for both the base `Inactive` state and the derived `Standing` state are invoked in order. ```csharp logic.Start(); // Prints: // Inactive // Standing ``` -------------------------------- ### Accessing Blackboard Dependencies in C# Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/docs/logic_blocks/basics/states.mdx This C# snippet illustrates how to interact with the `LogicBlock`'s internal blackboard. It shows how to instantiate a `LogicBlock`, add dependencies (like `IService`) to the blackboard using `Set()`, and then retrieve them using `Get()`. This mechanism allows states to access shared data. ```csharp var logic = new MyLogicBlock(); // Add all the dependencies that states will need. logic.Set(new MyRelatedService()); var service = logic.Get(); ``` -------------------------------- ### Referencing Godot .NET SDK in C# Project (XML) Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/docs/how_csharp_works.mdx This XML snippet shows the root `` element in a `.csproj` file, referencing the `Godot.NET.Sdk`. This SDK implicitly includes necessary source generators and configurations for C# development in Godot, streamlining the project setup. ```XML ``` -------------------------------- ### Starting and Stopping a LogicBlock in C# Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/docs/logic_blocks/basics/states.mdx Illustrates how to explicitly start and stop a LogicBlock instance. `logic.Start()` ensures the initial state is attached and entered, triggering relevant callbacks. `logic.Stop()` exits and detaches the current state, also invoking associated callbacks. This provides precise control over when the logic block's side effects begin and end, as logic blocks are lazily initialized by default. ```csharp var logic = new MyLogicBlock(); // Make sure the initial state is attached and entered. logic.Start(); // Exit and detach the current state. logic.Stop(); ``` -------------------------------- ### Setting Up a Fake Godot Scene Tree for Unit Testing (C#) Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/blog/game-architecture.mdx This C# `Setup` method demonstrates how to prepare a Godot scene script for unit testing using mock objects. It initializes mock dependencies for `IAppRepo`, `IAnimationPlayer`, `INode3D`, and `ICoinLogic`, then injects these mocks into the `Coin` object. The `FakeDependency` method prevents the node from searching the tree for providers, while `FakeNodeTree` maps mock objects to specific node paths, allowing the `Coin` script to be tested in isolation without a real scene tree. ```C# [Setup] public void Setup() { _appRepo = new Mock(); _animPlayer = new Mock(); _coinModel = new Mock(); _logic = new Mock(); _binding = CoinLogic.CreateFakeBinding(); _logic.Setup(logic => logic.Bind()).Returns(_binding); _coin = new Coin { IsTesting = true, AnimationPlayer = _animPlayer.Object, CoinModel = _coinModel.Object, CoinLogic = _logic.Object, CoinBinding = _binding }; _coin.FakeDependency(_appRepo.Object); _coin.FakeNodeTree(new() { ["%AnimationPlayer"] = _animPlayer.Object, ["%CoinModel"] = _coinModel.Object }); } ``` -------------------------------- ### Producing an Output from a State in C# Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/docs/logic_blocks/basics/outputs.mdx This example shows how a state produces an output by calling the `Output` method. Here, a `StatusChanged` output is produced when the `PoweredOn` state is entered, signaling a change in the light switch's status to external listeners. ```C# public record PoweredOn : State { public PoweredOn() { this.OnEnter(() => // Produce an output when we enter this state. Output(new Output.StatusChanged(IsOn: true)) ); } } ``` -------------------------------- ### Restricting Logic Block Operations with Interfaces in C# Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/docs/logic_blocks/basics/outputs.mdx This example demonstrates how to enforce a contract for interactions with blackboard objects by using interfaces. By setting and getting a service via `IMyRelatedService`, the logic block's state is restricted to only the operations defined by that interface, promoting better encapsulation and control. ```C# logic = new MyLogicBlock(); logic.Set(new MyRelatedService() as IMyRelatedService) // or, same as above: logic.Set(new MyRelatedService()) // elsewhere, in your logic block state public Transition On(in Input.SomethingHappened input) { // must access by the type it was stored as var something = Get().GrabSomethingForMe(); // ... return ToSelf(); } ``` -------------------------------- ### Adding LogicBlocks and Generator Package References (XML) Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/docs/logic_blocks/installation.mdx This snippet shows how to add NuGet package references for Chickensoft.LogicBlocks, its DiagramGenerator, and Introspection.Generator to a C# project file. It's crucial to include "PrivateAssets=\"all\"" and "OutputItemType=\"analyzer\"" for the generator packages to ensure they are correctly processed during compilation without being included in the build output. ```xml ``` -------------------------------- ### Setting Godot Environment Variable in Zsh (macOS) Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/docs/setup.mdx This snippet shows how to manually set the `GODOT` environment variable in the `~/.zshrc` file on macOS. This variable points to the Godot executable symlink managed by GodotEnv, ensuring Chickensoft templates and VSCode configurations can locate the correct Godot version. Users must log out and log back in for changes to take effect. ```sh # This should be added to your ~/.zshrc file by GodotEnv automatically, but # you can also add it manually and change the path of Godot to match # your system. export GODOT="/Users/{you}/.config/godotenv/godot/bin" ``` -------------------------------- ### Sending an Input to a Logic Block in C# Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/docs/logic_blocks/basics/inputs.mdx This C# example demonstrates how to interact with a logic block by sending it an input. It instantiates a `DimmableLightSwitch` and then calls its `Input` method, passing a new `DimmerUpdated` record struct with a value of `0.5d`. This illustrates how ephemeral input objects carry data to trigger actions within the logic block. ```csharp var dimmableLightSwitch = new DimmableLightSwitch(); dimmableLightSwitch.Input(new DimmableLightSwitch.Input.DimmerUpdated(0.5d)); ``` -------------------------------- ### Setting Godot Environment Variable in Bash (Linux) Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/docs/setup.mdx This snippet demonstrates how to manually set the `GODOT` environment variable in the `~/.bashrc` file on Linux. This variable directs to the Godot executable symlink managed by GodotEnv, which is crucial for Chickensoft templates and VSCode configurations to find the appropriate Godot version. A logout and login are required for the changes to be applied system-wide. ```sh # This should be added to your ~/.zshrc file by GodotEnv automatically, but # you can also add it manually and change the path of Godot to match # your system. export GODOT="/home/{you}/.config/godotenv/godot/bin" ``` -------------------------------- ### Configuring CS9057 Warning as Error in C# Project (XML) Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/docs/logic_blocks/installation.mdx This XML snippet demonstrates how to modify a C# project's PropertyGroup to treat the CS9057 warning as an error. This configuration is strongly recommended to proactively identify and prevent potential compiler-mismatch issues that can arise when using the Chickensoft Introspection generator, ensuring build stability. ```xml net8.0 ... CS9057 ... ``` -------------------------------- ### Mocking a Logic Block for Component Testing in C# Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/docs/logic_blocks/testing/testing_logic_blocks.mdx This example illustrates how to mock an `ITimer` LogicBlock using Moq within a unit test for `MyComponent`. It shows setting up the mock's state (`Timer.Value`) to simulate a specific condition (`State.PoweredOff`), enabling the testing of component behavior that depends on the LogicBlock's state without relying on its concrete implementation. ```C# using static Chickensoft.LogicBlocks.Tutorial.Timer; sealed record MyComponent(ITimer Timer) { public void DoSomething() { if (Timer.Value is State.PoweredOff) { // Do something when the timer is off. } } } public class MyComponentTest { [Fact] public void Mocks() { var timer = new Mock(); // Make the mock logic block be in a specific state. timer.Setup(t => t.Value).Returns(new State.PoweredOff()); var component = new MyComponent(timer.Object); component.DoSomething(); } } ``` -------------------------------- ### Implementing Versioned Serializable Models in C# Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/blog/serialization-for-csharp-games.mdx This C# example illustrates how to implement versioning for serializable models. `LogEntry1` is marked with `[Version(1)]` and implements `IOutdated`, providing an `Upgrade` method to transform old data into the `LogEntry2` format. `LogEntry2` is marked with `[Version(2)]`, ensuring that the serialization system can automatically upgrade outdated models during deserialization, maintaining data integrity across schema changes. ```C# [Meta, Id("log_entry")] public abstract partial class LogEntry : SystemLogEntry { } [Meta, Version(1)] public partial class LogEntry1 : LogEntry, IOutdated { [Save("text")] public required string Text { get; init; } [Save("type")] public required string Type { get; init; } public object Upgrade(IReadOnlyBlackboard deps) => new LogEntry2() { Text = Text, Type = Type switch { "info" => LogType.Info, "warning" => LogType.Warning, "error" or _ => LogType.Error, } }; } public enum LogType { Info, Warning, Error } [Meta, Version(2)] public partial class LogEntry2 : LogEntry { [Save("text")] public required string Text { get; init; } [Save("type")] public required LogType Type { get; init; } } ``` -------------------------------- ### Applying All AutoInject Mixins with Introspection (C#) Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/blog/serialization-for-csharp-games.mdx This C# snippet demonstrates how to apply all available AutoInject mixins to a Godot Node using the new Introspection generator. By decorating a partial class with `[Meta(typeof(IAutoNode))]`, the node automatically gains capabilities for dependency injection, property binding, dependency provision, and .NET-style notification callbacks, simplifying node setup and unit testing. ```csharp // Apply all of the AutoInject mixins at once: [Meta(typeof(IAutoNode))] public partial class MyNode : Node { } ``` -------------------------------- ### Running Development Server with npm Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/README.md This command initiates the Next.js development server, making the website accessible locally. It's a standard practice for local development, typically running on port 3000, and includes features like hot-reloading for efficient development. ```bash npm run dev ``` -------------------------------- ### Configuring Godot Project Settings for Display Scaling Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/blog/display-scaling.mdx This JSON snippet shows the recommended settings for the `project.godot` file to enable proper display scaling using Chickensoft's tools. It configures viewport and window sizes, initial position, default theme scale, and font rendering options for crisp visuals. ```JSON [display] window/size/viewport_width=720 window/size/viewport_height=720 window/size/initial_position_type=3 window/size/window_width_override=1280 window/size/window_height_override=720 [gui] theme/default_theme_scale=2.0 theme/default_font_multichannel_signed_distance_field=true theme/default_font_generate_mipmaps=true ``` -------------------------------- ### Testing Logic Block Initialization and Dependencies in C# Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/docs/logic_blocks/testing/testing_logic_blocks.mdx This snippet demonstrates how to test the initialization of a `Timer` LogicBlock. It involves mocking external dependencies like `IClock`, injecting them into the LogicBlock's blackboard, and then asserting that the LogicBlock correctly transitions to its initial state (`State.PoweredOff`) and properly registers its dependencies. ```C# [Fact] public void Initializes() { // Mock dependencies that the logic block needs. var clock = new Mock(); // Create the real logic block. var timer = new Timer(); // Add the mocked dependencies to the blackboard. timer.Set(clock.Object); // Check that the initial state is the one we expect. var state = timer.GetInitialState() .State .ShouldBeOfType(); // Verify the timer has set its blackboard data correctly. timer.Has().ShouldBeTrue(); timer.Get().ShouldBe(clock.Object); } ``` -------------------------------- ### Directly Manipulating a Blackboard Object in C# Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/docs/logic_blocks/basics/outputs.mdx This code demonstrates direct manipulation, where a state interacts with an object stored on the logic block's blackboard. By calling `Get()`, the state directly invokes a method on a service, suitable for mutating objects in a lower architectural layer. ```C# public Transition On(in Input.SomethingHappened input) { Get().ChangeSomething(input.Value); return ToSelf(); } ``` -------------------------------- ### Testing State Input and Dependency Injection with Fake Context in C# Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/docs/logic_blocks/testing/testing_states.mdx Illustrates how to test a state's reaction to an input and how to inject dependencies into the fake context's blackboard. It demonstrates setting a value on the blackboard, invoking an input, and verifying the state transition and updated data. ```csharp [Fact] public void ChangesDuration() { var state = new Timer.State.PoweredOn.Idle(); var context = state.CreateFakeContext(); // Put a value on the blackboard for the state to use. context.Set(new Timer.Data() { Duration = 30.0d }); var duration = 45; state.On(new Timer.Input.ChangeDuration(duration)) .State .ShouldBeOfType(); context.Get().Duration.ShouldBe(duration); } ``` -------------------------------- ### Defining Kitchen Timer State Machine with Mermaid Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/docs/logic_blocks/tutorial/index.mdx This Mermaid diagram visualizes the hierarchical state machine for a kitchen timer, outlining its various states (PoweredOff, PoweredOn, Idle, Countdown, Beeping) and the transitions between them triggered by events like PowerButtonPressed, StartStopButtonPressed, and TimeElapsed. It also shows OnEnter and OnExit actions for the Beeping state. ```Mermaid stateDiagram-v2 state "Timer State" as Chickensoft_LogicBlocks_Tests_Examples_Timer_State { state "PoweredOff" as Chickensoft_LogicBlocks_Tests_Examples_Timer_State_PoweredOff state "PoweredOn" as Chickensoft_LogicBlocks_Tests_Examples_Timer_State_PoweredOn { state "Idle" as Chickensoft_LogicBlocks_Tests_Examples_Timer_State_PoweredOn_Idle state "Countdown" as Chickensoft_LogicBlocks_Tests_Examples_Timer_State_PoweredOn_Countdown state "Beeping" as Chickensoft_LogicBlocks_Tests_Examples_Timer_State_PoweredOn_Beeping } } Chickensoft_LogicBlocks_Tests_Examples_Timer_State_PoweredOff --> Chickensoft_LogicBlocks_Tests_Examples_Timer_State_PoweredOn_Idle : PowerButtonPressed Chickensoft_LogicBlocks_Tests_Examples_Timer_State_PoweredOn --> Chickensoft_LogicBlocks_Tests_Examples_Timer_State_PoweredOff : PowerButtonPressed Chickensoft_LogicBlocks_Tests_Examples_Timer_State_PoweredOn_Countdown --> Chickensoft_LogicBlocks_Tests_Examples_Timer_State_PoweredOn_Beeping : TimeElapsed Chickensoft_LogicBlocks_Tests_Examples_Timer_State_PoweredOn_Countdown --> Chickensoft_LogicBlocks_Tests_Examples_Timer_State_PoweredOn_Countdown : TimeElapsed Chickensoft_LogicBlocks_Tests_Examples_Timer_State_PoweredOn_Countdown --> Chickensoft_LogicBlocks_Tests_Examples_Timer_State_PoweredOn_Idle : StartStopButtonPressed Chickensoft_LogicBlocks_Tests_Examples_Timer_State_PoweredOn_Idle --> Chickensoft_LogicBlocks_Tests_Examples_Timer_State_PoweredOn_Countdown : StartStopButtonPressed Chickensoft_LogicBlocks_Tests_Examples_Timer_State_PoweredOn_Beeping : OnEnter → PlayBeepingSound Chickensoft_LogicBlocks_Tests_Examples_Timer_State_PoweredOn_Beeping : OnExit → StopBeepingSound [*] --> Chickensoft_LogicBlocks_Tests_Examples_Timer_State_PoweredOff ``` -------------------------------- ### Providing Dependencies with AutoInject in C# Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/blog/game-architecture.mdx This snippet demonstrates how a Godot node, `Player`, provides an `IPlayerLogic` instance to its descendants using AutoInject. It implements `IProvide` and calls `Provide()` in `OnReady()` to signal that the dependency is available, ensuring proper initialization order. ```csharp [Meta(typeof(IAutoNode))] public partial class Player : CharacterBody3D, IPlayer, IProvide { public override void _Notification(int what) => this.Notify(what); #region Provisions IPlayerLogic IProvide.Value() => PlayerLogic; #endregion Provisions // ... public void OnReady() { PlayerLogic = new PlayerLogic(/* ... */); Provide(); // Indicate the dependencies we provide are now available. } } ``` -------------------------------- ### Handling Multiple Inputs and State Transitions in C# Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/docs/logic_blocks/basics/states.mdx This C# snippet shows a state (`MyState`) that implements multiple `IGet` interfaces to handle different input types (A, B, C). It demonstrates how to define `On` methods for each input, allowing the state to either remain in the current state (`ToSelf()`) or transition to a new state (`To()`). ```csharp public record MyState : State, IGet, IGet, IGet { // Don't change states on A public Transition On(in Input.A input) => ToSelf(); // Go to StateC on C public Transition On(in Input.C input) => To(); } ``` -------------------------------- ### Initializing Window Scaling with GameTools in C# Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/blog/display-scaling.mdx This snippet demonstrates how to initialize the window scaling behavior using the `LookGood` method from Chickensoft GameTools within Godot's `_Ready` lifecycle method. It sets the window to either `UIFixed` or `UIProportional` scaling based on a specified design resolution, such as `UHD4k`. ```csharp public override void _Ready() { GetWindow().LookGood( WindowScaleBehavior.UIFixed, // or UIProportional Display.UHD4k // your theme design resolution (such as 4K) ); } ``` -------------------------------- ### Visualizing LogicBlock State with Mermaid Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/docs/logic_blocks/index.mdx This Mermaid code snippet demonstrates how LogicBlocks can generate UML state diagrams from C# code. It visualizes the `LightSwitch` state machine, showing its `PoweredOn` and `PoweredOff` states, the `Toggle` transitions between them, and the `StatusChanged` output triggered on state entry, providing a clear high-level overview of the state machine's behavior. ```mermaid stateDiagram-v2 state "LightSwitch State" as Chickensoft_LogicBlocks_DiagramGenerator_Tests_TestCases_LightSwitch_State { state "PoweredOn" as Chickensoft_LogicBlocks_DiagramGenerator_Tests_TestCases_LightSwitch_State_PoweredOn state "PoweredOff" as Chickensoft_LogicBlocks_DiagramGenerator_Tests_TestCases_LightSwitch_State_PoweredOff } Chickensoft_LogicBlocks_DiagramGenerator_Tests_TestCases_LightSwitch_State_PoweredOff --> Chickensoft_LogicBlocks_DiagramGenerator_Tests_TestCases_LightSwitch_State_PoweredOn : Toggle Chickensoft_LogicBlocks_DiagramGenerator_Tests_TestCases_LightSwitch_State_PoweredOn --> Chickensoft_LogicBlocks_DiagramGenerator_Tests_TestCases_LightSwitch_State_PoweredOff : Toggle Chickensoft_LogicBlocks_DiagramGenerator_Tests_TestCases_LightSwitch_State_PoweredOff : OnEnter → StatusChanged Chickensoft_LogicBlocks_DiagramGenerator_Tests_TestCases_LightSwitch_State_PoweredOn : OnEnter → StatusChanged [*] --> Chickensoft_LogicBlocks_DiagramGenerator_Tests_TestCases_LightSwitch_State_PoweredOff ``` -------------------------------- ### Adding Start/Stop Button Input and Countdown Transition in C# Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/docs/logic_blocks/tutorial/power.mdx This C# snippet further enhances the `Idle` state by adding support for a `StartStopButtonPressed` input. It demonstrates how the `Idle` state transitions to a new `Countdown` state when the start/stop button is pressed, while still handling the `ChangeDuration` input by updating the shared `Data` and remaining in the current state. ```csharp public static class Input { public readonly record struct PowerButtonPressed; public readonly record struct ChangeDuration(double Duration); public readonly record struct StartStopButtonPressed; } public record Idle : PoweredOn, IGet, IGet { public Transition On(in Input.ChangeDuration input) { Get().Duration = input.Duration; return ToSelf(); } public Transition On(in Input.StartStopButtonPressed input) => To(); } ``` -------------------------------- ### Incorrect Generic Logic Block Declaration in C# Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/docs/logic_blocks/tips_and_tricks.mdx This example illustrates a common pitfall when declaring generic logic blocks in C#. It shows how nesting a logic block's state type inside a generic type leads to a CS0416 build error because typeof expressions within attributes cannot implicitly reference generic types. The State type, though seemingly non-generic, is implicitly generic due to its nesting. ```csharp // Example: nesting a logic block in a generic type public class MyGenericType { [LogicBlock(typeof(State))] // <- Error CS0416 public class MyLogicBlock : LogicBlock { public override Transition GetInitialState() => To(); public record State : StateLogic {} } } ``` -------------------------------- ### Creating Fake LogicBlock Bindings in C# Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/docs/logic_blocks/testing/testing_bindings.mdx This code illustrates how to create a fake binding for a `MyLogicBlock` using Moq. It initializes a mock of the logic block, then creates a fake binding using the static `CreateFakeBinding()` method, and finally sets up the mock to return this fake binding when `Bind()` is called, enabling simulation of logic block behavior. ```csharp var logic = new Mock(); // CreateFakeBinding() is actually a static method on the logic block. var binding = MyLogicBlock.CreateFakeBinding(); // Make our mock logic block return the fake binding. logic.Setup(logic => logic.Bind()).Returns(binding); ``` -------------------------------- ### Transitioning to Full-Screen with GameTools in C# Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/blog/display-scaling.mdx This code shows how to switch the application to full-screen mode while maintaining the specified window scaling behavior. By calling `LookGood` again with `isFullscreen: true`, the window adapts to full-screen while preserving the `UIFixed` or `UIProportional` scaling and design resolution. ```csharp GetWindow().LookGood( WindowScaleBehavior.UIFixed, Display.UHD4k, isFullscreen: true ); ``` -------------------------------- ### Adding Plain C# Package Reference to CSPROJ Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/docs/how_csharp_works.mdx This XML snippet demonstrates how to add a reference to a plain C# NuGet package, such as `Chickensoft.Serialization`, within the `` section of a `.csproj` file. This allows the project to utilize the package's functionalities. Dependencies are managed by `dotnet restore`. ```XML ``` -------------------------------- ### Simulating LogicBlock Input with Fake Binding in C# Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/docs/logic_blocks/testing/testing_bindings.mdx This snippet demonstrates how to simulate an input to a `MyLogicBlock` using a fake binding. After setting up a mock `IMyLogicBlock` to return a fake binding, the `Input()` method of the fake binding is called with a new `MyLogicBlock.Input.SomeInput()` instance, simulating an incoming input event. ```csharp var logic = new Mock(); var binding = MyLogicBlock.CreateFakeBinding(); logic.Setup(logic => logic.Bind()).Returns(binding); // Simulate an input with our fake binding. binding.Input(new MyLogicBlock.Input.SomeInput()); ``` -------------------------------- ### Configuring Godot .NET SDK Version with global.json (JSON) Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/docs/how_csharp_works.mdx This JSON snippet illustrates a `global.json` file used to specify the version of the `Godot.NET.Sdk` and the .NET SDK itself. It centralizes version management, allowing for easier updates and consistent development environments across projects by defining `msbuild-sdks` and `sdk` properties. ```JSON { "msbuild-sdks": { "Godot.NET.Sdk": "4.4.0" }, "sdk": { "rollForward": "major", "version": "8.0.401" } } ``` -------------------------------- ### Configuring Fixed UI Scaling with Minimum Size and Aspect Ratio in C# Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/blog/display-scaling.mdx This snippet illustrates advanced configuration for `UIFixed` scaling, allowing control over the minimum window size and aspect ratio. It prevents the window from shrinking below 50% of screen dimensions and attempts to maintain the project's defined aspect ratio, useful for responsive windowed modes. ```csharp // Don't allow the window to be less than 50% of either screen dimension, // and try to make sure the resulting size uses the aspect ratio of the // window size set in the project settings. GetWindow().LookGood( WindowScaleBehavior.UIFixed, BaseResolution, isFullscreen: _isFullscreen, minWindowedSize: 0.5f, useProjectAspectRatio: true ); ``` -------------------------------- ### Simulating LogicBlock Output with Fake Binding in C# Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/docs/logic_blocks/testing/testing_bindings.mdx This code shows how to simulate an output from a `MyLogicBlock` using a fake binding. Similar to input simulation, after configuring the mock logic block, the `Output()` method of the fake binding is invoked with a `MyLogicBlock.Output.SomeOutput()` instance, simulating an outgoing output event. ```csharp var logic = new Mock(); var binding = MyLogicBlock.CreateFakeBinding(); logic.Setup(logic => logic.Bind()).Returns(binding); // Simulate an input with our fake binding. binding.Output(new MyLogicBlock.Output.SomeOutput()); ``` -------------------------------- ### Feature-Based File Structure for Coin Feature Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/blog/game-architecture.mdx This snippet illustrates the recommended feature-based file organization for a 'Coin' feature. All related assets, scripts (C#), scenes (Godot), audio, and state machine logic are encapsulated within a single `coin` directory, promoting modularity and ease of access for both developers and artists. ```text ├── src │   ├── coin │   │   ├── Coin.cs │   │   ├── Coin.tscn │   │   ├── CollectorDetector.tscn │   │   ├── audio │   │   │   ├── coin_collected.mp3 │   │   │   └── coin_collected.mp3.import │   │   ├── state │   │   │   ├── CoinLogic.Input.cs │   │   │   ├── CoinLogic.Output.cs │   │   │   ├── CoinLogic.State.cs │   │   │   ├── CoinLogic.cs │   │   │   ├── CoinLogic.g.puml │   │   │   └── states │   │   │   ├── CoinLogic.State.Collecting.cs │   │   │   └── CoinLogic.State.Idle.cs │   │   └── visuals │   │   ├── coin_model.glb │   │   ├── coin_model.glb.import │   │   ├── coin_normal.tres │   │   ├── coin_roughness.tres │   │   ├── coin_texture.tres │   │   └── teleport_3d.gdshader ``` -------------------------------- ### Responding to an Output with a Binding in C# Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/docs/logic_blocks/basics/outputs.mdx This snippet illustrates how to subscribe to and handle specific outputs from a logic block using a binding. The `Handle` method allows external systems to react to an output, such as `StatusChanged`, enabling decoupled communication and ensuring zero memory allocations with `struct` types. ```C# using var binding = lightSwitch.Bind(); // Monitor an output: binding.Handle((in LightSwitch.Output.StatusChanged output) => System.Console.WriteLine( $"Status changed to {(output.IsOn ? "on" : "off")}" ) ); ``` -------------------------------- ### Output After Transitioning from Walking to Running State Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/docs/logic_blocks/basics/states.mdx This text snippet displays the console output when the state machine transitions from `Walking` to `Running`. It highlights that only the `OnEnter` callback for the `Running` state is invoked because both `Walking` and `Running` share the same `Active` parent state, demonstrating LogicBlocks' optimized callback execution for transitions within the same compound state. ```text Running ``` -------------------------------- ### Applying Custom Content Scale Factor in C# Source: https://github.com/chickensoft-games/chickensoft_site/blob/main/content/blog/display-scaling.mdx This code demonstrates how to apply an additional custom content scale factor after `LookGood` has determined the initial scaling. This allows developers to offer user-adjustable UI scaling, providing more granular control over the final UI size beyond the automatic scaling. ```csharp var myScaleFactor = 1.25f; GetWindow().ContentScaleFactor *= myScaleFactor; ```