{"id":23514444,"url":"https://github.com/chickensoft-games/LogicBlocks","last_synced_at":"2025-08-28T08:31:21.810Z","repository":{"id":181332663,"uuid":"666606232","full_name":"chickensoft-games/LogicBlocks","owner":"chickensoft-games","description":"Human-friendly, hierarchical and serializable state machines for games and apps in C#.","archived":false,"fork":false,"pushed_at":"2025-08-11T22:38:47.000Z","size":1694,"stargazers_count":250,"open_issues_count":4,"forks_count":10,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-08-12T00:23:31.112Z","etag":null,"topics":["app","csharp","game","gamedev","statechart","statecharts","statemachine","statemanagement"],"latest_commit_sha":null,"homepage":"https://www.nuget.org/packages/Chickensoft.LogicBlocks","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chickensoft-games.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-07-15T01:25:59.000Z","updated_at":"2025-08-11T22:38:39.000Z","dependencies_parsed_at":null,"dependency_job_id":"a449a3d4-8254-4b34-8e5b-98ff68a48b29","html_url":"https://github.com/chickensoft-games/LogicBlocks","commit_stats":null,"previous_names":["chickensoft-games/logicblocks"],"tags_count":44,"template":false,"template_full_name":null,"purl":"pkg:github/chickensoft-games/LogicBlocks","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chickensoft-games%2FLogicBlocks","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chickensoft-games%2FLogicBlocks/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chickensoft-games%2FLogicBlocks/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chickensoft-games%2FLogicBlocks/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chickensoft-games","download_url":"https://codeload.github.com/chickensoft-games/LogicBlocks/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chickensoft-games%2FLogicBlocks/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":272470220,"owners_count":24939927,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-28T02:00:10.768Z","response_time":74,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["app","csharp","game","gamedev","statechart","statecharts","statemachine","statemanagement"],"created_at":"2024-12-25T14:01:44.480Z","updated_at":"2025-08-28T08:31:21.803Z","avatar_url":"https://github.com/chickensoft-games.png","language":"C#","funding_links":[],"categories":["Contributors Welcome for those"],"sub_categories":["1. [ThisAssembly](https://ignatandrei.github.io/RSCG_Examples/v2/docs/ThisAssembly) , in the [EnhancementProject](https://ignatandrei.github.io/RSCG_Examples/v2/docs/rscg-examples#enhancementproject) category"],"readme":"# 💡 LogicBlocks\n\n[![Chickensoft Badge][chickensoft-badge]][chickensoft-website] [![Discord][discord-badge]][discord] [![Read the docs][read-the-docs-badge]][docs] ![line coverage][line-coverage] ![branch coverage][branch-coverage]\n\nLogicBlocks is a serializable, hierarchical state machine package for C# that works well when targeting ahead-of-time (AOT) environments. LogicBlocks draws inspiration from [statecharts], [state machines][state-machines], and [blocs][bloc-pattern].\n\n---\n\n\u003cp align=\"center\"\u003e\n\u003cimg alt=\"Chickensoft.LogicBlocks\" src=\"Chickensoft.LogicBlocks/icon.png\" width=\"200\"\u003e\n\u003c/p\u003e\n\n---\n\nInstead of elaborate transition tables, states are simply defined as self-contained class records that read like ordinary code using the [state pattern][state-pattern]. Logic blocks are designed with performance, adaptability, and error tolerance in mind, making them refactor-friendly and suitable for high performance scenarios (such as games).\n\nLogic blocks grow with your code: you can start with a simple state machine and easily scale it into a nested, hierarchical statechart that represents a more complex system — even while you're working out what the system should be.\n\n## 📚 What to Read Next\n\nLogic blocks are based on _statecharts_. You may also know them as hierarchical state machines (HSM's).\n\n- 🚨 The Official ✨ [LogicBlocks Docs][docs] ✨\n\n  Read this as soon as you're up to speed on statecharts.\n\n- 🟢 [Introduction to State Machines and Statecharts][xstate-intro]\n\n  **Beginner**: overview for those who are new to statecharts.\n\n- 🟡 [Statecharts.dev][statecharts]\n\n  **Intermediate**: all the statechart concepts in one place.\n\n- 🔴 [UML State Machine (Wikipedia)][UML]\n\n  **Expert**: all the juicy technical details are here.\n\n- 🔵 [Logic Blocks Timer Tutorial][tutorial]\n\n  **In a hurry?** Learn about hierarchical states and logic blocks all at once!\n\n## 💡 Example\n\n_A logic block is a class that **receives inputs**, **maintains a single state instance**, and **produces outputs**._\n\n_Logic blocks enable you to efficiently model complex behaviors_[^1].\n\n```csharp\nusing Chickensoft.Introspection;\n\n[Meta, LogicBlock(typeof(State), Diagram = true)]\npublic class LightSwitch : LogicBlock\u003cLightSwitch.State\u003e {\n  public override Transition GetInitialState() =\u003e To\u003cState.PoweredOff\u003e();\n\n  public static class Input {\n    public readonly record struct Toggle;\n  }\n\n  public abstract record State : StateLogic\u003cState\u003e {\n    public record PoweredOn : State, IGet\u003cInput.Toggle\u003e {\n      public Transition On(in Input.Toggle input) =\u003e To\u003cPoweredOff\u003e();\n    }\n\n    public record PoweredOff : State, IGet\u003cInput.Toggle\u003e {\n      public Transition On(in Input.Toggle input) =\u003e To\u003cPoweredOn\u003e();\n    }\n  }\n\n  public static class Output {\n    public readonly record struct StatusChanged(bool IsOn);\n  }\n}\n```\n\n## 🖼️ Visualizing Logic Blocks\n\nLogicBlocks provides a source generator that can generate [UML state diagrams][UML] of your code.\n\n```mermaid\nstateDiagram-v2\n\nstate \"LightSwitch State\" as Chickensoft_LogicBlocks_DiagramGenerator_Tests_TestCases_LightSwitch_State {\n  state \"PoweredOn\" as Chickensoft_LogicBlocks_DiagramGenerator_Tests_TestCases_LightSwitch_State_PoweredOn\n  state \"PoweredOff\" as Chickensoft_LogicBlocks_DiagramGenerator_Tests_TestCases_LightSwitch_State_PoweredOff\n}\n\nChickensoft_LogicBlocks_DiagramGenerator_Tests_TestCases_LightSwitch_State_PoweredOff --\u003e Chickensoft_LogicBlocks_DiagramGenerator_Tests_TestCases_LightSwitch_State_PoweredOn : Toggle\nChickensoft_LogicBlocks_DiagramGenerator_Tests_TestCases_LightSwitch_State_PoweredOn --\u003e Chickensoft_LogicBlocks_DiagramGenerator_Tests_TestCases_LightSwitch_State_PoweredOff : Toggle\n\nChickensoft_LogicBlocks_DiagramGenerator_Tests_TestCases_LightSwitch_State_PoweredOff : OnEnter → StatusChanged\nChickensoft_LogicBlocks_DiagramGenerator_Tests_TestCases_LightSwitch_State_PoweredOn : OnEnter → StatusChanged\n\n[*] --\u003e Chickensoft_LogicBlocks_DiagramGenerator_Tests_TestCases_LightSwitch_State_PoweredOff\n```\n\nGenerated UML diagrams are placed alongside the code for your logic block with the `*.g.puml` extension. You can use [PlantUML] (and/or the [PlantUML VSCode Extension]) to visualize the generated diagram code.\n\n\u003e [!TIP]\n\u003e A diagram explains all of the high level behavior of a state machine in a single picture. Without a diagram, you would have to read and scroll through all the relevant code files to understand the machine (especially if you weren't the author, or forgot how it worked since you had written it).\n\n## 🤫 Differences from Statecharts\n\nIn the interest of convenience, logic blocks have a few subtle differences from statecharts:\n\n- 💂‍♀️ No explicit guards\n\n  Use conditional logic in an input handler\n\n- 🪢 Attach/Detach callbacks\n\n  These are an implementation specific detail that are called whenever the state _instance_ changes, as opposed to only being called when the state type hierarchy (i.e., state configuration) changes.\n\n- 🕰️ No event deferral\n\n  Non-handled inputs are simply discarded. There's nothing to stop you from implementing [input buffering] on your own, though: you may even use the [boxless queue] collection that LogicBlocks uses internally.\n\nLogicBlocks also uses different terms for some of the statechart concepts to make them more intuitive or disambiguate them from other C# terminology.\n\n| statecharts         | logic blocks    |\n| ------------------- | --------------- |\n| internal transition | self transition |\n| event               | input           |\n| action              | output          |\n\n[^1]: Simple behaviors, like the light switch example, are considerably more verbose than they need to be. Logic blocks shine brightest when they're used for things that actually require hierarchical state machines.\n\n---\n\nLooking for more? **Read the ✨ [docs]! ✨**\n\n---\n🐣 Package generated from a 🐤 Chickensoft Template — \u003chttps://chickensoft.games\u003e\n\n[chickensoft-badge]: https://chickensoft.games/img/badges/chickensoft_badge.svg\n[chickensoft-website]: https://chickensoft.games\n[discord-badge]: https://chickensoft.games/img/badges/discord_badge.svg\n[discord]: https://discord.gg/gSjaPgMmYW\n[read-the-docs-badge]: https://chickensoft.games/img/badges/read_the_docs_badge.svg\n[docs]: https://chickensoft.games/docs/logic_blocks\n[branch-coverage]: Chickensoft.LogicBlocks.Tests/badges/branch_coverage.svg\n[line-coverage]: Chickensoft.LogicBlocks.Tests/badges/line_coverage.svg\n\n[xstate-intro]: https://xstate.js.org/docs/guides/introduction-to-state-machines-and-statecharts/\n[statecharts]: https://statecharts.dev/\n[UML]: https://en.wikipedia.org/wiki/UML_state_machine\n[PlantUML VSCode Extension]: https://marketplace.visualstudio.com/items?itemName=jebbs.plantuml\n[PlantUML]: https://plantuml.com/\n[input buffering]: https://supersmashbros.fandom.com/wiki/Input_Buffering\n[boxless queue]: https://github.com/chickensoft-games/Collections?tab=readme-ov-file#boxless-queue\n[bloc-pattern]: https://www.flutteris.com/blog/en/reactive-programming-streams-bloc\n[state-machines]: https://en.wikipedia.org/wiki/Finite-state_machine\n[state-pattern]: https://en.wikipedia.org/wiki/State_pattern\n[tutorial]: https://chickensoft.games/docs/logic_blocks/tutorial\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchickensoft-games%2FLogicBlocks","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchickensoft-games%2FLogicBlocks","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchickensoft-games%2FLogicBlocks/lists"}