Chione::

System class

The System (behavior) class

Constants

DEFAULT_ASPECT_HASH

A Hash that auto-vivifies only its :default key

Attributes

aspect_entities R

The Hash of Sets of entity IDs which match the System’s aspects, keyed by aspect name.

world R

The World which the System belongs to

Public Class Methods

aspect( name, *required, all_of: nil, one_of: nil, none_of: nil )

Add the specified component_types to the Aspect of this System as being required in any entities it processes.

   # File lib/chione/system.rb
55 def self::aspect( name, *required, all_of: nil, one_of: nil, none_of: nil )
56     aspect = Chione::Aspect.new
57 
58     all_of = required + Array( all_of )
59 
60     aspect = aspect.with_all_of( all_of )
61     aspect = aspect.with_one_of( one_of )   if one_of
62     aspect = aspect.with_none_of( none_of ) if none_of
63 
64     self.aspects[ name ] = aspect
65 end
every_tick( &block )

Declare a block that is called once every tick for each entity that matches the given aspect.

    # File lib/chione/system.rb
 97 def self::every_tick( &block )
 98     return self.on( 'timing' ) do |event_name, payload|
 99         self.instance_exec( *payload, &block )
100     end
101 end
inherited( subclass )

Add some per-subclass data structures to inheriting +subclass+es.

    # File lib/chione/system.rb
105 def self::inherited( subclass )
106     super
107     subclass.instance_variable_set( :@aspects, DEFAULT_ASPECT_HASH.clone )
108     subclass.instance_variable_set( :@event_handlers, self.event_handlers&.dup || [] )
109     subclass.instance_variable_set( :@injected_systems, self.injected_systems&.dup || {} )
110 end
inject( *systems )

Dependency-injection: declare one or more systems that should be passed to #start by the running World.

   # File lib/chione/system.rb
70 def self::inject( *systems )
71     systems.each do |system_type|
72         system_type = system_type.to_sym
73         system_class = Chione::System.get_subclass( system_type )
74         attr_accessor( "#{system_type}_system" )
75         self.injected_systems[ system_type ] = system_class
76     end
77 end
new( world, * )

Create a new Chione::System for the specified world.

    # File lib/chione/system.rb
114 def initialize( world, * )
115     self.log.debug "Setting up %p" % [ self.class ]
116     @world  = world
117     @aspect_entities = self.class.aspects.each_with_object( {} ) do |(aspect_name, aspect), hash|
118         matching_set = world.entities_with( aspect )
119         self.log.debug "Initial Set with the %s aspect: %p" % [ aspect_name, matching_set]
120         hash[ aspect_name ] = matching_set
121     end
122 end
on( event_name, &block )

Declare a block that is called once whenever an event matching event_name is broadcast to the World.

   # File lib/chione/system.rb
82 def self::on( event_name, &block )
83     raise LocalJumpError, "no block given" unless block
84     raise ArgumentError, "callback has wrong arity" unless block.arity >= 2 || block.arity < 0
85 
86     method_name = "on_%s_event" % [ event_name.tr('/', '_') ]
87     self.log.debug "Making handler method #%s for %s events out of %p" %
88         [ method_name, event_name, block ]
89     define_method( method_name, &block )
90 
91     self.event_handlers << [ event_name, method_name ]
92 end

Public Instance Methods

aspects()

The Hash of Chione::Aspects that describe entities this system is interested in, keyed by name (a Symbol). A System which declares no aspects will have a :default Aspect which matches all entities.

   # File lib/chione/system.rb
41 singleton_attr_reader :aspects
entities( aspect_name=:default )

Return an Enumerator that yields the entities which match the given aspect_name.

    # File lib/chione/system.rb
167 def entities( aspect_name=:default )
168     return self.aspect_entities[ aspect_name ].to_enum( :each )
169 end
entity_components_updated( entity_id, components_hash )

Entity callback – called whenever an entity has a component added to it or removed from it. Calls the appropriate callback (#inserted or #removed) if the component change caused it to belong to or stop belonging to one of the system’s aspects.

    # File lib/chione/system.rb
176 def entity_components_updated( entity_id, components_hash )
177     self.class.aspects.each do |aspect_name, aspect|
178         entity_ids = self.aspect_entities[ aspect_name ]
179 
180         if aspect.matches?( components_hash )
181             self.inserted( aspect_name, entity_id, components_hash ) if
182                 entity_ids.add?( entity_id )
183         else
184             self.removed( aspect_name, entity_id, components_hash ) if
185                 entity_ids.delete?( entity_id )
186         end
187     end
188 end
event_handlers()

Event handler tuples (event name, callback) that should be registered when the System is started.

   # File lib/chione/system.rb
46 singleton_attr_reader :event_handlers
injected_systems()

Systems to be injected by the world when this System is started.

   # File lib/chione/system.rb
50 singleton_attr_reader :injected_systems
inserted( aspect_name, entity_id, components )

Entity callback – called whenever an entity has a component added to it that makes it start matching an aspect of the receiving System. The aspect_name is the name of the Aspect it now matches, and the components are a Hash of the entity’s components keyed by Class. By default this is a no-op.

    # File lib/chione/system.rb
196 def inserted( aspect_name, entity_id, components )
197     self.log.debug "Entity %s now matches the %s aspect." % [ entity_id, aspect_name ]
198 end
removed( aspect_name, entity_id, components )

Entity callback – called whenever an entity has a component removed from it that makes it stop matching an aspect of the receiving System. The aspect_name is the name of the Aspect it no longer matches, and the components are a Hash of the entity’s components keyed by Class. By default this is a no-op.

    # File lib/chione/system.rb
206 def removed( aspect_name, entity_id, components )
207     self.log.debug "Entity %s no longer matches the %s aspect." % [ entity_id, aspect_name ]
208 end
start( **injected_systems )

Start the system.

    # File lib/chione/system.rb
139 def start( **injected_systems )
140     self.log.info "Starting the %p system; %d injected systems, %d event handlers to register" %
141         [ self.class, injected_systems.length, self.class.event_handlers.length ]
142 
143     injected_systems.each do |name, other_system|
144         self.public_send( "#{name}_system=", other_system )
145     end
146 
147     self.class.event_handlers.each do |event_name, method_name|
148         callback = self.method( method_name )
149         self.log.info "Registering %p as a callback for '%s' events." % [ callback, event_name ]
150         self.world.subscribe( event_name, callback )
151     end
152 end
stop()

Stop the system.

    # File lib/chione/system.rb
156 def stop
157     self.log.info "Stopping the %p system" % [ self.class ]
158     self.class.event_handlers.each do |_, method_name|
159         callback = self.method( method_name )
160         self.log.info "Unregistering subscription for %p." % [ callback ]
161         self.world.unsubscribe( callback )
162     end
163 end

Protected Instance Methods

inspect_details()

Return the detail part of the inspection string.

    # File lib/chione/system.rb
216 def inspect_details
217     return "for %p:%#016x" % [ self.world.class, self.world.object_id * 2 ]
218 end