@@ -21,9 +21,9 @@ def initialize
21
21
@ids_to_tags = Hash . new
22
22
@tags_to_ids = Hash . new
23
23
24
- # "Stores" hash: key=component class, value=a component store
25
- # Each "component store" hash: key=entity UUID, value=an array of components
26
- @component_stores = Hash . new
24
+ @component_stores = Hash . new { | h , k | h [ k ] = { } }
25
+
26
+ @mutex = Mutex . new
27
27
end
28
28
29
29
def all_entities
@@ -40,152 +40,155 @@ def create_tagged_entity(human_readable_tag)
40
40
raise ArgumentError , "Must specify tag" if human_readable_tag . nil?
41
41
raise ArgumentError , "Tag '-' is reserved and cannot be used" if human_readable_tag =='-'
42
42
43
- uuid = create_basic_entity
44
- @ids_to_tags [ uuid ] = human_readable_tag
45
- if @tags_to_ids . has_key? human_readable_tag
46
- @tags_to_ids [ human_readable_tag ] <<uuid
47
- else
48
- @tags_to_ids [ human_readable_tag ] = [ uuid ]
43
+ @mutex . synchronize do
44
+ uuid = create_basic_entity
45
+ @ids_to_tags [ uuid ] = human_readable_tag
46
+ if @tags_to_ids . has_key? human_readable_tag
47
+ @tags_to_ids [ human_readable_tag ] <<uuid
48
+ else
49
+ @tags_to_ids [ human_readable_tag ] = [ uuid ]
50
+ end
51
+
52
+ return uuid
49
53
end
54
+ end
50
55
51
- return uuid
56
+ def get_all_entities_with_tag ( tag )
57
+ @tags_to_ids [ tag ]
52
58
end
53
59
54
- # def set_tag(entity_uuid , human_readable_tag)
55
- # raise ArgumentError, "UUID and tag must be specified" if entity_uuid .nil? || human_readable_tag.nil?
60
+ # def set_tag(entity , human_readable_tag)
61
+ # raise ArgumentError, "UUID and tag must be specified" if entity .nil? || human_readable_tag.nil?
56
62
57
- # @ids_to_tags[entity_uuid ]=human_readable_tag
63
+ # @ids_to_tags[entity ]=human_readable_tag
58
64
# @tags_to_ids[]
59
- # @tags_to_ids[human_readable_tag]<<entity_uuid
65
+ # @tags_to_ids[human_readable_tag]<<entity
60
66
# end
61
67
62
- def get_tag ( entity_uuid )
63
- raise ArgumentError , "UUID must be specified" if entity_uuid . nil?
68
+ def get_tag ( entity )
69
+ raise ArgumentError , "UUID must be specified" if entity . nil?
64
70
65
- @ids_to_tags [ entity_uuid ]
71
+ @ids_to_tags [ entity ]
66
72
end
67
73
68
- def get_all_entities_with_tag ( tag )
69
- @tags_to_ids [ tag ]
70
- end
74
+ def has_component? ( entity , component )
75
+ raise ArgumentError , "UUID and component must be specified" if entity . nil? || component . nil?
71
76
72
- def kill_entity ( entity_uuid )
73
- raise ArgumentError , "UUID must be specified" if entity_uuid . nil?
74
-
75
- @component_stores . each_value do |store |
76
- store . delete ( entity_uuid )
77
- end
78
- @tags_to_ids . each_key do |tag |
79
- if @tags_to_ids [ tag ] . include? entity_uuid
80
- @tags_to_ids [ tag ] . delete entity_uuid
81
- end
77
+ store = @component_stores [ component . class ]
78
+ if store . nil?
79
+ return false # NOBODY has this component type
80
+ else
81
+ return store . has_key? ( entity ) && store [ entity ] . include? ( component )
82
82
end
83
+ end
83
84
84
- if @ids_to_tags . delete ( entity_uuid ) ==nil
85
- return false
85
+ def has_component_of_type? ( entity , component_class )
86
+ raise ArgumentError , "UUID and component class must be specified" if entity . nil? || component_class . nil?
87
+
88
+ store = @component_stores [ component_class ]
89
+ if store . nil?
90
+ return false # NOBODY has this component type
86
91
else
87
- return true
92
+ return store . has_key? ( entity ) && store [ entity ] . size > 0
88
93
end
89
94
end
90
95
91
- def add_component ( entity_uuid , component )
92
- raise ArgumentError , "UUID and component must be specified" if entity_uuid . nil? || component . nil?
96
+
97
+ def add_component ( entity , component )
98
+ raise ArgumentError , "UUID and component must be specified" if entity . nil? || component . nil?
93
99
94
100
# Get the store for this component class.
95
101
# If it doesn't exist, make it.
96
102
store = @component_stores [ component . class ]
97
- if store . nil?
98
- store = Hash . new
99
- @component_stores [ component . class ] = store
100
- end
103
+ @mutex . synchronize do
104
+ if store . nil?
105
+ store = Hash . new
106
+ @component_stores [ component . class ] = store
107
+ end
101
108
102
- if store . has_key? entity_uuid
103
- store [ entity_uuid ] << component unless store [ entity_uuid ] . include? component
104
- else
105
- store [ entity_uuid ] = [ component ]
109
+ if store . has_key? entity
110
+ store [ entity ] << component unless store [ entity ] . include? component
111
+ else
112
+ store [ entity ] = [ component ]
113
+ end
106
114
end
107
115
end
108
116
109
- def has_component ( entity_uuid , component )
110
- raise ArgumentError , "UUID and component must be specified" if entity_uuid . nil? || component . nil?
111
-
112
- store = @component_stores [ component . class ]
113
- if store . nil?
114
- return false # NOBODY has this component type
115
- else
116
- return store . has_key? ( entity_uuid ) && store [ entity_uuid ] . include? ( component )
117
+ def add_singleton_component ( entity , component )
118
+ if has_component_of_type? ( entity , component . class . to_s . to_sym )
119
+ $logger. warn "Denied attempt to add more than one singleton #{ component } to #{ entity } "
120
+ return false
117
121
end
122
+
123
+ add_component ( entity , component )
118
124
end
119
125
120
- def has_component_of_type ( entity_uuid , component_class )
121
- raise ArgumentError , "UUID and component class must be specified" if entity_uuid . nil? || component_class . nil?
126
+ def remove_component ( entity , component )
127
+ raise ArgumentError , "UUID and component must be specified" if entity . nil? || component . nil?
122
128
123
- store = @component_stores [ component_class ]
124
- if store . nil?
125
- return false # NOBODY has this component type
126
- else
127
- return store . has_key? ( entity_uuid ) && store [ entity_uuid ] . size > 0
129
+ Thread . exclusive do
130
+ store = @component_stores [ component . class ]
131
+ return nil if store . nil?
132
+
133
+ components = store [ entity ]
134
+ return nil if components . nil?
135
+
136
+ result = components . delete ( component )
137
+ if result . nil?
138
+ raise ArgumentError , "Entity #{ entity } did not possess #{ component } to remove"
139
+ else
140
+ store . delete ( entity ) if store [ entity ] . empty?
141
+ return true
142
+ end
128
143
end
129
144
end
130
145
131
- def get_component_of_type ( entity_uuid , component_class )
132
- raise ArgumentError , "UUID and component class must be specified" if entity_uuid . nil? || component_class . nil?
146
+ def get_component_of_type ( entity , component_class )
147
+ raise ArgumentError , "UUID and component class must be specified" if entity . nil? || component_class . nil?
133
148
134
- # return nil unless has_component_of_type(entity_uuid , component.class)
149
+ # return nil unless has_component_of_type?(entity , component.class)
135
150
store = @component_stores [ component_class ]
136
151
return nil if store . nil?
137
152
138
- components = store [ entity_uuid ]
153
+ components = store [ entity ]
139
154
return nil if components . nil? || components . empty?
140
155
141
156
if components . size != 1
142
- puts "Warning: you probably expected #{ entity_uuid } to have just one #{ component_class . to_s } but it had #{ components . size } ...returning first."
157
+ puts "Warning: you probably expected #{ entity } to have just one #{ component_class . to_s } but it had #{ components . size } ...returning first."
143
158
end
144
159
145
160
return components . first
146
161
end
147
162
148
- def get_components_of_type ( entity_uuid , component_class )
149
- raise ArgumentError , "UUID and component class must be specified" if entity_uuid . nil? || component_class . nil?
163
+ def get_components_of_type ( entity , component_class )
164
+ raise ArgumentError , "UUID and component class must be specified" if entity . nil? || component_class . nil?
150
165
151
- # return nil unless has_component_of_type(entity_uuid , component.class)
166
+ # return nil unless has_component_of_type?(entity , component.class)
152
167
store = @component_stores [ component_class ]
153
168
return nil if store . nil?
154
169
155
- components = store [ entity_uuid ]
170
+ components = store [ entity ]
156
171
return nil if components . nil? || components . empty?
157
172
158
173
return components
159
174
end
160
175
161
- def remove_component ( entity_uuid , component )
162
- raise ArgumentError , "UUID and component must be specified" if entity_uuid . nil? || component . nil?
163
-
164
- store = @component_stores [ component . class ]
165
- return nil if store . nil?
166
-
167
- components = store [ entity_uuid ]
168
- return nil if components . nil?
169
-
170
- result = components . delete ( component )
171
- if result . nil?
172
- raise ArgumentError , "Entity #{ entity_uuid } did not possess #{ component } to remove"
173
- else
174
- store . delete ( entity_uuid ) if store [ entity_uuid ] . empty?
175
- return true
176
- end
176
+ def get_all_components_of_type ( component_sym )
177
+ Set . new ( @component_stores [ component_sym ] . values ) . flatten
177
178
end
178
179
179
- def get_all_components ( entity_uuid )
180
- raise ArgumentError , "UUID must be specified" if entity_uuid . nil?
180
+ def get_all_components ( entity )
181
+ raise ArgumentError , "UUID must be specified" if entity . nil?
181
182
182
- components = [ ]
183
- @component_stores . values . each do |store |
184
- if store [ entity_uuid ]
185
- components += store [ entity_uuid ]
183
+ @mutex . synchronize do
184
+ components = [ ]
185
+ @component_stores . values . each do |store |
186
+ if store [ entity ]
187
+ components += store [ entity ]
188
+ end
186
189
end
190
+ components
187
191
end
188
- components
189
192
end
190
193
191
194
def get_all_entities_with_component_of_type ( component_class )
@@ -209,6 +212,25 @@ def get_all_entities_with_components_of_type(component_classes)
209
212
return entities
210
213
end
211
214
215
+ def kill_entity ( entity )
216
+ raise ArgumentError , "UUID must be specified" if entity . nil?
217
+
218
+ @component_stores . each_value do |store |
219
+ store . delete ( entity )
220
+ end
221
+ @tags_to_ids . each_key do |tag |
222
+ if @tags_to_ids [ tag ] . include? entity
223
+ @tags_to_ids [ tag ] . delete entity
224
+ end
225
+ end
226
+
227
+ if @ids_to_tags . delete ( entity ) ==nil
228
+ return false
229
+ else
230
+ return true
231
+ end
232
+ end
233
+
212
234
def dump_details
213
235
output = to_s
214
236
all_entities . each do |e |
0 commit comments