chione 0.3.0 → 0.4.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 +5 -5
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/ChangeLog +16 -2
- data/History.md +31 -0
- data/Manifest.txt +4 -0
- data/README.md +18 -11
- data/Rakefile +2 -0
- data/lib/chione.rb +7 -4
- data/lib/chione/archetype.rb +49 -3
- data/lib/chione/aspect.rb +52 -10
- data/lib/chione/component.rb +43 -8
- data/lib/chione/entity.rb +38 -28
- data/lib/chione/fixtures.rb +18 -0
- data/lib/chione/fixtures/entities.rb +32 -0
- data/lib/chione/iterating_system.rb +35 -0
- data/lib/chione/manager.rb +15 -0
- data/lib/chione/mixins.rb +22 -0
- data/lib/chione/system.rb +137 -12
- data/lib/chione/world.rb +155 -38
- data/spec/chione/archetype_spec.rb +14 -0
- data/spec/chione/aspect_spec.rb +90 -0
- data/spec/chione/component_spec.rb +37 -0
- data/spec/chione/entity_spec.rb +17 -24
- data/spec/chione/iterating_system_spec.rb +135 -0
- data/spec/chione/system_spec.rb +224 -27
- data/spec/chione/world_spec.rb +122 -59
- data/spec/spec_helper.rb +3 -0
- metadata +46 -14
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: ef14891907c37d8047d88177ab303208f073f8e0e33e940cbf56989a1e45e3ac
|
4
|
+
data.tar.gz: 35eaace97f89719cd01ba69fa437baed47bdfc8bcb84f918ba4c7e0ce08c512e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a2d8877f54851147ce6760c041e302fce3e1e1a55b6d64eaa0122c173b13b61b188d47d3bac630438bac81d25bf5b32b26d9b206ee6129b4513e459564183309
|
7
|
+
data.tar.gz: b085ac2e31c52eeeaee5f9776a1049ba6172c1d05927ea72b8229f8476c080a93cc732e9ab17c12cabc940630a056908c5a48277cb89785e44bf816b31245867
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/ChangeLog
CHANGED
@@ -1,8 +1,22 @@
|
|
1
|
+
2017-06-06 Michael Granger <ged@FaerieMUD.org>
|
2
|
+
|
3
|
+
* lib/chione/aspect.rb, lib/chione/component.rb, lib/chione/entity.rb,
|
4
|
+
lib/chione/manager.rb, lib/chione/mixins.rb, lib/chione/system.rb:
|
5
|
+
Pull up common #inspect functionality into a mixin
|
6
|
+
|
7
|
+
...and use it everywhere.
|
8
|
+
[0eb1e6c25953] [tip]
|
9
|
+
|
10
|
+
* lib/chione/world.rb, spec/chione/world_spec.rb:
|
11
|
+
Added World#remove_system and _manager; publish the instance of
|
12
|
+
/added and /removed events
|
13
|
+
[426735589cee]
|
14
|
+
|
1
15
|
2017-05-31 Michael Granger <ged@FaerieMUD.org>
|
2
16
|
|
3
17
|
* .hgtags:
|
4
18
|
Added tag v0.3.0 for changeset c91f71b3d7d9
|
5
|
-
[06fdcde9eb00] [
|
19
|
+
[06fdcde9eb00] [github/master]
|
6
20
|
|
7
21
|
* .hgsigs:
|
8
22
|
Added signature for changeset 0d453cae95c3
|
@@ -19,7 +33,7 @@
|
|
19
33
|
* lib/chione.rb, lib/chione/archetype.rb, lib/chione/assemblage.rb,
|
20
34
|
spec/chione/archetype_spec.rb:
|
21
35
|
Add more backward-compat for Chione::Assemblage
|
22
|
-
[a2e8b35fb950]
|
36
|
+
[a2e8b35fb950]
|
23
37
|
|
24
38
|
* .gems, Manifest.txt, Rakefile, chione.gemspec, lib/chione.rb,
|
25
39
|
lib/chione/archetype.rb, lib/chione/assemblage.rb,
|
data/History.md
CHANGED
@@ -1,3 +1,34 @@
|
|
1
|
+
## v0.4.0 [2017-12-11] Michael Granger <ged@FaerieMUD.org>
|
2
|
+
|
3
|
+
Enhancements:
|
4
|
+
|
5
|
+
- Add caching and #inserted/#removed callbacks for aspect-membership to Systems.
|
6
|
+
- Add Aspect#archetype and Archetype.from_aspect
|
7
|
+
- Add Aspect#matches? to match individual entities
|
8
|
+
- Add fixtures collection
|
9
|
+
- Normalize entity IDs in the World API
|
10
|
+
- Add constructor arguments to component-creation paths
|
11
|
+
- Add the entity ID to Component's inspect output
|
12
|
+
- Add Chione::IteratingSystem
|
13
|
+
- Entities are thinner and systems make better use of named aspects
|
14
|
+
- Added World#remove_system and _manager; publish the instance of /added and /removed events
|
15
|
+
- Pull up common #inspect functionality into a mixin and use it everywhere.
|
16
|
+
|
17
|
+
Changes:
|
18
|
+
|
19
|
+
- The `every_tick` callback is now only passed the delta and the tick count
|
20
|
+
- Init arguments are passed through to Component.add_component
|
21
|
+
- Add a processing block to Component field declaration
|
22
|
+
- Rename some component-API methods on the World for clarity (with aliases to the old methods)
|
23
|
+
- Add the entity ID to components on registration
|
24
|
+
- Event handler declarations no longer include an aspect.
|
25
|
+
|
26
|
+
Bugfixes:
|
27
|
+
|
28
|
+
- Fix API docs for Chione::System::on
|
29
|
+
|
30
|
+
|
31
|
+
|
1
32
|
## v0.3.0 [2017-05-31] Michael Granger <ged@FaerieMUD.org>
|
2
33
|
|
3
34
|
Changes:
|
data/Manifest.txt
CHANGED
@@ -12,6 +12,9 @@ lib/chione/assemblage.rb
|
|
12
12
|
lib/chione/behaviors.rb
|
13
13
|
lib/chione/component.rb
|
14
14
|
lib/chione/entity.rb
|
15
|
+
lib/chione/fixtures.rb
|
16
|
+
lib/chione/fixtures/entities.rb
|
17
|
+
lib/chione/iterating_system.rb
|
15
18
|
lib/chione/manager.rb
|
16
19
|
lib/chione/mixins.rb
|
17
20
|
lib/chione/system.rb
|
@@ -20,6 +23,7 @@ spec/chione/archetype_spec.rb
|
|
20
23
|
spec/chione/aspect_spec.rb
|
21
24
|
spec/chione/component_spec.rb
|
22
25
|
spec/chione/entity_spec.rb
|
26
|
+
spec/chione/iterating_system_spec.rb
|
23
27
|
spec/chione/manager_spec.rb
|
24
28
|
spec/chione/mixins_spec.rb
|
25
29
|
spec/chione/system_spec.rb
|
data/README.md
CHANGED
@@ -40,24 +40,28 @@ for making it better via email or whatever.
|
|
40
40
|
|
41
41
|
Articles/posts on ECS:
|
42
42
|
|
43
|
-
* http://gameprogrammingpatterns.com/component.html
|
44
|
-
* http://t-machine.org/index.php/2007/09/03/entity-systems-are-the-future-of-mmog-development-part-1
|
45
|
-
* http://www.richardlord.net/blog/what-is-an-entity-framework
|
46
|
-
* http://www.richardlord.net/blog/why-use-an-entity-framework
|
47
|
-
* http://cowboyprogramming.com/2007/01/05/evolve-your-heirachy
|
43
|
+
* <http://gameprogrammingpatterns.com/component.html>
|
44
|
+
* <http://t-machine.org/index.php/2007/09/03/entity-systems-are-the-future-of-mmog-development-part-1/>
|
45
|
+
* <http://www.richardlord.net/blog/what-is-an-entity-framework>
|
46
|
+
* <http://www.richardlord.net/blog/why-use-an-entity-framework>
|
47
|
+
* <http://cowboyprogramming.com/2007/01/05/evolve-your-heirachy/>
|
48
48
|
|
49
49
|
Other ECS Frameworks:
|
50
50
|
|
51
|
-
* https://github.com/junkdog/artemis-odb (Java)
|
52
|
-
*
|
53
|
-
*
|
54
|
-
|
51
|
+
* <https://github.com/junkdog/artemis-odb> (Java)
|
52
|
+
* <http://www.richardlord.net/ash/> (ActionScript)
|
53
|
+
* <https://github.com/libgdx/ashley> (Java)
|
54
|
+
* <https://github.com/astrosilverio/braga> (Python)
|
55
|
+
* <https://github.com/seanfisk/ecs> (Python)
|
56
|
+
* <https://github.com/tdavies/Ember2> (ActionScript)
|
57
|
+
* <https://github.com/cpowell/ruby-entity-component-framework> (JRuby)
|
58
|
+
* <https://github.com/alecmce/xember> (ActionScript)
|
55
59
|
|
56
60
|
## Contributing
|
57
61
|
|
58
62
|
You can check out the current development source with Mercurial via its
|
59
|
-
|
60
|
-
|
63
|
+
[project page][bitbucket]. Or if you prefer Git, via
|
64
|
+
[its Github mirror][github].
|
61
65
|
|
62
66
|
After checking out the source, run:
|
63
67
|
|
@@ -98,3 +102,6 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
98
102
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
99
103
|
|
100
104
|
|
105
|
+
[bitbucket]: http://bitbucket.org/ged/chione
|
106
|
+
[github]: https://github.com/ged/chione
|
107
|
+
|
data/Rakefile
CHANGED
@@ -36,6 +36,8 @@ hoespec = Hoe.spec 'chione' do |spec|
|
|
36
36
|
spec.dependency 'pluggability', '~> 0.4'
|
37
37
|
spec.dependency 'uuid', '~> 2.3'
|
38
38
|
spec.dependency 'deprecatable', '~> 1.0'
|
39
|
+
spec.dependency 'fluent_fixtures', '~> 0.6'
|
40
|
+
spec.dependency 'faker', '~> 1.8'
|
39
41
|
|
40
42
|
spec.dependency 'hoe-deveiate', '~> 1.0', :developer
|
41
43
|
spec.dependency 'simplecov', '~> 0.12', :developer
|
data/lib/chione.rb
CHANGED
@@ -12,7 +12,7 @@ module Chione
|
|
12
12
|
extend Loggability
|
13
13
|
|
14
14
|
# Gem version
|
15
|
-
VERSION = '0.
|
15
|
+
VERSION = '0.4.0'
|
16
16
|
|
17
17
|
|
18
18
|
# Loggability API -- set up a log host
|
@@ -26,9 +26,12 @@ module Chione
|
|
26
26
|
autoload :Component, 'chione/component'
|
27
27
|
autoload :Entity, 'chione/entity'
|
28
28
|
autoload :Manager, 'chione/manager'
|
29
|
-
autoload :System, 'chione/system'
|
30
29
|
autoload :World, 'chione/world'
|
31
30
|
|
31
|
+
autoload :System, 'chione/system'
|
32
|
+
autoload :IteratingSystem, 'chione/iterating_system'
|
33
|
+
|
34
|
+
|
32
35
|
##
|
33
36
|
# The global UUID object for generating new UUIDs
|
34
37
|
class << self; attr_reader :uuid ; end
|
@@ -36,9 +39,9 @@ module Chione
|
|
36
39
|
|
37
40
|
|
38
41
|
### Coerce the specified +object+ into a Chione::Component and return it.
|
39
|
-
def self::Component( object )
|
42
|
+
def self::Component( object, init_values={} )
|
40
43
|
return object if object.is_a?( Chione::Component )
|
41
|
-
return Chione::Component.create( object ) if
|
44
|
+
return Chione::Component.create( object, init_values ) if
|
42
45
|
object.is_a?( Class ) || object.is_a?( String ) || object.is_a?( Symbol )
|
43
46
|
raise TypeError, "can't convert %p into Chione::Component" % [ object.class ]
|
44
47
|
end
|
data/lib/chione/archetype.rb
CHANGED
@@ -5,6 +5,7 @@ require 'pluggability'
|
|
5
5
|
require 'loggability'
|
6
6
|
|
7
7
|
require 'chione' unless defined?( Chione )
|
8
|
+
require 'chione/mixins'
|
8
9
|
|
9
10
|
|
10
11
|
# An Archetype mixin for defining factories for common entity configurations.
|
@@ -21,10 +22,29 @@ module Chione::Archetype
|
|
21
22
|
|
22
23
|
### Extension callback -- add archetype functionality to an extended +object+.
|
23
24
|
def self::extended( object )
|
24
|
-
super
|
25
25
|
object.extend( Loggability )
|
26
|
+
# object.extend( Chione::Inspection )
|
27
|
+
object.extend( Chione::MethodUtilities )
|
28
|
+
|
29
|
+
super
|
30
|
+
|
26
31
|
object.log_to( :chione )
|
27
32
|
object.components ||= {}
|
33
|
+
object.singleton_attr_accessor :from_aspect
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
### Create an anonymous Archetype Module that will create entities which match
|
38
|
+
### the specified +aspect+ (Chione::Aspect).
|
39
|
+
def self::from_aspect( aspect )
|
40
|
+
mod = Module.new
|
41
|
+
mod.extend( self )
|
42
|
+
mod.from_aspect = aspect
|
43
|
+
|
44
|
+
aspect.all_of.each( &mod.method(:add) )
|
45
|
+
mod.add( aspect.one_of.first ) unless aspect.one_of.empty?
|
46
|
+
|
47
|
+
return mod
|
28
48
|
end
|
29
49
|
|
30
50
|
|
@@ -57,15 +77,41 @@ module Chione::Archetype
|
|
57
77
|
### Construct a new entity for the specified +world+ with all of the archetype's
|
58
78
|
### components.
|
59
79
|
def construct_for( world )
|
60
|
-
entity = world.
|
80
|
+
entity = world.create_blank_entity
|
61
81
|
self.components.each do |component_type, args|
|
62
82
|
component = component_type.new( *args )
|
63
|
-
|
83
|
+
world.add_component_to( entity, component )
|
64
84
|
end
|
65
85
|
|
66
86
|
return entity
|
67
87
|
end
|
68
88
|
|
89
|
+
|
90
|
+
### Return a human-readable representation of the object suitable for debugging.
|
91
|
+
def inspect
|
92
|
+
return "#<%p:%#016x %s>" % [
|
93
|
+
self.class,
|
94
|
+
self.object_id * 2,
|
95
|
+
self.inspect_details,
|
96
|
+
]
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
#########
|
101
|
+
protected
|
102
|
+
#########
|
103
|
+
|
104
|
+
### Provide details about the Archetype for #inspect output.
|
105
|
+
def inspect_details
|
106
|
+
if self.from_aspect
|
107
|
+
return "Chione::Archetype from %p" % [ self.from_aspect ]
|
108
|
+
else
|
109
|
+
return "Chione::Archetype for creating entities with %s" %
|
110
|
+
[ self.components.keys.map( &:name ).join(', ') ]
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
|
69
115
|
end # module Chione::Archetype
|
70
116
|
|
71
117
|
|
data/lib/chione/aspect.rb
CHANGED
@@ -5,13 +5,15 @@ require 'set'
|
|
5
5
|
require 'loggability'
|
6
6
|
|
7
7
|
require 'chione' unless defined?( Chione )
|
8
|
+
require 'chione/mixins'
|
9
|
+
require 'chione/archetype'
|
8
10
|
|
9
11
|
|
10
12
|
# An expression of component-matching criteria used to find entities that should be
|
11
13
|
# processed by a System.
|
12
14
|
class Chione::Aspect
|
13
15
|
extend Loggability
|
14
|
-
|
16
|
+
include Chione::Inspection
|
15
17
|
|
16
18
|
# Loggability API -- log to the chione logger
|
17
19
|
log_to :chione
|
@@ -95,34 +97,74 @@ class Chione::Aspect
|
|
95
97
|
|
96
98
|
### Returns true if the receiver is an empty aspect, i.e., matches all entities.
|
97
99
|
def empty?
|
98
|
-
return
|
100
|
+
return self.one_of.empty? && self.all_of.empty? && self.none_of.empty?
|
101
|
+
end
|
102
|
+
|
103
|
+
|
104
|
+
### Returns +true+ if the components contained in the specified +component_hash+
|
105
|
+
### match the Aspect's specifications.
|
106
|
+
def matches?( component_hash )
|
107
|
+
return true if self.empty?
|
108
|
+
|
109
|
+
component_hash = component_hash.components if component_hash.respond_to?( :components )
|
110
|
+
|
111
|
+
return false unless self.one_of.empty? ||
|
112
|
+
self.one_of.any? {|component| component_hash.key?(component) }
|
113
|
+
return false unless self.none_of.none? {|component| component_hash.key?(component) }
|
114
|
+
return false unless self.all_of.all? {|component| component_hash.key?(component) }
|
115
|
+
|
116
|
+
return true
|
117
|
+
end
|
118
|
+
alias_method :match, :matches?
|
119
|
+
|
120
|
+
|
121
|
+
### Given an +entity_hash+ keyed by Component class, return the subset of
|
122
|
+
### values matching the receiving Aspect.
|
123
|
+
def matching_entities( entity_hash )
|
124
|
+
initial_set = if self.one_of.empty?
|
125
|
+
entity_hash.values
|
126
|
+
else
|
127
|
+
entity_hash.values_at( *self.one_of )
|
128
|
+
end
|
129
|
+
|
130
|
+
with_one = initial_set.reduce( :| ) || Set.new
|
131
|
+
with_all = entity_hash.values_at( *self.all_of ).reduce( with_one, :& )
|
132
|
+
without_any = entity_hash.values_at( *self.none_of ).reduce( with_all, :- )
|
133
|
+
|
134
|
+
return without_any
|
99
135
|
end
|
100
136
|
|
101
137
|
|
102
|
-
### Return
|
103
|
-
|
138
|
+
### Return an (anonymous) Chione::Archetype module that can be used to create
|
139
|
+
### entities that match it.
|
140
|
+
def archetype
|
141
|
+
return Chione::Archetype.from_aspect( self )
|
142
|
+
end
|
143
|
+
|
144
|
+
|
145
|
+
#########
|
146
|
+
protected
|
147
|
+
#########
|
148
|
+
|
149
|
+
### Return the detail part of the #inspect output.
|
150
|
+
def inspect_details
|
104
151
|
parts = []
|
105
152
|
parts << self.one_of_description
|
106
153
|
parts << self.all_of_description
|
107
154
|
parts << self.none_of_description
|
108
155
|
parts.compact!
|
109
156
|
|
110
|
-
str = "
|
157
|
+
str = "matching entities"
|
111
158
|
if parts.empty?
|
112
159
|
str << " with any components"
|
113
160
|
else
|
114
161
|
str << parts.join( ', ' )
|
115
162
|
end
|
116
|
-
str << ">"
|
117
163
|
|
118
164
|
return str
|
119
165
|
end
|
120
166
|
|
121
167
|
|
122
|
-
#########
|
123
|
-
protected
|
124
|
-
#########
|
125
|
-
|
126
168
|
### Return a String describing the components matching entities must have at
|
127
169
|
### least one of.
|
128
170
|
def one_of_description
|
data/lib/chione/component.rb
CHANGED
@@ -14,6 +14,9 @@ class Chione::Component
|
|
14
14
|
Pluggability,
|
15
15
|
Chione::MethodUtilities
|
16
16
|
|
17
|
+
include Chione::Inspection
|
18
|
+
|
19
|
+
|
17
20
|
# Loggability API -- log to the 'chione' logger
|
18
21
|
log_to :chione
|
19
22
|
|
@@ -26,16 +29,32 @@ class Chione::Component
|
|
26
29
|
|
27
30
|
|
28
31
|
### Declare a field for the component named +name+, with a default value of
|
29
|
-
### +default+.
|
30
|
-
|
32
|
+
### +default+. If the optional +process_block+ is provided, it will be called
|
33
|
+
### with the new value being assigned to the field before it is set, and the
|
34
|
+
### return value of it will be used instead.
|
35
|
+
def self::field( name, default: nil, &process_block )
|
31
36
|
self.fields ||= {}
|
32
37
|
self.fields[ name ] = default
|
33
|
-
|
38
|
+
|
39
|
+
define_method( "process_#{name}", &process_block ) if process_block
|
40
|
+
define_method( "#{name}=" ) do |new_val|
|
41
|
+
new_val = self.send( "process_#{name}", new_val ) if self.respond_to?( "process_#{name}" )
|
42
|
+
self.instance_variable_set( "@#{name}", new_val )
|
43
|
+
end
|
44
|
+
|
45
|
+
attr_reader( name )
|
34
46
|
end
|
35
47
|
|
36
48
|
|
37
49
|
### Create a new component with the specified +values+.
|
38
|
-
def initialize( values={} )
|
50
|
+
def initialize( entity_id=nil, values={} )
|
51
|
+
if entity_id.is_a?( Hash )
|
52
|
+
values = entity_id
|
53
|
+
entity_id = nil
|
54
|
+
end
|
55
|
+
|
56
|
+
@entity_id = entity_id
|
57
|
+
|
39
58
|
if self.class.fields
|
40
59
|
self.class.fields.each do |name, default|
|
41
60
|
self.method( "#{name}=" ).call( values[name] || default_value(default) )
|
@@ -44,10 +63,25 @@ class Chione::Component
|
|
44
63
|
end
|
45
64
|
|
46
65
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
66
|
+
######
|
67
|
+
public
|
68
|
+
######
|
69
|
+
|
70
|
+
##
|
71
|
+
# The ID of the entity the component belongs to
|
72
|
+
attr_accessor :entity_id
|
73
|
+
|
74
|
+
|
75
|
+
#########
|
76
|
+
protected
|
77
|
+
#########
|
78
|
+
|
79
|
+
### Return the detailed part of the Component's #inspect output.
|
80
|
+
def inspect_details
|
81
|
+
return "{%s} %s" % [
|
82
|
+
self.entity_id || "(unassigned)",
|
83
|
+
self.fields_description
|
84
|
+
]
|
51
85
|
end
|
52
86
|
|
53
87
|
|
@@ -63,6 +97,7 @@ class Chione::Component
|
|
63
97
|
end
|
64
98
|
|
65
99
|
|
100
|
+
|
66
101
|
#######
|
67
102
|
private
|
68
103
|
#######
|