# Entities / Netcode for Entities

## Introduction

The Status Effect Framework now supports Unity's [Entities](https://docs.unity3d.com/Manual/com.unity.entities.html) and [Netcode for Entities](https://docs.unity3d.com/Packages/com.unity.netcode@1.5/manual/index.html) packages. Similar to the [Netcode for GameObjects](netcode-for-gameobjects) support the system is [server authoritative](https://docs.unity.com/ugs/en-us/manual/cloud-code/manual/server-authority). No additional setup is needed between [Entities](https://docs.unity3d.com/Manual/com.unity.entities.html) and [Netcode for Entities](https://docs.unity3d.com/Packages/com.unity.netcode@1.5/manual/index.html), but most of the work that will need to be done for additional functionality will be with how to interact with [StatusVariables](../type-specifics/classes/statusvariable) and handle [Modules](../type-specifics/scriptable-objects/module).

{% hint style="info" %}
This section is a lot more in-depth than others. If you do not have at least a basic understanding of ECS I would recommend playing around with Unity samples and learning how that works before tacking this section.
{% endhint %}

## Getting Started

Baking your player or characters will only change slightly as the way [StatusVariables](../type-specifics/classes/statusvariable) are setup in [Entities](https://docs.unity3d.com/Manual/com.unity.entities.html) is a little bit different.

For everything that contains a [StatusVariable](../type-specifics/classes/statusvariable) you will need to implement the `IEntityStatus` interface on the class. Then in `OnBake()` append all of the [StatusVariables](../type-specifics/classes/statusvariable) to the baked Entity.

<pre class="language-csharp" data-overflow="wrap" data-full-width="true"><code class="lang-csharp"><strong>using StatusEffects.Entities;
</strong>using Unity.Entities;
using System;
using UnityEngine;
// Note that there is a UnityEngine.Hash128 
// which we do not want to use here.
using Hash128 = Unity.Entities.Hash128;

public class ExamplePlayerAuthoring : MonoBehaviour, IEntityStatus
{
    public Hash128 ComponentId => m_ComponentId;
    private Hash128 m_ComponentId = new Hash128(Guid.NewGuid().ToString("N"));

    public void OnBake(Entity entity, StatusManagerBaker baker)
    {
        baker.DependsOn(this);
        baker.AppendToBuffer(entity, new StatusFloats(ComponentId, StatusMaxHealth));
        baker.AppendToBuffer(entity, new StatusFloats(ComponentId, StatusSpeed));
        baker.AppendToBuffer(entity, new StatusInts(ComponentId, StatusCoinMultiplier));
        baker.AppendToBuffer(entity, new StatusBools(ComponentId, StatusStunned));
    }
    
    // Example variables
    public StatusFloat StatusMaxHealth = new StatusFloat(100, true);
    public StatusFloat StatusSpeed = new StatusFloat(5, true);
    public StatusInt StatusCoinMultiplier = new StatusInt(1, true);
    public StatusBool StatusStunned = new StatusBool(false);
}
</code></pre>

When baking using a [Baker](https://docs.unity3d.com/Packages/com.unity.entities@1.0/manual/baking-prefabs.html), directly convert the [StatusVariables](../type-specifics/classes/statusvariable). For example `StatusEffects.StatusFloat` will convert to `StatusEffects.Entities.StatusFloat`.

{% code overflow="wrap" fullWidth="true" %}
```csharp
using Unity.Entities;
using StatusEffects.Entities;

public struct ExamplePlayer : IComponentData
{
    // This is important to look up StatusVariable
    // data from the dynamic buffer.
    public Hash128 ComponentId;
    
    public StatusFloat MaxHealth;
    public StatusInt CoinMultiplier;
    public StatusBool Stunned;
}

public class ExamplePlayerBaker : Baker<ExamplePlayerAuthoring>
{
    public override void Bake(ExamplePlayerAuthoring authoring)
    {
        var entity = GetEntity(TransformUsageFlags.Dynamic);
        AddComponent(entity, new ExamplePlayer
        {
            ComponentId = authoring.ComponentId,
            MaxHealth = authoring.StatusMaxHealth,
            CoinMultiplier = authoring.StatusCoinMultiplier,
            Stunned = authoring.StatusStunned
        });
    }
}
```
{% endcode %}

That is all you need to do to setup functional [StatusVariables](../type-specifics/classes/statusvariable) for ECS. The reason there is a two part baking system is because of the way [StatusVariables](../type-specifics/classes/statusvariable) needed to be dynamically updated by ISystems.

Here is an example of how you can lookup those dynamic variables from within a job.

{% code overflow="wrap" fullWidth="true" %}
```csharp
partial struct DebugPlayerMaxHealthJob : IJobEntity
{
    [ReadOnly]
    public BufferLookup<StatusFloats> StatusFloatsLookup; // from SystemAPI.GetBufferLookup<StatusFloats>()

    public uint LastSystemVersion; // from state.LastSystemVersion

    public void Execute(Entity entity, in ExamplePlayer player)
    {
        var statusFloatBuffer = StatusFloatsLookup[entity];
        // This is a check to see if the StatusFloats buffer was changed 
        // post baking. Unless you are doing something that modifies this 
        // buffer you may not need to check this and can exclude it from 
        // the GetValue() call.
        bool structuralChange = StatusFloatsLookup.DidChange(parentEntity, LastSystemVersion);
        player.MaxHealth.GetValue(player.ComponentId, statusFloatBuffer, out var maxHealth, structuralChange);
        UnityEngine.Debug.Log($"Max Health: {maxHealth}");
    }
}
```
{% endcode %}

## Additional Info

Please checkout the pages for:

* [Adding and removing effects](entities-netcode-for-entities/adding-and-removing-effects)
* [Setting up modules](entities-netcode-for-entities/how-to-setup-modules)
* [Dynamically updating the Status Effect Database](entities-netcode-for-entities/dynamically-updating-the-status-effect-database)

Please also check out the Entities specific code in the sample for more examples on how to implement the Status Effect Framework in ECS.

Thats it! If you have other questions or find any bugs feel free to send me a message on Discord or add it to the issue tracker on GitHub.
