generic
type Entity_Class (<>) is abstract tagged limited private;
type Entity_Access is access Entity_Class'Class;
with procedure Delete( e : in out Entity_Access );
-- This generic package is used to register an association of entity class
-- names and allocators. This allows us to instantiate an entity class simply
-- by name, without ever referencing its implementation in the code.
package Entity_Factory is
type Allocator is access function return Entity_Access;
-- Initializes the factory by name. The name should be the class of entities
-- that it manufactures. (ex: "item", "trigger", "player", etc). Classes
-- should be registered before the factory is initialized. Template
-- instances of each registered class are created at this time.
procedure Initialize( factoryName : String );
pragma Precondition( factoryName'Length > 0 );
procedure Finalize;
-- Returns null if no allocator is registered for the given id.
function Allocate( id : String ) return Entity_Access;
pragma Precondition( id'Length > 0 );
-- Iterate over the registered class id strings.
procedure Iterate_Classes( examine : access procedure( id : String ) );
-- Registers a class allocation function with an id.
procedure Register_Class( id : String; allocate : not null Allocator );
pragma Precondition( id'Length > 0 );
-- Returns a reference to a template instantiation of the class registered
-- with 'id'. Template entities are instantiated when the factory package is
-- initialized. If no class is registered for the id, null will be returned.
-- Do not modify the entity that is returned!
function Template( id : String ) return Entity_Access;
pragma Precondition( id'Length > 0 );
end Entity_Factory;