Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce Relative Entities (GameWorld) #102

Open
guerro323 opened this issue Aug 30, 2021 · 2 comments
Open

Introduce Relative Entities (GameWorld) #102

guerro323 opened this issue Aug 30, 2021 · 2 comments

Comments

@guerro323
Copy link
Owner

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
Copy link
Owner Author

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
Copy link
Owner Author

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:

  • Owned Relatives is automatic (no need to create a system that get followers)
  • Destroying an entity with followers will remove the relative component

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant