<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Seaube</title>
    <description>The latest articles on DEV Community by Seaube (@seaube).</description>
    <link>https://dev.to/seaube</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F6197%2F08a5a17d-f808-4ae2-af84-18a7df1a687e.png</url>
      <title>DEV Community: Seaube</title>
      <link>https://dev.to/seaube</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/seaube"/>
    <language>en</language>
    <item>
      <title>Introducing Ecsact</title>
      <dc:creator>Ezekiel Warren</dc:creator>
      <pubDate>Sat, 24 Jun 2023 22:54:28 +0000</pubDate>
      <link>https://dev.to/seaube/introducing-ecsact-13h6</link>
      <guid>https://dev.to/seaube/introducing-ecsact-13h6</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fecsact.dev%2Fassets%2Flogo.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fecsact.dev%2Fassets%2Flogo.svg" alt="Ecsact Logo" width="500" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;TL;DR - Ecsact (&lt;a href="https://ecsact.dev" rel="noopener noreferrer"&gt;ecsact.dev&lt;/a&gt;) is a free and open source language and runtime standard dedicated to the Entity Component System (ECS) architecture.&lt;/p&gt;

&lt;p&gt;If you don’t want to know how we came up with Ecsact you can just skip right to the “What is Ecsact?” section below.&lt;/p&gt;

&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;About ~3 years ago a friend of mine and myself set off to create a multiplayer game I will refer to as “Project ZC”. The game itself isn’t that important, but at the time I sold the Entity Component System (ECS) architecture to my friend.  Our strategy for synchronizing the game simulation was to create a deterministic set of systems that run on the server and clients. Player input was handled by sending out “actions” which were just systems that could be arbitrarily executed in the game simulation. Additionally we had some mechanisms to make sure the simulation ticks were not drifting.&lt;/p&gt;

&lt;p&gt;At first we weren’t sure which game engine to use. We debated between Unity, Unreal, Godot, and using some rust framework/engine. Based on our experiences with each and the kind of game we wanted to make, we ended up picking Unity. However we were willing to switch to something else over the next several months if it didn’t work out. Unity had ECS support as part of Unity DOTS, but it was version 0.0 at the time and it didn’t look quite ready. Ultimately we decided not to use Unity’s ECS not only because it was in early development, but because we wanted to have a standalone server that didn’t rely on anything Unity related.&lt;/p&gt;

&lt;p&gt;Since we wanted a common game simulation that would be on both the server and the client we looked into a few libraries that would fit our ECS needs. It was decided we were going to write this common part of our game in C++, but rust was considered. C++ was a familiar language for us so naturally &lt;a href="https://github.com/skypjack/entt" rel="noopener noreferrer"&gt;EnTT&lt;/a&gt; and &lt;a href="https://github.com/SanderMertens/flecs" rel="noopener noreferrer"&gt;flecs&lt;/a&gt; came up right away. I had used EnTT before, writing some small demo projects, so our choice was made based on familiarity. In order to integrate with Unity we created a small C interface to communicate between our simulation code and Unity’s C#. Here’s close to what it looked like. I removed some parts for brevity sake.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;zc_init&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;zc_quit&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;zc_auth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;zc_push_action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;action_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;action_data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Event callbacks&lt;/span&gt;
&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="nf"&gt;void&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;zc_component_event_callback&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;component_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;component_data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;user_data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;zc_register_init_component_callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="n"&gt;zc_component_event_callback&lt;/span&gt; &lt;span class="n"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;user_data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;zc_register_update_component_callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="n"&gt;zc_component_event_callback&lt;/span&gt; &lt;span class="n"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;user_data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;zc_register_remove_component_callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="n"&gt;zc_component_event_callback&lt;/span&gt; &lt;span class="n"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;user_data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Flush events - triggers any pending event callbacks&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;zc_flush&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this small API we had our C# listening to events happening to components in the simulation. For example we had a “Position” component that represented, well, the position. Simple X and Y coordinates. And for every entity we had a game object. By adding a few event listeners we were able to synchronize the game objects transform to the position component coordinates. Similarly we had an “Attacking” component and when that “Attacking” component was added an animation would trigger.&lt;/p&gt;

&lt;p&gt;This worked well for a while. We kept adding more components and setup effects when components changed or simply synchronizing state. One thing really bothered me though. I was duplicating component type definitions in C# and in C++. One weekend I came up with a solution. I created an interface description language (IDL) dubbed “ECS IDL”. The language looked something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;component Position {
  int32 x;
  int32 y;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which I would feed into a code generator that would create a C# struct like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Position&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;global&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Int32&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;global&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Int32&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And a C++ struct like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;cstdint&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Position&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;constexpr&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What I had at the time wasn’t very impressive, but it was useful! In hindsight I was overengineering the solution big time, but in my mind I figured I would add new things to the language to help with other ECS related things. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;And that we did&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Shortly after I gave the same treatment to our “action” concept since they could have fields like components can.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;action Jump {
  int32 player_id;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But it didn’t feel quite right. Actions are systems so they only run on entities with specific components. I figured “hey I could put that in the language too!”. I came up with a few keywords that made sense to me at the time.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Keyword&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;required&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The action implementation runs on components marked as &lt;code&gt;required&lt;/code&gt; and can read/write to them.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;readonly&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The action implementation can only read data from components marked as &lt;code&gt;readonly&lt;/code&gt;. Can only be used with the &lt;code&gt;required&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;include&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The action is run on entities with components marked as &lt;code&gt;include&lt;/code&gt; but cannot read or write them.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;exclude&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The action skips entities with components marked as &lt;code&gt;exclude&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;action Jump {
  int32 player_id;

  include Grounded;
  required Velocity;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I thought “why just actions, let’s put systems in there too!”&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;system ApplyVelocity {
  required readonly Position;
  required Velocity;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I didn’t immediately have a reason to do this, but it dawned on me that I could use these declarations for &lt;strong&gt;execution order&lt;/strong&gt;. I built a code generator that created EnTT views based on the system requirements and ran them in order specified by the file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;system PassiveHeal {
  required Health;
}

system PoisonDamage {
  required Health;
  include Poisoned;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those system (and action) declaration when ran through the code generator turned into something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;PassiveHealView&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;entt&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Health&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;PoisonDamageView&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;entt&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Health&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Poisoned&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This kept going and going. Feature after feature I noticed I could do more things by declaring systems in a dedicated language. Much more could be said about how we got to this point, but I think you get the idea.&lt;/p&gt;

&lt;p&gt;After playing with ECS IDL for a while we decided that this idea of a dedicated language for ECS would be useful as a general concept. We didn’t build ECS IDL to be generally used on other projects. It was built only for Project ZC. We decided to stop working on Project ZC and go full-boar trying to generalize ECS IDL as a tool anyone could use. Not only for us when we decide to start a new project, but for everyone who sees the value in it.&lt;/p&gt;

&lt;p&gt;Over a year we spent cleaning up the language, creating a flexible runtime standard, and implementing a runtime that can utilize the users files to make it optimal based on each project. Oh! And we changed the name to Ecsact. ECS-Act. Entity Component System + Action. It also sounds like “exact” and we liked that. The rest of this article goes on to talk about Ecsact which is slightly different from the ECS IDL I described.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Ecsact?
&lt;/h2&gt;

&lt;p&gt;Ecsact is a language and runtime standard dedicated to the Entity Component System architecture. Ecsact is not a programming language; it falls more under the category of an “&lt;a href="https://en.wikipedia.org/wiki/Interface_description_language" rel="noopener noreferrer"&gt;Interface Description Language&lt;/a&gt;” with some runtime consequences, but enough with the semantics. What is Ecsact!&lt;/p&gt;

&lt;h3&gt;
  
  
  The Language
&lt;/h3&gt;

&lt;p&gt;The Ecsact language is like a contract (and before you ask I don’t mean smart contracts - Ecsact has nothing to do with blockchain technology.) The contract specifies how your game simulation is executed. You declare your components and your systems in the Ecsact file and the simulation will run in the order your systems are declared. Here’s an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package example;

component Poisoned { i32 potency; } 
component Health   { i32 value; }
component Mana     { i32 value; }
component Dead;

system PoisonDamage {
    readonly Poisoned;
    readwrite Health;
    exclude Dead;
}

system PassiveHeal {
    readwrite Health;
    exclude Dead;
}

system PassiveManaRegen {
    readwrite Mana;
    exclude Dead;
}

system DeathChecker {
    readonly Health;
    adds Dead;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Read more about the language syntax: &lt;a href="https://ecsact.dev/docs/lang" rel="noopener noreferrer"&gt;ecsact.dev/docs/lang&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this example I have specified 4 components and 4 systems. The systems are executed in declaration order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;code&gt;PoisonDamage&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PassiveHeal&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PassiveManaRegen&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DeathChecker&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The order can have some nuance on your simulation and it’s nice to see how your game is simulated at a high level, but that’s only a small part of what Ecsact brings.&lt;/p&gt;

&lt;h3&gt;
  
  
  Systems and Code Generation
&lt;/h3&gt;

&lt;p&gt;Ecsact generates interfaces to implement your systems safely. Each system implementation may only access what was declared in the system block.&lt;/p&gt;

&lt;p&gt;Systems can be implemented in C++ and Rust at this time, but any language that can be compiled into Web Assembly can theoretically work. Here’s what a C++ and rust implementation of the &lt;code&gt;PoisonDamage&lt;/code&gt; might look like:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;C++&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;"example.ecsact.systems.hh"&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;PoisonDamage&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;impl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;poisoned&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Poisoned&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;health&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Health&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;health&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="n"&gt;poisoned&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;potency&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;health&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Rust&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;my_crate&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;#[ecsact_macro::system_impl(&lt;/span&gt;&lt;span class="s"&gt;"example.PoisonDamage"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;poison_dmg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="nn"&gt;example&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;PoisonDamage&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;poisoned&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;example&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Poisoned&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="nf"&gt;.get&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;health&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;example&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Health&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="nf"&gt;.get&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;health&lt;/span&gt;&lt;span class="py"&gt;.value&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="n"&gt;poisoned&lt;/span&gt;&lt;span class="py"&gt;.potency&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="nf"&gt;.update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;health&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In either example if you tried to do something your system wasn’t allowed to do you would get a compile time error. For example, if you tried to write &lt;code&gt;ctx.update(poisoned)&lt;/code&gt; in the PoisonDamage system implementation the compiler wouldn’t let you.&lt;/p&gt;

&lt;h3&gt;
  
  
  Optimized Runtime
&lt;/h3&gt;

&lt;p&gt;By having strong guarantees for your system implementations the Ecsact runtime can be optimized.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Systems that require unrelated components can run in parallel&lt;/li&gt;
&lt;li&gt;Systems that only read same components can run in parallel&lt;/li&gt;
&lt;li&gt;Components can be stored optimally for a system to avoid cache misses&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE: Optimizing the runtime is an on-going effort. We’re actively exploring utilizing different ECS libraries and other techniques such as code generation to optimize further.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  The Runtime
&lt;/h3&gt;

&lt;p&gt;The Ecsact runtime standard is a set of C headers available in the &lt;a href="https://github.com/ecsact-dev/ecsact_runtime" rel="noopener noreferrer"&gt;ecsact-dev/ecsact_runtime&lt;/a&gt; GitHub repository. We chose C for maximum compatibility between languages and integration between other software (such as game engines.)&lt;/p&gt;

&lt;p&gt;Here’s a small snippet of what the ecsact C API looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="c1"&gt;// small modified snippet from core header&lt;/span&gt;

&lt;span class="n"&gt;ecsact_registry_id&lt;/span&gt; &lt;span class="nf"&gt;ecsact_create_registry&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;ecsact_entity_id&lt;/span&gt; &lt;span class="nf"&gt;ecsact_create_entity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ecsact_registry_id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;ecsact_add_component&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;ecsact_registry_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ecsact_entity_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ecsact_component_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;component_data&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Ecsact runtime C API encompasses everything from entity creation to executing systems. Each part of the runtime is split into “modules”. Each module has a single C header. A high level is described here in the &lt;a href="https://ecsact.dev/docs/runtime" rel="noopener noreferrer"&gt;Ecsact runtime library overview&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Fortunately this API is not something you would use directly if you’re using Ecsact. Our intention with Ecsact is to have equivalent APIs for the language and/or game engine you’re using. Unless you’re implementing your own runtime, developing an integration, or creating/maintaining bindings for a language you’ll never see these C functions.&lt;/p&gt;

&lt;p&gt;For example in the above system implementation snippets the C++ and rust code are actually calling some Ecsact C functions such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// In C++ and rust ctx.get() calls this C function&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;ecsact_system_execution_context_get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;ecsact_system_execution_context&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;  &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ecsact_component_like_id&lt;/span&gt;          &lt;span class="n"&gt;component_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;                             &lt;span class="n"&gt;out_component_data&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  System Execution
&lt;/h3&gt;

&lt;p&gt;The heart of an Ecsact project involves executing your systems. In the core module there is a single function responsible for that. It accepts a few parameters which allow you to add options to that execution window and get events (feedback) from the execution.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fafac7o60gup75yjo0asv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fafac7o60gup75yjo0asv.png" alt="Ecsact Execution Chart" width="720" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every time systems are executed all relevant changes are reported to the event handlers.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Event Type&lt;/th&gt;
&lt;th&gt;Event Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Create Entity&lt;/td&gt;
&lt;td&gt;A new entity has been added to the registry either through execution options or generated by a system/action.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Init Component&lt;/td&gt;
&lt;td&gt;A new component has been added to an entity through execution options or by a system/action.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Update Component&lt;/td&gt;
&lt;td&gt;A components value has changed on an entity through execution options or by a system/action.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Remove Component&lt;/td&gt;
&lt;td&gt;A component has been removed from an entity through execution options or by a system/action&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Destroy Entity&lt;/td&gt;
&lt;td&gt;An entity has been removed from the registry through execution options or by a system/action.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;When integrating with a game engine or framework you listen to these events to trigger graphics, animations, particle effects etc.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmnpxuk2650sgqirqlv2d.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmnpxuk2650sgqirqlv2d.gif" alt="Ecsact Events Demonstration" width="720" height="414"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Networking (multiplayer)
&lt;/h3&gt;

&lt;p&gt;The async module of the Ecsact runtime is built for synchronizing a simulation over a network. It’s designed to work out of the box with almost no changes to your code.&lt;/p&gt;

&lt;p&gt;Executing systems doesn’t happen directly in the async module. Instead, executing systems are handled for you in the background and you’re given a function to “flush” the queued up events so that you may respond to them. A function is also given to “enqueue” execution options to be executed as soon as possible based on the async modules implementation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg0qkriw2s9gxo1xz7czl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg0qkriw2s9gxo1xz7czl.png" alt="Ecsact Async Execution Chart" width="800" height="489"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The async module implementation is responsible for deciding the rate at which systems are executed and also provide events coming from another source (such as another player.) Only relevant events are given when a flush occurs. For example if you flush between a few execution cycles and a component was added and removed from the same entity you would get no event.&lt;/p&gt;

&lt;p&gt;One other difference between the core system execution and the async module is a “connect” function. The connect function takes in a string in a format defined by the async module implementation. This typically would involve a way to identify which server to connect to as well as authentication.&lt;/p&gt;

&lt;h2&gt;
  
  
  Developing with Ecsact
&lt;/h2&gt;

&lt;p&gt;We’re using Ecsact ourselves. I would argue dogfooding a project like Ecsact is the only way to make it work. We’re doing all we can to make developing with Ecsact as easy as possible.&lt;/p&gt;

&lt;h3&gt;
  
  
  Integrations with &lt;em&gt;X&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;For the most part, focus on integrating with software that we use regularly is our priority. Following the instructions on ecsact.dev/start will get you the Ecsact SDK as well as instruction for integrating with a game engine.&lt;/p&gt;

&lt;p&gt;Here are some of the tools we’ve created so far:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A language server for Ecsact so we can use neovim, vscode or any other IDE that supports the language server protocol - &lt;a href="https://github.com/ecsact-dev/ecsact_lsp_server" rel="noopener noreferrer"&gt;ecsact-dev/ecsact_lsp_server&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Tree sitter for syntax highlighting on editors such as neovim that support it - &lt;a href="https://github.com/ecsact-dev/tree-sitter-ecsact" rel="noopener noreferrer"&gt;ecsact-dev/tree-sitter-ecsact&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Integration with the unity engine as a unity package - &lt;a href="https://github.com/ecsact-dev/ecsact_unity" rel="noopener noreferrer"&gt;ecsact-dev/ecsact_unity&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Command line tool for building the Ecsact runtime - &lt;a href="https://github.com/ecsact-dev/ecsact_rtb" rel="noopener noreferrer"&gt;ecsact-dev/ecsact_rtb&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Ecsact vscode plugin - &lt;a href="https://github.com/ecsact-dev/ecsact_vscode" rel="noopener noreferrer"&gt;ecsact-dev/ecsact_vscode&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We’ve planned support for other engines such as Unreal and Godot and creating tools for debugging your Ecsact simulation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Extending Ecsact
&lt;/h3&gt;

&lt;p&gt;Besides contributing to the many repositories on the &lt;a href="https://github.com/ecsact-dev" rel="noopener noreferrer"&gt;ecsact-dev github org&lt;/a&gt; the main way to extend Ecsact is by creating a code generator plugin. The ecsact command line can accept plugins built with a very simple C interface. There are also C++ and rust wrappers for creating a plugin very easily.&lt;/p&gt;

&lt;h2&gt;
  
  
  Future of Ecsact
&lt;/h2&gt;

&lt;p&gt;Ecsact is under heavy development. We’re not at the 1.0 stable LTS version quite yet. If Ecsact seems like something you’re interested in or you’d like to weigh in your opinion on its future then we encourage you to interact with us on our Discord, follow our &lt;a href="https://github.com/ecsact-dev" rel="noopener noreferrer"&gt;GitHub org&lt;/a&gt;, and checkout our website &lt;a href="https://ecsact.dev" rel="noopener noreferrer"&gt;ecsact.dev&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We’re eager to hear from you and hope to see many projects adopt Ecsact in the future.&lt;/p&gt;

</description>
      <category>ecsact</category>
      <category>gamedev</category>
      <category>entity</category>
    </item>
  </channel>
</rss>
