chione 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA256:
3
- metadata.gz: 414e1caef54ca7d5f41452376a2309e343bb52812f567012504628b5ec2347ff
4
- data.tar.gz: ca11c73c74c4e45c1373e54f224603f059b8eb0338e40b4a8e5cc676dc56c98f
2
+ SHA1:
3
+ metadata.gz: e97a13cf34e52ecdafa6435e9f8a6a055b0491d8
4
+ data.tar.gz: c166e2cf474f7eadd82c8974ce30cdab06961e2e
5
5
  SHA512:
6
- metadata.gz: 1a21bcb7a924fdeff7f3d1fd4effe157a642baf7ddbc56303cb966b83ad182e41c5b7ab9d9d000dfa7fc963ad36fd1cdab560bdcad2ae2da87a57789a0a8abf5
7
- data.tar.gz: 2ba9b26c5f7cbf5be5dd1d6b85857215861a4827e2454c67fd6d529154346921582568f1d47248d34bba8aef6af63bce2d860e2e8569009bc79e6afd6e77acf8
6
+ metadata.gz: f3d4d5d410fe1a8b41dd56f5ed5888d2e9a553c55a279857fb1759ce9e9b40c3e4b763aabaed899e04375b539b6143f1f526637d3db81e955a6f0d185c3b5644
7
+ data.tar.gz: de83ffeaefad492c73ca249f3af9ebfbb8d0371ec955a39c0f35938131be8fe95f4c140e3789404d88b147afb522ddcac1dcc19289c8c8ec404c5e71dcfdaa2e
Binary file
data.tar.gz.sig CHANGED
Binary file
data/ChangeLog CHANGED
@@ -1,8 +1,170 @@
1
+ 2017-05-26 Michael Granger <ged@FaerieMUD.org>
2
+
3
+ * Rakefile, chione.gemspec:
4
+ Update gemspec
5
+ [068af8eec0e0] [github/master, tip]
6
+
7
+ 2017-05-25 Michael Granger <ged@FaerieMUD.org>
8
+
9
+ * .hgignore, .ruby-version, Rakefile, chione.gemspec:
10
+ Update to latest Ruby.
11
+ [4dbb8e19b86c]
12
+
13
+ * .gems, lib/chione/world.rb, spec/chione/world_spec.rb:
14
+ Refactor the World for better subclassing
15
+
16
+ - Extract a method for creating blank Entities to facilitate
17
+ overriding which Entity class is used.
18
+ - Defer event processing until the event loop so events which are
19
+ published at startup aren't missed.
20
+ [a71b51f9f017]
21
+
22
+ * lib/chione/system.rb, spec/chione/system_spec.rb:
23
+ Allow shorthand required component list for system aspects
24
+ [4464660e20d0]
25
+
26
+ 2017-05-24 Michael Granger <ged@FaerieMUD.org>
27
+
28
+ * History.md, lib/chione.rb:
29
+ Bump the minor version.
30
+ [96d2395340ca]
31
+
32
+ * .gems, Rakefile, chione.gemspec, lib/chione/assemblage.rb,
33
+ lib/chione/component.rb, lib/chione/manager.rb,
34
+ lib/chione/system.rb, spec/chione/world_spec.rb:
35
+ Make Assemblage, Component, Manager and System all pluggable.
36
+ [7ef6fce14d50]
37
+
38
+ * lib/chione/system.rb, spec/chione/system_spec.rb:
39
+ Don't assume the process model of Systems
40
+ [b11a20a6e865]
41
+
42
+ 2017-05-22 Michael Granger <ged@FaerieMUD.org>
43
+
44
+ * .hgtags:
45
+ Added tag v0.1.0 for changeset 60f8ee90a031
46
+ [ba57ae8fc87c]
47
+
48
+ * .hgsigs:
49
+ Added signature for changeset d9f6a6089e01
50
+ [60f8ee90a031] [v0.1.0]
51
+
52
+ * History.md, lib/chione.rb:
53
+ Bump the minor version, update history.
54
+ [d9f6a6089e01]
55
+
56
+ * lib/chione/behaviors.rb, lib/chione/world.rb,
57
+ spec/chione/world_spec.rb:
58
+ Refactor a bit of the World start/stop logic
59
+
60
+ This makes it easier to override in implementations which have their
61
+ own process models.
62
+
63
+ This also stringifies the Manager or System in `manager/added` and
64
+ `system/added` events.
65
+ [3075fc1b71f7]
66
+
67
+ * lib/chione/component.rb, spec/chione/component_spec.rb:
68
+ Allow a component's default to be generated by a callable
69
+ [c72f6364c89a]
70
+
71
+ 2017-01-04 Michael Granger <ged@FaerieMUD.org>
72
+
73
+ * .hgtags:
74
+ Added tag v0.0.3 for changeset 80fff8665d92
75
+ [dd6453480c59]
76
+
77
+ * .hgsigs:
78
+ Added signature for changeset 7fac98a60c47
79
+ [80fff8665d92] [v0.0.3]
80
+
81
+ * History.md, lib/chione.rb:
82
+ Bump the patch version, update history.
83
+ [7fac98a60c47]
84
+
85
+ * .gems, .ruby-gemset, .ruby-version, .rvmrc, History.md,
86
+ History.rdoc, Manifest.txt, README.md, README.rdoc, Rakefile,
87
+ certs/ged.pem, chione.gemspec, lib/chione/component.rb,
88
+ lib/chione/world.rb:
89
+ Add a bunch of little updates
90
+
91
+ - Add a proper #inspect to Component
92
+ - Fix misnamed attr in World, update to latest Configurability syntax
93
+ - Update to version-manager-agnostic environment files
94
+ - Convert README and History to Markdown
95
+ - Update dependencies
96
+ - Update gem-signing cert
97
+ [e5a0f12057bb]
98
+
1
99
  2015-07-13 Michael Granger <ged@FaerieMUD.org>
2
100
 
101
+ * lib/chione/assemblage.rb, lib/chione/mixins.rb, lib/chione/world.rb:
102
+ Fix some documentation typos.
103
+ [9a01e0471b50]
104
+
105
+ * .hgtags:
106
+ Added tag v0.0.2 for changeset ee5d26409b8d
107
+ [bd7605922424]
108
+
109
+ * .hgsigs:
110
+ Added signature for changeset 1a4caa248cf7
111
+ [ee5d26409b8d] [v0.0.2]
112
+
113
+ * History.rdoc, lib/chione.rb:
114
+ Bump the patch version, update history.
115
+ [1a4caa248cf7]
116
+
117
+ * README.rdoc, Rakefile, chione.gemspec:
118
+ Fix a couple of build problems.
119
+ [31319f6c6df1]
120
+
121
+ * .hgtags:
122
+ Added tag v0.0.1 for changeset 79260690f4a7
123
+ [0c3b149df34c]
124
+
125
+ * .hgsigs:
126
+ Added signature for changeset 2cf024eb42d5
127
+ [79260690f4a7] [v0.0.1]
128
+
129
+ * History.md, History.rdoc, Manifest.txt, README.md, README.rdoc,
130
+ Rakefile, chione.gemspec:
131
+ Switch README and History back to RDoc
132
+
133
+ Markdown is still a little funky under Hoe.
134
+ [2cf024eb42d5]
135
+
136
+ * cert/ged.pem, certs/ged.pem:
137
+ Fix the name of the certs directory
138
+ [ed11a49519fc]
139
+
140
+ * Manifest.txt, lib/chione/system.rb, lib/chione/world.rb,
141
+ spec/chione/mixins_spec.rb, spec/chione/world_spec.rb:
142
+ Catch specs up to current code, fix a few little issues.
143
+
144
+ - Make World use class-level config instead of instance-level
145
+ - Add World#has_entity?
146
+ [1f44064f9807]
147
+
148
+ * README.md:
149
+ Reformat README for Hoe; add Gitter.im badge.
150
+
151
+ Closes ged/chione#1.
152
+ [8b96713eb85f]
153
+
154
+ * lib/chione/entity.rb, spec/chione/entity_spec.rb:
155
+ Change Entity#get_component to take a list, ala `one_of` Aspects.
156
+
157
+ COMPAT: This also removes the heretofore unused/untested
158
+ `raise_if_missing` setting.
159
+ [d071accf5605]
160
+
161
+ * Manifest.txt:
162
+ Add missing behaviors file to the Manifest
163
+ [c874155aa149]
164
+
3
165
  * lib/chione/behaviors.rb:
4
166
  Add a shared-behaviors collection
5
- [5ac263b85052] [github/master, tip]
167
+ [5ac263b85052]
6
168
 
7
169
  * lib/chione/world.rb, spec/chione/world_spec.rb:
8
170
  Add support for more than one GameWorld callback per event pattern
data/History.md CHANGED
@@ -1,3 +1,16 @@
1
+ ## v0.2.0 [2017-05-26] Michael Granger <ged@FaerieMUD.org>
2
+
3
+ Enhancements:
4
+
5
+ - Make Assemblage, Component, Manager and System all pluggable.
6
+ - Don't assume the process model of Systems
7
+ - Extract a method for creating blank Entities to facilitate
8
+ overriding which Entity class is used.
9
+ - Defer event processing until the event loop so events which are
10
+ published at startup aren't missed.
11
+ - Allow shorthand required component list for system aspects
12
+
13
+
1
14
  ## v0.1.0 [2017-05-22] Michael Granger <ged@FaerieMUD.org>
2
15
 
3
16
  Enhancements:
data/Rakefile CHANGED
@@ -33,11 +33,13 @@ hoespec = Hoe.spec 'chione' do |spec|
33
33
 
34
34
  spec.dependency 'loggability', '~> 0.12'
35
35
  spec.dependency 'configurability', '~> 3.0'
36
+ spec.dependency 'pluggability', '~> 0.4'
36
37
  spec.dependency 'uuid', '~> 2.3'
37
38
 
38
- spec.dependency 'hoe-deveiate', '~> 0.8', :developer
39
+ spec.dependency 'hoe-deveiate', '~> 1.0', :developer
39
40
  spec.dependency 'simplecov', '~> 0.12', :developer
40
- spec.dependency 'rdoc-generator-fivefish', '~> 0.1', :developer
41
+ spec.dependency 'rdoc-generator-fivefish', '~> 0.3', :developer
42
+ spec.dependency 'rdoc', '~> 5.1', :developer
41
43
 
42
44
  spec.require_ruby_version( '>=2.3.3' )
43
45
  spec.hg_sign_tags = true if spec.respond_to?( :hg_sign_tags= )
@@ -73,9 +75,9 @@ if File.directory?( '.hg' )
73
75
 
74
76
  Rake::Task[ 'docs' ].clear
75
77
  RDoc::Task.new( 'docs' ) do |rdoc|
76
- rdoc.main = "README.rdoc"
78
+ rdoc.main = "README.md"
77
79
  rdoc.markup = 'markdown'
78
- rdoc.rdoc_files.include( "*.rdoc", "ChangeLog", "lib/**/*.rb" )
80
+ rdoc.rdoc_files.include( "*.md", "ChangeLog", "lib/**/*.rb" )
79
81
  rdoc.generator = :fivefish
80
82
  rdoc.title = 'Chione'
81
83
  rdoc.rdoc_dir = 'doc'
@@ -86,6 +88,7 @@ end
86
88
  task :gemspec => GEMSPEC
87
89
  file GEMSPEC => __FILE__
88
90
  task GEMSPEC do |task|
91
+ Rake.application.trace "Updating gemspec"
89
92
  spec = $hoespec.spec
90
93
  spec.files.delete( '.gemtest' )
91
94
  spec.signing_key = nil
@@ -13,7 +13,7 @@ module Chione
13
13
 
14
14
 
15
15
  # Gem version
16
- VERSION = '0.1.0'
16
+ VERSION = '0.2.0'
17
17
 
18
18
 
19
19
  require 'chione/mixins'
@@ -1,6 +1,7 @@
1
1
  # -*- ruby -*-
2
2
  #encoding: utf-8
3
3
 
4
+ require 'pluggability'
4
5
  require 'loggability'
5
6
 
6
7
  require 'chione' unless defined?( Chione )
@@ -8,11 +9,15 @@ require 'chione' unless defined?( Chione )
8
9
 
9
10
  # An Assemblage mixin for defining factories for common entity configurations.
10
11
  module Chione::Assemblage
11
- extend Loggability
12
+ extend Loggability,
13
+ Pluggability
12
14
 
13
15
  # Loggability API -- log to the chione logger
14
16
  log_to :chione
15
17
 
18
+ # Pluggability API -- load subclasses from the 'chione/assemblage' directory
19
+ plugin_prefixes 'chione/assemblage'
20
+
16
21
 
17
22
  ### Extension callback -- add assemblage functionality to an extended +object+.
18
23
  def self::extended( object )
@@ -2,6 +2,7 @@
2
2
  #encoding: utf-8
3
3
 
4
4
  require 'loggability'
5
+ require 'pluggability'
5
6
 
6
7
  require 'chione' unless defined?( Chione )
7
8
  require 'chione/mixins'
@@ -10,11 +11,14 @@ require 'chione/mixins'
10
11
  # The Component (data) class
11
12
  class Chione::Component
12
13
  extend Loggability,
14
+ Pluggability,
13
15
  Chione::MethodUtilities
14
16
 
15
17
  # Loggability API -- log to the 'chione' logger
16
18
  log_to :chione
17
19
 
20
+ # Pluggability API -- load subclasses from the 'chione/component' directory
21
+ plugin_prefixes 'chione/component'
18
22
 
19
23
  ##
20
24
  # The Hash of fields implemented by the component
@@ -1,6 +1,7 @@
1
1
  # -*- ruby -*-
2
2
  #encoding: utf-8
3
3
 
4
+ require 'pluggability'
4
5
  require 'loggability'
5
6
 
6
7
  require 'chione' unless defined?( Chione )
@@ -8,11 +9,15 @@ require 'chione' unless defined?( Chione )
8
9
 
9
10
  # The Manager class
10
11
  class Chione::Manager
11
- extend Loggability
12
+ extend Loggability,
13
+ Pluggability
12
14
 
13
15
  # Loggability API -- send logs to the Chione logger
14
16
  log_to :chione
15
17
 
18
+ # Pluggability API -- load subclasses from the 'chione/manager' directory
19
+ plugin_prefixes 'chione/manager'
20
+
16
21
 
17
22
  ### Create a new Chione::Manager for the specified +world+.
18
23
  def initialize( world, * )
@@ -1,6 +1,7 @@
1
1
  # -*- ruby -*-
2
2
  #encoding: utf-8
3
3
 
4
+ require 'pluggability'
4
5
  require 'loggability'
5
6
 
6
7
  require 'chione' unless defined?( Chione )
@@ -11,18 +12,24 @@ require 'chione/aspect'
11
12
  # The System (behavior) class
12
13
  class Chione::System
13
14
  extend Loggability,
15
+ Pluggability,
14
16
  Chione::MethodUtilities
15
17
 
16
18
  # Loggability API -- send logs to the Chione logger
17
19
  log_to :chione
18
20
 
21
+ # Pluggability API -- load subclasses from the 'chione/system' directory
22
+ plugin_prefixes 'chione/system'
23
+
19
24
 
20
25
  ### Add the specified +component_types+ to the Aspect of this System as being
21
26
  ### required in any entities it processes.
22
- def self::aspect( all_of: nil, one_of: nil, none_of: nil )
27
+ def self::aspect( *required, all_of: nil, one_of: nil, none_of: nil )
23
28
  @aspect ||= Chione::Aspect.new
24
29
 
25
- @aspect = @aspect.with_all_of( all_of ) if all_of
30
+ all_of = required + Array( all_of )
31
+
32
+ @aspect = @aspect.with_all_of( all_of )
26
33
  @aspect = @aspect.with_one_of( one_of ) if one_of
27
34
  @aspect = @aspect.with_none_of( none_of ) if none_of
28
35
 
@@ -34,7 +41,6 @@ class Chione::System
34
41
  ### Create a new Chione::System for the specified +world+.
35
42
  def initialize( world, * )
36
43
  @world = world
37
- @thread = nil
38
44
  end
39
45
 
40
46
 
@@ -49,21 +55,12 @@ class Chione::System
49
55
  ### Start the system.
50
56
  def start
51
57
  self.log.info "Starting the %p" % [ self.class ]
52
- @thread = Thread.new( &self.method(:process_loop) )
53
58
  end
54
59
 
55
60
 
56
61
  ### Stop the system.
57
62
  def stop
58
- @thread.kill
59
63
  end
60
64
 
61
65
 
62
- ### The main loop of the system -- process entities that this system is
63
- ### interested in at an appropriate interval.
64
- def process_loop
65
- raise NotImplementedError, "%p does not implement required method #process_loop" %
66
- [ self.class ]
67
- end
68
-
69
66
  end # class Chione::System
@@ -45,6 +45,8 @@ class Chione::World
45
45
  @subscriptions = Hash.new do |h,k|
46
46
  h[ k ] = Set.new
47
47
  end
48
+ @defer_events = true
49
+ @deferred_events = []
48
50
 
49
51
  @main_thread = nil
50
52
  @world_threads = ThreadGroup.new
@@ -59,28 +61,45 @@ class Chione::World
59
61
  public
60
62
  ######
61
63
 
64
+ ##
62
65
  # The number of times the event loop has executed.
63
66
  attr_reader :timing_event_count
64
67
 
68
+ ##
65
69
  # The Hash of all Entities in the World, keyed by ID
66
70
  attr_reader :entities
67
71
 
72
+ ##
68
73
  # The Hash of all Systems currently in the World, keyed by class.
69
74
  attr_reader :systems
70
75
 
76
+ ##
71
77
  # The Hash of all Managers currently in the World, keyed by class.
72
78
  attr_reader :managers
73
79
 
80
+ ##
74
81
  # The ThreadGroup that contains all Threads managed by the World.
75
82
  attr_reader :world_threads
76
83
 
84
+ ##
77
85
  # The Thread object running the World's IO reactor loop
78
86
  attr_reader :main_thread
79
87
 
88
+ ##
80
89
  # The Hash of event subscription callbacks registered with the world, keyed by
81
90
  # event pattern.
82
91
  attr_reader :subscriptions
83
92
 
93
+ ##
94
+ # Whether or not to queue published events instead of sending them to
95
+ # subscribers immediately.
96
+ attr_predicate_accessor :defer_events
97
+
98
+ ##
99
+ # The queue of events that have not yet been sent to subscribers.
100
+ attr_reader :deferred_events
101
+ alias_method :deferring_events?, :defer_events?
102
+
84
103
 
85
104
  ### Start the world; returns the Thread in which the world is running.
86
105
  def start
@@ -190,7 +209,7 @@ class Chione::World
190
209
  raise ArgumentError, "callback has wrong arity" unless
191
210
  callback.arity >= 2 || callback.arity < 0
192
211
 
193
- @subscriptions[ event_name ].add( callback )
212
+ self.subscriptions[ event_name ].add( callback )
194
213
 
195
214
  return callback
196
215
  end
@@ -198,46 +217,86 @@ class Chione::World
198
217
 
199
218
  ### Unsubscribe from events that publish to the specified +callback+.
200
219
  def unsubscribe( callback )
201
- @subscriptions.values.each {|cbset| cbset.delete(callback) }
220
+ self.subscriptions.keys.each do |pattern|
221
+ cbset = self.subscriptions[ pattern ]
222
+ cbset.delete( callback )
223
+ self.subscriptions.delete( pattern ) if cbset.empty?
224
+ end
202
225
  end
203
226
 
204
227
 
205
- ### Publish an event with the specified +event_name+, calling any subscribers with
206
- ### the specified +payload+.
228
+ ### Publish an event with the specified +event_name+ and +payload+.
207
229
  def publish( event_name, *payload )
208
230
  # self.log.debug "Publishing a %p event: %p" % [ event_name, payload ]
209
- @subscriptions.each do |pattern, callbacks|
231
+ if self.defer_events?
232
+ self.deferred_events.push( [event_name, payload] )
233
+ else
234
+ self.call_subscription_callbacks( event_name, payload )
235
+ end
236
+ end
237
+
238
+
239
+ ### Send any deferred events to subscribers.
240
+ def publish_deferred_events
241
+ while event = self.deferred_events.shift
242
+ self.call_subscription_callbacks( *event )
243
+ end
244
+ end
245
+
246
+
247
+ ### Call the callbacks of any subscriptions matching the specified +event_name+ with
248
+ ### the given +payload+.
249
+ def call_subscription_callbacks( event_name, payload )
250
+ self.subscriptions.each do |pattern, callbacks|
210
251
  next unless File.fnmatch?( pattern, event_name, File::FNM_EXTGLOB|File::FNM_PATHNAME )
211
252
 
212
253
  callbacks.each do |callback|
213
- begin
214
- callback.call( event_name, payload )
215
- rescue => err
216
- self.log.error "%p while calling %p for a %p event: %s" %
217
- [ err.class, callback, event_name, err.message ]
218
- self.log.debug " %s" % [ err.backtrace.join("\n ") ]
219
- callbacks.delete( callback )
254
+ unless self.call_subscription_callback( callback, event_name, payload )
255
+ self.log.debug "Callback failed; removing it from the subscription."
256
+ self.unsubscribe( callback )
220
257
  end
221
258
  end
222
259
  end
223
260
  end
224
261
 
225
262
 
226
- ### Return a new Chione::Entity for the receiving World.
263
+ ### Call the specified +callback+ with the provided +event_name+ and +payload+, returning
264
+ ### +true+ if the callback executed without error.
265
+ def call_subscription_callback( callback, event_name, payload )
266
+ callback.call( event_name, payload )
267
+ return true
268
+ rescue => err
269
+ self.log.error "%p while calling %p for a %p event: %s" %
270
+ [ err.class, callback, event_name, err.message ]
271
+ self.log.debug " %s" % [ err.backtrace.join("\n ") ]
272
+ return false
273
+ end
274
+
275
+
276
+ ### Return a new Chione::Entity for the receiving World, using the optional
277
+ ### +assemblage+ to populate it with components if it's specified.
227
278
  def create_entity( assemblage=nil )
228
279
  entity = if assemblage
229
280
  assemblage.construct_for( self )
230
281
  else
231
- Chione::Entity.new( self )
282
+ self.create_blank_entity
232
283
  end
233
284
 
234
285
  @entities[ entity.id ] = entity
235
286
 
236
- self.publish( 'entity/created', entity )
287
+ self.publish( 'entity/created', entity.id )
237
288
  return entity
238
289
  end
239
290
 
240
291
 
292
+ ### Return a new Chione::Entity with no components for the receiving world.
293
+ ### Override this if you wish to use a class other than Chione::Entity for your
294
+ ### world.
295
+ def create_blank_entity
296
+ return Chione::Entity.new( self )
297
+ end
298
+
299
+
241
300
  ### Destroy the specified entity and remove it from any registered
242
301
  ### systems/managers.
243
302
  def destroy_entity( entity )
@@ -335,12 +394,14 @@ class Chione::World
335
394
  self.log.info "Starting timing loop."
336
395
  last_timing_event = Time.now
337
396
  interval = self.class.timing_event_interval
397
+ self.defer_events = false
338
398
  @timing_event_count = 0
339
399
 
340
400
  loop do
341
401
  previous_time, last_timing_event = last_timing_event, Time.now
342
402
 
343
403
  self.publish( 'timing', last_timing_event - previous_time, @timing_event_count )
404
+ self.publish_deferred_events
344
405
 
345
406
  @timing_event_count += 1
346
407
  remaining_time = interval - (Time.now - last_timing_event)
@@ -20,21 +20,17 @@ describe Chione::System do
20
20
  end
21
21
  end
22
22
 
23
+ let( :volition_component ) do
24
+ Class.new( Chione::Component ) do
25
+ field :verbs, default: []
26
+ end
27
+ end
28
+
23
29
 
24
30
  describe "a subclass" do
25
31
 
26
32
  let( :subclass ) do
27
- Class.new(described_class) do
28
- def initialize( * )
29
- super
30
- @processed = false
31
- end
32
- attr_reader :processed
33
-
34
- def process_loop
35
- @processed = true
36
- end
37
- end
33
+ Class.new(described_class)
38
34
  end
39
35
 
40
36
 
@@ -44,28 +40,23 @@ describe Chione::System do
44
40
 
45
41
 
46
42
  it "can declare components for its aspect" do
47
- subclass.aspect one_of: tags_component
43
+ subclass.aspect all_of: volition_component,
44
+ one_of: [ tags_component, location_component ]
48
45
 
49
46
  expect( subclass.aspect ).to_not be_empty
50
- expect( subclass.aspect.one_of ).to include( tags_component )
47
+ expect( subclass.aspect.all_of ).to include( volition_component )
48
+ expect( subclass.aspect.one_of ).to include( tags_component, location_component )
51
49
  end
52
50
 
53
51
 
54
- it "is required to implement #process_loop" do
55
- expect {
56
- Class.new( described_class ).new( :world ).process_loop
57
- }.to raise_error( NotImplementedError, /implement required method/i )
58
- end
59
-
52
+ it "can declare required components for its aspect via shorthand syntax" do
53
+ subclass.for_entities_that_have( volition_component )
60
54
 
61
- it "runs a Thread in its #process_loop when started" do
62
- system = subclass.new( :world )
63
- system_thread = system.start
64
- expect( system_thread ).to be_a( Thread )
65
- system_thread.join( 2 )
66
- expect( system.processed ).to be_truthy
55
+ expect( subclass.aspect ).to_not be_empty
56
+ expect( subclass.aspect.all_of ).to include( volition_component )
67
57
  end
68
58
 
59
+
69
60
  end
70
61
 
71
62
  end
@@ -24,22 +24,14 @@ describe Chione::World do
24
24
  @args = args
25
25
  @started = false
26
26
  @stopped = false
27
- @thread = nil
28
27
  end
29
- attr_reader :args, :started, :stopped, :thread
28
+ attr_reader :args, :started, :stopped
30
29
  def start
31
30
  @started = true
32
- super
33
31
  end
34
32
  def stop
35
- super
36
33
  @stopped = true
37
34
  end
38
- def process_loop
39
- loop do
40
- sleep 1
41
- end
42
- end
43
35
  end
44
36
  end
45
37
  let( :test_manager ) do
@@ -99,15 +91,6 @@ describe Chione::World do
99
91
  end
100
92
 
101
93
 
102
- it "joins on any Threads started by subsystems when stopping" do
103
- system = world.add_system( test_system )
104
- world.start
105
- sleep 0.1 until world.running?
106
- world.stop
107
- expect( system.thread ).to_not be_alive
108
- end
109
-
110
-
111
94
  describe "configuration" do
112
95
 
113
96
  it "is done via the Configurability API" do
@@ -127,11 +110,18 @@ describe Chione::World do
127
110
 
128
111
  describe "publish/subscribe" do
129
112
 
113
+
114
+ it "starts out with events deferred" do
115
+ expect( world ).to be_deferring_events
116
+ end
117
+
118
+
130
119
  it "allows subscription to events" do
131
120
  received = []
132
121
  world.subscribe( 'test/subscription' ) {|*args| received << args }
133
122
  expect {
134
123
  world.publish( 'test/subscription' )
124
+ world.publish_deferred_events
135
125
  }.to change { received.length }.by( 1 )
136
126
 
137
127
  expect( received ).to eq([ ['test/subscription', []] ])
@@ -144,6 +134,7 @@ describe Chione::World do
144
134
  world.subscribe( 'test/subscription' ) {|*args| received << 2 }
145
135
  expect {
146
136
  world.publish( 'test/subscription' )
137
+ world.publish_deferred_events
147
138
  }.to change { received.length }.by( 2 )
148
139
 
149
140
  expect( received ).to eq([ 1, 2 ])
@@ -155,6 +146,7 @@ describe Chione::World do
155
146
  expect {
156
147
  Loggability.with_level( :fatal ) do
157
148
  world.publish( 'test/subscription' )
149
+ world.publish_deferred_events
158
150
  end
159
151
  }.to change { world.subscriptions['test/subscription'].length }.by( -1 )
160
152
  expect( world.subscriptions['test/subscriptions'] ).to_not include( callback )
@@ -168,12 +160,20 @@ describe Chione::World do
168
160
 
169
161
  expect {
170
162
  world.publish( 'test/subscription' )
163
+ world.publish_deferred_events
171
164
  }.to_not change { received.length }
172
165
  end
173
166
 
174
167
 
175
168
  describe "with glob-style wildcard patterns" do
176
169
 
170
+ let( :world ) do
171
+ instance = super()
172
+ instance.defer_events = false
173
+ instance
174
+ end
175
+
176
+
177
177
  it "matches any one event segment with an asterisk" do
178
178
  received = []
179
179
 
@@ -229,6 +229,13 @@ describe Chione::World do
229
229
 
230
230
  describe "entities" do
231
231
 
232
+ let( :world ) do
233
+ instance = super()
234
+ instance.defer_events = false
235
+ instance
236
+ end
237
+
238
+
232
239
  it "can create entities" do
233
240
  expect( world.create_entity ).to be_a( Chione::Entity )
234
241
  end
@@ -262,7 +269,7 @@ describe Chione::World do
262
269
  world.subscribe( 'entity/created' ) {|*payload| event_payload = payload }
263
270
  entity = world.create_entity
264
271
 
265
- expect( event_payload ).to eq([ 'entity/created', [entity] ])
272
+ expect( event_payload ).to eq([ 'entity/created', [entity.id] ])
266
273
  end
267
274
 
268
275
 
@@ -289,6 +296,7 @@ describe Chione::World do
289
296
  world.subscribe( 'entity/destroyed' ) {|*payload| event_payload = payload }
290
297
  entity = world.create_entity
291
298
  world.destroy_entity( entity )
299
+ world.publish_deferred_events
292
300
 
293
301
  expect( event_payload ).to eq([ 'entity/destroyed', [entity] ])
294
302
  end
@@ -298,6 +306,13 @@ describe Chione::World do
298
306
 
299
307
  describe "components" do
300
308
 
309
+ let( :world ) do
310
+ instance = super()
311
+ instance.defer_events = false
312
+ instance
313
+ end
314
+
315
+
301
316
  let!( :entity1 ) do
302
317
  obj = world.create_entity
303
318
  obj.add_component( location_component.new )
@@ -360,6 +375,13 @@ describe Chione::World do
360
375
 
361
376
  describe "systems" do
362
377
 
378
+ let( :world ) do
379
+ instance = super()
380
+ instance.defer_events = false
381
+ instance
382
+ end
383
+
384
+
363
385
  it "can have Systems added to it" do
364
386
  system = world.add_system( test_system )
365
387
  expect( world.systems ).to include( test_system )
@@ -375,6 +397,7 @@ describe Chione::World do
375
397
 
376
398
  it "broadcasts a `system/added` event when a System is added" do
377
399
  event_payload = nil
400
+ world.defer_events = false
378
401
  world.subscribe( 'system/added' ) {|*payload| event_payload = payload }
379
402
 
380
403
  sys = world.add_system( test_system )
@@ -405,6 +428,13 @@ describe Chione::World do
405
428
 
406
429
  describe "managers" do
407
430
 
431
+ let( :world ) do
432
+ instance = super()
433
+ instance.defer_events = false
434
+ instance
435
+ end
436
+
437
+
408
438
  it "can register Managers" do
409
439
  manager = world.add_manager( test_manager )
410
440
  expect( world.managers ).to include( test_manager )
@@ -420,6 +450,7 @@ describe Chione::World do
420
450
 
421
451
  it "broadcasts a `manager/added` event when a Manager is added" do
422
452
  event_payload = nil
453
+ world.defer_events = false
423
454
  world.subscribe( 'manager/added' ) {|*payload| event_payload = payload }
424
455
 
425
456
  manager = world.add_manager( test_manager )
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chione
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Granger
@@ -35,7 +35,7 @@ cert_chain:
35
35
  w8aNA5re5+Rt/Vvjxj5AcEnZnZiz5x959NaddQocX32Z1unHw44pzRNUur1GInfW
36
36
  p4vpx2kUSFSAGjtCbDGTNV2AH8w9OU4xEmNz8c5lyoA=
37
37
  -----END CERTIFICATE-----
38
- date: 2017-05-22 00:00:00.000000000 Z
38
+ date: 2017-05-26 00:00:00.000000000 Z
39
39
  dependencies:
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: loggability
@@ -65,6 +65,20 @@ dependencies:
65
65
  - - "~>"
66
66
  - !ruby/object:Gem::Version
67
67
  version: '3.0'
68
+ - !ruby/object:Gem::Dependency
69
+ name: pluggability
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '0.4'
75
+ type: :runtime
76
+ prerelease: false
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '0.4'
68
82
  - !ruby/object:Gem::Dependency
69
83
  name: uuid
70
84
  requirement: !ruby/object:Gem::Requirement
@@ -141,28 +155,28 @@ dependencies:
141
155
  requirements:
142
156
  - - "~>"
143
157
  - !ruby/object:Gem::Version
144
- version: '0.1'
158
+ version: '0.3'
145
159
  type: :development
146
160
  prerelease: false
147
161
  version_requirements: !ruby/object:Gem::Requirement
148
162
  requirements:
149
163
  - - "~>"
150
164
  - !ruby/object:Gem::Version
151
- version: '0.1'
165
+ version: '0.3'
152
166
  - !ruby/object:Gem::Dependency
153
167
  name: rdoc
154
168
  requirement: !ruby/object:Gem::Requirement
155
169
  requirements:
156
170
  - - "~>"
157
171
  - !ruby/object:Gem::Version
158
- version: '4.0'
172
+ version: '5.1'
159
173
  type: :development
160
174
  prerelease: false
161
175
  version_requirements: !ruby/object:Gem::Requirement
162
176
  requirements:
163
177
  - - "~>"
164
178
  - !ruby/object:Gem::Version
165
- version: '4.0'
179
+ version: '5.1'
166
180
  - !ruby/object:Gem::Dependency
167
181
  name: hoe
168
182
  requirement: !ruby/object:Gem::Requirement
metadata.gz.sig CHANGED
Binary file