Class: GameEcs::EntityStore

Inherits:
Object
  • Object
show all
Defined in:
lib/game_ecs/entity_store.rb

Defined Under Namespace

Classes: EntityQueryResult, QueryResultSet

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeEntityStore

Returns a new instance of EntityStore.



7
8
9
# File 'lib/game_ecs/entity_store.rb', line 7

def initialize
  clear!
end

Instance Attribute Details

#entity_countObject (readonly)

Returns the value of attribute entity_count.



6
7
8
# File 'lib/game_ecs/entity_store.rb', line 6

def entity_count
  @entity_count
end

#id_to_compObject (readonly)

Returns the value of attribute id_to_comp.



6
7
8
# File 'lib/game_ecs/entity_store.rb', line 6

def id_to_comp
  @id_to_comp
end

Instance Method Details

#add_component(component:, id:) ⇒ Object



117
118
119
120
121
122
123
# File 'lib/game_ecs/entity_store.rb', line 117

def add_component(component:,id:)
  if _iterating?
    _add_component_later component: component, id: id
  else
    _add_component component: component, id: id
  end
end

#add_entity(*components) ⇒ Object



141
142
143
144
145
146
147
148
149
# File 'lib/game_ecs/entity_store.rb', line 141

def add_entity(*components)
  id = generate_id
  if _iterating?
    _add_entity_later(id:id, components: components)
  else
    _add_entity(id: id, components: components)
  end
  id
end

#clear!Object



27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/game_ecs/entity_store.rb', line 27

def clear!
  @comp_to_id = {}
  @id_to_comp = {}
  @cache = {}
  @entity_count = 0

  @iterator_count = 0
  @ents_to_add_later = []
  @comps_to_add_later = []
  @comps_to_remove_later = []
  @ents_to_remove_later = []
  clear_cache!
end

#clear_cache!Object



41
42
43
# File 'lib/game_ecs/entity_store.rb', line 41

def clear_cache!
  @cache = {}
end

#deep_cloneObject



11
12
13
14
15
16
17
18
19
20
21
# File 'lib/game_ecs/entity_store.rb', line 11

def deep_clone
  # NOTE! does not work for Hashes with default procs
  if _iterating?
    raise "AHH! EM is still iterating!!" 
  else
    _apply_updates
    clear_cache!
    em = Marshal.load( Marshal.dump(self) )
    em
  end
end

#each_entity(*klasses, &blk) ⇒ Object



99
100
101
102
103
104
105
106
107
# File 'lib/game_ecs/entity_store.rb', line 99

def each_entity(*klasses, &blk)
  ents = find(*klasses)
  if block_given?
    _iterating do
      ents.each &blk
    end
  end
  ents
end

#find_by_id(id, *klasses) ⇒ Object



45
46
47
48
49
50
51
52
53
54
55
# File 'lib/game_ecs/entity_store.rb', line 45

def find_by_id(id, *klasses)
  return nil unless @id_to_comp.key? id
  ent_record = @id_to_comp[id]
  components = ent_record.values_at(*klasses)
  rec = build_record(id, @id_to_comp[id], klasses) unless components.any?(&:nil?)
  if block_given?
    yield rec
  else
    rec
  end
end

#first(*klasses) ⇒ Object



95
96
97
# File 'lib/game_ecs/entity_store.rb', line 95

def first(*klasses)
  find(*klasses).first
end

#musts(*klasses) ⇒ Object Also known as: find



57
58
59
60
61
62
# File 'lib/game_ecs/entity_store.rb', line 57

def musts(*klasses)
  raise "specify at least one component" if klasses.empty?
  q = Q
  klasses.each{|k| q = q.must(k)}
  query(q)
end

#num_entitiesObject



23
24
25
# File 'lib/game_ecs/entity_store.rb', line 23

def num_entities
  @id_to_comp.keys.size
end

#query(q) ⇒ Object



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/game_ecs/entity_store.rb', line 65

def query(q)
  # TODO cache results as q with content based cache
  #   invalidate cache based on queried_comps
  cache_hit = @cache[q]
  return cache_hit if cache_hit

  queried_comps = q.components
  required_comps = q.required_components

  required_comps.each do |k|
    @comp_to_id[k] ||= Set.new
  end

  intersecting_ids = []
  unless required_comps.empty?
    id_collection = @comp_to_id.values_at(*required_comps)
    intersecting_ids = id_collection.sort_by(&:size).inject &:&
  end

  recs = intersecting_ids.
    select{|eid| q.matches?(eid, @id_to_comp[eid]) }.
    map do |eid|
      build_record eid, @id_to_comp[eid], queried_comps
    end
  result = QueryResultSet.new(records: recs, ids: recs.map(&:id))

  @cache[q] = result if q.cacheable?
  result
end

#remove_component(klass:, id:) ⇒ Object



109
110
111
112
113
114
115
# File 'lib/game_ecs/entity_store.rb', line 109

def remove_component(klass:, id:)
  if _iterating?
    _remove_component_later klass: klass, id: id
  else
    _remove_component klass: klass, id: id
  end
end

#remove_entites(ids:) ⇒ Object



125
126
127
128
129
130
131
# File 'lib/game_ecs/entity_store.rb', line 125

def remove_entites(ids:)
  if _iterating?
    _remove_entities_later(ids: ids)
  else
    _remove_entites(ids: ids)
  end
end

#remove_entity(id:) ⇒ Object



133
134
135
136
137
138
139
# File 'lib/game_ecs/entity_store.rb', line 133

def remove_entity(id:)
  if _iterating?
    _remove_entity_later(id: id)
  else
    _remove_entity(id: id)
  end
end