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
54 def self::aspect( name, *required, all_of: nil, one_of: nil, none_of: nil )
55     aspect = Chione::Aspect.new
56 
57     all_of = required + Array( all_of )
58 
59     aspect = aspect.with_all_of( all_of )
60     aspect = aspect.with_one_of( one_of )   if one_of
61     aspect = aspect.with_none_of( none_of ) if none_of
62 
63     self.aspects[ name ] = aspect
64 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
 96 def self::every_tick( &block )
 97     return self.on( 'timing' ) do |event_name, payload|
 98         self.instance_exec( *payload, &block )
 99     end
100 end
inherited( subclass )

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

    # File lib/chione/system.rb
104 def self::inherited( subclass )
105     super
106     subclass.instance_variable_set( :@aspects, DEFAULT_ASPECT_HASH.clone )
107     subclass.instance_variable_set( :@event_handlers, self.event_handlers&.dup || [] )
108     subclass.instance_variable_set( :@injected_systems, self.injected_systems&.dup || {} )
109 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
69 def self::inject( *systems )
70     systems.each do |system_type|
71         system_type = system_type.to_sym
72         system_class = Chione::System.get_subclass( system_type )
73         attr_accessor( "#{system_type}_system" )
74         self.injected_systems[ system_type ] = system_class
75     end
76 end
new( world, * )

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

    # File lib/chione/system.rb
113 def initialize( world, * )
114     self.log.debug "Setting up %p" % [ self.class ]
115     @world  = world
116     @aspect_entities = self.class.aspects.each_with_object( {} ) do |(aspect_name, aspect), hash|
117         matching_set = world.entities_with( aspect )
118         self.log.debug "Initial Set with the %s aspect: %p" % [ aspect_name, matching_set]
119         hash[ aspect_name ] = matching_set
120     end
121 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
81 def self::on( event_name, &block )
82     raise LocalJumpError, "no block given" unless block
83     raise ArgumentError, "callback has wrong arity" unless block.arity >= 2 || block.arity < 0
84 
85     method_name = "on_%s_event" % [ event_name.tr('/', '_') ]
86     self.log.debug "Making handler method #%s for %s events out of %p" %
87         [ method_name, event_name, block ]
88     define_method( method_name, &block )
89 
90     self.event_handlers << [ event_name, method_name ]
91 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
40 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
166 def entities( aspect_name=:default )
167     return self.aspect_entities[ aspect_name ].to_enum( :each )
168 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
175 def entity_components_updated( entity_id, components_hash )
176     self.class.aspects.each do |aspect_name, aspect|
177         entity_ids = self.aspect_entities[ aspect_name ]
178 
179         if aspect.matches?( components_hash )
180             self.inserted( aspect_name, entity_id, components_hash ) if
181                 entity_ids.add?( entity_id )
182         else
183             self.removed( aspect_name, entity_id, components_hash ) if
184                 entity_ids.delete?( entity_id )
185         end
186     end
187 end
event_handlers()

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

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

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

   # File lib/chione/system.rb
49 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
195 def inserted( aspect_name, entity_id, components )
196     self.log.debug "Entity %s now matches the %s aspect." % [ entity_id, aspect_name ]
197 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
205 def removed( aspect_name, entity_id, components )
206     self.log.debug "Entity %s no longer matches the %s aspect." % [ entity_id, aspect_name ]
207 end
start( **injected_systems )

Start the system.

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

Stop the system.

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

Protected Instance Methods

inspect_details()

Return the detail part of the inspection string.

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