Skip to content
Outerminds edited this page Feb 9, 2019 · 12 revisions

Content


Description

A phase describes an execution 'time' that is executed as a block. This means that a phase must be completely executed before another can execute. Phases are executed through a controller using its Run<T> method. They are linked with system interfaces by schedulers.

A phase must:

  • be a struct
  • implement the IPhase empty interface

A phase should:

  • contain only public instance non-readonly fields (no methods, constructors, properties, events, etc.)
  • not have fields that stores an Entia type (such as a component, a system, a message, a queryable, an injectable, etc.)

Usage

using System;
using System.Collections.Generic;
using Entia;
using Entia.Core;
using Entia.Modules;
using Entia.Modules.Control;
using Entia.Modules.Schedule;
using Entia.Nodes;
using Entia.Phases;
using Entia.Schedulables;
using Entia.Systems;
using static Entia.Nodes.Node;

namespace Phases
{
    // This phase is meant to execute before the 'Run' phase.
    // 'IResolve' is a phase interface that signals that the world should be
    // resolved after executing the phase.
    public struct PreRun : IPhase, IResolve { }
}

namespace Systems
{
    // This interface will allow to define systems that will be called during the
    // 'PreRun' phase.
    // A default 'IScheduler' implementation must be linked using the 'T'
    // in the 'ISchedulable<T>' interface.
    public interface IPreRun : ISchedulable<Schedulers.PreRun>
    {
        void PreRun();
    }
}

namespace Schedulers
{
    // 'Scheduler<T>' is an 'IScheduler' that automatically casts the
    // instance to the provided type 'T'
    public sealed class PreRun : Entia.Schedulers.Scheduler<Systems.IPreRun>
    {
        // Declare which phase types the schedule will schedule.
        public override Type[] Phases => new[] { typeof(Phases.PreRun) };

        public override Phase[] Schedule(
            Systems.IPreRun instance,
            Controller controller)
        {
            // Here is where the phase is linked with the system interface.
            var phase = Phase.From<Phases.PreRun>(instance.PreRun);
            // A scheduler may register a system interface to multiple phases.
            return new[] { phase };
        }
    }
}

namespace Resources
{
    public struct Game : IResource { public bool Quit; }
}

public static class Game
{
    public static readonly Node Node = Sequence();

    public static void Run()
    {
        var world = new World();
        var controllers = world.Controllers();
        var resources = world.Resources();

        if (controllers.Control(Node).TryValue(out var controller))
        {
            ref var game = ref resources.Get<Resources.Game>();

            // This is the typical execution routine.
            controller.Run<Initialize>();
            controller.Run<React.Initialize>();

            while (!game.Quit)
            {
                // The custom phase is inserted here.
                controller.Run<Phases.PreRun>();
                controller.Run<Run>();
            }

            controller.Run<React.Dispose>();
            controller.Run<Dispose>();
        }
    }
}

Related