guerro323 / GameHost

MIT License
0 stars 0 forks source link

Introduce Relative Entities (GameWorld) #102

Open guerro323 opened 3 years ago

guerro323 commented 3 years ago

This feature will be for later once GameHost.V3 is half done.

Introduce Relative entities, which link an entity with another one based on a description. (eg: a character linked to a player) This feature shouldn't be hardcoded into GameWorld code. Entity Links should also be modified to work in the same way as Relative Entities (aka not be hard coded)

Example:

void CreateCharacter(GameEntity player)
{
    var character = GameWorld.CreateEntity(new[]
    {
        GameWorld.AsComponentType<CharacterLayout>()
    });

    GameWorld.SetRelative<PlayerDescription>(character, player);
}

public static class RelativeExtensions
{
    public static void SetRelative<T>(this GameWorld gameWorld, GameEntityHandle source, GameEntity owner)
    {
        var board = (Board) gameWorld.GetComponentBoard<Relative<T>>();
        board.AddComponent(source, owner);
    }
}

public struct Relative<T> : IComponentData
{
    public GameEntity Target;

    public class Board : GameWorld.ComponentBoard
    {
        private IComponentEventBoard targetListener;
        private bool isFromParent;

        protected override void OnCreate()
        {
            targetListener = (IComponentEventBoard) GameWorld.GetComponentBoard<Owned>();
            targetListener.OnRowsRemoved += (rowSpan, dataSpan, count) => 
            {
                for (var i = 0; i < count; i++)
                {
                    var buffer = dataSpan[i];
                    foreach (var element in buffer) 
                    {
                        isFromParent = true;
                        World.RemoveComponent(element.Source, ComponentType);
                        isFromParent = false;
                    }
                }
            };
        }

        public void AddComponent(GameEntityHandle handle, GameEntity target)
        {
            if (!World.Exists(target))
                throw new InvalidOperationException(nameof(target));

            base.CreateRow(handle);
        }

        protected override void RemoveRows(Span<uint> span)
        {
            if (isFromParent) 
            {
                base.RemoveRows(span);
                return;
            }

            foreach (var row in span) 
            {
                var data   = Read<GameEntity>(row);
                var buffer = GameWorld.GetBuffer(data, targetListener.ComponentType);
                for (var i = 0; i < buffer.Length; i++) 
                {
                    if (buffer[i] == Owner[row])
                    {
                        buffer.RemoveAt(i--);
                    }
                }

                if (buffer.Length == 0)
                    GameWorld.RemoveComponent(data, targetListener.ComponentType);
            }

            base.RemoveRows(span);
        }
    }

    public struct Owned : IComponentBuffer, IProvideCustomComponentBoard
    {
        public GameEntityHandle Source;

        public ComponentBoard Provide()
        {
            return new ComponentBufferEventBoard(Unsafe.SizeOf<Owned>());
        }
    }
}
guerro323 commented 3 years ago

Relative Entities are not yet introduced, but non-hardcoded Linked Entities got included in GameHost.Simulation.V3:

// Add LinkedEntity feature
world.AddLinkedEntityModule();

var a = world.CreateEntity();
var b = world.CreateEntity();

// Link B (child) to A (parent)
world.SetLink(b, a, true);

// Destroy A, which will destroy B
world.DestroyEntity(a);

The behavior is the same as the previous version

guerro323 commented 3 years ago

Done!

world.AddRelativeEntityModule();

ComponentType playerType = world.RegisterRelativeDescription("PlayerDescription");
world.AddRelative(playerType, projectile, player);
world.RemoveRelative(playerType, projectile);

if (world.TryGetRelative(playerType, projectile, out var player)) {}

Span<UEntityHandle> ownedRelatives = world.ReadOwnedRelatives(playerType, player);

Big difference between the old version of relative entities:

The terminology will need to be remade, so the issue will still be up